@rubytech/create-sitedesk-code 0.1.402 → 0.1.404

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (59) hide show
  1. package/package.json +1 -1
  2. package/payload/platform/plugins/web-designer/skills/web-design/references/placeholders.md +19 -2
  3. package/payload/platform/plugins/web-designer/skills/web-design/templates/index.html +12 -12
  4. package/payload/platform/scripts/check-no-esm-require.mjs +3 -0
  5. package/payload/premium-plugins/sitedesk/BUNDLE.md +6 -4
  6. package/payload/premium-plugins/sitedesk/PLUGIN.md +2 -2
  7. package/payload/premium-plugins/sitedesk/agents/sitedesk--media-producer.md +18 -7
  8. package/payload/premium-plugins/sitedesk/plugins/sitedesk-media/.claude-plugin/plugin.json +1 -1
  9. package/payload/premium-plugins/sitedesk/plugins/sitedesk-media/PLUGIN.md +30 -26
  10. package/payload/premium-plugins/sitedesk/plugins/sitedesk-media/README.md +26 -36
  11. package/payload/premium-plugins/sitedesk/plugins/sitedesk-media/commands/make-media.md +2 -2
  12. package/payload/premium-plugins/sitedesk/plugins/sitedesk-media/skills/microsite/SKILL.md +52 -75
  13. package/payload/premium-plugins/sitedesk/plugins/sitedesk-media/skills/socials/SKILL.md +52 -120
  14. package/payload/premium-plugins/sitedesk/plugins/sitedesk-media/skills/socials/references/sources.md +17 -52
  15. package/payload/server/public/assets/{AdminLoginScreens-rlk263u9.js → AdminLoginScreens-BzErD9Zo.js} +1 -1
  16. package/payload/server/public/assets/AdminShell-BihejKg_.js +1 -0
  17. package/payload/server/public/assets/{Checkbox-Chz6bfy-.js → Checkbox-Ds004CBE.js} +1 -1
  18. package/payload/server/public/assets/{Transcript-Bsx-bGgY.js → Transcript-CgaMQKgY.js} +1 -1
  19. package/payload/server/public/assets/{admin-BnZH758N.js → admin-BSuRtMws.js} +1 -1
  20. package/payload/server/public/assets/{browser-CIrfyZWe.js → browser-BO2eR_YY.js} +1 -1
  21. package/payload/server/public/assets/{calendar-D6Z8Kmrn.js → calendar-12QuR_oh.js} +1 -1
  22. package/payload/server/public/assets/chat-Qpyg5t65.js +1 -0
  23. package/payload/server/public/assets/chevron-left-DBUeR2CX.js +1 -0
  24. package/payload/server/public/assets/data-Ch5bne41.js +1 -0
  25. package/payload/server/public/assets/{graph-XZJZHzvv.js → graph-CDOJZepc.js} +1 -1
  26. package/payload/server/public/assets/{graph-labels-Cabqmf35.js → graph-labels-6HKBjyXX.js} +1 -1
  27. package/payload/server/public/assets/{maximize-2-DPe-Noig.js → maximize-2-DWmyXX8h.js} +1 -1
  28. package/payload/server/public/assets/{operator-BM_CDyCb.js → operator-D-s7jVnf.js} +1 -1
  29. package/payload/server/public/assets/{page-CMIbXzSg.js → page-BcxrdxYL.js} +1 -1
  30. package/payload/server/public/assets/{page-E7I5sEVt.js → page-rDhp8G9q.js} +1 -1
  31. package/payload/server/public/assets/{public-CrdWCSk2.js → public-zK67N3z2.js} +1 -1
  32. package/payload/server/public/assets/{rotate-ccw-Dwtj0NJ7.js → rotate-ccw-BzBJxqBN.js} +1 -1
  33. package/payload/server/public/assets/useSubAccountSwitcher-B-GuP1jj.css +1 -0
  34. package/payload/server/public/browser.html +4 -4
  35. package/payload/server/public/calendar.html +5 -5
  36. package/payload/server/public/chat.html +9 -9
  37. package/payload/server/public/data.html +8 -8
  38. package/payload/server/public/graph.html +9 -9
  39. package/payload/server/public/index.html +11 -11
  40. package/payload/server/public/operator.html +11 -11
  41. package/payload/server/public/public.html +9 -9
  42. package/payload/server/server.js +32 -32
  43. package/payload/premium-plugins/sitedesk/plugins/sitedesk-media/skills/brand-extract/SKILL.md +0 -86
  44. package/payload/premium-plugins/sitedesk/plugins/sitedesk-media/skills/make-media/SKILL.md +0 -75
  45. package/payload/premium-plugins/sitedesk/plugins/sitedesk-media/skills/make-media/references/intake-and-questions.md +0 -74
  46. package/payload/premium-plugins/sitedesk/plugins/sitedesk-media/skills/microsite/references/placeholders.md +0 -96
  47. package/payload/premium-plugins/sitedesk/plugins/sitedesk-media/skills/microsite/references/sections.md +0 -48
  48. package/payload/premium-plugins/sitedesk/plugins/sitedesk-media/skills/microsite/templates/index.html +0 -1004
  49. package/payload/premium-plugins/sitedesk/plugins/sitedesk-media/skills/microsite/templates/llms.txt +0 -32
  50. package/payload/premium-plugins/sitedesk/plugins/sitedesk-media/skills/socials/references/pii-strip.md +0 -64
  51. package/payload/premium-plugins/sitedesk/plugins/sitedesk-media/skills/socials/templates/og.html +0 -92
  52. package/payload/premium-plugins/sitedesk/plugins/sitedesk-media/skills/socials/templates/social-posts.md +0 -47
  53. package/payload/premium-plugins/sitedesk/plugins/sitedesk-media/skills/socials/templates/socials.html +0 -87
  54. package/payload/server/public/assets/AdminShell-C5vWTy2n.js +0 -1
  55. package/payload/server/public/assets/chat-h7SytZHx.js +0 -1
  56. package/payload/server/public/assets/chevron-left-DSTeS1_g.js +0 -1
  57. package/payload/server/public/assets/data-CL7CyX1C.js +0 -1
  58. package/payload/server/public/assets/useSubAccountSwitcher-BH-YjP0H.css +0 -1
  59. /package/payload/server/public/assets/{useSubAccountSwitcher-BVCMAnWK.js → useSubAccountSwitcher-Bg0RH3Gk.js} +0 -0
@@ -1,133 +1,65 @@
1
1
  ---
2
2
  name: socials
3
- description: Render share-ready Open Graph and social tiles plus per-platform captions for a named subject — a brand micro-site, a job's progress, a valuation cycle, or a bespoke topic with a PII gate for any source that can carry client data. Resolves the subject through a source adapter into candidate images and copy, overlays brand typography, screenshots landscape (1200×628), square (1200×1200) and portrait (1080×1350) PNG tiles via the on-device browser, assembles a gallery and a captions file for all five platforms, and emits a redaction report reconciling every source item. For micro-sites it also wires the site's og:image. Never posts — the bundle is for operator review. Trigger phrases include "social tiles for this job", "og images for the site", "Instagram tiles + captions for <subject>", "social collateral for <business>".
3
+ description: Render share-ready Open Graph and social tiles plus captions for a SiteDesk subject — a brand micro-site, a job's progress, a valuation cycle, or a bespoke topic. The micro-site and bespoke subjects delegate straight to web-designer:socials. The job and valuation subjects are SiteDesk-specific: they read the job's progress from carried job state under a strict money boundary, stage a brand-safe brief, and render it through web-designer:socials in bespoke mode. Never posts — the bundle is for operator review. Trigger phrases include "social tiles for this job", "og images for the site", "valuation-cycle tiles for <job>", "social collateral for <business>".
4
4
  allowed-tools:
5
+ - Skill
5
6
  - Bash
6
7
  - Read
7
8
  - Write
8
9
  - Edit
9
10
  - Glob
10
11
  - Grep
11
- - mcp__plugin_browser_browser__browser-render
12
- - mcp__plugin_browser_browser__browser-navigate
13
- - mcp__plugin_browser_browser__browser-evaluate
14
- - mcp__plugin_browser_browser__browser-resize
15
- - mcp__plugin_browser_browser__browser-screenshot
16
- - mcp__plugin_browser_browser__browser-wait-for
17
12
  ---
18
13
 
19
14
  # socials
20
15
 
21
- One skill, one subject at a time. You take a named **subject**, resolve it through a
22
- source adapter, and emit a publication bundle: exact-size PNG social tiles, captions
23
- for all five platforms, a gallery, and for any subject that can carry client data
24
- a redaction report. You **never post**. The bundle is for the operator to review
25
- and sign off. You ship no business content; every fact is the operator's own data,
26
- read from the resolved source.
27
-
28
- ## Inputs
29
-
30
- - **subject** a name (the business, the job, the topic).
31
- - **mode** one of `microsite`, `job`, `valuation`, `bespoke`.
32
- - **material** the path the adapter reads (a built `site/`, a job folder, or the
33
- operator's own photos and notes).
34
- - **output** — where the bundle lands (for `microsite`, the site's own `site/`).
35
-
36
- ## 1. Resolve the subject, and echo it
37
-
38
- Resolve the subject through its adapter in [`references/sources.md`](references/sources.md)
39
- to the normalized intermediate (`topic`, headline/sub candidates, copy facts,
40
- candidate images, `piiBearing`). **Before you render anything, state the resolved
41
- subject and the source mode back** — e.g. "Resolving job 1737 in `valuation` mode,
42
- this period's progress." A mis-resolution must be visible here, not discovered in a
43
- finished tile.
44
-
45
- ## 2. PII gate (if `piiBearing`)
46
-
47
- If the adapter's `piiBearing` is true (`job` and `valuation` always; `bespoke`
48
- unless the operator declared the material brand-safe), run the gate in
49
- [`references/pii-strip.md`](references/pii-strip.md) over **every** candidate image
50
- and **every** copy fact before any of it reaches a template. Write
51
- `redaction-report.md` reconciling every source photo and text field as
52
- *used / redacted / rejected*. If every photo is rejected, stop and ask for a usable
53
- image; never emit an imageless bundle. **Do not present a bundle without the report.**
54
- `microsite` skips this step (the site is already published copy).
55
-
56
- ## 3. Render the tiles (browser plugin, PNG)
57
-
58
- 1. Build the resolved render page: copy [`templates/og.html`](templates/og.html) to
59
- `<output>/og.html` and substitute `{{ CANDIDATES_JSON }}` with the vetted
60
- candidate set (`{ key: { img, pos, head, sub }, }`) plus the scalar tokens
61
- (palette, eyebrow, specs, domain, phone). The logo and hero images resolve from
62
- the output dir's `images/`.
63
- 2. Serve `<output>/` over a local HTTP server so relative paths and webfonts load
64
- (`cd <output> && python3 -m http.server <port>` via `Bash`; `file://` will not
65
- load the fonts).
66
- 3. For each tile, drive the on-device browser:
67
- - `browser-navigate` to `http://localhost:<port>/og.html?format=F&hero=H`,
68
- - `browser-resize` to the exact size — landscape `1200×628`, square `1200×1200`,
69
- portrait `1080×1350`,
70
- - `browser-evaluate` `document.fonts.ready.then(() => true)` (and a short settle)
71
- so the webfonts have landed before capture,
72
- - `browser-screenshot` to `<output>/socials/og-F-H.png`.
73
- A **person** hero (`isPerson: true`) renders **portrait only** — a landscape or
74
- square crop cuts off the head.
75
- 4. `Read` each finished PNG to confirm it rendered: logo legible, copy readable,
76
- scrim adequate. A **sub-20KB** file is a blank page (server not running, wrong
77
- port, or the page threw) — diagnose before re-running, never ship it.
78
-
79
- ## 4. Captions — all five platforms, plain register
80
-
81
- Build `<output>/social-posts.md` from [`templates/social-posts.md`](templates/social-posts.md):
82
- one block per tile, with copy for **Instagram, LinkedIn, TikTok, Facebook, and X**.
83
- Write every line in the plain register (the `plainly` skill): no em-dashes, no
84
- inflation vocabulary, no "it's not X, it's Y", no rhetorical openers, no emoji faking
85
- enthusiasm. For a `piiBearing` subject, no caption names the client, the address or
86
- postcode, any figure, any individual, or any email sender.
87
-
88
- ## 5. Gallery, and (microsite only) the og:image
89
-
90
- Build `<output>/socials.html` from [`templates/socials.html`](templates/socials.html):
91
- repeat the group block once per tile key. For a **person** hero (`isPerson: true`),
92
- write only the portrait `<div class="tile">` cell for that key — delete the landscape
93
- and square cells, since those files are never rendered for a person.
94
-
95
- The OG snippet (`<div class="snippet">…</div>`) is **microsite only**. In `microsite`
96
- mode, keep it, render the tiles into the site's `site/socials/`, and set the site's
97
- `og:image`/`twitter:image` to `<WEBSITE_URL>socials/og-landscape-main.png` (a true
98
- 1200×628 card beats a raw hero for link previews; `WEBSITE_URL` is the site's absolute
99
- URL from the brand pack). For a **job/valuation/bespoke** bundle there is no site to
100
- wire — **delete the whole `<div class="snippet">` block** from the copied template
101
- before substituting, so no `WEBSITE_URL` token survives.
102
-
103
- ## Output contract
104
-
105
- ```
106
- <output>/
107
- og.html # the resolved render page (kept for re-runs)
108
- socials/
109
- og-landscape-<key>.png og-square-<key>.png og-portrait-<key>.png # per tile
110
- og-portrait-<person-key>.png # a person hero: portrait only
111
- socials.html # gallery: each tile at size, download links
112
- social-posts.md # captions per tile, all five platforms
113
- redaction-report.md # piiBearing subjects only — the standing reconciliation
114
- ```
115
-
116
- ## Completion criteria
117
-
118
- - Every tile exists at its exact pixel size; a person tile is portrait only.
119
- - Captions cover all five platforms; `socials.html` previews each tile with a working
120
- download link.
121
- - For a `piiBearing` subject, `redaction-report.md` is present and accounts for
122
- **every** source photo and text field; no output names the client, the address, a
123
- figure, an individual, or an email sender.
124
- - In `microsite` mode, the site's `og:image`/`twitter:image` point at the landscape
125
- main tile.
126
- - `Read` each finished PNG — file size alone is not proof.
127
-
128
- ## When NOT to use
129
-
130
- - The operator wants to **post** — this skill never posts; it produces a reviewable
131
- bundle and stops.
132
- - The deliverable is the micro-site itself → `microsite`. The full marketing run
133
- (site + tiles) → `make-media`, which calls this skill in `microsite` mode.
16
+ SiteDesk renders tiles for four subjects: `microsite`, `bespoke`, `job`, and
17
+ `valuation`. The **render core is web-designer's** this skill owns no tile
18
+ template, gallery, caption, or PII-gate machinery. It owns one thing: turning a
19
+ SiteDesk **job** or **valuation** into a brand-safe brief that `web-designer:socials`
20
+ can render. You **never post**; the bundle is for the operator to review.
21
+
22
+ ## microsite and bespoke — delegate
23
+
24
+ Run `web-designer:socials` directly in the same mode on the same subject. For a
25
+ built `site/`, that is `microsite` mode (it also wires the site's `og:image`); for
26
+ an operator-chosen topic with the operator's own photos and notes, that is `bespoke`
27
+ mode (its PII gate runs unless the operator declares the material brand-safe). Add
28
+ nothing here web-designer owns the whole run.
29
+
30
+ ## job and valuation — resolve, then render as bespoke
31
+
32
+ These read the operator's live job state, so SiteDesk owns the read under a strict
33
+ money boundary; the rendering is still web-designer's.
34
+
35
+ 1. **Resolve the job under the money boundary.** Read the job folder per
36
+ [`references/sources.md`](references/sources.md) the `job` adapter for a
37
+ whole-job milestone, the `valuation` adapter for this cycle's progress. Read only
38
+ the allowed non-money progress fields; **never** the money fields or the issued
39
+ `valuations/` documents. `sources.md` is the exact contract; it is the one place
40
+ the money boundary is written.
41
+ 2. **Stage a brand-safe brief.** Write the resolved subject to a staging folder as a
42
+ bespoke brief: a `topic`, headline and sub candidates from the strongest progress
43
+ lines, `copyFacts` limited to neutral context (a stage name, a trade, a month, a
44
+ town — never a figure or a client identifier), and the `source/` photos as
45
+ candidate images. No money field and no client identifier reaches the brief.
46
+ 3. **Render through web-designer.** Run `web-designer:socials` in `bespoke` mode on
47
+ the staged brief. Its PII gate runs over the staged images and copy as a second
48
+ check and writes the redaction report; `web-designer:socials` never reads the job
49
+ folder or `state.json`. State the resolved subject back before rendering — e.g.
50
+ "Resolving job 1737 in valuation mode, this period's progress."
51
+
52
+ ## The money boundary is absolute
53
+
54
+ No tile, caption, or brief SiteDesk produces from a job may carry a contract,
55
+ valuation, or payment figure, any `pctComplete` value, or any client identifier.
56
+ The progress is the story; the figures never leave the job folder. This boundary is
57
+ enforced at the read in step 1 (only non-money fields are ever read) and re-checked
58
+ by web-designer's gate at step 3.
59
+
60
+ ## What this does not do
61
+
62
+ - It ships no render template, gallery, caption set, or PII-gate reference — those
63
+ live in `web-designer:socials`.
64
+ - It never posts, never deploys, and never reads a money field or a `valuations/`
65
+ document.
@@ -1,13 +1,17 @@
1
- # socials — source adapters
1
+ # socials — SiteDesk job source adapters
2
2
 
3
- The `socials` skill resolves a named **subject** to a normalized intermediate that
4
- the shared render core consumes. One adapter per subject kind. This file is the
5
- contract and the **extension point**: a future subject (a quote, a timesheet, a
6
- testimonial) is a new row here, not a new skill.
3
+ SiteDesk owns two subject adapters: `job` and `valuation`. Both read the operator's
4
+ live job state and resolve it to the normalized intermediate below, which
5
+ `web-designer:socials` renders in `bespoke` mode. The `microsite` and `bespoke`
6
+ adapters are web-designer's this file does not repeat them.
7
+
8
+ This file is the one place SiteDesk's **money boundary** is written. It is the
9
+ contract for what a job tile may and may not carry.
7
10
 
8
11
  ## The normalized intermediate
9
12
 
10
- Every adapter resolves its subject to this shape:
13
+ Each adapter resolves its subject to the shape `web-designer:socials` bespoke mode
14
+ consumes:
11
15
 
12
16
  ```
13
17
  {
@@ -16,40 +20,16 @@ Every adapter resolves its subject to this shape:
16
20
  subCandidates, // [string] — supporting lines, paired to headlines
17
21
  copyFacts, // { eyebrow, specs[], domain, phone } — overlay scalars
18
22
  candidateImages, // [{ key, path, isPerson }] — vetted backgrounds
19
- piiBearing // boolean — does this source carry client data?
23
+ piiBearing // boolean — job and valuation are always true
20
24
  }
21
25
  ```
22
26
 
23
- `candidateImages[].key` becomes the tile `hero` and the filename suffix
24
- (`og-<format>-<key>.png`). `isPerson: true` marks a hero that must render
25
- **portrait only** (a landscape or square crop cuts off the head). `piiBearing`
26
- decides whether the PII gate in [`pii-strip.md`](pii-strip.md) runs before any of
27
- this reaches a template.
28
-
29
- ## Adapters
30
-
31
- ### `microsite` — `piiBearing: false`
32
-
33
- Reads a built `site/` directory (the output of `microsite`): the brand pack
34
- (`brand.md` tokens, `images/logo.png`) and the curated hero photos at the fixed
35
- paths the micro-site uses:
36
-
37
- | key | image | leads with |
38
- |---|---|---|
39
- | `main` | `images/hero-01.webp` | the firm's lead line |
40
- | `interior` | `images/hero-03.webp` | a finishes line |
41
- | `build` | `images/hero-06.webp` | a process line |
42
- | `founder` | `images/founder-portrait.webp` | "meet the…" — **`isPerson: true`, portrait only** |
43
-
44
- `copyFacts` for `microsite` is the brand pack's own credential cells (sector,
45
- trades, areas, years) plus `domain`, `phone`, and the site's full `WEBSITE_URL` (the
46
- microsite-only og:image wiring needs the absolute URL, not just the domain).
27
+ `candidateImages[].key` becomes the tile `hero` and the filename suffix.
28
+ `isPerson: true` marks a hero that must render portrait only. `piiBearing: true`
29
+ means web-designer's PII gate runs over the staged brief before any of it reaches a
30
+ template.
47
31
 
