@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 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 | Required |
26
- | ------------------- | ----------------- | -------- |
27
- | `ANTHROPIC_API_KEY` | Anthropic API key | Yes |
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
- # 1. Copy .env.example and add your Anthropic API key
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, auto-loads .env)
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
- ## Built-in Tools
87
+ ### CLI Updates
80
88
 
81
- The CLI provides 6 tools that the AI agent can invoke:
89
+ Robota can check npm for a newer `@robota-sdk/agent-cli` version:
82
90
 
83
- | Tool | Description | Primary Argument |
84
- | ------- | ------------------------------------ | ---------------- |
85
- | `Bash` | Execute shell commands | `command` |
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
- ## Permission System
95
+ When an update is available, Robota prints the npm global install command:
93
96
 
94
- Every tool call passes through a three-step permission gate before execution:
97
+ ```bash
98
+ npm install -g '@robota-sdk/agent-cli@latest'
99
+ ```
95
100
 
96
- 1. **Deny list** if any deny pattern matches, the action is blocked immediately
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
- When a tool requires approval, the user sees an interactive prompt:
103
+ ### Print Mode Output Formats
101
104
 
102
- ```
103
- [Permission Required] Tool: Bash
104
- Arguments: command: rm -rf dist
105
- Allow? [y/N]
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
- - Type `y` or `yes` to approve
109
- - Press Enter or type anything else to deny
123
+ ## First-Run Setup
110
124
 
111
- If denied, the AI agent receives a "Permission denied" error and can adjust its approach.
125
+ When no usable settings file exists, the CLI prompts for:
112
126
 
113
- ### Permission Modes
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
- | Mode | Alias | Read/Glob/Grep | Write/Edit | Bash |
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
- - **auto** — tool executes without prompting
123
- - **approve** — user is prompted to allow or deny
124
- - **deny** tool is blocked silently (no prompt shown)
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
- Unknown tools default to `approve` in most modes, `deny` in `plan` mode.
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 in the REPL:
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 (allow/deny lists)
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
- **Pattern syntax:**
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
- - `ToolName` — match any invocation of that tool (e.g., `Bash`)
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
- **Evaluation order:** deny patterns are checked first, then allow patterns, then the mode policy. Deny always wins.
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 | Description |
174
- | -------------- | ------------------------------- |
175
- | `/help` | Show help |
176
- | `/clear` | Clear conversation history |
177
- | `/mode [mode]` | Show or change permission mode |
178
- | `/resume` | List and resume a saved session |
179
- | `/cost` | Show token usage |
180
- | `/model` | Show current model |
181
- | `/exit` | Exit CLI |
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 loaded from (highest priority first):
305
+ Settings are merged in this order, from lowest to highest priority:
186
306
 
187
- 1. `.robota/settings.local.json` (local, gitignored)
188
- 2. `.robota/settings.json` (project, shared)
189
- 3. `~/.robota/settings.json` (user global)
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
- "provider": {
195
- "name": "anthropic",
196
- "model": "claude-sonnet-4-6",
197
- "apiKey": "$ENV:ANTHROPIC_API_KEY"
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
- ### Environment Variables
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
- | Variable | Description | Required |
209
- | ------------------- | ----------------- | -------- |
210
- | `ANTHROPIC_API_KEY` | Anthropic API key | Yes |
211
-
212
- Copy `.env.example` to `.env` and set your key. The CLI reads `.env` automatically in dev mode.
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 for the AI assistant.
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 (parseArgs, load config/context, create Session)
228
- ├── config/config-loader.ts — settings file discovery + Zod validation
229
- ├── context/context-loader.ts AGENTS.md/CLAUDE.md walk-up discovery
230
- ├── context/project-detector.ts — package.json/tsconfig detection
231
- ├── context/system-prompt-builder.ts system message assembly
232
- ├── session.ts — Robota agent wrapper + permission enforcement
233
- └── permissions/
234
- ├── permission-gate.ts — 3-step evaluation (deny allow → mode)
235
- ├── permission-mode.ts mode × tool policy matrix
236
- └── permission-prompt.ts — interactive [y/N] prompt
237
- ├── tools/ — 6 built-in tools (Bash, Read, Write, Edit, Glob, Grep)
238
- ├── session-store.ts — JSON file-based session persistence
239
- └── ui/ — Ink TUI components (App, MessageList, InputArea, etc.)
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
- Tool calls flow through the permission system:
412
+ ## Dependencies
243
413
 
244
- ```
245
- AI agent requests tool call
246
- Session.wrapToolWithPermission() intercepts execute()
247
- evaluatePermission(toolName, args, mode, allow/deny lists)
248
- deny list match? blocked
249
- allow list match? auto-approved
250
- mode policy lookup auto | approve | deny
251
- if 'approve': promptForApproval() → user types y/N
252
- if allowed: original tool.execute() runs
253
- if denied: returns error result to AI agent
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-4DYVT4WI.js";
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");