@rubytech/create-maxy-code 0.1.495 → 0.1.496

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 (53) hide show
  1. package/package.json +1 -1
  2. package/payload/platform/plugins/admin/skills/insight/SKILL.md +1 -1
  3. package/payload/platform/plugins/admin/skills/platform-architecture/SKILL.md +17 -6
  4. package/payload/platform/plugins/docs/references/admin-ui.md +16 -5
  5. package/payload/platform/plugins/memory/references/schema-estate-agent.md +1 -1
  6. package/payload/platform/scripts/__tests__/account-schema-owned-dirs.test.sh +51 -7
  7. package/payload/platform/scripts/__tests__/provision-role-stamp.test.sh +4 -1
  8. package/payload/platform/scripts/lib/account-schema-owned-dirs.py +13 -1
  9. package/payload/platform/scripts/lib/account-schema-owned-dirs.sh +23 -1
  10. package/payload/platform/scripts/lib/provision-account-dir.sh +5 -0
  11. package/payload/server/public/activity.html +5 -5
  12. package/payload/server/public/assets/{AdminLoginScreens-DgVFsHtd.js → AdminLoginScreens-CFF28MGy.js} +1 -1
  13. package/payload/server/public/assets/AdminShell-ClIT8c0K.js +2 -0
  14. package/payload/server/public/assets/{activity-2DL2DwLr.js → activity-CElZcdjR.js} +1 -1
  15. package/payload/server/public/assets/{admin-COe0dT2U.js → admin-BHiA9_Ks.js} +1 -1
  16. package/payload/server/public/assets/{bot-CpBuDQlF.js → bot-Q-JmeVT3.js} +1 -1
  17. package/payload/server/public/assets/{browser-CSApuZrv.js → browser-BrfPJMYF.js} +1 -1
  18. package/payload/server/public/assets/{calendar-DlvwZnS7.js → calendar-D45S_aal.js} +1 -1
  19. package/payload/server/public/assets/chat-gy8scQov.js +1 -0
  20. package/payload/server/public/assets/chevron-down-CdxvexgY.js +1 -0
  21. package/payload/server/public/assets/chevron-left-D5LLz6ke.js +1 -0
  22. package/payload/server/public/assets/chevron-right-DzPmwDew.js +1 -0
  23. package/payload/server/public/assets/data-CUsNHUpu.js +1 -0
  24. package/payload/server/public/assets/{graph-kaxS9a_7.js → graph-BLO4nVi3.js} +1 -1
  25. package/payload/server/public/assets/{graph-labels-GgejRtgV.js → graph-labels-ibEi7ggo.js} +1 -1
  26. package/payload/server/public/assets/{maximize-2-CPq3nwZA.js → maximize-2-CezchDEF.js} +1 -1
  27. package/payload/server/public/assets/{operator-Cxq9TxaH.js → operator-B-3vkwO8.js} +1 -1
  28. package/payload/server/public/assets/{page-DBHzC59_.js → page-BL1ko2_-.js} +1 -1
  29. package/payload/server/public/assets/{page-BE6DkJP9.js → page-BbxoY4QI.js} +1 -1
  30. package/payload/server/public/assets/{public-jIzvdjt_.js → public-DxfSLhNp.js} +1 -1
  31. package/payload/server/public/assets/{rotate-ccw-DieZzl10.js → rotate-ccw-CWvGAut4.js} +1 -1
  32. package/payload/server/public/assets/{tasks-DYyCGz8W.js → tasks-DlXIN3v3.js} +1 -1
  33. package/payload/server/public/assets/{time-entry-format-CC_9jFuR.js → time-entry-format-VzHwljTv.js} +1 -1
  34. package/payload/server/public/assets/{triangle-alert-7mQfCQWP.js → triangle-alert-C5BpoPlq.js} +1 -1
  35. package/payload/server/public/assets/{useCopyFeedback-os7N0yCx.js → useCopyFeedback-h1qT8mpZ.js} +1 -1
  36. package/payload/server/public/assets/{useSubAccountSwitcher-Bgfqig1V.css → useSubAccountSwitcher-DnfX9Uxe.css} +1 -1
  37. package/payload/server/public/assets/{useVoiceRecorder-ZFwt5i6d.js → useVoiceRecorder-kqMitFlk.js} +1 -1
  38. package/payload/server/public/browser.html +4 -4
  39. package/payload/server/public/calendar.html +6 -6
  40. package/payload/server/public/chat.html +13 -13
  41. package/payload/server/public/data.html +10 -10
  42. package/payload/server/public/graph.html +10 -10
  43. package/payload/server/public/index.html +15 -15
  44. package/payload/server/public/operator.html +14 -14
  45. package/payload/server/public/public.html +13 -13
  46. package/payload/server/public/tasks.html +6 -6
  47. package/payload/server/public/assets/AdminShell-BwNqwb4k.js +0 -2
  48. package/payload/server/public/assets/chat-1SSmFsjd.js +0 -1
  49. package/payload/server/public/assets/chevron-down-Dnuuw6Q2.js +0 -1
  50. package/payload/server/public/assets/chevron-left-CC4zmWOr.js +0 -1
  51. package/payload/server/public/assets/chevron-right-CG_lHTx_.js +0 -1
  52. package/payload/server/public/assets/data-CJbC_cVy.js +0 -1
  53. /package/payload/server/public/assets/{useSubAccountSwitcher-Q941cZYV.js → useSubAccountSwitcher-DDStL7Nt.js} +0 -0
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@rubytech/create-maxy-code",
3
- "version": "0.1.495",
3
+ "version": "0.1.496",
4
4
  "description": "Install Maxy — AI for Productive People",
5
5
  "bin": {
6
6
  "create-maxy-code": "./dist/index.js"
@@ -15,7 +15,7 @@ Run the four passes now over the session so far, then keep going in this same se
15
15
 
16
16
  Pass 1 — Technical learnings. Walk this session for operator corrections and self-detected mistakes. For each one, delegate one graph write to `database-operator` via the Task tool, persisting a Learning or Correction node per the schema. Count what you write.
17
17
 
18
- Pass 2 — Operator-relationship updates. Walk this session for tonal signals, rejected phrasings, and working-style preferences. For each one worth carrying forward, Write the observation into `SOUL.md` at the account-scoped path. Count what you write.
18
+ Pass 2 — Operator-relationship updates. Walk this session for tonal signals, rejected phrasings, and working-style preferences. For each one worth carrying forward, Write the observation into `agents/admin/SOUL.md`, the account-scoped identity path the spawn composer reads. That path is the only identity file; never write a bare `SOUL.md` at the account root, which the composer never reads and the schema guard blocks. Count what you write.
19
19
 
20
20
  Pass 3 — Graph completeness sweep. Walk this session for any node, edge, or commitment that was discussed but not written to the graph in-flight. For each missing write, delegate to `database-operator` via the Task tool. Count what you write.
21
21
 
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  name: platform-architecture
3
3
  description: Use when grounding any documented-surface claim about what Maxy ships — plugins, skills, specialists, install/deploy flows, internals. This is the install catalogue, not evidence of what is enabled on the current account. For install state on this account, call `capabilities-here`; for documented surface, cite the `Source:` URL inline.
4
- content-hash: sha256:59873e611d7a40e6aa9c3f41bc766d8a4e0632934f7542470aa309fb59dc5db7
4
+ content-hash: sha256:019a4f941c1466cfb0a9490c7c92f2eccbba4e67e57df48ddcb28f7b1ef5d835
5
5
  brand: maxy-code
6
6
  product-name: Maxy
7
7
  ---
@@ -3300,9 +3300,11 @@ authoritative. This section names the surfaces and what backs each.
3300
3300
  >
3301
3301
  > - **Nav rows** are Dashboard, Chat, Tasks, Calendar, Data, the brand container
3302
3302
  > row (Projects / Properties / Jobs, opening the graph filtered to the brand's
3303
- > primary container), Activity, and Browser. The active row carries an accent
3304
- > left indicator. The older People / Agents / Artefacts entries in the table
3305
- > below are pre-redesign.
3303
+ > primary container), Graph (the unfiltered whole graph at `/graph`, waypoints
3304
+ > icon active on plain `/graph`; the container row is active only when a
3305
+ > `label=` filter is present), Activity, and Browser. The active row carries an
3306
+ > accent left indicator. The older People / Agents / Artefacts entries in the
3307
+ > table below are pre-redesign.
3306
3308
  > - **Dashboard home** renders on `/` (a greeting, stat cards, a Live-now column,
3307
3309
  > a Recent artefacts card, and a Channels column), consuming existing endpoints
3308
3310
  > only.
@@ -3317,14 +3319,23 @@ authoritative. This section names the surfaces and what backs each.
3317
3319
  > - **Mobile (< 720px).** The sidebar opens as a drawer from a 44x44 header menu
3318
3320
  > button, and a fixed bottom tab bar (Home, Chat, Tasks, Data, Calendar) sits
3319
3321
  > under the content; Graph, Activity, and Browser stay reachable through the
3320
- > drawer. Between 721 and 1080px the sidebar defaults to the rail.
3322
+ > drawer. Between 721 and 1080px the sidebar defaults to the rail. The
3323
+ > drawer's SESSIONS head collapses its New-session pill to an icon-only `+`
3324
+ > (34px square); the label returns above 720px. The **operator** variant gets
3325
+ > its own fixed bottom tab bar — Chat, Conversations (rendered only when the
3326
+ > pane handler is wired), Data — while its burger keeps the AccountMenu tail.
3327
+ > In the webchat composer the icon control bar moves **above** the input box
3328
+ > with 44px touch squares (desktop keeps the below-input row), and the
3329
+ > composer placeholder never wraps (single line, ellipsized).
3321
3330
 
3322
3331
  > **Admin variant only.** Every surface below belongs to the `admin` shell
3323
3332
  > variant. The **operator** variant (`operator.<host>`) mounts no sidebar at
3324
3333
  > all: its dashboard is the persistent admin webchat at `/` and the data
3325
3334
  > browser at `/data`, plus a **Conversations** item reached from a dynamic
3326
3335
  > burger item — header order Chat → Conversations → Data → Log out, in a
3327
- > single-column `.platform.platform-operator` grid. On the operator **chat**
3336
+ > single-column `.platform.platform-operator` grid. Below 720px the same three
3337
+ > nav items also render as the operator bottom tab bar (see Mobile above);
3338
+ > the Chat tab targets the operator root `/`, the canonical-session route. On the operator **chat**
3328
3339
  > surface the Conversations item opens the same in-chat session
3329
3340
  > switcher the admin `/chat` surface uses (`ChatSurface`'s `SessionList` flyout):
3330
3341
  > the operator's own admin webchat conversations, newest-first, each resuming
@@ -399,9 +399,11 @@ authoritative. This section names the surfaces and what backs each.
399
399
  >
400
400
  > - **Nav rows** are Dashboard, Chat, Tasks, Calendar, Data, the brand container
401
401
  > row (Projects / Properties / Jobs, opening the graph filtered to the brand's
402
- > primary container), Activity, and Browser. The active row carries an accent
403
- > left indicator. The older People / Agents / Artefacts entries in the table
404
- > below are pre-redesign.
402
+ > primary container), Graph (the unfiltered whole graph at `/graph`, waypoints
403
+ > icon active on plain `/graph`; the container row is active only when a
404
+ > `label=` filter is present), Activity, and Browser. The active row carries an
405
+ > accent left indicator. The older People / Agents / Artefacts entries in the
406
+ > table below are pre-redesign.
405
407
  > - **Dashboard home** renders on `/` (a greeting, stat cards, a Live-now column,
406
408
  > a Recent artefacts card, and a Channels column), consuming existing endpoints
407
409
  > only.
@@ -416,14 +418,23 @@ authoritative. This section names the surfaces and what backs each.
416
418
  > - **Mobile (< 720px).** The sidebar opens as a drawer from a 44x44 header menu
417
419
  > button, and a fixed bottom tab bar (Home, Chat, Tasks, Data, Calendar) sits
418
420
  > under the content; Graph, Activity, and Browser stay reachable through the
419
- > drawer. Between 721 and 1080px the sidebar defaults to the rail.
421
+ > drawer. Between 721 and 1080px the sidebar defaults to the rail. The
422
+ > drawer's SESSIONS head collapses its New-session pill to an icon-only `+`
423
+ > (34px square); the label returns above 720px. The **operator** variant gets
424
+ > its own fixed bottom tab bar — Chat, Conversations (rendered only when the
425
+ > pane handler is wired), Data — while its burger keeps the AccountMenu tail.
426
+ > In the webchat composer the icon control bar moves **above** the input box
427
+ > with 44px touch squares (desktop keeps the below-input row), and the
428
+ > composer placeholder never wraps (single line, ellipsized).
420
429
 
