@bniladridas/cursor 0.1.17 → 0.1.19
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/.github/workflows/release.yml +2 -0
- package/AGENTS.md +66 -36
- package/CMakeLists.txt +54 -10
- package/DESIGN.md +775 -0
- package/README.md +10 -5
- package/cli.js +26 -3
- package/include/agent.h +55 -6
- package/include/services/ai_service.h +3 -0
- package/include/services/git_service.h +4 -0
- package/include/utils/platform.h +2 -2
- package/include/utils/ui.h +19 -0
- package/install.js +1 -0
- package/install.sh +2 -1
- package/package.json +3 -2
- package/release/checksums.txt +4 -4
- package/release/cursor-linux/cursor_v0.1.19_linux_amd64.tar.gz +0 -0
- package/release/cursor-macos/cursor-0.1.19.arm64_sequoia.bottle.tar.gz +0 -0
- package/release/cursor-macos/cursor_v0.1.19_darwin_arm64.tar.gz +0 -0
- package/release/cursor-windows/cursor__windows_amd64.zip +0 -0
- package/src/agent.cpp +1129 -157
- package/src/main.cpp +4 -1
- package/src/services/ai_service.cpp +7 -23
- package/src/services/git_service.cpp +45 -1
- package/src/services/web_service.cpp +7 -3
- package/src/utils/ui.cpp +94 -8
- package/src/utils/version.cpp +48 -15
- package/tests/e2e/run_local_batch.sh +131 -0
- package/tests/main_test.cpp +163 -0
- package/release/cursor-linux/cursor_v0.1.17_linux_amd64.tar.gz +0 -0
- package/release/cursor-macos/cursor-0.1.17.arm64_sequoia.bottle.tar.gz +0 -0
- package/release/cursor-macos/cursor_v0.1.17_darwin_arm64.tar.gz +0 -0
package/README.md
CHANGED
|
@@ -14,18 +14,23 @@ Cursor is a cross-platform AI coding agent that works with codebases, files, com
|
|
|
14
14
|
npm i -g @bniladridas/cursor
|
|
15
15
|
```
|
|
16
16
|
|
|
17
|
-
**Homebrew** (binary: `cursor-agent`):
|
|
17
|
+
**Homebrew** (binary: `cursor-agent` / `cursor`):
|
|
18
18
|
```bash
|
|
19
19
|
brew tap palmshed/cursor
|
|
20
|
-
brew install cursor
|
|
20
|
+
brew install palmshed/cursor/cursor --formula
|
|
21
21
|
```
|
|
22
22
|
|
|
23
|
-
**Curl** (binary: `cursor-agent`):
|
|
23
|
+
**Curl** (binary: `cursor-agent` / `cursor`):
|
|
24
24
|
```bash
|
|
25
|
-
curl -fsSL https://github.com/bniladridas/cursor/raw/main/install.sh | sh
|
|
25
|
+
curl -fsSL https://github.com/bniladridas/cursor/raw/main/install.sh | sudo sh
|
|
26
26
|
```
|
|
27
27
|
|
|
28
|
-
|
|
28
|
+
To install to a writable directory without `sudo`:
|
|
29
|
+
```bash
|
|
30
|
+
curl -fsSL https://github.com/bniladridas/cursor/raw/main/install.sh | INSTALL_DIR=~/.local/bin sh
|
|
31
|
+
```
|
|
32
|
+
|
|
33
|
+
**From source** (binary: `cursor-agent`):
|
|
29
34
|
```bash
|
|
30
35
|
cmake -S . -B build && cmake --build build
|
|
31
36
|
./build/cursor-tests # run tests
|
package/cli.js
CHANGED
|
@@ -7,10 +7,33 @@ const binaryDir = path.join(__dirname, 'binary');
|
|
|
7
7
|
const ext = process.platform === 'win32' ? '.exe' : '';
|
|
8
8
|
const binary = path.join(binaryDir, `cursor-agent${ext}`);
|
|
9
9
|
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
10
|
+
function looksLikeBinary(filePath) {
|
|
11
|
+
try {
|
|
12
|
+
const stat = fs.statSync(filePath);
|
|
13
|
+
if (stat.size < 50000) return false;
|
|
14
|
+
const fd = fs.openSync(filePath, 'r');
|
|
15
|
+
const buf = Buffer.alloc(4);
|
|
16
|
+
fs.readSync(fd, buf, 0, 4, 0);
|
|
17
|
+
fs.closeSync(fd);
|
|
18
|
+
return buf[0] !== 0x3c && buf[0] !== 0x7b && buf[0] !== 0x23;
|
|
19
|
+
} catch {
|
|
20
|
+
return false;
|
|
21
|
+
}
|
|
13
22
|
}
|
|
14
23
|
|
|
24
|
+
function validateBinary() {
|
|
25
|
+
if (!fs.existsSync(binary)) {
|
|
26
|
+
console.error('cursor binary not found. Run `npm install` to download it.');
|
|
27
|
+
process.exit(1);
|
|
28
|
+
}
|
|
29
|
+
if (!looksLikeBinary(binary)) {
|
|
30
|
+
console.error('cursor binary appears corrupted (downloaded an HTML/text file instead of an executable).');
|
|
31
|
+
console.error('Restore a working binary, or run `npm install` to reinstall.');
|
|
32
|
+
process.exit(1);
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
validateBinary();
|
|
37
|
+
|
|
15
38
|
const proc = spawn(binary, process.argv.slice(2), { stdio: 'inherit' });
|
|
16
39
|
proc.on('exit', (code) => process.exit(code));
|
package/include/agent.h
CHANGED
|
@@ -1,6 +1,8 @@
|
|
|
1
1
|
#pragma once
|
|
2
2
|
#include "agent_mode.h"
|
|
3
3
|
#include "utils/config.h" // For CURSOR_API
|
|
4
|
+
#include <map>
|
|
5
|
+
#include <optional>
|
|
4
6
|
#include <memory>
|
|
5
7
|
#include <string>
|
|
6
8
|
#include <vector>
|
|
@@ -19,11 +21,21 @@ class CURSOR_API Agent {
|
|
|
19
21
|
public:
|
|
20
22
|
using Mode = AgentMode; // Type alias for backward compatibility
|
|
21
23
|
|
|
24
|
+
struct AgentTask {
|
|
25
|
+
int id;
|
|
26
|
+
std::string description;
|
|
27
|
+
bool completed;
|
|
28
|
+
};
|
|
29
|
+
|
|
22
30
|
private:
|
|
23
31
|
Mode mode_{Mode::MODE_UNSET};
|
|
24
32
|
std::string api_key_;
|
|
33
|
+
std::string ollama_model_;
|
|
25
34
|
bool shell_mode_{false};
|
|
26
|
-
|
|
35
|
+
bool verbose_mode_{false};
|
|
36
|
+
std::string active_goal_;
|
|
37
|
+
std::vector<AgentTask> tasks_;
|
|
38
|
+
std::map<std::string, std::string> agent_params_;
|
|
27
39
|
std::unique_ptr<Data::MemoryManager> memory_;
|
|
28
40
|
std::unique_ptr<Services::AIService> ai_service_;
|
|
29
41
|
int command_count_{0};
|
|
@@ -39,15 +51,31 @@ public:
|
|
|
39
51
|
Agent &operator=(const Agent &) = delete;
|
|
40
52
|
|
|
41
53
|
void initialize_mode();
|
|
42
|
-
int
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
54
|
+
int show_menu(const std::string &title,
|
|
55
|
+
const std::vector<std::string> &items,
|
|
56
|
+
int default_index);
|
|
57
|
+
std::string process_user_input(const std::string &input);
|
|
46
58
|
void handle_direct_command(const std::string &input);
|
|
47
|
-
|
|
59
|
+
std::string handle_ai_chat(const std::string &input);
|
|
48
60
|
void handle_file_injection_command(const std::string &input);
|
|
49
61
|
void handle_shell_command(const std::string &input);
|
|
50
62
|
void handle_meta_command(const std::string &input);
|
|
63
|
+
void handle_agentic_command(const std::string &command);
|
|
64
|
+
void show_agentic_help();
|
|
65
|
+
void set_goal(const std::string &goal);
|
|
66
|
+
void show_goal() const;
|
|
67
|
+
void clear_goal();
|
|
68
|
+
void add_task(const std::string &task_description);
|
|
69
|
+
void list_tasks() const;
|
|
70
|
+
void complete_task(const std::string &args);
|
|
71
|
+
void remove_task(const std::string &args);
|
|
72
|
+
void set_param(const std::string ¶m_string);
|
|
73
|
+
void show_params() const;
|
|
74
|
+
std::string build_agent_context() const;
|
|
75
|
+
static bool is_direct_command_input(const std::string &input);
|
|
76
|
+
static bool is_git_status_query(const std::string &input);
|
|
77
|
+
static std::optional<std::string> map_nl_to_direct_command(
|
|
78
|
+
const std::string &input);
|
|
51
79
|
|
|
52
80
|
// File injection helpers
|
|
53
81
|
std::string process_file_injections(const std::string &input);
|
|
@@ -62,6 +90,7 @@ public:
|
|
|
62
90
|
void clear_screen();
|
|
63
91
|
void handle_chat_management(const std::string &command);
|
|
64
92
|
void show_available_tools();
|
|
93
|
+
void show_agent_documentation();
|
|
65
94
|
void show_memory_context();
|
|
66
95
|
void add_to_memory(const std::string &text);
|
|
67
96
|
void compress_context();
|
|
@@ -76,11 +105,31 @@ public:
|
|
|
76
105
|
void handle_sandbox_command(const std::string &command);
|
|
77
106
|
void handle_error_command(const std::string &command);
|
|
78
107
|
|
|
108
|
+
void toggle_verbose_mode();
|
|
109
|
+
void show_reasoning_header(const std::string &operation_type);
|
|
110
|
+
void show_pipeline_section(const std::string §ion_title);
|
|
111
|
+
void show_reasoning_step(const std::string &label,
|
|
112
|
+
const std::string &detail);
|
|
113
|
+
void show_parsed_input(const std::string &input,
|
|
114
|
+
const std::string &parsed_as);
|
|
115
|
+
void show_context_state();
|
|
116
|
+
void show_ai_prompt(const std::string &system_prompt,
|
|
117
|
+
const std::string &user_input);
|
|
118
|
+
void show_operation_result(const std::string &operation,
|
|
119
|
+
const std::string &result);
|
|
120
|
+
void show_search_results(const std::string &query,
|
|
121
|
+
const std::vector<std::string> &results);
|
|
122
|
+
void show_git_status_results(const std::vector<std::string> &files);
|
|
123
|
+
void show_file_preview(const std::string &filename, const std::string &content, int max_lines = 20);
|
|
124
|
+
|
|
79
125
|
[[nodiscard]] bool is_online_mode() const;
|
|
80
126
|
|
|
81
127
|
Agent();
|
|
82
128
|
~Agent();
|
|
83
129
|
|
|
84
130
|
void run();
|
|
131
|
+
|
|
132
|
+
static std::string format_message(const std::string &sender,
|
|
133
|
+
const std::string &content);
|
|
85
134
|
};
|
|
86
135
|
} // namespace Core
|
|
@@ -12,6 +12,7 @@ class AIService {
|
|
|
12
12
|
private:
|
|
13
13
|
Core::AgentMode mode_;
|
|
14
14
|
std::string api_key_;
|
|
15
|
+
std::string model_name_;
|
|
15
16
|
|
|
16
17
|
[[nodiscard]] bool is_online_mode() const;
|
|
17
18
|
nlohmann::json create_standard_payload(const std::string &model,
|
|
@@ -25,6 +26,8 @@ private:
|
|
|
25
26
|
public:
|
|
26
27
|
AIService(Core::AgentMode mode, const std::string &api_key = "");
|
|
27
28
|
|
|
29
|
+
void set_model_name(const std::string &name) { model_name_ = name; }
|
|
30
|
+
|
|
28
31
|
std::string chat(const std::string &user_input, const std::string &context);
|
|
29
32
|
bool is_available();
|
|
30
33
|
};
|
|
@@ -18,6 +18,10 @@ public:
|
|
|
18
18
|
// Get git status
|
|
19
19
|
static std::string get_git_status(const std::string &path);
|
|
20
20
|
|
|
21
|
+
// Get list of files changed in working tree (staged, unstaged, untracked)
|
|
22
|
+
static std::vector<std::string> get_working_tree_changed_files(
|
|
23
|
+
const std::string &path);
|
|
24
|
+
|
|
21
25
|
// Get list of files changed in last N days
|
|
22
26
|
static std::vector<std::string> get_changed_files(const std::string &path,
|
|
23
27
|
int days = 7);
|
package/include/utils/platform.h
CHANGED
|
@@ -9,14 +9,14 @@
|
|
|
9
9
|
#define NULL_DEVICE "NUL"
|
|
10
10
|
#define PATH_SEPARATOR "\\"
|
|
11
11
|
#define SHELL_REDIRECT " 2>NUL"
|
|
12
|
-
#define SHELL_REDIRECT_BOTH "
|
|
12
|
+
#define SHELL_REDIRECT_BOTH " 2>&1"
|
|
13
13
|
#else
|
|
14
14
|
#include <sys/wait.h>
|
|
15
15
|
#include <unistd.h>
|
|
16
16
|
#define NULL_DEVICE "/dev/null"
|
|
17
17
|
#define PATH_SEPARATOR "/"
|
|
18
18
|
#define SHELL_REDIRECT " 2>/dev/null"
|
|
19
|
-
#define SHELL_REDIRECT_BOTH "
|
|
19
|
+
#define SHELL_REDIRECT_BOTH " 2>&1"
|
|
20
20
|
#endif
|
|
21
21
|
|
|
22
22
|
#include <cstdio>
|
package/include/utils/ui.h
CHANGED
|
@@ -39,5 +39,24 @@ CURSOR_API void print_system_info(const std::string &mode,
|
|
|
39
39
|
CURSOR_API void print_ready_interface(const std::string &mode,
|
|
40
40
|
const std::string &model);
|
|
41
41
|
CURSOR_API std::string prompt_user(const std::string &prompt_text);
|
|
42
|
+
|
|
43
|
+
// Terminal management (chat mode)
|
|
44
|
+
CURSOR_API int get_terminal_width();
|
|
45
|
+
CURSOR_API int get_terminal_height();
|
|
46
|
+
CURSOR_API void clear_screen();
|
|
47
|
+
CURSOR_API void enter_chat_mode();
|
|
48
|
+
CURSOR_API void exit_chat_mode();
|
|
49
|
+
CURSOR_API void clear_line();
|
|
50
|
+
CURSOR_API void cursor_to(int line, int col);
|
|
51
|
+
CURSOR_API void draw_status_line(const std::string &mode,
|
|
52
|
+
const std::string &model,
|
|
53
|
+
const std::string &dir);
|
|
54
|
+
CURSOR_API void draw_context_line(const std::string &hints);
|
|
55
|
+
CURSOR_API void draw_input_bar(const std::string &text = "",
|
|
56
|
+
int cursor_pos = -1);
|
|
57
|
+
|
|
58
|
+
// Mouse support
|
|
59
|
+
CURSOR_API void enable_mouse();
|
|
60
|
+
CURSOR_API void disable_mouse();
|
|
42
61
|
} // namespace UI
|
|
43
62
|
} // namespace Utils
|
package/install.js
CHANGED
package/install.sh
CHANGED
|
@@ -46,6 +46,7 @@ tar -xzf "$TMPDIR/$ARCHIVE" -C "$TMPDIR"
|
|
|
46
46
|
mkdir -p "$INSTALL_DIR"
|
|
47
47
|
cp "$TMPDIR/$BINARY" "$INSTALL_DIR/cursor-agent"
|
|
48
48
|
chmod +x "$INSTALL_DIR/cursor-agent"
|
|
49
|
+
ln -sf cursor-agent "$INSTALL_DIR/cursor"
|
|
49
50
|
|
|
50
51
|
echo "installed cursor-agent to $INSTALL_DIR/cursor-agent"
|
|
51
|
-
echo "run: cursor-agent --help"
|
|
52
|
+
echo "run: cursor or cursor-agent --help"
|
package/package.json
CHANGED
|
@@ -1,9 +1,10 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@bniladridas/cursor",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.19",
|
|
4
4
|
"description": "Cross-platform AI coding agent",
|
|
5
5
|
"bin": {
|
|
6
|
-
"cursor": "cli.js"
|
|
6
|
+
"cursor": "cli.js",
|
|
7
|
+
"cursor-agent": "cli.js"
|
|
7
8
|
},
|
|
8
9
|
"scripts": {
|
|
9
10
|
"postinstall": "node install.js"
|
package/release/checksums.txt
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
1
|
+
87ea090028e086dc2cc408c55060c667aacf4cbe620e809e308ed1886d323d7b release/cursor-macos/cursor-0.1.19.arm64_sequoia.bottle.tar.gz
|
|
2
|
+
ec2f81ffc07d27813ec1f9300a8590ed004a22427c3cb6df1234bf4f5df974eb release/cursor-macos/cursor_v0.1.19_darwin_arm64.tar.gz
|
|
3
|
+
7763a5ecfa34da1c6b651b5a300b1ebd25cbbb288deec17bbf6eab2a0091938b release/cursor-linux/cursor_v0.1.19_linux_amd64.tar.gz
|
|
4
|
+
7c71c0604063ef86298eee60029a287cd9d39323862a72dc98661d03ea57a9cb release/cursor-windows/cursor__windows_amd64.zip
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|