@hybridaione/hybridclaw 0.24.4 → 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.
- package/AGENTS.md +7 -1
- package/CHANGELOG.md +97 -0
- package/README.md +11 -2
- package/config.example.json +10 -2
- package/console/dist/assets/chat-CDXd1yTl.js +4 -0
- package/console/dist/assets/index-DHzWClL-.css +1 -0
- package/console/dist/assets/index-DN3T1L-r.js +174 -0
- package/console/dist/assets/terminal-Dwbnwiir.js +1 -0
- package/console/dist/index.html +2 -2
- package/console/package.json +1 -1
- package/container/dist/artifacts.js +5 -0
- package/container/dist/artifacts.js.map +1 -1
- package/container/dist/providers/hybridai.js +13 -4
- package/container/dist/providers/hybridai.js.map +1 -1
- package/container/dist/user-agent.js +31 -0
- package/container/dist/user-agent.js.map +1 -0
- package/container/npm-shrinkwrap.json +2 -2
- package/container/package-lock.json +2 -2
- package/container/package.json +1 -1
- package/container/src/artifacts.ts +7 -0
- package/container/src/mcp/types.ts +2 -0
- package/container/src/providers/hybridai.ts +17 -4
- package/container/src/user-agent.ts +40 -0
- package/dist/agents/agent-config-command.d.ts.map +1 -1
- package/dist/agents/agent-config-command.js +7 -0
- package/dist/agents/agent-config-command.js.map +1 -1
- package/dist/agents/agent-registry.d.ts.map +1 -1
- package/dist/agents/agent-registry.js +5 -2
- package/dist/agents/agent-registry.js.map +1 -1
- package/dist/agents/agent-runtime-config.d.ts.map +1 -1
- package/dist/agents/agent-runtime-config.js +1 -0
- package/dist/agents/agent-runtime-config.js.map +1 -1
- package/dist/agents/agent-types.d.ts +2 -1
- package/dist/agents/agent-types.d.ts.map +1 -1
- package/dist/agents/agent-types.js +2 -1
- package/dist/agents/agent-types.js.map +1 -1
- package/dist/agents/claw-archive.d.ts +1 -0
- package/dist/agents/claw-archive.d.ts.map +1 -1
- package/dist/agents/claw-archive.js +14 -3
- package/dist/agents/claw-archive.js.map +1 -1
- package/dist/agents/claw-manifest.d.ts +1 -0
- package/dist/agents/claw-manifest.d.ts.map +1 -1
- package/dist/agents/claw-manifest.js +3 -1
- package/dist/agents/claw-manifest.js.map +1 -1
- package/dist/auth/codex-auth.d.ts.map +1 -1
- package/dist/auth/codex-auth.js +2 -27
- package/dist/auth/codex-auth.js.map +1 -1
- package/dist/auth/hybridai-auth.d.ts.map +1 -1
- package/dist/auth/hybridai-auth.js +2 -28
- package/dist/auth/hybridai-auth.js.map +1 -1
- package/dist/channels/email/connection.d.ts +3 -1
- package/dist/channels/email/connection.d.ts.map +1 -1
- package/dist/channels/email/connection.js.map +1 -1
- package/dist/channels/email/inbound.d.ts +2 -1
- package/dist/channels/email/inbound.d.ts.map +1 -1
- package/dist/channels/email/inbound.js +1 -0
- package/dist/channels/email/inbound.js.map +1 -1
- package/dist/channels/email/runtime.d.ts +6 -1
- package/dist/channels/email/runtime.d.ts.map +1 -1
- package/dist/channels/email/runtime.js +248 -101
- package/dist/channels/email/runtime.js.map +1 -1
- package/dist/channels/message/tool-actions.d.ts.map +1 -1
- package/dist/channels/message/tool-actions.js +5 -0
- package/dist/channels/message/tool-actions.js.map +1 -1
- package/dist/cli/agent-command.js +1 -1
- package/dist/cli/agent-command.js.map +1 -1
- package/dist/cli/help.d.ts.map +1 -1
- package/dist/cli/help.js +15 -4
- package/dist/cli/help.js.map +1 -1
- package/dist/cli.d.ts.map +1 -1
- package/dist/cli.js +5 -0
- package/dist/cli.js.map +1 -1
- package/dist/command-registry.d.ts.map +1 -1
- package/dist/command-registry.js +46 -4
- package/dist/command-registry.js.map +1 -1
- package/dist/config/config.d.ts +1 -0
- package/dist/config/config.d.ts.map +1 -1
- package/dist/config/config.js +2 -0
- package/dist/config/config.js.map +1 -1
- package/dist/config/runtime-config.d.ts +20 -1
- package/dist/config/runtime-config.d.ts.map +1 -1
- package/dist/config/runtime-config.js +149 -5
- package/dist/config/runtime-config.js.map +1 -1
- package/dist/evals/agent-risk-native.d.ts +52 -0
- package/dist/evals/agent-risk-native.d.ts.map +1 -0
- package/dist/evals/agent-risk-native.js +1346 -0
- package/dist/evals/agent-risk-native.js.map +1 -0
- package/dist/evals/eval-command.d.ts.map +1 -1
- package/dist/evals/eval-command.js +236 -16
- package/dist/evals/eval-command.js.map +1 -1
- package/dist/evals/hybridai-skills-command.d.ts.map +1 -1
- package/dist/evals/hybridai-skills-command.js +2 -0
- package/dist/evals/hybridai-skills-command.js.map +1 -1
- package/dist/evals/locomo-native.d.ts.map +1 -1
- package/dist/evals/locomo-native.js +2 -0
- package/dist/evals/locomo-native.js.map +1 -1
- package/dist/evals/openai-url.d.ts +3 -0
- package/dist/evals/openai-url.d.ts.map +1 -0
- package/dist/evals/openai-url.js +8 -0
- package/dist/evals/openai-url.js.map +1 -0
- package/dist/evolution/harness-evolution.d.ts +4 -0
- package/dist/evolution/harness-evolution.d.ts.map +1 -1
- package/dist/evolution/harness-evolution.js +35 -1
- package/dist/evolution/harness-evolution.js.map +1 -1
- package/dist/evolution/harness-risk-taxonomy.d.ts +149 -0
- package/dist/evolution/harness-risk-taxonomy.d.ts.map +1 -0
- package/dist/evolution/harness-risk-taxonomy.js +280 -0
- package/dist/evolution/harness-risk-taxonomy.js.map +1 -0
- package/dist/gateway/auth-token.d.ts +1 -0
- package/dist/gateway/auth-token.d.ts.map +1 -1
- package/dist/gateway/auth-token.js +3 -0
- package/dist/gateway/auth-token.js.map +1 -1
- package/dist/gateway/docs.d.ts +1 -0
- package/dist/gateway/docs.d.ts.map +1 -1
- package/dist/gateway/docs.js +116 -72
- package/dist/gateway/docs.js.map +1 -1
- package/dist/gateway/gateway-admin-secrets.js +2 -2
- package/dist/gateway/gateway-admin-secrets.js.map +1 -1
- package/dist/gateway/gateway-chat-service.d.ts.map +1 -1
- package/dist/gateway/gateway-chat-service.js +68 -34
- package/dist/gateway/gateway-chat-service.js.map +1 -1
- package/dist/gateway/gateway-client.d.ts +9 -1
- package/dist/gateway/gateway-client.d.ts.map +1 -1
- package/dist/gateway/gateway-client.js +43 -0
- package/dist/gateway/gateway-client.js.map +1 -1
- package/dist/gateway/gateway-http-server.d.ts.map +1 -1
- package/dist/gateway/gateway-http-server.js +257 -61
- package/dist/gateway/gateway-http-server.js.map +1 -1
- package/dist/gateway/gateway-service.d.ts +39 -3
- package/dist/gateway/gateway-service.d.ts.map +1 -1
- package/dist/gateway/gateway-service.js +1108 -60
- package/dist/gateway/gateway-service.js.map +1 -1
- package/dist/gateway/gateway-types.d.ts +78 -1
- package/dist/gateway/gateway-types.d.ts.map +1 -1
- package/dist/gateway/gateway-types.js.map +1 -1
- package/dist/gateway/gateway.js +20 -7
- package/dist/gateway/gateway.js.map +1 -1
- package/dist/gateway/hatching-completion.d.ts +18 -0
- package/dist/gateway/hatching-completion.d.ts.map +1 -0
- package/dist/gateway/hatching-completion.js +96 -0
- package/dist/gateway/hatching-completion.js.map +1 -0
- package/dist/infra/container-runner.d.ts.map +1 -1
- package/dist/infra/container-runner.js +3 -1
- package/dist/infra/container-runner.js.map +1 -1
- package/dist/infra/host-runner.d.ts.map +1 -1
- package/dist/infra/host-runner.js +3 -1
- package/dist/infra/host-runner.js.map +1 -1
- package/dist/mcp/mcp-oauth.d.ts +91 -0
- package/dist/mcp/mcp-oauth.d.ts.map +1 -0
- package/dist/mcp/mcp-oauth.js +434 -0
- package/dist/mcp/mcp-oauth.js.map +1 -0
- package/dist/mcp/server-config.d.ts +7 -0
- package/dist/mcp/server-config.d.ts.map +1 -0
- package/dist/mcp/server-config.js +9 -0
- package/dist/mcp/server-config.js.map +1 -0
- package/dist/memory/db.d.ts +4 -1
- package/dist/memory/db.d.ts.map +1 -1
- package/dist/memory/db.js +59 -4
- package/dist/memory/db.js.map +1 -1
- package/dist/onboarding.d.ts.map +1 -1
- package/dist/onboarding.js +3 -28
- package/dist/onboarding.js.map +1 -1
- package/dist/providers/hybridai.d.ts.map +1 -1
- package/dist/providers/hybridai.js +4 -1
- package/dist/providers/hybridai.js.map +1 -1
- package/dist/providers/user-agent.d.ts +3 -0
- package/dist/providers/user-agent.d.ts.map +1 -0
- package/dist/providers/user-agent.js +7 -0
- package/dist/providers/user-agent.js.map +1 -0
- package/dist/security/admin-rbac.d.ts +24 -1
- package/dist/security/admin-rbac.d.ts.map +1 -1
- package/dist/security/admin-rbac.js +505 -19
- package/dist/security/admin-rbac.js.map +1 -1
- package/dist/skills/skill-docs.d.ts +23 -0
- package/dist/skills/skill-docs.d.ts.map +1 -0
- package/dist/skills/skill-docs.js +189 -0
- package/dist/skills/skill-docs.js.map +1 -0
- package/dist/skills/skills.d.ts +3 -0
- package/dist/skills/skills.d.ts.map +1 -1
- package/dist/skills/skills.js +10 -0
- package/dist/skills/skills.js.map +1 -1
- package/dist/tui-mcp-wizard.d.ts +63 -0
- package/dist/tui-mcp-wizard.d.ts.map +1 -0
- package/dist/tui-mcp-wizard.js +299 -0
- package/dist/tui-mcp-wizard.js.map +1 -0
- package/dist/tui.d.ts.map +1 -1
- package/dist/tui.js +45 -1
- package/dist/tui.js.map +1 -1
- package/dist/types/models.d.ts +5 -0
- package/dist/types/models.d.ts.map +1 -1
- package/dist/types/models.js.map +1 -1
- package/dist/utils/open-url.d.ts +3 -0
- package/dist/utils/open-url.d.ts.map +1 -0
- package/dist/utils/open-url.js +29 -0
- package/dist/utils/open-url.js.map +1 -0
- package/dist/workspace.d.ts +23 -2
- package/dist/workspace.d.ts.map +1 -1
- package/dist/workspace.js +153 -178
- package/dist/workspace.js.map +1 -1
- package/docs/agents.html +20 -6
- package/docs/content/README.md +21 -10
- package/docs/content/channels/email.md +55 -0
- package/docs/content/developer-guide/README.md +11 -0
- package/docs/content/developer-guide/admin-access-control.md +107 -0
- package/docs/content/developer-guide/iso27001/README.md +51 -0
- package/docs/content/developer-guide/iso27001/_category_.json +5 -0
- package/docs/content/developer-guide/iso27001/access-control-matrix.md +45 -0
- package/docs/content/developer-guide/iso27001/asset-data-inventory.md +32 -0
- package/docs/content/developer-guide/iso27001/audit-monitoring-matrix.md +33 -0
- package/docs/content/developer-guide/iso27001/control-owners.md +23 -0
- package/docs/content/developer-guide/iso27001/evidence-calendar.md +31 -0
- package/docs/content/developer-guide/iso27001/review-signoff.md +35 -0
- package/docs/content/developer-guide/iso27001/risk-register.md +25 -0
- package/docs/content/developer-guide/iso27001/statement-of-applicability.md +45 -0
- package/docs/content/developer-guide/iso27001/supplier-register.md +20 -0
- package/docs/content/developer-guide/iso27001-control-matrix.md +165 -0
- package/docs/content/developer-guide/iso42001-aims-evidence-templates.md +184 -0
- package/docs/content/developer-guide/iso42001-aims-readiness.md +152 -0
- package/docs/content/extensibility/agent-packages.md +10 -8
- package/docs/content/getting-started/installation.md +1 -1
- package/docs/content/getting-started/quickstart.md +9 -0
- package/docs/content/guides/bundled-skills.md +3 -2
- package/docs/content/guides/tui-mcp.md +36 -1
- package/docs/content/internal/roadmap.md +2 -1
- package/docs/content/navigation.json +415 -0
- package/docs/content/reference/commands.md +15 -7
- package/docs/content/reference/model-selection.md +3 -0
- package/docs/index.html +80 -56
- package/docs/static/docs.js +12 -237
- package/npm-shrinkwrap.json +5 -5
- package/package.json +2 -1
- package/skills/blink/SKILL.md +1 -0
- package/skills/blink/logo.webp +0 -0
- package/skills/posthog/SKILL.md +269 -0
- package/skills/posthog/posthog.cjs +924 -0
- package/templates/BOOTSTRAP.md +88 -124
- package/templates/USER.md +7 -9
- package/console/dist/assets/chat-l6mMqTpB.js +0 -96
- package/console/dist/assets/index-BF_BYy1U.css +0 -1
- package/console/dist/assets/index-BM_8rwPN.js +0 -80
- package/console/dist/assets/terminal-BguiTgJZ.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.
|
|
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,103 @@
|
|
|
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
|
+
|
|
5
102
|
## [0.24.4](https://github.com/HybridAIOne/hybridclaw/tree/v0.24.4) - 2026-06-16
|
|
6
103
|
|
|
7
104
|
### Added
|
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 |
|
|
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.
|
|
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
|
package/config.example.json
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
{
|
|
2
|
-
"version":
|
|
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": {
|
|
@@ -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};
|