421
430
  > **Admin variant only.** Every surface below belongs to the `admin` shell
422
431
  > variant. The **operator** variant (`operator.<host>`) mounts no sidebar at
423
432
  > all: its dashboard is the persistent admin webchat at `/` and the data
424
433
  > browser at `/data`, plus a **Conversations** item reached from a dynamic
425
434
  > burger item — header order Chat → Conversations → Data → Log out, in a
426
- > single-column `.platform.platform-operator` grid. On the operator **chat**
435
+ > single-column `.platform.platform-operator` grid. Below 720px the same three
436
+ > nav items also render as the operator bottom tab bar (see Mobile above);
437
+ > the Chat tab targets the operator root `/`, the canonical-session route. On the operator **chat**
427
438
  > surface the Conversations item opens the same in-chat session
428
439
  > switcher the admin `/chat` surface uses (`ChatSurface`'s `SessionList` flyout):
429
440
  > the operator's own admin webchat conversations, newest-first, each resuming
@@ -13,7 +13,7 @@ When loading this reference, confirm: "Using schema-base + schema-estate-agent".
13
13
  | Entity | Neo4j Label | Owner | Schema.org Type | Required Properties |
14
14
  |--------|-------------|-------|-----------------|---------------------|
15
15
  | Property | `Property` | | `schema:Accommodation` | `accountId`, `slug` (id, address-derived), `address` |
16
- | Listing | `Listing` | | `schema:RealEstateListing` | `accountId`, `slug`, `displayName`, `listingType` (sale/let), `status`, `sourceSystem`, `sourceId`, `scope`, `heroImageUrl`*, `pageUrl`*, `blurb` |
16
+ | Listing | `Listing` | `Property` | `schema:RealEstateListing` | `accountId`, `slug`, `displayName`, `listingType` (sale/let), `status`, `sourceSystem`, `sourceId`, `scope`, `heroImageUrl`*, `pageUrl`*, `blurb` |
17
17
  | Viewing | `Viewing` | `Listing` | `schema:Event` (subtype) | `accountId`, `listing` (id), `applicant` (id), `date`, `feedback`, `outcome` |
18
18
  | Offer | `Offer` | `Listing` | `schema:Offer` | `accountId`, `listing` (id), `applicant` (id), `price`, `conditions`, `status`, `date` |
19
19
 
@@ -13,6 +13,8 @@ PASS=0; FAIL=0; FAILED=()
13
13
  assert_grep() { if printf '%s' "$2" | grep -qF "$1"; then PASS=$((PASS+1)); else FAIL=$((FAIL+1)); FAILED+=("$3: expected to find [$1]"); fi; }
14
14
  assert_nogrep() { if printf '%s' "$2" | grep -qF "$1"; then FAIL=$((FAIL+1)); FAILED+=("$3: expected NOT to find [$1]"); else PASS=$((PASS+1)); fi; }
15
15
  assert_eq() { if [ "$1" = "$2" ]; then PASS=$((PASS+1)); else FAIL=$((FAIL+1)); FAILED+=("$3: expected [$2] got [$1]"); fi; }
16
+ assert_dir() { if [ -d "$1" ]; then PASS=$((PASS+1)); else FAIL=$((FAIL+1)); FAILED+=("$2: expected directory [$1]"); fi; }
17
+ assert_nodir() { if [ -d "$1" ]; then FAIL=$((FAIL+1)); FAILED+=("$2: expected NO directory [$1]"); else PASS=$((PASS+1)); fi; }
16
18
 
17
19
  . "$PLAT_SCRIPTS/lib/account-schema-owned-dirs.sh"
18
20
 
@@ -156,21 +158,63 @@ assert_eq "$(shasum "$A_C/SCHEMA.md" | awk '{print $1}')" "$B_C" "con-idempotent
156
158
  RCS="$(PROJECT_DIR="$PROJECT_DIR" python3 "$PLAT_SCRIPTS/lib/account-schema-owned-dirs.py" reconcile "$A_C")"
157
159
  assert_grep "ontologyEntity=Supplier bucket=suppliers present=true" "$RCS" "con-supplier-root-present"
158
160
 
159
- # --- estate-agent vertical: root buckets only, listing-owned entities nested ---
161
+ # --- estate-agent vertical: Property is the sole root; Listing (and its own
162
+ # children Viewing/Offer) nest, mirroring Quote<-Job in construction ---
160
163
  T_E="$(make_vertical_tree '["real-agent"]' 'schema-estate-agent')"; A_E="$(make_account "$T_E")"
161
164
  export PROJECT_DIR="$T_E/platform"
162
- merge_owned_dirs_into_schema "$A_E" >/dev/null
165
+ OUT_E="$(merge_owned_dirs_into_schema "$A_E")"
166
+ assert_grep "domainBuckets=properties" "$OUT_E" "ea-domain-log"
167
+ assert_grep "roots=properties" "$OUT_E" "ea-roots-log"
168
+ assert_grep "nested=Listing<-Property,Viewing<-Listing,Offer<-Listing" "$OUT_E" "ea-nested-log"
163
169
  ALLOWED_E="$(awk '/^```allowed-top-level$/{f=1;next} /^```$/{f=0} f' "$A_E/SCHEMA.md")"
164
- # Root entities get a bucket; Listing-owned Viewing/Offer do not.
165
- for d in properties listings; do
166
- assert_grep "$d" "$ALLOWED_E" "ea-allow-$d"
167
- done
168
- for d in viewings offers; do
170
+ # Property (blank Owner) is the only root bucket.
171
+ assert_grep "properties" "$ALLOWED_E" "ea-allow-properties"
172
+ # Listing and its children nest; none is a root bucket.
173
+ for d in listings viewings offers; do
169
174
  assert_nogrep "$d" "$ALLOWED_E" "ea-noroot-$d"
170
175
  done
171
176
  assert_nogrep "jobs" "$ALLOWED_E" "ea-no-sitedesk-jobs"
172
177
  # The suppliers/ bucket is construction-only; it must not leak into another vertical.
173
178
  assert_nogrep "suppliers" "$ALLOWED_E" "ea-no-suppliers"
179
+ # The descriptive region tells the agent Listing records live under properties/.
180
+ assert_grep '`Listing` records live under `properties/` (owned by `Property`), not a root bucket.' "$(cat "$A_E/SCHEMA.md")" "ea-nested-line"
181
+
182
+ # --- roots subcommand + seed_domain_root_dirs: buckets materialise on disk ---
183
+ # estate-agent (PROJECT_DIR still $T_E/platform): properties/ is created.
184
+ ROOTS_E="$(PROJECT_DIR="$T_E/platform" python3 "$PLAT_SCRIPTS/lib/account-schema-owned-dirs.py" roots)"
185
+ assert_grep "properties" "$ROOTS_E" "ea-roots-cmd"
186
+ assert_nogrep "listings" "$ROOTS_E" "ea-roots-cmd-no-listings"
187
+ SEED_E="$(seed_domain_root_dirs "$A_E")"
188
+ assert_grep "seeded-roots=properties" "$SEED_E" "ea-seed-log"
189
+ assert_dir "$A_E/properties" "ea-seed-dir"
190
+ # Idempotent: a second run creates nothing.
191
+ SEED_E2="$(seed_domain_root_dirs "$A_E")"
192
+ assert_grep "seeded-roots=none" "$SEED_E2" "ea-seed-idempotent"
193
+
194
+ # construction: every root bucket is created; nested entities are not.
195
+ export PROJECT_DIR="$T_C/platform"
196
+ A_SEED_C="$(make_account "$T_C")"
197
+ ROOTS_C="$(PROJECT_DIR="$T_C/platform" python3 "$PLAT_SCRIPTS/lib/account-schema-owned-dirs.py" roots)"
198
+ for d in jobs customers customer-sites assets parts suppliers ppm-contracts; do
199
+ assert_grep "$d" "$ROOTS_C" "con-roots-cmd-$d"
200
+ done
201
+ seed_domain_root_dirs "$A_SEED_C" >/dev/null
202
+ for d in jobs customers customer-sites assets parts suppliers ppm-contracts; do
203
+ assert_dir "$A_SEED_C/$d" "con-seed-dir-$d"
204
+ done
205
+ for d in quotes visits purchase-orders; do
206
+ assert_nodir "$A_SEED_C/$d" "con-seed-nonested-$d"
207
+ done
208
+
209
+ # The all-accounts sweep seeds an existing account's root buckets too, so a
210
+ # sub-account (provisioned once at creation) gains properties/ on upgrade.
211
+ export PROJECT_DIR="$T_E/platform"
212
+ SWEEP_ACCTS="$(mktemp -d)"; mkdir -p "$SWEEP_ACCTS/ea1"
213
+ cp "$T_E/platform/templates/account-schema/SCHEMA.md" "$SWEEP_ACCTS/ea1/SCHEMA.md"
214
+ printf '{"accountId":"ea1","role":"client"}\n' > "$SWEEP_ACCTS/ea1/account.json"
215
+ SWEEP_E="$(reconcile_all_accounts_owned_dirs "$SWEEP_ACCTS" 2>&1)"
216
+ assert_grep "seeded-roots=properties" "$SWEEP_E" "sweep-seed-log"
217
+ assert_dir "$SWEEP_ACCTS/ea1/properties" "sweep-seed-properties-dir"
174
218
 
175
219
  # --- no vertical declared: generic base only ---
176
220
  T_N="$(make_tree '[]')"; A_N="$(make_account "$T_N")"
@@ -20,8 +20,11 @@ export USERS_FILE="/nonexistent/users.json"
20
20
 
21
21
  # Fresh account -> role=house stamped
22
22
  T1=$(mktemp -d); A1="$T1/acct-house"
23
- provision_account_dir "$A1" "aaaaaaaa-aaaa-aaaa-aaaa-aaaaaaaaaaaa" "house" >/dev/null 2>&1
23
+ OUT1="$(provision_account_dir "$A1" "aaaaaaaa-aaaa-aaaa-aaaa-aaaaaaaaaaaa" "house" 2>/dev/null)"
24
24
  assert_eq "$(role_of "$A1/account.json")" "house" "fresh-house-role"
25
+ # Task 1938 — provision seeds the vertical's root domain buckets; the log line
26
+ # proves seed_domain_root_dirs ran (bucket set depends on the brand's vertical).
27
+ assert_eq "$(printf '%s' "$OUT1" | grep -c 'seeded-roots=')" "1" "fresh-seed-roots-logged"
25
28
  assert_eq "$(ms_of "$A1/account.json")" "False" "fresh-managedService-default"
26
29
  # Task 1483 — the WhatsApp passive requirement-intake identity is seeded, non-empty.
27
30
  assert_nonempty "$A1/agents/passive/IDENTITY.md" "passive-identity-seeded"
@@ -410,9 +410,19 @@ def reconcile(project_dir, account_dir):
410
410
  f"bucket={b['dir']} expectedAtRoot=false stray={is_stray}")
411
411
 
412
412
 
413
+ def roots(project_dir):
414
+ """Print each root domain bucket dir (blank/absent Owner) of the brand's
415
+ vertical, one per line, in table order. Empty when no vertical is declared.
416
+ Provision consumes this to mkdir the operator-data buckets so they exist as
417
+ directories, not just allowed names."""
418
+ for b in resolve_domain_buckets(project_dir):
419
+ if _is_root(b["owner"]):
420
+ print(b["dir"])
421
+
422
+
413
423
  def main():
414
424
  if len(sys.argv) < 2:
415
- sys.exit("usage: account-schema-owned-dirs.py {resolve|merge|reconcile} [account_dir]")
425
+ sys.exit("usage: account-schema-owned-dirs.py {resolve|merge|reconcile|roots} [account_dir]")
416
426
  cmd = sys.argv[1]
417
427
  pd = _project_dir()
418
428
  if cmd == "resolve":
@@ -421,6 +431,8 @@ def main():
421
431
  merge(pd, sys.argv[2])
422
432
  elif cmd == "reconcile":
423
433
  reconcile(pd, sys.argv[2])
434
+ elif cmd == "roots":
435
+ roots(pd)
424
436
  else:
425
437
  sys.exit(f"unknown command: {cmd}")
426
438
 
@@ -17,9 +17,30 @@ merge_owned_dirs_into_schema() {
17
17
  echo " [acct-schema] op=seed-owned-dirs ${_out}"
18
18
  }
19
19
 
