@robota-sdk/agent-cli 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 +286 -106
- package/dist/node/bin.js +12 -1
- package/dist/node/chunk-6XQKLNRF.js +267 -0
- package/dist/node/chunk-GHQHUBHC.js +5469 -0
- package/dist/node/index.cjs +5407 -991
- 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 +47 -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,10 @@ 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
|
+
| `DASHSCOPE_API_KEY` | Alibaba Cloud Model Studio key for `qwen` | Qwen only |
|
|
28
33
|
|
|
29
34
|
Set your key before running:
|
|
30
35
|
|
|
@@ -35,11 +40,7 @@ export ANTHROPIC_API_KEY=sk-ant-...
|
|
|
35
40
|
## Development Setup (Monorepo)
|
|
36
41
|
|
|
37
42
|
```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
|
|
43
|
+
# Build dependencies and CLI
|
|
43
44
|
pnpm build:deps
|
|
44
45
|
pnpm --filter @robota-sdk/agent-cli build
|
|
45
46
|
```
|
|
@@ -50,7 +51,7 @@ pnpm --filter @robota-sdk/agent-cli build
|
|
|
50
51
|
# From monorepo root
|
|
51
52
|
cd packages/agent-cli
|
|
52
53
|
|
|
53
|
-
# Development mode (no build needed
|
|
54
|
+
# Development mode (no build needed)
|
|
54
55
|
pnpm dev
|
|
55
56
|
|
|
56
57
|
# Production mode (requires build)
|
|
@@ -71,73 +72,117 @@ robota -p "prompt" # Print mode (one-shot, exit after response)
|
|
|
71
72
|
robota -c # Continue last session
|
|
72
73
|
robota -r <session-id> # Resume session by ID
|
|
73
74
|
robota --model <model> # Model override (e.g., claude-sonnet-4-6)
|
|
75
|
+
robota --language <lang> # Response language (ko, en, ja, zh)
|
|
74
76
|
robota --permission-mode <mode> # plan | default | acceptEdits | bypassPermissions
|
|
75
77
|
robota --max-turns <n> # Limit agentic turns per interaction
|
|
78
|
+
robota --output-format <fmt> # text | json | stream-json (print mode)
|
|
79
|
+
robota --system-prompt <text> # Replace system prompt (print mode)
|
|
80
|
+
robota --append-system-prompt <text> # Append to system prompt (print mode)
|
|
81
|
+
robota --reset # Delete user settings and exit
|
|
82
|
+
robota --check-update # Check npm for a newer CLI version and exit
|
|
83
|
+
robota --disable-update-check # Skip interactive startup update check for this run
|
|
76
84
|
robota --version # Show version
|
|
77
85
|
```
|
|
78
86
|
|
|
79
|
-
|
|
87
|
+
### CLI Updates
|
|
80
88
|
|
|
81
|
-
|
|
89
|
+
Robota can check npm for a newer `@robota-sdk/agent-cli` version:
|
|
82
90
|
|
|
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` |
|
|
91
|
+
```bash
|
|
92
|
+
robota --check-update
|
|
93
|
+
```
|
|
91
94
|
|
|
92
|
-
|
|
95
|
+
When an update is available, Robota prints the npm global install command:
|
|
93
96
|
|
|
94
|
-
|
|
97
|
+
```bash
|
|
98
|
+
npm install -g '@robota-sdk/agent-cli@latest'
|
|
99
|
+
```
|
|
95
100
|
|
|
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
|
|
101
|
+
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
102
|
|
|
100
|
-
|
|
103
|
+
### Print Mode Output Formats
|
|
101
104
|
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
105
|
+
Print mode (`-p`) supports three output formats via `--output-format`:
|
|
106
|
+
|
|
107
|
+
| Format | Description |
|
|
108
|
+
| ------------- | ------------------------------------------------------------------ |
|
|
109
|
+
| `text` | Plain text response to stdout (default) |
|
|
110
|
+
| `json` | Single JSON object: `{ type, result, session_id, subtype }` |
|
|
111
|
+
| `stream-json` | Newline-delimited JSON with `content_block_delta` streaming events |
|
|
112
|
+
|
|
113
|
+
### Stdin Pipe
|
|
114
|
+
|
|
115
|
+
When `-p` is used without a positional argument and stdin is piped, the CLI reads from stdin:
|
|
116
|
+
|
|
117
|
+
```bash
|
|
118
|
+
echo "Explain this error" | robota -p
|
|
119
|
+
cat file.ts | robota -p "Review this code" --output-format json
|
|
120
|
+
git diff | robota -p "Summarize changes" --output-format stream-json
|
|
106
121
|
```
|
|
107
122
|
|
|
108
|
-
-
|
|
109
|
-
- Press Enter or type anything else to deny
|
|
123
|
+
## First-Run Setup
|
|
110
124
|
|
|
111
|
-
|
|
125
|
+
When no usable settings file exists, the CLI prompts for:
|
|
112
126
|
|
|
113
|
-
|
|
127
|
+
1. **Provider selection** from the providers assembled into the CLI binary
|
|
128
|
+
2. **Provider-specific setup fields** such as model, base URL, and masked API key
|
|
129
|
+
3. **Response language** (ko/en/ja/zh, default: en)
|
|
130
|
+
|
|
131
|
+
Creates `~/.robota/settings.json`. Use `robota --reset` to return to first-run state.
|
|
132
|
+
|
|
133
|
+
Provider setup is generated from provider definitions. The default CLI build includes Anthropic, OpenAI-compatible, Gemma, and Qwen providers; other embeddings can inject their own provider definitions.
|
|
114
134
|
|
|
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 |
|
|
135
|
+
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`.
|
|
121
136
|
|
|
122
|
-
-
|
|
123
|
-
|
|
124
|
-
|
|
137
|
+
## Built-in Tools
|
|
138
|
+
|
|
139
|
+
The AI agent can invoke 8 local tools:
|
|
140
|
+
|
|
141
|
+
| Tool | Description | Primary Argument |
|
|
142
|
+
| ----------- | ------------------------------------ | ---------------- |
|
|
143
|
+
| `Bash` | Execute shell commands | `command` |
|
|
144
|
+
| `Read` | Read file contents with line numbers | `filePath` |
|
|
145
|
+
| `Write` | Write content to a file | `filePath` |
|
|
146
|
+
| `Edit` | Replace a string in a file | `filePath` |
|
|
147
|
+
| `Glob` | Find files matching a pattern | `pattern` |
|
|
148
|
+
| `Grep` | Search file contents with regex | `pattern` |
|
|
149
|
+
| `WebFetch` | Fetch URL content as text | `url` |
|
|
150
|
+
| `WebSearch` | Search the internet | `query` |
|
|
151
|
+
|
|
152
|
+
## Recent TUI Capabilities
|
|
153
|
+
|
|
154
|
+
- Provider setup is generated from provider definitions, so the default CLI build can configure Anthropic, OpenAI-compatible, Gemma, and Qwen profiles without provider-specific UI branches.
|
|
155
|
+
- Interactive startup can check npm for newer CLI versions; print/headless mode skips startup update checks to keep scripted output deterministic.
|
|
156
|
+
- Long-running sessions show provider usage summaries, status activity, background job tree rows, and collapsed command-output transcripts.
|
|
157
|
+
- Edit results render as context hunks with markdown-friendly diff blocks.
|
|
158
|
+
- Background subagents are real runtime jobs with transcripts and resumable task snapshots.
|
|
159
|
+
- Explicit multi-agent requests can use the Agent tool `jobs` batch path through the SDK runtime.
|
|
160
|
+
|
|
161
|
+
## Permission System
|
|
162
|
+
|
|
163
|
+
Every tool call passes through a three-step permission gate:
|
|
164
|
+
|
|
165
|
+
1. **Deny list** — if any deny pattern matches, the action is blocked
|
|
166
|
+
2. **Allow list** — if any allow pattern matches, the action is auto-approved
|
|
167
|
+
3. **Mode policy** — the active permission mode determines the decision
|
|
168
|
+
|
|
169
|
+
### Permission Modes
|
|
125
170
|
|
|
126
|
-
|
|
171
|
+
| Mode | Read/Glob/Grep | Write/Edit | Bash |
|
|
172
|
+
| ------------------- | :------------: | :--------: | :-----: |
|
|
173
|
+
| `plan` | auto | deny | deny |
|
|
174
|
+
| `default` | auto | approve | approve |
|
|
175
|
+
| `acceptEdits` | auto | auto | approve |
|
|
176
|
+
| `bypassPermissions` | auto | auto | auto |
|
|
127
177
|
|
|
128
178
|
### Changing Mode at Runtime
|
|
129
179
|
|
|
130
|
-
Use the `/mode` slash command
|
|
180
|
+
Use the `/mode` slash command:
|
|
131
181
|
|
|
132
182
|
```
|
|
133
183
|
> /mode # Show current mode
|
|
134
|
-
Current permission mode: default
|
|
135
|
-
|
|
136
184
|
> /mode plan # Switch to plan (read-only)
|
|
137
|
-
Permission mode set to: plan
|
|
138
|
-
|
|
139
185
|
> /mode bypassPermissions # Skip all prompts
|
|
140
|
-
Permission mode set to: bypassPermissions
|
|
141
186
|
```
|
|
142
187
|
|
|
143
188
|
Or set it at startup:
|
|
@@ -146,7 +191,7 @@ Or set it at startup:
|
|
|
146
191
|
robota --permission-mode plan
|
|
147
192
|
```
|
|
148
193
|
|
|
149
|
-
### Permission Patterns
|
|
194
|
+
### Permission Patterns
|
|
150
195
|
|
|
151
196
|
Configure in `.robota/settings.json` or `.robota/settings.local.json`:
|
|
152
197
|
|
|
@@ -159,42 +204,141 @@ Configure in `.robota/settings.json` or `.robota/settings.local.json`:
|
|
|
159
204
|
}
|
|
160
205
|
```
|
|
161
206
|
|
|
162
|
-
|
|
207
|
+
Pattern syntax: `ToolName` matches any invocation; `ToolName(pattern)` matches on the primary argument with shell-style globs (`*`, `**`).
|
|
208
|
+
|
|
209
|
+
## Keyboard Controls
|
|
210
|
+
|
|
211
|
+
| Key | Action |
|
|
212
|
+
| ---------- | ----------------------------------------------------------- |
|
|
213
|
+
| Enter | Submit input |
|
|
214
|
+
| ESC | Abort current execution (graceful — saves partial response) |
|
|
215
|
+
| Ctrl+C | Exit process immediately |
|
|
216
|
+
| Up/Down | Navigate visual lines in wrapped multi-line input |
|
|
217
|
+
| Arrow keys | Navigate slash command autocomplete, permission prompt |
|
|
218
|
+
|
|
219
|
+
## Paste Handling
|
|
220
|
+
|
|
221
|
+
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.
|
|
222
|
+
|
|
223
|
+
Single-line paste is inserted directly as typed text. Terminals without bracketed paste fall back to heuristic detection.
|
|
224
|
+
|
|
225
|
+
## Edit Diff Display
|
|
226
|
+
|
|
227
|
+
After the Edit tool runs, a `DiffBlock` component renders the change inline:
|
|
228
|
+
|
|
229
|
+
```
|
|
230
|
+
✓ Edit(src/provider.ts)
|
|
231
|
+
│ src/provider.ts
|
|
232
|
+
│ - const DEFAULT_MAX_TOKENS = 4096;
|
|
233
|
+
│ + const maxTokens = getModelMaxOutput(modelId);
|
|
234
|
+
```
|
|
235
|
+
|
|
236
|
+
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.
|
|
237
|
+
|
|
238
|
+
## Session Management
|
|
239
|
+
|
|
240
|
+
The CLI supports continuing, resuming, forking, and naming sessions.
|
|
241
|
+
|
|
242
|
+
### CLI Flags
|
|
243
|
+
|
|
244
|
+
| Flag | Description |
|
|
245
|
+
| --------------------- | ------------------------------------------------ |
|
|
246
|
+
| `-c`, `--continue` | Continue the most recent session |
|
|
247
|
+
| `-r`, `--resume <id>` | Resume a specific session by ID |
|
|
248
|
+
| `--fork-session <id>` | Fork a session (new session with copied history) |
|
|
249
|
+
| `--name <name>` | Assign a name to the session at startup |
|
|
163
250
|
|
|
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)
|
|
251
|
+
### TUI Commands
|
|
168
252
|
|
|
169
|
-
|
|
253
|
+
| Command | Description |
|
|
254
|
+
| ---------------- | ----------------------------------- |
|
|
255
|
+
| `/resume` | List recent sessions and resume one |
|
|
256
|
+
| `/rename <name>` | Rename the current session |
|
|
257
|
+
|
|
258
|
+
### Session Name Display
|
|
259
|
+
|
|
260
|
+
When a session has a name, it appears in three places:
|
|
261
|
+
|
|
262
|
+
- **Input border** — session name shown in the input area border
|
|
263
|
+
- **Terminal title** — updated via ANSI escape sequences
|
|
264
|
+
- **StatusBar** — displayed alongside mode, model, and context usage
|
|
170
265
|
|
|
171
266
|
## Slash Commands
|
|
172
267
|
|
|
173
|
-
| Command
|
|
174
|
-
|
|
|
175
|
-
| `/help`
|
|
176
|
-
| `/clear`
|
|
177
|
-
| `/mode [mode]`
|
|
178
|
-
| `/
|
|
179
|
-
| `/
|
|
180
|
-
| `/
|
|
181
|
-
| `/
|
|
268
|
+
| Command | Description |
|
|
269
|
+
| ------------------------- | ---------------------------------------------------------- |
|
|
270
|
+
| `/help` | Show available commands |
|
|
271
|
+
| `/clear` | Clear conversation history |
|
|
272
|
+
| `/mode [mode]` | Show or change permission mode |
|
|
273
|
+
| `/model [model]` | Select AI model (confirmation prompt, CLI restarts) |
|
|
274
|
+
| `/language [lang]` | Set response language (ko, en, ja, zh), saves and restarts |
|
|
275
|
+
| `/compact [instructions]` | Compress context window |
|
|
276
|
+
| `/cost` | Show session info |
|
|
277
|
+
| `/context` | Context window details |
|
|
278
|
+
| `/agent` | Run and manage background subagent jobs |
|
|
279
|
+
| `/permissions` | Show permission rules |
|
|
280
|
+
| `/plugin [subcommand]` | Plugin management |
|
|
281
|
+
| `/resume` | List recent sessions and resume one |
|
|
282
|
+
| `/rename <name>` | Rename the current session |
|
|
283
|
+
| `/exit` | Exit CLI |
|
|
284
|
+
|
|
285
|
+
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., `/mode`, `/model`) show a nested submenu. Skill commands discovered from `.agents/skills/` and `.claude/commands/` appear alongside built-in commands.
|
|
286
|
+
|
|
287
|
+
## Plugin Management
|
|
288
|
+
|
|
289
|
+
The `/plugin` command opens an interactive TUI or runs plugin operations through the injected plugin command module:
|
|
290
|
+
|
|
291
|
+
| Subcommand | Description |
|
|
292
|
+
| ---------------------------------------- | ------------------------------------- |
|
|
293
|
+
| `/plugin` or `/plugin manage` | Open the plugin manager TUI |
|
|
294
|
+
| `/plugin install <name>@<marketplace>` | Install a plugin from a marketplace |
|
|
295
|
+
| `/plugin uninstall <name>@<marketplace>` | Remove an installed plugin |
|
|
296
|
+
| `/plugin enable <name>@<marketplace>` | Enable a disabled plugin |
|
|
297
|
+
| `/plugin disable <name>@<marketplace>` | Disable a plugin without uninstalling |
|
|
298
|
+
| `/plugin marketplace add <source>` | Add a marketplace source |
|
|
299
|
+
| `/plugin marketplace remove <name>` | Remove a marketplace source |
|
|
300
|
+
| `/plugin marketplace update <name>` | Update a marketplace source |
|
|
301
|
+
| `/plugin marketplace list` | List configured marketplace sources |
|
|
182
302
|
|
|
183
303
|
## Configuration
|
|
184
304
|
|
|
185
|
-
Settings are
|
|
305
|
+
Settings are merged in this order, from lowest to highest priority:
|
|
186
306
|
|
|
187
|
-
1.
|
|
188
|
-
2.
|
|
189
|
-
3.
|
|
307
|
+
1. `~/.robota/settings.json` (user global)
|
|
308
|
+
2. `~/.claude/settings.json` (user global, Claude Code compatible)
|
|
309
|
+
3. `.robota/settings.json` (project, shared)
|
|
310
|
+
4. `.robota/settings.local.json` (local, gitignored)
|
|
311
|
+
5. `.claude/settings.json` (project, Claude Code compatible)
|
|
312
|
+
6. `.claude/settings.local.json` (local, gitignored, Claude Code compatible)
|
|
190
313
|
|
|
191
314
|
```json
|
|
192
315
|
{
|
|
193
316
|
"defaultMode": "default",
|
|
194
|
-
"
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
"
|
|
317
|
+
"language": "en",
|
|
318
|
+
"currentProvider": "qwen",
|
|
319
|
+
"providers": {
|
|
320
|
+
"qwen": {
|
|
321
|
+
"type": "qwen",
|
|
322
|
+
"model": "qwen-plus",
|
|
323
|
+
"apiKey": "$ENV:DASHSCOPE_API_KEY",
|
|
324
|
+
"baseURL": "https://dashscope-intl.aliyuncs.com/compatible-mode/v1"
|
|
325
|
+
},
|
|
326
|
+
"gemma": {
|
|
327
|
+
"type": "gemma",
|
|
328
|
+
"model": "supergemma4-26b-uncensored-v2",
|
|
329
|
+
"apiKey": "lm-studio",
|
|
330
|
+
"baseURL": "http://localhost:1234/v1"
|
|
331
|
+
},
|
|
332
|
+
"openai": {
|
|
333
|
+
"type": "openai",
|
|
334
|
+
"model": "<openai-compatible-model>",
|
|
335
|
+
"apiKey": "$ENV:OPENAI_API_KEY"
|
|
336
|
+
},
|
|
337
|
+
"anthropic": {
|
|
338
|
+
"type": "anthropic",
|
|
339
|
+
"model": "claude-sonnet-4-6",
|
|
340
|
+
"apiKey": "$ENV:ANTHROPIC_API_KEY"
|
|
341
|
+
}
|
|
198
342
|
},
|
|
199
343
|
"permissions": {
|
|
200
344
|
"allow": ["Bash(pnpm *)"],
|
|
@@ -203,13 +347,17 @@ Settings are loaded from (highest priority first):
|
|
|
203
347
|
}
|
|
204
348
|
```
|
|
205
349
|
|
|
206
|
-
|
|
350
|
+
`currentProvider` selects a profile from `providers`. Qwen Model Studio profiles use `type: "qwen"` with a DashScope-compatible `baseURL`; the API key is usually stored as `$ENV:DASHSCOPE_API_KEY`. Gemma-family LM Studio models use `type: "gemma"` so Robota can apply Gemma-specific channel-marker projection while still talking to the OpenAI-compatible `/v1/chat/completions` API through `baseURL`. Generic OpenAI-compatible profiles use `type: "openai"` and do not apply provider-specific projection. The legacy single-provider shape remains supported:
|
|
207
351
|
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
352
|
+
```json
|
|
353
|
+
{
|
|
354
|
+
"provider": {
|
|
355
|
+
"name": "anthropic",
|
|
356
|
+
"model": "claude-sonnet-4-6",
|
|
357
|
+
"apiKey": "$ENV:ANTHROPIC_API_KEY"
|
|
358
|
+
}
|
|
359
|
+
}
|
|
360
|
+
```
|
|
213
361
|
|
|
214
362
|
## Context Discovery
|
|
215
363
|
|
|
@@ -219,36 +367,68 @@ The CLI automatically discovers and loads:
|
|
|
219
367
|
- **CLAUDE.md** — same walk-up discovery
|
|
220
368
|
- **Project metadata** — from `package.json`, `tsconfig.json`
|
|
221
369
|
|
|
222
|
-
All context is assembled into the system prompt
|
|
370
|
+
All context is assembled into the system prompt.
|
|
371
|
+
|
|
372
|
+
## Memory Management
|
|
373
|
+
|
|
374
|
+
- **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.
|
|
375
|
+
- **Tool state cleanup** — Completed tool execution states are trimmed to the most recent 50 entries.
|
|
376
|
+
- **React.memo** — `MessageItem` uses `React.memo` to skip redundant re-renders.
|
|
377
|
+
|
|
378
|
+
## Session Logging
|
|
379
|
+
|
|
380
|
+
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.
|
|
381
|
+
|
|
382
|
+
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
383
|
|
|
224
384
|
## Architecture
|
|
225
385
|
|
|
386
|
+
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.
|
|
387
|
+
|
|
226
388
|
```
|
|
227
|
-
bin.ts → cli.ts (
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
389
|
+
bin.ts → cli.ts (arg parsing)
|
|
390
|
+
└── ui/render.tsx → App.tsx (thin JSX shell)
|
|
391
|
+
├── useInteractiveSession (ONLY React↔SDK bridge)
|
|
392
|
+
│ ├── InteractiveSession (SDK)
|
|
393
|
+
│ ├── CommandRegistry (SDK, re-exported by CLI)
|
|
394
|
+
│ │ ├── BuiltinCommandSource (SDK, empty by default)
|
|
395
|
+
│ │ ├── SkillCommandSource (SDK, discovers from 4 paths)
|
|
396
|
+
│ │ ├── PluginCommandSource (SDK, plugin skills)
|
|
397
|
+
│ │ └── ICommandModule sources (/help, /compact, ...)
|
|
398
|
+
│ └── SystemCommandExecutor (SDK)
|
|
399
|
+
├── plugin-hooks-merger.ts (merges plugin hooks into SDK config)
|
|
400
|
+
├── MessageList.tsx
|
|
401
|
+
├── InputArea.tsx (CjkTextInput, bracketed paste, slash detection)
|
|
402
|
+
├── StatusBar.tsx (mode, model, context %, message count)
|
|
403
|
+
├── PermissionPrompt.tsx (arrow-key Allow/Deny)
|
|
404
|
+
├── SlashAutocomplete.tsx (command popup with scroll)
|
|
405
|
+
├── DiffBlock.tsx (Edit tool diff display)
|
|
406
|
+
├── MenuSelect.tsx (arrow-key menu, Plugin TUI)
|
|
407
|
+
├── PluginTUI.tsx (plugin management screen stack)
|
|
408
|
+
├── TextPrompt.tsx (text input for Plugin TUI)
|
|
409
|
+
└── ConfirmPrompt.tsx (reusable yes/no prompt)
|
|
240
410
|
```
|
|
241
411
|
|
|
242
|
-
|
|
412
|
+
## Dependencies
|
|
243
413
|
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
414
|
+
| Package | Purpose |
|
|
415
|
+
| -------------------------------------- | ------------------------------------------ |
|
|
416
|
+
| `@robota-sdk/agent-sdk` | Session factory, query, config, context |
|
|
417
|
+
| `@robota-sdk/agent-core` | Types (TPermissionMode, TToolArgs) |
|
|
418
|
+
| `@robota-sdk/agent-transport-headless` | Headless runner for print mode (`-p`) |
|
|
419
|
+
| `ink` 7, `react` 19.2+ | TUI rendering |
|
|
420
|
+
| `ink-select-input` | Arrow-key selection (permission prompt) |
|
|
421
|
+
| `ink-spinner` | Loading spinner |
|
|
422
|
+
| `chalk` | Terminal colors |
|
|
423
|
+
| `ink-text-input` | Base text input (extended by CjkTextInput) |
|
|
424
|
+
| `marked`, `marked-terminal` | Markdown parsing and terminal rendering |
|
|
425
|
+
| `cli-highlight` | Syntax highlighting for code blocks |
|
|
426
|
+
| `string-width` | Unicode-aware string width (CJK support) |
|
|
427
|
+
|
|
428
|
+
## Documentation
|
|
429
|
+
|
|
430
|
+
See [docs/SPEC.md](./docs/SPEC.md) for the full specification, architecture details, and design decisions.
|
|
431
|
+
|
|
432
|
+
## License
|
|
433
|
+
|
|
434
|
+
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-GHQHUBHC.js";
|
|
5
|
+
import "./chunk-6XQKLNRF.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");
|