codebuff 1.0.99

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 (153) hide show
  1. package/README.md +70 -0
  2. package/dist/chat-storage.d.ts +29 -0
  3. package/dist/chat-storage.js +125 -0
  4. package/dist/chat-storage.js.map +1 -0
  5. package/dist/cli.d.ts +37 -0
  6. package/dist/cli.js +416 -0
  7. package/dist/cli.js.map +1 -0
  8. package/dist/client.d.ts +41 -0
  9. package/dist/client.js +443 -0
  10. package/dist/client.js.map +1 -0
  11. package/dist/code-map/languages.d.ts +12 -0
  12. package/dist/code-map/languages.js +129 -0
  13. package/dist/code-map/languages.js.map +1 -0
  14. package/dist/code-map/parse.d.ts +11 -0
  15. package/dist/code-map/parse.js +127 -0
  16. package/dist/code-map/parse.js.map +1 -0
  17. package/dist/code-map/test-langs/test.d.ts +11 -0
  18. package/dist/code-map/test-langs/test.js +23 -0
  19. package/dist/code-map/test-langs/test.js.map +1 -0
  20. package/dist/code-map/tree-sitter-queries/readme.md +23 -0
  21. package/dist/code-map/tree-sitter-queries/tree-sitter-c-tags.scm +11 -0
  22. package/dist/code-map/tree-sitter-queries/tree-sitter-c_sharp-tags.scm +13 -0
  23. package/dist/code-map/tree-sitter-queries/tree-sitter-cpp-tags.scm +17 -0
  24. package/dist/code-map/tree-sitter-queries/tree-sitter-go-tags.scm +26 -0
  25. package/dist/code-map/tree-sitter-queries/tree-sitter-java-tags.scm +19 -0
  26. package/dist/code-map/tree-sitter-queries/tree-sitter-javascript-tags.scm +15 -0
  27. package/dist/code-map/tree-sitter-queries/tree-sitter-php-tags.scm +26 -0
  28. package/dist/code-map/tree-sitter-queries/tree-sitter-python-tags.scm +9 -0
  29. package/dist/code-map/tree-sitter-queries/tree-sitter-ruby-tags.scm +58 -0
  30. package/dist/code-map/tree-sitter-queries/tree-sitter-rust-tags.scm +26 -0
  31. package/dist/code-map/tree-sitter-queries/tree-sitter-typescript-tags.scm +15 -0
  32. package/dist/code-map/tsconfig.tsbuildinfo +1 -0
  33. package/dist/common/actions.d.ts +1062 -0
  34. package/dist/common/actions.js +180 -0
  35. package/dist/common/actions.js.map +1 -0
  36. package/dist/common/billing/quota-manager.d.ts +59 -0
  37. package/dist/common/billing/quota-manager.js +200 -0
  38. package/dist/common/billing/quota-manager.js.map +1 -0
  39. package/dist/common/constants.d.ts +24 -0
  40. package/dist/common/constants.js +73 -0
  41. package/dist/common/constants.js.map +1 -0
  42. package/dist/common/db/drizzle.config.d.ts +2 -0
  43. package/dist/common/db/drizzle.config.js +17 -0
  44. package/dist/common/db/drizzle.config.js.map +1 -0
  45. package/dist/common/db/env.d.mts +1 -0
  46. package/dist/common/db/env.mjs +26 -0
  47. package/dist/common/db/env.mjs.map +1 -0
  48. package/dist/common/db/index.d.ts +6 -0
  49. package/dist/common/db/index.js +35 -0
  50. package/dist/common/db/index.js.map +1 -0
  51. package/dist/common/db/schema.d.ts +994 -0
  52. package/dist/common/db/schema.js +113 -0
  53. package/dist/common/db/schema.js.map +1 -0
  54. package/dist/common/env.d.mts +1 -0
  55. package/dist/common/env.mjs +34 -0
  56. package/dist/common/env.mjs.map +1 -0
  57. package/dist/common/project-file-tree.d.ts +9 -0
  58. package/dist/common/project-file-tree.js +157 -0
  59. package/dist/common/project-file-tree.js.map +1 -0
  60. package/dist/common/types/referral.d.ts +2 -0
  61. package/dist/common/types/referral.js +5 -0
  62. package/dist/common/types/referral.js.map +1 -0
  63. package/dist/common/types/usage.d.ts +21 -0
  64. package/dist/common/types/usage.js +12 -0
  65. package/dist/common/types/usage.js.map +1 -0
  66. package/dist/common/util/__tests__/string.test.d.ts +1 -0
  67. package/dist/common/util/__tests__/string.test.js +83 -0
  68. package/dist/common/util/__tests__/string.test.js.map +1 -0
  69. package/dist/common/util/array.d.ts +6 -0
  70. package/dist/common/util/array.js +32 -0
  71. package/dist/common/util/array.js.map +1 -0
  72. package/dist/common/util/changes.d.ts +6 -0
  73. package/dist/common/util/changes.js +72 -0
  74. package/dist/common/util/changes.js.map +1 -0
  75. package/dist/common/util/credentials.d.ts +25 -0
  76. package/dist/common/util/credentials.js +24 -0
  77. package/dist/common/util/credentials.js.map +1 -0
  78. package/dist/common/util/dates.d.ts +1 -0
  79. package/dist/common/util/dates.js +13 -0
  80. package/dist/common/util/dates.js.map +1 -0
  81. package/dist/common/util/file.d.ts +106 -0
  82. package/dist/common/util/file.js +138 -0
  83. package/dist/common/util/file.js.map +1 -0
  84. package/dist/common/util/git.d.ts +4 -0
  85. package/dist/common/util/git.js +40 -0
  86. package/dist/common/util/git.js.map +1 -0
  87. package/dist/common/util/helpers.d.ts +1 -0
  88. package/dist/common/util/helpers.js +6 -0
  89. package/dist/common/util/helpers.js.map +1 -0
  90. package/dist/common/util/object.d.ts +18 -0
  91. package/dist/common/util/object.js +91 -0
  92. package/dist/common/util/object.js.map +1 -0
  93. package/dist/common/util/patch.d.ts +1 -0
  94. package/dist/common/util/patch.js +215 -0
  95. package/dist/common/util/patch.js.map +1 -0
  96. package/dist/common/util/promise.d.ts +1 -0
  97. package/dist/common/util/promise.js +33 -0
  98. package/dist/common/util/promise.js.map +1 -0
  99. package/dist/common/util/referral.d.ts +1 -0
  100. package/dist/common/util/referral.js +6 -0
  101. package/dist/common/util/referral.js.map +1 -0
  102. package/dist/common/util/server/referral.d.ts +14 -0
  103. package/dist/common/util/server/referral.js +85 -0
  104. package/dist/common/util/server/referral.js.map +1 -0
  105. package/dist/common/util/string.d.ts +3 -0
  106. package/dist/common/util/string.js +60 -0
  107. package/dist/common/util/string.js.map +1 -0
  108. package/dist/common/util/stripe.d.ts +2 -0
  109. package/dist/common/util/stripe.js +19 -0
  110. package/dist/common/util/stripe.js.map +1 -0
  111. package/dist/common/util/tools.d.ts +2 -0
  112. package/dist/common/util/tools.js +13 -0
  113. package/dist/common/util/tools.js.map +1 -0
  114. package/dist/common/websockets/websocket-client.d.ts +40 -0
  115. package/dist/common/websockets/websocket-client.js +187 -0
  116. package/dist/common/websockets/websocket-client.js.map +1 -0
  117. package/dist/common/websockets/websocket-schema.d.ts +2530 -0
  118. package/dist/common/websockets/websocket-schema.js +55 -0
  119. package/dist/common/websockets/websocket-schema.js.map +1 -0
  120. package/dist/config.d.ts +2 -0
  121. package/dist/config.js +8 -0
  122. package/dist/config.js.map +1 -0
  123. package/dist/credentials.d.ts +3 -0
  124. package/dist/credentials.js +33 -0
  125. package/dist/credentials.js.map +1 -0
  126. package/dist/fingerprint.d.ts +1 -0
  127. package/dist/fingerprint.js +43 -0
  128. package/dist/fingerprint.js.map +1 -0
  129. package/dist/index.d.ts +2 -0
  130. package/dist/index.js +50 -0
  131. package/dist/index.js.map +1 -0
  132. package/dist/manifold-api.d.ts +8 -0
  133. package/dist/manifold-api.js +32 -0
  134. package/dist/manifold-api.js.map +1 -0
  135. package/dist/menu.d.ts +1 -0
  136. package/dist/menu.js +92 -0
  137. package/dist/menu.js.map +1 -0
  138. package/dist/project-files.d.ts +48 -0
  139. package/dist/project-files.js +324 -0
  140. package/dist/project-files.js.map +1 -0
  141. package/dist/tool-handlers.d.ts +11 -0
  142. package/dist/tool-handlers.js +131 -0
  143. package/dist/tool-handlers.js.map +1 -0
  144. package/dist/update-manicode.d.ts +1 -0
  145. package/dist/update-manicode.js +151 -0
  146. package/dist/update-manicode.js.map +1 -0
  147. package/dist/web-scraper.d.ts +3 -0
  148. package/dist/web-scraper.js +79 -0
  149. package/dist/web-scraper.js.map +1 -0
  150. package/dist/worker-script-project-context.d.ts +1 -0
  151. package/dist/worker-script-project-context.js +13 -0
  152. package/dist/worker-script-project-context.js.map +1 -0
  153. package/package.json +62 -0
