@robota-sdk/agent-framework 3.0.0-beta.64

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/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2024 Robota Contributors
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/README.md ADDED
@@ -0,0 +1,513 @@
1
+ # @robota-sdk/agent-framework
2
+
3
+ Programmatic SDK for building AI agents with Robota. Provides `InteractiveSession` as the central client-facing API, `createQuery()` for one-shot use, session management, SDK-owned command/common APIs, permissions, hooks, streaming, context loading, bounded prompt file references, and context reference inventory.
4
+
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
+
7
+ ## Installation
8
+
9
+ ```bash
10
+ npm install @robota-sdk/agent-framework
11
+ # or
12
+ pnpm add @robota-sdk/agent-framework
13
+ ```
14
+
15
+ ## Quick Start
16
+
17
+ ```typescript
18
+ import { createQuery } from '@robota-sdk/agent-framework';
19
+ import { AnthropicProvider } from '@robota-sdk/agent-provider/anthropic';
20
+
21
+ const provider = new AnthropicProvider({ apiKey: process.env.ANTHROPIC_API_KEY });
22
+ const query = createQuery({ provider });
23
+
24
+ // Simple one-shot query
25
+ const response = await query('Show me the file list');
26
+
27
+ // With options
28
+ const queryWithOptions = createQuery({
29
+ provider,
30
+ cwd: '/path/to/project',
31
+ permissionMode: 'acceptEdits',
32
+ maxTurns: 10,
33
+ onTextDelta: (delta) => process.stdout.write(delta),
34
+ });
35
+
36
+ const detailedResponse = await queryWithOptions('Analyze the code');
37
+ ```
38
+
39
+ ## Features
40
+
41
+ - **InteractiveSession** — Event-driven session wrapper (composition over Session). Central client-facing API for CLI, web, API server, or any other client
42
+ - **SystemCommandExecutor + ISystemCommand** — SDK-level command execution infrastructure for product-composed command modules
43
+ - **CommandRegistry, BuiltinCommandSource, SkillCommandSource** — Command registry and SDK common discovery APIs. User-visible built-ins are composed through `agent-command-*` packages.
44
+ - **Model Command Common APIs** — Provider-neutral `/model` helpers that resolve active provider catalogs and optionally invoke provider-owned refresh hooks
45
+ - **createQuery()** — Provider-bound factory for one-shot AI agent interactions with streaming support
46
+ - **Session assembly** — Internal factory wires tools, provider, config, and context for `InteractiveSession`
47
+ - **Built-in Tools** — Bash, Read, Write, Edit, Glob, Grep, WebFetch, WebSearch are assembled for SDK sessions; direct tool usage imports from `@robota-sdk/agent-tools`
48
+ - **Sandbox Execution** — Optional `sandboxClient` injection routes Bash and core file tools through a provider-backed execution plane; `workspaceManifest` can prepare a fresh sandbox workspace before session creation
49
+ - **Sandbox Hydration** — Snapshot-capable sandbox clients persist `sandboxSnapshotId` on shutdown and restore it before saved message replay on non-fork resume
50
+ - **Agent Tool** — Sub-agent session creation for multi-agent workflows
51
+ - **Permissions** — 3-step evaluation (deny list, allow list, mode policy) with four modes: `plan`, `default`, `acceptEdits`, `bypassPermissions`
52
+ - **Hooks** — `PreToolUse`, `PostToolUse`, `PreCompact`, `PostCompact`, `SessionStart`, `UserPromptSubmit`, `Stop` events with shell command execution
53
+ - **Streaming** — Real-time text delta callbacks via `onTextDelta`
54
+ - **Context Loading** — AGENTS.md / CLAUDE.md walk-up discovery and system prompt assembly
55
+ - **Prompt File References** — Path-like `@file` prompt references are resolved by the SDK under the session `cwd`, bounded by size/recursion limits, recorded as structured history events, and registered as observed context references
56
+ - **Context Reference Inventory** — Manual `/context add` references are stored by `InteractiveSession`, included in future prompt model input, and exposed through SDK command common APIs
57
+ - **Config Loading** — 6-file settings merge with provider profiles, legacy provider compatibility, and `$ENV:VAR` substitution for provider credentials
58
+ - **Context Window Management** — Token tracking, configurable auto-compaction (default ~83.5%), manual `session.compact()`
59
+ - **Background Jobs** — Runtime-managed subagent tasks with transcripts and task snapshots
60
+ - **Agent Batch Jobs** — `Agent({ jobs: [...] })` starts explicit parallel subagent requests deterministically
61
+ - **Edit Checkpoints** — Checkpoint/rewind support for safer edit workflows
62
+ - **Project Memory** — Command-driven memory capture and retrieval surfaces
63
+ - **Replay Events** — Session execution can forward provider/tool boundary events and provider-native raw payload events into append-only logs
64
+ - **Bundle Plugin System** — Install and manage reusable extensions packaged as bundle plugins
65
+
66
+ ## Architecture
67
+
68
+ ```
69
+ agent-sdk (assembly layer)
70
+ ├── InteractiveSession ← central client-facing API (event-driven)
71
+ │ └── Session ← generic session (agent-sessions)
72
+ ├── SystemCommandExecutor ← SDK-level command execution
73
+ ├── CommandRegistry / BuiltinCommandSource / SkillCommandSource
74
+ ├── Agent runtime dependencies and background orchestration
75
+ ├── Edit checkpoints and command-driven memory
76
+ ├── createQuery() ← one-shot entry point factory
77
+ ├── createSession() ← internal assembly factory
78
+ └── deps:
79
+ agent-sessions (Session, SessionStore)
80
+ agent-tools (tool infrastructure + 8 built-in tools)
81
+ agent-provider-anthropic (Anthropic LLM provider)
82
+ agent-core (Robota engine, providers, permissions, hooks)
83
+
84
+ agent-cli (TUI layer — bridges InteractiveSession events to React/Ink state)
85
+ → agent-sdk
86
+ ```
87
+
88
+ 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.
89
+
90
+ ## API
91
+
92
+ ### InteractiveSession — Central Client-Facing API
93
+
94
+ `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.
95
+
96
+ ```typescript
97
+ import { InteractiveSession, createProjectSessionStore } from '@robota-sdk/agent-framework';
98
+ import type { IInteractiveSessionOptions } from '@robota-sdk/agent-framework';
99
+
100
+ const cwd = process.cwd();
101
+ const sessionStore = createProjectSessionStore(cwd);
102
+
103
+ const session = new InteractiveSession({
104
+ config,
105
+ context,
106
+ projectInfo,
107
+ sessionStore, // SDK-owned project-local persistence facade
108
+ resumeSessionId, // Session ID to restore, including sandbox snapshot when available
109
+ forkSession, // Session ID to fork from (optional)
110
+ permissionMode: 'default',
111
+ maxTurns: 10,
112
+ cwd,
113
+ permissionHandler: async (toolName, toolArgs) => ({ allowed: true }),
114
+ });
115
+
116
+ // Subscribe to events
117
+ session.on('text_delta', (delta: string) => {
118
+ process.stdout.write(delta); // streaming text chunk
119
+ });
120
+ session.on('tool_start', (state) => {
121
+ console.log(`Running: ${state.toolName}`);
122
+ });
123
+ session.on('tool_end', (state) => {
124
+ console.log(`Done: ${state.toolName} — ${state.result}`);
125
+ });
126
+ session.on('thinking', (isThinking: boolean) => {
127
+ // show/hide spinner
128
+ });
129
+ session.on('complete', (result) => {
130
+ console.log(result.response);
131
+ });
132
+ session.on('error', (error: Error) => {
133
+ console.error(error);
134
+ });
135
+ session.on('context_update', (state) => {
136
+ // token usage updated
137
+ });
138
+ session.on('interrupted', (result) => {
139
+ // abort completed
140
+ });
141
+
142
+ // Submit a prompt (queues if already executing, max 1 queued)
143
+ await session.submit('Explain this code');
144
+
145
+ // Path-like @file references are expanded into model-only prompt context by the SDK.
146
+ // The user-visible history keeps the original prompt plus a structured file-reference event.
147
+ await session.submit('Explain @AGENTS.md and @docs/SPEC.md');
148
+
149
+ // Submit with display override (shown in UI) and raw input (for hook matching)
150
+ await session.submit(fullPrompt, '/audit', '/rulebased-harness:audit');
151
+
152
+ // Execute slash commands through the command layer. With the skills command module composed,
153
+ // `/audit src/index.ts` is normalized by SDK to command "skills" with args "audit src/index.ts".
154
+ await session.executeCommand('audit', 'src/index.ts');
155
+
156
+ // Abort current execution and clear queue
157
+ session.abort();
158
+
159
+ // Cancel queued prompt without aborting current execution
160
+ session.cancelQueue();
161
+
162
+ // Execute system commands
163
+ const result = await session.executeCommand('context', '');
164
+ // result.message, result.success, result.data
165
+
166
+ // List all registered system commands
167
+ session.listCommands(); // Array<{ name, description }>
168
+
169
+ // State queries
170
+ session.isExecuting(); // boolean
171
+ session.getPendingPrompt(); // string | null
172
+ session.getMessages(); // TUniversalMessage[]
173
+ session.getContextState(); // IContextWindowState
174
+ session.getStreamingText(); // string (accumulated so far)
175
+ session.getActiveTools(); // IToolState[]
176
+
177
+ // Session naming
178
+ session.getName(); // string | undefined
179
+ session.setName('my-task'); // sets the session name
180
+
181
+ // Access underlying Session for advanced use
182
+ session.getSession(); // Session
183
+ ```
184
+
185
+ ### SystemCommandExecutor — SDK-Level Commands
186
+
187
+ `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.
188
+
189
+ ```typescript
190
+ import { SystemCommandExecutor, createSystemCommands } from '@robota-sdk/agent-framework';
191
+ import type { ICommandResult } from '@robota-sdk/agent-framework';
192
+
193
+ const executor = new SystemCommandExecutor(); // starts empty unless commands are supplied
194
+
195
+ // Execute a command
196
+ const result: ICommandResult | null = await executor.execute('status', session, '');
197
+ if (result) {
198
+ console.log(result.message); // "OK"
199
+ }
200
+
201
+ // Register a custom command
202
+ executor.register({
203
+ name: 'status',
204
+ description: 'Show agent status',
205
+ execute: (session, args) => ({ message: 'OK', success: true }),
206
+ });
207
+
208
+ // List all commands
209
+ executor.listCommands(); // ISystemCommand[]
210
+ executor.hasCommand('permissions'); // boolean
211
+ ```
212
+
213
+ SDK core does not own user-visible built-in commands. Product built-ins are supplied as `agent-command-*` modules. SDK command identity is slash-free (`skills`, `help`, `compact`); UI shells render and parse those commands as slash syntax such as `/skills`, `/help`, and `/compact`.
214
+
215
+ Command modules may use SDK common APIs for shared provider-neutral behavior. For `/model`, the SDK
216
+ resolves the active provider from settings, reads provider-owned fallback metadata from injected
217
+ `IProviderDefinition` records, and can invoke provider-owned catalog refresh hooks. The CLI/TUI must
218
+ only render command results and must not own provider model lists.
219
+
220
+ For provider setup, the SDK projects provider-owned setup help links from `IProviderDefinition`
221
+ records into generic prompt descriptions. The CLI/TUI renders those descriptions without owning
222
+ provider-specific API key or console URLs.
223
+
224
+ For `/permissions`, the SDK owns permission-mode constants, subcommand descriptors, validation,
225
+ state formatting, and command-host adapter access. The command module owns user-visible behavior and
226
+ keeps permission-mode changes under `/permissions [mode]`.
227
+
228
+ For `/validate-session`, the session command module calls SDK session command APIs to locate and
229
+ validate the current JSONL session log. Hosts may override `validateCurrentSessionReplayLog()` in
230
+ `ICommandHostContext` when they own a non-file-backed session log store.
231
+
232
+ ### CommandRegistry, BuiltinCommandSource, SkillCommandSource
233
+
234
+ These classes provide slash command discovery and aggregation for clients that expose a command palette or autocomplete UI.
235
+
236
+ ```typescript
237
+ import { CommandRegistry } from '@robota-sdk/agent-framework';
238
+ import { createSkillsCommandModule } from '@robota-sdk/agent-command-skills';
239
+
240
+ const registry = new CommandRegistry();
241
+ registry.addModule(createSkillsCommandModule({ cwd: process.cwd() }));
242
+
243
+ // Get all commands (returns ICommand[])
244
+ const commands = registry.getCommands();
245
+
246
+ // Filter by prefix (for autocomplete)
247
+ const filtered = registry.getCommands('mod'); // matches "mode", "model"
248
+
249
+ // Resolve short plugin name to fully qualified form
250
+ registry.resolveQualifiedName('audit'); // "my-plugin:audit"
251
+ ```
252
+
253
+ `SkillCommandSource` is the SDK common API used by the skills command module. It discovers skills from (highest priority first):
254
+
255
+ - `<cwd>/.claude/skills/*/SKILL.md`
256
+ - `<cwd>/.claude/commands/*.md` (Claude Code compatible)
257
+ - `~/.robota/skills/*/SKILL.md`
258
+ - `<cwd>/.agents/skills/*/SKILL.md`
259
+
260
+ Model-invocable skills are exposed to the model as metadata only when the session has a composed
261
+ model-invocable `skills` command descriptor. `@robota-sdk/agent-command-skills` owns `skills` and
262
+ activates skills through the SDK host API. Models use the SDK-projected `robota_command_skills`
263
+ tool with skill arguments in `args`. Mentioning a skill in ordinary prose,
264
+ recommending a skill in assistant text, or matching a natural-language phrase in SDK/TUI code does
265
+ not activate the skill.
266
+
267
+ ### createQuery()
268
+
269
+ ```typescript
270
+ import { createQuery } from '@robota-sdk/agent-framework';
271
+ import { AnthropicProvider } from '@robota-sdk/agent-provider/anthropic';
272
+
273
+ const provider = new AnthropicProvider({ apiKey: process.env.ANTHROPIC_API_KEY });
274
+ const query = createQuery({ provider });
275
+
276
+ const response = await query('Show me the file list');
277
+
278
+ const queryWithOptions = createQuery({
279
+ provider,
280
+ cwd: '/path/to/project',
281
+ permissionMode: 'acceptEdits',
282
+ maxTurns: 10,
283
+ onTextDelta: (delta) => process.stdout.write(delta),
284
+ });
285
+
286
+ const detailedResponse = await queryWithOptions('Analyze the code');
287
+ ```
288
+
289
+ ### Session Assembly
290
+
291
+ `createSession()`, `loadConfig()`, `loadContext()`, and `detectProject()` are internal SDK assembly
292
+ details. Use `InteractiveSession` for event-driven sessions or `createQuery()` for prompt-only
293
+ one-shot calls.
294
+
295
+ ### Built-in Tools
296
+
297
+ `@robota-sdk/agent-framework` assembles built-in tools for SDK sessions, but direct tool usage imports
298
+ from the owner package:
299
+
300
+ ```typescript
301
+ import {
302
+ bashTool,
303
+ editTool,
304
+ globTool,
305
+ grepTool,
306
+ readTool,
307
+ webFetchTool,
308
+ webSearchTool,
309
+ writeTool,
310
+ } from '@robota-sdk/agent-tools';
311
+ ```
312
+
313
+ ### Sandbox Execution
314
+
315
+ SDK sessions can receive a provider-neutral sandbox client. When provided, Bash, Read, Write, and Edit use the sandbox execution plane instead of the host process/filesystem:
316
+
317
+ ```typescript
318
+ import { InteractiveSession } from '@robota-sdk/agent-framework';
319
+ import { AnthropicProvider } from '@robota-sdk/agent-provider/anthropic';
320
+ import { E2BSandboxClient } from '@robota-sdk/agent-tools';
321
+ import type { IWorkspaceManifest } from '@robota-sdk/agent-tools';
322
+ import { Sandbox } from 'e2b';
323
+
324
+ const provider = new AnthropicProvider({ apiKey: process.env.ANTHROPIC_API_KEY });
325
+ const sandbox = await Sandbox.create();
326
+ const workspaceManifest: IWorkspaceManifest = {
327
+ entries: {
328
+ 'task.md': { type: 'file', content: 'Review this repository.\n' },
329
+ repo: { type: 'gitRepo', url: 'https://github.com/example/project.git', ref: 'main' },
330
+ output: { type: 'dir' },
331
+ },
332
+ };
333
+
334
+ const session = new InteractiveSession({
335
+ cwd: process.cwd(),
336
+ provider,
337
+ sandboxClient: new E2BSandboxClient({ sandbox }),
338
+ workspaceManifest,
339
+ reversibleExecution: { mode: 'local-first' },
340
+ });
341
+ ```
342
+
343
+ `E2BSandboxClient` is a structural adapter owned by `agent-tools`, and it does not make `e2b` a dependency of `agent-sdk`. Install and create the concrete provider SDK in the application layer, then pass the adapter into `InteractiveSession`. `workspaceManifest` also uses the `agent-tools` contract; SDK applies it once before constructing the underlying `Session`.
344
+
345
+ When `sessionStore` and a snapshot-capable `sandboxClient` are both provided, `InteractiveSession.shutdown()` stores `sandboxSnapshotId` in the session record. A later non-fork `resumeSessionId` restore calls `sandboxClient.restore(snapshotId)` before saved messages are injected back into the `Session`. Forked sessions intentionally do not hydrate the previous sandbox reference because provider pause/resume references can be one-to-one.
346
+
347
+ ## Subagent Sessions
348
+
349
+ `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.
350
+
351
+ ```typescript
352
+ import { createSubagentSession } from '@robota-sdk/agent-framework';
353
+
354
+ const subSession = createSubagentSession({
355
+ parentSession: session,
356
+ agentDefinition: 'explore',
357
+ prompt: 'Analyze the test coverage gaps',
358
+ });
359
+ const result = await subSession.run();
360
+ ```
361
+
362
+ ### Agent Definitions
363
+
364
+ `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.
365
+
366
+ Built-in agents: `general-purpose` (full tool access), `Explore` (read-only, Haiku model), `Plan` (read-only planning).
367
+
368
+ ### createAgentTool()
369
+
370
+ `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.
371
+
372
+ Background subagent lifecycle events are persisted through `InteractiveSession` when an SDK session persistence facade is configured. Streaming chunks are written to append-only JSONL logs/transcripts rather than rewriting the main session JSON per token.
373
+
374
+ ## Replay-Grade Session Events
375
+
376
+ `Session.run()` forwards core execution events through the session logger. Current events include provider request envelopes, provider-native raw request/response/stream payloads, provider-normalized responses, assistant message commits, tool batch starts, tool execution requests, and tool execution results.
377
+
378
+ Provider-native payload events are emitted by concrete provider packages through `IChatOptions.onProviderNativeRawPayload`, then redacted and externalized by the session logger before they are written to disk. The SDK exposes session command APIs so command modules such as `/validate-session` can validate replay coverage without adding file-log logic to CLI/TUI hosts.
379
+
380
+ ## Hook Executors (SDK-Specific)
381
+
382
+ `agent-sdk` provides two `IHookTypeExecutor` implementations beyond the `command` and `http` executors in `agent-core`:
383
+
384
+ | Executor | Hook Type | Description |
385
+ | ---------------- | --------- | ------------------------------------------------------------------------- |
386
+ | `PromptExecutor` | `prompt` | Injects the hook's prompt text into the session as a system instruction |
387
+ | `AgentExecutor` | `agent` | Creates a sub-agent session to process the hook input and return a result |
388
+
389
+ ## Bundle Plugin System
390
+
391
+ Bundle plugins package reusable extensions (tools, hooks, permissions, system prompt additions) into installable units.
392
+
393
+ ### Types
394
+
395
+ | Type | Description |
396
+ | ----------------------- | --------------------------------------------------------------- |
397
+ | `IBundlePluginManifest` | Plugin metadata: name, version, description, author, keywords |
398
+ | `ILoadedBundlePlugin` | Full bundle: manifest + tools, hooks, permissions, systemPrompt |
399
+
400
+ ### BundlePluginLoader
401
+
402
+ Loads a bundle plugin from a directory path. Reads the manifest, resolves tool/hook definitions, and validates the bundle structure.
403
+
404
+ ### BundlePluginInstaller
405
+
406
+ Manages plugin installation and uninstallation:
407
+
408
+ - Installs bundles to `~/.robota/plugins/` (user) or `.robota/plugins/` (project)
409
+ - Tracks installed plugins in a registry file
410
+ - Handles enable/disable state per plugin
411
+
412
+ ## Plugins
413
+
414
+ `agent-plugin-*` packages are **consumer opt-in** — they are not built into the CLI or SDK by default. Application consumers register plugins at composition time by passing plugin instances to the SDK assembly API.
415
+
416
+ ```typescript
417
+ import { InteractiveSession } from '@robota-sdk/agent-framework';
418
+ import { AnthropicProvider } from '@robota-sdk/agent-provider/anthropic';
419
+ import { ConversationHistoryPlugin } from '@robota-sdk/agent-plugin';
420
+ import { LoggingPlugin } from '@robota-sdk/agent-plugin';
421
+
422
+ const session = new InteractiveSession({
423
+ cwd: process.cwd(),
424
+ config,
425
+ context,
426
+ plugins: [
427
+ new ConversationHistoryPlugin({ maxMessages: 100 }),
428
+ new LoggingPlugin({ level: 'info' }),
429
+ ],
430
+ });
431
+ ```
432
+
433
+ Each plugin implements `AbstractPlugin` from `@robota-sdk/agent-core` and depends only on `agent-core`. Available plugins: `agent-plugin-conversation-history`, `agent-plugin-error-handling`, `agent-plugin-event-emitter`, `agent-plugin-execution-analytics`, `agent-plugin-limits`, `agent-plugin-logging`, `agent-plugin-performance`, `agent-plugin-usage`, `agent-plugin-webhook`.
434
+
435
+ ## Configuration
436
+
437
+ Settings are merged from lowest to highest priority:
438
+
439
+ | Layer | Path | Scope |
440
+ | ----- | ----------------------------- | --------------------------------------- |
441
+ | 1 | `~/.robota/settings.json` | User global |
442
+ | 2 | `~/.claude/settings.json` | User global (Claude Code compatible) |
443
+ | 3 | `.robota/settings.json` | Project |
444
+ | 4 | `.robota/settings.local.json` | Project (local) |
445
+ | 5 | `.claude/settings.json` | Project (Claude Code compatible) |
446
+ | 6 | `.claude/settings.local.json` | Project (local, Claude Code compatible) |
447
+
448
+ `$ENV:VAR` substitution is applied after merge for provider API keys.
449
+
450
+ ```json
451
+ {
452
+ "defaultMode": "default",
453
+ "currentProvider": "qwen",
454
+ "providers": {
455
+ "qwen": {
456
+ "type": "qwen",
457
+ "model": "qwen-plus",
458
+ "apiKey": "$ENV:DASHSCOPE_API_KEY",
459
+ "baseURL": "https://dashscope-intl.aliyuncs.com/compatible-mode/v1"
460
+ },
461
+ "gemma": {
462
+ "type": "gemma",
463
+ "model": "supergemma4-26b-uncensored-v2",
464
+ "apiKey": "lm-studio",
465
+ "baseURL": "http://localhost:1234/v1"
466
+ },
467
+ "openai": {
468
+ "type": "openai",
469
+ "model": "<openai-compatible-model>",
470
+ "apiKey": "$ENV:OPENAI_API_KEY"
471
+ },
472
+ "anthropic": {
473
+ "type": "anthropic",
474
+ "model": "claude-sonnet-4-6",
475
+ "apiKey": "$ENV:ANTHROPIC_API_KEY"
476
+ }
477
+ },
478
+ "permissions": {
479
+ "allow": ["Bash(pnpm *)"],
480
+ "deny": ["Bash(rm -rf *)"]
481
+ }
482
+ }
483
+ ```
484
+
485
+ `currentProvider` selects the active entry from `providers`. Qwen Model Studio profiles use `type: "qwen"` with the documented DashScope OpenAI-compatible `baseURL`. DeepSeek API profiles use `type: "deepseek"` with the documented DeepSeek 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.
486
+
487
+ ## Permission Modes
488
+
489
+ | Mode | Read/Glob/Grep | Write/Edit | Bash |
490
+ | ------------------- | :------------: | :--------: | :-----: |
491
+ | `plan` | auto | deny | deny |
492
+ | `default` | auto | approve | approve |
493
+ | `acceptEdits` | auto | auto | approve |
494
+ | `bypassPermissions` | auto | auto | auto |
495
+
496
+ ## Dependencies
497
+
498
+ | Package | Purpose |
499
+ | -------------------------------------- | ------------------------------------- |
500
+ | `@robota-sdk/agent-core` | Engine, providers, permissions, hooks |
501
+ | `@robota-sdk/agent-session` | Session, SessionStore |
502
+ | `@robota-sdk/agent-tools` | Tool infrastructure + built-in tools |
503
+ | `@robota-sdk/agent-provider/anthropic` | Anthropic LLM provider |
504
+ | `chalk` | Terminal colors (permission prompt) |
505
+ | `zod` | Settings schema validation |
506
+
507
+ ## Documentation
508
+
509
+ See [docs/SPEC.md](./docs/SPEC.md) for the full specification, architecture details, and design decisions.
510
+
511
+ ## License
512
+
513
+ MIT