From 765ad555285d266972608991f028fac45f5f17f2 Mon Sep 17 00:00:00 2001 From: jaylfc Date: Mon, 20 Apr 2026 13:55:44 +0100 Subject: [PATCH 1/9] docs: Chat Phase 3 typing-phase labels spec + plan --- .../2026-04-20-chat-phase-3-typing-labels.md | 563 ++++++++++++++++++ ...04-20-chat-phase-3-typing-labels-design.md | 94 +++ 2 files changed, 657 insertions(+) create mode 100644 docs/superpowers/plans/2026-04-20-chat-phase-3-typing-labels.md create mode 100644 docs/superpowers/specs/2026-04-20-chat-phase-3-typing-labels-design.md diff --git a/docs/superpowers/plans/2026-04-20-chat-phase-3-typing-labels.md b/docs/superpowers/plans/2026-04-20-chat-phase-3-typing-labels.md new file mode 100644 index 00000000..c6086dd7 --- /dev/null +++ b/docs/superpowers/plans/2026-04-20-chat-phase-3-typing-labels.md @@ -0,0 +1,563 @@ +# Chat Phase 3 — typing-phase labels — Implementation Plan + +> **For agentic workers:** REQUIRED SUB-SKILL: Use superpowers:subagent-driven-development. + +**Goal:** Ship structured `{phase, detail}` heartbeats from bridges + display phase-aware labels in the chat typing footer. + +**Architecture:** Additive fields on `POST /thinking` + `TypingRegistry` + WS `thinking` event. UI gains a phase→icon/label map. Bridges emit phase where the framework exposes it; omitting `phase` keeps current behavior. + +**Tech Stack:** Python 3.12 + FastAPI (backend), React/TS (UI), bash install scripts (bridges). + +--- + +## File structure + +### Modified +- `tinyagentos/chat/typing_registry.py` — store phase/detail, expose via list. +- `tinyagentos/routes/chat.py` — `POST /thinking` accepts phase/detail + validates enum; broadcast payload includes them. +- `tinyagentos/scripts/install_hermes.sh`, `install_smolagents.sh`, `install_langroid.sh`, `install_pocketflow.sh`, `install_openai_agents_sdk.sh`, `install_openai-agents-sdk.sh` — extend `_thinking()` helper to accept phase/detail; emit where framework exposes signals. +- `desktop/src/apps/chat/TypingFooter.tsx` — phase-aware labels + icons. + +### Tests +- `tests/test_typing_registry.py` — extend: phase/detail round-trip, default "thinking", overwrite semantics. +- `tests/test_routes_typing.py` (create or extend existing route-level tests) — POST /thinking with phase validates, broadcast includes phase. +- `desktop/src/apps/chat/__tests__/TypingFooter.test.tsx` — extend: icon/label per phase, detail truncation, unknown-phase fallback. + +--- + +## Task 1: TypingRegistry stores phase + detail + +**Files:** +- Modify: `tinyagentos/chat/typing_registry.py` +- Test: `tests/test_typing_registry.py` (extend) + +### Step 1: Write failing tests + +Append to `tests/test_typing_registry.py`: + +```python +@pytest.mark.asyncio +async def test_mark_with_phase_and_detail(): + reg = TypingRegistry() + reg.mark("c1", "tom", "agent", phase="tool", detail="web_search") + result = reg.list("c1") + agents = result["agent"] + assert len(agents) == 1 + entry = agents[0] + assert entry["slug"] == "tom" + assert entry["phase"] == "tool" + assert entry["detail"] == "web_search" + + +@pytest.mark.asyncio +async def test_mark_without_phase_defaults_to_thinking(): + reg = TypingRegistry() + reg.mark("c1", "tom", "agent") + result = reg.list("c1") + entry = result["agent"][0] + assert entry["phase"] == "thinking" + assert entry["detail"] is None + + +@pytest.mark.asyncio +async def test_mark_overwrites_phase_last_writer_wins(): + reg = TypingRegistry() + reg.mark("c1", "tom", "agent", phase="thinking") + reg.mark("c1", "tom", "agent", phase="tool", detail="search") + entry = reg.list("c1")["agent"][0] + assert entry["phase"] == "tool" + assert entry["detail"] == "search" + + +@pytest.mark.asyncio +async def test_human_entries_return_as_slug_only_for_backwards_compat(): + reg = TypingRegistry() + reg.mark("c1", "jay", "human") + result = reg.list("c1") + # Humans don't get phase/detail; kept as plain slug for legacy clients. + assert "jay" in (result["human"] if isinstance(result["human"][0], str) else [e["slug"] for e in result["human"]]) +``` + +Note: the new return shape will change `list()` contract. Agents become `[{slug, phase, detail}]` instead of `[slug]`. Humans stay as plain list-of-strings OR adopt the same dict shape. Pick consistency: **make humans use the same dict shape** `[{slug, phase: null, detail: null}]` and update the existing `test_routes_typing.py` + `TypingFooter` accordingly. Simpler. Update the 4th test to: + +```python +async def test_human_entry_shape_matches_agent(): + reg = TypingRegistry() + reg.mark("c1", "jay", "human") + entry = reg.list("c1")["human"][0] + assert entry["slug"] == "jay" + assert entry.get("phase") is None +``` + +### Step 2: Implement + +```python +from dataclasses import dataclass +from typing import Literal + +Kind = Literal["human", "agent"] +TypingPhase = Literal["thinking", "tool", "reading", "writing", "searching", "planning"] + +@dataclass +class _Entry: + kind: Kind + expires_at: float + phase: TypingPhase | None + detail: str | None + + +class TypingRegistry: + def __init__(self, human_ttl: int = 3, agent_ttl: int = 45) -> None: + self._ttls: dict[str, int] = {"human": human_ttl, "agent": agent_ttl} + self._entries: dict[tuple[str, str], _Entry] = {} + + def mark( + self, + channel_id: str, + slug: str, + kind: Kind, + *, + phase: TypingPhase | None = None, + detail: str | None = None, + ) -> None: + now = _now() + ttl = self._ttls[kind] + resolved_phase: TypingPhase | None = ( + phase if phase is not None else ("thinking" if kind == "agent" else None) + ) + self._entries[(channel_id, slug)] = _Entry( + kind=kind, + expires_at=now + ttl, + phase=resolved_phase, + detail=detail, + ) + + def clear(self, channel_id: str, slug: str) -> None: + self._entries.pop((channel_id, slug), None) + + def list(self, channel_id: str) -> dict[str, list[dict]]: + now = _now() + out: dict[str, list[dict]] = {"human": [], "agent": []} + stale: list[tuple[str, str]] = [] + for (ch, slug), entry in self._entries.items(): + if ch != channel_id: + continue + if entry.expires_at < now: + stale.append((ch, slug)) + continue + out[entry.kind].append({ + "slug": slug, + "phase": entry.phase, + "detail": entry.detail, + }) + for k in stale: + self._entries.pop(k, None) + out["human"].sort(key=lambda e: e["slug"]) + out["agent"].sort(key=lambda e: e["slug"]) + return out +``` + +### Step 3: Update `tests/test_typing_registry.py` existing tests to new shape + +Read the file; wherever it asserts `list["agent"] == ["tom"]`, change to check `[e["slug"] for e in list["agent"]] == ["tom"]` (or equivalent). + +### Step 4: Run tests → pass + +```bash +PYTHONPATH=. pytest tests/test_typing_registry.py -v +``` + +### Step 5: Commit + +```bash +git add tinyagentos/chat/typing_registry.py tests/test_typing_registry.py +git commit -m "feat(chat): typing registry stores phase + detail; agents expose {slug,phase,detail}" +``` + +--- + +## Task 2: `POST /thinking` accepts phase + detail + +**Files:** +- Modify: `tinyagentos/routes/chat.py` +- Test: existing route tests file for thinking if present (search), else extend `tests/test_chat_routes.py` + +### Step 1: Write failing test + +Create or extend `tests/test_chat_phase.py`: + +```python +import pytest, yaml +from httpx import AsyncClient, ASGITransport + + +def _make_phase_app(tmp_path): + cfg = {"server": {"host": "0.0.0.0", "port": 6969}, "backends": [], + "qmd": {"url": "http://localhost:7832"}, "agents": [], + "metrics": {"poll_interval": 30, "retention_days": 30}} + (tmp_path / "config.yaml").write_text(yaml.dump(cfg)) + (tmp_path / ".setup_complete").touch() + from tinyagentos.app import create_app + return create_app(data_dir=tmp_path) + + +async def _client_with_bearer(tmp_path): + app = _make_phase_app(tmp_path) + await app.state.chat_channels.init() + await app.state.chat_messages.init() + token = app.state.auth.get_local_token() + client = AsyncClient(transport=ASGITransport(app=app), base_url="http://test", + headers={"Authorization": f"Bearer {token}"}) + return app, client + + +@pytest.mark.asyncio +async def test_thinking_with_valid_phase_200(tmp_path): + app, client = await _client_with_bearer(tmp_path) + async with client: + r = await client.post("/api/chat/channels/c1/thinking", + json={"slug": "tom", "state": "start", "phase": "tool", "detail": "web_search"}) + assert r.status_code == 200, r.json() + listing = app.state.typing.list("c1") + assert listing["agent"][0]["phase"] == "tool" + assert listing["agent"][0]["detail"] == "web_search" + + +@pytest.mark.asyncio +async def test_thinking_with_invalid_phase_400(tmp_path): + app, client = await _client_with_bearer(tmp_path) + async with client: + r = await client.post("/api/chat/channels/c1/thinking", + json={"slug": "tom", "state": "start", "phase": "not-a-phase"}) + assert r.status_code == 400 + + +@pytest.mark.asyncio +async def test_thinking_without_phase_defaults_thinking(tmp_path): + app, client = await _client_with_bearer(tmp_path) + async with client: + r = await client.post("/api/chat/channels/c1/thinking", + json={"slug": "tom", "state": "start"}) + assert r.status_code == 200 + listing = app.state.typing.list("c1") + assert listing["agent"][0]["phase"] == "thinking" +``` + +### Step 2: Run → FAIL + +### Step 3: Update `POST /thinking` handler in routes/chat.py + +Around line 870-899, replace the body with: + +```python +VALID_PHASES = {"thinking", "tool", "reading", "writing", "searching", "planning"} + +@router.post("/api/chat/channels/{channel_id}/thinking") +async def post_thinking(channel_id: str, body: dict, request: Request): + auth = getattr(request.app.state, "auth", None) + bearer = request.headers.get("authorization", "") + if not bearer.lower().startswith("bearer "): + return JSONResponse({"error": "Unauthorized"}, status_code=401) + if auth is None or not auth.validate_local_token(bearer[7:].strip()): + return JSONResponse({"error": "Unauthorized"}, status_code=401) + + slug = (body or {}).get("slug") + state = (body or {}).get("state") + if not slug or state not in ("start", "end"): + return JSONResponse({"error": "slug and state in {start,end} required"}, status_code=400) + + phase = (body or {}).get("phase") + if phase is not None and phase not in VALID_PHASES: + return JSONResponse({"error": f"invalid phase; must be one of {sorted(VALID_PHASES)}"}, status_code=400) + detail = (body or {}).get("detail") + + reg = getattr(request.app.state, "typing", None) + hub = getattr(request.app.state, "chat_hub", None) + if reg is None: + return JSONResponse({"error": "typing registry not configured"}, status_code=503) + if state == "start": + reg.mark(channel_id, slug, "agent", phase=phase, detail=detail) + else: + reg.clear(channel_id, slug) + if hub is not None: + await hub.broadcast(channel_id, { + "type": "thinking", + "slug": slug, + "state": state, + "phase": phase if state == "start" else None, + "detail": detail if state == "start" else None, + }) + return JSONResponse({"ok": True}, status_code=200) +``` + +Also define `VALID_PHASES` at module top (or near the endpoint). + +### Step 4: Run tests → pass + +### Step 5: Commit + +```bash +git add tinyagentos/routes/chat.py tests/test_chat_phase.py +git commit -m "feat(chat): POST /thinking accepts phase + detail with enum validation" +``` + +--- + +## Task 3: TypingFooter — phase-aware labels + icons + +**Files:** +- Modify: `desktop/src/apps/chat/TypingFooter.tsx` +- Test: `desktop/src/apps/chat/__tests__/TypingFooter.test.tsx` (extend) + +### Step 1: Write failing tests + +Append to test file: + +```tsx +it("renders 'using X' for tool phase", () => { + render(); + expect(screen.getByText(/tom/i)).toBeInTheDocument(); + expect(screen.getByText(/using web_search/i)).toBeInTheDocument(); +}); + +it("renders 'writing X' for writing phase", () => { + render(); + expect(screen.getByText(/writing payment\.py/i)).toBeInTheDocument(); +}); + +it("truncates detail longer than 40 chars", () => { + const longDetail = "a".repeat(60); + render(); + const text = screen.getByText(/using/i).textContent ?? ""; + expect(text.length).toBeLessThanOrEqual(60); + expect(text).toContain("…"); +}); + +it("falls back to 'thinking' for unknown phase", () => { + render(); + expect(screen.getByText(/thinking/i)).toBeInTheDocument(); +}); +``` + +Also check the existing tests — they likely pass string slugs. Update them to the new `{slug, phase?, detail?}` shape or pass `slug` only (component should handle both for backward compat if existing callsites pass strings). + +### Step 2: Read and update component + +Read `TypingFooter.tsx`. Extend the `agents` prop type to accept `{slug, phase?, detail?}[]` (or `string[]` for back-compat if callers haven't migrated). Add a phase-to-label function: + +```tsx +type TypingPhase = "thinking" | "tool" | "reading" | "writing" | "searching" | "planning"; + +interface AgentTyping { + slug: string; + phase?: TypingPhase | null; + detail?: string | null; +} + +function phaseLabel(phase?: TypingPhase | null, detail?: string | null): { icon: string; text: string } { + const d = detail ? (detail.length > 40 ? detail.slice(0, 39) + "…" : detail) : null; + switch (phase) { + case "tool": return { icon: "🔧", text: d ? `using ${d}` : "using a tool" }; + case "reading": return { icon: "📖", text: d ? `reading ${d}` : "reading" }; + case "writing": return { icon: "✏️", text: d ? `writing ${d}` : "writing" }; + case "searching": return { icon: "🔍", text: d ? `searching ${d}` : "searching" }; + case "planning": return { icon: "📋", text: "planning" }; + case "thinking": + default: return { icon: "💭", text: "thinking" }; + } +} +``` + +Update the render to use `phaseLabel` per agent: + +```tsx +{agents.map((a) => { + const slug = typeof a === "string" ? a : a.slug; + const { icon, text } = typeof a === "string" + ? phaseLabel(null, null) + : phaseLabel(a.phase, a.detail); + return ( + + {icon} @{slug} is {text}… + + ); +})} +``` + +### Step 3: Update MessagesApp call site + +Find where `` is rendered. The data flows from: +- WS `thinking` event → local state +- `GET /typing` → list format + +Update the local state shape to `AgentTyping[]`. Adjust: +- WS handler for `type:"thinking"` to push `{slug, phase, detail}` (or clear on `state:"end"`). +- `fetchTyping` function to read `data.agent` which now contains dicts. + +### Step 4: Run tests + build → pass + +```bash +cd desktop && npm test -- --run TypingFooter +cd desktop && npm run build +``` + +### Step 5: Commit + +```bash +git add desktop/src/apps/chat/TypingFooter.tsx desktop/src/apps/chat/__tests__/TypingFooter.test.tsx desktop/src/apps/MessagesApp.tsx +git commit -m "feat(chat): TypingFooter shows phase-aware labels + icons" +``` + +--- + +## Task 4: Bridge scripts — emit phase heartbeats + +**Files:** +- Modify: 6 install scripts in `tinyagentos/scripts/install_*.sh` + +Each bridge has a `_thinking(c, channel_id, state)` helper. Extend signature to `_thinking(c, channel_id, state, *, phase=None, detail=None)` and pass `phase`/`detail` in the JSON body. + +### Shared helper pattern (apply to all 6 bridges): + +Find existing `async def _thinking(c: httpx.AsyncClient, ch_id, state: str) -> None:` block and replace with: + +```python +async def _thinking(c: httpx.AsyncClient, ch_id, state: str, *, + phase: str | None = None, detail: str | None = None) -> None: + if not ch_id: + return + body = {"slug": AGENT_NAME, "state": state} + if phase is not None: + body["phase"] = phase + if detail is not None: + body["detail"] = detail + try: + await c.post( + f"{BRIDGE_URL}/api/chat/channels/{ch_id}/thinking", + json=body, + headers={"Authorization": f"Bearer {LOCAL_TOKEN}"}, + timeout=5, + ) + except Exception: + pass +``` + +### Per-framework phase emission: + +- **Hermes** (`install_hermes.sh`): no framework-exposed phases. Keep existing `_thinking(c, ch_id, "start")` — defaults to `"thinking"`. No change beyond signature. + +- **SmolAgents** (`install_smolagents.sh`): `CodeAgent` emits step events. Wire a step callback that invokes `_thinking(c, ch_id, "start", phase="tool", detail=tool_name)` when a tool is called, `phase="writing"` when code is generated. If the smolagents API doesn't surface these hooks cleanly, just extend the existing `_thinking("start")` call — phase defaults to thinking. + +- **Langroid** (`install_langroid.sh`): if agent.tool_messages has signal, emit `tool`; else stay with default. + +- **PocketFlow** (`install_pocketflow.sh`): emit `_thinking(c, ch_id, "start", phase="tool", detail=f"node: {node.name}")` inside the `node_pre_run` or equivalent callback. If not easily available, stay default. + +- **OpenAI Agents SDK** (2 files): emit `_thinking(c, ch_id, "start", phase="tool", detail=tool.name)` from `on_handoff`/`on_tool` hooks if present. Otherwise default. + +**Scope note:** The minimum viable change is just updating the `_thinking` helper signature so future phase emission doesn't need another PR. Actual per-framework hook wiring is best-effort — if it's non-trivial for a given framework, leave that bridge on default thinking and note it in the PR description. + +### Step 1: Update all 6 helpers + +Apply the unified `_thinking` signature to all 6 bridges. + +### Step 2: Per-framework phase emission + +For each of smolagents / langroid / pocketflow / openai-agents-sdk, explore the framework API for callbacks: + +- `rg -n "step_callback\|run_async\|on_tool\|node_pre" tinyagentos/scripts/` — see what the existing loop already exposes. +- Where callbacks exist, emit `_thinking(c, ch_id, "start", phase=..., detail=...)` just before the native action. The existing `_thinking("end")` at the end of the turn stays put. + +If a framework doesn't expose callbacks, leave that bridge on default (no explicit phase) — it still works, just shows "thinking". + +### Step 3: Lint all 6 scripts + +```bash +for f in tinyagentos/scripts/install_hermes.sh \ + tinyagentos/scripts/install_smolagents.sh \ + tinyagentos/scripts/install_langroid.sh \ + tinyagentos/scripts/install_pocketflow.sh \ + tinyagentos/scripts/install_openai_agents_sdk.sh \ + tinyagentos/scripts/install_openai-agents-sdk.sh; do + bash -n "$f" && echo "$f ok" || echo "$f BAD" +done +``` + +All 6 should report `ok`. + +### Step 4: Commit + +```bash +git add tinyagentos/scripts/install_*.sh +git commit -m "feat(bridges): _thinking helper accepts phase/detail; emit per-framework where exposed" +``` + +--- + +## Task 5: Rebuild desktop bundle + +```bash +cd desktop && npm run build +cd /Volumes/NVMe/Users/jay/Development/tinyagentos +git add -A static/desktop desktop/tsconfig.tsbuildinfo +git commit -m "build: rebuild desktop bundle for chat Phase 3 typing labels" +``` + +--- + +## Task 6: Playwright E2E stub + +Create `tests/e2e/test_chat_phase3.py`: + +```python +"""Chat Phase 3 — typing-phase labels E2E. + +Requires TAOS_E2E_URL set. +""" +import os +import re + +import pytest +from playwright.sync_api import Page, expect + +pytestmark = [ + pytest.mark.e2e, + pytest.mark.skipif( + not os.environ.get("TAOS_E2E_URL"), + reason="TAOS_E2E_URL required", + ), +] +URL = os.environ.get("TAOS_E2E_URL", "") + + +def test_typing_footer_shows_phase_label(page: Page): + """Heartbeat with phase=tool + detail=web_search → footer renders 'using web_search'.""" + page.goto(URL) + page.get_by_role("button", name="Messages").click() + page.get_by_text("roundtable").first.click() + # The test requires a backend to emit a phase event; this is an env- + # gated stub, so it's left as a manual observation point. + # A CI-friendly version would POST /thinking via HTTP before asserting. +``` + +Commit: +```bash +git add tests/e2e/test_chat_phase3.py +git commit -m "test(e2e): chat Phase 3 typing-phase label stub" +``` + +--- + +## Final verification + +```bash +PYTHONPATH=. pytest tests/test_typing_registry.py tests/test_chat_phase.py -v +cd desktop && npm test -- --run +cd desktop && npm run build +``` + +```bash +git push -u origin feat/chat-phase-3-typing-labels +gh pr create --base master \ + --title "Chat Phase 3 — per-framework typing-phase labels" \ + --body-file docs/superpowers/specs/2026-04-20-chat-phase-3-typing-labels-design.md +``` diff --git a/docs/superpowers/specs/2026-04-20-chat-phase-3-typing-labels-design.md b/docs/superpowers/specs/2026-04-20-chat-phase-3-typing-labels-design.md new file mode 100644 index 00000000..1549bb00 --- /dev/null +++ b/docs/superpowers/specs/2026-04-20-chat-phase-3-typing-labels-design.md @@ -0,0 +1,94 @@ +# Chat Phase 3 — typing-phase labels + +**Status:** Approved 2026-04-20. + +## Goal + +Replace the generic "tom is thinking…" indicator with phase-aware labels so users can see what an agent is actually doing — "tom is using web_search", "don is writing payment.py", "tom is planning…". + +## Non-goals + +- Per-token streaming of the phase text. +- Persistent phase log / trace viewer (trace app is separate). +- Rich phase timelines in the channel. + +## Decisions + +1. **Structured payload:** `{phase: enum, detail?: string}`. Enum for consistent UI (icons, colour), detail for framework-specific specificity. +2. **Phase enum:** `thinking | tool | reading | writing | searching | planning`. +3. **Backwards compatible:** bridges that omit `phase` continue to send binary heartbeats, UI renders "thinking" as before. +4. **Rollout:** all 6 bridges + backend + UI in one PR. + +## Architecture + +### Payload + +```typescript +type TypingPhase = "thinking" | "tool" | "reading" | "writing" | "searching" | "planning"; + +interface ThinkingBody { + slug: string; + state: "start" | "end"; + phase?: TypingPhase; // optional; default "thinking" on start + detail?: string; // optional; free-form, truncated by UI to 40 chars +} +``` + +### Backend + +- `POST /api/chat/channels/{id}/thinking` body now accepts `phase` + `detail`. Validates `phase` against enum if present; rejects with 400 if invalid. +- `TypingRegistry.mark(channel_id, slug, kind, phase?, detail?)` stores `{kind, phase, detail, ts}` per (channel, slug). +- `TypingRegistry.list(channel_id)` returns agents with `{slug, phase, detail}` fields. +- `hub.broadcast` for `"thinking"` event includes `phase` and `detail`. + +### Frontend + +- Extend `TypingFooter` (`desktop/src/apps/chat/TypingFooter.tsx`) to accept an `agents` array shape `{slug, phase?, detail?}[]`. +- Phase label map: + | phase | label template | icon | + |---|---|---| + | `thinking` | `thinking` | 💭 | + | `tool` | `using ${detail}` (fallback: `using a tool`) | 🔧 | + | `reading` | `reading ${detail}` (fallback: `reading`) | 📖 | + | `writing` | `writing ${detail}` (fallback: `writing`) | ✏️ | + | `searching` | `searching ${detail}` (fallback: `searching`) | 🔍 | + | `planning` | `planning` | 📋 | +- `detail` strings truncated to 40 chars with ellipsis. +- Unknown `phase` values fall back to "thinking". + +### Bridge install scripts (6 files) + +Per framework, emit a phase heartbeat immediately before the corresponding action. Helper `_thinking(client, channel_id, state, phase=None, detail=None)` already exists as a shared shape from Phase 2a — extend to accept the new args. + +- **OpenClaw** (`install_openclaw.sh` — if present) — map tool calls to `tool`, file reads to `reading`, file writes to `writing`. +- **Hermes** (`install_hermes.sh`) — single completion. Emit `thinking` only. +- **SmolAgents** (`install_smolagents.sh`) — use step callbacks to emit `tool` (tool calls) + `writing` (CodeAgent code generation). +- **Langroid** (`install_langroid.sh`) — emit `tool` on tool calls. +- **PocketFlow** (`install_pocketflow.sh`) — emit `tool` with detail `"node: "` on each graph node enter. +- **OpenAI Agents SDK** (`install_openai_agents_sdk.sh` + `install_openai-agents-sdk.sh`) — emit `tool` when SDK dispatches a tool. + +Bridges without framework-exposed phases (Hermes) remain "thinking"-only; that's fine per the enum default. + +## Testing + +**Backend unit tests** (`tests/test_typing_registry.py`, extend): +- `mark` with phase/detail stores and `list` returns them. +- `mark` without phase defaults to `"thinking"`. +- Two marks for same slug overwrite phase (last-writer-wins). + +**Route tests** (`tests/test_routes_typing.py` extend or create): +- `POST /thinking` with valid phase 200s; invalid phase 400s. +- Payload in the broadcast event includes phase and detail. + +**Frontend unit tests** (`TypingFooter.test.tsx` extend): +- Renders correct icon + label per phase. +- Truncates detail >40 chars. +- Falls back to "thinking" for unknown phase. + +**E2E** (env-gated): post a `thinking` heartbeat with phase via HTTP, assert WS event shape. + +## Out of scope / later + +- Richer UI for phases (inline per-message thinking visualizer). +- Persistent per-session phase timelines. +- OpenClaw streaming integration — may need upstream changes to its SSE output. From ca56eed6e0364df310a64d4a4893330982a41fac Mon Sep 17 00:00:00 2001 From: jaylfc Date: Mon, 20 Apr 2026 13:58:56 +0100 Subject: [PATCH 2/9] feat(chat): typing registry stores phase + detail; agents expose {slug,phase,detail} --- tests/test_typing_registry.py | 227 ++++++++++++++++++++++++++++ tinyagentos/chat/typing_registry.py | 51 +++++-- 2 files changed, 267 insertions(+), 11 deletions(-) create mode 100644 tests/test_typing_registry.py diff --git a/tests/test_typing_registry.py b/tests/test_typing_registry.py new file mode 100644 index 00000000..68af5c3b --- /dev/null +++ b/tests/test_typing_registry.py @@ -0,0 +1,227 @@ +import pytest +from tinyagentos.chat.typing_registry import TypingRegistry + + +def test_empty_registry_returns_empty_lists(): + r = TypingRegistry() + assert r.list("c1") == {"human": [], "agent": []} + + +def test_mark_human_appears_in_list(): + r = TypingRegistry() + r.mark("c1", "jay", "human") + assert [e["slug"] for e in r.list("c1")["human"]] == ["jay"] + assert r.list("c1")["agent"] == [] + + +def test_mark_agent_appears_in_list(): + r = TypingRegistry() + r.mark("c1", "tom", "agent") + assert [e["slug"] for e in r.list("c1")["agent"]] == ["tom"] + + +def test_clear_removes_entry(): + r = TypingRegistry() + r.mark("c1", "tom", "agent") + r.clear("c1", "tom") + assert r.list("c1")["agent"] == [] + + +def test_clear_idempotent(): + r = TypingRegistry() + r.clear("c1", "nobody") # must not raise + + +def test_different_channels_independent(): + r = TypingRegistry() + r.mark("c1", "jay", "human") + assert r.list("c2") == {"human": [], "agent": []} + + +def test_human_ttl_expires(monkeypatch): + r = TypingRegistry(human_ttl=3, agent_ttl=45) + t = [1000.0] + monkeypatch.setattr("tinyagentos.chat.typing_registry._now", lambda: t[0]) + r.mark("c1", "jay", "human") + assert [e["slug"] for e in r.list("c1")["human"]] == ["jay"] + t[0] = 1003.1 + assert r.list("c1")["human"] == [] + + +def test_agent_ttl_expires(monkeypatch): + r = TypingRegistry(human_ttl=3, agent_ttl=45) + t = [1000.0] + monkeypatch.setattr("tinyagentos.chat.typing_registry._now", lambda: t[0]) + r.mark("c1", "tom", "agent") + assert [e["slug"] for e in r.list("c1")["agent"]] == ["tom"] + t[0] = 1045.1 + assert r.list("c1")["agent"] == [] + + +def test_mark_refreshes_ttl(monkeypatch): + r = TypingRegistry(human_ttl=3, agent_ttl=45) + t = [1000.0] + monkeypatch.setattr("tinyagentos.chat.typing_registry._now", lambda: t[0]) + r.mark("c1", "jay", "human") + t[0] = 1002.0 + r.mark("c1", "jay", "human") # refresh + t[0] = 1004.0 + assert [e["slug"] for e in r.list("c1")["human"]] == ["jay"] # still alive (refreshed at 1002) + + +# ── New phase/detail tests ───────────────────────────────────────────────────── + +@pytest.mark.asyncio +async def test_mark_with_phase_and_detail(): + reg = TypingRegistry() + reg.mark("c1", "tom", "agent", phase="tool", detail="web_search") + result = reg.list("c1") + agents = result["agent"] + assert len(agents) == 1 + entry = agents[0] + assert entry["slug"] == "tom" + assert entry["phase"] == "tool" + assert entry["detail"] == "web_search" + + +@pytest.mark.asyncio +async def test_mark_without_phase_defaults_to_thinking(): + reg = TypingRegistry() + reg.mark("c1", "tom", "agent") + result = reg.list("c1") + entry = result["agent"][0] + assert entry["phase"] == "thinking" + assert entry["detail"] is None + + +@pytest.mark.asyncio +async def test_mark_overwrites_phase_last_writer_wins(): + reg = TypingRegistry() + reg.mark("c1", "tom", "agent", phase="thinking") + reg.mark("c1", "tom", "agent", phase="tool", detail="search") + entry = reg.list("c1")["agent"][0] + assert entry["phase"] == "tool" + assert entry["detail"] == "search" + + +@pytest.mark.asyncio +async def test_human_entry_shape_matches_agent(): + reg = TypingRegistry() + reg.mark("c1", "jay", "human") + entry = reg.list("c1")["human"][0] + assert entry["slug"] == "jay" + assert entry.get("phase") is None + + +# ── HTTP endpoint tests ──────────────────────────────────────────────────────── + +import pytest +import yaml +from httpx import AsyncClient, ASGITransport +from tinyagentos.app import create_app + + +def _make_app(tmp_path): + cfg = { + "server": {"host": "0.0.0.0", "port": 6969}, + "backends": [], + "qmd": {"url": "http://localhost:7832"}, + "agents": [{"name": "tom", "host": "localhost", "color": "#fff"}], + "metrics": {"poll_interval": 30, "retention_days": 30}, + } + (tmp_path / "config.yaml").write_text(yaml.dump(cfg)) + (tmp_path / ".setup_complete").touch() + return create_app(data_dir=tmp_path) + + +async def _setup_client(tmp_path): + app = _make_app(tmp_path) + await app.state.chat_channels.init() + await app.state.chat_messages.init() + token = app.state.auth.get_local_token() + client = AsyncClient( + transport=ASGITransport(app=app), + base_url="http://test", + headers={"Authorization": f"Bearer {token}"}, + ) + return app, client, token + + +@pytest.mark.asyncio +async def test_post_typing_marks_registry(tmp_path): + app, client, _token = await _setup_client(tmp_path) + async with client: + store = app.state.chat_channels + ch = await store.create_channel( + name="g", type="group", description="", topic="", + members=["user", "tom"], settings={}, created_by="user", + ) + ch_id = ch["id"] if isinstance(ch, dict) else ch + + r = await client.post( + f"/api/chat/channels/{ch_id}/typing", + json={"author_id": "user"}, + ) + assert r.status_code == 200 + listing = app.state.typing.list(ch_id) + assert "user" in [e["slug"] for e in listing["human"]] + + +@pytest.mark.asyncio +async def test_post_thinking_start_marks_registry(tmp_path): + app, client, token = await _setup_client(tmp_path) + async with client: + store = app.state.chat_channels + ch = await store.create_channel( + name="g", type="group", description="", topic="", + members=["user", "tom"], settings={}, created_by="user", + ) + ch_id = ch["id"] if isinstance(ch, dict) else ch + + r = await client.post( + f"/api/chat/channels/{ch_id}/thinking", + json={"slug": "tom", "state": "start"}, + ) + assert r.status_code == 200 + listing = app.state.typing.list(ch_id) + assert "tom" in [e["slug"] for e in listing["agent"]] + + # end clears + r = await client.post( + f"/api/chat/channels/{ch_id}/thinking", + json={"slug": "tom", "state": "end"}, + ) + assert r.status_code == 200 + listing = app.state.typing.list(ch_id) + assert "tom" not in [e["slug"] for e in listing["agent"]] + + +@pytest.mark.asyncio +async def test_post_thinking_requires_bearer(tmp_path): + app = _make_app(tmp_path) + async with AsyncClient(transport=ASGITransport(app=app), base_url="http://test") as client: + r = await client.post( + "/api/chat/channels/x/thinking", + json={"slug": "tom", "state": "start"}, + ) + assert r.status_code == 401 + + +@pytest.mark.asyncio +async def test_get_typing_returns_current_state(tmp_path): + app, client, _token = await _setup_client(tmp_path) + async with client: + store = app.state.chat_channels + ch = await store.create_channel( + name="g", type="group", description="", topic="", + members=["user", "tom", "don"], settings={}, created_by="user", + ) + ch_id = ch["id"] if isinstance(ch, dict) else ch + app.state.typing.mark(ch_id, "user", "human") + app.state.typing.mark(ch_id, "tom", "agent") + + r = await client.get(f"/api/chat/channels/{ch_id}/typing") + assert r.status_code == 200 + body = r.json() + assert [e["slug"] for e in body["human"]] == ["user"] + assert [e["slug"] for e in body["agent"]] == ["tom"] diff --git a/tinyagentos/chat/typing_registry.py b/tinyagentos/chat/typing_registry.py index 7cd1c5b0..976d234f 100644 --- a/tinyagentos/chat/typing_registry.py +++ b/tinyagentos/chat/typing_registry.py @@ -7,6 +7,7 @@ from __future__ import annotations import time +from dataclasses import dataclass from typing import Literal @@ -15,35 +16,63 @@ def _now() -> float: Kind = Literal["human", "agent"] +TypingPhase = Literal["thinking", "tool", "reading", "writing", "searching", "planning"] + + +@dataclass +class _Entry: + kind: Kind + expires_at: float + phase: TypingPhase | None + detail: str | None class TypingRegistry: def __init__(self, human_ttl: int = 3, agent_ttl: int = 45) -> None: self._ttls: dict[str, int] = {"human": human_ttl, "agent": agent_ttl} - # (channel_id, slug) -> (kind, expires_at) - self._entries: dict[tuple[str, str], tuple[Kind, float]] = {} + self._entries: dict[tuple[str, str], _Entry] = {} - def mark(self, channel_id: str, slug: str, kind: Kind) -> None: + def mark( + self, + channel_id: str, + slug: str, + kind: Kind, + *, + phase: TypingPhase | None = None, + detail: str | None = None, + ) -> None: now = _now() ttl = self._ttls[kind] - self._entries[(channel_id, slug)] = (kind, now + ttl) + resolved_phase: TypingPhase | None = ( + phase if phase is not None else ("thinking" if kind == "agent" else None) + ) + self._entries[(channel_id, slug)] = _Entry( + kind=kind, + expires_at=now + ttl, + phase=resolved_phase, + detail=detail, + ) def clear(self, channel_id: str, slug: str) -> None: self._entries.pop((channel_id, slug), None) - def list(self, channel_id: str) -> dict[str, list[str]]: + def list(self, channel_id: str) -> dict[str, list[dict]]: now = _now() - out: dict[str, list[str]] = {"human": [], "agent": []} + out: dict[str, list[dict]] = {"human": [], "agent": []} stale: list[tuple[str, str]] = [] - for (ch, slug), (kind, expires_at) in self._entries.items(): + for (ch, slug), entry in self._entries.items(): if ch != channel_id: continue - if expires_at < now: + if entry.expires_at < now: stale.append((ch, slug)) continue - out[kind].append(slug) + out[entry.kind].append({ + "slug": slug, + "phase": entry.phase, + "detail": entry.detail, + }) for k in stale: self._entries.pop(k, None) - out["human"].sort() - out["agent"].sort() + out["human"].sort(key=lambda e: e["slug"]) + out["agent"].sort(key=lambda e: e["slug"]) return out From 3a95f23ebb2746dbd222e62e3cd04c2a3a82e385 Mon Sep 17 00:00:00 2001 From: jaylfc Date: Mon, 20 Apr 2026 13:59:26 +0100 Subject: [PATCH 3/9] feat(chat): POST /thinking accepts phase + detail with enum validation --- tests/test_chat_phase.py | 68 ++++++++++++++++++++++++++++++++++++++ tinyagentos/routes/chat.py | 12 ++++++- 2 files changed, 79 insertions(+), 1 deletion(-) create mode 100644 tests/test_chat_phase.py diff --git a/tests/test_chat_phase.py b/tests/test_chat_phase.py new file mode 100644 index 00000000..189b6234 --- /dev/null +++ b/tests/test_chat_phase.py @@ -0,0 +1,68 @@ +import pytest +import yaml +from httpx import AsyncClient, ASGITransport + + +def _make_phase_app(tmp_path): + cfg = { + "server": {"host": "0.0.0.0", "port": 6969}, + "backends": [], + "qmd": {"url": "http://localhost:7832"}, + "agents": [], + "metrics": {"poll_interval": 30, "retention_days": 30}, + } + (tmp_path / "config.yaml").write_text(yaml.dump(cfg)) + (tmp_path / ".setup_complete").touch() + from tinyagentos.app import create_app + return create_app(data_dir=tmp_path) + + +async def _client_with_bearer(tmp_path): + app = _make_phase_app(tmp_path) + await app.state.chat_channels.init() + await app.state.chat_messages.init() + token = app.state.auth.get_local_token() + client = AsyncClient( + transport=ASGITransport(app=app), + base_url="http://test", + headers={"Authorization": f"Bearer {token}"}, + ) + return app, client + + +@pytest.mark.asyncio +async def test_thinking_with_valid_phase_200(tmp_path): + app, client = await _client_with_bearer(tmp_path) + async with client: + r = await client.post( + "/api/chat/channels/c1/thinking", + json={"slug": "tom", "state": "start", "phase": "tool", "detail": "web_search"}, + ) + assert r.status_code == 200, r.json() + listing = app.state.typing.list("c1") + assert listing["agent"][0]["phase"] == "tool" + assert listing["agent"][0]["detail"] == "web_search" + + +@pytest.mark.asyncio +async def test_thinking_with_invalid_phase_400(tmp_path): + app, client = await _client_with_bearer(tmp_path) + async with client: + r = await client.post( + "/api/chat/channels/c1/thinking", + json={"slug": "tom", "state": "start", "phase": "not-a-phase"}, + ) + assert r.status_code == 400 + + +@pytest.mark.asyncio +async def test_thinking_without_phase_defaults_thinking(tmp_path): + app, client = await _client_with_bearer(tmp_path) + async with client: + r = await client.post( + "/api/chat/channels/c1/thinking", + json={"slug": "tom", "state": "start"}, + ) + assert r.status_code == 200 + listing = app.state.typing.list("c1") + assert listing["agent"][0]["phase"] == "thinking" diff --git a/tinyagentos/routes/chat.py b/tinyagentos/routes/chat.py index 081ff23c..f12a2442 100644 --- a/tinyagentos/routes/chat.py +++ b/tinyagentos/routes/chat.py @@ -845,6 +845,8 @@ async def list_wants_reply(channel_id: str, request: Request): return JSONResponse({"slugs": reg.list(channel_id)}) +VALID_PHASES = {"thinking", "tool", "reading", "writing", "searching", "planning"} + # ── Typing / thinking indicators ───────────────────────────────────────────── @router.post("/api/chat/channels/{channel_id}/typing") @@ -882,12 +884,18 @@ async def post_thinking(channel_id: str, body: dict, request: Request): state = (body or {}).get("state") if not slug or state not in ("start", "end"): return JSONResponse({"error": "slug and state in {start,end} required"}, status_code=400) + + phase = (body or {}).get("phase") + if phase is not None and phase not in VALID_PHASES: + return JSONResponse({"error": f"invalid phase; must be one of {sorted(VALID_PHASES)}"}, status_code=400) + detail = (body or {}).get("detail") + reg = getattr(request.app.state, "typing", None) hub = getattr(request.app.state, "chat_hub", None) if reg is None: return JSONResponse({"error": "typing registry not configured"}, status_code=503) if state == "start": - reg.mark(channel_id, slug, "agent") + reg.mark(channel_id, slug, "agent", phase=phase, detail=detail) else: reg.clear(channel_id, slug) if hub is not None: @@ -895,6 +903,8 @@ async def post_thinking(channel_id: str, body: dict, request: Request): "type": "thinking", "slug": slug, "state": state, + "phase": phase if state == "start" else None, + "detail": detail if state == "start" else None, }) return JSONResponse({"ok": True}, status_code=200) From 3e852d750d6093430f088278bd6c763344c661a2 Mon Sep 17 00:00:00 2001 From: jaylfc Date: Mon, 20 Apr 2026 14:01:28 +0100 Subject: [PATCH 4/9] feat(chat): TypingFooter shows phase-aware labels + icons --- desktop/src/apps/MessagesApp.tsx | 18 ++++--- desktop/src/apps/chat/TypingFooter.tsx | 48 ++++++++++++++--- .../apps/chat/__tests__/TypingFooter.test.tsx | 51 +++++++++++++++++-- 3 files changed, 102 insertions(+), 15 deletions(-) diff --git a/desktop/src/apps/MessagesApp.tsx b/desktop/src/apps/MessagesApp.tsx index 925c59f5..3fc3b3c4 100644 --- a/desktop/src/apps/MessagesApp.tsx +++ b/desktop/src/apps/MessagesApp.tsx @@ -35,7 +35,7 @@ import { resolveAgentEmoji } from "@/lib/agent-emoji"; import { ChannelSettingsPanel } from "./chat/ChannelSettingsPanel"; import { AgentContextMenu } from "./chat/AgentContextMenu"; import { SlashMenu, type SlashCommandsBySlug } from "./chat/SlashMenu"; -import { TypingFooter } from "./chat/TypingFooter"; +import { TypingFooter, type AgentTyping } from "./chat/TypingFooter"; import { useTypingEmitter } from "@/lib/use-typing-emitter"; import { MessageHoverActions } from "./chat/MessageHoverActions"; import { ThreadIndicator } from "./chat/ThreadIndicator"; @@ -256,7 +256,7 @@ export function MessagesApp({ windowId: _windowId, title }: { windowId: string; >(null); const [slashCommands, setSlashCommands] = useState({}); const [typingHumans, setTypingHumans] = useState([]); - const [typingAgents, setTypingAgents] = useState([]); + const [typingAgents, setTypingAgents] = useState([]); const [sendError, setSendError] = useState(null); const [hoveredMessageId, setHoveredMessageId] = useState(null); const [pendingAttachments, setPendingAttachments] = useState([]); @@ -387,9 +387,12 @@ export function MessagesApp({ windowId: _windowId, title }: { windowId: string; } if (data.type === "thinking") { if (data.state === "start") { - setTypingAgents((prev) => prev.includes(data.slug) ? prev : [...prev, data.slug]); + setTypingAgents((prev) => { + const without = prev.filter((a) => a.slug !== data.slug); + return [...without, { slug: data.slug, phase: data.phase ?? null, detail: data.detail ?? null }]; + }); } else { - setTypingAgents((prev) => prev.filter((s) => s !== data.slug)); + setTypingAgents((prev) => prev.filter((a) => a.slug !== data.slug)); } return; } @@ -428,9 +431,12 @@ export function MessagesApp({ windowId: _windowId, title }: { windowId: string; // Legacy WS typing (agent only) — route into typingAgents for TypingFooter // (human typing is handled by the phase-2a branch above) if ((data.user_type ?? "user") !== "agent") break; - setTypingAgents((prev) => prev.includes(data.user_id) ? prev : [...prev, data.user_id]); + setTypingAgents((prev) => { + const without = prev.filter((a) => a.slug !== data.user_id); + return [...without, { slug: data.user_id, phase: null, detail: null }]; + }); setTimeout(() => { - setTypingAgents((prev) => prev.filter((s) => s !== data.user_id)); + setTypingAgents((prev) => prev.filter((a) => a.slug !== data.user_id)); }, 5000); break; diff --git a/desktop/src/apps/chat/TypingFooter.tsx b/desktop/src/apps/chat/TypingFooter.tsx index cc19dacb..1cd15d4e 100644 --- a/desktop/src/apps/chat/TypingFooter.tsx +++ b/desktop/src/apps/chat/TypingFooter.tsx @@ -4,13 +4,22 @@ * Caller feeds in live arrays — they're empty when nothing is active * and the component renders nothing. */ + +type TypingPhase = "thinking" | "tool" | "reading" | "writing" | "searching" | "planning"; + +export interface AgentTyping { + slug: string; + phase?: TypingPhase | null; + detail?: string | null; +} + export function TypingFooter({ humans, agents, selfId = "user", }: { humans: string[]; - agents: string[]; + agents: AgentTyping[]; selfId?: string; }) { const others = humans.filter((h) => h !== selfId); @@ -19,7 +28,6 @@ export function TypingFooter({ if (!hasHumans && !hasAgents) return null; const humanLine = formatHumansTyping(others); - const agentLine = formatAgentsThinking(agents); return (
{humanLine && {humanLine}} - {agentLine && {agentLine}} + {agents.map((a) => { + const { icon, text } = phaseLabel(a.phase, a.detail); + return ( + + {icon} @{a.slug} is {text}… + + ); + })}
); } @@ -39,7 +54,28 @@ function formatHumansTyping(names: string[]): string | null { return `${names[0]} and ${names.length - 1} others are typing…`; } -function formatAgentsThinking(slugs: string[]): string | null { - if (slugs.length === 0) return null; - return slugs.map((s) => `${s} is thinking…`).join(" · "); +function phaseLabel( + phase?: TypingPhase | null, + detail?: string | null, +): { icon: string; text: string } { + const d = detail + ? detail.length > 40 + ? detail.slice(0, 39) + "…" + : detail + : null; + switch (phase) { + case "tool": + return { icon: "🔧", text: d ? `using ${d}` : "using a tool" }; + case "reading": + return { icon: "📖", text: d ? `reading ${d}` : "reading" }; + case "writing": + return { icon: "✏️", text: d ? `writing ${d}` : "writing" }; + case "searching": + return { icon: "🔍", text: d ? `searching ${d}` : "searching" }; + case "planning": + return { icon: "📋", text: "planning" }; + case "thinking": + default: + return { icon: "💭", text: "thinking" }; + } } diff --git a/desktop/src/apps/chat/__tests__/TypingFooter.test.tsx b/desktop/src/apps/chat/__tests__/TypingFooter.test.tsx index 675414d9..0d6210cc 100644 --- a/desktop/src/apps/chat/__tests__/TypingFooter.test.tsx +++ b/desktop/src/apps/chat/__tests__/TypingFooter.test.tsx @@ -19,8 +19,53 @@ describe("TypingFooter", () => { const { container } = render(); expect(container.firstChild).toBeNull(); }); - it("joins multiple agents with middle dot", () => { - render(); - expect(screen.getByText("tom is thinking… · don is thinking…")).toBeInTheDocument(); + it("shows default thinking label for agent with no phase", () => { + render(); + expect(screen.getByText(/tom/i)).toBeInTheDocument(); + expect(screen.getByText(/thinking/i)).toBeInTheDocument(); + }); + it("renders 'using X' for tool phase", () => { + render( + , + ); + expect(screen.getByText(/tom/i)).toBeInTheDocument(); + expect(screen.getByText(/using web_search/i)).toBeInTheDocument(); + }); + it("renders 'writing X' for writing phase", () => { + render( + , + ); + expect(screen.getByText(/writing payment\.py/i)).toBeInTheDocument(); + }); + it("truncates detail longer than 40 chars", () => { + const longDetail = "a".repeat(60); + render( + , + ); + const text = screen.getByText(/using/i).textContent ?? ""; + expect(text.length).toBeLessThanOrEqual(60); + expect(text).toContain("…"); + }); + it("falls back to 'thinking' for unknown phase", () => { + render( + , + ); + expect(screen.getByText(/thinking/i)).toBeInTheDocument(); }); }); From 2aaa47f66086a1b0cef69ff8da399bafda3051a6 Mon Sep 17 00:00:00 2001 From: jaylfc Date: Mon, 20 Apr 2026 14:03:11 +0100 Subject: [PATCH 5/9] feat(bridges): _thinking helper accepts phase/detail; emit per-framework where exposed --- tinyagentos/scripts/install_hermes.sh | 10 ++++++++-- tinyagentos/scripts/install_langroid.sh | 10 ++++++++-- tinyagentos/scripts/install_openai-agents-sdk.sh | 10 ++++++++-- tinyagentos/scripts/install_openai_agents_sdk.sh | 10 ++++++++-- tinyagentos/scripts/install_pocketflow.sh | 10 ++++++++-- tinyagentos/scripts/install_smolagents.sh | 10 ++++++++-- 6 files changed, 48 insertions(+), 12 deletions(-) diff --git a/tinyagentos/scripts/install_hermes.sh b/tinyagentos/scripts/install_hermes.sh index 72a0e621..3d4c20e8 100755 --- a/tinyagentos/scripts/install_hermes.sh +++ b/tinyagentos/scripts/install_hermes.sh @@ -170,13 +170,19 @@ def _suppress(reply, force): return None if stripped == "no_response" else reply -async def _thinking(c: httpx.AsyncClient, ch_id, state: str) -> None: +async def _thinking(c: httpx.AsyncClient, ch_id, state: str, *, + phase: str | None = None, detail: str | None = None) -> None: if not ch_id: return + body = {"slug": AGENT_NAME, "state": state} + if phase is not None: + body["phase"] = phase + if detail is not None: + body["detail"] = detail try: await c.post( f"{BRIDGE_URL}/api/chat/channels/{ch_id}/thinking", - json={"slug": AGENT_NAME, "state": state}, + json=body, headers={"Authorization": f"Bearer {LOCAL_TOKEN}"}, timeout=5, ) diff --git a/tinyagentos/scripts/install_langroid.sh b/tinyagentos/scripts/install_langroid.sh index 5033bc23..b4ab4496 100755 --- a/tinyagentos/scripts/install_langroid.sh +++ b/tinyagentos/scripts/install_langroid.sh @@ -50,13 +50,19 @@ def _suppress(reply, force): stripped = (reply or "").strip().lower().strip(".!,;:") return None if stripped == "no_response" else reply -async def _thinking(c: httpx.AsyncClient, ch_id, state: str) -> None: +async def _thinking(c: httpx.AsyncClient, ch_id, state: str, *, + phase: str | None = None, detail: str | None = None) -> None: if not ch_id: return + body = {"slug": AGENT_NAME, "state": state} + if phase is not None: + body["phase"] = phase + if detail is not None: + body["detail"] = detail try: await c.post( f"{BRIDGE_URL}/api/chat/channels/{ch_id}/thinking", - json={"slug": AGENT_NAME, "state": state}, + json=body, headers={"Authorization": f"Bearer {LOCAL_TOKEN}"}, timeout=5, ) diff --git a/tinyagentos/scripts/install_openai-agents-sdk.sh b/tinyagentos/scripts/install_openai-agents-sdk.sh index 78412e92..dc6e6185 100755 --- a/tinyagentos/scripts/install_openai-agents-sdk.sh +++ b/tinyagentos/scripts/install_openai-agents-sdk.sh @@ -52,13 +52,19 @@ def _suppress(reply, force): stripped = (reply or "").strip().lower().strip(".!,;:") return None if stripped == "no_response" else reply -async def _thinking(c: httpx.AsyncClient, ch_id, state: str) -> None: +async def _thinking(c: httpx.AsyncClient, ch_id, state: str, *, + phase: str | None = None, detail: str | None = None) -> None: if not ch_id: return + body = {"slug": AGENT_NAME, "state": state} + if phase is not None: + body["phase"] = phase + if detail is not None: + body["detail"] = detail try: await c.post( f"{BRIDGE_URL}/api/chat/channels/{ch_id}/thinking", - json={"slug": AGENT_NAME, "state": state}, + json=body, headers={"Authorization": f"Bearer {LOCAL_TOKEN}"}, timeout=5, ) diff --git a/tinyagentos/scripts/install_openai_agents_sdk.sh b/tinyagentos/scripts/install_openai_agents_sdk.sh index 78412e92..dc6e6185 100755 --- a/tinyagentos/scripts/install_openai_agents_sdk.sh +++ b/tinyagentos/scripts/install_openai_agents_sdk.sh @@ -52,13 +52,19 @@ def _suppress(reply, force): stripped = (reply or "").strip().lower().strip(".!,;:") return None if stripped == "no_response" else reply -async def _thinking(c: httpx.AsyncClient, ch_id, state: str) -> None: +async def _thinking(c: httpx.AsyncClient, ch_id, state: str, *, + phase: str | None = None, detail: str | None = None) -> None: if not ch_id: return + body = {"slug": AGENT_NAME, "state": state} + if phase is not None: + body["phase"] = phase + if detail is not None: + body["detail"] = detail try: await c.post( f"{BRIDGE_URL}/api/chat/channels/{ch_id}/thinking", - json={"slug": AGENT_NAME, "state": state}, + json=body, headers={"Authorization": f"Bearer {LOCAL_TOKEN}"}, timeout=5, ) diff --git a/tinyagentos/scripts/install_pocketflow.sh b/tinyagentos/scripts/install_pocketflow.sh index c24d81ce..a6607c28 100755 --- a/tinyagentos/scripts/install_pocketflow.sh +++ b/tinyagentos/scripts/install_pocketflow.sh @@ -50,13 +50,19 @@ def _suppress(reply, force): stripped = (reply or "").strip().lower().strip(".!,;:") return None if stripped == "no_response" else reply -async def _thinking(c: httpx.AsyncClient, ch_id, state: str) -> None: +async def _thinking(c: httpx.AsyncClient, ch_id, state: str, *, + phase: str | None = None, detail: str | None = None) -> None: if not ch_id: return + body = {"slug": AGENT_NAME, "state": state} + if phase is not None: + body["phase"] = phase + if detail is not None: + body["detail"] = detail try: await c.post( f"{BRIDGE_URL}/api/chat/channels/{ch_id}/thinking", - json={"slug": AGENT_NAME, "state": state}, + json=body, headers={"Authorization": f"Bearer {LOCAL_TOKEN}"}, timeout=5, ) diff --git a/tinyagentos/scripts/install_smolagents.sh b/tinyagentos/scripts/install_smolagents.sh index 2a2c8aab..e304923b 100755 --- a/tinyagentos/scripts/install_smolagents.sh +++ b/tinyagentos/scripts/install_smolagents.sh @@ -60,13 +60,19 @@ def _suppress(reply, force): stripped = (reply or "").strip().lower().strip(".!,;:") return None if stripped == "no_response" else reply -async def _thinking(c: httpx.AsyncClient, ch_id, state: str) -> None: +async def _thinking(c: httpx.AsyncClient, ch_id, state: str, *, + phase: str | None = None, detail: str | None = None) -> None: if not ch_id: return + body = {"slug": AGENT_NAME, "state": state} + if phase is not None: + body["phase"] = phase + if detail is not None: + body["detail"] = detail try: await c.post( f"{BRIDGE_URL}/api/chat/channels/{ch_id}/thinking", - json={"slug": AGENT_NAME, "state": state}, + json=body, headers={"Authorization": f"Bearer {LOCAL_TOKEN}"}, timeout=5, ) From 50060a41c5fb4500f58a3601cee469d439ffc4ba Mon Sep 17 00:00:00 2001 From: jaylfc Date: Mon, 20 Apr 2026 14:11:01 +0100 Subject: [PATCH 6/9] fix(tests): update test_chat_typing.py assertions to new dict shape --- tests/test_chat_typing.py | 19 ++++++++++--------- 1 file changed, 10 insertions(+), 9 deletions(-) diff --git a/tests/test_chat_typing.py b/tests/test_chat_typing.py index 24cdd4a0..9b53de98 100644 --- a/tests/test_chat_typing.py +++ b/tests/test_chat_typing.py @@ -10,14 +10,14 @@ def test_empty_registry_returns_empty_lists(): def test_mark_human_appears_in_list(): r = TypingRegistry() r.mark("c1", "jay", "human") - assert r.list("c1")["human"] == ["jay"] + assert [e["slug"] for e in r.list("c1")["human"]] == ["jay"] assert r.list("c1")["agent"] == [] def test_mark_agent_appears_in_list(): r = TypingRegistry() r.mark("c1", "tom", "agent") - assert r.list("c1")["agent"] == ["tom"] + assert [e["slug"] for e in r.list("c1")["agent"]] == ["tom"] def test_clear_removes_entry(): @@ -43,7 +43,7 @@ def test_human_ttl_expires(monkeypatch): t = [1000.0] monkeypatch.setattr("tinyagentos.chat.typing_registry._now", lambda: t[0]) r.mark("c1", "jay", "human") - assert r.list("c1")["human"] == ["jay"] + assert [e["slug"] for e in r.list("c1")["human"]] == ["jay"] t[0] = 1003.1 assert r.list("c1")["human"] == [] @@ -53,7 +53,7 @@ def test_agent_ttl_expires(monkeypatch): t = [1000.0] monkeypatch.setattr("tinyagentos.chat.typing_registry._now", lambda: t[0]) r.mark("c1", "tom", "agent") - assert r.list("c1")["agent"] == ["tom"] + assert [e["slug"] for e in r.list("c1")["agent"]] == ["tom"] t[0] = 1045.1 assert r.list("c1")["agent"] == [] @@ -66,7 +66,7 @@ def test_mark_refreshes_ttl(monkeypatch): t[0] = 1002.0 r.mark("c1", "jay", "human") # refresh t[0] = 1004.0 - assert r.list("c1")["human"] == ["jay"] # still alive (refreshed at 1002) + assert [e["slug"] for e in r.list("c1")["human"]] == ["jay"] # still alive (refreshed at 1002) # ── HTTP endpoint tests ──────────────────────────────────────────────────────── @@ -120,7 +120,7 @@ async def test_post_typing_marks_registry(tmp_path): ) assert r.status_code == 200 listing = app.state.typing.list(ch_id) - assert "user" in listing["human"] + assert "user" in [e["slug"] for e in listing["human"]] @pytest.mark.asyncio @@ -140,7 +140,7 @@ async def test_post_thinking_start_marks_registry(tmp_path): ) assert r.status_code == 200 listing = app.state.typing.list(ch_id) - assert "tom" in listing["agent"] + assert "tom" in [e["slug"] for e in listing["agent"]] # end clears r = await client.post( @@ -149,7 +149,7 @@ async def test_post_thinking_start_marks_registry(tmp_path): ) assert r.status_code == 200 listing = app.state.typing.list(ch_id) - assert "tom" not in listing["agent"] + assert "tom" not in [e["slug"] for e in listing["agent"]] @pytest.mark.asyncio @@ -179,4 +179,5 @@ async def test_get_typing_returns_current_state(tmp_path): r = await client.get(f"/api/chat/channels/{ch_id}/typing") assert r.status_code == 200 body = r.json() - assert body == {"human": ["user"], "agent": ["tom"]} + assert [e["slug"] for e in body["human"]] == ["user"] + assert [e["slug"] for e in body["agent"]] == ["tom"] From e976bcead80c2660fa6fd2f24d45746133c4eec7 Mon Sep 17 00:00:00 2001 From: jaylfc Date: Mon, 20 Apr 2026 14:12:12 +0100 Subject: [PATCH 7/9] build: rebuild desktop bundle for chat Phase 3 typing labels --- .../desktop/assets/{MCPApp-Ds2pyPo2.js => MCPApp-DBMY1x8q.js} | 2 +- static/desktop/assets/MessagesApp-CkhTvSE9.js | 1 + static/desktop/assets/MessagesApp-D7Umpsei.js | 1 - .../{ProvidersApp-BEdnJTlt.js => ProvidersApp-BZ0Cnn9e.js} | 2 +- .../{SettingsApp-3EqaoTva.js => SettingsApp-CR8h0q_c.js} | 2 +- static/desktop/assets/{chat-CnrplGIN.js => chat-R5uusfVD.js} | 4 ++-- static/desktop/assets/{main-w-WDDs5-.js => main-FOmUFQfu.js} | 4 ++-- static/desktop/chat.html | 2 +- static/desktop/index.html | 2 +- 9 files changed, 10 insertions(+), 10 deletions(-) rename static/desktop/assets/{MCPApp-Ds2pyPo2.js => MCPApp-DBMY1x8q.js} (99%) create mode 100644 static/desktop/assets/MessagesApp-CkhTvSE9.js delete mode 100644 static/desktop/assets/MessagesApp-D7Umpsei.js rename static/desktop/assets/{ProvidersApp-BEdnJTlt.js => ProvidersApp-BZ0Cnn9e.js} (99%) rename static/desktop/assets/{SettingsApp-3EqaoTva.js => SettingsApp-CR8h0q_c.js} (99%) rename static/desktop/assets/{chat-CnrplGIN.js => chat-R5uusfVD.js} (94%) rename static/desktop/assets/{main-w-WDDs5-.js => main-FOmUFQfu.js} (99%) diff --git a/static/desktop/assets/MCPApp-Ds2pyPo2.js b/static/desktop/assets/MCPApp-DBMY1x8q.js similarity index 99% rename from static/desktop/assets/MCPApp-Ds2pyPo2.js rename to static/desktop/assets/MCPApp-DBMY1x8q.js index 0239c277..bfa3d824 100644 --- a/static/desktop/assets/MCPApp-Ds2pyPo2.js +++ b/static/desktop/assets/MCPApp-DBMY1x8q.js @@ -1,2 +1,2 @@ -import{r as l,j as e}from"./vendor-react-l6srOxy7.js";import{B as k,C as T,I as E,T as Q,L as R,S as ee}from"./toolbar-UW6q5pkx.js";import{M as te}from"./MobileSplitView-B-4MQO2C.js";import{a as se,b as ae,g as le}from"./main-w-WDDs5-.js";import{ao as I,V as $,al as ne,a5 as ie,aN as re,R as ce,y as M,g as O,aG as oe,X as U,f as D,aw as de,r as xe}from"./vendor-icons--yQaiqiL.js";import"./vendor-radix-BhM7AEEG.js";import"./vendor-layout-B-pp9n1f.js";import"./tokens-BKHlNYpw.js";import"./vendor-codemirror-aNcHammg.js";const he={running:"bg-emerald-500",stopped:"bg-zinc-500",failed:"bg-red-500",installing:"bg-amber-500"},F={running:"bg-emerald-500/20 text-emerald-400",stopped:"bg-zinc-500/20 text-zinc-400",failed:"bg-red-500/20 text-red-400",installing:"bg-amber-500/20 text-amber-400"},P={running:"Running",stopped:"Stopped",failed:"Failed",installing:"Installing"},me={stdio:"bg-blue-500/20 text-blue-300",sse:"bg-violet-500/20 text-violet-300",ws:"bg-teal-500/20 text-teal-300"},pe=["running","installing","failed","stopped"];function ue(t){const n={running:[],stopped:[],failed:[],installing:[]};for(const o of t)n[o.status].push(o);return n}function G(t){return new Date(t*1e3).toLocaleTimeString(void 0,{hour:"2-digit",minute:"2-digit"})}function fe({server:t,attachments:n,onConfirm:o,onClose:i,loading:p}){const[m,r]=l.useState(""),b=n.length>=3,u=!b||m===t.id,g=l.useRef(null);l.useEffect(()=>{var h;(h=g.current)==null||h.focus()},[]);const f=n.map(h=>h.scope_kind==="all"?"all agents":h.scope_kind==="agent"?`agent: ${h.scope_id}`:`group: ${h.scope_id}`);return e.jsx("div",{className:"fixed inset-0 z-50 flex items-center justify-center bg-black/60 backdrop-blur-sm",role:"dialog","aria-modal":"true","aria-label":`Uninstall ${t.name}`,children:e.jsxs("div",{className:"bg-[#1a1a2e] border border-white/10 rounded-2xl p-6 w-full max-w-md shadow-2xl",children:[e.jsxs("div",{className:"flex items-start gap-3 mb-4",children:[e.jsx("div",{className:"p-2 rounded-lg bg-red-500/15 mt-0.5",children:e.jsx(xe,{size:20,className:"text-red-400","aria-hidden":!0})}),e.jsxs("div",{className:"flex-1 min-w-0",children:[e.jsxs("h2",{className:"text-base font-semibold text-shell-text",children:["Uninstall ",t.name,"?"]}),e.jsxs("p",{className:"text-xs text-shell-text-secondary mt-0.5",children:["v",t.version]})]}),e.jsx("button",{onClick:i,className:"text-shell-text-secondary hover:text-shell-text transition-colors","aria-label":"Close",children:e.jsx(U,{size:16})})]}),e.jsxs("div",{className:"space-y-2 mb-4",children:[n.length>0&&e.jsxs("div",{className:"text-sm text-shell-text-secondary bg-white/[0.03] rounded-lg px-3 py-2.5 border border-white/[0.06]",children:[e.jsxs("span",{className:"font-medium text-red-400",children:[n.length," attachment",n.length!==1?"s":""]})," will be revoked:"," ",e.jsx("span",{className:"text-shell-text",children:f.join(", ")})]}),e.jsx("p",{className:"text-xs text-shell-text-secondary",children:"This will stop the server process, remove all attachments, delete env secrets, and remove files from disk. This cannot be undone."})]}),b&&e.jsxs("div",{className:"mb-4",children:[e.jsxs(R,{htmlFor:"uninstall-confirm-input",className:"text-xs mb-1.5 block text-shell-text-secondary",children:["Type ",e.jsx("span",{className:"font-mono font-semibold text-shell-text",children:t.id})," to confirm"]}),e.jsx(E,{ref:g,id:"uninstall-confirm-input",value:m,onChange:h=>r(h.target.value),placeholder:t.id,className:"font-mono","aria-label":`Type ${t.id} to confirm uninstall`})]}),e.jsxs("div",{className:"flex gap-2 justify-end",children:[e.jsx(k,{variant:"outline",size:"sm",onClick:i,disabled:p,children:"Cancel"}),e.jsxs(k,{variant:"destructive",size:"sm",onClick:o,disabled:!u||p,"aria-label":`Confirm uninstall ${t.name}`,children:[p?e.jsx($,{size:14,className:"animate-spin mr-1"}):e.jsx(M,{size:14,className:"mr-1"}),"Uninstall"]})]})]})})}function je({serverId:t,agents:n,groups:o,capabilities:i,onSaved:p,onClose:m}){const[r,b]=l.useState("all"),[u,g]=l.useState(""),[f,h]=l.useState(""),[N,j]=l.useState(!0),[d,y]=l.useState(new Set),[S,s]=l.useState([]),[x,v]=l.useState(!1),[c,A]=l.useState(null),z=i.filter(a=>a.type==="tool"),_=n.filter(a=>(a.display_name||a.name).toLowerCase().includes(u.toLowerCase())),B=o.filter(a=>a.name.toLowerCase().includes(u.toLowerCase()));function V(a){y(w=>{const C=new Set(w);return C.has(a)?C.delete(a):C.add(a),C})}function H(){s(a=>[...a,""])}function K(a,w){s(C=>C.map((L,Z)=>Z===a?w:L))}function W(a){s(w=>w.filter((C,L)=>L!==a))}async function q(){if(r!=="all"&&!f){A("Select a specific agent or group.");return}v(!0),A(null);try{const a={scope_kind:r,scope_id:r==="all"?void 0:f,allowed_tools:N?[]:Array.from(d),allowed_resources:S.filter(C=>C.trim())},w=await fetch(`/api/mcp/servers/${encodeURIComponent(t)}/permissions`,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify(a)});if(!w.ok){const C=await w.json().catch(()=>({detail:"Failed to attach"}));A(C.detail??"Failed to attach"),v(!1);return}p()}catch{A("Network error"),v(!1)}}const X=r==="all"?"all agents":r==="agent"?f?`${f}`:"the selected agent":f?`group ${f}`:"the selected group",Y=N?"all tools":d.size===0?"no tools (unrestricted within this attachment)":`${d.size} tool${d.size!==1?"s":""}`,J=N?[]:z.filter(a=>!d.has(a.name));return e.jsx("div",{className:"fixed inset-0 z-50 flex items-end sm:items-center justify-center bg-black/60 backdrop-blur-sm",role:"dialog","aria-modal":"true","aria-label":"Attach permission",children:e.jsxs("div",{className:"bg-[#1a1a2e] border border-white/10 rounded-t-2xl sm:rounded-2xl p-5 w-full max-w-lg shadow-2xl max-h-[90vh] flex flex-col overflow-hidden",children:[e.jsxs("div",{className:"flex items-center justify-between mb-4 shrink-0",children:[e.jsx("h2",{className:"text-base font-semibold text-shell-text",children:"Attach Permission"}),e.jsx("button",{onClick:m,className:"text-shell-text-secondary hover:text-shell-text transition-colors","aria-label":"Close",children:e.jsx(U,{size:16})})]}),e.jsxs("div",{className:"overflow-y-auto flex-1 min-h-0 space-y-5 pr-1",children:[e.jsxs("div",{children:[e.jsx(R,{className:"text-xs mb-2 block text-shell-text-secondary",children:"Scope"}),e.jsx("div",{className:"flex gap-1 p-1 bg-white/[0.04] rounded-lg",children:["all","agent","group"].map(a=>e.jsx("button",{onClick:()=>{b(a),h(""),g("")},className:`flex-1 py-1.5 rounded-md text-xs font-medium transition-colors ${r===a?"bg-white/[0.1] text-shell-text shadow-sm":"text-shell-text-secondary hover:text-shell-text"}`,"aria-pressed":r===a,children:a==="all"?"All agents":a==="agent"?"Specific agent":"Specific group"},a))})]}),(r==="agent"||r==="group")&&e.jsxs("div",{children:[e.jsx(R,{className:"text-xs mb-2 block text-shell-text-secondary",children:r==="agent"?"Select agent":"Select group"}),e.jsx(E,{placeholder:`Search ${r}s...`,value:u,onChange:a=>g(a.target.value),className:"mb-2","aria-label":`Search ${r}s`}),e.jsxs("div",{className:"max-h-32 overflow-y-auto space-y-1",children:[(r==="agent"?_:B).map(a=>{const w="name"in a?a.name:a.id,C="display_name"in a&&a.display_name?a.display_name:("name"in a,a.name);return e.jsx("button",{onClick:()=>h(w),className:`w-full text-left px-3 py-2 rounded-lg text-sm transition-colors ${f===w?"bg-accent/20 text-accent-foreground border border-accent/30":"hover:bg-white/[0.06] text-shell-text-secondary"}`,"aria-pressed":f===w,children:C},w)}),(r==="agent"?_:B).length===0&&e.jsx("p",{className:"text-xs text-shell-text-secondary text-center py-2",children:"No results"})]})]}),e.jsxs("div",{children:[e.jsxs("div",{className:"flex items-center justify-between mb-2",children:[e.jsx(R,{className:"text-xs text-shell-text-secondary",children:"Tools"}),e.jsxs("div",{className:"flex items-center gap-2",children:[e.jsx("span",{className:"text-xs text-shell-text-secondary",children:"Unrestricted"}),e.jsx(ee,{checked:N,onCheckedChange:j,"aria-label":"Allow all tools (unrestricted)"})]})]}),!N&&e.jsxs(e.Fragment,{children:[e.jsxs("div",{className:"flex gap-2 mb-2",children:[e.jsx("button",{className:"text-xs text-accent hover:underline",onClick:()=>y(new Set(z.map(a=>a.name))),"aria-label":"Select all tools",children:"Select all"}),e.jsx("span",{className:"text-shell-text-secondary text-xs",children:"/"}),e.jsx("button",{className:"text-xs text-accent hover:underline",onClick:()=>y(new Set),"aria-label":"Select no tools",children:"None"})]}),e.jsxs("div",{className:"space-y-1 max-h-40 overflow-y-auto",children:[z.length===0&&e.jsx("p",{className:"text-xs text-shell-text-secondary py-2 text-center",children:"No tools discovered yet. Attach will be unrestricted within scope."}),z.map(a=>e.jsxs("label",{className:"flex items-start gap-2.5 p-2 rounded-lg hover:bg-white/[0.04] cursor-pointer",children:[e.jsx("input",{type:"checkbox",checked:d.has(a.name),onChange:()=>V(a.name),className:"mt-0.5 accent-blue-500","aria-label":`Allow tool ${a.name}`}),e.jsxs("div",{className:"min-w-0",children:[e.jsx("span",{className:"text-xs font-medium font-mono text-shell-text",children:a.name}),a.description&&e.jsx("p",{className:"text-[11px] text-shell-text-secondary truncate",children:a.description})]})]},a.name))]})]}),N&&e.jsx("p",{className:"text-xs text-shell-text-secondary",children:"All tools are allowed within this scope."})]}),e.jsxs("div",{children:[e.jsxs("div",{className:"flex items-center justify-between mb-2",children:[e.jsx(R,{className:"text-xs text-shell-text-secondary",children:"Resource patterns"}),e.jsxs("button",{onClick:H,className:"text-xs text-accent hover:underline flex items-center gap-1","aria-label":"Add resource pattern",children:[e.jsx(O,{size:12}),"Add pattern"]})]}),S.length===0&&e.jsx("p",{className:"text-xs text-shell-text-secondary",children:"No patterns — all resources unrestricted."}),e.jsx("div",{className:"space-y-1.5",children:S.map((a,w)=>e.jsxs("div",{className:"flex gap-1.5",children:[e.jsx(E,{value:a,onChange:C=>K(w,C.target.value),placeholder:"/workspace/* or https://api.github.com/*",className:"font-mono text-xs","aria-label":`Resource pattern ${w+1}`}),e.jsx("button",{onClick:()=>W(w),className:"text-shell-text-secondary hover:text-red-400 transition-colors shrink-0","aria-label":`Remove pattern ${w+1}`,children:e.jsx(U,{size:14})})]},w))})]}),e.jsx("div",{className:"bg-blue-500/[0.07] border border-blue-500/20 rounded-lg p-3",children:e.jsxs("p",{className:"text-xs text-blue-200 leading-relaxed",children:[e.jsx("span",{className:"font-semibold",children:X})," will be able to call:"," ",e.jsx("span",{className:"font-medium",children:Y}),".",J.length>0&&e.jsxs(e.Fragment,{children:[" ","It will NOT be able to call:"," ",e.jsx("span",{className:"font-medium",children:J.map(a=>a.name).join(", ")}),"."]}),S.filter(a=>a.trim()).length>0&&e.jsxs(e.Fragment,{children:[" ","Resource access restricted to ",S.filter(a=>a.trim()).length," pattern",S.filter(a=>a.trim()).length!==1?"s":"","."]})]})})]}),c&&e.jsx("p",{className:"text-xs text-red-400 mt-2 shrink-0",children:c}),e.jsxs("div",{className:"flex gap-2 justify-end mt-4 shrink-0",children:[e.jsx(k,{variant:"outline",size:"sm",onClick:m,disabled:x,children:"Cancel"}),e.jsxs(k,{size:"sm",onClick:q,disabled:x,"aria-label":"Save attachment",children:[x?e.jsx($,{size:14,className:"animate-spin mr-1"}):null,"Attach"]})]})]})})}function ge({server:t,selected:n,onSelect:o}){return e.jsxs("button",{onClick:o,className:`w-full text-left flex items-center gap-3 px-4 py-3 transition-colors hover:bg-white/[0.05] ${n?"bg-white/[0.07]":""}`,"aria-pressed":n,"aria-label":`${t.name}, ${P[t.status]}`,children:[e.jsxs("div",{className:"relative shrink-0",children:[e.jsx("div",{className:"w-8 h-8 rounded-lg bg-white/[0.06] flex items-center justify-center",children:e.jsx(I,{size:15,className:"text-shell-text-secondary","aria-hidden":!0})}),e.jsx("span",{className:`absolute -bottom-0.5 -right-0.5 w-2.5 h-2.5 rounded-full border-2 border-[#0f0f1e] ${he[t.status]}`,"aria-label":`Status: ${P[t.status]}`})]}),e.jsxs("div",{className:"flex-1 min-w-0",children:[e.jsxs("div",{className:"flex items-center gap-1.5 min-w-0",children:[e.jsx("span",{className:"text-sm font-medium text-shell-text truncate",children:t.name}),e.jsx("span",{className:`shrink-0 text-[10px] px-1.5 py-0.5 rounded font-medium ${me[t.transport]??"bg-zinc-500/20 text-zinc-300"}`,children:t.transport})]}),e.jsxs("div",{className:"flex items-center gap-2 mt-0.5 text-[11px] text-shell-text-secondary",children:[t.last_started_at&&e.jsxs("span",{children:["Started ",G(t.last_started_at)]}),t.pid&&e.jsxs("span",{children:["PID ",t.pid]})]})]})]})}function be({servers:t,loading:n,selectedId:o,onSelect:i,onOpenStore:p}){const m=ue(t);return n?e.jsx("div",{className:"flex items-center justify-center h-32",children:e.jsx($,{size:20,className:"animate-spin text-shell-text-secondary"})}):t.length===0?e.jsxs("div",{className:"flex flex-col items-center justify-center gap-4 h-40 px-6 text-center",children:[e.jsx(I,{size:32,className:"text-shell-text-tertiary opacity-40","aria-hidden":!0}),e.jsx("p",{className:"text-sm text-shell-text-secondary",children:"No MCP servers installed"}),e.jsxs(k,{size:"sm",variant:"outline",onClick:p,"aria-label":"Browse MCP servers in Store",children:[e.jsx(ne,{size:14,className:"mr-1.5"}),"Browse MCP servers in Store"]})]}):e.jsx("div",{children:pe.map(r=>{const b=m[r];return b.length===0?null:e.jsxs("div",{children:[e.jsx("div",{className:"px-4 py-1.5 text-[10px] font-semibold uppercase tracking-wider text-shell-text-tertiary border-b border-white/[0.04]",children:P[r]}),b.map(u=>e.jsx(ge,{server:u,selected:o===u.id,onSelect:()=>i(u.id)},u.id))]},r)})})}function ve({server:t,capabilities:n,attachments:o,onAction:i,onUninstall:p}){const m=n.filter(r=>r.type==="tool").length;return e.jsxs("div",{className:"p-4 space-y-5 overflow-y-auto h-full",children:[e.jsxs("div",{className:"flex flex-wrap items-center gap-2",children:[e.jsx("span",{className:`text-xs px-2 py-1 rounded-full font-medium ${F[t.status]}`,children:P[t.status]}),t.pid&&e.jsxs("span",{className:"text-xs text-shell-text-secondary",children:["PID ",t.pid]}),e.jsx("div",{className:"flex-1"}),t.status!=="running"&&e.jsxs(k,{size:"sm",variant:"outline",onClick:()=>i("start"),"aria-label":"Start server",children:[e.jsx(ie,{size:13,className:"mr-1"}),"Start"]}),t.status==="running"&&e.jsxs(k,{size:"sm",variant:"outline",onClick:()=>i("stop"),"aria-label":"Stop server",children:[e.jsx(re,{size:13,className:"mr-1"}),"Stop"]}),e.jsxs(k,{size:"sm",variant:"outline",onClick:()=>i("restart"),"aria-label":"Restart server",children:[e.jsx(ce,{size:13,className:"mr-1"}),"Restart"]})]}),e.jsxs("div",{className:"space-y-2",children:[t.description&&e.jsx("p",{className:"text-sm text-shell-text-secondary",children:t.description}),e.jsxs("div",{className:"grid grid-cols-2 gap-2",children:[e.jsxs(T,{className:"px-3 py-2.5",children:[e.jsx("div",{className:"text-[10px] text-shell-text-tertiary uppercase tracking-wide",children:"Version"}),e.jsx("div",{className:"text-sm font-mono font-medium",children:t.version})]}),e.jsxs(T,{className:"px-3 py-2.5",children:[e.jsx("div",{className:"text-[10px] text-shell-text-tertiary uppercase tracking-wide",children:"Transport"}),e.jsx("div",{className:"text-sm font-medium",children:t.transport})]}),e.jsxs(T,{className:"px-3 py-2.5",children:[e.jsx("div",{className:"text-[10px] text-shell-text-tertiary uppercase tracking-wide",children:"Tools"}),e.jsx("div",{className:"text-sm font-medium",children:m})]}),e.jsxs(T,{className:"px-3 py-2.5",children:[e.jsx("div",{className:"text-[10px] text-shell-text-tertiary uppercase tracking-wide",children:"Attachments"}),e.jsx("div",{className:"text-sm font-medium",children:o.length})]})]}),t.last_error&&e.jsxs("div",{className:"bg-red-500/10 border border-red-500/20 rounded-lg px-3 py-2",children:[e.jsx("p",{className:"text-xs font-medium text-red-400 mb-0.5",children:"Last error"}),e.jsx("pre",{className:"text-[11px] text-red-300 whitespace-pre-wrap font-mono",children:t.last_error})]})]}),e.jsx("div",{className:"pt-2 border-t border-white/[0.06]",children:e.jsxs(k,{variant:"destructive",size:"sm",onClick:p,"aria-label":`Uninstall ${t.name}`,children:[e.jsx(M,{size:13,className:"mr-1.5"}),"Uninstall"]})})]})}function Ne({serverId:t,attachments:n,onRefresh:o}){const[i,p]=l.useState(!1),[m,r]=l.useState([]),[b,u]=l.useState([]),[g,f]=l.useState([]),[h,N]=l.useState(null);l.useEffect(()=>{fetch("/api/agents",{headers:{Accept:"application/json"}}).then(s=>s.json()).then(s=>r(Array.isArray(s)?s:s.agents??[])).catch(()=>{}),fetch("/api/relationships/groups",{headers:{Accept:"application/json"}}).then(s=>s.json()).then(s=>u(Array.isArray(s)?s:[])).catch(()=>{}),fetch(`/api/mcp/servers/${encodeURIComponent(t)}/capabilities`,{headers:{Accept:"application/json"}}).then(s=>s.json()).then(s=>f(Array.isArray(s)?s:s.capabilities??[])).catch(()=>{})},[t]);async function j(s){await fetch(`/api/mcp/servers/${encodeURIComponent(t)}/permissions/${s}`,{method:"DELETE"}),o()}function d(s){return s.scope_kind==="all"?"All agents":s.scope_kind==="agent"?`Agent: ${s.scope_id}`:`Group: ${s.scope_id}`}function y(s){return s.allowed_tools.length===0?"all tools":`${s.allowed_tools.length} tool${s.allowed_tools.length!==1?"s":""}`}function S(s){return s.allowed_resources.length===0?"no restriction":`${s.allowed_resources.length} pattern${s.allowed_resources.length!==1?"s":""}`}return e.jsxs("div",{className:"p-4 flex flex-col gap-4 overflow-y-auto h-full",children:[e.jsxs("div",{className:"flex items-center justify-between",children:[e.jsx("p",{className:"text-xs text-shell-text-secondary",children:n.length===0?"No attachments. Server is unreachable to all agents.":`${n.length} attachment${n.length!==1?"s":""}`}),e.jsxs(k,{size:"sm",variant:"outline",onClick:()=>p(!0),"aria-label":"Add attachment",children:[e.jsx(O,{size:13,className:"mr-1"}),"Attach"]})]}),n.length===0&&e.jsxs("div",{className:"flex flex-col items-center justify-center py-10 gap-2 text-center",children:[e.jsx(I,{size:28,className:"text-shell-text-tertiary opacity-40","aria-hidden":!0}),e.jsx("p",{className:"text-sm text-shell-text-secondary",children:"Zero-access by default"}),e.jsx("p",{className:"text-xs text-shell-text-secondary max-w-xs",children:"Attach this server to an agent or group to grant access. Tool and resource restrictions are optional."})]}),e.jsx("div",{className:"space-y-2",children:n.map(s=>e.jsxs(T,{className:"overflow-hidden",children:[e.jsxs("div",{className:"flex items-center gap-3 px-3 py-2.5",children:[e.jsx("div",{className:"flex-1 min-w-0 space-y-1",children:e.jsxs("div",{className:"flex items-center gap-1.5 flex-wrap",children:[e.jsx("span",{className:"text-xs font-medium text-shell-text",children:d(s)}),e.jsx("span",{className:"text-[10px] px-1.5 py-0.5 rounded bg-white/[0.06] text-shell-text-secondary",children:y(s)}),e.jsx("span",{className:"text-[10px] px-1.5 py-0.5 rounded bg-white/[0.06] text-shell-text-secondary",children:S(s)})]})}),(s.allowed_tools.length>0||s.allowed_resources.length>0)&&e.jsx("button",{onClick:()=>N(h===s.id?null:s.id),className:"text-shell-text-secondary hover:text-shell-text transition-colors","aria-label":h===s.id?"Collapse details":"Expand details","aria-expanded":h===s.id,children:e.jsx(oe,{size:14,className:`transition-transform ${h===s.id?"rotate-180":""}`})}),e.jsx("button",{onClick:()=>j(s.id),className:"text-shell-text-secondary hover:text-red-400 transition-colors","aria-label":`Remove attachment for ${d(s)}`,children:e.jsx(U,{size:14})})]}),h===s.id&&e.jsxs("div",{className:"px-3 pb-2.5 space-y-2 border-t border-white/[0.06] pt-2",children:[s.allowed_tools.length>0&&e.jsxs("div",{children:[e.jsx("p",{className:"text-[10px] text-shell-text-tertiary uppercase tracking-wide mb-1",children:"Allowed tools"}),e.jsx("div",{className:"flex flex-wrap gap-1",children:s.allowed_tools.map(x=>e.jsx("span",{className:"text-[10px] px-1.5 py-0.5 rounded bg-blue-500/15 text-blue-300 font-mono",children:x},x))})]}),s.allowed_resources.length>0&&e.jsxs("div",{children:[e.jsx("p",{className:"text-[10px] text-shell-text-tertiary uppercase tracking-wide mb-1",children:"Resource patterns"}),e.jsx("div",{className:"flex flex-wrap gap-1",children:s.allowed_resources.map((x,v)=>e.jsx("span",{className:"text-[10px] px-1.5 py-0.5 rounded bg-violet-500/15 text-violet-300 font-mono",children:x},v))})]})]})]},s.id))}),i&&e.jsx(je,{serverId:t,agents:m,groups:b,capabilities:g,onSaved:()=>{p(!1),o()},onClose:()=>p(!1)})]})}function ye({serverId:t}){const[n,o]=l.useState([]),[i,p]=l.useState(!0),[m,r]=l.useState(!1),[b,u]=l.useState(null),[g,f]=l.useState(!1);l.useEffect(()=>{p(!0),fetch(`/api/mcp/servers/${encodeURIComponent(t)}/env`,{headers:{Accept:"application/json"}}).then(s=>s.json()).then(s=>{o(Object.entries(s??{}).map(([v,c])=>({key:v,value:c,revealed:!1})))}).catch(()=>o([])).finally(()=>p(!1))},[t]);function h(){o(s=>[...s,{key:"",value:"",revealed:!0}])}function N(s,x){o(v=>v.map((c,A)=>A===s?{...c,key:x}:c))}function j(s,x){o(v=>v.map((c,A)=>A===s?{...c,value:x}:c))}function d(s){o(x=>x.filter((v,c)=>c!==s))}function y(s){o(x=>x.map((v,c)=>c===s?{...v,revealed:!v.revealed}:v))}async function S(){r(!0),u(null),f(!1);const s={};for(const x of n)x.key.trim()&&(s[x.key.trim()]=x.value);try{const x=await fetch(`/api/mcp/servers/${encodeURIComponent(t)}/env`,{method:"PUT",headers:{"Content-Type":"application/json"},body:JSON.stringify(s)});if(x.ok)f(!0),setTimeout(()=>f(!1),2e3);else{const v=await x.json().catch(()=>({detail:"Save failed"}));u(v.detail??"Save failed")}}catch{u("Network error")}r(!1)}return i?e.jsx("div",{className:"flex items-center justify-center h-24",children:e.jsx($,{size:18,className:"animate-spin text-shell-text-secondary"})}):e.jsxs("div",{className:"p-4 flex flex-col gap-4 overflow-y-auto h-full",children:[e.jsxs("div",{className:"flex items-center justify-between",children:[e.jsx("p",{className:"text-xs text-shell-text-secondary",children:"Environment variables are stored as secrets."}),e.jsxs("button",{onClick:h,className:"text-xs text-accent hover:underline flex items-center gap-1","aria-label":"Add environment variable",children:[e.jsx(O,{size:12}),"Add"]})]}),e.jsx("div",{className:"space-y-2",children:n.map((s,x)=>e.jsxs("div",{className:"flex gap-2 items-center",children:[e.jsx(E,{value:s.key,onChange:v=>N(x,v.target.value),placeholder:"KEY",className:"font-mono text-xs w-36 shrink-0","aria-label":`Environment variable name ${x+1}`}),e.jsxs("div",{className:"flex-1 relative",children:[e.jsx(E,{type:s.revealed?"text":"password",value:s.value,onChange:v=>j(x,v.target.value),placeholder:"value",className:"font-mono text-xs pr-8","aria-label":`Environment variable value ${x+1}`}),e.jsx("button",{onClick:()=>y(x),className:"absolute right-2 top-1/2 -translate-y-1/2 text-shell-text-tertiary hover:text-shell-text transition-colors","aria-label":s.revealed?"Hide value":"Reveal value",children:s.revealed?e.jsx("span",{className:"text-[10px]",children:"hide"}):e.jsx("span",{className:"text-[10px]",children:"show"})})]}),e.jsx("button",{onClick:()=>d(x),className:"text-shell-text-secondary hover:text-red-400 transition-colors shrink-0","aria-label":`Remove variable ${s.key||x+1}`,children:e.jsx(U,{size:14})})]},x))}),b&&e.jsx("p",{className:"text-xs text-red-400",children:b}),e.jsxs(k,{size:"sm",onClick:S,disabled:m,className:"self-start","aria-label":"Save environment variables",children:[g?e.jsx(D,{size:13,className:"mr-1 text-emerald-400"}):m?e.jsx($,{size:13,className:"animate-spin mr-1"}):null,g?"Saved":"Save"]})]})}function we({serverId:t}){const[n,o]=l.useState(""),[i,p]=l.useState(!0),[m,r]=l.useState(!1),[b,u]=l.useState(null),[g,f]=l.useState(!1);l.useEffect(()=>{p(!0),fetch(`/api/mcp/servers/${encodeURIComponent(t)}/config`,{headers:{Accept:"application/json"}}).then(j=>j.json()).then(j=>o(JSON.stringify(j,null,2))).catch(()=>o("{}")).finally(()=>p(!1))},[t]);let h=!0;try{JSON.parse(n)}catch{h=!1}async function N(){if(h){r(!0),u(null),f(!1);try{const j=JSON.parse(n),d=await fetch(`/api/mcp/servers/${encodeURIComponent(t)}/config`,{method:"PUT",headers:{"Content-Type":"application/json"},body:JSON.stringify(j)});if(d.ok)f(!0),setTimeout(()=>f(!1),2e3);else{const y=await d.json().catch(()=>({detail:"Save failed"}));u(y.detail??"Save failed")}}catch{u("Network error")}r(!1)}}return i?e.jsx("div",{className:"flex items-center justify-center h-24",children:e.jsx($,{size:18,className:"animate-spin text-shell-text-secondary"})}):e.jsxs("div",{className:"p-4 flex flex-col gap-3 h-full overflow-hidden",children:[e.jsx("p",{className:"text-xs text-shell-text-secondary shrink-0",children:"JSON configuration overrides for this server."}),e.jsx(Q,{value:n,onChange:j=>o(j.target.value),className:`flex-1 font-mono text-xs resize-none ${h?"":"border-red-500/50"}`,"aria-label":"Server configuration JSON","aria-invalid":!h,spellCheck:!1}),!h&&e.jsx("p",{className:"text-xs text-red-400 shrink-0",children:"Invalid JSON"}),b&&e.jsx("p",{className:"text-xs text-red-400 shrink-0",children:b}),e.jsxs(k,{size:"sm",onClick:N,disabled:!h||m,className:"self-start shrink-0","aria-label":"Save configuration",children:[g?e.jsx(D,{size:13,className:"mr-1 text-emerald-400"}):m?e.jsx($,{size:13,className:"animate-spin mr-1"}):null,g?"Saved":"Save"]})]})}function Se({serverId:t}){const[n,o]=l.useState([]),[i,p]=l.useState(!1),[m,r]=l.useState(!1),[b,u]=l.useState(!1),g=l.useRef(null),f=l.useRef(!1),h=l.useRef(null);f.current=m,l.useEffect(()=>{const d=new EventSource(`/api/mcp/servers/${encodeURIComponent(t)}/logs/stream`);return h.current=d,d.onopen=()=>p(!0),d.onerror=()=>p(!1),d.onmessage=y=>{f.current||o(S=>[...S.slice(-500),y.data])},()=>{d.close(),h.current=null}},[t]),l.useEffect(()=>{!m&&g.current&&(g.current.scrollTop=g.current.scrollHeight)},[n,m]);function N(){const d=g.current;if(!d)return;const y=d.scrollHeight-d.scrollTop-d.clientHeight<40;!y&&!f.current&&r(!0),y&&f.current&&r(!1)}async function j(){await navigator.clipboard.writeText(n.join(` +import{r as l,j as e}from"./vendor-react-l6srOxy7.js";import{B as k,C as T,I as E,T as Q,L as R,S as ee}from"./toolbar-UW6q5pkx.js";import{M as te}from"./MobileSplitView-B-4MQO2C.js";import{a as se,b as ae,g as le}from"./main-FOmUFQfu.js";import{ao as I,V as $,al as ne,a5 as ie,aN as re,R as ce,y as M,g as O,aG as oe,X as U,f as D,aw as de,r as xe}from"./vendor-icons--yQaiqiL.js";import"./vendor-radix-BhM7AEEG.js";import"./vendor-layout-B-pp9n1f.js";import"./tokens-BKHlNYpw.js";import"./vendor-codemirror-aNcHammg.js";const he={running:"bg-emerald-500",stopped:"bg-zinc-500",failed:"bg-red-500",installing:"bg-amber-500"},F={running:"bg-emerald-500/20 text-emerald-400",stopped:"bg-zinc-500/20 text-zinc-400",failed:"bg-red-500/20 text-red-400",installing:"bg-amber-500/20 text-amber-400"},P={running:"Running",stopped:"Stopped",failed:"Failed",installing:"Installing"},me={stdio:"bg-blue-500/20 text-blue-300",sse:"bg-violet-500/20 text-violet-300",ws:"bg-teal-500/20 text-teal-300"},pe=["running","installing","failed","stopped"];function ue(t){const n={running:[],stopped:[],failed:[],installing:[]};for(const o of t)n[o.status].push(o);return n}function G(t){return new Date(t*1e3).toLocaleTimeString(void 0,{hour:"2-digit",minute:"2-digit"})}function fe({server:t,attachments:n,onConfirm:o,onClose:i,loading:p}){const[m,r]=l.useState(""),b=n.length>=3,u=!b||m===t.id,g=l.useRef(null);l.useEffect(()=>{var h;(h=g.current)==null||h.focus()},[]);const f=n.map(h=>h.scope_kind==="all"?"all agents":h.scope_kind==="agent"?`agent: ${h.scope_id}`:`group: ${h.scope_id}`);return e.jsx("div",{className:"fixed inset-0 z-50 flex items-center justify-center bg-black/60 backdrop-blur-sm",role:"dialog","aria-modal":"true","aria-label":`Uninstall ${t.name}`,children:e.jsxs("div",{className:"bg-[#1a1a2e] border border-white/10 rounded-2xl p-6 w-full max-w-md shadow-2xl",children:[e.jsxs("div",{className:"flex items-start gap-3 mb-4",children:[e.jsx("div",{className:"p-2 rounded-lg bg-red-500/15 mt-0.5",children:e.jsx(xe,{size:20,className:"text-red-400","aria-hidden":!0})}),e.jsxs("div",{className:"flex-1 min-w-0",children:[e.jsxs("h2",{className:"text-base font-semibold text-shell-text",children:["Uninstall ",t.name,"?"]}),e.jsxs("p",{className:"text-xs text-shell-text-secondary mt-0.5",children:["v",t.version]})]}),e.jsx("button",{onClick:i,className:"text-shell-text-secondary hover:text-shell-text transition-colors","aria-label":"Close",children:e.jsx(U,{size:16})})]}),e.jsxs("div",{className:"space-y-2 mb-4",children:[n.length>0&&e.jsxs("div",{className:"text-sm text-shell-text-secondary bg-white/[0.03] rounded-lg px-3 py-2.5 border border-white/[0.06]",children:[e.jsxs("span",{className:"font-medium text-red-400",children:[n.length," attachment",n.length!==1?"s":""]})," will be revoked:"," ",e.jsx("span",{className:"text-shell-text",children:f.join(", ")})]}),e.jsx("p",{className:"text-xs text-shell-text-secondary",children:"This will stop the server process, remove all attachments, delete env secrets, and remove files from disk. This cannot be undone."})]}),b&&e.jsxs("div",{className:"mb-4",children:[e.jsxs(R,{htmlFor:"uninstall-confirm-input",className:"text-xs mb-1.5 block text-shell-text-secondary",children:["Type ",e.jsx("span",{className:"font-mono font-semibold text-shell-text",children:t.id})," to confirm"]}),e.jsx(E,{ref:g,id:"uninstall-confirm-input",value:m,onChange:h=>r(h.target.value),placeholder:t.id,className:"font-mono","aria-label":`Type ${t.id} to confirm uninstall`})]}),e.jsxs("div",{className:"flex gap-2 justify-end",children:[e.jsx(k,{variant:"outline",size:"sm",onClick:i,disabled:p,children:"Cancel"}),e.jsxs(k,{variant:"destructive",size:"sm",onClick:o,disabled:!u||p,"aria-label":`Confirm uninstall ${t.name}`,children:[p?e.jsx($,{size:14,className:"animate-spin mr-1"}):e.jsx(M,{size:14,className:"mr-1"}),"Uninstall"]})]})]})})}function je({serverId:t,agents:n,groups:o,capabilities:i,onSaved:p,onClose:m}){const[r,b]=l.useState("all"),[u,g]=l.useState(""),[f,h]=l.useState(""),[N,j]=l.useState(!0),[d,y]=l.useState(new Set),[S,s]=l.useState([]),[x,v]=l.useState(!1),[c,A]=l.useState(null),z=i.filter(a=>a.type==="tool"),_=n.filter(a=>(a.display_name||a.name).toLowerCase().includes(u.toLowerCase())),B=o.filter(a=>a.name.toLowerCase().includes(u.toLowerCase()));function V(a){y(w=>{const C=new Set(w);return C.has(a)?C.delete(a):C.add(a),C})}function H(){s(a=>[...a,""])}function K(a,w){s(C=>C.map((L,Z)=>Z===a?w:L))}function W(a){s(w=>w.filter((C,L)=>L!==a))}async function q(){if(r!=="all"&&!f){A("Select a specific agent or group.");return}v(!0),A(null);try{const a={scope_kind:r,scope_id:r==="all"?void 0:f,allowed_tools:N?[]:Array.from(d),allowed_resources:S.filter(C=>C.trim())},w=await fetch(`/api/mcp/servers/${encodeURIComponent(t)}/permissions`,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify(a)});if(!w.ok){const C=await w.json().catch(()=>({detail:"Failed to attach"}));A(C.detail??"Failed to attach"),v(!1);return}p()}catch{A("Network error"),v(!1)}}const X=r==="all"?"all agents":r==="agent"?f?`${f}`:"the selected agent":f?`group ${f}`:"the selected group",Y=N?"all tools":d.size===0?"no tools (unrestricted within this attachment)":`${d.size} tool${d.size!==1?"s":""}`,J=N?[]:z.filter(a=>!d.has(a.name));return e.jsx("div",{className:"fixed inset-0 z-50 flex items-end sm:items-center justify-center bg-black/60 backdrop-blur-sm",role:"dialog","aria-modal":"true","aria-label":"Attach permission",children:e.jsxs("div",{className:"bg-[#1a1a2e] border border-white/10 rounded-t-2xl sm:rounded-2xl p-5 w-full max-w-lg shadow-2xl max-h-[90vh] flex flex-col overflow-hidden",children:[e.jsxs("div",{className:"flex items-center justify-between mb-4 shrink-0",children:[e.jsx("h2",{className:"text-base font-semibold text-shell-text",children:"Attach Permission"}),e.jsx("button",{onClick:m,className:"text-shell-text-secondary hover:text-shell-text transition-colors","aria-label":"Close",children:e.jsx(U,{size:16})})]}),e.jsxs("div",{className:"overflow-y-auto flex-1 min-h-0 space-y-5 pr-1",children:[e.jsxs("div",{children:[e.jsx(R,{className:"text-xs mb-2 block text-shell-text-secondary",children:"Scope"}),e.jsx("div",{className:"flex gap-1 p-1 bg-white/[0.04] rounded-lg",children:["all","agent","group"].map(a=>e.jsx("button",{onClick:()=>{b(a),h(""),g("")},className:`flex-1 py-1.5 rounded-md text-xs font-medium transition-colors ${r===a?"bg-white/[0.1] text-shell-text shadow-sm":"text-shell-text-secondary hover:text-shell-text"}`,"aria-pressed":r===a,children:a==="all"?"All agents":a==="agent"?"Specific agent":"Specific group"},a))})]}),(r==="agent"||r==="group")&&e.jsxs("div",{children:[e.jsx(R,{className:"text-xs mb-2 block text-shell-text-secondary",children:r==="agent"?"Select agent":"Select group"}),e.jsx(E,{placeholder:`Search ${r}s...`,value:u,onChange:a=>g(a.target.value),className:"mb-2","aria-label":`Search ${r}s`}),e.jsxs("div",{className:"max-h-32 overflow-y-auto space-y-1",children:[(r==="agent"?_:B).map(a=>{const w="name"in a?a.name:a.id,C="display_name"in a&&a.display_name?a.display_name:("name"in a,a.name);return e.jsx("button",{onClick:()=>h(w),className:`w-full text-left px-3 py-2 rounded-lg text-sm transition-colors ${f===w?"bg-accent/20 text-accent-foreground border border-accent/30":"hover:bg-white/[0.06] text-shell-text-secondary"}`,"aria-pressed":f===w,children:C},w)}),(r==="agent"?_:B).length===0&&e.jsx("p",{className:"text-xs text-shell-text-secondary text-center py-2",children:"No results"})]})]}),e.jsxs("div",{children:[e.jsxs("div",{className:"flex items-center justify-between mb-2",children:[e.jsx(R,{className:"text-xs text-shell-text-secondary",children:"Tools"}),e.jsxs("div",{className:"flex items-center gap-2",children:[e.jsx("span",{className:"text-xs text-shell-text-secondary",children:"Unrestricted"}),e.jsx(ee,{checked:N,onCheckedChange:j,"aria-label":"Allow all tools (unrestricted)"})]})]}),!N&&e.jsxs(e.Fragment,{children:[e.jsxs("div",{className:"flex gap-2 mb-2",children:[e.jsx("button",{className:"text-xs text-accent hover:underline",onClick:()=>y(new Set(z.map(a=>a.name))),"aria-label":"Select all tools",children:"Select all"}),e.jsx("span",{className:"text-shell-text-secondary text-xs",children:"/"}),e.jsx("button",{className:"text-xs text-accent hover:underline",onClick:()=>y(new Set),"aria-label":"Select no tools",children:"None"})]}),e.jsxs("div",{className:"space-y-1 max-h-40 overflow-y-auto",children:[z.length===0&&e.jsx("p",{className:"text-xs text-shell-text-secondary py-2 text-center",children:"No tools discovered yet. Attach will be unrestricted within scope."}),z.map(a=>e.jsxs("label",{className:"flex items-start gap-2.5 p-2 rounded-lg hover:bg-white/[0.04] cursor-pointer",children:[e.jsx("input",{type:"checkbox",checked:d.has(a.name),onChange:()=>V(a.name),className:"mt-0.5 accent-blue-500","aria-label":`Allow tool ${a.name}`}),e.jsxs("div",{className:"min-w-0",children:[e.jsx("span",{className:"text-xs font-medium font-mono text-shell-text",children:a.name}),a.description&&e.jsx("p",{className:"text-[11px] text-shell-text-secondary truncate",children:a.description})]})]},a.name))]})]}),N&&e.jsx("p",{className:"text-xs text-shell-text-secondary",children:"All tools are allowed within this scope."})]}),e.jsxs("div",{children:[e.jsxs("div",{className:"flex items-center justify-between mb-2",children:[e.jsx(R,{className:"text-xs text-shell-text-secondary",children:"Resource patterns"}),e.jsxs("button",{onClick:H,className:"text-xs text-accent hover:underline flex items-center gap-1","aria-label":"Add resource pattern",children:[e.jsx(O,{size:12}),"Add pattern"]})]}),S.length===0&&e.jsx("p",{className:"text-xs text-shell-text-secondary",children:"No patterns — all resources unrestricted."}),e.jsx("div",{className:"space-y-1.5",children:S.map((a,w)=>e.jsxs("div",{className:"flex gap-1.5",children:[e.jsx(E,{value:a,onChange:C=>K(w,C.target.value),placeholder:"/workspace/* or https://api.github.com/*",className:"font-mono text-xs","aria-label":`Resource pattern ${w+1}`}),e.jsx("button",{onClick:()=>W(w),className:"text-shell-text-secondary hover:text-red-400 transition-colors shrink-0","aria-label":`Remove pattern ${w+1}`,children:e.jsx(U,{size:14})})]},w))})]}),e.jsx("div",{className:"bg-blue-500/[0.07] border border-blue-500/20 rounded-lg p-3",children:e.jsxs("p",{className:"text-xs text-blue-200 leading-relaxed",children:[e.jsx("span",{className:"font-semibold",children:X})," will be able to call:"," ",e.jsx("span",{className:"font-medium",children:Y}),".",J.length>0&&e.jsxs(e.Fragment,{children:[" ","It will NOT be able to call:"," ",e.jsx("span",{className:"font-medium",children:J.map(a=>a.name).join(", ")}),"."]}),S.filter(a=>a.trim()).length>0&&e.jsxs(e.Fragment,{children:[" ","Resource access restricted to ",S.filter(a=>a.trim()).length," pattern",S.filter(a=>a.trim()).length!==1?"s":"","."]})]})})]}),c&&e.jsx("p",{className:"text-xs text-red-400 mt-2 shrink-0",children:c}),e.jsxs("div",{className:"flex gap-2 justify-end mt-4 shrink-0",children:[e.jsx(k,{variant:"outline",size:"sm",onClick:m,disabled:x,children:"Cancel"}),e.jsxs(k,{size:"sm",onClick:q,disabled:x,"aria-label":"Save attachment",children:[x?e.jsx($,{size:14,className:"animate-spin mr-1"}):null,"Attach"]})]})]})})}function ge({server:t,selected:n,onSelect:o}){return e.jsxs("button",{onClick:o,className:`w-full text-left flex items-center gap-3 px-4 py-3 transition-colors hover:bg-white/[0.05] ${n?"bg-white/[0.07]":""}`,"aria-pressed":n,"aria-label":`${t.name}, ${P[t.status]}`,children:[e.jsxs("div",{className:"relative shrink-0",children:[e.jsx("div",{className:"w-8 h-8 rounded-lg bg-white/[0.06] flex items-center justify-center",children:e.jsx(I,{size:15,className:"text-shell-text-secondary","aria-hidden":!0})}),e.jsx("span",{className:`absolute -bottom-0.5 -right-0.5 w-2.5 h-2.5 rounded-full border-2 border-[#0f0f1e] ${he[t.status]}`,"aria-label":`Status: ${P[t.status]}`})]}),e.jsxs("div",{className:"flex-1 min-w-0",children:[e.jsxs("div",{className:"flex items-center gap-1.5 min-w-0",children:[e.jsx("span",{className:"text-sm font-medium text-shell-text truncate",children:t.name}),e.jsx("span",{className:`shrink-0 text-[10px] px-1.5 py-0.5 rounded font-medium ${me[t.transport]??"bg-zinc-500/20 text-zinc-300"}`,children:t.transport})]}),e.jsxs("div",{className:"flex items-center gap-2 mt-0.5 text-[11px] text-shell-text-secondary",children:[t.last_started_at&&e.jsxs("span",{children:["Started ",G(t.last_started_at)]}),t.pid&&e.jsxs("span",{children:["PID ",t.pid]})]})]})]})}function be({servers:t,loading:n,selectedId:o,onSelect:i,onOpenStore:p}){const m=ue(t);return n?e.jsx("div",{className:"flex items-center justify-center h-32",children:e.jsx($,{size:20,className:"animate-spin text-shell-text-secondary"})}):t.length===0?e.jsxs("div",{className:"flex flex-col items-center justify-center gap-4 h-40 px-6 text-center",children:[e.jsx(I,{size:32,className:"text-shell-text-tertiary opacity-40","aria-hidden":!0}),e.jsx("p",{className:"text-sm text-shell-text-secondary",children:"No MCP servers installed"}),e.jsxs(k,{size:"sm",variant:"outline",onClick:p,"aria-label":"Browse MCP servers in Store",children:[e.jsx(ne,{size:14,className:"mr-1.5"}),"Browse MCP servers in Store"]})]}):e.jsx("div",{children:pe.map(r=>{const b=m[r];return b.length===0?null:e.jsxs("div",{children:[e.jsx("div",{className:"px-4 py-1.5 text-[10px] font-semibold uppercase tracking-wider text-shell-text-tertiary border-b border-white/[0.04]",children:P[r]}),b.map(u=>e.jsx(ge,{server:u,selected:o===u.id,onSelect:()=>i(u.id)},u.id))]},r)})})}function ve({server:t,capabilities:n,attachments:o,onAction:i,onUninstall:p}){const m=n.filter(r=>r.type==="tool").length;return e.jsxs("div",{className:"p-4 space-y-5 overflow-y-auto h-full",children:[e.jsxs("div",{className:"flex flex-wrap items-center gap-2",children:[e.jsx("span",{className:`text-xs px-2 py-1 rounded-full font-medium ${F[t.status]}`,children:P[t.status]}),t.pid&&e.jsxs("span",{className:"text-xs text-shell-text-secondary",children:["PID ",t.pid]}),e.jsx("div",{className:"flex-1"}),t.status!=="running"&&e.jsxs(k,{size:"sm",variant:"outline",onClick:()=>i("start"),"aria-label":"Start server",children:[e.jsx(ie,{size:13,className:"mr-1"}),"Start"]}),t.status==="running"&&e.jsxs(k,{size:"sm",variant:"outline",onClick:()=>i("stop"),"aria-label":"Stop server",children:[e.jsx(re,{size:13,className:"mr-1"}),"Stop"]}),e.jsxs(k,{size:"sm",variant:"outline",onClick:()=>i("restart"),"aria-label":"Restart server",children:[e.jsx(ce,{size:13,className:"mr-1"}),"Restart"]})]}),e.jsxs("div",{className:"space-y-2",children:[t.description&&e.jsx("p",{className:"text-sm text-shell-text-secondary",children:t.description}),e.jsxs("div",{className:"grid grid-cols-2 gap-2",children:[e.jsxs(T,{className:"px-3 py-2.5",children:[e.jsx("div",{className:"text-[10px] text-shell-text-tertiary uppercase tracking-wide",children:"Version"}),e.jsx("div",{className:"text-sm font-mono font-medium",children:t.version})]}),e.jsxs(T,{className:"px-3 py-2.5",children:[e.jsx("div",{className:"text-[10px] text-shell-text-tertiary uppercase tracking-wide",children:"Transport"}),e.jsx("div",{className:"text-sm font-medium",children:t.transport})]}),e.jsxs(T,{className:"px-3 py-2.5",children:[e.jsx("div",{className:"text-[10px] text-shell-text-tertiary uppercase tracking-wide",children:"Tools"}),e.jsx("div",{className:"text-sm font-medium",children:m})]}),e.jsxs(T,{className:"px-3 py-2.5",children:[e.jsx("div",{className:"text-[10px] text-shell-text-tertiary uppercase tracking-wide",children:"Attachments"}),e.jsx("div",{className:"text-sm font-medium",children:o.length})]})]}),t.last_error&&e.jsxs("div",{className:"bg-red-500/10 border border-red-500/20 rounded-lg px-3 py-2",children:[e.jsx("p",{className:"text-xs font-medium text-red-400 mb-0.5",children:"Last error"}),e.jsx("pre",{className:"text-[11px] text-red-300 whitespace-pre-wrap font-mono",children:t.last_error})]})]}),e.jsx("div",{className:"pt-2 border-t border-white/[0.06]",children:e.jsxs(k,{variant:"destructive",size:"sm",onClick:p,"aria-label":`Uninstall ${t.name}`,children:[e.jsx(M,{size:13,className:"mr-1.5"}),"Uninstall"]})})]})}function Ne({serverId:t,attachments:n,onRefresh:o}){const[i,p]=l.useState(!1),[m,r]=l.useState([]),[b,u]=l.useState([]),[g,f]=l.useState([]),[h,N]=l.useState(null);l.useEffect(()=>{fetch("/api/agents",{headers:{Accept:"application/json"}}).then(s=>s.json()).then(s=>r(Array.isArray(s)?s:s.agents??[])).catch(()=>{}),fetch("/api/relationships/groups",{headers:{Accept:"application/json"}}).then(s=>s.json()).then(s=>u(Array.isArray(s)?s:[])).catch(()=>{}),fetch(`/api/mcp/servers/${encodeURIComponent(t)}/capabilities`,{headers:{Accept:"application/json"}}).then(s=>s.json()).then(s=>f(Array.isArray(s)?s:s.capabilities??[])).catch(()=>{})},[t]);async function j(s){await fetch(`/api/mcp/servers/${encodeURIComponent(t)}/permissions/${s}`,{method:"DELETE"}),o()}function d(s){return s.scope_kind==="all"?"All agents":s.scope_kind==="agent"?`Agent: ${s.scope_id}`:`Group: ${s.scope_id}`}function y(s){return s.allowed_tools.length===0?"all tools":`${s.allowed_tools.length} tool${s.allowed_tools.length!==1?"s":""}`}function S(s){return s.allowed_resources.length===0?"no restriction":`${s.allowed_resources.length} pattern${s.allowed_resources.length!==1?"s":""}`}return e.jsxs("div",{className:"p-4 flex flex-col gap-4 overflow-y-auto h-full",children:[e.jsxs("div",{className:"flex items-center justify-between",children:[e.jsx("p",{className:"text-xs text-shell-text-secondary",children:n.length===0?"No attachments. Server is unreachable to all agents.":`${n.length} attachment${n.length!==1?"s":""}`}),e.jsxs(k,{size:"sm",variant:"outline",onClick:()=>p(!0),"aria-label":"Add attachment",children:[e.jsx(O,{size:13,className:"mr-1"}),"Attach"]})]}),n.length===0&&e.jsxs("div",{className:"flex flex-col items-center justify-center py-10 gap-2 text-center",children:[e.jsx(I,{size:28,className:"text-shell-text-tertiary opacity-40","aria-hidden":!0}),e.jsx("p",{className:"text-sm text-shell-text-secondary",children:"Zero-access by default"}),e.jsx("p",{className:"text-xs text-shell-text-secondary max-w-xs",children:"Attach this server to an agent or group to grant access. Tool and resource restrictions are optional."})]}),e.jsx("div",{className:"space-y-2",children:n.map(s=>e.jsxs(T,{className:"overflow-hidden",children:[e.jsxs("div",{className:"flex items-center gap-3 px-3 py-2.5",children:[e.jsx("div",{className:"flex-1 min-w-0 space-y-1",children:e.jsxs("div",{className:"flex items-center gap-1.5 flex-wrap",children:[e.jsx("span",{className:"text-xs font-medium text-shell-text",children:d(s)}),e.jsx("span",{className:"text-[10px] px-1.5 py-0.5 rounded bg-white/[0.06] text-shell-text-secondary",children:y(s)}),e.jsx("span",{className:"text-[10px] px-1.5 py-0.5 rounded bg-white/[0.06] text-shell-text-secondary",children:S(s)})]})}),(s.allowed_tools.length>0||s.allowed_resources.length>0)&&e.jsx("button",{onClick:()=>N(h===s.id?null:s.id),className:"text-shell-text-secondary hover:text-shell-text transition-colors","aria-label":h===s.id?"Collapse details":"Expand details","aria-expanded":h===s.id,children:e.jsx(oe,{size:14,className:`transition-transform ${h===s.id?"rotate-180":""}`})}),e.jsx("button",{onClick:()=>j(s.id),className:"text-shell-text-secondary hover:text-red-400 transition-colors","aria-label":`Remove attachment for ${d(s)}`,children:e.jsx(U,{size:14})})]}),h===s.id&&e.jsxs("div",{className:"px-3 pb-2.5 space-y-2 border-t border-white/[0.06] pt-2",children:[s.allowed_tools.length>0&&e.jsxs("div",{children:[e.jsx("p",{className:"text-[10px] text-shell-text-tertiary uppercase tracking-wide mb-1",children:"Allowed tools"}),e.jsx("div",{className:"flex flex-wrap gap-1",children:s.allowed_tools.map(x=>e.jsx("span",{className:"text-[10px] px-1.5 py-0.5 rounded bg-blue-500/15 text-blue-300 font-mono",children:x},x))})]}),s.allowed_resources.length>0&&e.jsxs("div",{children:[e.jsx("p",{className:"text-[10px] text-shell-text-tertiary uppercase tracking-wide mb-1",children:"Resource patterns"}),e.jsx("div",{className:"flex flex-wrap gap-1",children:s.allowed_resources.map((x,v)=>e.jsx("span",{className:"text-[10px] px-1.5 py-0.5 rounded bg-violet-500/15 text-violet-300 font-mono",children:x},v))})]})]})]},s.id))}),i&&e.jsx(je,{serverId:t,agents:m,groups:b,capabilities:g,onSaved:()=>{p(!1),o()},onClose:()=>p(!1)})]})}function ye({serverId:t}){const[n,o]=l.useState([]),[i,p]=l.useState(!0),[m,r]=l.useState(!1),[b,u]=l.useState(null),[g,f]=l.useState(!1);l.useEffect(()=>{p(!0),fetch(`/api/mcp/servers/${encodeURIComponent(t)}/env`,{headers:{Accept:"application/json"}}).then(s=>s.json()).then(s=>{o(Object.entries(s??{}).map(([v,c])=>({key:v,value:c,revealed:!1})))}).catch(()=>o([])).finally(()=>p(!1))},[t]);function h(){o(s=>[...s,{key:"",value:"",revealed:!0}])}function N(s,x){o(v=>v.map((c,A)=>A===s?{...c,key:x}:c))}function j(s,x){o(v=>v.map((c,A)=>A===s?{...c,value:x}:c))}function d(s){o(x=>x.filter((v,c)=>c!==s))}function y(s){o(x=>x.map((v,c)=>c===s?{...v,revealed:!v.revealed}:v))}async function S(){r(!0),u(null),f(!1);const s={};for(const x of n)x.key.trim()&&(s[x.key.trim()]=x.value);try{const x=await fetch(`/api/mcp/servers/${encodeURIComponent(t)}/env`,{method:"PUT",headers:{"Content-Type":"application/json"},body:JSON.stringify(s)});if(x.ok)f(!0),setTimeout(()=>f(!1),2e3);else{const v=await x.json().catch(()=>({detail:"Save failed"}));u(v.detail??"Save failed")}}catch{u("Network error")}r(!1)}return i?e.jsx("div",{className:"flex items-center justify-center h-24",children:e.jsx($,{size:18,className:"animate-spin text-shell-text-secondary"})}):e.jsxs("div",{className:"p-4 flex flex-col gap-4 overflow-y-auto h-full",children:[e.jsxs("div",{className:"flex items-center justify-between",children:[e.jsx("p",{className:"text-xs text-shell-text-secondary",children:"Environment variables are stored as secrets."}),e.jsxs("button",{onClick:h,className:"text-xs text-accent hover:underline flex items-center gap-1","aria-label":"Add environment variable",children:[e.jsx(O,{size:12}),"Add"]})]}),e.jsx("div",{className:"space-y-2",children:n.map((s,x)=>e.jsxs("div",{className:"flex gap-2 items-center",children:[e.jsx(E,{value:s.key,onChange:v=>N(x,v.target.value),placeholder:"KEY",className:"font-mono text-xs w-36 shrink-0","aria-label":`Environment variable name ${x+1}`}),e.jsxs("div",{className:"flex-1 relative",children:[e.jsx(E,{type:s.revealed?"text":"password",value:s.value,onChange:v=>j(x,v.target.value),placeholder:"value",className:"font-mono text-xs pr-8","aria-label":`Environment variable value ${x+1}`}),e.jsx("button",{onClick:()=>y(x),className:"absolute right-2 top-1/2 -translate-y-1/2 text-shell-text-tertiary hover:text-shell-text transition-colors","aria-label":s.revealed?"Hide value":"Reveal value",children:s.revealed?e.jsx("span",{className:"text-[10px]",children:"hide"}):e.jsx("span",{className:"text-[10px]",children:"show"})})]}),e.jsx("button",{onClick:()=>d(x),className:"text-shell-text-secondary hover:text-red-400 transition-colors shrink-0","aria-label":`Remove variable ${s.key||x+1}`,children:e.jsx(U,{size:14})})]},x))}),b&&e.jsx("p",{className:"text-xs text-red-400",children:b}),e.jsxs(k,{size:"sm",onClick:S,disabled:m,className:"self-start","aria-label":"Save environment variables",children:[g?e.jsx(D,{size:13,className:"mr-1 text-emerald-400"}):m?e.jsx($,{size:13,className:"animate-spin mr-1"}):null,g?"Saved":"Save"]})]})}function we({serverId:t}){const[n,o]=l.useState(""),[i,p]=l.useState(!0),[m,r]=l.useState(!1),[b,u]=l.useState(null),[g,f]=l.useState(!1);l.useEffect(()=>{p(!0),fetch(`/api/mcp/servers/${encodeURIComponent(t)}/config`,{headers:{Accept:"application/json"}}).then(j=>j.json()).then(j=>o(JSON.stringify(j,null,2))).catch(()=>o("{}")).finally(()=>p(!1))},[t]);let h=!0;try{JSON.parse(n)}catch{h=!1}async function N(){if(h){r(!0),u(null),f(!1);try{const j=JSON.parse(n),d=await fetch(`/api/mcp/servers/${encodeURIComponent(t)}/config`,{method:"PUT",headers:{"Content-Type":"application/json"},body:JSON.stringify(j)});if(d.ok)f(!0),setTimeout(()=>f(!1),2e3);else{const y=await d.json().catch(()=>({detail:"Save failed"}));u(y.detail??"Save failed")}}catch{u("Network error")}r(!1)}}return i?e.jsx("div",{className:"flex items-center justify-center h-24",children:e.jsx($,{size:18,className:"animate-spin text-shell-text-secondary"})}):e.jsxs("div",{className:"p-4 flex flex-col gap-3 h-full overflow-hidden",children:[e.jsx("p",{className:"text-xs text-shell-text-secondary shrink-0",children:"JSON configuration overrides for this server."}),e.jsx(Q,{value:n,onChange:j=>o(j.target.value),className:`flex-1 font-mono text-xs resize-none ${h?"":"border-red-500/50"}`,"aria-label":"Server configuration JSON","aria-invalid":!h,spellCheck:!1}),!h&&e.jsx("p",{className:"text-xs text-red-400 shrink-0",children:"Invalid JSON"}),b&&e.jsx("p",{className:"text-xs text-red-400 shrink-0",children:b}),e.jsxs(k,{size:"sm",onClick:N,disabled:!h||m,className:"self-start shrink-0","aria-label":"Save configuration",children:[g?e.jsx(D,{size:13,className:"mr-1 text-emerald-400"}):m?e.jsx($,{size:13,className:"animate-spin mr-1"}):null,g?"Saved":"Save"]})]})}function Se({serverId:t}){const[n,o]=l.useState([]),[i,p]=l.useState(!1),[m,r]=l.useState(!1),[b,u]=l.useState(!1),g=l.useRef(null),f=l.useRef(!1),h=l.useRef(null);f.current=m,l.useEffect(()=>{const d=new EventSource(`/api/mcp/servers/${encodeURIComponent(t)}/logs/stream`);return h.current=d,d.onopen=()=>p(!0),d.onerror=()=>p(!1),d.onmessage=y=>{f.current||o(S=>[...S.slice(-500),y.data])},()=>{d.close(),h.current=null}},[t]),l.useEffect(()=>{!m&&g.current&&(g.current.scrollTop=g.current.scrollHeight)},[n,m]);function N(){const d=g.current;if(!d)return;const y=d.scrollHeight-d.scrollTop-d.clientHeight<40;!y&&!f.current&&r(!0),y&&f.current&&r(!1)}async function j(){await navigator.clipboard.writeText(n.join(` `)),u(!0),setTimeout(()=>u(!1),1500)}return e.jsxs("div",{className:"flex flex-col h-full overflow-hidden",children:[e.jsxs("div",{className:"flex items-center gap-3 px-4 py-2 border-b border-white/[0.06] shrink-0",children:[e.jsx("span",{className:`w-2 h-2 rounded-full ${i?"bg-emerald-500":"bg-zinc-500"}`,"aria-label":i?"Connected":"Disconnected"}),e.jsx("span",{className:"text-xs text-shell-text-secondary",children:i?"Live":"Disconnected"}),m&&e.jsx("span",{className:"text-xs text-amber-400",children:"Paused — scroll to bottom to resume"}),e.jsx("div",{className:"flex-1"}),e.jsx(k,{size:"sm",variant:"ghost",onClick:j,"aria-label":"Copy all logs",children:b?e.jsx(D,{size:13}):e.jsx(de,{size:13})})]}),e.jsxs("div",{ref:g,onScroll:N,className:"flex-1 overflow-y-auto p-4 font-mono text-[11px] leading-relaxed text-shell-text-secondary whitespace-pre-wrap",role:"log","aria-label":"Server logs","aria-live":"polite",children:[n.length===0&&e.jsx("span",{className:"text-shell-text-tertiary",children:"Waiting for log lines..."}),n.map((d,y)=>{const S=/error|exception|traceback/i.test(d);return e.jsx("div",{className:S?"text-red-400":"",children:d},y)})]})]})}function Ce({serverId:t}){const[n,o]=l.useState([]);return l.useEffect(()=>{function i(){fetch(`/api/mcp/servers/${encodeURIComponent(t)}/used-by`,{headers:{Accept:"application/json"}}).then(m=>m.json()).then(m=>o(Array.isArray(m)?m:[])).catch(()=>{})}i();const p=setInterval(i,3e3);return()=>clearInterval(p)},[t]),e.jsx("div",{className:"p-4 overflow-y-auto h-full",children:n.length===0?e.jsxs("div",{className:"flex flex-col items-center justify-center gap-2 py-12 text-center",children:[e.jsx("p",{className:"text-sm text-shell-text-secondary",children:"No agents currently calling this server"}),e.jsx("p",{className:"text-xs text-shell-text-tertiary",children:"Updates every 3 seconds"})]}):e.jsx("div",{className:"space-y-2",children:n.map((i,p)=>e.jsxs(T,{className:"px-3 py-2.5 flex items-center gap-3",children:[e.jsx("span",{className:"w-2 h-2 rounded-full bg-emerald-500 shrink-0","aria-label":"Active"}),e.jsxs("div",{className:"flex-1 min-w-0",children:[e.jsx("p",{className:"text-sm font-medium text-shell-text",children:i.agent_name}),i.tool&&e.jsx("p",{className:"text-xs text-shell-text-secondary font-mono",children:i.tool})]}),i.started_at&&e.jsx("span",{className:"text-xs text-shell-text-secondary",children:G(i.started_at)})]},p))})})}function ke({server:t,onRefreshList:n,onDeselect:o}){const[i,p]=l.useState("overview"),[m,r]=l.useState([]),[b,u]=l.useState([]),[g,f]=l.useState(null),[h,N]=l.useState(!1),[j,d]=l.useState(!1),y=ae(c=>c.addNotification);function S(){fetch(`/api/mcp/servers/${encodeURIComponent(t.id)}/permissions`,{headers:{Accept:"application/json"}}).then(c=>c.json()).then(c=>u(Array.isArray(c)?c:[])).catch(()=>{})}l.useEffect(()=>{S(),fetch(`/api/mcp/servers/${encodeURIComponent(t.id)}/capabilities`,{headers:{Accept:"application/json"}}).then(c=>c.json()).then(c=>r(Array.isArray(c)?c:c.capabilities??[])).catch(()=>{})},[t.id]);async function s(c){f(c);try{await fetch(`/api/mcp/servers/${encodeURIComponent(t.id)}/${c}`,{method:"POST"}),n()}catch{y({source:"mcp",title:"Action failed",body:`Failed to ${c} ${t.name}`,level:"error"})}f(null)}async function x(){d(!0);try{const A=await(await fetch(`/api/mcp/servers/${encodeURIComponent(t.id)}`,{method:"DELETE"})).json().catch(()=>({})),z=A.agents_affected??b.length,_=A.secrets_dropped??0;y({source:"mcp",title:`Removed ${t.name}`,body:`${z} agent${z!==1?"s":""} lost access, ${_} secret${_!==1?"s":""} dropped.`,level:"info"}),N(!1),o(),n()}catch{y({source:"mcp",title:"Uninstall failed",body:`Could not uninstall ${t.name}`,level:"error"})}d(!1)}const v=[{id:"overview",label:"Overview"},{id:"permissions",label:"Permissions"},{id:"env",label:"Env"},{id:"config",label:"Config"},{id:"logs",label:"Logs"},{id:"used-by",label:"Used by"}];return e.jsxs("div",{className:"flex flex-col h-full overflow-hidden",children:[e.jsxs("div",{className:"shrink-0 px-4 py-3 border-b border-white/[0.06] flex items-center gap-3",children:[e.jsx("div",{className:"w-8 h-8 rounded-lg bg-white/[0.06] flex items-center justify-center shrink-0",children:e.jsx(I,{size:15,className:"text-shell-text-secondary","aria-hidden":!0})}),e.jsxs("div",{className:"flex-1 min-w-0",children:[e.jsx("h2",{className:"text-sm font-semibold text-shell-text truncate",children:t.name}),e.jsxs("p",{className:"text-[11px] text-shell-text-secondary",children:["v",t.version]})]}),e.jsx("span",{className:`text-[10px] px-2 py-0.5 rounded-full font-medium ${F[t.status]}`,children:P[t.status]}),g&&e.jsx($,{size:14,className:"animate-spin text-shell-text-secondary shrink-0","aria-label":"Loading"})]}),e.jsx("div",{className:"shrink-0 border-b border-white/[0.06] overflow-x-auto",children:e.jsx("div",{className:"flex min-w-max px-2",role:"tablist","aria-label":"Server detail tabs",children:v.map(c=>e.jsx("button",{role:"tab","aria-selected":i===c.id,onClick:()=>p(c.id),className:`px-3 py-2.5 text-xs font-medium whitespace-nowrap transition-colors border-b-2 ${i===c.id?"border-accent text-shell-text":"border-transparent text-shell-text-secondary hover:text-shell-text"}`,children:c.label},c.id))})}),e.jsxs("div",{className:"flex-1 min-h-0 overflow-hidden",children:[i==="overview"&&e.jsx(ve,{server:t,capabilities:m,attachments:b,onAction:s,onUninstall:()=>N(!0)}),i==="permissions"&&e.jsx(Ne,{serverId:t.id,attachments:b,onRefresh:S}),i==="env"&&e.jsx(ye,{serverId:t.id}),i==="config"&&e.jsx(we,{serverId:t.id}),i==="logs"&&e.jsx(Se,{serverId:t.id}),i==="used-by"&&e.jsx(Ce,{serverId:t.id})]}),h&&e.jsx(fe,{server:t,attachments:b,loading:j,onConfirm:x,onClose:()=>N(!1)})]})}function Ie({windowId:t}){const[n,o]=l.useState([]),[i,p]=l.useState(!0),[m,r]=l.useState(null),b=se(j=>j.openWindow),u=l.useCallback(async()=>{try{const j=await fetch("/api/mcp/servers",{headers:{Accept:"application/json"}});if(j.ok){const d=await j.json();o(Array.isArray(d)?d:d.servers??[])}}catch{}finally{p(!1)}},[]);l.useEffect(()=>{u();const j=setInterval(u,1e4);return()=>clearInterval(j)},[u]);const g=n.find(j=>j.id===m)??null;function f(){const j=le("store");j&&b("store",j.defaultSize)}const h=e.jsx(be,{servers:n,loading:i,selectedId:m,onSelect:r,onOpenStore:f}),N=g?e.jsx(ke,{server:g,onRefreshList:u,onDeselect:()=>r(null)}):null;return e.jsx(te,{list:h,detail:N,selectedId:m,onBack:()=>r(null),listTitle:"MCP",detailTitle:(g==null?void 0:g.name)??""})}export{Ie as MCPApp}; diff --git a/static/desktop/assets/MessagesApp-CkhTvSE9.js b/static/desktop/assets/MessagesApp-CkhTvSE9.js new file mode 100644 index 00000000..62b50f9c --- /dev/null +++ b/static/desktop/assets/MessagesApp-CkhTvSE9.js @@ -0,0 +1 @@ +import{r as o,j as e,p as ns,b as as}from"./vendor-react-l6srOxy7.js";import{B as F,r as ot,T as rs,L as te,I as xe,C as is,a as ls,b as os,c as cs}from"./toolbar-UW6q5pkx.js";import{M as ds}from"./MobileSplitView-B-4MQO2C.js";import{u as us}from"./use-is-mobile-v5lglusa.js";import{s as hs,g as ct,e as ps}from"./dnd-bus-CdEoCWzR.js";import{W as fe,z as dt,D as Te,E as ce,R as ut,y as ht,G as pt,J as mt,U as Ae,K as xt,v as ft,N as gt,X as ge,O as ms,Q as xs,g as bt}from"./vendor-icons--yQaiqiL.js";import"./vendor-radix-BhM7AEEG.js";import"./vendor-layout-B-pp9n1f.js";function yt(){if(typeof window>"u")return{height:0,keyboardInset:0};const s=window.visualViewport;if(!s)return{height:window.innerHeight,keyboardInset:0};const a=Math.max(0,window.innerHeight-s.height-s.offsetTop);return{height:s.height,keyboardInset:a}}function fs(){const[s,a]=o.useState(yt);return o.useEffect(()=>{if(typeof window>"u")return;const r=window.visualViewport;if(!r)return;const l=()=>a(yt());return r.addEventListener("resize",l),r.addEventListener("scroll",l),()=>{r.removeEventListener("resize",l),r.removeEventListener("scroll",l)}},[]),s}function gs(s){const{accept:a,onDrop:r,disabled:l=!1}=s,d=o.useSyncExternalStore(hs,ct,()=>null),p=o.useRef(0),[m,g]=o.useState(!1),k=!l&&d!==null&&a.includes(d.kind);return o.useEffect(()=>{d===null&&(p.current=0,g(!1))},[d]),{isOver:m,isValidTarget:k,dropHandlers:{onDragEnter:x=>{l||!k||(x.preventDefault(),p.current+=1,p.current===1&&g(!0))},onDragOver:x=>{l||!k||x.preventDefault()},onDragLeave:x=>{l||!k||(p.current=Math.max(0,p.current-1),p.current===0&&g(!1))},onDrop:x=>{p.current=0,g(!1);const v=ct();if(!l&&v&&a.includes(v.kind)){x.preventDefault();try{const u=r(v);u&&typeof u.then=="function"&&u.catch(S=>console.warn("drop handler failed",S))}catch(u){console.warn("drop handler failed",u)}ps()}}}}}async function bs(s){try{return await s.json()}catch{return null}}async function ue(s){if(s.ok)return;const a=await bs(s);throw new Error((a==null?void 0:a.error)||`HTTP ${s.status}`)}async function ys(s,a){const r=await fetch(`/api/chat/channels/${encodeURIComponent(s)}`,{method:"PATCH",headers:{"Content-Type":"application/json"},body:JSON.stringify(a)});await ue(r)}async function ws(s,a){const r=await fetch(`/api/chat/channels/${encodeURIComponent(s)}/members`,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({action:"add",slug:a})});await ue(r)}async function Nt(s,a){const r=await fetch(`/api/chat/channels/${encodeURIComponent(s)}/members`,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({action:"remove",slug:a})});await ue(r)}async function St(s,a){const r=await fetch(`/api/chat/channels/${encodeURIComponent(s)}/muted`,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({action:"add",slug:a})});await ue(r)}async function Ct(s,a){const r=await fetch(`/api/chat/channels/${encodeURIComponent(s)}/muted`,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({action:"remove",slug:a})});await ue(r)}function vs({channel:s,knownAgents:a,onClose:r,onChanged:l}){const[d,p]=o.useState(s.name),[m,g]=o.useState(s.topic||""),[k,x]=o.useState(s.settings.response_mode??"quiet"),[v,u]=o.useState(s.settings.max_hops??3),[S,$]=o.useState(s.settings.cooldown_seconds??5),[z,h]=o.useState(null);o.useEffect(()=>{p(s.name),g(s.topic||""),x(s.settings.response_mode??"quiet"),u(s.settings.max_hops??3),$(s.settings.cooldown_seconds??5)},[s]);const E=async(b,T)=>{h(null);try{await ys(s.id,b),l()}catch(K){T(),h(K instanceof Error?K.message:"failed")}},C=s.members||[],f=s.settings.muted||[],A=a.map(b=>b.name).filter(b=>!C.includes(b)),N=C.filter(b=>b!=="user"&&!f.includes(b));return e.jsxs("aside",{role:"complementary","aria-label":"Channel settings",className:"fixed top-0 right-0 h-full w-[360px] bg-shell-surface border-l border-white/10 shadow-xl flex flex-col z-40",children:[e.jsxs("header",{className:"flex items-center justify-between px-4 py-3 border-b border-white/10",children:[e.jsx("h2",{className:"text-sm font-semibold",children:"Channel settings"}),e.jsx("button",{onClick:r,"aria-label":"Close",className:"text-lg leading-none",children:"×"})]}),e.jsxs("div",{className:"flex-1 overflow-y-auto px-4 py-4 flex flex-col gap-5 text-sm",children:[e.jsxs("section",{"aria-label":"Overview",className:"flex flex-col gap-3",children:[e.jsx("h3",{className:"text-xs uppercase tracking-wider text-shell-text-tertiary",children:"Overview"}),e.jsxs("label",{className:"flex flex-col gap-1",children:[e.jsx("span",{className:"text-xs text-shell-text-secondary",children:"Name"}),e.jsx("input",{value:d,maxLength:100,onChange:b=>p(b.target.value),onBlur:()=>d!==s.name&&E({name:d},()=>p(s.name)),className:"bg-white/5 border border-white/10 rounded px-2 py-1.5 text-sm"})]}),e.jsxs("label",{className:"flex flex-col gap-1",children:[e.jsx("span",{className:"text-xs text-shell-text-secondary",children:"Topic"}),e.jsx("textarea",{value:m,maxLength:500,rows:3,onChange:b=>g(b.target.value),onBlur:()=>m!==(s.topic||"")&&E({topic:m},()=>g(s.topic||"")),className:"bg-white/5 border border-white/10 rounded px-2 py-1.5 text-sm resize-none"})]}),e.jsxs("div",{className:"text-[11px] text-shell-text-tertiary",children:["Type: ",e.jsx("span",{className:"uppercase tracking-wide",children:s.type})]})]}),e.jsxs("section",{"aria-label":"Members",className:"flex flex-col gap-2",children:[e.jsx("h3",{className:"text-xs uppercase tracking-wider text-shell-text-tertiary",children:"Members"}),e.jsx("ul",{className:"flex flex-col gap-1",children:C.map(b=>e.jsxs("li",{className:"flex items-center justify-between px-2 py-1 rounded hover:bg-white/5",children:[e.jsxs("span",{children:["@",b]}),b!=="user"&&e.jsx("button",{className:"text-xs text-red-300 hover:text-red-200",onClick:async()=>{try{await Nt(s.id,b),l()}catch(T){h(T instanceof Error?T.message:"failed")}},children:"Remove"})]},b))}),A.length>0&&e.jsx(wt,{label:"Add agent",options:A,onPick:async b=>{try{await ws(s.id,b),l()}catch(T){h(T instanceof Error?T.message:"failed")}}})]}),e.jsxs("section",{"aria-label":"Moderation",className:"flex flex-col gap-3",children:[e.jsx("h3",{className:"text-xs uppercase tracking-wider text-shell-text-tertiary",children:"Moderation"}),e.jsxs("div",{className:"flex items-center gap-2",children:[e.jsx("span",{className:"text-xs text-shell-text-secondary",children:"Mode:"}),e.jsx("button",{className:`px-2 py-1 rounded text-xs ${k==="quiet"?"bg-sky-500/30 text-sky-200":"bg-white/5"}`,onClick:()=>E({response_mode:"quiet"},()=>x(k)),children:"quiet"}),e.jsx("button",{className:`px-2 py-1 rounded text-xs ${k==="lively"?"bg-emerald-500/30 text-emerald-200":"bg-white/5"}`,onClick:()=>E({response_mode:"lively"},()=>x(k)),children:"lively"})]}),e.jsxs("div",{className:"flex flex-col gap-1",children:[e.jsx("span",{className:"text-xs text-shell-text-secondary",children:"Muted"}),e.jsxs("div",{className:"flex flex-wrap gap-1",children:[f.map(b=>e.jsxs("span",{className:"inline-flex items-center gap-1 bg-white/5 rounded px-2 py-0.5 text-xs",children:["@",b,e.jsx("button",{"aria-label":`Unmute ${b}`,onClick:async()=>{try{await Ct(s.id,b),l()}catch(T){h(T instanceof Error?T.message:"failed")}},children:"×"})]},b)),f.length===0&&e.jsx("span",{className:"text-[11px] text-shell-text-tertiary",children:"none"})]}),N.length>0&&e.jsx(wt,{label:"Mute agent",options:N,onPick:async b=>{try{await St(s.id,b),l()}catch(T){h(T instanceof Error?T.message:"failed")}}})]})]}),e.jsxs("section",{"aria-label":"Advanced",className:"flex flex-col gap-3",children:[e.jsx("h3",{className:"text-xs uppercase tracking-wider text-shell-text-tertiary",children:"Advanced"}),e.jsxs("label",{className:"flex flex-col gap-1",children:[e.jsxs("span",{className:"text-xs text-shell-text-secondary",children:["Max hops: ",v]}),e.jsx("input",{type:"range",min:1,max:10,value:v,onChange:b=>u(Number(b.target.value)),onMouseUp:()=>E({max_hops:v},()=>u(s.settings.max_hops??3))})]}),e.jsxs("label",{className:"flex flex-col gap-1",children:[e.jsxs("span",{className:"text-xs text-shell-text-secondary",children:["Cooldown: ",S,"s"]}),e.jsx("input",{type:"range",min:0,max:60,value:S,onChange:b=>$(Number(b.target.value)),onMouseUp:()=>E({cooldown_seconds:S},()=>$(s.settings.cooldown_seconds??5))})]})]}),z&&e.jsx("div",{role:"alert",className:"text-xs text-red-300 bg-red-500/10 border border-red-500/30 rounded px-2 py-1",children:z})]})]})}function wt({label:s,options:a,onPick:r}){return e.jsxs("select",{"aria-label":s,defaultValue:"",onChange:l=>{l.target.value&&(r(l.target.value),l.target.value="")},className:"bg-white/5 border border-white/10 rounded px-2 py-1 text-xs",children:[e.jsxs("option",{value:"",disabled:!0,children:[s,"…"]}),a.map(l=>e.jsxs("option",{value:l,children:["@",l]},l))]})}function js({slug:s,channelId:a,channelType:r,isMuted:l,x:d,y:p,onClose:m,onDm:g,onViewInfo:k,onJumpToSettings:x}){const v=o.useRef(null);o.useEffect(()=>{const z=E=>{v.current&&!v.current.contains(E.target)&&m()},h=E=>{E.key==="Escape"&&m()};return document.addEventListener("mousedown",z),document.addEventListener("keydown",h),()=>{document.removeEventListener("mousedown",z),document.removeEventListener("keydown",h)}},[m]);const u=r==="dm",S=async()=>{if(a)try{l?await Ct(a,s):await St(a,s)}finally{m()}},$=async()=>{if(a)try{await Nt(a,s)}finally{m()}};return e.jsxs("div",{ref:v,role:"menu","aria-label":`Actions for @${s}`,className:"fixed z-50 min-w-[200px] bg-shell-surface border border-white/10 rounded-lg shadow-xl py-1 text-sm",style:{top:p,left:d},children:[e.jsxs(de,{onClick:()=>{g==null||g(s),m()},children:["DM @",s]}),a&&!u&&e.jsxs(de,{onClick:S,children:[l?"Unmute":"Mute"," in this channel"]}),a&&!u&&e.jsx(de,{onClick:$,children:"Remove from channel"}),e.jsx("div",{className:"my-1 h-px bg-white/10"}),e.jsx(de,{onClick:()=>{k==null||k(s),m()},children:"View agent info"}),e.jsx(de,{onClick:()=>{x==null||x(s),m()},children:"Jump to agent settings"})]})}function de({onClick:s,children:a}){return e.jsx("button",{role:"menuitem",onClick:s,className:"w-full text-left px-3 py-1.5 hover:bg-white/5 focus:bg-white/5 focus:outline-none",children:a})}function ks({commands:s,queryAfterSlash:a,members:r,onPick:l,onClose:d}){const[p,m]=o.useState(0),g=o.useMemo(()=>Ns(s,r,a),[s,r,a]),k=g.filter(x=>x.kind==="cmd");return o.useEffect(()=>{m(0)},[a]),o.useEffect(()=>{const x=v=>{if(v.key==="Escape"){v.preventDefault(),d();return}if(v.key==="ArrowDown"){v.preventDefault(),m(u=>Math.min(k.length-1,u+1));return}if(v.key==="ArrowUp"){v.preventDefault(),m(u=>Math.max(0,u-1));return}if(v.key==="Enter"){v.preventDefault();const u=k[p];u&&l(u.slug,u.cmd.name)}};return document.addEventListener("keydown",x,!0),()=>document.removeEventListener("keydown",x,!0)},[k,p,l,d]),k.length===0&&g.length===0?null:e.jsx("div",{role:"listbox","aria-label":"Slash commands",className:"absolute bottom-full left-0 mb-2 w-full max-w-md bg-shell-surface border border-white/10 rounded-lg shadow-xl max-h-60 overflow-y-auto text-sm",children:g.length===0?e.jsx("div",{className:"px-3 py-2 text-xs text-shell-text-tertiary",children:"(no commands available)"}):g.map(x=>{if(x.kind==="header")return e.jsxs("div",{className:"px-3 py-1 text-[11px] uppercase tracking-wider text-shell-text-tertiary bg-white/5",children:["@",x.slug]},`h-${x.slug}`);const v=k.indexOf(x),u=v===p;return e.jsxs("button",{role:"option","aria-selected":u,onMouseEnter:()=>m(v),onClick:()=>l(x.slug,x.cmd.name),className:`w-full text-left px-3 py-1.5 flex items-center justify-between gap-3 ${u?"bg-white/10":"hover:bg-white/5"}`,children:[e.jsxs("span",{className:"font-mono text-[13px]",children:["/",x.cmd.name]}),e.jsx("span",{className:"text-xs text-shell-text-tertiary truncate",children:x.cmd.description})]},`${x.slug}-${x.cmd.name}`)})})}function Ns(s,a,r){const l=r.toLowerCase(),d=a.filter(g=>g!=="user"&&s[g]),p=d.length===1,m=[];for(const g of d){const k=(s[g]||[]).filter(x=>Ss(g,x,l));if(k.length!==0){p||m.push({kind:"header",slug:g});for(const x of k)m.push({kind:"cmd",slug:g,cmd:x})}}return m}function Ss(s,a,r){if(!r)return!0;const l=`${s} ${a.name} ${a.description}`.toLowerCase();let d=0;for(const p of r.split(/\s+/).join("")){const m=l.indexOf(p,d);if(m===-1)return!1;d=m+1}return!0}function Cs({humans:s,agents:a,selfId:r="user"}){const l=s.filter(g=>g!==r),d=l.length>0,p=a.length>0;if(!d&&!p)return null;const m=Es(l);return e.jsxs("div",{"aria-live":"polite",className:"px-4 pt-1 text-xs text-shell-text-tertiary flex flex-col gap-0.5",children:[m&&e.jsx("span",{children:m}),a.map(g=>{const{icon:k,text:x}=_s(g.phase,g.detail);return e.jsxs("span",{className:"italic",children:[k," @",g.slug," is ",x,"…"]},g.slug)})]})}function Es(s){return s.length===0?null:s.length===1?`${s[0]} is typing…`:s.length===2?`${s[0]} and ${s[1]} are typing…`:`${s[0]} and ${s.length-1} others are typing…`}function _s(s,a){const r=a?a.length>40?a.slice(0,39)+"…":a:null;switch(s){case"tool":return{icon:"🔧",text:r?`using ${r}`:"using a tool"};case"reading":return{icon:"📖",text:r?`reading ${r}`:"reading"};case"writing":return{icon:"✏️",text:r?`writing ${r}`:"writing"};case"searching":return{icon:"🔍",text:r?`searching ${r}`:"searching"};case"planning":return{icon:"📋",text:"planning"};case"thinking":default:return{icon:"💭",text:"thinking"}}}function $s(s,a,r=1e3){const l=o.useRef(0);return o.useCallback(()=>{if(!s)return;const d=Date.now();d-l.current{}))},[s,a,r])}function Ts({onReact:s,onReplyInThread:a,onOverflow:r}){return e.jsxs("div",{role:"toolbar","aria-label":"Message actions",className:"inline-flex items-center gap-0.5 bg-shell-surface border border-white/10 rounded-md shadow-sm px-1",children:[e.jsx("button",{"aria-label":"Add reaction",onClick:s,className:"p-1 hover:bg-white/5",children:"😀"}),e.jsx("button",{"aria-label":"Reply in thread",onClick:a,className:"p-1 hover:bg-white/5",children:"💬"}),e.jsx("button",{"aria-label":"More",onClick:r,className:"p-1 hover:bg-white/5",children:"⋯"})]})}function As({replyCount:s,lastReplyAt:a,onOpen:r}){if(s===0)return null;const l=a?`💬 ${s} repl${s===1?"y":"ies"} · last reply ${Ms(a)}`:`💬 ${s} repl${s===1?"y":"ies"}`;return e.jsx("button",{onClick:r,className:"mt-1 px-2 py-0.5 text-xs text-sky-200 hover:bg-white/5 rounded","aria-label":"Open thread",children:l})}function Ms(s){const a=Date.now()/1e3,r=Math.max(0,a-s);return r<60?"just now":r<3600?`${Math.floor(r/60)}m ago`:r<86400?`${Math.floor(r/3600)}h ago`:`${Math.floor(r/86400)}d ago`}function zs({channelId:s,parentId:a,onClose:r,onSend:l,isFullscreen:d=!1}){const[p,m]=o.useState(null),[g,k]=o.useState([]),[x,v]=o.useState(""),[u,S]=o.useState(null),[$,z]=o.useState(null),[h,E]=o.useState(!1),C=o.useRef(null);o.useEffect(()=>{const N=new AbortController;return S(null),fetch(`/api/chat/messages/${a}`,{signal:N.signal}).then(b=>{if(!b.ok)throw new Error(`parent fetch failed (${b.status})`);return b.json()}).then(b=>m(b)).catch(b=>{b.name!=="AbortError"&&S("couldn't load this thread")}),()=>N.abort()},[a]),o.useEffect(()=>{const N=new AbortController;return fetch(`/api/chat/channels/${s}/threads/${a}/messages`,{signal:N.signal}).then(b=>b.ok?b.json():{messages:[]}).then(b=>k(b.messages||[])).catch(b=>{b.name!=="AbortError"&&S("couldn't load this thread")}),()=>N.abort()},[s,a]);async function f(){const N=x.trim();if(!(!N||h)){E(!0),z(null);try{await l(N,[]),v("")}catch(b){z(b.message||"couldn't send reply")}finally{E(!1)}}}function A(N){N.key==="Enter"&&!N.shiftKey&&(N.preventDefault(),f())}return e.jsxs("div",{className:d?"fixed inset-0 z-50 bg-shell-surface flex flex-col":"fixed top-0 right-0 h-full w-[360px] bg-shell-surface border-l border-white/10 flex flex-col z-40",role:"complementary","aria-label":"Thread panel",style:d?{paddingTop:"env(safe-area-inset-top, 0px)"}:void 0,children:[e.jsxs("div",{className:"flex items-center justify-between px-4 py-3 border-b border-white/10",children:[e.jsx("span",{className:"font-semibold text-sm",children:"Thread"}),e.jsx("button",{"aria-label":d?"Back":"Close thread",onClick:r,className:"p-1 hover:bg-white/5 rounded",children:d?"◀":"✕"})]}),e.jsxs("div",{className:"flex-1 overflow-y-auto px-4 py-3 flex flex-col gap-3",children:[p&&e.jsxs("div",{className:"pb-3 border-b border-white/10",children:[e.jsx("div",{className:"text-xs text-white/50 mb-1",children:p.author_id}),e.jsx("div",{className:"text-sm",children:p.content})]}),g.map(N=>e.jsxs("div",{children:[e.jsx("div",{className:"text-xs text-white/50 mb-0.5",children:N.author_id}),e.jsx("div",{className:"text-sm",children:N.content})]},N.id)),u&&e.jsx("div",{role:"alert",className:"text-xs text-red-300",children:u})]}),e.jsxs("div",{className:"px-4 py-3 border-t border-white/10",children:[$&&e.jsx("div",{role:"alert",className:"text-xs text-red-300 mb-2",children:$}),e.jsx("textarea",{ref:C,value:x,onChange:N=>v(N.target.value),onKeyDown:A,placeholder:"Reply in thread…","aria-label":"Thread reply",rows:2,disabled:h,className:"w-full bg-white/5 rounded px-3 py-2 text-sm resize-none outline-none border border-white/10 focus:border-sky-400 disabled:opacity-50"})]})]})}function Ds({items:s,onRemove:a,onRetry:r}){return s.length===0?null:e.jsx("div",{"aria-label":"Pending attachments",className:"px-4 py-2 border-t border-white/10 flex gap-2 flex-wrap",children:s.map(l=>e.jsxs("div",{className:"flex items-center gap-2 bg-white/5 rounded px-2 py-1 text-xs max-w-[220px]",children:[e.jsx("span",{className:"truncate",children:l.filename}),e.jsxs("span",{className:"opacity-50",children:[Math.max(1,Math.round(l.size/1024))," KB"]}),l.uploading&&e.jsx("span",{className:"opacity-70",children:"…"}),l.error&&e.jsx("button",{"aria-label":"Retry upload",onClick:()=>r(l.id),className:"text-red-300",children:"retry"}),e.jsx("button",{"aria-label":`Remove ${l.filename}`,onClick:()=>a(l.id),className:"opacity-70 hover:opacity-100",children:"×"})]},l.id))})}function Ps({images:s,startIndex:a,onClose:r}){const[l,d]=o.useState(a);o.useEffect(()=>{const m=g=>{g.key==="Escape"&&r(),g.key==="ArrowLeft"&&d(k=>Math.max(0,k-1)),g.key==="ArrowRight"&&d(k=>Math.min(s.length-1,k+1))};return document.addEventListener("keydown",m),()=>document.removeEventListener("keydown",m)},[s.length,r]);const p=s[l];return e.jsxs("div",{role:"dialog","aria-label":"Image viewer",className:"fixed inset-0 z-50 bg-black/80 flex items-center justify-center",onClick:r,children:[e.jsx("img",{src:p.url,alt:p.filename,className:"max-w-[90vw] max-h-[90vh]",onClick:m=>m.stopPropagation()}),e.jsxs("div",{className:"absolute top-4 right-4 flex gap-2",children:[e.jsx("a",{href:p.url,download:p.filename,onClick:m=>m.stopPropagation(),className:"bg-white/10 hover:bg-white/20 rounded px-3 py-1 text-sm",children:"Download"}),e.jsx("button",{onClick:r,className:"bg-white/10 hover:bg-white/20 rounded px-3 py-1 text-sm",children:"Close"})]}),s.length>1&&e.jsxs("div",{className:"absolute bottom-4 text-white/70 text-xs",children:[l+1," / ",s.length]})]})}function Rs({attachments:s}){const[a,r]=o.useState(null);if(!(s!=null&&s.length))return null;const l=s.filter(m=>{var g;return(g=m.mime_type)==null?void 0:g.startsWith("image/")}),d=s.filter(m=>{var g;return!((g=m.mime_type)!=null&&g.startsWith("image/"))}),p=l.length>1?"grid grid-cols-2 gap-1 max-w-md":"";return e.jsxs("div",{className:"flex flex-col gap-2 mt-1",children:[l.length>0&&e.jsx("div",{className:p,children:l.slice(0,4).map((m,g)=>e.jsxs("button",{onClick:()=>r(g),className:"relative block",children:[e.jsx("img",{src:m.url,alt:m.filename,className:l.length===1?"max-w-[560px] max-h-[400px] rounded":"object-cover w-full h-32 rounded"}),l.length>4&&g===3&&e.jsxs("span",{className:"absolute inset-0 bg-black/60 flex items-center justify-center text-white",children:["+",l.length-4," more"]})]},m.url))}),d.length>0&&e.jsx("div",{className:"flex flex-col gap-1",children:d.map(m=>e.jsxs("a",{href:m.url,target:"_blank",rel:"noreferrer",className:"flex items-center gap-2 bg-white/5 hover:bg-white/10 rounded px-2 py-1 text-sm max-w-sm",children:[e.jsx("span",{"aria-hidden":!0,children:"📄"}),e.jsx("span",{className:"truncate",children:m.filename}),e.jsxs("span",{className:"ml-auto text-xs opacity-60",children:[Math.max(1,Math.round(m.size/1024))," KB"]})]},m.url))}),a!==null&&e.jsx(Ps,{images:l,startIndex:a,onClose:()=>r(null)})]})}async function Et(s){if(s.ok)return;let a=null;try{a=await s.json()}catch{}throw new Error((a==null?void 0:a.error)||`HTTP ${s.status}`)}async function Me(s,a){const r=new FormData;r.append("file",s),a&&r.append("channel_id",a);const l=await fetch("/api/chat/upload",{method:"POST",body:r});await Et(l);const d=await l.json();return{filename:d.filename,mime_type:d.mime_type||d.content_type||"application/octet-stream",size:d.size,url:d.url,source:"disk"}}async function vt(s){const a=await fetch("/api/chat/attachments/from-path",{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify(s)});return await Et(a),a.json()}function Os(){const[s,a]=o.useState(null);return{openThread:s,openThreadFor:(r,l)=>a({channelId:r,parentId:l}),closeThread:()=>a(null)}}function Ls(s,a){const r=a?`?path=${encodeURIComponent(a)}`:"";if(s==="/workspaces/user")return`/api/workspace/files${r}`;if(s.startsWith("/workspaces/agent/")){const l=s.slice(18);return`/api/agents/${encodeURIComponent(l)}/workspace/files${r}`}return`/api/workspace/files${r}`}function jt({root:s,onSelect:a,multi:r=!1}){const[l,d]=o.useState(""),[p,m]=o.useState([]),[g,k]=o.useState(new Set),[x,v]=o.useState(!1),[u,S]=o.useState(null);o.useEffect(()=>{let C=!1;return v(!0),S(null),fetch(Ls(s,l)).then(async f=>{if(!f.ok)throw new Error(`HTTP ${f.status}`);return f.json()}).then(f=>{if(C)return;const N=(Array.isArray(f)?f:[]).map(b=>({name:b.name,type:b.is_dir?"folder":"file",size:b.size,modified:b.modified?new Date(b.modified*1e3).toISOString():void 0}));N.sort((b,T)=>b.type!==T.type?b.type==="folder"?-1:1:b.name.localeCompare(T.name)),m(N)}).catch(f=>{C||(S(f instanceof Error?f.message:"Failed to load"),m([]))}).finally(()=>{C||v(!1)}),()=>{C=!0}},[s,l]);function $(C){const f=l?`${l}/${C}`:C;return`${s}/${f}`}function z(C){d(f=>f?`${f}/${C}`:C),k(new Set)}function h(C){const f=$(C);if(!r){a(f);return}k(A=>{const N=new Set(A);return N.has(f)?N.delete(f):N.add(f),a(Array.from(N)),N})}function E(){d(C=>{const f=C.split("/").filter(Boolean);return f.pop(),f.join("/")}),k(new Set)}return e.jsxs("div",{className:"vfs-browser",role:"region","aria-label":"File browser",children:[l&&e.jsx("button",{onClick:E,"aria-label":"Go up one folder",style:{marginBottom:4},children:"↑ .."}),x&&e.jsx("p",{children:"Loading…"}),u&&e.jsxs("p",{role:"alert",children:["Error: ",u]}),!x&&!u&&p.length===0&&e.jsx("p",{children:"Empty folder"}),e.jsx("ul",{style:{listStyle:"none",padding:0,margin:0},children:p.map(C=>{const f=$(C.name),A=g.has(f);return e.jsx("li",{children:e.jsxs("button",{onClick:()=>C.type==="folder"?z(C.name):h(C.name),"aria-selected":r?A:void 0,style:{fontWeight:A?"bold":void 0},children:[C.type==="folder"?"📁 ":"📄 ",C.name]})},C.name)})})]})}function Is({sources:s,accept:a,multi:r=!1,onPick:l,onCancel:d}){const[p,m]=o.useState(s[0]??"disk"),[g,k]=o.useState([]),[x,v]=o.useState([]),[u,S]=o.useState(null),$=o.useRef(null);o.useEffect(()=>{s.includes("agent-workspace")&&fetch("/api/agents").then(f=>f.json()).then(f=>v(Array.isArray(f)?f:[])).catch(()=>{})},[s]),o.useEffect(()=>{const f=A=>{A.key==="Escape"&&(A.preventDefault(),d())};return document.addEventListener("keydown",f),()=>document.removeEventListener("keydown",f)},[d]);const z=f=>{if(!f)return;const A=[];for(const N of Array.from(f))A.push({source:"disk",file:N});k(N=>r?[...N,...A]:A)},h=f=>{const N=(Array.isArray(f)?f:[f]).map(b=>({source:"workspace",path:b}));k(b=>r?[...b.filter(T=>T.source!=="workspace"),...N]:N)},E=f=>{if(!u)return;const N=(Array.isArray(f)?f:[f]).map(b=>({source:"agent-workspace",slug:u,path:b}));k(b=>r?[...b.filter(T=>T.source!=="agent-workspace"),...N]:N)},C=()=>l(g);return e.jsx("div",{role:"dialog","aria-modal":"true","aria-label":"Pick a file",className:"fixed inset-0 z-50 flex items-center justify-center bg-black/60",children:e.jsxs("div",{className:"bg-shell-surface border border-white/10 rounded-xl w-[720px] h-[540px] flex flex-col overflow-hidden",children:[e.jsxs("div",{role:"tablist",className:"flex border-b border-white/10",children:[s.includes("disk")&&e.jsx("button",{role:"tab","aria-selected":p==="disk",className:`px-4 py-2 text-sm ${p==="disk"?"border-b-2 border-sky-400":"opacity-70"}`,onClick:()=>m("disk"),children:"Disk"}),s.includes("workspace")&&e.jsx("button",{role:"tab","aria-selected":p==="workspace",className:`px-4 py-2 text-sm ${p==="workspace"?"border-b-2 border-sky-400":"opacity-70"}`,onClick:()=>m("workspace"),children:"My workspace"}),s.includes("agent-workspace")&&e.jsx("button",{role:"tab","aria-selected":p==="agent-workspace",className:`px-4 py-2 text-sm ${p==="agent-workspace"?"border-b-2 border-sky-400":"opacity-70"}`,onClick:()=>m("agent-workspace"),children:"Agent workspaces"})]}),e.jsxs("div",{className:"flex-1 overflow-hidden",children:[p==="disk"&&e.jsxs("div",{className:"p-6 flex items-center justify-center",children:[e.jsx("input",{ref:$,type:"file",className:"hidden",multiple:r,accept:a,onChange:f=>z(f.target.files)}),e.jsx("button",{onClick:()=>{var f;return(f=$.current)==null?void 0:f.click()},className:"px-4 py-2 bg-sky-500/20 text-sky-200 rounded",children:"Choose files from disk"}),g.filter(f=>f.source==="disk").length>0&&e.jsxs("div",{className:"ml-6 text-xs text-shell-text-tertiary",children:[g.length," file(s) queued"]})]}),p==="workspace"&&e.jsx(jt,{root:"/workspaces/user",onSelect:h,multi:r}),p==="agent-workspace"&&e.jsxs("div",{className:"h-full flex flex-col",children:[e.jsx("div",{className:"p-2 border-b border-white/10",children:e.jsxs("select",{value:u??"",onChange:f=>S(f.target.value||null),className:"bg-white/5 border border-white/10 rounded px-2 py-1 text-sm",children:[e.jsx("option",{value:"",children:"Pick an agent…"}),x.map(f=>e.jsxs("option",{value:f.name,children:["@",f.name]},f.name))]})}),u&&e.jsx(jt,{root:`/workspaces/agent/${u}`,onSelect:E,multi:r})]})]}),e.jsxs("div",{className:"border-t border-white/10 p-2 flex items-center justify-end gap-2 text-sm",children:[e.jsxs("span",{className:"opacity-60 mr-auto",children:[g.length," selected"]}),e.jsx("button",{onClick:d,className:"px-3 py-1 opacity-70 hover:opacity-100",children:"Cancel"}),e.jsxs("button",{onClick:C,disabled:g.length===0,className:"px-3 py-1 bg-sky-500/30 text-sky-200 rounded disabled:opacity-40",children:["Select (",g.length,")"]})]})]})})}function Us(s){return new Promise(a=>{const r=document.createElement("div");document.body.appendChild(r);const l=ns.createRoot(r),d=()=>{l.unmount(),r.remove()};l.render(as.createElement(Is,{sources:s.sources,accept:s.accept,multi:s.multi,onPick:p=>{d(),a(p)},onCancel:()=>{d(),a([])}}))})}function Fs({isOwn:s,isHuman:a,isPinned:r=!1,onEdit:l,onDelete:d,onCopyLink:p,onPin:m,onMarkUnread:g,onClose:k}){const x=o.useRef(null);o.useEffect(()=>{var S;const u=(S=x.current)==null?void 0:S.querySelector('[role="menuitem"]');u==null||u.focus()},[]);const v=u=>{var h,E,C,f,A;const S=Array.from(((h=x.current)==null?void 0:h.querySelectorAll('[role="menuitem"]'))||[]),$=document.activeElement,z=$?S.indexOf($):-1;u.key==="ArrowDown"?(u.preventDefault(),(E=S[Math.min(S.length-1,z+1)])==null||E.focus()):u.key==="ArrowUp"?(u.preventDefault(),(C=S[Math.max(0,z-1)])==null||C.focus()):u.key==="Home"?(u.preventDefault(),(f=S[0])==null||f.focus()):u.key==="End"?(u.preventDefault(),(A=S[S.length-1])==null||A.focus()):u.key==="Escape"&&(u.preventDefault(),k==null||k())};return e.jsxs("div",{ref:x,role:"menu","aria-label":"Message overflow menu",onKeyDown:v,className:"bg-shell-surface border border-white/10 rounded-md shadow-lg py-1 min-w-[160px] text-sm",children:[s&&e.jsx("button",{role:"menuitem",onClick:l,className:"block w-full text-left px-3 py-1.5 hover:bg-white/5 focus:bg-white/5 focus:outline-none",children:"Edit"}),s&&e.jsx("button",{role:"menuitem",onClick:d,className:"block w-full text-left px-3 py-1.5 hover:bg-white/5 focus:bg-white/5 focus:outline-none text-red-300",children:"Delete"}),e.jsx("button",{role:"menuitem",onClick:p,className:"block w-full text-left px-3 py-1.5 hover:bg-white/5 focus:bg-white/5 focus:outline-none",children:"Copy link"}),a&&e.jsx("button",{role:"menuitem",onClick:m,className:"block w-full text-left px-3 py-1.5 hover:bg-white/5 focus:bg-white/5 focus:outline-none",children:r?"Unpin":"Pin"}),e.jsx("button",{role:"menuitem",onClick:g,className:"block w-full text-left px-3 py-1.5 hover:bg-white/5 focus:bg-white/5 focus:outline-none",children:"Mark unread"})]})}const Hs=80;function Ws({open:s,onClose:a,children:r,labelledBy:l,dragHandle:d=!0}){const p=o.useRef(null),[m,g]=o.useState(0);if(o.useEffect(()=>{if(!s)return;const x=v=>{v.key==="Escape"&&(v.preventDefault(),a())};return document.addEventListener("keydown",x),()=>document.removeEventListener("keydown",x)},[s,a]),o.useEffect(()=>{var u;if(!s)return;const x=document.activeElement,v=(u=p.current)==null?void 0:u.querySelector('button, [href], input, select, textarea, [tabindex]:not([tabindex="-1"])');return v==null||v.focus(),()=>{var S;(S=x==null?void 0:x.focus)==null||S.call(x)}},[s]),o.useEffect(()=>{if(!s)return;const x=v=>{if(v.key!=="Tab")return;const u=p.current;if(!u)return;const S=Array.from(u.querySelectorAll('button, [href], input, select, textarea, [tabindex]:not([tabindex="-1"])')).filter(E=>!E.hasAttribute("disabled"));if(S.length===0)return;const $=S[0],z=S[S.length-1],h=document.activeElement;v.shiftKey&&h===$?(v.preventDefault(),z.focus()):!v.shiftKey&&h===z&&(v.preventDefault(),$.focus())};return document.addEventListener("keydown",x),()=>document.removeEventListener("keydown",x)},[s]),!s)return null;const k=x=>{const v=x.clientY,u=x.currentTarget;u.setPointerCapture(x.pointerId);const S=h=>{const E=Math.max(0,h.clientY-v);g(E)},$=h=>{const E=Math.max(0,h.clientY-v);u.releasePointerCapture(x.pointerId),u.removeEventListener("pointermove",S),u.removeEventListener("pointerup",$),u.removeEventListener("pointercancel",z),E>Hs&&a(),g(0)},z=()=>{u.releasePointerCapture(x.pointerId),u.removeEventListener("pointermove",S),u.removeEventListener("pointerup",$),u.removeEventListener("pointercancel",z),g(0)};u.addEventListener("pointermove",S),u.addEventListener("pointerup",$),u.addEventListener("pointercancel",z)};return e.jsxs(e.Fragment,{children:[e.jsx("div",{"data-testid":"bottom-sheet-backdrop",className:"fixed inset-0 z-50 bg-black/60",onClick:a}),e.jsxs("div",{ref:p,role:"dialog","aria-modal":"true","aria-labelledby":l,className:"fixed bottom-0 inset-x-0 z-50 bg-shell-surface rounded-t-xl border-t border-white/10 shadow-2xl max-h-[85vh] overflow-y-auto",style:{paddingBottom:"env(safe-area-inset-bottom, 0px)",transform:`translateY(${m}px)`,transition:m===0?"transform 0.2s ease-out":"none"},children:[d&&e.jsx("div",{"data-testid":"bottom-sheet-handle",onPointerDown:k,className:"flex justify-center py-2 cursor-grab active:cursor-grabbing touch-none",children:e.jsx("div",{className:"w-10 h-1 bg-white/20 rounded-full"})}),r]})]})}function Bs({initial:s,onSave:a,onCancel:r}){const[l,d]=o.useState(s);return e.jsx("textarea",{autoFocus:!0,value:l,onChange:p=>d(p.target.value),onKeyDown:p=>{if(p.key==="Escape")p.preventDefault(),r();else if(p.key==="Enter"&&!p.shiftKey){p.preventDefault();const m=l.trim();m?a(m):r()}},"aria-label":"Edit message",rows:1,className:"w-full bg-white/5 border border-white/10 rounded px-2 py-1 text-sm"})}function Js(){return e.jsx("span",{className:"text-white/40 italic text-sm",children:"This message was deleted"})}function Ks({count:s,onClick:a}){return s===0?null:e.jsxs("button",{onClick:a,className:"ml-1 px-1.5 py-0.5 text-xs bg-white/5 hover:bg-white/10 rounded opacity-70 hover:opacity-100","aria-label":`Pinned messages (${s})`,children:["📌 ",s]})}function qs({pins:s,onJumpTo:a,onClose:r}){return e.jsxs("div",{role:"dialog","aria-label":"Pinned messages",className:"absolute top-full right-0 mt-1 w-[320px] max-h-[400px] overflow-y-auto bg-shell-surface border border-white/10 rounded-md shadow-lg z-40",children:[e.jsxs("header",{className:"flex items-center justify-between px-3 py-2 border-b border-white/10",children:[e.jsxs("span",{className:"text-xs font-semibold",children:["Pinned (",s.length,")"]}),e.jsx("button",{onClick:r,"aria-label":"Close",className:"text-sm opacity-70 hover:opacity-100",children:"×"})]}),s.length===0?e.jsx("div",{className:"p-4 text-sm text-white/50",children:"No pinned messages yet."}):e.jsx("ul",{className:"divide-y divide-white/5",children:s.map(l=>e.jsxs("li",{className:"p-2 text-sm",children:[e.jsxs("div",{className:"text-xs opacity-60 mb-0.5",children:["@",l.author_id]}),e.jsx("div",{className:"line-clamp-2",children:l.content}),e.jsx("button",{onClick:()=>a(l.id),className:"mt-1 text-xs text-sky-300 hover:text-sky-200",children:"Jump to →"})]},l.id))})]})}function Vs({authorId:s,onApprove:a}){return e.jsxs("div",{className:"mt-1 flex items-center gap-2 text-xs",children:[e.jsxs("span",{className:"text-white/60",children:["@",s," wants to pin this"]}),e.jsx("button",{onClick:a,className:"px-2 py-0.5 bg-sky-500/20 text-sky-200 rounded hover:bg-sky-500/30","aria-label":`Pin this message from ${s}`,children:"📌 Pin this"})]})}async function se(s){if(s.ok)return;let a=null;try{a=await s.json()}catch{}throw new Error((a==null?void 0:a.error)||`HTTP ${s.status}`)}async function kt(s){const a=await fetch(`/api/chat/messages/${s}/pin`,{method:"POST"});await se(a)}async function Ys(s){const a=await fetch(`/api/chat/messages/${s}/pin`,{method:"DELETE"});await se(a)}async function ze(s){const a=await fetch(`/api/chat/channels/${s}/pins`);return await se(a),(await a.json()).pins||[]}async function Gs(s,a){const r=await fetch(`/api/chat/messages/${s}`,{method:"PATCH",headers:{"Content-Type":"application/json"},body:JSON.stringify({content:a})});return await se(r),r.json()}async function Xs(s){const a=await fetch(`/api/chat/messages/${s}`,{method:"DELETE"});await se(a)}async function Qs(s,a){const r=await fetch(`/api/chat/channels/${s}/read-cursor/rewind`,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({before_message_id:a})});await se(r)}function Zs(s,a,r,l){return a==="user"||r.some(d=>d.name===s)?"active":l.some(d=>{var p;return d.archived_slug===s||((p=d.original)==null?void 0:p.name)===s})?"archived":"removed"}function en(s){const a=Date.now()-new Date(s).getTime(),r=Math.floor(a/6e4);if(r<1)return"now";if(r<60)return`${r}m ago`;const l=Math.floor(r/60);if(l<24)return`${l}h ago`;const d=Math.floor(l/24);return d<7?`${d}d ago`:new Date(s).toLocaleDateString()}function tn(s){const a=[],r=/(\*\*(.+?)\*\*|\*(.+?)\*|`(.+?)`)/g;let l=0,d,p=0;for(;(d=r.exec(s))!==null;)d.index>l&&a.push(s.slice(l,d.index)),d[2]?a.push(e.jsx("strong",{className:"font-semibold",children:d[2]},p++)):d[3]?a.push(e.jsx("em",{className:"italic",children:d[3]},p++)):d[4]&&a.push(e.jsx("code",{className:"bg-white/10 px-1.5 py-0.5 rounded text-[13px] font-mono",children:d[4]},p++)),l=d.index+d[0].length;return l{var c;if(t.kind!=="file"||!h)return;const n=Ze.find(y=>y.id===h);if((c=n==null?void 0:n.settings)!=null&&c.archived)return;const i=Math.random().toString(36).slice(2);R(y=>[...y,{id:i,filename:t.name,size:t.size,uploading:!0}]);try{const y=t.path.startsWith("/workspaces/agent/"),w=y?"agent-workspace":"workspace",_=y?t.path.split("/")[3]:void 0,D=await vt({path:t.path,source:w,slug:_});R(U=>U.map(J=>J.id===i?{...J,record:D,uploading:!1}:J))}catch(y){R(w=>w.map(_=>_.id===i?{..._,uploading:!1,error:y.message}:_))}}}),[g,k]=o.useState([]),[x,v]=o.useState(!1),[u,S]=o.useState([]),[$,z]=o.useState([]),[h,E]=o.useState(null),[C,f]=o.useState([]),[A,N]=o.useState({}),[b,T]=o.useState(""),[K,be]=o.useState("disconnected"),[_t,G]=o.useState(!1),[De,Pe]=o.useState(null),[ye,we]=o.useState(null),[L,q]=o.useState({name:"",type:"topic",description:""}),[ne,Re]=o.useState(null),[$t,ve]=o.useState(!1),[V,ae]=o.useState(null),[W,Oe]=o.useState(null),[Tt,At]=o.useState({}),[Mt,je]=o.useState([]),[zt,re]=o.useState([]),[Le,O]=o.useState(null),[Dt,Ie]=o.useState(null),[X,R]=o.useState([]),[he,H]=o.useState(null),[Pt,ke]=o.useState(null),[Rt,Ne]=o.useState(!1),[pe,ie]=o.useState([]),[Ot,Lt]=o.useState(null),{openThread:le,openThreadFor:It,closeThread:Ue}=Os(),P=o.useRef(null),Fe=o.useRef(null),He=o.useRef(null),I=o.useRef(null),Se=o.useRef(null),Ce=o.useRef(0),Q=o.useRef(!0),Ee=o.useRef(1e3),Y=o.useRef(null),Z=o.useCallback(async()=>{try{const[t,n]=await Promise.all([fetch("/api/chat/channels"),fetch("/api/chat/unread")]);if(t.ok){const i=await t.json();p(i.channels??[])}if(n.ok){const i=await n.json();N(i.unread??{})}}catch{}},[]),oe=o.useCallback(async()=>{try{const t=await fetch("/api/chat/channels?archived=true");if(t.ok){const n=await t.json();k(n.channels??[])}}catch{}},[]),me=o.useCallback(async()=>{try{const[t,n]=await Promise.all([fetch("/api/agents"),fetch("/api/agents/archived")]);if(t.ok&&(t.headers.get("content-type")??"").includes("application/json")){const c=await t.json();Array.isArray(c)&&S(c)}if(n.ok&&(n.headers.get("content-type")??"").includes("application/json")){const c=await n.json();Array.isArray(c)&&z(c)}}catch{}},[]),We=o.useCallback(async t=>{try{const n=await fetch(`/api/chat/channels/${t}/messages?limit=50`);if(n.ok){const i=await n.json();f(i.messages??[]),Q.current=!0}}catch{}},[]),Be=o.useCallback(async t=>{try{await fetch(`/api/chat/channels/${t}/mark-read`,{method:"POST"}),N(n=>{const i={...n};return delete i[t],i})}catch{}},[]),_e=o.useCallback(()=>{if(P.current&&P.current.readyState<=1)return;be("connecting");const t=window.location.protocol==="https:"?"wss:":"ws:",n=new WebSocket(`${t}//${window.location.host}/ws/chat`);n.onopen=()=>{be("connected"),Ee.current=1e3,Y.current&&n.send(JSON.stringify({type:"join",channel_id:Y.current}))},n.onmessage=i=>{try{const c=JSON.parse(i.data);if(c.type==="typing"&&c.kind==="human"){je(y=>y.includes(c.slug)?y:[...y,c.slug]),setTimeout(()=>je(y=>y.filter(w=>w!==c.slug)),3500);return}if(c.type==="thinking"){c.state==="start"?re(y=>[...y.filter(_=>_.slug!==c.slug),{slug:c.slug,phase:c.phase??null,detail:c.detail??null}]):re(y=>y.filter(w=>w.slug!==c.slug));return}switch(c.type){case"message":f(y=>y.some(w=>w.id===c.id)?y:[...y,c]),c.channel_id!==Y.current&&N(y=>({...y,[c.channel_id]:(y[c.channel_id]??0)+1}));break;case"message_delta":f(y=>y.map(w=>w.id===c.message_id?{...w,content:w.content+(c.delta??""),state:"streaming"}:w));break;case"message_state":f(y=>y.map(w=>w.id===c.message_id?{...w,state:c.state}:w));break;case"typing":if((c.user_type??"user")!=="agent")break;re(y=>[...y.filter(_=>_.slug!==c.user_id),{slug:c.user_id,phase:null,detail:null}]),setTimeout(()=>{re(y=>y.filter(w=>w.slug!==c.user_id))},5e3);break;case"reaction_update":f(y=>y.map(w=>w.id===c.message_id?{...w,reactions:c.reactions}:w));break;case"message_edit":f(y=>y.map(w=>w.id===c.message_id?{...w,...c.content!==void 0&&{content:c.content},...c.edited_at!==void 0&&{edited_at:c.edited_at},...c.metadata!==void 0&&{metadata:c.metadata}}:w));break;case"message_delete":f(y=>y.map(w=>w.id===c.message_id?{...w,deleted_at:c.deleted_at??Date.now()/1e3}:w));break}}catch{}},n.onclose=()=>{be("disconnected"),P.current=null;const i=Ee.current;Ee.current=Math.min(i*2,3e4),setTimeout(_e,i)},n.onerror=()=>{n.close()},P.current=n},[]);o.useEffect(()=>(Z(),oe(),me(),_e(),()=>{P.current&&(P.current.onclose=null,P.current.close())}),[Z,oe,me,_e]),o.useEffect(()=>{fetch("/api/auth/me").then(t=>t.ok?t.json():null).then(t=>{t!=null&&t.id&&Lt(t.id)}).catch(()=>{})},[]),o.useEffect(()=>{let t=!1;const n=async i=>{const c=i.detail;if(c!=null&&c.channelId&&!t&&(E(c.channelId),c.prefillPromptName))try{const y=await fetch(`/api/admin-prompts/${encodeURIComponent(c.prefillPromptName)}`,{headers:{Accept:"application/json"}});if(t)return;if(y.ok&&(y.headers.get("content-type")??"").includes("application/json")){const _=await y.json();if(t)return;T(_.body??""),Re({promptName:c.prefillPromptName,agentName:c.prefillAgent}),setTimeout(()=>{var D;t||(D=I.current)==null||D.focus()},150)}}catch{}};return window.addEventListener("taos:open-messages",n),()=>{t=!0,window.removeEventListener("taos:open-messages",n)}},[]),o.useEffect(()=>{var t,n;h&&(Y.current&&Y.current!==h&&((t=P.current)==null?void 0:t.readyState)===1&&P.current.send(JSON.stringify({type:"leave",channel_id:Y.current})),Y.current=h,((n=P.current)==null?void 0:n.readyState)===1&&P.current.send(JSON.stringify({type:"join",channel_id:h})),We(h),Be(h),je([]),re([]))},[h,We,Be]);const Je=o.useRef(null);o.useEffect(()=>{if(!h||C.length===0)return;const n=new URLSearchParams(window.location.search).get("msg");if(!n||!/^[a-zA-Z0-9_-]{1,64}$/.test(n))return;const i=`${h}:${n}`;if(Je.current===i)return;const c=document.querySelector(`[data-message-id="${n}"]`);c&&(Je.current=i,c.scrollIntoView({behavior:"smooth",block:"center"}),c.classList.add("data-highlight"),setTimeout(()=>c.classList.remove("data-highlight"),2e3))},[h,C.length]),o.useEffect(()=>{if(!h){ie([]);return}ze(h).then(t=>ie(t)).catch(()=>ie([]))},[h]),o.useEffect(()=>{let t=!0;return fetch("/api/frameworks/slash-commands").then(n=>n.json()).then(n=>{t&&At(n||{})}).catch(()=>{}),()=>{t=!1}},[h]),o.useEffect(()=>{var t;Q.current&&((t=Fe.current)==null||t.scrollIntoView({behavior:"smooth"}))},[C]);const Ut=()=>{const t=He.current;if(!t)return;const n=t.scrollHeight-t.scrollTop-t.clientHeight<60;Q.current=n},Ft=$s(h,"user"),Ke=b.startsWith("/"),Ht=Ke&&b.slice(1).split(/\s/,1)[0]||"",Wt=()=>{Ue(),ve(!0)},qe=(t,n)=>{ve(!1),It(t,n)},Ve=async()=>{const t=b.trim();if(!t&&X.length===0||!h)return;if(X.some(i=>i.uploading)){O("waiting for uploads to finish…");return}const n=X.filter(i=>i.record&&!i.error).map(i=>i.record);if(n.length>0)try{const i=await fetch("/api/chat/messages",{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({channel_id:h,author_id:"user",author_type:"user",content:t,content_type:"text",attachments:n})});if(!i.ok){const c=await i.json().catch(()=>({}));O(c.error||"couldn't send message");return}T(""),R([]),I.current&&(I.current.style.height="auto"),Q.current=!0;return}catch(i){O(i.message||"send failed");return}if(t){if(t.startsWith("/"))try{const i=await fetch("/api/chat/messages",{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({channel_id:h,content:t})});if(i.status===400){const c=await i.json().catch(()=>({}));O(c.error||"couldn't send message");return}if(i.ok&&(await i.json().catch(()=>({}))).handled){O(null),T(""),Q.current=!0,I.current&&(I.current.style.height="auto");return}}catch{}if(O(null),P.current&&P.current.readyState===1)P.current.send(JSON.stringify({type:"message",channel_id:h,content:t}));else try{const i=await fetch("/api/chat/messages",{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({channel_id:h,author_id:"user",author_type:"user",content:t,content_type:"text"})});if(!i.ok){const c=await i.json().catch(()=>({}));O(c.error||"couldn't send message");return}}catch(i){O(i.message||"send failed");return}T(""),Q.current=!0,I.current&&(I.current.style.height="auto")}},Bt=t=>{var i;T(t),I.current&&(I.current.style.height="auto",I.current.style.height=Math.min(I.current.scrollHeight,120)+"px");const n=Date.now();h&&((i=P.current)==null?void 0:i.readyState)===1&&n-Ce.current>3e3&&(P.current.send(JSON.stringify({type:"typing",channel_id:h})),Ce.current=n),Se.current&&clearTimeout(Se.current),Se.current=setTimeout(()=>{Ce.current=0},4e3),Ft()},Jt=t=>{t.key==="Enter"&&!t.shiftKey&&(t.preventDefault(),Ve())},Kt=async()=>{const t=await Us({sources:["disk","workspace","agent-workspace"],multi:!0});for(const n of t){const i=Math.random().toString(36).slice(2),c=n.source==="disk"?n.file.name:n.path.split("/").pop()||"",y=n.source==="disk"?n.file.size:0;R(w=>[...w,{id:i,filename:c,size:y,uploading:!0}]);try{const w=n.source==="disk"?await Me(n.file,h??void 0):await vt({path:n.path,source:n.source,slug:n.source==="agent-workspace"?n.slug:void 0});R(_=>_.map(D=>D.id===i?{...D,record:w,uploading:!1}:D))}catch(w){R(_=>_.map(D=>D.id===i?{...D,uploading:!1,error:w.message}:D))}}},Ye=(t,n)=>{var i;((i=P.current)==null?void 0:i.readyState)===1&&P.current.send(JSON.stringify({type:"reaction",message_id:t,emoji:n})),Pe(null)},Ge=async()=>{if(L.name.trim())try{const t=await fetch("/api/chat/channels",{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({name:L.name.trim(),type:L.type,description:L.description.trim()||void 0})});if(t.ok){const n=await t.json();p(i=>[...i,n]),E(n.id),G(!1),q({name:"",type:"topic",description:""})}}catch{}},Xe=o.useCallback(async(t,n)=>{var c,y,w,_;const i=(y=(c=g.find(D=>D.id===t))==null?void 0:c.settings)==null?void 0:y.archived_agent_id;if(i){const D=$.find(U=>U.id===i);if(D){if(!window.confirm(`Restore agent "${((w=D.original)==null?void 0:w.display_name)||((_=D.original)==null?void 0:_.name)||D.archived_slug}"?`))return;try{const U=await fetch(`/api/agents/archived/${i}/restore`,{method:"POST"});if(!U.ok){const J=await U.json().catch(()=>({}));window.alert(`Restore failed: ${J.error??U.status}`);return}await Z(),await oe(),await me()}catch(U){window.alert(`Network error: ${String(U)}`)}}else window.alert("Agent entry missing — delete only.")}else window.alert(`Cannot restore channel "${n}": no associated agent found.`)},[g,$,Z,oe,me]),Qe=o.useCallback(async t=>{if(window.confirm("Permanently delete this chat? All messages are erased. This cannot be undone."))try{const n=await fetch(`/api/chat/channels/${t}`,{method:"DELETE"});if(!n.ok){const i=await n.json().catch(()=>({}));window.alert(`Delete failed: ${i.error??n.status}`);return}k(i=>i.filter(c=>c.id!==t)),h===t&&E(null)}catch(n){window.alert(`Network error: ${String(n)}`)}},[h,oe]),qt=t=>{ke(t),H(null)},Vt=async(t,n)=>{try{await Gs(t,n),ke(null)}catch(i){O(i.message)}},Yt=async t=>{if(H(null),!!window.confirm("Delete this message?"))try{await Xs(t)}catch(n){O(n.message)}},Gt=async t=>{if(H(null),!h)return;const n=`${window.location.origin}/chat/${h}?msg=${t}`;try{await navigator.clipboard.writeText(n)}catch{}},Xt=async t=>{H(null);const n=pe.some(i=>i.id===t.id);try{if(n?await Ys(t.id):await kt(t.id),h){const i=await ze(h);ie(i)}}catch(i){O(i.message)}},Qt=async t=>{if(H(null),!!h)try{await Qs(h,t)}catch(n){O(n.message)}},Zt=async t=>{try{if(await kt(t),h){const n=await ze(h);ie(n)}}catch(n){O(n.message)}},$e={dm:d.filter(t=>t.type==="dm"),topic:d.filter(t=>t.type==="topic"),group:d.filter(t=>t.type==="group")},Ze=[...d,...g],j=Ze.find(t=>t.id===h),B=((tt=j==null?void 0:j.settings)==null?void 0:tt.archived)===!0,et=[{label:"Direct Messages",icon:e.jsx(xt,{size:13}),items:$e.dm},{label:"Topics",icon:e.jsx(mt,{size:13}),items:$e.topic},{label:"Groups",icon:e.jsx(Ae,{size:13}),items:$e.group}],es=r?e.jsxs("div",{style:{padding:"8px 0 16px"},children:[e.jsx("div",{style:{padding:"0 20px 8px",fontSize:11,display:"flex",alignItems:"center",gap:6},children:K==="connected"?e.jsxs(e.Fragment,{children:[e.jsx(fe,{size:11,style:{color:"#34d399"}}),e.jsx("span",{style:{color:"rgba(52,211,153,0.8)"},children:"Connected"})]}):K==="connecting"?e.jsxs(e.Fragment,{children:[e.jsx(fe,{size:11,style:{color:"#fbbf24"}}),e.jsx("span",{style:{color:"rgba(251,191,36,0.8)"},children:"Connecting…"})]}):e.jsxs(e.Fragment,{children:[e.jsx(dt,{size:11,style:{color:"#f87171"}}),e.jsx("span",{style:{color:"rgba(248,113,113,0.8)"},children:"Offline"})]})}),et.map(t=>e.jsxs("div",{style:{marginBottom:20},children:[e.jsxs("div",{style:{fontSize:12,textTransform:"uppercase",letterSpacing:.5,color:"rgba(255,255,255,0.45)",padding:"0 20px 6px",fontWeight:600,display:"flex",alignItems:"center",gap:6},children:[t.icon," ",t.label]}),t.items.length===0?e.jsx("div",{style:{padding:"0 20px",fontSize:12,color:"rgba(255,255,255,0.2)",fontStyle:"italic"},children:"None yet"}):e.jsx("div",{style:{margin:"0 12px",borderRadius:16,background:"rgba(255,255,255,0.05)",border:"1px solid rgba(255,255,255,0.08)",overflow:"hidden"},children:t.items.map((n,i,c)=>e.jsxs("button",{type:"button",onClick:()=>E(n.id),"aria-label":`Channel ${n.name}`,style:{display:"flex",alignItems:"center",gap:10,width:"100%",padding:"14px 16px",background:h===n.id?"rgba(59,130,246,0.15)":"none",border:"none",borderBottom:i===c.length-1?"none":"1px solid rgba(255,255,255,0.06)",cursor:"pointer",color:"inherit",textAlign:"left"},children:[e.jsx("span",{style:{flex:1,fontSize:15,fontWeight:400,color:"rgba(255,255,255,0.9)",overflow:"hidden",textOverflow:"ellipsis",whiteSpace:"nowrap"},children:n.name}),(A[n.id]??0)>0&&e.jsx("span",{style:{background:"#3b82f6",color:"#fff",fontSize:10,fontWeight:700,borderRadius:9999,minWidth:18,height:18,display:"flex",alignItems:"center",justifyContent:"center",padding:"0 4px"},children:A[n.id]}),e.jsx(Te,{size:16,style:{color:"rgba(255,255,255,0.25)",flexShrink:0}})]},n.id))})]},t.label)),g.length>0&&e.jsxs("div",{style:{marginBottom:20},children:[e.jsxs("button",{type:"button",onClick:()=>v(t=>!t),"aria-expanded":x,"aria-controls":"archived-channels-mobile",style:{fontSize:12,textTransform:"uppercase",letterSpacing:.5,color:"rgba(255,255,255,0.35)",padding:"0 20px 6px",fontWeight:600,display:"flex",alignItems:"center",gap:6,background:"none",border:"none",cursor:"pointer",width:"100%"},children:[e.jsx(Te,{size:12,style:{transition:"transform 0.15s",transform:x?"rotate(90deg)":"none",color:"rgba(255,255,255,0.3)"},"aria-hidden":"true"}),e.jsx(ce,{size:12,"aria-hidden":"true"}),"Archived (",g.length,")"]}),e.jsx("div",{id:"archived-channels-mobile",style:{display:x?"block":"none"},children:e.jsx("div",{style:{margin:"0 12px",borderRadius:16,background:"rgba(255,255,255,0.03)",border:"1px solid rgba(255,255,255,0.06)",overflow:"hidden"},children:g.map((t,n,i)=>{var w;const c=(w=t.settings)==null?void 0:w.archived_agent_id,y=c?$.some(_=>_.id===c):!1;return e.jsxs("div",{style:{display:"flex",alignItems:"center",gap:8,borderBottom:n===i.length-1?"none":"1px solid rgba(255,255,255,0.04)",opacity:.6},children:[e.jsxs("button",{type:"button",onClick:()=>E(t.id),"aria-label":`Archived channel ${t.name}`,style:{flex:1,display:"flex",alignItems:"center",gap:8,padding:"12px 8px 12px 16px",background:h===t.id?"rgba(59,130,246,0.12)":"none",border:"none",cursor:"pointer",color:"inherit",textAlign:"left",minWidth:0},children:[e.jsx(ce,{size:11,"aria-hidden":"true",style:{color:"rgba(255,255,255,0.4)",flexShrink:0}}),e.jsx("span",{style:{flex:1,fontSize:14,color:"rgba(255,255,255,0.7)",overflow:"hidden",textOverflow:"ellipsis",whiteSpace:"nowrap"},children:t.name})]}),e.jsxs("div",{style:{display:"flex",gap:2,paddingRight:8},children:[e.jsx("button",{type:"button",onClick:()=>Xe(t.id,t.name),disabled:!y,"aria-label":`Restore archived channel ${t.name}`,title:y?"Restore agent":"Agent entry missing — delete only",style:{background:"none",border:"none",cursor:y?"pointer":"not-allowed",color:y?"rgba(52,211,153,0.7)":"rgba(255,255,255,0.2)",padding:"6px"},children:e.jsx(ut,{size:13,"aria-hidden":"true"})}),e.jsx("button",{type:"button",onClick:()=>Qe(t.id),"aria-label":`Permanently delete archived channel ${t.name}`,title:"Delete permanently",style:{background:"none",border:"none",cursor:"pointer",color:"rgba(248,113,113,0.7)",padding:"6px"},children:e.jsx(ht,{size:13,"aria-hidden":"true"})})]})]},t.id)})})})]})]}):e.jsxs("div",{className:"w-full flex flex-col h-full",children:[e.jsx("div",{className:"px-3 py-1.5 text-[11px] flex items-center gap-1.5",children:K==="connected"?e.jsxs(e.Fragment,{children:[e.jsx(fe,{size:11,className:"text-emerald-400"}),e.jsx("span",{className:"text-emerald-400/80",children:"Connected"})]}):K==="connecting"?e.jsxs(e.Fragment,{children:[e.jsx(fe,{size:11,className:"text-amber-400 animate-pulse"}),e.jsx("span",{className:"text-amber-400/80",children:"Connecting..."})]}):e.jsxs(e.Fragment,{children:[e.jsx(dt,{size:11,className:"text-red-400"}),e.jsx("span",{className:"text-red-400/80",children:"Offline"})]})}),e.jsxs("div",{className:"flex-1 overflow-y-auto py-1",children:[et.map(t=>e.jsxs("div",{children:[e.jsxs("div",{className:"px-3 pt-3 pb-1 text-[10px] font-semibold uppercase tracking-wider text-white/30 flex items-center gap-1.5",children:[t.icon," ",t.label]}),t.items.length===0&&e.jsx("div",{className:"px-3 py-1 text-[11px] text-white/20 italic",children:"None yet"}),t.items.map(n=>e.jsxs(F,{variant:h===n.id?"secondary":"ghost",onClick:()=>E(n.id),className:"w-full justify-start h-auto py-1.5 px-3 text-[13px] rounded-none font-normal","aria-label":`Channel ${n.name}`,children:[e.jsx("span",{className:"truncate flex-1 text-left",children:n.name}),(A[n.id]??0)>0&&e.jsx("span",{className:"shrink-0 bg-blue-500 text-white text-[10px] font-bold rounded-full min-w-[18px] h-[18px] flex items-center justify-center px-1",children:A[n.id]})]},n.id))]},t.label)),g.length>0&&e.jsxs("div",{className:"mt-2",children:[e.jsxs("button",{type:"button",onClick:()=>v(t=>!t),className:"flex items-center gap-1.5 px-3 pt-2 pb-1 text-[10px] font-semibold uppercase tracking-wider text-white/25 hover:text-white/40 transition-colors w-full text-left","aria-expanded":x,"aria-controls":"archived-channels-desktop",children:[e.jsx(Te,{size:11,className:`transition-transform ${x?"rotate-90":""}`,"aria-hidden":"true"}),e.jsx(ce,{size:11,"aria-hidden":"true"}),"Archived (",g.length,")"]}),e.jsx("div",{id:"archived-channels-desktop",className:x?"":"hidden",children:g.map(t=>{var c;const n=(c=t.settings)==null?void 0:c.archived_agent_id,i=n?$.some(y=>y.id===n):!1;return e.jsxs("div",{className:"group relative flex items-center opacity-60 hover:opacity-80 transition-opacity",children:[e.jsxs(F,{variant:h===t.id?"secondary":"ghost",onClick:()=>E(t.id),className:"flex-1 justify-start h-auto py-1.5 pl-3 pr-1 text-[13px] rounded-none font-normal min-w-0","aria-label":`Archived channel ${t.name}`,children:[e.jsx(ce,{size:11,className:"shrink-0 mr-1.5 text-white/40","aria-hidden":"true"}),e.jsx("span",{className:"truncate flex-1 text-left",children:t.name})]}),e.jsxs("div",{className:"hidden group-hover:flex items-center shrink-0 pr-1",children:[e.jsx("button",{type:"button",onClick:()=>Xe(t.id,t.name),disabled:!i,"aria-label":`Restore archived channel ${t.name}`,title:i?"Restore agent":"Agent entry missing — delete only",className:`p-1 rounded transition-colors ${i?"text-white/30 hover:text-emerald-400 hover:bg-emerald-500/10 cursor-pointer":"text-white/15 cursor-not-allowed"}`,children:e.jsx(ut,{size:12,"aria-hidden":"true"})}),e.jsx("button",{type:"button",onClick:()=>Qe(t.id),"aria-label":`Permanently delete archived channel ${t.name}`,title:"Delete permanently",className:"p-1 rounded text-white/30 hover:text-red-400 hover:bg-red-500/10 transition-colors cursor-pointer",children:e.jsx(ht,{size:12,"aria-hidden":"true"})})]})]},t.id)})})]})]})]}),ts=e.jsx("div",{className:"flex-1 flex flex-col min-w-0 h-full",children:h?e.jsxs(e.Fragment,{children:[e.jsxs("div",{className:"px-4 py-2.5 border-b border-white/[0.06] flex items-center gap-3 shrink-0",children:[(j==null?void 0:j.type)==="topic"?e.jsx(mt,{size:16,className:"text-white/40"}):(j==null?void 0:j.type)==="group"?e.jsx(Ae,{size:16,className:"text-white/40"}):e.jsx(xt,{size:16,className:"text-white/40"}),(()=>{if((j==null?void 0:j.type)!=="dm")return null;const t=(j.members??[]).find(i=>i!=="user");if(!t)return null;const n=u.find(i=>i.name===t);return n?e.jsx("span",{className:"text-base leading-none shrink-0","aria-hidden":"true",children:ot(n.emoji,n.framework)}):null})(),e.jsxs("div",{className:"min-w-0 flex-1",children:[e.jsxs("div",{className:"text-sm font-medium truncate flex items-center gap-1",children:[(j==null?void 0:j.name)??"Unknown",j&&j.type!=="dm"&&e.jsx("button",{"aria-label":"Channel settings",onClick:Wt,className:"ml-1 opacity-60 hover:opacity-100",children:"ⓘ"}),e.jsx("a",{"aria-label":"Open chat guide",href:"https://github.com/jaylfc/tinyagentos/blob/master/docs/chat-guide.md",target:"_blank",rel:"noreferrer",className:"ml-1 opacity-60 hover:opacity-100 text-[12px]",children:"?"}),e.jsxs("div",{className:"relative",children:[e.jsx(Ks,{count:pe.length,onClick:()=>Ne(t=>!t)}),Rt&&e.jsx(qs,{pins:pe,onJumpTo:t=>{Ne(!1);const n=document.querySelector(`[data-message-id="${t}"]`);n&&(n.scrollIntoView({behavior:"smooth",block:"center"}),n.classList.add("data-highlight"),setTimeout(()=>n.classList.remove("data-highlight"),2e3))},onClose:()=>Ne(!1)})]})]}),(j==null?void 0:j.description)&&e.jsx("div",{className:"text-[11px] text-white/35 truncate",children:j.description})]}),(j==null?void 0:j.members)&&e.jsxs("div",{className:"text-[11px] text-white/30 flex items-center gap-1",children:[e.jsx(Ae,{size:12})," ",j.members.length]})]}),e.jsxs("div",{ref:He,onScroll:Ut,className:`flex-1 overflow-y-auto px-4 py-3 space-y-0.5 message-list-drop-target ${m.isOver?"ring-2 ring-sky-400/60 ring-inset bg-sky-500/5":m.isValidTarget?"ring-2 ring-sky-400/30 ring-inset":""}`,style:r&&l>0?{paddingBottom:`${l+60}px`}:void 0,onDragEnter:m.dropHandlers.onDragEnter,onDragOver:t=>{m.dropHandlers.onDragOver(t),t.defaultPrevented||t.preventDefault()},onDragLeave:m.dropHandlers.onDragLeave,onDrop:t=>{if(t.dataTransfer.files&&t.dataTransfer.files.length>0){t.preventDefault();for(const n of Array.from(t.dataTransfer.files)){const i=Math.random().toString(36).slice(2);R(c=>[...c,{id:i,filename:n.name,size:n.size,uploading:!0}]),Me(n,h??void 0).then(c=>R(y=>y.map(w=>w.id===i?{...w,record:c,uploading:!1}:w))).catch(c=>R(y=>y.map(w=>w.id===i?{...w,uploading:!1,error:c.message}:w)))}return}m.dropHandlers.onDrop(t)},children:[C.length===0&&e.jsx("div",{className:"flex items-center justify-center h-full text-white/20 text-sm",children:"No messages yet. Say something!"}),C.map((t,n)=>{var U,J,at,rt;const i=t.author_type==="agent",c=n>0?C[n-1]:void 0,y=!c||c.author_id!==t.author_id,w=Zs(t.author_id,t.author_type,u,$),_=i&&w!=="active",D=w==="archived"?"Agent no longer active":w==="removed"?"Agent removed":void 0;return e.jsxs("div",{"data-message-id":t.id,className:`group relative px-3 py-1 rounded-md transition-colors hover:bg-white/[0.03] ${i&&!_?"bg-blue-500/[0.04]":""} ${y?"mt-3":""}`,onMouseEnter:()=>Ie(t.id),onMouseLeave:()=>Ie(M=>M===t.id?null:M),children:[y&&e.jsxs("div",{className:"flex items-center gap-2 mb-0.5",onContextMenu:M=>{t.author_type==="agent"&&(M.preventDefault(),ae({slug:t.author_id,x:M.clientX,y:M.clientY}))},children:[i&&!_&&(()=>{const M=u.find(ee=>ee.name===t.author_id);return M?e.jsx("span",{className:"text-[14px] leading-none","aria-hidden":"true",children:ot(M.emoji,M.framework)}):null})(),e.jsx("span",{className:`text-[13px] font-semibold ${_?"line-through text-white/35":i?"text-blue-400":"text-white/90"}`,style:_?{opacity:.55}:void 0,title:D,children:t.author_id}),i&&!_&&e.jsxs("span",{className:"text-[10px] bg-blue-500/20 text-blue-300 px-1.5 py-0.5 rounded font-medium flex items-center gap-0.5",children:[e.jsx(ft,{size:10,"aria-hidden":"true"})," Agent"]}),_&&e.jsxs("span",{className:"text-[10px] bg-zinc-500/20 text-zinc-500 px-1.5 py-0.5 rounded font-medium flex items-center gap-0.5",children:[e.jsx(ft,{size:10,"aria-hidden":"true"}),w==="archived"?"inactive":"removed"]}),e.jsx("span",{className:`text-[11px] ${_?"text-white/15":"text-white/25"}`,children:en(t.created_at)}),t.edited_at&&e.jsx("span",{className:"text-[10px] text-white/20",children:"(edited)"})]}),t.deleted_at?e.jsx(Js,{}):Pt===t.id?e.jsx(Bs,{initial:t.content,onSave:M=>Vt(t.id,M),onCancel:()=>ke(null)}):e.jsxs("div",{className:`text-[13px] leading-relaxed whitespace-pre-wrap break-words ${_?"text-white/45":"text-white/80"}`,children:[tn(t.content),t.state==="pending"&&e.jsx("span",{className:"ml-1 text-white/30",children:"..."}),t.state==="streaming"&&e.jsxs("span",{className:"ml-1 inline-flex gap-0.5",children:[e.jsx("span",{className:"w-1 h-1 bg-blue-400 rounded-full animate-bounce [animation-delay:0ms]"}),e.jsx("span",{className:"w-1 h-1 bg-blue-400 rounded-full animate-bounce [animation-delay:150ms]"}),e.jsx("span",{className:"w-1 h-1 bg-blue-400 rounded-full animate-bounce [animation-delay:300ms]"})]}),t.state==="error"&&e.jsx("span",{className:"ml-1 text-red-400 text-[11px]",children:"(error)"})]}),((U=t.metadata)==null?void 0:U.pin_requested)&&t.author_type==="agent"&&e.jsx(Vs,{authorId:t.author_id,onApprove:()=>Zt(t.id)}),t.content_type==="canvas"&&(((J=t.metadata)==null?void 0:J.canvas_url)||((at=t.metadata)==null?void 0:at.canvas_id))&&e.jsx("div",{className:"mt-2",children:e.jsxs(F,{size:"sm",variant:"outline",onClick:()=>{var ee,it,lt;const M=((ee=t.metadata)==null?void 0:ee.canvas_url)??`/canvas/${(it=t.metadata)==null?void 0:it.canvas_id}`;we({url:M,title:(lt=t.metadata)==null?void 0:lt.canvas_title})},className:"h-7 px-2.5 text-[12px] gap-1.5 bg-white/[0.04] border-white/10 hover:bg-white/[0.08]","aria-label":"View canvas",children:[e.jsx(gt,{size:13}),"View Canvas",(rt=t.metadata)!=null&&rt.canvas_title?`: ${t.metadata.canvas_title}`:""]})}),t.reactions&&Object.keys(t.reactions).length>0&&e.jsx("div",{className:"flex flex-wrap gap-1 mt-1",children:Object.entries(t.reactions).map(([M,ee])=>e.jsxs("button",{onClick:()=>Ye(t.id,M),className:"text-[12px] bg-white/[0.06] hover:bg-white/10 border border-white/[0.06] rounded-full px-2 py-0.5 flex items-center gap-1 transition-colors",children:[e.jsx("span",{children:M}),e.jsx("span",{className:"text-white/40",children:ee.length})]},M))}),(r||Dt===t.id)&&e.jsx("div",{className:"absolute top-0 right-2 -translate-y-1/2 z-10",children:e.jsx(Ts,{onReact:()=>Pe(De===t.id?null:t.id),onReplyInThread:()=>qe(t.channel_id??h??"",t.id),onOverflow:M=>{M.preventDefault(),H({messageId:t.id,x:M.clientX,y:M.clientY})}})}),e.jsx(Rs,{attachments:t.attachments||[]}),typeof t.reply_count=="number"&&t.reply_count>0&&e.jsx(As,{replyCount:t.reply_count,lastReplyAt:t.last_reply_at??null,onOpen:()=>qe(t.channel_id??h??"",t.id)}),De===t.id&&e.jsx("div",{className:"absolute right-2 top-5 bg-zinc-800 border border-white/10 rounded-lg shadow-xl p-2 flex gap-1 z-10",children:sn.map(M=>e.jsx("button",{onClick:()=>Ye(t.id,M),className:"text-lg hover:bg-white/10 rounded p-0.5 transition-colors",children:M},M))})]},t.id)}),e.jsx("div",{ref:Fe})]}),e.jsx(Cs,{humans:Mt,agents:zt,selfId:"user"}),B&&e.jsxs("div",{className:"mx-4 mb-2 px-3 py-2 rounded-lg bg-amber-500/10 border border-amber-500/20 text-[12px] text-amber-400/80 flex items-center gap-2 shrink-0",role:"status",children:[e.jsx(ce,{size:13,"aria-hidden":"true"}),"This chat is archived. The agent is no longer active."]}),ne&&e.jsxs("div",{className:"mx-4 mb-1 px-3 py-2 rounded-lg bg-blue-500/10 border border-blue-500/20 text-[12px] text-blue-300/90 flex items-center gap-2 shrink-0",role:"status","aria-label":`Composer prefilled from prompt: ${ne.promptName}`,children:[e.jsxs("span",{className:"flex-1 truncate",children:["Prefilled from: ",ne.promptName,ne.agentName?` for ${ne.agentName}`:""," — edit and send"]}),e.jsx("button",{onClick:()=>{Re(null),T("")},className:"shrink-0 p-0.5 rounded hover:bg-white/10 transition-colors","aria-label":"Dismiss prefill",children:e.jsx(ge,{size:12,"aria-hidden":"true"})})]}),Le&&e.jsx("div",{role:"alert",className:"text-xs text-red-300 bg-red-500/10 border border-red-500/30 rounded px-3 py-1 mx-4",children:Le}),e.jsx(Ds,{items:X,onRemove:t=>R(n=>n.filter(i=>i.id!==t)),onRetry:t=>{R(n=>n.map(i=>i.id===t?{...i,uploading:!1,error:"retry not yet supported — remove and re-add"}:i))}}),e.jsx("div",{className:"px-4 py-3 border-t border-white/[0.06] shrink-0",style:r?{paddingBottom:`max(env(safe-area-inset-bottom), ${l}px)`}:void 0,children:e.jsxs("div",{className:"relative",children:[Ke&&e.jsx(ks,{commands:Tt,queryAfterSlash:Ht,members:(j==null?void 0:j.members)||[],onPick:(t,n)=>{T(`@${t} /${n} `)},onClose:()=>{}}),e.jsxs("div",{className:`flex items-end gap-2 rounded-xl border px-2 py-1.5 ${B?"bg-white/[0.02] border-white/[0.04] opacity-50":"bg-white/[0.06] border-white/[0.08]"}`,children:[e.jsx(F,{variant:"ghost",size:"icon",onClick:Kt,className:"h-8 w-8 shrink-0 mb-0.5","aria-label":"Upload file",disabled:B,children:e.jsx(ms,{size:16})}),e.jsx(rs,{ref:I,value:b,onChange:t=>!B&&Bt(t.target.value),onKeyDown:t=>!B&&Jt(t),onPaste:t=>{if(!t.clipboardData)return;const n=Array.from(t.clipboardData.files).filter(i=>i.type.startsWith("image/"));if(n.length!==0){t.preventDefault();for(const i of n){const c=Math.random().toString(36).slice(2);R(y=>[...y,{id:c,filename:i.name||"pasted.png",size:i.size,uploading:!0}]),Me(i,h??void 0).then(y=>R(w=>w.map(_=>_.id===c?{..._,record:y,uploading:!1}:_))).catch(y=>R(w=>w.map(_=>_.id===c?{..._,uploading:!1,error:y.message}:_)))}}},placeholder:B?"This chat is archived":`Message #${(j==null?void 0:j.name)??""}...`,rows:1,disabled:B,className:"flex-1 bg-transparent border-0 px-1 py-1.5 min-h-0 text-[13px] focus-visible:ring-0 focus-visible:border-0 max-h-[120px] disabled:cursor-not-allowed","aria-label":"Message input"}),e.jsx(F,{size:"icon",onClick:Ve,disabled:!b.trim()&&X.length===0||B||X.some(t=>t.uploading),className:"h-8 w-8 shrink-0 mb-0.5","aria-label":"Send message",children:e.jsx(xs,{size:15})})]})]})})]}):e.jsx("div",{className:"flex-1 flex items-center justify-center text-white/20",children:e.jsxs("div",{className:"text-center",children:[e.jsx(pt,{size:48,className:"mx-auto mb-3 opacity-30"}),e.jsx("p",{className:"text-sm",children:"Select a channel to start chatting"})]})})}),ss=!r||h===null;return e.jsxs("div",{className:"flex flex-col h-full bg-shell-base text-white overflow-hidden",children:[ss&&e.jsx("div",{className:"relative flex items-center px-3 py-2.5 border-b border-white/[0.06] shrink-0",children:a?e.jsxs(e.Fragment,{children:[e.jsx("div",{className:"absolute inset-0 flex items-center justify-center pointer-events-none",children:e.jsx("span",{className:"text-sm font-semibold text-white/90",children:a})}),e.jsx("div",{className:"ml-auto",children:e.jsx(F,{variant:"ghost",size:"icon",onClick:()=>G(!0),className:"h-7 w-7","aria-label":"New channel",children:e.jsx(bt,{size:15})})})]}):e.jsxs(e.Fragment,{children:[e.jsxs("div",{className:"flex items-center gap-2 text-sm font-medium text-white/80",children:[e.jsx(pt,{size:15}),!r&&"Messages"]}),e.jsx(F,{variant:"ghost",size:"icon",onClick:()=>G(!0),className:"h-7 w-7 ml-auto","aria-label":"New channel",children:e.jsx(bt,{size:15})})]})}),e.jsx("div",{className:"flex-1 min-h-0 overflow-hidden",children:e.jsx(ds,{selectedId:h,onBack:()=>E(null),listTitle:"Messages",detailTitle:j==null?void 0:j.name,listWidth:240,list:es,detail:ts})}),he&&(()=>{const t=C.find(i=>i.id===he.messageId);if(!t)return null;const n=e.jsx(Fs,{isOwn:t.author_id===Ot,isHuman:!0,isPinned:pe.some(i=>i.id===t.id),onEdit:()=>qt(t.id),onDelete:()=>Yt(t.id),onCopyLink:()=>Gt(t.id),onPin:()=>Xt(t),onMarkUnread:()=>Qt(t.id),onClose:()=>H(null)});return r?e.jsx(Ws,{open:!0,onClose:()=>H(null),children:n}):e.jsxs(e.Fragment,{children:[e.jsx("div",{className:"fixed inset-0 z-40",onClick:()=>H(null)}),e.jsx("div",{className:"fixed z-50",style:{top:he.y,left:he.x},children:n})]})})(),$t&&j&&e.jsx(vs,{channel:{id:j.id,name:j.name,type:j.type,topic:j.topic??"",members:j.members??[],settings:j.settings??{}},knownAgents:u.map(t=>({name:t.name})),onClose:()=>ve(!1),onChanged:()=>{Z()}}),le&&e.jsx(zs,{channelId:le.channelId,parentId:le.parentId,onClose:Ue,isFullscreen:r,onSend:async(t,n)=>{const i=await fetch("/api/chat/messages",{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({channel_id:le.channelId,author_id:"user",author_type:"user",content:t,content_type:"text",thread_id:le.parentId,attachments:n})});if(!i.ok){const c=await i.json().catch(()=>({}));throw new Error(c.error||`HTTP ${i.status}`)}}}),V&&e.jsx(js,{slug:V.slug,channelId:h??void 0,channelType:j==null?void 0:j.type,isMuted:((nt=(st=j==null?void 0:j.settings)==null?void 0:st.muted)==null?void 0:nt.includes(V.slug))??!1,x:V.x,y:V.y,onClose:()=>ae(null),onDm:async t=>{const n=d.find(i=>i.type==="dm"&&(i.members||[]).length===2&&(i.members||[]).includes("user")&&(i.members||[]).includes(t));if(n)E(n.id);else{const i=await fetch("/api/chat/channels",{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({name:t,type:"dm",members:["user",t],description:"",topic:""})});if(i.ok){const c=await i.json();await Z(),E(c.id)}}ae(null)},onViewInfo:t=>{const n=u.find(i=>i.name===t);n&&Oe({slug:t,framework:n.framework||"unknown",model:n.model||"unknown",status:n.status||"unknown",x:V.x,y:V.y}),ae(null)},onJumpToSettings:t=>{window.dispatchEvent(new CustomEvent("taos:open-agent",{detail:{slug:t}})),ae(null)}}),W&&e.jsxs("div",{role:"dialog","aria-label":`Agent info for @${W.slug}`,className:"fixed z-50 bg-shell-surface border border-white/10 rounded-lg shadow-xl p-3 text-xs min-w-[200px]",style:{top:W.y,left:W.x},onMouseLeave:()=>Oe(null),children:[e.jsxs("div",{className:"font-semibold text-sm mb-1",children:["@",W.slug]}),e.jsxs("div",{className:"opacity-70",children:["Framework: ",W.framework]}),e.jsxs("div",{className:"opacity-70",children:["Model: ",W.model]}),e.jsxs("div",{className:"opacity-70",children:["Status: ",W.status]})]}),ye&&e.jsx("div",{className:"fixed inset-0 z-[10002] flex items-center justify-center bg-black/60 backdrop-blur-sm",onClick:()=>we(null),role:"dialog","aria-modal":"true","aria-label":"Canvas viewer",children:e.jsxs("div",{className:"w-[90vw] h-[85vh] max-w-5xl rounded-xl border border-white/10 overflow-hidden bg-zinc-900 flex flex-col",onClick:t=>t.stopPropagation(),children:[e.jsxs("div",{className:"flex items-center justify-between px-4 py-2 border-b border-white/10 shrink-0",children:[e.jsxs("div",{className:"flex items-center gap-2 text-sm text-white/80",children:[e.jsx(gt,{size:14}),e.jsx("span",{children:ye.title??"Canvas"})]}),e.jsx(F,{variant:"ghost",size:"icon",onClick:()=>we(null),className:"h-7 w-7","aria-label":"Close canvas viewer",children:e.jsx(ge,{size:14})})]}),e.jsx("iframe",{src:ye.url,className:"flex-1 w-full border-none bg-white",title:"Canvas"})]})}),_t&&(r?e.jsx("div",{className:"fixed inset-0 z-50",onClick:()=>G(!1),role:"dialog","aria-modal":"true","aria-label":"New channel",children:e.jsxs("div",{className:"absolute bottom-0 left-0 right-0 bg-zinc-900 border-t border-white/[0.08] rounded-t-2xl p-4 space-y-3",onClick:t=>t.stopPropagation(),children:[e.jsxs("div",{className:"flex items-center justify-between mb-1",children:[e.jsx("span",{className:"text-sm font-semibold",children:"New Channel"}),e.jsx(F,{variant:"ghost",size:"icon",onClick:()=>G(!1),className:"h-7 w-7","aria-label":"Close",children:e.jsx(ge,{size:15})})]}),e.jsxs("div",{className:"space-y-1",children:[e.jsx(te,{htmlFor:"new-channel-name-mobile",className:"block uppercase tracking-wider",children:"Name"}),e.jsx(xe,{id:"new-channel-name-mobile",value:L.name,onChange:t=>q(n=>({...n,name:t.target.value})),placeholder:"general","aria-label":"Channel name"})]}),e.jsxs("div",{className:"space-y-1",children:[e.jsx(te,{htmlFor:"new-channel-type-mobile",className:"block uppercase tracking-wider",children:"Type"}),e.jsxs("select",{id:"new-channel-type-mobile",value:L.type,onChange:t=>q(n=>({...n,type:t.target.value})),className:"w-full bg-white/[0.06] border border-white/10 rounded-lg px-3 py-2 text-sm text-white outline-none focus:border-blue-500/50","aria-label":"Channel type",children:[e.jsx("option",{value:"topic",children:"Topic"}),e.jsx("option",{value:"group",children:"Group"})]})]}),e.jsxs("div",{className:"space-y-1",children:[e.jsx(te,{htmlFor:"new-channel-description-mobile",className:"block uppercase tracking-wider",children:"Description"}),e.jsx(xe,{id:"new-channel-description-mobile",value:L.description,onChange:t=>q(n=>({...n,description:t.target.value})),placeholder:"What's this channel about?","aria-label":"Channel description"})]}),e.jsx(F,{onClick:Ge,disabled:!L.name.trim(),className:"w-full",children:"Create Channel"})]})}):e.jsx("div",{className:"absolute inset-0 bg-black/60 flex items-center justify-center z-50 p-4",children:e.jsxs(is,{className:"w-full max-w-[380px] max-h-full flex flex-col shadow-2xl bg-zinc-900",children:[e.jsxs(ls,{className:"flex flex-row items-center justify-between gap-2 p-0 px-4 py-3 border-b border-white/[0.06]",children:[e.jsx(os,{className:"text-sm font-medium",children:"New Channel"}),e.jsx(F,{variant:"ghost",size:"icon",onClick:()=>G(!1),className:"h-7 w-7","aria-label":"Close",children:e.jsx(ge,{size:15})})]}),e.jsxs(cs,{className:"p-4 pt-4 space-y-3",children:[e.jsxs("div",{className:"space-y-1",children:[e.jsx(te,{htmlFor:"new-channel-name",className:"block uppercase tracking-wider",children:"Name"}),e.jsx(xe,{id:"new-channel-name",value:L.name,onChange:t=>q(n=>({...n,name:t.target.value})),placeholder:"general","aria-label":"Channel name"})]}),e.jsxs("div",{className:"space-y-1",children:[e.jsx(te,{htmlFor:"new-channel-type",className:"block uppercase tracking-wider",children:"Type"}),e.jsxs("select",{id:"new-channel-type",value:L.type,onChange:t=>q(n=>({...n,type:t.target.value})),className:"w-full bg-white/[0.06] border border-white/10 rounded-lg px-3 py-2 text-sm text-white outline-none focus:border-blue-500/50","aria-label":"Channel type",children:[e.jsx("option",{value:"topic",children:"Topic"}),e.jsx("option",{value:"group",children:"Group"})]})]}),e.jsxs("div",{className:"space-y-1",children:[e.jsx(te,{htmlFor:"new-channel-description",className:"block uppercase tracking-wider",children:"Description"}),e.jsx(xe,{id:"new-channel-description",value:L.description,onChange:t=>q(n=>({...n,description:t.target.value})),placeholder:"What's this channel about?","aria-label":"Channel description"})]}),e.jsx(F,{onClick:Ge,disabled:!L.name.trim(),className:"w-full",children:"Create Channel"})]})]})}))]})}export{hn as MessagesApp,Zs as resolveAuthorDisplayState}; diff --git a/static/desktop/assets/MessagesApp-D7Umpsei.js b/static/desktop/assets/MessagesApp-D7Umpsei.js deleted file mode 100644 index 31b1a939..00000000 --- a/static/desktop/assets/MessagesApp-D7Umpsei.js +++ /dev/null @@ -1 +0,0 @@ -import{r as o,j as e,p as ns,b as as}from"./vendor-react-l6srOxy7.js";import{B as F,r as ot,T as rs,L as te,I as xe,C as is,a as ls,b as os,c as cs}from"./toolbar-UW6q5pkx.js";import{M as ds}from"./MobileSplitView-B-4MQO2C.js";import{u as us}from"./use-is-mobile-v5lglusa.js";import{s as hs,g as ct,e as ps}from"./dnd-bus-CdEoCWzR.js";import{W as fe,z as dt,D as $e,E as ce,R as ut,y as ht,G as pt,J as mt,U as Ae,K as xt,v as ft,N as gt,X as ge,O as ms,Q as xs,g as bt}from"./vendor-icons--yQaiqiL.js";import"./vendor-radix-BhM7AEEG.js";import"./vendor-layout-B-pp9n1f.js";function yt(){if(typeof window>"u")return{height:0,keyboardInset:0};const s=window.visualViewport;if(!s)return{height:window.innerHeight,keyboardInset:0};const a=Math.max(0,window.innerHeight-s.height-s.offsetTop);return{height:s.height,keyboardInset:a}}function fs(){const[s,a]=o.useState(yt);return o.useEffect(()=>{if(typeof window>"u")return;const i=window.visualViewport;if(!i)return;const l=()=>a(yt());return i.addEventListener("resize",l),i.addEventListener("scroll",l),()=>{i.removeEventListener("resize",l),i.removeEventListener("scroll",l)}},[]),s}function gs(s){const{accept:a,onDrop:i,disabled:l=!1}=s,d=o.useSyncExternalStore(hs,ct,()=>null),p=o.useRef(0),[m,y]=o.useState(!1),k=!l&&d!==null&&a.includes(d.kind);return o.useEffect(()=>{d===null&&(p.current=0,y(!1))},[d]),{isOver:m,isValidTarget:k,dropHandlers:{onDragEnter:g=>{l||!k||(g.preventDefault(),p.current+=1,p.current===1&&y(!0))},onDragOver:g=>{l||!k||g.preventDefault()},onDragLeave:g=>{l||!k||(p.current=Math.max(0,p.current-1),p.current===0&&y(!1))},onDrop:g=>{p.current=0,y(!1);const v=ct();if(!l&&v&&a.includes(v.kind)){g.preventDefault();try{const u=i(v);u&&typeof u.then=="function"&&u.catch(S=>console.warn("drop handler failed",S))}catch(u){console.warn("drop handler failed",u)}ps()}}}}}async function bs(s){try{return await s.json()}catch{return null}}async function ue(s){if(s.ok)return;const a=await bs(s);throw new Error((a==null?void 0:a.error)||`HTTP ${s.status}`)}async function ys(s,a){const i=await fetch(`/api/chat/channels/${encodeURIComponent(s)}`,{method:"PATCH",headers:{"Content-Type":"application/json"},body:JSON.stringify(a)});await ue(i)}async function ws(s,a){const i=await fetch(`/api/chat/channels/${encodeURIComponent(s)}/members`,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({action:"add",slug:a})});await ue(i)}async function Nt(s,a){const i=await fetch(`/api/chat/channels/${encodeURIComponent(s)}/members`,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({action:"remove",slug:a})});await ue(i)}async function St(s,a){const i=await fetch(`/api/chat/channels/${encodeURIComponent(s)}/muted`,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({action:"add",slug:a})});await ue(i)}async function Ct(s,a){const i=await fetch(`/api/chat/channels/${encodeURIComponent(s)}/muted`,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({action:"remove",slug:a})});await ue(i)}function vs({channel:s,knownAgents:a,onClose:i,onChanged:l}){const[d,p]=o.useState(s.name),[m,y]=o.useState(s.topic||""),[k,g]=o.useState(s.settings.response_mode??"quiet"),[v,u]=o.useState(s.settings.max_hops??3),[S,T]=o.useState(s.settings.cooldown_seconds??5),[z,h]=o.useState(null);o.useEffect(()=>{p(s.name),y(s.topic||""),g(s.settings.response_mode??"quiet"),u(s.settings.max_hops??3),T(s.settings.cooldown_seconds??5)},[s]);const E=async(b,$)=>{h(null);try{await ys(s.id,b),l()}catch(K){$(),h(K instanceof Error?K.message:"failed")}},C=s.members||[],x=s.settings.muted||[],A=a.map(b=>b.name).filter(b=>!C.includes(b)),N=C.filter(b=>b!=="user"&&!x.includes(b));return e.jsxs("aside",{role:"complementary","aria-label":"Channel settings",className:"fixed top-0 right-0 h-full w-[360px] bg-shell-surface border-l border-white/10 shadow-xl flex flex-col z-40",children:[e.jsxs("header",{className:"flex items-center justify-between px-4 py-3 border-b border-white/10",children:[e.jsx("h2",{className:"text-sm font-semibold",children:"Channel settings"}),e.jsx("button",{onClick:i,"aria-label":"Close",className:"text-lg leading-none",children:"×"})]}),e.jsxs("div",{className:"flex-1 overflow-y-auto px-4 py-4 flex flex-col gap-5 text-sm",children:[e.jsxs("section",{"aria-label":"Overview",className:"flex flex-col gap-3",children:[e.jsx("h3",{className:"text-xs uppercase tracking-wider text-shell-text-tertiary",children:"Overview"}),e.jsxs("label",{className:"flex flex-col gap-1",children:[e.jsx("span",{className:"text-xs text-shell-text-secondary",children:"Name"}),e.jsx("input",{value:d,maxLength:100,onChange:b=>p(b.target.value),onBlur:()=>d!==s.name&&E({name:d},()=>p(s.name)),className:"bg-white/5 border border-white/10 rounded px-2 py-1.5 text-sm"})]}),e.jsxs("label",{className:"flex flex-col gap-1",children:[e.jsx("span",{className:"text-xs text-shell-text-secondary",children:"Topic"}),e.jsx("textarea",{value:m,maxLength:500,rows:3,onChange:b=>y(b.target.value),onBlur:()=>m!==(s.topic||"")&&E({topic:m},()=>y(s.topic||"")),className:"bg-white/5 border border-white/10 rounded px-2 py-1.5 text-sm resize-none"})]}),e.jsxs("div",{className:"text-[11px] text-shell-text-tertiary",children:["Type: ",e.jsx("span",{className:"uppercase tracking-wide",children:s.type})]})]}),e.jsxs("section",{"aria-label":"Members",className:"flex flex-col gap-2",children:[e.jsx("h3",{className:"text-xs uppercase tracking-wider text-shell-text-tertiary",children:"Members"}),e.jsx("ul",{className:"flex flex-col gap-1",children:C.map(b=>e.jsxs("li",{className:"flex items-center justify-between px-2 py-1 rounded hover:bg-white/5",children:[e.jsxs("span",{children:["@",b]}),b!=="user"&&e.jsx("button",{className:"text-xs text-red-300 hover:text-red-200",onClick:async()=>{try{await Nt(s.id,b),l()}catch($){h($ instanceof Error?$.message:"failed")}},children:"Remove"})]},b))}),A.length>0&&e.jsx(wt,{label:"Add agent",options:A,onPick:async b=>{try{await ws(s.id,b),l()}catch($){h($ instanceof Error?$.message:"failed")}}})]}),e.jsxs("section",{"aria-label":"Moderation",className:"flex flex-col gap-3",children:[e.jsx("h3",{className:"text-xs uppercase tracking-wider text-shell-text-tertiary",children:"Moderation"}),e.jsxs("div",{className:"flex items-center gap-2",children:[e.jsx("span",{className:"text-xs text-shell-text-secondary",children:"Mode:"}),e.jsx("button",{className:`px-2 py-1 rounded text-xs ${k==="quiet"?"bg-sky-500/30 text-sky-200":"bg-white/5"}`,onClick:()=>E({response_mode:"quiet"},()=>g(k)),children:"quiet"}),e.jsx("button",{className:`px-2 py-1 rounded text-xs ${k==="lively"?"bg-emerald-500/30 text-emerald-200":"bg-white/5"}`,onClick:()=>E({response_mode:"lively"},()=>g(k)),children:"lively"})]}),e.jsxs("div",{className:"flex flex-col gap-1",children:[e.jsx("span",{className:"text-xs text-shell-text-secondary",children:"Muted"}),e.jsxs("div",{className:"flex flex-wrap gap-1",children:[x.map(b=>e.jsxs("span",{className:"inline-flex items-center gap-1 bg-white/5 rounded px-2 py-0.5 text-xs",children:["@",b,e.jsx("button",{"aria-label":`Unmute ${b}`,onClick:async()=>{try{await Ct(s.id,b),l()}catch($){h($ instanceof Error?$.message:"failed")}},children:"×"})]},b)),x.length===0&&e.jsx("span",{className:"text-[11px] text-shell-text-tertiary",children:"none"})]}),N.length>0&&e.jsx(wt,{label:"Mute agent",options:N,onPick:async b=>{try{await St(s.id,b),l()}catch($){h($ instanceof Error?$.message:"failed")}}})]})]}),e.jsxs("section",{"aria-label":"Advanced",className:"flex flex-col gap-3",children:[e.jsx("h3",{className:"text-xs uppercase tracking-wider text-shell-text-tertiary",children:"Advanced"}),e.jsxs("label",{className:"flex flex-col gap-1",children:[e.jsxs("span",{className:"text-xs text-shell-text-secondary",children:["Max hops: ",v]}),e.jsx("input",{type:"range",min:1,max:10,value:v,onChange:b=>u(Number(b.target.value)),onMouseUp:()=>E({max_hops:v},()=>u(s.settings.max_hops??3))})]}),e.jsxs("label",{className:"flex flex-col gap-1",children:[e.jsxs("span",{className:"text-xs text-shell-text-secondary",children:["Cooldown: ",S,"s"]}),e.jsx("input",{type:"range",min:0,max:60,value:S,onChange:b=>T(Number(b.target.value)),onMouseUp:()=>E({cooldown_seconds:S},()=>T(s.settings.cooldown_seconds??5))})]})]}),z&&e.jsx("div",{role:"alert",className:"text-xs text-red-300 bg-red-500/10 border border-red-500/30 rounded px-2 py-1",children:z})]})]})}function wt({label:s,options:a,onPick:i}){return e.jsxs("select",{"aria-label":s,defaultValue:"",onChange:l=>{l.target.value&&(i(l.target.value),l.target.value="")},className:"bg-white/5 border border-white/10 rounded px-2 py-1 text-xs",children:[e.jsxs("option",{value:"",disabled:!0,children:[s,"…"]}),a.map(l=>e.jsxs("option",{value:l,children:["@",l]},l))]})}function js({slug:s,channelId:a,channelType:i,isMuted:l,x:d,y:p,onClose:m,onDm:y,onViewInfo:k,onJumpToSettings:g}){const v=o.useRef(null);o.useEffect(()=>{const z=E=>{v.current&&!v.current.contains(E.target)&&m()},h=E=>{E.key==="Escape"&&m()};return document.addEventListener("mousedown",z),document.addEventListener("keydown",h),()=>{document.removeEventListener("mousedown",z),document.removeEventListener("keydown",h)}},[m]);const u=i==="dm",S=async()=>{if(a)try{l?await Ct(a,s):await St(a,s)}finally{m()}},T=async()=>{if(a)try{await Nt(a,s)}finally{m()}};return e.jsxs("div",{ref:v,role:"menu","aria-label":`Actions for @${s}`,className:"fixed z-50 min-w-[200px] bg-shell-surface border border-white/10 rounded-lg shadow-xl py-1 text-sm",style:{top:p,left:d},children:[e.jsxs(de,{onClick:()=>{y==null||y(s),m()},children:["DM @",s]}),a&&!u&&e.jsxs(de,{onClick:S,children:[l?"Unmute":"Mute"," in this channel"]}),a&&!u&&e.jsx(de,{onClick:T,children:"Remove from channel"}),e.jsx("div",{className:"my-1 h-px bg-white/10"}),e.jsx(de,{onClick:()=>{k==null||k(s),m()},children:"View agent info"}),e.jsx(de,{onClick:()=>{g==null||g(s),m()},children:"Jump to agent settings"})]})}function de({onClick:s,children:a}){return e.jsx("button",{role:"menuitem",onClick:s,className:"w-full text-left px-3 py-1.5 hover:bg-white/5 focus:bg-white/5 focus:outline-none",children:a})}function ks({commands:s,queryAfterSlash:a,members:i,onPick:l,onClose:d}){const[p,m]=o.useState(0),y=o.useMemo(()=>Ns(s,i,a),[s,i,a]),k=y.filter(g=>g.kind==="cmd");return o.useEffect(()=>{m(0)},[a]),o.useEffect(()=>{const g=v=>{if(v.key==="Escape"){v.preventDefault(),d();return}if(v.key==="ArrowDown"){v.preventDefault(),m(u=>Math.min(k.length-1,u+1));return}if(v.key==="ArrowUp"){v.preventDefault(),m(u=>Math.max(0,u-1));return}if(v.key==="Enter"){v.preventDefault();const u=k[p];u&&l(u.slug,u.cmd.name)}};return document.addEventListener("keydown",g,!0),()=>document.removeEventListener("keydown",g,!0)},[k,p,l,d]),k.length===0&&y.length===0?null:e.jsx("div",{role:"listbox","aria-label":"Slash commands",className:"absolute bottom-full left-0 mb-2 w-full max-w-md bg-shell-surface border border-white/10 rounded-lg shadow-xl max-h-60 overflow-y-auto text-sm",children:y.length===0?e.jsx("div",{className:"px-3 py-2 text-xs text-shell-text-tertiary",children:"(no commands available)"}):y.map(g=>{if(g.kind==="header")return e.jsxs("div",{className:"px-3 py-1 text-[11px] uppercase tracking-wider text-shell-text-tertiary bg-white/5",children:["@",g.slug]},`h-${g.slug}`);const v=k.indexOf(g),u=v===p;return e.jsxs("button",{role:"option","aria-selected":u,onMouseEnter:()=>m(v),onClick:()=>l(g.slug,g.cmd.name),className:`w-full text-left px-3 py-1.5 flex items-center justify-between gap-3 ${u?"bg-white/10":"hover:bg-white/5"}`,children:[e.jsxs("span",{className:"font-mono text-[13px]",children:["/",g.cmd.name]}),e.jsx("span",{className:"text-xs text-shell-text-tertiary truncate",children:g.cmd.description})]},`${g.slug}-${g.cmd.name}`)})})}function Ns(s,a,i){const l=i.toLowerCase(),d=a.filter(y=>y!=="user"&&s[y]),p=d.length===1,m=[];for(const y of d){const k=(s[y]||[]).filter(g=>Ss(y,g,l));if(k.length!==0){p||m.push({kind:"header",slug:y});for(const g of k)m.push({kind:"cmd",slug:y,cmd:g})}}return m}function Ss(s,a,i){if(!i)return!0;const l=`${s} ${a.name} ${a.description}`.toLowerCase();let d=0;for(const p of i.split(/\s+/).join("")){const m=l.indexOf(p,d);if(m===-1)return!1;d=m+1}return!0}function Cs({humans:s,agents:a,selfId:i="user"}){const l=s.filter(k=>k!==i),d=l.length>0,p=a.length>0;if(!d&&!p)return null;const m=Es(l),y=_s(a);return e.jsxs("div",{"aria-live":"polite",className:"px-4 pt-1 text-xs text-shell-text-tertiary flex flex-col gap-0.5",children:[m&&e.jsx("span",{children:m}),y&&e.jsx("span",{className:"italic",children:y})]})}function Es(s){return s.length===0?null:s.length===1?`${s[0]} is typing…`:s.length===2?`${s[0]} and ${s[1]} are typing…`:`${s[0]} and ${s.length-1} others are typing…`}function _s(s){return s.length===0?null:s.map(a=>`${a} is thinking…`).join(" · ")}function Ts(s,a,i=1e3){const l=o.useRef(0);return o.useCallback(()=>{if(!s)return;const d=Date.now();d-l.current{}))},[s,a,i])}function $s({onReact:s,onReplyInThread:a,onOverflow:i}){return e.jsxs("div",{role:"toolbar","aria-label":"Message actions",className:"inline-flex items-center gap-0.5 bg-shell-surface border border-white/10 rounded-md shadow-sm px-1",children:[e.jsx("button",{"aria-label":"Add reaction",onClick:s,className:"p-1 hover:bg-white/5",children:"😀"}),e.jsx("button",{"aria-label":"Reply in thread",onClick:a,className:"p-1 hover:bg-white/5",children:"💬"}),e.jsx("button",{"aria-label":"More",onClick:i,className:"p-1 hover:bg-white/5",children:"⋯"})]})}function As({replyCount:s,lastReplyAt:a,onOpen:i}){if(s===0)return null;const l=a?`💬 ${s} repl${s===1?"y":"ies"} · last reply ${Ms(a)}`:`💬 ${s} repl${s===1?"y":"ies"}`;return e.jsx("button",{onClick:i,className:"mt-1 px-2 py-0.5 text-xs text-sky-200 hover:bg-white/5 rounded","aria-label":"Open thread",children:l})}function Ms(s){const a=Date.now()/1e3,i=Math.max(0,a-s);return i<60?"just now":i<3600?`${Math.floor(i/60)}m ago`:i<86400?`${Math.floor(i/3600)}h ago`:`${Math.floor(i/86400)}d ago`}function zs({channelId:s,parentId:a,onClose:i,onSend:l,isFullscreen:d=!1}){const[p,m]=o.useState(null),[y,k]=o.useState([]),[g,v]=o.useState(""),[u,S]=o.useState(null),[T,z]=o.useState(null),[h,E]=o.useState(!1),C=o.useRef(null);o.useEffect(()=>{const N=new AbortController;return S(null),fetch(`/api/chat/messages/${a}`,{signal:N.signal}).then(b=>{if(!b.ok)throw new Error(`parent fetch failed (${b.status})`);return b.json()}).then(b=>m(b)).catch(b=>{b.name!=="AbortError"&&S("couldn't load this thread")}),()=>N.abort()},[a]),o.useEffect(()=>{const N=new AbortController;return fetch(`/api/chat/channels/${s}/threads/${a}/messages`,{signal:N.signal}).then(b=>b.ok?b.json():{messages:[]}).then(b=>k(b.messages||[])).catch(b=>{b.name!=="AbortError"&&S("couldn't load this thread")}),()=>N.abort()},[s,a]);async function x(){const N=g.trim();if(!(!N||h)){E(!0),z(null);try{await l(N,[]),v("")}catch(b){z(b.message||"couldn't send reply")}finally{E(!1)}}}function A(N){N.key==="Enter"&&!N.shiftKey&&(N.preventDefault(),x())}return e.jsxs("div",{className:d?"fixed inset-0 z-50 bg-shell-surface flex flex-col":"fixed top-0 right-0 h-full w-[360px] bg-shell-surface border-l border-white/10 flex flex-col z-40",role:"complementary","aria-label":"Thread panel",style:d?{paddingTop:"env(safe-area-inset-top, 0px)"}:void 0,children:[e.jsxs("div",{className:"flex items-center justify-between px-4 py-3 border-b border-white/10",children:[e.jsx("span",{className:"font-semibold text-sm",children:"Thread"}),e.jsx("button",{"aria-label":d?"Back":"Close thread",onClick:i,className:"p-1 hover:bg-white/5 rounded",children:d?"◀":"✕"})]}),e.jsxs("div",{className:"flex-1 overflow-y-auto px-4 py-3 flex flex-col gap-3",children:[p&&e.jsxs("div",{className:"pb-3 border-b border-white/10",children:[e.jsx("div",{className:"text-xs text-white/50 mb-1",children:p.author_id}),e.jsx("div",{className:"text-sm",children:p.content})]}),y.map(N=>e.jsxs("div",{children:[e.jsx("div",{className:"text-xs text-white/50 mb-0.5",children:N.author_id}),e.jsx("div",{className:"text-sm",children:N.content})]},N.id)),u&&e.jsx("div",{role:"alert",className:"text-xs text-red-300",children:u})]}),e.jsxs("div",{className:"px-4 py-3 border-t border-white/10",children:[T&&e.jsx("div",{role:"alert",className:"text-xs text-red-300 mb-2",children:T}),e.jsx("textarea",{ref:C,value:g,onChange:N=>v(N.target.value),onKeyDown:A,placeholder:"Reply in thread…","aria-label":"Thread reply",rows:2,disabled:h,className:"w-full bg-white/5 rounded px-3 py-2 text-sm resize-none outline-none border border-white/10 focus:border-sky-400 disabled:opacity-50"})]})]})}function Ds({items:s,onRemove:a,onRetry:i}){return s.length===0?null:e.jsx("div",{"aria-label":"Pending attachments",className:"px-4 py-2 border-t border-white/10 flex gap-2 flex-wrap",children:s.map(l=>e.jsxs("div",{className:"flex items-center gap-2 bg-white/5 rounded px-2 py-1 text-xs max-w-[220px]",children:[e.jsx("span",{className:"truncate",children:l.filename}),e.jsxs("span",{className:"opacity-50",children:[Math.max(1,Math.round(l.size/1024))," KB"]}),l.uploading&&e.jsx("span",{className:"opacity-70",children:"…"}),l.error&&e.jsx("button",{"aria-label":"Retry upload",onClick:()=>i(l.id),className:"text-red-300",children:"retry"}),e.jsx("button",{"aria-label":`Remove ${l.filename}`,onClick:()=>a(l.id),className:"opacity-70 hover:opacity-100",children:"×"})]},l.id))})}function Ps({images:s,startIndex:a,onClose:i}){const[l,d]=o.useState(a);o.useEffect(()=>{const m=y=>{y.key==="Escape"&&i(),y.key==="ArrowLeft"&&d(k=>Math.max(0,k-1)),y.key==="ArrowRight"&&d(k=>Math.min(s.length-1,k+1))};return document.addEventListener("keydown",m),()=>document.removeEventListener("keydown",m)},[s.length,i]);const p=s[l];return e.jsxs("div",{role:"dialog","aria-label":"Image viewer",className:"fixed inset-0 z-50 bg-black/80 flex items-center justify-center",onClick:i,children:[e.jsx("img",{src:p.url,alt:p.filename,className:"max-w-[90vw] max-h-[90vh]",onClick:m=>m.stopPropagation()}),e.jsxs("div",{className:"absolute top-4 right-4 flex gap-2",children:[e.jsx("a",{href:p.url,download:p.filename,onClick:m=>m.stopPropagation(),className:"bg-white/10 hover:bg-white/20 rounded px-3 py-1 text-sm",children:"Download"}),e.jsx("button",{onClick:i,className:"bg-white/10 hover:bg-white/20 rounded px-3 py-1 text-sm",children:"Close"})]}),s.length>1&&e.jsxs("div",{className:"absolute bottom-4 text-white/70 text-xs",children:[l+1," / ",s.length]})]})}function Rs({attachments:s}){const[a,i]=o.useState(null);if(!(s!=null&&s.length))return null;const l=s.filter(m=>{var y;return(y=m.mime_type)==null?void 0:y.startsWith("image/")}),d=s.filter(m=>{var y;return!((y=m.mime_type)!=null&&y.startsWith("image/"))}),p=l.length>1?"grid grid-cols-2 gap-1 max-w-md":"";return e.jsxs("div",{className:"flex flex-col gap-2 mt-1",children:[l.length>0&&e.jsx("div",{className:p,children:l.slice(0,4).map((m,y)=>e.jsxs("button",{onClick:()=>i(y),className:"relative block",children:[e.jsx("img",{src:m.url,alt:m.filename,className:l.length===1?"max-w-[560px] max-h-[400px] rounded":"object-cover w-full h-32 rounded"}),l.length>4&&y===3&&e.jsxs("span",{className:"absolute inset-0 bg-black/60 flex items-center justify-center text-white",children:["+",l.length-4," more"]})]},m.url))}),d.length>0&&e.jsx("div",{className:"flex flex-col gap-1",children:d.map(m=>e.jsxs("a",{href:m.url,target:"_blank",rel:"noreferrer",className:"flex items-center gap-2 bg-white/5 hover:bg-white/10 rounded px-2 py-1 text-sm max-w-sm",children:[e.jsx("span",{"aria-hidden":!0,children:"📄"}),e.jsx("span",{className:"truncate",children:m.filename}),e.jsxs("span",{className:"ml-auto text-xs opacity-60",children:[Math.max(1,Math.round(m.size/1024))," KB"]})]},m.url))}),a!==null&&e.jsx(Ps,{images:l,startIndex:a,onClose:()=>i(null)})]})}async function Et(s){if(s.ok)return;let a=null;try{a=await s.json()}catch{}throw new Error((a==null?void 0:a.error)||`HTTP ${s.status}`)}async function Me(s,a){const i=new FormData;i.append("file",s),a&&i.append("channel_id",a);const l=await fetch("/api/chat/upload",{method:"POST",body:i});await Et(l);const d=await l.json();return{filename:d.filename,mime_type:d.mime_type||d.content_type||"application/octet-stream",size:d.size,url:d.url,source:"disk"}}async function vt(s){const a=await fetch("/api/chat/attachments/from-path",{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify(s)});return await Et(a),a.json()}function Os(){const[s,a]=o.useState(null);return{openThread:s,openThreadFor:(i,l)=>a({channelId:i,parentId:l}),closeThread:()=>a(null)}}function Ls(s,a){const i=a?`?path=${encodeURIComponent(a)}`:"";if(s==="/workspaces/user")return`/api/workspace/files${i}`;if(s.startsWith("/workspaces/agent/")){const l=s.slice(18);return`/api/agents/${encodeURIComponent(l)}/workspace/files${i}`}return`/api/workspace/files${i}`}function jt({root:s,onSelect:a,multi:i=!1}){const[l,d]=o.useState(""),[p,m]=o.useState([]),[y,k]=o.useState(new Set),[g,v]=o.useState(!1),[u,S]=o.useState(null);o.useEffect(()=>{let C=!1;return v(!0),S(null),fetch(Ls(s,l)).then(async x=>{if(!x.ok)throw new Error(`HTTP ${x.status}`);return x.json()}).then(x=>{if(C)return;const N=(Array.isArray(x)?x:[]).map(b=>({name:b.name,type:b.is_dir?"folder":"file",size:b.size,modified:b.modified?new Date(b.modified*1e3).toISOString():void 0}));N.sort((b,$)=>b.type!==$.type?b.type==="folder"?-1:1:b.name.localeCompare($.name)),m(N)}).catch(x=>{C||(S(x instanceof Error?x.message:"Failed to load"),m([]))}).finally(()=>{C||v(!1)}),()=>{C=!0}},[s,l]);function T(C){const x=l?`${l}/${C}`:C;return`${s}/${x}`}function z(C){d(x=>x?`${x}/${C}`:C),k(new Set)}function h(C){const x=T(C);if(!i){a(x);return}k(A=>{const N=new Set(A);return N.has(x)?N.delete(x):N.add(x),a(Array.from(N)),N})}function E(){d(C=>{const x=C.split("/").filter(Boolean);return x.pop(),x.join("/")}),k(new Set)}return e.jsxs("div",{className:"vfs-browser",role:"region","aria-label":"File browser",children:[l&&e.jsx("button",{onClick:E,"aria-label":"Go up one folder",style:{marginBottom:4},children:"↑ .."}),g&&e.jsx("p",{children:"Loading…"}),u&&e.jsxs("p",{role:"alert",children:["Error: ",u]}),!g&&!u&&p.length===0&&e.jsx("p",{children:"Empty folder"}),e.jsx("ul",{style:{listStyle:"none",padding:0,margin:0},children:p.map(C=>{const x=T(C.name),A=y.has(x);return e.jsx("li",{children:e.jsxs("button",{onClick:()=>C.type==="folder"?z(C.name):h(C.name),"aria-selected":i?A:void 0,style:{fontWeight:A?"bold":void 0},children:[C.type==="folder"?"📁 ":"📄 ",C.name]})},C.name)})})]})}function Is({sources:s,accept:a,multi:i=!1,onPick:l,onCancel:d}){const[p,m]=o.useState(s[0]??"disk"),[y,k]=o.useState([]),[g,v]=o.useState([]),[u,S]=o.useState(null),T=o.useRef(null);o.useEffect(()=>{s.includes("agent-workspace")&&fetch("/api/agents").then(x=>x.json()).then(x=>v(Array.isArray(x)?x:[])).catch(()=>{})},[s]),o.useEffect(()=>{const x=A=>{A.key==="Escape"&&(A.preventDefault(),d())};return document.addEventListener("keydown",x),()=>document.removeEventListener("keydown",x)},[d]);const z=x=>{if(!x)return;const A=[];for(const N of Array.from(x))A.push({source:"disk",file:N});k(N=>i?[...N,...A]:A)},h=x=>{const N=(Array.isArray(x)?x:[x]).map(b=>({source:"workspace",path:b}));k(b=>i?[...b.filter($=>$.source!=="workspace"),...N]:N)},E=x=>{if(!u)return;const N=(Array.isArray(x)?x:[x]).map(b=>({source:"agent-workspace",slug:u,path:b}));k(b=>i?[...b.filter($=>$.source!=="agent-workspace"),...N]:N)},C=()=>l(y);return e.jsx("div",{role:"dialog","aria-modal":"true","aria-label":"Pick a file",className:"fixed inset-0 z-50 flex items-center justify-center bg-black/60",children:e.jsxs("div",{className:"bg-shell-surface border border-white/10 rounded-xl w-[720px] h-[540px] flex flex-col overflow-hidden",children:[e.jsxs("div",{role:"tablist",className:"flex border-b border-white/10",children:[s.includes("disk")&&e.jsx("button",{role:"tab","aria-selected":p==="disk",className:`px-4 py-2 text-sm ${p==="disk"?"border-b-2 border-sky-400":"opacity-70"}`,onClick:()=>m("disk"),children:"Disk"}),s.includes("workspace")&&e.jsx("button",{role:"tab","aria-selected":p==="workspace",className:`px-4 py-2 text-sm ${p==="workspace"?"border-b-2 border-sky-400":"opacity-70"}`,onClick:()=>m("workspace"),children:"My workspace"}),s.includes("agent-workspace")&&e.jsx("button",{role:"tab","aria-selected":p==="agent-workspace",className:`px-4 py-2 text-sm ${p==="agent-workspace"?"border-b-2 border-sky-400":"opacity-70"}`,onClick:()=>m("agent-workspace"),children:"Agent workspaces"})]}),e.jsxs("div",{className:"flex-1 overflow-hidden",children:[p==="disk"&&e.jsxs("div",{className:"p-6 flex items-center justify-center",children:[e.jsx("input",{ref:T,type:"file",className:"hidden",multiple:i,accept:a,onChange:x=>z(x.target.files)}),e.jsx("button",{onClick:()=>{var x;return(x=T.current)==null?void 0:x.click()},className:"px-4 py-2 bg-sky-500/20 text-sky-200 rounded",children:"Choose files from disk"}),y.filter(x=>x.source==="disk").length>0&&e.jsxs("div",{className:"ml-6 text-xs text-shell-text-tertiary",children:[y.length," file(s) queued"]})]}),p==="workspace"&&e.jsx(jt,{root:"/workspaces/user",onSelect:h,multi:i}),p==="agent-workspace"&&e.jsxs("div",{className:"h-full flex flex-col",children:[e.jsx("div",{className:"p-2 border-b border-white/10",children:e.jsxs("select",{value:u??"",onChange:x=>S(x.target.value||null),className:"bg-white/5 border border-white/10 rounded px-2 py-1 text-sm",children:[e.jsx("option",{value:"",children:"Pick an agent…"}),g.map(x=>e.jsxs("option",{value:x.name,children:["@",x.name]},x.name))]})}),u&&e.jsx(jt,{root:`/workspaces/agent/${u}`,onSelect:E,multi:i})]})]}),e.jsxs("div",{className:"border-t border-white/10 p-2 flex items-center justify-end gap-2 text-sm",children:[e.jsxs("span",{className:"opacity-60 mr-auto",children:[y.length," selected"]}),e.jsx("button",{onClick:d,className:"px-3 py-1 opacity-70 hover:opacity-100",children:"Cancel"}),e.jsxs("button",{onClick:C,disabled:y.length===0,className:"px-3 py-1 bg-sky-500/30 text-sky-200 rounded disabled:opacity-40",children:["Select (",y.length,")"]})]})]})})}function Us(s){return new Promise(a=>{const i=document.createElement("div");document.body.appendChild(i);const l=ns.createRoot(i),d=()=>{l.unmount(),i.remove()};l.render(as.createElement(Is,{sources:s.sources,accept:s.accept,multi:s.multi,onPick:p=>{d(),a(p)},onCancel:()=>{d(),a([])}}))})}function Fs({isOwn:s,isHuman:a,isPinned:i=!1,onEdit:l,onDelete:d,onCopyLink:p,onPin:m,onMarkUnread:y,onClose:k}){const g=o.useRef(null);o.useEffect(()=>{var S;const u=(S=g.current)==null?void 0:S.querySelector('[role="menuitem"]');u==null||u.focus()},[]);const v=u=>{var h,E,C,x,A;const S=Array.from(((h=g.current)==null?void 0:h.querySelectorAll('[role="menuitem"]'))||[]),T=document.activeElement,z=T?S.indexOf(T):-1;u.key==="ArrowDown"?(u.preventDefault(),(E=S[Math.min(S.length-1,z+1)])==null||E.focus()):u.key==="ArrowUp"?(u.preventDefault(),(C=S[Math.max(0,z-1)])==null||C.focus()):u.key==="Home"?(u.preventDefault(),(x=S[0])==null||x.focus()):u.key==="End"?(u.preventDefault(),(A=S[S.length-1])==null||A.focus()):u.key==="Escape"&&(u.preventDefault(),k==null||k())};return e.jsxs("div",{ref:g,role:"menu","aria-label":"Message overflow menu",onKeyDown:v,className:"bg-shell-surface border border-white/10 rounded-md shadow-lg py-1 min-w-[160px] text-sm",children:[s&&e.jsx("button",{role:"menuitem",onClick:l,className:"block w-full text-left px-3 py-1.5 hover:bg-white/5 focus:bg-white/5 focus:outline-none",children:"Edit"}),s&&e.jsx("button",{role:"menuitem",onClick:d,className:"block w-full text-left px-3 py-1.5 hover:bg-white/5 focus:bg-white/5 focus:outline-none text-red-300",children:"Delete"}),e.jsx("button",{role:"menuitem",onClick:p,className:"block w-full text-left px-3 py-1.5 hover:bg-white/5 focus:bg-white/5 focus:outline-none",children:"Copy link"}),a&&e.jsx("button",{role:"menuitem",onClick:m,className:"block w-full text-left px-3 py-1.5 hover:bg-white/5 focus:bg-white/5 focus:outline-none",children:i?"Unpin":"Pin"}),e.jsx("button",{role:"menuitem",onClick:y,className:"block w-full text-left px-3 py-1.5 hover:bg-white/5 focus:bg-white/5 focus:outline-none",children:"Mark unread"})]})}const Hs=80;function Ws({open:s,onClose:a,children:i,labelledBy:l,dragHandle:d=!0}){const p=o.useRef(null),[m,y]=o.useState(0);if(o.useEffect(()=>{if(!s)return;const g=v=>{v.key==="Escape"&&(v.preventDefault(),a())};return document.addEventListener("keydown",g),()=>document.removeEventListener("keydown",g)},[s,a]),o.useEffect(()=>{var u;if(!s)return;const g=document.activeElement,v=(u=p.current)==null?void 0:u.querySelector('button, [href], input, select, textarea, [tabindex]:not([tabindex="-1"])');return v==null||v.focus(),()=>{var S;(S=g==null?void 0:g.focus)==null||S.call(g)}},[s]),o.useEffect(()=>{if(!s)return;const g=v=>{if(v.key!=="Tab")return;const u=p.current;if(!u)return;const S=Array.from(u.querySelectorAll('button, [href], input, select, textarea, [tabindex]:not([tabindex="-1"])')).filter(E=>!E.hasAttribute("disabled"));if(S.length===0)return;const T=S[0],z=S[S.length-1],h=document.activeElement;v.shiftKey&&h===T?(v.preventDefault(),z.focus()):!v.shiftKey&&h===z&&(v.preventDefault(),T.focus())};return document.addEventListener("keydown",g),()=>document.removeEventListener("keydown",g)},[s]),!s)return null;const k=g=>{const v=g.clientY,u=g.currentTarget;u.setPointerCapture(g.pointerId);const S=h=>{const E=Math.max(0,h.clientY-v);y(E)},T=h=>{const E=Math.max(0,h.clientY-v);u.releasePointerCapture(g.pointerId),u.removeEventListener("pointermove",S),u.removeEventListener("pointerup",T),u.removeEventListener("pointercancel",z),E>Hs&&a(),y(0)},z=()=>{u.releasePointerCapture(g.pointerId),u.removeEventListener("pointermove",S),u.removeEventListener("pointerup",T),u.removeEventListener("pointercancel",z),y(0)};u.addEventListener("pointermove",S),u.addEventListener("pointerup",T),u.addEventListener("pointercancel",z)};return e.jsxs(e.Fragment,{children:[e.jsx("div",{"data-testid":"bottom-sheet-backdrop",className:"fixed inset-0 z-50 bg-black/60",onClick:a}),e.jsxs("div",{ref:p,role:"dialog","aria-modal":"true","aria-labelledby":l,className:"fixed bottom-0 inset-x-0 z-50 bg-shell-surface rounded-t-xl border-t border-white/10 shadow-2xl max-h-[85vh] overflow-y-auto",style:{paddingBottom:"env(safe-area-inset-bottom, 0px)",transform:`translateY(${m}px)`,transition:m===0?"transform 0.2s ease-out":"none"},children:[d&&e.jsx("div",{"data-testid":"bottom-sheet-handle",onPointerDown:k,className:"flex justify-center py-2 cursor-grab active:cursor-grabbing touch-none",children:e.jsx("div",{className:"w-10 h-1 bg-white/20 rounded-full"})}),i]})]})}function Bs({initial:s,onSave:a,onCancel:i}){const[l,d]=o.useState(s);return e.jsx("textarea",{autoFocus:!0,value:l,onChange:p=>d(p.target.value),onKeyDown:p=>{if(p.key==="Escape")p.preventDefault(),i();else if(p.key==="Enter"&&!p.shiftKey){p.preventDefault();const m=l.trim();m?a(m):i()}},"aria-label":"Edit message",rows:1,className:"w-full bg-white/5 border border-white/10 rounded px-2 py-1 text-sm"})}function Js(){return e.jsx("span",{className:"text-white/40 italic text-sm",children:"This message was deleted"})}function Ks({count:s,onClick:a}){return s===0?null:e.jsxs("button",{onClick:a,className:"ml-1 px-1.5 py-0.5 text-xs bg-white/5 hover:bg-white/10 rounded opacity-70 hover:opacity-100","aria-label":`Pinned messages (${s})`,children:["📌 ",s]})}function qs({pins:s,onJumpTo:a,onClose:i}){return e.jsxs("div",{role:"dialog","aria-label":"Pinned messages",className:"absolute top-full right-0 mt-1 w-[320px] max-h-[400px] overflow-y-auto bg-shell-surface border border-white/10 rounded-md shadow-lg z-40",children:[e.jsxs("header",{className:"flex items-center justify-between px-3 py-2 border-b border-white/10",children:[e.jsxs("span",{className:"text-xs font-semibold",children:["Pinned (",s.length,")"]}),e.jsx("button",{onClick:i,"aria-label":"Close",className:"text-sm opacity-70 hover:opacity-100",children:"×"})]}),s.length===0?e.jsx("div",{className:"p-4 text-sm text-white/50",children:"No pinned messages yet."}):e.jsx("ul",{className:"divide-y divide-white/5",children:s.map(l=>e.jsxs("li",{className:"p-2 text-sm",children:[e.jsxs("div",{className:"text-xs opacity-60 mb-0.5",children:["@",l.author_id]}),e.jsx("div",{className:"line-clamp-2",children:l.content}),e.jsx("button",{onClick:()=>a(l.id),className:"mt-1 text-xs text-sky-300 hover:text-sky-200",children:"Jump to →"})]},l.id))})]})}function Vs({authorId:s,onApprove:a}){return e.jsxs("div",{className:"mt-1 flex items-center gap-2 text-xs",children:[e.jsxs("span",{className:"text-white/60",children:["@",s," wants to pin this"]}),e.jsx("button",{onClick:a,className:"px-2 py-0.5 bg-sky-500/20 text-sky-200 rounded hover:bg-sky-500/30","aria-label":`Pin this message from ${s}`,children:"📌 Pin this"})]})}async function se(s){if(s.ok)return;let a=null;try{a=await s.json()}catch{}throw new Error((a==null?void 0:a.error)||`HTTP ${s.status}`)}async function kt(s){const a=await fetch(`/api/chat/messages/${s}/pin`,{method:"POST"});await se(a)}async function Ys(s){const a=await fetch(`/api/chat/messages/${s}/pin`,{method:"DELETE"});await se(a)}async function ze(s){const a=await fetch(`/api/chat/channels/${s}/pins`);return await se(a),(await a.json()).pins||[]}async function Gs(s,a){const i=await fetch(`/api/chat/messages/${s}`,{method:"PATCH",headers:{"Content-Type":"application/json"},body:JSON.stringify({content:a})});return await se(i),i.json()}async function Xs(s){const a=await fetch(`/api/chat/messages/${s}`,{method:"DELETE"});await se(a)}async function Qs(s,a){const i=await fetch(`/api/chat/channels/${s}/read-cursor/rewind`,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({before_message_id:a})});await se(i)}function Zs(s,a,i,l){return a==="user"||i.some(d=>d.name===s)?"active":l.some(d=>{var p;return d.archived_slug===s||((p=d.original)==null?void 0:p.name)===s})?"archived":"removed"}function en(s){const a=Date.now()-new Date(s).getTime(),i=Math.floor(a/6e4);if(i<1)return"now";if(i<60)return`${i}m ago`;const l=Math.floor(i/60);if(l<24)return`${l}h ago`;const d=Math.floor(l/24);return d<7?`${d}d ago`:new Date(s).toLocaleDateString()}function tn(s){const a=[],i=/(\*\*(.+?)\*\*|\*(.+?)\*|`(.+?)`)/g;let l=0,d,p=0;for(;(d=i.exec(s))!==null;)d.index>l&&a.push(s.slice(l,d.index)),d[2]?a.push(e.jsx("strong",{className:"font-semibold",children:d[2]},p++)):d[3]?a.push(e.jsx("em",{className:"italic",children:d[3]},p++)):d[4]&&a.push(e.jsx("code",{className:"bg-white/10 px-1.5 py-0.5 rounded text-[13px] font-mono",children:d[4]},p++)),l=d.index+d[0].length;return l{var c;if(t.kind!=="file"||!h)return;const n=Ze.find(f=>f.id===h);if((c=n==null?void 0:n.settings)!=null&&c.archived)return;const r=Math.random().toString(36).slice(2);R(f=>[...f,{id:r,filename:t.name,size:t.size,uploading:!0}]);try{const f=t.path.startsWith("/workspaces/agent/"),w=f?"agent-workspace":"workspace",_=f?t.path.split("/")[3]:void 0,D=await vt({path:t.path,source:w,slug:_});R(U=>U.map(J=>J.id===r?{...J,record:D,uploading:!1}:J))}catch(f){R(w=>w.map(_=>_.id===r?{..._,uploading:!1,error:f.message}:_))}}}),[y,k]=o.useState([]),[g,v]=o.useState(!1),[u,S]=o.useState([]),[T,z]=o.useState([]),[h,E]=o.useState(null),[C,x]=o.useState([]),[A,N]=o.useState({}),[b,$]=o.useState(""),[K,be]=o.useState("disconnected"),[_t,G]=o.useState(!1),[De,Pe]=o.useState(null),[ye,we]=o.useState(null),[L,q]=o.useState({name:"",type:"topic",description:""}),[ne,Re]=o.useState(null),[Tt,ve]=o.useState(!1),[V,ae]=o.useState(null),[W,Oe]=o.useState(null),[$t,At]=o.useState({}),[Mt,je]=o.useState([]),[zt,re]=o.useState([]),[Le,O]=o.useState(null),[Dt,Ie]=o.useState(null),[X,R]=o.useState([]),[he,H]=o.useState(null),[Pt,ke]=o.useState(null),[Rt,Ne]=o.useState(!1),[pe,ie]=o.useState([]),[Ot,Lt]=o.useState(null),{openThread:le,openThreadFor:It,closeThread:Ue}=Os(),P=o.useRef(null),Fe=o.useRef(null),He=o.useRef(null),I=o.useRef(null),Se=o.useRef(null),Ce=o.useRef(0),Q=o.useRef(!0),Ee=o.useRef(1e3),Y=o.useRef(null),Z=o.useCallback(async()=>{try{const[t,n]=await Promise.all([fetch("/api/chat/channels"),fetch("/api/chat/unread")]);if(t.ok){const r=await t.json();p(r.channels??[])}if(n.ok){const r=await n.json();N(r.unread??{})}}catch{}},[]),oe=o.useCallback(async()=>{try{const t=await fetch("/api/chat/channels?archived=true");if(t.ok){const n=await t.json();k(n.channels??[])}}catch{}},[]),me=o.useCallback(async()=>{try{const[t,n]=await Promise.all([fetch("/api/agents"),fetch("/api/agents/archived")]);if(t.ok&&(t.headers.get("content-type")??"").includes("application/json")){const c=await t.json();Array.isArray(c)&&S(c)}if(n.ok&&(n.headers.get("content-type")??"").includes("application/json")){const c=await n.json();Array.isArray(c)&&z(c)}}catch{}},[]),We=o.useCallback(async t=>{try{const n=await fetch(`/api/chat/channels/${t}/messages?limit=50`);if(n.ok){const r=await n.json();x(r.messages??[]),Q.current=!0}}catch{}},[]),Be=o.useCallback(async t=>{try{await fetch(`/api/chat/channels/${t}/mark-read`,{method:"POST"}),N(n=>{const r={...n};return delete r[t],r})}catch{}},[]),_e=o.useCallback(()=>{if(P.current&&P.current.readyState<=1)return;be("connecting");const t=window.location.protocol==="https:"?"wss:":"ws:",n=new WebSocket(`${t}//${window.location.host}/ws/chat`);n.onopen=()=>{be("connected"),Ee.current=1e3,Y.current&&n.send(JSON.stringify({type:"join",channel_id:Y.current}))},n.onmessage=r=>{try{const c=JSON.parse(r.data);if(c.type==="typing"&&c.kind==="human"){je(f=>f.includes(c.slug)?f:[...f,c.slug]),setTimeout(()=>je(f=>f.filter(w=>w!==c.slug)),3500);return}if(c.type==="thinking"){c.state==="start"?re(f=>f.includes(c.slug)?f:[...f,c.slug]):re(f=>f.filter(w=>w!==c.slug));return}switch(c.type){case"message":x(f=>f.some(w=>w.id===c.id)?f:[...f,c]),c.channel_id!==Y.current&&N(f=>({...f,[c.channel_id]:(f[c.channel_id]??0)+1}));break;case"message_delta":x(f=>f.map(w=>w.id===c.message_id?{...w,content:w.content+(c.delta??""),state:"streaming"}:w));break;case"message_state":x(f=>f.map(w=>w.id===c.message_id?{...w,state:c.state}:w));break;case"typing":if((c.user_type??"user")!=="agent")break;re(f=>f.includes(c.user_id)?f:[...f,c.user_id]),setTimeout(()=>{re(f=>f.filter(w=>w!==c.user_id))},5e3);break;case"reaction_update":x(f=>f.map(w=>w.id===c.message_id?{...w,reactions:c.reactions}:w));break;case"message_edit":x(f=>f.map(w=>w.id===c.message_id?{...w,...c.content!==void 0&&{content:c.content},...c.edited_at!==void 0&&{edited_at:c.edited_at},...c.metadata!==void 0&&{metadata:c.metadata}}:w));break;case"message_delete":x(f=>f.map(w=>w.id===c.message_id?{...w,deleted_at:c.deleted_at??Date.now()/1e3}:w));break}}catch{}},n.onclose=()=>{be("disconnected"),P.current=null;const r=Ee.current;Ee.current=Math.min(r*2,3e4),setTimeout(_e,r)},n.onerror=()=>{n.close()},P.current=n},[]);o.useEffect(()=>(Z(),oe(),me(),_e(),()=>{P.current&&(P.current.onclose=null,P.current.close())}),[Z,oe,me,_e]),o.useEffect(()=>{fetch("/api/auth/me").then(t=>t.ok?t.json():null).then(t=>{t!=null&&t.id&&Lt(t.id)}).catch(()=>{})},[]),o.useEffect(()=>{let t=!1;const n=async r=>{const c=r.detail;if(c!=null&&c.channelId&&!t&&(E(c.channelId),c.prefillPromptName))try{const f=await fetch(`/api/admin-prompts/${encodeURIComponent(c.prefillPromptName)}`,{headers:{Accept:"application/json"}});if(t)return;if(f.ok&&(f.headers.get("content-type")??"").includes("application/json")){const _=await f.json();if(t)return;$(_.body??""),Re({promptName:c.prefillPromptName,agentName:c.prefillAgent}),setTimeout(()=>{var D;t||(D=I.current)==null||D.focus()},150)}}catch{}};return window.addEventListener("taos:open-messages",n),()=>{t=!0,window.removeEventListener("taos:open-messages",n)}},[]),o.useEffect(()=>{var t,n;h&&(Y.current&&Y.current!==h&&((t=P.current)==null?void 0:t.readyState)===1&&P.current.send(JSON.stringify({type:"leave",channel_id:Y.current})),Y.current=h,((n=P.current)==null?void 0:n.readyState)===1&&P.current.send(JSON.stringify({type:"join",channel_id:h})),We(h),Be(h),je([]),re([]))},[h,We,Be]);const Je=o.useRef(null);o.useEffect(()=>{if(!h||C.length===0)return;const n=new URLSearchParams(window.location.search).get("msg");if(!n||!/^[a-zA-Z0-9_-]{1,64}$/.test(n))return;const r=`${h}:${n}`;if(Je.current===r)return;const c=document.querySelector(`[data-message-id="${n}"]`);c&&(Je.current=r,c.scrollIntoView({behavior:"smooth",block:"center"}),c.classList.add("data-highlight"),setTimeout(()=>c.classList.remove("data-highlight"),2e3))},[h,C.length]),o.useEffect(()=>{if(!h){ie([]);return}ze(h).then(t=>ie(t)).catch(()=>ie([]))},[h]),o.useEffect(()=>{let t=!0;return fetch("/api/frameworks/slash-commands").then(n=>n.json()).then(n=>{t&&At(n||{})}).catch(()=>{}),()=>{t=!1}},[h]),o.useEffect(()=>{var t;Q.current&&((t=Fe.current)==null||t.scrollIntoView({behavior:"smooth"}))},[C]);const Ut=()=>{const t=He.current;if(!t)return;const n=t.scrollHeight-t.scrollTop-t.clientHeight<60;Q.current=n},Ft=Ts(h,"user"),Ke=b.startsWith("/"),Ht=Ke&&b.slice(1).split(/\s/,1)[0]||"",Wt=()=>{Ue(),ve(!0)},qe=(t,n)=>{ve(!1),It(t,n)},Ve=async()=>{const t=b.trim();if(!t&&X.length===0||!h)return;if(X.some(r=>r.uploading)){O("waiting for uploads to finish…");return}const n=X.filter(r=>r.record&&!r.error).map(r=>r.record);if(n.length>0)try{const r=await fetch("/api/chat/messages",{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({channel_id:h,author_id:"user",author_type:"user",content:t,content_type:"text",attachments:n})});if(!r.ok){const c=await r.json().catch(()=>({}));O(c.error||"couldn't send message");return}$(""),R([]),I.current&&(I.current.style.height="auto"),Q.current=!0;return}catch(r){O(r.message||"send failed");return}if(t){if(t.startsWith("/"))try{const r=await fetch("/api/chat/messages",{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({channel_id:h,content:t})});if(r.status===400){const c=await r.json().catch(()=>({}));O(c.error||"couldn't send message");return}if(r.ok&&(await r.json().catch(()=>({}))).handled){O(null),$(""),Q.current=!0,I.current&&(I.current.style.height="auto");return}}catch{}if(O(null),P.current&&P.current.readyState===1)P.current.send(JSON.stringify({type:"message",channel_id:h,content:t}));else try{const r=await fetch("/api/chat/messages",{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({channel_id:h,author_id:"user",author_type:"user",content:t,content_type:"text"})});if(!r.ok){const c=await r.json().catch(()=>({}));O(c.error||"couldn't send message");return}}catch(r){O(r.message||"send failed");return}$(""),Q.current=!0,I.current&&(I.current.style.height="auto")}},Bt=t=>{var r;$(t),I.current&&(I.current.style.height="auto",I.current.style.height=Math.min(I.current.scrollHeight,120)+"px");const n=Date.now();h&&((r=P.current)==null?void 0:r.readyState)===1&&n-Ce.current>3e3&&(P.current.send(JSON.stringify({type:"typing",channel_id:h})),Ce.current=n),Se.current&&clearTimeout(Se.current),Se.current=setTimeout(()=>{Ce.current=0},4e3),Ft()},Jt=t=>{t.key==="Enter"&&!t.shiftKey&&(t.preventDefault(),Ve())},Kt=async()=>{const t=await Us({sources:["disk","workspace","agent-workspace"],multi:!0});for(const n of t){const r=Math.random().toString(36).slice(2),c=n.source==="disk"?n.file.name:n.path.split("/").pop()||"",f=n.source==="disk"?n.file.size:0;R(w=>[...w,{id:r,filename:c,size:f,uploading:!0}]);try{const w=n.source==="disk"?await Me(n.file,h??void 0):await vt({path:n.path,source:n.source,slug:n.source==="agent-workspace"?n.slug:void 0});R(_=>_.map(D=>D.id===r?{...D,record:w,uploading:!1}:D))}catch(w){R(_=>_.map(D=>D.id===r?{...D,uploading:!1,error:w.message}:D))}}},Ye=(t,n)=>{var r;((r=P.current)==null?void 0:r.readyState)===1&&P.current.send(JSON.stringify({type:"reaction",message_id:t,emoji:n})),Pe(null)},Ge=async()=>{if(L.name.trim())try{const t=await fetch("/api/chat/channels",{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({name:L.name.trim(),type:L.type,description:L.description.trim()||void 0})});if(t.ok){const n=await t.json();p(r=>[...r,n]),E(n.id),G(!1),q({name:"",type:"topic",description:""})}}catch{}},Xe=o.useCallback(async(t,n)=>{var c,f,w,_;const r=(f=(c=y.find(D=>D.id===t))==null?void 0:c.settings)==null?void 0:f.archived_agent_id;if(r){const D=T.find(U=>U.id===r);if(D){if(!window.confirm(`Restore agent "${((w=D.original)==null?void 0:w.display_name)||((_=D.original)==null?void 0:_.name)||D.archived_slug}"?`))return;try{const U=await fetch(`/api/agents/archived/${r}/restore`,{method:"POST"});if(!U.ok){const J=await U.json().catch(()=>({}));window.alert(`Restore failed: ${J.error??U.status}`);return}await Z(),await oe(),await me()}catch(U){window.alert(`Network error: ${String(U)}`)}}else window.alert("Agent entry missing — delete only.")}else window.alert(`Cannot restore channel "${n}": no associated agent found.`)},[y,T,Z,oe,me]),Qe=o.useCallback(async t=>{if(window.confirm("Permanently delete this chat? All messages are erased. This cannot be undone."))try{const n=await fetch(`/api/chat/channels/${t}`,{method:"DELETE"});if(!n.ok){const r=await n.json().catch(()=>({}));window.alert(`Delete failed: ${r.error??n.status}`);return}k(r=>r.filter(c=>c.id!==t)),h===t&&E(null)}catch(n){window.alert(`Network error: ${String(n)}`)}},[h,oe]),qt=t=>{ke(t),H(null)},Vt=async(t,n)=>{try{await Gs(t,n),ke(null)}catch(r){O(r.message)}},Yt=async t=>{if(H(null),!!window.confirm("Delete this message?"))try{await Xs(t)}catch(n){O(n.message)}},Gt=async t=>{if(H(null),!h)return;const n=`${window.location.origin}/chat/${h}?msg=${t}`;try{await navigator.clipboard.writeText(n)}catch{}},Xt=async t=>{H(null);const n=pe.some(r=>r.id===t.id);try{if(n?await Ys(t.id):await kt(t.id),h){const r=await ze(h);ie(r)}}catch(r){O(r.message)}},Qt=async t=>{if(H(null),!!h)try{await Qs(h,t)}catch(n){O(n.message)}},Zt=async t=>{try{if(await kt(t),h){const n=await ze(h);ie(n)}}catch(n){O(n.message)}},Te={dm:d.filter(t=>t.type==="dm"),topic:d.filter(t=>t.type==="topic"),group:d.filter(t=>t.type==="group")},Ze=[...d,...y],j=Ze.find(t=>t.id===h),B=((tt=j==null?void 0:j.settings)==null?void 0:tt.archived)===!0,et=[{label:"Direct Messages",icon:e.jsx(xt,{size:13}),items:Te.dm},{label:"Topics",icon:e.jsx(mt,{size:13}),items:Te.topic},{label:"Groups",icon:e.jsx(Ae,{size:13}),items:Te.group}],es=i?e.jsxs("div",{style:{padding:"8px 0 16px"},children:[e.jsx("div",{style:{padding:"0 20px 8px",fontSize:11,display:"flex",alignItems:"center",gap:6},children:K==="connected"?e.jsxs(e.Fragment,{children:[e.jsx(fe,{size:11,style:{color:"#34d399"}}),e.jsx("span",{style:{color:"rgba(52,211,153,0.8)"},children:"Connected"})]}):K==="connecting"?e.jsxs(e.Fragment,{children:[e.jsx(fe,{size:11,style:{color:"#fbbf24"}}),e.jsx("span",{style:{color:"rgba(251,191,36,0.8)"},children:"Connecting…"})]}):e.jsxs(e.Fragment,{children:[e.jsx(dt,{size:11,style:{color:"#f87171"}}),e.jsx("span",{style:{color:"rgba(248,113,113,0.8)"},children:"Offline"})]})}),et.map(t=>e.jsxs("div",{style:{marginBottom:20},children:[e.jsxs("div",{style:{fontSize:12,textTransform:"uppercase",letterSpacing:.5,color:"rgba(255,255,255,0.45)",padding:"0 20px 6px",fontWeight:600,display:"flex",alignItems:"center",gap:6},children:[t.icon," ",t.label]}),t.items.length===0?e.jsx("div",{style:{padding:"0 20px",fontSize:12,color:"rgba(255,255,255,0.2)",fontStyle:"italic"},children:"None yet"}):e.jsx("div",{style:{margin:"0 12px",borderRadius:16,background:"rgba(255,255,255,0.05)",border:"1px solid rgba(255,255,255,0.08)",overflow:"hidden"},children:t.items.map((n,r,c)=>e.jsxs("button",{type:"button",onClick:()=>E(n.id),"aria-label":`Channel ${n.name}`,style:{display:"flex",alignItems:"center",gap:10,width:"100%",padding:"14px 16px",background:h===n.id?"rgba(59,130,246,0.15)":"none",border:"none",borderBottom:r===c.length-1?"none":"1px solid rgba(255,255,255,0.06)",cursor:"pointer",color:"inherit",textAlign:"left"},children:[e.jsx("span",{style:{flex:1,fontSize:15,fontWeight:400,color:"rgba(255,255,255,0.9)",overflow:"hidden",textOverflow:"ellipsis",whiteSpace:"nowrap"},children:n.name}),(A[n.id]??0)>0&&e.jsx("span",{style:{background:"#3b82f6",color:"#fff",fontSize:10,fontWeight:700,borderRadius:9999,minWidth:18,height:18,display:"flex",alignItems:"center",justifyContent:"center",padding:"0 4px"},children:A[n.id]}),e.jsx($e,{size:16,style:{color:"rgba(255,255,255,0.25)",flexShrink:0}})]},n.id))})]},t.label)),y.length>0&&e.jsxs("div",{style:{marginBottom:20},children:[e.jsxs("button",{type:"button",onClick:()=>v(t=>!t),"aria-expanded":g,"aria-controls":"archived-channels-mobile",style:{fontSize:12,textTransform:"uppercase",letterSpacing:.5,color:"rgba(255,255,255,0.35)",padding:"0 20px 6px",fontWeight:600,display:"flex",alignItems:"center",gap:6,background:"none",border:"none",cursor:"pointer",width:"100%"},children:[e.jsx($e,{size:12,style:{transition:"transform 0.15s",transform:g?"rotate(90deg)":"none",color:"rgba(255,255,255,0.3)"},"aria-hidden":"true"}),e.jsx(ce,{size:12,"aria-hidden":"true"}),"Archived (",y.length,")"]}),e.jsx("div",{id:"archived-channels-mobile",style:{display:g?"block":"none"},children:e.jsx("div",{style:{margin:"0 12px",borderRadius:16,background:"rgba(255,255,255,0.03)",border:"1px solid rgba(255,255,255,0.06)",overflow:"hidden"},children:y.map((t,n,r)=>{var w;const c=(w=t.settings)==null?void 0:w.archived_agent_id,f=c?T.some(_=>_.id===c):!1;return e.jsxs("div",{style:{display:"flex",alignItems:"center",gap:8,borderBottom:n===r.length-1?"none":"1px solid rgba(255,255,255,0.04)",opacity:.6},children:[e.jsxs("button",{type:"button",onClick:()=>E(t.id),"aria-label":`Archived channel ${t.name}`,style:{flex:1,display:"flex",alignItems:"center",gap:8,padding:"12px 8px 12px 16px",background:h===t.id?"rgba(59,130,246,0.12)":"none",border:"none",cursor:"pointer",color:"inherit",textAlign:"left",minWidth:0},children:[e.jsx(ce,{size:11,"aria-hidden":"true",style:{color:"rgba(255,255,255,0.4)",flexShrink:0}}),e.jsx("span",{style:{flex:1,fontSize:14,color:"rgba(255,255,255,0.7)",overflow:"hidden",textOverflow:"ellipsis",whiteSpace:"nowrap"},children:t.name})]}),e.jsxs("div",{style:{display:"flex",gap:2,paddingRight:8},children:[e.jsx("button",{type:"button",onClick:()=>Xe(t.id,t.name),disabled:!f,"aria-label":`Restore archived channel ${t.name}`,title:f?"Restore agent":"Agent entry missing — delete only",style:{background:"none",border:"none",cursor:f?"pointer":"not-allowed",color:f?"rgba(52,211,153,0.7)":"rgba(255,255,255,0.2)",padding:"6px"},children:e.jsx(ut,{size:13,"aria-hidden":"true"})}),e.jsx("button",{type:"button",onClick:()=>Qe(t.id),"aria-label":`Permanently delete archived channel ${t.name}`,title:"Delete permanently",style:{background:"none",border:"none",cursor:"pointer",color:"rgba(248,113,113,0.7)",padding:"6px"},children:e.jsx(ht,{size:13,"aria-hidden":"true"})})]})]},t.id)})})})]})]}):e.jsxs("div",{className:"w-full flex flex-col h-full",children:[e.jsx("div",{className:"px-3 py-1.5 text-[11px] flex items-center gap-1.5",children:K==="connected"?e.jsxs(e.Fragment,{children:[e.jsx(fe,{size:11,className:"text-emerald-400"}),e.jsx("span",{className:"text-emerald-400/80",children:"Connected"})]}):K==="connecting"?e.jsxs(e.Fragment,{children:[e.jsx(fe,{size:11,className:"text-amber-400 animate-pulse"}),e.jsx("span",{className:"text-amber-400/80",children:"Connecting..."})]}):e.jsxs(e.Fragment,{children:[e.jsx(dt,{size:11,className:"text-red-400"}),e.jsx("span",{className:"text-red-400/80",children:"Offline"})]})}),e.jsxs("div",{className:"flex-1 overflow-y-auto py-1",children:[et.map(t=>e.jsxs("div",{children:[e.jsxs("div",{className:"px-3 pt-3 pb-1 text-[10px] font-semibold uppercase tracking-wider text-white/30 flex items-center gap-1.5",children:[t.icon," ",t.label]}),t.items.length===0&&e.jsx("div",{className:"px-3 py-1 text-[11px] text-white/20 italic",children:"None yet"}),t.items.map(n=>e.jsxs(F,{variant:h===n.id?"secondary":"ghost",onClick:()=>E(n.id),className:"w-full justify-start h-auto py-1.5 px-3 text-[13px] rounded-none font-normal","aria-label":`Channel ${n.name}`,children:[e.jsx("span",{className:"truncate flex-1 text-left",children:n.name}),(A[n.id]??0)>0&&e.jsx("span",{className:"shrink-0 bg-blue-500 text-white text-[10px] font-bold rounded-full min-w-[18px] h-[18px] flex items-center justify-center px-1",children:A[n.id]})]},n.id))]},t.label)),y.length>0&&e.jsxs("div",{className:"mt-2",children:[e.jsxs("button",{type:"button",onClick:()=>v(t=>!t),className:"flex items-center gap-1.5 px-3 pt-2 pb-1 text-[10px] font-semibold uppercase tracking-wider text-white/25 hover:text-white/40 transition-colors w-full text-left","aria-expanded":g,"aria-controls":"archived-channels-desktop",children:[e.jsx($e,{size:11,className:`transition-transform ${g?"rotate-90":""}`,"aria-hidden":"true"}),e.jsx(ce,{size:11,"aria-hidden":"true"}),"Archived (",y.length,")"]}),e.jsx("div",{id:"archived-channels-desktop",className:g?"":"hidden",children:y.map(t=>{var c;const n=(c=t.settings)==null?void 0:c.archived_agent_id,r=n?T.some(f=>f.id===n):!1;return e.jsxs("div",{className:"group relative flex items-center opacity-60 hover:opacity-80 transition-opacity",children:[e.jsxs(F,{variant:h===t.id?"secondary":"ghost",onClick:()=>E(t.id),className:"flex-1 justify-start h-auto py-1.5 pl-3 pr-1 text-[13px] rounded-none font-normal min-w-0","aria-label":`Archived channel ${t.name}`,children:[e.jsx(ce,{size:11,className:"shrink-0 mr-1.5 text-white/40","aria-hidden":"true"}),e.jsx("span",{className:"truncate flex-1 text-left",children:t.name})]}),e.jsxs("div",{className:"hidden group-hover:flex items-center shrink-0 pr-1",children:[e.jsx("button",{type:"button",onClick:()=>Xe(t.id,t.name),disabled:!r,"aria-label":`Restore archived channel ${t.name}`,title:r?"Restore agent":"Agent entry missing — delete only",className:`p-1 rounded transition-colors ${r?"text-white/30 hover:text-emerald-400 hover:bg-emerald-500/10 cursor-pointer":"text-white/15 cursor-not-allowed"}`,children:e.jsx(ut,{size:12,"aria-hidden":"true"})}),e.jsx("button",{type:"button",onClick:()=>Qe(t.id),"aria-label":`Permanently delete archived channel ${t.name}`,title:"Delete permanently",className:"p-1 rounded text-white/30 hover:text-red-400 hover:bg-red-500/10 transition-colors cursor-pointer",children:e.jsx(ht,{size:12,"aria-hidden":"true"})})]})]},t.id)})})]})]})]}),ts=e.jsx("div",{className:"flex-1 flex flex-col min-w-0 h-full",children:h?e.jsxs(e.Fragment,{children:[e.jsxs("div",{className:"px-4 py-2.5 border-b border-white/[0.06] flex items-center gap-3 shrink-0",children:[(j==null?void 0:j.type)==="topic"?e.jsx(mt,{size:16,className:"text-white/40"}):(j==null?void 0:j.type)==="group"?e.jsx(Ae,{size:16,className:"text-white/40"}):e.jsx(xt,{size:16,className:"text-white/40"}),(()=>{if((j==null?void 0:j.type)!=="dm")return null;const t=(j.members??[]).find(r=>r!=="user");if(!t)return null;const n=u.find(r=>r.name===t);return n?e.jsx("span",{className:"text-base leading-none shrink-0","aria-hidden":"true",children:ot(n.emoji,n.framework)}):null})(),e.jsxs("div",{className:"min-w-0 flex-1",children:[e.jsxs("div",{className:"text-sm font-medium truncate flex items-center gap-1",children:[(j==null?void 0:j.name)??"Unknown",j&&j.type!=="dm"&&e.jsx("button",{"aria-label":"Channel settings",onClick:Wt,className:"ml-1 opacity-60 hover:opacity-100",children:"ⓘ"}),e.jsx("a",{"aria-label":"Open chat guide",href:"https://github.com/jaylfc/tinyagentos/blob/master/docs/chat-guide.md",target:"_blank",rel:"noreferrer",className:"ml-1 opacity-60 hover:opacity-100 text-[12px]",children:"?"}),e.jsxs("div",{className:"relative",children:[e.jsx(Ks,{count:pe.length,onClick:()=>Ne(t=>!t)}),Rt&&e.jsx(qs,{pins:pe,onJumpTo:t=>{Ne(!1);const n=document.querySelector(`[data-message-id="${t}"]`);n&&(n.scrollIntoView({behavior:"smooth",block:"center"}),n.classList.add("data-highlight"),setTimeout(()=>n.classList.remove("data-highlight"),2e3))},onClose:()=>Ne(!1)})]})]}),(j==null?void 0:j.description)&&e.jsx("div",{className:"text-[11px] text-white/35 truncate",children:j.description})]}),(j==null?void 0:j.members)&&e.jsxs("div",{className:"text-[11px] text-white/30 flex items-center gap-1",children:[e.jsx(Ae,{size:12})," ",j.members.length]})]}),e.jsxs("div",{ref:He,onScroll:Ut,className:`flex-1 overflow-y-auto px-4 py-3 space-y-0.5 message-list-drop-target ${m.isOver?"ring-2 ring-sky-400/60 ring-inset bg-sky-500/5":m.isValidTarget?"ring-2 ring-sky-400/30 ring-inset":""}`,style:i&&l>0?{paddingBottom:`${l+60}px`}:void 0,onDragEnter:m.dropHandlers.onDragEnter,onDragOver:t=>{m.dropHandlers.onDragOver(t),t.defaultPrevented||t.preventDefault()},onDragLeave:m.dropHandlers.onDragLeave,onDrop:t=>{if(t.dataTransfer.files&&t.dataTransfer.files.length>0){t.preventDefault();for(const n of Array.from(t.dataTransfer.files)){const r=Math.random().toString(36).slice(2);R(c=>[...c,{id:r,filename:n.name,size:n.size,uploading:!0}]),Me(n,h??void 0).then(c=>R(f=>f.map(w=>w.id===r?{...w,record:c,uploading:!1}:w))).catch(c=>R(f=>f.map(w=>w.id===r?{...w,uploading:!1,error:c.message}:w)))}return}m.dropHandlers.onDrop(t)},children:[C.length===0&&e.jsx("div",{className:"flex items-center justify-center h-full text-white/20 text-sm",children:"No messages yet. Say something!"}),C.map((t,n)=>{var U,J,at,rt;const r=t.author_type==="agent",c=n>0?C[n-1]:void 0,f=!c||c.author_id!==t.author_id,w=Zs(t.author_id,t.author_type,u,T),_=r&&w!=="active",D=w==="archived"?"Agent no longer active":w==="removed"?"Agent removed":void 0;return e.jsxs("div",{"data-message-id":t.id,className:`group relative px-3 py-1 rounded-md transition-colors hover:bg-white/[0.03] ${r&&!_?"bg-blue-500/[0.04]":""} ${f?"mt-3":""}`,onMouseEnter:()=>Ie(t.id),onMouseLeave:()=>Ie(M=>M===t.id?null:M),children:[f&&e.jsxs("div",{className:"flex items-center gap-2 mb-0.5",onContextMenu:M=>{t.author_type==="agent"&&(M.preventDefault(),ae({slug:t.author_id,x:M.clientX,y:M.clientY}))},children:[r&&!_&&(()=>{const M=u.find(ee=>ee.name===t.author_id);return M?e.jsx("span",{className:"text-[14px] leading-none","aria-hidden":"true",children:ot(M.emoji,M.framework)}):null})(),e.jsx("span",{className:`text-[13px] font-semibold ${_?"line-through text-white/35":r?"text-blue-400":"text-white/90"}`,style:_?{opacity:.55}:void 0,title:D,children:t.author_id}),r&&!_&&e.jsxs("span",{className:"text-[10px] bg-blue-500/20 text-blue-300 px-1.5 py-0.5 rounded font-medium flex items-center gap-0.5",children:[e.jsx(ft,{size:10,"aria-hidden":"true"})," Agent"]}),_&&e.jsxs("span",{className:"text-[10px] bg-zinc-500/20 text-zinc-500 px-1.5 py-0.5 rounded font-medium flex items-center gap-0.5",children:[e.jsx(ft,{size:10,"aria-hidden":"true"}),w==="archived"?"inactive":"removed"]}),e.jsx("span",{className:`text-[11px] ${_?"text-white/15":"text-white/25"}`,children:en(t.created_at)}),t.edited_at&&e.jsx("span",{className:"text-[10px] text-white/20",children:"(edited)"})]}),t.deleted_at?e.jsx(Js,{}):Pt===t.id?e.jsx(Bs,{initial:t.content,onSave:M=>Vt(t.id,M),onCancel:()=>ke(null)}):e.jsxs("div",{className:`text-[13px] leading-relaxed whitespace-pre-wrap break-words ${_?"text-white/45":"text-white/80"}`,children:[tn(t.content),t.state==="pending"&&e.jsx("span",{className:"ml-1 text-white/30",children:"..."}),t.state==="streaming"&&e.jsxs("span",{className:"ml-1 inline-flex gap-0.5",children:[e.jsx("span",{className:"w-1 h-1 bg-blue-400 rounded-full animate-bounce [animation-delay:0ms]"}),e.jsx("span",{className:"w-1 h-1 bg-blue-400 rounded-full animate-bounce [animation-delay:150ms]"}),e.jsx("span",{className:"w-1 h-1 bg-blue-400 rounded-full animate-bounce [animation-delay:300ms]"})]}),t.state==="error"&&e.jsx("span",{className:"ml-1 text-red-400 text-[11px]",children:"(error)"})]}),((U=t.metadata)==null?void 0:U.pin_requested)&&t.author_type==="agent"&&e.jsx(Vs,{authorId:t.author_id,onApprove:()=>Zt(t.id)}),t.content_type==="canvas"&&(((J=t.metadata)==null?void 0:J.canvas_url)||((at=t.metadata)==null?void 0:at.canvas_id))&&e.jsx("div",{className:"mt-2",children:e.jsxs(F,{size:"sm",variant:"outline",onClick:()=>{var ee,it,lt;const M=((ee=t.metadata)==null?void 0:ee.canvas_url)??`/canvas/${(it=t.metadata)==null?void 0:it.canvas_id}`;we({url:M,title:(lt=t.metadata)==null?void 0:lt.canvas_title})},className:"h-7 px-2.5 text-[12px] gap-1.5 bg-white/[0.04] border-white/10 hover:bg-white/[0.08]","aria-label":"View canvas",children:[e.jsx(gt,{size:13}),"View Canvas",(rt=t.metadata)!=null&&rt.canvas_title?`: ${t.metadata.canvas_title}`:""]})}),t.reactions&&Object.keys(t.reactions).length>0&&e.jsx("div",{className:"flex flex-wrap gap-1 mt-1",children:Object.entries(t.reactions).map(([M,ee])=>e.jsxs("button",{onClick:()=>Ye(t.id,M),className:"text-[12px] bg-white/[0.06] hover:bg-white/10 border border-white/[0.06] rounded-full px-2 py-0.5 flex items-center gap-1 transition-colors",children:[e.jsx("span",{children:M}),e.jsx("span",{className:"text-white/40",children:ee.length})]},M))}),(i||Dt===t.id)&&e.jsx("div",{className:"absolute top-0 right-2 -translate-y-1/2 z-10",children:e.jsx($s,{onReact:()=>Pe(De===t.id?null:t.id),onReplyInThread:()=>qe(t.channel_id??h??"",t.id),onOverflow:M=>{M.preventDefault(),H({messageId:t.id,x:M.clientX,y:M.clientY})}})}),e.jsx(Rs,{attachments:t.attachments||[]}),typeof t.reply_count=="number"&&t.reply_count>0&&e.jsx(As,{replyCount:t.reply_count,lastReplyAt:t.last_reply_at??null,onOpen:()=>qe(t.channel_id??h??"",t.id)}),De===t.id&&e.jsx("div",{className:"absolute right-2 top-5 bg-zinc-800 border border-white/10 rounded-lg shadow-xl p-2 flex gap-1 z-10",children:sn.map(M=>e.jsx("button",{onClick:()=>Ye(t.id,M),className:"text-lg hover:bg-white/10 rounded p-0.5 transition-colors",children:M},M))})]},t.id)}),e.jsx("div",{ref:Fe})]}),e.jsx(Cs,{humans:Mt,agents:zt,selfId:"user"}),B&&e.jsxs("div",{className:"mx-4 mb-2 px-3 py-2 rounded-lg bg-amber-500/10 border border-amber-500/20 text-[12px] text-amber-400/80 flex items-center gap-2 shrink-0",role:"status",children:[e.jsx(ce,{size:13,"aria-hidden":"true"}),"This chat is archived. The agent is no longer active."]}),ne&&e.jsxs("div",{className:"mx-4 mb-1 px-3 py-2 rounded-lg bg-blue-500/10 border border-blue-500/20 text-[12px] text-blue-300/90 flex items-center gap-2 shrink-0",role:"status","aria-label":`Composer prefilled from prompt: ${ne.promptName}`,children:[e.jsxs("span",{className:"flex-1 truncate",children:["Prefilled from: ",ne.promptName,ne.agentName?` for ${ne.agentName}`:""," — edit and send"]}),e.jsx("button",{onClick:()=>{Re(null),$("")},className:"shrink-0 p-0.5 rounded hover:bg-white/10 transition-colors","aria-label":"Dismiss prefill",children:e.jsx(ge,{size:12,"aria-hidden":"true"})})]}),Le&&e.jsx("div",{role:"alert",className:"text-xs text-red-300 bg-red-500/10 border border-red-500/30 rounded px-3 py-1 mx-4",children:Le}),e.jsx(Ds,{items:X,onRemove:t=>R(n=>n.filter(r=>r.id!==t)),onRetry:t=>{R(n=>n.map(r=>r.id===t?{...r,uploading:!1,error:"retry not yet supported — remove and re-add"}:r))}}),e.jsx("div",{className:"px-4 py-3 border-t border-white/[0.06] shrink-0",style:i?{paddingBottom:`max(env(safe-area-inset-bottom), ${l}px)`}:void 0,children:e.jsxs("div",{className:"relative",children:[Ke&&e.jsx(ks,{commands:$t,queryAfterSlash:Ht,members:(j==null?void 0:j.members)||[],onPick:(t,n)=>{$(`@${t} /${n} `)},onClose:()=>{}}),e.jsxs("div",{className:`flex items-end gap-2 rounded-xl border px-2 py-1.5 ${B?"bg-white/[0.02] border-white/[0.04] opacity-50":"bg-white/[0.06] border-white/[0.08]"}`,children:[e.jsx(F,{variant:"ghost",size:"icon",onClick:Kt,className:"h-8 w-8 shrink-0 mb-0.5","aria-label":"Upload file",disabled:B,children:e.jsx(ms,{size:16})}),e.jsx(rs,{ref:I,value:b,onChange:t=>!B&&Bt(t.target.value),onKeyDown:t=>!B&&Jt(t),onPaste:t=>{if(!t.clipboardData)return;const n=Array.from(t.clipboardData.files).filter(r=>r.type.startsWith("image/"));if(n.length!==0){t.preventDefault();for(const r of n){const c=Math.random().toString(36).slice(2);R(f=>[...f,{id:c,filename:r.name||"pasted.png",size:r.size,uploading:!0}]),Me(r,h??void 0).then(f=>R(w=>w.map(_=>_.id===c?{..._,record:f,uploading:!1}:_))).catch(f=>R(w=>w.map(_=>_.id===c?{..._,uploading:!1,error:f.message}:_)))}}},placeholder:B?"This chat is archived":`Message #${(j==null?void 0:j.name)??""}...`,rows:1,disabled:B,className:"flex-1 bg-transparent border-0 px-1 py-1.5 min-h-0 text-[13px] focus-visible:ring-0 focus-visible:border-0 max-h-[120px] disabled:cursor-not-allowed","aria-label":"Message input"}),e.jsx(F,{size:"icon",onClick:Ve,disabled:!b.trim()&&X.length===0||B||X.some(t=>t.uploading),className:"h-8 w-8 shrink-0 mb-0.5","aria-label":"Send message",children:e.jsx(xs,{size:15})})]})]})})]}):e.jsx("div",{className:"flex-1 flex items-center justify-center text-white/20",children:e.jsxs("div",{className:"text-center",children:[e.jsx(pt,{size:48,className:"mx-auto mb-3 opacity-30"}),e.jsx("p",{className:"text-sm",children:"Select a channel to start chatting"})]})})}),ss=!i||h===null;return e.jsxs("div",{className:"flex flex-col h-full bg-shell-base text-white overflow-hidden",children:[ss&&e.jsx("div",{className:"relative flex items-center px-3 py-2.5 border-b border-white/[0.06] shrink-0",children:a?e.jsxs(e.Fragment,{children:[e.jsx("div",{className:"absolute inset-0 flex items-center justify-center pointer-events-none",children:e.jsx("span",{className:"text-sm font-semibold text-white/90",children:a})}),e.jsx("div",{className:"ml-auto",children:e.jsx(F,{variant:"ghost",size:"icon",onClick:()=>G(!0),className:"h-7 w-7","aria-label":"New channel",children:e.jsx(bt,{size:15})})})]}):e.jsxs(e.Fragment,{children:[e.jsxs("div",{className:"flex items-center gap-2 text-sm font-medium text-white/80",children:[e.jsx(pt,{size:15}),!i&&"Messages"]}),e.jsx(F,{variant:"ghost",size:"icon",onClick:()=>G(!0),className:"h-7 w-7 ml-auto","aria-label":"New channel",children:e.jsx(bt,{size:15})})]})}),e.jsx("div",{className:"flex-1 min-h-0 overflow-hidden",children:e.jsx(ds,{selectedId:h,onBack:()=>E(null),listTitle:"Messages",detailTitle:j==null?void 0:j.name,listWidth:240,list:es,detail:ts})}),he&&(()=>{const t=C.find(r=>r.id===he.messageId);if(!t)return null;const n=e.jsx(Fs,{isOwn:t.author_id===Ot,isHuman:!0,isPinned:pe.some(r=>r.id===t.id),onEdit:()=>qt(t.id),onDelete:()=>Yt(t.id),onCopyLink:()=>Gt(t.id),onPin:()=>Xt(t),onMarkUnread:()=>Qt(t.id),onClose:()=>H(null)});return i?e.jsx(Ws,{open:!0,onClose:()=>H(null),children:n}):e.jsxs(e.Fragment,{children:[e.jsx("div",{className:"fixed inset-0 z-40",onClick:()=>H(null)}),e.jsx("div",{className:"fixed z-50",style:{top:he.y,left:he.x},children:n})]})})(),Tt&&j&&e.jsx(vs,{channel:{id:j.id,name:j.name,type:j.type,topic:j.topic??"",members:j.members??[],settings:j.settings??{}},knownAgents:u.map(t=>({name:t.name})),onClose:()=>ve(!1),onChanged:()=>{Z()}}),le&&e.jsx(zs,{channelId:le.channelId,parentId:le.parentId,onClose:Ue,isFullscreen:i,onSend:async(t,n)=>{const r=await fetch("/api/chat/messages",{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({channel_id:le.channelId,author_id:"user",author_type:"user",content:t,content_type:"text",thread_id:le.parentId,attachments:n})});if(!r.ok){const c=await r.json().catch(()=>({}));throw new Error(c.error||`HTTP ${r.status}`)}}}),V&&e.jsx(js,{slug:V.slug,channelId:h??void 0,channelType:j==null?void 0:j.type,isMuted:((nt=(st=j==null?void 0:j.settings)==null?void 0:st.muted)==null?void 0:nt.includes(V.slug))??!1,x:V.x,y:V.y,onClose:()=>ae(null),onDm:async t=>{const n=d.find(r=>r.type==="dm"&&(r.members||[]).length===2&&(r.members||[]).includes("user")&&(r.members||[]).includes(t));if(n)E(n.id);else{const r=await fetch("/api/chat/channels",{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({name:t,type:"dm",members:["user",t],description:"",topic:""})});if(r.ok){const c=await r.json();await Z(),E(c.id)}}ae(null)},onViewInfo:t=>{const n=u.find(r=>r.name===t);n&&Oe({slug:t,framework:n.framework||"unknown",model:n.model||"unknown",status:n.status||"unknown",x:V.x,y:V.y}),ae(null)},onJumpToSettings:t=>{window.dispatchEvent(new CustomEvent("taos:open-agent",{detail:{slug:t}})),ae(null)}}),W&&e.jsxs("div",{role:"dialog","aria-label":`Agent info for @${W.slug}`,className:"fixed z-50 bg-shell-surface border border-white/10 rounded-lg shadow-xl p-3 text-xs min-w-[200px]",style:{top:W.y,left:W.x},onMouseLeave:()=>Oe(null),children:[e.jsxs("div",{className:"font-semibold text-sm mb-1",children:["@",W.slug]}),e.jsxs("div",{className:"opacity-70",children:["Framework: ",W.framework]}),e.jsxs("div",{className:"opacity-70",children:["Model: ",W.model]}),e.jsxs("div",{className:"opacity-70",children:["Status: ",W.status]})]}),ye&&e.jsx("div",{className:"fixed inset-0 z-[10002] flex items-center justify-center bg-black/60 backdrop-blur-sm",onClick:()=>we(null),role:"dialog","aria-modal":"true","aria-label":"Canvas viewer",children:e.jsxs("div",{className:"w-[90vw] h-[85vh] max-w-5xl rounded-xl border border-white/10 overflow-hidden bg-zinc-900 flex flex-col",onClick:t=>t.stopPropagation(),children:[e.jsxs("div",{className:"flex items-center justify-between px-4 py-2 border-b border-white/10 shrink-0",children:[e.jsxs("div",{className:"flex items-center gap-2 text-sm text-white/80",children:[e.jsx(gt,{size:14}),e.jsx("span",{children:ye.title??"Canvas"})]}),e.jsx(F,{variant:"ghost",size:"icon",onClick:()=>we(null),className:"h-7 w-7","aria-label":"Close canvas viewer",children:e.jsx(ge,{size:14})})]}),e.jsx("iframe",{src:ye.url,className:"flex-1 w-full border-none bg-white",title:"Canvas"})]})}),_t&&(i?e.jsx("div",{className:"fixed inset-0 z-50",onClick:()=>G(!1),role:"dialog","aria-modal":"true","aria-label":"New channel",children:e.jsxs("div",{className:"absolute bottom-0 left-0 right-0 bg-zinc-900 border-t border-white/[0.08] rounded-t-2xl p-4 space-y-3",onClick:t=>t.stopPropagation(),children:[e.jsxs("div",{className:"flex items-center justify-between mb-1",children:[e.jsx("span",{className:"text-sm font-semibold",children:"New Channel"}),e.jsx(F,{variant:"ghost",size:"icon",onClick:()=>G(!1),className:"h-7 w-7","aria-label":"Close",children:e.jsx(ge,{size:15})})]}),e.jsxs("div",{className:"space-y-1",children:[e.jsx(te,{htmlFor:"new-channel-name-mobile",className:"block uppercase tracking-wider",children:"Name"}),e.jsx(xe,{id:"new-channel-name-mobile",value:L.name,onChange:t=>q(n=>({...n,name:t.target.value})),placeholder:"general","aria-label":"Channel name"})]}),e.jsxs("div",{className:"space-y-1",children:[e.jsx(te,{htmlFor:"new-channel-type-mobile",className:"block uppercase tracking-wider",children:"Type"}),e.jsxs("select",{id:"new-channel-type-mobile",value:L.type,onChange:t=>q(n=>({...n,type:t.target.value})),className:"w-full bg-white/[0.06] border border-white/10 rounded-lg px-3 py-2 text-sm text-white outline-none focus:border-blue-500/50","aria-label":"Channel type",children:[e.jsx("option",{value:"topic",children:"Topic"}),e.jsx("option",{value:"group",children:"Group"})]})]}),e.jsxs("div",{className:"space-y-1",children:[e.jsx(te,{htmlFor:"new-channel-description-mobile",className:"block uppercase tracking-wider",children:"Description"}),e.jsx(xe,{id:"new-channel-description-mobile",value:L.description,onChange:t=>q(n=>({...n,description:t.target.value})),placeholder:"What's this channel about?","aria-label":"Channel description"})]}),e.jsx(F,{onClick:Ge,disabled:!L.name.trim(),className:"w-full",children:"Create Channel"})]})}):e.jsx("div",{className:"absolute inset-0 bg-black/60 flex items-center justify-center z-50 p-4",children:e.jsxs(is,{className:"w-full max-w-[380px] max-h-full flex flex-col shadow-2xl bg-zinc-900",children:[e.jsxs(ls,{className:"flex flex-row items-center justify-between gap-2 p-0 px-4 py-3 border-b border-white/[0.06]",children:[e.jsx(os,{className:"text-sm font-medium",children:"New Channel"}),e.jsx(F,{variant:"ghost",size:"icon",onClick:()=>G(!1),className:"h-7 w-7","aria-label":"Close",children:e.jsx(ge,{size:15})})]}),e.jsxs(cs,{className:"p-4 pt-4 space-y-3",children:[e.jsxs("div",{className:"space-y-1",children:[e.jsx(te,{htmlFor:"new-channel-name",className:"block uppercase tracking-wider",children:"Name"}),e.jsx(xe,{id:"new-channel-name",value:L.name,onChange:t=>q(n=>({...n,name:t.target.value})),placeholder:"general","aria-label":"Channel name"})]}),e.jsxs("div",{className:"space-y-1",children:[e.jsx(te,{htmlFor:"new-channel-type",className:"block uppercase tracking-wider",children:"Type"}),e.jsxs("select",{id:"new-channel-type",value:L.type,onChange:t=>q(n=>({...n,type:t.target.value})),className:"w-full bg-white/[0.06] border border-white/10 rounded-lg px-3 py-2 text-sm text-white outline-none focus:border-blue-500/50","aria-label":"Channel type",children:[e.jsx("option",{value:"topic",children:"Topic"}),e.jsx("option",{value:"group",children:"Group"})]})]}),e.jsxs("div",{className:"space-y-1",children:[e.jsx(te,{htmlFor:"new-channel-description",className:"block uppercase tracking-wider",children:"Description"}),e.jsx(xe,{id:"new-channel-description",value:L.description,onChange:t=>q(n=>({...n,description:t.target.value})),placeholder:"What's this channel about?","aria-label":"Channel description"})]}),e.jsx(F,{onClick:Ge,disabled:!L.name.trim(),className:"w-full",children:"Create Channel"})]})]})}))]})}export{hn as MessagesApp,Zs as resolveAuthorDisplayState}; diff --git a/static/desktop/assets/ProvidersApp-BEdnJTlt.js b/static/desktop/assets/ProvidersApp-BZ0Cnn9e.js similarity index 99% rename from static/desktop/assets/ProvidersApp-BEdnJTlt.js rename to static/desktop/assets/ProvidersApp-BZ0Cnn9e.js index cdc1d7d9..31600dab 100644 --- a/static/desktop/assets/ProvidersApp-BEdnJTlt.js +++ b/static/desktop/assets/ProvidersApp-BZ0Cnn9e.js @@ -1 +1 @@ -import{r as x,j as e}from"./vendor-react-l6srOxy7.js";import{B as g,C as F,c as U,L as O,I as D}from"./toolbar-UW6q5pkx.js";import{a as ne,g as ie}from"./main-w-WDDs5-.js";import{M as oe}from"./MobileSplitView-B-4MQO2C.js";import{u as H}from"./use-is-mobile-v5lglusa.js";import{j as q,a9 as W,g as V,ax as X,y as Q,f as ce,aw as de,ay as ae,X as xe}from"./vendor-icons--yQaiqiL.js";import"./vendor-radix-BhM7AEEG.js";import"./vendor-layout-B-pp9n1f.js";import"./tokens-BKHlNYpw.js";import"./vendor-codemirror-aNcHammg.js";const le=["openai","anthropic","openrouter","kilocode"],pe=["rkllama","ollama","llama-cpp","vllm","exo","mlx"],G={openai:"https://api.openai.com/v1",anthropic:"https://api.anthropic.com/v1",openrouter:"https://openrouter.ai/api/v1",kilocode:"https://api.kilo.ai/api/gateway",ollama:"http://localhost:11434",rkllama:"http://localhost:8080","llama-cpp":"http://localhost:8080",vllm:"http://localhost:8000"},Y={openai:{label:"OpenAI",description:"GPT-4o, o1, and more",url:"https://api.openai.com/v1",keyPlaceholder:"sk-..."},anthropic:{label:"Anthropic",description:"Claude Sonnet, Opus, Haiku",url:"https://api.anthropic.com/v1",keyPlaceholder:"sk-ant-..."},openrouter:{label:"OpenRouter",description:"300+ models via one API",url:"https://openrouter.ai/api/v1",keyPlaceholder:"sk-or-..."},kilocode:{label:"Kilo",description:"500+ models, smart routing",url:"https://api.kilo.ai/api/gateway",keyPlaceholder:"kilo-..."}},Z={ok:"bg-emerald-500/20 text-emerald-400",online:"bg-emerald-500/20 text-emerald-400",slow:"bg-amber-500/20 text-amber-400",error:"bg-red-500/20 text-red-400",unknown:"bg-zinc-500/20 text-zinc-400"},me={ok:"Online",online:"Online",slow:"Slow",error:"Error",unknown:"Unknown"},ee={local:"Local / On Device",network:"Network / Cluster",cloud:"Cloud"},he=["local","network","cloud"];function K(t){return le.includes(t)}function M({type:t}){const i=K(t);return e.jsx("span",{className:`text-[10px] px-1.5 py-0.5 rounded font-medium ${i?"bg-violet-500/20 text-violet-300":"bg-teal-500/20 text-teal-300"}`,children:t})}function J({status:t}){const i=Z[t]??Z.unknown,m=me[t]??"Unknown";return e.jsx("span",{className:`text-[10px] px-1.5 py-0.5 rounded-full font-medium ${i}`,children:m})}const te={running:"bg-emerald-500/20 text-emerald-400",stopped:"bg-zinc-500/20 text-zinc-400",error:"bg-red-500/20 text-red-400",starting:"bg-blue-500/20 text-blue-400",draining:"bg-amber-500/20 text-amber-400",stopping:"bg-amber-500/20 text-amber-400"},re={running:"Running",stopped:"Stopped",error:"Error",starting:"Starting…",draining:"Draining…",stopping:"Stopping…"};function ue({state:t}){const i=te[t]??te.stopped,m=re[t]??t,u=t==="starting"||t==="draining"||t==="stopping";return e.jsxs("span",{className:`text-[10px] px-1.5 py-0.5 rounded-full font-medium inline-flex items-center gap-1 ${i}`,children:[u&&e.jsx("svg",{className:"animate-spin",width:"8",height:"8",viewBox:"0 0 8 8",fill:"none","aria-hidden":"true",children:e.jsx("circle",{cx:"4",cy:"4",r:"3",stroke:"currentColor",strokeWidth:"1.5",strokeDasharray:"10",strokeDashoffset:"5"})}),m]})}function se({name:t,platform:i}){const m=i?` · ${i}`:"";return e.jsxs("span",{className:"text-[10px] px-1.5 py-0.5 rounded-full font-medium bg-blue-500/20 text-blue-300 inline-flex items-center gap-1",title:`Backend on worker ${t}${m}`,children:[e.jsx("svg",{width:"8",height:"8",viewBox:"0 0 8 8",fill:"none",children:e.jsx("circle",{cx:"4",cy:"4",r:"3",stroke:"currentColor",strokeWidth:"1.5"})}),t]})}function fe(t){var m;const i={local:[],network:[],cloud:[]};for(const u of t){const p=u.category??((m=u.source)!=null&&m.startsWith("worker:")?"network":le.includes(u.type)?"cloud":"local");i[p].push(u)}return i}function ge(t){return t?{name:t.name,type:t.type,url:t.url,apiKey:"",priority:String(t.priority??99)}:{name:"",type:"openai",url:G.openai,apiKey:"",priority:"99"}}function be({editing:t,onSave:i,onClose:m}){var z;const u=H(),p=!!t,[h,k]=x.useState(p?"config":"category"),[v,w]=x.useState(null),[r,f]=x.useState(()=>ge(t)),[b,j]=x.useState(null),[T,A]=x.useState(!1),[P,o]=x.useState(!1),[_,E]=x.useState(null),[R,$]=x.useState(!1);function L(s,n){f(l=>({...l,[s]:n})),j(null),$(!1)}function S(s){f(n=>({...n,type:s,url:G[s]??n.url})),j(null),$(!1)}function B(s){const n=Y[s];n&&(f(l=>({...l,type:s,url:n.url,name:l.name||s})),j(null),$(!1),k("config"))}function c(){if(h==="config"&&v==="cloud"){k("cloud-pick");return}if(h==="config"&&v==="local"){k("category");return}if(h==="config"&&v==="cluster"){k("cluster-info");return}if(h==="config"&&v===null){m();return}if(h==="cloud-pick"){k("category");return}if(h==="cluster-info"){k("category");return}}async function y(){A(!0),j(null),E(null);try{const n=await(await fetch("/api/providers/test",{method:"POST",headers:{"Content-Type":"application/json",Accept:"application/json"},body:JSON.stringify({type:r.type,url:r.url})})).json();j(n)}catch(s){j({reachable:!1,error:s instanceof Error?s.message:"Network error"})}A(!1)}async function d(){if(!r.name.trim()){E("Name is required");return}o(!0),E(null);let s=t==null?void 0:t.api_key_secret;if(r.apiKey.trim()){const n=`provider-${r.name.trim()}-key`;try{await fetch("/api/secrets",{method:"POST",headers:{"Content-Type":"application/json",Accept:"application/json"},body:JSON.stringify({name:n,value:r.apiKey.trim(),category:"api-key",description:`API key for ${r.name.trim()} provider`,agents:[]})}),s=n}catch{}}try{const n={name:r.name.trim(),type:r.type,url:r.url.trim(),priority:parseInt(r.priority)||99};s&&(n.api_key_secret=s),p&&await fetch(`/api/providers/${encodeURIComponent(t.name)}`,{method:"DELETE",headers:{Accept:"application/json"}});const l=await fetch("/api/providers",{method:"POST",headers:{"Content-Type":"application/json",Accept:"application/json"},body:JSON.stringify(n)});if(!l.ok){let C=`Save failed (${l.status})`;try{const I=await l.json();I!=null&&I.error&&(C=String(I.error))}catch{}E(C),o(!1);return}i()}catch(n){E(n instanceof Error?n.message:"Network error"),o(!1)}}const a=(p||(b==null?void 0:b.reachable)===!0||R)&&r.name.trim().length>0,N=Y[r.type];return e.jsx("div",{className:u?"absolute inset-0 z-50 flex items-end bg-black/50 backdrop-blur-sm":"absolute inset-0 z-50 flex items-center justify-center bg-black/60 backdrop-blur-sm p-4",onClick:m,role:"dialog","aria-modal":"true","aria-label":p?"Edit provider":"Add provider",children:e.jsx(F,{className:u?"w-full max-h-[92%] overflow-y-auto bg-shell-surface shadow-2xl":"w-full max-w-md max-h-full overflow-y-auto bg-shell-surface shadow-2xl",style:u?{borderRadius:"20px 20px 0 0"}:void 0,onClick:s=>s.stopPropagation(),children:e.jsxs(U,{className:"p-5 space-y-4",children:[e.jsxs("div",{className:"flex items-center justify-between",children:[e.jsxs("div",{className:"flex items-center gap-2",children:[h!=="category"&&!p&&e.jsx("button",{onClick:c,className:"text-shell-text-tertiary hover:text-shell-text mr-1","aria-label":"Go back",children:"←"}),e.jsx(q,{size:16,className:"text-accent"}),e.jsx("h2",{className:"text-sm font-semibold",children:p?"Edit Provider":h==="category"?"Add Provider":h==="cloud-pick"?"Choose Cloud Provider":h==="cluster-info"?"Add Cluster Worker":"Configure Provider"})]}),e.jsx(g,{variant:"ghost",size:"icon",onClick:m,"aria-label":"Close form",className:"h-7 w-7",children:e.jsx(xe,{size:16})})]}),h==="category"&&e.jsx("div",{className:"grid grid-cols-3 gap-3",role:"group","aria-label":"Provider category",children:["local","cluster","cloud"].map(s=>{const l={local:{icon:"🖥️",label:"Local",desc:"On-device AI"},cluster:{icon:"🌐",label:"Cluster",desc:"Linked workers"},cloud:{icon:"☁️",label:"Cloud",desc:"Hosted APIs"}}[s];return e.jsxs("button",{onClick:()=>{w(s),s==="cloud"?k("cloud-pick"):s==="cluster"?k("cluster-info"):(f(C=>({...C,type:"rkllama",url:G.rkllama})),k("config"))},className:"flex flex-col items-center gap-1.5 rounded-xl border border-white/10 bg-white/5 p-4 hover:bg-white/10 hover:border-accent/40 transition-colors text-center","aria-label":`${l.label}: ${l.desc}`,children:[e.jsx("span",{className:"text-2xl","aria-hidden":"true",children:l.icon}),e.jsx("span",{className:"text-[12px] font-semibold text-shell-text",children:l.label}),e.jsx("span",{className:"text-[10px] text-shell-text-tertiary",children:l.desc})]},s)})}),h==="cloud-pick"&&e.jsx("div",{className:"grid grid-cols-2 gap-3",role:"group","aria-label":"Cloud provider",children:Object.entries(Y).map(([s,n])=>e.jsxs("button",{onClick:()=>B(s),className:"flex flex-col items-start gap-1 rounded-xl border border-white/10 bg-white/5 p-3.5 hover:bg-white/10 hover:border-accent/40 transition-colors text-left","aria-label":`${n.label}: ${n.description}`,children:[e.jsx("span",{className:"text-[13px] font-semibold text-shell-text",children:n.label}),e.jsx("span",{className:"text-[10px] text-shell-text-tertiary",children:n.description})]},s))}),h==="cluster-info"&&e.jsxs("div",{className:"space-y-3",children:[e.jsx("p",{className:"text-[12px] text-shell-text-secondary leading-relaxed",children:"Cluster workers auto-register when the taOS worker agent is installed and running on a remote machine. No manual entry needed — workers appear automatically in the Network section once connected."}),e.jsxs("div",{className:"rounded-lg bg-black/30 border border-white/10 p-3",children:[e.jsx("p",{className:"text-[10px] text-shell-text-tertiary mb-1.5 uppercase tracking-wide",children:"Install worker agent"}),e.jsx("code",{className:"text-[11px] text-shell-text font-mono block",children:"curl -fsSL https://get.tinyagentos.com/worker | bash"})]}),e.jsx("p",{className:"text-[10px] text-shell-text-tertiary",children:"Point the worker at this controller's address and it will appear here within a few seconds."}),e.jsx(g,{variant:"secondary",onClick:m,className:"w-full",children:"Close"})]}),h==="config"&&e.jsxs(e.Fragment,{children:[e.jsxs("div",{className:"space-y-1.5",children:[e.jsx(O,{htmlFor:"prov-name",children:"Name"}),e.jsx(D,{id:"prov-name",type:"text",value:r.name,onChange:s=>L("name",s.target.value),placeholder:N?N.label.toLowerCase():"my-provider",disabled:p,autoFocus:!p})]}),v==="cloud"&&N&&!p&&e.jsxs("div",{className:"space-y-1.5",children:[e.jsx(O,{children:"API Endpoint"}),e.jsxs("div",{className:"flex items-center gap-2 rounded-lg border border-white/10 bg-white/5 px-3 py-2",children:[e.jsx(ae,{size:11,className:"text-shell-text-tertiary shrink-0"}),e.jsx("code",{className:"text-[11px] text-shell-text-tertiary font-mono truncate",children:N.url})]})]}),v==="local"&&!p&&e.jsxs(e.Fragment,{children:[e.jsxs("div",{className:"space-y-1.5",children:[e.jsx(O,{htmlFor:"prov-type",children:"Type"}),e.jsx("select",{id:"prov-type",value:r.type,onChange:s=>S(s.target.value),className:"flex h-9 w-full rounded-lg border border-white/10 bg-shell-bg-deep px-3 py-1 text-sm text-shell-text focus-visible:outline-none focus-visible:border-accent/40 focus-visible:ring-2 focus-visible:ring-accent/20",children:pe.map(s=>e.jsx("option",{value:s,children:s},s))})]}),e.jsxs("div",{className:"space-y-1.5",children:[e.jsx(O,{htmlFor:"prov-url",children:"URL"}),e.jsx(D,{id:"prov-url",type:"url",value:r.url,onChange:s=>L("url",s.target.value),placeholder:"http://localhost:8080"})]})]}),p&&e.jsxs("div",{className:"space-y-1.5",children:[e.jsx(O,{htmlFor:"prov-url",children:"URL"}),e.jsx(D,{id:"prov-url",type:"url",value:r.url,onChange:s=>L("url",s.target.value),placeholder:"http://localhost:8080"})]}),K(r.type)&&e.jsxs("div",{className:"space-y-1.5",children:[e.jsxs(O,{htmlFor:"prov-apikey",children:["API Key",p&&" (leave blank to keep existing)"]}),e.jsx(D,{id:"prov-apikey",type:"password",value:r.apiKey,onChange:s=>L("apiKey",s.target.value),placeholder:p?"••••••••":(N==null?void 0:N.keyPlaceholder)??"sk-...",className:"font-mono"}),e.jsxs("p",{className:"text-[10px] text-shell-text-tertiary",children:["Saved as ",e.jsxs("code",{children:["provider-",r.name||"{name}","-key"]})]})]}),e.jsxs("div",{className:"space-y-1.5",children:[e.jsx(O,{htmlFor:"prov-priority",children:"Priority (lower wins)"}),e.jsx(D,{id:"prov-priority",type:"number",value:r.priority,onChange:s=>L("priority",s.target.value),placeholder:"99",min:0})]}),b&&e.jsx("div",{role:"status",className:`text-xs rounded-lg px-3 py-2 border ${b.reachable?"bg-emerald-500/10 border-emerald-500/20 text-emerald-300":"bg-red-500/10 border-red-500/20 text-red-300"}`,children:b.reachable?`Connected — ${b.response_ms??0} ms · ${((z=b.models)==null?void 0:z.length)??0} models found`:`Connection failed: ${b.error??"unknown error"}`}),_&&e.jsx("div",{role:"alert",className:"text-xs text-red-300 bg-red-500/10 border border-red-500/20 rounded px-2 py-1.5",children:_}),e.jsxs("div",{className:"flex items-center gap-2 pt-1 flex-wrap",children:[e.jsxs(g,{variant:"outline",size:"sm",onClick:y,disabled:T||!r.url.trim(),"aria-label":"Test provider connection",children:[e.jsx(W,{size:13,className:T?"animate-spin":""}),T?"Testing...":"Test connection"]}),e.jsx(g,{onClick:d,disabled:!a||P,"aria-label":p?"Update provider":"Save provider",children:P?"Saving...":p?"Update":"Save"}),e.jsx(g,{variant:"secondary",onClick:m,children:"Cancel"}),b&&!b.reachable&&!R&&e.jsx("button",{type:"button",onClick:()=>$(!0),className:"text-[11px] text-shell-text-tertiary underline hover:text-shell-text transition-colors ml-auto","aria-label":"Save anyway despite connection failure",children:"Save anyway"})]})]})]})})})}function ye({provider:t,onEdit:i,onDelete:m,onTestDone:u,onRefresh:p}){var a,N,z,s,n;const h=H(),[k,v]=x.useState(!1),[w,r]=x.useState(!1),[f,b]=x.useState(null),[j,T]=x.useState(!1),[A,P]=x.useState(t.keep_alive_minutes??10),o=t.lifecycle_state??"running",_=!((a=t.source)!=null&&a.startsWith("worker:")),E=o==="starting"||o==="draining"||o==="stopping",R=ne(l=>l.openWindow);function $(){const l=ie("secrets");l&&R("secrets",l.defaultSize)}async function L(l){try{await navigator.clipboard.writeText(l),v(!0),window.setTimeout(()=>v(!1),1200)}catch{}}async function S(){r(!0),b(null);try{const C=await(await fetch("/api/providers/test",{method:"POST",headers:{"Content-Type":"application/json",Accept:"application/json"},body:JSON.stringify({type:t.type,url:t.url})})).json();b(C),u(C)}catch(l){const C={reachable:!1,error:l instanceof Error?l.message:"Network error"};b(C),u(C)}r(!1)}async function B(){T(!0);try{await fetch(`/api/providers/${encodeURIComponent(t.name)}/start`,{method:"POST"}),p()}finally{T(!1)}}async function c(l){T(!0);try{await fetch(`/api/providers/${encodeURIComponent(t.name)}/stop`,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({force:l})}),p()}finally{T(!1)}}async function y(l){try{await fetch(`/api/providers/${encodeURIComponent(t.name)}`,{method:"PATCH",headers:{"Content-Type":"application/json"},body:JSON.stringify(l)})}catch{}p()}const d=t.models??[];return e.jsxs("div",{className:"flex flex-col h-full min-h-0 overflow-hidden",children:[!h&&e.jsxs("div",{className:"flex items-start justify-between gap-3 px-4 py-3 border-b border-white/5 shrink-0",children:[e.jsxs("div",{className:"min-w-0",children:[e.jsxs("div",{className:"flex items-center gap-2 flex-wrap",children:[e.jsx("h2",{className:"text-sm font-semibold text-shell-text truncate",children:t.name}),e.jsx(M,{type:t.type}),e.jsx(J,{status:t.status}),_&&t.lifecycle_state&&e.jsx(ue,{state:o}),e.jsxs("span",{className:"text-[10px] px-1.5 py-0.5 rounded bg-white/5 text-shell-text-tertiary",children:["priority ",t.priority]})]}),t.response_ms>0&&e.jsxs("p",{className:"text-[11px] text-shell-text-tertiary mt-0.5",children:[t.response_ms," ms"]})]}),e.jsxs("div",{className:"flex items-center gap-1 shrink-0",children:[_&&t.auto_manage&&o==="stopped"&&e.jsx(g,{size:"sm",variant:"outline",onClick:B,disabled:j,"aria-label":`Start provider ${t.name}`,children:j?"Starting…":"Start"}),_&&t.auto_manage&&o==="running"&&e.jsx(g,{size:"sm",variant:"outline",onClick:()=>c(!1),disabled:j,"aria-label":`Stop provider ${t.name}`,children:"Stop"}),_&&t.auto_manage&&E&&e.jsxs(e.Fragment,{children:[e.jsx("span",{className:"text-[11px] text-shell-text-tertiary px-2",children:re[o]}),e.jsx("button",{onClick:()=>c(!0),disabled:j,className:"text-[11px] text-red-400 hover:text-red-300 px-1","aria-label":`Force kill provider ${t.name}`,children:"Kill"})]}),e.jsxs(g,{size:"sm",variant:"outline",onClick:S,disabled:w,"aria-label":`Test connection for ${t.name}`,children:[e.jsx(W,{size:13,className:w?"animate-spin":""}),w?"Testing...":"Test"]}),(!_||o==="running"||!t.lifecycle_state)&&e.jsxs(e.Fragment,{children:[e.jsxs(g,{size:"sm",variant:"outline",onClick:i,"aria-label":`Edit provider ${t.name}`,children:[e.jsx(X,{size:13}),"Edit"]}),e.jsxs(g,{size:"sm",variant:"outline",onClick:m,className:"hover:bg-red-500/15 hover:text-red-300","aria-label":`Delete provider ${t.name}`,children:[e.jsx(Q,{size:13}),"Delete"]})]})]})]}),h&&e.jsxs("div",{className:"shrink-0 px-4 py-3 border-b border-white/5",children:[e.jsxs("div",{className:"flex items-center gap-2 flex-wrap mb-3",children:[e.jsx(M,{type:t.type}),e.jsx(J,{status:t.status}),e.jsxs("span",{className:"text-[11px] px-1.5 py-0.5 rounded bg-white/5 text-shell-text-tertiary",children:["priority ",t.priority]}),t.response_ms>0&&e.jsxs("span",{className:"text-[11px] text-shell-text-tertiary",children:[t.response_ms," ms"]})]}),e.jsxs("div",{className:"flex gap-2",children:[e.jsxs(g,{size:"sm",variant:"outline",onClick:S,disabled:w,className:"flex-1",children:[e.jsx(W,{size:13,className:w?"animate-spin":""}),w?"Testing...":"Test"]}),e.jsxs(g,{size:"sm",variant:"outline",onClick:i,className:"flex-1",children:[e.jsx(X,{size:13}),"Edit"]}),e.jsxs(g,{size:"sm",variant:"outline",onClick:m,className:"flex-1 hover:bg-red-500/15 hover:text-red-300",children:[e.jsx(Q,{size:13}),"Delete"]})]})]}),e.jsxs("div",{className:"flex-1 overflow-y-auto p-4 space-y-3",children:[f&&e.jsx("div",{role:"status",className:`text-xs rounded-lg px-3 py-2 border ${f.reachable?"bg-emerald-500/10 border-emerald-500/20 text-emerald-300":"bg-red-500/10 border-red-500/20 text-red-300"}`,children:f.reachable?`Connected — ${f.response_ms??0} ms · ${((N=f.models)==null?void 0:N.length)??0} models found`:o==="stopping"||o==="draining"?"Provider is shutting down. Wait for it to stop before testing.":o==="stopped"&&(t.auto_manage??!1)?"Starting service…":o==="stopped"?"Service is stopped. Start it manually or enable Auto manage.":(z=f.error)!=null&&z.includes("Cannot connect")||(s=f.error)!=null&&s.includes("Connection refused")||(n=f.error)!=null&&n.includes("connect")?`Cannot reach ${t.url}. Check the service is running.`:`Connection failed: ${f.error??"unknown error"}`}),e.jsx(F,{className:"p-3",children:e.jsxs(U,{className:"p-0",children:[e.jsx("div",{className:"flex items-center gap-2 mb-1",children:e.jsx("span",{className:"text-[10px] uppercase tracking-wide text-shell-text-tertiary",children:"Base URL"})}),e.jsxs("div",{className:"flex items-center gap-2",children:[e.jsx("code",{className:"text-xs text-shell-text flex-1 truncate font-mono",children:t.url}),e.jsx(g,{variant:"ghost",size:"icon",className:"h-6 w-6 shrink-0",onClick:()=>L(t.url),"aria-label":"Copy URL",children:k?e.jsx(ce,{size:12}):e.jsx(de,{size:12})})]})]})}),e.jsx(F,{className:"p-3",children:e.jsxs(U,{className:"p-0",children:[e.jsx("div",{className:"flex items-center gap-2 mb-1",children:e.jsx("span",{className:"text-[10px] uppercase tracking-wide text-shell-text-tertiary",children:"API Key"})}),t.api_key_secret?e.jsxs("div",{className:"flex items-center gap-2",children:[e.jsx("code",{className:"text-xs text-shell-text-secondary font-mono flex-1",children:t.api_key_secret}),e.jsxs(g,{variant:"ghost",size:"sm",onClick:$,className:"h-6 text-[10px] gap-1","aria-label":"Open Secrets app to manage this key",children:[e.jsx(ae,{size:10}),"Manage"]})]}):e.jsx("p",{className:"text-xs text-shell-text-tertiary italic",children:K(t.type)?"No key configured":"Not required — local backend"})]})}),K(t.type)&&e.jsx(F,{className:"p-3",children:e.jsx(U,{className:"p-0",children:e.jsxs("div",{className:"flex items-center justify-between",children:[e.jsxs("div",{children:[e.jsx("span",{className:"text-[12px] text-shell-text-secondary",children:"Enabled"}),!(t.enabled??!0)&&e.jsx("p",{className:"text-[11px] text-amber-400 mt-0.5",children:"Suspended — requests will be blocked"})]}),e.jsx("button",{role:"switch","aria-checked":t.enabled??!0,"aria-label":"Toggle provider enabled",onClick:()=>y({enabled:!(t.enabled??!0)}),className:`w-8 h-4 rounded-full transition-colors relative ${t.enabled??!0?"bg-emerald-500":"bg-zinc-600"}`,children:e.jsx("span",{className:`absolute top-0.5 w-3 h-3 rounded-full bg-white transition-transform ${t.enabled??!0?"translate-x-4":"translate-x-0.5"}`})})]})})}),e.jsx(F,{className:"p-3",children:e.jsxs(U,{className:"p-0",children:[e.jsx("div",{className:"flex items-center gap-2 mb-2",children:e.jsxs("span",{className:"text-[10px] uppercase tracking-wide text-shell-text-tertiary",children:["Models (",d.length,")"]})}),d.length===0?e.jsx("p",{className:"text-xs text-shell-text-tertiary italic",children:"No models loaded"}):e.jsx("div",{className:"flex flex-wrap gap-1",children:d.map((l,C)=>{const I=l.id??l.name??String(C);return e.jsx("span",{className:"text-[10px] px-2 py-0.5 rounded-full bg-violet-500/15 text-violet-200 font-medium",children:I},`m-${C}-${I}`)})})]})}),_&&!K(t.type)&&t.auto_manage!==void 0&&e.jsxs(F,{className:"p-0 overflow-hidden",children:[e.jsx("div",{className:"px-3 py-2 border-b border-white/5",children:e.jsx("span",{className:"text-[10px] font-medium text-shell-text-tertiary uppercase tracking-wider",children:"Lifecycle"})}),e.jsxs(U,{className:"p-3 space-y-3",children:[e.jsxs("div",{className:"flex items-center justify-between",children:[e.jsx("span",{className:"text-[12px] text-shell-text-secondary",children:"Enabled"}),e.jsx("button",{role:"switch","aria-checked":t.enabled??!0,"aria-label":"Toggle provider enabled",onClick:()=>y({enabled:!(t.enabled??!0)}),className:`w-8 h-4 rounded-full transition-colors relative ${t.enabled??!0?"bg-emerald-500":"bg-zinc-600"}`,children:e.jsx("span",{className:`absolute top-0.5 w-3 h-3 rounded-full bg-white transition-transform ${t.enabled??!0?"translate-x-4":"translate-x-0.5"}`})})]}),e.jsxs("div",{className:"flex items-center justify-between",children:[e.jsx("span",{className:"text-[12px] text-shell-text-secondary",children:"Auto manage"}),e.jsx("button",{role:"switch","aria-checked":t.auto_manage??!1,"aria-label":"Toggle auto manage",onClick:()=>y({auto_manage:!(t.auto_manage??!1)}),className:`w-8 h-4 rounded-full transition-colors relative ${t.auto_manage??!1?"bg-emerald-500":"bg-zinc-600"}`,children:e.jsx("span",{className:`absolute top-0.5 w-3 h-3 rounded-full bg-white transition-transform ${t.auto_manage??!1?"translate-x-4":"translate-x-0.5"}`})})]}),(t.auto_manage??!1)&&e.jsxs("div",{className:"flex items-center justify-between gap-3",children:[e.jsxs("div",{children:[e.jsx("span",{className:"text-[12px] text-shell-text-secondary",children:"Keep alive"}),e.jsx("p",{className:"text-[10px] text-shell-text-tertiary",children:(t.keep_alive_minutes??10)===0?"Always on":`Stop after ${t.keep_alive_minutes??10} min idle`})]}),e.jsx("input",{type:"number",min:0,max:60,value:A,onChange:l=>P(Number(l.target.value)),onBlur:l=>y({keep_alive_minutes:Number(l.target.value)}),className:"w-14 text-[12px] bg-white/5 border border-white/10 rounded px-2 py-1 text-right text-shell-text","aria-label":"Keep alive minutes (0 = always on)"})]})]})]})]})]})}function Le({windowId:t}){const i=H(),m=x.useRef(i);x.useEffect(()=>{m.current=i},[i]);const[u,p]=x.useState([]),[h,k]=x.useState(!0),[v,w]=x.useState(null),[r,f]=x.useState(!1),[b,j]=x.useState(null),[T,A]=x.useState(null),P=x.useCallback(c=>{A(c),window.setTimeout(()=>A(null),3e3)},[]),o=x.useCallback(async()=>{try{const c=await fetch("/api/providers",{headers:{Accept:"application/json"}});if(c.ok&&(c.headers.get("content-type")??"").includes("application/json")){const d=await c.json();Array.isArray(d)&&(p(d),w(a=>a&&d.some(N=>N.name===a)?a:m.current?null:d.length>0?d[0].name:null))}}catch{}k(!1)},[]);x.useEffect(()=>{o();const c=setInterval(o,3e4);return()=>clearInterval(c)},[o]);async function _(c){if(window.confirm(`Remove provider "${c}"?`))try{const y=await fetch(`/api/providers/${encodeURIComponent(c)}`,{method:"DELETE",headers:{Accept:"application/json"}});if(!y.ok){let d=`Delete failed (${y.status})`;try{const a=await y.json();a!=null&&a.error&&(d=String(a.error))}catch{}P(d);return}P(`Provider "${c}" removed`),w(null),o()}catch(y){P(y instanceof Error?y.message:"Network error")}}function E(){j(null),f(!0)}function R(c){j(c),f(!0)}function $(){f(!1),j(null),o()}function L(){f(!1),j(null)}const S=u.find(c=>c.name===v)??null,B=!i||v===null;return e.jsxs("div",{className:"flex flex-col h-full min-h-0 overflow-hidden bg-shell-bg text-shell-text select-none relative",children:[B&&e.jsxs("div",{className:"flex items-center justify-between px-4 py-3 border-b border-white/5 shrink-0",children:[e.jsxs("div",{className:"flex items-center gap-2 min-w-0",children:[e.jsx(q,{size:18,className:"text-accent shrink-0"}),e.jsx("h1",{className:"text-sm font-semibold",children:"Providers"}),e.jsxs("span",{className:"text-xs text-shell-text-tertiary",children:[u.length," configured"]})]}),e.jsxs("div",{className:"flex items-center gap-2",children:[e.jsx(g,{variant:"ghost",size:"icon",onClick:o,"aria-label":"Refresh provider list",children:e.jsx(W,{size:14})}),e.jsxs(g,{size:"sm",onClick:E,"aria-label":"Add provider",children:[e.jsx(V,{size:14}),i?"Add":"Add Provider"]})]})]}),e.jsx(oe,{selectedId:v,onBack:()=>w(null),listTitle:"Providers",detailTitle:S==null?void 0:S.name,list:e.jsx("div",{className:i?"py-2":"p-3 space-y-2","aria-label":"Provider list",children:h?e.jsx("div",{className:"text-[11px] text-shell-text-tertiary px-4 py-6 text-center",children:"Loading providers..."}):u.length===0?e.jsxs("div",{className:"flex flex-col items-center gap-2 py-10 text-center px-4",children:[e.jsx(q,{size:36,className:"opacity-20 text-shell-text-tertiary"}),e.jsx("p",{className:"text-[13px] text-shell-text-tertiary",children:"No providers configured yet."}),e.jsxs(g,{size:"sm",onClick:E,className:"mt-2",children:[e.jsx(V,{size:13}),"Add your first"]})]}):(()=>{const c=fe(u),y=he.filter(d=>c[d].length>0);return i?e.jsx("div",{style:{padding:"8px 0 16px"},children:y.map(d=>e.jsxs("div",{style:{marginBottom:20},children:[e.jsx("div",{style:{fontSize:12,textTransform:"uppercase",letterSpacing:.5,color:"rgba(255,255,255,0.45)",padding:"0 20px 6px",fontWeight:600},children:ee[d]}),e.jsx("div",{style:{margin:"0 12px",borderRadius:16,background:"rgba(255,255,255,0.05)",border:"1px solid rgba(255,255,255,0.08)",overflow:"hidden"},children:c[d].map((a,N,z)=>e.jsxs("button",{type:"button",onClick:()=>w(a.name),"aria-label":`Select provider ${a.name}`,style:{display:"flex",alignItems:"center",gap:10,width:"100%",padding:"14px 16px",background:"none",border:"none",borderBottom:N===z.length-1?"none":"1px solid rgba(255,255,255,0.06)",cursor:"pointer",color:"inherit",textAlign:"left"},children:[e.jsxs("div",{style:{flex:1,minWidth:0},children:[e.jsxs("div",{style:{fontSize:15,fontWeight:600,color:"rgba(255,255,255,0.95)",display:"flex",alignItems:"center",gap:8,marginBottom:4},children:[e.jsx("span",{style:{overflow:"hidden",textOverflow:"ellipsis",whiteSpace:"nowrap"},children:a.name}),e.jsx(J,{status:a.status})]}),e.jsxs("div",{className:"flex items-center gap-1.5 flex-wrap",children:[e.jsx(M,{type:a.type}),a.worker_name&&e.jsx(se,{name:a.worker_name,platform:a.worker_platform}),e.jsxs("span",{className:"text-[11px] text-shell-text-tertiary",children:["priority ",a.priority]}),a.models.length>0&&e.jsxs("span",{className:"text-[11px] text-shell-text-tertiary",children:["· ",a.models.length," model",a.models.length!==1?"s":""]})]})]}),e.jsx("svg",{width:"8",height:"14",viewBox:"0 0 8 14",fill:"none",style:{color:"rgba(255,255,255,0.3)",flexShrink:0},children:e.jsx("path",{d:"M1 1L7 7L1 13",stroke:"currentColor",strokeWidth:"2",strokeLinecap:"round",strokeLinejoin:"round"})})]},a.name))})]},d))}):y.map(d=>e.jsxs("div",{className:"mb-4",children:[e.jsx("div",{className:"text-[10px] uppercase tracking-wider text-shell-text-tertiary font-semibold px-1 mb-1.5",children:ee[d]}),e.jsx("div",{className:"space-y-1.5",children:c[d].map(a=>e.jsxs("button",{type:"button",onClick:()=>w(a.name),"aria-pressed":v===a.name,"aria-label":`Select provider ${a.name}`,className:`w-full text-left p-2.5 rounded-lg border transition-colors ${v===a.name?"border-accent/50 bg-accent/10":"border-white/5 bg-white/[0.02] hover:bg-white/[0.04]"}`,children:[e.jsxs("div",{className:"flex items-center justify-between gap-1.5 mb-1",children:[e.jsx("span",{className:"text-[12px] font-semibold text-shell-text truncate",children:a.name}),e.jsx(J,{status:a.status})]}),e.jsxs("div",{className:"flex items-center gap-1.5 flex-wrap",children:[e.jsx(M,{type:a.type}),a.worker_name&&e.jsx(se,{name:a.worker_name,platform:a.worker_platform}),e.jsxs("span",{className:"text-[10px] text-shell-text-tertiary",children:["#",a.priority]}),a.models.length>0&&e.jsxs("span",{className:"text-[10px] text-shell-text-tertiary",children:[a.models.length," model",a.models.length!==1?"s":""]})]})]},a.name))})]},d))})()}),detail:S?e.jsx(ye,{provider:S,onEdit:()=>R(S),onDelete:()=>_(S.name),onTestDone:()=>o(),onRefresh:o}):i?null:e.jsx("div",{className:"flex items-center justify-center h-full text-shell-text-tertiary text-sm",children:h?"Loading...":u.length===0?"Add a provider to get started":"Select a provider"})}),r&&e.jsx(be,{editing:b,onSave:$,onClose:L}),T&&e.jsx("div",{role:"status","aria-live":"polite",className:"absolute bottom-4 left-1/2 -translate-x-1/2 px-3 py-2 rounded-lg bg-shell-surface border border-white/10 text-xs text-shell-text shadow-2xl",children:T})]})}export{Le as ProvidersApp}; +import{r as x,j as e}from"./vendor-react-l6srOxy7.js";import{B as g,C as F,c as U,L as O,I as D}from"./toolbar-UW6q5pkx.js";import{a as ne,g as ie}from"./main-FOmUFQfu.js";import{M as oe}from"./MobileSplitView-B-4MQO2C.js";import{u as H}from"./use-is-mobile-v5lglusa.js";import{j as q,a9 as W,g as V,ax as X,y as Q,f as ce,aw as de,ay as ae,X as xe}from"./vendor-icons--yQaiqiL.js";import"./vendor-radix-BhM7AEEG.js";import"./vendor-layout-B-pp9n1f.js";import"./tokens-BKHlNYpw.js";import"./vendor-codemirror-aNcHammg.js";const le=["openai","anthropic","openrouter","kilocode"],pe=["rkllama","ollama","llama-cpp","vllm","exo","mlx"],G={openai:"https://api.openai.com/v1",anthropic:"https://api.anthropic.com/v1",openrouter:"https://openrouter.ai/api/v1",kilocode:"https://api.kilo.ai/api/gateway",ollama:"http://localhost:11434",rkllama:"http://localhost:8080","llama-cpp":"http://localhost:8080",vllm:"http://localhost:8000"},Y={openai:{label:"OpenAI",description:"GPT-4o, o1, and more",url:"https://api.openai.com/v1",keyPlaceholder:"sk-..."},anthropic:{label:"Anthropic",description:"Claude Sonnet, Opus, Haiku",url:"https://api.anthropic.com/v1",keyPlaceholder:"sk-ant-..."},openrouter:{label:"OpenRouter",description:"300+ models via one API",url:"https://openrouter.ai/api/v1",keyPlaceholder:"sk-or-..."},kilocode:{label:"Kilo",description:"500+ models, smart routing",url:"https://api.kilo.ai/api/gateway",keyPlaceholder:"kilo-..."}},Z={ok:"bg-emerald-500/20 text-emerald-400",online:"bg-emerald-500/20 text-emerald-400",slow:"bg-amber-500/20 text-amber-400",error:"bg-red-500/20 text-red-400",unknown:"bg-zinc-500/20 text-zinc-400"},me={ok:"Online",online:"Online",slow:"Slow",error:"Error",unknown:"Unknown"},ee={local:"Local / On Device",network:"Network / Cluster",cloud:"Cloud"},he=["local","network","cloud"];function K(t){return le.includes(t)}function M({type:t}){const i=K(t);return e.jsx("span",{className:`text-[10px] px-1.5 py-0.5 rounded font-medium ${i?"bg-violet-500/20 text-violet-300":"bg-teal-500/20 text-teal-300"}`,children:t})}function J({status:t}){const i=Z[t]??Z.unknown,m=me[t]??"Unknown";return e.jsx("span",{className:`text-[10px] px-1.5 py-0.5 rounded-full font-medium ${i}`,children:m})}const te={running:"bg-emerald-500/20 text-emerald-400",stopped:"bg-zinc-500/20 text-zinc-400",error:"bg-red-500/20 text-red-400",starting:"bg-blue-500/20 text-blue-400",draining:"bg-amber-500/20 text-amber-400",stopping:"bg-amber-500/20 text-amber-400"},re={running:"Running",stopped:"Stopped",error:"Error",starting:"Starting…",draining:"Draining…",stopping:"Stopping…"};function ue({state:t}){const i=te[t]??te.stopped,m=re[t]??t,u=t==="starting"||t==="draining"||t==="stopping";return e.jsxs("span",{className:`text-[10px] px-1.5 py-0.5 rounded-full font-medium inline-flex items-center gap-1 ${i}`,children:[u&&e.jsx("svg",{className:"animate-spin",width:"8",height:"8",viewBox:"0 0 8 8",fill:"none","aria-hidden":"true",children:e.jsx("circle",{cx:"4",cy:"4",r:"3",stroke:"currentColor",strokeWidth:"1.5",strokeDasharray:"10",strokeDashoffset:"5"})}),m]})}function se({name:t,platform:i}){const m=i?` · ${i}`:"";return e.jsxs("span",{className:"text-[10px] px-1.5 py-0.5 rounded-full font-medium bg-blue-500/20 text-blue-300 inline-flex items-center gap-1",title:`Backend on worker ${t}${m}`,children:[e.jsx("svg",{width:"8",height:"8",viewBox:"0 0 8 8",fill:"none",children:e.jsx("circle",{cx:"4",cy:"4",r:"3",stroke:"currentColor",strokeWidth:"1.5"})}),t]})}function fe(t){var m;const i={local:[],network:[],cloud:[]};for(const u of t){const p=u.category??((m=u.source)!=null&&m.startsWith("worker:")?"network":le.includes(u.type)?"cloud":"local");i[p].push(u)}return i}function ge(t){return t?{name:t.name,type:t.type,url:t.url,apiKey:"",priority:String(t.priority??99)}:{name:"",type:"openai",url:G.openai,apiKey:"",priority:"99"}}function be({editing:t,onSave:i,onClose:m}){var z;const u=H(),p=!!t,[h,k]=x.useState(p?"config":"category"),[v,w]=x.useState(null),[r,f]=x.useState(()=>ge(t)),[b,j]=x.useState(null),[T,A]=x.useState(!1),[P,o]=x.useState(!1),[_,E]=x.useState(null),[R,$]=x.useState(!1);function L(s,n){f(l=>({...l,[s]:n})),j(null),$(!1)}function S(s){f(n=>({...n,type:s,url:G[s]??n.url})),j(null),$(!1)}function B(s){const n=Y[s];n&&(f(l=>({...l,type:s,url:n.url,name:l.name||s})),j(null),$(!1),k("config"))}function c(){if(h==="config"&&v==="cloud"){k("cloud-pick");return}if(h==="config"&&v==="local"){k("category");return}if(h==="config"&&v==="cluster"){k("cluster-info");return}if(h==="config"&&v===null){m();return}if(h==="cloud-pick"){k("category");return}if(h==="cluster-info"){k("category");return}}async function y(){A(!0),j(null),E(null);try{const n=await(await fetch("/api/providers/test",{method:"POST",headers:{"Content-Type":"application/json",Accept:"application/json"},body:JSON.stringify({type:r.type,url:r.url})})).json();j(n)}catch(s){j({reachable:!1,error:s instanceof Error?s.message:"Network error"})}A(!1)}async function d(){if(!r.name.trim()){E("Name is required");return}o(!0),E(null);let s=t==null?void 0:t.api_key_secret;if(r.apiKey.trim()){const n=`provider-${r.name.trim()}-key`;try{await fetch("/api/secrets",{method:"POST",headers:{"Content-Type":"application/json",Accept:"application/json"},body:JSON.stringify({name:n,value:r.apiKey.trim(),category:"api-key",description:`API key for ${r.name.trim()} provider`,agents:[]})}),s=n}catch{}}try{const n={name:r.name.trim(),type:r.type,url:r.url.trim(),priority:parseInt(r.priority)||99};s&&(n.api_key_secret=s),p&&await fetch(`/api/providers/${encodeURIComponent(t.name)}`,{method:"DELETE",headers:{Accept:"application/json"}});const l=await fetch("/api/providers",{method:"POST",headers:{"Content-Type":"application/json",Accept:"application/json"},body:JSON.stringify(n)});if(!l.ok){let C=`Save failed (${l.status})`;try{const I=await l.json();I!=null&&I.error&&(C=String(I.error))}catch{}E(C),o(!1);return}i()}catch(n){E(n instanceof Error?n.message:"Network error"),o(!1)}}const a=(p||(b==null?void 0:b.reachable)===!0||R)&&r.name.trim().length>0,N=Y[r.type];return e.jsx("div",{className:u?"absolute inset-0 z-50 flex items-end bg-black/50 backdrop-blur-sm":"absolute inset-0 z-50 flex items-center justify-center bg-black/60 backdrop-blur-sm p-4",onClick:m,role:"dialog","aria-modal":"true","aria-label":p?"Edit provider":"Add provider",children:e.jsx(F,{className:u?"w-full max-h-[92%] overflow-y-auto bg-shell-surface shadow-2xl":"w-full max-w-md max-h-full overflow-y-auto bg-shell-surface shadow-2xl",style:u?{borderRadius:"20px 20px 0 0"}:void 0,onClick:s=>s.stopPropagation(),children:e.jsxs(U,{className:"p-5 space-y-4",children:[e.jsxs("div",{className:"flex items-center justify-between",children:[e.jsxs("div",{className:"flex items-center gap-2",children:[h!=="category"&&!p&&e.jsx("button",{onClick:c,className:"text-shell-text-tertiary hover:text-shell-text mr-1","aria-label":"Go back",children:"←"}),e.jsx(q,{size:16,className:"text-accent"}),e.jsx("h2",{className:"text-sm font-semibold",children:p?"Edit Provider":h==="category"?"Add Provider":h==="cloud-pick"?"Choose Cloud Provider":h==="cluster-info"?"Add Cluster Worker":"Configure Provider"})]}),e.jsx(g,{variant:"ghost",size:"icon",onClick:m,"aria-label":"Close form",className:"h-7 w-7",children:e.jsx(xe,{size:16})})]}),h==="category"&&e.jsx("div",{className:"grid grid-cols-3 gap-3",role:"group","aria-label":"Provider category",children:["local","cluster","cloud"].map(s=>{const l={local:{icon:"🖥️",label:"Local",desc:"On-device AI"},cluster:{icon:"🌐",label:"Cluster",desc:"Linked workers"},cloud:{icon:"☁️",label:"Cloud",desc:"Hosted APIs"}}[s];return e.jsxs("button",{onClick:()=>{w(s),s==="cloud"?k("cloud-pick"):s==="cluster"?k("cluster-info"):(f(C=>({...C,type:"rkllama",url:G.rkllama})),k("config"))},className:"flex flex-col items-center gap-1.5 rounded-xl border border-white/10 bg-white/5 p-4 hover:bg-white/10 hover:border-accent/40 transition-colors text-center","aria-label":`${l.label}: ${l.desc}`,children:[e.jsx("span",{className:"text-2xl","aria-hidden":"true",children:l.icon}),e.jsx("span",{className:"text-[12px] font-semibold text-shell-text",children:l.label}),e.jsx("span",{className:"text-[10px] text-shell-text-tertiary",children:l.desc})]},s)})}),h==="cloud-pick"&&e.jsx("div",{className:"grid grid-cols-2 gap-3",role:"group","aria-label":"Cloud provider",children:Object.entries(Y).map(([s,n])=>e.jsxs("button",{onClick:()=>B(s),className:"flex flex-col items-start gap-1 rounded-xl border border-white/10 bg-white/5 p-3.5 hover:bg-white/10 hover:border-accent/40 transition-colors text-left","aria-label":`${n.label}: ${n.description}`,children:[e.jsx("span",{className:"text-[13px] font-semibold text-shell-text",children:n.label}),e.jsx("span",{className:"text-[10px] text-shell-text-tertiary",children:n.description})]},s))}),h==="cluster-info"&&e.jsxs("div",{className:"space-y-3",children:[e.jsx("p",{className:"text-[12px] text-shell-text-secondary leading-relaxed",children:"Cluster workers auto-register when the taOS worker agent is installed and running on a remote machine. No manual entry needed — workers appear automatically in the Network section once connected."}),e.jsxs("div",{className:"rounded-lg bg-black/30 border border-white/10 p-3",children:[e.jsx("p",{className:"text-[10px] text-shell-text-tertiary mb-1.5 uppercase tracking-wide",children:"Install worker agent"}),e.jsx("code",{className:"text-[11px] text-shell-text font-mono block",children:"curl -fsSL https://get.tinyagentos.com/worker | bash"})]}),e.jsx("p",{className:"text-[10px] text-shell-text-tertiary",children:"Point the worker at this controller's address and it will appear here within a few seconds."}),e.jsx(g,{variant:"secondary",onClick:m,className:"w-full",children:"Close"})]}),h==="config"&&e.jsxs(e.Fragment,{children:[e.jsxs("div",{className:"space-y-1.5",children:[e.jsx(O,{htmlFor:"prov-name",children:"Name"}),e.jsx(D,{id:"prov-name",type:"text",value:r.name,onChange:s=>L("name",s.target.value),placeholder:N?N.label.toLowerCase():"my-provider",disabled:p,autoFocus:!p})]}),v==="cloud"&&N&&!p&&e.jsxs("div",{className:"space-y-1.5",children:[e.jsx(O,{children:"API Endpoint"}),e.jsxs("div",{className:"flex items-center gap-2 rounded-lg border border-white/10 bg-white/5 px-3 py-2",children:[e.jsx(ae,{size:11,className:"text-shell-text-tertiary shrink-0"}),e.jsx("code",{className:"text-[11px] text-shell-text-tertiary font-mono truncate",children:N.url})]})]}),v==="local"&&!p&&e.jsxs(e.Fragment,{children:[e.jsxs("div",{className:"space-y-1.5",children:[e.jsx(O,{htmlFor:"prov-type",children:"Type"}),e.jsx("select",{id:"prov-type",value:r.type,onChange:s=>S(s.target.value),className:"flex h-9 w-full rounded-lg border border-white/10 bg-shell-bg-deep px-3 py-1 text-sm text-shell-text focus-visible:outline-none focus-visible:border-accent/40 focus-visible:ring-2 focus-visible:ring-accent/20",children:pe.map(s=>e.jsx("option",{value:s,children:s},s))})]}),e.jsxs("div",{className:"space-y-1.5",children:[e.jsx(O,{htmlFor:"prov-url",children:"URL"}),e.jsx(D,{id:"prov-url",type:"url",value:r.url,onChange:s=>L("url",s.target.value),placeholder:"http://localhost:8080"})]})]}),p&&e.jsxs("div",{className:"space-y-1.5",children:[e.jsx(O,{htmlFor:"prov-url",children:"URL"}),e.jsx(D,{id:"prov-url",type:"url",value:r.url,onChange:s=>L("url",s.target.value),placeholder:"http://localhost:8080"})]}),K(r.type)&&e.jsxs("div",{className:"space-y-1.5",children:[e.jsxs(O,{htmlFor:"prov-apikey",children:["API Key",p&&" (leave blank to keep existing)"]}),e.jsx(D,{id:"prov-apikey",type:"password",value:r.apiKey,onChange:s=>L("apiKey",s.target.value),placeholder:p?"••••••••":(N==null?void 0:N.keyPlaceholder)??"sk-...",className:"font-mono"}),e.jsxs("p",{className:"text-[10px] text-shell-text-tertiary",children:["Saved as ",e.jsxs("code",{children:["provider-",r.name||"{name}","-key"]})]})]}),e.jsxs("div",{className:"space-y-1.5",children:[e.jsx(O,{htmlFor:"prov-priority",children:"Priority (lower wins)"}),e.jsx(D,{id:"prov-priority",type:"number",value:r.priority,onChange:s=>L("priority",s.target.value),placeholder:"99",min:0})]}),b&&e.jsx("div",{role:"status",className:`text-xs rounded-lg px-3 py-2 border ${b.reachable?"bg-emerald-500/10 border-emerald-500/20 text-emerald-300":"bg-red-500/10 border-red-500/20 text-red-300"}`,children:b.reachable?`Connected — ${b.response_ms??0} ms · ${((z=b.models)==null?void 0:z.length)??0} models found`:`Connection failed: ${b.error??"unknown error"}`}),_&&e.jsx("div",{role:"alert",className:"text-xs text-red-300 bg-red-500/10 border border-red-500/20 rounded px-2 py-1.5",children:_}),e.jsxs("div",{className:"flex items-center gap-2 pt-1 flex-wrap",children:[e.jsxs(g,{variant:"outline",size:"sm",onClick:y,disabled:T||!r.url.trim(),"aria-label":"Test provider connection",children:[e.jsx(W,{size:13,className:T?"animate-spin":""}),T?"Testing...":"Test connection"]}),e.jsx(g,{onClick:d,disabled:!a||P,"aria-label":p?"Update provider":"Save provider",children:P?"Saving...":p?"Update":"Save"}),e.jsx(g,{variant:"secondary",onClick:m,children:"Cancel"}),b&&!b.reachable&&!R&&e.jsx("button",{type:"button",onClick:()=>$(!0),className:"text-[11px] text-shell-text-tertiary underline hover:text-shell-text transition-colors ml-auto","aria-label":"Save anyway despite connection failure",children:"Save anyway"})]})]})]})})})}function ye({provider:t,onEdit:i,onDelete:m,onTestDone:u,onRefresh:p}){var a,N,z,s,n;const h=H(),[k,v]=x.useState(!1),[w,r]=x.useState(!1),[f,b]=x.useState(null),[j,T]=x.useState(!1),[A,P]=x.useState(t.keep_alive_minutes??10),o=t.lifecycle_state??"running",_=!((a=t.source)!=null&&a.startsWith("worker:")),E=o==="starting"||o==="draining"||o==="stopping",R=ne(l=>l.openWindow);function $(){const l=ie("secrets");l&&R("secrets",l.defaultSize)}async function L(l){try{await navigator.clipboard.writeText(l),v(!0),window.setTimeout(()=>v(!1),1200)}catch{}}async function S(){r(!0),b(null);try{const C=await(await fetch("/api/providers/test",{method:"POST",headers:{"Content-Type":"application/json",Accept:"application/json"},body:JSON.stringify({type:t.type,url:t.url})})).json();b(C),u(C)}catch(l){const C={reachable:!1,error:l instanceof Error?l.message:"Network error"};b(C),u(C)}r(!1)}async function B(){T(!0);try{await fetch(`/api/providers/${encodeURIComponent(t.name)}/start`,{method:"POST"}),p()}finally{T(!1)}}async function c(l){T(!0);try{await fetch(`/api/providers/${encodeURIComponent(t.name)}/stop`,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({force:l})}),p()}finally{T(!1)}}async function y(l){try{await fetch(`/api/providers/${encodeURIComponent(t.name)}`,{method:"PATCH",headers:{"Content-Type":"application/json"},body:JSON.stringify(l)})}catch{}p()}const d=t.models??[];return e.jsxs("div",{className:"flex flex-col h-full min-h-0 overflow-hidden",children:[!h&&e.jsxs("div",{className:"flex items-start justify-between gap-3 px-4 py-3 border-b border-white/5 shrink-0",children:[e.jsxs("div",{className:"min-w-0",children:[e.jsxs("div",{className:"flex items-center gap-2 flex-wrap",children:[e.jsx("h2",{className:"text-sm font-semibold text-shell-text truncate",children:t.name}),e.jsx(M,{type:t.type}),e.jsx(J,{status:t.status}),_&&t.lifecycle_state&&e.jsx(ue,{state:o}),e.jsxs("span",{className:"text-[10px] px-1.5 py-0.5 rounded bg-white/5 text-shell-text-tertiary",children:["priority ",t.priority]})]}),t.response_ms>0&&e.jsxs("p",{className:"text-[11px] text-shell-text-tertiary mt-0.5",children:[t.response_ms," ms"]})]}),e.jsxs("div",{className:"flex items-center gap-1 shrink-0",children:[_&&t.auto_manage&&o==="stopped"&&e.jsx(g,{size:"sm",variant:"outline",onClick:B,disabled:j,"aria-label":`Start provider ${t.name}`,children:j?"Starting…":"Start"}),_&&t.auto_manage&&o==="running"&&e.jsx(g,{size:"sm",variant:"outline",onClick:()=>c(!1),disabled:j,"aria-label":`Stop provider ${t.name}`,children:"Stop"}),_&&t.auto_manage&&E&&e.jsxs(e.Fragment,{children:[e.jsx("span",{className:"text-[11px] text-shell-text-tertiary px-2",children:re[o]}),e.jsx("button",{onClick:()=>c(!0),disabled:j,className:"text-[11px] text-red-400 hover:text-red-300 px-1","aria-label":`Force kill provider ${t.name}`,children:"Kill"})]}),e.jsxs(g,{size:"sm",variant:"outline",onClick:S,disabled:w,"aria-label":`Test connection for ${t.name}`,children:[e.jsx(W,{size:13,className:w?"animate-spin":""}),w?"Testing...":"Test"]}),(!_||o==="running"||!t.lifecycle_state)&&e.jsxs(e.Fragment,{children:[e.jsxs(g,{size:"sm",variant:"outline",onClick:i,"aria-label":`Edit provider ${t.name}`,children:[e.jsx(X,{size:13}),"Edit"]}),e.jsxs(g,{size:"sm",variant:"outline",onClick:m,className:"hover:bg-red-500/15 hover:text-red-300","aria-label":`Delete provider ${t.name}`,children:[e.jsx(Q,{size:13}),"Delete"]})]})]})]}),h&&e.jsxs("div",{className:"shrink-0 px-4 py-3 border-b border-white/5",children:[e.jsxs("div",{className:"flex items-center gap-2 flex-wrap mb-3",children:[e.jsx(M,{type:t.type}),e.jsx(J,{status:t.status}),e.jsxs("span",{className:"text-[11px] px-1.5 py-0.5 rounded bg-white/5 text-shell-text-tertiary",children:["priority ",t.priority]}),t.response_ms>0&&e.jsxs("span",{className:"text-[11px] text-shell-text-tertiary",children:[t.response_ms," ms"]})]}),e.jsxs("div",{className:"flex gap-2",children:[e.jsxs(g,{size:"sm",variant:"outline",onClick:S,disabled:w,className:"flex-1",children:[e.jsx(W,{size:13,className:w?"animate-spin":""}),w?"Testing...":"Test"]}),e.jsxs(g,{size:"sm",variant:"outline",onClick:i,className:"flex-1",children:[e.jsx(X,{size:13}),"Edit"]}),e.jsxs(g,{size:"sm",variant:"outline",onClick:m,className:"flex-1 hover:bg-red-500/15 hover:text-red-300",children:[e.jsx(Q,{size:13}),"Delete"]})]})]}),e.jsxs("div",{className:"flex-1 overflow-y-auto p-4 space-y-3",children:[f&&e.jsx("div",{role:"status",className:`text-xs rounded-lg px-3 py-2 border ${f.reachable?"bg-emerald-500/10 border-emerald-500/20 text-emerald-300":"bg-red-500/10 border-red-500/20 text-red-300"}`,children:f.reachable?`Connected — ${f.response_ms??0} ms · ${((N=f.models)==null?void 0:N.length)??0} models found`:o==="stopping"||o==="draining"?"Provider is shutting down. Wait for it to stop before testing.":o==="stopped"&&(t.auto_manage??!1)?"Starting service…":o==="stopped"?"Service is stopped. Start it manually or enable Auto manage.":(z=f.error)!=null&&z.includes("Cannot connect")||(s=f.error)!=null&&s.includes("Connection refused")||(n=f.error)!=null&&n.includes("connect")?`Cannot reach ${t.url}. Check the service is running.`:`Connection failed: ${f.error??"unknown error"}`}),e.jsx(F,{className:"p-3",children:e.jsxs(U,{className:"p-0",children:[e.jsx("div",{className:"flex items-center gap-2 mb-1",children:e.jsx("span",{className:"text-[10px] uppercase tracking-wide text-shell-text-tertiary",children:"Base URL"})}),e.jsxs("div",{className:"flex items-center gap-2",children:[e.jsx("code",{className:"text-xs text-shell-text flex-1 truncate font-mono",children:t.url}),e.jsx(g,{variant:"ghost",size:"icon",className:"h-6 w-6 shrink-0",onClick:()=>L(t.url),"aria-label":"Copy URL",children:k?e.jsx(ce,{size:12}):e.jsx(de,{size:12})})]})]})}),e.jsx(F,{className:"p-3",children:e.jsxs(U,{className:"p-0",children:[e.jsx("div",{className:"flex items-center gap-2 mb-1",children:e.jsx("span",{className:"text-[10px] uppercase tracking-wide text-shell-text-tertiary",children:"API Key"})}),t.api_key_secret?e.jsxs("div",{className:"flex items-center gap-2",children:[e.jsx("code",{className:"text-xs text-shell-text-secondary font-mono flex-1",children:t.api_key_secret}),e.jsxs(g,{variant:"ghost",size:"sm",onClick:$,className:"h-6 text-[10px] gap-1","aria-label":"Open Secrets app to manage this key",children:[e.jsx(ae,{size:10}),"Manage"]})]}):e.jsx("p",{className:"text-xs text-shell-text-tertiary italic",children:K(t.type)?"No key configured":"Not required — local backend"})]})}),K(t.type)&&e.jsx(F,{className:"p-3",children:e.jsx(U,{className:"p-0",children:e.jsxs("div",{className:"flex items-center justify-between",children:[e.jsxs("div",{children:[e.jsx("span",{className:"text-[12px] text-shell-text-secondary",children:"Enabled"}),!(t.enabled??!0)&&e.jsx("p",{className:"text-[11px] text-amber-400 mt-0.5",children:"Suspended — requests will be blocked"})]}),e.jsx("button",{role:"switch","aria-checked":t.enabled??!0,"aria-label":"Toggle provider enabled",onClick:()=>y({enabled:!(t.enabled??!0)}),className:`w-8 h-4 rounded-full transition-colors relative ${t.enabled??!0?"bg-emerald-500":"bg-zinc-600"}`,children:e.jsx("span",{className:`absolute top-0.5 w-3 h-3 rounded-full bg-white transition-transform ${t.enabled??!0?"translate-x-4":"translate-x-0.5"}`})})]})})}),e.jsx(F,{className:"p-3",children:e.jsxs(U,{className:"p-0",children:[e.jsx("div",{className:"flex items-center gap-2 mb-2",children:e.jsxs("span",{className:"text-[10px] uppercase tracking-wide text-shell-text-tertiary",children:["Models (",d.length,")"]})}),d.length===0?e.jsx("p",{className:"text-xs text-shell-text-tertiary italic",children:"No models loaded"}):e.jsx("div",{className:"flex flex-wrap gap-1",children:d.map((l,C)=>{const I=l.id??l.name??String(C);return e.jsx("span",{className:"text-[10px] px-2 py-0.5 rounded-full bg-violet-500/15 text-violet-200 font-medium",children:I},`m-${C}-${I}`)})})]})}),_&&!K(t.type)&&t.auto_manage!==void 0&&e.jsxs(F,{className:"p-0 overflow-hidden",children:[e.jsx("div",{className:"px-3 py-2 border-b border-white/5",children:e.jsx("span",{className:"text-[10px] font-medium text-shell-text-tertiary uppercase tracking-wider",children:"Lifecycle"})}),e.jsxs(U,{className:"p-3 space-y-3",children:[e.jsxs("div",{className:"flex items-center justify-between",children:[e.jsx("span",{className:"text-[12px] text-shell-text-secondary",children:"Enabled"}),e.jsx("button",{role:"switch","aria-checked":t.enabled??!0,"aria-label":"Toggle provider enabled",onClick:()=>y({enabled:!(t.enabled??!0)}),className:`w-8 h-4 rounded-full transition-colors relative ${t.enabled??!0?"bg-emerald-500":"bg-zinc-600"}`,children:e.jsx("span",{className:`absolute top-0.5 w-3 h-3 rounded-full bg-white transition-transform ${t.enabled??!0?"translate-x-4":"translate-x-0.5"}`})})]}),e.jsxs("div",{className:"flex items-center justify-between",children:[e.jsx("span",{className:"text-[12px] text-shell-text-secondary",children:"Auto manage"}),e.jsx("button",{role:"switch","aria-checked":t.auto_manage??!1,"aria-label":"Toggle auto manage",onClick:()=>y({auto_manage:!(t.auto_manage??!1)}),className:`w-8 h-4 rounded-full transition-colors relative ${t.auto_manage??!1?"bg-emerald-500":"bg-zinc-600"}`,children:e.jsx("span",{className:`absolute top-0.5 w-3 h-3 rounded-full bg-white transition-transform ${t.auto_manage??!1?"translate-x-4":"translate-x-0.5"}`})})]}),(t.auto_manage??!1)&&e.jsxs("div",{className:"flex items-center justify-between gap-3",children:[e.jsxs("div",{children:[e.jsx("span",{className:"text-[12px] text-shell-text-secondary",children:"Keep alive"}),e.jsx("p",{className:"text-[10px] text-shell-text-tertiary",children:(t.keep_alive_minutes??10)===0?"Always on":`Stop after ${t.keep_alive_minutes??10} min idle`})]}),e.jsx("input",{type:"number",min:0,max:60,value:A,onChange:l=>P(Number(l.target.value)),onBlur:l=>y({keep_alive_minutes:Number(l.target.value)}),className:"w-14 text-[12px] bg-white/5 border border-white/10 rounded px-2 py-1 text-right text-shell-text","aria-label":"Keep alive minutes (0 = always on)"})]})]})]})]})]})}function Le({windowId:t}){const i=H(),m=x.useRef(i);x.useEffect(()=>{m.current=i},[i]);const[u,p]=x.useState([]),[h,k]=x.useState(!0),[v,w]=x.useState(null),[r,f]=x.useState(!1),[b,j]=x.useState(null),[T,A]=x.useState(null),P=x.useCallback(c=>{A(c),window.setTimeout(()=>A(null),3e3)},[]),o=x.useCallback(async()=>{try{const c=await fetch("/api/providers",{headers:{Accept:"application/json"}});if(c.ok&&(c.headers.get("content-type")??"").includes("application/json")){const d=await c.json();Array.isArray(d)&&(p(d),w(a=>a&&d.some(N=>N.name===a)?a:m.current?null:d.length>0?d[0].name:null))}}catch{}k(!1)},[]);x.useEffect(()=>{o();const c=setInterval(o,3e4);return()=>clearInterval(c)},[o]);async function _(c){if(window.confirm(`Remove provider "${c}"?`))try{const y=await fetch(`/api/providers/${encodeURIComponent(c)}`,{method:"DELETE",headers:{Accept:"application/json"}});if(!y.ok){let d=`Delete failed (${y.status})`;try{const a=await y.json();a!=null&&a.error&&(d=String(a.error))}catch{}P(d);return}P(`Provider "${c}" removed`),w(null),o()}catch(y){P(y instanceof Error?y.message:"Network error")}}function E(){j(null),f(!0)}function R(c){j(c),f(!0)}function $(){f(!1),j(null),o()}function L(){f(!1),j(null)}const S=u.find(c=>c.name===v)??null,B=!i||v===null;return e.jsxs("div",{className:"flex flex-col h-full min-h-0 overflow-hidden bg-shell-bg text-shell-text select-none relative",children:[B&&e.jsxs("div",{className:"flex items-center justify-between px-4 py-3 border-b border-white/5 shrink-0",children:[e.jsxs("div",{className:"flex items-center gap-2 min-w-0",children:[e.jsx(q,{size:18,className:"text-accent shrink-0"}),e.jsx("h1",{className:"text-sm font-semibold",children:"Providers"}),e.jsxs("span",{className:"text-xs text-shell-text-tertiary",children:[u.length," configured"]})]}),e.jsxs("div",{className:"flex items-center gap-2",children:[e.jsx(g,{variant:"ghost",size:"icon",onClick:o,"aria-label":"Refresh provider list",children:e.jsx(W,{size:14})}),e.jsxs(g,{size:"sm",onClick:E,"aria-label":"Add provider",children:[e.jsx(V,{size:14}),i?"Add":"Add Provider"]})]})]}),e.jsx(oe,{selectedId:v,onBack:()=>w(null),listTitle:"Providers",detailTitle:S==null?void 0:S.name,list:e.jsx("div",{className:i?"py-2":"p-3 space-y-2","aria-label":"Provider list",children:h?e.jsx("div",{className:"text-[11px] text-shell-text-tertiary px-4 py-6 text-center",children:"Loading providers..."}):u.length===0?e.jsxs("div",{className:"flex flex-col items-center gap-2 py-10 text-center px-4",children:[e.jsx(q,{size:36,className:"opacity-20 text-shell-text-tertiary"}),e.jsx("p",{className:"text-[13px] text-shell-text-tertiary",children:"No providers configured yet."}),e.jsxs(g,{size:"sm",onClick:E,className:"mt-2",children:[e.jsx(V,{size:13}),"Add your first"]})]}):(()=>{const c=fe(u),y=he.filter(d=>c[d].length>0);return i?e.jsx("div",{style:{padding:"8px 0 16px"},children:y.map(d=>e.jsxs("div",{style:{marginBottom:20},children:[e.jsx("div",{style:{fontSize:12,textTransform:"uppercase",letterSpacing:.5,color:"rgba(255,255,255,0.45)",padding:"0 20px 6px",fontWeight:600},children:ee[d]}),e.jsx("div",{style:{margin:"0 12px",borderRadius:16,background:"rgba(255,255,255,0.05)",border:"1px solid rgba(255,255,255,0.08)",overflow:"hidden"},children:c[d].map((a,N,z)=>e.jsxs("button",{type:"button",onClick:()=>w(a.name),"aria-label":`Select provider ${a.name}`,style:{display:"flex",alignItems:"center",gap:10,width:"100%",padding:"14px 16px",background:"none",border:"none",borderBottom:N===z.length-1?"none":"1px solid rgba(255,255,255,0.06)",cursor:"pointer",color:"inherit",textAlign:"left"},children:[e.jsxs("div",{style:{flex:1,minWidth:0},children:[e.jsxs("div",{style:{fontSize:15,fontWeight:600,color:"rgba(255,255,255,0.95)",display:"flex",alignItems:"center",gap:8,marginBottom:4},children:[e.jsx("span",{style:{overflow:"hidden",textOverflow:"ellipsis",whiteSpace:"nowrap"},children:a.name}),e.jsx(J,{status:a.status})]}),e.jsxs("div",{className:"flex items-center gap-1.5 flex-wrap",children:[e.jsx(M,{type:a.type}),a.worker_name&&e.jsx(se,{name:a.worker_name,platform:a.worker_platform}),e.jsxs("span",{className:"text-[11px] text-shell-text-tertiary",children:["priority ",a.priority]}),a.models.length>0&&e.jsxs("span",{className:"text-[11px] text-shell-text-tertiary",children:["· ",a.models.length," model",a.models.length!==1?"s":""]})]})]}),e.jsx("svg",{width:"8",height:"14",viewBox:"0 0 8 14",fill:"none",style:{color:"rgba(255,255,255,0.3)",flexShrink:0},children:e.jsx("path",{d:"M1 1L7 7L1 13",stroke:"currentColor",strokeWidth:"2",strokeLinecap:"round",strokeLinejoin:"round"})})]},a.name))})]},d))}):y.map(d=>e.jsxs("div",{className:"mb-4",children:[e.jsx("div",{className:"text-[10px] uppercase tracking-wider text-shell-text-tertiary font-semibold px-1 mb-1.5",children:ee[d]}),e.jsx("div",{className:"space-y-1.5",children:c[d].map(a=>e.jsxs("button",{type:"button",onClick:()=>w(a.name),"aria-pressed":v===a.name,"aria-label":`Select provider ${a.name}`,className:`w-full text-left p-2.5 rounded-lg border transition-colors ${v===a.name?"border-accent/50 bg-accent/10":"border-white/5 bg-white/[0.02] hover:bg-white/[0.04]"}`,children:[e.jsxs("div",{className:"flex items-center justify-between gap-1.5 mb-1",children:[e.jsx("span",{className:"text-[12px] font-semibold text-shell-text truncate",children:a.name}),e.jsx(J,{status:a.status})]}),e.jsxs("div",{className:"flex items-center gap-1.5 flex-wrap",children:[e.jsx(M,{type:a.type}),a.worker_name&&e.jsx(se,{name:a.worker_name,platform:a.worker_platform}),e.jsxs("span",{className:"text-[10px] text-shell-text-tertiary",children:["#",a.priority]}),a.models.length>0&&e.jsxs("span",{className:"text-[10px] text-shell-text-tertiary",children:[a.models.length," model",a.models.length!==1?"s":""]})]})]},a.name))})]},d))})()}),detail:S?e.jsx(ye,{provider:S,onEdit:()=>R(S),onDelete:()=>_(S.name),onTestDone:()=>o(),onRefresh:o}):i?null:e.jsx("div",{className:"flex items-center justify-center h-full text-shell-text-tertiary text-sm",children:h?"Loading...":u.length===0?"Add a provider to get started":"Select a provider"})}),r&&e.jsx(be,{editing:b,onSave:$,onClose:L}),T&&e.jsx("div",{role:"status","aria-live":"polite",className:"absolute bottom-4 left-1/2 -translate-x-1/2 px-3 py-2 rounded-lg bg-shell-surface border border-white/10 text-xs text-shell-text shadow-2xl",children:T})]})}export{Le as ProvidersApp}; diff --git a/static/desktop/assets/SettingsApp-3EqaoTva.js b/static/desktop/assets/SettingsApp-CR8h0q_c.js similarity index 99% rename from static/desktop/assets/SettingsApp-3EqaoTva.js rename to static/desktop/assets/SettingsApp-CR8h0q_c.js index 9adc1e29..ae390236 100644 --- a/static/desktop/assets/SettingsApp-3EqaoTva.js +++ b/static/desktop/assets/SettingsApp-CR8h0q_c.js @@ -1,4 +1,4 @@ -import{r as s,j as e}from"./vendor-react-l6srOxy7.js";import{B as b,C as w,L as N,I as E,S as T,T as Z}from"./toolbar-UW6q5pkx.js";import{u as ee}from"./main-w-WDDs5-.js";import{t as te,a0 as se,an as ae,ak as K,a9 as P,as as V,at as le,au as ne,l as re,U as ce,$ as ie,r as F,f as D,av as Y,g as oe,y as de,c as xe,ab as me,aw as ue,X as he}from"./vendor-icons--yQaiqiL.js";import"./vendor-radix-BhM7AEEG.js";import"./vendor-layout-B-pp9n1f.js";import"./tokens-BKHlNYpw.js";import"./vendor-codemirror-aNcHammg.js";function pe(r,l,t=a=>a,x=a=>({value:a})){const a=`taos-pref:${r}`,[d,i]=s.useState(()=>{try{const p=localStorage.getItem(a);if(p!==null)return JSON.parse(p)}catch{}return l}),[n,c]=s.useState(!1),m=s.useRef(null);s.useEffect(()=>{let p=!1;return(async()=>{try{const o=await fetch(`/api/preferences/${encodeURIComponent(r)}`);if(!o.ok){c(!0);return}const j=await o.json();if(p)return;if(j&&typeof j=="object"&&Object.keys(j).length>0){const v=t(j);i(v);try{localStorage.setItem(a,JSON.stringify(v))}catch{}}c(!0)}catch{c(!0)}})(),()=>{p=!0}},[r]);const h=s.useCallback(p=>{i(o=>{const j=typeof p=="function"?p(o):p;try{localStorage.setItem(a,JSON.stringify(j))}catch{}return m.current!==null&&clearTimeout(m.current),m.current=setTimeout(()=>{m.current=null,fetch(`/api/preferences/${encodeURIComponent(r)}`,{method:"PUT",headers:{"Content-Type":"application/json"},body:JSON.stringify(x(j))}).catch(()=>{})},500),j})},[a,x,r]);return[d,h,{loaded:n}]}const fe=[{id:"system",label:"System Info",icon:te},{id:"storage",label:"Storage",icon:se},{id:"memory",label:"Memory",icon:ae},{id:"backup",label:"Backup & Restore",icon:K},{id:"updates",label:"Updates",icon:P},{id:"advanced",label:"Advanced",icon:V},{id:"shortcuts",label:"Keyboard Shortcuts",icon:le},{id:"accessibility",label:"Accessibility",icon:ne},{id:"desktop",label:"Desktop & Dock",icon:re},{id:"users",label:"Users",icon:ce}],je={cpu:"Detecting...",ram:"Detecting...",npu:"Detecting...",gpu:"Detecting...",disk:"Detecting...",os:"Detecting..."},ye=[{label:"Models",size:"--",bytes:0,maxBytes:1},{label:"Data",size:"--",bytes:0,maxBytes:1},{label:"App Catalog",size:"--",bytes:0,maxBytes:1}];async function G(r,l){try{const t=await fetch(r,{headers:{Accept:"application/json"}});return!t.ok||!(t.headers.get("content-type")??"").includes("application/json")?l:await t.json()}catch{return l}}function be({value:r,max:l}){const t=l>0?Math.min(100,r/l*100):0;return e.jsx("div",{className:"h-2 w-full rounded-full bg-white/5",role:"progressbar","aria-valuenow":t,"aria-valuemin":0,"aria-valuemax":100,children:e.jsx("div",{className:"h-full rounded-full bg-sky-500 transition-all",style:{width:`${t}%`}})})}function ge(){const[r,l]=s.useState(je),[t,x]=s.useState(!1),[a,d]=s.useState(!1),i=s.useCallback(async()=>{var m,h,p,o,j,v,k,S,g,R,_,I,y;x(!0);const c=await G("/api/system",null);if(c!=null&&c.hardware||c!=null&&c.resources){const u=c.hardware??{},U=c.resources??{},C=U.ram_total_mb??u.ram_mb??0,$=U.disk_total_gb??((m=u.disk)==null?void 0:m.total_gb)??0,A=((h=u.cpu)==null?void 0:h.model)??((p=u.cpu)==null?void 0:p.soc)??"Unknown",B=(o=u.cpu)!=null&&o.cores?` × ${u.cpu.cores}`:"",L=(j=u.cpu)!=null&&j.arch?` (${u.cpu.arch})`:"",f=((v=u.gpu)==null?void 0:v.model)||((k=u.gpu)==null?void 0:k.type)||"None",z=(S=u.gpu)!=null&&S.vram_mb&&u.gpu.vram_mb>0?` (${(u.gpu.vram_mb/1024).toFixed(1)} GB)`:"",M=(g=u.npu)!=null&&g.type&&u.npu.type!=="none"?u.npu.type:"None",q=(R=u.npu)!=null&&R.tops&&u.npu.tops>0?` · ${u.npu.tops} TOPS`:"",X=(_=u.disk)!=null&&_.type?` ${u.disk.type}`:"",J=[(I=u.os)==null?void 0:I.distro,(y=u.os)==null?void 0:y.version].filter(Boolean),Q=J.length>0?J.join(" "):"—";l({cpu:`${A}${B}${L}`,ram:C>=1024?`${(C/1024).toFixed(1)} GB`:C>0?`${C} MB`:"—",npu:`${M}${q}`,gpu:`${f}${z}`,disk:$>0?`${$} GB${X}`:"—",os:Q})}else l({cpu:"Unavailable",ram:"Unavailable",npu:"Unavailable",gpu:"Unavailable",disk:"Unavailable",os:"Unavailable"});x(!1)},[]);s.useEffect(()=>{i()},[i]);const n=[["CPU",r.cpu],["RAM",r.ram],["NPU",r.npu],["GPU",r.gpu],["Disk",r.disk],["OS",r.os]];return e.jsxs("section",{"aria-label":"System information",children:[e.jsx("h2",{className:"text-lg font-semibold mb-5",children:"System Information"}),e.jsx("div",{className:"rounded-2xl bg-white/[0.04] border border-white/[0.06] overflow-x-auto backdrop-blur-sm",children:e.jsx("table",{className:"w-full text-sm min-w-[360px]",children:e.jsx("tbody",{children:n.map(([c,m])=>e.jsxs("tr",{className:"border-b border-white/5 last:border-0",children:[e.jsx("td",{className:"px-5 py-3 text-shell-text-secondary font-medium w-32",children:c}),e.jsx("td",{className:"px-5 py-3",children:m})]},c))})})}),e.jsxs("div",{className:"mt-3 flex items-center gap-2 flex-wrap",children:[e.jsxs(b,{variant:"outline",size:"sm",onClick:i,disabled:t,children:[e.jsx(P,{size:14,className:t?"animate-spin":""}),"Re-detect Hardware"]}),e.jsxs(b,{variant:"outline",size:"sm",onClick:async()=>{d(!0);try{await fetch("/api/system/restart/prepare",{method:"POST"})}catch{}},"aria-label":"Restart taOS server",children:[e.jsx(P,{size:14}),"Restart Server"]})]}),e.jsx("p",{className:"mt-2 text-xs text-shell-text-tertiary",children:"Restart the server to apply settings changes that require a reload."}),a&&e.jsx(W,{onClose:()=>d(!1)})]})}function Ne(){const[r,l]=s.useState(ye);return s.useEffect(()=>{G("/api/settings/storage",null).then(t=>{t&&Array.isArray(t)?l(t):l([{label:"Models",size:"4.2 GB",bytes:4200,maxBytes:32e3},{label:"Data",size:"1.8 GB",bytes:1800,maxBytes:32e3},{label:"App Catalog",size:"320 MB",bytes:320,maxBytes:32e3}])})},[]),e.jsxs("section",{"aria-label":"Storage usage",children:[e.jsx("h2",{className:"text-lg font-semibold mb-5",children:"Storage Usage"}),e.jsx("div",{className:"space-y-3",children:r.map(t=>e.jsxs(w,{className:"p-4",children:[e.jsxs("div",{className:"flex items-center justify-between mb-2",children:[e.jsx("span",{className:"text-sm font-medium",children:t.label}),e.jsx("span",{className:"text-sm text-shell-text-secondary tabular-nums",children:t.size})]}),e.jsx(be,{value:t.bytes,max:t.maxBytes})]},t.label))})]})}const ve=[{key:"capture_conversations",label:"Conversations",desc:"Messages you send to agents in the Message Hub"},{key:"capture_notes",label:"Notes",desc:"Notes from the Text Editor app"},{key:"capture_files",label:"File activity",desc:"Files you upload or open"},{key:"capture_searches",label:"Search queries",desc:"What you search for in global search"}];function we(){const[r,l]=s.useState(null),[t,x]=s.useState(null),[a,d]=s.useState(null);s.useEffect(()=>{fetch("/api/user-memory/settings").then(n=>n.ok?n.json():null).then(n=>{l(n||{})}).catch(()=>{l({}),d("Could not load memory settings.")}),fetch("/api/user-memory/stats").then(n=>n.ok?n.json():null).then(n=>{n&&x(n)}).catch(()=>{})},[]);const i=(n,c)=>{const m={...r||{},[n]:c};l(m),fetch("/api/user-memory/settings",{method:"PUT",headers:{"Content-Type":"application/json"},body:JSON.stringify({[n]:c})}).then(h=>{h.ok?d(null):d(`Failed to save setting (${h.status})`)}).catch(()=>d("Could not reach backend."))};return r?e.jsxs("section",{"aria-label":"Memory capture settings",children:[e.jsx("h2",{className:"text-lg font-semibold mb-2",children:"Memory Capture"}),e.jsx("p",{className:"text-sm text-shell-text-tertiary mb-5",children:"Choose what activity gets saved to your personal memory index. All data stays on this device."}),a&&e.jsxs("p",{className:"mb-3 text-xs text-amber-400 flex items-center gap-1.5",children:[e.jsx(F,{size:12})," ",a]}),e.jsx("div",{className:"space-y-2",children:ve.map(n=>{const c=!!r[n.key],m=`capture-${String(n.key)}`;return e.jsxs(w,{className:"p-4 flex items-center justify-between gap-3",children:[e.jsxs("div",{className:"flex-1 min-w-0",children:[e.jsx(N,{htmlFor:m,className:"text-sm font-medium text-shell-text",children:n.label}),e.jsx("p",{className:"text-xs text-shell-text-tertiary mt-0.5",children:n.desc})]}),e.jsx(T,{id:m,checked:c,onCheckedChange:h=>i(n.key,h),"aria-label":`Capture ${n.label}`})]},String(n.key))})}),t&&e.jsxs(w,{className:"mt-6 p-4",children:[e.jsx("h3",{className:"text-sm font-medium mb-3",children:"Stored chunks"}),e.jsxs("div",{className:"text-xs text-shell-text-secondary mb-2 tabular-nums",children:["Total: ",t.total]}),Object.keys(t.collections||{}).length>0?e.jsx("ul",{className:"space-y-1 text-xs text-shell-text-tertiary",children:Object.entries(t.collections).map(([n,c])=>e.jsxs("li",{className:"flex justify-between tabular-nums",children:[e.jsx("span",{children:n}),e.jsx("span",{children:c})]},n))}):e.jsx("p",{className:"text-xs text-shell-text-tertiary",children:"No memories captured yet."})]})]}):e.jsxs("section",{"aria-label":"Memory capture settings",children:[e.jsx("h2",{className:"text-lg font-semibold mb-5",children:"Memory Capture"}),e.jsx("p",{className:"text-sm text-shell-text-tertiary",children:"Loading..."})]})}function ke(){const[r,l]=s.useState(null),[t,x]=s.useState(!1),a=async()=>{x(!0),l(null);try{const d=await fetch("/api/backup",{method:"POST"});d.ok?l("Backup created successfully."):l(`Backup failed (${d.status}). API may not be available yet.`)}catch{l("Could not reach backup endpoint. API not available yet.")}x(!1)};return e.jsxs("section",{"aria-label":"Backup and restore",children:[e.jsx("h2",{className:"text-lg font-semibold mb-5",children:"Backup & Restore"}),e.jsxs(w,{className:"p-4 space-y-4",children:[e.jsxs("div",{children:[e.jsx("h3",{className:"text-sm font-medium mb-2",children:"Create Backup"}),e.jsx("p",{className:"text-xs text-shell-text-tertiary mb-3",children:"Export all agents, memory, and configuration as a backup archive."}),e.jsxs(b,{size:"sm",onClick:a,disabled:t,children:[e.jsx(K,{size:14,className:t?"animate-bounce":""}),t?"Creating...":"Create Backup"]}),r&&e.jsx("p",{className:`mt-2 text-xs ${r.includes("success")?"text-emerald-400":"text-amber-400"}`,children:r})]}),e.jsx("hr",{className:"border-white/5"}),e.jsxs("div",{children:[e.jsx("h3",{className:"text-sm font-medium mb-2",children:"Restore from Backup"}),e.jsx("p",{className:"text-xs text-shell-text-tertiary mb-3",children:"Upload a previously created backup archive to restore."}),e.jsxs("label",{className:"flex flex-col items-center gap-2 p-6 rounded-lg border-2 border-dashed border-white/10 hover:border-white/20 transition-colors cursor-pointer",children:[e.jsx(me,{size:24,className:"text-shell-text-tertiary"}),e.jsx("span",{className:"text-xs text-shell-text-tertiary",children:"Click to select a backup file"}),e.jsx("input",{type:"file",accept:".tar.gz,.zip,.bak",className:"hidden","aria-label":"Upload backup file"})]})]})]})]})}function W({onClose:r}){const[l,t]=s.useState(null),[x,a]=s.useState(!1);s.useEffect(()=>{let n=!1,c=null,m=null,h=!1;const p=()=>{h||n||(h=!0,c&&clearInterval(c),m=setInterval(async()=>{if(!n)try{(await fetch("/api/settings/update-status")).ok&&(a(!0),m&&clearInterval(m),setTimeout(()=>{n||window.location.reload()},500))}catch{}},2e3))};return c=setInterval(async()=>{if(!n)try{const o=await fetch("/api/system/restart/status");if(o.ok){const j=await o.json();t(j),j.phase==="restarting"&&p()}}catch{p()}},1e3),()=>{n=!0,c&&clearInterval(c),m&&clearInterval(m)}},[]);const d=l?Object.entries(l.agents):[];function i(n){return n==="ready"?e.jsx("span",{className:"text-[10px] px-1.5 py-0.5 rounded bg-emerald-500/20 text-emerald-300",children:"ready"}):n==="timeout"?e.jsx("span",{className:"text-[10px] px-1.5 py-0.5 rounded bg-amber-500/20 text-amber-300",children:"timeout"}):n==="error"?e.jsx("span",{className:"text-[10px] px-1.5 py-0.5 rounded bg-red-500/20 text-red-300",children:"error"}):e.jsxs("span",{className:"text-[10px] px-1.5 py-0.5 rounded bg-sky-500/20 text-sky-300 flex items-center gap-1",children:[e.jsx(P,{size:10,className:"animate-spin"}),n]})}return e.jsx("div",{role:"dialog","aria-modal":"true","aria-label":"Restart progress",className:"fixed inset-0 z-50 flex items-center justify-center bg-black/60",children:e.jsxs("div",{className:"bg-shell-surface border border-white/10 rounded-xl p-6 w-full max-w-md shadow-xl space-y-4",children:[e.jsx("h3",{className:"text-base font-semibold",children:x?"Restarted — reloading…":d.length>0?"Preparing agents for restart":"Restarting server…"}),d.length>0&&e.jsx("ul",{className:"space-y-1","aria-label":"Agent preparation status",children:d.map(([n,c])=>e.jsxs("li",{className:"flex items-center justify-between text-sm",children:[e.jsx("span",{className:"text-shell-text-secondary",children:n}),i(c.status)]},n))}),(l==null?void 0:l.phase)==="restarting"&&!x&&e.jsx("p",{className:"text-xs text-shell-text-tertiary",children:"Waiting for server to come back…"}),!l&&e.jsxs("p",{className:"text-xs text-shell-text-tertiary flex items-center gap-1",children:[e.jsx(P,{size:12,className:"animate-spin"})," Connecting…"]}),e.jsx("div",{className:"flex justify-end",children:e.jsx(b,{variant:"outline",size:"sm",onClick:r,"aria-label":"Cancel restart progress dialog",children:"Cancel"})})]})})}function Se(){const[r,l]=s.useState(!1),[t,x]=s.useState(!1),[a,d]=s.useState(null),[i,n]=s.useState(null),[c,m]=s.useState({check_enabled:!0,auto_apply:!1,auto_restart:!1}),[h,p]=s.useState(null),[o,j]=s.useState(!1),[v,k]=s.useState(!1);s.useEffect(()=>{(async()=>{try{const y=await fetch("/api/preferences/auto-update");if(y.ok){const u=await y.json();u&&typeof u=="object"&&m({check_enabled:u.check_enabled??!0,auto_apply:u.auto_apply??!1,auto_restart:u.auto_restart??!1})}}catch{}try{const y=await fetch("/api/settings/update-check");y.ok&&d(await y.json())}catch{}try{const y=await fetch("/api/settings/update-status");y.ok&&p(await y.json())}catch{}})()},[]);const S=s.useCallback(async y=>{m(y);try{await fetch("/api/preferences/auto-update",{method:"PUT",headers:{"Content-Type":"application/json"},body:JSON.stringify(y)})}catch{}},[]),g=async()=>{l(!0),n(null);try{const y=await fetch("/api/settings/update-check");if(y.ok){const u=await y.json();d(u),n(u.has_updates?"A new version is available.":"You are up to date.")}else n("Update check not available.")}catch{n("Could not reach update server.")}l(!1)},R=async()=>{x(!0),n(null);try{const y=await fetch("/api/settings/update",{method:"POST"});if(y.ok){const u=await y.json().catch(()=>({}));if(u.status==="restarting")j(!0);else{n(u.message??"Update applied. Restart the server to finish."),k(!0);const U=await fetch("/api/settings/update-check");U.ok&&d(await U.json());const C=await fetch("/api/settings/update-status");C.ok&&p(await C.json())}}else{const u=await y.json().catch(()=>({}));n(u.error??"Update failed.")}}catch{n("Could not apply update.")}x(!1)},_=async()=>{j(!0);try{await fetch("/api/system/restart/prepare",{method:"POST"})}catch{}},I=!!(h!=null&&h.pending_restart_sha);return e.jsxs("section",{"aria-label":"System updates",children:[e.jsx("h2",{className:"text-lg font-semibold mb-5",children:"Updates"}),I&&e.jsxs("div",{className:"mb-4 flex items-center justify-between gap-3 rounded-lg border border-amber-500/30 bg-amber-500/10 px-4 py-3",children:[e.jsxs("div",{className:"flex items-center gap-2 text-sm text-amber-200",children:[e.jsx(F,{size:16,className:"shrink-0"}),e.jsxs("span",{children:["Update pulled — restart to finish applying (",h.pending_restart_sha.slice(0,7),")"]})]}),e.jsx(b,{size:"sm",onClick:_,"aria-label":"Restart server to apply update",children:"Restart now"})]}),e.jsxs(w,{className:"p-4 space-y-4",children:[e.jsxs("div",{className:"flex items-center gap-3",children:[e.jsx("div",{className:"p-2 rounded-lg bg-white/5 text-sky-400",children:e.jsx(xe,{size:20})}),e.jsxs("div",{className:"flex-1 min-w-0",children:[e.jsx("p",{className:"text-sm font-medium",children:"taOS"}),a!=null&&a.has_updates&&a.new_commit?e.jsxs("div",{className:"flex flex-col gap-0.5",children:[e.jsxs("p",{className:"text-xs text-shell-text-tertiary tabular-nums",children:[e.jsx("span",{className:"text-white/40",children:"installed "}),a.current_commit]}),e.jsxs("p",{className:"text-xs text-amber-300/90 tabular-nums",children:[e.jsx("span",{className:"text-amber-300/50",children:"available "}),a.new_commit]})]}):e.jsx("p",{className:"text-xs text-shell-text-tertiary tabular-nums",children:(a==null?void 0:a.current_commit)??"v0.1.0-dev"})]}),(a==null?void 0:a.has_updates)&&e.jsx("span",{className:"text-[10px] px-2 py-1 rounded-full font-semibold bg-amber-500/20 text-amber-300",children:"Update available"})]}),e.jsxs("div",{className:"flex gap-2 flex-wrap",children:[e.jsxs(b,{variant:"outline",size:"sm",onClick:g,disabled:r,children:[e.jsx(P,{size:14,className:r?"animate-spin":""}),r?"Checking...":"Check Now"]}),v?e.jsx(b,{size:"sm",onClick:_,"aria-label":"Restart server to apply update",children:"Restart Now"}):a!=null&&a.has_updates?e.jsx(b,{size:"sm",onClick:R,disabled:t,children:t?"Installing...":"Install Update"}):null]}),i&&e.jsxs("div",{className:"flex items-start gap-2 text-xs",children:[i.includes("up to date")||i.includes("applied")?e.jsx(D,{size:14,className:"text-emerald-400 shrink-0 mt-0.5"}):e.jsx(F,{size:14,className:"text-amber-400 shrink-0 mt-0.5"}),e.jsx("span",{className:"text-shell-text-secondary",children:i})]}),e.jsxs("div",{className:"border-t border-white/5 pt-4 space-y-3",children:[e.jsxs("div",{className:"flex items-center justify-between gap-3",children:[e.jsxs("div",{className:"flex-1 min-w-0",children:[e.jsx(N,{className:"text-sm",children:"Check for updates automatically"}),e.jsx("p",{className:"text-[11px] text-shell-text-tertiary mt-0.5",children:"Polls GitHub hourly and notifies when a new version is available."})]}),e.jsx(T,{checked:c.check_enabled??!0,onCheckedChange:y=>S({...c,check_enabled:y})})]}),e.jsxs("div",{className:"flex items-center justify-between gap-3",children:[e.jsxs("div",{className:"flex-1 min-w-0",children:[e.jsx(N,{className:"text-sm",children:"Install updates automatically"}),e.jsx("p",{className:"text-[11px] text-shell-text-tertiary mt-0.5",children:"Pulls + installs new versions as soon as they're detected. You'll still need to restart the server manually."})]}),e.jsx(T,{checked:c.auto_apply??!1,onCheckedChange:y=>S({...c,auto_apply:y}),disabled:!(c.check_enabled??!0)})]}),e.jsxs("div",{className:"flex items-center justify-between gap-3",children:[e.jsxs("div",{className:"flex-1 min-w-0",children:[e.jsx(N,{className:"text-sm",children:"Automatically restart after update"}),e.jsx("p",{className:"text-[11px] text-shell-text-tertiary mt-0.5",children:c.auto_restart?"Server will restart automatically once an update is pulled.":"We'll remind you every 6 hours when a restart is pending."})]}),e.jsx(T,{checked:c.auto_restart??!1,onCheckedChange:y=>S({...c,auto_restart:y}),"aria-label":"Automatically restart after update"})]})]})]}),o&&e.jsx(W,{onClose:()=>j(!1)})]})}function Ce(){const[r,l]=s.useState(`# taOS Configuration +import{r as s,j as e}from"./vendor-react-l6srOxy7.js";import{B as b,C as w,L as N,I as E,S as T,T as Z}from"./toolbar-UW6q5pkx.js";import{u as ee}from"./main-FOmUFQfu.js";import{t as te,a0 as se,an as ae,ak as K,a9 as P,as as V,at as le,au as ne,l as re,U as ce,$ as ie,r as F,f as D,av as Y,g as oe,y as de,c as xe,ab as me,aw as ue,X as he}from"./vendor-icons--yQaiqiL.js";import"./vendor-radix-BhM7AEEG.js";import"./vendor-layout-B-pp9n1f.js";import"./tokens-BKHlNYpw.js";import"./vendor-codemirror-aNcHammg.js";function pe(r,l,t=a=>a,x=a=>({value:a})){const a=`taos-pref:${r}`,[d,i]=s.useState(()=>{try{const p=localStorage.getItem(a);if(p!==null)return JSON.parse(p)}catch{}return l}),[n,c]=s.useState(!1),m=s.useRef(null);s.useEffect(()=>{let p=!1;return(async()=>{try{const o=await fetch(`/api/preferences/${encodeURIComponent(r)}`);if(!o.ok){c(!0);return}const j=await o.json();if(p)return;if(j&&typeof j=="object"&&Object.keys(j).length>0){const v=t(j);i(v);try{localStorage.setItem(a,JSON.stringify(v))}catch{}}c(!0)}catch{c(!0)}})(),()=>{p=!0}},[r]);const h=s.useCallback(p=>{i(o=>{const j=typeof p=="function"?p(o):p;try{localStorage.setItem(a,JSON.stringify(j))}catch{}return m.current!==null&&clearTimeout(m.current),m.current=setTimeout(()=>{m.current=null,fetch(`/api/preferences/${encodeURIComponent(r)}`,{method:"PUT",headers:{"Content-Type":"application/json"},body:JSON.stringify(x(j))}).catch(()=>{})},500),j})},[a,x,r]);return[d,h,{loaded:n}]}const fe=[{id:"system",label:"System Info",icon:te},{id:"storage",label:"Storage",icon:se},{id:"memory",label:"Memory",icon:ae},{id:"backup",label:"Backup & Restore",icon:K},{id:"updates",label:"Updates",icon:P},{id:"advanced",label:"Advanced",icon:V},{id:"shortcuts",label:"Keyboard Shortcuts",icon:le},{id:"accessibility",label:"Accessibility",icon:ne},{id:"desktop",label:"Desktop & Dock",icon:re},{id:"users",label:"Users",icon:ce}],je={cpu:"Detecting...",ram:"Detecting...",npu:"Detecting...",gpu:"Detecting...",disk:"Detecting...",os:"Detecting..."},ye=[{label:"Models",size:"--",bytes:0,maxBytes:1},{label:"Data",size:"--",bytes:0,maxBytes:1},{label:"App Catalog",size:"--",bytes:0,maxBytes:1}];async function G(r,l){try{const t=await fetch(r,{headers:{Accept:"application/json"}});return!t.ok||!(t.headers.get("content-type")??"").includes("application/json")?l:await t.json()}catch{return l}}function be({value:r,max:l}){const t=l>0?Math.min(100,r/l*100):0;return e.jsx("div",{className:"h-2 w-full rounded-full bg-white/5",role:"progressbar","aria-valuenow":t,"aria-valuemin":0,"aria-valuemax":100,children:e.jsx("div",{className:"h-full rounded-full bg-sky-500 transition-all",style:{width:`${t}%`}})})}function ge(){const[r,l]=s.useState(je),[t,x]=s.useState(!1),[a,d]=s.useState(!1),i=s.useCallback(async()=>{var m,h,p,o,j,v,k,S,g,R,_,I,y;x(!0);const c=await G("/api/system",null);if(c!=null&&c.hardware||c!=null&&c.resources){const u=c.hardware??{},U=c.resources??{},C=U.ram_total_mb??u.ram_mb??0,$=U.disk_total_gb??((m=u.disk)==null?void 0:m.total_gb)??0,A=((h=u.cpu)==null?void 0:h.model)??((p=u.cpu)==null?void 0:p.soc)??"Unknown",B=(o=u.cpu)!=null&&o.cores?` × ${u.cpu.cores}`:"",L=(j=u.cpu)!=null&&j.arch?` (${u.cpu.arch})`:"",f=((v=u.gpu)==null?void 0:v.model)||((k=u.gpu)==null?void 0:k.type)||"None",z=(S=u.gpu)!=null&&S.vram_mb&&u.gpu.vram_mb>0?` (${(u.gpu.vram_mb/1024).toFixed(1)} GB)`:"",M=(g=u.npu)!=null&&g.type&&u.npu.type!=="none"?u.npu.type:"None",q=(R=u.npu)!=null&&R.tops&&u.npu.tops>0?` · ${u.npu.tops} TOPS`:"",X=(_=u.disk)!=null&&_.type?` ${u.disk.type}`:"",J=[(I=u.os)==null?void 0:I.distro,(y=u.os)==null?void 0:y.version].filter(Boolean),Q=J.length>0?J.join(" "):"—";l({cpu:`${A}${B}${L}`,ram:C>=1024?`${(C/1024).toFixed(1)} GB`:C>0?`${C} MB`:"—",npu:`${M}${q}`,gpu:`${f}${z}`,disk:$>0?`${$} GB${X}`:"—",os:Q})}else l({cpu:"Unavailable",ram:"Unavailable",npu:"Unavailable",gpu:"Unavailable",disk:"Unavailable",os:"Unavailable"});x(!1)},[]);s.useEffect(()=>{i()},[i]);const n=[["CPU",r.cpu],["RAM",r.ram],["NPU",r.npu],["GPU",r.gpu],["Disk",r.disk],["OS",r.os]];return e.jsxs("section",{"aria-label":"System information",children:[e.jsx("h2",{className:"text-lg font-semibold mb-5",children:"System Information"}),e.jsx("div",{className:"rounded-2xl bg-white/[0.04] border border-white/[0.06] overflow-x-auto backdrop-blur-sm",children:e.jsx("table",{className:"w-full text-sm min-w-[360px]",children:e.jsx("tbody",{children:n.map(([c,m])=>e.jsxs("tr",{className:"border-b border-white/5 last:border-0",children:[e.jsx("td",{className:"px-5 py-3 text-shell-text-secondary font-medium w-32",children:c}),e.jsx("td",{className:"px-5 py-3",children:m})]},c))})})}),e.jsxs("div",{className:"mt-3 flex items-center gap-2 flex-wrap",children:[e.jsxs(b,{variant:"outline",size:"sm",onClick:i,disabled:t,children:[e.jsx(P,{size:14,className:t?"animate-spin":""}),"Re-detect Hardware"]}),e.jsxs(b,{variant:"outline",size:"sm",onClick:async()=>{d(!0);try{await fetch("/api/system/restart/prepare",{method:"POST"})}catch{}},"aria-label":"Restart taOS server",children:[e.jsx(P,{size:14}),"Restart Server"]})]}),e.jsx("p",{className:"mt-2 text-xs text-shell-text-tertiary",children:"Restart the server to apply settings changes that require a reload."}),a&&e.jsx(W,{onClose:()=>d(!1)})]})}function Ne(){const[r,l]=s.useState(ye);return s.useEffect(()=>{G("/api/settings/storage",null).then(t=>{t&&Array.isArray(t)?l(t):l([{label:"Models",size:"4.2 GB",bytes:4200,maxBytes:32e3},{label:"Data",size:"1.8 GB",bytes:1800,maxBytes:32e3},{label:"App Catalog",size:"320 MB",bytes:320,maxBytes:32e3}])})},[]),e.jsxs("section",{"aria-label":"Storage usage",children:[e.jsx("h2",{className:"text-lg font-semibold mb-5",children:"Storage Usage"}),e.jsx("div",{className:"space-y-3",children:r.map(t=>e.jsxs(w,{className:"p-4",children:[e.jsxs("div",{className:"flex items-center justify-between mb-2",children:[e.jsx("span",{className:"text-sm font-medium",children:t.label}),e.jsx("span",{className:"text-sm text-shell-text-secondary tabular-nums",children:t.size})]}),e.jsx(be,{value:t.bytes,max:t.maxBytes})]},t.label))})]})}const ve=[{key:"capture_conversations",label:"Conversations",desc:"Messages you send to agents in the Message Hub"},{key:"capture_notes",label:"Notes",desc:"Notes from the Text Editor app"},{key:"capture_files",label:"File activity",desc:"Files you upload or open"},{key:"capture_searches",label:"Search queries",desc:"What you search for in global search"}];function we(){const[r,l]=s.useState(null),[t,x]=s.useState(null),[a,d]=s.useState(null);s.useEffect(()=>{fetch("/api/user-memory/settings").then(n=>n.ok?n.json():null).then(n=>{l(n||{})}).catch(()=>{l({}),d("Could not load memory settings.")}),fetch("/api/user-memory/stats").then(n=>n.ok?n.json():null).then(n=>{n&&x(n)}).catch(()=>{})},[]);const i=(n,c)=>{const m={...r||{},[n]:c};l(m),fetch("/api/user-memory/settings",{method:"PUT",headers:{"Content-Type":"application/json"},body:JSON.stringify({[n]:c})}).then(h=>{h.ok?d(null):d(`Failed to save setting (${h.status})`)}).catch(()=>d("Could not reach backend."))};return r?e.jsxs("section",{"aria-label":"Memory capture settings",children:[e.jsx("h2",{className:"text-lg font-semibold mb-2",children:"Memory Capture"}),e.jsx("p",{className:"text-sm text-shell-text-tertiary mb-5",children:"Choose what activity gets saved to your personal memory index. All data stays on this device."}),a&&e.jsxs("p",{className:"mb-3 text-xs text-amber-400 flex items-center gap-1.5",children:[e.jsx(F,{size:12})," ",a]}),e.jsx("div",{className:"space-y-2",children:ve.map(n=>{const c=!!r[n.key],m=`capture-${String(n.key)}`;return e.jsxs(w,{className:"p-4 flex items-center justify-between gap-3",children:[e.jsxs("div",{className:"flex-1 min-w-0",children:[e.jsx(N,{htmlFor:m,className:"text-sm font-medium text-shell-text",children:n.label}),e.jsx("p",{className:"text-xs text-shell-text-tertiary mt-0.5",children:n.desc})]}),e.jsx(T,{id:m,checked:c,onCheckedChange:h=>i(n.key,h),"aria-label":`Capture ${n.label}`})]},String(n.key))})}),t&&e.jsxs(w,{className:"mt-6 p-4",children:[e.jsx("h3",{className:"text-sm font-medium mb-3",children:"Stored chunks"}),e.jsxs("div",{className:"text-xs text-shell-text-secondary mb-2 tabular-nums",children:["Total: ",t.total]}),Object.keys(t.collections||{}).length>0?e.jsx("ul",{className:"space-y-1 text-xs text-shell-text-tertiary",children:Object.entries(t.collections).map(([n,c])=>e.jsxs("li",{className:"flex justify-between tabular-nums",children:[e.jsx("span",{children:n}),e.jsx("span",{children:c})]},n))}):e.jsx("p",{className:"text-xs text-shell-text-tertiary",children:"No memories captured yet."})]})]}):e.jsxs("section",{"aria-label":"Memory capture settings",children:[e.jsx("h2",{className:"text-lg font-semibold mb-5",children:"Memory Capture"}),e.jsx("p",{className:"text-sm text-shell-text-tertiary",children:"Loading..."})]})}function ke(){const[r,l]=s.useState(null),[t,x]=s.useState(!1),a=async()=>{x(!0),l(null);try{const d=await fetch("/api/backup",{method:"POST"});d.ok?l("Backup created successfully."):l(`Backup failed (${d.status}). API may not be available yet.`)}catch{l("Could not reach backup endpoint. API not available yet.")}x(!1)};return e.jsxs("section",{"aria-label":"Backup and restore",children:[e.jsx("h2",{className:"text-lg font-semibold mb-5",children:"Backup & Restore"}),e.jsxs(w,{className:"p-4 space-y-4",children:[e.jsxs("div",{children:[e.jsx("h3",{className:"text-sm font-medium mb-2",children:"Create Backup"}),e.jsx("p",{className:"text-xs text-shell-text-tertiary mb-3",children:"Export all agents, memory, and configuration as a backup archive."}),e.jsxs(b,{size:"sm",onClick:a,disabled:t,children:[e.jsx(K,{size:14,className:t?"animate-bounce":""}),t?"Creating...":"Create Backup"]}),r&&e.jsx("p",{className:`mt-2 text-xs ${r.includes("success")?"text-emerald-400":"text-amber-400"}`,children:r})]}),e.jsx("hr",{className:"border-white/5"}),e.jsxs("div",{children:[e.jsx("h3",{className:"text-sm font-medium mb-2",children:"Restore from Backup"}),e.jsx("p",{className:"text-xs text-shell-text-tertiary mb-3",children:"Upload a previously created backup archive to restore."}),e.jsxs("label",{className:"flex flex-col items-center gap-2 p-6 rounded-lg border-2 border-dashed border-white/10 hover:border-white/20 transition-colors cursor-pointer",children:[e.jsx(me,{size:24,className:"text-shell-text-tertiary"}),e.jsx("span",{className:"text-xs text-shell-text-tertiary",children:"Click to select a backup file"}),e.jsx("input",{type:"file",accept:".tar.gz,.zip,.bak",className:"hidden","aria-label":"Upload backup file"})]})]})]})]})}function W({onClose:r}){const[l,t]=s.useState(null),[x,a]=s.useState(!1);s.useEffect(()=>{let n=!1,c=null,m=null,h=!1;const p=()=>{h||n||(h=!0,c&&clearInterval(c),m=setInterval(async()=>{if(!n)try{(await fetch("/api/settings/update-status")).ok&&(a(!0),m&&clearInterval(m),setTimeout(()=>{n||window.location.reload()},500))}catch{}},2e3))};return c=setInterval(async()=>{if(!n)try{const o=await fetch("/api/system/restart/status");if(o.ok){const j=await o.json();t(j),j.phase==="restarting"&&p()}}catch{p()}},1e3),()=>{n=!0,c&&clearInterval(c),m&&clearInterval(m)}},[]);const d=l?Object.entries(l.agents):[];function i(n){return n==="ready"?e.jsx("span",{className:"text-[10px] px-1.5 py-0.5 rounded bg-emerald-500/20 text-emerald-300",children:"ready"}):n==="timeout"?e.jsx("span",{className:"text-[10px] px-1.5 py-0.5 rounded bg-amber-500/20 text-amber-300",children:"timeout"}):n==="error"?e.jsx("span",{className:"text-[10px] px-1.5 py-0.5 rounded bg-red-500/20 text-red-300",children:"error"}):e.jsxs("span",{className:"text-[10px] px-1.5 py-0.5 rounded bg-sky-500/20 text-sky-300 flex items-center gap-1",children:[e.jsx(P,{size:10,className:"animate-spin"}),n]})}return e.jsx("div",{role:"dialog","aria-modal":"true","aria-label":"Restart progress",className:"fixed inset-0 z-50 flex items-center justify-center bg-black/60",children:e.jsxs("div",{className:"bg-shell-surface border border-white/10 rounded-xl p-6 w-full max-w-md shadow-xl space-y-4",children:[e.jsx("h3",{className:"text-base font-semibold",children:x?"Restarted — reloading…":d.length>0?"Preparing agents for restart":"Restarting server…"}),d.length>0&&e.jsx("ul",{className:"space-y-1","aria-label":"Agent preparation status",children:d.map(([n,c])=>e.jsxs("li",{className:"flex items-center justify-between text-sm",children:[e.jsx("span",{className:"text-shell-text-secondary",children:n}),i(c.status)]},n))}),(l==null?void 0:l.phase)==="restarting"&&!x&&e.jsx("p",{className:"text-xs text-shell-text-tertiary",children:"Waiting for server to come back…"}),!l&&e.jsxs("p",{className:"text-xs text-shell-text-tertiary flex items-center gap-1",children:[e.jsx(P,{size:12,className:"animate-spin"})," Connecting…"]}),e.jsx("div",{className:"flex justify-end",children:e.jsx(b,{variant:"outline",size:"sm",onClick:r,"aria-label":"Cancel restart progress dialog",children:"Cancel"})})]})})}function Se(){const[r,l]=s.useState(!1),[t,x]=s.useState(!1),[a,d]=s.useState(null),[i,n]=s.useState(null),[c,m]=s.useState({check_enabled:!0,auto_apply:!1,auto_restart:!1}),[h,p]=s.useState(null),[o,j]=s.useState(!1),[v,k]=s.useState(!1);s.useEffect(()=>{(async()=>{try{const y=await fetch("/api/preferences/auto-update");if(y.ok){const u=await y.json();u&&typeof u=="object"&&m({check_enabled:u.check_enabled??!0,auto_apply:u.auto_apply??!1,auto_restart:u.auto_restart??!1})}}catch{}try{const y=await fetch("/api/settings/update-check");y.ok&&d(await y.json())}catch{}try{const y=await fetch("/api/settings/update-status");y.ok&&p(await y.json())}catch{}})()},[]);const S=s.useCallback(async y=>{m(y);try{await fetch("/api/preferences/auto-update",{method:"PUT",headers:{"Content-Type":"application/json"},body:JSON.stringify(y)})}catch{}},[]),g=async()=>{l(!0),n(null);try{const y=await fetch("/api/settings/update-check");if(y.ok){const u=await y.json();d(u),n(u.has_updates?"A new version is available.":"You are up to date.")}else n("Update check not available.")}catch{n("Could not reach update server.")}l(!1)},R=async()=>{x(!0),n(null);try{const y=await fetch("/api/settings/update",{method:"POST"});if(y.ok){const u=await y.json().catch(()=>({}));if(u.status==="restarting")j(!0);else{n(u.message??"Update applied. Restart the server to finish."),k(!0);const U=await fetch("/api/settings/update-check");U.ok&&d(await U.json());const C=await fetch("/api/settings/update-status");C.ok&&p(await C.json())}}else{const u=await y.json().catch(()=>({}));n(u.error??"Update failed.")}}catch{n("Could not apply update.")}x(!1)},_=async()=>{j(!0);try{await fetch("/api/system/restart/prepare",{method:"POST"})}catch{}},I=!!(h!=null&&h.pending_restart_sha);return e.jsxs("section",{"aria-label":"System updates",children:[e.jsx("h2",{className:"text-lg font-semibold mb-5",children:"Updates"}),I&&e.jsxs("div",{className:"mb-4 flex items-center justify-between gap-3 rounded-lg border border-amber-500/30 bg-amber-500/10 px-4 py-3",children:[e.jsxs("div",{className:"flex items-center gap-2 text-sm text-amber-200",children:[e.jsx(F,{size:16,className:"shrink-0"}),e.jsxs("span",{children:["Update pulled — restart to finish applying (",h.pending_restart_sha.slice(0,7),")"]})]}),e.jsx(b,{size:"sm",onClick:_,"aria-label":"Restart server to apply update",children:"Restart now"})]}),e.jsxs(w,{className:"p-4 space-y-4",children:[e.jsxs("div",{className:"flex items-center gap-3",children:[e.jsx("div",{className:"p-2 rounded-lg bg-white/5 text-sky-400",children:e.jsx(xe,{size:20})}),e.jsxs("div",{className:"flex-1 min-w-0",children:[e.jsx("p",{className:"text-sm font-medium",children:"taOS"}),a!=null&&a.has_updates&&a.new_commit?e.jsxs("div",{className:"flex flex-col gap-0.5",children:[e.jsxs("p",{className:"text-xs text-shell-text-tertiary tabular-nums",children:[e.jsx("span",{className:"text-white/40",children:"installed "}),a.current_commit]}),e.jsxs("p",{className:"text-xs text-amber-300/90 tabular-nums",children:[e.jsx("span",{className:"text-amber-300/50",children:"available "}),a.new_commit]})]}):e.jsx("p",{className:"text-xs text-shell-text-tertiary tabular-nums",children:(a==null?void 0:a.current_commit)??"v0.1.0-dev"})]}),(a==null?void 0:a.has_updates)&&e.jsx("span",{className:"text-[10px] px-2 py-1 rounded-full font-semibold bg-amber-500/20 text-amber-300",children:"Update available"})]}),e.jsxs("div",{className:"flex gap-2 flex-wrap",children:[e.jsxs(b,{variant:"outline",size:"sm",onClick:g,disabled:r,children:[e.jsx(P,{size:14,className:r?"animate-spin":""}),r?"Checking...":"Check Now"]}),v?e.jsx(b,{size:"sm",onClick:_,"aria-label":"Restart server to apply update",children:"Restart Now"}):a!=null&&a.has_updates?e.jsx(b,{size:"sm",onClick:R,disabled:t,children:t?"Installing...":"Install Update"}):null]}),i&&e.jsxs("div",{className:"flex items-start gap-2 text-xs",children:[i.includes("up to date")||i.includes("applied")?e.jsx(D,{size:14,className:"text-emerald-400 shrink-0 mt-0.5"}):e.jsx(F,{size:14,className:"text-amber-400 shrink-0 mt-0.5"}),e.jsx("span",{className:"text-shell-text-secondary",children:i})]}),e.jsxs("div",{className:"border-t border-white/5 pt-4 space-y-3",children:[e.jsxs("div",{className:"flex items-center justify-between gap-3",children:[e.jsxs("div",{className:"flex-1 min-w-0",children:[e.jsx(N,{className:"text-sm",children:"Check for updates automatically"}),e.jsx("p",{className:"text-[11px] text-shell-text-tertiary mt-0.5",children:"Polls GitHub hourly and notifies when a new version is available."})]}),e.jsx(T,{checked:c.check_enabled??!0,onCheckedChange:y=>S({...c,check_enabled:y})})]}),e.jsxs("div",{className:"flex items-center justify-between gap-3",children:[e.jsxs("div",{className:"flex-1 min-w-0",children:[e.jsx(N,{className:"text-sm",children:"Install updates automatically"}),e.jsx("p",{className:"text-[11px] text-shell-text-tertiary mt-0.5",children:"Pulls + installs new versions as soon as they're detected. You'll still need to restart the server manually."})]}),e.jsx(T,{checked:c.auto_apply??!1,onCheckedChange:y=>S({...c,auto_apply:y}),disabled:!(c.check_enabled??!0)})]}),e.jsxs("div",{className:"flex items-center justify-between gap-3",children:[e.jsxs("div",{className:"flex-1 min-w-0",children:[e.jsx(N,{className:"text-sm",children:"Automatically restart after update"}),e.jsx("p",{className:"text-[11px] text-shell-text-tertiary mt-0.5",children:c.auto_restart?"Server will restart automatically once an update is pulled.":"We'll remind you every 6 hours when a restart is pending."})]}),e.jsx(T,{checked:c.auto_restart??!1,onCheckedChange:y=>S({...c,auto_restart:y}),"aria-label":"Automatically restart after update"})]})]})]}),o&&e.jsx(W,{onClose:()=>j(!1)})]})}function Ce(){const[r,l]=s.useState(`# taOS Configuration # Edit YAML below server: diff --git a/static/desktop/assets/chat-CnrplGIN.js b/static/desktop/assets/chat-R5uusfVD.js similarity index 94% rename from static/desktop/assets/chat-CnrplGIN.js rename to static/desktop/assets/chat-R5uusfVD.js index bcba8711..c007058b 100644 --- a/static/desktop/assets/chat-CnrplGIN.js +++ b/static/desktop/assets/chat-R5uusfVD.js @@ -1,2 +1,2 @@ -const __vite__mapDeps=(i,m=__vite__mapDeps,d=(m.f||(m.f=["assets/MessagesApp-D7Umpsei.js","assets/vendor-react-l6srOxy7.js","assets/toolbar-UW6q5pkx.js","assets/vendor-radix-BhM7AEEG.js","assets/vendor-layout-B-pp9n1f.js","assets/vendor-layout-BfitWg9R.css","assets/MobileSplitView-B-4MQO2C.js","assets/vendor-icons--yQaiqiL.js","assets/use-is-mobile-v5lglusa.js","assets/dnd-bus-CdEoCWzR.js"])))=>i.map(i=>d[i]); -import"./tokens-BKHlNYpw.js";import{r as t,j as e,p as u}from"./vendor-react-l6srOxy7.js";import{_ as f}from"./vendor-codemirror-aNcHammg.js";import{u as x}from"./use-is-mobile-v5lglusa.js";const h=720*60*60*1e3,i="taos-install-dismissed";function y(){const s=x(),[n,a]=t.useState(null),[c,d]=t.useState(!1);if(t.useEffect(()=>{const o=l=>{l.preventDefault(),a(l)};return window.addEventListener("beforeinstallprompt",o),()=>window.removeEventListener("beforeinstallprompt",o)},[]),!s||!n||c||typeof window<"u"&&window.matchMedia("(display-mode: standalone)").matches)return null;const r=localStorage.getItem(i);if(r&&Date.now()-Number(r){try{await n.prompt(),await n.userChoice}catch{}a(null)},m=()=>{localStorage.setItem(i,String(Date.now())),d(!0)};return e.jsxs("div",{role:"region","aria-label":"Install prompt",className:"flex items-center gap-3 px-4 py-2 bg-sky-500/20 border-b border-sky-500/30 text-sm",children:[e.jsx("span",{className:"flex-1",children:"Install taOS talk for quick access"}),e.jsx("button",{onClick:p,className:"px-3 py-1 bg-sky-500/40 text-sky-100 rounded hover:bg-sky-500/60",children:"Install"}),e.jsx("button",{onClick:m,className:"px-2 py-1 opacity-70 hover:opacity-100",children:"Not now"})]})}const b=t.lazy(()=>f(()=>import("./MessagesApp-D7Umpsei.js"),__vite__mapDeps([0,1,2,3,4,5,6,7,8,9])).then(s=>({default:s.MessagesApp})));function w(){return e.jsxs("div",{className:"h-screen w-screen flex flex-col overflow-hidden",style:{backgroundColor:"#1a1b2e",paddingTop:"env(safe-area-inset-top, 0px)"},children:[e.jsx(y,{}),e.jsx(t.Suspense,{fallback:e.jsx("div",{className:"flex items-center justify-center h-full",style:{color:"rgba(255,255,255,0.4)"},children:"Loading…"}),children:e.jsx(b,{windowId:"standalone-chat",title:"taOS talk"})})]})}u.createRoot(document.getElementById("root")).render(e.jsx(t.StrictMode,{children:e.jsx(w,{})})); +const __vite__mapDeps=(i,m=__vite__mapDeps,d=(m.f||(m.f=["assets/MessagesApp-CkhTvSE9.js","assets/vendor-react-l6srOxy7.js","assets/toolbar-UW6q5pkx.js","assets/vendor-radix-BhM7AEEG.js","assets/vendor-layout-B-pp9n1f.js","assets/vendor-layout-BfitWg9R.css","assets/MobileSplitView-B-4MQO2C.js","assets/vendor-icons--yQaiqiL.js","assets/use-is-mobile-v5lglusa.js","assets/dnd-bus-CdEoCWzR.js"])))=>i.map(i=>d[i]); +import"./tokens-BKHlNYpw.js";import{r as t,j as e,p as u}from"./vendor-react-l6srOxy7.js";import{_ as f}from"./vendor-codemirror-aNcHammg.js";import{u as x}from"./use-is-mobile-v5lglusa.js";const h=720*60*60*1e3,i="taos-install-dismissed";function y(){const s=x(),[n,a]=t.useState(null),[c,d]=t.useState(!1);if(t.useEffect(()=>{const o=l=>{l.preventDefault(),a(l)};return window.addEventListener("beforeinstallprompt",o),()=>window.removeEventListener("beforeinstallprompt",o)},[]),!s||!n||c||typeof window<"u"&&window.matchMedia("(display-mode: standalone)").matches)return null;const r=localStorage.getItem(i);if(r&&Date.now()-Number(r){try{await n.prompt(),await n.userChoice}catch{}a(null)},m=()=>{localStorage.setItem(i,String(Date.now())),d(!0)};return e.jsxs("div",{role:"region","aria-label":"Install prompt",className:"flex items-center gap-3 px-4 py-2 bg-sky-500/20 border-b border-sky-500/30 text-sm",children:[e.jsx("span",{className:"flex-1",children:"Install taOS talk for quick access"}),e.jsx("button",{onClick:p,className:"px-3 py-1 bg-sky-500/40 text-sky-100 rounded hover:bg-sky-500/60",children:"Install"}),e.jsx("button",{onClick:m,className:"px-2 py-1 opacity-70 hover:opacity-100",children:"Not now"})]})}const b=t.lazy(()=>f(()=>import("./MessagesApp-CkhTvSE9.js"),__vite__mapDeps([0,1,2,3,4,5,6,7,8,9])).then(s=>({default:s.MessagesApp})));function w(){return e.jsxs("div",{className:"h-screen w-screen flex flex-col overflow-hidden",style:{backgroundColor:"#1a1b2e",paddingTop:"env(safe-area-inset-top, 0px)"},children:[e.jsx(y,{}),e.jsx(t.Suspense,{fallback:e.jsx("div",{className:"flex items-center justify-center h-full",style:{color:"rgba(255,255,255,0.4)"},children:"Loading…"}),children:e.jsx(b,{windowId:"standalone-chat",title:"taOS talk"})})]})}u.createRoot(document.getElementById("root")).render(e.jsx(t.StrictMode,{children:e.jsx(w,{})})); diff --git a/static/desktop/assets/main-w-WDDs5-.js b/static/desktop/assets/main-FOmUFQfu.js similarity index 99% rename from static/desktop/assets/main-w-WDDs5-.js rename to static/desktop/assets/main-FOmUFQfu.js index fa489137..2fa32dcb 100644 --- a/static/desktop/assets/main-w-WDDs5-.js +++ b/static/desktop/assets/main-FOmUFQfu.js @@ -1,5 +1,5 @@ -const __vite__mapDeps=(i,m=__vite__mapDeps,d=(m.f||(m.f=["assets/MessagesApp-D7Umpsei.js","assets/vendor-react-l6srOxy7.js","assets/toolbar-UW6q5pkx.js","assets/vendor-radix-BhM7AEEG.js","assets/vendor-layout-B-pp9n1f.js","assets/vendor-layout-BfitWg9R.css","assets/MobileSplitView-B-4MQO2C.js","assets/vendor-icons--yQaiqiL.js","assets/use-is-mobile-v5lglusa.js","assets/dnd-bus-CdEoCWzR.js","assets/AgentsApp-BZw6W6Vy.js","assets/framework-api-B6uX1y0T.js","assets/models-D8xGfVt0.js","assets/cluster-Ca85Gm-W.js","assets/FilesApp-DpnvIlme.js","assets/StoreApp-B9C6ujYf.js","assets/SettingsApp-3EqaoTva.js","assets/tokens-BKHlNYpw.js","assets/tokens-DbWedNtZ.css","assets/vendor-codemirror-aNcHammg.js","assets/ModelsApp-BGQXnEI3.js","assets/ProvidersApp-BEdnJTlt.js","assets/ActivityApp-B9wIvJAK.js","assets/ClusterApp-oYzyi0Dp.js","assets/MemoryApp-Dw5harOM.js","assets/MCPApp-Ds2pyPo2.js","assets/ChannelsApp-BveF_Oog.js","assets/SecretsApp-Dq-GKn40.js","assets/TasksApp-CcqxzxyH.js","assets/ImportApp-CB2pqwOR.js","assets/ImagesApp-DrJsImHG.js","assets/LibraryApp-BD1Wtjm7.js","assets/knowledge-ES9kK4zW.js","assets/RedditApp-CVpnnpBP.js","assets/YouTubeApp-CAVU-1ZB.js","assets/GitHubApp-B8-CS8Px.js","assets/XApp-CKMiMFvk.js","assets/AgentBrowsersApp-Ch7Kx-O4.js","assets/CalculatorApp-Chexv_Sm.js","assets/vendor-mathjs-B2vxIMHs.js","assets/CalendarApp-DZD5-sDA.js","assets/ContactsApp-DDczp9Hc.js","assets/BrowserApp-KbremVMB.js","assets/MediaPlayerApp-CYFx0qCR.js","assets/vendor-plyr-CqS7_LjI.js","assets/vendor-plyr-vOeuwXUh.css","assets/TextEditorApp-DX1ldFmW.js","assets/ImageViewerApp-IGHKuKLt.js","assets/TerminalApp-BxZkz7_e.js","assets/vendor-xterm-BZOrcpYI.js","assets/vendor-xterm-6GBZ9nXN.css","assets/ChessApp--VzQGvct.js","assets/vendor-chess-4YJtV_R7.js","assets/WordleApp-3FSioJkg.js","assets/CrosswordsApp-C75aS7vj.js"])))=>i.map(i=>d[i]); -import"./tokens-BKHlNYpw.js";import{r as o,b as D,j as e,p as gt}from"./vendor-react-l6srOxy7.js";import{R as xt,T as ft,P as bt,C as yt,I as Q,S as wt}from"./vendor-radix-BhM7AEEG.js";import{_ as z}from"./vendor-codemirror-aNcHammg.js";import{C as Ye,M as jt,a as vt,Z as kt,S as X,L as be,B as ae,P as St,b as Je,c as Ke,R as Ct,d as zt,e as Ce,f as Xe,H as Nt,X as P,g as Ze,h as _t,A as Tt,i as At,j as Et,F as It,I as Lt,k as Wt,l as Rt,m as Qe,n as G,o as H,p as Pt,q as Ot,r as Mt,T as Dt,s as Ft,t as $t,u as Ht,v as et,w as Ut,x as Bt,y as Vt}from"./vendor-icons--yQaiqiL.js";import{R as Gt,G as qt}from"./vendor-layout-B-pp9n1f.js";import{r as ze,B as Yt}from"./toolbar-UW6q5pkx.js";function Jt(){const[t,s]=o.useState(new Date);return o.useEffect(()=>{const r=setInterval(()=>s(new Date),3e4);return()=>clearInterval(r)},[]),t.toLocaleDateString("en-GB",{weekday:"short",day:"numeric",month:"short"})+" "+t.toLocaleTimeString("en-GB",{hour:"2-digit",minute:"2-digit"})}const Ne=t=>{let s;const n=new Set,r=(d,f)=>{const m=typeof d=="function"?d(s):d;if(!Object.is(m,s)){const p=s;s=f??(typeof m!="object"||m===null)?m:Object.assign({},s,m),n.forEach(h=>h(s,p))}},i=()=>s,l={setState:r,getState:i,getInitialState:()=>g,subscribe:d=>(n.add(d),()=>n.delete(d))},g=s=t(r,i,l);return l},Kt=(t=>t?Ne(t):Ne),Xt=t=>t;function Zt(t,s=Xt){const n=D.useSyncExternalStore(t.subscribe,D.useCallback(()=>s(t.getState()),[t,s]),D.useCallback(()=>s(t.getInitialState()),[t,s]));return D.useDebugValue(n),n}const _e=t=>{const s=Kt(t),n=r=>Zt(s,r);return Object.assign(n,s),n},q=(t=>t?_e(t):_e),Qt={clock:{w:3,h:2,minW:2,minH:2},"agent-status":{w:4,h:3,minW:2,minH:2},"quick-notes":{w:4,h:4,minW:2,minH:2},"system-stats":{w:3,h:3,minW:2,minH:2},weather:{w:3,h:3,minW:2,minH:2}};let en=1;function tn(){return`widget-${Date.now()}-${en++}`}function nn(t,s,n){for(let i=0;i<100;i++)for(let a=0;a<=12-s;a++)if(!t.some(l=>al.x&&il.y))return{x:a,y:i};return{x:0,y:0}}const ye="widgets",tt=`taos-pref:${ye}`,sn=500,rn=[{id:"default-clock",type:"clock",x:0,y:0,w:3,h:2},{id:"default-agents",type:"agent-status",x:3,y:0,w:4,h:3}];function an(){try{const t=localStorage.getItem(tt);if(!t)return null;const s=JSON.parse(t);return Array.isArray(s==null?void 0:s.widgets)&&typeof(s==null?void 0:s.showWidgets)=="boolean"?s:null}catch{return null}}function nt(t){try{localStorage.setItem(tt,JSON.stringify(t))}catch{}}const U=an(),R=q((t,s)=>({widgets:(U==null?void 0:U.widgets)??rn,showWidgets:(U==null?void 0:U.showWidgets)??!0,hydrated:!1,addWidget(n){const r=Qt[n]??{w:3,h:2},i=nn(s().widgets,r.w,r.h),a={id:tn(),type:n,x:i.x,y:i.y,w:r.w,h:r.h,minW:r.minW,minH:r.minH};t(u=>({widgets:[...u.widgets,a]}))},removeWidget(n){t(r=>({widgets:r.widgets.filter(i=>i.id!==n)}))},updateLayout(n){t(r=>({widgets:r.widgets.map(i=>{const a=n.find(u=>u.id===i.id);return a?{...i,x:a.x,y:a.y,w:a.w,h:a.h}:i})}))},toggleWidgets(){t(n=>({showWidgets:!n.showWidgets}))}}));function on(t,s){if(!t||!Array.isArray(s.widgets)||t.showWidgets!==s.showWidgets||t.widgets.length!==s.widgets.length)return!1;for(let n=0;n{try{const t=await fetch(`/api/preferences/${ye}`);if(!t.ok){R.setState({hydrated:!0});return}const s=await t.json();if(s&&Array.isArray(s.widgets)&&typeof s.showWidgets=="boolean"){const r={widgets:s.widgets,showWidgets:s.showWidgets},i={widgets:R.getState().widgets,showWidgets:R.getState().showWidgets};on(i,r)?R.setState({hydrated:!0}):R.setState({widgets:r.widgets,showWidgets:r.showWidgets,hydrated:!0}),nt(r)}else R.setState({hydrated:!0})}catch{R.setState({hydrated:!0})}})();let ee=null;R.subscribe(t=>{if(!t.hydrated)return;const s={widgets:t.widgets,showWidgets:t.showWidgets};nt(s),ee!==null&&clearTimeout(ee),ee=setTimeout(()=>{ee=null,fetch(`/api/preferences/${ye}`,{method:"PUT",headers:{"Content-Type":"application/json"},body:JSON.stringify(s)}).catch(()=>{})},sn)});let ln=0;const F=q((t,s)=>({notifications:[],centreOpen:!1,addNotification(n){const r=`notif-${++ln}`,i={...n,id:r,read:!1,timestamp:Date.now()};return t(a=>({notifications:[i,...a.notifications].slice(0,100)})),r},markRead(n){t(r=>({notifications:r.notifications.map(i=>i.id===n?{...i,read:!0}:i)}))},markAllRead(){t(n=>({notifications:n.notifications.map(r=>({...r,read:!0}))}))},dismiss(n){t(r=>({notifications:r.notifications.filter(i=>i.id!==n)}))},clearAll(){t({notifications:[]})},toggleCentre(){t(n=>({centreOpen:!n.centreOpen}))},closeCentre(){t({centreOpen:!1})},unreadCount(){return s().notifications.filter(n=>!n.read).length}}));let cn=0;const _=q((t,s)=>({windows:[],nextZIndex:1,openWindow(n,r,i){const a=s().windows.find(f=>f.appId===n);if(a)return s().focusWindow(a.id),a.id;const u=`win-${++cn}`,l=s().nextZIndex,g=s().windows.length%8*30,d={id:u,appId:n,position:{x:80+g,y:60+g},size:r,zIndex:l,minimized:!1,maximized:!1,snapped:null,focused:!0,props:i};return t(f=>({windows:f.windows.map(m=>({...m,focused:!1})).concat(d),nextZIndex:l+1})),u},closeWindow(n){t(r=>({windows:r.windows.filter(i=>i.id!==n)}))},focusWindow(n){const r=s().nextZIndex;t(i=>({windows:i.windows.map(a=>({...a,focused:a.id===n,zIndex:a.id===n?r:a.zIndex})),nextZIndex:r+1}))},minimizeWindow(n){t(r=>({windows:r.windows.map(i=>i.id===n?{...i,minimized:!0,focused:!1}:i)}))},restoreWindow(n){const r=s().nextZIndex;t(i=>({windows:i.windows.map(a=>a.id===n?{...a,minimized:!1,focused:!0,zIndex:r}:{...a,focused:!1}),nextZIndex:r+1}))},maximizeWindow(n){t(r=>({windows:r.windows.map(i=>i.id===n?{...i,maximized:!i.maximized}:i)}))},updatePosition(n,r,i){t(a=>({windows:a.windows.map(u=>u.id===n?{...u,position:{x:r,y:i}}:u)}))},updateSize(n,r,i){t(a=>({windows:a.windows.map(u=>u.id===n?{...u,size:{w:r,h:i}}:u)}))},snapWindow(n,r){t(i=>({windows:i.windows.map(a=>a.id===n?{...a,snapped:r}:a)}))},runningAppIds(){return s().windows.map(n=>n.appId)}})),st=[{id:"messages",name:"Messages",icon:"message-circle",category:"platform",component:()=>z(()=>import("./MessagesApp-D7Umpsei.js"),__vite__mapDeps([0,1,2,3,4,5,6,7,8,9])).then(t=>({default:t.MessagesApp})),defaultSize:{w:900,h:600},minSize:{w:400,h:300},singleton:!0,pinned:!0,launchpadOrder:1},{id:"agents",name:"Agents",icon:"bot",category:"platform",component:()=>z(()=>import("./AgentsApp-BZw6W6Vy.js"),__vite__mapDeps([10,1,11,7,2,3,4,5,12,13])).then(t=>({default:t.AgentsApp})),defaultSize:{w:1e3,h:650},minSize:{w:500,h:400},singleton:!0,pinned:!0,launchpadOrder:2},{id:"files",name:"Files",icon:"folder",category:"platform",component:()=>z(()=>import("./FilesApp-DpnvIlme.js"),__vite__mapDeps([14,1,2,3,4,5,6,7,8,9])).then(t=>({default:t.FilesApp})),defaultSize:{w:900,h:550},minSize:{w:400,h:300},singleton:!0,pinned:!0,launchpadOrder:3},{id:"store",name:"Store",icon:"shopping-bag",category:"platform",component:()=>z(()=>import("./StoreApp-B9C6ujYf.js"),__vite__mapDeps([15,1,2,3,4,5,11,7])).then(t=>({default:t.StoreApp})),defaultSize:{w:1e3,h:700},minSize:{w:600,h:400},singleton:!0,pinned:!0,launchpadOrder:4},{id:"settings",name:"Settings",icon:"settings",category:"platform",component:()=>z(()=>import("./SettingsApp-3EqaoTva.js"),__vite__mapDeps([16,1,2,3,4,5,7,17,18,19])).then(t=>({default:t.SettingsApp})),defaultSize:{w:800,h:550},minSize:{w:500,h:400},singleton:!0,pinned:!0,launchpadOrder:5},{id:"models",name:"Models",icon:"brain",category:"platform",component:()=>z(()=>import("./ModelsApp-BGQXnEI3.js"),__vite__mapDeps([20,1,2,3,4,5,12,7])).then(t=>({default:t.ModelsApp})),defaultSize:{w:900,h:600},minSize:{w:500,h:400},singleton:!0,pinned:!1,launchpadOrder:6},{id:"providers",name:"Providers",icon:"cloud",category:"platform",component:()=>z(()=>import("./ProvidersApp-BEdnJTlt.js"),__vite__mapDeps([21,1,2,3,4,5,6,7,8,17,18,19])).then(t=>({default:t.ProvidersApp})),defaultSize:{w:950,h:640},minSize:{w:600,h:400},singleton:!0,pinned:!1,launchpadOrder:6.5},{id:"dashboard",name:"Activity",icon:"activity",category:"platform",component:()=>z(()=>import("./ActivityApp-B9wIvJAK.js"),__vite__mapDeps([22,1,2,3,4,5,13,7])).then(t=>({default:t.ActivityApp})),defaultSize:{w:1100,h:720},minSize:{w:600,h:400},singleton:!0,pinned:!1,launchpadOrder:7},{id:"cluster",name:"Cluster",icon:"network",category:"platform",component:()=>z(()=>import("./ClusterApp-oYzyi0Dp.js"),__vite__mapDeps([23,1,2,3,4,5,13,7])).then(t=>({default:t.ClusterApp})),defaultSize:{w:1e3,h:680},minSize:{w:600,h:400},singleton:!0,pinned:!1,launchpadOrder:7.5},{id:"memory",name:"Memory",icon:"database",category:"platform",component:()=>z(()=>import("./MemoryApp-Dw5harOM.js"),__vite__mapDeps([24,1,2,3,4,5,7])).then(t=>({default:t.MemoryApp})),defaultSize:{w:850,h:550},minSize:{w:450,h:350},singleton:!0,pinned:!1,launchpadOrder:8},{id:"mcp",name:"MCP",icon:"plug",category:"platform",component:()=>z(()=>import("./MCPApp-Ds2pyPo2.js"),__vite__mapDeps([25,1,2,3,4,5,6,7,17,18,19])).then(t=>({default:t.MCPApp})),defaultSize:{w:1e3,h:680},minSize:{w:600,h:400},singleton:!0,pinned:!1,launchpadOrder:9.5},{id:"channels",name:"Channels",icon:"radio",category:"platform",component:()=>z(()=>import("./ChannelsApp-BveF_Oog.js"),__vite__mapDeps([26,1,2,3,4,5,6,7,8])).then(t=>({default:t.ChannelsApp})),defaultSize:{w:800,h:500},minSize:{w:450,h:350},singleton:!0,pinned:!1,launchpadOrder:9},{id:"secrets",name:"Secrets",icon:"key-round",category:"platform",component:()=>z(()=>import("./SecretsApp-Dq-GKn40.js"),__vite__mapDeps([27,1,2,3,4,5,7])).then(t=>({default:t.SecretsApp})),defaultSize:{w:750,h:500},minSize:{w:400,h:300},singleton:!0,pinned:!1,launchpadOrder:10},{id:"tasks",name:"Tasks",icon:"calendar-clock",category:"platform",component:()=>z(()=>import("./TasksApp-CcqxzxyH.js"),__vite__mapDeps([28,1,2,3,4,5,7])).then(t=>({default:t.TasksApp})),defaultSize:{w:800,h:500},minSize:{w:450,h:350},singleton:!0,pinned:!1,launchpadOrder:11},{id:"import",name:"Import",icon:"upload",category:"platform",component:()=>z(()=>import("./ImportApp-CB2pqwOR.js"),__vite__mapDeps([29,1,2,3,4,5,7])).then(t=>({default:t.ImportApp})),defaultSize:{w:700,h:450},minSize:{w:400,h:300},singleton:!0,pinned:!1,launchpadOrder:12},{id:"images",name:"Images",icon:"image",category:"platform",component:()=>z(()=>import("./ImagesApp-DrJsImHG.js"),__vite__mapDeps([30,1,2,3,4,5,12,7])).then(t=>({default:t.ImagesApp})),defaultSize:{w:900,h:600},minSize:{w:500,h:400},singleton:!0,pinned:!1,launchpadOrder:13},{id:"library",name:"Library",icon:"book-open",category:"platform",component:()=>z(()=>import("./LibraryApp-BD1Wtjm7.js"),__vite__mapDeps([31,1,6,7,8,2,3,4,5,32])).then(t=>({default:t.LibraryApp})),defaultSize:{w:1e3,h:650},minSize:{w:550,h:400},singleton:!0,pinned:!0,launchpadOrder:13.5},{id:"reddit",name:"Reddit",icon:"scroll-text",category:"platform",component:()=>z(()=>import("./RedditApp-CVpnnpBP.js"),__vite__mapDeps([33,1,2,3,4,5,32,6,7,8])).then(t=>({default:t.RedditApp})),defaultSize:{w:1e3,h:650},minSize:{w:550,h:400},singleton:!0,pinned:!1,launchpadOrder:14},{id:"youtube-library",name:"YouTube",icon:"play-circle",category:"platform",component:()=>z(()=>import("./YouTubeApp-CAVU-1ZB.js"),__vite__mapDeps([34,1,2,3,4,5,32,7])).then(t=>({default:t.YouTubeApp})),defaultSize:{w:1050,h:700},minSize:{w:600,h:450},singleton:!0,pinned:!1,launchpadOrder:14.5},{id:"github-browser",name:"GitHub",icon:"github",category:"platform",component:()=>z(()=>import("./GitHubApp-B8-CS8Px.js"),__vite__mapDeps([35,1,2,3,4,5,6,7,8])).then(t=>({default:t.GitHubApp})),defaultSize:{w:1e3,h:650},minSize:{w:550,h:400},singleton:!0,pinned:!1,launchpadOrder:15},{id:"x-monitor",name:"X",icon:"at-sign",category:"platform",component:()=>z(()=>import("./XApp-CKMiMFvk.js"),__vite__mapDeps([36,1,2,3,4,5,7])).then(t=>({default:t.XApp})),defaultSize:{w:1e3,h:650},minSize:{w:550,h:400},singleton:!0,pinned:!1,launchpadOrder:15.5},{id:"agent-browsers",name:"Browsers",icon:"globe",category:"platform",component:()=>z(()=>import("./AgentBrowsersApp-Ch7Kx-O4.js"),__vite__mapDeps([37,1,2,3,4,5,7])).then(t=>({default:t.AgentBrowsersApp})),defaultSize:{w:1e3,h:650},minSize:{w:550,h:400},singleton:!0,pinned:!1,launchpadOrder:16},{id:"weather",name:"Weather",icon:"cloud",category:"os",component:()=>z(()=>Promise.resolve().then(()=>Sn),void 0).then(t=>({default:t.WeatherApp})),defaultSize:{w:800,h:600},minSize:{w:400,h:400},singleton:!0,pinned:!1,launchpadOrder:19},{id:"calculator",name:"Calculator",icon:"calculator",category:"os",component:()=>z(()=>import("./CalculatorApp-Chexv_Sm.js"),__vite__mapDeps([38,1,2,3,4,5,39])).then(t=>({default:t.CalculatorApp})),defaultSize:{w:320,h:480},minSize:{w:280,h:400},singleton:!0,pinned:!1,launchpadOrder:20},{id:"calendar",name:"Calendar",icon:"calendar",category:"os",component:()=>z(()=>import("./CalendarApp-DZD5-sDA.js"),__vite__mapDeps([40,1,7])).then(t=>({default:t.CalendarApp})),defaultSize:{w:900,h:600},minSize:{w:600,h:400},singleton:!0,pinned:!1,launchpadOrder:21},{id:"contacts",name:"Contacts",icon:"contact",category:"os",component:()=>z(()=>import("./ContactsApp-DDczp9Hc.js"),__vite__mapDeps([41,1,2,3,4,5,6,7,8])).then(t=>({default:t.ContactsApp})),defaultSize:{w:700,h:500},minSize:{w:400,h:300},singleton:!0,pinned:!1,launchpadOrder:22},{id:"browser",name:"Browser",icon:"globe",category:"os",component:()=>z(()=>import("./BrowserApp-KbremVMB.js"),__vite__mapDeps([42,1,2,3,4,5,7])).then(t=>({default:t.BrowserApp})),defaultSize:{w:1024,h:700},minSize:{w:600,h:400},singleton:!1,pinned:!1,launchpadOrder:23},{id:"media-player",name:"Media Player",icon:"play-circle",category:"os",component:()=>z(()=>import("./MediaPlayerApp-CYFx0qCR.js"),__vite__mapDeps([43,1,44,45])).then(t=>({default:t.MediaPlayerApp})),defaultSize:{w:800,h:500},minSize:{w:400,h:300},singleton:!1,pinned:!1,launchpadOrder:24},{id:"text-editor",name:"Text Editor",icon:"file-text",category:"os",component:()=>z(()=>import("./TextEditorApp-DX1ldFmW.js").then(t=>t.T),__vite__mapDeps([46,1,19,7])).then(t=>({default:t.TextEditorApp})),defaultSize:{w:800,h:550},minSize:{w:400,h:300},singleton:!1,pinned:!1,launchpadOrder:25},{id:"image-viewer",name:"Image Viewer",icon:"eye",category:"os",component:()=>z(()=>import("./ImageViewerApp-IGHKuKLt.js"),__vite__mapDeps([47,1,7])).then(t=>({default:t.ImageViewerApp})),defaultSize:{w:800,h:600},minSize:{w:400,h:300},singleton:!1,pinned:!1,launchpadOrder:26},{id:"terminal",name:"Terminal",icon:"terminal",category:"os",component:()=>z(()=>import("./TerminalApp-BxZkz7_e.js"),__vite__mapDeps([48,1,49,50,2,3,4,5])).then(t=>({default:t.TerminalApp})),defaultSize:{w:800,h:500},minSize:{w:400,h:250},singleton:!1,pinned:!1,launchpadOrder:27},{id:"chess",name:"Chess",icon:"crown",category:"game",component:()=>z(()=>import("./ChessApp--VzQGvct.js"),__vite__mapDeps([51,1,52])).then(t=>({default:t.ChessApp})),defaultSize:{w:700,h:700},minSize:{w:500,h:500},singleton:!0,pinned:!1,launchpadOrder:40},{id:"wordle",name:"Wordle",icon:"spell-check",category:"game",component:()=>z(()=>import("./WordleApp-3FSioJkg.js"),__vite__mapDeps([53,1])).then(t=>({default:t.WordleApp})),defaultSize:{w:500,h:650},minSize:{w:400,h:550},singleton:!0,pinned:!1,launchpadOrder:41},{id:"crosswords",name:"Crosswords",icon:"grid-3x3",category:"game",component:()=>z(()=>import("./CrosswordsApp-C75aS7vj.js"),__vite__mapDeps([54,1])).then(t=>({default:t.CrosswordsApp})),defaultSize:{w:700,h:600},minSize:{w:500,h:450},singleton:!0,pinned:!1,launchpadOrder:42}];function L(t){return st.find(s=>s.id===t)}function rt(){return[...st].sort((t,s)=>t.launchpadOrder-s.launchpadOrder)}function te({icon:t,label:s,value:n,colour:r}){return e.jsxs("div",{className:"flex items-center gap-1 px-1.5 py-0.5 rounded hover:bg-white/5 transition-colors",title:`${s}: ${n!==null?`${Math.round(n)}%`:"—"}`,"aria-label":`${s} usage ${n!==null?`${Math.round(n)} percent`:"unknown"}`,children:[e.jsx("span",{className:"text-shell-text-tertiary",children:t}),e.jsx("div",{className:"relative w-6 h-1 rounded-full bg-white/10 overflow-hidden",children:n!==null&&e.jsx("div",{className:"absolute inset-y-0 left-0 transition-all rounded-full",style:{width:`${Math.min(100,Math.max(0,n))}%`,backgroundColor:r}})})]})}function ne(t){return t===null?"rgba(255,255,255,0.2)":t<50?"#43e97b":t<80?"#febc2e":"#ff5f57"}function it({compact:t=!1}){const[s,n]=o.useState(null),r=_(a=>a.openWindow);o.useEffect(()=>{let a=!1;const u=async()=>{var g,d,f;try{const m=await fetch("/api/system",{headers:{Accept:"application/json"}});if(!m.ok||!(m.headers.get("content-type")??"").includes("application/json"))return;const h=await m.json();if(a)return;const c=h.resources??h,x=h.hardware??h,y=(g=x==null?void 0:x.gpu)==null?void 0:g.type,w=(d=x==null?void 0:x.npu)==null?void 0:d.type;n({cpu_pct:c.cpu_percent??c.cpu_pct??null,ram_pct:c.ram_percent??c.ram_pct??null,ram_mb:c.ram_used_mb??null,vram_pct:c.vram_percent??c.vram_pct??null,vram_mb:c.vram_used_mb??null,vram_total_mb:((f=x==null?void 0:x.gpu)==null?void 0:f.vram_mb)??null,npu_pct:c.npu_percent??c.npu_pct??null,has_gpu:!!(y&&y!=="none"),has_npu:!!(w&&w!=="none")})}catch{}};u();const l=setInterval(u,3e3);return()=>{a=!0,clearInterval(l)}},[]);const i=()=>{const a=L("dashboard");a&&r("dashboard",a.defaultSize)};return s?e.jsxs("button",{onClick:i,className:`flex items-center gap-0.5 ${t?"":"px-1"}`,"aria-label":"Open Dashboard",children:[e.jsx(te,{icon:e.jsx(Ye,{size:11}),label:"CPU",value:s.cpu_pct??null,colour:ne(s.cpu_pct??null)}),e.jsx(te,{icon:e.jsx(jt,{size:11}),label:"RAM",value:s.ram_pct??null,colour:ne(s.ram_pct??null)}),s.has_gpu&&e.jsx(te,{icon:e.jsx(vt,{size:11}),label:"VRAM",value:s.vram_pct??null,colour:ne(s.vram_pct??null)}),s.has_npu&&e.jsx(te,{icon:e.jsx(kt,{size:11}),label:"NPU",value:s.npu_pct??null,colour:ne(s.npu_pct??null)})]}):null}function dn(){const t=_(a=>a.openWindow),s=async()=>{await fetch("/auth/lock",{method:"POST",credentials:"include"}).catch(()=>{}),window.location.reload()},n=()=>{t("settings",{w:760,h:520})},r=()=>{t("settings",{w:760,h:520})},i="flex items-center gap-2.5 w-full px-3 py-2 text-sm rounded-md text-shell-text-secondary hover:bg-shell-surface-hover hover:text-shell-text outline-none focus:bg-shell-surface-hover focus:text-shell-text cursor-pointer select-none transition-colors";return e.jsxs(xt,{children:[e.jsx(ft,{asChild:!0,children:e.jsx("button",{className:"p-1 rounded hover:bg-shell-surface-hover transition-colors text-shell-text-secondary","aria-label":"Power menu",title:"Power",children:e.jsx(St,{size:14})})}),e.jsx(bt,{children:e.jsxs(yt,{align:"end",sideOffset:6,className:"z-50 min-w-[180px] rounded-xl border border-white/10 bg-shell-surface p-1.5 shadow-2xl backdrop-blur-xl",style:{backgroundColor:"rgba(28,26,44,0.96)"},onEscapeKeyDown:()=>{},children:[e.jsxs(Q,{className:i,onSelect:s,children:[e.jsx(Je,{size:14}),e.jsx("span",{className:"flex-1",children:"Lock taOS"}),e.jsx("kbd",{className:"text-[10px] opacity-40 font-mono",children:"⌘L"})]}),e.jsxs(Q,{className:i,onSelect:n,children:[e.jsx(Ke,{size:14}),e.jsx("span",{className:"flex-1",children:"Settings"})]}),e.jsx(wt,{className:"my-1 h-px bg-white/10"}),e.jsxs(Q,{className:i,onSelect:r,children:[e.jsx(Ct,{size:14}),e.jsx("span",{className:"flex-1",children:"Restart server"})]}),e.jsxs(Q,{className:i,onSelect:s,children:[e.jsx(zt,{size:14}),e.jsx("span",{className:"flex-1",children:"Sign out"})]})]})})]})}function un({onSearchOpen:t}){const s=Jt(),{showWidgets:n,toggleWidgets:r}=R(),i=F(u=>u.notifications.filter(l=>!l.read).length),a=F(u=>u.toggleCentre);return e.jsxs("div",{className:"relative flex items-center px-4 shrink-0 select-none",style:{height:"var(--spacing-topbar-h)",backgroundColor:"var(--color-topbar-bg)",borderBottom:"1px solid var(--color-shell-border)"},children:[e.jsxs("div",{className:"flex items-center gap-2",children:[e.jsx("img",{src:"/static/taos-logo.png",alt:"taOS",className:"h-4 w-auto"}),e.jsx("span",{className:"text-xs font-medium text-shell-text-secondary",children:"taOS"})]}),e.jsxs("button",{onClick:t,className:"absolute left-1/2 -translate-x-1/2 flex items-center gap-2 px-3 py-1 rounded-md bg-shell-surface-hover text-shell-text-tertiary text-xs hover:bg-shell-surface-active transition-colors","aria-label":"Search",children:[e.jsx(X,{size:12}),e.jsx("span",{children:"Search"}),e.jsx("kbd",{className:"ml-2 text-[10px] opacity-50",children:"Ctrl+Space"})]}),e.jsxs("div",{className:"flex items-center gap-3 ml-auto",children:[e.jsx(it,{}),e.jsx("span",{className:"text-xs text-shell-text-tertiary",children:s}),e.jsx(dn,{}),e.jsx("button",{onClick:r,className:`p-1 rounded transition-colors ${n?"text-accent bg-accent/10":"text-shell-text-secondary hover:bg-shell-surface-hover"}`,"aria-label":"Toggle widgets",title:"Toggle widgets",children:e.jsx(be,{size:14})}),e.jsxs("button",{onClick:a,className:"relative p-1 rounded hover:bg-shell-surface-hover transition-colors","aria-label":`Notifications${i>0?` (${i} unread)`:""}`,children:[e.jsx(ae,{size:14,className:"text-shell-text-secondary"}),i>0&&e.jsx("span",{className:"absolute top-0 right-0 w-1.5 h-1.5 bg-red-500 rounded-full"})]})]})]})}const B=[{id:"default",label:"Default",image:"url('/static/wallpaper.png')",mobileImage:"url('/static/wallpaper-mobile.png')",fallback:"#1a1b2e"},{id:"deep-indigo",label:"Deep Indigo",image:"linear-gradient(160deg, #1a1b2e 0%, #1e2140 40%, #252848 100%)",fallback:"#1a1b2e"},{id:"midnight",label:"Midnight Blue",image:"linear-gradient(135deg, #0f0c29 0%, #302b63 50%, #24243e 100%)",fallback:"#0f0c29"},{id:"aurora",label:"Aurora",image:"linear-gradient(135deg, #0f2027 0%, #203a43 40%, #2c5364 100%)",fallback:"#0f2027"},{id:"dusk",label:"Dusk",image:"linear-gradient(135deg, #1a1a2e 0%, #16213e 40%, #0f3460 100%)",fallback:"#1a1a2e"},{id:"forest",label:"Forest",image:"linear-gradient(160deg, #0d1b0e 0%, #1a2f1a 40%, #1e3a1e 100%)",fallback:"#0d1b0e"},{id:"ocean",label:"Ocean",image:"linear-gradient(160deg, #0a192f 0%, #0d2847 40%, #112d4e 100%)",fallback:"#0a192f"},{id:"charcoal",label:"Charcoal",image:"linear-gradient(180deg, #1c1c1c 0%, #2d2d2d 100%)",fallback:"#1c1c1c"},{id:"gunmetal",label:"Gunmetal",image:"linear-gradient(165deg, #16181f 0%, #1f232c 50%, #252a35 100%)",fallback:"#16181f"}],M=q(t=>({wallpaperId:"default",wallpaperImage:B[0].image,wallpaperMobileImage:B[0].mobileImage??B[0].image,wallpaperFallback:B[0].fallback,showDesktopIcons:!0,setWallpaper(s){const n=B.find(r=>r.id===s);n&&t({wallpaperId:s,wallpaperImage:n.image,wallpaperMobileImage:n.mobileImage??n.image,wallpaperFallback:n.fallback})},toggleDesktopIcons(){t(s=>({showDesktopIcons:!s.showDesktopIcons}))},getWallpapers:()=>B})),Te=16,Ae=100;function pn(t,s,n){const r=t<=Te,i=t>=n.width-Te,a=s<=n.topBarH+Ae,u=s>=n.height-n.dockH-Ae;return r&&a?"top-left":r&&u?"bottom-left":i&&a?"top-right":i&&u?"bottom-right":r?"left":i?"right":null}function at(t,s){if(!t)return null;const n=s.height-s.topBarH-s.dockH,r=Math.floor(s.width/2),i=Math.floor(n/2);switch(t){case"left":return{x:0,y:0,w:r,h:n};case"right":return{x:r,y:0,w:r,h:n};case"top-left":return{x:0,y:0,w:r,h:i};case"top-right":return{x:r,y:0,w:r,h:i};case"bottom-left":return{x:0,y:i,w:r,h:i};case"bottom-right":return{x:r,y:i,w:r,h:i}}}function hn(t){const[s,n]=o.useState(null),r=o.useCallback((a,u)=>{n(pn(a,u,t))},[t]),i=o.useCallback(()=>{const a=s;return n(null),a},[s]);return{preview:s,previewBounds:at(s,t),onDrag:r,onDragStop:i}}function mn({appId:t,windowId:s}){const n=L(t),r=o.useMemo(()=>n?o.lazy(n.component):null,[n]);return r?e.jsx(o.Suspense,{fallback:e.jsx("div",{className:"flex items-center justify-center h-full text-shell-text-tertiary",children:"Loading..."}),children:e.jsx(r,{windowId:s})}):e.jsxs("div",{className:"flex items-center justify-center h-full text-shell-text-secondary",children:["Unknown app: ",t]})}function gn({win:t,onDrag:s,onDragStop:n}){const{focusWindow:r,closeWindow:i,minimizeWindow:a,maximizeWindow:u,updatePosition:l,updateSize:g,snapWindow:d}=_(),f=L(t.appId),m=o.useRef(null),p={width:window.innerWidth,height:window.innerHeight,topBarH:32,dockH:84};let h=t.position,c=t.size;if(t.maximized)h={x:0,y:0},c={w:p.width,h:p.height-p.topBarH-p.dockH};else if(t.snapped){const k=at(t.snapped,p);k&&(h={x:k.x,y:k.y},c={w:k.w,h:k.h})}const x=o.useCallback(()=>{r(t.id),t.snapped&&(m.current={...t.position,...t.size},d(t.id,null))},[r,d,t.id,t.snapped,t.position,t.size]),y=o.useCallback((k,N)=>{s(N.x,N.y)},[s]),w=o.useCallback((k,N)=>{const C=n();C?(m.current={x:N.x,y:N.y,w:t.size.w,h:t.size.h},d(t.id,C)):l(t.id,N.x,N.y)},[n,d,l,t.id,t.size]),b=o.useCallback((k,N,C)=>{g(t.id,C.offsetWidth,C.offsetHeight)},[g,t.id]);if(t.minimized)return null;const j=(f==null?void 0:f.minSize)??{w:300,h:200};return e.jsx(Gt,{position:{x:h.x,y:h.y},size:{width:c.w,height:c.h},minWidth:j.w,minHeight:j.h,style:{zIndex:t.zIndex},dragHandleClassName:"window-titlebar",disableDragging:t.maximized,enableResizing:!t.maximized&&!t.snapped,onDragStart:x,onDrag:y,onDragStop:w,onResizeStop:b,onMouseDown:()=>r(t.id),bounds:"parent",onContextMenu:k=>k.stopPropagation(),children:e.jsxs("div",{className:`flex flex-col h-full rounded-[var(--spacing-window-radius)] overflow-hidden border ${t.focused?"border-shell-border-strong shadow-[var(--shadow-window)]":"border-shell-border shadow-[var(--shadow-window-unfocused)]"}`,style:{backgroundColor:"var(--color-shell-bg)"},children:[e.jsxs("div",{className:"window-titlebar flex items-center h-8 px-3 shrink-0 bg-shell-surface select-none cursor-default",children:[e.jsxs("div",{className:"flex gap-1.5 items-center group/traffic",children:[e.jsx("button",{className:"w-3 h-3 rounded-full bg-traffic-close hover:brightness-110 flex items-center justify-center",onClick:k=>{k.stopPropagation(),i(t.id)},"aria-label":"Close window",title:"Close",children:e.jsx("svg",{className:"opacity-0 group-hover/traffic:opacity-100 transition-opacity duration-100",width:"7",height:"7",viewBox:"0 0 7 7",style:{color:"rgba(0,0,0,0.55)"},children:e.jsx("path",{d:"M1.5 1.5L5.5 5.5M5.5 1.5L1.5 5.5",stroke:"currentColor",strokeWidth:"1.25",strokeLinecap:"round"})})}),e.jsx("button",{className:"w-3 h-3 rounded-full bg-traffic-minimize hover:brightness-110 flex items-center justify-center",onClick:k=>{k.stopPropagation(),a(t.id)},"aria-label":"Minimize window",title:"Minimize",children:e.jsx("svg",{className:"opacity-0 group-hover/traffic:opacity-100 transition-opacity duration-100",width:"7",height:"7",viewBox:"0 0 7 7",style:{color:"rgba(0,0,0,0.55)"},children:e.jsx("path",{d:"M1 3.5H6",stroke:"currentColor",strokeWidth:"1.25",strokeLinecap:"round"})})}),e.jsx("button",{className:"w-3 h-3 rounded-full bg-traffic-maximize hover:brightness-110 flex items-center justify-center",onClick:k=>{k.stopPropagation(),u(t.id)},"aria-label":t.maximized?"Restore window":"Maximize window",title:t.maximized?"Restore":"Maximize",children:t.maximized?e.jsxs("svg",{className:"opacity-0 group-hover/traffic:opacity-100 transition-opacity duration-100",width:"7",height:"7",viewBox:"0 0 7 7",style:{color:"rgba(0,0,0,0.55)"},children:[e.jsx("path",{d:"M4.5 1V2.5H6M6 2.5L4 4.5",stroke:"currentColor",strokeWidth:"1.1",strokeLinecap:"round",strokeLinejoin:"round",fill:"none"}),e.jsx("path",{d:"M2.5 6V4.5H1M1 4.5L3 2.5",stroke:"currentColor",strokeWidth:"1.1",strokeLinecap:"round",strokeLinejoin:"round",fill:"none"})]}):e.jsxs("svg",{className:"opacity-0 group-hover/traffic:opacity-100 transition-opacity duration-100",width:"7",height:"7",viewBox:"0 0 7 7",style:{color:"rgba(0,0,0,0.55)"},children:[e.jsx("path",{d:"M1 3V1H3M1 1L3 3",stroke:"currentColor",strokeWidth:"1.1",strokeLinecap:"round",strokeLinejoin:"round",fill:"none"}),e.jsx("path",{d:"M6 4V6H4M6 6L4 4",stroke:"currentColor",strokeWidth:"1.1",strokeLinecap:"round",strokeLinejoin:"round",fill:"none"})]})})]}),e.jsx("div",{className:"flex-1 text-center text-xs text-shell-text-secondary truncate",children:(f==null?void 0:f.name)??t.appId}),e.jsx("div",{className:"w-12"})]}),e.jsx("div",{className:"flex-1 overflow-auto bg-shell-bg-deep",children:e.jsx(mn,{appId:t.appId,windowId:t.id})})]})})}function xn({bounds:t}){return t?e.jsx("div",{className:"fixed pointer-events-none z-[9998] rounded-lg border-2 border-dashed transition-all duration-150",style:{left:t.x,top:t.y,width:t.w,height:t.h,backgroundColor:"var(--color-snap-preview)",borderColor:"var(--color-snap-border)"}}):null}const fn=175,bn=290;function yn(t){return t<=fn?"s":t<=bn?"m":"l"}function Y(){const t=o.useRef(null),[s,n]=o.useState({width:200,height:200,tier:"m"});return o.useEffect(()=>{const r=t.current;if(!r)return;const i=(u,l)=>{n({width:u,height:l,tier:yn(l)})};i(r.offsetWidth,r.offsetHeight);const a=new ResizeObserver(u=>{for(const l of u)i(l.contentRect.width,l.contentRect.height)});return a.observe(r),()=>a.disconnect()},[]),[t,s]}function ot(){const[t,s]=o.useState(new Date),[n,{tier:r}]=Y();o.useEffect(()=>{const d=setInterval(()=>s(new Date),1e3);return()=>clearInterval(d)},[]);const i=t.toLocaleTimeString(void 0,{hour:"2-digit",minute:"2-digit"}),a=t.toLocaleTimeString(void 0,{hour:"2-digit",minute:"2-digit",second:"2-digit"}),u=t.toLocaleDateString(void 0,{weekday:"long",year:"numeric",month:"long",day:"numeric"}),l=t.toLocaleDateString(void 0,{weekday:"short",month:"short",day:"numeric"}),g=t.toLocaleDateString(void 0,{weekday:"long"});return e.jsxs("div",{ref:n,style:{display:"flex",flexDirection:"column",alignItems:"center",justifyContent:"center",height:"100%",gap:r==="s"?0:4},"aria-label":"Clock widget",role:"region",children:[r==="s"&&e.jsx("span",{style:{fontSize:"1.8rem",fontWeight:600,fontVariantNumeric:"tabular-nums",color:"rgba(255,255,255,0.95)",lineHeight:1,letterSpacing:"-0.02em"},"aria-live":"polite","aria-label":`Current time: ${i}`,children:i}),r==="m"&&e.jsxs(e.Fragment,{children:[e.jsx("span",{style:{fontSize:"2.4rem",fontWeight:600,fontVariantNumeric:"tabular-nums",color:"rgba(255,255,255,0.95)",lineHeight:1,letterSpacing:"-0.03em"},"aria-live":"polite","aria-label":`Current time: ${a}`,children:a}),e.jsx("span",{style:{fontSize:"0.7rem",color:"rgba(255,255,255,0.45)",letterSpacing:"0.03em",marginTop:4},children:l})]}),r==="l"&&e.jsxs(e.Fragment,{children:[e.jsx("span",{style:{fontSize:"2.8rem",fontWeight:600,fontVariantNumeric:"tabular-nums",color:"rgba(255,255,255,0.95)",lineHeight:1,letterSpacing:"-0.03em"},"aria-live":"polite","aria-label":`Current time: ${a}`,children:a}),e.jsx("span",{style:{fontSize:"0.85rem",fontWeight:600,color:"rgba(255,255,255,0.6)",letterSpacing:"0.08em",textTransform:"uppercase",marginTop:6},children:g}),e.jsx("span",{style:{fontSize:"0.7rem",color:"rgba(255,255,255,0.35)",marginTop:2},children:u})]})]})}function Ee(t){return t==="online"||t==="running"?"#4ade80":t==="offline"||t==="stopped"?"#f87171":"#fbbf24"}function ue({color:t}){return e.jsxs("span",{style:{position:"relative",display:"inline-flex",width:8,height:8,flexShrink:0},"aria-hidden":"true",children:[e.jsx("span",{style:{position:"absolute",inset:0,borderRadius:"50%",background:t,opacity:.4,animation:"ping 1.5s cubic-bezier(0,0,0.2,1) infinite"}}),e.jsx("span",{style:{position:"relative",display:"inline-block",width:8,height:8,borderRadius:"50%",background:t}})]})}function lt(){const[t,s]=o.useState(null),[n,r]=o.useState(!1),[i,{tier:a}]=Y();o.useEffect(()=>{let m=!1;async function p(){try{const c=await fetch("/api/agents",{headers:{Accept:"application/json"}});if(!c.ok)throw new Error("Failed");if(!(c.headers.get("content-type")??"").includes("application/json")){m||(s([]),r(!1));return}const y=await c.json();if(!m){const w=Array.isArray(y)?y:y.agents??y.items??[];s(w.map(b=>({name:b.name??b.id??"Unknown",status:b.status??"unknown",emoji:typeof b.emoji=="string"?b.emoji:void 0,framework:typeof b.framework=="string"?b.framework:void 0}))),r(!1)}}catch{m||r(!0)}}p();const h=setInterval(p,15e3);return()=>{m=!0,clearInterval(h)}},[]);const u=t?t.filter(m=>m.status==="running"||m.status==="online").length:0,l=t?t.length:0,g=u>0?"#4ade80":"#fbbf24",d={fontSize:"0.65rem",color:"rgba(255,255,255,0.35)"},f={fontSize:"0.65rem",fontWeight:600,color:"rgba(255,255,255,0.4)",textTransform:"uppercase",letterSpacing:"0.06em"};return e.jsxs("div",{ref:i,style:{height:"100%",display:"flex",flexDirection:"column",padding:a==="s"?"0 2px":"2px 2px 4px",overflow:"hidden"},"aria-label":"Agent status widget",role:"region",children:[a==="s"&&e.jsxs("div",{style:{display:"flex",alignItems:"center",justifyContent:"center",height:"100%",gap:8},children:[e.jsx(ue,{color:g}),e.jsx("span",{style:{fontSize:"1.2rem",fontWeight:600,color:"rgba(255,255,255,0.9)",fontVariantNumeric:"tabular-nums"},children:n||!t?"—":l}),e.jsx("span",{style:{fontSize:"0.7rem",color:"rgba(255,255,255,0.45)"},children:l===1?"agent":"agents"})]}),a==="m"&&e.jsxs(e.Fragment,{children:[e.jsx("div",{style:f,children:"Agents"}),e.jsxs("div",{style:{display:"flex",alignItems:"baseline",gap:6,margin:"4px 0 8px"},children:[e.jsx("span",{style:{fontSize:"1.6rem",fontWeight:600,color:"rgba(255,255,255,0.95)",fontVariantNumeric:"tabular-nums",lineHeight:1},children:n||!t?"—":l}),!n&&t&&e.jsxs("span",{style:{fontSize:"0.7rem",color:"rgba(255,255,255,0.4)"},children:[u," running"]})]}),!n&&t&&t.slice(0,2).map(m=>e.jsxs("div",{style:{display:"flex",alignItems:"center",gap:6,fontSize:"0.78rem",color:"rgba(255,255,255,0.8)",marginBottom:4},children:[e.jsx(ue,{color:Ee(m.status)}),e.jsx("span",{"aria-hidden":"true",style:{fontSize:"0.95rem",lineHeight:1},children:ze(m.emoji,m.framework)}),e.jsx("span",{style:{overflow:"hidden",textOverflow:"ellipsis",whiteSpace:"nowrap",flex:1},children:m.name}),e.jsx("span",{style:d,children:m.status})]},m.name)),n&&e.jsx("span",{style:{fontSize:"0.75rem",color:"rgba(255,255,255,0.35)"},children:"Unavailable"}),!t&&!n&&e.jsx("span",{style:{fontSize:"0.75rem",color:"rgba(255,255,255,0.35)"},children:"Loading…"})]}),a==="l"&&e.jsxs(e.Fragment,{children:[e.jsx("div",{style:f,children:"Agents"}),e.jsxs("div",{style:{display:"flex",alignItems:"baseline",gap:6,margin:"4px 0 10px"},children:[e.jsx("span",{style:{fontSize:"1.8rem",fontWeight:600,color:"rgba(255,255,255,0.95)",fontVariantNumeric:"tabular-nums",lineHeight:1},children:n||!t?"—":l}),!n&&t&&e.jsxs("span",{style:{fontSize:"0.75rem",color:"rgba(255,255,255,0.4)"},children:[u," running · ",l-u," idle"]})]}),n||!t?e.jsx("span",{style:{fontSize:"0.75rem",color:"rgba(255,255,255,0.35)"},children:n?"Agents unavailable":"Loading…"}):t.length===0?e.jsx("span",{style:{fontSize:"0.75rem",color:"rgba(255,255,255,0.35)"},children:"No agents configured"}):e.jsx("div",{style:{display:"flex",flexDirection:"column",gap:5,overflowY:"auto",flex:1},children:t.map(m=>e.jsxs("div",{style:{display:"flex",alignItems:"center",gap:8,fontSize:"0.8rem",color:"rgba(255,255,255,0.85)"},children:[e.jsx(ue,{color:Ee(m.status)}),e.jsx("span",{"aria-hidden":"true",style:{fontSize:"0.95rem",lineHeight:1},children:ze(m.emoji,m.framework)}),e.jsx("span",{style:{overflow:"hidden",textOverflow:"ellipsis",whiteSpace:"nowrap",flex:1},children:m.name}),e.jsx("span",{style:{...d,background:"rgba(255,255,255,0.06)",borderRadius:4,padding:"1px 6px",whiteSpace:"nowrap"},children:m.status})]},m.name))})]})]})}const Ie="tinyagentos-quick-notes";function ct(){const[t,s]=o.useState(()=>{try{return localStorage.getItem(Ie)??""}catch{return""}}),[n,{tier:r}]=Y(),i=o.useCallback(u=>{const l=u.target.value;s(l);try{localStorage.setItem(Ie,l)}catch{}},[]),a=r!=="s";return e.jsxs("div",{ref:n,style:{height:"100%",display:"flex",flexDirection:"column",padding:r==="s"?"2px":"2px 2px 4px"},"aria-label":"Quick notes widget",role:"region",children:[a&&e.jsx("div",{style:{fontSize:"0.65rem",fontWeight:600,color:"rgba(255,255,255,0.4)",textTransform:"uppercase",letterSpacing:"0.06em",marginBottom:5},children:"Quick Notes"}),e.jsx("textarea",{value:t,onChange:i,placeholder:r==="s"?"Notes…":"Type your notes here…","aria-label":"Quick notes",style:{flex:1,resize:"none",background:"rgba(255,255,255,0.05)",border:"1px solid rgba(255,255,255,0.08)",borderRadius:8,color:"rgba(255,255,255,0.85)",fontSize:r==="s"?"0.75rem":"0.8rem",padding:r==="s"?"6px 8px":"8px 10px",outline:"none",fontFamily:"inherit",lineHeight:1.55,transition:"border-color 0.15s, background 0.15s",caretColor:"rgba(255,255,255,0.7)"},onFocus:u=>{u.currentTarget.style.borderColor="rgba(255,255,255,0.2)",u.currentTarget.style.background="rgba(255,255,255,0.07)"},onBlur:u=>{u.currentTarget.style.borderColor="rgba(255,255,255,0.08)",u.currentTarget.style.background="rgba(255,255,255,0.05)"}})]})}function dt(t){return t>=80?"#f87171":t>=50?"#fbbf24":"#4ade80"}function se({label:t,value:s}){const n=dt(s);return e.jsxs("div",{style:{display:"flex",flexDirection:"column",gap:4},children:[e.jsxs("div",{style:{display:"flex",justifyContent:"space-between",fontSize:"0.72rem",color:"rgba(255,255,255,0.65)"},children:[e.jsx("span",{children:t}),e.jsxs("span",{style:{fontVariantNumeric:"tabular-nums",fontWeight:600,color:"rgba(255,255,255,0.85)"},children:[Math.round(s),"%"]})]}),e.jsx("div",{style:{height:5,borderRadius:3,background:"rgba(255,255,255,0.08)",overflow:"hidden"},role:"progressbar","aria-label":`${t} usage`,"aria-valuenow":Math.round(s),"aria-valuemin":0,"aria-valuemax":100,children:e.jsx("div",{style:{height:"100%",width:`${Math.min(100,Math.max(0,s))}%`,borderRadius:3,background:n,transition:"width 0.4s ease, background 0.4s ease",boxShadow:`0 0 6px ${n}66`}})})]})}function Le({label:t,value:s}){const n=dt(s),r=18,i=2*Math.PI*r,u=Math.min(100,Math.max(0,s))/100*i;return e.jsxs("div",{style:{display:"flex",flexDirection:"column",alignItems:"center",gap:3,flex:1},children:[e.jsxs("div",{style:{position:"relative",width:48,height:48},children:[e.jsxs("svg",{width:"48",height:"48",viewBox:"0 0 48 48","aria-hidden":"true",children:[e.jsx("circle",{cx:"24",cy:"24",r,fill:"none",stroke:"rgba(255,255,255,0.08)",strokeWidth:"4"}),e.jsx("circle",{cx:"24",cy:"24",r,fill:"none",stroke:n,strokeWidth:"4",strokeDasharray:`${u} ${i-u}`,strokeLinecap:"round",transform:"rotate(-90 24 24)",style:{transition:"stroke-dasharray 0.4s ease, stroke 0.4s ease",filter:`drop-shadow(0 0 3px ${n}99)`}})]}),e.jsx("span",{style:{position:"absolute",inset:0,display:"flex",alignItems:"center",justifyContent:"center",fontSize:"0.65rem",fontWeight:600,color:"rgba(255,255,255,0.85)",fontVariantNumeric:"tabular-nums"},children:Math.round(s)})]}),e.jsx("span",{style:{fontSize:"0.6rem",fontWeight:600,color:"rgba(255,255,255,0.4)",textTransform:"uppercase",letterSpacing:"0.06em"},children:t})]})}async function pe(t){try{const s=await fetch(t,{headers:{Accept:"application/json"}});return!s.ok||!(s.headers.get("content-type")??"").includes("application/json")?null:await s.json()}catch{return null}}function ut(){const[t,s]=o.useState(null),[n,r]=o.useState(!1),[i,{tier:a}]=Y();o.useEffect(()=>{let d=!1;async function f(){var w,b;const p=await pe("/api/system");if(p!=null&&p.resources){if(d)return;s({cpu:p.resources.cpu_percent??0,ram:p.resources.ram_percent??0}),r(!1);return}const[h,c]=await Promise.all([pe("/api/metrics/system.cpu_pct?range=1h"),pe("/api/metrics/system.ram_pct?range=1h")]);if(d)return;const x=Array.isArray(h)&&h.length>0?((w=h[h.length-1])==null?void 0:w.value)??null:null,y=Array.isArray(c)&&c.length>0?((b=c[c.length-1])==null?void 0:b.value)??null:null;if(x===null&&y===null){r(!0);return}s({cpu:x??0,ram:y??0}),r(!1)}f();const m=setInterval(f,5e3);return()=>{d=!0,clearInterval(m)}},[]);const u={fontSize:"0.65rem",fontWeight:600,color:"rgba(255,255,255,0.4)",textTransform:"uppercase",letterSpacing:"0.06em"},l=n||!t,g=n?"Stats unavailable":"Loading…";return e.jsxs("div",{ref:i,style:{height:"100%",display:"flex",flexDirection:"column",padding:a==="s"?"0 4px":"2px 4px 6px",overflow:"hidden"},"aria-label":"System stats widget",role:"region",children:[a==="s"&&e.jsx("div",{style:{display:"flex",alignItems:"center",justifyContent:"center",height:"100%",gap:16},children:l?e.jsx("span",{style:{fontSize:"0.7rem",color:"rgba(255,255,255,0.35)"},children:g}):e.jsxs(e.Fragment,{children:[e.jsx(Le,{label:"CPU",value:t.cpu}),e.jsx(Le,{label:"RAM",value:t.ram})]})}),a==="m"&&e.jsxs(e.Fragment,{children:[e.jsx("div",{style:u,children:"System"}),e.jsx("div",{style:{flex:1,display:"flex",flexDirection:"column",justifyContent:"center",gap:10,marginTop:8},children:l?e.jsx("span",{style:{fontSize:"0.75rem",color:"rgba(255,255,255,0.35)"},children:g}):e.jsxs(e.Fragment,{children:[e.jsx(se,{label:"CPU",value:t.cpu}),e.jsx(se,{label:"RAM",value:t.ram})]})})]}),a==="l"&&e.jsxs(e.Fragment,{children:[e.jsx("div",{style:u,children:"System"}),e.jsx("div",{style:{flex:1,display:"flex",flexDirection:"column",justifyContent:"center",gap:12,marginTop:10},children:l?e.jsx("span",{style:{fontSize:"0.75rem",color:"rgba(255,255,255,0.35)"},children:g}):e.jsxs(e.Fragment,{children:[e.jsx(se,{label:"CPU",value:t.cpu}),e.jsx(se,{label:"RAM",value:t.ram})]})}),e.jsx("div",{style:{display:"flex",gap:8,marginTop:6},children:!l&&e.jsxs(e.Fragment,{children:[e.jsxs("div",{style:{flex:1,background:"rgba(255,255,255,0.04)",borderRadius:8,padding:"6px 8px"},children:[e.jsx("div",{style:{fontSize:"0.6rem",color:"rgba(255,255,255,0.35)",textTransform:"uppercase",letterSpacing:"0.05em",marginBottom:2},children:"CPU"}),e.jsxs("div",{style:{fontSize:"1rem",fontWeight:600,color:"rgba(255,255,255,0.9)",fontVariantNumeric:"tabular-nums"},children:[Math.round(t.cpu),"%"]})]}),e.jsxs("div",{style:{flex:1,background:"rgba(255,255,255,0.04)",borderRadius:8,padding:"6px 8px"},children:[e.jsx("div",{style:{fontSize:"0.6rem",color:"rgba(255,255,255,0.35)",textTransform:"uppercase",letterSpacing:"0.05em",marginBottom:2},children:"RAM"}),e.jsxs("div",{style:{fontSize:"1rem",fontWeight:600,color:"rgba(255,255,255,0.9)",fontVariantNumeric:"tabular-nums"},children:[Math.round(t.ram),"%"]})]})]})})]})]})}const wn={0:{label:"Clear sky",icon:"☀️"},1:{label:"Mainly clear",icon:"🌤"},2:{label:"Partly cloudy",icon:"⛅"},3:{label:"Overcast",icon:"☁️"},45:{label:"Fog",icon:"🌫"},48:{label:"Rime fog",icon:"🌫"},51:{label:"Light drizzle",icon:"🌦"},53:{label:"Drizzle",icon:"🌦"},55:{label:"Heavy drizzle",icon:"🌧"},61:{label:"Light rain",icon:"🌦"},63:{label:"Rain",icon:"🌧"},65:{label:"Heavy rain",icon:"🌧"},71:{label:"Light snow",icon:"🌨"},73:{label:"Snow",icon:"🌨"},75:{label:"Heavy snow",icon:"❄️"},77:{label:"Snow grains",icon:"🌨"},80:{label:"Rain showers",icon:"🌦"},81:{label:"Rain showers",icon:"🌧"},82:{label:"Heavy showers",icon:"⛈"},85:{label:"Snow showers",icon:"🌨"},86:{label:"Heavy snow showers",icon:"❄️"},95:{label:"Thunderstorm",icon:"⛈"},96:{label:"Thunderstorm + hail",icon:"⛈"},99:{label:"Severe thunderstorm",icon:"⛈"}};function We(t,s=!0){const n=wn[t]??{label:"Unknown",icon:"🌤"};return(t===0||t===1)&&!s?{...n,icon:"🌙"}:n}const pt="weather",we="taos-pref:weather";function je(){try{const t=localStorage.getItem(we);return t?JSON.parse(t):{}}catch{return{}}}function K(){return je().home??null}function oe(){return je().tempUnit==="F"?"F":"C"}function le(){return je().windUnit==="mph"?"mph":"kmh"}function V(t){return Math.round(t*9/5+32)}function ve(t){return Math.round(t*.621371)}const ce="taos-weather-units-changed";function he(){window.dispatchEvent(new Event(ce))}async function jn(t){if(!t.trim())return[];try{const s=await fetch(`https://geocoding-api.open-meteo.com/v1/search?name=${encodeURIComponent(t)}&count=10&language=en&format=json`);return s.ok?((await s.json()).results??[]).map(r=>({name:r.name,country:r.country,admin1:r.admin1,latitude:r.latitude,longitude:r.longitude})):[]}catch{return[]}}async function vn(t){const s=new URLSearchParams({latitude:String(t.latitude),longitude:String(t.longitude),current:"temperature_2m,apparent_temperature,is_day,weather_code,relative_humidity_2m,wind_speed_10m,wind_direction_10m",daily:"weather_code,temperature_2m_max,temperature_2m_min,precipitation_sum",timezone:"auto",forecast_days:"7"}),n=await fetch(`https://api.open-meteo.com/v1/forecast?${s}`);if(!n.ok)return null;const r=await n.json(),i={temperature:Math.round(r.current.temperature_2m),feelsLike:Math.round(r.current.apparent_temperature),weatherCode:r.current.weather_code,humidity:r.current.relative_humidity_2m,windSpeed:Math.round(r.current.wind_speed_10m),windDirection:r.current.wind_direction_10m,isDay:r.current.is_day===1},a=r.daily.time.map((u,l)=>({date:u,tempMax:Math.round(r.daily.temperature_2m_max[l]),tempMin:Math.round(r.daily.temperature_2m_min[l]),weatherCode:r.daily.weather_code[l],precipitation:r.daily.precipitation_sum[l]}));return{current:i,daily:a}}async function me(t){try{localStorage.setItem(we,JSON.stringify(t))}catch{}try{await fetch(`/api/preferences/${pt}`,{method:"PUT",headers:{"Content-Type":"application/json"},body:JSON.stringify(t)})}catch{}}function kn(){const[t,s]=o.useState(K),[n,r]=o.useState(t),[i,a]=o.useState(""),[u,l]=o.useState([]),[g,d]=o.useState(!1),[f,m]=o.useState(null),[p,h]=o.useState(!1),[c,x]=o.useState(oe),[y,w]=o.useState(le);o.useEffect(()=>{let v=!1;return(async()=>{try{const W=await fetch(`/api/preferences/${pt}`);if(!W.ok)return;const T=await W.json();if(v||!T||Object.keys(T).length===0)return;T.home&&(s(T.home),r(O=>O??T.home??null)),(T.tempUnit==="C"||T.tempUnit==="F")&&x(T.tempUnit),(T.windUnit==="kmh"||T.windUnit==="mph")&&w(T.windUnit),localStorage.setItem(we,JSON.stringify(T)),he()}catch{}})(),()=>{v=!0}},[]);const b=o.useCallback(()=>{const v=c==="C"?"F":"C";x(v),me({home:t,tempUnit:v,windUnit:y}),he()},[c,t,y]),j=o.useCallback(()=>{const v=y==="kmh"?"mph":"kmh";w(v),me({home:t,tempUnit:c,windUnit:v}),he()},[y,t,c]),k=o.useCallback(async v=>{h(!0);const W=await vn(v);m(W),h(!1)},[]);o.useEffect(()=>{n&&k(n)},[n,k]),o.useEffect(()=>{if(!i.trim()){l([]);return}let v=!1;d(!0);const W=setTimeout(async()=>{const T=await jn(i);v||(l(T),d(!1))},300);return()=>{v=!0,clearTimeout(W)}},[i]);const N=v=>{r(v),a(""),l([])},C=v=>{s(v),me({home:v,tempUnit:c,windUnit:y})},A=f?We(f.current.weatherCode,f.current.isDay):null,E=n&&t&&n.latitude===t.latitude&&n.longitude===t.longitude;return e.jsxs("div",{style:{height:"100%",display:"flex",flexDirection:"column",background:"linear-gradient(160deg, #1a2a4a 0%, #0e1a36 100%)",color:"white",overflow:"hidden"},children:[e.jsx("div",{style:{padding:16,flexShrink:0,borderBottom:"1px solid rgba(255,255,255,0.05)"},children:e.jsxs("div",{style:{position:"relative"},children:[e.jsx(X,{size:16,style:{position:"absolute",left:12,top:12,color:"rgba(255,255,255,0.4)"}}),e.jsx("input",{value:i,onChange:v=>a(v.target.value),placeholder:"Search for a town or city...",style:{width:"100%",padding:"10px 12px 10px 36px",background:"rgba(255,255,255,0.08)",border:"1px solid rgba(255,255,255,0.1)",borderRadius:10,color:"white",fontSize:14,outline:"none"}}),u.length>0&&e.jsx("div",{style:{position:"absolute",top:"100%",left:0,right:0,marginTop:4,background:"rgba(15,20,40,0.98)",backdropFilter:"blur(20px)",border:"1px solid rgba(255,255,255,0.1)",borderRadius:10,maxHeight:280,overflowY:"auto",zIndex:10},children:u.map((v,W)=>e.jsxs("button",{onClick:()=>N(v),style:{width:"100%",padding:"10px 14px",textAlign:"left",background:"none",border:"none",color:"white",fontSize:13,display:"flex",alignItems:"center",gap:10,cursor:"pointer"},onMouseEnter:T=>T.currentTarget.style.background="rgba(255,255,255,0.06)",onMouseLeave:T=>T.currentTarget.style.background="none",children:[e.jsx(Ce,{size:14,style:{color:"rgba(255,255,255,0.4)"}}),e.jsxs("span",{style:{flex:1},children:[e.jsx("span",{style:{color:"rgba(255,255,255,0.9)"},children:v.name}),e.jsxs("span",{style:{color:"rgba(255,255,255,0.4)",marginLeft:6},children:[v.admin1?`${v.admin1}, `:"",v.country]})]})]},`${v.latitude}-${v.longitude}-${W}`))}),g&&i&&u.length===0&&e.jsx("div",{style:{position:"absolute",top:"100%",left:0,right:0,marginTop:4,padding:"12px 14px",background:"rgba(15,20,40,0.98)",backdropFilter:"blur(20px)",border:"1px solid rgba(255,255,255,0.1)",borderRadius:10,fontSize:13,color:"rgba(255,255,255,0.5)"},children:"Searching..."})]})}),e.jsxs("div",{style:{flex:1,overflowY:"auto",padding:20},children:[!n&&e.jsxs("div",{style:{display:"flex",flexDirection:"column",alignItems:"center",justifyContent:"center",height:"100%",gap:12,color:"rgba(255,255,255,0.5)"},children:[e.jsx(Ce,{size:48,style:{color:"rgba(255,255,255,0.2)"}}),e.jsx("p",{style:{fontSize:15},children:"Search for a location to see its weather"})]}),n&&p&&!f&&e.jsx("div",{style:{textAlign:"center",color:"rgba(255,255,255,0.5)",marginTop:40},children:"Loading forecast..."}),n&&f&&A&&e.jsxs(e.Fragment,{children:[e.jsxs("div",{style:{display:"flex",alignItems:"center",justifyContent:"space-between",marginBottom:20},children:[e.jsxs("div",{children:[e.jsx("h1",{style:{fontSize:24,fontWeight:600,margin:0,color:"rgba(255,255,255,0.95)"},children:n.name}),e.jsxs("p",{style:{fontSize:13,color:"rgba(255,255,255,0.5)",margin:"2px 0 0"},children:[n.admin1?`${n.admin1}, `:"",n.country]})]}),e.jsx("button",{onClick:()=>C(n),disabled:!!E,style:{display:"flex",alignItems:"center",gap:6,padding:"8px 14px",background:E?"rgba(80,200,120,0.2)":"rgba(255,255,255,0.08)",border:`1px solid ${E?"rgba(80,200,120,0.3)":"rgba(255,255,255,0.12)"}`,borderRadius:8,color:E?"rgb(150,220,170)":"rgba(255,255,255,0.85)",fontSize:12,fontWeight:500,cursor:E?"default":"pointer"},children:E?e.jsxs(e.Fragment,{children:[e.jsx(Xe,{size:14})," Home"]}):e.jsxs(e.Fragment,{children:[e.jsx(Nt,{size:14})," Set as home"]})})]}),e.jsxs("div",{style:{display:"flex",alignItems:"center",gap:16,marginBottom:28,padding:"16px 20px",background:"rgba(255,255,255,0.05)",borderRadius:16,border:"1px solid rgba(255,255,255,0.08)"},children:[e.jsx("div",{style:{fontSize:72,lineHeight:1},children:A.icon}),e.jsxs("div",{style:{flex:1},children:[e.jsxs("button",{onClick:b,title:"Tap to toggle °C / °F",style:{display:"flex",alignItems:"baseline",gap:8,background:"none",border:"none",padding:0,cursor:"pointer",color:"inherit"},children:[e.jsxs("span",{style:{fontSize:56,fontWeight:300,lineHeight:1,color:"rgba(255,255,255,0.95)"},children:[c==="C"?f.current.temperature:V(f.current.temperature),"°"]}),e.jsx("span",{style:{fontSize:18,color:"rgba(255,255,255,0.5)"},children:c})]}),e.jsx("p",{style:{fontSize:14,color:"rgba(255,255,255,0.7)",margin:"4px 0 0"},children:A.label}),e.jsxs("p",{style:{fontSize:12,color:"rgba(255,255,255,0.45)",margin:"2px 0 0"},children:["Feels like ",c==="C"?f.current.feelsLike:V(f.current.feelsLike),"°"]})]})]}),e.jsxs("div",{style:{display:"grid",gridTemplateColumns:"repeat(auto-fit, minmax(140px, 1fr))",gap:10,marginBottom:28},children:[e.jsxs("div",{style:{padding:14,background:"rgba(255,255,255,0.05)",borderRadius:12,border:"1px solid rgba(255,255,255,0.06)"},children:[e.jsx("div",{style:{fontSize:10,textTransform:"uppercase",letterSpacing:.5,color:"rgba(255,255,255,0.4)"},children:"Humidity"}),e.jsxs("div",{style:{fontSize:20,fontWeight:600,marginTop:4},children:[f.current.humidity,"%"]})]}),e.jsxs("button",{onClick:j,title:"Tap to toggle km/h / mph",style:{padding:14,background:"rgba(255,255,255,0.05)",borderRadius:12,border:"1px solid rgba(255,255,255,0.06)",textAlign:"left",cursor:"pointer",color:"inherit"},children:[e.jsx("div",{style:{fontSize:10,textTransform:"uppercase",letterSpacing:.5,color:"rgba(255,255,255,0.4)"},children:"Wind"}),e.jsxs("div",{style:{fontSize:20,fontWeight:600,marginTop:4},children:[y==="kmh"?f.current.windSpeed:ve(f.current.windSpeed),e.jsx("span",{style:{fontSize:13,color:"rgba(255,255,255,0.5)",marginLeft:4,fontWeight:400},children:y==="kmh"?"km/h":"mph"})]})]})]}),e.jsxs("div",{children:[e.jsx("h2",{style:{fontSize:11,textTransform:"uppercase",letterSpacing:.8,color:"rgba(255,255,255,0.45)",margin:"0 0 10px",fontWeight:600},children:"7-Day Forecast"}),e.jsx("div",{style:{background:"rgba(255,255,255,0.04)",borderRadius:14,border:"1px solid rgba(255,255,255,0.06)",overflow:"hidden"},children:f.daily.map((v,W)=>{const T=We(v.weatherCode),O=new Date(v.date),$=W===0?"Today":O.toLocaleDateString("en",{weekday:"short"});return e.jsxs("div",{style:{display:"flex",alignItems:"center",gap:14,padding:"12px 16px",borderTop:W===0?"none":"1px solid rgba(255,255,255,0.05)"},children:[e.jsx("span",{style:{width:52,fontSize:13,color:"rgba(255,255,255,0.8)",fontWeight:500},children:$}),e.jsx("span",{style:{fontSize:22,width:32,textAlign:"center"},children:T.icon}),e.jsx("span",{style:{flex:1,fontSize:12,color:"rgba(255,255,255,0.55)"},children:T.label}),e.jsxs("span",{style:{fontSize:13,color:"rgba(255,255,255,0.5)",width:36,textAlign:"right"},children:[c==="C"?v.tempMin:V(v.tempMin),"°"]}),e.jsxs("span",{style:{fontSize:13,color:"rgba(255,255,255,0.9)",width:36,textAlign:"right",fontWeight:500},children:[c==="C"?v.tempMax:V(v.tempMax),"°"]})]},v.date)})})]})]})]})]})}const Sn=Object.freeze(Object.defineProperty({__proto__:null,UNIT_CHANGED_EVENT:ce,WeatherApp:kn,cToF:V,getHomeLocation:K,getTempUnit:oe,getWindUnit:le,kmhToMph:ve},Symbol.toStringTag,{value:"Module"})),Cn={0:{label:"Clear",icon:"☀️"},1:{label:"Mainly clear",icon:"🌤"},2:{label:"Partly cloudy",icon:"⛅"},3:{label:"Overcast",icon:"☁️"},45:{label:"Fog",icon:"🌫"},48:{label:"Fog",icon:"🌫"},51:{label:"Drizzle",icon:"🌦"},53:{label:"Drizzle",icon:"🌦"},55:{label:"Drizzle",icon:"🌧"},61:{label:"Light rain",icon:"🌦"},63:{label:"Rain",icon:"🌧"},65:{label:"Heavy rain",icon:"🌧"},71:{label:"Light snow",icon:"🌨"},73:{label:"Snow",icon:"🌨"},75:{label:"Heavy snow",icon:"❄️"},80:{label:"Showers",icon:"🌦"},81:{label:"Showers",icon:"🌧"},82:{label:"Heavy showers",icon:"⛈"},95:{label:"Thunderstorm",icon:"⛈"},96:{label:"Thunderstorm",icon:"⛈"},99:{label:"Thunderstorm",icon:"⛈"}};function zn(t,s=!0){const n=Cn[t]??{label:"Unknown",icon:"🌤"};return(t===0||t===1)&&!s?{...n,icon:"🌙"}:n}async function Nn(){const t=K();if(!t)return null;try{const s=new URLSearchParams({latitude:String(t.latitude),longitude:String(t.longitude),current:"temperature_2m,apparent_temperature,is_day,weather_code,relative_humidity_2m,wind_speed_10m",timezone:"auto"}),n=await fetch(`https://api.open-meteo.com/v1/forecast?${s}`,{signal:AbortSignal.timeout(5e3)});if(!n.ok)return null;const r=await n.json(),i=zn(r.current.weather_code,r.current.is_day===1);return{temp:Math.round(r.current.temperature_2m),feelsLike:Math.round(r.current.apparent_temperature),condition:i.label,icon:i.icon,humidity:r.current.relative_humidity_2m,wind:Math.round(r.current.wind_speed_10m),location:t.name}}catch{return null}}function ht(){const[t,s]=o.useState(null),[n,r]=o.useState(!K()),[i,a]=o.useState(oe),[u,l]=o.useState(le),[g,{tier:d}]=Y();o.useEffect(()=>{const p=()=>{const w=K();r(!w),w&&Nn().then(s)};(async()=>{try{const w=await fetch("/api/preferences/weather");if(!w.ok){p();return}const b=await w.json();b&&typeof b=="object"&&Object.keys(b).length>0&&(localStorage.setItem("taos-pref:weather",JSON.stringify(b)),(b.tempUnit==="C"||b.tempUnit==="F")&&a(b.tempUnit),(b.windUnit==="kmh"||b.windUnit==="mph")&&l(b.windUnit))}catch{}p()})();const c=setInterval(p,6e5),x=()=>p(),y=()=>{a(oe()),l(le())};return window.addEventListener("storage",x),window.addEventListener(ce,y),()=>{clearInterval(c),window.removeEventListener("storage",x),window.removeEventListener(ce,y)}},[]);const f=p=>i==="C"?p:V(p),m=p=>u==="kmh"?`${p} km/h`:`${ve(p)} mph`;return n?e.jsxs("div",{ref:g,style:{display:"flex",flexDirection:"column",alignItems:"center",justifyContent:"center",height:"100%",gap:6,padding:8,textAlign:"center"},"aria-label":"Weather widget — no location set",role:"region",children:[e.jsx("span",{style:{fontSize:d==="s"?20:28,lineHeight:1},children:"🌤"}),d!=="s"&&e.jsx("span",{style:{fontSize:"0.72rem",color:"rgba(255,255,255,0.45)"},children:"Tap to set location"})]}):t?e.jsxs("div",{ref:g,style:{height:"100%",display:"flex",flexDirection:"column",padding:d==="s"?"0 4px":"2px 4px 6px",overflow:"hidden"},"aria-label":`Weather: ${t.condition}, ${f(t.temp)}°${i} in ${t.location}`,role:"region",children:[d==="s"&&e.jsxs("div",{style:{display:"flex",flexDirection:"column",justifyContent:"space-between",alignItems:"center",height:"100%",padding:"4px 2px"},children:[e.jsxs("div",{style:{display:"flex",alignItems:"center",gap:8},children:[e.jsx("span",{style:{fontSize:"1.8rem",lineHeight:1},children:t.icon}),e.jsxs("span",{style:{fontSize:"1.6rem",fontWeight:600,color:"rgba(255,255,255,0.95)",lineHeight:1,fontVariantNumeric:"tabular-nums"},children:[f(t.temp),"°"]})]}),e.jsxs("div",{style:{display:"flex",gap:8,fontSize:"0.65rem",color:"rgba(255,255,255,0.4)"},children:[e.jsxs("span",{children:["💧 ",t.humidity,"%"]}),e.jsxs("span",{children:["💨 ",m(t.wind)]})]})]}),d==="m"&&e.jsxs("div",{style:{display:"flex",flexDirection:"column",justifyContent:"space-between",height:"100%"},children:[e.jsx("div",{style:{display:"flex",alignItems:"flex-start",justifyContent:"space-between"},children:e.jsxs("div",{style:{display:"flex",alignItems:"center",gap:8},children:[e.jsx("span",{style:{fontSize:"2.2rem",lineHeight:1},children:t.icon}),e.jsxs("div",{children:[e.jsxs("div",{style:{fontSize:"1.8rem",fontWeight:600,color:"rgba(255,255,255,0.95)",lineHeight:1,fontVariantNumeric:"tabular-nums"},children:[f(t.temp),"°",e.jsx("span",{style:{fontSize:"0.85rem",fontWeight:400,color:"rgba(255,255,255,0.4)",marginLeft:1},children:i})]}),e.jsx("div",{style:{fontSize:"0.72rem",color:"rgba(255,255,255,0.5)",marginTop:2},children:t.condition})]})]})}),e.jsxs("div",{style:{display:"flex",gap:10,fontSize:"0.7rem",color:"rgba(255,255,255,0.4)"},children:[e.jsxs("span",{children:["Feels ",f(t.feelsLike),"°"]}),e.jsxs("span",{children:["💧 ",t.humidity,"%"]}),e.jsxs("span",{children:["💨 ",m(t.wind)]})]}),e.jsx("div",{style:{fontSize:"0.68rem",color:"rgba(255,255,255,0.35)",textTransform:"uppercase",letterSpacing:"0.04em",overflow:"hidden",textOverflow:"ellipsis",whiteSpace:"nowrap"},children:t.location})]}),d==="l"&&e.jsxs("div",{style:{display:"flex",flexDirection:"column",justifyContent:"space-between",height:"100%"},children:[e.jsx("div",{style:{fontSize:"0.65rem",fontWeight:600,color:"rgba(255,255,255,0.35)",textTransform:"uppercase",letterSpacing:"0.06em",overflow:"hidden",textOverflow:"ellipsis",whiteSpace:"nowrap"},children:t.location}),e.jsxs("div",{style:{display:"flex",alignItems:"center",gap:10,margin:"4px 0"},children:[e.jsx("span",{style:{fontSize:"2.8rem",lineHeight:1},children:t.icon}),e.jsxs("div",{children:[e.jsxs("div",{style:{fontSize:"2.4rem",fontWeight:600,color:"rgba(255,255,255,0.95)",lineHeight:1,fontVariantNumeric:"tabular-nums",letterSpacing:"-0.02em"},children:[f(t.temp),"°",e.jsx("span",{style:{fontSize:"1rem",fontWeight:400,color:"rgba(255,255,255,0.4)",marginLeft:2},children:i})]}),e.jsx("div",{style:{fontSize:"0.8rem",color:"rgba(255,255,255,0.55)",marginTop:3},children:t.condition})]})]}),e.jsx("div",{style:{display:"flex",justifyContent:"space-between",background:"rgba(255,255,255,0.05)",borderRadius:8,padding:"6px 10px",gap:4},children:[{icon:"🌡",label:"Feels",value:`${f(t.feelsLike)}°`},{icon:"💧",label:"Humidity",value:`${t.humidity}%`},{icon:"💨",label:"Wind",value:m(t.wind)}].map(({icon:p,label:h,value:c})=>e.jsxs("div",{style:{display:"flex",flexDirection:"column",alignItems:"center",flex:1},children:[e.jsx("span",{style:{fontSize:"0.75rem"},children:p}),e.jsx("span",{style:{fontSize:"0.72rem",fontWeight:600,color:"rgba(255,255,255,0.8)",fontVariantNumeric:"tabular-nums"},children:c}),e.jsx("span",{style:{fontSize:"0.58rem",color:"rgba(255,255,255,0.3)",textTransform:"uppercase",letterSpacing:"0.04em"},children:h})]},h))})]})]}):e.jsx("div",{ref:g,style:{display:"flex",alignItems:"center",justifyContent:"center",height:"100%",color:"rgba(255,255,255,0.3)",fontSize:"0.75rem"},"aria-label":"Weather widget — loading",role:"region",children:"Loading…"})}const _n=[{type:"clock",label:"Clock",icon:e.jsx(_t,{size:14})},{type:"agent-status",label:"Agent Status",icon:e.jsx(Tt,{size:14})},{type:"quick-notes",label:"Quick Notes",icon:e.jsx(At,{size:14})},{type:"system-stats",label:"System Stats",icon:e.jsx(Ye,{size:14})},{type:"weather",label:"Weather",icon:e.jsx(Et,{size:14})}];function Tn(t){switch(t){case"clock":return e.jsx(ot,{});case"agent-status":return e.jsx(lt,{});case"quick-notes":return e.jsx(ct,{});case"system-stats":return e.jsx(ut,{});case"weather":return e.jsx(ht,{});default:return e.jsx("div",{style:{color:"rgba(255,255,255,0.4)",fontSize:"0.75rem",padding:8},children:"Unknown widget"})}}function An(){const{widgets:t,showWidgets:s,addWidget:n,removeWidget:r,updateLayout:i}=R(),[a,u]=o.useState(!1),[l,g]=o.useState(1200),d=o.useRef(null),f=o.useRef(null);o.useEffect(()=>{if(!d.current)return;const h=new ResizeObserver(c=>{for(const x of c)g(x.contentRect.width)});return h.observe(d.current),()=>h.disconnect()},[]),o.useEffect(()=>{if(!a)return;function h(c){f.current&&!f.current.contains(c.target)&&u(!1)}return document.addEventListener("mousedown",h),()=>document.removeEventListener("mousedown",h)},[a]);const m=o.useCallback(h=>{i(h.map(c=>({id:c.i,x:c.x,y:c.y,w:c.w,h:c.h})))},[i]);if(!s)return null;const p=t.map(h=>({i:h.id,x:h.x,y:h.y,w:h.w,h:h.h,minW:h.minW??2,minH:h.minH??2}));return e.jsxs("div",{ref:d,style:{position:"absolute",inset:0,zIndex:1,pointerEvents:"none"},children:[e.jsx("div",{style:{pointerEvents:"auto",width:"100%",height:"100%"},children:e.jsx(qt,{className:"widget-grid",layout:p,cols:12,rowHeight:72,width:l,margin:[16,16],containerPadding:[24,24],isDraggable:!0,isResizable:!0,compactType:null,preventCollision:!0,draggableHandle:".widget-drag-handle",onLayoutChange:m,children:t.map(h=>e.jsx("div",{style:{overflow:"hidden"},children:e.jsxs("div",{style:{height:"100%",background:"rgba(20, 20, 35, 0.65)",backdropFilter:"blur(12px)",WebkitBackdropFilter:"blur(12px)",borderRadius:12,border:"1px solid rgba(255,255,255,0.1)",display:"flex",flexDirection:"column",position:"relative",overflow:"hidden"},children:[e.jsx("div",{className:"widget-drag-handle",style:{display:"flex",justifyContent:"flex-end",padding:"4px 6px 0",cursor:"grab",minHeight:20},children:e.jsx("button",{onClick:c=>{c.stopPropagation(),r(h.id)},"aria-label":`Remove ${h.type} widget`,style:{background:"rgba(255,255,255,0.1)",border:"none",borderRadius:4,width:18,height:18,display:"flex",alignItems:"center",justifyContent:"center",cursor:"pointer",color:"rgba(255,255,255,0.4)",transition:"color 0.15s, background 0.15s"},onMouseEnter:c=>{c.currentTarget.style.color="#fff",c.currentTarget.style.background="rgba(239,68,68,0.6)"},onMouseLeave:c=>{c.currentTarget.style.color="rgba(255,255,255,0.4)",c.currentTarget.style.background="rgba(255,255,255,0.1)"},children:e.jsx(P,{size:12})})}),e.jsx("div",{style:{flex:1,padding:"0 8px 8px",overflow:"hidden"},children:Tn(h.type)})]})},h.id))})}),e.jsxs("div",{style:{position:"absolute",bottom:16,right:16,pointerEvents:"auto",zIndex:10},children:[e.jsx("button",{onClick:()=>u(!a),"aria-label":"Add widget",style:{width:40,height:40,borderRadius:"50%",background:"rgba(20, 20, 35, 0.7)",backdropFilter:"blur(12px)",WebkitBackdropFilter:"blur(12px)",border:"1px solid rgba(255,255,255,0.15)",color:"rgba(255,255,255,0.7)",cursor:"pointer",display:"flex",alignItems:"center",justifyContent:"center",transition:"transform 0.15s, background 0.15s"},onMouseEnter:h=>{h.currentTarget.style.background="rgba(40, 40, 60, 0.85)",h.currentTarget.style.transform="scale(1.1)"},onMouseLeave:h=>{h.currentTarget.style.background="rgba(20, 20, 35, 0.7)",h.currentTarget.style.transform="scale(1)"},children:e.jsx(Ze,{size:20})}),a&&e.jsx("div",{ref:f,style:{position:"absolute",bottom:50,right:0,background:"rgba(20, 20, 35, 0.9)",backdropFilter:"blur(16px)",WebkitBackdropFilter:"blur(16px)",border:"1px solid rgba(255,255,255,0.15)",borderRadius:10,padding:6,minWidth:170,display:"flex",flexDirection:"column",gap:2},children:_n.map(h=>e.jsxs("button",{onClick:()=>{n(h.type),u(!1)},style:{display:"flex",alignItems:"center",gap:8,padding:"8px 10px",background:"transparent",border:"none",borderRadius:6,color:"rgba(255,255,255,0.8)",fontSize:"0.8rem",cursor:"pointer",textAlign:"left",transition:"background 0.12s"},onMouseEnter:c=>{c.currentTarget.style.background="rgba(255,255,255,0.1)"},onMouseLeave:c=>{c.currentTarget.style.background="transparent"},children:[h.icon,h.label]},h.type))})]})]})}function En({x:t,y:s,items:n,onClose:r}){const i=o.useRef(null);o.useEffect(()=>{const l=d=>{i.current&&!i.current.contains(d.target)&&r()},g=d=>{d.key==="Escape"&&r()};return document.addEventListener("mousedown",l),document.addEventListener("keydown",g),()=>{document.removeEventListener("mousedown",l),document.removeEventListener("keydown",g)}},[r]);const a=Math.min(t,window.innerWidth-220),u=Math.min(s,window.innerHeight-n.length*36-20);return e.jsx("div",{ref:i,className:"fixed z-[10001] min-w-[200px] py-1 rounded-lg border border-shell-border-strong overflow-hidden",style:{left:a,top:u,backgroundColor:"rgba(30, 31, 50, 0.95)",backdropFilter:"blur(20px)",boxShadow:"0 8px 32px rgba(0,0,0,0.5)"},children:n.map((l,g)=>l.separator?e.jsx("div",{className:"my-1 mx-2 border-t border-shell-border"},g):e.jsxs("button",{onClick:()=>{!l.disabled&&l.action&&(l.action(),r())},disabled:l.disabled,className:`w-full flex items-center gap-2.5 px-3 py-1.5 text-left text-sm transition-colors ${l.disabled?"text-shell-text-tertiary cursor-default":"text-shell-text hover:bg-white/8"}`,children:[l.icon&&e.jsx("span",{className:"w-4 h-4 flex items-center justify-center text-shell-text-secondary",children:l.icon}),e.jsx("span",{children:l.label})]},g))})}function In({open:t,onClose:s}){const{wallpaperId:n,setWallpaper:r,getWallpapers:i}=M(),a=i();return t?e.jsx("div",{className:"fixed inset-0 z-[10002] flex items-center justify-center bg-black/40 backdrop-blur-sm p-4",onClick:s,style:{paddingTop:"calc(env(safe-area-inset-top, 0px) + 16px)",paddingBottom:"calc(40px + env(safe-area-inset-bottom, 0px) * 0.35 + 16px)"},children:e.jsxs("div",{className:"w-full max-w-[500px] max-h-full flex flex-col rounded-xl border border-shell-border-strong overflow-hidden",style:{backgroundColor:"rgba(26, 27, 46, 0.98)"},onClick:u=>u.stopPropagation(),children:[e.jsxs("div",{className:"flex items-center justify-between px-4 py-3 border-b border-shell-border shrink-0",children:[e.jsx("h3",{className:"text-sm font-medium text-shell-text",children:"Change Wallpaper"}),e.jsx("button",{onClick:s,className:"text-shell-text-tertiary hover:text-shell-text text-lg leading-none","aria-label":"Close",children:"×"})]}),e.jsx("div",{className:"p-4 grid grid-cols-2 gap-3 overflow-y-auto flex-1",children:a.map(u=>e.jsxs("button",{onClick:()=>{r(u.id)},className:`relative rounded-lg overflow-hidden border-2 transition-all ${n===u.id?"border-accent ring-1 ring-accent/30":"border-shell-border hover:border-shell-border-strong"}`,children:[e.jsx("div",{className:"h-24 w-full",style:{backgroundImage:u.image,backgroundColor:u.fallback,backgroundSize:"cover",backgroundPosition:"center",backgroundRepeat:"no-repeat"}}),e.jsx("div",{className:"px-2 py-1.5 text-xs text-shell-text-secondary text-left",children:u.label}),n===u.id&&e.jsx("div",{className:"absolute top-2 right-2 w-5 h-5 rounded-full bg-accent flex items-center justify-center",children:e.jsx(Xe,{size:12,className:"text-white"})})]},u.id))})]})}):null}function Ln(){const t=_(b=>b.windows),{openWindow:s}=_(),n=M(b=>b.wallpaperImage),r=M(b=>b.wallpaperMobileImage),i=M(b=>b.wallpaperFallback),{showWidgets:a,toggleWidgets:u}=R(),[l,g]=o.useState(null),[d,f]=o.useState(!1),m={width:typeof window<"u"?window.innerWidth:1920,height:typeof window<"u"?window.innerHeight:1080,topBarH:32,dockH:84},{previewBounds:p,onDrag:h,onDragStop:c}=hn(m),x=o.useCallback(b=>{(b.target===b.currentTarget||b.target.closest("[data-desktop-surface]"))&&(b.preventDefault(),g({x:b.clientX,y:b.clientY}))},[]),y=o.useCallback(b=>{const j=L(b);j&&s(b,j.defaultSize)},[s]),w=[{label:"New Folder",icon:e.jsx(It,{size:14}),action:()=>y("files")},{label:"",separator:!0},{label:"Change Wallpaper",icon:e.jsx(Lt,{size:14}),action:()=>f(!0)},{label:"Save to Memory",icon:e.jsx(Wt,{size:14}),action:()=>{const b=window.prompt("Save to memory:");b&&fetch("/api/user-memory/save",{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({content:b,collection:"snippets"})}).catch(()=>{const j=JSON.parse(localStorage.getItem("tinyagentos-snippets")||"[]");j.push({content:b,savedAt:Date.now()}),localStorage.setItem("tinyagentos-snippets",JSON.stringify(j))})}},{label:"Display Settings",icon:e.jsx(Rt,{size:14}),action:()=>y("settings")},{label:"",separator:!0},{label:a?"Hide Widgets":"Show Widgets",icon:e.jsx(Qe,{size:14}),action:()=>u()},{label:"",separator:!0},{label:"Open Launchpad",icon:e.jsx(be,{size:14}),action:()=>{window.dispatchEvent(new CustomEvent("open-launchpad"))}},{label:"System Settings",icon:e.jsx(Ke,{size:14}),action:()=>y("settings")}];return e.jsxs("div",{className:"taos-wallpaper relative flex-1 overflow-hidden",style:{backgroundColor:i,"--wallpaper-desktop":n,"--wallpaper-mobile":r},onContextMenu:x,"data-desktop-surface":!0,children:[e.jsx(xn,{bounds:p}),e.jsx(An,{}),t.map(b=>e.jsx(gn,{win:b,onDrag:h,onDragStop:c},b.id)),l&&e.jsx(En,{x:l.x,y:l.y,items:w,onClose:()=>g(null)}),e.jsx(In,{open:d,onClose:()=>f(!1)})]})}const Wn=["messages","agents","files","store","settings"],de=q((t,s)=>({pinned:Wn,pin(n){s().pinned.includes(n)||t(r=>({pinned:[...r.pinned,n]}))},unpin(n){t(r=>({pinned:r.pinned.filter(i=>i!==n)}))},reorder(n){t({pinned:n})}}));function Re({appId:t,isRunning:s,onClick:n}){const r=L(t);if(!r)return null;const i=r.icon.split("-").map(u=>u.charAt(0).toUpperCase()+u.slice(1)).join(""),a=G[i]??H;return e.jsxs("button",{onClick:n,className:"group relative flex items-center justify-center w-10 h-10 rounded-lg bg-shell-surface hover:bg-shell-surface-active transition-all hover:scale-110","aria-label":`Open ${r.name}`,title:r.name,children:[e.jsx(a,{size:20,className:"text-shell-text"}),s&&e.jsx("div",{className:"absolute -bottom-1 left-1/2 -translate-x-1/2 w-1 h-1 rounded-full bg-accent"})]})}function Rn({onLaunchpadOpen:t}){const s=de(d=>d.pinned),n=_(d=>d.windows),{openWindow:r,focusWindow:i,restoreWindow:a}=_(),u=n.map(d=>d.appId),l=u.filter(d=>!s.includes(d)),g=d=>{const f=n.find(m=>m.appId===d);if(f)f.minimized?a(f.id):i(f.id);else{const m=L(d);m&&r(d,m.defaultSize)}};return e.jsxs("div",{className:"fixed bottom-3 left-1/2 -translate-x-1/2 flex items-center gap-1.5 px-3 rounded-2xl z-[9999] select-none",style:{height:"var(--spacing-dock-h)",padding:"var(--spacing-dock-padding)",backgroundColor:"var(--color-dock-bg)",border:"1px solid var(--color-dock-border)",boxShadow:"var(--shadow-dock)"},children:[e.jsx("button",{onClick:t,className:"flex items-center justify-center w-10 h-10 rounded-lg bg-shell-surface hover:bg-shell-surface-active transition-all hover:scale-110","aria-label":"Launchpad",title:"Launchpad",children:e.jsxs("svg",{width:"18",height:"18",viewBox:"0 0 16 16",className:"text-shell-text",fill:"currentColor",children:[e.jsx("rect",{x:"1",y:"1",width:"5",height:"5",rx:"1"}),e.jsx("rect",{x:"10",y:"1",width:"5",height:"5",rx:"1"}),e.jsx("rect",{x:"1",y:"10",width:"5",height:"5",rx:"1"}),e.jsx("rect",{x:"10",y:"10",width:"5",height:"5",rx:"1"})]})}),e.jsx("div",{className:"w-px h-8 bg-shell-border mx-1"}),s.map(d=>e.jsx(Re,{appId:d,isRunning:u.includes(d),onClick:()=>g(d)},d)),l.length>0&&e.jsx("div",{className:"w-px h-8 bg-shell-border mx-1"}),l.map(d=>e.jsx(Re,{appId:d,isRunning:!0,onClick:()=>g(d)},d))]})}function Pn(t){const s=t.toLowerCase().split("+").map(n=>n.trim());return{ctrl:s.includes("ctrl"),shift:s.includes("shift"),alt:s.includes("alt"),key:s.filter(n=>!["ctrl","shift","alt"].includes(n))[0]??""}}function On(t,s){const n=s.ctrlKey||s.metaKey;return t.ctrl!==n||t.shift!==s.shiftKey||t.alt!==s.altKey?!1:s.key.toLowerCase()===t.key}const ke=o.createContext(null),Pe={overlay:0,app:1,system:2};function Mn(t){const s=[];return t.ctrl&&s.push("Ctrl"),t.shift&&s.push("Shift"),t.alt&&s.push("Alt"),s.push(t.key.charAt(0).toUpperCase()+t.key.slice(1)),s.join("+")}function Oe({children:t}){const s=o.useRef(new Map),[n,r]=o.useState(!1);o.useEffect(()=>{const l=()=>{var g;document.fullscreenElement&&((g=navigator.keyboard)!=null&&g.lock)?navigator.keyboard.lock().then(()=>r(!0)).catch(()=>r(!1)):r(!1)};return document.addEventListener("fullscreenchange",l),()=>document.removeEventListener("fullscreenchange",l)},[]),o.useEffect(()=>{const l=g=>{const d=Array.from(s.current.values()).filter(f=>f.enabled).sort((f,m)=>Pe[f.scope]-Pe[m.scope]);for(const f of d)if(On(f.combo,g)){g.preventDefault(),g.stopPropagation(),f.action();return}};return window.addEventListener("keydown",l),()=>window.removeEventListener("keydown",l)},[]);const i=o.useCallback((l,g,d,f,m="system")=>{s.current.set(l,{id:l,combo:Pn(g),action:d,label:f,scope:m,enabled:!0})},[]),a=o.useCallback(l=>{s.current.delete(l)},[]),u=o.useCallback(()=>Array.from(s.current.values()).map(l=>({combo:Mn(l.combo),label:l.label,scope:l.scope})),[]);return e.jsx(ke.Provider,{value:{register:i,unregister:a,getAll:u,keyboardLockActive:n},children:t})}function I(t,s,n,r="system"){const i=o.useContext(ke),a=o.useRef(`shortcut-${t}-${Math.random().toString(36).slice(2,8)}`);o.useEffect(()=>(i==null||i.register(a.current,t,s,n,r),()=>i==null?void 0:i.unregister(a.current)),[i,t,s,n,r])}function js(){const t=o.useContext(ke);return{getAll:(t==null?void 0:t.getAll)??(()=>[]),keyboardLockActive:(t==null?void 0:t.keyboardLockActive)??!1}}function Dn({app:t,onClick:s}){const n=t.icon.split("-").map(i=>i.charAt(0).toUpperCase()+i.slice(1)).join(""),r=G[n]??H;return e.jsxs("button",{onClick:s,className:"flex flex-col items-center gap-2 p-3 rounded-xl hover:bg-white/5 transition-colors","aria-label":`Open ${t.name}`,children:[e.jsx("div",{className:"w-14 h-14 rounded-2xl bg-shell-surface-hover flex items-center justify-center",children:e.jsx(r,{size:28,className:"text-shell-text"})}),e.jsx("span",{className:"text-xs text-shell-text-secondary",children:t.name})]})}const Fn={platform:"Platform",os:"Utilities",streaming:"Streaming Apps",game:"Games"};function Me({open:t,onClose:s,onOpenApp:n}){const[r,i]=o.useState(""),a=o.useRef(t);a.current=t;const{openWindow:u}=_();I("Escape",()=>{a.current&&s()},"Close launchpad","overlay");const l=typeof window<"u"&&window.innerWidth<640,g=o.useMemo(()=>{const m=rt();if(!r.trim())return m;const p=r.toLowerCase();return m.filter(h=>h.name.toLowerCase().includes(p))},[r]),d=o.useMemo(()=>{var p;const m={};for(const h of g)(m[p=h.category]??(m[p]=[])).push(h);return m},[g]),f=m=>{const p=L(m);if(p){const h=u(m,p.defaultSize);n==null||n(h)}s(),i("")};return t?e.jsx("div",{className:"fixed top-0 left-0 right-0 z-[9000] flex flex-col backdrop-blur-md bg-black/40",onClick:s,style:{bottom:l?76:0,paddingTop:"calc(env(safe-area-inset-top, 0px) + 60px)",paddingBottom:l?16:"calc(52px + env(safe-area-inset-bottom, 0px) + 16px)"},children:e.jsxs("div",{className:"w-full max-w-3xl mx-auto px-4 flex-1 flex flex-col min-h-0",children:[e.jsxs("div",{className:"flex items-center gap-2 px-4 py-2 mb-4 rounded-xl bg-white/10 border border-white/10 shrink-0",onClick:m=>m.stopPropagation(),children:[e.jsx(X,{size:16,className:"text-shell-text-tertiary"}),e.jsx("input",{type:"text",value:r,onChange:m=>i(m.target.value),placeholder:"Search apps...",className:"flex-1 bg-transparent text-sm text-shell-text outline-none placeholder:text-shell-text-tertiary",autoFocus:!l}),r&&e.jsx("button",{onClick:()=>i(""),"aria-label":"Clear search",children:e.jsx(P,{size:14,className:"text-shell-text-tertiary"})})]}),e.jsx("div",{className:"flex-1 overflow-y-auto space-y-6 pr-1",children:Object.entries(d).map(([m,p])=>e.jsxs("div",{children:[e.jsx("h3",{className:"text-xs font-medium text-shell-text-tertiary uppercase tracking-wide mb-3 px-1",children:Fn[m]??m}),e.jsx("div",{className:"grid grid-cols-4 sm:grid-cols-5 md:grid-cols-6 gap-3",children:p.map(h=>e.jsx(Dn,{app:h,onClick:()=>f(h.id)},h.id))})]},m))})]})}):null}function De({open:t,onClose:s,onOpenApp:n}){const[r,i]=o.useState(""),a=o.useRef(null),u=o.useRef(t);u.current=t;const{openWindow:l}=_(),[g,d]=o.useState(0);I("Escape",()=>{u.current&&s()},"Close search","overlay"),o.useEffect(()=>{t&&(i(""),d(0),setTimeout(()=>{var j;return(j=a.current)==null?void 0:j.focus()},50))},[t]);const f=o.useMemo(()=>{const j=rt(),k=r.toLowerCase().trim();return j.filter(N=>!k||N.name.toLowerCase().includes(k)||N.category.includes(k)).slice(0,8).map(N=>({id:N.id,name:N.name,category:N.category,icon:N.icon,type:"app",action:()=>{const C=L(N.id);if(C){const A=l(N.id,C.defaultSize);n==null||n(A)}s()}}))},[r,l,s,n]),[m,p]=o.useState([]);o.useEffect(()=>{const j=r.trim();if(!j||j.length<2){p([]);return}const k=new AbortController,N=setTimeout(()=>{fetch(`/api/user-memory/search?q=${encodeURIComponent(j)}&limit=5`,{signal:k.signal}).then(C=>C.ok?C.json():{results:[]}).then(C=>{const A=Array.isArray(C==null?void 0:C.results)?C.results:[];p(A.map(E=>({id:`mem-${E.hash}`,name:E.title&&E.title.trim()||E.content.slice(0,60),category:E.collection,icon:"database",type:"memory",subtitle:E.content.slice(0,100),action:()=>{const v=L("memory");if(v){const W=l("memory",v.defaultSize);n==null||n(W)}s()}})))}).catch(()=>{})},300);return()=>{clearTimeout(N),k.abort()}},[r,l,s,n]);const[h,c]=o.useState([]);o.useEffect(()=>{const j=r.trim();if(!j||j.length<2){c([]);return}const k=new AbortController,N=setTimeout(()=>{fetch(`/api/memory/catalog/search?q=${encodeURIComponent(j)}&limit=3`,{signal:k.signal}).then(C=>C.ok?C.json():[]).then(C=>{Array.isArray(C)&&c(C.map(A=>({id:`catalog-${A.id}`,name:A.topic||"Session",category:A.category||"session",icon:"calendar-search",type:"memory",subtitle:`${A.date||""} ${A.start_str||""}-${A.end_str||""} ${A.description||""}`.trim().slice(0,100),action:()=>{const E=L("memory");if(E){const v=l("memory",E.defaultSize);n==null||n(v)}s()}})))}).catch(()=>{})},300);return()=>{clearTimeout(N),k.abort()}},[r,l,s,n]);const x=o.useMemo(()=>[...f,...m,...h],[f,m,h]);o.useEffect(()=>{d(0)},[x]);const y=j=>{j.key==="ArrowDown"?(j.preventDefault(),d(k=>Math.min(k+1,x.length-1))):j.key==="ArrowUp"?(j.preventDefault(),d(k=>Math.max(k-1,0))):j.key==="Enter"&&x[g]&&x[g].action()};if(!t)return null;const w=j=>{const k=j.split("-").map(C=>C.charAt(0).toUpperCase()+C.slice(1)).join(""),N=G[k]??H;return e.jsx(N,{size:18})},b={platform:"Platform",os:"Utility",streaming:"Streaming",game:"Game"};return e.jsx("div",{className:"fixed inset-0 z-[10003] flex justify-center items-start bg-black/30 backdrop-blur-sm px-4",onClick:s,style:{paddingTop:"calc(env(safe-area-inset-top, 0px) + 8px)"},children:e.jsxs("div",{className:"w-full max-w-[560px] max-h-[50vh] rounded-xl border border-shell-border-strong overflow-hidden flex flex-col",style:{backgroundColor:"rgba(26, 27, 46, 0.97)",boxShadow:"0 16px 64px rgba(0,0,0,0.5)"},onClick:j=>j.stopPropagation(),children:[e.jsxs("div",{className:"flex items-center gap-2 px-3 py-2 border-b border-shell-border",children:[e.jsx(X,{size:15,className:"text-shell-text-tertiary shrink-0"}),e.jsx("input",{ref:a,type:"text",value:r,onChange:j=>i(j.target.value),onKeyDown:y,placeholder:"Search apps, settings, files...",className:"flex-1 bg-transparent text-sm text-shell-text outline-none placeholder:text-shell-text-tertiary",autoFocus:!0}),r&&e.jsx("button",{onClick:()=>i(""),"aria-label":"Clear",children:e.jsx(P,{size:13,className:"text-shell-text-tertiary"})})]}),e.jsxs("div",{className:"flex-1 overflow-y-auto py-1",children:[x.length===0&&r&&e.jsxs("div",{className:"px-4 py-8 text-center text-sm text-shell-text-tertiary",children:['No results for "',r,'"']}),f.length>0&&e.jsx("div",{className:"px-4 pt-2 pb-1 text-[10px] uppercase tracking-wider text-shell-text-tertiary",role:"presentation",children:"Apps"}),f.map(j=>{const k=x.indexOf(j);return e.jsxs("button",{onClick:j.action,onMouseEnter:()=>d(k),className:`w-full flex items-center gap-2.5 px-3 py-1.5 text-left transition-colors ${k===g?"bg-accent/15":"hover:bg-white/5"}`,children:[e.jsx("div",{className:`w-7 h-7 rounded-md flex items-center justify-center ${k===g?"bg-accent/20 text-accent":"bg-shell-surface text-shell-text-secondary"}`,children:w(j.icon)}),e.jsx("div",{className:"flex-1 min-w-0",children:e.jsx("div",{className:"text-xs text-shell-text truncate",children:j.name})}),e.jsx("span",{className:"text-[9px] text-shell-text-tertiary uppercase tracking-wider",children:b[j.category]??j.category})]},j.id)}),m.length>0&&e.jsx("div",{className:"px-4 pt-3 pb-1 text-[10px] uppercase tracking-wider text-shell-text-tertiary",role:"presentation",children:"Memory"}),m.map(j=>{const k=x.indexOf(j);return e.jsxs("button",{onClick:j.action,onMouseEnter:()=>d(k),className:`w-full flex items-start gap-3 px-4 py-2.5 text-left transition-colors ${k===g?"bg-accent/15":"hover:bg-white/5"}`,children:[e.jsx("div",{className:`w-8 h-8 rounded-lg flex items-center justify-center shrink-0 ${k===g?"bg-slate-500/20 text-slate-300":"bg-shell-surface text-shell-text-secondary"}`,children:w(j.icon)}),e.jsxs("div",{className:"flex-1 min-w-0",children:[e.jsx("div",{className:"text-sm text-shell-text truncate",children:j.name}),j.subtitle&&e.jsx("div",{className:"text-[11px] text-shell-text-tertiary truncate mt-0.5",children:j.subtitle})]}),e.jsx("span",{className:"text-[10px] text-shell-text-tertiary uppercase tracking-wider shrink-0",children:j.category})]},j.id)}),!r&&e.jsx("div",{className:"px-4 py-6 text-center text-xs text-shell-text-tertiary",children:"Type to search apps and memory, or press Escape to close"})]}),e.jsxs("div",{className:"flex items-center justify-between px-4 py-2 border-t border-shell-border text-[10px] text-shell-text-tertiary",children:[e.jsx("span",{children:"↑↓ Navigate"}),e.jsx("span",{children:"↵ Open"}),e.jsx("span",{children:"Esc Close"})]})]})})}function $n(){const t=_(c=>c.windows),s=_(c=>c.openWindow),n=_(c=>c.updatePosition),r=_(c=>c.updateSize),i=_(c=>c.maximizeWindow),a=_(c=>c.snapWindow),u=de(c=>c.pinned),l=M(c=>c.wallpaperId),g=R(c=>c.widgets),d=o.useRef(!1),f=o.useRef(null),m=o.useRef(null),p=o.useRef(null),h=o.useRef(null);o.useEffect(()=>{d.current||(d.current=!0,fetch("/api/desktop/windows").then(c=>c.json()).then(c=>{if(Array.isArray(c))for(const x of c){if(!L(x.appId))continue;const w=s(x.appId,{w:x.w,h:x.h});n(w,x.x,x.y),r(w,x.w,x.h),x.maximized&&i(w),x.snapped&&a(w,x.snapped)}}).catch(()=>{}),fetch("/api/desktop/dock").then(c=>c.json()).then(c=>{c.pinned&&Array.isArray(c.pinned)&&de.getState().reorder(c.pinned)}).catch(()=>{}),fetch("/api/desktop/settings").then(c=>c.json()).then(c=>{c.wallpaper&&c.wallpaper!=="default"&&M.getState().setWallpaper(c.wallpaper)}).catch(()=>{}),fetch("/api/desktop/widgets").then(c=>c.json()).then(c=>{const x=Array.isArray(c)?c:c.widgets??[];x.length>0&&R.setState({widgets:x})}).catch(()=>{}))},[s,n,r,i,a]),o.useEffect(()=>{if(d.current)return f.current&&clearTimeout(f.current),f.current=setTimeout(()=>{const c=t.map(x=>({appId:x.appId,x:x.position.x,y:x.position.y,w:x.size.w,h:x.size.h,maximized:x.maximized,snapped:x.snapped}));fetch("/api/desktop/windows",{method:"PUT",headers:{"Content-Type":"application/json"},body:JSON.stringify({positions:c})}).catch(()=>{})},2e3),()=>{f.current&&clearTimeout(f.current)}},[t]),o.useEffect(()=>{if(d.current)return m.current&&clearTimeout(m.current),m.current=setTimeout(()=>{fetch("/api/desktop/dock",{method:"PUT",headers:{"Content-Type":"application/json"},body:JSON.stringify({pinned:u})}).catch(()=>{})},1e3),()=>{m.current&&clearTimeout(m.current)}},[u]),o.useEffect(()=>{if(d.current)return p.current&&clearTimeout(p.current),p.current=setTimeout(()=>{fetch("/api/desktop/settings",{method:"PUT",headers:{"Content-Type":"application/json"},body:JSON.stringify({wallpaper:l})}).catch(()=>{})},500),()=>{p.current&&clearTimeout(p.current)}},[l]),o.useEffect(()=>{if(d.current)return h.current&&clearTimeout(h.current),h.current=setTimeout(()=>{fetch("/api/desktop/widgets",{method:"PUT",headers:{"Content-Type":"application/json"},body:JSON.stringify({widgets:g})}).catch(()=>{})},1e3),()=>{h.current&&clearTimeout(h.current)}},[g])}function Fe(){const t=window.innerWidth,s=matchMedia("(pointer: coarse)").matches||navigator.maxTouchPoints>0;return t<768?"mobile":t<1024&&s?"tablet":"desktop"}function Hn(){const[t,s]=o.useState(Fe);return o.useEffect(()=>{const n=()=>s(Fe());return window.addEventListener("resize",n),()=>window.removeEventListener("resize",n)},[]),t}const Un=["messages","agents","files","store","settings","models","providers","activity","cluster","memory","channels","secrets","tasks","import","images","library","reddit","youtube","github","x-monitor","agent-browsers","calculator","calendar","contacts"],Bn=["messages","agents","files","store"],Vn=[{items:[{type:"widget",widgetType:"greeting"},{type:"widget",widgetType:"weather"},{type:"widget",widgetType:"system-stats"},{type:"widget",widgetType:"agent-status"}]},{items:Un.map(t=>({type:"app",appId:t}))}],ie=q(t=>({dockApps:Bn,pages:Vn,activePageIndex:0,setActivePage(s){t({activePageIndex:s})},setDockApps(s){t({dockApps:s})},addPage(){t(s=>({pages:[...s.pages,{items:[]}]}))},removePage(s){t(n=>{const r=n.pages.filter((a,u)=>u!==s),i=Math.min(n.activePageIndex,Math.max(0,r.length-1));return{pages:r,activePageIndex:i}})},addItemToPage(s,n){t(r=>({pages:r.pages.map((i,a)=>a===s?{items:[...i.items,n]}:i)}))},removeItemFromPage(s,n){t(r=>({pages:r.pages.map((i,a)=>a===s?{items:i.items.filter((u,l)=>l!==n)}:i)}))}}));function Gn(t){const s=t.split("-").map(n=>n.charAt(0).toUpperCase()+n.slice(1)).join("");return G[s]??H}function qn({onOpenApp:t,onToggleSwitcher:s,onOpenLaunchpad:n,activeAppId:r}){const i=ie(u=>u.dockApps),a=_(u=>u.windows);return e.jsxs("div",{role:"toolbar","aria-label":"Dock",className:"shrink-0",style:{display:"flex",alignItems:"center",justifyContent:"center",gap:8,paddingTop:6,paddingBottom:24},children:[e.jsx("button",{onClick:n,"aria-label":"All Apps",style:{width:44,height:44,borderRadius:12,background:"linear-gradient(135deg, rgba(60,65,78,0.85), rgba(35,38,48,0.9))",border:"1px solid rgba(255,255,255,0.1)",display:"flex",alignItems:"center",justifyContent:"center",cursor:"pointer",padding:0},children:e.jsx(be,{size:20,style:{color:"rgba(255,255,255,0.8)"}})}),i.map(u=>{const l=L(u);if(!l)return null;const g=Gn(l.icon),d=u===r,f=a.some(m=>m.appId===u);return e.jsxs("div",{style:{position:"relative",display:"flex",flexDirection:"column",alignItems:"center"},children:[e.jsx("button",{onClick:()=>t(u),"aria-label":`Open ${l.name}`,style:{width:44,height:44,borderRadius:12,background:"linear-gradient(135deg, rgba(60,65,78,0.85), rgba(35,38,48,0.9))",border:"1px solid rgba(255,255,255,0.1)",display:"flex",alignItems:"center",justifyContent:"center",cursor:"pointer",padding:0},children:e.jsx(g,{size:22,style:{color:"rgba(255,255,255,0.8)"}})}),d&&e.jsx("div",{style:{position:"absolute",bottom:-6,left:"50%",transform:"translateX(-50%)",width:4,height:4,borderRadius:"50%",background:"rgba(255,255,255,0.7)"}}),!d&&f&&e.jsx("div",{style:{position:"absolute",bottom:-6,left:"50%",transform:"translateX(-50%)",width:3,height:3,borderRadius:"50%",background:"rgba(255,255,255,0.3)"}})]},u)}),e.jsx("div",{style:{width:1,height:28,background:"rgba(255,255,255,0.15)",margin:"0 6px",flexShrink:0}}),e.jsx("button",{onClick:s,"aria-label":"App Switcher",style:{width:44,height:44,borderRadius:12,background:"rgba(255,255,255,0.06)",border:"1px solid rgba(255,255,255,0.1)",display:"flex",alignItems:"center",justifyContent:"center",cursor:"pointer",padding:0},children:e.jsx(Qe,{size:20,style:{color:"rgba(255,255,255,0.7)"}})})]})}function Yn(t){const s=t.split("-").map(n=>n.charAt(0).toUpperCase()+n.slice(1)).join("");return G[s]??H}function Jn({open:t,onClose:s,onSelectApp:n,onLaunchpad:r}){const i=_(p=>p.windows),a=_(p=>p.closeWindow),[u,l]=o.useState({}),g=o.useRef({}),d=o.useCallback((p,h)=>{g.current[p]=h,l(c=>({...c,[p]:0}))},[]),f=o.useCallback((p,h)=>{const c=g.current[p];if(c===void 0)return;const x=h-c;x<0&&l(y=>({...y,[p]:x}))},[]),m=o.useCallback(p=>{(u[p]??0)<-100?(l(c=>({...c,[p]:-999})),setTimeout(()=>{a(p),l(c=>{const x={...c};return delete x[p],x})},250)):l(c=>{const x={...c};return delete x[p],x}),delete g.current[p]},[u,a]);return t?e.jsxs("div",{className:"fixed inset-0 flex flex-col backdrop-blur-sm",style:{zIndex:9e3,backgroundColor:"rgba(0, 0, 0, 0.6)"},role:"dialog","aria-label":"App Switcher",onClick:s,children:[e.jsxs("div",{className:"flex items-center justify-between px-4 pt-4 pb-2",onClick:p=>p.stopPropagation(),children:[e.jsx("h2",{className:"text-white text-lg font-medium",children:"App Switcher"}),e.jsx("button",{onClick:s,className:"flex items-center justify-center w-8 h-8 rounded-full bg-white/10 active:bg-white/20 transition-colors","aria-label":"Close app switcher",children:e.jsx(P,{size:18,className:"text-white/80"})})]}),i.length===0?e.jsxs("div",{className:"flex-1 flex flex-col items-center justify-center gap-4",children:[e.jsx("p",{className:"text-white/60 text-base",children:"No apps open"}),e.jsxs("button",{onClick:p=>{p.stopPropagation(),r(),s()},className:"flex items-center gap-2 px-4 py-2 rounded-lg bg-white/10 active:bg-white/20 text-white/80 transition-colors","aria-label":"Open Launchpad",children:[e.jsx(Ze,{size:18}),"Open Launchpad"]})]}):e.jsx("div",{className:"flex-1 flex items-center overflow-x-auto snap-x snap-mandatory",style:{scrollSnapType:"x mandatory",WebkitOverflowScrolling:"touch",paddingLeft:"calc(50vw - 35vw)",paddingRight:"calc(50vw - 35vw)",gap:"1rem"},onClick:p=>{p.target===p.currentTarget&&s()},children:i.map(p=>{const h=L(p.appId),c=h?Yn(h.icon):H,x=u[p.id]??0,y=x===-999;return e.jsxs("div",{className:"flex-shrink-0 snap-center relative flex flex-col items-center justify-center rounded-2xl bg-white/8 border border-white/10",style:{width:"70vw",aspectRatio:"9 / 16",transform:y?"translateY(-120vh)":x<0?`translateY(${x}px)`:void 0,transition:y?"transform 250ms ease-in":x===0?"transform 200ms ease-out":void 0,opacity:y?0:1},onTouchStart:w=>{var b;return d(p.id,((b=w.touches[0])==null?void 0:b.clientY)??0)},onTouchMove:w=>{var b;return f(p.id,((b=w.touches[0])==null?void 0:b.clientY)??0)},onTouchEnd:()=>m(p.id),onClick:w=>{w.stopPropagation(),n(p.id),s()},role:"button","aria-label":`Switch to ${(h==null?void 0:h.name)??"Unknown"}`,tabIndex:0,children:[e.jsx("button",{onClick:w=>{w.stopPropagation(),a(p.id)},className:"absolute top-3 right-3 flex items-center justify-center w-7 h-7 rounded-full bg-white/10 active:bg-white/20 transition-colors","aria-label":`Close ${(h==null?void 0:h.name)??"app"}`,children:e.jsx(P,{size:14,className:"text-white/70"})}),e.jsx(c,{size:40,className:"text-white/60 mb-3"}),e.jsx("span",{className:"text-white/80 text-sm font-medium",children:(h==null?void 0:h.name)??p.appId})]},p.id)})})]}):null}function Kn({onHome:t,onSearch:s}){const n=F(i=>i.notifications.filter(a=>!a.read).length),r=F(i=>i.toggleCentre);return e.jsx("div",{className:"shrink-0",style:{paddingTop:"env(safe-area-inset-top, 0px)"},children:e.jsxs("div",{className:"flex items-center px-2",style:{height:44},children:[e.jsx("button",{onClick:t,className:"px-2 py-1 active:opacity-60 transition-opacity","aria-label":"Go to home screen",children:e.jsx("span",{className:"text-[17px] font-semibold text-shell-text",children:"taOS"})}),e.jsx("div",{className:"flex-1 flex items-center justify-center",children:e.jsx(it,{compact:!0})}),e.jsxs("div",{className:"flex items-center gap-2",children:[e.jsx("button",{onClick:s,className:"relative flex items-center justify-center active:opacity-60 transition-opacity",style:{width:32,height:32,borderRadius:"50%",background:"rgba(255,255,255,0.08)",backdropFilter:"blur(10px)",WebkitBackdropFilter:"blur(10px)",border:"1px solid rgba(255,255,255,0.1)"},"aria-label":"Search",children:e.jsx(X,{size:15,className:"text-white/70"})}),e.jsxs("button",{onClick:r,className:"relative flex items-center justify-center active:opacity-60 transition-opacity",style:{width:32,height:32,borderRadius:"50%",background:"rgba(255,255,255,0.08)",backdropFilter:"blur(10px)",WebkitBackdropFilter:"blur(10px)",border:"1px solid rgba(255,255,255,0.1)"},"aria-label":`Notifications${n>0?` (${n} unread)`:""}`,children:[e.jsx(ae,{size:15,className:"text-white/70"}),n>0&&e.jsx("span",{className:"absolute bg-red-500 rounded-full",style:{width:6,height:6,top:5,right:5}})]})]})]})})}function Xn({appId:t,windowId:s,onClose:n,onMinimise:r}){const i=L(t),a=o.useMemo(()=>i?o.lazy(i.component):null,[i]);return!i||!a?null:e.jsxs("div",{className:"flex flex-col h-full w-full",children:[e.jsxs("div",{className:"flex items-center px-3 gap-2 shrink-0",style:{height:"32px",background:"rgba(30, 30, 60, 0.9)",borderBottom:"1px solid rgba(255,255,255,0.08)"},children:[e.jsx("button",{onClick:n,"aria-label":"Close",className:"flex items-center justify-center rounded-full shrink-0",style:{width:"18px",height:"18px",background:"rgba(255,80,80,0.3)",border:"1px solid rgba(255,80,80,0.3)"},children:e.jsx(P,{size:10,style:{color:"rgba(255,120,120,0.8)"}})}),e.jsx("button",{onClick:r,"aria-label":"Minimise",className:"flex items-center justify-center rounded-full shrink-0",style:{width:"18px",height:"18px",background:"rgba(255,200,50,0.2)",border:"1px solid rgba(255,200,50,0.3)"},children:e.jsx(Pt,{size:10,style:{color:"rgba(255,200,80,0.8)"}})}),e.jsx("div",{className:"flex-1 text-center text-xs font-medium",style:{color:"rgba(255,255,255,0.6)"},children:i.name}),e.jsx("div",{style:{width:"44px"}})]}),e.jsx("div",{className:"flex-1 overflow-hidden",style:{background:"rgba(15,15,35,0.95)"},children:e.jsx(o.Suspense,{fallback:e.jsx("div",{className:"flex items-center justify-center h-full text-white/30 text-sm",children:"Loading..."}),children:e.jsx(a,{windowId:s})})})]})}function Zn(t){return t>=5&&t<12?"Good morning.":t>=12&&t<17?"Good afternoon.":t>=17&&t<21?"Good evening.":"Good night."}function Qn(t){return t>=5&&t<12?"☀️":t>=12&&t<17?"🌤":t>=17&&t<21?"🌅":"🌙"}async function $e(){try{const[t,s]=await Promise.all([fetch("/api/agents"),fetch("/api/jobs")]);if(!t.ok||!s.ok)return null;const n=await t.json(),r=await s.json(),i=Array.isArray(n)?n.length:(n==null?void 0:n.count)??0,a=Array.isArray(r)?r.length:(r==null?void 0:r.count)??0;return{agentCount:i,taskCount:a}}catch{return null}}function es(){const[t,s]=o.useState(()=>new Date),[n,r]=o.useState(null),[i,{tier:a}]=Y();o.useEffect(()=>{const m=setInterval(()=>s(new Date),6e4);return()=>clearInterval(m)},[]),o.useEffect(()=>{$e().then(r);const m=setInterval(()=>$e().then(r),3e4);return()=>clearInterval(m)},[]);const u=t.getHours(),l=Zn(u),g=Qn(u),d=[];n!==null&&(n.agentCount>0&&d.push(`${n.agentCount} agent${n.agentCount!==1?"s":""} running`),n.taskCount>0&&d.push(`${n.taskCount} task${n.taskCount!==1?"s":""} queued`));const f=d.length>0?d.join(" · "):"All systems operational";return e.jsxs("div",{ref:i,style:{display:"flex",flexDirection:"column",alignItems:"center",justifyContent:"center",height:"100%",padding:a==="s"?"4px 8px":a==="m"?"12px 12px":"20px 16px",gap:a==="s"?4:8,textAlign:"center"},"aria-label":"Greeting widget",role:"region",children:[a!=="s"&&e.jsx("span",{style:{fontSize:a==="l"?36:28,lineHeight:1},"aria-hidden":"true",children:g}),e.jsx("span",{style:{fontSize:a==="s"?"1rem":a==="m"?"1.3rem":"1.7rem",fontWeight:600,color:"rgba(255,255,255,0.92)",lineHeight:1.2,letterSpacing:"-0.02em"},children:a==="s"?e.jsxs(e.Fragment,{children:[g," ",l]}):l}),a!=="s"&&e.jsx("span",{style:{fontSize:a==="l"?"0.78rem":"0.7rem",color:"rgba(255,255,255,0.4)",letterSpacing:"0.01em"},children:f})]})}const He={platform:"linear-gradient(135deg, rgba(100,80,200,0.4), rgba(60,50,140,0.6))",os:"linear-gradient(135deg, rgba(50,160,140,0.35), rgba(30,100,90,0.55))",game:"linear-gradient(135deg, rgba(200,120,50,0.35), rgba(140,70,30,0.55))"};function ts(t){const s=t.split("-").map(n=>n.charAt(0).toUpperCase()+n.slice(1)).join("");return G[s]??H}const ge={borderRadius:"16px",background:"rgba(255,255,255,0.06)",border:"1px solid rgba(255,255,255,0.08)",backdropFilter:"blur(10px)",WebkitBackdropFilter:"blur(10px)",padding:"12px"},xe={weather:"weather","system-stats":"dashboard","agent-status":"agents",clock:"calendar"};function fe({children:t,style:s,onClick:n}){return e.jsx("div",{onClick:n,style:{...ge,...s,cursor:n?"pointer":void 0,transition:"background 150ms ease"},onMouseDown:n?r=>{r.currentTarget.style.background="rgba(255,255,255,0.1)"}:void 0,onMouseUp:n?r=>{r.currentTarget.style.background=ge.background}:void 0,onMouseLeave:n?r=>{r.currentTarget.style.background=ge.background}:void 0,children:t})}function re(t){switch(t){case"clock":return e.jsx(ot,{});case"system-stats":return e.jsx(ut,{});case"greeting":return e.jsx(es,{});case"agent-status":return e.jsx(lt,{});case"weather":return e.jsx(ht,{});case"quick-notes":return e.jsx(ct,{});default:return null}}function ns({page:t,onOpenApp:s}){const n=[];for(let r=0;r{if(r.kind==="widgets"){const a=[];let u=!1;for(let l=0;ls(p):void 0,children:re(g.widgetType)}),e.jsx(fe,{style:{flex:1},onClick:h?()=>s(h):void 0,children:re(d.widgetType)})]},`pair-${g.index}`)),u=!0}else{const p=xe[g.widgetType];a.push(e.jsx(fe,{onClick:p?()=>s(p):void 0,children:re(g.widgetType)},g.index))}}return e.jsx(D.Fragment,{children:a},`wg-${i}`)}return e.jsx("div",{style:{display:"grid",gridTemplateColumns:"repeat(4, 1fr)",gap:"12px",padding:"8px 4px"},children:r.items.map(({appId:a,index:u})=>{const l=L(a);if(!l)return null;const g=ts(l.icon),d=He[l.category]??He.platform;return e.jsxs("button",{onClick:()=>s(a),style:{display:"flex",flexDirection:"column",alignItems:"center",gap:"6px",background:"none",border:"none",cursor:"pointer",padding:0},"aria-label":l.name,children:[e.jsx("div",{style:{width:60,height:60,borderRadius:16,background:d,display:"flex",alignItems:"center",justifyContent:"center"},children:e.jsx(g,{size:26,color:"rgba(255,255,255,0.9)"})}),e.jsx("span",{style:{fontSize:11,color:"rgba(255,255,255,0.8)",textAlign:"center",lineHeight:1.2,maxWidth:64,overflow:"hidden",textOverflow:"ellipsis",whiteSpace:"nowrap"},children:l.name})]},u)})},`ag-${i}`)})})}function ss({onOpenApp:t}){const s=ie(g=>g.pages),n=ie(g=>g.activePageIndex),r=ie(g=>g.setActivePage),i=D.useRef(null),a=s[n]??s[0],u=D.useCallback(g=>{var d;i.current=((d=g.touches[0])==null?void 0:d.clientX)??null},[]),l=D.useCallback(g=>{var f;if(i.current===null)return;const d=(((f=g.changedTouches[0])==null?void 0:f.clientX)??0)-i.current;i.current=null,!(Math.abs(d)<50)&&(d<0&&n0&&n>0&&r(n-1))},[n,s.length,r]);return e.jsxs("div",{style:{height:"100%",display:"flex",flexDirection:"column"},children:[e.jsx("div",{style:{flex:1,overflowY:"auto",padding:"12px 16px 0"},onTouchStart:u,onTouchEnd:l,children:a&&e.jsx(ns,{page:a,onOpenApp:t})}),e.jsx("div",{style:{display:"flex",flexDirection:"row",alignItems:"center",justifyContent:"center",gap:10,padding:"12px 0",flexShrink:0},role:"tablist","aria-label":"Home screen pages",children:s.map((g,d)=>{const f=d===n;return e.jsx("button",{role:"tab","aria-selected":f,"aria-label":`Page ${d+1}`,onClick:()=>!f&&r(d),style:{width:f?36:12,height:12,borderRadius:f?6:"50%",background:f?"rgba(255,255,255,0.7)":"rgba(255,255,255,0.2)",border:"none",padding:0,cursor:f?"default":"pointer",transition:"width 0.2s ease, background 0.2s ease"}},d)})})]})}function Ue({onDone:t,invitedUsername:s,inviteCode:n,defaultAutoLogin:r}){const i=!!(s&&n),[a,u]=o.useState(s??""),[l,g]=o.useState(""),[d,f]=o.useState(""),[m,p]=o.useState(""),[h,c]=o.useState(""),[x,y]=o.useState(r??!i),[w,b]=o.useState(""),[j,k]=o.useState(!1),N=m.length>=4,C=m.length>0&&m===h,A=a.trim().length>0&&l.trim().length>0&&N&&C;async function E(v){if(v.preventDefault(),!!A){k(!0),b("");try{const W=i?"/auth/complete":"/auth/setup",T={username:a.trim(),full_name:l.trim(),email:d.trim(),password:m,auto_login:x};i&&(T.invite_code=n);const O=await fetch(W,{method:"POST",headers:{"Content-Type":"application/json"},credentials:"include",body:JSON.stringify(T)});if(!O.ok){const $=await O.json().catch(()=>({}));b(($==null?void 0:$.error)??`Setup failed (${O.status})`),k(!1);return}t()}catch{b("Network error — please try again"),k(!1)}}}return e.jsx("div",{className:"h-screen w-screen flex items-center justify-center overflow-y-auto",style:{background:"linear-gradient(160deg, #1a1b2e 0%, #1e2140 40%, #252848 100%)",paddingTop:"calc(env(safe-area-inset-top, 0px) + 16px)",paddingBottom:"calc(env(safe-area-inset-bottom, 0px) + 16px)",paddingLeft:"calc(env(safe-area-inset-left, 0px) + 16px)",paddingRight:"calc(env(safe-area-inset-right, 0px) + 16px)"},children:e.jsxs("form",{onSubmit:E,className:"w-full max-w-md p-6 rounded-2xl border border-white/10",style:{backgroundColor:"rgba(255,255,255,0.04)",backdropFilter:"blur(20px)"},"aria-label":i?"Complete your account":"Welcome to taOS",children:[e.jsxs("div",{className:"flex flex-col items-center gap-3 mb-6",children:[e.jsx("div",{className:"w-14 h-14 rounded-2xl flex items-center justify-center",style:{background:"linear-gradient(135deg, #8b92a3, #5b6170)"},children:e.jsx(Ot,{size:24,className:"text-white"})}),e.jsx("h1",{className:"text-lg font-semibold text-shell-text",children:i?"Complete your account":"Welcome to taOS"}),e.jsx("p",{className:"text-xs text-shell-text-secondary text-center",children:i?"Set a password and fill in your details to activate your account.":"Set up your account. You can change any of these later in Settings."})]}),e.jsxs("div",{className:"space-y-3",children:[e.jsx(J,{label:"Username",id:"onb-username",required:!0,children:i?e.jsx("div",{id:"onb-username",className:"onb-input opacity-60 cursor-not-allowed","aria-readonly":"true",role:"textbox",children:a}):e.jsx("input",{id:"onb-username",type:"text",value:a,onChange:v=>u(v.target.value.replace(/\s+/g,"").toLowerCase()),autoComplete:"username",autoFocus:!0,placeholder:"jay",className:"onb-input"})}),e.jsx(J,{label:"Full name",id:"onb-fullname",required:!0,children:e.jsx("input",{id:"onb-fullname",type:"text",value:l,onChange:v=>g(v.target.value),autoComplete:"name",autoFocus:i,placeholder:"Jay Doe",className:"onb-input"})}),e.jsx(J,{label:"Email",id:"onb-email",hint:"Used for cloud services later. Optional today.",children:e.jsx("input",{id:"onb-email",type:"email",value:d,onChange:v=>f(v.target.value),autoComplete:"email",placeholder:"you@example.com",className:"onb-input"})}),e.jsx(J,{label:"Password",id:"onb-password",required:!0,hint:"At least 4 characters.",children:e.jsx("input",{id:"onb-password",type:"password",value:m,onChange:v=>p(v.target.value),autoComplete:"new-password",className:"onb-input"})}),e.jsxs(J,{label:"Confirm password",id:"onb-confirm",required:!0,children:[e.jsx("input",{id:"onb-confirm",type:"password",value:h,onChange:v=>c(v.target.value),autoComplete:"new-password",className:"onb-input","aria-invalid":h.length>0&&!C}),h.length>0&&!C&&e.jsx("p",{className:"text-[11px] text-red-400 mt-1",children:"Passwords don't match."})]}),e.jsxs("label",{htmlFor:"onb-autologin",className:"flex items-start gap-3 mt-1 cursor-pointer select-none",children:[e.jsx("input",{id:"onb-autologin",type:"checkbox",checked:x,onChange:v=>y(v.target.checked),className:"mt-0.5 w-4 h-4 accent-accent cursor-pointer"}),e.jsxs("span",{className:"text-xs text-shell-text-secondary leading-snug",children:["Stay signed in on this device",e.jsx("span",{className:"block text-[10px] text-shell-text-tertiary mt-0.5",children:"Skips the login screen for a year. Turn off if this is a shared device."})]})]})]}),w&&e.jsx("p",{className:"text-xs text-red-400 mt-3 text-center",role:"alert",children:w}),e.jsx("button",{type:"submit",disabled:!A||j,className:"w-full mt-5 px-4 py-2.5 rounded-lg bg-accent text-white text-sm font-medium hover:brightness-110 disabled:opacity-40 disabled:cursor-not-allowed transition-all",children:j?i?"Activating...":"Setting up...":i?"Activate account":"Get started"}),e.jsx("style",{children:` +const __vite__mapDeps=(i,m=__vite__mapDeps,d=(m.f||(m.f=["assets/MessagesApp-CkhTvSE9.js","assets/vendor-react-l6srOxy7.js","assets/toolbar-UW6q5pkx.js","assets/vendor-radix-BhM7AEEG.js","assets/vendor-layout-B-pp9n1f.js","assets/vendor-layout-BfitWg9R.css","assets/MobileSplitView-B-4MQO2C.js","assets/vendor-icons--yQaiqiL.js","assets/use-is-mobile-v5lglusa.js","assets/dnd-bus-CdEoCWzR.js","assets/AgentsApp-BZw6W6Vy.js","assets/framework-api-B6uX1y0T.js","assets/models-D8xGfVt0.js","assets/cluster-Ca85Gm-W.js","assets/FilesApp-DpnvIlme.js","assets/StoreApp-B9C6ujYf.js","assets/SettingsApp-CR8h0q_c.js","assets/tokens-BKHlNYpw.js","assets/tokens-DbWedNtZ.css","assets/vendor-codemirror-aNcHammg.js","assets/ModelsApp-BGQXnEI3.js","assets/ProvidersApp-BZ0Cnn9e.js","assets/ActivityApp-B9wIvJAK.js","assets/ClusterApp-oYzyi0Dp.js","assets/MemoryApp-Dw5harOM.js","assets/MCPApp-DBMY1x8q.js","assets/ChannelsApp-BveF_Oog.js","assets/SecretsApp-Dq-GKn40.js","assets/TasksApp-CcqxzxyH.js","assets/ImportApp-CB2pqwOR.js","assets/ImagesApp-DrJsImHG.js","assets/LibraryApp-BD1Wtjm7.js","assets/knowledge-ES9kK4zW.js","assets/RedditApp-CVpnnpBP.js","assets/YouTubeApp-CAVU-1ZB.js","assets/GitHubApp-B8-CS8Px.js","assets/XApp-CKMiMFvk.js","assets/AgentBrowsersApp-Ch7Kx-O4.js","assets/CalculatorApp-Chexv_Sm.js","assets/vendor-mathjs-B2vxIMHs.js","assets/CalendarApp-DZD5-sDA.js","assets/ContactsApp-DDczp9Hc.js","assets/BrowserApp-KbremVMB.js","assets/MediaPlayerApp-CYFx0qCR.js","assets/vendor-plyr-CqS7_LjI.js","assets/vendor-plyr-vOeuwXUh.css","assets/TextEditorApp-DX1ldFmW.js","assets/ImageViewerApp-IGHKuKLt.js","assets/TerminalApp-BxZkz7_e.js","assets/vendor-xterm-BZOrcpYI.js","assets/vendor-xterm-6GBZ9nXN.css","assets/ChessApp--VzQGvct.js","assets/vendor-chess-4YJtV_R7.js","assets/WordleApp-3FSioJkg.js","assets/CrosswordsApp-C75aS7vj.js"])))=>i.map(i=>d[i]); +import"./tokens-BKHlNYpw.js";import{r as o,b as D,j as e,p as gt}from"./vendor-react-l6srOxy7.js";import{R as xt,T as ft,P as bt,C as yt,I as Q,S as wt}from"./vendor-radix-BhM7AEEG.js";import{_ as z}from"./vendor-codemirror-aNcHammg.js";import{C as Ye,M as jt,a as vt,Z as kt,S as X,L as be,B as ae,P as St,b as Je,c as Ke,R as Ct,d as zt,e as Ce,f as Xe,H as Nt,X as P,g as Ze,h as _t,A as Tt,i as At,j as Et,F as It,I as Lt,k as Wt,l as Rt,m as Qe,n as G,o as H,p as Pt,q as Ot,r as Mt,T as Dt,s as Ft,t as $t,u as Ht,v as et,w as Ut,x as Bt,y as Vt}from"./vendor-icons--yQaiqiL.js";import{R as Gt,G as qt}from"./vendor-layout-B-pp9n1f.js";import{r as ze,B as Yt}from"./toolbar-UW6q5pkx.js";function Jt(){const[t,s]=o.useState(new Date);return o.useEffect(()=>{const r=setInterval(()=>s(new Date),3e4);return()=>clearInterval(r)},[]),t.toLocaleDateString("en-GB",{weekday:"short",day:"numeric",month:"short"})+" "+t.toLocaleTimeString("en-GB",{hour:"2-digit",minute:"2-digit"})}const Ne=t=>{let s;const n=new Set,r=(d,f)=>{const m=typeof d=="function"?d(s):d;if(!Object.is(m,s)){const p=s;s=f??(typeof m!="object"||m===null)?m:Object.assign({},s,m),n.forEach(h=>h(s,p))}},i=()=>s,l={setState:r,getState:i,getInitialState:()=>g,subscribe:d=>(n.add(d),()=>n.delete(d))},g=s=t(r,i,l);return l},Kt=(t=>t?Ne(t):Ne),Xt=t=>t;function Zt(t,s=Xt){const n=D.useSyncExternalStore(t.subscribe,D.useCallback(()=>s(t.getState()),[t,s]),D.useCallback(()=>s(t.getInitialState()),[t,s]));return D.useDebugValue(n),n}const _e=t=>{const s=Kt(t),n=r=>Zt(s,r);return Object.assign(n,s),n},q=(t=>t?_e(t):_e),Qt={clock:{w:3,h:2,minW:2,minH:2},"agent-status":{w:4,h:3,minW:2,minH:2},"quick-notes":{w:4,h:4,minW:2,minH:2},"system-stats":{w:3,h:3,minW:2,minH:2},weather:{w:3,h:3,minW:2,minH:2}};let en=1;function tn(){return`widget-${Date.now()}-${en++}`}function nn(t,s,n){for(let i=0;i<100;i++)for(let a=0;a<=12-s;a++)if(!t.some(l=>al.x&&il.y))return{x:a,y:i};return{x:0,y:0}}const ye="widgets",tt=`taos-pref:${ye}`,sn=500,rn=[{id:"default-clock",type:"clock",x:0,y:0,w:3,h:2},{id:"default-agents",type:"agent-status",x:3,y:0,w:4,h:3}];function an(){try{const t=localStorage.getItem(tt);if(!t)return null;const s=JSON.parse(t);return Array.isArray(s==null?void 0:s.widgets)&&typeof(s==null?void 0:s.showWidgets)=="boolean"?s:null}catch{return null}}function nt(t){try{localStorage.setItem(tt,JSON.stringify(t))}catch{}}const U=an(),R=q((t,s)=>({widgets:(U==null?void 0:U.widgets)??rn,showWidgets:(U==null?void 0:U.showWidgets)??!0,hydrated:!1,addWidget(n){const r=Qt[n]??{w:3,h:2},i=nn(s().widgets,r.w,r.h),a={id:tn(),type:n,x:i.x,y:i.y,w:r.w,h:r.h,minW:r.minW,minH:r.minH};t(u=>({widgets:[...u.widgets,a]}))},removeWidget(n){t(r=>({widgets:r.widgets.filter(i=>i.id!==n)}))},updateLayout(n){t(r=>({widgets:r.widgets.map(i=>{const a=n.find(u=>u.id===i.id);return a?{...i,x:a.x,y:a.y,w:a.w,h:a.h}:i})}))},toggleWidgets(){t(n=>({showWidgets:!n.showWidgets}))}}));function on(t,s){if(!t||!Array.isArray(s.widgets)||t.showWidgets!==s.showWidgets||t.widgets.length!==s.widgets.length)return!1;for(let n=0;n{try{const t=await fetch(`/api/preferences/${ye}`);if(!t.ok){R.setState({hydrated:!0});return}const s=await t.json();if(s&&Array.isArray(s.widgets)&&typeof s.showWidgets=="boolean"){const r={widgets:s.widgets,showWidgets:s.showWidgets},i={widgets:R.getState().widgets,showWidgets:R.getState().showWidgets};on(i,r)?R.setState({hydrated:!0}):R.setState({widgets:r.widgets,showWidgets:r.showWidgets,hydrated:!0}),nt(r)}else R.setState({hydrated:!0})}catch{R.setState({hydrated:!0})}})();let ee=null;R.subscribe(t=>{if(!t.hydrated)return;const s={widgets:t.widgets,showWidgets:t.showWidgets};nt(s),ee!==null&&clearTimeout(ee),ee=setTimeout(()=>{ee=null,fetch(`/api/preferences/${ye}`,{method:"PUT",headers:{"Content-Type":"application/json"},body:JSON.stringify(s)}).catch(()=>{})},sn)});let ln=0;const F=q((t,s)=>({notifications:[],centreOpen:!1,addNotification(n){const r=`notif-${++ln}`,i={...n,id:r,read:!1,timestamp:Date.now()};return t(a=>({notifications:[i,...a.notifications].slice(0,100)})),r},markRead(n){t(r=>({notifications:r.notifications.map(i=>i.id===n?{...i,read:!0}:i)}))},markAllRead(){t(n=>({notifications:n.notifications.map(r=>({...r,read:!0}))}))},dismiss(n){t(r=>({notifications:r.notifications.filter(i=>i.id!==n)}))},clearAll(){t({notifications:[]})},toggleCentre(){t(n=>({centreOpen:!n.centreOpen}))},closeCentre(){t({centreOpen:!1})},unreadCount(){return s().notifications.filter(n=>!n.read).length}}));let cn=0;const _=q((t,s)=>({windows:[],nextZIndex:1,openWindow(n,r,i){const a=s().windows.find(f=>f.appId===n);if(a)return s().focusWindow(a.id),a.id;const u=`win-${++cn}`,l=s().nextZIndex,g=s().windows.length%8*30,d={id:u,appId:n,position:{x:80+g,y:60+g},size:r,zIndex:l,minimized:!1,maximized:!1,snapped:null,focused:!0,props:i};return t(f=>({windows:f.windows.map(m=>({...m,focused:!1})).concat(d),nextZIndex:l+1})),u},closeWindow(n){t(r=>({windows:r.windows.filter(i=>i.id!==n)}))},focusWindow(n){const r=s().nextZIndex;t(i=>({windows:i.windows.map(a=>({...a,focused:a.id===n,zIndex:a.id===n?r:a.zIndex})),nextZIndex:r+1}))},minimizeWindow(n){t(r=>({windows:r.windows.map(i=>i.id===n?{...i,minimized:!0,focused:!1}:i)}))},restoreWindow(n){const r=s().nextZIndex;t(i=>({windows:i.windows.map(a=>a.id===n?{...a,minimized:!1,focused:!0,zIndex:r}:{...a,focused:!1}),nextZIndex:r+1}))},maximizeWindow(n){t(r=>({windows:r.windows.map(i=>i.id===n?{...i,maximized:!i.maximized}:i)}))},updatePosition(n,r,i){t(a=>({windows:a.windows.map(u=>u.id===n?{...u,position:{x:r,y:i}}:u)}))},updateSize(n,r,i){t(a=>({windows:a.windows.map(u=>u.id===n?{...u,size:{w:r,h:i}}:u)}))},snapWindow(n,r){t(i=>({windows:i.windows.map(a=>a.id===n?{...a,snapped:r}:a)}))},runningAppIds(){return s().windows.map(n=>n.appId)}})),st=[{id:"messages",name:"Messages",icon:"message-circle",category:"platform",component:()=>z(()=>import("./MessagesApp-CkhTvSE9.js"),__vite__mapDeps([0,1,2,3,4,5,6,7,8,9])).then(t=>({default:t.MessagesApp})),defaultSize:{w:900,h:600},minSize:{w:400,h:300},singleton:!0,pinned:!0,launchpadOrder:1},{id:"agents",name:"Agents",icon:"bot",category:"platform",component:()=>z(()=>import("./AgentsApp-BZw6W6Vy.js"),__vite__mapDeps([10,1,11,7,2,3,4,5,12,13])).then(t=>({default:t.AgentsApp})),defaultSize:{w:1e3,h:650},minSize:{w:500,h:400},singleton:!0,pinned:!0,launchpadOrder:2},{id:"files",name:"Files",icon:"folder",category:"platform",component:()=>z(()=>import("./FilesApp-DpnvIlme.js"),__vite__mapDeps([14,1,2,3,4,5,6,7,8,9])).then(t=>({default:t.FilesApp})),defaultSize:{w:900,h:550},minSize:{w:400,h:300},singleton:!0,pinned:!0,launchpadOrder:3},{id:"store",name:"Store",icon:"shopping-bag",category:"platform",component:()=>z(()=>import("./StoreApp-B9C6ujYf.js"),__vite__mapDeps([15,1,2,3,4,5,11,7])).then(t=>({default:t.StoreApp})),defaultSize:{w:1e3,h:700},minSize:{w:600,h:400},singleton:!0,pinned:!0,launchpadOrder:4},{id:"settings",name:"Settings",icon:"settings",category:"platform",component:()=>z(()=>import("./SettingsApp-CR8h0q_c.js"),__vite__mapDeps([16,1,2,3,4,5,7,17,18,19])).then(t=>({default:t.SettingsApp})),defaultSize:{w:800,h:550},minSize:{w:500,h:400},singleton:!0,pinned:!0,launchpadOrder:5},{id:"models",name:"Models",icon:"brain",category:"platform",component:()=>z(()=>import("./ModelsApp-BGQXnEI3.js"),__vite__mapDeps([20,1,2,3,4,5,12,7])).then(t=>({default:t.ModelsApp})),defaultSize:{w:900,h:600},minSize:{w:500,h:400},singleton:!0,pinned:!1,launchpadOrder:6},{id:"providers",name:"Providers",icon:"cloud",category:"platform",component:()=>z(()=>import("./ProvidersApp-BZ0Cnn9e.js"),__vite__mapDeps([21,1,2,3,4,5,6,7,8,17,18,19])).then(t=>({default:t.ProvidersApp})),defaultSize:{w:950,h:640},minSize:{w:600,h:400},singleton:!0,pinned:!1,launchpadOrder:6.5},{id:"dashboard",name:"Activity",icon:"activity",category:"platform",component:()=>z(()=>import("./ActivityApp-B9wIvJAK.js"),__vite__mapDeps([22,1,2,3,4,5,13,7])).then(t=>({default:t.ActivityApp})),defaultSize:{w:1100,h:720},minSize:{w:600,h:400},singleton:!0,pinned:!1,launchpadOrder:7},{id:"cluster",name:"Cluster",icon:"network",category:"platform",component:()=>z(()=>import("./ClusterApp-oYzyi0Dp.js"),__vite__mapDeps([23,1,2,3,4,5,13,7])).then(t=>({default:t.ClusterApp})),defaultSize:{w:1e3,h:680},minSize:{w:600,h:400},singleton:!0,pinned:!1,launchpadOrder:7.5},{id:"memory",name:"Memory",icon:"database",category:"platform",component:()=>z(()=>import("./MemoryApp-Dw5harOM.js"),__vite__mapDeps([24,1,2,3,4,5,7])).then(t=>({default:t.MemoryApp})),defaultSize:{w:850,h:550},minSize:{w:450,h:350},singleton:!0,pinned:!1,launchpadOrder:8},{id:"mcp",name:"MCP",icon:"plug",category:"platform",component:()=>z(()=>import("./MCPApp-DBMY1x8q.js"),__vite__mapDeps([25,1,2,3,4,5,6,7,17,18,19])).then(t=>({default:t.MCPApp})),defaultSize:{w:1e3,h:680},minSize:{w:600,h:400},singleton:!0,pinned:!1,launchpadOrder:9.5},{id:"channels",name:"Channels",icon:"radio",category:"platform",component:()=>z(()=>import("./ChannelsApp-BveF_Oog.js"),__vite__mapDeps([26,1,2,3,4,5,6,7,8])).then(t=>({default:t.ChannelsApp})),defaultSize:{w:800,h:500},minSize:{w:450,h:350},singleton:!0,pinned:!1,launchpadOrder:9},{id:"secrets",name:"Secrets",icon:"key-round",category:"platform",component:()=>z(()=>import("./SecretsApp-Dq-GKn40.js"),__vite__mapDeps([27,1,2,3,4,5,7])).then(t=>({default:t.SecretsApp})),defaultSize:{w:750,h:500},minSize:{w:400,h:300},singleton:!0,pinned:!1,launchpadOrder:10},{id:"tasks",name:"Tasks",icon:"calendar-clock",category:"platform",component:()=>z(()=>import("./TasksApp-CcqxzxyH.js"),__vite__mapDeps([28,1,2,3,4,5,7])).then(t=>({default:t.TasksApp})),defaultSize:{w:800,h:500},minSize:{w:450,h:350},singleton:!0,pinned:!1,launchpadOrder:11},{id:"import",name:"Import",icon:"upload",category:"platform",component:()=>z(()=>import("./ImportApp-CB2pqwOR.js"),__vite__mapDeps([29,1,2,3,4,5,7])).then(t=>({default:t.ImportApp})),defaultSize:{w:700,h:450},minSize:{w:400,h:300},singleton:!0,pinned:!1,launchpadOrder:12},{id:"images",name:"Images",icon:"image",category:"platform",component:()=>z(()=>import("./ImagesApp-DrJsImHG.js"),__vite__mapDeps([30,1,2,3,4,5,12,7])).then(t=>({default:t.ImagesApp})),defaultSize:{w:900,h:600},minSize:{w:500,h:400},singleton:!0,pinned:!1,launchpadOrder:13},{id:"library",name:"Library",icon:"book-open",category:"platform",component:()=>z(()=>import("./LibraryApp-BD1Wtjm7.js"),__vite__mapDeps([31,1,6,7,8,2,3,4,5,32])).then(t=>({default:t.LibraryApp})),defaultSize:{w:1e3,h:650},minSize:{w:550,h:400},singleton:!0,pinned:!0,launchpadOrder:13.5},{id:"reddit",name:"Reddit",icon:"scroll-text",category:"platform",component:()=>z(()=>import("./RedditApp-CVpnnpBP.js"),__vite__mapDeps([33,1,2,3,4,5,32,6,7,8])).then(t=>({default:t.RedditApp})),defaultSize:{w:1e3,h:650},minSize:{w:550,h:400},singleton:!0,pinned:!1,launchpadOrder:14},{id:"youtube-library",name:"YouTube",icon:"play-circle",category:"platform",component:()=>z(()=>import("./YouTubeApp-CAVU-1ZB.js"),__vite__mapDeps([34,1,2,3,4,5,32,7])).then(t=>({default:t.YouTubeApp})),defaultSize:{w:1050,h:700},minSize:{w:600,h:450},singleton:!0,pinned:!1,launchpadOrder:14.5},{id:"github-browser",name:"GitHub",icon:"github",category:"platform",component:()=>z(()=>import("./GitHubApp-B8-CS8Px.js"),__vite__mapDeps([35,1,2,3,4,5,6,7,8])).then(t=>({default:t.GitHubApp})),defaultSize:{w:1e3,h:650},minSize:{w:550,h:400},singleton:!0,pinned:!1,launchpadOrder:15},{id:"x-monitor",name:"X",icon:"at-sign",category:"platform",component:()=>z(()=>import("./XApp-CKMiMFvk.js"),__vite__mapDeps([36,1,2,3,4,5,7])).then(t=>({default:t.XApp})),defaultSize:{w:1e3,h:650},minSize:{w:550,h:400},singleton:!0,pinned:!1,launchpadOrder:15.5},{id:"agent-browsers",name:"Browsers",icon:"globe",category:"platform",component:()=>z(()=>import("./AgentBrowsersApp-Ch7Kx-O4.js"),__vite__mapDeps([37,1,2,3,4,5,7])).then(t=>({default:t.AgentBrowsersApp})),defaultSize:{w:1e3,h:650},minSize:{w:550,h:400},singleton:!0,pinned:!1,launchpadOrder:16},{id:"weather",name:"Weather",icon:"cloud",category:"os",component:()=>z(()=>Promise.resolve().then(()=>Sn),void 0).then(t=>({default:t.WeatherApp})),defaultSize:{w:800,h:600},minSize:{w:400,h:400},singleton:!0,pinned:!1,launchpadOrder:19},{id:"calculator",name:"Calculator",icon:"calculator",category:"os",component:()=>z(()=>import("./CalculatorApp-Chexv_Sm.js"),__vite__mapDeps([38,1,2,3,4,5,39])).then(t=>({default:t.CalculatorApp})),defaultSize:{w:320,h:480},minSize:{w:280,h:400},singleton:!0,pinned:!1,launchpadOrder:20},{id:"calendar",name:"Calendar",icon:"calendar",category:"os",component:()=>z(()=>import("./CalendarApp-DZD5-sDA.js"),__vite__mapDeps([40,1,7])).then(t=>({default:t.CalendarApp})),defaultSize:{w:900,h:600},minSize:{w:600,h:400},singleton:!0,pinned:!1,launchpadOrder:21},{id:"contacts",name:"Contacts",icon:"contact",category:"os",component:()=>z(()=>import("./ContactsApp-DDczp9Hc.js"),__vite__mapDeps([41,1,2,3,4,5,6,7,8])).then(t=>({default:t.ContactsApp})),defaultSize:{w:700,h:500},minSize:{w:400,h:300},singleton:!0,pinned:!1,launchpadOrder:22},{id:"browser",name:"Browser",icon:"globe",category:"os",component:()=>z(()=>import("./BrowserApp-KbremVMB.js"),__vite__mapDeps([42,1,2,3,4,5,7])).then(t=>({default:t.BrowserApp})),defaultSize:{w:1024,h:700},minSize:{w:600,h:400},singleton:!1,pinned:!1,launchpadOrder:23},{id:"media-player",name:"Media Player",icon:"play-circle",category:"os",component:()=>z(()=>import("./MediaPlayerApp-CYFx0qCR.js"),__vite__mapDeps([43,1,44,45])).then(t=>({default:t.MediaPlayerApp})),defaultSize:{w:800,h:500},minSize:{w:400,h:300},singleton:!1,pinned:!1,launchpadOrder:24},{id:"text-editor",name:"Text Editor",icon:"file-text",category:"os",component:()=>z(()=>import("./TextEditorApp-DX1ldFmW.js").then(t=>t.T),__vite__mapDeps([46,1,19,7])).then(t=>({default:t.TextEditorApp})),defaultSize:{w:800,h:550},minSize:{w:400,h:300},singleton:!1,pinned:!1,launchpadOrder:25},{id:"image-viewer",name:"Image Viewer",icon:"eye",category:"os",component:()=>z(()=>import("./ImageViewerApp-IGHKuKLt.js"),__vite__mapDeps([47,1,7])).then(t=>({default:t.ImageViewerApp})),defaultSize:{w:800,h:600},minSize:{w:400,h:300},singleton:!1,pinned:!1,launchpadOrder:26},{id:"terminal",name:"Terminal",icon:"terminal",category:"os",component:()=>z(()=>import("./TerminalApp-BxZkz7_e.js"),__vite__mapDeps([48,1,49,50,2,3,4,5])).then(t=>({default:t.TerminalApp})),defaultSize:{w:800,h:500},minSize:{w:400,h:250},singleton:!1,pinned:!1,launchpadOrder:27},{id:"chess",name:"Chess",icon:"crown",category:"game",component:()=>z(()=>import("./ChessApp--VzQGvct.js"),__vite__mapDeps([51,1,52])).then(t=>({default:t.ChessApp})),defaultSize:{w:700,h:700},minSize:{w:500,h:500},singleton:!0,pinned:!1,launchpadOrder:40},{id:"wordle",name:"Wordle",icon:"spell-check",category:"game",component:()=>z(()=>import("./WordleApp-3FSioJkg.js"),__vite__mapDeps([53,1])).then(t=>({default:t.WordleApp})),defaultSize:{w:500,h:650},minSize:{w:400,h:550},singleton:!0,pinned:!1,launchpadOrder:41},{id:"crosswords",name:"Crosswords",icon:"grid-3x3",category:"game",component:()=>z(()=>import("./CrosswordsApp-C75aS7vj.js"),__vite__mapDeps([54,1])).then(t=>({default:t.CrosswordsApp})),defaultSize:{w:700,h:600},minSize:{w:500,h:450},singleton:!0,pinned:!1,launchpadOrder:42}];function L(t){return st.find(s=>s.id===t)}function rt(){return[...st].sort((t,s)=>t.launchpadOrder-s.launchpadOrder)}function te({icon:t,label:s,value:n,colour:r}){return e.jsxs("div",{className:"flex items-center gap-1 px-1.5 py-0.5 rounded hover:bg-white/5 transition-colors",title:`${s}: ${n!==null?`${Math.round(n)}%`:"—"}`,"aria-label":`${s} usage ${n!==null?`${Math.round(n)} percent`:"unknown"}`,children:[e.jsx("span",{className:"text-shell-text-tertiary",children:t}),e.jsx("div",{className:"relative w-6 h-1 rounded-full bg-white/10 overflow-hidden",children:n!==null&&e.jsx("div",{className:"absolute inset-y-0 left-0 transition-all rounded-full",style:{width:`${Math.min(100,Math.max(0,n))}%`,backgroundColor:r}})})]})}function ne(t){return t===null?"rgba(255,255,255,0.2)":t<50?"#43e97b":t<80?"#febc2e":"#ff5f57"}function it({compact:t=!1}){const[s,n]=o.useState(null),r=_(a=>a.openWindow);o.useEffect(()=>{let a=!1;const u=async()=>{var g,d,f;try{const m=await fetch("/api/system",{headers:{Accept:"application/json"}});if(!m.ok||!(m.headers.get("content-type")??"").includes("application/json"))return;const h=await m.json();if(a)return;const c=h.resources??h,x=h.hardware??h,y=(g=x==null?void 0:x.gpu)==null?void 0:g.type,w=(d=x==null?void 0:x.npu)==null?void 0:d.type;n({cpu_pct:c.cpu_percent??c.cpu_pct??null,ram_pct:c.ram_percent??c.ram_pct??null,ram_mb:c.ram_used_mb??null,vram_pct:c.vram_percent??c.vram_pct??null,vram_mb:c.vram_used_mb??null,vram_total_mb:((f=x==null?void 0:x.gpu)==null?void 0:f.vram_mb)??null,npu_pct:c.npu_percent??c.npu_pct??null,has_gpu:!!(y&&y!=="none"),has_npu:!!(w&&w!=="none")})}catch{}};u();const l=setInterval(u,3e3);return()=>{a=!0,clearInterval(l)}},[]);const i=()=>{const a=L("dashboard");a&&r("dashboard",a.defaultSize)};return s?e.jsxs("button",{onClick:i,className:`flex items-center gap-0.5 ${t?"":"px-1"}`,"aria-label":"Open Dashboard",children:[e.jsx(te,{icon:e.jsx(Ye,{size:11}),label:"CPU",value:s.cpu_pct??null,colour:ne(s.cpu_pct??null)}),e.jsx(te,{icon:e.jsx(jt,{size:11}),label:"RAM",value:s.ram_pct??null,colour:ne(s.ram_pct??null)}),s.has_gpu&&e.jsx(te,{icon:e.jsx(vt,{size:11}),label:"VRAM",value:s.vram_pct??null,colour:ne(s.vram_pct??null)}),s.has_npu&&e.jsx(te,{icon:e.jsx(kt,{size:11}),label:"NPU",value:s.npu_pct??null,colour:ne(s.npu_pct??null)})]}):null}function dn(){const t=_(a=>a.openWindow),s=async()=>{await fetch("/auth/lock",{method:"POST",credentials:"include"}).catch(()=>{}),window.location.reload()},n=()=>{t("settings",{w:760,h:520})},r=()=>{t("settings",{w:760,h:520})},i="flex items-center gap-2.5 w-full px-3 py-2 text-sm rounded-md text-shell-text-secondary hover:bg-shell-surface-hover hover:text-shell-text outline-none focus:bg-shell-surface-hover focus:text-shell-text cursor-pointer select-none transition-colors";return e.jsxs(xt,{children:[e.jsx(ft,{asChild:!0,children:e.jsx("button",{className:"p-1 rounded hover:bg-shell-surface-hover transition-colors text-shell-text-secondary","aria-label":"Power menu",title:"Power",children:e.jsx(St,{size:14})})}),e.jsx(bt,{children:e.jsxs(yt,{align:"end",sideOffset:6,className:"z-50 min-w-[180px] rounded-xl border border-white/10 bg-shell-surface p-1.5 shadow-2xl backdrop-blur-xl",style:{backgroundColor:"rgba(28,26,44,0.96)"},onEscapeKeyDown:()=>{},children:[e.jsxs(Q,{className:i,onSelect:s,children:[e.jsx(Je,{size:14}),e.jsx("span",{className:"flex-1",children:"Lock taOS"}),e.jsx("kbd",{className:"text-[10px] opacity-40 font-mono",children:"⌘L"})]}),e.jsxs(Q,{className:i,onSelect:n,children:[e.jsx(Ke,{size:14}),e.jsx("span",{className:"flex-1",children:"Settings"})]}),e.jsx(wt,{className:"my-1 h-px bg-white/10"}),e.jsxs(Q,{className:i,onSelect:r,children:[e.jsx(Ct,{size:14}),e.jsx("span",{className:"flex-1",children:"Restart server"})]}),e.jsxs(Q,{className:i,onSelect:s,children:[e.jsx(zt,{size:14}),e.jsx("span",{className:"flex-1",children:"Sign out"})]})]})})]})}function un({onSearchOpen:t}){const s=Jt(),{showWidgets:n,toggleWidgets:r}=R(),i=F(u=>u.notifications.filter(l=>!l.read).length),a=F(u=>u.toggleCentre);return e.jsxs("div",{className:"relative flex items-center px-4 shrink-0 select-none",style:{height:"var(--spacing-topbar-h)",backgroundColor:"var(--color-topbar-bg)",borderBottom:"1px solid var(--color-shell-border)"},children:[e.jsxs("div",{className:"flex items-center gap-2",children:[e.jsx("img",{src:"/static/taos-logo.png",alt:"taOS",className:"h-4 w-auto"}),e.jsx("span",{className:"text-xs font-medium text-shell-text-secondary",children:"taOS"})]}),e.jsxs("button",{onClick:t,className:"absolute left-1/2 -translate-x-1/2 flex items-center gap-2 px-3 py-1 rounded-md bg-shell-surface-hover text-shell-text-tertiary text-xs hover:bg-shell-surface-active transition-colors","aria-label":"Search",children:[e.jsx(X,{size:12}),e.jsx("span",{children:"Search"}),e.jsx("kbd",{className:"ml-2 text-[10px] opacity-50",children:"Ctrl+Space"})]}),e.jsxs("div",{className:"flex items-center gap-3 ml-auto",children:[e.jsx(it,{}),e.jsx("span",{className:"text-xs text-shell-text-tertiary",children:s}),e.jsx(dn,{}),e.jsx("button",{onClick:r,className:`p-1 rounded transition-colors ${n?"text-accent bg-accent/10":"text-shell-text-secondary hover:bg-shell-surface-hover"}`,"aria-label":"Toggle widgets",title:"Toggle widgets",children:e.jsx(be,{size:14})}),e.jsxs("button",{onClick:a,className:"relative p-1 rounded hover:bg-shell-surface-hover transition-colors","aria-label":`Notifications${i>0?` (${i} unread)`:""}`,children:[e.jsx(ae,{size:14,className:"text-shell-text-secondary"}),i>0&&e.jsx("span",{className:"absolute top-0 right-0 w-1.5 h-1.5 bg-red-500 rounded-full"})]})]})]})}const B=[{id:"default",label:"Default",image:"url('/static/wallpaper.png')",mobileImage:"url('/static/wallpaper-mobile.png')",fallback:"#1a1b2e"},{id:"deep-indigo",label:"Deep Indigo",image:"linear-gradient(160deg, #1a1b2e 0%, #1e2140 40%, #252848 100%)",fallback:"#1a1b2e"},{id:"midnight",label:"Midnight Blue",image:"linear-gradient(135deg, #0f0c29 0%, #302b63 50%, #24243e 100%)",fallback:"#0f0c29"},{id:"aurora",label:"Aurora",image:"linear-gradient(135deg, #0f2027 0%, #203a43 40%, #2c5364 100%)",fallback:"#0f2027"},{id:"dusk",label:"Dusk",image:"linear-gradient(135deg, #1a1a2e 0%, #16213e 40%, #0f3460 100%)",fallback:"#1a1a2e"},{id:"forest",label:"Forest",image:"linear-gradient(160deg, #0d1b0e 0%, #1a2f1a 40%, #1e3a1e 100%)",fallback:"#0d1b0e"},{id:"ocean",label:"Ocean",image:"linear-gradient(160deg, #0a192f 0%, #0d2847 40%, #112d4e 100%)",fallback:"#0a192f"},{id:"charcoal",label:"Charcoal",image:"linear-gradient(180deg, #1c1c1c 0%, #2d2d2d 100%)",fallback:"#1c1c1c"},{id:"gunmetal",label:"Gunmetal",image:"linear-gradient(165deg, #16181f 0%, #1f232c 50%, #252a35 100%)",fallback:"#16181f"}],M=q(t=>({wallpaperId:"default",wallpaperImage:B[0].image,wallpaperMobileImage:B[0].mobileImage??B[0].image,wallpaperFallback:B[0].fallback,showDesktopIcons:!0,setWallpaper(s){const n=B.find(r=>r.id===s);n&&t({wallpaperId:s,wallpaperImage:n.image,wallpaperMobileImage:n.mobileImage??n.image,wallpaperFallback:n.fallback})},toggleDesktopIcons(){t(s=>({showDesktopIcons:!s.showDesktopIcons}))},getWallpapers:()=>B})),Te=16,Ae=100;function pn(t,s,n){const r=t<=Te,i=t>=n.width-Te,a=s<=n.topBarH+Ae,u=s>=n.height-n.dockH-Ae;return r&&a?"top-left":r&&u?"bottom-left":i&&a?"top-right":i&&u?"bottom-right":r?"left":i?"right":null}function at(t,s){if(!t)return null;const n=s.height-s.topBarH-s.dockH,r=Math.floor(s.width/2),i=Math.floor(n/2);switch(t){case"left":return{x:0,y:0,w:r,h:n};case"right":return{x:r,y:0,w:r,h:n};case"top-left":return{x:0,y:0,w:r,h:i};case"top-right":return{x:r,y:0,w:r,h:i};case"bottom-left":return{x:0,y:i,w:r,h:i};case"bottom-right":return{x:r,y:i,w:r,h:i}}}function hn(t){const[s,n]=o.useState(null),r=o.useCallback((a,u)=>{n(pn(a,u,t))},[t]),i=o.useCallback(()=>{const a=s;return n(null),a},[s]);return{preview:s,previewBounds:at(s,t),onDrag:r,onDragStop:i}}function mn({appId:t,windowId:s}){const n=L(t),r=o.useMemo(()=>n?o.lazy(n.component):null,[n]);return r?e.jsx(o.Suspense,{fallback:e.jsx("div",{className:"flex items-center justify-center h-full text-shell-text-tertiary",children:"Loading..."}),children:e.jsx(r,{windowId:s})}):e.jsxs("div",{className:"flex items-center justify-center h-full text-shell-text-secondary",children:["Unknown app: ",t]})}function gn({win:t,onDrag:s,onDragStop:n}){const{focusWindow:r,closeWindow:i,minimizeWindow:a,maximizeWindow:u,updatePosition:l,updateSize:g,snapWindow:d}=_(),f=L(t.appId),m=o.useRef(null),p={width:window.innerWidth,height:window.innerHeight,topBarH:32,dockH:84};let h=t.position,c=t.size;if(t.maximized)h={x:0,y:0},c={w:p.width,h:p.height-p.topBarH-p.dockH};else if(t.snapped){const k=at(t.snapped,p);k&&(h={x:k.x,y:k.y},c={w:k.w,h:k.h})}const x=o.useCallback(()=>{r(t.id),t.snapped&&(m.current={...t.position,...t.size},d(t.id,null))},[r,d,t.id,t.snapped,t.position,t.size]),y=o.useCallback((k,N)=>{s(N.x,N.y)},[s]),w=o.useCallback((k,N)=>{const C=n();C?(m.current={x:N.x,y:N.y,w:t.size.w,h:t.size.h},d(t.id,C)):l(t.id,N.x,N.y)},[n,d,l,t.id,t.size]),b=o.useCallback((k,N,C)=>{g(t.id,C.offsetWidth,C.offsetHeight)},[g,t.id]);if(t.minimized)return null;const j=(f==null?void 0:f.minSize)??{w:300,h:200};return e.jsx(Gt,{position:{x:h.x,y:h.y},size:{width:c.w,height:c.h},minWidth:j.w,minHeight:j.h,style:{zIndex:t.zIndex},dragHandleClassName:"window-titlebar",disableDragging:t.maximized,enableResizing:!t.maximized&&!t.snapped,onDragStart:x,onDrag:y,onDragStop:w,onResizeStop:b,onMouseDown:()=>r(t.id),bounds:"parent",onContextMenu:k=>k.stopPropagation(),children:e.jsxs("div",{className:`flex flex-col h-full rounded-[var(--spacing-window-radius)] overflow-hidden border ${t.focused?"border-shell-border-strong shadow-[var(--shadow-window)]":"border-shell-border shadow-[var(--shadow-window-unfocused)]"}`,style:{backgroundColor:"var(--color-shell-bg)"},children:[e.jsxs("div",{className:"window-titlebar flex items-center h-8 px-3 shrink-0 bg-shell-surface select-none cursor-default",children:[e.jsxs("div",{className:"flex gap-1.5 items-center group/traffic",children:[e.jsx("button",{className:"w-3 h-3 rounded-full bg-traffic-close hover:brightness-110 flex items-center justify-center",onClick:k=>{k.stopPropagation(),i(t.id)},"aria-label":"Close window",title:"Close",children:e.jsx("svg",{className:"opacity-0 group-hover/traffic:opacity-100 transition-opacity duration-100",width:"7",height:"7",viewBox:"0 0 7 7",style:{color:"rgba(0,0,0,0.55)"},children:e.jsx("path",{d:"M1.5 1.5L5.5 5.5M5.5 1.5L1.5 5.5",stroke:"currentColor",strokeWidth:"1.25",strokeLinecap:"round"})})}),e.jsx("button",{className:"w-3 h-3 rounded-full bg-traffic-minimize hover:brightness-110 flex items-center justify-center",onClick:k=>{k.stopPropagation(),a(t.id)},"aria-label":"Minimize window",title:"Minimize",children:e.jsx("svg",{className:"opacity-0 group-hover/traffic:opacity-100 transition-opacity duration-100",width:"7",height:"7",viewBox:"0 0 7 7",style:{color:"rgba(0,0,0,0.55)"},children:e.jsx("path",{d:"M1 3.5H6",stroke:"currentColor",strokeWidth:"1.25",strokeLinecap:"round"})})}),e.jsx("button",{className:"w-3 h-3 rounded-full bg-traffic-maximize hover:brightness-110 flex items-center justify-center",onClick:k=>{k.stopPropagation(),u(t.id)},"aria-label":t.maximized?"Restore window":"Maximize window",title:t.maximized?"Restore":"Maximize",children:t.maximized?e.jsxs("svg",{className:"opacity-0 group-hover/traffic:opacity-100 transition-opacity duration-100",width:"7",height:"7",viewBox:"0 0 7 7",style:{color:"rgba(0,0,0,0.55)"},children:[e.jsx("path",{d:"M4.5 1V2.5H6M6 2.5L4 4.5",stroke:"currentColor",strokeWidth:"1.1",strokeLinecap:"round",strokeLinejoin:"round",fill:"none"}),e.jsx("path",{d:"M2.5 6V4.5H1M1 4.5L3 2.5",stroke:"currentColor",strokeWidth:"1.1",strokeLinecap:"round",strokeLinejoin:"round",fill:"none"})]}):e.jsxs("svg",{className:"opacity-0 group-hover/traffic:opacity-100 transition-opacity duration-100",width:"7",height:"7",viewBox:"0 0 7 7",style:{color:"rgba(0,0,0,0.55)"},children:[e.jsx("path",{d:"M1 3V1H3M1 1L3 3",stroke:"currentColor",strokeWidth:"1.1",strokeLinecap:"round",strokeLinejoin:"round",fill:"none"}),e.jsx("path",{d:"M6 4V6H4M6 6L4 4",stroke:"currentColor",strokeWidth:"1.1",strokeLinecap:"round",strokeLinejoin:"round",fill:"none"})]})})]}),e.jsx("div",{className:"flex-1 text-center text-xs text-shell-text-secondary truncate",children:(f==null?void 0:f.name)??t.appId}),e.jsx("div",{className:"w-12"})]}),e.jsx("div",{className:"flex-1 overflow-auto bg-shell-bg-deep",children:e.jsx(mn,{appId:t.appId,windowId:t.id})})]})})}function xn({bounds:t}){return t?e.jsx("div",{className:"fixed pointer-events-none z-[9998] rounded-lg border-2 border-dashed transition-all duration-150",style:{left:t.x,top:t.y,width:t.w,height:t.h,backgroundColor:"var(--color-snap-preview)",borderColor:"var(--color-snap-border)"}}):null}const fn=175,bn=290;function yn(t){return t<=fn?"s":t<=bn?"m":"l"}function Y(){const t=o.useRef(null),[s,n]=o.useState({width:200,height:200,tier:"m"});return o.useEffect(()=>{const r=t.current;if(!r)return;const i=(u,l)=>{n({width:u,height:l,tier:yn(l)})};i(r.offsetWidth,r.offsetHeight);const a=new ResizeObserver(u=>{for(const l of u)i(l.contentRect.width,l.contentRect.height)});return a.observe(r),()=>a.disconnect()},[]),[t,s]}function ot(){const[t,s]=o.useState(new Date),[n,{tier:r}]=Y();o.useEffect(()=>{const d=setInterval(()=>s(new Date),1e3);return()=>clearInterval(d)},[]);const i=t.toLocaleTimeString(void 0,{hour:"2-digit",minute:"2-digit"}),a=t.toLocaleTimeString(void 0,{hour:"2-digit",minute:"2-digit",second:"2-digit"}),u=t.toLocaleDateString(void 0,{weekday:"long",year:"numeric",month:"long",day:"numeric"}),l=t.toLocaleDateString(void 0,{weekday:"short",month:"short",day:"numeric"}),g=t.toLocaleDateString(void 0,{weekday:"long"});return e.jsxs("div",{ref:n,style:{display:"flex",flexDirection:"column",alignItems:"center",justifyContent:"center",height:"100%",gap:r==="s"?0:4},"aria-label":"Clock widget",role:"region",children:[r==="s"&&e.jsx("span",{style:{fontSize:"1.8rem",fontWeight:600,fontVariantNumeric:"tabular-nums",color:"rgba(255,255,255,0.95)",lineHeight:1,letterSpacing:"-0.02em"},"aria-live":"polite","aria-label":`Current time: ${i}`,children:i}),r==="m"&&e.jsxs(e.Fragment,{children:[e.jsx("span",{style:{fontSize:"2.4rem",fontWeight:600,fontVariantNumeric:"tabular-nums",color:"rgba(255,255,255,0.95)",lineHeight:1,letterSpacing:"-0.03em"},"aria-live":"polite","aria-label":`Current time: ${a}`,children:a}),e.jsx("span",{style:{fontSize:"0.7rem",color:"rgba(255,255,255,0.45)",letterSpacing:"0.03em",marginTop:4},children:l})]}),r==="l"&&e.jsxs(e.Fragment,{children:[e.jsx("span",{style:{fontSize:"2.8rem",fontWeight:600,fontVariantNumeric:"tabular-nums",color:"rgba(255,255,255,0.95)",lineHeight:1,letterSpacing:"-0.03em"},"aria-live":"polite","aria-label":`Current time: ${a}`,children:a}),e.jsx("span",{style:{fontSize:"0.85rem",fontWeight:600,color:"rgba(255,255,255,0.6)",letterSpacing:"0.08em",textTransform:"uppercase",marginTop:6},children:g}),e.jsx("span",{style:{fontSize:"0.7rem",color:"rgba(255,255,255,0.35)",marginTop:2},children:u})]})]})}function Ee(t){return t==="online"||t==="running"?"#4ade80":t==="offline"||t==="stopped"?"#f87171":"#fbbf24"}function ue({color:t}){return e.jsxs("span",{style:{position:"relative",display:"inline-flex",width:8,height:8,flexShrink:0},"aria-hidden":"true",children:[e.jsx("span",{style:{position:"absolute",inset:0,borderRadius:"50%",background:t,opacity:.4,animation:"ping 1.5s cubic-bezier(0,0,0.2,1) infinite"}}),e.jsx("span",{style:{position:"relative",display:"inline-block",width:8,height:8,borderRadius:"50%",background:t}})]})}function lt(){const[t,s]=o.useState(null),[n,r]=o.useState(!1),[i,{tier:a}]=Y();o.useEffect(()=>{let m=!1;async function p(){try{const c=await fetch("/api/agents",{headers:{Accept:"application/json"}});if(!c.ok)throw new Error("Failed");if(!(c.headers.get("content-type")??"").includes("application/json")){m||(s([]),r(!1));return}const y=await c.json();if(!m){const w=Array.isArray(y)?y:y.agents??y.items??[];s(w.map(b=>({name:b.name??b.id??"Unknown",status:b.status??"unknown",emoji:typeof b.emoji=="string"?b.emoji:void 0,framework:typeof b.framework=="string"?b.framework:void 0}))),r(!1)}}catch{m||r(!0)}}p();const h=setInterval(p,15e3);return()=>{m=!0,clearInterval(h)}},[]);const u=t?t.filter(m=>m.status==="running"||m.status==="online").length:0,l=t?t.length:0,g=u>0?"#4ade80":"#fbbf24",d={fontSize:"0.65rem",color:"rgba(255,255,255,0.35)"},f={fontSize:"0.65rem",fontWeight:600,color:"rgba(255,255,255,0.4)",textTransform:"uppercase",letterSpacing:"0.06em"};return e.jsxs("div",{ref:i,style:{height:"100%",display:"flex",flexDirection:"column",padding:a==="s"?"0 2px":"2px 2px 4px",overflow:"hidden"},"aria-label":"Agent status widget",role:"region",children:[a==="s"&&e.jsxs("div",{style:{display:"flex",alignItems:"center",justifyContent:"center",height:"100%",gap:8},children:[e.jsx(ue,{color:g}),e.jsx("span",{style:{fontSize:"1.2rem",fontWeight:600,color:"rgba(255,255,255,0.9)",fontVariantNumeric:"tabular-nums"},children:n||!t?"—":l}),e.jsx("span",{style:{fontSize:"0.7rem",color:"rgba(255,255,255,0.45)"},children:l===1?"agent":"agents"})]}),a==="m"&&e.jsxs(e.Fragment,{children:[e.jsx("div",{style:f,children:"Agents"}),e.jsxs("div",{style:{display:"flex",alignItems:"baseline",gap:6,margin:"4px 0 8px"},children:[e.jsx("span",{style:{fontSize:"1.6rem",fontWeight:600,color:"rgba(255,255,255,0.95)",fontVariantNumeric:"tabular-nums",lineHeight:1},children:n||!t?"—":l}),!n&&t&&e.jsxs("span",{style:{fontSize:"0.7rem",color:"rgba(255,255,255,0.4)"},children:[u," running"]})]}),!n&&t&&t.slice(0,2).map(m=>e.jsxs("div",{style:{display:"flex",alignItems:"center",gap:6,fontSize:"0.78rem",color:"rgba(255,255,255,0.8)",marginBottom:4},children:[e.jsx(ue,{color:Ee(m.status)}),e.jsx("span",{"aria-hidden":"true",style:{fontSize:"0.95rem",lineHeight:1},children:ze(m.emoji,m.framework)}),e.jsx("span",{style:{overflow:"hidden",textOverflow:"ellipsis",whiteSpace:"nowrap",flex:1},children:m.name}),e.jsx("span",{style:d,children:m.status})]},m.name)),n&&e.jsx("span",{style:{fontSize:"0.75rem",color:"rgba(255,255,255,0.35)"},children:"Unavailable"}),!t&&!n&&e.jsx("span",{style:{fontSize:"0.75rem",color:"rgba(255,255,255,0.35)"},children:"Loading…"})]}),a==="l"&&e.jsxs(e.Fragment,{children:[e.jsx("div",{style:f,children:"Agents"}),e.jsxs("div",{style:{display:"flex",alignItems:"baseline",gap:6,margin:"4px 0 10px"},children:[e.jsx("span",{style:{fontSize:"1.8rem",fontWeight:600,color:"rgba(255,255,255,0.95)",fontVariantNumeric:"tabular-nums",lineHeight:1},children:n||!t?"—":l}),!n&&t&&e.jsxs("span",{style:{fontSize:"0.75rem",color:"rgba(255,255,255,0.4)"},children:[u," running · ",l-u," idle"]})]}),n||!t?e.jsx("span",{style:{fontSize:"0.75rem",color:"rgba(255,255,255,0.35)"},children:n?"Agents unavailable":"Loading…"}):t.length===0?e.jsx("span",{style:{fontSize:"0.75rem",color:"rgba(255,255,255,0.35)"},children:"No agents configured"}):e.jsx("div",{style:{display:"flex",flexDirection:"column",gap:5,overflowY:"auto",flex:1},children:t.map(m=>e.jsxs("div",{style:{display:"flex",alignItems:"center",gap:8,fontSize:"0.8rem",color:"rgba(255,255,255,0.85)"},children:[e.jsx(ue,{color:Ee(m.status)}),e.jsx("span",{"aria-hidden":"true",style:{fontSize:"0.95rem",lineHeight:1},children:ze(m.emoji,m.framework)}),e.jsx("span",{style:{overflow:"hidden",textOverflow:"ellipsis",whiteSpace:"nowrap",flex:1},children:m.name}),e.jsx("span",{style:{...d,background:"rgba(255,255,255,0.06)",borderRadius:4,padding:"1px 6px",whiteSpace:"nowrap"},children:m.status})]},m.name))})]})]})}const Ie="tinyagentos-quick-notes";function ct(){const[t,s]=o.useState(()=>{try{return localStorage.getItem(Ie)??""}catch{return""}}),[n,{tier:r}]=Y(),i=o.useCallback(u=>{const l=u.target.value;s(l);try{localStorage.setItem(Ie,l)}catch{}},[]),a=r!=="s";return e.jsxs("div",{ref:n,style:{height:"100%",display:"flex",flexDirection:"column",padding:r==="s"?"2px":"2px 2px 4px"},"aria-label":"Quick notes widget",role:"region",children:[a&&e.jsx("div",{style:{fontSize:"0.65rem",fontWeight:600,color:"rgba(255,255,255,0.4)",textTransform:"uppercase",letterSpacing:"0.06em",marginBottom:5},children:"Quick Notes"}),e.jsx("textarea",{value:t,onChange:i,placeholder:r==="s"?"Notes…":"Type your notes here…","aria-label":"Quick notes",style:{flex:1,resize:"none",background:"rgba(255,255,255,0.05)",border:"1px solid rgba(255,255,255,0.08)",borderRadius:8,color:"rgba(255,255,255,0.85)",fontSize:r==="s"?"0.75rem":"0.8rem",padding:r==="s"?"6px 8px":"8px 10px",outline:"none",fontFamily:"inherit",lineHeight:1.55,transition:"border-color 0.15s, background 0.15s",caretColor:"rgba(255,255,255,0.7)"},onFocus:u=>{u.currentTarget.style.borderColor="rgba(255,255,255,0.2)",u.currentTarget.style.background="rgba(255,255,255,0.07)"},onBlur:u=>{u.currentTarget.style.borderColor="rgba(255,255,255,0.08)",u.currentTarget.style.background="rgba(255,255,255,0.05)"}})]})}function dt(t){return t>=80?"#f87171":t>=50?"#fbbf24":"#4ade80"}function se({label:t,value:s}){const n=dt(s);return e.jsxs("div",{style:{display:"flex",flexDirection:"column",gap:4},children:[e.jsxs("div",{style:{display:"flex",justifyContent:"space-between",fontSize:"0.72rem",color:"rgba(255,255,255,0.65)"},children:[e.jsx("span",{children:t}),e.jsxs("span",{style:{fontVariantNumeric:"tabular-nums",fontWeight:600,color:"rgba(255,255,255,0.85)"},children:[Math.round(s),"%"]})]}),e.jsx("div",{style:{height:5,borderRadius:3,background:"rgba(255,255,255,0.08)",overflow:"hidden"},role:"progressbar","aria-label":`${t} usage`,"aria-valuenow":Math.round(s),"aria-valuemin":0,"aria-valuemax":100,children:e.jsx("div",{style:{height:"100%",width:`${Math.min(100,Math.max(0,s))}%`,borderRadius:3,background:n,transition:"width 0.4s ease, background 0.4s ease",boxShadow:`0 0 6px ${n}66`}})})]})}function Le({label:t,value:s}){const n=dt(s),r=18,i=2*Math.PI*r,u=Math.min(100,Math.max(0,s))/100*i;return e.jsxs("div",{style:{display:"flex",flexDirection:"column",alignItems:"center",gap:3,flex:1},children:[e.jsxs("div",{style:{position:"relative",width:48,height:48},children:[e.jsxs("svg",{width:"48",height:"48",viewBox:"0 0 48 48","aria-hidden":"true",children:[e.jsx("circle",{cx:"24",cy:"24",r,fill:"none",stroke:"rgba(255,255,255,0.08)",strokeWidth:"4"}),e.jsx("circle",{cx:"24",cy:"24",r,fill:"none",stroke:n,strokeWidth:"4",strokeDasharray:`${u} ${i-u}`,strokeLinecap:"round",transform:"rotate(-90 24 24)",style:{transition:"stroke-dasharray 0.4s ease, stroke 0.4s ease",filter:`drop-shadow(0 0 3px ${n}99)`}})]}),e.jsx("span",{style:{position:"absolute",inset:0,display:"flex",alignItems:"center",justifyContent:"center",fontSize:"0.65rem",fontWeight:600,color:"rgba(255,255,255,0.85)",fontVariantNumeric:"tabular-nums"},children:Math.round(s)})]}),e.jsx("span",{style:{fontSize:"0.6rem",fontWeight:600,color:"rgba(255,255,255,0.4)",textTransform:"uppercase",letterSpacing:"0.06em"},children:t})]})}async function pe(t){try{const s=await fetch(t,{headers:{Accept:"application/json"}});return!s.ok||!(s.headers.get("content-type")??"").includes("application/json")?null:await s.json()}catch{return null}}function ut(){const[t,s]=o.useState(null),[n,r]=o.useState(!1),[i,{tier:a}]=Y();o.useEffect(()=>{let d=!1;async function f(){var w,b;const p=await pe("/api/system");if(p!=null&&p.resources){if(d)return;s({cpu:p.resources.cpu_percent??0,ram:p.resources.ram_percent??0}),r(!1);return}const[h,c]=await Promise.all([pe("/api/metrics/system.cpu_pct?range=1h"),pe("/api/metrics/system.ram_pct?range=1h")]);if(d)return;const x=Array.isArray(h)&&h.length>0?((w=h[h.length-1])==null?void 0:w.value)??null:null,y=Array.isArray(c)&&c.length>0?((b=c[c.length-1])==null?void 0:b.value)??null:null;if(x===null&&y===null){r(!0);return}s({cpu:x??0,ram:y??0}),r(!1)}f();const m=setInterval(f,5e3);return()=>{d=!0,clearInterval(m)}},[]);const u={fontSize:"0.65rem",fontWeight:600,color:"rgba(255,255,255,0.4)",textTransform:"uppercase",letterSpacing:"0.06em"},l=n||!t,g=n?"Stats unavailable":"Loading…";return e.jsxs("div",{ref:i,style:{height:"100%",display:"flex",flexDirection:"column",padding:a==="s"?"0 4px":"2px 4px 6px",overflow:"hidden"},"aria-label":"System stats widget",role:"region",children:[a==="s"&&e.jsx("div",{style:{display:"flex",alignItems:"center",justifyContent:"center",height:"100%",gap:16},children:l?e.jsx("span",{style:{fontSize:"0.7rem",color:"rgba(255,255,255,0.35)"},children:g}):e.jsxs(e.Fragment,{children:[e.jsx(Le,{label:"CPU",value:t.cpu}),e.jsx(Le,{label:"RAM",value:t.ram})]})}),a==="m"&&e.jsxs(e.Fragment,{children:[e.jsx("div",{style:u,children:"System"}),e.jsx("div",{style:{flex:1,display:"flex",flexDirection:"column",justifyContent:"center",gap:10,marginTop:8},children:l?e.jsx("span",{style:{fontSize:"0.75rem",color:"rgba(255,255,255,0.35)"},children:g}):e.jsxs(e.Fragment,{children:[e.jsx(se,{label:"CPU",value:t.cpu}),e.jsx(se,{label:"RAM",value:t.ram})]})})]}),a==="l"&&e.jsxs(e.Fragment,{children:[e.jsx("div",{style:u,children:"System"}),e.jsx("div",{style:{flex:1,display:"flex",flexDirection:"column",justifyContent:"center",gap:12,marginTop:10},children:l?e.jsx("span",{style:{fontSize:"0.75rem",color:"rgba(255,255,255,0.35)"},children:g}):e.jsxs(e.Fragment,{children:[e.jsx(se,{label:"CPU",value:t.cpu}),e.jsx(se,{label:"RAM",value:t.ram})]})}),e.jsx("div",{style:{display:"flex",gap:8,marginTop:6},children:!l&&e.jsxs(e.Fragment,{children:[e.jsxs("div",{style:{flex:1,background:"rgba(255,255,255,0.04)",borderRadius:8,padding:"6px 8px"},children:[e.jsx("div",{style:{fontSize:"0.6rem",color:"rgba(255,255,255,0.35)",textTransform:"uppercase",letterSpacing:"0.05em",marginBottom:2},children:"CPU"}),e.jsxs("div",{style:{fontSize:"1rem",fontWeight:600,color:"rgba(255,255,255,0.9)",fontVariantNumeric:"tabular-nums"},children:[Math.round(t.cpu),"%"]})]}),e.jsxs("div",{style:{flex:1,background:"rgba(255,255,255,0.04)",borderRadius:8,padding:"6px 8px"},children:[e.jsx("div",{style:{fontSize:"0.6rem",color:"rgba(255,255,255,0.35)",textTransform:"uppercase",letterSpacing:"0.05em",marginBottom:2},children:"RAM"}),e.jsxs("div",{style:{fontSize:"1rem",fontWeight:600,color:"rgba(255,255,255,0.9)",fontVariantNumeric:"tabular-nums"},children:[Math.round(t.ram),"%"]})]})]})})]})]})}const wn={0:{label:"Clear sky",icon:"☀️"},1:{label:"Mainly clear",icon:"🌤"},2:{label:"Partly cloudy",icon:"⛅"},3:{label:"Overcast",icon:"☁️"},45:{label:"Fog",icon:"🌫"},48:{label:"Rime fog",icon:"🌫"},51:{label:"Light drizzle",icon:"🌦"},53:{label:"Drizzle",icon:"🌦"},55:{label:"Heavy drizzle",icon:"🌧"},61:{label:"Light rain",icon:"🌦"},63:{label:"Rain",icon:"🌧"},65:{label:"Heavy rain",icon:"🌧"},71:{label:"Light snow",icon:"🌨"},73:{label:"Snow",icon:"🌨"},75:{label:"Heavy snow",icon:"❄️"},77:{label:"Snow grains",icon:"🌨"},80:{label:"Rain showers",icon:"🌦"},81:{label:"Rain showers",icon:"🌧"},82:{label:"Heavy showers",icon:"⛈"},85:{label:"Snow showers",icon:"🌨"},86:{label:"Heavy snow showers",icon:"❄️"},95:{label:"Thunderstorm",icon:"⛈"},96:{label:"Thunderstorm + hail",icon:"⛈"},99:{label:"Severe thunderstorm",icon:"⛈"}};function We(t,s=!0){const n=wn[t]??{label:"Unknown",icon:"🌤"};return(t===0||t===1)&&!s?{...n,icon:"🌙"}:n}const pt="weather",we="taos-pref:weather";function je(){try{const t=localStorage.getItem(we);return t?JSON.parse(t):{}}catch{return{}}}function K(){return je().home??null}function oe(){return je().tempUnit==="F"?"F":"C"}function le(){return je().windUnit==="mph"?"mph":"kmh"}function V(t){return Math.round(t*9/5+32)}function ve(t){return Math.round(t*.621371)}const ce="taos-weather-units-changed";function he(){window.dispatchEvent(new Event(ce))}async function jn(t){if(!t.trim())return[];try{const s=await fetch(`https://geocoding-api.open-meteo.com/v1/search?name=${encodeURIComponent(t)}&count=10&language=en&format=json`);return s.ok?((await s.json()).results??[]).map(r=>({name:r.name,country:r.country,admin1:r.admin1,latitude:r.latitude,longitude:r.longitude})):[]}catch{return[]}}async function vn(t){const s=new URLSearchParams({latitude:String(t.latitude),longitude:String(t.longitude),current:"temperature_2m,apparent_temperature,is_day,weather_code,relative_humidity_2m,wind_speed_10m,wind_direction_10m",daily:"weather_code,temperature_2m_max,temperature_2m_min,precipitation_sum",timezone:"auto",forecast_days:"7"}),n=await fetch(`https://api.open-meteo.com/v1/forecast?${s}`);if(!n.ok)return null;const r=await n.json(),i={temperature:Math.round(r.current.temperature_2m),feelsLike:Math.round(r.current.apparent_temperature),weatherCode:r.current.weather_code,humidity:r.current.relative_humidity_2m,windSpeed:Math.round(r.current.wind_speed_10m),windDirection:r.current.wind_direction_10m,isDay:r.current.is_day===1},a=r.daily.time.map((u,l)=>({date:u,tempMax:Math.round(r.daily.temperature_2m_max[l]),tempMin:Math.round(r.daily.temperature_2m_min[l]),weatherCode:r.daily.weather_code[l],precipitation:r.daily.precipitation_sum[l]}));return{current:i,daily:a}}async function me(t){try{localStorage.setItem(we,JSON.stringify(t))}catch{}try{await fetch(`/api/preferences/${pt}`,{method:"PUT",headers:{"Content-Type":"application/json"},body:JSON.stringify(t)})}catch{}}function kn(){const[t,s]=o.useState(K),[n,r]=o.useState(t),[i,a]=o.useState(""),[u,l]=o.useState([]),[g,d]=o.useState(!1),[f,m]=o.useState(null),[p,h]=o.useState(!1),[c,x]=o.useState(oe),[y,w]=o.useState(le);o.useEffect(()=>{let v=!1;return(async()=>{try{const W=await fetch(`/api/preferences/${pt}`);if(!W.ok)return;const T=await W.json();if(v||!T||Object.keys(T).length===0)return;T.home&&(s(T.home),r(O=>O??T.home??null)),(T.tempUnit==="C"||T.tempUnit==="F")&&x(T.tempUnit),(T.windUnit==="kmh"||T.windUnit==="mph")&&w(T.windUnit),localStorage.setItem(we,JSON.stringify(T)),he()}catch{}})(),()=>{v=!0}},[]);const b=o.useCallback(()=>{const v=c==="C"?"F":"C";x(v),me({home:t,tempUnit:v,windUnit:y}),he()},[c,t,y]),j=o.useCallback(()=>{const v=y==="kmh"?"mph":"kmh";w(v),me({home:t,tempUnit:c,windUnit:v}),he()},[y,t,c]),k=o.useCallback(async v=>{h(!0);const W=await vn(v);m(W),h(!1)},[]);o.useEffect(()=>{n&&k(n)},[n,k]),o.useEffect(()=>{if(!i.trim()){l([]);return}let v=!1;d(!0);const W=setTimeout(async()=>{const T=await jn(i);v||(l(T),d(!1))},300);return()=>{v=!0,clearTimeout(W)}},[i]);const N=v=>{r(v),a(""),l([])},C=v=>{s(v),me({home:v,tempUnit:c,windUnit:y})},A=f?We(f.current.weatherCode,f.current.isDay):null,E=n&&t&&n.latitude===t.latitude&&n.longitude===t.longitude;return e.jsxs("div",{style:{height:"100%",display:"flex",flexDirection:"column",background:"linear-gradient(160deg, #1a2a4a 0%, #0e1a36 100%)",color:"white",overflow:"hidden"},children:[e.jsx("div",{style:{padding:16,flexShrink:0,borderBottom:"1px solid rgba(255,255,255,0.05)"},children:e.jsxs("div",{style:{position:"relative"},children:[e.jsx(X,{size:16,style:{position:"absolute",left:12,top:12,color:"rgba(255,255,255,0.4)"}}),e.jsx("input",{value:i,onChange:v=>a(v.target.value),placeholder:"Search for a town or city...",style:{width:"100%",padding:"10px 12px 10px 36px",background:"rgba(255,255,255,0.08)",border:"1px solid rgba(255,255,255,0.1)",borderRadius:10,color:"white",fontSize:14,outline:"none"}}),u.length>0&&e.jsx("div",{style:{position:"absolute",top:"100%",left:0,right:0,marginTop:4,background:"rgba(15,20,40,0.98)",backdropFilter:"blur(20px)",border:"1px solid rgba(255,255,255,0.1)",borderRadius:10,maxHeight:280,overflowY:"auto",zIndex:10},children:u.map((v,W)=>e.jsxs("button",{onClick:()=>N(v),style:{width:"100%",padding:"10px 14px",textAlign:"left",background:"none",border:"none",color:"white",fontSize:13,display:"flex",alignItems:"center",gap:10,cursor:"pointer"},onMouseEnter:T=>T.currentTarget.style.background="rgba(255,255,255,0.06)",onMouseLeave:T=>T.currentTarget.style.background="none",children:[e.jsx(Ce,{size:14,style:{color:"rgba(255,255,255,0.4)"}}),e.jsxs("span",{style:{flex:1},children:[e.jsx("span",{style:{color:"rgba(255,255,255,0.9)"},children:v.name}),e.jsxs("span",{style:{color:"rgba(255,255,255,0.4)",marginLeft:6},children:[v.admin1?`${v.admin1}, `:"",v.country]})]})]},`${v.latitude}-${v.longitude}-${W}`))}),g&&i&&u.length===0&&e.jsx("div",{style:{position:"absolute",top:"100%",left:0,right:0,marginTop:4,padding:"12px 14px",background:"rgba(15,20,40,0.98)",backdropFilter:"blur(20px)",border:"1px solid rgba(255,255,255,0.1)",borderRadius:10,fontSize:13,color:"rgba(255,255,255,0.5)"},children:"Searching..."})]})}),e.jsxs("div",{style:{flex:1,overflowY:"auto",padding:20},children:[!n&&e.jsxs("div",{style:{display:"flex",flexDirection:"column",alignItems:"center",justifyContent:"center",height:"100%",gap:12,color:"rgba(255,255,255,0.5)"},children:[e.jsx(Ce,{size:48,style:{color:"rgba(255,255,255,0.2)"}}),e.jsx("p",{style:{fontSize:15},children:"Search for a location to see its weather"})]}),n&&p&&!f&&e.jsx("div",{style:{textAlign:"center",color:"rgba(255,255,255,0.5)",marginTop:40},children:"Loading forecast..."}),n&&f&&A&&e.jsxs(e.Fragment,{children:[e.jsxs("div",{style:{display:"flex",alignItems:"center",justifyContent:"space-between",marginBottom:20},children:[e.jsxs("div",{children:[e.jsx("h1",{style:{fontSize:24,fontWeight:600,margin:0,color:"rgba(255,255,255,0.95)"},children:n.name}),e.jsxs("p",{style:{fontSize:13,color:"rgba(255,255,255,0.5)",margin:"2px 0 0"},children:[n.admin1?`${n.admin1}, `:"",n.country]})]}),e.jsx("button",{onClick:()=>C(n),disabled:!!E,style:{display:"flex",alignItems:"center",gap:6,padding:"8px 14px",background:E?"rgba(80,200,120,0.2)":"rgba(255,255,255,0.08)",border:`1px solid ${E?"rgba(80,200,120,0.3)":"rgba(255,255,255,0.12)"}`,borderRadius:8,color:E?"rgb(150,220,170)":"rgba(255,255,255,0.85)",fontSize:12,fontWeight:500,cursor:E?"default":"pointer"},children:E?e.jsxs(e.Fragment,{children:[e.jsx(Xe,{size:14})," Home"]}):e.jsxs(e.Fragment,{children:[e.jsx(Nt,{size:14})," Set as home"]})})]}),e.jsxs("div",{style:{display:"flex",alignItems:"center",gap:16,marginBottom:28,padding:"16px 20px",background:"rgba(255,255,255,0.05)",borderRadius:16,border:"1px solid rgba(255,255,255,0.08)"},children:[e.jsx("div",{style:{fontSize:72,lineHeight:1},children:A.icon}),e.jsxs("div",{style:{flex:1},children:[e.jsxs("button",{onClick:b,title:"Tap to toggle °C / °F",style:{display:"flex",alignItems:"baseline",gap:8,background:"none",border:"none",padding:0,cursor:"pointer",color:"inherit"},children:[e.jsxs("span",{style:{fontSize:56,fontWeight:300,lineHeight:1,color:"rgba(255,255,255,0.95)"},children:[c==="C"?f.current.temperature:V(f.current.temperature),"°"]}),e.jsx("span",{style:{fontSize:18,color:"rgba(255,255,255,0.5)"},children:c})]}),e.jsx("p",{style:{fontSize:14,color:"rgba(255,255,255,0.7)",margin:"4px 0 0"},children:A.label}),e.jsxs("p",{style:{fontSize:12,color:"rgba(255,255,255,0.45)",margin:"2px 0 0"},children:["Feels like ",c==="C"?f.current.feelsLike:V(f.current.feelsLike),"°"]})]})]}),e.jsxs("div",{style:{display:"grid",gridTemplateColumns:"repeat(auto-fit, minmax(140px, 1fr))",gap:10,marginBottom:28},children:[e.jsxs("div",{style:{padding:14,background:"rgba(255,255,255,0.05)",borderRadius:12,border:"1px solid rgba(255,255,255,0.06)"},children:[e.jsx("div",{style:{fontSize:10,textTransform:"uppercase",letterSpacing:.5,color:"rgba(255,255,255,0.4)"},children:"Humidity"}),e.jsxs("div",{style:{fontSize:20,fontWeight:600,marginTop:4},children:[f.current.humidity,"%"]})]}),e.jsxs("button",{onClick:j,title:"Tap to toggle km/h / mph",style:{padding:14,background:"rgba(255,255,255,0.05)",borderRadius:12,border:"1px solid rgba(255,255,255,0.06)",textAlign:"left",cursor:"pointer",color:"inherit"},children:[e.jsx("div",{style:{fontSize:10,textTransform:"uppercase",letterSpacing:.5,color:"rgba(255,255,255,0.4)"},children:"Wind"}),e.jsxs("div",{style:{fontSize:20,fontWeight:600,marginTop:4},children:[y==="kmh"?f.current.windSpeed:ve(f.current.windSpeed),e.jsx("span",{style:{fontSize:13,color:"rgba(255,255,255,0.5)",marginLeft:4,fontWeight:400},children:y==="kmh"?"km/h":"mph"})]})]})]}),e.jsxs("div",{children:[e.jsx("h2",{style:{fontSize:11,textTransform:"uppercase",letterSpacing:.8,color:"rgba(255,255,255,0.45)",margin:"0 0 10px",fontWeight:600},children:"7-Day Forecast"}),e.jsx("div",{style:{background:"rgba(255,255,255,0.04)",borderRadius:14,border:"1px solid rgba(255,255,255,0.06)",overflow:"hidden"},children:f.daily.map((v,W)=>{const T=We(v.weatherCode),O=new Date(v.date),$=W===0?"Today":O.toLocaleDateString("en",{weekday:"short"});return e.jsxs("div",{style:{display:"flex",alignItems:"center",gap:14,padding:"12px 16px",borderTop:W===0?"none":"1px solid rgba(255,255,255,0.05)"},children:[e.jsx("span",{style:{width:52,fontSize:13,color:"rgba(255,255,255,0.8)",fontWeight:500},children:$}),e.jsx("span",{style:{fontSize:22,width:32,textAlign:"center"},children:T.icon}),e.jsx("span",{style:{flex:1,fontSize:12,color:"rgba(255,255,255,0.55)"},children:T.label}),e.jsxs("span",{style:{fontSize:13,color:"rgba(255,255,255,0.5)",width:36,textAlign:"right"},children:[c==="C"?v.tempMin:V(v.tempMin),"°"]}),e.jsxs("span",{style:{fontSize:13,color:"rgba(255,255,255,0.9)",width:36,textAlign:"right",fontWeight:500},children:[c==="C"?v.tempMax:V(v.tempMax),"°"]})]},v.date)})})]})]})]})]})}const Sn=Object.freeze(Object.defineProperty({__proto__:null,UNIT_CHANGED_EVENT:ce,WeatherApp:kn,cToF:V,getHomeLocation:K,getTempUnit:oe,getWindUnit:le,kmhToMph:ve},Symbol.toStringTag,{value:"Module"})),Cn={0:{label:"Clear",icon:"☀️"},1:{label:"Mainly clear",icon:"🌤"},2:{label:"Partly cloudy",icon:"⛅"},3:{label:"Overcast",icon:"☁️"},45:{label:"Fog",icon:"🌫"},48:{label:"Fog",icon:"🌫"},51:{label:"Drizzle",icon:"🌦"},53:{label:"Drizzle",icon:"🌦"},55:{label:"Drizzle",icon:"🌧"},61:{label:"Light rain",icon:"🌦"},63:{label:"Rain",icon:"🌧"},65:{label:"Heavy rain",icon:"🌧"},71:{label:"Light snow",icon:"🌨"},73:{label:"Snow",icon:"🌨"},75:{label:"Heavy snow",icon:"❄️"},80:{label:"Showers",icon:"🌦"},81:{label:"Showers",icon:"🌧"},82:{label:"Heavy showers",icon:"⛈"},95:{label:"Thunderstorm",icon:"⛈"},96:{label:"Thunderstorm",icon:"⛈"},99:{label:"Thunderstorm",icon:"⛈"}};function zn(t,s=!0){const n=Cn[t]??{label:"Unknown",icon:"🌤"};return(t===0||t===1)&&!s?{...n,icon:"🌙"}:n}async function Nn(){const t=K();if(!t)return null;try{const s=new URLSearchParams({latitude:String(t.latitude),longitude:String(t.longitude),current:"temperature_2m,apparent_temperature,is_day,weather_code,relative_humidity_2m,wind_speed_10m",timezone:"auto"}),n=await fetch(`https://api.open-meteo.com/v1/forecast?${s}`,{signal:AbortSignal.timeout(5e3)});if(!n.ok)return null;const r=await n.json(),i=zn(r.current.weather_code,r.current.is_day===1);return{temp:Math.round(r.current.temperature_2m),feelsLike:Math.round(r.current.apparent_temperature),condition:i.label,icon:i.icon,humidity:r.current.relative_humidity_2m,wind:Math.round(r.current.wind_speed_10m),location:t.name}}catch{return null}}function ht(){const[t,s]=o.useState(null),[n,r]=o.useState(!K()),[i,a]=o.useState(oe),[u,l]=o.useState(le),[g,{tier:d}]=Y();o.useEffect(()=>{const p=()=>{const w=K();r(!w),w&&Nn().then(s)};(async()=>{try{const w=await fetch("/api/preferences/weather");if(!w.ok){p();return}const b=await w.json();b&&typeof b=="object"&&Object.keys(b).length>0&&(localStorage.setItem("taos-pref:weather",JSON.stringify(b)),(b.tempUnit==="C"||b.tempUnit==="F")&&a(b.tempUnit),(b.windUnit==="kmh"||b.windUnit==="mph")&&l(b.windUnit))}catch{}p()})();const c=setInterval(p,6e5),x=()=>p(),y=()=>{a(oe()),l(le())};return window.addEventListener("storage",x),window.addEventListener(ce,y),()=>{clearInterval(c),window.removeEventListener("storage",x),window.removeEventListener(ce,y)}},[]);const f=p=>i==="C"?p:V(p),m=p=>u==="kmh"?`${p} km/h`:`${ve(p)} mph`;return n?e.jsxs("div",{ref:g,style:{display:"flex",flexDirection:"column",alignItems:"center",justifyContent:"center",height:"100%",gap:6,padding:8,textAlign:"center"},"aria-label":"Weather widget — no location set",role:"region",children:[e.jsx("span",{style:{fontSize:d==="s"?20:28,lineHeight:1},children:"🌤"}),d!=="s"&&e.jsx("span",{style:{fontSize:"0.72rem",color:"rgba(255,255,255,0.45)"},children:"Tap to set location"})]}):t?e.jsxs("div",{ref:g,style:{height:"100%",display:"flex",flexDirection:"column",padding:d==="s"?"0 4px":"2px 4px 6px",overflow:"hidden"},"aria-label":`Weather: ${t.condition}, ${f(t.temp)}°${i} in ${t.location}`,role:"region",children:[d==="s"&&e.jsxs("div",{style:{display:"flex",flexDirection:"column",justifyContent:"space-between",alignItems:"center",height:"100%",padding:"4px 2px"},children:[e.jsxs("div",{style:{display:"flex",alignItems:"center",gap:8},children:[e.jsx("span",{style:{fontSize:"1.8rem",lineHeight:1},children:t.icon}),e.jsxs("span",{style:{fontSize:"1.6rem",fontWeight:600,color:"rgba(255,255,255,0.95)",lineHeight:1,fontVariantNumeric:"tabular-nums"},children:[f(t.temp),"°"]})]}),e.jsxs("div",{style:{display:"flex",gap:8,fontSize:"0.65rem",color:"rgba(255,255,255,0.4)"},children:[e.jsxs("span",{children:["💧 ",t.humidity,"%"]}),e.jsxs("span",{children:["💨 ",m(t.wind)]})]})]}),d==="m"&&e.jsxs("div",{style:{display:"flex",flexDirection:"column",justifyContent:"space-between",height:"100%"},children:[e.jsx("div",{style:{display:"flex",alignItems:"flex-start",justifyContent:"space-between"},children:e.jsxs("div",{style:{display:"flex",alignItems:"center",gap:8},children:[e.jsx("span",{style:{fontSize:"2.2rem",lineHeight:1},children:t.icon}),e.jsxs("div",{children:[e.jsxs("div",{style:{fontSize:"1.8rem",fontWeight:600,color:"rgba(255,255,255,0.95)",lineHeight:1,fontVariantNumeric:"tabular-nums"},children:[f(t.temp),"°",e.jsx("span",{style:{fontSize:"0.85rem",fontWeight:400,color:"rgba(255,255,255,0.4)",marginLeft:1},children:i})]}),e.jsx("div",{style:{fontSize:"0.72rem",color:"rgba(255,255,255,0.5)",marginTop:2},children:t.condition})]})]})}),e.jsxs("div",{style:{display:"flex",gap:10,fontSize:"0.7rem",color:"rgba(255,255,255,0.4)"},children:[e.jsxs("span",{children:["Feels ",f(t.feelsLike),"°"]}),e.jsxs("span",{children:["💧 ",t.humidity,"%"]}),e.jsxs("span",{children:["💨 ",m(t.wind)]})]}),e.jsx("div",{style:{fontSize:"0.68rem",color:"rgba(255,255,255,0.35)",textTransform:"uppercase",letterSpacing:"0.04em",overflow:"hidden",textOverflow:"ellipsis",whiteSpace:"nowrap"},children:t.location})]}),d==="l"&&e.jsxs("div",{style:{display:"flex",flexDirection:"column",justifyContent:"space-between",height:"100%"},children:[e.jsx("div",{style:{fontSize:"0.65rem",fontWeight:600,color:"rgba(255,255,255,0.35)",textTransform:"uppercase",letterSpacing:"0.06em",overflow:"hidden",textOverflow:"ellipsis",whiteSpace:"nowrap"},children:t.location}),e.jsxs("div",{style:{display:"flex",alignItems:"center",gap:10,margin:"4px 0"},children:[e.jsx("span",{style:{fontSize:"2.8rem",lineHeight:1},children:t.icon}),e.jsxs("div",{children:[e.jsxs("div",{style:{fontSize:"2.4rem",fontWeight:600,color:"rgba(255,255,255,0.95)",lineHeight:1,fontVariantNumeric:"tabular-nums",letterSpacing:"-0.02em"},children:[f(t.temp),"°",e.jsx("span",{style:{fontSize:"1rem",fontWeight:400,color:"rgba(255,255,255,0.4)",marginLeft:2},children:i})]}),e.jsx("div",{style:{fontSize:"0.8rem",color:"rgba(255,255,255,0.55)",marginTop:3},children:t.condition})]})]}),e.jsx("div",{style:{display:"flex",justifyContent:"space-between",background:"rgba(255,255,255,0.05)",borderRadius:8,padding:"6px 10px",gap:4},children:[{icon:"🌡",label:"Feels",value:`${f(t.feelsLike)}°`},{icon:"💧",label:"Humidity",value:`${t.humidity}%`},{icon:"💨",label:"Wind",value:m(t.wind)}].map(({icon:p,label:h,value:c})=>e.jsxs("div",{style:{display:"flex",flexDirection:"column",alignItems:"center",flex:1},children:[e.jsx("span",{style:{fontSize:"0.75rem"},children:p}),e.jsx("span",{style:{fontSize:"0.72rem",fontWeight:600,color:"rgba(255,255,255,0.8)",fontVariantNumeric:"tabular-nums"},children:c}),e.jsx("span",{style:{fontSize:"0.58rem",color:"rgba(255,255,255,0.3)",textTransform:"uppercase",letterSpacing:"0.04em"},children:h})]},h))})]})]}):e.jsx("div",{ref:g,style:{display:"flex",alignItems:"center",justifyContent:"center",height:"100%",color:"rgba(255,255,255,0.3)",fontSize:"0.75rem"},"aria-label":"Weather widget — loading",role:"region",children:"Loading…"})}const _n=[{type:"clock",label:"Clock",icon:e.jsx(_t,{size:14})},{type:"agent-status",label:"Agent Status",icon:e.jsx(Tt,{size:14})},{type:"quick-notes",label:"Quick Notes",icon:e.jsx(At,{size:14})},{type:"system-stats",label:"System Stats",icon:e.jsx(Ye,{size:14})},{type:"weather",label:"Weather",icon:e.jsx(Et,{size:14})}];function Tn(t){switch(t){case"clock":return e.jsx(ot,{});case"agent-status":return e.jsx(lt,{});case"quick-notes":return e.jsx(ct,{});case"system-stats":return e.jsx(ut,{});case"weather":return e.jsx(ht,{});default:return e.jsx("div",{style:{color:"rgba(255,255,255,0.4)",fontSize:"0.75rem",padding:8},children:"Unknown widget"})}}function An(){const{widgets:t,showWidgets:s,addWidget:n,removeWidget:r,updateLayout:i}=R(),[a,u]=o.useState(!1),[l,g]=o.useState(1200),d=o.useRef(null),f=o.useRef(null);o.useEffect(()=>{if(!d.current)return;const h=new ResizeObserver(c=>{for(const x of c)g(x.contentRect.width)});return h.observe(d.current),()=>h.disconnect()},[]),o.useEffect(()=>{if(!a)return;function h(c){f.current&&!f.current.contains(c.target)&&u(!1)}return document.addEventListener("mousedown",h),()=>document.removeEventListener("mousedown",h)},[a]);const m=o.useCallback(h=>{i(h.map(c=>({id:c.i,x:c.x,y:c.y,w:c.w,h:c.h})))},[i]);if(!s)return null;const p=t.map(h=>({i:h.id,x:h.x,y:h.y,w:h.w,h:h.h,minW:h.minW??2,minH:h.minH??2}));return e.jsxs("div",{ref:d,style:{position:"absolute",inset:0,zIndex:1,pointerEvents:"none"},children:[e.jsx("div",{style:{pointerEvents:"auto",width:"100%",height:"100%"},children:e.jsx(qt,{className:"widget-grid",layout:p,cols:12,rowHeight:72,width:l,margin:[16,16],containerPadding:[24,24],isDraggable:!0,isResizable:!0,compactType:null,preventCollision:!0,draggableHandle:".widget-drag-handle",onLayoutChange:m,children:t.map(h=>e.jsx("div",{style:{overflow:"hidden"},children:e.jsxs("div",{style:{height:"100%",background:"rgba(20, 20, 35, 0.65)",backdropFilter:"blur(12px)",WebkitBackdropFilter:"blur(12px)",borderRadius:12,border:"1px solid rgba(255,255,255,0.1)",display:"flex",flexDirection:"column",position:"relative",overflow:"hidden"},children:[e.jsx("div",{className:"widget-drag-handle",style:{display:"flex",justifyContent:"flex-end",padding:"4px 6px 0",cursor:"grab",minHeight:20},children:e.jsx("button",{onClick:c=>{c.stopPropagation(),r(h.id)},"aria-label":`Remove ${h.type} widget`,style:{background:"rgba(255,255,255,0.1)",border:"none",borderRadius:4,width:18,height:18,display:"flex",alignItems:"center",justifyContent:"center",cursor:"pointer",color:"rgba(255,255,255,0.4)",transition:"color 0.15s, background 0.15s"},onMouseEnter:c=>{c.currentTarget.style.color="#fff",c.currentTarget.style.background="rgba(239,68,68,0.6)"},onMouseLeave:c=>{c.currentTarget.style.color="rgba(255,255,255,0.4)",c.currentTarget.style.background="rgba(255,255,255,0.1)"},children:e.jsx(P,{size:12})})}),e.jsx("div",{style:{flex:1,padding:"0 8px 8px",overflow:"hidden"},children:Tn(h.type)})]})},h.id))})}),e.jsxs("div",{style:{position:"absolute",bottom:16,right:16,pointerEvents:"auto",zIndex:10},children:[e.jsx("button",{onClick:()=>u(!a),"aria-label":"Add widget",style:{width:40,height:40,borderRadius:"50%",background:"rgba(20, 20, 35, 0.7)",backdropFilter:"blur(12px)",WebkitBackdropFilter:"blur(12px)",border:"1px solid rgba(255,255,255,0.15)",color:"rgba(255,255,255,0.7)",cursor:"pointer",display:"flex",alignItems:"center",justifyContent:"center",transition:"transform 0.15s, background 0.15s"},onMouseEnter:h=>{h.currentTarget.style.background="rgba(40, 40, 60, 0.85)",h.currentTarget.style.transform="scale(1.1)"},onMouseLeave:h=>{h.currentTarget.style.background="rgba(20, 20, 35, 0.7)",h.currentTarget.style.transform="scale(1)"},children:e.jsx(Ze,{size:20})}),a&&e.jsx("div",{ref:f,style:{position:"absolute",bottom:50,right:0,background:"rgba(20, 20, 35, 0.9)",backdropFilter:"blur(16px)",WebkitBackdropFilter:"blur(16px)",border:"1px solid rgba(255,255,255,0.15)",borderRadius:10,padding:6,minWidth:170,display:"flex",flexDirection:"column",gap:2},children:_n.map(h=>e.jsxs("button",{onClick:()=>{n(h.type),u(!1)},style:{display:"flex",alignItems:"center",gap:8,padding:"8px 10px",background:"transparent",border:"none",borderRadius:6,color:"rgba(255,255,255,0.8)",fontSize:"0.8rem",cursor:"pointer",textAlign:"left",transition:"background 0.12s"},onMouseEnter:c=>{c.currentTarget.style.background="rgba(255,255,255,0.1)"},onMouseLeave:c=>{c.currentTarget.style.background="transparent"},children:[h.icon,h.label]},h.type))})]})]})}function En({x:t,y:s,items:n,onClose:r}){const i=o.useRef(null);o.useEffect(()=>{const l=d=>{i.current&&!i.current.contains(d.target)&&r()},g=d=>{d.key==="Escape"&&r()};return document.addEventListener("mousedown",l),document.addEventListener("keydown",g),()=>{document.removeEventListener("mousedown",l),document.removeEventListener("keydown",g)}},[r]);const a=Math.min(t,window.innerWidth-220),u=Math.min(s,window.innerHeight-n.length*36-20);return e.jsx("div",{ref:i,className:"fixed z-[10001] min-w-[200px] py-1 rounded-lg border border-shell-border-strong overflow-hidden",style:{left:a,top:u,backgroundColor:"rgba(30, 31, 50, 0.95)",backdropFilter:"blur(20px)",boxShadow:"0 8px 32px rgba(0,0,0,0.5)"},children:n.map((l,g)=>l.separator?e.jsx("div",{className:"my-1 mx-2 border-t border-shell-border"},g):e.jsxs("button",{onClick:()=>{!l.disabled&&l.action&&(l.action(),r())},disabled:l.disabled,className:`w-full flex items-center gap-2.5 px-3 py-1.5 text-left text-sm transition-colors ${l.disabled?"text-shell-text-tertiary cursor-default":"text-shell-text hover:bg-white/8"}`,children:[l.icon&&e.jsx("span",{className:"w-4 h-4 flex items-center justify-center text-shell-text-secondary",children:l.icon}),e.jsx("span",{children:l.label})]},g))})}function In({open:t,onClose:s}){const{wallpaperId:n,setWallpaper:r,getWallpapers:i}=M(),a=i();return t?e.jsx("div",{className:"fixed inset-0 z-[10002] flex items-center justify-center bg-black/40 backdrop-blur-sm p-4",onClick:s,style:{paddingTop:"calc(env(safe-area-inset-top, 0px) + 16px)",paddingBottom:"calc(40px + env(safe-area-inset-bottom, 0px) * 0.35 + 16px)"},children:e.jsxs("div",{className:"w-full max-w-[500px] max-h-full flex flex-col rounded-xl border border-shell-border-strong overflow-hidden",style:{backgroundColor:"rgba(26, 27, 46, 0.98)"},onClick:u=>u.stopPropagation(),children:[e.jsxs("div",{className:"flex items-center justify-between px-4 py-3 border-b border-shell-border shrink-0",children:[e.jsx("h3",{className:"text-sm font-medium text-shell-text",children:"Change Wallpaper"}),e.jsx("button",{onClick:s,className:"text-shell-text-tertiary hover:text-shell-text text-lg leading-none","aria-label":"Close",children:"×"})]}),e.jsx("div",{className:"p-4 grid grid-cols-2 gap-3 overflow-y-auto flex-1",children:a.map(u=>e.jsxs("button",{onClick:()=>{r(u.id)},className:`relative rounded-lg overflow-hidden border-2 transition-all ${n===u.id?"border-accent ring-1 ring-accent/30":"border-shell-border hover:border-shell-border-strong"}`,children:[e.jsx("div",{className:"h-24 w-full",style:{backgroundImage:u.image,backgroundColor:u.fallback,backgroundSize:"cover",backgroundPosition:"center",backgroundRepeat:"no-repeat"}}),e.jsx("div",{className:"px-2 py-1.5 text-xs text-shell-text-secondary text-left",children:u.label}),n===u.id&&e.jsx("div",{className:"absolute top-2 right-2 w-5 h-5 rounded-full bg-accent flex items-center justify-center",children:e.jsx(Xe,{size:12,className:"text-white"})})]},u.id))})]})}):null}function Ln(){const t=_(b=>b.windows),{openWindow:s}=_(),n=M(b=>b.wallpaperImage),r=M(b=>b.wallpaperMobileImage),i=M(b=>b.wallpaperFallback),{showWidgets:a,toggleWidgets:u}=R(),[l,g]=o.useState(null),[d,f]=o.useState(!1),m={width:typeof window<"u"?window.innerWidth:1920,height:typeof window<"u"?window.innerHeight:1080,topBarH:32,dockH:84},{previewBounds:p,onDrag:h,onDragStop:c}=hn(m),x=o.useCallback(b=>{(b.target===b.currentTarget||b.target.closest("[data-desktop-surface]"))&&(b.preventDefault(),g({x:b.clientX,y:b.clientY}))},[]),y=o.useCallback(b=>{const j=L(b);j&&s(b,j.defaultSize)},[s]),w=[{label:"New Folder",icon:e.jsx(It,{size:14}),action:()=>y("files")},{label:"",separator:!0},{label:"Change Wallpaper",icon:e.jsx(Lt,{size:14}),action:()=>f(!0)},{label:"Save to Memory",icon:e.jsx(Wt,{size:14}),action:()=>{const b=window.prompt("Save to memory:");b&&fetch("/api/user-memory/save",{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({content:b,collection:"snippets"})}).catch(()=>{const j=JSON.parse(localStorage.getItem("tinyagentos-snippets")||"[]");j.push({content:b,savedAt:Date.now()}),localStorage.setItem("tinyagentos-snippets",JSON.stringify(j))})}},{label:"Display Settings",icon:e.jsx(Rt,{size:14}),action:()=>y("settings")},{label:"",separator:!0},{label:a?"Hide Widgets":"Show Widgets",icon:e.jsx(Qe,{size:14}),action:()=>u()},{label:"",separator:!0},{label:"Open Launchpad",icon:e.jsx(be,{size:14}),action:()=>{window.dispatchEvent(new CustomEvent("open-launchpad"))}},{label:"System Settings",icon:e.jsx(Ke,{size:14}),action:()=>y("settings")}];return e.jsxs("div",{className:"taos-wallpaper relative flex-1 overflow-hidden",style:{backgroundColor:i,"--wallpaper-desktop":n,"--wallpaper-mobile":r},onContextMenu:x,"data-desktop-surface":!0,children:[e.jsx(xn,{bounds:p}),e.jsx(An,{}),t.map(b=>e.jsx(gn,{win:b,onDrag:h,onDragStop:c},b.id)),l&&e.jsx(En,{x:l.x,y:l.y,items:w,onClose:()=>g(null)}),e.jsx(In,{open:d,onClose:()=>f(!1)})]})}const Wn=["messages","agents","files","store","settings"],de=q((t,s)=>({pinned:Wn,pin(n){s().pinned.includes(n)||t(r=>({pinned:[...r.pinned,n]}))},unpin(n){t(r=>({pinned:r.pinned.filter(i=>i!==n)}))},reorder(n){t({pinned:n})}}));function Re({appId:t,isRunning:s,onClick:n}){const r=L(t);if(!r)return null;const i=r.icon.split("-").map(u=>u.charAt(0).toUpperCase()+u.slice(1)).join(""),a=G[i]??H;return e.jsxs("button",{onClick:n,className:"group relative flex items-center justify-center w-10 h-10 rounded-lg bg-shell-surface hover:bg-shell-surface-active transition-all hover:scale-110","aria-label":`Open ${r.name}`,title:r.name,children:[e.jsx(a,{size:20,className:"text-shell-text"}),s&&e.jsx("div",{className:"absolute -bottom-1 left-1/2 -translate-x-1/2 w-1 h-1 rounded-full bg-accent"})]})}function Rn({onLaunchpadOpen:t}){const s=de(d=>d.pinned),n=_(d=>d.windows),{openWindow:r,focusWindow:i,restoreWindow:a}=_(),u=n.map(d=>d.appId),l=u.filter(d=>!s.includes(d)),g=d=>{const f=n.find(m=>m.appId===d);if(f)f.minimized?a(f.id):i(f.id);else{const m=L(d);m&&r(d,m.defaultSize)}};return e.jsxs("div",{className:"fixed bottom-3 left-1/2 -translate-x-1/2 flex items-center gap-1.5 px-3 rounded-2xl z-[9999] select-none",style:{height:"var(--spacing-dock-h)",padding:"var(--spacing-dock-padding)",backgroundColor:"var(--color-dock-bg)",border:"1px solid var(--color-dock-border)",boxShadow:"var(--shadow-dock)"},children:[e.jsx("button",{onClick:t,className:"flex items-center justify-center w-10 h-10 rounded-lg bg-shell-surface hover:bg-shell-surface-active transition-all hover:scale-110","aria-label":"Launchpad",title:"Launchpad",children:e.jsxs("svg",{width:"18",height:"18",viewBox:"0 0 16 16",className:"text-shell-text",fill:"currentColor",children:[e.jsx("rect",{x:"1",y:"1",width:"5",height:"5",rx:"1"}),e.jsx("rect",{x:"10",y:"1",width:"5",height:"5",rx:"1"}),e.jsx("rect",{x:"1",y:"10",width:"5",height:"5",rx:"1"}),e.jsx("rect",{x:"10",y:"10",width:"5",height:"5",rx:"1"})]})}),e.jsx("div",{className:"w-px h-8 bg-shell-border mx-1"}),s.map(d=>e.jsx(Re,{appId:d,isRunning:u.includes(d),onClick:()=>g(d)},d)),l.length>0&&e.jsx("div",{className:"w-px h-8 bg-shell-border mx-1"}),l.map(d=>e.jsx(Re,{appId:d,isRunning:!0,onClick:()=>g(d)},d))]})}function Pn(t){const s=t.toLowerCase().split("+").map(n=>n.trim());return{ctrl:s.includes("ctrl"),shift:s.includes("shift"),alt:s.includes("alt"),key:s.filter(n=>!["ctrl","shift","alt"].includes(n))[0]??""}}function On(t,s){const n=s.ctrlKey||s.metaKey;return t.ctrl!==n||t.shift!==s.shiftKey||t.alt!==s.altKey?!1:s.key.toLowerCase()===t.key}const ke=o.createContext(null),Pe={overlay:0,app:1,system:2};function Mn(t){const s=[];return t.ctrl&&s.push("Ctrl"),t.shift&&s.push("Shift"),t.alt&&s.push("Alt"),s.push(t.key.charAt(0).toUpperCase()+t.key.slice(1)),s.join("+")}function Oe({children:t}){const s=o.useRef(new Map),[n,r]=o.useState(!1);o.useEffect(()=>{const l=()=>{var g;document.fullscreenElement&&((g=navigator.keyboard)!=null&&g.lock)?navigator.keyboard.lock().then(()=>r(!0)).catch(()=>r(!1)):r(!1)};return document.addEventListener("fullscreenchange",l),()=>document.removeEventListener("fullscreenchange",l)},[]),o.useEffect(()=>{const l=g=>{const d=Array.from(s.current.values()).filter(f=>f.enabled).sort((f,m)=>Pe[f.scope]-Pe[m.scope]);for(const f of d)if(On(f.combo,g)){g.preventDefault(),g.stopPropagation(),f.action();return}};return window.addEventListener("keydown",l),()=>window.removeEventListener("keydown",l)},[]);const i=o.useCallback((l,g,d,f,m="system")=>{s.current.set(l,{id:l,combo:Pn(g),action:d,label:f,scope:m,enabled:!0})},[]),a=o.useCallback(l=>{s.current.delete(l)},[]),u=o.useCallback(()=>Array.from(s.current.values()).map(l=>({combo:Mn(l.combo),label:l.label,scope:l.scope})),[]);return e.jsx(ke.Provider,{value:{register:i,unregister:a,getAll:u,keyboardLockActive:n},children:t})}function I(t,s,n,r="system"){const i=o.useContext(ke),a=o.useRef(`shortcut-${t}-${Math.random().toString(36).slice(2,8)}`);o.useEffect(()=>(i==null||i.register(a.current,t,s,n,r),()=>i==null?void 0:i.unregister(a.current)),[i,t,s,n,r])}function js(){const t=o.useContext(ke);return{getAll:(t==null?void 0:t.getAll)??(()=>[]),keyboardLockActive:(t==null?void 0:t.keyboardLockActive)??!1}}function Dn({app:t,onClick:s}){const n=t.icon.split("-").map(i=>i.charAt(0).toUpperCase()+i.slice(1)).join(""),r=G[n]??H;return e.jsxs("button",{onClick:s,className:"flex flex-col items-center gap-2 p-3 rounded-xl hover:bg-white/5 transition-colors","aria-label":`Open ${t.name}`,children:[e.jsx("div",{className:"w-14 h-14 rounded-2xl bg-shell-surface-hover flex items-center justify-center",children:e.jsx(r,{size:28,className:"text-shell-text"})}),e.jsx("span",{className:"text-xs text-shell-text-secondary",children:t.name})]})}const Fn={platform:"Platform",os:"Utilities",streaming:"Streaming Apps",game:"Games"};function Me({open:t,onClose:s,onOpenApp:n}){const[r,i]=o.useState(""),a=o.useRef(t);a.current=t;const{openWindow:u}=_();I("Escape",()=>{a.current&&s()},"Close launchpad","overlay");const l=typeof window<"u"&&window.innerWidth<640,g=o.useMemo(()=>{const m=rt();if(!r.trim())return m;const p=r.toLowerCase();return m.filter(h=>h.name.toLowerCase().includes(p))},[r]),d=o.useMemo(()=>{var p;const m={};for(const h of g)(m[p=h.category]??(m[p]=[])).push(h);return m},[g]),f=m=>{const p=L(m);if(p){const h=u(m,p.defaultSize);n==null||n(h)}s(),i("")};return t?e.jsx("div",{className:"fixed top-0 left-0 right-0 z-[9000] flex flex-col backdrop-blur-md bg-black/40",onClick:s,style:{bottom:l?76:0,paddingTop:"calc(env(safe-area-inset-top, 0px) + 60px)",paddingBottom:l?16:"calc(52px + env(safe-area-inset-bottom, 0px) + 16px)"},children:e.jsxs("div",{className:"w-full max-w-3xl mx-auto px-4 flex-1 flex flex-col min-h-0",children:[e.jsxs("div",{className:"flex items-center gap-2 px-4 py-2 mb-4 rounded-xl bg-white/10 border border-white/10 shrink-0",onClick:m=>m.stopPropagation(),children:[e.jsx(X,{size:16,className:"text-shell-text-tertiary"}),e.jsx("input",{type:"text",value:r,onChange:m=>i(m.target.value),placeholder:"Search apps...",className:"flex-1 bg-transparent text-sm text-shell-text outline-none placeholder:text-shell-text-tertiary",autoFocus:!l}),r&&e.jsx("button",{onClick:()=>i(""),"aria-label":"Clear search",children:e.jsx(P,{size:14,className:"text-shell-text-tertiary"})})]}),e.jsx("div",{className:"flex-1 overflow-y-auto space-y-6 pr-1",children:Object.entries(d).map(([m,p])=>e.jsxs("div",{children:[e.jsx("h3",{className:"text-xs font-medium text-shell-text-tertiary uppercase tracking-wide mb-3 px-1",children:Fn[m]??m}),e.jsx("div",{className:"grid grid-cols-4 sm:grid-cols-5 md:grid-cols-6 gap-3",children:p.map(h=>e.jsx(Dn,{app:h,onClick:()=>f(h.id)},h.id))})]},m))})]})}):null}function De({open:t,onClose:s,onOpenApp:n}){const[r,i]=o.useState(""),a=o.useRef(null),u=o.useRef(t);u.current=t;const{openWindow:l}=_(),[g,d]=o.useState(0);I("Escape",()=>{u.current&&s()},"Close search","overlay"),o.useEffect(()=>{t&&(i(""),d(0),setTimeout(()=>{var j;return(j=a.current)==null?void 0:j.focus()},50))},[t]);const f=o.useMemo(()=>{const j=rt(),k=r.toLowerCase().trim();return j.filter(N=>!k||N.name.toLowerCase().includes(k)||N.category.includes(k)).slice(0,8).map(N=>({id:N.id,name:N.name,category:N.category,icon:N.icon,type:"app",action:()=>{const C=L(N.id);if(C){const A=l(N.id,C.defaultSize);n==null||n(A)}s()}}))},[r,l,s,n]),[m,p]=o.useState([]);o.useEffect(()=>{const j=r.trim();if(!j||j.length<2){p([]);return}const k=new AbortController,N=setTimeout(()=>{fetch(`/api/user-memory/search?q=${encodeURIComponent(j)}&limit=5`,{signal:k.signal}).then(C=>C.ok?C.json():{results:[]}).then(C=>{const A=Array.isArray(C==null?void 0:C.results)?C.results:[];p(A.map(E=>({id:`mem-${E.hash}`,name:E.title&&E.title.trim()||E.content.slice(0,60),category:E.collection,icon:"database",type:"memory",subtitle:E.content.slice(0,100),action:()=>{const v=L("memory");if(v){const W=l("memory",v.defaultSize);n==null||n(W)}s()}})))}).catch(()=>{})},300);return()=>{clearTimeout(N),k.abort()}},[r,l,s,n]);const[h,c]=o.useState([]);o.useEffect(()=>{const j=r.trim();if(!j||j.length<2){c([]);return}const k=new AbortController,N=setTimeout(()=>{fetch(`/api/memory/catalog/search?q=${encodeURIComponent(j)}&limit=3`,{signal:k.signal}).then(C=>C.ok?C.json():[]).then(C=>{Array.isArray(C)&&c(C.map(A=>({id:`catalog-${A.id}`,name:A.topic||"Session",category:A.category||"session",icon:"calendar-search",type:"memory",subtitle:`${A.date||""} ${A.start_str||""}-${A.end_str||""} ${A.description||""}`.trim().slice(0,100),action:()=>{const E=L("memory");if(E){const v=l("memory",E.defaultSize);n==null||n(v)}s()}})))}).catch(()=>{})},300);return()=>{clearTimeout(N),k.abort()}},[r,l,s,n]);const x=o.useMemo(()=>[...f,...m,...h],[f,m,h]);o.useEffect(()=>{d(0)},[x]);const y=j=>{j.key==="ArrowDown"?(j.preventDefault(),d(k=>Math.min(k+1,x.length-1))):j.key==="ArrowUp"?(j.preventDefault(),d(k=>Math.max(k-1,0))):j.key==="Enter"&&x[g]&&x[g].action()};if(!t)return null;const w=j=>{const k=j.split("-").map(C=>C.charAt(0).toUpperCase()+C.slice(1)).join(""),N=G[k]??H;return e.jsx(N,{size:18})},b={platform:"Platform",os:"Utility",streaming:"Streaming",game:"Game"};return e.jsx("div",{className:"fixed inset-0 z-[10003] flex justify-center items-start bg-black/30 backdrop-blur-sm px-4",onClick:s,style:{paddingTop:"calc(env(safe-area-inset-top, 0px) + 8px)"},children:e.jsxs("div",{className:"w-full max-w-[560px] max-h-[50vh] rounded-xl border border-shell-border-strong overflow-hidden flex flex-col",style:{backgroundColor:"rgba(26, 27, 46, 0.97)",boxShadow:"0 16px 64px rgba(0,0,0,0.5)"},onClick:j=>j.stopPropagation(),children:[e.jsxs("div",{className:"flex items-center gap-2 px-3 py-2 border-b border-shell-border",children:[e.jsx(X,{size:15,className:"text-shell-text-tertiary shrink-0"}),e.jsx("input",{ref:a,type:"text",value:r,onChange:j=>i(j.target.value),onKeyDown:y,placeholder:"Search apps, settings, files...",className:"flex-1 bg-transparent text-sm text-shell-text outline-none placeholder:text-shell-text-tertiary",autoFocus:!0}),r&&e.jsx("button",{onClick:()=>i(""),"aria-label":"Clear",children:e.jsx(P,{size:13,className:"text-shell-text-tertiary"})})]}),e.jsxs("div",{className:"flex-1 overflow-y-auto py-1",children:[x.length===0&&r&&e.jsxs("div",{className:"px-4 py-8 text-center text-sm text-shell-text-tertiary",children:['No results for "',r,'"']}),f.length>0&&e.jsx("div",{className:"px-4 pt-2 pb-1 text-[10px] uppercase tracking-wider text-shell-text-tertiary",role:"presentation",children:"Apps"}),f.map(j=>{const k=x.indexOf(j);return e.jsxs("button",{onClick:j.action,onMouseEnter:()=>d(k),className:`w-full flex items-center gap-2.5 px-3 py-1.5 text-left transition-colors ${k===g?"bg-accent/15":"hover:bg-white/5"}`,children:[e.jsx("div",{className:`w-7 h-7 rounded-md flex items-center justify-center ${k===g?"bg-accent/20 text-accent":"bg-shell-surface text-shell-text-secondary"}`,children:w(j.icon)}),e.jsx("div",{className:"flex-1 min-w-0",children:e.jsx("div",{className:"text-xs text-shell-text truncate",children:j.name})}),e.jsx("span",{className:"text-[9px] text-shell-text-tertiary uppercase tracking-wider",children:b[j.category]??j.category})]},j.id)}),m.length>0&&e.jsx("div",{className:"px-4 pt-3 pb-1 text-[10px] uppercase tracking-wider text-shell-text-tertiary",role:"presentation",children:"Memory"}),m.map(j=>{const k=x.indexOf(j);return e.jsxs("button",{onClick:j.action,onMouseEnter:()=>d(k),className:`w-full flex items-start gap-3 px-4 py-2.5 text-left transition-colors ${k===g?"bg-accent/15":"hover:bg-white/5"}`,children:[e.jsx("div",{className:`w-8 h-8 rounded-lg flex items-center justify-center shrink-0 ${k===g?"bg-slate-500/20 text-slate-300":"bg-shell-surface text-shell-text-secondary"}`,children:w(j.icon)}),e.jsxs("div",{className:"flex-1 min-w-0",children:[e.jsx("div",{className:"text-sm text-shell-text truncate",children:j.name}),j.subtitle&&e.jsx("div",{className:"text-[11px] text-shell-text-tertiary truncate mt-0.5",children:j.subtitle})]}),e.jsx("span",{className:"text-[10px] text-shell-text-tertiary uppercase tracking-wider shrink-0",children:j.category})]},j.id)}),!r&&e.jsx("div",{className:"px-4 py-6 text-center text-xs text-shell-text-tertiary",children:"Type to search apps and memory, or press Escape to close"})]}),e.jsxs("div",{className:"flex items-center justify-between px-4 py-2 border-t border-shell-border text-[10px] text-shell-text-tertiary",children:[e.jsx("span",{children:"↑↓ Navigate"}),e.jsx("span",{children:"↵ Open"}),e.jsx("span",{children:"Esc Close"})]})]})})}function $n(){const t=_(c=>c.windows),s=_(c=>c.openWindow),n=_(c=>c.updatePosition),r=_(c=>c.updateSize),i=_(c=>c.maximizeWindow),a=_(c=>c.snapWindow),u=de(c=>c.pinned),l=M(c=>c.wallpaperId),g=R(c=>c.widgets),d=o.useRef(!1),f=o.useRef(null),m=o.useRef(null),p=o.useRef(null),h=o.useRef(null);o.useEffect(()=>{d.current||(d.current=!0,fetch("/api/desktop/windows").then(c=>c.json()).then(c=>{if(Array.isArray(c))for(const x of c){if(!L(x.appId))continue;const w=s(x.appId,{w:x.w,h:x.h});n(w,x.x,x.y),r(w,x.w,x.h),x.maximized&&i(w),x.snapped&&a(w,x.snapped)}}).catch(()=>{}),fetch("/api/desktop/dock").then(c=>c.json()).then(c=>{c.pinned&&Array.isArray(c.pinned)&&de.getState().reorder(c.pinned)}).catch(()=>{}),fetch("/api/desktop/settings").then(c=>c.json()).then(c=>{c.wallpaper&&c.wallpaper!=="default"&&M.getState().setWallpaper(c.wallpaper)}).catch(()=>{}),fetch("/api/desktop/widgets").then(c=>c.json()).then(c=>{const x=Array.isArray(c)?c:c.widgets??[];x.length>0&&R.setState({widgets:x})}).catch(()=>{}))},[s,n,r,i,a]),o.useEffect(()=>{if(d.current)return f.current&&clearTimeout(f.current),f.current=setTimeout(()=>{const c=t.map(x=>({appId:x.appId,x:x.position.x,y:x.position.y,w:x.size.w,h:x.size.h,maximized:x.maximized,snapped:x.snapped}));fetch("/api/desktop/windows",{method:"PUT",headers:{"Content-Type":"application/json"},body:JSON.stringify({positions:c})}).catch(()=>{})},2e3),()=>{f.current&&clearTimeout(f.current)}},[t]),o.useEffect(()=>{if(d.current)return m.current&&clearTimeout(m.current),m.current=setTimeout(()=>{fetch("/api/desktop/dock",{method:"PUT",headers:{"Content-Type":"application/json"},body:JSON.stringify({pinned:u})}).catch(()=>{})},1e3),()=>{m.current&&clearTimeout(m.current)}},[u]),o.useEffect(()=>{if(d.current)return p.current&&clearTimeout(p.current),p.current=setTimeout(()=>{fetch("/api/desktop/settings",{method:"PUT",headers:{"Content-Type":"application/json"},body:JSON.stringify({wallpaper:l})}).catch(()=>{})},500),()=>{p.current&&clearTimeout(p.current)}},[l]),o.useEffect(()=>{if(d.current)return h.current&&clearTimeout(h.current),h.current=setTimeout(()=>{fetch("/api/desktop/widgets",{method:"PUT",headers:{"Content-Type":"application/json"},body:JSON.stringify({widgets:g})}).catch(()=>{})},1e3),()=>{h.current&&clearTimeout(h.current)}},[g])}function Fe(){const t=window.innerWidth,s=matchMedia("(pointer: coarse)").matches||navigator.maxTouchPoints>0;return t<768?"mobile":t<1024&&s?"tablet":"desktop"}function Hn(){const[t,s]=o.useState(Fe);return o.useEffect(()=>{const n=()=>s(Fe());return window.addEventListener("resize",n),()=>window.removeEventListener("resize",n)},[]),t}const Un=["messages","agents","files","store","settings","models","providers","activity","cluster","memory","channels","secrets","tasks","import","images","library","reddit","youtube","github","x-monitor","agent-browsers","calculator","calendar","contacts"],Bn=["messages","agents","files","store"],Vn=[{items:[{type:"widget",widgetType:"greeting"},{type:"widget",widgetType:"weather"},{type:"widget",widgetType:"system-stats"},{type:"widget",widgetType:"agent-status"}]},{items:Un.map(t=>({type:"app",appId:t}))}],ie=q(t=>({dockApps:Bn,pages:Vn,activePageIndex:0,setActivePage(s){t({activePageIndex:s})},setDockApps(s){t({dockApps:s})},addPage(){t(s=>({pages:[...s.pages,{items:[]}]}))},removePage(s){t(n=>{const r=n.pages.filter((a,u)=>u!==s),i=Math.min(n.activePageIndex,Math.max(0,r.length-1));return{pages:r,activePageIndex:i}})},addItemToPage(s,n){t(r=>({pages:r.pages.map((i,a)=>a===s?{items:[...i.items,n]}:i)}))},removeItemFromPage(s,n){t(r=>({pages:r.pages.map((i,a)=>a===s?{items:i.items.filter((u,l)=>l!==n)}:i)}))}}));function Gn(t){const s=t.split("-").map(n=>n.charAt(0).toUpperCase()+n.slice(1)).join("");return G[s]??H}function qn({onOpenApp:t,onToggleSwitcher:s,onOpenLaunchpad:n,activeAppId:r}){const i=ie(u=>u.dockApps),a=_(u=>u.windows);return e.jsxs("div",{role:"toolbar","aria-label":"Dock",className:"shrink-0",style:{display:"flex",alignItems:"center",justifyContent:"center",gap:8,paddingTop:6,paddingBottom:24},children:[e.jsx("button",{onClick:n,"aria-label":"All Apps",style:{width:44,height:44,borderRadius:12,background:"linear-gradient(135deg, rgba(60,65,78,0.85), rgba(35,38,48,0.9))",border:"1px solid rgba(255,255,255,0.1)",display:"flex",alignItems:"center",justifyContent:"center",cursor:"pointer",padding:0},children:e.jsx(be,{size:20,style:{color:"rgba(255,255,255,0.8)"}})}),i.map(u=>{const l=L(u);if(!l)return null;const g=Gn(l.icon),d=u===r,f=a.some(m=>m.appId===u);return e.jsxs("div",{style:{position:"relative",display:"flex",flexDirection:"column",alignItems:"center"},children:[e.jsx("button",{onClick:()=>t(u),"aria-label":`Open ${l.name}`,style:{width:44,height:44,borderRadius:12,background:"linear-gradient(135deg, rgba(60,65,78,0.85), rgba(35,38,48,0.9))",border:"1px solid rgba(255,255,255,0.1)",display:"flex",alignItems:"center",justifyContent:"center",cursor:"pointer",padding:0},children:e.jsx(g,{size:22,style:{color:"rgba(255,255,255,0.8)"}})}),d&&e.jsx("div",{style:{position:"absolute",bottom:-6,left:"50%",transform:"translateX(-50%)",width:4,height:4,borderRadius:"50%",background:"rgba(255,255,255,0.7)"}}),!d&&f&&e.jsx("div",{style:{position:"absolute",bottom:-6,left:"50%",transform:"translateX(-50%)",width:3,height:3,borderRadius:"50%",background:"rgba(255,255,255,0.3)"}})]},u)}),e.jsx("div",{style:{width:1,height:28,background:"rgba(255,255,255,0.15)",margin:"0 6px",flexShrink:0}}),e.jsx("button",{onClick:s,"aria-label":"App Switcher",style:{width:44,height:44,borderRadius:12,background:"rgba(255,255,255,0.06)",border:"1px solid rgba(255,255,255,0.1)",display:"flex",alignItems:"center",justifyContent:"center",cursor:"pointer",padding:0},children:e.jsx(Qe,{size:20,style:{color:"rgba(255,255,255,0.7)"}})})]})}function Yn(t){const s=t.split("-").map(n=>n.charAt(0).toUpperCase()+n.slice(1)).join("");return G[s]??H}function Jn({open:t,onClose:s,onSelectApp:n,onLaunchpad:r}){const i=_(p=>p.windows),a=_(p=>p.closeWindow),[u,l]=o.useState({}),g=o.useRef({}),d=o.useCallback((p,h)=>{g.current[p]=h,l(c=>({...c,[p]:0}))},[]),f=o.useCallback((p,h)=>{const c=g.current[p];if(c===void 0)return;const x=h-c;x<0&&l(y=>({...y,[p]:x}))},[]),m=o.useCallback(p=>{(u[p]??0)<-100?(l(c=>({...c,[p]:-999})),setTimeout(()=>{a(p),l(c=>{const x={...c};return delete x[p],x})},250)):l(c=>{const x={...c};return delete x[p],x}),delete g.current[p]},[u,a]);return t?e.jsxs("div",{className:"fixed inset-0 flex flex-col backdrop-blur-sm",style:{zIndex:9e3,backgroundColor:"rgba(0, 0, 0, 0.6)"},role:"dialog","aria-label":"App Switcher",onClick:s,children:[e.jsxs("div",{className:"flex items-center justify-between px-4 pt-4 pb-2",onClick:p=>p.stopPropagation(),children:[e.jsx("h2",{className:"text-white text-lg font-medium",children:"App Switcher"}),e.jsx("button",{onClick:s,className:"flex items-center justify-center w-8 h-8 rounded-full bg-white/10 active:bg-white/20 transition-colors","aria-label":"Close app switcher",children:e.jsx(P,{size:18,className:"text-white/80"})})]}),i.length===0?e.jsxs("div",{className:"flex-1 flex flex-col items-center justify-center gap-4",children:[e.jsx("p",{className:"text-white/60 text-base",children:"No apps open"}),e.jsxs("button",{onClick:p=>{p.stopPropagation(),r(),s()},className:"flex items-center gap-2 px-4 py-2 rounded-lg bg-white/10 active:bg-white/20 text-white/80 transition-colors","aria-label":"Open Launchpad",children:[e.jsx(Ze,{size:18}),"Open Launchpad"]})]}):e.jsx("div",{className:"flex-1 flex items-center overflow-x-auto snap-x snap-mandatory",style:{scrollSnapType:"x mandatory",WebkitOverflowScrolling:"touch",paddingLeft:"calc(50vw - 35vw)",paddingRight:"calc(50vw - 35vw)",gap:"1rem"},onClick:p=>{p.target===p.currentTarget&&s()},children:i.map(p=>{const h=L(p.appId),c=h?Yn(h.icon):H,x=u[p.id]??0,y=x===-999;return e.jsxs("div",{className:"flex-shrink-0 snap-center relative flex flex-col items-center justify-center rounded-2xl bg-white/8 border border-white/10",style:{width:"70vw",aspectRatio:"9 / 16",transform:y?"translateY(-120vh)":x<0?`translateY(${x}px)`:void 0,transition:y?"transform 250ms ease-in":x===0?"transform 200ms ease-out":void 0,opacity:y?0:1},onTouchStart:w=>{var b;return d(p.id,((b=w.touches[0])==null?void 0:b.clientY)??0)},onTouchMove:w=>{var b;return f(p.id,((b=w.touches[0])==null?void 0:b.clientY)??0)},onTouchEnd:()=>m(p.id),onClick:w=>{w.stopPropagation(),n(p.id),s()},role:"button","aria-label":`Switch to ${(h==null?void 0:h.name)??"Unknown"}`,tabIndex:0,children:[e.jsx("button",{onClick:w=>{w.stopPropagation(),a(p.id)},className:"absolute top-3 right-3 flex items-center justify-center w-7 h-7 rounded-full bg-white/10 active:bg-white/20 transition-colors","aria-label":`Close ${(h==null?void 0:h.name)??"app"}`,children:e.jsx(P,{size:14,className:"text-white/70"})}),e.jsx(c,{size:40,className:"text-white/60 mb-3"}),e.jsx("span",{className:"text-white/80 text-sm font-medium",children:(h==null?void 0:h.name)??p.appId})]},p.id)})})]}):null}function Kn({onHome:t,onSearch:s}){const n=F(i=>i.notifications.filter(a=>!a.read).length),r=F(i=>i.toggleCentre);return e.jsx("div",{className:"shrink-0",style:{paddingTop:"env(safe-area-inset-top, 0px)"},children:e.jsxs("div",{className:"flex items-center px-2",style:{height:44},children:[e.jsx("button",{onClick:t,className:"px-2 py-1 active:opacity-60 transition-opacity","aria-label":"Go to home screen",children:e.jsx("span",{className:"text-[17px] font-semibold text-shell-text",children:"taOS"})}),e.jsx("div",{className:"flex-1 flex items-center justify-center",children:e.jsx(it,{compact:!0})}),e.jsxs("div",{className:"flex items-center gap-2",children:[e.jsx("button",{onClick:s,className:"relative flex items-center justify-center active:opacity-60 transition-opacity",style:{width:32,height:32,borderRadius:"50%",background:"rgba(255,255,255,0.08)",backdropFilter:"blur(10px)",WebkitBackdropFilter:"blur(10px)",border:"1px solid rgba(255,255,255,0.1)"},"aria-label":"Search",children:e.jsx(X,{size:15,className:"text-white/70"})}),e.jsxs("button",{onClick:r,className:"relative flex items-center justify-center active:opacity-60 transition-opacity",style:{width:32,height:32,borderRadius:"50%",background:"rgba(255,255,255,0.08)",backdropFilter:"blur(10px)",WebkitBackdropFilter:"blur(10px)",border:"1px solid rgba(255,255,255,0.1)"},"aria-label":`Notifications${n>0?` (${n} unread)`:""}`,children:[e.jsx(ae,{size:15,className:"text-white/70"}),n>0&&e.jsx("span",{className:"absolute bg-red-500 rounded-full",style:{width:6,height:6,top:5,right:5}})]})]})]})})}function Xn({appId:t,windowId:s,onClose:n,onMinimise:r}){const i=L(t),a=o.useMemo(()=>i?o.lazy(i.component):null,[i]);return!i||!a?null:e.jsxs("div",{className:"flex flex-col h-full w-full",children:[e.jsxs("div",{className:"flex items-center px-3 gap-2 shrink-0",style:{height:"32px",background:"rgba(30, 30, 60, 0.9)",borderBottom:"1px solid rgba(255,255,255,0.08)"},children:[e.jsx("button",{onClick:n,"aria-label":"Close",className:"flex items-center justify-center rounded-full shrink-0",style:{width:"18px",height:"18px",background:"rgba(255,80,80,0.3)",border:"1px solid rgba(255,80,80,0.3)"},children:e.jsx(P,{size:10,style:{color:"rgba(255,120,120,0.8)"}})}),e.jsx("button",{onClick:r,"aria-label":"Minimise",className:"flex items-center justify-center rounded-full shrink-0",style:{width:"18px",height:"18px",background:"rgba(255,200,50,0.2)",border:"1px solid rgba(255,200,50,0.3)"},children:e.jsx(Pt,{size:10,style:{color:"rgba(255,200,80,0.8)"}})}),e.jsx("div",{className:"flex-1 text-center text-xs font-medium",style:{color:"rgba(255,255,255,0.6)"},children:i.name}),e.jsx("div",{style:{width:"44px"}})]}),e.jsx("div",{className:"flex-1 overflow-hidden",style:{background:"rgba(15,15,35,0.95)"},children:e.jsx(o.Suspense,{fallback:e.jsx("div",{className:"flex items-center justify-center h-full text-white/30 text-sm",children:"Loading..."}),children:e.jsx(a,{windowId:s})})})]})}function Zn(t){return t>=5&&t<12?"Good morning.":t>=12&&t<17?"Good afternoon.":t>=17&&t<21?"Good evening.":"Good night."}function Qn(t){return t>=5&&t<12?"☀️":t>=12&&t<17?"🌤":t>=17&&t<21?"🌅":"🌙"}async function $e(){try{const[t,s]=await Promise.all([fetch("/api/agents"),fetch("/api/jobs")]);if(!t.ok||!s.ok)return null;const n=await t.json(),r=await s.json(),i=Array.isArray(n)?n.length:(n==null?void 0:n.count)??0,a=Array.isArray(r)?r.length:(r==null?void 0:r.count)??0;return{agentCount:i,taskCount:a}}catch{return null}}function es(){const[t,s]=o.useState(()=>new Date),[n,r]=o.useState(null),[i,{tier:a}]=Y();o.useEffect(()=>{const m=setInterval(()=>s(new Date),6e4);return()=>clearInterval(m)},[]),o.useEffect(()=>{$e().then(r);const m=setInterval(()=>$e().then(r),3e4);return()=>clearInterval(m)},[]);const u=t.getHours(),l=Zn(u),g=Qn(u),d=[];n!==null&&(n.agentCount>0&&d.push(`${n.agentCount} agent${n.agentCount!==1?"s":""} running`),n.taskCount>0&&d.push(`${n.taskCount} task${n.taskCount!==1?"s":""} queued`));const f=d.length>0?d.join(" · "):"All systems operational";return e.jsxs("div",{ref:i,style:{display:"flex",flexDirection:"column",alignItems:"center",justifyContent:"center",height:"100%",padding:a==="s"?"4px 8px":a==="m"?"12px 12px":"20px 16px",gap:a==="s"?4:8,textAlign:"center"},"aria-label":"Greeting widget",role:"region",children:[a!=="s"&&e.jsx("span",{style:{fontSize:a==="l"?36:28,lineHeight:1},"aria-hidden":"true",children:g}),e.jsx("span",{style:{fontSize:a==="s"?"1rem":a==="m"?"1.3rem":"1.7rem",fontWeight:600,color:"rgba(255,255,255,0.92)",lineHeight:1.2,letterSpacing:"-0.02em"},children:a==="s"?e.jsxs(e.Fragment,{children:[g," ",l]}):l}),a!=="s"&&e.jsx("span",{style:{fontSize:a==="l"?"0.78rem":"0.7rem",color:"rgba(255,255,255,0.4)",letterSpacing:"0.01em"},children:f})]})}const He={platform:"linear-gradient(135deg, rgba(100,80,200,0.4), rgba(60,50,140,0.6))",os:"linear-gradient(135deg, rgba(50,160,140,0.35), rgba(30,100,90,0.55))",game:"linear-gradient(135deg, rgba(200,120,50,0.35), rgba(140,70,30,0.55))"};function ts(t){const s=t.split("-").map(n=>n.charAt(0).toUpperCase()+n.slice(1)).join("");return G[s]??H}const ge={borderRadius:"16px",background:"rgba(255,255,255,0.06)",border:"1px solid rgba(255,255,255,0.08)",backdropFilter:"blur(10px)",WebkitBackdropFilter:"blur(10px)",padding:"12px"},xe={weather:"weather","system-stats":"dashboard","agent-status":"agents",clock:"calendar"};function fe({children:t,style:s,onClick:n}){return e.jsx("div",{onClick:n,style:{...ge,...s,cursor:n?"pointer":void 0,transition:"background 150ms ease"},onMouseDown:n?r=>{r.currentTarget.style.background="rgba(255,255,255,0.1)"}:void 0,onMouseUp:n?r=>{r.currentTarget.style.background=ge.background}:void 0,onMouseLeave:n?r=>{r.currentTarget.style.background=ge.background}:void 0,children:t})}function re(t){switch(t){case"clock":return e.jsx(ot,{});case"system-stats":return e.jsx(ut,{});case"greeting":return e.jsx(es,{});case"agent-status":return e.jsx(lt,{});case"weather":return e.jsx(ht,{});case"quick-notes":return e.jsx(ct,{});default:return null}}function ns({page:t,onOpenApp:s}){const n=[];for(let r=0;r{if(r.kind==="widgets"){const a=[];let u=!1;for(let l=0;ls(p):void 0,children:re(g.widgetType)}),e.jsx(fe,{style:{flex:1},onClick:h?()=>s(h):void 0,children:re(d.widgetType)})]},`pair-${g.index}`)),u=!0}else{const p=xe[g.widgetType];a.push(e.jsx(fe,{onClick:p?()=>s(p):void 0,children:re(g.widgetType)},g.index))}}return e.jsx(D.Fragment,{children:a},`wg-${i}`)}return e.jsx("div",{style:{display:"grid",gridTemplateColumns:"repeat(4, 1fr)",gap:"12px",padding:"8px 4px"},children:r.items.map(({appId:a,index:u})=>{const l=L(a);if(!l)return null;const g=ts(l.icon),d=He[l.category]??He.platform;return e.jsxs("button",{onClick:()=>s(a),style:{display:"flex",flexDirection:"column",alignItems:"center",gap:"6px",background:"none",border:"none",cursor:"pointer",padding:0},"aria-label":l.name,children:[e.jsx("div",{style:{width:60,height:60,borderRadius:16,background:d,display:"flex",alignItems:"center",justifyContent:"center"},children:e.jsx(g,{size:26,color:"rgba(255,255,255,0.9)"})}),e.jsx("span",{style:{fontSize:11,color:"rgba(255,255,255,0.8)",textAlign:"center",lineHeight:1.2,maxWidth:64,overflow:"hidden",textOverflow:"ellipsis",whiteSpace:"nowrap"},children:l.name})]},u)})},`ag-${i}`)})})}function ss({onOpenApp:t}){const s=ie(g=>g.pages),n=ie(g=>g.activePageIndex),r=ie(g=>g.setActivePage),i=D.useRef(null),a=s[n]??s[0],u=D.useCallback(g=>{var d;i.current=((d=g.touches[0])==null?void 0:d.clientX)??null},[]),l=D.useCallback(g=>{var f;if(i.current===null)return;const d=(((f=g.changedTouches[0])==null?void 0:f.clientX)??0)-i.current;i.current=null,!(Math.abs(d)<50)&&(d<0&&n0&&n>0&&r(n-1))},[n,s.length,r]);return e.jsxs("div",{style:{height:"100%",display:"flex",flexDirection:"column"},children:[e.jsx("div",{style:{flex:1,overflowY:"auto",padding:"12px 16px 0"},onTouchStart:u,onTouchEnd:l,children:a&&e.jsx(ns,{page:a,onOpenApp:t})}),e.jsx("div",{style:{display:"flex",flexDirection:"row",alignItems:"center",justifyContent:"center",gap:10,padding:"12px 0",flexShrink:0},role:"tablist","aria-label":"Home screen pages",children:s.map((g,d)=>{const f=d===n;return e.jsx("button",{role:"tab","aria-selected":f,"aria-label":`Page ${d+1}`,onClick:()=>!f&&r(d),style:{width:f?36:12,height:12,borderRadius:f?6:"50%",background:f?"rgba(255,255,255,0.7)":"rgba(255,255,255,0.2)",border:"none",padding:0,cursor:f?"default":"pointer",transition:"width 0.2s ease, background 0.2s ease"}},d)})})]})}function Ue({onDone:t,invitedUsername:s,inviteCode:n,defaultAutoLogin:r}){const i=!!(s&&n),[a,u]=o.useState(s??""),[l,g]=o.useState(""),[d,f]=o.useState(""),[m,p]=o.useState(""),[h,c]=o.useState(""),[x,y]=o.useState(r??!i),[w,b]=o.useState(""),[j,k]=o.useState(!1),N=m.length>=4,C=m.length>0&&m===h,A=a.trim().length>0&&l.trim().length>0&&N&&C;async function E(v){if(v.preventDefault(),!!A){k(!0),b("");try{const W=i?"/auth/complete":"/auth/setup",T={username:a.trim(),full_name:l.trim(),email:d.trim(),password:m,auto_login:x};i&&(T.invite_code=n);const O=await fetch(W,{method:"POST",headers:{"Content-Type":"application/json"},credentials:"include",body:JSON.stringify(T)});if(!O.ok){const $=await O.json().catch(()=>({}));b(($==null?void 0:$.error)??`Setup failed (${O.status})`),k(!1);return}t()}catch{b("Network error — please try again"),k(!1)}}}return e.jsx("div",{className:"h-screen w-screen flex items-center justify-center overflow-y-auto",style:{background:"linear-gradient(160deg, #1a1b2e 0%, #1e2140 40%, #252848 100%)",paddingTop:"calc(env(safe-area-inset-top, 0px) + 16px)",paddingBottom:"calc(env(safe-area-inset-bottom, 0px) + 16px)",paddingLeft:"calc(env(safe-area-inset-left, 0px) + 16px)",paddingRight:"calc(env(safe-area-inset-right, 0px) + 16px)"},children:e.jsxs("form",{onSubmit:E,className:"w-full max-w-md p-6 rounded-2xl border border-white/10",style:{backgroundColor:"rgba(255,255,255,0.04)",backdropFilter:"blur(20px)"},"aria-label":i?"Complete your account":"Welcome to taOS",children:[e.jsxs("div",{className:"flex flex-col items-center gap-3 mb-6",children:[e.jsx("div",{className:"w-14 h-14 rounded-2xl flex items-center justify-center",style:{background:"linear-gradient(135deg, #8b92a3, #5b6170)"},children:e.jsx(Ot,{size:24,className:"text-white"})}),e.jsx("h1",{className:"text-lg font-semibold text-shell-text",children:i?"Complete your account":"Welcome to taOS"}),e.jsx("p",{className:"text-xs text-shell-text-secondary text-center",children:i?"Set a password and fill in your details to activate your account.":"Set up your account. You can change any of these later in Settings."})]}),e.jsxs("div",{className:"space-y-3",children:[e.jsx(J,{label:"Username",id:"onb-username",required:!0,children:i?e.jsx("div",{id:"onb-username",className:"onb-input opacity-60 cursor-not-allowed","aria-readonly":"true",role:"textbox",children:a}):e.jsx("input",{id:"onb-username",type:"text",value:a,onChange:v=>u(v.target.value.replace(/\s+/g,"").toLowerCase()),autoComplete:"username",autoFocus:!0,placeholder:"jay",className:"onb-input"})}),e.jsx(J,{label:"Full name",id:"onb-fullname",required:!0,children:e.jsx("input",{id:"onb-fullname",type:"text",value:l,onChange:v=>g(v.target.value),autoComplete:"name",autoFocus:i,placeholder:"Jay Doe",className:"onb-input"})}),e.jsx(J,{label:"Email",id:"onb-email",hint:"Used for cloud services later. Optional today.",children:e.jsx("input",{id:"onb-email",type:"email",value:d,onChange:v=>f(v.target.value),autoComplete:"email",placeholder:"you@example.com",className:"onb-input"})}),e.jsx(J,{label:"Password",id:"onb-password",required:!0,hint:"At least 4 characters.",children:e.jsx("input",{id:"onb-password",type:"password",value:m,onChange:v=>p(v.target.value),autoComplete:"new-password",className:"onb-input"})}),e.jsxs(J,{label:"Confirm password",id:"onb-confirm",required:!0,children:[e.jsx("input",{id:"onb-confirm",type:"password",value:h,onChange:v=>c(v.target.value),autoComplete:"new-password",className:"onb-input","aria-invalid":h.length>0&&!C}),h.length>0&&!C&&e.jsx("p",{className:"text-[11px] text-red-400 mt-1",children:"Passwords don't match."})]}),e.jsxs("label",{htmlFor:"onb-autologin",className:"flex items-start gap-3 mt-1 cursor-pointer select-none",children:[e.jsx("input",{id:"onb-autologin",type:"checkbox",checked:x,onChange:v=>y(v.target.checked),className:"mt-0.5 w-4 h-4 accent-accent cursor-pointer"}),e.jsxs("span",{className:"text-xs text-shell-text-secondary leading-snug",children:["Stay signed in on this device",e.jsx("span",{className:"block text-[10px] text-shell-text-tertiary mt-0.5",children:"Skips the login screen for a year. Turn off if this is a shared device."})]})]})]}),w&&e.jsx("p",{className:"text-xs text-red-400 mt-3 text-center",role:"alert",children:w}),e.jsx("button",{type:"submit",disabled:!A||j,className:"w-full mt-5 px-4 py-2.5 rounded-lg bg-accent text-white text-sm font-medium hover:brightness-110 disabled:opacity-40 disabled:cursor-not-allowed transition-all",children:j?i?"Activating...":"Setting up...":i?"Activate account":"Get started"}),e.jsx("style",{children:` .onb-input { width: 100%; padding: 10px 14px; diff --git a/static/desktop/chat.html b/static/desktop/chat.html index 00e358fb..c88fc1c8 100644 --- a/static/desktop/chat.html +++ b/static/desktop/chat.html @@ -43,7 +43,7 @@ } #root { height: 100%; width: 100%; } - + diff --git a/static/desktop/index.html b/static/desktop/index.html index 1db17af2..4a3ade04 100644 --- a/static/desktop/index.html +++ b/static/desktop/index.html @@ -47,7 +47,7 @@ width: 100vw; } - + From c3416f9a9e28b63e907ce8df575caa6db532441a Mon Sep 17 00:00:00 2001 From: jaylfc Date: Mon, 20 Apr 2026 14:12:30 +0100 Subject: [PATCH 8/9] test(e2e): chat Phase 3 typing footer smoke stub --- tests/e2e/test_chat_phase3.py | 29 +++++++++++++++++++++++++++++ 1 file changed, 29 insertions(+) create mode 100644 tests/e2e/test_chat_phase3.py diff --git a/tests/e2e/test_chat_phase3.py b/tests/e2e/test_chat_phase3.py new file mode 100644 index 00000000..0c67081f --- /dev/null +++ b/tests/e2e/test_chat_phase3.py @@ -0,0 +1,29 @@ +"""Chat Phase 3 — typing-phase labels E2E. + +Requires TAOS_E2E_URL set. +""" +import os + +import pytest +from playwright.sync_api import Page, expect + +pytestmark = [ + pytest.mark.e2e, + pytest.mark.skipif( + not os.environ.get("TAOS_E2E_URL"), + reason="TAOS_E2E_URL required", + ), +] +URL = os.environ.get("TAOS_E2E_URL", "") + + +def test_typing_footer_renders_at_all(page: Page): + """Smoke: open the chat, typing footer region is mounted (visibility + depends on real agent activity which this stub doesn't trigger).""" + page.goto(URL) + page.get_by_role("button", name="Messages").click() + page.get_by_text("roundtable").first.click() + # The footer container is always mounted (hidden when empty); just verify + # the channel opens without crash. Observing actual phase labels requires + # a backend test harness emitting phase heartbeats — out of scope for this stub. + expect(page.get_by_role("button", name="Attach files").first).to_be_visible() From 31bcbce9cde5a695ad99e77a34479ea963a8f431 Mon Sep 17 00:00:00 2001 From: jaylfc Date: Mon, 20 Apr 2026 14:30:15 +0100 Subject: [PATCH 9/9] fix(chat): guard non-string phase/detail in POST /thinking (400 not 500) --- tinyagentos/routes/chat.py | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/tinyagentos/routes/chat.py b/tinyagentos/routes/chat.py index f12a2442..b356afe7 100644 --- a/tinyagentos/routes/chat.py +++ b/tinyagentos/routes/chat.py @@ -886,9 +886,15 @@ async def post_thinking(channel_id: str, body: dict, request: Request): return JSONResponse({"error": "slug and state in {start,end} required"}, status_code=400) phase = (body or {}).get("phase") - if phase is not None and phase not in VALID_PHASES: - return JSONResponse({"error": f"invalid phase; must be one of {sorted(VALID_PHASES)}"}, status_code=400) + if phase is not None: + if not isinstance(phase, str) or phase not in VALID_PHASES: + return JSONResponse( + {"error": f"invalid phase; must be one of {sorted(VALID_PHASES)}"}, + status_code=400, + ) detail = (body or {}).get("detail") + if detail is not None and not isinstance(detail, str): + return JSONResponse({"error": "detail must be a string"}, status_code=400) reg = getattr(request.app.state, "typing", None) hub = getattr(request.app.state, "chat_hub", None)