@robota-sdk/agent-sdk 3.0.0-beta.6 → 3.0.0-beta.60

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/README.md CHANGED
@@ -1,8 +1,8 @@
1
1
  # @robota-sdk/agent-sdk
2
2
 
3
- Programmatic SDK for building AI agents with Robota. Provides a single `query()` entry point along with Session management, built-in tools, permissions, hooks, streaming, and context loading.
3
+ Programmatic SDK for building AI agents with Robota. Provides `InteractiveSession` as the central client-facing API, `query()` for one-shot use, session management, built-in tools, permissions, hooks, streaming, and context loading.
4
4
 
5
- This is the **assembly layer** of the Robota ecosystem -- it composes lower-level packages (`agent-core`, `agent-tools`, `agent-sessions`) into a cohesive SDK.
5
+ This is the **assembly layer** of the Robota ecosystem it composes lower-level packages (`agent-core`, `agent-tools`, `agent-sessions`, `agent-provider-anthropic`) into a cohesive SDK.
6
6
 
7
7
  ## Installation
8
8
 
@@ -31,39 +31,369 @@ const response = await query('Analyze the code', {
31
31
 
32
32
  ## Features
33
33
 
34
- - **query()** -- Single entry point for AI agent interactions with streaming support
35
- - **Session** -- Wraps the Robota engine with permission checks, tool wiring, history, and streaming
36
- - **Built-in Tools** -- Bash, Read, Write, Edit, Glob, Grep (from `@robota-sdk/agent-tools`)
37
- - **Agent Tool** -- Sub-agent session creation for multi-agent workflows
38
- - **Permissions** -- 3-step evaluation (deny list, allow list, mode policy) with four modes: `plan`, `default`, `acceptEdits`, `bypassPermissions`
39
- - **Hooks** -- `PreToolUse`, `PostToolUse`, `SessionStart`, `Stop` events with shell command execution
40
- - **Streaming** -- Real-time text delta callbacks via `onTextDelta`
41
- - **Context Loading** -- AGENTS.md / CLAUDE.md walk-up discovery and system prompt assembly
42
- - **Config Loading** -- 3-layer merge (user global, project, local) with `$ENV:VAR` substitution
43
- - **Context Window Management** -- Token tracking, auto-compaction at ~83.5%, manual `session.compact()`
34
+ - **InteractiveSession** — Event-driven session wrapper (composition over Session). Central client-facing API for CLI, web, API server, or any other client
35
+ - **SystemCommandExecutor + ISystemCommand** SDK-level command execution infrastructure for product-composed command modules
36
+ - **CommandRegistry, BuiltinCommandSource, SkillCommandSource** Slash command registry and discovery (owned by SDK; agent-cli re-exports `CommandRegistry` from here)
37
+ - **query()** Single entry point for one-shot AI agent interactions with streaming support
38
+ - **createSession()** Assembly factory: wires tools, provider, config, and context into a Session
39
+ - **Built-in Tools** Bash, Read, Write, Edit, Glob, Grep, WebFetch, WebSearch are assembled for sessions; six local file/process/search exports are re-exported from `@robota-sdk/agent-tools`
40
+ - **Agent Tool** Sub-agent session creation for multi-agent workflows
41
+ - **Permissions** 3-step evaluation (deny list, allow list, mode policy) with four modes: `plan`, `default`, `acceptEdits`, `bypassPermissions`
42
+ - **Hooks** `PreToolUse`, `PostToolUse`, `PreCompact`, `PostCompact`, `SessionStart`, `UserPromptSubmit`, `Stop` events with shell command execution
43
+ - **Streaming** Real-time text delta callbacks via `onTextDelta`
44
+ - **Context Loading** — AGENTS.md / CLAUDE.md walk-up discovery and system prompt assembly
45
+ - **Config Loading** — 6-file settings merge with provider profiles, legacy provider compatibility, and `$ENV:VAR` substitution for provider API keys
46
+ - **Context Window Management** — Token tracking, configurable auto-compaction (default ~83.5%), manual `session.compact()`
47
+ - **Background Jobs** — Runtime-managed subagent tasks with transcripts and task snapshots
48
+ - **Agent Batch Jobs** — `Agent({ jobs: [...] })` starts explicit parallel subagent requests deterministically
49
+ - **Edit Checkpoints** — Checkpoint/rewind support for safer edit workflows
50
+ - **Project Memory** — Command-driven memory capture and retrieval surfaces
51
+ - **Replay Events** — Session execution can forward provider/tool boundary events into append-only logs
52
+ - **Bundle Plugin System** — Install and manage reusable extensions packaged as bundle plugins
44
53
 
45
54
  ## Architecture
46
55
 
47
56
  ```
48
57
  agent-sdk (assembly layer)
49
- -> agent-sessions (Session, SessionStore)
50
- -> agent-tools (tool infrastructure + 6 built-in tools)
51
- -> agent-core (Robota engine, providers, permissions, hooks)
58
+ ├── InteractiveSession ← central client-facing API (event-driven)
59
+ └── Session ← generic session (agent-sessions)
60
+ ├── SystemCommandExecutor SDK-level command execution
61
+ ├── CommandRegistry / BuiltinCommandSource / SkillCommandSource
62
+ ├── Agent tool batch jobs and background orchestration
63
+ ├── Edit checkpoints and command-driven memory
64
+ ├── query() ← one-shot entry point
65
+ ├── createSession() ← assembly factory
66
+ └── deps:
67
+ agent-sessions (Session, SessionStore)
68
+ agent-tools (tool infrastructure + 8 built-in tools)
69
+ agent-provider-anthropic (Anthropic LLM provider)
70
+ agent-core (Robota engine, providers, permissions, hooks)
71
+
72
+ agent-cli (TUI layer — bridges InteractiveSession events to React/Ink state)
73
+ → agent-sdk
52
74
  ```
53
75
 
54
- `agent-sdk` assembles existing packages -- it does not re-implement functionality that belongs in lower layers.
76
+ The SDK is **pure TypeScript with no React dependency**. The CLI is a thin TUI-only layer that consumes `InteractiveSession` events and maps them to React state. Any other client (web app, API server, worker) can do the same.
77
+
78
+ ## API
79
+
80
+ ### InteractiveSession — Central Client-Facing API
81
+
82
+ `InteractiveSession` wraps `Session` (composition over inheritance) to provide event-driven interaction for any client. It manages streaming text accumulation, tool execution state tracking, prompt queuing, abort orchestration, and message history. Logic that was previously embedded in CLI React hooks now lives here.
83
+
84
+ ```typescript
85
+ import { InteractiveSession } from '@robota-sdk/agent-sdk';
86
+ import type { IInteractiveSessionOptions } from '@robota-sdk/agent-sdk';
87
+
88
+ const session = new InteractiveSession({
89
+ config,
90
+ context,
91
+ projectInfo,
92
+ sessionStore, // SessionStore instance for persistence
93
+ resumeSessionId, // Session ID to restore (optional)
94
+ forkSession, // Session ID to fork from (optional)
95
+ permissionMode: 'default',
96
+ maxTurns: 10,
97
+ cwd: process.cwd(),
98
+ permissionHandler: async (toolName, toolArgs) => ({ allowed: true }),
99
+ });
100
+
101
+ // Subscribe to events
102
+ session.on('text_delta', (delta: string) => {
103
+ process.stdout.write(delta); // streaming text chunk
104
+ });
105
+ session.on('tool_start', (state) => {
106
+ console.log(`Running: ${state.toolName}`);
107
+ });
108
+ session.on('tool_end', (state) => {
109
+ console.log(`Done: ${state.toolName} — ${state.result}`);
110
+ });
111
+ session.on('thinking', (isThinking: boolean) => {
112
+ // show/hide spinner
113
+ });
114
+ session.on('complete', (result) => {
115
+ console.log(result.response);
116
+ });
117
+ session.on('error', (error: Error) => {
118
+ console.error(error);
119
+ });
120
+ session.on('context_update', (state) => {
121
+ // token usage updated
122
+ });
123
+ session.on('interrupted', (result) => {
124
+ // abort completed
125
+ });
126
+
127
+ // Submit a prompt (queues if already executing, max 1 queued)
128
+ await session.submit('Explain this code');
129
+
130
+ // Submit with display override (shown in UI) and raw input (for hook matching)
131
+ await session.submit(fullPrompt, '/audit', '/rulebased-harness:audit');
132
+
133
+ // Abort current execution and clear queue
134
+ session.abort();
135
+
136
+ // Cancel queued prompt without aborting current execution
137
+ session.cancelQueue();
138
+
139
+ // Execute system commands
140
+ const result = await session.executeCommand('context', '');
141
+ // result.message, result.success, result.data
142
+
143
+ // List all registered system commands
144
+ session.listCommands(); // Array<{ name, description }>
145
+
146
+ // State queries
147
+ session.isExecuting(); // boolean
148
+ session.getPendingPrompt(); // string | null
149
+ session.getMessages(); // TUniversalMessage[]
150
+ session.getContextState(); // IContextWindowState
151
+ session.getStreamingText(); // string (accumulated so far)
152
+ session.getActiveTools(); // IToolState[]
153
+
154
+ // Session naming
155
+ session.getName(); // string | undefined
156
+ session.setName('my-task'); // sets the session name
157
+
158
+ // Access underlying Session for advanced use
159
+ session.getSession(); // Session
160
+ ```
161
+
162
+ ### SystemCommandExecutor — SDK-Level Commands
163
+
164
+ `SystemCommandExecutor` executes named system commands against an `InteractiveSession`. Commands are pure TypeScript — no React, no TUI dependency. The CLI wraps them as slash commands with UI chrome.
165
+
166
+ ```typescript
167
+ import { SystemCommandExecutor, createSystemCommands } from '@robota-sdk/agent-sdk';
168
+ import type { ICommandResult } from '@robota-sdk/agent-sdk';
169
+
170
+ const executor = new SystemCommandExecutor(); // starts empty unless commands are supplied
171
+
172
+ // Execute a command
173
+ const result: ICommandResult | null = await executor.execute('status', session, '');
174
+ if (result) {
175
+ console.log(result.message); // "OK"
176
+ }
177
+
178
+ // Register a custom command
179
+ executor.register({
180
+ name: 'status',
181
+ description: 'Show agent status',
182
+ execute: (session, args) => ({ message: 'OK', success: true }),
183
+ });
184
+
185
+ // List all commands
186
+ executor.listCommands(); // ISystemCommand[]
187
+ executor.hasCommand('mode'); // boolean
188
+ ```
189
+
190
+ Product built-ins are supplied as `agent-command-*` modules. For example, `/help` is owned by `@robota-sdk/agent-command-help`, while `/compact` is owned by `@robota-sdk/agent-command-compact`.
191
+
192
+ ### CommandRegistry, BuiltinCommandSource, SkillCommandSource
193
+
194
+ These classes provide slash command discovery and aggregation for clients that expose a command palette or autocomplete UI.
195
+
196
+ ```typescript
197
+ import { CommandRegistry, BuiltinCommandSource, SkillCommandSource } from '@robota-sdk/agent-sdk';
198
+
199
+ const registry = new CommandRegistry();
200
+ registry.addSource(new BuiltinCommandSource());
201
+ registry.addSource(new SkillCommandSource(process.cwd()));
202
+
203
+ // Get all commands (returns ICommand[])
204
+ const commands = registry.getCommands();
205
+
206
+ // Filter by prefix (for autocomplete)
207
+ const filtered = registry.getCommands('mod'); // matches "mode", "model"
208
+
209
+ // Resolve short plugin name to fully qualified form
210
+ registry.resolveQualifiedName('audit'); // "my-plugin:audit"
211
+ ```
212
+
213
+ `SkillCommandSource` discovers skills from (highest priority first):
214
+
215
+ - `<cwd>/.claude/skills/*/SKILL.md`
216
+ - `<cwd>/.claude/commands/*.md` (Claude Code compatible)
217
+ - `~/.robota/skills/*/SKILL.md`
218
+ - `<cwd>/.agents/skills/*/SKILL.md`
219
+
220
+ ### query()
221
+
222
+ ```typescript
223
+ import { query } from '@robota-sdk/agent-sdk';
224
+
225
+ const response = await query('Show me the file list');
226
+
227
+ const response = await query('Analyze the code', {
228
+ cwd: '/path/to/project',
229
+ permissionMode: 'acceptEdits',
230
+ maxTurns: 10,
231
+ autoCompactThreshold: 0.75,
232
+ onTextDelta: (delta) => process.stdout.write(delta),
233
+ onCompact: () => console.log('Context compacted'),
234
+ });
235
+ ```
55
236
 
56
- ## Session Usage
237
+ ### createSession()
57
238
 
58
239
  ```typescript
59
- import { Session } from '@robota-sdk/agent-sessions';
240
+ import { createSession, loadConfig, loadContext, detectProject } from '@robota-sdk/agent-sdk';
60
241
 
61
- const session = new Session({ config, context, terminal, permissionMode });
242
+ const [config, context, projectInfo] = await Promise.all([
243
+ loadConfig(cwd),
244
+ loadContext(cwd),
245
+ detectProject(cwd),
246
+ ]);
247
+
248
+ const session = createSession({ config, context, terminal, projectInfo, permissionMode });
62
249
  const response = await session.run('Hello');
63
- session.getHistory();
64
- session.clearHistory();
65
250
  ```
66
251
 
252
+ ### Built-in Tools
253
+
254
+ `@robota-sdk/agent-sdk` re-exports 6 of the 8 built-in tools from `@robota-sdk/agent-tools`:
255
+
256
+ ```typescript
257
+ import { bashTool, readTool, writeTool, editTool, globTool, grepTool } from '@robota-sdk/agent-sdk';
258
+ ```
259
+
260
+ `webFetchTool` and `webSearchTool` are **not** re-exported from `@robota-sdk/agent-sdk`. Import them directly from the owning package:
261
+
262
+ ```typescript
263
+ import { webFetchTool, webSearchTool } from '@robota-sdk/agent-tools';
264
+ ```
265
+
266
+ ## Subagent Sessions
267
+
268
+ `createSubagentSession()` creates an isolated child session for delegating subtasks. The subagent receives pre-resolved config and context from the parent — it does not load config files or context from disk. Callers may provide a stable `sessionId` and `sessionLogger` so the child session writes a durable transcript.
269
+
270
+ ```typescript
271
+ import { createSubagentSession } from '@robota-sdk/agent-sdk';
272
+
273
+ const subSession = createSubagentSession({
274
+ parentSession: session,
275
+ agentDefinition: 'explore',
276
+ prompt: 'Analyze the test coverage gaps',
277
+ });
278
+ const result = await subSession.run();
279
+ ```
280
+
281
+ ### Agent Definitions
282
+
283
+ `IAgentDefinition` describes a reusable agent configuration (system prompt, allowed tools, permission mode). Custom agents are discovered from `.robota/agents/` (project), `.claude/agents/` (Claude Code compatible), and `~/.robota/agents/` (user). `AgentDefinitionLoader` is an internal class — it is not part of the public API.
284
+
285
+ Built-in agents: `general-purpose` (full tool access), `Explore` (read-only, Haiku model), `Plan` (read-only planning).
286
+
287
+ ### createAgentTool()
288
+
289
+ `createAgentTool()` wraps subagent creation into a tool the AI can invoke directly. The parent session's hooks, permissions, and context are forwarded to the child.
290
+
291
+ Background subagent lifecycle events are persisted through `InteractiveSession` when a `SessionStore` is configured. Streaming chunks are written to append-only JSONL logs/transcripts rather than rewriting the main session JSON per token.
292
+
293
+ ## Hook Executors (SDK-Specific)
294
+
295
+ `agent-sdk` provides two `IHookTypeExecutor` implementations beyond the `command` and `http` executors in `agent-core`:
296
+
297
+ | Executor | Hook Type | Description |
298
+ | ---------------- | --------- | ------------------------------------------------------------------------- |
299
+ | `PromptExecutor` | `prompt` | Injects the hook's prompt text into the session as a system instruction |
300
+ | `AgentExecutor` | `agent` | Creates a sub-agent session to process the hook input and return a result |
301
+
302
+ ## Bundle Plugin System
303
+
304
+ Bundle plugins package reusable extensions (tools, hooks, permissions, system prompt additions) into installable units.
305
+
306
+ ### Types
307
+
308
+ | Type | Description |
309
+ | ----------------------- | --------------------------------------------------------------- |
310
+ | `IBundlePluginManifest` | Plugin metadata: name, version, description, author, keywords |
311
+ | `ILoadedBundlePlugin` | Full bundle: manifest + tools, hooks, permissions, systemPrompt |
312
+
313
+ ### BundlePluginLoader
314
+
315
+ Loads a bundle plugin from a directory path. Reads the manifest, resolves tool/hook definitions, and validates the bundle structure.
316
+
317
+ ### BundlePluginInstaller
318
+
319
+ Manages plugin installation and uninstallation:
320
+
321
+ - Installs bundles to `~/.robota/plugins/` (user) or `.robota/plugins/` (project)
322
+ - Tracks installed plugins in a registry file
323
+ - Handles enable/disable state per plugin
324
+
325
+ ## Configuration
326
+
327
+ Settings are merged from lowest to highest priority:
328
+
329
+ | Layer | Path | Scope |
330
+ | ----- | ----------------------------- | --------------------------------------- |
331
+ | 1 | `~/.robota/settings.json` | User global |
332
+ | 2 | `~/.claude/settings.json` | User global (Claude Code compatible) |
333
+ | 3 | `.robota/settings.json` | Project |
334
+ | 4 | `.robota/settings.local.json` | Project (local) |
335
+ | 5 | `.claude/settings.json` | Project (Claude Code compatible) |
336
+ | 6 | `.claude/settings.local.json` | Project (local, Claude Code compatible) |
337
+
338
+ `$ENV:VAR` substitution is applied after merge for provider API keys.
339
+
340
+ ```json
341
+ {
342
+ "defaultMode": "default",
343
+ "currentProvider": "qwen",
344
+ "providers": {
345
+ "qwen": {
346
+ "type": "qwen",
347
+ "model": "qwen-plus",
348
+ "apiKey": "$ENV:DASHSCOPE_API_KEY",
349
+ "baseURL": "https://dashscope-intl.aliyuncs.com/compatible-mode/v1"
350
+ },
351
+ "gemma": {
352
+ "type": "gemma",
353
+ "model": "supergemma4-26b-uncensored-v2",
354
+ "apiKey": "lm-studio",
355
+ "baseURL": "http://localhost:1234/v1"
356
+ },
357
+ "openai": {
358
+ "type": "openai",
359
+ "model": "<openai-compatible-model>",
360
+ "apiKey": "$ENV:OPENAI_API_KEY"
361
+ },
362
+ "anthropic": {
363
+ "type": "anthropic",
364
+ "model": "claude-sonnet-4-6",
365
+ "apiKey": "$ENV:ANTHROPIC_API_KEY"
366
+ }
367
+ },
368
+ "permissions": {
369
+ "allow": ["Bash(pnpm *)"],
370
+ "deny": ["Bash(rm -rf *)"]
371
+ }
372
+ }
373
+ ```
374
+
375
+ `currentProvider` selects the active entry from `providers`. Qwen Model Studio profiles use `type: "qwen"` with the documented DashScope OpenAI-compatible `baseURL`. Gemma-family local models should use a `type: "gemma"` profile so provider-specific stream projection is applied. The resolved SDK config normalizes the active profile into `provider.name`, `provider.model`, `provider.apiKey`, optional `provider.baseURL`, and optional `provider.timeout`. The legacy `provider` object remains supported when `currentProvider` is not configured.
376
+
377
+ ## Permission Modes
378
+
379
+ | Mode | Read/Glob/Grep | Write/Edit | Bash |
380
+ | ------------------- | :------------: | :--------: | :-----: |
381
+ | `plan` | auto | deny | deny |
382
+ | `default` | auto | approve | approve |
383
+ | `acceptEdits` | auto | auto | approve |
384
+ | `bypassPermissions` | auto | auto | auto |
385
+
386
+ ## Dependencies
387
+
388
+ | Package | Purpose |
389
+ | -------------------------------------- | ------------------------------------- |
390
+ | `@robota-sdk/agent-core` | Engine, providers, permissions, hooks |
391
+ | `@robota-sdk/agent-sessions` | Session, SessionStore |
392
+ | `@robota-sdk/agent-tools` | Tool infrastructure + built-in tools |
393
+ | `@robota-sdk/agent-provider-anthropic` | Anthropic LLM provider |
394
+ | `chalk` | Terminal colors (permission prompt) |
395
+ | `zod` | Settings schema validation |
396
+
67
397
  ## Documentation
68
398
 
69
399
  See [docs/SPEC.md](./docs/SPEC.md) for the full specification, architecture details, and design decisions.