@gencode/cli 0.6.10 → 0.7.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,24 @@
1
1
  # @gencode/cli
2
2
 
3
+ ## 0.7.0
4
+
5
+ ### Minor Changes
6
+
7
+ - dd8966e: Add Anthropic Messages API format support for AIMax runs. Users can keep the existing OpenAI-compatible default or set `AIMAX_API_FORMAT=anthropic-messages` / `--api-format anthropic-messages` with an Anthropic-compatible base URL, API key, and model. Agent turns, subagents, history compaction, topic segmentation, title generation, plugin LLM access, CLI runs, CLI resume, summarize, and Console-spawned runs now inherit the selected API format.
8
+
9
+ ### Patch Changes
10
+
11
+ - c2278fa: When the LLM returns a recognizable context-limit error (typically HTTP 400, including messages such as `请求上下文过大`), a single `aimax run` now automatically performs emergency history compaction and retries the current turn before exiting. Each turn allows one compaction plus one retry; each run allows up to two compactions shared by the main agent and subagents. If recovery succeeds, the run completes normally (`exit 0`) and active goals continue as before. If compaction is skipped or the retry still fails, the run exits with `exit 1` and an error message that notes emergency compaction was attempted and suggests `/compact` or reducing tool output. Non-context errors (for example invalid API keys) are not retried via this path.
12
+ - b620dae: Improve `aimax --encrypt-sessions` observability and cleanup. The CLI now records detailed `.aimax` encryption logs for gocryptfs dependency checks, first-time migration, backup restore, mount setup, and shutdown cleanup, and it verifies `/proc/self/mountinfo` after unmount commands so stale encrypted `.aimax` mounts can be retried with lazy `fusermount` and `umount` fallbacks before the process exits.
13
+ - d747bbd: Localize AIMax `/goal` user-facing guidance and status messages for Chinese-first users while keeping the `/goal`, `/goal pause`, `/goal resume`, `/goal clear`, and `--token-budget` command syntax unchanged. The empty-goal help now includes examples that show how to write both the objective and clear completion criteria together, so goal completion is guided by verifiable conditions such as test results and bug reproduction checks.
14
+ - 2f4d004: Topic segmentation now maintains Flash-generated conversation segments, stores segment embeddings in a session-level `topic-segments.sqlite` vector index, and uses a local `transformers.js` embedding model from the mounted `model/` directory to retrieve older relevant topics before final classification. Long IM-style sessions can now return to much older topics more reliably while still preserving the existing transcript files, fallback behavior, and CLI usage. Online Flash rerank and turn-supplement fallbacks now share an 8-second request budget; when that budget is exhausted, AIMax immediately returns the local retrieval result instead of waiting longer on remote model calls.
15
+ - Updated dependencies [c2278fa]
16
+ - Updated dependencies [e84813b]
17
+ - Updated dependencies [dd8966e]
18
+ - Updated dependencies [d747bbd]
19
+ - Updated dependencies [2f4d004]
20
+ - @gencode/agents@0.9.0
21
+
3
22
  ## 0.6.10
4
23
 
5
24
  ### 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-DDYm7FET.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-BxoNJefy.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{};
