@rubytech/create-realagent-code 0.1.611 → 0.1.613
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/package.json +1 -1
- package/payload/platform/plugins/admin/skills/platform-architecture/SKILL.md +22 -10
- package/payload/platform/plugins/admin/skills/whats-new/SKILL.md +9 -0
- package/payload/platform/plugins/docs/references/telegram-guide.md +21 -9
- package/payload/server/public/assets/{AdminLoginScreens-Bjsr45ed.js → AdminLoginScreens-BiHOXO0Y.js} +1 -1
- package/payload/server/public/assets/AdminLoginScreens-BiHOXO0Y.js.br +0 -0
- package/payload/server/public/assets/AdminLoginScreens-BiHOXO0Y.js.gz +0 -0
- package/payload/server/public/assets/{admin-B2IkUoSc.js → admin-Bs6cPAbz.js} +1 -1
- package/payload/server/public/assets/admin-Bs6cPAbz.js.br +0 -0
- package/payload/server/public/assets/admin-Bs6cPAbz.js.gz +0 -0
- package/payload/server/public/assets/chat-UvZFrM0K.js +1 -0
- package/payload/server/public/assets/chat-UvZFrM0K.js.br +3 -0
- package/payload/server/public/assets/chat-UvZFrM0K.js.gz +0 -0
- package/payload/server/public/assets/data-BBEjTZO8.js +1 -0
- package/payload/server/public/assets/data-BBEjTZO8.js.br +1 -0
- package/payload/server/public/assets/data-BBEjTZO8.js.gz +0 -0
- package/payload/server/public/assets/{operator-CO5ma-ky.js → operator-DxwbldCs.js} +1 -1
- package/payload/server/public/assets/operator-DxwbldCs.js.br +0 -0
- package/payload/server/public/assets/operator-DxwbldCs.js.gz +0 -0
- package/payload/server/public/assets/{page-CdRrpkky.js → page-BF6bGLX_.js} +1 -1
- package/payload/server/public/assets/page-BF6bGLX_.js.br +0 -0
- package/payload/server/public/assets/page-BF6bGLX_.js.gz +0 -0
- package/payload/server/public/assets/{page-BBRWbFzG.js → page-Bkl56P8R.js} +1 -1
- package/payload/server/public/assets/page-Bkl56P8R.js.br +0 -0
- package/payload/server/public/assets/page-Bkl56P8R.js.gz +0 -0
- package/payload/server/public/assets/{public-2mLo4k7L.js → public-D6YxlJcZ.js} +1 -1
- package/payload/server/public/assets/public-D6YxlJcZ.js.br +0 -0
- package/payload/server/public/assets/public-D6YxlJcZ.js.gz +0 -0
- package/payload/server/public/assets/useVoiceRecorder-Cvu4TePf.js +2 -0
- package/payload/server/public/assets/useVoiceRecorder-Cvu4TePf.js.br +0 -0
- package/payload/server/public/assets/useVoiceRecorder-Cvu4TePf.js.gz +0 -0
- package/payload/server/public/chat.html +3 -3
- package/payload/server/public/data.html +3 -3
- package/payload/server/public/index.html +4 -4
- package/payload/server/public/operator.html +4 -4
- package/payload/server/public/public.html +3 -3
- package/payload/server/server.js +141 -104
- package/payload/server/public/assets/AdminLoginScreens-Bjsr45ed.js.br +0 -0
- package/payload/server/public/assets/AdminLoginScreens-Bjsr45ed.js.gz +0 -0
- package/payload/server/public/assets/admin-B2IkUoSc.js.br +0 -0
- package/payload/server/public/assets/admin-B2IkUoSc.js.gz +0 -0
- package/payload/server/public/assets/chat-fP4sE4pU.js +0 -1
- package/payload/server/public/assets/chat-fP4sE4pU.js.br +0 -2
- package/payload/server/public/assets/chat-fP4sE4pU.js.gz +0 -0
- package/payload/server/public/assets/data-DKz9_73S.js +0 -1
- package/payload/server/public/assets/data-DKz9_73S.js.br +0 -1
- package/payload/server/public/assets/data-DKz9_73S.js.gz +0 -0
- package/payload/server/public/assets/operator-CO5ma-ky.js.br +0 -0
- package/payload/server/public/assets/operator-CO5ma-ky.js.gz +0 -0
- package/payload/server/public/assets/page-BBRWbFzG.js.br +0 -0
- package/payload/server/public/assets/page-BBRWbFzG.js.gz +0 -0
- package/payload/server/public/assets/page-CdRrpkky.js.br +0 -0
- package/payload/server/public/assets/page-CdRrpkky.js.gz +0 -0
- package/payload/server/public/assets/public-2mLo4k7L.js.br +0 -0
- package/payload/server/public/assets/public-2mLo4k7L.js.gz +0 -0
- package/payload/server/public/assets/useVoiceRecorder-D7_wLtrS.js +0 -2
- package/payload/server/public/assets/useVoiceRecorder-D7_wLtrS.js.br +0 -0
- package/payload/server/public/assets/useVoiceRecorder-D7_wLtrS.js.gz +0 -0
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: platform-architecture
|
|
3
3
|
description: Use when grounding any documented-surface claim about what Real Agent 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:
|
|
4
|
+
content-hash: sha256:0f6a37637cbc5d7fc6fa7c444898e9609c467c5081c54bb27dcf1b979ffc7c36
|
|
5
5
|
brand: realagent-code
|
|
6
6
|
product-name: Real Agent
|
|
7
7
|
---
|
|
@@ -2961,10 +2961,10 @@ Telegram profile name and will tell you plainly that it cannot put a name to the
|
|
|
2961
2961
|
Ask Real Agent to save the Telegram ID against the contact. It is one change to one contact, and
|
|
2962
2962
|
it takes effect on the very next message.
|
|
2963
2963
|
|
|
2964
|
-
## Correcting what
|
|
2964
|
+
## Correcting what an agent told someone
|
|
2965
2965
|
|
|
2966
|
-
When one of your
|
|
2967
|
-
|
|
2966
|
+
When one of your bots tells someone something wrong, the fix is to instruct the agent that is talking
|
|
2967
|
+
to them, not to message that person yourself.
|
|
2968
2968
|
|
|
2969
2969
|
The reason is worth understanding, because the obvious approach quietly fails. Every conversation is
|
|
2970
2970
|
its own separate agent with its own memory. If you send the visitor a correction from your chat, they
|
|
@@ -2979,16 +2979,28 @@ own conversation. The agent writes the message itself, in the same voice it has
|
|
|
2979
2979
|
own memory now holds what it said, so it will not contradict it a moment later. The visitor sees a
|
|
2980
2980
|
normal message from the assistant they have been talking to, with no sign that anybody stepped in.
|
|
2981
2981
|
|
|
2982
|
+
The same is true of your specialist bots. If a specialist relays for a driver, a supplier or a
|
|
2983
|
+
colleague, and you card that person yourself, the specialist never learns you did. It answers their
|
|
2984
|
+
next message with no idea what they are replying to. That happened on a live conversation: a driver
|
|
2985
|
+
was sent a job by card, and when he came back twelve minutes later with his prices, the bot filed
|
|
2986
|
+
them as a passing remark and thanked him. Instruct it the same way, naming its bot and their chat,
|
|
2987
|
+
and it writes the message and remembers writing it.
|
|
2988
|
+
|
|
2982
2989
|
Write the intent rather than the exact sentence. This is an instruction to the agent, not text
|
|
2983
2990
|
delivered word for word, so "tell them we can do Thursday morning but not the afternoon" works better
|
|
2984
2991
|
than a script.
|
|
2985
2992
|
|
|
2986
|
-
|
|
2987
|
-
|
|
2988
|
-
- The bot is
|
|
2989
|
-
|
|
2990
|
-
- The
|
|
2991
|
-
|
|
2993
|
+
Six situations are refused, and each one says why rather than failing quietly:
|
|
2994
|
+
|
|
2995
|
+
- The bot is your own admin bot. That chat is your conversation with the agent, so instructing it
|
|
2996
|
+
there is the agent talking to itself.
|
|
2997
|
+
- The bot is bound to nothing. It answers nobody, so there is no agent to instruct.
|
|
2998
|
+
- The agent has been switched off, or a specialist's card has been renamed or deleted. Nothing is
|
|
2999
|
+
resurrected behind your back; turn it back on, or message the person yourself.
|
|
3000
|
+
- The bot is not allowed to talk to that person. Every bot has its own rule about who it answers, and
|
|
3001
|
+
a specialist answers a named list and nobody else. Starting a conversation the bot would refuse to
|
|
3002
|
+
continue leaves the person holding a message nobody can follow up, so it is refused instead. Most
|
|
3003
|
+
often this is a mistyped chat ID.
|
|
2992
3004
|
- The chat belongs to a connected business account. Those conversations are held separately and this
|
|
2993
3005
|
route cannot reach them.
|
|
2994
3006
|
- The chat is a broadcast channel the bot does not allow. A channel post reaches every subscriber and
|
|
@@ -9,6 +9,15 @@ Invoked by the admin agent directly.
|
|
|
9
9
|
|
|
10
10
|
This is the platform's release timeline, newest first. Each entry shows the date it shipped and the version it shipped in, so you can tell the operator how current their install is. To compare, read the installed version from `capabilities-here` and match it against the versions below. Keep answers high level and in plain English; this is a summary, not a full commit log.
|
|
11
11
|
|
|
12
|
+
## 2026-08-16 (0.1.613)
|
|
13
|
+
|
|
14
|
+
- You can now tell the assistant what to say to someone one of your specialist bots is handling, the same way you already could for a public bot. Until now that was refused, so the only way through was to message the person yourself, and the specialist never learned you had. It would answer their next message with no idea what they were replying to.
|
|
15
|
+
- A bot will no longer start a conversation with someone it is set up never to answer. A mistyped chat ID used to send one message and then go silent, because every reply came back to a bot that refused it.
|
|
16
|
+
|
|
17
|
+
## 2026-08-15 (0.1.612)
|
|
18
|
+
|
|
19
|
+
- A conversation opened from the dashboard could show as completely empty even though the agent had answered in it. The reader was discarding the agent's replies instead of drawing them, so the thread looked like nothing had ever been said. Those replies now appear.
|
|
20
|
+
|
|
12
21
|
## 2026-08-15 (0.1.611)
|
|
13
22
|
|
|
14
23
|
- A message you send by hand to a switched-off agent is now recorded in the conversation instead of being refused. It was delivered as though it had arrived from the other person, so an agent that was off declined to take it.
|
|
@@ -138,10 +138,10 @@ Telegram profile name and will tell you plainly that it cannot put a name to the
|
|
|
138
138
|
Ask {{productName}} to save the Telegram ID against the contact. It is one change to one contact, and
|
|
139
139
|
it takes effect on the very next message.
|
|
140
140
|
|
|
141
|
-
## Correcting what
|
|
141
|
+
## Correcting what an agent told someone
|
|
142
142
|
|
|
143
|
-
When one of your
|
|
144
|
-
|
|
143
|
+
When one of your bots tells someone something wrong, the fix is to instruct the agent that is talking
|
|
144
|
+
to them, not to message that person yourself.
|
|
145
145
|
|
|
146
146
|
The reason is worth understanding, because the obvious approach quietly fails. Every conversation is
|
|
147
147
|
its own separate agent with its own memory. If you send the visitor a correction from your chat, they
|
|
@@ -156,16 +156,28 @@ own conversation. The agent writes the message itself, in the same voice it has
|
|
|
156
156
|
own memory now holds what it said, so it will not contradict it a moment later. The visitor sees a
|
|
157
157
|
normal message from the assistant they have been talking to, with no sign that anybody stepped in.
|
|
158
158
|
|
|
159
|
+
The same is true of your specialist bots. If a specialist relays for a driver, a supplier or a
|
|
160
|
+
colleague, and you card that person yourself, the specialist never learns you did. It answers their
|
|
161
|
+
next message with no idea what they are replying to. That happened on a live conversation: a driver
|
|
162
|
+
was sent a job by card, and when he came back twelve minutes later with his prices, the bot filed
|
|
163
|
+
them as a passing remark and thanked him. Instruct it the same way, naming its bot and their chat,
|
|
164
|
+
and it writes the message and remembers writing it.
|
|
165
|
+
|
|
159
166
|
Write the intent rather than the exact sentence. This is an instruction to the agent, not text
|
|
160
167
|
delivered word for word, so "tell them we can do Thursday morning but not the afternoon" works better
|
|
161
168
|
than a script.
|
|
162
169
|
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
- The bot is
|
|
166
|
-
|
|
167
|
-
- The
|
|
168
|
-
|
|
170
|
+
Six situations are refused, and each one says why rather than failing quietly:
|
|
171
|
+
|
|
172
|
+
- The bot is your own admin bot. That chat is your conversation with the agent, so instructing it
|
|
173
|
+
there is the agent talking to itself.
|
|
174
|
+
- The bot is bound to nothing. It answers nobody, so there is no agent to instruct.
|
|
175
|
+
- The agent has been switched off, or a specialist's card has been renamed or deleted. Nothing is
|
|
176
|
+
resurrected behind your back; turn it back on, or message the person yourself.
|
|
177
|
+
- The bot is not allowed to talk to that person. Every bot has its own rule about who it answers, and
|
|
178
|
+
a specialist answers a named list and nobody else. Starting a conversation the bot would refuse to
|
|
179
|
+
continue leaves the person holding a message nobody can follow up, so it is refused instead. Most
|
|
180
|
+
often this is a mistyped chat ID.
|
|
169
181
|
- The chat belongs to a connected business account. Those conversations are held separately and this
|
|
170
182
|
route cannot reach them.
|
|
171
183
|
- The chat is a broadcast channel the bot does not allow. A channel post reaches every subscriber and
|
package/payload/server/public/assets/{AdminLoginScreens-Bjsr45ed.js → AdminLoginScreens-BiHOXO0Y.js}
RENAMED
|
@@ -1 +1 @@
|
|
|
1
|
-
import{o as e}from"./chunk-BycB0eMI.js";import{i as t,t as n}from"./jsx-runtime-BY35JYDT.js";import{N as r,it as i,lt as a,ot as o}from"./useMediaQuery-e4ciNiuO.js";import{P as s}from"./useVoiceRecorder-D7_wLtrS.js";import{D as c,O as l,k as u,p as d}from"./AdminShell-Dm_nY4jF.js";var f=e(t(),1);function p(e=`admin`){let[t,n]=(0,f.useState)(`loading`),[r,i]=(0,f.useState)(``),[o,c]=(0,f.useState)(``),[l,d]=(0,f.useState)(``),[p,m]=(0,f.useState)(!1),[h,g]=(0,f.useState)(!1),[_,v]=(0,f.useState)(!1),[y,b]=(0,f.useState)(!1),[x,S]=(0,f.useState)(!1),[C,w]=(0,f.useState)(null),[T,E]=(0,f.useState)(null),[D,O]=(0,f.useState)(void 0),[k,A]=(0,f.useState)(null),[j,M]=(0,f.useState)(void 0),[N,P]=(0,f.useState)(null),[F,I]=(0,f.useState)(null),[L,R]=(0,f.useState)(void 0),z=(0,f.useRef)(void 0),[B,V]=(0,f.useState)(!1),[H,U]=(0,f.useState)(!0);(0,f.useEffect)(()=>{typeof window>`u`||fetch(`/api/remote-auth/status`).then(e=>e.ok?e.json():null).then(e=>{e?.configured&&V(!0)}).catch(()=>{})},[]);let W=(0,f.useRef)(null),G=(0,f.useRef)(null);(0,f.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();w(r.session_key),I(r.sessionId??null),O(r.businessName),A(r.role??null),M(r.userName===void 0?null:r.userName),P(r.avatar??null);let i=s(r.thinkingView);return z.current=i,R(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}U(!!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,f.useEffect)(()=>{t===`chat`&&C&&fetch(`/api/admin/claude-info?session_key=${encodeURIComponent(C)}`).then(e=>{if(e.ok)return e.json()}).then(e=>{e&&E(e)}).catch(()=>{})},[t,C]);let K=(0,f.useRef)(null);(0,f.useEffect)(()=>{if(t!==`chat`)return;let e=setInterval(async()=>{try{let e=await fetch(`/api/health`);if(e.ok){let t=await e.json();U(t.auth_status!==`dead`&&t.auth_status!==`missing`)}}catch{}if(C)try{let e=await fetch(`/api/admin/session?session_key=${encodeURIComponent(C)}`);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}`),K.current?.()}catch{}},300*1e3);return()=>clearInterval(e)},[t,C]),(0,f.useEffect)(()=>{t===`connect-claude`&&fetch(`/api/health`).then(e=>e.ok?e.json():null).then(e=>{e?.claude_authenticated&&(U(!0),n(`enter-pin`))}).catch(()=>{})},[t]);async function q(e,t){g(!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}d(e.error||`Invalid PIN`);return}let o=await r.json();w(o.session_key),I(o.sessionId??null),O(o.businessName),A(o.role??null),M(o.userName===void 0?null:o.userName),P(o.avatar??null);let c=s(o.thinkingView);z.current=c,R(c);try{sessionStorage.setItem(`maxy-admin-session-key`,o.session_key)}catch{}i(``),n(`chat`)}catch(e){console.error(`[admin] connection error:`,e),d(`Could not connect.`)}finally{g(!1)}}let J=(0,f.useCallback)(async e=>{if(e.preventDefault(),h)return;d(``);let t=o.trim();if(!t){d(`Please enter your name.`);return}if(r.length<4){d(`PIN must be at least 4 characters.`);return}let s=r;g(!0);try{let e=await fetch(`/api/onboarding/set-pin`,{method:`POST`,headers:{"Content-Type":`application/json`},body:JSON.stringify({pin:s,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){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`):d(t.error||`Failed to set PIN.`)}else n(`enter-pin`)}catch{n(`enter-pin`)}return}d(t.error||`Failed to set PIN.`);return}let r=await fetch(`/api/health`);if((r.ok?await r.json():null)?.claude_authenticated){await q(s);return}i(``),n(`connect-claude`)}catch(e){console.error(`[admin] connection error:`,e),d(`Could not connect.`)}finally{g(!1)}},[r,h,o]),Y=(0,f.useCallback)(async e=>{e.preventDefault(),d(``),await q(r)},[r]),X=(0,f.useCallback)(async()=>{S(!0);try{if(!await u())return console.warn(`[admin-ui] claude-disconnect not verified — credentials may persist; staying put`),!1;U(!1),w(null),A(null),M(void 0),P(null);try{sessionStorage.removeItem(`maxy-admin-session-key`)}catch{}return n(`connect-claude`),!0}finally{S(!1)}},[]),Z=(0,f.useCallback)(()=>{w(null),A(null),M(void 0),P(null);try{sessionStorage.removeItem(`maxy-admin-session-key`)}catch{}i(``),d(``),n(`enter-pin`)},[]);return(0,f.useEffect)(()=>{K.current=Z},[Z]),{appState:t,setAppState:n,pin:r,setPin:i,operatorName:o,setOperatorName:c,pinError:l,setPinError:d,showPin:p,setShowPin:m,pinLoading:h,authPolling:_,setAuthPolling:v,authLoading:y,setAuthLoading:b,disconnecting:x,cacheKey:C,setCacheKey:w,claudeInfo:T,setClaudeInfo:E,businessName:D,role:k,userName:j,userAvatar:N,sessionId:F,setSessionId:I,expandAll:L,setExpandAll:R,expandAllDefaultRef:z,remoteAuthEnabled:B,claudeConnected:H,pinInputRef:W,setPinFormRef:G,handleSetPin:J,handleLogin:Y,handleDisconnect:X,handleLogout:Z}}var m=n();function h({inputRef:e,value:t,onChange:n,onComplete:r,showPin:i,autoFocus:a}){let o=(0,f.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,m.jsx)(`div`,{className:`pin-field`,children:Array.from({length:6}).map((n,r)=>(0,m.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 g(e){let{pin:t,setPin:n,showPin:r,setShowPin:a,pinLoading:s,pinError:u,pinInputRef:d,setPinFormRef:f,onSubmit:p,operatorName:g,setOperatorName:_}=e;return(0,m.jsx)(`div`,{className:`connect-page`,children:(0,m.jsxs)(`div`,{className:`connect-content`,children:[(0,m.jsx)(`img`,{src:o,alt:i.productName,className:`connect-logo connect-logo--maxy`}),!i.logoContainsName&&(0,m.jsxs)(`h1`,{className:`connect-title`,children:[`Welcome to `,i.productName]}),(0,m.jsxs)(`p`,{className:`connect-subtitle`,children:[`Tell `,i.productName,` who you are, then choose a PIN.`]}),(0,m.jsxs)(`form`,{ref:f,onSubmit:p,className:`connect-pin-form`,children:[(0,m.jsxs)(`div`,{className:`pin-input-row`,children:[(0,m.jsx)(`input`,{type:`text`,className:`connect-name-input`,placeholder:`Your full name`,value:g,onChange:e=>_(e.target.value),autoComplete:`name`,autoFocus:!0,required:!0,"aria-label":`Your full name`}),(0,m.jsx)(`div`,{style:{width:38,flexShrink:0},"aria-hidden":`true`})]}),(0,m.jsxs)(`div`,{className:`pin-input-row`,children:[(0,m.jsx)(h,{inputRef:d,value:t,onChange:n,onComplete:()=>{},showPin:r}),(0,m.jsx)(c,{variant:`send`,type:`submit`,disabled:!t||!g.trim(),loading:s,"aria-label":`Set PIN`,children:(0,m.jsxs)(`svg`,{viewBox:`0 0 24 24`,fill:`none`,stroke:`currentColor`,strokeWidth:`2`,strokeLinecap:`round`,strokeLinejoin:`round`,children:[(0,m.jsx)(`line`,{x1:`5`,y1:`12`,x2:`19`,y2:`12`}),(0,m.jsx)(`polyline`,{points:`12 5 19 12 12 19`})]})})]}),(0,m.jsx)(l,{checked:r,onChange:()=>a(e=>!e),label:`Show PIN`})]}),u&&(0,m.jsx)(`p`,{className:`admin-pin-error`,children:u})]})})}function _(e){let{pin:t,setPin:n,showPin:r,setShowPin:a,pinLoading:s,pinError:u,pinInputRef:d,onSubmit:f,remoteAuthEnabled:p,onSignOutRemote:g}=e;return(0,m.jsxs)(`div`,{className:`connect-page`,children:[p&&g&&(0,m.jsx)(`button`,{type:`button`,className:`connect-signout`,onClick:g,children:`Sign out`}),(0,m.jsxs)(`div`,{className:`connect-content`,children:[(0,m.jsx)(`img`,{src:o,alt:i.productName,className:`connect-logo connect-logo--maxy`}),!i.logoContainsName&&(0,m.jsx)(`h1`,{className:`connect-title`,children:i.productName}),(0,m.jsxs)(`form`,{onSubmit:f,className:`connect-pin-form`,children:[(0,m.jsxs)(`div`,{className:`pin-input-row`,children:[(0,m.jsx)(h,{inputRef:d,value:t,onChange:n,onComplete:()=>{},showPin:r,autoFocus:!0}),(0,m.jsx)(c,{variant:`send`,type:`submit`,disabled:!t,loading:s,children:(0,m.jsxs)(`svg`,{viewBox:`0 0 24 24`,fill:`none`,stroke:`currentColor`,strokeWidth:`2`,strokeLinecap:`round`,strokeLinejoin:`round`,children:[(0,m.jsx)(`line`,{x1:`5`,y1:`12`,x2:`19`,y2:`12`}),(0,m.jsx)(`polyline`,{points:`12 5 19 12 12 19`})]})})]}),(0,m.jsx)(`div`,{className:`pin-options`,children:(0,m.jsx)(l,{checked:r,onChange:()=>a(e=>!e),label:`Show PIN`})})]}),u&&(0,m.jsx)(`p`,{className:`admin-pin-error`,children:u})]})]})}function v(e){let{authPolling:t,setAuthPolling:n,authLoading:r,setAuthLoading:a,pinError:s,setPinError:l,setAppState:u}=e,[p,h]=(0,f.useState)(!1),[g,_]=(0,f.useState)(!1),[v,y]=(0,f.useState)(``),[b,x]=(0,f.useState)(``),[S,C]=(0,f.useState)(``),[w,T]=(0,f.useState)(null),[E,D]=(0,f.useState)(null),[O,k]=(0,f.useState)(!1),A=(0,f.useRef)(0);(0,f.useEffect)(()=>{try{D(sessionStorage.getItem(`maxy-admin-session-key`))}catch{}k(!0)},[]);async function j(){C(``);try{let e=await(await fetch(`/api/onboarding/claude-auth`,{method:`POST`,headers:{"Content-Type":`application/json`},body:JSON.stringify({action:`paste-code`,code:b})})).json();e.accepted?(C(`Code submitted. Finishing sign-in…`),x(``)):C(e.error||`Could not submit code.`)}catch(e){console.error(`[admin] paste-code error:`,e),C(`Could not submit code.`)}}async function M(){_(!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?h(!0):e.error&&l(e.error)}catch(e){console.error(`[admin] browser launch error:`,e),l(`Could not launch browser.`)}_(!1)}async function N(){let e=++A.current;a(!0),l(``);try{let t=await(await fetch(`/api/onboarding/claude-auth`,{method:`POST`})).json();if(t.started){n(!0),h(!0),a(!1),y(t.transport||``);for(let t=0;t<120;t++){if(await new Promise(e=>setTimeout(e,2e3)),A.current!==e)return;let t=await(await fetch(`/api/onboarding/claude-auth`,{method:`POST`,headers:{"Content-Type":`application/json`},body:JSON.stringify({action:`wait`})})).json();if(typeof t.authTargetId==`string`&&T(t.authTargetId),t.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.`),n(!1)}else t.error&&l(t.error)}catch(e){console.error(`[admin] auth flow error:`,e),l(`Could not start auth flow.`)}a(!1)}async function P(){A.current++,await fetch(`/api/onboarding/claude-auth`,{method:`POST`,headers:{"Content-Type":`application/json`},body:JSON.stringify({action:`stop`})}),n(!1),l(``)}return t||p?(0,m.jsxs)(`div`,{style:{display:`flex`,flexDirection:`column`,height:`100dvh`,overflow:`auto`},children:[(0,m.jsxs)(`header`,{className:`chat-header`,style:{paddingBottom:`12px`,flexShrink:0,position:`relative`,maxWidth:`680px`,width:`100%`,margin:`0 auto`,padding:`24px 20px 12px`},children:[t?(0,m.jsx)(`button`,{onClick:P,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,m.jsx)(`button`,{onClick:()=>h(!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,m.jsx)(`img`,{src:`/brand/claude.png`,alt:`Claude`,className:`chat-logo`}),(0,m.jsx)(`h1`,{className:`chat-tagline`,children:`Connect Claude`}),(0,m.jsx)(`p`,{className:`chat-intro`,children:t?`Sign in and authorize in the browser below.`:`Open your email or prepare your accounts, then sign in.`}),!t&&(0,m.jsx)(`div`,{style:{marginTop:`12px`},children:(0,m.jsx)(c,{variant:`primary`,onClick:N,disabled:r,children:r?(0,m.jsxs)(m.Fragment,{children:[(0,m.jsx)(`span`,{className:`spin`,style:{display:`inline-block`},children:`✱`}),` Connecting…`]}):`Sign in to Claude`})}),t&&v===`native`&&(0,m.jsxs)(`div`,{style:{marginTop:`14px`,maxWidth:`420px`,margin:`14px auto 0`,display:`flex`,flexDirection:`column`,gap:`8px`},children:[(0,m.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,m.jsxs)(`div`,{style:{display:`flex`,gap:`8px`},children:[(0,m.jsx)(`input`,{type:`text`,value:b,onChange:e=>x(e.target.value),placeholder:`Paste code or redirect URL`,style:{flex:1,padding:`8px 10px`,fontSize:`13px`,border:`1px solid #ccc`,borderRadius:`6px`}}),(0,m.jsx)(c,{variant:`primary`,onClick:j,disabled:!b.trim(),children:`Submit`})]}),S&&(0,m.jsx)(`p`,{style:{fontSize:`12px`,color:`#999`,margin:0},children:S})]})]}),(0,m.jsx)(`div`,{style:{flex:1,display:`flex`,flexDirection:`column`,minHeight:0,gap:`10px`,padding:`0 0 16px`},children:O&&(0,m.jsx)(d,{preferTargetId:w,cacheKey:E,chrome:!1})}),s&&(0,m.jsx)(`p`,{className:`admin-pin-error`,style:{textAlign:`center`,padding:`0 20px 16px`},children:s})]}):(0,m.jsx)(`div`,{className:`connect-page`,children:(0,m.jsxs)(`div`,{className:`connect-content`,children:[(0,m.jsxs)(`div`,{className:`connect-logos`,children:[(0,m.jsx)(`div`,{className:`connect-logo-wrap`,children:(0,m.jsx)(`img`,{src:`/brand/claude.png`,alt:`Claude`,className:`connect-logo`})}),(0,m.jsx)(`svg`,{className:`connect-arrow`,viewBox:`0 0 48 24`,fill:`none`,xmlns:`http://www.w3.org/2000/svg`,children:(0,m.jsx)(`path`,{d:`M0 12h44m0 0l-8-8m8 8l-8 8`,stroke:`currentColor`,strokeWidth:`2`,strokeLinecap:`round`,strokeLinejoin:`round`})}),(0,m.jsxs)(`div`,{className:`connect-logo-wrap`,children:[(0,m.jsx)(`img`,{src:o,alt:i.productName,className:`connect-logo connect-logo--maxy`}),!i.logoContainsName&&(0,m.jsx)(`span`,{className:`connect-logo-label`,children:i.productName})]})]}),(0,m.jsxs)(`h1`,{className:`connect-title`,children:[`Connect Claude to power `,i.productName]}),(0,m.jsx)(`p`,{className:`connect-subtitle`,children:`Sign in with your Anthropic account to get started.`}),(0,m.jsx)(c,{variant:`primary`,onClick:N,disabled:r,children:r?(0,m.jsxs)(m.Fragment,{children:[(0,m.jsx)(`span`,{className:`spin`,style:{display:`inline-block`},children:`✱`}),` Connecting…`]}):`Sign in to Claude`}),(0,m.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,m.jsx)(`button`,{onClick:M,disabled:g,style:{marginTop:`12px`,background:`none`,border:`none`,color:`var(--color-primary, #666)`,fontSize:`13px`,cursor:`pointer`,textDecoration:`underline`,textUnderlineOffset:`3px`},children:g?`Launching…`:`Open browser first`}),s&&(0,m.jsx)(`p`,{className:`admin-pin-error`,children:s})]})})}function y({auth:e}){return e.appState===`loading`?(0,m.jsx)(r,{surface:`gate`}):e.appState===`set-pin`?(0,m.jsx)(g,{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,m.jsx)(v,{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,m.jsx)(_,{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:()=>{window.location.href=`/__remote-auth/logout`}}):null}export{p as n,y as t};
|
|
1
|
+
import{o as e}from"./chunk-BycB0eMI.js";import{i as t,t as n}from"./jsx-runtime-BY35JYDT.js";import{N as r,it as i,lt as a,ot as o}from"./useMediaQuery-e4ciNiuO.js";import{P as s}from"./useVoiceRecorder-Cvu4TePf.js";import{D as c,O as l,k as u,p as d}from"./AdminShell-Dm_nY4jF.js";var f=e(t(),1);function p(e=`admin`){let[t,n]=(0,f.useState)(`loading`),[r,i]=(0,f.useState)(``),[o,c]=(0,f.useState)(``),[l,d]=(0,f.useState)(``),[p,m]=(0,f.useState)(!1),[h,g]=(0,f.useState)(!1),[_,v]=(0,f.useState)(!1),[y,b]=(0,f.useState)(!1),[x,S]=(0,f.useState)(!1),[C,w]=(0,f.useState)(null),[T,E]=(0,f.useState)(null),[D,O]=(0,f.useState)(void 0),[k,A]=(0,f.useState)(null),[j,M]=(0,f.useState)(void 0),[N,P]=(0,f.useState)(null),[F,I]=(0,f.useState)(null),[L,R]=(0,f.useState)(void 0),z=(0,f.useRef)(void 0),[B,V]=(0,f.useState)(!1),[H,U]=(0,f.useState)(!0);(0,f.useEffect)(()=>{typeof window>`u`||fetch(`/api/remote-auth/status`).then(e=>e.ok?e.json():null).then(e=>{e?.configured&&V(!0)}).catch(()=>{})},[]);let W=(0,f.useRef)(null),G=(0,f.useRef)(null);(0,f.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();w(r.session_key),I(r.sessionId??null),O(r.businessName),A(r.role??null),M(r.userName===void 0?null:r.userName),P(r.avatar??null);let i=s(r.thinkingView);return z.current=i,R(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}U(!!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,f.useEffect)(()=>{t===`chat`&&C&&fetch(`/api/admin/claude-info?session_key=${encodeURIComponent(C)}`).then(e=>{if(e.ok)return e.json()}).then(e=>{e&&E(e)}).catch(()=>{})},[t,C]);let K=(0,f.useRef)(null);(0,f.useEffect)(()=>{if(t!==`chat`)return;let e=setInterval(async()=>{try{let e=await fetch(`/api/health`);if(e.ok){let t=await e.json();U(t.auth_status!==`dead`&&t.auth_status!==`missing`)}}catch{}if(C)try{let e=await fetch(`/api/admin/session?session_key=${encodeURIComponent(C)}`);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}`),K.current?.()}catch{}},300*1e3);return()=>clearInterval(e)},[t,C]),(0,f.useEffect)(()=>{t===`connect-claude`&&fetch(`/api/health`).then(e=>e.ok?e.json():null).then(e=>{e?.claude_authenticated&&(U(!0),n(`enter-pin`))}).catch(()=>{})},[t]);async function q(e,t){g(!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}d(e.error||`Invalid PIN`);return}let o=await r.json();w(o.session_key),I(o.sessionId??null),O(o.businessName),A(o.role??null),M(o.userName===void 0?null:o.userName),P(o.avatar??null);let c=s(o.thinkingView);z.current=c,R(c);try{sessionStorage.setItem(`maxy-admin-session-key`,o.session_key)}catch{}i(``),n(`chat`)}catch(e){console.error(`[admin] connection error:`,e),d(`Could not connect.`)}finally{g(!1)}}let J=(0,f.useCallback)(async e=>{if(e.preventDefault(),h)return;d(``);let t=o.trim();if(!t){d(`Please enter your name.`);return}if(r.length<4){d(`PIN must be at least 4 characters.`);return}let s=r;g(!0);try{let e=await fetch(`/api/onboarding/set-pin`,{method:`POST`,headers:{"Content-Type":`application/json`},body:JSON.stringify({pin:s,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){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`):d(t.error||`Failed to set PIN.`)}else n(`enter-pin`)}catch{n(`enter-pin`)}return}d(t.error||`Failed to set PIN.`);return}let r=await fetch(`/api/health`);if((r.ok?await r.json():null)?.claude_authenticated){await q(s);return}i(``),n(`connect-claude`)}catch(e){console.error(`[admin] connection error:`,e),d(`Could not connect.`)}finally{g(!1)}},[r,h,o]),Y=(0,f.useCallback)(async e=>{e.preventDefault(),d(``),await q(r)},[r]),X=(0,f.useCallback)(async()=>{S(!0);try{if(!await u())return console.warn(`[admin-ui] claude-disconnect not verified — credentials may persist; staying put`),!1;U(!1),w(null),A(null),M(void 0),P(null);try{sessionStorage.removeItem(`maxy-admin-session-key`)}catch{}return n(`connect-claude`),!0}finally{S(!1)}},[]),Z=(0,f.useCallback)(()=>{w(null),A(null),M(void 0),P(null);try{sessionStorage.removeItem(`maxy-admin-session-key`)}catch{}i(``),d(``),n(`enter-pin`)},[]);return(0,f.useEffect)(()=>{K.current=Z},[Z]),{appState:t,setAppState:n,pin:r,setPin:i,operatorName:o,setOperatorName:c,pinError:l,setPinError:d,showPin:p,setShowPin:m,pinLoading:h,authPolling:_,setAuthPolling:v,authLoading:y,setAuthLoading:b,disconnecting:x,cacheKey:C,setCacheKey:w,claudeInfo:T,setClaudeInfo:E,businessName:D,role:k,userName:j,userAvatar:N,sessionId:F,setSessionId:I,expandAll:L,setExpandAll:R,expandAllDefaultRef:z,remoteAuthEnabled:B,claudeConnected:H,pinInputRef:W,setPinFormRef:G,handleSetPin:J,handleLogin:Y,handleDisconnect:X,handleLogout:Z}}var m=n();function h({inputRef:e,value:t,onChange:n,onComplete:r,showPin:i,autoFocus:a}){let o=(0,f.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,m.jsx)(`div`,{className:`pin-field`,children:Array.from({length:6}).map((n,r)=>(0,m.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 g(e){let{pin:t,setPin:n,showPin:r,setShowPin:a,pinLoading:s,pinError:u,pinInputRef:d,setPinFormRef:f,onSubmit:p,operatorName:g,setOperatorName:_}=e;return(0,m.jsx)(`div`,{className:`connect-page`,children:(0,m.jsxs)(`div`,{className:`connect-content`,children:[(0,m.jsx)(`img`,{src:o,alt:i.productName,className:`connect-logo connect-logo--maxy`}),!i.logoContainsName&&(0,m.jsxs)(`h1`,{className:`connect-title`,children:[`Welcome to `,i.productName]}),(0,m.jsxs)(`p`,{className:`connect-subtitle`,children:[`Tell `,i.productName,` who you are, then choose a PIN.`]}),(0,m.jsxs)(`form`,{ref:f,onSubmit:p,className:`connect-pin-form`,children:[(0,m.jsxs)(`div`,{className:`pin-input-row`,children:[(0,m.jsx)(`input`,{type:`text`,className:`connect-name-input`,placeholder:`Your full name`,value:g,onChange:e=>_(e.target.value),autoComplete:`name`,autoFocus:!0,required:!0,"aria-label":`Your full name`}),(0,m.jsx)(`div`,{style:{width:38,flexShrink:0},"aria-hidden":`true`})]}),(0,m.jsxs)(`div`,{className:`pin-input-row`,children:[(0,m.jsx)(h,{inputRef:d,value:t,onChange:n,onComplete:()=>{},showPin:r}),(0,m.jsx)(c,{variant:`send`,type:`submit`,disabled:!t||!g.trim(),loading:s,"aria-label":`Set PIN`,children:(0,m.jsxs)(`svg`,{viewBox:`0 0 24 24`,fill:`none`,stroke:`currentColor`,strokeWidth:`2`,strokeLinecap:`round`,strokeLinejoin:`round`,children:[(0,m.jsx)(`line`,{x1:`5`,y1:`12`,x2:`19`,y2:`12`}),(0,m.jsx)(`polyline`,{points:`12 5 19 12 12 19`})]})})]}),(0,m.jsx)(l,{checked:r,onChange:()=>a(e=>!e),label:`Show PIN`})]}),u&&(0,m.jsx)(`p`,{className:`admin-pin-error`,children:u})]})})}function _(e){let{pin:t,setPin:n,showPin:r,setShowPin:a,pinLoading:s,pinError:u,pinInputRef:d,onSubmit:f,remoteAuthEnabled:p,onSignOutRemote:g}=e;return(0,m.jsxs)(`div`,{className:`connect-page`,children:[p&&g&&(0,m.jsx)(`button`,{type:`button`,className:`connect-signout`,onClick:g,children:`Sign out`}),(0,m.jsxs)(`div`,{className:`connect-content`,children:[(0,m.jsx)(`img`,{src:o,alt:i.productName,className:`connect-logo connect-logo--maxy`}),!i.logoContainsName&&(0,m.jsx)(`h1`,{className:`connect-title`,children:i.productName}),(0,m.jsxs)(`form`,{onSubmit:f,className:`connect-pin-form`,children:[(0,m.jsxs)(`div`,{className:`pin-input-row`,children:[(0,m.jsx)(h,{inputRef:d,value:t,onChange:n,onComplete:()=>{},showPin:r,autoFocus:!0}),(0,m.jsx)(c,{variant:`send`,type:`submit`,disabled:!t,loading:s,children:(0,m.jsxs)(`svg`,{viewBox:`0 0 24 24`,fill:`none`,stroke:`currentColor`,strokeWidth:`2`,strokeLinecap:`round`,strokeLinejoin:`round`,children:[(0,m.jsx)(`line`,{x1:`5`,y1:`12`,x2:`19`,y2:`12`}),(0,m.jsx)(`polyline`,{points:`12 5 19 12 12 19`})]})})]}),(0,m.jsx)(`div`,{className:`pin-options`,children:(0,m.jsx)(l,{checked:r,onChange:()=>a(e=>!e),label:`Show PIN`})})]}),u&&(0,m.jsx)(`p`,{className:`admin-pin-error`,children:u})]})]})}function v(e){let{authPolling:t,setAuthPolling:n,authLoading:r,setAuthLoading:a,pinError:s,setPinError:l,setAppState:u}=e,[p,h]=(0,f.useState)(!1),[g,_]=(0,f.useState)(!1),[v,y]=(0,f.useState)(``),[b,x]=(0,f.useState)(``),[S,C]=(0,f.useState)(``),[w,T]=(0,f.useState)(null),[E,D]=(0,f.useState)(null),[O,k]=(0,f.useState)(!1),A=(0,f.useRef)(0);(0,f.useEffect)(()=>{try{D(sessionStorage.getItem(`maxy-admin-session-key`))}catch{}k(!0)},[]);async function j(){C(``);try{let e=await(await fetch(`/api/onboarding/claude-auth`,{method:`POST`,headers:{"Content-Type":`application/json`},body:JSON.stringify({action:`paste-code`,code:b})})).json();e.accepted?(C(`Code submitted. Finishing sign-in…`),x(``)):C(e.error||`Could not submit code.`)}catch(e){console.error(`[admin] paste-code error:`,e),C(`Could not submit code.`)}}async function M(){_(!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?h(!0):e.error&&l(e.error)}catch(e){console.error(`[admin] browser launch error:`,e),l(`Could not launch browser.`)}_(!1)}async function N(){let e=++A.current;a(!0),l(``);try{let t=await(await fetch(`/api/onboarding/claude-auth`,{method:`POST`})).json();if(t.started){n(!0),h(!0),a(!1),y(t.transport||``);for(let t=0;t<120;t++){if(await new Promise(e=>setTimeout(e,2e3)),A.current!==e)return;let t=await(await fetch(`/api/onboarding/claude-auth`,{method:`POST`,headers:{"Content-Type":`application/json`},body:JSON.stringify({action:`wait`})})).json();if(typeof t.authTargetId==`string`&&T(t.authTargetId),t.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.`),n(!1)}else t.error&&l(t.error)}catch(e){console.error(`[admin] auth flow error:`,e),l(`Could not start auth flow.`)}a(!1)}async function P(){A.current++,await fetch(`/api/onboarding/claude-auth`,{method:`POST`,headers:{"Content-Type":`application/json`},body:JSON.stringify({action:`stop`})}),n(!1),l(``)}return t||p?(0,m.jsxs)(`div`,{style:{display:`flex`,flexDirection:`column`,height:`100dvh`,overflow:`auto`},children:[(0,m.jsxs)(`header`,{className:`chat-header`,style:{paddingBottom:`12px`,flexShrink:0,position:`relative`,maxWidth:`680px`,width:`100%`,margin:`0 auto`,padding:`24px 20px 12px`},children:[t?(0,m.jsx)(`button`,{onClick:P,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,m.jsx)(`button`,{onClick:()=>h(!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,m.jsx)(`img`,{src:`/brand/claude.png`,alt:`Claude`,className:`chat-logo`}),(0,m.jsx)(`h1`,{className:`chat-tagline`,children:`Connect Claude`}),(0,m.jsx)(`p`,{className:`chat-intro`,children:t?`Sign in and authorize in the browser below.`:`Open your email or prepare your accounts, then sign in.`}),!t&&(0,m.jsx)(`div`,{style:{marginTop:`12px`},children:(0,m.jsx)(c,{variant:`primary`,onClick:N,disabled:r,children:r?(0,m.jsxs)(m.Fragment,{children:[(0,m.jsx)(`span`,{className:`spin`,style:{display:`inline-block`},children:`✱`}),` Connecting…`]}):`Sign in to Claude`})}),t&&v===`native`&&(0,m.jsxs)(`div`,{style:{marginTop:`14px`,maxWidth:`420px`,margin:`14px auto 0`,display:`flex`,flexDirection:`column`,gap:`8px`},children:[(0,m.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,m.jsxs)(`div`,{style:{display:`flex`,gap:`8px`},children:[(0,m.jsx)(`input`,{type:`text`,value:b,onChange:e=>x(e.target.value),placeholder:`Paste code or redirect URL`,style:{flex:1,padding:`8px 10px`,fontSize:`13px`,border:`1px solid #ccc`,borderRadius:`6px`}}),(0,m.jsx)(c,{variant:`primary`,onClick:j,disabled:!b.trim(),children:`Submit`})]}),S&&(0,m.jsx)(`p`,{style:{fontSize:`12px`,color:`#999`,margin:0},children:S})]})]}),(0,m.jsx)(`div`,{style:{flex:1,display:`flex`,flexDirection:`column`,minHeight:0,gap:`10px`,padding:`0 0 16px`},children:O&&(0,m.jsx)(d,{preferTargetId:w,cacheKey:E,chrome:!1})}),s&&(0,m.jsx)(`p`,{className:`admin-pin-error`,style:{textAlign:`center`,padding:`0 20px 16px`},children:s})]}):(0,m.jsx)(`div`,{className:`connect-page`,children:(0,m.jsxs)(`div`,{className:`connect-content`,children:[(0,m.jsxs)(`div`,{className:`connect-logos`,children:[(0,m.jsx)(`div`,{className:`connect-logo-wrap`,children:(0,m.jsx)(`img`,{src:`/brand/claude.png`,alt:`Claude`,className:`connect-logo`})}),(0,m.jsx)(`svg`,{className:`connect-arrow`,viewBox:`0 0 48 24`,fill:`none`,xmlns:`http://www.w3.org/2000/svg`,children:(0,m.jsx)(`path`,{d:`M0 12h44m0 0l-8-8m8 8l-8 8`,stroke:`currentColor`,strokeWidth:`2`,strokeLinecap:`round`,strokeLinejoin:`round`})}),(0,m.jsxs)(`div`,{className:`connect-logo-wrap`,children:[(0,m.jsx)(`img`,{src:o,alt:i.productName,className:`connect-logo connect-logo--maxy`}),!i.logoContainsName&&(0,m.jsx)(`span`,{className:`connect-logo-label`,children:i.productName})]})]}),(0,m.jsxs)(`h1`,{className:`connect-title`,children:[`Connect Claude to power `,i.productName]}),(0,m.jsx)(`p`,{className:`connect-subtitle`,children:`Sign in with your Anthropic account to get started.`}),(0,m.jsx)(c,{variant:`primary`,onClick:N,disabled:r,children:r?(0,m.jsxs)(m.Fragment,{children:[(0,m.jsx)(`span`,{className:`spin`,style:{display:`inline-block`},children:`✱`}),` Connecting…`]}):`Sign in to Claude`}),(0,m.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,m.jsx)(`button`,{onClick:M,disabled:g,style:{marginTop:`12px`,background:`none`,border:`none`,color:`var(--color-primary, #666)`,fontSize:`13px`,cursor:`pointer`,textDecoration:`underline`,textUnderlineOffset:`3px`},children:g?`Launching…`:`Open browser first`}),s&&(0,m.jsx)(`p`,{className:`admin-pin-error`,children:s})]})})}function y({auth:e}){return e.appState===`loading`?(0,m.jsx)(r,{surface:`gate`}):e.appState===`set-pin`?(0,m.jsx)(g,{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,m.jsx)(v,{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,m.jsx)(_,{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:()=>{window.location.href=`/__remote-auth/logout`}}):null}export{p as n,y as t};
|
|
Binary file
|
|
Binary file
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import{o as e}from"./chunk-BycB0eMI.js";import{i as t,n,t as r}from"./jsx-runtime-BY35JYDT.js";import{C as i,E as a,F as o,P as s,R as c,ct as l,h as u,i as d,k as f,p,y as ee}from"./useMediaQuery-e4ciNiuO.js";import{n as m,t as h}from"./AdminLoginScreens-Bjsr45ed.js";import{T as g,c as _,p as te}from"./useVoiceRecorder-D7_wLtrS.js";import{h as ne,i as v,t as y,w as re,x as b}from"./AdminShell-Dm_nY4jF.js";import{t as x}from"./chevron-left-D3_hiHLC.js";import{i as S,n as C,r as ie}from"./page-CdRrpkky.js";import{t as ae}from"./file-text-CVZAL3Er.js";import"./graph-labels-BTFUSc63.js";import{n as oe}from"./file-download-B7zwa78w.js";var w=n(),T=e(t(),1),E=r();function D({onOpen:e}){return(0,E.jsx)(`footer`,{className:`admin-footer`,children:(0,E.jsxs)(`div`,{className:`powered-by`,role:`button`,tabIndex:0,onClick:e,onKeyDown:t=>{(t.key===`Enter`||t.key===` `)&&(t.preventDefault(),e())},"aria-label":`Powered by Claude Code — show details`,children:[(0,E.jsx)(`img`,{src:`/brand/claude.png`,alt:`Claude`,className:`powered-by-icon`}),(0,E.jsx)(`span`,{children:`Powered by Claude Code`})]})})}function O({sessionId:e,projectDir:t,sessionKey:n,contactName:r,onBack:i}){return(0,E.jsxs)(`div`,{className:`wa-web`,children:[(0,E.jsxs)(`header`,{className:`wa-web-header`,children:[i&&(0,E.jsx)(`button`,{type:`button`,className:`wa-web-back`,onClick:i,"aria-label":`Back`,children:(0,E.jsx)(x,{size:20})}),(0,E.jsx)(`span`,{className:`wa-web-avatar`,"aria-hidden":!0,children:(0,E.jsx)(g,{size:20})}),(0,E.jsx)(`div`,{className:`wa-web-titles`,children:(0,E.jsx)(`span`,{className:`wa-web-name`,children:r})})]}),(0,E.jsx)(`div`,{className:`wa-web-body`,children:(0,E.jsx)(_,{sessionId:e,projectDir:t,sessionKey:n,forceDeliveredOnly:!0})})]})}var k=6e4,A=60*k,j=24*A,M=k,N=[`Jan`,`Feb`,`Mar`,`Apr`,`May`,`Jun`,`Jul`,`Aug`,`Sep`,`Oct`,`Nov`,`Dec`],P=[`Sun`,`Mon`,`Tue`,`Wed`,`Thu`,`Fri`,`Sat`];function F(e){return e<10?`0${e}`:String(e)}function I(e,t){let n=f(e,t);return Date.UTC(n.y,n.m-1,n.d)}function L(e,t,n){if(!Number.isFinite(e)||e<=0||!Number.isFinite(t))return`—`;let r=t-e;if(r<-M)return`—`;let i=r<0?0:r;if(i<k)return`just now`;if(i<A)return`${Math.floor(i/k)}m`;if(i<j)return`${Math.floor(i/A)}h`;let a=I(new Date(t),n),o=I(new Date(e),n),s=Math.round((a-o)/j);if(s===1)return`yesterday`;let c=f(new Date(e),n);if(s>=2&&s<=6)return P[new Date(o).getUTCDay()];let l=F(c.d),u=N[c.m-1],d=f(new Date(t),n).y;return c.y===d?`${l} ${u}`:`${l} ${u} ${c.y}`}function R({variant:e=`row`,count:t=1}){return(0,E.jsx)(E.Fragment,{children:Array.from({length:t},(t,n)=>(0,E.jsx)(`span`,{className:`dashboard-skeleton dashboard-skeleton--${e}`,"data-testid":`dashboard-skeleton`,"aria-hidden":`true`},n))})}var se=6e4;function ce(e){return e<12?`morning`:e<18?`afternoon`:`evening`}function z(e){return e&&e.trim().split(/\s+/)[0]||`there`}function le(e){if(!e)return`everything is running normally.`;let t=e.cpuPct,n=e.memUsedPct;return t!==null&&t>=.98||n!==null&&n>=.98?`system load is critical.`:t!==null&&t>=.9||n!==null&&n>=.9?`system load is high.`:`everything is running normally.`}function B(e){return e==null?`—`:`${Math.round(e*100)}%`}function V(e){let t=Date.parse(e.lastMessageAt??``);return Number.isFinite(t)?t:-1/0}function ue(e,t,n){if(!e)return!1;let r=Date.parse(e);return Number.isFinite(r)?a(new Date(r),n)===a(new Date(t),n):!1}function de(e){return e?e.replace(/^claude-/,``):null}function fe(e,t,n,r,i){let a=0;for(let e=1;e<n.length;e+=1)V(n[e-1])<V(n[e])&&(a+=1);let o=!1;for(let e=1;e<t.length;e+=1)if(t[e-1].channel!==t[e].channel){o=!0;break}let s=new Map;for(let t of e)s.set(t.channel,(s.get(t.channel)??0)+1);return{feedRows:e.length,renderedRows:n.length,cap:r,hidden:e.length-n.length,expanded:i,outOfOrder:a,undated:e.filter(e=>V(e)===-1/0).length,channels:[...s.entries()].map(([e,t])=>`${e}:${t}`).join(`,`),interleaved:o}}var H=new Set([`sessions`,`conversations`,`tasks`,`artefacts`,`skills`,`stats`]),U=!1;function pe(e,t,n,r){let i=e=>t.get(e)??null,a=r?r.getEntriesByType(`navigation`)[0]:void 0,o=r?r.getEntriesByType(`resource`).filter(e=>new URL(e.name,`http://x`).pathname.startsWith(`/assets/`)):[],s=e=>e===void 0||!Number.isFinite(e)?null:Math.round(e),c=e=>e?s(e):null;return{batchMs:e,sessionsMs:i(`sessions`),conversationsMs:i(`conversations`),tasksMs:i(`tasks`),artefactsMs:i(`artefacts`),skillsMs:i(`skills`),statsMs:i(`stats`),failed:[...H].filter(e=>n.has(e)).join(`,`)||`none`,ttfbMs:s(a?.responseStart),domContentLoadedMs:c(a?.domContentLoadedEventEnd),loadMs:c(a?.loadEventEnd),assetCount:o.length,assetBytes:o.reduce((e,t)=>e+(t.transferSize||0),0),assetMs:o.length?s(Math.max(...o.map(e=>e.responseEnd))):null}}function W({cacheKey:e,userName:t,onSelectWhatsappConversation:n}){let{zone:r}=i(),a=o(e),[s,f]=(0,T.useState)(null),[m,h]=(0,T.useState)(null),[g,_]=(0,T.useState)(null),[v,y]=(0,T.useState)(null),[x,S]=(0,T.useState)(null),[C,ie]=(0,T.useState)(null),[w,D]=(0,T.useState)(null),[O,k]=(0,T.useState)(null),[A,j]=(0,T.useState)(null),[M,N]=(0,T.useState)(new Set),[P,F]=(0,T.useState)(()=>new Set),I=(0,T.useCallback)(e=>{F(t=>t.has(e)?t:new Set(t).add(e))},[]),H=Date.now(),W=(0,T.useRef)(!1),G=(0,T.useRef)(new Map),me=(0,T.useRef)(new Set),K=(0,T.useRef)(null);(0,T.useEffect)(()=>{if(!e)return;let t=!1;async function n(e,n,r,i){let o=Date.now(),s=typeof n==`string`?n:`unresolved`;try{typeof n!=`string`&&(s=await n());let e=await a(s);if(!e.ok)throw Error(`status ${e.status}`);let o=await e.json();t||i(r(o))}catch(t){me.current.add(e),console.error(`[admin-ui] dashboard-fetch-failed slice=${e} url=${s} ms=${Date.now()-o} reason=${t instanceof Error?t.message:String(t)}`)}finally{G.current.set(e,Date.now()-o),I(e)}}async function r(){if(!K.current){let e=await a(`/api/admin/accounts`);if(!e.ok)throw Error(`accounts status ${e.status}`);let t=await e.json(),n=t.accounts??[],r=t.activeAccountId??null,i=n.find(e=>e.accountId===r);if(!i)throw Error(`accounts: active ${r??`none`} absent from list of ${n.length}`);let o=i.isHouse||n.length===1;K.current={accountId:i.accountId,isHouse:o}}let{accountId:e,isHouse:t}=K.current;return t?`/api/operator-conversations/conversations-all`:`/api/operator-conversations/conversations`}let i={"sidebar-sessions":()=>n(`sessions`,`/api/admin/sidebar-sessions`,e=>e.sessions??[],f),"conversations-all":()=>n(`conversations`,r,e=>e.conversations??[],h),"tasks-list":()=>n(`tasks`,`/api/admin/tasks-list`,e=>e,y),"sidebar-artefacts":()=>n(`artefacts`,`/api/admin/sidebar-artefacts`,e=>e.artefacts??[],S),skills:()=>n(`skills`,`/api/admin/skills`,e=>e.skills??[],ie)};async function o(){if(W.current)return;W.current=!0;let e=Date.now();try{await Promise.all([...Object.values(i).map(e=>e()),n(`stats`,`/api/admin/system-stats`,e=>e,_),n(`bookingLink`,`/api/admin/calendar/booking-link`,e=>e.bookingDomain??null,D),n(`portalLink`,`/api/admin/data-portal/portal-link`,e=>e.portalDomain??null,k),n(`plannerLink`,`/api/admin/dispatch-planner/planner-link`,e=>e.plannerUrl??null,j)])}finally{W.current=!1;let t=Date.now()-e;if(!U){U=!0;try{let e=pe(t,G.current,me.current,typeof performance>`u`?null:performance);fetch(`/api/_client-error`,{method:`POST`,headers:{"content-type":`application/json`},body:JSON.stringify({kind:`event`,source:`dashboard-load`,...e}),keepalive:!0}).catch(()=>{})}catch{}}}}o();let s=null;try{s=new EventSource(l(`/api/admin/events`,e)),s.onmessage=e=>{if(document.visibilityState===`visible`)try{let{resource:t}=JSON.parse(e.data),n=t?i[t]:void 0;n&&n()}catch{}},s.onerror=()=>{console.error(`[admin-ui] dashboard-events stream error`)}}catch(e){console.error(`[admin-ui] dashboard-events unavailable reason=${e instanceof Error?e.message:String(e)}`)}let c=setInterval(()=>{document.visibilityState===`visible`&&o()},se),u=()=>{document.visibilityState===`visible`&&o()};return document.addEventListener(`visibilitychange`,u),()=>{t=!0,W.current=!1,clearInterval(c),s?.close(),document.removeEventListener(`visibilitychange`,u)}},[e,a]);let q=(0,T.useMemo)(()=>(s??[]).filter(e=>!e.isSubagent),[s]),J=(0,T.useMemo)(()=>q.filter(e=>e.live),[q]),he=(0,T.useMemo)(()=>(m??[]).filter(e=>ue(e.lastMessageAt,H,r)).length,[m,H]),ge=v?.open.length??0,Y=(0,T.useMemo)(()=>[...m??[]].sort((e,t)=>{let n=V(e),r=V(t);return n===r?0:r>n?1:-1}),[m]),[X,_e]=(0,T.useState)(!1),Z=X?Y:Y.slice(0,8),ve=Y.length-Z.length,ye=(0,T.useRef)(null),Q=(0,T.useRef)(null);(0,T.useEffect)(()=>{if(!P.has(`conversations`))return;let e=fe(m??[],Y,Z,8,X),t=JSON.stringify(e);ye.current!==t&&(ye.current=t,Q.current===null&&(Q.current=d()),fetch(`/api/_client-error`,{method:`POST`,headers:{"content-type":`application/json`},body:JSON.stringify({kind:`event`,source:`channels-card`,renderId:Q.current,...e})}).catch(()=>{}))},[P,m,Y,Z,X]);let be=(0,T.useRef)(!1);(0,T.useEffect)(()=>{be.current||!P.has(`bookingLink`)||!P.has(`portalLink`)||!P.has(`plannerLink`)||(be.current=!0)},[P,w,O,A]);let xe=(0,T.useCallback)(async e=>{if(!M.has(e)){N(t=>new Set(t).add(e));try{let t=await a(`/api/admin/session-stop`,{method:`POST`,headers:{"Content-Type":`application/json`},body:JSON.stringify({sessionId:e})});if(!t.ok){console.error(`[admin-ui] dashboard-session-stop-failed sessionId=${e} status=${t.status}`);return}f(t=>(t??[]).map(t=>t.sessionId===e?{...t,live:!1}:t))}catch(t){console.error(`[admin-ui] dashboard-session-stop-failed sessionId=${e} reason=${t instanceof Error?t.message:String(t)}`)}finally{N(t=>{let n=new Set(t);return n.delete(e),n})}}},[a,M]),Se=(0,T.useCallback)(t=>{if(!e||!t.downloadPath){console.error(`[admin-ui] dashboard-artefact-download-blocked id=${t.id} reason=${e?`not-downloadable`:`no-cache-key`}`);return}oe(e,t.downloadPath,t.downloadRoot??`data`)},[e]),$=ce(new Date(H).getHours());return(0,E.jsxs)(`div`,{className:`ui-page ui-page--full dashboard-home`,children:[(0,E.jsx)(`p`,{className:`dashboard-greeting`,children:P.has(`stats`)?`Good ${$}, ${z(t)} — ${le(g)}`:`Good ${$}, ${z(t)}`}),(0,E.jsxs)(`div`,{className:`dashboard-stats`,children:[(0,E.jsxs)(`div`,{className:`admin-stat-card dashboard-stat-card`,children:[(0,E.jsx)(`span`,{className:`dashboard-stat-label`,children:`Live sessions`}),P.has(`sessions`)?(0,E.jsxs)(E.Fragment,{children:[(0,E.jsx)(`span`,{className:`dashboard-stat-value`,children:J.length}),(0,E.jsxs)(`span`,{className:`dashboard-stat-delta`,children:[`of `,q.length,` total`]})]}):(0,E.jsx)(R,{variant:`value`})]}),(0,E.jsxs)(`div`,{className:`admin-stat-card dashboard-stat-card`,children:[(0,E.jsx)(`span`,{className:`dashboard-stat-label`,children:`Messages today`}),P.has(`conversations`)?(0,E.jsx)(`span`,{className:`dashboard-stat-value`,children:he}):(0,E.jsx)(R,{variant:`value`})]}),(0,E.jsxs)(`a`,{className:`admin-stat-card dashboard-stat-card dashboard-stat-card--link`,href:`/tasks`,children:[(0,E.jsx)(`span`,{className:`dashboard-stat-label`,children:`Open tasks`}),P.has(`tasks`)?(0,E.jsx)(`span`,{className:`dashboard-stat-value`,children:ge}):(0,E.jsx)(R,{variant:`value`})]}),(0,E.jsxs)(`div`,{className:`admin-stat-card dashboard-stat-card`,children:[(0,E.jsx)(`span`,{className:`dashboard-stat-label`,children:`Host CPU`}),P.has(`stats`)?(0,E.jsxs)(E.Fragment,{children:[(0,E.jsx)(`span`,{className:`dashboard-stat-value`,children:B(g?.cpuPct??null)}),(0,E.jsxs)(`span`,{className:`dashboard-stat-delta`,children:[`RAM `,B(g?.memUsedPct??null)]})]}):(0,E.jsx)(R,{variant:`value`})]})]}),(0,E.jsxs)(`div`,{className:`dashboard-columns`,children:[(0,E.jsxs)(`div`,{className:`dashboard-col`,children:[(w||O||A)&&(0,E.jsxs)(E.Fragment,{children:[(0,E.jsx)(`span`,{className:`admin-section-label dashboard-col-label`,children:`Public pages`}),(0,E.jsxs)(`div`,{className:`admin-card dashboard-public-pages`,children:[w&&(0,E.jsxs)(`a`,{className:`admin-row dashboard-public-row`,href:`https://${w}`,target:`_blank`,rel:`noopener noreferrer`,children:[(0,E.jsx)(`span`,{className:`dashboard-public-icon`,children:(0,E.jsx)(b,{size:16})}),(0,E.jsx)(`span`,{className:`dashboard-public-name`,children:`Booking page`})]}),O&&(0,E.jsxs)(`a`,{className:`admin-row dashboard-public-row`,href:`https://${O}`,target:`_blank`,rel:`noopener noreferrer`,children:[(0,E.jsx)(`span`,{className:`dashboard-public-icon`,children:(0,E.jsx)(b,{size:16})}),(0,E.jsx)(`span`,{className:`dashboard-public-name`,children:`File drop`})]}),A&&(0,E.jsxs)(`a`,{className:`admin-row dashboard-public-row`,href:A,target:`_blank`,rel:`noopener noreferrer`,children:[(0,E.jsx)(`span`,{className:`dashboard-public-icon`,children:(0,E.jsx)(b,{size:16})}),(0,E.jsx)(`span`,{className:`dashboard-public-name`,children:`Planner`})]})]})]}),(0,E.jsx)(`span`,{className:`admin-section-label dashboard-col-label`,children:`Live now`}),P.has(`sessions`)?J.length===0?(0,E.jsx)(`div`,{className:`admin-card dashboard-empty`,children:`No live sessions right now.`}):J.map(e=>{let t=[e.sessionId.slice(0,8),de(e.model),L(Date.parse(e.startedAt),H,r)].filter(Boolean).join(` · `);return(0,E.jsxs)(`div`,{className:`admin-card dashboard-live-card`,children:[(0,E.jsx)(`span`,{className:`admin-status-dot is-live`}),(0,E.jsxs)(`div`,{className:`dashboard-live-main`,children:[(0,E.jsx)(`span`,{className:`dashboard-live-name`,children:e.title}),(0,E.jsx)(`span`,{className:`dashboard-live-meta`,children:t})]}),(0,E.jsx)(`a`,{className:`admin-btn-cta dashboard-open-btn`,href:`/chat?session=${encodeURIComponent(e.sessionId)}`,children:`Open`}),(0,E.jsx)(`button`,{type:`button`,className:`dashboard-stop-btn`,"aria-label":`Stop ${e.title}`,disabled:M.has(e.sessionId),onClick:()=>void xe(e.sessionId),children:(0,E.jsx)(c,{size:12})})]},e.sessionId)}):(0,E.jsx)(R,{variant:`card`,count:2}),(0,E.jsx)(`span`,{className:`admin-section-label dashboard-col-label`,children:`Recent artefacts`}),(0,E.jsx)(`div`,{className:`admin-card dashboard-artefacts`,children:P.has(`artefacts`)?(x??[]).length===0?(0,E.jsx)(`div`,{className:`dashboard-empty`,children:`No recent artefacts.`}):(x??[]).slice(0,6).map(e=>(0,E.jsxs)(`button`,{type:`button`,className:`admin-row dashboard-artefact-row`,onClick:()=>Se(e),children:[(0,E.jsx)(`span`,{className:`dashboard-artefact-icon`,children:e.kind===`agent-template`?(0,E.jsx)(re,{size:16}):(0,E.jsx)(ae,{size:16})}),(0,E.jsx)(`div`,{className:`dashboard-artefact-body`,children:(0,E.jsx)(`span`,{className:`dashboard-artefact-name`,children:e.name})}),(0,E.jsx)(`span`,{className:`dashboard-artefact-time`,children:L(Date.parse(e.updatedAt),H,r)})]},e.id)):(0,E.jsx)(R,{count:3})}),(0,E.jsx)(`a`,{className:`admin-section-label dashboard-col-label dashboard-skills-label`,href:`/skills`,children:`Skills`}),(0,E.jsx)(`div`,{className:`admin-card dashboard-skills`,children:P.has(`skills`)?(C??[]).length===0?(0,E.jsx)(`div`,{className:`dashboard-empty`,children:`No skills yet.`}):(C??[]).map(e=>(0,E.jsxs)(`a`,{className:`admin-row dashboard-skill-row`,href:`/skills`,children:[(0,E.jsx)(`span`,{className:`dashboard-skill-icon`,children:(0,E.jsx)(ne,{size:16})}),(0,E.jsxs)(`div`,{className:`dashboard-skill-body`,children:[(0,E.jsx)(`span`,{className:`dashboard-skill-name`,children:e.skill}),(0,E.jsx)(`span`,{className:`dashboard-skill-plugin`,children:e.plugin})]})]},`${e.plugin}/${e.skill}`)):(0,E.jsx)(R,{count:2})})]}),(0,E.jsxs)(`div`,{className:`dashboard-col`,children:[(0,E.jsx)(`span`,{className:`admin-section-label dashboard-col-label`,children:`Channels`}),P.has(`conversations`)?Y.length===0?(0,E.jsx)(`div`,{className:`admin-card dashboard-empty`,children:`No channel activity.`}):(0,E.jsxs)(`div`,{className:`admin-card dashboard-channel-card`,children:[(0,E.jsx)(`div`,{className:`dashboard-channel-convs`,children:Z.map(t=>(0,E.jsxs)(`button`,{type:`button`,className:`admin-row dashboard-channel-conv-row`,onClick:()=>n(t),title:t.title,children:[(0,E.jsxs)(`span`,{className:`dashboard-channel-conv-line`,children:[(0,E.jsx)(`span`,{className:`dashboard-channel-conv-glyph`,children:(0,E.jsx)(ee,{channel:t.channel,size:13})}),(0,E.jsx)(te,{accountId:t.accountId??``,jid:t.remoteJid,sessionKey:e??``,className:`dashboard-channel-conv-avatar`,size:16}),(0,E.jsx)(`span`,{className:`dashboard-channel-conv-name`,children:p(t)}),t.isGroup===!0&&(0,E.jsx)(`span`,{className:`dashboard-channel-conv-tag is-group`,children:`Group`}),t.role===`public`&&(0,E.jsx)(`span`,{className:`dashboard-channel-conv-tag is-public`,children:`Public`}),(0,E.jsx)(`span`,{className:`dashboard-channel-conv-tag`,children:t.isHouse?`House`:`Client`}),!t.preview&&t.lastMessageAt&&(0,E.jsx)(`span`,{className:`dashboard-channel-conv-time`,children:L(Date.parse(t.lastMessageAt),H,r)})]}),t.preview?(0,E.jsxs)(`span`,{className:`dashboard-channel-conv-sub`,children:[(0,E.jsx)(`span`,{className:`dashboard-channel-conv-preview`,children:t.preview}),t.lastMessageAt&&(0,E.jsx)(`span`,{className:`dashboard-channel-conv-time`,children:L(Date.parse(t.lastMessageAt),H,r)})]}):null]},u(t)))}),ve>0&&(0,E.jsxs)(`button`,{type:`button`,className:`dashboard-channel-more`,onClick:()=>_e(!0),children:[`Show `,ve,` more`]})]}):(0,E.jsx)(R,{variant:`card`,count:2})]})]})]})}function G(){let e=m(),[t,n]=(0,T.useState)(!1);(0,T.useEffect)(()=>{if(!t)return;let e=e=>{e.key===`Escape`&&n(!1)};return window.addEventListener(`keydown`,e),()=>window.removeEventListener(`keydown`,e)},[t]);let r=(0,T.useCallback)(async()=>{let t=e.claudeInfo!=null;if(n(!0),t)return;let r=Date.now();if(!e.cacheKey){console.error(`[admin-ui] claude-info-fetch-skipped reason=no-session-key`);return}try{let t=await fetch(`/api/admin/claude-info?session_key=${encodeURIComponent(e.cacheKey)}`);if(t.ok){let n=await t.json();e.setClaudeInfo(n)}}catch(e){console.error(`[admin-ui] claude-info-fetch-failed ms=${Date.now()-r} error="${e instanceof Error?e.message:String(e)}"`)}},[e]),i=(0,T.useCallback)(({code:t,path:n})=>{console.warn(`[admin-auth] outcome=chat-tab-logout-on-401 code=${t} path=${n}`),e.handleLogout()},[e]);return e.appState===`chat`?(0,E.jsx)(s,{cacheKey:e.cacheKey,onSessionExpired:i,surface:`chat`,children:(0,E.jsx)(y,{cacheKey:e.cacheKey,businessName:e.businessName,sessionId:e.sessionId,onLogout:e.handleLogout,onDisconnect:e.handleDisconnect,disconnecting:e.disconnecting,claudeConnected:e.claudeConnected,onConnectClaude:()=>e.setAppState(`connect-claude`),userName:e.userName,userAvatar:e.userAvatar,role:e.role,footer:(0,E.jsxs)(E.Fragment,{children:[(0,E.jsx)(D,{onOpen:r}),(0,E.jsx)(v,{show:t,onClose:()=>n(!1),claudeInfo:e.claudeInfo,messages:[],sessionElapsed:0,sessionId:e.sessionId,cacheKey:e.cacheKey})]}),children:t=>(0,E.jsx)(E.Fragment,{children:t.dataOpen&&e.cacheKey?(0,E.jsx)(C,{cacheKey:e.cacheKey}):t.selectedWhatsapp&&e.cacheKey?t.selectedWhatsapp.source===`store`&&t.selectedWhatsapp.channel===`telegram`&&t.selectedWhatsapp.channelKey&&t.selectedWhatsapp.accountId?(0,E.jsx)(S,{accountId:t.selectedWhatsapp.accountId,channelKey:t.selectedWhatsapp.channelKey,contactName:p(t.selectedWhatsapp),sessionKey:e.cacheKey,onBack:t.onClearWhatsapp},u(t.selectedWhatsapp)):t.selectedWhatsapp.source===`store`&&t.selectedWhatsapp.remoteJid&&t.selectedWhatsapp.accountId?(0,E.jsx)(ie,{accountId:t.selectedWhatsapp.accountId,remoteJid:t.selectedWhatsapp.remoteJid,contactName:p(t.selectedWhatsapp),sessionKey:e.cacheKey,onBack:t.onClearWhatsapp},u(t.selectedWhatsapp)):(0,E.jsx)(O,{sessionId:t.selectedWhatsapp.sessionId,projectDir:t.selectedWhatsapp.projectDir,sessionKey:e.cacheKey,contactName:p(t.selectedWhatsapp),onBack:t.onClearWhatsapp},u(t.selectedWhatsapp)):(0,E.jsx)(W,{cacheKey:e.cacheKey,userName:e.userName,onSelectWhatsappConversation:t.onSelectWhatsappConversation})})})}):(0,E.jsx)(h,{auth:e})}(0,w.createRoot)(document.getElementById(`root`)).render((0,E.jsx)(G,{}));
|
|
1
|
+
import{o as e}from"./chunk-BycB0eMI.js";import{i as t,n,t as r}from"./jsx-runtime-BY35JYDT.js";import{C as i,E as a,F as o,P as s,R as c,ct as l,h as u,i as d,k as f,p,y as ee}from"./useMediaQuery-e4ciNiuO.js";import{n as m,t as h}from"./AdminLoginScreens-BiHOXO0Y.js";import{T as g,c as _,p as te}from"./useVoiceRecorder-Cvu4TePf.js";import{h as ne,i as v,t as y,w as re,x as b}from"./AdminShell-Dm_nY4jF.js";import{t as x}from"./chevron-left-D3_hiHLC.js";import{i as S,n as C,r as ie}from"./page-BF6bGLX_.js";import{t as ae}from"./file-text-CVZAL3Er.js";import"./graph-labels-BTFUSc63.js";import{n as oe}from"./file-download-B7zwa78w.js";var w=n(),T=e(t(),1),E=r();function D({onOpen:e}){return(0,E.jsx)(`footer`,{className:`admin-footer`,children:(0,E.jsxs)(`div`,{className:`powered-by`,role:`button`,tabIndex:0,onClick:e,onKeyDown:t=>{(t.key===`Enter`||t.key===` `)&&(t.preventDefault(),e())},"aria-label":`Powered by Claude Code — show details`,children:[(0,E.jsx)(`img`,{src:`/brand/claude.png`,alt:`Claude`,className:`powered-by-icon`}),(0,E.jsx)(`span`,{children:`Powered by Claude Code`})]})})}function O({sessionId:e,projectDir:t,sessionKey:n,contactName:r,onBack:i}){return(0,E.jsxs)(`div`,{className:`wa-web`,children:[(0,E.jsxs)(`header`,{className:`wa-web-header`,children:[i&&(0,E.jsx)(`button`,{type:`button`,className:`wa-web-back`,onClick:i,"aria-label":`Back`,children:(0,E.jsx)(x,{size:20})}),(0,E.jsx)(`span`,{className:`wa-web-avatar`,"aria-hidden":!0,children:(0,E.jsx)(g,{size:20})}),(0,E.jsx)(`div`,{className:`wa-web-titles`,children:(0,E.jsx)(`span`,{className:`wa-web-name`,children:r})})]}),(0,E.jsx)(`div`,{className:`wa-web-body`,children:(0,E.jsx)(_,{sessionId:e,projectDir:t,sessionKey:n,forceDeliveredOnly:!0})})]})}var k=6e4,A=60*k,j=24*A,M=k,N=[`Jan`,`Feb`,`Mar`,`Apr`,`May`,`Jun`,`Jul`,`Aug`,`Sep`,`Oct`,`Nov`,`Dec`],P=[`Sun`,`Mon`,`Tue`,`Wed`,`Thu`,`Fri`,`Sat`];function F(e){return e<10?`0${e}`:String(e)}function I(e,t){let n=f(e,t);return Date.UTC(n.y,n.m-1,n.d)}function L(e,t,n){if(!Number.isFinite(e)||e<=0||!Number.isFinite(t))return`—`;let r=t-e;if(r<-M)return`—`;let i=r<0?0:r;if(i<k)return`just now`;if(i<A)return`${Math.floor(i/k)}m`;if(i<j)return`${Math.floor(i/A)}h`;let a=I(new Date(t),n),o=I(new Date(e),n),s=Math.round((a-o)/j);if(s===1)return`yesterday`;let c=f(new Date(e),n);if(s>=2&&s<=6)return P[new Date(o).getUTCDay()];let l=F(c.d),u=N[c.m-1],d=f(new Date(t),n).y;return c.y===d?`${l} ${u}`:`${l} ${u} ${c.y}`}function R({variant:e=`row`,count:t=1}){return(0,E.jsx)(E.Fragment,{children:Array.from({length:t},(t,n)=>(0,E.jsx)(`span`,{className:`dashboard-skeleton dashboard-skeleton--${e}`,"data-testid":`dashboard-skeleton`,"aria-hidden":`true`},n))})}var se=6e4;function ce(e){return e<12?`morning`:e<18?`afternoon`:`evening`}function z(e){return e&&e.trim().split(/\s+/)[0]||`there`}function le(e){if(!e)return`everything is running normally.`;let t=e.cpuPct,n=e.memUsedPct;return t!==null&&t>=.98||n!==null&&n>=.98?`system load is critical.`:t!==null&&t>=.9||n!==null&&n>=.9?`system load is high.`:`everything is running normally.`}function B(e){return e==null?`—`:`${Math.round(e*100)}%`}function V(e){let t=Date.parse(e.lastMessageAt??``);return Number.isFinite(t)?t:-1/0}function ue(e,t,n){if(!e)return!1;let r=Date.parse(e);return Number.isFinite(r)?a(new Date(r),n)===a(new Date(t),n):!1}function de(e){return e?e.replace(/^claude-/,``):null}function fe(e,t,n,r,i){let a=0;for(let e=1;e<n.length;e+=1)V(n[e-1])<V(n[e])&&(a+=1);let o=!1;for(let e=1;e<t.length;e+=1)if(t[e-1].channel!==t[e].channel){o=!0;break}let s=new Map;for(let t of e)s.set(t.channel,(s.get(t.channel)??0)+1);return{feedRows:e.length,renderedRows:n.length,cap:r,hidden:e.length-n.length,expanded:i,outOfOrder:a,undated:e.filter(e=>V(e)===-1/0).length,channels:[...s.entries()].map(([e,t])=>`${e}:${t}`).join(`,`),interleaved:o}}var H=new Set([`sessions`,`conversations`,`tasks`,`artefacts`,`skills`,`stats`]),U=!1;function pe(e,t,n,r){let i=e=>t.get(e)??null,a=r?r.getEntriesByType(`navigation`)[0]:void 0,o=r?r.getEntriesByType(`resource`).filter(e=>new URL(e.name,`http://x`).pathname.startsWith(`/assets/`)):[],s=e=>e===void 0||!Number.isFinite(e)?null:Math.round(e),c=e=>e?s(e):null;return{batchMs:e,sessionsMs:i(`sessions`),conversationsMs:i(`conversations`),tasksMs:i(`tasks`),artefactsMs:i(`artefacts`),skillsMs:i(`skills`),statsMs:i(`stats`),failed:[...H].filter(e=>n.has(e)).join(`,`)||`none`,ttfbMs:s(a?.responseStart),domContentLoadedMs:c(a?.domContentLoadedEventEnd),loadMs:c(a?.loadEventEnd),assetCount:o.length,assetBytes:o.reduce((e,t)=>e+(t.transferSize||0),0),assetMs:o.length?s(Math.max(...o.map(e=>e.responseEnd))):null}}function W({cacheKey:e,userName:t,onSelectWhatsappConversation:n}){let{zone:r}=i(),a=o(e),[s,f]=(0,T.useState)(null),[m,h]=(0,T.useState)(null),[g,_]=(0,T.useState)(null),[v,y]=(0,T.useState)(null),[x,S]=(0,T.useState)(null),[C,ie]=(0,T.useState)(null),[w,D]=(0,T.useState)(null),[O,k]=(0,T.useState)(null),[A,j]=(0,T.useState)(null),[M,N]=(0,T.useState)(new Set),[P,F]=(0,T.useState)(()=>new Set),I=(0,T.useCallback)(e=>{F(t=>t.has(e)?t:new Set(t).add(e))},[]),H=Date.now(),W=(0,T.useRef)(!1),G=(0,T.useRef)(new Map),me=(0,T.useRef)(new Set),K=(0,T.useRef)(null);(0,T.useEffect)(()=>{if(!e)return;let t=!1;async function n(e,n,r,i){let o=Date.now(),s=typeof n==`string`?n:`unresolved`;try{typeof n!=`string`&&(s=await n());let e=await a(s);if(!e.ok)throw Error(`status ${e.status}`);let o=await e.json();t||i(r(o))}catch(t){me.current.add(e),console.error(`[admin-ui] dashboard-fetch-failed slice=${e} url=${s} ms=${Date.now()-o} reason=${t instanceof Error?t.message:String(t)}`)}finally{G.current.set(e,Date.now()-o),I(e)}}async function r(){if(!K.current){let e=await a(`/api/admin/accounts`);if(!e.ok)throw Error(`accounts status ${e.status}`);let t=await e.json(),n=t.accounts??[],r=t.activeAccountId??null,i=n.find(e=>e.accountId===r);if(!i)throw Error(`accounts: active ${r??`none`} absent from list of ${n.length}`);let o=i.isHouse||n.length===1;K.current={accountId:i.accountId,isHouse:o}}let{accountId:e,isHouse:t}=K.current;return t?`/api/operator-conversations/conversations-all`:`/api/operator-conversations/conversations`}let i={"sidebar-sessions":()=>n(`sessions`,`/api/admin/sidebar-sessions`,e=>e.sessions??[],f),"conversations-all":()=>n(`conversations`,r,e=>e.conversations??[],h),"tasks-list":()=>n(`tasks`,`/api/admin/tasks-list`,e=>e,y),"sidebar-artefacts":()=>n(`artefacts`,`/api/admin/sidebar-artefacts`,e=>e.artefacts??[],S),skills:()=>n(`skills`,`/api/admin/skills`,e=>e.skills??[],ie)};async function o(){if(W.current)return;W.current=!0;let e=Date.now();try{await Promise.all([...Object.values(i).map(e=>e()),n(`stats`,`/api/admin/system-stats`,e=>e,_),n(`bookingLink`,`/api/admin/calendar/booking-link`,e=>e.bookingDomain??null,D),n(`portalLink`,`/api/admin/data-portal/portal-link`,e=>e.portalDomain??null,k),n(`plannerLink`,`/api/admin/dispatch-planner/planner-link`,e=>e.plannerUrl??null,j)])}finally{W.current=!1;let t=Date.now()-e;if(!U){U=!0;try{let e=pe(t,G.current,me.current,typeof performance>`u`?null:performance);fetch(`/api/_client-error`,{method:`POST`,headers:{"content-type":`application/json`},body:JSON.stringify({kind:`event`,source:`dashboard-load`,...e}),keepalive:!0}).catch(()=>{})}catch{}}}}o();let s=null;try{s=new EventSource(l(`/api/admin/events`,e)),s.onmessage=e=>{if(document.visibilityState===`visible`)try{let{resource:t}=JSON.parse(e.data),n=t?i[t]:void 0;n&&n()}catch{}},s.onerror=()=>{console.error(`[admin-ui] dashboard-events stream error`)}}catch(e){console.error(`[admin-ui] dashboard-events unavailable reason=${e instanceof Error?e.message:String(e)}`)}let c=setInterval(()=>{document.visibilityState===`visible`&&o()},se),u=()=>{document.visibilityState===`visible`&&o()};return document.addEventListener(`visibilitychange`,u),()=>{t=!0,W.current=!1,clearInterval(c),s?.close(),document.removeEventListener(`visibilitychange`,u)}},[e,a]);let q=(0,T.useMemo)(()=>(s??[]).filter(e=>!e.isSubagent),[s]),J=(0,T.useMemo)(()=>q.filter(e=>e.live),[q]),he=(0,T.useMemo)(()=>(m??[]).filter(e=>ue(e.lastMessageAt,H,r)).length,[m,H]),ge=v?.open.length??0,Y=(0,T.useMemo)(()=>[...m??[]].sort((e,t)=>{let n=V(e),r=V(t);return n===r?0:r>n?1:-1}),[m]),[X,_e]=(0,T.useState)(!1),Z=X?Y:Y.slice(0,8),ve=Y.length-Z.length,ye=(0,T.useRef)(null),Q=(0,T.useRef)(null);(0,T.useEffect)(()=>{if(!P.has(`conversations`))return;let e=fe(m??[],Y,Z,8,X),t=JSON.stringify(e);ye.current!==t&&(ye.current=t,Q.current===null&&(Q.current=d()),fetch(`/api/_client-error`,{method:`POST`,headers:{"content-type":`application/json`},body:JSON.stringify({kind:`event`,source:`channels-card`,renderId:Q.current,...e})}).catch(()=>{}))},[P,m,Y,Z,X]);let be=(0,T.useRef)(!1);(0,T.useEffect)(()=>{be.current||!P.has(`bookingLink`)||!P.has(`portalLink`)||!P.has(`plannerLink`)||(be.current=!0)},[P,w,O,A]);let xe=(0,T.useCallback)(async e=>{if(!M.has(e)){N(t=>new Set(t).add(e));try{let t=await a(`/api/admin/session-stop`,{method:`POST`,headers:{"Content-Type":`application/json`},body:JSON.stringify({sessionId:e})});if(!t.ok){console.error(`[admin-ui] dashboard-session-stop-failed sessionId=${e} status=${t.status}`);return}f(t=>(t??[]).map(t=>t.sessionId===e?{...t,live:!1}:t))}catch(t){console.error(`[admin-ui] dashboard-session-stop-failed sessionId=${e} reason=${t instanceof Error?t.message:String(t)}`)}finally{N(t=>{let n=new Set(t);return n.delete(e),n})}}},[a,M]),Se=(0,T.useCallback)(t=>{if(!e||!t.downloadPath){console.error(`[admin-ui] dashboard-artefact-download-blocked id=${t.id} reason=${e?`not-downloadable`:`no-cache-key`}`);return}oe(e,t.downloadPath,t.downloadRoot??`data`)},[e]),$=ce(new Date(H).getHours());return(0,E.jsxs)(`div`,{className:`ui-page ui-page--full dashboard-home`,children:[(0,E.jsx)(`p`,{className:`dashboard-greeting`,children:P.has(`stats`)?`Good ${$}, ${z(t)} — ${le(g)}`:`Good ${$}, ${z(t)}`}),(0,E.jsxs)(`div`,{className:`dashboard-stats`,children:[(0,E.jsxs)(`div`,{className:`admin-stat-card dashboard-stat-card`,children:[(0,E.jsx)(`span`,{className:`dashboard-stat-label`,children:`Live sessions`}),P.has(`sessions`)?(0,E.jsxs)(E.Fragment,{children:[(0,E.jsx)(`span`,{className:`dashboard-stat-value`,children:J.length}),(0,E.jsxs)(`span`,{className:`dashboard-stat-delta`,children:[`of `,q.length,` total`]})]}):(0,E.jsx)(R,{variant:`value`})]}),(0,E.jsxs)(`div`,{className:`admin-stat-card dashboard-stat-card`,children:[(0,E.jsx)(`span`,{className:`dashboard-stat-label`,children:`Messages today`}),P.has(`conversations`)?(0,E.jsx)(`span`,{className:`dashboard-stat-value`,children:he}):(0,E.jsx)(R,{variant:`value`})]}),(0,E.jsxs)(`a`,{className:`admin-stat-card dashboard-stat-card dashboard-stat-card--link`,href:`/tasks`,children:[(0,E.jsx)(`span`,{className:`dashboard-stat-label`,children:`Open tasks`}),P.has(`tasks`)?(0,E.jsx)(`span`,{className:`dashboard-stat-value`,children:ge}):(0,E.jsx)(R,{variant:`value`})]}),(0,E.jsxs)(`div`,{className:`admin-stat-card dashboard-stat-card`,children:[(0,E.jsx)(`span`,{className:`dashboard-stat-label`,children:`Host CPU`}),P.has(`stats`)?(0,E.jsxs)(E.Fragment,{children:[(0,E.jsx)(`span`,{className:`dashboard-stat-value`,children:B(g?.cpuPct??null)}),(0,E.jsxs)(`span`,{className:`dashboard-stat-delta`,children:[`RAM `,B(g?.memUsedPct??null)]})]}):(0,E.jsx)(R,{variant:`value`})]})]}),(0,E.jsxs)(`div`,{className:`dashboard-columns`,children:[(0,E.jsxs)(`div`,{className:`dashboard-col`,children:[(w||O||A)&&(0,E.jsxs)(E.Fragment,{children:[(0,E.jsx)(`span`,{className:`admin-section-label dashboard-col-label`,children:`Public pages`}),(0,E.jsxs)(`div`,{className:`admin-card dashboard-public-pages`,children:[w&&(0,E.jsxs)(`a`,{className:`admin-row dashboard-public-row`,href:`https://${w}`,target:`_blank`,rel:`noopener noreferrer`,children:[(0,E.jsx)(`span`,{className:`dashboard-public-icon`,children:(0,E.jsx)(b,{size:16})}),(0,E.jsx)(`span`,{className:`dashboard-public-name`,children:`Booking page`})]}),O&&(0,E.jsxs)(`a`,{className:`admin-row dashboard-public-row`,href:`https://${O}`,target:`_blank`,rel:`noopener noreferrer`,children:[(0,E.jsx)(`span`,{className:`dashboard-public-icon`,children:(0,E.jsx)(b,{size:16})}),(0,E.jsx)(`span`,{className:`dashboard-public-name`,children:`File drop`})]}),A&&(0,E.jsxs)(`a`,{className:`admin-row dashboard-public-row`,href:A,target:`_blank`,rel:`noopener noreferrer`,children:[(0,E.jsx)(`span`,{className:`dashboard-public-icon`,children:(0,E.jsx)(b,{size:16})}),(0,E.jsx)(`span`,{className:`dashboard-public-name`,children:`Planner`})]})]})]}),(0,E.jsx)(`span`,{className:`admin-section-label dashboard-col-label`,children:`Live now`}),P.has(`sessions`)?J.length===0?(0,E.jsx)(`div`,{className:`admin-card dashboard-empty`,children:`No live sessions right now.`}):J.map(e=>{let t=[e.sessionId.slice(0,8),de(e.model),L(Date.parse(e.startedAt),H,r)].filter(Boolean).join(` · `);return(0,E.jsxs)(`div`,{className:`admin-card dashboard-live-card`,children:[(0,E.jsx)(`span`,{className:`admin-status-dot is-live`}),(0,E.jsxs)(`div`,{className:`dashboard-live-main`,children:[(0,E.jsx)(`span`,{className:`dashboard-live-name`,children:e.title}),(0,E.jsx)(`span`,{className:`dashboard-live-meta`,children:t})]}),(0,E.jsx)(`a`,{className:`admin-btn-cta dashboard-open-btn`,href:`/chat?session=${encodeURIComponent(e.sessionId)}`,children:`Open`}),(0,E.jsx)(`button`,{type:`button`,className:`dashboard-stop-btn`,"aria-label":`Stop ${e.title}`,disabled:M.has(e.sessionId),onClick:()=>void xe(e.sessionId),children:(0,E.jsx)(c,{size:12})})]},e.sessionId)}):(0,E.jsx)(R,{variant:`card`,count:2}),(0,E.jsx)(`span`,{className:`admin-section-label dashboard-col-label`,children:`Recent artefacts`}),(0,E.jsx)(`div`,{className:`admin-card dashboard-artefacts`,children:P.has(`artefacts`)?(x??[]).length===0?(0,E.jsx)(`div`,{className:`dashboard-empty`,children:`No recent artefacts.`}):(x??[]).slice(0,6).map(e=>(0,E.jsxs)(`button`,{type:`button`,className:`admin-row dashboard-artefact-row`,onClick:()=>Se(e),children:[(0,E.jsx)(`span`,{className:`dashboard-artefact-icon`,children:e.kind===`agent-template`?(0,E.jsx)(re,{size:16}):(0,E.jsx)(ae,{size:16})}),(0,E.jsx)(`div`,{className:`dashboard-artefact-body`,children:(0,E.jsx)(`span`,{className:`dashboard-artefact-name`,children:e.name})}),(0,E.jsx)(`span`,{className:`dashboard-artefact-time`,children:L(Date.parse(e.updatedAt),H,r)})]},e.id)):(0,E.jsx)(R,{count:3})}),(0,E.jsx)(`a`,{className:`admin-section-label dashboard-col-label dashboard-skills-label`,href:`/skills`,children:`Skills`}),(0,E.jsx)(`div`,{className:`admin-card dashboard-skills`,children:P.has(`skills`)?(C??[]).length===0?(0,E.jsx)(`div`,{className:`dashboard-empty`,children:`No skills yet.`}):(C??[]).map(e=>(0,E.jsxs)(`a`,{className:`admin-row dashboard-skill-row`,href:`/skills`,children:[(0,E.jsx)(`span`,{className:`dashboard-skill-icon`,children:(0,E.jsx)(ne,{size:16})}),(0,E.jsxs)(`div`,{className:`dashboard-skill-body`,children:[(0,E.jsx)(`span`,{className:`dashboard-skill-name`,children:e.skill}),(0,E.jsx)(`span`,{className:`dashboard-skill-plugin`,children:e.plugin})]})]},`${e.plugin}/${e.skill}`)):(0,E.jsx)(R,{count:2})})]}),(0,E.jsxs)(`div`,{className:`dashboard-col`,children:[(0,E.jsx)(`span`,{className:`admin-section-label dashboard-col-label`,children:`Channels`}),P.has(`conversations`)?Y.length===0?(0,E.jsx)(`div`,{className:`admin-card dashboard-empty`,children:`No channel activity.`}):(0,E.jsxs)(`div`,{className:`admin-card dashboard-channel-card`,children:[(0,E.jsx)(`div`,{className:`dashboard-channel-convs`,children:Z.map(t=>(0,E.jsxs)(`button`,{type:`button`,className:`admin-row dashboard-channel-conv-row`,onClick:()=>n(t),title:t.title,children:[(0,E.jsxs)(`span`,{className:`dashboard-channel-conv-line`,children:[(0,E.jsx)(`span`,{className:`dashboard-channel-conv-glyph`,children:(0,E.jsx)(ee,{channel:t.channel,size:13})}),(0,E.jsx)(te,{accountId:t.accountId??``,jid:t.remoteJid,sessionKey:e??``,className:`dashboard-channel-conv-avatar`,size:16}),(0,E.jsx)(`span`,{className:`dashboard-channel-conv-name`,children:p(t)}),t.isGroup===!0&&(0,E.jsx)(`span`,{className:`dashboard-channel-conv-tag is-group`,children:`Group`}),t.role===`public`&&(0,E.jsx)(`span`,{className:`dashboard-channel-conv-tag is-public`,children:`Public`}),(0,E.jsx)(`span`,{className:`dashboard-channel-conv-tag`,children:t.isHouse?`House`:`Client`}),!t.preview&&t.lastMessageAt&&(0,E.jsx)(`span`,{className:`dashboard-channel-conv-time`,children:L(Date.parse(t.lastMessageAt),H,r)})]}),t.preview?(0,E.jsxs)(`span`,{className:`dashboard-channel-conv-sub`,children:[(0,E.jsx)(`span`,{className:`dashboard-channel-conv-preview`,children:t.preview}),t.lastMessageAt&&(0,E.jsx)(`span`,{className:`dashboard-channel-conv-time`,children:L(Date.parse(t.lastMessageAt),H,r)})]}):null]},u(t)))}),ve>0&&(0,E.jsxs)(`button`,{type:`button`,className:`dashboard-channel-more`,onClick:()=>_e(!0),children:[`Show `,ve,` more`]})]}):(0,E.jsx)(R,{variant:`card`,count:2})]})]})]})}function G(){let e=m(),[t,n]=(0,T.useState)(!1);(0,T.useEffect)(()=>{if(!t)return;let e=e=>{e.key===`Escape`&&n(!1)};return window.addEventListener(`keydown`,e),()=>window.removeEventListener(`keydown`,e)},[t]);let r=(0,T.useCallback)(async()=>{let t=e.claudeInfo!=null;if(n(!0),t)return;let r=Date.now();if(!e.cacheKey){console.error(`[admin-ui] claude-info-fetch-skipped reason=no-session-key`);return}try{let t=await fetch(`/api/admin/claude-info?session_key=${encodeURIComponent(e.cacheKey)}`);if(t.ok){let n=await t.json();e.setClaudeInfo(n)}}catch(e){console.error(`[admin-ui] claude-info-fetch-failed ms=${Date.now()-r} error="${e instanceof Error?e.message:String(e)}"`)}},[e]),i=(0,T.useCallback)(({code:t,path:n})=>{console.warn(`[admin-auth] outcome=chat-tab-logout-on-401 code=${t} path=${n}`),e.handleLogout()},[e]);return e.appState===`chat`?(0,E.jsx)(s,{cacheKey:e.cacheKey,onSessionExpired:i,surface:`chat`,children:(0,E.jsx)(y,{cacheKey:e.cacheKey,businessName:e.businessName,sessionId:e.sessionId,onLogout:e.handleLogout,onDisconnect:e.handleDisconnect,disconnecting:e.disconnecting,claudeConnected:e.claudeConnected,onConnectClaude:()=>e.setAppState(`connect-claude`),userName:e.userName,userAvatar:e.userAvatar,role:e.role,footer:(0,E.jsxs)(E.Fragment,{children:[(0,E.jsx)(D,{onOpen:r}),(0,E.jsx)(v,{show:t,onClose:()=>n(!1),claudeInfo:e.claudeInfo,messages:[],sessionElapsed:0,sessionId:e.sessionId,cacheKey:e.cacheKey})]}),children:t=>(0,E.jsx)(E.Fragment,{children:t.dataOpen&&e.cacheKey?(0,E.jsx)(C,{cacheKey:e.cacheKey}):t.selectedWhatsapp&&e.cacheKey?t.selectedWhatsapp.source===`store`&&t.selectedWhatsapp.channel===`telegram`&&t.selectedWhatsapp.channelKey&&t.selectedWhatsapp.accountId?(0,E.jsx)(S,{accountId:t.selectedWhatsapp.accountId,channelKey:t.selectedWhatsapp.channelKey,contactName:p(t.selectedWhatsapp),sessionKey:e.cacheKey,onBack:t.onClearWhatsapp},u(t.selectedWhatsapp)):t.selectedWhatsapp.source===`store`&&t.selectedWhatsapp.remoteJid&&t.selectedWhatsapp.accountId?(0,E.jsx)(ie,{accountId:t.selectedWhatsapp.accountId,remoteJid:t.selectedWhatsapp.remoteJid,contactName:p(t.selectedWhatsapp),sessionKey:e.cacheKey,onBack:t.onClearWhatsapp},u(t.selectedWhatsapp)):(0,E.jsx)(O,{sessionId:t.selectedWhatsapp.sessionId,projectDir:t.selectedWhatsapp.projectDir,sessionKey:e.cacheKey,contactName:p(t.selectedWhatsapp),onBack:t.onClearWhatsapp},u(t.selectedWhatsapp)):(0,E.jsx)(W,{cacheKey:e.cacheKey,userName:e.userName,onSelectWhatsappConversation:t.onSelectWhatsappConversation})})})}):(0,E.jsx)(h,{auth:e})}(0,w.createRoot)(document.getElementById(`root`)).render((0,E.jsx)(G,{}));
|
|
Binary file
|
|
Binary file
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
import{n as e,t}from"./jsx-runtime-BY35JYDT.js";import"./useMediaQuery-e4ciNiuO.js";import"./useVoiceRecorder-Cvu4TePf.js";import"./AdminShell-Dm_nY4jF.js";import{n}from"./page-Bkl56P8R.js";import"./useCopyFeedback-1MKNUzp3.js";var r=e(),i=t();(0,r.createRoot)(document.getElementById(`root`)).render((0,i.jsx)(n,{}));
|
|
Binary file
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
import{n as e,t}from"./jsx-runtime-BY35JYDT.js";import"./useMediaQuery-e4ciNiuO.js";import"./useVoiceRecorder-Cvu4TePf.js";import{t as n}from"./page-BF6bGLX_.js";import"./graph-labels-BTFUSc63.js";var r=e(),i=t();(0,r.createRoot)(document.getElementById(`root`)).render((0,i.jsx)(n,{}));
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
@�j[�2�[x3M��-�3
|
|
Binary file
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import{o as e}from"./chunk-BycB0eMI.js";import{i as t,n,t as r}from"./jsx-runtime-BY35JYDT.js";import"./useMediaQuery-e4ciNiuO.js";import{n as i,t as a}from"./AdminLoginScreens-
|
|
1
|
+
import{o as e}from"./chunk-BycB0eMI.js";import{i as t,n,t as r}from"./jsx-runtime-BY35JYDT.js";import"./useMediaQuery-e4ciNiuO.js";import{n as i,t as a}from"./AdminLoginScreens-BiHOXO0Y.js";import"./useVoiceRecorder-Cvu4TePf.js";import"./AdminShell-Dm_nY4jF.js";import{t as o}from"./page-Bkl56P8R.js";import"./useCopyFeedback-1MKNUzp3.js";var s=n(),c=e(t(),1),l=r();function u(){let e=i(`operator`),t=(0,c.useRef)(null);return(0,c.useEffect)(()=>{e.appState!==`chat`&&t.current!==e.appState&&(t.current=e.appState)},[e.appState]),e.appState===`chat`?(0,l.jsx)(o,{variant:`operator`,forceCanonicalSession:window.location.pathname!==`/chat`}):(0,l.jsx)(a,{auth:e})}(0,s.createRoot)(document.getElementById(`root`)).render((0,l.jsx)(u,{}));
|
|
Binary file
|
|
Binary file
|