@gencode/cli 0.8.14 → 0.8.15-hotfix.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/CHANGELOG.md CHANGED
@@ -1,5 +1,19 @@
1
1
  # @gencode/cli
2
2
 
3
+ ## 0.8.15-hotfix.1
4
+
5
+ ### Hotfix Changes
6
+
7
+ - 修复同一会话连续触发 UI 表单时,后一个待提交表单会在前一个表单恢复完成后被错误清理的问题;现在连续 UI 表单可以依次提交并恢复。
8
+
9
+ ## 0.8.15
10
+
11
+ ### Patch Changes
12
+
13
+ - 37b2031: Fix session creation when `aimax run --session-id <id>` is called for a new session whose directory already exists because run logs were initialized first. AIMax now treats `session.json` as the session metadata contract, so sessions with pre-created `logs/<messageId>/` directories still get a proper `session.json` written under `<dataDir>/.aimax/<sessionStore>/<sessionId>/`.
14
+ - Updated dependencies [37b2031]
15
+ - @gencode/agents@0.10.13
16
+
3
17
  ## 0.8.14
4
18
 
5
19
  ### 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-BZGVIX65.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`),u=process.argv.includes(`run`)||process.argv.includes(`resume`);function d(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&&!u&&n(c,{messageId:d(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||u))}),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{};
2
+ import{a as e,i as t,r as n,t as r}from"./program-DxnLZqYC.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`),u=process.argv.includes(`run`)||process.argv.includes(`resume`);function d(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&&!u&&n(c,{messageId:d(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||u))}),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{};
@@ -4,8 +4,8 @@ import{createRequire as e}from"node:module";import{Command as t}from"commander";
4
4
  `),P(`session: ${e.sessionId}`),P(`duration: ${e.durationMs}ms`),P(`tokens: input=${e.usage.input} output=${e.usage.output} total=${e.usage.total}`),e.context&&(P(`context: ${e.context.snapshotPath}`),P(`tool-results: ${e.context.toolResultsDir}`)),e.error&&F(`error: ${e.error}`)}function rt(e,t){if(t===`json`){P(JSON.stringify(e,null,2));return}if(e.length===0){P(`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:—]`;P(`${t.id} ${e} [${t.channel}]${n} ${t.title}`)}}function it(e,t){if(t===`json`){P(JSON.stringify(e,null,2));return}P(`session: ${e.id}`),e.metadata&&(P(`title: ${e.metadata.title}`),P(`channel: ${e.metadata.channel}`),P(`created: ${e.metadata.createdAt}`),P(`updated: ${e.metadata.updatedAt}`)),P(`transcript: ${e.transcriptPath}`),P(`entries: ${e.transcriptEntryCount}`),P(`context: ${e.contextSnapshotPath}`),P(`session-memory: ${e.sessionMemoryPath}`),P(`collapse-log: ${e.collapseLogPath}`),P(`read-states: ${e.readStateCount}`),P(`tool-results: ${e.toolResultRefCount}`),P(`tool-results-dir: ${e.toolResultsDir}`)}function at(e,t){if(t===`json`){P(JSON.stringify(e,null,2));return}P(`session: ${e.id}`),P(`transcript: ${e.paths.transcriptPath}`),P(`context: ${e.paths.contextSnapshotPath}`),P(`session-memory: ${e.paths.sessionMemoryPath}`),P(`collapse-log: ${e.paths.collapseLogPath}`),P(`tool-results-dir: ${e.paths.toolResultsDir}`),P(`transcript-entries: ${e.transcript.length}`),P(`read-states: ${e.context.readStates.length}`),P(`tool-results: ${e.context.toolResults.length}`),P(`collapse-spans: ${e.context.compaction.collapseSpans.length}`)}function ot(e,t){if(t===`json`){P(JSON.stringify(e,null,2));return}P(`Bootstrap completed.`),P(`dataDir: ${e.dataDir}`),P(`created dirs: ${e.createdDirs.length}`),P(`created files: ${e.createdFiles.length}`),P(`skipped dirs: ${e.skippedDirs.length}`),P(`skipped files: ${e.skippedFiles.length}`)}const st=`.aimax`,ct=`${st}.pre-gocryptfs.`,lt=[`app.log`,`errors.log`],ut=[`logs`],dt=[`fusermount3`,`fusermount`,`umount`],ft=[{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 pt(e){return C.join(e,`.aimax.enc`)}function mt(e){return C.join(e,st)}function ht(e){return C.join(e,`${ct}${process.pid}.${Date.now()}`)}function gt(e){return C.join(e,`${st}.plaintext-restore.${process.pid}.${Date.now()}`)}function _t(e){return e.replace(/\\([0-7]{3})/g,(e,t)=>String.fromCharCode(Number.parseInt(t,8)))}async function L(e){try{let t=await bt.read(),n=C.resolve(e);for(let e of t.split(`
5
5
  `)){if(!e.trim())continue;let t=e.split(` `);if(t.length>=5&&C.resolve(_t(t[4]??``))===n)return!0}return!1}catch{return!1}}function vt(e){try{let t=S.readFileSync(`/proc/self/mountinfo`,`utf-8`),n=C.resolve(e);for(let e of t.split(`