@@ -0,0 +1,15 @@
1
+ import{createRequire as e}from"node:module";import{Command as t}from"commander";import{GoalConflictError as n,applyCliGoalBeforeRun as r,bootstrapMountLayout as i,buildAimaxGoalCliHelpExtra as a,buildResumeNarration as o,clearPendingUiTool as s,createBuiltinMemoryProvider as c,deleteGoal as l,ensureBootstrapMountLayout as u,exportSession as d,formatApprovalResolution as f,formatClarifyResolution as p,formatReviewResolution as m,hasBootstrapSentinel as h,initializePluginSystem as g,inspectSession as _,listAvailableSlashCommands as v,listSessionSummaries as ee,loadPendingHitl as te,loadPendingUiTool as ne,loadSkillsWithPluginDirs as re,loadTranscript as ie,normalizePluginsConfig as ae,normalizeSessionStoreName as y,readGoal as b,resolveGoalObjective as oe,resolveMemoryProvider as se,resolvePendingHitl as ce,resolvePendingUiTool as le,rewriteTranscript as ue,runAgent as de,updateGoal as fe,writeGoal as pe}from"@gencode/agents";import{formatTaskForDisplay as me,isAgentDiagnosticEvent as he,isHitlTool as ge,parseMatchedTextToResolution as _e,parseTextToResolution as ve}from"@gencode/shared";import x from"node:fs/promises";import S from"node:fs";import C from"node:path";import ye from"node:os";import{execFile as be,execFileSync as xe}from"node:child_process";import Se from"log4js";import Ce from"gensign-node";import{addAgent as we,addBinding as Te,getAgentConfig as w,listAgents as Ee,listBindings as De,loadAgentsConfig as T,normalizeAgentId as Oe,removeAgent as ke,removeBindings as Ae,resolveAgentDir as je,resolveDefaultAgentId as E,updateAgentIdentity as Me}from"@gencode/agents/config";import{randomUUID as Ne}from"node:crypto";function Pe(e){process.stdout.write(e)}function D(e){process.stdout.write(e+`
2
+ `)}function O(e){process.stderr.write(e+`
3
+ `)}function k(e){switch(e.type){case`start`:D(`\n[start] ${e.message}`);break;case`text`:Pe(e.text);break;case`stream_text_delta`:Pe(e.text);break;case`bootstrap`:D(`\n[bootstrap:${e.phase}] ${e.dataDir}`);break;case`session_reset`:D(`\n[session:${e.action}] ${e.message}`);break;case`tool_start`:D(`\n[tool:${e.name}] ${JSON.stringify(e.input??{})}`);break;case`tool_end`:D(`[tool:${e.name}] ${e.isError?`ERROR`:`OK`} ${e.output.slice(0,200)}`);break;case`compaction`:D(`\n[compaction${e.layer?`:${e.layer}`:``}] ${e.reason}${e.strategy?` (${e.strategy})`:``}`);break;case`skill_used`:D(`\n[skill] ${e.skillName} agent=${e.agent} task=${e.taskId}`);break;case`custom`:D(`\n[plugin:${e.pluginId}] ${e.name}${e.label?` ${e.label}`:``}${e.data?` ${JSON.stringify(e.data)}`:``}`);break;case`error`:O(`\n[error] ${e.message}`);break;case`diagnostic`:break;case`subagent_spawn`:D(`\n[subagent:spawn]${e.label?` "${e.label}"`:``} ${me(e.task)}`);break;case`subagent_complete`:D(`[subagent:${e.status}] ${me(e.task)}`);break;case`hitl_requested`:if(D(`\n[hitl:${e.request.kind}] ${e.request.title}`),D(` prompt: ${e.request.prompt}`),D(` requestId: ${e.request.requestId}`),e.request.input.mode===`choice`)for(let t of e.request.input.choices)D(` - [${t.id}] ${t.label}`);break;case`hitl_resumed`:D(`\n[hitl:resumed] requestId=${e.requestId} action=${e.resolution.action}`);break;case`hitl_expired`:D(`\n[hitl:expired] requestId=${e.requestId} reason=${e.reason}`);break;case`hitl_cancelled`:D(`\n[hitl:cancelled] requestId=${e.requestId}${e.reason?` reason=${e.reason}`:``}`);break;case`ui_tool_request`:D(`\n[ui-tool:${e.request.toolName}] ${e.request.outputSchema.title}`),D(` requestId: ${e.request.requestId}`),D(` toolCallId: ${e.request.toolCallId}`);break;case`ui_tool_result`:D(`\n[ui-tool:resumed] requestId=${e.requestId} tool=${e.toolName}`);break}}function Fe(e,t){if(t===`json`){e&&D(JSON.stringify(e,null,2));return}D(`
4
+ `),D(`session: ${e.sessionId}`),D(`duration: ${e.durationMs}ms`),D(`tokens: input=${e.usage.input} output=${e.usage.output} total=${e.usage.total}`),e.context&&(D(`context: ${e.context.snapshotPath}`),D(`tool-results: ${e.context.toolResultsDir}`)),e.error&&O(`error: ${e.error}`)}function Ie(e,t){if(t===`json`){D(JSON.stringify(e,null,2));return}if(e.length===0){D(`No sessions found.`);return}for(let t of e){let e=t.createdAt?new Date(t.createdAt).toLocaleString():`unknown`,n=t.goalStatus?` [GOAL:${t.goalStatus}]`:` [GOAL:—]`;D(`${t.id} ${e} [${t.channel}]${n} ${t.title}`)}}function Le(e,t){if(t===`json`){D(JSON.stringify(e,null,2));return}D(`session: ${e.id}`),e.metadata&&(D(`title: ${e.metadata.title}`),D(`channel: ${e.metadata.channel}`),D(`created: ${e.metadata.createdAt}`),D(`updated: ${e.metadata.updatedAt}`)),D(`transcript: ${e.transcriptPath}`),D(`entries: ${e.transcriptEntryCount}`),D(`context: ${e.contextSnapshotPath}`),D(`session-memory: ${e.sessionMemoryPath}`),D(`collapse-log: ${e.collapseLogPath}`),D(`read-states: ${e.readStateCount}`),D(`tool-results: ${e.toolResultRefCount}`),D(`tool-results-dir: ${e.toolResultsDir}`)}function Re(e,t){if(t===`json`){D(JSON.stringify(e,null,2));return}D(`session: ${e.id}`),D(`transcript: ${e.paths.transcriptPath}`),D(`context: ${e.paths.contextSnapshotPath}`),D(`session-memory: ${e.paths.sessionMemoryPath}`),D(`collapse-log: ${e.paths.collapseLogPath}`),D(`tool-results-dir: ${e.paths.toolResultsDir}`),D(`transcript-entries: ${e.transcript.length}`),D(`read-states: ${e.context.readStates.length}`),D(`tool-results: ${e.context.toolResults.length}`),D(`collapse-spans: ${e.context.compaction.collapseSpans.length}`)}function ze(e,t){if(t===`json`){D(JSON.stringify(e,null,2));return}D(`Bootstrap completed.`),D(`dataDir: ${e.dataDir}`),D(`created dirs: ${e.createdDirs.length}`),D(`created files: ${e.createdFiles.length}`),D(`skipped dirs: ${e.skippedDirs.length}`),D(`skipped files: ${e.skippedFiles.length}`)}function Be(e){let t=new Intl.DateTimeFormat(`en-CA`,{timeZone:`Asia/Shanghai`,year:`numeric`,month:`2-digit`,day:`2-digit`,hour:`2-digit`,minute:`2-digit`,second:`2-digit`,hour12:!1}).formatToParts(e);return Object.fromEntries(t.map(e=>[e.type,e.value]))}function Ve(e=new Date){let t=Be(e),n=String(e.getMilliseconds()).padStart(3,`0`);return`${t.year}-${t.month}-${t.day} ${t.hour}:${t.minute}:${t.second}.${n}`}let A=function(e){return e.INFO=`INFO`,e.ERROR=`ERROR`,e.WARN=`WARN`,e}({}),j=null;function He(){return Ve()}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 C.join(e,`.aimax`)}function Ge(e){return{appLogPath:C.join(e,`app.log`),errorLogPath:C.join(e,`errors.log`)}}function Ke(e){let{appLogPath:t,errorLogPath:n}=Ge(e);Se.configure({appenders:{appFile:{type:`file`,filename:t,maxLogSize:5*1024*1024,backups:3,compress:!0,keepFileExt:!0,layout:{type:`messagePassThrough`}},errorFile:{type:`file`,filename:n,maxLogSize:5*1024*1024,backups:3,compress:!0,keepFileExt:!0,layout:{type:`messagePassThrough`}},errorsOnly:{type:`logLevelFilter`,appender:`errorFile`,level:`error`,maxLevel:`fatal`}},categories:{default:{appenders:[`appFile`,`errorsOnly`],level:`info`}}})}function qe(e,t,n){return`[${He()}] [${e}] ${t}${Ue(n)}`}function Je(e,t,n){process.stderr.write(`${qe(e,t,n)}\n`)}function Ye(e,t,n){if(!j){Je(e,t,n);return}let r=qe(e,t,n),i=Se.getLogger();if(e===A.ERROR){i.error(r);return}if(e===A.WARN){i.warn(r);return}i.info(r)}function M(e){let t=We(e);S.mkdirSync(t,{recursive:!0}),Ke(t),j={dataDir:e,logDir:t}}function Xe(){return j?{...j}:null}async function Ze(){await Se.shutdown()}const N={info:(e,t)=>Ye(A.INFO,e,t),warn:(e,t)=>Ye(A.WARN,e,t),error:(e,t)=>Ye(A.ERROR,e,t)};var P=class{startTime;name;constructor(e){this.name=e,this.startTime=Date.now()}end(){let e=Date.now()-this.startTime;return N.info(`${this.name} completed in ${e}ms`),e}};const Qe=`.aimax`,$e=`${Qe}.pre-gocryptfs.`,et=[`fusermount3`,`fusermount`,`umount`],tt=[{command:`fusermount3`,args:[`-u`],label:`fusermount3 -u`},{command:`fusermount3`,args:[`-uz`],label:`fusermount3 -uz`},{command:`fusermount`,args:[`-u`],label:`fusermount -u`},{command:`fusermount`,args:[`-uz`],label:`fusermount -uz`},{command:`umount`,args:[],label:`umount`},{command:`umount`,args:[`-l`],label:`umount -l`}];function nt(e){return C.join(e,`.aimax.enc`)}function rt(e){return C.join(e,Qe)}function it(e){return C.join(e,`${$e}${process.pid}.${Date.now()}`)}function at(e){return e.replace(/\\([0-7]{3})/g,(e,t)=>String.fromCharCode(Number.parseInt(t,8)))}async function ot(e){try{let t=await lt.read(),n=C.resolve(e);for(let e of t.split(`
5
+ `)){if(!e.trim())continue;let t=e.split(` `);if(t.length>=5&&C.resolve(at(t[4]??``))===n)return!0}return!1}catch{return!1}}function st(e){try{let t=S.readFileSync(`/proc/self/mountinfo`,`utf-8`),n=C.resolve(e);for(let e of t.split(`
6
+ `)){if(!e.trim())continue;let t=e.split(` `);if(t.length>=5&&C.resolve(at(t[4]??``))===n)return!0}return!1}catch{return!1}}async function ct(){return await x.readFile(`/proc/self/mountinfo`,`utf-8`)}const lt={read:ct};async function F(e){try{return await x.stat(e),!0}catch(e){if(e.code===`ENOENT`)return!1;throw e}}async function I(e){await x.mkdir(e,{recursive:!0})}async function ut(e){if(await I(e),(await x.readdir(e)).length>0)throw Error(`Refusing to mount encrypted .aimax over non-empty directory: ${e}. Clear stale plaintext files or disable --encrypt-sessions for this run.`)}async function dt(e){return await F(e)?(await x.readdir(e)).length===0:!0}async function ft(e){if(!await F(C.join(e,`gocryptfs.conf`)))throw Error(`Encrypted .aimax directory exists but is not initialized: ${e}. Remove the incomplete .aimax.enc directory or restore it from backup before retrying --encrypt-sessions.`)}async function pt(e){return(await x.readdir(e,{withFileTypes:!0})).filter(e=>e.isDirectory()&&e.name.startsWith($e)).map(t=>C.join(e,t.name)).sort()}async function L(e,t){if(!await F(t))return null;let n=it(e);return N.info(`--encrypt-sessions moving plaintext .aimax aside before migration`,{plainDir:t,backupDir:n}),await x.rename(t,n),n}async function R(e,t,n){N.info(`--encrypt-sessions copying plaintext backup into encrypted mount`,{backupDir:e,plainDir:t,force:n}),await x.cp(e,t,{recursive:!0,force:n})}async function mt(e){let t=C.join(ye.tmpdir(),`aimax-gocryptfs-pass.${process.pid}.${Date.now()}`);await x.writeFile(t,`wizard_aimax@2026
7
+ `,{mode:384});try{return await e(t)}finally{await x.rm(t,{force:!0})}}async function ht(e){let t=e.includes(`-init`)?`init`:`mount`;N.info(`--encrypt-sessions starting gocryptfs ${t}`);try{await Ct(`gocryptfs`,e),N.info(`--encrypt-sessions completed gocryptfs ${t}`)}catch(n){let r=n instanceof Error?n.message:String(n);throw N.warn(`--encrypt-sessions failed gocryptfs ${t}`,{error:r}),Error(`gocryptfs ${e.join(` `)} failed: ${r}`)}}async function gt(){N.info(`--encrypt-sessions checking encryption dependencies`),await Tt(`gocryptfs`,`required for --encrypt-sessions`),N.info(`--encrypt-sessions dependency available`,{command:`gocryptfs`});for(let e of et)if(await wt(e)){N.info(`--encrypt-sessions unmount dependency available`,{command:e});return}throw Error(`--encrypt-sessions requires one of ${et.join(`, `)} to be installed for secure unmount cleanup.`)}async function _t(e,t){N.info(`--encrypt-sessions mounting encrypted .aimax`,{encryptedDir:e,plainDir:t}),await mt(async n=>{await ht([`-q`,`-passfile`,n,e,t])})}async function vt(e){N.info(`--encrypt-sessions initializing encrypted .aimax directory`,{encryptedDir:e}),await mt(async t=>{await ht([`-q`,`-init`,`-passfile`,t,e])})}async function yt(e){let t=[];N.info(`--encrypt-sessions unmounting encrypted .aimax`,{plainDir:e});for(let n of tt)try{if(N.info(`--encrypt-sessions attempting encrypted .aimax unmount`,{command:n.label,plainDir:e}),await Ct(n.command,[...n.args,e]),!await ot(e)){N.info(`--encrypt-sessions unmounted encrypted .aimax`,{command:n.label,plainDir:e});return}let r=`${n.label} returned success but ${e} is still mounted`;t.push(r),N.warn(`--encrypt-sessions unmount command returned success but mountpoint remains`,{command:n.label,plainDir:e})}catch(r){let i=Et(n.label,r);t.push(i),N.warn(`--encrypt-sessions unmount attempt failed`,{command:n.label,plainDir:e,error:r instanceof Error?r.message:String(r)})}throw Error(`Failed to unmount ${e}: ${t.join(`; `)}`)}function bt(e){for(let t of tt)try{if(xe(t.command,[...t.args,e],{stdio:`ignore`}),!st(e))return}catch{}}function xt(e){let t=!1,n=()=>{t||(t=!0,bt(e))},r=()=>n(),i=()=>{n(),process.exit(130)},a=()=>{n(),process.exit(143)};return process.once(`exit`,r),process.once(`SIGINT`,i),process.once(`SIGTERM`,a),{release(){process.removeListener(`exit`,r),process.removeListener(`SIGINT`,i),process.removeListener(`SIGTERM`,a)}}}async function St(e){let t=nt(e),n=rt(e);N.info(`--encrypt-sessions preparing encrypted .aimax mount`,{dataDir:e,encryptedDir:t,plainDir:n});let r=()=>({mounted:!1,plainDir:n,encryptedDir:t,async cleanup(){}});try{await gt()}catch(e){return N.warn(`--encrypt-sessions is unavailable; continuing with plaintext .aimax`,{error:e instanceof Error?e.message:String(e)}),await I(n),r()}if(await ot(n))return N.warn(`--encrypt-sessions found existing .aimax mount; continuing without taking ownership`,{plainDir:n}),r();let i=null,a=[],o=null,s=null,c=!1;try{if(a=await pt(e),a.length>0&&N.warn(`--encrypt-sessions found interrupted pre-gocryptfs migration backups`,{count:a.length}),!await F(t))if(N.info(`--encrypt-sessions encrypted .aimax directory does not exist; starting first-time migration`,{encryptedDir:t}),a.length>0?o=await L(e,n):i=await L(e,n),await I(t),await vt(t),await I(n),await _t(t,n),c=!0,s=xt(n),N.info(`--encrypt-sessions mounted encrypted .aimax`,{plainDir:n,encryptedDir:t}),a.length>0){for(let e of a)await R(e,n,!0);o&&=(await R(o,n,!1),await x.rm(o,{recursive:!0,force:!0}),N.info(`--encrypt-sessions removed residual plaintext backup after migration`,{backupDir:o}),null);for(let e of a)await x.rm(e,{recursive:!0,force:!0}),N.info(`--encrypt-sessions removed resumed plaintext migration backup`,{backupDir:e});a=[]}else i&&=(await R(i,n,!0),await x.rm(i,{recursive:!0,force:!0}),N.info(`--encrypt-sessions removed plaintext migration backup`,{backupDir:i}),null);else if(N.info(`--encrypt-sessions encrypted .aimax directory exists; mounting existing encrypted data`,{encryptedDir:t}),await ft(t),a.length>0?o=await L(e,n):await dt(n)||(i=await L(e,n)),await ut(n),await _t(t,n),c=!0,s=xt(n),N.info(`--encrypt-sessions mounted encrypted .aimax`,{plainDir:n,encryptedDir:t}),a.length>0){for(let e of a)await R(e,n,!0);o&&=(await R(o,n,!1),await x.rm(o,{recursive:!0,force:!0}),N.info(`--encrypt-sessions removed residual plaintext backup after migration`,{backupDir:o}),null);for(let e of a)await x.rm(e,{recursive:!0,force:!0}),N.info(`--encrypt-sessions removed resumed plaintext migration backup`,{backupDir:e});a=[]}else i&&=(await R(i,n,!0),await x.rm(i,{recursive:!0,force:!0}),N.info(`--encrypt-sessions removed plaintext migration backup`,{backupDir:i}),null);return{mounted:c,plainDir:n,encryptedDir:t,async cleanup(){if(s?.release(),c){c=!1,N.info(`--encrypt-sessions cleanup started`,{plainDir:n,encryptedDir:t});try{await yt(n),N.info(`--encrypt-sessions cleanup completed`,{plainDir:n,encryptedDir:t})}catch(e){N.warn(`--encrypt-sessions failed to unmount encrypted .aimax; continuing shutdown`,{error:e instanceof Error?e.message:String(e)})}}}}}catch(e){return s?.release(),c&&await yt(n).catch(e=>{N.warn(`--encrypt-sessions failed to unmount during mount rollback`,{error:e instanceof Error?e.message:String(e)})}),i&&await F(i)&&await dt(n)&&(await x.rm(n,{recursive:!0,force:!0}).catch(()=>{}),await x.rename(i,n).catch(()=>{}),N.info(`--encrypt-sessions restored plaintext backup after failed migration`,{backupDir:i,plainDir:n})),o&&await F(o)&&await dt(n)&&(await x.rm(n,{recursive:!0,force:!0}).catch(()=>{}),await x.rename(o,n).catch(()=>{}),N.info(`--encrypt-sessions restored residual plaintext backup after failed migration`,{backupDir:o,plainDir:n})),N.warn(`--encrypt-sessions failed; continuing with plaintext .aimax`,{error:e instanceof Error?e.message:String(e)}),await I(n),r()}}async function z(e,t,n){if(!t.encryptSessions)return n();let r=await St(e);try{return await n()}finally{await r.cleanup()}}async function Ct(e,t){await new Promise((n,r)=>{be(e,t,{encoding:`utf-8`},e=>{if(e){r(e);return}n()})})}async function wt(e){try{return await Ct(`sh`,[`-c`,`command -v "${e}" >/dev/null 2>&1`]),!0}catch{return!1}}async function Tt(e,t){if(!await wt(e))throw Error(`--encrypt-sessions requires ${e}: ${t}.`)}function Et(e,t){return`${e} failed: ${t instanceof Error?t.message:String(t)}`}function Dt(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`).option(`--encrypt-sessions`,`Enable gocryptfs-backed encryption for the .aimax data directory`).action(async e=>{let t=e.output===`json`?`json`:`text`;try{ze(await z(e.dataDir,e,async()=>i(e.dataDir)),t)}catch(e){O(`Error bootstrapping data directory: ${e.message}`),process.exit(1)}})}function Ot(e){return Ce.sm4_encrypt_ecb(e)}function kt(e){return Ot(e)}function At(e={}){let t=jt(e.apiFormat??process.env.AIMAX_API_FORMAT),n=e.baseUrl??process.env.AIMAX_BASE_URL,r=process.env.AIMAX_AUTH_TOKEN,i=e.authToken?kt(e.authToken):r?kt(r):e.apiKey??process.env.AIMAX_API_KEY,a=e.model??process.env.AIMAX_MODEL,o=[];if(n||o.push(`--base-url / AIMAX_BASE_URL`),i||o.push(`--api-key / AIMAX_API_KEY`),a||o.push(`--model / AIMAX_MODEL`),o.length>0)throw Error(`Missing required LLM configuration: ${o.join(`, `)}`);return{apiFormat:t,baseUrl:n,apiKey:i,model:a,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 jt(e){if(!e||e===`openai-completions`||e===`anthropic-messages`)return e;throw Error(`Unsupported LLM API format: ${e}`)}function Mt(e,t){return t?C.resolve(t):C.join(e,`.aimax`,`plugins.json`)}async function B(e,t){let n=Mt(e,t);try{let e=await x.readFile(n,`utf-8`);return JSON.parse(e)}catch(e){if(e.code===`ENOENT`)return;throw e}}async function V(e,t,n){let r=Mt(e,n);await x.mkdir(C.dirname(r),{recursive:!0}),await x.writeFile(r,JSON.stringify(t,null,2),`utf-8`)}function H(e){return typeof e==`object`&&!!e}function Nt(e){return H(e)&&e.type===`text`&&typeof e.text==`string`&&(e.textSignature===void 0||typeof e.textSignature==`string`)}function Pt(e){return H(e)&&e.type===`image`&&typeof e.data==`string`&&typeof e.mimeType==`string`}function Ft(e){return H(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 It(e){return H(e)&&e.type===`toolCall`&&typeof e.id==`string`&&typeof e.name==`string`&&H(e.arguments)&&(e.thoughtSignature===void 0||typeof e.thoughtSignature==`string`)}function Lt(e){return typeof e==`string`||Array.isArray(e)&&e.every(e=>Nt(e)||Pt(e))}function Rt(e){return Array.isArray(e)&&e.every(e=>Nt(e)||Ft(e)||It(e))}function zt(e){return H(e)&&typeof e.input==`number`&&typeof e.output==`number`&&typeof e.cacheRead==`number`&&typeof e.cacheWrite==`number`&&typeof e.totalTokens==`number`&&H(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 Bt(e){return!H(e)||typeof e.role!=`string`?!1:e.role===`user`?Lt(e.content):e.role===`assistant`?Rt(e.content)&&typeof e.api==`string`&&typeof e.provider==`string`&&typeof e.model==`string`&&zt(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=>Nt(e)||Pt(e))&&typeof e.isError==`boolean`:!1}async function Vt(e){let t;try{t=await x.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=>Bt(e)))throw Error(`Message file must contain one Message object or an array of Message objects`);return r}async function Ht(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 Vt(e.fromFile)}:{kind:`text`,message:e.message}}var Ut=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()}))}},Wt=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=Gt(e);N.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 N.error(`callback event failed`,{callbackUrl:this.url,httpStatus:r.status,durationMs:i,...n}),Error(`Callback failed with status ${r.status}`);N.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 Gt(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 Kt(e,t){if(t.kind===`none`)return e;let n=new URL(e);return n.searchParams.set(`authToken`,t.token),n.toString()}function U(){let e=globalThis.WebSocket;if(!e)throw Error(`WebSocket is not available in this runtime`);return e}function qt(e){return e?{kind:`query_token`,token:e}:{kind:`none`}}function Jt(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 Yt(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 Xt=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=U();if(!this.socket||this.socket.readyState!==e.OPEN)return;this.socket.send(JSON.stringify(t))}catch(e){N.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=U();if(!this.socket||this.socket.readyState!==e.OPEN)return;this.socket.send(JSON.stringify(t))}catch(e){N.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=U();e.readyState!==t.CLOSED&&await new Promise(t=>{Jt(e,`close`,()=>t()),e.close()})}async ensureConnected(){if(!this.enabled)return;let e=U();if(this.socket&&this.socket.readyState===e.OPEN)return;if(this.connectPromise){await this.connectPromise;return}let t=new e(Kt(this.url,qt(this.authToken)));this.connectPromise=new Promise((e,n)=>{Jt(t,`open`,()=>{this.socket=t,Yt(t,`close`,()=>{this.socket===t&&(this.socket=null)}),e()}),Jt(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)}`)}}}};function Zt(e){let t=e.trim();if(!t)throw Error(`Goal objective cannot be empty`);return t}function Qt(e,t){if(t.action===`unchanged`)return null;if(t.action===`created`||t.action===`replaced`)return t.action;if(e?.status!==t.goal.status)switch(t.goal.status){case`active`:return e?.status===`paused`?`resumed`:`updated`;case`paused`:return`paused`;case`complete`:return`completed`;case`budget_limited`:return`budget_limited`;default:return`updated`}return`updated`}function $t(e){let t=Qt(e.before,e.result);return t?{type:`goal_updated`,sessionId:e.sessionId,action:t,goalId:e.result.goal.goalId,goalStatus:e.result.goal.status}:null}const en=[`start`,`text`,`done`,`error`,`hitl`],tn=[`off`,`gate`,`dry_run`,`write`];function nn(e){if(!e?.trim())return new Set(en);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(en)}function rn(e){return e.disableTopicSegmentation===!0||process.env.AIMAX_DISABLE_TOPIC_SEGMENTATION===`true`?{enabled:!1}:void 0}function an(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 on(e){return e?.trim()||void 0}function sn(e){let t=(e.systemAgentsDir??process.env.AIMAX_SYSTEM_AGENTS_DIR)?.trim();if(t){if(!C.isAbsolute(t)){let n=e.systemAgentsDir===void 0?`AIMAX_SYSTEM_AGENTS_DIR`:`--system-agents-dir`;throw Error(`Invalid ${n}: ${t}. Path must be absolute.`)}return t}}function cn(e){return e?y(e):void 0}function ln(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(!C.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 un(e,t){if(e===void 0)return;let n=e.trim().toLowerCase();if(n){if([`true`,`1`,`yes`,`on`].includes(n))return!0;if([`false`,`0`,`no`,`off`].includes(n))return!1;throw Error(`Invalid ${t}: ${e}. Must be true or false.`)}}function dn(e,t){if(e===void 0)return;let n=e.trim().toLowerCase();if(n){if(tn.includes(n))return n;throw Error(`Invalid ${t}: ${e}. Must be one of off,gate,dry_run,write.`)}}function fn(e){let t=e.autoSkillsLoadEnabled===void 0?un(process.env.AIMAX_AUTO_SKILLS_LOAD_ENABLED,`AIMAX_AUTO_SKILLS_LOAD_ENABLED`):un(e.autoSkillsLoadEnabled,`--auto-skills-load-enabled`),n=e.autoSkillsReviewMode===void 0?dn(process.env.AIMAX_AUTO_SKILLS_REVIEW_MODE,`AIMAX_AUTO_SKILLS_REVIEW_MODE`):dn(e.autoSkillsReviewMode,`--auto-skills-review-mode`),r={};return t!==void 0&&(r.load={enabled:t}),n!==void 0&&(r.review={mode:n}),r.load||r.review?r:void 0}function pn(e,t){if(e.inputText&&t){let n=ve(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 mn(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 hn(e){let t=await ie(e.dataDir,e.sessionId,{storeName:e.sessionStoreName,encryptSessions:e.encryptSessions});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 gn(e){let t=an(e),n=e.channel??`WEB`,r=At({apiFormat:e.apiFormat,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,systemAgentsDir:sn(e),channel:n,format:e.output===`json`?`json`:`text`,timeoutMs:e.timeout?Number(e.timeout):void 0,llm:r,skillsLoadPaths:ln(e.skillsLoadPaths),autoSkills:fn(e)}}function _n(e){let t=[],n=null;return e.callbackUrl&&t.push(new Wt(e.callbackUrl)),e.streamUrl&&(n=new Xt(e.streamUrl,nn(e.streamEvents),e.streamAuthToken),t.push(n)),{sink:new Ut(t),websocketSink:n}}async function vn(e){let{dataDir:t,sessionId:n,sessionStoreName:r,toolCallId:i,toolName:a,resolution:o,encryptSessions:s}=e;if(!i||!a||!ge(a))return;let c=(e,t)=>{switch(e){case`request_approval`:return f(t);case`clarify`:return p(t);case`request_review`:return m(t);default:return JSON.stringify({action:t.action,values:t.values})}};await ue(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:c(a,o),isError:!1},n},{storeName:r,encryptSessions:s})}async function yn(e){let{dataDir:t,sessionId:n,sessionStoreName:r,result:i,encryptSessions:a}=e;await ue(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,encryptSessions:a})}async function bn(e){let t=an(e);await z(t,e,async()=>{M(t);let i=new P(`resume command`),a=null;try{let t=await gn(e),o=cn(e.sessionStore),c=null;if(e.goal||e.goalFile){let i;i=e.goalFile?await x.readFile(e.goalFile,`utf-8`):e.goal;let a=Zt(i),s=e.tokenBudget===void 0?void 0:e.tokenBudget===`0`||e.tokenBudget===``?null:Number(e.tokenBudget);s!=null&&(Number.isNaN(s)||s<=0)&&(O(`error: --token-budget must be a positive integer, or 0 for unlimited`),process.exit(1));try{let n=await b(t.dataDir,e.sessionId,{storeName:o}),i=await r({dataDir:t.dataDir,sessionId:e.sessionId,objective:a,tokenBudget:s,force:e.force,storeName:o});c=$t({sessionId:e.sessionId,before:n,result:i})}catch(e){throw e instanceof n&&(O(e.message),O(`Existing: ${e.existingObjectivePreview}`),process.exit(2)),e}}N.info(`resume command started`,{sessionId:e.sessionId,requestId:e.requestId,channel:t.channel,dataDir:t.dataDir});let l=await te(t.dataDir,e.sessionId,{storeName:o,encryptSessions:e.encryptSessions}),u=l?null:await ne(t.dataDir,e.sessionId,{storeName:o,encryptSessions:e.encryptSessions});if(!l&&!u)throw Error(`No pending HITL or UI tool request found for session "${e.sessionId}"`);if(l){if(l.request.requestId!==e.requestId)throw Error(`Request ID mismatch: pending is "${l.request.requestId}", got "${e.requestId}"`);if(l.status===`expired`)throw Error(`HITL request has expired`);if(l.status===`cancelled`)throw Error(`HITL request has been cancelled`)}else if(u){if(u.request.requestId!==e.requestId)throw Error(`Request ID mismatch: pending is "${u.request.requestId}", got "${e.requestId}"`);if(u.status!==`pending`)throw Error(`UI tool request is already "${u.status}", cannot resume`)}if(l){let n=pn(e,l.request),r=await ce({dataDir:t.dataDir,sessionStoreName:o,sessionId:e.sessionId,requestId:e.requestId,resolution:n}),s=r.state;if(!s)throw Error(`Resolved HITL state was not persisted`);let u=xn(n,s.request.kind);await vn({dataDir:t.dataDir,sessionId:e.sessionId,sessionStoreName:o,toolCallId:s.toolContext?.toolCallId,toolName:s.toolContext?.toolName,resolution:n,encryptSessions:e.encryptSessions});let d=_n(e);a=d.sink;let f=e.sessionId,p=async n=>{if(f=n.sessionId??f,!he(n)){if(n.type===`stream_text_delta`){t.format===`text`&&k(n),await d.websocketSink?.sendTextDelta({sessionId:f,channel:t.channel,messageId:e.messageId,user:e.user,text:n.text});return}t.format===`text`&&k(n),await a?.send({sessionId:f,channel:t.channel,messageId:e.messageId,user:e.user,type:`progress`,event:n})}};c&&await p(c),await p({type:`hitl_resumed`,requestId:e.requestId,resolution:n,sessionId:e.sessionId}),`idempotentReplay`in r&&r.idempotentReplay&&(N.info(`resume command treated as idempotent replay`,{sessionId:e.sessionId,requestId:e.requestId,idempotencyKey:n.idempotencyKey}),Fe({sessionId:e.sessionId,text:`Resume request already processed.`,usage:{input:0,output:0,total:0},durationMs:0},t.format),i.end(),process.exit(0));let m=e.pluginsConfig??process.env.AIMAX_PLUGINS_CONFIG,h=await B(t.dataDir,m),g;try{g=await de({dataDir:t.dataDir,projectDir:on(e.projectDir),systemAgentsDir:t.systemAgentsDir,sessionStoreName:o,sessionId:e.sessionId,messageId:e.messageId,channel:t.channel,llm:t.llm,skillsLoadPaths:t.skillsLoadPaths,autoSkills:t.autoSkills,timeoutMs:t.timeoutMs,message:u,encryptSessions:e.encryptSessions??!1,topicSegmentation:rn(e),hitlResume:{request:s.request,resolution:n,checkpoint:s.checkpoint,toolContext:s.toolContext},plugins:h?{config:h,dataDir:t.dataDir,workspaceDir:C.join(t.dataDir,`workspace`),bundledDir:process.env.AIMAX_PLUGINS_BUNDLED_DIR,llmAllowlist:h.llmAllowlist}:void 0,onProgress:p})}finally{}g.error?await a?.send({sessionId:g.sessionId,channel:t.channel,messageId:e.messageId,user:e.user,type:`error`,message:g.error}):await a?.send({sessionId:g.sessionId,channel:t.channel,messageId:e.messageId,user:e.user,type:`done`,result:{text:g.text,usage:g.usage,durationMs:g.durationMs,error:g.error,paused:g.paused,uiToolPending:g.uiToolPending}}),Fe(g,t.format),g.error?N.error(`resume command failed: ${g.error}`):N.info(`resume command succeeded`),i.end(),process.exit(g.error?1:0);return}let d=mn(e,u);if(!await le(t.dataDir,e.sessionId,e.requestId,d,{storeName:o,encryptSessions:e.encryptSessions}))throw Error(`UI tool resume validation failed`);await yn({dataDir:t.dataDir,sessionId:e.sessionId,sessionStoreName:o,result:d,encryptSessions:e.encryptSessions});let f=_n(e);a=f.sink;let p=e.sessionId,m=async n=>{if(p=n.sessionId??p,!he(n)){if(n.type===`stream_text_delta`){t.format===`text`&&k(n),await f.websocketSink?.sendTextDelta({sessionId:p,channel:t.channel,messageId:e.messageId,user:e.user,text:n.text});return}if(t.format===`text`&&k(n),n.type===`start`){await a?.send({sessionId:p,channel:t.channel,messageId:e.messageId,user:e.user,type:`start`,message:n.message});return}await a?.send({sessionId:p,channel:t.channel,messageId:e.messageId,user:e.user,type:`progress`,event:n})}},h=await hn({dataDir:t.dataDir,sessionId:e.sessionId,sessionStoreName:o,toolCallId:d.toolCallId,toolName:d.toolName,encryptSessions:e.encryptSessions});c&&await m(c),await m({type:`tool_end`,sessionId:e.sessionId,toolCallId:d.toolCallId,name:d.toolName,input:h,output:JSON.stringify({submitted:!0,values:d.values}),isError:!1});let g=e.pluginsConfig??process.env.AIMAX_PLUGINS_CONFIG,_=await B(t.dataDir,g),v=await de({dataDir:t.dataDir,projectDir:on(e.projectDir),systemAgentsDir:t.systemAgentsDir,sessionStoreName:o,sessionId:e.sessionId,messageId:e.messageId,channel:t.channel,llm:t.llm,skillsLoadPaths:t.skillsLoadPaths,autoSkills:t.autoSkills,timeoutMs:t.timeoutMs,message:`[UI_TOOL_RESUME]
8
+ The pending UI tool result has been written into the transcript. Continue from the latest tool result without repeating the same form request.`,encryptSessions:e.encryptSessions??!1,topicSegmentation:rn(e),uiToolResume:d,plugins:_?{config:_,dataDir:t.dataDir,workspaceDir:C.join(t.dataDir,`workspace`),bundledDir:process.env.AIMAX_PLUGINS_BUNDLED_DIR,llmAllowlist:_.llmAllowlist}:void 0,onProgress:m});await s(t.dataDir,e.sessionId,{storeName:o,encryptSessions:e.encryptSessions}),v.error?await a?.send({sessionId:v.sessionId,channel:t.channel,messageId:e.messageId,user:e.user,type:`error`,message:v.error}):await a?.send({sessionId:v.sessionId,channel:t.channel,messageId:e.messageId,user:e.user,type:`done`,result:{text:v.text,usage:v.usage,durationMs:v.durationMs,error:v.error,paused:v.paused,uiToolPending:v.uiToolPending}}),Fe(v,t.format),v.error?N.error(`resume command failed: ${v.error}`):N.info(`resume command succeeded`),i.end(),process.exit(v.error?1:0)}catch(t){let n=t;a&&(n.message.includes(`expired`)&&await a.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:n.message}}),n.message.includes(`cancelled`)&&await a.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:n.message}}),await a.send({sessionId:e.sessionId,channel:e.channel??`WEB`,messageId:e.messageId,user:e.user,type:`error`,message:`Resume failed: ${n.message}`})),N.error(`resume command error: ${n.message}`),O(`Fatal: ${n.message}`),i.end(),process.exit(1)}finally{await a?.close()}})}function xn(e,t){return o(e,t)}function Sn(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)`).option(`--project-dir <path>`,`Current project directory used as the default cwd context`).option(`--system-agents-dir <path>`,`System agent definition directory (overrides AIMAX_SYSTEM_AGENTS_DIR, default: /aimax/agents)`).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(`--auto-skills-load-enabled <boolean>`,`Enable learned auto-skill loading for the main agent (overrides AIMAX_AUTO_SKILLS_LOAD_ENABLED)`).option(`--auto-skills-review-mode <mode>`,`Auto-skill review mode: off, gate, dry_run, or write (overrides AIMAX_AUTO_SKILLS_REVIEW_MODE)`).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-format <format>`,`LLM API format: openai-completions or anthropic-messages (overrides AIMAX_API_FORMAT)`).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`).option(`--goal <text>`,`Set or replace the thread goal objective before resuming`).option(`--goal-file <path>`,`Read goal objective from a file`).option(`--token-budget <n>`,`Token budget for the goal (positive integer, or 0 for unlimited)`).option(`--force`,`Replace existing goal with a different objective`).option(`--encrypt-sessions`,`Enable encryption for the .aimax data directory`).option(`--disable-topic-segmentation`,`Disable smart topic segmentation for this resume run`).action(async e=>{await bn(e)})}const Cn=[`start`,`text`,`done`,`error`],wn=[`off`,`gate`,`dry_run`,`write`];function Tn(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,title_updated`);r.add(e)}return r.size>0?r:new Set(Cn)}function En(e){return e.disableTopicSegmentation===!0||process.env.AIMAX_DISABLE_TOPIC_SEGMENTATION===`true`?{enabled:!1}:void 0}function Dn(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 On(e){return e?.trim()||void 0}function kn(e){let t=(e.systemAgentsDir??process.env.AIMAX_SYSTEM_AGENTS_DIR)?.trim();if(t){if(!C.isAbsolute(t)){let n=e.systemAgentsDir===void 0?`AIMAX_SYSTEM_AGENTS_DIR`:`--system-agents-dir`;throw Error(`Invalid ${n}: ${t}. Path must be absolute.`)}return t}}function W(e){return e?.trim()||void 0}function An(e){return e??`WEB`}function G(e){return e?y(e):void 0}function jn(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(!C.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 Mn(e,t){if(e===void 0)return;let n=e.trim().toLowerCase();if(n){if([`true`,`1`,`yes`,`on`].includes(n))return!0;if([`false`,`0`,`no`,`off`].includes(n))return!1;throw Error(`Invalid ${t}: ${e}. Must be true or false.`)}}function Nn(e,t){if(e===void 0)return;let n=e.trim().toLowerCase();if(n){if(wn.includes(n))return n;throw Error(`Invalid ${t}: ${e}. Must be one of off,gate,dry_run,write.`)}}function Pn(e){let t=e.autoSkillsLoadEnabled===void 0?Mn(process.env.AIMAX_AUTO_SKILLS_LOAD_ENABLED,`AIMAX_AUTO_SKILLS_LOAD_ENABLED`):Mn(e.autoSkillsLoadEnabled,`--auto-skills-load-enabled`),n=e.autoSkillsReviewMode===void 0?Nn(process.env.AIMAX_AUTO_SKILLS_REVIEW_MODE,`AIMAX_AUTO_SKILLS_REVIEW_MODE`):Nn(e.autoSkillsReviewMode,`--auto-skills-review-mode`),r={};return t!==void 0&&(r.load={enabled:t}),n!==void 0&&(r.review={mode:n}),r.load||r.review?r:void 0}function Fn(e,t){return e.length<=t?e:t<=3?e.slice(0,t):`${e.slice(0,t-3)}...`}function In(e,t){if(t<=0)return[``];let n=[];for(let r=0;r<e.length;r+=t)n.push(e.slice(r,r+t));return n.length>0?n:[``]}function Ln(e,t,n=78){let r=Math.max(0,n-4),i=e?e.length+2:0,a=Math.max(r,i,...t.map(e=>e.length)),o=a+2,s=e?` ${Fn(e,Math.max(0,a-2))} `:``,c=e?`┌${s}${`─`.repeat(Math.max(0,o-s.length))}┐`:`┌${`─`.repeat(o)}┐`,l=`└${`─`.repeat(o)}┘`;return[c,...t.flatMap(e=>In(e,a).map(e=>`│ ${e.padEnd(a,` `)} │`)),l].join(`
9
+ `)}function Rn(e){return e.kind===`text`?`inline message (${e.message.length} chars)`:`message file (${e.messages.length} messages)`}function K(e,t=`-`){return e==null||e===``?t:String(e)}function zn(e){return e?`set`:`unset`}function Bn(e){return e?`true`:`false`}function Vn(e,t){let n=G(e.sessionStore)??`sessions`,r=t.timeoutMs===void 0?`default`:`${t.timeoutMs}`,i=e.callbackUrl?`enabled`:`disabled`,a=e.streamUrl?`enabled`:`disabled`,o=Rn(t.input),s=t.input.kind===`text`?`inline`:e.fromFile??`file`,c=Ve(),l=En(e)?.enabled===!1?`disabled`:`enabled`,u=e.pluginsConfig??process.env.AIMAX_PLUGINS_CONFIG,d=[...Tn(e.streamEvents)].join(`,`),f=t.autoSkills?.load?.enabled,p=t.autoSkills?.review?.mode,m=e.tokenBudget===`0`?`unlimited`:K(e.tokenBudget);return{banner:Ln(void 0,[`AIMax CLI`,`Stateless Agent Runner`]),contextBox:Ln(`Run Context`,[`time : ${c}`,`dataDir : ${t.dataDir}`,`projectDir : ${On(e.projectDir)??`-`}`,`systemAgents : ${t.systemAgentsDir??`/aimax/agents`}`,`agent : ${W(e.agent)??`-`}`,`channel : ${t.channel}`,`user : ${e.user??`-`}`,`message : ${e.message===void 0?`-`:`inline (${e.message.length} chars)`}`,`fromFile : ${K(e.fromFile)}`,`input : ${o}`,`skillsPaths : ${t.skillsLoadPaths.length>0?t.skillsLoadPaths.join(`,`):`-`}`,`autoSkillLoad: ${f===void 0?`-`:String(f)}`,`autoSkillRev : ${p??`-`}`,`sessionId : ${e.sessionId??`new`}`,`sessionStore : ${n}`,`messageId : ${e.messageId??`-`}`,`workspace : ${C.join(t.dataDir,`workspace`)}`,`baseUrl : ${t.llm.baseUrl}`,`apiKey : ${zn(e.apiKey)}`,`authToken : ${zn(e.authToken)}`,`model : ${t.llm.model}`,`contextWindow: ${K(t.llm.contextWindow)}`,`flashModel : ${K(t.llm.flashModel)}`,`callbackUrl : ${K(e.callbackUrl)}`,`streamUrl : ${K(e.streamUrl)}`,`streamAuth : ${zn(e.streamAuthToken)}`,`streamEvents : ${d}`,`output : ${t.format}`,`callback : ${i}`,`websocket : ${a}`,`timeoutMs : ${r}`,`pluginsConfig: ${K(u)}`,`goal : ${e.goal===void 0?`-`:`inline (${e.goal.length} chars)`}`,`goalFile : ${K(e.goalFile)}`,`tokenBudget : ${m}`,`force : ${Bn(e.force)}`,`resumeReqId : ${K(e.resumeRequestId)}`,`resumeInput : ${e.resumeInputJson===void 0?`-`:`inline (${e.resumeInputJson.length} chars)`}`,`resumeFile : ${K(e.resumeFromFile)}`,`encryptSess : ${Bn(e.encryptSessions)}`,`topicSegment : ${l}`]),logContext:{time:c,channel:t.channel,user:e.user,dataDir:t.dataDir,projectDir:On(e.projectDir),systemAgentsDir:t.systemAgentsDir,agent:W(e.agent),workspaceDir:C.join(t.dataDir,`workspace`),sessionId:e.sessionId??`new`,sessionStore:n,messageId:e.messageId,hasMessage:e.message!==void 0,fromFile:e.fromFile,skillsLoadPaths:t.skillsLoadPaths.join(`,`)||void 0,autoSkillsLoadEnabled:f,autoSkillsReviewMode:p,baseUrl:t.llm.baseUrl,hasApiKey:!!e.apiKey,hasAuthToken:!!e.authToken,model:t.llm.model,contextWindow:t.llm.contextWindow,flashModel:t.llm.flashModel,callbackUrl:e.callbackUrl,streamUrl:e.streamUrl,hasStreamAuthToken:!!e.streamAuthToken,streamEvents:d,output:t.format,hasCallback:!!e.callbackUrl,hasStream:!!e.streamUrl,timeoutMs:t.timeoutMs,pluginsConfig:u,hasGoal:e.goal!==void 0,goalFile:e.goalFile,tokenBudget:m===`-`?void 0:m,force:!!e.force,resumeRequestId:e.resumeRequestId,hasResumeInputJson:e.resumeInputJson!==void 0,resumeFromFile:e.resumeFromFile,encryptSessions:!!e.encryptSessions,topicSegmentation:l,inputKind:t.input.kind,inputSource:s,inputSummary:o}}}async function Hn(e,t){let n=Dn(e),r=An(e.channel),i=At({apiFormat:e.apiFormat,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,systemAgentsDir:kn(e),channel:r,format:e.output===`json`?`json`:`text`,timeoutMs:e.timeout?Number(e.timeout):void 0,llm:i,input:t,skillsLoadPaths:jn(e.skillsLoadPaths),autoSkills:Pn(e)}}function Un(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(`
10
+ `)}async function Wn(e,t){if(!e.sessionId)return null;let n=Un(t);if(!n)return null;let r=await te(Dn(e),e.sessionId,{storeName:G(e.sessionStore),encryptSessions:e.encryptSessions});return!r||r.status!==`pending`||!_e(n,r.request)?null:{requestId:r.request.requestId,inputText:n}}function Gn(e){let t=[],n=null;return e.callbackUrl&&t.push(new Wt(e.callbackUrl)),e.streamUrl&&(n=new Xt(e.streamUrl,Tn(e.streamEvents),e.streamAuthToken),t.push(n)),{sink:new Ut(t),websocketSink:n}}async function q(e,t){N.info(`dispatching external event`,ur(t)),await e.sink.send(t)}function Kn(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 qn(e){let t={sessionId:e.sessionId,messageId:e.messageId,parentSessionId:e.parentSessionId,depth:e.depth,scope:e.scope,phase:e.phase,...Kn(e.details)};if(e.level===`error`){N.error(e.message,t);return}if(e.level===`warn`){N.warn(e.message,t);return}N.info(e.message,t)}function Jn(e,t,n,r,i){return{sink:e,websocketSink:t,channel:n,defaultMessageId:r,user:i}}function Yn(){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 Xn(e){return{activeSessionId:e??`pending`,finalResult:null}}function Zn(e,t){e.activeSessionId=t.sessionId??e.activeSessionId}function Qn(e,t){return e.messageId??t}async function $n(e,t,n){if(!await h(e.dataDir)){if(await J(t,e.format,n.activeSessionId,e.dataDir,`checking`),(await u(e.dataDir)).performedBootstrap){await J(t,e.format,n.activeSessionId,e.dataDir,`initializing`),await J(t,e.format,n.activeSessionId,e.dataDir,`initialized`);return}await J(t,e.format,n.activeSessionId,e.dataDir,`ready`)}}async function J(e,t,n,r,i){let a={type:`bootstrap`,phase:i,dataDir:r};t===`text`&&k(a),await q(e,{sessionId:n,channel:e.channel,messageId:e.defaultMessageId,user:e.user,type:`progress`,event:a})}function er(e,t,n){return async r=>{if(Zn(n,r),he(r)){qn(r);return}if(r.type===`stream_text_delta`){e.format===`text`&&k(r),await t.websocketSink?.sendTextDelta({sessionId:n.activeSessionId,channel:e.channel,messageId:Qn(r,t.defaultMessageId),user:t.user,text:r.text});return}e.format===`text`&&k(r);let i=Qn(r,t.defaultMessageId);if(r.type===`hitl_requested`){await q(t,{sessionId:n.activeSessionId,channel:e.channel,messageId:i,user:t.user,type:`hitl`,request:r.request}),await q(t,{sessionId:n.activeSessionId,channel:e.channel,messageId:i,user:t.user,type:`progress`,event:r});return}if(r.type===`start`){await q(t,{sessionId:n.activeSessionId,channel:e.channel,messageId:i,user:t.user,type:`start`,message:r.message});return}if(r.type===`session_reset`){await q(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 q(t,{sessionId:n.activeSessionId,channel:e.channel,messageId:i,user:t.user,type:`progress`,event:r})}}function tr(e,t,n,r,i,a){let o={dataDir:t.dataDir,projectDir:On(e.projectDir),systemAgentsDir:t.systemAgentsDir,agentPolicy:W(e.agent)?{requestedAgentName:W(e.agent)}:void 0,sessionStoreName:G(e.sessionStore),sessionId:e.sessionId,messageId:e.messageId,channel:t.channel,llm:t.llm,skillsLoadPaths:t.skillsLoadPaths,autoSkills:t.autoSkills,timeoutMs:t.timeoutMs,abortSignal:n.signal,pendingGoal:a,encryptSessions:e.encryptSessions??!1,topicSegmentation:En(e),plugins:i?{config:i,dataDir:t.dataDir,workspaceDir:C.join(t.dataDir,`workspace`),bundledDir:process.env.AIMAX_PLUGINS_BUNDLED_DIR,llmAllowlist:i.llmAllowlist}:void 0,onProgress:r};return t.input.kind===`messages`?{...o,messages:t.input.messages}:{...o,message:t.input.message}}async function nr(e,t,n,r){if(t.activeSessionId=r.sessionId,t.finalResult=r,r.error){await q(e,{sessionId:r.sessionId,channel:e.channel,messageId:n,user:e.user,type:`error`,message:r.error});return}await q(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 rr(e,t,n,r){await q(e,{sessionId:t.finalResult?.sessionId??t.activeSessionId,channel:e.channel,messageId:n,user:e.user,type:`error`,message:`Fatal: ${r.message}`})}function ir(e,t){let n=Vn(e,t);N.info([`run command started`,n.banner,n.contextBox].join(`
11
+ `),n.logContext),t.format===`text`&&(D(n.banner),D(``),D(n.contextBox),D(``))}function ar(e,t,n){Fe(t,n),t.error?N.error(`run command failed: ${t.error}`):N.info(`run command succeeded`),e.end(),process.exit(t.error?1:0)}function or(e){let t=Xe();if(!t)return;let n=`[${Ve()}] [ERROR] ${e}\n`;try{S.appendFileSync(C.join(t.logDir,`app.log`),n),S.appendFileSync(C.join(t.logDir,`errors.log`),n)}catch{}}async function sr(e,t){let n=`run command error: ${t.message}`;N.error(n),or(n),O(`Fatal: ${t.message}`),e.end(),await Ze(),process.exit(1)}async function cr(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 x.readFile(e.resumeFromFile,`utf-8`)}catch(e){throw Error(`Failed to read resume input file: ${e.message}`)}}async function lr(e){let t=Dn(e);M(t);let i=new P(`run command`),a=null;try{a=e.encryptSessions?await St(t):null,a&&M(t)}catch(e){await sr(i,e);return}try{let t=await cr(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 bn({dataDir:e.dataDir,projectDir:e.projectDir,systemAgentsDir:e.systemAgentsDir,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,autoSkillsLoadEnabled:e.autoSkillsLoadEnabled,autoSkillsReviewMode:e.autoSkillsReviewMode,messageId:e.messageId,user:e.user,goal:e.goal,goalFile:e.goalFile,tokenBudget:e.tokenBudget,force:e.force,encryptSessions:e.encryptSessions,disableTopicSegmentation:e.disableTopicSegmentation});return}let a;try{a=await Ht({message:e.message,fromFile:e.fromFile})}catch(e){await sr(i,e);return}let o=await Wn(e,a);if(o){await bn({dataDir:e.dataDir,projectDir:e.projectDir,systemAgentsDir:e.systemAgentsDir,sessionId:e.sessionId,sessionStore:e.sessionStore,requestId:o.requestId,inputText:o.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,autoSkillsLoadEnabled:e.autoSkillsLoadEnabled,autoSkillsReviewMode:e.autoSkillsReviewMode,messageId:e.messageId,user:e.user,goal:e.goal,goalFile:e.goalFile,tokenBudget:e.tokenBudget,force:e.force,encryptSessions:e.encryptSessions,disableTopicSegmentation:e.disableTopicSegmentation});return}let{controller:s,cleanup:c}=Yn(),l=null,u=e.channel??`WEB`,d=Xn(e.sessionId);try{let t=await Hn(e,a);u=t.channel,ir(e,t);let o=Gn(e);l=o.sink,N.info(`external sink configured`,{callbackUrl:e.callbackUrl,streamUrl:e.streamUrl,streamEvents:e.streamEvents});let c=Jn(l,o.websocketSink,t.channel,e.messageId,e.user);await $n(t,c,d);let f,p=null;if(e.goal||e.goalFile){let i;i=e.goalFile?await x.readFile(e.goalFile,`utf-8`):e.goal;let a=Zt(i),o=G(e.sessionStore),s=e.tokenBudget===void 0?void 0:e.tokenBudget===`0`||e.tokenBudget===``?null:Number(e.tokenBudget);s!=null&&(Number.isNaN(s)||s<=0)&&(O(`error: --token-budget must be a positive integer, or 0 for unlimited`),process.exit(1));try{if(e.sessionId){let n=await b(t.dataDir,e.sessionId,{storeName:o}),i=await r({dataDir:t.dataDir,sessionId:e.sessionId,objective:a,tokenBudget:s,force:e.force,storeName:o});p=$t({sessionId:e.sessionId,before:n,result:i})}else f={objective:a,tokenBudget:s??null}}catch(e){throw e instanceof n&&(O(e.message),O(`Existing: ${e.existingObjectivePreview}`),process.exit(2)),e}}let m=e.pluginsConfig??process.env.AIMAX_PLUGINS_CONFIG,h=await B(t.dataDir,m),g=er(t,c,d);p&&await g(p);let _=await de(tr(e,t,s,g,h,f));await nr(c,d,e.messageId,_),ar(i,_,t.format)}catch(t){let n=t;l&&await rr(Jn(l,null,u,e.messageId,e.user),d,e.messageId,n),await sr(i,n)}finally{await l?.close(),c()}}finally{await a?.cleanup()}}function ur(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 dr(e){e.command(`run`).description(`Run an agent task`).option(`-d, --data-dir <path>`,`Data directory path (overrides AIMAX_DATA_DIR)`).option(`--project-dir <path>`,`Current project directory used as the default cwd context`).option(`--system-agents-dir <path>`,`System agent definition directory (overrides AIMAX_SYSTEM_AGENTS_DIR, default: /aimax/agents)`).option(`--agent <name>`,`Custom agent name to run as the root agent`).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(`--auto-skills-load-enabled <boolean>`,`Enable learned auto-skill loading for the main agent (overrides AIMAX_AUTO_SKILLS_LOAD_ENABLED)`).option(`--auto-skills-review-mode <mode>`,`Auto-skill review mode: off, gate, dry_run, or write (overrides AIMAX_AUTO_SKILLS_REVIEW_MODE)`).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-format <format>`,`LLM API format: openai-completions or anthropic-messages (overrides AIMAX_API_FORMAT)`).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(`--goal <text>`,`Set or replace the thread goal objective before running`).option(`--goal-file <path>`,`Read goal objective from a file`).option(`--token-budget <n>`,`Token budget for the goal (positive integer, or 0 for unlimited)`).option(`--force`,`Replace existing goal with a different objective`).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)`).option(`--encrypt-sessions`,`Enable gocryptfs-backed encryption for the .aimax data directory`).option(`--disable-topic-segmentation`,`Disable smart topic segmentation for this run`).action(async e=>{await lr(e)})}function fr(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`).option(`--encrypt-sessions`,`Enable gocryptfs-backed encryption for the .aimax data directory`).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||(O(`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`&&(O(`Invalid channel: ${r.channel}. Must be 'H5', 'WEB', 'KLPA', 'TASK', 'CRON', or 'EIP_ASSISTANT'`),process.exit(1));try{await z(r.dataDir,r,async()=>{let e=r.sessionStore?y(r.sessionStore):void 0;if(i===`list`){Ie(await ee(r.dataDir,r.channel,{storeName:e}),a);return}if(r.sessionId||(O(`error: required option '-s, --session-id <id>' not specified`),process.exit(1)),i===`inspect`){Le(await _(r.dataDir,r.sessionId,{storeName:e}),a);return}if(i===`export`){Re(await d(r.dataDir,r.sessionId,{storeName:e}),a);return}O(`Invalid sessions action: ${i}. Must be 'list', 'inspect', or 'export'`),process.exit(1)})}catch(e){O(`${i===`inspect`?`Error inspecting session`:i===`export`?`Error exporting session`:`Error listing sessions`}: ${e.message}`),process.exit(1)}})}function pr(e){return C.join(e,`workspace`)}function mr(){let e=process.env.AIMAX_PLUGINS_BUNDLED_DIR;return e&&e.trim()||void 0}function hr(e,t){let n=[];n.push(`backend: ${e.backend}`),n.push(`provider: ${e.provider}${e.model?` (${e.model})`:``}`);let r=typeof e.custom?.providerSource==`string`?e.custom.providerSource:void 0,i=typeof e.custom?.providerId==`string`?e.custom.providerId:void 0,a=typeof e.custom?.pluginId==`string`?e.custom.pluginId:void 0;r&&n.push(`provider_source: ${r}`),i&&n.push(`provider_id: ${i}`),a&&n.push(`plugin_id: ${a}`),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}`));let o=Array.isArray(e.custom?.cliWarnings)?e.custom.cliWarnings.filter(e=>typeof e==`string`&&e.length>0):[];for(let e of o)n.push(`warning: ${e}`);return n.join(`
12
+ `)}function gr(e){let t=e.level===`error`?`plugin error`:`plugin warning`;return e.pluginId?`${t} (${e.pluginId}): ${e.message}`:`${t}: ${e.message}`}function _r(e){if(!e||e===`cli`)return`cli`;if(e===`cron`)return`cron`;throw Error(`Unsupported dream trigger: ${e}. Expected "cli" or "cron".`)}async function vr(e){let t=[],n;try{n=await B(e.dataDir,e.pluginsConfig)}catch(e){t.push(`failed to load plugins config: ${e.message}`)}if(!e.shouldInitialize&&!n)return{warnings:t};try{let r=g({config:n,dataDir:e.dataDir,workspaceDir:pr(e.dataDir),bundledDir:mr()});return t.push(...r.diagnostics.map(gr)),{pluginSystem:r,warnings:t}}catch(e){return t.push(`failed to initialize plugin system: ${e.message}`),{warnings:t}}}async function yr(e){let t=C.join(e.dataDir,`.aimax`),{pluginSystem:n,warnings:r}=await vr({dataDir:e.dataDir,pluginsConfig:e.pluginsConfig,shouldInitialize:!!(e.requirePluginSystem||e.provider||e.providerPlugin)}),i=n?.normalizedConfig.slots.memory,a=e.providerPlugin?.trim()||(e.provider?void 0:i),o=se({providerId:e.provider,pluginId:a,dataDir:e.dataDir,memoryDir:t});return o?{provider:o.provider,providerId:o.registration.id,pluginId:o.registration.pluginId,providerOrigin:`plugin`,warnings:r,pluginSystem:n}:((a||e.provider)&&r.push(`requested memory provider was not resolved; falling back to builtin provider`),{provider:c({dataDir:e.dataDir,memoryDir:t},{includeSessions:e.includeSessions}),providerId:`builtin`,providerOrigin:`builtin`,warnings:r,pluginSystem:n})}function br(e,t,n){let r={...e.custom??{},providerSource:t.providerOrigin,providerId:t.providerId,pluginId:t.pluginId,cliWarnings:t.warnings},i={...e,custom:r};return n&&t.providerOrigin===`plugin`?i.custom={...r,note:`deep probe details are provider-defined for plugin memory providers`}:n&&(i.custom={...r,note:`deep probe is only supported by builtin provider`}),i}function xr(e){let t=e.command(`memory`).description(`Manage semantic memory indexing and search`),n=e=>e.option(`--plugins-config <path>`,`Plugins config file path`);n(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`).option(`--encrypt-sessions`,`Enable gocryptfs-backed encryption for the .aimax data directory`).action(async e=>{let t=e.output===`json`?`json`:`text`;try{await z(e.dataDir,e,async()=>{let n=await yr({dataDir:e.dataDir,provider:e.provider,providerPlugin:e.providerPlugin,pluginsConfig:e.pluginsConfig,includeSessions:e.includeSessions});e.index&&n.provider.sync&&await n.provider.sync(`cli-status`);let r=br(n.provider.status(),n,e.deep);D(t===`json`?JSON.stringify(r,null,2):hr(r,e.deep))})}catch(e){O(`Error getting memory status: ${e.message}`),process.exit(1)}}),n(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(`--rebuild`,`Force full rebuild from Markdown source`).option(`--verbose`,`Verbose output`).option(`--encrypt-sessions`,`Enable gocryptfs-backed encryption for the .aimax data directory`).action(async e=>{try{await z(e.dataDir,e,async()=>{let t=await yr({dataDir:e.dataDir,provider:e.provider,providerPlugin:e.providerPlugin,pluginsConfig:e.pluginsConfig,includeSessions:e.includeSessions}),n;if(t.provider.sync&&(await t.provider.sync(e.rebuild?`cli-rebuild`:`cli-index`),n=t.provider.status().custom?.lastRebuildSummary),t.warnings.length>0)for(let e of t.warnings)O(`Warning: ${e}`);e.verbose&&n&&D(JSON.stringify(n,null,2)),D(e.rebuild?`Memory index rebuilt.`:`Memory index refreshed.`)})}catch(e){O(`Error indexing memory: ${e.message}`),process.exit(1)}}),n(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`).option(`--encrypt-sessions`,`Enable gocryptfs-backed encryption for the .aimax data directory`).action(async(e,t)=>{let n=t.output===`json`?`json`:`text`,r=t.query?.trim()||e?.trim();r||(O(`Query is required: provide [query] or --query <text>`),process.exit(1));try{await z(t.dataDir,t,async()=>{let e=await(await yr({dataDir:t.dataDir,provider:t.provider,providerPlugin:t.providerPlugin,pluginsConfig:t.pluginsConfig,includeSessions:t.includeSessions})).provider.search(r);if(n===`json`){D(JSON.stringify(e,null,2));return}if(e.length===0){D(`No results found for: ${r}`);return}D(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(`
13
+ `))})}catch(e){O(`Error searching memory: ${e.message}`),process.exit(1)}}),n(t.command(`dream`)).description(`Trigger Dream Gate host hook for memory plugins`).requiredOption(`-d, --data-dir <path>`,`Data directory path`).option(`--provider <id>`,`Memory provider id`).option(`--provider-plugin <id>`,`Memory provider plugin id`).option(`--trigger <mode>`,`Dream Gate trigger mode: cli (default) or cron`,`cli`).option(`--dry-run`,`Return hook results without plugin-side mutation`).option(`--output <format>`,`Output format: text (default) or json`,`text`).option(`--encrypt-sessions`,`Enable gocryptfs-backed encryption for the .aimax data directory`).action(async e=>{let t=e.output===`json`?`json`:`text`;try{await z(e.dataDir,e,async()=>{let n=_r(e.trigger),r=await yr({dataDir:e.dataDir,provider:e.provider,providerPlugin:e.providerPlugin,pluginsConfig:e.pluginsConfig,requirePluginSystem:!0}),i=r.pluginSystem?await r.pluginSystem.registry.hooks.dispatch(`dream_gate`,{dataDir:e.dataDir,memoryDir:C.join(e.dataDir,`.aimax`),providerId:r.providerId,pluginId:r.pluginId,trigger:n,dryRun:!!e.dryRun},{workspaceDir:pr(e.dataDir)}):[],a={ok:!0,trigger:n,providerSource:r.providerOrigin,providerId:r.providerId,pluginId:r.pluginId,resultCount:i.length,results:i,warnings:r.warnings};if(t===`json`){D(JSON.stringify(a,null,2));return}D(`trigger: ${a.trigger}`),D(`provider_source: ${a.providerSource}`),D(`provider_id: ${a.providerId}`),a.pluginId&&D(`plugin_id: ${a.pluginId}`),D(`result_count: ${a.resultCount}`),a.results.length===0?D(`note: no dream_gate hook registered`):D(`results: ${JSON.stringify(a.results)}`);for(let e of a.warnings)D(`warning: ${e}`)})}catch(e){O(`Error running dream gate: ${e.message}`),process.exit(1)}})}function Sr(e){return`${e.match.accountId?`${e.match.channel}:${e.match.accountId}`:e.match.channel} -> ${e.agentId}`}function Cr(e){return async t=>{let n=await T(t),r=Ee(n),i=De(n);if(E(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=je(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(` - ${Sr(e)}`)}}}}function wr(e,t){return async n=>{w(await T(n),Oe(e))&&(console.error(`Agent "${e}" already exists.`),process.exit(1)),await we(n,{id:e,name:t.name,model:t.model,default:t.default})||(console.error(`Agent "${e}" already exists.`),process.exit(1));let r=je(n,e);console.log(`Agent "${e}" added successfully.`),console.log(` Agent dir: ${r}`)}}function Tr(e){return async t=>{let n=w(await T(t),Oe(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 ke(t,e)||(console.error(`Failed to delete agent "${e}".`),process.exit(1)),console.log(`Agent "${e}" deleted.`)}}function Er(e){return async t=>{let n=await T(t),r=e.agent??E(n);w(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 Te(t,{agentId:r,match:{channel:e,accountId:a||void 0}}),console.log(`Binding added: ${n} -> ${r}`)}}}function Dr(e){return async t=>{let n=await T(t),r=e.agent??E(n);if(w(n,r)||(console.error(`Agent "${r}" not found.`),process.exit(1)),e.all){let e=await Ae(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 Ae(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 Or(e){return async t=>{let n=De(await T(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(` ${Sr(e)}`)}}function kr(e){return async t=>{let n=await T(t),r=e.agent??E(n);w(n,r)||(console.error(`Agent "${r}" not found.`),process.exit(1)),await Me(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 Ar(e,t){let n=e.command(`agents`).description(`Manage agents`),r=e=>e.option(`--encrypt-sessions`,`Enable gocryptfs-backed encryption for the .aimax data directory`);r(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 z(n,e,async()=>{await Cr(e)(n)})}),r(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 z(r,n,async()=>{await wr(e,n)(r)})}),r(n.command(`delete <id>`).description(`Delete an agent`)).action(async(e,n)=>{let r=t();await z(r,n,async()=>{await Tr(e)(r)})}),r(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 z(n,e,async()=>{await Er(e)(n)})}),r(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 z(n,e,async()=>{await Dr(e)(n)})}),r(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 z(n,e,async()=>{await Or(e)(n)})}),r(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 z(n,e,async()=>{await kr(e)(n)})})}function Y(e){return C.join(e,`workspace`)}function X(){let e=process.env.AIMAX_PLUGINS_BUNDLED_DIR;return e&&e.trim()||void 0}function jr(e){if(e.length===0){D(`No plugins discovered.`);return}for(let t of e){let e=t.status.padEnd(8,` `);D(`${t.id} ${e} ${t.origin} ${t.source}`)}}function Mr(e){D(`id: ${e.id}`),D(`status: ${e.status}`),D(`origin: ${e.origin}`),D(`source: ${e.source}`),D(`enabled: ${e.enabled}`),e.error&&D(`error: ${e.error}`),D(`tools: ${e.toolCount}`),D(`hooks: ${e.hookCount}`),e.skills.length>0&&D(`skills: ${e.skills.join(`, `)}`)}function Nr(e){return Array.from(new Set((e??[]).map(e=>e.trim()).filter(Boolean)))}function Pr(e){if(e.length===0){D(`LLM allowlist is empty.`);return}for(let t of e)D(t)}function Fr(e,t){let n=e.command(`plugins`).description(`Manage AIMax plugins`),r=e=>e.option(`--plugins-config <path>`,`Plugins config file path`),i=e=>e.option(`--encrypt-sessions`,`Enable gocryptfs-backed encryption for the .aimax data directory`);i(r(n.command(`list`))).description(`List discovered plugins`).option(`-d, --data-dir <path>`,`Data directory path`).action(async e=>{let n=e.dataDir??t();await z(n,e,async()=>{jr(g({config:await B(n,e.pluginsConfig),dataDir:n,workspaceDir:Y(n),bundledDir:X()}).registry.plugins)})}),i(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();await z(r,n,async()=>{let t=g({config:await B(r,n.pluginsConfig),dataDir:r,workspaceDir:Y(r),bundledDir:X()}).registry.plugins.find(t=>t.id===e);t||(O(`Plugin not found: ${e}`),process.exit(1)),Mr(t)})}),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();await z(r,n,async()=>{let t=await B(r,n.pluginsConfig)??{},i=ae(t);g({config:t,dataDir:r,workspaceDir:Y(r),bundledDir:X()}).registry.plugins.some(t=>t.id===e)||(O(`Plugin not found: ${e}`),process.exit(1)),await V(r,{...t,entries:{...t.entries,[e]:{...t.entries?.[e]??{},enabled:!0}}},n.pluginsConfig),D(`Enabled ${e}`),i.allow.length>0&&!i.allow.includes(e)&&D(`Note: plugins.allow is set; add this plugin id to allowlist if needed.`)})}),i(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();await z(r,n,async()=>{let t=await B(r,n.pluginsConfig)??{};g({config:t,dataDir:r,workspaceDir:Y(r),bundledDir:X()}).registry.plugins.some(t=>t.id===e)||(O(`Plugin not found: ${e}`),process.exit(1)),await V(r,{...t,entries:{...t.entries,[e]:{...t.entries?.[e]??{},enabled:!1}}},n.pluginsConfig),D(`Disabled ${e}`)})}),i(r(n.command(`doctor`))).description(`Validate plugin configuration`).option(`-d, --data-dir <path>`,`Data directory path`).action(async e=>{let n=e.dataDir??t();await z(n,e,async()=>{let t=g({config:await B(n,e.pluginsConfig),dataDir:n,workspaceDir:Y(n),bundledDir:X()});if(t.diagnostics.length===0){D(`No plugin issues detected.`);return}for(let e of t.diagnostics)D(`${e.level===`error`?`ERROR`:`WARN`}${e.pluginId?` ${e.pluginId}`:``}: ${e.message}`);t.diagnostics.some(e=>e.level===`error`)&&process.exit(1)})});let a=n.command(`llm-allow`).description(`Manage plugin LLM allowlist`);i(r(a.command(`list`))).description(`List LLM allowlist entries`).option(`-d, --data-dir <path>`,`Data directory path`).action(async e=>{let n=e.dataDir??t();await z(n,e,async()=>{Pr(Nr((await B(n,e.pluginsConfig))?.llmAllowlist))})}),i(r(a.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();await z(r,n,async()=>{let t=await B(r,n.pluginsConfig)??{},i=Nr([...t.llmAllowlist??[],...e]);await V(r,{...t,llmAllowlist:i},n.pluginsConfig),D(`LLM allowlist updated (${i.length} entries).`)})}),i(r(a.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();await z(r,n,async()=>{let t=await B(r,n.pluginsConfig)??{},i=new Set(e.map(e=>e.trim()).filter(Boolean)),a=Nr(t.llmAllowlist).filter(e=>!i.has(e));await V(r,{...t,llmAllowlist:a},n.pluginsConfig),D(`LLM allowlist updated (${a.length} entries).`)})}),i(r(a.command(`clear`))).description(`Clear the LLM allowlist`).option(`-d, --data-dir <path>`,`Data directory path`).action(async e=>{let n=e.dataDir??t();await z(n,e,async()=>{await V(n,{...await B(n,e.pluginsConfig)??{},llmAllowlist:[]},e.pluginsConfig),D(`LLM allowlist cleared.`)})})}function Ir(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`).option(`--encrypt-sessions`,`Enable gocryptfs-backed encryption for the .aimax data directory`).action(async e=>{let t=e.output===`json`?`json`:`text`;try{await z(e.dataDir,e,async()=>{let n=v(await re(e.dataDir,[]));if(t===`json`){D(JSON.stringify(n,null,2));return}D(`Commands`),D(` builtin: ${n.builtin.map(e=>e.name).join(` | `)}`),n.skillCommands.length>0?D(` skills: ${n.skillCommands.map(e=>e.name).join(` | `)}`):D(` skills: (none)`)})}catch(e){O(`Error listing commands: ${e.message}`),process.exit(1)}})}function Z(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 Q(e){if(!e.sessionId)throw Error(`Session ID is required (--session-id or -s)`);return e.sessionId}function $(e){return e?y(e):void 0}async function Lr(e){let t={storeName:e.sessionStoreName},n=e.objective.trim(),r=await b(e.dataDir,e.sessionId,t);if(!r||(await oe(e.dataDir,e.sessionId,r,t)).trim()!==n)return pe(e.dataDir,e.sessionId,{goalId:Ne(),objective:n,status:`active`,tokenBudget:e.tokenBudget??null,tokensUsed:0,timeUsedSeconds:0},{...t,eventSource:`cli`});if(r.status===`complete`)return r;let i={};return r.status===`paused`&&(i.status=`active`),e.tokenBudget!==void 0&&e.tokenBudget!==r.tokenBudget&&(i.tokenBudget=e.tokenBudget),Object.keys(i).length===0?r:await fe(e.dataDir,e.sessionId,i,{...t,eventSource:`cli`})}async function Rr(e,t){let n=Z(t),r=Q(t),i=$(t.sessionStore),a=e.trim();a||(O(`error: objective cannot be empty`),process.exit(1));let o=t.tokenBudget===void 0||t.tokenBudget===`0`||t.tokenBudget===``?null:Number(t.tokenBudget);o!==null&&(Number.isNaN(o)||o<=0)&&(O(`error: --token-budget must be a positive integer, or 0 for unlimited`),process.exit(1));let s=await Lr({dataDir:n,sessionId:r,sessionStoreName:i,objective:a,tokenBudget:o});D(JSON.stringify({goal:s},null,2))}async function zr(e){let t=Z(e),n=Q(e),r=$(e.sessionStore),i=await b(t,n,{storeName:r});if(!i){D(JSON.stringify({goal:null},null,2));return}let a=await oe(t,n,i,{storeName:r});D(JSON.stringify({goal:{...i,objective:a}},null,2))}async function Br(e){let t=Z(e),n=Q(e),r=$(e.sessionStore),i=await b(t,n,{storeName:r});i||(O(`error: no goal exists for this session`),process.exit(1)),i.status===`complete`&&(O(`error: cannot pause a completed goal`),process.exit(1));let a=await fe(t,n,{status:`paused`},{storeName:r,eventSource:`cli`});D(JSON.stringify({goal:a},null,2))}async function Vr(e){let t=Z(e),n=Q(e),r=$(e.sessionStore),i=await b(t,n,{storeName:r});if(i||(O(`error: no goal exists for this session`),process.exit(1)),i.status===`complete`&&(O(`error: cannot resume a completed goal`),process.exit(1)),i.status===`budget_limited`&&(O(`error: cannot resume a budget-limited goal; clear or replace it instead`),process.exit(1)),i.status===`active`){D(JSON.stringify({goal:i},null,2));return}let a=await fe(t,n,{status:`active`},{storeName:r,eventSource:`cli`});D(JSON.stringify({goal:a},null,2))}async function Hr(e){let t=await l(Z(e),Q(e),{storeName:$(e.sessionStore),eventSource:`cli`});D(JSON.stringify({cleared:t},null,2))}function Ur(e){let t=e.command(`goal`).description(`Manage thread goals for a session`).addHelpText(`after`,a());t.command(`set <objective>`).description(`Set or replace the thread goal (creates new goalId)`).option(`-d, --data-dir <path>`,`Data directory path (overrides AIMAX_DATA_DIR)`).requiredOption(`-s, --session-id <id>`,`Session ID`).option(`--session-store <name>`,`Session store directory under .aimax (default: sessions)`).option(`--token-budget <n>`,`Optional token budget (positive integer, or 0 for unlimited)`).action(async(e,t)=>{try{await Rr(e,t)}catch(e){O(`error: ${e.message}`),process.exit(1)}}),t.command(`get`).description(`Get the current goal as JSON`).option(`-d, --data-dir <path>`,`Data directory path (overrides AIMAX_DATA_DIR)`).requiredOption(`-s, --session-id <id>`,`Session ID`).option(`--session-store <name>`,`Session store directory under .aimax (default: sessions)`).action(async e=>{try{await zr(e)}catch(e){O(`error: ${e.message}`),process.exit(1)}}),t.command(`pause`).description(`Pause the current goal`).option(`-d, --data-dir <path>`,`Data directory path (overrides AIMAX_DATA_DIR)`).requiredOption(`-s, --session-id <id>`,`Session ID`).option(`--session-store <name>`,`Session store directory under .aimax (default: sessions)`).action(async e=>{try{await Br(e)}catch(e){O(`error: ${e.message}`),process.exit(1)}}),t.command(`resume`).description(`Resume a paused goal`).option(`-d, --data-dir <path>`,`Data directory path (overrides AIMAX_DATA_DIR)`).requiredOption(`-s, --session-id <id>`,`Session ID`).option(`--session-store <name>`,`Session store directory under .aimax (default: sessions)`).action(async e=>{try{await Vr(e)}catch(e){O(`error: ${e.message}`),process.exit(1)}}),t.command(`clear`).description(`Clear the current goal`).option(`-d, --data-dir <path>`,`Data directory path (overrides AIMAX_DATA_DIR)`).requiredOption(`-s, --session-id <id>`,`Session ID`).option(`--session-store <name>`,`Session store directory under .aimax (default: sessions)`).action(async e=>{try{await Hr(e)}catch(e){O(`error: ${e.message}`),process.exit(1)}})}const Wr=[`progress`,`error`,`hitl`];function Gr(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 Kr(e){if(!e?.trim())return new Set(Wr);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(Wr)}function qr(e){return e?y(e):void 0}function Jr(e){let t=[];return e.callbackUrl&&t.push(new Wt(e.callbackUrl)),e.streamUrl&&t.push(new Xt(e.streamUrl,Kr(e.streamEvents),e.streamAuthToken)),new Ut(t)}async function Yr(e){let t=Gr(e);await z(t,e,async()=>{M(t);let n=new P(`cancel command`),r=e.channel??`WEB`,i=e.output===`json`?`json`:`text`,a=Jr(e),o=qr(e.sessionStore);try{let s=await te(t,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 ce({dataDir:t,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`&&k(l),await a.send({type:`progress`,sessionId:e.sessionId,channel:r,messageId:e.messageId,event:l}),n.end(),process.exit(0)}catch(t){let i=t;await a.send({type:`error`,sessionId:e.sessionId,channel:r,messageId:e.messageId,message:i.message}),N.error(`cancel command error: ${i.message}`),O(`Fatal: ${i.message}`),n.end(),process.exit(1)}finally{await a.close()}})}function Xr(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`).option(`--encrypt-sessions`,`Enable gocryptfs-backed encryption for the .aimax data directory`).action(async e=>{await Yr(e)})}function Zr(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 Qr(e){return e.query?.trim()||void 0}function $r(e){if(!e)return;let t=Number(e);if(!Number.isFinite(t)||t<=0)throw Error(`--timeout must be a positive number of milliseconds`);return t}function ei(e){if(!e)return;let t=Number(e);if(!Number.isInteger(t)||t<=0)throw Error(`--max-tokens must be a positive integer`);return t}async function ti(e){if(e.filePath){if(!C.isAbsolute(e.filePath))throw Error(`--file-path must be an absolute path`);try{await x.access(e.filePath)}catch(e){throw Error(`Failed to access --file-path: ${e.message}`)}return{source:`file`,filePath:e.filePath}}let t=e.content;if(!t||!t.trim())throw Error(`Either --file-path or --content must be provided`);return{source:`content`,content:t}}async function ni(e){let t=null;try{let n=Zr(e);M(n),t=new P(`summarize command`);let r=Qr(e),i=await ti(e),a=At({apiFormat:e.apiFormat,baseUrl:e.baseUrl,apiKey:e.apiKey,model:e.model,contextWindow:2e5}),o=$r(e.timeout),s=ei(e.maxTokens);N.info(`summarize command started`,{dataDir:n,source:i.source,filePath:i.source===`file`?i.filePath:void 0,queryLength:r?.length,contentLength:i.source===`content`?i.content.length:void 0,timeoutMs:o,maxTokens:s});let c=await de({dataDir:n,channel:`WEB`,message:ri(i,r),llm:{...a,maxTokens:s},timeoutMs:o});D(c.text.trim()),N.info(`summarize command succeeded`,{source:i.source,summaryLength:c.text.length,durationMs:c.durationMs}),t.end()}catch(e){N.error(`summarize command error: ${e.message}`),O(`Fatal: ${e.message}`),t?.end(),process.exit(1)}}function ri(e,t){return e.source===`file`?[t?`Summarize exactly one file for the query below.`:`Summarize exactly one file.`,`Read only the absolute file path provided here. Do not search, browse, read other files, execute commands, modify files, or perform any other processing.`,`Return only the summary text.`,``,...t?[`Query:\n${t}`,``]:[],`Input source: file`,`File path: ${e.filePath}`].join(`
14
+ `):[t?`Summarize the provided content for the query below.`:`Summarize the provided content.`,t?`Use only the provided content and query. Do not search, browse, read files, execute commands, modify files, or perform any other processing.`:`Use only the provided content. Do not search, browse, read files, execute commands, modify files, or perform any other processing.`,`Return only the summary text.`,``,...t?[`Query:\n${t}`,``]:[],`Input source: content`,`Source content:`,`<source>`,e.content,`</source>`].join(`
15
+ `)}function ii(e){e.command(`summarize`).description(`Summarize one absolute file path or inline content`).option(`--file-path <path>`,`Absolute file path to summarize`).option(`--content <text>`,`Inline text content to summarize when --file-path is not provided`).option(`--query <text>`,`Optional search target or current description to focus the summary`).option(`-d, --data-dir <path>`,`Data directory path (overrides AIMAX_DATA_DIR)`).option(`--base-url <url>`,`LLM API base URL (overrides AIMAX_BASE_URL)`).option(`--api-format <format>`,`LLM API format: openai-completions or anthropic-messages (overrides AIMAX_API_FORMAT)`).option(`--api-key <key>`,`LLM API key (overrides AIMAX_API_KEY)`).option(`--model <name>`,`LLM model name (overrides AIMAX_MODEL)`).option(`--timeout <ms>`,`Execution timeout in milliseconds`).option(`--max-tokens <number>`,`Maximum number of tokens for model output`).action(async e=>{await ni(e)})}const ai=e(import.meta.url)(`../package.json`);function oi(){return process.env.AIMAX_DATA_DIR||process.cwd()}function si(){let e=new t;return e.name(`aimax`).description(`AIMax CLI — runs agent tasks in a containerized environment`).version(ai.version),dr(e),Sn(e),Ur(e),Xr(e),fr(e),ii(e),Ir(e),Dt(e),xr(e),Ar(e,oi),Fr(e,oi),e}export{Ze as a,N as i,oi as n,M as r,si as t};
package/dist/program.js CHANGED
@@ -1 +1 @@
1
- import{n as e,t}from"./program-DDYm7FET.js";export{t as createProgram,e as getDataDir};
1
+ import{n as e,t}from"./program-BxoNJefy.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.6.10",
3
+ "version": "0.7.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.2.0",
26
- "@gencode/agents": "0.8.2"
25
+ "@gencode/agents": "0.9.0",
26
+ "@gencode/shared": "0.2.0"
27
27
  },
28
28
  "devDependencies": {
29
29
  "@types/node": "^22.0.0",
@@ -1,14 +0,0 @@
1
- import{createRequire as e}from"node:module";import{Command as t}from"commander";import{GoalConflictError as n,applyCliGoalBeforeRun as r,bootstrapMountLayout as i,buildResumeNarration as a,clearPendingUiTool as o,createBuiltinMemoryProvider as s,deleteGoal as c,ensureBootstrapMountLayout as l,exportSession as u,formatApprovalResolution as d,formatClarifyResolution as f,formatReviewResolution as p,hasBootstrapSentinel as m,initializePluginSystem as h,inspectSession as g,listAvailableSlashCommands as _,listSessionSummaries as v,loadPendingHitl as ee,loadPendingUiTool as te,loadSkillsWithPluginDirs as ne,loadTranscript as re,normalizePluginsConfig as ie,normalizeSessionStoreName as y,readGoal as b,resolveGoalObjective as ae,resolveMemoryProvider as oe,resolvePendingHitl as se,resolvePendingUiTool as ce,rewriteTranscript as le,runAgent as x,updateGoal as ue,writeGoal as de}from"@gencode/agents";import{formatTaskForDisplay as fe,isAgentDiagnosticEvent as pe,isHitlTool as me,parseMatchedTextToResolution as he,parseTextToResolution as ge}from"@gencode/shared";import S from"node:fs/promises";import C from"node:path";import _e from"node:os";import{execFile as ve,execFileSync as ye}from"node:child_process";import be from"node:fs";import xe from"log4js";import Se from"gensign-node";import{addAgent as Ce,addBinding as we,getAgentConfig as w,listAgents as Te,listBindings as Ee,loadAgentsConfig as T,normalizeAgentId as De,removeAgent as Oe,removeBindings as ke,resolveAgentDir as Ae,resolveDefaultAgentId as E,updateAgentIdentity as je}from"@gencode/agents/config";import{randomUUID as Me}from"node:crypto";function Ne(e){process.stdout.write(e)}function D(e){process.stdout.write(e+`
2
- `)}function O(e){process.stderr.write(e+`
3
- `)}function k(e){switch(e.type){case`start`:D(`\n[start] ${e.message}`);break;case`text`:Ne(e.text);break;case`stream_text_delta`:Ne(e.text);break;case`bootstrap`:D(`\n[bootstrap:${e.phase}] ${e.dataDir}`);break;case`session_reset`:D(`\n[session:${e.action}] ${e.message}`);break;case`tool_start`:D(`\n[tool:${e.name}] ${JSON.stringify(e.input??{})}`);break;case`tool_end`:D(`[tool:${e.name}] ${e.isError?`ERROR`:`OK`} ${e.output.slice(0,200)}`);break;case`compaction`:D(`\n[compaction${e.layer?`:${e.layer}`:``}] ${e.reason}${e.strategy?` (${e.strategy})`:``}`);break;case`skill_used`:D(`\n[skill] ${e.skillName} agent=${e.agent} task=${e.taskId}`);break;case`custom`:D(`\n[plugin:${e.pluginId}] ${e.name}${e.label?` ${e.label}`:``}${e.data?` ${JSON.stringify(e.data)}`:``}`);break;case`error`:O(`\n[error] ${e.message}`);break;case`diagnostic`:break;case`subagent_spawn`:D(`\n[subagent:spawn]${e.label?` "${e.label}"`:``} ${fe(e.task)}`);break;case`subagent_complete`:D(`[subagent:${e.status}] ${fe(e.task)}`);break;case`hitl_requested`:if(D(`\n[hitl:${e.request.kind}] ${e.request.title}`),D(` prompt: ${e.request.prompt}`),D(` requestId: ${e.request.requestId}`),e.request.input.mode===`choice`)for(let t of e.request.input.choices)D(` - [${t.id}] ${t.label}`);break;case`hitl_resumed`:D(`\n[hitl:resumed] requestId=${e.requestId} action=${e.resolution.action}`);break;case`hitl_expired`:D(`\n[hitl:expired] requestId=${e.requestId} reason=${e.reason}`);break;case`hitl_cancelled`:D(`\n[hitl:cancelled] requestId=${e.requestId}${e.reason?` reason=${e.reason}`:``}`);break;case`ui_tool_request`:D(`\n[ui-tool:${e.request.toolName}] ${e.request.outputSchema.title}`),D(` requestId: ${e.request.requestId}`),D(` toolCallId: ${e.request.toolCallId}`);break;case`ui_tool_result`:D(`\n[ui-tool:resumed] requestId=${e.requestId} tool=${e.toolName}`);break}}function Pe(e,t){if(t===`json`){e&&D(JSON.stringify(e,null,2));return}D(`
4
- `),D(`session: ${e.sessionId}`),D(`duration: ${e.durationMs}ms`),D(`tokens: input=${e.usage.input} output=${e.usage.output} total=${e.usage.total}`),e.context&&(D(`context: ${e.context.snapshotPath}`),D(`tool-results: ${e.context.toolResultsDir}`)),e.error&&O(`error: ${e.error}`)}function Fe(e,t){if(t===`json`){D(JSON.stringify(e,null,2));return}if(e.length===0){D(`No sessions found.`);return}for(let t of e){let e=t.createdAt?new Date(t.createdAt).toLocaleString():`unknown`,n=t.goalStatus?` [GOAL:${t.goalStatus}]`:` [GOAL:—]`;D(`${t.id} ${e} [${t.channel}]${n} ${t.title}`)}}function Ie(e,t){if(t===`json`){D(JSON.stringify(e,null,2));return}D(`session: ${e.id}`),e.metadata&&(D(`title: ${e.metadata.title}`),D(`channel: ${e.metadata.channel}`),D(`created: ${e.metadata.createdAt}`),D(`updated: ${e.metadata.updatedAt}`)),D(`transcript: ${e.transcriptPath}`),D(`entries: ${e.transcriptEntryCount}`),D(`context: ${e.contextSnapshotPath}`),D(`session-memory: ${e.sessionMemoryPath}`),D(`collapse-log: ${e.collapseLogPath}`),D(`read-states: ${e.readStateCount}`),D(`tool-results: ${e.toolResultRefCount}`),D(`tool-results-dir: ${e.toolResultsDir}`)}function Le(e,t){if(t===`json`){D(JSON.stringify(e,null,2));return}D(`session: ${e.id}`),D(`transcript: ${e.paths.transcriptPath}`),D(`context: ${e.paths.contextSnapshotPath}`),D(`session-memory: ${e.paths.sessionMemoryPath}`),D(`collapse-log: ${e.paths.collapseLogPath}`),D(`tool-results-dir: ${e.paths.toolResultsDir}`),D(`transcript-entries: ${e.transcript.length}`),D(`read-states: ${e.context.readStates.length}`),D(`tool-results: ${e.context.toolResults.length}`),D(`collapse-spans: ${e.context.compaction.collapseSpans.length}`)}function Re(e,t){if(t===`json`){D(JSON.stringify(e,null,2));return}D(`Bootstrap completed.`),D(`dataDir: ${e.dataDir}`),D(`created dirs: ${e.createdDirs.length}`),D(`created files: ${e.createdFiles.length}`),D(`skipped dirs: ${e.skippedDirs.length}`),D(`skipped files: ${e.skippedFiles.length}`)}function ze(e){let t=new Intl.DateTimeFormat(`en-CA`,{timeZone:`Asia/Shanghai`,year:`numeric`,month:`2-digit`,day:`2-digit`,hour:`2-digit`,minute:`2-digit`,second:`2-digit`,hour12:!1}).formatToParts(e);return Object.fromEntries(t.map(e=>[e.type,e.value]))}function Be(e=new Date){let t=ze(e),n=String(e.getMilliseconds()).padStart(3,`0`);return`${t.year}-${t.month}-${t.day} ${t.hour}:${t.minute}:${t.second}.${n}`}let A=function(e){return e.INFO=`INFO`,e.ERROR=`ERROR`,e.WARN=`WARN`,e}({}),Ve=null;function He(){return Be()}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 C.join(e,`.aimax`)}function Ge(e){return{appLogPath:C.join(e,`app.log`),errorLogPath:C.join(e,`errors.log`)}}function Ke(e){let{appLogPath:t,errorLogPath:n}=Ge(e);xe.configure({appenders:{appFile:{type:`file`,filename:t,maxLogSize:5*1024*1024,backups:3,compress:!0,keepFileExt:!0,layout:{type:`messagePassThrough`}},errorFile:{type:`file`,filename:n,maxLogSize:5*1024*1024,backups:3,compress:!0,keepFileExt:!0,layout:{type:`messagePassThrough`}},errorsOnly:{type:`logLevelFilter`,appender:`errorFile`,level:`error`,maxLevel:`fatal`}},categories:{default:{appenders:[`appFile`,`errorsOnly`],level:`info`}}})}function qe(e,t,n){return`[${He()}] [${e}] ${t}${Ue(n)}`}function Je(e,t,n){process.stderr.write(`${qe(e,t,n)}\n`)}function Ye(e,t,n){if(!Ve){Je(e,t,n);return}let r=qe(e,t,n),i=xe.getLogger();if(e===A.ERROR){i.error(r);return}if(e===A.WARN){i.warn(r);return}i.info(r)}function j(e){let t=We(e);be.mkdirSync(t,{recursive:!0}),Ke(t),Ve={dataDir:e,logDir:t}}function Xe(){return Ve?{...Ve}:null}async function Ze(){await xe.shutdown()}const M={info:(e,t)=>Ye(A.INFO,e,t),warn:(e,t)=>Ye(A.WARN,e,t),error:(e,t)=>Ye(A.ERROR,e,t)};var N=class{startTime;name;constructor(e){this.name=e,this.startTime=Date.now()}end(){let e=Date.now()-this.startTime;return M.info(`${this.name} completed in ${e}ms`),e}};const Qe=`.aimax`,$e=`${Qe}.pre-gocryptfs.`,et=[`fusermount3`,`fusermount`,`umount`];function tt(e){return C.join(e,`.aimax.enc`)}function nt(e){return C.join(e,Qe)}function rt(e){return C.join(e,`${$e}${process.pid}.${Date.now()}`)}function it(e){return e.replace(/\\([0-7]{3})/g,(e,t)=>String.fromCharCode(Number.parseInt(t,8)))}async function at(e){try{let t=await ot(),n=C.resolve(e);for(let e of t.split(`
5
- `)){if(!e.trim())continue;let t=e.split(` `);if(t.length>=5&&C.resolve(it(t[4]??``))===n)return!0}return!1}catch{return!1}}async function ot(){return await S.readFile(`/proc/self/mountinfo`,`utf-8`)}async function P(e){try{return await S.stat(e),!0}catch(e){if(e.code===`ENOENT`)return!1;throw e}}async function F(e){await S.mkdir(e,{recursive:!0})}async function st(e){if(await F(e),(await S.readdir(e)).length>0)throw Error(`Refusing to mount encrypted .aimax over non-empty directory: ${e}. Clear stale plaintext files or disable --encrypt-sessions for this run.`)}async function ct(e){return await P(e)?(await S.readdir(e)).length===0:!0}async function lt(e){if(!await P(C.join(e,`gocryptfs.conf`)))throw Error(`Encrypted .aimax directory exists but is not initialized: ${e}. Remove the incomplete .aimax.enc directory or restore it from backup before retrying --encrypt-sessions.`)}async function ut(e){return(await S.readdir(e,{withFileTypes:!0})).filter(e=>e.isDirectory()&&e.name.startsWith($e)).map(t=>C.join(e,t.name)).sort()}async function I(e,t){if(!await P(t))return null;let n=rt(e);return await S.rename(t,n),n}async function L(e,t,n){await S.cp(e,t,{recursive:!0,force:n})}async function dt(e){let t=C.join(_e.tmpdir(),`aimax-gocryptfs-pass.${process.pid}.${Date.now()}`);await S.writeFile(t,`wizard_aimax@2026
6
- `,{mode:384});try{return await e(t)}finally{await S.rm(t,{force:!0})}}async function ft(e){try{await z(`gocryptfs`,e)}catch(t){let n=t instanceof Error?t.message:String(t);throw Error(`gocryptfs ${e.join(` `)} failed: ${n}`)}}async function pt(){await mt(),await St(`gocryptfs`,`required for --encrypt-sessions`);for(let e of et)if(await xt(e))return;throw Error(`--encrypt-sessions requires one of ${et.join(`, `)} to be installed for secure unmount cleanup.`)}async function mt(){try{await z(`modprobe`,[`fuse`])}catch(e){M.warn(`--encrypt-sessions could not load the fuse kernel module; continuing to try gocryptfs`,{error:e instanceof Error?e.message:String(e)})}}async function ht(e,t){await dt(async n=>{await ft([`-q`,`-passfile`,n,e,t])})}async function gt(e){await dt(async t=>{await ft([`-q`,`-init`,`-passfile`,t,e])})}async function _t(e){let t=[];for(let n of et)try{await z(n,[`-u`,e]);return}catch(e){t.push(Ct(n,e))}throw Error(`Failed to unmount ${e}: ${t.join(`; `)}`)}function vt(e){for(let t of et)try{ye(t,[`-u`,e],{stdio:`ignore`});return}catch{}}function yt(e){let t=!1,n=()=>{t||(t=!0,vt(e))},r=()=>n(),i=()=>{n(),process.exit(130)},a=()=>{n(),process.exit(143)};return process.once(`exit`,r),process.once(`SIGINT`,i),process.once(`SIGTERM`,a),{release(){process.removeListener(`exit`,r),process.removeListener(`SIGINT`,i),process.removeListener(`SIGTERM`,a)}}}async function bt(e){let t=tt(e),n=nt(e),r=()=>({mounted:!1,plainDir:n,encryptedDir:t,async cleanup(){}});try{await pt()}catch(e){return M.warn(`--encrypt-sessions is unavailable; continuing with plaintext .aimax`,{error:e instanceof Error?e.message:String(e)}),await F(n),r()}if(await at(n))return r();let i=null,a=[],o=null,s=null,c=!1;try{if(a=await ut(e),!await P(t))if(a.length>0?o=await I(e,n):i=await I(e,n),await F(t),await gt(t),await F(n),await ht(t,n),c=!0,s=yt(n),a.length>0){for(let e of a)await L(e,n,!0);o&&=(await L(o,n,!1),await S.rm(o,{recursive:!0,force:!0}),null);for(let e of a)await S.rm(e,{recursive:!0,force:!0});a=[]}else i&&=(await L(i,n,!0),await S.rm(i,{recursive:!0,force:!0}),null);else if(await lt(t),a.length>0?o=await I(e,n):await ct(n)||(i=await I(e,n)),await st(n),await ht(t,n),c=!0,s=yt(n),a.length>0){for(let e of a)await L(e,n,!0);o&&=(await L(o,n,!1),await S.rm(o,{recursive:!0,force:!0}),null);for(let e of a)await S.rm(e,{recursive:!0,force:!0});a=[]}else i&&=(await L(i,n,!0),await S.rm(i,{recursive:!0,force:!0}),null);return{mounted:c,plainDir:n,encryptedDir:t,async cleanup(){if(s?.release(),c){c=!1;try{await _t(n)}catch(e){M.warn(`--encrypt-sessions failed to unmount encrypted .aimax; continuing shutdown`,{error:e instanceof Error?e.message:String(e)})}}}}}catch(e){return s?.release(),c&&await _t(n).catch(()=>{}),i&&await P(i)&&await ct(n)&&(await S.rm(n,{recursive:!0,force:!0}).catch(()=>{}),await S.rename(i,n).catch(()=>{})),o&&await P(o)&&await ct(n)&&(await S.rm(n,{recursive:!0,force:!0}).catch(()=>{}),await S.rename(o,n).catch(()=>{})),M.warn(`--encrypt-sessions failed; continuing with plaintext .aimax`,{error:e instanceof Error?e.message:String(e)}),await F(n),r()}}async function R(e,t,n){if(!t.encryptSessions)return n();let r=await bt(e);try{return await n()}finally{await r.cleanup()}}async function z(e,t){await new Promise((n,r)=>{ve(e,t,{encoding:`utf-8`},e=>{if(e){r(e);return}n()})})}async function xt(e){try{return await z(`sh`,[`-c`,`command -v "${e}" >/dev/null 2>&1`]),!0}catch{return!1}}async function St(e,t){if(!await xt(e))throw Error(`--encrypt-sessions requires ${e}: ${t}.`)}function Ct(e,t){return`${e} -u failed: ${t instanceof Error?t.message:String(t)}`}function wt(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`).option(`--encrypt-sessions`,`Enable gocryptfs-backed encryption for the .aimax data directory`).action(async e=>{let t=e.output===`json`?`json`:`text`;try{Re(await R(e.dataDir,e,async()=>i(e.dataDir)),t)}catch(e){O(`Error bootstrapping data directory: ${e.message}`),process.exit(1)}})}function Tt(e){return Se.sm4_encrypt_ecb(e)}function Et(e){return Tt(e)}function Dt(e={}){let t=e.baseUrl??process.env.AIMAX_BASE_URL,n=process.env.AIMAX_AUTH_TOKEN,r=e.authToken?Et(e.authToken):n?Et(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 Ot(e,t){return t?C.resolve(t):C.join(e,`.aimax`,`plugins.json`)}async function B(e,t){let n=Ot(e,t);try{let e=await S.readFile(n,`utf-8`);return JSON.parse(e)}catch(e){if(e.code===`ENOENT`)return;throw e}}async function V(e,t,n){let r=Ot(e,n);await S.mkdir(C.dirname(r),{recursive:!0}),await S.writeFile(r,JSON.stringify(t,null,2),`utf-8`)}function H(e){return typeof e==`object`&&!!e}function kt(e){return H(e)&&e.type===`text`&&typeof e.text==`string`&&(e.textSignature===void 0||typeof e.textSignature==`string`)}function At(e){return H(e)&&e.type===`image`&&typeof e.data==`string`&&typeof e.mimeType==`string`}function jt(e){return H(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 Mt(e){return H(e)&&e.type===`toolCall`&&typeof e.id==`string`&&typeof e.name==`string`&&H(e.arguments)&&(e.thoughtSignature===void 0||typeof e.thoughtSignature==`string`)}function Nt(e){return typeof e==`string`||Array.isArray(e)&&e.every(e=>kt(e)||At(e))}function Pt(e){return Array.isArray(e)&&e.every(e=>kt(e)||jt(e)||Mt(e))}function Ft(e){return H(e)&&typeof e.input==`number`&&typeof e.output==`number`&&typeof e.cacheRead==`number`&&typeof e.cacheWrite==`number`&&typeof e.totalTokens==`number`&&H(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 It(e){return!H(e)||typeof e.role!=`string`?!1:e.role===`user`?Nt(e.content):e.role===`assistant`?Pt(e.content)&&typeof e.api==`string`&&typeof e.provider==`string`&&typeof e.model==`string`&&Ft(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=>kt(e)||At(e))&&typeof e.isError==`boolean`:!1}async function Lt(e){let t;try{t=await S.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=>It(e)))throw Error(`Message file must contain one Message object or an array of Message objects`);return r}async function Rt(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 Lt(e.fromFile)}:{kind:`text`,message:e.message}}var zt=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()}))}},Bt=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=Vt(e);M.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 M.error(`callback event failed`,{callbackUrl:this.url,httpStatus:r.status,durationMs:i,...n}),Error(`Callback failed with status ${r.status}`);M.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 Vt(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 Ht(e,t){if(t.kind===`none`)return e;let n=new URL(e);return n.searchParams.set(`authToken`,t.token),n.toString()}function U(){let e=globalThis.WebSocket;if(!e)throw Error(`WebSocket is not available in this runtime`);return e}function Ut(e){return e?{kind:`query_token`,token:e}:{kind:`none`}}function Wt(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 Gt(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 Kt=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=U();if(!this.socket||this.socket.readyState!==e.OPEN)return;this.socket.send(JSON.stringify(t))}catch(e){M.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=U();if(!this.socket||this.socket.readyState!==e.OPEN)return;this.socket.send(JSON.stringify(t))}catch(e){M.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=U();e.readyState!==t.CLOSED&&await new Promise(t=>{Wt(e,`close`,()=>t()),e.close()})}async ensureConnected(){if(!this.enabled)return;let e=U();if(this.socket&&this.socket.readyState===e.OPEN)return;if(this.connectPromise){await this.connectPromise;return}let t=new e(Ht(this.url,Ut(this.authToken)));this.connectPromise=new Promise((e,n)=>{Wt(t,`open`,()=>{this.socket=t,Gt(t,`close`,()=>{this.socket===t&&(this.socket=null)}),e()}),Wt(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)}`)}}}};function qt(e){let t=e.trim();if(!t)throw Error(`Goal objective cannot be empty`);return t}function Jt(e,t){if(t.action===`unchanged`)return null;if(t.action===`created`||t.action===`replaced`)return t.action;if(e?.status!==t.goal.status)switch(t.goal.status){case`active`:return e?.status===`paused`?`resumed`:`updated`;case`paused`:return`paused`;case`complete`:return`completed`;case`budget_limited`:return`budget_limited`;default:return`updated`}return`updated`}function Yt(e){let t=Jt(e.before,e.result);return t?{type:`goal_updated`,sessionId:e.sessionId,action:t,goalId:e.result.goal.goalId,goalStatus:e.result.goal.status}:null}const Xt=[`start`,`text`,`done`,`error`,`hitl`],Zt=[`off`,`gate`,`dry_run`,`write`];function Qt(e){if(!e?.trim())return new Set(Xt);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(Xt)}function $t(e){return e.disableTopicSegmentation===!0||process.env.AIMAX_DISABLE_TOPIC_SEGMENTATION===`true`?{enabled:!1}:void 0}function en(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 tn(e){return e?.trim()||void 0}function nn(e){let t=(e.systemAgentsDir??process.env.AIMAX_SYSTEM_AGENTS_DIR)?.trim();if(t){if(!C.isAbsolute(t)){let n=e.systemAgentsDir===void 0?`AIMAX_SYSTEM_AGENTS_DIR`:`--system-agents-dir`;throw Error(`Invalid ${n}: ${t}. Path must be absolute.`)}return t}}function rn(e){return e?y(e):void 0}function an(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(!C.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 on(e,t){if(e===void 0)return;let n=e.trim().toLowerCase();if(n){if([`true`,`1`,`yes`,`on`].includes(n))return!0;if([`false`,`0`,`no`,`off`].includes(n))return!1;throw Error(`Invalid ${t}: ${e}. Must be true or false.`)}}function sn(e,t){if(e===void 0)return;let n=e.trim().toLowerCase();if(n){if(Zt.includes(n))return n;throw Error(`Invalid ${t}: ${e}. Must be one of off,gate,dry_run,write.`)}}function cn(e){let t=e.autoSkillsLoadEnabled===void 0?on(process.env.AIMAX_AUTO_SKILLS_LOAD_ENABLED,`AIMAX_AUTO_SKILLS_LOAD_ENABLED`):on(e.autoSkillsLoadEnabled,`--auto-skills-load-enabled`),n=e.autoSkillsReviewMode===void 0?sn(process.env.AIMAX_AUTO_SKILLS_REVIEW_MODE,`AIMAX_AUTO_SKILLS_REVIEW_MODE`):sn(e.autoSkillsReviewMode,`--auto-skills-review-mode`),r={};return t!==void 0&&(r.load={enabled:t}),n!==void 0&&(r.review={mode:n}),r.load||r.review?r:void 0}function ln(e,t){if(e.inputText&&t){let n=ge(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 un(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 dn(e){let t=await re(e.dataDir,e.sessionId,{storeName:e.sessionStoreName,encryptSessions:e.encryptSessions});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 fn(e){let t=en(e),n=e.channel??`WEB`,r=Dt({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,systemAgentsDir:nn(e),channel:n,format:e.output===`json`?`json`:`text`,timeoutMs:e.timeout?Number(e.timeout):void 0,llm:r,skillsLoadPaths:an(e.skillsLoadPaths),autoSkills:cn(e)}}function pn(e){let t=[],n=null;return e.callbackUrl&&t.push(new Bt(e.callbackUrl)),e.streamUrl&&(n=new Kt(e.streamUrl,Qt(e.streamEvents),e.streamAuthToken),t.push(n)),{sink:new zt(t),websocketSink:n}}async function mn(e){let{dataDir:t,sessionId:n,sessionStoreName:r,toolCallId:i,toolName:a,resolution:o,encryptSessions:s}=e;if(!i||!a||!me(a))return;let c=(e,t)=>{switch(e){case`request_approval`:return d(t);case`clarify`:return f(t);case`request_review`:return p(t);default:return JSON.stringify({action:t.action,values:t.values})}};await le(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:c(a,o),isError:!1},n},{storeName:r,encryptSessions:s})}async function hn(e){let{dataDir:t,sessionId:n,sessionStoreName:r,result:i,encryptSessions:a}=e;await le(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,encryptSessions:a})}async function gn(e){let t=en(e);await R(t,e,async()=>{j(t);let i=new N(`resume command`),a=null;try{let t=await fn(e),s=rn(e.sessionStore),c=null;if(e.goal||e.goalFile){let i;i=e.goalFile?await S.readFile(e.goalFile,`utf-8`):e.goal;let a=qt(i),o=e.tokenBudget===void 0?void 0:e.tokenBudget===`0`||e.tokenBudget===``?null:Number(e.tokenBudget);o!=null&&(Number.isNaN(o)||o<=0)&&(O(`error: --token-budget must be a positive integer, or 0 for unlimited`),process.exit(1));try{let n=await b(t.dataDir,e.sessionId,{storeName:s}),i=await r({dataDir:t.dataDir,sessionId:e.sessionId,objective:a,tokenBudget:o,force:e.force,storeName:s});c=Yt({sessionId:e.sessionId,before:n,result:i})}catch(e){throw e instanceof n&&(O(e.message),O(`Existing: ${e.existingObjectivePreview}`),process.exit(2)),e}}M.info(`resume command started`,{sessionId:e.sessionId,requestId:e.requestId,channel:t.channel,dataDir:t.dataDir});let l=await ee(t.dataDir,e.sessionId,{storeName:s,encryptSessions:e.encryptSessions}),u=l?null:await te(t.dataDir,e.sessionId,{storeName:s,encryptSessions:e.encryptSessions});if(!l&&!u)throw Error(`No pending HITL or UI tool request found for session "${e.sessionId}"`);if(l){if(l.request.requestId!==e.requestId)throw Error(`Request ID mismatch: pending is "${l.request.requestId}", got "${e.requestId}"`);if(l.status===`expired`)throw Error(`HITL request has expired`);if(l.status===`cancelled`)throw Error(`HITL request has been cancelled`)}else if(u){if(u.request.requestId!==e.requestId)throw Error(`Request ID mismatch: pending is "${u.request.requestId}", got "${e.requestId}"`);if(u.status!==`pending`)throw Error(`UI tool request is already "${u.status}", cannot resume`)}if(l){let n=ln(e,l.request),r=await se({dataDir:t.dataDir,sessionStoreName:s,sessionId:e.sessionId,requestId:e.requestId,resolution:n}),o=r.state;if(!o)throw Error(`Resolved HITL state was not persisted`);let u=_n(n,o.request.kind);await mn({dataDir:t.dataDir,sessionId:e.sessionId,sessionStoreName:s,toolCallId:o.toolContext?.toolCallId,toolName:o.toolContext?.toolName,resolution:n,encryptSessions:e.encryptSessions});let d=pn(e);a=d.sink;let f=e.sessionId,p=async n=>{if(f=n.sessionId??f,!pe(n)){if(n.type===`stream_text_delta`){t.format===`text`&&k(n),await d.websocketSink?.sendTextDelta({sessionId:f,channel:t.channel,messageId:e.messageId,user:e.user,text:n.text});return}t.format===`text`&&k(n),await a?.send({sessionId:f,channel:t.channel,messageId:e.messageId,user:e.user,type:`progress`,event:n})}};c&&await p(c),await p({type:`hitl_resumed`,requestId:e.requestId,resolution:n,sessionId:e.sessionId}),`idempotentReplay`in r&&r.idempotentReplay&&(M.info(`resume command treated as idempotent replay`,{sessionId:e.sessionId,requestId:e.requestId,idempotencyKey:n.idempotencyKey}),Pe({sessionId:e.sessionId,text:`Resume request already processed.`,usage:{input:0,output:0,total:0},durationMs:0},t.format),i.end(),process.exit(0));let m=e.pluginsConfig??process.env.AIMAX_PLUGINS_CONFIG,h=await B(t.dataDir,m),g;try{g=await x({dataDir:t.dataDir,projectDir:tn(e.projectDir),systemAgentsDir:t.systemAgentsDir,sessionStoreName:s,sessionId:e.sessionId,messageId:e.messageId,channel:t.channel,llm:t.llm,skillsLoadPaths:t.skillsLoadPaths,autoSkills:t.autoSkills,timeoutMs:t.timeoutMs,message:u,encryptSessions:e.encryptSessions??!1,topicSegmentation:$t(e),hitlResume:{request:o.request,resolution:n,checkpoint:o.checkpoint,toolContext:o.toolContext},plugins:h?{config:h,dataDir:t.dataDir,workspaceDir:C.join(t.dataDir,`workspace`),bundledDir:process.env.AIMAX_PLUGINS_BUNDLED_DIR,llmAllowlist:h.llmAllowlist}:void 0,onProgress:p})}finally{}g.error?await a?.send({sessionId:g.sessionId,channel:t.channel,messageId:e.messageId,user:e.user,type:`error`,message:g.error}):await a?.send({sessionId:g.sessionId,channel:t.channel,messageId:e.messageId,user:e.user,type:`done`,result:{text:g.text,usage:g.usage,durationMs:g.durationMs,error:g.error,paused:g.paused,uiToolPending:g.uiToolPending}}),Pe(g,t.format),g.error?M.error(`resume command failed: ${g.error}`):M.info(`resume command succeeded`),i.end(),process.exit(g.error?1:0);return}let d=un(e,u);if(!await ce(t.dataDir,e.sessionId,e.requestId,d,{storeName:s,encryptSessions:e.encryptSessions}))throw Error(`UI tool resume validation failed`);await hn({dataDir:t.dataDir,sessionId:e.sessionId,sessionStoreName:s,result:d,encryptSessions:e.encryptSessions});let f=pn(e);a=f.sink;let p=e.sessionId,m=async n=>{if(p=n.sessionId??p,!pe(n)){if(n.type===`stream_text_delta`){t.format===`text`&&k(n),await f.websocketSink?.sendTextDelta({sessionId:p,channel:t.channel,messageId:e.messageId,user:e.user,text:n.text});return}if(t.format===`text`&&k(n),n.type===`start`){await a?.send({sessionId:p,channel:t.channel,messageId:e.messageId,user:e.user,type:`start`,message:n.message});return}await a?.send({sessionId:p,channel:t.channel,messageId:e.messageId,user:e.user,type:`progress`,event:n})}},h=await dn({dataDir:t.dataDir,sessionId:e.sessionId,sessionStoreName:s,toolCallId:d.toolCallId,toolName:d.toolName,encryptSessions:e.encryptSessions});c&&await m(c),await m({type:`tool_end`,sessionId:e.sessionId,toolCallId:d.toolCallId,name:d.toolName,input:h,output:JSON.stringify({submitted:!0,values:d.values}),isError:!1});let g=e.pluginsConfig??process.env.AIMAX_PLUGINS_CONFIG,_=await B(t.dataDir,g),v=await x({dataDir:t.dataDir,projectDir:tn(e.projectDir),systemAgentsDir:t.systemAgentsDir,sessionStoreName:s,sessionId:e.sessionId,messageId:e.messageId,channel:t.channel,llm:t.llm,skillsLoadPaths:t.skillsLoadPaths,autoSkills:t.autoSkills,timeoutMs:t.timeoutMs,message:`[UI_TOOL_RESUME]
7
- The pending UI tool result has been written into the transcript. Continue from the latest tool result without repeating the same form request.`,encryptSessions:e.encryptSessions??!1,topicSegmentation:$t(e),uiToolResume:d,plugins:_?{config:_,dataDir:t.dataDir,workspaceDir:C.join(t.dataDir,`workspace`),bundledDir:process.env.AIMAX_PLUGINS_BUNDLED_DIR,llmAllowlist:_.llmAllowlist}:void 0,onProgress:m});await o(t.dataDir,e.sessionId,{storeName:s,encryptSessions:e.encryptSessions}),v.error?await a?.send({sessionId:v.sessionId,channel:t.channel,messageId:e.messageId,user:e.user,type:`error`,message:v.error}):await a?.send({sessionId:v.sessionId,channel:t.channel,messageId:e.messageId,user:e.user,type:`done`,result:{text:v.text,usage:v.usage,durationMs:v.durationMs,error:v.error,paused:v.paused,uiToolPending:v.uiToolPending}}),Pe(v,t.format),v.error?M.error(`resume command failed: ${v.error}`):M.info(`resume command succeeded`),i.end(),process.exit(v.error?1:0)}catch(t){let n=t;a&&(n.message.includes(`expired`)&&await a.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:n.message}}),n.message.includes(`cancelled`)&&await a.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:n.message}}),await a.send({sessionId:e.sessionId,channel:e.channel??`WEB`,messageId:e.messageId,user:e.user,type:`error`,message:`Resume failed: ${n.message}`})),M.error(`resume command error: ${n.message}`),O(`Fatal: ${n.message}`),i.end(),process.exit(1)}finally{await a?.close()}})}function _n(e,t){return a(e,t)}function vn(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)`).option(`--project-dir <path>`,`Current project directory used as the default cwd context`).option(`--system-agents-dir <path>`,`System agent definition directory (overrides AIMAX_SYSTEM_AGENTS_DIR, default: /aimax/agents)`).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(`--auto-skills-load-enabled <boolean>`,`Enable learned auto-skill loading for the main agent (overrides AIMAX_AUTO_SKILLS_LOAD_ENABLED)`).option(`--auto-skills-review-mode <mode>`,`Auto-skill review mode: off, gate, dry_run, or write (overrides AIMAX_AUTO_SKILLS_REVIEW_MODE)`).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`).option(`--goal <text>`,`Set or replace the thread goal objective before resuming`).option(`--goal-file <path>`,`Read goal objective from a file`).option(`--token-budget <n>`,`Token budget for the goal (positive integer, or 0 for unlimited)`).option(`--force`,`Replace existing goal with a different objective`).option(`--encrypt-sessions`,`Enable encryption for the .aimax data directory`).option(`--disable-topic-segmentation`,`Disable smart topic segmentation for this resume run`).action(async e=>{await gn(e)})}const yn=[`start`,`text`,`done`,`error`],bn=[`off`,`gate`,`dry_run`,`write`];function xn(e){if(!e?.trim())return new Set(yn);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(yn)}function Sn(e){return e.disableTopicSegmentation===!0||process.env.AIMAX_DISABLE_TOPIC_SEGMENTATION===`true`?{enabled:!1}:void 0}function Cn(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 wn(e){return e?.trim()||void 0}function Tn(e){let t=(e.systemAgentsDir??process.env.AIMAX_SYSTEM_AGENTS_DIR)?.trim();if(t){if(!C.isAbsolute(t)){let n=e.systemAgentsDir===void 0?`AIMAX_SYSTEM_AGENTS_DIR`:`--system-agents-dir`;throw Error(`Invalid ${n}: ${t}. Path must be absolute.`)}return t}}function W(e){return e?.trim()||void 0}function En(e){return e??`WEB`}function G(e){return e?y(e):void 0}function Dn(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(!C.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 On(e,t){if(e===void 0)return;let n=e.trim().toLowerCase();if(n){if([`true`,`1`,`yes`,`on`].includes(n))return!0;if([`false`,`0`,`no`,`off`].includes(n))return!1;throw Error(`Invalid ${t}: ${e}. Must be true or false.`)}}function kn(e,t){if(e===void 0)return;let n=e.trim().toLowerCase();if(n){if(bn.includes(n))return n;throw Error(`Invalid ${t}: ${e}. Must be one of off,gate,dry_run,write.`)}}function An(e){let t=e.autoSkillsLoadEnabled===void 0?On(process.env.AIMAX_AUTO_SKILLS_LOAD_ENABLED,`AIMAX_AUTO_SKILLS_LOAD_ENABLED`):On(e.autoSkillsLoadEnabled,`--auto-skills-load-enabled`),n=e.autoSkillsReviewMode===void 0?kn(process.env.AIMAX_AUTO_SKILLS_REVIEW_MODE,`AIMAX_AUTO_SKILLS_REVIEW_MODE`):kn(e.autoSkillsReviewMode,`--auto-skills-review-mode`),r={};return t!==void 0&&(r.load={enabled:t}),n!==void 0&&(r.review={mode:n}),r.load||r.review?r:void 0}function jn(e,t){return e.length<=t?e:t<=3?e.slice(0,t):`${e.slice(0,t-3)}...`}function Mn(e,t){if(t<=0)return[``];let n=[];for(let r=0;r<e.length;r+=t)n.push(e.slice(r,r+t));return n.length>0?n:[``]}function Nn(e,t,n=78){let r=Math.max(0,n-4),i=e?e.length+2:0,a=Math.max(r,i,...t.map(e=>e.length)),o=a+2,s=e?` ${jn(e,Math.max(0,a-2))} `:``,c=e?`┌${s}${`─`.repeat(Math.max(0,o-s.length))}┐`:`┌${`─`.repeat(o)}┐`,l=`└${`─`.repeat(o)}┘`;return[c,...t.flatMap(e=>Mn(e,a).map(e=>`│ ${e.padEnd(a,` `)} │`)),l].join(`
8
- `)}function Pn(e){return e.kind===`text`?`inline message (${e.message.length} chars)`:`message file (${e.messages.length} messages)`}function K(e,t=`-`){return e==null||e===``?t:String(e)}function Fn(e){return e?`set`:`unset`}function In(e){return e?`true`:`false`}function Ln(e,t){let n=G(e.sessionStore)??`sessions`,r=t.timeoutMs===void 0?`default`:`${t.timeoutMs}`,i=e.callbackUrl?`enabled`:`disabled`,a=e.streamUrl?`enabled`:`disabled`,o=Pn(t.input),s=t.input.kind===`text`?`inline`:e.fromFile??`file`,c=Be(),l=Sn(e)?.enabled===!1?`disabled`:`enabled`,u=e.pluginsConfig??process.env.AIMAX_PLUGINS_CONFIG,d=[...xn(e.streamEvents)].join(`,`),f=t.autoSkills?.load?.enabled,p=t.autoSkills?.review?.mode,m=e.tokenBudget===`0`?`unlimited`:K(e.tokenBudget);return{banner:Nn(void 0,[`AIMax CLI`,`Stateless Agent Runner`]),contextBox:Nn(`Run Context`,[`time : ${c}`,`dataDir : ${t.dataDir}`,`projectDir : ${wn(e.projectDir)??`-`}`,`systemAgents : ${t.systemAgentsDir??`/aimax/agents`}`,`agent : ${W(e.agent)??`-`}`,`channel : ${t.channel}`,`user : ${e.user??`-`}`,`message : ${e.message===void 0?`-`:`inline (${e.message.length} chars)`}`,`fromFile : ${K(e.fromFile)}`,`input : ${o}`,`skillsPaths : ${t.skillsLoadPaths.length>0?t.skillsLoadPaths.join(`,`):`-`}`,`autoSkillLoad: ${f===void 0?`-`:String(f)}`,`autoSkillRev : ${p??`-`}`,`sessionId : ${e.sessionId??`new`}`,`sessionStore : ${n}`,`messageId : ${e.messageId??`-`}`,`workspace : ${C.join(t.dataDir,`workspace`)}`,`baseUrl : ${t.llm.baseUrl}`,`apiKey : ${Fn(e.apiKey)}`,`authToken : ${Fn(e.authToken)}`,`model : ${t.llm.model}`,`contextWindow: ${K(t.llm.contextWindow)}`,`flashModel : ${K(t.llm.flashModel)}`,`callbackUrl : ${K(e.callbackUrl)}`,`streamUrl : ${K(e.streamUrl)}`,`streamAuth : ${Fn(e.streamAuthToken)}`,`streamEvents : ${d}`,`output : ${t.format}`,`callback : ${i}`,`websocket : ${a}`,`timeoutMs : ${r}`,`pluginsConfig: ${K(u)}`,`goal : ${e.goal===void 0?`-`:`inline (${e.goal.length} chars)`}`,`goalFile : ${K(e.goalFile)}`,`tokenBudget : ${m}`,`force : ${In(e.force)}`,`resumeReqId : ${K(e.resumeRequestId)}`,`resumeInput : ${e.resumeInputJson===void 0?`-`:`inline (${e.resumeInputJson.length} chars)`}`,`resumeFile : ${K(e.resumeFromFile)}`,`encryptSess : ${In(e.encryptSessions)}`,`topicSegment : ${l}`]),logContext:{time:c,channel:t.channel,user:e.user,dataDir:t.dataDir,projectDir:wn(e.projectDir),systemAgentsDir:t.systemAgentsDir,agent:W(e.agent),workspaceDir:C.join(t.dataDir,`workspace`),sessionId:e.sessionId??`new`,sessionStore:n,messageId:e.messageId,hasMessage:e.message!==void 0,fromFile:e.fromFile,skillsLoadPaths:t.skillsLoadPaths.join(`,`)||void 0,autoSkillsLoadEnabled:f,autoSkillsReviewMode:p,baseUrl:t.llm.baseUrl,hasApiKey:!!e.apiKey,hasAuthToken:!!e.authToken,model:t.llm.model,contextWindow:t.llm.contextWindow,flashModel:t.llm.flashModel,callbackUrl:e.callbackUrl,streamUrl:e.streamUrl,hasStreamAuthToken:!!e.streamAuthToken,streamEvents:d,output:t.format,hasCallback:!!e.callbackUrl,hasStream:!!e.streamUrl,timeoutMs:t.timeoutMs,pluginsConfig:u,hasGoal:e.goal!==void 0,goalFile:e.goalFile,tokenBudget:m===`-`?void 0:m,force:!!e.force,resumeRequestId:e.resumeRequestId,hasResumeInputJson:e.resumeInputJson!==void 0,resumeFromFile:e.resumeFromFile,encryptSessions:!!e.encryptSessions,topicSegmentation:l,inputKind:t.input.kind,inputSource:s,inputSummary:o}}}async function Rn(e,t){let n=Cn(e),r=En(e.channel),i=Dt({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,systemAgentsDir:Tn(e),channel:r,format:e.output===`json`?`json`:`text`,timeoutMs:e.timeout?Number(e.timeout):void 0,llm:i,input:t,skillsLoadPaths:Dn(e.skillsLoadPaths),autoSkills:An(e)}}function zn(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(`
9
- `)}async function Bn(e,t){if(!e.sessionId)return null;let n=zn(t);if(!n)return null;let r=await ee(Cn(e),e.sessionId,{storeName:G(e.sessionStore),encryptSessions:e.encryptSessions});return!r||r.status!==`pending`||!he(n,r.request)?null:{requestId:r.request.requestId,inputText:n}}function Vn(e){let t=[],n=null;return e.callbackUrl&&t.push(new Bt(e.callbackUrl)),e.streamUrl&&(n=new Kt(e.streamUrl,xn(e.streamEvents),e.streamAuthToken),t.push(n)),{sink:new zt(t),websocketSink:n}}async function q(e,t){M.info(`dispatching external event`,or(t)),await e.sink.send(t)}function Hn(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 Un(e){let t={sessionId:e.sessionId,messageId:e.messageId,parentSessionId:e.parentSessionId,depth:e.depth,scope:e.scope,phase:e.phase,...Hn(e.details)};if(e.level===`error`){M.error(e.message,t);return}if(e.level===`warn`){M.warn(e.message,t);return}M.info(e.message,t)}function Wn(e,t,n,r,i){return{sink:e,websocketSink:t,channel:n,defaultMessageId:r,user:i}}function Gn(){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 Kn(e){return{activeSessionId:e??`pending`,finalResult:null}}function qn(e,t){e.activeSessionId=t.sessionId??e.activeSessionId}function Jn(e,t){return e.messageId??t}async function Yn(e,t,n){if(!await m(e.dataDir)){if(await J(t,e.format,n.activeSessionId,e.dataDir,`checking`),(await l(e.dataDir)).performedBootstrap){await J(t,e.format,n.activeSessionId,e.dataDir,`initializing`),await J(t,e.format,n.activeSessionId,e.dataDir,`initialized`);return}await J(t,e.format,n.activeSessionId,e.dataDir,`ready`)}}async function J(e,t,n,r,i){let a={type:`bootstrap`,phase:i,dataDir:r};t===`text`&&k(a),await q(e,{sessionId:n,channel:e.channel,messageId:e.defaultMessageId,user:e.user,type:`progress`,event:a})}function Xn(e,t,n){return async r=>{if(qn(n,r),pe(r)){Un(r);return}if(r.type===`stream_text_delta`){e.format===`text`&&k(r),await t.websocketSink?.sendTextDelta({sessionId:n.activeSessionId,channel:e.channel,messageId:Jn(r,t.defaultMessageId),user:t.user,text:r.text});return}e.format===`text`&&k(r);let i=Jn(r,t.defaultMessageId);if(r.type===`hitl_requested`){await q(t,{sessionId:n.activeSessionId,channel:e.channel,messageId:i,user:t.user,type:`hitl`,request:r.request}),await q(t,{sessionId:n.activeSessionId,channel:e.channel,messageId:i,user:t.user,type:`progress`,event:r});return}if(r.type===`start`){await q(t,{sessionId:n.activeSessionId,channel:e.channel,messageId:i,user:t.user,type:`start`,message:r.message});return}if(r.type===`session_reset`){await q(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 q(t,{sessionId:n.activeSessionId,channel:e.channel,messageId:i,user:t.user,type:`progress`,event:r})}}function Zn(e,t,n,r,i,a){let o={dataDir:t.dataDir,projectDir:wn(e.projectDir),systemAgentsDir:t.systemAgentsDir,agentPolicy:W(e.agent)?{requestedAgentName:W(e.agent)}:void 0,sessionStoreName:G(e.sessionStore),sessionId:e.sessionId,messageId:e.messageId,channel:t.channel,llm:t.llm,skillsLoadPaths:t.skillsLoadPaths,autoSkills:t.autoSkills,timeoutMs:t.timeoutMs,abortSignal:n.signal,pendingGoal:a,encryptSessions:e.encryptSessions??!1,topicSegmentation:Sn(e),plugins:i?{config:i,dataDir:t.dataDir,workspaceDir:C.join(t.dataDir,`workspace`),bundledDir:process.env.AIMAX_PLUGINS_BUNDLED_DIR,llmAllowlist:i.llmAllowlist}:void 0,onProgress:r};return t.input.kind===`messages`?{...o,messages:t.input.messages}:{...o,message:t.input.message}}async function Qn(e,t,n,r){if(t.activeSessionId=r.sessionId,t.finalResult=r,r.error){await q(e,{sessionId:r.sessionId,channel:e.channel,messageId:n,user:e.user,type:`error`,message:r.error});return}await q(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 $n(e,t,n,r){await q(e,{sessionId:t.finalResult?.sessionId??t.activeSessionId,channel:e.channel,messageId:n,user:e.user,type:`error`,message:`Fatal: ${r.message}`})}function er(e,t){let n=Ln(e,t);M.info([`run command started`,n.banner,n.contextBox].join(`
10
- `),n.logContext),t.format===`text`&&(D(n.banner),D(``),D(n.contextBox),D(``))}function tr(e,t,n){Pe(t,n),t.error?M.error(`run command failed: ${t.error}`):M.info(`run command succeeded`),e.end(),process.exit(t.error?1:0)}function nr(e){let t=Xe();if(!t)return;let n=`[${Be()}] [ERROR] ${e}\n`;try{be.appendFileSync(C.join(t.logDir,`app.log`),n),be.appendFileSync(C.join(t.logDir,`errors.log`),n)}catch{}}async function rr(e,t){let n=`run command error: ${t.message}`;M.error(n),nr(n),O(`Fatal: ${t.message}`),e.end(),await Ze(),process.exit(1)}async function ir(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 S.readFile(e.resumeFromFile,`utf-8`)}catch(e){throw Error(`Failed to read resume input file: ${e.message}`)}}async function ar(e){let t=Cn(e);j(t);let i=new N(`run command`),a=null;try{a=e.encryptSessions?await bt(t):null,a&&j(t)}catch(e){await rr(i,e);return}try{let t=await ir(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 gn({dataDir:e.dataDir,projectDir:e.projectDir,systemAgentsDir:e.systemAgentsDir,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,autoSkillsLoadEnabled:e.autoSkillsLoadEnabled,autoSkillsReviewMode:e.autoSkillsReviewMode,messageId:e.messageId,user:e.user,goal:e.goal,goalFile:e.goalFile,tokenBudget:e.tokenBudget,force:e.force,encryptSessions:e.encryptSessions,disableTopicSegmentation:e.disableTopicSegmentation});return}let a;try{a=await Rt({message:e.message,fromFile:e.fromFile})}catch(e){await rr(i,e);return}let o=await Bn(e,a);if(o){await gn({dataDir:e.dataDir,projectDir:e.projectDir,systemAgentsDir:e.systemAgentsDir,sessionId:e.sessionId,sessionStore:e.sessionStore,requestId:o.requestId,inputText:o.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,autoSkillsLoadEnabled:e.autoSkillsLoadEnabled,autoSkillsReviewMode:e.autoSkillsReviewMode,messageId:e.messageId,user:e.user,goal:e.goal,goalFile:e.goalFile,tokenBudget:e.tokenBudget,force:e.force,encryptSessions:e.encryptSessions,disableTopicSegmentation:e.disableTopicSegmentation});return}let{controller:s,cleanup:c}=Gn(),l=null,u=e.channel??`WEB`,d=Kn(e.sessionId);try{let t=await Rn(e,a);u=t.channel,er(e,t);let o=Vn(e);l=o.sink,M.info(`external sink configured`,{callbackUrl:e.callbackUrl,streamUrl:e.streamUrl,streamEvents:e.streamEvents});let c=Wn(l,o.websocketSink,t.channel,e.messageId,e.user);await Yn(t,c,d);let f,p=null;if(e.goal||e.goalFile){let i;i=e.goalFile?await S.readFile(e.goalFile,`utf-8`):e.goal;let a=qt(i),o=G(e.sessionStore),s=e.tokenBudget===void 0?void 0:e.tokenBudget===`0`||e.tokenBudget===``?null:Number(e.tokenBudget);s!=null&&(Number.isNaN(s)||s<=0)&&(O(`error: --token-budget must be a positive integer, or 0 for unlimited`),process.exit(1));try{if(e.sessionId){let n=await b(t.dataDir,e.sessionId,{storeName:o}),i=await r({dataDir:t.dataDir,sessionId:e.sessionId,objective:a,tokenBudget:s,force:e.force,storeName:o});p=Yt({sessionId:e.sessionId,before:n,result:i})}else f={objective:a,tokenBudget:s??null}}catch(e){throw e instanceof n&&(O(e.message),O(`Existing: ${e.existingObjectivePreview}`),process.exit(2)),e}}let m=e.pluginsConfig??process.env.AIMAX_PLUGINS_CONFIG,h=await B(t.dataDir,m),g=Xn(t,c,d);p&&await g(p);let _=await x(Zn(e,t,s,g,h,f));await Qn(c,d,e.messageId,_),tr(i,_,t.format)}catch(t){let n=t;l&&await $n(Wn(l,null,u,e.messageId,e.user),d,e.messageId,n),await rr(i,n)}finally{await l?.close(),c()}}finally{await a?.cleanup()}}function or(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 sr(e){e.command(`run`).description(`Run an agent task`).option(`-d, --data-dir <path>`,`Data directory path (overrides AIMAX_DATA_DIR)`).option(`--project-dir <path>`,`Current project directory used as the default cwd context`).option(`--system-agents-dir <path>`,`System agent definition directory (overrides AIMAX_SYSTEM_AGENTS_DIR, default: /aimax/agents)`).option(`--agent <name>`,`Custom agent name to run as the root agent`).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(`--auto-skills-load-enabled <boolean>`,`Enable learned auto-skill loading for the main agent (overrides AIMAX_AUTO_SKILLS_LOAD_ENABLED)`).option(`--auto-skills-review-mode <mode>`,`Auto-skill review mode: off, gate, dry_run, or write (overrides AIMAX_AUTO_SKILLS_REVIEW_MODE)`).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(`--goal <text>`,`Set or replace the thread goal objective before running`).option(`--goal-file <path>`,`Read goal objective from a file`).option(`--token-budget <n>`,`Token budget for the goal (positive integer, or 0 for unlimited)`).option(`--force`,`Replace existing goal with a different objective`).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)`).option(`--encrypt-sessions`,`Enable gocryptfs-backed encryption for the .aimax data directory`).option(`--disable-topic-segmentation`,`Disable smart topic segmentation for this run`).action(async e=>{await ar(e)})}function cr(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`).option(`--encrypt-sessions`,`Enable gocryptfs-backed encryption for the .aimax data directory`).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||(O(`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`&&(O(`Invalid channel: ${r.channel}. Must be 'H5', 'WEB', 'KLPA', 'TASK', 'CRON', or 'EIP_ASSISTANT'`),process.exit(1));try{await R(r.dataDir,r,async()=>{let e=r.sessionStore?y(r.sessionStore):void 0;if(i===`list`){Fe(await v(r.dataDir,r.channel,{storeName:e}),a);return}if(r.sessionId||(O(`error: required option '-s, --session-id <id>' not specified`),process.exit(1)),i===`inspect`){Ie(await g(r.dataDir,r.sessionId,{storeName:e}),a);return}if(i===`export`){Le(await u(r.dataDir,r.sessionId,{storeName:e}),a);return}O(`Invalid sessions action: ${i}. Must be 'list', 'inspect', or 'export'`),process.exit(1)})}catch(e){O(`${i===`inspect`?`Error inspecting session`:i===`export`?`Error exporting session`:`Error listing sessions`}: ${e.message}`),process.exit(1)}})}function lr(e){return C.join(e,`workspace`)}function ur(){let e=process.env.AIMAX_PLUGINS_BUNDLED_DIR;return e&&e.trim()||void 0}function dr(e,t){let n=[];n.push(`backend: ${e.backend}`),n.push(`provider: ${e.provider}${e.model?` (${e.model})`:``}`);let r=typeof e.custom?.providerSource==`string`?e.custom.providerSource:void 0,i=typeof e.custom?.providerId==`string`?e.custom.providerId:void 0,a=typeof e.custom?.pluginId==`string`?e.custom.pluginId:void 0;r&&n.push(`provider_source: ${r}`),i&&n.push(`provider_id: ${i}`),a&&n.push(`plugin_id: ${a}`),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}`));let o=Array.isArray(e.custom?.cliWarnings)?e.custom.cliWarnings.filter(e=>typeof e==`string`&&e.length>0):[];for(let e of o)n.push(`warning: ${e}`);return n.join(`
11
- `)}function fr(e){let t=e.level===`error`?`plugin error`:`plugin warning`;return e.pluginId?`${t} (${e.pluginId}): ${e.message}`:`${t}: ${e.message}`}function pr(e){if(!e||e===`cli`)return`cli`;if(e===`cron`)return`cron`;throw Error(`Unsupported dream trigger: ${e}. Expected "cli" or "cron".`)}async function mr(e){let t=[],n;try{n=await B(e.dataDir,e.pluginsConfig)}catch(e){t.push(`failed to load plugins config: ${e.message}`)}if(!e.shouldInitialize&&!n)return{warnings:t};try{let r=h({config:n,dataDir:e.dataDir,workspaceDir:lr(e.dataDir),bundledDir:ur()});return t.push(...r.diagnostics.map(fr)),{pluginSystem:r,warnings:t}}catch(e){return t.push(`failed to initialize plugin system: ${e.message}`),{warnings:t}}}async function hr(e){let t=C.join(e.dataDir,`.aimax`),{pluginSystem:n,warnings:r}=await mr({dataDir:e.dataDir,pluginsConfig:e.pluginsConfig,shouldInitialize:!!(e.requirePluginSystem||e.provider||e.providerPlugin)}),i=n?.normalizedConfig.slots.memory,a=e.providerPlugin?.trim()||(e.provider?void 0:i),o=oe({providerId:e.provider,pluginId:a,dataDir:e.dataDir,memoryDir:t});return o?{provider:o.provider,providerId:o.registration.id,pluginId:o.registration.pluginId,providerOrigin:`plugin`,warnings:r,pluginSystem:n}:((a||e.provider)&&r.push(`requested memory provider was not resolved; falling back to builtin provider`),{provider:s({dataDir:e.dataDir,memoryDir:t},{includeSessions:e.includeSessions}),providerId:`builtin`,providerOrigin:`builtin`,warnings:r,pluginSystem:n})}function gr(e,t,n){let r={...e.custom??{},providerSource:t.providerOrigin,providerId:t.providerId,pluginId:t.pluginId,cliWarnings:t.warnings},i={...e,custom:r};return n&&t.providerOrigin===`plugin`?i.custom={...r,note:`deep probe details are provider-defined for plugin memory providers`}:n&&(i.custom={...r,note:`deep probe is only supported by builtin provider`}),i}function _r(e){let t=e.command(`memory`).description(`Manage semantic memory indexing and search`),n=e=>e.option(`--plugins-config <path>`,`Plugins config file path`);n(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`).option(`--encrypt-sessions`,`Enable gocryptfs-backed encryption for the .aimax data directory`).action(async e=>{let t=e.output===`json`?`json`:`text`;try{await R(e.dataDir,e,async()=>{let n=await hr({dataDir:e.dataDir,provider:e.provider,providerPlugin:e.providerPlugin,pluginsConfig:e.pluginsConfig,includeSessions:e.includeSessions});e.index&&n.provider.sync&&await n.provider.sync(`cli-status`);let r=gr(n.provider.status(),n,e.deep);D(t===`json`?JSON.stringify(r,null,2):dr(r,e.deep))})}catch(e){O(`Error getting memory status: ${e.message}`),process.exit(1)}}),n(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(`--rebuild`,`Force full rebuild from Markdown source`).option(`--verbose`,`Verbose output`).option(`--encrypt-sessions`,`Enable gocryptfs-backed encryption for the .aimax data directory`).action(async e=>{try{await R(e.dataDir,e,async()=>{let t=await hr({dataDir:e.dataDir,provider:e.provider,providerPlugin:e.providerPlugin,pluginsConfig:e.pluginsConfig,includeSessions:e.includeSessions}),n;if(t.provider.sync&&(await t.provider.sync(e.rebuild?`cli-rebuild`:`cli-index`),n=t.provider.status().custom?.lastRebuildSummary),t.warnings.length>0)for(let e of t.warnings)O(`Warning: ${e}`);e.verbose&&n&&D(JSON.stringify(n,null,2)),D(e.rebuild?`Memory index rebuilt.`:`Memory index refreshed.`)})}catch(e){O(`Error indexing memory: ${e.message}`),process.exit(1)}}),n(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`).option(`--encrypt-sessions`,`Enable gocryptfs-backed encryption for the .aimax data directory`).action(async(e,t)=>{let n=t.output===`json`?`json`:`text`,r=t.query?.trim()||e?.trim();r||(O(`Query is required: provide [query] or --query <text>`),process.exit(1));try{await R(t.dataDir,t,async()=>{let e=await(await hr({dataDir:t.dataDir,provider:t.provider,providerPlugin:t.providerPlugin,pluginsConfig:t.pluginsConfig,includeSessions:t.includeSessions})).provider.search(r);if(n===`json`){D(JSON.stringify(e,null,2));return}if(e.length===0){D(`No results found for: ${r}`);return}D(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(`
12
- `))})}catch(e){O(`Error searching memory: ${e.message}`),process.exit(1)}}),n(t.command(`dream`)).description(`Trigger Dream Gate host hook for memory plugins`).requiredOption(`-d, --data-dir <path>`,`Data directory path`).option(`--provider <id>`,`Memory provider id`).option(`--provider-plugin <id>`,`Memory provider plugin id`).option(`--trigger <mode>`,`Dream Gate trigger mode: cli (default) or cron`,`cli`).option(`--dry-run`,`Return hook results without plugin-side mutation`).option(`--output <format>`,`Output format: text (default) or json`,`text`).option(`--encrypt-sessions`,`Enable gocryptfs-backed encryption for the .aimax data directory`).action(async e=>{let t=e.output===`json`?`json`:`text`;try{await R(e.dataDir,e,async()=>{let n=pr(e.trigger),r=await hr({dataDir:e.dataDir,provider:e.provider,providerPlugin:e.providerPlugin,pluginsConfig:e.pluginsConfig,requirePluginSystem:!0}),i=r.pluginSystem?await r.pluginSystem.registry.hooks.dispatch(`dream_gate`,{dataDir:e.dataDir,memoryDir:C.join(e.dataDir,`.aimax`),providerId:r.providerId,pluginId:r.pluginId,trigger:n,dryRun:!!e.dryRun},{workspaceDir:lr(e.dataDir)}):[],a={ok:!0,trigger:n,providerSource:r.providerOrigin,providerId:r.providerId,pluginId:r.pluginId,resultCount:i.length,results:i,warnings:r.warnings};if(t===`json`){D(JSON.stringify(a,null,2));return}D(`trigger: ${a.trigger}`),D(`provider_source: ${a.providerSource}`),D(`provider_id: ${a.providerId}`),a.pluginId&&D(`plugin_id: ${a.pluginId}`),D(`result_count: ${a.resultCount}`),a.results.length===0?D(`note: no dream_gate hook registered`):D(`results: ${JSON.stringify(a.results)}`);for(let e of a.warnings)D(`warning: ${e}`)})}catch(e){O(`Error running dream gate: ${e.message}`),process.exit(1)}})}function vr(e){return`${e.match.accountId?`${e.match.channel}:${e.match.accountId}`:e.match.channel} -> ${e.agentId}`}function yr(e){return async t=>{let n=await T(t),r=Te(n),i=Ee(n);if(E(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=Ae(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(` - ${vr(e)}`)}}}}function br(e,t){return async n=>{w(await T(n),De(e))&&(console.error(`Agent "${e}" already exists.`),process.exit(1)),await Ce(n,{id:e,name:t.name,model:t.model,default:t.default})||(console.error(`Agent "${e}" already exists.`),process.exit(1));let r=Ae(n,e);console.log(`Agent "${e}" added successfully.`),console.log(` Agent dir: ${r}`)}}function xr(e){return async t=>{let n=w(await T(t),De(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 Oe(t,e)||(console.error(`Failed to delete agent "${e}".`),process.exit(1)),console.log(`Agent "${e}" deleted.`)}}function Sr(e){return async t=>{let n=await T(t),r=e.agent??E(n);w(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 we(t,{agentId:r,match:{channel:e,accountId:a||void 0}}),console.log(`Binding added: ${n} -> ${r}`)}}}function Cr(e){return async t=>{let n=await T(t),r=e.agent??E(n);if(w(n,r)||(console.error(`Agent "${r}" not found.`),process.exit(1)),e.all){let e=await ke(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 ke(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 wr(e){return async t=>{let n=Ee(await T(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(` ${vr(e)}`)}}function Tr(e){return async t=>{let n=await T(t),r=e.agent??E(n);w(n,r)||(console.error(`Agent "${r}" not found.`),process.exit(1)),await je(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 Er(e,t){let n=e.command(`agents`).description(`Manage agents`),r=e=>e.option(`--encrypt-sessions`,`Enable gocryptfs-backed encryption for the .aimax data directory`);r(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 R(n,e,async()=>{await yr(e)(n)})}),r(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 R(r,n,async()=>{await br(e,n)(r)})}),r(n.command(`delete <id>`).description(`Delete an agent`)).action(async(e,n)=>{let r=t();await R(r,n,async()=>{await xr(e)(r)})}),r(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 R(n,e,async()=>{await Sr(e)(n)})}),r(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 R(n,e,async()=>{await Cr(e)(n)})}),r(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 R(n,e,async()=>{await wr(e)(n)})}),r(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 R(n,e,async()=>{await Tr(e)(n)})})}function Y(e){return C.join(e,`workspace`)}function X(){let e=process.env.AIMAX_PLUGINS_BUNDLED_DIR;return e&&e.trim()||void 0}function Dr(e){if(e.length===0){D(`No plugins discovered.`);return}for(let t of e){let e=t.status.padEnd(8,` `);D(`${t.id} ${e} ${t.origin} ${t.source}`)}}function Or(e){D(`id: ${e.id}`),D(`status: ${e.status}`),D(`origin: ${e.origin}`),D(`source: ${e.source}`),D(`enabled: ${e.enabled}`),e.error&&D(`error: ${e.error}`),D(`tools: ${e.toolCount}`),D(`hooks: ${e.hookCount}`),e.skills.length>0&&D(`skills: ${e.skills.join(`, `)}`)}function kr(e){return Array.from(new Set((e??[]).map(e=>e.trim()).filter(Boolean)))}function Ar(e){if(e.length===0){D(`LLM allowlist is empty.`);return}for(let t of e)D(t)}function jr(e,t){let n=e.command(`plugins`).description(`Manage AIMax plugins`),r=e=>e.option(`--plugins-config <path>`,`Plugins config file path`),i=e=>e.option(`--encrypt-sessions`,`Enable gocryptfs-backed encryption for the .aimax data directory`);i(r(n.command(`list`))).description(`List discovered plugins`).option(`-d, --data-dir <path>`,`Data directory path`).action(async e=>{let n=e.dataDir??t();await R(n,e,async()=>{Dr(h({config:await B(n,e.pluginsConfig),dataDir:n,workspaceDir:Y(n),bundledDir:X()}).registry.plugins)})}),i(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();await R(r,n,async()=>{let t=h({config:await B(r,n.pluginsConfig),dataDir:r,workspaceDir:Y(r),bundledDir:X()}).registry.plugins.find(t=>t.id===e);t||(O(`Plugin not found: ${e}`),process.exit(1)),Or(t)})}),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();await R(r,n,async()=>{let t=await B(r,n.pluginsConfig)??{},i=ie(t);h({config:t,dataDir:r,workspaceDir:Y(r),bundledDir:X()}).registry.plugins.some(t=>t.id===e)||(O(`Plugin not found: ${e}`),process.exit(1)),await V(r,{...t,entries:{...t.entries,[e]:{...t.entries?.[e]??{},enabled:!0}}},n.pluginsConfig),D(`Enabled ${e}`),i.allow.length>0&&!i.allow.includes(e)&&D(`Note: plugins.allow is set; add this plugin id to allowlist if needed.`)})}),i(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();await R(r,n,async()=>{let t=await B(r,n.pluginsConfig)??{};h({config:t,dataDir:r,workspaceDir:Y(r),bundledDir:X()}).registry.plugins.some(t=>t.id===e)||(O(`Plugin not found: ${e}`),process.exit(1)),await V(r,{...t,entries:{...t.entries,[e]:{...t.entries?.[e]??{},enabled:!1}}},n.pluginsConfig),D(`Disabled ${e}`)})}),i(r(n.command(`doctor`))).description(`Validate plugin configuration`).option(`-d, --data-dir <path>`,`Data directory path`).action(async e=>{let n=e.dataDir??t();await R(n,e,async()=>{let t=h({config:await B(n,e.pluginsConfig),dataDir:n,workspaceDir:Y(n),bundledDir:X()});if(t.diagnostics.length===0){D(`No plugin issues detected.`);return}for(let e of t.diagnostics)D(`${e.level===`error`?`ERROR`:`WARN`}${e.pluginId?` ${e.pluginId}`:``}: ${e.message}`);t.diagnostics.some(e=>e.level===`error`)&&process.exit(1)})});let a=n.command(`llm-allow`).description(`Manage plugin LLM allowlist`);i(r(a.command(`list`))).description(`List LLM allowlist entries`).option(`-d, --data-dir <path>`,`Data directory path`).action(async e=>{let n=e.dataDir??t();await R(n,e,async()=>{Ar(kr((await B(n,e.pluginsConfig))?.llmAllowlist))})}),i(r(a.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();await R(r,n,async()=>{let t=await B(r,n.pluginsConfig)??{},i=kr([...t.llmAllowlist??[],...e]);await V(r,{...t,llmAllowlist:i},n.pluginsConfig),D(`LLM allowlist updated (${i.length} entries).`)})}),i(r(a.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();await R(r,n,async()=>{let t=await B(r,n.pluginsConfig)??{},i=new Set(e.map(e=>e.trim()).filter(Boolean)),a=kr(t.llmAllowlist).filter(e=>!i.has(e));await V(r,{...t,llmAllowlist:a},n.pluginsConfig),D(`LLM allowlist updated (${a.length} entries).`)})}),i(r(a.command(`clear`))).description(`Clear the LLM allowlist`).option(`-d, --data-dir <path>`,`Data directory path`).action(async e=>{let n=e.dataDir??t();await R(n,e,async()=>{await V(n,{...await B(n,e.pluginsConfig)??{},llmAllowlist:[]},e.pluginsConfig),D(`LLM allowlist cleared.`)})})}function Mr(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`).option(`--encrypt-sessions`,`Enable gocryptfs-backed encryption for the .aimax data directory`).action(async e=>{let t=e.output===`json`?`json`:`text`;try{await R(e.dataDir,e,async()=>{let n=_(await ne(e.dataDir,[]));if(t===`json`){D(JSON.stringify(n,null,2));return}D(`Commands`),D(` builtin: ${n.builtin.map(e=>e.name).join(` | `)}`),n.skillCommands.length>0?D(` skills: ${n.skillCommands.map(e=>e.name).join(` | `)}`):D(` skills: (none)`)})}catch(e){O(`Error listing commands: ${e.message}`),process.exit(1)}})}function Z(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 Q(e){if(!e.sessionId)throw Error(`Session ID is required (--session-id or -s)`);return e.sessionId}function $(e){return e?y(e):void 0}async function Nr(e){let t={storeName:e.sessionStoreName},n=e.objective.trim(),r=await b(e.dataDir,e.sessionId,t);if(!r||(await ae(e.dataDir,e.sessionId,r,t)).trim()!==n)return de(e.dataDir,e.sessionId,{goalId:Me(),objective:n,status:`active`,tokenBudget:e.tokenBudget??null,tokensUsed:0,timeUsedSeconds:0},{...t,eventSource:`cli`});if(r.status===`complete`)return r;let i={};return r.status===`paused`&&(i.status=`active`),e.tokenBudget!==void 0&&e.tokenBudget!==r.tokenBudget&&(i.tokenBudget=e.tokenBudget),Object.keys(i).length===0?r:await ue(e.dataDir,e.sessionId,i,{...t,eventSource:`cli`})}async function Pr(e,t){let n=Z(t),r=Q(t),i=$(t.sessionStore),a=e.trim();a||(O(`error: objective cannot be empty`),process.exit(1));let o=t.tokenBudget===void 0||t.tokenBudget===`0`||t.tokenBudget===``?null:Number(t.tokenBudget);o!==null&&(Number.isNaN(o)||o<=0)&&(O(`error: --token-budget must be a positive integer, or 0 for unlimited`),process.exit(1));let s=await Nr({dataDir:n,sessionId:r,sessionStoreName:i,objective:a,tokenBudget:o});D(JSON.stringify({goal:s},null,2))}async function Fr(e){let t=Z(e),n=Q(e),r=$(e.sessionStore),i=await b(t,n,{storeName:r});if(!i){D(JSON.stringify({goal:null},null,2));return}let a=await ae(t,n,i,{storeName:r});D(JSON.stringify({goal:{...i,objective:a}},null,2))}async function Ir(e){let t=Z(e),n=Q(e),r=$(e.sessionStore),i=await b(t,n,{storeName:r});i||(O(`error: no goal exists for this session`),process.exit(1)),i.status===`complete`&&(O(`error: cannot pause a completed goal`),process.exit(1));let a=await ue(t,n,{status:`paused`},{storeName:r,eventSource:`cli`});D(JSON.stringify({goal:a},null,2))}async function Lr(e){let t=Z(e),n=Q(e),r=$(e.sessionStore),i=await b(t,n,{storeName:r});if(i||(O(`error: no goal exists for this session`),process.exit(1)),i.status===`complete`&&(O(`error: cannot resume a completed goal`),process.exit(1)),i.status===`budget_limited`&&(O(`error: cannot resume a budget-limited goal; clear or replace it instead`),process.exit(1)),i.status===`active`){D(JSON.stringify({goal:i},null,2));return}let a=await ue(t,n,{status:`active`},{storeName:r,eventSource:`cli`});D(JSON.stringify({goal:a},null,2))}async function Rr(e){let t=await c(Z(e),Q(e),{storeName:$(e.sessionStore),eventSource:`cli`});D(JSON.stringify({cleared:t},null,2))}function zr(e){let t=e.command(`goal`).description(`Manage thread goals for a session`);t.command(`set <objective>`).description(`Set or replace the thread goal (creates new goalId)`).option(`-d, --data-dir <path>`,`Data directory path (overrides AIMAX_DATA_DIR)`).requiredOption(`-s, --session-id <id>`,`Session ID`).option(`--session-store <name>`,`Session store directory under .aimax (default: sessions)`).option(`--token-budget <n>`,`Optional token budget (positive integer, or 0 for unlimited)`).action(async(e,t)=>{try{await Pr(e,t)}catch(e){O(`error: ${e.message}`),process.exit(1)}}),t.command(`get`).description(`Get the current goal as JSON`).option(`-d, --data-dir <path>`,`Data directory path (overrides AIMAX_DATA_DIR)`).requiredOption(`-s, --session-id <id>`,`Session ID`).option(`--session-store <name>`,`Session store directory under .aimax (default: sessions)`).action(async e=>{try{await Fr(e)}catch(e){O(`error: ${e.message}`),process.exit(1)}}),t.command(`pause`).description(`Pause the current goal`).option(`-d, --data-dir <path>`,`Data directory path (overrides AIMAX_DATA_DIR)`).requiredOption(`-s, --session-id <id>`,`Session ID`).option(`--session-store <name>`,`Session store directory under .aimax (default: sessions)`).action(async e=>{try{await Ir(e)}catch(e){O(`error: ${e.message}`),process.exit(1)}}),t.command(`resume`).description(`Resume a paused goal`).option(`-d, --data-dir <path>`,`Data directory path (overrides AIMAX_DATA_DIR)`).requiredOption(`-s, --session-id <id>`,`Session ID`).option(`--session-store <name>`,`Session store directory under .aimax (default: sessions)`).action(async e=>{try{await Lr(e)}catch(e){O(`error: ${e.message}`),process.exit(1)}}),t.command(`clear`).description(`Clear the current goal`).option(`-d, --data-dir <path>`,`Data directory path (overrides AIMAX_DATA_DIR)`).requiredOption(`-s, --session-id <id>`,`Session ID`).option(`--session-store <name>`,`Session store directory under .aimax (default: sessions)`).action(async e=>{try{await Rr(e)}catch(e){O(`error: ${e.message}`),process.exit(1)}})}const Br=[`progress`,`error`,`hitl`];function Vr(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 Hr(e){if(!e?.trim())return new Set(Br);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(Br)}function Ur(e){return e?y(e):void 0}function Wr(e){let t=[];return e.callbackUrl&&t.push(new Bt(e.callbackUrl)),e.streamUrl&&t.push(new Kt(e.streamUrl,Hr(e.streamEvents),e.streamAuthToken)),new zt(t)}async function Gr(e){let t=Vr(e);await R(t,e,async()=>{j(t);let n=new N(`cancel command`),r=e.channel??`WEB`,i=e.output===`json`?`json`:`text`,a=Wr(e),o=Ur(e.sessionStore);try{let s=await ee(t,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 se({dataDir:t,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`&&k(l),await a.send({type:`progress`,sessionId:e.sessionId,channel:r,messageId:e.messageId,event:l}),n.end(),process.exit(0)}catch(t){let i=t;await a.send({type:`error`,sessionId:e.sessionId,channel:r,messageId:e.messageId,message:i.message}),M.error(`cancel command error: ${i.message}`),O(`Fatal: ${i.message}`),n.end(),process.exit(1)}finally{await a.close()}})}function Kr(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`).option(`--encrypt-sessions`,`Enable gocryptfs-backed encryption for the .aimax data directory`).action(async e=>{await Gr(e)})}function qr(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 Jr(e){return e.query?.trim()||void 0}function Yr(e){if(!e)return;let t=Number(e);if(!Number.isFinite(t)||t<=0)throw Error(`--timeout must be a positive number of milliseconds`);return t}function Xr(e){if(!e)return;let t=Number(e);if(!Number.isInteger(t)||t<=0)throw Error(`--max-tokens must be a positive integer`);return t}async function Zr(e){if(e.filePath){if(!C.isAbsolute(e.filePath))throw Error(`--file-path must be an absolute path`);try{await S.access(e.filePath)}catch(e){throw Error(`Failed to access --file-path: ${e.message}`)}return{source:`file`,filePath:e.filePath}}let t=e.content;if(!t||!t.trim())throw Error(`Either --file-path or --content must be provided`);return{source:`content`,content:t}}async function Qr(e){let t=null;try{let n=qr(e);j(n),t=new N(`summarize command`);let r=Jr(e),i=await Zr(e),a=Dt({baseUrl:e.baseUrl,apiKey:e.apiKey,model:e.model,contextWindow:2e5}),o=Yr(e.timeout),s=Xr(e.maxTokens);M.info(`summarize command started`,{dataDir:n,source:i.source,filePath:i.source===`file`?i.filePath:void 0,queryLength:r?.length,contentLength:i.source===`content`?i.content.length:void 0,timeoutMs:o,maxTokens:s});let c=await x({dataDir:n,channel:`WEB`,message:$r(i,r),llm:{...a,maxTokens:s},timeoutMs:o});D(c.text.trim()),M.info(`summarize command succeeded`,{source:i.source,summaryLength:c.text.length,durationMs:c.durationMs}),t.end()}catch(e){M.error(`summarize command error: ${e.message}`),O(`Fatal: ${e.message}`),t?.end(),process.exit(1)}}function $r(e,t){return e.source===`file`?[t?`Summarize exactly one file for the query below.`:`Summarize exactly one file.`,`Read only the absolute file path provided here. Do not search, browse, read other files, execute commands, modify files, or perform any other processing.`,`Return only the summary text.`,``,...t?[`Query:\n${t}`,``]:[],`Input source: file`,`File path: ${e.filePath}`].join(`
13
- `):[t?`Summarize the provided content for the query below.`:`Summarize the provided content.`,t?`Use only the provided content and query. Do not search, browse, read files, execute commands, modify files, or perform any other processing.`:`Use only the provided content. Do not search, browse, read files, execute commands, modify files, or perform any other processing.`,`Return only the summary text.`,``,...t?[`Query:\n${t}`,``]:[],`Input source: content`,`Source content:`,`<source>`,e.content,`</source>`].join(`
14
- `)}function ei(e){e.command(`summarize`).description(`Summarize one absolute file path or inline content`).option(`--file-path <path>`,`Absolute file path to summarize`).option(`--content <text>`,`Inline text content to summarize when --file-path is not provided`).option(`--query <text>`,`Optional search target or current description to focus the summary`).option(`-d, --data-dir <path>`,`Data directory path (overrides AIMAX_DATA_DIR)`).option(`--base-url <url>`,`LLM API base URL (overrides AIMAX_BASE_URL)`).option(`--api-key <key>`,`LLM API key (overrides AIMAX_API_KEY)`).option(`--model <name>`,`LLM model name (overrides AIMAX_MODEL)`).option(`--timeout <ms>`,`Execution timeout in milliseconds`).option(`--max-tokens <number>`,`Maximum number of tokens for model output`).action(async e=>{await Qr(e)})}const ti=e(import.meta.url)(`../package.json`);function ni(){return process.env.AIMAX_DATA_DIR||process.cwd()}function ri(){let e=new t;return e.name(`aimax`).description(`AIMax CLI — runs agent tasks in a containerized environment`).version(ti.version),sr(e),vn(e),zr(e),Kr(e),cr(e),ei(e),Mr(e),wt(e),_r(e),Er(e,ni),jr(e,ni),e}export{Ze as a,M as i,ni as n,j as r,ri as t};