@robota-sdk/agent-cli 3.0.0-beta.4 → 3.0.0-beta.41

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,6 +1,8 @@
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
+
5
+ **Version**: 3.0.0-beta.40
4
6
 
5
7
  ## Installation
6
8
 
@@ -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
@@ -71,14 +75,25 @@ robota -p "prompt" # Print mode (one-shot, exit after response)
71
75
  robota -c # Continue last session
72
76
  robota -r <session-id> # Resume session by ID
73
77
  robota --model <model> # Model override (e.g., claude-sonnet-4-6)
78
+ robota --language <lang> # Response language (ko, en, ja, zh)
74
79
  robota --permission-mode <mode> # plan | default | acceptEdits | bypassPermissions
75
80
  robota --max-turns <n> # Limit agentic turns per interaction
81
+ robota --reset # Delete user settings and exit
76
82
  robota --version # Show version
77
83
  ```
78
84
 
85
+ ## First-Run Setup
86
+
87
+ When no settings file exists, the CLI prompts for:
88
+
89
+ 1. **Anthropic API key** (input masked with asterisks)
90
+ 2. **Response language** (ko/en/ja/zh, default: en)
91
+
92
+ Creates `~/.robota/settings.json`. Use `robota --reset` to return to first-run state.
93
+
79
94
  ## Built-in Tools
80
95
 
81
- The CLI provides 6 tools that the AI agent can invoke:
96
+ The AI agent can invoke 6 tools:
82
97
 
83
98
  | Tool | Description | Primary Argument |
84
99
  | ------- | ------------------------------------ | ---------------- |
@@ -91,53 +106,29 @@ The CLI provides 6 tools that the AI agent can invoke:
91
106
 
92
107
  ## Permission System
93
108
 
94
- Every tool call passes through a three-step permission gate before execution:
109
+ Every tool call passes through a three-step permission gate:
95
110
 
96
- 1. **Deny list** — if any deny pattern matches, the action is blocked immediately
111
+ 1. **Deny list** — if any deny pattern matches, the action is blocked
97
112
  2. **Allow list** — if any allow pattern matches, the action is auto-approved
98
113
  3. **Mode policy** — the active permission mode determines the decision
99
114
 
100
- When a tool requires approval, the user sees an interactive prompt:
101
-
102
- ```
103
- [Permission Required] Tool: Bash
104
- Arguments: command: rm -rf dist
105
- Allow? [y/N]
106
- ```
107
-
108
- - Type `y` or `yes` to approve
109
- - Press Enter or type anything else to deny
110
-
111
- If denied, the AI agent receives a "Permission denied" error and can adjust its approach.
112
-
113
115
  ### Permission Modes
114
116
 
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 |
121
-
122
- - **auto** — tool executes without prompting
123
- - **approve** — user is prompted to allow or deny
124
- - **deny** — tool is blocked silently (no prompt shown)
125
-
126
- Unknown tools default to `approve` in most modes, `deny` in `plan` mode.
117
+ | Mode | Read/Glob/Grep | Write/Edit | Bash |
118
+ | ------------------- | :------------: | :--------: | :-----: |
119
+ | `plan` | auto | deny | deny |
120
+ | `default` | auto | approve | approve |
121
+ | `acceptEdits` | auto | auto | approve |
122
+ | `bypassPermissions` | auto | auto | auto |
127
123
 
128
124
  ### Changing Mode at Runtime
129
125
 
130
- Use the `/mode` slash command in the REPL:
126
+ Use the `/mode` slash command:
131
127
 
132
128
  ```
133
129
  > /mode # Show current mode
134
- Current permission mode: default
135
-
136
130
  > /mode plan # Switch to plan (read-only)
137
- Permission mode set to: plan
138
-
139
131
  > /mode bypassPermissions # Skip all prompts
140
- Permission mode set to: bypassPermissions
141
132
  ```
142
133
 
143
134
  Or set it at startup:
@@ -146,7 +137,7 @@ Or set it at startup:
146
137
  robota --permission-mode plan
147
138
  ```
148
139
 
149
- ### Permission Patterns (allow/deny lists)
140
+ ### Permission Patterns
150
141
 
151
142
  Configure in `.robota/settings.json` or `.robota/settings.local.json`:
152
143
 
