PageSourceSearch

https://www.parley.live/assets/LensBuilderPage-8H5xE2pc.js

js parley.live collected 2026-10-08 20:33:25 UTC 19,694 bytes, 2 lines download raw bytes

1/*! (c) 2026 Parley Labs (parley.live). All rights reserved. Proprietary and confidential: copying, redistribution or reverse engineering is not permitted. */
2import{r as c,j as e}from"./vendor-markdown-Ez2qizXG.js";import{C as J,G as Q,A as Z,a as ee,X as se,L as te,l as ne}from"./main-CunegClB.js";import{L as _,T as ie,P as ae}from"./index-BmygC2Jz.js";const re=["not tested","passed on glasses","issues found on glasses"],le=["not published","submitted","published"],m={title:40,instruction:220,warning:120,steps:20},D=()=>({procedureName:"",steps:[{instruction:"",warning:""}],completionMessage:"",voiceShortcuts:!0});function oe(){return window.electronAPI?.lensBuilder??null}function pe({onBack:a,backendUrl:l,authToken:x}){const n=oe(),[i,b]=c.useState(null),[u,w]=c.useState(""),[G,E]=c.useState(""),[P,B]=c.useState("describe"),[j,W]=c.useState(""),[N,$]=c.useState(null),[q,H]=c.useState(null),[o,g]=c.useState(D),[p,k]=c.useState("idle"),[T,O]=c.useState([]),[r,S]=c.useState(null),[d,R]=c.useState([]),M=c.useRef(null),y=c.useCallback(async()=>{if(!n)return;b(await n.status());const s=await n.metrics();s.ok&&s.metrics&&R(s.metrics.lenses)},[n]);c.useEffect(()=>{y()},[y]);const F=!!i&&i.configured&&i.reachable&&i.toolsOk;c.useEffect(()=>{if(!n||F||p!=="idle")return;const s=setInterval(()=>{n.status().then(b)},5e3);return()=>clearInterval(s)},[n,F,p]),c.useEffect(()=>{if(n)return n.onEvent(s=>{s.type==="log"&&s.message&&O(t=>[...t,s.message])})},[n]),c.useEffect(()=>{M.current?.scrollIntoView({block:"nearest"})},[T]);const I=!!i&&i.configured&&i.reachable&&i.toolsOk,C=ce(o),X=async()=>{if(!n)return;E("");const s=await n.connect(u);if(!s.ok){E(s.error||"Could not save the connection.");return}w(""),s.status&&b(s.status)},K=async()=>{if(!n||!j.trim())return;k("planning"),$(null),S(null);const s=await n.plan(j.trim(),{backendUrl:l,token:x});if(k("idle"),!s.ok||!s.planner){$({kind:"error",text:s.error||"Planning failed."});return}s.planner.decision==="build"&&s.planner.form?(g({...D(),...s.planner.form,steps:s.planner.form.steps.map(t=>({instruction:t.instruction,warning:t.warning||""}))}),H({...s.planner,prompt:j.trim()}),B("form")):$({kind:s.planner.decision==="clarify"?"clarify":"reject",text:s.planner.decision==="clarify"&&s.planner.question||s.planner.reason})},V=async()=>{if(!n||C.length)return;k("building"),O([]),S(null);const s=await n.build({form:o,planner:q??void 0});k("idle"),s.ok&&s.result?S(s.result):S({ok:!1,lens_id:"",iterations:0,seconds:0,costUsd:0,stage:"error",error:s.error,checks:[]}),y()},Y=async(s,t)=>{if(!n)return;R(f=>f.map(v=>v.run===s?{...v,...t}:v)),(await n.record({run:s,...t})).ok||y()},U=(s,t)=>g(h=>({...h,steps:h.steps.map((f,v)=>v===s?{...f,...t}:f)}));return e.jsxs("div",{className:"min-h-screen overflow-x-clip bg-zinc-950 text-zinc-100",children:[e.jsx("header",{className:"sticky top-0 z-10 border-b border-zinc-800/80 bg-zinc-950/80 backdrop-blur-md",children:e.jsxs("div",{className:"mx-auto flex max-w-5xl items-center gap-3 px-4 py-3",children:[e.jsxs("button",{onClick:a,className:"flex items-center gap-1 rounded-lg px-2 py-1 text-sm text-zinc-400 hover:bg-zinc-900 hover:text-zinc-100",children:[e.jsx(J,{className:"h-4 w-4"}),"Back"]}),e.jsx(Q,{className:"h-5 w-5 text-sky-400"}),e.jsx("h1",{className:"text-sm font-semibold",children:"New Specs Lens"})]})}),e.jsxs("main",{className:"mx-auto max-w-5xl space-y-6 px-4 py-8",children:[e.jsxs("section",{children:[e.jsx("h2",{className:"text-2xl font-semibold tracking-tight",children:"Turn your procedure into a hands-free guide on Snap Specs"}),e.jsx("p",{className:"mt-2 max-w-2xl text-sm text-zinc-400",children:"Write the steps the way you would explain them to a new hire. You get a Lens that shows one step at a time, with a pinch to move on and optional voice shortcuts. Every build is tested before you see it."})]}),!n&&e.jsxs("section",{className:"rounded-2xl border border-amber-500/30 bg-amber-500/5 p-5 text-sm",children:[e.jsxs("div",{className:"flex items-center gap-2 font-medium text-amber-300",children:[e.jsx(Z,{className:"h-4 w-4"}),"Building needs the Parley desktop app"]}),e.jsx("p",{className:"mt-2 text-zinc-300",children:"Lenses are built inside Lens Studio, which only talks to apps on the same computer. Open this page in the Parley desktop app with Lens Studio running. You can still draft your steps here and paste them in later."})]}),n&&i&&e.jsxs("section",{className:"rounded-2xl border border-zinc-800 bg-zinc-900/40 p-5",children:[e.jsxs("div",{className:"flex flex-wrap items-center gap-x-5 gap-y-2 text-sm",children:[e.jsx(A,{ok:i.lensStudioRunning,label:i.lensStudioRunning?"Lens Studio is running":"Lens Studio is not running"}),e.jsx(A,{ok:i.configured&&i.reachable,label:i.configured?i.reachable?"Connected":"Saved connection is not answering":"Not connected yet"}),e.jsx(A,{ok:i.toolsOk,label:i.toolsOk?"Build tools available":"Build tools missing"}),e.jsx("button",{onClick:()=>{y()},className:"ml-auto rounded-lg border border-zinc-700 px-3 py-1 text-xs text-zinc-300 hover:bg-zinc-800",children:"Check again"})]}),I?e.jsx("p",{className:"mt-3 text-sm text-emerald-300",children:"Ready. Lens Studio is connected and has everything it needs. Describe your procedure below, or fill in the steps."}):e.jsx(de,{status:i,configText:u,setConfigText:w,connect:()=>{X()},connectError:G})]}),e.jsxs("section",{className:"rounded-2xl border border-zinc-800 bg-zinc-900/40 p-5",children:[e.jsx("div",{className:"mb-4 inline-flex rounded-xl border border-zinc-800 bg-zinc-950 p-1 text-sm",children:["describe","form"].map(s=>e.jsx("button",{onClick:()=>B(s),className:`rounded-lg px-4 py-1.5 ${P===s?"bg-zinc-800 text-zinc-100":"text-zinc-400 hover:text-zinc-200"}`,children:s==="describe"?"Describe it":"Review and edit steps"},s))}),P==="describe"&&e.jsxs("div",{className:"space-y-3",children:[e.jsx("textarea",{value:j,onChange:s=>W(s.target.value),rows:6,placeholder:"Example: New baristas need to learn the end of day clean. Turn the machine off and let it c
2ool (it stays hot), knock out the puck and rinse the basket, backflush five times with cleaning powder, wipe and purge the steam wand.",className:"w-full rounded-xl border border-zinc-700 bg-zinc-950 p-3 text-sm text-zinc-100 outline-none focus:border-sky-500"}),e.jsxs("div",{className:"flex items-center gap-3",children:[e.jsxs("button",{onClick:()=>{K()},disabled:!n||p!=="idle"||!j.trim(),className:"flex items-center gap-2 rounded-lg bg-sky-500 px-4 py-2 text-sm font-medium text-zinc-950 disabled:opacity-40",children:[p==="planning"&&e.jsx(_,{className:"h-4 w-4 animate-spin"}),"Turn into steps"]}),e.jsx("span",{className:"text-xs text-zinc-500",children:"You review every step before anything is built. Turning a description into steps uses a little of your Parley credit; filling in the steps yourself is free."})]}),N&&e.jsxs("div",{className:`rounded-xl border p-3 text-sm ${N.kind==="clarify"?"border-sky-500/30 bg-sky-500/5 text-sky-200":"border-amber-500/30 bg-amber-500/5 text-amber-200"}`,children:[N.kind==="clarify"?"One question first: ":N.kind==="reject"?"This cannot be built as asked: ":"",N.text]})]}),P==="form"&&e.jsxs("div",{className:"space-y-4",children:[e.jsx(L,{label:"Procedure name",count:o.procedureName.length,max:m.title,children:e.jsx("input",{value:o.procedureName,onChange:s=>g({...o,procedureName:s.target.value}),className:"w-full rounded-lg border border-zinc-700 bg-zinc-950 px-3 py-2 text-sm outline-none focus:border-sky-500"})}),o.steps.map((s,t)=>e.jsxs("div",{className:"rounded-xl border border-zinc-800 bg-zinc-950/60 p-3",children:[e.jsxs("div",{className:"mb-2 flex items-center justify-between text-xs text-zinc-500",children:[e.jsxs("span",{children:["Step ",t+1]}),o.steps.length>1&&e.jsxs("button",{onClick:()=>g({...o,steps:o.steps.filter((h,f)=>f!==t)}),className:"flex items-center gap-1 hover:text-red-400",children:[e.jsx(ie,{className:"h-3.5 w-3.5"}),"Remove"]})]}),e.jsx(L,{label:"What to do",count:s.instruction.length,max:m.instruction,children:e.jsx("textarea",{value:s.instruction,onChange:h=>U(t,{instruction:h.target.value}),rows:2,className:"w-full rounded-lg border border-zinc-700 bg-zinc-950 px-3 py-2 text-sm outline-none focus:border-sky-500"})}),e.jsx(L,{label:"Safety caution (optional)",count:s.warning.length,max:m.warning,children:e.jsx("input",{value:s.warning,onChange:h=>U(t,{warning:h.target.value}),className:"w-full rounded-lg border border-zinc-700 bg-zinc-950 px-3 py-2 text-sm outline-none focus:border-sky-500"})})]},t)),o.steps.length<m.steps&&e.jsxs("button",{onClick:()=>g({...o,steps:[...o.steps,{instruction:"",warning:""}]}),className:"flex items-center gap-1 rounded-lg border border-zinc-700 px-3 py-1.5 text-sm text-zinc-300 hover:bg-zinc-800",children:[e.jsx(ae,{className:"h-4 w-4"}),"Add a step"]}),e.jsx(L,{label:"Message when finished (optional)",count:o.completionMessage.length,max:m.instruction,children:e.jsx("input",{value:o.completionMessage,onChange:s=>g({...o,completionMessage:s.target.value}),className:"w-full rounded-lg border border-zinc-700 bg-zinc-950 px-3 py-2 text-sm outline-none focus:border-sky-500"})}),e.jsxs("label",{className:"flex items-center gap-2 text-sm text-zinc-300",children:[e.jsx("input",{type:"checkbox",checked:o.voiceShortcuts,onChange:s=>g({...o,voiceShortcuts:s.target.checked})}),'Also allow saying "done", "next" and "back" (the pinch buttons always work)']}),C.length>0&&e.jsx("ul",{className:"list-disc pl-5 text-sm text-amber-300",children:C.map(s=>e.jsx("li",{children:s},s))}),e.jsxs("button",{onClick:()=>{V()},disabled:!I||p!=="idle"||C.length>0,className:"flex items-center gap-2 rounded-lg bg-sky-500 px-5 py-2.5 text-sm font-medium text-zinc-950 disabled:opacity-40",children:[p==="building"&&e.jsx(_,{className:"h-4 w-4 animate-spin"}),p==="building"?"Building and testing":"Build my Lens"]}),!I&&n&&e.jsx("p",{className:"text-xs text-zinc-500",children:"Connect Lens Studio above to build."})]})]}),(T.length>0||p==="building")&&e.jsxs("section",{className:"rounded-2xl border border-zinc-800 bg-zinc-900/40 p-5",children:[e.jsx("h3",{className:"mb-2 text-sm font-medium text-zinc-300",children:"Progress"}),e.jsxs("div",{className:"max-h-64 overflow-y-auto rounded-xl bg-zinc-950 p-3 font-mono text-xs text-zinc-400",children:[T.map((s,t)=>e.jsx("div",{className:/FAIL/.test(s)?"text-red-400":/PASS/.test(s)?"text-emerald-400":"",children:s},t)),e.jsx("div",{ref:M})]})]}),r&&e.jsxs("section",{className:`rounded-2xl border p-5 ${r.ok?"border-emerald-500/30 bg-emerald-500/5":"border-red-500/30 bg-red-500/5"}`,children:[e.jsxs("div",{className:"flex items-center gap-2 text-lg font-semibold",children:[r.ok?e.jsx(ee,{className:"h-5 w-5 text-emerald-400"}):e.jsx(se,{className:"h-5 w-5 text-red-400"}),r.ok?r.updated?"Your Lens was updated in place and passed every preview test":"Your Lens passed every preview test":"This build needs a person to look at it"]}),e.jsx("p",{className:"mt-1 text-sm text-zinc-400",children:r.error?r.error:`${r.seconds} seconds, ${r.iterations} ${r.iterations===1?"attempt":"attempts"}, model cost $${(r.costUsd??0).toFixed(4)}.`}),r.checks.length>0&&e.jsx("div",{className:"mt-4 overflow-x-auto",children:e.jsx("table",{className:"w-full text-left text-sm",children:e.jsx("tbody",{children:r.checks.map(s=>e.jsxs("tr",{className:"border-t border-zinc-800/80 align-top",children:[e.jsx("td",{className:"w-36 py-2 pr-3",children:e.jsx("span",{className:`rounded-full px-2 py-0.5 text-xs ${s.status==="pass"?"bg-emerald-500/15 text-emerald-300":s.status==="fail"?"bg-red-500/15 text-red-300":"bg-amber-500/15 text-amber-300"}`,children:s.status==="pass"?"Passed":s.status==="fail"?"Failed":"Check on glasses"})}),e.jsx("td",{className:"py-2 pr-3 text-zinc-200",children:s.item}),e.jsx("td",{className:"py-2 text-xs text-zinc-500",children:s.detail})]},s.item))})})}),r.ok&&e.jsx("div",{className:"mt-4 overflow-hidden rounded-xl border border-zinc-800 bg-zinc-950/40",children:e.jsx(te,{name:r.t
2itle||o.procedureName||r.lens_id,images:r.previewImages,bridge:ne()})}),r.ok&&e.jsxs("p",{className:"mt-4 text-sm text-zinc-300",children:["Next: look at it above, then pair your Specs in Lens Studio and press Send to my glasses to try it on. Publishing is done from Lens Studio. The full report is saved at ",e.jsx("span",{className:"font-mono text-xs text-zinc-400",children:r.reportPath})]})]}),d.length>0&&e.jsxs("section",{className:"rounded-2xl border border-zinc-800 bg-zinc-900/40 p-5",children:[e.jsx("h3",{className:"mb-3 text-sm font-medium text-zinc-300",children:"Lenses built on this computer"}),e.jsxs("div",{className:"mb-4 grid grid-cols-2 gap-3 sm:grid-cols-5",children:[e.jsx(z,{label:"Built",value:String(d.length)}),e.jsx(z,{label:"Passed testing",value:`${d.filter(s=>s.pass).length} of ${d.length}`}),e.jsx(z,{label:"Average time",value:`${Math.round(d.reduce((s,t)=>s+t.seconds,0)/d.length)} s`}),e.jsx(z,{label:"Checked on glasses",value:`${d.filter(s=>s.hardwareTest!=="not tested").length} of ${d.length}`}),e.jsx(z,{label:"Average model cost",value:`$${(d.reduce((s,t)=>s+(t.costUsd||0),0)/d.length).toFixed(3)}`})]}),e.jsx("div",{className:"overflow-x-auto",children:e.jsxs("table",{className:"w-full text-left text-xs text-zinc-400",children:[e.jsx("thead",{children:e.jsxs("tr",{className:"text-zinc-500",children:[e.jsx("th",{className:"py-1 pr-3 font-medium",children:"Lens"}),e.jsx("th",{className:"pr-3 font-medium",children:"Result"}),e.jsx("th",{className:"pr-3 font-medium",children:"Steps"}),e.jsx("th",{className:"pr-3 font-medium",children:"Time"}),e.jsx("th",{className:"pr-3 font-medium",children:"Cost"}),e.jsx("th",{className:"pr-3 font-medium",children:"On glasses"}),e.jsx("th",{className:"font-medium",children:"Published"})]})}),e.jsx("tbody",{children:d.slice(0,50).map(s=>e.jsxs("tr",{className:"border-t border-zinc-800/70",children:[e.jsx("td",{className:"py-1.5 pr-3 text-zinc-200",children:s.title}),e.jsx("td",{className:`pr-3 ${s.pass?"text-emerald-400":"text-red-400"}`,children:s.pass?"Passed":"Failed"}),e.jsx("td",{className:"pr-3",children:s.steps}),e.jsxs("td",{className:"pr-3",children:[s.seconds," s"]}),e.jsxs("td",{className:"pr-3",children:["$",(s.costUsd||0).toFixed(4)]}),e.jsx("td",{className:"pr-3",children:e.jsx("select",{"aria-label":`On glasses result for ${s.title}`,value:s.hardwareTest,onChange:t=>{Y(s.run,{hardwareTest:t.target.value})},className:"rounded border border-zinc-700 bg-zinc-950 px-1 py-0.5 text-xs text-zinc-300",children:re.map(t=>e.jsx("option",{children:t},t))})}),e.jsx("td",{children:e.jsx("select",{"aria-label":`Publish status for ${s.title}`,value:s.publishStatus,onChange:t=>{Y(s.run,{publishStatus:t.target.value})},className:"rounded border border-zinc-700 bg-zinc-950 px-1 py-0.5 text-xs text-zinc-300",children:le.map(t=>e.jsx("option",{children:t},t))})})]},s.run))})]})})]})]})]})}function ce(a){const l=[];return a.procedureName.trim()||l.push("Give the procedure a name."),a.procedureName.length>m.title&&l.push(`Keep the name to ${m.title} characters so it fits the panel.`),a.steps.forEach((x,n)=>{x.instruction.trim()||l.push(`Step ${n+1} needs an instruction.`),x.instruction.length>m.instruction&&l.push(`Step ${n+1} is too long to read comfortably. Split it into two steps.`),x.warning.length>m.warning&&l.push(`Shorten the caution on step ${n+1}.`)}),l}function de({status:a,configText:l,setConfigText:x,connect:n,connectError:i}){const b=/rejected/i.test(a.error||""),u=a.lensStudioRunning?!a.configured||b||!a.reachable?"connect":"tools":"install";return e.jsxs("div",{className:"mt-4 space-y-3 text-sm",children:[e.jsx("div",{className:"text-xs font-medium uppercase tracking-wide text-zinc-500",children:u==="install"?"Step 1 of 3":u==="connect"?"Step 2 of 3":"Step 3 of 3"}),u==="install"&&e.jsxs("div",{className:"space-y-2 text-zinc-300",children:[e.jsx("p",{className:"font-medium text-zinc-100",children:"Open Lens Studio with a project."}),e.jsxs("p",{children:["Lenses are built inside Snap's free Lens Studio (version 5.22 or later). Install it from ",e.jsx("span",{className:"font-mono text-zinc-200",children:"ar.snap.com/download"}),", open it, and create any project: on its home screen choose ",e.jsx("span",{className:"font-medium text-zinc-100",children:"SPECS"}),", then ",e.jsx("span",{className:"font-medium text-zinc-100",children:"Base Template"}),". Leave it open. Lens Studio only listens for Parley while a project is open. This page checks again by itself every few seconds."]})]}),u==="connect"&&e.jsxs("div",{className:"space-y-2 text-zinc-300",children:[e.jsx("p",{className:"font-medium text-zinc-100",children:b?"Lens Studio needs a fresh connection code.":"Connect Parley to Lens Studio, once."}),e.jsxs("p",{children:["In Lens Studio open ",e.jsx("span",{className:"font-medium text-zinc-100",children:"AI Assistant"}),", then ",e.jsx("span",{className:"font-medium text-zinc-100",children:"AI Model Context Protocol (MCP)"}),", then ",e.jsx("span",{className:"font-medium text-zinc-100",children:"Configure Server"}),", press ",e.jsx("span",{className:"font-medium text-zinc-100",children:"Copy MCP Config"}),", and paste it here.",b?" The saved code was refused, which happens when Lens Studio was reinstalled or its keychain entry was cleared.":" You do this one time: Lens Studio keeps the same code across restarts. It is stored encrypted on this computer and never leaves it."]}
2),e.jsx("textarea",{value:l,onChange:w=>x(w.target.value),rows:4,spellCheck:!1,placeholder:'{ "mcpServers": { "lens-studio": { ... } } }',className:"w-full rounded-xl border border-zinc-700 bg-zinc-950 p-3 font-mono text-xs text-zinc-200 outline-none focus:border-sky-500"}),e.jsxs("div",{className:"flex items-center gap-3",children:[e.jsx("button",{onClick:n,disabled:!l.trim(),className:"rounded-lg bg-sky-500 px-4 py-2 text-sm font-medium text-zinc-950 disabled:opacity-40",children:"Connect"}),i&&e.jsx("span",{className:"text-red-400",children:i})]})]}),u==="tools"&&e.jsxs("div",{className:"space-y-2 text-zinc-300",children:[e.jsx("p",{className:"font-medium text-zinc-100",children:"Let Lens Studio finish installing its build tools."}),e.jsxs("p",{children:["Parley builds through packages Snap ships for Lens Studio. Lens Studio installs them by itself the first time it starts while online, so a restart of Lens Studio usually completes this. If this light stays off after a restart, open ",e.jsx("span",{className:"font-medium text-zinc-100",children:"Window"}),", then ",e.jsx("span",{className:"font-medium text-zinc-100",children:"Asset Library"})," in Lens Studio, install ",e.jsx("span",{className:"font-medium text-zinc-100",children:"Core Chat Tools"})," and ",e.jsx("span",{className:"font-medium text-zinc-100",children:"Run Editor Code"}),", and restart Lens Studio."]})]}),a.error&&u!=="connect"&&e.jsx("p",{className:"text-amber-300",children:a.error})]})}function A({ok:a,label:l}){return e.jsxs("span",{className:"flex items-center gap-2",children:[e.jsx("span",{className:`h-2 w-2 rounded-full ${a?"bg-emerald-400":"bg-zinc-600"}`}),l]})}function L({label:a,count:l,max:x,children:n}){return e.jsxs("label",{className:"block",children:[e.jsxs("span",{className:"mb-1 flex justify-between text-xs text-zinc-500",children:[e.jsx("span",{children:a}),e.jsxs("span",{className:l>x?"text-red-400":"",children:[l,"/",x]})]}),n]})}function z({label:a,value:l}){return e.jsxs("div",{className:"rounded-xl border border-zinc-800 bg-zinc-950/60 p-3",children:[e.jsx("div",{className:"text-xs text-zinc-500",children:a}),e.jsx("div",{className:"mt-1 text-lg font-semibold text-zinc-100",children:l})]})}export{pe 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.