@ainyc/canonry 4.51.0 → 4.51.2

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.
@@ -1 +1 @@
1
- import{j as s}from"./vendor-tanstack-Dq7p98wZ.js";import{u as r,b8 as t,B as a}from"./index-DKBPD33e.js";function n({run:e}){const{openRun:i}=r();return s.jsxs("article",{className:"run-row",children:[s.jsxs("div",{className:"run-row-main",children:[s.jsxs("div",{className:"run-row-head",children:[s.jsxs("div",{children:[s.jsx("p",{className:"run-row-title",children:e.summary}),s.jsxs("p",{className:"run-row-subtitle",children:[e.projectName,e.location?` · ${e.location}`:""," · ",e.kindLabel]})]}),s.jsx(t,{status:e.status})]}),s.jsx("p",{className:"run-row-detail",children:e.statusDetail})]}),s.jsxs("dl",{className:"run-row-meta",children:[s.jsxs("div",{children:[s.jsx("dt",{children:"Started"}),s.jsx("dd",{children:e.startedAt})]}),s.jsxs("div",{children:[s.jsx("dt",{children:"Duration"}),s.jsx("dd",{children:e.duration})]}),s.jsxs("div",{children:[s.jsx("dt",{children:"Trigger"}),s.jsx("dd",{children:e.triggerLabel})]})]}),s.jsx(a,{variant:"outline",size:"sm",type:"button",onClick:()=>i(e.id),children:"View run"})]})}export{n as R};
1
+ import{j as s}from"./vendor-tanstack-Dq7p98wZ.js";import{u as r,bi as t,B as a}from"./index-VMFHNbas.js";function n({run:e}){const{openRun:i}=r();return s.jsxs("article",{className:"run-row",children:[s.jsxs("div",{className:"run-row-main",children:[s.jsxs("div",{className:"run-row-head",children:[s.jsxs("div",{children:[s.jsx("p",{className:"run-row-title",children:e.summary}),s.jsxs("p",{className:"run-row-subtitle",children:[e.projectName,e.location?` · ${e.location}`:""," · ",e.kindLabel]})]}),s.jsx(t,{status:e.status})]}),s.jsx("p",{className:"run-row-detail",children:e.statusDetail})]}),s.jsxs("dl",{className:"run-row-meta",children:[s.jsxs("div",{children:[s.jsx("dt",{children:"Started"}),s.jsx("dd",{children:e.startedAt})]}),s.jsxs("div",{children:[s.jsx("dt",{children:"Duration"}),s.jsx("dd",{children:e.duration})]}),s.jsxs("div",{children:[s.jsx("dt",{children:"Trigger"}),s.jsx("dd",{children:e.triggerLabel})]})]}),s.jsx(a,{variant:"outline",size:"sm",type:"button",onClick:()=>i(e.id),children:"View run"})]})}export{n as R};
@@ -1 +1 @@
1
- import{j as e,r as o}from"./vendor-tanstack-Dq7p98wZ.js";import{aH as m,b7 as u,B as h,t as x,g as p}from"./index-DKBPD33e.js";import{R as j}from"./RunRow-DqezNIUy.js";import"./vendor-radix-B57xfQbP.js";import"./vendor-recharts-DWvKDyBF.js";import"./vendor-markdown-DK7fbRNb.js";function R(){const{dashboard:l,isLoading:n}=m(),t=u();if(!l||n)return e.jsxs("div",{className:"page-skeleton",children:[e.jsxs("div",{className:"page-skeleton-header",children:[e.jsx("div",{className:"skeleton-text h-6 w-20"}),e.jsx("div",{className:"skeleton-text-sm w-72"})]}),e.jsx("div",{className:"space-y-2",children:[1,2,3,4].map(s=>e.jsxs("div",{className:"rounded-xl border border-zinc-800/60 bg-zinc-900/30 p-3 flex items-center gap-3",children:[e.jsxs("div",{className:"flex-1 space-y-1.5",children:[e.jsx("div",{className:"skeleton-text w-40"}),e.jsx("div",{className:"skeleton-text-sm w-56"})]}),e.jsx("div",{className:"skeleton h-5 w-16 rounded-full"})]},s))})]});const r=l.runs,[a,c]=o.useState("all"),i=a==="all"?r:r.filter(s=>s.status===a),d=async()=>{try{await t.mutateAsync(void 0)}catch{}};return e.jsxs("div",{className:"page-container",children:[e.jsxs("div",{className:"page-header",children:[e.jsxs("div",{className:"page-header-left",children:[e.jsx("h1",{className:"page-title",children:"Runs"}),e.jsx("p",{className:"page-subtitle",children:"Status, type, project, duration, and the shortest explanation that makes the outcome trustworthy."})]}),e.jsx(h,{type:"button",variant:"outline",size:"sm",disabled:t.isPending,onClick:()=>{d()},children:t.isPending?"Queueing…":"Run all projects"})]}),e.jsxs("section",{children:[e.jsx("div",{className:"filter-row",role:"toolbar","aria-label":"Run filters",children:["all","queued","running","completed","partial","failed","cancelled"].map(s=>e.jsx("button",{className:`filter-chip ${a===s?"filter-chip-active":""}`,type:"button","aria-pressed":a===s,onClick:()=>c(s),children:s==="all"?"All runs":x(s)},s))}),e.jsx("div",{className:"run-list",children:i.length>0?i.map(s=>e.jsx(j,{run:s},s.id)):e.jsxs(p,{className:"surface-card empty-card",children:[e.jsx("h2",{children:"No runs match this filter"}),e.jsx("p",{children:"Try another status filter or queue a new run from a project command center."})]})})]})]})}export{R as RunsPage};
1
+ import{j as e,r as o}from"./vendor-tanstack-Dq7p98wZ.js";import{bg as m,bh as u,B as h,t as x,g as p}from"./index-VMFHNbas.js";import{R as j}from"./RunRow-NfzAq5p2.js";import"./vendor-radix-B57xfQbP.js";import"./vendor-recharts-DWvKDyBF.js";import"./vendor-markdown-DK7fbRNb.js";function y(){const{dashboard:l,isLoading:n}=m(),t=u();if(!l||n)return e.jsxs("div",{className:"page-skeleton",children:[e.jsxs("div",{className:"page-skeleton-header",children:[e.jsx("div",{className:"skeleton-text h-6 w-20"}),e.jsx("div",{className:"skeleton-text-sm w-72"})]}),e.jsx("div",{className:"space-y-2",children:[1,2,3,4].map(s=>e.jsxs("div",{className:"rounded-xl border border-zinc-800/60 bg-zinc-900/30 p-3 flex items-center gap-3",children:[e.jsxs("div",{className:"flex-1 space-y-1.5",children:[e.jsx("div",{className:"skeleton-text w-40"}),e.jsx("div",{className:"skeleton-text-sm w-56"})]}),e.jsx("div",{className:"skeleton h-5 w-16 rounded-full"})]},s))})]});const r=l.runs,[a,c]=o.useState("all"),i=a==="all"?r:r.filter(s=>s.status===a),d=async()=>{try{await t.mutateAsync(void 0)}catch{}};return e.jsxs("div",{className:"page-container",children:[e.jsxs("div",{className:"page-header",children:[e.jsxs("div",{className:"page-header-left",children:[e.jsx("h1",{className:"page-title",children:"Runs"}),e.jsx("p",{className:"page-subtitle",children:"Status, type, project, duration, and the shortest explanation that makes the outcome trustworthy."})]}),e.jsx(h,{type:"button",variant:"outline",size:"sm",disabled:t.isPending,onClick:()=>{d()},children:t.isPending?"Queueing…":"Run all projects"})]}),e.jsxs("section",{children:[e.jsx("div",{className:"filter-row",role:"toolbar","aria-label":"Run filters",children:["all","queued","running","completed","partial","failed","cancelled"].map(s=>e.jsx("button",{className:`filter-chip ${a===s?"filter-chip-active":""}`,type:"button","aria-pressed":a===s,onClick:()=>c(s),children:s==="all"?"All runs":x(s)},s))}),e.jsx("div",{className:"run-list",children:i.length>0?i.map(s=>e.jsx(j,{run:s},s.id)):e.jsxs(p,{className:"surface-card empty-card",children:[e.jsx("h2",{children:"No runs match this filter"}),e.jsx("p",{children:"Try another status filter or queue a new run from a project command center."})]})})]})]})}export{y as RunsPage};
@@ -1 +1 @@
1
- import{r as n,j as e}from"./vendor-tanstack-Dq7p98wZ.js";import{B as f,i as k,b9 as $,L as A,ba as R,bb as E,g as b,T as y,bc as q,bd as V,aH as W,be as Q,bf as _,bg as F,bh as K}from"./index-DKBPD33e.js";import"./vendor-radix-B57xfQbP.js";import"./vendor-recharts-DWvKDyBF.js";import"./vendor-markdown-DK7fbRNb.js";function J({providerName:s,keyUrl:m,modelHint:l,onSaved:j}){const u=s.toLowerCase()==="local",[r,o]=n.useState(""),[x,d]=n.useState(""),[g,h]=n.useState(""),[p,a]=n.useState(""),[i,v]=n.useState(""),[N,S]=n.useState(""),[z,P]=n.useState(!1),[C,t]=n.useState(null),[L,I]=n.useState(!1),M=u?x.trim().length>0:r.trim().length>0;async function T(){if(M){P(!0),t(null),I(!1);try{const c=U=>{const B=parseInt(U.trim(),10);return Number.isFinite(B)&&B>0?B:void 0},w={},O=c(p);O!==void 0&&(w.maxConcurrency=O);const D=c(i);D!==void 0&&(w.maxRequestsPerMinute=D);const G=c(N);G!==void 0&&(w.maxRequestsPerDay=G),await $(s.toLowerCase(),{...r.trim()?{apiKey:r.trim()}:{},...x.trim()?{baseUrl:x.trim()}:{},...g.trim()?{model:g.trim()}:{},...Object.keys(w).length>0?{quota:w}:{}}),o(""),d(""),h(""),a(""),v(""),S(""),I(!0),A({title:"Provider updated",detail:`${s} configuration saved.`,tone:"positive",dedupeKey:`settings:provider:${s}`,dedupeMode:"replace"}),j()}catch(c){t(c instanceof Error?c.message:"Failed to update provider")}finally{P(!1)}}}const H=l??"Use default model";return e.jsxs("div",{className:"mt-3 rounded-lg border border-zinc-800 bg-zinc-900/40 p-3 space-y-2",children:[u&&e.jsxs("div",{children:[e.jsx("label",{className:"text-xs text-zinc-500",htmlFor:`base-url-${s}`,children:"Base URL"}),e.jsx("input",{id:`base-url-${s}`,type:"text",className:"mt-0.5 w-full rounded border border-zinc-700 bg-transparent px-2 py-1.5 text-sm text-zinc-200 placeholder-zinc-600 focus:border-zinc-500 focus:outline-none",placeholder:"http://localhost:11434/v1",value:x,onChange:c=>d(c.target.value)}),e.jsx("p",{className:"mt-0.5 text-[10px] text-zinc-600",children:"Any OpenAI-compatible endpoint — Ollama, LM Studio, llama.cpp, vLLM"})]}),e.jsxs("div",{children:[e.jsxs("div",{className:"flex items-center justify-between",children:[e.jsxs("label",{className:"text-xs text-zinc-500",htmlFor:`api-key-${s}`,children:["API Key",u?" (optional)":""]}),m&&e.jsxs("a",{href:m,target:"_blank",rel:"noopener noreferrer",className:"text-[10px] text-zinc-500 hover:text-zinc-300 underline underline-offset-2",children:["Get API key ","↗"]})]}),e.jsx("input",{id:`api-key-${s}`,type:"password",className:"mt-0.5 w-full rounded border border-zinc-700 bg-transparent px-2 py-1.5 text-sm text-zinc-200 placeholder-zinc-600 focus:border-zinc-500 focus:outline-none",placeholder:u?"Optional — most local servers don't need one":`Enter ${s} API key`,value:r,onChange:c=>o(c.target.value)})]}),e.jsxs("div",{children:[e.jsx("label",{className:"text-xs text-zinc-500",htmlFor:`model-${s}`,children:"Model (optional)"}),e.jsx("input",{id:`model-${s}`,type:"text",className:"mt-0.5 w-full rounded border border-zinc-700 bg-transparent px-2 py-1.5 text-sm text-zinc-200 placeholder-zinc-600 focus:border-zinc-500 focus:outline-none",placeholder:H,value:g,onChange:c=>h(c.target.value)})]}),e.jsxs("div",{children:[e.jsx("label",{className:"text-xs text-zinc-500",children:"Quota (optional)"}),e.jsxs("div",{className:"mt-0.5 grid grid-cols-3 gap-1.5",children:[e.jsxs("div",{children:[e.jsx("input",{type:"number",min:"1",className:"w-full rounded border border-zinc-700 bg-transparent px-2 py-1.5 text-sm text-zinc-200 placeholder-zinc-600 focus:border-zinc-500 focus:outline-none",placeholder:"Concurrent",value:p,onChange:c=>a(c.target.value)}),e.jsx("p",{className:"mt-0.5 text-[10px] text-zinc-600",children:"Max concurrent"})]}),e.jsxs("div",{children:[e.jsx("input",{type:"number",min:"1",className:"w-full rounded border border-zinc-700 bg-transparent px-2 py-1.5 text-sm text-zinc-200 placeholder-zinc-600 focus:border-zinc-500 focus:outline-none",placeholder:"/min",value:i,onChange:c=>v(c.target.value)}),e.jsx("p",{className:"mt-0.5 text-[10px] text-zinc-600",children:"Per minute"})]}),e.jsxs("div",{children:[e.jsx("input",{type:"number",min:"1",className:"w-full rounded border border-zinc-700 bg-transparent px-2 py-1.5 text-sm text-zinc-200 placeholder-zinc-600 focus:border-zinc-500 focus:outline-none",placeholder:"/day",value:N,onChange:c=>S(c.target.value)}),e.jsx("p",{className:"mt-0.5 text-[10px] text-zinc-600",children:"Per day"})]})]})]}),C&&e.jsx("p",{className:"text-xs text-rose-400",children:C}),L&&e.jsx("p",{className:"text-xs text-emerald-400",children:"Provider updated."}),e.jsx(f,{type:"button",size:"sm",disabled:!M||z,onClick:k(T),children:z?"Saving...":"Save"})]})}function X({onSaved:s}){const[m,l]=n.useState(""),[j,u]=n.useState(""),[r,o]=n.useState(!1),[x,d]=n.useState(null),[g,h]=n.useState(!1),p=m.trim().length>0&&j.trim().length>0;async function a(){if(p){o(!0),d(null),h(!1);try{await R({clientId:m.trim(),clientSecret:j.trim()}),l(""),u(""),h(!0),A({title:"Google OAuth app updated",detail:"Dashboard Google credentials were saved.",tone:"positive",dedupeKey:"settings:google-oauth",dedupeMode:"replace"}),s()}catch(i){d(i instanceof Error?i.message:"Failed to update Google OAuth credentials")}finally{o(!1)}}}return e.jsxs("div",{className:"mt-3 rounded-lg border border-zinc-800 bg-zinc-900/40 p-3 space-y-2",children:[e.jsxs("div",{children:[e.jsxs("div",{className:"flex items-center justify-between",children:[e.jsx("label",{className:"text-xs text-zinc-500",htmlFor:"google-client-id",children:"Client ID"}),e.jsxs("a",{href:"https://console.cloud.google.com/apis/credentials",target:"_blank",rel:"noopener noreferrer",className:"text-[10px] text-zinc-500 hover:text-zinc-300 underline underline-offset-2",children:["Google Cloud ","↗"]})]}),e.jsx("input",{id:"google-client-id",type:"text",className:"mt-0.5 w-full rounded border border-zinc-700 bg-transparent px-2 py-1.5 text-sm text-zinc-200 placeholder-zinc-600 focus:border-zinc-500 focus:outline-none",placeholder:"Google OAuth client ID",value:m,onChange:i=>l(i.target.value)})]}),e.jsxs("div",{children:[e.jsx("label",{className:"text-xs text-zinc-500",htmlFor:"google-client-secret",children:"Client secret"}),e.jsx("input",{id:"google-client-secret",type:"password",className:"mt-0.5 w-full rounded border border-zinc-700 bg-transparent px-2 py-1.5 text-sm text-zinc-200 placeholder-zinc-600 focus:border-zinc-500 focus:outline-none",placeholder:"Google OAuth client secret",value:j,onChange:i=>u(i.target.value)})]}),e.jsxs("p",{className:"text-[11px] text-zinc-500",children:["These credentials are stored in ",e.jsx("code",{children:"~/.canonry/config.yaml"}),". Project-level Search Console connections are created separately per canonical domain."]}),x&&e.jsx("p",{className:"text-xs text-rose-400",children:x}),g&&e.jsx("p",{className:"text-xs text-emerald-400",children:"Google OAuth credentials updated."}),e.jsx(f,{type:"button",size:"sm",disabled:!p||r,onClick:k(a),children:r?"Saving...":"Save Google OAuth app"})]})}function Y(){const[s,m]=n.useState(null),[l,j]=n.useState(null),[u,r]=n.useState(!1),[o,x]=n.useState("localhost"),[d,g]=n.useState("9222"),[h,p]=n.useState(!1);return n.useEffect(()=>{E().then(m).catch(a=>{const i=a instanceof Error?a.message:String(a);i.includes("501")||j(i)})},[]),e.jsxs(b,{className:"surface-card",children:[e.jsxs("div",{className:"section-head",children:[e.jsxs("div",{children:[e.jsx("p",{className:"eyebrow eyebrow-soft",children:"Browser provider"}),e.jsx("h2",{children:"ChatGPT (CDP)"})]}),e.jsx(y,{tone:s?.connected?"positive":"caution",children:s?.connected?"Connected":"Not connected"})]}),e.jsxs("dl",{className:"definition-list mt-3",children:[s?.endpoint&&e.jsxs("div",{children:[e.jsx("dt",{children:"Endpoint"}),e.jsx("dd",{className:"font-mono text-xs",children:s.endpoint})]}),s?.browserVersion&&e.jsxs("div",{children:[e.jsx("dt",{children:"Browser"}),e.jsx("dd",{className:"text-xs",children:s.browserVersion})]}),s?.targets&&s.targets.length>0&&e.jsxs("div",{children:[e.jsx("dt",{children:"Tabs"}),e.jsx("dd",{children:s.targets.map(a=>e.jsxs("span",{className:"mr-2",children:[a.name,": ",a.alive?"● alive":"○ idle"]},a.name))})]})]}),e.jsx("p",{className:"mt-2 text-sm text-zinc-500",children:s?.connected?"Connected to Chrome via CDP. Launch Chrome with --remote-debugging-port to use this provider.":l||"Not configured. Set an endpoint below or run: canonry cdp connect --host localhost --port 9222"}),e.jsx("div",{className:"mt-2",children:e.jsx(f,{type:"button",variant:"outline",size:"sm",onClick:()=>r(!u),children:u?"Cancel":s?.connected?"Update endpoint":"Configure"})}),u&&e.jsxs("form",{className:"mt-3 flex flex-col gap-2",onSubmit:k(async a=>{a.preventDefault(),p(!0);try{await q(o,parseInt(d,10)||9222);const i=await E().catch(()=>null);i&&m(i),r(!1),A({title:"CDP endpoint saved",detail:`${o}:${parseInt(d,10)||9222} is now configured.`,tone:"positive",dedupeKey:"settings:cdp",dedupeMode:"replace"})}catch(i){j(i instanceof Error?i.message:String(i))}finally{p(!1)}}),children:[e.jsxs("div",{className:"flex gap-2",children:[e.jsx("input",{className:"flex-1 rounded border border-zinc-700 bg-zinc-900 px-2 py-1 text-sm text-zinc-100 placeholder-zinc-500 focus:outline-none focus:ring-1 focus:ring-zinc-500",placeholder:"localhost",value:o,onChange:a=>x(a.target.value),"aria-label":"CDP host"}),e.jsx("input",{className:"w-24 rounded border border-zinc-700 bg-zinc-900 px-2 py-1 text-sm text-zinc-100 placeholder-zinc-500 focus:outline-none focus:ring-1 focus:ring-zinc-500",placeholder:"9222",value:d,onChange:a=>g(a.target.value),"aria-label":"CDP port"})]}),e.jsx("div",{children:e.jsx(f,{type:"submit",size:"sm",disabled:h,children:h?"Saving…":"Save endpoint"})})]})]})}const Z={apiStatus:{state:"checking",detail:"Checking service health"},workerStatus:{state:"checking",detail:"Checking service health"}};function ie(){const s=V(),{dashboard:m}=W(),l=m?.settings??s?.dashboard?.settings,r=Q(!s,s?.health).data??s?.health??Z,[o,x]=n.useState(null),[d,g]=n.useState(!1),[h,p]=n.useState(!1),[a,i]=n.useState(""),[v,N]=n.useState(!1),[S,z]=n.useState(null),[P,C]=n.useState(!1);return l?e.jsxs("div",{className:"page-container",children:[e.jsx("div",{className:"page-header",children:e.jsxs("div",{className:"page-header-left",children:[e.jsx("h1",{className:"page-title",children:"Settings"}),e.jsx("p",{className:"page-subtitle",children:"Provider state, Google OAuth, Bing WMT setup, and service health."})]})}),e.jsxs("section",{className:"settings-grid",children:[l.providerStatuses.map(t=>e.jsxs(b,{className:"surface-card",children:[e.jsxs("div",{className:"section-head",children:[e.jsxs("div",{children:[e.jsx("p",{className:"eyebrow eyebrow-soft",children:"Provider"}),e.jsx("h2",{children:t.displayName??t.name})]}),e.jsx(y,{tone:t.state==="ready"?"positive":"caution",children:t.state==="ready"?"Ready":"Needs config"})]}),e.jsxs("dl",{className:"definition-list mt-3",children:[e.jsxs("div",{children:[e.jsx("dt",{children:"Model"}),e.jsx("dd",{className:"font-mono text-xs",children:t.model})]}),t.quota&&e.jsxs(e.Fragment,{children:[e.jsxs("div",{children:[e.jsx("dt",{children:"Concurrency"}),e.jsx("dd",{children:t.quota.maxConcurrency})]}),e.jsxs("div",{children:[e.jsx("dt",{children:"Rate limit"}),e.jsxs("dd",{children:[t.quota.maxRequestsPerMinute,"/min · ",t.quota.maxRequestsPerDay,"/day"]})]})]})]}),e.jsx("p",{className:"mt-2 text-sm text-zinc-500",children:t.detail}),e.jsx("div",{className:"mt-2",children:e.jsx(f,{type:"button",variant:"outline",size:"sm",onClick:()=>x(o===t.name?null:t.name),children:o===t.name?"Cancel":t.state==="ready"?t.name.toLowerCase()==="local"?"Update config":"Update key":"Configure"})}),o===t.name&&e.jsx(J,{providerName:t.name,keyUrl:t.keyUrl,modelHint:t.modelHint,onSaved:()=>{x(null)}})]},t.name)),e.jsxs(b,{className:"surface-card",children:[e.jsxs("div",{className:"section-head",children:[e.jsxs("div",{children:[e.jsx("p",{className:"eyebrow eyebrow-soft",children:"Google"}),e.jsx("h2",{children:"Search Console OAuth"})]}),e.jsx(y,{tone:l.google.state==="ready"?"positive":"caution",children:l.google.state==="ready"?"Ready":"Needs config"})]}),e.jsxs("dl",{className:"definition-list mt-3",children:[e.jsxs("div",{children:[e.jsx("dt",{children:"Auth model"}),e.jsx("dd",{children:"One app credential set, then one OAuth connection per project domain"})]}),e.jsxs("div",{children:[e.jsx("dt",{children:"Storage"}),e.jsx("dd",{className:"font-mono text-xs",children:"~/.canonry/config.yaml"})]})]}),e.jsx("p",{className:"mt-2 text-sm text-zinc-500",children:l.google.detail}),e.jsx("div",{className:"mt-2",children:e.jsx(f,{type:"button",variant:"outline",size:"sm",onClick:()=>g(!d),children:d?"Cancel":l.google.state==="ready"?"Update OAuth app":"Configure Google OAuth"})}),d&&e.jsx(X,{onSaved:()=>{g(!1)}})]}),e.jsxs(b,{className:"surface-card",children:[e.jsxs("div",{className:"section-head",children:[e.jsxs("div",{children:[e.jsx("p",{className:"eyebrow eyebrow-soft",children:"Bing"}),e.jsx("h2",{children:"Webmaster Tools"})]}),e.jsx(y,{tone:l.bing.state==="ready"?"positive":"caution",children:l.bing.state==="ready"?"Ready":"Needs config"})]}),e.jsxs("dl",{className:"definition-list mt-3",children:[e.jsxs("div",{children:[e.jsx("dt",{children:"Auth model"}),e.jsx("dd",{children:"API key authentication — no OAuth needed"})]}),e.jsxs("div",{children:[e.jsx("dt",{children:"Storage"}),e.jsx("dd",{className:"font-mono text-xs",children:"~/.canonry/config.yaml"})]})]}),e.jsx("p",{className:"mt-2 text-sm text-zinc-500",children:l.bing.detail}),e.jsx("div",{className:"mt-2",children:e.jsx(f,{type:"button",variant:"outline",size:"sm",onClick:()=>p(!h),children:h?"Cancel":l.bing.state==="ready"?"Update API key":"Configure Bing"})}),h&&e.jsxs("div",{className:"mt-3 rounded-lg border border-zinc-800 bg-zinc-900/40 p-3 space-y-2",children:[e.jsxs("div",{children:[e.jsxs("div",{className:"flex items-center justify-between",children:[e.jsx("label",{className:"text-xs text-zinc-500",htmlFor:"bing-api-key",children:"API Key"}),e.jsx("a",{href:"https://www.bing.com/webmasters/",target:"_blank",rel:"noopener noreferrer",className:"text-[10px] text-zinc-500 hover:text-zinc-300 underline underline-offset-2",children:"Bing Webmaster Tools"})]}),e.jsx("input",{id:"bing-api-key",type:"password",className:"mt-0.5 w-full rounded border border-zinc-700 bg-transparent px-2 py-1.5 text-sm text-zinc-200 placeholder-zinc-600 focus:border-zinc-500 focus:outline-none",placeholder:"Bing Webmaster Tools API key",value:a,onChange:t=>i(t.target.value)})]}),e.jsxs("p",{className:"text-[11px] text-zinc-500",children:["This key is stored in ",e.jsx("code",{children:"~/.canonry/config.yaml"}),". Project-level Bing connections are created separately per canonical domain."]}),S&&e.jsx("p",{className:"text-xs text-rose-400",children:S}),P&&e.jsx("p",{className:"text-xs text-emerald-400",children:"Bing API key updated."}),e.jsx(f,{type:"button",size:"sm",disabled:!a.trim()||v,onClick:k(async()=>{if(a.trim()){N(!0),z(null),C(!1);try{await _(a.trim()),i(""),C(!0),p(!1),A({title:"Bing API key updated",detail:"Dashboard Bing credentials were saved.",tone:"positive",dedupeKey:"settings:bing",dedupeMode:"replace"})}catch(t){z(t instanceof Error?t.message:"Failed to update Bing API key")}finally{N(!1)}}}),children:v?"Saving...":"Save Bing API key"})]})]}),e.jsx(Y,{}),e.jsxs(b,{className:"surface-card",children:[e.jsx("div",{className:"section-head",children:e.jsxs("div",{children:[e.jsx("p",{className:"eyebrow eyebrow-soft",children:"Service health"}),e.jsx("h2",{children:"API and worker"})]})}),e.jsxs("div",{className:"compact-stack",children:[e.jsxs("div",{className:"health-row",children:[e.jsxs("div",{children:[e.jsx("p",{className:"run-row-title",children:"API"}),e.jsx("p",{className:"supporting-copy",children:r.apiStatus.detail})]}),e.jsx(y,{tone:K(r.apiStatus),title:F(r.apiStatus),children:r.apiStatus.state==="ok"?"Healthy":"Attention"})]}),e.jsxs("div",{className:"health-row",children:[e.jsxs("div",{children:[e.jsx("p",{className:"run-row-title",children:"Worker"}),e.jsx("p",{className:"supporting-copy",children:r.workerStatus.detail})]}),e.jsx(y,{tone:K(r.workerStatus),title:F(r.workerStatus),children:r.workerStatus.state==="ok"?"Healthy":"Attention"})]})]})]})]}),e.jsx("section",{className:"page-section",children:e.jsxs(b,{className:"surface-card",children:[e.jsx("div",{className:"section-head",children:e.jsxs("div",{children:[e.jsx("p",{className:"eyebrow eyebrow-soft",children:"Self-host notes"}),e.jsx("h2",{children:"Operational guidance"})]})}),e.jsx("ul",{className:"detail-list",children:l.selfHostNotes.map(t=>e.jsx("li",{children:t},t))}),e.jsx("p",{className:"supporting-copy",children:l.bootstrapNote})]})})]}):null}export{ie as SettingsPage};
1
+ import{r as n,j as e}from"./vendor-tanstack-Dq7p98wZ.js";import{B as f,i as k,bj as $,L as A,bk as q,bl as E,g as b,T as y,bm as R,aH as V,bg as W,bn as Q,bo as _,bp as F,bq as K}from"./index-VMFHNbas.js";import"./vendor-radix-B57xfQbP.js";import"./vendor-recharts-DWvKDyBF.js";import"./vendor-markdown-DK7fbRNb.js";function J({providerName:s,keyUrl:m,modelHint:l,onSaved:j}){const u=s.toLowerCase()==="local",[r,o]=n.useState(""),[x,d]=n.useState(""),[g,h]=n.useState(""),[p,a]=n.useState(""),[i,v]=n.useState(""),[N,S]=n.useState(""),[z,P]=n.useState(!1),[C,t]=n.useState(null),[L,I]=n.useState(!1),O=u?x.trim().length>0:r.trim().length>0;async function T(){if(O){P(!0),t(null),I(!1);try{const c=U=>{const B=parseInt(U.trim(),10);return Number.isFinite(B)&&B>0?B:void 0},w={},M=c(p);M!==void 0&&(w.maxConcurrency=M);const D=c(i);D!==void 0&&(w.maxRequestsPerMinute=D);const G=c(N);G!==void 0&&(w.maxRequestsPerDay=G),await $(s.toLowerCase(),{...r.trim()?{apiKey:r.trim()}:{},...x.trim()?{baseUrl:x.trim()}:{},...g.trim()?{model:g.trim()}:{},...Object.keys(w).length>0?{quota:w}:{}}),o(""),d(""),h(""),a(""),v(""),S(""),I(!0),A({title:"Provider updated",detail:`${s} configuration saved.`,tone:"positive",dedupeKey:`settings:provider:${s}`,dedupeMode:"replace"}),j()}catch(c){t(c instanceof Error?c.message:"Failed to update provider")}finally{P(!1)}}}const H=l??"Use default model";return e.jsxs("div",{className:"mt-3 rounded-lg border border-zinc-800 bg-zinc-900/40 p-3 space-y-2",children:[u&&e.jsxs("div",{children:[e.jsx("label",{className:"text-xs text-zinc-500",htmlFor:`base-url-${s}`,children:"Base URL"}),e.jsx("input",{id:`base-url-${s}`,type:"text",className:"mt-0.5 w-full rounded border border-zinc-700 bg-transparent px-2 py-1.5 text-sm text-zinc-200 placeholder-zinc-600 focus:border-zinc-500 focus:outline-none",placeholder:"http://localhost:11434/v1",value:x,onChange:c=>d(c.target.value)}),e.jsx("p",{className:"mt-0.5 text-[10px] text-zinc-600",children:"Any OpenAI-compatible endpoint — Ollama, LM Studio, llama.cpp, vLLM"})]}),e.jsxs("div",{children:[e.jsxs("div",{className:"flex items-center justify-between",children:[e.jsxs("label",{className:"text-xs text-zinc-500",htmlFor:`api-key-${s}`,children:["API Key",u?" (optional)":""]}),m&&e.jsxs("a",{href:m,target:"_blank",rel:"noopener noreferrer",className:"text-[10px] text-zinc-500 hover:text-zinc-300 underline underline-offset-2",children:["Get API key ","↗"]})]}),e.jsx("input",{id:`api-key-${s}`,type:"password",className:"mt-0.5 w-full rounded border border-zinc-700 bg-transparent px-2 py-1.5 text-sm text-zinc-200 placeholder-zinc-600 focus:border-zinc-500 focus:outline-none",placeholder:u?"Optional — most local servers don't need one":`Enter ${s} API key`,value:r,onChange:c=>o(c.target.value)})]}),e.jsxs("div",{children:[e.jsx("label",{className:"text-xs text-zinc-500",htmlFor:`model-${s}`,children:"Model (optional)"}),e.jsx("input",{id:`model-${s}`,type:"text",className:"mt-0.5 w-full rounded border border-zinc-700 bg-transparent px-2 py-1.5 text-sm text-zinc-200 placeholder-zinc-600 focus:border-zinc-500 focus:outline-none",placeholder:H,value:g,onChange:c=>h(c.target.value)})]}),e.jsxs("div",{children:[e.jsx("label",{className:"text-xs text-zinc-500",children:"Quota (optional)"}),e.jsxs("div",{className:"mt-0.5 grid grid-cols-3 gap-1.5",children:[e.jsxs("div",{children:[e.jsx("input",{type:"number",min:"1",className:"w-full rounded border border-zinc-700 bg-transparent px-2 py-1.5 text-sm text-zinc-200 placeholder-zinc-600 focus:border-zinc-500 focus:outline-none",placeholder:"Concurrent",value:p,onChange:c=>a(c.target.value)}),e.jsx("p",{className:"mt-0.5 text-[10px] text-zinc-600",children:"Max concurrent"})]}),e.jsxs("div",{children:[e.jsx("input",{type:"number",min:"1",className:"w-full rounded border border-zinc-700 bg-transparent px-2 py-1.5 text-sm text-zinc-200 placeholder-zinc-600 focus:border-zinc-500 focus:outline-none",placeholder:"/min",value:i,onChange:c=>v(c.target.value)}),e.jsx("p",{className:"mt-0.5 text-[10px] text-zinc-600",children:"Per minute"})]}),e.jsxs("div",{children:[e.jsx("input",{type:"number",min:"1",className:"w-full rounded border border-zinc-700 bg-transparent px-2 py-1.5 text-sm text-zinc-200 placeholder-zinc-600 focus:border-zinc-500 focus:outline-none",placeholder:"/day",value:N,onChange:c=>S(c.target.value)}),e.jsx("p",{className:"mt-0.5 text-[10px] text-zinc-600",children:"Per day"})]})]})]}),C&&e.jsx("p",{className:"text-xs text-rose-400",children:C}),L&&e.jsx("p",{className:"text-xs text-emerald-400",children:"Provider updated."}),e.jsx(f,{type:"button",size:"sm",disabled:!O||z,onClick:k(T),children:z?"Saving...":"Save"})]})}function X({onSaved:s}){const[m,l]=n.useState(""),[j,u]=n.useState(""),[r,o]=n.useState(!1),[x,d]=n.useState(null),[g,h]=n.useState(!1),p=m.trim().length>0&&j.trim().length>0;async function a(){if(p){o(!0),d(null),h(!1);try{await q({clientId:m.trim(),clientSecret:j.trim()}),l(""),u(""),h(!0),A({title:"Google OAuth app updated",detail:"Dashboard Google credentials were saved.",tone:"positive",dedupeKey:"settings:google-oauth",dedupeMode:"replace"}),s()}catch(i){d(i instanceof Error?i.message:"Failed to update Google OAuth credentials")}finally{o(!1)}}}return e.jsxs("div",{className:"mt-3 rounded-lg border border-zinc-800 bg-zinc-900/40 p-3 space-y-2",children:[e.jsxs("div",{children:[e.jsxs("div",{className:"flex items-center justify-between",children:[e.jsx("label",{className:"text-xs text-zinc-500",htmlFor:"google-client-id",children:"Client ID"}),e.jsxs("a",{href:"https://console.cloud.google.com/apis/credentials",target:"_blank",rel:"noopener noreferrer",className:"text-[10px] text-zinc-500 hover:text-zinc-300 underline underline-offset-2",children:["Google Cloud ","↗"]})]}),e.jsx("input",{id:"google-client-id",type:"text",className:"mt-0.5 w-full rounded border border-zinc-700 bg-transparent px-2 py-1.5 text-sm text-zinc-200 placeholder-zinc-600 focus:border-zinc-500 focus:outline-none",placeholder:"Google OAuth client ID",value:m,onChange:i=>l(i.target.value)})]}),e.jsxs("div",{children:[e.jsx("label",{className:"text-xs text-zinc-500",htmlFor:"google-client-secret",children:"Client secret"}),e.jsx("input",{id:"google-client-secret",type:"password",className:"mt-0.5 w-full rounded border border-zinc-700 bg-transparent px-2 py-1.5 text-sm text-zinc-200 placeholder-zinc-600 focus:border-zinc-500 focus:outline-none",placeholder:"Google OAuth client secret",value:j,onChange:i=>u(i.target.value)})]}),e.jsxs("p",{className:"text-[11px] text-zinc-500",children:["These credentials are stored in ",e.jsx("code",{children:"~/.canonry/config.yaml"}),". Project-level Search Console connections are created separately per canonical domain."]}),x&&e.jsx("p",{className:"text-xs text-rose-400",children:x}),g&&e.jsx("p",{className:"text-xs text-emerald-400",children:"Google OAuth credentials updated."}),e.jsx(f,{type:"button",size:"sm",disabled:!p||r,onClick:k(a),children:r?"Saving...":"Save Google OAuth app"})]})}function Y(){const[s,m]=n.useState(null),[l,j]=n.useState(null),[u,r]=n.useState(!1),[o,x]=n.useState("localhost"),[d,g]=n.useState("9222"),[h,p]=n.useState(!1);return n.useEffect(()=>{E().then(m).catch(a=>{const i=a instanceof Error?a.message:String(a);i.includes("501")||j(i)})},[]),e.jsxs(b,{className:"surface-card",children:[e.jsxs("div",{className:"section-head",children:[e.jsxs("div",{children:[e.jsx("p",{className:"eyebrow eyebrow-soft",children:"Browser provider"}),e.jsx("h2",{children:"ChatGPT (CDP)"})]}),e.jsx(y,{tone:s?.connected?"positive":"caution",children:s?.connected?"Connected":"Not connected"})]}),e.jsxs("dl",{className:"definition-list mt-3",children:[s?.endpoint&&e.jsxs("div",{children:[e.jsx("dt",{children:"Endpoint"}),e.jsx("dd",{className:"font-mono text-xs",children:s.endpoint})]}),s?.browserVersion&&e.jsxs("div",{children:[e.jsx("dt",{children:"Browser"}),e.jsx("dd",{className:"text-xs",children:s.browserVersion})]}),s?.targets&&s.targets.length>0&&e.jsxs("div",{children:[e.jsx("dt",{children:"Tabs"}),e.jsx("dd",{children:s.targets.map(a=>e.jsxs("span",{className:"mr-2",children:[a.name,": ",a.alive?"● alive":"○ idle"]},a.name))})]})]}),e.jsx("p",{className:"mt-2 text-sm text-zinc-500",children:s?.connected?"Connected to Chrome via CDP. Launch Chrome with --remote-debugging-port to use this provider.":l||"Not configured. Set an endpoint below or run: canonry cdp connect --host localhost --port 9222"}),e.jsx("div",{className:"mt-2",children:e.jsx(f,{type:"button",variant:"outline",size:"sm",onClick:()=>r(!u),children:u?"Cancel":s?.connected?"Update endpoint":"Configure"})}),u&&e.jsxs("form",{className:"mt-3 flex flex-col gap-2",onSubmit:k(async a=>{a.preventDefault(),p(!0);try{await R(o,parseInt(d,10)||9222);const i=await E().catch(()=>null);i&&m(i),r(!1),A({title:"CDP endpoint saved",detail:`${o}:${parseInt(d,10)||9222} is now configured.`,tone:"positive",dedupeKey:"settings:cdp",dedupeMode:"replace"})}catch(i){j(i instanceof Error?i.message:String(i))}finally{p(!1)}}),children:[e.jsxs("div",{className:"flex gap-2",children:[e.jsx("input",{className:"flex-1 rounded border border-zinc-700 bg-zinc-900 px-2 py-1 text-sm text-zinc-100 placeholder-zinc-500 focus:outline-none focus:ring-1 focus:ring-zinc-500",placeholder:"localhost",value:o,onChange:a=>x(a.target.value),"aria-label":"CDP host"}),e.jsx("input",{className:"w-24 rounded border border-zinc-700 bg-zinc-900 px-2 py-1 text-sm text-zinc-100 placeholder-zinc-500 focus:outline-none focus:ring-1 focus:ring-zinc-500",placeholder:"9222",value:d,onChange:a=>g(a.target.value),"aria-label":"CDP port"})]}),e.jsx("div",{children:e.jsx(f,{type:"submit",size:"sm",disabled:h,children:h?"Saving…":"Save endpoint"})})]})]})}const Z={apiStatus:{state:"checking",detail:"Checking service health"},workerStatus:{state:"checking",detail:"Checking service health"}};function ie(){const s=V(),{dashboard:m}=W(),l=m?.settings??s?.dashboard?.settings,r=Q(!s,s?.health).data??s?.health??Z,[o,x]=n.useState(null),[d,g]=n.useState(!1),[h,p]=n.useState(!1),[a,i]=n.useState(""),[v,N]=n.useState(!1),[S,z]=n.useState(null),[P,C]=n.useState(!1);return l?e.jsxs("div",{className:"page-container",children:[e.jsx("div",{className:"page-header",children:e.jsxs("div",{className:"page-header-left",children:[e.jsx("h1",{className:"page-title",children:"Settings"}),e.jsx("p",{className:"page-subtitle",children:"Provider state, Google OAuth, Bing WMT setup, and service health."})]})}),e.jsxs("section",{className:"settings-grid",children:[l.providerStatuses.map(t=>e.jsxs(b,{className:"surface-card",children:[e.jsxs("div",{className:"section-head",children:[e.jsxs("div",{children:[e.jsx("p",{className:"eyebrow eyebrow-soft",children:"Provider"}),e.jsx("h2",{children:t.displayName??t.name})]}),e.jsx(y,{tone:t.state==="ready"?"positive":"caution",children:t.state==="ready"?"Ready":"Needs config"})]}),e.jsxs("dl",{className:"definition-list mt-3",children:[e.jsxs("div",{children:[e.jsx("dt",{children:"Model"}),e.jsx("dd",{className:"font-mono text-xs",children:t.model})]}),t.quota&&e.jsxs(e.Fragment,{children:[e.jsxs("div",{children:[e.jsx("dt",{children:"Concurrency"}),e.jsx("dd",{children:t.quota.maxConcurrency})]}),e.jsxs("div",{children:[e.jsx("dt",{children:"Rate limit"}),e.jsxs("dd",{children:[t.quota.maxRequestsPerMinute,"/min · ",t.quota.maxRequestsPerDay,"/day"]})]})]})]}),e.jsx("p",{className:"mt-2 text-sm text-zinc-500",children:t.detail}),e.jsx("div",{className:"mt-2",children:e.jsx(f,{type:"button",variant:"outline",size:"sm",onClick:()=>x(o===t.name?null:t.name),children:o===t.name?"Cancel":t.state==="ready"?t.name.toLowerCase()==="local"?"Update config":"Update key":"Configure"})}),o===t.name&&e.jsx(J,{providerName:t.name,keyUrl:t.keyUrl,modelHint:t.modelHint,onSaved:()=>{x(null)}})]},t.name)),e.jsxs(b,{className:"surface-card",children:[e.jsxs("div",{className:"section-head",children:[e.jsxs("div",{children:[e.jsx("p",{className:"eyebrow eyebrow-soft",children:"Google"}),e.jsx("h2",{children:"Search Console OAuth"})]}),e.jsx(y,{tone:l.google.state==="ready"?"positive":"caution",children:l.google.state==="ready"?"Ready":"Needs config"})]}),e.jsxs("dl",{className:"definition-list mt-3",children:[e.jsxs("div",{children:[e.jsx("dt",{children:"Auth model"}),e.jsx("dd",{children:"One app credential set, then one OAuth connection per project domain"})]}),e.jsxs("div",{children:[e.jsx("dt",{children:"Storage"}),e.jsx("dd",{className:"font-mono text-xs",children:"~/.canonry/config.yaml"})]})]}),e.jsx("p",{className:"mt-2 text-sm text-zinc-500",children:l.google.detail}),e.jsx("div",{className:"mt-2",children:e.jsx(f,{type:"button",variant:"outline",size:"sm",onClick:()=>g(!d),children:d?"Cancel":l.google.state==="ready"?"Update OAuth app":"Configure Google OAuth"})}),d&&e.jsx(X,{onSaved:()=>{g(!1)}})]}),e.jsxs(b,{className:"surface-card",children:[e.jsxs("div",{className:"section-head",children:[e.jsxs("div",{children:[e.jsx("p",{className:"eyebrow eyebrow-soft",children:"Bing"}),e.jsx("h2",{children:"Webmaster Tools"})]}),e.jsx(y,{tone:l.bing.state==="ready"?"positive":"caution",children:l.bing.state==="ready"?"Ready":"Needs config"})]}),e.jsxs("dl",{className:"definition-list mt-3",children:[e.jsxs("div",{children:[e.jsx("dt",{children:"Auth model"}),e.jsx("dd",{children:"API key authentication — no OAuth needed"})]}),e.jsxs("div",{children:[e.jsx("dt",{children:"Storage"}),e.jsx("dd",{className:"font-mono text-xs",children:"~/.canonry/config.yaml"})]})]}),e.jsx("p",{className:"mt-2 text-sm text-zinc-500",children:l.bing.detail}),e.jsx("div",{className:"mt-2",children:e.jsx(f,{type:"button",variant:"outline",size:"sm",onClick:()=>p(!h),children:h?"Cancel":l.bing.state==="ready"?"Update API key":"Configure Bing"})}),h&&e.jsxs("div",{className:"mt-3 rounded-lg border border-zinc-800 bg-zinc-900/40 p-3 space-y-2",children:[e.jsxs("div",{children:[e.jsxs("div",{className:"flex items-center justify-between",children:[e.jsx("label",{className:"text-xs text-zinc-500",htmlFor:"bing-api-key",children:"API Key"}),e.jsx("a",{href:"https://www.bing.com/webmasters/",target:"_blank",rel:"noopener noreferrer",className:"text-[10px] text-zinc-500 hover:text-zinc-300 underline underline-offset-2",children:"Bing Webmaster Tools"})]}),e.jsx("input",{id:"bing-api-key",type:"password",className:"mt-0.5 w-full rounded border border-zinc-700 bg-transparent px-2 py-1.5 text-sm text-zinc-200 placeholder-zinc-600 focus:border-zinc-500 focus:outline-none",placeholder:"Bing Webmaster Tools API key",value:a,onChange:t=>i(t.target.value)})]}),e.jsxs("p",{className:"text-[11px] text-zinc-500",children:["This key is stored in ",e.jsx("code",{children:"~/.canonry/config.yaml"}),". Project-level Bing connections are created separately per canonical domain."]}),S&&e.jsx("p",{className:"text-xs text-rose-400",children:S}),P&&e.jsx("p",{className:"text-xs text-emerald-400",children:"Bing API key updated."}),e.jsx(f,{type:"button",size:"sm",disabled:!a.trim()||v,onClick:k(async()=>{if(a.trim()){N(!0),z(null),C(!1);try{await _(a.trim()),i(""),C(!0),p(!1),A({title:"Bing API key updated",detail:"Dashboard Bing credentials were saved.",tone:"positive",dedupeKey:"settings:bing",dedupeMode:"replace"})}catch(t){z(t instanceof Error?t.message:"Failed to update Bing API key")}finally{N(!1)}}}),children:v?"Saving...":"Save Bing API key"})]})]}),e.jsx(Y,{}),e.jsxs(b,{className:"surface-card",children:[e.jsx("div",{className:"section-head",children:e.jsxs("div",{children:[e.jsx("p",{className:"eyebrow eyebrow-soft",children:"Service health"}),e.jsx("h2",{children:"API and worker"})]})}),e.jsxs("div",{className:"compact-stack",children:[e.jsxs("div",{className:"health-row",children:[e.jsxs("div",{children:[e.jsx("p",{className:"run-row-title",children:"API"}),e.jsx("p",{className:"supporting-copy",children:r.apiStatus.detail})]}),e.jsx(y,{tone:K(r.apiStatus),title:F(r.apiStatus),children:r.apiStatus.state==="ok"?"Healthy":"Attention"})]}),e.jsxs("div",{className:"health-row",children:[e.jsxs("div",{children:[e.jsx("p",{className:"run-row-title",children:"Worker"}),e.jsx("p",{className:"supporting-copy",children:r.workerStatus.detail})]}),e.jsx(y,{tone:K(r.workerStatus),title:F(r.workerStatus),children:r.workerStatus.state==="ok"?"Healthy":"Attention"})]})]})]})]}),e.jsx("section",{className:"page-section",children:e.jsxs(b,{className:"surface-card",children:[e.jsx("div",{className:"section-head",children:e.jsxs("div",{children:[e.jsx("p",{className:"eyebrow eyebrow-soft",children:"Self-host notes"}),e.jsx("h2",{children:"Operational guidance"})]})}),e.jsx("ul",{className:"detail-list",children:l.selfHostNotes.map(t=>e.jsx("li",{children:t},t))}),e.jsx("p",{className:"supporting-copy",children:l.bootstrapNote})]})})]}):null}export{ie as SettingsPage};
@@ -1 +1 @@
1
- import{r as a,j as e,u as L,f as O,L as U}from"./vendor-tanstack-Dq7p98wZ.js";import{c as A,bq as _,br as $,bs as D,bt as F,bu as E,bv as B,B as N,i as k,a0 as T,bw as W,l as R,bx as I,g as S,by as G,T as H,bz as J}from"./index-DKBPD33e.js";import{a as M,b as Q,c as K,d as Z,t as Y,R as X}from"./server-traffic-Bm8iKtXK.js";import{A as ee}from"./arrow-left-DpxpMUNt.js";import"./vendor-radix-B57xfQbP.js";import"./vendor-recharts-DWvKDyBF.js";import"./vendor-markdown-DK7fbRNb.js";const te=[["path",{d:"M17.5 19H9a7 7 0 1 1 6.71-9h1.79a4.5 4.5 0 1 1 0 9Z",key:"p7xjir"}]],se=A("cloud",te);const re=[["path",{d:"M13.73 4a2 2 0 0 0-3.46 0l-8 14A2 2 0 0 0 4 21h16a2 2 0 0 0 1.73-3Z",key:"14u9p9"}]],ne=A("triangle",re);function oe({open:t,onOpenChange:i,projectName:o}){const[r,s]=a.useState("pick");a.useEffect(()=>{t&&s("pick")},[t]);const n=()=>{i(!1),s("pick")};return e.jsx(_,{open:t,onOpenChange:l=>{l?i(!0):n()},children:e.jsx($,{children:r==="pick"?e.jsx(ie,{onPick:s}):r==="wordpress"?e.jsx(ce,{projectName:o,onBack:()=>s("pick"),onClose:n}):r==="vercel"?e.jsx(de,{projectName:o,onBack:()=>s("pick"),onClose:n}):e.jsx(le,{projectName:o,onBack:()=>s("pick"),onClose:n})})})}const ae=[{type:"wordpress",name:"WordPress site",tagline:"Easiest if you run WordPress",description:"Install the Canonry Traffic Logger plugin and connect with an Application Password. No cloud account needed.",icon:B},{type:"cloud-run",name:"Google Cloud Run",tagline:"For apps hosted on Cloud Run",description:"Connect a Google Cloud service account so Canonry can read your Cloud Run request logs.",icon:se},{type:"vercel",name:"Vercel project",tagline:"For sites hosted on Vercel",description:"Connect a Vercel API token so Canonry can pull request logs straight from Vercel — no in-app instrumentation needed.",icon:ne}];function ie({onPick:t}){return e.jsxs(e.Fragment,{children:[e.jsxs(D,{children:[e.jsx(F,{children:"Connect a traffic source"}),e.jsx(E,{children:"Canonry reads your server logs to see when AI crawlers and AI-referred visitors hit your site. Pick where your site is hosted to get started."})]}),e.jsx("div",{className:"mt-6 flex flex-col gap-3",children:ae.map(({type:i,name:o,tagline:r,description:s,icon:n})=>e.jsxs("button",{type:"button",onClick:()=>t(i),className:"group flex items-start gap-4 rounded-lg border border-zinc-800 bg-zinc-900/30 p-4 text-left transition-colors hover:border-zinc-600 hover:bg-zinc-900/60 focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-zinc-400",children:[e.jsx("span",{className:"mt-0.5 inline-flex size-9 shrink-0 items-center justify-center rounded-md border border-zinc-800 bg-zinc-950 text-zinc-300 group-hover:text-zinc-100",children:e.jsx(n,{className:"size-4"})}),e.jsxs("span",{className:"flex flex-col gap-0.5",children:[e.jsxs("span",{className:"flex flex-wrap items-baseline gap-x-2",children:[e.jsx("span",{className:"text-sm font-medium text-zinc-100",children:o}),e.jsx("span",{className:"text-[11px] text-zinc-500",children:r})]}),e.jsx("span",{className:"text-xs leading-5 text-zinc-500",children:s})]})]},i))})]})}function q({title:t,description:i,onBack:o}){return e.jsxs(D,{children:[e.jsxs("button",{type:"button",onClick:o,className:"mb-1 inline-flex w-fit items-center gap-1 rounded text-xs text-zinc-500 transition-colors hover:text-zinc-200 focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-zinc-400",children:[e.jsx(ee,{className:"size-3"}),"Choose a different source"]}),e.jsx(F,{children:t}),e.jsx(E,{children:i})]})}function ce({projectName:t,onBack:i,onClose:o}){const[r,s]=a.useState(""),[n,l]=a.useState(""),[m,j]=a.useState(""),[p,w]=a.useState(""),[y,f]=a.useState(null),[z,h]=a.useState(null),v=M(t||null),C=async d=>{if(d.preventDefault(),f(null),h(null),!r.trim()){f("WordPress site URL is required.");return}if(!n.trim()){f("Username is required.");return}if(!m.trim()){f("Application Password is required.");return}try{const g=await v.mutateAsync({baseUrl:r.trim(),username:n.trim(),applicationPassword:m.trim(),displayName:p.trim()||void 0});j(""),h(`Connected ${g.displayName}.`)}catch(g){const x=g instanceof T||g instanceof Error?g.message:String(g);f(x)}};return e.jsxs(e.Fragment,{children:[e.jsx(q,{title:"Connect a WordPress site",description:e.jsxs(e.Fragment,{children:["Pulls request events from the Canonry Traffic Logger plugin. The Application Password is stored in ",e.jsx("code",{children:"~/.canonry/config.yaml"})," on the server and never echoed back to the dashboard."]}),onBack:i}),e.jsxs("form",{onSubmit:k(C),className:"mt-6 flex flex-col gap-5 overflow-y-auto pr-1",children:[e.jsx(u,{label:"Project",description:"Canonry project this source attaches to.",children:e.jsx("input",{type:"text",value:t,disabled:!0,className:"w-full rounded border border-zinc-700 bg-zinc-900/50 px-2 py-1.5 text-sm text-zinc-300"})}),e.jsx(u,{label:"WordPress site URL",description:"Base URL of the site running the Canonry Traffic Logger plugin.",required:!0,children:e.jsx("input",{type:"url",value:r,onChange:d=>s(d.target.value),required:!0,autoComplete:"url",placeholder:"https://example.com",className:"w-full rounded border border-zinc-700 bg-transparent px-2 py-1.5 text-sm text-zinc-200 placeholder-zinc-600 focus:border-zinc-500 focus:outline-none"})}),e.jsx(u,{label:"Username",description:"WordPress user that owns the Application Password.",required:!0,children:e.jsx("input",{type:"text",value:n,onChange:d=>l(d.target.value),required:!0,autoComplete:"username",className:"w-full rounded border border-zinc-700 bg-transparent px-2 py-1.5 text-sm text-zinc-200 placeholder-zinc-600 focus:border-zinc-500 focus:outline-none"})}),e.jsx(u,{label:"Application Password",description:"Create one in wp-admin under Users -> Profile -> Application Passwords.",required:!0,children:e.jsx("input",{type:"password",value:m,onChange:d=>j(d.target.value),required:!0,autoComplete:"new-password",className:"w-full rounded border border-zinc-700 bg-transparent px-2 py-1.5 text-sm text-zinc-200 placeholder-zinc-600 focus:border-zinc-500 focus:outline-none"})}),e.jsx(u,{label:"Display name (optional)",description:"Friendly label shown in the dashboard. Defaults to the WordPress host.",children:e.jsx("input",{type:"text",value:p,onChange:d=>w(d.target.value),autoComplete:"off",className:"w-full rounded border border-zinc-700 bg-transparent px-2 py-1.5 text-sm text-zinc-200 placeholder-zinc-600 focus:border-zinc-500 focus:outline-none"})}),y?e.jsx("p",{className:"rounded-md border border-rose-800/50 bg-rose-950/30 px-3 py-2 text-xs text-rose-200",children:y}):null,z?e.jsx("p",{className:"rounded-md border border-emerald-800/50 bg-emerald-950/30 px-3 py-2 text-xs text-emerald-200",children:z}):null,e.jsxs("div",{className:"mt-2 flex items-center justify-end gap-2 border-t border-zinc-800/60 pt-4",children:[e.jsx(N,{type:"button",variant:"ghost",size:"sm",onClick:o,children:"Close"}),e.jsx(N,{type:"submit",disabled:v.isPending,size:"sm",children:v.isPending?"Connecting...":"Connect"})]})]})]})}function le({projectName:t,onBack:i,onClose:o}){const[r,s]=a.useState(""),[n,l]=a.useState(""),[m,j]=a.useState(""),[p,w]=a.useState(""),[y,f]=a.useState(""),[z,h]=a.useState(null),[v,C]=a.useState(null),d=K(t||null),g=async c=>{if(c.preventDefault(),h(null),C(null),!r.trim()){h("GCP project ID is required.");return}if(!y.trim()){h("Service-account JSON content is required.");return}try{const b=await d.mutateAsync({gcpProjectId:r.trim(),serviceName:n.trim()||void 0,location:m.trim()||void 0,displayName:p.trim()||void 0,keyJson:y.trim()});f(""),C(`Connected ${b.displayName}.`)}catch(b){const V=b instanceof T||b instanceof Error?b.message:String(b);h(V)}},x=async c=>{if(!c)return;const b=await c.text();f(b)};return e.jsxs(e.Fragment,{children:[e.jsx(q,{title:"Connect a Cloud Run service",description:e.jsxs(e.Fragment,{children:["v1 supports service-account JSON only. The private key is stored in"," ",e.jsx("code",{children:"~/.canonry/config.yaml"})," on the server and never echoed back to the dashboard."]}),onBack:i}),e.jsxs("form",{onSubmit:k(g),className:"mt-6 flex flex-col gap-5 overflow-y-auto pr-1",children:[e.jsx(u,{label:"Project",description:"Canonry project this source attaches to.",children:e.jsx("input",{type:"text",value:t,disabled:!0,className:"w-full rounded border border-zinc-700 bg-zinc-900/50 px-2 py-1.5 text-sm text-zinc-300"})}),e.jsx(u,{label:"GCP project ID",description:"The Google Cloud project hosting the Cloud Run service (e.g. my-prod-foo).",required:!0,children:e.jsx("input",{type:"text",value:r,onChange:c=>s(c.target.value),required:!0,autoComplete:"off",className:"w-full rounded border border-zinc-700 bg-transparent px-2 py-1.5 text-sm text-zinc-200 placeholder-zinc-600 focus:border-zinc-500 focus:outline-none"})}),e.jsx(u,{label:"Service name (optional)",description:"Restrict log pulls to a specific Cloud Run service. Omit to pull all services in the project.",children:e.jsx("input",{type:"text",value:n,onChange:c=>l(c.target.value),autoComplete:"off",className:"w-full rounded border border-zinc-700 bg-transparent px-2 py-1.5 text-sm text-zinc-200 placeholder-zinc-600 focus:border-zinc-500 focus:outline-none"})}),e.jsx(u,{label:"Location (optional)",description:"Region of the Cloud Run service (e.g. us-central1). Helpful when multiple regions emit logs.",children:e.jsx("input",{type:"text",value:m,onChange:c=>j(c.target.value),autoComplete:"off",className:"w-full rounded border border-zinc-700 bg-transparent px-2 py-1.5 text-sm text-zinc-200 placeholder-zinc-600 focus:border-zinc-500 focus:outline-none"})}),e.jsx(u,{label:"Display name (optional)",description:"Friendly label shown in the dashboard. Defaults to the project + service combo.",children:e.jsx("input",{type:"text",value:p,onChange:c=>w(c.target.value),autoComplete:"off",className:"w-full rounded border border-zinc-700 bg-transparent px-2 py-1.5 text-sm text-zinc-200 placeholder-zinc-600 focus:border-zinc-500 focus:outline-none"})}),e.jsxs(u,{label:"Service-account JSON",description:"Paste the contents of the SA key (JSON). The SA needs roles/logging.viewer (or any role granting logging.logEntries.list).",required:!0,children:[e.jsx("textarea",{value:y,onChange:c=>f(c.target.value),rows:6,spellCheck:!1,autoComplete:"off",className:"w-full rounded border border-zinc-700 bg-transparent px-2 py-1.5 font-mono text-[11px] text-zinc-200 placeholder-zinc-600 focus:border-zinc-500 focus:outline-none",placeholder:'{"type":"service_account","project_id":"…","private_key":"…"}',required:!0}),e.jsxs("label",{className:"mt-2 inline-flex cursor-pointer items-center gap-2 text-xs text-zinc-400 hover:text-zinc-200",children:[e.jsx("input",{type:"file",accept:"application/json,.json",className:"hidden",onChange:c=>{x(c.target.files?.[0]??null)}}),e.jsx("span",{className:"rounded-md border border-zinc-800 px-2 py-1",children:"Or upload a key file"})]})]}),z?e.jsx("p",{className:"rounded-md border border-rose-800/50 bg-rose-950/30 px-3 py-2 text-xs text-rose-200",children:z}):null,v?e.jsx("p",{className:"rounded-md border border-emerald-800/50 bg-emerald-950/30 px-3 py-2 text-xs text-emerald-200",children:v}):null,e.jsxs("div",{className:"mt-2 flex items-center justify-end gap-2 border-t border-zinc-800/60 pt-4",children:[e.jsx(N,{type:"button",variant:"ghost",size:"sm",onClick:o,children:"Close"}),e.jsx(N,{type:"submit",disabled:d.isPending,size:"sm",children:d.isPending?"Connecting…":"Connect"})]})]})]})}function de({projectName:t,onBack:i,onClose:o}){const[r,s]=a.useState(""),[n,l]=a.useState(""),[m,j]=a.useState(""),[p,w]=a.useState("production"),[y,f]=a.useState(""),[z,h]=a.useState(null),[v,C]=a.useState(null),d=Q(t||null),g=async x=>{if(x.preventDefault(),h(null),C(null),!r.trim()){h("Vercel project ID is required.");return}if(!n.trim()){h("Vercel team ID is required.");return}if(!m.trim()){h("Vercel API token is required.");return}try{const c=await d.mutateAsync({projectId:r.trim(),teamId:n.trim(),token:m.trim(),environment:p,displayName:y.trim()||void 0});j(""),C(`Connected ${c.displayName}.`)}catch(c){const b=c instanceof T||c instanceof Error?c.message:String(c);h(b)}};return e.jsxs(e.Fragment,{children:[e.jsx(q,{title:"Connect a Vercel project",description:e.jsxs(e.Fragment,{children:["Pulls request logs straight from Vercel — no in-app instrumentation needed. The API token is stored in ",e.jsx("code",{children:"~/.canonry/config.yaml"})," on the server and never echoed back to the dashboard."]}),onBack:i}),e.jsxs("form",{onSubmit:k(g),className:"mt-6 flex flex-col gap-5 overflow-y-auto pr-1",children:[e.jsx(u,{label:"Project",description:"Canonry project this source attaches to.",children:e.jsx("input",{type:"text",value:t,disabled:!0,className:"w-full rounded border border-zinc-700 bg-zinc-900/50 px-2 py-1.5 text-sm text-zinc-300"})}),e.jsx(u,{label:"Vercel project ID",description:"The prj_… id from the Vercel dashboard or .vercel/project.json.",required:!0,children:e.jsx("input",{type:"text",value:r,onChange:x=>s(x.target.value),required:!0,autoComplete:"off",placeholder:"prj_…",className:"w-full rounded border border-zinc-700 bg-transparent px-2 py-1.5 text-sm text-zinc-200 placeholder-zinc-600 focus:border-zinc-500 focus:outline-none"})}),e.jsx(u,{label:"Vercel team ID",description:"The team_… (or owner) id the project belongs to.",required:!0,children:e.jsx("input",{type:"text",value:n,onChange:x=>l(x.target.value),required:!0,autoComplete:"off",placeholder:"team_…",className:"w-full rounded border border-zinc-700 bg-transparent px-2 py-1.5 text-sm text-zinc-200 placeholder-zinc-600 focus:border-zinc-500 focus:outline-none"})}),e.jsx(u,{label:"API token",description:"Create one in Vercel under Account Settings → Tokens. Tokens can expire — use a long-lived token.",required:!0,children:e.jsx("input",{type:"password",value:m,onChange:x=>j(x.target.value),required:!0,autoComplete:"new-password",className:"w-full rounded border border-zinc-700 bg-transparent px-2 py-1.5 text-sm text-zinc-200 placeholder-zinc-600 focus:border-zinc-500 focus:outline-none"})}),e.jsx(u,{label:"Environment",description:"Which deployment environment's request logs to pull.",children:e.jsxs("select",{value:p,onChange:x=>w(x.target.value),className:"w-full rounded border border-zinc-700 bg-transparent px-2 py-1.5 text-sm text-zinc-200 focus:border-zinc-500 focus:outline-none",children:[e.jsx("option",{value:"production",children:"production"}),e.jsx("option",{value:"preview",children:"preview"})]})}),e.jsx(u,{label:"Display name (optional)",description:"Friendly label shown in the dashboard. Defaults to the Vercel project ID.",children:e.jsx("input",{type:"text",value:y,onChange:x=>f(x.target.value),autoComplete:"off",className:"w-full rounded border border-zinc-700 bg-transparent px-2 py-1.5 text-sm text-zinc-200 placeholder-zinc-600 focus:border-zinc-500 focus:outline-none"})}),z?e.jsx("p",{className:"rounded-md border border-rose-800/50 bg-rose-950/30 px-3 py-2 text-xs text-rose-200",children:z}):null,v?e.jsx("p",{className:"rounded-md border border-emerald-800/50 bg-emerald-950/30 px-3 py-2 text-xs text-emerald-200",children:v}):null,e.jsxs("div",{className:"mt-2 flex items-center justify-end gap-2 border-t border-zinc-800/60 pt-4",children:[e.jsx(N,{type:"button",variant:"ghost",size:"sm",onClick:o,children:"Close"}),e.jsx(N,{type:"submit",disabled:d.isPending,size:"sm",children:d.isPending?"Connecting…":"Connect"})]})]})]})}function u({label:t,description:i,required:o,children:r}){return e.jsxs("label",{className:"flex flex-col gap-1",children:[e.jsxs("span",{className:"text-xs font-medium text-zinc-200",children:[t,o?e.jsx("span",{className:"ml-1 text-rose-400",children:"*"}):null]}),r,e.jsx("span",{className:"text-[11px] text-zinc-500",children:i})]})}function ue(t){if(!t)return"never";const i=Date.now()-new Date(t).getTime(),o=Math.floor(i/6e4);if(o<1)return"just now";if(o<60)return`${o}m ago`;const r=Math.floor(o/60);return r<24?`${r}h ago`:`${Math.floor(r/24)}d ago`}function P(t){return t>=1e6?`${(t/1e6).toFixed(1)}M`:t>=1e3?`${(t/1e3).toFixed(1)}K`:t.toLocaleString()}function ye(){const[t,i]=a.useState(""),[o,r]=a.useState(!1),n=L(W({client:R})).data??[],l=a.useMemo(()=>t||(n[0]?.name??""),[t,n]),m=Z(l||null),j=m.data?.sources??[];return e.jsxs("div",{className:"page-container",children:[e.jsxs("div",{className:"page-header",children:[e.jsxs("div",{className:"page-header-left",children:[e.jsx("h1",{className:"page-title",children:"Server traffic"}),e.jsx("p",{className:"page-subtitle",children:"Crawler hits and AI-referral sessions pulled directly from your server logs. Independent of GA — useful when you need server-side evidence that GPTBot or ChatGPT-User actually hit a page."})]}),e.jsx("div",{className:"flex flex-wrap items-center justify-end gap-2",children:e.jsxs(N,{type:"button",variant:"outline",size:"sm",onClick:()=>r(!0),disabled:!l,children:[e.jsx(I,{className:"size-3.5"}),"Connect a source"]})})]}),e.jsxs("section",{children:[e.jsx("div",{className:"filter-row",role:"toolbar","aria-label":"Project picker",children:n.map(p=>e.jsx("button",{type:"button",className:`filter-chip ${l===p.name?"filter-chip-active":""}`,"aria-pressed":l===p.name,onClick:()=>i(p.name),children:p.displayName??p.name},p.id))}),l?m.isLoading?e.jsx(S,{className:"p-6 text-center text-sm text-zinc-500",children:"Loading sources…"}):j.length===0?e.jsxs(S,{className:"p-8 text-center",children:[e.jsxs("p",{className:"text-sm text-zinc-300",children:["No traffic sources connected for ",l,"."]}),e.jsx("p",{className:"mt-1 text-xs text-zinc-500",children:"Connect a traffic source to start ingesting crawler hits and AI-referral sessions from your server logs."}),e.jsx("div",{className:"mt-4 flex flex-wrap items-center justify-center gap-2",children:e.jsxs(N,{type:"button",variant:"outline",size:"sm",onClick:()=>r(!0),children:[e.jsx(I,{className:"size-3.5"}),"Connect a source"]})})]}):e.jsx(pe,{projectName:l,sources:j}):e.jsx(S,{className:"p-6 text-center text-sm text-zinc-500",children:"No projects yet."})]}),e.jsx(oe,{open:o,onOpenChange:r,projectName:l})]})}function pe({projectName:t,sources:i}){const o=O({queries:i.map(s=>({...G({client:R,path:{name:t,id:s.id}}),staleTime:3e4}))}),r=i.map((s,n)=>({source:s,detail:o[n]?.data,isLoading:o[n]?.isLoading??!1}));return e.jsxs("div",{className:"rounded-xl border border-zinc-800/60 bg-zinc-900/30 overflow-hidden",children:[e.jsxs("table",{className:"w-full text-sm",children:[e.jsx("thead",{className:"bg-zinc-900/50 text-[10px] font-semibold uppercase tracking-wider text-zinc-500",children:e.jsxs("tr",{children:[e.jsx("th",{className:"px-4 py-2 text-left",children:"Source"}),e.jsx("th",{className:"px-4 py-2 text-left",children:"Status"}),e.jsx("th",{className:"px-4 py-2 text-left",children:"Last sync"}),e.jsx("th",{className:"px-4 py-2 text-right",children:"24h crawler"}),e.jsx("th",{className:"px-4 py-2 text-right",children:"24h AI sessions"}),e.jsx("th",{className:"px-4 py-2 text-right",children:"24h samples"}),e.jsx("th",{className:"px-4 py-2 text-right"})]})}),e.jsx("tbody",{className:"divide-y divide-zinc-800/60",children:r.map(({source:s,detail:n,isLoading:l})=>e.jsxs("tr",{className:"hover:bg-zinc-900/40 transition-colors",children:[e.jsxs("td",{className:"px-4 py-3",children:[e.jsx("div",{className:"font-medium text-zinc-100",children:s.displayName}),e.jsxs("div",{className:"text-[11px] text-zinc-500 font-mono",children:[s.sourceType," · ",s.id.slice(0,8)]})]}),e.jsxs("td",{className:"px-4 py-3",children:[e.jsx(H,{tone:Y(s.status),children:s.status}),s.lastError?e.jsx("p",{className:"mt-1 max-w-[18rem] truncate text-[11px] text-rose-400/80",title:s.lastError,children:s.lastError}):null]}),e.jsx("td",{className:"px-4 py-3 text-zinc-300",children:ue(s.lastSyncedAt)}),e.jsx("td",{className:"px-4 py-3 text-right tabular-nums text-zinc-100",children:l?"—":P(n?.totals24h.crawlerHits??0)}),e.jsx("td",{className:"px-4 py-3 text-right tabular-nums text-zinc-100",children:l?"—":P(n?.totals24h.aiReferralHits??0)}),e.jsx("td",{className:"px-4 py-3 text-right tabular-nums text-zinc-300",children:l?"—":P(n?.totals24h.sampleCount??0)}),e.jsx("td",{className:"px-4 py-3 text-right",children:e.jsxs(U,{to:"/traffic/$projectName/$sourceId",params:{projectName:t,sourceId:s.id},className:"inline-flex items-center gap-1 text-xs text-zinc-300 hover:text-zinc-100",children:[e.jsx(X,{className:"size-3"}),"View"]})})]},s.id))})]}),e.jsxs("p",{className:"border-t border-zinc-800/60 px-4 py-2 text-[11px] text-zinc-600",children:["Showing ",i.filter(s=>s.status!==J.archived).length," active source",i.length===1?"":"s"," for ",t,". Same shape as ",e.jsxs("code",{className:"text-zinc-400",children:["canonry traffic status ",t," --format json"]}),"."]})]})}export{ye as TrafficPage};
1
+ import{r as a,j as e,u as L,f as B,L as O}from"./vendor-tanstack-Dq7p98wZ.js";import{c as q,bz as U,bA as _,bB as D,bC as F,bD as E,bE as $,B as N,i as k,a0 as T,aT as G,l as R,bF as I,g as S,bG as W,T as H,bH as J}from"./index-VMFHNbas.js";import{a as M,b as Q,c as K,d as Z,t as Y,R as X}from"./server-traffic-Bym-drXr.js";import{A as ee}from"./arrow-left-VZ7oOCHS.js";import"./vendor-radix-B57xfQbP.js";import"./vendor-recharts-DWvKDyBF.js";import"./vendor-markdown-DK7fbRNb.js";const te=[["path",{d:"M17.5 19H9a7 7 0 1 1 6.71-9h1.79a4.5 4.5 0 1 1 0 9Z",key:"p7xjir"}]],se=q("cloud",te);const re=[["path",{d:"M13.73 4a2 2 0 0 0-3.46 0l-8 14A2 2 0 0 0 4 21h16a2 2 0 0 0 1.73-3Z",key:"14u9p9"}]],ne=q("triangle",re);function oe({open:t,onOpenChange:i,projectName:o}){const[r,s]=a.useState("pick");a.useEffect(()=>{t&&s("pick")},[t]);const n=()=>{i(!1),s("pick")};return e.jsx(U,{open:t,onOpenChange:l=>{l?i(!0):n()},children:e.jsx(_,{children:r==="pick"?e.jsx(ie,{onPick:s}):r==="wordpress"?e.jsx(ce,{projectName:o,onBack:()=>s("pick"),onClose:n}):r==="vercel"?e.jsx(de,{projectName:o,onBack:()=>s("pick"),onClose:n}):e.jsx(le,{projectName:o,onBack:()=>s("pick"),onClose:n})})})}const ae=[{type:"wordpress",name:"WordPress site",tagline:"Easiest if you run WordPress",description:"Install the Canonry Traffic Logger plugin and connect with an Application Password. No cloud account needed.",icon:$},{type:"cloud-run",name:"Google Cloud Run",tagline:"For apps hosted on Cloud Run",description:"Connect a Google Cloud service account so Canonry can read your Cloud Run request logs.",icon:se},{type:"vercel",name:"Vercel project",tagline:"For sites hosted on Vercel",description:"Connect a Vercel API token so Canonry can pull request logs straight from Vercel — no in-app instrumentation needed.",icon:ne}];function ie({onPick:t}){return e.jsxs(e.Fragment,{children:[e.jsxs(D,{children:[e.jsx(F,{children:"Connect a traffic source"}),e.jsx(E,{children:"Canonry reads your server logs to see when AI crawlers and AI-referred visitors hit your site. Pick where your site is hosted to get started."})]}),e.jsx("div",{className:"mt-6 flex flex-col gap-3",children:ae.map(({type:i,name:o,tagline:r,description:s,icon:n})=>e.jsxs("button",{type:"button",onClick:()=>t(i),className:"group flex items-start gap-4 rounded-lg border border-zinc-800 bg-zinc-900/30 p-4 text-left transition-colors hover:border-zinc-600 hover:bg-zinc-900/60 focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-zinc-400",children:[e.jsx("span",{className:"mt-0.5 inline-flex size-9 shrink-0 items-center justify-center rounded-md border border-zinc-800 bg-zinc-950 text-zinc-300 group-hover:text-zinc-100",children:e.jsx(n,{className:"size-4"})}),e.jsxs("span",{className:"flex flex-col gap-0.5",children:[e.jsxs("span",{className:"flex flex-wrap items-baseline gap-x-2",children:[e.jsx("span",{className:"text-sm font-medium text-zinc-100",children:o}),e.jsx("span",{className:"text-[11px] text-zinc-500",children:r})]}),e.jsx("span",{className:"text-xs leading-5 text-zinc-500",children:s})]})]},i))})]})}function A({title:t,description:i,onBack:o}){return e.jsxs(D,{children:[e.jsxs("button",{type:"button",onClick:o,className:"mb-1 inline-flex w-fit items-center gap-1 rounded text-xs text-zinc-500 transition-colors hover:text-zinc-200 focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-zinc-400",children:[e.jsx(ee,{className:"size-3"}),"Choose a different source"]}),e.jsx(F,{children:t}),e.jsx(E,{children:i})]})}function ce({projectName:t,onBack:i,onClose:o}){const[r,s]=a.useState(""),[n,l]=a.useState(""),[m,j]=a.useState(""),[p,w]=a.useState(""),[y,f]=a.useState(null),[z,h]=a.useState(null),v=M(t||null),C=async d=>{if(d.preventDefault(),f(null),h(null),!r.trim()){f("WordPress site URL is required.");return}if(!n.trim()){f("Username is required.");return}if(!m.trim()){f("Application Password is required.");return}try{const g=await v.mutateAsync({baseUrl:r.trim(),username:n.trim(),applicationPassword:m.trim(),displayName:p.trim()||void 0});j(""),h(`Connected ${g.displayName}.`)}catch(g){const x=g instanceof T||g instanceof Error?g.message:String(g);f(x)}};return e.jsxs(e.Fragment,{children:[e.jsx(A,{title:"Connect a WordPress site",description:e.jsxs(e.Fragment,{children:["Pulls request events from the Canonry Traffic Logger plugin. The Application Password is stored in ",e.jsx("code",{children:"~/.canonry/config.yaml"})," on the server and never echoed back to the dashboard."]}),onBack:i}),e.jsxs("form",{onSubmit:k(C),className:"mt-6 flex flex-col gap-5 overflow-y-auto pr-1",children:[e.jsx(u,{label:"Project",description:"Canonry project this source attaches to.",children:e.jsx("input",{type:"text",value:t,disabled:!0,className:"w-full rounded border border-zinc-700 bg-zinc-900/50 px-2 py-1.5 text-sm text-zinc-300"})}),e.jsx(u,{label:"WordPress site URL",description:"Base URL of the site running the Canonry Traffic Logger plugin.",required:!0,children:e.jsx("input",{type:"url",value:r,onChange:d=>s(d.target.value),required:!0,autoComplete:"url",placeholder:"https://example.com",className:"w-full rounded border border-zinc-700 bg-transparent px-2 py-1.5 text-sm text-zinc-200 placeholder-zinc-600 focus:border-zinc-500 focus:outline-none"})}),e.jsx(u,{label:"Username",description:"WordPress user that owns the Application Password.",required:!0,children:e.jsx("input",{type:"text",value:n,onChange:d=>l(d.target.value),required:!0,autoComplete:"username",className:"w-full rounded border border-zinc-700 bg-transparent px-2 py-1.5 text-sm text-zinc-200 placeholder-zinc-600 focus:border-zinc-500 focus:outline-none"})}),e.jsx(u,{label:"Application Password",description:"Create one in wp-admin under Users -> Profile -> Application Passwords.",required:!0,children:e.jsx("input",{type:"password",value:m,onChange:d=>j(d.target.value),required:!0,autoComplete:"new-password",className:"w-full rounded border border-zinc-700 bg-transparent px-2 py-1.5 text-sm text-zinc-200 placeholder-zinc-600 focus:border-zinc-500 focus:outline-none"})}),e.jsx(u,{label:"Display name (optional)",description:"Friendly label shown in the dashboard. Defaults to the WordPress host.",children:e.jsx("input",{type:"text",value:p,onChange:d=>w(d.target.value),autoComplete:"off",className:"w-full rounded border border-zinc-700 bg-transparent px-2 py-1.5 text-sm text-zinc-200 placeholder-zinc-600 focus:border-zinc-500 focus:outline-none"})}),y?e.jsx("p",{className:"rounded-md border border-rose-800/50 bg-rose-950/30 px-3 py-2 text-xs text-rose-200",children:y}):null,z?e.jsx("p",{className:"rounded-md border border-emerald-800/50 bg-emerald-950/30 px-3 py-2 text-xs text-emerald-200",children:z}):null,e.jsxs("div",{className:"mt-2 flex items-center justify-end gap-2 border-t border-zinc-800/60 pt-4",children:[e.jsx(N,{type:"button",variant:"ghost",size:"sm",onClick:o,children:"Close"}),e.jsx(N,{type:"submit",disabled:v.isPending,size:"sm",children:v.isPending?"Connecting...":"Connect"})]})]})]})}function le({projectName:t,onBack:i,onClose:o}){const[r,s]=a.useState(""),[n,l]=a.useState(""),[m,j]=a.useState(""),[p,w]=a.useState(""),[y,f]=a.useState(""),[z,h]=a.useState(null),[v,C]=a.useState(null),d=K(t||null),g=async c=>{if(c.preventDefault(),h(null),C(null),!r.trim()){h("GCP project ID is required.");return}if(!y.trim()){h("Service-account JSON content is required.");return}try{const b=await d.mutateAsync({gcpProjectId:r.trim(),serviceName:n.trim()||void 0,location:m.trim()||void 0,displayName:p.trim()||void 0,keyJson:y.trim()});f(""),C(`Connected ${b.displayName}.`)}catch(b){const V=b instanceof T||b instanceof Error?b.message:String(b);h(V)}},x=async c=>{if(!c)return;const b=await c.text();f(b)};return e.jsxs(e.Fragment,{children:[e.jsx(A,{title:"Connect a Cloud Run service",description:e.jsxs(e.Fragment,{children:["v1 supports service-account JSON only. The private key is stored in"," ",e.jsx("code",{children:"~/.canonry/config.yaml"})," on the server and never echoed back to the dashboard."]}),onBack:i}),e.jsxs("form",{onSubmit:k(g),className:"mt-6 flex flex-col gap-5 overflow-y-auto pr-1",children:[e.jsx(u,{label:"Project",description:"Canonry project this source attaches to.",children:e.jsx("input",{type:"text",value:t,disabled:!0,className:"w-full rounded border border-zinc-700 bg-zinc-900/50 px-2 py-1.5 text-sm text-zinc-300"})}),e.jsx(u,{label:"GCP project ID",description:"The Google Cloud project hosting the Cloud Run service (e.g. my-prod-foo).",required:!0,children:e.jsx("input",{type:"text",value:r,onChange:c=>s(c.target.value),required:!0,autoComplete:"off",className:"w-full rounded border border-zinc-700 bg-transparent px-2 py-1.5 text-sm text-zinc-200 placeholder-zinc-600 focus:border-zinc-500 focus:outline-none"})}),e.jsx(u,{label:"Service name (optional)",description:"Restrict log pulls to a specific Cloud Run service. Omit to pull all services in the project.",children:e.jsx("input",{type:"text",value:n,onChange:c=>l(c.target.value),autoComplete:"off",className:"w-full rounded border border-zinc-700 bg-transparent px-2 py-1.5 text-sm text-zinc-200 placeholder-zinc-600 focus:border-zinc-500 focus:outline-none"})}),e.jsx(u,{label:"Location (optional)",description:"Region of the Cloud Run service (e.g. us-central1). Helpful when multiple regions emit logs.",children:e.jsx("input",{type:"text",value:m,onChange:c=>j(c.target.value),autoComplete:"off",className:"w-full rounded border border-zinc-700 bg-transparent px-2 py-1.5 text-sm text-zinc-200 placeholder-zinc-600 focus:border-zinc-500 focus:outline-none"})}),e.jsx(u,{label:"Display name (optional)",description:"Friendly label shown in the dashboard. Defaults to the project + service combo.",children:e.jsx("input",{type:"text",value:p,onChange:c=>w(c.target.value),autoComplete:"off",className:"w-full rounded border border-zinc-700 bg-transparent px-2 py-1.5 text-sm text-zinc-200 placeholder-zinc-600 focus:border-zinc-500 focus:outline-none"})}),e.jsxs(u,{label:"Service-account JSON",description:"Paste the contents of the SA key (JSON). The SA needs roles/logging.viewer (or any role granting logging.logEntries.list).",required:!0,children:[e.jsx("textarea",{value:y,onChange:c=>f(c.target.value),rows:6,spellCheck:!1,autoComplete:"off",className:"w-full rounded border border-zinc-700 bg-transparent px-2 py-1.5 font-mono text-[11px] text-zinc-200 placeholder-zinc-600 focus:border-zinc-500 focus:outline-none",placeholder:'{"type":"service_account","project_id":"…","private_key":"…"}',required:!0}),e.jsxs("label",{className:"mt-2 inline-flex cursor-pointer items-center gap-2 text-xs text-zinc-400 hover:text-zinc-200",children:[e.jsx("input",{type:"file",accept:"application/json,.json",className:"hidden",onChange:c=>{x(c.target.files?.[0]??null)}}),e.jsx("span",{className:"rounded-md border border-zinc-800 px-2 py-1",children:"Or upload a key file"})]})]}),z?e.jsx("p",{className:"rounded-md border border-rose-800/50 bg-rose-950/30 px-3 py-2 text-xs text-rose-200",children:z}):null,v?e.jsx("p",{className:"rounded-md border border-emerald-800/50 bg-emerald-950/30 px-3 py-2 text-xs text-emerald-200",children:v}):null,e.jsxs("div",{className:"mt-2 flex items-center justify-end gap-2 border-t border-zinc-800/60 pt-4",children:[e.jsx(N,{type:"button",variant:"ghost",size:"sm",onClick:o,children:"Close"}),e.jsx(N,{type:"submit",disabled:d.isPending,size:"sm",children:d.isPending?"Connecting…":"Connect"})]})]})]})}function de({projectName:t,onBack:i,onClose:o}){const[r,s]=a.useState(""),[n,l]=a.useState(""),[m,j]=a.useState(""),[p,w]=a.useState("production"),[y,f]=a.useState(""),[z,h]=a.useState(null),[v,C]=a.useState(null),d=Q(t||null),g=async x=>{if(x.preventDefault(),h(null),C(null),!r.trim()){h("Vercel project ID is required.");return}if(!n.trim()){h("Vercel team ID is required.");return}if(!m.trim()){h("Vercel API token is required.");return}try{const c=await d.mutateAsync({projectId:r.trim(),teamId:n.trim(),token:m.trim(),environment:p,displayName:y.trim()||void 0});j(""),C(`Connected ${c.displayName}.`)}catch(c){const b=c instanceof T||c instanceof Error?c.message:String(c);h(b)}};return e.jsxs(e.Fragment,{children:[e.jsx(A,{title:"Connect a Vercel project",description:e.jsxs(e.Fragment,{children:["Pulls request logs straight from Vercel — no in-app instrumentation needed. The API token is stored in ",e.jsx("code",{children:"~/.canonry/config.yaml"})," on the server and never echoed back to the dashboard."]}),onBack:i}),e.jsxs("form",{onSubmit:k(g),className:"mt-6 flex flex-col gap-5 overflow-y-auto pr-1",children:[e.jsx(u,{label:"Project",description:"Canonry project this source attaches to.",children:e.jsx("input",{type:"text",value:t,disabled:!0,className:"w-full rounded border border-zinc-700 bg-zinc-900/50 px-2 py-1.5 text-sm text-zinc-300"})}),e.jsx(u,{label:"Vercel project ID",description:"The prj_… id from the Vercel dashboard or .vercel/project.json.",required:!0,children:e.jsx("input",{type:"text",value:r,onChange:x=>s(x.target.value),required:!0,autoComplete:"off",placeholder:"prj_…",className:"w-full rounded border border-zinc-700 bg-transparent px-2 py-1.5 text-sm text-zinc-200 placeholder-zinc-600 focus:border-zinc-500 focus:outline-none"})}),e.jsx(u,{label:"Vercel team ID",description:"The team_… (or owner) id the project belongs to.",required:!0,children:e.jsx("input",{type:"text",value:n,onChange:x=>l(x.target.value),required:!0,autoComplete:"off",placeholder:"team_…",className:"w-full rounded border border-zinc-700 bg-transparent px-2 py-1.5 text-sm text-zinc-200 placeholder-zinc-600 focus:border-zinc-500 focus:outline-none"})}),e.jsx(u,{label:"API token",description:"Create one in Vercel under Account Settings → Tokens. Tokens can expire — use a long-lived token.",required:!0,children:e.jsx("input",{type:"password",value:m,onChange:x=>j(x.target.value),required:!0,autoComplete:"new-password",className:"w-full rounded border border-zinc-700 bg-transparent px-2 py-1.5 text-sm text-zinc-200 placeholder-zinc-600 focus:border-zinc-500 focus:outline-none"})}),e.jsx(u,{label:"Environment",description:"Which deployment environment's request logs to pull.",children:e.jsxs("select",{value:p,onChange:x=>w(x.target.value),className:"w-full rounded border border-zinc-700 bg-transparent px-2 py-1.5 text-sm text-zinc-200 focus:border-zinc-500 focus:outline-none",children:[e.jsx("option",{value:"production",children:"production"}),e.jsx("option",{value:"preview",children:"preview"})]})}),e.jsx(u,{label:"Display name (optional)",description:"Friendly label shown in the dashboard. Defaults to the Vercel project ID.",children:e.jsx("input",{type:"text",value:y,onChange:x=>f(x.target.value),autoComplete:"off",className:"w-full rounded border border-zinc-700 bg-transparent px-2 py-1.5 text-sm text-zinc-200 placeholder-zinc-600 focus:border-zinc-500 focus:outline-none"})}),z?e.jsx("p",{className:"rounded-md border border-rose-800/50 bg-rose-950/30 px-3 py-2 text-xs text-rose-200",children:z}):null,v?e.jsx("p",{className:"rounded-md border border-emerald-800/50 bg-emerald-950/30 px-3 py-2 text-xs text-emerald-200",children:v}):null,e.jsxs("div",{className:"mt-2 flex items-center justify-end gap-2 border-t border-zinc-800/60 pt-4",children:[e.jsx(N,{type:"button",variant:"ghost",size:"sm",onClick:o,children:"Close"}),e.jsx(N,{type:"submit",disabled:d.isPending,size:"sm",children:d.isPending?"Connecting…":"Connect"})]})]})]})}function u({label:t,description:i,required:o,children:r}){return e.jsxs("label",{className:"flex flex-col gap-1",children:[e.jsxs("span",{className:"text-xs font-medium text-zinc-200",children:[t,o?e.jsx("span",{className:"ml-1 text-rose-400",children:"*"}):null]}),r,e.jsx("span",{className:"text-[11px] text-zinc-500",children:i})]})}function ue(t){if(!t)return"never";const i=Date.now()-new Date(t).getTime(),o=Math.floor(i/6e4);if(o<1)return"just now";if(o<60)return`${o}m ago`;const r=Math.floor(o/60);return r<24?`${r}h ago`:`${Math.floor(r/24)}d ago`}function P(t){return t>=1e6?`${(t/1e6).toFixed(1)}M`:t>=1e3?`${(t/1e3).toFixed(1)}K`:t.toLocaleString()}function ye(){const[t,i]=a.useState(""),[o,r]=a.useState(!1),n=L(G({client:R})).data??[],l=a.useMemo(()=>t||(n[0]?.name??""),[t,n]),m=Z(l||null),j=m.data?.sources??[];return e.jsxs("div",{className:"page-container",children:[e.jsxs("div",{className:"page-header",children:[e.jsxs("div",{className:"page-header-left",children:[e.jsx("h1",{className:"page-title",children:"Server traffic"}),e.jsx("p",{className:"page-subtitle",children:"Crawler hits and AI-referral sessions pulled directly from your server logs. Independent of GA — useful when you need server-side evidence that GPTBot or ChatGPT-User actually hit a page."})]}),e.jsx("div",{className:"flex flex-wrap items-center justify-end gap-2",children:e.jsxs(N,{type:"button",variant:"outline",size:"sm",onClick:()=>r(!0),disabled:!l,children:[e.jsx(I,{className:"size-3.5"}),"Connect a source"]})})]}),e.jsxs("section",{children:[e.jsx("div",{className:"filter-row",role:"toolbar","aria-label":"Project picker",children:n.map(p=>e.jsx("button",{type:"button",className:`filter-chip ${l===p.name?"filter-chip-active":""}`,"aria-pressed":l===p.name,onClick:()=>i(p.name),children:p.displayName??p.name},p.id))}),l?m.isLoading?e.jsx(S,{className:"p-6 text-center text-sm text-zinc-500",children:"Loading sources…"}):j.length===0?e.jsxs(S,{className:"p-8 text-center",children:[e.jsxs("p",{className:"text-sm text-zinc-300",children:["No traffic sources connected for ",l,"."]}),e.jsx("p",{className:"mt-1 text-xs text-zinc-500",children:"Connect a traffic source to start ingesting crawler hits and AI-referral sessions from your server logs."}),e.jsx("div",{className:"mt-4 flex flex-wrap items-center justify-center gap-2",children:e.jsxs(N,{type:"button",variant:"outline",size:"sm",onClick:()=>r(!0),children:[e.jsx(I,{className:"size-3.5"}),"Connect a source"]})})]}):e.jsx(pe,{projectName:l,sources:j}):e.jsx(S,{className:"p-6 text-center text-sm text-zinc-500",children:"No projects yet."})]}),e.jsx(oe,{open:o,onOpenChange:r,projectName:l})]})}function pe({projectName:t,sources:i}){const o=B({queries:i.map(s=>({...W({client:R,path:{name:t,id:s.id}}),staleTime:3e4}))}),r=i.map((s,n)=>({source:s,detail:o[n]?.data,isLoading:o[n]?.isLoading??!1}));return e.jsxs("div",{className:"rounded-xl border border-zinc-800/60 bg-zinc-900/30 overflow-hidden",children:[e.jsxs("table",{className:"w-full text-sm",children:[e.jsx("thead",{className:"bg-zinc-900/50 text-[10px] font-semibold uppercase tracking-wider text-zinc-500",children:e.jsxs("tr",{children:[e.jsx("th",{className:"px-4 py-2 text-left",children:"Source"}),e.jsx("th",{className:"px-4 py-2 text-left",children:"Status"}),e.jsx("th",{className:"px-4 py-2 text-left",children:"Last sync"}),e.jsx("th",{className:"px-4 py-2 text-right",children:"24h crawler"}),e.jsx("th",{className:"px-4 py-2 text-right",children:"24h AI sessions"}),e.jsx("th",{className:"px-4 py-2 text-right",children:"24h samples"}),e.jsx("th",{className:"px-4 py-2 text-right"})]})}),e.jsx("tbody",{className:"divide-y divide-zinc-800/60",children:r.map(({source:s,detail:n,isLoading:l})=>e.jsxs("tr",{className:"hover:bg-zinc-900/40 transition-colors",children:[e.jsxs("td",{className:"px-4 py-3",children:[e.jsx("div",{className:"font-medium text-zinc-100",children:s.displayName}),e.jsxs("div",{className:"text-[11px] text-zinc-500 font-mono",children:[s.sourceType," · ",s.id.slice(0,8)]})]}),e.jsxs("td",{className:"px-4 py-3",children:[e.jsx(H,{tone:Y(s.status),children:s.status}),s.lastError?e.jsx("p",{className:"mt-1 max-w-[18rem] truncate text-[11px] text-rose-400/80",title:s.lastError,children:s.lastError}):null]}),e.jsx("td",{className:"px-4 py-3 text-zinc-300",children:ue(s.lastSyncedAt)}),e.jsx("td",{className:"px-4 py-3 text-right tabular-nums text-zinc-100",children:l?"—":P(n?.totals24h.crawlerHits??0)}),e.jsx("td",{className:"px-4 py-3 text-right tabular-nums text-zinc-100",children:l?"—":P(n?.totals24h.aiReferralHits??0)}),e.jsx("td",{className:"px-4 py-3 text-right tabular-nums text-zinc-300",children:l?"—":P(n?.totals24h.sampleCount??0)}),e.jsx("td",{className:"px-4 py-3 text-right",children:e.jsxs(O,{to:"/traffic/$projectName/$sourceId",params:{projectName:t,sourceId:s.id},className:"inline-flex items-center gap-1 text-xs text-zinc-300 hover:text-zinc-100",children:[e.jsx(X,{className:"size-3"}),"View"]})})]},s.id))})]}),e.jsxs("p",{className:"border-t border-zinc-800/60 px-4 py-2 text-[11px] text-zinc-600",children:["Showing ",i.filter(s=>s.status!==J.archived).length," active source",i.length===1?"":"s"," for ",t,". Same shape as ",e.jsxs("code",{className:"text-zinc-400",children:["canonry traffic status ",t," --format json"]}),"."]})]})}export{ye as TrafficPage};
@@ -0,0 +1 @@
1
+ import{j as e,A as xe,B as me,r as m,L as he}from"./vendor-tanstack-Dq7p98wZ.js";import{I as pe,bI as v,T as fe,B as ge,g as A,a0 as be,bJ as je}from"./index-VMFHNbas.js";import{d as se,e as ye,C as G,a as Y,c as Ne}from"./ChartPrimitives-9Kx3gzQL.js";import{e as ve,f as we,g as Se,t as ze,R as ke}from"./server-traffic-Bym-drXr.js";import{R as Ce,B as Te,a as Re,X as $e,Y as Ae,T as Ie,b as X,d as Q}from"./vendor-recharts-DWvKDyBF.js";import{A as q}from"./arrow-left-VZ7oOCHS.js";import"./vendor-radix-B57xfQbP.js";import"./vendor-markdown-DK7fbRNb.js";function F({value:a,label:t,delta:n,tone:r,description:d,tooltip:i,isNumeric:o=!0,progress:c,providerCoverage:u}){const j=2*Math.PI*48,x=Number.parseInt(a,10),z=typeof c=="number"&&Number.isFinite(c)?Math.min(Math.max(c,0),100)/100:o&&!Number.isNaN(x)?Math.min(x/100,1):.5,y=j*(1-z);return e.jsxs("div",{className:"score-gauge",children:[e.jsxs("div",{className:"gauge-ring-wrapper",children:[e.jsxs("svg",{className:"gauge-ring",viewBox:"0 0 120 120","aria-hidden":"true",children:[e.jsx("circle",{className:"gauge-bg",cx:"60",cy:"60",r:48,strokeWidth:6}),e.jsx("circle",{className:`gauge-fill gauge-fill-${r}`,cx:"60",cy:"60",r:48,strokeWidth:6,strokeDasharray:j,strokeDashoffset:y,transform:"rotate(-90 60 60)"})]}),e.jsx("div",{className:"gauge-center",children:e.jsx("span",{className:o?"gauge-value":"gauge-value-text",children:a.split(" / ")[0]})})]}),e.jsxs("p",{className:"gauge-label",children:[t,i&&e.jsx(pe,{text:i})]}),e.jsx("p",{className:"gauge-delta",children:n}),u&&e.jsx("p",{className:"gauge-provider-coverage",children:u}),e.jsx("p",{className:"gauge-description",children:d})]})}const Le=[{value:"all",label:"All status"},{value:"2xx",label:"2xx success"},{value:"3xx",label:"3xx redirect"},{value:"4xx",label:"4xx client error"},{value:"5xx",label:"5xx server error"}];function De(a){return a==="all"?null:Number.parseInt(a[0],10)}function ae(a){return a.kind===v.crawler?a.botId:a.product}function Me(a){return a.kind===v.crawler?a.pathNormalized:a.landingPathNormalized}function re(a,t){if(t==="hour")return a;const n=new Date(a),r=n.getFullYear(),d=String(n.getMonth()+1).padStart(2,"0"),i=String(n.getDate()).padStart(2,"0");return`${r}-${d}-${i}`}function Ee(a,t,n){const r=t.pathQuery.trim().toLowerCase(),d=De(t.statusClass);return a.filter(i=>!(t.selectedBucket&&re(i.tsHour,n)!==t.selectedBucket||t.identity&&ae(i)!==t.identity||t.operator&&i.operator!==t.operator||r&&!Me(i).toLowerCase().includes(r)||d!==null&&Math.floor(i.status/100)!==d))}function He(a,t){if(!a||typeof a!="object")return null;const n=a.activeTooltipIndex;let r;if(typeof n=="number")r=n;else if(typeof n=="string"&&n!=="")r=Number(n);else return null;return!Number.isInteger(r)||r<0||r>=t.length?null:t[r]?.bucket??null}const L=[{value:60,label:"1h",granularity:"hour",fetchLimit:500},{value:360,label:"6h",granularity:"hour",fetchLimit:500},{value:1440,label:"24h",granularity:"hour",fetchLimit:500},{value:10080,label:"7d",granularity:"hour",fetchLimit:1e3},{value:720*60,label:"30d",granularity:"day",fetchLimit:2e3},{value:2160*60,label:"90d",granularity:"day",fetchLimit:5e3}],V=L.find(a=>a.label==="7d")??L[2],J=se[0],Z=se[1];function ne(a){const t=new Date(a);return`${t.getMonth()+1}/${t.getDate()} ${String(t.getHours()).padStart(2,"0")}:00`}function Fe(a){const t=new Date(`${a}T00:00:00`);return`${t.getMonth()+1}/${t.getDate()}`}function $(a){if(!a)return"never";const t=Date.now()-new Date(a).getTime(),n=Math.floor(t/6e4);if(n<1)return"just now";if(n<60)return`${n}m ago`;const r=Math.floor(n/60);return r<24?`${r}h ago`:`${Math.floor(r/24)}d ago`}function ee({canGoBack:a,className:t}){const n="inline-flex items-center gap-1";if(a){const r=()=>{window.history.back()};return e.jsxs("button",{type:"button",onClick:r,className:`${n} ${t??""}`,children:[e.jsx(q,{className:"size-3"})," Back"]})}return e.jsxs(he,{to:"/traffic",className:`${n} ${t??""}`,children:[e.jsx(q,{className:"size-3"})," All sources"]})}function Qe(){const a=xe({strict:!1}),t=a.projectName??"",n=me(),r=a.sourceId??"",[d,i]=m.useState(V.value),[o,c]=m.useState(()=>new Set(["crawler","ai-referral"])),[u,w]=m.useState(null),[p,j]=m.useState(""),[x,z]=m.useState(""),[y,D]=m.useState(""),[S,M]=m.useState("all"),[O,U]=m.useState(null),[B,P]=m.useState(null),g=m.useMemo(()=>L.find(s=>s.value===d)??V,[d]),E=ve(t||null,r||null),b=we(t||null,{kind:"all",sourceId:r||void 0,sinceMinutes:d,limit:g.fetchLimit}),R=Se(t||null,r||null),l=E.data,N=b.data?.events??[],k=b.data?.totals,H=m.useMemo(()=>N.filter(s=>s.kind===v.crawler?o.has("crawler"):o.has("ai-referral")),[N,o]),le=m.useMemo(()=>{const s=new Set;for(const h of N)s.add(ae(h));return p&&s.add(p),[...s].sort((h,f)=>h.localeCompare(f))},[N,p]),ie=m.useMemo(()=>{const s=new Set;for(const h of N)s.add(h.operator);return x&&s.add(x),[...s].sort((h,f)=>h.localeCompare(f))},[N,x]),_=m.useMemo(()=>Ee(H,{selectedBucket:u,identity:p,operator:x,pathQuery:y,statusClass:S},g.granularity),[H,u,p,x,y,S,g.granularity]),W=m.useMemo(()=>u?I(u,g.granularity):null,[u,g.granularity]),C=m.useMemo(()=>Oe(N,g.granularity,b.data?.windowStart,b.data?.windowEnd),[N,g.granularity,b.data?.windowStart,b.data?.windowEnd]),K=s=>{c(h=>{const f=new Set(h);return f.has(s)?f.size>1&&f.delete(s):f.add(s),f})},ce=s=>{const h=He(s,C);h&&w(f=>f===h?null:h)},oe=()=>{w(null),j(""),z(""),D(""),M("all")},de=!!(u||p||x||y.trim()||S!=="all"),ue=async()=>{U(null),P(null);try{const s=await R.mutateAsync({sinceMinutes:60});P(`Pulled ${s.pulledEvents} entries · ${s.crawlerHits} crawler · ${s.aiReferralHits} AI referral · ${s.unknownHits} unknown`)}catch(s){const h=s instanceof be||s instanceof Error?s.message:String(s);U(h)}};return!t||!r?e.jsx("div",{className:"page-container",children:e.jsx("p",{className:"text-sm text-zinc-500",children:"Missing project name or source id in URL."})}):E.isLoading?e.jsx("div",{className:"page-container",children:e.jsx("p",{className:"text-sm text-zinc-500",children:"Loading source…"})}):E.isError||!l?e.jsxs("div",{className:"page-container",children:[e.jsx("p",{className:"text-sm text-rose-300",children:"Could not load this source."}),e.jsx(ee,{canGoBack:n,className:"mt-2 text-xs text-zinc-400 hover:text-zinc-200"})]}):e.jsxs("div",{className:"page-container space-y-8",children:[e.jsxs("div",{className:"page-header",children:[e.jsxs("div",{className:"page-header-left",children:[e.jsx(ee,{canGoBack:n,className:"text-xs text-zinc-500 hover:text-zinc-200"}),e.jsx("h1",{className:"page-title mt-2",children:l.displayName}),e.jsxs("p",{className:"page-subtitle",children:[l.sourceType," · project ",e.jsx("span",{className:"text-zinc-300",children:t})," ·",e.jsx("span",{className:"ml-1 font-mono text-zinc-400",children:l.id})]})]}),e.jsxs("div",{className:"flex items-center gap-2",children:[e.jsx(fe,{tone:ze(l.status),children:l.status}),e.jsxs(ge,{type:"button",variant:"outline",size:"sm",disabled:R.isPending,onClick:()=>{ue()},children:[e.jsx(ke,{className:`size-3.5 ${R.isPending?"animate-spin":""}`}),R.isPending?"Syncing…":"Sync now"]})]})]}),O?e.jsx("div",{className:"rounded-md border border-rose-800/50 bg-rose-950/30 px-3 py-2 text-xs text-rose-200",children:O}):null,B?e.jsx("div",{className:"rounded-md border border-emerald-800/50 bg-emerald-950/30 px-3 py-2 text-xs text-emerald-200",children:B}):null,e.jsxs("section",{className:"grid grid-cols-1 gap-4 sm:grid-cols-3",children:[e.jsx(F,{label:"24h crawler hits",value:String(l.totals24h.crawlerHits),delta:l.lastSyncedAt?`last sync ${$(l.lastSyncedAt)}`:"never synced",tone:l.totals24h.crawlerHits>0?"positive":"neutral",description:"GPTBot, ChatGPT-User, PerplexityBot, etc. — verified crawler requests in the last 24h.",isNumeric:!0,progress:Math.min(100,Math.round(l.totals24h.crawlerHits/1e3*100))}),e.jsx(F,{label:"24h AI referral sessions",value:String(l.totals24h.aiReferralHits),delta:l.lastSyncedAt?`last sync ${$(l.lastSyncedAt)}`:"never synced",tone:l.totals24h.aiReferralHits>0?"positive":"neutral",description:"Sessionized visits arriving from chat.openai.com, perplexity.ai, etc. (Referer header evidence).",isNumeric:!0,progress:Math.min(100,Math.round(l.totals24h.aiReferralHits/1e3*100))}),e.jsx(F,{label:"24h sample rows",value:String(l.totals24h.sampleCount),delta:"bounded per sync",tone:"neutral",description:"Per-request samples retained for evidence (capped to keep storage bounded).",isNumeric:!0,progress:Math.min(100,Math.round(l.totals24h.sampleCount/100*100))})]}),e.jsxs("section",{children:[e.jsx("p",{className:"mb-4 text-[10px] font-semibold uppercase tracking-wider text-zinc-500",children:"Latest sync run"}),l.latestRun?e.jsxs(A,{className:"p-4 text-sm",children:[e.jsxs("div",{className:"flex flex-wrap items-center gap-x-6 gap-y-1.5",children:[e.jsxs("span",{className:"text-zinc-100",children:["Status: ",e.jsx("span",{className:"font-medium",children:l.latestRun.status})]}),e.jsxs("span",{className:"text-zinc-500",children:["Started: ",$(l.latestRun.startedAt)]}),l.latestRun.finishedAt?e.jsxs("span",{className:"text-zinc-500",children:["Finished: ",$(l.latestRun.finishedAt)]}):null,e.jsx("span",{className:"font-mono text-[11px] text-zinc-600",children:l.latestRun.runId})]}),l.latestRun.error?e.jsx("p",{className:"mt-2 rounded border border-rose-900/40 bg-rose-950/30 px-3 py-2 text-xs text-rose-300",children:l.latestRun.error}):null]}):e.jsx(A,{className:"px-4 py-3 text-sm text-zinc-500",children:'No traffic-sync runs recorded yet. Hit "Sync now" above to create one.'})]}),e.jsxs("section",{children:[e.jsxs("div",{className:"mb-4 flex flex-wrap items-end justify-between gap-x-4 gap-y-3",children:[e.jsxs("div",{children:[e.jsx("p",{className:"text-[10px] font-semibold uppercase tracking-wider text-zinc-500",children:"Events"}),e.jsx("h2",{className:"mt-1 text-base font-semibold text-zinc-50",children:g.granularity==="day"?"Daily rollups":"Hourly rollups"}),k?e.jsxs("p",{className:"mt-1.5 text-xs text-zinc-500",children:[k.crawlerHits.toLocaleString("en-US")," crawler ·"," ",k.aiReferralHits.toLocaleString("en-US")," AI referral sessions · last ",g.label]}):null]}),e.jsx("div",{className:"filter-row mb-0",role:"toolbar","aria-label":"Window",children:L.map(s=>e.jsx("button",{type:"button",className:`filter-chip ${d===s.value?"filter-chip-active":""}`,"aria-pressed":d===s.value,onClick:()=>{i(s.value),w(null)},children:s.label},s.value))})]}),e.jsxs(A,{className:"p-4",children:[e.jsxs("div",{className:"mb-3 flex flex-wrap items-center gap-2",role:"toolbar","aria-label":"Series",children:[e.jsx(te,{label:"Crawler",color:J,count:k?.crawlerHits??0,active:o.has("crawler"),onToggle:()=>K("crawler")}),e.jsx(te,{label:"AI referral sessions",color:Z,count:k?.aiReferralHits??0,active:o.has("ai-referral"),onToggle:()=>K("ai-referral")})]}),b.isError?e.jsxs("p",{className:"py-12 text-center text-xs text-rose-400",children:["Failed to load events: ",b.error instanceof Error?b.error.message:"Unknown error"]}):b.isLoading?e.jsx("p",{className:"py-12 text-center text-xs text-zinc-500",children:"Loading events…"}):C.length===0?e.jsx("p",{className:"py-12 text-center text-xs text-zinc-500",children:"No events in this window."}):e.jsx("div",{className:"h-72",children:e.jsx(Ce,{children:e.jsxs(Te,{data:C,margin:{top:4,right:4,bottom:0,left:0},onClick:ce,style:{cursor:"pointer"},children:[e.jsx(Re,{stroke:ye,strokeDasharray:"3 3"}),e.jsx($e,{dataKey:"label",tick:Y,stroke:G,interval:"preserveStartEnd",minTickGap:g.granularity==="day"?24:32}),e.jsx(Ae,{tick:Y,stroke:G,allowDecimals:!1}),e.jsx(Ie,{...Ne}),o.has("crawler")?e.jsx(X,{dataKey:"crawler",name:"Crawler",fill:J,stackId:"a",children:C.map(s=>e.jsx(Q,{fillOpacity:u&&u!==s.bucket?.25:1},s.bucket))}):null,o.has("ai-referral")?e.jsx(X,{dataKey:"aiReferral",name:"AI referral",fill:Z,stackId:"a",children:C.map(s=>e.jsx(Q,{fillOpacity:u&&u!==s.bucket?.25:1},s.bucket))}):null]})})})]})]}),e.jsxs("section",{children:[e.jsxs("div",{className:"mb-4 flex flex-wrap items-end justify-between gap-x-4 gap-y-2",children:[e.jsxs("div",{children:[e.jsx("p",{className:"text-[10px] font-semibold uppercase tracking-wider text-zinc-500",children:"Event rows"}),e.jsxs("p",{className:"mt-1 text-xs text-zinc-500",children:["Showing ",e.jsx("span",{className:"tabular-nums text-zinc-300",children:_.length.toLocaleString("en-US")})," of"," ",e.jsx("span",{className:"tabular-nums text-zinc-500",children:H.length.toLocaleString("en-US")})," events"]})]}),e.jsxs("div",{className:"flex flex-wrap items-center gap-2",children:[e.jsxs("select",{"aria-label":"Filter by identity",value:p,onChange:s=>j(s.target.value),className:"rounded-md border border-zinc-800 bg-zinc-950 px-2.5 py-1.5 text-xs text-zinc-200 focus:outline-none focus-visible:ring-1 focus-visible:ring-zinc-600",children:[e.jsx("option",{value:"",children:"All identities"}),le.map(s=>e.jsx("option",{value:s,children:s},s))]}),e.jsxs("select",{"aria-label":"Filter by operator",value:x,onChange:s=>z(s.target.value),className:"rounded-md border border-zinc-800 bg-zinc-950 px-2.5 py-1.5 text-xs text-zinc-200 focus:outline-none focus-visible:ring-1 focus-visible:ring-zinc-600",children:[e.jsx("option",{value:"",children:"All operators"}),ie.map(s=>e.jsx("option",{value:s,children:s},s))]}),e.jsx("select",{"aria-label":"Filter by HTTP status class",value:S,onChange:s=>M(s.target.value),className:"rounded-md border border-zinc-800 bg-zinc-950 px-2.5 py-1.5 text-xs text-zinc-200 focus:outline-none focus-visible:ring-1 focus-visible:ring-zinc-600",children:Le.map(s=>e.jsx("option",{value:s.value,children:s.label},s.value))}),e.jsx("input",{type:"search","aria-label":"Filter by path",placeholder:"path contains…",value:y,onChange:s=>D(s.target.value),className:"w-44 rounded-md border border-zinc-800 bg-zinc-950 px-2.5 py-1.5 text-xs text-zinc-200 placeholder:text-zinc-600 focus:outline-none focus-visible:ring-1 focus-visible:ring-zinc-600"})]})]}),de?e.jsxs("div",{className:"mb-3 flex flex-wrap items-center gap-2",children:[W?e.jsx(T,{label:`Bucket: ${W}`,onClear:()=>w(null)}):null,p?e.jsx(T,{label:`Identity: ${p}`,onClear:()=>j("")}):null,x?e.jsx(T,{label:`Operator: ${x}`,onClear:()=>z("")}):null,y.trim()?e.jsx(T,{label:`Path: ${y.trim()}`,onClear:()=>D("")}):null,S!=="all"?e.jsx(T,{label:`Status: ${S}`,onClear:()=>M("all")}):null,e.jsx("button",{type:"button",onClick:oe,className:"text-xs text-zinc-500 underline-offset-4 hover:text-zinc-200 hover:underline",children:"Clear all"})]}):null,e.jsx(Ue,{events:_})]})]})}function I(a,t){return t==="day"?Fe(a):ne(a)}function Oe(a,t,n,r){const d=new Map;for(const i of a){const o=re(i.tsHour,t);let c=d.get(o);c||(c={bucket:o,label:I(o,t),crawler:0,aiReferral:0},d.set(o,c)),i.kind===v.crawler?c.crawler+=i.hits:c.aiReferral+=i.hits}if(n&&r){const i=new Date(n),o=new Date(r);if(t==="day"){const c=new Date(Date.UTC(i.getUTCFullYear(),i.getUTCMonth(),i.getUTCDate())),u=new Date(Date.UTC(o.getUTCFullYear(),o.getUTCMonth(),o.getUTCDate()));for(;c<=u;){const w=c.getUTCFullYear(),p=String(c.getUTCMonth()+1).padStart(2,"0"),j=String(c.getUTCDate()).padStart(2,"0"),x=`${w}-${p}-${j}`;d.has(x)||d.set(x,{bucket:x,label:I(x,t),crawler:0,aiReferral:0}),c.setUTCDate(c.getUTCDate()+1)}}else{const c=new Date(i);for(c.setUTCMinutes(0,0,0);c<=o;){const u=c.toISOString();d.has(u)||d.set(u,{bucket:u,label:I(u,t),crawler:0,aiReferral:0}),c.setUTCHours(c.getUTCHours()+1)}}}return[...d.values()].sort((i,o)=>i.bucket<o.bucket?-1:i.bucket>o.bucket?1:0)}function T({label:a,onClear:t}){return e.jsxs("span",{className:"inline-flex items-center gap-1.5 rounded-full border border-zinc-700 bg-zinc-800/60 px-2.5 py-1 text-[11px] text-zinc-200",children:[a,e.jsx("button",{type:"button",onClick:t,"aria-label":`Clear ${a}`,className:"rounded-full p-0.5 text-zinc-400 hover:bg-zinc-700/60 hover:text-zinc-100",children:e.jsx(je,{className:"size-3"})})]})}function te({label:a,color:t,count:n,active:r,onToggle:d}){return e.jsxs("button",{type:"button",onClick:d,"aria-pressed":r,className:`inline-flex items-center gap-2 rounded-full border px-3 py-1 text-xs font-medium transition ${r?"border-zinc-700 bg-zinc-800/60 text-zinc-100":"border-zinc-800 bg-transparent text-zinc-500 hover:text-zinc-300"}`,children:[e.jsx("span",{"aria-hidden":"true",className:`size-2 rounded-full transition-opacity ${r?"opacity-100":"opacity-30"}`,style:{backgroundColor:t}}),e.jsx("span",{children:a}),e.jsx("span",{className:`tabular-nums ${r?"text-zinc-400":"text-zinc-600"}`,children:n.toLocaleString("en-US")})]})}function Ue({events:a}){return a.length===0?e.jsx(A,{className:"p-6 text-center text-sm text-zinc-500",children:"No event rows match the current filters."}):e.jsx("div",{className:"rounded-xl border border-zinc-800/60 bg-zinc-900/30 overflow-hidden",children:e.jsxs("table",{className:"w-full text-sm",children:[e.jsx("thead",{className:"bg-zinc-900/50 text-[10px] font-semibold uppercase tracking-wider text-zinc-500",children:e.jsxs("tr",{children:[e.jsx("th",{className:"px-4 py-2 text-left",children:"Hour"}),e.jsx("th",{className:"px-4 py-2 text-left",children:"Kind"}),e.jsx("th",{className:"px-4 py-2 text-left",children:"Identity"}),e.jsx("th",{className:"px-4 py-2 text-left",children:"Evidence / status"}),e.jsx("th",{className:"px-4 py-2 text-left",children:"Path"}),e.jsx("th",{className:"px-4 py-2 text-right",children:"Hits"})]})}),e.jsx("tbody",{className:"divide-y divide-zinc-800/60",children:a.map((t,n)=>e.jsxs("tr",{className:"hover:bg-zinc-900/40 transition-colors",children:[e.jsx("td",{className:"px-4 py-2 font-mono text-xs text-zinc-300",children:ne(t.tsHour)}),e.jsx("td",{className:"px-4 py-2 text-zinc-300",children:t.kind===v.crawler?"Crawler":"AI referral"}),e.jsxs("td",{className:"px-4 py-2 text-zinc-100",children:[t.kind===v.crawler?t.botId:t.product,e.jsx("span",{className:"ml-2 text-[11px] text-zinc-500",children:t.operator})]}),e.jsx("td",{className:"px-4 py-2 text-zinc-300",children:t.kind===v.crawler?`${t.verificationStatus} · HTTP ${t.status}`:`${t.evidenceType} · ${t.sourceDomain}`}),e.jsx("td",{className:"px-4 py-2 truncate font-mono text-xs text-zinc-300",children:t.kind===v.crawler?t.pathNormalized:t.landingPathNormalized}),e.jsx("td",{className:"px-4 py-2 text-right tabular-nums text-zinc-100",children:t.hits})]},`${t.kind}:${t.tsHour}:${n}`))})]})})}export{Qe as TrafficSourceDetailPage};
@@ -1 +1 @@
1
- import{c as o}from"./index-DKBPD33e.js";const e=[["path",{d:"m12 19-7-7 7-7",key:"1l729n"}],["path",{d:"M19 12H5",key:"x3x0zl"}]],r=o("arrow-left",e);export{r as A};
1
+ import{c as o}from"./index-VMFHNbas.js";const e=[["path",{d:"m12 19-7-7 7-7",key:"1l729n"}],["path",{d:"M19 12H5",key:"x3x0zl"}]],r=o("arrow-left",e);export{r as A};