deepseek-coder-agent-cli 1.0.29 → 1.0.31

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,15 +1,6 @@
1
1
  # DeepSeek Coder CLI
2
2
 
3
- An AI-powered coding assistant for the terminal. Built for developers who prefer working in the command line.
4
-
5
- ## Features
6
-
7
- - **Interactive Shell** - Full-featured terminal interface with multi-line input support
8
- - **Code Editing** - Read, write, and edit files with AI assistance
9
- - **Bash Integration** - Execute shell commands with real-time status display
10
- - **Multi-Provider Support** - Works with DeepSeek, OpenAI, Anthropic, Google, and xAI
11
- - **Session Management** - Save and restore conversation sessions
12
- - **File Change Tracking** - Revert all changes made during a session with `/revert`
3
+ A multi-provider AI coding agent for the terminal. Switch between DeepSeek, OpenAI, Anthropic, Google, and xAI models with a single command.
13
4
 
14
5
  ## Installation
15
6
 
@@ -17,77 +8,94 @@ An AI-powered coding assistant for the terminal. Built for developers who prefer
17
8
  npm install -g deepseek-coder-agent-cli
18
9
  ```
19
10
 
20
- ## Setup
21
-
22
- Get your API key from [DeepSeek Platform](https://platform.deepseek.com/api_keys), then:
11
+ Requires Node.js 20+.
23
12
 
24
- ```bash
25
- deepseek --key YOUR_API_KEY
26
- ```
27
-
28
- Or set via environment variable:
13
+ ## Quick Start
29
14
 
30
15
  ```bash
16
+ # Set your API key
31
17
  export DEEPSEEK_API_KEY=your_key_here
32
- ```
33
18
 
34
- ## Usage
35
-
36
- ```bash
37
19
  # Start interactive mode
38
20
  deepseek
39
21
 
40
- # Start with an initial prompt
22
+ # Or start with a prompt
41
23
  deepseek "explain this codebase"
42
24
 
