@gencode/cli 0.0.55 → 0.1.0

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.
package/CHANGELOG.md CHANGED
@@ -1,5 +1,18 @@
1
1
  # @gencode/cli
2
2
 
3
+ ## 0.1.0
4
+
5
+ ### Minor Changes
6
+
7
+ - Add CLI support for loading additional absolute skill directories and pass them through run and resume flows into the agent skill registry.
8
+
9
+ ### Patch Changes
10
+
11
+ - 059d077: Expose completed subagent results in status polling and delay delivery marking until parent announce handling succeeds.
12
+ - Updated dependencies
13
+ - Updated dependencies [059d077]
14
+ - @gencode/agents@0.2.0
15
+
3
16
  ## 0.0.55
4
17
 
5
18
  ### Patch Changes
package/dist/bin.js CHANGED
@@ -1,2 +1,2 @@
1
1
  #!/usr/bin/env node
2
- import{a as e,i as t,r as n,t as r}from"./program-PSkNAIli.js";function i(){globalThis.getPkgPath||(globalThis.getPkgPath=()=>`@wizard/aimax`)}i();const a=Date.now(),o=process.env.AIMAX_DATA_DIR;o&&n(o),t.info(`AIMax CLI starting (pid=${process.pid})`),r().parseAsync(process.argv).catch(e=>{t.error(`Unexpected error: ${e.message}`),process.exit(1)}).finally(()=>{let n=Date.now()-a;return t.info(`AIMax CLI exited (total uptime: ${n}ms)`),e()});export{};
2
+ import{a as e,i as t,r as n,t as r}from"./program-DcFUveRe.js";function i(){globalThis.getPkgPath||(globalThis.getPkgPath=()=>`@wizard/aimax`)}i();const a=Date.now(),o=process.env.AIMAX_DATA_DIR;o&&n(o),t.info(`AIMax CLI starting (pid=${process.pid})`),r().parseAsync(process.argv).catch(e=>{t.error(`Unexpected error: ${e.message}`),process.exit(1)}).finally(()=>{let n=Date.now()-a;return t.info(`AIMax CLI exited (total uptime: ${n}ms)`),e()});export{};
@@ -1,10 +1,10 @@
1
1
  import{createRequire as e}from"node:module";import{Command as t}from"commander";import{bootstrapMountLayout as n,buildResumeNarration as r,clearPendingUiTool as i,createBuiltinMemoryProvider as a,ensureBootstrapMountLayout as o,exportSession as s,formatApprovalResolution as c,formatClarifyResolution as l,formatReviewResolution as u,hasBootstrapSentinel as d,initializePluginSystem as f,inspectSession as p,listAvailableSlashCommands as m,listSessionSummaries as h,loadPendingHitl as g,loadPendingUiTool as ee,loadSkillsWithPluginDirs as te,loadTranscript as ne,normalizePluginsConfig as re,normalizeSessionStoreName as _,resolveMemoryProvider as ie,resolvePendingHitl as ae,resolvePendingUiTool as oe,rewriteTranscript as se,runAgent as v}from"@gencode/agents";import{formatTaskForDisplay as ce,isAgentDiagnosticEvent as y,isHitlTool as le,parseMatchedTextToResolution as ue,parseTextToResolution as de}from"@gencode/shared";import b from"node:fs/promises";import x from"node:path";import fe from"gensign-node";import pe from"node:fs";import S from"log4js";import{addAgent as me,addBinding as he,getAgentConfig as C,listAgents as ge,listBindings as _e,loadAgentsConfig as w,normalizeAgentId as ve,removeAgent as ye,removeBindings as be,resolveAgentDir as xe,resolveDefaultAgentId as T,updateAgentIdentity as Se}from"@gencode/agents/config";function Ce(e){process.stdout.write(e)}function E(e){process.stdout.write(e+`
2
2
  `)}function D(e){process.stderr.write(e+`
3
3
  `)}function O(e){switch(e.type){case`start`:E(`\n[start] ${e.message}`);break;case`text`:Ce(e.text);break;case`stream_text_delta`:Ce(e.text);break;case`bootstrap`:E(`\n[bootstrap:${e.phase}] ${e.dataDir}`);break;case`session_reset`:E(`\n[session:${e.action}] ${e.message}`);break;case`tool_start`:E(`\n[tool:${e.name}] ${JSON.stringify(e.input)}`);break;case`tool_end`:E(`[tool:${e.name}] ${e.isError?`ERROR`:`OK`} ${e.output.slice(0,200)}`);break;case`compaction`:E(`\n[compaction${e.layer?`:${e.layer}`:``}] ${e.reason}${e.strategy?` (${e.strategy})`:``}`);break;case`skill_used`:E(`\n[skill] ${e.skillName} agent=${e.agent} task=${e.taskId}`);break;case`custom`:E(`\n[plugin:${e.pluginId}] ${e.name}${e.label?` ${e.label}`:``}${e.data?` ${JSON.stringify(e.data)}`:``}`);break;case`error`:D(`\n[error] ${e.message}`);break;case`diagnostic`:break;case`subagent_spawn`:E(`\n[subagent:spawn]${e.label?` "${e.label}"`:``} ${ce(e.task)}`);break;case`subagent_complete`:E(`[subagent:${e.status}] ${ce(e.task)}`);break;case`hitl_requested`:if(E(`\n[hitl:${e.request.kind}] ${e.request.title}`),E(` prompt: ${e.request.prompt}`),E(` requestId: ${e.request.requestId}`),e.request.input.mode===`choice`)for(let t of e.request.input.choices)E(` - [${t.id}] ${t.label}`);break;case`hitl_resumed`:E(`\n[hitl:resumed] requestId=${e.requestId} action=${e.resolution.action}`);break;case`hitl_expired`:E(`\n[hitl:expired] requestId=${e.requestId} reason=${e.reason}`);break;case`hitl_cancelled`:E(`\n[hitl:cancelled] requestId=${e.requestId}${e.reason?` reason=${e.reason}`:``}`);break;case`ui_tool_request`:E(`\n[ui-tool:${e.request.toolName}] ${e.request.outputSchema.title}`),E(` requestId: ${e.request.requestId}`),E(` toolCallId: ${e.request.toolCallId}`);break;case`ui_tool_result`:E(`\n[ui-tool:resumed] requestId=${e.requestId} tool=${e.toolName}`);break}}function k(e,t){if(t===`json`){E(JSON.stringify(e,null,2));return}E(`
4
- `),E(`session: ${e.sessionId}`),E(`duration: ${e.durationMs}ms`),E(`tokens: input=${e.usage.input} output=${e.usage.output} total=${e.usage.total}`),e.context&&(E(`context: ${e.context.snapshotPath}`),E(`tool-results: ${e.context.toolResultsDir}`)),e.error&&D(`error: ${e.error}`)}function we(e,t){if(t===`json`){E(JSON.stringify(e,null,2));return}if(e.length===0){E(`No sessions found.`);return}for(let t of e){let e=t.createdAt?new Date(t.createdAt).toLocaleString():`unknown`;E(`${t.id} ${e} [${t.channel}] ${t.title}`)}}function Te(e,t){if(t===`json`){E(JSON.stringify(e,null,2));return}E(`session: ${e.id}`),e.metadata&&(E(`title: ${e.metadata.title}`),E(`channel: ${e.metadata.channel}`),E(`created: ${e.metadata.createdAt}`),E(`updated: ${e.metadata.updatedAt}`)),E(`transcript: ${e.transcriptPath}`),E(`entries: ${e.transcriptEntryCount}`),E(`context: ${e.contextSnapshotPath}`),E(`session-memory: ${e.sessionMemoryPath}`),E(`collapse-log: ${e.collapseLogPath}`),E(`read-states: ${e.readStateCount}`),E(`tool-results: ${e.toolResultRefCount}`),E(`tool-results-dir: ${e.toolResultsDir}`)}function Ee(e,t){if(t===`json`){E(JSON.stringify(e,null,2));return}E(`session: ${e.id}`),E(`transcript: ${e.paths.transcriptPath}`),E(`context: ${e.paths.contextSnapshotPath}`),E(`session-memory: ${e.paths.sessionMemoryPath}`),E(`collapse-log: ${e.paths.collapseLogPath}`),E(`tool-results-dir: ${e.paths.toolResultsDir}`),E(`transcript-entries: ${e.transcript.length}`),E(`read-states: ${e.context.readStates.length}`),E(`tool-results: ${e.context.toolResults.length}`),E(`collapse-spans: ${e.context.compaction.collapseSpans.length}`)}function De(e,t){if(t===`json`){E(JSON.stringify(e,null,2));return}E(`Bootstrap completed.`),E(`dataDir: ${e.dataDir}`),E(`created dirs: ${e.createdDirs.length}`),E(`created files: ${e.createdFiles.length}`),E(`skipped dirs: ${e.skippedDirs.length}`),E(`skipped files: ${e.skippedFiles.length}`)}function Oe(e){e.command(`bootstrap`).description(`Initialize the data directory with required directories and templates`).requiredOption(`-d, --data-dir <path>`,`Data directory path`).option(`--output <format>`,`Output format: text (default) or json`,`text`).action(async e=>{let t=e.output===`json`?`json`:`text`;try{De(await n(e.dataDir),t)}catch(e){D(`Error bootstrapping data directory: ${e.message}`),process.exit(1)}})}function ke(e){return fe.sm4_encrypt_ecb(e)}function Ae(e){return ke(e)}function je(e={}){let t=e.baseUrl??process.env.AIMAX_BASE_URL,n=process.env.AIMAX_AUTH_TOKEN,r=e.authToken?Ae(e.authToken):n?Ae(n):e.apiKey??process.env.AIMAX_API_KEY,i=e.model??process.env.AIMAX_MODEL,a=[];if(t||a.push(`--base-url / AIMAX_BASE_URL`),r||a.push(`--api-key / AIMAX_API_KEY`),i||a.push(`--model / AIMAX_MODEL`),a.length>0)throw Error(`Missing required LLM configuration: ${a.join(`, `)}`);return{baseUrl:t,apiKey:r,model:i,contextWindow:e.contextWindow??(process.env.AIMAX_CONTEXT_WINDOW?Number(process.env.AIMAX_CONTEXT_WINDOW):void 0),flashModel:e.flashModel??process.env.AIMAX_FLASH_MODEL}}function Me(e,t){return t?x.resolve(t):x.join(e,`.aimax`,`plugins.json`)}async function A(e,t){let n=Me(e,t);try{let e=await b.readFile(n,`utf-8`);return JSON.parse(e)}catch(e){if(e.code===`ENOENT`)return;throw e}}async function j(e,t,n){let r=Me(e,n);await b.mkdir(x.dirname(r),{recursive:!0}),await b.writeFile(r,JSON.stringify(t,null,2),`utf-8`)}function M(e){return typeof e==`object`&&!!e}function N(e){return M(e)&&e.type===`text`&&typeof e.text==`string`&&(e.textSignature===void 0||typeof e.textSignature==`string`)}function Ne(e){return M(e)&&e.type===`image`&&typeof e.data==`string`&&typeof e.mimeType==`string`}function Pe(e){return M(e)&&e.type===`thinking`&&typeof e.thinking==`string`&&(e.thinkingSignature===void 0||typeof e.thinkingSignature==`string`)&&(e.redacted===void 0||typeof e.redacted==`boolean`)}function Fe(e){return M(e)&&e.type===`toolCall`&&typeof e.id==`string`&&typeof e.name==`string`&&M(e.arguments)&&(e.thoughtSignature===void 0||typeof e.thoughtSignature==`string`)}function Ie(e){return typeof e==`string`||Array.isArray(e)&&e.every(e=>N(e)||Ne(e))}function Le(e){return Array.isArray(e)&&e.every(e=>N(e)||Pe(e)||Fe(e))}function Re(e){return M(e)&&typeof e.input==`number`&&typeof e.output==`number`&&typeof e.cacheRead==`number`&&typeof e.cacheWrite==`number`&&typeof e.totalTokens==`number`&&M(e.cost)&&typeof e.cost.input==`number`&&typeof e.cost.output==`number`&&typeof e.cost.cacheRead==`number`&&typeof e.cost.cacheWrite==`number`&&typeof e.cost.total==`number`}function ze(e){return!M(e)||typeof e.role!=`string`?!1:e.role===`user`?Ie(e.content):e.role===`assistant`?Le(e.content)&&typeof e.api==`string`&&typeof e.provider==`string`&&typeof e.model==`string`&&Re(e.usage)&&(e.stopReason===`stop`||e.stopReason===`length`||e.stopReason===`toolUse`||e.stopReason===`error`||e.stopReason===`aborted`)&&(e.errorMessage===void 0||typeof e.errorMessage==`string`):e.role===`toolResult`?typeof e.toolCallId==`string`&&typeof e.toolName==`string`&&Array.isArray(e.content)&&e.content.every(e=>N(e)||Ne(e))&&typeof e.isError==`boolean`:!1}async function Be(e){let t;try{t=await b.readFile(e,`utf-8`)}catch(e){throw Error(`Failed to read message file: ${e.message}`)}let n;try{n=JSON.parse(t)}catch(e){throw Error(`Invalid JSON in message file: ${e.message}`)}let r=Array.isArray(n)?n:[n];if(r.length===0||!r.every(e=>ze(e)))throw Error(`Message file must contain one Message object or an array of Message objects`);return r}async function Ve(e){if(!!e.message==!!e.fromFile)throw Error(`Exactly one of --message or --from-file must be provided`);return e.fromFile?{kind:`messages`,messages:await Be(e.fromFile)}:{kind:`text`,message:e.message}}let P=function(e){return e.INFO=`INFO`,e.ERROR=`ERROR`,e.WARN=`WARN`,e}({}),F=null;function He(){let e=new Date;return`${e.getFullYear()}-${String(e.getMonth()+1).padStart(2,`0`)}-${String(e.getDate()).padStart(2,`0`)} ${String(e.getHours()).padStart(2,`0`)}:${String(e.getMinutes()).padStart(2,`0`)}:${String(e.getSeconds()).padStart(2,`0`)}.${String(e.getMilliseconds()).padStart(3,`0`)}`}function Ue(e){if(!e)return``;let t=Object.entries(e).filter(([,e])=>e!==void 0).map(([e,t])=>`${e}=${JSON.stringify(t)}`);return t.length>0?` ${t.join(` `)}`:``}function We(e){return x.join(e,`.aimax`)}function Ge(e){return{appLogPath:x.join(e,`app.log`),errorLogPath:x.join(e,`errors.log`)}}function Ke(e){let{appLogPath:t,errorLogPath:n}=Ge(e);S.configure({appenders:{appFile:{type:`file`,filename:t,maxLogSize:5*1024*1024,backups:3,compress:!0,keepFileExt:!0,layout:{type:`pattern`,pattern:`[%d{yyyy-MM-dd hh:mm:ss.SSS}] [%p] %m`}},errorFile:{type:`file`,filename:n,maxLogSize:5*1024*1024,backups:3,compress:!0,keepFileExt:!0,layout:{type:`pattern`,pattern:`[%d{yyyy-MM-dd hh:mm:ss.SSS}] [%p] %m`}},errorsOnly:{type:`logLevelFilter`,appender:`errorFile`,level:`error`,maxLevel:`fatal`}},categories:{default:{appenders:[`appFile`,`errorsOnly`],level:`info`}}})}function qe(e,t,n){process.stderr.write(`[${He()}] [${e}] ${t}${Ue(n)}\n`)}function I(e,t,n){let r=`${t}${Ue(n)}`;if(!F){qe(e,r);return}let i=S.getLogger();if(e===P.ERROR){i.error(r);return}if(e===P.WARN){i.warn(r);return}i.info(r)}function L(e){let t=We(e);F?.dataDir!==e&&(pe.mkdirSync(t,{recursive:!0}),Ke(t),F={dataDir:e,logDir:t})}async function Je(){await S.shutdown()}const R={info:(e,t)=>I(P.INFO,e,t),warn:(e,t)=>I(P.WARN,e,t),error:(e,t)=>I(P.ERROR,e,t)};var z=class{startTime;name;constructor(e){this.name=e,this.startTime=Date.now()}end(){let e=Date.now()-this.startTime;return R.info(`${this.name} completed in ${e}ms`),e}},B=class{constructor(e){this.sinks=e}async send(e){await Promise.allSettled(this.sinks.map(async t=>{await t.send(e)}))}async close(){await Promise.allSettled(this.sinks.map(async e=>{await e.close()}))}},V=class{constructor(e){this.url=e}async send(e){await this.post(this.toPayload(e))}async close(){}async post(e){let t=Date.now(),n=Ye(e);R.info(`sending callback event`,{callbackUrl:this.url,...n});let r=await fetch(this.url,{method:`POST`,headers:{"content-type":`application/json`},body:JSON.stringify(e)}),i=Date.now()-t;if(!r.ok)throw R.error(`callback event failed`,{callbackUrl:this.url,httpStatus:r.status,durationMs:i,...n}),Error(`Callback failed with status ${r.status}`);R.info(`callback event delivered`,{callbackUrl:this.url,httpStatus:r.status,durationMs:i,...n})}toPayload(e){switch(e.type){case`start`:return e;case`progress`:return e;case`done`:return e;case`error`:return e;case`session_reset`:return e;case`hitl`:return e;case`title_updated`:return e;default:{let t=e;throw Error(`Unsupported callback event: ${JSON.stringify(t)}`)}}}};function Ye(e){return{eventType:e.type,sessionId:e.sessionId,messageId:e.messageId,channel:e.channel,user:e.user,progressType:e.type===`progress`?e.event.type:void 0}}function Xe(e,t){if(t.kind===`none`)return e;let n=new URL(e);return n.searchParams.set(`authToken`,t.token),n.toString()}function H(){let e=globalThis.WebSocket;if(!e)throw Error(`WebSocket is not available in this runtime`);return e}function Ze(e){return e?{kind:`query_token`,token:e}:{kind:`none`}}function U(e,t,n){if(typeof e.once==`function`){e.once(t,n);return}if(typeof e.addEventListener==`function`&&typeof e.removeEventListener==`function`){let r=(...i)=>{e.removeEventListener?.(t,r),n(...i)};e.addEventListener(t,r);return}throw Error(`WebSocket does not support one-time listener registration for "${t}"`)}function Qe(e,t,n){if(typeof e.on==`function`){e.on(t,n);return}if(typeof e.addEventListener==`function`){e.addEventListener(t,n);return}throw Error(`WebSocket does not support listener registration for "${t}"`)}var W=class{socket=null;connectPromise=null;enabled=!0;textSequence=0;constructor(e,t,n){this.url=e,this.events=t,this.authToken=n}async send(e){let t=this.toEnvelope(e);if(!(!t||!this.enabled))try{await this.ensureConnected();let e=H();if(!this.socket||this.socket.readyState!==e.OPEN)return;this.socket.send(JSON.stringify(t))}catch(e){R.warn(`websocket sink disabled after send failure`,{url:this.url,error:e instanceof Error?e.message:String(e)}),this.enabled=!1}}async sendTextDelta(e){if(!this.enabled||!this.events.has(`text`))return;this.textSequence+=1;let t={type:`text`,sessionId:e.sessionId,messageId:e.messageId,channel:e.channel,user:e.user,timestamp:new Date().toISOString(),sequence:this.textSequence,delta:e.text};try{await this.ensureConnected();let e=H();if(!this.socket||this.socket.readyState!==e.OPEN)return;this.socket.send(JSON.stringify(t))}catch(e){R.warn(`websocket sink disabled after text delta send failure`,{url:this.url,error:e instanceof Error?e.message:String(e)}),this.enabled=!1}}async close(){this.enabled=!1;let e=this.socket;if(this.socket=null,this.connectPromise=null,!e)return;let t=H();e.readyState!==t.CLOSED&&await new Promise(t=>{U(e,`close`,()=>t()),e.close()})}async ensureConnected(){if(!this.enabled)return;let e=H();if(this.socket&&this.socket.readyState===e.OPEN)return;if(this.connectPromise){await this.connectPromise;return}let t=new e(Xe(this.url,Ze(this.authToken)));this.connectPromise=new Promise((e,n)=>{U(t,`open`,()=>{this.socket=t,Qe(t,`close`,()=>{this.socket===t&&(this.socket=null)}),e()}),U(t,`error`,e=>{n(e)})});try{await this.connectPromise}finally{this.connectPromise=null}}toEnvelope(e){let t=new Date().toISOString();switch(e.type){case`start`:return this.events.has(`start`)?{...e,timestamp:t}:null;case`done`:return this.events.has(`done`)?{...e,timestamp:t}:null;case`error`:return this.events.has(`error`)?{...e,timestamp:t}:null;case`hitl`:return this.events.has(`hitl`)?{...e,timestamp:t}:null;case`title_updated`:return this.events.has(`title_updated`)?{type:`title_updated`,sessionId:e.sessionId,messageId:e.messageId,channel:e.channel,user:e.user,timestamp:t,title:e.title}:null;case`session_reset`:return null;case`progress`:return e.event.type===`text`?this.events.has(`text`)?(this.textSequence+=1,{type:`text`,sessionId:e.sessionId,messageId:e.messageId,channel:e.channel,user:e.user,timestamp:t,sequence:this.textSequence,delta:e.event.text}):null:e.event.type===`stream_text_delta`||!this.events.has(`progress`)?null:{type:`progress`,sessionId:e.sessionId,messageId:e.messageId,channel:e.channel,user:e.user,timestamp:t,event:e.event};default:{let t=e;throw Error(`Unsupported stream event: ${JSON.stringify(t)}`)}}}};const $e=[`start`,`text`,`done`,`error`,`hitl`];function et(e){if(!e?.trim())return new Set($e);let t=e.split(`,`).map(e=>e.trim().toLowerCase()).filter(Boolean),n=new Set([`start`,`text`,`progress`,`done`,`error`,`hitl`,`title_updated`]),r=new Set;for(let e of t){if(!n.has(e))throw Error(`Invalid stream event: ${e}. Must be one of start,text,progress,done,error,hitl`);r.add(e)}return r.size>0?r:new Set($e)}function tt(e){let t=e.dataDir??process.env.AIMAX_DATA_DIR;if(!t)throw Error(`Data directory must be specified via --data-dir or AIMAX_DATA_DIR`);return t}function nt(e){return e?_(e):void 0}function rt(e,t){if(e.inputText&&t){let n=de(e.inputText,t);return n.submittedBy={userId:e.user,channel:e.channel??`IM`},n}if(!e.inputJson&&!e.inputText)throw Error(`Either --input-json or --input-text must be provided for the resume command`);try{let t=JSON.parse(e.inputJson);return{requestId:e.requestId,sessionId:e.sessionId,action:t.action??`submit`,values:t.values,submittedBy:t.submittedBy,idempotencyKey:t.idempotencyKey,submittedAt:t.submittedAt??new Date().toISOString()}}catch(e){throw Error(`Invalid --input-json: ${e.message}`)}}function it(e,t){if(!e.inputJson)throw Error(`UI tool resume requires --input-json`);try{let n=JSON.parse(e.inputJson),r=n&&typeof n==`object`&&`values`in n&&n.values&&typeof n.values==`object`&&!Array.isArray(n.values)?n.values:n;return{requestId:t.request.requestId,sessionId:t.sessionId,toolCallId:t.request.toolCallId,toolName:t.request.toolName,values:r,submittedAt:new Date().toISOString()}}catch(e){throw Error(`Invalid --input-json: ${e.message}`)}}async function at(e){let t=await ne(e.dataDir,e.sessionId,{storeName:e.sessionStoreName});for(let n=t.length-1;n>=0;--n){let r=t[n];if(r?.role!==`assistant`||!Array.isArray(r.toolCalls))continue;let i=r.toolCalls.find(t=>t.id===e.toolCallId&&t.name===e.toolName);if(i)return i.arguments}}async function ot(e){let t=tt(e),n=e.channel??`WEB`,r=je({baseUrl:e.baseUrl,apiKey:e.apiKey,authToken:e.authToken,model:e.model,contextWindow:e.contextWindow?Number(e.contextWindow):void 0,flashModel:e.flashModel});return{dataDir:t,channel:n,format:e.output===`json`?`json`:`text`,timeoutMs:e.timeout?Number(e.timeout):void 0,llm:r}}function st(e){let t=[],n=null;return e.callbackUrl&&t.push(new V(e.callbackUrl)),e.streamUrl&&(n=new W(e.streamUrl,et(e.streamEvents),e.streamAuthToken),t.push(n)),{sink:new B(t),websocketSink:n}}async function ct(e){let{dataDir:t,sessionId:n,sessionStoreName:r,toolCallId:i,toolName:a,resolution:o}=e;if(!i||!a||!le(a))return;let s=(e,t)=>{switch(e){case`request_approval`:return c(t);case`clarify`:return l(t);case`request_review`:return u(t);default:return JSON.stringify({action:t.action,values:t.values})}};await se(t,n,e=>{let t=e.findIndex(e=>e.role===`tool_result`&&e.toolCallId===i&&e.toolName===a);if(t===-1)return e;let n=e.slice(0,t+1);return n[t]={...n[t],content:s(a,o),isError:!1},n},{storeName:r})}async function lt(e){let{dataDir:t,sessionId:n,sessionStoreName:r,result:i}=e;await se(t,n,e=>{let t=e.findIndex(e=>e.role===`assistant`&&Array.isArray(e.toolCalls)&&e.toolCalls.some(e=>e.id===i.toolCallId&&e.name===i.toolName));if(t===-1)return e;let n=e.slice(0,t+1);return n.push({role:`tool_result`,toolCallId:i.toolCallId,toolName:i.toolName,content:JSON.stringify({submitted:!0,values:i.values}),isError:!1,timestamp:i.submittedAt}),n},{storeName:r})}async function G(e){L(tt(e));let t=new z(`resume command`),n=null;try{let r=await ot(e),a=nt(e.sessionStore);R.info(`resume command started`,{sessionId:e.sessionId,requestId:e.requestId,channel:r.channel,dataDir:r.dataDir});let o=await g(r.dataDir,e.sessionId,{storeName:a}),s=o?null:await ee(r.dataDir,e.sessionId,{storeName:a});if(!o&&!s)throw Error(`No pending HITL or UI tool request found for session "${e.sessionId}"`);if(o){if(o.request.requestId!==e.requestId)throw Error(`Request ID mismatch: pending is "${o.request.requestId}", got "${e.requestId}"`);if(o.status===`expired`)throw Error(`HITL request has expired`);if(o.status===`cancelled`)throw Error(`HITL request has been cancelled`)}else if(s){if(s.request.requestId!==e.requestId)throw Error(`Request ID mismatch: pending is "${s.request.requestId}", got "${e.requestId}"`);if(s.status!==`pending`)throw Error(`UI tool request is already "${s.status}", cannot resume`)}if(o){let i=rt(e,o.request),s=await ae({dataDir:r.dataDir,sessionStoreName:a,sessionId:e.sessionId,requestId:e.requestId,resolution:i}),c=s.state;if(!c)throw Error(`Resolved HITL state was not persisted`);let l=ut(i,c.request.kind);await ct({dataDir:r.dataDir,sessionId:e.sessionId,sessionStoreName:a,toolCallId:c.toolContext?.toolCallId,toolName:c.toolContext?.toolName,resolution:i});let u=st(e);n=u.sink;let d=e.sessionId,f=async t=>{if(d=t.sessionId??d,!y(t)){if(t.type===`stream_text_delta`){r.format===`text`&&O(t),await u.websocketSink?.sendTextDelta({sessionId:d,channel:r.channel,messageId:e.messageId,user:e.user,text:t.text});return}r.format===`text`&&O(t),await n?.send({sessionId:d,channel:r.channel,messageId:e.messageId,user:e.user,type:`progress`,event:t})}};await f({type:`hitl_resumed`,requestId:e.requestId,resolution:i,sessionId:e.sessionId}),`idempotentReplay`in s&&s.idempotentReplay&&(R.info(`resume command treated as idempotent replay`,{sessionId:e.sessionId,requestId:e.requestId,idempotencyKey:i.idempotencyKey}),k({sessionId:e.sessionId,text:`Resume request already processed.`,usage:{input:0,output:0,total:0},durationMs:0},r.format),t.end(),process.exit(0));let p=e.pluginsConfig??process.env.AIMAX_PLUGINS_CONFIG,m=await A(r.dataDir,p),h;try{h=await v({dataDir:r.dataDir,sessionStoreName:a,sessionId:e.sessionId,messageId:e.messageId,channel:r.channel,llm:r.llm,timeoutMs:r.timeoutMs,message:l,hitlResume:{request:c.request,resolution:i,checkpoint:c.checkpoint,toolContext:c.toolContext},plugins:m?{config:m,dataDir:r.dataDir,workspaceDir:x.join(r.dataDir,`workspace`),bundledDir:process.env.AIMAX_PLUGINS_BUNDLED_DIR,llmAllowlist:m.llmAllowlist}:void 0,onProgress:f})}finally{}h.error?await n?.send({sessionId:h.sessionId,channel:r.channel,messageId:e.messageId,user:e.user,type:`error`,message:h.error}):await n?.send({sessionId:h.sessionId,channel:r.channel,messageId:e.messageId,user:e.user,type:`done`,result:{text:h.text,usage:h.usage,durationMs:h.durationMs,error:h.error,paused:h.paused,uiToolPending:h.uiToolPending}}),k(h,r.format),h.error?R.error(`resume command failed: ${h.error}`):R.info(`resume command succeeded`),t.end(),process.exit(h.error?1:0);return}let c=it(e,s);if(!await oe(r.dataDir,e.sessionId,e.requestId,c,{storeName:a}))throw Error(`UI tool resume validation failed`);await lt({dataDir:r.dataDir,sessionId:e.sessionId,sessionStoreName:a,result:c});let l=st(e);n=l.sink;let u=e.sessionId,d=async t=>{if(u=t.sessionId??u,!y(t)){if(t.type===`stream_text_delta`){r.format===`text`&&O(t),await l.websocketSink?.sendTextDelta({sessionId:u,channel:r.channel,messageId:e.messageId,user:e.user,text:t.text});return}if(r.format===`text`&&O(t),t.type===`start`){await n?.send({sessionId:u,channel:r.channel,messageId:e.messageId,user:e.user,type:`start`,message:t.message});return}await n?.send({sessionId:u,channel:r.channel,messageId:e.messageId,user:e.user,type:`progress`,event:t})}},f=await at({dataDir:r.dataDir,sessionId:e.sessionId,sessionStoreName:a,toolCallId:c.toolCallId,toolName:c.toolName});await d({type:`tool_end`,sessionId:e.sessionId,toolCallId:c.toolCallId,name:c.toolName,input:f,output:JSON.stringify({submitted:!0,values:c.values}),isError:!1});let p=e.pluginsConfig??process.env.AIMAX_PLUGINS_CONFIG,m=await A(r.dataDir,p),h=await v({dataDir:r.dataDir,sessionStoreName:a,sessionId:e.sessionId,messageId:e.messageId,channel:r.channel,llm:r.llm,timeoutMs:r.timeoutMs,message:`[UI_TOOL_RESUME]
5
- The pending UI tool result has been written into the transcript. Continue from the latest tool result without repeating the same form request.`,uiToolResume:c,plugins:m?{config:m,dataDir:r.dataDir,workspaceDir:x.join(r.dataDir,`workspace`),bundledDir:process.env.AIMAX_PLUGINS_BUNDLED_DIR,llmAllowlist:m.llmAllowlist}:void 0,onProgress:d});await i(r.dataDir,e.sessionId,{storeName:a}),h.error?await n?.send({sessionId:h.sessionId,channel:r.channel,messageId:e.messageId,user:e.user,type:`error`,message:h.error}):await n?.send({sessionId:h.sessionId,channel:r.channel,messageId:e.messageId,user:e.user,type:`done`,result:{text:h.text,usage:h.usage,durationMs:h.durationMs,error:h.error,paused:h.paused,uiToolPending:h.uiToolPending}}),k(h,r.format),h.error?R.error(`resume command failed: ${h.error}`):R.info(`resume command succeeded`),t.end(),process.exit(h.error?1:0)}catch(r){let i=r;n&&(i.message.includes(`expired`)&&await n.send({sessionId:e.sessionId,channel:e.channel??`WEB`,messageId:e.messageId,user:e.user,type:`progress`,event:{type:`hitl_expired`,sessionId:e.sessionId,requestId:e.requestId,reason:i.message}}),i.message.includes(`cancelled`)&&await n.send({sessionId:e.sessionId,channel:e.channel??`WEB`,messageId:e.messageId,user:e.user,type:`progress`,event:{type:`hitl_cancelled`,sessionId:e.sessionId,requestId:e.requestId,reason:i.message}}),await n.send({sessionId:e.sessionId,channel:e.channel??`WEB`,messageId:e.messageId,user:e.user,type:`error`,message:`Resume failed: ${i.message}`})),R.error(`resume command error: ${i.message}`),D(`Fatal: ${i.message}`),t.end(),process.exit(1)}finally{await n?.close()}}function ut(e,t){return r(e,t)}function dt(e){e.command(`resume`).description(`Resume a paused HITL session with user input`).requiredOption(`-d, --data-dir <path>`,`Data directory path (overrides AIMAX_DATA_DIR)`).requiredOption(`-s, --session-id <id>`,`Session ID to resume`).option(`--session-store <name>`,`Session store directory under .aimax (default: sessions)`).requiredOption(`--request-id <id>`,`HITL request ID to resolve`).option(`--input-json <json>`,`JSON string with the resolution (action, values, etc.)`).option(`--input-text <text>`,`Plain text response for IM channels without rich UI (e.g. '同意', '拒绝')`).option(`--message-id <id>`,`Message ID for correlating events`).option(`--user <id>`,`User identifier propagated to external callback and stream payloads`).option(`-c, --channel <channel>`,`Channel name (default: WEB)`,`WEB`).option(`--base-url <url>`,`LLM API base URL (overrides AIMAX_BASE_URL)`).option(`--api-key <key>`,`LLM API key (overrides AIMAX_API_KEY)`).option(`--auth-token <token>`,`Auth token used to generate the API key`).option(`--model <name>`,`LLM model name (overrides AIMAX_MODEL)`).option(`--context-window <n>`,`LLM context window size`).option(`--callback-url <url>`,`HTTP callback URL for progress events`).option(`--stream-url <url>`,`WebSocket URL for streaming text events`).option(`--stream-auth-token <token>`,`Auth token for WebSocket streaming`).option(`--stream-events <list>`,`Comma-separated stream events`).option(`--timeout <ms>`,`Execution timeout in milliseconds`).option(`--output <format>`,`Output format: text (default) or json`,`text`).option(`--plugins-config <path>`,`Plugins config file path`).action(async e=>{await G(e)})}const ft=[`start`,`text`,`done`,`error`];function pt(e){if(!e?.trim())return new Set(ft);let t=e.split(`,`).map(e=>e.trim().toLowerCase()).filter(Boolean),n=new Set([`start`,`text`,`progress`,`done`,`error`,`hitl`,`title_updated`]),r=new Set;for(let e of t){if(!n.has(e))throw Error(`Invalid stream event: ${e}. Must be one of start,text,progress,done,error,hitl,title_updated`);r.add(e)}return r.size>0?r:new Set(ft)}function K(e){let t=e.dataDir??process.env.AIMAX_DATA_DIR;if(!t)throw Error(`Data directory must be specified via --data-dir option or AIMAX_DATA_DIR environment variable`);return t}function mt(e){return e??`WEB`}function q(e){return e?_(e):void 0}function ht(e,t){return e.length<=t?e:t<=3?e.slice(0,t):`${e.slice(0,t-3)}...`}function gt(e,t,n=78){let r=n-2,i=r-2,a=e?` ${ht(e,Math.max(0,i-2))} `:``,o=e?`┌${a}${`─`.repeat(Math.max(0,r-a.length))}┐`:`┌${`─`.repeat(r)}┐`,s=`└${`─`.repeat(r)}┘`;return[o,...t.map(e=>`│ ${ht(e,i).padEnd(i,` `)} │`),s].join(`
6
- `)}function _t(e){return e.kind===`text`?`inline message (${e.message.length} chars)`:`message file (${e.messages.length} messages)`}function vt(e,t){let n=q(e.sessionStore)??`sessions`,r=t.timeoutMs===void 0?`default`:`${t.timeoutMs}`,i=e.callbackUrl?`enabled`:`disabled`,a=e.streamUrl?`enabled`:`disabled`,o=_t(t.input),s=t.input.kind===`text`?`inline`:e.fromFile??`file`,c=new Date().toISOString();return{banner:gt(void 0,[`AIMax CLI`,`Stateless Agent Runner`]),contextBox:gt(`Run Context`,[`time : ${c}`,`channel : ${t.channel}`,`user : ${e.user??`-`}`,`sessionId : ${e.sessionId??`new`}`,`sessionStore : ${n}`,`messageId : ${e.messageId??`-`}`,`dataDir : ${t.dataDir}`,`workspace : ${x.join(t.dataDir,`workspace`)}`,`output : ${t.format}`,`callback : ${i}`,`websocket : ${a}`,`timeoutMs : ${r}`,`input : ${o}`]),logContext:{time:c,channel:t.channel,user:e.user,dataDir:t.dataDir,workspaceDir:x.join(t.dataDir,`workspace`),sessionId:e.sessionId??`new`,sessionStore:n,messageId:e.messageId,output:t.format,hasCallback:!!e.callbackUrl,hasStream:!!e.streamUrl,timeoutMs:t.timeoutMs,inputKind:t.input.kind,inputSource:s,inputSummary:o}}}async function yt(e,t){let n=K(e),r=mt(e.channel),i=je({baseUrl:e.baseUrl,apiKey:e.apiKey,authToken:e.authToken,model:e.model,contextWindow:e.contextWindow?Number(e.contextWindow):void 0,flashModel:e.flashModel});return{dataDir:n,channel:r,format:e.output===`json`?`json`:`text`,timeoutMs:e.timeout?Number(e.timeout):void 0,llm:i,input:t}}function bt(e){if(e.kind===`text`)return e.message;if(e.messages.length!==1)return null;let[t]=e.messages;if(t.role!==`user`)return null;if(typeof t.content==`string`)return t.content;if(t.content.length===0)return null;let n=[];for(let e of t.content){if(e.type!==`text`)return null;n.push(e.text)}return n.join(`
7
- `)}async function xt(e,t){if(!e.sessionId)return null;let n=bt(t);if(!n)return null;let r=await g(K(e),e.sessionId,{storeName:q(e.sessionStore)});return!r||r.status!==`pending`||!ue(n,r.request)?null:{requestId:r.request.requestId,inputText:n}}function St(e){let t=[],n=null;return e.callbackUrl&&t.push(new V(e.callbackUrl)),e.streamUrl&&(n=new W(e.streamUrl,pt(e.streamEvents),e.streamAuthToken),t.push(n)),{sink:new B(t),websocketSink:n}}async function J(e,t){R.info(`dispatching external event`,Bt(t)),await e.sink.send(t)}function Ct(e){if(!e)return{};let t={};for(let[n,r]of Object.entries(e)){if(r===null||typeof r==`string`||typeof r==`number`||typeof r==`boolean`){t[n]=r;continue}if(r instanceof Error){t[n]=`${r.name}: ${r.message}`;continue}t[n]=JSON.stringify(r)}return t}function wt(e){let t={sessionId:e.sessionId,messageId:e.messageId,parentSessionId:e.parentSessionId,depth:e.depth,scope:e.scope,phase:e.phase,...Ct(e.details)};if(e.level===`error`){R.error(e.message,t);return}if(e.level===`warn`){R.warn(e.message,t);return}R.info(e.message,t)}function Tt(e,t,n,r,i){return{sink:e,websocketSink:t,channel:n,defaultMessageId:r,user:i}}function Et(){let e=new AbortController,t=()=>e.abort();return process.once(`SIGTERM`,t),process.once(`SIGINT`,t),{controller:e,cleanup:()=>{process.off(`SIGTERM`,t),process.off(`SIGINT`,t)}}}function Dt(e){return{activeSessionId:e??`pending`,finalResult:null}}function Ot(e,t){e.activeSessionId=t.sessionId??e.activeSessionId}function kt(e,t){return e.messageId??t}async function At(e,t,n){if(!await d(e.dataDir)){if(await Y(t,e.format,n.activeSessionId,e.dataDir,`checking`),(await o(e.dataDir)).performedBootstrap){await Y(t,e.format,n.activeSessionId,e.dataDir,`initializing`),await Y(t,e.format,n.activeSessionId,e.dataDir,`initialized`);return}await Y(t,e.format,n.activeSessionId,e.dataDir,`ready`)}}async function Y(e,t,n,r,i){let a={type:`bootstrap`,phase:i,dataDir:r};t===`text`&&O(a),await J(e,{sessionId:n,channel:e.channel,messageId:e.defaultMessageId,user:e.user,type:`progress`,event:a})}function jt(e,t,n){return async r=>{if(Ot(n,r),y(r)){wt(r);return}if(r.type===`stream_text_delta`){e.format===`text`&&O(r),await t.websocketSink?.sendTextDelta({sessionId:n.activeSessionId,channel:e.channel,messageId:kt(r,t.defaultMessageId),user:t.user,text:r.text});return}e.format===`text`&&O(r);let i=kt(r,t.defaultMessageId);if(r.type===`hitl_requested`){await J(t,{sessionId:n.activeSessionId,channel:e.channel,messageId:i,user:t.user,type:`hitl`,request:r.request}),await J(t,{sessionId:n.activeSessionId,channel:e.channel,messageId:i,user:t.user,type:`progress`,event:r});return}if(r.type===`start`){await J(t,{sessionId:n.activeSessionId,channel:e.channel,messageId:i,user:t.user,type:`start`,message:r.message});return}if(r.type===`session_reset`){await J(t,{sessionId:n.activeSessionId,channel:e.channel,messageId:i,user:t.user,type:`session_reset`,action:r.action,previousSessionId:r.previousSessionId,message:r.message});return}await J(t,{sessionId:n.activeSessionId,channel:e.channel,messageId:i,user:t.user,type:`progress`,event:r})}}function Mt(e,t,n,r,i){let a={dataDir:t.dataDir,sessionStoreName:q(e.sessionStore),sessionId:e.sessionId,messageId:e.messageId,channel:t.channel,llm:t.llm,timeoutMs:t.timeoutMs,abortSignal:n.signal,plugins:i?{config:i,dataDir:t.dataDir,workspaceDir:x.join(t.dataDir,`workspace`),bundledDir:process.env.AIMAX_PLUGINS_BUNDLED_DIR,llmAllowlist:i.llmAllowlist}:void 0,onProgress:r};return t.input.kind===`messages`?{...a,messages:t.input.messages}:{...a,message:t.input.message}}async function Nt(e,t,n,r){if(t.activeSessionId=r.sessionId,t.finalResult=r,r.error){await J(e,{sessionId:r.sessionId,channel:e.channel,messageId:n,user:e.user,type:`error`,message:r.error});return}await J(e,{sessionId:r.sessionId,channel:e.channel,messageId:n,user:e.user,type:`done`,result:{text:r.text,usage:r.usage,durationMs:r.durationMs,error:r.error,paused:r.paused}})}async function Pt(e,t,n,r){await J(e,{sessionId:t.finalResult?.sessionId??t.activeSessionId,channel:e.channel,messageId:n,user:e.user,type:`error`,message:`Fatal: ${r.message}`})}function Ft(e,t){let n=vt(e,t);R.info([`run command started`,n.banner,n.contextBox].join(`
8
- `),n.logContext),t.format===`text`&&(E(n.banner),E(``),E(n.contextBox),E(``))}function It(e,t,n){k(t,n),t.error?R.error(`run command failed: ${t.error}`):R.info(`run command succeeded`),e.end(),process.exit(t.error?1:0)}function Lt(e,t){R.error(`run command error: ${t.message}`),D(`Fatal: ${t.message}`),e.end(),process.exit(1)}async function Rt(e){if(e.resumeInputJson&&e.resumeFromFile)throw Error(`--resume-input-json and --resume-from-file are mutually exclusive`);if(!e.resumeFromFile)return e.resumeInputJson;try{return await b.readFile(e.resumeFromFile,`utf-8`)}catch(e){throw Error(`Failed to read resume input file: ${e.message}`)}}async function zt(e){let t=await Rt(e);if(e.resumeRequestId||t||e.resumeFromFile){if(!e.sessionId||!e.resumeRequestId||!t)throw Error(`--session-id, --resume-request-id, and exactly one of --resume-input-json or --resume-from-file must be provided together`);await G({dataDir:e.dataDir,sessionId:e.sessionId,sessionStore:e.sessionStore,requestId:e.resumeRequestId,inputJson:t,channel:e.channel,baseUrl:e.baseUrl,apiKey:e.apiKey,authToken:e.authToken,model:e.model,contextWindow:e.contextWindow,flashModel:e.flashModel,callbackUrl:e.callbackUrl,streamUrl:e.streamUrl,streamAuthToken:e.streamAuthToken,streamEvents:e.streamEvents,timeout:e.timeout,output:e.output,pluginsConfig:e.pluginsConfig,messageId:e.messageId,user:e.user});return}let n;try{n=await Ve({message:e.message,fromFile:e.fromFile})}catch(t){L(K(e)),Lt(new z(`run command`),t);return}let r=await xt(e,n);if(r){await G({dataDir:e.dataDir,sessionId:e.sessionId,sessionStore:e.sessionStore,requestId:r.requestId,inputText:r.inputText,channel:e.channel,baseUrl:e.baseUrl,apiKey:e.apiKey,authToken:e.authToken,model:e.model,contextWindow:e.contextWindow,flashModel:e.flashModel,callbackUrl:e.callbackUrl,streamUrl:e.streamUrl,streamAuthToken:e.streamAuthToken,streamEvents:e.streamEvents,timeout:e.timeout,output:e.output,pluginsConfig:e.pluginsConfig,messageId:e.messageId,user:e.user});return}L(K(e));let i=new z(`run command`),{controller:a,cleanup:o}=Et(),s=null,c=e.channel??`WEB`,l=Dt(e.sessionId);try{let t=await yt(e,n);c=t.channel,Ft(e,t);let r=St(e);s=r.sink,R.info(`external sink configured`,{callbackUrl:e.callbackUrl,streamUrl:e.streamUrl,streamEvents:e.streamEvents});let o=Tt(s,r.websocketSink,t.channel,e.messageId,e.user);await At(t,o,l);let u=e.pluginsConfig??process.env.AIMAX_PLUGINS_CONFIG,d=await A(t.dataDir,u),f=await v(Mt(e,t,a,jt(t,o,l),d));await Nt(o,l,e.messageId,f),It(i,f,t.format)}catch(t){let n=t;s&&await Pt(Tt(s,null,c,e.messageId,e.user),l,e.messageId,n),Lt(i,n)}finally{await s?.close(),o()}}function Bt(e){return{eventType:e.type,sessionId:e.sessionId,messageId:e.messageId,channel:e.channel,user:e.user,progressType:e.type===`progress`?e.event.type:void 0,textLength:e.type===`done`?e.result.text.length:void 0,hasError:e.type===`error`?!0:e.type===`done`?!!e.result.error:void 0}}function Vt(e){e.command(`run`).description(`Run an agent task`).option(`-d, --data-dir <path>`,`Data directory path (overrides AIMAX_DATA_DIR)`).option(`--user <id>`,`User identifier propagated to external callback and stream payloads`).option(`--message <text>`,`User message to send to the agent`).option(`--from-file <path>`,`Load structured Message JSON from a file`).option(`-s, --session-id <id>`,`Resume an existing session by ID`).option(`--session-store <name>`,`Session store directory under .aimax (default: sessions)`).option(`--message-id <id>`,`Message ID for correlating events`).option(`-c, --channel <channel>`,`Channel name (default: WEB)`,`WEB`).option(`--base-url <url>`,`LLM API base URL (overrides AIMAX_BASE_URL)`).option(`--api-key <key>`,`LLM API key (overrides AIMAX_API_KEY)`).option(`--auth-token <token>`,`Auth token used to generate the API key (highest priority)`).option(`--model <name>`,`LLM model name (overrides AIMAX_MODEL)`).option(`--context-window <n>`,`LLM context window size`).option(`--flash-model <name>`,`Flash model for lightweight tasks like title generation (overrides AIMAX_FLASH_MODEL)`).option(`--callback-url <url>`,`HTTP callback URL for progress events`).option(`--stream-url <url>`,`WebSocket URL for streaming text events`).option(`--stream-auth-token <token>`,`Auth token for WebSocket streaming`).option(`--stream-events <list>`,`Comma-separated stream events: start,text,progress,done,error`).option(`--timeout <ms>`,`Execution timeout in milliseconds (default: 600000)`).option(`--output <format>`,`Output format: text (default) or json`,`text`).option(`--plugins-config <path>`,`Plugins config file path`).option(`--resume-request-id <id>`,`Resume a pending HITL request from aimax run`).option(`--resume-input-json <json>`,`Structured HITL resume payload used with --resume-request-id`).option(`--resume-from-file <path>`,`Load structured HITL resume payload from a file (alternative to --resume-input-json)`).action(async e=>{await zt(e)})}function Ht(e){e.command(`sessions`).description(`List or inspect sessions for a data directory`).argument(`[action]`,`Action: list (default) | inspect | export`).option(`-d, --data-dir <path>`,`Data directory path`).option(`--session-store <name>`,`Session store directory under .aimax (default: sessions)`).option(`-c, --channel <channel>`,`Filter by channel type: H5 | WEB | KLPA | TASK | CRON | EIP_ASSISTANT`).option(`-s, --session-id <id>`,`Session ID for inspect/export`).option(`--output <format>`,`Output format: text or json`).action(async(e,t,n)=>{let r=n.opts(),i=e??`list`,a=i===`export`?r.output===`text`?`text`:`json`:r.output===`json`?`json`:`text`;r.dataDir||(D(`error: required option '-d, --data-dir <path>' not specified`),process.exit(1)),r.channel&&r.channel!==`H5`&&r.channel!==`WEB`&&r.channel!==`KLPA`&&r.channel!==`TASK`&&r.channel!==`CRON`&&r.channel!==`EIP_ASSISTANT`&&(D(`Invalid channel: ${r.channel}. Must be 'H5', 'WEB', 'KLPA', 'TASK', 'CRON', or 'EIP_ASSISTANT'`),process.exit(1));try{let e=r.sessionStore?_(r.sessionStore):void 0;if(i===`list`){we(await h(r.dataDir,r.channel,{storeName:e}),a);return}if(r.sessionId||(D(`error: required option '-s, --session-id <id>' not specified`),process.exit(1)),i===`inspect`){Te(await p(r.dataDir,r.sessionId,{storeName:e}),a);return}if(i===`export`){Ee(await s(r.dataDir,r.sessionId,{storeName:e}),a);return}D(`Invalid sessions action: ${i}. Must be 'list', 'inspect', or 'export'`),process.exit(1)}catch(e){D(`${i===`inspect`?`Error inspecting session`:i===`export`?`Error exporting session`:`Error listing sessions`}: ${e.message}`),process.exit(1)}})}function Ut(e,t){let n=[];return n.push(`backend: ${e.backend}`),n.push(`provider: ${e.provider}${e.model?` (${e.model})`:``}`),typeof e.files==`number`&&n.push(`files: ${e.files}`),typeof e.chunks==`number`&&n.push(`chunks: ${e.chunks}`),typeof e.dirty==`boolean`&&n.push(`dirty: ${e.dirty}`),e.dbPath&&n.push(`db: ${e.dbPath}`),e.sources?.length&&n.push(`sources: ${e.sources.join(`, `)}`),t&&(e.fts&&(n.push(`fts: enabled=${e.fts.enabled} available=${e.fts.available}`),e.fts.error&&n.push(`fts_error: ${e.fts.error}`)),e.vector&&(n.push(`vector: enabled=${e.vector.enabled} available=${e.vector.available??`unknown`}`),e.vector.dims&&n.push(`vector_dims: ${e.vector.dims}`),e.vector.loadError&&n.push(`vector_error: ${e.vector.loadError}`)),e.cache&&n.push(`cache: enabled=${e.cache.enabled} entries=${e.cache.entries??0}`)),n.join(`
9
- `)}function X(e){let t=x.join(e.dataDir,`.aimax`),n=ie({providerId:e.provider,pluginId:e.providerPlugin,dataDir:e.dataDir,memoryDir:t});return n?n.provider:a({dataDir:e.dataDir,memoryDir:t},{includeSessions:e.includeSessions})}function Wt(e){let t=e.command(`memory`).description(`Manage semantic memory indexing and search`);t.command(`status`).description(`Show memory index status`).requiredOption(`-d, --data-dir <path>`,`Data directory path`).option(`--deep`,`Probe embedding/vector availability`).option(`--index`,`Run a refresh before reporting status`).option(`--include-sessions`,`Include session transcripts in indexing`).option(`--provider <id>`,`Memory provider id`).option(`--provider-plugin <id>`,`Memory provider plugin id`).option(`--verbose`,`Verbose output`).option(`--output <format>`,`Output format: text (default) or json`,`text`).action(async e=>{let t=e.output===`json`?`json`:`text`;try{let n=X({dataDir:e.dataDir,provider:e.provider,providerPlugin:e.providerPlugin,includeSessions:e.includeSessions});e.index&&n.sync&&await n.sync(`cli-status`);let r=n.status();e.deep&&((r.custom??={}).note=`deep probe is only supported by builtin provider`),E(t===`json`?JSON.stringify(r,null,2):Ut(r,e.deep))}catch(e){D(`Error getting memory status: ${e.message}`),process.exit(1)}}),t.command(`index`).description(`Reindex memory files`).requiredOption(`-d, --data-dir <path>`,`Data directory path`).option(`--include-sessions`,`Include session transcripts in indexing`).option(`--provider <id>`,`Memory provider id`).option(`--provider-plugin <id>`,`Memory provider plugin id`).option(`--verbose`,`Verbose output`).action(async e=>{try{let t=X({dataDir:e.dataDir,provider:e.provider,providerPlugin:e.providerPlugin,includeSessions:e.includeSessions});t.sync&&await t.sync(`cli-index`),E(`Memory index refreshed.`)}catch(e){D(`Error indexing memory: ${e.message}`),process.exit(1)}}),t.command(`search [query]`).description(`Search semantic memory`).requiredOption(`-d, --data-dir <path>`,`Data directory path`).option(`--query <text>`,`Search query`).option(`--include-sessions`,`Include session transcripts in search`).option(`--provider <id>`,`Memory provider id`).option(`--provider-plugin <id>`,`Memory provider plugin id`).option(`--output <format>`,`Output format: text (default) or json`,`text`).action(async(e,t)=>{let n=t.output===`json`?`json`:`text`,r=t.query?.trim()||e?.trim();r||(D(`Query is required: provide [query] or --query <text>`),process.exit(1));try{let e=await X({dataDir:t.dataDir,provider:t.provider,providerPlugin:t.providerPlugin,includeSessions:t.includeSessions}).search(r);if(n===`json`){E(JSON.stringify(e,null,2));return}if(e.length===0){E(`No results found for: ${r}`);return}E(e.map(e=>{let t=`${e.path}:${e.startLine}-${e.endLine} (${e.score.toFixed(4)}) ${e.snippet}`;return e.citation?`${t}\n${e.citation}`:t}).join(`
10
- `))}catch(e){D(`Error searching memory: ${e.message}`),process.exit(1)}})}function Gt(e){return`${e.match.accountId?`${e.match.channel}:${e.match.accountId}`:e.match.channel} -> ${e.agentId}`}function Kt(e){return async t=>{let n=await w(t),r=ge(n),i=_e(n);if(T(n),e.json){console.log(JSON.stringify({agents:r,bindings:i},null,2));return}console.log(`Agents:`);for(let e of r){let n=e.default?` (default)`:``,r=e.name&&e.name!==e.id?`${e.id}${n} (${e.name})`:`${e.id}${n}`;if(console.log(` - ${r}`),e.identity?.emoji||e.identity?.name){let t=[e.identity.emoji,e.identity.name].filter(Boolean).join(` `);console.log(` Identity: ${t}`)}let a=xe(t,e.id);if(console.log(` Agent dir: ${a}`),e.model){let t=typeof e.model==`string`?e.model:e.model.primary;console.log(` Model: ${t}`)}let o=i.filter(t=>t.agentId===e.id);if(o.length>0){console.log(` Routing rules:`);for(let e of o)console.log(` - ${Gt(e)}`)}}}}function qt(e,t){return async n=>{C(await w(n),ve(e))&&(console.error(`Agent "${e}" already exists.`),process.exit(1)),await me(n,{id:e,name:t.name,model:t.model,default:t.default})||(console.error(`Agent "${e}" already exists.`),process.exit(1));let r=xe(n,e);console.log(`Agent "${e}" added successfully.`),console.log(` Agent dir: ${r}`)}}function Jt(e){return async t=>{let n=C(await w(t),ve(e));n||(console.error(`Agent "${e}" not found.`),process.exit(1)),n.default===!0&&(console.error(`Cannot delete default agent "${e}".`),process.exit(1)),await ye(t,e)||(console.error(`Failed to delete agent "${e}".`),process.exit(1)),console.log(`Agent "${e}" deleted.`)}}function Yt(e){return async t=>{let n=await w(t),r=e.agent??T(n);C(n,r)||(console.error(`Agent "${r}" not found.`),process.exit(1)),(!e.bind||e.bind.length===0)&&(console.error(`Please specify --bind <channel>[:<account>]`),process.exit(1));for(let n of e.bind){let[e,...i]=n.split(`:`),a=i.join(`:`),o=[`H5`,`WEB`,`KLPA`,`TASK`,`CRON`,`EIP_ASSISTANT`];o.includes(e)||(console.error(`Invalid channel: ${e}`),console.error(`Valid channels: ${o.join(`, `)}`),process.exit(1)),await he(t,{agentId:r,match:{channel:e,accountId:a||void 0}}),console.log(`Binding added: ${n} -> ${r}`)}}}function Xt(e){return async t=>{let n=await w(t),r=e.agent??T(n);if(C(n,r)||(console.error(`Agent "${r}" not found.`),process.exit(1)),e.all){let e=await be(t,r,`*`);console.log(`Removed ${e} binding(s) for agent "${r}".`)}else if(e.bind&&e.bind.length>0){let n=0;for(let i of e.bind){let[e,...a]=i.split(`:`),o=await be(t,r,e,a.join(`:`)||void 0);o>0?(console.log(`Binding removed: ${i} -> ${r}`),n+=o):console.log(`No binding found: ${i} -> ${r}`)}}else console.error(`Please specify --bind <channel>[:<account>] or --all`),process.exit(1)}}function Zt(e){return async t=>{let n=_e(await w(t));if(e.agent&&(n=n.filter(t=>t.agentId===e.agent)),e.json){console.log(JSON.stringify(n,null,2));return}if(n.length===0){console.log(`No bindings configured.`);return}console.log(`Routing bindings:`);for(let e of n)console.log(` ${Gt(e)}`)}}function Qt(e){return async t=>{let n=await w(t),r=e.agent??T(n);C(n,r)||(console.error(`Agent "${r}" not found.`),process.exit(1)),await Se(t,r,{name:e.name,emoji:e.emoji,avatar:e.avatar})||(console.error(`Failed to update identity for agent "${r}".`),process.exit(1)),console.log(`Identity updated for agent "${r}".`)}}function $t(e,t){let n=e.command(`agents`).description(`Manage agents`);n.command(`list`).description(`List all configured agents`).option(`-j, --json`,`Output as JSON`).option(`-b, --bindings`,`Show detailed binding rules`).action(async e=>{let n=t();await Kt(e)(n)}),n.command(`add <id>`).description(`Add a new agent`).option(`-n, --name <name>`,`Display name`).option(`-m, --model <model>`,`Model identifier`).option(`--default`,`Mark as default agent`).action(async(e,n)=>{let r=t();await qt(e,n)(r)}),n.command(`delete <id>`).description(`Delete an agent`).action(async e=>{let n=t();await Jt(e)(n)}),n.command(`bind`).description(`Bind a channel to an agent`).option(`-a, --agent <id>`,`Target agent ID`).option(`-b, --bind <channel...>`,`Channel binding (e.g., WEB, KLPA:ops)`).action(async e=>{let n=t();await Yt(e)(n)}),n.command(`unbind`).description(`Unbind a channel from an agent`).option(`-a, --agent <id>`,`Target agent ID`).option(`-b, --bind <channel...>`,`Channel binding to remove`).option(`--all`,`Remove all bindings for the agent`).action(async e=>{let n=t();await Xt(e)(n)}),n.command(`bindings`).description(`List routing bindings`).option(`-a, --agent <id>`,`Filter by agent ID`).option(`-j, --json`,`Output as JSON`).action(async e=>{let n=t();await Zt(e)(n)}),n.command(`set-identity`).description(`Set agent identity`).option(`-a, --agent <id>`,`Target agent ID`).option(`-n, --name <name>`,`Agent name`).option(`-e, --emoji <emoji>`,`Agent emoji`).option(`--avatar <path>`,`Avatar path`).action(async e=>{let n=t();await Qt(e)(n)})}function Z(e){return x.join(e,`workspace`)}function Q(){let e=process.env.AIMAX_PLUGINS_BUNDLED_DIR;return e&&e.trim()||void 0}function en(e){if(e.length===0){E(`No plugins discovered.`);return}for(let t of e){let e=t.status.padEnd(8,` `);E(`${t.id} ${e} ${t.origin} ${t.source}`)}}function tn(e){E(`id: ${e.id}`),E(`status: ${e.status}`),E(`origin: ${e.origin}`),E(`source: ${e.source}`),E(`enabled: ${e.enabled}`),e.error&&E(`error: ${e.error}`),E(`tools: ${e.toolCount}`),E(`hooks: ${e.hookCount}`),e.skills.length>0&&E(`skills: ${e.skills.join(`, `)}`)}function $(e){return Array.from(new Set((e??[]).map(e=>e.trim()).filter(Boolean)))}function nn(e){if(e.length===0){E(`LLM allowlist is empty.`);return}for(let t of e)E(t)}function rn(e,t){let n=e.command(`plugins`).description(`Manage AIMax plugins`),r=e=>e.option(`--plugins-config <path>`,`Plugins config file path`);r(n.command(`list`)).description(`List discovered plugins`).option(`-d, --data-dir <path>`,`Data directory path`).action(async e=>{let n=e.dataDir??t();en(f({config:await A(n,e.pluginsConfig),dataDir:n,workspaceDir:Z(n),bundledDir:Q()}).registry.plugins)}),r(n.command(`info`)).description(`Show plugin details`).argument(`<id>`,`Plugin id`).option(`-d, --data-dir <path>`,`Data directory path`).action(async(e,n)=>{let r=n.dataDir??t(),i=f({config:await A(r,n.pluginsConfig),dataDir:r,workspaceDir:Z(r),bundledDir:Q()}).registry.plugins.find(t=>t.id===e);i||(D(`Plugin not found: ${e}`),process.exit(1)),tn(i)}),r(n.command(`enable`)).description(`Enable a plugin`).argument(`<id>`,`Plugin id`).option(`-d, --data-dir <path>`,`Data directory path`).action(async(e,n)=>{let r=n.dataDir??t(),i=await A(r,n.pluginsConfig)??{},a=re(i);f({config:i,dataDir:r,workspaceDir:Z(r),bundledDir:Q()}).registry.plugins.some(t=>t.id===e)||(D(`Plugin not found: ${e}`),process.exit(1)),await j(r,{...i,entries:{...i.entries,[e]:{...i.entries?.[e]??{},enabled:!0}}},n.pluginsConfig),E(`Enabled ${e}`),a.allow.length>0&&!a.allow.includes(e)&&E(`Note: plugins.allow is set; add this plugin id to allowlist if needed.`)}),r(n.command(`disable`)).description(`Disable a plugin`).argument(`<id>`,`Plugin id`).option(`-d, --data-dir <path>`,`Data directory path`).action(async(e,n)=>{let r=n.dataDir??t(),i=await A(r,n.pluginsConfig)??{};f({config:i,dataDir:r,workspaceDir:Z(r),bundledDir:Q()}).registry.plugins.some(t=>t.id===e)||(D(`Plugin not found: ${e}`),process.exit(1)),await j(r,{...i,entries:{...i.entries,[e]:{...i.entries?.[e]??{},enabled:!1}}},n.pluginsConfig),E(`Disabled ${e}`)}),r(n.command(`doctor`)).description(`Validate plugin configuration`).option(`-d, --data-dir <path>`,`Data directory path`).action(async e=>{let n=e.dataDir??t(),r=f({config:await A(n,e.pluginsConfig),dataDir:n,workspaceDir:Z(n),bundledDir:Q()});if(r.diagnostics.length===0){E(`No plugin issues detected.`);return}for(let e of r.diagnostics)E(`${e.level===`error`?`ERROR`:`WARN`}${e.pluginId?` ${e.pluginId}`:``}: ${e.message}`);r.diagnostics.some(e=>e.level===`error`)&&process.exit(1)});let i=n.command(`llm-allow`).description(`Manage plugin LLM allowlist`);r(i.command(`list`)).description(`List LLM allowlist entries`).option(`-d, --data-dir <path>`,`Data directory path`).action(async e=>{nn($((await A(e.dataDir??t(),e.pluginsConfig))?.llmAllowlist))}),r(i.command(`add`)).description(`Add entries to the LLM allowlist (plugin id or tool name)`).argument(`<entry...>`,`Plugin id or tool name`).option(`-d, --data-dir <path>`,`Data directory path`).action(async(e,n)=>{let r=n.dataDir??t(),i=await A(r,n.pluginsConfig)??{},a=$([...i.llmAllowlist??[],...e]);await j(r,{...i,llmAllowlist:a},n.pluginsConfig),E(`LLM allowlist updated (${a.length} entries).`)}),r(i.command(`remove`)).description(`Remove entries from the LLM allowlist`).argument(`<entry...>`,`Plugin id or tool name`).option(`-d, --data-dir <path>`,`Data directory path`).action(async(e,n)=>{let r=n.dataDir??t(),i=await A(r,n.pluginsConfig)??{},a=new Set(e.map(e=>e.trim()).filter(Boolean)),o=$(i.llmAllowlist).filter(e=>!a.has(e));await j(r,{...i,llmAllowlist:o},n.pluginsConfig),E(`LLM allowlist updated (${o.length} entries).`)}),r(i.command(`clear`)).description(`Clear the LLM allowlist`).option(`-d, --data-dir <path>`,`Data directory path`).action(async e=>{let n=e.dataDir??t();await j(n,{...await A(n,e.pluginsConfig)??{},llmAllowlist:[]},e.pluginsConfig),E(`LLM allowlist cleared.`)})}function an(e){e.command(`commands`).description(`List available slash commands for a data directory`).requiredOption(`-d, --data-dir <path>`,`Data directory path`).option(`--output <format>`,`Output format: text (default) or json`,`text`).action(async e=>{let t=e.output===`json`?`json`:`text`;try{let n=m(await te(e.dataDir,[]));if(t===`json`){E(JSON.stringify(n,null,2));return}E(`Commands`),E(` builtin: ${n.builtin.map(e=>e.name).join(` | `)}`),n.skillCommands.length>0?E(` skills: ${n.skillCommands.map(e=>e.name).join(` | `)}`):E(` skills: (none)`)}catch(e){D(`Error listing commands: ${e.message}`),process.exit(1)}})}const on=[`progress`,`error`,`hitl`];function sn(e){let t=e.dataDir??process.env.AIMAX_DATA_DIR;if(!t)throw Error(`Data directory must be specified via --data-dir or AIMAX_DATA_DIR`);return t}function cn(e){if(!e?.trim())return new Set(on);let t=e.split(`,`).map(e=>e.trim().toLowerCase()).filter(Boolean),n=new Set([`start`,`text`,`progress`,`done`,`error`,`hitl`,`title_updated`]),r=new Set;for(let e of t){if(!n.has(e))throw Error(`Invalid stream event: ${e}. Must be one of start,text,progress,done,error,hitl`);r.add(e)}return r.size>0?r:new Set(on)}function ln(e){return e?_(e):void 0}function un(e){let t=[];return e.callbackUrl&&t.push(new V(e.callbackUrl)),e.streamUrl&&t.push(new W(e.streamUrl,cn(e.streamEvents),e.streamAuthToken)),new B(t)}async function dn(e){L(sn(e));let t=new z(`cancel command`),n=sn(e),r=e.channel??`WEB`,i=e.output===`json`?`json`:`text`,a=un(e),o=ln(e.sessionStore);try{let s=await g(n,e.sessionId,{storeName:o});if(!s)throw Error(`No pending HITL request found for session "${e.sessionId}"`);let c=e.requestId??s.request.requestId;if(s.request.requestId!==c)throw Error(`Request ID mismatch: pending is "${s.request.requestId}", got "${c}"`);if(!(await ae({dataDir:n,sessionStoreName:o,sessionId:e.sessionId,requestId:c,resolution:{requestId:c,sessionId:e.sessionId,action:`cancel`,submittedAt:new Date().toISOString(),submittedBy:{channel:r}}})).state)throw Error(`Failed to cancel HITL request`);let l={type:`hitl_cancelled`,sessionId:e.sessionId,requestId:c,reason:e.reason??`cancelled by operator`};i===`text`&&O(l),await a.send({type:`progress`,sessionId:e.sessionId,channel:r,messageId:e.messageId,event:l}),t.end(),process.exit(0)}catch(n){let i=n;await a.send({type:`error`,sessionId:e.sessionId,channel:r,messageId:e.messageId,message:i.message}),R.error(`cancel command error: ${i.message}`),D(`Fatal: ${i.message}`),t.end(),process.exit(1)}finally{await a.close()}}function fn(e){e.command(`cancel`).description(`Cancel a pending HITL request`).requiredOption(`-d, --data-dir <path>`,`Data directory path`).requiredOption(`-s, --session-id <id>`,`Session ID containing the pending HITL request`).option(`--session-store <name>`,`Session store directory under .aimax (default: sessions)`).option(`--request-id <id>`,`HITL request ID to cancel`).option(`--reason <text>`,`Human-readable cancel reason`).option(`-c, --channel <channel>`,`Channel type (default: WEB)`,`WEB`).option(`--callback-url <url>`,`HTTP callback URL for progress events`).option(`--stream-url <url>`,`WebSocket URL for streaming text events`).option(`--stream-auth-token <token>`,`Auth token for WebSocket streaming`).option(`--stream-events <list>`,`Comma-separated stream events`).option(`--message-id <id>`,`Message ID for correlating events`).option(`--output <format>`,`Output format: text (default) or json`,`text`).action(async e=>{await dn(e)})}const pn=e(import.meta.url)(`../package.json`);function mn(){return process.env.AIMAX_DATA_DIR||process.cwd()}function hn(){let e=new t;return e.name(`aimax`).description(`AIMax CLI — runs agent tasks in a containerized environment`).version(pn.version),Vt(e),dt(e),fn(e),Ht(e),an(e),Oe(e),Wt(e),$t(e,mn),rn(e,mn),e}export{Je as a,R as i,mn as n,L as r,hn as t};
4
+ `),E(`session: ${e.sessionId}`),E(`duration: ${e.durationMs}ms`),E(`tokens: input=${e.usage.input} output=${e.usage.output} total=${e.usage.total}`),e.context&&(E(`context: ${e.context.snapshotPath}`),E(`tool-results: ${e.context.toolResultsDir}`)),e.error&&D(`error: ${e.error}`)}function we(e,t){if(t===`json`){E(JSON.stringify(e,null,2));return}if(e.length===0){E(`No sessions found.`);return}for(let t of e){let e=t.createdAt?new Date(t.createdAt).toLocaleString():`unknown`;E(`${t.id} ${e} [${t.channel}] ${t.title}`)}}function Te(e,t){if(t===`json`){E(JSON.stringify(e,null,2));return}E(`session: ${e.id}`),e.metadata&&(E(`title: ${e.metadata.title}`),E(`channel: ${e.metadata.channel}`),E(`created: ${e.metadata.createdAt}`),E(`updated: ${e.metadata.updatedAt}`)),E(`transcript: ${e.transcriptPath}`),E(`entries: ${e.transcriptEntryCount}`),E(`context: ${e.contextSnapshotPath}`),E(`session-memory: ${e.sessionMemoryPath}`),E(`collapse-log: ${e.collapseLogPath}`),E(`read-states: ${e.readStateCount}`),E(`tool-results: ${e.toolResultRefCount}`),E(`tool-results-dir: ${e.toolResultsDir}`)}function Ee(e,t){if(t===`json`){E(JSON.stringify(e,null,2));return}E(`session: ${e.id}`),E(`transcript: ${e.paths.transcriptPath}`),E(`context: ${e.paths.contextSnapshotPath}`),E(`session-memory: ${e.paths.sessionMemoryPath}`),E(`collapse-log: ${e.paths.collapseLogPath}`),E(`tool-results-dir: ${e.paths.toolResultsDir}`),E(`transcript-entries: ${e.transcript.length}`),E(`read-states: ${e.context.readStates.length}`),E(`tool-results: ${e.context.toolResults.length}`),E(`collapse-spans: ${e.context.compaction.collapseSpans.length}`)}function De(e,t){if(t===`json`){E(JSON.stringify(e,null,2));return}E(`Bootstrap completed.`),E(`dataDir: ${e.dataDir}`),E(`created dirs: ${e.createdDirs.length}`),E(`created files: ${e.createdFiles.length}`),E(`skipped dirs: ${e.skippedDirs.length}`),E(`skipped files: ${e.skippedFiles.length}`)}function Oe(e){e.command(`bootstrap`).description(`Initialize the data directory with required directories and templates`).requiredOption(`-d, --data-dir <path>`,`Data directory path`).option(`--output <format>`,`Output format: text (default) or json`,`text`).action(async e=>{let t=e.output===`json`?`json`:`text`;try{De(await n(e.dataDir),t)}catch(e){D(`Error bootstrapping data directory: ${e.message}`),process.exit(1)}})}function ke(e){return fe.sm4_encrypt_ecb(e)}function Ae(e){return ke(e)}function je(e={}){let t=e.baseUrl??process.env.AIMAX_BASE_URL,n=process.env.AIMAX_AUTH_TOKEN,r=e.authToken?Ae(e.authToken):n?Ae(n):e.apiKey??process.env.AIMAX_API_KEY,i=e.model??process.env.AIMAX_MODEL,a=[];if(t||a.push(`--base-url / AIMAX_BASE_URL`),r||a.push(`--api-key / AIMAX_API_KEY`),i||a.push(`--model / AIMAX_MODEL`),a.length>0)throw Error(`Missing required LLM configuration: ${a.join(`, `)}`);return{baseUrl:t,apiKey:r,model:i,contextWindow:e.contextWindow??(process.env.AIMAX_CONTEXT_WINDOW?Number(process.env.AIMAX_CONTEXT_WINDOW):void 0),flashModel:e.flashModel??process.env.AIMAX_FLASH_MODEL}}function Me(e,t){return t?x.resolve(t):x.join(e,`.aimax`,`plugins.json`)}async function A(e,t){let n=Me(e,t);try{let e=await b.readFile(n,`utf-8`);return JSON.parse(e)}catch(e){if(e.code===`ENOENT`)return;throw e}}async function j(e,t,n){let r=Me(e,n);await b.mkdir(x.dirname(r),{recursive:!0}),await b.writeFile(r,JSON.stringify(t,null,2),`utf-8`)}function M(e){return typeof e==`object`&&!!e}function N(e){return M(e)&&e.type===`text`&&typeof e.text==`string`&&(e.textSignature===void 0||typeof e.textSignature==`string`)}function Ne(e){return M(e)&&e.type===`image`&&typeof e.data==`string`&&typeof e.mimeType==`string`}function Pe(e){return M(e)&&e.type===`thinking`&&typeof e.thinking==`string`&&(e.thinkingSignature===void 0||typeof e.thinkingSignature==`string`)&&(e.redacted===void 0||typeof e.redacted==`boolean`)}function Fe(e){return M(e)&&e.type===`toolCall`&&typeof e.id==`string`&&typeof e.name==`string`&&M(e.arguments)&&(e.thoughtSignature===void 0||typeof e.thoughtSignature==`string`)}function Ie(e){return typeof e==`string`||Array.isArray(e)&&e.every(e=>N(e)||Ne(e))}function Le(e){return Array.isArray(e)&&e.every(e=>N(e)||Pe(e)||Fe(e))}function Re(e){return M(e)&&typeof e.input==`number`&&typeof e.output==`number`&&typeof e.cacheRead==`number`&&typeof e.cacheWrite==`number`&&typeof e.totalTokens==`number`&&M(e.cost)&&typeof e.cost.input==`number`&&typeof e.cost.output==`number`&&typeof e.cost.cacheRead==`number`&&typeof e.cost.cacheWrite==`number`&&typeof e.cost.total==`number`}function ze(e){return!M(e)||typeof e.role!=`string`?!1:e.role===`user`?Ie(e.content):e.role===`assistant`?Le(e.content)&&typeof e.api==`string`&&typeof e.provider==`string`&&typeof e.model==`string`&&Re(e.usage)&&(e.stopReason===`stop`||e.stopReason===`length`||e.stopReason===`toolUse`||e.stopReason===`error`||e.stopReason===`aborted`)&&(e.errorMessage===void 0||typeof e.errorMessage==`string`):e.role===`toolResult`?typeof e.toolCallId==`string`&&typeof e.toolName==`string`&&Array.isArray(e.content)&&e.content.every(e=>N(e)||Ne(e))&&typeof e.isError==`boolean`:!1}async function Be(e){let t;try{t=await b.readFile(e,`utf-8`)}catch(e){throw Error(`Failed to read message file: ${e.message}`)}let n;try{n=JSON.parse(t)}catch(e){throw Error(`Invalid JSON in message file: ${e.message}`)}let r=Array.isArray(n)?n:[n];if(r.length===0||!r.every(e=>ze(e)))throw Error(`Message file must contain one Message object or an array of Message objects`);return r}async function Ve(e){if(!!e.message==!!e.fromFile)throw Error(`Exactly one of --message or --from-file must be provided`);return e.fromFile?{kind:`messages`,messages:await Be(e.fromFile)}:{kind:`text`,message:e.message}}let P=function(e){return e.INFO=`INFO`,e.ERROR=`ERROR`,e.WARN=`WARN`,e}({}),F=null;function He(){let e=new Date;return`${e.getFullYear()}-${String(e.getMonth()+1).padStart(2,`0`)}-${String(e.getDate()).padStart(2,`0`)} ${String(e.getHours()).padStart(2,`0`)}:${String(e.getMinutes()).padStart(2,`0`)}:${String(e.getSeconds()).padStart(2,`0`)}.${String(e.getMilliseconds()).padStart(3,`0`)}`}function Ue(e){if(!e)return``;let t=Object.entries(e).filter(([,e])=>e!==void 0).map(([e,t])=>`${e}=${JSON.stringify(t)}`);return t.length>0?` ${t.join(` `)}`:``}function We(e){return x.join(e,`.aimax`)}function Ge(e){return{appLogPath:x.join(e,`app.log`),errorLogPath:x.join(e,`errors.log`)}}function Ke(e){let{appLogPath:t,errorLogPath:n}=Ge(e);S.configure({appenders:{appFile:{type:`file`,filename:t,maxLogSize:5*1024*1024,backups:3,compress:!0,keepFileExt:!0,layout:{type:`pattern`,pattern:`[%d{yyyy-MM-dd hh:mm:ss.SSS}] [%p] %m`}},errorFile:{type:`file`,filename:n,maxLogSize:5*1024*1024,backups:3,compress:!0,keepFileExt:!0,layout:{type:`pattern`,pattern:`[%d{yyyy-MM-dd hh:mm:ss.SSS}] [%p] %m`}},errorsOnly:{type:`logLevelFilter`,appender:`errorFile`,level:`error`,maxLevel:`fatal`}},categories:{default:{appenders:[`appFile`,`errorsOnly`],level:`info`}}})}function qe(e,t,n){process.stderr.write(`[${He()}] [${e}] ${t}${Ue(n)}\n`)}function I(e,t,n){let r=`${t}${Ue(n)}`;if(!F){qe(e,r);return}let i=S.getLogger();if(e===P.ERROR){i.error(r);return}if(e===P.WARN){i.warn(r);return}i.info(r)}function L(e){let t=We(e);F?.dataDir!==e&&(pe.mkdirSync(t,{recursive:!0}),Ke(t),F={dataDir:e,logDir:t})}async function Je(){await S.shutdown()}const R={info:(e,t)=>I(P.INFO,e,t),warn:(e,t)=>I(P.WARN,e,t),error:(e,t)=>I(P.ERROR,e,t)};var z=class{startTime;name;constructor(e){this.name=e,this.startTime=Date.now()}end(){let e=Date.now()-this.startTime;return R.info(`${this.name} completed in ${e}ms`),e}},B=class{constructor(e){this.sinks=e}async send(e){await Promise.allSettled(this.sinks.map(async t=>{await t.send(e)}))}async close(){await Promise.allSettled(this.sinks.map(async e=>{await e.close()}))}},V=class{constructor(e){this.url=e}async send(e){await this.post(this.toPayload(e))}async close(){}async post(e){let t=Date.now(),n=Ye(e);R.info(`sending callback event`,{callbackUrl:this.url,...n});let r=await fetch(this.url,{method:`POST`,headers:{"content-type":`application/json`},body:JSON.stringify(e)}),i=Date.now()-t;if(!r.ok)throw R.error(`callback event failed`,{callbackUrl:this.url,httpStatus:r.status,durationMs:i,...n}),Error(`Callback failed with status ${r.status}`);R.info(`callback event delivered`,{callbackUrl:this.url,httpStatus:r.status,durationMs:i,...n})}toPayload(e){switch(e.type){case`start`:return e;case`progress`:return e;case`done`:return e;case`error`:return e;case`session_reset`:return e;case`hitl`:return e;case`title_updated`:return e;default:{let t=e;throw Error(`Unsupported callback event: ${JSON.stringify(t)}`)}}}};function Ye(e){return{eventType:e.type,sessionId:e.sessionId,messageId:e.messageId,channel:e.channel,user:e.user,progressType:e.type===`progress`?e.event.type:void 0}}function Xe(e,t){if(t.kind===`none`)return e;let n=new URL(e);return n.searchParams.set(`authToken`,t.token),n.toString()}function H(){let e=globalThis.WebSocket;if(!e)throw Error(`WebSocket is not available in this runtime`);return e}function Ze(e){return e?{kind:`query_token`,token:e}:{kind:`none`}}function U(e,t,n){if(typeof e.once==`function`){e.once(t,n);return}if(typeof e.addEventListener==`function`&&typeof e.removeEventListener==`function`){let r=(...i)=>{e.removeEventListener?.(t,r),n(...i)};e.addEventListener(t,r);return}throw Error(`WebSocket does not support one-time listener registration for "${t}"`)}function Qe(e,t,n){if(typeof e.on==`function`){e.on(t,n);return}if(typeof e.addEventListener==`function`){e.addEventListener(t,n);return}throw Error(`WebSocket does not support listener registration for "${t}"`)}var W=class{socket=null;connectPromise=null;enabled=!0;textSequence=0;constructor(e,t,n){this.url=e,this.events=t,this.authToken=n}async send(e){let t=this.toEnvelope(e);if(!(!t||!this.enabled))try{await this.ensureConnected();let e=H();if(!this.socket||this.socket.readyState!==e.OPEN)return;this.socket.send(JSON.stringify(t))}catch(e){R.warn(`websocket sink disabled after send failure`,{url:this.url,error:e instanceof Error?e.message:String(e)}),this.enabled=!1}}async sendTextDelta(e){if(!this.enabled||!this.events.has(`text`))return;this.textSequence+=1;let t={type:`text`,sessionId:e.sessionId,messageId:e.messageId,channel:e.channel,user:e.user,timestamp:new Date().toISOString(),sequence:this.textSequence,delta:e.text};try{await this.ensureConnected();let e=H();if(!this.socket||this.socket.readyState!==e.OPEN)return;this.socket.send(JSON.stringify(t))}catch(e){R.warn(`websocket sink disabled after text delta send failure`,{url:this.url,error:e instanceof Error?e.message:String(e)}),this.enabled=!1}}async close(){this.enabled=!1;let e=this.socket;if(this.socket=null,this.connectPromise=null,!e)return;let t=H();e.readyState!==t.CLOSED&&await new Promise(t=>{U(e,`close`,()=>t()),e.close()})}async ensureConnected(){if(!this.enabled)return;let e=H();if(this.socket&&this.socket.readyState===e.OPEN)return;if(this.connectPromise){await this.connectPromise;return}let t=new e(Xe(this.url,Ze(this.authToken)));this.connectPromise=new Promise((e,n)=>{U(t,`open`,()=>{this.socket=t,Qe(t,`close`,()=>{this.socket===t&&(this.socket=null)}),e()}),U(t,`error`,e=>{n(e)})});try{await this.connectPromise}finally{this.connectPromise=null}}toEnvelope(e){let t=new Date().toISOString();switch(e.type){case`start`:return this.events.has(`start`)?{...e,timestamp:t}:null;case`done`:return this.events.has(`done`)?{...e,timestamp:t}:null;case`error`:return this.events.has(`error`)?{...e,timestamp:t}:null;case`hitl`:return this.events.has(`hitl`)?{...e,timestamp:t}:null;case`title_updated`:return this.events.has(`title_updated`)?{type:`title_updated`,sessionId:e.sessionId,messageId:e.messageId,channel:e.channel,user:e.user,timestamp:t,title:e.title}:null;case`session_reset`:return null;case`progress`:return e.event.type===`text`?this.events.has(`text`)?(this.textSequence+=1,{type:`text`,sessionId:e.sessionId,messageId:e.messageId,channel:e.channel,user:e.user,timestamp:t,sequence:this.textSequence,delta:e.event.text}):null:e.event.type===`stream_text_delta`||!this.events.has(`progress`)?null:{type:`progress`,sessionId:e.sessionId,messageId:e.messageId,channel:e.channel,user:e.user,timestamp:t,event:e.event};default:{let t=e;throw Error(`Unsupported stream event: ${JSON.stringify(t)}`)}}}};const $e=[`start`,`text`,`done`,`error`,`hitl`];function et(e){if(!e?.trim())return new Set($e);let t=e.split(`,`).map(e=>e.trim().toLowerCase()).filter(Boolean),n=new Set([`start`,`text`,`progress`,`done`,`error`,`hitl`,`title_updated`]),r=new Set;for(let e of t){if(!n.has(e))throw Error(`Invalid stream event: ${e}. Must be one of start,text,progress,done,error,hitl`);r.add(e)}return r.size>0?r:new Set($e)}function tt(e){let t=e.dataDir??process.env.AIMAX_DATA_DIR;if(!t)throw Error(`Data directory must be specified via --data-dir or AIMAX_DATA_DIR`);return t}function nt(e){return e?_(e):void 0}function rt(e){if(!e?.trim())return[];let t=e.split(`,`).map(e=>e.trim()).filter(Boolean),n=new Set,r=[];for(let e of t){if(!x.isAbsolute(e))throw Error(`Invalid --skillsLoadPaths entry: ${e}. Each path must be absolute.`);n.has(e)||(n.add(e),r.push(e))}return r}function it(e,t){if(e.inputText&&t){let n=de(e.inputText,t);return n.submittedBy={userId:e.user,channel:e.channel??`IM`},n}if(!e.inputJson&&!e.inputText)throw Error(`Either --input-json or --input-text must be provided for the resume command`);try{let t=JSON.parse(e.inputJson);return{requestId:e.requestId,sessionId:e.sessionId,action:t.action??`submit`,values:t.values,submittedBy:t.submittedBy,idempotencyKey:t.idempotencyKey,submittedAt:t.submittedAt??new Date().toISOString()}}catch(e){throw Error(`Invalid --input-json: ${e.message}`)}}function at(e,t){if(!e.inputJson)throw Error(`UI tool resume requires --input-json`);try{let n=JSON.parse(e.inputJson),r=n&&typeof n==`object`&&`values`in n&&n.values&&typeof n.values==`object`&&!Array.isArray(n.values)?n.values:n;return{requestId:t.request.requestId,sessionId:t.sessionId,toolCallId:t.request.toolCallId,toolName:t.request.toolName,values:r,submittedAt:new Date().toISOString()}}catch(e){throw Error(`Invalid --input-json: ${e.message}`)}}async function ot(e){let t=await ne(e.dataDir,e.sessionId,{storeName:e.sessionStoreName});for(let n=t.length-1;n>=0;--n){let r=t[n];if(r?.role!==`assistant`||!Array.isArray(r.toolCalls))continue;let i=r.toolCalls.find(t=>t.id===e.toolCallId&&t.name===e.toolName);if(i)return i.arguments}}async function st(e){let t=tt(e),n=e.channel??`WEB`,r=je({baseUrl:e.baseUrl,apiKey:e.apiKey,authToken:e.authToken,model:e.model,contextWindow:e.contextWindow?Number(e.contextWindow):void 0,flashModel:e.flashModel});return{dataDir:t,channel:n,format:e.output===`json`?`json`:`text`,timeoutMs:e.timeout?Number(e.timeout):void 0,llm:r,skillsLoadPaths:rt(e.skillsLoadPaths)}}function ct(e){let t=[],n=null;return e.callbackUrl&&t.push(new V(e.callbackUrl)),e.streamUrl&&(n=new W(e.streamUrl,et(e.streamEvents),e.streamAuthToken),t.push(n)),{sink:new B(t),websocketSink:n}}async function lt(e){let{dataDir:t,sessionId:n,sessionStoreName:r,toolCallId:i,toolName:a,resolution:o}=e;if(!i||!a||!le(a))return;let s=(e,t)=>{switch(e){case`request_approval`:return c(t);case`clarify`:return l(t);case`request_review`:return u(t);default:return JSON.stringify({action:t.action,values:t.values})}};await se(t,n,e=>{let t=e.findIndex(e=>e.role===`tool_result`&&e.toolCallId===i&&e.toolName===a);if(t===-1)return e;let n=e.slice(0,t+1);return n[t]={...n[t],content:s(a,o),isError:!1},n},{storeName:r})}async function ut(e){let{dataDir:t,sessionId:n,sessionStoreName:r,result:i}=e;await se(t,n,e=>{let t=e.findIndex(e=>e.role===`assistant`&&Array.isArray(e.toolCalls)&&e.toolCalls.some(e=>e.id===i.toolCallId&&e.name===i.toolName));if(t===-1)return e;let n=e.slice(0,t+1);return n.push({role:`tool_result`,toolCallId:i.toolCallId,toolName:i.toolName,content:JSON.stringify({submitted:!0,values:i.values}),isError:!1,timestamp:i.submittedAt}),n},{storeName:r})}async function G(e){L(tt(e));let t=new z(`resume command`),n=null;try{let r=await st(e),a=nt(e.sessionStore);R.info(`resume command started`,{sessionId:e.sessionId,requestId:e.requestId,channel:r.channel,dataDir:r.dataDir});let o=await g(r.dataDir,e.sessionId,{storeName:a}),s=o?null:await ee(r.dataDir,e.sessionId,{storeName:a});if(!o&&!s)throw Error(`No pending HITL or UI tool request found for session "${e.sessionId}"`);if(o){if(o.request.requestId!==e.requestId)throw Error(`Request ID mismatch: pending is "${o.request.requestId}", got "${e.requestId}"`);if(o.status===`expired`)throw Error(`HITL request has expired`);if(o.status===`cancelled`)throw Error(`HITL request has been cancelled`)}else if(s){if(s.request.requestId!==e.requestId)throw Error(`Request ID mismatch: pending is "${s.request.requestId}", got "${e.requestId}"`);if(s.status!==`pending`)throw Error(`UI tool request is already "${s.status}", cannot resume`)}if(o){let i=it(e,o.request),s=await ae({dataDir:r.dataDir,sessionStoreName:a,sessionId:e.sessionId,requestId:e.requestId,resolution:i}),c=s.state;if(!c)throw Error(`Resolved HITL state was not persisted`);let l=dt(i,c.request.kind);await lt({dataDir:r.dataDir,sessionId:e.sessionId,sessionStoreName:a,toolCallId:c.toolContext?.toolCallId,toolName:c.toolContext?.toolName,resolution:i});let u=ct(e);n=u.sink;let d=e.sessionId,f=async t=>{if(d=t.sessionId??d,!y(t)){if(t.type===`stream_text_delta`){r.format===`text`&&O(t),await u.websocketSink?.sendTextDelta({sessionId:d,channel:r.channel,messageId:e.messageId,user:e.user,text:t.text});return}r.format===`text`&&O(t),await n?.send({sessionId:d,channel:r.channel,messageId:e.messageId,user:e.user,type:`progress`,event:t})}};await f({type:`hitl_resumed`,requestId:e.requestId,resolution:i,sessionId:e.sessionId}),`idempotentReplay`in s&&s.idempotentReplay&&(R.info(`resume command treated as idempotent replay`,{sessionId:e.sessionId,requestId:e.requestId,idempotencyKey:i.idempotencyKey}),k({sessionId:e.sessionId,text:`Resume request already processed.`,usage:{input:0,output:0,total:0},durationMs:0},r.format),t.end(),process.exit(0));let p=e.pluginsConfig??process.env.AIMAX_PLUGINS_CONFIG,m=await A(r.dataDir,p),h;try{h=await v({dataDir:r.dataDir,sessionStoreName:a,sessionId:e.sessionId,messageId:e.messageId,channel:r.channel,llm:r.llm,skillsLoadPaths:r.skillsLoadPaths,timeoutMs:r.timeoutMs,message:l,hitlResume:{request:c.request,resolution:i,checkpoint:c.checkpoint,toolContext:c.toolContext},plugins:m?{config:m,dataDir:r.dataDir,workspaceDir:x.join(r.dataDir,`workspace`),bundledDir:process.env.AIMAX_PLUGINS_BUNDLED_DIR,llmAllowlist:m.llmAllowlist}:void 0,onProgress:f})}finally{}h.error?await n?.send({sessionId:h.sessionId,channel:r.channel,messageId:e.messageId,user:e.user,type:`error`,message:h.error}):await n?.send({sessionId:h.sessionId,channel:r.channel,messageId:e.messageId,user:e.user,type:`done`,result:{text:h.text,usage:h.usage,durationMs:h.durationMs,error:h.error,paused:h.paused,uiToolPending:h.uiToolPending}}),k(h,r.format),h.error?R.error(`resume command failed: ${h.error}`):R.info(`resume command succeeded`),t.end(),process.exit(h.error?1:0);return}let c=at(e,s);if(!await oe(r.dataDir,e.sessionId,e.requestId,c,{storeName:a}))throw Error(`UI tool resume validation failed`);await ut({dataDir:r.dataDir,sessionId:e.sessionId,sessionStoreName:a,result:c});let l=ct(e);n=l.sink;let u=e.sessionId,d=async t=>{if(u=t.sessionId??u,!y(t)){if(t.type===`stream_text_delta`){r.format===`text`&&O(t),await l.websocketSink?.sendTextDelta({sessionId:u,channel:r.channel,messageId:e.messageId,user:e.user,text:t.text});return}if(r.format===`text`&&O(t),t.type===`start`){await n?.send({sessionId:u,channel:r.channel,messageId:e.messageId,user:e.user,type:`start`,message:t.message});return}await n?.send({sessionId:u,channel:r.channel,messageId:e.messageId,user:e.user,type:`progress`,event:t})}},f=await ot({dataDir:r.dataDir,sessionId:e.sessionId,sessionStoreName:a,toolCallId:c.toolCallId,toolName:c.toolName});await d({type:`tool_end`,sessionId:e.sessionId,toolCallId:c.toolCallId,name:c.toolName,input:f,output:JSON.stringify({submitted:!0,values:c.values}),isError:!1});let p=e.pluginsConfig??process.env.AIMAX_PLUGINS_CONFIG,m=await A(r.dataDir,p),h=await v({dataDir:r.dataDir,sessionStoreName:a,sessionId:e.sessionId,messageId:e.messageId,channel:r.channel,llm:r.llm,skillsLoadPaths:r.skillsLoadPaths,timeoutMs:r.timeoutMs,message:`[UI_TOOL_RESUME]
5
+ The pending UI tool result has been written into the transcript. Continue from the latest tool result without repeating the same form request.`,uiToolResume:c,plugins:m?{config:m,dataDir:r.dataDir,workspaceDir:x.join(r.dataDir,`workspace`),bundledDir:process.env.AIMAX_PLUGINS_BUNDLED_DIR,llmAllowlist:m.llmAllowlist}:void 0,onProgress:d});await i(r.dataDir,e.sessionId,{storeName:a}),h.error?await n?.send({sessionId:h.sessionId,channel:r.channel,messageId:e.messageId,user:e.user,type:`error`,message:h.error}):await n?.send({sessionId:h.sessionId,channel:r.channel,messageId:e.messageId,user:e.user,type:`done`,result:{text:h.text,usage:h.usage,durationMs:h.durationMs,error:h.error,paused:h.paused,uiToolPending:h.uiToolPending}}),k(h,r.format),h.error?R.error(`resume command failed: ${h.error}`):R.info(`resume command succeeded`),t.end(),process.exit(h.error?1:0)}catch(r){let i=r;n&&(i.message.includes(`expired`)&&await n.send({sessionId:e.sessionId,channel:e.channel??`WEB`,messageId:e.messageId,user:e.user,type:`progress`,event:{type:`hitl_expired`,sessionId:e.sessionId,requestId:e.requestId,reason:i.message}}),i.message.includes(`cancelled`)&&await n.send({sessionId:e.sessionId,channel:e.channel??`WEB`,messageId:e.messageId,user:e.user,type:`progress`,event:{type:`hitl_cancelled`,sessionId:e.sessionId,requestId:e.requestId,reason:i.message}}),await n.send({sessionId:e.sessionId,channel:e.channel??`WEB`,messageId:e.messageId,user:e.user,type:`error`,message:`Resume failed: ${i.message}`})),R.error(`resume command error: ${i.message}`),D(`Fatal: ${i.message}`),t.end(),process.exit(1)}finally{await n?.close()}}function dt(e,t){return r(e,t)}function ft(e){e.command(`resume`).description(`Resume a paused HITL session with user input`).requiredOption(`-d, --data-dir <path>`,`Data directory path (overrides AIMAX_DATA_DIR)`).requiredOption(`-s, --session-id <id>`,`Session ID to resume`).option(`--session-store <name>`,`Session store directory under .aimax (default: sessions)`).requiredOption(`--request-id <id>`,`HITL request ID to resolve`).option(`--input-json <json>`,`JSON string with the resolution (action, values, etc.)`).option(`--input-text <text>`,`Plain text response for IM channels without rich UI (e.g. '同意', '拒绝')`).option(`--skillsLoadPaths <paths>`,`Comma-separated absolute skill load paths`).option(`--message-id <id>`,`Message ID for correlating events`).option(`--user <id>`,`User identifier propagated to external callback and stream payloads`).option(`-c, --channel <channel>`,`Channel name (default: WEB)`,`WEB`).option(`--base-url <url>`,`LLM API base URL (overrides AIMAX_BASE_URL)`).option(`--api-key <key>`,`LLM API key (overrides AIMAX_API_KEY)`).option(`--auth-token <token>`,`Auth token used to generate the API key`).option(`--model <name>`,`LLM model name (overrides AIMAX_MODEL)`).option(`--context-window <n>`,`LLM context window size`).option(`--callback-url <url>`,`HTTP callback URL for progress events`).option(`--stream-url <url>`,`WebSocket URL for streaming text events`).option(`--stream-auth-token <token>`,`Auth token for WebSocket streaming`).option(`--stream-events <list>`,`Comma-separated stream events`).option(`--timeout <ms>`,`Execution timeout in milliseconds`).option(`--output <format>`,`Output format: text (default) or json`,`text`).option(`--plugins-config <path>`,`Plugins config file path`).action(async e=>{await G(e)})}const pt=[`start`,`text`,`done`,`error`];function mt(e){if(!e?.trim())return new Set(pt);let t=e.split(`,`).map(e=>e.trim().toLowerCase()).filter(Boolean),n=new Set([`start`,`text`,`progress`,`done`,`error`,`hitl`,`title_updated`]),r=new Set;for(let e of t){if(!n.has(e))throw Error(`Invalid stream event: ${e}. Must be one of start,text,progress,done,error,hitl,title_updated`);r.add(e)}return r.size>0?r:new Set(pt)}function K(e){let t=e.dataDir??process.env.AIMAX_DATA_DIR;if(!t)throw Error(`Data directory must be specified via --data-dir option or AIMAX_DATA_DIR environment variable`);return t}function ht(e){return e??`WEB`}function q(e){return e?_(e):void 0}function gt(e){if(!e?.trim())return[];let t=e.split(`,`).map(e=>e.trim()).filter(Boolean),n=new Set,r=[];for(let e of t){if(!x.isAbsolute(e))throw Error(`Invalid --skillsLoadPaths entry: ${e}. Each path must be absolute.`);n.has(e)||(n.add(e),r.push(e))}return r}function _t(e,t){return e.length<=t?e:t<=3?e.slice(0,t):`${e.slice(0,t-3)}...`}function vt(e,t,n=78){let r=n-2,i=r-2,a=e?` ${_t(e,Math.max(0,i-2))} `:``,o=e?`┌${a}${`─`.repeat(Math.max(0,r-a.length))}┐`:`┌${`─`.repeat(r)}┐`,s=`└${`─`.repeat(r)}┘`;return[o,...t.map(e=>`│ ${_t(e,i).padEnd(i,` `)} │`),s].join(`
6
+ `)}function yt(e){return e.kind===`text`?`inline message (${e.message.length} chars)`:`message file (${e.messages.length} messages)`}function bt(e,t){let n=q(e.sessionStore)??`sessions`,r=t.timeoutMs===void 0?`default`:`${t.timeoutMs}`,i=e.callbackUrl?`enabled`:`disabled`,a=e.streamUrl?`enabled`:`disabled`,o=yt(t.input),s=t.input.kind===`text`?`inline`:e.fromFile??`file`,c=new Date().toISOString();return{banner:vt(void 0,[`AIMax CLI`,`Stateless Agent Runner`]),contextBox:vt(`Run Context`,[`time : ${c}`,`channel : ${t.channel}`,`user : ${e.user??`-`}`,`sessionId : ${e.sessionId??`new`}`,`sessionStore : ${n}`,`messageId : ${e.messageId??`-`}`,`dataDir : ${t.dataDir}`,`workspace : ${x.join(t.dataDir,`workspace`)}`,`output : ${t.format}`,`callback : ${i}`,`websocket : ${a}`,`timeoutMs : ${r}`,`input : ${o}`]),logContext:{time:c,channel:t.channel,user:e.user,dataDir:t.dataDir,workspaceDir:x.join(t.dataDir,`workspace`),sessionId:e.sessionId??`new`,sessionStore:n,messageId:e.messageId,output:t.format,hasCallback:!!e.callbackUrl,hasStream:!!e.streamUrl,timeoutMs:t.timeoutMs,inputKind:t.input.kind,inputSource:s,inputSummary:o}}}async function xt(e,t){let n=K(e),r=ht(e.channel),i=je({baseUrl:e.baseUrl,apiKey:e.apiKey,authToken:e.authToken,model:e.model,contextWindow:e.contextWindow?Number(e.contextWindow):void 0,flashModel:e.flashModel});return{dataDir:n,channel:r,format:e.output===`json`?`json`:`text`,timeoutMs:e.timeout?Number(e.timeout):void 0,llm:i,input:t,skillsLoadPaths:gt(e.skillsLoadPaths)}}function St(e){if(e.kind===`text`)return e.message;if(e.messages.length!==1)return null;let[t]=e.messages;if(t.role!==`user`)return null;if(typeof t.content==`string`)return t.content;if(t.content.length===0)return null;let n=[];for(let e of t.content){if(e.type!==`text`)return null;n.push(e.text)}return n.join(`
7
+ `)}async function Ct(e,t){if(!e.sessionId)return null;let n=St(t);if(!n)return null;let r=await g(K(e),e.sessionId,{storeName:q(e.sessionStore)});return!r||r.status!==`pending`||!ue(n,r.request)?null:{requestId:r.request.requestId,inputText:n}}function wt(e){let t=[],n=null;return e.callbackUrl&&t.push(new V(e.callbackUrl)),e.streamUrl&&(n=new W(e.streamUrl,mt(e.streamEvents),e.streamAuthToken),t.push(n)),{sink:new B(t),websocketSink:n}}async function J(e,t){R.info(`dispatching external event`,Ht(t)),await e.sink.send(t)}function Tt(e){if(!e)return{};let t={};for(let[n,r]of Object.entries(e)){if(r===null||typeof r==`string`||typeof r==`number`||typeof r==`boolean`){t[n]=r;continue}if(r instanceof Error){t[n]=`${r.name}: ${r.message}`;continue}t[n]=JSON.stringify(r)}return t}function Et(e){let t={sessionId:e.sessionId,messageId:e.messageId,parentSessionId:e.parentSessionId,depth:e.depth,scope:e.scope,phase:e.phase,...Tt(e.details)};if(e.level===`error`){R.error(e.message,t);return}if(e.level===`warn`){R.warn(e.message,t);return}R.info(e.message,t)}function Dt(e,t,n,r,i){return{sink:e,websocketSink:t,channel:n,defaultMessageId:r,user:i}}function Ot(){let e=new AbortController,t=()=>e.abort();return process.once(`SIGTERM`,t),process.once(`SIGINT`,t),{controller:e,cleanup:()=>{process.off(`SIGTERM`,t),process.off(`SIGINT`,t)}}}function kt(e){return{activeSessionId:e??`pending`,finalResult:null}}function At(e,t){e.activeSessionId=t.sessionId??e.activeSessionId}function jt(e,t){return e.messageId??t}async function Mt(e,t,n){if(!await d(e.dataDir)){if(await Y(t,e.format,n.activeSessionId,e.dataDir,`checking`),(await o(e.dataDir)).performedBootstrap){await Y(t,e.format,n.activeSessionId,e.dataDir,`initializing`),await Y(t,e.format,n.activeSessionId,e.dataDir,`initialized`);return}await Y(t,e.format,n.activeSessionId,e.dataDir,`ready`)}}async function Y(e,t,n,r,i){let a={type:`bootstrap`,phase:i,dataDir:r};t===`text`&&O(a),await J(e,{sessionId:n,channel:e.channel,messageId:e.defaultMessageId,user:e.user,type:`progress`,event:a})}function Nt(e,t,n){return async r=>{if(At(n,r),y(r)){Et(r);return}if(r.type===`stream_text_delta`){e.format===`text`&&O(r),await t.websocketSink?.sendTextDelta({sessionId:n.activeSessionId,channel:e.channel,messageId:jt(r,t.defaultMessageId),user:t.user,text:r.text});return}e.format===`text`&&O(r);let i=jt(r,t.defaultMessageId);if(r.type===`hitl_requested`){await J(t,{sessionId:n.activeSessionId,channel:e.channel,messageId:i,user:t.user,type:`hitl`,request:r.request}),await J(t,{sessionId:n.activeSessionId,channel:e.channel,messageId:i,user:t.user,type:`progress`,event:r});return}if(r.type===`start`){await J(t,{sessionId:n.activeSessionId,channel:e.channel,messageId:i,user:t.user,type:`start`,message:r.message});return}if(r.type===`session_reset`){await J(t,{sessionId:n.activeSessionId,channel:e.channel,messageId:i,user:t.user,type:`session_reset`,action:r.action,previousSessionId:r.previousSessionId,message:r.message});return}await J(t,{sessionId:n.activeSessionId,channel:e.channel,messageId:i,user:t.user,type:`progress`,event:r})}}function Pt(e,t,n,r,i){let a={dataDir:t.dataDir,sessionStoreName:q(e.sessionStore),sessionId:e.sessionId,messageId:e.messageId,channel:t.channel,llm:t.llm,skillsLoadPaths:t.skillsLoadPaths,timeoutMs:t.timeoutMs,abortSignal:n.signal,plugins:i?{config:i,dataDir:t.dataDir,workspaceDir:x.join(t.dataDir,`workspace`),bundledDir:process.env.AIMAX_PLUGINS_BUNDLED_DIR,llmAllowlist:i.llmAllowlist}:void 0,onProgress:r};return t.input.kind===`messages`?{...a,messages:t.input.messages}:{...a,message:t.input.message}}async function Ft(e,t,n,r){if(t.activeSessionId=r.sessionId,t.finalResult=r,r.error){await J(e,{sessionId:r.sessionId,channel:e.channel,messageId:n,user:e.user,type:`error`,message:r.error});return}await J(e,{sessionId:r.sessionId,channel:e.channel,messageId:n,user:e.user,type:`done`,result:{text:r.text,usage:r.usage,durationMs:r.durationMs,error:r.error,paused:r.paused}})}async function It(e,t,n,r){await J(e,{sessionId:t.finalResult?.sessionId??t.activeSessionId,channel:e.channel,messageId:n,user:e.user,type:`error`,message:`Fatal: ${r.message}`})}function Lt(e,t){let n=bt(e,t);R.info([`run command started`,n.banner,n.contextBox].join(`
8
+ `),n.logContext),t.format===`text`&&(E(n.banner),E(``),E(n.contextBox),E(``))}function Rt(e,t,n){k(t,n),t.error?R.error(`run command failed: ${t.error}`):R.info(`run command succeeded`),e.end(),process.exit(t.error?1:0)}function zt(e,t){R.error(`run command error: ${t.message}`),D(`Fatal: ${t.message}`),e.end(),process.exit(1)}async function Bt(e){if(e.resumeInputJson&&e.resumeFromFile)throw Error(`--resume-input-json and --resume-from-file are mutually exclusive`);if(!e.resumeFromFile)return e.resumeInputJson;try{return await b.readFile(e.resumeFromFile,`utf-8`)}catch(e){throw Error(`Failed to read resume input file: ${e.message}`)}}async function Vt(e){let t=await Bt(e);if(e.resumeRequestId||t||e.resumeFromFile){if(!e.sessionId||!e.resumeRequestId||!t)throw Error(`--session-id, --resume-request-id, and exactly one of --resume-input-json or --resume-from-file must be provided together`);await G({dataDir:e.dataDir,sessionId:e.sessionId,sessionStore:e.sessionStore,requestId:e.resumeRequestId,inputJson:t,channel:e.channel,baseUrl:e.baseUrl,apiKey:e.apiKey,authToken:e.authToken,model:e.model,contextWindow:e.contextWindow,flashModel:e.flashModel,callbackUrl:e.callbackUrl,streamUrl:e.streamUrl,streamAuthToken:e.streamAuthToken,streamEvents:e.streamEvents,timeout:e.timeout,output:e.output,pluginsConfig:e.pluginsConfig,skillsLoadPaths:e.skillsLoadPaths,messageId:e.messageId,user:e.user});return}let n;try{n=await Ve({message:e.message,fromFile:e.fromFile})}catch(t){L(K(e)),zt(new z(`run command`),t);return}let r=await Ct(e,n);if(r){await G({dataDir:e.dataDir,sessionId:e.sessionId,sessionStore:e.sessionStore,requestId:r.requestId,inputText:r.inputText,channel:e.channel,baseUrl:e.baseUrl,apiKey:e.apiKey,authToken:e.authToken,model:e.model,contextWindow:e.contextWindow,flashModel:e.flashModel,callbackUrl:e.callbackUrl,streamUrl:e.streamUrl,streamAuthToken:e.streamAuthToken,streamEvents:e.streamEvents,timeout:e.timeout,output:e.output,pluginsConfig:e.pluginsConfig,skillsLoadPaths:e.skillsLoadPaths,messageId:e.messageId,user:e.user});return}L(K(e));let i=new z(`run command`),{controller:a,cleanup:o}=Ot(),s=null,c=e.channel??`WEB`,l=kt(e.sessionId);try{let t=await xt(e,n);c=t.channel,Lt(e,t);let r=wt(e);s=r.sink,R.info(`external sink configured`,{callbackUrl:e.callbackUrl,streamUrl:e.streamUrl,streamEvents:e.streamEvents});let o=Dt(s,r.websocketSink,t.channel,e.messageId,e.user);await Mt(t,o,l);let u=e.pluginsConfig??process.env.AIMAX_PLUGINS_CONFIG,d=await A(t.dataDir,u),f=await v(Pt(e,t,a,Nt(t,o,l),d));await Ft(o,l,e.messageId,f),Rt(i,f,t.format)}catch(t){let n=t;s&&await It(Dt(s,null,c,e.messageId,e.user),l,e.messageId,n),zt(i,n)}finally{await s?.close(),o()}}function Ht(e){return{eventType:e.type,sessionId:e.sessionId,messageId:e.messageId,channel:e.channel,user:e.user,progressType:e.type===`progress`?e.event.type:void 0,textLength:e.type===`done`?e.result.text.length:void 0,hasError:e.type===`error`?!0:e.type===`done`?!!e.result.error:void 0}}function Ut(e){e.command(`run`).description(`Run an agent task`).option(`-d, --data-dir <path>`,`Data directory path (overrides AIMAX_DATA_DIR)`).option(`--user <id>`,`User identifier propagated to external callback and stream payloads`).option(`--message <text>`,`User message to send to the agent`).option(`--from-file <path>`,`Load structured Message JSON from a file`).option(`--skillsLoadPaths <paths>`,`Comma-separated absolute skill load paths`).option(`-s, --session-id <id>`,`Resume an existing session by ID`).option(`--session-store <name>`,`Session store directory under .aimax (default: sessions)`).option(`--message-id <id>`,`Message ID for correlating events`).option(`-c, --channel <channel>`,`Channel name (default: WEB)`,`WEB`).option(`--base-url <url>`,`LLM API base URL (overrides AIMAX_BASE_URL)`).option(`--api-key <key>`,`LLM API key (overrides AIMAX_API_KEY)`).option(`--auth-token <token>`,`Auth token used to generate the API key (highest priority)`).option(`--model <name>`,`LLM model name (overrides AIMAX_MODEL)`).option(`--context-window <n>`,`LLM context window size`).option(`--flash-model <name>`,`Flash model for lightweight tasks like title generation (overrides AIMAX_FLASH_MODEL)`).option(`--callback-url <url>`,`HTTP callback URL for progress events`).option(`--stream-url <url>`,`WebSocket URL for streaming text events`).option(`--stream-auth-token <token>`,`Auth token for WebSocket streaming`).option(`--stream-events <list>`,`Comma-separated stream events: start,text,progress,done,error`).option(`--timeout <ms>`,`Execution timeout in milliseconds (default: 600000)`).option(`--output <format>`,`Output format: text (default) or json`,`text`).option(`--plugins-config <path>`,`Plugins config file path`).option(`--resume-request-id <id>`,`Resume a pending HITL request from aimax run`).option(`--resume-input-json <json>`,`Structured HITL resume payload used with --resume-request-id`).option(`--resume-from-file <path>`,`Load structured HITL resume payload from a file (alternative to --resume-input-json)`).action(async e=>{await Vt(e)})}function Wt(e){e.command(`sessions`).description(`List or inspect sessions for a data directory`).argument(`[action]`,`Action: list (default) | inspect | export`).option(`-d, --data-dir <path>`,`Data directory path`).option(`--session-store <name>`,`Session store directory under .aimax (default: sessions)`).option(`-c, --channel <channel>`,`Filter by channel type: H5 | WEB | KLPA | TASK | CRON | EIP_ASSISTANT`).option(`-s, --session-id <id>`,`Session ID for inspect/export`).option(`--output <format>`,`Output format: text or json`).action(async(e,t,n)=>{let r=n.opts(),i=e??`list`,a=i===`export`?r.output===`text`?`text`:`json`:r.output===`json`?`json`:`text`;r.dataDir||(D(`error: required option '-d, --data-dir <path>' not specified`),process.exit(1)),r.channel&&r.channel!==`H5`&&r.channel!==`WEB`&&r.channel!==`KLPA`&&r.channel!==`TASK`&&r.channel!==`CRON`&&r.channel!==`EIP_ASSISTANT`&&(D(`Invalid channel: ${r.channel}. Must be 'H5', 'WEB', 'KLPA', 'TASK', 'CRON', or 'EIP_ASSISTANT'`),process.exit(1));try{let e=r.sessionStore?_(r.sessionStore):void 0;if(i===`list`){we(await h(r.dataDir,r.channel,{storeName:e}),a);return}if(r.sessionId||(D(`error: required option '-s, --session-id <id>' not specified`),process.exit(1)),i===`inspect`){Te(await p(r.dataDir,r.sessionId,{storeName:e}),a);return}if(i===`export`){Ee(await s(r.dataDir,r.sessionId,{storeName:e}),a);return}D(`Invalid sessions action: ${i}. Must be 'list', 'inspect', or 'export'`),process.exit(1)}catch(e){D(`${i===`inspect`?`Error inspecting session`:i===`export`?`Error exporting session`:`Error listing sessions`}: ${e.message}`),process.exit(1)}})}function Gt(e,t){let n=[];return n.push(`backend: ${e.backend}`),n.push(`provider: ${e.provider}${e.model?` (${e.model})`:``}`),typeof e.files==`number`&&n.push(`files: ${e.files}`),typeof e.chunks==`number`&&n.push(`chunks: ${e.chunks}`),typeof e.dirty==`boolean`&&n.push(`dirty: ${e.dirty}`),e.dbPath&&n.push(`db: ${e.dbPath}`),e.sources?.length&&n.push(`sources: ${e.sources.join(`, `)}`),t&&(e.fts&&(n.push(`fts: enabled=${e.fts.enabled} available=${e.fts.available}`),e.fts.error&&n.push(`fts_error: ${e.fts.error}`)),e.vector&&(n.push(`vector: enabled=${e.vector.enabled} available=${e.vector.available??`unknown`}`),e.vector.dims&&n.push(`vector_dims: ${e.vector.dims}`),e.vector.loadError&&n.push(`vector_error: ${e.vector.loadError}`)),e.cache&&n.push(`cache: enabled=${e.cache.enabled} entries=${e.cache.entries??0}`)),n.join(`
9
+ `)}function X(e){let t=x.join(e.dataDir,`.aimax`),n=ie({providerId:e.provider,pluginId:e.providerPlugin,dataDir:e.dataDir,memoryDir:t});return n?n.provider:a({dataDir:e.dataDir,memoryDir:t},{includeSessions:e.includeSessions})}function Kt(e){let t=e.command(`memory`).description(`Manage semantic memory indexing and search`);t.command(`status`).description(`Show memory index status`).requiredOption(`-d, --data-dir <path>`,`Data directory path`).option(`--deep`,`Probe embedding/vector availability`).option(`--index`,`Run a refresh before reporting status`).option(`--include-sessions`,`Include session transcripts in indexing`).option(`--provider <id>`,`Memory provider id`).option(`--provider-plugin <id>`,`Memory provider plugin id`).option(`--verbose`,`Verbose output`).option(`--output <format>`,`Output format: text (default) or json`,`text`).action(async e=>{let t=e.output===`json`?`json`:`text`;try{let n=X({dataDir:e.dataDir,provider:e.provider,providerPlugin:e.providerPlugin,includeSessions:e.includeSessions});e.index&&n.sync&&await n.sync(`cli-status`);let r=n.status();e.deep&&((r.custom??={}).note=`deep probe is only supported by builtin provider`),E(t===`json`?JSON.stringify(r,null,2):Gt(r,e.deep))}catch(e){D(`Error getting memory status: ${e.message}`),process.exit(1)}}),t.command(`index`).description(`Reindex memory files`).requiredOption(`-d, --data-dir <path>`,`Data directory path`).option(`--include-sessions`,`Include session transcripts in indexing`).option(`--provider <id>`,`Memory provider id`).option(`--provider-plugin <id>`,`Memory provider plugin id`).option(`--verbose`,`Verbose output`).action(async e=>{try{let t=X({dataDir:e.dataDir,provider:e.provider,providerPlugin:e.providerPlugin,includeSessions:e.includeSessions});t.sync&&await t.sync(`cli-index`),E(`Memory index refreshed.`)}catch(e){D(`Error indexing memory: ${e.message}`),process.exit(1)}}),t.command(`search [query]`).description(`Search semantic memory`).requiredOption(`-d, --data-dir <path>`,`Data directory path`).option(`--query <text>`,`Search query`).option(`--include-sessions`,`Include session transcripts in search`).option(`--provider <id>`,`Memory provider id`).option(`--provider-plugin <id>`,`Memory provider plugin id`).option(`--output <format>`,`Output format: text (default) or json`,`text`).action(async(e,t)=>{let n=t.output===`json`?`json`:`text`,r=t.query?.trim()||e?.trim();r||(D(`Query is required: provide [query] or --query <text>`),process.exit(1));try{let e=await X({dataDir:t.dataDir,provider:t.provider,providerPlugin:t.providerPlugin,includeSessions:t.includeSessions}).search(r);if(n===`json`){E(JSON.stringify(e,null,2));return}if(e.length===0){E(`No results found for: ${r}`);return}E(e.map(e=>{let t=`${e.path}:${e.startLine}-${e.endLine} (${e.score.toFixed(4)}) ${e.snippet}`;return e.citation?`${t}\n${e.citation}`:t}).join(`
10
+ `))}catch(e){D(`Error searching memory: ${e.message}`),process.exit(1)}})}function qt(e){return`${e.match.accountId?`${e.match.channel}:${e.match.accountId}`:e.match.channel} -> ${e.agentId}`}function Jt(e){return async t=>{let n=await w(t),r=ge(n),i=_e(n);if(T(n),e.json){console.log(JSON.stringify({agents:r,bindings:i},null,2));return}console.log(`Agents:`);for(let e of r){let n=e.default?` (default)`:``,r=e.name&&e.name!==e.id?`${e.id}${n} (${e.name})`:`${e.id}${n}`;if(console.log(` - ${r}`),e.identity?.emoji||e.identity?.name){let t=[e.identity.emoji,e.identity.name].filter(Boolean).join(` `);console.log(` Identity: ${t}`)}let a=xe(t,e.id);if(console.log(` Agent dir: ${a}`),e.model){let t=typeof e.model==`string`?e.model:e.model.primary;console.log(` Model: ${t}`)}let o=i.filter(t=>t.agentId===e.id);if(o.length>0){console.log(` Routing rules:`);for(let e of o)console.log(` - ${qt(e)}`)}}}}function Yt(e,t){return async n=>{C(await w(n),ve(e))&&(console.error(`Agent "${e}" already exists.`),process.exit(1)),await me(n,{id:e,name:t.name,model:t.model,default:t.default})||(console.error(`Agent "${e}" already exists.`),process.exit(1));let r=xe(n,e);console.log(`Agent "${e}" added successfully.`),console.log(` Agent dir: ${r}`)}}function Xt(e){return async t=>{let n=C(await w(t),ve(e));n||(console.error(`Agent "${e}" not found.`),process.exit(1)),n.default===!0&&(console.error(`Cannot delete default agent "${e}".`),process.exit(1)),await ye(t,e)||(console.error(`Failed to delete agent "${e}".`),process.exit(1)),console.log(`Agent "${e}" deleted.`)}}function Zt(e){return async t=>{let n=await w(t),r=e.agent??T(n);C(n,r)||(console.error(`Agent "${r}" not found.`),process.exit(1)),(!e.bind||e.bind.length===0)&&(console.error(`Please specify --bind <channel>[:<account>]`),process.exit(1));for(let n of e.bind){let[e,...i]=n.split(`:`),a=i.join(`:`),o=[`H5`,`WEB`,`KLPA`,`TASK`,`CRON`,`EIP_ASSISTANT`];o.includes(e)||(console.error(`Invalid channel: ${e}`),console.error(`Valid channels: ${o.join(`, `)}`),process.exit(1)),await he(t,{agentId:r,match:{channel:e,accountId:a||void 0}}),console.log(`Binding added: ${n} -> ${r}`)}}}function Qt(e){return async t=>{let n=await w(t),r=e.agent??T(n);if(C(n,r)||(console.error(`Agent "${r}" not found.`),process.exit(1)),e.all){let e=await be(t,r,`*`);console.log(`Removed ${e} binding(s) for agent "${r}".`)}else if(e.bind&&e.bind.length>0){let n=0;for(let i of e.bind){let[e,...a]=i.split(`:`),o=await be(t,r,e,a.join(`:`)||void 0);o>0?(console.log(`Binding removed: ${i} -> ${r}`),n+=o):console.log(`No binding found: ${i} -> ${r}`)}}else console.error(`Please specify --bind <channel>[:<account>] or --all`),process.exit(1)}}function $t(e){return async t=>{let n=_e(await w(t));if(e.agent&&(n=n.filter(t=>t.agentId===e.agent)),e.json){console.log(JSON.stringify(n,null,2));return}if(n.length===0){console.log(`No bindings configured.`);return}console.log(`Routing bindings:`);for(let e of n)console.log(` ${qt(e)}`)}}function en(e){return async t=>{let n=await w(t),r=e.agent??T(n);C(n,r)||(console.error(`Agent "${r}" not found.`),process.exit(1)),await Se(t,r,{name:e.name,emoji:e.emoji,avatar:e.avatar})||(console.error(`Failed to update identity for agent "${r}".`),process.exit(1)),console.log(`Identity updated for agent "${r}".`)}}function tn(e,t){let n=e.command(`agents`).description(`Manage agents`);n.command(`list`).description(`List all configured agents`).option(`-j, --json`,`Output as JSON`).option(`-b, --bindings`,`Show detailed binding rules`).action(async e=>{let n=t();await Jt(e)(n)}),n.command(`add <id>`).description(`Add a new agent`).option(`-n, --name <name>`,`Display name`).option(`-m, --model <model>`,`Model identifier`).option(`--default`,`Mark as default agent`).action(async(e,n)=>{let r=t();await Yt(e,n)(r)}),n.command(`delete <id>`).description(`Delete an agent`).action(async e=>{let n=t();await Xt(e)(n)}),n.command(`bind`).description(`Bind a channel to an agent`).option(`-a, --agent <id>`,`Target agent ID`).option(`-b, --bind <channel...>`,`Channel binding (e.g., WEB, KLPA:ops)`).action(async e=>{let n=t();await Zt(e)(n)}),n.command(`unbind`).description(`Unbind a channel from an agent`).option(`-a, --agent <id>`,`Target agent ID`).option(`-b, --bind <channel...>`,`Channel binding to remove`).option(`--all`,`Remove all bindings for the agent`).action(async e=>{let n=t();await Qt(e)(n)}),n.command(`bindings`).description(`List routing bindings`).option(`-a, --agent <id>`,`Filter by agent ID`).option(`-j, --json`,`Output as JSON`).action(async e=>{let n=t();await $t(e)(n)}),n.command(`set-identity`).description(`Set agent identity`).option(`-a, --agent <id>`,`Target agent ID`).option(`-n, --name <name>`,`Agent name`).option(`-e, --emoji <emoji>`,`Agent emoji`).option(`--avatar <path>`,`Avatar path`).action(async e=>{let n=t();await en(e)(n)})}function Z(e){return x.join(e,`workspace`)}function Q(){let e=process.env.AIMAX_PLUGINS_BUNDLED_DIR;return e&&e.trim()||void 0}function nn(e){if(e.length===0){E(`No plugins discovered.`);return}for(let t of e){let e=t.status.padEnd(8,` `);E(`${t.id} ${e} ${t.origin} ${t.source}`)}}function rn(e){E(`id: ${e.id}`),E(`status: ${e.status}`),E(`origin: ${e.origin}`),E(`source: ${e.source}`),E(`enabled: ${e.enabled}`),e.error&&E(`error: ${e.error}`),E(`tools: ${e.toolCount}`),E(`hooks: ${e.hookCount}`),e.skills.length>0&&E(`skills: ${e.skills.join(`, `)}`)}function $(e){return Array.from(new Set((e??[]).map(e=>e.trim()).filter(Boolean)))}function an(e){if(e.length===0){E(`LLM allowlist is empty.`);return}for(let t of e)E(t)}function on(e,t){let n=e.command(`plugins`).description(`Manage AIMax plugins`),r=e=>e.option(`--plugins-config <path>`,`Plugins config file path`);r(n.command(`list`)).description(`List discovered plugins`).option(`-d, --data-dir <path>`,`Data directory path`).action(async e=>{let n=e.dataDir??t();nn(f({config:await A(n,e.pluginsConfig),dataDir:n,workspaceDir:Z(n),bundledDir:Q()}).registry.plugins)}),r(n.command(`info`)).description(`Show plugin details`).argument(`<id>`,`Plugin id`).option(`-d, --data-dir <path>`,`Data directory path`).action(async(e,n)=>{let r=n.dataDir??t(),i=f({config:await A(r,n.pluginsConfig),dataDir:r,workspaceDir:Z(r),bundledDir:Q()}).registry.plugins.find(t=>t.id===e);i||(D(`Plugin not found: ${e}`),process.exit(1)),rn(i)}),r(n.command(`enable`)).description(`Enable a plugin`).argument(`<id>`,`Plugin id`).option(`-d, --data-dir <path>`,`Data directory path`).action(async(e,n)=>{let r=n.dataDir??t(),i=await A(r,n.pluginsConfig)??{},a=re(i);f({config:i,dataDir:r,workspaceDir:Z(r),bundledDir:Q()}).registry.plugins.some(t=>t.id===e)||(D(`Plugin not found: ${e}`),process.exit(1)),await j(r,{...i,entries:{...i.entries,[e]:{...i.entries?.[e]??{},enabled:!0}}},n.pluginsConfig),E(`Enabled ${e}`),a.allow.length>0&&!a.allow.includes(e)&&E(`Note: plugins.allow is set; add this plugin id to allowlist if needed.`)}),r(n.command(`disable`)).description(`Disable a plugin`).argument(`<id>`,`Plugin id`).option(`-d, --data-dir <path>`,`Data directory path`).action(async(e,n)=>{let r=n.dataDir??t(),i=await A(r,n.pluginsConfig)??{};f({config:i,dataDir:r,workspaceDir:Z(r),bundledDir:Q()}).registry.plugins.some(t=>t.id===e)||(D(`Plugin not found: ${e}`),process.exit(1)),await j(r,{...i,entries:{...i.entries,[e]:{...i.entries?.[e]??{},enabled:!1}}},n.pluginsConfig),E(`Disabled ${e}`)}),r(n.command(`doctor`)).description(`Validate plugin configuration`).option(`-d, --data-dir <path>`,`Data directory path`).action(async e=>{let n=e.dataDir??t(),r=f({config:await A(n,e.pluginsConfig),dataDir:n,workspaceDir:Z(n),bundledDir:Q()});if(r.diagnostics.length===0){E(`No plugin issues detected.`);return}for(let e of r.diagnostics)E(`${e.level===`error`?`ERROR`:`WARN`}${e.pluginId?` ${e.pluginId}`:``}: ${e.message}`);r.diagnostics.some(e=>e.level===`error`)&&process.exit(1)});let i=n.command(`llm-allow`).description(`Manage plugin LLM allowlist`);r(i.command(`list`)).description(`List LLM allowlist entries`).option(`-d, --data-dir <path>`,`Data directory path`).action(async e=>{an($((await A(e.dataDir??t(),e.pluginsConfig))?.llmAllowlist))}),r(i.command(`add`)).description(`Add entries to the LLM allowlist (plugin id or tool name)`).argument(`<entry...>`,`Plugin id or tool name`).option(`-d, --data-dir <path>`,`Data directory path`).action(async(e,n)=>{let r=n.dataDir??t(),i=await A(r,n.pluginsConfig)??{},a=$([...i.llmAllowlist??[],...e]);await j(r,{...i,llmAllowlist:a},n.pluginsConfig),E(`LLM allowlist updated (${a.length} entries).`)}),r(i.command(`remove`)).description(`Remove entries from the LLM allowlist`).argument(`<entry...>`,`Plugin id or tool name`).option(`-d, --data-dir <path>`,`Data directory path`).action(async(e,n)=>{let r=n.dataDir??t(),i=await A(r,n.pluginsConfig)??{},a=new Set(e.map(e=>e.trim()).filter(Boolean)),o=$(i.llmAllowlist).filter(e=>!a.has(e));await j(r,{...i,llmAllowlist:o},n.pluginsConfig),E(`LLM allowlist updated (${o.length} entries).`)}),r(i.command(`clear`)).description(`Clear the LLM allowlist`).option(`-d, --data-dir <path>`,`Data directory path`).action(async e=>{let n=e.dataDir??t();await j(n,{...await A(n,e.pluginsConfig)??{},llmAllowlist:[]},e.pluginsConfig),E(`LLM allowlist cleared.`)})}function sn(e){e.command(`commands`).description(`List available slash commands for a data directory`).requiredOption(`-d, --data-dir <path>`,`Data directory path`).option(`--output <format>`,`Output format: text (default) or json`,`text`).action(async e=>{let t=e.output===`json`?`json`:`text`;try{let n=m(await te(e.dataDir,[]));if(t===`json`){E(JSON.stringify(n,null,2));return}E(`Commands`),E(` builtin: ${n.builtin.map(e=>e.name).join(` | `)}`),n.skillCommands.length>0?E(` skills: ${n.skillCommands.map(e=>e.name).join(` | `)}`):E(` skills: (none)`)}catch(e){D(`Error listing commands: ${e.message}`),process.exit(1)}})}const cn=[`progress`,`error`,`hitl`];function ln(e){let t=e.dataDir??process.env.AIMAX_DATA_DIR;if(!t)throw Error(`Data directory must be specified via --data-dir or AIMAX_DATA_DIR`);return t}function un(e){if(!e?.trim())return new Set(cn);let t=e.split(`,`).map(e=>e.trim().toLowerCase()).filter(Boolean),n=new Set([`start`,`text`,`progress`,`done`,`error`,`hitl`,`title_updated`]),r=new Set;for(let e of t){if(!n.has(e))throw Error(`Invalid stream event: ${e}. Must be one of start,text,progress,done,error,hitl`);r.add(e)}return r.size>0?r:new Set(cn)}function dn(e){return e?_(e):void 0}function fn(e){let t=[];return e.callbackUrl&&t.push(new V(e.callbackUrl)),e.streamUrl&&t.push(new W(e.streamUrl,un(e.streamEvents),e.streamAuthToken)),new B(t)}async function pn(e){L(ln(e));let t=new z(`cancel command`),n=ln(e),r=e.channel??`WEB`,i=e.output===`json`?`json`:`text`,a=fn(e),o=dn(e.sessionStore);try{let s=await g(n,e.sessionId,{storeName:o});if(!s)throw Error(`No pending HITL request found for session "${e.sessionId}"`);let c=e.requestId??s.request.requestId;if(s.request.requestId!==c)throw Error(`Request ID mismatch: pending is "${s.request.requestId}", got "${c}"`);if(!(await ae({dataDir:n,sessionStoreName:o,sessionId:e.sessionId,requestId:c,resolution:{requestId:c,sessionId:e.sessionId,action:`cancel`,submittedAt:new Date().toISOString(),submittedBy:{channel:r}}})).state)throw Error(`Failed to cancel HITL request`);let l={type:`hitl_cancelled`,sessionId:e.sessionId,requestId:c,reason:e.reason??`cancelled by operator`};i===`text`&&O(l),await a.send({type:`progress`,sessionId:e.sessionId,channel:r,messageId:e.messageId,event:l}),t.end(),process.exit(0)}catch(n){let i=n;await a.send({type:`error`,sessionId:e.sessionId,channel:r,messageId:e.messageId,message:i.message}),R.error(`cancel command error: ${i.message}`),D(`Fatal: ${i.message}`),t.end(),process.exit(1)}finally{await a.close()}}function mn(e){e.command(`cancel`).description(`Cancel a pending HITL request`).requiredOption(`-d, --data-dir <path>`,`Data directory path`).requiredOption(`-s, --session-id <id>`,`Session ID containing the pending HITL request`).option(`--session-store <name>`,`Session store directory under .aimax (default: sessions)`).option(`--request-id <id>`,`HITL request ID to cancel`).option(`--reason <text>`,`Human-readable cancel reason`).option(`-c, --channel <channel>`,`Channel type (default: WEB)`,`WEB`).option(`--callback-url <url>`,`HTTP callback URL for progress events`).option(`--stream-url <url>`,`WebSocket URL for streaming text events`).option(`--stream-auth-token <token>`,`Auth token for WebSocket streaming`).option(`--stream-events <list>`,`Comma-separated stream events`).option(`--message-id <id>`,`Message ID for correlating events`).option(`--output <format>`,`Output format: text (default) or json`,`text`).action(async e=>{await pn(e)})}const hn=e(import.meta.url)(`../package.json`);function gn(){return process.env.AIMAX_DATA_DIR||process.cwd()}function _n(){let e=new t;return e.name(`aimax`).description(`AIMax CLI — runs agent tasks in a containerized environment`).version(hn.version),Ut(e),ft(e),mn(e),Wt(e),sn(e),Oe(e),Kt(e),tn(e,gn),on(e,gn),e}export{Je as a,R as i,gn as n,L as r,_n as t};
package/dist/program.js CHANGED
@@ -1 +1 @@
1
- import{n as e,t}from"./program-PSkNAIli.js";export{t as createProgram,e as getDataDir};
1
+ import{n as e,t}from"./program-DcFUveRe.js";export{t as createProgram,e as getDataDir};
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@gencode/cli",
3
- "version": "0.0.55",
3
+ "version": "0.1.0",
4
4
  "type": "module",
5
5
  "bin": {
6
6
  "aimax": "./dist/bin.js"
@@ -22,8 +22,8 @@
22
22
  "commander": "^14.0.3",
23
23
  "gensign-node": "latest",
24
24
  "log4js": "^6.9.1",
25
- "@gencode/shared": "0.1.0",
26
- "@gencode/agents": "0.1.1"
25
+ "@gencode/agents": "0.2.0",
26
+ "@gencode/shared": "0.1.0"
27
27
  },
28
28
  "devDependencies": {
29
29
  "@types/node": "^22.0.0",