20
+ # seed_domain_root_dirs <account_dir>
21
+ # mkdir each root domain bucket the brand's vertical projects (Property ->
22
+ # properties/ for estate-agent, Job/Customer/... for construction), so the
23
+ # operator-data buckets exist as directories, not just allowed names. Idempotent.
24
+ # Logs the buckets created so a provision can be audited from its log.
25
+ seed_domain_root_dirs() {
26
+ local _acct="$1"
27
+ local _created=""
28
+ local _d
29
+ while IFS= read -r _d; do
30
+ [ -n "$_d" ] || continue
31
+ if [ ! -d "$_acct/$_d" ]; then
32
+ mkdir -p "$_acct/$_d"
33
+ _created="${_created:+$_created,}$_d"
34
+ fi
35
+ done < <(PROJECT_DIR="$PROJECT_DIR" python3 "$_ACCT_SCHEMA_PY" roots 2>/dev/null)
36
+ echo " [acct-schema] seeded-roots=${_created:-none}"
37
+ }
38
+
20
39
  # reconcile_all_accounts_owned_dirs <accounts_dir>
21
40
  # Standing check + backfill: for every account dir with an account.json, log the
22
- # pre-merge present state of each declared owned dir, then merge (backfill).
41
+ # pre-merge present state of each declared owned dir, merge (backfill), then seed
42
+ # the vertical's root buckets so an existing account (sub-accounts are only
43
+ # provisioned once, at creation) gains the same directories a fresh one gets.
23
44
  reconcile_all_accounts_owned_dirs() {
24
45
  local _accts="$1"
25
46
  [ -d "$_accts" ] || return 0
@@ -29,5 +50,6 @@ reconcile_all_accounts_owned_dirs() {
29
50
  PROJECT_DIR="$PROJECT_DIR" python3 "$_ACCT_SCHEMA_PY" reconcile "$_acct" 2>/dev/null \
30
51
  | while IFS= read -r _line; do echo " [acct-schema] op=reconcile ${_line}"; done
31
52
  merge_owned_dirs_into_schema "$_acct"
53
+ seed_domain_root_dirs "$_acct"
32
54
  done
33
55
  }
@@ -45,6 +45,11 @@ provision_account_dir() {
45
45
  # seeded SCHEMA.md so the guard admits them (e.g. quoting/ on SiteDesk).
46
46
  merge_owned_dirs_into_schema "$ACCOUNT_DIR"
47
47
 
48
+ # Create the vertical's root domain buckets on disk (Property -> properties/
49
+ # for estate-agent, Job/Customer/... for construction) so they are present
50
+ # directories, not just allowed names the operator never sees.
51
+ seed_domain_root_dirs "$ACCOUNT_DIR"
52
+
48
53
  # Claude Code discovers project-level .claude/ relative to the nearest .git
49
54
  # root. Without a .git in the account dir it traverses up to ~/maxy/.git and
50
55
  # misses accountDir/.claude/. Initialise a repo so the account dir IS the root.
@@ -5,12 +5,12 @@
5
5
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
6
6
  <title>Activity — Maxy</title>
7
7
  <link rel="icon" href="/favicon.ico">
8
- <script type="module" crossorigin src="/assets/activity-2DL2DwLr.js"></script>
8
+ <script type="module" crossorigin src="/assets/activity-CElZcdjR.js"></script>
9
9
  <link rel="modulepreload" crossorigin href="/assets/chunk-TPjIAO9U.js">
10
- <link rel="modulepreload" crossorigin href="/assets/useSubAccountSwitcher-Q941cZYV.js">
11
- <link rel="modulepreload" crossorigin href="/assets/AdminShell-BwNqwb4k.js">
12
- <link rel="modulepreload" crossorigin href="/assets/triangle-alert-7mQfCQWP.js">
13
- <link rel="stylesheet" crossorigin href="/assets/useSubAccountSwitcher-Bgfqig1V.css">
10
+ <link rel="modulepreload" crossorigin href="/assets/useSubAccountSwitcher-DDStL7Nt.js">
11
+ <link rel="modulepreload" crossorigin href="/assets/AdminShell-ClIT8c0K.js">
12
+ <link rel="modulepreload" crossorigin href="/assets/triangle-alert-C5BpoPlq.js">
13
+ <link rel="stylesheet" crossorigin href="/assets/useSubAccountSwitcher-DnfX9Uxe.css">
14
14
  <link rel="stylesheet" href="/brand-defaults.css">
15
15
  </head>
16
16
  <body>
@@ -1 +1 @@
1
- import{o as e}from"./chunk-TPjIAO9U.js";import{I as t,P as n,R as r,U as i,z as a}from"./useSubAccountSwitcher-Q941cZYV.js";import{D as o}from"./useVoiceRecorder-ZFwt5i6d.js";import{_ as s,v as c,y as l}from"./AdminShell-BwNqwb4k.js";var u=`admin-landing-redirected`,d=`/graph`;function f(e){return e.variant===`operator`?!1:e.appState===`chat`&&!e.alreadyRedirected}var p=e(i(),1);function m(e=`admin`){let[t,n]=(0,p.useState)(`loading`),[r,i]=(0,p.useState)(``),[s,c]=(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`){a(`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`){a(`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{}i(``),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`){a(`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}i(``),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 l())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{}i(``),h(``),n(`enter-pin`)},[]);return(0,p.useEffect)(()=>{Y.current=$},[$]),{appState:t,setAppState:n,pin:r,setPin:i,operatorName:s,setOperatorName:c,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:r,setPin:i,showPin:a,setShowPin:o,pinLoading:l,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:n.productName,className:`connect-logo connect-logo--maxy`}),!n.logoContainsName&&(0,h.jsxs)(`h1`,{className:`connect-title`,children:[`Welcome to `,n.productName]}),(0,h.jsxs)(`p`,{className:`connect-subtitle`,children:[`Tell `,n.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:r,onChange:i,onComplete:()=>{},showPin:a}),(0,h.jsx)(s,{variant:`send`,type:`submit`,disabled:!r||!m.trim(),loading:l,"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)(c,{checked:a,onChange:()=>o(e=>!e),label:`Show PIN`})]}),u&&(0,h.jsx)(`p`,{className:`admin-pin-error`,children:u})]})})}function v(e){let{pin:r,setPin:i,showPin:a,setShowPin:o,pinLoading:l,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:n.productName,className:`connect-logo connect-logo--maxy`}),!n.logoContainsName&&(0,h.jsx)(`h1`,{className:`connect-title`,children:n.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:r,onChange:i,onComplete:()=>{},showPin:a,autoFocus:!0}),(0,h.jsx)(s,{variant:`send`,type:`submit`,disabled:!r,loading:l,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)(c,{checked:a,onChange:()=>o(e=>!e),label:`Show PIN`})})]}),u&&(0,h.jsx)(`p`,{className:`admin-pin-error`,children:u})]})]})}function y(e){let{authPolling:r,setAuthPolling:i,authLoading:a,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){i(!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.`),i(!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`})}),i(!1),l(``)}return r||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:[r?(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:r?`Sign in and authorize in the browser below.`:`Open your email or prepare your accounts, then sign in.`}),!r&&(0,h.jsx)(`div`,{style:{marginTop:`12px`},children:(0,h.jsx)(s,{variant:`primary`,onClick:T,disabled:a,children:a?(0,h.jsxs)(h.Fragment,{children:[(0,h.jsx)(`span`,{className:`spin`,style:{display:`inline-block`},children:`✱`}),` Connecting…`]}):`Sign in to Claude`})}),r&&_===`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:n.productName,className:`connect-logo connect-logo--maxy`}),!n.logoContainsName&&(0,h.jsx)(`span`,{className:`connect-logo-label`,children:n.productName})]})]}),(0,h.jsxs)(`h1`,{className:`connect-title`,children:[`Connect Claude to power `,n.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:a,children:a?(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-TPjIAO9U.js";import{I as t,P as n,R as r,U as i,z as a}from"./useSubAccountSwitcher-DDStL7Nt.js";import{D as o}from"./useVoiceRecorder-kqMitFlk.js";import{_ as s,v as c,y as l}from"./AdminShell-ClIT8c0K.js";var u=`admin-landing-redirected`,d=`/graph`;function f(e){return e.variant===`operator`?!1:e.appState===`chat`&&!e.alreadyRedirected}var p=e(i(),1);function m(e=`admin`){let[t,n]=(0,p.useState)(`loading`),[r,i]=(0,p.useState)(``),[s,c]=(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`){a(`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`){a(`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{}i(``),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`){a(`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}i(``),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 l())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{}i(``),h(``),n(`enter-pin`)},[]);return(0,p.useEffect)(()=>{Y.current=$},[$]),{appState:t,setAppState:n,pin:r,setPin:i,operatorName:s,setOperatorName:c,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:r,setPin:i,showPin:a,setShowPin:o,pinLoading:l,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:n.productName,className:`connect-logo connect-logo--maxy`}),!n.logoContainsName&&(0,h.jsxs)(`h1`,{className:`connect-title`,children:[`Welcome to `,n.productName]}),(0,h.jsxs)(`p`,{className:`connect-subtitle`,children:[`Tell `,n.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:r,onChange:i,onComplete:()=>{},showPin:a}),(0,h.jsx)(s,{variant:`send`,type:`submit`,disabled:!r||!m.trim(),loading:l,"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)(c,{checked:a,onChange:()=>o(e=>!e),label:`Show PIN`})]}),u&&(0,h.jsx)(`p`,{className:`admin-pin-error`,children:u})]})})}function v(e){let{pin:r,setPin:i,showPin:a,setShowPin:o,pinLoading:l,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:n.productName,className:`connect-logo connect-logo--maxy`}),!n.logoContainsName&&(0,h.jsx)(`h1`,{className:`connect-title`,children:n.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:r,onChange:i,onComplete:()=>{},showPin:a,autoFocus:!0}),(0,h.jsx)(s,{variant:`send`,type:`submit`,disabled:!r,loading:l,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)(c,{checked:a,onChange:()=>o(e=>!e),label:`Show PIN`})})]}),u&&(0,h.jsx)(`p`,{className:`admin-pin-error`,children:u})]})]})}function y(e){let{authPolling:r,setAuthPolling:i,authLoading:a,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){i(!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.`),i(!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`})}),i(!1),l(``)}return r||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:[r?(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:r?`Sign in and authorize in the browser below.`:`Open your email or prepare your accounts, then sign in.`}),!r&&(0,h.jsx)(`div`,{style:{marginTop:`12px`},children:(0,h.jsx)(s,{variant:`primary`,onClick:T,disabled:a,children:a?(0,h.jsxs)(h.Fragment,{children:[(0,h.jsx)(`span`,{className:`spin`,style:{display:`inline-block`},children:`✱`}),` Connecting…`]}):`Sign in to Claude`})}),r&&_===`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:n.productName,className:`connect-logo connect-logo--maxy`}),!n.logoContainsName&&(0,h.jsx)(`span`,{className:`connect-logo-label`,children:n.productName})]})]}),(0,h.jsxs)(`h1`,{className:`connect-title`,children:[`Connect Claude to power `,n.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:a,children:a?(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,2 @@
1
+ import{o as e}from"./chunk-TPjIAO9U.js";import{C as t,D as n,E as r,F as i,H as a,L as o,M as s,N as c,O as l,P as u,R as d,S as f,T as p,U as m,_ as h,a as g,b as _,d as ee,f as te,g as v,h as y,j as b,k as x,m as S,o as ne,r as C,t as re,u as ie,v as ae,w as oe,x as se,y as w}from"./useSubAccountSwitcher-DDStL7Nt.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 T=d();function E({checked:e,onChange:t,label:n,disabled:r,ariaLabel:i=n}){return(0,T.jsxs)(`label`,{className:`maxy-checkbox${r?` maxy-checkbox--disabled`:``}`,children:[(0,T.jsx)(`input`,{type:`checkbox`,"aria-label":i,checked:e,onChange:e=>t(e.target.checked),disabled:r}),(0,T.jsx)(`span`,{className:`maxy-checkbox__box`,children:`✱`}),n&&(0,T.jsx)(`span`,{className:`maxy-checkbox__label`,children:n})]})}var D=e(m(),1),le={sm:14,md:16,lg:18},O={sm:30,md:38,lg:46};function k({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,"aria-pressed":u,style:d,className:f,children:p}){let m=[`btn`,`btn--${e}`,t===`md`?``:`btn--${t}`,a?`btn--full`:``,f].filter(Boolean).join(` `),h=le[t],g={...e===`send`?{width:O[t],height:O[t]}:{},...d},_=Object.keys(g).length>0;return(0,T.jsxs)(`button`,{type:s,className:m,disabled:i||o,onClick:c,"aria-label":l,"aria-pressed":u,style:_?g:void 0,children:[(0,T.jsxs)(`span`,{className:`btn__content`,style:{visibility:i?`hidden`:`visible`},children:[n&&r===`leading`&&(0,T.jsx)(n,{size:h}),p,n&&r===`trailing`&&(0,T.jsx)(n,{size:h})]}),i&&(0,T.jsx)(`span`,{className:`btn__spinner`,children:`✱`})]})}var ue=c(`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`}]]),de=c(`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`}]]),fe=c(`ellipsis-vertical`,[[`circle`,{cx:`12`,cy:`12`,r:`1`,key:`41hilf`}],[`circle`,{cx:`12`,cy:`5`,r:`1`,key:`gxeob9`}],[`circle`,{cx:`12`,cy:`19`,r:`1`,key:`lyex9k`}]]),A=c(`gauge`,[[`path`,{d:`m12 14 4-4`,key:`9kzdfg`}],[`path`,{d:`M3.34 19a10 10 0 1 1 17.32 0`,key:`19p75a`}]]),pe=c(`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`}]]),me=c(`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`}]]),he=c(`panel-left`,[[`rect`,{width:`18`,height:`18`,x:`3`,y:`3`,rx:`2`,key:`afitv7`}],[`path`,{d:`M9 3v18`,key:`fh3hqa`}]]),ge=c(`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=c(`waypoints`,[[`path`,{d:`m10.586 5.414-5.172 5.172`,key:`4mc350`}],[`path`,{d:`m18.586 13.414-5.172 5.172`,key:`8c96vv`}],[`path`,{d:`M6 12h12`,key:`8npq4p`}],[`circle`,{cx:`12`,cy:`20`,r:`2`,key:`144qzu`}],[`circle`,{cx:`12`,cy:`4`,r:`2`,key:`muu5ef`}],[`circle`,{cx:`20`,cy:`12`,r:`2`,key:`1xzzfp`}],[`circle`,{cx:`4`,cy:`12`,r:`2`,key:`1hvhnz`}]]);function ve({connected:e,onConnectClaude:t}){return e?(0,T.jsxs)(`span`,{className:`claude-status-pill`,"data-connected":`true`,title:`Claude is connected`,children:[(0,T.jsx)(`img`,{src:`/brand/claude.png`,alt:``,className:`claude-status-pill__mark`}),(0,T.jsx)(`span`,{className:`claude-status-pill__label`,children:`Connected`}),(0,T.jsx)(`span`,{className:`claude-status-pill__dot claude-status-pill__dot--live`,"aria-hidden":`true`})]}):(0,T.jsxs)(`button`,{type:`button`,className:`claude-status-pill claude-status-pill--action`,"data-connected":`false`,onClick:t,title:`Connect Claude`,children:[(0,T.jsx)(`img`,{src:`/brand/claude.png`,alt:``,className:`claude-status-pill__mark`}),(0,T.jsx)(`span`,{className:`claude-status-pill__label`,children:`Connect`}),(0,T.jsx)(`span`,{className:`claude-status-pill__dot claude-status-pill__dot--down`,"aria-hidden":`true`})]})}function ye(e){return e===`/`||e===``?`Dashboard`:e.startsWith(`/chat`)?`Chat`:e.startsWith(`/tasks`)?`Tasks`:e.startsWith(`/data`)?`Data`:e.startsWith(`/calendar`)?`Calendar`:e.startsWith(`/graph`)?`Graph`:e.startsWith(`/activity`)?`Activity`:e.startsWith(`/browser`)?`Browser`:`Dashboard`}function be({title:e,sidebarOpen:n,onToggleSidebar:r,claudeConnected:i,onConnectClaude:a}){let o=e??ye(typeof window<`u`?window.location.pathname:`/`),s=i!==void 0&&a!==void 0;return(0,T.jsxs)(`header`,{className:`admin-page-header`,children:[(0,T.jsxs)(`button`,{type:`button`,className:`admin-page-header__toggle`,"aria-label":n?`Hide sidebar`:`Show sidebar`,title:n?`Hide sidebar`:`Show sidebar`,"aria-expanded":n,onClick:r,children:[(0,T.jsx)(he,{className:`admin-page-header__toggle-desktop`,size:18,strokeWidth:1.75}),(0,T.jsx)(t,{className:`admin-page-header__toggle-mobile`,size:22,strokeWidth:1.75})]}),(0,T.jsx)(`h1`,{className:`admin-page-header__title`,children:o}),s&&(0,T.jsx)(`div`,{className:`admin-page-header__right`,children:(0,T.jsx)(ve,{connected:i,onConnectClaude:a})})]})}var xe=[{label:`Home`,href:`/`,Icon:p,match:e=>e===`/`||e===``},{label:`Chat`,href:`/chat`,Icon:f,match:e=>e.startsWith(`/chat`)},{label:`Tasks`,href:`/tasks`,Icon:pe,match:e=>e.startsWith(`/tasks`)},{label:`Data`,href:`/data`,Icon:x,match:e=>e.startsWith(`/data`)},{label:`Calendar`,href:`/calendar`,Icon:b,match:e=>e.startsWith(`/calendar`)}],Se=[{label:`Chat`,href:`/`,Icon:f,match:e=>e===`/`||e===``||e.startsWith(`/chat`)},{label:`Data`,href:`/data`,Icon:x,match:e=>e.startsWith(`/data`)}];function Ce(e){let t=xe.find(t=>t.match(e));return t?t.href:`/`}function j({variant:e=`admin`,onOpenConversations:t}={}){let n=typeof window<`u`?window.location.pathname:`/`,r=e===`operator`?Se:xe,i=e===`operator`?Se.find(e=>e.match(n))?.href??`/`:Ce(n),a=e=>{let t=e.href===i,{Icon:n}=e;return(0,T.jsxs)(`a`,{href:e.href,className:`bottom-tab${t?` is-active`:``}`,"aria-current":t?`page`:void 0,children:[(0,T.jsx)(n,{size:19,strokeWidth:1.75}),(0,T.jsx)(`span`,{className:`bottom-tab__label`,children:e.label})]},e.href)};return(0,T.jsxs)(`nav`,{className:`bottom-tab-bar`,"aria-label":`Primary`,children:[r.slice(0,1).map(a),e===`operator`&&t&&(0,T.jsxs)(`button`,{type:`button`,className:`bottom-tab`,onClick:t,children:[(0,T.jsx)(f,{size:19,strokeWidth:1.75}),(0,T.jsx)(`span`,{className:`bottom-tab__label`,children:`Conversations`})]}),r.slice(1).map(a)]})}var we=`maxy-shell-side-px`;function Te(){if(typeof window>`u`)return 0;let e=document.querySelector(`.platform > .artefact`)?.getBoundingClientRect();return e&&e.width>0?Math.round(e.width):0}function M(e){if(typeof window>`u`)return e;let t=window.innerWidth,n=Math.max(248,t-480-Te());return Math.min(Math.max(e,248),n)}function Ee(){if(typeof window>`u`)return 264;try{let e=window.localStorage.getItem(we);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 M(t)}catch{}return 264}function De({targetSelector:e=`.platform`}){let t=(0,D.useRef)(null),[n,r]=(0,D.useState)(()=>Ee()),i=(0,D.useRef)(n);(0,D.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,D.useCallback)(()=>{r(e=>{let t=M(e);return t===e?e:t})},[]);(0,D.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(M(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(we,String(t))}catch{}console.info(`[admin-ui] sidebar-resize px=${t}`)};window.addEventListener(`pointermove`,o),window.addEventListener(`pointerup`,s)},s=()=>{let e=M(264);r(e);try{window.localStorage.removeItem(we)}catch{}console.info(`[admin-ui] sidebar-resize px=${e}`)};return(0,T.jsx)(`div`,{ref:t,className:`side-resize-handle`,role:`separator`,"aria-orientation":`vertical`,"aria-label":`Resize sidebar`,onPointerDown:o,onDoubleClick:s})}var Oe=a();function ke(e){return Math.max(14,e/2-386)}function Ae(e){return e.left===0&&e.top===0&&e.width===0&&e.height===0}var N={position:`fixed`,visibility:`hidden`};function P({anchorRef:e,onClose:t,className:n,role:r,ariaLabel:i,anchorId:a,children:o}){let s=(0,D.useRef)(null),[c,l]=(0,D.useState)(N),u=(0,D.useRef)(null),d=(0,D.useCallback)(()=>{let t=s.current;if(!t)return;let r=e.current,i=[n,a].filter(Boolean).join(`:`)||`unknown`,o=t.getBoundingClientRect(),c=window.innerWidth,d=window.innerHeight,f=o.width>0&&o.height>0,p=r?r.getBoundingClientRect():null,m=(e,t)=>console.error(`[anchored-popover] op=offscreen id=${i} left=${e} top=${t} w=${o.width} h=${o.height} viewport=${c},${d}`),h=e=>{e!==u.current&&(u.current=e,console.log(e))};if(h(`[anchored-popover] op=anchor id=${i} present=${!!r} rect=${p?`${p.left},${p.top},${p.width},${p.height}`:`none`}`),!p){let e=Math.max(4,c-o.width-ke(c)),t=Math.max(4,d-o.height-14);l({position:`fixed`,left:e,top:t,visibility:`visible`}),h(`[anchored-popover] op=placed id=${i} left=${e} top=${t} w=${o.width} h=${o.height} flipped=false clampedLeft=false clampedRight=false`);return}if(f&&Ae(p)){l(N),m(p.left,p.top);return}let g=p.right-o.width,_=c-o.width-4,ee=!1,te=!1;g>_&&(g=_,ee=!0),g<4&&(g=4,te=!0);let v=d-p.bottom-4,y=p.top-4,b=o.height+8<=v?!1:o.height+8<=y?!0:y>v,x=Math.max(0,b?y:v),S=b?Math.max(4,p.top-Math.min(o.height,x)):p.bottom;l({position:`fixed`,left:g,top:S,maxHeight:x,visibility:`visible`}),h(`[anchored-popover] op=placed id=${i} left=${g} top=${S} w=${o.width} h=${o.height} maxH=${x} flipped=${b} clampedLeft=${te} clampedRight=${ee}`);let ne=Math.min(o.height,x);f&&(g+o.width<=0||g>=c||S+ne<=0||S>=d)&&m(g,S)},[e,a,n]);return(0,D.useLayoutEffect)(()=>{if(d(),typeof ResizeObserver>`u`)return;let e=new ResizeObserver(()=>d());return s.current&&e.observe(s.current),()=>e.disconnect()},[d]),(0,D.useEffect)(()=>{let n=e=>{e.key===`Escape`&&t()},r=n=>{let r=n.target;e.current?.contains(r)||s.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,Oe.createPortal)((0,T.jsx)(`div`,{ref:s,className:n,role:r,"aria-label":i,style:c,children:o}),document.body)}function je({actions:e,disabled:n}){let[r,i]=(0,D.useState)(!1),[a,o]=(0,D.useState)(null),s=(0,D.useRef)(null),c=(0,D.useCallback)(()=>{i(!1),o(null)},[]);return(0,T.jsxs)(`div`,{className:`conv-actions`,children:[(0,T.jsx)(`button`,{ref:s,type:`button`,className:`conv-action conv-actions-overflow`,onClick:()=>i(e=>!e),disabled:n,"aria-haspopup":`menu`,"aria-expanded":r,"aria-label":`Session actions`,title:`Session actions`,children:(0,T.jsx)(t,{size:12})}),r&&(0,T.jsx)(P,{anchorRef:s,onClose:c,className:`conv-actions-menu`,role:`menu`,children:e.map(e=>e.panel?(0,T.jsxs)(`div`,{className:`conv-actions-menu-disclosure`,children:[(0,T.jsxs)(`button`,{type:`button`,role:`menuitem`,"aria-haspopup":`dialog`,"aria-expanded":a===e.key,disabled:n,onClick:()=>o(t=>t===e.key?null:e.key),children:[e.icon,(0,T.jsx)(`span`,{children:e.menuLabel})]}),a===e.key&&(0,T.jsx)(`div`,{className:`conv-actions-menu-panel`,children:e.panel()})]},e.key):(0,T.jsxs)(`button`,{type:`button`,role:`menuitem`,className:e.danger?`conv-action-danger`:void 0,"aria-busy":e.busy,disabled:n,onClick:t=>{e.onClick?.(t),c()},children:[e.icon,(0,T.jsx)(`span`,{children:e.menuLabel})]},e.key))})]})}var F=`claude-opus-4-8[1m]`,Me=`claude-sonnet-5`,I=`claude-haiku-4-5`,Ne={[F]:`Opus 4.8 (1M context)`,[Me]:`Sonnet 5`,[I]:`Haiku 4.5`};function Pe(e){return Ne[e]??e}var L=[F,Me,I];function R(e){return e.replace(/\[1m\]$/,``)}function z(e){return L.find(t=>R(t)===R(e))??e}var B=[`default`,`acceptEdits`,`plan`,`auto`,`bypassPermissions`],Fe=[`low`,`medium`,`high`,`xhigh`];[...B],[...Fe],[...Fe];var Ie=[F,Me,I],Le={default:`Ask permissions`,acceptEdits:`Accept edits`,plan:`Plan mode`,auto:`Auto mode`,bypassPermissions:`Bypass permissions`},Re=B.map(e=>({value:e,label:Le[e]??e})),ze={low:`Low`,medium:`Medium`,high:`High`,xhigh:`Highest`},Be=Fe.map(e=>({value:e,label:ze[e]??e}));function Ve(e){if(e){let t=Ie.find(t=>R(t)===R(e));if(t)return t}return F}function He({row:e,adminFetch:t,onError:n}){let[r,i]=(0,D.useState)(()=>Ve(e.model)),[a,o]=(0,D.useState)(``),[s,c]=(0,D.useState)(``),[l,u]=(0,D.useState)(!1),d=(0,D.useRef)(!1);(0,D.useEffect)(()=>{i(Ve(e.model))},[e.model]);let f=async()=>{if(!d.current){d.current=!0,u(!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}`),d.current=!1,u(!1);return}let o=await i.json().catch(()=>({}));o.target?window.location.assign(o.target):(n(`Reset of ${e.title} returned no target`),d.current=!1,u(!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)}`),d.current=!1,u(!1)}}};return(0,T.jsxs)(T.Fragment,{children:[(0,T.jsxs)(`label`,{className:`reseat-field`,children:[(0,T.jsx)(`span`,{children:`Model`}),(0,T.jsx)(`select`,{"data-kind":`model`,value:r,disabled:l,onChange:e=>i(e.target.value),children:Ie.map(e=>(0,T.jsx)(`option`,{value:e,children:Pe(e)},e))})]}),(0,T.jsxs)(`label`,{className:`reseat-field`,children:[(0,T.jsx)(`span`,{children:`Mode`}),(0,T.jsxs)(`select`,{"data-kind":`mode`,value:a,disabled:l,onChange:e=>o(e.target.value),children:[(0,T.jsx)(`option`,{value:``,children:`Keep current`}),Re.map(e=>(0,T.jsx)(`option`,{value:e.value,children:e.label},e.value))]})]}),(0,T.jsxs)(`label`,{className:`reseat-field`,children:[(0,T.jsx)(`span`,{children:`Effort`}),(0,T.jsxs)(`select`,{"data-kind":`effort`,value:s,disabled:l,onChange:e=>c(e.target.value),children:[(0,T.jsx)(`option`,{value:``,children:`Keep current`}),Be.map(e=>(0,T.jsx)(`option`,{value:e.value,children:e.label},e.value))]})]}),(0,T.jsx)(`button`,{type:`button`,className:`reseat-apply`,disabled:l,"aria-busy":l,onClick:()=>void f(),children:l?(0,T.jsxs)(T.Fragment,{children:[(0,T.jsx)(oe,{size:12,className:`spin`,"aria-hidden":`true`}),`Resetting…`]}):`Reset`})]})}function Ue(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 We(e){return e>=1e3?`${(e/1e3).toFixed(1)}k`:String(e)}function Ge({target:e,anchorEl:t,onConfirm:n,onCancel:r}){let i=(0,D.useRef)(null);return i.current=t,e?(0,T.jsxs)(P,{anchorRef:i,onClose:r,className:`conv-delete-confirm`,role:`alertdialog`,ariaLabel:`Confirm delete session`,children:[(0,T.jsxs)(`div`,{className:`claude-info-header`,children:[(0,T.jsx)(`span`,{children:`Delete this conversation?`}),(0,T.jsx)(`button`,{className:`claude-info-close`,onClick:r,"aria-label":`Close`,children:`✕`})]}),(0,T.jsxs)(`div`,{className:`claude-info-section`,style:{padding:`12px 14px`,fontSize:`11px`,color:`var(--text-secondary)`},children:[(0,T.jsxs)(`div`,{className:`conv-delete-target`,children:[(0,T.jsx)(`span`,{className:`conv-delete-label`,title:e.title,children:e.title||`Untitled session`}),(0,T.jsx)(`code`,{className:`conv-delete-id`,title:e.sessionId,children:e.sessionId.slice(0,8)})]}),(0,T.jsx)(`div`,{style:{marginTop:`8px`},children:`This permanently removes the transcript. It is not moved to Archive and cannot be recovered.`}),e.live&&(0,T.jsx)(`div`,{style:{marginTop:`8px`},children:`This session is running; deleting stops it first.`})]}),(0,T.jsxs)(`div`,{className:`claude-info-section`,style:{display:`flex`,gap:`8px`,padding:`10px 14px`},children:[(0,T.jsx)(k,{variant:`danger`,size:`sm`,style:{flex:1},onClick:n,children:`Delete`}),(0,T.jsx)(k,{variant:`secondary`,size:`sm`,style:{flex:1},onClick:r,children:`Cancel`})]})]}):null}function Ke({open:e,count:t,liveCount:n,onConfirm:r,onCancel:i}){if(!e)return null;let a=t===1?``:`s`;return(0,T.jsx)(`div`,{className:`claude-info-overlay`,onClick:i,children:(0,T.jsxs)(`div`,{className:`claude-info-modal`,onClick:e=>e.stopPropagation(),role:`alertdialog`,"aria-label":`Confirm delete sessions`,children:[(0,T.jsxs)(`div`,{className:`claude-info-header`,children:[(0,T.jsxs)(`span`,{children:[`Delete `,t,` conversation`,a,`?`]}),(0,T.jsx)(`button`,{className:`claude-info-close`,onClick:i,"aria-label":`Close`,children:`✕`})]}),(0,T.jsxs)(`div`,{className:`claude-info-section`,style:{padding:`12px 14px`,fontSize:`11px`,color:`var(--text-secondary)`},children:[`This permanently removes `,t,` transcript`,a,`. `,t===1?`It is`:`They are`,` not moved to Archive and cannot be recovered.`,n>0&&(0,T.jsxs)(`div`,{style:{marginTop:`8px`},children:[n,` `,n===1?`is`:`are`,` running and will be stopped first.`]})]}),(0,T.jsxs)(`div`,{className:`claude-info-section`,style:{display:`flex`,gap:`8px`,padding:`10px 14px`},children:[(0,T.jsxs)(k,{variant:`danger`,size:`sm`,style:{flex:1},onClick:r,children:[`Delete `,t]}),(0,T.jsx)(k,{variant:`secondary`,size:`sm`,style:{flex:1},onClick:i,children:`Cancel`})]})]})})}var qe=`auth-refresh-failed`;function Je({error:e,onClose:t}){if(!e)return null;let n=e.reason===qe,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,T.jsx)(`div`,{className:`claude-info-overlay`,onClick:t,children:(0,T.jsxs)(`div`,{className:`claude-info-modal`,onClick:e=>e.stopPropagation(),role:`alertdialog`,"aria-label":`Session could not be opened`,children:[(0,T.jsxs)(`div`,{className:`claude-info-header`,children:[(0,T.jsx)(`span`,{children:r}),(0,T.jsx)(`button`,{className:`claude-info-close`,onClick:t,"aria-label":`Close`,children:`✕`})]}),(0,T.jsxs)(`div`,{className:`claude-info-section`,style:{padding:`12px 14px`,fontSize:`11px`,color:`var(--text-secondary)`},children:[i,(0,T.jsxs)(`div`,{className:`claude-info-row`,style:{marginTop:`8px`},children:[(0,T.jsx)(`span`,{className:`claude-info-label`,children:`Reason`}),(0,T.jsx)(`span`,{className:`claude-info-value`,children:e.reason})]}),e.sessionId&&(0,T.jsxs)(`div`,{className:`claude-info-row`,children:[(0,T.jsx)(`span`,{className:`claude-info-label`,children:`Session`}),(0,T.jsxs)(`span`,{className:`claude-info-value`,children:[e.sessionId.slice(0,8),`…`]})]})]})]})})}function Ye(e){let{show:t,onClose:n,claudeInfo:r,messages:i,sessionElapsed:a,sessionId:o,cacheKey:s}=e,[c,l]=(0,D.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,_=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,T.jsx)(`div`,{className:`claude-info-overlay`,onClick:n,children:(0,T.jsxs)(`div`,{className:`claude-info-modal`,onClick:e=>e.stopPropagation(),children:[(0,T.jsxs)(`div`,{className:`claude-info-header`,children:[(0,T.jsx)(`img`,{src:`/brand/claude.png`,alt:`Claude`,className:`claude-info-icon`}),(0,T.jsx)(`span`,{children:`Claude Code`}),(0,T.jsx)(`button`,{className:`claude-info-close`,onClick:n,"aria-label":`Close`,children:`✕`})]}),(0,T.jsxs)(`div`,{className:`claude-info-section`,children:[(0,T.jsxs)(`div`,{className:`claude-info-row`,children:[(0,T.jsx)(`span`,{className:`claude-info-label`,children:`Version`}),(0,T.jsx)(`span`,{className:`claude-info-value`,children:r?r.version:`…`})]}),(0,T.jsxs)(`div`,{className:`claude-info-row`,children:[(0,T.jsx)(`span`,{className:`claude-info-label`,children:`Email`}),(0,T.jsx)(`span`,{className:`claude-info-value`,children:r?.account?.email??`…`})]})]}),(g||m||h>0)&&(0,T.jsxs)(`div`,{className:`claude-info-section`,children:[g&&(0,T.jsxs)(`div`,{className:`claude-info-row`,children:[(0,T.jsx)(`span`,{className:`claude-info-label`,children:`Plan`}),(0,T.jsx)(`span`,{className:`claude-info-value`,style:{textTransform:`capitalize`},children:g})]}),m&&(0,T.jsxs)(T.Fragment,{children:[(0,T.jsxs)(`div`,{className:`claude-info-row`,children:[(0,T.jsx)(`span`,{className:`claude-info-label`,children:`Usage`}),(0,T.jsxs)(`span`,{className:`claude-info-value`,children:[Math.round(m.utilization*100),`%`]})]}),(0,T.jsxs)(`div`,{className:`claude-info-row`,children:[(0,T.jsx)(`span`,{className:`claude-info-label`,children:`Resets in`}),(0,T.jsx)(`span`,{className:`claude-info-value`,children:_(m.resetsAt)})]}),m.isUsingOverage&&(0,T.jsxs)(`div`,{className:`claude-info-row`,children:[(0,T.jsx)(`span`,{className:`claude-info-label`,children:`Overage`}),(0,T.jsx)(`span`,{className:`claude-info-value`,children:`Active`})]})]}),h>0&&(0,T.jsxs)(`div`,{className:`claude-info-row`,children:[(0,T.jsx)(`span`,{className:`claude-info-label`,children:`Session cost`}),(0,T.jsxs)(`span`,{className:`claude-info-value`,children:[`$`,h<.01?h.toFixed(4):h.toFixed(2)]})]})]}),(0,T.jsxs)(`div`,{className:`claude-info-section`,children:[(0,T.jsxs)(`div`,{className:`claude-info-row`,children:[(0,T.jsx)(`span`,{className:`claude-info-label`,children:`Model`}),(0,T.jsx)(`span`,{className:`claude-info-value`,children:r?.model??`…`})]}),(0,T.jsxs)(`div`,{className:`claude-info-row`,children:[(0,T.jsx)(`span`,{className:`claude-info-label`,children:`Context used`}),(0,T.jsx)(`span`,{className:`claude-info-value`,children:f>0?`${f}%`:`—`})]}),(0,T.jsxs)(`div`,{className:`claude-info-row`,children:[(0,T.jsx)(`span`,{className:`claude-info-label`,children:`Tokens`}),(0,T.jsx)(`span`,{className:`claude-info-value`,children:p>0?We(p):`—`})]}),(0,T.jsxs)(`div`,{className:`claude-info-row`,children:[(0,T.jsx)(`span`,{className:`claude-info-label`,children:`Session`}),(0,T.jsx)(`span`,{className:`claude-info-value`,children:Ue(a)})]}),(o||s)&&(()=>{let e=o??s??``;return(0,T.jsxs)(`div`,{className:`claude-info-row`,children:[(0,T.jsx)(`span`,{className:`claude-info-label`,children:`Session`}),(0,T.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 C(e)?`copied`:`failed`),setTimeout(()=>l(null),1200)},children:c===`copied`?`copied ✓`:c===`failed`?`copy failed ✕`:`${e.slice(0,8)}…`})]})})()]})]})})}function Xe({open:e,onConnect:t,onClose:n}){return e?(0,T.jsx)(`div`,{className:`claude-info-overlay`,onClick:n,children:(0,T.jsxs)(`div`,{className:`claude-info-modal`,onClick:e=>e.stopPropagation(),role:`alertdialog`,"aria-label":`Claude is not connected`,children:[(0,T.jsxs)(`div`,{className:`claude-info-header`,children:[(0,T.jsx)(`span`,{children:`Claude isn’t connected`}),(0,T.jsx)(`button`,{className:`claude-info-close`,onClick:n,"aria-label":`Close`,children:`✕`})]}),(0,T.jsxs)(`div`,{className:`claude-info-section`,style:{padding:`12px 14px`,fontSize:`11px`,color:`var(--text-secondary)`,display:`flex`,flexDirection:`column`,gap:`10px`},children:[(0,T.jsx)(`span`,{children:`This needs Claude, which is currently disconnected. Connect to continue — the rest of the dashboard stays available either way.`}),(0,T.jsxs)(`div`,{style:{display:`flex`,gap:`8px`,alignItems:`center`},children:[(0,T.jsx)(k,{variant:`primary`,size:`sm`,onClick:t,children:`Connect Claude`}),(0,T.jsx)(`button`,{type:`button`,className:`claude-info-close`,style:{fontSize:`11px`},onClick:n,children:`Not now`})]})]})]})}):null}function Ze(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 Qe(e){return e.activeMs.thinking+e.activeMs.messaging+e.activeMs.toolUse}function V(e){return e.toLocaleString(`en-GB`)}function H(e){return`£${e.toFixed(2)}`}function $e(e){let t=[`Day`,`Active`,`Output tokens`,`Input tokens`,`Cache write`,`Cache read`,`Opus 4.8 (GBP)`,`Sonnet 4.6 (GBP)`],n=(e,t)=>[e,Ze(Qe(t)),String(t.tokens.output),String(t.tokens.input),String(t.tokens.cacheWrite),String(t.tokens.cacheRead),t.costGBP.opus.toFixed(2),t.costGBP.sonnet.toFixed(2)];return[t,...e.days.map(e=>n(e.date,e)),n(`TOTAL (${e.days.length} d)`,e.totals)].map(e=>e.join(`,`)).join(`
2
+ `)}function U({label:e,d:t,bold:n}){let r=n?`th`:`td`;return(0,T.jsxs)(`tr`,{className:n?`usage-total-row`:void 0,children:[(0,T.jsx)(r,{className:`usage-day`,children:e}),(0,T.jsx)(r,{children:Ze(Qe(t))}),(0,T.jsx)(r,{children:V(t.tokens.output)}),(0,T.jsx)(r,{children:V(t.tokens.input)}),(0,T.jsx)(r,{children:V(t.tokens.cacheWrite)}),(0,T.jsx)(r,{children:V(t.tokens.cacheRead)}),(0,T.jsx)(r,{children:H(t.costGBP.opus)}),(0,T.jsx)(r,{children:H(t.costGBP.sonnet)})]})}function et({show:e,onClose:t,anchorEl:n,sessionId:r,summary:i,loading:a,error:o}){let s=(0,D.useRef)(null);if(s.current=n,!e)return null;let c=!!i&&i.days.length>0;return(0,T.jsxs)(P,{anchorRef:s,onClose:t,className:`usage-popover`,role:`dialog`,ariaLabel:`Session usage and cost`,anchorId:r??void 0,children:[(0,T.jsxs)(`div`,{className:`claude-info-header`,children:[(0,T.jsxs)(`span`,{children:[`Usage & cost`,r?` · ${r.slice(0,8)}`:``]}),c&&(0,T.jsx)(`button`,{className:`usage-download`,onClick:()=>{if(!i)return;let e=new Blob([$e(i)],{type:`text/csv;charset=utf-8`}),t=URL.createObjectURL(e),n=document.createElement(`a`);n.href=t,n.download=`usage-${r?r.slice(0,8):`session`}.csv`,document.body.appendChild(n),n.click(),n.remove(),URL.revokeObjectURL(t)},"aria-label":`Download as CSV`,title:`Download as CSV`,children:(0,T.jsx)(l,{size:14})}),(0,T.jsx)(`button`,{className:`claude-info-close`,onClick:t,"aria-label":`Close`,children:(0,T.jsx)(y,{size:14})})]}),(0,T.jsxs)(`div`,{className:`claude-info-section usage-body`,children:[a&&(0,T.jsx)(`div`,{className:`usage-note`,children:`Computing usage…`}),!a&&o&&(0,T.jsx)(`div`,{className:`usage-note usage-error`,children:o}),!a&&!o&&i&&i.days.length===0&&(0,T.jsx)(`div`,{className:`usage-note`,children:`No usage recorded for this session yet.`}),!a&&!o&&i&&i.days.length>0&&(0,T.jsxs)(T.Fragment,{children:[(0,T.jsx)(`div`,{className:`usage-table-scroll`,children:(0,T.jsxs)(`table`,{className:`usage-table`,children:[(0,T.jsx)(`thead`,{children:(0,T.jsxs)(`tr`,{children:[(0,T.jsx)(`th`,{className:`usage-day`,children:`Day`}),(0,T.jsx)(`th`,{children:`Active`}),(0,T.jsx)(`th`,{children:`Output tok`}),(0,T.jsx)(`th`,{children:`Input tok`}),(0,T.jsx)(`th`,{children:`Cache write`}),(0,T.jsx)(`th`,{children:`Cache read`}),(0,T.jsx)(`th`,{children:`Opus 4.8 (£)`}),(0,T.jsx)(`th`,{children:`Sonnet 4.6 (£)`})]})}),(0,T.jsxs)(`tbody`,{children:[i.days.map(e=>(0,T.jsx)(U,{label:e.date,d:e},e.date)),(0,T.jsx)(U,{label:`TOTAL (${i.days.length} d)`,d:i.totals,bold:!0})]})]})}),(0,T.jsxs)(`div`,{className:`usage-note usage-caveats`,children:[`Prices dated `,i.pricing.opusPriceDate,` · £/$ `,i.pricing.usdPerGbp,` · Sonnet tokenizer factor `,i.pricing.tokenizerFactor,`. Idle human-wait dominates the calendar span; cache-read tokens dominate cost; Sonnet is a tokenizer-adjusted estimate.`]})]})]})]})}var tt=`https://claude.ai/code`,nt=200,rt=[500,1e3,1500,2e3,2500,3e3,3e3];function it(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:`${tt}/${r}`,sameOrigin:!1};let i=n.reason||n.error||`status ${t}`;return{kind:`error`,sessionId:n.sessionId??null,reason:i}}function at(e){if(!e)return``;let t=Date.parse(e);return Number.isFinite(t)?new Date(t).toLocaleString(void 0,{dateStyle:`medium`,timeStyle:`short`}):``}function ot(e){let{businessName:t,cacheKey:a,onConnectClaude:c,role:l,userName:d,userAvatar:m,onSelectProjects:ee,onSelectTasks:y,onCloseMobileDrawer:C,collapsed:re,onSelectData:oe,initialDataSurface:ce=!1,onLogout:le,onDisconnect:O,disconnecting:k,claudeConnected:he=!0,subAccounts:ve,activeAccountId:ye,switchingAccount:be,onSwitchAccount:xe,refreshAccounts:Se,onOpenConversations:Ce}=e,j=S(a),we=(0,D.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,T.jsx)(ge,{size:12}),panel:()=>(0,T.jsx)(He,{row:e,adminFetch:j,onError:e=>F({message:e,failed:!0})})}),[j]),Te=u.productName,M=t||Te,Ee=typeof d==`string`?d:d===null?`name unavailable`:M,De=(Ee.trim().charAt(0)||`?`).toUpperCase(),[Oe,ke]=(0,D.useState)(ce?`data`:`sessions`),[Ae,N]=(0,D.useState)(!1),[P,F]=(0,D.useState)(null),[Me,I]=(0,D.useState)(null),[Ne,Pe]=(0,D.useState)(!1),[L,R]=(0,D.useState)([]),[z]=(0,D.useState)(()=>typeof window>`u`?null:new URLSearchParams(window.location.search).get(`session`)),[B,Fe]=(0,D.useState)(!1),[Ie,Le]=(0,D.useState)(null),[Re,ze]=(0,D.useState)(!1),[Be,Ve]=(0,D.useState)(!1),[Ue,We]=(0,D.useState)(!1),[qe,Ye]=(0,D.useState)(null),[Ze,Qe]=(0,D.useState)(new Set),V=(0,D.useRef)(new Map),[H,$e]=(0,D.useState)(!1),[U,tt]=(0,D.useState)(new Set),[ot,st]=(0,D.useState)(!1),[W,G]=(0,D.useState)(null),[ut,dt]=(0,D.useState)(new Set),[ft,pt]=(0,D.useState)(new Set),[mt,ht]=(0,D.useState)(new Set),[K,q]=(0,D.useState)(null),[gt,J]=(0,D.useState)(``),[_t,vt]=(0,D.useState)(!1),[Y,yt]=(0,D.useState)(null),[bt,xt]=(0,D.useState)(null),[St,Ct]=(0,D.useState)(!1),[wt,Tt]=(0,D.useState)(null),[X,Et]=(0,D.useState)(!1),Dt=(0,D.useRef)(0);(0,D.useEffect)(()=>{if(!P)return;let e=setTimeout(()=>F(null),2500);return()=>clearTimeout(e)},[P]);let Ot=z!=null&&L.some(e=>e.sessionId===z);(0,D.useEffect)(()=>{z==null||!B||console.info(`[sidebar-sessions] op=select-highlight session=${z.slice(0,8)} matched=${Ot}`)},[z,Ot,B]);let Z=(0,D.useCallback)(async()=>{if(!a)return null;let e=++Dt.current;ze(!0),Le(null);try{let t=await j(`/api/admin/sidebar-sessions`);if(!t.ok)throw Error(`status ${t.status}`);let n=await t.json(),r=n.sessions??[];return e===Dt.current?(R(r),Ye(n.accountId??null),Fe(!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===Dt.current&&Le(`Failed to load sessions: ${n}`),console.error(`[admin-ui] sidebar-sessions fetch failed: ${n}`),null}finally{e===Dt.current&&ze(!1)}},[a,j]);(0,D.useEffect)(()=>{!a||B||Z()},[a,B,Z]),(0,D.useEffect)(()=>{if(!a)return;let e=null;function t(){console.info(`[admin-ui] sidebar-refresh surface=sessions trigger=poll`),Z()}function n(){e===null&&(e=setInterval(t,ct))}function r(){e!==null&&(clearInterval(e),e=null)}function i(){document.hidden?r():(t(),n())}return document.hidden||n(),document.addEventListener(`visibilitychange`,i),()=>{r(),document.removeEventListener(`visibilitychange`,i)}},[a,Z]);let kt=()=>{console.info(`[admin-ui] sidebar-refresh surface=sessions trigger=manual`),Z()},At=()=>{ke(`data`),console.info(`[admin-ui] sidebar-nav surface=data collapsed=${re}`),oe(),C()},Q=typeof window<`u`&&window.location?.pathname||`/`,jt=Oe===`data`,Mt=typeof window<`u`&&window.location?.search||``,Nt=new URLSearchParams(Mt),Pt=Nt.has(`label`)&&!Nt.has(`nodeId`),$=e=>{C(),window.location.href=e},Ft=[{key:`dashboard`,label:`Dashboard`,icon:(0,T.jsx)(p,{size:17,strokeWidth:1.75}),active:Q===`/`&&!jt,onClick:()=>$(`/`)},{key:`chat`,label:`Chat`,icon:(0,T.jsx)(f,{size:17,strokeWidth:1.75}),active:Q.startsWith(`/chat`),onClick:()=>$(`/chat`)},{key:`tasks`,label:`Tasks`,icon:(0,T.jsx)(pe,{size:17,strokeWidth:1.75}),active:Q.startsWith(`/tasks`),onClick:()=>{y(),C()}},{key:`calendar`,label:`Calendar`,icon:(0,T.jsx)(b,{size:17,strokeWidth:1.75}),active:Q.startsWith(`/calendar`),onClick:()=>$(`/calendar`)},{key:`data`,label:`Data`,icon:(0,T.jsx)(x,{size:17,strokeWidth:1.75}),active:jt,onClick:At},{key:`container`,label:o().term,icon:(0,T.jsx)(ae,{size:17,strokeWidth:1.75}),active:Q.startsWith(`/graph`)&&Pt,onClick:()=>{ee(),C()}},{key:`graph`,label:`Graph`,icon:(0,T.jsx)(_e,{size:17,strokeWidth:1.75}),active:Q.startsWith(`/graph`)&&!Pt,onClick:()=>$(`/graph`)},{key:`activity`,label:`Activity`,icon:(0,T.jsx)(s,{size:17,strokeWidth:1.75}),active:Q.startsWith(`/activity`),onClick:()=>$(`/activity`)},{key:`browser`,label:`Browser`,icon:(0,T.jsx)(r,{size:17,strokeWidth:1.75}),active:Q.startsWith(`/browser`),onClick:()=>$(`/browser`)}],It=(0,D.useCallback)(async e=>{if(ut.has(e.sessionId))return;dt(t=>{let n=new Set(t);return n.add(e.sessionId),n});let t=window.open(``,`_blank`);try{let n=await j(`/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=it(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`?(C(),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}`),I(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}`),I({sessionId:e.sessionId,reason:r})}finally{dt(t=>{let n=new Set(t);return n.delete(e.sessionId),n})}},[j,C,ut]),Lt=(0,D.useCallback)(async e=>{let t=e.slice(0,8);for(let n=1;n<=rt.length;n++){await new Promise(e=>setTimeout(e,rt[n-1]));let r=await Z();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}`)},[Z]),Rt=(0,D.useCallback)(async()=>{if(!X){Et(!0);try{let e=await j(`/api/admin/session-rc-spawn`,{method:`POST`,headers:{"Content-Type":`application/json`},body:JSON.stringify({})}),t=await e.json().catch(()=>({})),n=it(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?Lt(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`),Pe(!0)):(console.error(`[admin-ui] sidebar-new-session-failed status=${e.status} reason=${n.reason}`),I(n))}catch(e){let t=e instanceof Error?e.message:String(e);console.error(`[admin-ui] sidebar-new-session-failed error=${t}`),I({sessionId:null,reason:t})}finally{Et(!1)}}},[j,X,Lt]),zt=(0,D.useCallback)((e,t)=>{e.stopPropagation(),G(t)},[]),Bt=(0,D.useCallback)(async(e,t)=>{e.stopPropagation(),yt(t),xt(null),Tt(null),Ct(!0);try{let e=await j(`/api/admin/session-usage?sessionId=${encodeURIComponent(t.sessionId)}`),n=await e.json().catch(()=>({}));e.ok?xt(n):Tt(n.error??`status ${e.status}`)}catch(e){Tt(e instanceof Error?e.message:String(e))}finally{Ct(!1)}},[j]),Vt=(0,D.useCallback)(async(e,t={})=>{let n=t.refresh??!0;if(Ze.has(e.sessionId))return!1;Qe(t=>{let n=new Set(t);return n.add(e.sessionId),n});try{let t=await j(`/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(()=>({}));return console.error(`[admin-ui] sidebar-session-delete-failed sessionId=${e.sessionId} status=${t.status} error=${n.error??`unknown`}`),F({message:`Delete failed: ${n.error??`status ${t.status}`}`,failed:!0}),!1}let r=await t.json();return console.info(`[admin-ui] sidebar-session-delete sessionId=${e.sessionId} live=${e.live} confirmed=true pidKilled=${r.pidKilled??`?`} deleted=${r.deleted??`?`}`),R(t=>t.filter(t=>t.sessionId!==e.sessionId)),n&&Z(),!0}catch(t){let n=t instanceof Error?t.message:String(t);return console.error(`[admin-ui] sidebar-session-delete-failed sessionId=${e.sessionId} error=${n}`),F({message:`Delete failed: ${n}`,failed:!0}),!1}finally{Qe(t=>{let n=new Set(t);return n.delete(e.sessionId),n})}},[j,Ze,Z]),Ht=(0,D.useCallback)(e=>{tt(t=>{let n=new Set(t);return n.has(e)?n.delete(e):n.add(e),n})},[]),Ut=(0,D.useCallback)(()=>{$e(!1),tt(new Set)},[]),Wt=(0,D.useCallback)(async()=>{let e=[...U].map(e=>L.find(t=>t.sessionId===e)).filter(e=>!!e),t=e.filter(e=>e.live).length;console.info(`[admin-ui] sidebar-bulk-delete op=start count=${e.length} live=${t}`);let n=(await Promise.all(e.map(e=>Vt(e,{refresh:!1})))).filter(Boolean).length;console.info(`[admin-ui] sidebar-bulk-delete op=done requested=${e.length} ok=${n} failed=${e.length-n}`),Z(),Ut()},[U,L,Vt,Z,Ut]),Gt=(0,D.useCallback)(async(e,t)=>{if(e.stopPropagation(),!ft.has(t.sessionId)){pt(e=>{let n=new Set(e);return n.add(t.sessionId),n});try{let e=await j(`/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`}`),F({message:`Stop failed: ${n.error??`status ${e.status}`}`,failed:!0});return}console.info(`[admin-ui] sidebar-session-stop sessionId=${t.sessionId}`),Z()}catch(e){let n=e instanceof Error?e.message:String(e);console.error(`[admin-ui] sidebar-session-stop-failed sessionId=${t.sessionId} error=${n}`),F({message:`Stop failed: ${n}`,failed:!0})}finally{pt(e=>{let n=new Set(e);return n.delete(t.sessionId),n})}}},[j,ft,Z]),Kt=(0,D.useCallback)(async(e,t,n)=>{if(e.stopPropagation(),!mt.has(t.sessionId)){ht(e=>{let n=new Set(e);return n.add(t.sessionId),n});try{let e=await j(`/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`}`),F({message:`${n===`archive`?`Archive`:`Unarchive`} failed: ${i}`,failed:!0});return}console.info(`[admin-ui] sidebar-session-archive sessionId=${t.sessionId} mode=${n}`),Z()}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}`),F({message:`${n===`archive`?`Archive`:`Unarchive`} failed: ${r}`,failed:!0})}finally{ht(e=>{let n=new Set(e);return n.delete(t.sessionId),n})}}},[j,mt,Z]),qt=(0,D.useCallback)(async e=>{let t=gt.trim();if(!t){F({message:`Title can’t be empty`,failed:!0});return}if(t.length>nt){F({message:`Title too long (max ${nt})`,failed:!0});return}vt(!0);try{let n=await j(`/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}`),F({message:`Rename failed: ${r}`,failed:!0});return}console.info(`[admin-ui] sidebar-session-rename sessionId=${e.sessionId.slice(0,8)} outcome=ok`),q(null),J(``),Z()}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}`),F({message:`Rename failed: ${n}`,failed:!0})}finally{vt(!1)}},[j,gt,Z]);return(0,T.jsxs)(`aside`,{className:`side`,children:[(0,T.jsxs)(`div`,{className:`side-brand`,children:[(0,T.jsx)(`img`,{className:`side-brand-icon`,src:i,alt:``,"aria-hidden":`true`}),(0,T.jsxs)(`span`,{className:`side-brand-lockup`,children:[(0,T.jsx)(`span`,{className:`side-brand-business`,children:M}),(0,T.jsx)(`span`,{className:`side-brand-product`,children:u.productName})]})]}),(0,T.jsx)(`nav`,{className:`side-nav`,children:Ft.map(e=>(0,T.jsxs)(`button`,{type:`button`,className:`admin-row nav-row${e.active?` active`:``}`,"aria-current":e.active?`page`:void 0,onClick:e.onClick,children:[e.icon,(0,T.jsx)(`span`,{className:`label`,children:e.label}),(0,T.jsx)(`span`,{className:`kbd`})]},e.key))}),(()=>{let e=L.filter(e=>Be?!0:!e.isSubagent).filter(e=>Ue?!0:!e.archived),t=L.some(e=>e.isSubagent),r=L.some(e=>e.archived);return(0,T.jsx)(`div`,{className:`side-sessions`,children:(0,T.jsxs)(`div`,{className:`side-list`,children:[(0,T.jsxs)(`div`,{className:`group-head`,children:[(0,T.jsx)(`span`,{children:`Sessions`}),(0,T.jsxs)(`span`,{className:`group-head-meta`,children:[(0,T.jsx)(`button`,{type:`button`,className:`group-head-select${H?` active`:``}`,"aria-pressed":H,title:H?`Exit select mode`:`Select multiple sessions to delete`,onClick:()=>{$e(e=>!e),tt(new Set),q(null),J(``)},children:`Select`}),(0,T.jsx)(`button`,{type:`button`,className:`group-head-refresh`,title:`Refresh sessions`,"aria-label":`Refresh sessions`,onClick:kt,disabled:Re,children:(0,T.jsx)(w,{size:12,className:Re?`spinning`:void 0})}),(0,T.jsx)(`span`,{children:Re?`…`:String(e.length)}),(0,T.jsxs)(`button`,{type:`button`,className:`admin-btn-cta side-sessions-new`,onClick:Rt,disabled:X,"aria-busy":X,"aria-label":X?`Spawning session`:`New session`,title:X?`Spawning session`:`New session`,children:[(0,T.jsx)(_,{size:13}),(0,T.jsx)(`span`,{children:X?`Spawning…`:`New session`})]})]})]}),H&&(0,T.jsxs)(`div`,{className:`session-select-bar`,children:[(0,T.jsxs)(`span`,{className:`session-select-count`,children:[U.size,` selected`]}),(0,T.jsxs)(`button`,{type:`button`,className:`session-select-delete`,disabled:U.size===0,onClick:()=>st(!0),children:[`Delete `,U.size]}),(0,T.jsx)(`button`,{type:`button`,className:`session-select-cancel`,onClick:Ut,children:`Cancel`})]}),qe&&(0,T.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,T.jsx)(`code`,{children:qe})}),(t||r)&&(0,T.jsxs)(`div`,{className:`artefact-filter-chips`,children:[t&&(0,T.jsx)(`button`,{type:`button`,className:`artefact-filter-chip${Be?` active`:``}`,"aria-pressed":Be,onClick:()=>Ve(e=>!e),title:Be?`Hide subagent sessions`:`Show subagent sessions`,children:`Subagents`}),r&&(0,T.jsx)(`button`,{type:`button`,className:`artefact-filter-chip${Ue?` active`:``}`,"aria-pressed":Ue,onClick:()=>We(e=>!e),title:Ue?`Hide archived sessions`:`Show archived sessions`,children:`Archived`})]}),Ie&&(0,T.jsx)(`div`,{className:`conv`,style:{color:`var(--text-tertiary)`,cursor:`default`},children:Ie}),B&&!Ie&&e.length===0&&(0,T.jsx)(`div`,{className:`conv`,style:{color:`var(--text-tertiary)`,cursor:`default`},children:`No sessions yet`}),e.map(e=>{let t=at(e.startedAt),r=ut.has(e.sessionId),i=Ze.has(e.sessionId),a=ft.has(e.sessionId),o=mt.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,T.jsx)(n,{size:12}),busy:r,onClick:()=>{It(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,T.jsx)(me,{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,T.jsx)(A,{size:12}),onClick:t=>{Bt(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,T.jsx)(h,{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,T.jsx)(ue,{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,T.jsx)(de,{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,T.jsx)(se,{size:12}),busy:_t&&K===e.sessionId,onClick:t=>{t.stopPropagation(),q(e.sessionId),J(e.personName??e.title)}},{key:`delete`,label:`Delete session ${e.title}`,menuLabel:`Delete`,title:`Delete session (stops the process, removes the conversation)`,icon:(0,T.jsx)(v,{size:12}),danger:!0,busy:i,onClick:t=>{zt(t,e)}},we({sessionId:e.sessionId,model:e.model??null,title:e.personName??e.title})],u=e.channel===`whatsapp`?` conv-channel-whatsapp`:e.channel===`telegram`?` conv-channel-telegram`:``,d=e.channel===`whatsapp`||e.channel===`telegram`||e.channel===`webchat`,f=ne.includes(e.channel??``)&&e.senderId&&e.titleSource===`prefix`?g({operatorName:e.personName??null,whatsappName:e.whatsappName??null,senderId:e.senderId,title:e.title}):e.personName??e.title;return(0,T.jsxs)(`div`,{ref:t=>{let n=V.current;t?n.set(e.sessionId,t):n.delete(e.sessionId)},className:`conv conv-with-actions${u}${e.sessionId===z?` active`:``}`,children:[(0,T.jsxs)(`div`,{className:`conv-main-static conv-main-clickable`,role:`button`,tabIndex:0,"aria-label":`Open ${f} in webchat`,onClick:()=>{if(K!==e.sessionId){if(H){Ht(e.sessionId);return}c()}},onKeyDown:t=>{K!==e.sessionId&&(t.key===`Enter`||t.key===` `)&&(t.preventDefault(),H?Ht(e.sessionId):c())},children:[H&&(0,T.jsx)(`span`,{className:`conv-select-check`,onClick:e=>e.stopPropagation(),children:(0,T.jsx)(E,{checked:U.has(e.sessionId),ariaLabel:`Select ${f}`,onChange:()=>Ht(e.sessionId)})}),(0,T.jsx)(`span`,{className:`conv-live-dot`,"data-live":e.live?`1`:`0`,"aria-label":e.live?`live session`:`ended session`}),(0,T.jsxs)(`span`,{className:`conv-stack`,children:[(0,T.jsxs)(`span`,{className:`conv-name-line`,children:[d&&(0,T.jsx)(ie,{channel:e.channel,size:13}),K===e.sessionId?(0,T.jsx)(`input`,{className:`conv-name conv-name-edit`,autoFocus:!0,onFocus:e=>e.currentTarget.select(),value:gt,disabled:_t,"aria-label":`New title for session ${e.title}`,onChange:e=>J(e.target.value),onClick:e=>e.stopPropagation(),onKeyDown:t=>{t.key===`Enter`?(t.preventDefault(),qt(e)):t.key===`Escape`&&(t.preventDefault(),q(null),J(``))},onBlur:()=>{K===e.sessionId&&!_t&&(q(null),J(``))}}):(0,T.jsx)(`span`,{className:`conv-name`,title:f,children:f})]}),(0,T.jsxs)(`span`,{className:`conv-timestamp`,children:[(0,T.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)}),t&&(0,T.jsxs)(`span`,{children:[` · `,t]})]})]})]}),!H&&(0,T.jsx)(je,{actions:l,disabled:s})]},e.sessionId)})]})})})(),(0,T.jsxs)(`div`,{className:`side-foot`,children:[(0,T.jsx)(`div`,{className:`avatar`,children:m?(0,T.jsx)(`img`,{src:m,alt:Ee}):De}),(0,T.jsxs)(`div`,{className:`who`,children:[(0,T.jsx)(`span`,{className:`name`,children:Ee}),(0,T.jsx)(lt,{})]}),(0,T.jsx)(`button`,{type:`button`,className:`side-foot-kebab`,"aria-label":`Account menu`,"aria-haspopup":`menu`,"aria-expanded":Ae,onClick:()=>N(e=>!e),children:(0,T.jsx)(fe,{size:16})}),Ae&&(0,T.jsxs)(T.Fragment,{children:[(0,T.jsx)(`div`,{className:`side-foot-menu-scrim`,"aria-hidden":`true`,onClick:()=>N(!1)}),(0,T.jsx)(`div`,{className:`side-foot-menu`,role:`menu`,children:(0,T.jsx)(te,{variant:`admin`,onCloseMenu:()=>N(!1),onLogout:le??(()=>{}),onDisconnect:O,disconnecting:k,claudeConnected:he,onConnectClaude:c,cacheKey:a,subAccounts:ve,activeAccountId:ye,switchingAccount:be,onSwitchAccount:xe,refreshAccounts:Se,onOpenConversations:Ce})})]})]}),P&&(0,T.jsx)(`div`,{className:`copy-toast${P.failed?` copy-toast-failed`:``}`,role:`status`,children:P.message}),(0,T.jsx)(Je,{error:Me,onClose:()=>I(null)}),(0,T.jsx)(Xe,{open:Ne,onConnect:()=>{Pe(!1),c?.()},onClose:()=>Pe(!1)}),(0,T.jsx)(Ge,{target:W,anchorEl:W?V.current.get(W.sessionId)??null:null,onCancel:()=>G(null),onConfirm:()=>{let e=W;G(null),e&&Vt(e)}},W?.sessionId??`none`),(0,T.jsx)(Ke,{open:ot,count:U.size,liveCount:L.filter(e=>U.has(e.sessionId)&&e.live).length,onConfirm:()=>{st(!1),Wt()},onCancel:()=>st(!1)}),(0,T.jsx)(et,{show:Y!==null,onClose:()=>{yt(null),xt(null),Tt(null)},anchorEl:Y?V.current.get(Y.sessionId)??null:null,sessionId:Y?.sessionId??null,summary:bt,loading:St,error:wt},Y?.sessionId??`none`)]})}var st=5e3,ct=3e4;function lt(){let[e,t]=(0,D.useState)(null);if((0,D.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()},st))}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=[`system-stats`];return c&&d.push(`system-stats--warn`),l&&d.push(`system-stats--crit`),(0,T.jsxs)(`span`,{className:d.join(` `),role:`status`,"aria-label":`host CPU and RAM`,children:[(0,T.jsxs)(`span`,{className:i?`system-stats__fig system-stats__fig--warn`:`system-stats__fig`,children:[`CPU `,u(n)]}),` · `,(0,T.jsxs)(`span`,{className:o?`system-stats__fig system-stats__fig--warn`:`system-stats__fig`,children:[`RAM `,u(r)]})]})}var W=`admin-sidebar-collapsed`,G=`admin-sidebar-drawer-open`,ut=1080;function dt(){if(typeof window>`u`)return!1;let e=null;try{e=window.sessionStorage.getItem(W)}catch{e=null}return e===null?typeof window.matchMedia==`function`?window.matchMedia(`(min-width: 721px) and (max-width: ${ut}px)`).matches:!1:e===`1`}function ft(e){if(!(typeof window>`u`))try{e?window.sessionStorage.setItem(W,`1`):window.sessionStorage.removeItem(W)}catch{}}function pt(){if(typeof window>`u`)return!1;try{return window.sessionStorage.getItem(G)===`1`}catch{return!1}}function mt(e){if(!(typeof window>`u`))try{e?window.sessionStorage.setItem(G,`1`):window.sessionStorage.removeItem(G)}catch{}}function ht(e){let[t,n]=(0,D.useState)(()=>typeof window>`u`||typeof window.matchMedia!=`function`?!1:window.matchMedia(e).matches);return(0,D.useEffect)(()=>{if(typeof window>`u`||typeof window.matchMedia!=`function`)return;let t=window.matchMedia(e),r=()=>n(t.matches);return r(),t.addEventListener(`change`,r),()=>t.removeEventListener(`change`,r)},[e]),t}var K=720;function q(e,t){return e===`/`?{via:`in-place`}:{via:`navigate`,href:`/?wa=${encodeURIComponent(t.remoteJid??``)}&acct=${encodeURIComponent(t.accountId??``)}`}}function gt(e){return e===`/`?{via:`in-place`}:{via:`navigate`,href:`/?data=1`}}function J(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 _t(e,t){return e===`/`?new URLSearchParams(t).has(`data`):!1}function vt(e,t){return t===`operator`&&e===`chat`||e===`dashboard`?`/`:e===`data`?`/data`:e===`graph`?`/graph`:e===`calendar`?`/calendar`:e===`chat`?`/chat`:e===`activity`?`/activity`:`/browser`}function Y(e){let{cacheKey:t,businessName:n,variant:r=`admin`,onLogout:i,onDisconnect:a,disconnecting:s,claudeConnected:c,onConnectClaude:l,userName:u,userAvatar:d,role:f,onOpenConversations:p,children:m,footer:h}=e,{subAccounts:g,activeAccountId:_,switching:te,switchAccount:v,refreshAccounts:y}=re(t),[b,x]=(0,D.useState)(!0);(0,D.useEffect)(()=>{if(c!==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||x(n.auth_status!==`dead`&&n.auth_status!==`missing`)}catch{}};t();let n=setInterval(t,6e4);return()=>{e=!0,clearInterval(n)}},[c,r]);let S=c??b,ne=l??(()=>{window.location.assign(`/?connect=claude`)}),[C,ie]=(0,D.useState)(()=>dt()),[ae,oe]=(0,D.useState)(!1),se=(0,D.useRef)(!0);(0,D.useEffect)(()=>{if(se.current){se.current=!1;return}oe(!0);let e=setTimeout(()=>oe(!1),260);return()=>clearTimeout(e)},[C]);let[w,ce]=(0,D.useState)(()=>pt()),E=ht(`(max-width: ${K}px)`),[le,O]=(0,D.useState)(()=>typeof window>`u`||_t(window.location.pathname,window.location.search)?null:J(window.location.pathname,window.location.search)),[k,ue]=(0,D.useState)(()=>typeof window>`u`?!1:_t(window.location.pathname,window.location.search)),[de]=(0,D.useState)(()=>k),fe=(0,D.useCallback)(e=>{ft(e),ie(e)},[]),A=(0,D.useCallback)(e=>{mt(e),ce(e)},[]);(0,D.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=${C} drawer=${w}`)},[]),(0,D.useEffect)(()=>{typeof window>`u`||!le||(console.info(`[admin-ui] wa-hydrate route=/ remoteJid=${le.remoteJid??``}`),window.history.replaceState(null,``,`/`))},[]),(0,D.useEffect)(()=>{typeof window>`u`||!k||(console.info(`[admin-ui] data-hydrate route=/`),window.history.replaceState(null,``,`/`))},[]);let pe=(0,D.useCallback)(e=>{if(ue(!1),e===null){O(null);return}let t=typeof window<`u`?window.location.pathname:`/`,n=q(t,e);console.info(`[admin-ui] wa-open route=${t} via=${n.via} sessionId=${e.sessionId.slice(0,8)}`),n.via===`in-place`?O(e):window.location.href=n.href},[]),me=(0,D.useCallback)(()=>{let e=typeof window<`u`?window.location.pathname:`/`,t=gt(e);if(console.info(`[admin-ui] data-open route=${e} via=${t.via}`),t.via===`navigate`){window.location.href=t.href;return}O(null),ue(!0)},[]),he=E?w:!C,ge=(0,D.useCallback)(()=>{if(!(typeof window>`u`))if(window.matchMedia(`(max-width: ${K}px)`).matches){let e=w;console.info(`[admin-ui] header-sidebar-toggle from=${e?`open`:`closed`} mode=drawer`),A(!e)}else{let e=C;console.info(`[admin-ui] header-sidebar-toggle from=${e?`closed`:`open`} mode=collapse`),fe(!e)}},[C,w,fe,A]),_e=(0,D.useCallback)(e=>{let t=vt(e,r);console.info(`[admin-ui] header-menu-nav target=${e} dest=${t}`),window.location.href=t},[r]),ve={collapsed:C,mobileDrawerOpen:w,sidebarOpen:he,onToggleSidebar:ge,setMobileDrawerOpen:A,selectedWhatsapp:le,onClearWhatsapp:()=>O(null),onSelectWhatsappConversation:pe,dataOpen:k};return r===`operator`?(0,T.jsxs)(`div`,{className:`admin-shell admin-page admin-shell-root`,children:[(0,T.jsx)(ee,{businessName:n,variant:r,onNavigate:_e,onOpenConversations:p,onToggleSidebar:ge,sidebarOpen:he,onLogout:i,onDisconnect:a,disconnecting:s,cacheKey:t,subAccounts:g,activeAccountId:_,switchingAccount:te,onSwitchAccount:v,refreshAccounts:y}),(0,T.jsx)(`div`,{className:`platform platform-operator`,children:typeof m==`function`?m(ve):m}),(0,T.jsx)(j,{variant:`operator`,onOpenConversations:p}),h]}):(0,T.jsxs)(`div`,{className:`admin-shell admin-page admin-shell-root`,children:[(0,T.jsxs)(`div`,{className:`platform${w?` menu-open`:``}${!E&&C?` sidebar-collapsed`:``}${ae?` sidebar-animating`:``}`,"data-artefact":`closed`,children:[(0,T.jsx)(ot,{businessName:n,cacheKey:t,onConnectClaude:ne,role:f??null,userName:u,userAvatar:d??null,onSelectProjects:()=>{window.location.href=`/graph?label=${o().label}`},onSelectTasks:()=>{window.location.href=`/tasks`},onCloseMobileDrawer:()=>A(!1),collapsed:C,mobileDrawerOpen:w,onSelectData:me,onCloseData:()=>ue(!1),initialDataSurface:de,onLogout:i,onDisconnect:a,disconnecting:s,claudeConnected:S,subAccounts:g,activeAccountId:_,switchingAccount:te,onSwitchAccount:v,refreshAccounts:y,onOpenConversations:p}),!E&&(0,T.jsx)(De,{}),(0,T.jsx)(be,{sidebarOpen:he,onToggleSidebar:ge,claudeConnected:S,onConnectClaude:ne}),typeof m==`function`?m(ve):m]}),w&&(0,T.jsx)(`div`,{className:`sidebar-backdrop menu-open`,"aria-hidden":`true`,onClick:()=>A(!1)}),(0,T.jsx)(j,{}),h]})}export{k as _,Ye as a,Me as c,ge as d,pe as f,ue as g,de as h,Xe as i,z as l,fe as m,ht as n,I as o,A as p,it as r,F as s,Y as t,Pe as u,E as v,ce as y};