Skip to content

Sessions Specification

Scope

Owns the CLI session lifecycle for the Robota SDK. This package provides the Session class that wraps a Robota agent instance with permission-gated tool execution, hook-based lifecycle events, context window tracking, conversation compaction, and optional JSON file persistence via SessionStore. It is the primary runtime used by the CLI application (agent-cli) via the assembly layer (agent-sdk).

Boundaries

  • Does not own AI provider creation. Accepts a pre-constructed IAIProvider via injection.
  • Does not own tool implementations. Accepts pre-constructed IToolWithEventService[] via injection.
  • Does not own system prompt building. Accepts a pre-built systemMessage string.
  • Does not own configuration resolution or context loading. Those belong to agent-sdk.
  • Does not own the permission evaluation algorithm or hook execution engine. Those belong to @robota-sdk/agent-core (evaluatePermission, runHooks).
  • Owns the session persistence port. SessionStore and ISessionRecord are the SSOT for conversation session persistence contracts. Storage adapters implement these interfaces; the port interface must not be duplicated in other packages. Consumers obtain a session store through SDK facades (createProjectSessionStore) rather than constructing SessionStore directly.

Architecture Overview

The package follows a modular structure with Session delegating to focused sub-components:

session.ts                -- Session class: orchestrates run loop, delegates to sub-components
session-run.ts            -- Per-turn Session.run execution helper and replay-event forwarding
session-tool-execution-bridge.ts -- Bridges unknown-tool replay events to onToolExecution display callbacks
permission-enforcer.ts    -- PermissionEnforcer: tool wrapping, permission checks, hooks, truncation
context-window-tracker.ts -- ContextWindowTracker: token usage tracking, auto-compact threshold
compaction-orchestrator.ts -- CompactionOrchestrator: conversation summarization via LLM
session-logger.ts         -- ISessionLogger interface + FileSessionLogger / SilentSessionLogger
session-store.ts          -- SessionStore: JSON file persistence for conversation sessions

Design patterns used:

  • Facade -- Session hides Robota agent creation, tool registration, permission wiring, and hook execution behind a single run() method.
  • Decorator -- Each tool is wrapped with a permission-checking proxy via PermissionEnforcer.wrapTools() before being registered with the Robota agent.
  • Adapter -- session-tool-execution-bridge adapts core replay events for unregistered tool calls into the same UI callback shape used by wrapped registered tools.
  • Strategy (injected) -- Permission approval can be handled by a TPermissionHandler callback, an injected promptForApproval function, or denied by default.
  • Composition -- Session delegates to PermissionEnforcer, ContextWindowTracker, and CompactionOrchestrator rather than implementing everything inline.
  • Null Object -- When no SessionStore is provided, persistence is silently skipped.

Dependency direction:

  • @robota-sdk/agent-session depends on @robota-sdk/agent-core only.
  • No dependency on @robota-sdk/agent-tools or @robota-sdk/agent-provider/anthropic.
  • Tool and provider assembly is the responsibility of the consuming layer (agent-sdk).

Type Ownership

Types owned by this package (SSOT):

TypeKindFileDescription
ISessionInterfacesession-interface.tsMinimal session abstraction: { readonly sessionId: string }. Used by agent-interface-transport to break the circular dep with agent-sdk. InteractiveSession in agent-sdk implements this interface.
ISessionOptionsInterfacesession.tsConstructor options for Session (tools, provider, systemMessage, providerTimeout, optional sessionId)
ISessionShutdownOptionsInterfacesession-types.tsGraceful shutdown options, including Claude-compatible reason
TPermissionHandlerTypepermission-enforcer.tsAsync callback (toolName, toolArgs) => Promise<TPermissionResult>
TPermissionResultTypepermission-enforcer.tsboolean | 'allow-session'
ITerminalOutputInterfacepermission-enforcer.tsTerminal I/O abstraction (write, prompt, select, spinner)
ISpinnerInterfacepermission-enforcer.tsSpinner handle returned by ITerminalOutput.spinner()
IPermissionEnforcerOptionsInterfacepermission-enforcer.tsOptions for constructing PermissionEnforcer
ICompactionOptionsInterfacecompaction-orchestrator.tsOptions for constructing CompactionOrchestrator
ISessionLoggerInterfacesession-logger.tsPluggable session event logger interface
TSessionLogDataTypesession-logger.tsStructured log event data (Record<string, string | number | boolean | object | null>)
IExternalPayloadReferenceInterfacesession-logger.tsContent-addressed JSON payload reference used when a log field exceeds inline size policy
ISessionReplayRecordInterfacesession-log-replay.tsReconstructed replay state from append-only JSONL logs
ISessionRecordInterfacesession-store.tsPersisted session record (id, cwd, timestamps, messages, history, opaque diagnostic extension fields)