package/README.md ADDED
@@ -0,0 +1,70 @@
1
+ # The AI coder for serious engineers
2
+
3
+ Manicode helps you generate better code from your terminal.
4
+
5
+ 1. Run `manicode` from your project directory
6
+ 2. Tell it what to do
7
+ 3. It will read and write to files to produce the code you want
8
+
9
+ ## Installation
10
+
11
+ To install Manicode, run:
12
+
13
+ ```bash
14
+ npm install -g manicode
15
+ ```
16
+
17
+ ## Usage
18
+
19
+ After installation, you can start Manicode by running:
20
+
21
+ ```bash
22
+ manicode [project-directory]
23
+ ```
24
+
25
+ If no project directory is specified, Manicode will use the current directory.
26
+
27
+ After running `manicode`, simply chat with it to say what coding task you want done.
28
+
29
+ ## Features
30
+
31
+ - Interacts with your codebase using natural language
32
+ - Reads and writes files within your project directory
33
+ - Runs commands in your terminal
34
+ - Scrapes the web to gather information for tasks
35
+
36
+ Ask Manicode to implement small features, write unit tests, write scripts, or give advice.
37
+
38
+ ## Knowledge Files
39
+
40
+ To unlock the full benefits of modern LLMs, we recommend storing knowledge alongside your code. Add a `knowledge.md` file anywhere in your project to provide helpful context, guidance, and tips for the LLM as it performs tasks for you.
41
+
42
+ Manicode can fluently read and write files, so it will add knowledge as it goes. You don't need to write knowledge manually!
43
+
44
+ Some have said every change should be paired with a unit test. In 2024, every change should come with a knowledge update!
45
+
46
+ ## Tips
47
+
48
+ 1. Create a `knowledge.md` file and collect specific points of advice. The assistant will use this knowledge to improve its responses.
49
+ 2. Type `undo` or `redo` to revert or reapply file changes from the conversation.
50
+ 3. Press `Esc` or `Ctrl+C` while Manicode is generating a response to stop it.
51
+
52
+ ## Troubleshooting
53
+
54
+ If you are getting permission errors when installing globally with '-g', or when running `manicode`, try [installing node with a version manager](https://docs.npmjs.com/downloading-and-installing-node-js-and-npm).
55
+
56
+ #### For OSX or Unix, use [nvm](https://docs.npmjs.com/downloading-and-installing-node-js-and-npm). Run:
57
+
58
+ ```bash
59
+ curl -o- https://raw.githubusercontent.com/nvm-sh/nvm/v0.40.1/install.sh | bash
60
+ ```
61
+
62
+ #### For Windows, use [nvm-windows](https://github.com/coreybutler/nvm-windows):
63
+
64
+ Make sure to uninstall your existing node program. Then get this executable:
65
+
66
+ [Download the release .exe](https://github.com/coreybutler/nvm-windows/releases)
67
+
68
+ ## Feedback
69
+
70
+ We value your input! Please email your feedback to `james@manicode.ai`. Thank you for using Manicode!
@@ -0,0 +1,29 @@
1
+ import { Message } from './common/actions';
2
+ interface Chat {
3
+ id: string;
4
+ messages: Message[];
5
+ fileVersions: FileVersion[];
6
+ createdAt: string;
7
+ updatedAt: string;
8
+ }
9
+ interface FileVersion {
10
+ files: Record<string, string>;
11
+ }
12
+ export declare class ChatStorage {
13
+ private baseDir;
14
+ private currentChat;
15
+ private currentVersionIndex;
16
+ constructor();
17
+ getCurrentChat(): Chat;
18
+ addMessage(chat: Chat, message: Message): void;
19
+ getCurrentVersion(): FileVersion | null;
20
+ navigateVersion(direction: 'undo' | 'redo'): boolean;
21
+ saveFilesChanged(filesChanged: string[]): string[];
22
+ saveCurrentFileState(files: Record<string, string>): void;
23
+ addNewFileState(files: Record<string, string>): void;
24
+ private createChat;
25
+ private saveChat;
26
+ private generateChatId;
27
+ private getFilePath;
28
+ }
29
+ export {};
@@ -0,0 +1,125 @@
1
+ "use strict";
2
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
+ if (k2 === undefined) k2 = k;
4
+ var desc = Object.getOwnPropertyDescriptor(m, k);
5
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
+ desc = { enumerable: true, get: function() { return m[k]; } };
7
+ }
8
+ Object.defineProperty(o, k2, desc);
9
+ }) : (function(o, m, k, k2) {
10
+ if (k2 === undefined) k2 = k;
11
+ o[k2] = m[k];
12
+ }));
13
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
14
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
15
+ }) : function(o, v) {
16
+ o["default"] = v;
17
+ });
18
+ var __importStar = (this && this.__importStar) || function (mod) {
19
+ if (mod && mod.__esModule) return mod;
20
+ var result = {};
21
+ if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
22
+ __setModuleDefault(result, mod);
23
+ return result;
24
+ };
25
+ Object.defineProperty(exports, "__esModule", { value: true });
26
+ exports.ChatStorage = void 0;
27
+ const path = __importStar(require("path"));
28
+ const project_files_1 = require("./project-files");
29
+ const MANICODE_DIR = '.manicode';
30
+ const CHATS_DIR = 'chats';
31
+ class ChatStorage {
32
+ baseDir;
33
+ currentChat;
34
+ currentVersionIndex;
35
+ constructor() {
36
+ this.baseDir = path.join((0, project_files_1.getProjectRoot)(), MANICODE_DIR, CHATS_DIR);
37
+ this.currentChat = this.createChat();
38
+ this.currentVersionIndex = -1;
39
+ }
40
+ getCurrentChat() {
41
+ return this.currentChat;
42
+ }
43
+ addMessage(chat, message) {
44
+ chat.messages.push(message);
45
+ chat.updatedAt = new Date().toISOString();
46
+ this.saveChat(chat);
47
+ }
48
+ getCurrentVersion() {
49
+ if (this.currentVersionIndex >= 0 &&
50
+ this.currentVersionIndex < this.currentChat.fileVersions.length) {
51
+ return this.currentChat.fileVersions[this.currentVersionIndex];
52
+ }
53
+ return null;
54
+ }
55
+ navigateVersion(direction) {
56
+ if (direction === 'undo' && this.currentVersionIndex >= 0) {
57
+ this.currentVersionIndex--;
58
+ return true;
59
+ }
60
+ else if (direction === 'redo' &&
61
+ this.currentVersionIndex < this.currentChat.fileVersions.length - 1) {
62
+ this.currentVersionIndex++;
63
+ return true;
64
+ }
65
+ return false;
66
+ }
67
+ saveFilesChanged(filesChanged) {
68
+ let currentVersion = this.getCurrentVersion();
69
+ if (!currentVersion) {
70
+ this.addNewFileState({});
71
+ currentVersion = this.getCurrentVersion();
72
+ }
73
+ const newFilesChanged = filesChanged.filter((f) => !currentVersion.files[f]);
74
+ const updatedFiles = (0, project_files_1.getExistingFiles)(newFilesChanged);
75
+ currentVersion.files = { ...currentVersion.files, ...updatedFiles };
76
+ return Object.keys(currentVersion.files);
77
+ }
78
+ saveCurrentFileState(files) {
79
+ const currentVersion = this.getCurrentVersion();
80
+ if (currentVersion) {
81
+ currentVersion.files = files;
82
+ }
83
+ else {
84
+ this.addNewFileState(files);
85
+ }
86
+ }
87
+ addNewFileState(files) {
88
+ const newVersion = {
89
+ files,
90
+ };
91
+ this.currentChat.fileVersions.push(newVersion);
92
+ this.currentVersionIndex = this.currentChat.fileVersions.length - 1;
93
+ }
94
+ createChat(messages = []) {
95
+ const chat = {
96
+ id: this.generateChatId(),
97
+ messages,
98
+ fileVersions: [],
99
+ createdAt: new Date().toISOString(),
100
+ updatedAt: new Date().toISOString(),
101
+ };
102
+ this.saveChat(chat);
103
+ return chat;
104
+ }
105
+ saveChat(chat) {
106
+ const filePath = this.getFilePath(chat.id);
107
+ // fs.writeFileSync(filePath, JSON.stringify(chat, null, 2))
108
+ }
109
+ generateChatId() {
110
+ const now = new Date();
111
+ const datePart = now.toISOString().split('T')[0]; // YYYY-MM-DD
112
+ const timePart = now
113
+ .toISOString()
114
+ .split('T')[1]
115
+ .replace(/:/g, '-')
116
+ .split('.')[0]; // HH-MM-SS
117
+ const randomPart = Math.random().toString(36).substr(2, 5);
118
+ return `${datePart}_${timePart}_${randomPart}`;
119
+ }
120
+ getFilePath(chatId) {
121
+ return path.join(this.baseDir, `${chatId}.json`);
122
+ }
123
+ }
124
+ exports.ChatStorage = ChatStorage;
125
+ //# sourceMappingURL=chat-storage.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"chat-storage.js","sourceRoot":"","sources":["../src/chat-storage.ts"],"names":[],"mappings":"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"}
package/dist/cli.d.ts ADDED
@@ -0,0 +1,37 @@
1
+ import { ProjectFileContext } from './common/util/file';
2
+ export declare class CLI {
3
+ private client;
4
+ private chatStorage;
5
+ private readyPromise;
6
+ private autoGit;
7
+ private rl;
8
+ private isReceivingResponse;
9
+ private stopResponse;
10
+ private loadingInterval;
11
+ private lastChanges;
12
+ private lastInputTime;
13
+ private consecutiveFastInputs;
14
+ private pastedContent;
15
+ private isPasting;
16
+ constructor(readyPromise: Promise<[void, ProjectFileContext]>, { autoGit }: {
17
+ autoGit: boolean;
18
+ });
19
+ private onWebSocketError;
20
+ private detectPasting;
21
+ private handleInput;
22
+ private setPrompt;
23
+ printInitialPrompt(initialInput?: string): void;
24
+ private handleUndo;
25
+ private handleRedo;
26
+ private navigateFileVersion;
27
+ private handleStopResponse;
28
+ private handleExit;
29
+ private handleEscKey;
30
+ private applyAndDisplayCurrentFileVersion;
31
+ private startLoadingAnimation;
32
+ private stopLoadingAnimation;
33
+ private autoCommitChanges;
34
+ private handleDiff;
35
+ private handleUserInput;
36
+ private sendUserInputAndAwaitResponse;
37
+ }
package/dist/cli.js ADDED
@@ -0,0 +1,416 @@
1
+ "use strict";
2
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
+ if (k2 === undefined) k2 = k;
4
+ var desc = Object.getOwnPropertyDescriptor(m, k);
5
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
+ desc = { enumerable: true, get: function() { return m[k]; } };
7
+ }
8
+ Object.defineProperty(o, k2, desc);
9
+ }) : (function(o, m, k, k2) {
10
+ if (k2 === undefined) k2 = k;
11
+ o[k2] = m[k];
12
+ }));
13
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
14
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
15
+ }) : function(o, v) {
16
+ o["default"] = v;
17
+ });
18
+ var __importStar = (this && this.__importStar) || function (mod) {
19
+ if (mod && mod.__esModule) return mod;
20
+ var result = {};
21
+ if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
22
+ __setModuleDefault(result, mod);
23
+ return result;
24
+ };
25
+ Object.defineProperty(exports, "__esModule", { value: true });
26
+ exports.CLI = void 0;
27
+ const lodash_1 = require("lodash");
28
+ const changes_1 = require("./common/util/changes");
29
+ const readline = __importStar(require("readline"));
30
+ const picocolors_1 = require("picocolors");
31
+ const path_1 = require("path");
32
+ const config_1 = require("./config");
33
+ const chat_storage_1 = require("./chat-storage");
34
+ const client_1 = require("./client");
35
+ const menu_1 = require("./menu");
36
+ const project_files_1 = require("./project-files");
37
+ const tool_handlers_1 = require("./tool-handlers");
38
+ const constants_1 = require("./common/constants");
39
+ const file_1 = require("./common/util/file");
40
+ const web_scraper_1 = require("./web-scraper");
41
+ const git_1 = require("./common/util/git");
42
+ class CLI {
43
+ client;
44
+ chatStorage;
45
+ readyPromise;
46
+ autoGit;
47
+ rl;
48
+ isReceivingResponse = false;
49
+ stopResponse = null;
50
+ loadingInterval = null;
51
+ lastChanges = [];
52
+ lastInputTime = 0;
53
+ consecutiveFastInputs = 0;
54
+ pastedContent = '';
55
+ isPasting = false;
56
+ constructor(readyPromise, { autoGit }) {
57
+ this.autoGit = autoGit;
58
+ this.chatStorage = new chat_storage_1.ChatStorage();
59
+ this.rl = readline.createInterface({
60
+ input: process.stdin,
61
+ output: process.stdout,
62
+ historySize: 1000,
63
+ });
64
+ this.client = new client_1.Client(config_1.websocketUrl, this.chatStorage, this.onWebSocketError.bind(this), () => {
65
+ this.rl.prompt();
66
+ this.isReceivingResponse = false;
67
+ if (this.stopResponse) {
68
+ this.stopResponse();
69
+ }
70
+ this.stopLoadingAnimation();
71
+ });
72
+ this.readyPromise = Promise.all([
73
+ readyPromise.then((results) => {
74
+ const [_, fileContext] = results;
75
+ this.client.initFileVersions(fileContext);
76
+ return this.client.warmContextCache();
77
+ }),
78
+ this.client.connect(),
79
+ ]);
80
+ this.setPrompt();
81
+ this.rl.on('line', (line) => {
82
+ this.handleInput(line);
83
+ });
84
+ this.rl.on('SIGINT', () => {
85
+ if (this.isReceivingResponse) {
86
+ this.handleStopResponse();
87
+ }
88
+ else {
89
+ this.handleExit();
90
+ }
91
+ });
92
+ process.stdin.on('keypress', (_, key) => {
93
+ if (key.name === 'escape') {
94
+ this.handleEscKey();
95
+ }
96
+ this.detectPasting();
97
+ });
98
+ }
99
+ onWebSocketError() {
100
+ this.stopLoadingAnimation();
101
+ this.isReceivingResponse = false;
102
+ if (this.stopResponse) {
103
+ this.stopResponse();
104
+ this.stopResponse = null;
105
+ }
106
+ console.error((0, picocolors_1.yellow)('\nCould not connect. Retrying...'));
107
+ }
108
+ detectPasting() {
109
+ const currentTime = Date.now();
110
+ const timeDiff = currentTime - this.lastInputTime;
111
+ if (timeDiff < 10) {
112
+ this.consecutiveFastInputs++;
113
+ if (this.consecutiveFastInputs >= 2) {
114
+ this.isPasting = true;
115
+ }
116
+ }
117
+ else {
118
+ this.consecutiveFastInputs = 0;
119
+ if (this.isPasting) {
120
+ this.isPasting = false;
121
+ }
122
+ }
123
+ this.lastInputTime = currentTime;
124
+ }
125
+ handleInput(line) {
126
+ this.detectPasting();
127
+ if (this.isPasting) {
128
+ this.pastedContent += line + '\n';
129
+ }
130
+ else if (!this.isReceivingResponse) {
131
+ if (this.pastedContent) {
132
+ this.handleUserInput((this.pastedContent + line).trim());
133
+ this.pastedContent = '';
134
+ }
135
+ else {
136
+ this.handleUserInput(line.trim());
137
+ }
138
+ }
139
+ }
140
+ setPrompt() {
141
+ this.rl.setPrompt((0, picocolors_1.green)(`${(0, path_1.parse)((0, project_files_1.getProjectRoot)()).base} > `));
142
+ }
143
+ printInitialPrompt(initialInput) {
144
+ if (this.client.user) {
145
+ console.log(`\nWelcome back ${this.client.user.name}! What would you like to do?`);
146
+ }
147
+ else {
148
+ console.log(`What would you like to do?\n`);
149
+ }
150
+ this.rl.prompt();
151
+ if (initialInput) {
152
+ process.stdout.write(initialInput + '\n');
153
+ this.handleUserInput(initialInput);
154
+ }
155
+ }
156
+ handleUndo() {
157
+ this.navigateFileVersion('undo');
158
+ this.rl.prompt();
159
+ }
160
+ handleRedo() {
161
+ this.navigateFileVersion('redo');
162
+ this.rl.prompt();
163
+ }
164
+ navigateFileVersion(direction) {
165
+ const currentVersion = this.chatStorage.getCurrentVersion();
166
+ const filePaths = Object.keys(currentVersion ? currentVersion.files : {});
167
+ const currentFiles = (0, project_files_1.getExistingFiles)(filePaths);
168
+ this.chatStorage.saveCurrentFileState(currentFiles);
169
+ const navigated = this.chatStorage.navigateVersion(direction);
170
+ if (navigated) {
171
+ console.log(direction === 'undo'
172
+ ? (0, picocolors_1.green)('Undo last change')
173
+ : (0, picocolors_1.green)('Redo last change'));
174
+ const files = this.applyAndDisplayCurrentFileVersion();
175
+ console.log((0, picocolors_1.green)('Loaded files:'), (0, picocolors_1.green)(Object.keys(files).join(', ')));
176
+ }
177
+ else {
178
+ console.log((0, picocolors_1.green)(`No more ${direction === 'undo' ? 'undo' : 'redo'}s`));
179
+ }
180
+ }
181
+ handleStopResponse() {
182
+ console.log((0, picocolors_1.yellow)('\n[Response stopped by user]'));
183
+ this.isReceivingResponse = false;
184
+ if (this.stopResponse) {
185
+ this.stopResponse();
186
+ }
187
+ this.stopLoadingAnimation();
188
+ }
189
+ handleExit() {
190
+ console.log((0, picocolors_1.green)('\n\nExiting. Manicode out!'));
191
+ process.exit(0);
192
+ }
193
+ handleEscKey() {
194
+ if (this.isReceivingResponse) {
195
+ this.handleStopResponse();
196
+ }
197
+ }
198
+ applyAndDisplayCurrentFileVersion() {
199
+ const currentVersion = this.chatStorage.getCurrentVersion();
200
+ if (currentVersion) {
201
+ (0, project_files_1.setFiles)(currentVersion.files);
202
+ return currentVersion.files;
203
+ }
204
+ return {};
205
+ }
206
+ startLoadingAnimation() {
207
+ const chars = ['⠋', '⠙', '⠹', '⠸', '⠼', '⠴', '⠦', '⠧', '⠇', '⠏'];
208
+ let i = 0;
209
+ this.loadingInterval = setInterval(() => {
210
+ process.stdout.clearLine(0);
211
+ process.stdout.cursorTo(0);
212
+ process.stdout.write((0, picocolors_1.green)(`${chars[i]} Thinking...`));
213
+ i = (i + 1) % chars.length;
214
+ }, 100);
215
+ }
216
+ stopLoadingAnimation() {
217
+ if (this.loadingInterval) {
218
+ clearInterval(this.loadingInterval);
219
+ this.loadingInterval = null;
220
+ process.stdout.clearLine(0);
221
+ process.stdout.cursorTo(0);
222
+ }
223
+ }
224
+ async autoCommitChanges() {
225
+ if ((0, git_1.hasStagedChanges)()) {
226
+ const stagedChanges = (0, git_1.getStagedChanges)();
227
+ if (!stagedChanges)
228
+ return;
229
+ const commitMessage = await this.client.generateCommitMessage(stagedChanges);
230
+ (0, git_1.commitChanges)(commitMessage);
231
+ return commitMessage;
232
+ }
233
+ return undefined;
234
+ }
235
+ handleDiff() {
236
+ if (this.lastChanges.length === 0) {
237
+ console.log((0, picocolors_1.yellow)('No changes found in the last assistant response.'));
238
+ return;
239
+ }
240
+ this.lastChanges.forEach((change) => {
241
+ console.log('-', change.filePath);
242
+ const lines = change.content
243
+ .split('\n')
244
+ .map((line) => (change.type === 'file' ? '+' + line : line));
245
+ lines.forEach((line) => {
246
+ if (line.startsWith('+')) {
247
+ console.log((0, picocolors_1.green)(line));
248
+ }
249
+ else if (line.startsWith('-')) {
250
+ console.log((0, picocolors_1.red)(line));
251
+ }
252
+ else {
253
+ console.log(line);
254
+ }
255
+ });
256
+ });
257
+ }
258
+ async handleUserInput(userInput) {
259
+ if (!userInput)
260
+ return;
261
+ userInput = userInput.trim();
262
+ // Handle commands
263
+ if (userInput === 'help' || userInput === 'h') {
264
+ (0, menu_1.displayMenu)();
265
+ this.rl.prompt();
266
+ return;
267
+ }
268
+ if (userInput === 'login' || userInput === 'signin') {
269
+ await this.client.login();
270
+ return;
271
+ }
272
+ else if (userInput === 'logout' || userInput === 'signout') {
273
+ await this.client.logout();
274
+ this.rl.prompt();
275
+ return;
276
+ }
277
+ else if (userInput.startsWith('ref-')) {
278
+ await this.client.handleReferralCode(userInput.trim());
279
+ return;
280
+ }
281
+ else if (userInput === 'usage' || userInput === 'credits') {
282
+ this.client.getUsage();
283
+ return;
284
+ }
285
+ else if (userInput === 'undo' || userInput === 'u') {
286
+ this.handleUndo();
287
+ return;
288
+ }
289
+ else if (userInput === 'redo' || userInput === 'r') {
290
+ this.handleRedo();
291
+ return;
292
+ }
293
+ else if (userInput === 'quit' ||
294
+ userInput === 'exit' ||
295
+ userInput === 'q') {
296
+ this.handleExit();
297
+ return;
298
+ }
299
+ else if (userInput === 'diff' ||
300
+ userInput === 'doff' ||
301
+ userInput === 'dif' ||
302
+ userInput === 'iff' ||
303
+ userInput === 'd') {
304
+ this.handleDiff();
305
+ this.rl.prompt();
306
+ return;
307
+ }
308
+ const runPrefix = '/run ';
309
+ const hasRunPrefix = userInput.startsWith(runPrefix);
310
+ if (hasRunPrefix ||
311
+ (!constants_1.SKIPPED_TERMINAL_COMMANDS.some((command) => userInput.toLowerCase().startsWith(command)) &&
312
+ !userInput.includes('error ') &&
313
+ userInput.split(' ').length <= 4)) {
314
+ const withoutRunPrefix = userInput.replace(runPrefix, '');
315
+ const { result, stdout, stderr } = await (0, tool_handlers_1.handleRunTerminalCommand)({ command: withoutRunPrefix }, 'user', 'user');
316
+ if (result !== 'command not found') {
317
+ this.setPrompt();
318
+ this.rl.prompt();
319
+ return;
320
+ }
321
+ else if (hasRunPrefix) {
322
+ process.stdout.write(stdout);
323
+ process.stderr.write(stderr);
324
+ this.setPrompt();
325
+ this.rl.prompt();
326
+ return;
327
+ }
328
+ }
329
+ this.startLoadingAnimation();
330
+ await this.readyPromise;
331
+ let autoCommitPromise = null;
332
+ if (this.autoGit) {
333
+ autoCommitPromise = this.autoCommitChanges();
334
+ }
335
+ const currentChat = this.chatStorage.getCurrentChat();
336
+ const { fileVersions } = currentChat;
337
+ const currentFileVersion = fileVersions[fileVersions.length - 1]?.files ?? {};
338
+ const changesSinceLastFileVersion = (0, project_files_1.getChangesSinceLastFileVersion)(currentFileVersion);
339
+ const changesFileBlocks = Object.entries(changesSinceLastFileVersion)
340
+ .map(([filePath, patch]) => [
341
+ filePath,
342
+ patch.length < 8_000
343
+ ? patch
344
+ : '[LARGE_FILE_CHANGE_TOO_LONG_TO_REPRODUCE]',
345
+ ])
346
+ .map(([filePath, patch]) => (0, file_1.createFileBlock)(filePath, patch));
347
+ const changesMessage = changesFileBlocks.length > 0
348
+ ? `<user_edits_since_last_chat>\n${changesFileBlocks.join('\n')}\n</user_edits_since_last_chat>\n\n`
349
+ : '';
350
+ const urls = (0, web_scraper_1.parseUrlsFromContent)(userInput);
351
+ const scrapedBlocks = await (0, web_scraper_1.getScrapedContentBlocks)(urls);
352
+ const scrapedContent = scrapedBlocks.length > 0 ? scrapedBlocks.join('\n\n') + '\n\n' : '';
353
+ const newMessage = {
354
+ role: 'user',
355
+ content: `${changesMessage}${scrapedContent}${userInput}`,
356
+ };
357
+ this.chatStorage.addMessage(currentChat, newMessage);
358
+ this.isReceivingResponse = true;
359
+ const { response, changes } = await this.sendUserInputAndAwaitResponse();
360
+ this.isReceivingResponse = false;
361
+ this.stopLoadingAnimation();
362
+ if (this.autoGit) {
363
+ const commitMessage = await autoCommitPromise;
364
+ if (commitMessage) {
365
+ console.log((0, picocolors_1.green)('\nAutomatically committed changes:'));
366
+ console.log(`${commitMessage}`);
367
+ }
368
+ const changesStaged = (0, git_1.stageAllChanges)();
369
+ if (changesStaged) {
370
+ console.log((0, picocolors_1.green)('\nAll previous changes have been staged'));
371
+ }
372
+ }
373
+ const filesChanged = (0, lodash_1.uniq)(changes.map((change) => change.filePath));
374
+ const allFilesChanged = this.chatStorage.saveFilesChanged(filesChanged);
375
+ const { created, modified } = (0, changes_1.applyChanges)((0, project_files_1.getProjectRoot)(), changes);
376
+ if (created.length > 0 || modified.length > 0) {
377
+ console.log();
378
+ }
379
+ for (const file of created) {
380
+ console.log((0, picocolors_1.green)(`- Created ${file}`));
381
+ }
382
+ for (const file of modified) {
383
+ console.log((0, picocolors_1.green)(`- Updated ${file}`));
384
+ }
385
+ if (created.length > 0 || modified.length > 0) {
386
+ console.log('\nComplete! Type "diff" to see the changes made.');
387
+ this.client.showUsageWarning();
388
+ }
389
+ console.log();
390
+ this.lastChanges = changes;
391
+ const assistantMessage = {
392
+ role: 'assistant',
393
+ content: response,
394
+ };
395
+ this.chatStorage.addMessage(this.chatStorage.getCurrentChat(), assistantMessage);
396
+ const updatedFiles = (0, project_files_1.getExistingFiles)(allFilesChanged);
397
+ this.chatStorage.addNewFileState(updatedFiles);
398
+ this.rl.prompt();
399
+ }
400
+ async sendUserInputAndAwaitResponse() {
401
+ const userInputId = `mc-input-` + Math.random().toString(36).substring(2, 15);
402
+ const { responsePromise, stopResponse } = this.client.subscribeToResponse((chunk) => {
403
+ process.stdout.write(chunk);
404
+ }, userInputId, () => {
405
+ this.stopLoadingAnimation();
406
+ process.stdout.write((0, picocolors_1.green)((0, picocolors_1.underline)('\nManicode') + ':') + ' ');
407
+ });
408
+ this.stopResponse = stopResponse;
409
+ this.client.sendUserInput([], userInputId);
410
+ const result = await responsePromise;
411
+ this.stopResponse = null;
412
+ return result;
413
+ }
414
+ }
415
+ exports.CLI = CLI;
416
+ //# sourceMappingURL=cli.js.map