@robota-sdk/agent-cli 3.0.0-beta.60 → 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 CHANGED
@@ -29,6 +29,7 @@ robota -p "List all files" # Print mode (one-shot, exit after response)
29
29
  | Variable | Description | Required |
30
30
  | ------------------- | ---------------------------------------------- | -------------- |
31
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 |
32
33
  | `DASHSCOPE_API_KEY` | Alibaba Cloud Model Studio key for `qwen` | Qwen only |
33
34
 
34
35
  Set your key before running:
@@ -130,7 +131,14 @@ When no usable settings file exists, the CLI prompts for:
130
131
 
131
132
  Creates `~/.robota/settings.json`. Use `robota --reset` to return to first-run state.
132
133
 
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.
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.
140
+
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.
134
142
 
135
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`.
136
144
 
@@ -151,12 +159,14 @@ The AI agent can invoke 8 local tools:
151
159
 
152
160
  ## Recent TUI Capabilities
153
161
 
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.
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.
155
165
  - Interactive startup can check npm for newer CLI versions; print/headless mode skips startup update checks to keep scripted output deterministic.
156
166
  - Long-running sessions show provider usage summaries, status activity, background job tree rows, and collapsed command-output transcripts.
157
167
  - Edit results render as context hunks with markdown-friendly diff blocks.
158
168
  - 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.
169
+ - Explicit multi-agent requests use the `/agent` command module batch path through the SDK runtime.
160
170
 
161
171
  ## Permission System
162
172
 
@@ -177,12 +187,12 @@ Every tool call passes through a three-step permission gate:
177
187
 
178
188
  ### Changing Mode at Runtime
179
189
 
180
- Use the `/mode` slash command:
190
+ Use the `/permissions` slash command:
181
191
 
182
192
  ```
183
- > /mode # Show current mode
184
- > /mode plan # Switch to plan (read-only)
185
- > /mode bypassPermissions # Skip all prompts
193
+ > /permissions # Show current mode and session-approved tools
194
+ > /permissions plan # Switch to plan (read-only)
195
+ > /permissions bypassPermissions # Skip all prompts
186
196
  ```
187
197
 
188
198
  Or set it at startup:
@@ -261,28 +271,27 @@ When a session has a name, it appears in three places:
261
271
 
262
272
  - **Input border** — session name shown in the input area border
263
273
  - **Terminal title** — updated via ANSI escape sequences
264
- - **StatusBar** — displayed alongside mode, model, and context usage
274
+ - **StatusBar** — displayed alongside activity, model, and context usage
265
275
 
266
276
  ## Slash Commands
267
277
 
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.
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.
286
295
 
287
296
  ## Plugin Management
288
297
 
@@ -315,26 +324,26 @@ Settings are merged in this order, from lowest to highest priority:
315
324
  {
316
325
  "defaultMode": "default",
317
326
  "language": "en",
318
- "currentProvider": "qwen",
327
+ "currentProvider": "qwen-plus",
319
328
  "providers": {
320
- "qwen": {
329
+ "qwen-plus": {
321
330
  "type": "qwen",
322
331
  "model": "qwen-plus",
323
332
  "apiKey": "$ENV:DASHSCOPE_API_KEY",
324
333
  "baseURL": "https://dashscope-intl.aliyuncs.com/compatible-mode/v1"
325
334
  },
326
- "gemma": {
335
+ "supergemma4-26b-uncensored-v2": {
327
336
  "type": "gemma",
328
337
  "model": "supergemma4-26b-uncensored-v2",
329
338
  "apiKey": "lm-studio",
330
339
  "baseURL": "http://localhost:1234/v1"
331
340
  },
332
- "openai": {
341
+ "gpt-4o": {
333
342
  "type": "openai",
334
- "model": "<openai-compatible-model>",
343
+ "model": "gpt-4o",
335
344
  "apiKey": "$ENV:OPENAI_API_KEY"
336
345
  },
337
- "anthropic": {
346
+ "claude-sonnet-4-6": {
338
347
  "type": "anthropic",
339
348
  "model": "claude-sonnet-4-6",
340
349
  "apiKey": "$ENV:ANTHROPIC_API_KEY"
@@ -347,7 +356,17 @@ Settings are merged in this order, from lowest to highest priority:
347
356
  }
348
357
  ```
349
358
 
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:
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:
351
370
 