43
- # Quick mode (non-interactive, single response)
44
- deepseek -q "list all TypeScript files"
25
+ # Quick mode (single response, then exit)
26
+ deepseek -q "list all files"
45
27
  ```
46
28
 
29
+ ## Supported Providers
30
+
31
+ | Provider | Environment Variable | Models |
32
+ |----------|---------------------|--------|
33
+ | DeepSeek | `DEEPSEEK_API_KEY` | deepseek-reasoner, deepseek-chat |
34
+ | OpenAI | `OPENAI_API_KEY` | gpt-5.2-pro, gpt-5.2-codex, gpt-5.2-codex-mini |
35
+ | Anthropic | `ANTHROPIC_API_KEY` | claude-opus-4-5, claude-sonnet-4-5, claude-haiku-4-5 |
36
+ | Google | `GEMINI_API_KEY` | gemini-3.0-pro, gemini-2.5-flash |
37
+ | xAI | `XAI_API_KEY` | grok-4-1-fast-reasoning, grok-4 |
38
+ | Ollama | `OLLAMA_BASE_URL` | llama3.3:70b, llama3.2:3b (local) |
39
+ | Qwen | `DASHSCOPE_API_KEY` | qwen-max, qwen-turbo |
40
+
41
+ Use `/model` to switch providers and models interactively.
42
+
47
43
  ## Commands
48
44
 
49
45
  | Command | Description |
50
46
  |---------|-------------|
51
- | `/help` | Show help information |
52
- | `/exit` | Exit the shell |
53
- | `/model` | Switch AI model/provider |
54
- | `/context` | Refresh workspace context |
55
- | `/sessions` | Manage conversation sessions |
56
- | `/revert` | Revert file changes made this session |
57
- | `/tools` | Show available tools |
58
- | `/shortcuts` | Show keyboard shortcuts |
47
+ | `/model` | Switch model/provider |
48
+ | `/help` | Show all commands |
49
+ | `/exit` or `/quit` | Exit the CLI |
50
+ | `/clear` | Clear conversation history |
51
+ | `/compact` | Summarize conversation to save context |
52
+ | `/diff` | Show git diff of changes |
53
+ | `/undo` | Undo last turn |
54
+ | `/rewind` | Rewind to a checkpoint |
55
+ | `/sessions` | Manage saved sessions |
56
+ | `/resume` | Resume a previous session |
57
+ | `/export` | Export conversation to file |
58
+ | `/context` | Refresh workspace snapshot |
59
+ | `/status` | Show session config and token usage |
60
+ | `/cost` | Show API cost breakdown |
61
+ | `/tools` | Enable/disable tools |
62
+ | `/secrets` | Configure API keys |
63
+ | `/providers` | List configured providers |
64
+ | `/refresh-models` | Discover new models from APIs |
65
+ | `/doctor` | Check environment and tool readiness |
66
+ | `/thinking` | Toggle thinking mode (balanced/extended) |
67
+ | `/vim` | Toggle vim-style input editing |
59
68
 
60
69
  ## Keyboard Shortcuts
61
70
 
62
71
  | Shortcut | Action |
63
72
  |----------|--------|
64
- | `Ctrl+C` | Cancel current operation / Exit |
73
+ | `Ctrl+C` | Interrupt / Double-press to exit |
74
+ | `Ctrl+D` | Exit (when input empty) |
65
75
  | `Ctrl+U` | Clear input line |
76
+ | `Esc` | Interrupt AI response |
66
77
  | `Option+A` | Toggle auto-approve mode |
67
78
  | `Option+G` | Toggle agentic mode |
68
- | `Option+T` | Toggle thinking depth |
79
+ | `Option+T` | Cycle thinking depth |
80
+
81
+ ## Tools
69
82
 
70
- ## Tools Available to AI
83
+ The AI has access to these tools:
71
84
 
72
85
  | Tool | Description |
73
86
  |------|-------------|
74
- | `read_file` | Read file contents with line numbers |
75
- | `write_file` | Create or overwrite files |
76
- | `edit_file` | Make precise edits to existing files |
77
- | `bash` | Execute shell commands |
78
- | `search` | Search for files by pattern |
79
- | `grep` | Search file contents with regex |
80
- | `web_search` | Search the web for information |
81
-
82
- ## Supported Providers
83
-
84
- | Provider | Environment Variable | Models |
85
- |----------|---------------------|--------|
86
- | DeepSeek | `DEEPSEEK_API_KEY` | DeepSeek V3, DeepSeek Coder |
87
- | OpenAI | `OPENAI_API_KEY` | GPT-4, GPT-4o |
88
- | Anthropic | `ANTHROPIC_API_KEY` | Claude 3.5 Sonnet, Claude 3 Opus |
89
- | Google | `GOOGLE_API_KEY` | Gemini 2.0 |
90
- | xAI | `XAI_API_KEY` | Grok |
87
+ | `Read` | Read file contents |
88
+ | `Write` | Create or overwrite files |
89
+ | `Edit` | Make precise edits to files |
90
+ | `Bash` | Execute shell commands |
91
+ | `Glob` | Find files by pattern |
92
+ | `Grep` | Search file contents |
93
+ | `WebSearch` | Search the web |
94
+ | `WebFetch` | Fetch and analyze URLs |
95
+ | `LSP` | Language server operations (go to definition, find references) |
96
+ | `Task` | Launch background agents |
97
+ | `TodoWrite` | Track task progress |
98
+ | `HITL_Decision` | Request human input for decisions |
91
99
 
92
100
  ## CLI Options
93
101
 
@@ -95,27 +103,39 @@ deepseek -q "list all TypeScript files"
95
103
  deepseek [options] [prompt]
96
104
 
97
105
  Options:
98
- -v, --version Show version
99
- -h, --help Show help
100
- -q, --quick Quick mode (non-interactive)
101
- --provider <id> Select provider
102
- --model <name> Select model
103
- --key <api-key> Set API key
104
- --debug Enable debug logging
106
+ -v, --version Show version
107
+ -h, --help Show help
108
+ -q, --quick Quick mode (non-interactive)
109
+ --provider <id> Select provider (deepseek, openai, anthropic, google, xai)
110
+ --model <name> Select model
111
+ --profile <name> Use agent profile
112
+ --debug Enable debug logging
105
113
  ```
106
114
 
115
+ ## Configuration
116
+
117
+ Settings are stored in `~/.agi/`:
118
+ - `settings.json` - Model preferences per profile
119
+ - `secrets.json` - Encrypted API keys
120
+ - `discovered-models.json` - Cached model discovery
121
+
122
+ ## Features
123
+
124
+ - **Multi-provider**: Switch between 7 AI providers seamlessly
125
+ - **HITL (Human-in-the-Loop)**: AI requests approval for important decisions
126
+ - **Session persistence**: Save and resume conversations
127
+ - **Checkpoint/Rewind**: Undo changes and revert to previous states
128
+ - **Streaming**: Real-time response streaming with interrupt support
129
+ - **Context management**: Automatic summarization to stay within limits
130
+ - **Tool permissions**: Configure which tools require approval
131
+
107
132
  ## Development
108
133
 
