clawdbot 2026.1.4-1

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 (550) hide show
  1. package/CHANGELOG.md +120 -0
  2. package/LICENSE +21 -0
  3. package/README-header.png +0 -0
  4. package/README.md +297 -0
  5. package/dist/agents/agent-paths.js +17 -0
  6. package/dist/agents/bash-process-registry.js +126 -0
  7. package/dist/agents/bash-tools.js +837 -0
  8. package/dist/agents/clawdbot-tools.js +30 -0
  9. package/dist/agents/clawdis-tools.js +27 -0
  10. package/dist/agents/context.js +34 -0
  11. package/dist/agents/defaults.js +6 -0
  12. package/dist/agents/model-auth.js +112 -0
  13. package/dist/agents/model-catalog.js +55 -0
  14. package/dist/agents/model-fallback.js +191 -0
  15. package/dist/agents/model-scan.js +263 -0
  16. package/dist/agents/model-selection.js +116 -0
  17. package/dist/agents/models-config.js +49 -0
  18. package/dist/agents/pi-embedded-helpers.js +74 -0
  19. package/dist/agents/pi-embedded-runner.js +407 -0
  20. package/dist/agents/pi-embedded-subscribe.js +568 -0
  21. package/dist/agents/pi-embedded-utils.js +20 -0
  22. package/dist/agents/pi-embedded.js +1 -0
  23. package/dist/agents/pi-oauth.js +88 -0
  24. package/dist/agents/pi-tools.js +433 -0
  25. package/dist/agents/sandbox-paths.js +68 -0
  26. package/dist/agents/sandbox.js +644 -0
  27. package/dist/agents/shell-utils.js +53 -0
  28. package/dist/agents/skills-install.js +244 -0
  29. package/dist/agents/skills-status.js +157 -0
  30. package/dist/agents/skills.js +470 -0
  31. package/dist/agents/steerable-agent-loop.js +338 -0
  32. package/dist/agents/steerable-provider-transport.js +48 -0
  33. package/dist/agents/system-prompt.js +104 -0
  34. package/dist/agents/tool-display.js +162 -0
  35. package/dist/agents/tool-images.js +138 -0
  36. package/dist/agents/tools/browser-tool.js +339 -0
  37. package/dist/agents/tools/canvas-tool.js +193 -0
  38. package/dist/agents/tools/common.js +88 -0
  39. package/dist/agents/tools/cron-tool.js +124 -0
  40. package/dist/agents/tools/discord-actions-guild.js +186 -0
  41. package/dist/agents/tools/discord-actions-messaging.js +285 -0
  42. package/dist/agents/tools/discord-actions-moderation.js +70 -0
  43. package/dist/agents/tools/discord-actions.js +56 -0
  44. package/dist/agents/tools/discord-schema.js +199 -0
  45. package/dist/agents/tools/discord-tool.js +16 -0
  46. package/dist/agents/tools/gateway-tool.js +46 -0
  47. package/dist/agents/tools/gateway.js +27 -0
  48. package/dist/agents/tools/image-tool.js +132 -0
  49. package/dist/agents/tools/nodes-tool.js +413 -0
  50. package/dist/agents/tools/nodes-utils.js +92 -0
  51. package/dist/agents/tools/sessions-helpers.js +88 -0
  52. package/dist/agents/tools/sessions-history-tool.js +53 -0
  53. package/dist/agents/tools/sessions-list-tool.js +143 -0
  54. package/dist/agents/tools/sessions-send-helpers.js +100 -0
  55. package/dist/agents/tools/sessions-send-tool.js +347 -0
  56. package/dist/agents/tools/slack-actions.js +129 -0
  57. package/dist/agents/tools/slack-schema.js +59 -0
  58. package/dist/agents/tools/slack-tool.js +16 -0
  59. package/dist/agents/usage.js +39 -0
  60. package/dist/agents/workspace.js +241 -0
  61. package/dist/auto-reply/chunk.js +76 -0
  62. package/dist/auto-reply/envelope.js +38 -0
  63. package/dist/auto-reply/group-activation.js +20 -0
  64. package/dist/auto-reply/heartbeat.js +57 -0
  65. package/dist/auto-reply/model.js +14 -0
  66. package/dist/auto-reply/reply/abort.js +14 -0
  67. package/dist/auto-reply/reply/agent-runner.js +371 -0
  68. package/dist/auto-reply/reply/block-streaming.js +34 -0
  69. package/dist/auto-reply/reply/body.js +29 -0
  70. package/dist/auto-reply/reply/commands.js +207 -0
  71. package/dist/auto-reply/reply/directive-handling.js +361 -0
  72. package/dist/auto-reply/reply/directives.js +47 -0
  73. package/dist/auto-reply/reply/followup-runner.js +149 -0
  74. package/dist/auto-reply/reply/groups.js +91 -0
  75. package/dist/auto-reply/reply/mentions.js +38 -0
  76. package/dist/auto-reply/reply/model-selection.js +114 -0
  77. package/dist/auto-reply/reply/queue.js +399 -0
  78. package/dist/auto-reply/reply/reply-tags.js +26 -0
  79. package/dist/auto-reply/reply/session-updates.js +87 -0
  80. package/dist/auto-reply/reply/session.js +160 -0
  81. package/dist/auto-reply/reply/typing.js +75 -0
  82. package/dist/auto-reply/reply.js +535 -0
  83. package/dist/auto-reply/send-policy.js +28 -0
  84. package/dist/auto-reply/status.js +158 -0
  85. package/dist/auto-reply/templating.js +9 -0
  86. package/dist/auto-reply/thinking.js +49 -0
  87. package/dist/auto-reply/tokens.js +2 -0
  88. package/dist/auto-reply/tool-meta.js +74 -0
  89. package/dist/auto-reply/transcription.js +57 -0
  90. package/dist/auto-reply/types.js +1 -0
  91. package/dist/browser/bridge-server.js +37 -0
  92. package/dist/browser/cdp.js +382 -0
  93. package/dist/browser/chrome.js +432 -0
  94. package/dist/browser/client-actions-core.js +67 -0
  95. package/dist/browser/client-actions-observe.js +24 -0
  96. package/dist/browser/client-actions-types.js +1 -0
  97. package/dist/browser/client-actions.js +3 -0
  98. package/dist/browser/client-fetch.js +43 -0
  99. package/dist/browser/client.js +105 -0
  100. package/dist/browser/config.js +140 -0
  101. package/dist/browser/constants.js +4 -0
  102. package/dist/browser/profiles-service.js +122 -0
  103. package/dist/browser/profiles.js +85 -0
  104. package/dist/browser/pw-ai.js +2 -0
  105. package/dist/browser/pw-session.js +144 -0
  106. package/dist/browser/pw-tools-core.js +363 -0
  107. package/dist/browser/routes/agent.js +535 -0
  108. package/dist/browser/routes/basic.js +155 -0
  109. package/dist/browser/routes/index.js +8 -0
  110. package/dist/browser/routes/tabs.js +105 -0
  111. package/dist/browser/routes/utils.js +62 -0
  112. package/dist/browser/screenshot.js +40 -0
  113. package/dist/browser/server-context.js +377 -0
  114. package/dist/browser/server.js +81 -0
  115. package/dist/browser/target-id.js +18 -0
  116. package/dist/browser/trash.js +21 -0
  117. package/dist/canvas-host/a2ui/.bundle.hash +1 -0
  118. package/dist/canvas-host/a2ui/a2ui.bundle.js +17768 -0
  119. package/dist/canvas-host/a2ui/index.html +246 -0
  120. package/dist/canvas-host/a2ui.js +187 -0
  121. package/dist/canvas-host/server.js +382 -0
  122. package/dist/cli/browser-cli-actions-input.js +459 -0
  123. package/dist/cli/browser-cli-actions-observe.js +56 -0
  124. package/dist/cli/browser-cli-examples.js +31 -0
  125. package/dist/cli/browser-cli-inspect.js +97 -0
  126. package/dist/cli/browser-cli-manage.js +286 -0
  127. package/dist/cli/browser-cli-shared.js +1 -0
  128. package/dist/cli/browser-cli.js +26 -0
  129. package/dist/cli/canvas-cli.js +416 -0
  130. package/dist/cli/cron-cli.js +454 -0
  131. package/dist/cli/deps.js +17 -0
  132. package/dist/cli/dns-cli.js +180 -0
  133. package/dist/cli/gateway-cli.js +489 -0
  134. package/dist/cli/gateway-rpc.js +20 -0
  135. package/dist/cli/hooks-cli.js +135 -0
  136. package/dist/cli/models-cli.js +248 -0
  137. package/dist/cli/nodes-camera.js +57 -0
  138. package/dist/cli/nodes-canvas.js +26 -0
  139. package/dist/cli/nodes-cli.js +946 -0
  140. package/dist/cli/nodes-screen.js +37 -0
  141. package/dist/cli/parse-duration.js +20 -0
  142. package/dist/cli/ports.js +97 -0
  143. package/dist/cli/program.js +406 -0
  144. package/dist/cli/prompt.js +19 -0
  145. package/dist/cli/tui-cli.js +35 -0
  146. package/dist/cli/wait.js +8 -0
  147. package/dist/commands/agent.js +645 -0
  148. package/dist/commands/antigravity-oauth.js +327 -0
  149. package/dist/commands/configure.js +480 -0
  150. package/dist/commands/doctor.js +484 -0
  151. package/dist/commands/health.js +108 -0
  152. package/dist/commands/models/aliases.js +64 -0
  153. package/dist/commands/models/fallbacks.js +99 -0
  154. package/dist/commands/models/image-fallbacks.js +99 -0
  155. package/dist/commands/models/list.js +323 -0
  156. package/dist/commands/models/scan.js +266 -0
  157. package/dist/commands/models/set-image.js +23 -0
  158. package/dist/commands/models/set.js +23 -0
  159. package/dist/commands/models/shared.js +72 -0
  160. package/dist/commands/models.js +7 -0
  161. package/dist/commands/onboard-auth.js +70 -0
  162. package/dist/commands/onboard-helpers.js +295 -0
  163. package/dist/commands/onboard-interactive.js +17 -0
  164. package/dist/commands/onboard-non-interactive.js +202 -0
  165. package/dist/commands/onboard-providers.js +634 -0
  166. package/dist/commands/onboard-remote.js +120 -0
  167. package/dist/commands/onboard-skills.js +148 -0
  168. package/dist/commands/onboard-types.js +1 -0
  169. package/dist/commands/onboard.js +12 -0
  170. package/dist/commands/send.js +124 -0
  171. package/dist/commands/sessions.js +212 -0
  172. package/dist/commands/setup.js +58 -0
  173. package/dist/commands/signal-install.js +135 -0
  174. package/dist/commands/status.js +207 -0
  175. package/dist/commands/update.js +16 -0
  176. package/dist/config/config.js +6 -0
  177. package/dist/config/defaults.js +61 -0
  178. package/dist/config/io.js +147 -0
  179. package/dist/config/legacy-migrate.js +13 -0
  180. package/dist/config/legacy.js +159 -0
  181. package/dist/config/paths.js +71 -0
  182. package/dist/config/schema.js +150 -0
  183. package/dist/config/sessions.js +282 -0
  184. package/dist/config/talk.js +31 -0
  185. package/dist/config/types.js +1 -0
  186. package/dist/config/validation.js +29 -0
  187. package/dist/config/zod-schema.js +831 -0
  188. package/dist/control-ui/assets/index-BFID3yAA.css +1 -0
  189. package/dist/control-ui/assets/index-CE_axlTS.js +2235 -0
  190. package/dist/control-ui/assets/index-CE_axlTS.js.map +1 -0
  191. package/dist/control-ui/index.html +15 -0
  192. package/dist/cron/isolated-agent.js +499 -0
  193. package/dist/cron/run-log.js +72 -0
  194. package/dist/cron/schedule.js +24 -0
  195. package/dist/cron/service.js +471 -0
  196. package/dist/cron/store.js +43 -0
  197. package/dist/cron/types.js +1 -0
  198. package/dist/daemon/constants.js +10 -0
  199. package/dist/daemon/launchd.js +276 -0
  200. package/dist/daemon/legacy.js +63 -0
  201. package/dist/daemon/program-args.js +76 -0
  202. package/dist/daemon/schtasks.js +257 -0
  203. package/dist/daemon/service.js +60 -0
  204. package/dist/daemon/systemd.js +266 -0
  205. package/dist/discord/index.js +2 -0
  206. package/dist/discord/monitor.js +1188 -0
  207. package/dist/discord/probe.js +54 -0
  208. package/dist/discord/send.js +577 -0
  209. package/dist/discord/token.js +8 -0
  210. package/dist/gateway/auth.js +121 -0
  211. package/dist/gateway/call.js +94 -0
  212. package/dist/gateway/chat-attachments.js +41 -0
  213. package/dist/gateway/client.js +180 -0
  214. package/dist/gateway/config-reload.js +274 -0
  215. package/dist/gateway/control-ui.js +184 -0
  216. package/dist/gateway/hooks-mapping.js +282 -0
  217. package/dist/gateway/hooks.js +168 -0
  218. package/dist/gateway/net.js +29 -0
  219. package/dist/gateway/protocol/index.js +61 -0
  220. package/dist/gateway/protocol/schema.js +560 -0
  221. package/dist/gateway/server-bridge-subscriptions.js +93 -0
  222. package/dist/gateway/server-bridge.js +1013 -0
  223. package/dist/gateway/server-browser.js +12 -0
  224. package/dist/gateway/server-chat.js +159 -0
  225. package/dist/gateway/server-constants.js +8 -0
  226. package/dist/gateway/server-discovery.js +62 -0
  227. package/dist/gateway/server-http.js +165 -0
  228. package/dist/gateway/server-methods/agent-job.js +125 -0
  229. package/dist/gateway/server-methods/agent.js +250 -0
  230. package/dist/gateway/server-methods/chat.js +200 -0
  231. package/dist/gateway/server-methods/config.js +50 -0
  232. package/dist/gateway/server-methods/connect.js +6 -0
  233. package/dist/gateway/server-methods/cron.js +83 -0
  234. package/dist/gateway/server-methods/health.js +28 -0
  235. package/dist/gateway/server-methods/models.js +16 -0
  236. package/dist/gateway/server-methods/nodes.js +294 -0
  237. package/dist/gateway/server-methods/providers.js +217 -0
  238. package/dist/gateway/server-methods/send.js +166 -0
  239. package/dist/gateway/server-methods/sessions.js +305 -0
  240. package/dist/gateway/server-methods/skills.js +83 -0
  241. package/dist/gateway/server-methods/system.js +118 -0
  242. package/dist/gateway/server-methods/talk.js +22 -0
  243. package/dist/gateway/server-methods/types.js +1 -0
  244. package/dist/gateway/server-methods/voicewake.js +30 -0
  245. package/dist/gateway/server-methods/web.js +58 -0
  246. package/dist/gateway/server-methods/wizard.js +100 -0
  247. package/dist/gateway/server-methods.js +53 -0
  248. package/dist/gateway/server-providers.js +644 -0
  249. package/dist/gateway/server-shared.js +1 -0
  250. package/dist/gateway/server-utils.js +35 -0
  251. package/dist/gateway/server.js +1437 -0
  252. package/dist/gateway/session-utils.js +216 -0
  253. package/dist/gateway/ws-log.js +349 -0
  254. package/dist/gateway/ws-logging.js +8 -0
  255. package/dist/globals.js +41 -0
  256. package/dist/hooks/gmail-ops.js +236 -0
  257. package/dist/hooks/gmail-setup-utils.js +278 -0
  258. package/dist/hooks/gmail-watcher.js +175 -0
  259. package/dist/hooks/gmail.js +177 -0
  260. package/dist/imessage/client.js +165 -0
  261. package/dist/imessage/index.js +3 -0
  262. package/dist/imessage/monitor.js +272 -0
  263. package/dist/imessage/probe.js +26 -0
  264. package/dist/imessage/send.js +83 -0
  265. package/dist/imessage/targets.js +176 -0
  266. package/dist/index.js +50 -0
  267. package/dist/infra/agent-events.js +46 -0
  268. package/dist/infra/binaries.js +9 -0
  269. package/dist/infra/bonjour-discovery.js +163 -0
  270. package/dist/infra/bonjour.js +200 -0
  271. package/dist/infra/bridge/server.js +562 -0
  272. package/dist/infra/canvas-host-url.js +54 -0
  273. package/dist/infra/env.js +8 -0
  274. package/dist/infra/errors.js +28 -0
  275. package/dist/infra/gateway-lock.js +8 -0
  276. package/dist/infra/heartbeat-events.js +21 -0
  277. package/dist/infra/heartbeat-runner.js +453 -0
  278. package/dist/infra/heartbeat-wake.js +61 -0
  279. package/dist/infra/is-main.js +37 -0
  280. package/dist/infra/machine-name.js +40 -0
  281. package/dist/infra/node-pairing.js +211 -0
  282. package/dist/infra/pam.js +42 -0
  283. package/dist/infra/path-env.js +92 -0
  284. package/dist/infra/ports.js +87 -0
  285. package/dist/infra/provider-summary.js +80 -0
  286. package/dist/infra/restart.js +29 -0
  287. package/dist/infra/retry.js +16 -0
  288. package/dist/infra/runtime-guard.js +59 -0
  289. package/dist/infra/system-events.js +44 -0
  290. package/dist/infra/system-presence.js +216 -0
  291. package/dist/infra/tailnet.js +46 -0
  292. package/dist/infra/tailscale.js +149 -0
  293. package/dist/infra/voicewake.js +77 -0
  294. package/dist/infra/widearea-dns.js +123 -0
  295. package/dist/infra/ws.js +13 -0
  296. package/dist/logger.js +52 -0
  297. package/dist/logging.js +490 -0
  298. package/dist/macos/gateway-daemon.js +141 -0
  299. package/dist/macos/relay.js +46 -0
  300. package/dist/media/constants.js +33 -0
  301. package/dist/media/host.js +42 -0
  302. package/dist/media/image-ops.js +121 -0
  303. package/dist/media/mime.js +115 -0
  304. package/dist/media/parse.js +81 -0
  305. package/dist/media/server.js +64 -0
  306. package/dist/media/store.js +139 -0
  307. package/dist/process/command-queue.js +97 -0
  308. package/dist/process/exec.js +75 -0
  309. package/dist/protocol.schema.json +2918 -0
  310. package/dist/provider-web.js +8 -0
  311. package/dist/providers/web/index.js +2 -0
  312. package/dist/runtime.js +8 -0
  313. package/dist/sessions/send-policy.js +68 -0
  314. package/dist/signal/client.js +134 -0
  315. package/dist/signal/daemon.js +69 -0
  316. package/dist/signal/index.js +3 -0
  317. package/dist/signal/monitor.js +336 -0
  318. package/dist/signal/probe.js +46 -0
  319. package/dist/signal/send.js +91 -0
  320. package/dist/slack/actions.js +97 -0
  321. package/dist/slack/index.js +5 -0
  322. package/dist/slack/monitor.js +1029 -0
  323. package/dist/slack/probe.js +47 -0
  324. package/dist/slack/send.js +131 -0
  325. package/dist/slack/token.js +10 -0
  326. package/dist/telegram/bot.js +394 -0
  327. package/dist/telegram/download.js +34 -0
  328. package/dist/telegram/index.js +4 -0
  329. package/dist/telegram/monitor.js +47 -0
  330. package/dist/telegram/probe.js +63 -0
  331. package/dist/telegram/proxy.js +9 -0
  332. package/dist/telegram/send.js +138 -0
  333. package/dist/telegram/token.js +30 -0
  334. package/dist/telegram/webhook-set.js +12 -0
  335. package/dist/telegram/webhook.js +56 -0
  336. package/dist/tui/commands.js +74 -0
  337. package/dist/tui/components/assistant-message.js +16 -0
  338. package/dist/tui/components/chat-log.js +92 -0
  339. package/dist/tui/components/custom-editor.js +53 -0
  340. package/dist/tui/components/selectors.js +8 -0
  341. package/dist/tui/components/tool-execution.js +111 -0
  342. package/dist/tui/components/user-message.js +17 -0
  343. package/dist/tui/gateway-chat.js +140 -0
  344. package/dist/tui/layout.js +41 -0
  345. package/dist/tui/message-list.js +57 -0
  346. package/dist/tui/theme/theme.js +80 -0
  347. package/dist/tui/theme.js +25 -0
  348. package/dist/tui/tui.js +708 -0
  349. package/dist/utils.js +133 -0
  350. package/dist/version.js +18 -0
  351. package/dist/web/active-listener.js +7 -0
  352. package/dist/web/auto-reply.js +1203 -0
  353. package/dist/web/inbound.js +481 -0
  354. package/dist/web/login-qr.js +204 -0
  355. package/dist/web/login.js +59 -0
  356. package/dist/web/media.js +148 -0
  357. package/dist/web/outbound.js +67 -0
  358. package/dist/web/qr-image.js +97 -0
  359. package/dist/web/reconnect.js +60 -0
  360. package/dist/web/reply-heartbeat-wake.js +61 -0
  361. package/dist/web/session.js +346 -0
  362. package/dist/wizard/clack-prompter.js +56 -0
  363. package/dist/wizard/onboarding.js +452 -0
  364. package/dist/wizard/prompts.js +6 -0
  365. package/dist/wizard/session.js +203 -0
  366. package/docs/AGENTS.default.md +116 -0
  367. package/docs/CNAME +1 -0
  368. package/docs/RELEASING.md +64 -0
  369. package/docs/_config.yml +51 -0
  370. package/docs/_layouts/default.html +145 -0
  371. package/docs/agent-send.md +21 -0
  372. package/docs/agent.md +104 -0
  373. package/docs/android/connect.md +131 -0
  374. package/docs/architecture.md +89 -0
  375. package/docs/assets/markdown.css +130 -0
  376. package/docs/assets/pixel-lobster.svg +60 -0
  377. package/docs/assets/terminal.css +497 -0
  378. package/docs/assets/theme.js +55 -0
  379. package/docs/audio.md +50 -0
  380. package/docs/background-process.md +74 -0
  381. package/docs/bash.md +32 -0
  382. package/docs/bonjour.md +159 -0
  383. package/docs/browser.md +289 -0
  384. package/docs/camera.md +152 -0
  385. package/docs/clawd.md +199 -0
  386. package/docs/clawdbot-mac.md +104 -0
  387. package/docs/configuration.md +1177 -0
  388. package/docs/control-api.md +49 -0
  389. package/docs/control-ui.md +83 -0
  390. package/docs/cron.md +374 -0
  391. package/docs/dashboard.md +17 -0
  392. package/docs/device-models.md +46 -0
  393. package/docs/discord.md +293 -0
  394. package/docs/discovery.md +112 -0
  395. package/docs/docker.md +251 -0
  396. package/docs/docs.json +86 -0
  397. package/docs/doctor.md +47 -0
  398. package/docs/elevated.md +31 -0
  399. package/docs/faq.md +640 -0
  400. package/docs/gateway/pairing.md +109 -0
  401. package/docs/gateway-lock.md +28 -0
  402. package/docs/gateway.md +174 -0
  403. package/docs/gmail-pubsub.md +191 -0
  404. package/docs/grammy.md +27 -0
  405. package/docs/group-messages.md +71 -0
  406. package/docs/groups.md +78 -0
  407. package/docs/health.md +28 -0
  408. package/docs/heartbeat.md +64 -0
  409. package/docs/images.md +52 -0
  410. package/docs/imessage.md +63 -0
  411. package/docs/index.md +182 -0
  412. package/docs/ios/connect.md +177 -0
  413. package/docs/ios/spec.md +236 -0
  414. package/docs/location-command.md +95 -0
  415. package/docs/logging.md +99 -0
  416. package/docs/lore.md +131 -0
  417. package/docs/mac/bun.md +133 -0
  418. package/docs/mac/canvas.md +161 -0
  419. package/docs/mac/child-process.md +72 -0
  420. package/docs/mac/dev-setup.md +81 -0
  421. package/docs/mac/health.md +28 -0
  422. package/docs/mac/icon.md +26 -0
  423. package/docs/mac/logging.md +51 -0
  424. package/docs/mac/menu-bar.md +69 -0
  425. package/docs/mac/peekaboo.md +170 -0
  426. package/docs/mac/permissions.md +40 -0
  427. package/docs/mac/release.md +76 -0
  428. package/docs/mac/remote.md +57 -0
  429. package/docs/mac/signing.md +41 -0
  430. package/docs/mac/skills.md +27 -0
  431. package/docs/mac/voice-overlay.md +52 -0
  432. package/docs/mac/voicewake.md +56 -0
  433. package/docs/mac/webchat.md +27 -0
  434. package/docs/mac/xpc.md +40 -0
  435. package/docs/models.md +90 -0
  436. package/docs/nix.md +49 -0
  437. package/docs/nodes.md +157 -0
  438. package/docs/onboarding-config-protocol.md +29 -0
  439. package/docs/onboarding.md +185 -0
  440. package/docs/presence.md +133 -0
  441. package/docs/queue.md +78 -0
  442. package/docs/refactor/browser-control-simplification.md +58 -0
  443. package/docs/refactor/canvas-a2ui.md +93 -0
  444. package/docs/refactor/cli-unification.md +64 -0
  445. package/docs/refactor/gateway-client.md +31 -0
  446. package/docs/refactor/gateway.md +99 -0
  447. package/docs/refactor/new-arch.md +171 -0
  448. package/docs/refactor/tui.md +26 -0
  449. package/docs/refactor/web-gateway-troubleshooting.md +37 -0
  450. package/docs/refactor/webagent-session.md +46 -0
  451. package/docs/remote-gateway-readme.md +148 -0
  452. package/docs/remote.md +66 -0
  453. package/docs/research/memory.md +227 -0
  454. package/docs/rpc.md +35 -0
  455. package/docs/security.md +168 -0
  456. package/docs/session-tool.md +119 -0
  457. package/docs/session.md +84 -0
  458. package/docs/sessions.md +8 -0
  459. package/docs/setup.md +118 -0
  460. package/docs/signal.md +113 -0
  461. package/docs/skills-config.md +58 -0
  462. package/docs/skills.md +149 -0
  463. package/docs/slack.md +158 -0
  464. package/docs/surface.md +20 -0
  465. package/docs/tailscale.md +71 -0
  466. package/docs/talk.md +79 -0
  467. package/docs/telegram.md +90 -0
  468. package/docs/templates/AGENTS.md +126 -0
  469. package/docs/templates/BOOTSTRAP.md +53 -0
  470. package/docs/templates/IDENTITY.md +17 -0
  471. package/docs/templates/SOUL.md +41 -0
  472. package/docs/templates/TOOLS.md +41 -0
  473. package/docs/templates/USER.md +22 -0
  474. package/docs/test.md +35 -0
  475. package/docs/thinking.md +46 -0
  476. package/docs/tools.md +248 -0
  477. package/docs/troubleshooting.md +227 -0
  478. package/docs/tui.md +69 -0
  479. package/docs/typebox.md +42 -0
  480. package/docs/voicewake.md +61 -0
  481. package/docs/web.md +115 -0
  482. package/docs/webchat.md +34 -0
  483. package/docs/webhook.md +132 -0
  484. package/docs/whatsapp-clawd.jpg +0 -0
  485. package/docs/whatsapp.md +142 -0
  486. package/docs/wizard.md +158 -0
  487. package/package.json +186 -0
  488. package/skills/apple-notes/SKILL.md +50 -0
  489. package/skills/apple-reminders/SKILL.md +67 -0
  490. package/skills/bear-notes/SKILL.md +79 -0
  491. package/skills/bird/SKILL.md +25 -0
  492. package/skills/blogwatcher/SKILL.md +46 -0
  493. package/skills/blucli/SKILL.md +27 -0
  494. package/skills/brave-search/SKILL.md +30 -0
  495. package/skills/brave-search/scripts/content.mjs +53 -0
  496. package/skills/brave-search/scripts/search.mjs +79 -0
  497. package/skills/camsnap/SKILL.md +25 -0
  498. package/skills/clawdhub/SKILL.md +53 -0
  499. package/skills/coding-agent/SKILL.md +275 -0
  500. package/skills/discord/SKILL.md +369 -0
  501. package/skills/eightctl/SKILL.md +29 -0
  502. package/skills/food-order/SKILL.md +41 -0
  503. package/skills/gemini/SKILL.md +23 -0
  504. package/skills/gifgrep/SKILL.md +47 -0
  505. package/skills/github/SKILL.md +47 -0
  506. package/skills/gog/SKILL.md +36 -0
  507. package/skills/goplaces/SKILL.md +30 -0
  508. package/skills/imsg/SKILL.md +25 -0
  509. package/skills/local-places/SERVER_README.md +101 -0
  510. package/skills/local-places/SKILL.md +91 -0
  511. package/skills/local-places/pyproject.toml +27 -0
  512. package/skills/local-places/src/local_places/__init__.py +2 -0
  513. package/skills/local-places/src/local_places/__pycache__/__init__.cpython-314.pyc +0 -0
  514. package/skills/local-places/src/local_places/__pycache__/google_places.cpython-314.pyc +0 -0
  515. package/skills/local-places/src/local_places/__pycache__/main.cpython-314.pyc +0 -0
  516. package/skills/local-places/src/local_places/__pycache__/schemas.cpython-314.pyc +0 -0
  517. package/skills/local-places/src/local_places/google_places.py +314 -0
  518. package/skills/local-places/src/local_places/main.py +65 -0
  519. package/skills/local-places/src/local_places/schemas.py +107 -0
  520. package/skills/mcporter/SKILL.md +38 -0
  521. package/skills/nano-banana-pro/SKILL.md +29 -0
  522. package/skills/nano-banana-pro/scripts/generate_image.py +167 -0
  523. package/skills/nano-pdf/SKILL.md +20 -0
  524. package/skills/notion/SKILL.md +156 -0
  525. package/skills/obsidian/SKILL.md +55 -0
  526. package/skills/openai-image-gen/SKILL.md +31 -0
  527. package/skills/openai-image-gen/scripts/gen.py +173 -0
  528. package/skills/openai-whisper/SKILL.md +19 -0
  529. package/skills/openai-whisper-api/SKILL.md +43 -0
  530. package/skills/openai-whisper-api/scripts/transcribe.sh +85 -0
  531. package/skills/openhue/SKILL.md +30 -0
  532. package/skills/oracle/SKILL.md +105 -0
  533. package/skills/ordercli/SKILL.md +47 -0
  534. package/skills/peekaboo/SKILL.md +153 -0
  535. package/skills/qmd/SKILL.md +26 -0
  536. package/skills/sag/SKILL.md +62 -0
  537. package/skills/slack/SKILL.md +143 -0
  538. package/skills/songsee/SKILL.md +29 -0
  539. package/skills/sonoscli/SKILL.md +26 -0
  540. package/skills/spotify-player/SKILL.md +34 -0
  541. package/skills/summarize/SKILL.md +49 -0
  542. package/skills/things-mac/SKILL.md +61 -0
  543. package/skills/tmux/SKILL.md +121 -0
  544. package/skills/tmux/scripts/find-sessions.sh +112 -0
  545. package/skills/tmux/scripts/wait-for-text.sh +83 -0
  546. package/skills/trello/SKILL.md +84 -0
  547. package/skills/video-frames/SKILL.md +29 -0
  548. package/skills/video-frames/scripts/frame.sh +81 -0
  549. package/skills/wacli/SKILL.md +42 -0
  550. package/skills/weather/SKILL.md +49 -0