Types consumed from other packages (not owned here):

TypeSource
Robota@robota-sdk/agent-core
IAgentConfig@robota-sdk/agent-core
IAIProvider@robota-sdk/agent-core
IToolWithEventService@robota-sdk/agent-core
TPermissionMode@robota-sdk/agent-core
TToolArgs@robota-sdk/agent-core
THooksConfig@robota-sdk/agent-core
IHookInput@robota-sdk/agent-core
evaluatePermission@robota-sdk/agent-core
runHooks@robota-sdk/agent-core
TRUST_TO_MODE@robota-sdk/agent-core
TUniversalMessage@robota-sdk/agent-core
IHistoryEntry@robota-sdk/agent-core

Public API Surface

ExportKindDescription
ISessionInterfaceMinimal session abstraction { readonly sessionId: string } used by agent-interface-transport
SessionClassWraps Robota agent with permissions, hooks, streaming, and persistence
PermissionEnforcerClassTool permission checking, hook execution, output truncation
ContextWindowTrackerClassToken usage tracking and auto-compact threshold
CompactionOrchestratorClassConversation compaction via LLM summary
SessionStoreClassJSON file persistence for session records (~/.robota/sessions/)
FileSessionLoggerClassJSONL file-based session event logger
SilentSessionLoggerClassNo-op session logger
ISessionOptionsInterfaceConstructor options for Session
ISessionShutdownOptionsInterfaceGraceful shutdown options for Session.shutdown()
TAutoCompactThresholdTypeAuto-compact threshold fraction, or false to disable automatic compaction
TPermissionHandlerTypeCustom permission approval callback
TPermissionResultTypePermission decision result
ITerminalOutputInterfaceTerminal I/O abstraction
ISpinnerInterfaceSpinner handle
IPermissionEnforcerOptionsInterface (internal)Options for constructing PermissionEnforcernot exported from src/index.ts. Internal to the package.
ISessionLoggerInterfacePluggable session event logger interface
TSessionLogDataTypeStructured log event data
ISessionRecordInterfacePersisted session record shape
ISessionStoreInterfaceMinimal persistence port consumed by Session; implemented by SessionStore
IContextWindowStateTypeContext window usage state (re-exported from agent-core)

Session Constructor — sessionId Parameter

ISessionOptions.sessionId is an optional parameter. When provided, the Session reuses that ID. When omitted, a fresh UUID is generated (default). This allows the consuming layer to control whether a resumed session continues under the same file or creates a new one.

ISessionOptions.providerTimeout is an optional provider idle timeout in milliseconds. When provided, Session forwards it to the underlying Robota IAgentConfig.timeout, where agent-core enforces it per provider call and refreshes the idle timer on streaming text deltas.

ISessionOptions.maxTurns is an optional maximum number of model/tool rounds for one Session.run() call. When provided, Session forwards it to Robota.run() as maxExecutionRounds. When omitted, Session forwards maxExecutionRounds: 0, which means the session run has no core round cap and is instead bounded by abort, context-window checks, provider idle timeout, and runtime-level controls.

ISessionOptions.onContextUpdate is an optional callback fired from the session runtime whenever ContextWindowTracker is refreshed. It fires before the provider call using the assembled request history estimate and again after the provider response is committed with exact provider usage when available. Consumers such as InteractiveSession forward it as context_update.

ISessionOptions.autoCompactThreshold controls the initial automatic compaction trigger as a 0 < value <= 1 fraction. The default is 0.835. Set it to false when an embedding runtime manages compaction externally. Session.setAutoCompactThreshold() may change this policy after construction; subsequent run() calls use the new policy immediately.

ISessionOptions.onCompactEvent receives structured compaction metadata with trigger, before, and after context-window states. Manual Session.compact() calls report trigger: "manual" by default; auto-compaction from Session.run() reports trigger: "auto". The session logger also writes a context_compact event with the same before/after state so headless transports and logs can explain what happened without streaming compaction summary text into the normal answer path.

Key Session Methods

