citadel_cli 1.4.1 → 1.4.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,9 +1,9 @@
1
- (function(g,c){typeof exports=="object"&&typeof module<"u"?c(exports,require("react/jsx-runtime"),require("react"),require("react-dom/client")):typeof define=="function"&&define.amd?define(["exports","react/jsx-runtime","react","react-dom/client"],c):(g=typeof globalThis<"u"?globalThis:g||self,c(g.Citadel={},g.jsxRuntime,g.React,g.client))})(this,function(g,c,a,Me){"use strict";var ut=Object.defineProperty;var pt=(g,c,a)=>c in g?ut(g,c,{enumerable:!0,configurable:!0,writable:!0,value:a}):g[c]=a;var C=(g,c,a)=>pt(g,typeof c!="symbol"?c+"":c,a);var j=(t=>(t.Pending="pending",t.Success="success",t.Failure="failure",t.Timeout="timeout",t))(j||{});class _{constructor(e=Date.now()){C(this,"_status","pending");this.timestamp=e}get status(){return this._status}markSuccess(){this._status="success"}markFailure(){this._status="failure"}markTimeout(){this._status="timeout"}}class oe extends _{constructor(e,n){super(n),this.data=e}render(){return c.jsx("pre",{className:"citadel-result-json",children:JSON.stringify(this.data,null,2)})}}class q extends _{constructor(e,n){super(n),this.text=e}render(){return c.jsx("div",{className:"citadel-result-text",children:this.text})}}class ie extends _{constructor(e,n="true",s="false",r){super(r),this.value=e,this.trueText=n,this.falseText=s}render(){return c.jsx("div",{className:"citadel-result-text citadel-result-boolean",children:this.value?this.trueText:this.falseText})}}class Z extends _{constructor(e,n){super(n),this.error=e,this.markFailure()}render(){return c.jsx("div",{className:"citadel-result-error",children:this.error})}}class le extends _{render(){return c.jsx("div",{className:"citadel-result-pending",children:"..."})}}class ce extends _{constructor(e,n="",s){super(s),this.imageUrl=e,this.altText=n}render(){return c.jsx("div",{className:"citadel-result-image-wrap",children:c.jsx("img",{src:this.imageUrl,alt:this.altText,className:"citadel-result-image"})})}}const Pe=t=>async function(){const n=t.commands.filter(s=>s.fullPath[0]!=="help").map(s=>{const i=`${s.segments.map(d=>d.type==="argument"?`<${d.name}>`:d.name).join(" ")} - ${s.description}`,o=s.segments.filter(d=>d.type==="argument"&&d.description).map(d=>` <${d.name}>: ${d.description}`);return{commandLine:i,argumentLines:o}}).sort((s,r)=>s.commandLine.localeCompare(r.commandLine)).flatMap(s=>[s.commandLine,...s.argumentLines]);return n.length===0?new q("No commands available yet. Add some commands to get started!"):(n.push("help - Show available commands"),new q(`Available Commands:
2
- `+n.join(`
3
- `)))};var R=(t=>(t[t.NONE=0]="NONE",t[t.ERROR=1]="ERROR",t[t.WARN=2]="WARN",t[t.INFO=3]="INFO",t[t.DEBUG=4]="DEBUG",t[t.TRACE=5]="TRACE",t))(R||{});const de=!0;class x{static configure(e){this.level=e.level,this.prefix=e.prefix||"[Citadel]"}static trace(...e){this.level>=5&&!de&&console.trace(this.prefix,...e)}static debug(...e){this.level>=4&&!de&&console.debug(this.prefix,...e)}static info(...e){this.level>=3&&console.info(this.prefix,...e)}static warn(...e){this.level>=2&&console.warn(this.prefix,...e)}static error(...e){this.level>=1&&console.error(this.prefix,...e)}}C(x,"level",0),C(x,"prefix","");const k={commandTimeoutMs:1e4,cursorColor:"var(--cursor-color, #fff)",cursorSpeed:530,cursorType:"blink",includeHelpCommand:!0,fontFamily:"monospace",fontSize:"0.875rem",initialHeight:"50vh",logLevel:R.ERROR,maxHeight:"80vh",minHeight:"200",outputFontSize:"0.875rem",resetStateOnHide:!1,closeOnEscape:!0,showCitadelKey:".",showOnLoad:!1,displayMode:"panel",storage:{type:"localStorage",maxCommands:100}},me=async()=>new q("");class ee{constructor(e,n,s){this.type=e,this.name=n,this.description=s}toString(){return this.name}}class te extends ee{constructor(){super("null",">null<","Empty segment")}}class ue extends ee{constructor(e,n){super("word",e,n)}}class U extends ee{constructor(e,n,s,r){super("argument",e,n),this.value=s,this.valid=r}}const He=t=>{if(t.type==="word")return new ue(t.name,t.description);if(t.type==="argument"){const e=t;return new U(e.name,e.description,e.value,e.valid)}return new te},H=t=>t.map(e=>He(e));class _e{constructor(e,n,s=me){C(this,"_segments");C(this,"_description");C(this,"_handler");this._segments=e,this._description=n,this._handler=s}get segments(){return this._segments}get description(){return this._description}get handler(){return this._handler}get hasArguments(){return this.segments.some(e=>e.type==="argument")}get fullPath(){return this.segments.map(e=>e.name)}get fullPath_s(){return this.fullPath.join(" ")}equals(e){return this.fullPath.join(" ")===e.fullPath.join(" ")}}class K{constructor(){C(this,"_commands",[])}get commands(){return this._commands}addCommand(e,n,s=me){if(e===void 0||e.length===0)throw new Error("Command path cannot be empty");const r=new _e(e,n,s),i=this._commands.find(o=>{const d=o.segments.map(u=>u.type==="argument"?"*":u.name).join(" "),l=e.map(u=>u.type==="argument"?"*":u.name).join(" ");return d===l});if(i)throw new Error(`Duplicate commands: '${i.fullPath_s}' and '${r.fullPath_s}'`);this._commands.push(r)}removeCommand(e){const n=e.join(" "),s=this._commands.findIndex(r=>r.fullPath.join(" ")===n);return s===-1?!1:(this._commands.splice(s,1),!0)}getCommand(e){return this._commands.find(n=>{const s=n.fullPath.join(" "),r=e.join(" ");if(s===r)return!0;const o=n.segments.filter(d=>d.type==="word").map(d=>d.name);return o.length===e.length&&o.join(" ")===r})}commandExistsForPath(e){const n=this._commands.map(r=>r.segments.map(i=>i.type==="argument"?"*":i.name).join(" ")),s=e.map((r,i)=>this._commands.some(d=>{var l;return((l=d.segments[i])==null?void 0:l.type)==="argument"})?"*":r).join(" ");return n.includes(s)}getCompletionNames(e){return this.getCompletions(e).map(n=>n.name)}getMatchingCompletions(e,n){const s=n.trim().toLowerCase(),r=this.getCompletions(e);return s?r.filter(i=>i.name.toLowerCase().startsWith(s)):r}getUniqueCompletion(e,n){const s=this.getMatchingCompletions(e,n);if(s.length===1)return s[0]}getCompletions(e){if(x.debug("[getCompletions] path: ",e),!e.length){const i=this._commands.map(l=>l.segments[0]),o=(l,u)=>l.type===u.type&&l.name===u.name;return i.filter((l,u,y)=>u===y.findIndex(p=>o(p,l)))}const n=e.length;return this._commands.filter(i=>{const o=i.segments;if(o.length<=n-1)return!1;for(let d=0;d<n;d++){const l=e[d],u=o[d];if(!(l==="*"&&u.type==="argument")&&l!==u.name)return!1}return!0}).filter(i=>i.segments.length>n).map(i=>{const o=i.segments[n],d=o.type==="argument"?U:ue;return new d(o.name,o.description)}).filter((i,o,d)=>o===d.findIndex(l=>l.type===i.type&&l.name===i.name))}hasNextSegment(e){return this.getCompletions(e).length>0}}class pe{constructor(e){C(this,"config");this.config={type:"localStorage",maxCommands:100,...e}}async addStoredCommand(e){const n=await this.getStoredCommands();for(n.push(e);n.length>this.config.maxCommands;)n.shift();await this.saveCommands(n)}}class Te extends pe{constructor(n){super(n);C(this,"storageKey","citadel_command_history")}async getStoredCommands(){try{const n=window.localStorage.getItem(this.storageKey);return n?JSON.parse(n).map(r=>({commandSegments:Array.isArray(r.commandSegments)?H(r.commandSegments):[],timestamp:r.timestamp})):[]}catch(n){return console.warn("Failed to load commands from localStorage:",n),[]}}async clear(){try{window.localStorage.removeItem(this.storageKey)}catch(n){console.warn("Failed to clear localStorage:",n)}}async saveCommands(n){try{const s=n.map(r=>({commandSegments:Array.isArray(r.commandSegments)?H(r.commandSegments).map(i=>({type:i.type,name:i.name,description:i.description,...i instanceof U?{value:i.value}:{}})):[],timestamp:r.timestamp}));window.localStorage.setItem(this.storageKey,JSON.stringify(s))}catch(s){throw console.warn("Failed to save commands to localStorage:",s),s}}}class he extends pe{constructor(n){super(n);C(this,"storedCommands",[])}async getStoredCommands(){return this.storedCommands.map(n=>({commandSegments:Array.isArray(n.commandSegments)?H(n.commandSegments):[],timestamp:n.timestamp}))}async clear(){this.storedCommands=[]}async saveCommands(n){this.storedCommands=n.map(s=>({commandSegments:Array.isArray(s.commandSegments)?H(s.commandSegments):[],timestamp:s.timestamp}))}}const z=class z{constructor(){C(this,"currentStorage")}static reset(){z.instance=void 0}static getInstance(){return z.instance||(z.instance=new z),z.instance}initializeStorage(e){try{e.type==="memory"?this.currentStorage=new he(e):this.currentStorage=new Te(e)}catch(n){console.warn("Failed to create storage, falling back to memory storage:",n),this.currentStorage=new he(e)}}getStorage(){if(!this.currentStorage)throw new Error("Storage not initialized. Call initializeStorage first.");return this.currentStorage}};C(z,"instance");let Y=z;class ge{constructor(){C(this,"segments",[]);C(this,"nullSegment",new te);C(this,"observers",[])}subscribe(e){this.observers.push(e)}unsubscribe(e){this.observers=this.observers.filter(n=>n!==e)}notifyObservers(){this.observers.forEach(e=>e.update())}clear(){this.segments=[],this.notifyObservers()}push(e){this.segments.push(e),this.notifyObservers()}pushAll(e){e.forEach(n=>this.push(n))}pop(){const e=this.segments.pop()||this.nullSegment;return this.notifyObservers(),e}peek(){return this.segments[this.segments.length-1]||this.nullSegment}size(){return this.segments.length}isEmpty(){return this.segments.length===0}get hasArguments(){return this.segments.some(e=>e.type==="argument")}get arguments(){return this.segments.filter(e=>e.type==="argument")}path(){return this.segments.map(e=>e.name)}toArray(){return[...this.segments]}}const ze={config:k,commands:new K,segmentStack:new ge},W=a.createContext(ze),De=({config:t=k,commandRegistry:e,children:n})=>{const[s,r]=a.useState(),[i]=a.useState(()=>new ge),o=a.useMemo(()=>({...k,...t,storage:{...k.storage,...t.storage},cursorType:t.cursorType??k.cursorType,cursorColor:t.cursorColor??k.cursorColor,cursorSpeed:t.cursorSpeed??k.cursorSpeed,closeOnEscape:t.closeOnEscape??k.closeOnEscape,showCitadelKey:t.showCitadelKey??k.showCitadelKey,showOnLoad:t.showOnLoad??k.showOnLoad}),[t]);a.useEffect(()=>{Y.getInstance().initializeStorage(o.storage??k.storage),r(Y.getInstance().getStorage())},[o.storage]),a.useEffect(()=>{if(e){if(o.includeHelpCommand){if(!e.commandExistsForPath(["help"])){const l=Pe(e);e.addCommand([{type:"word",name:"help"}],"Show available commands",l)}return}e.removeCommand(["help"])}},[e,o.includeHelpCommand]);const d=a.useMemo(()=>({config:o,commands:e||new K,storage:s,segmentStack:i}),[o,e,s,i]);return c.jsx(W.Provider,{value:d,children:n})},T=()=>{const t=a.useContext(W);if(t===void 0)throw new Error("useCitadelConfig must be used within a CitadelConfigProvider");return t.config},J=()=>{const t=a.useContext(W);if(t===void 0)throw new Error("useCitadelCommands must be used within a CitadelConfigProvider");return t.commands},fe=()=>{const t=a.useContext(W);if(t===void 0)throw new Error("useCitadelStorage must be used within a CitadelConfigProvider");return t.storage},B=()=>{const t=a.useContext(W);if(t===void 0)throw new Error("useSegmentStack must be used within a CitadelConfigProvider");return t.segmentStack},X=class X{constructor(e,n){C(this,"id");C(this,"timestamp");C(this,"command");C(this,"result");this.id=`output-${Date.now()}-${X.idCounter++}`,this.command=e.toArray().map(s=>s.type==="argument"?s.value||"":s.name),this.timestamp=Date.now(),this.result=n??new le}};C(X,"idCounter",0);let G=X;function Oe(t){return{commandSegments:H(t),timestamp:Date.now()}}function ye(){const t=fe(),[e,n]=a.useState({storedCommands:[],position:null}),s=a.useCallback(async d=>{if(t)try{const l=Oe(d);await t.addStoredCommand(l),n(u=>({...u,storedCommands:[...u.storedCommands,{...l,commandSegments:H(l.commandSegments)}],position:null}))}catch(l){console.warn("Failed to save command to history:",l)}},[t]),r=a.useCallback(async()=>t?(await t.getStoredCommands()).map(l=>({...l,commandSegments:H(l.commandSegments)})):[],[t]);a.useEffect(()=>{if(!t)return;(async()=>{try{const u=(await t.getStoredCommands()).map(y=>({...y,commandSegments:H(y.commandSegments)}));return n(y=>({...y,storedCommands:u})),u}catch(l){console.warn("Failed to load command history:",l)}})()},[t]);const i=a.useCallback(async d=>{const l=await r();if(l.length===0)return n(p=>({...p,storedCommands:[],position:null})),{segments:null,position:null};let u=null;if(d==="up"?e.position===null?u=l.length-1:e.position>0?u=e.position-1:u=0:e.position===null||e.position>=l.length-1?u=null:u=e.position+1,n(p=>({...p,storedCommands:l.map(f=>({...f,commandSegments:H(f.commandSegments)})),position:u})),u===null)return{segments:[],position:null};const y=l[u];return y?{segments:H(y.commandSegments),position:u}:{segments:[],position:null}},[e.position,r]),o=a.useCallback(async()=>{try{if(!t)return;await t.clear(),n({storedCommands:[],position:null})}catch(d){console.warn("Failed to clear command history:",d)}},[t]);return{history:e,addStoredCommand:s,getStoredCommands:r,navigateHistory:i,clear:o}}const ne=()=>{const t=T(),e=J(),n=ye(),s=B(),r=fe(),[i,o]=a.useState({currentInput:"",isEnteringArg:!1,output:[],history:{commands:[],position:null,storage:r}});a.useEffect(()=>{},[r]),a.useEffect(()=>{o(l=>({...l,history:{commands:n.history.storedCommands,position:n.history.position,storage:r}}))},[n.history,r]);const d={setCurrentInput:a.useCallback(l=>{x.debug("[CitadelActions] setCurrentInput: ",l),o(u=>({...u,currentInput:l}))},[]),setIsEnteringArg:a.useCallback(l=>{x.debug("[CitadelActions] setIsEnteringArg: ",l),o(u=>({...u,isEnteringArg:l}))},[]),addOutput:a.useCallback(l=>{x.debug("[CitadelActions]addOutput: ",l),o(u=>({...u,output:[...u.output,l]}))},[]),executeCommand:a.useCallback(async()=>{const l=s.path(),u=e.getCommand(l);if(!u){console.error("[CitadelActions][executeCommand] Cannot execute command because no command was found for the given path: ",l);return}const y=new G(s);o(p=>({...p,output:[...p.output,y]}));try{const p=new Promise((v,E)=>{setTimeout(()=>{E(new Error("Request timed out"))},t.commandTimeoutMs)}),f=s.arguments.map(v=>v.value||""),b=await Promise.race([u.handler(f),p]);if(!(b instanceof _))throw new Error(`The ${l.join(".")} command returned an invalid result type. Commands must return an instance of a CommandResult.
1
+ (function(g,c){typeof exports=="object"&&typeof module<"u"?c(exports,require("react/jsx-runtime"),require("react"),require("react-dom/client")):typeof define=="function"&&define.amd?define(["exports","react/jsx-runtime","react","react-dom/client"],c):(g=typeof globalThis<"u"?globalThis:g||self,c(g.Citadel={},g.jsxRuntime,g.React,g.client))})(this,function(g,c,o,Oe){"use strict";var wt=Object.defineProperty;var vt=(g,c,o)=>c in g?wt(g,c,{enumerable:!0,configurable:!0,writable:!0,value:o}):g[c]=o;var C=(g,c,o)=>vt(g,typeof c!="symbol"?c+"":c,o);var $=(n=>(n.Pending="pending",n.Success="success",n.Failure="failure",n.Timeout="timeout",n))($||{});class F{constructor(e=Date.now()){C(this,"_status","pending");this.timestamp=e}get status(){return this._status}markSuccess(){this._status="success"}markFailure(){this._status="failure"}markTimeout(){this._status="timeout"}}class de extends F{constructor(e,t){super(t),this.data=e}render(){return c.jsx("pre",{className:"citadel-result-json",children:JSON.stringify(this.data,null,2)})}}class q extends F{constructor(e,t){super(t),this.text=e}render(){return c.jsx("div",{className:"citadel-result-text",children:this.text})}}class me extends F{constructor(e,t="true",s="false",r){super(r),this.value=e,this.trueText=t,this.falseText=s}render(){return c.jsx("div",{className:"citadel-result-text citadel-result-boolean",children:this.value?this.trueText:this.falseText})}}class ne extends F{constructor(e,t){super(t),this.error=e,this.markFailure()}render(){return c.jsx("div",{className:"citadel-result-error",children:this.error})}}class ue extends F{render(){return c.jsx("div",{className:"citadel-result-pending",children:"..."})}}class pe extends F{constructor(e,t="",s){super(s),this.imageUrl=e,this.altText=t}render(){return c.jsx("div",{className:"citadel-result-image-wrap",children:c.jsx("img",{src:this.imageUrl,alt:this.altText,className:"citadel-result-image"})})}}const De=n=>async function(){const t=n.commands.filter(s=>s.fullPath[0]!=="help").map(s=>{const i=`${s.segments.map(d=>d.type==="argument"?`<${d.name}>`:d.name).join(" ")} - ${s.description}`,a=s.segments.filter(d=>d.type==="argument"&&d.description).map(d=>` <${d.name}>: ${d.description}`);return{commandLine:i,argumentLines:a}}).sort((s,r)=>s.commandLine.localeCompare(r.commandLine)).flatMap(s=>[s.commandLine,...s.argumentLines]);return t.length===0?new q("No commands available yet. Add some commands to get started!"):(t.push("help - Show available commands"),new q(`Available Commands:
2
+ `+t.join(`
3
+ `)))};var se=(n=>(n[n.NONE=0]="NONE",n[n.ERROR=1]="ERROR",n[n.WARN=2]="WARN",n[n.INFO=3]="INFO",n[n.DEBUG=4]="DEBUG",n[n.TRACE=5]="TRACE",n))(se||{});const he=!0;class k{static configure(e){this.level=e.level,this.prefix=e.prefix||"[Citadel]"}static trace(...e){this.level>=5&&!he&&console.trace(this.prefix,...e)}static debug(...e){this.level>=4&&!he&&console.debug(this.prefix,...e)}static info(...e){this.level>=3&&console.info(this.prefix,...e)}static warn(...e){this.level>=2&&console.warn(this.prefix,...e)}static error(...e){this.level>=1&&console.error(this.prefix,...e)}}C(k,"level",0),C(k,"prefix","");const E={commandTimeoutMs:1e4,cursorColor:"var(--cursor-color, #fff)",cursorSpeed:530,cursorType:"blink",includeHelpCommand:!0,fontFamily:"monospace",fontSize:"0.875rem",initialHeight:"50vh",logLevel:se.ERROR,maxHeight:"80vh",minHeight:"200",outputFontSize:"0.875rem",showOutputPane:!0,resetStateOnHide:!1,closeOnEscape:!0,showCitadelKey:".",showOnLoad:!1,displayMode:"panel",storage:{type:"localStorage",maxCommands:100}},ge=async()=>new q("");class re{constructor(e,t,s){this.type=e,this.name=t,this.description=s}toString(){return this.name}}class oe extends re{constructor(){super("null",">null<","Empty segment")}}class fe extends re{constructor(e,t){super("word",e,t)}}class j extends re{constructor(e,t,s,r){super("argument",e,t),this.value=s,this.valid=r}}const ze=n=>{if(n.type==="word")return new fe(n.name,n.description);if(n.type==="argument"){const e=n;return new j(e.name,e.description,e.value,e.valid)}return new oe},_=n=>n.map(e=>ze(e));class Fe{constructor(e,t,s=ge){C(this,"_segments");C(this,"_description");C(this,"_handler");this._segments=e,this._description=t,this._handler=s}get segments(){return this._segments}get description(){return this._description}get handler(){return this._handler}get hasArguments(){return this.segments.some(e=>e.type==="argument")}get fullPath(){return this.segments.map(e=>e.name)}get fullPath_s(){return this.fullPath.join(" ")}equals(e){return this.fullPath.join(" ")===e.fullPath.join(" ")}}class K{constructor(){C(this,"_commands",[])}get commands(){return this._commands}addCommand(e,t,s=ge){if(e===void 0||e.length===0)throw new Error("Command path cannot be empty");const r=new Fe(e,t,s),i=this._commands.find(a=>{const d=a.segments.map(u=>u.type==="argument"?"*":u.name).join(" "),l=e.map(u=>u.type==="argument"?"*":u.name).join(" ");return d===l});if(i)throw new Error(`Duplicate commands: '${i.fullPath_s}' and '${r.fullPath_s}'`);this._commands.push(r)}removeCommand(e){const t=e.join(" "),s=this._commands.findIndex(r=>r.fullPath.join(" ")===t);return s===-1?!1:(this._commands.splice(s,1),!0)}getCommand(e){return this._commands.find(t=>{const s=t.fullPath.join(" "),r=e.join(" ");if(s===r)return!0;const a=t.segments.filter(d=>d.type==="word").map(d=>d.name);return a.length===e.length&&a.join(" ")===r})}commandExistsForPath(e){const t=this._commands.map(r=>r.segments.map(i=>i.type==="argument"?"*":i.name).join(" ")),s=e.map((r,i)=>this._commands.some(d=>{var l;return((l=d.segments[i])==null?void 0:l.type)==="argument"})?"*":r).join(" ");return t.includes(s)}getCompletionNames(e){return this.getCompletions(e).map(t=>t.name)}getMatchingCompletions(e,t){const s=t.trim().toLowerCase(),r=this.getCompletions(e);return s?r.filter(i=>i.name.toLowerCase().startsWith(s)):r}getUniqueCompletion(e,t){const s=this.getMatchingCompletions(e,t);if(s.length===1)return s[0]}getCompletions(e){if(k.debug("[getCompletions] path: ",e),!e.length){const i=this._commands.map(l=>l.segments[0]),a=(l,u)=>l.type===u.type&&l.name===u.name;return i.filter((l,u,f)=>u===f.findIndex(p=>a(p,l)))}const t=e.length;return this._commands.filter(i=>{const a=i.segments;if(a.length<=t-1)return!1;for(let d=0;d<t;d++){const l=e[d],u=a[d];if(!(l==="*"&&u.type==="argument")&&l!==u.name)return!1}return!0}).filter(i=>i.segments.length>t).map(i=>{const a=i.segments[t],d=a.type==="argument"?j:fe;return new d(a.name,a.description)}).filter((i,a,d)=>a===d.findIndex(l=>l.type===i.type&&l.name===i.name))}hasNextSegment(e){return this.getCompletions(e).length>0}}class ye{constructor(e){C(this,"config");this.config={type:"localStorage",maxCommands:100,...e}}async addStoredCommand(e){const t=await this.getStoredCommands();for(t.push(e);t.length>this.config.maxCommands;)t.shift();await this.saveCommands(t)}}class Le extends ye{constructor(t){super(t);C(this,"storageKey","citadel_command_history")}async getStoredCommands(){try{const t=window.localStorage.getItem(this.storageKey);return t?JSON.parse(t).map(r=>({commandSegments:Array.isArray(r.commandSegments)?_(r.commandSegments):[],timestamp:r.timestamp})):[]}catch(t){return console.warn("Failed to load commands from localStorage:",t),[]}}async clear(){try{window.localStorage.removeItem(this.storageKey)}catch(t){console.warn("Failed to clear localStorage:",t)}}async saveCommands(t){try{const s=t.map(r=>({commandSegments:Array.isArray(r.commandSegments)?_(r.commandSegments).map(i=>({type:i.type,name:i.name,description:i.description,...i instanceof j?{value:i.value}:{}})):[],timestamp:r.timestamp}));window.localStorage.setItem(this.storageKey,JSON.stringify(s))}catch(s){throw console.warn("Failed to save commands to localStorage:",s),s}}}class Ce extends ye{constructor(t){super(t);C(this,"storedCommands",[])}async getStoredCommands(){return this.storedCommands.map(t=>({commandSegments:Array.isArray(t.commandSegments)?_(t.commandSegments):[],timestamp:t.timestamp}))}async clear(){this.storedCommands=[]}async saveCommands(t){this.storedCommands=t.map(s=>({commandSegments:Array.isArray(s.commandSegments)?_(s.commandSegments):[],timestamp:s.timestamp}))}}const U=class U{constructor(){C(this,"currentStorage")}static reset(){U.instance=void 0}static getInstance(){return U.instance||(U.instance=new U),U.instance}initializeStorage(e){try{e.type==="memory"?this.currentStorage=new Ce(e):this.currentStorage=new Le(e)}catch(t){console.warn("Failed to create storage, falling back to memory storage:",t),this.currentStorage=new Ce(e)}}getStorage(){if(!this.currentStorage)throw new Error("Storage not initialized. Call initializeStorage first.");return this.currentStorage}};C(U,"instance");let J=U;class we{constructor(){C(this,"segments",[]);C(this,"nullSegment",new oe);C(this,"observers",[])}subscribe(e){this.observers.push(e)}unsubscribe(e){this.observers=this.observers.filter(t=>t!==e)}notifyObservers(){this.observers.forEach(e=>e.update())}clear(){this.segments=[],this.notifyObservers()}push(e){this.segments.push(e),this.notifyObservers()}pushAll(e){e.forEach(t=>this.push(t))}pop(){const e=this.segments.pop()||this.nullSegment;return this.notifyObservers(),e}peek(){return this.segments[this.segments.length-1]||this.nullSegment}size(){return this.segments.length}isEmpty(){return this.segments.length===0}get hasArguments(){return this.segments.some(e=>e.type==="argument")}get arguments(){return this.segments.filter(e=>e.type==="argument")}path(){return this.segments.map(e=>e.name)}toArray(){return[...this.segments]}}const Ue={config:E,commands:new K,segmentStack:new we},W=o.createContext(Ue),$e=({config:n=E,commandRegistry:e,children:t})=>{const[s,r]=o.useState(),[i]=o.useState(()=>new we),a=o.useMemo(()=>({...E,...n,storage:{...E.storage,...n.storage},cursorType:n.cursorType??E.cursorType,cursorColor:n.cursorColor??E.cursorColor,cursorSpeed:n.cursorSpeed??E.cursorSpeed,closeOnEscape:n.closeOnEscape??E.closeOnEscape,showCitadelKey:n.showCitadelKey??E.showCitadelKey,showOnLoad:n.showOnLoad??E.showOnLoad}),[n]);o.useEffect(()=>{J.getInstance().initializeStorage(a.storage??E.storage),r(J.getInstance().getStorage())},[a.storage]),o.useEffect(()=>{if(e){if(a.includeHelpCommand){if(!e.commandExistsForPath(["help"])){const l=De(e);e.addCommand([{type:"word",name:"help"}],"Show available commands",l)}return}e.removeCommand(["help"])}},[e,a.includeHelpCommand]);const d=o.useMemo(()=>({config:a,commands:e||new K,storage:s,segmentStack:i}),[a,e,s,i]);return c.jsx(W.Provider,{value:d,children:t})},L=()=>{const n=o.useContext(W);if(n===void 0)throw new Error("useCitadelConfig must be used within a CitadelConfigProvider");return n.config},X=()=>{const n=o.useContext(W);if(n===void 0)throw new Error("useCitadelCommands must be used within a CitadelConfigProvider");return n.commands},ve=()=>{const n=o.useContext(W);if(n===void 0)throw new Error("useCitadelStorage must be used within a CitadelConfigProvider");return n.storage},B=()=>{const n=o.useContext(W);if(n===void 0)throw new Error("useSegmentStack must be used within a CitadelConfigProvider");return n.segmentStack},ee=class ee{constructor(e,t){C(this,"id");C(this,"timestamp");C(this,"command");C(this,"result");this.id=`output-${Date.now()}-${ee.idCounter++}`,this.command=e.toArray().map(s=>s.type==="argument"?s.value||"":s.name),this.timestamp=Date.now(),this.result=t??new ue}};C(ee,"idCounter",0);let Q=ee;function je(n){return{commandSegments:_(n),timestamp:Date.now()}}function Se(){const n=ve(),[e,t]=o.useState({storedCommands:[],position:null}),s=o.useCallback(async d=>{if(n)try{const l=je(d);await n.addStoredCommand(l),t(u=>({...u,storedCommands:[...u.storedCommands,{...l,commandSegments:_(l.commandSegments)}],position:null}))}catch(l){console.warn("Failed to save command to history:",l)}},[n]),r=o.useCallback(async()=>n?(await n.getStoredCommands()).map(l=>({...l,commandSegments:_(l.commandSegments)})):[],[n]);o.useEffect(()=>{if(!n)return;(async()=>{try{const u=(await n.getStoredCommands()).map(f=>({...f,commandSegments:_(f.commandSegments)}));return t(f=>({...f,storedCommands:u})),u}catch(l){console.warn("Failed to load command history:",l)}})()},[n]);const i=o.useCallback(async d=>{const l=await r();if(l.length===0)return t(p=>({...p,storedCommands:[],position:null})),{segments:null,position:null};let u=null;if(d==="up"?e.position===null?u=l.length-1:e.position>0?u=e.position-1:u=0:e.position===null||e.position>=l.length-1?u=null:u=e.position+1,t(p=>({...p,storedCommands:l.map(y=>({...y,commandSegments:_(y.commandSegments)})),position:u})),u===null)return{segments:[],position:null};const f=l[u];return f?{segments:_(f.commandSegments),position:u}:{segments:[],position:null}},[e.position,r]),a=o.useCallback(async()=>{try{if(!n)return;await n.clear(),t({storedCommands:[],position:null})}catch(d){console.warn("Failed to clear command history:",d)}},[n]);return{history:e,addStoredCommand:s,getStoredCommands:r,navigateHistory:i,clear:a}}const ae=()=>{const n=L(),e=X(),t=Se(),s=B(),r=ve(),[i,a]=o.useState({currentInput:"",isEnteringArg:!1,output:[],history:{commands:[],position:null,storage:r}});o.useEffect(()=>{},[r]),o.useEffect(()=>{a(l=>({...l,history:{commands:t.history.storedCommands,position:t.history.position,storage:r}}))},[t.history,r]);const d={setCurrentInput:o.useCallback(l=>{k.debug("[CitadelActions] setCurrentInput: ",l),a(u=>({...u,currentInput:l}))},[]),setIsEnteringArg:o.useCallback(l=>{k.debug("[CitadelActions] setIsEnteringArg: ",l),a(u=>({...u,isEnteringArg:l}))},[]),addOutput:o.useCallback(l=>{k.debug("[CitadelActions]addOutput: ",l),a(u=>({...u,output:[...u.output,l]}))},[]),executeCommand:o.useCallback(async()=>{const l=s.path(),u=e.getCommand(l);if(!u){console.error("[CitadelActions][executeCommand] Cannot execute command because no command was found for the given path: ",l);return}const f=new Q(s);a(p=>({...p,output:[...p.output,f]}));try{const p=new Promise((S,N)=>{setTimeout(()=>{N(new Error("Request timed out"))},n.commandTimeoutMs)}),y=s.arguments.map(S=>S.value||""),w=await Promise.race([u.handler(y),p]);if(!(w instanceof F))throw new Error(`The ${l.join(".")} command returned an invalid result type. Commands must return an instance of a CommandResult.
4
4
  For example:
5
5
  return new JsonCommandResult({ text: "Hello World" });
6
- Check the definition of the ${l.join(".")} command and update the return type for its handler.`);b.markSuccess(),o(v=>({...v,output:v.output.map(E=>E.id===y.id?{...E,result:b}:E)}))}catch(p){const f=new Z(p instanceof Error?p.message:"Unknown error");f.markFailure(),o(b=>({...b,output:b.output.map(v=>v.id===y.id?{...v,result:f}:v)}))}},[e,t.commandTimeoutMs,s]),clearHistory:a.useCallback(async()=>{try{await n.clear()}catch(l){console.warn("Failed to clear history:",l)}},[n])};return{state:i,actions:d}},Fe=({onOpen:t,onClose:e,isVisible:n,showCitadelKey:s,closeOnEscape:r})=>{a.useEffect(()=>{const i=o=>{var d,l;!n&&o.key===s&&!["input","textarea"].includes(((l=(d=o.target)==null?void 0:d.tagName)==null?void 0:l.toLowerCase())||"")&&(o.preventDefault(),t()),r&&n&&o.key==="Escape"&&(o.preventDefault(),e())};return document.addEventListener("keydown",i),()=>document.removeEventListener("keydown",i)},[t,e,n,s,r])},Le=200,je=t=>{const{isVisible:e,isClosing:n,onAnimationComplete:s}=t,r=a.useMemo(()=>e?n?"citadel_slideDown":"citadel_slideUp":"",[e,n]);return a.useEffect(()=>{if(!n||!s)return;if(window.matchMedia("(prefers-reduced-motion: reduce)").matches){s();return}const o=setTimeout(()=>{s()},Le);return()=>clearTimeout(o)},[n,s]),{animationClass:r}},Ue=()=>c.jsx("div",{"data-testid":"spinner",className:"citadel-spinner"}),Ce=t=>{const e=t==null?void 0:t.trim();return e||void 0},$e=t=>{const e=Ce(t);return e?{style:{fontSize:e}}:{}},Q=(t,e)=>{const n=Ce(t),r={...$e(e).style};return n&&(r.fontFamily=n),{style:Object.keys(r).length>0?r:void 0}},qe=({command:t,timestamp:e,status:n,fontFamily:s,fontSize:r})=>{const i=a.useMemo(()=>Q(s,r??"0.875rem"),[s,r]);return c.jsxs("div",{className:"citadel-output-line",style:i.style,children:[c.jsxs("span",{className:"citadel-output-command",children:["> ",t.split(" ").map((o,d)=>{const l=o.startsWith("<")&&o.endsWith(">");return c.jsxs("span",{className:l?"citadel-output-command-arg":"citadel-output-command-word",children:[d>0?" ":"",o]},d)})]}),c.jsx("span",{className:"citadel-output-separator",children:"·"}),c.jsx("span",{className:"citadel-output-timestamp",children:e}),n===j.Pending&&c.jsx(Ue,{}),n===j.Success&&c.jsx("div",{"data-testid":"success-indicator",className:"citadel-status-dot citadel-status-dot-success"}),(n===j.Timeout||n===j.Failure)&&c.jsx("div",{"data-testid":"success-indicator",className:"citadel-status-dot citadel-status-dot-failure"})]})},Ke=({output:t,outputRef:e})=>{const n=T(),s=a.useMemo(()=>Q(n.fontFamily,n.outputFontSize??n.fontSize),[n.fontFamily,n.fontSize,n.outputFontSize]),r=a.useCallback(()=>{if(e.current){const i=e.current;requestAnimationFrame(()=>{i.scrollTop=i.scrollHeight})}},[e]);return a.useEffect(()=>{if(r(),e.current){const i=e.current.getElementsByTagName("img"),o=i[i.length-1];if(o&&!o.complete)return o.addEventListener("load",r),()=>o.removeEventListener("load",r)}},[t,r,e]),c.jsx("div",{ref:e,className:"citadel-output","data-testid":"citadel-command-output",children:t.map(i=>c.jsxs("div",{className:"citadel-output-item",children:[c.jsx(qe,{command:i.command.join(" "),timestamp:new Date(i.timestamp).toLocaleTimeString(),status:i.result.status,fontFamily:n.fontFamily,fontSize:n.fontSize}),c.jsx("div",{className:"citadel-output-content",style:s.style,children:i.result.render()})]},i.id))})},we={blink:{character:"▋",speed:530,color:"#fff"},spin:{character:"⠋",speed:120,color:"#fff"},solid:{character:"▋",speed:0,color:"#fff"},bbs:{character:"|",speed:120,color:"#fff"}},ve=["⠋","⠙","⠹","⠸","⠼","⠴","⠦","⠧","⠇","⠏"],Se=["|","/","-","\\"],We=({style:t={type:"blink"},isValid:e=!0,errorMessage:n})=>{const s=a.useMemo(()=>({...we[t.type],...t}),[t]),[r,i]=a.useState(!0),[o,d]=a.useState(0);a.useEffect(()=>{if(s.speed===0)return;const y=setInterval(()=>{s.type==="blink"?i(p=>!p):["spin","bbs"].includes(s.type)&&d(p=>(p+1)%(s.type==="bbs"?Se.length:ve.length))},s.speed);return()=>clearInterval(y)},[s.type,s.speed]);const l=a.useMemo(()=>({color:e?s.color:"#ff4444",transition:"color 0.15s ease-in-out"}),[e,s.color]),u=()=>!e&&n?"✗":["spin","bbs"].includes(s.type)?(s.type==="bbs"?Se:ve)[o]:s.type==="solid"||r?s.character:" ";return c.jsx("div",{className:"citadel-cursor-wrapper",children:c.jsx("span",{className:`command-cursor ${e?"":"animate-shake"}`,style:l,title:n,children:u()})})};function Be(t,e){switch(e.type){case"set":return x.debug(`[inputStateReducer] InputState changing from ${t} to ${e.state}`),e.state;default:return t}}const Ve=()=>{const{state:t}=ne(),e=J(),n=ye(),s=B(),[r,i]=a.useReducer(Be,"idle"),o=m=>{i({type:"set",state:m})},d=a.useCallback(()=>{const h=e.getCompletions(s.path())[0]||s.nullSegment;return x.debug("[getNextExpectedSegment] ",h),h},[e,s]),l=a.useCallback(()=>e.getCompletionNames(s.path()).map(h=>e.getCommand([...s.path(),h])).filter(h=>h!==void 0),[e,s]),u=a.useCallback((m,h)=>{if(!m)return h;const w=s.path().length;return h.filter(D=>{const S=D.segments[w];return!S||S.type!=="word"?!1:S.name.toLowerCase().startsWith(m.toLowerCase())})},[s]),y=a.useCallback(m=>{const h=e.getUniqueCompletion(s.path(),m);return h&&h.type==="word"?h:s.nullSegment},[e,s]),p=a.useCallback(m=>{const h=s.path(),w=e.getCompletions(h);return w.length===0&&m?!1:w.some(S=>S.type==="argument")?!0:e.getMatchingCompletions(h,m).some(S=>S.type==="word")},[e,s]),f=a.useCallback(m=>{x.debug("[tryAutoComplete] input: ",m);const h=y(m);return!h||h.type==="null"?new te:(x.debug("[tryAutoComplete] result: ",h),h)},[y]),b=a.useCallback((m,h)=>{if(t.history.position!==null)return;h.setCurrentInput(m),x.debug("[useCommandParser][handleInputChange] newValue: ",m);const w=d();if(w.type==="argument"||r==="entering_argument"){const A=be(m);if(A.isQuoted)if(A.isComplete){if(!(w instanceof U))return;w.value=m.trim()||"",x.debug("[useCommandParser][handleInputChange][entering_command] pushing: ",w),s.push(w),h.setCurrentInput(""),o("idle");return}else return;else if(A.isComplete){if(!(w instanceof U))return;w.value=m.trim()||"",x.debug("[useCommandParser][handleInputChange][entering_command] pushing: ",w),s.push(w),h.setCurrentInput(""),o("idle");return}else return}if(m.endsWith(" ")){const A=m.trim().toLowerCase(),P=e.getCompletions(s.path()).filter(N=>N.type==="word"&&N.name.toLowerCase()===A);if(P.length===1){s.push(P[0]),h.setCurrentInput(""),o("idle");return}}const S=f(m);if(S.type==="word"){x.debug("[useCommandParser][handleInputChange][entering_command] pushing: ",S),s.push(S),h.setCurrentInput(""),o("idle");return}},[f,t,d,r,s,e]),v=a.useCallback(m=>{m.setCurrentInput(""),m.setIsEnteringArg(!1),s.clear(),o("idle")},[s]),E=a.useCallback((m,h,w)=>{if(!(m.key==="Backspace"||m.key==="Enter"||m.key==="ArrowUp"||m.key==="ArrowDown"||m.key==="ArrowLeft"||m.key==="ArrowRight"||m.key==="Escape"||m.key==="Delete"||m.key==="Home"||m.key==="End"||m.key.length===1))return!0;const{currentInput:S,isEnteringArg:A}=h,P=be(S);switch(m.key){case"Backspace":return S===""&&(m.preventDefault(),s.size()>0&&s.pop(),o("idle")),!0;case"Enter":{if(m.preventDefault(),P.isQuoted&&!P.isComplete)return!0;if(r==="entering_argument"||A&&S.trim()){const F=d();F instanceof U&&(F.value=S,x.debug("[handleKeyDown][Enter]['entering_argument'] pushing: ",F),s.push(F))}const N=s.path(),V=e.getCommand(N);if(!V)return!1;const O=V.segments.filter(F=>F.type==="argument"),$=s.arguments;return O.length>$.length?!1:(x.debug("[handleKeyDown][Enter] calling actions.executeCommand. segmentStack: ",s),w.executeCommand(),n.addStoredCommand(s.toArray()),v(w),!0)}case"ArrowUp":return m.preventDefault(),(async()=>{const N=await n.navigateHistory("up");return N.segments&&(s.clear(),s.pushAll(N.segments),w.setCurrentInput("")),!0})();case"ArrowDown":return m.preventDefault(),(async()=>{const N=await n.navigateHistory("down");return N.segments&&(s.clear(),s.pushAll(N.segments),w.setCurrentInput("")),!0})();default:{if(!A&&m.key.length===1){const N=S+m.key;if(!p(N))return m.preventDefault(),!1}return!0}}},[r,p,d,n,v,e,s]);return{handleInputChange:b,handleKeyDown:E,inputState:r,setInputStateWithLogging:o,findMatchingCommands:u,getAutocompleteSuggestion:y,getAvailableNodes:l,getNextExpectedSegment:d,isValidCommandInput:p}};function be(t){const e=[];let n="",s=!1,r;for(let i=0;i<t.length;i++){const o=t[i];(o==='"'||o==="'")&&(!s||o===r)?s?(e.push(n),n="",s=!1,r=void 0):(n&&(e.push(n),n=""),s=!0,r=o):!s&&o===" "?n&&(e.push(n),n=""):n+=o}return{words:e,currentWord:n,isQuoted:s,quoteChar:r,isComplete:!s&&!n}}const Ye=()=>{const t=B(),[e,n]=a.useState(0);return a.useEffect(()=>{const s={update:()=>{n(r=>r+1)}};return t.subscribe(s),()=>{t.unsubscribe(s)}},[t]),e},Je=({state:t,actions:e})=>{const n=a.useRef(null),s=J(),r=B(),{handleKeyDown:i,handleInputChange:o,inputState:d,setInputStateWithLogging:l,getNextExpectedSegment:u}=Ve(),[y,p]=a.useState(!1),f=T(),b=Ye(),v=a.useRef(null),[E,m]=a.useState(0),h=a.useMemo(()=>Q(f.fontFamily,f.fontSize),[f.fontFamily,f.fontSize]),w=a.useCallback(async I=>{const M=i(I,t,e);await Promise.resolve(M)===!1&&(p(!0),setTimeout(()=>p(!1),500))},[e,i,t]),D=a.useCallback(I=>{o(I.target.value,e)},[e,o]),S=a.useCallback(I=>{I.preventDefault();const M=I.clipboardData.getData("text");o(M,e)},[e,o]);a.useEffect(()=>{n.current&&n.current.focus(),d!=="entering_command"&&l("entering_command")},[d,l]),a.useEffect(()=>{if(d!=="idle")return;const I=u();let M="idle";switch(I.type){case"word":M="entering_command",e.setIsEnteringArg(!1);break;case"argument":M="entering_argument",e.setIsEnteringArg(!0);break}l(M)},[b,d,u,l,e]);const A=a.useMemo(()=>{const I=[],M=r.toArray().map((L,re)=>{I.push(L.name);const Ae=s.hasNextSegment(I);if(L.type==="argument"){const ae=L;return c.jsxs(a.Fragment,{children:[c.jsx("span",{className:"citadel-input-segment-arg",children:ae.value}),re<r.size()&&Ae&&c.jsx("span",{className:"citadel-input-segment-space",children:" "})]},"arg-"+ae.name+ae.value)}return c.jsxs(a.Fragment,{children:[c.jsx("span",{className:"citadel-input-segment-word",children:L.name}),re<r.size()&&Ae&&c.jsx("span",{className:"citadel-input-segment-space citadel-input-segment-space-command",children:" "})]},"word-"+L.name)});return[c.jsx("div",{className:"citadel-input-segments","data-testid":"user-input-area",children:M},b)]},[b,s,r]),[P,N]=a.useState("");a.useEffect(()=>{const I=u();I.type==="argument"?N(I.name):N("")},[b,u]);const O=!t.isEnteringArg?"is-command-mode":"is-argument-mode",$=a.useMemo(()=>({left:`${E}px`,transition:"left 0.05s ease-out"}),[E]),F=a.useMemo(()=>({type:f.cursorType??k.cursorType,color:f.cursorColor||k.cursorColor,speed:f.cursorSpeed||k.cursorSpeed}),[f.cursorColor,f.cursorSpeed,f.cursorType]);return a.useLayoutEffect(()=>{const I=v.current,M=n.current;if(!I||!M){m(0);return}const L=I.getBoundingClientRect().width;m(Math.max(0,L-M.scrollLeft))},[t.currentInput,O,h.style]),c.jsx("div",{className:"citadel-input-shell",children:c.jsxs("div",{className:"citadel-input-line",style:h.style,children:[c.jsx("div",{className:"citadel-input-prompt",children:">"}),c.jsxs("div",{className:"citadel-input-row",children:[A,c.jsxs("div",{className:"citadel-input-control",children:[c.jsx("span",{ref:v,className:`citadel-input-measure ${O}`.trim(),"aria-hidden":"true",children:t.currentInput}),c.jsx("input",{ref:n,type:"text",role:"textbox",value:t.currentInput,onChange:D,onKeyDown:w,onPaste:S,"data-testid":"citadel-command-input",className:`citadel-input-field ${O} ${y?"invalid-input-animation":""}`.trim(),spellCheck:!1,autoComplete:"off",placeholder:P}),c.jsx("div",{className:"citadel-input-cursor",style:$,children:c.jsx(We,{style:F})})]})]})]})})},Ge=({currentInput:t=""})=>{const e=J(),n=T(),s=B(),r=a.useMemo(()=>Q(n.fontFamily,n.fontSize),[n.fontFamily,n.fontSize]),i=t.trim().toLowerCase(),o=e.getMatchingCompletions(s.path(),i);x.debug("[AvailableCommands] nextCommandSegments: ",o);const d=a.useMemo(()=>{const p=[...o],f=m=>m.name.toLowerCase()==="help",b=p.filter(f);return[...p.filter(m=>!f(m)).sort((m,h)=>m.name.localeCompare(h.name,void 0,{sensitivity:"base"})),...b]},[o]),l=a.useMemo(()=>{const p=new Map;for(const f of d){const b=d.reduce((v,E)=>{if(E===f)return v;let m=0;for(;m<f.name.length&&m<E.name.length&&f.name[m].toLowerCase()===E.name[m].toLowerCase();)m++;return Math.max(v,m+1)},1);p.set(f.name,b)}return p},[d]),u=o.some(p=>p.type==="argument"),y=o[0];return c.jsx("div",{className:"citadel-available-commands","data-testid":"available-commands",children:c.jsx("div",{className:"citadel-available-commands-content",style:r.style,children:u?o.length>0?c.jsxs(c.Fragment,{children:[c.jsx("span",{className:"citadel-available-next-arg",children:y.name}),y.description&&c.jsxs("span",{className:"citadel-available-next-desc",children:["- ",y.description]})]}):null:c.jsx("div",{className:"citadel-available-chip-list",children:d==null?void 0:d.map(p=>{const f=l.get(p.name)??1;return c.jsx("div",{"data-testid":"available-command-chip",className:"citadel-available-chip",children:c.jsxs("span",{className:"citadel-available-chip-text",children:[c.jsx("strong",{className:"citadel-available-chip-prefix",children:p.name.slice(0,f)}),p.name.slice(f)]})},p.name)})})})})},xe=({state:t,actions:e,outputRef:n})=>{const r=T().displayMode==="inline",i=a.useMemo(()=>r?{overflow:"hidden"}:void 0,[r]);return c.jsxs("div",{className:"innerContainer citadel-tty",children:[c.jsx("div",{className:"citadel-tty-output-pane","data-testid":"citadel-output-pane",style:i,children:c.jsx(Ke,{output:t.output,outputRef:n})}),c.jsxs("div",{className:"citadel-tty-input-region",children:[c.jsx(Je,{state:t,actions:e}),c.jsx(Ge,{currentInput:t.isEnteringArg?"":t.currentInput})]})]})},Qe=()=>{const t=T(),[e,n]=a.useState(()=>t.showOnLoad??!1),[s,r]=a.useState(!1),[i,o]=a.useState(()=>t.initialHeight||null),d=a.useRef(null),l=a.useRef(null),u=a.useRef(!1),y=a.useRef(0),p=a.useRef(0),{state:f,actions:b}=ne(),v=a.useCallback(()=>{r(!1),n(!0)},[]),E=a.useCallback(()=>{r(!0)},[]);Fe({onOpen:v,onClose:E,isVisible:e&&!s,showCitadelKey:t.showCitadelKey||".",closeOnEscape:t.closeOnEscape??!0});const m=a.useCallback(P=>{var $;if(!u.current)return;const N=P.clientY-y.current,V=($=t.maxHeight)!=null&&$.endsWith("vh")?window.innerHeight*parseInt(t.maxHeight,10)/100:parseInt(t.maxHeight||"80vh",10),O=Math.min(Math.max(p.current-N,parseInt(t.minHeight||"200",10)),V);l.current&&(l.current.style.height=`${O}px`,l.current.style.bottom="0",o(`${O}px`))},[t.maxHeight,t.minHeight]),h=a.useCallback(()=>{u.current=!1,document.documentElement.style.userSelect="",document.documentElement.style.webkitUserSelect="",document.documentElement.style.mozUserSelect="",document.documentElement.style.msUserSelect="",document.removeEventListener("mousemove",m),document.removeEventListener("mouseup",h)},[m]),w=a.useCallback(P=>{l.current&&(u.current=!0,y.current=P.clientY,p.current=l.current.offsetHeight,document.documentElement.style.userSelect="none",document.documentElement.style.webkitUserSelect="none",document.documentElement.style.mozUserSelect="none",document.documentElement.style.msUserSelect="none",document.addEventListener("mousemove",m),document.addEventListener("mouseup",h))},[m,h]);a.useEffect(()=>()=>{document.removeEventListener("mousemove",m),document.removeEventListener("mouseup",h)},[m,h]);const D=a.useCallback(()=>{s&&(n(!1),r(!1))},[s]),{animationClass:S}=je({isVisible:e,isClosing:s,onAnimationComplete:D}),A=a.useMemo(()=>({...i?{height:i}:{},maxHeight:t.maxHeight}),[t.maxHeight,i]);return e?c.jsxs("div",{ref:l,className:`panelContainer ${S}`.trim(),style:A,children:[c.jsx("div",{className:"resizeHandle",onMouseDown:w}),c.jsx(xe,{state:f,actions:b,outputRef:d})]}):null},se=t=>{if(!t)return;const e=t.trim();if(e)return/^\d+(\.\d+)?$/.test(e)?`${e}px`:e},Xe=()=>{const{state:t,actions:e}=ne(),n=T(),s=a.useRef(null),r=a.useMemo(()=>({height:se(n.initialHeight),maxHeight:se(n.maxHeight),minHeight:se(n.minHeight)}),[n.initialHeight,n.maxHeight,n.minHeight]);return c.jsx("div",{className:"inlineContainer","data-testid":"citadel-inline-container",style:r,children:c.jsx(xe,{state:t,actions:e,outputRef:s})})},ke=`:host {
6
+ Check the definition of the ${l.join(".")} command and update the return type for its handler.`);w.markSuccess(),a(S=>({...S,output:S.output.map(N=>N.id===f.id?{...N,result:w}:N)}))}catch(p){const y=new ne(p instanceof Error?p.message:"Unknown error");y.markFailure(),a(w=>({...w,output:w.output.map(S=>S.id===f.id?{...S,result:y}:S)}))}},[e,n.commandTimeoutMs,s]),clearHistory:o.useCallback(async()=>{try{await t.clear()}catch(l){console.warn("Failed to clear history:",l)}},[t])};return{state:i,actions:d}},qe=({onOpen:n,onClose:e,isVisible:t,showCitadelKey:s,closeOnEscape:r})=>{o.useEffect(()=>{const i=a=>{var d,l;!t&&a.key===s&&!["input","textarea"].includes(((l=(d=a.target)==null?void 0:d.tagName)==null?void 0:l.toLowerCase())||"")&&(a.preventDefault(),n()),r&&t&&a.key==="Escape"&&(a.preventDefault(),e())};return document.addEventListener("keydown",i),()=>document.removeEventListener("keydown",i)},[n,e,t,s,r])},Ke=200,We=n=>{const{isVisible:e,isClosing:t,onAnimationComplete:s}=n,r=o.useMemo(()=>e?t?"citadel_slideDown":"citadel_slideUp":"",[e,t]);return o.useEffect(()=>{if(!t||!s)return;if(window.matchMedia("(prefers-reduced-motion: reduce)").matches){s();return}const a=setTimeout(()=>{s()},Ke);return()=>clearTimeout(a)},[t,s]),{animationClass:r}},Be=()=>c.jsx("div",{"data-testid":"spinner",className:"citadel-spinner"}),be=n=>{const e=n==null?void 0:n.trim();return e||void 0},Ve=n=>{const e=be(n);return e?{style:{fontSize:e}}:{}},Z=(n,e)=>{const t=be(n),r={...Ve(e).style};return t&&(r.fontFamily=t),{style:Object.keys(r).length>0?r:void 0}},Ge=({command:n,timestamp:e,status:t,fontFamily:s,fontSize:r})=>{const i=o.useMemo(()=>Z(s,r??"0.875rem"),[s,r]);return c.jsxs("div",{className:"citadel-output-line",style:i.style,children:[c.jsxs("span",{className:"citadel-output-command",children:["> ",n.split(" ").map((a,d)=>{const l=a.startsWith("<")&&a.endsWith(">");return c.jsxs("span",{className:l?"citadel-output-command-arg":"citadel-output-command-word",children:[d>0?" ":"",a]},d)})]}),c.jsx("span",{className:"citadel-output-separator",children:"·"}),c.jsx("span",{className:"citadel-output-timestamp",children:e}),t===$.Pending&&c.jsx(Be,{}),t===$.Success&&c.jsx("div",{"data-testid":"success-indicator",className:"citadel-status-dot citadel-status-dot-success"}),(t===$.Timeout||t===$.Failure)&&c.jsx("div",{"data-testid":"success-indicator",className:"citadel-status-dot citadel-status-dot-failure"})]})},Ye=({output:n,outputRef:e})=>{const t=L(),s=o.useMemo(()=>Z(t.fontFamily,t.outputFontSize??t.fontSize),[t.fontFamily,t.fontSize,t.outputFontSize]),r=o.useCallback(()=>{if(e.current){const i=e.current;requestAnimationFrame(()=>{i.scrollTop=i.scrollHeight})}},[e]);return o.useEffect(()=>{if(r(),e.current){const i=e.current.getElementsByTagName("img"),a=i[i.length-1];if(a&&!a.complete)return a.addEventListener("load",r),()=>a.removeEventListener("load",r)}},[n,r,e]),c.jsx("div",{ref:e,className:"citadel-output","data-testid":"citadel-command-output",children:n.map(i=>c.jsxs("div",{className:"citadel-output-item",children:[c.jsx(Ge,{command:i.command.join(" "),timestamp:new Date(i.timestamp).toLocaleTimeString(),status:i.result.status,fontFamily:t.fontFamily,fontSize:t.fontSize}),c.jsx("div",{className:"citadel-output-content",style:s.style,children:i.result.render()})]},i.id))})},xe={blink:{character:"▋",speed:530,color:"#fff"},spin:{character:"⠋",speed:120,color:"#fff"},solid:{character:"▋",speed:0,color:"#fff"},bbs:{character:"|",speed:120,color:"#fff"}},ke=["⠋","⠙","⠹","⠸","⠼","⠴","⠦","⠧","⠇","⠏"],Ee=["|","/","-","\\"],Je=({style:n={type:"blink"},isValid:e=!0,errorMessage:t})=>{const s=o.useMemo(()=>({...xe[n.type],...n}),[n]),[r,i]=o.useState(!0),[a,d]=o.useState(0);o.useEffect(()=>{if(s.speed===0)return;const f=setInterval(()=>{s.type==="blink"?i(p=>!p):["spin","bbs"].includes(s.type)&&d(p=>(p+1)%(s.type==="bbs"?Ee.length:ke.length))},s.speed);return()=>clearInterval(f)},[s.type,s.speed]);const l=o.useMemo(()=>({color:e?s.color:"#ff4444",transition:"color 0.15s ease-in-out"}),[e,s.color]),u=()=>!e&&t?"✗":["spin","bbs"].includes(s.type)?(s.type==="bbs"?Ee:ke)[a]:s.type==="solid"||r?s.character:" ";return c.jsx("div",{className:"citadel-cursor-wrapper",children:c.jsx("span",{className:`command-cursor ${e?"":"animate-shake"}`,style:l,title:t,children:u()})})};function Xe(n,e){switch(e.type){case"set":return k.debug(`[inputStateReducer] InputState changing from ${n} to ${e.state}`),e.state;default:return n}}const Qe=()=>{const{state:n}=ae(),e=X(),t=Se(),s=B(),[r,i]=o.useReducer(Xe,"idle"),a=m=>{i({type:"set",state:m})},d=o.useCallback(()=>{const h=e.getCompletions(s.path())[0]||s.nullSegment;return k.debug("[getNextExpectedSegment] ",h),h},[e,s]),l=o.useCallback(()=>e.getCompletionNames(s.path()).map(h=>e.getCommand([...s.path(),h])).filter(h=>h!==void 0),[e,s]),u=o.useCallback((m,h)=>{if(!m)return h;const v=s.path().length;return h.filter(T=>{const b=T.segments[v];return!b||b.type!=="word"?!1:b.name.toLowerCase().startsWith(m.toLowerCase())})},[s]),f=o.useCallback(m=>{const h=e.getUniqueCompletion(s.path(),m);return h&&h.type==="word"?h:s.nullSegment},[e,s]),p=o.useCallback(m=>{const h=s.path(),v=e.getCompletions(h);return v.length===0&&m?!1:v.some(b=>b.type==="argument")?!0:e.getMatchingCompletions(h,m).some(b=>b.type==="word")},[e,s]),y=o.useCallback(m=>{k.debug("[tryAutoComplete] input: ",m);const h=f(m);return!h||h.type==="null"?new oe:(k.debug("[tryAutoComplete] result: ",h),h)},[f]),w=o.useCallback((m,h)=>{if(n.history.position!==null)return;h.setCurrentInput(m),k.debug("[useCommandParser][handleInputChange] newValue: ",m);const v=d();if(v.type==="argument"||r==="entering_argument"){const H=Ne(m);if(H.isQuoted)if(H.isComplete){if(!(v instanceof j))return;v.value=m.trim()||"",k.debug("[useCommandParser][handleInputChange][entering_command] pushing: ",v),s.push(v),h.setCurrentInput(""),a("idle");return}else return;else if(H.isComplete){if(!(v instanceof j))return;v.value=m.trim()||"",k.debug("[useCommandParser][handleInputChange][entering_command] pushing: ",v),s.push(v),h.setCurrentInput(""),a("idle");return}else return}if(m.endsWith(" ")){const H=m.trim().toLowerCase(),z=e.getCompletions(s.path()).filter(I=>I.type==="word"&&I.name.toLowerCase()===H);if(z.length===1){s.push(z[0]),h.setCurrentInput(""),a("idle");return}}const b=y(m);if(b.type==="word"){k.debug("[useCommandParser][handleInputChange][entering_command] pushing: ",b),s.push(b),h.setCurrentInput(""),a("idle");return}},[y,n,d,r,s,e]),S=o.useCallback(m=>{m.setCurrentInput(""),m.setIsEnteringArg(!1),s.clear(),a("idle")},[s]),N=o.useCallback((m,h,v)=>{if(!(m.key==="Backspace"||m.key==="Enter"||m.key==="ArrowUp"||m.key==="ArrowDown"||m.key==="ArrowLeft"||m.key==="ArrowRight"||m.key==="Escape"||m.key==="Delete"||m.key==="Home"||m.key==="End"||m.key.length===1))return!0;const{currentInput:b,isEnteringArg:H}=h,z=Ne(b);switch(m.key){case"Backspace":return b===""&&(m.preventDefault(),s.size()>0&&s.pop(),a("idle")),!0;case"Enter":{if(m.preventDefault(),z.isQuoted&&!z.isComplete)return!0;if(r==="entering_argument"||H&&b.trim()){const D=d();D instanceof j&&(D.value=b,k.debug("[handleKeyDown][Enter]['entering_argument'] pushing: ",D),s.push(D))}const I=s.path(),O=e.getCommand(I);if(!O)return!1;const M=O.segments.filter(D=>D.type==="argument"),V=s.arguments;return M.length>V.length?!1:(k.debug("[handleKeyDown][Enter] calling actions.executeCommand. segmentStack: ",s),v.executeCommand(),t.addStoredCommand(s.toArray()),S(v),!0)}case"ArrowUp":return m.preventDefault(),(async()=>{const I=await t.navigateHistory("up");return I.segments&&(s.clear(),s.pushAll(I.segments),v.setCurrentInput("")),!0})();case"ArrowDown":return m.preventDefault(),(async()=>{const I=await t.navigateHistory("down");return I.segments&&(s.clear(),s.pushAll(I.segments),v.setCurrentInput("")),!0})();default:{if(!H&&m.key.length===1){const I=b+m.key;if(!p(I))return m.preventDefault(),!1}return!0}}},[r,p,d,t,S,e,s]);return{handleInputChange:w,handleKeyDown:N,inputState:r,setInputStateWithLogging:a,findMatchingCommands:u,getAutocompleteSuggestion:f,getAvailableNodes:l,getNextExpectedSegment:d,isValidCommandInput:p}};function Ne(n){const e=[];let t="",s=!1,r;for(let i=0;i<n.length;i++){const a=n[i];(a==='"'||a==="'")&&(!s||a===r)?s?(e.push(t),t="",s=!1,r=void 0):(t&&(e.push(t),t=""),s=!0,r=a):!s&&a===" "?t&&(e.push(t),t=""):t+=a}return{words:e,currentWord:t,isQuoted:s,quoteChar:r,isComplete:!s&&!t}}const Ze=()=>{const n=B(),[e,t]=o.useState(0);return o.useEffect(()=>{const s={update:()=>{t(r=>r+1)}};return n.subscribe(s),()=>{n.unsubscribe(s)}},[n]),e},Re=({state:n,actions:e})=>{const t=o.useRef(null),s=X(),r=B(),{handleKeyDown:i,handleInputChange:a,inputState:d,setInputStateWithLogging:l,getNextExpectedSegment:u}=Qe(),[f,p]=o.useState(!1),y=L(),w=Ze(),S=o.useRef(null),[N,m]=o.useState(0),h=o.useMemo(()=>Z(y.fontFamily,y.fontSize),[y.fontFamily,y.fontSize]),v=o.useCallback(async x=>{const A=i(x,n,e);await Promise.resolve(A)===!1&&(p(!0),setTimeout(()=>p(!1),500))},[e,i,n]),T=o.useCallback(x=>{a(x.target.value,e)},[e,a]),b=o.useCallback(x=>{x.preventDefault();const A=x.clipboardData.getData("text");a(A,e)},[e,a]);o.useEffect(()=>{t.current&&t.current.focus(),d!=="entering_command"&&l("entering_command")},[d,l]),o.useEffect(()=>{if(d!=="idle")return;const x=u();let A="idle";switch(x.type){case"word":A="entering_command",e.setIsEnteringArg(!1);break;case"argument":A="entering_argument",e.setIsEnteringArg(!0);break}l(A)},[w,d,u,l,e]);const H=o.useMemo(()=>{const x=[],A=r.toArray().map((P,G)=>{x.push(P.name);const te=s.hasNextSegment(x);if(P.type==="argument"){const Y=P;return c.jsxs(o.Fragment,{children:[c.jsx("span",{className:"citadel-input-segment-arg",children:Y.value}),G<r.size()&&te&&c.jsx("span",{className:"citadel-input-segment-space",children:" "})]},"arg-"+Y.name+Y.value)}return c.jsxs(o.Fragment,{children:[c.jsx("span",{className:"citadel-input-segment-word",children:P.name}),G<r.size()&&te&&c.jsx("span",{className:"citadel-input-segment-space citadel-input-segment-space-command",children:" "})]},"word-"+P.name)});return[c.jsx("div",{className:"citadel-input-segments","data-testid":"user-input-area",children:A},w)]},[w,s,r]),[z,I]=o.useState("");o.useEffect(()=>{const x=u();x.type==="argument"?I(x.name):I("")},[w,u]);const M=!n.isEnteringArg?"is-command-mode":"is-argument-mode",V=o.useMemo(()=>({left:`${N}px`,transition:"left 0.05s ease-out"}),[N]),D=o.useMemo(()=>({type:y.cursorType??E.cursorType,color:y.cursorColor||E.cursorColor,speed:y.cursorSpeed||E.cursorSpeed}),[y.cursorColor,y.cursorSpeed,y.cursorType]);return o.useLayoutEffect(()=>{const x=S.current,A=t.current;if(!x||!A){m(0);return}const P=x.getBoundingClientRect().width;m(Math.max(0,P-A.scrollLeft))},[n.currentInput,M,h.style]),c.jsx("div",{className:"citadel-input-shell",children:c.jsxs("div",{className:"citadel-input-line",style:h.style,children:[c.jsx("div",{className:"citadel-input-prompt",children:">"}),c.jsxs("div",{className:"citadel-input-row",children:[H,c.jsxs("div",{className:"citadel-input-control",children:[c.jsx("span",{ref:S,className:`citadel-input-measure ${M}`.trim(),"aria-hidden":"true",children:n.currentInput}),c.jsx("input",{ref:t,type:"text",role:"textbox",value:n.currentInput,onChange:T,onKeyDown:v,onPaste:b,"data-testid":"citadel-command-input",className:`citadel-input-field ${M} ${f?"invalid-input-animation":""}`.trim(),spellCheck:!1,autoComplete:"off",placeholder:z}),c.jsx("div",{className:"citadel-input-cursor",style:V,children:c.jsx(Je,{style:D})})]})]})]})})},et=({currentInput:n=""})=>{const e=X(),t=L(),s=B(),r=o.useMemo(()=>Z(t.fontFamily,t.fontSize),[t.fontFamily,t.fontSize]),i=n.trim().toLowerCase(),a=e.getMatchingCompletions(s.path(),i);k.debug("[AvailableCommands] nextCommandSegments: ",a);const d=o.useMemo(()=>{const p=[...a],y=m=>m.name.toLowerCase()==="help",w=p.filter(y);return[...p.filter(m=>!y(m)).sort((m,h)=>m.name.localeCompare(h.name,void 0,{sensitivity:"base"})),...w]},[a]),l=o.useMemo(()=>{const p=new Map;for(const y of d){const w=d.reduce((S,N)=>{if(N===y)return S;let m=0;for(;m<y.name.length&&m<N.name.length&&y.name[m].toLowerCase()===N.name[m].toLowerCase();)m++;return Math.max(S,m+1)},1);p.set(y.name,w)}return p},[d]),u=a.some(p=>p.type==="argument"),f=a[0];return c.jsx("div",{className:"citadel-available-commands","data-testid":"available-commands",children:c.jsx("div",{className:"citadel-available-commands-content",style:r.style,children:u?a.length>0?c.jsxs(c.Fragment,{children:[c.jsx("span",{className:"citadel-available-next-arg",children:f.name}),f.description&&c.jsxs("span",{className:"citadel-available-next-desc",children:["- ",f.description]})]}):null:c.jsx("div",{className:"citadel-available-chip-list",children:d==null?void 0:d.map(p=>{const y=l.get(p.name)??1;return c.jsx("div",{"data-testid":"available-command-chip",className:"citadel-available-chip",children:c.jsxs("span",{className:"citadel-available-chip-text",children:[c.jsx("strong",{className:"citadel-available-chip-prefix",children:p.name.slice(0,y)}),p.name.slice(y)]})},p.name)})})})})},Ie=({state:n,actions:e,outputRef:t})=>{const s=L(),r=s.displayMode==="inline",i=s.showOutputPane??!0,a=o.useMemo(()=>i&&r?{overflow:"hidden"}:void 0,[r,i]);return c.jsxs("div",{className:"innerContainer citadel-tty",children:[i?c.jsx("div",{className:"citadel-tty-output-pane","data-testid":"citadel-output-pane",style:a,children:c.jsx(Ye,{output:n.output,outputRef:t})}):null,c.jsxs("div",{className:"citadel-tty-input-region",children:[c.jsx(Re,{state:n,actions:e}),c.jsx(et,{currentInput:n.isEnteringArg?"":n.currentInput})]})]})},R="128px",tt="200px",nt="80vh",ie=n=>{if(!n)return;const e=n.trim();if(e)return/^\d+(\.\d+)?$/.test(e)?`${e}px`:e},Ae=(n,e)=>{if(!n)return e;const t=n.trim();if(!t)return e;if(t.endsWith("vh")){const r=Number.parseFloat(t);return Number.isFinite(r)?window.innerHeight*r/100:e}const s=Number.parseFloat(t);return Number.isFinite(s)?s:e},st=()=>{const n=L(),e=n.showOutputPane??!0,t=ie(n.minHeight)??tt,s=ie(n.maxHeight)??nt,r=e?t:R,i=Number.parseFloat(R),[a,d]=o.useState(()=>{const P=ie(n.initialHeight);return e?P??null:R}),[l,u]=o.useState(()=>n.showOnLoad??!1),[f,p]=o.useState(!1),y=o.useRef(null),w=o.useRef(null),S=o.useRef(!1),N=o.useRef(0),m=o.useRef(0),h=o.useRef(null),v=o.useRef(a),T=o.useRef(e),{state:b,actions:H}=ae(),z=o.useCallback(()=>{p(!1),u(!0)},[]),I=o.useCallback(()=>{p(!0)},[]);qe({onOpen:z,onClose:I,isVisible:l&&!f,showCitadelKey:n.showCitadelKey||".",closeOnEscape:n.closeOnEscape??!0});const O=o.useCallback(P=>{if(!S.current)return;const G=P.clientY-N.current,te=Ae(s,window.innerHeight*80/100),Y=Ae(r,i),Te=Math.min(Math.max(m.current-G,Y),te);w.current&&(w.current.style.height=`${Te}px`,w.current.style.bottom="0",d(`${Te}px`))},[i,r,s]),M=o.useCallback(()=>{S.current=!1,document.documentElement.style.userSelect="",document.documentElement.style.webkitUserSelect="",document.documentElement.style.mozUserSelect="",document.documentElement.style.msUserSelect="",document.removeEventListener("mousemove",O),document.removeEventListener("mouseup",M)},[O]),V=o.useCallback(P=>{w.current&&(S.current=!0,N.current=P.clientY,m.current=w.current.offsetHeight,document.documentElement.style.userSelect="none",document.documentElement.style.webkitUserSelect="none",document.documentElement.style.mozUserSelect="none",document.documentElement.style.msUserSelect="none",document.addEventListener("mousemove",O),document.addEventListener("mouseup",M))},[O,M]);o.useEffect(()=>()=>{document.removeEventListener("mousemove",O),document.removeEventListener("mouseup",M)},[O,M]),o.useEffect(()=>{v.current=a},[a]),o.useEffect(()=>{if(!e){T.current&&(h.current=v.current??(w.current?`${w.current.offsetHeight}px`:null)),T.current=!1,d(R);return}T.current=!0,h.current&&(d(h.current),h.current=null)},[e]);const D=o.useCallback(()=>{f&&(u(!1),p(!1))},[f]),{animationClass:x}=We({isVisible:l,isClosing:f,onAnimationComplete:D}),A=o.useMemo(()=>({...a?{height:a}:{},minHeight:r,maxHeight:s}),[r,a,s]);return l?c.jsxs("div",{ref:w,className:`panelContainer ${x}`.trim(),style:A,children:[c.jsx("div",{className:"resizeHandle",onMouseDown:V}),c.jsx(Ie,{state:b,actions:H,outputRef:y})]}):null},le="128px",ce=n=>{if(!n)return;const e=n.trim();if(e)return/^\d+(\.\d+)?$/.test(e)?`${e}px`:e},rt=()=>{const{state:n,actions:e}=ae(),t=L(),s=t.showOutputPane??!0,r=o.useRef(null),i=o.useMemo(()=>({height:s?ce(t.initialHeight):le,maxHeight:s?ce(t.maxHeight):le,minHeight:s?ce(t.minHeight):le}),[t.initialHeight,t.maxHeight,t.minHeight,s]);return c.jsx("div",{className:"inlineContainer","data-testid":"citadel-inline-container",style:i,children:c.jsx(Ie,{state:n,actions:e,outputRef:r})})},Pe=`:host {
7
7
  --citadel-bg: oklch(20.8% 0.042 265.8);
8
8
  --citadel-surface: oklch(27.9% 0.041 260);
9
9
  --citadel-border: oklch(37.2% 0.044 257.3);
@@ -475,5 +475,5 @@ Check the definition of the ${l.join(".")} command and update the return type fo
475
475
  object-fit: contain;
476
476
  border-radius: 0.5rem;
477
477
  }
478
- `,Ze=({config:t=k,commandRegistry:e,containerId:n=null})=>{const s=a.useRef(new K),r=e??s.current,i=a.useRef(null),o=a.useMemo(()=>({width:"100%",height:"100%"}),[]),d=t.displayMode??k.displayMode??"panel";return a.useEffect(()=>{x.configure({level:t.logLevel||k.logLevel||R.ERROR,prefix:"[Citadel]"});const l=new Ee(r,t),u=d==="inline"&&!n,y=u?i.current:n?document.getElementById(n):document.body;if(y)y.appendChild(l);else{if(u){console.warn("[Citadel] No host available for inline mode; skipping mount.");return}console.warn(`Container with id "${n}" not found, falling back to body`),document.body.appendChild(l)}return()=>{var p;(p=l.parentElement)==null||p.removeChild(l)}},[r,n,t,d]),d==="inline"&&!n?c.jsx("div",{ref:i,style:o}):null};class Ee extends HTMLElement{constructor(n,s){var i;super();C(this,"shadow");C(this,"root",null);C(this,"commandRegistry");C(this,"config");this.shadow=this.attachShadow({mode:"open"}),this.commandRegistry=n,this.config=s;const r=((i=this.config)==null?void 0:i.displayMode)??"panel";this.setAttribute("data-display-mode",r)}connectedCallback(){try{const s=[ke].map(r=>{const i=new CSSStyleSheet;return i.replaceSync(r),i});this.shadow.adoptedStyleSheets=[...s]}catch{const s=[ke].join(`
479
- `),r=document.createElement("style");r.textContent=s,this.shadow.appendChild(r)}const n=document.createElement("div");n.id="citadel-root",n.style.width="100%",n.style.height="100%",this.shadow.appendChild(n),this.root=Me.createRoot(n),this.root.render(c.jsx(De,{config:this.config||k,commandRegistry:this.commandRegistry,children:c.jsx(Re,{})}))}disconnectedCallback(){const n=this.root;if(this.root=null,!n){this.shadow.replaceChildren();return}queueMicrotask(()=>{n.unmount(),this.shadow.replaceChildren()})}}typeof window<"u"&&window.customElements&&!window.customElements.get("citadel-element")&&window.customElements.define("citadel-element",Ee);const Re=()=>(T().displayMode??"panel")==="inline"?c.jsx(Xe,{}):c.jsx(Qe,{});class et{constructor(){C(this,"_description")}describe(e){return this._description=e,this}get description(){return this._description}}class tt{constructor(e){C(this,"state");this.state={path:e,description:"",segments:nt(e)}}describe(e){return this.state.description=e,this}details(e){return this.state.details=e,this}arg(e,n){const s=new et;return n==null||n(s),this.state.segments.push({type:"argument",name:e,description:s.description}),this}handle(e){return{path:this.state.path,description:this.state.description,details:this.state.details,segments:[...this.state.segments],handler:e}}}function nt(t){const e=t.trim();if(!e)throw new Error("Command path cannot be empty");const n=e.split(".");if(n.some(s=>s.trim()===""))throw new Error(`Invalid command path "${t}". Empty segments are not allowed.`);if(n.some(s=>s.includes(" ")))throw new Error(`Invalid command path "${t}". Use dot-delimited words (e.g. "user.show").`);return n.map(s=>({type:"word",name:s}))}function st(t){return t.flatMap(e=>e.type==="argument"?[e.name]:[])}function rt(t){const e=st(t.segments);return async n=>{const s=e.reduce((r,i,o)=>(r[i]=n[o],r),{});return Promise.resolve(t.handler({rawArgs:n,namedArgs:s,commandPath:t.path}))}}function at(t){return new tt(t)}function Ne(t,e){t.addCommand(e.segments,e.description,rt(e))}function Ie(t,e){return e.forEach(n=>Ne(t,n)),t}function ot(t){const e=new K;return Ie(e,t)}function it(t){return new q(t)}function lt(t,e="true",n="false"){return new ie(t,e,n)}function ct(t){return new oe(t)}function dt(t,e=""){return new ce(t,e)}function mt(t){return new Z(t)}g.BooleanCommandResult=ie,g.Citadel=Ze,g.CommandRegistry=K,g.CommandResult=_,g.CommandStatus=j,g.DEFAULT_CURSOR_CONFIGS=we,g.ErrorCommandResult=Z,g.ImageCommandResult=ce,g.JsonCommandResult=oe,g.OutputItem=G,g.PendingCommandResult=le,g.TextCommandResult=q,g.bool=lt,g.command=at,g.createCommandRegistry=ot,g.error=mt,g.image=dt,g.json=ct,g.registerCommand=Ne,g.registerCommands=Ie,g.text=it,Object.defineProperty(g,Symbol.toStringTag,{value:"Module"})});
478
+ `,ot=({config:n=E,commandRegistry:e,containerId:t=null})=>{const s=o.useRef(new K),r=e??s.current,i=o.useRef(null),a=o.useMemo(()=>({width:"100%",height:"100%"}),[]),d=n.displayMode??E.displayMode??"panel";return o.useEffect(()=>{k.configure({level:n.logLevel||E.logLevel||se.ERROR,prefix:"[Citadel]"});const l=new He(r,n),u=d==="inline"&&!t,f=u?i.current:t?document.getElementById(t):document.body;if(f)f.appendChild(l);else{if(u){console.warn("[Citadel] No host available for inline mode; skipping mount.");return}console.warn(`Container with id "${t}" not found, falling back to body`),document.body.appendChild(l)}return()=>{var p;(p=l.parentElement)==null||p.removeChild(l)}},[r,t,n,d]),d==="inline"&&!t?c.jsx("div",{ref:i,style:a}):null};class He extends HTMLElement{constructor(t,s){var i;super();C(this,"shadow");C(this,"root",null);C(this,"commandRegistry");C(this,"config");this.shadow=this.attachShadow({mode:"open"}),this.commandRegistry=t,this.config=s;const r=((i=this.config)==null?void 0:i.displayMode)??"panel";this.setAttribute("data-display-mode",r)}connectedCallback(){try{const s=[Pe].map(r=>{const i=new CSSStyleSheet;return i.replaceSync(r),i});this.shadow.adoptedStyleSheets=[...s]}catch{const s=[Pe].join(`
479
+ `),r=document.createElement("style");r.textContent=s,this.shadow.appendChild(r)}const t=document.createElement("div");t.id="citadel-root",t.style.width="100%",t.style.height="100%",this.shadow.appendChild(t),this.root=Oe.createRoot(t),this.root.render(c.jsx($e,{config:this.config||E,commandRegistry:this.commandRegistry,children:c.jsx(at,{})}))}disconnectedCallback(){const t=this.root;if(this.root=null,!t){this.shadow.replaceChildren();return}queueMicrotask(()=>{t.unmount(),this.shadow.replaceChildren()})}}typeof window<"u"&&window.customElements&&!window.customElements.get("citadel-element")&&window.customElements.define("citadel-element",He);const at=()=>(L().displayMode??"panel")==="inline"?c.jsx(rt,{}):c.jsx(st,{});class it{constructor(){C(this,"_description")}describe(e){return this._description=e,this}get description(){return this._description}}class lt{constructor(e){C(this,"state");this.state={path:e,description:"",segments:ct(e)}}describe(e){return this.state.description=e,this}details(e){return this.state.details=e,this}arg(e,t){const s=new it;return t==null||t(s),this.state.segments.push({type:"argument",name:e,description:s.description}),this}handle(e){return{path:this.state.path,description:this.state.description,details:this.state.details,segments:[...this.state.segments],handler:e}}}function ct(n){const e=n.trim();if(!e)throw new Error("Command path cannot be empty");const t=e.split(".");if(t.some(s=>s.trim()===""))throw new Error(`Invalid command path "${n}". Empty segments are not allowed.`);if(t.some(s=>s.includes(" ")))throw new Error(`Invalid command path "${n}". Use dot-delimited words (e.g. "user.show").`);return t.map(s=>({type:"word",name:s}))}function dt(n){return n.flatMap(e=>e.type==="argument"?[e.name]:[])}function mt(n){const e=dt(n.segments);return async t=>{const s=e.reduce((r,i,a)=>(r[i]=t[a],r),{});return Promise.resolve(n.handler({rawArgs:t,namedArgs:s,commandPath:n.path}))}}function ut(n){return new lt(n)}function Me(n,e){n.addCommand(e.segments,e.description,mt(e))}function _e(n,e){return e.forEach(t=>Me(n,t)),n}function pt(n){const e=new K;return _e(e,n)}function ht(n){return new q(n)}function gt(n,e="true",t="false"){return new me(n,e,t)}function ft(n){return new de(n)}function yt(n,e=""){return new pe(n,e)}function Ct(n){return new ne(n)}g.BooleanCommandResult=me,g.Citadel=ot,g.CommandRegistry=K,g.CommandResult=F,g.CommandStatus=$,g.DEFAULT_CURSOR_CONFIGS=xe,g.ErrorCommandResult=ne,g.ImageCommandResult=pe,g.JsonCommandResult=de,g.OutputItem=Q,g.PendingCommandResult=ue,g.TextCommandResult=q,g.bool=gt,g.command=ut,g.createCommandRegistry=pt,g.error=Ct,g.image=yt,g.json=ft,g.registerCommand=Me,g.registerCommands=_e,g.text=ht,Object.defineProperty(g,Symbol.toStringTag,{value:"Module"})});
@@ -1,9 +1,9 @@
1
- (function(g,c){typeof exports=="object"&&typeof module<"u"?c(exports,require("react/jsx-runtime"),require("react"),require("react-dom/client")):typeof define=="function"&&define.amd?define(["exports","react/jsx-runtime","react","react-dom/client"],c):(g=typeof globalThis<"u"?globalThis:g||self,c(g.Citadel={},g.jsxRuntime,g.React,g.client))})(this,function(g,c,a,Me){"use strict";var ut=Object.defineProperty;var pt=(g,c,a)=>c in g?ut(g,c,{enumerable:!0,configurable:!0,writable:!0,value:a}):g[c]=a;var C=(g,c,a)=>pt(g,typeof c!="symbol"?c+"":c,a);var j=(t=>(t.Pending="pending",t.Success="success",t.Failure="failure",t.Timeout="timeout",t))(j||{});class _{constructor(e=Date.now()){C(this,"_status","pending");this.timestamp=e}get status(){return this._status}markSuccess(){this._status="success"}markFailure(){this._status="failure"}markTimeout(){this._status="timeout"}}class oe extends _{constructor(e,n){super(n),this.data=e}render(){return c.jsx("pre",{className:"citadel-result-json",children:JSON.stringify(this.data,null,2)})}}class q extends _{constructor(e,n){super(n),this.text=e}render(){return c.jsx("div",{className:"citadel-result-text",children:this.text})}}class ie extends _{constructor(e,n="true",s="false",r){super(r),this.value=e,this.trueText=n,this.falseText=s}render(){return c.jsx("div",{className:"citadel-result-text citadel-result-boolean",children:this.value?this.trueText:this.falseText})}}class Z extends _{constructor(e,n){super(n),this.error=e,this.markFailure()}render(){return c.jsx("div",{className:"citadel-result-error",children:this.error})}}class le extends _{render(){return c.jsx("div",{className:"citadel-result-pending",children:"..."})}}class ce extends _{constructor(e,n="",s){super(s),this.imageUrl=e,this.altText=n}render(){return c.jsx("div",{className:"citadel-result-image-wrap",children:c.jsx("img",{src:this.imageUrl,alt:this.altText,className:"citadel-result-image"})})}}const Pe=t=>async function(){const n=t.commands.filter(s=>s.fullPath[0]!=="help").map(s=>{const i=`${s.segments.map(d=>d.type==="argument"?`<${d.name}>`:d.name).join(" ")} - ${s.description}`,o=s.segments.filter(d=>d.type==="argument"&&d.description).map(d=>` <${d.name}>: ${d.description}`);return{commandLine:i,argumentLines:o}}).sort((s,r)=>s.commandLine.localeCompare(r.commandLine)).flatMap(s=>[s.commandLine,...s.argumentLines]);return n.length===0?new q("No commands available yet. Add some commands to get started!"):(n.push("help - Show available commands"),new q(`Available Commands:
2
- `+n.join(`
3
- `)))};var R=(t=>(t[t.NONE=0]="NONE",t[t.ERROR=1]="ERROR",t[t.WARN=2]="WARN",t[t.INFO=3]="INFO",t[t.DEBUG=4]="DEBUG",t[t.TRACE=5]="TRACE",t))(R||{});const de=!0;class x{static configure(e){this.level=e.level,this.prefix=e.prefix||"[Citadel]"}static trace(...e){this.level>=5&&!de&&console.trace(this.prefix,...e)}static debug(...e){this.level>=4&&!de&&console.debug(this.prefix,...e)}static info(...e){this.level>=3&&console.info(this.prefix,...e)}static warn(...e){this.level>=2&&console.warn(this.prefix,...e)}static error(...e){this.level>=1&&console.error(this.prefix,...e)}}C(x,"level",0),C(x,"prefix","");const k={commandTimeoutMs:1e4,cursorColor:"var(--cursor-color, #fff)",cursorSpeed:530,cursorType:"blink",includeHelpCommand:!0,fontFamily:"monospace",fontSize:"0.875rem",initialHeight:"50vh",logLevel:R.ERROR,maxHeight:"80vh",minHeight:"200",outputFontSize:"0.875rem",resetStateOnHide:!1,closeOnEscape:!0,showCitadelKey:".",showOnLoad:!1,displayMode:"panel",storage:{type:"localStorage",maxCommands:100}},me=async()=>new q("");class ee{constructor(e,n,s){this.type=e,this.name=n,this.description=s}toString(){return this.name}}class te extends ee{constructor(){super("null",">null<","Empty segment")}}class ue extends ee{constructor(e,n){super("word",e,n)}}class U extends ee{constructor(e,n,s,r){super("argument",e,n),this.value=s,this.valid=r}}const He=t=>{if(t.type==="word")return new ue(t.name,t.description);if(t.type==="argument"){const e=t;return new U(e.name,e.description,e.value,e.valid)}return new te},H=t=>t.map(e=>He(e));class _e{constructor(e,n,s=me){C(this,"_segments");C(this,"_description");C(this,"_handler");this._segments=e,this._description=n,this._handler=s}get segments(){return this._segments}get description(){return this._description}get handler(){return this._handler}get hasArguments(){return this.segments.some(e=>e.type==="argument")}get fullPath(){return this.segments.map(e=>e.name)}get fullPath_s(){return this.fullPath.join(" ")}equals(e){return this.fullPath.join(" ")===e.fullPath.join(" ")}}class K{constructor(){C(this,"_commands",[])}get commands(){return this._commands}addCommand(e,n,s=me){if(e===void 0||e.length===0)throw new Error("Command path cannot be empty");const r=new _e(e,n,s),i=this._commands.find(o=>{const d=o.segments.map(u=>u.type==="argument"?"*":u.name).join(" "),l=e.map(u=>u.type==="argument"?"*":u.name).join(" ");return d===l});if(i)throw new Error(`Duplicate commands: '${i.fullPath_s}' and '${r.fullPath_s}'`);this._commands.push(r)}removeCommand(e){const n=e.join(" "),s=this._commands.findIndex(r=>r.fullPath.join(" ")===n);return s===-1?!1:(this._commands.splice(s,1),!0)}getCommand(e){return this._commands.find(n=>{const s=n.fullPath.join(" "),r=e.join(" ");if(s===r)return!0;const o=n.segments.filter(d=>d.type==="word").map(d=>d.name);return o.length===e.length&&o.join(" ")===r})}commandExistsForPath(e){const n=this._commands.map(r=>r.segments.map(i=>i.type==="argument"?"*":i.name).join(" ")),s=e.map((r,i)=>this._commands.some(d=>{var l;return((l=d.segments[i])==null?void 0:l.type)==="argument"})?"*":r).join(" ");return n.includes(s)}getCompletionNames(e){return this.getCompletions(e).map(n=>n.name)}getMatchingCompletions(e,n){const s=n.trim().toLowerCase(),r=this.getCompletions(e);return s?r.filter(i=>i.name.toLowerCase().startsWith(s)):r}getUniqueCompletion(e,n){const s=this.getMatchingCompletions(e,n);if(s.length===1)return s[0]}getCompletions(e){if(x.debug("[getCompletions] path: ",e),!e.length){const i=this._commands.map(l=>l.segments[0]),o=(l,u)=>l.type===u.type&&l.name===u.name;return i.filter((l,u,y)=>u===y.findIndex(p=>o(p,l)))}const n=e.length;return this._commands.filter(i=>{const o=i.segments;if(o.length<=n-1)return!1;for(let d=0;d<n;d++){const l=e[d],u=o[d];if(!(l==="*"&&u.type==="argument")&&l!==u.name)return!1}return!0}).filter(i=>i.segments.length>n).map(i=>{const o=i.segments[n],d=o.type==="argument"?U:ue;return new d(o.name,o.description)}).filter((i,o,d)=>o===d.findIndex(l=>l.type===i.type&&l.name===i.name))}hasNextSegment(e){return this.getCompletions(e).length>0}}class pe{constructor(e){C(this,"config");this.config={type:"localStorage",maxCommands:100,...e}}async addStoredCommand(e){const n=await this.getStoredCommands();for(n.push(e);n.length>this.config.maxCommands;)n.shift();await this.saveCommands(n)}}class Te extends pe{constructor(n){super(n);C(this,"storageKey","citadel_command_history")}async getStoredCommands(){try{const n=window.localStorage.getItem(this.storageKey);return n?JSON.parse(n).map(r=>({commandSegments:Array.isArray(r.commandSegments)?H(r.commandSegments):[],timestamp:r.timestamp})):[]}catch(n){return console.warn("Failed to load commands from localStorage:",n),[]}}async clear(){try{window.localStorage.removeItem(this.storageKey)}catch(n){console.warn("Failed to clear localStorage:",n)}}async saveCommands(n){try{const s=n.map(r=>({commandSegments:Array.isArray(r.commandSegments)?H(r.commandSegments).map(i=>({type:i.type,name:i.name,description:i.description,...i instanceof U?{value:i.value}:{}})):[],timestamp:r.timestamp}));window.localStorage.setItem(this.storageKey,JSON.stringify(s))}catch(s){throw console.warn("Failed to save commands to localStorage:",s),s}}}class he extends pe{constructor(n){super(n);C(this,"storedCommands",[])}async getStoredCommands(){return this.storedCommands.map(n=>({commandSegments:Array.isArray(n.commandSegments)?H(n.commandSegments):[],timestamp:n.timestamp}))}async clear(){this.storedCommands=[]}async saveCommands(n){this.storedCommands=n.map(s=>({commandSegments:Array.isArray(s.commandSegments)?H(s.commandSegments):[],timestamp:s.timestamp}))}}const z=class z{constructor(){C(this,"currentStorage")}static reset(){z.instance=void 0}static getInstance(){return z.instance||(z.instance=new z),z.instance}initializeStorage(e){try{e.type==="memory"?this.currentStorage=new he(e):this.currentStorage=new Te(e)}catch(n){console.warn("Failed to create storage, falling back to memory storage:",n),this.currentStorage=new he(e)}}getStorage(){if(!this.currentStorage)throw new Error("Storage not initialized. Call initializeStorage first.");return this.currentStorage}};C(z,"instance");let Y=z;class ge{constructor(){C(this,"segments",[]);C(this,"nullSegment",new te);C(this,"observers",[])}subscribe(e){this.observers.push(e)}unsubscribe(e){this.observers=this.observers.filter(n=>n!==e)}notifyObservers(){this.observers.forEach(e=>e.update())}clear(){this.segments=[],this.notifyObservers()}push(e){this.segments.push(e),this.notifyObservers()}pushAll(e){e.forEach(n=>this.push(n))}pop(){const e=this.segments.pop()||this.nullSegment;return this.notifyObservers(),e}peek(){return this.segments[this.segments.length-1]||this.nullSegment}size(){return this.segments.length}isEmpty(){return this.segments.length===0}get hasArguments(){return this.segments.some(e=>e.type==="argument")}get arguments(){return this.segments.filter(e=>e.type==="argument")}path(){return this.segments.map(e=>e.name)}toArray(){return[...this.segments]}}const ze={config:k,commands:new K,segmentStack:new ge},W=a.createContext(ze),De=({config:t=k,commandRegistry:e,children:n})=>{const[s,r]=a.useState(),[i]=a.useState(()=>new ge),o=a.useMemo(()=>({...k,...t,storage:{...k.storage,...t.storage},cursorType:t.cursorType??k.cursorType,cursorColor:t.cursorColor??k.cursorColor,cursorSpeed:t.cursorSpeed??k.cursorSpeed,closeOnEscape:t.closeOnEscape??k.closeOnEscape,showCitadelKey:t.showCitadelKey??k.showCitadelKey,showOnLoad:t.showOnLoad??k.showOnLoad}),[t]);a.useEffect(()=>{Y.getInstance().initializeStorage(o.storage??k.storage),r(Y.getInstance().getStorage())},[o.storage]),a.useEffect(()=>{if(e){if(o.includeHelpCommand){if(!e.commandExistsForPath(["help"])){const l=Pe(e);e.addCommand([{type:"word",name:"help"}],"Show available commands",l)}return}e.removeCommand(["help"])}},[e,o.includeHelpCommand]);const d=a.useMemo(()=>({config:o,commands:e||new K,storage:s,segmentStack:i}),[o,e,s,i]);return c.jsx(W.Provider,{value:d,children:n})},T=()=>{const t=a.useContext(W);if(t===void 0)throw new Error("useCitadelConfig must be used within a CitadelConfigProvider");return t.config},J=()=>{const t=a.useContext(W);if(t===void 0)throw new Error("useCitadelCommands must be used within a CitadelConfigProvider");return t.commands},fe=()=>{const t=a.useContext(W);if(t===void 0)throw new Error("useCitadelStorage must be used within a CitadelConfigProvider");return t.storage},B=()=>{const t=a.useContext(W);if(t===void 0)throw new Error("useSegmentStack must be used within a CitadelConfigProvider");return t.segmentStack},X=class X{constructor(e,n){C(this,"id");C(this,"timestamp");C(this,"command");C(this,"result");this.id=`output-${Date.now()}-${X.idCounter++}`,this.command=e.toArray().map(s=>s.type==="argument"?s.value||"":s.name),this.timestamp=Date.now(),this.result=n??new le}};C(X,"idCounter",0);let G=X;function Oe(t){return{commandSegments:H(t),timestamp:Date.now()}}function ye(){const t=fe(),[e,n]=a.useState({storedCommands:[],position:null}),s=a.useCallback(async d=>{if(t)try{const l=Oe(d);await t.addStoredCommand(l),n(u=>({...u,storedCommands:[...u.storedCommands,{...l,commandSegments:H(l.commandSegments)}],position:null}))}catch(l){console.warn("Failed to save command to history:",l)}},[t]),r=a.useCallback(async()=>t?(await t.getStoredCommands()).map(l=>({...l,commandSegments:H(l.commandSegments)})):[],[t]);a.useEffect(()=>{if(!t)return;(async()=>{try{const u=(await t.getStoredCommands()).map(y=>({...y,commandSegments:H(y.commandSegments)}));return n(y=>({...y,storedCommands:u})),u}catch(l){console.warn("Failed to load command history:",l)}})()},[t]);const i=a.useCallback(async d=>{const l=await r();if(l.length===0)return n(p=>({...p,storedCommands:[],position:null})),{segments:null,position:null};let u=null;if(d==="up"?e.position===null?u=l.length-1:e.position>0?u=e.position-1:u=0:e.position===null||e.position>=l.length-1?u=null:u=e.position+1,n(p=>({...p,storedCommands:l.map(f=>({...f,commandSegments:H(f.commandSegments)})),position:u})),u===null)return{segments:[],position:null};const y=l[u];return y?{segments:H(y.commandSegments),position:u}:{segments:[],position:null}},[e.position,r]),o=a.useCallback(async()=>{try{if(!t)return;await t.clear(),n({storedCommands:[],position:null})}catch(d){console.warn("Failed to clear command history:",d)}},[t]);return{history:e,addStoredCommand:s,getStoredCommands:r,navigateHistory:i,clear:o}}const ne=()=>{const t=T(),e=J(),n=ye(),s=B(),r=fe(),[i,o]=a.useState({currentInput:"",isEnteringArg:!1,output:[],history:{commands:[],position:null,storage:r}});a.useEffect(()=>{},[r]),a.useEffect(()=>{o(l=>({...l,history:{commands:n.history.storedCommands,position:n.history.position,storage:r}}))},[n.history,r]);const d={setCurrentInput:a.useCallback(l=>{x.debug("[CitadelActions] setCurrentInput: ",l),o(u=>({...u,currentInput:l}))},[]),setIsEnteringArg:a.useCallback(l=>{x.debug("[CitadelActions] setIsEnteringArg: ",l),o(u=>({...u,isEnteringArg:l}))},[]),addOutput:a.useCallback(l=>{x.debug("[CitadelActions]addOutput: ",l),o(u=>({...u,output:[...u.output,l]}))},[]),executeCommand:a.useCallback(async()=>{const l=s.path(),u=e.getCommand(l);if(!u){console.error("[CitadelActions][executeCommand] Cannot execute command because no command was found for the given path: ",l);return}const y=new G(s);o(p=>({...p,output:[...p.output,y]}));try{const p=new Promise((v,E)=>{setTimeout(()=>{E(new Error("Request timed out"))},t.commandTimeoutMs)}),f=s.arguments.map(v=>v.value||""),b=await Promise.race([u.handler(f),p]);if(!(b instanceof _))throw new Error(`The ${l.join(".")} command returned an invalid result type. Commands must return an instance of a CommandResult.
1
+ (function(g,c){typeof exports=="object"&&typeof module<"u"?c(exports,require("react/jsx-runtime"),require("react"),require("react-dom/client")):typeof define=="function"&&define.amd?define(["exports","react/jsx-runtime","react","react-dom/client"],c):(g=typeof globalThis<"u"?globalThis:g||self,c(g.Citadel={},g.jsxRuntime,g.React,g.client))})(this,function(g,c,o,Oe){"use strict";var wt=Object.defineProperty;var vt=(g,c,o)=>c in g?wt(g,c,{enumerable:!0,configurable:!0,writable:!0,value:o}):g[c]=o;var C=(g,c,o)=>vt(g,typeof c!="symbol"?c+"":c,o);var $=(n=>(n.Pending="pending",n.Success="success",n.Failure="failure",n.Timeout="timeout",n))($||{});class F{constructor(e=Date.now()){C(this,"_status","pending");this.timestamp=e}get status(){return this._status}markSuccess(){this._status="success"}markFailure(){this._status="failure"}markTimeout(){this._status="timeout"}}class de extends F{constructor(e,t){super(t),this.data=e}render(){return c.jsx("pre",{className:"citadel-result-json",children:JSON.stringify(this.data,null,2)})}}class q extends F{constructor(e,t){super(t),this.text=e}render(){return c.jsx("div",{className:"citadel-result-text",children:this.text})}}class me extends F{constructor(e,t="true",s="false",r){super(r),this.value=e,this.trueText=t,this.falseText=s}render(){return c.jsx("div",{className:"citadel-result-text citadel-result-boolean",children:this.value?this.trueText:this.falseText})}}class ne extends F{constructor(e,t){super(t),this.error=e,this.markFailure()}render(){return c.jsx("div",{className:"citadel-result-error",children:this.error})}}class ue extends F{render(){return c.jsx("div",{className:"citadel-result-pending",children:"..."})}}class pe extends F{constructor(e,t="",s){super(s),this.imageUrl=e,this.altText=t}render(){return c.jsx("div",{className:"citadel-result-image-wrap",children:c.jsx("img",{src:this.imageUrl,alt:this.altText,className:"citadel-result-image"})})}}const De=n=>async function(){const t=n.commands.filter(s=>s.fullPath[0]!=="help").map(s=>{const i=`${s.segments.map(d=>d.type==="argument"?`<${d.name}>`:d.name).join(" ")} - ${s.description}`,a=s.segments.filter(d=>d.type==="argument"&&d.description).map(d=>` <${d.name}>: ${d.description}`);return{commandLine:i,argumentLines:a}}).sort((s,r)=>s.commandLine.localeCompare(r.commandLine)).flatMap(s=>[s.commandLine,...s.argumentLines]);return t.length===0?new q("No commands available yet. Add some commands to get started!"):(t.push("help - Show available commands"),new q(`Available Commands:
2
+ `+t.join(`
3
+ `)))};var se=(n=>(n[n.NONE=0]="NONE",n[n.ERROR=1]="ERROR",n[n.WARN=2]="WARN",n[n.INFO=3]="INFO",n[n.DEBUG=4]="DEBUG",n[n.TRACE=5]="TRACE",n))(se||{});const he=!0;class k{static configure(e){this.level=e.level,this.prefix=e.prefix||"[Citadel]"}static trace(...e){this.level>=5&&!he&&console.trace(this.prefix,...e)}static debug(...e){this.level>=4&&!he&&console.debug(this.prefix,...e)}static info(...e){this.level>=3&&console.info(this.prefix,...e)}static warn(...e){this.level>=2&&console.warn(this.prefix,...e)}static error(...e){this.level>=1&&console.error(this.prefix,...e)}}C(k,"level",0),C(k,"prefix","");const E={commandTimeoutMs:1e4,cursorColor:"var(--cursor-color, #fff)",cursorSpeed:530,cursorType:"blink",includeHelpCommand:!0,fontFamily:"monospace",fontSize:"0.875rem",initialHeight:"50vh",logLevel:se.ERROR,maxHeight:"80vh",minHeight:"200",outputFontSize:"0.875rem",showOutputPane:!0,resetStateOnHide:!1,closeOnEscape:!0,showCitadelKey:".",showOnLoad:!1,displayMode:"panel",storage:{type:"localStorage",maxCommands:100}},ge=async()=>new q("");class re{constructor(e,t,s){this.type=e,this.name=t,this.description=s}toString(){return this.name}}class oe extends re{constructor(){super("null",">null<","Empty segment")}}class fe extends re{constructor(e,t){super("word",e,t)}}class j extends re{constructor(e,t,s,r){super("argument",e,t),this.value=s,this.valid=r}}const ze=n=>{if(n.type==="word")return new fe(n.name,n.description);if(n.type==="argument"){const e=n;return new j(e.name,e.description,e.value,e.valid)}return new oe},_=n=>n.map(e=>ze(e));class Fe{constructor(e,t,s=ge){C(this,"_segments");C(this,"_description");C(this,"_handler");this._segments=e,this._description=t,this._handler=s}get segments(){return this._segments}get description(){return this._description}get handler(){return this._handler}get hasArguments(){return this.segments.some(e=>e.type==="argument")}get fullPath(){return this.segments.map(e=>e.name)}get fullPath_s(){return this.fullPath.join(" ")}equals(e){return this.fullPath.join(" ")===e.fullPath.join(" ")}}class K{constructor(){C(this,"_commands",[])}get commands(){return this._commands}addCommand(e,t,s=ge){if(e===void 0||e.length===0)throw new Error("Command path cannot be empty");const r=new Fe(e,t,s),i=this._commands.find(a=>{const d=a.segments.map(u=>u.type==="argument"?"*":u.name).join(" "),l=e.map(u=>u.type==="argument"?"*":u.name).join(" ");return d===l});if(i)throw new Error(`Duplicate commands: '${i.fullPath_s}' and '${r.fullPath_s}'`);this._commands.push(r)}removeCommand(e){const t=e.join(" "),s=this._commands.findIndex(r=>r.fullPath.join(" ")===t);return s===-1?!1:(this._commands.splice(s,1),!0)}getCommand(e){return this._commands.find(t=>{const s=t.fullPath.join(" "),r=e.join(" ");if(s===r)return!0;const a=t.segments.filter(d=>d.type==="word").map(d=>d.name);return a.length===e.length&&a.join(" ")===r})}commandExistsForPath(e){const t=this._commands.map(r=>r.segments.map(i=>i.type==="argument"?"*":i.name).join(" ")),s=e.map((r,i)=>this._commands.some(d=>{var l;return((l=d.segments[i])==null?void 0:l.type)==="argument"})?"*":r).join(" ");return t.includes(s)}getCompletionNames(e){return this.getCompletions(e).map(t=>t.name)}getMatchingCompletions(e,t){const s=t.trim().toLowerCase(),r=this.getCompletions(e);return s?r.filter(i=>i.name.toLowerCase().startsWith(s)):r}getUniqueCompletion(e,t){const s=this.getMatchingCompletions(e,t);if(s.length===1)return s[0]}getCompletions(e){if(k.debug("[getCompletions] path: ",e),!e.length){const i=this._commands.map(l=>l.segments[0]),a=(l,u)=>l.type===u.type&&l.name===u.name;return i.filter((l,u,f)=>u===f.findIndex(p=>a(p,l)))}const t=e.length;return this._commands.filter(i=>{const a=i.segments;if(a.length<=t-1)return!1;for(let d=0;d<t;d++){const l=e[d],u=a[d];if(!(l==="*"&&u.type==="argument")&&l!==u.name)return!1}return!0}).filter(i=>i.segments.length>t).map(i=>{const a=i.segments[t],d=a.type==="argument"?j:fe;return new d(a.name,a.description)}).filter((i,a,d)=>a===d.findIndex(l=>l.type===i.type&&l.name===i.name))}hasNextSegment(e){return this.getCompletions(e).length>0}}class ye{constructor(e){C(this,"config");this.config={type:"localStorage",maxCommands:100,...e}}async addStoredCommand(e){const t=await this.getStoredCommands();for(t.push(e);t.length>this.config.maxCommands;)t.shift();await this.saveCommands(t)}}class Le extends ye{constructor(t){super(t);C(this,"storageKey","citadel_command_history")}async getStoredCommands(){try{const t=window.localStorage.getItem(this.storageKey);return t?JSON.parse(t).map(r=>({commandSegments:Array.isArray(r.commandSegments)?_(r.commandSegments):[],timestamp:r.timestamp})):[]}catch(t){return console.warn("Failed to load commands from localStorage:",t),[]}}async clear(){try{window.localStorage.removeItem(this.storageKey)}catch(t){console.warn("Failed to clear localStorage:",t)}}async saveCommands(t){try{const s=t.map(r=>({commandSegments:Array.isArray(r.commandSegments)?_(r.commandSegments).map(i=>({type:i.type,name:i.name,description:i.description,...i instanceof j?{value:i.value}:{}})):[],timestamp:r.timestamp}));window.localStorage.setItem(this.storageKey,JSON.stringify(s))}catch(s){throw console.warn("Failed to save commands to localStorage:",s),s}}}class Ce extends ye{constructor(t){super(t);C(this,"storedCommands",[])}async getStoredCommands(){return this.storedCommands.map(t=>({commandSegments:Array.isArray(t.commandSegments)?_(t.commandSegments):[],timestamp:t.timestamp}))}async clear(){this.storedCommands=[]}async saveCommands(t){this.storedCommands=t.map(s=>({commandSegments:Array.isArray(s.commandSegments)?_(s.commandSegments):[],timestamp:s.timestamp}))}}const U=class U{constructor(){C(this,"currentStorage")}static reset(){U.instance=void 0}static getInstance(){return U.instance||(U.instance=new U),U.instance}initializeStorage(e){try{e.type==="memory"?this.currentStorage=new Ce(e):this.currentStorage=new Le(e)}catch(t){console.warn("Failed to create storage, falling back to memory storage:",t),this.currentStorage=new Ce(e)}}getStorage(){if(!this.currentStorage)throw new Error("Storage not initialized. Call initializeStorage first.");return this.currentStorage}};C(U,"instance");let J=U;class we{constructor(){C(this,"segments",[]);C(this,"nullSegment",new oe);C(this,"observers",[])}subscribe(e){this.observers.push(e)}unsubscribe(e){this.observers=this.observers.filter(t=>t!==e)}notifyObservers(){this.observers.forEach(e=>e.update())}clear(){this.segments=[],this.notifyObservers()}push(e){this.segments.push(e),this.notifyObservers()}pushAll(e){e.forEach(t=>this.push(t))}pop(){const e=this.segments.pop()||this.nullSegment;return this.notifyObservers(),e}peek(){return this.segments[this.segments.length-1]||this.nullSegment}size(){return this.segments.length}isEmpty(){return this.segments.length===0}get hasArguments(){return this.segments.some(e=>e.type==="argument")}get arguments(){return this.segments.filter(e=>e.type==="argument")}path(){return this.segments.map(e=>e.name)}toArray(){return[...this.segments]}}const Ue={config:E,commands:new K,segmentStack:new we},W=o.createContext(Ue),$e=({config:n=E,commandRegistry:e,children:t})=>{const[s,r]=o.useState(),[i]=o.useState(()=>new we),a=o.useMemo(()=>({...E,...n,storage:{...E.storage,...n.storage},cursorType:n.cursorType??E.cursorType,cursorColor:n.cursorColor??E.cursorColor,cursorSpeed:n.cursorSpeed??E.cursorSpeed,closeOnEscape:n.closeOnEscape??E.closeOnEscape,showCitadelKey:n.showCitadelKey??E.showCitadelKey,showOnLoad:n.showOnLoad??E.showOnLoad}),[n]);o.useEffect(()=>{J.getInstance().initializeStorage(a.storage??E.storage),r(J.getInstance().getStorage())},[a.storage]),o.useEffect(()=>{if(e){if(a.includeHelpCommand){if(!e.commandExistsForPath(["help"])){const l=De(e);e.addCommand([{type:"word",name:"help"}],"Show available commands",l)}return}e.removeCommand(["help"])}},[e,a.includeHelpCommand]);const d=o.useMemo(()=>({config:a,commands:e||new K,storage:s,segmentStack:i}),[a,e,s,i]);return c.jsx(W.Provider,{value:d,children:t})},L=()=>{const n=o.useContext(W);if(n===void 0)throw new Error("useCitadelConfig must be used within a CitadelConfigProvider");return n.config},X=()=>{const n=o.useContext(W);if(n===void 0)throw new Error("useCitadelCommands must be used within a CitadelConfigProvider");return n.commands},ve=()=>{const n=o.useContext(W);if(n===void 0)throw new Error("useCitadelStorage must be used within a CitadelConfigProvider");return n.storage},B=()=>{const n=o.useContext(W);if(n===void 0)throw new Error("useSegmentStack must be used within a CitadelConfigProvider");return n.segmentStack},ee=class ee{constructor(e,t){C(this,"id");C(this,"timestamp");C(this,"command");C(this,"result");this.id=`output-${Date.now()}-${ee.idCounter++}`,this.command=e.toArray().map(s=>s.type==="argument"?s.value||"":s.name),this.timestamp=Date.now(),this.result=t??new ue}};C(ee,"idCounter",0);let Q=ee;function je(n){return{commandSegments:_(n),timestamp:Date.now()}}function Se(){const n=ve(),[e,t]=o.useState({storedCommands:[],position:null}),s=o.useCallback(async d=>{if(n)try{const l=je(d);await n.addStoredCommand(l),t(u=>({...u,storedCommands:[...u.storedCommands,{...l,commandSegments:_(l.commandSegments)}],position:null}))}catch(l){console.warn("Failed to save command to history:",l)}},[n]),r=o.useCallback(async()=>n?(await n.getStoredCommands()).map(l=>({...l,commandSegments:_(l.commandSegments)})):[],[n]);o.useEffect(()=>{if(!n)return;(async()=>{try{const u=(await n.getStoredCommands()).map(f=>({...f,commandSegments:_(f.commandSegments)}));return t(f=>({...f,storedCommands:u})),u}catch(l){console.warn("Failed to load command history:",l)}})()},[n]);const i=o.useCallback(async d=>{const l=await r();if(l.length===0)return t(p=>({...p,storedCommands:[],position:null})),{segments:null,position:null};let u=null;if(d==="up"?e.position===null?u=l.length-1:e.position>0?u=e.position-1:u=0:e.position===null||e.position>=l.length-1?u=null:u=e.position+1,t(p=>({...p,storedCommands:l.map(y=>({...y,commandSegments:_(y.commandSegments)})),position:u})),u===null)return{segments:[],position:null};const f=l[u];return f?{segments:_(f.commandSegments),position:u}:{segments:[],position:null}},[e.position,r]),a=o.useCallback(async()=>{try{if(!n)return;await n.clear(),t({storedCommands:[],position:null})}catch(d){console.warn("Failed to clear command history:",d)}},[n]);return{history:e,addStoredCommand:s,getStoredCommands:r,navigateHistory:i,clear:a}}const ae=()=>{const n=L(),e=X(),t=Se(),s=B(),r=ve(),[i,a]=o.useState({currentInput:"",isEnteringArg:!1,output:[],history:{commands:[],position:null,storage:r}});o.useEffect(()=>{},[r]),o.useEffect(()=>{a(l=>({...l,history:{commands:t.history.storedCommands,position:t.history.position,storage:r}}))},[t.history,r]);const d={setCurrentInput:o.useCallback(l=>{k.debug("[CitadelActions] setCurrentInput: ",l),a(u=>({...u,currentInput:l}))},[]),setIsEnteringArg:o.useCallback(l=>{k.debug("[CitadelActions] setIsEnteringArg: ",l),a(u=>({...u,isEnteringArg:l}))},[]),addOutput:o.useCallback(l=>{k.debug("[CitadelActions]addOutput: ",l),a(u=>({...u,output:[...u.output,l]}))},[]),executeCommand:o.useCallback(async()=>{const l=s.path(),u=e.getCommand(l);if(!u){console.error("[CitadelActions][executeCommand] Cannot execute command because no command was found for the given path: ",l);return}const f=new Q(s);a(p=>({...p,output:[...p.output,f]}));try{const p=new Promise((S,N)=>{setTimeout(()=>{N(new Error("Request timed out"))},n.commandTimeoutMs)}),y=s.arguments.map(S=>S.value||""),w=await Promise.race([u.handler(y),p]);if(!(w instanceof F))throw new Error(`The ${l.join(".")} command returned an invalid result type. Commands must return an instance of a CommandResult.
4
4
  For example:
5
5
  return new JsonCommandResult({ text: "Hello World" });
6
- Check the definition of the ${l.join(".")} command and update the return type for its handler.`);b.markSuccess(),o(v=>({...v,output:v.output.map(E=>E.id===y.id?{...E,result:b}:E)}))}catch(p){const f=new Z(p instanceof Error?p.message:"Unknown error");f.markFailure(),o(b=>({...b,output:b.output.map(v=>v.id===y.id?{...v,result:f}:v)}))}},[e,t.commandTimeoutMs,s]),clearHistory:a.useCallback(async()=>{try{await n.clear()}catch(l){console.warn("Failed to clear history:",l)}},[n])};return{state:i,actions:d}},Fe=({onOpen:t,onClose:e,isVisible:n,showCitadelKey:s,closeOnEscape:r})=>{a.useEffect(()=>{const i=o=>{var d,l;!n&&o.key===s&&!["input","textarea"].includes(((l=(d=o.target)==null?void 0:d.tagName)==null?void 0:l.toLowerCase())||"")&&(o.preventDefault(),t()),r&&n&&o.key==="Escape"&&(o.preventDefault(),e())};return document.addEventListener("keydown",i),()=>document.removeEventListener("keydown",i)},[t,e,n,s,r])},Le=200,je=t=>{const{isVisible:e,isClosing:n,onAnimationComplete:s}=t,r=a.useMemo(()=>e?n?"citadel_slideDown":"citadel_slideUp":"",[e,n]);return a.useEffect(()=>{if(!n||!s)return;if(window.matchMedia("(prefers-reduced-motion: reduce)").matches){s();return}const o=setTimeout(()=>{s()},Le);return()=>clearTimeout(o)},[n,s]),{animationClass:r}},Ue=()=>c.jsx("div",{"data-testid":"spinner",className:"citadel-spinner"}),Ce=t=>{const e=t==null?void 0:t.trim();return e||void 0},$e=t=>{const e=Ce(t);return e?{style:{fontSize:e}}:{}},Q=(t,e)=>{const n=Ce(t),r={...$e(e).style};return n&&(r.fontFamily=n),{style:Object.keys(r).length>0?r:void 0}},qe=({command:t,timestamp:e,status:n,fontFamily:s,fontSize:r})=>{const i=a.useMemo(()=>Q(s,r??"0.875rem"),[s,r]);return c.jsxs("div",{className:"citadel-output-line",style:i.style,children:[c.jsxs("span",{className:"citadel-output-command",children:["> ",t.split(" ").map((o,d)=>{const l=o.startsWith("<")&&o.endsWith(">");return c.jsxs("span",{className:l?"citadel-output-command-arg":"citadel-output-command-word",children:[d>0?" ":"",o]},d)})]}),c.jsx("span",{className:"citadel-output-separator",children:"·"}),c.jsx("span",{className:"citadel-output-timestamp",children:e}),n===j.Pending&&c.jsx(Ue,{}),n===j.Success&&c.jsx("div",{"data-testid":"success-indicator",className:"citadel-status-dot citadel-status-dot-success"}),(n===j.Timeout||n===j.Failure)&&c.jsx("div",{"data-testid":"success-indicator",className:"citadel-status-dot citadel-status-dot-failure"})]})},Ke=({output:t,outputRef:e})=>{const n=T(),s=a.useMemo(()=>Q(n.fontFamily,n.outputFontSize??n.fontSize),[n.fontFamily,n.fontSize,n.outputFontSize]),r=a.useCallback(()=>{if(e.current){const i=e.current;requestAnimationFrame(()=>{i.scrollTop=i.scrollHeight})}},[e]);return a.useEffect(()=>{if(r(),e.current){const i=e.current.getElementsByTagName("img"),o=i[i.length-1];if(o&&!o.complete)return o.addEventListener("load",r),()=>o.removeEventListener("load",r)}},[t,r,e]),c.jsx("div",{ref:e,className:"citadel-output","data-testid":"citadel-command-output",children:t.map(i=>c.jsxs("div",{className:"citadel-output-item",children:[c.jsx(qe,{command:i.command.join(" "),timestamp:new Date(i.timestamp).toLocaleTimeString(),status:i.result.status,fontFamily:n.fontFamily,fontSize:n.fontSize}),c.jsx("div",{className:"citadel-output-content",style:s.style,children:i.result.render()})]},i.id))})},we={blink:{character:"▋",speed:530,color:"#fff"},spin:{character:"⠋",speed:120,color:"#fff"},solid:{character:"▋",speed:0,color:"#fff"},bbs:{character:"|",speed:120,color:"#fff"}},ve=["⠋","⠙","⠹","⠸","⠼","⠴","⠦","⠧","⠇","⠏"],Se=["|","/","-","\\"],We=({style:t={type:"blink"},isValid:e=!0,errorMessage:n})=>{const s=a.useMemo(()=>({...we[t.type],...t}),[t]),[r,i]=a.useState(!0),[o,d]=a.useState(0);a.useEffect(()=>{if(s.speed===0)return;const y=setInterval(()=>{s.type==="blink"?i(p=>!p):["spin","bbs"].includes(s.type)&&d(p=>(p+1)%(s.type==="bbs"?Se.length:ve.length))},s.speed);return()=>clearInterval(y)},[s.type,s.speed]);const l=a.useMemo(()=>({color:e?s.color:"#ff4444",transition:"color 0.15s ease-in-out"}),[e,s.color]),u=()=>!e&&n?"✗":["spin","bbs"].includes(s.type)?(s.type==="bbs"?Se:ve)[o]:s.type==="solid"||r?s.character:" ";return c.jsx("div",{className:"citadel-cursor-wrapper",children:c.jsx("span",{className:`command-cursor ${e?"":"animate-shake"}`,style:l,title:n,children:u()})})};function Be(t,e){switch(e.type){case"set":return x.debug(`[inputStateReducer] InputState changing from ${t} to ${e.state}`),e.state;default:return t}}const Ve=()=>{const{state:t}=ne(),e=J(),n=ye(),s=B(),[r,i]=a.useReducer(Be,"idle"),o=m=>{i({type:"set",state:m})},d=a.useCallback(()=>{const h=e.getCompletions(s.path())[0]||s.nullSegment;return x.debug("[getNextExpectedSegment] ",h),h},[e,s]),l=a.useCallback(()=>e.getCompletionNames(s.path()).map(h=>e.getCommand([...s.path(),h])).filter(h=>h!==void 0),[e,s]),u=a.useCallback((m,h)=>{if(!m)return h;const w=s.path().length;return h.filter(D=>{const S=D.segments[w];return!S||S.type!=="word"?!1:S.name.toLowerCase().startsWith(m.toLowerCase())})},[s]),y=a.useCallback(m=>{const h=e.getUniqueCompletion(s.path(),m);return h&&h.type==="word"?h:s.nullSegment},[e,s]),p=a.useCallback(m=>{const h=s.path(),w=e.getCompletions(h);return w.length===0&&m?!1:w.some(S=>S.type==="argument")?!0:e.getMatchingCompletions(h,m).some(S=>S.type==="word")},[e,s]),f=a.useCallback(m=>{x.debug("[tryAutoComplete] input: ",m);const h=y(m);return!h||h.type==="null"?new te:(x.debug("[tryAutoComplete] result: ",h),h)},[y]),b=a.useCallback((m,h)=>{if(t.history.position!==null)return;h.setCurrentInput(m),x.debug("[useCommandParser][handleInputChange] newValue: ",m);const w=d();if(w.type==="argument"||r==="entering_argument"){const A=be(m);if(A.isQuoted)if(A.isComplete){if(!(w instanceof U))return;w.value=m.trim()||"",x.debug("[useCommandParser][handleInputChange][entering_command] pushing: ",w),s.push(w),h.setCurrentInput(""),o("idle");return}else return;else if(A.isComplete){if(!(w instanceof U))return;w.value=m.trim()||"",x.debug("[useCommandParser][handleInputChange][entering_command] pushing: ",w),s.push(w),h.setCurrentInput(""),o("idle");return}else return}if(m.endsWith(" ")){const A=m.trim().toLowerCase(),P=e.getCompletions(s.path()).filter(N=>N.type==="word"&&N.name.toLowerCase()===A);if(P.length===1){s.push(P[0]),h.setCurrentInput(""),o("idle");return}}const S=f(m);if(S.type==="word"){x.debug("[useCommandParser][handleInputChange][entering_command] pushing: ",S),s.push(S),h.setCurrentInput(""),o("idle");return}},[f,t,d,r,s,e]),v=a.useCallback(m=>{m.setCurrentInput(""),m.setIsEnteringArg(!1),s.clear(),o("idle")},[s]),E=a.useCallback((m,h,w)=>{if(!(m.key==="Backspace"||m.key==="Enter"||m.key==="ArrowUp"||m.key==="ArrowDown"||m.key==="ArrowLeft"||m.key==="ArrowRight"||m.key==="Escape"||m.key==="Delete"||m.key==="Home"||m.key==="End"||m.key.length===1))return!0;const{currentInput:S,isEnteringArg:A}=h,P=be(S);switch(m.key){case"Backspace":return S===""&&(m.preventDefault(),s.size()>0&&s.pop(),o("idle")),!0;case"Enter":{if(m.preventDefault(),P.isQuoted&&!P.isComplete)return!0;if(r==="entering_argument"||A&&S.trim()){const F=d();F instanceof U&&(F.value=S,x.debug("[handleKeyDown][Enter]['entering_argument'] pushing: ",F),s.push(F))}const N=s.path(),V=e.getCommand(N);if(!V)return!1;const O=V.segments.filter(F=>F.type==="argument"),$=s.arguments;return O.length>$.length?!1:(x.debug("[handleKeyDown][Enter] calling actions.executeCommand. segmentStack: ",s),w.executeCommand(),n.addStoredCommand(s.toArray()),v(w),!0)}case"ArrowUp":return m.preventDefault(),(async()=>{const N=await n.navigateHistory("up");return N.segments&&(s.clear(),s.pushAll(N.segments),w.setCurrentInput("")),!0})();case"ArrowDown":return m.preventDefault(),(async()=>{const N=await n.navigateHistory("down");return N.segments&&(s.clear(),s.pushAll(N.segments),w.setCurrentInput("")),!0})();default:{if(!A&&m.key.length===1){const N=S+m.key;if(!p(N))return m.preventDefault(),!1}return!0}}},[r,p,d,n,v,e,s]);return{handleInputChange:b,handleKeyDown:E,inputState:r,setInputStateWithLogging:o,findMatchingCommands:u,getAutocompleteSuggestion:y,getAvailableNodes:l,getNextExpectedSegment:d,isValidCommandInput:p}};function be(t){const e=[];let n="",s=!1,r;for(let i=0;i<t.length;i++){const o=t[i];(o==='"'||o==="'")&&(!s||o===r)?s?(e.push(n),n="",s=!1,r=void 0):(n&&(e.push(n),n=""),s=!0,r=o):!s&&o===" "?n&&(e.push(n),n=""):n+=o}return{words:e,currentWord:n,isQuoted:s,quoteChar:r,isComplete:!s&&!n}}const Ye=()=>{const t=B(),[e,n]=a.useState(0);return a.useEffect(()=>{const s={update:()=>{n(r=>r+1)}};return t.subscribe(s),()=>{t.unsubscribe(s)}},[t]),e},Je=({state:t,actions:e})=>{const n=a.useRef(null),s=J(),r=B(),{handleKeyDown:i,handleInputChange:o,inputState:d,setInputStateWithLogging:l,getNextExpectedSegment:u}=Ve(),[y,p]=a.useState(!1),f=T(),b=Ye(),v=a.useRef(null),[E,m]=a.useState(0),h=a.useMemo(()=>Q(f.fontFamily,f.fontSize),[f.fontFamily,f.fontSize]),w=a.useCallback(async I=>{const M=i(I,t,e);await Promise.resolve(M)===!1&&(p(!0),setTimeout(()=>p(!1),500))},[e,i,t]),D=a.useCallback(I=>{o(I.target.value,e)},[e,o]),S=a.useCallback(I=>{I.preventDefault();const M=I.clipboardData.getData("text");o(M,e)},[e,o]);a.useEffect(()=>{n.current&&n.current.focus(),d!=="entering_command"&&l("entering_command")},[d,l]),a.useEffect(()=>{if(d!=="idle")return;const I=u();let M="idle";switch(I.type){case"word":M="entering_command",e.setIsEnteringArg(!1);break;case"argument":M="entering_argument",e.setIsEnteringArg(!0);break}l(M)},[b,d,u,l,e]);const A=a.useMemo(()=>{const I=[],M=r.toArray().map((L,re)=>{I.push(L.name);const Ae=s.hasNextSegment(I);if(L.type==="argument"){const ae=L;return c.jsxs(a.Fragment,{children:[c.jsx("span",{className:"citadel-input-segment-arg",children:ae.value}),re<r.size()&&Ae&&c.jsx("span",{className:"citadel-input-segment-space",children:" "})]},"arg-"+ae.name+ae.value)}return c.jsxs(a.Fragment,{children:[c.jsx("span",{className:"citadel-input-segment-word",children:L.name}),re<r.size()&&Ae&&c.jsx("span",{className:"citadel-input-segment-space citadel-input-segment-space-command",children:" "})]},"word-"+L.name)});return[c.jsx("div",{className:"citadel-input-segments","data-testid":"user-input-area",children:M},b)]},[b,s,r]),[P,N]=a.useState("");a.useEffect(()=>{const I=u();I.type==="argument"?N(I.name):N("")},[b,u]);const O=!t.isEnteringArg?"is-command-mode":"is-argument-mode",$=a.useMemo(()=>({left:`${E}px`,transition:"left 0.05s ease-out"}),[E]),F=a.useMemo(()=>({type:f.cursorType??k.cursorType,color:f.cursorColor||k.cursorColor,speed:f.cursorSpeed||k.cursorSpeed}),[f.cursorColor,f.cursorSpeed,f.cursorType]);return a.useLayoutEffect(()=>{const I=v.current,M=n.current;if(!I||!M){m(0);return}const L=I.getBoundingClientRect().width;m(Math.max(0,L-M.scrollLeft))},[t.currentInput,O,h.style]),c.jsx("div",{className:"citadel-input-shell",children:c.jsxs("div",{className:"citadel-input-line",style:h.style,children:[c.jsx("div",{className:"citadel-input-prompt",children:">"}),c.jsxs("div",{className:"citadel-input-row",children:[A,c.jsxs("div",{className:"citadel-input-control",children:[c.jsx("span",{ref:v,className:`citadel-input-measure ${O}`.trim(),"aria-hidden":"true",children:t.currentInput}),c.jsx("input",{ref:n,type:"text",role:"textbox",value:t.currentInput,onChange:D,onKeyDown:w,onPaste:S,"data-testid":"citadel-command-input",className:`citadel-input-field ${O} ${y?"invalid-input-animation":""}`.trim(),spellCheck:!1,autoComplete:"off",placeholder:P}),c.jsx("div",{className:"citadel-input-cursor",style:$,children:c.jsx(We,{style:F})})]})]})]})})},Ge=({currentInput:t=""})=>{const e=J(),n=T(),s=B(),r=a.useMemo(()=>Q(n.fontFamily,n.fontSize),[n.fontFamily,n.fontSize]),i=t.trim().toLowerCase(),o=e.getMatchingCompletions(s.path(),i);x.debug("[AvailableCommands] nextCommandSegments: ",o);const d=a.useMemo(()=>{const p=[...o],f=m=>m.name.toLowerCase()==="help",b=p.filter(f);return[...p.filter(m=>!f(m)).sort((m,h)=>m.name.localeCompare(h.name,void 0,{sensitivity:"base"})),...b]},[o]),l=a.useMemo(()=>{const p=new Map;for(const f of d){const b=d.reduce((v,E)=>{if(E===f)return v;let m=0;for(;m<f.name.length&&m<E.name.length&&f.name[m].toLowerCase()===E.name[m].toLowerCase();)m++;return Math.max(v,m+1)},1);p.set(f.name,b)}return p},[d]),u=o.some(p=>p.type==="argument"),y=o[0];return c.jsx("div",{className:"citadel-available-commands","data-testid":"available-commands",children:c.jsx("div",{className:"citadel-available-commands-content",style:r.style,children:u?o.length>0?c.jsxs(c.Fragment,{children:[c.jsx("span",{className:"citadel-available-next-arg",children:y.name}),y.description&&c.jsxs("span",{className:"citadel-available-next-desc",children:["- ",y.description]})]}):null:c.jsx("div",{className:"citadel-available-chip-list",children:d==null?void 0:d.map(p=>{const f=l.get(p.name)??1;return c.jsx("div",{"data-testid":"available-command-chip",className:"citadel-available-chip",children:c.jsxs("span",{className:"citadel-available-chip-text",children:[c.jsx("strong",{className:"citadel-available-chip-prefix",children:p.name.slice(0,f)}),p.name.slice(f)]})},p.name)})})})})},xe=({state:t,actions:e,outputRef:n})=>{const r=T().displayMode==="inline",i=a.useMemo(()=>r?{overflow:"hidden"}:void 0,[r]);return c.jsxs("div",{className:"innerContainer citadel-tty",children:[c.jsx("div",{className:"citadel-tty-output-pane","data-testid":"citadel-output-pane",style:i,children:c.jsx(Ke,{output:t.output,outputRef:n})}),c.jsxs("div",{className:"citadel-tty-input-region",children:[c.jsx(Je,{state:t,actions:e}),c.jsx(Ge,{currentInput:t.isEnteringArg?"":t.currentInput})]})]})},Qe=()=>{const t=T(),[e,n]=a.useState(()=>t.showOnLoad??!1),[s,r]=a.useState(!1),[i,o]=a.useState(()=>t.initialHeight||null),d=a.useRef(null),l=a.useRef(null),u=a.useRef(!1),y=a.useRef(0),p=a.useRef(0),{state:f,actions:b}=ne(),v=a.useCallback(()=>{r(!1),n(!0)},[]),E=a.useCallback(()=>{r(!0)},[]);Fe({onOpen:v,onClose:E,isVisible:e&&!s,showCitadelKey:t.showCitadelKey||".",closeOnEscape:t.closeOnEscape??!0});const m=a.useCallback(P=>{var $;if(!u.current)return;const N=P.clientY-y.current,V=($=t.maxHeight)!=null&&$.endsWith("vh")?window.innerHeight*parseInt(t.maxHeight,10)/100:parseInt(t.maxHeight||"80vh",10),O=Math.min(Math.max(p.current-N,parseInt(t.minHeight||"200",10)),V);l.current&&(l.current.style.height=`${O}px`,l.current.style.bottom="0",o(`${O}px`))},[t.maxHeight,t.minHeight]),h=a.useCallback(()=>{u.current=!1,document.documentElement.style.userSelect="",document.documentElement.style.webkitUserSelect="",document.documentElement.style.mozUserSelect="",document.documentElement.style.msUserSelect="",document.removeEventListener("mousemove",m),document.removeEventListener("mouseup",h)},[m]),w=a.useCallback(P=>{l.current&&(u.current=!0,y.current=P.clientY,p.current=l.current.offsetHeight,document.documentElement.style.userSelect="none",document.documentElement.style.webkitUserSelect="none",document.documentElement.style.mozUserSelect="none",document.documentElement.style.msUserSelect="none",document.addEventListener("mousemove",m),document.addEventListener("mouseup",h))},[m,h]);a.useEffect(()=>()=>{document.removeEventListener("mousemove",m),document.removeEventListener("mouseup",h)},[m,h]);const D=a.useCallback(()=>{s&&(n(!1),r(!1))},[s]),{animationClass:S}=je({isVisible:e,isClosing:s,onAnimationComplete:D}),A=a.useMemo(()=>({...i?{height:i}:{},maxHeight:t.maxHeight}),[t.maxHeight,i]);return e?c.jsxs("div",{ref:l,className:`panelContainer ${S}`.trim(),style:A,children:[c.jsx("div",{className:"resizeHandle",onMouseDown:w}),c.jsx(xe,{state:f,actions:b,outputRef:d})]}):null},se=t=>{if(!t)return;const e=t.trim();if(e)return/^\d+(\.\d+)?$/.test(e)?`${e}px`:e},Xe=()=>{const{state:t,actions:e}=ne(),n=T(),s=a.useRef(null),r=a.useMemo(()=>({height:se(n.initialHeight),maxHeight:se(n.maxHeight),minHeight:se(n.minHeight)}),[n.initialHeight,n.maxHeight,n.minHeight]);return c.jsx("div",{className:"inlineContainer","data-testid":"citadel-inline-container",style:r,children:c.jsx(xe,{state:t,actions:e,outputRef:s})})},ke=`:host {
6
+ Check the definition of the ${l.join(".")} command and update the return type for its handler.`);w.markSuccess(),a(S=>({...S,output:S.output.map(N=>N.id===f.id?{...N,result:w}:N)}))}catch(p){const y=new ne(p instanceof Error?p.message:"Unknown error");y.markFailure(),a(w=>({...w,output:w.output.map(S=>S.id===f.id?{...S,result:y}:S)}))}},[e,n.commandTimeoutMs,s]),clearHistory:o.useCallback(async()=>{try{await t.clear()}catch(l){console.warn("Failed to clear history:",l)}},[t])};return{state:i,actions:d}},qe=({onOpen:n,onClose:e,isVisible:t,showCitadelKey:s,closeOnEscape:r})=>{o.useEffect(()=>{const i=a=>{var d,l;!t&&a.key===s&&!["input","textarea"].includes(((l=(d=a.target)==null?void 0:d.tagName)==null?void 0:l.toLowerCase())||"")&&(a.preventDefault(),n()),r&&t&&a.key==="Escape"&&(a.preventDefault(),e())};return document.addEventListener("keydown",i),()=>document.removeEventListener("keydown",i)},[n,e,t,s,r])},Ke=200,We=n=>{const{isVisible:e,isClosing:t,onAnimationComplete:s}=n,r=o.useMemo(()=>e?t?"citadel_slideDown":"citadel_slideUp":"",[e,t]);return o.useEffect(()=>{if(!t||!s)return;if(window.matchMedia("(prefers-reduced-motion: reduce)").matches){s();return}const a=setTimeout(()=>{s()},Ke);return()=>clearTimeout(a)},[t,s]),{animationClass:r}},Be=()=>c.jsx("div",{"data-testid":"spinner",className:"citadel-spinner"}),be=n=>{const e=n==null?void 0:n.trim();return e||void 0},Ve=n=>{const e=be(n);return e?{style:{fontSize:e}}:{}},Z=(n,e)=>{const t=be(n),r={...Ve(e).style};return t&&(r.fontFamily=t),{style:Object.keys(r).length>0?r:void 0}},Ge=({command:n,timestamp:e,status:t,fontFamily:s,fontSize:r})=>{const i=o.useMemo(()=>Z(s,r??"0.875rem"),[s,r]);return c.jsxs("div",{className:"citadel-output-line",style:i.style,children:[c.jsxs("span",{className:"citadel-output-command",children:["> ",n.split(" ").map((a,d)=>{const l=a.startsWith("<")&&a.endsWith(">");return c.jsxs("span",{className:l?"citadel-output-command-arg":"citadel-output-command-word",children:[d>0?" ":"",a]},d)})]}),c.jsx("span",{className:"citadel-output-separator",children:"·"}),c.jsx("span",{className:"citadel-output-timestamp",children:e}),t===$.Pending&&c.jsx(Be,{}),t===$.Success&&c.jsx("div",{"data-testid":"success-indicator",className:"citadel-status-dot citadel-status-dot-success"}),(t===$.Timeout||t===$.Failure)&&c.jsx("div",{"data-testid":"success-indicator",className:"citadel-status-dot citadel-status-dot-failure"})]})},Ye=({output:n,outputRef:e})=>{const t=L(),s=o.useMemo(()=>Z(t.fontFamily,t.outputFontSize??t.fontSize),[t.fontFamily,t.fontSize,t.outputFontSize]),r=o.useCallback(()=>{if(e.current){const i=e.current;requestAnimationFrame(()=>{i.scrollTop=i.scrollHeight})}},[e]);return o.useEffect(()=>{if(r(),e.current){const i=e.current.getElementsByTagName("img"),a=i[i.length-1];if(a&&!a.complete)return a.addEventListener("load",r),()=>a.removeEventListener("load",r)}},[n,r,e]),c.jsx("div",{ref:e,className:"citadel-output","data-testid":"citadel-command-output",children:n.map(i=>c.jsxs("div",{className:"citadel-output-item",children:[c.jsx(Ge,{command:i.command.join(" "),timestamp:new Date(i.timestamp).toLocaleTimeString(),status:i.result.status,fontFamily:t.fontFamily,fontSize:t.fontSize}),c.jsx("div",{className:"citadel-output-content",style:s.style,children:i.result.render()})]},i.id))})},xe={blink:{character:"▋",speed:530,color:"#fff"},spin:{character:"⠋",speed:120,color:"#fff"},solid:{character:"▋",speed:0,color:"#fff"},bbs:{character:"|",speed:120,color:"#fff"}},ke=["⠋","⠙","⠹","⠸","⠼","⠴","⠦","⠧","⠇","⠏"],Ee=["|","/","-","\\"],Je=({style:n={type:"blink"},isValid:e=!0,errorMessage:t})=>{const s=o.useMemo(()=>({...xe[n.type],...n}),[n]),[r,i]=o.useState(!0),[a,d]=o.useState(0);o.useEffect(()=>{if(s.speed===0)return;const f=setInterval(()=>{s.type==="blink"?i(p=>!p):["spin","bbs"].includes(s.type)&&d(p=>(p+1)%(s.type==="bbs"?Ee.length:ke.length))},s.speed);return()=>clearInterval(f)},[s.type,s.speed]);const l=o.useMemo(()=>({color:e?s.color:"#ff4444",transition:"color 0.15s ease-in-out"}),[e,s.color]),u=()=>!e&&t?"✗":["spin","bbs"].includes(s.type)?(s.type==="bbs"?Ee:ke)[a]:s.type==="solid"||r?s.character:" ";return c.jsx("div",{className:"citadel-cursor-wrapper",children:c.jsx("span",{className:`command-cursor ${e?"":"animate-shake"}`,style:l,title:t,children:u()})})};function Xe(n,e){switch(e.type){case"set":return k.debug(`[inputStateReducer] InputState changing from ${n} to ${e.state}`),e.state;default:return n}}const Qe=()=>{const{state:n}=ae(),e=X(),t=Se(),s=B(),[r,i]=o.useReducer(Xe,"idle"),a=m=>{i({type:"set",state:m})},d=o.useCallback(()=>{const h=e.getCompletions(s.path())[0]||s.nullSegment;return k.debug("[getNextExpectedSegment] ",h),h},[e,s]),l=o.useCallback(()=>e.getCompletionNames(s.path()).map(h=>e.getCommand([...s.path(),h])).filter(h=>h!==void 0),[e,s]),u=o.useCallback((m,h)=>{if(!m)return h;const v=s.path().length;return h.filter(T=>{const b=T.segments[v];return!b||b.type!=="word"?!1:b.name.toLowerCase().startsWith(m.toLowerCase())})},[s]),f=o.useCallback(m=>{const h=e.getUniqueCompletion(s.path(),m);return h&&h.type==="word"?h:s.nullSegment},[e,s]),p=o.useCallback(m=>{const h=s.path(),v=e.getCompletions(h);return v.length===0&&m?!1:v.some(b=>b.type==="argument")?!0:e.getMatchingCompletions(h,m).some(b=>b.type==="word")},[e,s]),y=o.useCallback(m=>{k.debug("[tryAutoComplete] input: ",m);const h=f(m);return!h||h.type==="null"?new oe:(k.debug("[tryAutoComplete] result: ",h),h)},[f]),w=o.useCallback((m,h)=>{if(n.history.position!==null)return;h.setCurrentInput(m),k.debug("[useCommandParser][handleInputChange] newValue: ",m);const v=d();if(v.type==="argument"||r==="entering_argument"){const H=Ne(m);if(H.isQuoted)if(H.isComplete){if(!(v instanceof j))return;v.value=m.trim()||"",k.debug("[useCommandParser][handleInputChange][entering_command] pushing: ",v),s.push(v),h.setCurrentInput(""),a("idle");return}else return;else if(H.isComplete){if(!(v instanceof j))return;v.value=m.trim()||"",k.debug("[useCommandParser][handleInputChange][entering_command] pushing: ",v),s.push(v),h.setCurrentInput(""),a("idle");return}else return}if(m.endsWith(" ")){const H=m.trim().toLowerCase(),z=e.getCompletions(s.path()).filter(I=>I.type==="word"&&I.name.toLowerCase()===H);if(z.length===1){s.push(z[0]),h.setCurrentInput(""),a("idle");return}}const b=y(m);if(b.type==="word"){k.debug("[useCommandParser][handleInputChange][entering_command] pushing: ",b),s.push(b),h.setCurrentInput(""),a("idle");return}},[y,n,d,r,s,e]),S=o.useCallback(m=>{m.setCurrentInput(""),m.setIsEnteringArg(!1),s.clear(),a("idle")},[s]),N=o.useCallback((m,h,v)=>{if(!(m.key==="Backspace"||m.key==="Enter"||m.key==="ArrowUp"||m.key==="ArrowDown"||m.key==="ArrowLeft"||m.key==="ArrowRight"||m.key==="Escape"||m.key==="Delete"||m.key==="Home"||m.key==="End"||m.key.length===1))return!0;const{currentInput:b,isEnteringArg:H}=h,z=Ne(b);switch(m.key){case"Backspace":return b===""&&(m.preventDefault(),s.size()>0&&s.pop(),a("idle")),!0;case"Enter":{if(m.preventDefault(),z.isQuoted&&!z.isComplete)return!0;if(r==="entering_argument"||H&&b.trim()){const D=d();D instanceof j&&(D.value=b,k.debug("[handleKeyDown][Enter]['entering_argument'] pushing: ",D),s.push(D))}const I=s.path(),O=e.getCommand(I);if(!O)return!1;const M=O.segments.filter(D=>D.type==="argument"),V=s.arguments;return M.length>V.length?!1:(k.debug("[handleKeyDown][Enter] calling actions.executeCommand. segmentStack: ",s),v.executeCommand(),t.addStoredCommand(s.toArray()),S(v),!0)}case"ArrowUp":return m.preventDefault(),(async()=>{const I=await t.navigateHistory("up");return I.segments&&(s.clear(),s.pushAll(I.segments),v.setCurrentInput("")),!0})();case"ArrowDown":return m.preventDefault(),(async()=>{const I=await t.navigateHistory("down");return I.segments&&(s.clear(),s.pushAll(I.segments),v.setCurrentInput("")),!0})();default:{if(!H&&m.key.length===1){const I=b+m.key;if(!p(I))return m.preventDefault(),!1}return!0}}},[r,p,d,t,S,e,s]);return{handleInputChange:w,handleKeyDown:N,inputState:r,setInputStateWithLogging:a,findMatchingCommands:u,getAutocompleteSuggestion:f,getAvailableNodes:l,getNextExpectedSegment:d,isValidCommandInput:p}};function Ne(n){const e=[];let t="",s=!1,r;for(let i=0;i<n.length;i++){const a=n[i];(a==='"'||a==="'")&&(!s||a===r)?s?(e.push(t),t="",s=!1,r=void 0):(t&&(e.push(t),t=""),s=!0,r=a):!s&&a===" "?t&&(e.push(t),t=""):t+=a}return{words:e,currentWord:t,isQuoted:s,quoteChar:r,isComplete:!s&&!t}}const Ze=()=>{const n=B(),[e,t]=o.useState(0);return o.useEffect(()=>{const s={update:()=>{t(r=>r+1)}};return n.subscribe(s),()=>{n.unsubscribe(s)}},[n]),e},Re=({state:n,actions:e})=>{const t=o.useRef(null),s=X(),r=B(),{handleKeyDown:i,handleInputChange:a,inputState:d,setInputStateWithLogging:l,getNextExpectedSegment:u}=Qe(),[f,p]=o.useState(!1),y=L(),w=Ze(),S=o.useRef(null),[N,m]=o.useState(0),h=o.useMemo(()=>Z(y.fontFamily,y.fontSize),[y.fontFamily,y.fontSize]),v=o.useCallback(async x=>{const A=i(x,n,e);await Promise.resolve(A)===!1&&(p(!0),setTimeout(()=>p(!1),500))},[e,i,n]),T=o.useCallback(x=>{a(x.target.value,e)},[e,a]),b=o.useCallback(x=>{x.preventDefault();const A=x.clipboardData.getData("text");a(A,e)},[e,a]);o.useEffect(()=>{t.current&&t.current.focus(),d!=="entering_command"&&l("entering_command")},[d,l]),o.useEffect(()=>{if(d!=="idle")return;const x=u();let A="idle";switch(x.type){case"word":A="entering_command",e.setIsEnteringArg(!1);break;case"argument":A="entering_argument",e.setIsEnteringArg(!0);break}l(A)},[w,d,u,l,e]);const H=o.useMemo(()=>{const x=[],A=r.toArray().map((P,G)=>{x.push(P.name);const te=s.hasNextSegment(x);if(P.type==="argument"){const Y=P;return c.jsxs(o.Fragment,{children:[c.jsx("span",{className:"citadel-input-segment-arg",children:Y.value}),G<r.size()&&te&&c.jsx("span",{className:"citadel-input-segment-space",children:" "})]},"arg-"+Y.name+Y.value)}return c.jsxs(o.Fragment,{children:[c.jsx("span",{className:"citadel-input-segment-word",children:P.name}),G<r.size()&&te&&c.jsx("span",{className:"citadel-input-segment-space citadel-input-segment-space-command",children:" "})]},"word-"+P.name)});return[c.jsx("div",{className:"citadel-input-segments","data-testid":"user-input-area",children:A},w)]},[w,s,r]),[z,I]=o.useState("");o.useEffect(()=>{const x=u();x.type==="argument"?I(x.name):I("")},[w,u]);const M=!n.isEnteringArg?"is-command-mode":"is-argument-mode",V=o.useMemo(()=>({left:`${N}px`,transition:"left 0.05s ease-out"}),[N]),D=o.useMemo(()=>({type:y.cursorType??E.cursorType,color:y.cursorColor||E.cursorColor,speed:y.cursorSpeed||E.cursorSpeed}),[y.cursorColor,y.cursorSpeed,y.cursorType]);return o.useLayoutEffect(()=>{const x=S.current,A=t.current;if(!x||!A){m(0);return}const P=x.getBoundingClientRect().width;m(Math.max(0,P-A.scrollLeft))},[n.currentInput,M,h.style]),c.jsx("div",{className:"citadel-input-shell",children:c.jsxs("div",{className:"citadel-input-line",style:h.style,children:[c.jsx("div",{className:"citadel-input-prompt",children:">"}),c.jsxs("div",{className:"citadel-input-row",children:[H,c.jsxs("div",{className:"citadel-input-control",children:[c.jsx("span",{ref:S,className:`citadel-input-measure ${M}`.trim(),"aria-hidden":"true",children:n.currentInput}),c.jsx("input",{ref:t,type:"text",role:"textbox",value:n.currentInput,onChange:T,onKeyDown:v,onPaste:b,"data-testid":"citadel-command-input",className:`citadel-input-field ${M} ${f?"invalid-input-animation":""}`.trim(),spellCheck:!1,autoComplete:"off",placeholder:z}),c.jsx("div",{className:"citadel-input-cursor",style:V,children:c.jsx(Je,{style:D})})]})]})]})})},et=({currentInput:n=""})=>{const e=X(),t=L(),s=B(),r=o.useMemo(()=>Z(t.fontFamily,t.fontSize),[t.fontFamily,t.fontSize]),i=n.trim().toLowerCase(),a=e.getMatchingCompletions(s.path(),i);k.debug("[AvailableCommands] nextCommandSegments: ",a);const d=o.useMemo(()=>{const p=[...a],y=m=>m.name.toLowerCase()==="help",w=p.filter(y);return[...p.filter(m=>!y(m)).sort((m,h)=>m.name.localeCompare(h.name,void 0,{sensitivity:"base"})),...w]},[a]),l=o.useMemo(()=>{const p=new Map;for(const y of d){const w=d.reduce((S,N)=>{if(N===y)return S;let m=0;for(;m<y.name.length&&m<N.name.length&&y.name[m].toLowerCase()===N.name[m].toLowerCase();)m++;return Math.max(S,m+1)},1);p.set(y.name,w)}return p},[d]),u=a.some(p=>p.type==="argument"),f=a[0];return c.jsx("div",{className:"citadel-available-commands","data-testid":"available-commands",children:c.jsx("div",{className:"citadel-available-commands-content",style:r.style,children:u?a.length>0?c.jsxs(c.Fragment,{children:[c.jsx("span",{className:"citadel-available-next-arg",children:f.name}),f.description&&c.jsxs("span",{className:"citadel-available-next-desc",children:["- ",f.description]})]}):null:c.jsx("div",{className:"citadel-available-chip-list",children:d==null?void 0:d.map(p=>{const y=l.get(p.name)??1;return c.jsx("div",{"data-testid":"available-command-chip",className:"citadel-available-chip",children:c.jsxs("span",{className:"citadel-available-chip-text",children:[c.jsx("strong",{className:"citadel-available-chip-prefix",children:p.name.slice(0,y)}),p.name.slice(y)]})},p.name)})})})})},Ie=({state:n,actions:e,outputRef:t})=>{const s=L(),r=s.displayMode==="inline",i=s.showOutputPane??!0,a=o.useMemo(()=>i&&r?{overflow:"hidden"}:void 0,[r,i]);return c.jsxs("div",{className:"innerContainer citadel-tty",children:[i?c.jsx("div",{className:"citadel-tty-output-pane","data-testid":"citadel-output-pane",style:a,children:c.jsx(Ye,{output:n.output,outputRef:t})}):null,c.jsxs("div",{className:"citadel-tty-input-region",children:[c.jsx(Re,{state:n,actions:e}),c.jsx(et,{currentInput:n.isEnteringArg?"":n.currentInput})]})]})},R="128px",tt="200px",nt="80vh",ie=n=>{if(!n)return;const e=n.trim();if(e)return/^\d+(\.\d+)?$/.test(e)?`${e}px`:e},Ae=(n,e)=>{if(!n)return e;const t=n.trim();if(!t)return e;if(t.endsWith("vh")){const r=Number.parseFloat(t);return Number.isFinite(r)?window.innerHeight*r/100:e}const s=Number.parseFloat(t);return Number.isFinite(s)?s:e},st=()=>{const n=L(),e=n.showOutputPane??!0,t=ie(n.minHeight)??tt,s=ie(n.maxHeight)??nt,r=e?t:R,i=Number.parseFloat(R),[a,d]=o.useState(()=>{const P=ie(n.initialHeight);return e?P??null:R}),[l,u]=o.useState(()=>n.showOnLoad??!1),[f,p]=o.useState(!1),y=o.useRef(null),w=o.useRef(null),S=o.useRef(!1),N=o.useRef(0),m=o.useRef(0),h=o.useRef(null),v=o.useRef(a),T=o.useRef(e),{state:b,actions:H}=ae(),z=o.useCallback(()=>{p(!1),u(!0)},[]),I=o.useCallback(()=>{p(!0)},[]);qe({onOpen:z,onClose:I,isVisible:l&&!f,showCitadelKey:n.showCitadelKey||".",closeOnEscape:n.closeOnEscape??!0});const O=o.useCallback(P=>{if(!S.current)return;const G=P.clientY-N.current,te=Ae(s,window.innerHeight*80/100),Y=Ae(r,i),Te=Math.min(Math.max(m.current-G,Y),te);w.current&&(w.current.style.height=`${Te}px`,w.current.style.bottom="0",d(`${Te}px`))},[i,r,s]),M=o.useCallback(()=>{S.current=!1,document.documentElement.style.userSelect="",document.documentElement.style.webkitUserSelect="",document.documentElement.style.mozUserSelect="",document.documentElement.style.msUserSelect="",document.removeEventListener("mousemove",O),document.removeEventListener("mouseup",M)},[O]),V=o.useCallback(P=>{w.current&&(S.current=!0,N.current=P.clientY,m.current=w.current.offsetHeight,document.documentElement.style.userSelect="none",document.documentElement.style.webkitUserSelect="none",document.documentElement.style.mozUserSelect="none",document.documentElement.style.msUserSelect="none",document.addEventListener("mousemove",O),document.addEventListener("mouseup",M))},[O,M]);o.useEffect(()=>()=>{document.removeEventListener("mousemove",O),document.removeEventListener("mouseup",M)},[O,M]),o.useEffect(()=>{v.current=a},[a]),o.useEffect(()=>{if(!e){T.current&&(h.current=v.current??(w.current?`${w.current.offsetHeight}px`:null)),T.current=!1,d(R);return}T.current=!0,h.current&&(d(h.current),h.current=null)},[e]);const D=o.useCallback(()=>{f&&(u(!1),p(!1))},[f]),{animationClass:x}=We({isVisible:l,isClosing:f,onAnimationComplete:D}),A=o.useMemo(()=>({...a?{height:a}:{},minHeight:r,maxHeight:s}),[r,a,s]);return l?c.jsxs("div",{ref:w,className:`panelContainer ${x}`.trim(),style:A,children:[c.jsx("div",{className:"resizeHandle",onMouseDown:V}),c.jsx(Ie,{state:b,actions:H,outputRef:y})]}):null},le="128px",ce=n=>{if(!n)return;const e=n.trim();if(e)return/^\d+(\.\d+)?$/.test(e)?`${e}px`:e},rt=()=>{const{state:n,actions:e}=ae(),t=L(),s=t.showOutputPane??!0,r=o.useRef(null),i=o.useMemo(()=>({height:s?ce(t.initialHeight):le,maxHeight:s?ce(t.maxHeight):le,minHeight:s?ce(t.minHeight):le}),[t.initialHeight,t.maxHeight,t.minHeight,s]);return c.jsx("div",{className:"inlineContainer","data-testid":"citadel-inline-container",style:i,children:c.jsx(Ie,{state:n,actions:e,outputRef:r})})},Pe=`:host {
7
7
  --citadel-bg: oklch(20.8% 0.042 265.8);
8
8
  --citadel-surface: oklch(27.9% 0.041 260);
9
9
  --citadel-border: oklch(37.2% 0.044 257.3);
@@ -475,5 +475,5 @@ Check the definition of the ${l.join(".")} command and update the return type fo
475
475
  object-fit: contain;
476
476
  border-radius: 0.5rem;
477
477
  }
478
- `,Ze=({config:t=k,commandRegistry:e,containerId:n=null})=>{const s=a.useRef(new K),r=e??s.current,i=a.useRef(null),o=a.useMemo(()=>({width:"100%",height:"100%"}),[]),d=t.displayMode??k.displayMode??"panel";return a.useEffect(()=>{x.configure({level:t.logLevel||k.logLevel||R.ERROR,prefix:"[Citadel]"});const l=new Ee(r,t),u=d==="inline"&&!n,y=u?i.current:n?document.getElementById(n):document.body;if(y)y.appendChild(l);else{if(u){console.warn("[Citadel] No host available for inline mode; skipping mount.");return}console.warn(`Container with id "${n}" not found, falling back to body`),document.body.appendChild(l)}return()=>{var p;(p=l.parentElement)==null||p.removeChild(l)}},[r,n,t,d]),d==="inline"&&!n?c.jsx("div",{ref:i,style:o}):null};class Ee extends HTMLElement{constructor(n,s){var i;super();C(this,"shadow");C(this,"root",null);C(this,"commandRegistry");C(this,"config");this.shadow=this.attachShadow({mode:"open"}),this.commandRegistry=n,this.config=s;const r=((i=this.config)==null?void 0:i.displayMode)??"panel";this.setAttribute("data-display-mode",r)}connectedCallback(){try{const s=[ke].map(r=>{const i=new CSSStyleSheet;return i.replaceSync(r),i});this.shadow.adoptedStyleSheets=[...s]}catch{const s=[ke].join(`
479
- `),r=document.createElement("style");r.textContent=s,this.shadow.appendChild(r)}const n=document.createElement("div");n.id="citadel-root",n.style.width="100%",n.style.height="100%",this.shadow.appendChild(n),this.root=Me.createRoot(n),this.root.render(c.jsx(De,{config:this.config||k,commandRegistry:this.commandRegistry,children:c.jsx(Re,{})}))}disconnectedCallback(){const n=this.root;if(this.root=null,!n){this.shadow.replaceChildren();return}queueMicrotask(()=>{n.unmount(),this.shadow.replaceChildren()})}}typeof window<"u"&&window.customElements&&!window.customElements.get("citadel-element")&&window.customElements.define("citadel-element",Ee);const Re=()=>(T().displayMode??"panel")==="inline"?c.jsx(Xe,{}):c.jsx(Qe,{});class et{constructor(){C(this,"_description")}describe(e){return this._description=e,this}get description(){return this._description}}class tt{constructor(e){C(this,"state");this.state={path:e,description:"",segments:nt(e)}}describe(e){return this.state.description=e,this}details(e){return this.state.details=e,this}arg(e,n){const s=new et;return n==null||n(s),this.state.segments.push({type:"argument",name:e,description:s.description}),this}handle(e){return{path:this.state.path,description:this.state.description,details:this.state.details,segments:[...this.state.segments],handler:e}}}function nt(t){const e=t.trim();if(!e)throw new Error("Command path cannot be empty");const n=e.split(".");if(n.some(s=>s.trim()===""))throw new Error(`Invalid command path "${t}". Empty segments are not allowed.`);if(n.some(s=>s.includes(" ")))throw new Error(`Invalid command path "${t}". Use dot-delimited words (e.g. "user.show").`);return n.map(s=>({type:"word",name:s}))}function st(t){return t.flatMap(e=>e.type==="argument"?[e.name]:[])}function rt(t){const e=st(t.segments);return async n=>{const s=e.reduce((r,i,o)=>(r[i]=n[o],r),{});return Promise.resolve(t.handler({rawArgs:n,namedArgs:s,commandPath:t.path}))}}function at(t){return new tt(t)}function Ne(t,e){t.addCommand(e.segments,e.description,rt(e))}function Ie(t,e){return e.forEach(n=>Ne(t,n)),t}function ot(t){const e=new K;return Ie(e,t)}function it(t){return new q(t)}function lt(t,e="true",n="false"){return new ie(t,e,n)}function ct(t){return new oe(t)}function dt(t,e=""){return new ce(t,e)}function mt(t){return new Z(t)}g.BooleanCommandResult=ie,g.Citadel=Ze,g.CommandRegistry=K,g.CommandResult=_,g.CommandStatus=j,g.DEFAULT_CURSOR_CONFIGS=we,g.ErrorCommandResult=Z,g.ImageCommandResult=ce,g.JsonCommandResult=oe,g.OutputItem=G,g.PendingCommandResult=le,g.TextCommandResult=q,g.bool=lt,g.command=at,g.createCommandRegistry=ot,g.error=mt,g.image=dt,g.json=ct,g.registerCommand=Ne,g.registerCommands=Ie,g.text=it,Object.defineProperty(g,Symbol.toStringTag,{value:"Module"})});
478
+ `,ot=({config:n=E,commandRegistry:e,containerId:t=null})=>{const s=o.useRef(new K),r=e??s.current,i=o.useRef(null),a=o.useMemo(()=>({width:"100%",height:"100%"}),[]),d=n.displayMode??E.displayMode??"panel";return o.useEffect(()=>{k.configure({level:n.logLevel||E.logLevel||se.ERROR,prefix:"[Citadel]"});const l=new He(r,n),u=d==="inline"&&!t,f=u?i.current:t?document.getElementById(t):document.body;if(f)f.appendChild(l);else{if(u){console.warn("[Citadel] No host available for inline mode; skipping mount.");return}console.warn(`Container with id "${t}" not found, falling back to body`),document.body.appendChild(l)}return()=>{var p;(p=l.parentElement)==null||p.removeChild(l)}},[r,t,n,d]),d==="inline"&&!t?c.jsx("div",{ref:i,style:a}):null};class He extends HTMLElement{constructor(t,s){var i;super();C(this,"shadow");C(this,"root",null);C(this,"commandRegistry");C(this,"config");this.shadow=this.attachShadow({mode:"open"}),this.commandRegistry=t,this.config=s;const r=((i=this.config)==null?void 0:i.displayMode)??"panel";this.setAttribute("data-display-mode",r)}connectedCallback(){try{const s=[Pe].map(r=>{const i=new CSSStyleSheet;return i.replaceSync(r),i});this.shadow.adoptedStyleSheets=[...s]}catch{const s=[Pe].join(`
479
+ `),r=document.createElement("style");r.textContent=s,this.shadow.appendChild(r)}const t=document.createElement("div");t.id="citadel-root",t.style.width="100%",t.style.height="100%",this.shadow.appendChild(t),this.root=Oe.createRoot(t),this.root.render(c.jsx($e,{config:this.config||E,commandRegistry:this.commandRegistry,children:c.jsx(at,{})}))}disconnectedCallback(){const t=this.root;if(this.root=null,!t){this.shadow.replaceChildren();return}queueMicrotask(()=>{t.unmount(),this.shadow.replaceChildren()})}}typeof window<"u"&&window.customElements&&!window.customElements.get("citadel-element")&&window.customElements.define("citadel-element",He);const at=()=>(L().displayMode??"panel")==="inline"?c.jsx(rt,{}):c.jsx(st,{});class it{constructor(){C(this,"_description")}describe(e){return this._description=e,this}get description(){return this._description}}class lt{constructor(e){C(this,"state");this.state={path:e,description:"",segments:ct(e)}}describe(e){return this.state.description=e,this}details(e){return this.state.details=e,this}arg(e,t){const s=new it;return t==null||t(s),this.state.segments.push({type:"argument",name:e,description:s.description}),this}handle(e){return{path:this.state.path,description:this.state.description,details:this.state.details,segments:[...this.state.segments],handler:e}}}function ct(n){const e=n.trim();if(!e)throw new Error("Command path cannot be empty");const t=e.split(".");if(t.some(s=>s.trim()===""))throw new Error(`Invalid command path "${n}". Empty segments are not allowed.`);if(t.some(s=>s.includes(" ")))throw new Error(`Invalid command path "${n}". Use dot-delimited words (e.g. "user.show").`);return t.map(s=>({type:"word",name:s}))}function dt(n){return n.flatMap(e=>e.type==="argument"?[e.name]:[])}function mt(n){const e=dt(n.segments);return async t=>{const s=e.reduce((r,i,a)=>(r[i]=t[a],r),{});return Promise.resolve(n.handler({rawArgs:t,namedArgs:s,commandPath:n.path}))}}function ut(n){return new lt(n)}function Me(n,e){n.addCommand(e.segments,e.description,mt(e))}function _e(n,e){return e.forEach(t=>Me(n,t)),n}function pt(n){const e=new K;return _e(e,n)}function ht(n){return new q(n)}function gt(n,e="true",t="false"){return new me(n,e,t)}function ft(n){return new de(n)}function yt(n,e=""){return new pe(n,e)}function Ct(n){return new ne(n)}g.BooleanCommandResult=me,g.Citadel=ot,g.CommandRegistry=K,g.CommandResult=F,g.CommandStatus=$,g.DEFAULT_CURSOR_CONFIGS=xe,g.ErrorCommandResult=ne,g.ImageCommandResult=pe,g.JsonCommandResult=de,g.OutputItem=Q,g.PendingCommandResult=ue,g.TextCommandResult=q,g.bool=gt,g.command=ut,g.createCommandRegistry=pt,g.error=Ct,g.image=yt,g.json=ft,g.registerCommand=Me,g.registerCommands=_e,g.text=ht,Object.defineProperty(g,Symbol.toStringTag,{value:"Module"})});
@@ -28,6 +28,8 @@ import { CitadelConfig } from './types';
28
28
  *
29
29
  * @property outputFontSize - The output font size as a CSS value. Default: '0.875rem'.
30
30
  *
31
+ * @property showOutputPane - Whether to render the output pane. Default: true.
32
+ *
31
33
  * @property resetStateOnHide - When true, hiding the interface (via Escape key or other means) will clear the command input.
32
34
  * When false, the interface preserves the last input when hidden. Default: false.
33
35
  *
@@ -65,6 +65,12 @@ export interface CitadelConfig {
65
65
  * If omitted, output uses `fontSize`.
66
66
  */
67
67
  outputFontSize?: string;
68
+ /**
69
+ * Controls whether the output pane is rendered.
70
+ * Set to `false` when command side effects are rendered elsewhere in the host app.
71
+ * Defaults to `true`.
72
+ */
73
+ showOutputPane?: boolean;
68
74
  /**
69
75
  * Whether to reset the state when the interface is hidden (via Escape key or other means).
70
76
  */
@@ -8,6 +8,7 @@ export interface RuntimeConfigControls {
8
8
  setCursorColor: (color: string) => void;
9
9
  setDisplayMode: (mode: DisplayMode) => void;
10
10
  setIncludeHelpCommand: (enabled: boolean) => void;
11
+ toggleOutputPane: () => void;
11
12
  setMaxHeight: (value: string) => void;
12
13
  resetConfig: () => void;
13
14
  }
package/package.json CHANGED
@@ -17,7 +17,7 @@
17
17
  "type": "git",
18
18
  "url": "git+https://github.com/jchilders/citadel_cli.git"
19
19
  },
20
- "version": "1.4.1",
20
+ "version": "1.4.2",
21
21
  "type": "module",
22
22
  "scripts": {
23
23
  "build": "tsc && vite build && node scripts/sync-package-artifacts.mjs",