48
- Brand-safe by construction (the site is already published copy), so the PII gate is
49
- skipped. This is the path `make-media` calls as its final stage; it also wires the
50
- site's `og:image`/`twitter:image` to the landscape `main` tile.
51
-
52
- ### `job` — `piiBearing: true`
32
+ ## `job` `piiBearing: true`
53
33
 
54
34
  A whole-job progress milestone. Topic = the site/job overall. Reads the job folder
55
35
  `{ACCOUNT_DIR}/jobs/{jobId}/`:
@@ -72,25 +52,10 @@ client should never see on a public tile. `lines[].id` and `variations[].number`
72
52
  **keys only** — use them to select a line, never as copy on a tile or caption (an
73
53
  operator may have keyed a line with a client name or address fragment).
74
54
 
75
- ### `valuation` — `piiBearing: true`
55
+ ## `valuation` — `piiBearing: true`
76
56
 
77
57
  The current valuation cycle's progress. Same job folder and the **same non-money
78
58
  fields** as `job`, but framed to **this period**: the lines and variations whose
79
59
  `pctComplete` advanced this cycle. Topic = "this period's progress on the job". The
80
60
  same money-field and `valuations/`-document exclusions apply — read the progress,
81
61
  never the figures.
82
-
83
- ### `bespoke` — `piiBearing: true` (operator may waive)
84
-
85
- An operator-chosen topic with the operator's own photos and notes. The operator
86
- supplies the topic, the headline/sub ideas, and the candidate images. The PII gate
87
- runs by default; the operator may declare the material brand-safe (their own
88
- marketing photos, no client identifiable) to skip it — that declaration is the only
89
- way the gate is waived for a bespoke subject.
90
-
91
- ## Adding a subject later
92
-
93
- A new subject kind (quote, timesheet, testimonial, …) is a new adapter section here:
94
- name what it reads, how it maps to the normalized intermediate, and its `piiBearing`
95
- value. No new skill, no new render core, no new caption register. If the source can
96
- carry client data, set `piiBearing: true` and the existing gate covers it.
@@ -1 +1 @@
1
- import{o as e}from"./chunk-CAM3fms7.js";import{A as t,L as n,M as r,N as i,O as a}from"./useSubAccountSwitcher-BVCMAnWK.js";import{i as o}from"./admin-types-hioowVct.js";import{b as s,x as c}from"./AdminShell-C5vWTy2n.js";import{t as l}from"./Checkbox-Chz6bfy-.js";var u=`admin-landing-redirected`,d=`/graph`;function f(e){return e.variant===`operator`?!1:e.appState===`chat`&&!e.alreadyRedirected}var p=e(n(),1);function m(e=`admin`){let[t,n]=(0,p.useState)(`loading`),[r,a]=(0,p.useState)(``),[s,l]=(0,p.useState)(``),[m,h]=(0,p.useState)(``),[g,_]=(0,p.useState)(!1),[v,y]=(0,p.useState)(!1),[b,x]=(0,p.useState)(!1),[S,C]=(0,p.useState)(!1),[w,T]=(0,p.useState)(!1),[E,D]=(0,p.useState)(null),[O,k]=(0,p.useState)(null),[A,j]=(0,p.useState)(void 0),[M,N]=(0,p.useState)(null),[P,F]=(0,p.useState)(void 0),[I,L]=(0,p.useState)(null),[R,z]=(0,p.useState)(null),[B,V]=(0,p.useState)(void 0),H=(0,p.useRef)(void 0),[U,W]=(0,p.useState)(!1),[G,K]=(0,p.useState)(!0);(0,p.useEffect)(()=>{typeof window>`u`||fetch(`/api/remote-auth/status`).then(e=>e.ok?e.json():null).then(e=>{e?.configured&&W(!0)}).catch(()=>{})},[]);let q=(0,p.useRef)(null),J=(0,p.useRef)(null);(0,p.useEffect)(()=>{async function e(){let e=null;try{e=sessionStorage.getItem(`maxy-admin-session-key`)}catch{}if(!e)return!1;try{let t=await fetch(`/api/admin/session?session_key=${encodeURIComponent(e)}`);if(t.status===401){try{sessionStorage.removeItem(`maxy-admin-session-key`)}catch{}return!1}if(!t.ok)return!1;let r=await t.json();D(r.session_key),z(r.sessionId??null),j(r.businessName),N(r.role??null),F(r.userName===void 0?null:r.userName),L(r.avatar??null);let i=o(r.thinkingView);return H.current=i,V(i),n(`chat`),!0}catch(e){return console.error(`[admin] session restore failed:`,e),!1}}async function t(r=2){try{let i=await fetch(`/api/health`);if(!i.ok){if(r>0)return await new Promise(e=>setTimeout(e,1500)),t(r-1);console.error(`[admin] health check returned ${i.status} after retries`),n(`set-pin`);return}let a=await i.json();if(!a.pin_configured){n(`set-pin`);return}K(!!a.claude_authenticated);let o=!1;try{o=new URLSearchParams(window.location.search).get(`connect`)===`claude`}catch{}if(o){try{let e=new URL(window.location.href);e.searchParams.delete(`connect`),window.history.replaceState(null,``,e.pathname+e.search+e.hash)}catch{}if(!a.claude_authenticated){n(`connect-claude`);return}}if(await e())return;n(`enter-pin`)}catch(e){if(r>0)return await new Promise(e=>setTimeout(e,1500)),t(r-1);console.error(`[admin] health check failed:`,e),n(`set-pin`)}}t()},[]),(0,p.useEffect)(()=>{t===`chat`&&fetch(`/api/admin/claude-info`).then(e=>{if(e.ok)return e.json()}).then(e=>{e&&k(e)}).catch(()=>{})},[t]),(0,p.useEffect)(()=>{if(typeof window>`u`)return;let n=!1;try{n=sessionStorage.getItem(u)===`1`}catch{}if(f({appState:t,alreadyRedirected:n,variant:e})){try{sessionStorage.setItem(u,`1`)}catch{}console.info(`[admin-ui] landing-redirect target=${d}`),window.location.replace(d)}},[t,e]);let Y=(0,p.useRef)(null);(0,p.useEffect)(()=>{if(t!==`chat`)return;let e=setInterval(async()=>{try{let e=await fetch(`/api/health`);if(e.ok){let t=await e.json();K(t.auth_status!==`dead`&&t.auth_status!==`missing`)}}catch{}if(E)try{let e=await fetch(`/api/admin/session?session_key=${encodeURIComponent(E)}`);if(e.status!==401)return;let t=(await e.clone().json().catch(()=>null))?.code??`unknown-401`;if(t===`remote-auth-required`){i(`heartbeat`,`/api/admin/session`);return}console.warn(`[admin-auth] outcome=heartbeat-detected-expiry code=${t}`),Y.current?.()}catch{}},300*1e3);return()=>clearInterval(e)},[t,E]),(0,p.useEffect)(()=>{t===`connect-claude`&&fetch(`/api/health`).then(e=>e.ok?e.json():null).then(e=>{e?.claude_authenticated&&(K(!0),n(`enter-pin`))}).catch(()=>{})},[t]);async function X(e,t){y(!0);try{let r=await fetch(`/api/admin/session`,{method:`POST`,headers:{"Content-Type":`application/json`},body:JSON.stringify({pin:e,...t?{accountId:t}:{}})});if(!r.ok){let e=await r.json().catch(()=>({}));if(r.status===401&&e?.code===`remote-auth-required`){i(`enter-pin`,`/api/admin/session`);return}h(e.error||`Invalid PIN`);return}let s=await r.json();D(s.session_key),z(s.sessionId??null),j(s.businessName),N(s.role??null),F(s.userName===void 0?null:s.userName),L(s.avatar??null);let c=o(s.thinkingView);H.current=c,V(c);try{sessionStorage.setItem(`maxy-admin-session-key`,s.session_key)}catch{}a(``),n(`chat`)}catch(e){console.error(`[admin] connection error:`,e),h(`Could not connect.`)}finally{y(!1)}}let Z=(0,p.useCallback)(async e=>{if(e.preventDefault(),v)return;h(``);let t=s.trim();if(!t){h(`Please enter your name.`);return}if(r.length<4){h(`PIN must be at least 4 characters.`);return}let o=r;y(!0);try{let e=await fetch(`/api/onboarding/set-pin`,{method:`POST`,headers:{"Content-Type":`application/json`},body:JSON.stringify({pin:o,name:t})});if(!e.ok){let t=await e.json().catch(()=>({}));if(e.status===401&&t?.code===`remote-auth-required`){i(`set-pin`,`/api/onboarding/set-pin`);return}if(e.status===409){console.log(`[admin] PIN already configured — re-checking health`);try{let e=await fetch(`/api/health`);if(e.ok){let r=await e.json();r.pin_configured&&r.claude_authenticated?n(`enter-pin`):r.pin_configured?n(`connect-claude`):h(t.error||`Failed to set PIN.`)}else n(`enter-pin`)}catch{n(`enter-pin`)}return}h(t.error||`Failed to set PIN.`);return}let r=await fetch(`/api/health`);if((r.ok?await r.json():null)?.claude_authenticated){await X(o);return}a(``),n(`connect-claude`)}catch(e){console.error(`[admin] connection error:`,e),h(`Could not connect.`)}finally{y(!1)}},[r,v,s]),Q=(0,p.useCallback)(async e=>{e.preventDefault(),h(``),await X(r)},[r]),ee=(0,p.useCallback)(async()=>{T(!0);try{if(!await c())return console.warn(`[admin-ui] claude-disconnect not verified — credentials may persist; staying put`),!1;K(!1),D(null),N(null),F(void 0),L(null);try{sessionStorage.removeItem(`maxy-admin-session-key`),sessionStorage.removeItem(u)}catch{}return n(`connect-claude`),!0}finally{T(!1)}},[]),$=(0,p.useCallback)(()=>{D(null),N(null),F(void 0),L(null);try{sessionStorage.removeItem(`maxy-admin-session-key`),sessionStorage.removeItem(u)}catch{}a(``),h(``),n(`enter-pin`)},[]);return(0,p.useEffect)(()=>{Y.current=$},[$]),{appState:t,setAppState:n,pin:r,setPin:a,operatorName:s,setOperatorName:l,pinError:m,setPinError:h,showPin:g,setShowPin:_,pinLoading:v,authPolling:b,setAuthPolling:x,authLoading:S,setAuthLoading:C,disconnecting:w,cacheKey:E,setCacheKey:D,claudeInfo:O,setClaudeInfo:k,businessName:A,role:M,userName:P,userAvatar:I,sessionId:R,setSessionId:z,expandAll:B,setExpandAll:V,expandAllDefaultRef:H,remoteAuthEnabled:U,claudeConnected:G,pinInputRef:q,setPinFormRef:J,handleSetPin:Z,handleLogin:Q,handleDisconnect:ee,handleLogout:$}}var h=r();function g({inputRef:e,value:t,onChange:n,onComplete:r,showPin:i,autoFocus:a}){let o=(0,p.useRef)([]);function s(e,r){r.key===`Backspace`?(r.preventDefault(),t[e]?n(t.slice(0,e)+t.slice(e+1)):e>0&&(n(t.slice(0,e-1)+t.slice(e)),o.current[e-1]?.focus())):r.key===`ArrowLeft`&&e>0?o.current[e-1]?.focus():r.key===`ArrowRight`&&e<5?o.current[e+1]?.focus():r.key===`Enter`&&(r.preventDefault(),r.currentTarget.form?.requestSubmit())}function c(e,i){let a=i.nativeEvent.data;if(!a||!/^\d$/.test(a))return;let s=t.split(``);for(s[e]=a;s.length<e;)s.push(``);let c=s.join(``).replace(/\D/g,``).slice(0,6);n(c),c.length===6?r?.(c):e<5&&o.current[e+1]?.focus()}function l(e){e.preventDefault();let t=e.clipboardData.getData(`text`).replace(/\D/g,``).slice(0,6);t&&(n(t),t.length===6?r?.(t):o.current[t.length]?.focus())}return(0,h.jsx)(`div`,{className:`pin-field`,children:Array.from({length:6}).map((n,r)=>(0,h.jsx)(`input`,{ref:t=>{o.current[r]=t,r===0&&e&&(e.current=t)},type:`text`,inputMode:`numeric`,className:`pin-box${t[r]?` pin-box-filled`:``}`,value:t[r]?i?t[r]:`•`:``,onKeyDown:e=>s(r,e),onInput:e=>c(r,e),onPaste:l,onFocus:e=>e.target.select(),autoFocus:a&&r===0,autoComplete:`off`,maxLength:1,"aria-label":`PIN digit ${r+1}`},r))})}function _(e){let{pin:n,setPin:r,showPin:i,setShowPin:o,pinLoading:c,pinError:u,pinInputRef:d,setPinFormRef:f,onSubmit:p,operatorName:m,setOperatorName:_}=e;return(0,h.jsx)(`div`,{className:`connect-page`,children:(0,h.jsxs)(`div`,{className:`connect-content`,children:[(0,h.jsx)(`img`,{src:t,alt:a.productName,className:`connect-logo connect-logo--maxy`}),!a.logoContainsName&&(0,h.jsxs)(`h1`,{className:`connect-title`,children:[`Welcome to `,a.productName]}),(0,h.jsxs)(`p`,{className:`connect-subtitle`,children:[`Tell `,a.productName,` who you are, then choose a PIN.`]}),(0,h.jsxs)(`form`,{ref:f,onSubmit:p,className:`connect-pin-form`,children:[(0,h.jsxs)(`div`,{className:`pin-input-row`,children:[(0,h.jsx)(`input`,{type:`text`,className:`connect-name-input`,placeholder:`Your full name`,value:m,onChange:e=>_(e.target.value),autoComplete:`name`,autoFocus:!0,required:!0,"aria-label":`Your full name`}),(0,h.jsx)(`div`,{style:{width:38,flexShrink:0},"aria-hidden":`true`})]}),(0,h.jsxs)(`div`,{className:`pin-input-row`,children:[(0,h.jsx)(g,{inputRef:d,value:n,onChange:r,onComplete:()=>{},showPin:i}),(0,h.jsx)(s,{variant:`send`,type:`submit`,disabled:!n||!m.trim(),loading:c,"aria-label":`Set PIN`,children:(0,h.jsxs)(`svg`,{viewBox:`0 0 24 24`,fill:`none`,stroke:`currentColor`,strokeWidth:`2`,strokeLinecap:`round`,strokeLinejoin:`round`,children:[(0,h.jsx)(`line`,{x1:`5`,y1:`12`,x2:`19`,y2:`12`}),(0,h.jsx)(`polyline`,{points:`12 5 19 12 12 19`})]})})]}),(0,h.jsx)(l,{checked:i,onChange:()=>o(e=>!e),label:`Show PIN`})]}),u&&(0,h.jsx)(`p`,{className:`admin-pin-error`,children:u})]})})}function v(e){let{pin:n,setPin:r,showPin:i,setShowPin:o,pinLoading:c,pinError:u,pinInputRef:d,onSubmit:f,remoteAuthEnabled:p,onSignOutRemote:m}=e;return(0,h.jsxs)(`div`,{className:`connect-page`,children:[p&&m&&(0,h.jsx)(`button`,{type:`button`,className:`connect-signout`,onClick:m,children:`Sign out`}),(0,h.jsxs)(`div`,{className:`connect-content`,children:[(0,h.jsx)(`img`,{src:t,alt:a.productName,className:`connect-logo connect-logo--maxy`}),!a.logoContainsName&&(0,h.jsx)(`h1`,{className:`connect-title`,children:a.productName}),(0,h.jsxs)(`form`,{onSubmit:f,className:`connect-pin-form`,children:[(0,h.jsxs)(`div`,{className:`pin-input-row`,children:[(0,h.jsx)(g,{inputRef:d,value:n,onChange:r,onComplete:()=>{},showPin:i,autoFocus:!0}),(0,h.jsx)(s,{variant:`send`,type:`submit`,disabled:!n,loading:c,children:(0,h.jsxs)(`svg`,{viewBox:`0 0 24 24`,fill:`none`,stroke:`currentColor`,strokeWidth:`2`,strokeLinecap:`round`,strokeLinejoin:`round`,children:[(0,h.jsx)(`line`,{x1:`5`,y1:`12`,x2:`19`,y2:`12`}),(0,h.jsx)(`polyline`,{points:`12 5 19 12 12 19`})]})})]}),(0,h.jsx)(`div`,{className:`pin-options`,children:(0,h.jsx)(l,{checked:i,onChange:()=>o(e=>!e),label:`Show PIN`})})]}),u&&(0,h.jsx)(`p`,{className:`admin-pin-error`,children:u})]})]})}function y(e){let{authPolling:n,setAuthPolling:r,authLoading:i,setAuthLoading:o,pinError:c,setPinError:l,setAppState:u}=e,[d,f]=(0,p.useState)(!1),[m,g]=(0,p.useState)(!1),[_,v]=(0,p.useState)(``),[y,b]=(0,p.useState)(``),[x,S]=(0,p.useState)(``);async function C(){S(``);try{let e=await(await fetch(`/api/onboarding/claude-auth`,{method:`POST`,headers:{"Content-Type":`application/json`},body:JSON.stringify({action:`paste-code`,code:y})})).json();e.accepted?(S(`Code submitted. Finishing sign-in…`),b(``)):S(e.error||`Could not submit code.`)}catch(e){console.error(`[admin] paste-code error:`,e),S(`Could not submit code.`)}}async function w(){g(!0),l(``);try{let e=await(await fetch(`/api/onboarding/claude-auth`,{method:`POST`,headers:{"Content-Type":`application/json`},body:JSON.stringify({action:`launch-browser`})})).json();e.launched?f(!0):e.error&&l(e.error)}catch(e){console.error(`[admin] browser launch error:`,e),l(`Could not launch browser.`)}g(!1)}async function T(){o(!0),l(``);try{let e=await(await fetch(`/api/onboarding/claude-auth`,{method:`POST`})).json();if(e.started){r(!0),f(!0),o(!1),v(e.transport||``);for(let e=0;e<120;e++)if(await new Promise(e=>setTimeout(e,2e3)),(await(await fetch(`/api/onboarding/claude-auth`,{method:`POST`,headers:{"Content-Type":`application/json`},body:JSON.stringify({action:`wait`})})).json()).authenticated){await fetch(`/api/onboarding/claude-auth`,{method:`POST`,headers:{"Content-Type":`application/json`},body:JSON.stringify({action:`stop`})}),u(`enter-pin`);return}l(`Timed out waiting for sign-in. Try again.`),r(!1)}else e.error&&l(e.error)}catch(e){console.error(`[admin] auth flow error:`,e),l(`Could not start auth flow.`)}o(!1)}async function E(){await fetch(`/api/onboarding/claude-auth`,{method:`POST`,headers:{"Content-Type":`application/json`},body:JSON.stringify({action:`stop`})}),r(!1),l(``)}return n||d?(0,h.jsxs)(`div`,{style:{display:`flex`,flexDirection:`column`,height:`100dvh`,overflow:`auto`},children:[(0,h.jsxs)(`header`,{className:`chat-header`,style:{paddingBottom:`12px`,flexShrink:0,position:`relative`,maxWidth:`680px`,width:`100%`,margin:`0 auto`,padding:`24px 20px 12px`},children:[n?(0,h.jsx)(`button`,{onClick:E,style:{position:`absolute`,top:`12px`,right:`12px`,background:`none`,border:`none`,color:`#999`,fontSize:`13px`,cursor:`pointer`,padding:`4px 8px`},"aria-label":`Cancel`,children:`✕`}):(0,h.jsx)(`button`,{onClick:()=>f(!1),style:{position:`absolute`,top:`12px`,right:`12px`,background:`none`,border:`none`,color:`#999`,fontSize:`13px`,cursor:`pointer`,padding:`4px 8px`},"aria-label":`Close browser`,children:`✕`}),(0,h.jsx)(`img`,{src:`/brand/claude.png`,alt:`Claude`,className:`chat-logo`}),(0,h.jsx)(`h1`,{className:`chat-tagline`,children:`Connect Claude`}),(0,h.jsx)(`p`,{className:`chat-intro`,children:n?`Sign in and authorize in the browser below.`:`Open your email or prepare your accounts, then sign in.`}),!n&&(0,h.jsx)(`div`,{style:{marginTop:`12px`},children:(0,h.jsx)(s,{variant:`primary`,onClick:T,disabled:i,children:i?(0,h.jsxs)(h.Fragment,{children:[(0,h.jsx)(`span`,{className:`spin`,style:{display:`inline-block`},children:`✱`}),` Connecting…`]}):`Sign in to Claude`})}),n&&_===`native`&&(0,h.jsxs)(`div`,{style:{marginTop:`14px`,maxWidth:`420px`,margin:`14px auto 0`,display:`flex`,flexDirection:`column`,gap:`8px`},children:[(0,h.jsx)(`label`,{style:{fontSize:`12px`,color:`#999`,lineHeight:1.4},children:`If the browser didn't finish sign-in, paste the code or full redirect URL from Claude's page:`}),(0,h.jsxs)(`div`,{style:{display:`flex`,gap:`8px`},children:[(0,h.jsx)(`input`,{type:`text`,value:y,onChange:e=>b(e.target.value),placeholder:`Paste code or redirect URL`,style:{flex:1,padding:`8px 10px`,fontSize:`13px`,border:`1px solid #ccc`,borderRadius:`6px`}}),(0,h.jsx)(s,{variant:`primary`,onClick:C,disabled:!y.trim(),children:`Submit`})]}),x&&(0,h.jsx)(`p`,{style:{fontSize:`12px`,color:`#999`,margin:0},children:x})]})]}),(0,h.jsx)(`div`,{style:{flex:1,display:`flex`,flexDirection:`column`,minHeight:0,gap:`10px`,padding:`0 0 16px`},children:(0,h.jsx)(`iframe`,{src:`/vnc-viewer.html`,style:{flex:1,width:`100%`,minHeight:0,border:`none`,background:`#111`,display:`block`},title:`Claude Sign-in`})}),c&&(0,h.jsx)(`p`,{className:`admin-pin-error`,style:{textAlign:`center`,padding:`0 20px 16px`},children:c})]}):(0,h.jsx)(`div`,{className:`connect-page`,children:(0,h.jsxs)(`div`,{className:`connect-content`,children:[(0,h.jsxs)(`div`,{className:`connect-logos`,children:[(0,h.jsx)(`div`,{className:`connect-logo-wrap`,children:(0,h.jsx)(`img`,{src:`/brand/claude.png`,alt:`Claude`,className:`connect-logo`})}),(0,h.jsx)(`svg`,{className:`connect-arrow`,viewBox:`0 0 48 24`,fill:`none`,xmlns:`http://www.w3.org/2000/svg`,children:(0,h.jsx)(`path`,{d:`M0 12h44m0 0l-8-8m8 8l-8 8`,stroke:`currentColor`,strokeWidth:`2`,strokeLinecap:`round`,strokeLinejoin:`round`})}),(0,h.jsxs)(`div`,{className:`connect-logo-wrap`,children:[(0,h.jsx)(`img`,{src:t,alt:a.productName,className:`connect-logo connect-logo--maxy`}),!a.logoContainsName&&(0,h.jsx)(`span`,{className:`connect-logo-label`,children:a.productName})]})]}),(0,h.jsxs)(`h1`,{className:`connect-title`,children:[`Connect Claude to power `,a.productName]}),(0,h.jsx)(`p`,{className:`connect-subtitle`,children:`Sign in with your Anthropic account to get started.`}),(0,h.jsx)(s,{variant:`primary`,onClick:T,disabled:i,children:i?(0,h.jsxs)(h.Fragment,{children:[(0,h.jsx)(`span`,{className:`spin`,style:{display:`inline-block`},children:`✱`}),` Connecting…`]}):`Sign in to Claude`}),(0,h.jsx)(`p`,{style:{marginTop:`6px`,fontSize:`11px`,color:`#999`,maxWidth:`300px`,textAlign:`center`,lineHeight:`1.4`},children:`First time? You may need to sign into your email and Anthropic account in the browser before connecting.`}),(0,h.jsx)(`button`,{onClick:w,disabled:m,style:{marginTop:`12px`,background:`none`,border:`none`,color:`var(--color-primary, #666)`,fontSize:`13px`,cursor:`pointer`,textDecoration:`underline`,textUnderlineOffset:`3px`},children:m?`Launching…`:`Open browser first`}),c&&(0,h.jsx)(`p`,{className:`admin-pin-error`,children:c})]})})}function b({auth:e}){return e.appState===`loading`?(0,h.jsx)(`div`,{className:`connect-page`}):e.appState===`set-pin`?(0,h.jsx)(_,{pin:e.pin,setPin:e.setPin,showPin:e.showPin,setShowPin:e.setShowPin,pinLoading:e.pinLoading,pinError:e.pinError,pinInputRef:e.pinInputRef,setPinFormRef:e.setPinFormRef,onSubmit:e.handleSetPin,operatorName:e.operatorName,setOperatorName:e.setOperatorName}):e.appState===`connect-claude`?(0,h.jsx)(y,{authPolling:e.authPolling,setAuthPolling:e.setAuthPolling,authLoading:e.authLoading,setAuthLoading:e.setAuthLoading,pinError:e.pinError,setPinError:e.setPinError,setAppState:e.setAppState}):e.appState===`enter-pin`?(0,h.jsx)(v,{pin:e.pin,setPin:e.setPin,showPin:e.showPin,setShowPin:e.setShowPin,pinLoading:e.pinLoading,pinError:e.pinError,pinInputRef:e.pinInputRef,onSubmit:e.handleLogin,remoteAuthEnabled:e.remoteAuthEnabled,onSignOutRemote:()=>{console.info(`[admin-ui] remote-auth sign-out → /__remote-auth/logout`),window.location.href=`/__remote-auth/logout`}}):null}export{m as n,b as t};
1
+ import{o as e}from"./chunk-CAM3fms7.js";import{A as t,L as n,M as r,N as i,O as a}from"./useSubAccountSwitcher-Bg0RH3Gk.js";import{i as o}from"./admin-types-hioowVct.js";import{b as s,x as c}from"./AdminShell-BihejKg_.js";import{t as l}from"./Checkbox-Ds004CBE.js";var u=`admin-landing-redirected`,d=`/graph`;function f(e){return e.variant===`operator`?!1:e.appState===`chat`&&!e.alreadyRedirected}var p=e(n(),1);function m(e=`admin`){let[t,n]=(0,p.useState)(`loading`),[r,a]=(0,p.useState)(``),[s,l]=(0,p.useState)(``),[m,h]=(0,p.useState)(``),[g,_]=(0,p.useState)(!1),[v,y]=(0,p.useState)(!1),[b,x]=(0,p.useState)(!1),[S,C]=(0,p.useState)(!1),[w,T]=(0,p.useState)(!1),[E,D]=(0,p.useState)(null),[O,k]=(0,p.useState)(null),[A,j]=(0,p.useState)(void 0),[M,N]=(0,p.useState)(null),[P,F]=(0,p.useState)(void 0),[I,L]=(0,p.useState)(null),[R,z]=(0,p.useState)(null),[B,V]=(0,p.useState)(void 0),H=(0,p.useRef)(void 0),[U,W]=(0,p.useState)(!1),[G,K]=(0,p.useState)(!0);(0,p.useEffect)(()=>{typeof window>`u`||fetch(`/api/remote-auth/status`).then(e=>e.ok?e.json():null).then(e=>{e?.configured&&W(!0)}).catch(()=>{})},[]);let q=(0,p.useRef)(null),J=(0,p.useRef)(null);(0,p.useEffect)(()=>{async function e(){let e=null;try{e=sessionStorage.getItem(`maxy-admin-session-key`)}catch{}if(!e)return!1;try{let t=await fetch(`/api/admin/session?session_key=${encodeURIComponent(e)}`);if(t.status===401){try{sessionStorage.removeItem(`maxy-admin-session-key`)}catch{}return!1}if(!t.ok)return!1;let r=await t.json();D(r.session_key),z(r.sessionId??null),j(r.businessName),N(r.role??null),F(r.userName===void 0?null:r.userName),L(r.avatar??null);let i=o(r.thinkingView);return H.current=i,V(i),n(`chat`),!0}catch(e){return console.error(`[admin] session restore failed:`,e),!1}}async function t(r=2){try{let i=await fetch(`/api/health`);if(!i.ok){if(r>0)return await new Promise(e=>setTimeout(e,1500)),t(r-1);console.error(`[admin] health check returned ${i.status} after retries`),n(`set-pin`);return}let a=await i.json();if(!a.pin_configured){n(`set-pin`);return}K(!!a.claude_authenticated);let o=!1;try{o=new URLSearchParams(window.location.search).get(`connect`)===`claude`}catch{}if(o){try{let e=new URL(window.location.href);e.searchParams.delete(`connect`),window.history.replaceState(null,``,e.pathname+e.search+e.hash)}catch{}if(!a.claude_authenticated){n(`connect-claude`);return}}if(await e())return;n(`enter-pin`)}catch(e){if(r>0)return await new Promise(e=>setTimeout(e,1500)),t(r-1);console.error(`[admin] health check failed:`,e),n(`set-pin`)}}t()},[]),(0,p.useEffect)(()=>{t===`chat`&&fetch(`/api/admin/claude-info`).then(e=>{if(e.ok)return e.json()}).then(e=>{e&&k(e)}).catch(()=>{})},[t]),(0,p.useEffect)(()=>{if(typeof window>`u`)return;let n=!1;try{n=sessionStorage.getItem(u)===`1`}catch{}if(f({appState:t,alreadyRedirected:n,variant:e})){try{sessionStorage.setItem(u,`1`)}catch{}console.info(`[admin-ui] landing-redirect target=${d}`),window.location.replace(d)}},[t,e]);let Y=(0,p.useRef)(null);(0,p.useEffect)(()=>{if(t!==`chat`)return;let e=setInterval(async()=>{try{let e=await fetch(`/api/health`);if(e.ok){let t=await e.json();K(t.auth_status!==`dead`&&t.auth_status!==`missing`)}}catch{}if(E)try{let e=await fetch(`/api/admin/session?session_key=${encodeURIComponent(E)}`);if(e.status!==401)return;let t=(await e.clone().json().catch(()=>null))?.code??`unknown-401`;if(t===`remote-auth-required`){i(`heartbeat`,`/api/admin/session`);return}console.warn(`[admin-auth] outcome=heartbeat-detected-expiry code=${t}`),Y.current?.()}catch{}},300*1e3);return()=>clearInterval(e)},[t,E]),(0,p.useEffect)(()=>{t===`connect-claude`&&fetch(`/api/health`).then(e=>e.ok?e.json():null).then(e=>{e?.claude_authenticated&&(K(!0),n(`enter-pin`))}).catch(()=>{})},[t]);async function X(e,t){y(!0);try{let r=await fetch(`/api/admin/session`,{method:`POST`,headers:{"Content-Type":`application/json`},body:JSON.stringify({pin:e,...t?{accountId:t}:{}})});if(!r.ok){let e=await r.json().catch(()=>({}));if(r.status===401&&e?.code===`remote-auth-required`){i(`enter-pin`,`/api/admin/session`);return}h(e.error||`Invalid PIN`);return}let s=await r.json();D(s.session_key),z(s.sessionId??null),j(s.businessName),N(s.role??null),F(s.userName===void 0?null:s.userName),L(s.avatar??null);let c=o(s.thinkingView);H.current=c,V(c);try{sessionStorage.setItem(`maxy-admin-session-key`,s.session_key)}catch{}a(``),n(`chat`)}catch(e){console.error(`[admin] connection error:`,e),h(`Could not connect.`)}finally{y(!1)}}let Z=(0,p.useCallback)(async e=>{if(e.preventDefault(),v)return;h(``);let t=s.trim();if(!t){h(`Please enter your name.`);return}if(r.length<4){h(`PIN must be at least 4 characters.`);return}let o=r;y(!0);try{let e=await fetch(`/api/onboarding/set-pin`,{method:`POST`,headers:{"Content-Type":`application/json`},body:JSON.stringify({pin:o,name:t})});if(!e.ok){let t=await e.json().catch(()=>({}));if(e.status===401&&t?.code===`remote-auth-required`){i(`set-pin`,`/api/onboarding/set-pin`);return}if(e.status===409){console.log(`[admin] PIN already configured — re-checking health`);try{let e=await fetch(`/api/health`);if(e.ok){let r=await e.json();r.pin_configured&&r.claude_authenticated?n(`enter-pin`):r.pin_configured?n(`connect-claude`):h(t.error||`Failed to set PIN.`)}else n(`enter-pin`)}catch{n(`enter-pin`)}return}h(t.error||`Failed to set PIN.`);return}let r=await fetch(`/api/health`);if((r.ok?await r.json():null)?.claude_authenticated){await X(o);return}a(``),n(`connect-claude`)}catch(e){console.error(`[admin] connection error:`,e),h(`Could not connect.`)}finally{y(!1)}},[r,v,s]),Q=(0,p.useCallback)(async e=>{e.preventDefault(),h(``),await X(r)},[r]),ee=(0,p.useCallback)(async()=>{T(!0);try{if(!await c())return console.warn(`[admin-ui] claude-disconnect not verified — credentials may persist; staying put`),!1;K(!1),D(null),N(null),F(void 0),L(null);try{sessionStorage.removeItem(`maxy-admin-session-key`),sessionStorage.removeItem(u)}catch{}return n(`connect-claude`),!0}finally{T(!1)}},[]),$=(0,p.useCallback)(()=>{D(null),N(null),F(void 0),L(null);try{sessionStorage.removeItem(`maxy-admin-session-key`),sessionStorage.removeItem(u)}catch{}a(``),h(``),n(`enter-pin`)},[]);return(0,p.useEffect)(()=>{Y.current=$},[$]),{appState:t,setAppState:n,pin:r,setPin:a,operatorName:s,setOperatorName:l,pinError:m,setPinError:h,showPin:g,setShowPin:_,pinLoading:v,authPolling:b,setAuthPolling:x,authLoading:S,setAuthLoading:C,disconnecting:w,cacheKey:E,setCacheKey:D,claudeInfo:O,setClaudeInfo:k,businessName:A,role:M,userName:P,userAvatar:I,sessionId:R,setSessionId:z,expandAll:B,setExpandAll:V,expandAllDefaultRef:H,remoteAuthEnabled:U,claudeConnected:G,pinInputRef:q,setPinFormRef:J,handleSetPin:Z,handleLogin:Q,handleDisconnect:ee,handleLogout:$}}var h=r();function g({inputRef:e,value:t,onChange:n,onComplete:r,showPin:i,autoFocus:a}){let o=(0,p.useRef)([]);function s(e,r){r.key===`Backspace`?(r.preventDefault(),t[e]?n(t.slice(0,e)+t.slice(e+1)):e>0&&(n(t.slice(0,e-1)+t.slice(e)),o.current[e-1]?.focus())):r.key===`ArrowLeft`&&e>0?o.current[e-1]?.focus():r.key===`ArrowRight`&&e<5?o.current[e+1]?.focus():r.key===`Enter`&&(r.preventDefault(),r.currentTarget.form?.requestSubmit())}function c(e,i){let a=i.nativeEvent.data;if(!a||!/^\d$/.test(a))return;let s=t.split(``);for(s[e]=a;s.length<e;)s.push(``);let c=s.join(``).replace(/\D/g,``).slice(0,6);n(c),c.length===6?r?.(c):e<5&&o.current[e+1]?.focus()}function l(e){e.preventDefault();let t=e.clipboardData.getData(`text`).replace(/\D/g,``).slice(0,6);t&&(n(t),t.length===6?r?.(t):o.current[t.length]?.focus())}return(0,h.jsx)(`div`,{className:`pin-field`,children:Array.from({length:6}).map((n,r)=>(0,h.jsx)(`input`,{ref:t=>{o.current[r]=t,r===0&&e&&(e.current=t)},type:`text`,inputMode:`numeric`,className:`pin-box${t[r]?` pin-box-filled`:``}`,value:t[r]?i?t[r]:`•`:``,onKeyDown:e=>s(r,e),onInput:e=>c(r,e),onPaste:l,onFocus:e=>e.target.select(),autoFocus:a&&r===0,autoComplete:`off`,maxLength:1,"aria-label":`PIN digit ${r+1}`},r))})}function _(e){let{pin:n,setPin:r,showPin:i,setShowPin:o,pinLoading:c,pinError:u,pinInputRef:d,setPinFormRef:f,onSubmit:p,operatorName:m,setOperatorName:_}=e;return(0,h.jsx)(`div`,{className:`connect-page`,children:(0,h.jsxs)(`div`,{className:`connect-content`,children:[(0,h.jsx)(`img`,{src:t,alt:a.productName,className:`connect-logo connect-logo--maxy`}),!a.logoContainsName&&(0,h.jsxs)(`h1`,{className:`connect-title`,children:[`Welcome to `,a.productName]}),(0,h.jsxs)(`p`,{className:`connect-subtitle`,children:[`Tell `,a.productName,` who you are, then choose a PIN.`]}),(0,h.jsxs)(`form`,{ref:f,onSubmit:p,className:`connect-pin-form`,children:[(0,h.jsxs)(`div`,{className:`pin-input-row`,children:[(0,h.jsx)(`input`,{type:`text`,className:`connect-name-input`,placeholder:`Your full name`,value:m,onChange:e=>_(e.target.value),autoComplete:`name`,autoFocus:!0,required:!0,"aria-label":`Your full name`}),(0,h.jsx)(`div`,{style:{width:38,flexShrink:0},"aria-hidden":`true`})]}),(0,h.jsxs)(`div`,{className:`pin-input-row`,children:[(0,h.jsx)(g,{inputRef:d,value:n,onChange:r,onComplete:()=>{},showPin:i}),(0,h.jsx)(s,{variant:`send`,type:`submit`,disabled:!n||!m.trim(),loading:c,"aria-label":`Set PIN`,children:(0,h.jsxs)(`svg`,{viewBox:`0 0 24 24`,fill:`none`,stroke:`currentColor`,strokeWidth:`2`,strokeLinecap:`round`,strokeLinejoin:`round`,children:[(0,h.jsx)(`line`,{x1:`5`,y1:`12`,x2:`19`,y2:`12`}),(0,h.jsx)(`polyline`,{points:`12 5 19 12 12 19`})]})})]}),(0,h.jsx)(l,{checked:i,onChange:()=>o(e=>!e),label:`Show PIN`})]}),u&&(0,h.jsx)(`p`,{className:`admin-pin-error`,children:u})]})})}function v(e){let{pin:n,setPin:r,showPin:i,setShowPin:o,pinLoading:c,pinError:u,pinInputRef:d,onSubmit:f,remoteAuthEnabled:p,onSignOutRemote:m}=e;return(0,h.jsxs)(`div`,{className:`connect-page`,children:[p&&m&&(0,h.jsx)(`button`,{type:`button`,className:`connect-signout`,onClick:m,children:`Sign out`}),(0,h.jsxs)(`div`,{className:`connect-content`,children:[(0,h.jsx)(`img`,{src:t,alt:a.productName,className:`connect-logo connect-logo--maxy`}),!a.logoContainsName&&(0,h.jsx)(`h1`,{className:`connect-title`,children:a.productName}),(0,h.jsxs)(`form`,{onSubmit:f,className:`connect-pin-form`,children:[(0,h.jsxs)(`div`,{className:`pin-input-row`,children:[(0,h.jsx)(g,{inputRef:d,value:n,onChange:r,onComplete:()=>{},showPin:i,autoFocus:!0}),(0,h.jsx)(s,{variant:`send`,type:`submit`,disabled:!n,loading:c,children:(0,h.jsxs)(`svg`,{viewBox:`0 0 24 24`,fill:`none`,stroke:`currentColor`,strokeWidth:`2`,strokeLinecap:`round`,strokeLinejoin:`round`,children:[(0,h.jsx)(`line`,{x1:`5`,y1:`12`,x2:`19`,y2:`12`}),(0,h.jsx)(`polyline`,{points:`12 5 19 12 12 19`})]})})]}),(0,h.jsx)(`div`,{className:`pin-options`,children:(0,h.jsx)(l,{checked:i,onChange:()=>o(e=>!e),label:`Show PIN`})})]}),u&&(0,h.jsx)(`p`,{className:`admin-pin-error`,children:u})]})]})}function y(e){let{authPolling:n,setAuthPolling:r,authLoading:i,setAuthLoading:o,pinError:c,setPinError:l,setAppState:u}=e,[d,f]=(0,p.useState)(!1),[m,g]=(0,p.useState)(!1),[_,v]=(0,p.useState)(``),[y,b]=(0,p.useState)(``),[x,S]=(0,p.useState)(``);async function C(){S(``);try{let e=await(await fetch(`/api/onboarding/claude-auth`,{method:`POST`,headers:{"Content-Type":`application/json`},body:JSON.stringify({action:`paste-code`,code:y})})).json();e.accepted?(S(`Code submitted. Finishing sign-in…`),b(``)):S(e.error||`Could not submit code.`)}catch(e){console.error(`[admin] paste-code error:`,e),S(`Could not submit code.`)}}async function w(){g(!0),l(``);try{let e=await(await fetch(`/api/onboarding/claude-auth`,{method:`POST`,headers:{"Content-Type":`application/json`},body:JSON.stringify({action:`launch-browser`})})).json();e.launched?f(!0):e.error&&l(e.error)}catch(e){console.error(`[admin] browser launch error:`,e),l(`Could not launch browser.`)}g(!1)}async function T(){o(!0),l(``);try{let e=await(await fetch(`/api/onboarding/claude-auth`,{method:`POST`})).json();if(e.started){r(!0),f(!0),o(!1),v(e.transport||``);for(let e=0;e<120;e++)if(await new Promise(e=>setTimeout(e,2e3)),(await(await fetch(`/api/onboarding/claude-auth`,{method:`POST`,headers:{"Content-Type":`application/json`},body:JSON.stringify({action:`wait`})})).json()).authenticated){await fetch(`/api/onboarding/claude-auth`,{method:`POST`,headers:{"Content-Type":`application/json`},body:JSON.stringify({action:`stop`})}),u(`enter-pin`);return}l(`Timed out waiting for sign-in. Try again.`),r(!1)}else e.error&&l(e.error)}catch(e){console.error(`[admin] auth flow error:`,e),l(`Could not start auth flow.`)}o(!1)}async function E(){await fetch(`/api/onboarding/claude-auth`,{method:`POST`,headers:{"Content-Type":`application/json`},body:JSON.stringify({action:`stop`})}),r(!1),l(``)}return n||d?(0,h.jsxs)(`div`,{style:{display:`flex`,flexDirection:`column`,height:`100dvh`,overflow:`auto`},children:[(0,h.jsxs)(`header`,{className:`chat-header`,style:{paddingBottom:`12px`,flexShrink:0,position:`relative`,maxWidth:`680px`,width:`100%`,margin:`0 auto`,padding:`24px 20px 12px`},children:[n?(0,h.jsx)(`button`,{onClick:E,style:{position:`absolute`,top:`12px`,right:`12px`,background:`none`,border:`none`,color:`#999`,fontSize:`13px`,cursor:`pointer`,padding:`4px 8px`},"aria-label":`Cancel`,children:`✕`}):(0,h.jsx)(`button`,{onClick:()=>f(!1),style:{position:`absolute`,top:`12px`,right:`12px`,background:`none`,border:`none`,color:`#999`,fontSize:`13px`,cursor:`pointer`,padding:`4px 8px`},"aria-label":`Close browser`,children:`✕`}),(0,h.jsx)(`img`,{src:`/brand/claude.png`,alt:`Claude`,className:`chat-logo`}),(0,h.jsx)(`h1`,{className:`chat-tagline`,children:`Connect Claude`}),(0,h.jsx)(`p`,{className:`chat-intro`,children:n?`Sign in and authorize in the browser below.`:`Open your email or prepare your accounts, then sign in.`}),!n&&(0,h.jsx)(`div`,{style:{marginTop:`12px`},children:(0,h.jsx)(s,{variant:`primary`,onClick:T,disabled:i,children:i?(0,h.jsxs)(h.Fragment,{children:[(0,h.jsx)(`span`,{className:`spin`,style:{display:`inline-block`},children:`✱`}),` Connecting…`]}):`Sign in to Claude`})}),n&&_===`native`&&(0,h.jsxs)(`div`,{style:{marginTop:`14px`,maxWidth:`420px`,margin:`14px auto 0`,display:`flex`,flexDirection:`column`,gap:`8px`},children:[(0,h.jsx)(`label`,{style:{fontSize:`12px`,color:`#999`,lineHeight:1.4},children:`If the browser didn't finish sign-in, paste the code or full redirect URL from Claude's page:`}),(0,h.jsxs)(`div`,{style:{display:`flex`,gap:`8px`},children:[(0,h.jsx)(`input`,{type:`text`,value:y,onChange:e=>b(e.target.value),placeholder:`Paste code or redirect URL`,style:{flex:1,padding:`8px 10px`,fontSize:`13px`,border:`1px solid #ccc`,borderRadius:`6px`}}),(0,h.jsx)(s,{variant:`primary`,onClick:C,disabled:!y.trim(),children:`Submit`})]}),x&&(0,h.jsx)(`p`,{style:{fontSize:`12px`,color:`#999`,margin:0},children:x})]})]}),(0,h.jsx)(`div`,{style:{flex:1,display:`flex`,flexDirection:`column`,minHeight:0,gap:`10px`,padding:`0 0 16px`},children:(0,h.jsx)(`iframe`,{src:`/vnc-viewer.html`,style:{flex:1,width:`100%`,minHeight:0,border:`none`,background:`#111`,display:`block`},title:`Claude Sign-in`})}),c&&(0,h.jsx)(`p`,{className:`admin-pin-error`,style:{textAlign:`center`,padding:`0 20px 16px`},children:c})]}):(0,h.jsx)(`div`,{className:`connect-page`,children:(0,h.jsxs)(`div`,{className:`connect-content`,children:[(0,h.jsxs)(`div`,{className:`connect-logos`,children:[(0,h.jsx)(`div`,{className:`connect-logo-wrap`,children:(0,h.jsx)(`img`,{src:`/brand/claude.png`,alt:`Claude`,className:`connect-logo`})}),(0,h.jsx)(`svg`,{className:`connect-arrow`,viewBox:`0 0 48 24`,fill:`none`,xmlns:`http://www.w3.org/2000/svg`,children:(0,h.jsx)(`path`,{d:`M0 12h44m0 0l-8-8m8 8l-8 8`,stroke:`currentColor`,strokeWidth:`2`,strokeLinecap:`round`,strokeLinejoin:`round`})}),(0,h.jsxs)(`div`,{className:`connect-logo-wrap`,children:[(0,h.jsx)(`img`,{src:t,alt:a.productName,className:`connect-logo connect-logo--maxy`}),!a.logoContainsName&&(0,h.jsx)(`span`,{className:`connect-logo-label`,children:a.productName})]})]}),(0,h.jsxs)(`h1`,{className:`connect-title`,children:[`Connect Claude to power `,a.productName]}),(0,h.jsx)(`p`,{className:`connect-subtitle`,children:`Sign in with your Anthropic account to get started.`}),(0,h.jsx)(s,{variant:`primary`,onClick:T,disabled:i,children:i?(0,h.jsxs)(h.Fragment,{children:[(0,h.jsx)(`span`,{className:`spin`,style:{display:`inline-block`},children:`✱`}),` Connecting…`]}):`Sign in to Claude`}),(0,h.jsx)(`p`,{style:{marginTop:`6px`,fontSize:`11px`,color:`#999`,maxWidth:`300px`,textAlign:`center`,lineHeight:`1.4`},children:`First time? You may need to sign into your email and Anthropic account in the browser before connecting.`}),(0,h.jsx)(`button`,{onClick:w,disabled:m,style:{marginTop:`12px`,background:`none`,border:`none`,color:`var(--color-primary, #666)`,fontSize:`13px`,cursor:`pointer`,textDecoration:`underline`,textUnderlineOffset:`3px`},children:m?`Launching…`:`Open browser first`}),c&&(0,h.jsx)(`p`,{className:`admin-pin-error`,children:c})]})})}function b({auth:e}){return e.appState===`loading`?(0,h.jsx)(`div`,{className:`connect-page`}):e.appState===`set-pin`?(0,h.jsx)(_,{pin:e.pin,setPin:e.setPin,showPin:e.showPin,setShowPin:e.setShowPin,pinLoading:e.pinLoading,pinError:e.pinError,pinInputRef:e.pinInputRef,setPinFormRef:e.setPinFormRef,onSubmit:e.handleSetPin,operatorName:e.operatorName,setOperatorName:e.setOperatorName}):e.appState===`connect-claude`?(0,h.jsx)(y,{authPolling:e.authPolling,setAuthPolling:e.setAuthPolling,authLoading:e.authLoading,setAuthLoading:e.setAuthLoading,pinError:e.pinError,setPinError:e.setPinError,setAppState:e.setAppState}):e.appState===`enter-pin`?(0,h.jsx)(v,{pin:e.pin,setPin:e.setPin,showPin:e.showPin,setShowPin:e.setShowPin,pinLoading:e.pinLoading,pinError:e.pinError,pinInputRef:e.pinInputRef,onSubmit:e.handleLogin,remoteAuthEnabled:e.remoteAuthEnabled,onSignOutRemote:()=>{console.info(`[admin-ui] remote-auth sign-out → /__remote-auth/logout`),window.location.href=`/__remote-auth/logout`}}):null}export{m as n,b as t};
@@ -0,0 +1 @@
1
+ import{o as e}from"./chunk-CAM3fms7.js";import{C as t,D as n,I as r,L as i,M as a,O as o,S as s,T as c,_ as l,b as u,c as d,d as f,h as p,j as m,l as h,m as g,o as ee,p as te,r as ne,s as _,t as re,u as ie,v as ae,w as oe,y as se}from"./useSubAccountSwitcher-Bg0RH3Gk.js";async function ce(){try{let e=await fetch(`/api/onboarding/claude-auth`,{method:`POST`,headers:{"Content-Type":`application/json`},body:JSON.stringify({action:`logout`})});return e.ok?(await e.json().catch(()=>({})))?.logged_out===!0:(console.error(`[admin-ui] claude-logout http-status=${e.status}`),!1)}catch(e){return console.error(`[admin-ui] claude-logout fetch failed: ${e instanceof Error?e.message:String(e)}`),!1}}var v=e(i(),1),y=a(),b={sm:14,md:16,lg:18},x={sm:30,md:38,lg:46};function S({variant:e=`primary`,size:t=`md`,icon:n,iconPosition:r=`leading`,loading:i=!1,fullWidth:a=!1,disabled:o=!1,type:s=`button`,onClick:c,"aria-label":l,style:u,className:d,children:f}){let p=[`btn`,`btn--${e}`,t===`md`?``:`btn--${t}`,a?`btn--full`:``,d].filter(Boolean).join(` `),m=b[t],h={...e===`send`?{width:x[t],height:x[t]}:{},...u},g=Object.keys(h).length>0;return(0,y.jsxs)(`button`,{type:s,className:p,disabled:i||o,onClick:c,"aria-label":l,style:g?h:void 0,children:[(0,y.jsxs)(`span`,{className:`btn__content`,style:{visibility:i?`hidden`:`visible`},children:[n&&r===`leading`&&(0,y.jsx)(n,{size:m}),f,n&&r===`trailing`&&(0,y.jsx)(n,{size:m})]}),i&&(0,y.jsx)(`span`,{className:`btn__spinner`,children:`✱`})]})}var le=n(`archive-restore`,[[`rect`,{width:`20`,height:`5`,x:`2`,y:`3`,rx:`1`,key:`1wp1u1`}],[`path`,{d:`M4 8v11a2 2 0 0 0 2 2h2`,key:`tvwodi`}],[`path`,{d:`M20 8v11a2 2 0 0 1-2 2h-2`,key:`1gkqxj`}],[`path`,{d:`m9 15 3-3 3 3`,key:`1pd0qc`}],[`path`,{d:`M12 12v9`,key:`192myk`}]]),ue=n(`archive`,[[`rect`,{width:`20`,height:`5`,x:`2`,y:`3`,rx:`1`,key:`1wp1u1`}],[`path`,{d:`M4 8v11a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V8`,key:`1s80jp`}],[`path`,{d:`M10 12h4`,key:`a56b0p`}]]),de=n(`bot`,[[`path`,{d:`M12 8V4H8`,key:`hb8ula`}],[`rect`,{width:`16`,height:`12`,x:`4`,y:`8`,rx:`2`,key:`enze0r`}],[`path`,{d:`M2 14h2`,key:`vft8re`}],[`path`,{d:`M20 14h2`,key:`4cs60a`}],[`path`,{d:`M15 13v2`,key:`1xurst`}],[`path`,{d:`M9 13v2`,key:`rq6x2g`}]]),C=n(`box`,[[`path`,{d:`M21 8a2 2 0 0 0-1-1.73l-7-4a2 2 0 0 0-2 0l-7 4A2 2 0 0 0 3 8v8a2 2 0 0 0 1 1.73l7 4a2 2 0 0 0 2 0l7-4A2 2 0 0 0 21 16Z`,key:`hh9hay`}],[`path`,{d:`m3.3 7 8.7 5 8.7-5`,key:`g66t2b`}],[`path`,{d:`M12 22V12`,key:`d0xqtd`}]]),w=n(`gauge`,[[`path`,{d:`m12 14 4-4`,key:`9kzdfg`}],[`path`,{d:`M3.34 19a10 10 0 1 1 17.32 0`,key:`19p75a`}]]),fe=n(`history`,[[`path`,{d:`M3 12a9 9 0 1 0 9-9 9.75 9.75 0 0 0-6.74 2.74L3 8`,key:`1357e3`}],[`path`,{d:`M3 3v5h5`,key:`1xhq8a`}],[`path`,{d:`M12 7v5l4 2`,key:`1fdv2h`}]]),T=n(`list-todo`,[[`path`,{d:`M13 5h8`,key:`a7qcls`}],[`path`,{d:`M13 12h8`,key:`h98zly`}],[`path`,{d:`M13 19h8`,key:`c3s6r1`}],[`path`,{d:`m3 17 2 2 4-4`,key:`1jhpwq`}],[`rect`,{x:`3`,y:`4`,width:`6`,height:`6`,rx:`1`,key:`cif1o7`}]]),pe=n(`message-square`,[[`path`,{d:`M22 17a2 2 0 0 1-2 2H6.828a2 2 0 0 0-1.414.586l-2.202 2.202A.71.71 0 0 1 2 21.286V5a2 2 0 0 1 2-2h16a2 2 0 0 1 2 2z`,key:`18887p`}]]),me=n(`plus`,[[`path`,{d:`M5 12h14`,key:`1ays0h`}],[`path`,{d:`M12 5v14`,key:`s699le`}]]),he=n(`sliders-horizontal`,[[`path`,{d:`M10 5H3`,key:`1qgfaw`}],[`path`,{d:`M12 19H3`,key:`yhmn1j`}],[`path`,{d:`M14 3v4`,key:`1sua03`}],[`path`,{d:`M16 17v4`,key:`1q0r14`}],[`path`,{d:`M21 12h-9`,key:`1o4lsq`}],[`path`,{d:`M21 19h-5`,key:`1rlt1p`}],[`path`,{d:`M21 5h-7`,key:`1oszz2`}],[`path`,{d:`M8 10v4`,key:`tgpxqk`}],[`path`,{d:`M8 12H3`,key:`a7s4jb`}]]),E=n(`square`,[[`rect`,{width:`18`,height:`18`,x:`3`,y:`3`,rx:`2`,key:`afitv7`}]]),ge=n(`users`,[[`path`,{d:`M16 21v-2a4 4 0 0 0-4-4H6a4 4 0 0 0-4 4v2`,key:`1yyitq`}],[`path`,{d:`M16 3.128a4 4 0 0 1 0 7.744`,key:`16gr8j`}],[`path`,{d:`M22 21v-2a4 4 0 0 0-3-3.87`,key:`kshegd`}],[`circle`,{cx:`9`,cy:`7`,r:`4`,key:`nufk8`}]]),D=`maxy-shell-side-px`;function O(){if(typeof window>`u`)return 0;let e=document.querySelector(`.platform > .artefact`)?.getBoundingClientRect();return e&&e.width>0?Math.round(e.width):0}function k(e){if(typeof window>`u`)return e;let t=window.innerWidth,n=Math.max(248,t-480-O());return Math.min(Math.max(e,248),n)}function _e(){if(typeof window>`u`)return 264;try{let e=window.localStorage.getItem(D);if(!e)return 264;let t=parseInt(e,10);if(!Number.isFinite(t))return console.warn(`[admin-ui] sidebar-width-parse-failed stored=${JSON.stringify(e)} fallback=264`),264;if(t>=248)return k(t)}catch{}return 264}function ve({targetSelector:e=`.platform`}){let t=(0,v.useRef)(null),[n,r]=(0,v.useState)(()=>_e()),i=(0,v.useRef)(n);(0,v.useLayoutEffect)(()=>{let t=document.querySelector(e);!t||!(t instanceof HTMLElement)||(t.style.setProperty(`--side-px`,`${n}px`),i.current=n)},[n,e]);let a=(0,v.useCallback)(()=>{r(e=>{let t=k(e);return t===e?e:t})},[]);(0,v.useEffect)(()=>{a(),window.addEventListener(`resize`,a);let t=document.querySelector(e),n=null;return t instanceof HTMLElement&&(n=new MutationObserver(a),n.observe(t,{attributes:!0,attributeFilter:[`data-artefact`,`class`]})),()=>{window.removeEventListener(`resize`,a),n?.disconnect()}},[a,e]);let o=e=>{e.preventDefault();let n=t.current;if(!n)return;n.setPointerCapture(e.pointerId),n.classList.add(`dragging`);let a=!1,o=e=>{a=!0,r(k(Math.round(e.clientX)))},s=()=>{if(n.releasePointerCapture(e.pointerId),n.classList.remove(`dragging`),window.removeEventListener(`pointermove`,o),window.removeEventListener(`pointerup`,s),!a)return;let t=i.current;try{window.localStorage.setItem(D,String(t))}catch{}console.info(`[admin-ui] sidebar-resize px=${t}`)};window.addEventListener(`pointermove`,o),window.addEventListener(`pointerup`,s)},s=()=>{let e=k(264);r(e);try{window.localStorage.removeItem(D)}catch{}console.info(`[admin-ui] sidebar-resize px=${e}`)};return(0,y.jsx)(`div`,{ref:t,className:`side-resize-handle`,role:`separator`,"aria-orientation":`vertical`,"aria-label":`Resize sidebar`,onPointerDown:o,onDoubleClick:s})}var A=r();function ye({anchorRef:e,onClose:t,className:n,role:r,ariaLabel:i,children:a}){let o=(0,v.useRef)(null),[s,c]=(0,v.useState)({position:`fixed`,visibility:`hidden`}),l=(0,v.useCallback)(()=>{let t=e.current,n=o.current;if(!t||!n)return;let r=t.getBoundingClientRect(),i=n.getBoundingClientRect(),a=r.right-i.width;a<4&&(a=4);let s=window.innerHeight-r.bottom<i.height+8&&r.top>i.height+8?r.top-i.height:r.bottom;c({position:`fixed`,left:a,top:s,visibility:`visible`})},[e]);return(0,v.useLayoutEffect)(()=>{if(l(),typeof ResizeObserver>`u`)return;let e=new ResizeObserver(()=>l());return o.current&&e.observe(o.current),()=>e.disconnect()},[l]),(0,v.useEffect)(()=>{let n=e=>{e.key===`Escape`&&t()},r=n=>{let r=n.target;e.current?.contains(r)||o.current?.contains(r)||t()},i=n=>{let r=e.current;r&&n.target instanceof Node&&n.target.contains(r)&&t()},a=()=>t();return document.addEventListener(`keydown`,n),document.addEventListener(`pointerdown`,r),window.addEventListener(`scroll`,i,!0),window.addEventListener(`resize`,a),()=>{document.removeEventListener(`keydown`,n),document.removeEventListener(`pointerdown`,r),window.removeEventListener(`scroll`,i,!0),window.removeEventListener(`resize`,a)}},[e,t]),(0,A.createPortal)((0,y.jsx)(`div`,{ref:o,className:n,role:r,"aria-label":i,style:s,children:a}),document.body)}function be({actions:e,disabled:t}){let[n,r]=(0,v.useState)(!1),[i,a]=(0,v.useState)(null),o=(0,v.useRef)(null),s=(0,v.useCallback)(()=>{r(!1),a(null)},[]);return(0,y.jsxs)(`div`,{className:`conv-actions`,children:[(0,y.jsx)(`button`,{ref:o,type:`button`,className:`conv-action conv-actions-overflow`,onClick:()=>r(e=>!e),disabled:t,"aria-haspopup":`menu`,"aria-expanded":n,"aria-label":`Session actions`,title:`Session actions`,children:(0,y.jsx)(se,{size:12})}),n&&(0,y.jsx)(ye,{anchorRef:o,onClose:s,className:`conv-actions-menu`,role:`menu`,children:e.map(e=>e.panel?(0,y.jsxs)(`div`,{className:`conv-actions-menu-disclosure`,children:[(0,y.jsxs)(`button`,{type:`button`,role:`menuitem`,"aria-haspopup":`dialog`,"aria-expanded":i===e.key,disabled:t,onClick:()=>a(t=>t===e.key?null:e.key),children:[e.icon,(0,y.jsx)(`span`,{children:e.menuLabel})]}),i===e.key&&(0,y.jsx)(`div`,{className:`conv-actions-menu-panel`,children:e.panel()})]},e.key):(0,y.jsxs)(`button`,{type:`button`,role:`menuitem`,className:e.danger?`conv-action-danger`:void 0,"aria-busy":e.busy,disabled:t,onClick:t=>{e.onClick?.(t),s()},children:[e.icon,(0,y.jsx)(`span`,{children:e.menuLabel})]},e.key))})]})}var j=`claude-opus-4-8[1m]`,M=`claude-sonnet-5`,N=`claude-haiku-4-5`,P={[j]:`Opus 4.8 (1M context)`,[M]:`Sonnet 5`,[N]:`Haiku 4.5`};function F(e){return P[e]??e}var I=[j,M,N];function L(e){return e.replace(/\[1m\]$/,``)}function xe(e){return I.find(t=>L(t)===L(e))??e}var Se=[`default`,`acceptEdits`,`plan`,`auto`,`bypassPermissions`],R=[`low`,`medium`,`high`,`xhigh`];[...Se],[...R],[...R];var Ce=[j,M,N],we={default:`Ask permissions`,acceptEdits:`Accept edits`,plan:`Plan mode`,auto:`Auto mode`,bypassPermissions:`Bypass permissions`},Te=Se.map(e=>({value:e,label:we[e]??e})),Ee={low:`Low`,medium:`Medium`,high:`High`,xhigh:`Highest`},De=R.map(e=>({value:e,label:Ee[e]??e}));function z(e){if(e){let t=Ce.find(t=>L(t)===L(e));if(t)return t}return j}function Oe({row:e,adminFetch:t,onError:n}){let[r,i]=(0,v.useState)(()=>z(e.model)),[a,o]=(0,v.useState)(``),[s,c]=(0,v.useState)(``),[l,d]=(0,v.useState)(!1),f=(0,v.useRef)(!1);(0,v.useEffect)(()=>{i(z(e.model))},[e.model]);let p=async()=>{if(!f.current){f.current=!0,d(!0);try{let i=await t(`/api/admin/session-reseat`,{method:`POST`,headers:{"content-type":`application/json`},body:JSON.stringify({fromSessionId:e.sessionId,model:r,...a?{permissionMode:a}:{},...s?{effort:s}:{}})});if(!i.ok){n(`Could not reset ${e.title} (status ${i.status})`),console.error(`[admin-ui] dashboard-reseat-failed sessionId=${e.sessionId} status=${i.status}`),f.current=!1,d(!1);return}let o=await i.json().catch(()=>({}));o.target?window.location.assign(o.target):(n(`Reset of ${e.title} returned no target`),f.current=!1,d(!1))}catch(t){n(`Could not reset ${e.title} (network error)`),console.error(`[admin-ui] dashboard-reseat-failed sessionId=${e.sessionId} error=${t instanceof Error?t.message:String(t)}`),f.current=!1,d(!1)}}};return(0,y.jsxs)(y.Fragment,{children:[(0,y.jsxs)(`label`,{className:`reseat-field`,children:[(0,y.jsx)(`span`,{children:`Model`}),(0,y.jsx)(`select`,{"data-kind":`model`,value:r,disabled:l,onChange:e=>i(e.target.value),children:Ce.map(e=>(0,y.jsx)(`option`,{value:e,children:F(e)},e))})]}),(0,y.jsxs)(`label`,{className:`reseat-field`,children:[(0,y.jsx)(`span`,{children:`Mode`}),(0,y.jsxs)(`select`,{"data-kind":`mode`,value:a,disabled:l,onChange:e=>o(e.target.value),children:[(0,y.jsx)(`option`,{value:``,children:`Keep current`}),Te.map(e=>(0,y.jsx)(`option`,{value:e.value,children:e.label},e.value))]})]}),(0,y.jsxs)(`label`,{className:`reseat-field`,children:[(0,y.jsx)(`span`,{children:`Effort`}),(0,y.jsxs)(`select`,{"data-kind":`effort`,value:s,disabled:l,onChange:e=>c(e.target.value),children:[(0,y.jsx)(`option`,{value:``,children:`Keep current`}),De.map(e=>(0,y.jsx)(`option`,{value:e.value,children:e.label},e.value))]})]}),(0,y.jsx)(`button`,{type:`button`,className:`reseat-apply`,disabled:l,"aria-busy":l,onClick:()=>void p(),children:l?(0,y.jsxs)(y.Fragment,{children:[(0,y.jsx)(u,{size:12,className:`spin`,"aria-hidden":`true`}),`Resetting…`]}):`Reset`})]})}function B(e){if(e<60)return`${e}s`;let t=Math.floor(e/60),n=e%60;return n>0?`${t}m ${n}s`:`${t}m`}function ke(e){return e>=1e3?`${(e/1e3).toFixed(1)}k`:String(e)}async function V(e){if(navigator.clipboard)try{return await navigator.clipboard.writeText(e),!0}catch{}try{let t=document.createElement(`textarea`);t.value=e,t.style.position=`fixed`,t.style.opacity=`0`,document.body.appendChild(t),t.select();let n=document.execCommand(`copy`);return document.body.removeChild(t),n}catch{return!1}}function Ae({target:e,onConfirm:t,onCancel:n}){return e?(0,y.jsx)(`div`,{className:`claude-info-overlay`,onClick:n,children:(0,y.jsxs)(`div`,{className:`claude-info-modal`,onClick:e=>e.stopPropagation(),role:`alertdialog`,"aria-label":`Confirm delete session`,children:[(0,y.jsxs)(`div`,{className:`claude-info-header`,children:[(0,y.jsx)(`span`,{children:`Delete this conversation?`}),(0,y.jsx)(`button`,{className:`claude-info-close`,onClick:n,"aria-label":`Close`,children:`✕`})]}),(0,y.jsxs)(`div`,{className:`claude-info-section`,style:{padding:`12px 14px`,fontSize:`11px`,color:`var(--text-secondary)`},children:[`This permanently removes the transcript. It is not moved to Archive and cannot be recovered.`,e.live&&(0,y.jsx)(`div`,{style:{marginTop:`8px`},children:`This session is running; deleting stops it first.`})]}),(0,y.jsxs)(`div`,{className:`claude-info-section`,style:{display:`flex`,gap:`8px`,padding:`10px 14px`},children:[(0,y.jsx)(S,{variant:`danger`,size:`sm`,style:{flex:1},onClick:t,children:`Delete`}),(0,y.jsx)(S,{variant:`secondary`,size:`sm`,style:{flex:1},onClick:n,children:`Cancel`})]})]})}):null}var je=`auth-refresh-failed`;function Me({error:e,onClose:t}){if(!e)return null;let n=e.reason===je,r=n?`Claude sign-in expired`:`Session didn’t open`,i=n?`Your claude.ai login has expired. Re-authenticate to resume sessions.`:`The session did not bind within 60 seconds, so there is no live conversation to open.`;return(0,y.jsx)(`div`,{className:`claude-info-overlay`,onClick:t,children:(0,y.jsxs)(`div`,{className:`claude-info-modal`,onClick:e=>e.stopPropagation(),role:`alertdialog`,"aria-label":`Session could not be opened`,children:[(0,y.jsxs)(`div`,{className:`claude-info-header`,children:[(0,y.jsx)(`span`,{children:r}),(0,y.jsx)(`button`,{className:`claude-info-close`,onClick:t,"aria-label":`Close`,children:`✕`})]}),(0,y.jsxs)(`div`,{className:`claude-info-section`,style:{padding:`12px 14px`,fontSize:`11px`,color:`var(--text-secondary)`},children:[i,(0,y.jsxs)(`div`,{className:`claude-info-row`,style:{marginTop:`8px`},children:[(0,y.jsx)(`span`,{className:`claude-info-label`,children:`Reason`}),(0,y.jsx)(`span`,{className:`claude-info-value`,children:e.reason})]}),e.sessionId&&(0,y.jsxs)(`div`,{className:`claude-info-row`,children:[(0,y.jsx)(`span`,{className:`claude-info-label`,children:`Session`}),(0,y.jsxs)(`span`,{className:`claude-info-value`,children:[e.sessionId.slice(0,8),`…`]})]})]})]})})}function Ne(e){let{show:t,onClose:n,claudeInfo:r,messages:i,sessionElapsed:a,sessionId:o,cacheKey:s}=e,[c,l]=(0,v.useState)(null);if(!t)return null;let u=i.flatMap(e=>e.events?.filter(e=>e.type===`usage`)??[]),d=u.at(-1),f=d?.peak_request_pct==null?d?.context_window?Math.round((d.input_tokens+d.cache_creation_tokens+d.cache_read_tokens)/d.context_window*100):0:Math.round(d.peak_request_pct*100),p=u.reduce((e,t)=>e+t.input_tokens+t.cache_creation_tokens+t.cache_read_tokens+t.output_tokens,0),m=i.flatMap(e=>e.events?.filter(e=>e.type===`rate_limit`)??[]).at(-1),h=u.reduce((e,t)=>e+(t.total_cost_usd??0),0),g=r?.account?.subscriptionType,ee=e=>{let t=e*1e3-Date.now();if(t<=0)return`now`;let n=Math.floor(t/36e5),r=Math.floor(t%36e5/6e4);return n>0?`${n}h ${r}m`:`${r}m`};return(0,y.jsx)(`div`,{className:`claude-info-overlay`,onClick:n,children:(0,y.jsxs)(`div`,{className:`claude-info-modal`,onClick:e=>e.stopPropagation(),children:[(0,y.jsxs)(`div`,{className:`claude-info-header`,children:[(0,y.jsx)(`img`,{src:`/brand/claude.png`,alt:`Claude`,className:`claude-info-icon`}),(0,y.jsx)(`span`,{children:`Claude Code`}),(0,y.jsx)(`button`,{className:`claude-info-close`,onClick:n,"aria-label":`Close`,children:`✕`})]}),(0,y.jsxs)(`div`,{className:`claude-info-section`,children:[(0,y.jsxs)(`div`,{className:`claude-info-row`,children:[(0,y.jsx)(`span`,{className:`claude-info-label`,children:`Version`}),(0,y.jsx)(`span`,{className:`claude-info-value`,children:r?r.version:`…`})]}),(0,y.jsxs)(`div`,{className:`claude-info-row`,children:[(0,y.jsx)(`span`,{className:`claude-info-label`,children:`Email`}),(0,y.jsx)(`span`,{className:`claude-info-value`,children:r?.account?.email??`…`})]})]}),(g||m||h>0)&&(0,y.jsxs)(`div`,{className:`claude-info-section`,children:[g&&(0,y.jsxs)(`div`,{className:`claude-info-row`,children:[(0,y.jsx)(`span`,{className:`claude-info-label`,children:`Plan`}),(0,y.jsx)(`span`,{className:`claude-info-value`,style:{textTransform:`capitalize`},children:g})]}),m&&(0,y.jsxs)(y.Fragment,{children:[(0,y.jsxs)(`div`,{className:`claude-info-row`,children:[(0,y.jsx)(`span`,{className:`claude-info-label`,children:`Usage`}),(0,y.jsxs)(`span`,{className:`claude-info-value`,children:[Math.round(m.utilization*100),`%`]})]}),(0,y.jsxs)(`div`,{className:`claude-info-row`,children:[(0,y.jsx)(`span`,{className:`claude-info-label`,children:`Resets in`}),(0,y.jsx)(`span`,{className:`claude-info-value`,children:ee(m.resetsAt)})]}),m.isUsingOverage&&(0,y.jsxs)(`div`,{className:`claude-info-row`,children:[(0,y.jsx)(`span`,{className:`claude-info-label`,children:`Overage`}),(0,y.jsx)(`span`,{className:`claude-info-value`,children:`Active`})]})]}),h>0&&(0,y.jsxs)(`div`,{className:`claude-info-row`,children:[(0,y.jsx)(`span`,{className:`claude-info-label`,children:`Session cost`}),(0,y.jsxs)(`span`,{className:`claude-info-value`,children:[`$`,h<.01?h.toFixed(4):h.toFixed(2)]})]})]}),(0,y.jsxs)(`div`,{className:`claude-info-section`,children:[(0,y.jsxs)(`div`,{className:`claude-info-row`,children:[(0,y.jsx)(`span`,{className:`claude-info-label`,children:`Model`}),(0,y.jsx)(`span`,{className:`claude-info-value`,children:r?.model??`…`})]}),(0,y.jsxs)(`div`,{className:`claude-info-row`,children:[(0,y.jsx)(`span`,{className:`claude-info-label`,children:`Context used`}),(0,y.jsx)(`span`,{className:`claude-info-value`,children:f>0?`${f}%`:`—`})]}),(0,y.jsxs)(`div`,{className:`claude-info-row`,children:[(0,y.jsx)(`span`,{className:`claude-info-label`,children:`Tokens`}),(0,y.jsx)(`span`,{className:`claude-info-value`,children:p>0?ke(p):`—`})]}),(0,y.jsxs)(`div`,{className:`claude-info-row`,children:[(0,y.jsx)(`span`,{className:`claude-info-label`,children:`Session`}),(0,y.jsx)(`span`,{className:`claude-info-value`,children:B(a)})]}),(o||s)&&(()=>{let e=o??s??``;return(0,y.jsxs)(`div`,{className:`claude-info-row`,children:[(0,y.jsx)(`span`,{className:`claude-info-label`,children:`Session`}),(0,y.jsx)(`button`,{type:`button`,className:`claude-info-value claude-info-id-copy`,title:`${e} (${o?`flushed`:`pre-flush`}) — click to copy`,onClick:async()=>{l(await V(e)?`copied`:`failed`),setTimeout(()=>l(null),1200)},children:c===`copied`?`copied ✓`:c===`failed`?`copy failed ✕`:`${e.slice(0,8)}…`})]})})()]})]})})}function Pe({open:e,onConnect:t,onClose:n}){return e?(0,y.jsx)(`div`,{className:`claude-info-overlay`,onClick:n,children:(0,y.jsxs)(`div`,{className:`claude-info-modal`,onClick:e=>e.stopPropagation(),role:`alertdialog`,"aria-label":`Claude is not connected`,children:[(0,y.jsxs)(`div`,{className:`claude-info-header`,children:[(0,y.jsx)(`span`,{children:`Claude isn’t connected`}),(0,y.jsx)(`button`,{className:`claude-info-close`,onClick:n,"aria-label":`Close`,children:`✕`})]}),(0,y.jsxs)(`div`,{className:`claude-info-section`,style:{padding:`12px 14px`,fontSize:`11px`,color:`var(--text-secondary)`,display:`flex`,flexDirection:`column`,gap:`10px`},children:[(0,y.jsx)(`span`,{children:`This needs Claude, which is currently disconnected. Connect to continue — the rest of the dashboard stays available either way.`}),(0,y.jsxs)(`div`,{style:{display:`flex`,gap:`8px`,alignItems:`center`},children:[(0,y.jsx)(S,{variant:`primary`,size:`sm`,onClick:t,children:`Connect Claude`}),(0,y.jsx)(`button`,{type:`button`,className:`claude-info-close`,style:{fontSize:`11px`},onClick:n,children:`Not now`})]})]})]})}):null}function H(e){let t=Math.round(e/6e4),n=Math.floor(t/60),r=t%60;return`${n}h ${String(r).padStart(2,`0`)}m`}function Fe(e){return e.activeMs.thinking+e.activeMs.messaging+e.activeMs.toolUse}function U(e){return e.toLocaleString(`en-GB`)}function Ie(e){return`£${e.toFixed(2)}`}function W({label:e,d:t,bold:n}){let r=n?`th`:`td`;return(0,y.jsxs)(`tr`,{className:n?`usage-total-row`:void 0,children:[(0,y.jsx)(r,{className:`usage-day`,children:e}),(0,y.jsx)(r,{children:H(Fe(t))}),(0,y.jsx)(r,{children:U(t.tokens.output)}),(0,y.jsx)(r,{children:U(t.tokens.input)}),(0,y.jsx)(r,{children:U(t.tokens.cacheWrite)}),(0,y.jsx)(r,{children:U(t.tokens.cacheRead)}),(0,y.jsx)(r,{children:Ie(t.costGBP.opus)}),(0,y.jsx)(r,{children:Ie(t.costGBP.sonnet)})]})}function Le({show:e,onClose:t,sessionId:n,summary:r,loading:i,error:a}){return e?(0,y.jsx)(`div`,{className:`claude-info-overlay`,onClick:t,children:(0,y.jsxs)(`div`,{className:`claude-info-modal usage-modal`,onClick:e=>e.stopPropagation(),role:`dialog`,"aria-label":`Session usage and cost`,children:[(0,y.jsxs)(`div`,{className:`claude-info-header`,children:[(0,y.jsxs)(`span`,{children:[`Usage & cost`,n?` · ${n.slice(0,8)}`:``]}),(0,y.jsx)(`button`,{className:`claude-info-close`,onClick:t,"aria-label":`Close`,children:(0,y.jsx)(g,{size:14})})]}),(0,y.jsxs)(`div`,{className:`claude-info-section usage-body`,children:[i&&(0,y.jsx)(`div`,{className:`usage-note`,children:`Computing usage…`}),!i&&a&&(0,y.jsx)(`div`,{className:`usage-note usage-error`,children:a}),!i&&!a&&r&&r.days.length===0&&(0,y.jsx)(`div`,{className:`usage-note`,children:`No usage recorded for this session yet.`}),!i&&!a&&r&&r.days.length>0&&(0,y.jsxs)(y.Fragment,{children:[(0,y.jsx)(`div`,{className:`usage-table-scroll`,children:(0,y.jsxs)(`table`,{className:`usage-table`,children:[(0,y.jsx)(`thead`,{children:(0,y.jsxs)(`tr`,{children:[(0,y.jsx)(`th`,{className:`usage-day`,children:`Day`}),(0,y.jsx)(`th`,{children:`Active`}),(0,y.jsx)(`th`,{children:`Output tok`}),(0,y.jsx)(`th`,{children:`Input tok`}),(0,y.jsx)(`th`,{children:`Cache write`}),(0,y.jsx)(`th`,{children:`Cache read`}),(0,y.jsx)(`th`,{children:`Opus 4.8 (£)`}),(0,y.jsx)(`th`,{children:`Sonnet 4.6 (£)`})]})}),(0,y.jsxs)(`tbody`,{children:[r.days.map(e=>(0,y.jsx)(W,{label:e.date,d:e},e.date)),(0,y.jsx)(W,{label:`TOTAL (${r.days.length} d)`,d:r.totals,bold:!0})]})]})}),(0,y.jsxs)(`div`,{className:`usage-note usage-caveats`,children:[`Prices dated `,r.pricing.opusPriceDate,` · £/$ `,r.pricing.usdPerGbp,` · Sonnet tokenizer factor `,r.pricing.tokenizerFactor,`. Idle human-wait dominates the calendar span; cache-read tokens dominate cost; Sonnet is a tokenizer-adjusted estimate.`]})]})]})]})}):null}var Re=`https://claude.ai/code`,ze=200,Be=[500,1e3,1500,2e3,2500,3e3,3e3];function Ve(e,t,n){if(e&&n.target)return{kind:`navigate`,url:n.target,sameOrigin:!0};let r=n.slug??n.bridgeSessionId??null;if(e&&r)return{kind:`navigate`,url:`${Re}/${r}`,sameOrigin:!1};let i=n.reason||n.error||`status ${t}`;return{kind:`error`,sessionId:n.sessionId??null,reason:i}}function He(e){if(!e)return``;let t=Date.parse(e);return Number.isFinite(t)?new Date(t).toLocaleString(void 0,{dateStyle:`medium`,timeStyle:`short`}):``}function Ue(e){let{businessName:n,cacheKey:r,onConnectClaude:i,role:a,userName:u,userAvatar:f,onSelectProjects:g,onSelectPeople:re,onSelectTasks:se,onSelectAgents:ce,onCloseMobileDrawer:b,collapsed:x,selectedWhatsappId:S,onSelectWhatsappConversation:D,initialWhatsappSurface:O=!1,onSelectData:k,onCloseData:_e,initialDataSurface:ve=!1}=e,A=te(r),ye=(0,v.useCallback)(e=>({key:`reseat`,label:`Reset session ${e.title} (model, mode, effort)`,menuLabel:`Reset`,title:`Reset — move this session onto a chosen model, mode, and effort`,icon:(0,y.jsx)(he,{size:12}),panel:()=>(0,y.jsx)(Oe,{row:e,adminFetch:A,onError:e=>B({message:e,failed:!0})})}),[A]),j=o.productName,M=typeof u==`string`?u:u===null?`name unavailable`:n||j,N=(M.trim().charAt(0)||`?`).toUpperCase(),[P,F]=(0,v.useState)(ve?`data`:O?`whatsapp`:`sessions`),[I,L]=(0,v.useState)([]),[xe,Se]=(0,v.useState)(!1),[R,Ce]=(0,v.useState)(null),[we,Te]=(0,v.useState)(!1),[Ee,De]=(0,v.useState)(`file`),[z,B]=(0,v.useState)(null),[ke,V]=(0,v.useState)(null),[je,Ne]=(0,v.useState)(!1),[H,Fe]=(0,v.useState)([]),[U,Ie]=(0,v.useState)(!1),[W,Re]=(0,v.useState)(null),[Ue,We]=(0,v.useState)(!1),[G,Je]=(0,v.useState)(!1),[K,Ye]=(0,v.useState)(!1),[Xe,Ze]=(0,v.useState)(null),[q,Qe]=(0,v.useState)(new Set),[$e,et]=(0,v.useState)(null),[J,tt]=(0,v.useState)(new Set),[nt,rt]=(0,v.useState)(new Set),[it,at]=(0,v.useState)(new Set),[Y,ot]=(0,v.useState)(null),[st,X]=(0,v.useState)(``),[ct,lt]=(0,v.useState)(!1),[ut,dt]=(0,v.useState)(null),[ft,pt]=(0,v.useState)(null),[mt,ht]=(0,v.useState)(!1),[gt,_t]=(0,v.useState)(null),[Z,vt]=(0,v.useState)(!1),yt=(0,v.useRef)(0),[bt,xt]=(0,v.useState)([]),[St,Ct]=(0,v.useState)(!1),[wt,Tt]=(0,v.useState)(null),[Et,Dt]=(0,v.useState)(`whatsapp`),Ot=(0,v.useCallback)(e=>{if(b(),!r){console.error(`[admin-ui] artefact-download-blocked id=${e.id} reason=no-cache-key`),B({message:`Session not ready — try again`,failed:!0});return}if(!e.downloadPath){console.error(`[admin-ui] artefact-download-blocked id=${e.id} reason=not-downloadable`),B({message:`${e.name} can’t be downloaded`,failed:!0});return}console.info(`[admin-ui] artefact-download id=${e.id} root=${e.downloadRoot??`data`} path=${e.downloadPath}`),ne(r,e.downloadPath,e.downloadRoot??`data`),B({message:`Downloading ${e.name}`,failed:!1})},[r,b]);(0,v.useEffect)(()=>{if(!z)return;let e=setTimeout(()=>B(null),2500);return()=>clearTimeout(e)},[z]);let kt=(0,v.useCallback)(async()=>{if(r){Te(!0),Ce(null);try{let e=await A(`/api/admin/sidebar-artefacts`);if(!e.ok)throw Error(`status ${e.status}`);L((await e.json()).artefacts??[]),Se(!0)}catch(e){let t=e instanceof Error?e.message:String(e);Ce(`Failed to load artefacts: ${t}`),console.error(`[admin-ui] sidebar-artefacts fetch failed: ${t}`)}finally{Te(!1)}}},[r,A]),Q=(0,v.useCallback)(async()=>{if(!r)return null;let e=++yt.current;We(!0),Re(null);try{let t=await A(`/api/admin/sidebar-sessions`);if(!t.ok)throw Error(`status ${t.status}`);let n=await t.json(),r=n.sessions??[];return e===yt.current?(Fe(r),Ze(n.accountId??null),Ie(!0),r):(console.info(`[admin-ui] sidebar-sessions-stale-response-dropped token=${e}`),r)}catch(t){let n=t instanceof Error?t.message:String(t);return e===yt.current&&Re(`Failed to load sessions: ${n}`),console.error(`[admin-ui] sidebar-sessions fetch failed: ${n}`),null}finally{e===yt.current&&We(!1)}},[r,A]),At=(0,v.useCallback)(async()=>{if(r){Tt(null);try{let e=await A(`/api/whatsapp-reader/conversations`);if(!e.ok)throw Error(`status ${e.status}`);xt((await e.json()).conversations??[]),Ct(!0)}catch(e){let t=e instanceof Error?e.message:String(e);Tt(`Couldn't load conversations.`),console.error(`[admin-ui] channel-convos fetch failed: ${t}`)}}},[r,A]);(0,v.useEffect)(()=>{!r||U||Q()},[r,U,Q]),(0,v.useEffect)(()=>{if(!r)return;let e=null;return At(),e=setInterval(()=>{At()},Ge),()=>{e!==null&&clearInterval(e)}},[r,At]),(0,v.useEffect)(()=>{if(!r)return;let e=null;function t(){console.info(`[admin-ui] sidebar-refresh surface=sessions trigger=poll`),Q()}function n(){e===null&&(e=setInterval(t,Ke))}function i(){e!==null&&(clearInterval(e),e=null)}function a(){document.hidden?i():(t(),n())}return document.hidden||n(),document.addEventListener(`visibilitychange`,a),()=>{i(),document.removeEventListener(`visibilitychange`,a)}},[r,Q]);let jt=(0,v.useMemo)(()=>{let e=new Map;for(let t of _)e.set(t,[]);for(let t of bt)e.get(t.channel)?.push(t);for(let t of _)console.info(`[admin-ui] sidebar-nav surface=${t} count=${e.get(t).length}`);return e},[bt]),Mt={whatsapp:`WhatsApp`,telegram:`Telegram`,webchat:`Webchat`},Nt=()=>{D(null),F(`artefacts`),console.info(`[admin-ui] sidebar-nav surface=artefacts count=${xe?I.length:0} collapsed=${x}`),kt()},$=1.5,Pt=()=>{console.info(`[admin-ui] sidebar-refresh surface=artefacts`),kt()},Ft=()=>{D(null),F(`sessions`),console.info(`[admin-ui] sidebar-nav surface=sessions count=${U?H.length:0} collapsed=${x}`),U||Q()},It=()=>{console.info(`[admin-ui] sidebar-refresh surface=sessions trigger=manual`),Q()},Lt=()=>{F(`data`),console.info(`[admin-ui] sidebar-nav surface=data collapsed=${x}`),k(),b()},Rt=e=>{_e?.(),F(`whatsapp`),Dt(e),console.info(`[admin-ui] sidebar-nav surface=${e} count=${jt.get(e)?.length??0} collapsed=${x}`)},zt=(0,v.useCallback)(async e=>{if(J.has(e.sessionId))return;tt(t=>{let n=new Set(t);return n.add(e.sessionId),n});let t=window.open(``,`_blank`);try{let n=await A(`/api/admin/session-rc-spawn`,{method:`POST`,headers:{"Content-Type":`application/json`},body:JSON.stringify({sessionId:e.sessionId,name:e.title||e.sessionId,...e.accountId?{targetAccountId:e.accountId}:{}})}),r=await n.json().catch(()=>({})),i=Ve(n.ok,n.status,{...r,sessionId:r.sessionId??e.sessionId});console.info(`[admin-ui] sidebar-session-resume sessionId=${e.sessionId} status=${n.status} outcome=${i.kind} slug=${r.slug??r.bridgeSessionId??`none`}`),i.kind===`navigate`?(b(),t?t.location.href=i.url:window.open(i.url,`_blank`)):(t?.close(),console.error(`[admin-ui] sidebar-session-resume-failed sessionId=${e.sessionId} status=${n.status} reason=${i.reason}`),V(i))}catch(n){t?.close();let r=n instanceof Error?n.message:String(n);console.error(`[admin-ui] sidebar-session-resume-failed sessionId=${e.sessionId} error=${r}`),V({sessionId:e.sessionId,reason:r})}finally{tt(t=>{let n=new Set(t);return n.delete(e.sessionId),n})}},[A,b,J]),Bt=(0,v.useCallback)(async e=>{let t=e.slice(0,8);for(let n=1;n<=Be.length;n++){await new Promise(e=>setTimeout(e,Be[n-1]));let r=await Q();if(r&&r.some(t=>t.sessionId===e)){console.info(`[admin-ui] sidebar-new-session-converged sessionId=${t} via=retry attempts=${n}`);return}}console.error(`[admin-ui] sidebar-new-session-converge-timeout sessionId=${t}`)},[Q]),Vt=(0,v.useCallback)(async()=>{if(!Z){vt(!0);try{let e=await A(`/api/admin/session-rc-spawn`,{method:`POST`,headers:{"Content-Type":`application/json`},body:JSON.stringify({})}),t=await e.json().catch(()=>({})),n=Ve(e.ok,e.status,t);console.info(`[admin-ui] sidebar-new-session-spawned status=${e.status} outcome=${n.kind} slug=${t.slug??t.bridgeSessionId??`none`}`),n.kind===`navigate`?n.sameOrigin?window.location.assign(n.url):(window.open(n.url,`_blank`),t.sessionId?Bt(t.sessionId):console.error(`[admin-ui] sidebar-new-session-converge-skipped reason=no-session-id`)):e.status===503||n.reason===`claude-auth-dead`?(console.info(`[admin-ui] op=llm-action-blocked action=spawn reason=claude-disconnected`),Ne(!0)):(console.error(`[admin-ui] sidebar-new-session-failed status=${e.status} reason=${n.reason}`),V(n))}catch(e){let t=e instanceof Error?e.message:String(e);console.error(`[admin-ui] sidebar-new-session-failed error=${t}`),V({sessionId:null,reason:t})}finally{vt(!1)}}},[A,Z,Bt]),Ht=(0,v.useCallback)((e,t)=>{e.stopPropagation(),et(t)},[]),Ut=(0,v.useCallback)(async(e,t)=>{e.stopPropagation(),dt(t),pt(null),_t(null),ht(!0);try{let e=await A(`/api/admin/session-usage?sessionId=${encodeURIComponent(t.sessionId)}`),n=await e.json().catch(()=>({}));e.ok?pt(n):_t(n.error??`status ${e.status}`)}catch(e){_t(e instanceof Error?e.message:String(e))}finally{ht(!1)}},[A]),Wt=(0,v.useCallback)(async e=>{if(!q.has(e.sessionId)){Qe(t=>{let n=new Set(t);return n.add(e.sessionId),n});try{let t=await A(`/api/admin/session-delete`,{method:`POST`,headers:{"Content-Type":`application/json`},body:JSON.stringify({sessionId:e.sessionId})});if(!t.ok){let n=await t.json().catch(()=>({}));console.error(`[admin-ui] sidebar-session-delete-failed sessionId=${e.sessionId} status=${t.status} error=${n.error??`unknown`}`),B({message:`Delete failed: ${n.error??`status ${t.status}`}`,failed:!0});return}let n=await t.json();console.info(`[admin-ui] sidebar-session-delete sessionId=${e.sessionId} live=${e.live} confirmed=true pidKilled=${n.pidKilled??`?`} deleted=${n.deleted??`?`}`),Fe(t=>t.filter(t=>t.sessionId!==e.sessionId)),Q()}catch(t){let n=t instanceof Error?t.message:String(t);console.error(`[admin-ui] sidebar-session-delete-failed sessionId=${e.sessionId} error=${n}`),B({message:`Delete failed: ${n}`,failed:!0})}finally{Qe(t=>{let n=new Set(t);return n.delete(e.sessionId),n})}}},[A,q,Q]),Gt=(0,v.useCallback)(async(e,t)=>{if(e.stopPropagation(),!nt.has(t.sessionId)){rt(e=>{let n=new Set(e);return n.add(t.sessionId),n});try{let e=await A(`/api/admin/session-stop`,{method:`POST`,headers:{"Content-Type":`application/json`},body:JSON.stringify({sessionId:t.sessionId})});if(!e.ok){let n=await e.json().catch(()=>({}));console.error(`[admin-ui] sidebar-session-stop-failed sessionId=${t.sessionId} status=${e.status} error=${n.error??`unknown`}`),B({message:`Stop failed: ${n.error??`status ${e.status}`}`,failed:!0});return}console.info(`[admin-ui] sidebar-session-stop sessionId=${t.sessionId}`),Q()}catch(e){let n=e instanceof Error?e.message:String(e);console.error(`[admin-ui] sidebar-session-stop-failed sessionId=${t.sessionId} error=${n}`),B({message:`Stop failed: ${n}`,failed:!0})}finally{rt(e=>{let n=new Set(e);return n.delete(t.sessionId),n})}}},[A,nt,Q]),Kt=(0,v.useCallback)(async(e,t,n)=>{if(e.stopPropagation(),!it.has(t.sessionId)){at(e=>{let n=new Set(e);return n.add(t.sessionId),n});try{let e=await A(`/api/admin/session-archive`,{method:`POST`,headers:{"Content-Type":`application/json`},body:JSON.stringify({sessionId:t.sessionId,mode:n})});if(!e.ok){let r=await e.json().catch(()=>({})),i=r.detail??r.error??`status ${e.status}`;console.error(`[admin-ui] sidebar-session-archive-failed sessionId=${t.sessionId} mode=${n} status=${e.status} error=${r.error??`unknown`}`),B({message:`${n===`archive`?`Archive`:`Unarchive`} failed: ${i}`,failed:!0});return}console.info(`[admin-ui] sidebar-session-archive sessionId=${t.sessionId} mode=${n}`),Q()}catch(e){let r=e instanceof Error?e.message:String(e);console.error(`[admin-ui] sidebar-session-archive-failed sessionId=${t.sessionId} mode=${n} error=${r}`),B({message:`${n===`archive`?`Archive`:`Unarchive`} failed: ${r}`,failed:!0})}finally{at(e=>{let n=new Set(e);return n.delete(t.sessionId),n})}}},[A,it,Q]),qt=(0,v.useCallback)(async e=>{let t=st.trim();if(!t){B({message:`Title can’t be empty`,failed:!0});return}if(t.length>ze){B({message:`Title too long (max ${ze})`,failed:!0});return}lt(!0);try{let n=await A(`/api/admin/session-rename`,{method:`POST`,headers:{"Content-Type":`application/json`},body:JSON.stringify({sessionId:e.sessionId,title:t})});if(!n.ok){let t=await n.json().catch(()=>({})),r=t.reason??t.error??`status ${n.status}`;console.error(`[admin-ui] sidebar-session-rename sessionId=${e.sessionId.slice(0,8)} outcome=rejected reason=${r}`),B({message:`Rename failed: ${r}`,failed:!0});return}console.info(`[admin-ui] sidebar-session-rename sessionId=${e.sessionId.slice(0,8)} outcome=ok`),ot(null),X(``),Q()}catch(t){let n=t instanceof Error?t.message:String(t);console.error(`[admin-ui] sidebar-session-rename sessionId=${e.sessionId.slice(0,8)} outcome=rejected reason=${n}`),B({message:`Rename failed: ${n}`,failed:!0})}finally{lt(!1)}},[A,st,Q]);return(0,y.jsxs)(`aside`,{className:`side`,children:[(0,y.jsx)(`div`,{className:`side-new-session-row`,children:(0,y.jsxs)(`button`,{type:`button`,className:`side-new-session`,onClick:Vt,disabled:Z,"aria-busy":Z,children:[(0,y.jsx)(me,{size:14}),(0,y.jsx)(`span`,{children:Z?`Spawning…`:`New session`})]})}),(0,y.jsxs)(`nav`,{className:`side-nav`,children:[(0,y.jsxs)(`button`,{type:`button`,className:`nav-row`,onClick:()=>{console.info(`[admin-ui] sidebar-nav surface=people`),re(),b()},children:[(0,y.jsx)(ge,{size:20,strokeWidth:$}),(0,y.jsx)(`span`,{className:`label`,children:`People`}),(0,y.jsx)(`span`,{className:`kbd`})]}),(0,y.jsxs)(`button`,{type:`button`,className:`nav-row`,onClick:()=>{console.info(`[admin-ui] sidebar-nav surface=agents`),ce(),b()},children:[(0,y.jsx)(de,{size:20,strokeWidth:$}),(0,y.jsx)(`span`,{className:`label`,children:`Agents`}),(0,y.jsx)(`span`,{className:`kbd`})]}),(0,y.jsxs)(`button`,{type:`button`,className:`nav-row`,onClick:()=>{console.info(`[admin-ui] sidebar-nav surface=projects`),g(),b()},children:[(0,y.jsx)(C,{size:20,strokeWidth:$}),(0,y.jsx)(`span`,{className:`label`,children:m().term}),(0,y.jsx)(`span`,{className:`kbd`})]}),(0,y.jsxs)(`button`,{type:`button`,className:`nav-row`,onClick:()=>{console.info(`[admin-ui] sidebar-nav surface=tasks`),se(),b()},children:[(0,y.jsx)(T,{size:20,strokeWidth:$}),(0,y.jsx)(`span`,{className:`label`,children:`Tasks`}),(0,y.jsx)(`span`,{className:`kbd`})]}),(0,y.jsxs)(`button`,{type:`button`,className:`nav-row${P===`artefacts`?` active`:``}`,onClick:Nt,children:[(0,y.jsx)(s,{size:20,strokeWidth:$}),(0,y.jsx)(`span`,{className:`label`,children:`Artefacts`}),(0,y.jsx)(`span`,{className:`kbd`})]}),(0,y.jsxs)(`button`,{type:`button`,className:`nav-row${P===`sessions`?` active`:``}`,onClick:Ft,children:[(0,y.jsx)(fe,{size:20,strokeWidth:$}),(0,y.jsx)(`span`,{className:`label`,children:`Sessions`}),(0,y.jsx)(`span`,{className:`kbd`})]}),(0,y.jsxs)(`button`,{type:`button`,className:`nav-row${P===`data`?` active`:``}`,onClick:Lt,children:[(0,y.jsx)(c,{size:20,strokeWidth:$}),(0,y.jsx)(`span`,{className:`label`,children:`Data`}),(0,y.jsx)(`span`,{className:`kbd`})]}),St&&_.filter(e=>jt.get(e).length>0).map(e=>(0,y.jsxs)(`button`,{type:`button`,className:`nav-row${P===`whatsapp`&&Et===e?` active`:``}`,onClick:()=>Rt(e),children:[(0,y.jsx)(h,{channel:e,size:16}),(0,y.jsx)(`span`,{className:`label`,children:Mt[e]}),(0,y.jsx)(`span`,{className:`kbd`})]},e)),wt&&(0,y.jsx)(`div`,{className:`nav-row`,style:{color:`var(--text-tertiary)`,cursor:`default`},"aria-disabled":`true`,children:(0,y.jsx)(`span`,{className:`label`,children:wt})})]}),P===`artefacts`&&(0,y.jsxs)(`div`,{className:`side-list`,children:[(0,y.jsxs)(`div`,{className:`group-head`,children:[(0,y.jsx)(`span`,{children:`Artefacts`}),(0,y.jsxs)(`span`,{className:`group-head-meta`,children:[(0,y.jsx)(`button`,{type:`button`,className:`group-head-refresh`,title:`Refresh artefacts`,"aria-label":`Refresh artefacts`,onClick:Pt,disabled:we,children:(0,y.jsx)(l,{size:12,className:we?`spinning`:void 0})}),(0,y.jsx)(`span`,{children:we?`…`:String(I.length)})]})]}),R&&(0,y.jsx)(`div`,{className:`conv`,style:{color:`var(--text-tertiary)`,cursor:`default`},children:R}),xe&&!R&&I.length>0&&(()=>{let e=I.filter(e=>e.kind===`agent-template`).length,t=I.length-e;return(0,y.jsx)(`div`,{className:`artefact-filter-chips`,children:[{key:`all`,label:`All`,count:I.length},{key:`agent`,label:`Agents`,count:e},{key:`file`,label:`Files`,count:t}].map(e=>(0,y.jsxs)(`button`,{type:`button`,className:`artefact-filter-chip${Ee===e.key?` active`:``}`,onClick:()=>De(e.key),disabled:e.count===0&&e.key!==`all`,children:[e.label,(0,y.jsx)(`span`,{className:`artefact-filter-chip-count`,children:e.count})]},e.key))})})(),xe&&!R&&I.length===0&&(0,y.jsx)(`div`,{className:`conv`,style:{color:`var(--text-tertiary)`,cursor:`default`},children:`No artefacts yet`}),I.filter(e=>Ee===`all`?!0:Ee===`agent`?e.kind===`agent-template`:e.kind!==`agent-template`).map(e=>{let t=e.kind===`agent-template`,n=t?de:s,r=He(e.updatedAt),i=e.downloadPath!==null;return(0,y.jsxs)(`button`,{type:`button`,className:`conv`,onClick:()=>Ot(e),disabled:!i,style:i?void 0:{cursor:`default`},title:i?`Download ${e.name}`:`${e.name} can’t be downloaded`,children:[(0,y.jsx)(n,{size:14,className:`conv-icon`,"data-kind":t?`agent`:`file`,"aria-label":t?`agent template`:`file`}),(0,y.jsxs)(`span`,{className:`conv-stack`,children:[(0,y.jsx)(`span`,{className:`conv-name-line`,children:(0,y.jsx)(`span`,{className:`conv-name`,children:e.name})}),r&&(0,y.jsx)(`span`,{className:`conv-timestamp`,children:r})]}),i&&(0,y.jsx)(oe,{size:12,className:`conv-rc-icon`,"aria-hidden":`true`})]},e.id)})]}),P===`sessions`&&(()=>{let e=H.filter(e=>G?!0:!e.isSubagent).filter(e=>K?!0:!e.archived),n=H.some(e=>e.isSubagent),r=H.some(e=>e.archived);return(0,y.jsxs)(`div`,{className:`side-list`,children:[(0,y.jsxs)(`div`,{className:`group-head`,children:[(0,y.jsx)(`span`,{children:`Sessions`}),(0,y.jsxs)(`span`,{className:`group-head-meta`,children:[(0,y.jsx)(`button`,{type:`button`,className:`group-head-refresh`,title:`Refresh sessions`,"aria-label":`Refresh sessions`,onClick:It,disabled:Ue,children:(0,y.jsx)(l,{size:12,className:Ue?`spinning`:void 0})}),(0,y.jsx)(`span`,{children:Ue?`…`:String(e.length)})]})]}),Xe&&(0,y.jsx)(`div`,{className:`side-account-id`,title:`This install's accountId. The first 8 characters match the truncated UUID label on the live Remote Control daemon entry in claude.ai/code.`,children:(0,y.jsx)(`code`,{children:Xe})}),(n||r)&&(0,y.jsxs)(`div`,{className:`artefact-filter-chips`,children:[n&&(0,y.jsx)(`button`,{type:`button`,className:`artefact-filter-chip${G?` active`:``}`,"aria-pressed":G,onClick:()=>Je(e=>!e),title:G?`Hide subagent sessions`:`Show subagent sessions`,children:`Subagents`}),r&&(0,y.jsx)(`button`,{type:`button`,className:`artefact-filter-chip${K?` active`:``}`,"aria-pressed":K,onClick:()=>Ye(e=>!e),title:K?`Hide archived sessions`:`Show archived sessions`,children:`Archived`})]}),W&&(0,y.jsx)(`div`,{className:`conv`,style:{color:`var(--text-tertiary)`,cursor:`default`},children:W}),U&&!W&&e.length===0&&(0,y.jsx)(`div`,{className:`conv`,style:{color:`var(--text-tertiary)`,cursor:`default`},children:`No sessions yet`}),e.map(e=>{let n=He(e.startedAt),r=J.has(e.sessionId),i=q.has(e.sessionId),a=nt.has(e.sessionId),o=it.has(e.sessionId),s=r||i||a||o,c=()=>{window.location.assign(`/chat?session=${e.sessionId}`)},l=[{key:`open`,label:`Resume session ${e.title} in claude.ai/code`,menuLabel:`Resume in claude.ai/code`,title:`Resume in a fresh local Remote Control PTY`,icon:(0,y.jsx)(t,{size:12}),busy:r,onClick:()=>{zt(e)}},{key:`message`,label:`Open session ${e.title} in admin webchat`,menuLabel:`Open in webchat`,title:`Open in admin webchat (/chat) — sending resumes this session`,icon:(0,y.jsx)(pe,{size:12}),onClick:()=>{c()}},{key:`usage`,label:`Usage and cost for session ${e.title}`,menuLabel:`Usage & cost`,title:`Per-day active time, tokens, and estimated GBP cost`,icon:(0,y.jsx)(w,{size:12}),onClick:t=>{Ut(t,e)}},...e.live?[{key:`stop`,label:`Stop session ${e.title}`,menuLabel:`Stop`,title:`Stop session process (keeps the conversation, can resume later)`,icon:(0,y.jsx)(E,{size:12}),busy:a,onClick:t=>{Gt(t,e)}}]:[],e.archived?{key:`unarchive`,label:`Unarchive session ${e.title}`,menuLabel:`Unarchive`,title:`Unarchive (move back to the active list)`,icon:(0,y.jsx)(le,{size:12}),busy:o,onClick:t=>{Kt(t,e,`unarchive`)}}:{key:`archive`,label:`Archive session ${e.title}`,menuLabel:`Archive`,title:`Archive (hide from the list, keeps the conversation resumable)`,icon:(0,y.jsx)(ue,{size:12}),busy:o,onClick:t=>{Kt(t,e,`archive`)}},{key:`rename`,label:`Rename session ${e.title}`,menuLabel:`Rename`,title:`Rename this session`,icon:(0,y.jsx)(ae,{size:12}),busy:ct&&Y===e.sessionId,onClick:t=>{t.stopPropagation(),ot(e.sessionId),X(e.personName??e.title)}},{key:`delete`,label:`Delete session ${e.title}`,menuLabel:`Delete`,title:`Delete session (stops the process, removes the conversation)`,icon:(0,y.jsx)(p,{size:12}),danger:!0,busy:i,onClick:t=>{Ht(t,e)}},ye({sessionId:e.sessionId,model:e.model??null,title:e.personName??e.title})];return(0,y.jsxs)(`div`,{className:`conv conv-with-actions`,children:[(0,y.jsxs)(`div`,{className:`conv-main-static conv-main-clickable`,role:`button`,tabIndex:0,"aria-label":`Open ${e.personName??e.title} in webchat`,onClick:()=>{Y!==e.sessionId&&c()},onKeyDown:t=>{Y!==e.sessionId&&(t.key===`Enter`||t.key===` `)&&(t.preventDefault(),c())},children:[(0,y.jsx)(`span`,{className:`conv-live-dot`,"data-live":e.live?`1`:`0`,"aria-label":e.live?`live session`:`ended session`}),(0,y.jsxs)(`span`,{className:`conv-stack`,children:[(0,y.jsxs)(`span`,{className:`conv-name-line`,children:[e.channel&&(0,y.jsx)(ie,{channel:e.channel,size:13}),Y===e.sessionId?(0,y.jsx)(`input`,{className:`conv-name conv-name-edit`,autoFocus:!0,value:st,disabled:ct,"aria-label":`New title for session ${e.title}`,onChange:e=>X(e.target.value),onClick:e=>e.stopPropagation(),onKeyDown:t=>{t.key===`Enter`?(t.preventDefault(),qt(e)):t.key===`Escape`&&(t.preventDefault(),ot(null),X(``))},onBlur:()=>{Y===e.sessionId&&!ct&&(ot(null),X(``))}}):(0,y.jsx)(`span`,{className:`conv-name`,title:e.personName??e.title,children:e.personName??e.title})]}),(0,y.jsxs)(`span`,{className:`conv-timestamp`,children:[(0,y.jsx)(`code`,{className:`conv-session-id`,title:`First 8 characters of this session's id — distinguishes rows with identical auto-titles. The resume/delete buttons act on the full id.`,children:e.sessionId.slice(0,8)}),n&&(0,y.jsxs)(`span`,{children:[` · `,n]})]})]})]}),(0,y.jsx)(be,{actions:l,disabled:s})]},e.sessionId)})]})})(),P===`whatsapp`&&(0,y.jsxs)(`div`,{className:`side-list`,children:[(0,y.jsxs)(`div`,{className:`group-head`,children:[(0,y.jsx)(`span`,{children:Mt[Et]}),(0,y.jsxs)(`span`,{className:`group-head-meta`,children:[(0,y.jsx)(`button`,{type:`button`,className:`group-head-refresh`,title:`Refresh conversations`,"aria-label":`Refresh conversations`,onClick:()=>{At()},children:(0,y.jsx)(l,{size:12})}),(0,y.jsx)(`span`,{children:String(jt.get(Et).length)})]})]}),jt.get(Et).map(e=>{let t=He(e.lastMessageAt),n=d(e);return(0,y.jsxs)(`div`,{className:`conv conv-with-actions${e.source===`store`?e.scope===`admin`?` conv-scope-admin`:` conv-scope-public`:``}${S===n?` active`:``}`,children:[(0,y.jsxs)(`button`,{type:`button`,className:`conv-main-static conv-main-btn`,onClick:()=>{D(e),b()},title:e.title,children:[(0,y.jsx)(h,{channel:e.channel,size:14}),(0,y.jsxs)(`span`,{className:`conv-stack`,children:[(0,y.jsx)(`span`,{className:`conv-name-line`,children:(0,y.jsx)(`span`,{className:`conv-name`,children:ee(e)})}),t&&(0,y.jsx)(`span`,{className:`conv-timestamp`,children:t})]})]}),e.source===`session`&&(0,y.jsx)(be,{actions:[ye({sessionId:e.sessionId,model:e.model,title:e.title})],disabled:!1})]},n)})]}),(0,y.jsx)(qe,{}),(0,y.jsxs)(`div`,{className:`side-foot`,children:[(0,y.jsx)(`div`,{className:`avatar`,children:f?(0,y.jsx)(`img`,{src:f,alt:M}):N}),(0,y.jsxs)(`div`,{className:`who`,children:[(0,y.jsx)(`span`,{className:`name`,children:M}),(0,y.jsx)(`span`,{className:`role`,children:a??`operator`})]})]}),z&&(0,y.jsx)(`div`,{className:`copy-toast${z.failed?` copy-toast-failed`:``}`,role:`status`,children:z.message}),(0,y.jsx)(Me,{error:ke,onClose:()=>V(null)}),(0,y.jsx)(Pe,{open:je,onConnect:()=>{Ne(!1),i?.()},onClose:()=>Ne(!1)}),(0,y.jsx)(Ae,{target:$e,onCancel:()=>et(null),onConfirm:()=>{let e=$e;et(null),e&&Wt(e)}}),(0,y.jsx)(Le,{show:ut!==null,onClose:()=>{dt(null),pt(null),_t(null)},sessionId:ut?.sessionId??null,summary:ft,loading:mt,error:gt})]})}var We=5e3,Ge=3e4,Ke=3e4;function qe(){let[e,t]=(0,v.useState)(null);if((0,v.useEffect)(()=>{let e=!1,n=null;async function r(){try{let n=await fetch(`/api/admin/system-stats`);if(!n.ok){console.error(`[admin-ui] system-stats-fetch-failed status=${n.status}`);return}let r=await n.json();e||t(r)}catch(e){console.error(`[admin-ui] system-stats-fetch-failed reason=${e instanceof Error?e.message:String(e)}`)}}function i(){n===null&&(r(),n=setInterval(()=>{r()},We))}function a(){n!==null&&(clearInterval(n),n=null)}function o(){document.hidden?a():i()}return document.hidden||i(),document.addEventListener(`visibilitychange`,o),()=>{e=!0,a(),document.removeEventListener(`visibilitychange`,o)}},[]),!e||e.platform===`darwin`)return null;let n=e.cpuPct,r=e.memUsedPct,i=n!==null&&n>=.9,a=n!==null&&n>=.98,o=r!==null&&r>=.9,s=r!==null&&r>=.98,c=i||o,l=a||s,u=e=>e===null?`—`:`${Math.round(e*100)}%`,d=e=>{if(e===null)return{width:`0%`,background:`var(--text-tertiary)`};let t=Math.min(1,Math.max(0,e)),n=Math.round(140*(1-t));return{width:`${Math.round(t*100)}%`,background:`hsl(${n}, 65%, 45%)`}},f=[`system-stats`];return c&&f.push(`system-stats--warn`),l&&f.push(`system-stats--crit`),(0,y.jsxs)(`div`,{className:f.join(` `),role:`status`,"aria-label":`host CPU and RAM`,children:[(0,y.jsxs)(`div`,{className:`system-stats__metric`,children:[(0,y.jsxs)(`span`,{className:i?`system-stats__fig system-stats__fig--warn`:`system-stats__fig`,children:[`CPU `,u(n)]}),(0,y.jsx)(`div`,{className:`system-stats__bar`,children:(0,y.jsx)(`div`,{className:`system-stats__bar-fill`,style:d(n)})})]}),(0,y.jsxs)(`div`,{className:`system-stats__metric`,children:[(0,y.jsxs)(`span`,{className:o?`system-stats__fig system-stats__fig--warn`:`system-stats__fig`,children:[`RAM `,u(r)]}),(0,y.jsx)(`div`,{className:`system-stats__bar`,children:(0,y.jsx)(`div`,{className:`system-stats__bar-fill`,style:d(r)})})]})]})}var G=`admin-sidebar-collapsed`,Je=`admin-sidebar-drawer-open`;function K(){if(typeof window>`u`)return!1;try{return window.sessionStorage.getItem(G)===`1`}catch{return!1}}function Ye(e){if(!(typeof window>`u`))try{e?window.sessionStorage.setItem(G,`1`):window.sessionStorage.removeItem(G)}catch{}}function Xe(){if(typeof window>`u`)return!1;try{return window.sessionStorage.getItem(Je)===`1`}catch{return!1}}function Ze(e){if(!(typeof window>`u`))try{e?window.sessionStorage.setItem(Je,`1`):window.sessionStorage.removeItem(Je)}catch{}}var q=720;function Qe(e,t){return e===`/`?{via:`in-place`}:{via:`navigate`,href:`/?wa=${encodeURIComponent(t.remoteJid??``)}&acct=${encodeURIComponent(t.accountId??``)}`}}function $e(e){return e===`/`?{via:`in-place`}:{via:`navigate`,href:`/?data=1`}}function et(e,t){if(e!==`/`)return null;let n=new URLSearchParams(t),r=n.get(`wa`),i=n.get(`acct`);return!r||!i?null:{sessionId:``,projectDir:``,title:``,senderId:null,startedAt:``,channel:`whatsapp`,role:`public`,operatorName:null,whatsappName:null,lastMessageAt:null,modelGated:!1,model:null,source:`store`,accountId:i,remoteJid:r}}function J(e,t){return e===`/`?new URLSearchParams(t).has(`data`):!1}function tt(e,t){return t===`operator`&&e===`chat`||e===`dashboard`?`/`:e===`data`?`/data`:e===`graph`?`/graph`:e===`calendar`?`/calendar`:e===`chat`?`/chat`:`/browser`}function nt(e){let{cacheKey:t,businessName:n,variant:r=`admin`,onLogout:i,onDisconnect:a,disconnecting:o,claudeConnected:s,onConnectClaude:c,userName:l,userAvatar:u,role:p,onOpenConversations:h,children:g,footer:ee}=e,{subAccounts:te,activeAccountId:ne,switching:_,switchAccount:ie}=re(t),[ae,oe]=(0,v.useState)(!0);(0,v.useEffect)(()=>{if(s!==void 0||r!==`admin`)return;let e=!1,t=async()=>{try{let t=await fetch(`/api/health`);if(!t.ok)return;let n=await t.json();e||oe(n.auth_status!==`dead`&&n.auth_status!==`missing`)}catch{}};t();let n=setInterval(t,6e4);return()=>{e=!0,clearInterval(n)}},[s,r]);let se=s??ae,ce=c??(()=>{window.location.assign(`/?connect=claude`)}),[b,x]=(0,v.useState)(()=>K()),[S,le]=(0,v.useState)(()=>Xe()),[ue,de]=(0,v.useState)(()=>typeof window<`u`&&window.matchMedia(`(max-width: ${q}px)`).matches),[C,w]=(0,v.useState)(()=>typeof window>`u`||J(window.location.pathname,window.location.search)?null:et(window.location.pathname,window.location.search)),[fe]=(0,v.useState)(()=>C!==null),[T,pe]=(0,v.useState)(()=>typeof window>`u`?!1:J(window.location.pathname,window.location.search)),[me]=(0,v.useState)(()=>T);(0,v.useEffect)(()=>{if(typeof window>`u`)return;let e=window.matchMedia(`(max-width: ${q}px)`),t=e=>de(e.matches);return e.addEventListener(`change`,t),()=>e.removeEventListener(`change`,t)},[]);let he=(0,v.useCallback)(e=>{Ye(e),x(e)},[]),E=(0,v.useCallback)(e=>{Ze(e),le(e)},[]);(0,v.useEffect)(()=>{if(typeof window>`u`)return;let e=window.location?.pathname??``;console.info(`[admin-ui] shell-mount route=${e} variant=${r} sidebar=${r===`operator`?`none`:`present`} collapsed=${b} drawer=${S}`)},[]),(0,v.useEffect)(()=>{typeof window>`u`||!C||(console.info(`[admin-ui] wa-hydrate route=/ remoteJid=${C.remoteJid??``}`),window.history.replaceState(null,``,`/`))},[]),(0,v.useEffect)(()=>{typeof window>`u`||!T||(console.info(`[admin-ui] data-hydrate route=/`),window.history.replaceState(null,``,`/`))},[]);let ge=(0,v.useCallback)(e=>{if(pe(!1),e===null){w(null);return}let t=typeof window<`u`?window.location.pathname:`/`,n=Qe(t,e);console.info(`[admin-ui] wa-open route=${t} via=${n.via} sessionId=${e.sessionId.slice(0,8)}`),n.via===`in-place`?w(e):window.location.href=n.href},[]),D=(0,v.useCallback)(()=>{let e=typeof window<`u`?window.location.pathname:`/`,t=$e(e);if(console.info(`[admin-ui] data-open route=${e} via=${t.via}`),t.via===`navigate`){window.location.href=t.href;return}w(null),pe(!0)},[]),O=ue?S:!b,k=(0,v.useCallback)(()=>{if(!(typeof window>`u`))if(window.matchMedia(`(max-width: ${q}px)`).matches){let e=S;console.info(`[admin-ui] header-sidebar-toggle from=${e?`open`:`closed`} mode=drawer`),E(!e)}else{let e=b;console.info(`[admin-ui] header-sidebar-toggle from=${e?`closed`:`open`} mode=collapse`),he(!e)}},[b,S,he,E]),_e=(0,v.useCallback)(e=>{let t=tt(e,r);console.info(`[admin-ui] header-menu-nav target=${e} dest=${t}`),window.location.href=t},[r]),A={collapsed:b,mobileDrawerOpen:S,sidebarOpen:O,onToggleSidebar:k,setMobileDrawerOpen:E,selectedWhatsapp:C,onClearWhatsapp:()=>w(null),dataOpen:T};return r===`operator`?(0,y.jsxs)(`div`,{className:`admin-shell admin-page admin-shell-root`,children:[(0,y.jsx)(f,{businessName:n,variant:r,onNavigate:_e,onOpenConversations:h,onToggleSidebar:k,sidebarOpen:O,onLogout:i,onDisconnect:a,disconnecting:o,cacheKey:t,subAccounts:te,activeAccountId:ne,switchingAccount:_,onSwitchAccount:ie}),(0,y.jsx)(`div`,{className:`platform platform-operator`,children:typeof g==`function`?g(A):g}),ee]}):(0,y.jsxs)(`div`,{className:`admin-shell admin-page admin-shell-root`,children:[(0,y.jsx)(f,{businessName:n,variant:r,onNavigate:_e,onOpenConversations:h,onToggleSidebar:k,sidebarOpen:O,onLogout:i,onDisconnect:a,disconnecting:o,claudeConnected:se,onConnectClaude:ce,cacheKey:t,subAccounts:te,activeAccountId:ne,switchingAccount:_,onSwitchAccount:ie}),(0,y.jsxs)(`div`,{className:`platform${S?` menu-open`:``}${b?` sidebar-collapsed`:``}`,"data-artefact":`closed`,children:[(0,y.jsx)(Ue,{businessName:n,cacheKey:t,onConnectClaude:ce,role:p??null,userName:l,userAvatar:u??null,onSelectProjects:()=>{window.location.href=`/graph?label=${m().label}`},onSelectPeople:()=>{window.location.href=`/graph?label=Person`},onSelectTasks:()=>{window.location.href=`/graph?label=Task`},onSelectAgents:()=>{window.location.href=`/graph?label=Agent`},onCloseMobileDrawer:()=>E(!1),collapsed:b,mobileDrawerOpen:S,selectedWhatsappId:C?d(C):null,onSelectWhatsappConversation:ge,initialWhatsappSurface:fe,onSelectData:D,onCloseData:()=>pe(!1),initialDataSurface:me}),!ue&&(0,y.jsx)(ve,{}),typeof g==`function`?g(A):g]}),S&&(0,y.jsx)(`div`,{className:`sidebar-backdrop menu-open`,"aria-hidden":`true`,onClick:()=>E(!1)}),ee]})}export{de as _,V as a,S as b,M as c,ge as d,E as f,w as g,T as h,Ne as i,xe as l,me as m,Ve as n,N as o,he as p,Pe as r,j as s,nt as t,F as u,ue as v,ce as x,le as y};
@@ -1 +1 @@
1
- import{M as e}from"./useSubAccountSwitcher-BVCMAnWK.js";var t=e();function n({checked:e,onChange:n,label:r,disabled:i}){return(0,t.jsxs)(`label`,{className:`maxy-checkbox${i?` maxy-checkbox--disabled`:``}`,children:[(0,t.jsx)(`input`,{type:`checkbox`,checked:e,onChange:e=>n(e.target.checked),disabled:i}),(0,t.jsx)(`span`,{className:`maxy-checkbox__box`,children:`✱`}),r&&(0,t.jsx)(`span`,{className:`maxy-checkbox__label`,children:r})]})}export{n as t};
1
+ import{M as e}from"./useSubAccountSwitcher-Bg0RH3Gk.js";var t=e();function n({checked:e,onChange:n,label:r,disabled:i}){return(0,t.jsxs)(`label`,{className:`maxy-checkbox${i?` maxy-checkbox--disabled`:``}`,children:[(0,t.jsx)(`input`,{type:`checkbox`,checked:e,onChange:e=>n(e.target.checked),disabled:i}),(0,t.jsx)(`span`,{className:`maxy-checkbox__box`,children:`✱`}),r&&(0,t.jsx)(`span`,{className:`maxy-checkbox__label`,children:r})]})}export{n as t};