MethodSignatureDescription
run(message: string) => Promise<string>Send a message; returns AI response. Persists session if store exists.
getPermissionMode() => TPermissionModeReturns the active permission mode.
setPermissionMode(mode: TPermissionMode) => voidChanges the permission mode for future tool calls.
getSessionId() => stringReturns the stable session identifier.
getMessageCount() => numberReturns the number of completed run() calls.
clearHistory() => voidClears the underlying Robota conversation history and resets token usage.
getHistory() => TUniversalMessage[]Returns the current conversation history as TUniversalMessage[] (chat entries only). Unchanged.
getFullHistory() => IHistoryEntry[]Returns the full history as IHistoryEntry[], including both chat messages and event entries (e.g., tool summaries).
addHistoryEntry(entry: IHistoryEntry) => voidAppends a pre-built IHistoryEntry (e.g., a tool-summary event entry) to the session history via ConversationStore.addEntry().
getContextState() => IContextWindowStateReturns real-time effective context window usage (tokens, percentage) from the shared agent-core estimator.
getAutoCompactThreshold() => TAutoCompactThresholdReturns the configured automatic compaction threshold, or false when disabled.
setAutoCompactThreshold(threshold: TAutoCompactThreshold) => voidUpdates the automatic compaction threshold for subsequent run() calls.
compact(instructions?: string) => Promise<void>Compresses conversation via LLM summary. System message is preserved across compaction (see below). Fires PreCompact/PostCompact hooks.
abort() => voidCancels the currently running run() call. No-op if not running.
shutdown(options?: ISessionShutdownOptions) => Promise<void>Aborts active work, persists the session when a store exists, logs shutdown, and fires SessionEnd exactly once.
isRunning() => booleanReturns true if a run() call is in progress.
getSessionAllowedTools() => string[]Returns tools that were session-approved ("Allow always").
clearSessionAllowedTools() => voidClears all session-scoped allow rules.
injectMessage(role: 'user' | 'assistant' | 'system', content: string) => voidInjects a message into conversation history without triggering an AI response. Used for restoring context on session resume.

Usage And Context Refresh

Session.run() performs two context refreshes per successful prompt:

  1. Pre-send estimate -- after hooks and request payload assembly, ContextWindowTracker.updateFromHistory() receives the current history plus the enriched user message. This emits estimated context usage before the provider responds.
  2. Post-response reconciliation -- after the assistant response is committed, ContextWindowTracker.updateFromHistory() reads exact provider token metadata when available and emits the reconciled context state.

The callback payload is provider-neutral IContextWindowState; provider-specific usage details remain in message metadata and are interpreted by higher layers only through normalized token fields.

ISessionRecord Fields

FieldTypeRequiredDescription
idstringYesUnique session identifier
cwdstringYesWorking directory where the session was created
namestringNoUser-assigned session name for easy identification
createdAtstringYesISO timestamp of session creation
updatedAtstringYesISO timestamp of last update
messagesunknown[]YesAI provider messages (TUniversalMessage[]) for context restoration. Saved from session.getHistory(), replayed via session.injectMessage() on resume.
historyunknown[]YesFull UI timeline (IHistoryEntry[] — chat + events) for rendering restoration. Passed to TuiStateManager on resume.
systemPromptstringNoExact system prompt used to create the session. Duplicates the system message in messages intentionally so diagnostics can inspect prompt composition directly.
toolSchemasunknown[]NoTool schemas registered for the session, including model-invocable projected command tools such as robota_command_skills.
backgroundTasksunknown[]NoLatest persisted background task snapshots.
backgroundTaskEventsunknown[]NoDurable background task lifecycle/progress events needed for resume/debugging, including text deltas when the SDK persists background streams.
backgroundJobGroupsunknown[]NoLatest persisted background job group snapshots for agent/runtime orchestration resume.
backgroundJobGroupEventsunknown[]NoDurable background job group lifecycle events needed for resume/debugging.
memoryEventsunknown[]NoSDK-owned automatic memory audit events such as extracted, queued, saved, skipped, approved, rejected, and retrieved.
usedMemoryReferencesunknown[]NoSDK-owned provenance records for memory topics injected into the latest prompt turn.
contextReferencesunknown[]NoSDK-owned context reference inventory for resume/debugging.
sandboxSnapshotIdstringNoProvider-owned sandbox workspace reference used by SDK resume hydration. agent-sessions stores this value opaquely and does not import sandbox packages.

