@robota-sdk/agent-session 3.0.0-beta.83 → 3.0.0-beta.84
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 +38 -0
- package/README.md +200 -157
- package/dist/node/index.cjs +7 -7
- package/dist/node/index.d.cts +436 -361
- package/dist/node/index.d.cts.map +1 -1
- package/dist/node/index.d.ts +436 -361
- package/dist/node/index.d.ts.map +1 -1
- package/dist/node/index.js +9 -9
- package/dist/node/index.js.map +1 -1
- package/package.json +7 -7
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,43 @@
|
|
|
1
1
|
# @robota-sdk/agent-session
|
|
2
2
|
|
|
3
|
+
## 3.0.0-beta.84
|
|
4
|
+
|
|
5
|
+
### Minor Changes
|
|
6
|
+
|
|
7
|
+
- 9f46375: A session can save a pending tool approval and answer it after it is reopened.
|
|
8
|
+
`Session.runRecoverable()` runs a prompt with a host-owned execution journal from
|
|
9
|
+
`@robota-sdk/agent-core`. When a tool call needs approval, it returns `waiting` with the saved
|
|
10
|
+
request (the exact action and its arguments) instead of asking a live approver.
|
|
11
|
+
`Session.resumeRecoverable()` takes the answer and continues that execution without adding another
|
|
12
|
+
user message; a session recreated with the same session ID, workspace, provider and model can do the
|
|
13
|
+
same. Ordinary `run()` keeps asking for approval live.
|
|
14
|
+
|
|
15
|
+
An approval covers only the action and arguments it was given; it never grants session-wide consent.
|
|
16
|
+
Current permissions, hooks and task restrictions are still checked when the tool runs, and a saved
|
|
17
|
+
denial holds even if the policy has since become more permissive. Reusing a response ID with
|
|
18
|
+
different content is refused.
|
|
19
|
+
|
|
20
|
+
While an execution waits, the session refuses new prompts. `Session.getPendingExecution()` returns
|
|
21
|
+
its `executionId` and saved requests, also after a cancellation that ended the turn once the wait
|
|
22
|
+
was saved. A resume refused before it continues, such as a stale response or a storage failure,
|
|
23
|
+
leaves the execution pending for another attempt; once it has continued, a later failure ends it
|
|
24
|
+
like an ordinary turn. `Session.abandonPendingExecution(executionId)` gives it up so the session
|
|
25
|
+
accepts new input: nothing runs and nothing is written to the journal, its open tool calls are
|
|
26
|
+
closed as failed in history, and that execution can no longer be resumed. The same journal also
|
|
27
|
+
records compaction's model call before history changes, and a journal write failure stays a failure
|
|
28
|
+
even when the turn is being cancelled.
|
|
29
|
+
|
|
30
|
+
### Patch Changes
|
|
31
|
+
|
|
32
|
+
- Updated dependencies [9f46375]
|
|
33
|
+
- Updated dependencies [e8d70ac]
|
|
34
|
+
- Updated dependencies [9c6a8db]
|
|
35
|
+
- Updated dependencies [9c6a8db]
|
|
36
|
+
- @robota-sdk/agent-core@3.0.0-beta.84
|
|
37
|
+
- @robota-sdk/agent-interface-session@3.0.0-beta.84
|
|
38
|
+
- @robota-sdk/agent-interface-execution@3.0.0-beta.84
|
|
39
|
+
- @robota-sdk/agent-file-authority@3.0.0-beta.84
|
|
40
|
+
|
|
3
41
|
## 3.0.0-beta.83
|
|
4
42
|
|
|
5
43
|
### Minor Changes
|
package/README.md
CHANGED
|
@@ -1,6 +1,12 @@
|
|
|
1
1
|
# @robota-sdk/agent-session
|
|
2
2
|
|
|
3
|
-
Session lifecycle
|
|
3
|
+
Session lifecycle for the Robota SDK. A `Session` wraps a `Robota` agent from
|
|
4
|
+
`@robota-sdk/agent-core` and adds permission-gated tool execution, lifecycle hooks, context-window
|
|
5
|
+
tracking, conversation compaction, session logs and optional persistence.
|
|
6
|
+
|
|
7
|
+
Most applications use `InteractiveSession` or `createQuery()` from `@robota-sdk/agent-framework`,
|
|
8
|
+
which build a `Session` with tools, provider and system prompt already wired. Use this package
|
|
9
|
+
directly when you assemble a session yourself.
|
|
4
10
|
|
|
5
11
|
## Installation
|
|
6
12
|
|
|
@@ -8,11 +14,14 @@ Session lifecycle management for the Robota SDK. Wraps a `Robota` agent instance
|
|
|
8
14
|
npm install @robota-sdk/agent-session @robota-sdk/agent-core
|
|
9
15
|
```
|
|
10
16
|
|
|
17
|
+
Requires Node.js 22.12 or later.
|
|
18
|
+
|
|
11
19
|
## Quick Start
|
|
12
20
|
|
|
13
21
|
```typescript
|
|
14
22
|
import { Session } from '@robota-sdk/agent-session';
|
|
15
|
-
import type {
|
|
23
|
+
import type { ITerminalOutput } from '@robota-sdk/agent-session';
|
|
24
|
+
import type { IAIProvider, IToolWithEventService } from '@robota-sdk/agent-core';
|
|
16
25
|
|
|
17
26
|
declare const tools: IToolWithEventService[];
|
|
18
27
|
declare const provider: IAIProvider;
|
|
@@ -23,9 +32,7 @@ const session = new Session({
|
|
|
23
32
|
provider,
|
|
24
33
|
systemMessage: 'You are a helpful assistant.',
|
|
25
34
|
terminal,
|
|
26
|
-
//
|
|
27
|
-
// permission root and the persisted record — it is not read from the process any more, so a
|
|
28
|
-
// subagent runs in its own workspace rather than its parent's.
|
|
35
|
+
// Required. The session's root: hook inputs, the permission workspace and the stored record use it.
|
|
29
36
|
cwd: process.cwd(),
|
|
30
37
|
permissions: { allow: ['Read(*)'], deny: [] },
|
|
31
38
|
autoCompactThreshold: 0.75,
|
|
@@ -35,178 +42,214 @@ const response = await session.run('Hello!');
|
|
|
35
42
|
|
|
36
43
|
// Context tracking
|
|
37
44
|
const state = session.getContextState();
|
|
38
|
-
console.log(`${state.usedPercentage.toFixed(1)}% context used
|
|
45
|
+
console.log(`${state.usedPercentage.toFixed(1)}% context used`, response);
|
|
39
46
|
|
|
40
47
|
// Manual compaction
|
|
41
48
|
await session.compact('Focus on the API changes');
|
|
49
|
+
|
|
50
|
+
await session.shutdown();
|
|
42
51
|
```
|
|
43
52
|
|
|
44
|
-
|
|
53
|
+
`ITerminalOutput` is a small terminal I/O interface (`write`, `writeLine`, `prompt`, `select`,
|
|
54
|
+
`spinner`, …). The session writes notices to it and hands it to an injected `promptForApproval`
|
|
55
|
+
function. A tool call that needs approval goes to `permissionHandler` or `promptForApproval`; with
|
|
56
|
+
neither, it is denied.
|
|
57
|
+
|
|
58
|
+
## Checkpointed approval
|
|
59
|
+
|
|
60
|
+
Use `runRecoverable` when the host must save an approval request and answer it after reopening the
|
|
61
|
+
same Session. Supply an `IRecoverableExecutionJournal` from `@robota-sdk/agent-core`; the host owns
|
|
62
|
+
exclusive access and durable, idempotent record storage. Ordinary `run` keeps live approval handling.
|
|
63
|
+
|
|
64
|
+
```typescript
|
|
65
|
+
import type { IRecoverableExecutionJournal } from '@robota-sdk/agent-core';
|
|
66
|
+
|
|
67
|
+
declare const journal: IRecoverableExecutionJournal;
|
|
68
|
+
declare const approvedByHost: boolean;
|
|
69
|
+
declare const hostResponseId: string; // Persist this ID and reuse it for redelivery.
|
|
70
|
+
|
|
71
|
+
const result = await session.runRecoverable('Perform the requested task', {
|
|
72
|
+
executionJournal: journal,
|
|
73
|
+
});
|
|
74
|
+
if (result.status === 'waiting') {
|
|
75
|
+
const request = result.requests.find((value) => value.kind === 'robota-session/approval');
|
|
76
|
+
if (request) {
|
|
77
|
+
// Authenticate the responder and show the exact request.data.arguments before answering.
|
|
78
|
+
const continued = await session.resumeRecoverable({
|
|
79
|
+
executionId: request.executionId,
|
|
80
|
+
journal,
|
|
81
|
+
toolResponses: [
|
|
82
|
+
{
|
|
83
|
+
requestId: request.requestId,
|
|
84
|
+
responseId: hostResponseId,
|
|
85
|
+
response: { approved: approvedByHost },
|
|
86
|
+
},
|
|
87
|
+
],
|
|
88
|
+
});
|
|
89
|
+
// continued may wait again, including for another action with identical arguments.
|
|
90
|
+
}
|
|
91
|
+
}
|
|
92
|
+
```
|
|
45
93
|
|
|
46
|
-
`
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
94
|
+
`resumeRecoverable` continues execution without adding another user message. A recreated Session
|
|
95
|
+
must use the same session ID, canonical workspace, provider and model. Current hooks, permissions,
|
|
96
|
+
task restrictions and peer restrictions are checked again; approval never grants session-wide consent.
|
|
97
|
+
A response with a reused ID and different content is refused. Existing saved decisions also bind
|
|
98
|
+
ordinary `resume`.
|
|
99
|
+
|
|
100
|
+
While an execution waits, `run` refuses new input. `getPendingExecution()` returns its
|
|
101
|
+
`executionId` and `requests`, including after a cancellation that ended the turn once the wait was
|
|
102
|
+
saved. A journaled `run`, `runRecoverable` or resume that fails (a storage failure, an unreconciled
|
|
103
|
+
effect) while its tool calls are open in history also leaves the execution pending, with only the
|
|
104
|
+
waits whose effect never started in `requests`; resume it once the journal is readable, or abandon
|
|
105
|
+
it. A failure after its rounds settled ends it like an ordinary turn.
|
|
106
|
+
`abandonPendingExecution(executionId)` gives it up without running anything: its open tool calls
|
|
107
|
+
are closed as failed in this Session's history and this Session can no longer resume it, but the
|
|
108
|
+
journal is left untouched. Discard that execution's journal records yourself; otherwise a Session
|
|
109
|
+
without this history, such as a fresh one, can still resume the execution from them.
|
|
110
|
+
|
|
111
|
+
Waiting is returned only after request writes are durable and tools already running beside the
|
|
112
|
+
waiting one finish; calls not yet started stay pending. Cancellation interrupts running tools but
|
|
113
|
+
still waits for them to settle. Storage failures propagate, and uncertain effects raise a
|
|
114
|
+
reconciliation error rather than being replayed. Turn-level lifecycle hooks are omitted on
|
|
115
|
+
continuation because their effects lack durable receipts; structured-output recovery is unsupported.
|
|
116
|
+
This API alone does not provide arbitrary-effect recovery or durable Roundtable execution.
|
|
51
117
|
|
|
52
118
|
## Features
|
|
53
119
|
|
|
54
|
-
| Feature | Description
|
|
55
|
-
| -------------------------- |
|
|
56
|
-
| **Permission enforcement** |
|
|
57
|
-
|
|
|
58
|
-
| **
|
|
59
|
-
| **
|
|
60
|
-
| **
|
|
61
|
-
| **
|
|
62
|
-
| **
|
|
63
|
-
| **
|
|
64
|
-
| **
|
|
65
|
-
| **
|
|
66
|
-
| **Provider capabilities** | Generic native web capability setup is requested through the provider contract, not provider-name branches |
|
|
120
|
+
| Feature | Description |
|
|
121
|
+
| -------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
|
122
|
+
| **Permission enforcement** | Every tool call is decided by `evaluatePermission` from `agent-core` (deny, ask and allow rules plus the permission mode). Approvals go to `permissionHandler` or `promptForApproval`; with neither, the call is denied. |
|
|
123
|
+
| **`auto` mode** | `AutoModeGate` sends calls the mode would ask about to a `permissionClassifier`; after repeated blocks it falls back to asking a person |
|
|
124
|
+
| **Hooks** | Fires `PreToolUse`, `PostToolUse`, `PermissionDecision`, `SessionStart`, `SessionEnd`, `UserPromptSubmit`, `Stop`, `StopFailure`, `PreCompact`, `PostCompact`, `PreModelCall` and `PostModelCall`. See the [hook event catalog](../agent-core/docs/HOOK-CATALOG.md). |
|
|
125
|
+
| **Context tracking** | Token usage from the shared core estimator, with a configurable auto-compact threshold (default 83.5% of the context window) |
|
|
126
|
+
| **Compaction** | A model-written summary replaces the history to free context space; an invalid summary throws `CompactionError` and leaves the history untouched |
|
|
127
|
+
| **Persistence** | Inject an `IInteractiveSessionStore`; each completed `run()` and `shutdown()` save the record. `NodeSessionStore` writes JSON files atomically (temp file + rename) |
|
|
128
|
+
| **Abort** | `session.abort()` stops the running turn; `run()` then rejects with an `AbortError` |
|
|
129
|
+
| **One turn at a time** | A concurrent `run()` is refused with `SessionBusyError`; `isRunning()` is true until the running turn has fully unwound |
|
|
130
|
+
| **Session logging** | `FileSessionLogger` writes versioned JSONL through an injected sink; `NodeSessionLogSink` is the file-system sink |
|
|
131
|
+
| **Replay events** | Provider and tool execution events from core are written to the log so a session can be replayed and validated |
|
|
67
132
|
|
|
68
133
|
## Key Methods
|
|
69
134
|
|
|
70
|
-
| Method
|
|
71
|
-
|
|
|
72
|
-
| `constructor(options)`
|
|
73
|
-
| `run(message)`
|
|
74
|
-
| `
|
|
75
|
-
| `
|
|
76
|
-
| `
|
|
77
|
-
| `
|
|
78
|
-
| `
|
|
79
|
-
| `
|
|
80
|
-
| `
|
|
81
|
-
| `
|
|
82
|
-
| `
|
|
83
|
-
| `
|
|
84
|
-
| `
|
|
85
|
-
| `
|
|
86
|
-
| `
|
|
87
|
-
| `
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
|
92
|
-
|
|
|
93
|
-
| `
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
|
98
|
-
|
|
|
99
|
-
| `
|
|
100
|
-
| `
|
|
101
|
-
| `
|
|
102
|
-
| `
|
|
103
|
-
| `
|
|
104
|
-
| `
|
|
105
|
-
| `
|
|
106
|
-
| `
|
|
107
|
-
| `TPermissionResult`
|
|
108
|
-
| `ITerminalOutput`
|
|
109
|
-
| `
|
|
110
|
-
| `
|
|
111
|
-
| `
|
|
112
|
-
| `
|
|
113
|
-
| `
|
|
114
|
-
| `
|
|
115
|
-
| `
|
|
116
|
-
| `
|
|
117
|
-
| `
|
|
118
|
-
| `
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
| ------------------------ | ------------------------------------------------------------------- |
|
|
126
|
-
| `PermissionEnforcer` | Tool wrapping, permission checks, hook execution, output truncation |
|
|
127
|
-
| `ContextWindowTracker` | Token usage tracking, auto-compact threshold |
|
|
128
|
-
| `CompactionOrchestrator` | Conversation summarization via LLM |
|
|
135
|
+
| Method | Description |
|
|
136
|
+
| --------------------------------------------------------- | ------------------------------------------------------------------------------- |
|
|
137
|
+
| `constructor(options)` | `ISessionOptions`; pass `sessionId` for a deterministic ID |
|
|
138
|
+
| `run(message)` | Send a message and return the response |
|
|
139
|
+
| `runRecoverable(message, options)` | Run with a recovery journal; returns a completed response or saved waits |
|
|
140
|
+
| `resumeRecoverable(options)` | Answer saved waits and continue that execution without new input |
|
|
141
|
+
| `getPendingExecution()` | The execution whose saved waits block new input, if any |
|
|
142
|
+
| `abandonPendingExecution(executionId)` | Give up that execution without running it, so new input is accepted |
|
|
143
|
+
| `injectMessage(role, content)` | Add a message to the history without running the agent |
|
|
144
|
+
| `compact(instructions?)` | Summarize the conversation to free context space |
|
|
145
|
+
| `getContextState()` | `{ usedTokens, maxTokens, usedPercentage, remainingPercentage }` |
|
|
146
|
+
| `getAutoCompactThreshold()` | Auto-compact threshold fraction, or `false` when disabled |
|
|
147
|
+
| `getPermissionMode()` / `setPermissionMode(mode)` | Read or change the permission mode |
|
|
148
|
+
| `getModelEffort()` | The model-effort selection for the next call (`auto` when unset) |
|
|
149
|
+
| `getHistory()` / `clearHistory()` | Read or clear the conversation history |
|
|
150
|
+
| `addTools(tools)` | Register more tools on a live session |
|
|
151
|
+
| `getProvider()` / `swapProvider(provider, model)` | Read or replace the provider the session uses |
|
|
152
|
+
| `abort()` | Signal the running turn to stop (it holds the session until it unwinds) |
|
|
153
|
+
| `isRunning()` | True while a turn is in flight, including one that was aborted and is unwinding |
|
|
154
|
+
| `getSessionId()` | The stable session identifier |
|
|
155
|
+
| `getMessageCount()` | Number of completed `run()` calls |
|
|
156
|
+
| `getSessionAllowedTools()` / `clearSessionAllowedTools()` | Approvals remembered for this session |
|
|
157
|
+
| `getRecentPermissionDenials()` | Calls this session refused, most recent first, with the reason |
|
|
158
|
+
| `shutdown()` | Fire `SessionEnd`, save the record and release the agent |
|
|
159
|
+
|
|
160
|
+
## Public API
|
|
161
|
+
|
|
162
|
+
| Export | Kind | Description |
|
|
163
|
+
| ------------------------------------------------------------------------------------------------------------ | ------------------- | ---------------------------------------------------------------------------------------- |
|
|
164
|
+
| `Session` | Class | Wraps `Robota` with permissions, hooks, compaction, logging and persistence |
|
|
165
|
+
| `ISessionOptions`, `ISessionRunOptions`, `ISessionShutdownOptions` | Types | Constructor, run and shutdown options |
|
|
166
|
+
| `SessionBusyError`, `TurnClaim` | Classes | The refusal of a concurrent turn, and the identity of the running turn |
|
|
167
|
+
| `PermissionEnforcer` | Class | Tool permission checks, hook execution and output truncation |
|
|
168
|
+
| `consentScopeFor` | Function | The permission pattern an "allow for this session/project" answer grants |
|
|
169
|
+
| `AutoModeGate`, `IPermissionClassifier` | Class, type | The `auto` permission mode and the classifier port it calls |
|
|
170
|
+
| `ContextWindowTracker`, `AUTO_COMPACT_THRESHOLD` | Class, const | Token usage tracking and the default auto-compact threshold |
|
|
171
|
+
| `CompactionOrchestrator`, `CompactionError`, `DEFAULT_COMPACTION_PROMPT` | Class, error, const | Conversation compaction |
|
|
172
|
+
| `TPermissionHandler`, `TPermissionResult` | Types | Approval callback and its answer (`true`, `false`, `'allow-session'`, `'allow-project'`) |
|
|
173
|
+
| `ITerminalOutput`, `ISpinner` | Types | Terminal I/O used for approval prompts |
|
|
174
|
+
| `NodeSessionStore` | Class | File-system JSON store for session records |
|
|
175
|
+
| `IInteractiveSessionRecord`, `IInteractiveSessionStore` | Types | The persisted session record and store port (from `@robota-sdk/agent-interface-session`) |
|
|
176
|
+
| `decodeInteractiveSessionRecord`, `decodeVersionedInteractiveSessionRecord` | Functions | Validate a stored record before use |
|
|
177
|
+
| `serializeSessionArtifact`, `deserializeSessionArtifact` | Functions | Export a session record to a portable artifact and import it again |
|
|
178
|
+
| `scrubSensitiveKeys`, `isSensitiveKey` | Functions | Redact secret-looking keys (used by the logger; optional for artifacts) |
|
|
179
|
+
| `CheckpointTree` | Class | In-memory branching tree of checkpoint IDs (fork and switch between branches) |
|
|
180
|
+
| `FileSessionLogger`, `SilentSessionLogger`, `ISessionLogger` | Class, type | JSONL session logger and the logger port |
|
|
181
|
+
| `NodeSessionLogSink`, `NodeSessionLogSource`, `ISessionLogSink`, `ISessionLogSource` | Classes, types | File-system log writer and reader, and their ports |
|
|
182
|
+
| `loadSessionLogEntries`, `decodeSessionLogEntries`, `SessionLogDecodeError` | Functions, error | Read and validate a session log |
|
|
183
|
+
| `replaySessionLogEntries`, `validateSessionReplayLogEntries` | Functions | Rebuild history from a log and report gaps |
|
|
184
|
+
| `SESSION_LOG_EVENT`, `SESSION_LOG_SCHEMA_VERSION` | Consts | The log event vocabulary and schema version |
|
|
185
|
+
| `resolveSessionLogExternalPayloads`, `NodeExternalPayloadSource`, `createSessionLogExternalPayloadReference` | Functions, class | Large log fields stored as separate payload files |
|
|
186
|
+
| `NodeToolResultSpillStore` | Class | Stores oversized tool results in files for the life of the session |
|
|
187
|
+
| `NodePromptHistoryFile` | Class | Append-only prompt history file that can be read newest-first |
|
|
188
|
+
|
|
189
|
+
`IContextWindowState` (the `getContextState()` result) is exported by `@robota-sdk/agent-core`.
|
|
129
190
|
|
|
130
191
|
## Session vs Robota
|
|
131
192
|
|
|
132
|
-
- **`Robota`** (agent-core):
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
store
|
|
143
|
-
|
|
144
|
-
Session-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
Streaming text deltas
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
`
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
- `
|
|
163
|
-
- `
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
content-addressed JSON payload references under `{sessionId}.payloads/`. `loadSessionLogEntries()`
|
|
181
|
-
hydrates those sidecars before replay and fails closed on malformed references, path/symlink escape,
|
|
182
|
-
missing or unreadable files, byte-length/hash mismatch, invalid JSON, cycles, or configured depth/byte
|
|
183
|
-
limits. Each source read receives the remaining aggregate byte budget; the Node adapter checks it before
|
|
184
|
-
allocation and reads from the same no-follow descriptor it validated. `session-log-replay` exports replay
|
|
185
|
-
readers and validators that reconstruct chat history from
|
|
186
|
-
`history_mutation` and report missing provider/tool terminal events; an unresolved history message or
|
|
187
|
-
normalized provider response is replay-incomplete. Replay validation also requires provider-native raw
|
|
188
|
-
response or stream payload coverage for each `provider_request`. Direct `NodeSessionLogSink` calls reject
|
|
189
|
-
unsafe session path components and reject payload digests that are malformed or do not hash the supplied
|
|
190
|
-
serialized content. Host and authority-backed sinks share
|
|
191
|
-
`createSessionLogExternalPayloadReference()` as the validation and reference-construction SSOT.
|
|
192
|
-
|
|
193
|
-
A migration script is available for upgrading session records from older formats. See the package source for details.
|
|
194
|
-
|
|
195
|
-
## Assembly
|
|
196
|
-
|
|
197
|
-
Most users should use `InteractiveSession` or `createQuery()` from `@robota-sdk/agent-framework` — or `createAgentRuntime().createSession()` for multi-session runtimes — instead of constructing `Session` directly. (`createSession()` itself is an internal assembly factory and is not part of the public entry.) The SDK wires tools, provider, and system prompt automatically from config and context.
|
|
193
|
+
- **`Robota`** (`agent-core`): the raw agent — conversation, tools and plugins. No permissions, no
|
|
194
|
+
hooks.
|
|
195
|
+
- **`Session`** (this package): `Robota` plus permissions, hooks, compaction, logging and
|
|
196
|
+
persistence. `@robota-sdk/agent-framework` builds its sessions from it.
|
|
197
|
+
|
|
198
|
+
## Persistence
|
|
199
|
+
|
|
200
|
+
`IInteractiveSessionRecord` carries the full conversation and resumable state. `NodeSessionStore`
|
|
201
|
+
saves the record without inspecting its payload. It is a host adapter: passing it a directory does
|
|
202
|
+
not establish workspace trust. `@robota-sdk/agent-framework` instead adapts a trusted project's
|
|
203
|
+
state storage to the same store port.
|
|
204
|
+
|
|
205
|
+
When a `Session` re-saves an existing record, it keeps the fields it does not own and refreshes only
|
|
206
|
+
its live conversation, history, prompt, schema, path and timestamp fields. A resumed session must
|
|
207
|
+
reuse the record ID for its new turns to update that record; a session without a store stays
|
|
208
|
+
transient.
|
|
209
|
+
|
|
210
|
+
## Session logs and replay
|
|
211
|
+
|
|
212
|
+
`FileSessionLogger` writes versioned JSONL through an injected `ISessionLogSink`. It redacts common
|
|
213
|
+
secret fields and stores large fields as content-addressed JSON payload files under
|
|
214
|
+
`{sessionId}.payloads/`. Streaming text deltas go to the log as `text_delta` events; keep
|
|
215
|
+
high-frequency output in logs and the session record focused on resumable state.
|
|
216
|
+
|
|
217
|
+
`Session.run()` forwards core execution events into the log, including `provider_request`,
|
|
218
|
+
`provider_native_raw_payload`, `provider_stream_raw_delta`, `provider_response_raw`,
|
|
219
|
+
`provider_response_normalized`, `assistant_message_committed`, `tool_batch_started`,
|
|
220
|
+
`tool_execution_request`, `tool_execution_result`, `tool_message_committed` and `history_mutation`.
|
|
221
|
+
`SESSION_LOG_EVENT` is the complete vocabulary that writers and readers share.
|
|
222
|
+
|
|
223
|
+
Reading is source-driven: `loadSessionLogEntries(source)` takes an explicit `ISessionLogSource` and
|
|
224
|
+
never turns a filename into file-system access on its own. Use `NodeSessionLogSource` when the
|
|
225
|
+
application owns the path. Every declared event is validated before replay, nested messages
|
|
226
|
+
included; unknown events, malformed fields and unsupported versions raise `SessionLogDecodeError`,
|
|
227
|
+
and unversioned logs are not accepted. Payload files are read with an aggregate byte budget and
|
|
228
|
+
checked for path escape, symlink replacement, size and hash mismatch; a failure is reported rather
|
|
229
|
+
than skipped. `replaySessionLogEntries` rebuilds the chat history from `history_mutation` events, and
|
|
230
|
+
`validateSessionReplayLogEntries` reports missing provider or tool events.
|
|
231
|
+
|
|
232
|
+
Manual and automatic compaction carry one trigger value (`manual` or `auto`) to `PreCompact`,
|
|
233
|
+
`PostCompact`, the `context_compact` log entry and `onCompactEvent`.
|
|
234
|
+
|
|
235
|
+
## Legacy session migration
|
|
236
|
+
|
|
237
|
+
From `packages/agent-session` in the repository, `node scripts/migrate-session-history.mjs
|
|
238
|
+
--sessions-dir <absolute-directory>` backfills history in legacy session files. It rewrites the files
|
|
239
|
+
in that directory, so back them up first. `node examples/verify-session-history-migration.mjs`
|
|
240
|
+
checks the conversion on disposable files without touching your sessions.
|
|
198
241
|
|
|
199
242
|
## Dependencies
|
|
200
243
|
|
|
201
|
-
- `@robota-sdk/agent-core`
|
|
244
|
+
- `@robota-sdk/agent-core` — the `Robota` agent, permissions, hooks and core types
|
|
245
|
+
- `@robota-sdk/agent-interface-session` — the session record and store contracts
|
|
246
|
+
- `@robota-sdk/agent-interface-execution` — background task contracts stored in the session record
|
|
247
|
+
- `@robota-sdk/agent-file-authority` — bounded, root-relative file reads for log payloads
|
|
202
248
|
|
|
203
|
-
##
|
|
249
|
+
## Documentation
|
|
204
250
|
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
legacy session files; back them up first. The disposable example
|
|
208
|
-
`node examples/verify-session-history-migration.mjs` checks conversion without using your stored
|
|
209
|
-
sessions. See [Session Data Migration](./docs/SPEC.md) for the exact policy.
|
|
251
|
+
- [docs/SPEC.md](./docs/SPEC.md) — package contract, invariants and design decisions
|
|
252
|
+
- [Hook event catalog](../agent-core/docs/HOOK-CATALOG.md)
|
|
210
253
|
|
|
211
254
|
## License
|
|
212
255
|
|