352
371
  ```json
353
372
  {
@@ -369,6 +388,11 @@ The CLI automatically discovers and loads:
369
388
 
370
389
  All context is assembled into the system prompt.
371
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
+
372
396
  ## Memory Management
373
397
 
374
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.
@@ -392,14 +416,14 @@ bin.ts → cli.ts (arg parsing)
392
416
  │ ├── InteractiveSession (SDK)
393
417
  │ ├── CommandRegistry (SDK, re-exported by CLI)
394
418
  │ │ ├── BuiltinCommandSource (SDK, empty by default)
395
- │ │ ├── SkillCommandSource (SDK, discovers from 4 paths)
419
+ │ │ ├── agent-command-skills (/skills command + virtual skill aliases)
396
420
  │ │ ├── PluginCommandSource (SDK, plugin skills)
397
421
  │ │ └── ICommandModule sources (/help, /compact, ...)
398
422
  │ └── SystemCommandExecutor (SDK)
399
423
  ├── plugin-hooks-merger.ts (merges plugin hooks into SDK config)
400
424
  ├── MessageList.tsx
401
425
  ├── InputArea.tsx (CjkTextInput, bracketed paste, slash detection)
402
- ├── StatusBar.tsx (mode, model, context %, message count)
426
+ ├── StatusBar.tsx (activity, conditional mode, model, context %)
403
427
  ├── PermissionPrompt.tsx (arrow-key Allow/Deny)
404
428
  ├── SlashAutocomplete.tsx (command popup with scroll)
405
429
  ├── DiffBlock.tsx (Edit tool diff display)
package/dist/node/bin.js CHANGED
@@ -1,8 +1,8 @@
1
1
  #!/usr/bin/env node
2
2
  import {
3
3
  startCli
4
- } from "./chunk-GHQHUBHC.js";
5
- import "./chunk-6XQKLNRF.js";
4
+ } from "./chunk-J654S773.js";
5
+ import "./chunk-BENOH47A.js";
6
6
 
7
7
  // src/bin.ts
8
8
  process.on("uncaughtException", (err) => {
@@ -4,6 +4,7 @@ import { join } from "path";
4
4
 
5
5
  // src/utils/provider-default-definitions.ts
6
6
  import { createAnthropicProviderDefinition } from "@robota-sdk/agent-provider-anthropic";
7
+ import { createDeepSeekProviderDefinition } from "@robota-sdk/agent-provider-deepseek";
7
8
  import { createGemmaProviderDefinition } from "@robota-sdk/agent-provider-gemma";
8
9
  import { createGeminiProviderDefinition } from "@robota-sdk/agent-provider-gemini";
9
10
  import { createOpenAIProviderDefinition } from "@robota-sdk/agent-provider-openai";
@@ -13,11 +14,16 @@ var DEFAULT_PROVIDER_DEFINITIONS = [
13
14
  createOpenAIProviderDefinition(),
14
15
  createGeminiProviderDefinition(),
15
16
  createGemmaProviderDefinition(),
16
- createQwenProviderDefinition()
17
+ createQwenProviderDefinition(),
18
+ createDeepSeekProviderDefinition()
17
19
  ];
18
20
 
19
21
  // src/utils/provider-definition.ts
20
- import { findProviderDefinition, formatSupportedProviderTypes } from "@robota-sdk/agent-core";
22
+ import {
23
+ findProviderDefinition,
24
+ formatSupportedProviderTypes,
25
+ getProviderCredentialRequirement
26
+ } from "@robota-sdk/agent-core";
21
27
 
22
28
  // src/utils/env-ref.ts
23
29
  import {
@@ -163,8 +169,11 @@ function createProviderFromConfig(settings, providerDefinitions) {
163
169
  `Unknown provider: ${settings.name}. Currently supported: ${formatSupportedProviderTypes(providerDefinitions)}`
164
170
  );
165
171
  }
166
- if (definition.requiresApiKey === true && !settings.apiKey) {
167
- throw new Error(`Provider ${settings.name} requires apiKey`);
172
+ const credentialRequirement = getProviderCredentialRequirement(definition);
173
+ if (credentialRequirement !== void 0 && !hasRequiredProviderCredential(settings, credentialRequirement)) {
174
+ throw new Error(
175
+ `Provider ${settings.name} requires ${formatCredentialRequirement(credentialRequirement)}`
176
+ );
168
177
  }
169
178
  return definition.createProvider(settings);
170
179
  }
@@ -190,6 +199,16 @@ function createProviderFromProfile(profile, modelOverride, providerDefinitions =
190
199
  providerDefinitions
191
200
  );
192
201
  }
202
+ function hasRequiredProviderCredential(settings, requirement) {
203
+ return requirement.anyOf.some((field) => hasProviderCredentialValue(settings, field));
204
+ }
205
+ function hasProviderCredentialValue(settings, field) {
206
+ const value = settings[field];
207
+ return value !== void 0 && value.length > 0;
208
+ }
209
+ function formatCredentialRequirement(requirement) {
210
+ return requirement.anyOf.join(" or ");
211
+ }
193
212
  function getProviderDefinitions(options) {
194
213
  return options.providerDefinitions ?? DEFAULT_PROVIDER_DEFINITIONS;
195
214
  }
@@ -255,6 +274,7 @@ export {
255
274
  DEFAULT_PROVIDER_DEFINITIONS,
256
275
  findProviderDefinition,
257
276
  formatSupportedProviderTypes,
277
+ getProviderCredentialRequirement,
258
278
  hasUsableSecretReference,
259
279
  readProviderSettings,
260
280
  readMergedProviderSettings,