6
6
  `)){if(!e.trim())continue;let t=e.split(` `);if(t.length>=5&&C.resolve(_t(t[4]??``))===n)return!0}return!1}catch{return!1}}async function yt(){return await w.readFile(`/proc/self/mountinfo`,`utf-8`)}const bt={read:yt};async function R(e){try{return await w.stat(e),!0}catch(e){if(e.code===`ENOENT`)return!1;throw e}}async function z(e){await w.mkdir(e,{recursive:!0})}async function xt(e){if(await z(e),(await w.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 St(e){return await R(e)?(await w.readdir(e)).length===0:!0}async function B(e){if(await R(e))return(await w.readdir(e)).length}async function Ct(e){if(!await R(e))return!1;let t=await w.readdir(e,{withFileTypes:!0});for(let e of t)if(!(e.isDirectory()&&ut.includes(e.name))&&!(e.isFile()&&lt.some(t=>e.name.startsWith(t))))return!0;return!1}async function wt(e){let t=await w.readdir(e,{withFileTypes:!0});for(let n of t){if(n.isDirectory()&&ut.includes(n.name)){await w.rm(C.join(e,n.name),{recursive:!0,force:!0}).catch(()=>{});continue}n.isFile()&&lt.some(e=>n.name.startsWith(e))&&await w.rm(C.join(e,n.name),{force:!0}).catch(()=>{})}}async function Tt(e){if(!await R(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 Et(e){return(await w.readdir(e,{withFileTypes:!0})).filter(e=>e.isDirectory()&&e.name.startsWith(ct)).map(t=>C.join(e,t.name)).sort()}async function Dt(e,t){if(!await R(t))return null;let n=ht(e);return M.info(`--encrypt-sessions moving plaintext .aimax aside before migration`,{plainDir:t,backupDir:n}),await w.rename(t,n),n}async function V(e,t,n){M.info(`--encrypt-sessions copying plaintext backup into encrypted mount`,{backupDir:e,plainDir:t,force:n}),await w.cp(e,t,{recursive:!0,force:n})}async function Ot(e,t){if(e.length===0)return[];await z(t);let n=[];for(let r of e)await R(r)&&(await V(r,t,!0),await w.rm(r,{recursive:!0,force:!0}),M.info(`--encrypt-sessions restored interrupted plaintext backup after failed migration`,{backupDir:r,plainDir:t}),n.push(r));return n}async function kt(e){let t=pt(e),n=mt(e),r=await R(t);if(!r)return;let i=r&&await R(C.join(t,`gocryptfs.conf`)),a=await R(n),o=a?await L(n):!1,s=await St(n);if(M.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 B(n)}),!i){M.warn(`plaintext .aimax restore skipped because .aimax.enc is not initialized`,{encryptedDir:t,plainDir:n}),await z(n);return}if(o){M.warn(`plaintext .aimax restore skipped because .aimax is already a mount point`,{plainDir:n,encryptedDir:t});return}if(await Ct(n)){M.info(`plaintext .aimax restore skipped because plaintext .aimax already contains data`,{plainDir:n,encryptedDir:t,plainDirEntryCount:await B(n)});return}s||(M.info(`plaintext .aimax clearing ephemeral files before restore`,{plainDir:n,encryptedDir:t,plainDirEntryCount:await B(n)}),await wt(n));try{await Mt()}catch(e){M.warn(`plaintext .aimax restore unavailable; continuing with plaintext .aimax`,{error:e instanceof Error?e.message:String(e),plainDir:n,encryptedDir:t}),await z(n);return}let c=gt(e),l=!1;try{await xt(n),await Nt(t,n),l=!0,await w.rm(c,{recursive:!0,force:!0}),await z(c),await w.cp(n,c,{recursive:!0,force:!0}),M.info(`plaintext .aimax restore copied encrypted history to staging directory`,{plainDir:n,encryptedDir:t,restoreDir:c,restoredEntryCount:await B(c)}),await Ft(n),l=!1,await w.rm(n,{recursive:!0,force:!0}),await w.rename(c,n),M.info(`plaintext .aimax restore completed for disabled --encrypt-sessions`,{plainDir:n,encryptedDir:t})}catch(e){l&&await Ft(n).catch(e=>{M.warn(`plaintext .aimax restore failed to unmount during rollback`,{error:e instanceof Error?e.message:String(e),plainDir:n,encryptedDir:t})}),await w.rm(c,{recursive:!0,force:!0}).catch(()=>{}),await z(n).catch(()=>{}),M.warn(`plaintext .aimax restore failed; continuing with existing plaintext .aimax`,{error:e instanceof Error?e.message:String(e),plainDir:n,encryptedDir:t})}}async function At(e){let t=C.join(ye.tmpdir(),`aimax-gocryptfs-pass.${process.pid}.${Date.now()}`);await w.writeFile(t,`wizard_aimax@2026
