PageSourceSearch

https://loothing.xyz/assets/GuildAdminGuide-I9sPoJCi.js

js loothing.xyz collected 2026-10-02 02:14:17 UTC 51,330 bytes, 1 lines download raw bytes

1import{j as e,r as s}from"./react-vendor-BR2bEzcq.js";import{G as t}from"./GuideCallout-DdHDiUqN.js";import{G as a}from"./GuideDemoFrame-CPlrz0dx.js";import{G as r}from"./GuideLayout-BmQS_pv4.js";import{g as l,e as i,a as n,b as o,c as d,f as c,M as m,d as g}from"./MobileDemo-Dezr2koG.js";import{L as x}from"./layout-grid-BTk_CvLf.js";import{S as p}from"./shield-alert-gOWkfPRp.js";import{F as h}from"./funnel-DDgrh7CG.js";import{E as u}from"./eye-tKxUxQQk.js";import{av as b,D as y,e as v,aM as f,Z as j,bD as w,m as N,X as k,i as A,g as C,R as T,W as S,F as I,A as L,ay as R}from"./index-CpSDEIFT.js";import{R as _}from"./radio-TlwUtTDC.js";import{P as E}from"./play-D4PNe4IR.js";import{L as D}from"./loader-circle-D91B_GSQ.js";import{B}from"./ban-BMpk153J.js";import{C as M}from"./clock-7p0Hl2bb.js";import{C as $}from"./circle-check-REcAsX_P.js";import{D as P}from"./database-fKN-p4vL.js";import{T as O}from"./trash-2-CefGdBnP.js";import{F as U}from"./folder-open-D9oUOKV8.js";import{H as F}from"./hard-drive-DHRG2Vu-.js";import{W as H}from"./wifi-off-P9AwqLB0.js";import"./GuideStep-w0KIOkRN.js";import"./share-2-BlQHCczL.js";import"./axios-ClGXtqae.js";const G=[{id:1,level:"info",source:"discord_agent",code:"AGENT_TURN_COMPLETED",message:"Agent turn completed — #loot-council · Dreadmoon (3 iter, 2 tools)",occurrenceCount:47,lastSeenAt:"10s ago",acknowledgedAt:null},{id:2,level:"error",source:"battlenet",code:"BNET_TOKEN_FAILURE",message:"OAuth token refresh failed: invalid_client — client credentials may be wrong or token revoked.",occurrenceCount:14,lastSeenAt:"2m ago",acknowledgedAt:null},{id:3,level:"warn",source:"discord_agent",code:"AGENT_TOOL_FAILURE",message:"Tool search_memories failed: Vector store timeout after 5000ms",occurrenceCount:3,lastSeenAt:"5m ago",acknowledgedAt:null},{id:4,level:"warn",source:"wcl",code:"WCL_CREDENTIALS_MISSING",message:"WarcraftLogs API key not configured. Log imports and parse queries are unavailable.",occurrenceCount:3,lastSeenAt:"18m ago",acknowledgedAt:null},{id:5,level:"error",source:"raiderio",code:"RAIDERIO_SYNC_FAILED",message:'Raider.io sync failed for roster "Mythic Core": request timed out after 10s',occurrenceCount:2,lastSeenAt:"1h ago",acknowledgedAt:"30m ago"}],W={error:{dot:"bg-red-400",text:"text-red-400",bg:"bg-red-900/20",border:"border-red-500/30",label:"Error"},warn:{dot:"bg-yellow-400",text:"text-yellow-400",bg:"bg-yellow-900/20",border:"border-yellow-500/30",label:"Warn"},info:{dot:"bg-blue-400",text:"text-blue-400",bg:"bg-blue-900/20",border:"border-blue-500/30",label:"Info"}},q={battlenet:"Battle.net",wcl:"WarcraftLogs",raiderio:"Raider.io",discord_bot:"Bot Cmd",discord_agent:"AI Agent",forms:"Forms",api:"API",worker:"Worker",other:"Other"},Z=[{id:1,status:"completed",source:"battle.net",startedAt:"2026-04-09T08:12:00Z",charactersProcessed:47,charactersCreated:3,charactersUpdated:44,triggeredBy:"Scheduled"},{id:2,status:"running",source:"battle.net",startedAt:"2026-04-09T10:30:00Z",charactersProcessed:12,charactersCreated:0,charactersUpdated:12,triggeredBy:"Dreadmoon"},{id:3,status:"failed",source:"battle.net",startedAt:"2026-04-08T22:05:00Z",charactersProcessed:0,charactersCreated:0,charactersUpdated:0,triggeredBy:"Scheduled"},{id:4,status:"completed",source:"battle.net",startedAt:"2026-04-08T08:12:00Z",charactersProcessed:47,charactersCreated:0,charactersUpdated:47,triggeredBy:"Scheduled"}],Q=[{batchId:"wcl-001",status:"completed",createdAt:"2026-04-08T20:00:00Z",progress:{current:6,total:6,percentage:100},results:{imported:5,skipped:1,failed:0}},{batchId:"wcl-002",status:"in_progress",createdAt:"2026-04-09T10:45:00Z",progress:{current:2,total:4,percentage:50},results:{imported:2,skipped:0,failed:0}}],K={running:{bg:"bg-blue-500/20",text:"text-blue-400",border:"border-blue-500/30",Icon:D,spin:!0},completed:{bg:"bg-green-500/20",text:"text-green-400",border:"border-green-500/30",Icon:$},failed:{bg:"bg-red-500/20",text:"text-red-400",border:"border-red-500/30",Icon:S},pending:{bg:"bg-yellow-500/20",text:"text-yellow-400",border:"border-yellow-500/30",Icon:M},cancelled:{bg:"bg-gray-500/20",text:"text-gray-400",border:"border-gray-500/30",Icon:B},in_progress:{bg:"bg-blue-500/20",text:"text-blue-400",border:"border-blue-500/30",Icon:D,spin:!0}},J={battlenet:{source:"battlenet",label:"Battle.net",color:"#00aeff",totalRequests:1284,errorCount:3,errorRate:.2,avgDurationMs:342},wcl:{source:"wcl",label:"WarcraftLogs",color:"#f5a623",totalRequests:218,errorCount:12,errorRate:5.5,avgDurationMs:890},raiderio:{source:"raiderio",label:"Raider.io",color:"#c850c0",totalRequests:764,errorCount:0,errorRate:0,avgDurationMs:195}},X=[{id:1,source:"wcl",statusCode:429,endpoint:"/api/v2/client",durationMs:120,errorMessage:"Rate limit exceeded",createdAt:"2026-04-09T10:12:30Z"},{id:2,source:"wcl",statusCode:401,endpoint:"/api/v2/client",durationMs:45,errorMessage:"Invalid token",createdAt:"2026-04-09T09:55:00Z"},{id:3,source:"wcl",statusCode:500,endpoint:"/api/v2/client",durationMs:2100,errorMessage:"Internal server error",createdAt:"2026-04-08T22:10:00Z"}],Y=[{id:1,source:"settings",type:"audit",action:"settings.update",message:"Updated AI configuration — model changed to claude-sonnet",timestamp:"2026-04-09T10:15:00Z",userId:"189234567890123456"},{id:2,source:"permissions",type:"audit",action:"permissions.role.update",message:'Role "Officer" granted loot.manage permission',timestamp:"2026-04-09T09:30:00Z",userId:"189234567890123456"},{id:3,source:"roster",type:"log",action:"roster.member.add",message:"Added Dreadmoon-Stormrage to Mythic Core roster",timestamp:"2026-04-08T21:45:00Z",userId:"283456789012345678"},{id:4,source:"events",type:"log",action:"event.create",message:'Created event "Mythic Nerub-ar Palace" for Apr 10',timestamp:"2026-04-08T18:00:00Z",userId:"283456789012345678"},{id:5,source:"battlenet",type:"log",action:"battlenet.reauth",message:"Battle.net token refreshed — OAuth re-authenticated",timestamp:"2026-04-08T14:20:00Z",userId:null}],V={settings:{bg:"bg-blue-500/15",text:"text-blue-300",border:"border-blue-500/30",dot:"bg-blue-400"},permissions:{bg:"bg-amber-500/15",text:"text-amber-300",border:"border-amber-500/30",dot:"bg-
1amber-400"},roster:{bg:"bg-emerald-500/15",text:"text-emerald-300",border:"border-emerald-500/30",dot:"bg-emerald-400"},events:{bg:"bg-orange-500/15",text:"text-orange-300",border:"border-orange-500/30",dot:"bg-orange-400"},battlenet:{bg:"bg-cyan-500/15",text:"text-cyan-300",border:"border-cyan-500/30",dot:"bg-cyan-400"}},z=[{title:"Guild Admin Suite",shortTitle:"Overview",icon:x,description:"The Guild Admin Suite at /guild-admin is a separate area from Settings, gated by the guild.admin_suite permission. In logged-in navigation it appears under Admin → Diagnostics for users with access. It is granted by default to Guild Owners and users with the lootAdmin role. It includes six modules: Logs (live activity stream), Imports & Sync (character import and WCL batch tracking), API Health (external API usage and error rates), Change History (timeline of guild configuration changes), Quick Actions (bulk operations for sync, cache, and data cleanup), and Bash Terminal (live shell into the per-guild bash sandbox; requires the additional bash.execute permission).",tip:"Open Admin → Diagnostics when you have guild.admin_suite. The nested Bash Terminal link appears only when you also have bash.execute. If you do not see either item, ask your guild owner to grant the matching permission in Settings → Permissions.",component:()=>e.jsxs("div",{className:"space-y-3",children:[e.jsx(a,{label:"Guild Admin Suite",mobileContent:e.jsxs("div",{className:"space-y-3",children:[e.jsx(l,{tabs:[{label:"Logs"},{label:"Imports & Sync"},{label:"API Health"},{label:"Change History"},{label:"Quick Actions"},{label:"Bash Terminal"}]}),e.jsx(i,{items:[{label:"Logs",desc:"Live activity stream"},{label:"Imports & Sync",desc:"Character & WCL batches"},{label:"API Health",desc:"External API metrics"},{label:"Change History",desc:"Config timeline"},{label:"Quick Actions",desc:"Bulk operations"},{label:"Bash Terminal",desc:"Shared bash workspace"}],cols:2})]}),children:e.jsxs("div",{className:"space-y-3",children:[e.jsxs("div",{className:"flex items-center gap-3 px-4 py-3 rounded-xl border border-violet-700/40 bg-violet-900/10",children:[e.jsx("div",{className:"p-2 bg-violet-500/20 rounded-lg border border-violet-500/30",children:e.jsx(p,{className:"w-5 h-5 text-violet-400"})}),e.jsxs("div",{children:[e.jsx("h3",{className:"text-sm font-bold text-gray-100",children:"Guild Admin Suite"}),e.jsx("p",{className:"text-xs text-gray-400",children:"Logs · Imports · API Health · Changes · Quick Actions · Terminal"})]})]}),e.jsxs("div",{className:"flex flex-col sm:flex-row gap-3",children:[e.jsxs("div",{className:"w-full sm:w-36 sm:shrink-0 rounded-lg border border-gray-700/50 bg-gray-800/40 p-2 space-y-0.5",children:[e.jsx("span",{className:"text-[10px] font-semibold text-gray-500 uppercase tracking-wider px-2 block mb-1.5",children:"Modules"}),[{label:"Logs",active:!0},{label:"Imports & Sync",active:!1},{label:"API Health",active:!1},{label:"Change History",active:!1},{label:"Quick Actions",active:!1},{label:"Bash Terminal",active:!1}].map(s=>e.jsxs("div",{className:"flex items-center gap-2 px-2 py-1.5 rounded-md text-xs "+(s.active?"bg-(--theme-primary-color,#6366f1)/15 text-(--theme-primary-color,#6366f1) font-medium":"text-gray-500"),children:[s.active?e.jsx(p,{className:"w-3.5 h-3.5 shrink-0"}):e.jsx("div",{className:"w-3.5 h-3.5 shrink-0"}),s.label]},s.label))]}),e.jsxs("div",{className:"flex-1 min-w-0 rounded-lg border border-gray-700/50 bg-gray-800/30 p-3 flex flex-col items-center justify-center text-center gap-2",children:[e.jsx(p,{className:"w-8 h-8 text-violet-400/60"}),e.jsx("div",{className:"text-sm font-medium text-gray-300",children:"Logs"}),e.jsx("div",{className:"text-xs text-gray-500 max-w-[200px]",children:"Live activity from the bot, AI agent, and integrations — info, warnings, and errors in one place"})]})]})]})}),e.jsxs(t,{type:"info",children:["Guild Admin Suite is accessible at ",e.jsx("span",{className:"font-mono text-xs bg-gray-700/60 px-1 py-0.5 rounded-sm",children:"/guild-admin"}),". It requires the ",e.jsx("span",{className:"font-mono text-xs bg-gray-700/60 px-1 py-0.5 rounded-sm",children:"guild.admin_suite"})," permission, which is granted by default to Guild Owners and users with the ",e.jsx("span",{className:"font-mono text-xs bg-gray-700/60 px-1 py-0.5 rounded-sm",children:"lootAdmin"})," role. The Bash Terminal module also requires ",e.jsx("span",{className:"font-mono text-xs bg-gray-700/60 px-1 py-0.5 rounded-sm",children:"bash.execute"}),"."]})]})},{title:"Logs Module",shortTitle:"Logs",icon:p,description:"The Logs module lists every guild-scoped event captured by the system — info, warnings, and errors all in one place. Sources include the Discord AI agent (turn start, user prompt, replies, tool actions, turn completion, heartbeats, and scheduled-wake fires/completions/defers/failures), bot slash commands, Battle.net, WarcraftLogs, Raider.io, Forms, and any integration worker. Each row shows the level, source, optional code, full message, when it last occurred, and an occurrence count. Agent turn logs are keyed per turn — and scheduled-wake events are keyed per wake — so the detail drawer can show the exact user message, action timeline, or wake context for that specific run.",tip:"
1Codes like AGENT_TURN_COMPLETED, AGENT_HEARTBEAT_STARTED, AGENT_SCHEDULED_WAKE_FIRED, BNET_TOKEN_FAILURE, WCL_CREDENTIALS_MISSING, or AGENT_TOOL_FAILURE tell you exactly which subsystem needs attention. Use them to pinpoint the fix before opening Settings.",component:()=>e.jsxs("div",{className:"space-y-3",children:[e.jsx(a,{label:"Guild Logs",mobileContent:e.jsx(n,{items:G.map(e=>({icon:"error"===e.level?"🔴":"warn"===e.level?"🟡":"🔵",label:e.code||e.source,desc:e.message,badge:e.level.toUpperCase(),trailing:e.lastSeenAt}))}),children:e.jsx("div",{className:"space-y-2",children:G.map((s,t)=>{const a=W[s.level];return e.jsxs(N.div,{initial:{opacity:0,y:8},animate:{opacity:1,y:0},transition:{delay:.06*t,type:"spring",stiffness:280,damping:24},className:`flex items-start gap-3 px-3 py-2.5 rounded-lg border ${a.border} ${a.bg} ${s.acknowledgedAt?"opacity-50":""}`,children:[e.jsx("div",{className:`mt-0.5 w-2 h-2 rounded-full shrink-0 ${a.dot}`}),e.jsxs("div",{className:"flex-1 min-w-0",children:[e.jsxs("div",{className:"flex flex-wrap items-center gap-1.5 mb-0.5",children:[e.jsx("span",{className:`text-[10px] font-bold uppercase shrink-0 ${a.text}`,children:a.label}),e.jsx("span",{className:"text-[10px] text-gray-500 bg-gray-700/60 px-1.5 py-0.5 rounded-sm shrink-0",children:q[s.source]}),s.code&&e.jsx("span",{className:"text-[10px] text-gray-500 font-mono shrink-0",children:s.code}),s.acknowledgedAt&&e.jsxs("span",{className:"text-[10px] text-green-400 flex items-center gap-1 shrink-0",children:[e.jsx(b,{className:"w-3 h-3"}),"Acknowledged"]})]}),e.jsx("p",{className:"text-xs text-gray-300 truncate",children:s.message})]}),e.jsxs("div",{className:"text-right shrink-0",children:[e.jsx("div",{className:"text-[10px] text-gray-500",children:s.lastSeenAt}),s.occurrenceCount>1&&e.jsxs("div",{className:"text-[10px] text-gray-500",children:["×",s.occurrenceCount]})]})]},s.id)})})}),e.jsx(t,{type:"info",children:"Each row shows level (error / warn / info), source system (AI Agent, Bot Cmd, Battle.net, WarcraftLogs, Raider.io, Forms…), optional code, message preview, last-seen time, and occurrence count. Repeated integration errors are grouped by fingerprint, while agent audit rows are preserved per turn so their exact user text and action timeline remain inspectable."})]})},{title:"Filtering",shortTitle:"Filtering",icon:h,description:"Narrow the log stream with the filter bar. Filter by level (error, warn, info), by source system (AI Agent, Bot Cmd, Battle.net, WarcraftLogs, Raider.io, Forms…), by acknowledged status, or by time range. Filters combine — level=info + source=discord_agent gives you the agent's activity stream, while level=error + source=battlenet narrows to Battle.net errors only.",tip:"Use level=info + source=discord_agent to watch the AI agent in real time as it processes turns and calls tools. Use level=error to focus on actionable problems.",component:()=>{const[r,l]=s.useState("error"),[i,n]=s.useState(null),[c,m]=s.useState("false"),[g,x]=s.useState("24h");return e.jsxs("div",{className:"space-y-3",children:[e.jsx(a,{label:"Filter Bar",mobileContent:e.jsxs("div",{className:"space-y-3",children:[e.jsx(o,{badges:[{label:"All Levels"},{label:"Error",color:"red"},{label:"Warn",color:"yellow"},{label:"Info",color:"blue"}]}),e.jsx(o,{badges:[{label:"Battle.net"},{label:"WarcraftLogs"},{label:"Bot Cmd"}]}),e.jsx(d,{pairs:[{label:"Active Level",value:"Error"},{label:"Showing",value:"1 entry"},{label:"Acknowledgement",value:"Unacknowledged"},{label:"Time Range",value:"Last 24h"}]})]}),children:e.jsxs("div",{className:"space-y-3",children:[e.jsxs("div",{className:"flex flex-wrap items-center gap-2",children:[e.jsx("div",{className:"flex gap-1",children:["all","error","warn","info"].map(s=>e.jsx("button",{type:"button",onClick:()=>l(s),className:"px-2.5 py-1 rounded-full text-xs font-medium transition-colors "+(r===s?"error"===s?"bg-red-500/30 text-red-300 border border-red-500/50":"warn"===s?"bg-yellow-500/30 text-yellow-300 border border-yellow-500/50":"info"===s?"bg-blue-500/30 text-blue-300 border border-blue-500/50":"bg-gray-700 text-gray-200 border border-gray-600":"bg-gray-800/60 text-gray-500 border border-gray-700/50 hover:text-gray-300"),children:"all"===s?"All Levels":s.charAt(0).toUpperCase()+s.slice(1)},s))}),e.jsx("div",{className:"flex gap-1",children:["battlenet","wcl","discord_bot"].map(s=>e.jsx("button",{type:"button",onClick:()=>n(i===s?null:s),className:"px-2.5 py-1 rounded-full text-xs transition-colors "+(i===s?"bg-(--theme-primary-color,#6366f1)/2
10 text-(--theme-primary-color,#6366f1) border border-(--theme-primary-color,#6366f1)/40":"bg-gray-800/60 text-gray-500 border border-gray-700/50 hover:text-gray-300"),children:q[s]},s))}),e.jsx("div",{className:"flex gap-1",children:[{value:"",label:"All"},{value:"false",label:"Unacknowledged"},{value:"true",label:"Acknowledged"}].map(s=>e.jsxs("button",{type:"button",onClick:()=>m(s.value),className:"flex items-center gap-1.5 px-2.5 py-1 rounded-full text-xs transition-colors "+(c===s.value?"bg-green-500/20 text-green-300 border border-green-500/40":"bg-gray-800/60 text-gray-500 border border-gray-700/50 hover:text-gray-300"),children:[e.jsx(b,{className:"w-3.5 h-3.5"}),s.label]},s.value))}),e.jsx("div",{className:"flex gap-1",children:[{value:"",label:"All time"},{value:"1h",label:"Last 1h"},{value:"24h",label:"Last 24h"},{value:"7d",label:"Last 7d"}].map(s=>e.jsx("button",{type:"button",onClick:()=>x(s.value),className:"px-2.5 py-1 rounded-full text-xs transition-colors "+(g===s.value?"bg-blue-500/20 text-blue-300 border border-blue-500/40":"bg-gray-800/60 text-gray-500 border border-gray-700/50 hover:text-gray-300"),children:s.label},s.value))})]}),e.jsxs("div",{className:"text-xs text-gray-500 px-1",children:["Showing ",e.jsx("span",{className:"text-gray-300 font-medium",children:"error"===r?"true"===c?"2":"1":"true"===c?"4":"3"})," entries","all"!==r&&e.jsxs("span",{children:[" · Level: ",e.jsx("span",{className:"text-gray-300",children:r})]}),i&&e.jsxs("span",{children:[" · Source: ",e.jsx("span",{className:"text-gray-300",children:q[i]})]}),e.jsxs("span",{children:[" · Acknowledgement: ",e.jsx("span",{className:"text-gray-300",children:""===c?"All":"true"===c?"Acknowledged":"Unacknowledged"})]}),g&&e.jsxs("span",{children:[" · Time: ",e.jsx("span",{className:"text-gray-300",children:g})]})]})]})}),e.jsx(t,{type:"tip",children:"Combine filters freely — e.g. level=info + source=discord_agent shows only the AI agent's activity stream, while level=error + source=battlenet narrows to Battle.net errors only. Use the acknowledgement selector for All, Unacknowledged, or Acknowledged, and the time-range selector for All time, Last 1h, Last 24h, or Last 7d."})]})}},{title:"Detail Drawer",shortTitle:"Detail",icon:u,description:"Click any row to open the detail drawer. It shows the full message, first-seen and last-seen timestamps, occurrence count, scrubbed context, and the stack trace when available. For AI Agent rows, the drawer renders the context as readable sections before the raw JSON: run metadata, GPT-OSS-generated turn summary, Discord message history, message ID references, runtime instructions, channel participants, retrieved memories and related messages, agent replies, tool/action timeline with arguments and result previews, and heartbeat channel review details when the row came from a heartbeat. The raw audit JSON remains available under a collapsed Raw Audit Context panel.",tip:"Use AGENT_TURN_COMPLETED for the coherent “what happened” view: summary, user text, tool actions, replies, duration, iterations, and whether the agent responded.",component:()=>{const s=G[0],r=W[s.level];return e.jsxs("div",{className:"space-y-3",children:[e.jsx(a,{label:"Log Detail Drawer",mobileContent:e.jsxs("div",{className:"space-y-3",children:[e.jsx(o,{badges:[{label:"INFO",color:"blue"},{label:"AI Agent"},{label:"AGENT_TURN_COMPLETED"}]}),e.jsx(d,{pairs:[{label:"Summary",value:"Used 2 tools and sent 1 reply"},{label:"Trigger",value:"User message"},{label:"Iterations",value:"3"},{label:"Actions",value:"2 tools"}]}),e.jsx(c,{steps:[{label:"Acknowledge",desc:"Mark as seen",status:"active"},{label:"Resolve",desc:"Mark as fixed"}]})]}),children:e.jsxs("div",{className:"space-y-3",children:[e.jsxs("div",{className:`flex items-start justify-between gap-2 p-3 rounded-lg border ${r.border} ${r.bg}`,children:[e.jsxs("div",{className:"min-w-0",children:[e.jsxs("div",{className:"flex flex-wrap items-center gap-1.5 mb-1",children:[e.jsx("span",{className:`text-[10px] font-bold uppercase shrink-0 ${r.text}`,children:r.label}),e.jsx("span",{className:"text-[10px] text-gray-400 bg-gray-700/60 px-1.5 py-0.5 rounded-sm shrink-0",children:q[s.source]}),e.jsx("span",{className:"text-[10px] text-gray-500 font-mono shrink-0",children:s.code})]}),e.jsx("p",{className:"text-xs text-gray-200 leading-relaxed wrap-break-word",children:s.message})]}),e.jsx(k,{className:"w-4 h-4 text-gray-500 shrink-0 mt-0.5"})]}),e.jsx("div",{className:"grid grid-cols-1 sm:grid-cols-3 gap-2 text-[10px]",children:[{label:"Trigger",value:"user_message"},{label:"Channel",value:"#loot-council"},{label:"Iterations",value:"3"}].map(s=>e.jsxs("div",{className:"rounded-lg bg-gray-800/50 border border-gray-700/40 p-2",children:[e.jsx("div",{className:"text-gray-500 mb-0.5",children:s.label}),e.jsx("div",{className:"text-gray-200 font-medium",children:s.value})]},s.label))}),e.jsxs("div",{className:"space-y-2",children:[e.jsxs("div",{className:"flex items-center gap-1.5 mb-1 text-[10px] text-gray-500 uppercase tracking-wider font-semibold",children:[e.jsx(u,{className:"w-3 h-3"})," Structured Context"]}
1),[{title:"Turn Summary",body:"The user asked for loot context. The agent searched recent messages, checked WarcraftLogs, and sent one Discord reply."},{title:"Discord Message History",body:"@Dreadmoon: How did our healers parse on the last boss?"},{title:"Agent Actions",body:"search_help_docs ok · get_warcraftlogs_report ok"},{title:"Raw Audit Context",body:"Collapsed by default for exact JSON inspection."}].map(s=>e.jsxs("div",{className:"rounded-lg border border-gray-700/40 bg-gray-900/35 p-2.5",children:[e.jsx("div",{className:"text-[10px] text-gray-400 uppercase tracking-wider mb-1",children:s.title}),e.jsx("div",{className:"text-xs text-gray-300",children:s.body})]},s.title))]}),e.jsxs("div",{className:"flex flex-wrap gap-2",children:[e.jsxs("button",{type:"button",className:"flex items-center gap-1.5 px-3 py-1.5 rounded-lg bg-green-500/20 text-green-300 border border-green-500/30 text-xs hover:bg-green-500/30 transition-colors",children:[e.jsx(b,{className:"w-3.5 h-3.5"})," Acknowledge"]}),e.jsxs("button",{type:"button",className:"flex items-center gap-1.5 px-3 py-1.5 rounded-lg bg-gray-700/50 text-gray-300 border border-gray-600/50 text-xs hover:bg-gray-700 transition-colors",children:[e.jsx(A,{className:"w-3.5 h-3.5"})," Resolve"]})]})]})}),e.jsx(t,{type:"info",children:"Click any row to open the detail drawer. AI Agent entries render readable sections first: run metadata, GPT-OSS turn summary, Discord message history, runtime instructions, participants, retrieved memories, replies, actions, and heartbeat review details. The raw audit JSON is still available, but it is collapsed by default for agent rows."})]})}},{title:"Acknowledge & Resolve",shortTitle:"Managing",icon:b,description:'Acknowledge marks an entry as seen — the row dims but stays visible and new occurrences continue to be tracked. Resolve marks the entry as fixed — it disappears from the default view and can be deleted with "Clear Resolved" once it is older than 7 days. Events appear automatically via a live SSE stream without a page refresh. The stream is cluster-safe via Redis pub/sub, so events captured by any PM2 worker reach your browser. All entries are persisted to the database regardless of stream state.',tip:"Acknowledge errors you are actively working on to keep your team informed. Resolve them once the underlying integration is fixed so your log view stays focused on what matters.",component:()=>e.jsx("div",{className:"space-y-3",children:e.jsx(a,{label:"Managing Log Entries",mobileContent:e.jsxs("div",{className:"space-y-3",children:[e.jsx(c,{steps:[{label:"Acknowledge",desc:"Seen — row dims, new occurrences still tracked",status:"done"},{label:"Resolve",desc:"Fixed — hidden from default view",status:"active"},{label:"Clear Resolved",desc:"Delete resolved entries older than 7 days"}]}),e.jsx(d,{pairs:[{label:"Live Stream",value:"Connected",color:"green"},{label:"Transport",value:"Redis pub/sub"},{label:"Refresh needed",value:"No"}]})]}),children:e.jsxs("div",{className:"space-y-3",children:[e.jsx("div",{className:"grid grid-cols-1 sm:grid-cols-2 gap-2 sm:gap-3",children:[{icon:b,color:"text-green-400",bg:"bg-green-900/20",border:"border-green-500/30",title:"Acknowledge",desc:"I've seen this entry — it's being investigated or is a known issue. Row dims but stays visible. Does not suppress future occurrences."},{icon:A,color:"text-gray-400",bg:"bg-gray-800/40",border:"border-gray-600/40",title:"Resolve",desc:'This entry is fixed or no longer relevant. Resolved entries are hidden from the default view and can be deleted after 7 days via the "Clear Resolved" button.'}].map(s=>{const t=s.icon;return e.jsxs("div",{className:`rounded-lg border ${s.border} ${s.bg} p-3`,children:[e.jsxs("div",{className:`flex items-center gap-2 mb-1.5 ${s.color}`,children:[e.jsx(t,{className:"w-4 h-4"}),e.jsx("span",{className:"text-sm font-semibold",children:s.title})]}),e.jsx("p",{className:"text-xs text-gray-400 leading-relaxed",children:s.desc})]},s.title)})}),e.jsxs("div",{className:"flex items-center gap-3 rounded-lg border border-gray-700/50 bg-gray-800/30 px-3 py-2.5",children:[e.jsx(_,{className:"w-4 h-4 text-violet-400 shrink-0 animate-pulse"}),e.jsxs("div",{className:"flex-1 min-w-0",children:[e.jsx("div",{className:"text-xs font-medium text-gray-200",children:"Live Stream"}),e.jsx("div",{className:"text-[10px] text-gray-500",children:"New events appear automatically — no refresh needed"})]}),e.jsxs("div",{className:"flex items-center gap-1.5 text-[10px] text-green-400",children:[e.jsx("div",{className:"w-1.5 h-1.5 rounded-full bg-green-400"}),"Connected"]})]}),e.jsxs("div",{className:"flex items-start gap-2 rounded-lg border border-sky-600/30 bg-sky-900/10 px-3 py-2.5",children:[e.jsx(C,{className:"w-4 h-4 text-sky-400 shrink-0 mt-0.5"}),e.jsxs("p",{className:"text-xs text-gray-400 leading-relaxed",children:[e.jsx("span",{className:"text-sky-300 font-medium",children:"Live stream:"})," Events appear in real time across the entire PM2 cluster via Redis pub/sub — no refresh needed regardless of which worker captured the event. If the stream ever shows as disconnected, all events are still being captured and persisted to the database; use the ",e.jsxs("span",{className:"inline-flex items-center gap-1 text-gray-300",children:[e.jsx(T,{className:"w-3 h-3"}),"Refresh"]})," button to reload while the connection re-establishes."]})]})]})})})},{title:"Imports & Sync",shortTitle:"Imports",icon:y,description:"The Imports & Sync module shows your guild's character import sessions and WarcraftLogs batch imports. You can see the status of running imports (completed, running, failed, cancelled), view history of past imports, and trigger a force resync of all characters. Character imports pull data from Battle.net including gear, talents, and mythic plus scores. WCL batch imports pull combat log data for parse analysis. The module auto-refreshes every 15 seconds.",tip:'If an import has been "running" for more than 2 hours, it is likely stuck. Use the Quick Actions module to scan for and fix stuck imports.',component:()=>{const s=e=>
1new Date(e).toLocaleString(void 0,{month:"short",day:"numeric",hour:"2-digit",minute:"2-digit"});return e.jsxs("div",{className:"space-y-3",children:[e.jsx(a,{label:"Imports & Sync",mobileContent:e.jsxs("div",{className:"space-y-3",children:[e.jsx(m,{items:Z.map(e=>({title:`Import #${e.id}`,subtitle:`${e.source} · Triggered by ${e.triggeredBy}`,badges:[e.status],meta:`${e.charactersProcessed} chars`}))}),e.jsx(n,{items:Q.map(e=>({label:e.batchId,desc:`${e.progress.current}/${e.progress.total} logs (${e.progress.percentage}%)`,badge:e.status.replace(/_/g," "),trailing:`${e.results.failed} errors`}))})]}),children:e.jsxs("div",{className:"space-y-4",children:[e.jsxs("div",{className:"flex items-center justify-between",children:[e.jsxs("div",{className:"flex items-center gap-2",children:[e.jsx(y,{className:"w-4 h-4 text-violet-400"}),e.jsx("span",{className:"text-sm font-semibold text-gray-200",children:"Character Imports"})]}),e.jsxs("button",{type:"button",className:"flex items-center gap-1.5 px-2.5 py-1 rounded-lg text-xs font-medium text-white bg-violet-600/80 border border-violet-500/40",children:[e.jsx(E,{className:"w-3 h-3"})," Force Resync"]})]}),e.jsx("div",{className:"rounded-lg border border-gray-700/50 overflow-x-auto",children:e.jsxs("div",{className:"min-w-[340px]",children:[e.jsxs("div",{className:"grid grid-cols-[80px_70px_1fr_60px] gap-2 items-center px-3 py-1.5 bg-gray-800/40 text-[9px] uppercase tracking-wider text-gray-500 font-semibold",children:[e.jsx("div",{children:"Status"}),e.jsx("div",{children:"Source"}),e.jsx("div",{children:"Started"}),e.jsx("div",{className:"text-right",children:"Chars"})]}),Z.map((t,a)=>{const r=K[t.status],l=r.Icon;return e.jsxs(N.div,{initial:{opacity:0,y:6},animate:{opacity:1,y:0},transition:{delay:.05*a,type:"spring",stiffness:280,damping:24},className:"grid grid-cols-[80px_70px_1fr_60px] gap-2 items-center px-3 py-2 border-t border-gray-700/30 text-xs",children:[e.jsxs("span",{className:`inline-flex items-center gap-1 px-1.5 py-0.5 rounded-full text-[10px] font-medium border ${r.bg} ${r.text} ${r.border}`,children:[e.jsx(l,{className:"h-2.5 w-2.5 "+(r.spin?"animate-spin":"")}),t.status]}),e.jsx("span",{className:"text-gray-400 truncate",children:t.source}),e.jsx("span",{className:"text-gray-400",children:s(t.startedAt)}),e.jsx("span",{className:"text-right text-gray-300",children:t.charactersProcessed})]},t.id)})]})}),e.jsxs("div",{className:"flex items-center gap-2 mt-2",children:[e.jsx(I,{className:"w-4 h-4 text-violet-400"}),e.jsx("span",{className:"text-sm font-semibold text-gray-200",children:"WarcraftLogs Batches"})]}),e.jsx("div",{className:"rounded-lg border border-gray-700/50 overflow-x-auto",children:e.jsxs("div",{className:"min-w-[340px]",children:[e.jsxs("div",{className:"grid grid-cols-[80px_80px_1fr_50px] gap-2 items-center px-3 py-1.5 bg-gray-800/40 text-[9px] uppercase tracking-wider text-gray-500 font-semibold",children:[e.jsx("div",{children:"Status"}),e.jsx("div",{children:"Progress"}),e.jsx("div",{children:"Started"}),e.jsx("div",{className:"text-right",children:"Errors"})]}),Q.map((t,a)=>{const r=K[t.status],l=r.Icon;return e.jsxs(N.div,{initial:{opacity:0,y:6},animate:{opacity:1,y:0},transition:{delay:.05*a+.2,type:"spring",stiffness:280,damping:24},className:"grid grid-cols-[80px_80px_1fr_50px] gap-2 items-center px-3 py-2 border-t border-gray-700/30 text-xs",children:[e.jsxs("span",{className:`inline-flex items-center gap-1 px-1.5 py-0.5 rounded-full text-[10px] font-medium border ${r.bg} ${r.text} ${r.border}`,children:[e.jsx(l,{className:"h-2.5 w-2.5 "+(r.spin?"animate-spin":"")}),t.status.replace(/_/g," ")]}),e.jsxs("span",{className:"text-gray-400",children:[t.progress.current,"/",t.progress.total," (",t.progress.percentage,"%)"]}),e.jsx("span",{className:"text-gray-400",children:s(t.createdAt)}),e.jsx("span",{className:"text-right text-gray-500",children:t.results.failed})]},t.batchId)})]})})]})}),e.jsxs(t,{type:"info",children:["Imports run in the background — you can safely close the page. The module auto-refreshes every 15 seconds. Use ",e.jsx("span",{className:"font-mono text-xs bg-gray-700/60 px-1 py-0.5 rounded-sm",children:"Force Resync"})," to trigger a full character re-import from Battle.net. Running imports can be cancelled from this view."]})]})}},{title:"API Health",shortTitle:"API Health",icon:v,description:"The API Health module shows real-time metrics for your guild's external API usage — Battle.net, WarcraftLogs, and Raider.io. Each provider card displays total requests, error count, error rate percentage, and average latency. Color-coded health indicators show Healthy (green, <5% errors), Degraded (yellow, 5–15%), or Unhealthy (red, >15%). Click any provider to drill down into a table of recent errors with status codes, endpoints, latency, and error messages.",tip:"A spike in Battle.net 401 errors usually means your OAuth credentials need refreshing — head to Settings → Battle.net to re-authenticate.",component:()=>{const[r,l]=s.useState(null),i=Object.values(J),o=e=>e<5?"Healthy":e<15?"Degraded":"Unhealthy";return e.jsxs("div",{className:"space-y-3",children:[e.jsx(a,{label:"API Health",mobileContent:e.jsxs("div",{className:"space-y-3",children:[e.jsx(g,{stats:[{label:"Battle.net Requests",value:"1,284"},{label:"WCL Requests",value:"218"},{label:"Raider.io Requests",value:"764"}]}),e.jsx(n,{items:Object.values(J).map(e=>({label:e.label,desc:`Avg latency: ${e.avgDurationMs}ms · ${e.errorCount} errors`,badge:e.errorRate<5?"Healthy":e.errorRate<15?"Degraded":"Unhealthy",trailing:`${e.errorRate}% err`}))})]}),children:e.jsx("div",{className:"space-y-3",children:r?e.jsxs(e.Fragment,{children:[e.jsxs("div",{className:"flex items-center gap-2 mb-1",children:[e.jsx("button",{type:"button",onClick:()=>l(null),className:"text-gray-400 hover:text-gray-200 transition-colors",children:e.jsx(k,{className:"w-3.5 h-3.5"})}),e.jsxs("span",{className:"text-xs font-semibold text-gray-200",children:["Recent Errors — ",J[r]?.label]})]}),e.jsx("div",{className:"rounded-lg border border-gray-700/50 overflow-x-auto",children:e.jsxs("div",{className:"min-w-[300px]",children:[e.jsxs("div",{className:"grid grid-cols-[60px_40px_1fr_80px] gap-2 items-center px-3 py-1.5 bg-gray-800/40 text-[9px] uppercase tracking-wider text-gray-500 font-semibold",children:[e.jsx("div",{children:"Time"}),e.jsx("div",{children:"Code"}),e.jsx("div",{children:"Endpoint"}),e.jsx("div",{className:"text-right",children:"Error"})]}),X.map((s,t)=>{const a=s.statusCode>=500?"#ef4444":"#eab308";return e.jsxs(N.div,{initial:{opacity:0,y:6}
1,animate:{opacity:1,y:0},transition:{delay:.05*t,type:"spring",stiffness:280,damping:24},className:"grid grid-cols-[60px_40px_1fr_80px] gap-2 items-center px-3 py-2 border-t border-gray-700/30 text-[10px]",children:[e.jsx("span",{className:"text-gray-500 tabular-nums",children:new Date(s.createdAt).toLocaleTimeString(void 0,{hour:"2-digit",minute:"2-digit"})}),e.jsx("span",{className:"font-bold px-1.5 py-0.5 rounded-sm text-[9px]",style:{color:a,background:`color-mix(in srgb, ${a} 15%, transparent)`},children:s.statusCode}),e.jsx("span",{className:"text-gray-400 font-mono truncate",children:s.endpoint}),e.jsx("span",{className:"text-gray-500 truncate text-right",children:s.errorMessage})]},s.id)})]})})]}):e.jsxs(e.Fragment,{children:[e.jsx("div",{className:"grid grid-cols-1 sm:grid-cols-3 gap-2",children:i.map((s,t)=>{const a=(r=s.errorRate)<5?"#22c55e":r<15?"#eab308":"#ef4444";var r;return e.jsxs(N.button,{type:"button",initial:{opacity:0,y:8},animate:{opacity:1,y:0},transition:{delay:.06*t,type:"spring",stiffness:280,damping:24},onClick:()=>l(s.source),className:"rounded-lg border border-gray-700/50 bg-gray-800/30 p-3 text-left hover:border-gray-600/60 transition-colors",children:[e.jsxs("div",{className:"flex items-center justify-between mb-2",children:[e.jsx("span",{className:"text-xs font-semibold text-gray-200",children:s.label}),e.jsx("span",{className:"text-[9px] font-bold uppercase px-1.5 py-0.5 rounded-full",style:{color:a,background:`color-mix(in srgb, ${a} 15%, transparent)`},children:o(s.errorRate)})]}),e.jsxs("div",{className:"space-y-1 text-[10px]",children:[e.jsxs("div",{className:"flex justify-between",children:[e.jsx("span",{className:"text-gray-500",children:"Requests"}),e.jsx("span",{className:"text-gray-300 font-medium",children:s.totalRequests.toLocaleString()})]}),e.jsxs("div",{className:"flex justify-between",children:[e.jsx("span",{className:"text-gray-500",children:"Errors"}),e.jsx("span",{style:{color:s.errorCount>0?a:void 0},className:0===s.errorCount?"text-gray-300":"font-medium",children:s.errorCount})]}),e.jsxs("div",{className:"flex justify-between",children:[e.jsx("span",{className:"text-gray-500",children:"Avg Latency"}),e.jsxs("span",{className:"text-gray-300",children:[s.avgDurationMs,"ms"]})]})]})]},s.source)})}),e.jsx("p",{className:"text-[10px] text-gray-500 text-center",children:"Click a provider to view recent errors"})]})})}),e.jsxs(t,{type:"tip",children:["High error rates may indicate expired API tokens — check ",e.jsx("span",{className:"font-mono text-xs bg-gray-700/60 px-1 py-0.5 rounded-sm",children:"Settings → Integrations"}),". A ",e.jsx("span",{className:"text-yellow-300 font-medium",children:"Degraded"})," status (5–15% error rate) often means rate limiting, while ",e.jsx("span",{className:"text-red-300 font-medium",children:"Unhealthy"})," (>15%) usually means bad credentials."]})]})}},{title:"Change History",shortTitle:"Changes",icon:f,description:"The Change History module provides a timeline of every configuration change in your guild — settings updates, permission changes, roster modifications, event creation, and integration re-authentication. Each entry shows when it happened, which source triggered it, a human-readable description, and the user responsible. Entries can be expanded to show the full action code, type (audit log vs guild log), and exact timestamp. Filter by source or time range to narrow results.",tip:"If something suddenly broke, filter Change History to the last 24 hours to see what was modified. The source badges make it easy to spot settings vs permission changes at a glance.",component:()=>{const[r,l]=s.useState(null),[i,o]=s.useState(null),d=i?Y.filter(e=>e.source===i):Y,c=e=>{const s=Date.now()-new Date(e).getTime(),t=Math.floor(s/6e4);if(t<60)return`${t}m ago`;const a=Math.floor(t/60);return a<24?`${a}h ago`:`${Math.floor(a/24)}d ago`};return e.jsxs("div",{className:"space-y-3",children:[e.jsx(a,{label:"Change History",mobileContent:e.jsx(n,{items:Y.map(e=>({label:e.action,desc:e.message,badge:e.source,trailing:(()=>{const s=Date.now()-new Date(e.timestamp).getTime(),t=Math.floor(s/6e4);if(t<60)return`${t}m ago`;const a=Math.floor(t/60);return a<24?`${a}h ago`:`${Math.floor(a/24)}d ago`})()}))}),children:e.jsxs("div",{className:"space-y-3",children:[e.jsxs("div",{className:"flex flex-wrap items-center gap-2",children:[e.jsx(h,{className:"w-3.5 h-3.5 text-gray-500 shrink-0"}),["all","settings","permissions","roster","events"].map(s=>e.jsx("button",{type:"button",onClick:()=>
1o("all"===s?null:s),className:"px-2 py-0.5 rounded-full text-[10px] font-medium transition-colors "+("all"===s&&!i||i===s?"bg-(--theme-primary-color,#6366f1)/20 text-(--theme-primary-color,#6366f1) border border-(--theme-primary-color,#6366f1)/40":"bg-gray-800/60 text-gray-500 border border-gray-700/50 hover:text-gray-300"),children:"all"===s?"All":s.charAt(0).toUpperCase()+s.slice(1)},s))]}),e.jsx("div",{className:"rounded-lg border border-gray-700/50 overflow-x-auto",children:e.jsx("div",{className:"min-w-[320px]",children:d.map((s,t)=>{const a=V[s.source]||V.settings,i=r===s.id;return e.jsxs(N.div,{initial:{opacity:0,x:-8},animate:{opacity:1,x:0},transition:{delay:.04*t,type:"spring",stiffness:300,damping:26},children:[e.jsxs("button",{type:"button",onClick:()=>l(i?null:s.id),className:"w-full grid grid-cols-[60px_70px_1fr_20px] gap-2 items-center px-3 py-2.5 border-b border-gray-700/30 text-left hover:bg-gray-800/30 transition-colors",children:[e.jsx("span",{className:"text-[10px] text-gray-500",children:c(s.timestamp)}),e.jsxs("span",{className:`inline-flex items-center gap-1 text-[9px] font-semibold uppercase px-1.5 py-0.5 rounded-md border ${a.bg} ${a.text} ${a.border}`,children:[e.jsx("span",{className:`w-1.5 h-1.5 rounded-full ${a.dot}`}),s.source]}),e.jsx("span",{className:"text-xs text-gray-300 truncate",children:s.message}),e.jsx("span",{className:"text-gray-500",children:i?"▴":"▾"})]}),e.jsx(L,{children:i&&e.jsx(N.div,{initial:{height:0,opacity:0},animate:{height:"auto",opacity:1},exit:{height:0,opacity:0},transition:{duration:.15},className:"overflow-hidden",children:e.jsxs("div",{className:"px-3 py-2 bg-gray-900/40 border-b border-gray-700/30 text-[10px] text-gray-500 space-y-1",children:[e.jsxs("div",{children:["Action: ",e.jsx("span",{className:"font-mono text-gray-400",children:s.action})]}),e.jsxs("div",{children:["Type: ",e.jsx("span",{className:"text-gray-400",children:"audit"===s.type?"Audit Log":"Guild Log"})]}),e.jsxs("div",{children:["Time: ",e.jsx("span",{className:"text-gray-400",children:new Date(s.timestamp).toLocaleString()})]})]})})})]},s.id)})})})]})}),e.jsx(t,{type:"info",children:"Change history helps identify when and why settings were modified. Each entry records the source (settings, permissions, roster, events, integrations), the user who made the change, and a JSON diff of what changed. Filter by source or time range to narrow results. Both audit-log entr
1ies (user actions) and guild-log entries (system events) appear here."})]})}},{title:"Quick Actions",shortTitle:"Actions",icon:j,description:"Quick Actions provides three bulk-operation cards. Sync Status shows your most recent character import and lets you trigger a force resync. Cache Management lets you clear all cached guild data (settings, roster lookups, API responses) — data is re-fetched on next access. Data Cleanup scans for stuck import sessions (running >2 hours) and orphaned character records (no matching guild), with a report-first workflow that shows exactly what will be cleaned before you execute.",tip:"The cleanup button requires two clicks — one to initiate and a second confirmation within 4 seconds — to prevent accidental deletions.",component:()=>e.jsxs("div",{className:"space-y-3",children:[e.jsx(a,{label:"Quick Actions",mobileContent:e.jsxs("div",{className:"space-y-3",children:[e.jsx(d,{pairs:[{label:"Last Import",value:"2h ago"},{label:"Status",value:"Completed",color:"green"},{label:"Processed",value:"47 characters"},{label:"Source",value:"Scheduled"}]}),e.jsx(g,{stats:[{label:"Stuck Imports",value:"1",color:"yellow"},{label:"Orphaned Chars",value:"3",color:"yellow"},{label:"Cache Age",value:"Live"}]})]}),children:e.jsxs("div",{className:"space-y-3",children:[e.jsxs("div",{className:"rounded-lg border border-gray-700/50 bg-gray-800/30 p-3",children:[e.jsxs("div",{className:"flex items-center gap-2 mb-3",children:[e.jsx(T,{className:"w-3.5 h-3.5 text-violet-400"}),e.jsx("span",{className:"text-xs font-semibold text-gray-200",children:"Sync Status"})]}),e.jsx("div",{className:"grid grid-cols-1 sm:grid-cols-2 gap-2 text-[10px] mb-3",children:[{label:"Last Import",value:"2h ago"},{label:"Status",value:"completed",isStatus:!0},{label:"Processed",value:"47 characters"},{label:"Source",value:"Scheduled"}].map(s=>e.jsxs("div",{className:"rounded-md bg-gray-900/40 p-2",children:[e.jsx("div",{className:"text-gray-500 mb-0.5",children:s.label}),s.isStatus?e.jsx("span",{className:"text-[9px] font-semibold uppercase px-1.5 py-0.5 rounded-full bg-green-500/20 text-green-400 border border-green-500/30",children:s.value}):e.jsx("div",{className:"text-gray-200 font-medium",children:s.value})]},s.label))}),e.jsxs("button",{type:"button",className:"flex items-center gap-1.5 px-3 py-1.5 rounded-lg text-xs text-gray-200 bg-gray-700/50 border border-gray-600/40 hover:bg-gray-700 transition-colors",children:[e.jsx(T,{className:"w-3 h-3"})," Force Character Resync"]})]}),e.jsxs("div",{className:"grid grid-cols-1 sm:grid-cols-2 gap-2",children:[e.jsxs("div",{className:"rounded-lg border border-gray-700/50 bg-gray-800/30 p-3",children:[e.jsxs("div",{className:"flex items-center gap-2 mb-2",children:[e.jsx(P,{className:"w-3.5 h-3.5 text-violet-400"}),e.jsx("span",{className:"text-xs font-semibold text-gray-200",children:"Cache"})]}),e.jsx("p",{className:"text-[10px] text-gray-500 mb-2",children:"Clear cached data — settings, roster lookups, API responses."}),e.jsxs("button",{type:"button",className:"flex items-center gap-1.5 px-2.5 py-1 rounded-lg text-[10px] text-gray-300 bg-gray-700/50 border border-gray-600/40 hover:text-red-300 hover:border-red-500/40 transition-colors",children:[e.jsx(O,{className:"w-3 h-3"})," Clear Guild Cache"]})]}),e.jsxs("div",{className:"rounded-lg border border-gray-700/50 bg-gray-800/30 p-3",children:[e.jsxs("div",{className:"flex items-center gap-2 mb-2",children:[e.jsx(p,{className:"w-3.5 h-3.5 text-violet-400"}),e.jsx("span",{className:"text-xs font-semibold text-gray-200",children:"Data Cleanup"})]}),e.jsx("p",{className:"text-[10px] text-gray-500 mb-2",children:"Scan for stuck imports and orphaned character records."}),e.jsxs("button",{type:"button",className:"flex items-center gap-1.5 px-2.5 py-1 rounded-lg text-[10px] text-gray-300 bg-gray-700/50 border border-gray-600/40 transition-colors",children:[e.jsx(R,{className:"w-3 h-3"})," Run Orphan Report"]})]})]}),e.jsxs(N.div,{initial:{opacity:0,y:6},animate:{opacity:1,y:0},transition:{delay:.2,type:"spring",stiffness:280,damping:24},className:"rounded-lg border border-gray-700/50 bg-gray-800/30 p-3",children:[e.jsx("div",{className:"text-[10px] text-gray-500 uppercase tracking-wider font-semibold mb-2",children:"Report Results"}),e.jsxs("div",{className:"grid grid-cols-1 sm:grid-cols-2 gap-2 mb-2",children:[e.jsxs("div",{className:"rounded-md bg-gray-900/40 p-2",children:[e.jsx("div",{className:"text-[10px] text-gray-500 mb-0.5",children:"Stuck Imports"}),e.jsx("div",{className:"text-lg font-bold text-gray-200",children:"1"}),e.jsx("div",{className:"text-[9px] text-gray-500",children:"Running > 2 hours"})]}),e.jsxs("div",{className:"rounded-md bg-gray-900/40 p-2",children:[e.jsx("div",{className:"text-[10px] text-gray-500 mb-0.5",children:"Orphaned Characters"}),e.jsx("div",{className:"text-lg font-bold text-gray-200",children:"3"}),e.jsx("div",{className:"text-[9px] text-gray-500",children:"No matching guild"})]})]}),e.jsxs("div",{className:"flex items-center gap-1.5 text-[10px] text-yellow-300",children:[e.jsx(C,{className:"w-3 h-3"})," Review results before executing cleanup"]})]})]})}),e.jsxs(t,{type:"warning",children:["Always run a dry report before executing cleanup — deleted data cannot be recovered. The ",e.jsx("span",{className:"font-mono text-xs bg-gray-700/60 px-1 py-0.5 rounded-sm",children:"Execute Cleanup"})," button requires a second confirmation click to prevent accidental data loss."]})]})},{title:"Bash Terminal",shortTitle:"Bash Term.",icon:w,description:"The Bash Terminal at /guild-admin/bash-terminal combines a Dolphin-style file browser, markdown editor, and live xterm.js shell for the same per-guild bash sandbox the AI uses. Shell execution runs through bashSandboxService.exec and file operations run through the same sandbox service path guards — filesystem isolation, disk quota, per-call timeout, network policy, output caps, command and loop limits, and the per-guild mutex still apply. Network policy is shared with the AI tool: default deny, optional URL allow-list, or public-network mode for public HTTP/HTTPS destinations only, with private/internal IPs blocked and all guilds sharing a global 10 MiB/s bash network throttle. Two permissions are required: guild.admin_suite (the suite-wide gate) AND bash.execute (the same capability that gates the AI's bash tool). Sessions are stateless beyond cwd — env vars, functions, and aliases reset every command — so the terminal fakes only w
1orking-directory persistence by tracking cwd client-side and parsing the new pwd from each response. Files written under / persist and are shared with the AI's tool: both are talking to the same workspace. Use it to inspect or repair the AI's workspace, edit markdown memories with live preview, drop pre-baked memories into agent/memories/, debug network settings with curl, or verify what the AI wrote to its self-files.",tip:"Every accepted exec is audited (action guild_admin.bash_terminal.exec) with the script's SHA-256 hash, length, before/after cwd, exit code, duration, quota usage, and error type. The raw script, stdout, and stderr are never logged — admins paste tokens. Local input history is in-memory only and is cleared when the page unmounts.",component:()=>e.jsxs("div",{className:"space-y-3",children:[e.jsx(a,{label:"Bash Terminal",mobileContent:e.jsxs("div",{className:"space-y-3",children:[e.jsx(d,{pairs:[{label:"cwd",value:"/"},{label:"Quota",value:"12 KB / 100 MiB"},{label:"Timeout",value:"60s"},{label:"Network",value:"Denied",color:"green"}]}),e.jsx(o,{items:[{label:"guild.admin_suite",color:"sky"},{label:"bash.execute",color:"sky"}]})]}),children:e.jsxs("div",{className:"space-y-3",children:[e.jsx("div",{className:"grid grid-cols-2 lg:grid-cols-4 gap-2",children:[{icon:U,label:"cwd",value:"/"},{icon:M,label:"Timeout",value:"60s"},{icon:F,label:"Quota",value:"12 KB / 100 MiB"},{icon:H,label:"Network",value:"Denied"}].map(s=>{const t=s.icon;return e.jsxs("div",{className:"rounded-md bg-gray-900/40 p-2 flex items-start gap-2",children:[e.jsx(t,{className:"w-3.5 h-3.5 mt-0.5 text-violet-400 shrink-0"}),e.jsxs("div",{className:"min-w-0",children:[e.jsx("div",{className:"text-[9px] text-gray-500 uppercase tracking-wider",children:s.label}),e.jsx("div",{className:"text-[11px] text-gray-200 font-mono truncate",children:s.value})]})]},s.label)})}),e.jsxs("div",{className:"rounded-lg border border-gray-700/50 bg-black/70 p-3 font-mono text-[11px] text-gray-200 leading-relaxed",children:[e.jsx("div",{className:"text-gray-500 mb-1",children:"Files: /agent/memories/weekly-raid.md  |  Markdown preview: on"}),e.jsxs("div",{children:[e.jsx("span",{className:"text-emerald-400",children:"loothing@guild"}),":",e.jsx("span",{className:"text-yellow-400",children:"/"}),"$ ls agent/"]}),e.jsx("div",{className:"text-gray-300",children:"HEARTBEAT.md  INBOX.md  LESSONS.md  SOUL.md  TODO.md  memories/"}),e.jsx("div",{className:"text-gray-500",children:"[exit 0, 18ms, 12KB/102400KB]"}),e.jsxs("div",{className:"mt-1",children:[e.jsx("span",{className:"text-emerald-400",children:"loothing@guild"}),":",e.jsx("span",{className:"text-yellow-400",children:"/"}),"$ cat agent/SOUL.md"]}),e.jsx("div",{className:"text-gray-300",children:"…"}),e.jsx("div",{className:"text-gray-500",children:"[exit 0, 12ms, 12KB/102400KB]"})]})]})}),e.jsxs(t,{type:"warning",children:["Sessions are stateless beyond ",e.jsx("strong",{children:"cwd"}),". Each command runs in a fresh shell — env vars, exported functions, and aliases reset every time. Files written under"," ",e.jsx("code",{className:"text-xs bg-gray-700/60 px-1 py-0.5 rounded-sm",children:"/"})," persist and are shared with the AI's bash tool — both touch the same per-guild workspace."]}),e.jsxs(t,{type:"info",children:["Every accepted exec is audited as ",e.jsx("code",{children:"guild_admin.bash_terminal.exec"})," with the script's SHA-256 hash and the result envelope. File browser reads log path and file metadata only; writes log path, size, and content hash. Raw scripts, stdout, stderr, and file contents are"," ",e.jsx("strong",{children:"never"})," logged because admins routinely paste tokens and secrets. Local input history is in-memory only."]})]})}];function ee({onDone:s,initialStep:t=0,guideId:a}){return e.jsx(r,{steps:z,onDone:s,initialStep:t,guideId:a})}export{ee as default};

Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.