Memory event and used-reference fields are audit/debug data, not baseline user-local preferences. Inspectable user-local memory is governed by ../../../.agents/specs/user-local-memory.md. Session records must not become a command source or hidden preference store.

Session Data Migration

scripts/migrate-session-history.mjs backfills the history field for sessions created before this field existed. It converts messages[] to IHistoryEntry[] format. Safe to run multiple times — skips sessions that already have history. Run once after upgrading.

Key SessionStore Methods

MethodSignatureDescription
save(session: ISessionRecord) => voidPersist a session record to disk. Creates directory if needed.
load(id: string) => ISessionRecord | undefinedLoad a session by ID. Returns undefined if not found.
list() => ISessionRecord[]List all sessions, sorted by updatedAt descending.
delete(id: string) => voidDelete a session file. No-ops if not found.

Session Logging

The session log records structured events to a JSONL file for diagnostics and replay. Logs must preserve enough raw data to reconstruct what was sent to the model and what came back:

  • session_init event -- Recorded when a session is constructed. Includes systemPrompt, systemPromptLength, provider/model, cwd, and registered toolSchemas.
  • server_tool event -- Recorded when a server-managed tool (e.g., web search) executes during streaming. Includes the tool name and query.
  • pre_run event -- Recorded at the start of each run() call. Includes the provider name, provider-native web capability/enabled state, full enriched input, and current message history before the model call.
  • provider_request event -- Recorded before each provider call. Includes the provider-neutral request envelope: provider, model, messages, tool schemas/options, round, and execution identifiers.
  • provider_native_raw_payload event -- Recorded when a provider package reports an SDK-native request, response, or stream event through IChatOptions.onProviderNativeRawPayload. Includes provider, optional API surface, payload kind, sequence, payload, round, and execution identifiers. This event is provider-owned at capture time; Session only persists it through the existing logger.
  • provider_stream_raw_delta event -- Recorded for each provider text delta observed by the core streaming callback. Includes sequence, delta, round, and execution identifiers.
  • provider_response_raw event -- Recorded immediately after provider chat() returns and before core validates/extracts the assistant message. Includes the provider-returned response object and responseKind.
  • provider_response_normalized event -- Recorded immediately after the provider adapter returns a TUniversalMessage. Includes the normalized assistant message, tool call count, provider/model metadata, round, and execution identifiers.
  • tool_batch_started event -- Recorded before a tool batch executes. Includes batch mode, max concurrency, request count, ordered tool names, round, and execution identifiers.
  • tool_execution_request event -- Recorded for each parsed tool request. Includes tool name, toolCallId/executionId, parsed parameters, batch index, owner path, round, and execution identifiers.
  • tool_execution_result event -- Recorded for each terminal tool result. Includes tool name, toolCallId/executionId, success/error, result payload when available, result metadata, batch index, round, and execution identifiers.
  • tool_message_committed event -- Recorded when a tool result message is appended to canonical history.
  • history_mutation event -- Recorded for append-only canonical chat history changes used by replay readers.
  • text_delta event -- Recorded for each streaming text chunk delivered through ISessionOptions.onTextDelta. This is append-only JSONL data and must be available while a run is still in progress.
  • assistant event -- Recorded after each assistant response. Includes full assistant content, full post-run history, and historyStructure: an array with per-message metadata (role, contentLength, hasToolCalls, toolCallNames, metadata).
  • session_shutdown event -- Recorded once when Session.shutdown() begins. Includes the Claude-compatible shutdown reason.
  • Provider-native web configuration -- Session calls IAIProvider.configureNativeWebTools?.({ webSearch: true }) during construction. Providers that own auto-enabled hosted web behavior may implement the hook; Session must not branch on concrete provider names or import provider packages.
  • onServerToolUse callback wiring -- When session logging is enabled, the onServerToolUse callback from the provider is automatically wired to emit server_tool log events.

FileSessionLogger applies recursive secret redaction before persistence. Keys such as apiKey, authorization, accessToken, refreshToken, secret, password, and xApiKey are replaced with [REDACTED]. Log fields larger than the inline threshold are stored as content-addressed JSON payload files in {sessionId}.payloads/{sha256}.json, and the JSONL line stores an IExternalPayloadReference.