@@ -159,26 +150,67 @@ Configure in `.robota/settings.json` or `.robota/settings.local.json`:
159
150
  }
160
151
  ```
161
152
 
162
- **Pattern syntax:**
153
+ Pattern syntax: `ToolName` matches any invocation; `ToolName(pattern)` matches on the primary argument with shell-style globs (`*`, `**`).
154
+
155
+ ## Keyboard Controls
156
+
157
+ | Key | Action |
158
+ | ---------- | ----------------------------------------------------------- |
159
+ | Enter | Submit input |
160
+ | ESC | Abort current execution (graceful — saves partial response) |
161
+ | Ctrl+C | Exit process immediately |
162
+ | Up/Down | Navigate visual lines in wrapped multi-line input |
163
+ | Arrow keys | Navigate slash command autocomplete, permission prompt |
164
+
165
+ ## Paste Handling
166
+
167
+ 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.
168
+
169
+ Single-line paste is inserted directly as typed text. Terminals without bracketed paste fall back to heuristic detection.
163
170
 
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)
171
+ ## Edit Diff Display
168
172
 
169
- **Evaluation order:** deny patterns are checked first, then allow patterns, then the mode policy. Deny always wins.
173
+ After the Edit tool runs, a `DiffBlock` component renders the change inline:
174
+
175
+ ```
176
+ ✓ Edit(src/provider.ts)
177
+ │ src/provider.ts
178
+ │ - const DEFAULT_MAX_TOKENS = 4096;
179
+ │ + const maxTokens = getModelMaxOutput(modelId);
180
+ ```
181
+
182
+ 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.
170
183
 
171
184
  ## Slash Commands
172
185
 
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 |
186
+ | Command | Description |
187
+ | ------------------------- | ---------------------------------------------------------- |
188
+ | `/help` | Show available commands |
189
+ | `/clear` | Clear conversation history |
190
+ | `/mode [mode]` | Show or change permission mode |
191
+ | `/model [model]` | Select AI model (confirmation prompt, CLI restarts) |
192
+ | `/language [lang]` | Set response language (ko, en, ja, zh), saves and restarts |
193
+ | `/compact [instructions]` | Compress context window |
194
+ | `/cost` | Show session info |
195
+ | `/context` | Context window details |
196
+ | `/permissions` | Show permission rules |
197
+ | `/plugin [subcommand]` | Plugin management TUI |
198
+ | `/exit` | Exit CLI |
199
+
200
+ Typing `/` triggers an autocomplete popup with arrow-key navigation, Tab completion, and Esc to dismiss. 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.
201
+
202
+ ## Plugin Management
203
+
204
+ The `/plugin` command opens an interactive TUI for managing bundle plugins:
205
+
206
+ | Subcommand | Description |
207
+ | -------------------------- | ------------------------------------------------ |
208
+ | `/plugin install <name>` | Install a plugin from marketplace or local path |
209
+ | `/plugin uninstall <name>` | Remove an installed plugin |
210
+ | `/plugin enable <name>` | Enable a disabled plugin |
211
+ | `/plugin disable <name>` | Disable a plugin without uninstalling |
212
+ | `/plugin list` | List installed plugins with status |
213
+ | `/plugin marketplace` | Browse available plugins from configured sources |
182
214
 
183
215
  ## Configuration
184
216
 
@@ -186,11 +218,14 @@ Settings are loaded from (highest priority first):
186
218
 
187
219
  1. `.robota/settings.local.json` (local, gitignored)
188
220
  2. `.robota/settings.json` (project, shared)
189
- 3. `~/.robota/settings.json` (user global)
221
+ 3. `.claude/settings.json` (project, Claude Code compatible)
222
+ 4. `~/.robota/settings.json` (user global)
223
+ 5. `~/.claude/settings.json` (user global, Claude Code compatible)
190
224
 
191
225
  ```json
