@bniladridas/cursor 0.1.7

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.
Files changed (100) hide show
  1. package/.clang-tidy +28 -0
  2. package/.dockerignore +56 -0
  3. package/.env.example +29 -0
  4. package/.github/CODEOWNERS +2 -0
  5. package/.github/ISSUE_TEMPLATE/blank.md +27 -0
  6. package/.github/ISSUE_TEMPLATE/bug_report.md +33 -0
  7. package/.github/ISSUE_TEMPLATE/feature_request.md +24 -0
  8. package/.github/SECURITY.md +24 -0
  9. package/.github/codeql/codeql-config.yml +8 -0
  10. package/.github/dependabot.yml +14 -0
  11. package/.github/labeler.yml +50 -0
  12. package/.github/packaging/brand-cursor.png +0 -0
  13. package/.github/packaging/database/init.sql +48 -0
  14. package/.github/packaging/docker/Dockerfile +111 -0
  15. package/.github/packaging/docker/docker-compose.yml +56 -0
  16. package/.github/packaging/scripts/preflight.sh +413 -0
  17. package/.github/packaging/scripts/prepare-release.sh +141 -0
  18. package/.github/packaging/scripts/release.sh +22 -0
  19. package/.github/packaging/scripts/setup-git-hooks.sh +73 -0
  20. package/.github/pull_request_template.md +31 -0
  21. package/.github/signed.json +9 -0
  22. package/.github/workflows/README.md +23 -0
  23. package/.github/workflows/ci.yml +181 -0
  24. package/.github/workflows/cla.yml +33 -0
  25. package/.github/workflows/formula-sha.yml +63 -0
  26. package/.github/workflows/issue-response.yml +44 -0
  27. package/.github/workflows/labeler.yml +42 -0
  28. package/.github/workflows/pr-body.yml +49 -0
  29. package/.github/workflows/release.yml +176 -0
  30. package/.github/workflows/security.yml +94 -0
  31. package/.github/workflows/stale.yml +38 -0
  32. package/AGENTS.md +49 -0
  33. package/CHANGELOG.md +3 -0
  34. package/CMakeLists.txt +646 -0
  35. package/Formula/cursor.rb +46 -0
  36. package/LICENSE +201 -0
  37. package/Makefile +28 -0
  38. package/README.md +46 -0
  39. package/cli.js +16 -0
  40. package/include/agent.h +86 -0
  41. package/include/agent_mode.h +17 -0
  42. package/include/memory_manager.h +102 -0
  43. package/include/services/ai_service.h +31 -0
  44. package/include/services/auth_service.h +87 -0
  45. package/include/services/checkpoint_service.h +69 -0
  46. package/include/services/codebase_service.h +38 -0
  47. package/include/services/command_service.h +23 -0
  48. package/include/services/context_service.h +74 -0
  49. package/include/services/database_service.h +56 -0
  50. package/include/services/error_service.h +106 -0
  51. package/include/services/file_service.h +51 -0
  52. package/include/services/git_service.h +29 -0
  53. package/include/services/github_service.h +85 -0
  54. package/include/services/mcp_service.h +85 -0
  55. package/include/services/multi_file_service.h +93 -0
  56. package/include/services/sandbox_service.h +96 -0
  57. package/include/services/theme_service.h +67 -0
  58. package/include/services/web_service.h +52 -0
  59. package/include/utils/config.h +68 -0
  60. package/include/utils/memory_utils.h +79 -0
  61. package/include/utils/platform.h +56 -0
  62. package/include/utils/ui.h +43 -0
  63. package/include/utils/validation.h +63 -0
  64. package/include/utils/version.h.in +17 -0
  65. package/install.js +49 -0
  66. package/package.json +16 -0
  67. package/release/checksums.txt +3 -0
  68. package/release/cursor-linux/cursor_v0.1.7_linux_amd64.tar.gz +0 -0
  69. package/release/cursor-macos/cursor_v0.1.7_darwin_arm64.tar.gz +0 -0
  70. package/release/cursor-windows/cursor__windows_amd64.zip +0 -0
  71. package/src/agent.cpp +2026 -0
  72. package/src/main.cpp +97 -0
  73. package/src/memory_manager.cpp +814 -0
  74. package/src/services/ai_service.cpp +366 -0
  75. package/src/services/auth_service.cpp +779 -0
  76. package/src/services/checkpoint_service.cpp +465 -0
  77. package/src/services/codebase_service.cpp +233 -0
  78. package/src/services/command_service.cpp +82 -0
  79. package/src/services/context_service.cpp +348 -0
  80. package/src/services/database_service.cpp +148 -0
  81. package/src/services/error_service.cpp +438 -0
  82. package/src/services/file_service.cpp +349 -0
  83. package/src/services/git_service.cpp +148 -0
  84. package/src/services/github_service.cpp +435 -0
  85. package/src/services/mcp_service.cpp +481 -0
  86. package/src/services/multi_file_service.cpp +591 -0
  87. package/src/services/sandbox_service.cpp +678 -0
  88. package/src/services/theme_service.cpp +429 -0
  89. package/src/services/web_service.cpp +532 -0
  90. package/src/utils/config.cpp +77 -0
  91. package/src/utils/memory_utils.cpp +93 -0
  92. package/src/utils/ui.cpp +307 -0
  93. package/src/utils/validation.cpp +306 -0
  94. package/src/utils/version.cpp +175 -0
  95. package/tests/e2e/docker-compose.yml +195 -0
  96. package/tests/e2e/run_e2e_tests.sh +70 -0
  97. package/tests/e2e/run_tests_in_docker.sh +115 -0
  98. package/tests/main_test.cpp +16 -0
  99. package/tests/mocks/mock_ollama.py +98 -0
  100. package/tests/mocks/start_nginx.sh +64 -0