109
134
  ```bash
110
- # Clone and install
111
- git clone https://github.com/anthropics/deepseek-cli.git
135
+ git clone <repo-url>
112
136
  cd deepseek-cli
113
137
  npm install
114
-
115
- # Build
116
138
  npm run build
117
-
118
- # Run locally
119
139
  npm start
120
140
  ```
121
141
 
@@ -0,0 +1,52 @@
1
+ /**
2
+ * Sudo Password Manager - handles sudo password caching and prompting
3
+ *
4
+ * This module provides a singleton manager for sudo passwords, allowing
5
+ * bash commands to run with sudo privileges by prompting the user for
6
+ * their password when needed.
7
+ */
8
+ import { EventEmitter } from 'node:events';
9
+ declare class SudoPasswordManager extends EventEmitter {
10
+ private cachedPassword;
11
+ private passwordValidUntil;
12
+ private readonly CACHE_DURATION_MS;
13
+ private pendingRequest;
14
+ /**
15
+ * Get the cached sudo password if still valid
16
+ */
17
+ getCachedPassword(): string | null;
18
+ /**
19
+ * Cache a sudo password
20
+ */
21
+ cachePassword(password: string): void;
22
+ /**
23
+ * Invalidate the cached password (e.g., if sudo fails)
24
+ */
25
+ invalidatePassword(): void;
26
+ /**
27
+ * Request a sudo password - emits 'password-needed' event
28
+ * Returns the password or null if cancelled
29
+ */
30
+ requestPassword(): Promise<string | null>;
31
+ /**
32
+ * Provide the password in response to a 'password-needed' event
33
+ */
34
+ providePassword(password: string | null): void;
35
+ /**
36
+ * Cancel the pending password request
37
+ */
38
+ cancelRequest(): void;
39
+ /**
40
+ * Check if there's a pending password request
41
+ */
42
+ hasPendingRequest(): boolean;
43
+ }
44
+ export declare const sudoPasswordManager: SudoPasswordManager;
45
+ export declare function getSudoPassword(): Promise<string | null>;
46
+ export declare function setCachedSudoPassword(password: string): void;
47
+ export declare function invalidateSudoPassword(): void;
48
+ export declare function onSudoPasswordNeeded(callback: () => void): void;
49
+ export declare function offSudoPasswordNeeded(callback: () => void): void;
50
+ export declare function provideSudoPassword(password: string | null): void;
51
+ export {};
52
+ //# sourceMappingURL=sudoPasswordManager.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"sudoPasswordManager.d.ts","sourceRoot":"","sources":["../../src/core/sudoPasswordManager.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH,OAAO,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC;AAO3C,cAAM,mBAAoB,SAAQ,YAAY;IAC5C,OAAO,CAAC,cAAc,CAAuB;IAC7C,OAAO,CAAC,kBAAkB,CAAa;IACvC,OAAO,CAAC,QAAQ,CAAC,iBAAiB,CAAiB;IACnD,OAAO,CAAC,cAAc,CAAoC;IAE1D;;OAEG;IACH,iBAAiB,IAAI,MAAM,GAAG,IAAI;IAOlC;;OAEG;IACH,aAAa,CAAC,QAAQ,EAAE,MAAM,GAAG,IAAI;IAKrC;;OAEG;IACH,kBAAkB,IAAI,IAAI;IAK1B;;;OAGG;IACG,eAAe,IAAI,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC;IA0B/C;;OAEG;IACH,eAAe,CAAC,QAAQ,EAAE,MAAM,GAAG,IAAI,GAAG,IAAI;IAY9C;;OAEG;IACH,aAAa,IAAI,IAAI;IAQrB;;OAEG;IACH,iBAAiB,IAAI,OAAO;CAG7B;AAGD,eAAO,MAAM,mBAAmB,qBAA4B,CAAC;AAG7D,wBAAgB,eAAe,IAAI,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC,CAExD;AAED,wBAAgB,qBAAqB,CAAC,QAAQ,EAAE,MAAM,GAAG,IAAI,CAE5D;AAED,wBAAgB,sBAAsB,IAAI,IAAI,CAE7C;AAED,wBAAgB,oBAAoB,CAAC,QAAQ,EAAE,MAAM,IAAI,GAAG,IAAI,CAE/D;AAED,wBAAgB,qBAAqB,CAAC,QAAQ,EAAE,MAAM,IAAI,GAAG,IAAI,CAEhE;AAED,wBAAgB,mBAAmB,CAAC,QAAQ,EAAE,MAAM,GAAG,IAAI,GAAG,IAAI,CAEjE"}
@@ -0,0 +1,115 @@
1
+ /**
2
+ * Sudo Password Manager - handles sudo password caching and prompting
3
+ *
4
+ * This module provides a singleton manager for sudo passwords, allowing
5
+ * bash commands to run with sudo privileges by prompting the user for
6
+ * their password when needed.
7
+ */
8
+ import { EventEmitter } from 'node:events';
9
+ class SudoPasswordManager extends EventEmitter {
10
+ cachedPassword = null;
11
+ passwordValidUntil = 0;
12
+ CACHE_DURATION_MS = 5 * 60 * 1000; // 5 minutes (matches typical sudo timeout)
13
+ pendingRequest = null;
14
+ /**
15
+ * Get the cached sudo password if still valid
16
+ */
17
+ getCachedPassword() {
18
+ if (this.cachedPassword && Date.now() < this.passwordValidUntil) {
19
+ return this.cachedPassword;
20
+ }
21
+ return null;
22
+ }
23
+ /**
24
+ * Cache a sudo password
25
+ */
26
+ cachePassword(password) {
27
+ this.cachedPassword = password;
28
+ this.passwordValidUntil = Date.now() + this.CACHE_DURATION_MS;
29
+ }
30
+ /**
31
+ * Invalidate the cached password (e.g., if sudo fails)
32
+ */
33
+ invalidatePassword() {
34
+ this.cachedPassword = null;
35
+ this.passwordValidUntil = 0;
36
+ }
37
+ /**
38
+ * Request a sudo password - emits 'password-needed' event
39
+ * Returns the password or null if cancelled
40
+ */
41
+ async requestPassword() {
42
+ // Check cache first
43
+ const cached = this.getCachedPassword();
44
+ if (cached) {
45
+ return cached;
46
+ }
47
+ // If there's already a pending request, wait for it
48
+ if (this.pendingRequest) {
49
+ return new Promise((resolve, reject) => {
50
+ // Subscribe to the same request
51
+ const originalResolve = this.pendingRequest.resolve;
52
+ this.pendingRequest.resolve = (password) => {
53
+ originalResolve(password);
54
+ resolve(password);
55
+ };
56
+ });
57
+ }
58
+ // Create new request
59
+ return new Promise((resolve, reject) => {
60
+ this.pendingRequest = { resolve, reject };
61
+ this.emit('password-needed');
62
+ });
63
+ }
64
+ /**
65
+ * Provide the password in response to a 'password-needed' event
66
+ */
67
+ providePassword(password) {
68
+ if (this.pendingRequest) {
69
+ const request = this.pendingRequest;
70
+ this.pendingRequest = null;
71
+ if (password) {
72
+ this.cachePassword(password);
73
+ }
74
+ request.resolve(password);
75
+ }
76
+ }
77
+ /**
78
+ * Cancel the pending password request
79
+ */
80
+ cancelRequest() {
81
+ if (this.pendingRequest) {
82
+ const request = this.pendingRequest;
83
+ this.pendingRequest = null;
84
+ request.resolve(null);
85
+ }
86
+ }
87
+ /**
88
+ * Check if there's a pending password request
89
+ */
90
+ hasPendingRequest() {
91
+ return this.pendingRequest !== null;
92
+ }
93
+ }
94
+ // Singleton instance
95
+ export const sudoPasswordManager = new SudoPasswordManager();
96
+ // Convenience exports
97
+ export function getSudoPassword() {
98
+ return sudoPasswordManager.requestPassword();
99
+ }
100
+ export function setCachedSudoPassword(password) {
101
+ sudoPasswordManager.cachePassword(password);
102
+ }
103
+ export function invalidateSudoPassword() {
104
+ sudoPasswordManager.invalidatePassword();
105
+ }
106
+ export function onSudoPasswordNeeded(callback) {
107
+ sudoPasswordManager.on('password-needed', callback);
108
+ }
109
+ export function offSudoPasswordNeeded(callback) {
110
+ sudoPasswordManager.off('password-needed', callback);
111
+ }
112
+ export function provideSudoPassword(password) {
113
+ sudoPasswordManager.providePassword(password);
114
+ }
115
+ //# sourceMappingURL=sudoPasswordManager.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"sudoPasswordManager.js","sourceRoot":"","sources":["../../src/core/sudoPasswordManager.ts"],"names":[],"mappings":"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"}
@@ -1 +1 @@
1
- {"version":3,"file":"interactiveShell.d.ts","sourceRoot":"","sources":["../../src/headless/interactiveShell.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;GAaG;AAwJH,MAAM,WAAW,uBAAuB;IACtC,IAAI,EAAE,MAAM,EAAE,CAAC;CAChB;AAOD;;GAEG;AACH,wBAAsB,mBAAmB,CAAC,OAAO,EAAE,uBAAuB,GAAG,OAAO,CAAC,IAAI,CAAC,CAuDzF"}
1
+ {"version":3,"file":"interactiveShell.d.ts","sourceRoot":"","sources":["../../src/headless/interactiveShell.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;GAaG;AAyJH,MAAM,WAAW,uBAAuB;IACtC,IAAI,EAAE,MAAM,EAAE,CAAC;CAChB;AAOD;;GAEG;AACH,wBAAsB,mBAAmB,CAAC,OAAO,EAAE,uBAAuB,GAAG,OAAO,CAAC,IAAI,CAAC,CAuDzF"}
@@ -49,6 +49,7 @@ import { getSelfUpgrade, SelfUpgrade, resumeAfterUpgrade } from '../core/selfUpg
49
49
  import { getHotReload } from '../core/hotReload.js';
50
50
  import { theme } from '../ui/theme.js';
51
51
  import { startNewRun } from '../tools/fileChangeTracker.js';
52
+ import { onSudoPasswordNeeded, offSudoPasswordNeeded, provideSudoPassword } from '../core/sudoPasswordManager.js';
52
53
  // Timeout constants for attack tournament - balanced for model response time
53
54
  const ATTACK_AGENT_STEP_TIMEOUT_MS = 24 * 60 * 60 * 1000; // 24 hours per agent step - effectively infinite
54
55
  const ATTACK_REASONING_TIMEOUT_MS = 24 * 60 * 60 * 1000; // 24 hours max for reasoning-only before forcing action
@@ -384,6 +385,8 @@ class InteractiveShell {
384
385
  // Start the UI
385
386
  this.promptController.start();
386
387
  this.applyDebugState(this.debugEnabled);
388
+ // Set up sudo password prompt handler
389
+ this.setupSudoPasswordHandler();
387
390
  // Set initial status
388
391
  this.promptController.setChromeMeta({
389
392
  profile: this.profile,
@@ -474,6 +477,50 @@ class InteractiveShell {
474
477
  // Ignore errors clearing pinned prompt
475
478
  }
476
479
  }
480
+ /**
481
+ * Set up handler for sudo password prompts from bash tool execution.
482
+ * When a sudo command needs a password, this prompts the user securely.
483
+ */
484
+ sudoPasswordHandler = null;
485
+ setupSudoPasswordHandler() {
486
+ this.sudoPasswordHandler = async () => {
487
+ const renderer = this.promptController?.getRenderer();
488
+ if (!renderer) {
489
+ provideSudoPassword(null);
490
+ return;
491
+ }
492
+ try {
493
+ // Show password prompt
494
+ renderer.addEvent('system', chalk.yellow('🔐 Sudo password required'));
495
+ renderer.setSecretMode(true);
496
+ renderer.clearBuffer();
497
+ // Capture password input
498
+ const password = await renderer.captureInput({ allowEmpty: false, trim: true, resetBuffer: true });
499
+ // Hide password mode
500
+ renderer.setSecretMode(false);
501
+ if (password) {
502
+ provideSudoPassword(password);
503
+ renderer.addEvent('system', chalk.green('✓ Password provided'));
504
+ }
505
+ else {
506
+ provideSudoPassword(null);
507
+ renderer.addEvent('system', chalk.yellow('Sudo cancelled'));
508
+ }
509
+ }
510
+ catch (error) {
511
+ renderer.setSecretMode(false);
512
+ provideSudoPassword(null);
513
+ renderer.addEvent('system', chalk.red('Password prompt cancelled'));
514
+ }
515
+ };
516
+ onSudoPasswordNeeded(this.sudoPasswordHandler);
517
+ }
518
+ cleanupSudoPasswordHandler() {
519
+ if (this.sudoPasswordHandler) {
520
+ offSudoPasswordNeeded(this.sudoPasswordHandler);
521
+ this.sudoPasswordHandler = null;
522
+ }
523
+ }
477
524
  applyDebugState(enabled, statusMessage) {
478
525
  this.debugEnabled = enabled;
479
526
  setDebugMode(enabled);
@@ -3727,6 +3774,7 @@ Any text response is a failure. Only tool calls are accepted.`;
3727
3774
  }
3728
3775
  handleExit() {
3729
3776
  this.shouldExit = true;
3777
+ this.cleanupSudoPasswordHandler();
3730
3778
  this.promptController?.stop();
3731
3779
  void authorizedShutdown(0);
3732
3780
  }