@hybridaione/hybridclaw 0.24.3 → 0.25.0

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 (257) hide show
  1. package/AGENTS.md +7 -1
  2. package/CHANGELOG.md +128 -0
  3. package/README.md +11 -2
  4. package/config.example.json +13 -3
  5. package/console/dist/assets/chat-CDXd1yTl.js +4 -0
  6. package/console/dist/assets/index-DHzWClL-.css +1 -0
  7. package/console/dist/assets/index-DN3T1L-r.js +174 -0
  8. package/console/dist/assets/terminal-Dwbnwiir.js +1 -0
  9. package/console/dist/index.html +2 -2
  10. package/console/package.json +1 -1
  11. package/container/dist/artifacts.js +5 -0
  12. package/container/dist/artifacts.js.map +1 -1
  13. package/container/dist/providers/hybridai.js +13 -4
  14. package/container/dist/providers/hybridai.js.map +1 -1
  15. package/container/dist/user-agent.js +31 -0
  16. package/container/dist/user-agent.js.map +1 -0
  17. package/container/npm-shrinkwrap.json +2 -2
  18. package/container/package-lock.json +2 -2
  19. package/container/package.json +1 -1
  20. package/container/src/artifacts.ts +7 -0
  21. package/container/src/mcp/types.ts +2 -0
  22. package/container/src/providers/hybridai.ts +17 -4
  23. package/container/src/user-agent.ts +40 -0
  24. package/dist/agents/agent-config-command.d.ts.map +1 -1
  25. package/dist/agents/agent-config-command.js +7 -0
  26. package/dist/agents/agent-config-command.js.map +1 -1
  27. package/dist/agents/agent-registry.d.ts.map +1 -1
  28. package/dist/agents/agent-registry.js +5 -2
  29. package/dist/agents/agent-registry.js.map +1 -1
  30. package/dist/agents/agent-runtime-config.d.ts.map +1 -1
  31. package/dist/agents/agent-runtime-config.js +1 -0
  32. package/dist/agents/agent-runtime-config.js.map +1 -1
  33. package/dist/agents/agent-types.d.ts +2 -1
  34. package/dist/agents/agent-types.d.ts.map +1 -1
  35. package/dist/agents/agent-types.js +2 -1
  36. package/dist/agents/agent-types.js.map +1 -1
  37. package/dist/agents/claw-archive.d.ts +1 -0
  38. package/dist/agents/claw-archive.d.ts.map +1 -1
  39. package/dist/agents/claw-archive.js +14 -3
  40. package/dist/agents/claw-archive.js.map +1 -1
  41. package/dist/agents/claw-manifest.d.ts +1 -0
  42. package/dist/agents/claw-manifest.d.ts.map +1 -1
  43. package/dist/agents/claw-manifest.js +3 -1
  44. package/dist/agents/claw-manifest.js.map +1 -1
  45. package/dist/auth/codex-auth.d.ts.map +1 -1
  46. package/dist/auth/codex-auth.js +2 -27
  47. package/dist/auth/codex-auth.js.map +1 -1
  48. package/dist/auth/hybridai-auth.d.ts.map +1 -1
  49. package/dist/auth/hybridai-auth.js +2 -28
  50. package/dist/auth/hybridai-auth.js.map +1 -1
  51. package/dist/channels/email/connection.d.ts +3 -1
  52. package/dist/channels/email/connection.d.ts.map +1 -1
  53. package/dist/channels/email/connection.js.map +1 -1
  54. package/dist/channels/email/inbound.d.ts +2 -1
  55. package/dist/channels/email/inbound.d.ts.map +1 -1
  56. package/dist/channels/email/inbound.js +1 -0
  57. package/dist/channels/email/inbound.js.map +1 -1
  58. package/dist/channels/email/runtime.d.ts +6 -1
  59. package/dist/channels/email/runtime.d.ts.map +1 -1
  60. package/dist/channels/email/runtime.js +248 -101
  61. package/dist/channels/email/runtime.js.map +1 -1
  62. package/dist/channels/message/tool-actions.d.ts.map +1 -1
  63. package/dist/channels/message/tool-actions.js +5 -0
  64. package/dist/channels/message/tool-actions.js.map +1 -1
  65. package/dist/cli/agent-command.js +1 -1
  66. package/dist/cli/agent-command.js.map +1 -1
  67. package/dist/cli/help.d.ts.map +1 -1
  68. package/dist/cli/help.js +15 -4
  69. package/dist/cli/help.js.map +1 -1
  70. package/dist/cli.d.ts.map +1 -1
  71. package/dist/cli.js +9 -5
  72. package/dist/cli.js.map +1 -1
  73. package/dist/command-registry.d.ts.map +1 -1
  74. package/dist/command-registry.js +46 -4
  75. package/dist/command-registry.js.map +1 -1
  76. package/dist/config/config.d.ts +1 -0
  77. package/dist/config/config.d.ts.map +1 -1
  78. package/dist/config/config.js +2 -0
  79. package/dist/config/config.js.map +1 -1
  80. package/dist/config/runtime-config.d.ts +22 -1
  81. package/dist/config/runtime-config.d.ts.map +1 -1
  82. package/dist/config/runtime-config.js +153 -5
  83. package/dist/config/runtime-config.js.map +1 -1
  84. package/dist/evals/agent-risk-native.d.ts +52 -0
  85. package/dist/evals/agent-risk-native.d.ts.map +1 -0
  86. package/dist/evals/agent-risk-native.js +1346 -0
  87. package/dist/evals/agent-risk-native.js.map +1 -0
  88. package/dist/evals/eval-command.d.ts.map +1 -1
  89. package/dist/evals/eval-command.js +236 -16
  90. package/dist/evals/eval-command.js.map +1 -1
  91. package/dist/evals/hybridai-skills-command.d.ts.map +1 -1
  92. package/dist/evals/hybridai-skills-command.js +2 -0
  93. package/dist/evals/hybridai-skills-command.js.map +1 -1
  94. package/dist/evals/locomo-native.d.ts.map +1 -1
  95. package/dist/evals/locomo-native.js +2 -0
  96. package/dist/evals/locomo-native.js.map +1 -1
  97. package/dist/evals/openai-url.d.ts +3 -0
  98. package/dist/evals/openai-url.d.ts.map +1 -0
  99. package/dist/evals/openai-url.js +8 -0
  100. package/dist/evals/openai-url.js.map +1 -0
  101. package/dist/evolution/harness-evolution.d.ts +4 -0
  102. package/dist/evolution/harness-evolution.d.ts.map +1 -1
  103. package/dist/evolution/harness-evolution.js +35 -1
  104. package/dist/evolution/harness-evolution.js.map +1 -1
  105. package/dist/evolution/harness-risk-taxonomy.d.ts +149 -0
  106. package/dist/evolution/harness-risk-taxonomy.d.ts.map +1 -0
  107. package/dist/evolution/harness-risk-taxonomy.js +280 -0
  108. package/dist/evolution/harness-risk-taxonomy.js.map +1 -0
  109. package/dist/gateway/auth-token.d.ts +1 -0
  110. package/dist/gateway/auth-token.d.ts.map +1 -1
  111. package/dist/gateway/auth-token.js +3 -0
  112. package/dist/gateway/auth-token.js.map +1 -1
  113. package/dist/gateway/docs.d.ts +1 -0
  114. package/dist/gateway/docs.d.ts.map +1 -1
  115. package/dist/gateway/docs.js +116 -72
  116. package/dist/gateway/docs.js.map +1 -1
  117. package/dist/gateway/gateway-admin-secrets.js +2 -2
  118. package/dist/gateway/gateway-admin-secrets.js.map +1 -1
  119. package/dist/gateway/gateway-chat-service.d.ts.map +1 -1
  120. package/dist/gateway/gateway-chat-service.js +90 -39
  121. package/dist/gateway/gateway-chat-service.js.map +1 -1
  122. package/dist/gateway/gateway-client.d.ts +9 -1
  123. package/dist/gateway/gateway-client.d.ts.map +1 -1
  124. package/dist/gateway/gateway-client.js +43 -0
  125. package/dist/gateway/gateway-client.js.map +1 -1
  126. package/dist/gateway/gateway-http-server.d.ts.map +1 -1
  127. package/dist/gateway/gateway-http-server.js +259 -62
  128. package/dist/gateway/gateway-http-server.js.map +1 -1
  129. package/dist/gateway/gateway-log-service.d.ts +17 -0
  130. package/dist/gateway/gateway-log-service.d.ts.map +1 -1
  131. package/dist/gateway/gateway-log-service.js +48 -4
  132. package/dist/gateway/gateway-log-service.js.map +1 -1
  133. package/dist/gateway/gateway-service.d.ts +39 -3
  134. package/dist/gateway/gateway-service.d.ts.map +1 -1
  135. package/dist/gateway/gateway-service.js +1109 -61
  136. package/dist/gateway/gateway-service.js.map +1 -1
  137. package/dist/gateway/gateway-types.d.ts +78 -1
  138. package/dist/gateway/gateway-types.d.ts.map +1 -1
  139. package/dist/gateway/gateway-types.js.map +1 -1
  140. package/dist/gateway/gateway.js +20 -7
  141. package/dist/gateway/gateway.js.map +1 -1
  142. package/dist/gateway/hatching-completion.d.ts +18 -0
  143. package/dist/gateway/hatching-completion.d.ts.map +1 -0
  144. package/dist/gateway/hatching-completion.js +96 -0
  145. package/dist/gateway/hatching-completion.js.map +1 -0
  146. package/dist/infra/container-runner.d.ts.map +1 -1
  147. package/dist/infra/container-runner.js +5 -4
  148. package/dist/infra/container-runner.js.map +1 -1
  149. package/dist/infra/host-runner.d.ts.map +1 -1
  150. package/dist/infra/host-runner.js +5 -4
  151. package/dist/infra/host-runner.js.map +1 -1
  152. package/dist/infra/model-response-debug.d.ts +1 -0
  153. package/dist/infra/model-response-debug.d.ts.map +1 -1
  154. package/dist/infra/model-response-debug.js +21 -2
  155. package/dist/infra/model-response-debug.js.map +1 -1
  156. package/dist/logger-format.d.ts +1 -0
  157. package/dist/logger-format.d.ts.map +1 -1
  158. package/dist/logger-format.js +1 -0
  159. package/dist/logger-format.js.map +1 -1
  160. package/dist/logger.d.ts +7 -0
  161. package/dist/logger.d.ts.map +1 -1
  162. package/dist/logger.js +39 -3
  163. package/dist/logger.js.map +1 -1
  164. package/dist/mcp/mcp-oauth.d.ts +91 -0
  165. package/dist/mcp/mcp-oauth.d.ts.map +1 -0
  166. package/dist/mcp/mcp-oauth.js +434 -0
  167. package/dist/mcp/mcp-oauth.js.map +1 -0
  168. package/dist/mcp/server-config.d.ts +7 -0
  169. package/dist/mcp/server-config.d.ts.map +1 -0
  170. package/dist/mcp/server-config.js +9 -0
  171. package/dist/mcp/server-config.js.map +1 -0
  172. package/dist/memory/db.d.ts +4 -1
  173. package/dist/memory/db.d.ts.map +1 -1
  174. package/dist/memory/db.js +59 -4
  175. package/dist/memory/db.js.map +1 -1
  176. package/dist/onboarding.d.ts.map +1 -1
  177. package/dist/onboarding.js +3 -28
  178. package/dist/onboarding.js.map +1 -1
  179. package/dist/providers/hybridai.d.ts.map +1 -1
  180. package/dist/providers/hybridai.js +4 -1
  181. package/dist/providers/hybridai.js.map +1 -1
  182. package/dist/providers/user-agent.d.ts +3 -0
  183. package/dist/providers/user-agent.d.ts.map +1 -0
  184. package/dist/providers/user-agent.js +7 -0
  185. package/dist/providers/user-agent.js.map +1 -0
  186. package/dist/security/admin-rbac.d.ts +24 -1
  187. package/dist/security/admin-rbac.d.ts.map +1 -1
  188. package/dist/security/admin-rbac.js +505 -19
  189. package/dist/security/admin-rbac.js.map +1 -1
  190. package/dist/skills/skill-docs.d.ts +23 -0
  191. package/dist/skills/skill-docs.d.ts.map +1 -0
  192. package/dist/skills/skill-docs.js +189 -0
  193. package/dist/skills/skill-docs.js.map +1 -0
  194. package/dist/skills/skills.d.ts +3 -0
  195. package/dist/skills/skills.d.ts.map +1 -1
  196. package/dist/skills/skills.js +10 -0
  197. package/dist/skills/skills.js.map +1 -1
  198. package/dist/tui-mcp-wizard.d.ts +63 -0
  199. package/dist/tui-mcp-wizard.d.ts.map +1 -0
  200. package/dist/tui-mcp-wizard.js +299 -0
  201. package/dist/tui-mcp-wizard.js.map +1 -0
  202. package/dist/tui.d.ts.map +1 -1
  203. package/dist/tui.js +45 -1
  204. package/dist/tui.js.map +1 -1
  205. package/dist/types/models.d.ts +5 -0
  206. package/dist/types/models.d.ts.map +1 -1
  207. package/dist/types/models.js.map +1 -1
  208. package/dist/utils/open-url.d.ts +3 -0
  209. package/dist/utils/open-url.d.ts.map +1 -0
  210. package/dist/utils/open-url.js +29 -0
  211. package/dist/utils/open-url.js.map +1 -0
  212. package/dist/workspace.d.ts +23 -2
  213. package/dist/workspace.d.ts.map +1 -1
  214. package/dist/workspace.js +153 -178
  215. package/dist/workspace.js.map +1 -1
  216. package/docs/agents.html +20 -6
  217. package/docs/content/README.md +21 -9
  218. package/docs/content/channels/email.md +55 -0
  219. package/docs/content/developer-guide/README.md +11 -0
  220. package/docs/content/developer-guide/admin-access-control.md +107 -0
  221. package/docs/content/developer-guide/iso27001/README.md +51 -0
  222. package/docs/content/developer-guide/iso27001/_category_.json +5 -0
  223. package/docs/content/developer-guide/iso27001/access-control-matrix.md +45 -0
  224. package/docs/content/developer-guide/iso27001/asset-data-inventory.md +32 -0
  225. package/docs/content/developer-guide/iso27001/audit-monitoring-matrix.md +33 -0
  226. package/docs/content/developer-guide/iso27001/control-owners.md +23 -0
  227. package/docs/content/developer-guide/iso27001/evidence-calendar.md +31 -0
  228. package/docs/content/developer-guide/iso27001/review-signoff.md +35 -0
  229. package/docs/content/developer-guide/iso27001/risk-register.md +25 -0
  230. package/docs/content/developer-guide/iso27001/statement-of-applicability.md +45 -0
  231. package/docs/content/developer-guide/iso27001/supplier-register.md +20 -0
  232. package/docs/content/developer-guide/iso27001-control-matrix.md +165 -0
  233. package/docs/content/developer-guide/iso42001-aims-evidence-templates.md +184 -0
  234. package/docs/content/developer-guide/iso42001-aims-readiness.md +152 -0
  235. package/docs/content/extensibility/agent-packages.md +10 -8
  236. package/docs/content/getting-started/installation.md +1 -1
  237. package/docs/content/getting-started/quickstart.md +9 -0
  238. package/docs/content/guides/bundled-skills.md +3 -2
  239. package/docs/content/guides/tui-mcp.md +36 -1
  240. package/docs/content/internal/roadmap.md +2 -1
  241. package/docs/content/navigation.json +415 -0
  242. package/docs/content/reference/commands.md +15 -7
  243. package/docs/content/reference/model-selection.md +3 -0
  244. package/docs/index.html +80 -56
  245. package/docs/static/docs.js +12 -237
  246. package/npm-shrinkwrap.json +5 -5
  247. package/package.json +2 -1
  248. package/skills/blink/SKILL.md +1 -0
  249. package/skills/blink/logo.webp +0 -0
  250. package/skills/posthog/SKILL.md +269 -0
  251. package/skills/posthog/posthog.cjs +924 -0
  252. package/templates/BOOTSTRAP.md +88 -124
  253. package/templates/USER.md +7 -9
  254. package/console/dist/assets/chat-CxVoYrJK.js +0 -96
  255. package/console/dist/assets/index-B4At9j5Y.js +0 -80
  256. package/console/dist/assets/index-B5qDvpvj.css +0 -1
  257. package/console/dist/assets/terminal-Dnsm3Yl9.js +0 -1
