@robota-sdk/agent-session 3.0.0-beta.65 → 3.0.0-beta.66

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/CHANGELOG.md CHANGED
@@ -1,5 +1,11 @@
1
1
  # @robota-sdk/agent-session
2
2
 
3
+ ## 3.0.0-beta.66
4
+
5
+ ### Patch Changes
6
+
7
+ - @robota-sdk/agent-core@3.0.0-beta.66
8
+
3
9
  ## 3.0.0-beta.65
4
10
 
5
11
  ### Patch Changes
@@ -1,6 +1,6 @@
1
- Object.defineProperty(exports,Symbol.toStringTag,{value:`Module`});let e=require(`@robota-sdk/agent-core`),t=require(`node:crypto`),n=require(`node:fs`),r=require(`node:path`),i=require(`fs`),a=require(`path`);const o=`unknown_tool`;function s(e){return{knownToolNames:new Set(e.knownToolNames),unknownToolCallIds:new Set,...e.onToolExecution&&{onToolExecution:e.onToolExecution}}}function c(e,t,n){if(e.onToolExecution){if(t===`tool_execution_request`){l(e,n);return}t===`tool_execution_result`&&u(e,n)}}function l(e,t){let n=f(t.toolName),r=f(t.toolCallId);!n||!r||e.knownToolNames.has(n)||(e.unknownToolCallIds.add(r),e.onToolExecution?.({type:`start`,toolName:n,toolArgs:d(t.parameters)}))}function u(e,t){let n=f(t.toolName),r=f(t.toolCallId);if(!n||!r)return;let i=p(t.metadata);if(!(e.unknownToolCallIds.has(r)||i?.errorCode===o))return;e.unknownToolCallIds.delete(r);let a=f(t.error)??`Tool "${n}" is not registered.`;e.onToolExecution?.({type:`end`,toolName:n,success:!1,toolResultData:JSON.stringify({success:!1,error:a,errorCode:o,requestedTool:f(i?.requestedTool)??n,availableTools:m(i?.availableTools)})})}function d(e){let t=p(e);if(!t)return;let n={};for(let[e,r]of Object.entries(t))(typeof r==`string`||typeof r==`number`||typeof r==`boolean`||typeof r==`object`&&r)&&(n[e]=r);return n}function f(e){return typeof e==`string`&&e.length>0?e:void 0}function p(e){return typeof e==`object`&&e&&!Array.isArray(e)?e:void 0}function m(e){return Array.isArray(e)?e.filter(e=>typeof e==`string`):[]}async function h(t,n,r,i){if(r.contextTracker.updateFromHistory(r.robota.getHistory()),r.contextTracker.shouldAutoCompact()){let e=r.aiProvider,t=e.onTextDelta;e.onTextDelta=void 0;try{await r.compact()}finally{e.onTextDelta=t}}r.log(`user`,{content:t});let a=await(0,e.runHooks)(r.hooks,`UserPromptSubmit`,{session_id:r.sessionId,cwd:r.cwd,hook_event_name:`UserPromptSubmit`,user_message:n??t,prompt:n??t,...r.permissionMode!==void 0&&{permission_mode:r.permissionMode},...r.transcriptPath!==void 0&&{transcript_path:r.transcriptPath},env:{CLAUDE_PROJECT_DIR:r.cwd,CLAUDE_SESSION_ID:r.sessionId}},r.hookTypeExecutors),o=[r.sessionStartStdout,a.stdout].filter(Boolean).join(`
2
- `),l=o?`<system-reminder>\n${o}\n</system-reminder>\n${t}`:t;r.clearSessionStartStdout();let u=r.robota.getHistory(),d=JSON.stringify(u),f=(0,e.getProviderCapabilities)(r.aiProvider);r.log(`pre_run`,{historyLength:u.length,historyChars:d.length,historyEstTokens:Math.ceil(d.length/4),input:l,history:u,model:r.model,provider:r.aiProvider.name,maxTokens:r.contextTracker.getContextState().maxTokens,nativeWebSearchSupported:f.nativeWebTools.webSearch.supported,nativeWebSearchEnabled:f.nativeWebTools.webSearch.enabled,nativeWebFetchSupported:f.nativeWebTools.webFetch.supported,nativeWebFetchEnabled:f.nativeWebTools.webFetch.enabled}),r.contextTracker.updateFromHistory([...u,(0,e.createUserMessage)(l)]),r.onContextUpdate?.(r.contextTracker.getContextState());let p;try{let e=s({knownToolNames:r.knownToolNames??[],...r.onToolExecution&&{onToolExecution:r.onToolExecution}}),t=r.onTextDelta?e=>{r.log(`text_delta`,{delta:e}),r.onTextDelta?.(e)}:void 0;if(p=await r.robota.run(l,{signal:i,maxExecutionRounds:r.maxTurns??0,onExecutionEvent:(t,n)=>{r.log(t,n),c(e,t,n)},...t&&{onTextDelta:t}}),i.aborted)throw new DOMException(`Aborted`,`AbortError`)}catch(t){throw r.log(`error`,{message:t instanceof Error?t.message:String(t),stack:t instanceof Error?t.stack??``:``,historyLength:r.robota.getHistory().length}),(0,e.runHooks)(r.hooks,`StopFailure`,{session_id:r.sessionId,cwd:r.cwd,hook_event_name:`StopFailure`,reason:t instanceof Error?t.message:String(t),stop_hook_active:!1,...r.permissionMode!==void 0&&{permission_mode:r.permissionMode},...r.transcriptPath!==void 0&&{transcript_path:r.transcriptPath},env:{CLAUDE_PROJECT_DIR:r.cwd,CLAUDE_SESSION_ID:r.sessionId}},r.hookTypeExecutors).catch(()=>{}),t}let m=r.robota.getHistory(),h=m.map(e=>{let t=`toolCalls`in e&&Array.isArray(e.toolCalls)&&e.toolCalls.length>0,n=t?e.toolCalls.map(e=>e.function.name):[];return{role:e.role,contentLength:typeof e.content==`string`?e.content.length:0,hasToolCalls:t,toolCallNames:n,...e.metadata?{metadata:e.metadata}:{}}});r.log(`assistant`,{content:p,historyLength:m.length,estimatedChars:JSON.stringify(m).length,history:m,historyStructure:h}),r.contextTracker.updateFromHistory(m);let g=r.contextTracker.getContextState();return r.onContextUpdate?.(g),r.log(`context`,{maxTokens:g.maxTokens,usedTokens:g.usedTokens,usedPercentage:g.usedPercentage,remainingPercentage:g.remainingPercentage}),(0,e.runHooks)(r.hooks,`Stop`,{session_id:r.sessionId,cwd:r.cwd,hook_event_name:`Stop`,response:p.substring(0,500),last_assistant_message:p,stop_hook_active:!1,...r.permissionMode!==void 0&&{permission_mode:r.permissionMode},...r.transcriptPath!==void 0&&{transcript_path:r.transcriptPath},env:{CLAUDE_PROJECT_DIR:r.cwd,CLAUDE_SESSION_ID:r.sessionId}},r.hookTypeExecutors).catch(()=>{}),r.getSessionStore()&&r.persistSession(),p}async function g(t,n){let r=n.robota.getHistory();if(r.length===0)return;n.contextTracker.updateFromHistory(r);let i=n.contextTracker.getContextState(),a=r.filter(e=>e.role!==`system`),o=await n.compactionOrchestrator.compact(n.aiProvider,a,t);n.robota.clearHistory(),n.robota.injectMessage(`system`,n.systemMessage),n.robota.injectMessage(`assistant`,`[Context Summary]\n${o}`),n.contextTracker.updateFromHistory(n.robota.getHistory());let s={session_id:n.sessionId,cwd:n.cwd,hook_event_name:`PostCompact`,trigger:n.trigger,compact_summary:o};(0,e.runHooks)(n.hooks,`PostCompact`,s,n.hookTypeExecutors).catch(()=>{});let c=n.contextTracker.getContextState();n.log(`context_compact`,{trigger:n.trigger,before:i,after:c}),n.onCompactEventCallback?.({trigger:n.trigger,before:i,after:c}),n.onCompactCallback&&n.onCompactCallback(o)}function _(e){let t=e.robota.getHistory(),n=new Date().toISOString(),r=e.sessionStore.load(e.sessionId),i={id:e.sessionId,name:r?.name,cwd:e.cwd,createdAt:r?.createdAt??n,updatedAt:n,messages:t,history:e.getFullHistory(),systemPrompt:e.systemPrompt,toolSchemas:e.toolSchemas};e.sessionStore.save(i)}function v(e,t,n){e.configureNativeWebTools?.({webSearch:!0}),`onServerToolUse`in e&&(e.onServerToolUse=(e,t)=>{n(`server_tool`,{tool:e,...t})})}function y(t,n,r,i,a,o,s){(0,e.runHooks)(r,`SessionStart`,{session_id:t,cwd:n,hook_event_name:`SessionStart`,...o!==void 0&&{permission_mode:o},...s!==void 0&&{transcript_path:s},env:{CLAUDE_PROJECT_DIR:n,CLAUDE_SESSION_ID:t}},i).then(e=>{e.stdout&&a(e.stdout)}).catch(()=>{})}async function ee(t,n,r,i,a,o,s){await(0,e.runHooks)(i,`SessionEnd`,{session_id:t,cwd:n,hook_event_name:`SessionEnd`,reason:r,...o!==void 0&&{permission_mode:o},...s!==void 0&&{transcript_path:s},env:{CLAUDE_PROJECT_DIR:n,CLAUDE_SESSION_ID:t}},a)}var b=class{getPermissionMode(){return this.permissionMode}setPermissionMode(e){this.permissionMode=e}getSessionId(){return this.sessionId}getSystemMessage(){return this.systemMessage}updateSystemMessage(e){this.systemMessage=e,this.robota.setModel({provider:this.aiProvider.name,model:this.model,systemMessage:e})}getToolSchemas(){return this.toolSchemas}getMessageCount(){return this.messageCount}getSessionAllowedTools(){return this.permissionEnforcer.getSessionAllowedTools()}clearSessionAllowedTools(){this.permissionEnforcer.clearSessionAllowedTools()}abort(){this.abortController&&=(this.abortController.abort(),null)}isRunning(){return this.abortController!==null}getContextState(){return this.contextTracker.getContextState()}getAutoCompactThreshold(){return this.contextTracker.getAutoCompactThreshold()}setAutoCompactThreshold(e){this.contextTracker.setAutoCompactThreshold(e)}getHistory(){return this.robota.getHistory()}getFullHistory(){return this.robota.getFullHistory()}addHistoryEntry(e){this.robota.addHistoryEntry(e)}injectMessage(e,t,n){this.robota.injectMessage(e,t,n)}clearHistory(){this.robota.clearHistory(),this.contextTracker.reset()}};const x={success:!0,data:JSON.stringify({success:!1,output:``,error:`Permission denied. The user did not approve this action.`}),metadata:{}};function S(e){if(typeof e.data!=`string`||e.data.length<=3e4)return e;let t=15e3,n=e.data.substring(0,t),r=e.data.substring(e.data.length-t),i=`${n}\n\n[... output truncated: ${e.data.length.toLocaleString()} chars total, showing first and last ${t.toLocaleString()} chars ...]\n\n${r}`;return{...e,data:i}}function te(e,t,n,r,i,a){return{session_id:e,cwd:t,hook_event_name:`PreToolUse`,tool_name:n,tool_input:r,...i!==void 0&&{permission_mode:i},...a!==void 0&&{transcript_path:a}}}async function C(t,n,r){let i=await(0,e.runHooks)(t,`PreToolUse`,n,r);return i.blocked?{success:!0,data:JSON.stringify({blocked:!0,reason:i.reason??`Blocked by hook`}),metadata:{}}:null}function w(t,n,r,i){(0,e.runHooks)(t,`PostToolUse`,{...n,hook_event_name:`PostToolUse`,tool_output:typeof r.data==`string`?r.data:JSON.stringify(r.data)},i).catch(()=>{})}var T=class{sessionId;cwd;getPermissionMode;config;terminal;permissionHandler;promptForApprovalFn;sessionLogger;onToolExecution;hookTypeExecutors;transcriptPath;sessionAllowedTools=new Set;constructor(e){this.sessionId=e.sessionId,this.cwd=e.cwd,this.getPermissionMode=e.getPermissionMode,this.config=e.config,this.terminal=e.terminal,this.permissionHandler=e.permissionHandler,this.promptForApprovalFn=e.promptForApprovalFn,this.sessionLogger=e.sessionLogger,this.onToolExecution=e.onToolExecution,this.hookTypeExecutors=e.hookTypeExecutors,this.transcriptPath=e.transcriptPath}wrapTools(e){return e.map(e=>this.wrapToolWithPermission(e))}getSessionAllowedTools(){return[...this.sessionAllowedTools]}clearSessionAllowedTools(){this.sessionAllowedTools.clear()}wrapToolWithPermission(e){let t=this,n=e.execute.bind(e),r=Object.create(e);return r.execute=async(r,i)=>{try{let a=e.getName();t.log(`tool_call`,{tool:a,args:r});let o=te(t.sessionId,t.cwd,a,r,t.getPermissionMode(),t.transcriptPath),s=await C(t.config.hooks,o,t.hookTypeExecutors);if(s)return t.log(`tool_blocked`,{tool:a,reason:`hook`}),s;if(!await t.checkPermission(a,r))return t.log(`tool_denied`,{tool:a,reason:`permission`}),t.onToolExecution?.({type:`end`,toolName:a,toolArgs:r,success:!1,denied:!0}),x;t.onToolExecution?.({type:`start`,toolName:a,toolArgs:r});let c=await n(r,i),l=S(c);t.onToolExecution?.({type:`end`,toolName:a,toolArgs:r,success:l.success,toolResultData:typeof l.data==`string`?l.data:JSON.stringify(l.data)});let u=typeof l.data==`string`?l.data.length:JSON.stringify(l.data).length;return t.log(`tool_result`,{tool:a,success:l.success,dataChars:u,truncated:l!==c}),w(t.config.hooks,o,l,t.hookTypeExecutors),l}catch(e){let t=e instanceof Error?e.message:String(e);return{success:!0,data:JSON.stringify({success:!1,output:``,error:t}),metadata:{}}}},r}async checkPermission(t,n){let r=(0,e.evaluatePermission)(t,n,this.getPermissionMode(),{allow:this.config.permissions.allow,deny:this.config.permissions.deny});if(r===`auto`)return!0;if(r===`deny`)return!1;if(this.sessionAllowedTools.has(t))return!0;if(this.permissionHandler){let e=await this.permissionHandler(t,n);return e===`allow-session`?(this.sessionAllowedTools.add(t),!0):e}return this.promptForApprovalFn?this.promptForApprovalFn(this.terminal,t,n):!1}log(e,t){this.sessionLogger?.log(this.sessionId,e,t)}};const E=.835;var D=class{contextUsedTokens=0;contextMaxTokens;autoCompactThreshold;constructor(t,n,r){this.contextMaxTokens=n??(0,e.getModelContextWindow)(t),this.autoCompactThreshold=O(r)}getContextState(){let e=Math.min(100,this.contextUsedTokens/this.contextMaxTokens*100);return{maxTokens:this.contextMaxTokens,usedTokens:this.contextUsedTokens,usedPercentage:Math.round(e*100)/100,remainingPercentage:Math.round((100-e)*100)/100}}shouldAutoCompact(){return this.autoCompactThreshold===!1?!1:this.getContextState().usedPercentage>=this.autoCompactThreshold*100}getAutoCompactThreshold(){return this.autoCompactThreshold}setAutoCompactThreshold(e){this.autoCompactThreshold=O(e)}updateFromHistory(t){this.contextUsedTokens=(0,e.estimateContextTokensFromMessages)(t).usedTokens}reset(){this.contextUsedTokens=0}};function O(e){if(e===void 0)return E;if(e===!1)return!1;if(!Number.isFinite(e)||e<=0||e>1)throw RangeError(`autoCompactThreshold must be a number greater than 0 and at most 1.`);return e}var k=class{sessionId;cwd;model;hooks;compactInstructions;hookTypeExecutors;constructor(e){this.sessionId=e.sessionId,this.cwd=e.cwd,this.model=e.model,this.hooks=e.hooks,this.compactInstructions=e.compactInstructions,this.hookTypeExecutors=e.hookTypeExecutors}async compact(n,r,i){if(r.length===0)return``;let a=i===void 0?`auto`:`manual`,o={session_id:this.sessionId,cwd:this.cwd,hook_event_name:`PreCompact`,trigger:a};await(0,e.runHooks)(this.hooks,`PreCompact`,o,this.hookTypeExecutors);let s=this.buildCompactionPrompt(r,i),c=await n.chat([{id:(0,t.randomUUID)(),role:`user`,content:s,state:`complete`,timestamp:new Date}],{model:this.model});return typeof c.content==`string`?c.content:`(compaction failed)`}buildCompactionPrompt(e,t){let n=t??this.compactInstructions??``;return[`Summarize the following conversation concisely, preserving:`,`- User's original requests and goals`,`- Key decisions and conclusions`,`- Important code changes and file paths`,`- Current task status and next steps`,n?`\nAdditional focus:\n${n}\n`:``,`Drop verbose tool outputs, debugging steps, and exploratory work that didn't lead to results.`,``,`Conversation:`,e.map(e=>{let t=typeof e.content==`string`?e.content:JSON.stringify(e.content);return`${e.role}: ${t}`}).join(`
1
+ Object.defineProperty(exports,Symbol.toStringTag,{value:`Module`});let e=require(`@robota-sdk/agent-core`),t=require(`node:crypto`),n=require(`node:fs`),r=require(`node:path`),i=require(`fs`),a=require(`path`);var o=class{getPermissionMode(){return this.permissionMode}setPermissionMode(e){this.permissionMode=e}getSessionId(){return this.sessionId}getSystemMessage(){return this.systemMessage}updateSystemMessage(e){this.systemMessage=e,this.robota.setModel({provider:this.aiProvider.name,model:this.model,systemMessage:e})}getToolSchemas(){return this.toolSchemas}getMessageCount(){return this.messageCount}getSessionAllowedTools(){return this.permissionEnforcer.getSessionAllowedTools()}clearSessionAllowedTools(){this.permissionEnforcer.clearSessionAllowedTools()}abort(){this.abortController&&=(this.abortController.abort(),null)}isRunning(){return this.abortController!==null}getContextState(){return this.contextTracker.getContextState()}getAutoCompactThreshold(){return this.contextTracker.getAutoCompactThreshold()}setAutoCompactThreshold(e){this.contextTracker.setAutoCompactThreshold(e)}getHistory(){return this.robota.getHistory()}getFullHistory(){return this.robota.getFullHistory()}addHistoryEntry(e){this.robota.addHistoryEntry(e)}injectMessage(e,t,n){this.robota.injectMessage(e,t,n)}clearHistory(){this.robota.clearHistory(),this.contextTracker.reset()}},s=class{sessionId;cwd;model;hooks;compactInstructions;hookTypeExecutors;constructor(e){this.sessionId=e.sessionId,this.cwd=e.cwd,this.model=e.model,this.hooks=e.hooks,this.compactInstructions=e.compactInstructions,this.hookTypeExecutors=e.hookTypeExecutors}async compact(n,r,i){if(r.length===0)return``;let a=i===void 0?`auto`:`manual`,o={session_id:this.sessionId,cwd:this.cwd,hook_event_name:`PreCompact`,trigger:a};await(0,e.runHooks)(this.hooks,`PreCompact`,o,this.hookTypeExecutors);let s=this.buildCompactionPrompt(r,i),c=await n.chat([{id:(0,t.randomUUID)(),role:`user`,content:s,state:`complete`,timestamp:new Date}],{model:this.model});return typeof c.content==`string`?c.content:`(compaction failed)`}buildCompactionPrompt(e,t){let n=t??this.compactInstructions??``;return[`Summarize the following conversation concisely, preserving:`,`- User's original requests and goals`,`- Key decisions and conclusions`,`- Important code changes and file paths`,`- Current task status and next steps`,n?`\nAdditional focus:\n${n}\n`:``,`Drop verbose tool outputs, debugging steps, and exploratory work that didn't lead to results.`,``,`Conversation:`,e.map(e=>{let t=typeof e.content==`string`?e.content:JSON.stringify(e.content);return`${e.role}: ${t}`}).join(`
3
2
  `)].join(`
4
- `)}};function A(e,t,n,r,i){return new T({sessionId:t,cwd:n,getPermissionMode:r,config:{permissions:e.permissions??{allow:[],deny:[]},hooks:e.hooks},terminal:e.terminal,permissionHandler:e.permissionHandler,promptForApprovalFn:e.promptForApproval,sessionLogger:e.sessionLogger,onToolExecution:e.onToolExecution,hookTypeExecutors:e.hookTypeExecutors,transcriptPath:i})}function j(e,t,n,r){return{contextTracker:new D(t,e.contextMaxTokens,e.autoCompactThreshold),compactionOrchestrator:new k({sessionId:n,cwd:r,model:t,hooks:e.hooks,compactInstructions:e.compactInstructions,hookTypeExecutors:e.hookTypeExecutors})}}function M(t,n,r,i,a,o){let s=n.wrapTools(r);return new e.Robota({name:t.agentName??`agent`,aiProviders:[i],defaultModel:{provider:i.name,model:a,systemMessage:o},systemMessage:o,tools:s,logging:{enabled:!1},...t.providerTimeout!==void 0&&{timeout:t.providerTimeout}})}var N=class extends b{robota;permissionEnforcer;contextTracker;permissionMode;sessionId;aiProvider;toolSchemas;model;systemMessage;messageCount=0;abortController=null;terminal;sessionStore;cwd;hooks;hookTypeExecutors;onTextDeltaCallback;onContextUpdateCallback;onToolExecutionCallback;onCompactCallback;onCompactEventCallback;sessionLogger;maxTurns;compactionOrchestrator;shutdownPromise=null;sessionStartStdout=``;transcriptPath;constructor(t){super();let{tools:n,provider:r,systemMessage:i}=t;this.terminal=t.terminal,this.sessionStore=t.sessionStore,this.systemMessage=i,this.toolSchemas=n.map(e=>e.schema),this.cwd=process.cwd(),this.sessionLogger=t.sessionLogger,this.hooks=t.hooks,this.hookTypeExecutors=t.hookTypeExecutors,this.onTextDeltaCallback=t.onTextDelta,this.onContextUpdateCallback=t.onContextUpdate,this.onToolExecutionCallback=t.onToolExecution,this.onCompactCallback=t.onCompact,this.onCompactEventCallback=t.onCompactEvent,this.maxTurns=t.maxTurns,this.model=t.model??`claude-sonnet-4-5`,this.sessionId=t.sessionId??`session_${Date.now()}_${Math.random().toString(36).substr(2,9)}`,this.permissionMode=t.permissionMode??(t.defaultTrustLevel?e.TRUST_TO_MODE[t.defaultTrustLevel]:void 0)??`default`,this.transcriptPath=t.sessionStore?.getFilePath?.(this.sessionId),this.log(`session_init`,{cwd:this.cwd,systemPromptLength:i.length,systemPrompt:i,toolSchemas:this.toolSchemas,model:this.model,provider:r.name}),this.aiProvider=r,v(r,t,(e,t)=>this.log(e,t)),this.permissionEnforcer=A(t,this.sessionId,this.cwd,()=>this.permissionMode,this.transcriptPath);let{contextTracker:a,compactionOrchestrator:o}=j(t,this.model,this.sessionId,this.cwd);this.contextTracker=a,this.compactionOrchestrator=o,this.robota=M(t,this.permissionEnforcer,n,r,this.model,i),y(this.sessionId,this.cwd,this.hooks,this.hookTypeExecutors,e=>void(this.sessionStartStdout=e),this.permissionMode,this.transcriptPath)}async run(e,t){this.abortController=new AbortController;let{signal:n}=this.abortController;try{let r=await h(e,t,this.buildRunContext(),n);return this.messageCount+=1,r}finally{this.abortController=null}}log(e,t){this.sessionLogger?.log(this.sessionId,e,t)}persistSessionInternal(){this.sessionStore&&_({sessionId:this.sessionId,cwd:this.cwd,systemPrompt:this.systemMessage,toolSchemas:this.toolSchemas,sessionStore:this.sessionStore,robota:this.robota,getFullHistory:()=>this.getFullHistory()})}shutdown(e={}){if(this.shutdownPromise)return this.shutdownPromise;let t=e.reason??`other`;return this.shutdownPromise=(async()=>{this.abort(),this.log(`session_shutdown`,{reason:t}),this.persistSessionInternal(),await ee(this.sessionId,this.cwd,t,this.hooks,this.hookTypeExecutors,this.permissionMode,this.transcriptPath)})(),this.shutdownPromise}async compact(e,t=`manual`){await g(e,{sessionId:this.sessionId,cwd:this.cwd,systemMessage:this.systemMessage,robota:this.robota,aiProvider:this.aiProvider,compactionOrchestrator:this.compactionOrchestrator,contextTracker:this.contextTracker,hooks:this.hooks,hookTypeExecutors:this.hookTypeExecutors,onCompactCallback:this.onCompactCallback,onCompactEventCallback:this.onCompactEventCallback,trigger:t,log:(e,t)=>this.log(e,t)})}buildRunContext(){return{sessionId:this.sessionId,cwd:this.cwd,model:this.model,robota:this.robota,aiProvider:this.aiProvider,contextTracker:this.contextTracker,hooks:this.hooks,hookTypeExecutors:this.hookTypeExecutors,sessionStartStdout:this.sessionStartStdout,log:(e,t)=>this.log(e,t),compact:()=>this.compact(void 0,`auto`),persistSession:()=>this.persistSessionInternal(),getSessionStore:()=>!!this.sessionStore,clearSessionStartStdout:()=>void(this.sessionStartStdout=``),permissionMode:this.permissionMode,transcriptPath:this.transcriptPath,maxTurns:this.maxTurns,onTextDelta:this.onTextDeltaCallback,onContextUpdate:this.onContextUpdateCallback,onToolExecution:this.onToolExecutionCallback,knownToolNames:this.toolSchemas.map(e=>e.name)}}};const P=/^(api[-_]?key|authorization|access[-_]?token|refresh[-_]?token|secret|password|x[-_]?api[-_]?key)$/i;var F=class{logDir;options;constructor(e,t={}){this.logDir=e,this.options={externalPayloadThresholdBytes:t.externalPayloadThresholdBytes??32768,redactedValue:t.redactedValue??`[REDACTED]`};try{(0,n.mkdirSync)(e,{recursive:!0})}catch{}}log(e,t,i){try{let a=I(e,this.logDir,i,this.options),o=JSON.stringify({timestamp:new Date().toISOString(),sessionId:e,event:t,...a});(0,n.appendFileSync)((0,r.join)(this.logDir,`${e}.jsonl`),o+`
5
- `)}catch{}}};function I(e,t,n,r){let i={};for(let[a,o]of Object.entries(n))i[a]=L(e,t,a,o,r);return i}function L(e,t,n,r,i){if(P.test(n))return i.redactedValue;if(r==null||typeof r==`string`||typeof r==`number`)return R(e,t,r,i);if(typeof r==`boolean`)return r;if(r instanceof Date)return r.toISOString();if(Array.isArray(r))return R(e,t,r.map(r=>L(e,t,n,r,i)),i);if(typeof r==`object`){let n=r,a={};for(let[r,o]of Object.entries(n))a[r]=L(e,t,r,o,i);return R(e,t,a,i)}return String(r)}function R(e,i,a,o){let s=JSON.stringify(a);if(s===void 0)return a;let c=Buffer.byteLength(s);if(c<=o.externalPayloadThresholdBytes)return a;let l=(0,t.createHash)(`sha256`).update(s).digest(`hex`),u=`${e}.payloads`,d=(0,r.join)(u,`${l}.json`),f=(0,r.join)(i,u),p=(0,r.join)(i,d);return(0,n.mkdirSync)(f,{recursive:!0}),(0,n.existsSync)(p)||(0,n.writeFileSync)(p,s,`utf-8`),{kind:`external-payload`,encoding:`json`,sha256:l,byteLength:c,relativePath:d}}var z=class{log(){}};function B(e){let t=[],n=V(),r=ne();return e.forEach((e,i)=>{J(e,i,t),H(n,e,i),U(r,e,i)}),W(n,t),G(r,t),{ok:t.length===0,issues:t}}function V(){return{requests:new Map,nativeRawPayloads:new Set,rawResponses:new Set,normalizedResponses:new Set}}function ne(){return{requests:new Map,results:new Set}}function H(e,t,n){let r=K(t);r&&(t.event===`provider_request`&&e.requests.set(r.key,{executionId:r.executionId,round:r.round,index:n}),t.event===`provider_response_raw`&&e.rawResponses.add(r.key),t.event===`provider_native_raw_payload`&&(t.payloadKind===`response`||t.payloadKind===`stream_event`)&&e.nativeRawPayloads.add(r.key),t.event===`provider_response_normalized`&&e.normalizedResponses.add(r.key))}function U(e,t,n){let r=q(t);r&&(t.event===`tool_execution_request`&&e.requests.set(r.key,{executionId:r.executionId,toolCallId:r.toolCallId,index:n}),t.event===`tool_execution_result`&&e.results.add(r.key))}function W(e,t){for(let[n,r]of e.requests)e.nativeRawPayloads.has(n)||t.push({code:`PROVIDER_NATIVE_RAW_PAYLOAD_MISSING`,message:`Provider request ${n} has no provider-native raw response or stream payload event.`,eventIndex:r.index,executionId:r.executionId,round:r.round}),e.rawResponses.has(n)||t.push({code:`PROVIDER_RESPONSE_RAW_MISSING`,message:`Provider request ${n} has no raw response event.`,eventIndex:r.index,executionId:r.executionId,round:r.round}),e.normalizedResponses.has(n)||t.push({code:`PROVIDER_RESPONSE_NORMALIZED_MISSING`,message:`Provider request ${n} has no normalized response event.`,eventIndex:r.index,executionId:r.executionId,round:r.round})}function G(e,t){for(let[n,r]of e.requests)e.results.has(n)||t.push({code:`TOOL_RESULT_MISSING`,message:`Tool request ${n} has no terminal result event.`,eventIndex:r.index,executionId:r.executionId,toolCallId:r.toolCallId})}function K(e){if(typeof e.executionId!=`string`)return;let t=typeof e.round==`number`?e.round:Number(e.round);if(Number.isFinite(t))return{key:`${e.executionId}:${t}`,executionId:e.executionId,round:t}}function q(e){if(typeof e.executionId!=`string`)return;let t=typeof e.toolCallId==`string`?e.toolCallId:typeof e.toolExecutionId==`string`?e.toolExecutionId:void 0;if(t)return{key:`${e.executionId}:${t}`,executionId:e.executionId,toolCallId:t}}function J(e,t,n){if(Array.isArray(e)){e.forEach(e=>J(e,t,n));return}if(Y(e)){if(e.kind===`external-payload`){(e.encoding!==`json`||typeof e.sha256!=`string`||typeof e.relativePath!=`string`||typeof e.byteLength!=`number`)&&n.push({code:`PAYLOAD_REFERENCE_INVALID`,message:`External payload reference is missing required replay fields.`,eventIndex:t});return}Object.values(e).forEach(e=>J(e,t,n))}}function Y(e){return typeof e==`object`&&!!e&&!Array.isArray(e)}function X(e){return(0,n.existsSync)(e)?(0,n.readFileSync)(e,`utf-8`).split(`
6
- `).map(e=>e.trim()).filter(e=>e.length>0).map(e=>JSON.parse(e)):[]}function Z(t){let n=[],r=[],i={backgroundTaskEvents:[],backgroundJobGroupEvents:[],memoryEvents:[]},a,o,s,c;for(let l of t){if(a??=l.sessionId,s??=l.timestamp,c=l.timestamp,l.event===`session_init`&&(o=typeof l.cwd==`string`?l.cwd:o),l.event===`history_mutation`&&l.mutation===`append_message`){let t=ie(l.message);t&&(n.push(t),r.push((0,e.messageToHistoryEntry)(t)))}re(l,i)}return{sessionId:a,cwd:o,createdAt:s,updatedAt:c,messages:n,history:r,backgroundTaskEvents:i.backgroundTaskEvents,backgroundJobGroupEvents:i.backgroundJobGroupEvents,memoryEvents:i.memoryEvents}}function re(e,t){if(e.event===`background_task_event`){$(t.backgroundTaskEvents,e,`backgroundEvent`,`data`);return}if(e.event===`background_job_group_event`){$(t.backgroundJobGroupEvents,e,`backgroundJobGroupEvent`,`data`);return}e.event===`memory_event`&&$(t.memoryEvents,e,`memoryEvent`,`data`)}function ie(e){if(!ae(e))return;let t=e.role;if(t!==`user`&&t!==`assistant`&&t!==`system`&&t!==`tool`)return;let n=typeof e.id==`string`?e.id:`${t}-${Date.now()}`,r=e.timestamp instanceof Date?e.timestamp:new Date(typeof e.timestamp==`string`?e.timestamp:Date.now());return{...e,id:n,role:t,timestamp:r}}function ae(e){return typeof e==`object`&&!!e&&!Array.isArray(e)}function Q(e,t){let n=e[t];if(!(typeof n!=`object`||!n||Array.isArray(n)||n instanceof Date))return n}function $(e,t,n,r){let i=Q(t,n)??Q(t,r);i&&e.push(i)}function oe(){return process.env.HOME??process.env.USERPROFILE??`/`}var se=class{baseDir;constructor(e){this.baseDir=e??(0,a.join)(oe(),`.robota`,`sessions`)}ensureDir(){(0,i.existsSync)(this.baseDir)||(0,i.mkdirSync)(this.baseDir,{recursive:!0})}filePath(e){return(0,a.join)(this.baseDir,`${e}.json`)}getFilePath(e){return this.filePath(e)}save(e){this.ensureDir(),(0,i.writeFileSync)(this.filePath(e.id),JSON.stringify(e,null,2),`utf-8`)}load(e){let t=this.filePath(e);if(!(0,i.existsSync)(t))return;let n=(0,i.readFileSync)(t,`utf-8`);return JSON.parse(n)}list(){if(!(0,i.existsSync)(this.baseDir))return[];let e=(0,i.readdirSync)(this.baseDir).filter(e=>e.endsWith(`.json`)),t=[];for(let n of e)try{let e=(0,i.readFileSync)((0,a.join)(this.baseDir,n),`utf-8`),r=JSON.parse(e);t.push(r)}catch{}return t.sort((e,t)=>new Date(t.updatedAt).getTime()-new Date(e.updatedAt).getTime())}delete(e){let t=this.filePath(e);(0,i.existsSync)(t)&&(0,i.unlinkSync)(t)}};exports.AUTO_COMPACT_THRESHOLD=E,exports.CompactionOrchestrator=k,exports.ContextWindowTracker=D,exports.FileSessionLogger=F,exports.PermissionEnforcer=T,exports.Session=N,exports.SessionStore=se,exports.SilentSessionLogger=z,exports.loadSessionLogEntries=X,exports.replaySessionLogEntries=Z,exports.validateSessionReplayLogEntries=B;
3
+ `)}};const c=.835;var l=class{contextUsedTokens=0;contextMaxTokens;autoCompactThreshold;constructor(t,n,r){this.contextMaxTokens=n??(0,e.getModelContextWindow)(t),this.autoCompactThreshold=u(r)}getContextState(){let e=Math.min(100,this.contextUsedTokens/this.contextMaxTokens*100);return{maxTokens:this.contextMaxTokens,usedTokens:this.contextUsedTokens,usedPercentage:Math.round(e*100)/100,remainingPercentage:Math.round((100-e)*100)/100}}shouldAutoCompact(){return this.autoCompactThreshold===!1?!1:this.getContextState().usedPercentage>=this.autoCompactThreshold*100}getAutoCompactThreshold(){return this.autoCompactThreshold}setAutoCompactThreshold(e){this.autoCompactThreshold=u(e)}updateFromHistory(t){this.contextUsedTokens=(0,e.estimateContextTokensFromMessages)(t).usedTokens}reset(){this.contextUsedTokens=0}};function u(e){if(e===void 0)return c;if(e===!1)return!1;if(!Number.isFinite(e)||e<=0||e>1)throw RangeError(`autoCompactThreshold must be a number greater than 0 and at most 1.`);return e}const d={success:!0,data:JSON.stringify({success:!1,output:``,error:`Permission denied. The user did not approve this action.`}),metadata:{}};function f(e){if(typeof e.data!=`string`||e.data.length<=3e4)return e;let t=15e3,n=e.data.substring(0,t),r=e.data.substring(e.data.length-t),i=`${n}\n\n[... output truncated: ${e.data.length.toLocaleString()} chars total, showing first and last ${t.toLocaleString()} chars ...]\n\n${r}`;return{...e,data:i}}function p(e,t,n,r,i,a){return{session_id:e,cwd:t,hook_event_name:`PreToolUse`,tool_name:n,tool_input:r,...i!==void 0&&{permission_mode:i},...a!==void 0&&{transcript_path:a}}}async function m(t,n,r){let i=await(0,e.runHooks)(t,`PreToolUse`,n,r);return i.blocked?{success:!0,data:JSON.stringify({blocked:!0,reason:i.reason??`Blocked by hook`}),metadata:{}}:null}function h(t,n,r,i){(0,e.runHooks)(t,`PostToolUse`,{...n,hook_event_name:`PostToolUse`,tool_output:typeof r.data==`string`?r.data:JSON.stringify(r.data)},i).catch(()=>{})}var g=class{sessionId;cwd;getPermissionMode;config;terminal;permissionHandler;promptForApprovalFn;sessionLogger;onToolExecution;hookTypeExecutors;transcriptPath;sessionAllowedTools=new Set;constructor(e){this.sessionId=e.sessionId,this.cwd=e.cwd,this.getPermissionMode=e.getPermissionMode,this.config=e.config,this.terminal=e.terminal,this.permissionHandler=e.permissionHandler,this.promptForApprovalFn=e.promptForApprovalFn,this.sessionLogger=e.sessionLogger,this.onToolExecution=e.onToolExecution,this.hookTypeExecutors=e.hookTypeExecutors,this.transcriptPath=e.transcriptPath}wrapTools(e){return e.map(e=>this.wrapToolWithPermission(e))}getSessionAllowedTools(){return[...this.sessionAllowedTools]}clearSessionAllowedTools(){this.sessionAllowedTools.clear()}wrapToolWithPermission(e){let t=this,n=e.execute.bind(e),r=Object.create(e);return r.execute=async(r,i)=>{try{let a=e.getName();t.log(`tool_call`,{tool:a,args:r});let o=p(t.sessionId,t.cwd,a,r,t.getPermissionMode(),t.transcriptPath),s=await m(t.config.hooks,o,t.hookTypeExecutors);if(s)return t.log(`tool_blocked`,{tool:a,reason:`hook`}),s;if(!await t.checkPermission(a,r))return t.log(`tool_denied`,{tool:a,reason:`permission`}),t.onToolExecution?.({type:`end`,toolName:a,toolArgs:r,success:!1,denied:!0}),d;t.onToolExecution?.({type:`start`,toolName:a,toolArgs:r});let c=await n(r,i),l=f(c);t.onToolExecution?.({type:`end`,toolName:a,toolArgs:r,success:l.success,toolResultData:typeof l.data==`string`?l.data:JSON.stringify(l.data)});let u=typeof l.data==`string`?l.data.length:JSON.stringify(l.data).length;return t.log(`tool_result`,{tool:a,success:l.success,dataChars:u,truncated:l!==c}),h(t.config.hooks,o,l,t.hookTypeExecutors),l}catch(e){let t=e instanceof Error?e.message:String(e);return{success:!0,data:JSON.stringify({success:!1,output:``,error:t}),metadata:{}}}},r}async checkPermission(t,n){let r=(0,e.evaluatePermission)(t,n,this.getPermissionMode(),{allow:this.config.permissions.allow,deny:this.config.permissions.deny});if(r===`auto`)return!0;if(r===`deny`)return!1;if(this.sessionAllowedTools.has(t))return!0;if(this.permissionHandler){let e=await this.permissionHandler(t,n);return e===`allow-session`?(this.sessionAllowedTools.add(t),!0):e}return this.promptForApprovalFn?this.promptForApprovalFn(this.terminal,t,n):!1}log(e,t){this.sessionLogger?.log(this.sessionId,e,t)}};function _(e,t,n,r,i){return new g({sessionId:t,cwd:n,getPermissionMode:r,config:{permissions:e.permissions??{allow:[],deny:[]},hooks:e.hooks},terminal:e.terminal,permissionHandler:e.permissionHandler,promptForApprovalFn:e.promptForApproval,sessionLogger:e.sessionLogger,onToolExecution:e.onToolExecution,hookTypeExecutors:e.hookTypeExecutors,transcriptPath:i})}function v(e,t,n,r){return{contextTracker:new l(t,e.contextMaxTokens,e.autoCompactThreshold),compactionOrchestrator:new s({sessionId:n,cwd:r,model:t,hooks:e.hooks,compactInstructions:e.compactInstructions,hookTypeExecutors:e.hookTypeExecutors})}}function y(t,n,r,i,a,o){let s=n.wrapTools(r);return new e.Robota({name:t.agentName??`agent`,aiProviders:[i],defaultModel:{provider:i.name,model:a,systemMessage:o},systemMessage:o,tools:s,logging:{enabled:!1},...t.providerTimeout!==void 0&&{timeout:t.providerTimeout}})}async function b(t,n){let r=n.robota.getHistory();if(r.length===0)return;n.contextTracker.updateFromHistory(r);let i=n.contextTracker.getContextState(),a=r.filter(e=>e.role!==`system`),o=await n.compactionOrchestrator.compact(n.aiProvider,a,t);n.robota.clearHistory(),n.robota.injectMessage(`system`,n.systemMessage),n.robota.injectMessage(`assistant`,`[Context Summary]\n${o}`),n.contextTracker.updateFromHistory(n.robota.getHistory());let s={session_id:n.sessionId,cwd:n.cwd,hook_event_name:`PostCompact`,trigger:n.trigger,compact_summary:o};(0,e.runHooks)(n.hooks,`PostCompact`,s,n.hookTypeExecutors).catch(()=>{});let c=n.contextTracker.getContextState();n.log(`context_compact`,{trigger:n.trigger,before:i,after:c}),n.onCompactEventCallback?.({trigger:n.trigger,before:i,after:c}),n.onCompactCallback&&n.onCompactCallback(o)}function x(e){let t=e.robota.getHistory(),n=new Date().toISOString(),r=e.sessionStore.load(e.sessionId),i={id:e.sessionId,name:r?.name,cwd:e.cwd,createdAt:r?.createdAt??n,updatedAt:n,messages:t,history:e.getFullHistory(),systemPrompt:e.systemPrompt,toolSchemas:e.toolSchemas};e.sessionStore.save(i)}function S(e,t,n){e.configureNativeWebTools?.({webSearch:!0}),`onServerToolUse`in e&&(e.onServerToolUse=(e,t)=>{n(`server_tool`,{tool:e,...t})})}function ee(t,n,r,i,a,o,s){(0,e.runHooks)(r,`SessionStart`,{session_id:t,cwd:n,hook_event_name:`SessionStart`,...o!==void 0&&{permission_mode:o},...s!==void 0&&{transcript_path:s},env:{CLAUDE_PROJECT_DIR:n,CLAUDE_SESSION_ID:t}},i).then(e=>{e.stdout&&a(e.stdout)}).catch(()=>{})}async function te(t,n,r,i,a,o,s){await(0,e.runHooks)(i,`SessionEnd`,{session_id:t,cwd:n,hook_event_name:`SessionEnd`,reason:r,...o!==void 0&&{permission_mode:o},...s!==void 0&&{transcript_path:s},env:{CLAUDE_PROJECT_DIR:n,CLAUDE_SESSION_ID:t}},a)}const C=`unknown_tool`;function w(e){return{knownToolNames:new Set(e.knownToolNames),unknownToolCallIds:new Set,...e.onToolExecution&&{onToolExecution:e.onToolExecution}}}function T(e,t,n){if(e.onToolExecution){if(t===`tool_execution_request`){E(e,n);return}t===`tool_execution_result`&&D(e,n)}}function E(e,t){let n=k(t.toolName),r=k(t.toolCallId);!n||!r||e.knownToolNames.has(n)||(e.unknownToolCallIds.add(r),e.onToolExecution?.({type:`start`,toolName:n,toolArgs:O(t.parameters)}))}function D(e,t){let n=k(t.toolName),r=k(t.toolCallId);if(!n||!r)return;let i=A(t.metadata);if(!(e.unknownToolCallIds.has(r)||i?.errorCode===C))return;e.unknownToolCallIds.delete(r);let a=k(t.error)??`Tool "${n}" is not registered.`;e.onToolExecution?.({type:`end`,toolName:n,success:!1,toolResultData:JSON.stringify({success:!1,error:a,errorCode:C,requestedTool:k(i?.requestedTool)??n,availableTools:j(i?.availableTools)})})}function O(e){let t=A(e);if(!t)return;let n={};for(let[e,r]of Object.entries(t))(typeof r==`string`||typeof r==`number`||typeof r==`boolean`||typeof r==`object`&&r)&&(n[e]=r);return n}function k(e){return typeof e==`string`&&e.length>0?e:void 0}function A(e){return typeof e==`object`&&e&&!Array.isArray(e)?e:void 0}function j(e){return Array.isArray(e)?e.filter(e=>typeof e==`string`):[]}async function M(t,n,r,i){if(r.contextTracker.updateFromHistory(r.robota.getHistory()),r.contextTracker.shouldAutoCompact()){let e=r.aiProvider,t=e.onTextDelta;e.onTextDelta=void 0;try{await r.compact()}finally{e.onTextDelta=t}}r.log(`user`,{content:t});let a=await(0,e.runHooks)(r.hooks,`UserPromptSubmit`,{session_id:r.sessionId,cwd:r.cwd,hook_event_name:`UserPromptSubmit`,user_message:n??t,prompt:n??t,...r.permissionMode!==void 0&&{permission_mode:r.permissionMode},...r.transcriptPath!==void 0&&{transcript_path:r.transcriptPath},env:{CLAUDE_PROJECT_DIR:r.cwd,CLAUDE_SESSION_ID:r.sessionId}},r.hookTypeExecutors),o=[r.sessionStartStdout,a.stdout].filter(Boolean).join(`
4
+ `),s=o?`<system-reminder>\n${o}\n</system-reminder>\n${t}`:t;r.clearSessionStartStdout();let c=r.robota.getHistory(),l=JSON.stringify(c),u=(0,e.getProviderCapabilities)(r.aiProvider);r.log(`pre_run`,{historyLength:c.length,historyChars:l.length,historyEstTokens:Math.ceil(l.length/4),input:s,history:c,model:r.model,provider:r.aiProvider.name,maxTokens:r.contextTracker.getContextState().maxTokens,nativeWebSearchSupported:u.nativeWebTools.webSearch.supported,nativeWebSearchEnabled:u.nativeWebTools.webSearch.enabled,nativeWebFetchSupported:u.nativeWebTools.webFetch.supported,nativeWebFetchEnabled:u.nativeWebTools.webFetch.enabled}),r.contextTracker.updateFromHistory([...c,(0,e.createUserMessage)(s)]),r.onContextUpdate?.(r.contextTracker.getContextState());let d;try{let e=w({knownToolNames:r.knownToolNames??[],...r.onToolExecution&&{onToolExecution:r.onToolExecution}}),t=r.onTextDelta?e=>{r.log(`text_delta`,{delta:e}),r.onTextDelta?.(e)}:void 0;if(d=await r.robota.run(s,{signal:i,maxExecutionRounds:r.maxTurns??0,onExecutionEvent:(t,n)=>{r.log(t,n),T(e,t,n)},...t&&{onTextDelta:t}}),i.aborted)throw new DOMException(`Aborted`,`AbortError`)}catch(t){throw r.log(`error`,{message:t instanceof Error?t.message:String(t),stack:t instanceof Error?t.stack??``:``,historyLength:r.robota.getHistory().length}),(0,e.runHooks)(r.hooks,`StopFailure`,{session_id:r.sessionId,cwd:r.cwd,hook_event_name:`StopFailure`,reason:t instanceof Error?t.message:String(t),stop_hook_active:!1,...r.permissionMode!==void 0&&{permission_mode:r.permissionMode},...r.transcriptPath!==void 0&&{transcript_path:r.transcriptPath},env:{CLAUDE_PROJECT_DIR:r.cwd,CLAUDE_SESSION_ID:r.sessionId}},r.hookTypeExecutors).catch(()=>{}),t}let f=r.robota.getHistory(),p=f.map(e=>{let t=`toolCalls`in e&&Array.isArray(e.toolCalls)&&e.toolCalls.length>0,n=t?e.toolCalls.map(e=>e.function.name):[];return{role:e.role,contentLength:typeof e.content==`string`?e.content.length:0,hasToolCalls:t,toolCallNames:n,...e.metadata?{metadata:e.metadata}:{}}});r.log(`assistant`,{content:d,historyLength:f.length,estimatedChars:JSON.stringify(f).length,history:f,historyStructure:p}),r.contextTracker.updateFromHistory(f);let m=r.contextTracker.getContextState();return r.onContextUpdate?.(m),r.log(`context`,{maxTokens:m.maxTokens,usedTokens:m.usedTokens,usedPercentage:m.usedPercentage,remainingPercentage:m.remainingPercentage}),(0,e.runHooks)(r.hooks,`Stop`,{session_id:r.sessionId,cwd:r.cwd,hook_event_name:`Stop`,response:d.substring(0,500),last_assistant_message:d,stop_hook_active:!1,...r.permissionMode!==void 0&&{permission_mode:r.permissionMode},...r.transcriptPath!==void 0&&{transcript_path:r.transcriptPath},env:{CLAUDE_PROJECT_DIR:r.cwd,CLAUDE_SESSION_ID:r.sessionId}},r.hookTypeExecutors).catch(()=>{}),r.getSessionStore()&&r.persistSession(),d}var N=class extends o{robota;permissionEnforcer;contextTracker;permissionMode;sessionId;aiProvider;toolSchemas;model;systemMessage;messageCount=0;abortController=null;terminal;sessionStore;cwd;hooks;hookTypeExecutors;onTextDeltaCallback;onContextUpdateCallback;onToolExecutionCallback;onCompactCallback;onCompactEventCallback;sessionLogger;maxTurns;compactionOrchestrator;shutdownPromise=null;sessionStartStdout=``;transcriptPath;constructor(t){super();let{tools:n,provider:r,systemMessage:i}=t;this.terminal=t.terminal,this.sessionStore=t.sessionStore,this.systemMessage=i,this.toolSchemas=n.map(e=>e.schema),this.cwd=process.cwd(),this.sessionLogger=t.sessionLogger,this.hooks=t.hooks,this.hookTypeExecutors=t.hookTypeExecutors,this.onTextDeltaCallback=t.onTextDelta,this.onContextUpdateCallback=t.onContextUpdate,this.onToolExecutionCallback=t.onToolExecution,this.onCompactCallback=t.onCompact,this.onCompactEventCallback=t.onCompactEvent,this.maxTurns=t.maxTurns,this.model=t.model??`claude-sonnet-4-5`,this.sessionId=t.sessionId??`session_${Date.now()}_${Math.random().toString(36).substr(2,9)}`,this.permissionMode=t.permissionMode??(t.defaultTrustLevel?e.TRUST_TO_MODE[t.defaultTrustLevel]:void 0)??`default`,this.transcriptPath=t.sessionStore?.getFilePath?.(this.sessionId),this.log(`session_init`,{cwd:this.cwd,systemPromptLength:i.length,systemPrompt:i,toolSchemas:this.toolSchemas,model:this.model,provider:r.name}),this.aiProvider=r,S(r,t,(e,t)=>this.log(e,t)),this.permissionEnforcer=_(t,this.sessionId,this.cwd,()=>this.permissionMode,this.transcriptPath);let{contextTracker:a,compactionOrchestrator:o}=v(t,this.model,this.sessionId,this.cwd);this.contextTracker=a,this.compactionOrchestrator=o,this.robota=y(t,this.permissionEnforcer,n,r,this.model,i),ee(this.sessionId,this.cwd,this.hooks,this.hookTypeExecutors,e=>void(this.sessionStartStdout=e),this.permissionMode,this.transcriptPath)}async run(e,t){this.abortController=new AbortController;let{signal:n}=this.abortController;try{let r=await M(e,t,this.buildRunContext(),n);return this.messageCount+=1,r}finally{this.abortController=null}}log(e,t){this.sessionLogger?.log(this.sessionId,e,t)}persistSessionInternal(){this.sessionStore&&x({sessionId:this.sessionId,cwd:this.cwd,systemPrompt:this.systemMessage,toolSchemas:this.toolSchemas,sessionStore:this.sessionStore,robota:this.robota,getFullHistory:()=>this.getFullHistory()})}shutdown(e={}){if(this.shutdownPromise)return this.shutdownPromise;let t=e.reason??`other`;return this.shutdownPromise=(async()=>{this.abort(),this.log(`session_shutdown`,{reason:t}),this.persistSessionInternal(),await te(this.sessionId,this.cwd,t,this.hooks,this.hookTypeExecutors,this.permissionMode,this.transcriptPath)})(),this.shutdownPromise}async compact(e,t=`manual`){await b(e,{sessionId:this.sessionId,cwd:this.cwd,systemMessage:this.systemMessage,robota:this.robota,aiProvider:this.aiProvider,compactionOrchestrator:this.compactionOrchestrator,contextTracker:this.contextTracker,hooks:this.hooks,hookTypeExecutors:this.hookTypeExecutors,onCompactCallback:this.onCompactCallback,onCompactEventCallback:this.onCompactEventCallback,trigger:t,log:(e,t)=>this.log(e,t)})}buildRunContext(){return{sessionId:this.sessionId,cwd:this.cwd,model:this.model,robota:this.robota,aiProvider:this.aiProvider,contextTracker:this.contextTracker,hooks:this.hooks,hookTypeExecutors:this.hookTypeExecutors,sessionStartStdout:this.sessionStartStdout,log:(e,t)=>this.log(e,t),compact:()=>this.compact(void 0,`auto`),persistSession:()=>this.persistSessionInternal(),getSessionStore:()=>!!this.sessionStore,clearSessionStartStdout:()=>void(this.sessionStartStdout=``),permissionMode:this.permissionMode,transcriptPath:this.transcriptPath,maxTurns:this.maxTurns,onTextDelta:this.onTextDeltaCallback,onContextUpdate:this.onContextUpdateCallback,onToolExecution:this.onToolExecutionCallback,knownToolNames:this.toolSchemas.map(e=>e.name)}}};const P=/^(api[-_]?key|authorization|access[-_]?token|refresh[-_]?token|secret|password|x[-_]?api[-_]?key)$/i;var F=class{logDir;options;constructor(e,t={}){this.logDir=e,this.options={externalPayloadThresholdBytes:t.externalPayloadThresholdBytes??32768,redactedValue:t.redactedValue??`[REDACTED]`};try{(0,n.mkdirSync)(e,{recursive:!0})}catch{}}log(e,t,i){try{let a=I(e,this.logDir,i,this.options),o=JSON.stringify({timestamp:new Date().toISOString(),sessionId:e,event:t,...a});(0,n.appendFileSync)((0,r.join)(this.logDir,`${e}.jsonl`),o+`
5
+ `)}catch{}}};function I(e,t,n,r){let i={};for(let[a,o]of Object.entries(n))i[a]=L(e,t,a,o,r);return i}function L(e,t,n,r,i){if(P.test(n))return i.redactedValue;if(r==null||typeof r==`string`||typeof r==`number`)return R(e,t,r,i);if(typeof r==`boolean`)return r;if(r instanceof Date)return r.toISOString();if(Array.isArray(r))return R(e,t,r.map(r=>L(e,t,n,r,i)),i);if(typeof r==`object`){let n=r,a={};for(let[r,o]of Object.entries(n))a[r]=L(e,t,r,o,i);return R(e,t,a,i)}return String(r)}function R(e,i,a,o){let s=JSON.stringify(a);if(s===void 0)return a;let c=Buffer.byteLength(s);if(c<=o.externalPayloadThresholdBytes)return a;let l=(0,t.createHash)(`sha256`).update(s).digest(`hex`),u=`${e}.payloads`,d=(0,r.join)(u,`${l}.json`),f=(0,r.join)(i,u),p=(0,r.join)(i,d);return(0,n.mkdirSync)(f,{recursive:!0}),(0,n.existsSync)(p)||(0,n.writeFileSync)(p,s,`utf-8`),{kind:`external-payload`,encoding:`json`,sha256:l,byteLength:c,relativePath:d}}var ne=class{log(){}};function z(e){let t=[],n=B(),r=V();return e.forEach((e,i)=>{J(e,i,t),H(n,e,i),U(r,e,i)}),W(n,t),G(r,t),{ok:t.length===0,issues:t}}function B(){return{requests:new Map,nativeRawPayloads:new Set,rawResponses:new Set,normalizedResponses:new Set}}function V(){return{requests:new Map,results:new Set}}function H(e,t,n){let r=K(t);r&&(t.event===`provider_request`&&e.requests.set(r.key,{executionId:r.executionId,round:r.round,index:n}),t.event===`provider_response_raw`&&e.rawResponses.add(r.key),t.event===`provider_native_raw_payload`&&(t.payloadKind===`response`||t.payloadKind===`stream_event`)&&e.nativeRawPayloads.add(r.key),t.event===`provider_response_normalized`&&e.normalizedResponses.add(r.key))}function U(e,t,n){let r=q(t);r&&(t.event===`tool_execution_request`&&e.requests.set(r.key,{executionId:r.executionId,toolCallId:r.toolCallId,index:n}),t.event===`tool_execution_result`&&e.results.add(r.key))}function W(e,t){for(let[n,r]of e.requests)e.nativeRawPayloads.has(n)||t.push({code:`PROVIDER_NATIVE_RAW_PAYLOAD_MISSING`,message:`Provider request ${n} has no provider-native raw response or stream payload event.`,eventIndex:r.index,executionId:r.executionId,round:r.round}),e.rawResponses.has(n)||t.push({code:`PROVIDER_RESPONSE_RAW_MISSING`,message:`Provider request ${n} has no raw response event.`,eventIndex:r.index,executionId:r.executionId,round:r.round}),e.normalizedResponses.has(n)||t.push({code:`PROVIDER_RESPONSE_NORMALIZED_MISSING`,message:`Provider request ${n} has no normalized response event.`,eventIndex:r.index,executionId:r.executionId,round:r.round})}function G(e,t){for(let[n,r]of e.requests)e.results.has(n)||t.push({code:`TOOL_RESULT_MISSING`,message:`Tool request ${n} has no terminal result event.`,eventIndex:r.index,executionId:r.executionId,toolCallId:r.toolCallId})}function K(e){if(typeof e.executionId!=`string`)return;let t=typeof e.round==`number`?e.round:Number(e.round);if(Number.isFinite(t))return{key:`${e.executionId}:${t}`,executionId:e.executionId,round:t}}function q(e){if(typeof e.executionId!=`string`)return;let t=typeof e.toolCallId==`string`?e.toolCallId:typeof e.toolExecutionId==`string`?e.toolExecutionId:void 0;if(t)return{key:`${e.executionId}:${t}`,executionId:e.executionId,toolCallId:t}}function J(e,t,n){if(Array.isArray(e)){e.forEach(e=>J(e,t,n));return}if(Y(e)){if(e.kind===`external-payload`){(e.encoding!==`json`||typeof e.sha256!=`string`||typeof e.relativePath!=`string`||typeof e.byteLength!=`number`)&&n.push({code:`PAYLOAD_REFERENCE_INVALID`,message:`External payload reference is missing required replay fields.`,eventIndex:t});return}Object.values(e).forEach(e=>J(e,t,n))}}function Y(e){return typeof e==`object`&&!!e&&!Array.isArray(e)}function X(e){return(0,n.existsSync)(e)?(0,n.readFileSync)(e,`utf-8`).split(`
6
+ `).map(e=>e.trim()).filter(e=>e.length>0).map(e=>JSON.parse(e)):[]}function Z(t){let n=[],r=[],i={backgroundTaskEvents:[],backgroundJobGroupEvents:[],memoryEvents:[]},a,o,s,c;for(let l of t){if(a??=l.sessionId,s??=l.timestamp,c=l.timestamp,l.event===`session_init`&&(o=typeof l.cwd==`string`?l.cwd:o),l.event===`history_mutation`&&l.mutation===`append_message`){let t=ie(l.message);t&&(n.push(t),r.push((0,e.messageToHistoryEntry)(t)))}re(l,i)}return{sessionId:a,cwd:o,createdAt:s,updatedAt:c,messages:n,history:r,backgroundTaskEvents:i.backgroundTaskEvents,backgroundJobGroupEvents:i.backgroundJobGroupEvents,memoryEvents:i.memoryEvents}}function re(e,t){if(e.event===`background_task_event`){$(t.backgroundTaskEvents,e,`backgroundEvent`,`data`);return}if(e.event===`background_job_group_event`){$(t.backgroundJobGroupEvents,e,`backgroundJobGroupEvent`,`data`);return}e.event===`memory_event`&&$(t.memoryEvents,e,`memoryEvent`,`data`)}function ie(e){if(!ae(e))return;let t=e.role;if(t!==`user`&&t!==`assistant`&&t!==`system`&&t!==`tool`)return;let n=typeof e.id==`string`?e.id:`${t}-${Date.now()}`,r=e.timestamp instanceof Date?e.timestamp:new Date(typeof e.timestamp==`string`?e.timestamp:Date.now());return{...e,id:n,role:t,timestamp:r}}function ae(e){return typeof e==`object`&&!!e&&!Array.isArray(e)}function Q(e,t){let n=e[t];if(!(typeof n!=`object`||!n||Array.isArray(n)||n instanceof Date))return n}function $(e,t,n,r){let i=Q(t,n)??Q(t,r);i&&e.push(i)}function oe(){return process.env.HOME??process.env.USERPROFILE??`/`}var se=class{baseDir;constructor(e){this.baseDir=e??(0,a.join)(oe(),`.robota`,`sessions`)}ensureDir(){(0,i.existsSync)(this.baseDir)||(0,i.mkdirSync)(this.baseDir,{recursive:!0})}filePath(e){return(0,a.join)(this.baseDir,`${e}.json`)}getFilePath(e){return this.filePath(e)}save(e){this.ensureDir(),(0,i.writeFileSync)(this.filePath(e.id),JSON.stringify(e,null,2),`utf-8`)}load(e){let t=this.filePath(e);if(!(0,i.existsSync)(t))return;let n=(0,i.readFileSync)(t,`utf-8`);return JSON.parse(n)}list(){if(!(0,i.existsSync)(this.baseDir))return[];let e=(0,i.readdirSync)(this.baseDir).filter(e=>e.endsWith(`.json`)),t=[];for(let n of e)try{let e=(0,i.readFileSync)((0,a.join)(this.baseDir,n),`utf-8`),r=JSON.parse(e);t.push(r)}catch{}return t.sort((e,t)=>new Date(t.updatedAt).getTime()-new Date(e.updatedAt).getTime())}delete(e){let t=this.filePath(e);(0,i.existsSync)(t)&&(0,i.unlinkSync)(t)}};exports.AUTO_COMPACT_THRESHOLD=c,exports.CompactionOrchestrator=s,exports.ContextWindowTracker=l,exports.FileSessionLogger=F,exports.PermissionEnforcer=g,exports.Session=N,exports.SessionStore=se,exports.SilentSessionLogger=ne,exports.loadSessionLogEntries=X,exports.replaySessionLogEntries=Z,exports.validateSessionReplayLogEntries=z;
@@ -1,5 +1,33 @@
1
1
  import { IAIProvider, IContextWindowState, IContextWindowState as IContextWindowState$1, IHistoryEntry, IHookTypeExecutor, ISession, ISpinner, ITerminalOutput, IToolSchema, IToolWithEventService, Robota, TPermissionMode, TSessionEndReason, TToolArgs, TUniversalMessage, TUniversalValue } from "@robota-sdk/agent-core";
2
2
 
3
+ //#region src/context-window-tracker.d.ts
4
+ /** Auto-compact when context usage reaches this fraction */
5
+ declare const AUTO_COMPACT_THRESHOLD = 0.835;
6
+ type TAutoCompactThreshold = number | false;
7
+ declare class ContextWindowTracker {
8
+ private contextUsedTokens;
9
+ private readonly contextMaxTokens;
10
+ private autoCompactThreshold;
11
+ constructor(model: string, contextMaxTokens?: number, autoCompactThreshold?: TAutoCompactThreshold);
12
+ /** Get current context window state */
13
+ getContextState(): IContextWindowState$1;
14
+ /** Whether auto-compaction threshold has been exceeded */
15
+ shouldAutoCompact(): boolean;
16
+ /** The auto-compaction policy for this tracker. */
17
+ getAutoCompactThreshold(): TAutoCompactThreshold;
18
+ /** Update the auto-compaction policy for this tracker. */
19
+ setAutoCompactThreshold(autoCompactThreshold: TAutoCompactThreshold): void;
20
+ /**
21
+ * Estimate token usage from conversation history.
22
+ *
23
+ * Uses the shared core estimator so session display, /context, auto-compact, and core
24
+ * execution guards reason about the same effective token state.
25
+ */
26
+ updateFromHistory(history: TUniversalMessage[]): void;
27
+ /** Reset token tracking */
28
+ reset(): void;
29
+ }
30
+ //#endregion
3
31
  //#region src/session-logger.d.ts
4
32
  /**
5
33
  * Session Logger — pluggable logging interface for session events.
@@ -124,32 +152,47 @@ declare class PermissionEnforcer {
124
152
  private log;
125
153
  }
126
154
  //#endregion
127
- //#region src/context-window-tracker.d.ts
128
- /** Auto-compact when context usage reaches this fraction */
129
- declare const AUTO_COMPACT_THRESHOLD = 0.835;
130
- type TAutoCompactThreshold = number | false;
131
- declare class ContextWindowTracker {
132
- private contextUsedTokens;
133
- private readonly contextMaxTokens;
134
- private autoCompactThreshold;
135
- constructor(model: string, contextMaxTokens?: number, autoCompactThreshold?: TAutoCompactThreshold);
136
- /** Get current context window state */
155
+ //#region src/session-base.d.ts
156
+ declare abstract class SessionBase {
157
+ protected abstract readonly robota: Robota;
158
+ protected abstract readonly permissionEnforcer: PermissionEnforcer;
159
+ protected abstract readonly contextTracker: ContextWindowTracker;
160
+ protected abstract permissionMode: TPermissionMode;
161
+ protected abstract readonly sessionId: string;
162
+ protected abstract readonly aiProvider: IAIProvider;
163
+ protected abstract readonly toolSchemas: IToolSchema[];
164
+ protected abstract readonly model: string;
165
+ protected abstract systemMessage: string;
166
+ protected abstract messageCount: number;
167
+ protected abstract abortController: AbortController | null;
168
+ getPermissionMode(): TPermissionMode;
169
+ /** Change the active permission mode — future tool calls will use the new mode. */
170
+ setPermissionMode(mode: TPermissionMode): void;
171
+ getSessionId(): string;
172
+ getSystemMessage(): string;
173
+ /** Replace the active system message and propagate to the agent (used by staleness detection). */
174
+ updateSystemMessage(newMessage: string): void;
175
+ getToolSchemas(): IToolSchema[];
176
+ getMessageCount(): number;
177
+ /** Get tools that have been session-approved (via "Allow always" choice). */
178
+ getSessionAllowedTools(): string[];
179
+ clearSessionAllowedTools(): void;
180
+ /** Abort the currently running execution. No-op if nothing is running. */
181
+ abort(): void;
182
+ isRunning(): boolean;
137
183
  getContextState(): IContextWindowState$1;
138
- /** Whether auto-compaction threshold has been exceeded */
139
- shouldAutoCompact(): boolean;
140
- /** The auto-compaction policy for this tracker. */
141
184
  getAutoCompactThreshold(): TAutoCompactThreshold;
142
- /** Update the auto-compaction policy for this tracker. */
143
- setAutoCompactThreshold(autoCompactThreshold: TAutoCompactThreshold): void;
144
- /**
145
- * Estimate token usage from conversation history.
146
- *
147
- * Uses the shared core estimator so session display, /context, auto-compact, and core
148
- * execution guards reason about the same effective token state.
149
- */
150
- updateFromHistory(history: TUniversalMessage[]): void;
151
- /** Reset token tracking */
152
- reset(): void;
185
+ setAutoCompactThreshold(threshold: number | false): void;
186
+ getHistory(): TUniversalMessage[];
187
+ getFullHistory(): IHistoryEntry[];
188
+ /** Add an event entry to history (not a chat message) */
189
+ addHistoryEntry(entry: IHistoryEntry): void;
190
+ /** Inject a message into conversation history without execution (used for session restore). */
191
+ injectMessage(role: 'user' | 'assistant' | 'system' | 'tool', content: string, options?: {
192
+ toolCallId?: string;
193
+ name?: string;
194
+ }): void;
195
+ clearHistory(): void;
153
196
  }
154
197
  //#endregion
155
198
  //#region src/session-store.d.ts
@@ -312,49 +355,6 @@ interface ISessionOptions {
312
355
  agentName?: string;
313
356
  }
314
357
  //#endregion
315
- //#region src/session-base.d.ts
316
- declare abstract class SessionBase {
317
- protected abstract readonly robota: Robota;
318
- protected abstract readonly permissionEnforcer: PermissionEnforcer;
319
- protected abstract readonly contextTracker: ContextWindowTracker;
320
- protected abstract permissionMode: TPermissionMode;
321
- protected abstract readonly sessionId: string;
322
- protected abstract readonly aiProvider: IAIProvider;
323
- protected abstract readonly toolSchemas: IToolSchema[];
324
- protected abstract readonly model: string;
325
- protected abstract systemMessage: string;
326
- protected abstract messageCount: number;
327
- protected abstract abortController: AbortController | null;
328
- getPermissionMode(): TPermissionMode;
329
- /** Change the active permission mode — future tool calls will use the new mode. */
330
- setPermissionMode(mode: TPermissionMode): void;
331
- getSessionId(): string;
332
- getSystemMessage(): string;
333
- /** Replace the active system message and propagate to the agent (used by staleness detection). */
334
- updateSystemMessage(newMessage: string): void;
335
- getToolSchemas(): IToolSchema[];
336
- getMessageCount(): number;
337
- /** Get tools that have been session-approved (via "Allow always" choice). */
338
- getSessionAllowedTools(): string[];
339
- clearSessionAllowedTools(): void;
340
- /** Abort the currently running execution. No-op if nothing is running. */
341
- abort(): void;
342
- isRunning(): boolean;
343
- getContextState(): import("@robota-sdk/agent-core").IContextWindowState;
344
- getAutoCompactThreshold(): TAutoCompactThreshold;
345
- setAutoCompactThreshold(threshold: number | false): void;
346
- getHistory(): import("@robota-sdk/agent-core").TUniversalMessage[];
347
- getFullHistory(): IHistoryEntry[];
348
- /** Add an event entry to history (not a chat message) */
349
- addHistoryEntry(entry: IHistoryEntry): void;
350
- /** Inject a message into conversation history without execution (used for session restore). */
351
- injectMessage(role: 'user' | 'assistant' | 'system' | 'tool', content: string, options?: {
352
- toolCallId?: string;
353
- name?: string;
354
- }): void;
355
- clearHistory(): void;
356
- }
357
- //#endregion
358
358
  //#region src/session.d.ts
359
359
  /** Wraps a Robota agent with project context, permission state, and optional persistence. */
360
360
  declare class Session extends SessionBase {
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","names":[],"sources":["../../src/session-logger.ts","../../src/permission-types.ts","../../src/permission-enforcer.ts","../../src/context-window-tracker.ts","../../src/session-store.ts","../../src/session-types.ts","../../src/session-base.ts","../../src/session.ts","../../src/compaction-orchestrator.ts","../../src/session-log-validation.ts","../../src/session-log-replay.ts"],"mappings":"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"}
1
+ {"version":3,"file":"index.d.ts","names":[],"sources":["../../src/context-window-tracker.ts","../../src/session-logger.ts","../../src/permission-types.ts","../../src/permission-enforcer.ts","../../src/session-base.ts","../../src/session-store.ts","../../src/session-types.ts","../../src/session.ts","../../src/compaction-orchestrator.ts","../../src/session-log-validation.ts","../../src/session-log-replay.ts"],"mappings":"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"}
@@ -1,7 +1,7 @@
1
- import{Robota as e,TRUST_TO_MODE as t,createUserMessage as n,estimateContextTokensFromMessages as r,evaluatePermission as i,getModelContextWindow as a,getProviderCapabilities as o,messageToHistoryEntry as s,runHooks as c}from"@robota-sdk/agent-core";import{createHash as l,randomUUID as u}from"node:crypto";import{appendFileSync as d,existsSync as f,mkdirSync as p,readFileSync as m,writeFileSync as h}from"node:fs";import{join as g}from"node:path";import{existsSync as _,mkdirSync as v,readFileSync as y,readdirSync as b,unlinkSync as ee,writeFileSync as te}from"fs";import{join as x}from"path";const S=`unknown_tool`;function C(e){return{knownToolNames:new Set(e.knownToolNames),unknownToolCallIds:new Set,...e.onToolExecution&&{onToolExecution:e.onToolExecution}}}function w(e,t,n){if(e.onToolExecution){if(t===`tool_execution_request`){T(e,n);return}t===`tool_execution_result`&&ne(e,n)}}function T(e,t){let n=E(t.toolName),r=E(t.toolCallId);!n||!r||e.knownToolNames.has(n)||(e.unknownToolCallIds.add(r),e.onToolExecution?.({type:`start`,toolName:n,toolArgs:re(t.parameters)}))}function ne(e,t){let n=E(t.toolName),r=E(t.toolCallId);if(!n||!r)return;let i=D(t.metadata);if(!(e.unknownToolCallIds.has(r)||i?.errorCode===S))return;e.unknownToolCallIds.delete(r);let a=E(t.error)??`Tool "${n}" is not registered.`;e.onToolExecution?.({type:`end`,toolName:n,success:!1,toolResultData:JSON.stringify({success:!1,error:a,errorCode:S,requestedTool:E(i?.requestedTool)??n,availableTools:ie(i?.availableTools)})})}function re(e){let t=D(e);if(!t)return;let n={};for(let[e,r]of Object.entries(t))(typeof r==`string`||typeof r==`number`||typeof r==`boolean`||typeof r==`object`&&r)&&(n[e]=r);return n}function E(e){return typeof e==`string`&&e.length>0?e:void 0}function D(e){return typeof e==`object`&&e&&!Array.isArray(e)?e:void 0}function ie(e){return Array.isArray(e)?e.filter(e=>typeof e==`string`):[]}async function ae(e,t,r,i){if(r.contextTracker.updateFromHistory(r.robota.getHistory()),r.contextTracker.shouldAutoCompact()){let e=r.aiProvider,t=e.onTextDelta;e.onTextDelta=void 0;try{await r.compact()}finally{e.onTextDelta=t}}r.log(`user`,{content:e});let a=await c(r.hooks,`UserPromptSubmit`,{session_id:r.sessionId,cwd:r.cwd,hook_event_name:`UserPromptSubmit`,user_message:t??e,prompt:t??e,...r.permissionMode!==void 0&&{permission_mode:r.permissionMode},...r.transcriptPath!==void 0&&{transcript_path:r.transcriptPath},env:{CLAUDE_PROJECT_DIR:r.cwd,CLAUDE_SESSION_ID:r.sessionId}},r.hookTypeExecutors),s=[r.sessionStartStdout,a.stdout].filter(Boolean).join(`
2
- `),l=s?`<system-reminder>\n${s}\n</system-reminder>\n${e}`:e;r.clearSessionStartStdout();let u=r.robota.getHistory(),d=JSON.stringify(u),f=o(r.aiProvider);r.log(`pre_run`,{historyLength:u.length,historyChars:d.length,historyEstTokens:Math.ceil(d.length/4),input:l,history:u,model:r.model,provider:r.aiProvider.name,maxTokens:r.contextTracker.getContextState().maxTokens,nativeWebSearchSupported:f.nativeWebTools.webSearch.supported,nativeWebSearchEnabled:f.nativeWebTools.webSearch.enabled,nativeWebFetchSupported:f.nativeWebTools.webFetch.supported,nativeWebFetchEnabled:f.nativeWebTools.webFetch.enabled}),r.contextTracker.updateFromHistory([...u,n(l)]),r.onContextUpdate?.(r.contextTracker.getContextState());let p;try{let e=C({knownToolNames:r.knownToolNames??[],...r.onToolExecution&&{onToolExecution:r.onToolExecution}}),t=r.onTextDelta?e=>{r.log(`text_delta`,{delta:e}),r.onTextDelta?.(e)}:void 0;if(p=await r.robota.run(l,{signal:i,maxExecutionRounds:r.maxTurns??0,onExecutionEvent:(t,n)=>{r.log(t,n),w(e,t,n)},...t&&{onTextDelta:t}}),i.aborted)throw new DOMException(`Aborted`,`AbortError`)}catch(e){throw r.log(`error`,{message:e instanceof Error?e.message:String(e),stack:e instanceof Error?e.stack??``:``,historyLength:r.robota.getHistory().length}),c(r.hooks,`StopFailure`,{session_id:r.sessionId,cwd:r.cwd,hook_event_name:`StopFailure`,reason:e instanceof Error?e.message:String(e),stop_hook_active:!1,...r.permissionMode!==void 0&&{permission_mode:r.permissionMode},...r.transcriptPath!==void 0&&{transcript_path:r.transcriptPath},env:{CLAUDE_PROJECT_DIR:r.cwd,CLAUDE_SESSION_ID:r.sessionId}},r.hookTypeExecutors).catch(()=>{}),e}let m=r.robota.getHistory(),h=m.map(e=>{let t=`toolCalls`in e&&Array.isArray(e.toolCalls)&&e.toolCalls.length>0,n=t?e.toolCalls.map(e=>e.function.name):[];return{role:e.role,contentLength:typeof e.content==`string`?e.content.length:0,hasToolCalls:t,toolCallNames:n,...e.metadata?{metadata:e.metadata}:{}}});r.log(`assistant`,{content:p,historyLength:m.length,estimatedChars:JSON.stringify(m).length,history:m,historyStructure:h}),r.contextTracker.updateFromHistory(m);let g=r.contextTracker.getContextState();return r.onContextUpdate?.(g),r.log(`context`,{maxTokens:g.maxTokens,usedTokens:g.usedTokens,usedPercentage:g.usedPercentage,remainingPercentage:g.remainingPercentage}),c(r.hooks,`Stop`,{session_id:r.sessionId,cwd:r.cwd,hook_event_name:`Stop`,response:p.substring(0,500),last_assistant_message:p,stop_hook_active:!1,...r.permissionMode!==void 0&&{permission_mode:r.permissionMode},...r.transcriptPath!==void 0&&{transcript_path:r.transcriptPath},env:{CLAUDE_PROJECT_DIR:r.cwd,CLAUDE_SESSION_ID:r.sessionId}},r.hookTypeExecutors).catch(()=>{}),r.getSessionStore()&&r.persistSession(),p}async function O(e,t){let n=t.robota.getHistory();if(n.length===0)return;t.contextTracker.updateFromHistory(n);let r=t.contextTracker.getContextState(),i=n.filter(e=>e.role!==`system`),a=await t.compactionOrchestrator.compact(t.aiProvider,i,e);t.robota.clearHistory(),t.robota.injectMessage(`system`,t.systemMessage),t.robota.injectMessage(`assistant`,`[Context Summary]\n${a}`),t.contextTracker.updateFromHistory(t.robota.getHistory());let o={session_id:t.sessionId,cwd:t.cwd,hook_event_name:`PostCompact`,trigger:t.trigger,compact_summary:a};c(t.hooks,`PostCompact`,o,t.hookTypeExecutors).catch(()=>{});let s=t.contextTracker.getContextState();t.log(`context_compact`,{trigger:t.trigger,before:r,after:s}),t.onCompactEventCallback?.({trigger:t.trigger,before:r,after:s}),t.onCompactCallback&&t.onCompactCallback(a)}function k(e){let t=e.robota.getHistory(),n=new Date().toISOString(),r=e.sessionStore.load(e.sessionId),i={id:e.sessionId,name:r?.name,cwd:e.cwd,createdAt:r?.createdAt??n,updatedAt:n,messages:t,history:e.getFullHistory(),systemPrompt:e.systemPrompt,toolSchemas:e.toolSchemas};e.sessionStore.save(i)}function A(e,t,n){e.configureNativeWebTools?.({webSearch:!0}),`onServerToolUse`in e&&(e.onServerToolUse=(e,t)=>{n(`server_tool`,{tool:e,...t})})}function j(e,t,n,r,i,a,o){c(n,`SessionStart`,{session_id:e,cwd:t,hook_event_name:`SessionStart`,...a!==void 0&&{permission_mode:a},...o!==void 0&&{transcript_path:o},env:{CLAUDE_PROJECT_DIR:t,CLAUDE_SESSION_ID:e}},r).then(e=>{e.stdout&&i(e.stdout)}).catch(()=>{})}async function M(e,t,n,r,i,a,o){await c(r,`SessionEnd`,{session_id:e,cwd:t,hook_event_name:`SessionEnd`,reason:n,...a!==void 0&&{permission_mode:a},...o!==void 0&&{transcript_path:o},env:{CLAUDE_PROJECT_DIR:t,CLAUDE_SESSION_ID:e}},i)}var N=class{getPermissionMode(){return this.permissionMode}setPermissionMode(e){this.permissionMode=e}getSessionId(){return this.sessionId}getSystemMessage(){return this.systemMessage}updateSystemMessage(e){this.systemMessage=e,this.robota.setModel({provider:this.aiProvider.name,model:this.model,systemMessage:e})}getToolSchemas(){return this.toolSchemas}getMessageCount(){return this.messageCount}getSessionAllowedTools(){return this.permissionEnforcer.getSessionAllowedTools()}clearSessionAllowedTools(){this.permissionEnforcer.clearSessionAllowedTools()}abort(){this.abortController&&=(this.abortController.abort(),null)}isRunning(){return this.abortController!==null}getContextState(){return this.contextTracker.getContextState()}getAutoCompactThreshold(){return this.contextTracker.getAutoCompactThreshold()}setAutoCompactThreshold(e){this.contextTracker.setAutoCompactThreshold(e)}getHistory(){return this.robota.getHistory()}getFullHistory(){return this.robota.getFullHistory()}addHistoryEntry(e){this.robota.addHistoryEntry(e)}injectMessage(e,t,n){this.robota.injectMessage(e,t,n)}clearHistory(){this.robota.clearHistory(),this.contextTracker.reset()}};const P={success:!0,data:JSON.stringify({success:!1,output:``,error:`Permission denied. The user did not approve this action.`}),metadata:{}};function F(e){if(typeof e.data!=`string`||e.data.length<=3e4)return e;let t=15e3,n=e.data.substring(0,t),r=e.data.substring(e.data.length-t),i=`${n}\n\n[... output truncated: ${e.data.length.toLocaleString()} chars total, showing first and last ${t.toLocaleString()} chars ...]\n\n${r}`;return{...e,data:i}}function I(e,t,n,r,i,a){return{session_id:e,cwd:t,hook_event_name:`PreToolUse`,tool_name:n,tool_input:r,...i!==void 0&&{permission_mode:i},...a!==void 0&&{transcript_path:a}}}async function L(e,t,n){let r=await c(e,`PreToolUse`,t,n);return r.blocked?{success:!0,data:JSON.stringify({blocked:!0,reason:r.reason??`Blocked by hook`}),metadata:{}}:null}function R(e,t,n,r){c(e,`PostToolUse`,{...t,hook_event_name:`PostToolUse`,tool_output:typeof n.data==`string`?n.data:JSON.stringify(n.data)},r).catch(()=>{})}var z=class{sessionId;cwd;getPermissionMode;config;terminal;permissionHandler;promptForApprovalFn;sessionLogger;onToolExecution;hookTypeExecutors;transcriptPath;sessionAllowedTools=new Set;constructor(e){this.sessionId=e.sessionId,this.cwd=e.cwd,this.getPermissionMode=e.getPermissionMode,this.config=e.config,this.terminal=e.terminal,this.permissionHandler=e.permissionHandler,this.promptForApprovalFn=e.promptForApprovalFn,this.sessionLogger=e.sessionLogger,this.onToolExecution=e.onToolExecution,this.hookTypeExecutors=e.hookTypeExecutors,this.transcriptPath=e.transcriptPath}wrapTools(e){return e.map(e=>this.wrapToolWithPermission(e))}getSessionAllowedTools(){return[...this.sessionAllowedTools]}clearSessionAllowedTools(){this.sessionAllowedTools.clear()}wrapToolWithPermission(e){let t=this,n=e.execute.bind(e),r=Object.create(e);return r.execute=async(r,i)=>{try{let a=e.getName();t.log(`tool_call`,{tool:a,args:r});let o=I(t.sessionId,t.cwd,a,r,t.getPermissionMode(),t.transcriptPath),s=await L(t.config.hooks,o,t.hookTypeExecutors);if(s)return t.log(`tool_blocked`,{tool:a,reason:`hook`}),s;if(!await t.checkPermission(a,r))return t.log(`tool_denied`,{tool:a,reason:`permission`}),t.onToolExecution?.({type:`end`,toolName:a,toolArgs:r,success:!1,denied:!0}),P;t.onToolExecution?.({type:`start`,toolName:a,toolArgs:r});let c=await n(r,i),l=F(c);t.onToolExecution?.({type:`end`,toolName:a,toolArgs:r,success:l.success,toolResultData:typeof l.data==`string`?l.data:JSON.stringify(l.data)});let u=typeof l.data==`string`?l.data.length:JSON.stringify(l.data).length;return t.log(`tool_result`,{tool:a,success:l.success,dataChars:u,truncated:l!==c}),R(t.config.hooks,o,l,t.hookTypeExecutors),l}catch(e){let t=e instanceof Error?e.message:String(e);return{success:!0,data:JSON.stringify({success:!1,output:``,error:t}),metadata:{}}}},r}async checkPermission(e,t){let n=i(e,t,this.getPermissionMode(),{allow:this.config.permissions.allow,deny:this.config.permissions.deny});if(n===`auto`)return!0;if(n===`deny`)return!1;if(this.sessionAllowedTools.has(e))return!0;if(this.permissionHandler){let n=await this.permissionHandler(e,t);return n===`allow-session`?(this.sessionAllowedTools.add(e),!0):n}return this.promptForApprovalFn?this.promptForApprovalFn(this.terminal,e,t):!1}log(e,t){this.sessionLogger?.log(this.sessionId,e,t)}};const B=.835;var V=class{contextUsedTokens=0;contextMaxTokens;autoCompactThreshold;constructor(e,t,n){this.contextMaxTokens=t??a(e),this.autoCompactThreshold=H(n)}getContextState(){let e=Math.min(100,this.contextUsedTokens/this.contextMaxTokens*100);return{maxTokens:this.contextMaxTokens,usedTokens:this.contextUsedTokens,usedPercentage:Math.round(e*100)/100,remainingPercentage:Math.round((100-e)*100)/100}}shouldAutoCompact(){return this.autoCompactThreshold===!1?!1:this.getContextState().usedPercentage>=this.autoCompactThreshold*100}getAutoCompactThreshold(){return this.autoCompactThreshold}setAutoCompactThreshold(e){this.autoCompactThreshold=H(e)}updateFromHistory(e){this.contextUsedTokens=r(e).usedTokens}reset(){this.contextUsedTokens=0}};function H(e){if(e===void 0)return B;if(e===!1)return!1;if(!Number.isFinite(e)||e<=0||e>1)throw RangeError(`autoCompactThreshold must be a number greater than 0 and at most 1.`);return e}var U=class{sessionId;cwd;model;hooks;compactInstructions;hookTypeExecutors;constructor(e){this.sessionId=e.sessionId,this.cwd=e.cwd,this.model=e.model,this.hooks=e.hooks,this.compactInstructions=e.compactInstructions,this.hookTypeExecutors=e.hookTypeExecutors}async compact(e,t,n){if(t.length===0)return``;let r=n===void 0?`auto`:`manual`,i={session_id:this.sessionId,cwd:this.cwd,hook_event_name:`PreCompact`,trigger:r};await c(this.hooks,`PreCompact`,i,this.hookTypeExecutors);let a=this.buildCompactionPrompt(t,n),o=await e.chat([{id:u(),role:`user`,content:a,state:`complete`,timestamp:new Date}],{model:this.model});return typeof o.content==`string`?o.content:`(compaction failed)`}buildCompactionPrompt(e,t){let n=t??this.compactInstructions??``;return[`Summarize the following conversation concisely, preserving:`,`- User's original requests and goals`,`- Key decisions and conclusions`,`- Important code changes and file paths`,`- Current task status and next steps`,n?`\nAdditional focus:\n${n}\n`:``,`Drop verbose tool outputs, debugging steps, and exploratory work that didn't lead to results.`,``,`Conversation:`,e.map(e=>{let t=typeof e.content==`string`?e.content:JSON.stringify(e.content);return`${e.role}: ${t}`}).join(`
1
+ import{Robota as e,TRUST_TO_MODE as t,createUserMessage as n,estimateContextTokensFromMessages as r,evaluatePermission as i,getModelContextWindow as a,getProviderCapabilities as o,messageToHistoryEntry as s,runHooks as c}from"@robota-sdk/agent-core";import{createHash as l,randomUUID as u}from"node:crypto";import{appendFileSync as d,existsSync as f,mkdirSync as p,readFileSync as m,writeFileSync as h}from"node:fs";import{join as g}from"node:path";import{existsSync as _,mkdirSync as ee,readFileSync as v,readdirSync as y,unlinkSync as b,writeFileSync as x}from"fs";import{join as S}from"path";var C=class{getPermissionMode(){return this.permissionMode}setPermissionMode(e){this.permissionMode=e}getSessionId(){return this.sessionId}getSystemMessage(){return this.systemMessage}updateSystemMessage(e){this.systemMessage=e,this.robota.setModel({provider:this.aiProvider.name,model:this.model,systemMessage:e})}getToolSchemas(){return this.toolSchemas}getMessageCount(){return this.messageCount}getSessionAllowedTools(){return this.permissionEnforcer.getSessionAllowedTools()}clearSessionAllowedTools(){this.permissionEnforcer.clearSessionAllowedTools()}abort(){this.abortController&&=(this.abortController.abort(),null)}isRunning(){return this.abortController!==null}getContextState(){return this.contextTracker.getContextState()}getAutoCompactThreshold(){return this.contextTracker.getAutoCompactThreshold()}setAutoCompactThreshold(e){this.contextTracker.setAutoCompactThreshold(e)}getHistory(){return this.robota.getHistory()}getFullHistory(){return this.robota.getFullHistory()}addHistoryEntry(e){this.robota.addHistoryEntry(e)}injectMessage(e,t,n){this.robota.injectMessage(e,t,n)}clearHistory(){this.robota.clearHistory(),this.contextTracker.reset()}},w=class{sessionId;cwd;model;hooks;compactInstructions;hookTypeExecutors;constructor(e){this.sessionId=e.sessionId,this.cwd=e.cwd,this.model=e.model,this.hooks=e.hooks,this.compactInstructions=e.compactInstructions,this.hookTypeExecutors=e.hookTypeExecutors}async compact(e,t,n){if(t.length===0)return``;let r=n===void 0?`auto`:`manual`,i={session_id:this.sessionId,cwd:this.cwd,hook_event_name:`PreCompact`,trigger:r};await c(this.hooks,`PreCompact`,i,this.hookTypeExecutors);let a=this.buildCompactionPrompt(t,n),o=await e.chat([{id:u(),role:`user`,content:a,state:`complete`,timestamp:new Date}],{model:this.model});return typeof o.content==`string`?o.content:`(compaction failed)`}buildCompactionPrompt(e,t){let n=t??this.compactInstructions??``;return[`Summarize the following conversation concisely, preserving:`,`- User's original requests and goals`,`- Key decisions and conclusions`,`- Important code changes and file paths`,`- Current task status and next steps`,n?`\nAdditional focus:\n${n}\n`:``,`Drop verbose tool outputs, debugging steps, and exploratory work that didn't lead to results.`,``,`Conversation:`,e.map(e=>{let t=typeof e.content==`string`?e.content:JSON.stringify(e.content);return`${e.role}: ${t}`}).join(`
3
2
  `)].join(`
4
- `)}};function W(e,t,n,r,i){return new z({sessionId:t,cwd:n,getPermissionMode:r,config:{permissions:e.permissions??{allow:[],deny:[]},hooks:e.hooks},terminal:e.terminal,permissionHandler:e.permissionHandler,promptForApprovalFn:e.promptForApproval,sessionLogger:e.sessionLogger,onToolExecution:e.onToolExecution,hookTypeExecutors:e.hookTypeExecutors,transcriptPath:i})}function G(e,t,n,r){return{contextTracker:new V(t,e.contextMaxTokens,e.autoCompactThreshold),compactionOrchestrator:new U({sessionId:n,cwd:r,model:t,hooks:e.hooks,compactInstructions:e.compactInstructions,hookTypeExecutors:e.hookTypeExecutors})}}function K(t,n,r,i,a,o){let s=n.wrapTools(r);return new e({name:t.agentName??`agent`,aiProviders:[i],defaultModel:{provider:i.name,model:a,systemMessage:o},systemMessage:o,tools:s,logging:{enabled:!1},...t.providerTimeout!==void 0&&{timeout:t.providerTimeout}})}var q=class extends N{robota;permissionEnforcer;contextTracker;permissionMode;sessionId;aiProvider;toolSchemas;model;systemMessage;messageCount=0;abortController=null;terminal;sessionStore;cwd;hooks;hookTypeExecutors;onTextDeltaCallback;onContextUpdateCallback;onToolExecutionCallback;onCompactCallback;onCompactEventCallback;sessionLogger;maxTurns;compactionOrchestrator;shutdownPromise=null;sessionStartStdout=``;transcriptPath;constructor(e){super();let{tools:n,provider:r,systemMessage:i}=e;this.terminal=e.terminal,this.sessionStore=e.sessionStore,this.systemMessage=i,this.toolSchemas=n.map(e=>e.schema),this.cwd=process.cwd(),this.sessionLogger=e.sessionLogger,this.hooks=e.hooks,this.hookTypeExecutors=e.hookTypeExecutors,this.onTextDeltaCallback=e.onTextDelta,this.onContextUpdateCallback=e.onContextUpdate,this.onToolExecutionCallback=e.onToolExecution,this.onCompactCallback=e.onCompact,this.onCompactEventCallback=e.onCompactEvent,this.maxTurns=e.maxTurns,this.model=e.model??`claude-sonnet-4-5`,this.sessionId=e.sessionId??`session_${Date.now()}_${Math.random().toString(36).substr(2,9)}`,this.permissionMode=e.permissionMode??(e.defaultTrustLevel?t[e.defaultTrustLevel]:void 0)??`default`,this.transcriptPath=e.sessionStore?.getFilePath?.(this.sessionId),this.log(`session_init`,{cwd:this.cwd,systemPromptLength:i.length,systemPrompt:i,toolSchemas:this.toolSchemas,model:this.model,provider:r.name}),this.aiProvider=r,A(r,e,(e,t)=>this.log(e,t)),this.permissionEnforcer=W(e,this.sessionId,this.cwd,()=>this.permissionMode,this.transcriptPath);let{contextTracker:a,compactionOrchestrator:o}=G(e,this.model,this.sessionId,this.cwd);this.contextTracker=a,this.compactionOrchestrator=o,this.robota=K(e,this.permissionEnforcer,n,r,this.model,i),j(this.sessionId,this.cwd,this.hooks,this.hookTypeExecutors,e=>void(this.sessionStartStdout=e),this.permissionMode,this.transcriptPath)}async run(e,t){this.abortController=new AbortController;let{signal:n}=this.abortController;try{let r=await ae(e,t,this.buildRunContext(),n);return this.messageCount+=1,r}finally{this.abortController=null}}log(e,t){this.sessionLogger?.log(this.sessionId,e,t)}persistSessionInternal(){this.sessionStore&&k({sessionId:this.sessionId,cwd:this.cwd,systemPrompt:this.systemMessage,toolSchemas:this.toolSchemas,sessionStore:this.sessionStore,robota:this.robota,getFullHistory:()=>this.getFullHistory()})}shutdown(e={}){if(this.shutdownPromise)return this.shutdownPromise;let t=e.reason??`other`;return this.shutdownPromise=(async()=>{this.abort(),this.log(`session_shutdown`,{reason:t}),this.persistSessionInternal(),await M(this.sessionId,this.cwd,t,this.hooks,this.hookTypeExecutors,this.permissionMode,this.transcriptPath)})(),this.shutdownPromise}async compact(e,t=`manual`){await O(e,{sessionId:this.sessionId,cwd:this.cwd,systemMessage:this.systemMessage,robota:this.robota,aiProvider:this.aiProvider,compactionOrchestrator:this.compactionOrchestrator,contextTracker:this.contextTracker,hooks:this.hooks,hookTypeExecutors:this.hookTypeExecutors,onCompactCallback:this.onCompactCallback,onCompactEventCallback:this.onCompactEventCallback,trigger:t,log:(e,t)=>this.log(e,t)})}buildRunContext(){return{sessionId:this.sessionId,cwd:this.cwd,model:this.model,robota:this.robota,aiProvider:this.aiProvider,contextTracker:this.contextTracker,hooks:this.hooks,hookTypeExecutors:this.hookTypeExecutors,sessionStartStdout:this.sessionStartStdout,log:(e,t)=>this.log(e,t),compact:()=>this.compact(void 0,`auto`),persistSession:()=>this.persistSessionInternal(),getSessionStore:()=>!!this.sessionStore,clearSessionStartStdout:()=>void(this.sessionStartStdout=``),permissionMode:this.permissionMode,transcriptPath:this.transcriptPath,maxTurns:this.maxTurns,onTextDelta:this.onTextDeltaCallback,onContextUpdate:this.onContextUpdateCallback,onToolExecution:this.onToolExecutionCallback,knownToolNames:this.toolSchemas.map(e=>e.name)}}};const oe=/^(api[-_]?key|authorization|access[-_]?token|refresh[-_]?token|secret|password|x[-_]?api[-_]?key)$/i;var se=class{logDir;options;constructor(e,t={}){this.logDir=e,this.options={externalPayloadThresholdBytes:t.externalPayloadThresholdBytes??32768,redactedValue:t.redactedValue??`[REDACTED]`};try{p(e,{recursive:!0})}catch{}}log(e,t,n){try{let r=ce(e,this.logDir,n,this.options),i=JSON.stringify({timestamp:new Date().toISOString(),sessionId:e,event:t,...r});d(g(this.logDir,`${e}.jsonl`),i+`
3
+ `)}};const T=.835;var E=class{contextUsedTokens=0;contextMaxTokens;autoCompactThreshold;constructor(e,t,n){this.contextMaxTokens=t??a(e),this.autoCompactThreshold=D(n)}getContextState(){let e=Math.min(100,this.contextUsedTokens/this.contextMaxTokens*100);return{maxTokens:this.contextMaxTokens,usedTokens:this.contextUsedTokens,usedPercentage:Math.round(e*100)/100,remainingPercentage:Math.round((100-e)*100)/100}}shouldAutoCompact(){return this.autoCompactThreshold===!1?!1:this.getContextState().usedPercentage>=this.autoCompactThreshold*100}getAutoCompactThreshold(){return this.autoCompactThreshold}setAutoCompactThreshold(e){this.autoCompactThreshold=D(e)}updateFromHistory(e){this.contextUsedTokens=r(e).usedTokens}reset(){this.contextUsedTokens=0}};function D(e){if(e===void 0)return T;if(e===!1)return!1;if(!Number.isFinite(e)||e<=0||e>1)throw RangeError(`autoCompactThreshold must be a number greater than 0 and at most 1.`);return e}const te={success:!0,data:JSON.stringify({success:!1,output:``,error:`Permission denied. The user did not approve this action.`}),metadata:{}};function ne(e){if(typeof e.data!=`string`||e.data.length<=3e4)return e;let t=15e3,n=e.data.substring(0,t),r=e.data.substring(e.data.length-t),i=`${n}\n\n[... output truncated: ${e.data.length.toLocaleString()} chars total, showing first and last ${t.toLocaleString()} chars ...]\n\n${r}`;return{...e,data:i}}function re(e,t,n,r,i,a){return{session_id:e,cwd:t,hook_event_name:`PreToolUse`,tool_name:n,tool_input:r,...i!==void 0&&{permission_mode:i},...a!==void 0&&{transcript_path:a}}}async function ie(e,t,n){let r=await c(e,`PreToolUse`,t,n);return r.blocked?{success:!0,data:JSON.stringify({blocked:!0,reason:r.reason??`Blocked by hook`}),metadata:{}}:null}function ae(e,t,n,r){c(e,`PostToolUse`,{...t,hook_event_name:`PostToolUse`,tool_output:typeof n.data==`string`?n.data:JSON.stringify(n.data)},r).catch(()=>{})}var O=class{sessionId;cwd;getPermissionMode;config;terminal;permissionHandler;promptForApprovalFn;sessionLogger;onToolExecution;hookTypeExecutors;transcriptPath;sessionAllowedTools=new Set;constructor(e){this.sessionId=e.sessionId,this.cwd=e.cwd,this.getPermissionMode=e.getPermissionMode,this.config=e.config,this.terminal=e.terminal,this.permissionHandler=e.permissionHandler,this.promptForApprovalFn=e.promptForApprovalFn,this.sessionLogger=e.sessionLogger,this.onToolExecution=e.onToolExecution,this.hookTypeExecutors=e.hookTypeExecutors,this.transcriptPath=e.transcriptPath}wrapTools(e){return e.map(e=>this.wrapToolWithPermission(e))}getSessionAllowedTools(){return[...this.sessionAllowedTools]}clearSessionAllowedTools(){this.sessionAllowedTools.clear()}wrapToolWithPermission(e){let t=this,n=e.execute.bind(e),r=Object.create(e);return r.execute=async(r,i)=>{try{let a=e.getName();t.log(`tool_call`,{tool:a,args:r});let o=re(t.sessionId,t.cwd,a,r,t.getPermissionMode(),t.transcriptPath),s=await ie(t.config.hooks,o,t.hookTypeExecutors);if(s)return t.log(`tool_blocked`,{tool:a,reason:`hook`}),s;if(!await t.checkPermission(a,r))return t.log(`tool_denied`,{tool:a,reason:`permission`}),t.onToolExecution?.({type:`end`,toolName:a,toolArgs:r,success:!1,denied:!0}),te;t.onToolExecution?.({type:`start`,toolName:a,toolArgs:r});let c=await n(r,i),l=ne(c);t.onToolExecution?.({type:`end`,toolName:a,toolArgs:r,success:l.success,toolResultData:typeof l.data==`string`?l.data:JSON.stringify(l.data)});let u=typeof l.data==`string`?l.data.length:JSON.stringify(l.data).length;return t.log(`tool_result`,{tool:a,success:l.success,dataChars:u,truncated:l!==c}),ae(t.config.hooks,o,l,t.hookTypeExecutors),l}catch(e){let t=e instanceof Error?e.message:String(e);return{success:!0,data:JSON.stringify({success:!1,output:``,error:t}),metadata:{}}}},r}async checkPermission(e,t){let n=i(e,t,this.getPermissionMode(),{allow:this.config.permissions.allow,deny:this.config.permissions.deny});if(n===`auto`)return!0;if(n===`deny`)return!1;if(this.sessionAllowedTools.has(e))return!0;if(this.permissionHandler){let n=await this.permissionHandler(e,t);return n===`allow-session`?(this.sessionAllowedTools.add(e),!0):n}return this.promptForApprovalFn?this.promptForApprovalFn(this.terminal,e,t):!1}log(e,t){this.sessionLogger?.log(this.sessionId,e,t)}};function k(e,t,n,r,i){return new O({sessionId:t,cwd:n,getPermissionMode:r,config:{permissions:e.permissions??{allow:[],deny:[]},hooks:e.hooks},terminal:e.terminal,permissionHandler:e.permissionHandler,promptForApprovalFn:e.promptForApproval,sessionLogger:e.sessionLogger,onToolExecution:e.onToolExecution,hookTypeExecutors:e.hookTypeExecutors,transcriptPath:i})}function A(e,t,n,r){return{contextTracker:new E(t,e.contextMaxTokens,e.autoCompactThreshold),compactionOrchestrator:new w({sessionId:n,cwd:r,model:t,hooks:e.hooks,compactInstructions:e.compactInstructions,hookTypeExecutors:e.hookTypeExecutors})}}function j(t,n,r,i,a,o){let s=n.wrapTools(r);return new e({name:t.agentName??`agent`,aiProviders:[i],defaultModel:{provider:i.name,model:a,systemMessage:o},systemMessage:o,tools:s,logging:{enabled:!1},...t.providerTimeout!==void 0&&{timeout:t.providerTimeout}})}async function M(e,t){let n=t.robota.getHistory();if(n.length===0)return;t.contextTracker.updateFromHistory(n);let r=t.contextTracker.getContextState(),i=n.filter(e=>e.role!==`system`),a=await t.compactionOrchestrator.compact(t.aiProvider,i,e);t.robota.clearHistory(),t.robota.injectMessage(`system`,t.systemMessage),t.robota.injectMessage(`assistant`,`[Context Summary]\n${a}`),t.contextTracker.updateFromHistory(t.robota.getHistory());let o={session_id:t.sessionId,cwd:t.cwd,hook_event_name:`PostCompact`,trigger:t.trigger,compact_summary:a};c(t.hooks,`PostCompact`,o,t.hookTypeExecutors).catch(()=>{});let s=t.contextTracker.getContextState();t.log(`context_compact`,{trigger:t.trigger,before:r,after:s}),t.onCompactEventCallback?.({trigger:t.trigger,before:r,after:s}),t.onCompactCallback&&t.onCompactCallback(a)}function N(e){let t=e.robota.getHistory(),n=new Date().toISOString(),r=e.sessionStore.load(e.sessionId),i={id:e.sessionId,name:r?.name,cwd:e.cwd,createdAt:r?.createdAt??n,updatedAt:n,messages:t,history:e.getFullHistory(),systemPrompt:e.systemPrompt,toolSchemas:e.toolSchemas};e.sessionStore.save(i)}function P(e,t,n){e.configureNativeWebTools?.({webSearch:!0}),`onServerToolUse`in e&&(e.onServerToolUse=(e,t)=>{n(`server_tool`,{tool:e,...t})})}function F(e,t,n,r,i,a,o){c(n,`SessionStart`,{session_id:e,cwd:t,hook_event_name:`SessionStart`,...a!==void 0&&{permission_mode:a},...o!==void 0&&{transcript_path:o},env:{CLAUDE_PROJECT_DIR:t,CLAUDE_SESSION_ID:e}},r).then(e=>{e.stdout&&i(e.stdout)}).catch(()=>{})}async function I(e,t,n,r,i,a,o){await c(r,`SessionEnd`,{session_id:e,cwd:t,hook_event_name:`SessionEnd`,reason:n,...a!==void 0&&{permission_mode:a},...o!==void 0&&{transcript_path:o},env:{CLAUDE_PROJECT_DIR:t,CLAUDE_SESSION_ID:e}},i)}const L=`unknown_tool`;function R(e){return{knownToolNames:new Set(e.knownToolNames),unknownToolCallIds:new Set,...e.onToolExecution&&{onToolExecution:e.onToolExecution}}}function z(e,t,n){if(e.onToolExecution){if(t===`tool_execution_request`){B(e,n);return}t===`tool_execution_result`&&V(e,n)}}function B(e,t){let n=U(t.toolName),r=U(t.toolCallId);!n||!r||e.knownToolNames.has(n)||(e.unknownToolCallIds.add(r),e.onToolExecution?.({type:`start`,toolName:n,toolArgs:H(t.parameters)}))}function V(e,t){let n=U(t.toolName),r=U(t.toolCallId);if(!n||!r)return;let i=W(t.metadata);if(!(e.unknownToolCallIds.has(r)||i?.errorCode===L))return;e.unknownToolCallIds.delete(r);let a=U(t.error)??`Tool "${n}" is not registered.`;e.onToolExecution?.({type:`end`,toolName:n,success:!1,toolResultData:JSON.stringify({success:!1,error:a,errorCode:L,requestedTool:U(i?.requestedTool)??n,availableTools:G(i?.availableTools)})})}function H(e){let t=W(e);if(!t)return;let n={};for(let[e,r]of Object.entries(t))(typeof r==`string`||typeof r==`number`||typeof r==`boolean`||typeof r==`object`&&r)&&(n[e]=r);return n}function U(e){return typeof e==`string`&&e.length>0?e:void 0}function W(e){return typeof e==`object`&&e&&!Array.isArray(e)?e:void 0}function G(e){return Array.isArray(e)?e.filter(e=>typeof e==`string`):[]}async function K(e,t,r,i){if(r.contextTracker.updateFromHistory(r.robota.getHistory()),r.contextTracker.shouldAutoCompact()){let e=r.aiProvider,t=e.onTextDelta;e.onTextDelta=void 0;try{await r.compact()}finally{e.onTextDelta=t}}r.log(`user`,{content:e});let a=await c(r.hooks,`UserPromptSubmit`,{session_id:r.sessionId,cwd:r.cwd,hook_event_name:`UserPromptSubmit`,user_message:t??e,prompt:t??e,...r.permissionMode!==void 0&&{permission_mode:r.permissionMode},...r.transcriptPath!==void 0&&{transcript_path:r.transcriptPath},env:{CLAUDE_PROJECT_DIR:r.cwd,CLAUDE_SESSION_ID:r.sessionId}},r.hookTypeExecutors),s=[r.sessionStartStdout,a.stdout].filter(Boolean).join(`
4
+ `),l=s?`<system-reminder>\n${s}\n</system-reminder>\n${e}`:e;r.clearSessionStartStdout();let u=r.robota.getHistory(),d=JSON.stringify(u),f=o(r.aiProvider);r.log(`pre_run`,{historyLength:u.length,historyChars:d.length,historyEstTokens:Math.ceil(d.length/4),input:l,history:u,model:r.model,provider:r.aiProvider.name,maxTokens:r.contextTracker.getContextState().maxTokens,nativeWebSearchSupported:f.nativeWebTools.webSearch.supported,nativeWebSearchEnabled:f.nativeWebTools.webSearch.enabled,nativeWebFetchSupported:f.nativeWebTools.webFetch.supported,nativeWebFetchEnabled:f.nativeWebTools.webFetch.enabled}),r.contextTracker.updateFromHistory([...u,n(l)]),r.onContextUpdate?.(r.contextTracker.getContextState());let p;try{let e=R({knownToolNames:r.knownToolNames??[],...r.onToolExecution&&{onToolExecution:r.onToolExecution}}),t=r.onTextDelta?e=>{r.log(`text_delta`,{delta:e}),r.onTextDelta?.(e)}:void 0;if(p=await r.robota.run(l,{signal:i,maxExecutionRounds:r.maxTurns??0,onExecutionEvent:(t,n)=>{r.log(t,n),z(e,t,n)},...t&&{onTextDelta:t}}),i.aborted)throw new DOMException(`Aborted`,`AbortError`)}catch(e){throw r.log(`error`,{message:e instanceof Error?e.message:String(e),stack:e instanceof Error?e.stack??``:``,historyLength:r.robota.getHistory().length}),c(r.hooks,`StopFailure`,{session_id:r.sessionId,cwd:r.cwd,hook_event_name:`StopFailure`,reason:e instanceof Error?e.message:String(e),stop_hook_active:!1,...r.permissionMode!==void 0&&{permission_mode:r.permissionMode},...r.transcriptPath!==void 0&&{transcript_path:r.transcriptPath},env:{CLAUDE_PROJECT_DIR:r.cwd,CLAUDE_SESSION_ID:r.sessionId}},r.hookTypeExecutors).catch(()=>{}),e}let m=r.robota.getHistory(),h=m.map(e=>{let t=`toolCalls`in e&&Array.isArray(e.toolCalls)&&e.toolCalls.length>0,n=t?e.toolCalls.map(e=>e.function.name):[];return{role:e.role,contentLength:typeof e.content==`string`?e.content.length:0,hasToolCalls:t,toolCallNames:n,...e.metadata?{metadata:e.metadata}:{}}});r.log(`assistant`,{content:p,historyLength:m.length,estimatedChars:JSON.stringify(m).length,history:m,historyStructure:h}),r.contextTracker.updateFromHistory(m);let g=r.contextTracker.getContextState();return r.onContextUpdate?.(g),r.log(`context`,{maxTokens:g.maxTokens,usedTokens:g.usedTokens,usedPercentage:g.usedPercentage,remainingPercentage:g.remainingPercentage}),c(r.hooks,`Stop`,{session_id:r.sessionId,cwd:r.cwd,hook_event_name:`Stop`,response:p.substring(0,500),last_assistant_message:p,stop_hook_active:!1,...r.permissionMode!==void 0&&{permission_mode:r.permissionMode},...r.transcriptPath!==void 0&&{transcript_path:r.transcriptPath},env:{CLAUDE_PROJECT_DIR:r.cwd,CLAUDE_SESSION_ID:r.sessionId}},r.hookTypeExecutors).catch(()=>{}),r.getSessionStore()&&r.persistSession(),p}var q=class extends C{robota;permissionEnforcer;contextTracker;permissionMode;sessionId;aiProvider;toolSchemas;model;systemMessage;messageCount=0;abortController=null;terminal;sessionStore;cwd;hooks;hookTypeExecutors;onTextDeltaCallback;onContextUpdateCallback;onToolExecutionCallback;onCompactCallback;onCompactEventCallback;sessionLogger;maxTurns;compactionOrchestrator;shutdownPromise=null;sessionStartStdout=``;transcriptPath;constructor(e){super();let{tools:n,provider:r,systemMessage:i}=e;this.terminal=e.terminal,this.sessionStore=e.sessionStore,this.systemMessage=i,this.toolSchemas=n.map(e=>e.schema),this.cwd=process.cwd(),this.sessionLogger=e.sessionLogger,this.hooks=e.hooks,this.hookTypeExecutors=e.hookTypeExecutors,this.onTextDeltaCallback=e.onTextDelta,this.onContextUpdateCallback=e.onContextUpdate,this.onToolExecutionCallback=e.onToolExecution,this.onCompactCallback=e.onCompact,this.onCompactEventCallback=e.onCompactEvent,this.maxTurns=e.maxTurns,this.model=e.model??`claude-sonnet-4-5`,this.sessionId=e.sessionId??`session_${Date.now()}_${Math.random().toString(36).substr(2,9)}`,this.permissionMode=e.permissionMode??(e.defaultTrustLevel?t[e.defaultTrustLevel]:void 0)??`default`,this.transcriptPath=e.sessionStore?.getFilePath?.(this.sessionId),this.log(`session_init`,{cwd:this.cwd,systemPromptLength:i.length,systemPrompt:i,toolSchemas:this.toolSchemas,model:this.model,provider:r.name}),this.aiProvider=r,P(r,e,(e,t)=>this.log(e,t)),this.permissionEnforcer=k(e,this.sessionId,this.cwd,()=>this.permissionMode,this.transcriptPath);let{contextTracker:a,compactionOrchestrator:o}=A(e,this.model,this.sessionId,this.cwd);this.contextTracker=a,this.compactionOrchestrator=o,this.robota=j(e,this.permissionEnforcer,n,r,this.model,i),F(this.sessionId,this.cwd,this.hooks,this.hookTypeExecutors,e=>void(this.sessionStartStdout=e),this.permissionMode,this.transcriptPath)}async run(e,t){this.abortController=new AbortController;let{signal:n}=this.abortController;try{let r=await K(e,t,this.buildRunContext(),n);return this.messageCount+=1,r}finally{this.abortController=null}}log(e,t){this.sessionLogger?.log(this.sessionId,e,t)}persistSessionInternal(){this.sessionStore&&N({sessionId:this.sessionId,cwd:this.cwd,systemPrompt:this.systemMessage,toolSchemas:this.toolSchemas,sessionStore:this.sessionStore,robota:this.robota,getFullHistory:()=>this.getFullHistory()})}shutdown(e={}){if(this.shutdownPromise)return this.shutdownPromise;let t=e.reason??`other`;return this.shutdownPromise=(async()=>{this.abort(),this.log(`session_shutdown`,{reason:t}),this.persistSessionInternal(),await I(this.sessionId,this.cwd,t,this.hooks,this.hookTypeExecutors,this.permissionMode,this.transcriptPath)})(),this.shutdownPromise}async compact(e,t=`manual`){await M(e,{sessionId:this.sessionId,cwd:this.cwd,systemMessage:this.systemMessage,robota:this.robota,aiProvider:this.aiProvider,compactionOrchestrator:this.compactionOrchestrator,contextTracker:this.contextTracker,hooks:this.hooks,hookTypeExecutors:this.hookTypeExecutors,onCompactCallback:this.onCompactCallback,onCompactEventCallback:this.onCompactEventCallback,trigger:t,log:(e,t)=>this.log(e,t)})}buildRunContext(){return{sessionId:this.sessionId,cwd:this.cwd,model:this.model,robota:this.robota,aiProvider:this.aiProvider,contextTracker:this.contextTracker,hooks:this.hooks,hookTypeExecutors:this.hookTypeExecutors,sessionStartStdout:this.sessionStartStdout,log:(e,t)=>this.log(e,t),compact:()=>this.compact(void 0,`auto`),persistSession:()=>this.persistSessionInternal(),getSessionStore:()=>!!this.sessionStore,clearSessionStartStdout:()=>void(this.sessionStartStdout=``),permissionMode:this.permissionMode,transcriptPath:this.transcriptPath,maxTurns:this.maxTurns,onTextDelta:this.onTextDeltaCallback,onContextUpdate:this.onContextUpdateCallback,onToolExecution:this.onToolExecutionCallback,knownToolNames:this.toolSchemas.map(e=>e.name)}}};const oe=/^(api[-_]?key|authorization|access[-_]?token|refresh[-_]?token|secret|password|x[-_]?api[-_]?key)$/i;var se=class{logDir;options;constructor(e,t={}){this.logDir=e,this.options={externalPayloadThresholdBytes:t.externalPayloadThresholdBytes??32768,redactedValue:t.redactedValue??`[REDACTED]`};try{p(e,{recursive:!0})}catch{}}log(e,t,n){try{let r=ce(e,this.logDir,n,this.options),i=JSON.stringify({timestamp:new Date().toISOString(),sessionId:e,event:t,...r});d(g(this.logDir,`${e}.jsonl`),i+`
5
5
  `)}catch{}}};function ce(e,t,n,r){let i={};for(let[a,o]of Object.entries(n))i[a]=J(e,t,a,o,r);return i}function J(e,t,n,r,i){if(oe.test(n))return i.redactedValue;if(r==null||typeof r==`string`||typeof r==`number`)return Y(e,t,r,i);if(typeof r==`boolean`)return r;if(r instanceof Date)return r.toISOString();if(Array.isArray(r))return Y(e,t,r.map(r=>J(e,t,n,r,i)),i);if(typeof r==`object`){let n=r,a={};for(let[r,o]of Object.entries(n))a[r]=J(e,t,r,o,i);return Y(e,t,a,i)}return String(r)}function Y(e,t,n,r){let i=JSON.stringify(n);if(i===void 0)return n;let a=Buffer.byteLength(i);if(a<=r.externalPayloadThresholdBytes)return n;let o=l(`sha256`).update(i).digest(`hex`),s=`${e}.payloads`,c=g(s,`${o}.json`),u=g(t,s),d=g(t,c);return p(u,{recursive:!0}),f(d)||h(d,i,`utf-8`),{kind:`external-payload`,encoding:`json`,sha256:o,byteLength:a,relativePath:c}}var le=class{log(){}};function ue(e){let t=[],n=de(),r=fe();return e.forEach((e,i)=>{X(e,i,t),pe(n,e,i),me(r,e,i)}),he(n,t),ge(r,t),{ok:t.length===0,issues:t}}function de(){return{requests:new Map,nativeRawPayloads:new Set,rawResponses:new Set,normalizedResponses:new Set}}function fe(){return{requests:new Map,results:new Set}}function pe(e,t,n){let r=_e(t);r&&(t.event===`provider_request`&&e.requests.set(r.key,{executionId:r.executionId,round:r.round,index:n}),t.event===`provider_response_raw`&&e.rawResponses.add(r.key),t.event===`provider_native_raw_payload`&&(t.payloadKind===`response`||t.payloadKind===`stream_event`)&&e.nativeRawPayloads.add(r.key),t.event===`provider_response_normalized`&&e.normalizedResponses.add(r.key))}function me(e,t,n){let r=ve(t);r&&(t.event===`tool_execution_request`&&e.requests.set(r.key,{executionId:r.executionId,toolCallId:r.toolCallId,index:n}),t.event===`tool_execution_result`&&e.results.add(r.key))}function he(e,t){for(let[n,r]of e.requests)e.nativeRawPayloads.has(n)||t.push({code:`PROVIDER_NATIVE_RAW_PAYLOAD_MISSING`,message:`Provider request ${n} has no provider-native raw response or stream payload event.`,eventIndex:r.index,executionId:r.executionId,round:r.round}),e.rawResponses.has(n)||t.push({code:`PROVIDER_RESPONSE_RAW_MISSING`,message:`Provider request ${n} has no raw response event.`,eventIndex:r.index,executionId:r.executionId,round:r.round}),e.normalizedResponses.has(n)||t.push({code:`PROVIDER_RESPONSE_NORMALIZED_MISSING`,message:`Provider request ${n} has no normalized response event.`,eventIndex:r.index,executionId:r.executionId,round:r.round})}function ge(e,t){for(let[n,r]of e.requests)e.results.has(n)||t.push({code:`TOOL_RESULT_MISSING`,message:`Tool request ${n} has no terminal result event.`,eventIndex:r.index,executionId:r.executionId,toolCallId:r.toolCallId})}function _e(e){if(typeof e.executionId!=`string`)return;let t=typeof e.round==`number`?e.round:Number(e.round);if(Number.isFinite(t))return{key:`${e.executionId}:${t}`,executionId:e.executionId,round:t}}function ve(e){if(typeof e.executionId!=`string`)return;let t=typeof e.toolCallId==`string`?e.toolCallId:typeof e.toolExecutionId==`string`?e.toolExecutionId:void 0;if(t)return{key:`${e.executionId}:${t}`,executionId:e.executionId,toolCallId:t}}function X(e,t,n){if(Array.isArray(e)){e.forEach(e=>X(e,t,n));return}if(ye(e)){if(e.kind===`external-payload`){(e.encoding!==`json`||typeof e.sha256!=`string`||typeof e.relativePath!=`string`||typeof e.byteLength!=`number`)&&n.push({code:`PAYLOAD_REFERENCE_INVALID`,message:`External payload reference is missing required replay fields.`,eventIndex:t});return}Object.values(e).forEach(e=>X(e,t,n))}}function ye(e){return typeof e==`object`&&!!e&&!Array.isArray(e)}function be(e){return f(e)?m(e,`utf-8`).split(`
6
- `).map(e=>e.trim()).filter(e=>e.length>0).map(e=>JSON.parse(e)):[]}function xe(e){let t=[],n=[],r={backgroundTaskEvents:[],backgroundJobGroupEvents:[],memoryEvents:[]},i,a,o,c;for(let l of e){if(i??=l.sessionId,o??=l.timestamp,c=l.timestamp,l.event===`session_init`&&(a=typeof l.cwd==`string`?l.cwd:a),l.event===`history_mutation`&&l.mutation===`append_message`){let e=Z(l.message);e&&(t.push(e),n.push(s(e)))}Se(l,r)}return{sessionId:i,cwd:a,createdAt:o,updatedAt:c,messages:t,history:n,backgroundTaskEvents:r.backgroundTaskEvents,backgroundJobGroupEvents:r.backgroundJobGroupEvents,memoryEvents:r.memoryEvents}}function Se(e,t){if(e.event===`background_task_event`){$(t.backgroundTaskEvents,e,`backgroundEvent`,`data`);return}if(e.event===`background_job_group_event`){$(t.backgroundJobGroupEvents,e,`backgroundJobGroupEvent`,`data`);return}e.event===`memory_event`&&$(t.memoryEvents,e,`memoryEvent`,`data`)}function Z(e){if(!Ce(e))return;let t=e.role;if(t!==`user`&&t!==`assistant`&&t!==`system`&&t!==`tool`)return;let n=typeof e.id==`string`?e.id:`${t}-${Date.now()}`,r=e.timestamp instanceof Date?e.timestamp:new Date(typeof e.timestamp==`string`?e.timestamp:Date.now());return{...e,id:n,role:t,timestamp:r}}function Ce(e){return typeof e==`object`&&!!e&&!Array.isArray(e)}function Q(e,t){let n=e[t];if(!(typeof n!=`object`||!n||Array.isArray(n)||n instanceof Date))return n}function $(e,t,n,r){let i=Q(t,n)??Q(t,r);i&&e.push(i)}function we(){return process.env.HOME??process.env.USERPROFILE??`/`}var Te=class{baseDir;constructor(e){this.baseDir=e??x(we(),`.robota`,`sessions`)}ensureDir(){_(this.baseDir)||v(this.baseDir,{recursive:!0})}filePath(e){return x(this.baseDir,`${e}.json`)}getFilePath(e){return this.filePath(e)}save(e){this.ensureDir(),te(this.filePath(e.id),JSON.stringify(e,null,2),`utf-8`)}load(e){let t=this.filePath(e);if(!_(t))return;let n=y(t,`utf-8`);return JSON.parse(n)}list(){if(!_(this.baseDir))return[];let e=b(this.baseDir).filter(e=>e.endsWith(`.json`)),t=[];for(let n of e)try{let e=y(x(this.baseDir,n),`utf-8`),r=JSON.parse(e);t.push(r)}catch{}return t.sort((e,t)=>new Date(t.updatedAt).getTime()-new Date(e.updatedAt).getTime())}delete(e){let t=this.filePath(e);_(t)&&ee(t)}};export{B as AUTO_COMPACT_THRESHOLD,U as CompactionOrchestrator,V as ContextWindowTracker,se as FileSessionLogger,z as PermissionEnforcer,q as Session,Te as SessionStore,le as SilentSessionLogger,be as loadSessionLogEntries,xe as replaySessionLogEntries,ue as validateSessionReplayLogEntries};
6
+ `).map(e=>e.trim()).filter(e=>e.length>0).map(e=>JSON.parse(e)):[]}function xe(e){let t=[],n=[],r={backgroundTaskEvents:[],backgroundJobGroupEvents:[],memoryEvents:[]},i,a,o,c;for(let l of e){if(i??=l.sessionId,o??=l.timestamp,c=l.timestamp,l.event===`session_init`&&(a=typeof l.cwd==`string`?l.cwd:a),l.event===`history_mutation`&&l.mutation===`append_message`){let e=Z(l.message);e&&(t.push(e),n.push(s(e)))}Se(l,r)}return{sessionId:i,cwd:a,createdAt:o,updatedAt:c,messages:t,history:n,backgroundTaskEvents:r.backgroundTaskEvents,backgroundJobGroupEvents:r.backgroundJobGroupEvents,memoryEvents:r.memoryEvents}}function Se(e,t){if(e.event===`background_task_event`){$(t.backgroundTaskEvents,e,`backgroundEvent`,`data`);return}if(e.event===`background_job_group_event`){$(t.backgroundJobGroupEvents,e,`backgroundJobGroupEvent`,`data`);return}e.event===`memory_event`&&$(t.memoryEvents,e,`memoryEvent`,`data`)}function Z(e){if(!Ce(e))return;let t=e.role;if(t!==`user`&&t!==`assistant`&&t!==`system`&&t!==`tool`)return;let n=typeof e.id==`string`?e.id:`${t}-${Date.now()}`,r=e.timestamp instanceof Date?e.timestamp:new Date(typeof e.timestamp==`string`?e.timestamp:Date.now());return{...e,id:n,role:t,timestamp:r}}function Ce(e){return typeof e==`object`&&!!e&&!Array.isArray(e)}function Q(e,t){let n=e[t];if(!(typeof n!=`object`||!n||Array.isArray(n)||n instanceof Date))return n}function $(e,t,n,r){let i=Q(t,n)??Q(t,r);i&&e.push(i)}function we(){return process.env.HOME??process.env.USERPROFILE??`/`}var Te=class{baseDir;constructor(e){this.baseDir=e??S(we(),`.robota`,`sessions`)}ensureDir(){_(this.baseDir)||ee(this.baseDir,{recursive:!0})}filePath(e){return S(this.baseDir,`${e}.json`)}getFilePath(e){return this.filePath(e)}save(e){this.ensureDir(),x(this.filePath(e.id),JSON.stringify(e,null,2),`utf-8`)}load(e){let t=this.filePath(e);if(!_(t))return;let n=v(t,`utf-8`);return JSON.parse(n)}list(){if(!_(this.baseDir))return[];let e=y(this.baseDir).filter(e=>e.endsWith(`.json`)),t=[];for(let n of e)try{let e=v(S(this.baseDir,n),`utf-8`),r=JSON.parse(e);t.push(r)}catch{}return t.sort((e,t)=>new Date(t.updatedAt).getTime()-new Date(e.updatedAt).getTime())}delete(e){let t=this.filePath(e);_(t)&&b(t)}};export{T as AUTO_COMPACT_THRESHOLD,w as CompactionOrchestrator,E as ContextWindowTracker,se as FileSessionLogger,O as PermissionEnforcer,q as Session,Te as SessionStore,le as SilentSessionLogger,be as loadSessionLogEntries,xe as replaySessionLogEntries,ue as validateSessionReplayLogEntries};
7
7
  //# sourceMappingURL=index.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","names":["isRecord","join","existsSync","readFileSync"],"sources":["../../src/session-tool-execution-bridge.ts","../../src/session-run.ts","../../src/session-history-ops.ts","../../src/session-lifecycle.ts","../../src/session-base.ts","../../src/permission-types.ts","../../src/tool-hook-helpers.ts","../../src/permission-enforcer.ts","../../src/context-window-tracker.ts","../../src/compaction-orchestrator.ts","../../src/session-components.ts","../../src/session.ts","../../src/session-logger.ts","../../src/session-log-validation.ts","../../src/session-log-replay.ts","../../src/session-store.ts"],"sourcesContent":["import type { TExecutionEventData, TToolArgs } from '@robota-sdk/agent-core';\nimport type { ISessionOptions } from './session-types.js';\n\nconst UNKNOWN_TOOL_ERROR_CODE = 'unknown_tool';\n\ntype TToolExecutionCallback = NonNullable<ISessionOptions['onToolExecution']>;\n\nexport interface IToolExecutionBridge {\n knownToolNames: ReadonlySet<string>;\n unknownToolCallIds: Set<string>;\n onToolExecution?: TToolExecutionCallback;\n}\n\nexport function createToolExecutionBridge(options: {\n knownToolNames: readonly string[];\n onToolExecution?: TToolExecutionCallback;\n}): IToolExecutionBridge {\n return {\n knownToolNames: new Set(options.knownToolNames),\n unknownToolCallIds: new Set<string>(),\n ...(options.onToolExecution && { onToolExecution: options.onToolExecution }),\n };\n}\n\nexport function forwardToolExecutionEvent(\n bridge: IToolExecutionBridge,\n event: string,\n data: TExecutionEventData,\n): void {\n if (!bridge.onToolExecution) return;\n if (event === 'tool_execution_request') {\n forwardUnknownToolStart(bridge, data);\n return;\n }\n if (event === 'tool_execution_result') {\n forwardUnknownToolEnd(bridge, data);\n }\n}\n\nfunction forwardUnknownToolStart(bridge: IToolExecutionBridge, data: TExecutionEventData): void {\n const toolName = getString(data.toolName);\n const toolCallId = getString(data.toolCallId);\n if (!toolName || !toolCallId || bridge.knownToolNames.has(toolName)) return;\n\n bridge.unknownToolCallIds.add(toolCallId);\n bridge.onToolExecution?.({\n type: 'start',\n toolName,\n toolArgs: toToolArgs(data.parameters),\n });\n}\n\nfunction forwardUnknownToolEnd(bridge: IToolExecutionBridge, data: TExecutionEventData): void {\n const toolName = getString(data.toolName);\n const toolCallId = getString(data.toolCallId);\n if (!toolName || !toolCallId) return;\n\n const metadata = getRecord(data.metadata);\n const isUnknown =\n bridge.unknownToolCallIds.has(toolCallId) || metadata?.errorCode === UNKNOWN_TOOL_ERROR_CODE;\n if (!isUnknown) return;\n\n bridge.unknownToolCallIds.delete(toolCallId);\n const error = getString(data.error) ?? `Tool \"${toolName}\" is not registered.`;\n bridge.onToolExecution?.({\n type: 'end',\n toolName,\n success: false,\n toolResultData: JSON.stringify({\n success: false,\n error,\n errorCode: UNKNOWN_TOOL_ERROR_CODE,\n requestedTool: getString(metadata?.requestedTool) ?? toolName,\n availableTools: getStringArray(metadata?.availableTools),\n }),\n });\n}\n\nfunction toToolArgs(value: unknown): TToolArgs | undefined {\n const record = getRecord(value);\n if (!record) return undefined;\n\n const args: TToolArgs = {};\n for (const [key, item] of Object.entries(record)) {\n if (\n typeof item === 'string' ||\n typeof item === 'number' ||\n typeof item === 'boolean' ||\n (typeof item === 'object' && item !== null)\n ) {\n args[key] = item;\n }\n }\n return args;\n}\n\nfunction getString(value: unknown): string | undefined {\n return typeof value === 'string' && value.length > 0 ? value : undefined;\n}\n\nfunction getRecord(value: unknown): Record<string, unknown> | undefined {\n return typeof value === 'object' && value !== null && !Array.isArray(value)\n ? (value as Record<string, unknown>)\n : undefined;\n}\n\nfunction getStringArray(value: unknown): string[] {\n if (!Array.isArray(value)) return [];\n return value.filter((item): item is string => typeof item === 'string');\n}\n","/**\n * Session run — core execution logic for a single agent turn.\n *\n * Extracted from Session to keep session.ts under the 300-line limit.\n * Stateless: all mutable state is passed in via IRunContext.\n */\n\nimport { createUserMessage, getProviderCapabilities, runHooks } from '@robota-sdk/agent-core';\nimport type {\n IAIProvider,\n IContextWindowState,\n THooksConfig,\n IHookTypeExecutor,\n TTextDeltaCallback,\n} from '@robota-sdk/agent-core';\nimport type { Robota } from '@robota-sdk/agent-core';\nimport type { ContextWindowTracker } from './context-window-tracker.js';\nimport type { TSessionLogData } from './session-logger.js';\nimport type { ISessionOptions } from './session-types.js';\nimport {\n createToolExecutionBridge,\n forwardToolExecutionEvent,\n} from './session-tool-execution-bridge.js';\n\n/** Dependencies injected by Session.run() */\nexport interface IRunContext {\n sessionId: string;\n cwd: string;\n model: string;\n /** Current permission mode — passed to all hook inputs as permission_mode */\n permissionMode?: string;\n /** Absolute path to session transcript file — passed to all hook inputs as transcript_path */\n transcriptPath?: string;\n robota: Robota;\n aiProvider: IAIProvider;\n contextTracker: ContextWindowTracker;\n hooks: Record<string, unknown> | undefined;\n hookTypeExecutors: IHookTypeExecutor[] | undefined;\n sessionStartStdout: string;\n log: (event: string, data: TSessionLogData) => void;\n compact: () => Promise<void>;\n persistSession: () => void;\n getSessionStore: () => boolean;\n clearSessionStartStdout: () => void;\n maxTurns?: number;\n onTextDelta?: TTextDeltaCallback;\n onContextUpdate?: (state: IContextWindowState) => void;\n onToolExecution?: ISessionOptions['onToolExecution'];\n knownToolNames?: readonly string[];\n}\n\n/**\n * Execute a single agent turn: run hooks, send message to AI, log results.\n *\n * @param message - The processed message to send to the AI\n * @param rawInput - Optional raw user input (used for hook prompt field)\n * @param ctx - Session state and callbacks\n * @param abortSignal - AbortSignal from the session's AbortController\n */\nexport async function executeRun(\n message: string,\n rawInput: string | undefined,\n ctx: IRunContext,\n abortSignal: AbortSignal,\n): Promise<string> {\n // Auto-compact BEFORE processing the new message (not after).\n // This prevents compaction from interfering with the current response stream.\n ctx.contextTracker.updateFromHistory(ctx.robota.getHistory());\n if (ctx.contextTracker.shouldAutoCompact()) {\n // Providers store onTextDelta as an instance property for their own internal streaming.\n // Compaction calls provider.chat() without passing onTextDelta in options, so the\n // provider falls back to this.onTextDelta. Temporarily clearing it prevents compaction\n // summary text from streaming to the UI. This workaround stays until provider packages\n // remove the instance-level onTextDelta property.\n const provider = ctx.aiProvider as { onTextDelta?: unknown };\n const savedDelta = provider.onTextDelta;\n provider.onTextDelta = undefined;\n try {\n await ctx.compact();\n } finally {\n provider.onTextDelta = savedDelta;\n }\n }\n\n ctx.log('user', { content: message });\n\n // Fire UserPromptSubmit hook before AI processes input\n const hookResult = await runHooks(\n ctx.hooks as THooksConfig | undefined,\n 'UserPromptSubmit',\n {\n session_id: ctx.sessionId,\n cwd: ctx.cwd,\n hook_event_name: 'UserPromptSubmit',\n user_message: rawInput ?? message,\n prompt: rawInput ?? message,\n ...(ctx.permissionMode !== undefined && { permission_mode: ctx.permissionMode }),\n ...(ctx.transcriptPath !== undefined && { transcript_path: ctx.transcriptPath }),\n env: {\n CLAUDE_PROJECT_DIR: ctx.cwd,\n CLAUDE_SESSION_ID: ctx.sessionId,\n },\n },\n ctx.hookTypeExecutors,\n );\n\n // Inject hook stdout into user message (e.g., plugin path info)\n const hookStdout = [ctx.sessionStartStdout, hookResult.stdout].filter(Boolean).join('\\n');\n const enrichedMessage = hookStdout\n ? `<system-reminder>\\n${hookStdout}\\n</system-reminder>\\n${message}`\n : message;\n // Clear sessionStart stdout after first injection\n ctx.clearSessionStartStdout();\n\n const history = ctx.robota.getHistory();\n const historyJson = JSON.stringify(history);\n const providerCapabilities = getProviderCapabilities(ctx.aiProvider);\n ctx.log('pre_run', {\n historyLength: history.length,\n historyChars: historyJson.length,\n historyEstTokens: Math.ceil(historyJson.length / 4),\n input: enrichedMessage,\n history,\n model: ctx.model,\n provider: ctx.aiProvider.name,\n maxTokens: ctx.contextTracker.getContextState().maxTokens,\n nativeWebSearchSupported: providerCapabilities.nativeWebTools.webSearch.supported,\n nativeWebSearchEnabled: providerCapabilities.nativeWebTools.webSearch.enabled,\n nativeWebFetchSupported: providerCapabilities.nativeWebTools.webFetch.supported,\n nativeWebFetchEnabled: providerCapabilities.nativeWebTools.webFetch.enabled,\n });\n ctx.contextTracker.updateFromHistory([...history, createUserMessage(enrichedMessage)]);\n ctx.onContextUpdate?.(ctx.contextTracker.getContextState());\n\n let response: string;\n try {\n const toolExecutionBridge = createToolExecutionBridge({\n knownToolNames: ctx.knownToolNames ?? [],\n ...(ctx.onToolExecution && { onToolExecution: ctx.onToolExecution }),\n });\n const onTextDelta = ctx.onTextDelta\n ? (delta: string): void => {\n ctx.log('text_delta', { delta });\n ctx.onTextDelta?.(delta);\n }\n : undefined;\n\n response = await ctx.robota.run(enrichedMessage, {\n signal: abortSignal,\n maxExecutionRounds: ctx.maxTurns ?? 0,\n onExecutionEvent: (event, data) => {\n ctx.log(event, data as TSessionLogData);\n forwardToolExecutionEvent(toolExecutionBridge, event, data);\n },\n ...(onTextDelta && { onTextDelta }),\n });\n\n // If execution was interrupted (abort fired during execution),\n // throw AbortError so the caller (useSubmitHandler) shows \"Cancelled.\"\n if (abortSignal.aborted) {\n throw new DOMException('Aborted', 'AbortError');\n }\n } catch (error) {\n ctx.log('error', {\n message: error instanceof Error ? error.message : String(error),\n stack: error instanceof Error ? (error.stack ?? '') : '',\n historyLength: ctx.robota.getHistory().length,\n });\n runHooks(\n ctx.hooks as THooksConfig | undefined,\n 'StopFailure',\n {\n session_id: ctx.sessionId,\n cwd: ctx.cwd,\n hook_event_name: 'StopFailure',\n reason: error instanceof Error ? error.message : String(error),\n stop_hook_active: false,\n ...(ctx.permissionMode !== undefined && { permission_mode: ctx.permissionMode }),\n ...(ctx.transcriptPath !== undefined && { transcript_path: ctx.transcriptPath }),\n env: {\n CLAUDE_PROJECT_DIR: ctx.cwd,\n CLAUDE_SESSION_ID: ctx.sessionId,\n },\n },\n ctx.hookTypeExecutors,\n ).catch(() => {});\n throw error;\n }\n\n // Log the response and full history structure\n const postHistory = ctx.robota.getHistory();\n const historyStructure = postHistory.map((msg) => {\n const hasToolCalls =\n 'toolCalls' in msg && Array.isArray(msg.toolCalls) && msg.toolCalls.length > 0;\n const toolCallNames = hasToolCalls\n ? (msg.toolCalls as Array<{ function: { name: string } }>).map((tc) => tc.function.name)\n : [];\n return {\n role: msg.role,\n contentLength: typeof msg.content === 'string' ? msg.content.length : 0,\n hasToolCalls,\n toolCallNames,\n ...(msg.metadata ? { metadata: msg.metadata } : {}),\n };\n });\n ctx.log('assistant', {\n content: response,\n historyLength: postHistory.length,\n estimatedChars: JSON.stringify(postHistory).length,\n history: postHistory,\n historyStructure,\n });\n\n // Update token usage from the latest assistant message metadata\n ctx.contextTracker.updateFromHistory(postHistory);\n\n const ctxState = ctx.contextTracker.getContextState();\n ctx.onContextUpdate?.(ctxState);\n ctx.log('context', {\n maxTokens: ctxState.maxTokens,\n usedTokens: ctxState.usedTokens,\n usedPercentage: ctxState.usedPercentage,\n remainingPercentage: ctxState.remainingPercentage,\n });\n\n // Fire Stop hook after AI response is complete (informational, fire and forget)\n runHooks(\n ctx.hooks as THooksConfig | undefined,\n 'Stop',\n {\n session_id: ctx.sessionId,\n cwd: ctx.cwd,\n hook_event_name: 'Stop',\n response: response.substring(0, 500),\n last_assistant_message: response,\n stop_hook_active: false,\n ...(ctx.permissionMode !== undefined && { permission_mode: ctx.permissionMode }),\n ...(ctx.transcriptPath !== undefined && { transcript_path: ctx.transcriptPath }),\n env: {\n CLAUDE_PROJECT_DIR: ctx.cwd,\n CLAUDE_SESSION_ID: ctx.sessionId,\n },\n },\n ctx.hookTypeExecutors,\n ).catch(() => {});\n\n if (ctx.getSessionStore()) {\n ctx.persistSession();\n }\n\n return response;\n}\n","/**\n * Session history operations — compaction and persistence helpers.\n *\n * Extracted from Session to keep session.ts under the 300-line limit.\n * Each function receives its dependencies explicitly.\n */\n\nimport { runHooks } from '@robota-sdk/agent-core';\nimport type {\n IAIProvider,\n THooksConfig,\n IHookInput,\n IHookTypeExecutor,\n} from '@robota-sdk/agent-core';\nimport type { Robota } from '@robota-sdk/agent-core';\nimport type { ISessionRecord, ISessionStore } from './session-store.js';\nimport type { CompactionOrchestrator } from './compaction-orchestrator.js';\nimport type { ContextWindowTracker } from './context-window-tracker.js';\nimport type { TSessionLogData } from './session-logger.js';\nimport type { IToolSchema } from '@robota-sdk/agent-core';\nimport type { ICompactEvent, TCompactTrigger } from './session-types.js';\n\n/** Dependencies for compact() */\nexport interface ICompactContext {\n sessionId: string;\n cwd: string;\n systemMessage: string;\n robota: Robota;\n aiProvider: IAIProvider;\n compactionOrchestrator: CompactionOrchestrator;\n contextTracker: ContextWindowTracker;\n hooks: Record<string, unknown> | undefined;\n hookTypeExecutors: IHookTypeExecutor[] | undefined;\n onCompactCallback: ((summary: string) => void) | undefined;\n onCompactEventCallback: ((event: ICompactEvent) => void) | undefined;\n trigger: TCompactTrigger;\n log: (event: string, data: TSessionLogData) => void;\n}\n\n/**\n * Summarize the conversation to free context space.\n *\n * @param instructions - Optional focus instructions for the summary\n * @param ctx - Session state and callbacks\n */\nexport async function compact(\n instructions: string | undefined,\n ctx: ICompactContext,\n): Promise<void> {\n const history = ctx.robota.getHistory();\n if (history.length === 0) return;\n\n ctx.contextTracker.updateFromHistory(history);\n const before = ctx.contextTracker.getContextState();\n\n // Exclude system messages from compaction — they are preserved and re-injected after\n const nonSystemHistory = history.filter((msg) => msg.role !== 'system');\n const summary = await ctx.compactionOrchestrator.compact(\n ctx.aiProvider,\n nonSystemHistory,\n instructions,\n );\n\n // Clear history, re-inject system message, then inject summary.\n // System message must persist across compactions — it contains project context\n // (cwd, AGENTS.md, CLAUDE.md) that the AI needs for every response.\n ctx.robota.clearHistory();\n ctx.robota.injectMessage('system', ctx.systemMessage);\n ctx.robota.injectMessage('assistant', `[Context Summary]\\n${summary}`);\n\n // Reset token tracking based on the new shorter history\n ctx.contextTracker.updateFromHistory(ctx.robota.getHistory());\n\n // Fire PostCompact hook after history replacement is complete\n const postHookInput: IHookInput = {\n session_id: ctx.sessionId,\n cwd: ctx.cwd,\n hook_event_name: 'PostCompact',\n trigger: ctx.trigger,\n compact_summary: summary,\n };\n runHooks(\n ctx.hooks as THooksConfig | undefined,\n 'PostCompact',\n postHookInput,\n ctx.hookTypeExecutors,\n ).catch(() => {});\n\n // Notify via callback after compaction is fully complete\n const after = ctx.contextTracker.getContextState();\n ctx.log('context_compact', {\n trigger: ctx.trigger,\n before,\n after,\n });\n ctx.onCompactEventCallback?.({ trigger: ctx.trigger, before, after });\n if (ctx.onCompactCallback) {\n ctx.onCompactCallback(summary);\n }\n}\n\n/** Dependencies for persistSession() */\nexport interface IPersistContext {\n sessionId: string;\n cwd: string;\n systemPrompt: string;\n toolSchemas: IToolSchema[];\n sessionStore: ISessionStore;\n robota: Robota;\n getFullHistory: () => Array<{\n id: string;\n timestamp: Date;\n category: string;\n type: string;\n data?: unknown;\n }>;\n}\n\n/** Persist the current session to the store */\nexport function persistSession(ctx: IPersistContext): void {\n const history = ctx.robota.getHistory();\n const now = new Date().toISOString();\n\n const existing = ctx.sessionStore.load(ctx.sessionId);\n\n const record: ISessionRecord = {\n id: ctx.sessionId,\n name: existing?.name,\n cwd: ctx.cwd,\n createdAt: existing?.createdAt ?? now,\n updatedAt: now,\n messages: history,\n history: ctx.getFullHistory(),\n systemPrompt: ctx.systemPrompt,\n toolSchemas: ctx.toolSchemas,\n };\n\n ctx.sessionStore.save(record);\n}\n","/**\n * Session lifecycle helpers — provider configuration and session start hooks.\n *\n * Extracted from Session to keep session.ts under the 300-line limit.\n * All functions receive their dependencies explicitly.\n */\n\nimport { runHooks } from '@robota-sdk/agent-core';\nimport type {\n IAIProvider,\n TSessionEndReason,\n THooksConfig,\n IHookInput,\n IHookTypeExecutor,\n} from '@robota-sdk/agent-core';\nimport type { ISessionOptions } from './session-types.js';\nimport type { TSessionLogData } from './session-logger.js';\n\n/**\n * Configure provider-specific features: streaming, web tools, server tool logging.\n * Mutates the provider object in-place.\n */\nexport function configureProvider(\n provider: IAIProvider,\n _options: ISessionOptions,\n log: (event: string, data: TSessionLogData) => void,\n): void {\n provider.configureNativeWebTools?.({ webSearch: true });\n\n // Wire server tool logging\n if ('onServerToolUse' in provider) {\n (\n provider as { onServerToolUse?: (name: string, input: Record<string, string>) => void }\n ).onServerToolUse = (name: string, input: Record<string, string>) => {\n log('server_tool', { tool: name, ...input });\n };\n }\n}\n\n/**\n * Fire SessionStart hook asynchronously.\n * Calls onStdout when the hook produces stdout (used to seed the first run()).\n */\nexport function fireSessionStartHook(\n sessionId: string,\n cwd: string,\n hooks: Record<string, unknown> | undefined,\n hookTypeExecutors: IHookTypeExecutor[] | undefined,\n onStdout: (stdout: string) => void,\n permissionMode?: string,\n transcriptPath?: string,\n): void {\n const hookInput: IHookInput = {\n session_id: sessionId,\n cwd,\n hook_event_name: 'SessionStart',\n ...(permissionMode !== undefined && { permission_mode: permissionMode }),\n ...(transcriptPath !== undefined && { transcript_path: transcriptPath }),\n env: {\n CLAUDE_PROJECT_DIR: cwd,\n CLAUDE_SESSION_ID: sessionId,\n },\n };\n runHooks(hooks as THooksConfig | undefined, 'SessionStart', hookInput, hookTypeExecutors)\n .then((result) => {\n if (result.stdout) {\n onStdout(result.stdout);\n }\n })\n .catch(() => {});\n}\n\n/** Fire SessionEnd hook and wait for hook completion before process exit. */\nexport async function fireSessionEndHook(\n sessionId: string,\n cwd: string,\n reason: TSessionEndReason,\n hooks: Record<string, unknown> | undefined,\n hookTypeExecutors: IHookTypeExecutor[] | undefined,\n permissionMode?: string,\n transcriptPath?: string,\n): Promise<void> {\n const hookInput: IHookInput = {\n session_id: sessionId,\n cwd,\n hook_event_name: 'SessionEnd',\n reason,\n ...(permissionMode !== undefined && { permission_mode: permissionMode }),\n ...(transcriptPath !== undefined && { transcript_path: transcriptPath }),\n env: {\n CLAUDE_PROJECT_DIR: cwd,\n CLAUDE_SESSION_ID: sessionId,\n },\n };\n await runHooks(hooks as THooksConfig | undefined, 'SessionEnd', hookInput, hookTypeExecutors);\n}\n","import type {\n Robota,\n IAIProvider,\n IToolSchema,\n TPermissionMode,\n IHistoryEntry,\n} from '@robota-sdk/agent-core';\nimport type { PermissionEnforcer } from './permission-enforcer.js';\nimport type { ContextWindowTracker } from './context-window-tracker.js';\n\nexport abstract class SessionBase {\n protected abstract readonly robota: Robota;\n protected abstract readonly permissionEnforcer: PermissionEnforcer;\n protected abstract readonly contextTracker: ContextWindowTracker;\n protected abstract permissionMode: TPermissionMode;\n protected abstract readonly sessionId: string;\n protected abstract readonly aiProvider: IAIProvider;\n protected abstract readonly toolSchemas: IToolSchema[];\n protected abstract readonly model: string;\n protected abstract systemMessage: string;\n protected abstract messageCount: number;\n protected abstract abortController: AbortController | null;\n\n getPermissionMode(): TPermissionMode {\n return this.permissionMode;\n }\n\n /** Change the active permission mode — future tool calls will use the new mode. */\n setPermissionMode(mode: TPermissionMode): void {\n this.permissionMode = mode;\n }\n\n getSessionId(): string {\n return this.sessionId;\n }\n\n getSystemMessage(): string {\n return this.systemMessage;\n }\n\n /** Replace the active system message and propagate to the agent (used by staleness detection). */\n updateSystemMessage(newMessage: string): void {\n this.systemMessage = newMessage;\n this.robota.setModel({\n provider: this.aiProvider.name,\n model: this.model,\n systemMessage: newMessage,\n });\n }\n\n getToolSchemas(): IToolSchema[] {\n return this.toolSchemas;\n }\n\n getMessageCount(): number {\n return this.messageCount;\n }\n\n /** Get tools that have been session-approved (via \"Allow always\" choice). */\n getSessionAllowedTools(): string[] {\n return this.permissionEnforcer.getSessionAllowedTools();\n }\n\n clearSessionAllowedTools(): void {\n this.permissionEnforcer.clearSessionAllowedTools();\n }\n\n /** Abort the currently running execution. No-op if nothing is running. */\n abort(): void {\n if (this.abortController) {\n this.abortController.abort();\n this.abortController = null;\n }\n }\n\n isRunning(): boolean {\n return this.abortController !== null;\n }\n\n getContextState() {\n return this.contextTracker.getContextState();\n }\n\n getAutoCompactThreshold() {\n return this.contextTracker.getAutoCompactThreshold();\n }\n\n setAutoCompactThreshold(threshold: number | false): void {\n this.contextTracker.setAutoCompactThreshold(threshold);\n }\n\n getHistory() {\n return this.robota.getHistory();\n }\n\n getFullHistory(): IHistoryEntry[] {\n return this.robota.getFullHistory();\n }\n\n /** Add an event entry to history (not a chat message) */\n addHistoryEntry(entry: IHistoryEntry): void {\n this.robota.addHistoryEntry(entry);\n }\n\n /** Inject a message into conversation history without execution (used for session restore). */\n injectMessage(\n role: 'user' | 'assistant' | 'system' | 'tool',\n content: string,\n options?: { toolCallId?: string; name?: string },\n ): void {\n this.robota.injectMessage(role, content, options);\n }\n\n clearHistory(): void {\n this.robota.clearHistory();\n this.contextTracker.reset();\n }\n}\n","/**\n * Permission types — interfaces and type aliases for permission enforcement.\n */\n\nimport type { IToolWithEventService, TPermissionMode, TToolArgs } from '@robota-sdk/agent-core';\nimport type { IHookTypeExecutor, ISpinner, ITerminalOutput } from '@robota-sdk/agent-core';\nimport type { ISessionLogger } from './session-logger.js';\n\nexport type { ISpinner, ITerminalOutput };\n\n/**\n * Permission handler result:\n * - true: allow this invocation\n * - false: deny this invocation\n * - 'allow-session': allow this invocation and auto-approve this tool for the rest of the session\n */\nexport type TPermissionResult = boolean | 'allow-session';\n\n/**\n * Custom permission handler — called when a tool needs user approval.\n * Returns true to allow, false to deny, or 'allow-session' to remember for the session.\n */\nexport type TPermissionHandler = (\n toolName: string,\n toolArgs: TToolArgs,\n) => Promise<TPermissionResult>;\n\nexport interface IPermissionEnforcerOptions {\n sessionId: string;\n cwd: string;\n getPermissionMode: () => TPermissionMode;\n config: {\n permissions: { allow: string[]; deny: string[] };\n hooks?: Record<string, unknown>;\n };\n terminal: ITerminalOutput;\n permissionHandler?: TPermissionHandler;\n promptForApprovalFn?: (\n terminal: ITerminalOutput,\n toolName: string,\n toolArgs: TToolArgs,\n ) => Promise<boolean>;\n sessionLogger?: ISessionLogger;\n onToolExecution?: (event: {\n type: 'start' | 'end';\n toolName: string;\n toolArgs?: TToolArgs;\n success?: boolean;\n denied?: boolean;\n toolResultData?: string;\n }) => void;\n /** Additional hook type executors (e.g. prompt, agent) beyond the core defaults. */\n hookTypeExecutors?: IHookTypeExecutor[];\n /** Absolute path to session transcript file — passed to PreToolUse hook inputs as transcript_path */\n transcriptPath?: string;\n}\n\n/** Returned when the user denies a permission prompt. success:true prevents ToolExecutionError. */\nexport const PERMISSION_DENIED_RESULT = {\n success: true,\n data: JSON.stringify({\n success: false,\n output: '',\n error: 'Permission denied. The user did not approve this action.',\n }),\n metadata: {},\n} as const;\n\n/** Maximum chars for any single tool output. Matches Claude Code's 30K limit. */\nexport const MAX_TOOL_OUTPUT_CHARS = 30_000;\n","/**\n * Tool hook helpers — stateless utility functions for tool hook execution\n * and output truncation used by PermissionEnforcer.\n */\n\nimport { runHooks } from '@robota-sdk/agent-core';\nimport type {\n IToolResult,\n TToolParameters,\n THooksConfig,\n IHookInput,\n IHookTypeExecutor,\n} from '@robota-sdk/agent-core';\nimport { MAX_TOOL_OUTPUT_CHARS } from './permission-types.js';\n\n/**\n * Truncate tool result data if it exceeds MAX_TOOL_OUTPUT_CHARS.\n * Uses middle-truncation: keeps first and last portions, removes middle.\n */\nexport function truncateToolResult(result: IToolResult): IToolResult {\n if (typeof result.data !== 'string') return result;\n if (result.data.length <= MAX_TOOL_OUTPUT_CHARS) return result;\n\n const halfLimit = Math.floor(MAX_TOOL_OUTPUT_CHARS / 2);\n const head = result.data.substring(0, halfLimit);\n const tail = result.data.substring(result.data.length - halfLimit);\n const originalSize = result.data.length;\n const truncatedData = `${head}\\n\\n[... output truncated: ${originalSize.toLocaleString()} chars total, showing first and last ${halfLimit.toLocaleString()} chars ...]\\n\\n${tail}`;\n\n return { ...result, data: truncatedData };\n}\n\n/** Build a hook input object for tool execution hooks */\nexport function buildHookInput(\n sessionId: string,\n cwd: string,\n toolName: string,\n parameters: TToolParameters,\n permissionMode?: string,\n transcriptPath?: string,\n): IHookInput {\n return {\n session_id: sessionId,\n cwd,\n hook_event_name: 'PreToolUse',\n tool_name: toolName,\n tool_input: parameters as Record<string, string | number | boolean | object>,\n ...(permissionMode !== undefined && { permission_mode: permissionMode }),\n ...(transcriptPath !== undefined && { transcript_path: transcriptPath }),\n };\n}\n\n/** Run PreToolUse hooks; returns a denial IToolResult if blocked, or null to proceed */\nexport async function runPreToolHook(\n hooks: Record<string, unknown> | undefined,\n hookInput: IHookInput,\n hookTypeExecutors: IHookTypeExecutor[] | undefined,\n): Promise<IToolResult | null> {\n const hookResult = await runHooks(\n hooks as THooksConfig | undefined,\n 'PreToolUse',\n hookInput,\n hookTypeExecutors,\n );\n if (hookResult.blocked) {\n return {\n success: true,\n data: JSON.stringify({\n blocked: true,\n reason: hookResult.reason ?? 'Blocked by hook',\n }),\n metadata: {},\n };\n }\n return null;\n}\n\n/** Fire PostToolUse hooks (fire and forget) */\nexport function firePostToolHook(\n hooks: Record<string, unknown> | undefined,\n hookInput: IHookInput,\n result: IToolResult,\n hookTypeExecutors: IHookTypeExecutor[] | undefined,\n): void {\n const postHookInput: IHookInput = {\n ...hookInput,\n hook_event_name: 'PostToolUse',\n tool_output: typeof result.data === 'string' ? result.data : JSON.stringify(result.data),\n };\n runHooks(\n hooks as THooksConfig | undefined,\n 'PostToolUse',\n postHookInput,\n hookTypeExecutors,\n ).catch(() => {});\n}\n","/**\n * PermissionEnforcer — handles tool permission checking, hook execution,\n * and tool output truncation.\n *\n * Extracted from Session to separate permission/hook concerns from\n * conversation management.\n */\n\nimport { evaluatePermission } from '@robota-sdk/agent-core';\nimport type {\n IToolWithEventService,\n IToolResult,\n TToolParameters,\n IToolExecutionContext,\n TToolArgs,\n} from '@robota-sdk/agent-core';\nimport type { ISessionLogger, TSessionLogData } from './session-logger.js';\nimport type {\n IPermissionEnforcerOptions,\n TPermissionHandler,\n TPermissionResult,\n ITerminalOutput,\n ISpinner,\n} from './permission-types.js';\nimport { PERMISSION_DENIED_RESULT } from './permission-types.js';\nimport {\n truncateToolResult,\n buildHookInput,\n runPreToolHook,\n firePostToolHook,\n} from './tool-hook-helpers.js';\n\nexport type { TPermissionHandler, TPermissionResult, ITerminalOutput, ISpinner };\nexport type { IPermissionEnforcerOptions };\n\nexport class PermissionEnforcer {\n private readonly sessionId: string;\n private readonly cwd: string;\n private readonly getPermissionMode: IPermissionEnforcerOptions['getPermissionMode'];\n private readonly config: IPermissionEnforcerOptions['config'];\n private readonly terminal: ITerminalOutput;\n private readonly permissionHandler?: TPermissionHandler;\n private readonly promptForApprovalFn?: IPermissionEnforcerOptions['promptForApprovalFn'];\n private readonly sessionLogger?: ISessionLogger;\n private readonly onToolExecution?: IPermissionEnforcerOptions['onToolExecution'];\n private readonly hookTypeExecutors?: IPermissionEnforcerOptions['hookTypeExecutors'];\n private readonly transcriptPath?: string;\n private readonly sessionAllowedTools = new Set<string>();\n\n constructor(options: IPermissionEnforcerOptions) {\n this.sessionId = options.sessionId;\n this.cwd = options.cwd;\n this.getPermissionMode = options.getPermissionMode;\n this.config = options.config;\n this.terminal = options.terminal;\n this.permissionHandler = options.permissionHandler;\n this.promptForApprovalFn = options.promptForApprovalFn;\n this.sessionLogger = options.sessionLogger;\n this.onToolExecution = options.onToolExecution;\n this.hookTypeExecutors = options.hookTypeExecutors;\n this.transcriptPath = options.transcriptPath;\n }\n\n /** Wrap all tools with permission checking */\n wrapTools(tools: IToolWithEventService[]): IToolWithEventService[] {\n return tools.map((tool) => this.wrapToolWithPermission(tool));\n }\n\n /** Get tools that have been session-approved (via \"Allow always\" choice). */\n getSessionAllowedTools(): string[] {\n return [...this.sessionAllowedTools];\n }\n\n /** Clear all session-scoped allow rules. */\n clearSessionAllowedTools(): void {\n this.sessionAllowedTools.clear();\n }\n\n /**\n * Wrap a tool with permission checking.\n * The wrapper intercepts execute() and runs permission evaluation before delegating.\n * If denied, returns a tool result indicating the action was blocked.\n */\n private wrapToolWithPermission(tool: IToolWithEventService): IToolWithEventService {\n const enforcer = this;\n const originalExecute = tool.execute.bind(tool);\n\n const wrappedTool = Object.create(tool) as IToolWithEventService;\n wrappedTool.execute = async (\n parameters: TToolParameters,\n context?: IToolExecutionContext,\n ): Promise<IToolResult> => {\n // Must NEVER throw — if this throws, the execution round records the\n // assistant tool_use in history but never adds a tool_result, which\n // corrupts the conversation and causes a 400 error on the next API call.\n try {\n const toolName = tool.getName();\n enforcer.log('tool_call', {\n tool: toolName,\n args: parameters as Record<string, string | number | boolean | object>,\n });\n\n const hookInput = buildHookInput(\n enforcer.sessionId,\n enforcer.cwd,\n toolName,\n parameters,\n enforcer.getPermissionMode(),\n enforcer.transcriptPath,\n );\n\n const preResult = await runPreToolHook(\n enforcer.config.hooks,\n hookInput,\n enforcer.hookTypeExecutors,\n );\n if (preResult) {\n enforcer.log('tool_blocked', { tool: toolName, reason: 'hook' });\n return preResult;\n }\n\n const allowed = await enforcer.checkPermission(toolName, parameters as TToolArgs);\n if (!allowed) {\n enforcer.log('tool_denied', { tool: toolName, reason: 'permission' });\n enforcer.onToolExecution?.({\n type: 'end',\n toolName,\n toolArgs: parameters as TToolArgs,\n success: false,\n denied: true,\n });\n return PERMISSION_DENIED_RESULT;\n }\n\n enforcer.onToolExecution?.({ type: 'start', toolName, toolArgs: parameters as TToolArgs });\n\n const result = await originalExecute(parameters, context as IToolExecutionContext);\n\n // Truncate oversized tool output (Claude Code uses 30K char limit)\n const truncatedResult = truncateToolResult(result);\n\n enforcer.onToolExecution?.({\n type: 'end',\n toolName,\n toolArgs: parameters as TToolArgs,\n success: truncatedResult.success,\n toolResultData:\n typeof truncatedResult.data === 'string'\n ? truncatedResult.data\n : JSON.stringify(truncatedResult.data),\n });\n\n const dataSize =\n typeof truncatedResult.data === 'string'\n ? truncatedResult.data.length\n : JSON.stringify(truncatedResult.data).length;\n enforcer.log('tool_result', {\n tool: toolName,\n success: truncatedResult.success,\n dataChars: dataSize,\n truncated: truncatedResult !== result,\n });\n firePostToolHook(\n enforcer.config.hooks,\n hookInput,\n truncatedResult,\n enforcer.hookTypeExecutors,\n );\n return truncatedResult;\n } catch (err) {\n const message = err instanceof Error ? err.message : String(err);\n return {\n success: true,\n data: JSON.stringify({ success: false, output: '', error: message }),\n metadata: {},\n };\n }\n };\n\n return wrappedTool;\n }\n\n /** Evaluate permission for a tool call using the current mode and config */\n async checkPermission(toolName: string, toolArgs: TToolArgs): Promise<boolean> {\n const decision = evaluatePermission(toolName, toolArgs, this.getPermissionMode(), {\n allow: this.config.permissions.allow,\n deny: this.config.permissions.deny,\n });\n\n if (decision === 'auto') return true;\n if (decision === 'deny') return false;\n\n // Check session-scoped allow list before prompting\n if (this.sessionAllowedTools.has(toolName)) return true;\n\n // 'approve' — prompt the user via custom handler, injected approval fn, or deny\n if (this.permissionHandler) {\n const result = await this.permissionHandler(toolName, toolArgs);\n if (result === 'allow-session') {\n this.sessionAllowedTools.add(toolName);\n return true;\n }\n return result;\n }\n if (this.promptForApprovalFn) {\n return this.promptForApprovalFn(this.terminal, toolName, toolArgs);\n }\n // No approval mechanism available — deny by default\n return false;\n }\n\n /** Delegate session event to the injected logger. */\n private log(event: string, data: TSessionLogData): void {\n this.sessionLogger?.log(this.sessionId, event, data);\n }\n}\n","/**\n * ContextWindowTracker — tracks token usage and context window state.\n *\n * Extracted from Session to separate context monitoring from conversation management.\n */\n\nimport type { IContextWindowState, TUniversalMessage } from '@robota-sdk/agent-core';\nimport { estimateContextTokensFromMessages, getModelContextWindow } from '@robota-sdk/agent-core';\n\n/** Percentage conversion factor */\nconst PERCENT = 100;\n\n/** Auto-compact when context usage reaches this fraction */\nexport const AUTO_COMPACT_THRESHOLD = 0.835;\n\nexport type TAutoCompactThreshold = number | false;\n\nexport class ContextWindowTracker {\n private contextUsedTokens = 0;\n private readonly contextMaxTokens: number;\n private autoCompactThreshold: TAutoCompactThreshold;\n\n constructor(\n model: string,\n contextMaxTokens?: number,\n autoCompactThreshold?: TAutoCompactThreshold,\n ) {\n this.contextMaxTokens = contextMaxTokens ?? getModelContextWindow(model);\n this.autoCompactThreshold = normalizeAutoCompactThreshold(autoCompactThreshold);\n }\n\n /** Get current context window state */\n getContextState(): IContextWindowState {\n const usedPercentage = Math.min(\n PERCENT,\n (this.contextUsedTokens / this.contextMaxTokens) * PERCENT,\n );\n return {\n maxTokens: this.contextMaxTokens,\n usedTokens: this.contextUsedTokens,\n usedPercentage: Math.round(usedPercentage * PERCENT) / PERCENT,\n remainingPercentage: Math.round((PERCENT - usedPercentage) * PERCENT) / PERCENT,\n };\n }\n\n /** Whether auto-compaction threshold has been exceeded */\n shouldAutoCompact(): boolean {\n if (this.autoCompactThreshold === false) {\n return false;\n }\n return this.getContextState().usedPercentage >= this.autoCompactThreshold * PERCENT;\n }\n\n /** The auto-compaction policy for this tracker. */\n getAutoCompactThreshold(): TAutoCompactThreshold {\n return this.autoCompactThreshold;\n }\n\n /** Update the auto-compaction policy for this tracker. */\n setAutoCompactThreshold(autoCompactThreshold: TAutoCompactThreshold): void {\n this.autoCompactThreshold = normalizeAutoCompactThreshold(autoCompactThreshold);\n }\n\n /**\n * Estimate token usage from conversation history.\n *\n * Uses the shared core estimator so session display, /context, auto-compact, and core\n * execution guards reason about the same effective token state.\n */\n updateFromHistory(history: TUniversalMessage[]): void {\n this.contextUsedTokens = estimateContextTokensFromMessages(history).usedTokens;\n }\n\n /** Reset token tracking */\n reset(): void {\n this.contextUsedTokens = 0;\n }\n}\n\nfunction normalizeAutoCompactThreshold(\n autoCompactThreshold: TAutoCompactThreshold | undefined,\n): TAutoCompactThreshold {\n if (autoCompactThreshold === undefined) {\n return AUTO_COMPACT_THRESHOLD;\n }\n if (autoCompactThreshold === false) {\n return false;\n }\n if (\n !Number.isFinite(autoCompactThreshold) ||\n autoCompactThreshold <= 0 ||\n autoCompactThreshold > 1\n ) {\n throw new RangeError('autoCompactThreshold must be a number greater than 0 and at most 1.');\n }\n return autoCompactThreshold;\n}\n","/**\n * CompactionOrchestrator — handles conversation compaction (summarization)\n * to free context window space.\n *\n * Extracted from Session to separate compaction logic from conversation management.\n */\n\nimport { randomUUID } from 'node:crypto';\nimport { runHooks } from '@robota-sdk/agent-core';\nimport type {\n IAIProvider,\n TUniversalMessage,\n THooksConfig,\n IHookInput,\n IHookTypeExecutor,\n} from '@robota-sdk/agent-core';\n\nexport interface ICompactionOptions {\n sessionId: string;\n cwd: string;\n model: string;\n hooks?: Record<string, unknown>;\n compactInstructions?: string;\n /** Additional hook type executors (e.g. prompt, agent) beyond the core defaults. */\n hookTypeExecutors?: IHookTypeExecutor[];\n}\n\nexport class CompactionOrchestrator {\n private readonly sessionId: string;\n private readonly cwd: string;\n private readonly model: string;\n private readonly hooks?: Record<string, unknown>;\n private readonly compactInstructions?: string;\n private readonly hookTypeExecutors?: IHookTypeExecutor[];\n\n constructor(options: ICompactionOptions) {\n this.sessionId = options.sessionId;\n this.cwd = options.cwd;\n this.model = options.model;\n this.hooks = options.hooks;\n this.compactInstructions = options.compactInstructions;\n this.hookTypeExecutors = options.hookTypeExecutors;\n }\n\n /**\n * Run compaction — summarize the conversation to free context space.\n * @param provider - The AI provider to use for summarization\n * @param history - Current conversation history\n * @param instructions - Optional focus instructions for the summary\n * @returns The generated summary string\n */\n async compact(\n provider: IAIProvider,\n history: TUniversalMessage[],\n instructions?: string,\n ): Promise<string> {\n if (history.length === 0) return '';\n\n const trigger: 'auto' | 'manual' = instructions !== undefined ? 'manual' : 'auto';\n\n // Fire PreCompact hook\n const preHookInput: IHookInput = {\n session_id: this.sessionId,\n cwd: this.cwd,\n hook_event_name: 'PreCompact',\n trigger,\n };\n await runHooks(\n this.hooks as THooksConfig | undefined,\n 'PreCompact',\n preHookInput,\n this.hookTypeExecutors,\n );\n\n // Build compaction prompt\n const compactPrompt = this.buildCompactionPrompt(history, instructions);\n\n // Call provider to generate summary\n const summaryMessage = await provider.chat(\n [\n {\n id: randomUUID(),\n role: 'user',\n content: compactPrompt,\n state: 'complete' as const,\n timestamp: new Date(),\n },\n ],\n { model: this.model },\n );\n const summary =\n typeof summaryMessage.content === 'string' ? summaryMessage.content : '(compaction failed)';\n\n return summary;\n }\n\n /** Build the compaction prompt from conversation history */\n private buildCompactionPrompt(history: TUniversalMessage[], instructions?: string): string {\n const instructionBlock = instructions ?? this.compactInstructions ?? '';\n const instructionSection = instructionBlock ? `\\nAdditional focus:\\n${instructionBlock}\\n` : '';\n\n const formattedHistory = history\n .map((msg) => {\n const content = typeof msg.content === 'string' ? msg.content : JSON.stringify(msg.content);\n return `${msg.role}: ${content}`;\n })\n .join('\\n');\n\n return [\n 'Summarize the following conversation concisely, preserving:',\n \"- User's original requests and goals\",\n '- Key decisions and conclusions',\n '- Important code changes and file paths',\n '- Current task status and next steps',\n instructionSection,\n \"Drop verbose tool outputs, debugging steps, and exploratory work that didn't lead to results.\",\n '',\n 'Conversation:',\n formattedHistory,\n ].join('\\n');\n }\n}\n","import { Robota } from '@robota-sdk/agent-core';\nimport type {\n IAgentConfig,\n IAIProvider,\n IToolWithEventService,\n TPermissionMode,\n} from '@robota-sdk/agent-core';\nimport { PermissionEnforcer } from './permission-enforcer.js';\nimport { ContextWindowTracker } from './context-window-tracker.js';\nimport { CompactionOrchestrator } from './compaction-orchestrator.js';\nimport type { ISessionOptions } from './session-types.js';\n\nexport function buildPermissionEnforcer(\n options: ISessionOptions,\n sessionId: string,\n cwd: string,\n getPermissionMode: () => TPermissionMode,\n transcriptPath: string | undefined,\n): PermissionEnforcer {\n return new PermissionEnforcer({\n sessionId,\n cwd,\n getPermissionMode,\n config: {\n permissions: options.permissions ?? { allow: [], deny: [] },\n hooks: options.hooks,\n },\n terminal: options.terminal,\n permissionHandler: options.permissionHandler,\n promptForApprovalFn: options.promptForApproval,\n sessionLogger: options.sessionLogger,\n onToolExecution: options.onToolExecution,\n hookTypeExecutors: options.hookTypeExecutors,\n transcriptPath,\n });\n}\n\nexport function buildSessionTrackers(\n options: ISessionOptions,\n model: string,\n sessionId: string,\n cwd: string,\n): { contextTracker: ContextWindowTracker; compactionOrchestrator: CompactionOrchestrator } {\n const contextTracker = new ContextWindowTracker(\n model,\n options.contextMaxTokens,\n options.autoCompactThreshold,\n );\n const compactionOrchestrator = new CompactionOrchestrator({\n sessionId,\n cwd,\n model,\n hooks: options.hooks,\n compactInstructions: options.compactInstructions,\n hookTypeExecutors: options.hookTypeExecutors,\n });\n return { contextTracker, compactionOrchestrator };\n}\n\nexport function buildRobota(\n options: ISessionOptions,\n permissionEnforcer: PermissionEnforcer,\n tools: IToolWithEventService[],\n provider: IAIProvider,\n model: string,\n systemMessage: string,\n): Robota {\n const wrappedTools = permissionEnforcer.wrapTools(tools);\n const agentConfig: IAgentConfig = {\n name: options.agentName ?? 'agent',\n aiProviders: [provider],\n defaultModel: {\n provider: provider.name,\n model,\n systemMessage,\n },\n systemMessage,\n tools: wrappedTools,\n logging: { enabled: false },\n ...(options.providerTimeout !== undefined && { timeout: options.providerTimeout }),\n };\n return new Robota(agentConfig);\n}\n","import { TRUST_TO_MODE } from '@robota-sdk/agent-core';\nimport type {\n IAIProvider,\n IContextWindowState,\n IToolSchema,\n TPermissionMode,\n IHookTypeExecutor,\n} from '@robota-sdk/agent-core';\nimport type { ISessionStore } from './session-store.js';\nimport type { ISessionLogger, TSessionLogData } from './session-logger.js';\nimport { PermissionEnforcer } from './permission-enforcer.js';\nimport type {\n TPermissionHandler,\n TPermissionResult,\n ITerminalOutput,\n ISpinner,\n} from './permission-types.js';\nimport { ContextWindowTracker } from './context-window-tracker.js';\nimport { CompactionOrchestrator } from './compaction-orchestrator.js';\nimport type {\n ICompactEvent,\n ISessionOptions,\n ISessionShutdownOptions,\n TCompactTrigger,\n} from './session-types.js';\nimport { executeRun } from './session-run.js';\nimport { compact, persistSession } from './session-history-ops.js';\nimport {\n configureProvider,\n fireSessionEndHook,\n fireSessionStartHook,\n} from './session-lifecycle.js';\nimport { SessionBase } from './session-base.js';\nimport {\n buildPermissionEnforcer,\n buildRobota,\n buildSessionTrackers,\n} from './session-components.js';\nimport type { Robota } from '@robota-sdk/agent-core';\n\nexport type {\n ICompactEvent,\n TPermissionHandler,\n TPermissionResult,\n ITerminalOutput,\n ISpinner,\n ISessionOptions,\n ISessionShutdownOptions,\n TCompactTrigger,\n};\nexport type { TAutoCompactThreshold } from './context-window-tracker.js';\n\nconst ID_RADIX = 36;\nconst ID_RANDOM_LENGTH = 9;\n\n/** Wraps a Robota agent with project context, permission state, and optional persistence. */\nexport class Session extends SessionBase {\n protected readonly robota: Robota;\n protected readonly permissionEnforcer: PermissionEnforcer;\n protected readonly contextTracker: ContextWindowTracker;\n protected permissionMode: TPermissionMode;\n protected readonly sessionId: string;\n protected readonly aiProvider: IAIProvider;\n protected readonly toolSchemas: IToolSchema[];\n protected readonly model: string;\n protected systemMessage: string;\n protected messageCount = 0;\n protected abortController: AbortController | null = null;\n private readonly terminal: ITerminalOutput;\n private readonly sessionStore?: ISessionStore;\n private readonly cwd: string;\n private readonly hooks?: Record<string, unknown>;\n private readonly hookTypeExecutors?: IHookTypeExecutor[];\n private readonly onTextDeltaCallback?: (delta: string) => void;\n private readonly onContextUpdateCallback?: (state: IContextWindowState) => void;\n private readonly onToolExecutionCallback?: ISessionOptions['onToolExecution'];\n private readonly onCompactCallback?: (summary: string) => void;\n private readonly onCompactEventCallback?: ISessionOptions['onCompactEvent'];\n private readonly sessionLogger?: ISessionLogger;\n private readonly maxTurns?: number;\n private readonly compactionOrchestrator: CompactionOrchestrator;\n private shutdownPromise: Promise<void> | null = null;\n /** Stdout collected from SessionStart hooks, injected on first run(). */\n private sessionStartStdout = '';\n /** Absolute path to the session transcript file, if file-backed storage is active. */\n private readonly transcriptPath: string | undefined;\n\n constructor(options: ISessionOptions) {\n super();\n const { tools, provider, systemMessage } = options;\n\n this.terminal = options.terminal;\n this.sessionStore = options.sessionStore;\n this.systemMessage = systemMessage;\n this.toolSchemas = tools.map((tool) => tool.schema);\n this.cwd = process.cwd();\n this.sessionLogger = options.sessionLogger;\n this.hooks = options.hooks;\n this.hookTypeExecutors = options.hookTypeExecutors;\n this.onTextDeltaCallback = options.onTextDelta;\n this.onContextUpdateCallback = options.onContextUpdate;\n this.onToolExecutionCallback = options.onToolExecution;\n this.onCompactCallback = options.onCompact;\n this.onCompactEventCallback = options.onCompactEvent;\n this.maxTurns = options.maxTurns;\n this.model = options.model ?? 'claude-sonnet-4-5';\n this.sessionId =\n options.sessionId ??\n `session_${Date.now()}_${Math.random().toString(ID_RADIX).substr(2, ID_RANDOM_LENGTH)}`;\n this.permissionMode =\n options.permissionMode ??\n (options.defaultTrustLevel ? TRUST_TO_MODE[options.defaultTrustLevel] : undefined) ??\n 'default';\n this.transcriptPath = options.sessionStore?.getFilePath?.(this.sessionId);\n this.log('session_init', {\n cwd: this.cwd,\n systemPromptLength: systemMessage.length,\n systemPrompt: systemMessage,\n toolSchemas: this.toolSchemas,\n model: this.model,\n provider: provider.name,\n });\n this.aiProvider = provider;\n configureProvider(provider, options, (event, data) => this.log(event, data));\n this.permissionEnforcer = buildPermissionEnforcer(\n options,\n this.sessionId,\n this.cwd,\n () => this.permissionMode,\n this.transcriptPath,\n );\n const { contextTracker, compactionOrchestrator } = buildSessionTrackers(\n options,\n this.model,\n this.sessionId,\n this.cwd,\n );\n this.contextTracker = contextTracker;\n this.compactionOrchestrator = compactionOrchestrator;\n this.robota = buildRobota(\n options,\n this.permissionEnforcer,\n tools,\n provider,\n this.model,\n systemMessage,\n );\n fireSessionStartHook(\n this.sessionId,\n this.cwd,\n this.hooks,\n this.hookTypeExecutors,\n (stdout) => void (this.sessionStartStdout = stdout),\n this.permissionMode,\n this.transcriptPath,\n );\n }\n\n async run(message: string, rawInput?: string): Promise<string> {\n this.abortController = new AbortController();\n const { signal } = this.abortController;\n try {\n const response = await executeRun(message, rawInput, this.buildRunContext(), signal);\n this.messageCount += 1;\n return response;\n } finally {\n this.abortController = null;\n }\n }\n\n private log(event: string, data: TSessionLogData): void {\n this.sessionLogger?.log(this.sessionId, event, data);\n }\n\n private persistSessionInternal(): void {\n if (!this.sessionStore) return;\n persistSession({\n sessionId: this.sessionId,\n cwd: this.cwd,\n systemPrompt: this.systemMessage,\n toolSchemas: this.toolSchemas,\n sessionStore: this.sessionStore,\n robota: this.robota,\n getFullHistory: () => this.getFullHistory(),\n });\n }\n\n /** Gracefully end the session and fire SessionEnd hooks once. */\n shutdown(options: ISessionShutdownOptions = {}): Promise<void> {\n if (this.shutdownPromise) return this.shutdownPromise;\n const reason = options.reason ?? 'other';\n this.shutdownPromise = (async () => {\n this.abort();\n this.log('session_shutdown', { reason });\n this.persistSessionInternal();\n await fireSessionEndHook(\n this.sessionId,\n this.cwd,\n reason,\n this.hooks,\n this.hookTypeExecutors,\n this.permissionMode,\n this.transcriptPath,\n );\n })();\n return this.shutdownPromise;\n }\n\n async compact(instructions?: string, trigger: TCompactTrigger = 'manual'): Promise<void> {\n await compact(instructions, {\n sessionId: this.sessionId,\n cwd: this.cwd,\n systemMessage: this.systemMessage,\n robota: this.robota,\n aiProvider: this.aiProvider,\n compactionOrchestrator: this.compactionOrchestrator,\n contextTracker: this.contextTracker,\n hooks: this.hooks,\n hookTypeExecutors: this.hookTypeExecutors,\n onCompactCallback: this.onCompactCallback,\n onCompactEventCallback: this.onCompactEventCallback,\n trigger,\n log: (event, data) => this.log(event, data),\n });\n }\n\n private buildRunContext() {\n return {\n sessionId: this.sessionId,\n cwd: this.cwd,\n model: this.model,\n robota: this.robota,\n aiProvider: this.aiProvider,\n contextTracker: this.contextTracker,\n hooks: this.hooks,\n hookTypeExecutors: this.hookTypeExecutors,\n sessionStartStdout: this.sessionStartStdout,\n log: (event: string, data: TSessionLogData) => this.log(event, data),\n compact: () => this.compact(undefined, 'auto'),\n persistSession: () => this.persistSessionInternal(),\n getSessionStore: () => !!this.sessionStore,\n clearSessionStartStdout: () => void (this.sessionStartStdout = ''),\n permissionMode: this.permissionMode,\n transcriptPath: this.transcriptPath,\n maxTurns: this.maxTurns,\n onTextDelta: this.onTextDeltaCallback,\n onContextUpdate: this.onContextUpdateCallback,\n onToolExecution: this.onToolExecutionCallback,\n knownToolNames: this.toolSchemas.map((tool) => tool.name),\n };\n }\n}\n","/**\n * Session Logger — pluggable logging interface for session events.\n *\n * ISessionLogger defines the contract. FileSessionLogger is the default\n * implementation that writes JSONL to disk. Consumers can implement their\n * own (e.g., remote, database, silent) and inject via Session constructor.\n */\n\nimport { createHash } from 'node:crypto';\nimport { mkdirSync, appendFileSync, existsSync, writeFileSync } from 'node:fs';\nimport { join } from 'node:path';\n\n/** Session log event data — extensible record of event metadata. */\nexport type TSessionLogValue = string | number | boolean | object | null | undefined;\nexport type TSessionLogData = Record<string, TSessionLogValue>;\n\nexport interface IExternalPayloadReference {\n kind: 'external-payload';\n encoding: 'json';\n sha256: string;\n byteLength: number;\n relativePath: string;\n}\n\nexport interface IFileSessionLoggerOptions {\n externalPayloadThresholdBytes?: number;\n redactedValue?: string;\n}\n\nconst BYTES_PER_KIB = 1024;\nconst DEFAULT_EXTERNAL_PAYLOAD_THRESHOLD_KIB = 32;\nconst DEFAULT_EXTERNAL_PAYLOAD_THRESHOLD_BYTES =\n DEFAULT_EXTERNAL_PAYLOAD_THRESHOLD_KIB * BYTES_PER_KIB;\nconst DEFAULT_REDACTED_VALUE = '[REDACTED]';\nconst SENSITIVE_KEY_PATTERN =\n /^(api[-_]?key|authorization|access[-_]?token|refresh[-_]?token|secret|password|x[-_]?api[-_]?key)$/i;\n\n/**\n * Session logger interface — injected into Session for pluggable logging.\n *\n * Implementations decide where and how to persist session events.\n * The Session class calls log() for every significant action.\n */\nexport interface ISessionLogger {\n /** Log a session event with structured data. */\n log(sessionId: string, event: string, data: TSessionLogData): void;\n}\n\n/**\n * File-based session logger — writes JSONL to {logDir}/{sessionId}.jsonl.\n *\n * This is the default implementation used by the CLI.\n * Each line is a self-contained JSON object with timestamp, sessionId, event, and data.\n */\nexport class FileSessionLogger implements ISessionLogger {\n private readonly logDir: string;\n private readonly options: Required<IFileSessionLoggerOptions>;\n\n constructor(logDir: string, options: IFileSessionLoggerOptions = {}) {\n this.logDir = logDir;\n this.options = {\n externalPayloadThresholdBytes:\n options.externalPayloadThresholdBytes ?? DEFAULT_EXTERNAL_PAYLOAD_THRESHOLD_BYTES,\n redactedValue: options.redactedValue ?? DEFAULT_REDACTED_VALUE,\n };\n try {\n mkdirSync(logDir, { recursive: true });\n } catch {\n // Best-effort: logging disabled if directory cannot be created\n }\n }\n\n log(sessionId: string, event: string, data: TSessionLogData): void {\n try {\n const normalizedData = normalizeLogData(sessionId, this.logDir, data, this.options);\n const entry = JSON.stringify({\n timestamp: new Date().toISOString(),\n sessionId,\n event,\n ...normalizedData,\n });\n const logFile = join(this.logDir, `${sessionId}.jsonl`);\n appendFileSync(logFile, entry + '\\n');\n } catch {\n // Logging failure must never break the session\n }\n }\n}\n\nfunction normalizeLogData(\n sessionId: string,\n logDir: string,\n data: TSessionLogData,\n options: Required<IFileSessionLoggerOptions>,\n): TSessionLogData {\n const normalized: TSessionLogData = {};\n for (const [key, value] of Object.entries(data)) {\n normalized[key] = normalizeLogValue(sessionId, logDir, key, value, options);\n }\n return normalized;\n}\n\nfunction normalizeLogValue(\n sessionId: string,\n logDir: string,\n key: string,\n value: TSessionLogValue,\n options: Required<IFileSessionLoggerOptions>,\n): TSessionLogValue {\n if (SENSITIVE_KEY_PATTERN.test(key)) {\n return options.redactedValue;\n }\n if (\n value === null ||\n value === undefined ||\n typeof value === 'string' ||\n typeof value === 'number'\n ) {\n return maybeExternalizePayload(sessionId, logDir, value, options);\n }\n if (typeof value === 'boolean') {\n return value;\n }\n if (value instanceof Date) {\n return value.toISOString();\n }\n if (Array.isArray(value)) {\n const normalizedArray = value.map((item) =>\n normalizeLogValue(sessionId, logDir, key, item as TSessionLogValue, options),\n );\n return maybeExternalizePayload(sessionId, logDir, normalizedArray, options);\n }\n if (typeof value === 'object') {\n const record = value as Record<string, TSessionLogValue>;\n const normalizedRecord: Record<string, TSessionLogValue> = {};\n for (const [childKey, childValue] of Object.entries(record)) {\n normalizedRecord[childKey] = normalizeLogValue(\n sessionId,\n logDir,\n childKey,\n childValue,\n options,\n );\n }\n return maybeExternalizePayload(sessionId, logDir, normalizedRecord, options);\n }\n return String(value);\n}\n\nfunction maybeExternalizePayload(\n sessionId: string,\n logDir: string,\n value: TSessionLogValue,\n options: Required<IFileSessionLoggerOptions>,\n): TSessionLogValue {\n const serialized = JSON.stringify(value);\n if (serialized === undefined) {\n return value;\n }\n const byteLength = Buffer.byteLength(serialized);\n if (byteLength <= options.externalPayloadThresholdBytes) {\n return value;\n }\n\n const sha256 = createHash('sha256').update(serialized).digest('hex');\n const payloadDirName = `${sessionId}.payloads`;\n const payloadFileName = `${sha256}.json`;\n const relativePath = join(payloadDirName, payloadFileName);\n const payloadDir = join(logDir, payloadDirName);\n const payloadPath = join(logDir, relativePath);\n mkdirSync(payloadDir, { recursive: true });\n if (!existsSync(payloadPath)) {\n writeFileSync(payloadPath, serialized, 'utf-8');\n }\n return {\n kind: 'external-payload',\n encoding: 'json',\n sha256,\n byteLength,\n relativePath,\n } satisfies IExternalPayloadReference;\n}\n\n/** No-op logger — used when logging is disabled. */\nexport class SilentSessionLogger implements ISessionLogger {\n log(): void {\n // intentionally empty\n }\n}\n","import type { TUniversalValue } from '@robota-sdk/agent-core';\nimport type { ISessionLogEntry } from './session-log-replay.js';\n\nexport interface ISessionReplayValidationIssue {\n code:\n | 'PROVIDER_RESPONSE_RAW_MISSING'\n | 'PROVIDER_NATIVE_RAW_PAYLOAD_MISSING'\n | 'PROVIDER_RESPONSE_NORMALIZED_MISSING'\n | 'TOOL_RESULT_MISSING'\n | 'PAYLOAD_REFERENCE_INVALID';\n message: string;\n eventIndex?: number;\n executionId?: string;\n round?: number;\n toolCallId?: string;\n}\n\nexport interface ISessionReplayValidationResult {\n ok: boolean;\n issues: ISessionReplayValidationIssue[];\n}\n\nexport function validateSessionReplayLogEntries(\n entries: readonly ISessionLogEntry[],\n): ISessionReplayValidationResult {\n const issues: ISessionReplayValidationIssue[] = [];\n const providerEvents = createProviderReplayEventIndex();\n const toolEvents = createToolReplayEventIndex();\n\n entries.forEach((entry, index) => {\n collectPayloadReferenceIssues(entry, index, issues);\n collectProviderReplayEvent(providerEvents, entry, index);\n collectToolReplayEvent(toolEvents, entry, index);\n });\n\n appendProviderReplayIssues(providerEvents, issues);\n appendToolReplayIssues(toolEvents, issues);\n\n return { ok: issues.length === 0, issues };\n}\n\ninterface IProviderReplayRequest {\n executionId: string;\n round: number;\n index: number;\n}\n\ninterface IProviderReplayEventIndex {\n requests: Map<string, IProviderReplayRequest>;\n nativeRawPayloads: Set<string>;\n rawResponses: Set<string>;\n normalizedResponses: Set<string>;\n}\n\ninterface IToolReplayRequest {\n executionId: string;\n toolCallId: string;\n index: number;\n}\n\ninterface IToolReplayEventIndex {\n requests: Map<string, IToolReplayRequest>;\n results: Set<string>;\n}\n\nfunction createProviderReplayEventIndex(): IProviderReplayEventIndex {\n return {\n requests: new Map<string, IProviderReplayRequest>(),\n nativeRawPayloads: new Set<string>(),\n rawResponses: new Set<string>(),\n normalizedResponses: new Set<string>(),\n };\n}\n\nfunction createToolReplayEventIndex(): IToolReplayEventIndex {\n return {\n requests: new Map<string, IToolReplayRequest>(),\n results: new Set<string>(),\n };\n}\n\nfunction collectProviderReplayEvent(\n events: IProviderReplayEventIndex,\n entry: ISessionLogEntry,\n index: number,\n): void {\n const key = providerKey(entry);\n if (!key) return;\n if (entry.event === 'provider_request') {\n events.requests.set(key.key, {\n executionId: key.executionId,\n round: key.round,\n index,\n });\n }\n if (entry.event === 'provider_response_raw') {\n events.rawResponses.add(key.key);\n }\n if (\n entry.event === 'provider_native_raw_payload' &&\n (entry.payloadKind === 'response' || entry.payloadKind === 'stream_event')\n ) {\n events.nativeRawPayloads.add(key.key);\n }\n if (entry.event === 'provider_response_normalized') {\n events.normalizedResponses.add(key.key);\n }\n}\n\nfunction collectToolReplayEvent(\n events: IToolReplayEventIndex,\n entry: ISessionLogEntry,\n index: number,\n): void {\n const key = toolKey(entry);\n if (!key) return;\n if (entry.event === 'tool_execution_request') {\n events.requests.set(key.key, {\n executionId: key.executionId,\n toolCallId: key.toolCallId,\n index,\n });\n }\n if (entry.event === 'tool_execution_result') {\n events.results.add(key.key);\n }\n}\n\nfunction appendProviderReplayIssues(\n events: IProviderReplayEventIndex,\n issues: ISessionReplayValidationIssue[],\n): void {\n for (const [key, request] of events.requests) {\n if (!events.nativeRawPayloads.has(key)) {\n issues.push({\n code: 'PROVIDER_NATIVE_RAW_PAYLOAD_MISSING',\n message: `Provider request ${key} has no provider-native raw response or stream payload event.`,\n eventIndex: request.index,\n executionId: request.executionId,\n round: request.round,\n });\n }\n if (!events.rawResponses.has(key)) {\n issues.push({\n code: 'PROVIDER_RESPONSE_RAW_MISSING',\n message: `Provider request ${key} has no raw response event.`,\n eventIndex: request.index,\n executionId: request.executionId,\n round: request.round,\n });\n }\n if (!events.normalizedResponses.has(key)) {\n issues.push({\n code: 'PROVIDER_RESPONSE_NORMALIZED_MISSING',\n message: `Provider request ${key} has no normalized response event.`,\n eventIndex: request.index,\n executionId: request.executionId,\n round: request.round,\n });\n }\n }\n}\n\nfunction appendToolReplayIssues(\n events: IToolReplayEventIndex,\n issues: ISessionReplayValidationIssue[],\n): void {\n for (const [key, request] of events.requests) {\n if (!events.results.has(key)) {\n issues.push({\n code: 'TOOL_RESULT_MISSING',\n message: `Tool request ${key} has no terminal result event.`,\n eventIndex: request.index,\n executionId: request.executionId,\n toolCallId: request.toolCallId,\n });\n }\n }\n}\n\nfunction providerKey(\n entry: ISessionLogEntry,\n): { key: string; executionId: string; round: number } | undefined {\n if (typeof entry.executionId !== 'string') return undefined;\n const round = typeof entry.round === 'number' ? entry.round : Number(entry.round);\n if (!Number.isFinite(round)) return undefined;\n return { key: `${entry.executionId}:${round}`, executionId: entry.executionId, round };\n}\n\nfunction toolKey(\n entry: ISessionLogEntry,\n): { key: string; executionId: string; toolCallId: string } | undefined {\n if (typeof entry.executionId !== 'string') return undefined;\n const toolCallId =\n typeof entry.toolCallId === 'string'\n ? entry.toolCallId\n : typeof entry.toolExecutionId === 'string'\n ? entry.toolExecutionId\n : undefined;\n if (!toolCallId) return undefined;\n return { key: `${entry.executionId}:${toolCallId}`, executionId: entry.executionId, toolCallId };\n}\n\nfunction collectPayloadReferenceIssues(\n value: TUniversalValue,\n eventIndex: number,\n issues: ISessionReplayValidationIssue[],\n): void {\n if (Array.isArray(value)) {\n value.forEach((item) => collectPayloadReferenceIssues(item, eventIndex, issues));\n return;\n }\n if (!isRecord(value)) return;\n if (value.kind === 'external-payload') {\n if (\n value.encoding !== 'json' ||\n typeof value.sha256 !== 'string' ||\n typeof value.relativePath !== 'string' ||\n typeof value.byteLength !== 'number'\n ) {\n issues.push({\n code: 'PAYLOAD_REFERENCE_INVALID',\n message: 'External payload reference is missing required replay fields.',\n eventIndex,\n });\n }\n return;\n }\n Object.values(value).forEach((child) => collectPayloadReferenceIssues(child, eventIndex, issues));\n}\n\nfunction isRecord(value: TUniversalValue): value is Record<string, TUniversalValue> {\n return typeof value === 'object' && value !== null && !Array.isArray(value);\n}\n","import { existsSync, readFileSync } from 'node:fs';\nimport { messageToHistoryEntry } from '@robota-sdk/agent-core';\nimport type { IHistoryEntry, TUniversalMessage, TUniversalValue } from '@robota-sdk/agent-core';\n\nexport interface ISessionLogEntry extends Record<string, TUniversalValue> {\n timestamp: string;\n sessionId: string;\n event: string;\n}\n\nexport interface ISessionReplayRecord {\n sessionId: string | undefined;\n cwd: string | undefined;\n createdAt: string | undefined;\n updatedAt: string | undefined;\n messages: TUniversalMessage[];\n history: IHistoryEntry[];\n backgroundTaskEvents: object[];\n backgroundJobGroupEvents: object[];\n memoryEvents: object[];\n}\n\nexport { validateSessionReplayLogEntries } from './session-log-validation.js';\nexport type {\n ISessionReplayValidationIssue,\n ISessionReplayValidationResult,\n} from './session-log-validation.js';\n\nexport function loadSessionLogEntries(logFile: string): ISessionLogEntry[] {\n if (!existsSync(logFile)) {\n return [];\n }\n return readFileSync(logFile, 'utf-8')\n .split('\\n')\n .map((line) => line.trim())\n .filter((line) => line.length > 0)\n .map((line) => JSON.parse(line) as ISessionLogEntry);\n}\n\nexport function replaySessionLogEntries(\n entries: readonly ISessionLogEntry[],\n): ISessionReplayRecord {\n const messages: TUniversalMessage[] = [];\n const history: IHistoryEntry[] = [];\n const auxiliaryEvents: IAuxiliaryReplayEvents = {\n backgroundTaskEvents: [],\n backgroundJobGroupEvents: [],\n memoryEvents: [],\n };\n let sessionId: string | undefined;\n let cwd: string | undefined;\n let createdAt: string | undefined;\n let updatedAt: string | undefined;\n\n for (const entry of entries) {\n sessionId = sessionId ?? entry.sessionId;\n createdAt = createdAt ?? entry.timestamp;\n updatedAt = entry.timestamp;\n\n if (entry.event === 'session_init') {\n cwd = typeof entry.cwd === 'string' ? entry.cwd : cwd;\n }\n\n if (entry.event === 'history_mutation' && entry.mutation === 'append_message') {\n const message = normalizeLogMessage(entry.message);\n if (message) {\n messages.push(message);\n history.push(messageToHistoryEntry(message));\n }\n }\n\n collectAuxiliaryReplayEvent(entry, auxiliaryEvents);\n }\n\n return {\n sessionId,\n cwd,\n createdAt,\n updatedAt,\n messages,\n history,\n backgroundTaskEvents: auxiliaryEvents.backgroundTaskEvents,\n backgroundJobGroupEvents: auxiliaryEvents.backgroundJobGroupEvents,\n memoryEvents: auxiliaryEvents.memoryEvents,\n };\n}\n\ninterface IAuxiliaryReplayEvents {\n backgroundTaskEvents: object[];\n backgroundJobGroupEvents: object[];\n memoryEvents: object[];\n}\n\nfunction collectAuxiliaryReplayEvent(\n entry: ISessionLogEntry,\n auxiliaryEvents: IAuxiliaryReplayEvents,\n): void {\n if (entry.event === 'background_task_event') {\n pushObjectPayload(auxiliaryEvents.backgroundTaskEvents, entry, 'backgroundEvent', 'data');\n return;\n }\n if (entry.event === 'background_job_group_event') {\n pushObjectPayload(\n auxiliaryEvents.backgroundJobGroupEvents,\n entry,\n 'backgroundJobGroupEvent',\n 'data',\n );\n return;\n }\n if (entry.event === 'memory_event') {\n pushObjectPayload(auxiliaryEvents.memoryEvents, entry, 'memoryEvent', 'data');\n }\n}\n\nfunction normalizeLogMessage(value: TUniversalValue): TUniversalMessage | undefined {\n if (!isRecord(value)) return undefined;\n const role = value.role;\n if (role !== 'user' && role !== 'assistant' && role !== 'system' && role !== 'tool') {\n return undefined;\n }\n const id = typeof value.id === 'string' ? value.id : `${role}-${Date.now()}`;\n const timestamp =\n value.timestamp instanceof Date\n ? value.timestamp\n : new Date(typeof value.timestamp === 'string' ? value.timestamp : Date.now());\n return {\n ...value,\n id,\n role,\n timestamp,\n } as TUniversalMessage;\n}\n\nfunction isRecord(value: TUniversalValue): value is Record<string, TUniversalValue> {\n return typeof value === 'object' && value !== null && !Array.isArray(value);\n}\n\nfunction getObjectPayload(entry: ISessionLogEntry, key: string): object | undefined {\n const value = entry[key];\n if (\n typeof value !== 'object' ||\n value === null ||\n Array.isArray(value) ||\n value instanceof Date\n ) {\n return undefined;\n }\n return value;\n}\n\nfunction pushObjectPayload(\n target: object[],\n entry: ISessionLogEntry,\n primaryKey: string,\n fallbackKey: string,\n): void {\n const payload = getObjectPayload(entry, primaryKey) ?? getObjectPayload(entry, fallbackKey);\n if (payload) target.push(payload);\n}\n","/**\n * SessionStore — persists conversation sessions as JSON files.\n *\n * Sessions are stored at `~/.robota/sessions/{id}.json` by default.\n * Consumers can inject a project-local directory such as `.robota/sessions`.\n * The store directory is created on first write if it does not exist.\n */\n\nimport { readFileSync, writeFileSync, existsSync, mkdirSync, unlinkSync, readdirSync } from 'fs';\nimport { join } from 'path';\nimport type { IToolSchema } from '@robota-sdk/agent-core';\n\n/** A persisted session record */\nexport interface ISessionRecord {\n /** Unique session identifier */\n id: string;\n /** Optional human-readable session name */\n name?: string;\n /** Working directory when the session was created */\n cwd: string;\n /** ISO-8601 creation timestamp */\n createdAt: string;\n /** ISO-8601 last-updated timestamp */\n updatedAt: string;\n /** Conversation messages (opaque to the store) */\n messages: unknown[];\n /** Full UI timeline (chat + events) for rendering restoration */\n history?: unknown[];\n /** Exact system prompt used to create the session. */\n systemPrompt?: string;\n /** Tool schemas registered for the session. */\n toolSchemas?: IToolSchema[];\n /** Latest background task snapshots for resume/debugging. */\n backgroundTasks?: unknown[];\n /** Durable non-streaming background task events for resume/debugging. */\n backgroundTaskEvents?: unknown[];\n /** Latest background job group snapshots for resume/debugging. */\n backgroundJobGroups?: unknown[];\n /** Durable background job group events for resume/debugging. */\n backgroundJobGroupEvents?: unknown[];\n /** Durable skill activation events for resume/debugging. */\n skillActivationEvents?: unknown[];\n /** Durable automatic memory events for resume/debugging. */\n memoryEvents?: unknown[];\n /** Memory references used by the latest prompt turn. */\n usedMemoryReferences?: unknown[];\n /** SDK-owned context reference inventory for resume/debugging. */\n contextReferences?: unknown[];\n /** Provider sandbox snapshot identifier for workspace hydration on resume. */\n sandboxSnapshotId?: string;\n}\n\n/** Minimal persistence port consumed by Session. */\nexport interface ISessionStore {\n save(session: ISessionRecord): void;\n load(id: string): ISessionRecord | undefined;\n list(): ISessionRecord[];\n delete(id: string): void;\n /** Return the absolute file path for a session file, if the store is file-backed. */\n getFilePath?(id: string): string;\n}\n\n/**\n * Return the current user home directory.\n * Reads process.env.HOME at call time so tests can override it.\n */\nfunction getHomeDir(): string {\n return process.env.HOME ?? process.env.USERPROFILE ?? '/';\n}\n\n/**\n * Persistent session store backed by individual JSON files.\n *\n * Construct with a custom `baseDir` to redirect storage (useful in tests).\n */\nexport class SessionStore implements ISessionStore {\n private readonly baseDir: string;\n\n constructor(baseDir?: string) {\n this.baseDir = baseDir ?? join(getHomeDir(), '.robota', 'sessions');\n }\n\n /** Ensure the storage directory exists */\n private ensureDir(): void {\n if (!existsSync(this.baseDir)) {\n mkdirSync(this.baseDir, { recursive: true });\n }\n }\n\n /** Absolute path to a session's JSON file */\n private filePath(id: string): string {\n return join(this.baseDir, `${id}.json`);\n }\n\n /** Return the absolute file path for a session — implements ISessionStore.getFilePath */\n getFilePath(id: string): string {\n return this.filePath(id);\n }\n\n /**\n * Persist a session record to disk.\n * Creates the storage directory if needed.\n */\n save(session: ISessionRecord): void {\n this.ensureDir();\n writeFileSync(this.filePath(session.id), JSON.stringify(session, null, 2), 'utf-8');\n }\n\n /**\n * Load a session by its ID.\n * Returns `undefined` when the session file does not exist.\n */\n load(id: string): ISessionRecord | undefined {\n const path = this.filePath(id);\n if (!existsSync(path)) {\n return undefined;\n }\n const raw = readFileSync(path, 'utf-8');\n return JSON.parse(raw) as ISessionRecord;\n }\n\n /**\n * List all persisted sessions, sorted by `updatedAt` descending (most recent first).\n */\n list(): ISessionRecord[] {\n if (!existsSync(this.baseDir)) {\n return [];\n }\n\n const files = readdirSync(this.baseDir).filter((f) => f.endsWith('.json'));\n const sessions: ISessionRecord[] = [];\n\n for (const file of files) {\n try {\n const raw = readFileSync(join(this.baseDir, file), 'utf-8');\n const record = JSON.parse(raw) as ISessionRecord;\n sessions.push(record);\n } catch {\n // Skip malformed files\n }\n }\n\n return sessions.sort(\n (a, b) => new Date(b.updatedAt).getTime() - new Date(a.updatedAt).getTime(),\n );\n }\n\n /**\n * Delete a session by its ID.\n * No-ops silently if the session does not exist.\n */\n delete(id: string): void {\n const path = this.filePath(id);\n if (existsSync(path)) {\n unlinkSync(path);\n }\n }\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"index.js","names":["isRecord","join","existsSync","readFileSync"],"sources":["../../src/session-base.ts","../../src/compaction-orchestrator.ts","../../src/context-window-tracker.ts","../../src/permission-types.ts","../../src/tool-hook-helpers.ts","../../src/permission-enforcer.ts","../../src/session-components.ts","../../src/session-history-ops.ts","../../src/session-lifecycle.ts","../../src/session-tool-execution-bridge.ts","../../src/session-run.ts","../../src/session.ts","../../src/session-logger.ts","../../src/session-log-validation.ts","../../src/session-log-replay.ts","../../src/session-store.ts"],"sourcesContent":["import type { ContextWindowTracker, TAutoCompactThreshold } from './context-window-tracker.js';\nimport type { PermissionEnforcer } from './permission-enforcer.js';\nimport type {\n Robota,\n IAIProvider,\n IContextWindowState,\n IHistoryEntry,\n IToolSchema,\n TPermissionMode,\n TUniversalMessage,\n} from '@robota-sdk/agent-core';\n\nexport abstract class SessionBase {\n protected abstract readonly robota: Robota;\n protected abstract readonly permissionEnforcer: PermissionEnforcer;\n protected abstract readonly contextTracker: ContextWindowTracker;\n protected abstract permissionMode: TPermissionMode;\n protected abstract readonly sessionId: string;\n protected abstract readonly aiProvider: IAIProvider;\n protected abstract readonly toolSchemas: IToolSchema[];\n protected abstract readonly model: string;\n protected abstract systemMessage: string;\n protected abstract messageCount: number;\n protected abstract abortController: AbortController | null;\n\n getPermissionMode(): TPermissionMode {\n return this.permissionMode;\n }\n\n /** Change the active permission mode — future tool calls will use the new mode. */\n setPermissionMode(mode: TPermissionMode): void {\n this.permissionMode = mode;\n }\n\n getSessionId(): string {\n return this.sessionId;\n }\n\n getSystemMessage(): string {\n return this.systemMessage;\n }\n\n /** Replace the active system message and propagate to the agent (used by staleness detection). */\n updateSystemMessage(newMessage: string): void {\n this.systemMessage = newMessage;\n this.robota.setModel({\n provider: this.aiProvider.name,\n model: this.model,\n systemMessage: newMessage,\n });\n }\n\n getToolSchemas(): IToolSchema[] {\n return this.toolSchemas;\n }\n\n getMessageCount(): number {\n return this.messageCount;\n }\n\n /** Get tools that have been session-approved (via \"Allow always\" choice). */\n getSessionAllowedTools(): string[] {\n return this.permissionEnforcer.getSessionAllowedTools();\n }\n\n clearSessionAllowedTools(): void {\n this.permissionEnforcer.clearSessionAllowedTools();\n }\n\n /** Abort the currently running execution. No-op if nothing is running. */\n abort(): void {\n if (this.abortController) {\n this.abortController.abort();\n this.abortController = null;\n }\n }\n\n isRunning(): boolean {\n return this.abortController !== null;\n }\n\n getContextState(): IContextWindowState {\n return this.contextTracker.getContextState();\n }\n\n getAutoCompactThreshold(): TAutoCompactThreshold {\n return this.contextTracker.getAutoCompactThreshold();\n }\n\n setAutoCompactThreshold(threshold: number | false): void {\n this.contextTracker.setAutoCompactThreshold(threshold);\n }\n\n getHistory(): TUniversalMessage[] {\n return this.robota.getHistory();\n }\n\n getFullHistory(): IHistoryEntry[] {\n return this.robota.getFullHistory();\n }\n\n /** Add an event entry to history (not a chat message) */\n addHistoryEntry(entry: IHistoryEntry): void {\n this.robota.addHistoryEntry(entry);\n }\n\n /** Inject a message into conversation history without execution (used for session restore). */\n injectMessage(\n role: 'user' | 'assistant' | 'system' | 'tool',\n content: string,\n options?: { toolCallId?: string; name?: string },\n ): void {\n this.robota.injectMessage(role, content, options);\n }\n\n clearHistory(): void {\n this.robota.clearHistory();\n this.contextTracker.reset();\n }\n}\n","/**\n * CompactionOrchestrator — handles conversation compaction (summarization)\n * to free context window space.\n *\n * Extracted from Session to separate compaction logic from conversation management.\n */\n\nimport { randomUUID } from 'node:crypto';\n\nimport { runHooks } from '@robota-sdk/agent-core';\n\nimport type {\n IAIProvider,\n TUniversalMessage,\n THooksConfig,\n IHookInput,\n IHookTypeExecutor,\n} from '@robota-sdk/agent-core';\n\nexport interface ICompactionOptions {\n sessionId: string;\n cwd: string;\n model: string;\n hooks?: Record<string, unknown>;\n compactInstructions?: string;\n /** Additional hook type executors (e.g. prompt, agent) beyond the core defaults. */\n hookTypeExecutors?: IHookTypeExecutor[];\n}\n\nexport class CompactionOrchestrator {\n private readonly sessionId: string;\n private readonly cwd: string;\n private readonly model: string;\n private readonly hooks?: Record<string, unknown>;\n private readonly compactInstructions?: string;\n private readonly hookTypeExecutors?: IHookTypeExecutor[];\n\n constructor(options: ICompactionOptions) {\n this.sessionId = options.sessionId;\n this.cwd = options.cwd;\n this.model = options.model;\n this.hooks = options.hooks;\n this.compactInstructions = options.compactInstructions;\n this.hookTypeExecutors = options.hookTypeExecutors;\n }\n\n /**\n * Run compaction — summarize the conversation to free context space.\n * @param provider - The AI provider to use for summarization\n * @param history - Current conversation history\n * @param instructions - Optional focus instructions for the summary\n * @returns The generated summary string\n */\n async compact(\n provider: IAIProvider,\n history: TUniversalMessage[],\n instructions?: string,\n ): Promise<string> {\n if (history.length === 0) return '';\n\n const trigger: 'auto' | 'manual' = instructions !== undefined ? 'manual' : 'auto';\n\n // Fire PreCompact hook\n const preHookInput: IHookInput = {\n session_id: this.sessionId,\n cwd: this.cwd,\n hook_event_name: 'PreCompact',\n trigger,\n };\n await runHooks(\n this.hooks as THooksConfig | undefined,\n 'PreCompact',\n preHookInput,\n this.hookTypeExecutors,\n );\n\n // Build compaction prompt\n const compactPrompt = this.buildCompactionPrompt(history, instructions);\n\n // Call provider to generate summary\n const summaryMessage = await provider.chat(\n [\n {\n id: randomUUID(),\n role: 'user',\n content: compactPrompt,\n state: 'complete' as const,\n timestamp: new Date(),\n },\n ],\n { model: this.model },\n );\n const summary =\n typeof summaryMessage.content === 'string' ? summaryMessage.content : '(compaction failed)';\n\n return summary;\n }\n\n /** Build the compaction prompt from conversation history */\n private buildCompactionPrompt(history: TUniversalMessage[], instructions?: string): string {\n const instructionBlock = instructions ?? this.compactInstructions ?? '';\n const instructionSection = instructionBlock ? `\\nAdditional focus:\\n${instructionBlock}\\n` : '';\n\n const formattedHistory = history\n .map((msg) => {\n const content = typeof msg.content === 'string' ? msg.content : JSON.stringify(msg.content);\n return `${msg.role}: ${content}`;\n })\n .join('\\n');\n\n return [\n 'Summarize the following conversation concisely, preserving:',\n \"- User's original requests and goals\",\n '- Key decisions and conclusions',\n '- Important code changes and file paths',\n '- Current task status and next steps',\n instructionSection,\n \"Drop verbose tool outputs, debugging steps, and exploratory work that didn't lead to results.\",\n '',\n 'Conversation:',\n formattedHistory,\n ].join('\\n');\n }\n}\n","/**\n * ContextWindowTracker — tracks token usage and context window state.\n *\n * Extracted from Session to separate context monitoring from conversation management.\n */\n\nimport { estimateContextTokensFromMessages, getModelContextWindow } from '@robota-sdk/agent-core';\n\nimport type { IContextWindowState, TUniversalMessage } from '@robota-sdk/agent-core';\n\n/** Percentage conversion factor */\nconst PERCENT = 100;\n\n/** Auto-compact when context usage reaches this fraction */\nexport const AUTO_COMPACT_THRESHOLD = 0.835;\n\nexport type TAutoCompactThreshold = number | false;\n\nexport class ContextWindowTracker {\n private contextUsedTokens = 0;\n private readonly contextMaxTokens: number;\n private autoCompactThreshold: TAutoCompactThreshold;\n\n constructor(\n model: string,\n contextMaxTokens?: number,\n autoCompactThreshold?: TAutoCompactThreshold,\n ) {\n this.contextMaxTokens = contextMaxTokens ?? getModelContextWindow(model);\n this.autoCompactThreshold = normalizeAutoCompactThreshold(autoCompactThreshold);\n }\n\n /** Get current context window state */\n getContextState(): IContextWindowState {\n const usedPercentage = Math.min(\n PERCENT,\n (this.contextUsedTokens / this.contextMaxTokens) * PERCENT,\n );\n return {\n maxTokens: this.contextMaxTokens,\n usedTokens: this.contextUsedTokens,\n usedPercentage: Math.round(usedPercentage * PERCENT) / PERCENT,\n remainingPercentage: Math.round((PERCENT - usedPercentage) * PERCENT) / PERCENT,\n };\n }\n\n /** Whether auto-compaction threshold has been exceeded */\n shouldAutoCompact(): boolean {\n if (this.autoCompactThreshold === false) {\n return false;\n }\n return this.getContextState().usedPercentage >= this.autoCompactThreshold * PERCENT;\n }\n\n /** The auto-compaction policy for this tracker. */\n getAutoCompactThreshold(): TAutoCompactThreshold {\n return this.autoCompactThreshold;\n }\n\n /** Update the auto-compaction policy for this tracker. */\n setAutoCompactThreshold(autoCompactThreshold: TAutoCompactThreshold): void {\n this.autoCompactThreshold = normalizeAutoCompactThreshold(autoCompactThreshold);\n }\n\n /**\n * Estimate token usage from conversation history.\n *\n * Uses the shared core estimator so session display, /context, auto-compact, and core\n * execution guards reason about the same effective token state.\n */\n updateFromHistory(history: TUniversalMessage[]): void {\n this.contextUsedTokens = estimateContextTokensFromMessages(history).usedTokens;\n }\n\n /** Reset token tracking */\n reset(): void {\n this.contextUsedTokens = 0;\n }\n}\n\nfunction normalizeAutoCompactThreshold(\n autoCompactThreshold: TAutoCompactThreshold | undefined,\n): TAutoCompactThreshold {\n if (autoCompactThreshold === undefined) {\n return AUTO_COMPACT_THRESHOLD;\n }\n if (autoCompactThreshold === false) {\n return false;\n }\n if (\n !Number.isFinite(autoCompactThreshold) ||\n autoCompactThreshold <= 0 ||\n autoCompactThreshold > 1\n ) {\n throw new RangeError('autoCompactThreshold must be a number greater than 0 and at most 1.');\n }\n return autoCompactThreshold;\n}\n","/**\n * Permission types — interfaces and type aliases for permission enforcement.\n */\n\nimport type { ISessionLogger } from './session-logger.js';\nimport type { IToolWithEventService, TPermissionMode, TToolArgs } from '@robota-sdk/agent-core';\nimport type { IHookTypeExecutor, ISpinner, ITerminalOutput } from '@robota-sdk/agent-core';\n\nexport type { ISpinner, ITerminalOutput };\n\n/**\n * Permission handler result:\n * - true: allow this invocation\n * - false: deny this invocation\n * - 'allow-session': allow this invocation and auto-approve this tool for the rest of the session\n */\nexport type TPermissionResult = boolean | 'allow-session';\n\n/**\n * Custom permission handler — called when a tool needs user approval.\n * Returns true to allow, false to deny, or 'allow-session' to remember for the session.\n */\nexport type TPermissionHandler = (\n toolName: string,\n toolArgs: TToolArgs,\n) => Promise<TPermissionResult>;\n\nexport interface IPermissionEnforcerOptions {\n sessionId: string;\n cwd: string;\n getPermissionMode: () => TPermissionMode;\n config: {\n permissions: { allow: string[]; deny: string[] };\n hooks?: Record<string, unknown>;\n };\n terminal: ITerminalOutput;\n permissionHandler?: TPermissionHandler;\n promptForApprovalFn?: (\n terminal: ITerminalOutput,\n toolName: string,\n toolArgs: TToolArgs,\n ) => Promise<boolean>;\n sessionLogger?: ISessionLogger;\n onToolExecution?: (event: {\n type: 'start' | 'end';\n toolName: string;\n toolArgs?: TToolArgs;\n success?: boolean;\n denied?: boolean;\n toolResultData?: string;\n }) => void;\n /** Additional hook type executors (e.g. prompt, agent) beyond the core defaults. */\n hookTypeExecutors?: IHookTypeExecutor[];\n /** Absolute path to session transcript file — passed to PreToolUse hook inputs as transcript_path */\n transcriptPath?: string;\n}\n\n/** Returned when the user denies a permission prompt. success:true prevents ToolExecutionError. */\nexport const PERMISSION_DENIED_RESULT = {\n success: true,\n data: JSON.stringify({\n success: false,\n output: '',\n error: 'Permission denied. The user did not approve this action.',\n }),\n metadata: {},\n} as const;\n\n/** Maximum chars for any single tool output. Matches Claude Code's 30K limit. */\nexport const MAX_TOOL_OUTPUT_CHARS = 30_000;\n","/**\n * Tool hook helpers — stateless utility functions for tool hook execution\n * and output truncation used by PermissionEnforcer.\n */\n\nimport { runHooks } from '@robota-sdk/agent-core';\n\nimport { MAX_TOOL_OUTPUT_CHARS } from './permission-types.js';\n\nimport type {\n IToolResult,\n TToolParameters,\n THooksConfig,\n IHookInput,\n IHookTypeExecutor,\n} from '@robota-sdk/agent-core';\n\n/**\n * Truncate tool result data if it exceeds MAX_TOOL_OUTPUT_CHARS.\n * Uses middle-truncation: keeps first and last portions, removes middle.\n */\nexport function truncateToolResult(result: IToolResult): IToolResult {\n if (typeof result.data !== 'string') return result;\n if (result.data.length <= MAX_TOOL_OUTPUT_CHARS) return result;\n\n const halfLimit = Math.floor(MAX_TOOL_OUTPUT_CHARS / 2);\n const head = result.data.substring(0, halfLimit);\n const tail = result.data.substring(result.data.length - halfLimit);\n const originalSize = result.data.length;\n const truncatedData = `${head}\\n\\n[... output truncated: ${originalSize.toLocaleString()} chars total, showing first and last ${halfLimit.toLocaleString()} chars ...]\\n\\n${tail}`;\n\n return { ...result, data: truncatedData };\n}\n\n/** Build a hook input object for tool execution hooks */\nexport function buildHookInput(\n sessionId: string,\n cwd: string,\n toolName: string,\n parameters: TToolParameters,\n permissionMode?: string,\n transcriptPath?: string,\n): IHookInput {\n return {\n session_id: sessionId,\n cwd,\n hook_event_name: 'PreToolUse',\n tool_name: toolName,\n tool_input: parameters as Record<string, string | number | boolean | object>,\n ...(permissionMode !== undefined && { permission_mode: permissionMode }),\n ...(transcriptPath !== undefined && { transcript_path: transcriptPath }),\n };\n}\n\n/** Run PreToolUse hooks; returns a denial IToolResult if blocked, or null to proceed */\nexport async function runPreToolHook(\n hooks: Record<string, unknown> | undefined,\n hookInput: IHookInput,\n hookTypeExecutors: IHookTypeExecutor[] | undefined,\n): Promise<IToolResult | null> {\n const hookResult = await runHooks(\n hooks as THooksConfig | undefined,\n 'PreToolUse',\n hookInput,\n hookTypeExecutors,\n );\n if (hookResult.blocked) {\n return {\n success: true,\n data: JSON.stringify({\n blocked: true,\n reason: hookResult.reason ?? 'Blocked by hook',\n }),\n metadata: {},\n };\n }\n return null;\n}\n\n/** Fire PostToolUse hooks (fire and forget) */\nexport function firePostToolHook(\n hooks: Record<string, unknown> | undefined,\n hookInput: IHookInput,\n result: IToolResult,\n hookTypeExecutors: IHookTypeExecutor[] | undefined,\n): void {\n const postHookInput: IHookInput = {\n ...hookInput,\n hook_event_name: 'PostToolUse',\n tool_output: typeof result.data === 'string' ? result.data : JSON.stringify(result.data),\n };\n runHooks(\n hooks as THooksConfig | undefined,\n 'PostToolUse',\n postHookInput,\n hookTypeExecutors,\n ).catch(() => {});\n}\n","/**\n * PermissionEnforcer — handles tool permission checking, hook execution,\n * and tool output truncation.\n *\n * Extracted from Session to separate permission/hook concerns from\n * conversation management.\n */\n\nimport { evaluatePermission } from '@robota-sdk/agent-core';\n\nimport { PERMISSION_DENIED_RESULT } from './permission-types.js';\nimport {\n truncateToolResult,\n buildHookInput,\n runPreToolHook,\n firePostToolHook,\n} from './tool-hook-helpers.js';\n\nimport type {\n IPermissionEnforcerOptions,\n TPermissionHandler,\n TPermissionResult,\n ITerminalOutput,\n ISpinner,\n} from './permission-types.js';\nimport type { ISessionLogger, TSessionLogData } from './session-logger.js';\nimport type {\n IToolWithEventService,\n IToolResult,\n TToolParameters,\n IToolExecutionContext,\n TToolArgs,\n} from '@robota-sdk/agent-core';\n\nexport type { TPermissionHandler, TPermissionResult, ITerminalOutput, ISpinner };\nexport type { IPermissionEnforcerOptions };\n\nexport class PermissionEnforcer {\n private readonly sessionId: string;\n private readonly cwd: string;\n private readonly getPermissionMode: IPermissionEnforcerOptions['getPermissionMode'];\n private readonly config: IPermissionEnforcerOptions['config'];\n private readonly terminal: ITerminalOutput;\n private readonly permissionHandler?: TPermissionHandler;\n private readonly promptForApprovalFn?: IPermissionEnforcerOptions['promptForApprovalFn'];\n private readonly sessionLogger?: ISessionLogger;\n private readonly onToolExecution?: IPermissionEnforcerOptions['onToolExecution'];\n private readonly hookTypeExecutors?: IPermissionEnforcerOptions['hookTypeExecutors'];\n private readonly transcriptPath?: string;\n private readonly sessionAllowedTools = new Set<string>();\n\n constructor(options: IPermissionEnforcerOptions) {\n this.sessionId = options.sessionId;\n this.cwd = options.cwd;\n this.getPermissionMode = options.getPermissionMode;\n this.config = options.config;\n this.terminal = options.terminal;\n this.permissionHandler = options.permissionHandler;\n this.promptForApprovalFn = options.promptForApprovalFn;\n this.sessionLogger = options.sessionLogger;\n this.onToolExecution = options.onToolExecution;\n this.hookTypeExecutors = options.hookTypeExecutors;\n this.transcriptPath = options.transcriptPath;\n }\n\n /** Wrap all tools with permission checking */\n wrapTools(tools: IToolWithEventService[]): IToolWithEventService[] {\n return tools.map((tool) => this.wrapToolWithPermission(tool));\n }\n\n /** Get tools that have been session-approved (via \"Allow always\" choice). */\n getSessionAllowedTools(): string[] {\n return [...this.sessionAllowedTools];\n }\n\n /** Clear all session-scoped allow rules. */\n clearSessionAllowedTools(): void {\n this.sessionAllowedTools.clear();\n }\n\n /**\n * Wrap a tool with permission checking.\n * The wrapper intercepts execute() and runs permission evaluation before delegating.\n * If denied, returns a tool result indicating the action was blocked.\n */\n private wrapToolWithPermission(tool: IToolWithEventService): IToolWithEventService {\n const enforcer = this;\n const originalExecute = tool.execute.bind(tool);\n\n const wrappedTool = Object.create(tool) as IToolWithEventService;\n wrappedTool.execute = async (\n parameters: TToolParameters,\n context?: IToolExecutionContext,\n ): Promise<IToolResult> => {\n // Must NEVER throw — if this throws, the execution round records the\n // assistant tool_use in history but never adds a tool_result, which\n // corrupts the conversation and causes a 400 error on the next API call.\n try {\n const toolName = tool.getName();\n enforcer.log('tool_call', {\n tool: toolName,\n args: parameters as Record<string, string | number | boolean | object>,\n });\n\n const hookInput = buildHookInput(\n enforcer.sessionId,\n enforcer.cwd,\n toolName,\n parameters,\n enforcer.getPermissionMode(),\n enforcer.transcriptPath,\n );\n\n const preResult = await runPreToolHook(\n enforcer.config.hooks,\n hookInput,\n enforcer.hookTypeExecutors,\n );\n if (preResult) {\n enforcer.log('tool_blocked', { tool: toolName, reason: 'hook' });\n return preResult;\n }\n\n const allowed = await enforcer.checkPermission(toolName, parameters as TToolArgs);\n if (!allowed) {\n enforcer.log('tool_denied', { tool: toolName, reason: 'permission' });\n enforcer.onToolExecution?.({\n type: 'end',\n toolName,\n toolArgs: parameters as TToolArgs,\n success: false,\n denied: true,\n });\n return PERMISSION_DENIED_RESULT;\n }\n\n enforcer.onToolExecution?.({ type: 'start', toolName, toolArgs: parameters as TToolArgs });\n\n const result = await originalExecute(parameters, context as IToolExecutionContext);\n\n // Truncate oversized tool output (Claude Code uses 30K char limit)\n const truncatedResult = truncateToolResult(result);\n\n enforcer.onToolExecution?.({\n type: 'end',\n toolName,\n toolArgs: parameters as TToolArgs,\n success: truncatedResult.success,\n toolResultData:\n typeof truncatedResult.data === 'string'\n ? truncatedResult.data\n : JSON.stringify(truncatedResult.data),\n });\n\n const dataSize =\n typeof truncatedResult.data === 'string'\n ? truncatedResult.data.length\n : JSON.stringify(truncatedResult.data).length;\n enforcer.log('tool_result', {\n tool: toolName,\n success: truncatedResult.success,\n dataChars: dataSize,\n truncated: truncatedResult !== result,\n });\n firePostToolHook(\n enforcer.config.hooks,\n hookInput,\n truncatedResult,\n enforcer.hookTypeExecutors,\n );\n return truncatedResult;\n } catch (err) {\n const message = err instanceof Error ? err.message : String(err);\n return {\n success: true,\n data: JSON.stringify({ success: false, output: '', error: message }),\n metadata: {},\n };\n }\n };\n\n return wrappedTool;\n }\n\n /** Evaluate permission for a tool call using the current mode and config */\n async checkPermission(toolName: string, toolArgs: TToolArgs): Promise<boolean> {\n const decision = evaluatePermission(toolName, toolArgs, this.getPermissionMode(), {\n allow: this.config.permissions.allow,\n deny: this.config.permissions.deny,\n });\n\n if (decision === 'auto') return true;\n if (decision === 'deny') return false;\n\n // Check session-scoped allow list before prompting\n if (this.sessionAllowedTools.has(toolName)) return true;\n\n // 'approve' — prompt the user via custom handler, injected approval fn, or deny\n if (this.permissionHandler) {\n const result = await this.permissionHandler(toolName, toolArgs);\n if (result === 'allow-session') {\n this.sessionAllowedTools.add(toolName);\n return true;\n }\n return result;\n }\n if (this.promptForApprovalFn) {\n return this.promptForApprovalFn(this.terminal, toolName, toolArgs);\n }\n // No approval mechanism available — deny by default\n return false;\n }\n\n /** Delegate session event to the injected logger. */\n private log(event: string, data: TSessionLogData): void {\n this.sessionLogger?.log(this.sessionId, event, data);\n }\n}\n","import { Robota } from '@robota-sdk/agent-core';\n\nimport { CompactionOrchestrator } from './compaction-orchestrator.js';\nimport { ContextWindowTracker } from './context-window-tracker.js';\nimport { PermissionEnforcer } from './permission-enforcer.js';\n\nimport type { ISessionOptions } from './session-types.js';\nimport type {\n IAgentConfig,\n IAIProvider,\n IToolWithEventService,\n TPermissionMode,\n} from '@robota-sdk/agent-core';\n\nexport function buildPermissionEnforcer(\n options: ISessionOptions,\n sessionId: string,\n cwd: string,\n getPermissionMode: () => TPermissionMode,\n transcriptPath: string | undefined,\n): PermissionEnforcer {\n return new PermissionEnforcer({\n sessionId,\n cwd,\n getPermissionMode,\n config: {\n permissions: options.permissions ?? { allow: [], deny: [] },\n hooks: options.hooks,\n },\n terminal: options.terminal,\n permissionHandler: options.permissionHandler,\n promptForApprovalFn: options.promptForApproval,\n sessionLogger: options.sessionLogger,\n onToolExecution: options.onToolExecution,\n hookTypeExecutors: options.hookTypeExecutors,\n transcriptPath,\n });\n}\n\nexport function buildSessionTrackers(\n options: ISessionOptions,\n model: string,\n sessionId: string,\n cwd: string,\n): { contextTracker: ContextWindowTracker; compactionOrchestrator: CompactionOrchestrator } {\n const contextTracker = new ContextWindowTracker(\n model,\n options.contextMaxTokens,\n options.autoCompactThreshold,\n );\n const compactionOrchestrator = new CompactionOrchestrator({\n sessionId,\n cwd,\n model,\n hooks: options.hooks,\n compactInstructions: options.compactInstructions,\n hookTypeExecutors: options.hookTypeExecutors,\n });\n return { contextTracker, compactionOrchestrator };\n}\n\nexport function buildRobota(\n options: ISessionOptions,\n permissionEnforcer: PermissionEnforcer,\n tools: IToolWithEventService[],\n provider: IAIProvider,\n model: string,\n systemMessage: string,\n): Robota {\n const wrappedTools = permissionEnforcer.wrapTools(tools);\n const agentConfig: IAgentConfig = {\n name: options.agentName ?? 'agent',\n aiProviders: [provider],\n defaultModel: {\n provider: provider.name,\n model,\n systemMessage,\n },\n systemMessage,\n tools: wrappedTools,\n logging: { enabled: false },\n ...(options.providerTimeout !== undefined && { timeout: options.providerTimeout }),\n };\n return new Robota(agentConfig);\n}\n","/**\n * Session history operations — compaction and persistence helpers.\n *\n * Extracted from Session to keep session.ts under the 300-line limit.\n * Each function receives its dependencies explicitly.\n */\n\nimport { runHooks } from '@robota-sdk/agent-core';\n\nimport type { CompactionOrchestrator } from './compaction-orchestrator.js';\nimport type { ContextWindowTracker } from './context-window-tracker.js';\nimport type { TSessionLogData } from './session-logger.js';\nimport type { ISessionRecord, ISessionStore } from './session-store.js';\nimport type { ICompactEvent, TCompactTrigger } from './session-types.js';\nimport type { IToolSchema } from '@robota-sdk/agent-core';\nimport type { Robota } from '@robota-sdk/agent-core';\nimport type {\n IAIProvider,\n THooksConfig,\n IHookInput,\n IHookTypeExecutor,\n} from '@robota-sdk/agent-core';\n\n/** Dependencies for compact() */\nexport interface ICompactContext {\n sessionId: string;\n cwd: string;\n systemMessage: string;\n robota: Robota;\n aiProvider: IAIProvider;\n compactionOrchestrator: CompactionOrchestrator;\n contextTracker: ContextWindowTracker;\n hooks: Record<string, unknown> | undefined;\n hookTypeExecutors: IHookTypeExecutor[] | undefined;\n onCompactCallback: ((summary: string) => void) | undefined;\n onCompactEventCallback: ((event: ICompactEvent) => void) | undefined;\n trigger: TCompactTrigger;\n log: (event: string, data: TSessionLogData) => void;\n}\n\n/**\n * Summarize the conversation to free context space.\n *\n * @param instructions - Optional focus instructions for the summary\n * @param ctx - Session state and callbacks\n */\nexport async function compact(\n instructions: string | undefined,\n ctx: ICompactContext,\n): Promise<void> {\n const history = ctx.robota.getHistory();\n if (history.length === 0) return;\n\n ctx.contextTracker.updateFromHistory(history);\n const before = ctx.contextTracker.getContextState();\n\n // Exclude system messages from compaction — they are preserved and re-injected after\n const nonSystemHistory = history.filter((msg) => msg.role !== 'system');\n const summary = await ctx.compactionOrchestrator.compact(\n ctx.aiProvider,\n nonSystemHistory,\n instructions,\n );\n\n // Clear history, re-inject system message, then inject summary.\n // System message must persist across compactions — it contains project context\n // (cwd, AGENTS.md, CLAUDE.md) that the AI needs for every response.\n ctx.robota.clearHistory();\n ctx.robota.injectMessage('system', ctx.systemMessage);\n ctx.robota.injectMessage('assistant', `[Context Summary]\\n${summary}`);\n\n // Reset token tracking based on the new shorter history\n ctx.contextTracker.updateFromHistory(ctx.robota.getHistory());\n\n // Fire PostCompact hook after history replacement is complete\n const postHookInput: IHookInput = {\n session_id: ctx.sessionId,\n cwd: ctx.cwd,\n hook_event_name: 'PostCompact',\n trigger: ctx.trigger,\n compact_summary: summary,\n };\n runHooks(\n ctx.hooks as THooksConfig | undefined,\n 'PostCompact',\n postHookInput,\n ctx.hookTypeExecutors,\n ).catch(() => {});\n\n // Notify via callback after compaction is fully complete\n const after = ctx.contextTracker.getContextState();\n ctx.log('context_compact', {\n trigger: ctx.trigger,\n before,\n after,\n });\n ctx.onCompactEventCallback?.({ trigger: ctx.trigger, before, after });\n if (ctx.onCompactCallback) {\n ctx.onCompactCallback(summary);\n }\n}\n\n/** Dependencies for persistSession() */\nexport interface IPersistContext {\n sessionId: string;\n cwd: string;\n systemPrompt: string;\n toolSchemas: IToolSchema[];\n sessionStore: ISessionStore;\n robota: Robota;\n getFullHistory: () => Array<{\n id: string;\n timestamp: Date;\n category: string;\n type: string;\n data?: unknown;\n }>;\n}\n\n/** Persist the current session to the store */\nexport function persistSession(ctx: IPersistContext): void {\n const history = ctx.robota.getHistory();\n const now = new Date().toISOString();\n\n const existing = ctx.sessionStore.load(ctx.sessionId);\n\n const record: ISessionRecord = {\n id: ctx.sessionId,\n name: existing?.name,\n cwd: ctx.cwd,\n createdAt: existing?.createdAt ?? now,\n updatedAt: now,\n messages: history,\n history: ctx.getFullHistory(),\n systemPrompt: ctx.systemPrompt,\n toolSchemas: ctx.toolSchemas,\n };\n\n ctx.sessionStore.save(record);\n}\n","/**\n * Session lifecycle helpers — provider configuration and session start hooks.\n *\n * Extracted from Session to keep session.ts under the 300-line limit.\n * All functions receive their dependencies explicitly.\n */\n\nimport { runHooks } from '@robota-sdk/agent-core';\n\nimport type { TSessionLogData } from './session-logger.js';\nimport type { ISessionOptions } from './session-types.js';\nimport type {\n IAIProvider,\n TSessionEndReason,\n THooksConfig,\n IHookInput,\n IHookTypeExecutor,\n} from '@robota-sdk/agent-core';\n\n/**\n * Configure provider-specific features: streaming, web tools, server tool logging.\n * Mutates the provider object in-place.\n */\nexport function configureProvider(\n provider: IAIProvider,\n _options: ISessionOptions,\n log: (event: string, data: TSessionLogData) => void,\n): void {\n provider.configureNativeWebTools?.({ webSearch: true });\n\n // Wire server tool logging\n if ('onServerToolUse' in provider) {\n (\n provider as { onServerToolUse?: (name: string, input: Record<string, string>) => void }\n ).onServerToolUse = (name: string, input: Record<string, string>) => {\n log('server_tool', { tool: name, ...input });\n };\n }\n}\n\n/**\n * Fire SessionStart hook asynchronously.\n * Calls onStdout when the hook produces stdout (used to seed the first run()).\n */\nexport function fireSessionStartHook(\n sessionId: string,\n cwd: string,\n hooks: Record<string, unknown> | undefined,\n hookTypeExecutors: IHookTypeExecutor[] | undefined,\n onStdout: (stdout: string) => void,\n permissionMode?: string,\n transcriptPath?: string,\n): void {\n const hookInput: IHookInput = {\n session_id: sessionId,\n cwd,\n hook_event_name: 'SessionStart',\n ...(permissionMode !== undefined && { permission_mode: permissionMode }),\n ...(transcriptPath !== undefined && { transcript_path: transcriptPath }),\n env: {\n CLAUDE_PROJECT_DIR: cwd,\n CLAUDE_SESSION_ID: sessionId,\n },\n };\n runHooks(hooks as THooksConfig | undefined, 'SessionStart', hookInput, hookTypeExecutors)\n .then((result) => {\n if (result.stdout) {\n onStdout(result.stdout);\n }\n })\n .catch(() => {});\n}\n\n/** Fire SessionEnd hook and wait for hook completion before process exit. */\nexport async function fireSessionEndHook(\n sessionId: string,\n cwd: string,\n reason: TSessionEndReason,\n hooks: Record<string, unknown> | undefined,\n hookTypeExecutors: IHookTypeExecutor[] | undefined,\n permissionMode?: string,\n transcriptPath?: string,\n): Promise<void> {\n const hookInput: IHookInput = {\n session_id: sessionId,\n cwd,\n hook_event_name: 'SessionEnd',\n reason,\n ...(permissionMode !== undefined && { permission_mode: permissionMode }),\n ...(transcriptPath !== undefined && { transcript_path: transcriptPath }),\n env: {\n CLAUDE_PROJECT_DIR: cwd,\n CLAUDE_SESSION_ID: sessionId,\n },\n };\n await runHooks(hooks as THooksConfig | undefined, 'SessionEnd', hookInput, hookTypeExecutors);\n}\n","import type { ISessionOptions } from './session-types.js';\nimport type { TExecutionEventData, TToolArgs } from '@robota-sdk/agent-core';\n\nconst UNKNOWN_TOOL_ERROR_CODE = 'unknown_tool';\n\ntype TToolExecutionCallback = NonNullable<ISessionOptions['onToolExecution']>;\n\nexport interface IToolExecutionBridge {\n knownToolNames: ReadonlySet<string>;\n unknownToolCallIds: Set<string>;\n onToolExecution?: TToolExecutionCallback;\n}\n\nexport function createToolExecutionBridge(options: {\n knownToolNames: readonly string[];\n onToolExecution?: TToolExecutionCallback;\n}): IToolExecutionBridge {\n return {\n knownToolNames: new Set(options.knownToolNames),\n unknownToolCallIds: new Set<string>(),\n ...(options.onToolExecution && { onToolExecution: options.onToolExecution }),\n };\n}\n\nexport function forwardToolExecutionEvent(\n bridge: IToolExecutionBridge,\n event: string,\n data: TExecutionEventData,\n): void {\n if (!bridge.onToolExecution) return;\n if (event === 'tool_execution_request') {\n forwardUnknownToolStart(bridge, data);\n return;\n }\n if (event === 'tool_execution_result') {\n forwardUnknownToolEnd(bridge, data);\n }\n}\n\nfunction forwardUnknownToolStart(bridge: IToolExecutionBridge, data: TExecutionEventData): void {\n const toolName = getString(data.toolName);\n const toolCallId = getString(data.toolCallId);\n if (!toolName || !toolCallId || bridge.knownToolNames.has(toolName)) return;\n\n bridge.unknownToolCallIds.add(toolCallId);\n bridge.onToolExecution?.({\n type: 'start',\n toolName,\n toolArgs: toToolArgs(data.parameters),\n });\n}\n\nfunction forwardUnknownToolEnd(bridge: IToolExecutionBridge, data: TExecutionEventData): void {\n const toolName = getString(data.toolName);\n const toolCallId = getString(data.toolCallId);\n if (!toolName || !toolCallId) return;\n\n const metadata = getRecord(data.metadata);\n const isUnknown =\n bridge.unknownToolCallIds.has(toolCallId) || metadata?.errorCode === UNKNOWN_TOOL_ERROR_CODE;\n if (!isUnknown) return;\n\n bridge.unknownToolCallIds.delete(toolCallId);\n const error = getString(data.error) ?? `Tool \"${toolName}\" is not registered.`;\n bridge.onToolExecution?.({\n type: 'end',\n toolName,\n success: false,\n toolResultData: JSON.stringify({\n success: false,\n error,\n errorCode: UNKNOWN_TOOL_ERROR_CODE,\n requestedTool: getString(metadata?.requestedTool) ?? toolName,\n availableTools: getStringArray(metadata?.availableTools),\n }),\n });\n}\n\nfunction toToolArgs(value: unknown): TToolArgs | undefined {\n const record = getRecord(value);\n if (!record) return undefined;\n\n const args: TToolArgs = {};\n for (const [key, item] of Object.entries(record)) {\n if (\n typeof item === 'string' ||\n typeof item === 'number' ||\n typeof item === 'boolean' ||\n (typeof item === 'object' && item !== null)\n ) {\n args[key] = item;\n }\n }\n return args;\n}\n\nfunction getString(value: unknown): string | undefined {\n return typeof value === 'string' && value.length > 0 ? value : undefined;\n}\n\nfunction getRecord(value: unknown): Record<string, unknown> | undefined {\n return typeof value === 'object' && value !== null && !Array.isArray(value)\n ? (value as Record<string, unknown>)\n : undefined;\n}\n\nfunction getStringArray(value: unknown): string[] {\n if (!Array.isArray(value)) return [];\n return value.filter((item): item is string => typeof item === 'string');\n}\n","/**\n * Session run — core execution logic for a single agent turn.\n *\n * Extracted from Session to keep session.ts under the 300-line limit.\n * Stateless: all mutable state is passed in via IRunContext.\n */\n\nimport { createUserMessage, getProviderCapabilities, runHooks } from '@robota-sdk/agent-core';\n\nimport {\n createToolExecutionBridge,\n forwardToolExecutionEvent,\n} from './session-tool-execution-bridge.js';\n\nimport type { ContextWindowTracker } from './context-window-tracker.js';\nimport type { TSessionLogData } from './session-logger.js';\nimport type { ISessionOptions } from './session-types.js';\nimport type {\n IAIProvider,\n IContextWindowState,\n THooksConfig,\n IHookTypeExecutor,\n TTextDeltaCallback,\n} from '@robota-sdk/agent-core';\nimport type { Robota } from '@robota-sdk/agent-core';\n\n/** Dependencies injected by Session.run() */\nexport interface IRunContext {\n sessionId: string;\n cwd: string;\n model: string;\n /** Current permission mode — passed to all hook inputs as permission_mode */\n permissionMode?: string;\n /** Absolute path to session transcript file — passed to all hook inputs as transcript_path */\n transcriptPath?: string;\n robota: Robota;\n aiProvider: IAIProvider;\n contextTracker: ContextWindowTracker;\n hooks: Record<string, unknown> | undefined;\n hookTypeExecutors: IHookTypeExecutor[] | undefined;\n sessionStartStdout: string;\n log: (event: string, data: TSessionLogData) => void;\n compact: () => Promise<void>;\n persistSession: () => void;\n getSessionStore: () => boolean;\n clearSessionStartStdout: () => void;\n maxTurns?: number;\n onTextDelta?: TTextDeltaCallback;\n onContextUpdate?: (state: IContextWindowState) => void;\n onToolExecution?: ISessionOptions['onToolExecution'];\n knownToolNames?: readonly string[];\n}\n\n/**\n * Execute a single agent turn: run hooks, send message to AI, log results.\n *\n * @param message - The processed message to send to the AI\n * @param rawInput - Optional raw user input (used for hook prompt field)\n * @param ctx - Session state and callbacks\n * @param abortSignal - AbortSignal from the session's AbortController\n */\nexport async function executeRun(\n message: string,\n rawInput: string | undefined,\n ctx: IRunContext,\n abortSignal: AbortSignal,\n): Promise<string> {\n // Auto-compact BEFORE processing the new message (not after).\n // This prevents compaction from interfering with the current response stream.\n ctx.contextTracker.updateFromHistory(ctx.robota.getHistory());\n if (ctx.contextTracker.shouldAutoCompact()) {\n // Providers store onTextDelta as an instance property for their own internal streaming.\n // Compaction calls provider.chat() without passing onTextDelta in options, so the\n // provider falls back to this.onTextDelta. Temporarily clearing it prevents compaction\n // summary text from streaming to the UI. This workaround stays until provider packages\n // remove the instance-level onTextDelta property.\n const provider = ctx.aiProvider as { onTextDelta?: unknown };\n const savedDelta = provider.onTextDelta;\n provider.onTextDelta = undefined;\n try {\n await ctx.compact();\n } finally {\n provider.onTextDelta = savedDelta;\n }\n }\n\n ctx.log('user', { content: message });\n\n // Fire UserPromptSubmit hook before AI processes input\n const hookResult = await runHooks(\n ctx.hooks as THooksConfig | undefined,\n 'UserPromptSubmit',\n {\n session_id: ctx.sessionId,\n cwd: ctx.cwd,\n hook_event_name: 'UserPromptSubmit',\n user_message: rawInput ?? message,\n prompt: rawInput ?? message,\n ...(ctx.permissionMode !== undefined && { permission_mode: ctx.permissionMode }),\n ...(ctx.transcriptPath !== undefined && { transcript_path: ctx.transcriptPath }),\n env: {\n CLAUDE_PROJECT_DIR: ctx.cwd,\n CLAUDE_SESSION_ID: ctx.sessionId,\n },\n },\n ctx.hookTypeExecutors,\n );\n\n // Inject hook stdout into user message (e.g., plugin path info)\n const hookStdout = [ctx.sessionStartStdout, hookResult.stdout].filter(Boolean).join('\\n');\n const enrichedMessage = hookStdout\n ? `<system-reminder>\\n${hookStdout}\\n</system-reminder>\\n${message}`\n : message;\n // Clear sessionStart stdout after first injection\n ctx.clearSessionStartStdout();\n\n const history = ctx.robota.getHistory();\n const historyJson = JSON.stringify(history);\n const providerCapabilities = getProviderCapabilities(ctx.aiProvider);\n ctx.log('pre_run', {\n historyLength: history.length,\n historyChars: historyJson.length,\n historyEstTokens: Math.ceil(historyJson.length / 4),\n input: enrichedMessage,\n history,\n model: ctx.model,\n provider: ctx.aiProvider.name,\n maxTokens: ctx.contextTracker.getContextState().maxTokens,\n nativeWebSearchSupported: providerCapabilities.nativeWebTools.webSearch.supported,\n nativeWebSearchEnabled: providerCapabilities.nativeWebTools.webSearch.enabled,\n nativeWebFetchSupported: providerCapabilities.nativeWebTools.webFetch.supported,\n nativeWebFetchEnabled: providerCapabilities.nativeWebTools.webFetch.enabled,\n });\n ctx.contextTracker.updateFromHistory([...history, createUserMessage(enrichedMessage)]);\n ctx.onContextUpdate?.(ctx.contextTracker.getContextState());\n\n let response: string;\n try {\n const toolExecutionBridge = createToolExecutionBridge({\n knownToolNames: ctx.knownToolNames ?? [],\n ...(ctx.onToolExecution && { onToolExecution: ctx.onToolExecution }),\n });\n const onTextDelta = ctx.onTextDelta\n ? (delta: string): void => {\n ctx.log('text_delta', { delta });\n ctx.onTextDelta?.(delta);\n }\n : undefined;\n\n response = await ctx.robota.run(enrichedMessage, {\n signal: abortSignal,\n maxExecutionRounds: ctx.maxTurns ?? 0,\n onExecutionEvent: (event, data) => {\n ctx.log(event, data as TSessionLogData);\n forwardToolExecutionEvent(toolExecutionBridge, event, data);\n },\n ...(onTextDelta && { onTextDelta }),\n });\n\n // If execution was interrupted (abort fired during execution),\n // throw AbortError so the caller (useSubmitHandler) shows \"Cancelled.\"\n if (abortSignal.aborted) {\n throw new DOMException('Aborted', 'AbortError');\n }\n } catch (error) {\n ctx.log('error', {\n message: error instanceof Error ? error.message : String(error),\n stack: error instanceof Error ? (error.stack ?? '') : '',\n historyLength: ctx.robota.getHistory().length,\n });\n runHooks(\n ctx.hooks as THooksConfig | undefined,\n 'StopFailure',\n {\n session_id: ctx.sessionId,\n cwd: ctx.cwd,\n hook_event_name: 'StopFailure',\n reason: error instanceof Error ? error.message : String(error),\n stop_hook_active: false,\n ...(ctx.permissionMode !== undefined && { permission_mode: ctx.permissionMode }),\n ...(ctx.transcriptPath !== undefined && { transcript_path: ctx.transcriptPath }),\n env: {\n CLAUDE_PROJECT_DIR: ctx.cwd,\n CLAUDE_SESSION_ID: ctx.sessionId,\n },\n },\n ctx.hookTypeExecutors,\n ).catch(() => {});\n throw error;\n }\n\n // Log the response and full history structure\n const postHistory = ctx.robota.getHistory();\n const historyStructure = postHistory.map((msg) => {\n const hasToolCalls =\n 'toolCalls' in msg && Array.isArray(msg.toolCalls) && msg.toolCalls.length > 0;\n const toolCallNames = hasToolCalls\n ? (msg.toolCalls as Array<{ function: { name: string } }>).map((tc) => tc.function.name)\n : [];\n return {\n role: msg.role,\n contentLength: typeof msg.content === 'string' ? msg.content.length : 0,\n hasToolCalls,\n toolCallNames,\n ...(msg.metadata ? { metadata: msg.metadata } : {}),\n };\n });\n ctx.log('assistant', {\n content: response,\n historyLength: postHistory.length,\n estimatedChars: JSON.stringify(postHistory).length,\n history: postHistory,\n historyStructure,\n });\n\n // Update token usage from the latest assistant message metadata\n ctx.contextTracker.updateFromHistory(postHistory);\n\n const ctxState = ctx.contextTracker.getContextState();\n ctx.onContextUpdate?.(ctxState);\n ctx.log('context', {\n maxTokens: ctxState.maxTokens,\n usedTokens: ctxState.usedTokens,\n usedPercentage: ctxState.usedPercentage,\n remainingPercentage: ctxState.remainingPercentage,\n });\n\n // Fire Stop hook after AI response is complete (informational, fire and forget)\n runHooks(\n ctx.hooks as THooksConfig | undefined,\n 'Stop',\n {\n session_id: ctx.sessionId,\n cwd: ctx.cwd,\n hook_event_name: 'Stop',\n response: response.substring(0, 500),\n last_assistant_message: response,\n stop_hook_active: false,\n ...(ctx.permissionMode !== undefined && { permission_mode: ctx.permissionMode }),\n ...(ctx.transcriptPath !== undefined && { transcript_path: ctx.transcriptPath }),\n env: {\n CLAUDE_PROJECT_DIR: ctx.cwd,\n CLAUDE_SESSION_ID: ctx.sessionId,\n },\n },\n ctx.hookTypeExecutors,\n ).catch(() => {});\n\n if (ctx.getSessionStore()) {\n ctx.persistSession();\n }\n\n return response;\n}\n","import { TRUST_TO_MODE } from '@robota-sdk/agent-core';\n\nimport { SessionBase } from './session-base.js';\nimport {\n buildPermissionEnforcer,\n buildRobota,\n buildSessionTrackers,\n} from './session-components.js';\nimport { compact, persistSession } from './session-history-ops.js';\nimport {\n configureProvider,\n fireSessionEndHook,\n fireSessionStartHook,\n} from './session-lifecycle.js';\nimport { executeRun } from './session-run.js';\n\nimport type { CompactionOrchestrator } from './compaction-orchestrator.js';\nimport type { ContextWindowTracker } from './context-window-tracker.js';\nimport type { PermissionEnforcer } from './permission-enforcer.js';\nimport type {\n TPermissionHandler,\n TPermissionResult,\n ITerminalOutput,\n ISpinner,\n} from './permission-types.js';\nimport type { ISessionLogger, TSessionLogData } from './session-logger.js';\nimport type { IRunContext } from './session-run.js';\nimport type { ISessionStore } from './session-store.js';\nimport type {\n ICompactEvent,\n ISessionOptions,\n ISessionShutdownOptions,\n TCompactTrigger,\n} from './session-types.js';\nimport type {\n IAIProvider,\n IContextWindowState,\n IToolSchema,\n TPermissionMode,\n IHookTypeExecutor,\n} from '@robota-sdk/agent-core';\nimport type { Robota } from '@robota-sdk/agent-core';\n\nexport type {\n ICompactEvent,\n TPermissionHandler,\n TPermissionResult,\n ITerminalOutput,\n ISpinner,\n ISessionOptions,\n ISessionShutdownOptions,\n TCompactTrigger,\n};\nexport type { TAutoCompactThreshold } from './context-window-tracker.js';\n\nconst ID_RADIX = 36;\nconst ID_RANDOM_LENGTH = 9;\n\n/** Wraps a Robota agent with project context, permission state, and optional persistence. */\nexport class Session extends SessionBase {\n protected readonly robota: Robota;\n protected readonly permissionEnforcer: PermissionEnforcer;\n protected readonly contextTracker: ContextWindowTracker;\n protected permissionMode: TPermissionMode;\n protected readonly sessionId: string;\n protected readonly aiProvider: IAIProvider;\n protected readonly toolSchemas: IToolSchema[];\n protected readonly model: string;\n protected systemMessage: string;\n protected messageCount = 0;\n protected abortController: AbortController | null = null;\n private readonly terminal: ITerminalOutput;\n private readonly sessionStore?: ISessionStore;\n private readonly cwd: string;\n private readonly hooks?: Record<string, unknown>;\n private readonly hookTypeExecutors?: IHookTypeExecutor[];\n private readonly onTextDeltaCallback?: (delta: string) => void;\n private readonly onContextUpdateCallback?: (state: IContextWindowState) => void;\n private readonly onToolExecutionCallback?: ISessionOptions['onToolExecution'];\n private readonly onCompactCallback?: (summary: string) => void;\n private readonly onCompactEventCallback?: ISessionOptions['onCompactEvent'];\n private readonly sessionLogger?: ISessionLogger;\n private readonly maxTurns?: number;\n private readonly compactionOrchestrator: CompactionOrchestrator;\n private shutdownPromise: Promise<void> | null = null;\n /** Stdout collected from SessionStart hooks, injected on first run(). */\n private sessionStartStdout = '';\n /** Absolute path to the session transcript file, if file-backed storage is active. */\n private readonly transcriptPath: string | undefined;\n\n constructor(options: ISessionOptions) {\n super();\n const { tools, provider, systemMessage } = options;\n\n this.terminal = options.terminal;\n this.sessionStore = options.sessionStore;\n this.systemMessage = systemMessage;\n this.toolSchemas = tools.map((tool) => tool.schema);\n this.cwd = process.cwd();\n this.sessionLogger = options.sessionLogger;\n this.hooks = options.hooks;\n this.hookTypeExecutors = options.hookTypeExecutors;\n this.onTextDeltaCallback = options.onTextDelta;\n this.onContextUpdateCallback = options.onContextUpdate;\n this.onToolExecutionCallback = options.onToolExecution;\n this.onCompactCallback = options.onCompact;\n this.onCompactEventCallback = options.onCompactEvent;\n this.maxTurns = options.maxTurns;\n this.model = options.model ?? 'claude-sonnet-4-5';\n this.sessionId =\n options.sessionId ??\n `session_${Date.now()}_${Math.random().toString(ID_RADIX).substr(2, ID_RANDOM_LENGTH)}`;\n this.permissionMode =\n options.permissionMode ??\n (options.defaultTrustLevel ? TRUST_TO_MODE[options.defaultTrustLevel] : undefined) ??\n 'default';\n this.transcriptPath = options.sessionStore?.getFilePath?.(this.sessionId);\n this.log('session_init', {\n cwd: this.cwd,\n systemPromptLength: systemMessage.length,\n systemPrompt: systemMessage,\n toolSchemas: this.toolSchemas,\n model: this.model,\n provider: provider.name,\n });\n this.aiProvider = provider;\n configureProvider(provider, options, (event, data) => this.log(event, data));\n this.permissionEnforcer = buildPermissionEnforcer(\n options,\n this.sessionId,\n this.cwd,\n () => this.permissionMode,\n this.transcriptPath,\n );\n const { contextTracker, compactionOrchestrator } = buildSessionTrackers(\n options,\n this.model,\n this.sessionId,\n this.cwd,\n );\n this.contextTracker = contextTracker;\n this.compactionOrchestrator = compactionOrchestrator;\n this.robota = buildRobota(\n options,\n this.permissionEnforcer,\n tools,\n provider,\n this.model,\n systemMessage,\n );\n fireSessionStartHook(\n this.sessionId,\n this.cwd,\n this.hooks,\n this.hookTypeExecutors,\n (stdout) => void (this.sessionStartStdout = stdout),\n this.permissionMode,\n this.transcriptPath,\n );\n }\n\n async run(message: string, rawInput?: string): Promise<string> {\n this.abortController = new AbortController();\n const { signal } = this.abortController;\n try {\n const response = await executeRun(message, rawInput, this.buildRunContext(), signal);\n this.messageCount += 1;\n return response;\n } finally {\n this.abortController = null;\n }\n }\n\n private log(event: string, data: TSessionLogData): void {\n this.sessionLogger?.log(this.sessionId, event, data);\n }\n\n private persistSessionInternal(): void {\n if (!this.sessionStore) return;\n persistSession({\n sessionId: this.sessionId,\n cwd: this.cwd,\n systemPrompt: this.systemMessage,\n toolSchemas: this.toolSchemas,\n sessionStore: this.sessionStore,\n robota: this.robota,\n getFullHistory: () => this.getFullHistory(),\n });\n }\n\n /** Gracefully end the session and fire SessionEnd hooks once. */\n shutdown(options: ISessionShutdownOptions = {}): Promise<void> {\n if (this.shutdownPromise) return this.shutdownPromise;\n const reason = options.reason ?? 'other';\n this.shutdownPromise = (async () => {\n this.abort();\n this.log('session_shutdown', { reason });\n this.persistSessionInternal();\n await fireSessionEndHook(\n this.sessionId,\n this.cwd,\n reason,\n this.hooks,\n this.hookTypeExecutors,\n this.permissionMode,\n this.transcriptPath,\n );\n })();\n return this.shutdownPromise;\n }\n\n async compact(instructions?: string, trigger: TCompactTrigger = 'manual'): Promise<void> {\n await compact(instructions, {\n sessionId: this.sessionId,\n cwd: this.cwd,\n systemMessage: this.systemMessage,\n robota: this.robota,\n aiProvider: this.aiProvider,\n compactionOrchestrator: this.compactionOrchestrator,\n contextTracker: this.contextTracker,\n hooks: this.hooks,\n hookTypeExecutors: this.hookTypeExecutors,\n onCompactCallback: this.onCompactCallback,\n onCompactEventCallback: this.onCompactEventCallback,\n trigger,\n log: (event, data) => this.log(event, data),\n });\n }\n\n private buildRunContext(): IRunContext {\n return {\n sessionId: this.sessionId,\n cwd: this.cwd,\n model: this.model,\n robota: this.robota,\n aiProvider: this.aiProvider,\n contextTracker: this.contextTracker,\n hooks: this.hooks,\n hookTypeExecutors: this.hookTypeExecutors,\n sessionStartStdout: this.sessionStartStdout,\n log: (event: string, data: TSessionLogData) => this.log(event, data),\n compact: () => this.compact(undefined, 'auto'),\n persistSession: () => this.persistSessionInternal(),\n getSessionStore: () => !!this.sessionStore,\n clearSessionStartStdout: () => void (this.sessionStartStdout = ''),\n permissionMode: this.permissionMode,\n transcriptPath: this.transcriptPath,\n maxTurns: this.maxTurns,\n onTextDelta: this.onTextDeltaCallback,\n onContextUpdate: this.onContextUpdateCallback,\n onToolExecution: this.onToolExecutionCallback,\n knownToolNames: this.toolSchemas.map((tool) => tool.name),\n };\n }\n}\n","/**\n * Session Logger — pluggable logging interface for session events.\n *\n * ISessionLogger defines the contract. FileSessionLogger is the default\n * implementation that writes JSONL to disk. Consumers can implement their\n * own (e.g., remote, database, silent) and inject via Session constructor.\n */\n\nimport { createHash } from 'node:crypto';\nimport { mkdirSync, appendFileSync, existsSync, writeFileSync } from 'node:fs';\nimport { join } from 'node:path';\n\n/** Session log event data — extensible record of event metadata. */\nexport type TSessionLogValue = string | number | boolean | object | null | undefined;\nexport type TSessionLogData = Record<string, TSessionLogValue>;\n\nexport interface IExternalPayloadReference {\n kind: 'external-payload';\n encoding: 'json';\n sha256: string;\n byteLength: number;\n relativePath: string;\n}\n\nexport interface IFileSessionLoggerOptions {\n externalPayloadThresholdBytes?: number;\n redactedValue?: string;\n}\n\nconst BYTES_PER_KIB = 1024;\nconst DEFAULT_EXTERNAL_PAYLOAD_THRESHOLD_KIB = 32;\nconst DEFAULT_EXTERNAL_PAYLOAD_THRESHOLD_BYTES =\n DEFAULT_EXTERNAL_PAYLOAD_THRESHOLD_KIB * BYTES_PER_KIB;\nconst DEFAULT_REDACTED_VALUE = '[REDACTED]';\nconst SENSITIVE_KEY_PATTERN =\n /^(api[-_]?key|authorization|access[-_]?token|refresh[-_]?token|secret|password|x[-_]?api[-_]?key)$/i;\n\n/**\n * Session logger interface — injected into Session for pluggable logging.\n *\n * Implementations decide where and how to persist session events.\n * The Session class calls log() for every significant action.\n */\nexport interface ISessionLogger {\n /** Log a session event with structured data. */\n log(sessionId: string, event: string, data: TSessionLogData): void;\n}\n\n/**\n * File-based session logger — writes JSONL to {logDir}/{sessionId}.jsonl.\n *\n * This is the default implementation used by the CLI.\n * Each line is a self-contained JSON object with timestamp, sessionId, event, and data.\n */\nexport class FileSessionLogger implements ISessionLogger {\n private readonly logDir: string;\n private readonly options: Required<IFileSessionLoggerOptions>;\n\n constructor(logDir: string, options: IFileSessionLoggerOptions = {}) {\n this.logDir = logDir;\n this.options = {\n externalPayloadThresholdBytes:\n options.externalPayloadThresholdBytes ?? DEFAULT_EXTERNAL_PAYLOAD_THRESHOLD_BYTES,\n redactedValue: options.redactedValue ?? DEFAULT_REDACTED_VALUE,\n };\n try {\n mkdirSync(logDir, { recursive: true });\n } catch {\n // Best-effort: logging disabled if directory cannot be created\n }\n }\n\n log(sessionId: string, event: string, data: TSessionLogData): void {\n try {\n const normalizedData = normalizeLogData(sessionId, this.logDir, data, this.options);\n const entry = JSON.stringify({\n timestamp: new Date().toISOString(),\n sessionId,\n event,\n ...normalizedData,\n });\n const logFile = join(this.logDir, `${sessionId}.jsonl`);\n appendFileSync(logFile, entry + '\\n');\n } catch {\n // Logging failure must never break the session\n }\n }\n}\n\nfunction normalizeLogData(\n sessionId: string,\n logDir: string,\n data: TSessionLogData,\n options: Required<IFileSessionLoggerOptions>,\n): TSessionLogData {\n const normalized: TSessionLogData = {};\n for (const [key, value] of Object.entries(data)) {\n normalized[key] = normalizeLogValue(sessionId, logDir, key, value, options);\n }\n return normalized;\n}\n\nfunction normalizeLogValue(\n sessionId: string,\n logDir: string,\n key: string,\n value: TSessionLogValue,\n options: Required<IFileSessionLoggerOptions>,\n): TSessionLogValue {\n if (SENSITIVE_KEY_PATTERN.test(key)) {\n return options.redactedValue;\n }\n if (\n value === null ||\n value === undefined ||\n typeof value === 'string' ||\n typeof value === 'number'\n ) {\n return maybeExternalizePayload(sessionId, logDir, value, options);\n }\n if (typeof value === 'boolean') {\n return value;\n }\n if (value instanceof Date) {\n return value.toISOString();\n }\n if (Array.isArray(value)) {\n const normalizedArray = value.map((item) =>\n normalizeLogValue(sessionId, logDir, key, item as TSessionLogValue, options),\n );\n return maybeExternalizePayload(sessionId, logDir, normalizedArray, options);\n }\n if (typeof value === 'object') {\n const record = value as Record<string, TSessionLogValue>;\n const normalizedRecord: Record<string, TSessionLogValue> = {};\n for (const [childKey, childValue] of Object.entries(record)) {\n normalizedRecord[childKey] = normalizeLogValue(\n sessionId,\n logDir,\n childKey,\n childValue,\n options,\n );\n }\n return maybeExternalizePayload(sessionId, logDir, normalizedRecord, options);\n }\n return String(value);\n}\n\nfunction maybeExternalizePayload(\n sessionId: string,\n logDir: string,\n value: TSessionLogValue,\n options: Required<IFileSessionLoggerOptions>,\n): TSessionLogValue {\n const serialized = JSON.stringify(value);\n if (serialized === undefined) {\n return value;\n }\n const byteLength = Buffer.byteLength(serialized);\n if (byteLength <= options.externalPayloadThresholdBytes) {\n return value;\n }\n\n const sha256 = createHash('sha256').update(serialized).digest('hex');\n const payloadDirName = `${sessionId}.payloads`;\n const payloadFileName = `${sha256}.json`;\n const relativePath = join(payloadDirName, payloadFileName);\n const payloadDir = join(logDir, payloadDirName);\n const payloadPath = join(logDir, relativePath);\n mkdirSync(payloadDir, { recursive: true });\n if (!existsSync(payloadPath)) {\n writeFileSync(payloadPath, serialized, 'utf-8');\n }\n return {\n kind: 'external-payload',\n encoding: 'json',\n sha256,\n byteLength,\n relativePath,\n } satisfies IExternalPayloadReference;\n}\n\n/** No-op logger — used when logging is disabled. */\nexport class SilentSessionLogger implements ISessionLogger {\n log(): void {\n // intentionally empty\n }\n}\n","import type { ISessionLogEntry } from './session-log-replay.js';\nimport type { TUniversalValue } from '@robota-sdk/agent-core';\n\nexport interface ISessionReplayValidationIssue {\n code:\n | 'PROVIDER_RESPONSE_RAW_MISSING'\n | 'PROVIDER_NATIVE_RAW_PAYLOAD_MISSING'\n | 'PROVIDER_RESPONSE_NORMALIZED_MISSING'\n | 'TOOL_RESULT_MISSING'\n | 'PAYLOAD_REFERENCE_INVALID';\n message: string;\n eventIndex?: number;\n executionId?: string;\n round?: number;\n toolCallId?: string;\n}\n\nexport interface ISessionReplayValidationResult {\n ok: boolean;\n issues: ISessionReplayValidationIssue[];\n}\n\nexport function validateSessionReplayLogEntries(\n entries: readonly ISessionLogEntry[],\n): ISessionReplayValidationResult {\n const issues: ISessionReplayValidationIssue[] = [];\n const providerEvents = createProviderReplayEventIndex();\n const toolEvents = createToolReplayEventIndex();\n\n entries.forEach((entry, index) => {\n collectPayloadReferenceIssues(entry, index, issues);\n collectProviderReplayEvent(providerEvents, entry, index);\n collectToolReplayEvent(toolEvents, entry, index);\n });\n\n appendProviderReplayIssues(providerEvents, issues);\n appendToolReplayIssues(toolEvents, issues);\n\n return { ok: issues.length === 0, issues };\n}\n\ninterface IProviderReplayRequest {\n executionId: string;\n round: number;\n index: number;\n}\n\ninterface IProviderReplayEventIndex {\n requests: Map<string, IProviderReplayRequest>;\n nativeRawPayloads: Set<string>;\n rawResponses: Set<string>;\n normalizedResponses: Set<string>;\n}\n\ninterface IToolReplayRequest {\n executionId: string;\n toolCallId: string;\n index: number;\n}\n\ninterface IToolReplayEventIndex {\n requests: Map<string, IToolReplayRequest>;\n results: Set<string>;\n}\n\nfunction createProviderReplayEventIndex(): IProviderReplayEventIndex {\n return {\n requests: new Map<string, IProviderReplayRequest>(),\n nativeRawPayloads: new Set<string>(),\n rawResponses: new Set<string>(),\n normalizedResponses: new Set<string>(),\n };\n}\n\nfunction createToolReplayEventIndex(): IToolReplayEventIndex {\n return {\n requests: new Map<string, IToolReplayRequest>(),\n results: new Set<string>(),\n };\n}\n\nfunction collectProviderReplayEvent(\n events: IProviderReplayEventIndex,\n entry: ISessionLogEntry,\n index: number,\n): void {\n const key = providerKey(entry);\n if (!key) return;\n if (entry.event === 'provider_request') {\n events.requests.set(key.key, {\n executionId: key.executionId,\n round: key.round,\n index,\n });\n }\n if (entry.event === 'provider_response_raw') {\n events.rawResponses.add(key.key);\n }\n if (\n entry.event === 'provider_native_raw_payload' &&\n (entry.payloadKind === 'response' || entry.payloadKind === 'stream_event')\n ) {\n events.nativeRawPayloads.add(key.key);\n }\n if (entry.event === 'provider_response_normalized') {\n events.normalizedResponses.add(key.key);\n }\n}\n\nfunction collectToolReplayEvent(\n events: IToolReplayEventIndex,\n entry: ISessionLogEntry,\n index: number,\n): void {\n const key = toolKey(entry);\n if (!key) return;\n if (entry.event === 'tool_execution_request') {\n events.requests.set(key.key, {\n executionId: key.executionId,\n toolCallId: key.toolCallId,\n index,\n });\n }\n if (entry.event === 'tool_execution_result') {\n events.results.add(key.key);\n }\n}\n\nfunction appendProviderReplayIssues(\n events: IProviderReplayEventIndex,\n issues: ISessionReplayValidationIssue[],\n): void {\n for (const [key, request] of events.requests) {\n if (!events.nativeRawPayloads.has(key)) {\n issues.push({\n code: 'PROVIDER_NATIVE_RAW_PAYLOAD_MISSING',\n message: `Provider request ${key} has no provider-native raw response or stream payload event.`,\n eventIndex: request.index,\n executionId: request.executionId,\n round: request.round,\n });\n }\n if (!events.rawResponses.has(key)) {\n issues.push({\n code: 'PROVIDER_RESPONSE_RAW_MISSING',\n message: `Provider request ${key} has no raw response event.`,\n eventIndex: request.index,\n executionId: request.executionId,\n round: request.round,\n });\n }\n if (!events.normalizedResponses.has(key)) {\n issues.push({\n code: 'PROVIDER_RESPONSE_NORMALIZED_MISSING',\n message: `Provider request ${key} has no normalized response event.`,\n eventIndex: request.index,\n executionId: request.executionId,\n round: request.round,\n });\n }\n }\n}\n\nfunction appendToolReplayIssues(\n events: IToolReplayEventIndex,\n issues: ISessionReplayValidationIssue[],\n): void {\n for (const [key, request] of events.requests) {\n if (!events.results.has(key)) {\n issues.push({\n code: 'TOOL_RESULT_MISSING',\n message: `Tool request ${key} has no terminal result event.`,\n eventIndex: request.index,\n executionId: request.executionId,\n toolCallId: request.toolCallId,\n });\n }\n }\n}\n\nfunction providerKey(\n entry: ISessionLogEntry,\n): { key: string; executionId: string; round: number } | undefined {\n if (typeof entry.executionId !== 'string') return undefined;\n const round = typeof entry.round === 'number' ? entry.round : Number(entry.round);\n if (!Number.isFinite(round)) return undefined;\n return { key: `${entry.executionId}:${round}`, executionId: entry.executionId, round };\n}\n\nfunction toolKey(\n entry: ISessionLogEntry,\n): { key: string; executionId: string; toolCallId: string } | undefined {\n if (typeof entry.executionId !== 'string') return undefined;\n const toolCallId =\n typeof entry.toolCallId === 'string'\n ? entry.toolCallId\n : typeof entry.toolExecutionId === 'string'\n ? entry.toolExecutionId\n : undefined;\n if (!toolCallId) return undefined;\n return { key: `${entry.executionId}:${toolCallId}`, executionId: entry.executionId, toolCallId };\n}\n\nfunction collectPayloadReferenceIssues(\n value: TUniversalValue,\n eventIndex: number,\n issues: ISessionReplayValidationIssue[],\n): void {\n if (Array.isArray(value)) {\n value.forEach((item) => collectPayloadReferenceIssues(item, eventIndex, issues));\n return;\n }\n if (!isRecord(value)) return;\n if (value.kind === 'external-payload') {\n if (\n value.encoding !== 'json' ||\n typeof value.sha256 !== 'string' ||\n typeof value.relativePath !== 'string' ||\n typeof value.byteLength !== 'number'\n ) {\n issues.push({\n code: 'PAYLOAD_REFERENCE_INVALID',\n message: 'External payload reference is missing required replay fields.',\n eventIndex,\n });\n }\n return;\n }\n Object.values(value).forEach((child) => collectPayloadReferenceIssues(child, eventIndex, issues));\n}\n\nfunction isRecord(value: TUniversalValue): value is Record<string, TUniversalValue> {\n return typeof value === 'object' && value !== null && !Array.isArray(value);\n}\n","import { existsSync, readFileSync } from 'node:fs';\n\nimport { messageToHistoryEntry } from '@robota-sdk/agent-core';\n\nimport type { IHistoryEntry, TUniversalMessage, TUniversalValue } from '@robota-sdk/agent-core';\n\nexport interface ISessionLogEntry extends Record<string, TUniversalValue> {\n timestamp: string;\n sessionId: string;\n event: string;\n}\n\nexport interface ISessionReplayRecord {\n sessionId: string | undefined;\n cwd: string | undefined;\n createdAt: string | undefined;\n updatedAt: string | undefined;\n messages: TUniversalMessage[];\n history: IHistoryEntry[];\n backgroundTaskEvents: object[];\n backgroundJobGroupEvents: object[];\n memoryEvents: object[];\n}\n\nexport { validateSessionReplayLogEntries } from './session-log-validation.js';\nexport type {\n ISessionReplayValidationIssue,\n ISessionReplayValidationResult,\n} from './session-log-validation.js';\n\nexport function loadSessionLogEntries(logFile: string): ISessionLogEntry[] {\n if (!existsSync(logFile)) {\n return [];\n }\n return readFileSync(logFile, 'utf-8')\n .split('\\n')\n .map((line) => line.trim())\n .filter((line) => line.length > 0)\n .map((line) => JSON.parse(line) as ISessionLogEntry);\n}\n\nexport function replaySessionLogEntries(\n entries: readonly ISessionLogEntry[],\n): ISessionReplayRecord {\n const messages: TUniversalMessage[] = [];\n const history: IHistoryEntry[] = [];\n const auxiliaryEvents: IAuxiliaryReplayEvents = {\n backgroundTaskEvents: [],\n backgroundJobGroupEvents: [],\n memoryEvents: [],\n };\n let sessionId: string | undefined;\n let cwd: string | undefined;\n let createdAt: string | undefined;\n let updatedAt: string | undefined;\n\n for (const entry of entries) {\n sessionId = sessionId ?? entry.sessionId;\n createdAt = createdAt ?? entry.timestamp;\n updatedAt = entry.timestamp;\n\n if (entry.event === 'session_init') {\n cwd = typeof entry.cwd === 'string' ? entry.cwd : cwd;\n }\n\n if (entry.event === 'history_mutation' && entry.mutation === 'append_message') {\n const message = normalizeLogMessage(entry.message);\n if (message) {\n messages.push(message);\n history.push(messageToHistoryEntry(message));\n }\n }\n\n collectAuxiliaryReplayEvent(entry, auxiliaryEvents);\n }\n\n return {\n sessionId,\n cwd,\n createdAt,\n updatedAt,\n messages,\n history,\n backgroundTaskEvents: auxiliaryEvents.backgroundTaskEvents,\n backgroundJobGroupEvents: auxiliaryEvents.backgroundJobGroupEvents,\n memoryEvents: auxiliaryEvents.memoryEvents,\n };\n}\n\ninterface IAuxiliaryReplayEvents {\n backgroundTaskEvents: object[];\n backgroundJobGroupEvents: object[];\n memoryEvents: object[];\n}\n\nfunction collectAuxiliaryReplayEvent(\n entry: ISessionLogEntry,\n auxiliaryEvents: IAuxiliaryReplayEvents,\n): void {\n if (entry.event === 'background_task_event') {\n pushObjectPayload(auxiliaryEvents.backgroundTaskEvents, entry, 'backgroundEvent', 'data');\n return;\n }\n if (entry.event === 'background_job_group_event') {\n pushObjectPayload(\n auxiliaryEvents.backgroundJobGroupEvents,\n entry,\n 'backgroundJobGroupEvent',\n 'data',\n );\n return;\n }\n if (entry.event === 'memory_event') {\n pushObjectPayload(auxiliaryEvents.memoryEvents, entry, 'memoryEvent', 'data');\n }\n}\n\nfunction normalizeLogMessage(value: TUniversalValue): TUniversalMessage | undefined {\n if (!isRecord(value)) return undefined;\n const role = value.role;\n if (role !== 'user' && role !== 'assistant' && role !== 'system' && role !== 'tool') {\n return undefined;\n }\n const id = typeof value.id === 'string' ? value.id : `${role}-${Date.now()}`;\n const timestamp =\n value.timestamp instanceof Date\n ? value.timestamp\n : new Date(typeof value.timestamp === 'string' ? value.timestamp : Date.now());\n return {\n ...value,\n id,\n role,\n timestamp,\n } as TUniversalMessage;\n}\n\nfunction isRecord(value: TUniversalValue): value is Record<string, TUniversalValue> {\n return typeof value === 'object' && value !== null && !Array.isArray(value);\n}\n\nfunction getObjectPayload(entry: ISessionLogEntry, key: string): object | undefined {\n const value = entry[key];\n if (\n typeof value !== 'object' ||\n value === null ||\n Array.isArray(value) ||\n value instanceof Date\n ) {\n return undefined;\n }\n return value;\n}\n\nfunction pushObjectPayload(\n target: object[],\n entry: ISessionLogEntry,\n primaryKey: string,\n fallbackKey: string,\n): void {\n const payload = getObjectPayload(entry, primaryKey) ?? getObjectPayload(entry, fallbackKey);\n if (payload) target.push(payload);\n}\n","/**\n * SessionStore — persists conversation sessions as JSON files.\n *\n * Sessions are stored at `~/.robota/sessions/{id}.json` by default.\n * Consumers can inject a project-local directory such as `.robota/sessions`.\n * The store directory is created on first write if it does not exist.\n */\n\nimport { readFileSync, writeFileSync, existsSync, mkdirSync, unlinkSync, readdirSync } from 'fs';\nimport { join } from 'path';\n\nimport type { IToolSchema } from '@robota-sdk/agent-core';\n\n/** A persisted session record */\nexport interface ISessionRecord {\n /** Unique session identifier */\n id: string;\n /** Optional human-readable session name */\n name?: string;\n /** Working directory when the session was created */\n cwd: string;\n /** ISO-8601 creation timestamp */\n createdAt: string;\n /** ISO-8601 last-updated timestamp */\n updatedAt: string;\n /** Conversation messages (opaque to the store) */\n messages: unknown[];\n /** Full UI timeline (chat + events) for rendering restoration */\n history?: unknown[];\n /** Exact system prompt used to create the session. */\n systemPrompt?: string;\n /** Tool schemas registered for the session. */\n toolSchemas?: IToolSchema[];\n /** Latest background task snapshots for resume/debugging. */\n backgroundTasks?: unknown[];\n /** Durable non-streaming background task events for resume/debugging. */\n backgroundTaskEvents?: unknown[];\n /** Latest background job group snapshots for resume/debugging. */\n backgroundJobGroups?: unknown[];\n /** Durable background job group events for resume/debugging. */\n backgroundJobGroupEvents?: unknown[];\n /** Durable skill activation events for resume/debugging. */\n skillActivationEvents?: unknown[];\n /** Durable automatic memory events for resume/debugging. */\n memoryEvents?: unknown[];\n /** Memory references used by the latest prompt turn. */\n usedMemoryReferences?: unknown[];\n /** SDK-owned context reference inventory for resume/debugging. */\n contextReferences?: unknown[];\n /** Provider sandbox snapshot identifier for workspace hydration on resume. */\n sandboxSnapshotId?: string;\n}\n\n/** Minimal persistence port consumed by Session. */\nexport interface ISessionStore {\n save(session: ISessionRecord): void;\n load(id: string): ISessionRecord | undefined;\n list(): ISessionRecord[];\n delete(id: string): void;\n /** Return the absolute file path for a session file, if the store is file-backed. */\n getFilePath?(id: string): string;\n}\n\n/**\n * Return the current user home directory.\n * Reads process.env.HOME at call time so tests can override it.\n */\nfunction getHomeDir(): string {\n return process.env.HOME ?? process.env.USERPROFILE ?? '/';\n}\n\n/**\n * Persistent session store backed by individual JSON files.\n *\n * Construct with a custom `baseDir` to redirect storage (useful in tests).\n */\nexport class SessionStore implements ISessionStore {\n private readonly baseDir: string;\n\n constructor(baseDir?: string) {\n this.baseDir = baseDir ?? join(getHomeDir(), '.robota', 'sessions');\n }\n\n /** Ensure the storage directory exists */\n private ensureDir(): void {\n if (!existsSync(this.baseDir)) {\n mkdirSync(this.baseDir, { recursive: true });\n }\n }\n\n /** Absolute path to a session's JSON file */\n private filePath(id: string): string {\n return join(this.baseDir, `${id}.json`);\n }\n\n /** Return the absolute file path for a session — implements ISessionStore.getFilePath */\n getFilePath(id: string): string {\n return this.filePath(id);\n }\n\n /**\n * Persist a session record to disk.\n * Creates the storage directory if needed.\n */\n save(session: ISessionRecord): void {\n this.ensureDir();\n writeFileSync(this.filePath(session.id), JSON.stringify(session, null, 2), 'utf-8');\n }\n\n /**\n * Load a session by its ID.\n * Returns `undefined` when the session file does not exist.\n */\n load(id: string): ISessionRecord | undefined {\n const path = this.filePath(id);\n if (!existsSync(path)) {\n return undefined;\n }\n const raw = readFileSync(path, 'utf-8');\n return JSON.parse(raw) as ISessionRecord;\n }\n\n /**\n * List all persisted sessions, sorted by `updatedAt` descending (most recent first).\n */\n list(): ISessionRecord[] {\n if (!existsSync(this.baseDir)) {\n return [];\n }\n\n const files = readdirSync(this.baseDir).filter((f) => f.endsWith('.json'));\n const sessions: ISessionRecord[] = [];\n\n for (const file of files) {\n try {\n const raw = readFileSync(join(this.baseDir, file), 'utf-8');\n const record = JSON.parse(raw) as ISessionRecord;\n sessions.push(record);\n } catch {\n // Skip malformed files\n }\n }\n\n return sessions.sort(\n (a, b) => new Date(b.updatedAt).getTime() - new Date(a.updatedAt).getTime(),\n );\n }\n\n /**\n * Delete a session by its ID.\n * No-ops silently if the session does not exist.\n */\n delete(id: string): void {\n const path = this.filePath(id);\n if (existsSync(path)) {\n unlinkSync(path);\n }\n }\n}\n"],"mappings":"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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@robota-sdk/agent-session",
3
- "version": "3.0.0-beta.65",
3
+ "version": "3.0.0-beta.66",
4
4
  "description": "Session and chat management for Robota SDK - multi-session support with independent workspaces",
5
5
  "type": "module",
6
6
  "main": "dist/node/index.js",
@@ -60,7 +60,7 @@
60
60
  "node": ">=18.0.0"
61
61
  },
62
62
  "dependencies": {
63
- "@robota-sdk/agent-core": "3.0.0-beta.65"
63
+ "@robota-sdk/agent-core": "3.0.0-beta.66"
64
64
  },
65
65
  "peerDependencies": {},
66
66
  "devDependencies": {
@@ -69,7 +69,7 @@
69
69
  "tsdown": "^0.22.0",
70
70
  "typescript": "^5.3.3",
71
71
  "vitest": "^1.6.1",
72
- "@robota-sdk/agent-core": "3.0.0-beta.65"
72
+ "@robota-sdk/agent-core": "3.0.0-beta.66"
73
73
  },
74
74
  "publishConfig": {
75
75
  "access": "public",