192
226
  {
193
227
  "defaultMode": "default",
228
+ "language": "en",
194
229
  "provider": {
195
230
  "name": "anthropic",
196
231
  "model": "claude-sonnet-4-6",
@@ -203,14 +238,6 @@ Settings are loaded from (highest priority first):
203
238
  }
204
239
  ```
205
240
 
206
- ### Environment Variables
207
-
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.
213
-
214
241
  ## Context Discovery
215
242
 
216
243
  The CLI automatically discovers and loads:
@@ -219,36 +246,59 @@ The CLI automatically discovers and loads:
219
246
  - **CLAUDE.md** — same walk-up discovery
220
247
  - **Project metadata** — from `package.json`, `tsconfig.json`
221
248
 
222
- All context is assembled into the system prompt for the AI assistant.
249
+ All context is assembled into the system prompt.
250
+
251
+ ## Memory Management
252
+
253
+ - **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.
254
+ - **Tool state cleanup** — Completed tool execution states are trimmed to the most recent 50 entries.
255
+ - **React.memo** — `MessageItem` uses `React.memo` to skip redundant re-renders.
256
+
257
+ ## Session Logging
258
+
259
+ Session logs are written to `.robota/logs/{sessionId}.jsonl` in JSONL format by default, capturing structured events for diagnostics and replay.
223
260
 
224
261
  ## Architecture
225
262
 
226
263
  ```
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.)
264
+ bin.ts → cli.ts (arg parsing)
265
+ └── ui/render.tsx App.tsx (Ink TUI)
266
+ ├── MessageList.tsx
267
+ ├── InputArea.tsx (CjkTextInput, bracketed paste, slash detection)
268
+ ├── StatusBar.tsx (mode, model, context %, message count)
269
+ ├── PermissionPrompt.tsx (arrow-key Allow/Deny)
270
+ ├── SlashAutocomplete.tsx (command popup with scroll)
271
+ ├── DiffBlock.tsx (Edit tool diff display)
272
+ ├── MenuSelect.tsx (arrow-key menu, Plugin TUI)
273
+ ├── PluginTUI.tsx (plugin management screen stack)
274
+ ├── TextPrompt.tsx (text input for Plugin TUI)
275
+ ├── ConfirmPrompt.tsx (reusable yes/no prompt)
276
+ ├── CommandRegistry
277
+ │ ├── BuiltinCommandSource
278
+ │ ├── SkillCommandSource (discovers from 4 paths)
279
+ │ └── PluginCommandSource (from installed plugins)
280
+ └── Session (from @robota-sdk/agent-sessions)
240
281
  ```
241
282
 
242
- Tool calls flow through the permission system:
283
+ ## Dependencies
243
284
 
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
- ```
285
+ | Package | Purpose |
286
+ | --------------------------- | ------------------------------------------ |
287
+ | `@robota-sdk/agent-sdk` | Session factory, query, config, context |
288
+ | `@robota-sdk/agent-core` | Types (TPermissionMode, TToolArgs) |
289
+ | `ink`, `react` | TUI rendering |
290
+ | `ink-select-input` | Arrow-key selection (permission prompt) |
291
+ | `ink-spinner` | Loading spinner |
292
+ | `chalk` | Terminal colors |
293
+ | `ink-text-input` | Base text input (extended by CjkTextInput) |
294
+ | `marked`, `marked-terminal` | Markdown parsing and terminal rendering |
295
+ | `cli-highlight` | Syntax highlighting for code blocks |
296
+ | `string-width` | Unicode-aware string width (CJK support) |
297
+
298
+ ## Documentation
299
+
300
+ See [docs/SPEC.md](./docs/SPEC.md) for the full specification, architecture details, and design decisions.
301
+
302
+ ## License
303
+
304
+ MIT
package/dist/node/bin.js CHANGED
@@ -1,9 +1,19 @@
1
1
  #!/usr/bin/env node
2
2
  import {
3
3
  startCli
4
- } from "./chunk-4DYVT4WI.js";
4
+ } from "./chunk-KX3JUGSB.js";
5
5
 
6
6
  // src/bin.ts
7
+ process.on("uncaughtException", (err) => {
8
+ const msg = err.message ?? "";
9
+ const isLikelyIME = msg.includes("string-width") || msg.includes("setCursorPosition") || msg.includes("getStringWidth") || msg.includes("slice") || msg.includes("charCodeAt");
10
+ if (isLikelyIME) {
11
+ process.stderr.write(`[robota] IME error suppressed: ${msg}
12
+ `);
13
+ return;
14
+ }
15
+ throw err;
16
+ });
7
17
  startCli().catch((err) => {
8
18
  const message = err instanceof Error ? err.message : String(err);
9
19
  process.stderr.write(message + "\n");