@robota-sdk/agent-session 3.0.0-beta.76 → 3.0.0-beta.78
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 +17 -1
- package/LICENSE +661 -21
- package/README.md +17 -12
- package/dist/node/index.cjs +5 -5
- package/dist/node/index.d.ts +101 -12
- package/dist/node/index.d.ts.map +1 -1
- package/dist/node/index.js +5 -5
- package/dist/node/index.js.map +1 -1
- package/package.json +5 -4
package/README.md
CHANGED
|
@@ -12,6 +12,11 @@ npm install @robota-sdk/agent-session @robota-sdk/agent-core
|
|
|
12
12
|
|
|
13
13
|
```typescript
|
|
14
14
|
import { Session } from '@robota-sdk/agent-session';
|
|
15
|
+
import type { IAIProvider, IToolWithEventService, ITerminalOutput } from '@robota-sdk/agent-core';
|
|
16
|
+
|
|
17
|
+
declare const tools: IToolWithEventService[];
|
|
18
|
+
declare const provider: IAIProvider;
|
|
19
|
+
declare const terminal: ITerminalOutput;
|
|
15
20
|
|
|
16
21
|
const session = new Session({
|
|
17
22
|
tools,
|
|
@@ -34,17 +39,17 @@ await session.compact('Focus on the API changes');
|
|
|
34
39
|
|
|
35
40
|
## Features
|
|
36
41
|
|
|
37
|
-
| Feature | Description
|
|
38
|
-
| -------------------------- |
|
|
39
|
-
| **Permission enforcement** | Tool calls gated by 3-step policy (deny list, allow list, mode policy)
|
|
40
|
-
| **Hook execution** | PreToolUse, PostToolUse, PreCompact, PostCompact, SessionStart, Stop
|
|
41
|
-
| **Context tracking** | Effective token usage from the shared core estimator, configurable auto-compact threshold (default ~83.5%)
|
|
42
|
-
| **Compaction** | LLM-generated conversation summary to free context space
|
|
43
|
-
| **Persistence** | `SessionStore` for JSON file-based session save/load
|
|
44
|
-
| **Abort** | Cancel via `session.abort()` — propagates AbortSignal to `robota.run()`, throws `AbortError` to caller
|
|
45
|
-
| **Session logging** | `FileSessionLogger` writes JSONL event logs
|
|
46
|
-
| **Replay events** | Provider/tool execution boundary events are forwarded from core into append-only session logs
|
|
47
|
-
| **Provider capabilities** | Generic native web capability setup is requested through the provider contract, not provider-name branches
|
|
42
|
+
| Feature | Description |
|
|
43
|
+
| -------------------------- | ---------------------------------------------------------------------------------------------------------------------------------- |
|
|
44
|
+
| **Permission enforcement** | Tool calls gated by 3-step policy (deny list, allow list, mode policy) |
|
|
45
|
+
| **Hook execution** | PreToolUse, PostToolUse, PreCompact, PostCompact, SessionStart, Stop |
|
|
46
|
+
| **Context tracking** | Effective token usage from the shared core estimator, configurable auto-compact threshold (default ~83.5%) |
|
|
47
|
+
| **Compaction** | LLM-generated conversation summary to free context space; an invalid summary throws `CompactionError` and leaves history untouched |
|
|
48
|
+
| **Persistence** | `SessionStore` for JSON file-based session save/load (atomic temp-file + rename writes) |
|
|
49
|
+
| **Abort** | Cancel via `session.abort()` — propagates AbortSignal to `robota.run()`, throws `AbortError` to caller |
|
|
50
|
+
| **Session logging** | `FileSessionLogger` writes JSONL event logs |
|
|
51
|
+
| **Replay events** | Provider/tool execution boundary events are forwarded from core into append-only session logs |
|
|
52
|
+
| **Provider capabilities** | Generic native web capability setup is requested through the provider contract, not provider-name branches |
|
|
48
53
|
|
|
49
54
|
## Key Methods
|
|
50
55
|
|
|
@@ -139,4 +144,4 @@ Most users should use `createSession()` from `@robota-sdk/agent-framework` inste
|
|
|
139
144
|
|
|
140
145
|
## License
|
|
141
146
|
|
|
142
|
-
|
|
147
|
+
Robota is dual-licensed under the [GNU AGPL-3.0](../../LICENSE) or a [commercial license](../../COMMERCIAL.md). See [LICENSING.md](../../LICENSING.md).
|
package/dist/node/index.cjs
CHANGED
|
@@ -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");var o=class{getPermissionMode(){return this.permissionMode}setPermissionMode(e){this.permissionMode=e}getActivePresetId(){return this.activePresetId}setActivePresetId(e){this.activePresetId=e}getParallelSubagentsEnabled(){return this.parallelSubagentsEnabled}setParallelSubagentsEnabled(e){this.parallelSubagentsEnabled=e}getSessionId(){return this.sessionId}getSystemMessage(){return this.systemMessage}updateSystemMessage(e){this.systemMessage=e,this.robota.
|
|
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}getActivePresetId(){return this.activePresetId}setActivePresetId(e){this.activePresetId=e}getParallelSubagentsEnabled(){return this.parallelSubagentsEnabled}setParallelSubagentsEnabled(e){this.parallelSubagentsEnabled=e}getSessionId(){return this.sessionId}getSystemMessage(){return this.systemMessage}updateSystemMessage(e){this.systemMessage=e,this.robota.updateSystemPrompt(e)}async applyModelOptions(e){await this.robota.ensureReady();let t=e.model??this.model;this.robota.setModel({provider:this.aiProvider.name,model:t,...e.effort!==void 0&&{effort:e.effort},...e.temperature!==void 0&&{temperature:e.temperature},...e.maxOutputTokens!==void 0&&{maxTokens:e.maxOutputTokens}}),this.model=t}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()}syncContextFromHistory(){this.contextTracker.updateFromHistory(this.robota.getHistory())}getAutoCompactThreshold(){return this.contextTracker.getAutoCompactThreshold()}setAutoCompactThreshold(e){this.contextTracker.setAutoCompactThreshold(e)}getHistory(){return this.robota.getHistory()}getFullHistory(){return this.robota.getFullHistory()}getSessionTokenUsage(){let e=0,t=0,n=!1;for(let r of this.getFullHistory()){if(r.category!==`event`||r.type!==`usage-summary`)continue;let i=r.data;e+=i?.promptTokens??0,t+=i?.completionTokens??0,n=!0}return n?{inputTokens:e,outputTokens:t}:void 0}getModelId(){return this.model}addHistoryEntry(e){this.robota.addHistoryEntry(e)}injectMessage(e,t,n){this.robota.injectMessage(e,t,n)}injectRawMessage(e){this.robota.injectRawMessage(e)}clearHistory(){this.robota.clearHistory(),this.contextTracker.reset()}},s=class extends Error{constructor(e){super(e),this.name=`CompactionError`}},c=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 c=this.buildCompactionPrompt(r,i),l=await n.chat([{id:(0,t.randomUUID)(),role:`user`,content:c,state:`complete`,timestamp:new Date}],{model:this.model});if(typeof l.content!=`string`||l.content.trim()===``)throw new s(`Compaction produced an invalid summary (provider=${n.name}, content type=${typeof l.content}); conversation history preserved untouched`);return l.content}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(`
|
|
2
2
|
`)].join(`
|
|
3
|
-
`)}};const
|
|
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/e.CONTEXT_ESTIMATE_CHARS_PER_TOKEN),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=
|
|
5
|
-
`)}catch{}}};function
|
|
6
|
-
`).map(e=>e.trim()).filter(e=>e.length>0).map(e=>JSON.parse(e)):[]}function
|
|
3
|
+
`)}};const l=.835;var u=class{contextUsedTokens=0;contextMaxTokens;autoCompactThreshold;constructor(t,n,r){this.contextMaxTokens=n??(0,e.getModelContextWindow)(t),this.autoCompactThreshold=d(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=d(e)}updateFromHistory(t){this.contextUsedTokens=(0,e.estimateContextTokensFromMessages)(t).usedTokens}reset(){this.contextUsedTokens=0}};function d(e){if(e===void 0)return l;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 f={success:!0,data:JSON.stringify({success:!1,output:``,error:`Permission denied. The user did not approve this action.`}),metadata:{}},p=(0,e.createLogger)(`ToolHookHelpers`);function m(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 h(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 g(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 _(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(e=>p.warn(`hook failed`,{error:e}))}var v=class{sessionId;cwd;getPermissionMode;config;terminal;permissionHandler;promptForApprovalFn;sessionLogger;onToolExecution;hookTypeExecutors;transcriptPath;sessionAllowedTools=new Set;onProjectAllowTool;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,this.onProjectAllowTool=e.onProjectAllowTool}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=h(t.sessionId,t.cwd,a,r,t.getPermissionMode(),t.transcriptPath),s=await g(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,executionId:i?.executionId}),f;t.onToolExecution?.({type:`start`,toolName:a,toolArgs:r,executionId:i?.executionId});let c=await n(r,i),l=m(c);l!==c&&typeof c.data==`string`&&t.terminal.writeLine(` ⚠ Output truncated: ${c.data.length.toLocaleString()} chars total — model sees first and last 15,000 chars`),t.onToolExecution?.({type:`end`,toolName:a,toolArgs:r,success:l.success,toolResultData:typeof l.data==`string`?l.data:JSON.stringify(l.data),executionId:i?.executionId});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}),_(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===`allow-project`?(this.sessionAllowedTools.add(t),this.onProjectAllowTool?.(t),!0):e}if(this.promptForApprovalFn){let e=await this.promptForApprovalFn(this.terminal,t,n);return e===`allow-session`?(this.sessionAllowedTools.add(t),!0):e===`allow-project`?(this.sessionAllowedTools.add(t),this.onProjectAllowTool?.(t),!0):e}return!1}log(e,t){this.sessionLogger?.log(this.sessionId,e,t)}};function y(e,t,n,r,i){return new v({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,onProjectAllowTool:e.onProjectAllowTool})}function b(e,t,n,r){return{contextTracker:new u(t,e.contextMaxTokens,e.autoCompactThreshold),compactionOrchestrator:new c({sessionId:n,cwd:r,model:t,hooks:e.hooks,compactInstructions:e.compactInstructions,hookTypeExecutors:e.hookTypeExecutors})}}function x(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,...t.effort!==void 0&&{effort:t.effort}},systemMessage:o,tools:s,logging:{enabled:!1},...t.providerTimeout!==void 0&&{timeout:t.providerTimeout},...t.responseFormat?{responseFormat:t.responseFormat}:{},...t.ask?{ask:t.ask}:{}})}const ee=(0,e.createLogger)(`SessionHistoryOps`);async function te(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(e=>ee.warn(`hook failed`,{error:e}));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 ne(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)}const re=(0,e.createLogger)(`SessionLifecycle`);function S(e,t,n){e.configureNativeWebTools?.({webSearch:!0}),`onServerToolUse`in e&&(e.onServerToolUse=(e,t)=>{n(`server_tool`,{tool:e,...t})})}function C(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(e=>re.warn(`SessionStart hook failed`,{error:e}))}async function w(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 T=`unknown_tool`;function E(e){return{knownToolNames:new Set(e.knownToolNames),unknownToolCallIds:new Set,...e.onToolExecution&&{onToolExecution:e.onToolExecution}}}function D(e,t,n){if(e.onToolExecution){if(t===`tool_execution_request`){O(e,n);return}t===`tool_execution_result`&&k(e,n)}}function O(e,t){let n=j(t.toolName),r=j(t.toolCallId);!n||!r||e.knownToolNames.has(n)||(e.unknownToolCallIds.add(r),e.onToolExecution?.({type:`start`,toolName:n,toolArgs:A(t.parameters)}))}function k(e,t){let n=j(t.toolName),r=j(t.toolCallId);if(!n||!r)return;let i=M(t.metadata);if(!(e.unknownToolCallIds.has(r)||i?.errorCode===T))return;e.unknownToolCallIds.delete(r);let a=j(t.error)??`Tool "${n}" is not registered.`;e.onToolExecution?.({type:`end`,toolName:n,success:!1,toolResultData:JSON.stringify({success:!1,error:a,errorCode:T,requestedTool:j(i?.requestedTool)??n,availableTools:N(i?.availableTools)})})}function A(e){let t=M(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 j(e){return typeof e==`string`&&e.length>0?e:void 0}function M(e){return typeof e==`object`&&e&&!Array.isArray(e)?e:void 0}function N(e){return Array.isArray(e)?e.filter(e=>typeof e==`string`):[]}const P=(0,e.createLogger)(`SessionRun`);async function F(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/e.CONTEXT_ESTIMATE_CHARS_PER_TOKEN),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=E({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),D(e,t,n),t===`assistant_message_committed`&&(r.contextTracker.updateFromHistory(r.robota.getHistory()),r.onContextUpdate?.(r.contextTracker.getContextState()))},...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(e=>P.warn(`hook failed`,{error:e})),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(e=>P.warn(`hook failed`,{error:e})),r.getSessionStore()&&r.persistSession(),d}var I=class extends o{robota;permissionEnforcer;contextTracker;permissionMode;activePresetId;parallelSubagentsEnabled;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.activePresetId=t.activePresetId??`default`,this.parallelSubagentsEnabled=t.enableParallelSubagents??!0,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=y(t,this.sessionId,this.cwd,()=>this.permissionMode,this.transcriptPath);let{contextTracker:a,compactionOrchestrator:o}=b(t,this.model,this.sessionId,this.cwd);this.contextTracker=a,this.compactionOrchestrator=o,this.robota=x(t,this.permissionEnforcer,n,r,this.model,i),C(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 F(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&&ne({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`,n=async(e,t)=>{try{await t()}catch(t){this.log(`session_shutdown_step_error`,{step:e,error:t instanceof Error?t.message:String(t)})}};return this.shutdownPromise=(async()=>{await n(`abort`,()=>this.abort()),this.log(`session_shutdown`,{reason:t}),await n(`persist`,()=>this.persistSessionInternal()),await n(`session-end-hook`,()=>w(this.sessionId,this.cwd,t,this.hooks,this.hookTypeExecutors,this.permissionMode,this.transcriptPath)),await n(`destroy-agent`,async()=>{await this.robota.destroy()})})(),this.shutdownPromise}swapProvider(e,t){this.robota.swapDefaultProvider(e,t),e.configureNativeWebTools?.({webSearch:!0}),`onServerToolUse`in e&&(e.onServerToolUse=(e,t)=>this.log(`server_tool`,{tool:e,...t})),this.aiProvider=e}async compact(e,t=`manual`){await te(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 L=/^(api[-_]?key|authorization|access[-_]?token|refresh[-_]?token|secret|password|x[-_]?api[-_]?key)$/i;var R=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=z(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 z(e,t,n,r){let i={};for(let[a,o]of Object.entries(n))i[a]=B(e,t,a,o,r);return i}function B(e,t,n,r,i){if(L.test(n))return i.redactedValue;if(r==null||typeof r==`string`||typeof r==`number`)return V(e,t,r,i);if(typeof r==`boolean`)return r;if(r instanceof Date)return r.toISOString();if(Array.isArray(r))return V(e,t,r.map(r=>B(e,t,n,r,i)),i);if(typeof r==`object`){let n=r,a={};for(let[r,o]of Object.entries(n))a[r]=B(e,t,r,o,i);return V(e,t,a,i)}return String(r)}function V(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 ie=class{log(){}};const H={sessionInit:`session_init`,sessionShutdown:`session_shutdown`,context:`context`,contextCompact:`context_compact`,error:`error`,historyMutation:`history_mutation`,providerRequest:`provider_request`,providerNativeRawPayload:`provider_native_raw_payload`,providerResponseRaw:`provider_response_raw`,providerResponseNormalized:`provider_response_normalized`,toolExecutionRequest:`tool_execution_request`,toolExecutionResult:`tool_execution_result`,user:`user`,preRun:`pre_run`,textDelta:`text_delta`,assistant:`assistant`,toolCall:`tool_call`,toolResult:`tool_result`,toolBlocked:`tool_blocked`,toolDenied:`tool_denied`,serverTool:`server_tool`};function U(e,t){return e.event===t}function W(e){let t=[],n=G(),r=K();return e.forEach((e,i)=>{X(e,i,t),q(n,e,i),J(r,e,i)}),Y(n,t),ae(r,t),{ok:t.length===0,issues:t}}function G(){return{requests:new Map,nativeRawPayloads:new Set,rawResponses:new Set,normalizedResponses:new Set}}function K(){return{requests:new Map,results:new Set}}function q(e,t,n){let r=oe(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 J(e,t,n){let r=se(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 Y(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 ae(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 oe(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 se(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(ce(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 ce(e){return typeof e==`object`&&!!e&&!Array.isArray(e)}function Z(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 le(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=de(l.message);t&&(n.push(t),r.push((0,e.messageToHistoryEntry)(t)))}ue(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 ue(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 de(e){if(!fe(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 fe(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 pe(){return process.env.HOME??process.env.USERPROFILE??`/`}var me=class{baseDir;constructor(e){this.baseDir=e??(0,a.join)(pe(),`.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();let t=this.filePath(e.id),n=`${t}.${process.pid}.tmp`;(0,i.writeFileSync)(n,JSON.stringify(e,null,2),`utf-8`);try{(0,i.renameSync)(n,t)}catch(e){throw(0,i.unlinkSync)(n),e}}load(e){let t=this.filePath(e);if((0,i.existsSync)(t))try{let e=(0,i.readFileSync)(t,`utf-8`);return JSON.parse(e)}catch{return}}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=l,exports.CompactionError=s,exports.CompactionOrchestrator=c,exports.ContextWindowTracker=u,exports.FileSessionLogger=R,exports.PermissionEnforcer=v,exports.SESSION_LOG_EVENT=H,exports.Session=I,exports.SessionStore=me,exports.SilentSessionLogger=ie,exports.isSessionLogEvent=U,exports.loadSessionLogEntries=Z,exports.replaySessionLogEntries=le,exports.validateSessionReplayLogEntries=W;
|
package/dist/node/index.d.ts
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
|
-
import { IAIProvider, IContextWindowState, IHistoryEntry, IHookTypeExecutor, ISpinner, ITerminalOutput, IToolSchema, IToolWithEventService, Robota, TModelEffort, TPermissionMode, TSessionEndReason, TToolArgs, TUniversalMessage, TUniversalValue } from "@robota-sdk/agent-core";
|
|
1
|
+
import { IAIProvider, IContextWindowState, IHistoryEntry, IHookTypeExecutor, ISpinner, ITerminalOutput, IToolSchema, IToolWithEventService, IUserInteraction, Robota, TModelEffort, TPermissionMode, TSessionEndReason, TToolArgs, TUniversalMessage, TUniversalValue } from "@robota-sdk/agent-core";
|
|
2
|
+
import { ICompactEvent, TCompactTrigger } from "@robota-sdk/agent-interface-transport";
|
|
2
3
|
|
|
3
4
|
//#region src/context-window-tracker.d.ts
|
|
4
5
|
/** Auto-compact when context usage reaches this fraction */
|
|
@@ -192,7 +193,14 @@ declare abstract class SessionBase {
|
|
|
192
193
|
setParallelSubagentsEnabled(enabled: boolean): void;
|
|
193
194
|
getSessionId(): string;
|
|
194
195
|
getSystemMessage(): string;
|
|
195
|
-
/**
|
|
196
|
+
/**
|
|
197
|
+
* Replace the active system message and propagate it so the next provider request carries it.
|
|
198
|
+
* Records the live value on `this.systemMessage` (re-injected on compaction) and delegates to
|
|
199
|
+
* `Robota.updateSystemPrompt`, which updates the single-source `config.systemMessage` and the live
|
|
200
|
+
* conversation store head. The system prompt is an agent-level concern, not model config, so this
|
|
201
|
+
* does not route through `setModel`. Used by persona application, the self-verification toggle, and
|
|
202
|
+
* AGENTS.md/CLAUDE.md staleness refresh.
|
|
203
|
+
*/
|
|
196
204
|
updateSystemMessage(newMessage: string): void;
|
|
197
205
|
/**
|
|
198
206
|
* Re-apply model options to the live session (PRESET-013 model/effort re-application seam).
|
|
@@ -306,8 +314,12 @@ declare class SessionStore implements ISessionStore {
|
|
|
306
314
|
/** Return the absolute file path for a session — implements ISessionStore.getFilePath */
|
|
307
315
|
getFilePath(id: string): string;
|
|
308
316
|
/**
|
|
309
|
-
* Persist a session record to disk.
|
|
317
|
+
* Persist a session record to disk atomically (CORE-019).
|
|
310
318
|
* Creates the storage directory if needed.
|
|
319
|
+
*
|
|
320
|
+
* Bytes go to a same-directory temp file first, then move into place with rename —
|
|
321
|
+
* a crash mid-write can therefore never leave a truncated JSON where the previous
|
|
322
|
+
* record used to be. Same-directory is load-bearing: cross-device rename is a copy.
|
|
311
323
|
*/
|
|
312
324
|
save(session: ISessionRecord): void;
|
|
313
325
|
/**
|
|
@@ -327,12 +339,6 @@ declare class SessionStore implements ISessionStore {
|
|
|
327
339
|
}
|
|
328
340
|
//#endregion
|
|
329
341
|
//#region src/session-types.d.ts
|
|
330
|
-
type TCompactTrigger = 'manual' | 'auto';
|
|
331
|
-
interface ICompactEvent {
|
|
332
|
-
trigger: TCompactTrigger;
|
|
333
|
-
before: IContextWindowState;
|
|
334
|
-
after: IContextWindowState;
|
|
335
|
-
}
|
|
336
342
|
/** Options for graceful session shutdown. */
|
|
337
343
|
interface ISessionShutdownOptions {
|
|
338
344
|
reason?: TSessionEndReason;
|
|
@@ -355,6 +361,11 @@ interface ISessionOptions {
|
|
|
355
361
|
hooks?: Record<string, unknown>;
|
|
356
362
|
/** Initial permission mode */
|
|
357
363
|
permissionMode?: TPermissionMode;
|
|
364
|
+
/**
|
|
365
|
+
* Injected "ask the user" port (CMD-005): forwarded into the agent config so model-invoked tools
|
|
366
|
+
* (AskUserQuestion) can solicit a structured answer. Absent in headless/automation sessions.
|
|
367
|
+
*/
|
|
368
|
+
ask?: IUserInteraction['ask'];
|
|
358
369
|
/** Default trust level — used to derive permissionMode if not given */
|
|
359
370
|
defaultTrustLevel?: 'safe' | 'moderate' | 'full';
|
|
360
371
|
/** Active preset id selected at startup (PRESET-011 runtime state). Defaults to 'default'. */
|
|
@@ -459,7 +470,12 @@ declare class Session extends SessionBase {
|
|
|
459
470
|
run(message: string, rawInput?: string): Promise<string>;
|
|
460
471
|
private log;
|
|
461
472
|
private persistSessionInternal;
|
|
462
|
-
/**
|
|
473
|
+
/**
|
|
474
|
+
* Gracefully end the session and fire SessionEnd hooks once — **best-effort** (CORE-013
|
|
475
|
+
* disposal convention): never rejects, so `void session.shutdown()` cannot become an
|
|
476
|
+
* unhandled rejection. Step failures are recorded to the session log and remaining steps
|
|
477
|
+
* still run.
|
|
478
|
+
*/
|
|
463
479
|
shutdown(options?: ISessionShutdownOptions): Promise<void>;
|
|
464
480
|
swapProvider(newProvider: IAIProvider, model: string): void;
|
|
465
481
|
compact(instructions?: string, trigger?: TCompactTrigger): Promise<void>;
|
|
@@ -467,6 +483,14 @@ declare class Session extends SessionBase {
|
|
|
467
483
|
}
|
|
468
484
|
//#endregion
|
|
469
485
|
//#region src/compaction-orchestrator.d.ts
|
|
486
|
+
/**
|
|
487
|
+
* Thrown when a compaction summary is invalid (non-string or empty provider content).
|
|
488
|
+
* Conversation history is append-only source data — callers must not clear or replace
|
|
489
|
+
* it when this is thrown (see SPEC § Compaction Failure Contract).
|
|
490
|
+
*/
|
|
491
|
+
declare class CompactionError extends Error {
|
|
492
|
+
constructor(message: string);
|
|
493
|
+
}
|
|
470
494
|
interface ICompactionOptions {
|
|
471
495
|
sessionId: string;
|
|
472
496
|
cwd: string;
|
|
@@ -489,13 +513,78 @@ declare class CompactionOrchestrator {
|
|
|
489
513
|
* @param provider - The AI provider to use for summarization
|
|
490
514
|
* @param history - Current conversation history
|
|
491
515
|
* @param instructions - Optional focus instructions for the summary
|
|
492
|
-
* @returns The generated summary string
|
|
516
|
+
* @returns The generated summary string (always a non-empty string)
|
|
517
|
+
* @throws {CompactionError} when the provider returns a non-string or empty summary —
|
|
518
|
+
* callers must leave the conversation history untouched in that case
|
|
493
519
|
*/
|
|
494
520
|
compact(provider: IAIProvider, history: TUniversalMessage[], instructions?: string): Promise<string>;
|
|
495
521
|
/** Build the compaction prompt from conversation history */
|
|
496
522
|
private buildCompactionPrompt;
|
|
497
523
|
}
|
|
498
524
|
//#endregion
|
|
525
|
+
//#region src/session-log-events.d.ts
|
|
526
|
+
/**
|
|
527
|
+
* INFRA-017: typed contract for session-log event names + replay keys (SSOT).
|
|
528
|
+
*
|
|
529
|
+
* The `FileSessionLogger` writes JSONL lines `{ timestamp, sessionId, event, ...data }`. The event
|
|
530
|
+
* names were previously implicit string literals scattered across the session/execution code. This
|
|
531
|
+
* module names them once so the writer, the replay validator (`session-log-validation.ts`), and the
|
|
532
|
+
* session-log replay provider (INFRA-017 / TEST-008) share one type-safe schema — without changing
|
|
533
|
+
* what is written (it formalizes the existing format, it does not add a new one).
|
|
534
|
+
*
|
|
535
|
+
* The **replay substrate** is the provider/tool execution layer, keyed deterministically:
|
|
536
|
+
* a `provider_request` (executionId + round) is answered by its recorded
|
|
537
|
+
* `provider_native_raw_payload` / `provider_response_normalized`; a `tool_execution_request`
|
|
538
|
+
* (executionId + toolCallId) by its `tool_execution_result`. `validateSessionReplayLogEntries`
|
|
539
|
+
* proves a log carries all of these (i.e. is replay-complete).
|
|
540
|
+
*/
|
|
541
|
+
/** Canonical session-log event names. */
|
|
542
|
+
declare const SESSION_LOG_EVENT: {
|
|
543
|
+
readonly sessionInit: "session_init";
|
|
544
|
+
readonly sessionShutdown: "session_shutdown";
|
|
545
|
+
readonly context: "context";
|
|
546
|
+
readonly contextCompact: "context_compact";
|
|
547
|
+
readonly error: "error";
|
|
548
|
+
readonly historyMutation: "history_mutation";
|
|
549
|
+
readonly providerRequest: "provider_request";
|
|
550
|
+
readonly providerNativeRawPayload: "provider_native_raw_payload";
|
|
551
|
+
readonly providerResponseRaw: "provider_response_raw";
|
|
552
|
+
readonly providerResponseNormalized: "provider_response_normalized";
|
|
553
|
+
readonly toolExecutionRequest: "tool_execution_request";
|
|
554
|
+
readonly toolExecutionResult: "tool_execution_result";
|
|
555
|
+
readonly user: "user";
|
|
556
|
+
readonly preRun: "pre_run";
|
|
557
|
+
readonly textDelta: "text_delta";
|
|
558
|
+
readonly assistant: "assistant";
|
|
559
|
+
readonly toolCall: "tool_call";
|
|
560
|
+
readonly toolResult: "tool_result";
|
|
561
|
+
readonly toolBlocked: "tool_blocked";
|
|
562
|
+
readonly toolDenied: "tool_denied";
|
|
563
|
+
readonly serverTool: "server_tool";
|
|
564
|
+
};
|
|
565
|
+
type TSessionLogEventName = (typeof SESSION_LOG_EVENT)[keyof typeof SESSION_LOG_EVENT];
|
|
566
|
+
/** Common envelope written for every line by `FileSessionLogger`. */
|
|
567
|
+
interface ISessionLogLine {
|
|
568
|
+
readonly timestamp: string;
|
|
569
|
+
readonly sessionId: string;
|
|
570
|
+
readonly event: string;
|
|
571
|
+
readonly [key: string]: unknown;
|
|
572
|
+
}
|
|
573
|
+
/** Replay correlation key for a provider call. */
|
|
574
|
+
interface IProviderEventKey {
|
|
575
|
+
readonly executionId: string;
|
|
576
|
+
readonly round: number;
|
|
577
|
+
}
|
|
578
|
+
/** Replay correlation key for a tool execution. */
|
|
579
|
+
interface IToolEventKey {
|
|
580
|
+
readonly executionId: string;
|
|
581
|
+
readonly toolCallId: string;
|
|
582
|
+
}
|
|
583
|
+
/** Narrow a raw log line to a specific event name. */
|
|
584
|
+
declare function isSessionLogEvent<TName extends TSessionLogEventName>(line: ISessionLogLine, name: TName): line is ISessionLogLine & {
|
|
585
|
+
event: TName;
|
|
586
|
+
};
|
|
587
|
+
//#endregion
|
|
499
588
|
//#region src/session-log-validation.d.ts
|
|
500
589
|
interface ISessionReplayValidationIssue {
|
|
501
590
|
code: 'PROVIDER_RESPONSE_RAW_MISSING' | 'PROVIDER_NATIVE_RAW_PAYLOAD_MISSING' | 'PROVIDER_RESPONSE_NORMALIZED_MISSING' | 'TOOL_RESULT_MISSING' | 'PAYLOAD_REFERENCE_INVALID';
|
|
@@ -531,5 +620,5 @@ interface ISessionReplayRecord {
|
|
|
531
620
|
declare function loadSessionLogEntries(logFile: string): ISessionLogEntry[];
|
|
532
621
|
declare function replaySessionLogEntries(entries: readonly ISessionLogEntry[]): ISessionReplayRecord;
|
|
533
622
|
//#endregion
|
|
534
|
-
export { AUTO_COMPACT_THRESHOLD, CompactionOrchestrator, ContextWindowTracker, FileSessionLogger, type
|
|
623
|
+
export { AUTO_COMPACT_THRESHOLD, CompactionError, CompactionOrchestrator, ContextWindowTracker, FileSessionLogger, type IExternalPayloadReference, type IFileSessionLoggerOptions, type IProviderEventKey, type ISessionLogEntry, type ISessionLogLine, type ISessionLogger, type ISessionOptions, type ISessionRecord, type ISessionReplayRecord, type ISessionReplayValidationIssue, type ISessionReplayValidationResult, type ISessionShutdownOptions, type ISessionStore, type ISpinner, type ITerminalOutput, type IToolEventKey, PermissionEnforcer, SESSION_LOG_EVENT, Session, SessionStore, SilentSessionLogger, type TAutoCompactThreshold, type TPermissionHandler, type TPermissionResult, type TSessionLogData, type TSessionLogEventName, type TSessionLogValue, isSessionLogEvent, loadSessionLogEntries, replaySessionLogEntries, validateSessionReplayLogEntries };
|
|
535
624
|
//# sourceMappingURL=index.d.ts.map
|
package/dist/node/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
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":"
|
|
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-events.ts","../../src/session-log-validation.ts","../../src/session-log-replay.ts"],"mappings":"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"}
|
package/dist/node/index.js
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
|
-
import{CONTEXT_ESTIMATE_CHARS_PER_TOKEN as e,Robota as t,TRUST_TO_MODE as n,createLogger as r,createUserMessage as i,estimateContextTokensFromMessages as a,evaluatePermission as o,getModelContextWindow as s,getProviderCapabilities as c,messageToHistoryEntry as l,runHooks as u}from"@robota-sdk/agent-core";import{createHash as d,randomUUID as f}from"node:crypto";import{appendFileSync as p,existsSync as m,mkdirSync as h,readFileSync as g,writeFileSync as _}from"node:fs";import{join as v}from"node:path";import{existsSync as y,mkdirSync as
|
|
1
|
+
import{CONTEXT_ESTIMATE_CHARS_PER_TOKEN as e,Robota as t,TRUST_TO_MODE as n,createLogger as r,createUserMessage as i,estimateContextTokensFromMessages as a,evaluatePermission as o,getModelContextWindow as s,getProviderCapabilities as c,messageToHistoryEntry as l,runHooks as u}from"@robota-sdk/agent-core";import{createHash as d,randomUUID as f}from"node:crypto";import{appendFileSync as p,existsSync as m,mkdirSync as h,readFileSync as g,writeFileSync as _}from"node:fs";import{join as v}from"node:path";import{existsSync as y,mkdirSync as b,readFileSync as x,readdirSync as ee,renameSync as te,unlinkSync as S,writeFileSync as ne}from"fs";import{join as C}from"path";var re=class{getPermissionMode(){return this.permissionMode}setPermissionMode(e){this.permissionMode=e}getActivePresetId(){return this.activePresetId}setActivePresetId(e){this.activePresetId=e}getParallelSubagentsEnabled(){return this.parallelSubagentsEnabled}setParallelSubagentsEnabled(e){this.parallelSubagentsEnabled=e}getSessionId(){return this.sessionId}getSystemMessage(){return this.systemMessage}updateSystemMessage(e){this.systemMessage=e,this.robota.updateSystemPrompt(e)}async applyModelOptions(e){await this.robota.ensureReady();let t=e.model??this.model;this.robota.setModel({provider:this.aiProvider.name,model:t,...e.effort!==void 0&&{effort:e.effort},...e.temperature!==void 0&&{temperature:e.temperature},...e.maxOutputTokens!==void 0&&{maxTokens:e.maxOutputTokens}}),this.model=t}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()}syncContextFromHistory(){this.contextTracker.updateFromHistory(this.robota.getHistory())}getAutoCompactThreshold(){return this.contextTracker.getAutoCompactThreshold()}setAutoCompactThreshold(e){this.contextTracker.setAutoCompactThreshold(e)}getHistory(){return this.robota.getHistory()}getFullHistory(){return this.robota.getFullHistory()}getSessionTokenUsage(){let e=0,t=0,n=!1;for(let r of this.getFullHistory()){if(r.category!==`event`||r.type!==`usage-summary`)continue;let i=r.data;e+=i?.promptTokens??0,t+=i?.completionTokens??0,n=!0}return n?{inputTokens:e,outputTokens:t}:void 0}getModelId(){return this.model}addHistoryEntry(e){this.robota.addHistoryEntry(e)}injectMessage(e,t,n){this.robota.injectMessage(e,t,n)}injectRawMessage(e){this.robota.injectRawMessage(e)}clearHistory(){this.robota.clearHistory(),this.contextTracker.reset()}},w=class extends Error{constructor(e){super(e),this.name=`CompactionError`}},T=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 u(this.hooks,`PreCompact`,i,this.hookTypeExecutors);let a=this.buildCompactionPrompt(t,n),o=await e.chat([{id:f(),role:`user`,content:a,state:`complete`,timestamp:new Date}],{model:this.model});if(typeof o.content!=`string`||o.content.trim()===``)throw new w(`Compaction produced an invalid summary (provider=${e.name}, content type=${typeof o.content}); conversation history preserved untouched`);return o.content}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(`
|
|
2
2
|
`)].join(`
|
|
3
|
-
`)}};const
|
|
4
|
-
`),l=s?`<system-reminder>\n${s}\n</system-reminder>\n${t}`:t;r.clearSessionStartStdout();let d=r.robota.getHistory(),f=JSON.stringify(d),p=c(r.aiProvider);r.log(`pre_run`,{historyLength:d.length,historyChars:f.length,historyEstTokens:Math.ceil(f.length/e),input:l,history:d,model:r.model,provider:r.aiProvider.name,maxTokens:r.contextTracker.getContextState().maxTokens,nativeWebSearchSupported:p.nativeWebTools.webSearch.supported,nativeWebSearchEnabled:p.nativeWebTools.webSearch.enabled,nativeWebFetchSupported:p.nativeWebTools.webFetch.supported,nativeWebFetchEnabled:p.nativeWebTools.webFetch.enabled}),r.contextTracker.updateFromHistory([...d,i(l)]),r.onContextUpdate?.(r.contextTracker.getContextState());let m;try{let e=
|
|
5
|
-
`)}catch{}}};function
|
|
6
|
-
`).map(e=>e.trim()).filter(e=>e.length>0).map(e=>JSON.parse(e)):[]}function
|
|
3
|
+
`)}};const E=.835;var D=class{contextUsedTokens=0;contextMaxTokens;autoCompactThreshold;constructor(e,t,n){this.contextMaxTokens=t??s(e),this.autoCompactThreshold=O(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=O(e)}updateFromHistory(e){this.contextUsedTokens=a(e).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}const ie={success:!0,data:JSON.stringify({success:!1,output:``,error:`Permission denied. The user did not approve this action.`}),metadata:{}},ae=r(`ToolHookHelpers`);function oe(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 se(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 ce(e,t,n){let r=await u(e,`PreToolUse`,t,n);return r.blocked?{success:!0,data:JSON.stringify({blocked:!0,reason:r.reason??`Blocked by hook`}),metadata:{}}:null}function le(e,t,n,r){u(e,`PostToolUse`,{...t,hook_event_name:`PostToolUse`,tool_output:typeof n.data==`string`?n.data:JSON.stringify(n.data)},r).catch(e=>ae.warn(`hook failed`,{error:e}))}var k=class{sessionId;cwd;getPermissionMode;config;terminal;permissionHandler;promptForApprovalFn;sessionLogger;onToolExecution;hookTypeExecutors;transcriptPath;sessionAllowedTools=new Set;onProjectAllowTool;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,this.onProjectAllowTool=e.onProjectAllowTool}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=se(t.sessionId,t.cwd,a,r,t.getPermissionMode(),t.transcriptPath),s=await ce(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,executionId:i?.executionId}),ie;t.onToolExecution?.({type:`start`,toolName:a,toolArgs:r,executionId:i?.executionId});let c=await n(r,i),l=oe(c);l!==c&&typeof c.data==`string`&&t.terminal.writeLine(` ⚠ Output truncated: ${c.data.length.toLocaleString()} chars total — model sees first and last 15,000 chars`),t.onToolExecution?.({type:`end`,toolName:a,toolArgs:r,success:l.success,toolResultData:typeof l.data==`string`?l.data:JSON.stringify(l.data),executionId:i?.executionId});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}),le(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=o(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===`allow-project`?(this.sessionAllowedTools.add(e),this.onProjectAllowTool?.(e),!0):n}if(this.promptForApprovalFn){let n=await this.promptForApprovalFn(this.terminal,e,t);return n===`allow-session`?(this.sessionAllowedTools.add(e),!0):n===`allow-project`?(this.sessionAllowedTools.add(e),this.onProjectAllowTool?.(e),!0):n}return!1}log(e,t){this.sessionLogger?.log(this.sessionId,e,t)}};function A(e,t,n,r,i){return new k({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,onProjectAllowTool:e.onProjectAllowTool})}function j(e,t,n,r){return{contextTracker:new D(t,e.contextMaxTokens,e.autoCompactThreshold),compactionOrchestrator:new T({sessionId:n,cwd:r,model:t,hooks:e.hooks,compactInstructions:e.compactInstructions,hookTypeExecutors:e.hookTypeExecutors})}}function M(e,n,r,i,a,o){let s=n.wrapTools(r);return new t({name:e.agentName??`agent`,aiProviders:[i],defaultModel:{provider:i.name,model:a,...e.effort!==void 0&&{effort:e.effort}},systemMessage:o,tools:s,logging:{enabled:!1},...e.providerTimeout!==void 0&&{timeout:e.providerTimeout},...e.responseFormat?{responseFormat:e.responseFormat}:{},...e.ask?{ask:e.ask}:{}})}const N=r(`SessionHistoryOps`);async function P(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};u(t.hooks,`PostCompact`,o,t.hookTypeExecutors).catch(e=>N.warn(`hook failed`,{error:e}));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 F(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)}const I=r(`SessionLifecycle`);function L(e,t,n){e.configureNativeWebTools?.({webSearch:!0}),`onServerToolUse`in e&&(e.onServerToolUse=(e,t)=>{n(`server_tool`,{tool:e,...t})})}function R(e,t,n,r,i,a,o){u(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(e=>I.warn(`SessionStart hook failed`,{error:e}))}async function z(e,t,n,r,i,a,o){await u(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 B=`unknown_tool`;function V(e){return{knownToolNames:new Set(e.knownToolNames),unknownToolCallIds:new Set,...e.onToolExecution&&{onToolExecution:e.onToolExecution}}}function H(e,t,n){if(e.onToolExecution){if(t===`tool_execution_request`){U(e,n);return}t===`tool_execution_result`&&W(e,n)}}function U(e,t){let n=G(t.toolName),r=G(t.toolCallId);!n||!r||e.knownToolNames.has(n)||(e.unknownToolCallIds.add(r),e.onToolExecution?.({type:`start`,toolName:n,toolArgs:ue(t.parameters)}))}function W(e,t){let n=G(t.toolName),r=G(t.toolCallId);if(!n||!r)return;let i=K(t.metadata);if(!(e.unknownToolCallIds.has(r)||i?.errorCode===B))return;e.unknownToolCallIds.delete(r);let a=G(t.error)??`Tool "${n}" is not registered.`;e.onToolExecution?.({type:`end`,toolName:n,success:!1,toolResultData:JSON.stringify({success:!1,error:a,errorCode:B,requestedTool:G(i?.requestedTool)??n,availableTools:de(i?.availableTools)})})}function ue(e){let t=K(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 G(e){return typeof e==`string`&&e.length>0?e:void 0}function K(e){return typeof e==`object`&&e&&!Array.isArray(e)?e:void 0}function de(e){return Array.isArray(e)?e.filter(e=>typeof e==`string`):[]}const q=r(`SessionRun`);async function fe(t,n,r,a){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 o=await u(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),s=[r.sessionStartStdout,o.stdout].filter(Boolean).join(`
|
|
4
|
+
`),l=s?`<system-reminder>\n${s}\n</system-reminder>\n${t}`:t;r.clearSessionStartStdout();let d=r.robota.getHistory(),f=JSON.stringify(d),p=c(r.aiProvider);r.log(`pre_run`,{historyLength:d.length,historyChars:f.length,historyEstTokens:Math.ceil(f.length/e),input:l,history:d,model:r.model,provider:r.aiProvider.name,maxTokens:r.contextTracker.getContextState().maxTokens,nativeWebSearchSupported:p.nativeWebTools.webSearch.supported,nativeWebSearchEnabled:p.nativeWebTools.webSearch.enabled,nativeWebFetchSupported:p.nativeWebTools.webFetch.supported,nativeWebFetchEnabled:p.nativeWebTools.webFetch.enabled}),r.contextTracker.updateFromHistory([...d,i(l)]),r.onContextUpdate?.(r.contextTracker.getContextState());let m;try{let e=V({knownToolNames:r.knownToolNames??[],...r.onToolExecution&&{onToolExecution:r.onToolExecution}}),t=r.onTextDelta?e=>{r.log(`text_delta`,{delta:e}),r.onTextDelta?.(e)}:void 0;if(m=await r.robota.run(l,{signal:a,maxExecutionRounds:r.maxTurns??0,onExecutionEvent:(t,n)=>{r.log(t,n),H(e,t,n),t===`assistant_message_committed`&&(r.contextTracker.updateFromHistory(r.robota.getHistory()),r.onContextUpdate?.(r.contextTracker.getContextState()))},...t&&{onTextDelta:t}}),a.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}),u(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=>q.warn(`hook failed`,{error:e})),e}let h=r.robota.getHistory(),g=h.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:m,historyLength:h.length,estimatedChars:JSON.stringify(h).length,history:h,historyStructure:g}),r.contextTracker.updateFromHistory(h);let _=r.contextTracker.getContextState();return r.onContextUpdate?.(_),r.log(`context`,{maxTokens:_.maxTokens,usedTokens:_.usedTokens,usedPercentage:_.usedPercentage,remainingPercentage:_.remainingPercentage}),u(r.hooks,`Stop`,{session_id:r.sessionId,cwd:r.cwd,hook_event_name:`Stop`,response:m.substring(0,500),last_assistant_message:m,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=>q.warn(`hook failed`,{error:e})),r.getSessionStore()&&r.persistSession(),m}var pe=class extends re{robota;permissionEnforcer;contextTracker;permissionMode;activePresetId;parallelSubagentsEnabled;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:t,provider:r,systemMessage:i}=e;this.terminal=e.terminal,this.sessionStore=e.sessionStore,this.systemMessage=i,this.toolSchemas=t.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?n[e.defaultTrustLevel]:void 0)??`default`,this.activePresetId=e.activePresetId??`default`,this.parallelSubagentsEnabled=e.enableParallelSubagents??!0,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,L(r,e,(e,t)=>this.log(e,t)),this.permissionEnforcer=A(e,this.sessionId,this.cwd,()=>this.permissionMode,this.transcriptPath);let{contextTracker:a,compactionOrchestrator:o}=j(e,this.model,this.sessionId,this.cwd);this.contextTracker=a,this.compactionOrchestrator=o,this.robota=M(e,this.permissionEnforcer,t,r,this.model,i),R(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 fe(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&&F({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`,n=async(e,t)=>{try{await t()}catch(t){this.log(`session_shutdown_step_error`,{step:e,error:t instanceof Error?t.message:String(t)})}};return this.shutdownPromise=(async()=>{await n(`abort`,()=>this.abort()),this.log(`session_shutdown`,{reason:t}),await n(`persist`,()=>this.persistSessionInternal()),await n(`session-end-hook`,()=>z(this.sessionId,this.cwd,t,this.hooks,this.hookTypeExecutors,this.permissionMode,this.transcriptPath)),await n(`destroy-agent`,async()=>{await this.robota.destroy()})})(),this.shutdownPromise}swapProvider(e,t){this.robota.swapDefaultProvider(e,t),e.configureNativeWebTools?.({webSearch:!0}),`onServerToolUse`in e&&(e.onServerToolUse=(e,t)=>this.log(`server_tool`,{tool:e,...t})),this.aiProvider=e}async compact(e,t=`manual`){await P(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 me=/^(api[-_]?key|authorization|access[-_]?token|refresh[-_]?token|secret|password|x[-_]?api[-_]?key)$/i;var he=class{logDir;options;constructor(e,t={}){this.logDir=e,this.options={externalPayloadThresholdBytes:t.externalPayloadThresholdBytes??32768,redactedValue:t.redactedValue??`[REDACTED]`};try{h(e,{recursive:!0})}catch{}}log(e,t,n){try{let r=ge(e,this.logDir,n,this.options),i=JSON.stringify({timestamp:new Date().toISOString(),sessionId:e,event:t,...r});p(v(this.logDir,`${e}.jsonl`),i+`
|
|
5
|
+
`)}catch{}}};function ge(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(me.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=d(`sha256`).update(i).digest(`hex`),s=`${e}.payloads`,c=v(s,`${o}.json`),l=v(t,s),u=v(t,c);return h(l,{recursive:!0}),m(u)||_(u,i,`utf-8`),{kind:`external-payload`,encoding:`json`,sha256:o,byteLength:a,relativePath:c}}var _e=class{log(){}};const ve={sessionInit:`session_init`,sessionShutdown:`session_shutdown`,context:`context`,contextCompact:`context_compact`,error:`error`,historyMutation:`history_mutation`,providerRequest:`provider_request`,providerNativeRawPayload:`provider_native_raw_payload`,providerResponseRaw:`provider_response_raw`,providerResponseNormalized:`provider_response_normalized`,toolExecutionRequest:`tool_execution_request`,toolExecutionResult:`tool_execution_result`,user:`user`,preRun:`pre_run`,textDelta:`text_delta`,assistant:`assistant`,toolCall:`tool_call`,toolResult:`tool_result`,toolBlocked:`tool_blocked`,toolDenied:`tool_denied`,serverTool:`server_tool`};function ye(e,t){return e.event===t}function be(e){let t=[],n=xe(),r=Se();return e.forEach((e,i)=>{X(e,i,t),Ce(n,e,i),we(r,e,i)}),Te(n,t),Ee(r,t),{ok:t.length===0,issues:t}}function xe(){return{requests:new Map,nativeRawPayloads:new Set,rawResponses:new Set,normalizedResponses:new Set}}function Se(){return{requests:new Map,results:new Set}}function Ce(e,t,n){let r=De(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 we(e,t,n){let r=Oe(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 Te(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 Ee(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 De(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 Oe(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(ke(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 ke(e){return typeof e==`object`&&!!e&&!Array.isArray(e)}function Z(e){return m(e)?g(e,`utf-8`).split(`
|
|
6
|
+
`).map(e=>e.trim()).filter(e=>e.length>0).map(e=>JSON.parse(e)):[]}function Ae(e){let t=[],n=[],r={backgroundTaskEvents:[],backgroundJobGroupEvents:[],memoryEvents:[]},i,a,o,s;for(let c of e){if(i??=c.sessionId,o??=c.timestamp,s=c.timestamp,c.event===`session_init`&&(a=typeof c.cwd==`string`?c.cwd:a),c.event===`history_mutation`&&c.mutation===`append_message`){let e=Me(c.message);e&&(t.push(e),n.push(l(e)))}je(c,r)}return{sessionId:i,cwd:a,createdAt:o,updatedAt:s,messages:t,history:n,backgroundTaskEvents:r.backgroundTaskEvents,backgroundJobGroupEvents:r.backgroundJobGroupEvents,memoryEvents:r.memoryEvents}}function je(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 Me(e){if(!Ne(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 Ne(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 Pe(){return process.env.HOME??process.env.USERPROFILE??`/`}var Fe=class{baseDir;constructor(e){this.baseDir=e??C(Pe(),`.robota`,`sessions`)}ensureDir(){y(this.baseDir)||b(this.baseDir,{recursive:!0})}filePath(e){return C(this.baseDir,`${e}.json`)}getFilePath(e){return this.filePath(e)}save(e){this.ensureDir();let t=this.filePath(e.id),n=`${t}.${process.pid}.tmp`;ne(n,JSON.stringify(e,null,2),`utf-8`);try{te(n,t)}catch(e){throw S(n),e}}load(e){let t=this.filePath(e);if(y(t))try{let e=x(t,`utf-8`);return JSON.parse(e)}catch{return}}list(){if(!y(this.baseDir))return[];let e=ee(this.baseDir).filter(e=>e.endsWith(`.json`)),t=[];for(let n of e)try{let e=x(C(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);y(t)&&S(t)}};export{E as AUTO_COMPACT_THRESHOLD,w as CompactionError,T as CompactionOrchestrator,D as ContextWindowTracker,he as FileSessionLogger,k as PermissionEnforcer,ve as SESSION_LOG_EVENT,pe as Session,Fe as SessionStore,_e as SilentSessionLogger,ye as isSessionLogEvent,Z as loadSessionLogEntries,Ae as replaySessionLogEntries,be as validateSessionReplayLogEntries};
|
|
7
7
|
//# sourceMappingURL=index.js.map
|