@gencode/cli 0.8.12 → 0.8.13
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 +8 -0
- package/dist/bin.js +1 -1
- package/dist/program-7zc_ihJ4.js +15 -0
- package/dist/program.js +1 -1
- package/package.json +2 -2
- package/dist/program-D3rEzXvw.js +0 -15
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,13 @@
|
|
|
1
1
|
# @gencode/cli
|
|
2
2
|
|
|
3
|
+
## 0.8.13
|
|
4
|
+
|
|
5
|
+
### Patch Changes
|
|
6
|
+
|
|
7
|
+
- a8c7e9e: Improve AIMax CLI resilience when multiple containers run against the same NAS-mounted user data directory. If the process stdout or stderr stream reports a write failure while rendering progress output, the CLI now records a local diagnostic under `<dataDir>/.aimax/logs/<messageId>/app.log`, suppresses further writes to that failed stream, and continues the agent run so callback and websocket delivery can still complete. Runtime environments should still mount shared NAS storage with working lock and sync semantics, for example the deployment-required NFS v3 plus `sync` configuration rather than `nolock`.
|
|
8
|
+
- Updated dependencies [a8c7e9e]
|
|
9
|
+
- @gencode/agents@0.10.11
|
|
10
|
+
|
|
3
11
|
## 0.8.12
|
|
4
12
|
|
|
5
13
|
### 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-
|
|
2
|
+
import{a as e,i as t,r as n,t as r}from"./program-7zc_ihJ4.js";function i(){globalThis.getPkgPath||(globalThis.getPkgPath=()=>`@wizard/aimax`)}i();function a(e){return e instanceof Error?e.stack??`${e.name}: ${e.message}`:String(e)}function o(e){let t=e.shutdownTimeoutMs??2e3,n=!1,r=(r,i)=>{if(e.logError(`Fatal ${r}: ${a(i)}`),n)return;n=!0;let o=setTimeout(()=>e.exit(1),t);typeof o.unref==`function`&&o.unref(),Promise.resolve().then(()=>e.shutdown()).catch(()=>{}).finally(()=>{clearTimeout(o),e.exit(1)})};e.proc.on(`uncaughtException`,e=>r(`uncaughtException`,e)),e.proc.on(`unhandledRejection`,e=>r(`unhandledRejection`,e))}const s=Date.now(),c=process.env.AIMAX_DATA_DIR,l=process.argv.includes(`run`)&&process.argv.includes(`--encrypt-sessions`);function u(e){for(let t=0;t<e.length;t++){let n=e[t];if(n===`--message-id`||n===`--messageId`)return e[t+1];if(n?.startsWith(`--message-id=`))return n.slice(13);if(n?.startsWith(`--messageId=`))return n.slice(12)}}c&&!l&&n(c,{messageId:u(process.argv)}),o({proc:process,logError:e=>t.error(e),shutdown:e,exit:e=>process.exit(e)}),t.info(`AIMax CLI starting (pid=${process.pid})`,{dataDir:c,encryptedRun:l,loggerDeferred:!!(c&&l)}),r().parseAsync(process.argv).catch(e=>{t.error(`Unexpected error: ${e.message}`),process.exit(1)}).finally(()=>{let n=Date.now()-s;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";import S from"node:path";import ye from"log4js";import C from"node:fs/promises";import be from"node:os";import{execFile as xe,execFileSync as Se}from"node:child_process";import Ce from"gensign-node";import{fileURLToPath as we}from"node:url";import{addAgent as Te,addBinding as Ee,getAgentConfig as w,listAgents as De,listBindings as Oe,loadAgentsConfig as T,normalizeAgentId as ke,removeAgent as Ae,removeBindings as je,resolveAgentDir as Me,resolveDefaultAgentId as Ne,updateAgentIdentity as Pe}from"@gencode/agents/config";import{randomUUID as Fe}from"node:crypto";function Ie(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 Le(e=new Date){let t=Ie(e),n=String(e.getMilliseconds()).padStart(3,`0`);return`${t.year}-${t.month}-${t.day} ${t.hour}:${t.minute}:${t.second}.${n}`}let E=function(e){return e.INFO=`INFO`,e.ERROR=`ERROR`,e.WARN=`WARN`,e}({}),Re=null;function ze(){return Le()}function Be(e){if(!e)return``;let t=Object.entries(e).filter(([,e])=>e!==void 0).map(([e,t])=>`${e}=${Ve(t)}`);return t.length>0?` ${t.join(` `)}`:``}function Ve(e){return JSON.stringify(He(e,new WeakSet))??`undefined`}function He(e,t){return typeof e==`bigint`?e.toString():e==null||typeof e==`string`||typeof e==`number`||typeof e==`boolean`?e:e instanceof Error?{name:e.name,message:e.message,stack:e.stack}:typeof e!=`object`&&typeof e!=`function`?String(e):t.has(e)?`[Circular]`:(t.add(e),Array.isArray(e)?e.map(e=>He(e,t)):Object.fromEntries(Object.entries(e).filter(([,e])=>e!==void 0).map(([e,n])=>[e,He(n,t)])))}function Ue(e){return S.join(e,`.aimax`)}function We(e){let t=e?.trim();return t&&t.replace(/[^A-Za-z0-9_.-]/g,`_`)||`no-message-${process.pid}`}function Ge(e,t){let n=We(t);return{runLogId:n,logDir:S.join(Ue(e),`logs`,n)}}function Ke(e){return{appLogPath:S.join(e,`app.log`),errorLogPath:S.join(e,`errors.log`)}}function qe(e){let{appLogPath:t,errorLogPath:n}=Ke(e);ye.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 Je(e,t,n){return`[${ze()}] [${e}] ${t}${Be(n)}`}function Ye(e,t,n){try{process.stderr.write(`${Je(e,t,n)}\n`)}catch{}}function Xe(e,t,n){if(!Re){Ye(e,t,n);return}let r=Je(e,t,n),i=ye.getLogger();if(e===E.ERROR){i.error(r);return}if(e===E.WARN){i.warn(r);return}i.info(r)}function D(e,t){let{logDir:n,runLogId:r}=Ge(e,t?.messageId);x.mkdirSync(n,{recursive:!0}),qe(n),Re={dataDir:e,logDir:n,runLogId:r}}function Ze(){return Re?{...Re}:null}async function Qe(){await ye.shutdown()}const O={info:(e,t)=>Xe(E.INFO,e,t),warn:(e,t)=>Xe(E.WARN,e,t),error:(e,t)=>Xe(E.ERROR,e,t)};var $e=class{startTime;name;constructor(e){this.name=e,this.startTime=Date.now()}end(){let e=Date.now()-this.startTime;return O.info(`${this.name} completed in ${e}ms`),e}};function et(e){if(typeof e==`string`)return e;let t=JSON.stringify(e);return t===void 0?String(e):t}const tt=new Set;function nt(e){return e instanceof Error?{name:e.name,message:e.message,code:e.code}:{message:String(e)}}function rt(e,t){try{O.warn(`CLI ${e} write failed; suppressing further ${e} writes`,{stream:e,...nt(t)})}catch{}}function it(e,t){if(tt.has(e))return;let n=e===`stdout`?process.stdout:process.stderr;try{n.write(t)}catch(t){tt.add(e),rt(e,t)}}function at(e){it(`stdout`,e)}function k(e){it(`stdout`,e+`
|
|
2
|
+
`)}function A(e){it(`stderr`,e+`
|
|
3
|
+
`)}function j(e){switch(e.type){case`start`:k(`\n[start] ${e.message}`);break;case`text`:at(e.text);break;case`stream_text_delta`:at(e.text);break;case`bootstrap`:k(`\n[bootstrap:${e.phase}] ${e.dataDir}`);break;case`session_reset`:k(`\n[session:${e.action}] ${e.message}`);break;case`tool_start`:k(`\n[tool:${e.name}] ${JSON.stringify(e.input??{})}`);break;case`tool_end`:{let t=et(e.output);k(`[tool:${e.name}] ${e.isError?`ERROR`:`OK`} ${t.slice(0,200)}`);break}case`compaction`:k(`\n[compaction${e.layer?`:${e.layer}`:``}] ${e.reason}${e.strategy?` (${e.strategy})`:``}`);break;case`skill_used`:k(`\n[skill] ${e.skillName} agent=${e.agent} task=${e.taskId}`);break;case`custom`:k(`\n[plugin:${e.pluginId}] ${e.name}${e.label?` ${e.label}`:``}${e.data?` ${JSON.stringify(e.data)}`:``}`);break;case`error`:A(`\n[error] ${e.message}`);break;case`diagnostic`:break;case`subagent_spawn`:k(`\n[subagent:spawn]${e.label?` "${e.label}"`:``} ${me(e.task)}`);break;case`subagent_complete`:k(`[subagent:${e.status}] ${me(e.task)}`);break;case`hitl_requested`:if(k(`\n[hitl:${e.request.kind}] ${e.request.title}`),k(` prompt: ${e.request.prompt}`),k(` requestId: ${e.request.requestId}`),e.request.input.mode===`choice`)for(let t of e.request.input.choices)k(` - [${t.id}] ${t.label}`);break;case`hitl_resumed`:k(`\n[hitl:resumed] requestId=${e.requestId} action=${e.resolution.action}`);break;case`hitl_expired`:k(`\n[hitl:expired] requestId=${e.requestId} reason=${e.reason}`);break;case`hitl_cancelled`:k(`\n[hitl:cancelled] requestId=${e.requestId}${e.reason?` reason=${e.reason}`:``}`);break;case`ui_tool_request`:k(`\n[ui-tool:${e.request.toolName}] ${e.request.outputSchema.title}`),k(` requestId: ${e.request.requestId}`),k(` toolCallId: ${e.request.toolCallId}`);break;case`ui_tool_result`:k(`\n[ui-tool:resumed] requestId=${e.requestId} tool=${e.toolName}`);break}}function M(e,t){if(t===`json`){e&&k(JSON.stringify(e,null,2));return}k(`
|
|
4
|
+
`),k(`session: ${e.sessionId}`),k(`duration: ${e.durationMs}ms`),k(`tokens: input=${e.usage.input} output=${e.usage.output} total=${e.usage.total}`),e.context&&(k(`context: ${e.context.snapshotPath}`),k(`tool-results: ${e.context.toolResultsDir}`)),e.error&&A(`error: ${e.error}`)}function ot(e,t){if(t===`json`){k(JSON.stringify(e,null,2));return}if(e.length===0){k(`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:—]`;k(`${t.id} ${e} [${t.channel}]${n} ${t.title}`)}}function st(e,t){if(t===`json`){k(JSON.stringify(e,null,2));return}k(`session: ${e.id}`),e.metadata&&(k(`title: ${e.metadata.title}`),k(`channel: ${e.metadata.channel}`),k(`created: ${e.metadata.createdAt}`),k(`updated: ${e.metadata.updatedAt}`)),k(`transcript: ${e.transcriptPath}`),k(`entries: ${e.transcriptEntryCount}`),k(`context: ${e.contextSnapshotPath}`),k(`session-memory: ${e.sessionMemoryPath}`),k(`collapse-log: ${e.collapseLogPath}`),k(`read-states: ${e.readStateCount}`),k(`tool-results: ${e.toolResultRefCount}`),k(`tool-results-dir: ${e.toolResultsDir}`)}function ct(e,t){if(t===`json`){k(JSON.stringify(e,null,2));return}k(`session: ${e.id}`),k(`transcript: ${e.paths.transcriptPath}`),k(`context: ${e.paths.contextSnapshotPath}`),k(`session-memory: ${e.paths.sessionMemoryPath}`),k(`collapse-log: ${e.paths.collapseLogPath}`),k(`tool-results-dir: ${e.paths.toolResultsDir}`),k(`transcript-entries: ${e.transcript.length}`),k(`read-states: ${e.context.readStates.length}`),k(`tool-results: ${e.context.toolResults.length}`),k(`collapse-spans: ${e.context.compaction.collapseSpans.length}`)}function lt(e,t){if(t===`json`){k(JSON.stringify(e,null,2));return}k(`Bootstrap completed.`),k(`dataDir: ${e.dataDir}`),k(`created dirs: ${e.createdDirs.length}`),k(`created files: ${e.createdFiles.length}`),k(`skipped dirs: ${e.skippedDirs.length}`),k(`skipped files: ${e.skippedFiles.length}`)}const ut=`.aimax`,dt=`${ut}.pre-gocryptfs.`,ft=[`app.log`,`errors.log`],pt=[`logs`],mt=[`fusermount3`,`fusermount`,`umount`],ht=[{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 gt(e){return S.join(e,`.aimax.enc`)}function _t(e){return S.join(e,ut)}function vt(e){return S.join(e,`${dt}${process.pid}.${Date.now()}`)}function yt(e){return S.join(e,`${ut}.plaintext-restore.${process.pid}.${Date.now()}`)}function bt(e){return e.replace(/\\([0-7]{3})/g,(e,t)=>String.fromCharCode(Number.parseInt(t,8)))}async function N(e){try{let t=await Ct.read(),n=S.resolve(e);for(let e of t.split(`
|
|
5
|
+
`)){if(!e.trim())continue;let t=e.split(` `);if(t.length>=5&&S.resolve(bt(t[4]??``))===n)return!0}return!1}catch{return!1}}function xt(e){try{let t=x.readFileSync(`/proc/self/mountinfo`,`utf-8`),n=S.resolve(e);for(let e of t.split(`
|
|
6
|
+
`)){if(!e.trim())continue;let t=e.split(` `);if(t.length>=5&&S.resolve(bt(t[4]??``))===n)return!0}return!1}catch{return!1}}async function St(){return await C.readFile(`/proc/self/mountinfo`,`utf-8`)}const Ct={read:St};async function P(e){try{return await C.stat(e),!0}catch(e){if(e.code===`ENOENT`)return!1;throw e}}async function F(e){await C.mkdir(e,{recursive:!0})}async function wt(e){if(await F(e),(await C.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 Tt(e){return await P(e)?(await C.readdir(e)).length===0:!0}async function I(e){if(await P(e))return(await C.readdir(e)).length}async function Et(e){if(!await P(e))return!1;let t=await C.readdir(e,{withFileTypes:!0});for(let e of t)if(!(e.isDirectory()&&pt.includes(e.name))&&!(e.isFile()&&ft.some(t=>e.name.startsWith(t))))return!0;return!1}async function Dt(e){let t=await C.readdir(e,{withFileTypes:!0});for(let n of t){if(n.isDirectory()&&pt.includes(n.name)){await C.rm(S.join(e,n.name),{recursive:!0,force:!0}).catch(()=>{});continue}n.isFile()&&ft.some(e=>n.name.startsWith(e))&&await C.rm(S.join(e,n.name),{force:!0}).catch(()=>{})}}async function Ot(e){if(!await P(S.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 kt(e){return(await C.readdir(e,{withFileTypes:!0})).filter(e=>e.isDirectory()&&e.name.startsWith(dt)).map(t=>S.join(e,t.name)).sort()}async function L(e,t){if(!await P(t))return null;let n=vt(e);return O.info(`--encrypt-sessions moving plaintext .aimax aside before migration`,{plainDir:t,backupDir:n}),await C.rename(t,n),n}async function R(e,t,n){O.info(`--encrypt-sessions copying plaintext backup into encrypted mount`,{backupDir:e,plainDir:t,force:n}),await C.cp(e,t,{recursive:!0,force:n})}async function At(e,t){if(e.length===0)return[];await F(t);let n=[];for(let r of e)await P(r)&&(await R(r,t,!0),await C.rm(r,{recursive:!0,force:!0}),O.info(`--encrypt-sessions restored interrupted plaintext backup after failed migration`,{backupDir:r,plainDir:t}),n.push(r));return n}async function jt(e){let t=gt(e),n=_t(e),r=await P(t);if(!r)return;let i=r&&await P(S.join(t,`gocryptfs.conf`)),a=await P(n),o=a?await N(n):!1,s=await Tt(n);if(O.info(`plaintext .aimax restore check for disabled --encrypt-sessions`,{dataDir:e,encryptedDir:t,plainDir:n,encryptedDirExists:r,encryptedDirInitialized:i,plainDirExists:a,plainDirMountPoint:o,plainDirEntryCount:await I(n)}),!i){O.warn(`plaintext .aimax restore skipped because .aimax.enc is not initialized`,{encryptedDir:t,plainDir:n}),await F(n);return}if(o){O.warn(`plaintext .aimax restore skipped because .aimax is already a mount point`,{plainDir:n,encryptedDir:t});return}if(await Et(n)){O.info(`plaintext .aimax restore skipped because plaintext .aimax already contains data`,{plainDir:n,encryptedDir:t,plainDirEntryCount:await I(n)});return}s||(O.info(`plaintext .aimax clearing ephemeral files before restore`,{plainDir:n,encryptedDir:t,plainDirEntryCount:await I(n)}),await Dt(n));try{await Pt()}catch(e){O.warn(`plaintext .aimax restore unavailable; continuing with plaintext .aimax`,{error:e instanceof Error?e.message:String(e),plainDir:n,encryptedDir:t}),await F(n);return}let c=yt(e),l=!1;try{await wt(n),await Ft(t,n),l=!0,await C.rm(c,{recursive:!0,force:!0}),await F(c),await C.cp(n,c,{recursive:!0,force:!0}),O.info(`plaintext .aimax restore copied encrypted history to staging directory`,{plainDir:n,encryptedDir:t,restoreDir:c,restoredEntryCount:await I(c)}),await Lt(n),l=!1,await C.rm(n,{recursive:!0,force:!0}),await C.rename(c,n),O.info(`plaintext .aimax restore completed for disabled --encrypt-sessions`,{plainDir:n,encryptedDir:t})}catch(e){l&&await Lt(n).catch(e=>{O.warn(`plaintext .aimax restore failed to unmount during rollback`,{error:e instanceof Error?e.message:String(e),plainDir:n,encryptedDir:t})}),await C.rm(c,{recursive:!0,force:!0}).catch(()=>{}),await F(n).catch(()=>{}),O.warn(`plaintext .aimax restore failed; continuing with existing plaintext .aimax`,{error:e instanceof Error?e.message:String(e),plainDir:n,encryptedDir:t})}}async function Mt(e){let t=S.join(be.tmpdir(),`aimax-gocryptfs-pass.${process.pid}.${Date.now()}`);await C.writeFile(t,`wizard_aimax@2026
|
|
7
|
+
`,{mode:384});try{return await e(t)}finally{await C.rm(t,{force:!0})}}async function Nt(e){let t=e.includes(`-init`)?`init`:`mount`;O.info(`--encrypt-sessions starting gocryptfs ${t}`);try{await Vt(`gocryptfs`,e),O.info(`--encrypt-sessions completed gocryptfs ${t}`)}catch(n){let r=n instanceof Error?n.message:String(n);throw O.warn(`--encrypt-sessions failed gocryptfs ${t}`,{error:r}),Error(`gocryptfs ${e.join(` `)} failed: ${r}`)}}async function Pt(){O.info(`--encrypt-sessions checking encryption dependencies`),await Ut(`gocryptfs`,`required for --encrypt-sessions`),O.info(`--encrypt-sessions dependency available`,{command:`gocryptfs`});for(let e of mt)if(await Ht(e)){O.info(`--encrypt-sessions unmount dependency available`,{command:e});return}throw Error(`--encrypt-sessions requires one of ${mt.join(`, `)} to be installed for secure unmount cleanup.`)}async function Ft(e,t){O.info(`--encrypt-sessions mounting encrypted .aimax`,{encryptedDir:e,plainDir:t}),await Mt(async n=>{await Nt([`-q`,`-passfile`,n,e,t])})}async function It(e){O.info(`--encrypt-sessions initializing encrypted .aimax directory`,{encryptedDir:e}),await Mt(async t=>{await Nt([`-q`,`-init`,`-passfile`,t,e])})}async function Lt(e){let t=[];O.info(`--encrypt-sessions unmounting encrypted .aimax`,{plainDir:e});for(let n of ht)try{if(O.info(`--encrypt-sessions attempting encrypted .aimax unmount`,{command:n.label,plainDir:e}),await Vt(n.command,[...n.args,e]),!await N(e)){O.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),O.warn(`--encrypt-sessions unmount command returned success but mountpoint remains`,{command:n.label,plainDir:e})}catch(r){let i=Wt(n.label,r);t.push(i),O.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 Rt(e){for(let t of ht)try{if(Se(t.command,[...t.args,e],{stdio:`ignore`}),!xt(e))return}catch{}}function zt(e){let t=!1,n=()=>{t||(t=!0,Rt(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=gt(e),n=_t(e),r=await P(n),i=await P(t),a=i&&await P(S.join(t,`gocryptfs.conf`)),o=r?await N(n):!1;O.info(`--encrypt-sessions preparing encrypted .aimax mount`,{dataDir:e,encryptedDir:t,plainDir:n,plainDirExists:r,encryptedDirExists:i,encryptedDirInitialized:a,plainDirMountPoint:o,plainDirEntryCount:await I(n),encryptedDirEntryCount:await I(t)});let s=()=>({mounted:!1,plainDir:n,encryptedDir:t,async cleanup(){}});try{await Pt()}catch(e){return O.warn(`--encrypt-sessions is unavailable; continuing with plaintext .aimax`,{error:e instanceof Error?e.message:String(e)}),await F(n),s()}if(await N(n))return O.warn(`--encrypt-sessions found existing .aimax mount; continuing without taking ownership`,{plainDir:n}),s();let c=null,l=[],u=null,d=null,f=!1;try{if(l=await kt(e),l.length>0&&O.warn(`--encrypt-sessions found interrupted pre-gocryptfs migration backups`,{count:l.length}),!await P(t))if(O.info(`--encrypt-sessions encrypted .aimax directory does not exist; starting first-time migration`,{encryptedDir:t,plainDir:n,resumedBackupCount:l.length}),l.length>0?u=await L(e,n):c=await L(e,n),await F(t),await It(t),await F(n),await Ft(t,n),f=!0,d=zt(n),O.info(`--encrypt-sessions mounted encrypted .aimax`,{plainDir:n,encryptedDir:t}),l.length>0){for(let e of l)await R(e,n,!0);u&&=(await R(u,n,!1),await C.rm(u,{recursive:!0,force:!0}),O.info(`--encrypt-sessions removed residual plaintext backup after migration`,{backupDir:u}),null);for(let e of l)await C.rm(e,{recursive:!0,force:!0}),O.info(`--encrypt-sessions removed resumed plaintext migration backup`,{backupDir:e});l=[]}else c&&=(await R(c,n,!0),await C.rm(c,{recursive:!0,force:!0}),O.info(`--encrypt-sessions removed plaintext migration backup`,{backupDir:c}),null);else if(O.info(`--encrypt-sessions encrypted .aimax directory exists; mounting existing encrypted data`,{encryptedDir:t,plainDir:n,resumedBackupCount:l.length,plainDirEntryCount:await I(n)}),await Ot(t),l.length>0?u=await L(e,n):await Tt(n)||(c=await L(e,n)),await wt(n),await Ft(t,n),f=!0,d=zt(n),O.info(`--encrypt-sessions mounted encrypted .aimax`,{plainDir:n,encryptedDir:t}),l.length>0){for(let e of l)await R(e,n,!0);u&&=(await R(u,n,!1),await C.rm(u,{recursive:!0,force:!0}),O.info(`--encrypt-sessions removed residual plaintext backup after migration`,{backupDir:u}),null);for(let e of l)await C.rm(e,{recursive:!0,force:!0}),O.info(`--encrypt-sessions removed resumed plaintext migration backup`,{backupDir:e});l=[]}else c&&=(await R(c,n,!0),await C.rm(c,{recursive:!0,force:!0}),O.info(`--encrypt-sessions removed plaintext migration backup`,{backupDir:c}),null);return O.info(`--encrypt-sessions prepared encrypted .aimax mount result`,{mounted:f,plainDir:n,encryptedDir:t,plainDirMountPoint:await N(n),plainDirEntryCount:await I(n),encryptedDirEntryCount:await I(t)}),{mounted:f,plainDir:n,encryptedDir:t,async cleanup(){if(d?.release(),!f){O.info(`--encrypt-sessions cleanup skipped because encrypted .aimax is not mounted`,{plainDir:n,encryptedDir:t});return}f=!1,O.info(`--encrypt-sessions cleanup started`,{plainDir:n,encryptedDir:t});try{await Lt(n),O.info(`--encrypt-sessions cleanup completed`,{plainDir:n,encryptedDir:t})}catch(e){O.warn(`--encrypt-sessions failed to unmount encrypted .aimax; continuing shutdown`,{error:e instanceof Error?e.message:String(e)})}}}}catch(e){d?.release(),f&&await Lt(n).catch(e=>{O.warn(`--encrypt-sessions failed to unmount during mount rollback`,{error:e instanceof Error?e.message:String(e),plainDir:n,encryptedDir:t})}),c&&await P(c)&&await Tt(n)&&(await C.rm(n,{recursive:!0,force:!0}).catch(()=>{}),await C.rename(c,n).catch(()=>{}),O.info(`--encrypt-sessions restored plaintext backup after failed migration`,{backupDir:c,plainDir:n})),u&&await P(u)&&await Tt(n)&&(await C.rm(n,{recursive:!0,force:!0}).catch(()=>{}),await C.rename(u,n).catch(()=>{}),O.info(`--encrypt-sessions restored residual plaintext backup after failed migration`,{backupDir:u,plainDir:n}));let r=await At(l,n).catch(e=>(O.warn(`--encrypt-sessions failed to restore interrupted plaintext backups after failed migration`,{error:e instanceof Error?e.message:String(e),plainDir:n,backupCount:l.length}),[]));return l=l.filter(e=>!r.includes(e)),O.warn(`--encrypt-sessions failed; continuing with plaintext .aimax`,{error:e instanceof Error?e.message:String(e),mountedBeforeFailure:f,plainDir:n,encryptedDir:t,backupDir:c,residualPlainBackupDir:u,resumedBackupCount:l.length}),await F(n),s()}}async function z(e,t,n){if(!t.encryptSessions)return await jt(e),n();O.info(`--encrypt-sessions wrapper starting encrypted .aimax preparation`,{dataDir:e});let r=await Bt(e);O.info(`--encrypt-sessions wrapper prepared encrypted .aimax state`,{dataDir:e,mounted:r.mounted,plainDir:r.plainDir,encryptedDir:r.encryptedDir});try{return O.info(`--encrypt-sessions wrapper entering protected operation`,{dataDir:e,mounted:r.mounted}),await n(r)}finally{O.info(`--encrypt-sessions wrapper starting cleanup`,{dataDir:e,mounted:r.mounted,plainDir:r.plainDir,encryptedDir:r.encryptedDir}),await r.cleanup(),O.info(`--encrypt-sessions wrapper finished cleanup`,{dataDir:e,mounted:r.mounted,plainDir:r.plainDir,encryptedDir:r.encryptedDir})}}async function Vt(e,t){await new Promise((n,r)=>{xe(e,t,{encoding:`utf-8`},e=>{if(e){r(e);return}n()})})}async function Ht(e){try{return await Vt(`sh`,[`-c`,`command -v "${e}" >/dev/null 2>&1`]),!0}catch{return!1}}async function Ut(e,t){if(!await Ht(e))throw Error(`--encrypt-sessions requires ${e}: ${t}.`)}function Wt(e,t){return`${e} failed: ${t instanceof Error?t.message:String(t)}`}function Gt(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{lt(await z(e.dataDir,e,async()=>i(e.dataDir)),t)}catch(e){A(`Error bootstrapping data directory: ${e.message}`),process.exit(1)}})}function Kt(e){return Ce.sm4_encrypt_ecb(e)}function qt(e){return Kt(e)}function Jt(e={}){let t=Yt(e.apiFormat??process.env.AIMAX_API_FORMAT),n=e.baseUrl??process.env.AIMAX_BASE_URL,r=process.env.AIMAX_AUTH_TOKEN,i=e.authToken?qt(e.authToken):r?qt(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 Yt(e){if(!e||e===`openai-completions`||e===`anthropic-messages`)return e;throw Error(`Unsupported LLM API format: ${e}`)}function Xt(e,t){return t?S.resolve(t):S.join(e,`.aimax`,`plugins.json`)}async function B(e,t){let n=Xt(e,t);try{let e=await C.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=Xt(e,n);await C.mkdir(S.dirname(r),{recursive:!0}),await C.writeFile(r,JSON.stringify(t,null,2),`utf-8`)}function H(e){return typeof e==`object`&&!!e}function Zt(e){return H(e)&&e.type===`text`&&typeof e.text==`string`&&(e.textSignature===void 0||typeof e.textSignature==`string`)}function Qt(e){return H(e)&&e.type===`image`&&typeof e.data==`string`&&typeof e.mimeType==`string`}function $t(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 en(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 tn(e){return typeof e==`string`||Array.isArray(e)&&e.every(e=>Zt(e)||Qt(e))}function nn(e){return Array.isArray(e)&&e.every(e=>Zt(e)||$t(e)||en(e))}function rn(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 an(e){return!H(e)||typeof e.role!=`string`?!1:e.role===`user`?tn(e.content):e.role===`assistant`?nn(e.content)&&typeof e.api==`string`&&typeof e.provider==`string`&&typeof e.model==`string`&&rn(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=>Zt(e)||Qt(e))&&typeof e.isError==`boolean`:!1}async function on(e){let t;try{t=await C.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=>an(e)))throw Error(`Message file must contain one Message object or an array of Message objects`);return r}async function sn(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 on(e.fromFile)}:{kind:`text`,message:e.message}}var cn=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()}))}},ln=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=un(e);O.info(`sending callback event`,{callbackUrl:this.url,...n});let r=new AbortController,i=!1,a=setTimeout(()=>{i=!0,r.abort()},5e3);try{let a=await fetch(this.url,{method:`POST`,headers:{"content-type":`application/json`},body:JSON.stringify(e),signal:r.signal}),o=Date.now()-t;if(!a.ok){O.error(`callback event failed`,{callbackUrl:this.url,httpStatus:a.status,durationMs:o,timedOut:i,...n});return}O.info(`callback event delivered`,{callbackUrl:this.url,httpStatus:a.status,durationMs:o,...n})}catch(e){let r=Date.now()-t;O.error(`callback event failed`,{callbackUrl:this.url,error:e instanceof Error?e.message:String(e),durationMs:r,timedOut:i,...n})}finally{clearTimeout(a)}}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 un(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 dn(e,t){if(t.kind===`none`)return e;let n=new URL(e);return n.searchParams.set(`authToken`,t.token),n.toString()}const U=5e3,fn=5e3;function W(){let e=globalThis.WebSocket;if(!e)throw Error(`WebSocket is not available in this runtime`);return e}function pn(e){return e?{kind:`query_token`,token:e}:{kind:`none`}}function mn(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 hn(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 gn=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 _n(this.ensureConnected(),U,`WebSocket connection timed out after ${U}ms`);let e=W();if(!this.socket||this.socket.readyState!==e.OPEN)return;this.socket.send(JSON.stringify(t))}catch(e){O.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 _n(this.ensureConnected(),U,`WebSocket connection timed out after ${U}ms`);let e=W();if(!this.socket||this.socket.readyState!==e.OPEN)return;this.socket.send(JSON.stringify(t))}catch(e){O.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=W();if(e.readyState!==t.CLOSED)try{await _n(new Promise(t=>{mn(e,`close`,()=>t()),e.close()}),fn,`WebSocket close timed out after ${fn}ms`)}catch(e){O.warn(`websocket sink close timed out`,{url:this.url,error:e instanceof Error?e.message:String(e)})}}async ensureConnected(){if(!this.enabled)return;let e=W();if(this.socket&&this.socket.readyState===e.OPEN)return;if(this.connectPromise){await this.connectPromise;return}let t=new e(dn(this.url,pn(this.authToken)));this.connectPromise=new Promise((e,n)=>{mn(t,`open`,()=>{this.socket=t,hn(t,`close`,()=>{this.socket===t&&(this.socket=null)}),e()}),mn(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 _n(e,t,n){return new Promise((r,i)=>{let a=setTimeout(()=>i(Error(n)),t);e.then(e=>{clearTimeout(a),r(e)},e=>{clearTimeout(a),i(e)})})}function vn(e){let t=e.trim();if(!t)throw Error(`Goal objective cannot be empty`);return t}function yn(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 bn(e){let t=yn(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}function xn(e){let t=e?.packageRoot??Sn(),n=S.join(t,`models`),r=S.join(n,...`Xenova/bge-small-zh-v1.5`.split(`/`));if(x.existsSync(S.join(r,`config.json`)))return n}function Sn(){let e=S.dirname(we(import.meta.url));return S.basename(e)===`src`||S.basename(e)===`dist`?S.resolve(e,`..`):e}const Cn=[`start`,`text`,`done`,`error`,`hitl`],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`);r.add(e)}return r.size>0?r:new Set(Cn)}function En(e){if(e.disableTopicSegmentation===!0||process.env.AIMAX_DISABLE_TOPIC_SEGMENTATION===`true`)return{enabled:!1};let t=xn();return t?{embeddingModelDir:t}: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 or AIMAX_DATA_DIR`);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(!S.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 An(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(!S.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){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 In(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 Ln(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 Rn(e){let t=Dn(e),n=e.channel??`WEB`,r=Jt({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:kn(e),channel:n,format:e.output===`json`?`json`:`text`,timeoutMs:e.timeout?Number(e.timeout):void 0,llm:r,skillsLoadPaths:jn(e.skillsLoadPaths),autoSkills:Pn(e)}}function zn(e){let t=[],n=null;return e.callbackUrl&&t.push(new ln(e.callbackUrl)),e.streamUrl&&(n=new gn(e.streamUrl,Tn(e.streamEvents),e.streamAuthToken),t.push(n)),{sink:new cn(t),websocketSink:n}}async function Bn(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 Vn(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 Hn(e){let t=Dn(e);await z(t,e,async()=>{D(t,{messageId:e.messageId});let i=new $e(`resume command`),a=null;try{let t=await Rn(e),o=An(e.sessionStore),c=null;if(e.goal||e.goalFile){let i;i=e.goalFile?await C.readFile(e.goalFile,`utf-8`):e.goal;let a=vn(i),s=e.tokenBudget===void 0?void 0:e.tokenBudget===`0`||e.tokenBudget===``?null:Number(e.tokenBudget);s!=null&&(Number.isNaN(s)||s<=0)&&(A(`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=bn({sessionId:e.sessionId,before:n,result:i})}catch(e){throw e instanceof n&&(A(e.message),A(`Existing: ${e.existingObjectivePreview}`),process.exit(2)),e}}O.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=Fn(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=Un(n,s.request.kind);await Bn({dataDir:t.dataDir,sessionId:e.sessionId,sessionStoreName:o,toolCallId:s.toolContext?.toolCallId,toolName:s.toolContext?.toolName,resolution:n,encryptSessions:e.encryptSessions});let d=zn(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`&&j(n),await d.websocketSink?.sendTextDelta({sessionId:f,channel:t.channel,messageId:e.messageId,user:e.user,text:n.text});return}t.format===`text`&&j(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&&(O.info(`resume command treated as idempotent replay`,{sessionId:e.sessionId,requestId:e.requestId,idempotencyKey:n.idempotencyKey}),M({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:En(e),hitlResume:{request:s.request,resolution:n,checkpoint:s.checkpoint,toolContext:s.toolContext},plugins:h?{config:h,dataDir:t.dataDir,workspaceDir:S.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}}),M(g,t.format),g.error?O.error(`resume command failed: ${g.error}`):O.info(`resume command succeeded`),i.end(),process.exit(g.error?1:0);return}let d=In(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 Vn({dataDir:t.dataDir,sessionId:e.sessionId,sessionStoreName:o,result:d,encryptSessions:e.encryptSessions});let f=zn(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`&&j(n),await f.websocketSink?.sendTextDelta({sessionId:p,channel:t.channel,messageId:e.messageId,user:e.user,text:n.text});return}if(t.format===`text`&&j(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 Ln({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:En(e),uiToolResume:d,plugins:_?{config:_,dataDir:t.dataDir,workspaceDir:S.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}}),M(v,t.format),v.error?O.error(`resume command failed: ${v.error}`):O.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}`})),O.error(`resume command error: ${n.message}`),A(`Fatal: ${n.message}`),i.end(),process.exit(1)}finally{await a?.close()}})}function Un(e,t){return o(e,t)}function Wn(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 Hn(e)})}const Gn=[`start`,`text`,`done`,`error`],Kn=[`off`,`gate`,`dry_run`,`write`];function qn(e){if(!e?.trim())return new Set(Gn);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(Gn)}function Jn(e){if(e.disableTopicSegmentation===!0||process.env.AIMAX_DISABLE_TOPIC_SEGMENTATION===`true`)return{enabled:!1};let t=xn();return t?{embeddingModelDir:t}:void 0}function Yn(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 Xn(e){return e?.trim()||void 0}function Zn(e){let t=(e.systemAgentsDir??process.env.AIMAX_SYSTEM_AGENTS_DIR)?.trim();if(t){if(!S.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 G(e){return e?.trim()||void 0}function Qn(e){return e??`WEB`}function K(e){return e?y(e):void 0}function $n(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(!S.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 er(e){let t=``;for(let n=0;n<e.length;n+=1){let r=e[n];if(r===`\\`&&n+1<e.length){let r=e[n+1];if(r===`,`||r===`\\`||r===`=`){t+=r,n+=1;continue}}t+=r}return t}function tr(e){let t=[],n=``;for(let r=0;r<e.length;r+=1){let i=e[r];if(i===`\\`&&r+1<e.length){let t=e[r+1];if(t===`,`||t===`\\`){n+=t,r+=1;continue}}if(i===`,`){t.push(n),n=``;continue}n+=i}return t.push(n),t}function nr(e){if(!e?.trim())return{};let t=[],n=new Set;for(let r of tr(e)){let e=r.trim();if(!e)continue;let i=e.indexOf(`=`);if(i<=0)throw Error(`Invalid --env entry: ${e}. Expected KEY=VALUE (use \\= to embed an equals sign in the value).`);let a=e.slice(0,i).trim(),o=e.slice(i+1).trim();if(!a)throw Error(`Invalid --env entry: ${e}. Key must not be empty.`);if(n.has(a))throw Error(`Invalid --env entry: duplicate key ${a}.`);n.add(a),t.push([a,er(o)])}return Object.fromEntries(t)}function rr(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 ir(e,t){if(e===void 0)return;let n=e.trim().toLowerCase();if(n){if(Kn.includes(n))return n;throw Error(`Invalid ${t}: ${e}. Must be one of off,gate,dry_run,write.`)}}function ar(e){let t=e.autoSkillsLoadEnabled===void 0?rr(process.env.AIMAX_AUTO_SKILLS_LOAD_ENABLED,`AIMAX_AUTO_SKILLS_LOAD_ENABLED`):rr(e.autoSkillsLoadEnabled,`--auto-skills-load-enabled`),n=e.autoSkillsReviewMode===void 0?ir(process.env.AIMAX_AUTO_SKILLS_REVIEW_MODE,`AIMAX_AUTO_SKILLS_REVIEW_MODE`):ir(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 or(e,t){return e.length<=t?e:t<=3?e.slice(0,t):`${e.slice(0,t-3)}...`}function sr(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 cr(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?` ${or(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=>sr(e,a).map(e=>`│ ${e.padEnd(a,` `)} │`)),l].join(`
|
|
9
|
+
`)}function lr(e){return e.kind===`text`?`inline message (${e.message.length} chars)`:`message file (${e.messages.length} messages)`}function q(e,t=`-`){return e==null||e===``?t:String(e)}function ur(e){return e?`set`:`unset`}function dr(e){return e?`true`:`false`}function fr(e,t){let n=K(e.sessionStore)??`sessions`,r=t.timeoutMs===void 0?`default`:`${t.timeoutMs}`,i=e.callbackUrl?`enabled`:`disabled`,a=e.streamUrl?`enabled`:`disabled`,o=lr(t.input),s=t.input.kind===`text`?`inline`:e.fromFile??`file`,c=Le(),l=Jn(e)?.enabled===!1?`disabled`:`enabled`,u=e.pluginsConfig??process.env.AIMAX_PLUGINS_CONFIG,d=[...qn(e.streamEvents)].join(`,`),f=t.autoSkills?.load?.enabled,p=t.autoSkills?.review?.mode,m=e.tokenBudget===`0`?`unlimited`:q(e.tokenBudget),h=e.env?Object.keys(nr(e.env)):[],g=h.length===0?`-`:`${h.length} key${h.length===1?``:`s`}`;return{banner:cr(void 0,[`AIMax CLI`,`Stateless Agent Runner`]),contextBox:cr(`Run Context`,[`time : ${c}`,`dataDir : ${t.dataDir}`,`projectDir : ${Xn(e.projectDir)??`-`}`,`systemAgents : ${t.systemAgentsDir??`/aimax/agents`}`,`agent : ${G(e.agent)??`-`}`,`channel : ${t.channel}`,`user : ${e.user??`-`}`,`message : ${e.message===void 0?`-`:`inline (${e.message.length} chars)`}`,`fromFile : ${q(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 : ${S.join(t.dataDir,`workspace`)}`,`baseUrl : ${t.llm.baseUrl}`,`apiKey : ${ur(e.apiKey)}`,`authToken : ${ur(e.authToken)}`,`model : ${t.llm.model}`,`contextWindow: ${q(t.llm.contextWindow)}`,`flashModel : ${q(t.llm.flashModel)}`,`callbackUrl : ${q(e.callbackUrl)}`,`streamUrl : ${q(e.streamUrl)}`,`streamAuth : ${ur(e.streamAuthToken)}`,`streamEvents : ${d}`,`output : ${t.format}`,`callback : ${i}`,`websocket : ${a}`,`timeoutMs : ${r}`,`pluginsConfig: ${q(u)}`,`env : ${g}`,`goal : ${e.goal===void 0?`-`:`inline (${e.goal.length} chars)`}`,`goalFile : ${q(e.goalFile)}`,`tokenBudget : ${m}`,`force : ${dr(e.force)}`,`resumeReqId : ${q(e.resumeRequestId)}`,`resumeInput : ${e.resumeInputJson===void 0?`-`:`inline (${e.resumeInputJson.length} chars)`}`,`resumeFile : ${q(e.resumeFromFile)}`,`encryptSess : ${dr(e.encryptSessions)}`,`topicSegment : ${l}`]),logContext:{time:c,channel:t.channel,user:e.user,dataDir:t.dataDir,projectDir:Xn(e.projectDir),systemAgentsDir:t.systemAgentsDir,agent:G(e.agent),workspaceDir:S.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,envKeys:h.length>0?h.join(`,`):void 0,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 pr(e,t){let n=Yn(e),r=Qn(e.channel),i=Jt({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:Zn(e),channel:r,format:e.output===`json`?`json`:`text`,timeoutMs:e.timeout?Number(e.timeout):void 0,llm:i,input:t,skillsLoadPaths:$n(e.skillsLoadPaths),autoSkills:ar(e)}}function mr(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 hr(e,t){if(!e.sessionId)return null;let n=mr(t);if(!n)return null;let r=await te(Yn(e),e.sessionId,{storeName:K(e.sessionStore),encryptSessions:e.encryptSessions});return!r||r.status!==`pending`||!_e(n,r.request)?null:{requestId:r.request.requestId,inputText:n}}function gr(e){let t=[],n=null;return e.callbackUrl&&t.push(new ln(e.callbackUrl)),e.streamUrl&&(n=new gn(e.streamUrl,qn(e.streamEvents),e.streamAuthToken),t.push(n)),{sink:new cn(t),websocketSink:n}}async function J(e,t){O.info(`dispatching external event`,Fr(t)),await e.sink.send(t)}function _r(e){let t={sessionId:e.sessionId,messageId:e.messageId,parentSessionId:e.parentSessionId,depth:e.depth,scope:e.scope,phase:e.phase,...e.details};if(e.level===`error`){O.error(e.message,t);return}if(e.level===`warn`){O.warn(e.message,t);return}O.info(e.message,t)}function vr(e,t,n,r,i){return{sink:e,websocketSink:t,channel:n,defaultMessageId:r,user:i}}function yr(e){let t=new AbortController,n=n=>{O.warn(`run abort signal received`,{signal:n,uptimeMs:Math.round(process.uptime()*1e3),alreadyAborted:t.signal.aborted,...e?.()}),t.abort()},r=()=>n(`SIGTERM`),i=()=>n(`SIGINT`);return process.once(`SIGTERM`,r),process.once(`SIGINT`,i),{controller:t,cleanup:()=>{process.off(`SIGTERM`,r),process.off(`SIGINT`,i)}}}function br(e){return{activeSessionId:e??`pending`,finalResult:null}}function xr(e,t){e.activeSessionId=t.sessionId??e.activeSessionId}function Sr(e,t){return e.messageId??t}async function Cr(e,t,n){if(!await h(e.dataDir)){if(await wr(t,e.format,n.activeSessionId,e.dataDir,`checking`),(await u(e.dataDir)).performedBootstrap){await wr(t,e.format,n.activeSessionId,e.dataDir,`initializing`),await wr(t,e.format,n.activeSessionId,e.dataDir,`initialized`);return}await wr(t,e.format,n.activeSessionId,e.dataDir,`ready`)}}async function wr(e,t,n,r,i){let a={type:`bootstrap`,phase:i,dataDir:r};t===`text`&&j(a),await J(e,{sessionId:n,channel:e.channel,messageId:e.defaultMessageId,user:e.user,type:`progress`,event:a})}function Tr(e,t,n){return async r=>{if(xr(n,r),he(r)){_r(r);return}if(r.type===`stream_text_delta`){e.format===`text`&&j(r),await t.websocketSink?.sendTextDelta({sessionId:n.activeSessionId,channel:e.channel,messageId:Sr(r,t.defaultMessageId),user:t.user,text:r.text});return}e.format===`text`&&j(r);let i=Sr(r,t.defaultMessageId);if(r.type===`hitl_requested`){await J(t,{sessionId:n.activeSessionId,channel:e.channel,messageId:i,user:t.user,type:`hitl`,request:r.request}),await J(t,{sessionId:n.activeSessionId,channel:e.channel,messageId:i,user:t.user,type:`progress`,event:r});return}if(r.type===`start`){await J(t,{sessionId:n.activeSessionId,channel:e.channel,messageId:i,user:t.user,type:`start`,message:r.message});return}if(r.type===`session_reset`){await J(t,{sessionId:n.activeSessionId,channel:e.channel,messageId:i,user:t.user,type:`session_reset`,action:r.action,previousSessionId:r.previousSessionId,message:r.message});return}await J(t,{sessionId:n.activeSessionId,channel:e.channel,messageId:i,user:t.user,type:`progress`,event:r})}}function Er(e,t,n,r,i,a){let o={dataDir:t.dataDir,projectDir:Xn(e.projectDir),systemAgentsDir:t.systemAgentsDir,agentPolicy:G(e.agent)?{requestedAgentName:G(e.agent)}:void 0,sessionStoreName:K(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:Jn(e),env:nr(e.env),plugins:i?{config:i,dataDir:t.dataDir,workspaceDir:S.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 Dr(e,t,n,r){if(t.activeSessionId=r.sessionId,t.finalResult=r,r.error){await J(e,{sessionId:r.sessionId,channel:e.channel,messageId:n,user:e.user,type:`error`,message:r.error});return}await J(e,{sessionId:r.sessionId,channel:e.channel,messageId:n,user:e.user,type:`done`,result:{text:r.text,usage:r.usage,durationMs:r.durationMs,error:r.error,paused:r.paused}})}async function Or(e,t,n,r){await J(e,{sessionId:t.finalResult?.sessionId??t.activeSessionId,channel:e.channel,messageId:n,user:e.user,type:`error`,message:`Fatal: ${r.message}`})}function kr(e,t){let n=fr(e,t);O.info([`run command started`,n.banner,n.contextBox].join(`
|
|
11
|
+
`),n.logContext),t.format===`text`&&(k(n.banner),k(``),k(n.contextBox),k(``))}function Ar(e,t,n){return M(t,n),t.error?O.error(`run command failed: ${t.error}`):O.info(`run command succeeded`),e.end(),t.error?1:0}function jr(e){let t=Ze();if(!t)return;let n=`[${Le()}] [ERROR] ${e}\n`;try{x.appendFileSync(S.join(t.logDir,`app.log`),n),x.appendFileSync(S.join(t.logDir,`errors.log`),n)}catch{}}async function Mr(e,t){let n=`run command error: ${t.message}`;O.error(n),jr(n),A(`Fatal: ${t.message}`),e.end(),await Qe(),process.exit(1)}async function Nr(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 C.readFile(e.resumeFromFile,`utf-8`)}catch(e){throw Error(`Failed to read resume input file: ${e.message}`)}}async function Pr(e){let t=Yn(e);await z(t,e,async i=>{D(t,{messageId:e.messageId}),e.encryptSessions&&O.info(`--encrypt-sessions run mount state after logger initialization`,{dataDir:t,mounted:i?.mounted??!1,plainDir:i?.plainDir,encryptedDir:i?.encryptedDir});let a=new $e(`run command`),o=await Nr(e);if(e.resumeRequestId||o||e.resumeFromFile){if(!e.sessionId||!e.resumeRequestId||!o)throw Error(`--session-id, --resume-request-id, and exactly one of --resume-input-json or --resume-from-file must be provided together`);await Hn({dataDir:e.dataDir,projectDir:e.projectDir,systemAgentsDir:e.systemAgentsDir,sessionId:e.sessionId,sessionStore:e.sessionStore,requestId:e.resumeRequestId,inputJson:o,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 s;try{s=await sn({message:e.message,fromFile:e.fromFile})}catch(e){await Mr(a,e);return}let c=await hr(e,s);if(c){await Hn({dataDir:e.dataDir,projectDir:e.projectDir,systemAgentsDir:e.systemAgentsDir,sessionId:e.sessionId,sessionStore:e.sessionStore,requestId:c.requestId,inputText:c.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 l=e.channel??`WEB`,u=br(e.sessionId),{controller:d,cleanup:f}=yr(()=>({activeSessionId:u.activeSessionId,finalSessionId:u.finalResult?.sessionId,messageId:e.messageId,channel:l,user:e.user})),p=null;try{let t=await pr(e,s);l=t.channel,kr(e,t);let i=gr(e);p=i.sink,O.info(`external sink configured`,{callbackUrl:e.callbackUrl,streamUrl:e.streamUrl,streamEvents:e.streamEvents});let o=vr(p,i.websocketSink,t.channel,e.messageId,e.user);await Cr(t,o,u);let c,f=null;if(e.goal||e.goalFile){let i;i=e.goalFile?await C.readFile(e.goalFile,`utf-8`):e.goal;let a=vn(i),o=K(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)&&(A(`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});f=bn({sessionId:e.sessionId,before:n,result:i})}else c={objective:a,tokenBudget:s??null}}catch(e){throw e instanceof n&&(A(e.message),A(`Existing: ${e.existingObjectivePreview}`),process.exit(2)),e}}let m=e.pluginsConfig??process.env.AIMAX_PLUGINS_CONFIG,h=await B(t.dataDir,m),g=Tr(t,o,u);f&&await g(f);let _=await de(Er(e,t,d,g,h,c));await Dr(o,u,e.messageId,_),process.exitCode=Ar(a,_,t.format)}catch(t){let n=t;p&&await Or(vr(p,null,l,e.messageId,e.user),u,e.messageId,n),await Mr(a,n)}finally{await p?.close(),f()}})}function Fr(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 Ir(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`).option(`--output <format>`,`Output format: text (default) or json`,`text`).option(`--plugins-config <path>`,`Plugins config file path`).option(`--env <kvlist>`,`Session-scoped env vars injected into the run. Comma-separated KEY=VALUE pairs. Backslash-escape "," and "=" inside values. Available to plugins via api.runtime.session.env and merged into child process environments spawned by the exec/process tools.`).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 Pr(e)})}function Lr(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||(A(`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`&&(A(`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`){ot(await ee(r.dataDir,r.channel,{storeName:e}),a);return}if(r.sessionId||(A(`error: required option '-s, --session-id <id>' not specified`),process.exit(1)),i===`inspect`){st(await _(r.dataDir,r.sessionId,{storeName:e}),a);return}if(i===`export`){ct(await d(r.dataDir,r.sessionId,{storeName:e}),a);return}A(`Invalid sessions action: ${i}. Must be 'list', 'inspect', or 'export'`),process.exit(1)})}catch(e){A(`${i===`inspect`?`Error inspecting session`:i===`export`?`Error exporting session`:`Error listing sessions`}: ${e.message}`),process.exit(1)}})}function Rr(e){return S.join(e,`workspace`)}function zr(){let e=process.env.AIMAX_PLUGINS_BUNDLED_DIR;return e&&e.trim()||void 0}function Br(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 Vr(e){let t=e.level===`error`?`plugin error`:`plugin warning`;return e.pluginId?`${t} (${e.pluginId}): ${e.message}`:`${t}: ${e.message}`}function Hr(e){if(!e||e===`cli`)return`cli`;if(e===`cron`)return`cron`;throw Error(`Unsupported dream trigger: ${e}. Expected "cli" or "cron".`)}async function Ur(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:Rr(e.dataDir),bundledDir:zr()});return t.push(...r.diagnostics.map(Vr)),{pluginSystem:r,warnings:t}}catch(e){return t.push(`failed to initialize plugin system: ${e.message}`),{warnings:t}}}async function Wr(e){let t=S.join(e.dataDir,`.aimax`),{pluginSystem:n,warnings:r}=await Ur({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 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 Kr(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 Wr({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);k(t===`json`?JSON.stringify(r,null,2):Br(r,e.deep))})}catch(e){A(`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 Wr({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)A(`Warning: ${e}`);e.verbose&&n&&k(JSON.stringify(n,null,2)),k(e.rebuild?`Memory index rebuilt.`:`Memory index refreshed.`)})}catch(e){A(`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||(A(`Query is required: provide [query] or --query <text>`),process.exit(1));try{await z(t.dataDir,t,async()=>{let e=await(await Wr({dataDir:t.dataDir,provider:t.provider,providerPlugin:t.providerPlugin,pluginsConfig:t.pluginsConfig,includeSessions:t.includeSessions})).provider.search(r);if(n===`json`){k(JSON.stringify(e,null,2));return}if(e.length===0){k(`No results found for: ${r}`);return}k(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){A(`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=Hr(e.trigger),r=await Wr({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:S.join(e.dataDir,`.aimax`),providerId:r.providerId,pluginId:r.pluginId,trigger:n,dryRun:!!e.dryRun},{workspaceDir:Rr(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`){k(JSON.stringify(a,null,2));return}k(`trigger: ${a.trigger}`),k(`provider_source: ${a.providerSource}`),k(`provider_id: ${a.providerId}`),a.pluginId&&k(`plugin_id: ${a.pluginId}`),k(`result_count: ${a.resultCount}`),a.results.length===0?k(`note: no dream_gate hook registered`):k(`results: ${JSON.stringify(a.results)}`);for(let e of a.warnings)k(`warning: ${e}`)})}catch(e){A(`Error running dream gate: ${e.message}`),process.exit(1)}})}function qr(e){return`${e.match.accountId?`${e.match.channel}:${e.match.accountId}`:e.match.channel} -> ${e.agentId}`}function Jr(e){return async t=>{let n=await T(t),r=De(n),i=Oe(n);if(Ne(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=Me(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(` - ${qr(e)}`)}}}}function Yr(e,t){return async n=>{w(await T(n),ke(e))&&(console.error(`Agent "${e}" already exists.`),process.exit(1)),await Te(n,{id:e,name:t.name,model:t.model,default:t.default})||(console.error(`Agent "${e}" already exists.`),process.exit(1));let r=Me(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),ke(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 Ae(t,e)||(console.error(`Failed to delete agent "${e}".`),process.exit(1)),console.log(`Agent "${e}" deleted.`)}}function Zr(e){return async t=>{let n=await T(t),r=e.agent??Ne(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 Ee(t,{agentId:r,match:{channel:e,accountId:a||void 0}}),console.log(`Binding added: ${n} -> ${r}`)}}}function Qr(e){return async t=>{let n=await T(t),r=e.agent??Ne(n);if(w(n,r)||(console.error(`Agent "${r}" not found.`),process.exit(1)),e.all){let e=await je(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 je(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 $r(e){return async t=>{let n=Oe(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(` ${qr(e)}`)}}function ei(e){return async t=>{let n=await T(t),r=e.agent??Ne(n);w(n,r)||(console.error(`Agent "${r}" not found.`),process.exit(1)),await Pe(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 ti(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 Jr(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 Yr(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 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 z(n,e,async()=>{await Zr(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 Qr(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 $r(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 ei(e)(n)})})}function Y(e){return S.join(e,`workspace`)}function X(){let e=process.env.AIMAX_PLUGINS_BUNDLED_DIR;return e&&e.trim()||void 0}function ni(e){if(e.length===0){k(`No plugins discovered.`);return}for(let t of e){let e=t.status.padEnd(8,` `);k(`${t.id} ${e} ${t.origin} ${t.source}`)}}function ri(e){k(`id: ${e.id}`),k(`status: ${e.status}`),k(`origin: ${e.origin}`),k(`source: ${e.source}`),k(`enabled: ${e.enabled}`),e.error&&k(`error: ${e.error}`),k(`tools: ${e.toolCount}`),k(`hooks: ${e.hookCount}`),e.skills.length>0&&k(`skills: ${e.skills.join(`, `)}`)}function ii(e){return Array.from(new Set((e??[]).map(e=>e.trim()).filter(Boolean)))}function ai(e){if(e.length===0){k(`LLM allowlist is empty.`);return}for(let t of e)k(t)}function oi(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()=>{ni(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||(A(`Plugin not found: ${e}`),process.exit(1)),ri(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)||(A(`Plugin not found: ${e}`),process.exit(1)),await V(r,{...t,entries:{...t.entries,[e]:{...t.entries?.[e]??{},enabled:!0}}},n.pluginsConfig),k(`Enabled ${e}`),i.allow.length>0&&!i.allow.includes(e)&&k(`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)||(A(`Plugin not found: ${e}`),process.exit(1)),await V(r,{...t,entries:{...t.entries,[e]:{...t.entries?.[e]??{},enabled:!1}}},n.pluginsConfig),k(`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){k(`No plugin issues detected.`);return}for(let e of t.diagnostics)k(`${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()=>{ai(ii((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=ii([...t.llmAllowlist??[],...e]);await V(r,{...t,llmAllowlist:i},n.pluginsConfig),k(`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=ii(t.llmAllowlist).filter(e=>!i.has(e));await V(r,{...t,llmAllowlist:a},n.pluginsConfig),k(`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),k(`LLM allowlist cleared.`)})})}function si(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`){k(JSON.stringify(n,null,2));return}k(`Commands`),k(` builtin: ${n.builtin.map(e=>e.name).join(` | `)}`),n.skillCommands.length>0?k(` skills: ${n.skillCommands.map(e=>e.name).join(` | `)}`):k(` skills: (none)`)})}catch(e){A(`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 ci(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:Fe(),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 li(e,t){let n=Z(t),r=Q(t),i=$(t.sessionStore),a=e.trim();a||(A(`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)&&(A(`error: --token-budget must be a positive integer, or 0 for unlimited`),process.exit(1));let s=await ci({dataDir:n,sessionId:r,sessionStoreName:i,objective:a,tokenBudget:o});k(JSON.stringify({goal:s},null,2))}async function ui(e){let t=Z(e),n=Q(e),r=$(e.sessionStore),i=await b(t,n,{storeName:r});if(!i){k(JSON.stringify({goal:null},null,2));return}let a=await oe(t,n,i,{storeName:r});k(JSON.stringify({goal:{...i,objective:a}},null,2))}async function di(e){let t=Z(e),n=Q(e),r=$(e.sessionStore),i=await b(t,n,{storeName:r});i||(A(`error: no goal exists for this session`),process.exit(1)),i.status===`complete`&&(A(`error: cannot pause a completed goal`),process.exit(1));let a=await fe(t,n,{status:`paused`},{storeName:r,eventSource:`cli`});k(JSON.stringify({goal:a},null,2))}async function fi(e){let t=Z(e),n=Q(e),r=$(e.sessionStore),i=await b(t,n,{storeName:r});if(i||(A(`error: no goal exists for this session`),process.exit(1)),i.status===`complete`&&(A(`error: cannot resume a completed goal`),process.exit(1)),i.status===`budget_limited`&&(A(`error: cannot resume a budget-limited goal; clear or replace it instead`),process.exit(1)),i.status===`active`){k(JSON.stringify({goal:i},null,2));return}let a=await fe(t,n,{status:`active`},{storeName:r,eventSource:`cli`});k(JSON.stringify({goal:a},null,2))}async function pi(e){let t=await l(Z(e),Q(e),{storeName:$(e.sessionStore),eventSource:`cli`});k(JSON.stringify({cleared:t},null,2))}function mi(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 li(e,t)}catch(e){A(`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 ui(e)}catch(e){A(`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 di(e)}catch(e){A(`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 fi(e)}catch(e){A(`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 pi(e)}catch(e){A(`error: ${e.message}`),process.exit(1)}})}const hi=[`progress`,`error`,`hitl`];function gi(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 _i(e){if(!e?.trim())return new Set(hi);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(hi)}function vi(e){return e?y(e):void 0}function yi(e){let t=[];return e.callbackUrl&&t.push(new ln(e.callbackUrl)),e.streamUrl&&t.push(new gn(e.streamUrl,_i(e.streamEvents),e.streamAuthToken)),new cn(t)}async function bi(e){let t=gi(e);await z(t,e,async()=>{D(t,{messageId:e.messageId});let n=new $e(`cancel command`),r=e.channel??`WEB`,i=e.output===`json`?`json`:`text`,a=yi(e),o=vi(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`&&j(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}),O.error(`cancel command error: ${i.message}`),A(`Fatal: ${i.message}`),n.end(),process.exit(1)}finally{await a.close()}})}function xi(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 bi(e)})}function Si(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 Ci(e){return e.query?.trim()||void 0}function wi(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 Ti(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 Ei(e){if(e.filePath){if(!S.isAbsolute(e.filePath))throw Error(`--file-path must be an absolute path`);try{await C.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 Di(e){let t=null;try{let n=Si(e);D(n,{messageId:e.messageId}),t=new $e(`summarize command`);let r=Ci(e),i=await Ei(e),a=Jt({apiFormat:e.apiFormat,baseUrl:e.baseUrl,apiKey:e.apiKey,model:e.model,contextWindow:2e5}),o=wi(e.timeout),s=Ti(e.maxTokens);O.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`,messageId:e.messageId,message:Oi(i,r),llm:{...a,maxTokens:s},timeoutMs:o});k(c.text.trim()),O.info(`summarize command succeeded`,{source:i.source,summaryLength:c.text.length,durationMs:c.durationMs}),t.end()}catch(e){O.error(`summarize command error: ${e.message}`),A(`Fatal: ${e.message}`),t?.end(),process.exit(1)}}function Oi(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 ki(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`).option(`--message-id <id>`,`Message ID for log correlation`).action(async e=>{await Di(e)})}const Ai=e(import.meta.url)(`../package.json`);function ji(){return process.env.AIMAX_DATA_DIR||process.cwd()}function Mi(){let e=new t;return e.name(`aimax`).description(`AIMax CLI — runs agent tasks in a containerized environment`).version(Ai.version),Ir(e),Wn(e),mi(e),xi(e),Lr(e),ki(e),si(e),Gt(e),Kr(e),ti(e,ji),oi(e,ji),e}export{Qe as a,O as i,ji as n,D as r,Mi as t};
|
package/dist/program.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
import{n as e,t}from"./program-
|
|
1
|
+
import{n as e,t}from"./program-7zc_ihJ4.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.8.
|
|
3
|
+
"version": "0.8.13",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"bin": {
|
|
6
6
|
"aimax": "./dist/bin.js"
|
|
@@ -23,7 +23,7 @@
|
|
|
23
23
|
"commander": "^14.0.3",
|
|
24
24
|
"gensign-node": "latest",
|
|
25
25
|
"log4js": "^6.9.1",
|
|
26
|
-
"@gencode/agents": "0.10.
|
|
26
|
+
"@gencode/agents": "0.10.11",
|
|
27
27
|
"@gencode/shared": "0.2.1"
|
|
28
28
|
},
|
|
29
29
|
"devDependencies": {
|
package/dist/program-D3rEzXvw.js
DELETED
|
@@ -1,15 +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,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{fileURLToPath as we}from"node:url";import{addAgent as Te,addBinding as Ee,getAgentConfig as w,listAgents as De,listBindings as Oe,loadAgentsConfig as T,normalizeAgentId as ke,removeAgent as Ae,removeBindings as je,resolveAgentDir as Me,resolveDefaultAgentId as E,updateAgentIdentity as Ne}from"@gencode/agents/config";import{randomUUID as Pe}from"node:crypto";function Fe(e){if(typeof e==`string`)return e;let t=JSON.stringify(e);return t===void 0?String(e):t}function Ie(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`:Ie(e.text);break;case`stream_text_delta`:Ie(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`:{let t=Fe(e.output);D(`[tool:${e.name}] ${e.isError?`ERROR`:`OK`} ${t.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 Le(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 Re(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 ze(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 Be(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 Ve(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 He(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 Ue(e=new Date){let t=He(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 We(){return Ue()}function Ge(e){if(!e)return``;let t=Object.entries(e).filter(([,e])=>e!==void 0).map(([e,t])=>`${e}=${Ke(t)}`);return t.length>0?` ${t.join(` `)}`:``}function Ke(e){return JSON.stringify(qe(e,new WeakSet))??`undefined`}function qe(e,t){return typeof e==`bigint`?e.toString():e==null||typeof e==`string`||typeof e==`number`||typeof e==`boolean`?e:e instanceof Error?{name:e.name,message:e.message,stack:e.stack}:typeof e!=`object`&&typeof e!=`function`?String(e):t.has(e)?`[Circular]`:(t.add(e),Array.isArray(e)?e.map(e=>qe(e,t)):Object.fromEntries(Object.entries(e).filter(([,e])=>e!==void 0).map(([e,n])=>[e,qe(n,t)])))}function Je(e){return C.join(e,`.aimax`)}function Ye(e){let t=e?.trim();return t&&t.replace(/[^A-Za-z0-9_.-]/g,`_`)||`no-message-${process.pid}`}function Xe(e,t){let n=Ye(t);return{runLogId:n,logDir:C.join(Je(e),`logs`,n)}}function Ze(e){return{appLogPath:C.join(e,`app.log`),errorLogPath:C.join(e,`errors.log`)}}function Qe(e){let{appLogPath:t,errorLogPath:n}=Ze(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 $e(e,t,n){return`[${We()}] [${e}] ${t}${Ge(n)}`}function et(e,t,n){process.stderr.write(`${$e(e,t,n)}\n`)}function tt(e,t,n){if(!j){et(e,t,n);return}let r=$e(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,t){let{logDir:n,runLogId:r}=Xe(e,t?.messageId);S.mkdirSync(n,{recursive:!0}),Qe(n),j={dataDir:e,logDir:n,runLogId:r}}function nt(){return j?{...j}:null}async function rt(){await Se.shutdown()}const N={info:(e,t)=>tt(A.INFO,e,t),warn:(e,t)=>tt(A.WARN,e,t),error:(e,t)=>tt(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 it=`.aimax`,at=`${it}.pre-gocryptfs.`,ot=[`app.log`,`errors.log`],st=[`logs`],ct=[`fusermount3`,`fusermount`,`umount`],lt=[{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 ut(e){return C.join(e,`.aimax.enc`)}function dt(e){return C.join(e,it)}function ft(e){return C.join(e,`${at}${process.pid}.${Date.now()}`)}function pt(e){return C.join(e,`${it}.plaintext-restore.${process.pid}.${Date.now()}`)}function mt(e){return e.replace(/\\([0-7]{3})/g,(e,t)=>String.fromCharCode(Number.parseInt(t,8)))}async function F(e){try{let t=await _t.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(mt(t[4]??``))===n)return!0}return!1}catch{return!1}}function ht(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(mt(t[4]??``))===n)return!0}return!1}catch{return!1}}async function gt(){return await x.readFile(`/proc/self/mountinfo`,`utf-8`)}const _t={read:gt};async function I(e){try{return await x.stat(e),!0}catch(e){if(e.code===`ENOENT`)return!1;throw e}}async function L(e){await x.mkdir(e,{recursive:!0})}async function vt(e){if(await L(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 yt(e){return await I(e)?(await x.readdir(e)).length===0:!0}async function R(e){if(await I(e))return(await x.readdir(e)).length}async function bt(e){if(!await I(e))return!1;let t=await x.readdir(e,{withFileTypes:!0});for(let e of t)if(!(e.isDirectory()&&st.includes(e.name))&&!(e.isFile()&&ot.some(t=>e.name.startsWith(t))))return!0;return!1}async function xt(e){let t=await x.readdir(e,{withFileTypes:!0});for(let n of t){if(n.isDirectory()&&st.includes(n.name)){await x.rm(C.join(e,n.name),{recursive:!0,force:!0}).catch(()=>{});continue}n.isFile()&&ot.some(e=>n.name.startsWith(e))&&await x.rm(C.join(e,n.name),{force:!0}).catch(()=>{})}}async function St(e){if(!await I(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 Ct(e){return(await x.readdir(e,{withFileTypes:!0})).filter(e=>e.isDirectory()&&e.name.startsWith(at)).map(t=>C.join(e,t.name)).sort()}async function wt(e,t){if(!await I(t))return null;let n=ft(e);return N.info(`--encrypt-sessions moving plaintext .aimax aside before migration`,{plainDir:t,backupDir:n}),await x.rename(t,n),n}async function z(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 Tt(e,t){if(e.length===0)return[];await L(t);let n=[];for(let r of e)await I(r)&&(await z(r,t,!0),await x.rm(r,{recursive:!0,force:!0}),N.info(`--encrypt-sessions restored interrupted plaintext backup after failed migration`,{backupDir:r,plainDir:t}),n.push(r));return n}async function Et(e){let t=ut(e),n=dt(e),r=await I(t);if(!r)return;let i=r&&await I(C.join(t,`gocryptfs.conf`)),a=await I(n),o=a?await F(n):!1,s=await yt(n);if(N.info(`plaintext .aimax restore check for disabled --encrypt-sessions`,{dataDir:e,encryptedDir:t,plainDir:n,encryptedDirExists:r,encryptedDirInitialized:i,plainDirExists:a,plainDirMountPoint:o,plainDirEntryCount:await R(n)}),!i){N.warn(`plaintext .aimax restore skipped because .aimax.enc is not initialized`,{encryptedDir:t,plainDir:n}),await L(n);return}if(o){N.warn(`plaintext .aimax restore skipped because .aimax is already a mount point`,{plainDir:n,encryptedDir:t});return}if(await bt(n)){N.info(`plaintext .aimax restore skipped because plaintext .aimax already contains data`,{plainDir:n,encryptedDir:t,plainDirEntryCount:await R(n)});return}s||(N.info(`plaintext .aimax clearing ephemeral files before restore`,{plainDir:n,encryptedDir:t,plainDirEntryCount:await R(n)}),await xt(n));try{await kt()}catch(e){N.warn(`plaintext .aimax restore unavailable; continuing with plaintext .aimax`,{error:e instanceof Error?e.message:String(e),plainDir:n,encryptedDir:t}),await L(n);return}let c=pt(e),l=!1;try{await vt(n),await At(t,n),l=!0,await x.rm(c,{recursive:!0,force:!0}),await L(c),await x.cp(n,c,{recursive:!0,force:!0}),N.info(`plaintext .aimax restore copied encrypted history to staging directory`,{plainDir:n,encryptedDir:t,restoreDir:c,restoredEntryCount:await R(c)}),await B(n),l=!1,await x.rm(n,{recursive:!0,force:!0}),await x.rename(c,n),N.info(`plaintext .aimax restore completed for disabled --encrypt-sessions`,{plainDir:n,encryptedDir:t})}catch(e){l&&await B(n).catch(e=>{N.warn(`plaintext .aimax restore failed to unmount during rollback`,{error:e instanceof Error?e.message:String(e),plainDir:n,encryptedDir:t})}),await x.rm(c,{recursive:!0,force:!0}).catch(()=>{}),await L(n).catch(()=>{}),N.warn(`plaintext .aimax restore failed; continuing with existing plaintext .aimax`,{error:e instanceof Error?e.message:String(e),plainDir:n,encryptedDir:t})}}async function Dt(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 Ot(e){let t=e.includes(`-init`)?`init`:`mount`;N.info(`--encrypt-sessions starting gocryptfs ${t}`);try{await Ft(`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 kt(){N.info(`--encrypt-sessions checking encryption dependencies`),await Lt(`gocryptfs`,`required for --encrypt-sessions`),N.info(`--encrypt-sessions dependency available`,{command:`gocryptfs`});for(let e of ct)if(await It(e)){N.info(`--encrypt-sessions unmount dependency available`,{command:e});return}throw Error(`--encrypt-sessions requires one of ${ct.join(`, `)} to be installed for secure unmount cleanup.`)}async function At(e,t){N.info(`--encrypt-sessions mounting encrypted .aimax`,{encryptedDir:e,plainDir:t}),await Dt(async n=>{await Ot([`-q`,`-passfile`,n,e,t])})}async function jt(e){N.info(`--encrypt-sessions initializing encrypted .aimax directory`,{encryptedDir:e}),await Dt(async t=>{await Ot([`-q`,`-init`,`-passfile`,t,e])})}async function B(e){let t=[];N.info(`--encrypt-sessions unmounting encrypted .aimax`,{plainDir:e});for(let n of lt)try{if(N.info(`--encrypt-sessions attempting encrypted .aimax unmount`,{command:n.label,plainDir:e}),await Ft(n.command,[...n.args,e]),!await F(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=Rt(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 Mt(e){for(let t of lt)try{if(xe(t.command,[...t.args,e],{stdio:`ignore`}),!ht(e))return}catch{}}function Nt(e){let t=!1,n=()=>{t||(t=!0,Mt(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 Pt(e){let t=ut(e),n=dt(e),r=await I(n),i=await I(t),a=i&&await I(C.join(t,`gocryptfs.conf`)),o=r?await F(n):!1;N.info(`--encrypt-sessions preparing encrypted .aimax mount`,{dataDir:e,encryptedDir:t,plainDir:n,plainDirExists:r,encryptedDirExists:i,encryptedDirInitialized:a,plainDirMountPoint:o,plainDirEntryCount:await R(n),encryptedDirEntryCount:await R(t)});let s=()=>({mounted:!1,plainDir:n,encryptedDir:t,async cleanup(){}});try{await kt()}catch(e){return N.warn(`--encrypt-sessions is unavailable; continuing with plaintext .aimax`,{error:e instanceof Error?e.message:String(e)}),await L(n),s()}if(await F(n))return N.warn(`--encrypt-sessions found existing .aimax mount; continuing without taking ownership`,{plainDir:n}),s();let c=null,l=[],u=null,d=null,f=!1;try{if(l=await Ct(e),l.length>0&&N.warn(`--encrypt-sessions found interrupted pre-gocryptfs migration backups`,{count:l.length}),!await I(t))if(N.info(`--encrypt-sessions encrypted .aimax directory does not exist; starting first-time migration`,{encryptedDir:t,plainDir:n,resumedBackupCount:l.length}),l.length>0?u=await wt(e,n):c=await wt(e,n),await L(t),await jt(t),await L(n),await At(t,n),f=!0,d=Nt(n),N.info(`--encrypt-sessions mounted encrypted .aimax`,{plainDir:n,encryptedDir:t}),l.length>0){for(let e of l)await z(e,n,!0);u&&=(await z(u,n,!1),await x.rm(u,{recursive:!0,force:!0}),N.info(`--encrypt-sessions removed residual plaintext backup after migration`,{backupDir:u}),null);for(let e of l)await x.rm(e,{recursive:!0,force:!0}),N.info(`--encrypt-sessions removed resumed plaintext migration backup`,{backupDir:e});l=[]}else c&&=(await z(c,n,!0),await x.rm(c,{recursive:!0,force:!0}),N.info(`--encrypt-sessions removed plaintext migration backup`,{backupDir:c}),null);else if(N.info(`--encrypt-sessions encrypted .aimax directory exists; mounting existing encrypted data`,{encryptedDir:t,plainDir:n,resumedBackupCount:l.length,plainDirEntryCount:await R(n)}),await St(t),l.length>0?u=await wt(e,n):await yt(n)||(c=await wt(e,n)),await vt(n),await At(t,n),f=!0,d=Nt(n),N.info(`--encrypt-sessions mounted encrypted .aimax`,{plainDir:n,encryptedDir:t}),l.length>0){for(let e of l)await z(e,n,!0);u&&=(await z(u,n,!1),await x.rm(u,{recursive:!0,force:!0}),N.info(`--encrypt-sessions removed residual plaintext backup after migration`,{backupDir:u}),null);for(let e of l)await x.rm(e,{recursive:!0,force:!0}),N.info(`--encrypt-sessions removed resumed plaintext migration backup`,{backupDir:e});l=[]}else c&&=(await z(c,n,!0),await x.rm(c,{recursive:!0,force:!0}),N.info(`--encrypt-sessions removed plaintext migration backup`,{backupDir:c}),null);return N.info(`--encrypt-sessions prepared encrypted .aimax mount result`,{mounted:f,plainDir:n,encryptedDir:t,plainDirMountPoint:await F(n),plainDirEntryCount:await R(n),encryptedDirEntryCount:await R(t)}),{mounted:f,plainDir:n,encryptedDir:t,async cleanup(){if(d?.release(),!f){N.info(`--encrypt-sessions cleanup skipped because encrypted .aimax is not mounted`,{plainDir:n,encryptedDir:t});return}f=!1,N.info(`--encrypt-sessions cleanup started`,{plainDir:n,encryptedDir:t});try{await B(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){d?.release(),f&&await B(n).catch(e=>{N.warn(`--encrypt-sessions failed to unmount during mount rollback`,{error:e instanceof Error?e.message:String(e),plainDir:n,encryptedDir:t})}),c&&await I(c)&&await yt(n)&&(await x.rm(n,{recursive:!0,force:!0}).catch(()=>{}),await x.rename(c,n).catch(()=>{}),N.info(`--encrypt-sessions restored plaintext backup after failed migration`,{backupDir:c,plainDir:n})),u&&await I(u)&&await yt(n)&&(await x.rm(n,{recursive:!0,force:!0}).catch(()=>{}),await x.rename(u,n).catch(()=>{}),N.info(`--encrypt-sessions restored residual plaintext backup after failed migration`,{backupDir:u,plainDir:n}));let r=await Tt(l,n).catch(e=>(N.warn(`--encrypt-sessions failed to restore interrupted plaintext backups after failed migration`,{error:e instanceof Error?e.message:String(e),plainDir:n,backupCount:l.length}),[]));return l=l.filter(e=>!r.includes(e)),N.warn(`--encrypt-sessions failed; continuing with plaintext .aimax`,{error:e instanceof Error?e.message:String(e),mountedBeforeFailure:f,plainDir:n,encryptedDir:t,backupDir:c,residualPlainBackupDir:u,resumedBackupCount:l.length}),await L(n),s()}}async function V(e,t,n){if(!t.encryptSessions)return await Et(e),n();N.info(`--encrypt-sessions wrapper starting encrypted .aimax preparation`,{dataDir:e});let r=await Pt(e);N.info(`--encrypt-sessions wrapper prepared encrypted .aimax state`,{dataDir:e,mounted:r.mounted,plainDir:r.plainDir,encryptedDir:r.encryptedDir});try{return N.info(`--encrypt-sessions wrapper entering protected operation`,{dataDir:e,mounted:r.mounted}),await n(r)}finally{N.info(`--encrypt-sessions wrapper starting cleanup`,{dataDir:e,mounted:r.mounted,plainDir:r.plainDir,encryptedDir:r.encryptedDir}),await r.cleanup(),N.info(`--encrypt-sessions wrapper finished cleanup`,{dataDir:e,mounted:r.mounted,plainDir:r.plainDir,encryptedDir:r.encryptedDir})}}async function Ft(e,t){await new Promise((n,r)=>{be(e,t,{encoding:`utf-8`},e=>{if(e){r(e);return}n()})})}async function It(e){try{return await Ft(`sh`,[`-c`,`command -v "${e}" >/dev/null 2>&1`]),!0}catch{return!1}}async function Lt(e,t){if(!await It(e))throw Error(`--encrypt-sessions requires ${e}: ${t}.`)}function Rt(e,t){return`${e} failed: ${t instanceof Error?t.message:String(t)}`}function zt(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{Ve(await V(e.dataDir,e,async()=>i(e.dataDir)),t)}catch(e){O(`Error bootstrapping data directory: ${e.message}`),process.exit(1)}})}function Bt(e){return Ce.sm4_encrypt_ecb(e)}function Vt(e){return Bt(e)}function Ht(e={}){let t=Ut(e.apiFormat??process.env.AIMAX_API_FORMAT),n=e.baseUrl??process.env.AIMAX_BASE_URL,r=process.env.AIMAX_AUTH_TOKEN,i=e.authToken?Vt(e.authToken):r?Vt(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 Ut(e){if(!e||e===`openai-completions`||e===`anthropic-messages`)return e;throw Error(`Unsupported LLM API format: ${e}`)}function Wt(e,t){return t?C.resolve(t):C.join(e,`.aimax`,`plugins.json`)}async function H(e,t){let n=Wt(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 U(e,t,n){let r=Wt(e,n);await x.mkdir(C.dirname(r),{recursive:!0}),await x.writeFile(r,JSON.stringify(t,null,2),`utf-8`)}function W(e){return typeof e==`object`&&!!e}function Gt(e){return W(e)&&e.type===`text`&&typeof e.text==`string`&&(e.textSignature===void 0||typeof e.textSignature==`string`)}function Kt(e){return W(e)&&e.type===`image`&&typeof e.data==`string`&&typeof e.mimeType==`string`}function qt(e){return W(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 Jt(e){return W(e)&&e.type===`toolCall`&&typeof e.id==`string`&&typeof e.name==`string`&&W(e.arguments)&&(e.thoughtSignature===void 0||typeof e.thoughtSignature==`string`)}function Yt(e){return typeof e==`string`||Array.isArray(e)&&e.every(e=>Gt(e)||Kt(e))}function Xt(e){return Array.isArray(e)&&e.every(e=>Gt(e)||qt(e)||Jt(e))}function Zt(e){return W(e)&&typeof e.input==`number`&&typeof e.output==`number`&&typeof e.cacheRead==`number`&&typeof e.cacheWrite==`number`&&typeof e.totalTokens==`number`&&W(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 Qt(e){return!W(e)||typeof e.role!=`string`?!1:e.role===`user`?Yt(e.content):e.role===`assistant`?Xt(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=>Gt(e)||Kt(e))&&typeof e.isError==`boolean`:!1}async function $t(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=>Qt(e)))throw Error(`Message file must contain one Message object or an array of Message objects`);return r}async function en(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 $t(e.fromFile)}:{kind:`text`,message:e.message}}var tn=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()}))}},nn=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=rn(e);N.info(`sending callback event`,{callbackUrl:this.url,...n});let r=new AbortController,i=!1,a=setTimeout(()=>{i=!0,r.abort()},5e3);try{let a=await fetch(this.url,{method:`POST`,headers:{"content-type":`application/json`},body:JSON.stringify(e),signal:r.signal}),o=Date.now()-t;if(!a.ok){N.error(`callback event failed`,{callbackUrl:this.url,httpStatus:a.status,durationMs:o,timedOut:i,...n});return}N.info(`callback event delivered`,{callbackUrl:this.url,httpStatus:a.status,durationMs:o,...n})}catch(e){let r=Date.now()-t;N.error(`callback event failed`,{callbackUrl:this.url,error:e instanceof Error?e.message:String(e),durationMs:r,timedOut:i,...n})}finally{clearTimeout(a)}}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 rn(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 an(e,t){if(t.kind===`none`)return e;let n=new URL(e);return n.searchParams.set(`authToken`,t.token),n.toString()}const G=5e3,on=5e3;function K(){let e=globalThis.WebSocket;if(!e)throw Error(`WebSocket is not available in this runtime`);return e}function sn(e){return e?{kind:`query_token`,token:e}:{kind:`none`}}function cn(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 ln(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 un=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 dn(this.ensureConnected(),G,`WebSocket connection timed out after ${G}ms`);let e=K();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 dn(this.ensureConnected(),G,`WebSocket connection timed out after ${G}ms`);let e=K();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=K();if(e.readyState!==t.CLOSED)try{await dn(new Promise(t=>{cn(e,`close`,()=>t()),e.close()}),on,`WebSocket close timed out after ${on}ms`)}catch(e){N.warn(`websocket sink close timed out`,{url:this.url,error:e instanceof Error?e.message:String(e)})}}async ensureConnected(){if(!this.enabled)return;let e=K();if(this.socket&&this.socket.readyState===e.OPEN)return;if(this.connectPromise){await this.connectPromise;return}let t=new e(an(this.url,sn(this.authToken)));this.connectPromise=new Promise((e,n)=>{cn(t,`open`,()=>{this.socket=t,ln(t,`close`,()=>{this.socket===t&&(this.socket=null)}),e()}),cn(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 dn(e,t,n){return new Promise((r,i)=>{let a=setTimeout(()=>i(Error(n)),t);e.then(e=>{clearTimeout(a),r(e)},e=>{clearTimeout(a),i(e)})})}function fn(e){let t=e.trim();if(!t)throw Error(`Goal objective cannot be empty`);return t}function pn(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 mn(e){let t=pn(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}function hn(e){let t=e?.packageRoot??gn(),n=C.join(t,`models`),r=C.join(n,...`Xenova/bge-small-zh-v1.5`.split(`/`));if(S.existsSync(C.join(r,`config.json`)))return n}function gn(){let e=C.dirname(we(import.meta.url));return C.basename(e)===`src`||C.basename(e)===`dist`?C.resolve(e,`..`):e}const _n=[`start`,`text`,`done`,`error`,`hitl`],vn=[`off`,`gate`,`dry_run`,`write`];function yn(e){if(!e?.trim())return new Set(_n);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(_n)}function bn(e){if(e.disableTopicSegmentation===!0||process.env.AIMAX_DISABLE_TOPIC_SEGMENTATION===`true`)return{enabled:!1};let t=hn();return t?{embeddingModelDir:t}:void 0}function xn(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 Sn(e){return e?.trim()||void 0}function Cn(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 wn(e){return e?y(e):void 0}function Tn(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 En(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(vn.includes(n))return n;throw Error(`Invalid ${t}: ${e}. Must be one of off,gate,dry_run,write.`)}}function On(e){let t=e.autoSkillsLoadEnabled===void 0?En(process.env.AIMAX_AUTO_SKILLS_LOAD_ENABLED,`AIMAX_AUTO_SKILLS_LOAD_ENABLED`):En(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 kn(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 An(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 jn(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 Mn(e){let t=xn(e),n=e.channel??`WEB`,r=Ht({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:Cn(e),channel:n,format:e.output===`json`?`json`:`text`,timeoutMs:e.timeout?Number(e.timeout):void 0,llm:r,skillsLoadPaths:Tn(e.skillsLoadPaths),autoSkills:On(e)}}function Nn(e){let t=[],n=null;return e.callbackUrl&&t.push(new nn(e.callbackUrl)),e.streamUrl&&(n=new un(e.streamUrl,yn(e.streamEvents),e.streamAuthToken),t.push(n)),{sink:new tn(t),websocketSink:n}}async function Pn(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 Fn(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 In(e){let t=xn(e);await V(t,e,async()=>{M(t,{messageId:e.messageId});let i=new P(`resume command`),a=null;try{let t=await Mn(e),o=wn(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=fn(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=mn({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=kn(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=Ln(n,s.request.kind);await Pn({dataDir:t.dataDir,sessionId:e.sessionId,sessionStoreName:o,toolCallId:s.toolContext?.toolCallId,toolName:s.toolContext?.toolName,resolution:n,encryptSessions:e.encryptSessions});let d=Nn(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}),Le({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 H(t.dataDir,m),g;try{g=await de({dataDir:t.dataDir,projectDir:Sn(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:bn(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}}),Le(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=An(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 Fn({dataDir:t.dataDir,sessionId:e.sessionId,sessionStoreName:o,result:d,encryptSessions:e.encryptSessions});let f=Nn(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 jn({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 H(t.dataDir,g),v=await de({dataDir:t.dataDir,projectDir:Sn(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:bn(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}}),Le(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 Ln(e,t){return o(e,t)}function Rn(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 In(e)})}const zn=[`start`,`text`,`done`,`error`],Bn=[`off`,`gate`,`dry_run`,`write`];function Vn(e){if(!e?.trim())return new Set(zn);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(zn)}function Hn(e){if(e.disableTopicSegmentation===!0||process.env.AIMAX_DISABLE_TOPIC_SEGMENTATION===`true`)return{enabled:!1};let t=hn();return t?{embeddingModelDir:t}:void 0}function Un(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 Gn(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 Kn(e){return e?.trim()||void 0}function qn(e){return e??`WEB`}function Jn(e){return e?y(e):void 0}function Yn(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 Xn(e){let t=``;for(let n=0;n<e.length;n+=1){let r=e[n];if(r===`\\`&&n+1<e.length){let r=e[n+1];if(r===`,`||r===`\\`||r===`=`){t+=r,n+=1;continue}}t+=r}return t}function Zn(e){let t=[],n=``;for(let r=0;r<e.length;r+=1){let i=e[r];if(i===`\\`&&r+1<e.length){let t=e[r+1];if(t===`,`||t===`\\`){n+=t,r+=1;continue}}if(i===`,`){t.push(n),n=``;continue}n+=i}return t.push(n),t}function Qn(e){if(!e?.trim())return{};let t=[],n=new Set;for(let r of Zn(e)){let e=r.trim();if(!e)continue;let i=e.indexOf(`=`);if(i<=0)throw Error(`Invalid --env entry: ${e}. Expected KEY=VALUE (use \\= to embed an equals sign in the value).`);let a=e.slice(0,i).trim(),o=e.slice(i+1).trim();if(!a)throw Error(`Invalid --env entry: ${e}. Key must not be empty.`);if(n.has(a))throw Error(`Invalid --env entry: duplicate key ${a}.`);n.add(a),t.push([a,Xn(o)])}return Object.fromEntries(t)}function $n(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 er(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 tr(e){let t=e.autoSkillsLoadEnabled===void 0?$n(process.env.AIMAX_AUTO_SKILLS_LOAD_ENABLED,`AIMAX_AUTO_SKILLS_LOAD_ENABLED`):$n(e.autoSkillsLoadEnabled,`--auto-skills-load-enabled`),n=e.autoSkillsReviewMode===void 0?er(process.env.AIMAX_AUTO_SKILLS_REVIEW_MODE,`AIMAX_AUTO_SKILLS_REVIEW_MODE`):er(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 nr(e,t){return e.length<=t?e:t<=3?e.slice(0,t):`${e.slice(0,t-3)}...`}function rr(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 ir(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?` ${nr(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=>rr(e,a).map(e=>`│ ${e.padEnd(a,` `)} │`)),l].join(`
|
|
9
|
-
`)}function ar(e){return e.kind===`text`?`inline message (${e.message.length} chars)`:`message file (${e.messages.length} messages)`}function q(e,t=`-`){return e==null||e===``?t:String(e)}function or(e){return e?`set`:`unset`}function sr(e){return e?`true`:`false`}function cr(e,t){let n=Jn(e.sessionStore)??`sessions`,r=t.timeoutMs===void 0?`default`:`${t.timeoutMs}`,i=e.callbackUrl?`enabled`:`disabled`,a=e.streamUrl?`enabled`:`disabled`,o=ar(t.input),s=t.input.kind===`text`?`inline`:e.fromFile??`file`,c=Ue(),l=Hn(e)?.enabled===!1?`disabled`:`enabled`,u=e.pluginsConfig??process.env.AIMAX_PLUGINS_CONFIG,d=[...Vn(e.streamEvents)].join(`,`),f=t.autoSkills?.load?.enabled,p=t.autoSkills?.review?.mode,m=e.tokenBudget===`0`?`unlimited`:q(e.tokenBudget),h=e.env?Object.keys(Qn(e.env)):[],g=h.length===0?`-`:`${h.length} key${h.length===1?``:`s`}`;return{banner:ir(void 0,[`AIMax CLI`,`Stateless Agent Runner`]),contextBox:ir(`Run Context`,[`time : ${c}`,`dataDir : ${t.dataDir}`,`projectDir : ${Wn(e.projectDir)??`-`}`,`systemAgents : ${t.systemAgentsDir??`/aimax/agents`}`,`agent : ${Kn(e.agent)??`-`}`,`channel : ${t.channel}`,`user : ${e.user??`-`}`,`message : ${e.message===void 0?`-`:`inline (${e.message.length} chars)`}`,`fromFile : ${q(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 : ${or(e.apiKey)}`,`authToken : ${or(e.authToken)}`,`model : ${t.llm.model}`,`contextWindow: ${q(t.llm.contextWindow)}`,`flashModel : ${q(t.llm.flashModel)}`,`callbackUrl : ${q(e.callbackUrl)}`,`streamUrl : ${q(e.streamUrl)}`,`streamAuth : ${or(e.streamAuthToken)}`,`streamEvents : ${d}`,`output : ${t.format}`,`callback : ${i}`,`websocket : ${a}`,`timeoutMs : ${r}`,`pluginsConfig: ${q(u)}`,`env : ${g}`,`goal : ${e.goal===void 0?`-`:`inline (${e.goal.length} chars)`}`,`goalFile : ${q(e.goalFile)}`,`tokenBudget : ${m}`,`force : ${sr(e.force)}`,`resumeReqId : ${q(e.resumeRequestId)}`,`resumeInput : ${e.resumeInputJson===void 0?`-`:`inline (${e.resumeInputJson.length} chars)`}`,`resumeFile : ${q(e.resumeFromFile)}`,`encryptSess : ${sr(e.encryptSessions)}`,`topicSegment : ${l}`]),logContext:{time:c,channel:t.channel,user:e.user,dataDir:t.dataDir,projectDir:Wn(e.projectDir),systemAgentsDir:t.systemAgentsDir,agent:Kn(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,envKeys:h.length>0?h.join(`,`):void 0,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 lr(e,t){let n=Un(e),r=qn(e.channel),i=Ht({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:Gn(e),channel:r,format:e.output===`json`?`json`:`text`,timeoutMs:e.timeout?Number(e.timeout):void 0,llm:i,input:t,skillsLoadPaths:Yn(e.skillsLoadPaths),autoSkills:tr(e)}}function ur(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 dr(e,t){if(!e.sessionId)return null;let n=ur(t);if(!n)return null;let r=await te(Un(e),e.sessionId,{storeName:Jn(e.sessionStore),encryptSessions:e.encryptSessions});return!r||r.status!==`pending`||!_e(n,r.request)?null:{requestId:r.request.requestId,inputText:n}}function fr(e){let t=[],n=null;return e.callbackUrl&&t.push(new nn(e.callbackUrl)),e.streamUrl&&(n=new un(e.streamUrl,Vn(e.streamEvents),e.streamAuthToken),t.push(n)),{sink:new tn(t),websocketSink:n}}async function J(e,t){N.info(`dispatching external event`,jr(t)),await e.sink.send(t)}function pr(e){let t={sessionId:e.sessionId,messageId:e.messageId,parentSessionId:e.parentSessionId,depth:e.depth,scope:e.scope,phase:e.phase,...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 mr(e,t,n,r,i){return{sink:e,websocketSink:t,channel:n,defaultMessageId:r,user:i}}function hr(e){let t=new AbortController,n=n=>{N.warn(`run abort signal received`,{signal:n,uptimeMs:Math.round(process.uptime()*1e3),alreadyAborted:t.signal.aborted,...e?.()}),t.abort()},r=()=>n(`SIGTERM`),i=()=>n(`SIGINT`);return process.once(`SIGTERM`,r),process.once(`SIGINT`,i),{controller:t,cleanup:()=>{process.off(`SIGTERM`,r),process.off(`SIGINT`,i)}}}function gr(e){return{activeSessionId:e??`pending`,finalResult:null}}function _r(e,t){e.activeSessionId=t.sessionId??e.activeSessionId}function vr(e,t){return e.messageId??t}async function yr(e,t,n){if(!await h(e.dataDir)){if(await br(t,e.format,n.activeSessionId,e.dataDir,`checking`),(await u(e.dataDir)).performedBootstrap){await br(t,e.format,n.activeSessionId,e.dataDir,`initializing`),await br(t,e.format,n.activeSessionId,e.dataDir,`initialized`);return}await br(t,e.format,n.activeSessionId,e.dataDir,`ready`)}}async function br(e,t,n,r,i){let a={type:`bootstrap`,phase:i,dataDir:r};t===`text`&&k(a),await J(e,{sessionId:n,channel:e.channel,messageId:e.defaultMessageId,user:e.user,type:`progress`,event:a})}function xr(e,t,n){return async r=>{if(_r(n,r),he(r)){pr(r);return}if(r.type===`stream_text_delta`){e.format===`text`&&k(r),await t.websocketSink?.sendTextDelta({sessionId:n.activeSessionId,channel:e.channel,messageId:vr(r,t.defaultMessageId),user:t.user,text:r.text});return}e.format===`text`&&k(r);let i=vr(r,t.defaultMessageId);if(r.type===`hitl_requested`){await J(t,{sessionId:n.activeSessionId,channel:e.channel,messageId:i,user:t.user,type:`hitl`,request:r.request}),await J(t,{sessionId:n.activeSessionId,channel:e.channel,messageId:i,user:t.user,type:`progress`,event:r});return}if(r.type===`start`){await J(t,{sessionId:n.activeSessionId,channel:e.channel,messageId:i,user:t.user,type:`start`,message:r.message});return}if(r.type===`session_reset`){await J(t,{sessionId:n.activeSessionId,channel:e.channel,messageId:i,user:t.user,type:`session_reset`,action:r.action,previousSessionId:r.previousSessionId,message:r.message});return}await J(t,{sessionId:n.activeSessionId,channel:e.channel,messageId:i,user:t.user,type:`progress`,event:r})}}function Sr(e,t,n,r,i,a){let o={dataDir:t.dataDir,projectDir:Wn(e.projectDir),systemAgentsDir:t.systemAgentsDir,agentPolicy:Kn(e.agent)?{requestedAgentName:Kn(e.agent)}:void 0,sessionStoreName:Jn(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:Hn(e),env:Qn(e.env),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 Cr(e,t,n,r){if(t.activeSessionId=r.sessionId,t.finalResult=r,r.error){await J(e,{sessionId:r.sessionId,channel:e.channel,messageId:n,user:e.user,type:`error`,message:r.error});return}await J(e,{sessionId:r.sessionId,channel:e.channel,messageId:n,user:e.user,type:`done`,result:{text:r.text,usage:r.usage,durationMs:r.durationMs,error:r.error,paused:r.paused}})}async function wr(e,t,n,r){await J(e,{sessionId:t.finalResult?.sessionId??t.activeSessionId,channel:e.channel,messageId:n,user:e.user,type:`error`,message:`Fatal: ${r.message}`})}function Tr(e,t){let n=cr(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 Er(e,t,n){return Le(t,n),t.error?N.error(`run command failed: ${t.error}`):N.info(`run command succeeded`),e.end(),t.error?1:0}function Dr(e){let t=nt();if(!t)return;let n=`[${Ue()}] [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 Or(e,t){let n=`run command error: ${t.message}`;N.error(n),Dr(n),O(`Fatal: ${t.message}`),e.end(),await rt(),process.exit(1)}async function kr(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 Ar(e){let t=Un(e);await V(t,e,async i=>{M(t,{messageId:e.messageId}),e.encryptSessions&&N.info(`--encrypt-sessions run mount state after logger initialization`,{dataDir:t,mounted:i?.mounted??!1,plainDir:i?.plainDir,encryptedDir:i?.encryptedDir});let a=new P(`run command`),o=await kr(e);if(e.resumeRequestId||o||e.resumeFromFile){if(!e.sessionId||!e.resumeRequestId||!o)throw Error(`--session-id, --resume-request-id, and exactly one of --resume-input-json or --resume-from-file must be provided together`);await In({dataDir:e.dataDir,projectDir:e.projectDir,systemAgentsDir:e.systemAgentsDir,sessionId:e.sessionId,sessionStore:e.sessionStore,requestId:e.resumeRequestId,inputJson:o,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 s;try{s=await en({message:e.message,fromFile:e.fromFile})}catch(e){await Or(a,e);return}let c=await dr(e,s);if(c){await In({dataDir:e.dataDir,projectDir:e.projectDir,systemAgentsDir:e.systemAgentsDir,sessionId:e.sessionId,sessionStore:e.sessionStore,requestId:c.requestId,inputText:c.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 l=e.channel??`WEB`,u=gr(e.sessionId),{controller:d,cleanup:f}=hr(()=>({activeSessionId:u.activeSessionId,finalSessionId:u.finalResult?.sessionId,messageId:e.messageId,channel:l,user:e.user})),p=null;try{let t=await lr(e,s);l=t.channel,Tr(e,t);let i=fr(e);p=i.sink,N.info(`external sink configured`,{callbackUrl:e.callbackUrl,streamUrl:e.streamUrl,streamEvents:e.streamEvents});let o=mr(p,i.websocketSink,t.channel,e.messageId,e.user);await yr(t,o,u);let c,f=null;if(e.goal||e.goalFile){let i;i=e.goalFile?await x.readFile(e.goalFile,`utf-8`):e.goal;let a=fn(i),o=Jn(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});f=mn({sessionId:e.sessionId,before:n,result:i})}else c={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 H(t.dataDir,m),g=xr(t,o,u);f&&await g(f);let _=await de(Sr(e,t,d,g,h,c));await Cr(o,u,e.messageId,_),process.exitCode=Er(a,_,t.format)}catch(t){let n=t;p&&await wr(mr(p,null,l,e.messageId,e.user),u,e.messageId,n),await Or(a,n)}finally{await p?.close(),f()}})}function jr(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 Mr(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`).option(`--output <format>`,`Output format: text (default) or json`,`text`).option(`--plugins-config <path>`,`Plugins config file path`).option(`--env <kvlist>`,`Session-scoped env vars injected into the run. Comma-separated KEY=VALUE pairs. Backslash-escape "," and "=" inside values. Available to plugins via api.runtime.session.env and merged into child process environments spawned by the exec/process tools.`).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 Nr(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 V(r.dataDir,r,async()=>{let e=r.sessionStore?y(r.sessionStore):void 0;if(i===`list`){Re(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`){ze(await _(r.dataDir,r.sessionId,{storeName:e}),a);return}if(i===`export`){Be(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 Fr(){let e=process.env.AIMAX_PLUGINS_BUNDLED_DIR;return e&&e.trim()||void 0}function Ir(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 Lr(e){let t=e.level===`error`?`plugin error`:`plugin warning`;return e.pluginId?`${t} (${e.pluginId}): ${e.message}`:`${t}: ${e.message}`}function Rr(e){if(!e||e===`cli`)return`cli`;if(e===`cron`)return`cron`;throw Error(`Unsupported dream trigger: ${e}. Expected "cli" or "cron".`)}async function zr(e){let t=[],n;try{n=await H(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:Fr()});return t.push(...r.diagnostics.map(Lr)),{pluginSystem:r,warnings:t}}catch(e){return t.push(`failed to initialize plugin system: ${e.message}`),{warnings:t}}}async function Br(e){let t=C.join(e.dataDir,`.aimax`),{pluginSystem:n,warnings:r}=await zr({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 Vr(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 Hr(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 V(e.dataDir,e,async()=>{let n=await Br({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=Vr(n.provider.status(),n,e.deep);D(t===`json`?JSON.stringify(r,null,2):Ir(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 V(e.dataDir,e,async()=>{let t=await Br({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 V(t.dataDir,t,async()=>{let e=await(await Br({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 V(e.dataDir,e,async()=>{let n=Rr(e.trigger),r=await Br({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 Ur(e){return`${e.match.accountId?`${e.match.channel}:${e.match.accountId}`:e.match.channel} -> ${e.agentId}`}function Wr(e){return async t=>{let n=await T(t),r=De(n),i=Oe(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=Me(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(` - ${Ur(e)}`)}}}}function Gr(e,t){return async n=>{w(await T(n),ke(e))&&(console.error(`Agent "${e}" already exists.`),process.exit(1)),await Te(n,{id:e,name:t.name,model:t.model,default:t.default})||(console.error(`Agent "${e}" already exists.`),process.exit(1));let r=Me(n,e);console.log(`Agent "${e}" added successfully.`),console.log(` Agent dir: ${r}`)}}function Kr(e){return async t=>{let n=w(await T(t),ke(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 Ae(t,e)||(console.error(`Failed to delete agent "${e}".`),process.exit(1)),console.log(`Agent "${e}" deleted.`)}}function qr(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 Ee(t,{agentId:r,match:{channel:e,accountId:a||void 0}}),console.log(`Binding added: ${n} -> ${r}`)}}}function Jr(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 je(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 je(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 Yr(e){return async t=>{let n=Oe(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(` ${Ur(e)}`)}}function Xr(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 Ne(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 Zr(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 V(n,e,async()=>{await Wr(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 V(r,n,async()=>{await Gr(e,n)(r)})}),r(n.command(`delete <id>`).description(`Delete an agent`)).action(async(e,n)=>{let r=t();await V(r,n,async()=>{await Kr(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 V(n,e,async()=>{await qr(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 V(n,e,async()=>{await Jr(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 V(n,e,async()=>{await Yr(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 V(n,e,async()=>{await Xr(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 Qr(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 $r(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 ei(e){return Array.from(new Set((e??[]).map(e=>e.trim()).filter(Boolean)))}function ti(e){if(e.length===0){D(`LLM allowlist is empty.`);return}for(let t of e)D(t)}function ni(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 V(n,e,async()=>{Qr(g({config:await H(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 V(r,n,async()=>{let t=g({config:await H(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)),$r(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 V(r,n,async()=>{let t=await H(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 U(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 V(r,n,async()=>{let t=await H(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 U(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 V(n,e,async()=>{let t=g({config:await H(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 V(n,e,async()=>{ti(ei((await H(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 V(r,n,async()=>{let t=await H(r,n.pluginsConfig)??{},i=ei([...t.llmAllowlist??[],...e]);await U(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 V(r,n,async()=>{let t=await H(r,n.pluginsConfig)??{},i=new Set(e.map(e=>e.trim()).filter(Boolean)),a=ei(t.llmAllowlist).filter(e=>!i.has(e));await U(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 V(n,e,async()=>{await U(n,{...await H(n,e.pluginsConfig)??{},llmAllowlist:[]},e.pluginsConfig),D(`LLM allowlist cleared.`)})})}function ri(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 V(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 ii(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:Pe(),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 ai(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 ii({dataDir:n,sessionId:r,sessionStoreName:i,objective:a,tokenBudget:o});D(JSON.stringify({goal:s},null,2))}async function oi(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 si(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 ci(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 li(e){let t=await l(Z(e),Q(e),{storeName:$(e.sessionStore),eventSource:`cli`});D(JSON.stringify({cleared:t},null,2))}function ui(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 ai(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 oi(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 si(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 ci(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 li(e)}catch(e){O(`error: ${e.message}`),process.exit(1)}})}const di=[`progress`,`error`,`hitl`];function fi(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 pi(e){if(!e?.trim())return new Set(di);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(di)}function mi(e){return e?y(e):void 0}function hi(e){let t=[];return e.callbackUrl&&t.push(new nn(e.callbackUrl)),e.streamUrl&&t.push(new un(e.streamUrl,pi(e.streamEvents),e.streamAuthToken)),new tn(t)}async function gi(e){let t=fi(e);await V(t,e,async()=>{M(t,{messageId:e.messageId});let n=new P(`cancel command`),r=e.channel??`WEB`,i=e.output===`json`?`json`:`text`,a=hi(e),o=mi(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 _i(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 gi(e)})}function vi(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 yi(e){return e.query?.trim()||void 0}function bi(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 xi(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 Si(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 Ci(e){let t=null;try{let n=vi(e);M(n,{messageId:e.messageId}),t=new P(`summarize command`);let r=yi(e),i=await Si(e),a=Ht({apiFormat:e.apiFormat,baseUrl:e.baseUrl,apiKey:e.apiKey,model:e.model,contextWindow:2e5}),o=bi(e.timeout),s=xi(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`,messageId:e.messageId,message:wi(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 wi(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 Ti(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`).option(`--message-id <id>`,`Message ID for log correlation`).action(async e=>{await Ci(e)})}const Ei=e(import.meta.url)(`../package.json`);function Di(){return process.env.AIMAX_DATA_DIR||process.cwd()}function Oi(){let e=new t;return e.name(`aimax`).description(`AIMax CLI — runs agent tasks in a containerized environment`).version(Ei.version),Mr(e),Rn(e),ui(e),_i(e),Nr(e),Ti(e),ri(e),zt(e),Hr(e),Zr(e,Di),ni(e,Di),e}export{rt as a,N as i,Di as n,M as r,Oi as t};
|