@gencode/cli 0.15.2 → 0.16.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +54 -0
- package/dist/bin.js +1 -1
- package/dist/index.d.ts +1 -0
- package/dist/index.js +1 -1
- package/dist/program-Cm76RPAA.js +40 -0
- package/dist/program.js +1 -1
- package/package.json +3 -3
- package/dist/program-Bd8KnLF6.js +0 -40
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,59 @@
|
|
|
1
1
|
# @gencode/cli
|
|
2
2
|
|
|
3
|
+
## 0.16.0
|
|
4
|
+
|
|
5
|
+
### Minor Changes
|
|
6
|
+
|
|
7
|
+
- 37f0256: Add `--workdir-allowlist` CLI option to allow specifying additional directories that exec-style tools can access as working directories. This enables users to grant agents access to directories outside the default workspace root when needed.
|
|
8
|
+
|
|
9
|
+
Usage: `aimax run --workdir-allowlist "/path/to/dir1,/path/to/dir2" --message "your task"`
|
|
10
|
+
|
|
11
|
+
The allowlist is automatically propagated to child agents spawned via subagent tools and applies to all exec-style tools (bash, skill actions, etc.).
|
|
12
|
+
|
|
13
|
+
- 0279e82: Add Phase 3 Knowledge Controller integration as an optional core memory fallback layer. CLI parses `AIMAX_MEMORY_KC_*` env vars into structured `memory.core.knowledgeController` config; agents dynamically import KC only when enabled with `searchMode=fallback` and local recall is empty or weak. KC failures emit diagnostics without blocking agent runtime creation.
|
|
14
|
+
- 6717f94: Add `llm.headers` option to allow passing custom HTTP headers into every LLM request. Default AIMax headers (`Client-Code`, `X-Session-Id`, etc.) are preserved; entries in `llm.headers` are merged on top and can override defaults.
|
|
15
|
+
|
|
16
|
+
Usage:
|
|
17
|
+
|
|
18
|
+
```json
|
|
19
|
+
{
|
|
20
|
+
"llm": {
|
|
21
|
+
"baseUrl": "https://api.example.com/v1",
|
|
22
|
+
"apiKey": "...",
|
|
23
|
+
"model": "...",
|
|
24
|
+
"headers": {
|
|
25
|
+
"Client-Code": "MyApp",
|
|
26
|
+
"X-Custom": "value"
|
|
27
|
+
}
|
|
28
|
+
}
|
|
29
|
+
}
|
|
30
|
+
```
|
|
31
|
+
|
|
32
|
+
- 9ff9574: Add `api.yaml` to PluginApi, giving plugins direct access to the `yaml` module for parsing, stringifying, and manipulating YAML documents.
|
|
33
|
+
|
|
34
|
+
Plugins can now use `api.yaml.parse()`, `api.yaml.stringify()`, `api.yaml.Document`, and all other exports from the `yaml` npm package without adding their own dependency.
|
|
35
|
+
|
|
36
|
+
### Patch Changes
|
|
37
|
+
|
|
38
|
+
- 0279e82: Default local memory is now built into the core: daily entries go to `.aimax/memory/YYYY-MM-DD.md`, structured `MEMORY.md` updates merge by section, and no plugin is required for the default provider path. Optional core capabilities—recall, capture, compaction recall, and Knowledge Controller—are configured via `memory.core` and remain off unless explicitly enabled (`memory.core.*.enabled`). CLI parses `AIMAX_MEMORY_KC_*` into structured `memory.core.knowledgeController` for agents. The `aimax-memory-plugin` continues to provide Mem0 Cloud, Mem0 OSS, and third-party memory provider overrides when selected through `plugins.slots.memory` in `plugins.json` or a file passed with `--plugins-config`, with plugin discovery configured through `plugins.load.paths`.
|
|
39
|
+
- 0279e82: The built-in memory provider now handles recent memory writes without requiring a plugin: daily entries are appended to `.aimax/memory/YYYY-MM-DD.md`, session entries use `.aimax/memory/session-<sessionId>.md`, and structured `MEMORY.md` updates replace matching sections while preserving unrelated sections. This keeps the default CLI memory path aligned with the local memory layout users already configure under `.aimax`.
|
|
40
|
+
- 0279e82: Require the public `goal` completion tool to submit a per-task acceptance report. A complete goal now needs `completedTasks` entries covering every required task and required acceptance criterion with evidence summaries and sources; AIMax records those entries as manual evidence before marking the workflow complete.
|
|
41
|
+
|
|
42
|
+
Goal continuation context now includes the required task and acceptance-criterion ids needed to build that completion report. Calls that omit required summaries, tasks, criteria, or evidence sources are rejected with structured errors such as `missing_summary`, `missing_completed_tasks`, `missing_required_completed_task`, `missing_required_acceptance_evidence`, `blocked_tasks_remain`, `unknown_completed_task`, `unknown_acceptance_criterion`, `missing_evidence_summary`, `missing_evidence_source`, `workflow_not_initialized`, or `workflow_corrupt`.
|
|
43
|
+
|
|
44
|
+
- 0279e82: `aimax run` now releases built-in memory index watchers and timers at the end of each agent run. This keeps the default core memory provider path from holding the Node.js process open after the final session output has been written, while preserving the existing `.aimax/MEMORY.md` and `.aimax/memory/YYYY-MM-DD.md` storage layout.
|
|
45
|
+
- Updated dependencies [37f0256]
|
|
46
|
+
- Updated dependencies [0279e82]
|
|
47
|
+
- Updated dependencies [0279e82]
|
|
48
|
+
- Updated dependencies [0279e82]
|
|
49
|
+
- Updated dependencies [6717f94]
|
|
50
|
+
- Updated dependencies [0279e82]
|
|
51
|
+
- Updated dependencies [0279e82]
|
|
52
|
+
- Updated dependencies [0279e82]
|
|
53
|
+
- Updated dependencies [9ff9574]
|
|
54
|
+
- @gencode/agents@0.18.0
|
|
55
|
+
- @gencode/shared@0.6.0
|
|
56
|
+
|
|
3
57
|
## 0.15.2
|
|
4
58
|
|
|
5
59
|
### Patch Changes
|
package/dist/bin.js
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
-
import"./pkg-path-D6anqptM.js";import{a as e,i as t,o as n,t as r}from"./program-
|
|
2
|
+
import"./pkg-path-D6anqptM.js";import{a as e,i as t,o as n,t as r}from"./program-Cm76RPAA.js";function i(e){return e instanceof Error?e.stack??`${e.name}: ${e.message}`:String(e)}function a(e){let t=e.shutdownTimeoutMs??2e3,n=!1,r=(r,a)=>{if(e.logError(`Fatal ${r}: ${i(a)}`),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 o=Date.now(),s=process.env.AIMAX_DATA_DIR,c=process.argv.includes(`run`)&&process.argv.includes(`--encrypt-sessions`),l=process.argv.includes(`run`)||process.argv.includes(`resume`);function u(e){for(let t=0;t<e.length;t++){let n=e[t];if(n===`--message-id`||n===`--messageId`)return e[t+1];if(n?.startsWith(`--message-id=`))return n.slice(13);if(n?.startsWith(`--messageId=`))return n.slice(12)}}s&&!c&&!l&&t(s,{messageId:u(process.argv)}),a({proc:process,logError:t=>e.error(t),shutdown:n,exit:e=>process.exit(e)}),e.info(`AIMax CLI starting (pid=${process.pid})`,{dataDir:s,encryptedRun:c,loggerDeferred:!!(s&&(c||l))}),r().parseAsync(process.argv).catch(t=>{e.error(`Unexpected error: ${t.message}`),process.exit(1)}).finally(()=>{let t=Date.now()-o;return e.info(`AIMax CLI exited (total uptime: ${t}ms)`),n()});export{};
|
package/dist/index.d.ts
CHANGED
package/dist/index.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
import"./pkg-path-D6anqptM.js";import{n as e,r as t,t as n}from"./program-
|
|
1
|
+
import"./pkg-path-D6anqptM.js";import{n as e,r as t,t as n}from"./program-Cm76RPAA.js";export{n as createProgram,t as executeRun,e as getDataDir};
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
import{createRequire as e}from"node:module";import{Command as t}from"commander";import{GoalConflictError as n,applyCliGoalBeforeRun as r,bootstrapMountLayout as i,buildAimaxGoalCliHelpExtra as a,buildResumeNarration as o,clearPendingUiTool as s,deleteGoal as c,ensureBootstrapMountLayout as l,exportSession as u,formatApprovalResolution as d,formatClarifyResolution as f,formatReviewResolution as p,hasBootstrapSentinel as m,initializePluginSystem as h,inspectSession as g,listAvailableSlashCommands as _,listSessionSummaries as v,loadPendingHitl as ee,loadPendingUiTool as te,loadSessionExportSnapshots as ne,loadSkillsWithPluginDirs as re,loadTranscript as ie,normalizePluginsConfig as ae,normalizeSessionStoreName as y,readGoal as b,resolveGoalObjective as oe,resolveMemoryProviderOrDefault as se,resolvePendingHitl as ce,resolvePendingUiTool as le,rewriteTranscript as ue,runAgent as de,sessionsDir as fe,transcriptPath as pe,updateGoal as me,writeGoal as he}from"@gencode/agents";import{formatTaskForDisplay as ge,isAgentDiagnosticEvent as _e,isHitlTool as ve,parseMatchedTextToResolution as ye,parseTextToResolution as be}from"@gencode/shared";import x,{existsSync as S,mkdirSync as xe,readFileSync as Se,statSync as Ce,writeFileSync as we}from"node:fs";import C,{basename as Te,dirname as Ee,isAbsolute as De,join as w,relative as Oe,resolve as T}from"node:path";import ke from"log4js";import E from"node:fs/promises";import Ae from"node:os";import{execFile as je,execFileSync as Me}from"node:child_process";import Ne from"gensign-node";import{fileURLToPath as Pe}from"node:url";import{addAgent as Fe,addBinding as Ie,getAgentConfig as D,listAgents as Le,listBindings as Re,loadAgentsConfig as O,normalizeAgentId as ze,removeAgent as Be,removeBindings as Ve,resolveAgentDir as He,resolveDefaultAgentId as Ue,updateAgentIdentity as We}from"@gencode/agents/config";import{createHash as Ge,randomUUID as Ke}from"node:crypto";function qe(e){let t=new Intl.DateTimeFormat(`en-CA`,{timeZone:`Asia/Shanghai`,year:`numeric`,month:`2-digit`,day:`2-digit`,hour:`2-digit`,minute:`2-digit`,second:`2-digit`,hour12:!1}).formatToParts(e);return Object.fromEntries(t.map(e=>[e.type,e.value]))}function Je(e=new Date){let t=qe(e),n=String(e.getMilliseconds()).padStart(3,`0`);return`${t.year}-${t.month}-${t.day} ${t.hour}:${t.minute}:${t.second}.${n}`}let k=function(e){return e.INFO=`INFO`,e.ERROR=`ERROR`,e.WARN=`WARN`,e}({}),A=null,Ye=!1,j=[],Xe=Promise.resolve();function Ze(){return Je()}function Qe(e){if(!e)return``;let t=Object.entries(e).filter(([,e])=>e!==void 0).map(([e,t])=>`${e}=${$e(t)}`);return t.length>0?` ${t.join(` `)}`:``}function $e(e){return JSON.stringify(et(e,new WeakSet))??`undefined`}function et(e,t){return typeof e==`bigint`?e.toString():e==null||typeof e==`string`||typeof e==`number`||typeof e==`boolean`?e:e instanceof Error?{name:e.name,message:e.message,stack:e.stack}:typeof e!=`object`&&typeof e!=`function`?String(e):t.has(e)?`[Circular]`:(t.add(e),Array.isArray(e)?e.map(e=>et(e,t)):Object.fromEntries(Object.entries(e).filter(([,e])=>e!==void 0).map(([e,n])=>[e,et(n,t)])))}function tt(e){return C.join(e,`.aimax`)}function nt(e){let t=e?.trim();return t&&t.replace(/[^A-Za-z0-9_.-]/g,`_`)||`no-message-${process.pid}`}function rt(e,t){let n=nt(t?.messageId),r=t?.sessionStoreName?.trim()||`sessions`;return t?.sessionId?{runLogId:n,logDir:C.join(tt(e),r,t.sessionId,`logs`,n)}:{runLogId:n,logDir:C.join(tt(e),`logs`,n)}}function it(e){return{appLogPath:C.join(e,`app.log`),errorLogPath:C.join(e,`errors.log`)}}function at(e){let{appLogPath:t,errorLogPath:n}=it(e);ke.configure({appenders:{appFile:{type:`file`,filename:t,maxLogSize:5*1024*1024,backups:3,compress:!0,keepFileExt:!0,layout:{type:`messagePassThrough`}},errorFile:{type:`file`,filename:n,maxLogSize:5*1024*1024,backups:3,compress:!0,keepFileExt:!0,layout:{type:`messagePassThrough`}},errorsOnly:{type:`logLevelFilter`,appender:`errorFile`,level:`error`,maxLevel:`fatal`}},categories:{default:{appenders:[`appFile`,`errorsOnly`],level:`info`}}})}function ot(e,t,n){return`[${Ze()}] [${e}] ${t}${Qe(n)}`}function st(e,t,n){try{process.stderr.write(`${ot(e,t,n)}\n`)}catch{}}function M(e,t,n){if(!A){j.push({level:e,message:t,context:n}),j.length>200&&(j=j.slice(-200)),st(e,t,n);return}Ye||=(at(A.logDir),!0);let r=ot(e,t,n),i=ke.getLogger();if(e===k.ERROR){i.error(r);return}if(e===k.WARN){i.warn(r);return}i.info(r)}function N(e,t){let{logDir:n,runLogId:r}=rt(e,t);if(Ye&&A?.dataDir===e&&A.runLogId===r&&A.logDir===n)return;x.mkdirSync(n,{recursive:!0}),at(n),Ye=!0,A={dataDir:e,logDir:n,runLogId:r};let i=j;j=[];for(let e of i)M(e.level,e.message,e.context)}function ct(){return A?{...A}:null}function lt(e){if(!e.logDir){e.level===`ERROR`?M(k.ERROR,e.message,e.context):e.level===`WARN`?M(k.WARN,e.message,e.context):M(k.INFO,e.message,e.context);return}let{appLogPath:t,errorLogPath:n}=it(e.logDir),r=`${e.formatted}\n`;Xe=Xe.then(async()=>{await x.promises.mkdir(e.logDir,{recursive:!0}),await x.promises.appendFile(t,r,`utf-8`),e.level===`ERROR`&&await x.promises.appendFile(n,r,`utf-8`)}).catch(t=>{st(k.ERROR,`delegated agent log write failed`,{logDir:e.logDir,error:t instanceof Error?t.message:String(t)})})}async function ut(){await Xe;try{await dt()}finally{Ye=!1}}function dt(){return new Promise((e,t)=>{ke.shutdown(n=>{if(n){t(n);return}e()})})}const P={info:(e,t)=>M(k.INFO,e,t),warn:(e,t)=>M(k.WARN,e,t),error:(e,t)=>M(k.ERROR,e,t)};var ft=class{startTime;name;constructor(e){this.name=e,this.startTime=Date.now()}end(){let e=Date.now()-this.startTime;return P.info(`${this.name} completed in ${e}ms`),e}};function pt(e){if(typeof e==`string`)return e;let t=JSON.stringify(e);return t===void 0?String(e):t}const mt=new Set;function ht(e){return e instanceof Error?{name:e.name,message:e.message,code:e.code}:{message:String(e)}}function gt(e,t){try{P.warn(`CLI ${e} write failed; suppressing further ${e} writes`,{stream:e,...ht(t)})}catch{}}function _t(e,t){if(mt.has(e))return;let n=e===`stdout`?process.stdout:process.stderr;try{n.write(t)}catch(t){mt.add(e),gt(e,t)}}function vt(e){_t(`stdout`,e)}function F(e){_t(`stdout`,e+`
|
|
2
|
+
`)}function I(e){_t(`stderr`,e+`
|
|
3
|
+
`)}function L(e){switch(e.type){case`start`:F(`\n[start] ${e.message}`);break;case`text`:vt(e.text);break;case`stream_text_delta`:vt(e.text);break;case`bootstrap`:F(`\n[bootstrap:${e.phase}] ${e.dataDir}`);break;case`session_reset`:F(`\n[session:${e.action}] ${e.message}`);break;case`tool_start`:F(`\n[tool:${e.name}] ${JSON.stringify(e.input??{})}`);break;case`tool_end`:{let t=pt(e.output);F(`[tool:${e.name}] ${e.isError?`ERROR`:`OK`} ${t.slice(0,200)}`);break}case`compaction`:F(`\n[compaction${e.layer?`:${e.layer}`:``}] ${e.reason}${e.strategy?` (${e.strategy})`:``}`);break;case`skill_used`:F(`\n[skill] ${e.skillName} agent=${e.agent} task=${e.taskId}`);break;case`custom`:F(`\n[plugin:${e.pluginId}] ${e.name}${e.label?` ${e.label}`:``}${e.data?` ${JSON.stringify(e.data)}`:``}`);break;case`error`:I(`\n[error] ${e.message}`);break;case`diagnostic`:break;case`subagent_spawn`:F(`\n[subagent:spawn]${e.label?` "${e.label}"`:``} ${ge(e.task)}`);break;case`subagent_complete`:F(`[subagent:${e.status}] ${ge(e.task)}`);break;case`hitl_requested`:if(F(`\n[hitl:${e.request.kind}] ${e.request.title}`),F(` prompt: ${e.request.prompt}`),F(` requestId: ${e.request.requestId}`),e.request.input.mode===`choice`)for(let t of e.request.input.choices)F(` - [${t.id}] ${t.label}`);break;case`hitl_resumed`:F(`\n[hitl:resumed] requestId=${e.requestId} action=${e.resolution.action}`);break;case`hitl_expired`:F(`\n[hitl:expired] requestId=${e.requestId} reason=${e.reason}`);break;case`hitl_cancelled`:F(`\n[hitl:cancelled] requestId=${e.requestId}${e.reason?` reason=${e.reason}`:``}`);break;case`ui_tool_request`:F(`\n[ui-tool:${e.request.toolName}] ${e.request.outputSchema.title}`),F(` requestId: ${e.request.requestId}`),F(` toolCallId: ${e.request.toolCallId}`);break;case`ui_tool_result`:F(`\n[ui-tool:resumed] requestId=${e.requestId} tool=${e.toolName}`);break}}function yt(e,t){if(t===`json`){e&&F(JSON.stringify(e,null,2));return}F(`
|
|
4
|
+
`),F(`session: ${e.sessionId}`),F(`duration: ${e.durationMs}ms`),F(`tokens: input=${e.usage.input} output=${e.usage.output} total=${e.usage.total}`),e.context&&(F(`context: ${e.context.snapshotPath}`),F(`tool-results: ${e.context.toolResultsDir}`)),e.error&&I(`error: ${e.error}`)}function bt(e,t){if(t===`json`){F(JSON.stringify(e,null,2));return}if(e.length===0){F(`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:—]`;F(`${t.id} ${e} [${t.channel}]${n} ${t.title}`)}}function xt(e,t){if(t===`json`){F(JSON.stringify(e,null,2));return}F(`session: ${e.id}`),e.metadata&&(F(`title: ${e.metadata.title}`),F(`channel: ${e.metadata.channel}`),F(`created: ${e.metadata.createdAt}`),F(`updated: ${e.metadata.updatedAt}`)),F(`transcript: ${e.transcriptPath}`),F(`entries: ${e.transcriptEntryCount}`),F(`context: ${e.contextSnapshotPath}`),F(`session-memory: ${e.sessionMemoryPath}`),F(`collapse-log: ${e.collapseLogPath}`),F(`read-states: ${e.readStateCount}`),F(`tool-results: ${e.toolResultRefCount}`),F(`tool-results-dir: ${e.toolResultsDir}`)}function St(e,t){if(t===`json`){F(JSON.stringify(e,null,2));return}F(`session: ${e.id}`),F(`transcript: ${e.paths.transcriptPath}`),F(`context: ${e.paths.contextSnapshotPath}`),F(`session-memory: ${e.paths.sessionMemoryPath}`),F(`collapse-log: ${e.paths.collapseLogPath}`),F(`tool-results-dir: ${e.paths.toolResultsDir}`),F(`transcript-entries: ${e.transcript.length}`),F(`read-states: ${e.context.readStates.length}`),F(`tool-results: ${e.context.toolResults.length}`),F(`collapse-spans: ${e.context.compaction.collapseSpans.length}`)}function Ct(e,t){if(t===`json`){F(JSON.stringify(e,null,2));return}F(`Bootstrap completed.`),F(`dataDir: ${e.dataDir}`),F(`created dirs: ${e.createdDirs.length}`),F(`created files: ${e.createdFiles.length}`),F(`skipped dirs: ${e.skippedDirs.length}`),F(`skipped files: ${e.skippedFiles.length}`)}const wt=`.aimax`,Tt=`${wt}.pre-gocryptfs.`,Et=[`app.log`,`errors.log`],Dt=[`logs`],Ot=[`fusermount3`,`fusermount`,`umount`],kt=[{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 At(e){return C.join(e,`.aimax.enc`)}function jt(e){return C.join(e,wt)}function Mt(e){return C.join(e,`${Tt}${process.pid}.${Date.now()}`)}function Nt(e){return C.join(e,`${wt}.plaintext-restore.${process.pid}.${Date.now()}`)}function Pt(e){return e.replace(/\\([0-7]{3})/g,(e,t)=>String.fromCharCode(Number.parseInt(t,8)))}async function R(e){try{let t=await Lt.read(),n=C.resolve(e);for(let e of t.split(`
|
|
5
|
+
`)){if(!e.trim())continue;let t=e.split(` `);if(t.length>=5&&C.resolve(Pt(t[4]??``))===n)return!0}return!1}catch{return!1}}function Ft(e){try{let t=x.readFileSync(`/proc/self/mountinfo`,`utf-8`),n=C.resolve(e);for(let e of t.split(`
|
|
6
|
+
`)){if(!e.trim())continue;let t=e.split(` `);if(t.length>=5&&C.resolve(Pt(t[4]??``))===n)return!0}return!1}catch{return!1}}async function It(){return await E.readFile(`/proc/self/mountinfo`,`utf-8`)}const Lt={read:It};async function z(e){try{return await E.stat(e),!0}catch(e){if(e.code===`ENOENT`)return!1;throw e}}async function B(e){await E.mkdir(e,{recursive:!0})}async function Rt(e){if(await B(e),(await E.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 zt(e){return await z(e)?(await E.readdir(e)).length===0:!0}async function V(e){if(await z(e))return(await E.readdir(e)).length}async function Bt(e){if(!await z(e))return!1;let t=await E.readdir(e,{withFileTypes:!0});for(let e of t)if(!(e.isDirectory()&&Dt.includes(e.name))&&!(e.isFile()&&Et.some(t=>e.name.startsWith(t))))return!0;return!1}async function Vt(e){let t=await E.readdir(e,{withFileTypes:!0});for(let n of t){if(n.isDirectory()&&Dt.includes(n.name)){await E.rm(C.join(e,n.name),{recursive:!0,force:!0}).catch(()=>{});continue}n.isFile()&&Et.some(e=>n.name.startsWith(e))&&await E.rm(C.join(e,n.name),{force:!0}).catch(()=>{})}}async function Ht(e){if(!await z(C.join(e,`gocryptfs.conf`)))throw Error(`Encrypted .aimax directory exists but is not initialized: ${e}. Remove the incomplete .aimax.enc directory or restore it from backup before retrying --encrypt-sessions.`)}async function Ut(e){return(await E.readdir(e,{withFileTypes:!0})).filter(e=>e.isDirectory()&&e.name.startsWith(Tt)).map(t=>C.join(e,t.name)).sort()}async function Wt(e,t){if(!await z(t))return null;let n=Mt(e);return P.info(`--encrypt-sessions moving plaintext .aimax aside before migration`,{plainDir:t,backupDir:n}),await E.rename(t,n),n}async function H(e,t,n){P.info(`--encrypt-sessions copying plaintext backup into encrypted mount`,{backupDir:e,plainDir:t,force:n}),await E.cp(e,t,{recursive:!0,force:n})}async function Gt(e,t){if(e.length===0)return[];await B(t);let n=[];for(let r of e)await z(r)&&(await H(r,t,!0),await E.rm(r,{recursive:!0,force:!0}),P.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=At(e),n=jt(e),r=await z(t);if(!r)return;let i=r&&await z(C.join(t,`gocryptfs.conf`)),a=await z(n),o=a?await R(n):!1,s=await zt(n);if(P.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 V(n)}),!i){P.warn(`plaintext .aimax restore skipped because .aimax.enc is not initialized`,{encryptedDir:t,plainDir:n}),await B(n);return}if(o){P.warn(`plaintext .aimax restore skipped because .aimax is already a mount point`,{plainDir:n,encryptedDir:t});return}if(await Bt(n)){P.info(`plaintext .aimax restore skipped because plaintext .aimax already contains data`,{plainDir:n,encryptedDir:t,plainDirEntryCount:await V(n)});return}s||(P.info(`plaintext .aimax clearing ephemeral files before restore`,{plainDir:n,encryptedDir:t,plainDirEntryCount:await V(n)}),await Vt(n));try{await Yt()}catch(e){P.warn(`plaintext .aimax restore unavailable; continuing with plaintext .aimax`,{error:e instanceof Error?e.message:String(e),plainDir:n,encryptedDir:t}),await B(n);return}let c=Nt(e),l=!1;try{await Rt(n),await Xt(t,n),l=!0,await E.rm(c,{recursive:!0,force:!0}),await B(c),await E.cp(n,c,{recursive:!0,force:!0}),P.info(`plaintext .aimax restore copied encrypted history to staging directory`,{plainDir:n,encryptedDir:t,restoreDir:c,restoredEntryCount:await V(c)}),await Qt(n),l=!1,await E.rm(n,{recursive:!0,force:!0}),await E.rename(c,n),P.info(`plaintext .aimax restore completed for disabled --encrypt-sessions`,{plainDir:n,encryptedDir:t})}catch(e){l&&await Qt(n).catch(e=>{P.warn(`plaintext .aimax restore failed to unmount during rollback`,{error:e instanceof Error?e.message:String(e),plainDir:n,encryptedDir:t})}),await E.rm(c,{recursive:!0,force:!0}).catch(()=>{}),await B(n).catch(()=>{}),P.warn(`plaintext .aimax restore failed; continuing with existing plaintext .aimax`,{error:e instanceof Error?e.message:String(e),plainDir:n,encryptedDir:t})}}async function qt(e){let t=C.join(Ae.tmpdir(),`aimax-gocryptfs-pass.${process.pid}.${Date.now()}`);await E.writeFile(t,`wizard_aimax@2026
|
|
7
|
+
`,{mode:384});try{return await e(t)}finally{await E.rm(t,{force:!0})}}async function Jt(e){let t=e.includes(`-init`)?`init`:`mount`;P.info(`--encrypt-sessions starting gocryptfs ${t}`);try{await nn(`gocryptfs`,e),P.info(`--encrypt-sessions completed gocryptfs ${t}`)}catch(n){let r=n instanceof Error?n.message:String(n);throw P.warn(`--encrypt-sessions failed gocryptfs ${t}`,{error:r}),Error(`gocryptfs ${e.join(` `)} failed: ${r}`)}}async function Yt(){P.info(`--encrypt-sessions checking encryption dependencies`),await an(`gocryptfs`,`required for --encrypt-sessions`),P.info(`--encrypt-sessions dependency available`,{command:`gocryptfs`});for(let e of Ot)if(await rn(e)){P.info(`--encrypt-sessions unmount dependency available`,{command:e});return}throw Error(`--encrypt-sessions requires one of ${Ot.join(`, `)} to be installed for secure unmount cleanup.`)}async function Xt(e,t){P.info(`--encrypt-sessions mounting encrypted .aimax`,{encryptedDir:e,plainDir:t}),await qt(async n=>{await Jt([`-q`,`-passfile`,n,e,t])})}async function Zt(e){P.info(`--encrypt-sessions initializing encrypted .aimax directory`,{encryptedDir:e}),await qt(async t=>{await Jt([`-q`,`-init`,`-passfile`,t,e])})}async function Qt(e){let t=[];P.info(`--encrypt-sessions unmounting encrypted .aimax`,{plainDir:e});for(let n of kt)try{if(P.info(`--encrypt-sessions attempting encrypted .aimax unmount`,{command:n.label,plainDir:e}),await nn(n.command,[...n.args,e]),!await R(e)){P.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),P.warn(`--encrypt-sessions unmount command returned success but mountpoint remains`,{command:n.label,plainDir:e})}catch(r){let i=on(n.label,r);t.push(i),P.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 $t(e){for(let t of kt)try{if(Me(t.command,[...t.args,e],{stdio:`ignore`}),!Ft(e))return}catch{}}function en(e){let t=!1,n=()=>{t||(t=!0,$t(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 tn(e){let t=At(e),n=jt(e),r=await z(n),i=await z(t),a=i&&await z(C.join(t,`gocryptfs.conf`)),o=r?await R(n):!1;P.info(`--encrypt-sessions preparing encrypted .aimax mount`,{dataDir:e,encryptedDir:t,plainDir:n,plainDirExists:r,encryptedDirExists:i,encryptedDirInitialized:a,plainDirMountPoint:o,plainDirEntryCount:await V(n),encryptedDirEntryCount:await V(t)});let s=()=>({mounted:!1,plainDir:n,encryptedDir:t,async cleanup(){}});try{await Yt()}catch(e){return P.warn(`--encrypt-sessions is unavailable; continuing with plaintext .aimax`,{error:e instanceof Error?e.message:String(e)}),await B(n),s()}if(await R(n))return P.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 Ut(e),l.length>0&&P.warn(`--encrypt-sessions found interrupted pre-gocryptfs migration backups`,{count:l.length}),!await z(t))if(P.info(`--encrypt-sessions encrypted .aimax directory does not exist; starting first-time migration`,{encryptedDir:t,plainDir:n,resumedBackupCount:l.length}),l.length>0?u=await Wt(e,n):c=await Wt(e,n),await B(t),await Zt(t),await B(n),await Xt(t,n),f=!0,d=en(n),P.info(`--encrypt-sessions mounted encrypted .aimax`,{plainDir:n,encryptedDir:t}),l.length>0){for(let e of l)await H(e,n,!0);u&&=(await H(u,n,!1),await E.rm(u,{recursive:!0,force:!0}),P.info(`--encrypt-sessions removed residual plaintext backup after migration`,{backupDir:u}),null);for(let e of l)await E.rm(e,{recursive:!0,force:!0}),P.info(`--encrypt-sessions removed resumed plaintext migration backup`,{backupDir:e});l=[]}else c&&=(await H(c,n,!0),await E.rm(c,{recursive:!0,force:!0}),P.info(`--encrypt-sessions removed plaintext migration backup`,{backupDir:c}),null);else if(P.info(`--encrypt-sessions encrypted .aimax directory exists; mounting existing encrypted data`,{encryptedDir:t,plainDir:n,resumedBackupCount:l.length,plainDirEntryCount:await V(n)}),await Ht(t),l.length>0?u=await Wt(e,n):await zt(n)||(c=await Wt(e,n)),await Rt(n),await Xt(t,n),f=!0,d=en(n),P.info(`--encrypt-sessions mounted encrypted .aimax`,{plainDir:n,encryptedDir:t}),l.length>0){for(let e of l)await H(e,n,!0);u&&=(await H(u,n,!1),await E.rm(u,{recursive:!0,force:!0}),P.info(`--encrypt-sessions removed residual plaintext backup after migration`,{backupDir:u}),null);for(let e of l)await E.rm(e,{recursive:!0,force:!0}),P.info(`--encrypt-sessions removed resumed plaintext migration backup`,{backupDir:e});l=[]}else c&&=(await H(c,n,!0),await E.rm(c,{recursive:!0,force:!0}),P.info(`--encrypt-sessions removed plaintext migration backup`,{backupDir:c}),null);return P.info(`--encrypt-sessions prepared encrypted .aimax mount result`,{mounted:f,plainDir:n,encryptedDir:t,plainDirMountPoint:await R(n),plainDirEntryCount:await V(n),encryptedDirEntryCount:await V(t)}),{mounted:f,plainDir:n,encryptedDir:t,async cleanup(){if(d?.release(),!f){P.info(`--encrypt-sessions cleanup skipped because encrypted .aimax is not mounted`,{plainDir:n,encryptedDir:t});return}f=!1,P.info(`--encrypt-sessions cleanup started`,{plainDir:n,encryptedDir:t});try{await Qt(n),P.info(`--encrypt-sessions cleanup completed`,{plainDir:n,encryptedDir:t})}catch(e){P.warn(`--encrypt-sessions failed to unmount encrypted .aimax; continuing shutdown`,{error:e instanceof Error?e.message:String(e)})}}}}catch(e){d?.release(),f&&await Qt(n).catch(e=>{P.warn(`--encrypt-sessions failed to unmount during mount rollback`,{error:e instanceof Error?e.message:String(e),plainDir:n,encryptedDir:t})}),c&&await z(c)&&await zt(n)&&(await E.rm(n,{recursive:!0,force:!0}).catch(()=>{}),await E.rename(c,n).catch(()=>{}),P.info(`--encrypt-sessions restored plaintext backup after failed migration`,{backupDir:c,plainDir:n})),u&&await z(u)&&await zt(n)&&(await E.rm(n,{recursive:!0,force:!0}).catch(()=>{}),await E.rename(u,n).catch(()=>{}),P.info(`--encrypt-sessions restored residual plaintext backup after failed migration`,{backupDir:u,plainDir:n}));let r=await Gt(l,n).catch(e=>(P.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)),P.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 B(n),s()}}async function U(e,t,n){if(!t.encryptSessions)return await Kt(e),n();P.info(`--encrypt-sessions wrapper starting encrypted .aimax preparation`,{dataDir:e});let r=await tn(e);P.info(`--encrypt-sessions wrapper prepared encrypted .aimax state`,{dataDir:e,mounted:r.mounted,plainDir:r.plainDir,encryptedDir:r.encryptedDir});try{return P.info(`--encrypt-sessions wrapper entering protected operation`,{dataDir:e,mounted:r.mounted}),await n(r)}finally{P.info(`--encrypt-sessions wrapper starting cleanup`,{dataDir:e,mounted:r.mounted,plainDir:r.plainDir,encryptedDir:r.encryptedDir}),await r.cleanup(),P.info(`--encrypt-sessions wrapper finished cleanup`,{dataDir:e,mounted:r.mounted,plainDir:r.plainDir,encryptedDir:r.encryptedDir})}}async function nn(e,t){await new Promise((n,r)=>{je(e,t,{encoding:`utf-8`},e=>{if(e){r(e);return}n()})})}async function rn(e){try{return await nn(`sh`,[`-c`,`command -v "${e}" >/dev/null 2>&1`]),!0}catch{return!1}}async function an(e,t){if(!await rn(e))throw Error(`--encrypt-sessions requires ${e}: ${t}.`)}function on(e,t){return`${e} failed: ${t instanceof Error?t.message:String(t)}`}function sn(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{Ct(await U(e.dataDir,e,async()=>i(e.dataDir)),t)}catch(e){I(`Error bootstrapping data directory: ${e.message}`),process.exit(1)}})}function cn(e){return Ne.sm4_encrypt_ecb(e)}function ln(e){return cn(e)}const un=[`minimal`,`low`,`medium`,`high`,`xhigh`];function dn(e,t){if(e===void 0)return;let n=e.trim().toLowerCase();if(n){if(un.includes(n))return n;throw Error(`Invalid ${t}: ${e}. Must be one of ${un.join(`, `)}.`)}}function fn(e={}){let t=pn(e.apiFormat??process.env.AIMAX_API_FORMAT),n=e.baseUrl??process.env.AIMAX_BASE_URL,r=process.env.AIMAX_AUTH_TOKEN,i=e.authToken?ln(e.authToken):r?ln(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,thinking:e.thinking===void 0?dn(process.env.AIMAX_THINKING,`AIMAX_THINKING`):dn(e.thinking,`--thinking`)}}function pn(e){if(!e||e===`openai-completions`||e===`anthropic-messages`)return e;throw Error(`Unsupported LLM API format: ${e}`)}const mn=[`off`,`fallback`];function hn(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 gn(e,t){if(e===void 0)return;let n=e.trim();if(!n)return;let r=Number(n);if(!Number.isFinite(r))throw Error(`Invalid ${t}: ${e}. Must be a number.`);return r}function _n(e,t){if(e===void 0)return;let n=e.trim().toLowerCase();if(n){if(mn.includes(n))return n;throw Error(`Invalid ${t}: ${e}. Must be one of ${mn.join(`, `)}.`)}}function vn(){return[`AIMAX_MEMORY_KC_ENABLED`,`AIMAX_MEMORY_KC_BASE_URL`,`AIMAX_MEMORY_KC_BASE_PATH`,`AIMAX_MEMORY_KC_AUTH_TOKEN`,`AIMAX_MEMORY_KC_SEARCH_MODE`,`AIMAX_MEMORY_KC_TOP_K`,`AIMAX_MEMORY_KC_SCORE_THRESHOLD`,`AIMAX_MEMORY_KC_TIMEOUT_MS`,`AIMAX_MEMORY_KC_SYNC_ENABLED`].some(e=>process.env[e]!==void 0)}function yn(e){return Object.values(e).some(e=>e!==void 0)}function bn(e={}){if(!(!yn(e)&&!vn()))return{knowledgeController:{enabled:e.kcEnabled??hn(process.env.AIMAX_MEMORY_KC_ENABLED,`AIMAX_MEMORY_KC_ENABLED`),baseUrl:e.kcBaseUrl??process.env.AIMAX_MEMORY_KC_BASE_URL,basePath:e.kcBasePath??process.env.AIMAX_MEMORY_KC_BASE_PATH,authToken:e.kcAuthToken??process.env.AIMAX_MEMORY_KC_AUTH_TOKEN,searchMode:e.kcSearchMode===void 0?_n(process.env.AIMAX_MEMORY_KC_SEARCH_MODE,`AIMAX_MEMORY_KC_SEARCH_MODE`)??`off`:_n(e.kcSearchMode,`kcSearchMode`),topK:e.kcTopK??gn(process.env.AIMAX_MEMORY_KC_TOP_K,`AIMAX_MEMORY_KC_TOP_K`),scoreThreshold:e.kcScoreThreshold??gn(process.env.AIMAX_MEMORY_KC_SCORE_THRESHOLD,`AIMAX_MEMORY_KC_SCORE_THRESHOLD`),timeoutMs:e.kcTimeoutMs??gn(process.env.AIMAX_MEMORY_KC_TIMEOUT_MS,`AIMAX_MEMORY_KC_TIMEOUT_MS`),syncEnabled:e.kcSyncEnabled??hn(process.env.AIMAX_MEMORY_KC_SYNC_ENABLED,`AIMAX_MEMORY_KC_SYNC_ENABLED`)}}}function xn(e,t){return t?C.resolve(t):C.join(e,`.aimax`,`plugins.json`)}async function W(e,t){let n=xn(e,t);try{let e=await E.readFile(n,`utf-8`);return JSON.parse(e)}catch(e){if(e.code===`ENOENT`)return;throw e}}async function G(e,t,n){let r=xn(e,n);await E.mkdir(C.dirname(r),{recursive:!0}),await E.writeFile(r,JSON.stringify(t,null,2),`utf-8`)}function K(e){return typeof e==`object`&&!!e}function Sn(e){return K(e)&&e.type===`text`&&typeof e.text==`string`&&(e.textSignature===void 0||typeof e.textSignature==`string`)}function Cn(e){return K(e)&&e.type===`image`&&typeof e.data==`string`&&typeof e.mimeType==`string`}function wn(e){return K(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 Tn(e){return K(e)&&e.type===`toolCall`&&typeof e.id==`string`&&typeof e.name==`string`&&K(e.arguments)&&(e.thoughtSignature===void 0||typeof e.thoughtSignature==`string`)}function En(e){return typeof e==`string`||Array.isArray(e)&&e.every(e=>Sn(e)||Cn(e))}function Dn(e){return Array.isArray(e)&&e.every(e=>Sn(e)||wn(e)||Tn(e))}function On(e){return K(e)&&typeof e.input==`number`&&typeof e.output==`number`&&typeof e.cacheRead==`number`&&typeof e.cacheWrite==`number`&&typeof e.totalTokens==`number`&&K(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 kn(e){return!K(e)||typeof e.role!=`string`?!1:e.role===`user`?En(e.content):e.role===`assistant`?Dn(e.content)&&typeof e.api==`string`&&typeof e.provider==`string`&&typeof e.model==`string`&&On(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=>Sn(e)||Cn(e))&&typeof e.isError==`boolean`:!1}async function An(e){let t;try{t=await E.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}`)}return jn(n,`Message file`)}function jn(e,t=`Messages input`){let n=Array.isArray(e)?e:[e];if(n.length===0||!n.every(e=>kn(e)))throw Error(`${t} must contain one Message object or an array of Message objects`);return n}async function Mn(e){if([!!e.message,!!e.fromFile,e.messages!==void 0].filter(Boolean).length!==1)throw Error(`Exactly one of --message, --from-file, or messages must be provided`);return e.fromFile?{kind:`messages`,messages:await An(e.fromFile),source:`file`}:e.messages===void 0?{kind:`text`,message:e.message}:{kind:`messages`,messages:jn(e.messages),source:`inline`}}var Nn=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()}))}},Pn=class{deliveryQueue=Promise.resolve();constructor(e){this.url=e}async send(e){this.enqueue(this.toPayload(e))}async close(){await this.deliveryQueue}enqueue(e){let t=this.deliveryQueue.then(async()=>{await this.post(e)},async()=>{await this.post(e)});return this.deliveryQueue=t.catch(()=>{}),t}async post(e){let t=Date.now(),n=Fn(e);P.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){P.error(`callback event failed`,{callbackUrl:this.url,httpStatus:a.status,durationMs:o,timedOut:i,...n});return}P.info(`callback event delivered`,{callbackUrl:this.url,httpStatus:a.status,durationMs:o,...n})}catch(e){let r=Date.now()-t;P.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 Fn(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 In(e,t){if(t.kind===`none`)return e;let n=new URL(e);return n.searchParams.set(`authToken`,t.token),n.toString()}const Ln=5e3,Rn=5e3;function zn(){let e=globalThis.WebSocket;if(!e)throw Error(`WebSocket is not available in this runtime`);return e}function Bn(e){return e?{kind:`query_token`,token:e}:{kind:`none`}}function Vn(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 Un=class{socket=null;connectPromise=null;enabled=!0;textSequence=0;constructor(e,t,n){this.url=e,this.events=t,this.authToken=n}async send(e){let t=this.toEnvelope(e);if(!(!t||!this.enabled))try{await Wn(this.ensureConnected(),Ln,`WebSocket connection timed out after ${Ln}ms`);let e=zn();if(!this.socket||this.socket.readyState!==e.OPEN)return;this.socket.send(JSON.stringify(t))}catch(e){P.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 Wn(this.ensureConnected(),Ln,`WebSocket connection timed out after ${Ln}ms`);let e=zn();if(!this.socket||this.socket.readyState!==e.OPEN)return;this.socket.send(JSON.stringify(t))}catch(e){P.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=zn();if(e.readyState!==t.CLOSED)try{await Wn(new Promise(t=>{Vn(e,`close`,()=>t()),e.close()}),Rn,`WebSocket close timed out after ${Rn}ms`)}catch(e){P.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=zn();if(this.socket&&this.socket.readyState===e.OPEN)return;if(this.connectPromise){await this.connectPromise;return}let t=new e(In(this.url,Bn(this.authToken)));this.connectPromise=new Promise((e,n)=>{Vn(t,`open`,()=>{this.socket=t,Hn(t,`close`,()=>{this.socket===t&&(this.socket=null)}),e()}),Vn(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 Wn(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 Gn(e){let t=e.trim();if(!t)throw Error(`Goal objective cannot be empty`);return t}function Kn(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 qn(e){let t=Kn(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 Jn(e){let t=e?.packageRoot??Yn(),n=C.join(t,`models`),r=C.join(n,...`Xenova/bge-small-zh-v1.5`.split(`/`));if(x.existsSync(C.join(r,`config.json`)))return n}function Yn(){let e=C.dirname(Pe(import.meta.url));return C.basename(e)===`src`||C.basename(e)===`dist`?C.resolve(e,`..`):e}function Xn(e){return{text:e.text,usage:e.usage,durationMs:e.durationMs,...e.error?{error:e.error}:{},...e.paused?{paused:e.paused}:{},...e.uiToolPending?{uiToolPending:e.uiToolPending}:{},...e.artifacts&&e.artifacts.length>0?{artifacts:e.artifacts}:{}}}function Zn(e){if(!e?.trim())return;let t=new Set,n=[];for(let r of e.split(`,`)){let e=r.trim();if(!e)continue;let i=Qn(e);if(!i)throw Error(`Invalid --artifacts-url-whitelist entry: ${e}. Expected a domain or URL with a valid hostname.`);t.has(i)||(t.add(i),n.push(i))}return n.length>0?n:void 0}function Qn(e){try{let t=/^[a-z][a-z\d+.-]*:\/\//i.test(e)?e:`http://${e}`,n=new URL(t);return n.username||n.password?null:n.hostname.trim().toLowerCase()||null}catch{return null}}const $n=[`start`,`text`,`done`,`error`,`hitl`],er=[`off`,`gate`,`dry_run`,`write`];function tr(e){if(!e?.trim())return new Set($n);let t=e.split(`,`).map(e=>e.trim().toLowerCase()).filter(Boolean),n=new Set([`start`,`text`,`progress`,`done`,`error`,`hitl`,`title_updated`]),r=new Set;for(let e of t){if(!n.has(e))throw Error(`Invalid stream event: ${e}. Must be one of start,text,progress,done,error,hitl`);r.add(e)}return r.size>0?r:new Set($n)}function nr(e){if(e.disableTopicSegmentation===!0||process.env.AIMAX_DISABLE_TOPIC_SEGMENTATION===`true`)return{enabled:!1};let t=Jn();return t?{embeddingModelDir:t}:void 0}function rr(e){return e.disableTitle===!0||process.env.AIMAX_DISABLE_TITLE===`true`?{enabled:!1}:void 0}function ir(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 ar(e){return e?.trim()||void 0}function or(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 sr(e){return e?y(e):void 0}function cr(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 lr(e){if(!e?.trim())return[];let t=e.split(`,`).map(e=>e.trim()).filter(Boolean),n=new Set,r=[];for(let e of t)n.has(e)||(n.add(e),r.push(e));return r}function ur(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 dr(e,t){if(e===void 0)return;let n=e.trim().toLowerCase();if(n){if(er.includes(n))return n;throw Error(`Invalid ${t}: ${e}. Must be one of off,gate,dry_run,write.`)}}function fr(e){let t=e.autoSkillsLoadEnabled===void 0?ur(process.env.AIMAX_AUTO_SKILLS_LOAD_ENABLED,`AIMAX_AUTO_SKILLS_LOAD_ENABLED`):ur(e.autoSkillsLoadEnabled,`--auto-skills-load-enabled`),n=e.autoSkillsReviewMode===void 0?dr(process.env.AIMAX_AUTO_SKILLS_REVIEW_MODE,`AIMAX_AUTO_SKILLS_REVIEW_MODE`):dr(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 pr(e,t){if(e.inputText&&t){let n=be(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 mr(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 hr(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 gr(e){let t=ir(e),n=e.channel??`WEB`,r=fn({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,thinking:e.thinking});return{dataDir:t,systemAgentsDir:or(e),channel:n,format:e.output===`json`?`json`:`text`,timeoutMs:e.timeout?Number(e.timeout):void 0,llm:r,skillsLoadPaths:cr(e.skillsLoadPaths),workdirAllowlist:lr(e.workdirAllowlist),artifactsUrlWhitelist:Zn(e.artifactsUrlWhitelist),autoSkills:fr(e)}}function _r(e){let t=[],n=null;return e.callbackUrl&&t.push(new Pn(e.callbackUrl)),e.streamUrl&&(n=new Un(e.streamUrl,tr(e.streamEvents),e.streamAuthToken),t.push(n)),{sink:new Nn(t),websocketSink:n}}async function vr(e){let{dataDir:t,sessionId:n,sessionStoreName:r,toolCallId:i,toolName:a,resolution:o,encryptSessions:s}=e;if(!i||!a||!ve(a))return;let c=(e,t)=>{switch(e){case`request_approval`:return d(t);case`clarify`:return f(t);case`request_review`:return p(t);default:return JSON.stringify({action:t.action,values:t.values})}};await 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 yr(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})}function br(){let e=bn();return e?{core:e}:void 0}async function xr(e){let t=ir(e);await U(t,e,async()=>{N(t,{messageId:e.messageId,sessionId:e.sessionId,sessionStoreName:sr(e.sessionStore)});let i=new ft(`resume command`),a=null;try{let t=await gr(e),o=sr(e.sessionStore),c=null;if(e.goal||e.goalFile){let i;i=e.goalFile?await E.readFile(e.goalFile,`utf-8`):e.goal;let a=Gn(i),s=e.tokenBudget===void 0?void 0:e.tokenBudget===`0`||e.tokenBudget===``?null:Number(e.tokenBudget);s!=null&&(Number.isNaN(s)||s<=0)&&(I(`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=qn({sessionId:e.sessionId,before:n,result:i})}catch(e){throw e instanceof n&&(I(e.message),I(`Existing: ${e.existingObjectivePreview}`),process.exit(2)),e}}P.info(`resume command started`,{sessionId:e.sessionId,requestId:e.requestId,channel:t.channel,dataDir:t.dataDir});let l=await ee(t.dataDir,e.sessionId,{storeName:o,encryptSessions:e.encryptSessions}),u=l?null:await te(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=pr(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=Sr(n,s.request.kind);await vr({dataDir:t.dataDir,sessionId:e.sessionId,sessionStoreName:o,toolCallId:s.toolContext?.toolCallId,toolName:s.toolContext?.toolName,resolution:n,encryptSessions:e.encryptSessions});let d=_r(e);a=d.sink;let f=e.sessionId,p=async n=>{if(f=n.sessionId??f,!_e(n)){if(n.type===`stream_text_delta`){t.format===`text`&&L(n),await d.websocketSink?.sendTextDelta({sessionId:f,channel:t.channel,messageId:e.messageId,user:e.user,text:n.text});return}t.format===`text`&&L(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&&(P.info(`resume command treated as idempotent replay`,{sessionId:e.sessionId,requestId:e.requestId,idempotencyKey:n.idempotencyKey}),yt({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 W(t.dataDir,m),g;try{g=await de({dataDir:t.dataDir,projectDir:ar(e.projectDir),systemAgentsDir:t.systemAgentsDir,sessionStoreName:o,sessionId:e.sessionId,messageId:e.messageId,channel:t.channel,llm:t.llm,skillsLoadPaths:t.skillsLoadPaths,workdirAllowlist:t.workdirAllowlist,artifactsUrlWhitelist:t.artifactsUrlWhitelist,autoSkills:t.autoSkills,timeoutMs:t.timeoutMs,message:u,encryptSessions:e.encryptSessions??!1,topicSegmentation:nr(e),titleGeneration:rr(e),memory:br(),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,onLog:lt})}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:Xn(g)}),yt(g,t.format),g.error?P.error(`resume command failed: ${g.error}`):P.info(`resume command succeeded`),i.end(),process.exit(g.error?1:0)}let d=mr(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 yr({dataDir:t.dataDir,sessionId:e.sessionId,sessionStoreName:o,result:d,encryptSessions:e.encryptSessions});let f=_r(e);a=f.sink;let p=e.sessionId,m=async n=>{if(p=n.sessionId??p,!_e(n)){if(n.type===`stream_text_delta`){t.format===`text`&&L(n),await f.websocketSink?.sendTextDelta({sessionId:p,channel:t.channel,messageId:e.messageId,user:e.user,text:n.text});return}if(t.format===`text`&&L(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 hr({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 W(t.dataDir,g),v=await de({dataDir:t.dataDir,projectDir:ar(e.projectDir),systemAgentsDir:t.systemAgentsDir,sessionStoreName:o,sessionId:e.sessionId,messageId:e.messageId,channel:t.channel,llm:t.llm,skillsLoadPaths:t.skillsLoadPaths,workdirAllowlist:t.workdirAllowlist,artifactsUrlWhitelist:t.artifactsUrlWhitelist,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:nr(e),titleGeneration:rr(e),memory:br(),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,onLog:lt});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:Xn(v)}),yt(v,t.format),v.error?P.error(`resume command failed: ${v.error}`):P.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}`})),P.error(`resume command error: ${n.message}`),I(`Fatal: ${n.message}`),i.end(),process.exit(1)}})}function Sr(e,t){return o(e,t)}function Cr(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(`--workdir-allowlist <paths>`,`Comma-separated additional roots allowed as cwd for exec-style tools`).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(`--thinking <level>`,`Explicit thinking level: minimal, low, medium, high, or xhigh (overrides AIMAX_THINKING)`).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`).option(`--disable-title`,`Skip LLM session title generation for new sessions (overrides AIMAX_DISABLE_TITLE)`).action(async e=>{await xr(e)})}function wr(e,t){return{notify:(n,r=`info`)=>{t?.readyState===1?t.send(JSON.stringify({type:`diagnostic`,sessionId:e,level:r,message:n})):console.log(`[${r}] ${n}`)},confirm:async n=>!t||t.readyState!==1?!1:new Promise(r=>{let i=`confirm-${Date.now()}`;t.send(JSON.stringify({type:`hitl_confirm`,sessionId:e,id:i,message:n}));let a=e=>{try{let t=JSON.parse(String(e));r(t.id===i&&t.confirmed===!0)}catch{r(!1)}};typeof t.once==`function`?t.once(`message`,a):t.addEventListener(`message`,e=>a(e.data),{once:!0})}),select:async(n,r)=>{if(!(!t||t.readyState!==1))return new Promise(i=>{let a=`select-${Date.now()}`;t.send(JSON.stringify({type:`hitl_select`,sessionId:e,id:a,title:n,options:r}));let o=e=>{try{let t=JSON.parse(String(e));i(t.id===a?t.selected:void 0)}catch{i(void 0)}};typeof t.once==`function`?t.once(`message`,o):t.addEventListener(`message`,e=>o(e.data),{once:!0})})},setStatus:n=>{t?.readyState===1?t.send(JSON.stringify({type:`diagnostic`,sessionId:e,level:`info`,message:n})):console.log(`[status] ${n}`)}}}const Tr=[`start`,`text`,`done`,`error`],Er=[`off`,`gate`,`dry_run`,`write`];function Dr(e){if(!e?.trim())return new Set(Tr);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(Tr)}function Or(e){if(e.disableTopicSegmentation===!0||process.env.AIMAX_DISABLE_TOPIC_SEGMENTATION===`true`)return{enabled:!1};let t=Jn();return t?{embeddingModelDir:t}:void 0}function kr(e){return e.disableTitle===!0||process.env.AIMAX_DISABLE_TITLE===`true`?{enabled:!1}:void 0}function Ar(e){let t=e.dataDir??process.env.AIMAX_DATA_DIR;if(!t)throw Error(`Data directory must be specified via --data-dir option or AIMAX_DATA_DIR environment variable`);return t}function jr(e){return e?.trim()||void 0}function Mr(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 Nr(e){return e?.trim()||void 0}function Pr(e){return e??`WEB`}function Fr(e){return e?y(e):void 0}function Ir(e,t){return e===`CRON`?`crons`:Fr(t)}function Lr(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 Rr(e){if(!e?.trim())return[];let t=e.split(`,`).map(e=>e.trim()).filter(Boolean),n=new Set,r=[];for(let e of t)n.has(e)||(n.add(e),r.push(e));return r}function zr(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 Br(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 Vr(e){if(!e?.trim())return{};let t=[],n=new Set;for(let r of Br(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,zr(o)])}return Object.fromEntries(t)}function Hr(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 Ur(e,t){if(e===void 0)return;let n=e.trim().toLowerCase();if(n){if(Er.includes(n))return n;throw Error(`Invalid ${t}: ${e}. Must be one of off,gate,dry_run,write.`)}}function Wr(e){let t=e.autoSkillsLoadEnabled===void 0?Hr(process.env.AIMAX_AUTO_SKILLS_LOAD_ENABLED,`AIMAX_AUTO_SKILLS_LOAD_ENABLED`):Hr(e.autoSkillsLoadEnabled,`--auto-skills-load-enabled`),n=e.autoSkillsReviewMode===void 0?Ur(process.env.AIMAX_AUTO_SKILLS_REVIEW_MODE,`AIMAX_AUTO_SKILLS_REVIEW_MODE`):Ur(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 Gr(e,t){return e.length<=t?e:t<=3?e.slice(0,t):`${e.slice(0,t-3)}...`}function Kr(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 qr(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?` ${Gr(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=>Kr(e,a).map(e=>`│ ${e.padEnd(a,` `)} │`)),l].join(`
|
|
9
|
+
`)}function Jr(e){return e.kind===`text`?`inline message (${e.message.length} chars)`:e.source===`file`?`message file (${e.messages.length} messages)`:`inline messages (${e.messages.length} messages)`}function q(e,t=`-`){return e==null||e===``?t:String(e)}function Yr(e){return e?`set`:`unset`}function Xr(e){return e?`true`:`false`}function Zr(e,t){let n=Ir(t.channel,e.sessionStore)??`sessions`,r=t.timeoutMs===void 0?`default`:`${t.timeoutMs}`,i=e.callbackUrl?`enabled`:`disabled`,a=e.streamUrl?`enabled`:`disabled`,o=Jr(t.input),s=t.input.kind===`text`?`inline`:e.fromFile??t.input.source,c=Je(),l=Or(e)?.enabled===!1?`disabled`:`enabled`,u=kr(e)?.enabled===!1?`disabled`:`enabled`,d=e.pluginsConfig??process.env.AIMAX_PLUGINS_CONFIG,f=[...Dr(e.streamEvents)].join(`,`),p=t.autoSkills?.load?.enabled,m=t.autoSkills?.review?.mode,h=e.tokenBudget===`0`?`unlimited`:q(e.tokenBudget),g=t.artifactsUrlWhitelist?.join(`,`)??`-`,_=e.env?Object.keys(Vr(e.env)):[],v=_.length===0?`-`:`${_.length} key${_.length===1?``:`s`}`;return{banner:qr(void 0,[`AIMax CLI`,`Stateless Agent Runner`]),contextBox:qr(`Run Context`,[`time : ${c}`,`dataDir : ${t.dataDir}`,`projectDir : ${jr(e.projectDir)??`-`}`,`systemAgents : ${t.systemAgentsDir??`/aimax/agents`}`,`agent : ${Nr(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: ${p===void 0?`-`:String(p)}`,`autoSkillRev : ${m??`-`}`,`sessionId : ${e.sessionId??`new`}`,`sessionStore : ${n}`,`messageId : ${e.messageId??`-`}`,`workspace : ${C.join(t.dataDir,`workspace`)}`,`baseUrl : ${t.llm.baseUrl}`,`apiKey : ${Yr(t.llm.apiKey)}`,`authToken : ${Yr(e.authToken)}`,`model : ${t.llm.model}`,`contextWindow: ${q(t.llm.contextWindow)}`,`flashModel : ${q(t.llm.flashModel)}`,`thinking : ${q(t.llm.thinking)}`,`callbackUrl : ${q(e.callbackUrl)}`,`streamUrl : ${q(e.streamUrl)}`,`streamAuth : ${Yr(e.streamAuthToken)}`,`streamEvents : ${f}`,`artifactUrls : ${g}`,`output : ${t.format}`,`callback : ${i}`,`websocket : ${a}`,`timeoutMs : ${r}`,`pluginsConfig: ${q(d)}`,`env : ${v}`,`goal : ${e.goal===void 0?`-`:`inline (${e.goal.length} chars)`}`,`goalFile : ${q(e.goalFile)}`,`tokenBudget : ${h}`,`force : ${Xr(e.force)}`,`resumeReqId : ${q(e.resumeRequestId)}`,`resumeInput : ${e.resumeInputJson===void 0?`-`:`inline (${e.resumeInputJson.length} chars)`}`,`resumeFile : ${q(e.resumeFromFile)}`,`encryptSess : ${Xr(e.encryptSessions)}`,`topicSegment : ${l}`,`titleGen : ${u}`]),logContext:{time:c,channel:t.channel,user:e.user,dataDir:t.dataDir,projectDir:jr(e.projectDir),systemAgentsDir:t.systemAgentsDir,agent:Nr(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:p,autoSkillsReviewMode:m,baseUrl:t.llm.baseUrl,hasApiKey:!!t.llm.apiKey,hasAuthToken:!!e.authToken,model:t.llm.model,contextWindow:t.llm.contextWindow,flashModel:t.llm.flashModel,thinking:t.llm.thinking,callbackUrl:e.callbackUrl,streamUrl:e.streamUrl,hasStreamAuthToken:!!e.streamAuthToken,streamEvents:f,artifactsUrlWhitelist:t.artifactsUrlWhitelist?.join(`,`)||void 0,output:t.format,hasCallback:!!e.callbackUrl,hasStream:!!e.streamUrl,timeoutMs:t.timeoutMs,pluginsConfig:d,envKeys:_.length>0?_.join(`,`):void 0,hasGoal:e.goal!==void 0,goalFile:e.goalFile,tokenBudget:h===`-`?void 0:h,force:!!e.force,resumeRequestId:e.resumeRequestId,hasResumeInputJson:e.resumeInputJson!==void 0,resumeFromFile:e.resumeFromFile,encryptSessions:!!e.encryptSessions,topicSegmentation:l,titleGeneration:u,inputKind:t.input.kind,inputSource:s,inputSummary:o}}}async function Qr(e,t){let n=Ar(e),r=Pr(e.channel),i=fn({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,thinking:e.thinking});return{dataDir:n,systemAgentsDir:Mr(e),channel:r,format:e.output===`json`?`json`:`text`,timeoutMs:e.timeout?Number(e.timeout):void 0,llm:i,input:t,skillsLoadPaths:Lr(e.skillsLoadPaths),workdirAllowlist:Rr(e.workdirAllowlist),artifactsUrlWhitelist:Zn(e.artifactsUrlWhitelist),autoSkills:Wr(e)}}function $r(e){if(e.kind===`text`)return e.message;if(e.messages.length!==1)return null;let[t]=e.messages;if(t.role!==`user`)return null;if(typeof t.content==`string`)return t.content;if(t.content.length===0)return null;let n=[];for(let e of t.content){if(e.type!==`text`)return null;n.push(e.text)}return n.join(`
|
|
10
|
+
`)}async function ei(e,t){if(!e.sessionId)return null;let n=$r(t);if(!n)return null;let r=await ee(Ar(e),e.sessionId,{storeName:Fr(e.sessionStore),encryptSessions:e.encryptSessions});return!r||r.status!==`pending`||!ye(n,r.request)?null:{requestId:r.request.requestId,inputText:n}}function ti(e){let t=[],n=null;return e.callbackUrl&&t.push(new Pn(e.callbackUrl)),e.streamUrl&&(n=new Un(e.streamUrl,Dr(e.streamEvents),e.streamAuthToken),t.push(n)),{sink:new Nn(t),websocketSink:n}}async function J(e,t){P.info(`dispatching external event`,Si(t)),await e.sink.send(t)}function ni(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`){P.error(e.message,t);return}if(e.level===`warn`){P.warn(e.message,t);return}P.info(e.message,t)}function ri(e,t,n,r,i){return{sink:e,websocketSink:t,channel:n,defaultMessageId:r,user:i}}function ii(e){let t=new AbortController,n=n=>{P.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 ai(e){return{activeSessionId:e??`pending`,finalResult:null,loggerSessionId:void 0}}function oi(e,t,n,r){!r||n.loggerSessionId===r||(N(e,{messageId:t.messageId,sessionId:r,sessionStoreName:Ir(t.channel,t.sessionStore)}),n.loggerSessionId=r)}function si(e,t){e.activeSessionId=t.sessionId??e.activeSessionId}function ci(e,t){return e.messageId??t}async function li(e,t,n){if(!await m(e.dataDir)){if(await ui(t,e.format,n.activeSessionId,e.dataDir,`checking`),(await l(e.dataDir)).performedBootstrap){await ui(t,e.format,n.activeSessionId,e.dataDir,`initializing`),await ui(t,e.format,n.activeSessionId,e.dataDir,`initialized`);return}await ui(t,e.format,n.activeSessionId,e.dataDir,`ready`)}}async function ui(e,t,n,r,i){let a={type:`bootstrap`,phase:i,dataDir:r};t===`text`&&L(a),await J(e,{sessionId:n,channel:e.channel,messageId:e.defaultMessageId,user:e.user,type:`progress`,event:a})}function di(e,t,n,r){return async i=>{if(si(n,i),oi(e.dataDir,{...r,channel:e.channel},n,i.sessionId),_e(i)){ni(i);return}if(i.type===`stream_text_delta`){e.format===`text`&&L(i),await t.websocketSink?.sendTextDelta({sessionId:n.activeSessionId,channel:e.channel,messageId:ci(i,t.defaultMessageId),user:t.user,text:i.text});return}e.format===`text`&&L(i);let a=ci(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 fi(e){let t=wr(e);return{confirm:(e,n)=>t.confirm(e),select:(e,n,r)=>t.select?t.select(e,n):Promise.resolve(void 0)}}function pi(e,t,n,r,i,a){let o=bn(),s={dataDir:t.dataDir,projectDir:jr(e.projectDir),systemAgentsDir:t.systemAgentsDir,agentPolicy:Nr(e.agent)?{requestedAgentName:Nr(e.agent)}:void 0,sessionStoreName:Ir(t.channel,e.sessionStore),sessionId:e.sessionId,messageId:e.messageId,channel:t.channel,llm:t.llm,skillsLoadPaths:t.skillsLoadPaths,workdirAllowlist:t.workdirAllowlist,artifactsUrlWhitelist:t.artifactsUrlWhitelist,autoSkills:t.autoSkills,timeoutMs:t.timeoutMs,abortSignal:n.signal,pendingGoal:a,encryptSessions:e.encryptSessions??!1,topicSegmentation:Or(e),titleGeneration:kr(e),env:Vr(e.env),...o?{memory:{core:o}}:{},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,onLog:lt,createPiExtensionDialogBridge:fi};return t.input.kind===`messages`?{...s,messages:t.input.messages}:{...s,message:t.input.message}}async function mi(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:Xn(r)})}async function hi(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 gi(e,t){let n=Zr(e,t);P.info([`run command started`,n.banner,n.contextBox].join(`
|
|
11
|
+
`),n.logContext),t.format===`text`&&(F(n.banner),F(``),F(n.contextBox),F(``))}function _i(e,t,n){return yt(t,n),t.error?P.error(`run command failed: ${t.error}`):P.info(`run command succeeded`),e.end(),t.error?1:0}function vi(e){let t=ct();if(!t)return;let n=`[${Je()}] [ERROR] ${e}\n`;try{x.appendFileSync(C.join(t.logDir,`app.log`),n),x.appendFileSync(C.join(t.logDir,`errors.log`),n)}catch{}}async function yi(e,t){let n=`run command error: ${t.message}`;P.error(n),vi(n),I(`Fatal: ${t.message}`),e.end(),await ut(),process.exit(1)}async function bi(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 E.readFile(e.resumeFromFile,`utf-8`)}catch(e){throw Error(`Failed to read resume input file: ${e.message}`)}}async function xi(e){let t=Ar(e);try{await U(t,e,async i=>{let a=ai(e.sessionId);oi(t,{...e,channel:Pr(e.channel)},a,e.sessionId),e.encryptSessions&&P.info(`--encrypt-sessions run mount state after logger initialization`,{dataDir:t,mounted:i?.mounted??!1,plainDir:i?.plainDir,encryptedDir:i?.encryptedDir});let o=new ft(`run command`),s=await bi(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 xr({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,thinking:e.thinking,callbackUrl:e.callbackUrl,streamUrl:e.streamUrl,streamAuthToken:e.streamAuthToken,streamEvents:e.streamEvents,timeout:e.timeout,output:e.output,pluginsConfig:e.pluginsConfig,artifactsUrlWhitelist:e.artifactsUrlWhitelist,skillsLoadPaths:e.skillsLoadPaths,workdirAllowlist:e.workdirAllowlist,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,disableTitle:e.disableTitle});return}let c;try{c=await Mn({message:e.message,fromFile:e.fromFile,messages:e.messages})}catch(e){await yi(o,e);return}let l=await ei(e,c);if(l){await xr({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,thinking:e.thinking,callbackUrl:e.callbackUrl,streamUrl:e.streamUrl,streamAuthToken:e.streamAuthToken,streamEvents:e.streamEvents,timeout:e.timeout,output:e.output,pluginsConfig:e.pluginsConfig,artifactsUrlWhitelist:e.artifactsUrlWhitelist,skillsLoadPaths:e.skillsLoadPaths,workdirAllowlist:e.workdirAllowlist,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,disableTitle:e.disableTitle});return}let u=e.channel??`WEB`,{controller:d,cleanup:f}=ii(()=>({activeSessionId:a.activeSessionId,finalSessionId:a.finalResult?.sessionId,messageId:e.messageId,channel:u,user:e.user})),p=null;try{let t=await Qr(e,c);u=t.channel,gi(e,t);let i=ti(e);p=i.sink,P.info(`external sink configured`,{callbackUrl:e.callbackUrl,streamUrl:e.streamUrl,streamEvents:e.streamEvents});let s=ri(p,i.websocketSink,t.channel,e.messageId,e.user);await li(t,s,a);let l,f=null;if(e.goal||e.goalFile){let i;i=e.goalFile?await E.readFile(e.goalFile,`utf-8`):e.goal;let a=Gn(i),o=Fr(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)&&(I(`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=qn({sessionId:e.sessionId,before:n,result:i})}else l={objective:a,tokenBudget:s??null}}catch(e){throw e instanceof n&&(I(e.message),I(`Existing: ${e.existingObjectivePreview}`),process.exit(2)),e}}let m=e.pluginsConfig??process.env.AIMAX_PLUGINS_CONFIG,h=await W(t.dataDir,m),g=di(t,s,a,e);f&&await g(f);let _=await de(pi(e,t,d,g,h,l));oi(t.dataDir,{...e,channel:t.channel},a,_.sessionId),await mi(s,a,e.messageId,_),process.exitCode=_i(o,_,t.format)}catch(t){let n=t;p&&await hi(ri(p,null,u,e.messageId,e.user),a,e.messageId,n),await yi(o,n)}finally{await p?.close(),f()}})}finally{await ut()}}function Si(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 Ci(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(`--workdir-allowlist <paths>`,`Comma-separated additional roots allowed as cwd for exec-style tools`).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(`--thinking <level>`,`Explicit thinking level: minimal, low, medium, high, or xhigh (overrides AIMAX_THINKING)`).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(`--artifacts-url-whitelist <urls>`,`Comma-separated URL artifact hostnames or URLs to collect; unset collects all URL artifacts`).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`).option(`--disable-title`,`Skip LLM session title generation for new sessions (title falls back to a truncated first message; overrides AIMAX_DISABLE_TITLE)`).action(async e=>{await xi(e)})}function wi(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||(I(`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`&&(I(`Invalid channel: ${r.channel}. Must be 'H5', 'WEB', 'KLPA', 'TASK', 'CRON', or 'EIP_ASSISTANT'`),process.exit(1));try{await U(r.dataDir,r,async()=>{let e=r.sessionStore?y(r.sessionStore):void 0;if(i===`list`){bt(await v(r.dataDir,r.channel,{storeName:e}),a);return}if(r.sessionId||(I(`error: required option '-s, --session-id <id>' not specified`),process.exit(1)),i===`inspect`){xt(await g(r.dataDir,r.sessionId,{storeName:e}),a);return}if(i===`export`){St(await u(r.dataDir,r.sessionId,{storeName:e}),a);return}I(`Invalid sessions action: ${i}. Must be 'list', 'inspect', or 'export'`),process.exit(1)})}catch(e){I(`${i===`inspect`?`Error inspecting session`:i===`export`?`Error exporting session`:`Error listing sessions`}: ${e.message}`),process.exit(1)}})}function Ti(e){return C.join(e,`workspace`)}function Ei(){let e=process.env.AIMAX_PLUGINS_BUNDLED_DIR;return e&&e.trim()||void 0}function Di(e,t){let n=[];n.push(`backend: ${e.backend}`),n.push(`provider: ${e.provider}${e.model?` (${e.model})`:``}`);let r=typeof e.custom?.providerSource==`string`?e.custom.providerSource:void 0,i=typeof e.custom?.providerId==`string`?e.custom.providerId:void 0,a=typeof e.custom?.pluginId==`string`?e.custom.pluginId:void 0;r&&n.push(`provider_source: ${r}`),i&&n.push(`provider_id: ${i}`),a&&n.push(`plugin_id: ${a}`),typeof e.files==`number`&&n.push(`files: ${e.files}`),typeof e.chunks==`number`&&n.push(`chunks: ${e.chunks}`),typeof e.dirty==`boolean`&&n.push(`dirty: ${e.dirty}`),e.dbPath&&n.push(`db: ${e.dbPath}`),e.sources?.length&&n.push(`sources: ${e.sources.join(`, `)}`),t&&(e.fts&&(n.push(`fts: enabled=${e.fts.enabled} available=${e.fts.available}`),e.fts.error&&n.push(`fts_error: ${e.fts.error}`)),e.vector&&(n.push(`vector: enabled=${e.vector.enabled} available=${e.vector.available??`unknown`}`),e.vector.dims&&n.push(`vector_dims: ${e.vector.dims}`),e.vector.loadError&&n.push(`vector_error: ${e.vector.loadError}`)),e.cache&&n.push(`cache: enabled=${e.cache.enabled} entries=${e.cache.entries??0}`));let o=Array.isArray(e.custom?.cliWarnings)?e.custom.cliWarnings.filter(e=>typeof e==`string`&&e.length>0):[];for(let e of o)n.push(`warning: ${e}`);return n.join(`
|
|
12
|
+
`)}function Oi(e){let t=e.level===`error`?`plugin error`:`plugin warning`;return e.pluginId?`${t} (${e.pluginId}): ${e.message}`:`${t}: ${e.message}`}function ki(e){if(!e||e===`cli`)return`cli`;if(e===`cron`)return`cron`;throw Error(`Unsupported dream trigger: ${e}. Expected "cli" or "cron".`)}async function Ai(e){let t=[],n;try{n=await W(e.dataDir,e.pluginsConfig)}catch(e){t.push(`failed to load plugins config: ${e.message}`)}if(!e.shouldInitialize&&!n)return{warnings:t};try{let r=h({config:n,dataDir:e.dataDir,workspaceDir:Ti(e.dataDir),bundledDir:Ei()});return t.push(...r.diagnostics.map(Oi)),{pluginSystem:r,warnings:t}}catch(e){return t.push(`failed to initialize plugin system: ${e.message}`),{warnings:t}}}async function ji(e){let t=C.join(e.dataDir,`.aimax`),{pluginSystem:n,warnings:r}=await Ai({dataDir:e.dataDir,pluginsConfig:e.pluginsConfig,shouldInitialize:!!(e.requirePluginSystem||e.provider||e.providerPlugin)}),i=n?.normalizedConfig.slots.memory,a=e.providerPlugin?.trim()||(e.provider?void 0:i),o=se({providerId:e.provider,pluginId:a,dataDir:e.dataDir,memoryDir:t,includeSessions:e.includeSessions});return o.providerSource===`plugin`?{provider:o.provider,providerId:o.providerId,pluginId:o.pluginId,providerOrigin:`plugin`,warnings:r,pluginSystem:n}:((a||e.provider)&&r.push(`requested memory provider was not resolved; falling back to builtin provider`),{provider:o.provider,providerId:`builtin`,providerOrigin:`builtin`,warnings:r,pluginSystem:n})}function Mi(e,t,n){let r={...e.custom??{},providerSource:t.providerOrigin,providerId:t.providerId,pluginId:t.pluginId,cliWarnings:t.warnings},i={...e,custom:r};return n&&t.providerOrigin===`plugin`?i.custom={...r,note:`deep probe details are provider-defined for plugin memory providers`}:n&&(i.custom={...r,note:`deep probe is only supported by builtin provider`}),i}function Ni(e){let t=e.command(`memory`).description(`Manage semantic memory indexing and search`),n=e=>e.option(`--plugins-config <path>`,`Plugins config file path`);n(t.command(`status`)).description(`Show memory index status`).requiredOption(`-d, --data-dir <path>`,`Data directory path`).option(`--deep`,`Probe embedding/vector availability`).option(`--index`,`Run a refresh before reporting status`).option(`--include-sessions`,`Include session transcripts in indexing`).option(`--provider <id>`,`Memory provider id`).option(`--provider-plugin <id>`,`Memory provider plugin id`).option(`--verbose`,`Verbose output`).option(`--output <format>`,`Output format: text (default) or json`,`text`).option(`--encrypt-sessions`,`Enable gocryptfs-backed encryption for the .aimax data directory`).action(async e=>{let t=e.output===`json`?`json`:`text`;try{await U(e.dataDir,e,async()=>{let n=await ji({dataDir:e.dataDir,provider:e.provider,providerPlugin:e.providerPlugin,pluginsConfig:e.pluginsConfig,includeSessions:e.includeSessions});e.index&&n.provider.sync&&await n.provider.sync(`cli-status`);let r=Mi(n.provider.status(),n,e.deep);F(t===`json`?JSON.stringify(r,null,2):Di(r,e.deep))})}catch(e){I(`Error getting memory status: ${e.message}`),process.exit(1)}}),n(t.command(`index`)).description(`Reindex memory files`).requiredOption(`-d, --data-dir <path>`,`Data directory path`).option(`--include-sessions`,`Include session transcripts in indexing`).option(`--provider <id>`,`Memory provider id`).option(`--provider-plugin <id>`,`Memory provider plugin id`).option(`--rebuild`,`Force full rebuild from Markdown source`).option(`--verbose`,`Verbose output`).option(`--encrypt-sessions`,`Enable gocryptfs-backed encryption for the .aimax data directory`).action(async e=>{try{await U(e.dataDir,e,async()=>{let t=await ji({dataDir:e.dataDir,provider:e.provider,providerPlugin:e.providerPlugin,pluginsConfig:e.pluginsConfig,includeSessions:e.includeSessions}),n;if(t.provider.sync&&(await t.provider.sync(e.rebuild?`cli-rebuild`:`cli-index`),n=t.provider.status().custom?.lastRebuildSummary),t.warnings.length>0)for(let e of t.warnings)I(`Warning: ${e}`);e.verbose&&n&&F(JSON.stringify(n,null,2)),F(e.rebuild?`Memory index rebuilt.`:`Memory index refreshed.`)})}catch(e){I(`Error indexing memory: ${e.message}`),process.exit(1)}}),n(t.command(`search [query]`)).description(`Search semantic memory`).requiredOption(`-d, --data-dir <path>`,`Data directory path`).option(`--query <text>`,`Search query`).option(`--include-sessions`,`Include session transcripts in search`).option(`--provider <id>`,`Memory provider id`).option(`--provider-plugin <id>`,`Memory provider plugin id`).option(`--output <format>`,`Output format: text (default) or json`,`text`).option(`--encrypt-sessions`,`Enable gocryptfs-backed encryption for the .aimax data directory`).action(async(e,t)=>{let n=t.output===`json`?`json`:`text`,r=t.query?.trim()||e?.trim();r||(I(`Query is required: provide [query] or --query <text>`),process.exit(1));try{await U(t.dataDir,t,async()=>{let e=await(await ji({dataDir:t.dataDir,provider:t.provider,providerPlugin:t.providerPlugin,pluginsConfig:t.pluginsConfig,includeSessions:t.includeSessions})).provider.search(r);if(n===`json`){F(JSON.stringify(e,null,2));return}if(e.length===0){F(`No results found for: ${r}`);return}F(e.map(e=>{let t=`${e.path}:${e.startLine}-${e.endLine} (${e.score.toFixed(4)}) ${e.snippet}`;return e.citation?`${t}\n${e.citation}`:t}).join(`
|
|
13
|
+
`))})}catch(e){I(`Error searching memory: ${e.message}`),process.exit(1)}}),n(t.command(`dream`)).description(`Trigger Dream Gate host hook for memory plugins`).requiredOption(`-d, --data-dir <path>`,`Data directory path`).option(`--provider <id>`,`Memory provider id`).option(`--provider-plugin <id>`,`Memory provider plugin id`).option(`--trigger <mode>`,`Dream Gate trigger mode: cli (default) or cron`,`cli`).option(`--dry-run`,`Return hook results without plugin-side mutation`).option(`--output <format>`,`Output format: text (default) or json`,`text`).option(`--encrypt-sessions`,`Enable gocryptfs-backed encryption for the .aimax data directory`).action(async e=>{let t=e.output===`json`?`json`:`text`;try{await U(e.dataDir,e,async()=>{let n=ki(e.trigger),r=await ji({dataDir:e.dataDir,provider:e.provider,providerPlugin:e.providerPlugin,pluginsConfig:e.pluginsConfig,requirePluginSystem:!0}),i=r.pluginSystem?await r.pluginSystem.registry.hooks.dispatch(`dream_gate`,{dataDir:e.dataDir,memoryDir:C.join(e.dataDir,`.aimax`),providerId:r.providerId,pluginId:r.pluginId,trigger:n,dryRun:!!e.dryRun},{workspaceDir:Ti(e.dataDir)}):[],a={ok:!0,trigger:n,providerSource:r.providerOrigin,providerId:r.providerId,pluginId:r.pluginId,resultCount:i.length,results:i,warnings:r.warnings};if(t===`json`){F(JSON.stringify(a,null,2));return}F(`trigger: ${a.trigger}`),F(`provider_source: ${a.providerSource}`),F(`provider_id: ${a.providerId}`),a.pluginId&&F(`plugin_id: ${a.pluginId}`),F(`result_count: ${a.resultCount}`),a.results.length===0?F(`note: no dream_gate hook registered`):F(`results: ${JSON.stringify(a.results)}`);for(let e of a.warnings)F(`warning: ${e}`)})}catch(e){I(`Error running dream gate: ${e.message}`),process.exit(1)}})}function Pi(e){return`${e.match.accountId?`${e.match.channel}:${e.match.accountId}`:e.match.channel} -> ${e.agentId}`}function Fi(e){return async t=>{let n=await O(t),r=Le(n),i=Re(n);if(Ue(n),e.json){console.log(JSON.stringify({agents:r,bindings:i},null,2));return}console.log(`Agents:`);for(let e of r){let n=e.default?` (default)`:``,r=e.name&&e.name!==e.id?`${e.id}${n} (${e.name})`:`${e.id}${n}`;if(console.log(` - ${r}`),e.identity?.emoji||e.identity?.name){let t=[e.identity.emoji,e.identity.name].filter(Boolean).join(` `);console.log(` Identity: ${t}`)}let a=He(t,e.id);if(console.log(` Agent dir: ${a}`),e.model){let t=typeof e.model==`string`?e.model:e.model.primary;console.log(` Model: ${t}`)}let o=i.filter(t=>t.agentId===e.id);if(o.length>0){console.log(` Routing rules:`);for(let e of o)console.log(` - ${Pi(e)}`)}}}}function Ii(e,t){return async n=>{D(await O(n),ze(e))&&(console.error(`Agent "${e}" already exists.`),process.exit(1)),await Fe(n,{id:e,name:t.name,model:t.model,default:t.default})||(console.error(`Agent "${e}" already exists.`),process.exit(1));let r=He(n,e);console.log(`Agent "${e}" added successfully.`),console.log(` Agent dir: ${r}`)}}function Li(e){return async t=>{let n=D(await O(t),ze(e));n||(console.error(`Agent "${e}" not found.`),process.exit(1)),n.default===!0&&(console.error(`Cannot delete default agent "${e}".`),process.exit(1)),await Be(t,e)||(console.error(`Failed to delete agent "${e}".`),process.exit(1)),console.log(`Agent "${e}" deleted.`)}}function Ri(e){return async t=>{let n=await O(t),r=e.agent??Ue(n);D(n,r)||(console.error(`Agent "${r}" not found.`),process.exit(1)),(!e.bind||e.bind.length===0)&&(console.error(`Please specify --bind <channel>[:<account>]`),process.exit(1));for(let n of e.bind){let[e,...i]=n.split(`:`),a=i.join(`:`),o=[`H5`,`WEB`,`KLPA`,`TASK`,`CRON`,`EIP_ASSISTANT`];o.includes(e)||(console.error(`Invalid channel: ${e}`),console.error(`Valid channels: ${o.join(`, `)}`),process.exit(1)),await Ie(t,{agentId:r,match:{channel:e,accountId:a||void 0}}),console.log(`Binding added: ${n} -> ${r}`)}}}function zi(e){return async t=>{let n=await O(t),r=e.agent??Ue(n);if(D(n,r)||(console.error(`Agent "${r}" not found.`),process.exit(1)),e.all){let e=await Ve(t,r,`*`);console.log(`Removed ${e} binding(s) for agent "${r}".`)}else if(e.bind&&e.bind.length>0){let n=0;for(let i of e.bind){let[e,...a]=i.split(`:`),o=await Ve(t,r,e,a.join(`:`)||void 0);o>0?(console.log(`Binding removed: ${i} -> ${r}`),n+=o):console.log(`No binding found: ${i} -> ${r}`)}}else console.error(`Please specify --bind <channel>[:<account>] or --all`),process.exit(1)}}function Bi(e){return async t=>{let n=Re(await O(t));if(e.agent&&(n=n.filter(t=>t.agentId===e.agent)),e.json){console.log(JSON.stringify(n,null,2));return}if(n.length===0){console.log(`No bindings configured.`);return}console.log(`Routing bindings:`);for(let e of n)console.log(` ${Pi(e)}`)}}function Vi(e){return async t=>{let n=await O(t),r=e.agent??Ue(n);D(n,r)||(console.error(`Agent "${r}" not found.`),process.exit(1)),await We(t,r,{name:e.name,emoji:e.emoji,avatar:e.avatar})||(console.error(`Failed to update identity for agent "${r}".`),process.exit(1)),console.log(`Identity updated for agent "${r}".`)}}function Hi(e,t){let n=e.command(`agents`).description(`Manage agents`),r=e=>e.option(`--encrypt-sessions`,`Enable gocryptfs-backed encryption for the .aimax data directory`);r(n.command(`list`).description(`List all configured agents`).option(`-j, --json`,`Output as JSON`).option(`-b, --bindings`,`Show detailed binding rules`)).action(async e=>{let n=t();await U(n,e,async()=>{await Fi(e)(n)})}),r(n.command(`add <id>`).description(`Add a new agent`).option(`-n, --name <name>`,`Display name`).option(`-m, --model <model>`,`Model identifier`).option(`--default`,`Mark as default agent`)).action(async(e,n)=>{let r=t();await U(r,n,async()=>{await Ii(e,n)(r)})}),r(n.command(`delete <id>`).description(`Delete an agent`)).action(async(e,n)=>{let r=t();await U(r,n,async()=>{await Li(e)(r)})}),r(n.command(`bind`).description(`Bind a channel to an agent`).option(`-a, --agent <id>`,`Target agent ID`).option(`-b, --bind <channel...>`,`Channel binding (e.g., WEB, KLPA:ops)`)).action(async e=>{let n=t();await U(n,e,async()=>{await Ri(e)(n)})}),r(n.command(`unbind`).description(`Unbind a channel from an agent`).option(`-a, --agent <id>`,`Target agent ID`).option(`-b, --bind <channel...>`,`Channel binding to remove`).option(`--all`,`Remove all bindings for the agent`)).action(async e=>{let n=t();await U(n,e,async()=>{await zi(e)(n)})}),r(n.command(`bindings`).description(`List routing bindings`).option(`-a, --agent <id>`,`Filter by agent ID`).option(`-j, --json`,`Output as JSON`)).action(async e=>{let n=t();await U(n,e,async()=>{await Bi(e)(n)})}),r(n.command(`set-identity`).description(`Set agent identity`).option(`-a, --agent <id>`,`Target agent ID`).option(`-n, --name <name>`,`Agent name`).option(`-e, --emoji <emoji>`,`Agent emoji`).option(`--avatar <path>`,`Avatar path`)).action(async e=>{let n=t();await U(n,e,async()=>{await Vi(e)(n)})})}function Y(e){return C.join(e,`workspace`)}function X(){let e=process.env.AIMAX_PLUGINS_BUNDLED_DIR;return e&&e.trim()||void 0}function Ui(e){if(e.length===0){F(`No plugins discovered.`);return}for(let t of e){let e=t.status.padEnd(8,` `);F(`${t.id} ${e} ${t.origin} ${t.source}`)}}function Wi(e){F(`id: ${e.id}`),F(`status: ${e.status}`),F(`origin: ${e.origin}`),F(`source: ${e.source}`),F(`enabled: ${e.enabled}`),e.error&&F(`error: ${e.error}`),F(`tools: ${e.toolCount}`),F(`hooks: ${e.hookCount}`),e.skills.length>0&&F(`skills: ${e.skills.join(`, `)}`)}function Gi(e){return Array.from(new Set((e??[]).map(e=>e.trim()).filter(Boolean)))}function Ki(e){if(e.length===0){F(`LLM allowlist is empty.`);return}for(let t of e)F(t)}function qi(e,t){let n=e.command(`plugins`).description(`Manage AIMax plugins`),r=e=>e.option(`--plugins-config <path>`,`Plugins config file path`),i=e=>e.option(`--encrypt-sessions`,`Enable gocryptfs-backed encryption for the .aimax data directory`);i(r(n.command(`list`))).description(`List discovered plugins`).option(`-d, --data-dir <path>`,`Data directory path`).action(async e=>{let n=e.dataDir??t();await U(n,e,async()=>{Ui(h({config:await W(n,e.pluginsConfig),dataDir:n,workspaceDir:Y(n),bundledDir:X()}).registry.plugins)})}),i(r(n.command(`info`))).description(`Show plugin details`).argument(`<id>`,`Plugin id`).option(`-d, --data-dir <path>`,`Data directory path`).action(async(e,n)=>{let r=n.dataDir??t();await U(r,n,async()=>{let t=h({config:await W(r,n.pluginsConfig),dataDir:r,workspaceDir:Y(r),bundledDir:X()}).registry.plugins.find(t=>t.id===e);t||(I(`Plugin not found: ${e}`),process.exit(1)),Wi(t)})}),i(r(n.command(`enable`))).description(`Enable a plugin`).argument(`<id>`,`Plugin id`).option(`-d, --data-dir <path>`,`Data directory path`).action(async(e,n)=>{let r=n.dataDir??t();await U(r,n,async()=>{let t=await W(r,n.pluginsConfig)??{},i=ae(t);h({config:t,dataDir:r,workspaceDir:Y(r),bundledDir:X()}).registry.plugins.some(t=>t.id===e)||(I(`Plugin not found: ${e}`),process.exit(1)),await G(r,{...t,entries:{...t.entries,[e]:{...t.entries?.[e]??{},enabled:!0}}},n.pluginsConfig),F(`Enabled ${e}`),i.allow.length>0&&!i.allow.includes(e)&&F(`Note: plugins.allow is set; add this plugin id to allowlist if needed.`)})}),i(r(n.command(`disable`))).description(`Disable a plugin`).argument(`<id>`,`Plugin id`).option(`-d, --data-dir <path>`,`Data directory path`).action(async(e,n)=>{let r=n.dataDir??t();await U(r,n,async()=>{let t=await W(r,n.pluginsConfig)??{};h({config:t,dataDir:r,workspaceDir:Y(r),bundledDir:X()}).registry.plugins.some(t=>t.id===e)||(I(`Plugin not found: ${e}`),process.exit(1)),await G(r,{...t,entries:{...t.entries,[e]:{...t.entries?.[e]??{},enabled:!1}}},n.pluginsConfig),F(`Disabled ${e}`)})}),i(r(n.command(`doctor`))).description(`Validate plugin configuration`).option(`-d, --data-dir <path>`,`Data directory path`).action(async e=>{let n=e.dataDir??t();await U(n,e,async()=>{let t=h({config:await W(n,e.pluginsConfig),dataDir:n,workspaceDir:Y(n),bundledDir:X()});if(t.diagnostics.length===0){F(`No plugin issues detected.`);return}for(let e of t.diagnostics)F(`${e.level===`error`?`ERROR`:`WARN`}${e.pluginId?` ${e.pluginId}`:``}: ${e.message}`);t.diagnostics.some(e=>e.level===`error`)&&process.exit(1)})});let a=n.command(`llm-allow`).description(`Manage plugin LLM allowlist`);i(r(a.command(`list`))).description(`List LLM allowlist entries`).option(`-d, --data-dir <path>`,`Data directory path`).action(async e=>{let n=e.dataDir??t();await U(n,e,async()=>{Ki(Gi((await W(n,e.pluginsConfig))?.llmAllowlist))})}),i(r(a.command(`add`))).description(`Add entries to the LLM allowlist (plugin id or tool name)`).argument(`<entry...>`,`Plugin id or tool name`).option(`-d, --data-dir <path>`,`Data directory path`).action(async(e,n)=>{let r=n.dataDir??t();await U(r,n,async()=>{let t=await W(r,n.pluginsConfig)??{},i=Gi([...t.llmAllowlist??[],...e]);await G(r,{...t,llmAllowlist:i},n.pluginsConfig),F(`LLM allowlist updated (${i.length} entries).`)})}),i(r(a.command(`remove`))).description(`Remove entries from the LLM allowlist`).argument(`<entry...>`,`Plugin id or tool name`).option(`-d, --data-dir <path>`,`Data directory path`).action(async(e,n)=>{let r=n.dataDir??t();await U(r,n,async()=>{let t=await W(r,n.pluginsConfig)??{},i=new Set(e.map(e=>e.trim()).filter(Boolean)),a=Gi(t.llmAllowlist).filter(e=>!i.has(e));await G(r,{...t,llmAllowlist:a},n.pluginsConfig),F(`LLM allowlist updated (${a.length} entries).`)})}),i(r(a.command(`clear`))).description(`Clear the LLM allowlist`).option(`-d, --data-dir <path>`,`Data directory path`).action(async e=>{let n=e.dataDir??t();await U(n,e,async()=>{await G(n,{...await W(n,e.pluginsConfig)??{},llmAllowlist:[]},e.pluginsConfig),F(`LLM allowlist cleared.`)})})}function Ji(e){e.command(`commands`).description(`List available slash commands for a data directory`).requiredOption(`-d, --data-dir <path>`,`Data directory path`).option(`--output <format>`,`Output format: text (default) or json`,`text`).option(`--encrypt-sessions`,`Enable gocryptfs-backed encryption for the .aimax data directory`).action(async e=>{let t=e.output===`json`?`json`:`text`;try{await U(e.dataDir,e,async()=>{let n=_(await re(e.dataDir,[]));if(t===`json`){F(JSON.stringify(n,null,2));return}F(`Commands`),F(` builtin: ${n.builtin.map(e=>e.name).join(` | `)}`),n.skillCommands.length>0?F(` skills: ${n.skillCommands.map(e=>e.name).join(` | `)}`):F(` skills: (none)`)})}catch(e){I(`Error listing commands: ${e.message}`),process.exit(1)}})}function Z(e){let t=e.dataDir??process.env.AIMAX_DATA_DIR;if(!t)throw Error(`Data directory must be specified via --data-dir option or AIMAX_DATA_DIR environment variable`);return t}function Q(e){if(!e.sessionId)throw Error(`Session ID is required (--session-id or -s)`);return e.sessionId}function $(e){return e?y(e):void 0}async function Yi(e){let t={storeName:e.sessionStoreName},n=e.objective.trim(),r=await b(e.dataDir,e.sessionId,t);if(!r||(await oe(e.dataDir,e.sessionId,r,t)).trim()!==n)return he(e.dataDir,e.sessionId,{goalId:Ke(),objective:n,status:`active`,tokenBudget:e.tokenBudget??null,tokensUsed:0,timeUsedSeconds:0},{...t,eventSource:`cli`});if(r.status===`complete`)return r;let i={};return r.status===`paused`&&(i.status=`active`),e.tokenBudget!==void 0&&e.tokenBudget!==r.tokenBudget&&(i.tokenBudget=e.tokenBudget),Object.keys(i).length===0?r:await me(e.dataDir,e.sessionId,i,{...t,eventSource:`cli`})}async function Xi(e,t){let n=Z(t),r=Q(t),i=$(t.sessionStore),a=e.trim();a||(I(`error: objective cannot be empty`),process.exit(1));let o=t.tokenBudget===void 0||t.tokenBudget===`0`||t.tokenBudget===``?null:Number(t.tokenBudget);o!==null&&(Number.isNaN(o)||o<=0)&&(I(`error: --token-budget must be a positive integer, or 0 for unlimited`),process.exit(1));let s=await Yi({dataDir:n,sessionId:r,sessionStoreName:i,objective:a,tokenBudget:o});F(JSON.stringify({goal:s},null,2))}async function Zi(e){let t=Z(e),n=Q(e),r=$(e.sessionStore),i=await b(t,n,{storeName:r});if(!i){F(JSON.stringify({goal:null},null,2));return}let a=await oe(t,n,i,{storeName:r});F(JSON.stringify({goal:{...i,objective:a}},null,2))}async function Qi(e){let t=Z(e),n=Q(e),r=$(e.sessionStore),i=await b(t,n,{storeName:r});i||(I(`error: no goal exists for this session`),process.exit(1)),i.status===`complete`&&(I(`error: cannot pause a completed goal`),process.exit(1));let a=await me(t,n,{status:`paused`},{storeName:r,eventSource:`cli`});F(JSON.stringify({goal:a},null,2))}async function $i(e){let t=Z(e),n=Q(e),r=$(e.sessionStore),i=await b(t,n,{storeName:r});if(i||(I(`error: no goal exists for this session`),process.exit(1)),i.status===`complete`&&(I(`error: cannot resume a completed goal`),process.exit(1)),i.status===`budget_limited`&&(I(`error: cannot resume a budget-limited goal; clear or replace it instead`),process.exit(1)),i.status===`active`){F(JSON.stringify({goal:i},null,2));return}let a=await me(t,n,{status:`active`},{storeName:r,eventSource:`cli`});F(JSON.stringify({goal:a},null,2))}async function ea(e){let t=await c(Z(e),Q(e),{storeName:$(e.sessionStore),eventSource:`cli`});F(JSON.stringify({cleared:t},null,2))}function ta(e){let t=e.command(`goal`).description(`Manage thread goals for a session`).addHelpText(`after`,a());t.command(`set <objective>`).description(`Set or replace the thread goal (creates new goalId)`).option(`-d, --data-dir <path>`,`Data directory path (overrides AIMAX_DATA_DIR)`).requiredOption(`-s, --session-id <id>`,`Session ID`).option(`--session-store <name>`,`Session store directory under .aimax (default: sessions)`).option(`--token-budget <n>`,`Optional token budget (positive integer, or 0 for unlimited)`).action(async(e,t)=>{try{await Xi(e,t)}catch(e){I(`error: ${e.message}`),process.exit(1)}}),t.command(`get`).description(`Get the current goal as JSON`).option(`-d, --data-dir <path>`,`Data directory path (overrides AIMAX_DATA_DIR)`).requiredOption(`-s, --session-id <id>`,`Session ID`).option(`--session-store <name>`,`Session store directory under .aimax (default: sessions)`).action(async e=>{try{await Zi(e)}catch(e){I(`error: ${e.message}`),process.exit(1)}}),t.command(`pause`).description(`Pause the current goal`).option(`-d, --data-dir <path>`,`Data directory path (overrides AIMAX_DATA_DIR)`).requiredOption(`-s, --session-id <id>`,`Session ID`).option(`--session-store <name>`,`Session store directory under .aimax (default: sessions)`).action(async e=>{try{await Qi(e)}catch(e){I(`error: ${e.message}`),process.exit(1)}}),t.command(`resume`).description(`Resume a paused goal`).option(`-d, --data-dir <path>`,`Data directory path (overrides AIMAX_DATA_DIR)`).requiredOption(`-s, --session-id <id>`,`Session ID`).option(`--session-store <name>`,`Session store directory under .aimax (default: sessions)`).action(async e=>{try{await $i(e)}catch(e){I(`error: ${e.message}`),process.exit(1)}}),t.command(`clear`).description(`Clear the current goal`).option(`-d, --data-dir <path>`,`Data directory path (overrides AIMAX_DATA_DIR)`).requiredOption(`-s, --session-id <id>`,`Session ID`).option(`--session-store <name>`,`Session store directory under .aimax (default: sessions)`).action(async e=>{try{await ea(e)}catch(e){I(`error: ${e.message}`),process.exit(1)}})}const na=[`progress`,`error`,`hitl`];function ra(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 ia(e){if(!e?.trim())return new Set(na);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(na)}function aa(e){return e?y(e):void 0}function oa(e){let t=[];return e.callbackUrl&&t.push(new Pn(e.callbackUrl)),e.streamUrl&&t.push(new Un(e.streamUrl,ia(e.streamEvents),e.streamAuthToken)),new Nn(t)}async function sa(e){let t=ra(e);await U(t,e,async()=>{N(t,{messageId:e.messageId});let n=new ft(`cancel command`),r=e.channel??`WEB`,i=e.output===`json`?`json`:`text`,a=oa(e),o=aa(e.sessionStore);try{let s=await ee(t,e.sessionId,{storeName:o});if(!s)throw Error(`No pending HITL request found for session "${e.sessionId}"`);let c=e.requestId??s.request.requestId;if(s.request.requestId!==c)throw Error(`Request ID mismatch: pending is "${s.request.requestId}", got "${c}"`);if(!(await ce({dataDir:t,sessionStoreName:o,sessionId:e.sessionId,requestId:c,resolution:{requestId:c,sessionId:e.sessionId,action:`cancel`,submittedAt:new Date().toISOString(),submittedBy:{channel:r}}})).state)throw Error(`Failed to cancel HITL request`);let l={type:`hitl_cancelled`,sessionId:e.sessionId,requestId:c,reason:e.reason??`cancelled by operator`};i===`text`&&L(l),await a.send({type:`progress`,sessionId:e.sessionId,channel:r,messageId:e.messageId,event:l}),n.end(),process.exit(0)}catch(t){let i=t;await a.send({type:`error`,sessionId:e.sessionId,channel:r,messageId:e.messageId,message:i.message}),P.error(`cancel command error: ${i.message}`),I(`Fatal: ${i.message}`),n.end(),process.exit(1)}finally{await a.close()}})}function ca(e){e.command(`cancel`).description(`Cancel a pending HITL request`).requiredOption(`-d, --data-dir <path>`,`Data directory path`).requiredOption(`-s, --session-id <id>`,`Session ID containing the pending HITL request`).option(`--session-store <name>`,`Session store directory under .aimax (default: sessions)`).option(`--request-id <id>`,`HITL request ID to cancel`).option(`--reason <text>`,`Human-readable cancel reason`).option(`-c, --channel <channel>`,`Channel type (default: WEB)`,`WEB`).option(`--callback-url <url>`,`HTTP callback URL for progress events`).option(`--stream-url <url>`,`WebSocket URL for streaming text events`).option(`--stream-auth-token <token>`,`Auth token for WebSocket streaming`).option(`--stream-events <list>`,`Comma-separated stream events`).option(`--message-id <id>`,`Message ID for correlating events`).option(`--output <format>`,`Output format: text (default) or json`,`text`).option(`--encrypt-sessions`,`Enable gocryptfs-backed encryption for the .aimax data directory`).action(async e=>{await sa(e)})}function la(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 ua(e){return e.query?.trim()||void 0}function da(e){if(!e)return;let t=Number(e);if(!Number.isFinite(t)||t<=0)throw Error(`--timeout must be a positive number of milliseconds`);return t}function fa(e){if(!e)return;let t=Number(e);if(!Number.isInteger(t)||t<=0)throw Error(`--max-tokens must be a positive integer`);return t}async function pa(e){if(e.filePath){if(!C.isAbsolute(e.filePath))throw Error(`--file-path must be an absolute path`);try{await E.access(e.filePath)}catch(e){throw Error(`Failed to access --file-path: ${e.message}`)}return{source:`file`,filePath:e.filePath}}let t=e.content;if(!t||!t.trim())throw Error(`Either --file-path or --content must be provided`);return{source:`content`,content:t}}async function ma(e){let t=null;try{let n=la(e);N(n,{messageId:e.messageId}),t=new ft(`summarize command`);let r=ua(e),i=await pa(e),a=fn({apiFormat:e.apiFormat,baseUrl:e.baseUrl,apiKey:e.apiKey,model:e.model,contextWindow:2e5}),o=da(e.timeout),s=fa(e.maxTokens);P.info(`summarize command started`,{dataDir:n,source:i.source,filePath:i.source===`file`?i.filePath:void 0,queryLength:r?.length,contentLength:i.source===`content`?i.content.length:void 0,timeoutMs:o,maxTokens:s});let c=await de({dataDir:n,channel:`WEB`,messageId:e.messageId,message:ha(i,r),llm:{...a,maxTokens:s},timeoutMs:o});F(c.text.trim()),P.info(`summarize command succeeded`,{source:i.source,summaryLength:c.text.length,durationMs:c.durationMs}),t.end()}catch(e){P.error(`summarize command error: ${e.message}`),I(`Fatal: ${e.message}`),t?.end(),process.exit(1)}}function ha(e,t){return e.source===`file`?[t?`Summarize exactly one file for the query below.`:`Summarize exactly one file.`,`Read only the absolute file path provided here. Do not search, browse, read other files, execute commands, modify files, or perform any other processing.`,`Return only the summary text.`,``,...t?[`Query:\n${t}`,``]:[],`Input source: file`,`File path: ${e.filePath}`].join(`
|
|
14
|
+
`):[t?`Summarize the provided content for the query below.`:`Summarize the provided content.`,t?`Use only the provided content and query. Do not search, browse, read files, execute commands, modify files, or perform any other processing.`:`Use only the provided content. Do not search, browse, read files, execute commands, modify files, or perform any other processing.`,`Return only the summary text.`,``,...t?[`Query:\n${t}`,``]:[],`Input source: content`,`Source content:`,`<source>`,e.content,`</source>`].join(`
|
|
15
|
+
`)}function ga(e){e.command(`summarize`).description(`Summarize one absolute file path or inline content`).option(`--file-path <path>`,`Absolute file path to summarize`).option(`--content <text>`,`Inline text content to summarize when --file-path is not provided`).option(`--query <text>`,`Optional search target or current description to focus the summary`).option(`-d, --data-dir <path>`,`Data directory path (overrides AIMAX_DATA_DIR)`).option(`--base-url <url>`,`LLM API base URL (overrides AIMAX_BASE_URL)`).option(`--api-format <format>`,`LLM API format: openai-completions or anthropic-messages (overrides AIMAX_API_FORMAT)`).option(`--api-key <key>`,`LLM API key (overrides AIMAX_API_KEY)`).option(`--model <name>`,`LLM model name (overrides AIMAX_MODEL)`).option(`--timeout <ms>`,`Execution timeout in milliseconds`).option(`--max-tokens <number>`,`Maximum number of tokens for model output`).option(`--message-id <id>`,`Message ID for log correlation`).action(async e=>{await ma(e)})}const _a={accent:`#8abeb7`,border:`#5f87ff`,borderAccent:`#00d7ff`,borderMuted:`#505050`,success:`#b5bd68`,error:`#cc6666`,warning:`#ffff00`,muted:`#808080`,dim:`#666666`,text:`#d4d4d4`,thinkingText:`#808080`,selectedBg:`#3a3a4a`,userMessageBg:`#343541`,userMessageText:`#d4d4d4`,customMessageBg:`#2d2838`,customMessageText:`#d4d4d4`,customMessageLabel:`#9575cd`,toolPendingBg:`#282832`,toolSuccessBg:`#283228`,toolErrorBg:`#3c2828`,toolTitle:`#d4d4d4`,toolOutput:`#808080`,mdHeading:`#f0c674`,mdLink:`#81a2be`,mdLinkUrl:`#666666`,mdCode:`#8abeb7`,mdCodeBlock:`#b5bd68`,mdCodeBlockBorder:`#808080`,mdQuote:`#808080`,mdQuoteBorder:`#808080`,mdHr:`#808080`,mdListBullet:`#8abeb7`,toolDiffAdded:`#b5bd68`,toolDiffRemoved:`#cc6666`,toolDiffContext:`#808080`,syntaxComment:`#6A9955`,syntaxKeyword:`#569CD6`,syntaxFunction:`#DCDCAA`,syntaxVariable:`#9CDCFE`,syntaxString:`#CE9178`,syntaxNumber:`#B5CEA8`,syntaxType:`#4EC9B0`,syntaxOperator:`#D4D4D4`,syntaxPunctuation:`#D4D4D4`,thinkingOff:`#505050`,thinkingMinimal:`#6e6e6e`,thinkingLow:`#5f87af`,thinkingMedium:`#81a2be`,thinkingHigh:`#b294bb`,thinkingXhigh:`#d183e8`,bashMode:`#b5bd68`},va=`#18181e`,ya=`#1e1e24`,ba=`#3c3728`;function xa(e){if(!e||typeof e!=`object`)return!1;let t=e.role;return t===`user`||t===`assistant`||t===`tool_result`||t===`compaction`}function Sa(e){return!e||typeof e!=`object`?!1:typeof e.type==`string`}function Ca(e){return{type:`text`,text:e}}function wa(e){return{type:`thinking`,thinking:e}}function Ta(e,t){let n=e.timestamp,r=typeof n==`string`&&n?n:e.content;return`${e.role}\0${r}\0${t}`}function Ea(e,t,n){let r=Ta(e,t);for(let e=0;e<100;e++){let t=Ge(`sha256`).update(`${r}\0${e}`).digest(`hex`).slice(0,8);if(!n.has(t))return n.add(t),t}let i=Ge(`sha256`).update(`${r}\0fallback`).digest(`hex`);return n.add(i),i}function Da(e,t){let n=new Set,r=null,i=[],a={type:`session`,version:3,id:t?.sessionId??Ke(),timestamp:e.find(e=>e.timestamp)?.timestamp??new Date().toISOString(),cwd:t?.cwd??process.cwd()};for(let[t,a]of e.entries()){let e=Ea(a,t,n),o={id:e,parentId:r,timestamp:a.timestamp};if(a.role===`user`)i.push({type:`message`,...o,message:{role:`user`,content:[Ca(a.content)]}});else if(a.role===`assistant`){let e=[];a.thinking?.trim()&&e.push(wa(a.thinking.trim())),a.content.trim()&&e.push(Ca(a.content));for(let t of a.toolCalls??[])e.push({type:`toolCall`,id:t.id,name:t.name,arguments:t.arguments});a.errorMessage&&e.push(Ca(a.errorMessage)),i.push({type:`message`,...o,message:{role:`assistant`,content:e,...a.stopReason?{stopReason:a.stopReason}:{}}})}else if(a.role===`tool_result`){let e=a.content;a.toolResultRef?.preview&&!e.includes(a.toolResultRef.preview)&&(e=`${e}\n\nPreview:\n${a.toolResultRef.preview}`),a.toolResultRef?.storagePath&&(e=`${e}\n\n[Full output: ${a.toolResultRef.storagePath}]`),i.push({type:`message`,...o,message:{role:`toolResult`,toolCallId:a.toolCallId,toolName:a.toolName,content:[Ca(e)],isError:a.isError}})}else a.role===`compaction`&&i.push({type:`compaction`,...o,summary:a.content,firstKeptEntryId:r??e,tokensBefore:0});r=e}return{header:a,entries:i,leafId:r}}function Oa(e,t){let n=e.trim().split(`
|
|
16
|
+
`).filter(e=>e.trim()),r=[],i=0;for(let e of n)try{r.push(JSON.parse(e))}catch{i+=1}if(r.length===0)return{data:Da([],t),skippedLines:i};let a=r[0];if(Sa(a)&&a.type===`session`){let e=a,t=r.slice(1).filter(Sa);return{data:{header:e,entries:t,leafId:t.length>0?t[t.length-1].id:null},skippedLines:i}}if(r.every(Sa)){let e=r;return{data:{header:{type:`session`,version:3,id:t?.sessionId??Ke(),timestamp:e[0]?.timestamp??new Date().toISOString(),cwd:t?.cwd??process.cwd()},entries:e,leafId:e.length>0?e[e.length-1].id:null},skippedLines:i}}return{data:Da(r.filter(xa),t),skippedLines:i}}function ka(e){let t=e;for(;t!==Ee(t);){if(S(w(t,`package.json`)))return t;t=Ee(t)}throw Error(`Could not find @gencode/cli package root`)}function Aa(){let e=ka(Ee(Pe(import.meta.url))),t=[w(e,`dist`,`export-html`),w(e,`src`,`export-html`)];for(let e of t)if(S(w(e,`template.html`)))return e;throw Error(`export-html template directory not found under ${e}`)}function ja(e){let t=C.resolve(e),n=`${C.sep}.aimax${C.sep}`,r=t.indexOf(n);if(!(r<0))return t.slice(0,r)}function Ma(e){let t=C.dirname(C.resolve(e));return C.basename(t)}async function Na(e){let t=e.dataDir??(e.transcriptPath?ja(e.transcriptPath):void 0),n=e.sessionId??(e.transcriptPath?Ma(e.transcriptPath):void 0);return!t||!n?{}:ne(t,n,e.sessionPathOptions)}const Pa=new Map;function Fa(e){let t=Pa.get(e);if(t!==void 0)return t;let n=Se(w(Aa(),e),`utf-8`);return Pa.set(e,n),n}function Ia(){let e=[];for(let[t,n]of Object.entries(_a))e.push(`--${t}: ${n};`);return e.push(`--exportPageBg: ${va};`),e.push(`--exportCardBg: ${ya};`),e.push(`--exportInfoBg: ${ba};`),e.join(`
|
|
17
|
+
`)}function La(e){return e.replace(/[&<>"']/g,e=>{switch(e){case`&`:return`&`;case`<`:return`<`;case`>`:return`>`;case`"`:return`"`;case`'`:return`'`;default:return e}})}function Ra(e){let t=Fa(`template.html`),n=Fa(`template.css`),r=Fa(`template.js`),i=Buffer.from(JSON.stringify(e)).toString(`base64`),a=n.replace(`{{THEME_VARS}}`,Ia()).replace(`{{BODY_BG}}`,va).replace(`{{CONTAINER_BG}}`,ya).replace(`{{INFO_BG}}`,ba);return t.replace(`{{CSS}}`,a).replace(`{{JS}}`,r).replace(`{{SESSION_DATA}}`,i)}function za(e,t){return t||`aimax-session-${Te(e,`.jsonl`)}.html`}function Ba(e,t){return`Skipped ${t} malformed JSONL line(s) while exporting ${e}`}function Va(e){for(let t of e)console.warn(t)}function Ha(e){return e.replace(/\\/g,`/`)}function Ua(e){return e.replace(/[|\\{}()[\]^$+?.]/g,`\\$&`)}function Wa(e){let t=Ha(e),n=`^`;for(let e=0;e<t.length;e+=1){let r=t[e],i=t[e+1];if(r===`*`){i===`*`?t[e+2]===`/`?(n+=`(?:.*\\/)?`,e+=2):(n+=`.*`,e+=1):n+=`[^/]*`;continue}if(r===`?`){n+=`[^/]`;continue}n+=Ua(r)}return n+=`$`,new RegExp(n)}function Ga(e){return/[*?[]/.test(e)}function Ka(e,t){let n=Ha(De(e)?T(e):T(t,e)).split(`/`),r=[];for(let e of n){if(Ga(e))break;r.push(e)}return T(r.join(`/`)||`/`)}async function qa(e){let t;try{t=await E.readdir(e,{withFileTypes:!0})}catch(e){let t=e.code;if(t===`ENOENT`||t===`ENOTDIR`)return[];throw e}let n=[];for(let r of t){let t=w(e,r.name);if(r.isDirectory()){n.push(...await qa(t));continue}r.isFile()&&n.push(t)}return n}async function Ja(e,t,n){let r=[];for await(let i of e(t,{cwd:n}))r.push(i);return r}async function Ya(e,t){let n=T(t),r=De(e),i=Wa(Ha(r?T(e):e));return(await qa(Ka(e,n))).map(e=>({file:e,candidate:Ha(r?T(e):Oe(n,e))})).filter(({candidate:e})=>i.test(e)).map(({file:e})=>r?T(e):Ha(Oe(n,e)))}async function Xa(e,t){let n=E.glob;return typeof n==`function`?Ja(n,e,t):Ya(e,t)}async function Za(e,t){if(t.options?.includeSnapshots===!1)return e;let n=await Na({dataDir:t.options?.dataDir,sessionId:t.options?.sessionId??e.header.id,transcriptPath:t.inputLabel,sessionPathOptions:t.options?.sessionPathOptions});return n.tools?.length?{...e,tools:n.tools}:e}async function Qa(e,t,n){let r=Oa(e,{sessionId:n?.sessionId,cwd:n?.cwd}),i=r.skippedLines>0?[Ba(t,r.skippedLines)]:[],a=r.data;a=await Za(a,{inputLabel:t,options:n});let o=Ra(a),s=za(t,n?.outputPath);return we(s,o,`utf8`),{outputPath:s,warnings:i}}async function $a(e,t){if(!S(e))throw Error(`File not found: ${e}`);return Qa(Se(e,`utf-8`),e,t)}async function eo(e,t){let n=await $a(e,t);return Va(n.warnings),n.outputPath}async function to(e,t,n){let r=pe(e,t,n);if(!S(r))throw Error(`Transcript not found: ${r}`);if((await ie(e,t,n)).length===0&&!Se(r,`utf-8`).trim())throw Error(`Nothing to export yet - transcript is empty`);let i=Se(r,`utf-8`),{outputPath:a,sessionId:o,cwd:s,dataDir:c,includeSnapshots:l,...u}=n??{};return Qa(i,r,{outputPath:n?.outputPath,sessionId:t,cwd:n?.cwd,dataDir:e,sessionPathOptions:u,includeSnapshots:n?.includeSnapshots})}async function no(e,t,n){let r=await to(e,t,n);return Va(r.warnings),r.outputPath}function ro(e,t){let n=t.map(t=>{let n=S(w(e,t.fileName))?Ce(w(e,t.fileName)):void 0,r=n?`${Math.round(n.size/1024)} KB`:``,i=t.sourcePath?`<span class="muted">${La(t.sourcePath)}</span>`:``;return`<tr><td><a href="${La(t.fileName)}">${La(t.sessionId)}</a></td><td>${r}</td><td>${i}</td></tr>`}).join(`
|
|
18
|
+
`),r=`<!DOCTYPE html>
|
|
19
|
+
<html lang="zh-CN">
|
|
20
|
+
<head>
|
|
21
|
+
<meta charset="UTF-8">
|
|
22
|
+
<title>AIMax Session Exports</title>
|
|
23
|
+
<style>
|
|
24
|
+
body { font-family: system-ui, sans-serif; margin: 2rem; background: #18181e; color: #d4d4d4; }
|
|
25
|
+
table { border-collapse: collapse; width: 100%; }
|
|
26
|
+
th, td { text-align: left; padding: 0.5rem 0.75rem; border-bottom: 1px solid #333; }
|
|
27
|
+
a { color: #81a2be; }
|
|
28
|
+
.muted { color: #808080; font-size: 0.85em; }
|
|
29
|
+
</style>
|
|
30
|
+
</head>
|
|
31
|
+
<body>
|
|
32
|
+
<h1>AIMax Session Exports (${t.length})</h1>
|
|
33
|
+
<table>
|
|
34
|
+
<thead><tr><th>Session</th><th>Size</th><th>Source</th></tr></thead>
|
|
35
|
+
<tbody>
|
|
36
|
+
${n}
|
|
37
|
+
</tbody>
|
|
38
|
+
</table>
|
|
39
|
+
</body>
|
|
40
|
+
</html>`,i=w(e,`index.html`);return we(i,r,`utf8`),i}async function io(e,t,n){xe(t,{recursive:!0});let r=fe(e,n),i=[],a=[],o=[],s=[],c;try{c=await E.readdir(r)}catch(e){throw e.code===`ENOENT`?Error(`Sessions directory not found: ${r}`):e}for(let r of c.sort()){let c=pe(e,r,n);if(!S(c)){a.push({sessionId:r,reason:`no transcript.jsonl`});continue}try{let a=w(t,`${r}.html`),l=await to(e,r,{...n,outputPath:a});o.push(...l.warnings),i.push({sessionId:r,path:l.outputPath}),s.push({sessionId:r,fileName:`${r}.html`,sourcePath:c})}catch(e){a.push({sessionId:r,reason:e.message})}}let l;return n?.writeIndex!==!1&&s.length>0&&(l=ro(t,s)),{exported:i,skipped:a,warnings:o,indexPath:l}}async function ao(e,t,n){xe(t,{recursive:!0});let r=[],i=[],a=[],o=[],s=[];if(s.push(...await Xa(e,process.cwd())),s.sort(),s.length===0)throw Error(`No files matched glob: ${e}`);for(let e of s){let n=T(e),s=Te(Ee(n));if(!S(n)){i.push({sessionId:s,reason:`file missing`});continue}try{let e=await $a(n,{outputPath:w(t,`${s}.html`),sessionId:s,dataDir:ja(n)});a.push(...e.warnings),r.push({sessionId:s,path:e.outputPath}),o.push({sessionId:s,fileName:`${s}.html`,sourcePath:n})}catch(e){i.push({sessionId:s,reason:e.message})}}let c;return n?.writeIndex!==!1&&o.length>0&&(c=ro(t,o)),{exported:r,skipped:i,warnings:a,indexPath:c}}function oo(e){e.command(`export-html`).description(`Export transcript.jsonl to standalone HTML files for browsing`).argument(`[transcript]`,`Path to transcript.jsonl (or use -d/-s, --all, or --glob)`).option(`-d, --data-dir <path>`,`Data directory containing .aimax/sessions`).option(`-s, --session-id <id>`,`Session ID under the data directory`).option(`--session-store <name>`,`Session store under .aimax (default: sessions)`).option(`-o, --output <path>`,`Output HTML path for a single export`).option(`--output-dir <path>`,`Output directory for batch export`).option(`--all`,`Export all sessions under --data-dir (requires --output-dir)`).option(`--glob <pattern>`,`Export transcripts matching a glob (requires --output-dir)`).option(`--no-index`,`Skip writing index.html in batch mode`).option(`--encrypt-sessions`,`Enable gocryptfs-backed encryption for the .aimax data directory`).action(async(e,t,n)=>{let r=n.opts();try{if(r.glob){r.outputDir||(I(`error: --glob requires --output-dir`),process.exit(1)),co(await ao(r.glob,T(r.outputDir),{writeIndex:!r.noIndex}));return}if(r.all){(!r.dataDir||!r.outputDir)&&(I(`error: --all requires --data-dir and --output-dir`),process.exit(1)),await U(r.dataDir,r,async()=>{let e=r.sessionStore?y(r.sessionStore):void 0;co(await io(r.dataDir,T(r.outputDir),{storeName:e,writeIndex:!r.noIndex}))});return}if(e){let t=T(e);S(t)||(I(`File not found: ${t}`),process.exit(1)),r.outputDir&&xe(T(r.outputDir),{recursive:!0});let n=await eo(t,{outputPath:r.outputDir?w(T(r.outputDir),`${Te(Ee(t))}.html`):r.output});console.log(n);return}(!r.dataDir||!r.sessionId)&&(I(`error: specify <transcript.jsonl>, --glob, (-d --all --output-dir), or (-d -s)`),process.exit(1)),so(r.sessionId),await U(r.dataDir,r,async()=>{let e=r.sessionStore?y(r.sessionStore):void 0;r.outputDir&&xe(T(r.outputDir),{recursive:!0});let t=r.outputDir?T(r.outputDir,`${r.sessionId}.html`):r.output,n=await no(r.dataDir,r.sessionId,{outputPath:t,storeName:e});console.log(n)})}catch(e){I(`Error exporting HTML: ${e.message}`),process.exit(1)}})}function so(e){if(e.includes(`..`)||e.startsWith(`/`))throw Error(`Invalid session id: ${e}`)}function co(e){for(let t of e.exported)console.log(t.path);for(let t of e.warnings??[])I(`warning: ${t}`);for(let t of e.skipped)I(`skipped ${t.sessionId}: ${t.reason}`);e.indexPath&&console.log(e.indexPath),console.log(`exported ${e.exported.length}, skipped ${e.skipped.length}`)}const lo=e(import.meta.url)(`../package.json`);function uo(){return process.env.AIMAX_DATA_DIR||process.cwd()}function fo(){let e=new t;return e.name(`aimax`).description(`AIMax CLI — runs agent tasks in a containerized environment`).version(lo.version),Ci(e),Cr(e),ta(e),ca(e),wi(e),oo(e),ga(e),Ji(e),sn(e),Ni(e),Hi(e,uo),qi(e,uo),e}export{P as a,N as i,uo as n,ut as o,xi as r,fo as t};
|
package/dist/program.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
import{n as e,t}from"./program-
|
|
1
|
+
import{n as e,t}from"./program-Cm76RPAA.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.
|
|
3
|
+
"version": "0.16.0",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"bin": {
|
|
6
6
|
"aimax": "./dist/bin.js"
|
|
@@ -28,8 +28,8 @@
|
|
|
28
28
|
"commander": "^14.0.3",
|
|
29
29
|
"gensign-node": "latest",
|
|
30
30
|
"log4js": "^6.9.1",
|
|
31
|
-
"@gencode/agents": "0.
|
|
32
|
-
"@gencode/shared": "0.
|
|
31
|
+
"@gencode/agents": "0.18.0",
|
|
32
|
+
"@gencode/shared": "0.6.0"
|
|
33
33
|
},
|
|
34
34
|
"devDependencies": {
|
|
35
35
|
"@types/node": "^22.0.0",
|
package/dist/program-Bd8KnLF6.js
DELETED
|
@@ -1,40 +0,0 @@
|
|
|
1
|
-
import{createRequire as e}from"node:module";import{Command as t}from"commander";import{GoalConflictError as n,applyCliGoalBeforeRun as r,bootstrapMountLayout as i,buildAimaxGoalCliHelpExtra as a,buildResumeNarration as o,clearPendingUiTool as s,deleteGoal as c,ensureBootstrapMountLayout as l,exportSession as u,formatApprovalResolution as d,formatClarifyResolution as f,formatReviewResolution as p,hasBootstrapSentinel as m,initializePluginSystem as h,inspectSession as g,listAvailableSlashCommands as _,listSessionSummaries as v,loadPendingHitl as ee,loadPendingUiTool as te,loadSessionExportSnapshots as ne,loadSkillsWithPluginDirs as re,loadTranscript as ie,normalizePluginsConfig as ae,normalizeSessionStoreName as y,readGoal as b,resolveGoalObjective as oe,resolveMemoryProviderOrDefault as se,resolvePendingHitl as ce,resolvePendingUiTool as le,rewriteTranscript as ue,runAgent as de,sessionsDir as fe,transcriptPath as pe,updateGoal as me,writeGoal as he}from"@gencode/agents";import{formatTaskForDisplay as ge,isAgentDiagnosticEvent as _e,isHitlTool as ve,parseMatchedTextToResolution as ye,parseTextToResolution as be}from"@gencode/shared";import x,{existsSync as S,mkdirSync as xe,readFileSync as Se,statSync as Ce,writeFileSync as we}from"node:fs";import C,{basename as Te,dirname as w,isAbsolute as Ee,join as T,relative as De,resolve as E}from"node:path";import Oe from"log4js";import D from"node:fs/promises";import ke from"node:os";import{execFile as Ae,execFileSync as je}from"node:child_process";import Me from"gensign-node";import{fileURLToPath as Ne}from"node:url";import{addAgent as Pe,addBinding as Fe,getAgentConfig as O,listAgents as Ie,listBindings as Le,loadAgentsConfig as k,normalizeAgentId as Re,removeAgent as ze,removeBindings as Be,resolveAgentDir as Ve,resolveDefaultAgentId as He,updateAgentIdentity as Ue}from"@gencode/agents/config";import{createHash as We,randomUUID as Ge}from"node:crypto";function Ke(e){let t=new Intl.DateTimeFormat(`en-CA`,{timeZone:`Asia/Shanghai`,year:`numeric`,month:`2-digit`,day:`2-digit`,hour:`2-digit`,minute:`2-digit`,second:`2-digit`,hour12:!1}).formatToParts(e);return Object.fromEntries(t.map(e=>[e.type,e.value]))}function qe(e=new Date){let t=Ke(e),n=String(e.getMilliseconds()).padStart(3,`0`);return`${t.year}-${t.month}-${t.day} ${t.hour}:${t.minute}:${t.second}.${n}`}let A=function(e){return e.INFO=`INFO`,e.ERROR=`ERROR`,e.WARN=`WARN`,e}({}),j=null,Je=!1,M=[],Ye=Promise.resolve();function Xe(){return qe()}function Ze(e){if(!e)return``;let t=Object.entries(e).filter(([,e])=>e!==void 0).map(([e,t])=>`${e}=${Qe(t)}`);return t.length>0?` ${t.join(` `)}`:``}function Qe(e){return JSON.stringify($e(e,new WeakSet))??`undefined`}function $e(e,t){return typeof e==`bigint`?e.toString():e==null||typeof e==`string`||typeof e==`number`||typeof e==`boolean`?e:e instanceof Error?{name:e.name,message:e.message,stack:e.stack}:typeof e!=`object`&&typeof e!=`function`?String(e):t.has(e)?`[Circular]`:(t.add(e),Array.isArray(e)?e.map(e=>$e(e,t)):Object.fromEntries(Object.entries(e).filter(([,e])=>e!==void 0).map(([e,n])=>[e,$e(n,t)])))}function et(e){return C.join(e,`.aimax`)}function tt(e){let t=e?.trim();return t&&t.replace(/[^A-Za-z0-9_.-]/g,`_`)||`no-message-${process.pid}`}function nt(e,t){let n=tt(t?.messageId),r=t?.sessionStoreName?.trim()||`sessions`;return t?.sessionId?{runLogId:n,logDir:C.join(et(e),r,t.sessionId,`logs`,n)}:{runLogId:n,logDir:C.join(et(e),`logs`,n)}}function rt(e){return{appLogPath:C.join(e,`app.log`),errorLogPath:C.join(e,`errors.log`)}}function it(e){let{appLogPath:t,errorLogPath:n}=rt(e);Oe.configure({appenders:{appFile:{type:`file`,filename:t,maxLogSize:5*1024*1024,backups:3,compress:!0,keepFileExt:!0,layout:{type:`messagePassThrough`}},errorFile:{type:`file`,filename:n,maxLogSize:5*1024*1024,backups:3,compress:!0,keepFileExt:!0,layout:{type:`messagePassThrough`}},errorsOnly:{type:`logLevelFilter`,appender:`errorFile`,level:`error`,maxLevel:`fatal`}},categories:{default:{appenders:[`appFile`,`errorsOnly`],level:`info`}}})}function at(e,t,n){return`[${Xe()}] [${e}] ${t}${Ze(n)}`}function ot(e,t,n){try{process.stderr.write(`${at(e,t,n)}\n`)}catch{}}function N(e,t,n){if(!j){M.push({level:e,message:t,context:n}),M.length>200&&(M=M.slice(-200)),ot(e,t,n);return}Je||=(it(j.logDir),!0);let r=at(e,t,n),i=Oe.getLogger();if(e===A.ERROR){i.error(r);return}if(e===A.WARN){i.warn(r);return}i.info(r)}function P(e,t){let{logDir:n,runLogId:r}=nt(e,t);if(Je&&j?.dataDir===e&&j.runLogId===r&&j.logDir===n)return;x.mkdirSync(n,{recursive:!0}),it(n),Je=!0,j={dataDir:e,logDir:n,runLogId:r};let i=M;M=[];for(let e of i)N(e.level,e.message,e.context)}function st(){return j?{...j}:null}function ct(e){if(!e.logDir){e.level===`ERROR`?N(A.ERROR,e.message,e.context):e.level===`WARN`?N(A.WARN,e.message,e.context):N(A.INFO,e.message,e.context);return}let{appLogPath:t,errorLogPath:n}=rt(e.logDir),r=`${e.formatted}\n`;Ye=Ye.then(async()=>{await x.promises.mkdir(e.logDir,{recursive:!0}),await x.promises.appendFile(t,r,`utf-8`),e.level===`ERROR`&&await x.promises.appendFile(n,r,`utf-8`)}).catch(t=>{ot(A.ERROR,`delegated agent log write failed`,{logDir:e.logDir,error:t instanceof Error?t.message:String(t)})})}async function lt(){await Ye;try{await ut()}finally{Je=!1}}function ut(){return new Promise((e,t)=>{Oe.shutdown(n=>{if(n){t(n);return}e()})})}const F={info:(e,t)=>N(A.INFO,e,t),warn:(e,t)=>N(A.WARN,e,t),error:(e,t)=>N(A.ERROR,e,t)};var dt=class{startTime;name;constructor(e){this.name=e,this.startTime=Date.now()}end(){let e=Date.now()-this.startTime;return F.info(`${this.name} completed in ${e}ms`),e}};function ft(e){if(typeof e==`string`)return e;let t=JSON.stringify(e);return t===void 0?String(e):t}const pt=new Set;function mt(e){return e instanceof Error?{name:e.name,message:e.message,code:e.code}:{message:String(e)}}function ht(e,t){try{F.warn(`CLI ${e} write failed; suppressing further ${e} writes`,{stream:e,...mt(t)})}catch{}}function gt(e,t){if(pt.has(e))return;let n=e===`stdout`?process.stdout:process.stderr;try{n.write(t)}catch(t){pt.add(e),ht(e,t)}}function _t(e){gt(`stdout`,e)}function I(e){gt(`stdout`,e+`
|
|
2
|
-
`)}function L(e){gt(`stderr`,e+`
|
|
3
|
-
`)}function R(e){switch(e.type){case`start`:I(`\n[start] ${e.message}`);break;case`text`:_t(e.text);break;case`stream_text_delta`:_t(e.text);break;case`bootstrap`:I(`\n[bootstrap:${e.phase}] ${e.dataDir}`);break;case`session_reset`:I(`\n[session:${e.action}] ${e.message}`);break;case`tool_start`:I(`\n[tool:${e.name}] ${JSON.stringify(e.input??{})}`);break;case`tool_end`:{let t=ft(e.output);I(`[tool:${e.name}] ${e.isError?`ERROR`:`OK`} ${t.slice(0,200)}`);break}case`compaction`:I(`\n[compaction${e.layer?`:${e.layer}`:``}] ${e.reason}${e.strategy?` (${e.strategy})`:``}`);break;case`skill_used`:I(`\n[skill] ${e.skillName} agent=${e.agent} task=${e.taskId}`);break;case`custom`:I(`\n[plugin:${e.pluginId}] ${e.name}${e.label?` ${e.label}`:``}${e.data?` ${JSON.stringify(e.data)}`:``}`);break;case`error`:L(`\n[error] ${e.message}`);break;case`diagnostic`:break;case`subagent_spawn`:I(`\n[subagent:spawn]${e.label?` "${e.label}"`:``} ${ge(e.task)}`);break;case`subagent_complete`:I(`[subagent:${e.status}] ${ge(e.task)}`);break;case`hitl_requested`:if(I(`\n[hitl:${e.request.kind}] ${e.request.title}`),I(` prompt: ${e.request.prompt}`),I(` requestId: ${e.request.requestId}`),e.request.input.mode===`choice`)for(let t of e.request.input.choices)I(` - [${t.id}] ${t.label}`);break;case`hitl_resumed`:I(`\n[hitl:resumed] requestId=${e.requestId} action=${e.resolution.action}`);break;case`hitl_expired`:I(`\n[hitl:expired] requestId=${e.requestId} reason=${e.reason}`);break;case`hitl_cancelled`:I(`\n[hitl:cancelled] requestId=${e.requestId}${e.reason?` reason=${e.reason}`:``}`);break;case`ui_tool_request`:I(`\n[ui-tool:${e.request.toolName}] ${e.request.outputSchema.title}`),I(` requestId: ${e.request.requestId}`),I(` toolCallId: ${e.request.toolCallId}`);break;case`ui_tool_result`:I(`\n[ui-tool:resumed] requestId=${e.requestId} tool=${e.toolName}`);break}}function vt(e,t){if(t===`json`){e&&I(JSON.stringify(e,null,2));return}I(`
|
|
4
|
-
`),I(`session: ${e.sessionId}`),I(`duration: ${e.durationMs}ms`),I(`tokens: input=${e.usage.input} output=${e.usage.output} total=${e.usage.total}`),e.context&&(I(`context: ${e.context.snapshotPath}`),I(`tool-results: ${e.context.toolResultsDir}`)),e.error&&L(`error: ${e.error}`)}function yt(e,t){if(t===`json`){I(JSON.stringify(e,null,2));return}if(e.length===0){I(`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:—]`;I(`${t.id} ${e} [${t.channel}]${n} ${t.title}`)}}function bt(e,t){if(t===`json`){I(JSON.stringify(e,null,2));return}I(`session: ${e.id}`),e.metadata&&(I(`title: ${e.metadata.title}`),I(`channel: ${e.metadata.channel}`),I(`created: ${e.metadata.createdAt}`),I(`updated: ${e.metadata.updatedAt}`)),I(`transcript: ${e.transcriptPath}`),I(`entries: ${e.transcriptEntryCount}`),I(`context: ${e.contextSnapshotPath}`),I(`session-memory: ${e.sessionMemoryPath}`),I(`collapse-log: ${e.collapseLogPath}`),I(`read-states: ${e.readStateCount}`),I(`tool-results: ${e.toolResultRefCount}`),I(`tool-results-dir: ${e.toolResultsDir}`)}function xt(e,t){if(t===`json`){I(JSON.stringify(e,null,2));return}I(`session: ${e.id}`),I(`transcript: ${e.paths.transcriptPath}`),I(`context: ${e.paths.contextSnapshotPath}`),I(`session-memory: ${e.paths.sessionMemoryPath}`),I(`collapse-log: ${e.paths.collapseLogPath}`),I(`tool-results-dir: ${e.paths.toolResultsDir}`),I(`transcript-entries: ${e.transcript.length}`),I(`read-states: ${e.context.readStates.length}`),I(`tool-results: ${e.context.toolResults.length}`),I(`collapse-spans: ${e.context.compaction.collapseSpans.length}`)}function St(e,t){if(t===`json`){I(JSON.stringify(e,null,2));return}I(`Bootstrap completed.`),I(`dataDir: ${e.dataDir}`),I(`created dirs: ${e.createdDirs.length}`),I(`created files: ${e.createdFiles.length}`),I(`skipped dirs: ${e.skippedDirs.length}`),I(`skipped files: ${e.skippedFiles.length}`)}const Ct=`.aimax`,wt=`${Ct}.pre-gocryptfs.`,Tt=[`app.log`,`errors.log`],Et=[`logs`],Dt=[`fusermount3`,`fusermount`,`umount`],Ot=[{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 kt(e){return C.join(e,`.aimax.enc`)}function At(e){return C.join(e,Ct)}function jt(e){return C.join(e,`${wt}${process.pid}.${Date.now()}`)}function Mt(e){return C.join(e,`${Ct}.plaintext-restore.${process.pid}.${Date.now()}`)}function Nt(e){return e.replace(/\\([0-7]{3})/g,(e,t)=>String.fromCharCode(Number.parseInt(t,8)))}async function z(e){try{let t=await It.read(),n=C.resolve(e);for(let e of t.split(`
|
|
5
|
-
`)){if(!e.trim())continue;let t=e.split(` `);if(t.length>=5&&C.resolve(Nt(t[4]??``))===n)return!0}return!1}catch{return!1}}function Pt(e){try{let t=x.readFileSync(`/proc/self/mountinfo`,`utf-8`),n=C.resolve(e);for(let e of t.split(`
|
|
6
|
-
`)){if(!e.trim())continue;let t=e.split(` `);if(t.length>=5&&C.resolve(Nt(t[4]??``))===n)return!0}return!1}catch{return!1}}async function Ft(){return await D.readFile(`/proc/self/mountinfo`,`utf-8`)}const It={read:Ft};async function B(e){try{return await D.stat(e),!0}catch(e){if(e.code===`ENOENT`)return!1;throw e}}async function V(e){await D.mkdir(e,{recursive:!0})}async function Lt(e){if(await V(e),(await D.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 Rt(e){return await B(e)?(await D.readdir(e)).length===0:!0}async function H(e){if(await B(e))return(await D.readdir(e)).length}async function zt(e){if(!await B(e))return!1;let t=await D.readdir(e,{withFileTypes:!0});for(let e of t)if(!(e.isDirectory()&&Et.includes(e.name))&&!(e.isFile()&&Tt.some(t=>e.name.startsWith(t))))return!0;return!1}async function Bt(e){let t=await D.readdir(e,{withFileTypes:!0});for(let n of t){if(n.isDirectory()&&Et.includes(n.name)){await D.rm(C.join(e,n.name),{recursive:!0,force:!0}).catch(()=>{});continue}n.isFile()&&Tt.some(e=>n.name.startsWith(e))&&await D.rm(C.join(e,n.name),{force:!0}).catch(()=>{})}}async function Vt(e){if(!await B(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 Ht(e){return(await D.readdir(e,{withFileTypes:!0})).filter(e=>e.isDirectory()&&e.name.startsWith(wt)).map(t=>C.join(e,t.name)).sort()}async function Ut(e,t){if(!await B(t))return null;let n=jt(e);return F.info(`--encrypt-sessions moving plaintext .aimax aside before migration`,{plainDir:t,backupDir:n}),await D.rename(t,n),n}async function U(e,t,n){F.info(`--encrypt-sessions copying plaintext backup into encrypted mount`,{backupDir:e,plainDir:t,force:n}),await D.cp(e,t,{recursive:!0,force:n})}async function Wt(e,t){if(e.length===0)return[];await V(t);let n=[];for(let r of e)await B(r)&&(await U(r,t,!0),await D.rm(r,{recursive:!0,force:!0}),F.info(`--encrypt-sessions restored interrupted plaintext backup after failed migration`,{backupDir:r,plainDir:t}),n.push(r));return n}async function Gt(e){let t=kt(e),n=At(e),r=await B(t);if(!r)return;let i=r&&await B(C.join(t,`gocryptfs.conf`)),a=await B(n),o=a?await z(n):!1,s=await Rt(n);if(F.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 H(n)}),!i){F.warn(`plaintext .aimax restore skipped because .aimax.enc is not initialized`,{encryptedDir:t,plainDir:n}),await V(n);return}if(o){F.warn(`plaintext .aimax restore skipped because .aimax is already a mount point`,{plainDir:n,encryptedDir:t});return}if(await zt(n)){F.info(`plaintext .aimax restore skipped because plaintext .aimax already contains data`,{plainDir:n,encryptedDir:t,plainDirEntryCount:await H(n)});return}s||(F.info(`plaintext .aimax clearing ephemeral files before restore`,{plainDir:n,encryptedDir:t,plainDirEntryCount:await H(n)}),await Bt(n));try{await Jt()}catch(e){F.warn(`plaintext .aimax restore unavailable; continuing with plaintext .aimax`,{error:e instanceof Error?e.message:String(e),plainDir:n,encryptedDir:t}),await V(n);return}let c=Mt(e),l=!1;try{await Lt(n),await Yt(t,n),l=!0,await D.rm(c,{recursive:!0,force:!0}),await V(c),await D.cp(n,c,{recursive:!0,force:!0}),F.info(`plaintext .aimax restore copied encrypted history to staging directory`,{plainDir:n,encryptedDir:t,restoreDir:c,restoredEntryCount:await H(c)}),await Zt(n),l=!1,await D.rm(n,{recursive:!0,force:!0}),await D.rename(c,n),F.info(`plaintext .aimax restore completed for disabled --encrypt-sessions`,{plainDir:n,encryptedDir:t})}catch(e){l&&await Zt(n).catch(e=>{F.warn(`plaintext .aimax restore failed to unmount during rollback`,{error:e instanceof Error?e.message:String(e),plainDir:n,encryptedDir:t})}),await D.rm(c,{recursive:!0,force:!0}).catch(()=>{}),await V(n).catch(()=>{}),F.warn(`plaintext .aimax restore failed; continuing with existing plaintext .aimax`,{error:e instanceof Error?e.message:String(e),plainDir:n,encryptedDir:t})}}async function Kt(e){let t=C.join(ke.tmpdir(),`aimax-gocryptfs-pass.${process.pid}.${Date.now()}`);await D.writeFile(t,`wizard_aimax@2026
|
|
7
|
-
`,{mode:384});try{return await e(t)}finally{await D.rm(t,{force:!0})}}async function qt(e){let t=e.includes(`-init`)?`init`:`mount`;F.info(`--encrypt-sessions starting gocryptfs ${t}`);try{await tn(`gocryptfs`,e),F.info(`--encrypt-sessions completed gocryptfs ${t}`)}catch(n){let r=n instanceof Error?n.message:String(n);throw F.warn(`--encrypt-sessions failed gocryptfs ${t}`,{error:r}),Error(`gocryptfs ${e.join(` `)} failed: ${r}`)}}async function Jt(){F.info(`--encrypt-sessions checking encryption dependencies`),await rn(`gocryptfs`,`required for --encrypt-sessions`),F.info(`--encrypt-sessions dependency available`,{command:`gocryptfs`});for(let e of Dt)if(await nn(e)){F.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 Yt(e,t){F.info(`--encrypt-sessions mounting encrypted .aimax`,{encryptedDir:e,plainDir:t}),await Kt(async n=>{await qt([`-q`,`-passfile`,n,e,t])})}async function Xt(e){F.info(`--encrypt-sessions initializing encrypted .aimax directory`,{encryptedDir:e}),await Kt(async t=>{await qt([`-q`,`-init`,`-passfile`,t,e])})}async function Zt(e){let t=[];F.info(`--encrypt-sessions unmounting encrypted .aimax`,{plainDir:e});for(let n of Ot)try{if(F.info(`--encrypt-sessions attempting encrypted .aimax unmount`,{command:n.label,plainDir:e}),await tn(n.command,[...n.args,e]),!await z(e)){F.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),F.warn(`--encrypt-sessions unmount command returned success but mountpoint remains`,{command:n.label,plainDir:e})}catch(r){let i=an(n.label,r);t.push(i),F.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 Qt(e){for(let t of Ot)try{if(je(t.command,[...t.args,e],{stdio:`ignore`}),!Pt(e))return}catch{}}function $t(e){let t=!1,n=()=>{t||(t=!0,Qt(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 en(e){let t=kt(e),n=At(e),r=await B(n),i=await B(t),a=i&&await B(C.join(t,`gocryptfs.conf`)),o=r?await z(n):!1;F.info(`--encrypt-sessions preparing encrypted .aimax mount`,{dataDir:e,encryptedDir:t,plainDir:n,plainDirExists:r,encryptedDirExists:i,encryptedDirInitialized:a,plainDirMountPoint:o,plainDirEntryCount:await H(n),encryptedDirEntryCount:await H(t)});let s=()=>({mounted:!1,plainDir:n,encryptedDir:t,async cleanup(){}});try{await Jt()}catch(e){return F.warn(`--encrypt-sessions is unavailable; continuing with plaintext .aimax`,{error:e instanceof Error?e.message:String(e)}),await V(n),s()}if(await z(n))return F.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 Ht(e),l.length>0&&F.warn(`--encrypt-sessions found interrupted pre-gocryptfs migration backups`,{count:l.length}),!await B(t))if(F.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 Ut(e,n):c=await Ut(e,n),await V(t),await Xt(t),await V(n),await Yt(t,n),f=!0,d=$t(n),F.info(`--encrypt-sessions mounted encrypted .aimax`,{plainDir:n,encryptedDir:t}),l.length>0){for(let e of l)await U(e,n,!0);u&&=(await U(u,n,!1),await D.rm(u,{recursive:!0,force:!0}),F.info(`--encrypt-sessions removed residual plaintext backup after migration`,{backupDir:u}),null);for(let e of l)await D.rm(e,{recursive:!0,force:!0}),F.info(`--encrypt-sessions removed resumed plaintext migration backup`,{backupDir:e});l=[]}else c&&=(await U(c,n,!0),await D.rm(c,{recursive:!0,force:!0}),F.info(`--encrypt-sessions removed plaintext migration backup`,{backupDir:c}),null);else if(F.info(`--encrypt-sessions encrypted .aimax directory exists; mounting existing encrypted data`,{encryptedDir:t,plainDir:n,resumedBackupCount:l.length,plainDirEntryCount:await H(n)}),await Vt(t),l.length>0?u=await Ut(e,n):await Rt(n)||(c=await Ut(e,n)),await Lt(n),await Yt(t,n),f=!0,d=$t(n),F.info(`--encrypt-sessions mounted encrypted .aimax`,{plainDir:n,encryptedDir:t}),l.length>0){for(let e of l)await U(e,n,!0);u&&=(await U(u,n,!1),await D.rm(u,{recursive:!0,force:!0}),F.info(`--encrypt-sessions removed residual plaintext backup after migration`,{backupDir:u}),null);for(let e of l)await D.rm(e,{recursive:!0,force:!0}),F.info(`--encrypt-sessions removed resumed plaintext migration backup`,{backupDir:e});l=[]}else c&&=(await U(c,n,!0),await D.rm(c,{recursive:!0,force:!0}),F.info(`--encrypt-sessions removed plaintext migration backup`,{backupDir:c}),null);return F.info(`--encrypt-sessions prepared encrypted .aimax mount result`,{mounted:f,plainDir:n,encryptedDir:t,plainDirMountPoint:await z(n),plainDirEntryCount:await H(n),encryptedDirEntryCount:await H(t)}),{mounted:f,plainDir:n,encryptedDir:t,async cleanup(){if(d?.release(),!f){F.info(`--encrypt-sessions cleanup skipped because encrypted .aimax is not mounted`,{plainDir:n,encryptedDir:t});return}f=!1,F.info(`--encrypt-sessions cleanup started`,{plainDir:n,encryptedDir:t});try{await Zt(n),F.info(`--encrypt-sessions cleanup completed`,{plainDir:n,encryptedDir:t})}catch(e){F.warn(`--encrypt-sessions failed to unmount encrypted .aimax; continuing shutdown`,{error:e instanceof Error?e.message:String(e)})}}}}catch(e){d?.release(),f&&await Zt(n).catch(e=>{F.warn(`--encrypt-sessions failed to unmount during mount rollback`,{error:e instanceof Error?e.message:String(e),plainDir:n,encryptedDir:t})}),c&&await B(c)&&await Rt(n)&&(await D.rm(n,{recursive:!0,force:!0}).catch(()=>{}),await D.rename(c,n).catch(()=>{}),F.info(`--encrypt-sessions restored plaintext backup after failed migration`,{backupDir:c,plainDir:n})),u&&await B(u)&&await Rt(n)&&(await D.rm(n,{recursive:!0,force:!0}).catch(()=>{}),await D.rename(u,n).catch(()=>{}),F.info(`--encrypt-sessions restored residual plaintext backup after failed migration`,{backupDir:u,plainDir:n}));let r=await Wt(l,n).catch(e=>(F.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)),F.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 V(n),s()}}async function W(e,t,n){if(!t.encryptSessions)return await Gt(e),n();F.info(`--encrypt-sessions wrapper starting encrypted .aimax preparation`,{dataDir:e});let r=await en(e);F.info(`--encrypt-sessions wrapper prepared encrypted .aimax state`,{dataDir:e,mounted:r.mounted,plainDir:r.plainDir,encryptedDir:r.encryptedDir});try{return F.info(`--encrypt-sessions wrapper entering protected operation`,{dataDir:e,mounted:r.mounted}),await n(r)}finally{F.info(`--encrypt-sessions wrapper starting cleanup`,{dataDir:e,mounted:r.mounted,plainDir:r.plainDir,encryptedDir:r.encryptedDir}),await r.cleanup(),F.info(`--encrypt-sessions wrapper finished cleanup`,{dataDir:e,mounted:r.mounted,plainDir:r.plainDir,encryptedDir:r.encryptedDir})}}async function tn(e,t){await new Promise((n,r)=>{Ae(e,t,{encoding:`utf-8`},e=>{if(e){r(e);return}n()})})}async function nn(e){try{return await tn(`sh`,[`-c`,`command -v "${e}" >/dev/null 2>&1`]),!0}catch{return!1}}async function rn(e,t){if(!await nn(e))throw Error(`--encrypt-sessions requires ${e}: ${t}.`)}function an(e,t){return`${e} failed: ${t instanceof Error?t.message:String(t)}`}function on(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{St(await W(e.dataDir,e,async()=>i(e.dataDir)),t)}catch(e){L(`Error bootstrapping data directory: ${e.message}`),process.exit(1)}})}function sn(e){return Me.sm4_encrypt_ecb(e)}function cn(e){return sn(e)}const ln=[`minimal`,`low`,`medium`,`high`,`xhigh`];function un(e,t){if(e===void 0)return;let n=e.trim().toLowerCase();if(n){if(ln.includes(n))return n;throw Error(`Invalid ${t}: ${e}. Must be one of ${ln.join(`, `)}.`)}}function dn(e={}){let t=fn(e.apiFormat??process.env.AIMAX_API_FORMAT),n=e.baseUrl??process.env.AIMAX_BASE_URL,r=process.env.AIMAX_AUTH_TOKEN,i=e.authToken?cn(e.authToken):r?cn(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,thinking:e.thinking===void 0?un(process.env.AIMAX_THINKING,`AIMAX_THINKING`):un(e.thinking,`--thinking`)}}function fn(e){if(!e||e===`openai-completions`||e===`anthropic-messages`)return e;throw Error(`Unsupported LLM API format: ${e}`)}const pn=[`off`,`fallback`];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 hn(e,t){if(e===void 0)return;let n=e.trim();if(!n)return;let r=Number(n);if(!Number.isFinite(r))throw Error(`Invalid ${t}: ${e}. Must be a number.`);return r}function gn(e,t){if(e===void 0)return;let n=e.trim().toLowerCase();if(n){if(pn.includes(n))return n;throw Error(`Invalid ${t}: ${e}. Must be one of ${pn.join(`, `)}.`)}}function _n(){return[`AIMAX_MEMORY_KC_ENABLED`,`AIMAX_MEMORY_KC_BASE_URL`,`AIMAX_MEMORY_KC_BASE_PATH`,`AIMAX_MEMORY_KC_AUTH_TOKEN`,`AIMAX_MEMORY_KC_SEARCH_MODE`,`AIMAX_MEMORY_KC_TOP_K`,`AIMAX_MEMORY_KC_SCORE_THRESHOLD`,`AIMAX_MEMORY_KC_TIMEOUT_MS`,`AIMAX_MEMORY_KC_SYNC_ENABLED`].some(e=>process.env[e]!==void 0)}function vn(e){return Object.values(e).some(e=>e!==void 0)}function yn(e={}){if(!(!vn(e)&&!_n()))return{knowledgeController:{enabled:e.kcEnabled??mn(process.env.AIMAX_MEMORY_KC_ENABLED,`AIMAX_MEMORY_KC_ENABLED`),baseUrl:e.kcBaseUrl??process.env.AIMAX_MEMORY_KC_BASE_URL,basePath:e.kcBasePath??process.env.AIMAX_MEMORY_KC_BASE_PATH,authToken:e.kcAuthToken??process.env.AIMAX_MEMORY_KC_AUTH_TOKEN,searchMode:e.kcSearchMode===void 0?gn(process.env.AIMAX_MEMORY_KC_SEARCH_MODE,`AIMAX_MEMORY_KC_SEARCH_MODE`)??`off`:gn(e.kcSearchMode,`kcSearchMode`),topK:e.kcTopK??hn(process.env.AIMAX_MEMORY_KC_TOP_K,`AIMAX_MEMORY_KC_TOP_K`),scoreThreshold:e.kcScoreThreshold??hn(process.env.AIMAX_MEMORY_KC_SCORE_THRESHOLD,`AIMAX_MEMORY_KC_SCORE_THRESHOLD`),timeoutMs:e.kcTimeoutMs??hn(process.env.AIMAX_MEMORY_KC_TIMEOUT_MS,`AIMAX_MEMORY_KC_TIMEOUT_MS`),syncEnabled:e.kcSyncEnabled??mn(process.env.AIMAX_MEMORY_KC_SYNC_ENABLED,`AIMAX_MEMORY_KC_SYNC_ENABLED`)}}}function bn(e,t){return t?C.resolve(t):C.join(e,`.aimax`,`plugins.json`)}async function G(e,t){let n=bn(e,t);try{let e=await D.readFile(n,`utf-8`);return JSON.parse(e)}catch(e){if(e.code===`ENOENT`)return;throw e}}async function K(e,t,n){let r=bn(e,n);await D.mkdir(C.dirname(r),{recursive:!0}),await D.writeFile(r,JSON.stringify(t,null,2),`utf-8`)}function q(e){return typeof e==`object`&&!!e}function xn(e){return q(e)&&e.type===`text`&&typeof e.text==`string`&&(e.textSignature===void 0||typeof e.textSignature==`string`)}function Sn(e){return q(e)&&e.type===`image`&&typeof e.data==`string`&&typeof e.mimeType==`string`}function Cn(e){return q(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 wn(e){return q(e)&&e.type===`toolCall`&&typeof e.id==`string`&&typeof e.name==`string`&&q(e.arguments)&&(e.thoughtSignature===void 0||typeof e.thoughtSignature==`string`)}function Tn(e){return typeof e==`string`||Array.isArray(e)&&e.every(e=>xn(e)||Sn(e))}function En(e){return Array.isArray(e)&&e.every(e=>xn(e)||Cn(e)||wn(e))}function Dn(e){return q(e)&&typeof e.input==`number`&&typeof e.output==`number`&&typeof e.cacheRead==`number`&&typeof e.cacheWrite==`number`&&typeof e.totalTokens==`number`&&q(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 On(e){return!q(e)||typeof e.role!=`string`?!1:e.role===`user`?Tn(e.content):e.role===`assistant`?En(e.content)&&typeof e.api==`string`&&typeof e.provider==`string`&&typeof e.model==`string`&&Dn(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=>xn(e)||Sn(e))&&typeof e.isError==`boolean`:!1}async function kn(e){let t;try{t=await D.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}`)}return An(n,`Message file`)}function An(e,t=`Messages input`){let n=Array.isArray(e)?e:[e];if(n.length===0||!n.every(e=>On(e)))throw Error(`${t} must contain one Message object or an array of Message objects`);return n}async function jn(e){if([!!e.message,!!e.fromFile,e.messages!==void 0].filter(Boolean).length!==1)throw Error(`Exactly one of --message, --from-file, or messages must be provided`);return e.fromFile?{kind:`messages`,messages:await kn(e.fromFile),source:`file`}:e.messages===void 0?{kind:`text`,message:e.message}:{kind:`messages`,messages:An(e.messages),source:`inline`}}var Mn=class{constructor(e){this.sinks=e}async send(e){await Promise.allSettled(this.sinks.map(async t=>{await t.send(e)}))}async close(){await Promise.allSettled(this.sinks.map(async e=>{await e.close()}))}},Nn=class{deliveryQueue=Promise.resolve();constructor(e){this.url=e}async send(e){this.enqueue(this.toPayload(e))}async close(){await this.deliveryQueue}enqueue(e){let t=this.deliveryQueue.then(async()=>{await this.post(e)},async()=>{await this.post(e)});return this.deliveryQueue=t.catch(()=>{}),t}async post(e){let t=Date.now(),n=Pn(e);F.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){F.error(`callback event failed`,{callbackUrl:this.url,httpStatus:a.status,durationMs:o,timedOut:i,...n});return}F.info(`callback event delivered`,{callbackUrl:this.url,httpStatus:a.status,durationMs:o,...n})}catch(e){let r=Date.now()-t;F.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 Pn(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 Fn(e,t){if(t.kind===`none`)return e;let n=new URL(e);return n.searchParams.set(`authToken`,t.token),n.toString()}const In=5e3,Ln=5e3;function Rn(){let e=globalThis.WebSocket;if(!e)throw Error(`WebSocket is not available in this runtime`);return e}function zn(e){return e?{kind:`query_token`,token:e}:{kind:`none`}}function Bn(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 Vn(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 Hn=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 Un(this.ensureConnected(),In,`WebSocket connection timed out after ${In}ms`);let e=Rn();if(!this.socket||this.socket.readyState!==e.OPEN)return;this.socket.send(JSON.stringify(t))}catch(e){F.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 Un(this.ensureConnected(),In,`WebSocket connection timed out after ${In}ms`);let e=Rn();if(!this.socket||this.socket.readyState!==e.OPEN)return;this.socket.send(JSON.stringify(t))}catch(e){F.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=Rn();if(e.readyState!==t.CLOSED)try{await Un(new Promise(t=>{Bn(e,`close`,()=>t()),e.close()}),Ln,`WebSocket close timed out after ${Ln}ms`)}catch(e){F.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=Rn();if(this.socket&&this.socket.readyState===e.OPEN)return;if(this.connectPromise){await this.connectPromise;return}let t=new e(Fn(this.url,zn(this.authToken)));this.connectPromise=new Promise((e,n)=>{Bn(t,`open`,()=>{this.socket=t,Vn(t,`close`,()=>{this.socket===t&&(this.socket=null)}),e()}),Bn(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 Un(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 Wn(e){let t=e.trim();if(!t)throw Error(`Goal objective cannot be empty`);return t}function Gn(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 Kn(e){let t=Gn(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 qn(e){let t=e?.packageRoot??Jn(),n=C.join(t,`models`),r=C.join(n,...`Xenova/bge-small-zh-v1.5`.split(`/`));if(x.existsSync(C.join(r,`config.json`)))return n}function Jn(){let e=C.dirname(Ne(import.meta.url));return C.basename(e)===`src`||C.basename(e)===`dist`?C.resolve(e,`..`):e}function Yn(e){return{text:e.text,usage:e.usage,durationMs:e.durationMs,...e.error?{error:e.error}:{},...e.paused?{paused:e.paused}:{},...e.uiToolPending?{uiToolPending:e.uiToolPending}:{},...e.artifacts&&e.artifacts.length>0?{artifacts:e.artifacts}:{}}}function Xn(e){if(!e?.trim())return;let t=new Set,n=[];for(let r of e.split(`,`)){let e=r.trim();if(!e)continue;let i=Zn(e);if(!i)throw Error(`Invalid --artifacts-url-whitelist entry: ${e}. Expected a domain or URL with a valid hostname.`);t.has(i)||(t.add(i),n.push(i))}return n.length>0?n:void 0}function Zn(e){try{let t=/^[a-z][a-z\d+.-]*:\/\//i.test(e)?e:`http://${e}`,n=new URL(t);return n.username||n.password?null:n.hostname.trim().toLowerCase()||null}catch{return null}}const Qn=[`start`,`text`,`done`,`error`,`hitl`],$n=[`off`,`gate`,`dry_run`,`write`];function er(e){if(!e?.trim())return new Set(Qn);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(Qn)}function tr(e){if(e.disableTopicSegmentation===!0||process.env.AIMAX_DISABLE_TOPIC_SEGMENTATION===`true`)return{enabled:!1};let t=qn();return t?{embeddingModelDir:t}:void 0}function nr(e){return e.disableTitle===!0||process.env.AIMAX_DISABLE_TITLE===`true`?{enabled:!1}:void 0}function rr(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 ir(e){return e?.trim()||void 0}function ar(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 or(e){return e?y(e):void 0}function sr(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 cr(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 lr(e,t){if(e===void 0)return;let n=e.trim().toLowerCase();if(n){if($n.includes(n))return n;throw Error(`Invalid ${t}: ${e}. Must be one of off,gate,dry_run,write.`)}}function ur(e){let t=e.autoSkillsLoadEnabled===void 0?cr(process.env.AIMAX_AUTO_SKILLS_LOAD_ENABLED,`AIMAX_AUTO_SKILLS_LOAD_ENABLED`):cr(e.autoSkillsLoadEnabled,`--auto-skills-load-enabled`),n=e.autoSkillsReviewMode===void 0?lr(process.env.AIMAX_AUTO_SKILLS_REVIEW_MODE,`AIMAX_AUTO_SKILLS_REVIEW_MODE`):lr(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 dr(e,t){if(e.inputText&&t){let n=be(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 fr(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 pr(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 mr(e){let t=rr(e),n=e.channel??`WEB`,r=dn({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,thinking:e.thinking});return{dataDir:t,systemAgentsDir:ar(e),channel:n,format:e.output===`json`?`json`:`text`,timeoutMs:e.timeout?Number(e.timeout):void 0,llm:r,skillsLoadPaths:sr(e.skillsLoadPaths),artifactsUrlWhitelist:Xn(e.artifactsUrlWhitelist),autoSkills:ur(e)}}function hr(e){let t=[],n=null;return e.callbackUrl&&t.push(new Nn(e.callbackUrl)),e.streamUrl&&(n=new Hn(e.streamUrl,er(e.streamEvents),e.streamAuthToken),t.push(n)),{sink:new Mn(t),websocketSink:n}}async function gr(e){let{dataDir:t,sessionId:n,sessionStoreName:r,toolCallId:i,toolName:a,resolution:o,encryptSessions:s}=e;if(!i||!a||!ve(a))return;let c=(e,t)=>{switch(e){case`request_approval`:return d(t);case`clarify`:return f(t);case`request_review`:return p(t);default:return JSON.stringify({action:t.action,values:t.values})}};await 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 _r(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})}function vr(){let e=yn();return e?{core:e}:void 0}async function yr(e){let t=rr(e);await W(t,e,async()=>{P(t,{messageId:e.messageId,sessionId:e.sessionId,sessionStoreName:or(e.sessionStore)});let i=new dt(`resume command`),a=null;try{let t=await mr(e),o=or(e.sessionStore),c=null;if(e.goal||e.goalFile){let i;i=e.goalFile?await D.readFile(e.goalFile,`utf-8`):e.goal;let a=Wn(i),s=e.tokenBudget===void 0?void 0:e.tokenBudget===`0`||e.tokenBudget===``?null:Number(e.tokenBudget);s!=null&&(Number.isNaN(s)||s<=0)&&(L(`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=Kn({sessionId:e.sessionId,before:n,result:i})}catch(e){throw e instanceof n&&(L(e.message),L(`Existing: ${e.existingObjectivePreview}`),process.exit(2)),e}}F.info(`resume command started`,{sessionId:e.sessionId,requestId:e.requestId,channel:t.channel,dataDir:t.dataDir});let l=await ee(t.dataDir,e.sessionId,{storeName:o,encryptSessions:e.encryptSessions}),u=l?null:await te(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=dr(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=br(n,s.request.kind);await gr({dataDir:t.dataDir,sessionId:e.sessionId,sessionStoreName:o,toolCallId:s.toolContext?.toolCallId,toolName:s.toolContext?.toolName,resolution:n,encryptSessions:e.encryptSessions});let d=hr(e);a=d.sink;let f=e.sessionId,p=async n=>{if(f=n.sessionId??f,!_e(n)){if(n.type===`stream_text_delta`){t.format===`text`&&R(n),await d.websocketSink?.sendTextDelta({sessionId:f,channel:t.channel,messageId:e.messageId,user:e.user,text:n.text});return}t.format===`text`&&R(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&&(F.info(`resume command treated as idempotent replay`,{sessionId:e.sessionId,requestId:e.requestId,idempotencyKey:n.idempotencyKey}),vt({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 G(t.dataDir,m),g;try{g=await de({dataDir:t.dataDir,projectDir:ir(e.projectDir),systemAgentsDir:t.systemAgentsDir,sessionStoreName:o,sessionId:e.sessionId,messageId:e.messageId,channel:t.channel,llm:t.llm,skillsLoadPaths:t.skillsLoadPaths,artifactsUrlWhitelist:t.artifactsUrlWhitelist,autoSkills:t.autoSkills,timeoutMs:t.timeoutMs,message:u,encryptSessions:e.encryptSessions??!1,topicSegmentation:tr(e),titleGeneration:nr(e),memory:vr(),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,onLog:ct})}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:Yn(g)}),vt(g,t.format),g.error?F.error(`resume command failed: ${g.error}`):F.info(`resume command succeeded`),i.end(),process.exit(g.error?1:0);return}let d=fr(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 _r({dataDir:t.dataDir,sessionId:e.sessionId,sessionStoreName:o,result:d,encryptSessions:e.encryptSessions});let f=hr(e);a=f.sink;let p=e.sessionId,m=async n=>{if(p=n.sessionId??p,!_e(n)){if(n.type===`stream_text_delta`){t.format===`text`&&R(n),await f.websocketSink?.sendTextDelta({sessionId:p,channel:t.channel,messageId:e.messageId,user:e.user,text:n.text});return}if(t.format===`text`&&R(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 pr({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 G(t.dataDir,g),v=await de({dataDir:t.dataDir,projectDir:ir(e.projectDir),systemAgentsDir:t.systemAgentsDir,sessionStoreName:o,sessionId:e.sessionId,messageId:e.messageId,channel:t.channel,llm:t.llm,skillsLoadPaths:t.skillsLoadPaths,artifactsUrlWhitelist:t.artifactsUrlWhitelist,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:tr(e),titleGeneration:nr(e),memory:vr(),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,onLog:ct});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:Yn(v)}),vt(v,t.format),v.error?F.error(`resume command failed: ${v.error}`):F.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}`})),F.error(`resume command error: ${n.message}`),L(`Fatal: ${n.message}`),i.end(),process.exit(1)}finally{await a?.close()}})}function br(e,t){return o(e,t)}function xr(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(`--thinking <level>`,`Explicit thinking level: minimal, low, medium, high, or xhigh (overrides AIMAX_THINKING)`).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`).option(`--disable-title`,`Skip LLM session title generation for new sessions (overrides AIMAX_DISABLE_TITLE)`).action(async e=>{await yr(e)})}function Sr(e,t){return{notify:(n,r=`info`)=>{t?.readyState===1?t.send(JSON.stringify({type:`diagnostic`,sessionId:e,level:r,message:n})):console.log(`[${r}] ${n}`)},confirm:async n=>!t||t.readyState!==1?!1:new Promise(r=>{let i=`confirm-${Date.now()}`;t.send(JSON.stringify({type:`hitl_confirm`,sessionId:e,id:i,message:n}));let a=e=>{try{let t=JSON.parse(String(e));r(t.id===i&&t.confirmed===!0)}catch{r(!1)}};typeof t.once==`function`?t.once(`message`,a):t.addEventListener(`message`,e=>a(e.data),{once:!0})}),select:async(n,r)=>{if(!(!t||t.readyState!==1))return new Promise(i=>{let a=`select-${Date.now()}`;t.send(JSON.stringify({type:`hitl_select`,sessionId:e,id:a,title:n,options:r}));let o=e=>{try{let t=JSON.parse(String(e));i(t.id===a?t.selected:void 0)}catch{i(void 0)}};typeof t.once==`function`?t.once(`message`,o):t.addEventListener(`message`,e=>o(e.data),{once:!0})})},setStatus:n=>{t?.readyState===1?t.send(JSON.stringify({type:`diagnostic`,sessionId:e,level:`info`,message:n})):console.log(`[status] ${n}`)}}}const Cr=[`start`,`text`,`done`,`error`],wr=[`off`,`gate`,`dry_run`,`write`];function Tr(e){if(!e?.trim())return new Set(Cr);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(Cr)}function Er(e){if(e.disableTopicSegmentation===!0||process.env.AIMAX_DISABLE_TOPIC_SEGMENTATION===`true`)return{enabled:!1};let t=qn();return t?{embeddingModelDir:t}:void 0}function Dr(e){return e.disableTitle===!0||process.env.AIMAX_DISABLE_TITLE===`true`?{enabled:!1}:void 0}function Or(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 kr(e){return e?.trim()||void 0}function Ar(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 jr(e){return e?.trim()||void 0}function Mr(e){return e??`WEB`}function Nr(e){return e?y(e):void 0}function Pr(e,t){return e===`CRON`?`crons`:Nr(t)}function Fr(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 Ir(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 Lr(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 Lr(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,Ir(o)])}return Object.fromEntries(t)}function zr(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 Br(e,t){if(e===void 0)return;let n=e.trim().toLowerCase();if(n){if(wr.includes(n))return n;throw Error(`Invalid ${t}: ${e}. Must be one of off,gate,dry_run,write.`)}}function Vr(e){let t=e.autoSkillsLoadEnabled===void 0?zr(process.env.AIMAX_AUTO_SKILLS_LOAD_ENABLED,`AIMAX_AUTO_SKILLS_LOAD_ENABLED`):zr(e.autoSkillsLoadEnabled,`--auto-skills-load-enabled`),n=e.autoSkillsReviewMode===void 0?Br(process.env.AIMAX_AUTO_SKILLS_REVIEW_MODE,`AIMAX_AUTO_SKILLS_REVIEW_MODE`):Br(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 Hr(e,t){return e.length<=t?e:t<=3?e.slice(0,t):`${e.slice(0,t-3)}...`}function Ur(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 Wr(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?` ${Hr(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=>Ur(e,a).map(e=>`│ ${e.padEnd(a,` `)} │`)),l].join(`
|
|
9
|
-
`)}function Gr(e){return e.kind===`text`?`inline message (${e.message.length} chars)`:e.source===`file`?`message file (${e.messages.length} messages)`:`inline messages (${e.messages.length} messages)`}function J(e,t=`-`){return e==null||e===``?t:String(e)}function Kr(e){return e?`set`:`unset`}function qr(e){return e?`true`:`false`}function Jr(e,t){let n=Pr(t.channel,e.sessionStore)??`sessions`,r=t.timeoutMs===void 0?`default`:`${t.timeoutMs}`,i=e.callbackUrl?`enabled`:`disabled`,a=e.streamUrl?`enabled`:`disabled`,o=Gr(t.input),s=t.input.kind===`text`?`inline`:e.fromFile??t.input.source,c=qe(),l=Er(e)?.enabled===!1?`disabled`:`enabled`,u=Dr(e)?.enabled===!1?`disabled`:`enabled`,d=e.pluginsConfig??process.env.AIMAX_PLUGINS_CONFIG,f=[...Tr(e.streamEvents)].join(`,`),p=t.autoSkills?.load?.enabled,m=t.autoSkills?.review?.mode,h=e.tokenBudget===`0`?`unlimited`:J(e.tokenBudget),g=t.artifactsUrlWhitelist?.join(`,`)??`-`,_=e.env?Object.keys(Rr(e.env)):[],v=_.length===0?`-`:`${_.length} key${_.length===1?``:`s`}`;return{banner:Wr(void 0,[`AIMax CLI`,`Stateless Agent Runner`]),contextBox:Wr(`Run Context`,[`time : ${c}`,`dataDir : ${t.dataDir}`,`projectDir : ${kr(e.projectDir)??`-`}`,`systemAgents : ${t.systemAgentsDir??`/aimax/agents`}`,`agent : ${jr(e.agent)??`-`}`,`channel : ${t.channel}`,`user : ${e.user??`-`}`,`message : ${e.message===void 0?`-`:`inline (${e.message.length} chars)`}`,`fromFile : ${J(e.fromFile)}`,`input : ${o}`,`skillsPaths : ${t.skillsLoadPaths.length>0?t.skillsLoadPaths.join(`,`):`-`}`,`autoSkillLoad: ${p===void 0?`-`:String(p)}`,`autoSkillRev : ${m??`-`}`,`sessionId : ${e.sessionId??`new`}`,`sessionStore : ${n}`,`messageId : ${e.messageId??`-`}`,`workspace : ${C.join(t.dataDir,`workspace`)}`,`baseUrl : ${t.llm.baseUrl}`,`apiKey : ${Kr(t.llm.apiKey)}`,`authToken : ${Kr(e.authToken)}`,`model : ${t.llm.model}`,`contextWindow: ${J(t.llm.contextWindow)}`,`flashModel : ${J(t.llm.flashModel)}`,`thinking : ${J(t.llm.thinking)}`,`callbackUrl : ${J(e.callbackUrl)}`,`streamUrl : ${J(e.streamUrl)}`,`streamAuth : ${Kr(e.streamAuthToken)}`,`streamEvents : ${f}`,`artifactUrls : ${g}`,`output : ${t.format}`,`callback : ${i}`,`websocket : ${a}`,`timeoutMs : ${r}`,`pluginsConfig: ${J(d)}`,`env : ${v}`,`goal : ${e.goal===void 0?`-`:`inline (${e.goal.length} chars)`}`,`goalFile : ${J(e.goalFile)}`,`tokenBudget : ${h}`,`force : ${qr(e.force)}`,`resumeReqId : ${J(e.resumeRequestId)}`,`resumeInput : ${e.resumeInputJson===void 0?`-`:`inline (${e.resumeInputJson.length} chars)`}`,`resumeFile : ${J(e.resumeFromFile)}`,`encryptSess : ${qr(e.encryptSessions)}`,`topicSegment : ${l}`,`titleGen : ${u}`]),logContext:{time:c,channel:t.channel,user:e.user,dataDir:t.dataDir,projectDir:kr(e.projectDir),systemAgentsDir:t.systemAgentsDir,agent:jr(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:p,autoSkillsReviewMode:m,baseUrl:t.llm.baseUrl,hasApiKey:!!t.llm.apiKey,hasAuthToken:!!e.authToken,model:t.llm.model,contextWindow:t.llm.contextWindow,flashModel:t.llm.flashModel,thinking:t.llm.thinking,callbackUrl:e.callbackUrl,streamUrl:e.streamUrl,hasStreamAuthToken:!!e.streamAuthToken,streamEvents:f,artifactsUrlWhitelist:t.artifactsUrlWhitelist?.join(`,`)||void 0,output:t.format,hasCallback:!!e.callbackUrl,hasStream:!!e.streamUrl,timeoutMs:t.timeoutMs,pluginsConfig:d,envKeys:_.length>0?_.join(`,`):void 0,hasGoal:e.goal!==void 0,goalFile:e.goalFile,tokenBudget:h===`-`?void 0:h,force:!!e.force,resumeRequestId:e.resumeRequestId,hasResumeInputJson:e.resumeInputJson!==void 0,resumeFromFile:e.resumeFromFile,encryptSessions:!!e.encryptSessions,topicSegmentation:l,titleGeneration:u,inputKind:t.input.kind,inputSource:s,inputSummary:o}}}async function Yr(e,t){let n=Or(e),r=Mr(e.channel),i=dn({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,thinking:e.thinking});return{dataDir:n,systemAgentsDir:Ar(e),channel:r,format:e.output===`json`?`json`:`text`,timeoutMs:e.timeout?Number(e.timeout):void 0,llm:i,input:t,skillsLoadPaths:Fr(e.skillsLoadPaths),artifactsUrlWhitelist:Xn(e.artifactsUrlWhitelist),autoSkills:Vr(e)}}function Xr(e){if(e.kind===`text`)return e.message;if(e.messages.length!==1)return null;let[t]=e.messages;if(t.role!==`user`)return null;if(typeof t.content==`string`)return t.content;if(t.content.length===0)return null;let n=[];for(let e of t.content){if(e.type!==`text`)return null;n.push(e.text)}return n.join(`
|
|
10
|
-
`)}async function Zr(e,t){if(!e.sessionId)return null;let n=Xr(t);if(!n)return null;let r=await ee(Or(e),e.sessionId,{storeName:Nr(e.sessionStore),encryptSessions:e.encryptSessions});return!r||r.status!==`pending`||!ye(n,r.request)?null:{requestId:r.request.requestId,inputText:n}}function Qr(e){let t=[],n=null;return e.callbackUrl&&t.push(new Nn(e.callbackUrl)),e.streamUrl&&(n=new Hn(e.streamUrl,Tr(e.streamEvents),e.streamAuthToken),t.push(n)),{sink:new Mn(t),websocketSink:n}}async function Y(e,t){F.info(`dispatching external event`,yi(t)),await e.sink.send(t)}function $r(e){let t={sessionId:e.sessionId,messageId:e.messageId,parentSessionId:e.parentSessionId,depth:e.depth,scope:e.scope,phase:e.phase,...e.details};if(e.level===`error`){F.error(e.message,t);return}if(e.level===`warn`){F.warn(e.message,t);return}F.info(e.message,t)}function ei(e,t,n,r,i){return{sink:e,websocketSink:t,channel:n,defaultMessageId:r,user:i}}function ti(e){let t=new AbortController,n=n=>{F.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 ni(e){return{activeSessionId:e??`pending`,finalResult:null,loggerSessionId:void 0}}function ri(e,t,n,r){!r||n.loggerSessionId===r||(P(e,{messageId:t.messageId,sessionId:r,sessionStoreName:Pr(t.channel,t.sessionStore)}),n.loggerSessionId=r)}function ii(e,t){e.activeSessionId=t.sessionId??e.activeSessionId}function ai(e,t){return e.messageId??t}async function oi(e,t,n){if(!await m(e.dataDir)){if(await si(t,e.format,n.activeSessionId,e.dataDir,`checking`),(await l(e.dataDir)).performedBootstrap){await si(t,e.format,n.activeSessionId,e.dataDir,`initializing`),await si(t,e.format,n.activeSessionId,e.dataDir,`initialized`);return}await si(t,e.format,n.activeSessionId,e.dataDir,`ready`)}}async function si(e,t,n,r,i){let a={type:`bootstrap`,phase:i,dataDir:r};t===`text`&&R(a),await Y(e,{sessionId:n,channel:e.channel,messageId:e.defaultMessageId,user:e.user,type:`progress`,event:a})}function ci(e,t,n,r){return async i=>{if(ii(n,i),ri(e.dataDir,{...r,channel:e.channel},n,i.sessionId),_e(i)){$r(i);return}if(i.type===`stream_text_delta`){e.format===`text`&&R(i),await t.websocketSink?.sendTextDelta({sessionId:n.activeSessionId,channel:e.channel,messageId:ai(i,t.defaultMessageId),user:t.user,text:i.text});return}e.format===`text`&&R(i);let a=ai(i,t.defaultMessageId);if(i.type===`hitl_requested`){await Y(t,{sessionId:n.activeSessionId,channel:e.channel,messageId:a,user:t.user,type:`hitl`,request:i.request}),await Y(t,{sessionId:n.activeSessionId,channel:e.channel,messageId:a,user:t.user,type:`progress`,event:i});return}if(i.type===`start`){await Y(t,{sessionId:n.activeSessionId,channel:e.channel,messageId:a,user:t.user,type:`start`,message:i.message});return}if(i.type===`session_reset`){await Y(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 Y(t,{sessionId:n.activeSessionId,channel:e.channel,messageId:a,user:t.user,type:`progress`,event:i})}}function li(e){let t=Sr(e);return{confirm:(e,n)=>t.confirm(e),select:(e,n,r)=>t.select?t.select(e,n):Promise.resolve(void 0)}}function ui(e,t,n,r,i,a){let o=yn(),s={dataDir:t.dataDir,projectDir:kr(e.projectDir),systemAgentsDir:t.systemAgentsDir,agentPolicy:jr(e.agent)?{requestedAgentName:jr(e.agent)}:void 0,sessionStoreName:Pr(t.channel,e.sessionStore),sessionId:e.sessionId,messageId:e.messageId,channel:t.channel,llm:t.llm,skillsLoadPaths:t.skillsLoadPaths,artifactsUrlWhitelist:t.artifactsUrlWhitelist,autoSkills:t.autoSkills,timeoutMs:t.timeoutMs,abortSignal:n.signal,pendingGoal:a,encryptSessions:e.encryptSessions??!1,topicSegmentation:Er(e),titleGeneration:Dr(e),env:Rr(e.env),...o?{memory:{core:o}}:{},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,onLog:ct,createPiExtensionDialogBridge:li};return t.input.kind===`messages`?{...s,messages:t.input.messages}:{...s,message:t.input.message}}async function di(e,t,n,r){if(t.activeSessionId=r.sessionId,t.finalResult=r,r.error){await Y(e,{sessionId:r.sessionId,channel:e.channel,messageId:n,user:e.user,type:`error`,message:r.error});return}await Y(e,{sessionId:r.sessionId,channel:e.channel,messageId:n,user:e.user,type:`done`,result:Yn(r)})}async function fi(e,t,n,r){await Y(e,{sessionId:t.finalResult?.sessionId??t.activeSessionId,channel:e.channel,messageId:n,user:e.user,type:`error`,message:`Fatal: ${r.message}`})}function pi(e,t){let n=Jr(e,t);F.info([`run command started`,n.banner,n.contextBox].join(`
|
|
11
|
-
`),n.logContext),t.format===`text`&&(I(n.banner),I(``),I(n.contextBox),I(``))}function mi(e,t,n){return vt(t,n),t.error?F.error(`run command failed: ${t.error}`):F.info(`run command succeeded`),e.end(),t.error?1:0}function hi(e){let t=st();if(!t)return;let n=`[${qe()}] [ERROR] ${e}\n`;try{x.appendFileSync(C.join(t.logDir,`app.log`),n),x.appendFileSync(C.join(t.logDir,`errors.log`),n)}catch{}}async function gi(e,t){let n=`run command error: ${t.message}`;F.error(n),hi(n),L(`Fatal: ${t.message}`),e.end(),await lt(),process.exit(1)}async function _i(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 D.readFile(e.resumeFromFile,`utf-8`)}catch(e){throw Error(`Failed to read resume input file: ${e.message}`)}}async function vi(e){let t=Or(e);try{await W(t,e,async i=>{let a=ni(e.sessionId);ri(t,{...e,channel:Mr(e.channel)},a,e.sessionId),e.encryptSessions&&F.info(`--encrypt-sessions run mount state after logger initialization`,{dataDir:t,mounted:i?.mounted??!1,plainDir:i?.plainDir,encryptedDir:i?.encryptedDir});let o=new dt(`run command`),s=await _i(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 yr({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,thinking:e.thinking,callbackUrl:e.callbackUrl,streamUrl:e.streamUrl,streamAuthToken:e.streamAuthToken,streamEvents:e.streamEvents,timeout:e.timeout,output:e.output,pluginsConfig:e.pluginsConfig,artifactsUrlWhitelist:e.artifactsUrlWhitelist,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,disableTitle:e.disableTitle});return}let c;try{c=await jn({message:e.message,fromFile:e.fromFile,messages:e.messages})}catch(e){await gi(o,e);return}let l=await Zr(e,c);if(l){await yr({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,thinking:e.thinking,callbackUrl:e.callbackUrl,streamUrl:e.streamUrl,streamAuthToken:e.streamAuthToken,streamEvents:e.streamEvents,timeout:e.timeout,output:e.output,pluginsConfig:e.pluginsConfig,artifactsUrlWhitelist:e.artifactsUrlWhitelist,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,disableTitle:e.disableTitle});return}let u=e.channel??`WEB`,{controller:d,cleanup:f}=ti(()=>({activeSessionId:a.activeSessionId,finalSessionId:a.finalResult?.sessionId,messageId:e.messageId,channel:u,user:e.user})),p=null;try{let t=await Yr(e,c);u=t.channel,pi(e,t);let i=Qr(e);p=i.sink,F.info(`external sink configured`,{callbackUrl:e.callbackUrl,streamUrl:e.streamUrl,streamEvents:e.streamEvents});let s=ei(p,i.websocketSink,t.channel,e.messageId,e.user);await oi(t,s,a);let l,f=null;if(e.goal||e.goalFile){let i;i=e.goalFile?await D.readFile(e.goalFile,`utf-8`):e.goal;let a=Wn(i),o=Nr(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)&&(L(`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=Kn({sessionId:e.sessionId,before:n,result:i})}else l={objective:a,tokenBudget:s??null}}catch(e){throw e instanceof n&&(L(e.message),L(`Existing: ${e.existingObjectivePreview}`),process.exit(2)),e}}let m=e.pluginsConfig??process.env.AIMAX_PLUGINS_CONFIG,h=await G(t.dataDir,m),g=ci(t,s,a,e);f&&await g(f);let _=await de(ui(e,t,d,g,h,l));ri(t.dataDir,{...e,channel:t.channel},a,_.sessionId),await di(s,a,e.messageId,_),process.exitCode=mi(o,_,t.format)}catch(t){let n=t;p&&await fi(ei(p,null,u,e.messageId,e.user),a,e.messageId,n),await gi(o,n)}finally{await p?.close(),f()}})}finally{await lt()}}function yi(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 bi(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(`--thinking <level>`,`Explicit thinking level: minimal, low, medium, high, or xhigh (overrides AIMAX_THINKING)`).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(`--artifacts-url-whitelist <urls>`,`Comma-separated URL artifact hostnames or URLs to collect; unset collects all URL artifacts`).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`).option(`--disable-title`,`Skip LLM session title generation for new sessions (title falls back to a truncated first message; overrides AIMAX_DISABLE_TITLE)`).action(async e=>{await vi(e)})}function xi(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||(L(`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`&&(L(`Invalid channel: ${r.channel}. Must be 'H5', 'WEB', 'KLPA', 'TASK', 'CRON', or 'EIP_ASSISTANT'`),process.exit(1));try{await W(r.dataDir,r,async()=>{let e=r.sessionStore?y(r.sessionStore):void 0;if(i===`list`){yt(await v(r.dataDir,r.channel,{storeName:e}),a);return}if(r.sessionId||(L(`error: required option '-s, --session-id <id>' not specified`),process.exit(1)),i===`inspect`){bt(await g(r.dataDir,r.sessionId,{storeName:e}),a);return}if(i===`export`){xt(await u(r.dataDir,r.sessionId,{storeName:e}),a);return}L(`Invalid sessions action: ${i}. Must be 'list', 'inspect', or 'export'`),process.exit(1)})}catch(e){L(`${i===`inspect`?`Error inspecting session`:i===`export`?`Error exporting session`:`Error listing sessions`}: ${e.message}`),process.exit(1)}})}function Si(e){return C.join(e,`workspace`)}function Ci(){let e=process.env.AIMAX_PLUGINS_BUNDLED_DIR;return e&&e.trim()||void 0}function wi(e,t){let n=[];n.push(`backend: ${e.backend}`),n.push(`provider: ${e.provider}${e.model?` (${e.model})`:``}`);let r=typeof e.custom?.providerSource==`string`?e.custom.providerSource:void 0,i=typeof e.custom?.providerId==`string`?e.custom.providerId:void 0,a=typeof e.custom?.pluginId==`string`?e.custom.pluginId:void 0;r&&n.push(`provider_source: ${r}`),i&&n.push(`provider_id: ${i}`),a&&n.push(`plugin_id: ${a}`),typeof e.files==`number`&&n.push(`files: ${e.files}`),typeof e.chunks==`number`&&n.push(`chunks: ${e.chunks}`),typeof e.dirty==`boolean`&&n.push(`dirty: ${e.dirty}`),e.dbPath&&n.push(`db: ${e.dbPath}`),e.sources?.length&&n.push(`sources: ${e.sources.join(`, `)}`),t&&(e.fts&&(n.push(`fts: enabled=${e.fts.enabled} available=${e.fts.available}`),e.fts.error&&n.push(`fts_error: ${e.fts.error}`)),e.vector&&(n.push(`vector: enabled=${e.vector.enabled} available=${e.vector.available??`unknown`}`),e.vector.dims&&n.push(`vector_dims: ${e.vector.dims}`),e.vector.loadError&&n.push(`vector_error: ${e.vector.loadError}`)),e.cache&&n.push(`cache: enabled=${e.cache.enabled} entries=${e.cache.entries??0}`));let o=Array.isArray(e.custom?.cliWarnings)?e.custom.cliWarnings.filter(e=>typeof e==`string`&&e.length>0):[];for(let e of o)n.push(`warning: ${e}`);return n.join(`
|
|
12
|
-
`)}function Ti(e){let t=e.level===`error`?`plugin error`:`plugin warning`;return e.pluginId?`${t} (${e.pluginId}): ${e.message}`:`${t}: ${e.message}`}function Ei(e){if(!e||e===`cli`)return`cli`;if(e===`cron`)return`cron`;throw Error(`Unsupported dream trigger: ${e}. Expected "cli" or "cron".`)}async function Di(e){let t=[],n;try{n=await G(e.dataDir,e.pluginsConfig)}catch(e){t.push(`failed to load plugins config: ${e.message}`)}if(!e.shouldInitialize&&!n)return{warnings:t};try{let r=h({config:n,dataDir:e.dataDir,workspaceDir:Si(e.dataDir),bundledDir:Ci()});return t.push(...r.diagnostics.map(Ti)),{pluginSystem:r,warnings:t}}catch(e){return t.push(`failed to initialize plugin system: ${e.message}`),{warnings:t}}}async function Oi(e){let t=C.join(e.dataDir,`.aimax`),{pluginSystem:n,warnings:r}=await Di({dataDir:e.dataDir,pluginsConfig:e.pluginsConfig,shouldInitialize:!!(e.requirePluginSystem||e.provider||e.providerPlugin)}),i=n?.normalizedConfig.slots.memory,a=e.providerPlugin?.trim()||(e.provider?void 0:i),o=se({providerId:e.provider,pluginId:a,dataDir:e.dataDir,memoryDir:t,includeSessions:e.includeSessions});return o.providerSource===`plugin`?{provider:o.provider,providerId:o.providerId,pluginId:o.pluginId,providerOrigin:`plugin`,warnings:r,pluginSystem:n}:((a||e.provider)&&r.push(`requested memory provider was not resolved; falling back to builtin provider`),{provider:o.provider,providerId:`builtin`,providerOrigin:`builtin`,warnings:r,pluginSystem:n})}function ki(e,t,n){let r={...e.custom??{},providerSource:t.providerOrigin,providerId:t.providerId,pluginId:t.pluginId,cliWarnings:t.warnings},i={...e,custom:r};return n&&t.providerOrigin===`plugin`?i.custom={...r,note:`deep probe details are provider-defined for plugin memory providers`}:n&&(i.custom={...r,note:`deep probe is only supported by builtin provider`}),i}function Ai(e){let t=e.command(`memory`).description(`Manage semantic memory indexing and search`),n=e=>e.option(`--plugins-config <path>`,`Plugins config file path`);n(t.command(`status`)).description(`Show memory index status`).requiredOption(`-d, --data-dir <path>`,`Data directory path`).option(`--deep`,`Probe embedding/vector availability`).option(`--index`,`Run a refresh before reporting status`).option(`--include-sessions`,`Include session transcripts in indexing`).option(`--provider <id>`,`Memory provider id`).option(`--provider-plugin <id>`,`Memory provider plugin id`).option(`--verbose`,`Verbose output`).option(`--output <format>`,`Output format: text (default) or json`,`text`).option(`--encrypt-sessions`,`Enable gocryptfs-backed encryption for the .aimax data directory`).action(async e=>{let t=e.output===`json`?`json`:`text`;try{await W(e.dataDir,e,async()=>{let n=await Oi({dataDir:e.dataDir,provider:e.provider,providerPlugin:e.providerPlugin,pluginsConfig:e.pluginsConfig,includeSessions:e.includeSessions});e.index&&n.provider.sync&&await n.provider.sync(`cli-status`);let r=ki(n.provider.status(),n,e.deep);I(t===`json`?JSON.stringify(r,null,2):wi(r,e.deep))})}catch(e){L(`Error getting memory status: ${e.message}`),process.exit(1)}}),n(t.command(`index`)).description(`Reindex memory files`).requiredOption(`-d, --data-dir <path>`,`Data directory path`).option(`--include-sessions`,`Include session transcripts in indexing`).option(`--provider <id>`,`Memory provider id`).option(`--provider-plugin <id>`,`Memory provider plugin id`).option(`--rebuild`,`Force full rebuild from Markdown source`).option(`--verbose`,`Verbose output`).option(`--encrypt-sessions`,`Enable gocryptfs-backed encryption for the .aimax data directory`).action(async e=>{try{await W(e.dataDir,e,async()=>{let t=await Oi({dataDir:e.dataDir,provider:e.provider,providerPlugin:e.providerPlugin,pluginsConfig:e.pluginsConfig,includeSessions:e.includeSessions}),n;if(t.provider.sync&&(await t.provider.sync(e.rebuild?`cli-rebuild`:`cli-index`),n=t.provider.status().custom?.lastRebuildSummary),t.warnings.length>0)for(let e of t.warnings)L(`Warning: ${e}`);e.verbose&&n&&I(JSON.stringify(n,null,2)),I(e.rebuild?`Memory index rebuilt.`:`Memory index refreshed.`)})}catch(e){L(`Error indexing memory: ${e.message}`),process.exit(1)}}),n(t.command(`search [query]`)).description(`Search semantic memory`).requiredOption(`-d, --data-dir <path>`,`Data directory path`).option(`--query <text>`,`Search query`).option(`--include-sessions`,`Include session transcripts in search`).option(`--provider <id>`,`Memory provider id`).option(`--provider-plugin <id>`,`Memory provider plugin id`).option(`--output <format>`,`Output format: text (default) or json`,`text`).option(`--encrypt-sessions`,`Enable gocryptfs-backed encryption for the .aimax data directory`).action(async(e,t)=>{let n=t.output===`json`?`json`:`text`,r=t.query?.trim()||e?.trim();r||(L(`Query is required: provide [query] or --query <text>`),process.exit(1));try{await W(t.dataDir,t,async()=>{let e=await(await Oi({dataDir:t.dataDir,provider:t.provider,providerPlugin:t.providerPlugin,pluginsConfig:t.pluginsConfig,includeSessions:t.includeSessions})).provider.search(r);if(n===`json`){I(JSON.stringify(e,null,2));return}if(e.length===0){I(`No results found for: ${r}`);return}I(e.map(e=>{let t=`${e.path}:${e.startLine}-${e.endLine} (${e.score.toFixed(4)}) ${e.snippet}`;return e.citation?`${t}\n${e.citation}`:t}).join(`
|
|
13
|
-
`))})}catch(e){L(`Error searching memory: ${e.message}`),process.exit(1)}}),n(t.command(`dream`)).description(`Trigger Dream Gate host hook for memory plugins`).requiredOption(`-d, --data-dir <path>`,`Data directory path`).option(`--provider <id>`,`Memory provider id`).option(`--provider-plugin <id>`,`Memory provider plugin id`).option(`--trigger <mode>`,`Dream Gate trigger mode: cli (default) or cron`,`cli`).option(`--dry-run`,`Return hook results without plugin-side mutation`).option(`--output <format>`,`Output format: text (default) or json`,`text`).option(`--encrypt-sessions`,`Enable gocryptfs-backed encryption for the .aimax data directory`).action(async e=>{let t=e.output===`json`?`json`:`text`;try{await W(e.dataDir,e,async()=>{let n=Ei(e.trigger),r=await Oi({dataDir:e.dataDir,provider:e.provider,providerPlugin:e.providerPlugin,pluginsConfig:e.pluginsConfig,requirePluginSystem:!0}),i=r.pluginSystem?await r.pluginSystem.registry.hooks.dispatch(`dream_gate`,{dataDir:e.dataDir,memoryDir:C.join(e.dataDir,`.aimax`),providerId:r.providerId,pluginId:r.pluginId,trigger:n,dryRun:!!e.dryRun},{workspaceDir:Si(e.dataDir)}):[],a={ok:!0,trigger:n,providerSource:r.providerOrigin,providerId:r.providerId,pluginId:r.pluginId,resultCount:i.length,results:i,warnings:r.warnings};if(t===`json`){I(JSON.stringify(a,null,2));return}I(`trigger: ${a.trigger}`),I(`provider_source: ${a.providerSource}`),I(`provider_id: ${a.providerId}`),a.pluginId&&I(`plugin_id: ${a.pluginId}`),I(`result_count: ${a.resultCount}`),a.results.length===0?I(`note: no dream_gate hook registered`):I(`results: ${JSON.stringify(a.results)}`);for(let e of a.warnings)I(`warning: ${e}`)})}catch(e){L(`Error running dream gate: ${e.message}`),process.exit(1)}})}function ji(e){return`${e.match.accountId?`${e.match.channel}:${e.match.accountId}`:e.match.channel} -> ${e.agentId}`}function Mi(e){return async t=>{let n=await k(t),r=Ie(n),i=Le(n);if(He(n),e.json){console.log(JSON.stringify({agents:r,bindings:i},null,2));return}console.log(`Agents:`);for(let e of r){let n=e.default?` (default)`:``,r=e.name&&e.name!==e.id?`${e.id}${n} (${e.name})`:`${e.id}${n}`;if(console.log(` - ${r}`),e.identity?.emoji||e.identity?.name){let t=[e.identity.emoji,e.identity.name].filter(Boolean).join(` `);console.log(` Identity: ${t}`)}let a=Ve(t,e.id);if(console.log(` Agent dir: ${a}`),e.model){let t=typeof e.model==`string`?e.model:e.model.primary;console.log(` Model: ${t}`)}let o=i.filter(t=>t.agentId===e.id);if(o.length>0){console.log(` Routing rules:`);for(let e of o)console.log(` - ${ji(e)}`)}}}}function Ni(e,t){return async n=>{O(await k(n),Re(e))&&(console.error(`Agent "${e}" already exists.`),process.exit(1)),await Pe(n,{id:e,name:t.name,model:t.model,default:t.default})||(console.error(`Agent "${e}" already exists.`),process.exit(1));let r=Ve(n,e);console.log(`Agent "${e}" added successfully.`),console.log(` Agent dir: ${r}`)}}function Pi(e){return async t=>{let n=O(await k(t),Re(e));n||(console.error(`Agent "${e}" not found.`),process.exit(1)),n.default===!0&&(console.error(`Cannot delete default agent "${e}".`),process.exit(1)),await ze(t,e)||(console.error(`Failed to delete agent "${e}".`),process.exit(1)),console.log(`Agent "${e}" deleted.`)}}function Fi(e){return async t=>{let n=await k(t),r=e.agent??He(n);O(n,r)||(console.error(`Agent "${r}" not found.`),process.exit(1)),(!e.bind||e.bind.length===0)&&(console.error(`Please specify --bind <channel>[:<account>]`),process.exit(1));for(let n of e.bind){let[e,...i]=n.split(`:`),a=i.join(`:`),o=[`H5`,`WEB`,`KLPA`,`TASK`,`CRON`,`EIP_ASSISTANT`];o.includes(e)||(console.error(`Invalid channel: ${e}`),console.error(`Valid channels: ${o.join(`, `)}`),process.exit(1)),await Fe(t,{agentId:r,match:{channel:e,accountId:a||void 0}}),console.log(`Binding added: ${n} -> ${r}`)}}}function Ii(e){return async t=>{let n=await k(t),r=e.agent??He(n);if(O(n,r)||(console.error(`Agent "${r}" not found.`),process.exit(1)),e.all){let e=await Be(t,r,`*`);console.log(`Removed ${e} binding(s) for agent "${r}".`)}else if(e.bind&&e.bind.length>0){let n=0;for(let i of e.bind){let[e,...a]=i.split(`:`),o=await Be(t,r,e,a.join(`:`)||void 0);o>0?(console.log(`Binding removed: ${i} -> ${r}`),n+=o):console.log(`No binding found: ${i} -> ${r}`)}}else console.error(`Please specify --bind <channel>[:<account>] or --all`),process.exit(1)}}function Li(e){return async t=>{let n=Le(await k(t));if(e.agent&&(n=n.filter(t=>t.agentId===e.agent)),e.json){console.log(JSON.stringify(n,null,2));return}if(n.length===0){console.log(`No bindings configured.`);return}console.log(`Routing bindings:`);for(let e of n)console.log(` ${ji(e)}`)}}function Ri(e){return async t=>{let n=await k(t),r=e.agent??He(n);O(n,r)||(console.error(`Agent "${r}" not found.`),process.exit(1)),await Ue(t,r,{name:e.name,emoji:e.emoji,avatar:e.avatar})||(console.error(`Failed to update identity for agent "${r}".`),process.exit(1)),console.log(`Identity updated for agent "${r}".`)}}function zi(e,t){let n=e.command(`agents`).description(`Manage agents`),r=e=>e.option(`--encrypt-sessions`,`Enable gocryptfs-backed encryption for the .aimax data directory`);r(n.command(`list`).description(`List all configured agents`).option(`-j, --json`,`Output as JSON`).option(`-b, --bindings`,`Show detailed binding rules`)).action(async e=>{let n=t();await W(n,e,async()=>{await Mi(e)(n)})}),r(n.command(`add <id>`).description(`Add a new agent`).option(`-n, --name <name>`,`Display name`).option(`-m, --model <model>`,`Model identifier`).option(`--default`,`Mark as default agent`)).action(async(e,n)=>{let r=t();await W(r,n,async()=>{await Ni(e,n)(r)})}),r(n.command(`delete <id>`).description(`Delete an agent`)).action(async(e,n)=>{let r=t();await W(r,n,async()=>{await Pi(e)(r)})}),r(n.command(`bind`).description(`Bind a channel to an agent`).option(`-a, --agent <id>`,`Target agent ID`).option(`-b, --bind <channel...>`,`Channel binding (e.g., WEB, KLPA:ops)`)).action(async e=>{let n=t();await W(n,e,async()=>{await Fi(e)(n)})}),r(n.command(`unbind`).description(`Unbind a channel from an agent`).option(`-a, --agent <id>`,`Target agent ID`).option(`-b, --bind <channel...>`,`Channel binding to remove`).option(`--all`,`Remove all bindings for the agent`)).action(async e=>{let n=t();await W(n,e,async()=>{await Ii(e)(n)})}),r(n.command(`bindings`).description(`List routing bindings`).option(`-a, --agent <id>`,`Filter by agent ID`).option(`-j, --json`,`Output as JSON`)).action(async e=>{let n=t();await W(n,e,async()=>{await Li(e)(n)})}),r(n.command(`set-identity`).description(`Set agent identity`).option(`-a, --agent <id>`,`Target agent ID`).option(`-n, --name <name>`,`Agent name`).option(`-e, --emoji <emoji>`,`Agent emoji`).option(`--avatar <path>`,`Avatar path`)).action(async e=>{let n=t();await W(n,e,async()=>{await Ri(e)(n)})})}function X(e){return C.join(e,`workspace`)}function Z(){let e=process.env.AIMAX_PLUGINS_BUNDLED_DIR;return e&&e.trim()||void 0}function Bi(e){if(e.length===0){I(`No plugins discovered.`);return}for(let t of e){let e=t.status.padEnd(8,` `);I(`${t.id} ${e} ${t.origin} ${t.source}`)}}function Vi(e){I(`id: ${e.id}`),I(`status: ${e.status}`),I(`origin: ${e.origin}`),I(`source: ${e.source}`),I(`enabled: ${e.enabled}`),e.error&&I(`error: ${e.error}`),I(`tools: ${e.toolCount}`),I(`hooks: ${e.hookCount}`),e.skills.length>0&&I(`skills: ${e.skills.join(`, `)}`)}function Hi(e){return Array.from(new Set((e??[]).map(e=>e.trim()).filter(Boolean)))}function Ui(e){if(e.length===0){I(`LLM allowlist is empty.`);return}for(let t of e)I(t)}function Wi(e,t){let n=e.command(`plugins`).description(`Manage AIMax plugins`),r=e=>e.option(`--plugins-config <path>`,`Plugins config file path`),i=e=>e.option(`--encrypt-sessions`,`Enable gocryptfs-backed encryption for the .aimax data directory`);i(r(n.command(`list`))).description(`List discovered plugins`).option(`-d, --data-dir <path>`,`Data directory path`).action(async e=>{let n=e.dataDir??t();await W(n,e,async()=>{Bi(h({config:await G(n,e.pluginsConfig),dataDir:n,workspaceDir:X(n),bundledDir:Z()}).registry.plugins)})}),i(r(n.command(`info`))).description(`Show plugin details`).argument(`<id>`,`Plugin id`).option(`-d, --data-dir <path>`,`Data directory path`).action(async(e,n)=>{let r=n.dataDir??t();await W(r,n,async()=>{let t=h({config:await G(r,n.pluginsConfig),dataDir:r,workspaceDir:X(r),bundledDir:Z()}).registry.plugins.find(t=>t.id===e);t||(L(`Plugin not found: ${e}`),process.exit(1)),Vi(t)})}),i(r(n.command(`enable`))).description(`Enable a plugin`).argument(`<id>`,`Plugin id`).option(`-d, --data-dir <path>`,`Data directory path`).action(async(e,n)=>{let r=n.dataDir??t();await W(r,n,async()=>{let t=await G(r,n.pluginsConfig)??{},i=ae(t);h({config:t,dataDir:r,workspaceDir:X(r),bundledDir:Z()}).registry.plugins.some(t=>t.id===e)||(L(`Plugin not found: ${e}`),process.exit(1)),await K(r,{...t,entries:{...t.entries,[e]:{...t.entries?.[e]??{},enabled:!0}}},n.pluginsConfig),I(`Enabled ${e}`),i.allow.length>0&&!i.allow.includes(e)&&I(`Note: plugins.allow is set; add this plugin id to allowlist if needed.`)})}),i(r(n.command(`disable`))).description(`Disable a plugin`).argument(`<id>`,`Plugin id`).option(`-d, --data-dir <path>`,`Data directory path`).action(async(e,n)=>{let r=n.dataDir??t();await W(r,n,async()=>{let t=await G(r,n.pluginsConfig)??{};h({config:t,dataDir:r,workspaceDir:X(r),bundledDir:Z()}).registry.plugins.some(t=>t.id===e)||(L(`Plugin not found: ${e}`),process.exit(1)),await K(r,{...t,entries:{...t.entries,[e]:{...t.entries?.[e]??{},enabled:!1}}},n.pluginsConfig),I(`Disabled ${e}`)})}),i(r(n.command(`doctor`))).description(`Validate plugin configuration`).option(`-d, --data-dir <path>`,`Data directory path`).action(async e=>{let n=e.dataDir??t();await W(n,e,async()=>{let t=h({config:await G(n,e.pluginsConfig),dataDir:n,workspaceDir:X(n),bundledDir:Z()});if(t.diagnostics.length===0){I(`No plugin issues detected.`);return}for(let e of t.diagnostics)I(`${e.level===`error`?`ERROR`:`WARN`}${e.pluginId?` ${e.pluginId}`:``}: ${e.message}`);t.diagnostics.some(e=>e.level===`error`)&&process.exit(1)})});let a=n.command(`llm-allow`).description(`Manage plugin LLM allowlist`);i(r(a.command(`list`))).description(`List LLM allowlist entries`).option(`-d, --data-dir <path>`,`Data directory path`).action(async e=>{let n=e.dataDir??t();await W(n,e,async()=>{Ui(Hi((await G(n,e.pluginsConfig))?.llmAllowlist))})}),i(r(a.command(`add`))).description(`Add entries to the LLM allowlist (plugin id or tool name)`).argument(`<entry...>`,`Plugin id or tool name`).option(`-d, --data-dir <path>`,`Data directory path`).action(async(e,n)=>{let r=n.dataDir??t();await W(r,n,async()=>{let t=await G(r,n.pluginsConfig)??{},i=Hi([...t.llmAllowlist??[],...e]);await K(r,{...t,llmAllowlist:i},n.pluginsConfig),I(`LLM allowlist updated (${i.length} entries).`)})}),i(r(a.command(`remove`))).description(`Remove entries from the LLM allowlist`).argument(`<entry...>`,`Plugin id or tool name`).option(`-d, --data-dir <path>`,`Data directory path`).action(async(e,n)=>{let r=n.dataDir??t();await W(r,n,async()=>{let t=await G(r,n.pluginsConfig)??{},i=new Set(e.map(e=>e.trim()).filter(Boolean)),a=Hi(t.llmAllowlist).filter(e=>!i.has(e));await K(r,{...t,llmAllowlist:a},n.pluginsConfig),I(`LLM allowlist updated (${a.length} entries).`)})}),i(r(a.command(`clear`))).description(`Clear the LLM allowlist`).option(`-d, --data-dir <path>`,`Data directory path`).action(async e=>{let n=e.dataDir??t();await W(n,e,async()=>{await K(n,{...await G(n,e.pluginsConfig)??{},llmAllowlist:[]},e.pluginsConfig),I(`LLM allowlist cleared.`)})})}function Gi(e){e.command(`commands`).description(`List available slash commands for a data directory`).requiredOption(`-d, --data-dir <path>`,`Data directory path`).option(`--output <format>`,`Output format: text (default) or json`,`text`).option(`--encrypt-sessions`,`Enable gocryptfs-backed encryption for the .aimax data directory`).action(async e=>{let t=e.output===`json`?`json`:`text`;try{await W(e.dataDir,e,async()=>{let n=_(await re(e.dataDir,[]));if(t===`json`){I(JSON.stringify(n,null,2));return}I(`Commands`),I(` builtin: ${n.builtin.map(e=>e.name).join(` | `)}`),n.skillCommands.length>0?I(` skills: ${n.skillCommands.map(e=>e.name).join(` | `)}`):I(` skills: (none)`)})}catch(e){L(`Error listing commands: ${e.message}`),process.exit(1)}})}function Q(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 $(e){if(!e.sessionId)throw Error(`Session ID is required (--session-id or -s)`);return e.sessionId}function Ki(e){return e?y(e):void 0}async function qi(e){let t={storeName:e.sessionStoreName},n=e.objective.trim(),r=await b(e.dataDir,e.sessionId,t);if(!r||(await oe(e.dataDir,e.sessionId,r,t)).trim()!==n)return he(e.dataDir,e.sessionId,{goalId:Ge(),objective:n,status:`active`,tokenBudget:e.tokenBudget??null,tokensUsed:0,timeUsedSeconds:0},{...t,eventSource:`cli`});if(r.status===`complete`)return r;let i={};return r.status===`paused`&&(i.status=`active`),e.tokenBudget!==void 0&&e.tokenBudget!==r.tokenBudget&&(i.tokenBudget=e.tokenBudget),Object.keys(i).length===0?r:await me(e.dataDir,e.sessionId,i,{...t,eventSource:`cli`})}async function Ji(e,t){let n=Q(t),r=$(t),i=Ki(t.sessionStore),a=e.trim();a||(L(`error: objective cannot be empty`),process.exit(1));let o=t.tokenBudget===void 0||t.tokenBudget===`0`||t.tokenBudget===``?null:Number(t.tokenBudget);o!==null&&(Number.isNaN(o)||o<=0)&&(L(`error: --token-budget must be a positive integer, or 0 for unlimited`),process.exit(1));let s=await qi({dataDir:n,sessionId:r,sessionStoreName:i,objective:a,tokenBudget:o});I(JSON.stringify({goal:s},null,2))}async function Yi(e){let t=Q(e),n=$(e),r=Ki(e.sessionStore),i=await b(t,n,{storeName:r});if(!i){I(JSON.stringify({goal:null},null,2));return}let a=await oe(t,n,i,{storeName:r});I(JSON.stringify({goal:{...i,objective:a}},null,2))}async function Xi(e){let t=Q(e),n=$(e),r=Ki(e.sessionStore),i=await b(t,n,{storeName:r});i||(L(`error: no goal exists for this session`),process.exit(1)),i.status===`complete`&&(L(`error: cannot pause a completed goal`),process.exit(1));let a=await me(t,n,{status:`paused`},{storeName:r,eventSource:`cli`});I(JSON.stringify({goal:a},null,2))}async function Zi(e){let t=Q(e),n=$(e),r=Ki(e.sessionStore),i=await b(t,n,{storeName:r});if(i||(L(`error: no goal exists for this session`),process.exit(1)),i.status===`complete`&&(L(`error: cannot resume a completed goal`),process.exit(1)),i.status===`budget_limited`&&(L(`error: cannot resume a budget-limited goal; clear or replace it instead`),process.exit(1)),i.status===`active`){I(JSON.stringify({goal:i},null,2));return}let a=await me(t,n,{status:`active`},{storeName:r,eventSource:`cli`});I(JSON.stringify({goal:a},null,2))}async function Qi(e){let t=await c(Q(e),$(e),{storeName:Ki(e.sessionStore),eventSource:`cli`});I(JSON.stringify({cleared:t},null,2))}function $i(e){let t=e.command(`goal`).description(`Manage thread goals for a session`).addHelpText(`after`,a());t.command(`set <objective>`).description(`Set or replace the thread goal (creates new goalId)`).option(`-d, --data-dir <path>`,`Data directory path (overrides AIMAX_DATA_DIR)`).requiredOption(`-s, --session-id <id>`,`Session ID`).option(`--session-store <name>`,`Session store directory under .aimax (default: sessions)`).option(`--token-budget <n>`,`Optional token budget (positive integer, or 0 for unlimited)`).action(async(e,t)=>{try{await Ji(e,t)}catch(e){L(`error: ${e.message}`),process.exit(1)}}),t.command(`get`).description(`Get the current goal as JSON`).option(`-d, --data-dir <path>`,`Data directory path (overrides AIMAX_DATA_DIR)`).requiredOption(`-s, --session-id <id>`,`Session ID`).option(`--session-store <name>`,`Session store directory under .aimax (default: sessions)`).action(async e=>{try{await Yi(e)}catch(e){L(`error: ${e.message}`),process.exit(1)}}),t.command(`pause`).description(`Pause the current goal`).option(`-d, --data-dir <path>`,`Data directory path (overrides AIMAX_DATA_DIR)`).requiredOption(`-s, --session-id <id>`,`Session ID`).option(`--session-store <name>`,`Session store directory under .aimax (default: sessions)`).action(async e=>{try{await Xi(e)}catch(e){L(`error: ${e.message}`),process.exit(1)}}),t.command(`resume`).description(`Resume a paused goal`).option(`-d, --data-dir <path>`,`Data directory path (overrides AIMAX_DATA_DIR)`).requiredOption(`-s, --session-id <id>`,`Session ID`).option(`--session-store <name>`,`Session store directory under .aimax (default: sessions)`).action(async e=>{try{await Zi(e)}catch(e){L(`error: ${e.message}`),process.exit(1)}}),t.command(`clear`).description(`Clear the current goal`).option(`-d, --data-dir <path>`,`Data directory path (overrides AIMAX_DATA_DIR)`).requiredOption(`-s, --session-id <id>`,`Session ID`).option(`--session-store <name>`,`Session store directory under .aimax (default: sessions)`).action(async e=>{try{await Qi(e)}catch(e){L(`error: ${e.message}`),process.exit(1)}})}const ea=[`progress`,`error`,`hitl`];function ta(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 na(e){if(!e?.trim())return new Set(ea);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(ea)}function ra(e){return e?y(e):void 0}function ia(e){let t=[];return e.callbackUrl&&t.push(new Nn(e.callbackUrl)),e.streamUrl&&t.push(new Hn(e.streamUrl,na(e.streamEvents),e.streamAuthToken)),new Mn(t)}async function aa(e){let t=ta(e);await W(t,e,async()=>{P(t,{messageId:e.messageId});let n=new dt(`cancel command`),r=e.channel??`WEB`,i=e.output===`json`?`json`:`text`,a=ia(e),o=ra(e.sessionStore);try{let s=await ee(t,e.sessionId,{storeName:o});if(!s)throw Error(`No pending HITL request found for session "${e.sessionId}"`);let c=e.requestId??s.request.requestId;if(s.request.requestId!==c)throw Error(`Request ID mismatch: pending is "${s.request.requestId}", got "${c}"`);if(!(await ce({dataDir:t,sessionStoreName:o,sessionId:e.sessionId,requestId:c,resolution:{requestId:c,sessionId:e.sessionId,action:`cancel`,submittedAt:new Date().toISOString(),submittedBy:{channel:r}}})).state)throw Error(`Failed to cancel HITL request`);let l={type:`hitl_cancelled`,sessionId:e.sessionId,requestId:c,reason:e.reason??`cancelled by operator`};i===`text`&&R(l),await a.send({type:`progress`,sessionId:e.sessionId,channel:r,messageId:e.messageId,event:l}),n.end(),process.exit(0)}catch(t){let i=t;await a.send({type:`error`,sessionId:e.sessionId,channel:r,messageId:e.messageId,message:i.message}),F.error(`cancel command error: ${i.message}`),L(`Fatal: ${i.message}`),n.end(),process.exit(1)}finally{await a.close()}})}function oa(e){e.command(`cancel`).description(`Cancel a pending HITL request`).requiredOption(`-d, --data-dir <path>`,`Data directory path`).requiredOption(`-s, --session-id <id>`,`Session ID containing the pending HITL request`).option(`--session-store <name>`,`Session store directory under .aimax (default: sessions)`).option(`--request-id <id>`,`HITL request ID to cancel`).option(`--reason <text>`,`Human-readable cancel reason`).option(`-c, --channel <channel>`,`Channel type (default: WEB)`,`WEB`).option(`--callback-url <url>`,`HTTP callback URL for progress events`).option(`--stream-url <url>`,`WebSocket URL for streaming text events`).option(`--stream-auth-token <token>`,`Auth token for WebSocket streaming`).option(`--stream-events <list>`,`Comma-separated stream events`).option(`--message-id <id>`,`Message ID for correlating events`).option(`--output <format>`,`Output format: text (default) or json`,`text`).option(`--encrypt-sessions`,`Enable gocryptfs-backed encryption for the .aimax data directory`).action(async e=>{await aa(e)})}function sa(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 ca(e){return e.query?.trim()||void 0}function la(e){if(!e)return;let t=Number(e);if(!Number.isFinite(t)||t<=0)throw Error(`--timeout must be a positive number of milliseconds`);return t}function ua(e){if(!e)return;let t=Number(e);if(!Number.isInteger(t)||t<=0)throw Error(`--max-tokens must be a positive integer`);return t}async function da(e){if(e.filePath){if(!C.isAbsolute(e.filePath))throw Error(`--file-path must be an absolute path`);try{await D.access(e.filePath)}catch(e){throw Error(`Failed to access --file-path: ${e.message}`)}return{source:`file`,filePath:e.filePath}}let t=e.content;if(!t||!t.trim())throw Error(`Either --file-path or --content must be provided`);return{source:`content`,content:t}}async function fa(e){let t=null;try{let n=sa(e);P(n,{messageId:e.messageId}),t=new dt(`summarize command`);let r=ca(e),i=await da(e),a=dn({apiFormat:e.apiFormat,baseUrl:e.baseUrl,apiKey:e.apiKey,model:e.model,contextWindow:2e5}),o=la(e.timeout),s=ua(e.maxTokens);F.info(`summarize command started`,{dataDir:n,source:i.source,filePath:i.source===`file`?i.filePath:void 0,queryLength:r?.length,contentLength:i.source===`content`?i.content.length:void 0,timeoutMs:o,maxTokens:s});let c=await de({dataDir:n,channel:`WEB`,messageId:e.messageId,message:pa(i,r),llm:{...a,maxTokens:s},timeoutMs:o});I(c.text.trim()),F.info(`summarize command succeeded`,{source:i.source,summaryLength:c.text.length,durationMs:c.durationMs}),t.end()}catch(e){F.error(`summarize command error: ${e.message}`),L(`Fatal: ${e.message}`),t?.end(),process.exit(1)}}function pa(e,t){return e.source===`file`?[t?`Summarize exactly one file for the query below.`:`Summarize exactly one file.`,`Read only the absolute file path provided here. Do not search, browse, read other files, execute commands, modify files, or perform any other processing.`,`Return only the summary text.`,``,...t?[`Query:\n${t}`,``]:[],`Input source: file`,`File path: ${e.filePath}`].join(`
|
|
14
|
-
`):[t?`Summarize the provided content for the query below.`:`Summarize the provided content.`,t?`Use only the provided content and query. Do not search, browse, read files, execute commands, modify files, or perform any other processing.`:`Use only the provided content. Do not search, browse, read files, execute commands, modify files, or perform any other processing.`,`Return only the summary text.`,``,...t?[`Query:\n${t}`,``]:[],`Input source: content`,`Source content:`,`<source>`,e.content,`</source>`].join(`
|
|
15
|
-
`)}function ma(e){e.command(`summarize`).description(`Summarize one absolute file path or inline content`).option(`--file-path <path>`,`Absolute file path to summarize`).option(`--content <text>`,`Inline text content to summarize when --file-path is not provided`).option(`--query <text>`,`Optional search target or current description to focus the summary`).option(`-d, --data-dir <path>`,`Data directory path (overrides AIMAX_DATA_DIR)`).option(`--base-url <url>`,`LLM API base URL (overrides AIMAX_BASE_URL)`).option(`--api-format <format>`,`LLM API format: openai-completions or anthropic-messages (overrides AIMAX_API_FORMAT)`).option(`--api-key <key>`,`LLM API key (overrides AIMAX_API_KEY)`).option(`--model <name>`,`LLM model name (overrides AIMAX_MODEL)`).option(`--timeout <ms>`,`Execution timeout in milliseconds`).option(`--max-tokens <number>`,`Maximum number of tokens for model output`).option(`--message-id <id>`,`Message ID for log correlation`).action(async e=>{await fa(e)})}const ha={accent:`#8abeb7`,border:`#5f87ff`,borderAccent:`#00d7ff`,borderMuted:`#505050`,success:`#b5bd68`,error:`#cc6666`,warning:`#ffff00`,muted:`#808080`,dim:`#666666`,text:`#d4d4d4`,thinkingText:`#808080`,selectedBg:`#3a3a4a`,userMessageBg:`#343541`,userMessageText:`#d4d4d4`,customMessageBg:`#2d2838`,customMessageText:`#d4d4d4`,customMessageLabel:`#9575cd`,toolPendingBg:`#282832`,toolSuccessBg:`#283228`,toolErrorBg:`#3c2828`,toolTitle:`#d4d4d4`,toolOutput:`#808080`,mdHeading:`#f0c674`,mdLink:`#81a2be`,mdLinkUrl:`#666666`,mdCode:`#8abeb7`,mdCodeBlock:`#b5bd68`,mdCodeBlockBorder:`#808080`,mdQuote:`#808080`,mdQuoteBorder:`#808080`,mdHr:`#808080`,mdListBullet:`#8abeb7`,toolDiffAdded:`#b5bd68`,toolDiffRemoved:`#cc6666`,toolDiffContext:`#808080`,syntaxComment:`#6A9955`,syntaxKeyword:`#569CD6`,syntaxFunction:`#DCDCAA`,syntaxVariable:`#9CDCFE`,syntaxString:`#CE9178`,syntaxNumber:`#B5CEA8`,syntaxType:`#4EC9B0`,syntaxOperator:`#D4D4D4`,syntaxPunctuation:`#D4D4D4`,thinkingOff:`#505050`,thinkingMinimal:`#6e6e6e`,thinkingLow:`#5f87af`,thinkingMedium:`#81a2be`,thinkingHigh:`#b294bb`,thinkingXhigh:`#d183e8`,bashMode:`#b5bd68`},ga=`#18181e`,_a=`#1e1e24`,va=`#3c3728`;function ya(e){if(!e||typeof e!=`object`)return!1;let t=e.role;return t===`user`||t===`assistant`||t===`tool_result`||t===`compaction`}function ba(e){return!e||typeof e!=`object`?!1:typeof e.type==`string`}function xa(e){return{type:`text`,text:e}}function Sa(e){return{type:`thinking`,thinking:e}}function Ca(e,t){let n=e.timestamp,r=typeof n==`string`&&n?n:e.content;return`${e.role}\0${r}\0${t}`}function wa(e,t,n){let r=Ca(e,t);for(let e=0;e<100;e++){let t=We(`sha256`).update(`${r}\0${e}`).digest(`hex`).slice(0,8);if(!n.has(t))return n.add(t),t}let i=We(`sha256`).update(`${r}\0fallback`).digest(`hex`);return n.add(i),i}function Ta(e,t){let n=new Set,r=null,i=[],a={type:`session`,version:3,id:t?.sessionId??Ge(),timestamp:e.find(e=>e.timestamp)?.timestamp??new Date().toISOString(),cwd:t?.cwd??process.cwd()};for(let[t,a]of e.entries()){let e=wa(a,t,n),o={id:e,parentId:r,timestamp:a.timestamp};if(a.role===`user`)i.push({type:`message`,...o,message:{role:`user`,content:[xa(a.content)]}});else if(a.role===`assistant`){let e=[];a.thinking?.trim()&&e.push(Sa(a.thinking.trim())),a.content.trim()&&e.push(xa(a.content));for(let t of a.toolCalls??[])e.push({type:`toolCall`,id:t.id,name:t.name,arguments:t.arguments});a.errorMessage&&e.push(xa(a.errorMessage)),i.push({type:`message`,...o,message:{role:`assistant`,content:e,...a.stopReason?{stopReason:a.stopReason}:{}}})}else if(a.role===`tool_result`){let e=a.content;a.toolResultRef?.preview&&!e.includes(a.toolResultRef.preview)&&(e=`${e}\n\nPreview:\n${a.toolResultRef.preview}`),a.toolResultRef?.storagePath&&(e=`${e}\n\n[Full output: ${a.toolResultRef.storagePath}]`),i.push({type:`message`,...o,message:{role:`toolResult`,toolCallId:a.toolCallId,toolName:a.toolName,content:[xa(e)],isError:a.isError}})}else a.role===`compaction`&&i.push({type:`compaction`,...o,summary:a.content,firstKeptEntryId:r??e,tokensBefore:0});r=e}return{header:a,entries:i,leafId:r}}function Ea(e,t){let n=e.trim().split(`
|
|
16
|
-
`).filter(e=>e.trim()),r=[],i=0;for(let e of n)try{r.push(JSON.parse(e))}catch{i+=1}if(r.length===0)return{data:Ta([],t),skippedLines:i};let a=r[0];if(ba(a)&&a.type===`session`){let e=a,t=r.slice(1).filter(ba);return{data:{header:e,entries:t,leafId:t.length>0?t[t.length-1].id:null},skippedLines:i}}if(r.every(ba)){let e=r;return{data:{header:{type:`session`,version:3,id:t?.sessionId??Ge(),timestamp:e[0]?.timestamp??new Date().toISOString(),cwd:t?.cwd??process.cwd()},entries:e,leafId:e.length>0?e[e.length-1].id:null},skippedLines:i}}return{data:Ta(r.filter(ya),t),skippedLines:i}}function Da(e){let t=e;for(;t!==w(t);){if(S(T(t,`package.json`)))return t;t=w(t)}throw Error(`Could not find @gencode/cli package root`)}function Oa(){let e=Da(w(Ne(import.meta.url))),t=[T(e,`dist`,`export-html`),T(e,`src`,`export-html`)];for(let e of t)if(S(T(e,`template.html`)))return e;throw Error(`export-html template directory not found under ${e}`)}function ka(e){let t=C.resolve(e),n=`${C.sep}.aimax${C.sep}`,r=t.indexOf(n);if(!(r<0))return t.slice(0,r)}function Aa(e){let t=C.dirname(C.resolve(e));return C.basename(t)}async function ja(e){let t=e.dataDir??(e.transcriptPath?ka(e.transcriptPath):void 0),n=e.sessionId??(e.transcriptPath?Aa(e.transcriptPath):void 0);return!t||!n?{}:ne(t,n,e.sessionPathOptions)}const Ma=new Map;function Na(e){let t=Ma.get(e);if(t!==void 0)return t;let n=Se(T(Oa(),e),`utf-8`);return Ma.set(e,n),n}function Pa(){let e=[];for(let[t,n]of Object.entries(ha))e.push(`--${t}: ${n};`);return e.push(`--exportPageBg: ${ga};`),e.push(`--exportCardBg: ${_a};`),e.push(`--exportInfoBg: ${va};`),e.join(`
|
|
17
|
-
`)}function Fa(e){return e.replace(/[&<>"']/g,e=>{switch(e){case`&`:return`&`;case`<`:return`<`;case`>`:return`>`;case`"`:return`"`;case`'`:return`'`;default:return e}})}function Ia(e){let t=Na(`template.html`),n=Na(`template.css`),r=Na(`template.js`),i=Buffer.from(JSON.stringify(e)).toString(`base64`),a=n.replace(`{{THEME_VARS}}`,Pa()).replace(`{{BODY_BG}}`,ga).replace(`{{CONTAINER_BG}}`,_a).replace(`{{INFO_BG}}`,va);return t.replace(`{{CSS}}`,a).replace(`{{JS}}`,r).replace(`{{SESSION_DATA}}`,i)}function La(e,t){return t||`aimax-session-${Te(e,`.jsonl`)}.html`}function Ra(e,t){return`Skipped ${t} malformed JSONL line(s) while exporting ${e}`}function za(e){for(let t of e)console.warn(t)}function Ba(e){return e.replace(/\\/g,`/`)}function Va(e){return e.replace(/[|\\{}()[\]^$+?.]/g,`\\$&`)}function Ha(e){let t=Ba(e),n=`^`;for(let e=0;e<t.length;e+=1){let r=t[e],i=t[e+1];if(r===`*`){i===`*`?t[e+2]===`/`?(n+=`(?:.*\\/)?`,e+=2):(n+=`.*`,e+=1):n+=`[^/]*`;continue}if(r===`?`){n+=`[^/]`;continue}n+=Va(r)}return n+=`$`,new RegExp(n)}function Ua(e){return/[*?[]/.test(e)}function Wa(e,t){let n=Ba(Ee(e)?E(e):E(t,e)).split(`/`),r=[];for(let e of n){if(Ua(e))break;r.push(e)}return E(r.join(`/`)||`/`)}async function Ga(e){let t;try{t=await D.readdir(e,{withFileTypes:!0})}catch(e){let t=e.code;if(t===`ENOENT`||t===`ENOTDIR`)return[];throw e}let n=[];for(let r of t){let t=T(e,r.name);if(r.isDirectory()){n.push(...await Ga(t));continue}r.isFile()&&n.push(t)}return n}async function Ka(e,t,n){let r=[];for await(let i of e(t,{cwd:n}))r.push(i);return r}async function qa(e,t){let n=E(t),r=Ee(e),i=Ha(Ba(r?E(e):e));return(await Ga(Wa(e,n))).map(e=>({file:e,candidate:Ba(r?E(e):De(n,e))})).filter(({candidate:e})=>i.test(e)).map(({file:e})=>r?E(e):Ba(De(n,e)))}async function Ja(e,t){let n=D.glob;return typeof n==`function`?Ka(n,e,t):qa(e,t)}async function Ya(e,t){if(t.options?.includeSnapshots===!1)return e;let n=await ja({dataDir:t.options?.dataDir,sessionId:t.options?.sessionId??e.header.id,transcriptPath:t.inputLabel,sessionPathOptions:t.options?.sessionPathOptions});return n.tools?.length?{...e,tools:n.tools}:e}async function Xa(e,t,n){let r=Ea(e,{sessionId:n?.sessionId,cwd:n?.cwd}),i=r.skippedLines>0?[Ra(t,r.skippedLines)]:[],a=r.data;a=await Ya(a,{inputLabel:t,options:n});let o=Ia(a),s=La(t,n?.outputPath);return we(s,o,`utf8`),{outputPath:s,warnings:i}}async function Za(e,t){if(!S(e))throw Error(`File not found: ${e}`);return Xa(Se(e,`utf-8`),e,t)}async function Qa(e,t){let n=await Za(e,t);return za(n.warnings),n.outputPath}async function $a(e,t,n){let r=pe(e,t,n);if(!S(r))throw Error(`Transcript not found: ${r}`);if((await ie(e,t,n)).length===0&&!Se(r,`utf-8`).trim())throw Error(`Nothing to export yet - transcript is empty`);let i=Se(r,`utf-8`),{outputPath:a,sessionId:o,cwd:s,dataDir:c,includeSnapshots:l,...u}=n??{};return Xa(i,r,{outputPath:n?.outputPath,sessionId:t,cwd:n?.cwd,dataDir:e,sessionPathOptions:u,includeSnapshots:n?.includeSnapshots})}async function eo(e,t,n){let r=await $a(e,t,n);return za(r.warnings),r.outputPath}function to(e,t){let n=t.map(t=>{let n=S(T(e,t.fileName))?Ce(T(e,t.fileName)):void 0,r=n?`${Math.round(n.size/1024)} KB`:``,i=t.sourcePath?`<span class="muted">${Fa(t.sourcePath)}</span>`:``;return`<tr><td><a href="${Fa(t.fileName)}">${Fa(t.sessionId)}</a></td><td>${r}</td><td>${i}</td></tr>`}).join(`
|
|
18
|
-
`),r=`<!DOCTYPE html>
|
|
19
|
-
<html lang="zh-CN">
|
|
20
|
-
<head>
|
|
21
|
-
<meta charset="UTF-8">
|
|
22
|
-
<title>AIMax Session Exports</title>
|
|
23
|
-
<style>
|
|
24
|
-
body { font-family: system-ui, sans-serif; margin: 2rem; background: #18181e; color: #d4d4d4; }
|
|
25
|
-
table { border-collapse: collapse; width: 100%; }
|
|
26
|
-
th, td { text-align: left; padding: 0.5rem 0.75rem; border-bottom: 1px solid #333; }
|
|
27
|
-
a { color: #81a2be; }
|
|
28
|
-
.muted { color: #808080; font-size: 0.85em; }
|
|
29
|
-
</style>
|
|
30
|
-
</head>
|
|
31
|
-
<body>
|
|
32
|
-
<h1>AIMax Session Exports (${t.length})</h1>
|
|
33
|
-
<table>
|
|
34
|
-
<thead><tr><th>Session</th><th>Size</th><th>Source</th></tr></thead>
|
|
35
|
-
<tbody>
|
|
36
|
-
${n}
|
|
37
|
-
</tbody>
|
|
38
|
-
</table>
|
|
39
|
-
</body>
|
|
40
|
-
</html>`,i=T(e,`index.html`);return we(i,r,`utf8`),i}async function no(e,t,n){xe(t,{recursive:!0});let r=fe(e,n),i=[],a=[],o=[],s=[],c;try{c=await D.readdir(r)}catch(e){throw e.code===`ENOENT`?Error(`Sessions directory not found: ${r}`):e}for(let r of c.sort()){let c=pe(e,r,n);if(!S(c)){a.push({sessionId:r,reason:`no transcript.jsonl`});continue}try{let a=T(t,`${r}.html`),l=await $a(e,r,{...n,outputPath:a});o.push(...l.warnings),i.push({sessionId:r,path:l.outputPath}),s.push({sessionId:r,fileName:`${r}.html`,sourcePath:c})}catch(e){a.push({sessionId:r,reason:e.message})}}let l;return n?.writeIndex!==!1&&s.length>0&&(l=to(t,s)),{exported:i,skipped:a,warnings:o,indexPath:l}}async function ro(e,t,n){xe(t,{recursive:!0});let r=[],i=[],a=[],o=[],s=[];if(s.push(...await Ja(e,process.cwd())),s.sort(),s.length===0)throw Error(`No files matched glob: ${e}`);for(let e of s){let n=E(e),s=Te(w(n));if(!S(n)){i.push({sessionId:s,reason:`file missing`});continue}try{let e=await Za(n,{outputPath:T(t,`${s}.html`),sessionId:s,dataDir:ka(n)});a.push(...e.warnings),r.push({sessionId:s,path:e.outputPath}),o.push({sessionId:s,fileName:`${s}.html`,sourcePath:n})}catch(e){i.push({sessionId:s,reason:e.message})}}let c;return n?.writeIndex!==!1&&o.length>0&&(c=to(t,o)),{exported:r,skipped:i,warnings:a,indexPath:c}}function io(e){e.command(`export-html`).description(`Export transcript.jsonl to standalone HTML files for browsing`).argument(`[transcript]`,`Path to transcript.jsonl (or use -d/-s, --all, or --glob)`).option(`-d, --data-dir <path>`,`Data directory containing .aimax/sessions`).option(`-s, --session-id <id>`,`Session ID under the data directory`).option(`--session-store <name>`,`Session store under .aimax (default: sessions)`).option(`-o, --output <path>`,`Output HTML path for a single export`).option(`--output-dir <path>`,`Output directory for batch export`).option(`--all`,`Export all sessions under --data-dir (requires --output-dir)`).option(`--glob <pattern>`,`Export transcripts matching a glob (requires --output-dir)`).option(`--no-index`,`Skip writing index.html in batch mode`).option(`--encrypt-sessions`,`Enable gocryptfs-backed encryption for the .aimax data directory`).action(async(e,t,n)=>{let r=n.opts();try{if(r.glob){r.outputDir||(L(`error: --glob requires --output-dir`),process.exit(1)),oo(await ro(r.glob,E(r.outputDir),{writeIndex:!r.noIndex}));return}if(r.all){(!r.dataDir||!r.outputDir)&&(L(`error: --all requires --data-dir and --output-dir`),process.exit(1)),await W(r.dataDir,r,async()=>{let e=r.sessionStore?y(r.sessionStore):void 0;oo(await no(r.dataDir,E(r.outputDir),{storeName:e,writeIndex:!r.noIndex}))});return}if(e){let t=E(e);S(t)||(L(`File not found: ${t}`),process.exit(1)),r.outputDir&&xe(E(r.outputDir),{recursive:!0});let n=await Qa(t,{outputPath:r.outputDir?T(E(r.outputDir),`${Te(w(t))}.html`):r.output});console.log(n);return}(!r.dataDir||!r.sessionId)&&(L(`error: specify <transcript.jsonl>, --glob, (-d --all --output-dir), or (-d -s)`),process.exit(1)),ao(r.sessionId),await W(r.dataDir,r,async()=>{let e=r.sessionStore?y(r.sessionStore):void 0;r.outputDir&&xe(E(r.outputDir),{recursive:!0});let t=r.outputDir?E(r.outputDir,`${r.sessionId}.html`):r.output,n=await eo(r.dataDir,r.sessionId,{outputPath:t,storeName:e});console.log(n)})}catch(e){L(`Error exporting HTML: ${e.message}`),process.exit(1)}})}function ao(e){if(e.includes(`..`)||e.startsWith(`/`))throw Error(`Invalid session id: ${e}`)}function oo(e){for(let t of e.exported)console.log(t.path);for(let t of e.warnings??[])L(`warning: ${t}`);for(let t of e.skipped)L(`skipped ${t.sessionId}: ${t.reason}`);e.indexPath&&console.log(e.indexPath),console.log(`exported ${e.exported.length}, skipped ${e.skipped.length}`)}const so=e(import.meta.url)(`../package.json`);function co(){return process.env.AIMAX_DATA_DIR||process.cwd()}function lo(){let e=new t;return e.name(`aimax`).description(`AIMax CLI — runs agent tasks in a containerized environment`).version(so.version),bi(e),xr(e),$i(e),oa(e),xi(e),io(e),ma(e),Gi(e),on(e),Ai(e),zi(e,co),Wi(e,co),e}export{F as a,P as i,co as n,lt as o,vi as r,lo as t};
|