PageSourceSearch

https://studio.findem.ai/assets/StudioAppBuilder-B9p24JL3.js

js findem.ai collected 2026-10-02 05:23:48 UTC 55,894 bytes, 40 lines download raw bytes

1const __vite__mapDeps=(i,m=__vite__mapDeps,d=(m.f||(m.f=["assets/PeopleSearchPilot-Cumnsbwx.js","assets/index-_Ci2S7BU.js","assets/index-C0XQwy2u.css","assets/CandidatePreviewDetailDrawer-DNwkd6ek.js","assets/intakeMeetingUtils-C9OJd3Pt.js","assets/connectionListsApi-C3s6czPI.js","assets/history-CN7vUlA4.js","assets/ProfileDrawers.module-DNyTUhXv.js","assets/ProfileDrawers-BhPIf_xw.css","assets/thumbs-up-DZitqOSX.js","assets/external-link-DYcRdATM.js","assets/PeopleTable-4iNORKyC.js","assets/clock-AOQfIQHm.js","assets/arrow-up-down-QBDmpmFo.js","assets/link-D9bcGDaP.js","assets/EvidenceMark-SEhHeIjN.js","assets/ListAlertOffer-YhWzUArF.js","assets/WatchListSheet-B9Ir5FDf.js","assets/AlertIntakeModal-BXmxzRDP.js","assets/companyEntryParse-CRpGIu3w.js","assets/alertStyles-BHKPp5pv.js","assets/PeopleSearchPilot-CEOi-DcH.css"])))=>i.map(i=>d[i]);
2import{j as e,m as z,B as v,m$ as j,r,L as H,nk as be,o as F,nl as oe,d0 as we,ni as ye,q as U,bE as J,y as le,bN as ae,hx as ke,z as _e,x as Se,J as Ne,W as re,fz as Ce,nm as Ae,cl as Pe,nn as Re,g2 as Ee}from"./index-_Ci2S7BU.js";import{A as ce}from"./AppFrame-lb1uRc70.js";import{c as Te,A as $e,a as Le}from"./AppActionReview-KlT7tfxq.js";import{A as qe}from"./RemoteMcpModal-CBZERauN.js";/* empty css                   */import{S as ze}from"./save-B5mRpfen.js";import{E as Oe}from"./external-link-DYcRdATM.js";import"./workflowLaunchHandoff-O3uYSikj.js";import"./oauthPopup-U7ZIp_nH.js";import"./connectorsCatalog-BVQYoe69.js";import"./remoteConnector-DYZmzCR3.js";import"./link-2-Daw6Vy4l.js";function De(s){if(Array.isArray(s?.inputs)&&s.inputs.length)return s.inputs.filter(o=>o&&typeof o.key=="string").map(({key:o,label:d,required:n})=>({key:o,label:d||o,required:n===!0}));const i=s?.input_schema?.properties||{},l=Array.isArray(s?.input_schema?.required)?s.input_schema.required:[];return(s?.input_keys||[]).map(o=>({key:o,label:i[o]?.title||o,required:l.includes(o)}))}function Ie(s){return[...s?.bindings||[],...s?.tool_bindings||[]].map(i=>({key:i.key,name:i.name,inputs:De(i)}))}function Fe({app:s,dirty:i,busy:l,action:o}){const d=s.domain,n=f=>o(()=>j.domain(s.app_id,{...f,revision:s.revision}),f.action==="verify"?"DNS ownership verified. The hosting ingress must serve this hostname over HTTPS.":"Domain settings saved.");return e.jsxs("section",{className:"studio-apps-card",children:[e.jsx("h2",{children:"Custom domain"}),e.jsx("p",{children:"Public pages can use your own hostname. Private pages and signed-in agent actions use the app’s Studio URL."}),e.jsxs("form",{onSubmit:f=>{f.preventDefault(),n({action:"request",hostname:new FormData(f.currentTarget).get("hostname")}
2)},children:[e.jsx(z,{label:"Public app hostname",name:"hostname",required:!0,placeholder:"portal.yourcompany.com",defaultValue:d?.hostname||""}),e.jsx(v,{type:"submit",disabled:i||l||s.audience!=="public",children:"Get DNS records"})]}),d&&e.jsxs(e.Fragment,{children:[e.jsx("p",{children:d.verified_at?"DNS ownership verified":"Awaiting DNS verification"}),e.jsxs("dl",{children:[e.jsx("dt",{children:"TXT name"}),e.jsx("dd",{children:e.jsxs("code",{children:["_studio.",d.hostname]})}),e.jsx("dt",{children:"TXT value"}),e.jsx("dd",{children:e.jsxs("code",{children:["studio-app=",d.token]})}),e.jsx("dt",{children:"CNAME name"}),e.jsx("dd",{children:e.jsx("code",{children:d.hostname})}),e.jsx("dt",{children:"CNAME target"}),e.jsx("dd",{children:e.jsx("code",{children:d.target})})]}),e.jsx("p",{children:"Verification requests expire after 24 hours. Add these records with your DNS provider, then verify."}),e.jsxs("div",{className:"studio-apps-actions",children:[e.jsx(v,{disabled:i||l,onClick:()=>n({action:"verify"}),children:"Verify DNS"}),e.jsx(v,{disabled:i||l,onClick:()=>n({action:"remove"}),children:"Disconnect domain"})]})]})]})}async function Ue({app:s,api:i,onUpdate:l,onProgress:o,cancelled:d=()=>!1}){let n=s;for(let f=0;f<=2;f++){if(d())return{status:"cancelled",app:n};if(o(`Testing proposal${f?` after repair ${f} of 2`:""}…`),n=(await i.buildProposal(n.app_id,n.revision)).app,l(n),d())return{status:"cancelled",app:n};const g=n.builder_proposal?.build;if(g?.status==="passed")return{status:"passed",app:n};if(g?.status!=="failed")throw Error("The proposal test did not return a valid result.");if(f===2)return{status:"failed",app:n};o(`Repairing startup errors · attempt ${f+1} of 2…`),n=(await i.generate(n.app_id,{revision:n.revision,prompt:"Repair the current proposal using its build diagnostics. Preserve the requested functionality and organization design. Return the complete corrected source; do not fabricate a passed test."})).app,l(n)}}function Be({app:s,disabled:i,sync:l}){const[o,d]=r.useState(!1),[n,f]=r.useState(""),[g,x]=r.useState(""),t=r.useRef(!1),h=r.useRef(!0);r.useEffect(()=>(h.current=!0,()=>{h.current=!1}),[]);const u=s.builder_creation;if(!u)return null;async function b(){if(t.current)return;t.current=!0,d(!0),f("");let m=s;try{const C=await j.createWorkflow(s.app_id,{action:"start",revision:s.revision});m=C.app,h.current&&l(m);const w=await be(s.mcp_org_id,C.args);h.current&&x(w.workflow_id);const p=await j.createWorkflow(s.app_id,{action:"attach",revision:m.revision,workflow_id:w.workflow_id});h.current&&l(p.app)}catch(C){h.current&&f(`${C.message} Creation is never retried automatically. If submitted, check existing agents and attach the created workflow below.`)}finally{t.current=!1,h.current&&d(!1)}}async function y(m){if(m.preventDefault(),!t.current){t.current=!0,d(!0),f("");try{const C=await j.createWorkflow(s.app_id,{action:"attach",revision:s.revision,workflow_id:g});h.current&&l(C.app)}catch(C){h.current&&f(C.message)}finally{t.current=!1,h.current&&d(!1)}}}async function _(){if(!t.current){t.current=!0,d(!0),f("");try{const m=await j.createWorkflow(s.app_id,{action:"reset",revision:s.revision,checked_existing:!0});h.current&&l(m.app)}catch(m){h.current&&f(m.message)}finally{t.current=!1,h.current&&d(!1)}}}return e.jsxs("section",{className:"studio-apps-card",children:[e.jsxs("h3",{children:["Workflow setup · ",u.recipe.name]}),e.jsx("p",{children:u.recipe.objective}),e.jsx("p",{children:"Creates a private workflow using Studio’s existing recipe. A billing admin must publish its fixed price and authorize its release before it can run."}),n&&e.jsx("p",{role:"alert",className:"studio-apps-error",children:n}),u.status==="ready"&&e.jsx(v,{disabled:i||o||s.role!=="owner",loading:o,onClick:b,children:"Create and connect workflow"}),u.status==="submitted"&&e.jsxs(e.Fragment,{children:[e.jsx("p",{role:"status",children:"Creation was submitted. Check your saved agents if its outcome is unknown."}),e.jsx(v,{as:H,to:"/agents",target:"_blank",rel:"noopener noreferrer",children:"View saved agents"}),e.jsxs("form",{onSubmit:y,children:[e.jsx(z,{label:"Created workflow ID",required:!0,maxLength:150,value:g,onChange:m=>x(m.target.value)}),e.jsx(v,{type:"submit",disabled:i||o||s.role!=="owner",children:"Attach existing workflow"})]}),e.jsx("p",{children:"Only allow another attempt after verifying that no workflow was created or is still being created."}),e.jsx(v,{disabled:i||o||s.role!=="owner",onClick:_,children:"I checked: allow another attempt"})]}),u.status==="attached"&&e.jsxs("p",{role:"status",children:["Connected as ",u.recipe.key,". Once launch is authorized, ask the builder to enable its form and run button. No run has started."]})]})}function Me({app:s,dirty:i,busy:l,apply:o,sync:d}){const[n,f]=r.useState(""),[g,x]=r.useState(!1),[t,h]=r.useState(s.builder_proposal||null),[u,b]=r.useState(""),[y,_]=r.useState(s.builder_chat||[]),m=r.useRef(!0),C=r.useRef(!1),[w,p]=r.useState(""),[N,$]=r.useState(!1);r.useEffect(()=>(m.current=!0,()=>{m.current=!1}),[]),r.useEffect(()=>{_(s.builder_chat||[])},[s.builder_chat]),r.useEffect(()=>{h(s.builder_proposal||null),s.builder_proposal||p("")},[s.builder_proposal]);async function D(k){k.preventDefault(),x(!0),b(""),p(""),h(null),_(A=>[...A,{role:"user",text:n}]);try{p("Discovering available agents and Studio tools…");const A=s.mcp_org_id?await oe(s.mcp_org_id,n):void 0;if(!m.current)return;p("Building a page and connection plan…");const I=await j.generate(s.app_id,{prompt:n,revision:s.revision,...A?{native_tools:A}:{}});if(!m.current)return;I.app?(d?.(I.app),_(I.app.builder_chat||[])):_(c=>[...c,{role:"assistant",text:I.message}]),h(I),f(""),p("")}catch(A){m.current&&(b(A.message),p(""),h(s.builder_proposal||null))}finally{m.current&&x(!1)}}async function P(k){x(!0),b(""),p("");try{const A=await j.editChat(s.app_id,{action:k,revision:s.revision});m.current&&(d?.(A.app),h(null),_(A.app.builder_chat||[]))}catch(A){m.current&&b(A.message)}finally{m.current&&x(!1)}}async function O(){C.current=!1,x(!0),$(!0),b("");try{const k=await Ue({app:s,api:j,cancelled:()=>!m.current||C.current,onProgress:A=>{m.current&&p(A)}
2,onUpdate:A=>{m.current&&(d?.(A),h(A.builder_proposal),_(A.builder_chat||[]))}});m.current&&p(k.status==="passed"?"Build and startup checks passed. Review the page before applying.":k.status==="cancelled"?"Stopped after the current request. The latest proposal is saved.":"Two repairs were attempted. Review the remaining errors or ask for a smaller change.")}catch(k){m.current&&(b(k.message),p(""))}finally{m.current&&(x(!1),$(!1))}}return e.jsxs("section",{className:"studio-app-chat",children:[e.jsxs("aside",{className:"studio-apps-card",children:[e.jsx("h2",{children:"Build with a prompt"}),e.jsx("p",{children:"Describe your page or ask for a change. Studio discovers accessible agents and MCP tools, proposes relevant connections, and uses your saved source and organization branding."}),e.jsx("p",{className:"studio-apps-note",children:"The last 25 completed exchanges and latest proposal are saved with this app and shared with its editors."}),e.jsx("div",{className:"studio-app-chat-history","aria-live":"polite",children:y.map((k,A)=>e.jsxs("article",{children:[e.jsx("strong",{children:k.role==="user"?"Request":"Studio"}),e.jsx("p",{children:k.text})]},A))}),y.length>0&&e.jsx(v,{size:"sm",disabled:l||i||g,onClick:()=>P("clear"),children:"Clear conversation"}),e.jsxs("form",{onSubmit:D,children:[e.jsx(F,{label:"What should we build?",required:!0,maxLength:6e3,rows:6,value:n,onChange:k=>f(k.target.value),placeholder:"Build a branded research portal with a company form and a button that runs my connected research agent."}),e.jsx(v,{variant:"primary",type:"submit",loading:g,disabled:l||i||g,children:"Generate proposal"})]}),s.build?.status==="failed"&&e.jsx("p",{className:"studio-apps-note",children:"The next prompt includes the failed build’s diagnostics. Ask Studio to fix them."}),i&&e.jsx("p",{className:"studio-apps-note",children:"Save your current draft before asking for another change."}),u&&e.jsx("p",{role:"alert",className:"studio-apps-error",children:u}),w&&e.jsx("p",{role:"status",children:w}),g&&N&&e.jsx(v,{onClick:()=>{C.current=!0},children:"Stop after current step"}),e.jsx("p",{className:"studio-apps-note",children:"You can use HTML and JavaScript or ask for React and TypeScript. Generated changes require your review and a build before publishing."}),e.jsx(Be,{app:s,disabled:l||i||g,sync:d})]}),e.jsxs("div",{className:"studio-apps-card",children:[e.jsx("h2",{children:"Proposed changes"}),t?e.jsxs(e.Fragment,{children:[e.jsx("p",{children:t.brand?`Uses ${t.brand.name} v${t.brand.version}.`:"No organization design system is selected."}),t.composition&&e.jsxs("section",{className:"studio-app-composition","aria-label":"Proposed workflow and connections",children:[e.jsx("h3",{children:"Workflow and connections"}),e.jsx("ol",{children:t.composition.actions.map(k=>e.jsxs("li",{children:[e.jsx("strong",{children:k.capability.binding.name})," · ",k.key,e.jsx("p",{children:k.reason}),e.jsx("p",{children:"workflow_id"in k.capability.binding?"Reuses an existing agent with its predefined outcome.":"Uses the visitor’s existing Studio connection. Each action requires review."}),k.capability.binding.externally_runnable===!1&&e.jsx("p",{children:"Launch authorization is required before this agent can run."})]},k.key))}),t.composition.gaps.length>0&&e.jsxs(e.Fragment,{children:[e.jsx("h4",{children:"Needs setup or support"}),e.jsx("ul",{children:t.composition.gaps.map((k,A)=>e.jsx("li",{children:k},A))})]}),t.composition.create_workflow&&e.jsxs("p",{children:["Proposes a new private workflow: ",t.composition.create_workflow.name,". Apply this proposal, then review workflow creation below the chat. Pricing and launch authorization are still required."]}),s.role!=="owner"&&(t.composition.actions.length>0||t.composition.create_workflow)&&e.jsx("p",{children:"The app owner must apply proposed connections."})]}),t.source.format==="react"&&t.build?.status!=="passed"?e.jsx("p",{children:"Test this proposal to compile React and TypeScript and preview the result."}):e.jsx(ce,{source:t.build?.status==="passed"?t.build.source:t.source,title:"Proposed app preview"}),t.build&&e.jsxs("details",{className:"studio-app-build-log",open:t.build.status==="failed",children:[e.jsxs("summary",{children:["Proposal build · ",t.build.status]}),e.jsx("pre",{children:t.build.logs.join(`
3`)})]}),e.jsx(v,{disabled:l||i||g||t.base_revision!==s.revision,onClick:O,children:"Test & repair proposal"}),e.jsx("p",{className:"studio-apps-note",children:"Runs the isolated build and up to two model repairs. Normal generation and build limits apply. Review interactions before publishing."}),e.jsx("div",{className:"studio-app-change-summary",children:["html","css","javascript"].map(k=>e.jsxs("details",{children:[e.jsxs("summary",{children:[k," · ",s.source[k]===t.source[k]?"unchanged":"changed"]}),e.jsxs("div",{className:"studio-app-diff",children:[e.jsxs("div",{children:[e.jsx("strong",{children:"Saved"}),e.jsx("pre",{children:s.source[k]})]}),e.jsxs("div",{children:[e.jsx("strong",{children:"Proposed"}),e.jsx("pre",{children:t.source[k]})]})]})]},k))}),e.jsxs("div",{className:"studio-apps-actions",children:[e.jsx(v,{disabled:l||i||g,onClick:()=>
3P("discard"),children:"Discard proposal"}),e.jsx(v,{variant:"primary",disabled:l||i||g||t.base_revision!==s.revision||s.role!=="owner"&&!!(t.composition?.actions.length||t.composition?.create_workflow),onClick:async()=>{await o(t.source)&&h(null)},children:"Apply to draft"})]}),t.base_revision!==s.revision&&e.jsx("p",{role:"status",children:"The saved app changed. Generate a fresh proposal to preserve those changes."})]}):e.jsx("p",{children:g?"Generating your page…":"Your next proposal will appear here for review."})]})]})}const Je=(s,i)=>i?.from==="stage"?`${s}: from “${i.stage}” (${i.path})`:`${i?.label||s}${i?.required===!1?" (optional)":""}`;function ne({stages:s,capabilityName:i}){return e.jsx("ol",{className:"studio-app-journey-stages",children:s.map((l,o)=>e.jsxs("li",{children:[e.jsxs("strong",{children:[o+1,". ",l.title]})," ",e.jsxs("span",{className:"studio-apps-note",children:[i(l)," · ",e.jsx("code",{children:l.id})]}),e.jsx("p",{children:l.goal}),e.jsxs("p",{className:"studio-apps-note",children:["Asks for: ",Object.keys(l.inputs||{}).length?Object.entries(l.inputs).map(([d,n])=>Je(d,n)).join(" · "):"nothing",l.deliverable?` · Produces: ${l.deliverable}`:""]})]},l.id))})}function Ve({app:s,dirty:i,busy:l,sync:o,action:d}){const[n,f]=r.useState(s.journey?.objective||""),[g,x]=r.useState(!1),[t,h]=r.useState(null),[u,b]=r.useState(""),y=r.useRef(!0);r.useEffect(()=>(y.current=!0,()=>{y.current=!1}),[]);const _=s.journey_proposal,m=_&&_.base_revision===s.revision,C=t?.code==="JOURNEY_OUT_OF_SCOPE";async function w(p){p.preventDefault(),x(!0),h(null);try{b("Reading the agents and tools this app can use…");const N=s.mcp_org_id?await oe(s.mcp_org_id,n):void 0;if(!y.current)return;b("Mapping the objective to a journey…");const $=await j.planJourney(s.app_id,{objective:n,revision:s.revision,...N?{native_tools:N}:{}});if(!y.current)return;$.app&&o?.($.app),b("")}catch(N){y.current&&(h(N),b(""))}finally{y.current&&x(!1)}}return e.jsxs("section",{className:"studio-app-journey",children:[e.jsxs("aside",{className:"studio-apps-card",children:[e.jsx("h2",{children:"What should this app produce?"}),e.jsx("p",{children:"Describe the outcome for the people who will use it. Studio maps it to a journey over the agents and tools your workspace has: people, roles, leadership, hiring, workforce and company intelligence."}),e.jsxs("form",{onSubmit:w,children:[e.jsx(F,{label:"Objective",required:!0,maxLength:2e3,rows:5,value:n,onChange:p=>f(p.target.value),placeholder:"Give a client a CFO shortlist for their company with a one-page brief on each finalist."}),e.jsx(v,{variant:"primary",type:"submit",loading:g,disabled:l||i||g||!n.trim(),children:s.journey?"Plan again":"Plan the journey"})]}),i&&e.jsx("p",{className:"studio-apps-note",children:"Save your current draft before planning."}),u&&e.jsx("p",{role:"status",children:u}),t&&e.jsx("p",{role:"alert",className:C?"studio-apps-notice":"studio-apps-error",children:C?`Not something this app can plan. ${t.message.replace(/^This app plans people-intelligence journeys only\.\s*/,"")}`:t.message}),e.jsx("p",{className:"studio-apps-note",children:"Objectives outside people intelligence are refused. Each stage runs one connected agent or tool; the page asks visitors only for what the plan cannot take from an earlier stage."})]}),e.jsx("div",{className:"studio-apps-card",children:m?e.jsxs(e.Fragment,{children:[e.jsx("h2",{children:"Proposed journey"}),e.jsx("p",{children:_.plan.scope.reason}),e.jsx(ne,{stages:_.plan.stages,capabilityName:p=>p.capability?.binding?.name||p.capability_id}),_.plan.gaps.length>0&&e.jsxs(e.Fragment,{children:[e.jsx("h3",{children:"Not covered by the palette"}),e.jsx("ul",{children:_.plan.gaps.map((p,N)=>e.jsx("li",{children:p},N))})]}),_.warnings?.length>0&&e.jsx("ul",{className:"studio-apps-note",children:_.warnings.map((p,N)=>e.jsx("li",{children:p},N))}),e.jsxs("div",{className:"studio-apps-actions",children:[e.jsx(v,{disabled:l||i||g,onClick:()=>d(()=>j.discardJourney(s.app_id,s.revision),"Proposed journey discarded."),children:"Discard"}),s.role==="owner"?e.jsx(v,{variant:"primary",disabled:l||i||g,onClick:()=>d(()=>j.applyJourney(s.app_id,s.revision),"Journey applied. The page now renders these stages. Build and test, then publish."),children:"Apply journey"}):e.jsx("p",{className:"studio-apps-note",children:"The app owner applies journeys."})]})]}):_?e.jsx("p",{role:"status",children:"The saved app changed since this journey was planned. Plan it again to continue."}):s.journey?e.jsxs(e.Fragment,{children:[e.jsx("h2",{children:"Current journey"}),e.jsx("p",{children:s.journey.objective}),e.jsx(ne,{stages:s.journey.stages,capabilityName:p=>p.capability_name||p.capability_id}),s.journey.gaps?.length>0&&e.jsxs(e.Fragment,{children:[e.jsx("h3",{children:"Not covered by the palette"}),e.jsx("ul",{children:s.journey.gaps.map((p,N)=>e.jsx("li",{children:p},N))})]}),e.jsx("p",{className:"studio-apps-note",children:"Each stage is connected as an action with the same name. Shape the page in Chat or Code; the plan stays the same."})]}):e.jsx("p",{children:g?"Planning…":"Your journey will appear here for review."})})]})}const We={text:"short answer",long_text:"longer answer",company_list:"company list",people_list:"people list",choice:"choice"};function Ge({app:s,dirty:i,busy:l,sync:o}){const[d,n]=r.useState(""),[f,g]=r.useState(!1),[x,t]=r.useState(null),[h,u]=r.useState(""),b=r.useRef(!0);r.useEffect(()=>(b.current=!0,()=>{b.current=!1}),[]);const y=s.outcome;if(!y)return null;async function _(m){m.preventDefault(),g(!0),t(null),u("");try{const C=s.mcp_org_id?await ye(s.mcp_org_id).catch(()=>[]):[],w=await j.reviseOutcome(s.app_id,{instruction:d,revision:s.revision,agents:C});if(!b.current)return;w.app&&o?.(w.app),n(""),u("Updated. Build and test, then publish so visitors get the new version.")}catch(C){b.current&&t(C)}finally{b.current&&g(!1)}}return e.jsxs("section",{className:"studio-app-journey",children:[e.jsxs("aside",{className:"studio-apps-card",children:[e.jsx("h2",{children:"Change how it’s done"}),e.jsx("p",{children:"Tell Studio what to do differently: what to ask for, which evidence to use, what the deliverable should contain. The look of the page stays; use Chat for that."}),e.jsxs("form",{onSubmit:_,children:[e.jsx(F,{label:"Instruction",required:!0,maxLength:2e3,rows:5,value:d,onChange:m=>n(m.target.value),placeholder:"Also rate each successor’s flight risk and add a slide comparing the top three."}),e.jsx(v,{variant:"primary",type:"submit",loading:f,disabled:l||i||f||!d.trim(),children:"Update the app"})]}),i&&e.jsx("p",{className:"studio-apps-note",children:"Save your current draft before changing the app."}),x&&e.jsx("p",{role:"alert",className:x.code==="JOURNEY_OUT_OF_SCOPE"?"studio-apps-notice":"studio-apps-error",children:x.message}),h&&e.jsx("p",{role:"status",className:"studio-apps-notice",children:h}),e.jsxs("p",{className:"studio-apps-note",children:["Version ",y.version," · people-intelligence apps only."]})]}),e.jsxs("div",{className:"studio-apps-card",children:[e.jsx("h2",{children:s.name}),e.jsx("p",{children:y.objective}),e.jsx("h3",{children:"Visitors provide"}),e.jsx("ol",{className:"studio-app-journey-stages",children:y.inputs.map(m=>e.jsxs("li",{children:[e.jsx("strong",{children:m.label})," ",e.jsxs("span",{className:"studio-apps-note",children:[We[m.kind]||m.kind,m.required?"":" · optional",m.options?` · ${m.options.join(" / ")}`:""]})]},m.key))}),e.jsx("h3",{children:"How it’s done"}),e.jsxs("p",{className:"studio-apps-note",children:["Runs ",we(y.engine.agent_name),y.engine.skill_id?` with the ${y.engine.skill_id} skill`:"",", unattended, with the visitor’s own credits and permissions."]}),e.jsx("pre",{className:"studio-app-method",children:y.engine.method}),e.jsx("h3",{children:"Visitors receive"}),e.jsxs("p",{children:[y.engine.deliverable.title," ",e.jsxs("span",{className:"studio-apps-note",children:["(",y.engine.deliverable.format,y.engine.deliverable.render_skill_id?`, rendered with ${y.engine.deliverable.render_skill_id}`:"",")"]})]}),y.gaps?.length>0&&e.jsxs(e.Fragment,{children:[e.jsx("h3",{children:"Not covered"}),e.jsx("ul",{children:y.gaps.map((m,C)=>e.jsx("li",{children:m},C))})]})]})]})}const Ye=[["save_search","Save as Findem search","Visitors with a Findem license save the search to the Findem platform."],["add_to_list","Add to a list","Visitors add the people they pick to one of their people lists."],["create_list","Create a list","Visitors create a new people list from the people they pick."]],Q=s=>({name:s.name,description:s.description||"",title:s.pilot?.title||"",intro:s.pilot?.
3intro||"",guidance:s.pilot?.guidance||"",starters:(s.pilot?.starters||[]).join(`
4`),limit:String(s.pilot?.results?.limit||10),actions:s.pilot?.actions||[]});function He({app:s,busy:i,action:l}){const[o,d]=r.useState(()=>Q(s));r.useEffect(()=>{d(Q(s))},[s.app_id,s.revision]);const n=t=>h=>d(u=>({...u,[t]:h.target.value})),f=(t,h)=>d(u=>({...u,actions:h?[...new Set([...u.actions,t])]:u.actions.filter(b=>b!==t)})),g=JSON.stringify(o)!==JSON.stringify(Q(s));function x(t){t.preventDefault(),l(()=>j.updatePilot(s.app_id,{revision:s.revision,name:o.name,description:o.description,pilot:{template:"people_search",title:o.title,intro:o.intro,guidance:o.guidance,starters:o.starters.split(`
5`).map(h=>h.trim()).filter(Boolean).slice(0,4),results:{limit:Number(o.limit)},actions:o.actions}}),"Saved. Publish so visitors get this version.")}return e.jsxs("section",{className:"studio-app-journey",children:[e.jsxs("aside",{className:"studio-apps-card",children:[e.jsx("h2",{children:"How this app works"}),e.jsx("p",{children:"Visitors describe who they are looking for in the chat. Studio builds the people search from their words and narrows it with your rules, then keeps its top matches on the right, scored on every criterion and on your rules. Each message refines the same search."}),e.jsx("p",{children:"Searches, scores and lists run as each visitor, in this workspace, with their own credits. Nothing is generated or built, so changes here publish as they are."}),e.jsxs("p",{className:"studio-apps-note",children:["Version ",s.pilot?.version||1,". Published pilots also appear under Configured Pilots in the sidebar for people who can use them."]})]}),e.jsxs("form",{className:"studio-apps-card",onSubmit:x,children:[e.jsx(z,{label:"App name",required:!0,maxLength:100,value:o.name,onChange:n("name")}),e.jsx(F,{label:"Description",maxLength:500,rows:2,value:o.description,onChange:n("description")}),e.jsx(z,{label:"Heading above the chat",required:!0,maxLength:100,value:o.title,onChange:n("title")}),e.jsx(F,{label:"Opening message",maxLength:600,rows:3,value:o.intro,onChange:n("intro")}),e.jsx(F,{label:"Rules for every search",maxLength:4e3,rows:4,value:o.guidance,onChange:n("guidance"),hint:"Studio narrows every visitor's search with these where Findem can filter on them, and scores each match against them: location, seniority, what to weigh most. A rule never widens what the visitor asked for."}),e.jsx(F,{label:"Example requests",maxLength:900,rows:4,value:o.starters,onChange:n("starters"),hint:"One per line, up to four. Visitors can click one to start."}),e.jsx(U,{label:"Top matches to show",value:o.limit,onChange:n("limit"),children:[5,10,15,20].map(t=>e.jsx("option",{value:String(t),children:t},t))}),e.jsxs("fieldset",{className:"studio-app-creators",children:[e.jsx("legend",{children:"What visitors can do with the matches"}),Ye.map(([t,h,u])=>e.jsxs("label",{children:[e.jsx(J,{type:"checkbox",checked:o.actions.includes(t),onChange:b=>f(t,b.target.checked)}),e.jsxs("span",{children:[h,e.jsx("small",{children:u})]})]},t))]}),e.jsx("div",{className:"studio-apps-actions",children:e.jsx(v,{variant:"primary",type:"submit",disabled:i||!g,children:"Save app"})})]})]})}const M=s=>String(s).replace(/[&<>"']/g,i=>({"&":"&amp;","<":"&lt;",">":"&gt;",'"':"&quot;","'":"&#39;"})[i]),Z=s=>JSON.stringify(s).replace(/</g,"\\u003c");function de(s={},i=0){if(i>10)return{};const l=Object.assign({},...["anyOf","oneOf","allOf"].flatMap(o=>(s[o]||[]).map(d=>de(d,i+1))));return Object.fromEntries(Object.entries({...l,...s.properties||{}}).map(([o,d])=>{const n=Array.isArray(d.type)?d.type.find(f=>f!=="null"):d.type;return[o,{...d,type:n||"string"}]}))}function Ke(s,i){const l=`studio-action-${i.key}`;if(s.html.includes(`id="${l}"`))throw Error("This action already has a form. Edit it in Code or ask Chat to change it.");const o=de(i.input_schema),d=Object.entries(o).map(([x,t])=>{const h=t.type||"string",u=i.input_schema?.required?.includes(x),b=h==="boolean"?`<input name="${M(x)}" type="checkbox">`:["object","array"].includes(h)?`<textarea name="${M(x)}" placeholder="${h==="array"?"[]":"{}"}" ${u?"required":""}></textarea>`:`<input name="${M(x)}" type="${["number","integer"].includes(h)?"number":"text"}" ${h==="number"?'step="any"':""} ${u?"required":""}>`;return`<label>${M(t.title||x)}${u?" *":""}${b}</label>`}).join(`
6`),n=`<section id="${l}" class="studio-data-block"><h2>${M(i.name)}</h2><form>${d}<button type="submit">${M(i.name)}</button></form>
6<p role="status" aria-live="polite"></p><div class="studio-data-results"></div></section>`,f=`
7;(() => {
8const section = document.getElementById(${Z(l)});
9const form = section.querySelector('form'), status = section.querySelector('[role="status"]'), output = section.querySelector('.studio-data-results');
10const fields = ${Z(o)};
11form.addEventListener('submit', async event => {
12  event.preventDefault(); const button = form.querySelector('button'); if (button.disabled) return;
13  button.disabled = true; status.textContent = 'Waiting for your review…'; output.replaceChildren();
14  try {
15    const inputs = {}; const data = new FormData(form);
16    for (const [name, schema] of Object.entries(fields)) {
17      const value = data.get(name);
18      if (schema.type === 'boolean') inputs[name] = data.has(name);
19      else if (value !== '' && value !== null) inputs[name] = ['object','array'].includes(schema.type) ? JSON.parse(value) : ['number','integer'].includes(schema.type) ? Number(value) : value;
20    }
21    const result = await window.studio.run(${Z(i.key)}, inputs);
22    if (result.status === 'failed') { status.textContent = 'The tool reported a failure.'; const pre = document.createElement('pre'); pre.textContent = result.text || JSON.stringify(result.data, null, 2); output.append(pre); return; }
23    status.textContent = 'Complete';
24    if (Array.isArray(result.data) && result.data.length && result.data.every(row => row && typeof row === 'object' && !Array.isArray(row))) {
25      const columns = [...new Set(result.data.flatMap(row => Object.keys(row)))].slice(0, 20);
26      const table = document.createElement('table'), head = document.createElement('thead'), header = document.createElement('tr');
27      for (const key of columns) { const th = document.createElement('th'); th.textContent = key; header.append(th); } head.append(header); table.append(head);
28      const body = document.createElement('tbody');
29      for (const row of result.data.slice(0, 200)) { const tr = document.createElement('tr'); for (const key of columns) { const td = document.createElement('td'); td.textContent = typeof row[key] === 'object' ? JSON.stringify(row[key]) : String(row[key] ?? ''); tr.append(td); } body.append(tr); }
30      table.append(body); output.append(table);
31      if (result.data.length > 200) status.textContent = 'Showing the first 200 records.';
32    } else { const pre = document.createElement('pre'); pre.textContent = result.data == null || (Array.isArray(result.data) && !result.data.length) ? (result.text || 'No results.') : typeof result.data === 'string' ? result.data : JSON.stringify(result.data, null, 2); output.append(pre); }
33  } catch (error) { status.textContent = error.message || 'Action unavailable.'; }
34  finally { button.disabled = false; }
35});
36})();`;return{...s,html:`${s.html}
37${n}`,css:s.css+`
38.studio-data-block{margin:24px 0;padding:24px;border:1px solid var(--color-border,#dfe5ed);border-radius:12px}.studio-data-block form{display:grid;gap:12px}.studio-data-block label{display:grid;gap:6px}.studio-data-block input,.studio-data-block textarea{padding:10px;font:inherit}.studio-data-block button{padding:12px;background:var(--color-primary,#284b70);color:white;border:0;border-radius:6px;cursor:pointer}.studio-data-results{overflow:auto}.studio-data-results table{width:100%;border-collapse:collapse}.studio-data-results th,.studio-data-results td{padding:10px;text-align:left;border-bottom:1px solid #ddd}.studio-data-results pre{white-space:pre-wrap;overflow-wrap:anywhere}`,javascript:s.javascript+f}}function Xe({app:s,busy:i,dirty:l,action:o,changeSource:d}){const[n,f]=r.useState({connections:[],can_share:!1}),[g,x]=r.useState(""),[t,h]=r.useState([]),[u,b]=r.useState([]),[y,_]=r.useState(""),[m,C]=r.useState("visitor"),[w,p]=r.useState(""),[N,$]=r.useState(!1),[D,P]=r.useState(!1),O=r.useRef(!0);r.useEffect(()=>(O.current=!0,()=>{O.current=!1}),[]);async function k(){const c=await j.mcpConnections(s.app_id);O.current&&f(c)}r.useEffect(()=>{k().catch(c=>{O.current&&p(c.message)})},[s.app_id,s.revision]),r.useEffect(()=>{let c=!0;if(h([]),b([]),_(""),p(""),!!g)return $(!0),j.mcpTools(s.app_id,g).then(E=>{c&&(h(E.tools),b(E.unavailable||[]),_(E.tools[0]?.tool_name||""))}).catch(E=>{c&&p(E.message)}).finally(()=>{c&&$(!1)}),()=>{c=!1}},[s.app_id,g,s.revision,n]);const A=t.find(c=>c.tool_name===y);async function I(c){c.preventDefault();const E=new FormData(c.currentTarget);await o(()=>j.bindMcpTool(s.app_id,{revision:s.revision,key:E.get("key"),provider:g,tool_name:y,share_connection_url:E.get("share_connection_url")==="on",credential_mode:m,authorize_shared:E.get("authorize_shared")==="on",result_path:E.get("result_path")||""}),"MCP action connected to the draft. Publish to update the live app.")}return e.jsxs("section",{className:"studio-apps-card studio-app-mcp",children:[e.jsx("h2",{children:"Third-party MCP actions"}),e.jsx("p",{children:"Connect a server, choose a tool, and add a form or ask Chat to design its interface. Credentials stay in Studio."}),e.jsx(v,{disabled:i||l,onClick:()=>P(!0),children:"Connect MCP server"}),w&&e.jsx("p",{role:"alert",className:"studio-apps-error",children:w}),D&&e.jsx(qe,{onClose:()=>P(!1),onAdd:c=>Te(c,async E=>{await k(),O.current&&(x(E),P(!1))})}),(s.tool_bindings||[]).map(c=>e.jsxs("article",{className:"studio-app-agent",children:[e.jsx("strong",{children:c.name}),e.jsxs("small",{children:[c.provider.replace(/^remote:/,"").replace(/~[a-f0-9]{16}$/i,"")," · ",c.credential_mode==="organization"?"Admin-authorized organization connection":"Each visitor connects their own account"]}),e.jsxs("code",{children:[c.key,c.result_path?` → ${c.result_path}`:""]}),e.jsxs("div",{className:"studio-apps-actions",children:[e.jsx(v,{size:"sm",disabled:i||l,onClick:()=>{try{d(Ke(s.source,c)),p("")}catch(E){p(E.message)}},children:"Insert form & results"}),s.role==="owner"&&e.jsx(v,{size:"sm",disabled:i||l,onClick:()=>o(()=>j.bindMcpTool(s.app_id,{key:c.key,remove:!0,revision:s.revision}),"Removed from the draft. Publish to remove the live action; revoke shared authorization below to stop shared access immediately."),children:"Remove action"})]})]},c.key)),s.role==="owner"&&e.jsxs("form",{className:"studio-app-mcp-form",onSubmit:I,children:[e.jsxs(U,{label:"Your connection",value:g,onChange:c=>x(c.target.value),required:!0,children:[e.jsx("option",{value:"",children:"Choose an MCP connection"}),n.connections.map(c=>e.jsxs("option",{value:c.provider,children:[c.name," · ",c.status==="active"?c.account:"Reconnect required"]},c.id))]}),N&&e.jsx("p",{role:"status",children:"Discovering available tools…"}),e.jsx(U,{label:"Tool",value:y,onChange:c=>_(c.target.value),required:!0,disabled:N||!t.length,children:t.map(c=>e.jsx("option",{value:c.tool_name,children:c.name},c.tool_name))}),A&&e.jsxs("details",{children:[e.jsx("summary",{children:"Inputs and result schema"}),e.jsx("pre",{children:JSON.stringify({inputs:A.input_schema,output:A.output_schema||"Returned by the tool"},null,2)})]}),!!u.length&&e.jsxs("details",{children:[e.jsxs("summary",{children:[u.length," tools need additional schema support"]}),u.map(c=>e.jsxs("p",{children:[c.name,": ",c.reason]},c.name))]}),n.connections.find(c=>c.provider===g)?.connect_url&&e.jsxs("label",{className:"studio-app-toggle",children:[e.jsx(J,{name:"share_connection_url",type:"checkbox"}),"Include this server address in visitor connection setup: ",n.connections.find(c=>c.provider===g).connect_url,". Leave unchecked if the address contains a private access token."]}),e.jsx(z,{label:"Action name",name:"key",required:!0,maxLength:50,pattern:"[a-z][a-z0-9_]*",placeholder:"load_records"}),e.jsx(z,{label:"Data path in the result",name:"result_path",maxLength:300,placeholder:"/records — leave empty for the full result"}),e.jsxs(U,{label:"Connection access",value:m,onChange:c=>C(c.target.value),children:[e.jsx("option",{value:"visitor",children:"Each visitor’s own account"}),e.jsx("option",{value:"organization",disabled:!n.can_share,children:"Admin-authorized organization connection"})]}),m==="organization"&&e.jsxs("label",{className:"studio-app-toggle",children:[e.jsx(J,{type:"checkbox",name:"authorize_shared",required:!0}),"I authorize active organization members with access to this app to run this selected tool using my connected account. A dedicated service account is recommended."]}),e.jsx(v,{type:"submit",disabled:i||l||N||!A,children:"Connect tool action"})]}),n.can_share&&(s.tool_grants||[]).filter(c=>c.status==="active").map(c=>e.jsxs("div",{className:"studio-app-agent",children:[e.jsxs("span",{children:[c.tool_name," · shared access authorized"]}),e.jsx(v,{size:"sm",disabled:i||l,onClick:()=>o(()=>j.revokeMcpGrant(s.app_id,{grant_id:c.id,revision:s.revision}),"Shared access revoked immediately for drafts and published versions."),children:"Revoke shared access now"})]},c.id)),e.jsx("p",{className:"studio-apps-note",children:"Every call requires visitor review. Returned data is shown only in that visitor’s app session. Draft previews can execute real actions after review."})]})}function Qe({app:s,busy:i,dirty:l,action:o,changeSource:d}){const[n,f]=r.useState([]),[g,x]=r.useState(null),[t,h]=r.useState(""),{mcpScopeOrg:u,canManageActiveOrgMembers:b}=le(),y=b&&u?.mcp_org_id===s.mcp_org_id;r.useEffect(()=>{let w=!0;return Promise.allSettled([j.agents(s.app_id),j.branding(s.app_id)]).then(([p,N])=>
38{w&&(p.status==="fulfilled"&&f(p.value.workflows),N.status==="fulfilled"&&x(N.value.brand),(p.status==="rejected"||N.status==="rejected")&&h([p,N].filter($=>$.status==="rejected").map($=>$.reason.message).join(" ")))}),()=>{w=!1}},[s.app_id,s.revision]);async function _(w){w.preventDefault();const p=new FormData(w.currentTarget);await o(()=>j.bindAgent(s.app_id,{key:p.get("key"),workflow_id:p.get("agent"),revision:s.revision}),"Agent connected to the draft. Publish to update the live app.")}async function m(w){const p=w.target.files?.[0];if(w.target.value="",!p)return;if(!["image/png","image/jpeg","image/webp"].includes(p.type)||p.size>24e3){h("Choose a PNG, JPEG, or WebP logo under 24 KB.");return}const N=new FileReader;N.onload=()=>d({...s.source,html:`<img alt="Organization logo" src="${N.result}" style="max-width:180px;max-height:80px;object-fit:contain;margin:24px" />
39${s.source.html}`}),N.onerror=()=>h("This logo could not be read."),N.readAsDataURL(p)}async function C(w){const p=w.target.files?.[0];w.target.value="",p&&await o(async()=>{await ke.upload(p,{makeDefault:!0});const N=await j.branding(s.app_id);x(N.brand)},"Organization design system uploaded and selected.")}return e.jsxs("div",{className:"studio-app-access",children:[t&&e.jsx("p",{role:"alert",className:"studio-apps-error",children:t}),e.jsxs("section",{className:"studio-apps-card",children:[e.jsx("h2",{children:"Organization branding"}),e.jsx("p",{children:g?`${g.name} · v${g.version}`:"Select an organization design system to use its colors, typography tokens, and component guidance."}),e.jsxs("div",{className:"studio-apps-actions",children:[e.jsx(v,{disabled:i||l||!g,onClick:()=>o(()=>j.applyBrand(s.app_id,s.revision),"Organization design tokens applied to the draft."),children:"Apply organization styles"}),e.jsx(v,{as:H,to:"/design-systems",children:"Manage design systems"})]}),y&&e.jsx(ae,{hint:"This becomes the organization default for compatible renders and future app prompts.",label:"Upload organization design system",accept:".zip,.json",disabled:i||l,onChange:C}),e.jsx(ae,{hint:"PNG, JPEG, or WebP up to 24 KB. The image is saved with the app.",label:"Add a logo to this page",accept:"image/png,image/jpeg,image/webp",disabled:i||l,onChange:m})]}),e.jsxs("section",{className:"studio-apps-card",children:[e.jsx("h2",{children:"Connected agents"}),e.jsx("p",{children:"Give a saved agent an action name, then ask the builder to add a button or form for it. Visitors review actions in Studio and use their own permissions."}),s.bindings?.map(w=>e.jsxs("article",{className:"studio-app-agent",children:[e.jsx("strong",{children:w.name}),e.jsxs("code",{children:["window.studio.run('",w.key,"', ","{…}",")"]}),e.jsxs("small",{children:["Inputs: ",w.input_keys.join(", ")||"none"]}),s.role==="owner"&&e.jsx(v,{size:"sm",disabled:i||l,onClick:()=>o(()=>j.bindAgent(s.app_id,{key:w.key,remove:!0,revision:s.revision}),"Agent disconnected from the draft."),children:"Disconnect"})]},w.key)),s.role==="owner"&&e.jsxs("form",{onSubmit:_,children:[e.jsx(z,{label:"Action name",name:"key",required:!0,maxLength:50,pattern:"[a-z][a-z0-9_]*",placeholder:"research_company"}),e.jsxs(U,{label:"Saved agent",name:"agent",required:!0,defaultValue:"",children:[e.jsx("option",{value:"",disabled:!0,children:"Choose an agent"}),n.map(w=>e.jsx("option",{value:w.workflow_id,children:w.name},w.workflow_id))]}),e.jsx(v,{type:"submit",disabled:i||l||!n.length,children:"Connect agent"})]}),e.jsx("p",{className:"studio-apps-note",children:"External guests can use the page. Running organization agents requires active organization membership and access to the selected agent. Requests that need additional setup or charge approval continue in Studio."})]}),e.jsx(Xe,{app:s,busy:i,dirty:l,action:o,changeSource:d})]})}const Ze=r.lazy(()=>Ee(()=>import("./PeopleSearchPilot-Cumnsbwx.js"),__vite__mapDeps([0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21])));function ps(){const s=_e(),{appId:i}=Se(),{user:l,isScopeLocked:o}=le(),d=`${i}:${l?.id||""}`,n=r.useRef(null);n.current?.key!==d&&(n.current={key:d});const f=n.current,g=r.useRef(null),x=()=>n.current===f;r.useEffect(()=>(n.current=f,()=>{n.current===f&&(n.current=null)}),[f]);const[t,h]=r.useState(null),[u,b]=r.useState(null),y=r.useRef(u);y.current=u;const[_,m]=r.useState(null),[C,w]=r.useState("html"),[p,N]=r.useState(""),[$,D]=r.useState(""),[P,O]=r.useState(!1),[k,A]=r.useState(""),[I,c]=r.useState(null),E=r.useRef(null),[K,ee]=r.useState(null),V=r.useRef(null);function ue(){return Promise.reject(Error("Publish this app to take real submissions. Drafts do not send intake."))}function pe(a){return V.current?Promise.reject(Error("Finish choosing the current list first.")):new Promise((S,q)=>{V.current={resolve:S,reject:q},ee({kind:a})})}function he(a,S){S?V.current?.reject(S):V.current?.resolve(a),V.current=null,ee(null)}r.useEffect(()=>()=>{E.current?.reject(Error("The draft changed or closed.")),E.current=null},[f,u?.source]),r.useEffect(()=>{c(null)},[f,u?.source]);
39function me(a){return R?Promise.reject(Error("Save the draft before testing a connected action.")):E.current?Promise.reject(Error("Finish the current action review first.")):new Promise((S,q)=>{E.current={resolve:S,reject:q},c({...a,draft:!0})})}function fe(a,S){S?E.current?.reject(S):E.current?.resolve(a),E.current=null,c(null)}const se=a=>Re(a,{origin:window.location.origin,partnerWorkspace:o}),X=se(`/a/${i}`),R=t&&u&&JSON.stringify({name:t.name,description:t.description,source:t.source})!==JSON.stringify(u),W=(a,S=!1)=>{!x()||a.app_id!==i||(g.current=f,h(a),S||b({name:a.name,description:a.description,source:a.source}))};r.useEffect(()=>{let a=!1;return h(null),b(null),N(""),A(""),O(!1),D(""),j.get(i).then(S=>{a||W(S.app)}).catch(S=>{a||N(S.message)}),()=>{a=!0}},[i,l?.id]),r.useEffect(()=>{if(!R)return;const a=S=>{S.preventDefault(),S.returnValue=""};return window.addEventListener("beforeunload",a),()=>window.removeEventListener("beforeunload",a)},[R]);async function T(a,S){const q=y.current;O(!0),N(""),D("");try{const B=await a();return x()?(B?.app&&W(B.app,y.current!==q),S!==null&&D(S||""),!0):!1}catch(B){return x()&&N(B.message),!1}finally{x()&&O(!1)}}async function G(a){await T(async()=>{if(await j.lifecycle(i,{...a,revision:t.revision}),!!x()){if(a.action==="transfer"){s("/apps");return}return j.get(i)}},"App updated.")}async function ge(){await T(async()=>{let a=0;const S=[];do{const ie=await j.audit(i,a);S.push(...ie.events),a=ie.next_cursor}while(a);if(!x())return;const q=URL.createObjectURL(new Blob([JSON.stringify(S,null,2)],{type:"application/json"})),B=document.createElement("a");B.href=q,B.download=`studio-app-${i}-audit.json`,B.click(),setTimeout(()=>URL.revokeObjectURL(q),1e3)},"Audit exported.")}async function ve(a){a.preventDefault();const S=new FormData(a.currentTarget);await T(async()=>{const q=await j.invite(i,{email:S.get("email"),role:S.get("role"),send_email:S.get("send_email")==="on",revision:t.revision});if(x())return A(se(q.invitation_path)),D(q.email_delivery==="queued"?"Invitation queued for email delivery.":q.email_delivery==="failed"?"Email could not be queued. Copy the invitation link or create a new invitation to retry.":q.email_delivery==="not_configured"?"Email is not configured. Copy the invitation link to share it.":"Invitation link created."),j.get(i)},null)}async function te(a){try{await navigator.clipboard.writeText(a),D("Link copied.")}catch{D("Select the link below and copy it.")}}if(!t||!u||t.app_id!==i||g.current!==f)return e.jsxs("main",{className:"studio-apps-page",children:[e.jsx(H,{to:"/apps",children:"Back to apps"}),e.jsx("p",{role:p?"alert":"status",children:p||"Loading your app…"})]});const L=t.kind==="pilot",xe=L||t.outcome?"app":"journey",Y=_||xe,je=L?["app","preview"]:[t.outcome?"app":"journey","chat","preview","code","connections"];return e.jsxs("main",{className:"studio-apps-page studio-app-builder",children:[e.jsxs("header",{className:"studio-apps-heading",children:[e.jsxs("div",{children:[e.jsxs(H,{
39className:"studio-app-back",to:"/apps",children:[e.jsx(Ne,{size:14}),"Apps"]}),e.jsx("h1",{children:t.name}),e.jsxs("p",{children:[R?"Unsaved draft changes":"Saved to Studio"," · ",t.archived?"Archived":t.published_version?`Published v${t.published_version}`:"Private draft"]})]}),e.jsxs("div",{className:"studio-apps-actions",children:[!L&&e.jsx(v,{disabled:!R||P,onClick:()=>T(()=>j.update(i,{...u,revision:t.revision}),"Draft saved."),iconLeft:e.jsx(ze,{size:15}),children:"Save draft"}),!L&&e.jsx(v,{disabled:R||P||t.archived,onClick:()=>T(()=>j.build(i,t.revision),"Build finished. Review the logs below."),children:"Build & test"}),t.role==="owner"&&e.jsx(v,{variant:"primary",disabled:R||P||t.archived||!L&&t.build?.status!=="passed",onClick:()=>T(()=>j.publish(i,t.revision),"Published. Your app link now opens this version."),children:"Publish"}),t.published_version&&e.jsx(v,{as:"a",href:X,target:"_blank",rel:"noopener noreferrer",iconRight:e.jsx(Oe,{size:14}),children:"Open app"})]})]}),p&&e.jsxs("div",{role:"alert",className:"studio-apps-error",children:[p,e.jsx(v,{size:"sm",disabled:P,onClick:()=>T(()=>j.get(i),"Reloaded the latest app. Local unsaved edits were discarded."),children:"Reload saved app"})]}),$&&e.jsx("p",{role:"status",className:"studio-apps-notice",children:$}),e.jsx(re,{className:"studio-apps-tabs",variant:"underline",ariaLabel:"App builder",items:[...je,...t.role==="owner"?["access"]:[]].map(a=>({id:a,label:a[0].toUpperCase()+a.slice(1)})),activeId:Y,onChange:m}),t.build&&!L&&e.jsxs("details",{className:"studio-app-build-log",children:[e.jsxs("summary",{children:["Last build · ",t.build.status," · ",new Date(t.build.checked_at).toLocaleString()]}),e.jsx("pre",{children:t.build.logs.join(`
40`)}),e.jsx("p",{children:"Builds check startup errors. Review forms and interactions in Preview before publishing."})]}),Y==="app"&&L&&e.jsx(He,{app:t,busy:P,action:T},d),Y==="app"&&!L&&t.outcome&&e.jsx(Ge,{app:t,dirty:R,busy:P,sync:a=>W(a,!0)},`${i}:${l?.id}`),Y==="journey"&&!L&&!t.outcome&&e.jsx(Ve,{app:t,dirty:R,busy:P,sync:a=>W(a,!0),action:T},`${i}:${l?.id}`),!L&&e.jsx("div",{hidden:_!=="chat",children:e.jsx(Me,{app:t,dirty:R,busy:P,sync:a=>W(a,!0),apply:()=>T(()=>j.applyProposal(i,t.revision),"Proposal saved to the draft. Build and test before publishing.")},`${i}:${l?.id}`)}),_==="connections"&&!L&&e.jsx(Qe,{app:t,busy:P,dirty:R,action:T,changeSource:a=>{x()&&b(S=>({...S,source:a}))}},d),_==="preview"&&L&&e.jsx("div",{className:"studio-app-pilot-preview",children:e.jsx(r.Suspense,{fallback:e.jsx("p",{role:"status",children:"Loading the preview…"}),children:e.jsx(Ze,{appId:`draft:${i}`,orgId:t.mcp_org_id,pilot:t.pilot,preview:!0},`${d}:${t.revision}`)})}),_==="preview"&&!L&&e.jsxs(e.Fragment,{children:[u.source.format==="react"&&(R||t.build?.status!=="passed")?e.jsxs("section",{className:"studio-apps-card",children:[e.jsx("h2",{children:"Compile your React app"}),e.jsx("p",{children:"Save this draft, then choose Build & test to compile React and TypeScript and see the preview."})]}):e.jsx(ce,{source:u.source.format==="react"?t.build.source:u.source,title:`${u.name} draft preview`,onAction:me,onPick:pe,onSubmit:ue,actions:Ie(t),journey:t.journey||null,outcome:t.outcome||null,intake:t.public_intake?.enabled?{questions:t.public_intake.questions}:null}),e.jsx("p",{className:"studio-apps-note",children:"Connected actions can be tested here after saving, with your review before each real call. Studio checks permissions, usage charges, and approvals for agent previews too."})]}),_==="code"&&!L&&e.jsxs("section",{className:"studio-app-code",children:[e.jsxs("aside",{className:"studio-apps-card",children:[e.jsx("h2",{children:"Page details"}),e.jsx(z,{label:"App name",maxLength:100,value:u.name,onChange:a=>b({...u,name:a.target.value})}),e.jsx(F,{label:"Description",maxLength:500,value:u.description,onChange:a=>b({...u,description:a.target.value})}),e.jsxs(U,{label:"Page format",value:u.source.format||"html",onChange:a=>b({...u,source:{...u.source,format:a.target.value}}),children:[e.jsx("option",{value:"html",children:"HTML + JavaScript"}),e.jsx("option",{value:"react",children:"React + TypeScript (TSX)"})]}),e.jsx("p",{className:"studio-apps-note",children:"React imports: react, react-dom/client, and react/jsx-runtime. Mount your component in an HTML element such as #root. Unsupported imports appear in the build log."})]}),e.jsxs("div",{className:"studio-app-source",children:[e.jsx(re,{className:"studio-apps-tabs",variant:"underline",ariaLabel:"Source files",items:[["html","index.html"],["css","styles.css"],["javascript",u.source.format==="react"?"app.tsx":"app.js"]].map(([a,S])=>({id:a,label:S})),activeId:C,onChange:w}),e.jsx(F,{className:"studio-app-code-editor",spellCheck:!1,"aria-label":`${C} source code`,value:u.source[C],onChange:a=>
40b({...u,source:{...u.source,[C]:a.target.value}})})]})]}),_==="access"&&e.jsxs("div",{className:"studio-app-access",children:[e.jsxs("section",{className:"studio-apps-card",children:[e.jsxs("h2",{children:[e.jsx(Ce,{size:18}),"Access to this app"]}),e.jsx("p",{children:"Choose who can open this page. Agent actions always require a signed-in Studio user with the required permissions."}),e.jsxs(U,{label:"Audience",value:t.audience,disabled:R||P,onChange:a=>T(()=>j.access(i,{audience:a.target.value,revision:t.revision}),"App access updated."),children:[e.jsx("option",{value:"private",children:"Private — owner and org admins"}),e.jsx("option",{value:"invited",children:"Invited people"}),e.jsx("option",{value:"org",children:"Organization members"}),e.jsx("option",{value:"public",children:"Public — requires org admin setting"})]}),e.jsxs("label",{className:"studio-app-toggle",children:[e.jsx(J,{type:"checkbox",checked:!!t.listed,disabled:R||P||t.archived,onChange:a=>T(()=>j.access(i,{audience:t.audience,listed:a.target.checked,revision:t.revision}),a.target.checked?"Listed under Use cases for people who can open this app.":"Removed from Use cases.")}),"List under Use cases"]}),e.jsx("p",{className:"studio-apps-note",children:"Listed apps appear on the Use cases page beside Studio’s guided journeys, only for people this app is shared with and only while a version is published."}),e.jsxs("label",{className:"studio-app-toggle",children:[e.jsx(J,{type:"checkbox",checked:Ae(t),disabled:R||P||t.archived,onChange:a=>T(()=>j.access(i,{audience:t.audience,configured:a.target.checked,revision:t.revision}),a.target.checked?"Shown under Configured Apps for people who can open this app.":"Removed from Configured Apps.")}),"Show under Configured Apps"]}),e.jsx("p",{className:"studio-apps-note",children:"Configured Apps in the Studio sidebar lists this app for people who can open it. Search pilots start on; page apps start off and appear once a version is published."}),e.jsxs("div",{children:["Direct app URL",e.jsxs("div",{className:"studio-app-link",children:[e.jsx(z,{"aria-label":"Direct app URL",readOnly:!0,value:X}),e.jsx(v,{size:"sm",onClick:()=>te(X),iconLeft:e.jsx(Pe,{size:14}),children:"Copy"})]})]}),e.jsx("p",{className:"studio-apps-note",children:"Opens this app directly. Visitors can choose Open Studio to see apps shared with them. New versions use the same URL."})]}),e.jsxs("section",{className:"studio-apps-card",children:[e.jsx("h2",{children:"Invite someone to this app"}),e.jsxs("p",{children:["“You’ve been invited to Studio to access ",t.name,".”"]}),e.jsxs("form",{className:"studio-app-invite-form",onSubmit:ve,children:[e.jsx(z,{name:"email",type:"email",required:!0,placeholder:"[email protected]","aria-label":"Invitation email"}),e.jsxs(U,{name:"role","aria-label":"App role",children:[e.jsx("option",{value:"use",children:"Can use"}),e.jsx("option",{value:"edit",children:"Can edit"})]}),e.jsxs("label",{className:"studio-app-toggle",children:[e.jsx(J,{type:"checkbox",name:"send_email",defaultChecked:!0}),"Send invitation email"]}),e.jsx(v,{type:"submit",disabled:P||R||t.archived,children:"Invite"})]}),e.jsx("p",{className:"studio-apps-note",children:"Links expire after 7 days. This invitation grants app access. Joining the organization requires a separate invitation, and external guests must be enabled by its admin."}),k&&e.jsxs("div",{children:["Invitation link",e.jsxs("div",{className:"studio-app-link",children:[e.jsx(z,{"aria-label":"Invitation link",readOnly:!0,value:k}),e.jsx(v,{onClick:()=>te(k),size:"sm",children:"Copy invitation"})]})]}),e.jsx("div",{className:"studio-app-members",children:t.grants?.map(a=>e.jsxs("div",{children:[e.jsxs("span",{children:[e.jsx("strong",{children:a.email}),e.jsxs("small",{children:[a.role==="edit"?"Can edit draft":"Can use"," · ",a.status==="pending"&&Date.parse(a.expires_at)<=Date.now()?"expired":a.status]})]}),a.status!=="revoked"&&e.jsxs(U,{"aria-label":`Role for ${a.email}`,value:a.role,disabled:P||R,onChange:S=>G({action:"role",grant_id:a.id,role:S.target.value}),children:[e.jsx("option",{value:"use",children:"Can use"}),e.jsx("option",{value:"edit",children:"Can edit"})]}),a.status!=="revoked"&&e.jsx(v,{size:"sm",disabled:P||R,onClick:()=>T(()=>j.revoke(i,a.id,t.revision),"App access revoked."),children:"Revoke"})]},a.id))}),e.jsx("p",{className:"studio-apps-note",children:"Editors can change the draft. Publishing and sharing stay with the owner and organization admins."})]}),e.jsx(Fe,{app:t,busy:P,dirty:R,action:T}),e.jsxs("section",{className:"studio-apps-card",children:[e.jsx("h2",{children:"Version history"}),e.jsx("p",{children:"Restore a previous version to the draft, then build and publish it."}),t.versions?.map(a=>e.jsxs("div",{className:"studio-app-version",children:[e.jsxs("span",{children:["Version ",a.version," · ",new Date(a.published_at).toLocaleStr
40ing()]}),e.jsx(v,{size:"sm",disabled:P||R,onClick:()=>G({action:"rollback",version:a.version}),children:"Restore to draft"})]},a.version)),e.jsx(v,{disabled:P,onClick:ge,children:"Export app audit"})]}),e.jsxs("section",{className:"studio-apps-card",children:[e.jsx("h2",{children:"App ownership and archive"}),e.jsxs("form",{onSubmit:a=>{a.preventDefault(),G({action:"transfer",user_id:new FormData(a.currentTarget).get("user_id")})},children:[e.jsx(z,{label:"Transfer to an active organization member",name:"user_id",required:!0,placeholder:"Organization member user ID"}),e.jsx(v,{type:"submit",disabled:P||R,children:"Transfer ownership"})]}),e.jsx("p",{children:"Archiving takes the app offline and revokes its invitations. Restoring keeps it private until you publish again."}),e.jsx(v,{disabled:P||R,onClick:()=>G({action:t.archived?"restore":"archive"}),children:t.archived?"Restore app":"Archive app"})]}),t.published_version&&e.jsxs("section",{className:"studio-apps-card",children:[e.jsx("h2",{children:"Take this app offline"}),e.jsx("p",{children:"Unpublishing disables the app URL and preserves the draft and saved versions."}),e.jsx(v,{variant:"danger",disabled:P||R,onClick:()=>T(()=>j.unpublish(i,t.revision),"App unpublished."),children:"Unpublish app"})]})]}),I&&e.jsx($e,{appId:i,request:I,settle:fe},`${d}:${t.revision}`),K&&e.jsx(Le,{orgId:t.mcp_org_id,kind:K.kind,settle:he},`${d}:${K.kind}`)]})}export{ps 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.