@robota-sdk/agent-cli 3.0.0-beta.6 → 3.0.0-beta.61
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 +313 -109
- package/dist/node/bin.js +12 -1
- package/dist/node/chunk-BENOH47A.js +287 -0
- package/dist/node/chunk-J654S773.js +5541 -0
- package/dist/node/index.cjs +5481 -986
- package/dist/node/index.d.cts +68 -24
- package/dist/node/index.d.ts +68 -24
- package/dist/node/index.js +12 -8
- package/dist/node/subagents/child-process-subagent-worker.d.ts +2 -0
- package/dist/node/subagents/child-process-subagent-worker.js +123 -0
- package/package.json +48 -7
- package/dist/node/bin.cjs +0 -1217
- package/dist/node/bin.d.cts +0 -1
- package/dist/node/chunk-4DYVT4WI.js +0 -1196
package/README.md
CHANGED
|
@@ -1,9 +1,11 @@
|
|
|
1
1
|
# @robota-sdk/agent-cli
|
|
2
2
|
|
|
3
|
-
AI coding assistant CLI built on Robota SDK. Loads AGENTS.md/CLAUDE.md for project context and provides tool-calling REPL with Claude Code-compatible permission modes.
|
|
3
|
+
AI coding assistant CLI built on Robota SDK. Loads AGENTS.md/CLAUDE.md for project context and provides a tool-calling REPL with Claude Code-compatible permission modes.
|
|
4
4
|
|
|
5
5
|
## Installation
|
|
6
6
|
|
|
7
|
+
Requires Node.js 22+.
|
|
8
|
+
|
|
7
9
|
```bash
|
|
8
10
|
# Global install
|
|
9
11
|
npm install -g @robota-sdk/agent-cli
|
|
@@ -12,6 +14,8 @@ npm install -g @robota-sdk/agent-cli
|
|
|
12
14
|
npx @robota-sdk/agent-cli
|
|
13
15
|
```
|
|
14
16
|
|
|
17
|
+
> **macOS users**: Korean/CJK IME input may crash macOS Terminal.app. Use **[iTerm2](https://iterm2.com/)** instead. This is a known Ink + Terminal.app issue shared with Claude Code.
|
|
18
|
+
|
|
15
19
|
After installing globally, the `robota` command is available system-wide:
|
|
16
20
|
|
|
17
21
|
```bash
|
|
@@ -22,9 +26,11 @@ robota -p "List all files" # Print mode (one-shot, exit after response)
|
|
|
22
26
|
|
|
23
27
|
### Environment Variables
|
|
24
28
|
|
|
25
|
-
| Variable | Description
|
|
26
|
-
| ------------------- |
|
|
27
|
-
| `ANTHROPIC_API_KEY` | Anthropic API key |
|
|
29
|
+
| Variable | Description | Required |
|
|
30
|
+
| ------------------- | ---------------------------------------------- | -------------- |
|
|
31
|
+
| `ANTHROPIC_API_KEY` | Anthropic API key for the `anthropic` provider | Anthropic only |
|
|
32
|
+
| `DEEPSEEK_API_KEY` | DeepSeek API key for the `deepseek` provider | DeepSeek only |
|
|
33
|
+
| `DASHSCOPE_API_KEY` | Alibaba Cloud Model Studio key for `qwen` | Qwen only |
|
|
28
34
|
|
|
29
35
|
Set your key before running:
|
|
30
36
|
|
|
@@ -35,11 +41,7 @@ export ANTHROPIC_API_KEY=sk-ant-...
|
|
|
35
41
|
## Development Setup (Monorepo)
|
|
36
42
|
|
|
37
43
|
```bash
|
|
38
|
-
#
|
|
39
|
-
cp packages/agent-cli/.env.example packages/agent-cli/.env
|
|
40
|
-
# Edit .env and set ANTHROPIC_API_KEY=sk-ant-...
|
|
41
|
-
|
|
42
|
-
# 2. Build dependencies and CLI
|
|
44
|
+
# Build dependencies and CLI
|
|
43
45
|
pnpm build:deps
|
|
44
46
|
pnpm --filter @robota-sdk/agent-cli build
|
|
45
47
|
```
|
|
@@ -50,7 +52,7 @@ pnpm --filter @robota-sdk/agent-cli build
|
|
|
50
52
|
# From monorepo root
|
|
51
53
|
cd packages/agent-cli
|
|
52
54
|
|
|
53
|
-
# Development mode (no build needed
|
|
55
|
+
# Development mode (no build needed)
|
|
54
56
|
pnpm dev
|
|
55
57
|
|
|
56
58
|
# Production mode (requires build)
|
|
@@ -71,73 +73,126 @@ robota -p "prompt" # Print mode (one-shot, exit after response)
|
|
|
71
73
|
robota -c # Continue last session
|
|
72
74
|
robota -r <session-id> # Resume session by ID
|
|
73
75
|
robota --model <model> # Model override (e.g., claude-sonnet-4-6)
|
|
76
|
+
robota --language <lang> # Response language (ko, en, ja, zh)
|
|
74
77
|
robota --permission-mode <mode> # plan | default | acceptEdits | bypassPermissions
|
|
75
78
|
robota --max-turns <n> # Limit agentic turns per interaction
|
|
79
|
+
robota --output-format <fmt> # text | json | stream-json (print mode)
|
|
80
|
+
robota --system-prompt <text> # Replace system prompt (print mode)
|
|
81
|
+
robota --append-system-prompt <text> # Append to system prompt (print mode)
|
|
82
|
+
robota --reset # Delete user settings and exit
|
|
83
|
+
robota --check-update # Check npm for a newer CLI version and exit
|
|
84
|
+
robota --disable-update-check # Skip interactive startup update check for this run
|
|
76
85
|
robota --version # Show version
|
|
77
86
|
```
|
|
78
87
|
|
|
79
|
-
|
|
88
|
+
### CLI Updates
|
|
80
89
|
|
|
81
|
-
|
|
90
|
+
Robota can check npm for a newer `@robota-sdk/agent-cli` version:
|
|
82
91
|
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
| `Read` | Read file contents with line numbers | `filePath` |
|
|
87
|
-
| `Write` | Write content to a file | `filePath` |
|
|
88
|
-
| `Edit` | Replace a string in a file | `filePath` |
|
|
89
|
-
| `Glob` | Find files matching a pattern | `pattern` |
|
|
90
|
-
| `Grep` | Search file contents with regex | `pattern` |
|
|
92
|
+
```bash
|
|
93
|
+
robota --check-update
|
|
94
|
+
```
|
|
91
95
|
|
|
92
|
-
|
|
96
|
+
When an update is available, Robota prints the npm global install command:
|
|
93
97
|
|
|
94
|
-
|
|
98
|
+
```bash
|
|
99
|
+
npm install -g '@robota-sdk/agent-cli@latest'
|
|
100
|
+
```
|
|
95
101
|
|
|
96
|
-
|
|
97
|
-
2. **Allow list** — if any allow pattern matches, the action is auto-approved
|
|
98
|
-
3. **Mode policy** — the active permission mode determines the decision
|
|
102
|
+
Robota does not implement its own updater and does not modify `~/.robota/settings.json` for update checks. Interactive startup checks use a user-level operational cache at `~/.robota/update-check.json` and can be skipped for one run with `--disable-update-check`. Print/headless mode (`robota -p`) does not perform automatic startup update checks so scripted stdout and stderr remain deterministic.
|
|
99
103
|
|
|
100
|
-
|
|
104
|
+
### Print Mode Output Formats
|
|
101
105
|
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
+
Print mode (`-p`) supports three output formats via `--output-format`:
|
|
107
|
+
|
|
108
|
+
| Format | Description |
|
|
109
|
+
| ------------- | ------------------------------------------------------------------ |
|
|
110
|
+
| `text` | Plain text response to stdout (default) |
|
|
111
|
+
| `json` | Single JSON object: `{ type, result, session_id, subtype }` |
|
|
112
|
+
| `stream-json` | Newline-delimited JSON with `content_block_delta` streaming events |
|
|
113
|
+
|
|
114
|
+
### Stdin Pipe
|
|
115
|
+
|
|
116
|
+
When `-p` is used without a positional argument and stdin is piped, the CLI reads from stdin:
|
|
117
|
+
|
|
118
|
+
```bash
|
|
119
|
+
echo "Explain this error" | robota -p
|
|
120
|
+
cat file.ts | robota -p "Review this code" --output-format json
|
|
121
|
+
git diff | robota -p "Summarize changes" --output-format stream-json
|
|
106
122
|
```
|
|
107
123
|
|
|
108
|
-
-
|
|
109
|
-
- Press Enter or type anything else to deny
|
|
124
|
+
## First-Run Setup
|
|
110
125
|
|
|
111
|
-
|
|
126
|
+
When no usable settings file exists, the CLI prompts for:
|
|
112
127
|
|
|
113
|
-
|
|
128
|
+
1. **Provider selection** from the providers assembled into the CLI binary
|
|
129
|
+
2. **Provider-specific setup fields** such as model, base URL, and masked API key
|
|
130
|
+
3. **Response language** (ko/en/ja/zh, default: en)
|
|
114
131
|
|
|
115
|
-
|
|
116
|
-
| ------------------- | -------- | :------------: | :--------: | :-----: |
|
|
117
|
-
| `plan` | safe | auto | deny | deny |
|
|
118
|
-
| `default` | moderate | auto | approve | approve |
|
|
119
|
-
| `acceptEdits` | full | auto | auto | approve |
|
|
120
|
-
| `bypassPermissions` | — | auto | auto | auto |
|
|
132
|
+
Creates `~/.robota/settings.json`. Use `robota --reset` to return to first-run state.
|
|
121
133
|
|
|
122
|
-
|
|
123
|
-
-
|
|
124
|
-
|
|
134
|
+
Provider setup is generated from provider definitions. The default CLI build includes Anthropic,
|
|
135
|
+
OpenAI-compatible, DeepSeek, Gemma, and Qwen providers; other embeddings can inject their own
|
|
136
|
+
provider definitions.
|
|
137
|
+
Interactive setup creates a readable profile key from the selected model id, such as
|
|
138
|
+
`claude-sonnet-4-6` or `gpt-4o`, and appends `-2`, `-3`, etc. when that key already exists. Generated
|
|
139
|
+
profile keys never include API keys or credential hints.
|
|
125
140
|
|
|
126
|
-
|
|
141
|
+
Inside the TUI, `/provider` and `/provider list` show configured profiles as an interactive picker. Selecting a profile opens command-owned actions for switch, edit, test, duplicate, delete, and cancel. Headless mode prints the same profile list text without opening prompts.
|
|
127
142
|
|
|
128
|
-
|
|
143
|
+
Non-interactive/headless mode never prompts. Configure a provider ahead of time with `robota --configure` in an interactive terminal, or use `robota --configure-provider <profile> --type <type> ... --set-current`.
|
|
144
|
+
|
|
145
|
+
## Built-in Tools
|
|
129
146
|
|
|
130
|
-
|
|
147
|
+
The AI agent can invoke 8 local tools:
|
|
148
|
+
|
|
149
|
+
| Tool | Description | Primary Argument |
|
|
150
|
+
| ----------- | ------------------------------------ | ---------------- |
|
|
151
|
+
| `Bash` | Execute shell commands | `command` |
|
|
152
|
+
| `Read` | Read file contents with line numbers | `filePath` |
|
|
153
|
+
| `Write` | Write content to a file | `filePath` |
|
|
154
|
+
| `Edit` | Replace a string in a file | `filePath` |
|
|
155
|
+
| `Glob` | Find files matching a pattern | `pattern` |
|
|
156
|
+
| `Grep` | Search file contents with regex | `pattern` |
|
|
157
|
+
| `WebFetch` | Fetch URL content as text | `url` |
|
|
158
|
+
| `WebSearch` | Search the internet | `query` |
|
|
159
|
+
|
|
160
|
+
## Recent TUI Capabilities
|
|
161
|
+
|
|
162
|
+
- Provider setup and profile management are generated from provider definitions, so the default CLI
|
|
163
|
+
build can configure, switch, edit, test, duplicate, and delete Anthropic, OpenAI-compatible,
|
|
164
|
+
DeepSeek, Gemma, and Qwen profiles without provider-specific UI branches.
|
|
165
|
+
- Interactive startup can check npm for newer CLI versions; print/headless mode skips startup update checks to keep scripted output deterministic.
|
|
166
|
+
- Long-running sessions show provider usage summaries, status activity, background job tree rows, and collapsed command-output transcripts.
|
|
167
|
+
- Edit results render as context hunks with markdown-friendly diff blocks.
|
|
168
|
+
- Background subagents are real runtime jobs with transcripts and resumable task snapshots.
|
|
169
|
+
- Explicit multi-agent requests use the `/agent` command module batch path through the SDK runtime.
|
|
131
170
|
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
171
|
+
## Permission System
|
|
172
|
+
|
|
173
|
+
Every tool call passes through a three-step permission gate:
|
|
174
|
+
|
|
175
|
+
1. **Deny list** — if any deny pattern matches, the action is blocked
|
|
176
|
+
2. **Allow list** — if any allow pattern matches, the action is auto-approved
|
|
177
|
+
3. **Mode policy** — the active permission mode determines the decision
|
|
178
|
+
|
|
179
|
+
### Permission Modes
|
|
180
|
+
|
|
181
|
+
| Mode | Read/Glob/Grep | Write/Edit | Bash |
|
|
182
|
+
| ------------------- | :------------: | :--------: | :-----: |
|
|
183
|
+
| `plan` | auto | deny | deny |
|
|
184
|
+
| `default` | auto | approve | approve |
|
|
185
|
+
| `acceptEdits` | auto | auto | approve |
|
|
186
|
+
| `bypassPermissions` | auto | auto | auto |
|
|
135
187
|
|
|
136
|
-
|
|
137
|
-
|
|
188
|
+
### Changing Mode at Runtime
|
|
189
|
+
|
|
190
|
+
Use the `/permissions` slash command:
|
|
138
191
|
|
|
139
|
-
|
|
140
|
-
|
|
192
|
+
```
|
|
193
|
+
> /permissions # Show current mode and session-approved tools
|
|
194
|
+
> /permissions plan # Switch to plan (read-only)
|
|
195
|
+
> /permissions bypassPermissions # Skip all prompts
|
|
141
196
|
```
|
|
142
197
|
|
|
143
198
|
Or set it at startup:
|
|
@@ -146,7 +201,7 @@ Or set it at startup:
|
|
|
146
201
|
robota --permission-mode plan
|
|
147
202
|
```
|
|
148
203
|
|
|
149
|
-
### Permission Patterns
|
|
204
|
+
### Permission Patterns
|
|
150
205
|
|
|
151
206
|
Configure in `.robota/settings.json` or `.robota/settings.local.json`:
|
|
152
207
|
|
|
@@ -159,42 +214,140 @@ Configure in `.robota/settings.json` or `.robota/settings.local.json`:
|
|
|
159
214
|
}
|
|
160
215
|
```
|
|
161
216
|
|
|
162
|
-
|
|
217
|
+
Pattern syntax: `ToolName` matches any invocation; `ToolName(pattern)` matches on the primary argument with shell-style globs (`*`, `**`).
|
|
218
|
+
|
|
219
|
+
## Keyboard Controls
|
|
220
|
+
|
|
221
|
+
| Key | Action |
|
|
222
|
+
| ---------- | ----------------------------------------------------------- |
|
|
223
|
+
| Enter | Submit input |
|
|
224
|
+
| ESC | Abort current execution (graceful — saves partial response) |
|
|
225
|
+
| Ctrl+C | Exit process immediately |
|
|
226
|
+
| Up/Down | Navigate visual lines in wrapped multi-line input |
|
|
227
|
+
| Arrow keys | Navigate slash command autocomplete, permission prompt |
|
|
163
228
|
|
|
164
|
-
|
|
165
|
-
- `ToolName(pattern)` — match when the primary argument matches the glob (e.g., `Bash(pnpm *)`)
|
|
166
|
-
- `*` — zero or more characters (shell-style)
|
|
167
|
-
- `**` — one or more characters (recursive path matching)
|
|
229
|
+
## Paste Handling
|
|
168
230
|
|
|
169
|
-
|
|
231
|
+
Bracketed paste mode (DECSET 2004) is enabled on startup. When pasting multiline text, the input area collapses it into a label: `[Pasted text #1 +42 lines]`. Multiple pastes are numbered sequentially. The full content is expanded on submit.
|
|
232
|
+
|
|
233
|
+
Single-line paste is inserted directly as typed text. Terminals without bracketed paste fall back to heuristic detection.
|
|
234
|
+
|
|
235
|
+
## Edit Diff Display
|
|
236
|
+
|
|
237
|
+
After the Edit tool runs, a `DiffBlock` component renders the change inline:
|
|
238
|
+
|
|
239
|
+
```
|
|
240
|
+
✓ Edit(src/provider.ts)
|
|
241
|
+
│ src/provider.ts
|
|
242
|
+
│ - const DEFAULT_MAX_TOKENS = 4096;
|
|
243
|
+
│ + const maxTokens = getModelMaxOutput(modelId);
|
|
244
|
+
```
|
|
245
|
+
|
|
246
|
+
Removed lines appear in red with `-`, added lines in green with `+`. Diffs longer than 10 lines show the first 8 + a `... and N more lines` summary.
|
|
247
|
+
|
|
248
|
+
## Session Management
|
|
249
|
+
|
|
250
|
+
The CLI supports continuing, resuming, forking, and naming sessions.
|
|
251
|
+
|
|
252
|
+
### CLI Flags
|
|
253
|
+
|
|
254
|
+
| Flag | Description |
|
|
255
|
+
| --------------------- | ------------------------------------------------ |
|
|
256
|
+
| `-c`, `--continue` | Continue the most recent session |
|
|
257
|
+
| `-r`, `--resume <id>` | Resume a specific session by ID |
|
|
258
|
+
| `--fork-session <id>` | Fork a session (new session with copied history) |
|
|
259
|
+
| `--name <name>` | Assign a name to the session at startup |
|
|
260
|
+
|
|
261
|
+
### TUI Commands
|
|
262
|
+
|
|
263
|
+
| Command | Description |
|
|
264
|
+
| ---------------- | ----------------------------------- |
|
|
265
|
+
| `/resume` | List recent sessions and resume one |
|
|
266
|
+
| `/rename <name>` | Rename the current session |
|
|
267
|
+
|
|
268
|
+
### Session Name Display
|
|
269
|
+
|
|
270
|
+
When a session has a name, it appears in three places:
|
|
271
|
+
|
|
272
|
+
- **Input border** — session name shown in the input area border
|
|
273
|
+
- **Terminal title** — updated via ANSI escape sequences
|
|
274
|
+
- **StatusBar** — displayed alongside activity, model, and context usage
|
|
170
275
|
|
|
171
276
|
## Slash Commands
|
|
172
277
|
|
|
173
|
-
| Command
|
|
174
|
-
|
|
|
175
|
-
| `/help`
|
|
176
|
-
| `/clear`
|
|
177
|
-
| `/
|
|
178
|
-
| `/
|
|
179
|
-
| `/
|
|
180
|
-
| `/
|
|
181
|
-
| `/
|
|
278
|
+
| Command | Description |
|
|
279
|
+
| ------------------------- | ---------------------------------------------------------------------- |
|
|
280
|
+
| `/help` | Show available commands |
|
|
281
|
+
| `/clear` | Clear conversation history |
|
|
282
|
+
| `/model [model]` | Select AI model (confirmation prompt, CLI restarts) |
|
|
283
|
+
| `/language [lang]` | Set response language (ko, en, ja, zh), saves and restarts |
|
|
284
|
+
| `/compact [instructions]` | Compress context window |
|
|
285
|
+
| `/cost` | Show session info |
|
|
286
|
+
| `/context` | Context window details, reference inventory, and auto-compact controls |
|
|
287
|
+
| `/agent` | Run and manage background subagent jobs |
|
|
288
|
+
| `/permissions [mode]` | Show permission rules or change permission mode |
|
|
289
|
+
| `/plugin [subcommand]` | Plugin management |
|
|
290
|
+
| `/resume` | List recent sessions and resume one |
|
|
291
|
+
| `/rename <name>` | Rename the current session |
|
|
292
|
+
| `/exit` | Exit CLI |
|
|
293
|
+
|
|
294
|
+
Typing `/` triggers an autocomplete popup with arrow-key navigation and Esc to dismiss. Tab inserts the highlighted command into the input field without executing — continue typing args or press Enter to execute. Enter selects and executes immediately. Commands with subcommands (e.g., `/permissions`, `/model`) show a nested submenu. Skill commands discovered from `.agents/skills/` and `.claude/commands/` appear alongside built-in commands.
|
|
295
|
+
|
|
296
|
+
## Plugin Management
|
|
297
|
+
|
|
298
|
+
The `/plugin` command opens an interactive TUI or runs plugin operations through the injected plugin command module:
|
|
299
|
+
|
|
300
|
+
| Subcommand | Description |
|
|
301
|
+
| ---------------------------------------- | ------------------------------------- |
|
|
302
|
+
| `/plugin` or `/plugin manage` | Open the plugin manager TUI |
|
|
303
|
+
| `/plugin install <name>@<marketplace>` | Install a plugin from a marketplace |
|
|
304
|
+
| `/plugin uninstall <name>@<marketplace>` | Remove an installed plugin |
|
|
305
|
+
| `/plugin enable <name>@<marketplace>` | Enable a disabled plugin |
|
|
306
|
+
| `/plugin disable <name>@<marketplace>` | Disable a plugin without uninstalling |
|
|
307
|
+
| `/plugin marketplace add <source>` | Add a marketplace source |
|
|
308
|
+
| `/plugin marketplace remove <name>` | Remove a marketplace source |
|
|
309
|
+
| `/plugin marketplace update <name>` | Update a marketplace source |
|
|
310
|
+
| `/plugin marketplace list` | List configured marketplace sources |
|
|
182
311
|
|
|
183
312
|
## Configuration
|
|
184
313
|
|
|
185
|
-
Settings are
|
|
314
|
+
Settings are merged in this order, from lowest to highest priority:
|
|
186
315
|
|
|
187
|
-
1.
|
|
188
|
-
2.
|
|
189
|
-
3.
|
|
316
|
+
1. `~/.robota/settings.json` (user global)
|
|
317
|
+
2. `~/.claude/settings.json` (user global, Claude Code compatible)
|
|
318
|
+
3. `.robota/settings.json` (project, shared)
|
|
319
|
+
4. `.robota/settings.local.json` (local, gitignored)
|
|
320
|
+
5. `.claude/settings.json` (project, Claude Code compatible)
|
|
321
|
+
6. `.claude/settings.local.json` (local, gitignored, Claude Code compatible)
|
|
190
322
|
|
|
191
323
|
```json
|
|
192
324
|
{
|
|
193
325
|
"defaultMode": "default",
|
|
194
|
-
"
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
"
|
|
326
|
+
"language": "en",
|
|
327
|
+
"currentProvider": "qwen-plus",
|
|
328
|
+
"providers": {
|
|
329
|
+
"qwen-plus": {
|
|
330
|
+
"type": "qwen",
|
|
331
|
+
"model": "qwen-plus",
|
|
332
|
+
"apiKey": "$ENV:DASHSCOPE_API_KEY",
|
|
333
|
+
"baseURL": "https://dashscope-intl.aliyuncs.com/compatible-mode/v1"
|
|
334
|
+
},
|
|
335
|
+
"supergemma4-26b-uncensored-v2": {
|
|
336
|
+
"type": "gemma",
|
|
337
|
+
"model": "supergemma4-26b-uncensored-v2",
|
|
338
|
+
"apiKey": "lm-studio",
|
|
339
|
+
"baseURL": "http://localhost:1234/v1"
|
|
340
|
+
},
|
|
341
|
+
"gpt-4o": {
|
|
342
|
+
"type": "openai",
|
|
343
|
+
"model": "gpt-4o",
|
|
344
|
+
"apiKey": "$ENV:OPENAI_API_KEY"
|
|
345
|
+
},
|
|
346
|
+
"claude-sonnet-4-6": {
|
|
347
|
+
"type": "anthropic",
|
|
348
|
+
"model": "claude-sonnet-4-6",
|
|
349
|
+
"apiKey": "$ENV:ANTHROPIC_API_KEY"
|
|
350
|
+
}
|
|
198
351
|
},
|
|
199
352
|
"permissions": {
|
|
200
353
|
"allow": ["Bash(pnpm *)"],
|
|
@@ -203,13 +356,27 @@ Settings are loaded from (highest priority first):
|
|
|
203
356
|
}
|
|
204
357
|
```
|
|
205
358
|
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
359
|
+
`currentProvider` selects a profile key from `providers`. The key is the stable profile identity, not
|
|
360
|
+
the provider type; multiple profile keys may use the same provider type and model when they represent
|
|
361
|
+
different credentials, endpoints, accounts, or operational defaults. Qwen Model Studio profiles use
|
|
362
|
+
`type: "qwen"` with a DashScope-compatible `baseURL`; the API key is usually stored as
|
|
363
|
+
`$ENV:DASHSCOPE_API_KEY`. DeepSeek profiles use `type: "deepseek"` with
|
|
364
|
+
`https://api.deepseek.com` and `$ENV:DEEPSEEK_API_KEY`. Gemma-family LM Studio models use
|
|
365
|
+
`type: "gemma"` so Robota can apply Gemma-specific channel-marker projection while still talking to
|
|
366
|
+
the OpenAI-compatible `/v1/chat/completions` API through `baseURL`. Generic OpenAI-compatible profiles use
|
|
367
|
+
`type: "openai"` and do not apply provider-specific projection. Use `--provider <profile>` for a
|
|
368
|
+
one-shot invocation override; add `--set-current` only when the selected profile should become the
|
|
369
|
+
persisted default. The legacy single-provider shape remains supported:
|
|
211
370
|
|
|
212
|
-
|
|
371
|
+
```json
|
|
372
|
+
{
|
|
373
|
+
"provider": {
|
|
374
|
+
"name": "anthropic",
|
|
375
|
+
"model": "claude-sonnet-4-6",
|
|
376
|
+
"apiKey": "$ENV:ANTHROPIC_API_KEY"
|
|
377
|
+
}
|
|
378
|
+
}
|
|
379
|
+
```
|
|
213
380
|
|
|
214
381
|
## Context Discovery
|
|
215
382
|
|
|
@@ -219,36 +386,73 @@ The CLI automatically discovers and loads:
|
|
|
219
386
|
- **CLAUDE.md** — same walk-up discovery
|
|
220
387
|
- **Project metadata** — from `package.json`, `tsconfig.json`
|
|
221
388
|
|
|
222
|
-
All context is assembled into the system prompt
|
|
389
|
+
All context is assembled into the system prompt.
|
|
390
|
+
|
|
391
|
+
Ordinary prompts may also reference workspace-local files with path-like `@file` tokens, for
|
|
392
|
+
example `@AGENTS.md` or `@docs/SPEC.md`. The CLI passes those prompts through unchanged; the SDK
|
|
393
|
+
resolves bounded file content under the active `cwd`, sends the enriched prompt to the model, and
|
|
394
|
+
records a structured file-reference event in the session history.
|
|
395
|
+
|
|
396
|
+
## Memory Management
|
|
397
|
+
|
|
398
|
+
- **Message windowing** — React state keeps the most recent 100 messages. Older messages are dropped from the render tree; full history remains in the session store.
|
|
399
|
+
- **Tool state cleanup** — Completed tool execution states are trimmed to the most recent 50 entries.
|
|
400
|
+
- **React.memo** — `MessageItem` uses `React.memo` to skip redundant re-renders.
|
|
401
|
+
|
|
402
|
+
## Session Logging
|
|
403
|
+
|
|
404
|
+
Session logs are written to `.robota/logs/{sessionId}.jsonl` in JSONL format by default, capturing structured events for diagnostics and replay. Background task lifecycle/progress events are logged there as they happen. Child-process subagents also write append-only transcripts to `.robota/logs/{sessionId}/subagents/{agentId}.jsonl`, including streaming text deltas while the local provider request is still running.
|
|
405
|
+
|
|
406
|
+
Resumable session JSON is written to `.robota/sessions/{sessionId}.json` for the current project and includes messages, UI history, the exact system prompt, registered tool schemas, and background task snapshots. High-frequency streaming chunks stay in JSONL transcript files; the session JSON stores task state and transcript paths.
|
|
223
407
|
|
|
224
408
|
## Architecture
|
|
225
409
|
|
|
410
|
+
The CLI is a pure TUI layer. All business logic lives in `@robota-sdk/agent-sdk`'s `InteractiveSession`. `useInteractiveSession` is the sole React↔SDK bridge, converting SDK events to React state.
|
|
411
|
+
|
|
226
412
|
```
|
|
227
|
-
bin.ts → cli.ts (
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
413
|
+
bin.ts → cli.ts (arg parsing)
|
|
414
|
+
└── ui/render.tsx → App.tsx (thin JSX shell)
|
|
415
|
+
├── useInteractiveSession (ONLY React↔SDK bridge)
|
|
416
|
+
│ ├── InteractiveSession (SDK)
|
|
417
|
+
│ ├── CommandRegistry (SDK, re-exported by CLI)
|
|
418
|
+
│ │ ├── BuiltinCommandSource (SDK, empty by default)
|
|
419
|
+
│ │ ├── agent-command-skills (/skills command + virtual skill aliases)
|
|
420
|
+
│ │ ├── PluginCommandSource (SDK, plugin skills)
|
|
421
|
+
│ │ └── ICommandModule sources (/help, /compact, ...)
|
|
422
|
+
│ └── SystemCommandExecutor (SDK)
|
|
423
|
+
├── plugin-hooks-merger.ts (merges plugin hooks into SDK config)
|
|
424
|
+
├── MessageList.tsx
|
|
425
|
+
├── InputArea.tsx (CjkTextInput, bracketed paste, slash detection)
|
|
426
|
+
├── StatusBar.tsx (activity, conditional mode, model, context %)
|
|
427
|
+
├── PermissionPrompt.tsx (arrow-key Allow/Deny)
|
|
428
|
+
├── SlashAutocomplete.tsx (command popup with scroll)
|
|
429
|
+
├── DiffBlock.tsx (Edit tool diff display)
|
|
430
|
+
├── MenuSelect.tsx (arrow-key menu, Plugin TUI)
|
|
431
|
+
├── PluginTUI.tsx (plugin management screen stack)
|
|
432
|
+
├── TextPrompt.tsx (text input for Plugin TUI)
|
|
433
|
+
└── ConfirmPrompt.tsx (reusable yes/no prompt)
|
|
240
434
|
```
|
|
241
435
|
|
|
242
|
-
|
|
436
|
+
## Dependencies
|
|
243
437
|
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
438
|
+
| Package | Purpose |
|
|
439
|
+
| -------------------------------------- | ------------------------------------------ |
|
|
440
|
+
| `@robota-sdk/agent-sdk` | Session factory, query, config, context |
|
|
441
|
+
| `@robota-sdk/agent-core` | Types (TPermissionMode, TToolArgs) |
|
|
442
|
+
| `@robota-sdk/agent-transport-headless` | Headless runner for print mode (`-p`) |
|
|
443
|
+
| `ink` 7, `react` 19.2+ | TUI rendering |
|
|
444
|
+
| `ink-select-input` | Arrow-key selection (permission prompt) |
|
|
445
|
+
| `ink-spinner` | Loading spinner |
|
|
446
|
+
| `chalk` | Terminal colors |
|
|
447
|
+
| `ink-text-input` | Base text input (extended by CjkTextInput) |
|
|
448
|
+
| `marked`, `marked-terminal` | Markdown parsing and terminal rendering |
|
|
449
|
+
| `cli-highlight` | Syntax highlighting for code blocks |
|
|
450
|
+
| `string-width` | Unicode-aware string width (CJK support) |
|
|
451
|
+
|
|
452
|
+
## Documentation
|
|
453
|
+
|
|
454
|
+
See [docs/SPEC.md](./docs/SPEC.md) for the full specification, architecture details, and design decisions.
|
|
455
|
+
|
|
456
|
+
## License
|
|
457
|
+
|
|
458
|
+
MIT
|
package/dist/node/bin.js
CHANGED
|
@@ -1,9 +1,20 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
import {
|
|
3
3
|
startCli
|
|
4
|
-
} from "./chunk-
|
|
4
|
+
} from "./chunk-J654S773.js";
|
|
5
|
+
import "./chunk-BENOH47A.js";
|
|
5
6
|
|
|
6
7
|
// src/bin.ts
|
|
8
|
+
process.on("uncaughtException", (err) => {
|
|
9
|
+
const msg = err.message ?? "";
|
|
10
|
+
const isLikelyIME = msg.includes("string-width") || msg.includes("setCursorPosition") || msg.includes("getStringWidth") || msg.includes("slice") || msg.includes("charCodeAt");
|
|
11
|
+
if (isLikelyIME) {
|
|
12
|
+
process.stderr.write(`[robota] IME error suppressed: ${msg}
|
|
13
|
+
`);
|
|
14
|
+
return;
|
|
15
|
+
}
|
|
16
|
+
throw err;
|
|
17
|
+
});
|
|
7
18
|
startCli().catch((err) => {
|
|
8
19
|
const message = err instanceof Error ? err.message : String(err);
|
|
9
20
|
process.stderr.write(message + "\n");
|