7
- `,{mode:384});try{return await e(t)}finally{await w.rm(t,{force:!0})}}async function jt(e){let t=e.includes(`-init`)?`init`:`mount`;M.info(`--encrypt-sessions starting gocryptfs ${t}`);try{await zt(`gocryptfs`,e),M.info(`--encrypt-sessions completed gocryptfs ${t}`)}catch(n){let r=n instanceof Error?n.message:String(n);throw M.warn(`--encrypt-sessions failed gocryptfs ${t}`,{error:r}),Error(`gocryptfs ${e.join(` `)} failed: ${r}`)}}async function Mt(){M.info(`--encrypt-sessions checking encryption dependencies`),await Vt(`gocryptfs`,`required for --encrypt-sessions`),M.info(`--encrypt-sessions dependency available`,{command:`gocryptfs`});for(let e of dt)if(await Bt(e)){M.info(`--encrypt-sessions unmount dependency available`,{command:e});return}throw Error(`--encrypt-sessions requires one of ${dt.join(`, `)} to be installed for secure unmount cleanup.`)}async function Nt(e,t){M.info(`--encrypt-sessions mounting encrypted .aimax`,{encryptedDir:e,plainDir:t}),await At(async n=>{await jt([`-q`,`-passfile`,n,e,t])})}async function Pt(e){M.info(`--encrypt-sessions initializing encrypted .aimax directory`,{encryptedDir:e}),await At(async t=>{await jt([`-q`,`-init`,`-passfile`,t,e])})}async function Ft(e){let t=[];M.info(`--encrypt-sessions unmounting encrypted .aimax`,{plainDir:e});for(let n of ft)try{if(M.info(`--encrypt-sessions attempting encrypted .aimax unmount`,{command:n.label,plainDir:e}),await zt(n.command,[...n.args,e]),!await L(e)){M.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),M.warn(`--encrypt-sessions unmount command returned success but mountpoint remains`,{command:n.label,plainDir:e})}catch(r){let i=Ht(n.label,r);t.push(i),M.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 It(e){for(let t of ft)try{if(xe(t.command,[...t.args,e],{stdio:`ignore`}),!vt(e))return}catch{}}function Lt(e){let t=!1,n=()=>{t||(t=!0,It(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 Rt(e){let t=pt(e),n=mt(e),r=await R(n),i=await R(t),a=i&&await R(C.join(t,`gocryptfs.conf`)),o=r?await L(n):!1;M.info(`--encrypt-sessions preparing encrypted .aimax mount`,{dataDir:e,encryptedDir:t,plainDir:n,plainDirExists:r,encryptedDirExists:i,encryptedDirInitialized:a,plainDirMountPoint:o,plainDirEntryCount:await B(n),encryptedDirEntryCount:await B(t)});let s=()=>({mounted:!1,plainDir:n,encryptedDir:t,async cleanup(){}});try{await Mt()}catch(e){return M.warn(`--encrypt-sessions is unavailable; continuing with plaintext .aimax`,{error:e instanceof Error?e.message:String(e)}),await z(n),s()}if(await L(n))return M.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 Et(e),l.length>0&&M.warn(`--encrypt-sessions found interrupted pre-gocryptfs migration backups`,{count:l.length}),!await R(t))if(M.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 Dt(e,n):c=await Dt(e,n),await z(t),await Pt(t),await z(n),await Nt(t,n),f=!0,d=Lt(n),M.info(`--encrypt-sessions mounted encrypted .aimax`,{plainDir:n,encryptedDir:t}),l.length>0){for(let e of l)await V(e,n,!0);u&&=(await V(u,n,!1),await w.rm(u,{recursive:!0,force:!0}),M.info(`--encrypt-sessions removed residual plaintext backup after migration`,{backupDir:u}),null);for(let e of l)await w.rm(e,{recursive:!0,force:!0}),M.info(`--encrypt-sessions removed resumed plaintext migration backup`,{backupDir:e});l=[]}else c&&=(await V(c,n,!0),await w.rm(c,{recursive:!0,force:!0}),M.info(`--encrypt-sessions removed plaintext migration backup`,{backupDir:c}),null);else if(M.info(`--encrypt-sessions encrypted .aimax directory exists; mounting existing encrypted data`,{encryptedDir:t,plainDir:n,resumedBackupCount:l.length,plainDirEntryCount:await B(n)}),await Tt(t),l.length>0?u=await Dt(e,n):await St(n)||(c=await Dt(e,n)),await xt(n),await Nt(t,n),f=!0,d=Lt(n),M.info(`--encrypt-sessions mounted encrypted .aimax`,{plainDir:n,encryptedDir:t}),l.length>0){for(let e of l)await V(e,n,!0);u&&=(await V(u,n,!1),await w.rm(u,{recursive:!0,force:!0}),M.info(`--encrypt-sessions removed residual plaintext backup after migration`,{backupDir:u}),null);for(let e of l)await w.rm(e,{recursive:!0,force:!0}),M.info(`--encrypt-sessions removed resumed plaintext migration backup`,{backupDir:e});l=[]}else c&&=(await V(c,n,!0),await w.rm(c,{recursive:!0,force:!0}),M.info(`--encrypt-sessions removed plaintext migration backup`,{backupDir:c}),null);return M.info(`--encrypt-sessions prepared encrypted .aimax mount result`,{mounted:f,plainDir:n,encryptedDir:t,plainDirMountPoint:await L(n),plainDirEntryCount:await B(n),encryptedDirEntryCount:await B(t)}),{mounted:f,plainDir:n,encryptedDir:t,async cleanup(){if(d?.release(),!f){M.info(`--encrypt-sessions cleanup skipped because encrypted .aimax is not mounted`,{plainDir:n,encryptedDir:t});return}f=!1,M.info(`--encrypt-sessions cleanup started`,{plainDir:n,encryptedDir:t});try{await Ft(n),M.info(`--encrypt-sessions cleanup completed`,{plainDir:n,encryptedDir:t})}catch(e){M.warn(`--encrypt-sessions failed to unmount encrypted .aimax; continuing shutdown`,{error:e instanceof Error?e.message:String(e)})}}}}catch(e){d?.release(),f&&await Ft(n).catch(e=>{M.warn(`--encrypt-sessions failed to unmount during mount rollback`,{error:e instanceof Error?e.message:String(e),plainDir:n,encryptedDir:t})}),c&&await R(c)&&await St(n)&&(await w.rm(n,{recursive:!0,force:!0}).catch(()=>{}),await w.rename(c,n).catch(()=>{}),M.info(`--encrypt-sessions restored plaintext backup after failed migration`,{backupDir:c,plainDir:n})),u&&await R(u)&&await St(n)&&(await w.rm(n,{recursive:!0,force:!0}).catch(()=>{}),await w.rename(u,n).catch(()=>{}),M.info(`--encrypt-sessions restored residual plaintext backup after failed migration`,{backupDir:u,plainDir:n}));let r=await Ot(l,n).catch(e=>(M.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)),M.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 z(n),s()}}async function H(e,t,n){if(!t.encryptSessions)return await kt(e),n();M.info(`--encrypt-sessions wrapper starting encrypted .aimax preparation`,{dataDir:e});let r=await Rt(e);M.info(`--encrypt-sessions wrapper prepared encrypted .aimax state`,{dataDir:e,mounted:r.mounted,plainDir:r.plainDir,encryptedDir:r.encryptedDir});try{return M.info(`--encrypt-sessions wrapper entering protected operation`,{dataDir:e,mounted:r.mounted}),await n(r)}finally{M.info(`--encrypt-sessions wrapper starting cleanup`,{dataDir:e,mounted:r.mounted,plainDir:r.plainDir,encryptedDir:r.encryptedDir}),await r.cleanup(),M.info(`--encrypt-sessions wrapper finished cleanup`,{dataDir:e,mounted:r.mounted,plainDir:r.plainDir,encryptedDir:r.encryptedDir})}}async function zt(e,t){await new Promise((n,r)=>{be(e,t,{encoding:`utf-8`},e=>{if(e){r(e);return}n()})})}async function Bt(e){try{return await zt(`sh`,[`-c`,`command -v "${e}" >/dev/null 2>&1`]),!0}catch{return!1}}async function Vt(e,t){if(!await Bt(e))throw Error(`--encrypt-sessions requires ${e}: ${t}.`)}function Ht(e,t){return`${e} failed: ${t instanceof Error?t.message:String(t)}`}function Ut(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{ot(await H(e.dataDir,e,async()=>i(e.dataDir)),t)}catch(e){F(`Error bootstrapping data directory: ${e.message}`),process.exit(1)}})}function Wt(e){return Se.sm4_encrypt_ecb(e)}function Gt(e){return Wt(e)}function Kt(e={}){let t=qt(e.apiFormat??process.env.AIMAX_API_FORMAT),n=e.baseUrl??process.env.AIMAX_BASE_URL,r=process.env.AIMAX_AUTH_TOKEN,i=e.authToken?Gt(e.authToken):r?Gt(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 qt(e){if(!e||e===`openai-completions`||e===`anthropic-messages`)return e;throw Error(`Unsupported LLM API format: ${e}`)}function Jt(e,t){return t?C.resolve(t):C.join(e,`.aimax`,`plugins.json`)}async function U(e,t){let n=Jt(e,t);try{let e=await w.readFile(n,`utf-8`);return JSON.parse(e)}catch(e){if(e.code===`ENOENT`)return;throw e}}async function W(e,t,n){let r=Jt(e,n);await w.mkdir(C.dirname(r),{recursive:!0}),await w.writeFile(r,JSON.stringify(t,null,2),`utf-8`)}function G(e){return typeof e==`object`&&!!e}function Yt(e){return G(e)&&e.type===`text`&&typeof e.text==`string`&&(e.textSignature===void 0||typeof e.textSignature==`string`)}function Xt(e){return G(e)&&e.type===`image`&&typeof e.data==`string`&&typeof e.mimeType==`string`}function Zt(e){return G(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 Qt(e){return G(e)&&e.type===`toolCall`&&typeof e.id==`string`&&typeof e.name==`string`&&G(e.arguments)&&(e.thoughtSignature===void 0||typeof e.thoughtSignature==`string`)}function $t(e){return typeof e==`string`||Array.isArray(e)&&e.every(e=>Yt(e)||Xt(e))}function en(e){return Array.isArray(e)&&e.every(e=>Yt(e)||Zt(e)||Qt(e))}function tn(e){return G(e)&&typeof e.input==`number`&&typeof e.output==`number`&&typeof e.cacheRead==`number`&&typeof e.cacheWrite==`number`&&typeof e.totalTokens==`number`&&G(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 nn(e){return!G(e)||typeof e.role!=`string`?!1:e.role===`user`?$t(e.content):e.role===`assistant`?en(e.content)&&typeof e.api==`string`&&typeof e.provider==`string`&&typeof e.model==`string`&&tn(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=>Yt(e)||Xt(e))&&typeof e.isError==`boolean`:!1}async function rn(e){let t;try{t=await w.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=>nn(e)))throw Error(`Message file must contain one Message object or an array of Message objects`);return r}async function an(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 rn(e.fromFile)}:{kind:`text`,message:e.message}}var on=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()}))}},sn=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=cn(e);M.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){M.error(`callback event failed`,{callbackUrl:this.url,httpStatus:a.status,durationMs:o,timedOut:i,...n});return}M.info(`callback event delivered`,{callbackUrl:this.url,httpStatus:a.status,durationMs:o,...n})}catch(e){let r=Date.now()-t;M.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 cn(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 ln(e,t){if(t.kind===`none`)return e;let n=new URL(e);return n.searchParams.set(`authToken`,t.token),n.toString()}const un=5e3,dn=5e3;function fn(){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(),un,`WebSocket connection timed out after ${un}ms`);let e=fn();if(!this.socket||this.socket.readyState!==e.OPEN)return;this.socket.send(JSON.stringify(t))}catch(e){M.warn(`websocket sink disabled after send failure`,{url:this.url,error:e instanceof Error?e.message:String(e)}),this.enabled=!1}}async sendTextDelta(e){if(!this.enabled||!this.events.has(`text`))return;this.textSequence+=1;let t={type:`text`,sessionId:e.sessionId,messageId:e.messageId,channel:e.channel,user:e.user,timestamp:new Date().toISOString(),sequence:this.textSequence,delta:e.text};try{await _n(this.ensureConnected(),un,`WebSocket connection timed out after ${un}ms`);let e=fn();if(!this.socket||this.socket.readyState!==e.OPEN)return;this.socket.send(JSON.stringify(t))}catch(e){M.warn(`websocket sink disabled after text delta send failure`,{url:this.url,error:e instanceof Error?e.message:String(e)}),this.enabled=!1}}async close(){this.enabled=!1;let e=this.socket;if(this.socket=null,this.connectPromise=null,!e)return;let t=fn();if(e.readyState!==t.CLOSED)try{await _n(new Promise(t=>{mn(e,`close`,()=>t()),e.close()}),dn,`WebSocket close timed out after ${dn}ms`)}catch(e){M.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=fn();if(this.socket&&this.socket.readyState===e.OPEN)return;if(this.connectPromise){await this.connectPromise;return}let t=new e(ln(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=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 Sn(){let e=C.dirname(Ce(import.meta.url));return C.basename(e)===`src`||C.basename(e)===`dist`?C.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(!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 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(!C.isAbsolute(e))throw Error(`Invalid --skillsLoadPaths entry: ${e}. Each path must be absolute.`);n.has(e)||(n.add(e),r.push(e))}return r}function Mn(e,t){if(e===void 0)return;let n=e.trim().toLowerCase();if(n){if([`true`,`1`,`yes`,`on`].includes(n))return!0;if([`false`,`0`,`no`,`off`].includes(n))return!1;throw Error(`Invalid ${t}: ${e}. Must be true or false.`)}}function Nn(e,t){if(e===void 0)return;let n=e.trim().toLowerCase();if(n){if(wn.includes(n))return n;throw Error(`Invalid ${t}: ${e}. Must be one of off,gate,dry_run,write.`)}}function Pn(e){let t=e.autoSkillsLoadEnabled===void 0?Mn(process.env.AIMAX_AUTO_SKILLS_LOAD_ENABLED,`AIMAX_AUTO_SKILLS_LOAD_ENABLED`):Mn(e.autoSkillsLoadEnabled,`--auto-skills-load-enabled`),n=e.autoSkillsReviewMode===void 0?Nn(process.env.AIMAX_AUTO_SKILLS_REVIEW_MODE,`AIMAX_AUTO_SKILLS_REVIEW_MODE`):Nn(e.autoSkillsReviewMode,`--auto-skills-review-mode`),r={};return t!==void 0&&(r.load={enabled:t}),n!==void 0&&(r.review={mode:n}),r.load||r.review?r:void 0}function Fn(e,t){if(e.inputText&&t){let n=_e(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=Kt({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 sn(e.callbackUrl)),e.streamUrl&&(n=new gn(e.streamUrl,Tn(e.streamEvents),e.streamAuthToken),t.push(n)),{sink:new on(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||!he(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 H(t,e,async()=>{j(t,{messageId:e.messageId,sessionId:e.sessionId,sessionStoreName:An(e.sessionStore)});let i=new N(`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 w.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)&&(F(`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&&(F(e.message),F(`Existing: ${e.existingObjectivePreview}`),process.exit(2)),e}}M.info(`resume command started`,{sessionId:e.sessionId,requestId:e.requestId,channel:t.channel,dataDir:t.dataDir});let l=await 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,!me(n)){if(n.type===`stream_text_delta`){t.format===`text`&&I(n),await d.websocketSink?.sendTextDelta({sessionId:f,channel:t.channel,messageId:e.messageId,user:e.user,text:n.text});return}t.format===`text`&&I(n),await a?.send({sessionId:f,channel:t.channel,messageId:e.messageId,user:e.user,type:`progress`,event:n})}};c&&await p(c),await p({type:`hitl_resumed`,requestId:e.requestId,resolution:n,sessionId:e.sessionId}),`idempotentReplay`in r&&r.idempotentReplay&&(M.info(`resume command treated as idempotent replay`,{sessionId:e.sessionId,requestId:e.requestId,idempotencyKey:n.idempotencyKey}),nt({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 U(t.dataDir,m),g;try{g=await x({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: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}}),nt(g,t.format),g.error?M.error(`resume command failed: ${g.error}`):M.info(`resume command succeeded`),i.end(),process.exit(g.error?1:0);return}let d=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,!me(n)){if(n.type===`stream_text_delta`){t.format===`text`&&I(n),await f.websocketSink?.sendTextDelta({sessionId:p,channel:t.channel,messageId:e.messageId,user:e.user,text:n.text});return}if(t.format===`text`&&I(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 U(t.dataDir,g),v=await x({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: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}}),nt(v,t.format),v.error?M.error(`resume command failed: ${v.error}`):M.info(`resume command succeeded`),i.end(),process.exit(v.error?1:0)}catch(t){let n=t;a&&(n.message.includes(`expired`)&&await a.send({sessionId:e.sessionId,channel:e.channel??`WEB`,messageId:e.messageId,user:e.user,type:`progress`,event:{type:`hitl_expired`,sessionId:e.sessionId,requestId:e.requestId,reason:n.message}}),n.message.includes(`cancelled`)&&await a.send({sessionId:e.sessionId,channel:e.channel??`WEB`,messageId:e.messageId,user:e.user,type:`progress`,event:{type:`hitl_cancelled`,sessionId:e.sessionId,requestId:e.requestId,reason:n.message}}),await a.send({sessionId:e.sessionId,channel:e.channel??`WEB`,messageId:e.messageId,user:e.user,type:`error`,message:`Resume failed: ${n.message}`})),M.error(`resume command error: ${n.message}`),F(`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(!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 Qn(e){return e?.trim()||void 0}function $n(e){return e??`WEB`}function K(e){return e?y(e):void 0}function er(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 tr(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 nr(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 rr(e){if(!e?.trim())return{};let t=[],n=new Set;for(let r of nr(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,tr(o)])}return Object.fromEntries(t)}function ir(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 ar(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 or(e){let t=e.autoSkillsLoadEnabled===void 0?ir(process.env.AIMAX_AUTO_SKILLS_LOAD_ENABLED,`AIMAX_AUTO_SKILLS_LOAD_ENABLED`):ir(e.autoSkillsLoadEnabled,`--auto-skills-load-enabled`),n=e.autoSkillsReviewMode===void 0?ar(process.env.AIMAX_AUTO_SKILLS_REVIEW_MODE,`AIMAX_AUTO_SKILLS_REVIEW_MODE`):ar(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 sr(e,t){return e.length<=t?e:t<=3?e.slice(0,t):`${e.slice(0,t-3)}...`}function cr(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 lr(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?` ${sr(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=>cr(e,a).map(e=>`│ ${e.padEnd(a,` `)} │`)),l].join(`
7
+ `,{mode:384});try{return await e(t)}finally{await w.rm(t,{force:!0})}}async function jt(e){let t=e.includes(`-init`)?`init`:`mount`;M.info(`--encrypt-sessions starting gocryptfs ${t}`);try{await zt(`gocryptfs`,e),M.info(`--encrypt-sessions completed gocryptfs ${t}`)}catch(n){let r=n instanceof Error?n.message:String(n);throw M.warn(`--encrypt-sessions failed gocryptfs ${t}`,{error:r}),Error(`gocryptfs ${e.join(` `)} failed: ${r}`)}}async function Mt(){M.info(`--encrypt-sessions checking encryption dependencies`),await Vt(`gocryptfs`,`required for --encrypt-sessions`),M.info(`--encrypt-sessions dependency available`,{command:`gocryptfs`});for(let e of dt)if(await Bt(e)){M.info(`--encrypt-sessions unmount dependency available`,{command:e});return}throw Error(`--encrypt-sessions requires one of ${dt.join(`, `)} to be installed for secure unmount cleanup.`)}async function Nt(e,t){M.info(`--encrypt-sessions mounting encrypted .aimax`,{encryptedDir:e,plainDir:t}),await At(async n=>{await jt([`-q`,`-passfile`,n,e,t])})}async function Pt(e){M.info(`--encrypt-sessions initializing encrypted .aimax directory`,{encryptedDir:e}),await At(async t=>{await jt([`-q`,`-init`,`-passfile`,t,e])})}async function Ft(e){let t=[];M.info(`--encrypt-sessions unmounting encrypted .aimax`,{plainDir:e});for(let n of ft)try{if(M.info(`--encrypt-sessions attempting encrypted .aimax unmount`,{command:n.label,plainDir:e}),await zt(n.command,[...n.args,e]),!await L(e)){M.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),M.warn(`--encrypt-sessions unmount command returned success but mountpoint remains`,{command:n.label,plainDir:e})}catch(r){let i=Ht(n.label,r);t.push(i),M.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 It(e){for(let t of ft)try{if(xe(t.command,[...t.args,e],{stdio:`ignore`}),!vt(e))return}catch{}}function Lt(e){let t=!1,n=()=>{t||(t=!0,It(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 Rt(e){let t=pt(e),n=mt(e),r=await R(n),i=await R(t),a=i&&await R(C.join(t,`gocryptfs.conf`)),o=r?await L(n):!1;M.info(`--encrypt-sessions preparing encrypted .aimax mount`,{dataDir:e,encryptedDir:t,plainDir:n,plainDirExists:r,encryptedDirExists:i,encryptedDirInitialized:a,plainDirMountPoint:o,plainDirEntryCount:await B(n),encryptedDirEntryCount:await B(t)});let s=()=>({mounted:!1,plainDir:n,encryptedDir:t,async cleanup(){}});try{await Mt()}catch(e){return M.warn(`--encrypt-sessions is unavailable; continuing with plaintext .aimax`,{error:e instanceof Error?e.message:String(e)}),await z(n),s()}if(await L(n))return M.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 Et(e),l.length>0&&M.warn(`--encrypt-sessions found interrupted pre-gocryptfs migration backups`,{count:l.length}),!await R(t))if(M.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 Dt(e,n):c=await Dt(e,n),await z(t),await Pt(t),await z(n),await Nt(t,n),f=!0,d=Lt(n),M.info(`--encrypt-sessions mounted encrypted .aimax`,{plainDir:n,encryptedDir:t}),l.length>0){for(let e of l)await V(e,n,!0);u&&=(await V(u,n,!1),await w.rm(u,{recursive:!0,force:!0}),M.info(`--encrypt-sessions removed residual plaintext backup after migration`,{backupDir:u}),null);for(let e of l)await w.rm(e,{recursive:!0,force:!0}),M.info(`--encrypt-sessions removed resumed plaintext migration backup`,{backupDir:e});l=[]}else c&&=(await V(c,n,!0),await w.rm(c,{recursive:!0,force:!0}),M.info(`--encrypt-sessions removed plaintext migration backup`,{backupDir:c}),null);else if(M.info(`--encrypt-sessions encrypted .aimax directory exists; mounting existing encrypted data`,{encryptedDir:t,plainDir:n,resumedBackupCount:l.length,plainDirEntryCount:await B(n)}),await Tt(t),l.length>0?u=await Dt(e,n):await St(n)||(c=await Dt(e,n)),await xt(n),await Nt(t,n),f=!0,d=Lt(n),M.info(`--encrypt-sessions mounted encrypted .aimax`,{plainDir:n,encryptedDir:t}),l.length>0){for(let e of l)await V(e,n,!0);u&&=(await V(u,n,!1),await w.rm(u,{recursive:!0,force:!0}),M.info(`--encrypt-sessions removed residual plaintext backup after migration`,{backupDir:u}),null);for(let e of l)await w.rm(e,{recursive:!0,force:!0}),M.info(`--encrypt-sessions removed resumed plaintext migration backup`,{backupDir:e});l=[]}else c&&=(await V(c,n,!0),await w.rm(c,{recursive:!0,force:!0}),M.info(`--encrypt-sessions removed plaintext migration backup`,{backupDir:c}),null);return M.info(`--encrypt-sessions prepared encrypted .aimax mount result`,{mounted:f,plainDir:n,encryptedDir:t,plainDirMountPoint:await L(n),plainDirEntryCount:await B(n),encryptedDirEntryCount:await B(t)}),{mounted:f,plainDir:n,encryptedDir:t,async cleanup(){if(d?.release(),!f){M.info(`--encrypt-sessions cleanup skipped because encrypted .aimax is not mounted`,{plainDir:n,encryptedDir:t});return}f=!1,M.info(`--encrypt-sessions cleanup started`,{plainDir:n,encryptedDir:t});try{await Ft(n),M.info(`--encrypt-sessions cleanup completed`,{plainDir:n,encryptedDir:t})}catch(e){M.warn(`--encrypt-sessions failed to unmount encrypted .aimax; continuing shutdown`,{error:e instanceof Error?e.message:String(e)})}}}}catch(e){d?.release(),f&&await Ft(n).catch(e=>{M.warn(`--encrypt-sessions failed to unmount during mount rollback`,{error:e instanceof Error?e.message:String(e),plainDir:n,encryptedDir:t})}),c&&await R(c)&&await St(n)&&(await w.rm(n,{recursive:!0,force:!0}).catch(()=>{}),await w.rename(c,n).catch(()=>{}),M.info(`--encrypt-sessions restored plaintext backup after failed migration`,{backupDir:c,plainDir:n})),u&&await R(u)&&await St(n)&&(await w.rm(n,{recursive:!0,force:!0}).catch(()=>{}),await w.rename(u,n).catch(()=>{}),M.info(`--encrypt-sessions restored residual plaintext backup after failed migration`,{backupDir:u,plainDir:n}));let r=await Ot(l,n).catch(e=>(M.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)),M.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 z(n),s()}}async function H(e,t,n){if(!t.encryptSessions)return await kt(e),n();M.info(`--encrypt-sessions wrapper starting encrypted .aimax preparation`,{dataDir:e});let r=await Rt(e);M.info(`--encrypt-sessions wrapper prepared encrypted .aimax state`,{dataDir:e,mounted:r.mounted,plainDir:r.plainDir,encryptedDir:r.encryptedDir});try{return M.info(`--encrypt-sessions wrapper entering protected operation`,{dataDir:e,mounted:r.mounted}),await n(r)}finally{M.info(`--encrypt-sessions wrapper starting cleanup`,{dataDir:e,mounted:r.mounted,plainDir:r.plainDir,encryptedDir:r.encryptedDir}),await r.cleanup(),M.info(`--encrypt-sessions wrapper finished cleanup`,{dataDir:e,mounted:r.mounted,plainDir:r.plainDir,encryptedDir:r.encryptedDir})}}async function zt(e,t){await new Promise((n,r)=>{be(e,t,{encoding:`utf-8`},e=>{if(e){r(e);return}n()})})}async function Bt(e){try{return await zt(`sh`,[`-c`,`command -v "${e}" >/dev/null 2>&1`]),!0}catch{return!1}}async function Vt(e,t){if(!await Bt(e))throw Error(`--encrypt-sessions requires ${e}: ${t}.`)}function Ht(e,t){return`${e} failed: ${t instanceof Error?t.message:String(t)}`}function Ut(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{ot(await H(e.dataDir,e,async()=>i(e.dataDir)),t)}catch(e){F(`Error bootstrapping data directory: ${e.message}`),process.exit(1)}})}function Wt(e){return Se.sm4_encrypt_ecb(e)}function Gt(e){return Wt(e)}function Kt(e={}){let t=qt(e.apiFormat??process.env.AIMAX_API_FORMAT),n=e.baseUrl??process.env.AIMAX_BASE_URL,r=process.env.AIMAX_AUTH_TOKEN,i=e.authToken?Gt(e.authToken):r?Gt(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 qt(e){if(!e||e===`openai-completions`||e===`anthropic-messages`)return e;throw Error(`Unsupported LLM API format: ${e}`)}function Jt(e,t){return t?C.resolve(t):C.join(e,`.aimax`,`plugins.json`)}async function U(e,t){let n=Jt(e,t);try{let e=await w.readFile(n,`utf-8`);return JSON.parse(e)}catch(e){if(e.code===`ENOENT`)return;throw e}}async function W(e,t,n){let r=Jt(e,n);await w.mkdir(C.dirname(r),{recursive:!0}),await w.writeFile(r,JSON.stringify(t,null,2),`utf-8`)}function G(e){return typeof e==`object`&&!!e}function Yt(e){return G(e)&&e.type===`text`&&typeof e.text==`string`&&(e.textSignature===void 0||typeof e.textSignature==`string`)}function Xt(e){return G(e)&&e.type===`image`&&typeof e.data==`string`&&typeof e.mimeType==`string`}function Zt(e){return G(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 Qt(e){return G(e)&&e.type===`toolCall`&&typeof e.id==`string`&&typeof e.name==`string`&&G(e.arguments)&&(e.thoughtSignature===void 0||typeof e.thoughtSignature==`string`)}function $t(e){return typeof e==`string`||Array.isArray(e)&&e.every(e=>Yt(e)||Xt(e))}function en(e){return Array.isArray(e)&&e.every(e=>Yt(e)||Zt(e)||Qt(e))}function tn(e){return G(e)&&typeof e.input==`number`&&typeof e.output==`number`&&typeof e.cacheRead==`number`&&typeof e.cacheWrite==`number`&&typeof e.totalTokens==`number`&&G(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 nn(e){return!G(e)||typeof e.role!=`string`?!1:e.role===`user`?$t(e.content):e.role===`assistant`?en(e.content)&&typeof e.api==`string`&&typeof e.provider==`string`&&typeof e.model==`string`&&tn(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=>Yt(e)||Xt(e))&&typeof e.isError==`boolean`:!1}async function rn(e){let t;try{t=await w.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=>nn(e)))throw Error(`Message file must contain one Message object or an array of Message objects`);return r}async function an(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 rn(e.fromFile)}:{kind:`text`,message:e.message}}var on=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()}))}},sn=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=cn(e);M.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){M.error(`callback event failed`,{callbackUrl:this.url,httpStatus:a.status,durationMs:o,timedOut:i,...n});return}M.info(`callback event delivered`,{callbackUrl:this.url,httpStatus:a.status,durationMs:o,...n})}catch(e){let r=Date.now()-t;M.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 cn(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 ln(e,t){if(t.kind===`none`)return e;let n=new URL(e);return n.searchParams.set(`authToken`,t.token),n.toString()}const un=5e3,dn=5e3;function fn(){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(),un,`WebSocket connection timed out after ${un}ms`);let e=fn();if(!this.socket||this.socket.readyState!==e.OPEN)return;this.socket.send(JSON.stringify(t))}catch(e){M.warn(`websocket sink disabled after send failure`,{url:this.url,error:e instanceof Error?e.message:String(e)}),this.enabled=!1}}async sendTextDelta(e){if(!this.enabled||!this.events.has(`text`))return;this.textSequence+=1;let t={type:`text`,sessionId:e.sessionId,messageId:e.messageId,channel:e.channel,user:e.user,timestamp:new Date().toISOString(),sequence:this.textSequence,delta:e.text};try{await _n(this.ensureConnected(),un,`WebSocket connection timed out after ${un}ms`);let e=fn();if(!this.socket||this.socket.readyState!==e.OPEN)return;this.socket.send(JSON.stringify(t))}catch(e){M.warn(`websocket sink disabled after text delta send failure`,{url:this.url,error:e instanceof Error?e.message:String(e)}),this.enabled=!1}}async close(){this.enabled=!1;let e=this.socket;if(this.socket=null,this.connectPromise=null,!e)return;let t=fn();if(e.readyState!==t.CLOSED)try{await _n(new Promise(t=>{mn(e,`close`,()=>t()),e.close()}),dn,`WebSocket close timed out after ${dn}ms`)}catch(e){M.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=fn();if(this.socket&&this.socket.readyState===e.OPEN)return;if(this.connectPromise){await this.connectPromise;return}let t=new e(ln(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=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 Sn(){let e=C.dirname(Ce(import.meta.url));return C.basename(e)===`src`||C.basename(e)===`dist`?C.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(!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 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(!C.isAbsolute(e))throw Error(`Invalid --skillsLoadPaths entry: ${e}. Each path must be absolute.`);n.has(e)||(n.add(e),r.push(e))}return r}function Mn(e,t){if(e===void 0)return;let n=e.trim().toLowerCase();if(n){if([`true`,`1`,`yes`,`on`].includes(n))return!0;if([`false`,`0`,`no`,`off`].includes(n))return!1;throw Error(`Invalid ${t}: ${e}. Must be true or false.`)}}function Nn(e,t){if(e===void 0)return;let n=e.trim().toLowerCase();if(n){if(wn.includes(n))return n;throw Error(`Invalid ${t}: ${e}. Must be one of off,gate,dry_run,write.`)}}function Pn(e){let t=e.autoSkillsLoadEnabled===void 0?Mn(process.env.AIMAX_AUTO_SKILLS_LOAD_ENABLED,`AIMAX_AUTO_SKILLS_LOAD_ENABLED`):Mn(e.autoSkillsLoadEnabled,`--auto-skills-load-enabled`),n=e.autoSkillsReviewMode===void 0?Nn(process.env.AIMAX_AUTO_SKILLS_REVIEW_MODE,`AIMAX_AUTO_SKILLS_REVIEW_MODE`):Nn(e.autoSkillsReviewMode,`--auto-skills-review-mode`),r={};return t!==void 0&&(r.load={enabled:t}),n!==void 0&&(r.review={mode:n}),r.load||r.review?r:void 0}function Fn(e,t){if(e.inputText&&t){let n=_e(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=Kt({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 sn(e.callbackUrl)),e.streamUrl&&(n=new gn(e.streamUrl,Tn(e.streamEvents),e.streamAuthToken),t.push(n)),{sink:new on(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||!he(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 H(t,e,async()=>{j(t,{messageId:e.messageId,sessionId:e.sessionId,sessionStoreName:An(e.sessionStore)});let i=new N(`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 w.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)&&(F(`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&&(F(e.message),F(`Existing: ${e.existingObjectivePreview}`),process.exit(2)),e}}M.info(`resume command started`,{sessionId:e.sessionId,requestId:e.requestId,channel:t.channel,dataDir:t.dataDir});let l=await 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,!me(n)){if(n.type===`stream_text_delta`){t.format===`text`&&I(n),await d.websocketSink?.sendTextDelta({sessionId:f,channel:t.channel,messageId:e.messageId,user:e.user,text:n.text});return}t.format===`text`&&I(n),await a?.send({sessionId:f,channel:t.channel,messageId:e.messageId,user:e.user,type:`progress`,event:n})}};c&&await p(c),await p({type:`hitl_resumed`,requestId:e.requestId,resolution:n,sessionId:e.sessionId}),`idempotentReplay`in r&&r.idempotentReplay&&(M.info(`resume command treated as idempotent replay`,{sessionId:e.sessionId,requestId:e.requestId,idempotencyKey:n.idempotencyKey}),nt({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 U(t.dataDir,m),g;try{g=await x({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: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}}),nt(g,t.format),g.error?M.error(`resume command failed: ${g.error}`):M.info(`resume command succeeded`),i.end(),process.exit(g.error?1:0);return}let d=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}),await s(t.dataDir,e.sessionId,{storeName:o,encryptSessions:e.encryptSessions});let f=zn(e);a=f.sink;let p=e.sessionId,m=async n=>{if(p=n.sessionId??p,!me(n)){if(n.type===`stream_text_delta`){t.format===`text`&&I(n),await f.websocketSink?.sendTextDelta({sessionId:p,channel:t.channel,messageId:e.messageId,user:e.user,text:n.text});return}if(t.format===`text`&&I(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 U(t.dataDir,g),v=await x({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:C.join(t.dataDir,`workspace`),bundledDir:process.env.AIMAX_PLUGINS_BUNDLED_DIR,llmAllowlist:_.llmAllowlist}:void 0,onProgress:m});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}}),nt(v,t.format),v.error?M.error(`resume command failed: ${v.error}`):M.info(`resume command succeeded`),i.end(),process.exit(v.error?1:0)}catch(t){let n=t;a&&(n.message.includes(`expired`)&&await a.send({sessionId:e.sessionId,channel:e.channel??`WEB`,messageId:e.messageId,user:e.user,type:`progress`,event:{type:`hitl_expired`,sessionId:e.sessionId,requestId:e.requestId,reason:n.message}}),n.message.includes(`cancelled`)&&await a.send({sessionId:e.sessionId,channel:e.channel??`WEB`,messageId:e.messageId,user:e.user,type:`progress`,event:{type:`hitl_cancelled`,sessionId:e.sessionId,requestId:e.requestId,reason:n.message}}),await a.send({sessionId:e.sessionId,channel:e.channel??`WEB`,messageId:e.messageId,user:e.user,type:`error`,message:`Resume failed: ${n.message}`})),M.error(`resume command error: ${n.message}`),F(`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(!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 Qn(e){return e?.trim()||void 0}function $n(e){return e??`WEB`}function K(e){return e?y(e):void 0}function er(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 tr(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 nr(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 rr(e){if(!e?.trim())return{};let t=[],n=new Set;for(let r of nr(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,tr(o)])}return Object.fromEntries(t)}function ir(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 ar(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 or(e){let t=e.autoSkillsLoadEnabled===void 0?ir(process.env.AIMAX_AUTO_SKILLS_LOAD_ENABLED,`AIMAX_AUTO_SKILLS_LOAD_ENABLED`):ir(e.autoSkillsLoadEnabled,`--auto-skills-load-enabled`),n=e.autoSkillsReviewMode===void 0?ar(process.env.AIMAX_AUTO_SKILLS_REVIEW_MODE,`AIMAX_AUTO_SKILLS_REVIEW_MODE`):ar(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 sr(e,t){return e.length<=t?e:t<=3?e.slice(0,t):`${e.slice(0,t-3)}...`}function cr(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 lr(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?` ${sr(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=>cr(e,a).map(e=>`│ ${e.padEnd(a,` `)} │`)),l].join(`
9
9
  `)}function ur(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 dr(e){return e?`set`:`unset`}function fr(e){return e?`true`:`false`}function pr(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=ur(t.input),s=t.input.kind===`text`?`inline`:e.fromFile??`file`,c=Ie(),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(rr(e.env)):[],g=h.length===0?`-`:`${h.length} key${h.length===1?``:`s`}`;return{banner:lr(void 0,[`AIMax CLI`,`Stateless Agent Runner`]),contextBox:lr(`Run Context`,[`time : ${c}`,`dataDir : ${t.dataDir}`,`projectDir : ${Xn(e.projectDir)??`-`}`,`systemAgents : ${t.systemAgentsDir??`/aimax/agents`}`,`agent : ${Qn(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 : ${dr(e.apiKey)}`,`authToken : ${dr(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 : ${dr(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 : ${fr(e.force)}`,`resumeReqId : ${q(e.resumeRequestId)}`,`resumeInput : ${e.resumeInputJson===void 0?`-`:`inline (${e.resumeInputJson.length} chars)`}`,`resumeFile : ${q(e.resumeFromFile)}`,`encryptSess : ${fr(e.encryptSessions)}`,`topicSegment : ${l}`]),logContext:{time:c,channel:t.channel,user:e.user,dataDir:t.dataDir,projectDir:Xn(e.projectDir),systemAgentsDir:t.systemAgentsDir,agent:Qn(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 mr(e,t){let n=Yn(e),r=$n(e.channel),i=Kt({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:er(e.skillsLoadPaths),autoSkills:or(e)}}function hr(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
10
  `)}async function gr(e,t){if(!e.sessionId)return null;let n=hr(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`||!ge(n,r.request)?null:{requestId:r.request.requestId,inputText:n}}function _r(e){let t=[],n=null;return e.callbackUrl&&t.push(new sn(e.callbackUrl)),e.streamUrl&&(n=new gn(e.streamUrl,qn(e.streamEvents),e.streamAuthToken),t.push(n)),{sink:new on(t),websocketSink:n}}async function J(e,t){M.info(`dispatching external event`,Lr(t)),await e.sink.send(t)}function vr(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`){M.error(e.message,t);return}if(e.level===`warn`){M.warn(e.message,t);return}M.info(e.message,t)}function yr(e,t,n,r,i){return{sink:e,websocketSink:t,channel:n,defaultMessageId:r,user:i}}function br(e){let t=new AbortController,n=n=>{M.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 xr(e){return{activeSessionId:e??`pending`,finalResult:null,loggerSessionId:void 0}}function Sr(e,t,n,r){!r||n.loggerSessionId===r||(j(e,{messageId:t.messageId,sessionId:r,sessionStoreName:K(t.sessionStore)}),n.loggerSessionId=r)}function Cr(e,t){e.activeSessionId=t.sessionId??e.activeSessionId}function wr(e,t){return e.messageId??t}async function Tr(e,t,n){if(!await h(e.dataDir)){if(await Er(t,e.format,n.activeSessionId,e.dataDir,`checking`),(await u(e.dataDir)).performedBootstrap){await Er(t,e.format,n.activeSessionId,e.dataDir,`initializing`),await Er(t,e.format,n.activeSessionId,e.dataDir,`initialized`);return}await Er(t,e.format,n.activeSessionId,e.dataDir,`ready`)}}async function Er(e,t,n,r,i){let a={type:`bootstrap`,phase:i,dataDir:r};t===`text`&&I(a),await J(e,{sessionId:n,channel:e.channel,messageId:e.defaultMessageId,user:e.user,type:`progress`,event:a})}function Dr(e,t,n,r){return async i=>{if(Cr(n,i),Sr(e.dataDir,r,n,i.sessionId),me(i)){vr(i);return}if(i.type===`stream_text_delta`){e.format===`text`&&I(i),await t.websocketSink?.sendTextDelta({sessionId:n.activeSessionId,channel:e.channel,messageId:wr(i,t.defaultMessageId),user:t.user,text:i.text});return}e.format===`text`&&I(i);let a=wr(i,t.defaultMessageId);if(i.type===`hitl_requested`){await J(t,{sessionId:n.activeSessionId,channel:e.channel,messageId:a,user:t.user,type:`hitl`,request:i.request}),await J(t,{sessionId:n.activeSessionId,channel:e.channel,messageId:a,user:t.user,type:`progress`,event:i});return}if(i.type===`start`){await J(t,{sessionId:n.activeSessionId,channel:e.channel,messageId:a,user:t.user,type:`start`,message:i.message});return}if(i.type===`session_reset`){await J(t,{sessionId:n.activeSessionId,channel:e.channel,messageId:a,user:t.user,type:`session_reset`,action:i.action,previousSessionId:i.previousSessionId,message:i.message});return}await J(t,{sessionId:n.activeSessionId,channel:e.channel,messageId:a,user:t.user,type:`progress`,event:i})}}function Or(e,t,n,r,i,a){let o={dataDir:t.dataDir,projectDir:Xn(e.projectDir),systemAgentsDir:t.systemAgentsDir,agentPolicy:Qn(e.agent)?{requestedAgentName:Qn(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:rr(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 kr(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 Ar(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 jr(e,t){let n=pr(e,t);M.info([`run command started`,n.banner,n.contextBox].join(`
11
11
  `),n.logContext),t.format===`text`&&(P(n.banner),P(``),P(n.contextBox),P(``))}function Mr(e,t,n){return nt(t,n),t.error?M.error(`run command failed: ${t.error}`):M.info(`run command succeeded`),e.end(),t.error?1:0}function Nr(e){let t=Je();if(!t)return;let n=`[${Ie()}] [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 Pr(e,t){let n=`run command error: ${t.message}`;M.error(n),Nr(n),F(`Fatal: ${t.message}`),e.end(),await Ye(),process.exit(1)}async function Fr(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 w.readFile(e.resumeFromFile,`utf-8`)}catch(e){throw Error(`Failed to read resume input file: ${e.message}`)}}async function Ir(e){let t=Yn(e);await H(t,e,async i=>{let a=xr(e.sessionId);Sr(t,e,a,e.sessionId),e.encryptSessions&&M.info(`--encrypt-sessions run mount state after logger initialization`,{dataDir:t,mounted:i?.mounted??!1,plainDir:i?.plainDir,encryptedDir:i?.encryptedDir});let o=new N(`run command`),s=await Fr(e);if(e.resumeRequestId||s||e.resumeFromFile){if(!e.sessionId||!e.resumeRequestId||!s)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:s,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 c;try{c=await an({message:e.message,fromFile:e.fromFile})}catch(e){await Pr(o,e);return}let l=await gr(e,c);if(l){await Hn({dataDir:e.dataDir,projectDir:e.projectDir,systemAgentsDir:e.systemAgentsDir,sessionId:e.sessionId,sessionStore:e.sessionStore,requestId:l.requestId,inputText:l.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 u=e.channel??`WEB`,{controller:d,cleanup:f}=br(()=>({activeSessionId:a.activeSessionId,finalSessionId:a.finalResult?.sessionId,messageId:e.messageId,channel:u,user:e.user})),p=null;try{let t=await mr(e,c);u=t.channel,jr(e,t);let i=_r(e);p=i.sink,M.info(`external sink configured`,{callbackUrl:e.callbackUrl,streamUrl:e.streamUrl,streamEvents:e.streamEvents});let s=yr(p,i.websocketSink,t.channel,e.messageId,e.user);await Tr(t,s,a);let l,f=null;if(e.goal||e.goalFile){let i;i=e.goalFile?await w.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)&&(F(`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 l={objective:a,tokenBudget:s??null}}catch(e){throw e instanceof n&&(F(e.message),F(`Existing: ${e.existingObjectivePreview}`),process.exit(2)),e}}let m=e.pluginsConfig??process.env.AIMAX_PLUGINS_CONFIG,h=await U(t.dataDir,m),g=Dr(t,s,a,e);f&&await g(f);let _=await x(Or(e,t,d,g,h,l));Sr(t.dataDir,e,a,_.sessionId),await kr(s,a,e.messageId,_),process.exitCode=Mr(o,_,t.format)}catch(t){let n=t;p&&await Ar(yr(p,null,u,e.messageId,e.user),a,e.messageId,n),await Pr(o,n)}finally{await p?.close(),f()}})}function Lr(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 Rr(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 Ir(e)})}function zr(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||(F(`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`&&(F(`Invalid channel: ${r.channel}. Must be 'H5', 'WEB', 'KLPA', 'TASK', 'CRON', or 'EIP_ASSISTANT'`),process.exit(1));try{await H(r.dataDir,r,async()=>{let e=r.sessionStore?y(r.sessionStore):void 0;if(i===`list`){rt(await ee(r.dataDir,r.channel,{storeName:e}),a);return}if(r.sessionId||(F(`error: required option '-s, --session-id <id>' not specified`),process.exit(1)),i===`inspect`){it(await _(r.dataDir,r.sessionId,{storeName:e}),a);return}if(i===`export`){at(await d(r.dataDir,r.sessionId,{storeName:e}),a);return}F(`Invalid sessions action: ${i}. Must be 'list', 'inspect', or 'export'`),process.exit(1)})}catch(e){F(`${i===`inspect`?`Error inspecting session`:i===`export`?`Error exporting session`:`Error listing sessions`}: ${e.message}`),process.exit(1)}})}function Br(e){return C.join(e,`workspace`)}function Vr(){let e=process.env.AIMAX_PLUGINS_BUNDLED_DIR;return e&&e.trim()||void 0}function Hr(e,t){let n=[];n.push(`backend: ${e.backend}`),n.push(`provider: ${e.provider}${e.model?` (${e.model})`:``}`);let r=typeof e.custom?.providerSource==`string`?e.custom.providerSource:void 0,i=typeof e.custom?.providerId==`string`?e.custom.providerId:void 0,a=typeof e.custom?.pluginId==`string`?e.custom.pluginId:void 0;r&&n.push(`provider_source: ${r}`),i&&n.push(`provider_id: ${i}`),a&&n.push(`plugin_id: ${a}`),typeof e.files==`number`&&n.push(`files: ${e.files}`),typeof e.chunks==`number`&&n.push(`chunks: ${e.chunks}`),typeof e.dirty==`boolean`&&n.push(`dirty: ${e.dirty}`),e.dbPath&&n.push(`db: ${e.dbPath}`),e.sources?.length&&n.push(`sources: ${e.sources.join(`, `)}`),t&&(e.fts&&(n.push(`fts: enabled=${e.fts.enabled} available=${e.fts.available}`),e.fts.error&&n.push(`fts_error: ${e.fts.error}`)),e.vector&&(n.push(`vector: enabled=${e.vector.enabled} available=${e.vector.available??`unknown`}`),e.vector.dims&&n.push(`vector_dims: ${e.vector.dims}`),e.vector.loadError&&n.push(`vector_error: ${e.vector.loadError}`)),e.cache&&n.push(`cache: enabled=${e.cache.enabled} entries=${e.cache.entries??0}`));let o=Array.isArray(e.custom?.cliWarnings)?e.custom.cliWarnings.filter(e=>typeof e==`string`&&e.length>0):[];for(let e of o)n.push(`warning: ${e}`);return n.join(`
package/dist/program.js CHANGED
@@ -1 +1 @@
1
- import{n as e,t}from"./program-BZGVIX65.js";export{t as createProgram,e as getDataDir};
1
+ import{n as e,t}from"./program-DxnLZqYC.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.14",
3
+ "version": "0.8.15-hotfix.1",
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.12",
26
+ "@gencode/agents": "0.10.13",
27
27
  "@gencode/shared": "0.2.1"
28
28
  },
29
29
  "devDependencies": {