session-log-replay.ts owns replay readers and validators. replaySessionLogEntries() reconstructs provider messages and chat history from history_mutation events. validateSessionReplayLogEntries() reports missing provider-native raw payloads, missing provider-normalized raw responses, missing normalized responses, unmatched tool requests/results, and invalid external payload references. Every provider_request must be paired with at least one provider_native_raw_payload event for the same executionId/round whose payloadKind is response or stream_event, plus the existing provider_response_raw and provider_response_normalized events.

Hook Lifecycle

Session fires Claude Code-compatible lifecycle hooks through runHooks:

  • SessionStart fires once when a Session is constructed.
  • UserPromptSubmit fires before each model turn and may inject stdout into the next prompt.
  • Stop fires after each successful assistant response and includes response, last_assistant_message, and stop_hook_active.
  • StopFailure fires when a model turn errors and includes reason.
  • SessionEnd fires exactly once from Session.shutdown(), after local persistence, and includes the Claude-compatible reason.

Extension Points

  1. ISessionOptions.terminal (required) -- Inject an ITerminalOutput implementation for permission prompts and UI output. The consuming layer provides either a real terminal (CLI print mode) or an Ink-based no-op (TUI mode).

  2. ISessionOptions.tools -- Inject any set of IToolWithEventService[]. The consuming layer (agent-sdk) provides the default 8 tools + agent-tool.

  3. ISessionOptions.provider -- Inject any IAIProvider. The consuming layer (agent-sdk) creates the appropriate provider from config.

  4. ISessionOptions.systemMessage -- Inject the pre-built system prompt string. The consuming layer (agent-sdk) builds this from AGENTS.md, CLAUDE.md, tool descriptions, and trust level.

  5. ISessionOptions.permissionHandler -- Inject a custom permission approval callback (used by Ink-based UI to show approval prompts in React components).

  6. ISessionOptions.promptForApproval -- Alternative approval function that receives the terminal handle.

  7. ISessionOptions.onTextDelta -- Streaming callback for real-time text output to the UI. Session stores this callback and passes it to Robota.run() as a per-run option; it MUST NOT mutate provider-level onTextDelta state because parent/subagent sessions may share the same provider instance.

  8. ISessionOptions.onToolExecution -- Callback for real-time tool execution events. Fires { type: 'start', toolName, toolArgs } when a tool begins and { type: 'end', toolName, toolArgs, success, denied?, toolResultData? } when it completes. toolResultData is the serialized, possibly truncated tool result payload used by higher layers for display metadata such as Edit start lines. Registered tool execution is wired through PermissionEnforcer.wrapToolWithPermission(). Unregistered tool calls are not wrapped by PermissionEnforcer, so Session bridges core replay events into the same callback with success: false, errorCode: "unknown_tool", and the reason the tool call was not executed. The bridge must not duplicate registered tool events.

  9. ISessionOptions.onCompact -- Callback invoked when compaction occurs (auto or manual), receives the generated summary string.

  10. ISessionOptions.compactInstructions -- Custom instructions for the compaction summary prompt (e.g., extracted from CLAUDE.md "Compact Instructions" section).

  11. ISessionOptions.maxTurns -- Optional model/tool round cap passed to the underlying Robota run. Omitted means unlimited for the session layer.

  12. ISessionOptions.autoCompactThreshold -- Optional automatic compaction threshold. A number is interpreted as a fraction of the context window; false disables automatic compaction.

  13. SessionStore constructor -- Accept a custom baseDir to redirect storage location (useful in tests).

Abort Behavior

The Session class supports aborting an in-progress run() call via AbortController.

Mechanism

  • session.abort() calls AbortController.abort() on the controller created for the current run() call.
  • session.isRunning() returns true while a run() call is in progress.

Session.run() Abort Flow

  1. Session.run() creates an AbortController and passes { signal } to robota.run().
  2. Signal propagates through ExecutionService -> executeRound -> callProviderWithCache -> provider.chat() -> streamWithAbort.
  3. When abort is signalled, executeRound calls commitAssistant('interrupted') on ConversationStore before returning. This saves the partial response (with state: 'interrupted') to conversation history. Text is ALWAYS preserved (no stripping).
  4. robota.run() always returns normally on abort — it does not throw. The result includes interrupted: true.
  5. After robota.run() returns, Session.run() checks signal.aborted. If true, it throws DOMException('Aborted', 'AbortError').
  6. The post-run check in Session.run() is the sole source of AbortErrorrobota.run() itself never throws on abort.

Compaction Behavior

System Message Preservation