package/AGENTS.md CHANGED
@@ -327,7 +327,13 @@ Skill resolution order (first match wins):
327
327
  }
328
328
  ```
329
329
  2. Tools are auto-discovered at startup and merged into the tool namespace.
330
- 3. Test with `hybridclaw` running in dev mode.
330
+ 3. Remote `http`/`sse` servers can set `"auth": "oauth"`; the gateway runs the
331
+ OAuth 2.1 flow (`src/mcp/mcp-oauth.ts`), stores credentials in the
332
+ encrypted runtime secret store (`~/.hybridclaw/credentials.json`, one
333
+ `MCP_OAUTH_*` entry per server), and injects a fresh `Authorization` header
334
+ per turn. Connect via `/mcp login <name>`, the TUI `/mcp add` wizard, or the
335
+ console MCP page.
336
+ 4. Test with `hybridclaw` running in dev mode.
331
337
 
332
338
  ### 7.4 Modifying Approval Policy
333
339
 
package/CHANGELOG.md CHANGED
@@ -2,6 +2,134 @@
2
2
 
3
3
  ## Unreleased
4
4
 
5
+ ## [0.25.0](https://github.com/HybridAIOne/hybridclaw/tree/v0.25.0) - 2026-06-20
6
+
7
+ ### Added
8
+
9
+ - **Improved onboarding experience**: First-run hatching has a dedicated
10
+ `hybridai.onboardingModel` override, runtime-aware bootstrap context,
11
+ stronger welcome-email guidance, preserved setup links in chat, direct
12
+ Markdown links for local setup routes, completion tracking after the first
13
+ email, and duplicate-autostart protection. New agents receive the bootstrap
14
+ file at creation time, reinstalled agents can hatch again when appropriate,
15
+ and completed agents can show tailored empty-chat headers without restarting
16
+ onboarding.
17
+ - **Remote MCP OAuth**: Remote `http` and `sse` MCP servers can opt into
18
+ `"auth": "oauth"` with gateway-managed OAuth 2.1 discovery, PKCE, dynamic
19
+ client registration, encrypted token storage, automatic refresh, and guided
20
+ setup in both the TUI and admin console. Added `/mcp login`, `/mcp logout`,
21
+ and `/mcp status` flows for local and chat channels.
22
+ - **Admin skill detail pages**: `/admin/skills` now opens dedicated detail
23
+ pages with parsed docs, tool/prompt/dependency metadata, package logos,
24
+ credential status, write-only secret management, enable/disable controls,
25
+ example prompt launchers, recent invocations, and guarded text-file editing
26
+ for installed skill packages.
27
+ - **Per-agent email mailboxes**: Built-in IMAP/SMTP email supports
28
+ `email.accounts[]` so separate mailbox credentials can route inbound mail to
29
+ specific agents, send replies from the mailbox that received the thread, and
30
+ prefer the active agent's mailbox for agent-initiated sends.
31
+ - **Agent-risk eval harness**: Added `/eval agent-risk` and
32
+ `hybridclaw eval agent-risk` with synthetic canary scenarios covering every
33
+ top-level NIST AI RMF function, NIST AI 600-1 GAI risk, and OWASP LLM Top 10
34
+ 2025 item. The gate writes redacted evidence artifacts and supports focused
35
+ scenario runs.
36
+ - **Admin access control evidence**: Added scoped admin RBAC role bundles,
37
+ route-level action enforcement for scoped sessions, terminal stream
38
+ authorization checks, admin access-control docs, and ISO/IEC 27001 evidence
39
+ records for access review, control ownership, monitoring, suppliers, risk,
40
+ asset/data inventory, signoff, and evidence cadence.
41
+ - **ISO/IEC 42001 readiness docs**: Added an AI management-system readiness
42
+ matrix and reusable evidence templates for HybridClaw AI subsystem inventory,
43
+ risk, impact, lifecycle, monitoring, and human oversight records.
44
+ - **PostHog business skill**: Added a bundled `posthog` skill for guarded
45
+ event capture, person-property updates, private person reads, feature flag
46
+ reads and test evaluation, Query API/HogQL reads, approval plans, and
47
+ missing-secret diagnostics through the gateway HTTP proxy.
48
+ - **Guarded session pruning**: Added `sessions prune --older-than <duration>`
49
+ with dry-run default, explicit `--confirm`, protected-session skips, minimum
50
+ retention, and structured `session.prune` audit events.
51
+ - **Supply-chain security workflow**: Added BuildKit provenance and SBOM
52
+ attestations for Docker builds, a pinned Security Scan workflow with CodeQL
53
+ and tracked secret scanning, and `npm run security:secret-scan` for local
54
+ verification.
55
+
56
+ ### Changed
57
+
58
+ - **Agent package installs**: `.claw` installs restore only archived workspace
59
+ files plus manifest-declared bundled/imported assets. Default bootstrap
60
+ templates are seeded by agent creation, not by package install, preserving
61
+ the package author's exact workspace file set.
62
+ - **Admin browser auth**: Browser admin auth uses signed HttpOnly session
63
+ cookies for callback flows, keeps manual fallback tokens tab-scoped, removes
64
+ EventSource query-token auth, and keeps broad bearer-token API compatibility
65
+ for existing operators.
66
+ - **MCP and docs navigation**: Docs navigation now comes from a shared
67
+ `docs/content/navigation.json` manifest used by the static docs app and
68
+ gateway docs renderer, keeping internal docs direct-linkable but absent from
69
+ sidebar and search unless explicitly listed.
70
+ - **HybridAI request identity**: Gateway, container, and eval HybridAI calls
71
+ include a versioned `hybridclaw/<version>` user agent for upstream
72
+ diagnostics.
73
+ - **Homepage and docs positioning**: The homepage, docs shell, setup docs, and
74
+ release facts were refreshed around current managed-cloud, distillation,
75
+ A2A, proxy-agent, channel, business-skill, admin, and security capabilities.
76
+
77
+ ### Fixed
78
+
79
+ - **Hatching and opening-message reliability**: Bootstrap autostarts use an
80
+ atomic cross-process claim, GPT-5-family hatching is guided to send the
81
+ welcome email once required user details are present, duplicated bootstrap
82
+ blocks are collapsed, `OPENING.md` autostart produces one assistant message,
83
+ and setup links remain visible in chat after the welcome email.
84
+ - **HybridAI onboarding bot fallback**: Agent/model controls stay in sync after
85
+ `/agent switch`, `/bot clear` clears both session and configured default bot
86
+ state, and HybridAI default-user fallback can resolve the user's bot without
87
+ stale default-chatbot reuse.
88
+ - **Mobile chat QR handoff**: QR continuation tokens preserve web-session auth
89
+ and set the signed session cookie before redirecting to the target chat, so
90
+ cloud/container deployments open the intended session instead of bouncing to
91
+ login.
92
+ - **Named local model selection**: The model switcher shows local route labels
93
+ in row subtitles and search text, so duplicate-looking entries such as
94
+ default `vLLM` and named `haigpu1` Qwen routes are distinguishable.
95
+ - **Skill admin polish**: Skill detail navigation stays inside the admin app,
96
+ skill-only slash commands link back to detail pages, package assets are not
97
+ surfaced as generic chat artifacts, credential overwrite labels are clearer,
98
+ set credentials show checkmarks, and Blink uses the official logo asset.
99
+ - **Secret-scan eval fixtures**: Agent-risk eval canaries were renamed to avoid
100
+ secret-shaped false positives while preserving the intended leakage tests.
101
+
102
+ ## [0.24.4](https://github.com/HybridAIOne/hybridclaw/tree/v0.24.4) - 2026-06-16
103
+
104
+ ### Added
105
+
106
+ - **Admin logging modes**: The admin Logs page can switch logging Off, On, or
107
+ Debug from the console, persist the runtime config, reload the gateway, and
108
+ keep selected log tails pinned to the newest content after load or refresh.
109
+
110
+ ### Changed
111
+
112
+ - **Admin Logs readability**: The Logs page gives the detail panel more room,
113
+ avoids duplicate path display, keeps the selected path visible in metadata,
114
+ strips ANSI color from tails, aligns mid-file tails, and shows full local
115
+ dates in formatted timestamps.
116
+ - **Runtime logging config**: Request logging and model-response debug capture
117
+ are controlled through `ops.logRequests` and `ops.debugModelResponses` while
118
+ preserving environment and CLI startup overrides.
119
+
120
+ ### Fixed
121
+
122
+ - **Admin dropdown selection**: Controlled native selects now apply the first
123
+ chosen option immediately by marking fields touched through React
124
+ change/blur handling instead of wrapper-level native listeners.
125
+ - **GPT-5 onboarding email send**: GPT-5-family hatching prompts now tell the
126
+ agent to send the welcome message once basic user info and a valid email
127
+ address are present, without showing a draft or asking for another
128
+ confirmation.
129
+ - **Logging mode save feedback**: The Logs page checks gateway reload
130
+ responses before reporting logging mode updates as saved and refreshes the
131
+ effective runtime state after save.
132
+
5
133
  ## [0.24.3](https://github.com/HybridAIOne/hybridclaw/tree/v0.24.3) - 2026-06-15
6
134
 
7
135
  ### Changed
package/README.md CHANGED
@@ -30,6 +30,10 @@ HybridAI proxy agents, and trusted peer HybridClaw instances can address one
30
30
  another, exchange A2A envelopes, and route work through approval-aware
31
31
  channels.
32
32
 
33
+ First-run onboarding is built around hatching: a new agent asks about the
34
+ user's work, records useful context, keeps setup links visible in chat, and can
35
+ send a tailored first-jobs welcome email when an email route is available.
36
+
33
37
  Credentials stay outside the model context. Secrets live in the encrypted
34
38
  runtime store and SecretRef-backed tools resolve them at execution time, so
35
39
  LLMs see the requested action and approval context, not raw API keys,
@@ -51,6 +55,7 @@ HybridClaw on HybridAI Cloud in a few minutes at
51
55
 
52
56
  | You need | HybridClaw gives you |
53
57
  | --- | --- |
58
+ | A first run that becomes useful quickly | Guided hatching with setup links, tailored first-job suggestions, optional onboarding-specific model routing, and welcome-email handoff |
54
59
  | Business workflows that survive real use | Production skill helpers with fixtures, eval scenarios, targeted tests, approval tiers, and a `Qwen/Qwen3.6-27B-FP8` validation baseline |
55
60
  | Multi-agent workflows across installations | Local agents, hosted proxy agents, A2A trust, explicit addressing, inbound envelopes, and admin-visible peer pairing |
56
61
  | Credentials the model cannot read | Encrypted runtime secrets and SecretRef-backed execution paths that keep raw keys and passwords out of prompts and tool results |
@@ -113,7 +118,7 @@ npm run desktop
113
118
  | Runtime | Gateway service, TUI client, web chat, admin console, loopback OpenAI-compatible API, Docker or host execution |
114
119
  | Governance | Encrypted runtime secrets, SecretRef credential isolation, approval policies, sandbox controls, audit trails with hash-chain integrity |
115
120
  | Memory | Local memory files, SQLite persistence, semantic recall, session compaction, optional HybridAI cloud memory sync |
116
- | Agents | Per-agent workspaces, models, budgets, prompt files, explicit addressing, proxy agents, A2A trust, peer-instance communication |
121
+ | Agents | Guided hatching, per-agent workspaces, models, budgets, prompt files, explicit addressing, proxy agents, A2A trust, peer-instance communication |
117
122
  | Extensibility | Packaged business skills, plugins, MCP servers, SecretRef-backed HTTP tools |
118
123
 
119
124
  ## Product Strengths
@@ -121,6 +126,10 @@ npm run desktop
121
126
  - **Validated business skills**: production skills use deterministic helpers,
122
127
  fixtures, eval scenarios, and targeted tests so small models can perform
123
128
  useful work through structured actions.
129
+ - **Guided onboarding**: hatching collects useful work context, keeps setup
130
+ links handy, writes first-job suggestions, and can route the first-run
131
+ conversation through a stronger onboarding model before returning to the
132
+ normal default.
124
133
  - **Multi-agent operations**: agents can coordinate across local workspaces,
125
134
  hosted HybridAI proxies, and trusted peer HybridClaw instances with A2A
126
135
  pairing, explicit addressing, inbound envelopes, and admin-visible trust.
@@ -211,7 +220,7 @@ Core pieces:
211
220
  | Build desktop releases | [Desktop Release Builds](https://hybridaione.github.io/hybridclaw/docs/developer-guide/desktop-release) |
212
221
  | Contribute | [CONTRIBUTING.md](./CONTRIBUTING.md), [docs/content/README.md](./docs/content/README.md) |
213
222
 
214
- Latest release: [v0.24.3](https://github.com/HybridAIOne/hybridclaw/releases/tag/v0.24.3).
223
+ Latest release: [v0.25.0](https://github.com/HybridAIOne/hybridclaw/releases/tag/v0.25.0).
215
224
  Release notes: [CHANGELOG.md](./CHANGELOG.md)
216
225
 
217
226
  ## Development
@@ -1,5 +1,5 @@
1
1
  {
2
- "version": 30,
2
+ "version": 31,
3
3
  "security": {
4
4
  "trustModelAccepted": false,
5
5
  "trustModelAcceptedAt": "",
@@ -304,11 +304,13 @@
304
304
  "folders": ["INBOX"],
305
305
  "allowFrom": [],
306
306
  "textChunkLimit": 50000,
307
- "mediaMaxMb": 20
307
+ "mediaMaxMb": 20,
308
+ "accounts": []
308
309
  },
309
310
  "hybridai": {
310
311
  "baseUrl": "https://hybridai.one",
311
312
  "defaultModel": "gpt-4.1-mini",
313
+ "onboardingModel": "",
312
314
  "defaultChatbotId": "",
313
315
  "maxTokens": 4096,
314
316
  "enableRag": true,
@@ -513,6 +515,12 @@
513
515
  "command": "npx",
514
516
  "args": ["-y", "@playwright/mcp@latest"],
515
517
  "enabled": false
518
+ },
519
+ "linear": {
520
+ "transport": "http",
521
+ "url": "https://mcp.linear.app/mcp",
522
+ "auth": "oauth",
523
+ "enabled": false
516
524
  }
517
525
  },
518
526
  "web": {
@@ -581,7 +589,9 @@
581
589
  "gatewayBaseUrl": "http://127.0.0.1:9090",
582
590
  "gatewayApiToken": "",
583
591
  "dbPath": "~/.hybridclaw/data/hybridclaw.db",
584
- "logLevel": "info"
592
+ "logLevel": "info",
593
+ "logRequests": false,
594
+ "debugModelResponses": false
585
595
  },
586
596
  "observability": {
587
597
  "enabled": true,
@@ -0,0 +1,4 @@
1
+ import{n as e}from"./rolldown-runtime-Bh1tDfsg.js";import{C as t,a as n,n as r,o as i,r as a}from"./query-o_Dd9s85.js";import{d as o,l as s}from"./router-DoNPHesn.js";import{$ as c,A as l,B as u,C as d,E as f,F as p,G as m,H as h,I as g,J as _,K as v,L as y,M as b,N as x,O as S,P as C,Q as w,R as T,S as E,T as ee,U as te,V as ne,W as re,X as D,Y as ie,Z as O,_ as k,a as A,at as ae,b as j,c as oe,ct as se,d as M,dt as N,et as ce,f as le,g as P,h as ue,ht as de,i as fe,it as pe,j as me,k as he,l as F,lt as ge,mt as _e,n as ve,nt as ye,o as be,ot as I,p as L,q as xe,r as R,s as Se,st as Ce,t as we,tt as Te,u as Ee,ut as z,v as De,w as B,x as Oe,y as V,z as H}from"./index-DN3T1L-r.js";var U=e(t(),1);function ke(e,t,n=`web`,r=10,i,a){let o=new URLSearchParams({userId:t,channelId:n,limit:String(r)});return i&&o.set(`q`,i),a&&o.set(`scope`,a),N(`/api/chat/recent?${o.toString()}`,{token:e})}function Ae(e,t,n=80,r){let i=new URLSearchParams({sessionId:t,limit:String(n)});return r&&i.set(`userId`,r),N(`/api/history?${i.toString()}`,{token:e})}function je(e,t){return N(`/api/chat/context?${new URLSearchParams({sessionId:t}).toString()}`,{token:e})}function Me(e,t){return N(t?`/api/chat/commands?q=${encodeURIComponent(t)}`:`/api/chat/commands`,{token:e})}function Ne(e,t){return N(`/api/chat/mobile-qr`,{token:e,method:`POST`,body:t})}function Pe(e,t,n){return N(`/api/chat/branch`,{token:e,method:`POST`,body:{sessionId:t,beforeMessageId:n}})}function Fe(e,t){return N(`/api/chat/rating`,{token:e,method:`POST`,body:t})}function Ie(e,t,n,r){return N(`/api/command`,{token:e,method:`POST`,body:pe({sessionId:t,args:r,userId:n,username:`web`})})}function Le(e,t){return N(`/api/media/upload`,{token:e,method:`POST`,rawBody:t,extraHeaders:{"Content-Type":t.type||`application/octet-stream`,"X-Hybridclaw-Filename":encodeURIComponent(t.name||`upload`)}})}function Re(e){return`/api/artifact?${new URLSearchParams({path:e}).toString()}`}function ze(e){return e}async function Be(e,t){let n=await fetch(t,{headers:z(e),cache:`no-store`});if(!n.ok){let e=(n.headers.get(`content-type`)||``).toLowerCase().trim(),t=`${n.status} ${n.statusText}`;if(e.includes(`application/json`)){let e=await n.json().catch(()=>null);t=e?.error||e?.text||t}else{let e=(await n.text().catch(()=>``)).trim();e&&(t=e)}throw n.status===401&&I(t),Error(t)}return n.blob()}async function W(e,t){return Be(e,Re(t))}function Ve(e,t){return Be(e,ze(t))}var He={maxRecentSessions:10,maxSearchResults:50};function Ue(e,t){let[n,r]=(0,U.useState)(e);return(0,U.useEffect)(()=>{let n=window.setTimeout(()=>{r(e)},t);return()=>{window.clearTimeout(n)}},[e,t]),n}var We=String.raw`(?=$|[\s:.,!?;)\]}])`;RegExp(`^@([A-Za-z0-9._-]+)${We}`,`u`);var Ge=RegExp(`@([A-Za-z0-9._-]+)${We}`,`gu`);function Ke(e){let t=[];for(let n of e.matchAll(Ge)){let r=n[0],i=n[1]??``,a=n.index??0;if(!i)continue;let o=a===0?``:e[a-1];o&&!/[\s([{]/u.test(o)||t.push({mention:r,agentId:i,index:a})}return t}var qe=new Map;function G(e){return String(e??``).trim().toLowerCase()}function K(e,t){let n=e.sessionId??t,r=new Map((e.branchFamilies??[]).map(e=>[`${e.anchorSessionId}:${e.anchorMessageId}`,e.variants])),i=new Map;for(let[e,t]of r.entries()){let r=t.find(e=>e.sessionId===n);r&&i.set(r.messageId,e)}let a=e.history??[],o=G(e.agentId),s=null;return{messages:a.map((e,t)=>{let r=a.slice(t+1).find(e=>e.role!==`system`),c=G(r?.agent_id??r?.assistantPresentation?.agentId),l=e.role===`user`&&r?.role===`assistant`&&c&&c!==o?r?.assistantPresentation??null:null;e.role===`user`&&(s=e.content);let u=e.role===`user`?e.content:e.role===`assistant`?s:null;return{id:j(),role:e.role,content:e.content,rawContent:e.content,sessionId:n,messageId:e.id??null,media:[],artifacts:e.artifacts??[],replayRequest:u===null?null:{content:u,media:[]},assistantPresentation:e.assistantPresentation??null,addressedAgentPresentation:l,responseRating:e.response_rating??null,branchKey:e.id!==void 0&&e.id!==null?i.get(e.id)??null:null}}),branchFamilies:r,resolvedSessionId:n,agentId:e.agentId?.trim()||null,bootstrapAutostart:e.bootstrapAutostart??null}}function q(e,t){return[`chat-history`,e,t]}async function Je(e,t,n){return K(await Ae(e,t,80,n),t)}var J=i();function Ye(e){let t=ye(),n=T(),r=e.searchQuery.trim().length>0;return(0,U.useEffect)(()=>{n.openMobile&&e.onRefreshRecent?.()},[e.onRefreshRecent,n.openMobile]),(0,J.jsxs)(b,{side:`left`,collapsible:`icon`,children:[(0,J.jsxs)(p,{children:[(0,J.jsxs)(`div`,{className:H.headerRow,children:[(0,J.jsx)(he,{}),(0,J.jsx)(y,{className:H.sidebarToggle})]}),(0,J.jsxs)(`button`,{type:`button`,className:R.newChatButton,onClick:e.onNewChat,children:[(0,J.jsx)(`span`,{"aria-hidden":`true`,children:`+`}),(0,J.jsx)(`span`,{children:`New Conversation`})]}),(0,J.jsx)(`div`,{className:R.sidebarSearchWrap,children:(0,J.jsx)(`input`,{type:`search`,className:R.sidebarSearch,value:e.searchQuery,onChange:t=>e.onSearchQueryChange(t.target.value),placeholder:`Search`,"aria-label":`Search conversations`})})]}),(0,J.jsx)(x,{children:(0,J.jsx)(Xe,{...e,isSearching:r})}),(0,J.jsx)(C,{children:(0,J.jsxs)(`div`,{className:H.footerBlock,children:[(0,J.jsx)(l,{version:t.gatewayStatus?.version}),(0,J.jsx)(u,{labelClassName:H.themeToggleLabel})]})})]})}function Xe(e){return(0,J.jsxs)(`div`,{className:R.chatSidebarContent,children:[(0,J.jsxs)(`div`,{className:R.sidebarListHeader,children:[(0,J.jsx)(`div`,{className:R.sidebarLabel,children:e.isSearching?`Search Results`:`Recent Chats`}),(0,J.jsx)(`div`,{className:R.sidebarScopeToggle,children:[`user`,`all`].map(t=>(0,J.jsx)(`button`,{type:`button`,className:O(R.sidebarScopeButton,e.recentScope===t&&R.sidebarScopeButtonActive),"aria-pressed":e.recentScope===t,onClick:()=>e.onRecentScopeChange(t),children:t===`user`?`User`:`All`},t))})]}),e.isLoading&&e.isSearching?(0,J.jsx)(`div`,{className:R.sidebarStatus,children:`Searching...`}):e.sessions.length===0?(0,J.jsx)(`div`,{className:R.sidebarStatus,children:e.isSearching?`No matching conversations.`:`No recent chats yet.`}):(0,J.jsx)(`ul`,{className:R.sessionList,"aria-live":`polite`,children:e.sessions.map(t=>(0,J.jsx)(`li`,{children:(0,J.jsxs)(`div`,{className:R.sessionItemRow,children:[(0,J.jsxs)(`button`,{type:`button`,className:O(R.sessionItem,t.sessionId===e.activeSessionId&&R.sessionItemActive,t.sessionId===e.activeSessionId&&e.isPending&&R.sessionItemPending),"aria-current":t.sessionId===e.activeSessionId?`page`:void 0,onMouseEnter:()=>e.onHoverSession?.(t.sessionId),onClick:()=>e.onOpenSession(t.sessionId),children:[(0,J.jsx)(`span`,{className:R.sessionTitle,children:t.title||`Untitled`}),t.searchSnippet?(0,J.jsx)(`span`,{className:R.sessionSnippet,children:t.searchSnippet}):null,(0,J.jsx)(`span`,{className:R.sessionTime,children:B(t.lastActive)})]}),(0,J.jsx)(`button`,{type:`button`,className:R.sessionDeleteButton,"aria-label":`Delete ${t.title||`Untitled`} session`,title:`Delete session`,disabled:e.deleteDisabled,onClick:()=>e.onRequestDeleteSession(t),children:(0,J.jsx)(w,{className:R.sessionDeleteIcon})})]})},t.sessionId))})]})}var Y=new Map;function Ze(e,t){return`${e}\u0000${t}`}function Qe(e,t){let n=Ze(e,t),r=Y.get(n);return r||(r={objectUrl:null,loading:!1,promise:null,listeners:new Set},Y.set(n,r)),r}function X(e){for(let t of e.listeners)t()}function $e(e,t){let n=t?.trim(),r=e.trim();if(!n)return null;let i=Qe(r,n);return i.objectUrl?Promise.resolve(i.objectUrl):i.promise?i.promise:(i.loading=!0,i.promise=Ve(r,n).then(e=>{let t=URL.createObjectURL(e);return i.objectUrl=t,i.loading=!1,i.promise=null,X(i),t}).catch(()=>(i.objectUrl=null,i.loading=!1,i.promise=null,X(i),null)),X(i),i.promise)}function et(e){let t=e.token.trim(),n=e.imageUrl?.trim()??``,[r,i]=(0,U.useState)(()=>{if(!n)return{objectUrl:null,loading:!1};let e=Qe(t,n);return{objectUrl:e.objectUrl,loading:e.loading}});return(0,U.useEffect)(()=>{if(!n){i({objectUrl:null,loading:!1});return}let e=Qe(t,n),r=()=>{i({objectUrl:e.objectUrl,loading:e.loading})};return e.listeners.add(r),r(),$e(t,n),()=>{e.listeners.delete(r)}},[t,n]),r}function Z(){return(0,J.jsx)(`svg`,{"aria-hidden":`true`,focusable:`false`,viewBox:`0 0 24 24`,width:`14`,height:`14`,fill:`none`,stroke:`currentColor`,strokeWidth:`2`,strokeLinecap:`round`,strokeLinejoin:`round`,children:(0,J.jsx)(`path`,{d:`m6 9 6 6 6-6`})})}function tt(e){if(e.agents.length===0)return null;let t=e.agents.find(t=>t.id===e.selectedAgentId),n=t?.name?.trim()||t?.id||`Agent`;return(0,J.jsxs)(fe,{value:e.selectedAgentId,disabled:e.disabled,onValueChange:t=>{!t||t===e.selectedAgentId||e.onSwitch(t)},children:[(0,J.jsxs)(oe,{className:R.composerPill,"aria-label":`Switch agent`,disabled:e.disabled,children:[(0,J.jsx)(F,{children:n}),(0,J.jsx)(be,{className:R.composerPillChevron,children:(0,J.jsx)(Z,{})})]}),(0,J.jsx)(A,{className:R.agentSelectPopup,children:e.agents.map(t=>(0,J.jsxs)(Se,{value:t.id,textValue:t.name?.trim()||t.id,className:R.agentSelectItem,children:[(0,J.jsx)(nt,{agent:t,token:e.token}),(0,J.jsx)(`span`,{className:R.agentSelectItemText,children:t.name?.trim()||t.id})]},t.id))})]})}function nt(e){let t=e.agent.imageUrl?.trim(),n=et({token:e.token??``,imageUrl:t});return n.objectUrl?(0,J.jsx)(`img`,{className:R.agentSelectAvatar,src:n.objectUrl,alt:``}):t?(0,J.jsx)(`span`,{className:R.agentSelectAvatarLoading,"aria-hidden":`true`}):null}function rt(e,t){let n=e.lastIndexOf(`
2
+ `,t-1)+1,r=-1;for(let i=n;i<t;i++)e[i]===`/`&&(i===n||/\s/.test(e[i-1]))&&(r=i);return r===-1?null:{query:e.slice(r+1,t),tokenStart:r}}function it(e,t){return`${e}-opt-${t}`}function at({mode:e,kind:t=`slash`,suggestions:n,activeIdx:r,query:i,listboxId:a,token:o,onSelect:s,onActiveChange:c}){(0,U.useEffect)(()=>{e!==`list`||n.length===0||document.getElementById(it(a,r))?.scrollIntoView({block:`nearest`})},[r,e,n.length,a]);let l=i.trim().toLowerCase(),u=t===`agent`?`@`:`/`,d=t===`agent`?`Agents`:`Slash commands`,f=t===`agent`?`No agents match ${u}${i}`:`No commands match ${u}${i}`;return(0,J.jsx)(te,{side:`top`,focusOnOpen:`none`,closeOnEscape:!1,closeOnOutsideClick:!0,sideOffset:4,className:R.slashSuggestions,children:(0,J.jsxs)(Ee,{className:R.slashSuggestionsScroll,children:[(0,J.jsx)(L,{id:a,role:`listbox`,"aria-label":d,className:R.slashSuggestionsList,children:e===`list`?n.map((e,n)=>(0,J.jsxs)(`div`,{id:it(a,n),className:O(R.suggestionItem,t===`agent`&&R.suggestionItemAgent,n===r&&R.suggestionItemActive,(e.depth??1)>=2&&R.suggestionItemSub),role:`option`,tabIndex:-1,"aria-selected":n===r,onMouseDown:t=>{t.preventDefault(),s(e)},onMouseEnter:()=>c(n),title:e.description||void 0,children:[t===`agent`?(0,J.jsx)(ot,{item:e,token:o}):null,(0,J.jsxs)(`span`,{className:R.suggestionText,children:[(0,J.jsx)(`span`,{className:R.suggestionLabel,children:ct(e.label,l)}),e.description?(0,J.jsx)(`span`,{className:R.suggestionDesc,children:e.description}):null]})]},e.id)):(0,J.jsx)(`div`,{className:R.suggestionEmpty,role:`status`,children:f})}),(0,J.jsx)(M,{children:(0,J.jsx)(le,{})})]})})}function ot(e){let t=e.item.imageUrl?.trim(),n=et({token:e.token??``,imageUrl:t});return n.objectUrl?(0,J.jsx)(`img`,{className:R.suggestionAvatar,src:n.objectUrl,alt:``}):t?(0,J.jsx)(`span`,{className:R.suggestionAvatarLoading,"aria-hidden":`true`}):null}var st=/<[^>]+>|\[[^\]]+\]/g;function ct(e,t){let n=[],r=0,i=0,a=(e,r)=>{if(!e)return;let a=r?R.suggestionLabelMono:void 0,o=t?e.toLowerCase().indexOf(t):-1;n.push(o===-1?(0,J.jsx)(`span`,{className:a,children:e},i++):(0,J.jsxs)(`span`,{className:a,children:[e.slice(0,o),(0,J.jsx)(`mark`,{className:R.suggestionMatch,children:e.slice(o,o+t.length)}),e.slice(o+t.length)]},i++))};for(let t of e.matchAll(st)){let n=t.index??0;a(e.slice(r,n),!1),a(t[0],!0),r=n+t[0].length}return a(e.slice(r),!1),n}var lt=/@([A-Za-z0-9._-]+)(?=$|[\s:])/gu;function ut(e,t){let n=e.slice(0,t).lastIndexOf(`@`);if(n===-1)return null;let r=n===0?``:e[n-1];if(r&&!/[\s([{]/u.test(r))return null;let i=e.slice(n+1,t);return/^[A-Za-z0-9._-]*$/u.test(i)?{tokenStart:n,query:i}:null}function dt(e){let t=(0,U.useRef)(null),n=(0,U.useRef)(null),r=(0,U.useRef)(null),[i,a]=(0,U.useState)([]),[o,s]=(0,U.useState)(0),[c,l]=(0,U.useState)([]),[u,d]=(0,U.useState)(`slash`),[f,p]=(0,U.useState)(0),[m,g]=(0,U.useState)(`closed`),[_,v]=(0,U.useState)(``),[y,b]=(0,U.useState)(``),x=(0,U.useRef)(null),S=(0,U.useRef)(null),C=(0,U.useRef)(0),w=(0,U.useRef)(null),T=(0,U.useId)(),E=m!==`closed`,te=m===`closed`?``:u===`agent`?m===`list`?`${ee(c.length,`agent`)} available`:`No agents match @${_}`:m===`list`?`${ee(c.length,`command`)} available`:`No commands match /${_}`;(0,U.useEffect)(()=>()=>{S.current&&clearTimeout(S.current),C.current+=1},[]),(0,U.useEffect)(()=>{let e=r.current;if(!e)return;let t=()=>{let t=e.getBoundingClientRect().height;!Number.isFinite(t)||t<=0||document.documentElement.style.setProperty(`--chat-composer-height`,`${Math.ceil(t)}px`)};t();let n=typeof ResizeObserver>`u`?null:new ResizeObserver(t);return n?.observe(e),window.addEventListener(`resize`,t),()=>{n?.disconnect(),window.removeEventListener(`resize`,t),document.documentElement.style.removeProperty(`--chat-composer-height`)}},[]);let re=(0,U.useRef)(e.isStreaming);(0,U.useEffect)(()=>{re.current&&!e.isStreaming&&t.current?.focus(),re.current=e.isStreaming},[e.isStreaming]);let D=(0,U.useCallback)(()=>{let e=t.current;e&&(e.style.height=`36px`,e.style.height=`${Math.max(36,Math.min(e.scrollHeight,180))}px`)},[]);(0,U.useEffect)(()=>{let n=e.initialValue?.trim()||``;if(x.current===n||(x.current=n,!n))return;let r=t.current;r&&(r.value=n,r.setSelectionRange(n.length,n.length),b(n),g(`closed`),C.current+=1,D(),r.focus())},[e.initialValue,D]);let ie=()=>{S.current&&=(clearTimeout(S.current),null),C.current+=1},k=()=>{ie(),g(`closed`)},A=(0,U.useCallback)(async t=>{let n=C.current;try{let r=await Me(e.token,t||void 0);if(n!==C.current)return;let i=r.commands??[];l(i),p(0),v(t),i.length>0?g(`list`):g(t===``?`closed`:`empty`)}catch{if(n!==C.current)return;l([]),g(`closed`)}},[e.token]),ae=(0,U.useCallback)(t=>{let n=t.trim().toLowerCase();return(e.agents??[]).filter(e=>n?e.id.toLowerCase().includes(n)||(e.name??``).toLowerCase().includes(n):!0).map(e=>{let t=e.name?.trim();return{id:`agent:${e.id}`,label:`@${e.id}`,insertText:`@${e.id}`,description:t&&t!==e.id?t:``,imageUrl:e.imageUrl??null}})},[e.agents]);(0,U.useEffect)(()=>{for(let t of e.agents??[])$e(e.token,t.imageUrl)},[e.agents,e.token]);let j=()=>{D();let n=t.current;if(!n)return;b(n.value);let r=n.selectionStart??n.value.length,i=rt(n.value,r);if(i){let e=i.query.trim();d(`slash`),ie(),S.current=setTimeout(()=>{A(e)},150);return}let a=ut(n.value,r);if(a&&(e.agents?.length??0)>0){ie();let e=ae(a.query);l(e),d(`agent`),p(0),v(a.query),g(e.length>0?`list`:a.query===``?`closed`:`empty`)}else k()},oe=e=>{let n=t.current;if(!n)return;let r=n.value,i=n.selectionStart??r.length,a=e.insertText.replace(/\s+$/,``);if(u===`agent`){let e=ut(r,i);if(e){let t=r.slice(0,e.tokenStart),o=r.slice(i),s=o.startsWith(` `)?a:`${a} `;n.value=t+s+o;let c=t.length+s.length;n.setSelectionRange(c,c)}else n.value=`${a} `,n.setSelectionRange(n.value.length,n.value.length);b(n.value),k(),D(),n.focus();return}let o=rt(r,i);if(o){let e=r.slice(0,o.tokenStart),t=r.slice(i),s=t.startsWith(` `)?a:`${a} `;n.value=e+s+t;let c=e.length+s.length;n.setSelectionRange(c,c)}else n.value=`${a} `,n.setSelectionRange(n.value.length,n.value.length);b(n.value),k(),D(),n.focus()},se=()=>{if(e.isStreaming){e.onStop();return}let n=(t.current?.value??``).trim();!n&&i.length===0||o>0||(e.onSend(n,i),t.current&&(t.current.value=``),b(``),a([]),k(),D())},M=()=>{let e=t.current,n=w.current;!e||!n||(n.scrollTop=e.scrollTop,n.scrollLeft=e.scrollLeft)},N=e=>{if(!(e.nativeEvent.isComposing||e.nativeEvent.keyCode===229)){if(m===`list`&&c.length>0){if(e.key===`ArrowDown`){e.preventDefault(),p(e=>(e+1)%c.length);return}if(e.key===`ArrowUp`){e.preventDefault(),p(e=>(e-1+c.length)%c.length);return}if(e.key===`Home`){e.preventDefault(),p(0);return}if(e.key===`End`){e.preventDefault(),p(c.length-1);return}if(e.key===`Tab`){e.preventDefault(),oe(c[f]);return}}if(e.key===`Escape`){let t=E;if(k(),t){e.preventDefault();return}}e.key===`Enter`&&!e.shiftKey&&(e.preventDefault(),se())}},ce=e=>{let t=De(e.clipboardData);t.length>0&&(e.preventDefault(),le(t))},le=async t=>{s(e=>e+t.length);try{let n=await e.onUploadFiles(t);n.length>0&&a(e=>[...e,...n])}finally{s(e=>Math.max(0,e-t.length))}},P=e=>{let t=Array.from(e.target.files??[]);t.length>0&&le(t),e.target.value=``},ue=e=>{a(t=>t.filter((t,n)=>n!==e))},de=e.agents??[],fe=(0,U.useMemo)(()=>new Map(de.map(e=>[e.id,e])),[de]),pe=e.selectedAgentId??``,me=e.models??[],he=e.selectedModelId??``;return(0,J.jsxs)(`div`,{className:R.composerWrapper,ref:r,children:[(0,J.jsxs)(ne,{open:E,onOpenChange:e=>{e||k()},children:[(0,J.jsxs)(`div`,{className:R.composer,children:[i.length>0||o>0?(0,J.jsxs)(`div`,{className:R.pendingMediaRow,children:[i.map((e,t)=>(0,J.jsxs)(`span`,{className:R.mediaChip,children:[(0,J.jsx)(`span`,{className:R.mediaChipName,children:e.filename}),(0,J.jsx)(`button`,{type:`button`,className:R.mediaChipRemove,onClick:()=>ue(t),children:`×`})]},e.path)),o>0?(0,J.jsx)(`span`,{className:R.mediaChip,children:`Uploading…`}):null]}):null,(0,J.jsxs)(h,{className:R.composerInputWrap,children:[y?(0,J.jsx)(`div`,{ref:w,className:R.composerInputOverlay,"aria-hidden":`true`,children:(0,J.jsx)(ft,{value:y,agents:fe,token:e.token})}):null,(0,J.jsx)(`textarea`,{ref:t,className:O(R.composerInput,y&&R.composerInputHasOverlay),rows:1,placeholder:`Message HybridClaw`,disabled:e.isStreaming,onInput:j,onKeyDown:N,onPaste:ce,onScroll:M,"aria-label":`Message input`,role:`combobox`,"aria-autocomplete":`list`,"aria-haspopup":`listbox`,"aria-controls":T,"aria-expanded":E,"aria-activedescendant":m===`list`&&c.length>0?it(T,f):void 0})]}),(0,J.jsxs)(`div`,{className:R.composerActions,children:[(0,J.jsxs)(`div`,{className:R.composerLeftActions,children:[(0,J.jsx)(`button`,{type:`button`,className:R.attachButton,onClick:()=>n.current?.click(),"aria-label":`Attach files`,children:`+`}),(0,J.jsx)(tt,{agents:de,selectedAgentId:pe,token:e.token,disabled:e.isStreaming,onSwitch:t=>e.onAgentSwitch?.(t)}),(0,J.jsx)(ve,{models:me,selectedModelId:he,disabled:e.isStreaming,onSwitch:t=>e.onModelSwitch?.(t)})]}),(0,J.jsx)(`button`,{type:`button`,className:O(R.sendButton,e.isStreaming&&R.stopping),onClick:se,"aria-label":e.isStreaming?`Stop`:`Send message`,children:e.isStreaming?(0,J.jsx)(`svg`,{viewBox:`0 0 24 24`,width:`16`,height:`16`,fill:`currentColor`,"aria-hidden":`true`,children:(0,J.jsx)(`rect`,{x:`6`,y:`6`,width:`12`,height:`12`,rx:`2`})}):(0,J.jsxs)(`svg`,{viewBox:`0 0 24 24`,width:`16`,height:`16`,fill:`none`,stroke:`currentColor`,strokeWidth:`2.4`,strokeLinecap:`round`,strokeLinejoin:`round`,"aria-hidden":`true`,children:[(0,J.jsx)(`path`,{d:`M12 19V5`}),(0,J.jsx)(`path`,{d:`m5 12 7-7 7 7`})]})}),(0,J.jsx)(`input`,{ref:n,type:`file`,hidden:!0,multiple:!0,onChange:P})]})]}),m===`closed`?null:(0,J.jsx)(at,{mode:m,kind:u,suggestions:c,activeIdx:f,query:_,listboxId:T,token:e.token,onSelect:oe,onActiveChange:p})]}),(0,J.jsx)(`div`,{className:R.slashLiveRegion,"aria-live":`polite`,"aria-atomic":`true`,children:te})]})}function ft(e){let t=[],n=0,r=0;for(let i of e.value.matchAll(lt)){let a=i[0],o=i[1]??``,s=i.index??0,c=e.agents.get(o);c&&(s>n&&t.push(e.value.slice(n,s)),t.push((0,J.jsx)(pt,{mention:a,imageUrl:c.imageUrl??null,token:e.token},`mention-${r++}`)),n=s+a.length)}return n<e.value.length&&t.push(e.value.slice(n)),t.length>0?t:e.value}function pt(e){let t=et({token:e.token,imageUrl:e.imageUrl});return(0,J.jsxs)(`span`,{className:R.composerMentionPill,children:[t.objectUrl?(0,J.jsx)(`img`,{className:R.composerMentionAvatar,src:t.objectUrl,alt:``}):null,(0,J.jsx)(`span`,{children:e.mention})]})}var Q={wrap:`_wrap_jrif0_1`,trigger:`_trigger_jrif0_11`,ring:`_ring_jrif0_33`,ringTrack:`_ringTrack_jrif0_37`,ringFill:`_ringFill_jrif0_43`,ringFillNominal:`_ringFillNominal_jrif0_52`,ringFillWarn:`_ringFillWarn_jrif0_56`,ringFillDanger:`_ringFillDanger_jrif0_60`,ringLabel:`_ringLabel_jrif0_64`,ringLabelUnknown:`_ringLabelUnknown_jrif0_77`,popover:`_popover_jrif0_81`,popoverTitle:`_popoverTitle_jrif0_112`,popoverTitleValue:`_popoverTitleValue_jrif0_121`,popoverRow:`_popoverRow_jrif0_126`,popoverRowValue:`_popoverRowValue_jrif0_133`,popoverProgress:`_popoverProgress_jrif0_138`,popoverProgressFill:`_popoverProgressFill_jrif0_148`,popoverProgressFillWarn:`_popoverProgressFillWarn_jrif0_157`,popoverProgressFillDanger:`_popoverProgressFillDanger_jrif0_161`,popoverFoot:`_popoverFoot_jrif0_165`},mt=14,ht=2*Math.PI*mt;function $(e){if(e==null)return`n/a`;let t=Math.abs(e);return t>=1e6?`${(t>=1e7?(e/1e6).toFixed(0):(e/1e6).toFixed(1)).replace(/\.0$/,``)}M`:t>=1e3?`${(t>=1e4?(e/1e3).toFixed(0):(e/1e3).toFixed(1)).replace(/\.0$/,``)}k`:String(Math.round(e))}function gt(e){return e==null||!Number.isFinite(e)?0:Math.max(0,Math.min(100,e))}function _t(e){return e==null?`nominal`:e>=90?`danger`:e>=70?`warn`:`nominal`}function vt(e){let t=e.sessionId,n=e.enabled&&!!t,r=a({queryKey:[`chat-context`,e.token,t],queryFn:()=>je(e.token,t),enabled:n,staleTime:15e3,refetchOnWindowFocus:!1}).data?.snapshot??null,i=r?.contextUsagePercent??null,o=gt(i),s=_t(i),c=r?.contextBudgetTokens!=null&&r.contextUsedTokens!=null,l=c?ht*(1-o/100):ht,u=i!=null&&Number.isFinite(i)?Math.max(0,Math.round(i)):null,d=u==null?`–`:`${u}%`,f=r&&c&&u!=null?`Context usage ${u} percent (${$(r.contextUsedTokens)} of ${$(r.contextBudgetTokens)} tokens)`:`Context usage unavailable`;return(0,J.jsxs)(`div`,{className:Q.wrap,children:[(0,J.jsxs)(`button`,{type:`button`,className:Q.trigger,"aria-label":f,children:[(0,J.jsxs)(`svg`,{width:34,height:34,viewBox:`0 0 34 34`,className:Q.ring,"aria-hidden":`true`,children:[(0,J.jsx)(`circle`,{cx:17,cy:17,r:mt,className:Q.ringTrack}),(0,J.jsx)(`circle`,{cx:17,cy:17,r:mt,className:O(Q.ringFill,s===`warn`&&Q.ringFillWarn,s===`danger`&&Q.ringFillDanger,s===`nominal`&&Q.ringFillNominal),strokeDasharray:ht,strokeDashoffset:l})]}),(0,J.jsx)(`span`,{className:O(Q.ringLabel,u==null&&Q.ringLabelUnknown),children:d})]}),(0,J.jsxs)(`div`,{role:`tooltip`,className:Q.popover,children:[(0,J.jsxs)(`div`,{className:Q.popoverTitle,children:[(0,J.jsx)(`span`,{children:`Context`}),(0,J.jsx)(`span`,{className:Q.popoverTitleValue,children:r?.model||`unknown model`})]}),r&&c?(0,J.jsxs)(J.Fragment,{children:[(0,J.jsx)(`div`,{className:Q.popoverProgress,children:(0,J.jsx)(`div`,{className:O(Q.popoverProgressFill,s===`warn`&&Q.popoverProgressFillWarn,s===`danger`&&Q.popoverProgressFillDanger),style:{width:`${o}%`}})}),(0,J.jsxs)(`div`,{className:Q.popoverRow,children:[(0,J.jsx)(`span`,{children:`Used`}),(0,J.jsxs)(`span`,{className:Q.popoverRowValue,children:[$(r.contextUsedTokens),` /`,` `,$(r.contextBudgetTokens),` tokens`]})]}),(0,J.jsxs)(`div`,{className:Q.popoverRow,children:[(0,J.jsx)(`span`,{children:`Headroom`}),(0,J.jsxs)(`span`,{className:Q.popoverRowValue,children:[$(r.contextRemainingTokens),` tokens`]})]})]}):(0,J.jsxs)(`div`,{className:Q.popoverRow,children:[(0,J.jsx)(`span`,{children:`Used`}),(0,J.jsx)(`span`,{className:Q.popoverRowValue,children:r?.contextUsedTokens==null?`no usage recorded yet`:`${$(r.contextUsedTokens)} tokens`})]}),(0,J.jsxs)(`div`,{className:Q.popoverRow,children:[(0,J.jsx)(`span`,{children:`Compactions`}),(0,J.jsx)(`span`,{className:Q.popoverRowValue,children:r?`${r.compactionCount} · ${$(r.compactionMessageThreshold)} msgs / ${$(r.compactionTokenBudget)} tokens`:`n/a`})]}),(0,J.jsxs)(`div`,{className:Q.popoverFoot,children:[`Run `,(0,J.jsx)(`code`,{children:`/context`}),` for full details · `,(0,J.jsx)(`code`,{children:`/compact`}),` to archive older history.`]})]})]})}var yt=[{label:`Trust session`,action:`session`,isAvailable:e=>e.allowSession===!0},{label:`Trust agent`,action:`agent`,isAvailable:e=>e.allowAgent===!0},{label:`Always allow`,action:`all`,isAvailable:e=>e.allowAll===!0}],bt=/^([^:\n]{2,44}):\s+(.+)$/,xt=/^(GET|POST|PUT|PATCH|DELETE|HEAD|OPTIONS)\s+/i;function St(e){return e===`yellow`?`Amber`:e===`red`?`Red`:null}function Ct(e){return/^reply\b/i.test(e)||/^approval expires\b/i.test(e)||/^approval id\b/i.test(e)}function wt(e){let t=e.trim();return/^proposed action$/i.test(t)?`Request`:/^why$/i.test(t)?`Reason`:t}function Tt(e){let t=[],n,r=e.split(/\r?\n/).map(e=>e.trim()).filter(Boolean);for(let e of r){if(Ct(e)||/^classifier reasoning$/i.test(e)||/^if you skip this/i.test(e))continue;let r=e.match(bt);if(r){let e=wt(r[1]??``);/^classifier reasoning$/i.test(e)||t.push({label:e,value:r[2]??``});continue}n??=e}return{introLine:n,rows:t}}function Et(e){let t=[],n=new Set,r=(e,r)=>{let i=e.trim(),a=String(r??``).trim();if(!i||!a)return;let o=`${i.toLowerCase()}:${a}`;n.has(o)||(n.add(o),t.push({label:i,value:a}))};e.intent&&r(`Action`,e.intent),e.commandPreview&&r(xt.test(e.commandPreview)?`Request`:`Preview`,e.commandPreview),e.toolName&&r(`Tool`,e.toolName);for(let t of Tt(e.prompt).rows)r(t.label,t.value);if(r(`Approval ID`,e.approvalId),e.expiresAt&&Number.isFinite(e.expiresAt)){let t=new Date(e.expiresAt);Number.isNaN(t.getTime())||r(`Expires`,t.toLocaleTimeString())}return t}function Dt(e){let{introLine:t}=Tt(e.prompt);return t||(e.summary?e.summary.split(/\r?\n/)[0]??``:e.intent?`Confirmation required for ${e.intent}.`:`Confirmation required before this action can continue.`)}function Ot(e){let{approval:t}=e,n=(0,U.useMemo)(()=>Et(t),[t]),r=(0,U.useMemo)(()=>Dt(t),[t]),i=yt.filter(e=>e.isAvailable(t)),a=St(t.approvalTier),o=n=>{e.onAction(n,t.approvalId)};return(0,J.jsxs)(`div`,{className:R.approvalCard,children:[(0,J.jsxs)(`div`,{className:R.approvalHeader,children:[a?(0,J.jsx)(`span`,{className:R.approvalTier,children:a}):null,(0,J.jsx)(`span`,{className:R.approvalTitle,children:`Confirmation required`})]}),(0,J.jsx)(`p`,{className:R.approvalIntro,children:r}),n.length>0?(0,J.jsx)(`dl`,{className:R.approvalDetails,children:n.map(e=>(0,J.jsxs)(`div`,{className:R.approvalDetailRow,children:[(0,J.jsx)(`dt`,{children:e.label}),(0,J.jsx)(`dd`,{children:e.value})]},`${e.label}:${e.value}`))}):null,(0,J.jsxs)(`div`,{className:R.approvalPrimaryActions,children:[(0,J.jsx)(d,{size:`sm`,disabled:e.busy,onClick:()=>o(`once`),children:`Allow once`}),(0,J.jsx)(d,{variant:`danger`,size:`sm`,disabled:e.busy,onClick:()=>o(`deny`),children:`Cancel`})]}),i.length>0?(0,J.jsx)(`div`,{className:R.approvalTrustActions,children:i.map(t=>(0,J.jsx)(d,{variant:`outline`,size:`sm`,className:R.approvalAllow,disabled:e.busy,onClick:()=>o(t.action),children:t.label},t.action))}):null]})}var kt=120;function At(e,t,n){let[r,i]=(0,U.useState)(e),a=(0,U.useRef)(e),o=(0,U.useRef)(null);a.current=e,(0,U.useEffect)(()=>{if(!t){o.current!==null&&(window.clearTimeout(o.current),o.current=null),i(``);return}if(!n){o.current!==null&&(window.clearTimeout(o.current),o.current=null),i(e);return}o.current!==null||e===r||(o.current=window.setTimeout(()=>{o.current=null,(0,U.startTransition)(()=>{i(a.current)})},kt))},[e,t,n,r]),(0,U.useEffect)(()=>()=>{o.current!==null&&window.clearTimeout(o.current)},[]);let s=t?n?r:e:``;return(0,U.useMemo)(()=>t?we(s,{highlight:!n}):``,[t,s,n])}var jt=`<svg viewBox="0 0 24 24" width="14" height="14" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><rect x="9" y="9" width="11" height="11" rx="2"/><path d="M5 15V5a2 2 0 0 1 2-2h10"/></svg>`,Mt=`<svg viewBox="0 0 24 24" width="14" height="14" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><path d="M20 6 9 17l-5-5"/></svg>`,Nt=`<svg viewBox="0 0 24 24" width="11" height="11" fill="none" stroke="currentColor" stroke-width="2.4" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><path d="m9 7-5 5 5 5"/><path d="m15 7 5 5-5 5"/><path d="m13.5 5-3 14"/></svg>`,Pt=/^\/([A-Za-z0-9][A-Za-z0-9._-]*)(?=$|[\s:.,!?;)\]}])/u,Ft=new Set([`text`,`plaintext`,`plain`,`txt`]);function It(e){let t=e.querySelector(`code`)?.className.match(/language-([\w#.+-]+)/)?.[1]??``;return Ft.has(t)?``:t}function Lt(e){if(e.querySelector(`button[data-copy-btn]`))return;let t=It(e);if(t){e.classList.add(R.codeBlockLabeled);let n=document.createElement(`span`);n.className=R.codeLangLabel,n.setAttribute(`aria-hidden`,`true`),n.innerHTML=Nt;let r=document.createElement(`span`);r.textContent=t,n.appendChild(r),e.appendChild(n)}let n=document.createElement(`button`);n.type=`button`,n.dataset.copyBtn=``,n.className=R.codeCopyButton,n.innerHTML=jt;let r=e=>{n.setAttribute(`aria-label`,e),n.title=e};r(`Copy code`);let i=null;n.addEventListener(`click`,()=>{k((e.querySelector(`code`)??e).textContent??``).then(e=>{e&&(n.innerHTML=Mt,n.classList.add(R.codeCopyButtonDone),r(`Copied`),i!==null&&window.clearTimeout(i),i=window.setTimeout(()=>{n.innerHTML=jt,n.classList.remove(R.codeCopyButtonDone),r(`Copy code`)},1500))})}),e.appendChild(n)}function Rt(){let e=(0,U.useRef)(null);return(0,U.useCallback)(t=>{if(e.current?.disconnect(),e.current=null,!t)return;let n=()=>{for(let e of t.querySelectorAll(`pre`))Lt(e)};n();let r=new MutationObserver(n);r.observe(t,{childList:!0,subtree:!0}),e.current=r},[])}function zt(e,t){let n=t.split(`;`)[0]?.trim().toLowerCase()||``;return!n||n!==`application/pdf`&&!n.startsWith(`image/`)&&!n.startsWith(`video/`)||e.type.toLowerCase()===n?e:new Blob([e],{type:n})}function Bt(e){let{artifact:t,token:n}=e,r=(0,U.useRef)(null),[i,a]=(0,U.useState)(null),[o,s]=(0,U.useState)(!1),c=(t.mimeType??``).toLowerCase(),l=t.filename??`artifact`,u=c.startsWith(`image/`),d=c.startsWith(`video/`)||/\.(mp4|m4v|mov|webm)$/i.test(t.filename??``)||/\.(mp4|m4v|mov|webm)$/i.test(t.path??``),f=c===`application/pdf`||/\.pdf$/i.test(t.filename??``)||/\.pdf$/i.test(t.path??``),p=u||d||f;(0,U.useEffect)(()=>{let e=r.current;if(r.current=null,e&&URL.revokeObjectURL(e),a(null),!p||!t.path)return;let i=!1;return W(n,t.path).then(e=>{if(i)return;let t=URL.createObjectURL(zt(e,c));r.current=t,a(t)}).catch(()=>{i||a(null)}),()=>{i=!0;let e=r.current;r.current=null,e&&URL.revokeObjectURL(e)}},[t.path,p,c,n]);let m=o?`Downloading…`:`Download`,h=async()=>{if(!(!t.path||o)){s(!0);try{let e=i??URL.createObjectURL(await W(n,t.path)),r=document.createElement(`a`);r.href=e,r.download=t.filename??`artifact`,r.rel=`noopener noreferrer`,document.body.appendChild(r),r.click(),r.remove(),i||window.setTimeout(()=>URL.revokeObjectURL(e),0)}catch{}finally{s(!1)}}};return(0,J.jsxs)(`div`,{className:O(R.artifactCard,i&&R.artifactCardWithPreview),children:[(0,J.jsxs)(`div`,{className:R.artifactHeader,children:[(0,J.jsx)(`span`,{className:R.artifactFilename,children:l}),t.type?(0,J.jsx)(`span`,{className:R.artifactBadge,children:t.type}):null,t.path?(0,J.jsx)(`button`,{type:`button`,className:R.artifactDownload,disabled:o,onClick:()=>{h()},children:m}):null]}),u&&i?(0,J.jsx)(`div`,{className:R.artifactPreview,children:(0,J.jsx)(`img`,{src:i,alt:l})}):null,f&&i?(0,J.jsx)(`div`,{className:O(R.artifactPreview,R.artifactPdfPreview),children:(0,J.jsx)(`iframe`,{src:i,title:`${l} preview`,sandbox:``})}):null,d&&i?(0,J.jsx)(`div`,{className:O(R.artifactPreview,R.artifactVideoPreview),children:(0,J.jsx)(`video`,{controls:!0,preload:`metadata`,src:i,children:(0,J.jsxs)(`a`,{href:i,download:l,children:[`Download `,l]})})}):null]})}function Vt(e){let t=(0,U.useRef)(null),[n,r]=(0,U.useState)(null);return(0,U.useEffect)(()=>{let n=t.current;if(t.current=null,n&&URL.revokeObjectURL(n),r(null),!e.imageUrl)return;let i=!1;return Ve(e.token,e.imageUrl).then(e=>{if(i)return;let n=URL.createObjectURL(e);t.current=n,r(n)}).catch(()=>{i||r(null)}),()=>{i=!0;let e=t.current;t.current=null,e&&URL.revokeObjectURL(e)}},[e.imageUrl,e.token]),n}var Ht=(0,U.memo)(function(e){let{message:t,token:n}=e,[r,i]=(0,U.useState)(!1),a=()=>{e.onCopy(t.rawContent??t.content),i(!0),setTimeout(()=>i(!1),900)},o=(0,U.useMemo)(()=>{let e=new Map;return(t.artifacts??[]).map(t=>{let n=[t.path,t.filename,t.mimeType,t.type].filter(Boolean),r=n.length>0?n.join(`|`):`artifact`,i=e.get(r)??0;return e.set(r,i+1),{artifact:t,key:`${r}:${i}`}})},[t.artifacts]),s=t.role===`approval`,l=s&&!!t.pendingApproval,u=t.role===`assistant`||t.role===`command`||s&&!l,f=At(t.content,u,e.isStreaming),p=Rt(),m=t.assistantPresentation,h=m?.displayName??`Assistant`,g=Vt({token:n,imageUrl:m?.imageUrl});if(t.role===`thinking`)return(0,J.jsxs)(`div`,{className:R.thinking,role:`status`,"aria-label":`Assistant is thinking`,children:[(0,J.jsx)(`span`,{className:R.thinkingDot}),(0,J.jsx)(`span`,{className:R.thinkingDot}),(0,J.jsx)(`span`,{className:R.thinkingDot})]});let _=t.role===`user`,v=t.role===`assistant`,y=_||t.content.trim().length>0||o.length===0||s,b=O(R.messageBlock,_&&R.messageBlockUser,(v||t.role===`system`||t.role===`command`||s)&&R.messageBlockAssistant),x=O(R.bubble,_&&R.bubbleUser,(v||s)&&R.bubbleAssistant,s&&R.bubbleApproval,t.role===`system`&&R.bubbleSystem,t.role===`command`&&R.bubbleCommand);return(0,J.jsxs)(`div`,{className:b,children:[v?(0,J.jsxs)(`div`,{className:R.agentLabel,children:[g?(0,J.jsx)(`img`,{className:R.agentAvatar,src:g,alt:``}):(0,J.jsx)(`span`,{className:R.agentInitial,children:h.charAt(0).toUpperCase()}),(0,J.jsx)(`span`,{children:h})]}):null,y?(0,J.jsx)(`div`,{className:x,children:l&&t.pendingApproval?(0,J.jsx)(Ot,{approval:t.pendingApproval,busy:e.approvalBusy,onAction:e.onApprovalAction}):u?(0,J.jsx)(`div`,{ref:p,className:R.markdownContent,dangerouslySetInnerHTML:{__html:f}}):_?(0,J.jsx)(Ut,{content:t.content,presentation:t.addressedAgentPresentation,skillInvocationTargets:e.skillInvocationTargets,token:n}):t.content}):null,o.map(({artifact:e,key:t})=>(0,J.jsx)(Bt,{artifact:e,token:n},t)),e.isStreaming?null:(0,J.jsxs)(`div`,{className:R.messageActions,children:[v&&t.replayRequest?(0,J.jsx)(d,{variant:`ghost`,size:`icon`,className:R.actionButton,title:`Regenerate`,"aria-label":`Regenerate response`,onClick:()=>e.onRegenerate(t),children:`↻`}):null,v?(0,J.jsxs)(J.Fragment,{children:[(0,J.jsx)(d,{variant:`ghost`,size:`icon`,className:O(R.actionButton,t.responseRating===`up`&&R.actionButtonSelected),title:t.responseRating===`up`?`Clear thumbs up`:`Thumbs up`,"aria-label":t.responseRating===`up`?`Clear thumbs up rating`:`Rate response thumbs up`,"aria-pressed":t.responseRating===`up`,"data-rating-locked":t.responseRating?`true`:void 0,disabled:e.ratingBusy===!0||!t.messageId||t.responseRating===`down`,onClick:()=>e.onRate?.(t,t.responseRating===`up`?null:`up`),children:(0,J.jsx)(c,{width:`13`,height:`13`,filled:t.responseRating===`up`})}),(0,J.jsx)(d,{variant:`ghost`,size:`icon`,className:O(R.actionButton,t.responseRating===`down`&&R.actionButtonSelected),title:t.responseRating===`down`?`Clear thumbs down`:`Thumbs down`,"aria-label":t.responseRating===`down`?`Clear thumbs down rating`:`Rate response thumbs down`,"aria-pressed":t.responseRating===`down`,"data-rating-locked":t.responseRating?`true`:void 0,disabled:e.ratingBusy===!0||!t.messageId||t.responseRating===`up`,onClick:()=>e.onRate?.(t,t.responseRating===`down`?null:`down`),children:(0,J.jsx)(ce,{width:`13`,height:`13`,filled:t.responseRating===`down`})})]}):null,(0,J.jsx)(d,{variant:`ghost`,size:`icon`,className:O(R.actionButton,r&&R.actionButtonSuccess),title:`Copy`,"aria-label":r?`Copied`:`Copy message`,onClick:a,children:r?`✓`:`⧉`}),_?(0,J.jsx)(d,{variant:`ghost`,size:`icon`,className:R.actionButton,title:`Edit`,"aria-label":`Edit message`,onClick:()=>e.onEdit(t),children:`✎`}):null,e.branchInfo&&e.branchInfo.total>1?(0,J.jsxs)(`div`,{className:R.branchSwitcher,children:[(0,J.jsx)(d,{variant:`ghost`,size:`icon`,className:R.branchButton,"aria-label":`Previous branch`,disabled:e.branchInfo.current<=1,onClick:()=>e.onBranchNav(t,-1),children:`‹`}),(0,J.jsxs)(`span`,{children:[e.branchInfo.current,`/`,e.branchInfo.total]}),(0,J.jsx)(d,{variant:`ghost`,size:`icon`,className:R.branchButton,"aria-label":`Next branch`,disabled:e.branchInfo.current>=e.branchInfo.total,onClick:()=>e.onBranchNav(t,1),children:`›`})]}):null]})]})});function Ut(e){let t=Ke(e.content),n=[],r=0;for(let[i,a]of t.entries()){a.index>r&&Wt(n,e.content.slice(r,a.index),`text-${i}`,r===0,e.skillInvocationTargets);let t=e.presentation?.agentId?.toLowerCase()===a.agentId.toLowerCase()?e.presentation:null;n.push((0,J.jsx)(Gt,{mention:a.mention,imageUrl:t?.imageUrl??null,token:e.token},`${a.index}-${i}`)),r=a.index+a.mention.length}return r<e.content.length&&Wt(n,e.content.slice(r),`text-tail`,r===0,e.skillInvocationTargets),(0,J.jsx)(J.Fragment,{children:n})}function Wt(e,t,n,r,i){if(!t)return;if(!r||!i){e.push(t);return}let a=Pt.exec(t),o=a?.[1]??``,s=i.get(o.toLowerCase());if(!a||!o||!s){e.push(t);return}let c=a[0];e.push((0,J.jsx)(`a`,{className:R.userSkillCommandLink,href:`/admin/skills/${encodeURIComponent(s)}`,children:c},`${n}-skill-command`));let l=t.slice(c.length);l&&e.push(l)}function Gt(e){let t=Vt({token:e.token,imageUrl:e.imageUrl});return(0,J.jsxs)(`span`,{className:R.userAgentMentionPill,children:[t?(0,J.jsx)(`img`,{className:R.userAgentMentionAvatar,src:t,alt:``}):null,(0,J.jsx)(`span`,{children:e.mention})]})}function Kt(e){let[t,n]=(0,U.useState)(e.initial);return(0,J.jsxs)(J.Fragment,{children:[(0,J.jsx)(`textarea`,{className:R.editArea,value:t,onChange:e=>n(e.target.value),"aria-label":`Edit message`,autoFocus:!0}),(0,J.jsxs)(`div`,{className:R.editButtons,children:[(0,J.jsx)(d,{onClick:()=>e.onSave(t.trim()),disabled:!t.trim(),children:`Save`}),(0,J.jsx)(d,{variant:`ghost`,onClick:e.onCancel,children:`Cancel`})]})]})}function qt(){let e=s(),t=o({strict:!1}).sessionId,n=(0,U.useRef)(null),r=t??n.current??``,i=(0,U.useRef)(r);i.current=r,(0,U.useEffect)(()=>{t&&(n.current=null)},[t]),(0,U.useEffect)(()=>{r&&E(r)},[r]);let a=(0,U.useCallback)(()=>i.current,[]),c=(0,U.useCallback)((t,n)=>e({to:`/chat/$sessionId`,params:{sessionId:t},...n}),[e]);return{sessionId:r,getSessionId:a,navigateToSession:c,switchToSession:(0,U.useCallback)((e,t)=>(n.current=e,i.current=e,c(e,t)),[c]),startFreshChat:(0,U.useCallback)(()=>{n.current=null,e({to:`/chat`})},[e]),ensureSessionForSend:(0,U.useCallback)(()=>{if(i.current)return;let e=V();n.current=e,i.current=e,c(e,{replace:!0})},[c]),handleSessionIdCorrection:(0,U.useCallback)(e=>{e!==i.current&&c(e,{replace:!0})},[c])}}async function Jt(e,t){let n=await fetch(e,{method:`POST`,headers:{...z(t.token,t.body),Accept:`application/x-ndjson`},body:JSON.stringify(t.body),signal:t.signal});n.ok||await _e(n);let{callbacks:r}=t,i=e=>{let t=String(e||``).trim();if(!t)return null;let n;try{n=JSON.parse(t)}catch{return console.warn(`Ignoring malformed chat stream line`,t),null}return!n||typeof n!=`object`?null:n.type===`text`&&typeof n.delta==`string`?(r.onTextDelta(n.delta),null):n.type===`approval`&&typeof n.approvalId==`string`&&typeof n.prompt==`string`?(r.onApproval(n),null):n.type===`result`&&n.result&&typeof n.result==`object`?n.result:typeof n.status==`string`&&Array.isArray(n.toolsUsed)?n:null};if(!n.body){let e=await n.text().catch(()=>``),t=null;for(let n of e.split(`
3
+ `)){let e=i(n);e&&(t=e)}if(!t)throw Error(`Chat stream ended without a result payload.`);return t}let a=n.body.getReader(),o=new TextDecoder,s=``,c=null,l=(e=!1)=>{let t=s.split(`
4
+ `),n=e?t.pop()??``:null;s=e?``:t.pop()??``;for(let e of t){let t=i(e);t&&(c=t)}if(e&&n?.trim()){let e=i(n);e&&(c=e)}};try{for(;;){let{done:e,value:t}=await a.read();if(e)break;s+=o.decode(t,{stream:!0}),l()}s+=o.decode(),l(!0)}finally{a.releaseLock()}if(!c)throw Error(`Chat stream ended without a result payload.`);return c}function Yt(e){let t=e.trim().split(/\s+/),n=t[0]?.replace(/^\/+/,``).toLowerCase(),r=t[1]?.toLowerCase();return(n===`agent`||n===`agents`)&&(r===`create`||r===`install`)}function Xt(e){let t=e.trim().split(/\s+/),n=t[0]?.replace(/^\/+/,``).toLowerCase();if(n!==`agent`&&n!==`agents`||t[1]?.toLowerCase()!==`switch`)return null;let r=t[2]?.trim();return r&&!/\s/.test(r)?r:null}function Zt(e){return/^Session agent set to\b/i.test(e.trim())}function Qt(e){return/\bBOOTSTRAP\.md\b/i.test(e)}function $t(e){let{token:t,userId:r,getSessionId:i,setError:a,refreshRecent:o,onSessionIdCorrection:s,onModelResolved:c,resolveAddressedAgentPresentation:l}=e,u=n(),d=(0,U.useRef)(null),[p,m]=(0,U.useState)(!1),[h,g]=(0,U.useState)(null),[_,v]=(0,U.useState)(null),y=(0,U.useCallback)((e,n)=>{let r=q(t,e);u.setQueryData(r,t=>{let r=t?.messages??[],i=typeof n==`function`?n(r):n;return i===r?t:{messages:i,branchFamilies:t?.branchFamilies??new Map,resolvedSessionId:t?.resolvedSessionId??e,agentId:t?.agentId??null,bootstrapAutostart:t?.bootstrapAutostart??null}})},[u,t]);return{sendMessage:(0,U.useCallback)(async(e,n,p)=>{if(d.current)return a(`Wait for the current run to finish before sending another message.`),!1;let h=i(),_=e=>y(h,e),b=p?.hideUser?null:j();if(a(``),b){let t=l?.(e)??null,r={id:b,role:`user`,content:e,rawContent:e,sessionId:h,media:n,artifacts:[],replayRequest:{content:e,media:n},addressedAgentPresentation:t};_(e=>[...e,r])}let x=j();_(e=>[...e,{id:x,role:`thinking`,content:``,sessionId:h}]);let S=j();g(S);let C={controller:new AbortController,sessionId:h,messageRole:`assistant`,assistantText:``,lastRenderedText:``,pendingApproval:null,renderFrame:0,stopping:!1};d.current=C,v(h),m(!0);let w=()=>{if(C.renderFrame=0,C.assistantText===C.lastRenderedText&&!C.pendingApproval)return;C.lastRenderedText=C.assistantText;let e=C.assistantText,t=C.pendingApproval;_(n=>{let r=n.filter(e=>e.id!==x),i=r.find(e=>e.id===S);return i?r.map(n=>n===i?{...n,role:C.messageRole,content:e,pendingApproval:t}:n):[...r,{id:S,role:C.messageRole,content:e,sessionId:C.sessionId,artifacts:[],pendingApproval:t}]})},T=()=>{C.renderFrame&&=(cancelAnimationFrame(C.renderFrame),0),w()},E=()=>{C.renderFrame||=requestAnimationFrame(w)};try{let i=await Jt(`/api/chat`,{token:t,body:{sessionId:h,channelId:`web`,userId:r,username:`web`,content:e,stream:!0,...n.length>0?{media:n}:{}},signal:C.controller.signal,callbacks:{onTextDelta:e=>{C.assistantText+=e,E()},onApproval:e=>{C.pendingApproval=e,C.messageRole=`approval`,C.assistantText.trim()||(C.assistantText=P(e)),E()}}});if(i.status===`error`)throw Error(i.error??`Unknown error`);i.sessionId&&i.sessionId!==h&&s(i.sessionId);let a=i.model?.trim();a&&c?.(a),T();let l=i.result??C.assistantText??``,d=C.pendingApproval,f=i.artifacts??[],p=typeof i.addressEnvelope?.to==`string`?i.addressEnvelope.to:null;if(!i.messageRole)throw Error(`Gateway chat result is missing messageRole.`);let m=i.messageRole,g=m===`command`&&l.trim().length===0&&f.length===0,v=(t,r,a)=>({...a,id:t,role:m,content:l,sessionId:r,messageId:i.assistantMessageId??null,artifacts:f,assistantPresentation:i.assistantPresentation??null,pendingApproval:d,responseRating:null,replayRequest:{content:e,media:n}});_(e=>{let t=e.filter(e=>e.id!==x),n=t.some(e=>e.id===S),r=e=>e.id===S?v(S,i.sessionId??e.sessionId,e):b&&e.id===b&&e.role===`user`?{...e,addressedAgentPresentation:p?i.assistantPresentation??null:null,messageId:e.messageId??i.userMessageId??null,sessionId:i.sessionId??e.sessionId}:e;if(g)return t.filter(e=>e.id!==S).map(r);let a=t.map(r);return n?a:[...a,v(S,i.sessionId??C.sessionId)]}),o();let y=m===`command`&&Zt(l)?Xt(e):null;if(y){let e=i.sessionId??h,n=q(t,e);u.setQueryData(n,e=>e&&{...e,agentId:y,bootstrapAutostart:Qt(l)?{status:`starting`,fileName:`BOOTSTRAP.md`}:e.bootstrapAutostart}),u.invalidateQueries({queryKey:n,refetchType:`none`}),u.invalidateQueries({queryKey:[`chat-context`,t,e]})}m===`command`&&Yt(e)&&u.invalidateQueries({queryKey:[`agents-list`,t]})}catch(e){C.renderFrame&&cancelAnimationFrame(C.renderFrame);let t=f(e);_(e=>{let n=e.filter(e=>e.id!==x);return C.stopping?n:[...n,{id:j(),role:`system`,content:`Error: ${t}`,sessionId:h}]})}finally{d.current=null,v(null),m(!1),g(null)}return!0},[t,r,i,y,s,c,l,u,a,o]),stopRequest:(0,U.useCallback)(async()=>{let e=d.current;if(!(!e||e.stopping)){e.stopping=!0;try{await Ie(t,e.sessionId,r,[`stop`])}catch(e){a(`Failed to stop: ${f(e)}`)}finally{e.controller.abort()}}},[t,r,a]),isStreaming:p,streamingMsgId:h,activeSessionId:_,isActive:(0,U.useCallback)(()=>d.current!==null,[])}}var en=120,tn=220;function nn(){let e=(0,U.useRef)(null),t=(0,U.useRef)(null),n=(0,U.useRef)(null),r=(0,U.useRef)(0),[i,a]=(0,U.useState)(!0),o=(0,U.useRef)(!0),s=(0,U.useRef)(!1),c=(0,U.useCallback)(e=>{o.current!==e&&(o.current=e,a(e))},[]),l=(0,U.useCallback)((e,t)=>{let n=Math.max(0,e.scrollHeight-e.clientHeight),r=Math.max(0,Math.min(t,n));r!==e.scrollTop&&(s.current=!0,e.scrollTop=r)},[]),u=(0,U.useCallback)(()=>{let t=e.current;!t||!o.current||t.scrollHeight<=t.clientHeight||l(t,t.scrollHeight)},[l]),d=(0,U.useCallback)(n=>{if(t.current?.abort(),t.current=null,e.current=n,!n)return;let r=new AbortController;t.current=r,n.addEventListener(`scroll`,()=>{if(s.current){s.current=!1;return}c(n.scrollHeight-n.scrollTop-n.clientHeight<=en)},{passive:!0,signal:r.signal}),u()},[c,u]),f=(0,U.useCallback)(e=>{if(n.current?.disconnect(),n.current=null,!e||typeof ResizeObserver>`u`)return;let t=new ResizeObserver(()=>u());t.observe(e),n.current=t},[u]),p=(0,U.useCallback)(()=>{let t=e.current;if(!t)return;if(r.current&&=(cancelAnimationFrame(r.current),0),c(!0),typeof window<`u`&&typeof window.matchMedia==`function`&&window.matchMedia(`(prefers-reduced-motion: reduce)`).matches){l(t,t.scrollHeight);return}let n=t.scrollTop;if(t.scrollHeight-t.clientHeight-n<=0)return;let i=performance.now(),a=()=>{let t=e.current;if(!t){r.current=0;return}let o=Math.min(1,(performance.now()-i)/tn),s=1-(1-o)**3;l(t,n+(t.scrollHeight-t.clientHeight-n)*s),r.current=o<1?requestAnimationFrame(a):0};r.current=requestAnimationFrame(a)},[c,l]),m=(0,U.useCallback)(()=>{c(!0);let t=e.current;t&&l(t,t.scrollHeight)},[c,l]);return(0,U.useEffect)(()=>()=>{t.current?.abort(),n.current?.disconnect(),r.current&&cancelAnimationFrame(r.current)},[]),{scrollRef:d,contentRef:f,isPinned:i,jumpToBottom:p,resetToBottom:m}}var rn=[],an=[],on=5e3,sn=`bootstrap-autostart-thinking`,cn=1500,ln=`Ready to claw through your to-do list?`;function un(e,t){let n=new Map;if(t.size===0)return n;for(let r of e){let e=r.branchKey;if(!e)continue;let i=t.get(e);if(!i||i.length<2)continue;let a=i.findIndex(e=>e.sessionId===r.sessionId);a<0||n.set(r.id,{current:a+1,total:i.length})}return n}function dn(e,t,n=``,r=`user`){return[`chat-recent`,e,t,n,r]}function fn(e,t){return[`chat-recent`,e,t]}function pn(e,t){return[`chat-context`,e,t]}function mn(){let e=ye(),t=n(),i=(0,U.useRef)(Oe()).current,o=(0,U.useMemo)(()=>new URLSearchParams(window.location.search).get(`prompt`)||``,[]),[s,c]=(0,U.useState)({message:``,version:0}),l=s.message,u=(0,U.useCallback)(e=>{c(t=>({message:typeof e==`function`?e(t.message):e,version:t.version+1}))},[]),[d,p]=(0,U.useState)(!1),[h,y]=(0,U.useState)(null),[b,x]=(0,U.useState)(!1),[C,w]=(0,U.useState)(null),[T,E]=(0,U.useState)(!1),[ee,te]=(0,U.useState)(null),[ne,O]=(0,U.useState)(``),[A,oe]=(0,U.useState)(`user`),[M,N]=(0,U.useState)(null),[ce,le]=(0,U.useState)(``),P=Ue(ce,160).trim(),{scrollRef:fe,contentRef:pe,isPinned:he,jumpToBottom:F,resetToBottom:_e}=nn(),ve=(0,U.useRef)(null),be=(0,U.useRef)(null);(0,U.useEffect)(()=>{let e=()=>{let e=window.visualViewport?.height??window.innerHeight;!Number.isFinite(e)||e<=0||(document.documentElement.style.setProperty(`--chat-visual-viewport-height`,`${Math.round(e)}px`),document.scrollingElement?.scrollTo({left:0}),document.body.scrollLeft=0,document.documentElement.scrollLeft=0)};return e(),window.addEventListener(`resize`,e),window.addEventListener(`orientationchange`,e),window.visualViewport?.addEventListener(`resize`,e),window.visualViewport?.addEventListener(`scroll`,e),()=>{window.removeEventListener(`resize`,e),window.removeEventListener(`orientationchange`,e),window.visualViewport?.removeEventListener(`resize`,e),window.visualViewport?.removeEventListener(`scroll`,e),document.documentElement.style.removeProperty(`--chat-visual-viewport-height`)}},[]);let{sessionId:I,getSessionId:L,navigateToSession:Se,switchToSession:we,startFreshChat:Ee,ensureSessionForSend:z,handleSessionIdCorrection:De}=qt(),B=(0,U.useCallback)(()=>{t.invalidateQueries({queryKey:fn(e.token,i)}),t.invalidateQueries({queryKey:q(e.token,L()),refetchType:`none`})},[t,e.token,i,L]),V=Te(e),H=a({queryKey:[`app-status`,e.token],queryFn:()=>de(e.token),staleTime:1/0,enabled:V,initialData:e.status===`ready`&&e.gatewayStatus?e.gatewayStatus:void 0}),Ae=a({queryKey:[`agents-list`,e.token],queryFn:()=>Ce(e.token),staleTime:3e4,enabled:V}),Me=a({queryKey:[`models`,e.token],queryFn:()=>se(e.token),staleTime:3e4,enabled:V}),Re=a({queryKey:[`skills`,e.token],queryFn:()=>ge(e.token),staleTime:6e4,retry:!1,enabled:V});(0,U.useEffect)(()=>{O(H.data?.defaultModel?.trim()??``)},[I,H.data?.defaultModel]),(0,U.useEffect)(()=>{H.error&&(console.error(`Failed to load gateway status for chat page`,H.error),u(`Failed to load the default agent. New chats will use main until gateway status loads.`))},[H.error,u]),(0,U.useEffect)(()=>{Me.error&&(console.error(`Failed to load models list for chat page`,Me.error),u(`Failed to load the model list. Model switching is unavailable.`))},[Me.error,u]);let ze=a({queryKey:dn(e.token,i,P,A),queryFn:()=>ke(e.token,i,`web`,P?He.maxSearchResults:He.maxRecentSessions,P||void 0,A),staleTime:1e4,enabled:V}),Be=ze.data?.sessions??[],W=(0,U.useMemo)(()=>(Ae.data??[]).map(e=>({id:e.id,name:e.name,imageUrl:e.imageUrl??null,emptyChatHeader:e.emptyChatHeader??null})),[Ae.data]),Ve=(0,U.useMemo)(()=>new Map((Re.data?.skills??[]).filter(e=>e.userInvocable).map(e=>[e.name.toLowerCase(),e.name])),[Re.data?.skills]),We=(0,U.useCallback)(e=>{let t=Ke(e);for(let e of t){let t=W.find(t=>t.id.toLowerCase()===e.agentId.toLowerCase());if(t)return{agentId:t.id,displayName:t.name??t.id,imageUrl:t.imageUrl??null}}return null},[W]),Ge=Me.data?.models??an,G=$t({token:e.token,userId:i,getSessionId:L,setError:u,refreshRecent:B,onSessionIdCorrection:De,onModelResolved:O,resolveAddressedAgentPresentation:We});(0,U.useEffect)(()=>{let e=s.message;if(p(!1),!e)return;let t=window.setTimeout(()=>{p(!0)},on),n=window.setTimeout(()=>{u(``),p(!1)},5200);return()=>{window.clearTimeout(t),window.clearTimeout(n)}},[s,u]);let K=a({queryKey:q(e.token,I),queryFn:()=>Je(e.token,I,i),enabled:V&&!!I,staleTime:1/0}),Xe=a({queryKey:pn(e.token,I),queryFn:()=>je(e.token,I),enabled:V&&!!I,staleTime:15e3,refetchOnWindowFocus:!1}),Y=K.data?.messages??rn,Ze=K.data?.bootstrapAutostart?.status===`starting`,Qe=(0,U.useMemo)(()=>Ze?[...Y,{id:sn,role:`thinking`,content:``,sessionId:I}]:Y,[Ze,Y,I]),X=K.data?.branchFamilies??qe,$e=ee?.trim().toLowerCase()||K.data?.agentId?.trim().toLowerCase()||H.data?.defaultAgentId?.trim().toLowerCase()||`main`,et=W.find(e=>e.id.toLowerCase()===$e)?.emptyChatHeader?.trim()||ln,Z=r({mutationFn:t=>ae(e.token,t),onSuccess:n=>{if(!n.deleted){u(`Delete failed: session was not found.`);return}let r=n.sessionId;t.removeQueries({queryKey:q(e.token,r)}),t.removeQueries({queryKey:pn(e.token,r)}),t.invalidateQueries({queryKey:fn(e.token,i)}),t.invalidateQueries({queryKey:[`overview`],refetchType:`none`}),N(null),r===L()&&Ee()},onError:e=>{u(`Delete failed: ${f(e)}`)}}),tt=r({mutationFn:t=>{if(!t.message.messageId)throw Error(`This response cannot be rated right now.`);return Fe(e.token,{sessionId:t.message.sessionId,messageId:t.message.messageId,userId:i,rating:t.rating})},onSuccess:(n,r)=>{let i=r.message.sessionId;t.setQueryData(q(e.token,i),e=>e&&{...e,messages:e.messages.map(e=>e.messageId===n.messageId?{...e,responseRating:n.rating}:e)})},onError:e=>{u(`Rating failed: ${f(e)}`)}});(0,U.useEffect)(()=>{let e=Xe.data?.snapshot?.model?.trim()??``;e&&O(e)},[Xe.data?.snapshot?.model]),(0,U.useEffect)(()=>{te(null)},[I]),(0,U.useEffect)(()=>{K.error&&u(f(K.error))},[K.error,u]),(0,U.useEffect)(()=>{if(K.data?.bootstrapAutostart?.status!==`starting`||K.isFetching)return;let e=window.setTimeout(()=>{K.refetch()},cn);return()=>window.clearTimeout(e)},[K.data?.bootstrapAutostart?.status,K.isFetching,K.refetch]),(0,U.useEffect)(()=>{if(!C)return;let e=document.body.style.overflow,t=document.activeElement;document.body.style.overflow=`hidden`,be.current?.focus();let n=e=>{if(e.key===`Escape`){e.preventDefault(),w(null);return}if(e.key!==`Tab`)return;let t=Array.from(ve.current?.querySelectorAll(`a[href], button:not(:disabled)`)??[]);if(t.length===0)return;let n=t[0],r=t[t.length-1];e.shiftKey&&document.activeElement===n?(e.preventDefault(),r?.focus()):!e.shiftKey&&document.activeElement===r&&(e.preventDefault(),n?.focus())};return document.addEventListener(`keydown`,n),()=>{document.removeEventListener(`keydown`,n),document.body.style.overflow=e,t instanceof HTMLElement&&t.focus()}},[C]),(0,U.useEffect)(()=>{let e=K.data?.resolvedSessionId;!e||e===I||Se(e,{replace:!0})},[K.data?.resolvedSessionId,I,Se]);let nt=(0,U.useMemo)(()=>un(Y,X),[Y,X]),rt=(0,U.useRef)(!1);(0,U.useEffect)(()=>{rt.current&&!G.isStreaming&&I&&t.invalidateQueries({queryKey:pn(e.token,I)}),rt.current=G.isStreaming},[G.isStreaming,t,e.token,I]),(0,U.useEffect)(()=>{I&&_e()},[I,_e]);let it=(0,U.useCallback)(async(n,r)=>{if(!n.messageId||!n.sessionId){u(`This message cannot be edited right now.`);return}y(null);try{let a=await Pe(e.token,n.sessionId,n.messageId);t.invalidateQueries({queryKey:q(e.token,n.sessionId),refetchType:`none`}),await t.ensureQueryData({queryKey:q(e.token,a.sessionId),queryFn:()=>Je(e.token,a.sessionId,i)}),await we(a.sessionId),G.sendMessage(r,n.media??[])}catch(e){u(f(e))}},[e.token,t,u,we,G.sendMessage,i]),at=(0,U.useCallback)(e=>{e.replayRequest&&(F(),G.sendMessage(e.replayRequest.content,e.replayRequest.media,{hideUser:!0}))},[F,G.sendMessage]),ot=(0,U.useCallback)(async(e,t)=>{let n=ue(e,t);if(n){x(!0);try{F(),await G.sendMessage(n,[],{hideUser:!0})}finally{x(!1)}}},[F,G.sendMessage]),st=(0,U.useCallback)((e,t)=>{tt.mutate({message:e,rating:t})},[tt]),ct=(0,U.useCallback)(async t=>{let n=await Promise.allSettled(t.map(t=>Le(e.token,t))),r=[];for(let e of n)e.status===`fulfilled`&&e.value.media?r.push(e.value.media):e.status===`rejected`&&u(f(e.reason));return r},[e.token,u]),lt=(0,U.useCallback)(()=>{if(G.isActive()){u(`Stop the current run before starting a new chat.`);return}Ee(),B()},[G.isActive,Ee,B,u]),ut=(0,U.useCallback)((e,t)=>{z(),F(),G.sendMessage(e,t)},[z,F,G.sendMessage]),ft=(0,U.useCallback)((n,r)=>{let i=r.trim();i&&t.setQueryData(q(e.token,n),e=>{let t=e?.messages??[];return t.some(e=>e.role===`command`&&(e.rawContent||e.content).trim()===i)?e:{messages:[...t,{id:j(),role:`command`,content:i,rawContent:i,sessionId:n,artifacts:[],replayRequest:null}],branchFamilies:e?.branchFamilies??new Map,resolvedSessionId:n,agentId:e?.agentId??null,bootstrapAutostart:e?.bootstrapAutostart??null}})},[e.token,t]),pt=(0,U.useCallback)(async n=>{let r=q(e.token,n);return t.fetchQuery({queryKey:r,queryFn:()=>Je(e.token,n,i),staleTime:0}).catch(e=>(console.warn(`Failed to prefetch chat history before appending switch result`,e),null))},[e.token,t,i]),Q=(0,U.useCallback)(async(n,r,a,o)=>{if(!r||/\s/.test(r))return;if(G.isActive()){u(o);return}z();let s=L();try{let o=await Ie(e.token,s,i,[...n,r]),c=o.sessionId?.trim()||s,l=await pt(c);ft(c,o.text),c!==s&&await we(c,{replace:!0}),t.invalidateQueries({queryKey:pn(e.token,c)}),n[0]===`agent`&&n[1]===`switch`&&l?.bootstrapAutostart?.fileName===`BOOTSTRAP.md`&&(l.bootstrapAutostart.status===`idle`||l.bootstrapAutostart.status===`starting`)&&(t.setQueryData(q(e.token,c),e=>e&&{...e,bootstrapAutostart:{status:`starting`,fileName:`BOOTSTRAP.md`}}),F()),B(),a(r)}catch(e){u(f(e))}},[ft,e.token,z,pt,L,F,t,B,u,G.isActive,we,i]),mt=(0,U.useCallback)(e=>Q([`agent`,`switch`],e,te,`Could not switch agent — stop the current run and try again.`),[Q]),ht=(0,U.useCallback)(e=>Q([`model`,`set`],e,O,`Could not switch model — stop the current run and try again.`),[Q]),$=(0,U.useCallback)(e=>{if(G.isActive()){u(`Stop the current run before switching chats.`);return}Se(e)},[G.isActive,Se,u]),gt=(0,U.useCallback)(e=>G.activeSessionId===e?(u(`Stop the current run before deleting this chat.`),!1):!Z.isPending,[Z.isPending,G.activeSessionId,u]),_t=(0,U.useCallback)(e=>{gt(e.sessionId)&&N(e)},[gt]),yt=(0,U.useCallback)(()=>{if(!M)throw Error(`Delete confirmation is missing a session.`);gt(M.sessionId)&&Z.mutate(M.sessionId)},[gt,Z,M]),bt=(0,U.useCallback)(n=>{n!==L()&&t.prefetchQuery({queryKey:q(e.token,n),queryFn:()=>Je(e.token,n,i),staleTime:3e4})},[t,e.token,L,i]),xt=(0,U.useCallback)(()=>{t.invalidateQueries({queryKey:dn(e.token,i,P,A)})},[t,e.token,i,P,A]),St=(0,U.useCallback)(async()=>{let t=L();if(!t){u(`Open or send a chat before creating a mobile QR code.`);return}E(!0);try{w(await Ne(e.token,{userId:i,sessionId:t,baseUrl:window.location.origin}))}catch(e){u(f(e))}finally{E(!1)}},[e.token,L,i,u]),Ct=(0,U.useCallback)(e=>{y(e.id)},[]),wt=(0,U.useCallback)((e,t)=>{let n=e.branchKey;if(!n)return;let r=X.get(n);if(!r||r.length<2)return;let i=r.findIndex(t=>t.sessionId===e.sessionId);if(i<0)return;let a=i+t;if(a<0||a>=r.length)return;let o=r[a];o&&$(o.sessionId)},[X,$]),Tt=Qe.length===0,Et=K.isFetching,Dt={sessions:Be,activeSessionId:I,onNewChat:lt,onOpenSession:$,onHoverSession:bt,onRequestDeleteSession:_t,deleteDisabled:Z.isPending,isPending:Et,searchQuery:ce,onSearchQueryChange:le,recentScope:A,onRecentScopeChange:oe,isLoading:ze.isFetching,onRefreshRecent:xt};return(0,J.jsx)(g,{children:(0,J.jsxs)(`div`,{className:R.chatPage,"aria-busy":Et,children:[(0,J.jsx)(Ye,{...Dt}),(0,J.jsxs)(`div`,{className:R.chatMain,children:[(0,J.jsxs)(`div`,{className:R.chatTopbar,children:[(0,J.jsx)(me,{className:R.chatMobileTrigger}),(0,J.jsx)(vt,{sessionId:I,token:e.token,enabled:V}),(0,J.jsx)(`button`,{type:`button`,className:R.mobileQrButton,onClick:()=>void St(),disabled:T,"aria-label":`Show mobile QR code`,title:`Show mobile QR code`,children:(0,J.jsxs)(`span`,{"aria-hidden":`true`,className:R.mobileQrIcon,children:[(0,J.jsx)(`span`,{}),(0,J.jsx)(`span`,{}),(0,J.jsx)(`span`,{}),(0,J.jsx)(`span`,{})]})}),(0,J.jsx)(S,{})]}),C?(0,J.jsx)(`div`,{className:R.mobileQrOverlay,children:(0,J.jsxs)(`div`,{ref:ve,className:R.mobileQrDialog,role:`dialog`,"aria-modal":`true`,"aria-labelledby":`mobile-qr-title`,children:[(0,J.jsxs)(`div`,{className:R.mobileQrHeader,children:[(0,J.jsx)(`h2`,{id:`mobile-qr-title`,children:`Open on mobile`}),(0,J.jsx)(`button`,{ref:be,type:`button`,className:R.mobileQrClose,onClick:()=>w(null),"aria-label":`Close mobile QR code`,children:`x`})]}),(0,J.jsx)(`div`,{className:R.mobileQrImage,children:(0,J.jsx)(`img`,{src:`data:image/svg+xml;charset=utf-8,${encodeURIComponent(C.qrSvg)}`,alt:`Mobile session QR code`})}),(0,J.jsx)(`a`,{className:R.mobileQrLink,href:C.launchUrl,children:`Open link`})]})}):null,Tt?(0,J.jsx)(`div`,{className:R.emptyState,children:(0,J.jsx)(`h1`,{className:R.greeting,children:et})}):(0,J.jsx)(`div`,{className:R.messageArea,ref:fe,children:(0,J.jsx)(`div`,{className:R.messageList,ref:pe,children:Qe.map(t=>h===t.id&&t.role!==`thinking`?(0,J.jsx)(`div`,{className:R.messageBlock,children:(0,J.jsx)(Kt,{initial:t.rawContent??t.content,onSave:e=>void it(t,e),onCancel:()=>y(null)})},t.id):(0,J.jsx)(Ht,{message:t,token:e.token,isStreaming:t.id===G.streamingMsgId,onCopy:k,onEdit:Ct,onRegenerate:at,onRate:st,ratingBusy:tt.isPending&&tt.variables?.message.id===t.id,skillInvocationTargets:Ve,onApprovalAction:ot,approvalBusy:b,branchInfo:nt.get(t.id)??null,onBranchNav:wt},t.id))})}),!Tt&&!he?(0,J.jsxs)(`button`,{type:`button`,className:R.jumpToLatest,onClick:F,"aria-label":`Jump to latest message`,children:[(0,J.jsx)(`span`,{"aria-hidden":`true`,children:`↓`}),(0,J.jsx)(`span`,{children:`Latest`})]}):null,l?(0,J.jsx)(`div`,{className:`${R.errorBanner} ${d?R.errorBannerExiting:``}`,children:l}):null,(0,J.jsx)(dt,{isStreaming:G.isStreaming,onSend:ut,onStop:()=>void G.stopRequest(),onUploadFiles:ct,token:e.token,agents:W,selectedAgentId:$e,onAgentSwitch:e=>void mt(e),models:Ge,selectedModelId:ne,onModelSwitch:e=>void ht(e),initialValue:o})]}),(0,J.jsx)(re,{open:M!==null,onOpenChange:e=>{!e&&!Z.isPending&&N(null)},children:(0,J.jsxs)(v,{size:`sm`,role:`alertdialog`,preventCloseOnOutsideClick:Z.isPending,children:[(0,J.jsxs)(ie,{children:[(0,J.jsx)(D,{children:`Delete session?`}),(0,J.jsx)(xe,{children:`This permanently removes the conversation and associated session records.`})]}),(0,J.jsxs)(_,{children:[(0,J.jsx)(m,{className:`ghost-button`,disabled:Z.isPending,children:`Cancel`}),(0,J.jsx)(`button`,{type:`button`,className:`danger-button`,disabled:Z.isPending,onClick:yt,children:Z.isPending?`Deleting...`:`Delete`})]})]})})]})})}export{mn as ChatPage};