@@ -0,0 +1,366 @@
1
+ #include "services/ai_service.h"
2
+ #include "agent_mode.h"
3
+ #include "services/web_service.h"
4
+ #include "utils/config.h"
5
+ #include <curl/curl.h>
6
+ #include <nlohmann/json.hpp>
7
+ #include <sstream>
8
+
9
+ // Use the HeaderMap from web_service.h
10
+
11
+ // Reuse the CaseInsensitiveCompare and HeaderMap from web_service.h
12
+
13
+ namespace Services {
14
+
15
+ AIService::AIService(Core::AgentMode mode, const std::string &api_key)
16
+ : mode_(mode), api_key_(api_key) {}
17
+
18
+ bool AIService::is_online_mode() const {
19
+ return mode_ == Core::AgentMode::MODE_TOGETHER ||
20
+ mode_ == Core::AgentMode::MODE_CEREBRAS ||
21
+ mode_ == Core::AgentMode::MODE_FIREWORKS ||
22
+ mode_ == Core::AgentMode::MODE_GROQ ||
23
+ mode_ == Core::AgentMode::MODE_DEEPSEEK ||
24
+ mode_ == Core::AgentMode::MODE_OPENAI;
25
+ }
26
+
27
+ bool AIService::is_available() {
28
+ // For online providers API key is required.
29
+ if (is_online_mode()) {
30
+ return !api_key_.empty();
31
+ }
32
+ // Offline modes don't need an API key (they talk to local server)
33
+ return true;
34
+ }
35
+
36
+ std::string AIService::get_api_url() {
37
+ if (std::getenv("TEST_MODE")) {
38
+ // Use mock URLs for testing
39
+ switch (mode_) {
40
+ case Core::AgentMode::MODE_TOGETHER:
41
+ return "http://mock-together/v1/chat/completions";
42
+ case Core::AgentMode::MODE_CEREBRAS:
43
+ return "http://mock-cerebras/v1/chat/completions";
44
+ case Core::AgentMode::MODE_FIREWORKS:
45
+ return "http://mock-fireworks/inference/v1/chat/completions";
46
+ case Core::AgentMode::MODE_GROQ:
47
+ return "http://mock-groq/openai/v1/chat/completions";
48
+ case Core::AgentMode::MODE_DEEPSEEK:
49
+ return "http://mock-deepseek/v1/chat/completions";
50
+ case Core::AgentMode::MODE_OPENAI:
51
+ return "http://mock-openai/v1/chat/completions";
52
+ case Core::AgentMode::MODE_LLAMA_3B:
53
+ case Core::AgentMode::MODE_LLAMA_LATEST:
54
+ case Core::AgentMode::MODE_LLAMA_31:
55
+ default:
56
+ return "http://mock-ollama:11434/api/chat";
57
+ }
58
+ } else {
59
+ switch (mode_) {
60
+ case Core::AgentMode::MODE_TOGETHER:
61
+ return "https://api.together.xyz/v1/chat/completions";
62
+ case Core::AgentMode::MODE_CEREBRAS:
63
+ return "https://api.cerebras.ai/v1/chat/completions";
64
+ case Core::AgentMode::MODE_FIREWORKS:
65
+ return "https://api.fireworks.ai/inference/v1/chat/completions";
66
+ case Core::AgentMode::MODE_GROQ:
67
+ return "https://api.groq.com/openai/v1/chat/completions";
68
+ case Core::AgentMode::MODE_DEEPSEEK:
69
+ return "https://api.deepseek.com/v1/chat/completions";
70
+ case Core::AgentMode::MODE_OPENAI:
71
+ return "https://api.openai.com/v1/chat/completions";
72
+ case Core::AgentMode::MODE_LLAMA_3B:
73
+ case Core::AgentMode::MODE_LLAMA_LATEST:
74
+ case Core::AgentMode::MODE_LLAMA_31:
75
+ default:
76
+ return "http://localhost:11434/api/chat";
77
+ }
78
+ }
79
+ }
80
+
81
+ nlohmann::json AIService::create_standard_payload(const std::string &model,
82
+ const std::string &user_input,
83
+ const std::string &context) {
84
+ std::string system_prompt = "You are a helpful AI assistant. " + context;
85
+ return {{"model", model},
86
+ {"messages",
87
+ {{{"role", "system"}, {"content", system_prompt}},
88
+ {{"role", "user"}, {"content", user_input}}}},
89
+ {"max_tokens", 1000},
90
+ {"temperature", 0.7}};
91
+ }
92
+
93
+ nlohmann::json AIService::create_payload(const std::string &user_input,
94
+ const std::string &context) {
95
+ std::string system_prompt =
96
+ "You are an advanced AI agent with comprehensive codebase analysis and "
97
+ "development capabilities.\n\n"
98
+ "BASIC COMMANDS:\n"
99
+ "• search:query - Search the web for information\n"
100
+ "• cmd:command - Execute shell commands safely\n"
101
+ "• read:filename - Read file contents\n"
102
+ "• read:filename:start:count - Read specific line ranges from files\n"
103
+ "• write:filename content - Write content to files\n\n"
104
+ "ADVANCED FILE OPERATIONS:\n"
105
+ "• replace:filename:old_text:new_text[:expected_count] - Replace text in "
106
+ "files with precision\n"
107
+ "• grep:pattern[:directory[:file_filter]] - Search for patterns in files "
108
+ "and directories\n\n"
109
+ "CODEBASE ANALYSIS:\n"
110
+ "• analyze:path - Analyze codebase structure, file types, and project "
111
+ "configuration\n"
112
+ "• components:path - Find main components and their relationships\n"
113
+ "• todos:path - Find all task comments in codebase\n"
114
+ "• tree:path - Display directory tree structure\n\n"
115
+ "GIT INTEGRATION:\n"
116
+ "• git:log - Show recent git commit history\n"
117
+ "• git:status - Show git working directory status\n"
118
+ "• git:analyze - Comprehensive git repository analysis\n\n"
119
+ "MEMORY MANAGEMENT:\n"
120
+ "• remember:fact - Save important facts to persistent global memory\n"
121
+ "• memory - View stored global memories\n"
122
+ "• clear - Clear current session memory\n"
123
+ "• forget - Clear all global memories\n\n"
124
+ "CAPABILITIES:\n"
125
+ "- Understand codebase structure and relationships\n"
126
+ "- Analyze git history and track changes\n"
127
+ "- Find and prioritize task comments\n"
128
+ "- Advanced text search and replacement with context validation\n"
129
+ "- Structured memory system for facts and preferences\n"
130
+ "- File operations with safety checks and path validation\n"
131
+ "- Enhanced error handling and user feedback\n\n"
132
+ "When users ask about codebase analysis, use analyze: or components: "
133
+ "commands.\n"
134
+ "For git-related questions, use git: commands.\n"
135
+ "For finding tasks or technical debt, use todos: command.\n"
136
+ "For complex file editing, use replace: instead of write: when modifying "
137
+ "existing content.\n"
138
+ "Use grep: to search for code patterns or text across multiple files.\n"
139
+ "Remember important user preferences and facts using remember:.\n"
140
+ "Be helpful, precise, and professional.\n\n"
141
+ "Conversation history:\n" +
142
+ context;
143
+
144
+ switch (mode_) {
145
+ case Core::AgentMode::MODE_TOGETHER: // Together AI
146
+ return create_standard_payload(
147
+ "meta-llama/Llama-3.3-70B-Instruct-Turbo-Free", user_input,
148
+ system_prompt);
149
+ case Core::AgentMode::MODE_CEREBRAS: // Cerebras
150
+ return {{"model", "llama-4-maverick-17b-128e-instruct"},
151
+ {"messages",
152
+ {{{"role", "system"}, {"content", system_prompt}},
153
+ {{"role", "user"}, {"content", user_input}}}},
154
+ {"stream", true},
155
+ {"max_completion_tokens", 4096},
156
+ {"temperature", 0.7},
157
+ {"top_p", 0.9}};
158
+ case Core::AgentMode::MODE_FIREWORKS: // Fireworks
159
+ return create_standard_payload(
160
+ "accounts/fireworks/models/llama-v3-70b-instruct", user_input,
161
+ system_prompt);
162
+ case Core::AgentMode::MODE_GROQ: // Groq
163
+ return create_standard_payload("llama-3.1-70b-versatile", user_input,
164
+ system_prompt);
165
+ case Core::AgentMode::MODE_DEEPSEEK: // DeepSeek
166
+ return create_standard_payload("deepseek-chat", user_input, system_prompt);
167
+ case Core::AgentMode::MODE_OPENAI: // OpenAI
168
+ return create_standard_payload("gpt-4", user_input, system_prompt);
169
+ case Core::AgentMode::MODE_LLAMA_3B: // Llama 3B (local)
170
+ return {{"model", "llama3.2:3b"},
171
+ {"stream", false},
172
+ {"messages",
173
+ {{{"role", "system"}, {"content", system_prompt}},
174
+ {{"role", "user"}, {"content", user_input}}}}};
175
+
176
+ case Core::AgentMode::MODE_LLAMA_LATEST: // Llama latest (local)
177
+ return {{"model", "llama3.2:latest"},
178
+ {"stream", false},
179
+ {"messages",
180
+ {{{"role", "system"}, {"content", system_prompt}},
181
+ {{"role", "user"}, {"content", user_input}}}}};
182
+
183
+ case Core::AgentMode::MODE_LLAMA_31: // Llama 3.1 (local)
184
+ return {{"model", "llama3.1:latest"},
185
+ {"stream", false},
186
+ {"messages",
187
+ {{{"role", "system"}, {"content", system_prompt}},
188
+ {{"role", "user"}, {"content", user_input}}}}};
189
+
190
+ default: // Fallback to Llama 3B
191
+ return {{"model", "llama3.2:3b"},
192
+ {"stream", false},
193
+ {"messages",
194
+ {{{"role", "system"}, {"content", system_prompt}},
195
+ {{"role", "user"}, {"content", user_input}}}}};
196
+ }
197
+ }
198
+
199
+ std::string AIService::parse_cerebras_stream(const std::string &response) {
200
+ // Response is server-sent events style; accumulate content deltas.
201
+ std::string result;
202
+ std::istringstream stream(response);
203
+ std::string line;
204
+
205
+ while (std::getline(stream, line)) {
206
+ // trim leading spaces
207
+ if (line.starts_with("data: ")) {
208
+ std::string json_str = line.substr(6);
209
+ if (json_str == "[DONE]")
210
+ break;
211
+
212
+ try {
213
+ auto json = nlohmann::json::parse(json_str);
214
+ if (json.contains("choices") && !json["choices"].empty()) {
215
+ auto &choice = json["choices"][0];
216
+ if (choice.contains("delta") && choice["delta"].contains("content")) {
217
+ // content might be string
218
+ result += choice["delta"]["content"].get<std::string>();
219
+ } else if (choice.contains("text")) {
220
+ result += choice["text"].get<std::string>();
221
+ }
222
+ }
223
+ } catch (const std::exception &) {
224
+ // ignore malformed chunk and continue
225
+ continue;
226
+ }
227
+ }
228
+ }
229
+ return result;
230
+ }
231
+
232
+ std::string safe_get_string(const nlohmann::json &j,
233
+ const std::initializer_list<std::string> &path,
234
+ const std::string &fallback = "") {
235
+ const nlohmann::json *cur = &j;
236
+ for (const auto &p : path) {
237
+ if (!cur->is_object() || !cur->contains(p))
238
+ return fallback;
239
+ cur = &((*cur)[p]);
240
+ }
241
+ if (cur->is_string())
242
+ return cur->get<std::string>();
243
+ return fallback;
244
+ }
245
+
246
+ std::string AIService::chat(const std::string &user_input,
247
+ const std::string &context) {
248
+ if (!is_available()) {
249
+ return "Error: AI service is not available. Please check your API key and "
250
+ "internet connection.";
251
+ }
252
+
253
+ auto payload = create_payload(user_input, context);
254
+ auto url = get_api_url();
255
+
256
+ try {
257
+ // Set up headers
258
+ HeaderMap headers = {{"Content-Type", "application/json"},
259
+ {"Accept", "text/event-stream"}};
260
+
261
+ // Set API key in appropriate header based on service
262
+ switch (mode_) {
263
+ case Core::AgentMode::MODE_TOGETHER: // Together AI
264
+ case Core::AgentMode::MODE_FIREWORKS: // Fireworks
265
+ case Core::AgentMode::MODE_GROQ: // Groq
266
+ case Core::AgentMode::MODE_DEEPSEEK: // DeepSeek
267
+ case Core::AgentMode::MODE_OPENAI: // OpenAI
268
+ headers["Authorization"] = "Bearer " + api_key_;
269
+ break;
270
+ case Core::AgentMode::MODE_CEREBRAS: // Cerebras
271
+ headers["X-API-Key"] = api_key_;
272
+ break;
273
+ case Core::AgentMode::MODE_LLAMA_3B: // Local Ollama
274
+ case Core::AgentMode::MODE_LLAMA_LATEST:
275
+ case Core::AgentMode::MODE_LLAMA_31:
276
+ // No API key needed for local
277
+ break;
278
+ case Core::AgentMode::MODE_UNSET:
279
+ // No action
280
+ break;
281
+ }
282
+
283
+ // Use WebService to make the HTTP request
284
+ WebService web_service;
285
+ std::string json_body = payload.dump();
286
+
287
+ WebResponse response;
288
+ if (mode_ == Core::AgentMode::MODE_TOGETHER ||
289
+ mode_ == Core::AgentMode::MODE_CEREBRAS ||
290
+ mode_ == Core::AgentMode::MODE_FIREWORKS ||
291
+ mode_ == Core::AgentMode::MODE_GROQ ||
292
+ mode_ == Core::AgentMode::MODE_DEEPSEEK ||
293
+ mode_ == Core::AgentMode::MODE_OPENAI ||
294
+ mode_ == Core::AgentMode::MODE_LLAMA_3B ||
295
+ mode_ == Core::AgentMode::MODE_LLAMA_LATEST ||
296
+ mode_ == Core::AgentMode::MODE_LLAMA_31) {
297
+ // All providers use POST
298
+ response = web_service.post_json(url, json_body, headers);
299
+ } else {
300
+ // Fallback (should not happen)
301
+ response = web_service.post_json(url, json_body, headers);
302
+ }
303
+
304
+ if (response.status_code != 200) {
305
+ std::string error_content = response.content;
306
+ if (error_content.length() > 500) {
307
+ error_content = error_content.substr(0, 500) + "...[truncated]";
308
+ }
309
+ return "Error: AI service returned status code " +
310
+ std::to_string(response.status_code) + " - " + error_content +
311
+ " | Error: " + response.error_message;
312
+ }
313
+
314
+ // Handle streaming response for Cerebras
315
+ if (mode_ == Core::AgentMode::MODE_CEREBRAS) {
316
+ return parse_cerebras_stream(response.content);
317
+ }
318
+
319
+ // Parse the response based on the service
320
+ auto json_response = nlohmann::json::parse(response.content);
321
+
322
+ // Handle different response formats
323
+ switch (mode_) {
324
+ case Core::AgentMode::MODE_TOGETHER: // Together AI
325
+ case Core::AgentMode::MODE_FIREWORKS: // Fireworks
326
+ case Core::AgentMode::MODE_GROQ: // Groq
327
+ case Core::AgentMode::MODE_DEEPSEEK: // DeepSeek
328
+ case Core::AgentMode::MODE_OPENAI: // OpenAI
329
+ case Core::AgentMode::MODE_CEREBRAS: // Cerebras
330
+ if (json_response.contains("choices") &&
331
+ !json_response["choices"].empty()) {
332
+ auto &choice = json_response["choices"][0];
333
+ if (choice.contains("message") &&
334
+ choice["message"].contains("content")) {
335
+ return choice["message"]["content"].get<std::string>();
336
+ } else if (choice.contains("text")) {
337
+ return choice["text"].get<std::string>();
338
+ }
339
+ }
340
+ break;
341
+ case Core::AgentMode::MODE_LLAMA_3B: // Local Ollama
342
+ case Core::AgentMode::MODE_LLAMA_LATEST:
343
+ case Core::AgentMode::MODE_LLAMA_31:
344
+ if (json_response.contains("message") &&
345
+ json_response["message"].contains("content")) {
346
+ return json_response["message"]["content"].get<std::string>();
347
+ } else if (json_response.contains("response")) {
348
+ return json_response["response"].get<std::string>();
349
+ }
350
+ break;
351
+ case Core::AgentMode::MODE_UNSET:
352
+ // No action
353
+ break;
354
+ }
355
+
356
+ // If we get here, the response format wasn't as expected
357
+ return "Error: Unexpected response format from AI service: " +
358
+ response.content;
359
+
360
+ } catch (const std::exception &e) {
361
+ return "Error: " + std::string(e.what());
362
+ }
363
+ return "Error: Unknown error occurred in AI service";
364
+ }
365
+
366
+ } // namespace Services