When compact() runs, the system message (project context: cwd, AGENTS.md, CLAUDE.md, tool descriptions, etc.) is preserved across compaction. The flow:

  1. Exclude system messages from the summarization input — they are not summarized
  2. Clear conversation history
  3. Re-inject the original system message
  4. Inject the compact summary as an assistant message

Post-compaction history:

[system]    Original system prompt (project context, rules, tool descriptions)
[assistant] [Context Summary] Summarized conversation...

This ensures the AI retains project context (working directory, coding rules, available tools) after compaction. Without this, the AI loses awareness of the project environment.

Auto-Compaction

Auto-compaction triggers at the start of run() (before processing the user message) when ContextWindowTracker.shouldAutoCompact() returns true. This prevents compaction from interfering with the current response stream. The trigger defaults to 83.5% of the context window and can be configured per session or disabled with autoCompactThreshold: false.

ContextWindowTracker.updateFromHistory() delegates token estimation to agent-core's shared context estimator. The tracker treats terminal provider usage as exact post-response state; when metadata-free messages follow the latest provider usage, it uses the maximum of serialized-history estimate, latest provider usage, and any future caller floor instead of summing all historical provider input counts. This keeps /context, status bars, automatic compaction, and core hard-capacity guards aligned on the same effective context state.

Error Taxonomy

This package does not define a custom error hierarchy. All errors are thrown as standard Error instances. Error scenarios include:

Error ConditionThrown ByMessage Pattern
Tool permission deniedPermissionEnforcerReturns IToolResult with "Permission denied" (no throw)
Hook blocked toolPermissionEnforcerReturns IToolResult with "Blocked by hook: {reason}"
Tool execution errorPermissionEnforcerReturns IToolResult with error message (never throws)
Unknown tool callExecutionServiceReturns a failed tool result with errorCode: "unknown_tool" and explains that execution was skipped

The permission wrapper deliberately catches all errors and returns them as IToolResult objects to avoid corrupting the conversation history with unmatched tool_use/tool_result pairs.

Session.run() Error Recovery

When run() encounters an error (e.g., from the execution loop or provider), the Session must:

  1. Log the error — write an error event to the session logger with the error details
  2. Preserve history — conversation history up to the point of failure remains intact
  3. Remain usable — the session is not corrupted; the user can continue or retry
  4. Propagate the error — re-throw after logging so the caller can handle it (e.g., display an error message)

Class Contract Registry

Interface Implementations

No formal interface implementations. Session, PermissionEnforcer, ContextWindowTracker, CompactionOrchestrator, and SessionStore are standalone classes.

Inheritance Chains

None. Classes are standalone.

Cross-Package Port Consumers

Port (Owner)Consumer ClassLocation
Robota (agent-core)Sessionsrc/session.ts
IAIProvider (agent-core)Sessionsrc/session.ts
evaluatePermission (agent-core)PermissionEnforcersrc/permission-enforcer.ts
runHooks (agent-core)PermissionEnforcersrc/permission-enforcer.ts
runHooks (agent-core)Sessionsrc/session.ts (PostCompact)
runHooks (agent-core)CompactionOrchestratorsrc/compaction-orchestrator.ts

Test Strategy

Current Test Coverage

  • Session system prompt delivery -- 6 tests verifying system prompt is passed to Robota at both top-level and defaultModel.
  • Session provider callback isolation -- 1 regression test verifying two sessions sharing one provider keep onTextDelta output isolated per run.

Gaps

  • Session -- permission mode switching, hook integration, and session persistence are untested.
  • PermissionEnforcer -- wrapTools(), checkPermission(), session-scoped allow, tool truncation are untested.
  • ContextWindowTracker -- updateFromHistory(), shouldAutoCompact(), metadata vs fallback estimation are untested.
  • CompactionOrchestrator -- compact(), hook firing, prompt building are untested.
  • SessionStore -- Covered by agent-sdk/src/__tests__/session-store.test.ts (12 tests: save/load/list/delete/directory creation).
  • FileSessionLogger -- log(), file creation, JSONL formatting, error handling on read-only paths are untested.
  • SilentSessionLogger -- No-op behavior untested (trivial, low priority).
  • All classes should be testable with mock IAIProvider and mock ITerminalOutput injections.

Dependencies

Production (1)

  • @robota-sdk/agent-core -- Robota agent, permission system, hook system, core types

Released under the MIT License.