@@ -0,0 +1,338 @@
1
+ import { streamSimple, validateToolArguments } from "@mariozechner/pi-ai";
2
+ class EventStream {
3
+ isComplete;
4
+ extractResult;
5
+ queue = [];
6
+ waiting = [];
7
+ done = false;
8
+ finalResultPromise;
9
+ resolveFinalResult;
10
+ constructor(isComplete, extractResult) {
11
+ this.isComplete = isComplete;
12
+ this.extractResult = extractResult;
13
+ this.finalResultPromise = new Promise((resolve) => {
14
+ this.resolveFinalResult = resolve;
15
+ });
16
+ }
17
+ push(event) {
18
+ if (this.done)
19
+ return;
20
+ if (this.isComplete(event)) {
21
+ this.done = true;
22
+ this.resolveFinalResult(this.extractResult(event));
23
+ }
24
+ const waiter = this.waiting.shift();
25
+ if (waiter) {
26
+ waiter({ value: event, done: false });
27
+ }
28
+ else {
29
+ this.queue.push(event);
30
+ }
31
+ }
32
+ end(result) {
33
+ this.done = true;
34
+ if (result !== undefined) {
35
+ this.resolveFinalResult(result);
36
+ }
37
+ while (this.waiting.length > 0) {
38
+ const waiter = this.waiting.shift();
39
+ if (waiter) {
40
+ waiter({ value: undefined, done: true });
41
+ }
42
+ }
43
+ }
44
+ async *[Symbol.asyncIterator]() {
45
+ while (true) {
46
+ if (this.queue.length > 0) {
47
+ const next = this.queue.shift();
48
+ if (next !== undefined) {
49
+ yield next;
50
+ }
51
+ }
52
+ else if (this.done) {
53
+ return;
54
+ }
55
+ else {
56
+ const result = await new Promise((resolve) => this.waiting.push(resolve));
57
+ if (result.done)
58
+ return;
59
+ yield result.value;
60
+ }
61
+ }
62
+ }
63
+ result() {
64
+ return this.finalResultPromise;
65
+ }
66
+ }
67
+ function createAgentStream() {
68
+ return new EventStream((event) => event.type === "agent_end", (event) => (event.type === "agent_end" ? event.messages : []));
69
+ }
70
+ export function agentLoop(prompt, context, config, signal, streamFn) {
71
+ const stream = createAgentStream();
72
+ void (async () => {
73
+ const newMessages = [prompt];
74
+ const currentContext = {
75
+ ...context,
76
+ messages: [...context.messages, prompt],
77
+ };
78
+ stream.push({ type: "agent_start" });
79
+ stream.push({ type: "turn_start" });
80
+ stream.push({ type: "message_start", message: prompt });
81
+ stream.push({ type: "message_end", message: prompt });
82
+ await runLoop(currentContext, newMessages, config, signal, stream, streamFn);
83
+ })();
84
+ return stream;
85
+ }
86
+ export function agentLoopContinue(context, config, signal, streamFn) {
87
+ const lastMessage = context.messages[context.messages.length - 1];
88
+ if (!lastMessage) {
89
+ throw new Error("Cannot continue: no messages in context");
90
+ }
91
+ if (lastMessage.role !== "user" && lastMessage.role !== "toolResult") {
92
+ throw new Error(`Cannot continue from message role: ${lastMessage.role}. Expected 'user' or 'toolResult'.`);
93
+ }
94
+ const stream = createAgentStream();
95
+ void (async () => {
96
+ const newMessages = [];
97
+ const currentContext = { ...context };
98
+ stream.push({ type: "agent_start" });
99
+ stream.push({ type: "turn_start" });
100
+ await runLoop(currentContext, newMessages, config, signal, stream, streamFn);
101
+ })();
102
+ return stream;
103
+ }
104
+ async function runLoop(currentContext, newMessages, config, signal, stream, streamFn) {
105
+ let hasMoreToolCalls = true;
106
+ let firstTurn = true;
107
+ const getQueuedMessages = config.getQueuedMessages;
108
+ let queuedMessages = getQueuedMessages
109
+ ? await getQueuedMessages()
110
+ : [];
111
+ let queuedAfterTools = null;
112
+ while (hasMoreToolCalls || queuedMessages.length > 0) {
113
+ if (!firstTurn) {
114
+ stream.push({ type: "turn_start" });
115
+ }
116
+ else {
117
+ firstTurn = false;
118
+ }
119
+ if (queuedMessages.length > 0) {
120
+ for (const { original, llm } of queuedMessages) {
121
+ stream.push({ type: "message_start", message: original });
122
+ stream.push({ type: "message_end", message: original });
123
+ if (llm) {
124
+ currentContext.messages.push(llm);
125
+ newMessages.push(llm);
126
+ }
127
+ }
128
+ queuedMessages = [];
129
+ }
130
+ const message = await streamAssistantResponse(currentContext, config, signal, stream, streamFn);
131
+ newMessages.push(message);
132
+ if (message.stopReason === "error" || message.stopReason === "aborted") {
133
+ stream.push({ type: "turn_end", message, toolResults: [] });
134
+ stream.push({ type: "agent_end", messages: newMessages });
135
+ stream.end(newMessages);
136
+ return;
137
+ }
138
+ const toolCalls = message.content.filter((c) => c.type === "toolCall");
139
+ hasMoreToolCalls = toolCalls.length > 0;
140
+ const toolResults = [];
141
+ if (hasMoreToolCalls) {
142
+ const toolExecution = await executeToolCalls(currentContext.tools, message, signal, stream, config.getQueuedMessages);
143
+ toolResults.push(...toolExecution.toolResults);
144
+ queuedAfterTools = toolExecution.queuedMessages ?? null;
145
+ currentContext.messages.push(...toolResults);
146
+ newMessages.push(...toolResults);
147
+ }
148
+ stream.push({ type: "turn_end", message, toolResults: toolResults });
149
+ if (queuedAfterTools && queuedAfterTools.length > 0) {
150
+ queuedMessages = queuedAfterTools;
151
+ queuedAfterTools = null;
152
+ }
153
+ else {
154
+ queuedMessages = getQueuedMessages
155
+ ? await getQueuedMessages()
156
+ : [];
157
+ }
158
+ }
159
+ stream.push({ type: "agent_end", messages: newMessages });
160
+ stream.end(newMessages);
161
+ }
162
+ async function streamAssistantResponse(context, config, signal, stream, streamFn) {
163
+ const processedMessages = config.preprocessor
164
+ ? await config.preprocessor(context.messages, signal)
165
+ : [...context.messages];
166
+ const processedContext = {
167
+ systemPrompt: context.systemPrompt,
168
+ messages: [...processedMessages].map((m) => {
169
+ if (m.role === "toolResult") {
170
+ const { details: _details, ...rest } = m;
171
+ return rest;
172
+ }
173
+ return m;
174
+ }),
175
+ tools: context.tools,
176
+ };
177
+ const streamFunction = streamFn || streamSimple;
178
+ const resolvedApiKey = (config.getApiKey
179
+ ? await config.getApiKey(config.model.provider)
180
+ : undefined) || config.apiKey;
181
+ const response = await streamFunction(config.model, processedContext, {
182
+ ...config,
183
+ apiKey: resolvedApiKey,
184
+ signal,
185
+ });
186
+ let partialMessage = null;
187
+ let addedPartial = false;
188
+ for await (const event of response) {
189
+ switch (event.type) {
190
+ case "start":
191
+ partialMessage = event.partial;
192
+ context.messages.push(partialMessage);
193
+ addedPartial = true;
194
+ stream.push({ type: "message_start", message: { ...partialMessage } });
195
+ break;
196
+ case "text_start":
197
+ case "text_delta":
198
+ case "text_end":
199
+ case "thinking_start":
200
+ case "thinking_delta":
201
+ case "thinking_end":
202
+ case "toolcall_start":
203
+ case "toolcall_delta":
204
+ case "toolcall_end":
205
+ if (partialMessage) {
206
+ partialMessage = event.partial;
207
+ context.messages[context.messages.length - 1] = partialMessage;
208
+ stream.push({
209
+ type: "message_update",
210
+ assistantMessageEvent: event,
211
+ message: { ...partialMessage },
212
+ });
213
+ }
214
+ break;
215
+ case "done":
216
+ case "error": {
217
+ const finalMessage = await response.result();
218
+ if (addedPartial) {
219
+ context.messages[context.messages.length - 1] = finalMessage;
220
+ }
221
+ else {
222
+ context.messages.push(finalMessage);
223
+ }
224
+ if (!addedPartial) {
225
+ stream.push({ type: "message_start", message: { ...finalMessage } });
226
+ }
227
+ stream.push({ type: "message_end", message: finalMessage });
228
+ return finalMessage;
229
+ }
230
+ }
231
+ }
232
+ return await response.result();
233
+ }
234
+ async function executeToolCalls(tools, assistantMessage, signal, stream, getQueuedMessages) {
235
+ const toolCalls = assistantMessage.content.filter((c) => c.type === "toolCall");
236
+ const results = [];
237
+ let queuedMessages;
238
+ for (let index = 0; index < toolCalls.length; index++) {
239
+ const toolCall = toolCalls[index];
240
+ const tool = tools?.find((t) => t.name === toolCall.name);
241
+ stream.push({
242
+ type: "tool_execution_start",
243
+ toolCallId: toolCall.id,
244
+ toolName: toolCall.name,
245
+ args: toolCall.arguments,
246
+ });
247
+ let result;
248
+ let isError = false;
249
+ try {
250
+ if (!tool)
251
+ throw new Error(`Tool ${toolCall.name} not found`);
252
+ const validatedArgs = validateToolArguments(tool, toolCall);
253
+ result = await tool.execute(toolCall.id, validatedArgs, signal, (partialResult) => {
254
+ stream.push({
255
+ type: "tool_execution_update",
256
+ toolCallId: toolCall.id,
257
+ toolName: toolCall.name,
258
+ args: toolCall.arguments,
259
+ partialResult,
260
+ });
261
+ });
262
+ }
263
+ catch (err) {
264
+ result = {
265
+ content: [
266
+ {
267
+ type: "text",
268
+ text: err instanceof Error ? err.message : String(err),
269
+ },
270
+ ],
271
+ details: {},
272
+ };
273
+ isError = true;
274
+ }
275
+ stream.push({
276
+ type: "tool_execution_end",
277
+ toolCallId: toolCall.id,
278
+ toolName: toolCall.name,
279
+ result,
280
+ isError,
281
+ });
282
+ const toolResultMessage = {
283
+ role: "toolResult",
284
+ toolCallId: toolCall.id,
285
+ toolName: toolCall.name,
286
+ content: result.content,
287
+ details: result.details,
288
+ isError,
289
+ timestamp: Date.now(),
290
+ };
291
+ results.push(toolResultMessage);
292
+ stream.push({ type: "message_start", message: toolResultMessage });
293
+ stream.push({ type: "message_end", message: toolResultMessage });
294
+ if (getQueuedMessages) {
295
+ const queued = await getQueuedMessages();
296
+ if (queued.length > 0) {
297
+ queuedMessages = queued;
298
+ const remainingCalls = toolCalls.slice(index + 1);
299
+ for (const skipped of remainingCalls) {
300
+ results.push(skipToolCall(skipped, stream));
301
+ }
302
+ break;
303
+ }
304
+ }
305
+ }
306
+ return { toolResults: results, queuedMessages };
307
+ }
308
+ function skipToolCall(toolCall, stream) {
309
+ const result = {
310
+ content: [{ type: "text", text: "Skipped due to queued user message." }],
311
+ details: {},
312
+ };
313
+ stream.push({
314
+ type: "tool_execution_start",
315
+ toolCallId: toolCall.id,
316
+ toolName: toolCall.name,
317
+ args: toolCall.arguments,
318
+ });
319
+ stream.push({
320
+ type: "tool_execution_end",
321
+ toolCallId: toolCall.id,
322
+ toolName: toolCall.name,
323
+ result,
324
+ isError: true,
325
+ });
326
+ const toolResultMessage = {
327
+ role: "toolResult",
328
+ toolCallId: toolCall.id,
329
+ toolName: toolCall.name,
330
+ content: result.content,
331
+ details: result.details,
332
+ isError: true,
333
+ timestamp: Date.now(),
334
+ };
335
+ stream.push({ type: "message_start", message: toolResultMessage });
336
+ stream.push({ type: "message_end", message: toolResultMessage });
337
+ return toolResultMessage;
338
+ }
@@ -0,0 +1,48 @@
1
+ import { agentLoop, agentLoopContinue } from "./steerable-agent-loop.js";
2
+ export class SteerableProviderTransport {
3
+ options;
4
+ constructor(options = {}) {
5
+ this.options = options;
6
+ }
7
+ getModel(cfg) {
8
+ let model = cfg.model;
9
+ if (this.options.corsProxyUrl && cfg.model.baseUrl) {
10
+ model = {
11
+ ...cfg.model,
12
+ baseUrl: `${this.options.corsProxyUrl}/?url=${encodeURIComponent(cfg.model.baseUrl)}`,
13
+ };
14
+ }
15
+ return model;
16
+ }
17
+ buildContext(messages, cfg) {
18
+ return {
19
+ systemPrompt: cfg.systemPrompt,
20
+ messages,
21
+ tools: cfg.tools,
22
+ };
23
+ }
24
+ buildLoopConfig(model, cfg) {
25
+ return {
26
+ model,
27
+ reasoning: cfg.reasoning,
28
+ getApiKey: this.options.getApiKey,
29
+ getQueuedMessages: cfg.getQueuedMessages,
30
+ };
31
+ }
32
+ async *run(messages, userMessage, cfg, signal) {
33
+ const model = this.getModel(cfg);
34
+ const context = this.buildContext(messages, cfg);
35
+ const pc = this.buildLoopConfig(model, cfg);
36
+ for await (const ev of agentLoop(userMessage, context, pc, signal)) {
37
+ yield ev;
38
+ }
39
+ }
40
+ async *continue(messages, cfg, signal) {
41
+ const model = this.getModel(cfg);
42
+ const context = this.buildContext(messages, cfg);
43
+ const pc = this.buildLoopConfig(model, cfg);
44
+ for await (const ev of agentLoopContinue(context, pc, signal)) {
45
+ yield ev;
46
+ }
47
+ }
48
+ }
@@ -0,0 +1,104 @@
1
+ export function buildAgentSystemPromptAppend(params) {
2
+ const thinkHint = params.defaultThinkLevel && params.defaultThinkLevel !== "off"
3
+ ? `Default thinking level: ${params.defaultThinkLevel}.`
4
+ : "Default thinking level: off.";
5
+ const extraSystemPrompt = params.extraSystemPrompt?.trim();
6
+ const ownerNumbers = (params.ownerNumbers ?? [])
7
+ .map((value) => value.trim())
8
+ .filter(Boolean);
9
+ const ownerLine = ownerNumbers.length > 0
10
+ ? `Owner numbers: ${ownerNumbers.join(", ")}. Treat messages from these numbers as the user.`
11
+ : undefined;
12
+ const reasoningHint = params.reasoningTagHint
13
+ ? [
14
+ "ALL internal reasoning MUST be inside <think>...</think>.",
15
+ "Do not output any analysis outside <think>.",
16
+ "Format every reply as <think>...</think> then <final>...</final>, with no other text.",
17
+ "Only the final user-visible reply may appear inside <final>.",
18
+ "Only text inside <final> is shown to the user; everything else is discarded and never seen by the user.",
19
+ "Example:",
20
+ "<think>Short internal reasoning.</think>",
21
+ "<final>Hey there! What would you like to do next?</final>",
22
+ ].join(" ")
23
+ : undefined;
24
+ const runtimeInfo = params.runtimeInfo;
25
+ const runtimeLines = [];
26
+ if (runtimeInfo?.host)
27
+ runtimeLines.push(`Host: ${runtimeInfo.host}`);
28
+ if (runtimeInfo?.os) {
29
+ const archSuffix = runtimeInfo.arch ? ` (${runtimeInfo.arch})` : "";
30
+ runtimeLines.push(`OS: ${runtimeInfo.os}${archSuffix}`);
31
+ }
32
+ else if (runtimeInfo?.arch) {
33
+ runtimeLines.push(`Arch: ${runtimeInfo.arch}`);
34
+ }
35
+ if (runtimeInfo?.node)
36
+ runtimeLines.push(`Node: ${runtimeInfo.node}`);
37
+ if (runtimeInfo?.model)
38
+ runtimeLines.push(`Model: ${runtimeInfo.model}`);
39
+ const lines = [
40
+ "You are Clawd, a personal assistant running inside Clawdbot.",
41
+ "",
42
+ "## Tooling",
43
+ "Pi lists the standard tools above. This runtime enables:",
44
+ "- grep: search file contents for patterns",
45
+ "- find: find files by glob pattern",
46
+ "- ls: list directory contents",
47
+ "- bash: run shell commands (supports background via yieldMs/background)",
48
+ "- process: manage background bash sessions",
49
+ "- whatsapp_login: generate a WhatsApp QR code and wait for linking",
50
+ "- browser: control clawd's dedicated browser",
51
+ "- canvas: present/eval/snapshot the Canvas",
52
+ "- nodes: list/describe/notify/camera/screen on paired nodes",
53
+ "- cron: manage cron jobs and wake events",
54
+ "TOOLS.md does not control tool availability; it is user guidance for how to use external tools.",
55
+ "",
56
+ "## Workspace",
57
+ `Your working directory is: ${params.workspaceDir}`,
58
+ "Treat this directory as the single global workspace for file operations unless explicitly instructed otherwise.",
59
+ "",
60
+ params.sandboxInfo?.enabled ? "## Sandbox" : "",
61
+ params.sandboxInfo?.enabled
62
+ ? [
63
+ "Tool execution is isolated in a Docker sandbox.",
64
+ "Some tools may be unavailable due to sandbox policy.",
65
+ params.sandboxInfo.workspaceDir
66
+ ? `Sandbox workspace: ${params.sandboxInfo.workspaceDir}`
67
+ : "",
68
+ params.sandboxInfo.browserControlUrl
69
+ ? `Sandbox browser control URL: ${params.sandboxInfo.browserControlUrl}`
70
+ : "",
71
+ params.sandboxInfo.browserNoVncUrl
72
+ ? `Sandbox browser observer (noVNC): ${params.sandboxInfo.browserNoVncUrl}`
73
+ : "",
74
+ ]
75
+ .filter(Boolean)
76
+ .join("\n")
77
+ : "",
78
+ params.sandboxInfo?.enabled ? "" : "",
79
+ ownerLine ? "## User Identity" : "",
80
+ ownerLine ?? "",
81
+ ownerLine ? "" : "",
82
+ "## Workspace Files (injected)",
83
+ "These user-editable files are loaded by Clawdbot and included below in Project Context.",
84
+ "",
85
+ "## Messaging Safety",
86
+ "Never send streaming/partial replies to external messaging surfaces; only final replies should be delivered there.",
87
+ "Clawdbot handles message transport automatically; respond normally and your reply will be delivered to the current chat.",
88
+ "",
89
+ "## Reply Tags",
90
+ "To request a native reply/quote on supported surfaces, include one tag in your reply:",
91
+ "- [[reply_to_current]] replies to the triggering message.",
92
+ "- [[reply_to:<id>]] replies to a specific message id when you have it.",
93
+ "Tags are stripped before sending; support depends on the current provider config.",
94
+ "",
95
+ ];
96
+ if (extraSystemPrompt) {
97
+ lines.push("## Group Chat Context", extraSystemPrompt, "");
98
+ }
99
+ if (reasoningHint) {
100
+ lines.push("## Reasoning Format", reasoningHint, "");
101
+ }
102
+ lines.push("## Heartbeats", 'If you receive a heartbeat poll (a user message containing just "HEARTBEAT"), and there is nothing that needs attention, reply exactly:', "HEARTBEAT_OK", 'Clawdbot treats a leading/trailing "HEARTBEAT_OK" as a heartbeat ack (and may discard it).', 'If something needs attention, do NOT include "HEARTBEAT_OK"; reply with the alert text instead.', "", "## Runtime", ...runtimeLines, thinkHint);
103
+ return lines.filter(Boolean).join("\n");
104
+ }
@@ -0,0 +1,162 @@
1
+ import fs from "node:fs";
2
+ import { shortenHomeInString } from "../utils.js";
3
+ const TOOL_DISPLAY_CONFIG = (() => {
4
+ try {
5
+ const raw = fs.readFileSync(new URL("./tool-display.json", import.meta.url), "utf8");
6
+ return JSON.parse(raw);
7
+ }
8
+ catch {
9
+ return {};
10
+ }
11
+ })();
12
+ const FALLBACK = TOOL_DISPLAY_CONFIG.fallback ?? { emoji: "🧩" };
13
+ const TOOL_MAP = TOOL_DISPLAY_CONFIG.tools ?? {};
14
+ function normalizeToolName(name) {
15
+ return (name ?? "tool").trim();
16
+ }
17
+ function defaultTitle(name) {
18
+ const cleaned = name.replace(/_/g, " ").trim();
19
+ if (!cleaned)
20
+ return "Tool";
21
+ return cleaned
22
+ .split(/\s+/)
23
+ .map((part) => part.length <= 2 && part.toUpperCase() === part
24
+ ? part
25
+ : `${part.at(0)?.toUpperCase() ?? ""}${part.slice(1)}`)
26
+ .join(" ");
27
+ }
28
+ function normalizeVerb(value) {
29
+ const trimmed = value?.trim();
30
+ if (!trimmed)
31
+ return undefined;
32
+ return trimmed.replace(/_/g, " ");
33
+ }
34
+ function coerceDisplayValue(value) {
35
+ if (value === null || value === undefined)
36
+ return undefined;
37
+ if (typeof value === "string") {
38
+ const trimmed = value.trim();
39
+ if (!trimmed)
40
+ return undefined;
41
+ const firstLine = trimmed.split(/\r?\n/)[0]?.trim() ?? "";
42
+ if (!firstLine)
43
+ return undefined;
44
+ return firstLine.length > 160 ? `${firstLine.slice(0, 157)}…` : firstLine;
45
+ }
46
+ if (typeof value === "number" || typeof value === "boolean") {
47
+ return String(value);
48
+ }
49
+ if (Array.isArray(value)) {
50
+ const values = value
51
+ .map((item) => coerceDisplayValue(item))
52
+ .filter((item) => Boolean(item));
53
+ if (values.length === 0)
54
+ return undefined;
55
+ const preview = values.slice(0, 3).join(", ");
56
+ return values.length > 3 ? `${preview}…` : preview;
57
+ }
58
+ return undefined;
59
+ }
60
+ function lookupValueByPath(args, path) {
61
+ if (!args || typeof args !== "object")
62
+ return undefined;
63
+ let current = args;
64
+ for (const segment of path.split(".")) {
65
+ if (!segment)
66
+ return undefined;
67
+ if (!current || typeof current !== "object")
68
+ return undefined;
69
+ const record = current;
70
+ current = record[segment];
71
+ }
72
+ return current;
73
+ }
74
+ function resolveDetailFromKeys(args, keys) {
75
+ for (const key of keys) {
76
+ const value = lookupValueByPath(args, key);
77
+ const display = coerceDisplayValue(value);
78
+ if (display)
79
+ return display;
80
+ }
81
+ return undefined;
82
+ }
83
+ function resolveReadDetail(args) {
84
+ if (!args || typeof args !== "object")
85
+ return undefined;
86
+ const record = args;
87
+ const path = typeof record.path === "string" ? record.path : undefined;
88
+ if (!path)
89
+ return undefined;
90
+ const offset = typeof record.offset === "number" ? record.offset : undefined;
91
+ const limit = typeof record.limit === "number" ? record.limit : undefined;
92
+ if (offset !== undefined && limit !== undefined) {
93
+ return `${path}:${offset}-${offset + limit}`;
94
+ }
95
+ return path;
96
+ }
97
+ function resolveWriteDetail(args) {
98
+ if (!args || typeof args !== "object")
99
+ return undefined;
100
+ const record = args;
101
+ const path = typeof record.path === "string" ? record.path : undefined;
102
+ return path;
103
+ }
104
+ function resolveActionSpec(spec, action) {
105
+ if (!spec || !action)
106
+ return undefined;
107
+ return spec.actions?.[action] ?? undefined;
108
+ }
109
+ export function resolveToolDisplay(params) {
110
+ const name = normalizeToolName(params.name);
111
+ const key = name.toLowerCase();
112
+ const spec = TOOL_MAP[key];
113
+ const emoji = spec?.emoji ?? FALLBACK.emoji ?? "🧩";
114
+ const title = spec?.title ?? defaultTitle(name);
115
+ const label = spec?.label ?? name;
116
+ const actionRaw = params.args && typeof params.args === "object"
117
+ ? params.args.action
118
+ : undefined;
119
+ const action = typeof actionRaw === "string" ? actionRaw.trim() : undefined;
120
+ const actionSpec = resolveActionSpec(spec, action);
121
+ const verb = normalizeVerb(actionSpec?.label ?? action);
122
+ let detail;
123
+ if (key === "read")
124
+ detail = resolveReadDetail(params.args);
125
+ if (!detail && (key === "write" || key === "edit" || key === "attach")) {
126
+ detail = resolveWriteDetail(params.args);
127
+ }
128
+ const detailKeys = actionSpec?.detailKeys ?? spec?.detailKeys ?? FALLBACK.detailKeys ?? [];
129
+ if (!detail && detailKeys.length > 0) {
130
+ detail = resolveDetailFromKeys(params.args, detailKeys);
131
+ }
132
+ if (!detail && params.meta) {
133
+ detail = params.meta;
134
+ }
135
+ if (detail) {
136
+ detail = shortenHomeInString(detail);
137
+ }
138
+ return {
139
+ name,
140
+ emoji,
141
+ title,
142
+ label,
143
+ verb,
144
+ detail,
145
+ };
146
+ }
147
+ export function formatToolDetail(display) {
148
+ const parts = [];
149
+ if (display.verb)
150
+ parts.push(display.verb);
151
+ if (display.detail)
152
+ parts.push(display.detail);
153
+ if (parts.length === 0)
154
+ return undefined;
155
+ return parts.join(" · ");
156
+ }
157
+ export function formatToolSummary(display) {
158
+ const detail = formatToolDetail(display);
159
+ return detail
160
+ ? `${display.emoji} ${display.label}: ${detail}`
161
+ : `${display.emoji} ${display.label}`;
162
+ }