PageSourceSearch

https://bsquared.ai/assets/skills-CI9qGZg4.js

js bsquared.ai collected 2026-10-05 15:20:16 UTC 8,694 bytes, 4 lines download raw bytes

1import{ag as H,u as L,r,j as e,U as M,B as n,C as y,i as f,k as N,m,I as u,s as b,af as w,H as O,ai as Y,a9 as J,G as o}from"./index-DhwrhnZy.js";import{P as V}from"./plus-LIPWcPXb.js";import{W as X}from"./wand-sparkles-CPYXfrpg.js";import{T as Z}from"./trash-2-DcpaeqmH.js";const F={auto:{label:"runs freely",cls:"text-green-600 border-green-300"},notify:{label:"tells you after",cls:"text-blue-600 border-blue-300"},require_approval:{label:"asks first",cls:"text-amber-600 border-amber-300"},forbidden:{label:"never",cls:"text-red-600 border-red-300"}},ee={id:0,name:"",trigger:"",instruction:"",tools:[],require_approval:!1,enabled:!0};function ie(){const k=H(),{data:h,isLoading:A}=L({queryKey:["/api/org/skills"],queryFn:async()=>(await o("GET","/api/org/skills")).json()}),{data:x}=L({queryKey:["/api/org/skills/catalog"],queryFn:async()=>(await o("GET","/api/org/skills/catalog")).json()}),[t,i]=r.useState(null),[C,T]=r.useState(!1),[S,g]=r.useState(null),[c,D]=r.useState(""),[p,R]=r.useState(""),[q,j]=r.useState(null),[_,E]=r.useState(!1),[v,G]=r.useState(null),[$,W]=r.useState([]);async function I(){if(t){T(!0),g(null);try{const s={name:t.name,trigger:t.trigger,instruction:t.instruction,tools:t.tools,require_approval:t.require_approval,enabled:t.enabled},a=t.id?await o("PUT",`/api/org/skills/${t.id}`,s):await o("POST","/api/org/skills",s);if(!a.ok){const l=await a.json();g(l.error+(l.tools?`: ${l.tools.join(", ")}`:""));return}i(null),k.invalidateQueries({queryKey:["/api/org/skills"]})}finally{T(!1)}}}async function B(s){confirm("Delete this skill? Gary forgets it immediately.")&&(await o("DELETE",`/api/org/skills/${s}`),k.invalidateQueries({queryKey:["/api/org/skills"]}))}async function K(){E(!0),j(null);try{const a=await(await o("POST","/api/org/skills/test",{utterance:p})).json();a.matched?j(a.ambiguous?`Matches "${a.matched.name}" — but also ${a.also_matched.map(l=>`"${l.name}"`).join(", ")}. Gary will ask which one; consider sharper "when" phrasing.`:`✓ Gary would use "${a.matched.name}".`):j("No skill matches — Gary would handle this normally.")}finally{E(!1)}}async function Q(s){if(v===s){G(null);return}const l=await(await o("GET",`/api/org/skills/${s}/activity`)).json();W(l.activity??[]),G(s)}const P=(h==null?void 0:h.skills)??[],U=((x==null?void 0:x.tools)??[]).filter(s=>!c||s.name.includes(c.toLowerCase())||(s.description??"").toLowerCase().includes(c.toLowerCase()));return e.jsx(M,{children:e.jsxs("div",{className:"max-w-4xl mx-auto p-6 space-y-6",children:[e.jsxs("div",{className:"flex items-start justify-between",children:[e.jsxs("div",{children:[e.jsx("h1",{className:"text-2xl font-semibold",children:"Skills"}),e.jsx("p",{className:"text-muted-foreground mt-1",children:"Teach Gary how your business works — a trigger, instructions, and the tools he may use. He only ever uses the tools you pick."})]}),!t&&e.jsxs(n,{onClick:()=>i({...ee}),children:[e.jsx(V,{className:"h-4 w-4 mr-1"})," New skill"]})]}),t&&e.jsxs(y,{children:[e.jsx(f,{children:e.jsx(N,{className:"text-lg",children:t.id?`Edit "${t.name}"`:"New skill"})}),e.jsxs(m,{className:"space-y-4",children:[e.jsxs("div",{children:[e.jsx("label",{className:"text-sm font-medium",children:"Name"}),e.jsx(u,{placeholder:"New Listing Intake",value:t.name,onChange:s=>i(a=>a&&{...a,name:s.target.value})})]}),e.jsxs("div",{children:[e.jsx("label",{className:"text-sm font-medium",children:"When should Gary use it?"}),e.jsx(u,{placeholder:"When a new listing comes in, or I say 'run listing intake'",value:t.trigger,onChange:s=>i(a=>a&&{...a,trigger:s.target.value})})]}),e.jsxs("div",{children:[e.jsx("label",{className:"text-sm font-medium",children:"What should Gary do?"}),e.jsx("textarea",{className:"w-full border rounded-md p-2 text-sm bg-background min-h-28",placeholder:`1. Pull the listing details and comps.
22. Draft the MLS description in our voice — warm, no clichés.
33. Create the listing folder.
44. Text me a one-line summary.`,value:t.instruction,onChange:s=>i(a=>a&&{...a,instruction:s.target.value})})]}),e.jsxs("div",{children:[e.jsxs("label",{className:"text-sm font-medium",children:["Which tools may it use? ",e.jsxs("span",{className:"text-muted-foreground font-normal",children:["(",t.tools.length," picked)"]})]}),e.jsx(u,{className:"my-2 max-w-xs",placeholder:"Filter… (e.g. listing, email)",value:c,onChange:s=>D(s.target.value)}),e.jsx("div",{className:"max-h-64 overflow-y-auto border rounded-md divide-y",children:U.map(s=>{const a=t.tools.includes(s.name),l=F[s.tier]??F.auto;return e.jsxs("label",{className:"flex items-start gap-2 p-2 cursor-pointer hover:bg-muted/50",children:[e.jsx("input",{type:"checkbox",className:"mt-1",checked:a,disabled:s.tier==="forbidden",onChange:()=>i(d=>d&&{...d,tools:a?d.tools.filter(z=>z!==s.name):[...d.tools,s.name]})}),e.jsxs("div",{className:"min-w-0",children:[e.jsx("code",{className:"text-xs",children:s.name}),e.jsx(b,{variant:"outline",className:`ml-2 text-[10px] ${l.cls}`,children:l.label}),s.description&&e.jsxs("div",{className:"text-xs text-muted-foreground",children:[s.description,"."]}
4)]})]},s.name)})})]}),e.jsxs("label",{className:"flex items-center gap-2 text-sm",children:[e.jsx("input",{type:"checkbox",checked:t.require_approval,onChange:s=>i(a=>a&&{...a,require_approval:s.target.checked})}),"Ask me before every action this skill takes (good while you're still trusting it)"]}),S&&e.jsx("div",{className:"text-sm text-red-500",children:S}),e.jsxs("div",{className:"flex gap-2",children:[e.jsx(n,{onClick:I,disabled:C,children:C?e.jsx(w,{className:"h-4 w-4 animate-spin"}):"Save skill"}),e.jsx(n,{variant:"ghost",onClick:()=>{i(null),g(null)},children:"Cancel"})]})]})]}),e.jsxs(y,{children:[e.jsxs(f,{children:[e.jsxs(N,{className:"text-lg flex items-center gap-2",children:[e.jsx(O,{className:"h-4 w-4"})," Try a phrase"]}),e.jsx("p",{className:"text-sm text-muted-foreground",children:"Type what you'd say to Gary and see which skill (if any) would run — before it's ever live in a real conversation."})]}),e.jsxs(m,{className:"flex gap-2 items-start",children:[e.jsx(u,{placeholder:'"a new listing just came in at 12 Oak St"',value:p,onChange:s=>R(s.target.value)}),e.jsx(n,{variant:"outline",onClick:K,disabled:_||!p.trim(),children:_?e.jsx(w,{className:"h-4 w-4 animate-spin"}):"Test"})]}),q&&e.jsx(m,{className:"pt-0 text-sm",children:q})]}),e.jsxs(y,{children:[e.jsx(f,{children:e.jsxs(N,{className:"text-lg flex items-center gap-2",children:[e.jsx(X,{className:"h-4 w-4"})," Your skills"]})}),e.jsx(m,{children:A?e.jsx("div",{className:"flex justify-center py-6",children:e.jsx(w,{className:"h-5 w-5 animate-spin"})}):P.length===0?e.jsx("p",{className:"text-sm text-muted-foreground py-2",children:"No skills yet — create one above. Gary picks them up within a minute, no restart."}):e.jsx("div",{className:"divide-y",children:P.map(s=>e.jsxs("div",{className:"py-3",children:[e.jsxs("div",{className:"flex items-center justify-between gap-3",children:[e.jsxs("div",{className:"min-w-0",children:[e.jsx("span",{className:"font-medium",children:s.name}),!s.enabled&&e.jsx(b,{variant:"outline",className:"ml-2",children:"off"}),s.require_approval&&e.jsx(b,{variant:"outline",className:"ml-2 text-amber-600 border-amber-300",children:"asks first"}),e.jsxs("div",{className:"text-xs text-muted-foreground truncate",children:["when: ",s.trigger]}),e.jsxs("div",{className:"text-xs text-muted-foreground",children:[s.tools.length," tools · run ",s.run_count,"×",s.trigger_aliases.length>0?` · learned: ${s.trigger_aliases.slice(0,2).map(a=>`"${a}"`).join(", ")}`:""]})]}),e.jsxs("div",{className:"flex items-center gap-1 shrink-0",children:[e.jsxs(n,{variant:"ghost",size:"sm",onClick:()=>Q(s.id),children:[v===s.id?e.jsx(Y,{className:"h-4 w-4"}):e.jsx(J,{className:"h-4 w-4"})," activity"]}),e.jsx(n,{variant:"ghost",size:"sm",onClick:()=>i({id:s.id,name:s.name,trigger:s.trigger,instruction:s.instruction,tools:s.tools,require_approval:s.require_approval,enabled:s.enabled}),children:"edit"}),e.jsx(n,{variant:"ghost",size:"icon",onClick:()=>B(s.id),children:e.jsx(Z,{className:"h-4 w-4"})})]})]}),v===s.id&&e.jsx("div",{className:"mt-2 border rounded-md p-2 text-xs space-y-1 bg-muted/30",children:$.length===0?e.jsx("div",{className:"text-muted-foreground",children:"This skill hasn't run yet."}):$.map((a,l)=>e.jsxs("div",{className:"flex justify-between",children:[e.jsxs("span",{children:[e.jsx("code",{children:a.tool})," ",e.jsxs("span",{className:"text-muted-foreground",children:["via ",a.platform]})]}),e.jsx("span",{className:a.status==="success"?"text-green-600":"text-amber-600",children:a.decision})]},l))})]},s.id))})})]})]})})}export{ie as default};

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