const __vite__mapDeps=(i,m=__vite__mapDeps,d=(m.f||(m.f=["assets/index-rvuS68Al.js","assets/vendor-mini-lit-Cx886NBU.js","assets/vendor-lit-BtHfzs80.js","assets/vendor-lucide-DBEJLfdn.js","assets/vendor-marked-_iteVaMm.js","assets/vendor-sortable-B1o3v0Qs.js","assets/index-BXulo2kC.css","assets/dialogs-DeLdzEM7.js"])))=>i.map(i=>d[i]);
import{r as l,A as ie,B as re,g as q,C as le,e as z,D as ce,E as de,_ as y,F as K,G as pe,H as ue,s as x,I as fe}from"./index-rvuS68Al.js";import{b as r,A as ve}from"./vendor-lit-BtHfzs80.js";import{a as h,B,I as me}from"./vendor-mini-lit-Cx886NBU.js";import{g as T,r as be,a as X,c as G,b as H,d as ge,i as he,e as Z,s as $e}from"./config-scope-psrVBNWL.js";import{renderModelRow as we}from"./settings-page-ClHvgmN2.js";import{r as J,T as N,P as ee,j as ye}from"./vendor-lucide-DBEJLfdn.js";import"./vendor-marked-_iteVaMm.js";import"./vendor-sortable-B1o3v0Qs.js";import"./workflow-page-CU9GxoWV.js";import"./dialogs-DeLdzEM7.js";import"./ModelSelector-DvyX4Tfh.js";import"./ident-CvQrffF1.js";import"./edit-CLPUkaSB.js";import"./Input-BnVujzeE.js";import"./ImageModelSelector-DZVWQjXD.js";function F(e,s=40,t=0,o=0){const a=e&&e!=="none"?`bobbit-${e==="crown"?"crowned":e}`:"";return fe({accClass:a,size:s,hueIndex:t,phaseIndex:o})}const W=[{value:"",label:"Use tool default"},{value:"allow",label:"Allow"},{value:"ask",label:"Ask"},{value:"never",label:"Never"}],Y={allow:"Allow",ask:"Ask",never:"Never"};let b="list",p=[],j=[],i=null,P=!0,S="",C="",L="none",M="",c={},O="",E="",f="prompt",$=!1,w=!1,D={},R=new Set,k=[],u="baseline",_=new Map,V=new Map;function ke(e,s){if(c[e])return c[e];const t=e.split("__");if(t.length>=3){const a=t.slice(0,2).join("__");if(c[a])return c[a]}if(c[s])return c[s];const o=j.find(a=>a.name===e);return o?.grantPolicy?o.grantPolicy:D[s]?D[s]:"allow"}function Pe(e,s){if(c[e])return"role override";const t=e.split("__");if(t.length>=3){const a=t.slice(0,2).join("__");if(c[a])return`from ${a}`}return c[s]?`from ${s} role override`:j.find(a=>a.name===e)?.grantPolicy?"tool default":D[s]?"group default":"system default"}async function v(){const e=T(),s=e?`/api/roles?projectId=${encodeURIComponent(e)}`:"/api/roles";try{const t=await q(s);if(!t.ok)return[];const o=await t.json();return o.roles||o||[]}catch{return[]}}async function Ze(){b="list",i=null,P=!0,$=!1,w=!1,l();const[e,s,t]=await Promise.all([v(),ie(),re()]);p=e,j=s,D=t,P=!1,l()}function Ne(){b="list",i=null,P=!0,$=!1,w=!1}function A(){b="list",i=null,z("roles")}function te(e){b="edit",i=e,S=e.label,C=e.promptTemplate,L=e.accessory,M=e.name,c={...e.toolPolicies??{}},O=e.model??"",E=e.thinkingLevel??"",f="prompt",$=!1,w=!1,R=new Set(j.map(s=>s.group||"Other")),u="baseline",_=new Map,V=new Map,e.name==="assistant"?le().then(s=>{k=s,_=new Map(s.map(t=>[t.type,t.prompt])),V=new Map(s.map(t=>[t.type,t.prompt])),l()}):k=[]}function m(e){te(e),z("role-edit",e.name)}function et(e){const s=p.find(t=>t.name===e);s?te(s):(b="list",i=null),l()}async function se(){if(!x.creatingSession){x.creatingSession=!0,l();try{const e={assistantType:"role"},s=T();if(s){e.projectId=s;const n=x.projects.find(d=>d.id===s);n&&(e.cwd=n.rootPath)}const t=await q("/api/sessions",{method:"POST",body:JSON.stringify(e)});if(!t.ok){const{errorFromResponse:n}=await y(async()=>{const{errorFromResponse:d}=await import("./index-rvuS68Al.js").then(I=>I.bj);return{errorFromResponse:d}},__vite__mapDeps([0,1,2,3,4,5,6]));throw await n(t,`Session creation failed: ${t.status}`)}const{id:o}=await t.json(),{connectToSession:a}=await y(async()=>{const{connectToSession:n}=await import("./index-rvuS68Al.js").then(d=>d.bk);return{connectToSession:n}},__vite__mapDeps([0,1,2,3,4,5,6]));await a(o,!1,{assistantType:"role"})}catch(e){const{showConnectionError:s}=await y(async()=>{const{showConnectionError:d}=await import("./dialogs-DeLdzEM7.js");return{showConnectionError:d}},__vite__mapDeps([7,0,1,2,3,4,5,6])),{errorDetails:t}=await y(async()=>{const{errorDetails:d}=await import("./index-rvuS68Al.js").then(I=>I.bj);return{errorDetails:d}},__vite__mapDeps([0,1,2,3,4,5,6])),{message:o,code:a,stack:n}=t(e);s("Failed to create role assistant",o,{code:a,stack:n})}finally{x.creatingSession=!1,l()}}}async function _e(){if($=!0,l(),i){const e=T(),s=await pe(i.name,{label:S,promptTemplate:C,accessory:L,toolPolicies:Object.keys(c).length>0?c:{},model:O,thinkingLevel:E},e||void 0),t=Array.from(_.entries()).filter(([o,a])=>a!==(V.get(o)??""));if(t.length>0&&await Promise.all(t.map(([o,a])=>ue(o,a))),s){const[o]=await Promise.all([v()]);p=o;const a=p.find(n=>n.name===i.name);a?m(a):A();return}}$=!1,l()}async function Ae(){if(!i)return;const{confirmAction:e}=await y(async()=>{const{confirmAction:o}=await import("./dialogs-DeLdzEM7.js");return{confirmAction:o}},__vite__mapDeps([7,0,1,2,3,4,5,6]));if(!await e("Delete Role",`Are you sure you want to delete "${i.label}"? This cannot be undone.`,"Delete",!0))return;if(w=!0,l(),await K(i.name,T()||void 0)){const[o]=await Promise.all([v()]);p=o,A()}else w=!1,l()}function Te(){if(b!=="list"&&i){const e=Array.from(_.entries()).some(([n,d])=>d!==(V.get(n)??"")),s=JSON.stringify(c)!==JSON.stringify(i?.toolPolicies??{}),t=(O||"")!==(i?.model||""),o=(E||"")!==(i?.thinkingLevel||""),a=i&&(S!==i.label||C!==i.promptTemplate||L!==i.accessory||s||t||o||e);return r`
			<div class="roles-nav">
				<div class="roles-nav-left">
					<button class="roles-back" @click=${A} title="Back to roles">
						${h(J,"sm")}
					</button>
					<div class="roles-title-group">
						<span class="roles-breadcrumb" @click=${A}>Roles</span>
						<span class="roles-breadcrumb-sep">/</span>
						<h1 class="roles-title">${i.label}</h1>
					</div>
				</div>
				<div class="roles-nav-right">
					${B({variant:"ghost",size:"sm",onClick:Ae,disabled:w,className:"text-destructive hover:text-destructive hover:bg-destructive/10",children:r`<span class="inline-flex items-center gap-1">${h(N,"sm")} ${w?"Deleting…":"Delete"}</span>`})}
					<span data-testid="role-save-btn">${B({variant:"default",size:"sm",onClick:_e,disabled:$||!a,children:$?"Saving…":"Save"})}</span>
				</div>
			</div>
		`}return r`
		<div class="roles-nav">
			<div class="roles-nav-left">
				<button class="roles-back" @click=${()=>z("landing")} title="Back to sessions">
					${h(J,"sm")}
				</button>
				<h1 class="roles-title">Roles</h1>
			</div>
			<div class="roles-nav-right">
				${B({variant:"default",size:"sm",onClick:se,children:r`<span class="inline-flex items-center gap-1.5 font-semibold">${h(ee,"sm")} New Role</span>`})}
			</div>
		</div>
	`}async function Re(e){const{confirmAction:s}=await y(async()=>{const{confirmAction:a}=await import("./dialogs-DeLdzEM7.js");return{confirmAction:a}},__vite__mapDeps([7,0,1,2,3,4,5,6]));if(!await s("Delete Role",`Are you sure you want to delete "${e.label}"? This cannot be undone.`,"Delete",!0))return;if(await K(e.name,T()||void 0)){const[a]=await Promise.all([v()]);p=a,l()}}async function Se(e){$e(e),P=!0,l(),p=await v(),P=!1,l()}function Ce(e,s){const t=e.origin,o=e.overrides,a=he(t);return r`
		<div class="role-row ${a?"config-item-inherited":""}" tabindex="0" role="button" @click=${()=>m(e)} @keydown=${n=>{(n.key==="Enter"||n.key===" ")&&(n.preventDefault(),m(e))}}>
			${F(e.accessory??"none",42,s,s)}
			<div class="role-row-info">
				<span class="role-row-label">${e.label}</span>
				<span class="role-row-slug">${e.name} ${X(t,o)}</span>
			</div>
			<div class="role-row-actions">
				<button class="role-row-action-btn" @click=${n=>{n.stopPropagation(),m(e)}} title="Edit">
					${h(ye,"sm")}
				</button>
				<button class="role-row-action-btn delete" @click=${n=>{n.stopPropagation(),Re(e)}} title="Delete">
					${h(N,"sm")}
				</button>
			</div>
		</div>
	`}function Le(){return P?r`
			<div class="roles-loading">
				<svg class="animate-spin" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
					<path d="M21 12a9 9 0 1 1-6.219-8.56"></path>
				</svg>
				<span>Loading roles\u2026</span>
			</div>
		`:p.length===0?r`
			<div class="roles-empty">
				<div class="roles-empty-bobbit">${F("none",52)}</div>
				<p class="roles-empty-title">No roles yet</p>
				<p class="roles-empty-desc">Roles give agents a persona, system prompt, and tool restrictions.</p>
				${B({variant:"default",onClick:se,children:r`<span class="inline-flex items-center gap-1.5">${h(ee,"sm")} Create your first role</span>`})}
			</div>
		`:r`
		<p class="text-sm text-muted-foreground mb-6" style="max-width: 600px; margin-inline: auto;">Roles define what an agent can do \u2014 its system prompt and which tools it has access to. Bobbit includes built-in roles (coder, reviewer, tester) and you can create custom ones.</p>
		<div class="roles-list">
			${p.map((e,s)=>Ce(e,s))}
		</div>
	`}function Q(e,s){if(s)c={...c,[e]:s};else{const{[e]:t,...o}=c;c=o}l()}function Oe(e){R.has(e)?R.delete(e):R.add(e),l()}function Ee(){const e=new Map;for(const t of j){const o=t.group||"Other",a=e.get(o)||[];a.push(t),e.set(o,a)}const s=r`<svg class="roles-access-group-chevron" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="m6 9 6 6 6-6"/></svg>`;return r`
		<p class="roles-tools-note">Set per-tool access policies for this role. Tools left at "Use default" inherit from tool, group, or system defaults.</p>
		<div class="roles-access-list">
			${Array.from(e.entries()).map(([t,o])=>{const a=R.has(t);return r`
					<div class="roles-access-group ${a?"collapsed":""}">
						<div class="roles-access-group-header" @click=${()=>Oe(t)}>
							${s}
							<span class="roles-access-group-name">${t}</span>
							<span class="roles-access-group-count">${o.length} tool${o.length!==1?"s":""}</span>
							<span class="roles-access-group-policy-label">Group Policy:</span>
							<select class="roles-access-group-select"
								.value=${c[t]||""}
								@click=${n=>n.stopPropagation()}
								@change=${n=>{n.stopPropagation(),Q(t,n.target.value)}}
							>
								<option value="" ?selected=${!c[t]}>Use tool default</option>
								${W.filter(n=>n.value!=="").map(n=>r`
									<option value=${n.value} ?selected=${c[t]===n.value}>${n.label}</option>
								`)}
							</select>
							<span class="roles-access-group-hint">${(()=>{const n=D[t]||"allow",d=Y[n]||n;return r`\u2192 ${d} [system default]`})()}</span>
						</div>
						<div class="roles-access-group-items">
							${o.map(n=>{const d=c[n.name]||"",oe=!!c[t]?"Use group role default":"Use tool default",U=ke(n.name,t),ae=Y[U]||U,ne=Pe(n.name,t);return r`
									<div class="roles-access-row">
										<span class="roles-access-row-label" title="${n.description}">${n.name}</span>
										<select
											class="roles-access-row-select"
											.value=${d}
											@change=${g=>Q(n.name,g.target.value)}
										>
											<option value="" ?selected=${!d}>${oe}</option>
											${W.filter(g=>g.value!=="").map(g=>r`
												<option value=${g.value} ?selected=${d===g.value}>${g.label}</option>
											`)}
										</select>
										<span class="roles-access-row-hint">\u2192 ${ae} [${ne}]</span>
									</div>
								`})}
						</div>
					</div>
				`})}
		</div>
	`}function De(){return r`
		${M==="assistant"&&k.length>0?r`
			<div class="roles-prompt-tabs">
				<button
					class="roles-prompt-tab ${u==="baseline"?"roles-prompt-tab--active":""}"
					@click=${()=>{u="baseline",l()}}
				>Shared Baseline</button>
				${k.map(e=>r`
					<button
						class="roles-prompt-tab ${u===e.type?"roles-prompt-tab--active":""}"
						@click=${()=>{u=e.type,l()}}
					>${e.title.replace(" Assistant","").replace(" Wizard","")}</button>
				`)}
			</div>
		`:ve}
		${u==="baseline"||M!=="assistant"||k.length===0?r`
			<textarea
				class="roles-prompt-editor"
				.value=${C}
				placeholder="Markdown system prompt template. Supports {{GOAL_BRANCH}} and {{AGENT_ID}} placeholders."
				@input=${e=>{C=e.target.value}}
			></textarea>
		`:r`
			<p class="roles-prompt-hint">This prompt is appended after the shared baseline for ${k.find(e=>e.type===u)?.title??u} sessions.</p>
			<textarea
				class="roles-prompt-editor"
				.value=${_.get(u)??""}
				@input=${e=>{_.set(u,e.target.value),l()}}
			></textarea>
		`}
	`}function je(){return r`
		<p class="roles-tools-note" data-testid="roles-model-tab">
			Overrides the global default for sessions running as this role. Leave blank to inherit.
		</p>
		${we("Model","When set, sessions assuming this role bind to this model on first turn. Empty = inherit default.sessionModel (or default.reviewModel for reviewer/QA sessions).",O,e=>{O=e,l()},E,e=>{E=e,l()},"",{fallbackLabel:"(use default)"})}
	`}function Ie(){return r`
		<div class="roles-edit-container">
			<div class="roles-edit-main">
				<!-- Identity section -->
				<div class="roles-edit-section">
					<div class="flex items-center justify-between">
						<h2 class="roles-section-title">Identity</h2>
						<span class="inline-flex items-center gap-2">
							${X(i?.origin,i?.overrides)}
							${xe()}
						</span>
					</div>
					<div class="roles-identity-row">
						<div class="roles-edit-field">
							<label class="roles-field-label">Id</label>
							<div class="roles-field-readonly">${M}</div>
						</div>
						<div class="roles-edit-field" style="flex:1;min-width:0;">
							<label class="roles-field-label">Label</label>
							${me({value:S,placeholder:"e.g. Documentation Writer",onInput:e=>{S=e.target.value,l()}})}
						</div>
					</div>
				</div>

				<!-- Accessory selector -->
				<div class="roles-edit-section">
					<h2 class="roles-section-title">Accessory</h2>
					<div class="roles-accessory-grid">
						${ce.map((e,s)=>{const t=de(e);return r`
								<button
									class="roles-accessory-option ${L===e?"roles-accessory-option--selected":""}"
									title="${t.label}"
									@click=${()=>{L=e,l()}}
								>
									<span class="roles-accessory-preview">
										${F(e,42,s,s)}
									</span>
									<span class="roles-accessory-label">${t.label}</span>
								</button>
							`})}
					</div>
				</div>

				<!-- Tab bar -->
				<div class="roles-tab-bar">
					<button class="roles-tab ${f==="prompt"?"roles-tab--active":""}"
						@click=${()=>{f="prompt",l()}}>Prompt</button>
					<button class="roles-tab ${f==="tools"?"roles-tab--active":""}"
						@click=${()=>{f="tools",l()}}>Tool Access</button>
					<button class="roles-tab ${f==="model"?"roles-tab--active":""}"
						@click=${()=>{f="model",l()}} data-testid="roles-tab-model">Model</button>
				</div>

				<!-- Tab content -->
				<div class="roles-tab-content">
					${f==="prompt"?De():f==="tools"?Ee():je()}
				</div>
			</div>
		</div>
	`}function xe(){if(!i)return"";const e=i.origin;if(!e)return"";const s=Z(),t=T();if(s==="system"){if(e==="builtin")return r`<button class="config-action-btn" @click=${async()=>{if(await G("roles",i.name,"server")){p=await v();const o=p.find(a=>a.name===i.name);o&&m(o)}}}>Customize at Server Level</button>`;if(e==="server")return r`<button class="config-action-btn config-action-btn--revert" @click=${async()=>{if(await H("roles",i.name,"server")){p=await v();const o=p.find(a=>a.name===i.name);o?m(o):A()}}}>Revert to Builtin</button>`}else{if(e==="builtin"||e==="server")return r`<button class="config-action-btn" @click=${async()=>{if(await G("roles",i.name,"project",t)){p=await v();const o=p.find(a=>a.name===i.name);o&&m(o)}}}>Customize for ${ge()}</button>`;if(e==="project")return r`<button class="config-action-btn config-action-btn--revert" @click=${async()=>{if(await H("roles",i.name,"project",t)){p=await v();const o=p.find(a=>a.name===i.name);o?m(o):A()}}}>Revert to Inherited</button>`}return""}function tt(){return r`
		<div class="roles-container">
			${Te()}
			${b==="list"?be(Z(),Se):""}
			<div class="roles-body">
				${b==="list"?Le():Ie()}
			</div>
		</div>
	`}export{Ne as clearRolePageState,Ze as loadRolePageData,et as navigateToRoleEdit,tt as renderRoleManagerPage};
