citadel_cli 1.4.0 → 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(f,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):(f=typeof globalThis<"u"?globalThis:f||self,c(f.Citadel={},f.jsxRuntime,f.React,f.client))})(this,function(f,c,o,Ae){"use strict";var ct=Object.defineProperty;var dt=(f,c,o)=>c in f?ct(f,c,{enumerable:!0,configurable:!0,writable:!0,value:o}):f[c]=o;var C=(f,c,o)=>dt(f,typeof c!="symbol"?c+"":c,o);var L=(n=>(n.Pending="pending",n.Success="success",n.Failure="failure",n.Timeout="timeout",n))(L||{});class j{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 ae extends j{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 O extends j{constructor(e,t){super(t),this.text=e}render(){return c.jsx("div",{className:"citadel-result-text",children:this.text})}}class Q extends j{constructor(e,t){super(t),this.error=e,this.markFailure()}render(){return c.jsx("div",{className:"citadel-result-error",children:this.error})}}class ie extends j{render(){return c.jsx("div",{className:"citadel-result-pending",children:"..."})}}class le extends j{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 Pe=n=>async function(){const t=n.commands.filter(s=>s.fullPath[0]!=="help").map(s=>{const a=`${s.segments.map(d=>d.type==="argument"?`<${d.name}>`:d.name).join(" ")} - ${s.description}`,i=s.segments.filter(d=>d.type==="argument"&&d.description).map(d=>` <${d.name}>: ${d.description}`);return{commandLine:a,argumentLines:i}}).sort((s,r)=>s.commandLine.localeCompare(r.commandLine)).flatMap(s=>[s.commandLine,...s.argumentLines]);return t.length===0?new O("No commands available yet. Add some commands to get started!"):(t.push("help - Show available commands"),new O(`Available Commands:
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
2
  `+t.join(`
3
- `)))};var X=(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))(X||{});const ce=!0;class k{static configure(e){this.level=e.level,this.prefix=e.prefix||"[Citadel]"}static trace(...e){this.level>=5&&!ce&&console.trace(this.prefix,...e)}static debug(...e){this.level>=4&&!ce&&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 I={commandTimeoutMs:1e4,cursorColor:"var(--cursor-color, #fff)",cursorSpeed:530,cursorType:"blink",includeHelpCommand:!0,fontFamily:"monospace",fontSize:"0.875rem",initialHeight:"50vh",logLevel:X.ERROR,maxHeight:"80vh",minHeight:"200",outputFontSize:"0.875rem",resetStateOnHide:!1,showCitadelKey:".",displayMode:"panel",storage:{type:"localStorage",maxCommands:100}},de=async()=>new O("");class Z{constructor(e,t,s){this.type=e,this.name=t,this.description=s}toString(){return this.name}}class R extends Z{constructor(){super("null",">null<","Empty segment")}}class me extends Z{constructor(e,t){super("word",e,t)}}class U extends Z{constructor(e,t,s,r){super("argument",e,t),this.value=s,this.valid=r}}const Me=n=>{if(n.type==="word")return new me(n.name,n.description);if(n.type==="argument"){const e=n;return new U(e.name,e.description,e.value,e.valid)}return new R},M=n=>n.map(e=>Me(e));class He{constructor(e,t,s=de){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 ${constructor(){C(this,"_commands",[])}get commands(){return this._commands}addCommand(e,t,s=de){if(e===void 0||e.length===0)throw new Error("Command path cannot be empty");const r=new He(e,t,s),a=this._commands.find(i=>{const d=i.segments.map(u=>u.type==="argument"?"*":u.name).join(" "),l=e.map(u=>u.type==="argument"?"*":u.name).join(" ");return d===l});if(a)throw new Error(`Duplicate commands: '${a.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 i=t.segments.filter(d=>d.type==="word").map(d=>d.name);return i.length===e.length&&i.join(" ")===r})}commandExistsForPath(e){const t=this._commands.map(r=>r.segments.map(a=>a.type==="argument"?"*":a.name).join(" ")),s=e.map((r,a)=>this._commands.some(d=>{var l;return((l=d.segments[a])==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(a=>a.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 a=this._commands.map(l=>l.segments[0]),i=(l,u)=>l.type===u.type&&l.name===u.name;return a.filter((l,u,y)=>u===y.findIndex(p=>i(p,l)))}const t=e.length;return this._commands.filter(a=>{const i=a.segments;if(i.length<=t-1)return!1;for(let d=0;d<t;d++){const l=e[d],u=i[d];if(!(l==="*"&&u.type==="argument")&&l!==u.name)return!1}return!0}).filter(a=>a.segments.length>t).map(a=>{const i=a.segments[t],d=i.type==="argument"?U:me;return new d(i.name,i.description)}).filter((a,i,d)=>i===d.findIndex(l=>l.type===a.type&&l.name===a.name))}hasNextSegment(e){return this.getCompletions(e).length>0}}class ue{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 _e extends ue{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)?M(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)?M(r.commandSegments).map(a=>({type:a.type,name:a.name,description:a.description,...a instanceof U?{value:a.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 pe extends ue{constructor(t){super(t);C(this,"storedCommands",[])}async getStoredCommands(){return this.storedCommands.map(t=>({commandSegments:Array.isArray(t.commandSegments)?M(t.commandSegments):[],timestamp:t.timestamp}))}async clear(){this.storedCommands=[]}async saveCommands(t){this.storedCommands=t.map(s=>({commandSegments:Array.isArray(s.commandSegments)?M(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 pe(e):this.currentStorage=new _e(e)}catch(t){console.warn("Failed to create storage, falling back to memory storage:",t),this.currentStorage=new pe(e)}}getStorage(){if(!this.currentStorage)throw new Error("Storage not initialized. Call initializeStorage first.");return this.currentStorage}};C(z,"instance");let B=z;class he{constructor(){C(this,"segments",[]);C(this,"nullSegment",new R);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 Te={config:I,commands:new $,segmentStack:new he},q=o.createContext(Te),ze=({config:n=I,commandRegistry:e,children:t})=>{const[s,r]=o.useState(),[a]=o.useState(()=>new he),i=o.useMemo(()=>({...I,...n,storage:{...I.storage,...n.storage},cursorType:n.cursorType??I.cursorType,cursorColor:n.cursorColor??I.cursorColor,cursorSpeed:n.cursorSpeed??I.cursorSpeed,showCitadelKey:n.showCitadelKey||"."}),[n]);o.useEffect(()=>{B.getInstance().initializeStorage(i.storage??I.storage),r(B.getInstance().getStorage())},[i.storage]),o.useEffect(()=>{if(e){if(i.includeHelpCommand){if(!e.commandExistsForPath(["help"])){const l=Pe(e);e.addCommand([{type:"word",name:"help"}],"Show available commands",l)}return}e.removeCommand(["help"])}},[e,i.includeHelpCommand]);const d=o.useMemo(()=>({config:i,commands:e||new $,storage:s,segmentStack:a}),[i,e,s,a]);return c.jsx(q.Provider,{value:d,children:t})},T=()=>{const n=o.useContext(q);if(n===void 0)throw new Error("useCitadelConfig must be used within a CitadelConfigProvider");return n.config},V=()=>{const n=o.useContext(q);if(n===void 0)throw new Error("useCitadelCommands must be used within a CitadelConfigProvider");return n.commands},ge=()=>{const n=o.useContext(q);if(n===void 0)throw new Error("useCitadelStorage must be used within a CitadelConfigProvider");return n.storage},W=()=>{const n=o.useContext(q);if(n===void 0)throw new Error("useSegmentStack must be used within a CitadelConfigProvider");return n.segmentStack},G=class G{constructor(e,t){C(this,"id");C(this,"timestamp");C(this,"command");C(this,"result");this.id=`output-${Date.now()}-${G.idCounter++}`,this.command=e.toArray().map(s=>s.type==="argument"?s.value||"":s.name),this.timestamp=Date.now(),this.result=t??new ie}};C(G,"idCounter",0);let Y=G;function De(n){return{commandSegments:M(n),timestamp:Date.now()}}function fe(){const n=ge(),[e,t]=o.useState({storedCommands:[],position:null}),s=o.useCallback(async d=>{if(n)try{const l=De(d);await n.addStoredCommand(l),t(u=>({...u,storedCommands:[...u.storedCommands,{...l,commandSegments:M(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:M(l.commandSegments)})):[],[n]);o.useEffect(()=>{if(!n)return;(async()=>{try{const u=(await n.getStoredCommands()).map(y=>({...y,commandSegments:M(y.commandSegments)}));return t(y=>({...y,storedCommands:u})),u}catch(l){console.warn("Failed to load command history:",l)}})()},[n]);const a=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(g=>({...g,commandSegments:M(g.commandSegments)})),position:u})),u===null)return{segments:[],position:null};const y=l[u];return y?{segments:M(y.commandSegments),position:u}:{segments:[],position:null}},[e.position,r]),i=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:a,clear:i}}const ee=()=>{const n=T(),e=V(),t=fe(),s=W(),r=ge(),[a,i]=o.useState({currentInput:"",isEnteringArg:!1,output:[],history:{commands:[],position:null,storage:r}});o.useEffect(()=>{},[r]),o.useEffect(()=>{i(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),i(u=>({...u,currentInput:l}))},[]),setIsEnteringArg:o.useCallback(l=>{k.debug("[CitadelActions] setIsEnteringArg: ",l),i(u=>({...u,isEnteringArg:l}))},[]),addOutput:o.useCallback(l=>{k.debug("[CitadelActions]addOutput: ",l),i(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 y=new Y(s);i(p=>({...p,output:[...p.output,y]}));try{const p=new Promise((w,S)=>{setTimeout(()=>{S(new Error("Request timed out"))},n.commandTimeoutMs)}),g=s.arguments.map(w=>w.value||""),x=await Promise.race([u.handler(g),p]);if(!(x instanceof j))throw new Error(`The ${l.join(".")} command returned an invalid result type. Commands must return an instance of a CommandResult.
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.`);x.markSuccess(),i(w=>({...w,output:w.output.map(S=>S.id===y.id?{...S,result:x}:S)}))}catch(p){const g=new Q(p instanceof Error?p.message:"Unknown error");g.markFailure(),i(x=>({...x,output:x.output.map(w=>w.id===y.id?{...w,result:g}:w)}))}},[e,n.commandTimeoutMs,s]),clearHistory:o.useCallback(async()=>{try{await t.clear()}catch(l){console.warn("Failed to clear history:",l)}},[t])};return{state:a,actions:d}},Fe=({onOpen:n,onClose:e,isVisible:t,showCitadelKey:s})=>{o.useEffect(()=>{const r=a=>{var i,d;!t&&a.key===s&&!["input","textarea"].includes(((d=(i=a.target)==null?void 0:i.tagName)==null?void 0:d.toLowerCase())||"")&&(a.preventDefault(),n()),t&&a.key==="Escape"&&(a.preventDefault(),e())};return document.addEventListener("keydown",r),()=>document.removeEventListener("keydown",r)},[n,e,t,s])},je=n=>{const{isVisible:e,isClosing:t,onAnimationComplete:s}=n,r=o.useMemo(()=>e?t?"citadel_slideDown":"citadel_slideUp":"",[e,t]);return o.useEffect(()=>{if(s){const i=setTimeout(()=>{s()},200);return()=>clearTimeout(i)}},[t,s]),{style:o.useMemo(()=>({opacity:e?1:0,transform:e?"translateY(0)":t?"translateY(100%)":"translateY(-100%)",transition:"opacity 200ms ease-in-out, transform 200ms ease-in-out"}),[e,t]),animationClass:r}},Le=()=>c.jsx("div",{"data-testid":"spinner",className:"citadel-spinner"}),ye=n=>{const e=n==null?void 0:n.trim();return e||void 0},Ue=n=>{const e=ye(n);return e?{style:{fontSize:e}}:{}},J=(n,e)=>{const t=ye(n),r={...Ue(e).style};return t&&(r.fontFamily=t),{style:Object.keys(r).length>0?r:void 0}},Oe=({command:n,timestamp:e,status:t,fontFamily:s,fontSize:r})=>{const a=o.useMemo(()=>J(s,r??"0.875rem"),[s,r]);return c.jsxs("div",{className:"citadel-output-line",style:a.style,children:[c.jsxs("span",{className:"citadel-output-command",children:["> ",n.split(" ").map((i,d)=>{const l=i.startsWith("<")&&i.endsWith(">");return c.jsxs("span",{className:l?"citadel-output-command-arg":"citadel-output-command-word",children:[d>0?" ":"",i]},d)})]}),c.jsx("span",{className:"citadel-output-separator",children:"·"}),c.jsx("span",{className:"citadel-output-timestamp",children:e}),t===L.Pending&&c.jsx(Le,{}),t===L.Success&&c.jsx("div",{"data-testid":"success-indicator",className:"citadel-status-dot citadel-status-dot-success"}),(t===L.Timeout||t===L.Failure)&&c.jsx("div",{"data-testid":"success-indicator",className:"citadel-status-dot citadel-status-dot-failure"})]})},$e=({output:n,outputRef:e})=>{const t=T(),s=o.useMemo(()=>J(t.fontFamily,t.outputFontSize??t.fontSize),[t.fontFamily,t.fontSize,t.outputFontSize]),r=o.useCallback(()=>{if(e.current){const a=e.current;requestAnimationFrame(()=>{a.scrollTop=a.scrollHeight})}},[e]);return o.useEffect(()=>{if(r(),e.current){const a=e.current.getElementsByTagName("img"),i=a[a.length-1];if(i&&!i.complete)return i.addEventListener("load",r),()=>i.removeEventListener("load",r)}},[n,r,e]),c.jsx("div",{ref:e,className:"citadel-output","data-testid":"citadel-command-output",children:n.map(a=>c.jsxs("div",{className:"citadel-output-item",children:[c.jsx(Oe,{command:a.command.join(" "),timestamp:new Date(a.timestamp).toLocaleTimeString(),status:a.result.status,fontFamily:t.fontFamily,fontSize:t.fontSize}),c.jsx("div",{className:"citadel-output-content",style:s.style,children:a.result.render()})]},a.id))})},Ce={blink:{character:"▋",speed:530,color:"#fff"},spin:{character:"⠋",speed:120,color:"#fff"},solid:{character:"▋",speed:0,color:"#fff"},bbs:{character:"|",speed:120,color:"#fff"}},we=["⠋","⠙","⠹","⠸","⠼","⠴","⠦","⠧","⠇","⠏"],ve=["|","/","-","\\"],qe=({style:n={type:"blink"},isValid:e=!0,errorMessage:t})=>{const s=o.useMemo(()=>({...Ce[n.type],...n}),[n]),[r,a]=o.useState(!0),[i,d]=o.useState(0);o.useEffect(()=>{if(s.speed===0)return;const y=setInterval(()=>{s.type==="blink"?a(p=>!p):["spin","bbs"].includes(s.type)&&d(p=>(p+1)%(s.type==="bbs"?ve.length:we.length))},s.speed);return()=>clearInterval(y)},[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"?ve:we)[i]: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 We(n,e){switch(e.type){case"set":return k.debug(`[inputStateReducer] InputState changing from ${n} to ${e.state}`),e.state;default:return n}}const Ke=()=>{const{state:n}=ee(),e=V(),t=fe(),s=W(),[r,a]=o.useReducer(We,"idle"),i=m=>{a({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(H=>{const b=H.segments[v];return!b||b.type!=="word"?!1:b.name.toLowerCase().startsWith(m.toLowerCase())})},[s]),y=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]),g=o.useCallback(m=>{k.debug("[tryAutoComplete] input: ",m);const h=y(m);return!h||h.type==="null"?new R:(k.debug("[tryAutoComplete] result: ",h),h)},[y]),x=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 A=Se(m);if(A.isQuoted)if(A.isComplete){if(!(v instanceof U))return;v.value=m.trim()||"",k.debug("[useCommandParser][handleInputChange][entering_command] pushing: ",v),s.push(v),h.setCurrentInput(""),i("idle");return}else return;else if(A.isComplete){if(!(v instanceof U))return;v.value=m.trim()||"",k.debug("[useCommandParser][handleInputChange][entering_command] pushing: ",v),s.push(v),h.setCurrentInput(""),i("idle");return}else return}if(m.endsWith(" ")){const A=m.trim().toLowerCase(),_=e.getCompletions(s.path()).filter(E=>E.type==="word"&&E.name.toLowerCase()===A);if(_.length===1){s.push(_[0]),h.setCurrentInput(""),i("idle");return}}const b=g(m);if(b.type==="word"){k.debug("[useCommandParser][handleInputChange][entering_command] pushing: ",b),s.push(b),h.setCurrentInput(""),i("idle");return}},[g,n,d,r,s,e]),w=o.useCallback(m=>{m.setCurrentInput(""),m.setIsEnteringArg(!1),s.clear(),i("idle")},[s]),S=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:A}=h,_=Se(b);switch(m.key){case"Backspace":return b===""&&(m.preventDefault(),s.size()>0&&s.pop(),i("idle")),!0;case"Enter":{if(m.preventDefault(),_.isQuoted&&!_.isComplete)return!0;if(r==="entering_argument"||A&&b.trim()){const D=d();D instanceof U&&(D.value=b,k.debug("[handleKeyDown][Enter]['entering_argument'] pushing: ",D),s.push(D))}const E=s.path(),ne=e.getCommand(E);if(!ne)return!1;const K=ne.segments.filter(D=>D.type==="argument"),se=s.arguments;return K.length>se.length?!1:(k.debug("[handleKeyDown][Enter] calling actions.executeCommand. segmentStack: ",s),v.executeCommand(),t.addStoredCommand(s.toArray()),w(v),!0)}case"ArrowUp":return m.preventDefault(),(async()=>{const E=await t.navigateHistory("up");return E.segments&&(s.clear(),s.pushAll(E.segments),v.setCurrentInput("")),!0})();case"ArrowDown":return m.preventDefault(),(async()=>{const E=await t.navigateHistory("down");return E.segments&&(s.clear(),s.pushAll(E.segments),v.setCurrentInput("")),!0})();default:{if(!A&&m.key.length===1){const E=b+m.key;if(!p(E))return m.preventDefault(),!1}return!0}}},[r,p,d,t,w,e,s]);return{handleInputChange:x,handleKeyDown:S,inputState:r,setInputStateWithLogging:i,findMatchingCommands:u,getAutocompleteSuggestion:y,getAvailableNodes:l,getNextExpectedSegment:d,isValidCommandInput:p}};function Se(n){const e=[];let t="",s=!1,r;for(let a=0;a<n.length;a++){const i=n[a];(i==='"'||i==="'")&&(!s||i===r)?s?(e.push(t),t="",s=!1,r=void 0):(t&&(e.push(t),t=""),s=!0,r=i):!s&&i===" "?t&&(e.push(t),t=""):t+=i}return{words:e,currentWord:t,isQuoted:s,quoteChar:r,isComplete:!s&&!t}}const Be=()=>{const n=W(),[e,t]=o.useState(0);return o.useEffect(()=>{const s={update:()=>{t(r=>r+1)}};return n.subscribe(s),()=>{n.unsubscribe(s)}},[n]),e},Ve=({state:n,actions:e})=>{const t=o.useRef(null),s=V(),r=W(),{handleKeyDown:a,handleInputChange:i,inputState:d,setInputStateWithLogging:l,getNextExpectedSegment:u}=Ke(),[y,p]=o.useState(!1),g=T(),x=Be(),w=o.useRef(null),[S,m]=o.useState(0),h=o.useMemo(()=>J(g.fontFamily,g.fontSize),[g.fontFamily,g.fontSize]),v=o.useCallback(async N=>{const P=a(N,n,e);await Promise.resolve(P)===!1&&(p(!0),setTimeout(()=>p(!1),500))},[e,a,n]),H=o.useCallback(N=>{i(N.target.value,e)},[e,i]),b=o.useCallback(N=>{N.preventDefault();const P=N.clipboardData.getData("text");i(P,e)},[e,i]);o.useEffect(()=>{t.current&&t.current.focus(),d!=="entering_command"&&l("entering_command")},[d,l]),o.useEffect(()=>{if(d!=="idle")return;const N=u();let P="idle";switch(N.type){case"word":P="entering_command",e.setIsEnteringArg(!1);break;case"argument":P="entering_argument",e.setIsEnteringArg(!0);break}l(P)},[x,d,u,l,e]);const A=o.useMemo(()=>{const N=[],P=r.toArray().map((F,re)=>{N.push(F.name);const Ie=s.hasNextSegment(N);if(F.type==="argument"){const oe=F;return c.jsxs(o.Fragment,{children:[c.jsx("span",{className:"citadel-input-segment-arg",children:oe.value}),re<r.size()&&Ie&&c.jsx("span",{className:"citadel-input-segment-space",children:" "})]},"arg-"+oe.name+oe.value)}return c.jsxs(o.Fragment,{children:[c.jsx("span",{className:"citadel-input-segment-word",children:F.name}),re<r.size()&&Ie&&c.jsx("span",{className:"citadel-input-segment-space citadel-input-segment-space-command",children:" "})]},"word-"+F.name)});return[c.jsx("div",{className:"citadel-input-segments","data-testid":"user-input-area",children:P},x)]},[x,s,r]),[_,E]=o.useState("");o.useEffect(()=>{const N=u();N.type==="argument"?E(N.name):E("")},[x,u]);const K=!n.isEnteringArg?"is-command-mode":"is-argument-mode",se=o.useMemo(()=>({left:`${S}px`,transition:"left 0.05s ease-out"}),[S]),D=o.useMemo(()=>({type:g.cursorType??I.cursorType,color:g.cursorColor||I.cursorColor,speed:g.cursorSpeed||I.cursorSpeed}),[g.cursorColor,g.cursorSpeed,g.cursorType]);return o.useLayoutEffect(()=>{const N=w.current,P=t.current;if(!N||!P){m(0);return}const F=N.getBoundingClientRect().width;m(Math.max(0,F-P.scrollLeft))},[n.currentInput,K,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:w,className:`citadel-input-measure ${K}`.trim(),"aria-hidden":"true",children:n.currentInput}),c.jsx("input",{ref:t,type:"text",role:"textbox",value:n.currentInput,onChange:H,onKeyDown:v,onPaste:b,"data-testid":"citadel-command-input",className:`citadel-input-field ${K} ${y?"invalid-input-animation":""}`.trim(),spellCheck:!1,autoComplete:"off",placeholder:_}),c.jsx("div",{className:"citadel-input-cursor",style:se,children:c.jsx(qe,{style:D})})]})]})]})})},Ye=({currentInput:n=""})=>{const e=V(),t=T(),s=W(),r=o.useMemo(()=>J(t.fontFamily,t.fontSize),[t.fontFamily,t.fontSize]),a=n.trim().toLowerCase(),i=e.getMatchingCompletions(s.path(),a);k.debug("[AvailableCommands] nextCommandSegments: ",i);const d=o.useMemo(()=>{const p=[...i],g=m=>m.name.toLowerCase()==="help",x=p.filter(g);return[...p.filter(m=>!g(m)).sort((m,h)=>m.name.localeCompare(h.name,void 0,{sensitivity:"base"})),...x]},[i]),l=o.useMemo(()=>{const p=new Map;for(const g of d){const x=d.reduce((w,S)=>{if(S===g)return w;let m=0;for(;m<g.name.length&&m<S.name.length&&g.name[m].toLowerCase()===S.name[m].toLowerCase();)m++;return Math.max(w,m+1)},1);p.set(g.name,x)}return p},[d]),u=i.some(p=>p.type==="argument"),y=i[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?i.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 g=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,g)}),p.name.slice(g)]})},p.name)})})})})},be=({state:n,actions:e,outputRef:t})=>{const r=T().displayMode==="inline",a=o.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:a,children:c.jsx($e,{output:n.output,outputRef:t})}),c.jsxs("div",{className:"citadel-tty-input-region",children:[c.jsx(Ve,{state:n,actions:e}),c.jsx(Ye,{currentInput:n.isEnteringArg?"":n.currentInput})]})]})},Je=()=>{const[n,e]=o.useState(!1),[t,s]=o.useState(!1),r=T(),[a,i]=o.useState(()=>r.initialHeight||null),d=o.useRef(null),l=o.useRef(null),u=o.useRef(!1),y=o.useRef(0),p=o.useRef(0),{state:g,actions:x}=ee();Fe({onOpen:()=>e(!0),onClose:()=>s(!0),isVisible:n,showCitadelKey:r.showCitadelKey||"."});const w=o.useCallback(H=>{var E;if(!u.current)return;const b=H.clientY-y.current,A=(E=r.maxHeight)!=null&&E.endsWith("vh")?window.innerHeight*parseInt(r.maxHeight,10)/100:parseInt(r.maxHeight||"80vh",10),_=Math.min(Math.max(p.current-b,parseInt(r.minHeight||"200",10)),A);l.current&&(l.current.style.height=`${_}px`,l.current.style.bottom="0",i(`${_}px`))},[r.maxHeight,r.minHeight]),S=o.useCallback(()=>{u.current=!1,document.documentElement.style.userSelect="",document.documentElement.style.webkitUserSelect="",document.documentElement.style.mozUserSelect="",document.documentElement.style.msUserSelect="",document.removeEventListener("mousemove",w),document.removeEventListener("mouseup",S)},[w]),m=o.useCallback(H=>{l.current&&(u.current=!0,y.current=H.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",w),document.addEventListener("mouseup",S))},[w,S]);o.useEffect(()=>()=>{document.removeEventListener("mousemove",w),document.removeEventListener("mouseup",S)},[w,S]);const h=o.useCallback(()=>{t&&(e(!1),s(!1))},[t]);je({isVisible:n,isClosing:t,onAnimationComplete:h});const v=o.useMemo(()=>({...a?{height:a}:{},maxHeight:r.maxHeight}),[r.maxHeight,a]);return n?c.jsxs("div",{ref:l,className:`panelContainer ${n?"citadel_slideUp":""} ${t?"citadel_slideDown":""}`,style:v,children:[c.jsx("div",{className:"resizeHandle",onMouseDown:m}),c.jsx(be,{state:g,actions:x,outputRef:d})]}):null},te=n=>{if(!n)return;const e=n.trim();if(e)return/^\d+(\.\d+)?$/.test(e)?`${e}px`:e},Ge=()=>{const{state:n,actions:e}=ee(),t=T(),s=o.useRef(null),r=o.useMemo(()=>({height:te(t.initialHeight),maxHeight:te(t.maxHeight),minHeight:te(t.minHeight)}),[t.initialHeight,t.maxHeight,t.minHeight]);return c.jsx("div",{className:"inlineContainer","data-testid":"citadel-inline-container",style:r,children:c.jsx(be,{state:n,actions:e,outputRef:s})})},xe=`: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);
@@ -17,6 +17,10 @@ Check the definition of the ${l.join(".")} command and update the return type fo
17
17
  --citadel-min-height: 200px;
18
18
  --citadel-max-height: 80vh;
19
19
  --citadel-default-height: 35vh;
20
+ --citadel-panel-enter-duration: 200ms;
21
+ --citadel-panel-exit-duration: 200ms;
22
+ --citadel-panel-enter-easing: cubic-bezier(0.16, 1, 0.3, 1);
23
+ --citadel-panel-exit-easing: cubic-bezier(0.4, 0, 1, 1);
20
24
 
21
25
  display: block;
22
26
  pointer-events: auto;
@@ -76,6 +80,8 @@ Check the definition of the ${l.join(".")} command and update the return type fo
76
80
  padding: 0;
77
81
  background-color: var(--citadel-bg);
78
82
  overflow: hidden;
83
+ transform: translateY(0);
84
+ will-change: transform;
79
85
  }
80
86
 
81
87
  .innerContainer {
@@ -143,11 +149,18 @@ Check the definition of the ${l.join(".")} command and update the return type fo
143
149
  }
144
150
 
145
151
  .citadel_slideUp {
146
- animation: citadel_slideUp 0.2s ease-out forwards;
152
+ animation: citadel_slideUp var(--citadel-panel-enter-duration) var(--citadel-panel-enter-easing) forwards;
147
153
  }
148
154
 
149
155
  .citadel_slideDown {
150
- animation: citadel_slideDown 0.2s ease-out forwards;
156
+ animation: citadel_slideDown var(--citadel-panel-exit-duration) var(--citadel-panel-exit-easing) forwards;
157
+ }
158
+
159
+ @media (prefers-reduced-motion: reduce) {
160
+ :host {
161
+ --citadel-panel-enter-duration: 1ms;
162
+ --citadel-panel-exit-duration: 1ms;
163
+ }
151
164
  }
152
165
 
153
166
  .inlineContainer {
@@ -462,5 +475,5 @@ Check the definition of the ${l.join(".")} command and update the return type fo
462
475
  object-fit: contain;
463
476
  border-radius: 0.5rem;
464
477
  }
465
- `,Qe=({config:n=I,commandRegistry:e,containerId:t=null})=>{const s=o.useRef(new $),r=e??s.current,a=o.useRef(null),i=o.useMemo(()=>({width:"100%",height:"100%"}),[]),d=n.displayMode??I.displayMode??"panel";return o.useEffect(()=>{k.configure({level:n.logLevel||I.logLevel||X.ERROR,prefix:"[Citadel]"});const l=new ke(r,n),u=d==="inline"&&!t,y=u?a.current:t?document.getElementById(t):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 "${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:a,style:i}):null};class ke extends HTMLElement{constructor(t,s){var a;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=((a=this.config)==null?void 0:a.displayMode)??"panel";this.setAttribute("data-display-mode",r)}connectedCallback(){try{const s=[xe].map(r=>{const a=new CSSStyleSheet;return a.replaceSync(r),a});this.shadow.adoptedStyleSheets=[...s]}catch{const s=[xe].join(`
466
- `),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=Ae.createRoot(t),this.root.render(c.jsx(ze,{config:this.config||I,commandRegistry:this.commandRegistry,children:c.jsx(Xe,{})}))}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",ke);const Xe=()=>(T().displayMode??"panel")==="inline"?c.jsx(Ge,{}):c.jsx(Je,{});class Ze{constructor(){C(this,"_description")}describe(e){return this._description=e,this}get description(){return this._description}}class Re{constructor(e){C(this,"state");this.state={path:e,description:"",segments:et(e)}}describe(e){return this.state.description=e,this}details(e){return this.state.details=e,this}arg(e,t){const s=new Ze;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 et(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 tt(n){return n.flatMap(e=>e.type==="argument"?[e.name]:[])}function nt(n){const e=tt(n.segments);return async t=>{const s=e.reduce((r,a,i)=>(r[a]=t[i],r),{});return Promise.resolve(n.handler({rawArgs:t,namedArgs:s,commandPath:n.path}))}}function st(n){return new Re(n)}function Ee(n,e){n.addCommand(e.segments,e.description,nt(e))}function Ne(n,e){return e.forEach(t=>Ee(n,t)),n}function rt(n){const e=new $;return Ne(e,n)}function ot(n){return new O(n)}function at(n){return new ae(n)}function it(n,e=""){return new le(n,e)}function lt(n){return new Q(n)}f.Citadel=Qe,f.CommandRegistry=$,f.CommandResult=j,f.CommandStatus=L,f.DEFAULT_CURSOR_CONFIGS=Ce,f.ErrorCommandResult=Q,f.ImageCommandResult=le,f.JsonCommandResult=ae,f.OutputItem=Y,f.PendingCommandResult=ie,f.TextCommandResult=O,f.command=st,f.createCommandRegistry=rt,f.error=lt,f.image=it,f.json=at,f.registerCommand=Ee,f.registerCommands=Ne,f.text=ot,Object.defineProperty(f,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,11 +28,17 @@ 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
  *
36
+ * @property closeOnEscape - When true, pressing Escape hides the panel in panel mode. Default: true.
37
+ *
34
38
  * @property showCitadelKey - The keyboard key that shows the command interface. Default: '.' (period).
35
39
  *
40
+ * @property showOnLoad - When true, panel mode starts visible on mount. Default: false.
41
+ *
36
42
  * @property storage - Configuration for command history storage. Default: { type: 'localStorage', maxCommands: 100 }.
37
43
  */
38
44
  export declare const defaultConfig: CitadelConfig;
@@ -65,14 +65,30 @@ 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
  */
71
77
  resetStateOnHide?: boolean;
78
+ /**
79
+ * Whether to keep Escape from closing the panel in `displayMode: 'panel'`.
80
+ * Defaults to `true`.
81
+ */
82
+ closeOnEscape?: boolean;
72
83
  /**
73
84
  * The keyboard key that shows the command interface.
74
85
  */
75
86
  showCitadelKey?: string;
87
+ /**
88
+ * Whether to show the panel immediately on mount when `displayMode: 'panel'`.
89
+ * Defaults to `false`.
90
+ */
91
+ showOnLoad?: boolean;
76
92
  /**
77
93
  * Presentation mode for rendering the Citadel interface.
78
94
  * - 'panel': Renders as an overlay panel anchored to the viewport bottom and toggled via keyboard shortcuts.
@@ -3,6 +3,7 @@ interface UseGlobalShortcutProps {
3
3
  onClose: () => void;
4
4
  isVisible: boolean;
5
5
  showCitadelKey: string;
6
+ closeOnEscape: boolean;
6
7
  }
7
- export declare const useGlobalShortcut: ({ onOpen, onClose, isVisible, showCitadelKey }: UseGlobalShortcutProps) => void;
8
+ export declare const useGlobalShortcut: ({ onOpen, onClose, isVisible, showCitadelKey, closeOnEscape }: UseGlobalShortcutProps) => void;
8
9
  export {};
@@ -3,12 +3,8 @@ interface SlideAnimationOptions {
3
3
  isClosing: boolean;
4
4
  onAnimationComplete?: () => void;
5
5
  }
6
+ export declare const PANEL_CLOSE_DURATION_MS = 200;
6
7
  export declare const useSlideAnimation: (options: SlideAnimationOptions) => {
7
- style: {
8
- opacity: number;
9
- transform: string;
10
- transition: string;
11
- };
12
8
  animationClass: string;
13
9
  };
14
10
  export {};
@@ -1,5 +1,5 @@
1
1
  import { CommandRegistry, CommandSegment } from './command-registry';
2
- import { CommandResult, ErrorCommandResult, ImageCommandResult, JsonCommandResult, TextCommandResult } from './command-results';
2
+ import { BooleanCommandResult, CommandResult, ErrorCommandResult, ImageCommandResult, JsonCommandResult, TextCommandResult } from './command-results';
3
3
  export interface CommandExecutionContext<ArgName extends string = string> {
4
4
  rawArgs: string[];
5
5
  namedArgs: Record<ArgName, string | undefined>;
@@ -27,6 +27,7 @@ export declare function registerCommand(registry: CommandRegistry, definition: C
27
27
  export declare function registerCommands(registry: CommandRegistry, definitions: CommandDefinition[]): CommandRegistry;
28
28
  export declare function createCommandRegistry(definitions: CommandDefinition[]): CommandRegistry;
29
29
  export declare function text(value: string): TextCommandResult;
30
+ export declare function bool(value: boolean, trueText?: string, falseText?: string): BooleanCommandResult;
30
31
  export declare function json(value: unknown): JsonCommandResult;
31
32
  export declare function image(url: string, altText?: string): ImageCommandResult;
32
33
  export declare function error(value: string): ErrorCommandResult;
@@ -25,6 +25,13 @@ export declare class TextCommandResult extends CommandResult {
25
25
  constructor(text: string, timestamp?: number);
26
26
  render(): React.ReactNode;
27
27
  }
28
+ export declare class BooleanCommandResult extends CommandResult {
29
+ readonly value: boolean;
30
+ readonly trueText: string;
31
+ readonly falseText: string;
32
+ constructor(value: boolean, trueText?: string, falseText?: string, timestamp?: number);
33
+ render(): React.ReactNode;
34
+ }
28
35
  export declare class ErrorCommandResult extends CommandResult {
29
36
  readonly error: string;
30
37
  constructor(error: string, timestamp?: number);
@@ -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,10 +17,11 @@
17
17
  "type": "git",
18
18
  "url": "git+https://github.com/jchilders/citadel_cli.git"
19
19
  },
20
- "version": "1.4.0",
20
+ "version": "1.4.2",
21
21
  "type": "module",
22
22
  "scripts": {
23
- "build": "tsc && vite build",
23
+ "build": "tsc && vite build && node scripts/sync-package-artifacts.mjs",
24
+ "verify:pack": "node scripts/verify-package-artifacts.mjs",
24
25
  "dev": "vite",
25
26
  "lint": "eslint .",
26
27
  "lint:fix": "eslint . --fix",