centaurus-cli 3.1.2 → 3.1.4

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 (142) hide show
  1. package/dist/cli-adapter.js +689 -155
  2. package/dist/cli-adapter.js.map +1 -1
  3. package/dist/config/defaultConfig.js +1 -4
  4. package/dist/config/defaultConfig.js.map +1 -1
  5. package/dist/config/models.js +6 -0
  6. package/dist/config/models.js.map +1 -1
  7. package/dist/config/slash-commands.js +66 -2
  8. package/dist/config/slash-commands.js.map +1 -1
  9. package/dist/config/types.js +4 -4
  10. package/dist/config/types.js.map +1 -1
  11. package/dist/index.js +36 -0
  12. package/dist/index.js.map +1 -1
  13. package/dist/services/ai-context-injector.js +109 -0
  14. package/dist/services/ai-context-injector.js.map +1 -1
  15. package/dist/services/ai-service-client.js +3 -2
  16. package/dist/services/ai-service-client.js.map +1 -1
  17. package/dist/services/api-client.js.map +1 -1
  18. package/dist/services/background-task-manager.js +59 -0
  19. package/dist/services/background-task-manager.js.map +1 -1
  20. package/dist/services/local-chat-storage.js +2 -0
  21. package/dist/services/local-chat-storage.js.map +1 -1
  22. package/dist/services/skill-storage.js +141 -0
  23. package/dist/services/skill-storage.js.map +1 -0
  24. package/dist/services/sub-agent-manager.js +49 -8
  25. package/dist/services/sub-agent-manager.js.map +1 -1
  26. package/dist/services/warpify-detector.js +17 -5
  27. package/dist/services/warpify-detector.js.map +1 -1
  28. package/dist/tools/background-command.js +5 -2
  29. package/dist/tools/background-command.js.map +1 -1
  30. package/dist/tools/command.js +367 -109
  31. package/dist/tools/command.js.map +1 -1
  32. package/dist/tools/file-ops.js +23 -6
  33. package/dist/tools/file-ops.js.map +1 -1
  34. package/dist/tools/plan-mode.js +184 -336
  35. package/dist/tools/plan-mode.js.map +1 -1
  36. package/dist/tools/sub-agent.js +24 -5
  37. package/dist/tools/sub-agent.js.map +1 -1
  38. package/dist/tools/todo-list.js +157 -0
  39. package/dist/tools/todo-list.js.map +1 -0
  40. package/dist/types/skill.js +30 -0
  41. package/dist/types/skill.js.map +1 -0
  42. package/dist/ui/components/App.js +956 -162
  43. package/dist/ui/components/App.js.map +1 -1
  44. package/dist/ui/components/AuthScreen.js +3 -1
  45. package/dist/ui/components/AuthScreen.js.map +1 -1
  46. package/dist/ui/components/AuthWelcomeScreen.js +3 -1
  47. package/dist/ui/components/AuthWelcomeScreen.js.map +1 -1
  48. package/dist/ui/components/CodeBlock.js +3 -1
  49. package/dist/ui/components/CodeBlock.js.map +1 -1
  50. package/dist/ui/components/CompactShellPreview.js +44 -0
  51. package/dist/ui/components/CompactShellPreview.js.map +1 -0
  52. package/dist/ui/components/ConfigViewer.js +3 -1
  53. package/dist/ui/components/ConfigViewer.js.map +1 -1
  54. package/dist/ui/components/ConfirmPrompt.js +3 -1
  55. package/dist/ui/components/ConfirmPrompt.js.map +1 -1
  56. package/dist/ui/components/ConnectionStatusMessage.js +3 -1
  57. package/dist/ui/components/ConnectionStatusMessage.js.map +1 -1
  58. package/dist/ui/components/DetailedPlanReviewScreen.js +84 -74
  59. package/dist/ui/components/DetailedPlanReviewScreen.js.map +1 -1
  60. package/dist/ui/components/DiffViewer.js +6 -3
  61. package/dist/ui/components/DiffViewer.js.map +1 -1
  62. package/dist/ui/components/FileCreationPreview.js.map +1 -1
  63. package/dist/ui/components/FileTagAutocomplete.js +4 -2
  64. package/dist/ui/components/FileTagAutocomplete.js.map +1 -1
  65. package/dist/ui/components/InputBox.js +243 -40
  66. package/dist/ui/components/InputBox.js.map +1 -1
  67. package/dist/ui/components/InteractiveShell.js +5 -3
  68. package/dist/ui/components/InteractiveShell.js.map +1 -1
  69. package/dist/ui/components/KeyboardHelp.js +4 -1
  70. package/dist/ui/components/KeyboardHelp.js.map +1 -1
  71. package/dist/ui/components/LoadingIndicator.js +3 -1
  72. package/dist/ui/components/LoadingIndicator.js.map +1 -1
  73. package/dist/ui/components/MCPAddScreen.js +63 -13
  74. package/dist/ui/components/MCPAddScreen.js.map +1 -1
  75. package/dist/ui/components/MarkdownRenderer.js +3 -1
  76. package/dist/ui/components/MarkdownRenderer.js.map +1 -1
  77. package/dist/ui/components/MessageDisplay.js +9 -7
  78. package/dist/ui/components/MessageDisplay.js.map +1 -1
  79. package/dist/ui/components/ModelPicker.js +170 -0
  80. package/dist/ui/components/ModelPicker.js.map +1 -0
  81. package/dist/ui/components/MonitorModeAIPanel.js +3 -1
  82. package/dist/ui/components/MonitorModeAIPanel.js.map +1 -1
  83. package/dist/ui/components/PlanAcceptedMessage.js +12 -6
  84. package/dist/ui/components/PlanAcceptedMessage.js.map +1 -1
  85. package/dist/ui/components/PlanQuestionMessage.js +37 -0
  86. package/dist/ui/components/PlanQuestionMessage.js.map +1 -0
  87. package/dist/ui/components/PlanQuestionScreen.js +138 -0
  88. package/dist/ui/components/PlanQuestionScreen.js.map +1 -0
  89. package/dist/ui/components/PlanReviewScreen.js +7 -9
  90. package/dist/ui/components/PlanReviewScreen.js.map +1 -1
  91. package/dist/ui/components/RulesEditorScreen.js +65 -28
  92. package/dist/ui/components/RulesEditorScreen.js.map +1 -1
  93. package/dist/ui/components/SelectPrompt.js +3 -1
  94. package/dist/ui/components/SelectPrompt.js.map +1 -1
  95. package/dist/ui/components/SkillCreatorScreen.js +217 -0
  96. package/dist/ui/components/SkillCreatorScreen.js.map +1 -0
  97. package/dist/ui/components/SlashCommandAutocomplete.js +4 -2
  98. package/dist/ui/components/SlashCommandAutocomplete.js.map +1 -1
  99. package/dist/ui/components/StatusBar.js +4 -2
  100. package/dist/ui/components/StatusBar.js.map +1 -1
  101. package/dist/ui/components/StreamingMessageDisplay.js +5 -3
  102. package/dist/ui/components/StreamingMessageDisplay.js.map +1 -1
  103. package/dist/ui/components/SubAgentListScreen.js +65 -0
  104. package/dist/ui/components/SubAgentListScreen.js.map +1 -0
  105. package/dist/ui/components/SubAgentViewScreen.js +123 -0
  106. package/dist/ui/components/SubAgentViewScreen.js.map +1 -0
  107. package/dist/ui/components/TaskCompletedMessage.js +40 -8
  108. package/dist/ui/components/TaskCompletedMessage.js.map +1 -1
  109. package/dist/ui/components/TaskProgressIndicator.js +6 -4
  110. package/dist/ui/components/TaskProgressIndicator.js.map +1 -1
  111. package/dist/ui/components/TextEditor.js +297 -0
  112. package/dist/ui/components/TextEditor.js.map +1 -0
  113. package/dist/ui/components/TodoListMessage.js +59 -0
  114. package/dist/ui/components/TodoListMessage.js.map +1 -0
  115. package/dist/ui/components/ToolExecutionMessage.js +134 -84
  116. package/dist/ui/components/ToolExecutionMessage.js.map +1 -1
  117. package/dist/ui/components/ToolExecutionStatus.js +3 -1
  118. package/dist/ui/components/ToolExecutionStatus.js.map +1 -1
  119. package/dist/ui/components/WelcomeBanner.js +33 -33
  120. package/dist/ui/components/WelcomeBanner.js.map +1 -1
  121. package/dist/ui/components/WorkflowCreatorScreen.js +5 -3
  122. package/dist/ui/components/WorkflowCreatorScreen.js.map +1 -1
  123. package/dist/ui/theme.js +97 -0
  124. package/dist/ui/theme.js.map +1 -0
  125. package/dist/ui/utils/chat-history-limit.js +247 -0
  126. package/dist/ui/utils/chat-history-limit.js.map +1 -0
  127. package/dist/utils/chat-formatter.js +22 -9
  128. package/dist/utils/chat-formatter.js.map +1 -1
  129. package/dist/utils/git-stats.js +7 -5
  130. package/dist/utils/git-stats.js.map +1 -1
  131. package/dist/utils/input-classifier.js +11 -1
  132. package/dist/utils/input-classifier.js.map +1 -1
  133. package/dist/utils/output-truncation.js +175 -0
  134. package/dist/utils/output-truncation.js.map +1 -0
  135. package/dist/utils/rule-reference-resolver.js +3 -3
  136. package/dist/utils/rule-reference-resolver.js.map +1 -1
  137. package/dist/utils/tunnel-commands-manager.js +134 -0
  138. package/dist/utils/tunnel-commands-manager.js.map +1 -0
  139. package/package.json +91 -90
  140. package/postinstall.js +4 -11
  141. package/dist/ui/components/MultiLineInput.js +0 -255
  142. package/dist/ui/components/MultiLineInput.js.map +0 -1
@@ -0,0 +1,134 @@
1
+ import * as fs from "fs/promises";
2
+ import * as fsSync from "fs";
3
+ import * as path from "path";
4
+ import * as os from "os";
5
+ function normalizeTunnelCommand(command) {
6
+ return command.trim().replace(/\s+/g, " ").toLowerCase();
7
+ }
8
+ function matchTunnelableCommand(command, registeredCommands) {
9
+ const normalizedInput = normalizeTunnelCommand(command);
10
+ if (!normalizedInput) {
11
+ return null;
12
+ }
13
+ const normalizedRegistered = [...new Set(
14
+ registeredCommands.map(normalizeTunnelCommand).filter(Boolean)
15
+ )].sort((a, b) => b.length - a.length);
16
+ for (const registeredCommand of normalizedRegistered) {
17
+ if (normalizedInput === registeredCommand || normalizedInput.startsWith(`${registeredCommand} `)) {
18
+ return registeredCommand;
19
+ }
20
+ }
21
+ return null;
22
+ }
23
+ class TunnelCommandsManager {
24
+ static instance;
25
+ configPath;
26
+ data;
27
+ loaded = false;
28
+ constructor() {
29
+ const configDir = path.join(os.homedir(), ".centaurus");
30
+ this.configPath = path.join(configDir, "tunnel-commands.json");
31
+ this.data = { commands: [], version: 1 };
32
+ }
33
+ static getInstance() {
34
+ if (!TunnelCommandsManager.instance) {
35
+ TunnelCommandsManager.instance = new TunnelCommandsManager();
36
+ }
37
+ return TunnelCommandsManager.instance;
38
+ }
39
+ async initialize() {
40
+ if (this.loaded) return;
41
+ await this.load();
42
+ }
43
+ loadSync() {
44
+ if (this.loaded) return;
45
+ try {
46
+ if (fsSync.existsSync(this.configPath)) {
47
+ const content = fsSync.readFileSync(this.configPath, "utf-8");
48
+ const parsed = JSON.parse(content);
49
+ if (parsed.commands && Array.isArray(parsed.commands)) {
50
+ this.data = {
51
+ commands: parsed.commands.map(normalizeTunnelCommand).filter(Boolean),
52
+ version: parsed.version || 1
53
+ };
54
+ }
55
+ }
56
+ } catch {
57
+ this.data = { commands: [], version: 1 };
58
+ }
59
+ this.loaded = true;
60
+ }
61
+ async ensureConfigDir() {
62
+ const configDir = path.dirname(this.configPath);
63
+ try {
64
+ await fs.access(configDir);
65
+ } catch {
66
+ await fs.mkdir(configDir, { recursive: true });
67
+ }
68
+ }
69
+ async load() {
70
+ try {
71
+ const content = await fs.readFile(this.configPath, "utf-8");
72
+ const parsed = JSON.parse(content);
73
+ if (parsed.commands && Array.isArray(parsed.commands)) {
74
+ this.data = {
75
+ commands: parsed.commands.map(normalizeTunnelCommand).filter(Boolean),
76
+ version: parsed.version || 1
77
+ };
78
+ } else {
79
+ this.data = { commands: [], version: 1 };
80
+ }
81
+ } catch {
82
+ this.data = { commands: [], version: 1 };
83
+ }
84
+ this.loaded = true;
85
+ }
86
+ async save() {
87
+ await this.ensureConfigDir();
88
+ await fs.writeFile(
89
+ this.configPath,
90
+ JSON.stringify(this.data, null, 2),
91
+ "utf-8"
92
+ );
93
+ }
94
+ async addCommand(command) {
95
+ const normalized = normalizeTunnelCommand(command);
96
+ if (!normalized) {
97
+ return { success: false, message: "Tunnel command cannot be empty" };
98
+ }
99
+ if (this.data.commands.includes(normalized)) {
100
+ return { success: false, message: `Tunnel command "${normalized}" already exists` };
101
+ }
102
+ this.data.commands.push(normalized);
103
+ this.data.commands.sort();
104
+ await this.save();
105
+ return { success: true, message: `Added "${normalized}" to tunnel commands` };
106
+ }
107
+ async deleteCommand(command) {
108
+ const normalized = normalizeTunnelCommand(command);
109
+ const index = this.data.commands.indexOf(normalized);
110
+ if (index === -1) {
111
+ return { success: false, message: `Tunnel command "${normalized}" not found` };
112
+ }
113
+ this.data.commands.splice(index, 1);
114
+ await this.save();
115
+ return { success: true, message: `Deleted "${normalized}" from tunnel commands` };
116
+ }
117
+ listCommands() {
118
+ return [...this.data.commands];
119
+ }
120
+ matchCommand(command) {
121
+ return matchTunnelableCommand(command, this.data.commands);
122
+ }
123
+ getCount() {
124
+ return this.data.commands.length;
125
+ }
126
+ }
127
+ var tunnel_commands_manager_default = TunnelCommandsManager;
128
+ export {
129
+ TunnelCommandsManager,
130
+ tunnel_commands_manager_default as default,
131
+ matchTunnelableCommand,
132
+ normalizeTunnelCommand
133
+ };
134
+ //# sourceMappingURL=tunnel-commands-manager.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../src/utils/tunnel-commands-manager.ts"],"sourcesContent":["import * as fs from 'fs/promises';\r\nimport * as fsSync from 'fs';\r\nimport * as path from 'path';\r\nimport * as os from 'os';\r\n\r\ninterface TunnelCommandsData {\r\n commands: string[];\r\n version: number;\r\n}\r\n\r\nexport function normalizeTunnelCommand(command: string): string {\r\n return command.trim().replace(/\\s+/g, ' ').toLowerCase();\r\n}\r\n\r\nexport function matchTunnelableCommand(command: string, registeredCommands: string[]): string | null {\r\n const normalizedInput = normalizeTunnelCommand(command);\r\n if (!normalizedInput) {\r\n return null;\r\n }\r\n\r\n const normalizedRegistered = [...new Set(\r\n registeredCommands\r\n .map(normalizeTunnelCommand)\r\n .filter(Boolean)\r\n )].sort((a, b) => b.length - a.length);\r\n\r\n for (const registeredCommand of normalizedRegistered) {\r\n if (\r\n normalizedInput === registeredCommand ||\r\n normalizedInput.startsWith(`${registeredCommand} `)\r\n ) {\r\n return registeredCommand;\r\n }\r\n }\r\n\r\n return null;\r\n}\r\n\r\nexport class TunnelCommandsManager {\r\n private static instance: TunnelCommandsManager;\r\n private configPath: string;\r\n private data: TunnelCommandsData;\r\n private loaded: boolean = false;\r\n\r\n private constructor() {\r\n const configDir = path.join(os.homedir(), '.centaurus');\r\n this.configPath = path.join(configDir, 'tunnel-commands.json');\r\n this.data = { commands: [], version: 1 };\r\n }\r\n\r\n static getInstance(): TunnelCommandsManager {\r\n if (!TunnelCommandsManager.instance) {\r\n TunnelCommandsManager.instance = new TunnelCommandsManager();\r\n }\r\n return TunnelCommandsManager.instance;\r\n }\r\n\r\n async initialize(): Promise<void> {\r\n if (this.loaded) return;\r\n await this.load();\r\n }\r\n\r\n loadSync(): void {\r\n if (this.loaded) return;\r\n\r\n try {\r\n if (fsSync.existsSync(this.configPath)) {\r\n const content = fsSync.readFileSync(this.configPath, 'utf-8');\r\n const parsed = JSON.parse(content);\r\n if (parsed.commands && Array.isArray(parsed.commands)) {\r\n this.data = {\r\n commands: parsed.commands.map(normalizeTunnelCommand).filter(Boolean),\r\n version: parsed.version || 1,\r\n };\r\n }\r\n }\r\n } catch {\r\n this.data = { commands: [], version: 1 };\r\n }\r\n\r\n this.loaded = true;\r\n }\r\n\r\n private async ensureConfigDir(): Promise<void> {\r\n const configDir = path.dirname(this.configPath);\r\n try {\r\n await fs.access(configDir);\r\n } catch {\r\n await fs.mkdir(configDir, { recursive: true });\r\n }\r\n }\r\n\r\n private async load(): Promise<void> {\r\n try {\r\n const content = await fs.readFile(this.configPath, 'utf-8');\r\n const parsed = JSON.parse(content);\r\n if (parsed.commands && Array.isArray(parsed.commands)) {\r\n this.data = {\r\n commands: parsed.commands.map(normalizeTunnelCommand).filter(Boolean),\r\n version: parsed.version || 1,\r\n };\r\n } else {\r\n this.data = { commands: [], version: 1 };\r\n }\r\n } catch {\r\n this.data = { commands: [], version: 1 };\r\n }\r\n\r\n this.loaded = true;\r\n }\r\n\r\n private async save(): Promise<void> {\r\n await this.ensureConfigDir();\r\n await fs.writeFile(\r\n this.configPath,\r\n JSON.stringify(this.data, null, 2),\r\n 'utf-8'\r\n );\r\n }\r\n\r\n async addCommand(command: string): Promise<{ success: boolean; message: string }> {\r\n const normalized = normalizeTunnelCommand(command);\r\n\r\n if (!normalized) {\r\n return { success: false, message: 'Tunnel command cannot be empty' };\r\n }\r\n\r\n if (this.data.commands.includes(normalized)) {\r\n return { success: false, message: `Tunnel command \"${normalized}\" already exists` };\r\n }\r\n\r\n this.data.commands.push(normalized);\r\n this.data.commands.sort();\r\n await this.save();\r\n\r\n return { success: true, message: `Added \"${normalized}\" to tunnel commands` };\r\n }\r\n\r\n async deleteCommand(command: string): Promise<{ success: boolean; message: string }> {\r\n const normalized = normalizeTunnelCommand(command);\r\n const index = this.data.commands.indexOf(normalized);\r\n\r\n if (index === -1) {\r\n return { success: false, message: `Tunnel command \"${normalized}\" not found` };\r\n }\r\n\r\n this.data.commands.splice(index, 1);\r\n await this.save();\r\n\r\n return { success: true, message: `Deleted \"${normalized}\" from tunnel commands` };\r\n }\r\n\r\n listCommands(): string[] {\r\n return [...this.data.commands];\r\n }\r\n\r\n matchCommand(command: string): string | null {\r\n return matchTunnelableCommand(command, this.data.commands);\r\n }\r\n\r\n getCount(): number {\r\n return this.data.commands.length;\r\n }\r\n}\r\n\r\nexport default TunnelCommandsManager;\r\n"],"mappings":"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","names":[]}
package/package.json CHANGED
@@ -1,92 +1,93 @@
1
1
  {
2
- "name": "centaurus-cli",
3
- "version": "3.1.2",
4
- "description": "A powerful command-line AI coding assistant with Google Gemini support",
5
- "type": "module",
6
- "main": "dist/index.js",
7
- "bin": {
8
- "centaurus": "dist/index.js",
9
- "centaurus-cli": "dist/index.js"
10
- },
11
- "scripts": {
12
- "build": "tsc --noEmit \u0026\u0026 tsup",
13
- "typecheck": "tsc --noEmit",
14
- "dev": "tsup --watch",
15
- "start": "node dist/index.js",
16
- "prepublishOnly": "npm run build",
17
- "postinstall": "node postinstall.js || true",
18
- "test": "node --experimental-vm-modules node_modules/.bin/jest --config jest.config.cjs",
19
- "test:ci": "node --experimental-vm-modules node_modules/.bin/jest --config jest.config.cjs --ci --forceExit"
20
- },
21
- "keywords": [
22
- "ai",
23
- "cli",
24
- "coding-assistant",
25
- "gemini",
26
- "agentic",
27
- "code-editor",
28
- "ai-assistant",
29
- "terminal",
30
- "developer-tools",
31
- "llm",
32
- "artificial-intelligence"
33
- ],
34
- "author": "Rohan Abhilash S",
35
- "license": "MIT",
36
- "engines": {
37
- "node": "\u003e=18.0.0"
38
- },
39
- "files": [
40
- "dist",
41
- "prompts",
42
- "postinstall.js",
43
- "models-config.json",
44
- "README.md",
45
- "LICENSE",
46
- "CONFIG_GUIDE.md",
47
- "AUTH_FLOW.md"
48
- ],
49
- "dependencies": {
50
- "@anthropic-ai/sdk": "^0.74.0",
51
- "@crosscopy/clipboard": "^0.2.8",
52
- "@homebridge/node-pty-prebuilt-multiarch": "^0.13.1",
53
- "@huggingface/transformers": "^3.8.1",
54
- "@modelcontextprotocol/sdk": "^1.24.2",
55
- "@types/sharp": "^0.31.1",
56
- "axios": "^1.12.2",
57
- "boxen": "^8.0.1",
58
- "chalk": "^5.6.2",
59
- "cheerio": "^1.1.2",
60
- "cli-highlight": "^2.1.11",
61
- "clipboard-files": "^3.0.0",
62
- "commander": "^14.0.1",
63
- "cross-spawn": "^7.0.6",
64
- "diff": "^8.0.2",
65
- "fast-glob": "^3.3.3",
66
- "ink": "^4.4.1",
67
- "ink-select-input": "^5.0.0",
68
- "ink-spinner": "^5.0.0",
69
- "ink-text-input": "^5.0.1",
70
- "js-tiktoken": "^1.0.21",
71
- "open": "^10.1.0",
72
- "react": "^18.3.1",
73
- "sharp": "^0.34.5",
74
- "ssh2": "^1.15.0",
75
- "string-width": "^8.1.0",
76
- "strip-ansi": "^7.1.0",
77
- "typescript": "^5.9.3",
78
- "wrap-ansi": "^9.0.2"
79
- },
80
- "devDependencies": {
81
- "@types/inquirer": "^9.0.9",
82
- "@types/jest": "^30.0.0",
83
- "@types/node": "^24.7.2",
84
- "@types/react": "^18.3.26",
85
- "@types/ssh2": "^1.15.0",
86
- "jest": "^30.2.0",
87
- "prettier": "^3.6.2",
88
- "ts-jest": "^29.4.6",
89
- "ts-node": "^10.9.2",
90
- "tsup": "^8.5.1"
91
- }
2
+ "name": "centaurus-cli",
3
+ "version": "3.1.4",
4
+ "description": "A powerful command-line AI coding assistant with Google Gemini support",
5
+ "type": "module",
6
+ "main": "dist/index.js",
7
+ "bin": {
8
+ "centaurus": "dist/index.js",
9
+ "centaurus-cli": "dist/index.js"
10
+ },
11
+ "scripts": {
12
+ "build": "tsc --noEmit && tsup",
13
+ "build:release": "node scripts/build-release-bundle.mjs",
14
+ "typecheck": "tsc --noEmit",
15
+ "dev": "tsup --watch",
16
+ "start": "node --max-old-space-size=6144 dist/index.js",
17
+ "prepublishOnly": "npm run build",
18
+ "postinstall": "node postinstall.js || true",
19
+ "test": "node --experimental-vm-modules node_modules/.bin/jest --config jest.config.cjs",
20
+ "test:ci": "node --experimental-vm-modules node_modules/.bin/jest --config jest.config.cjs --ci --forceExit"
21
+ },
22
+ "keywords": [
23
+ "ai",
24
+ "cli",
25
+ "coding-assistant",
26
+ "gemini",
27
+ "agentic",
28
+ "code-editor",
29
+ "ai-assistant",
30
+ "terminal",
31
+ "developer-tools",
32
+ "llm",
33
+ "artificial-intelligence"
34
+ ],
35
+ "author": "Rohan Abhilash S",
36
+ "license": "MIT",
37
+ "engines": {
38
+ "node": ">=18.0.0"
39
+ },
40
+ "files": [
41
+ "dist",
42
+ "prompts",
43
+ "postinstall.js",
44
+ "models-config.json",
45
+ "README.md",
46
+ "LICENSE",
47
+ "CONFIG_GUIDE.md",
48
+ "AUTH_FLOW.md"
49
+ ],
50
+ "dependencies": {
51
+ "@anthropic-ai/sdk": "^0.74.0",
52
+ "@crosscopy/clipboard": "^0.2.8",
53
+ "@homebridge/node-pty-prebuilt-multiarch": "^0.13.1",
54
+ "@huggingface/transformers": "^3.8.1",
55
+ "@modelcontextprotocol/sdk": "^1.24.2",
56
+ "@types/sharp": "^0.31.1",
57
+ "axios": "^1.12.2",
58
+ "boxen": "^8.0.1",
59
+ "chalk": "^5.6.2",
60
+ "cheerio": "^1.1.2",
61
+ "cli-highlight": "^2.1.11",
62
+ "clipboard-files": "^3.0.0",
63
+ "commander": "^14.0.1",
64
+ "cross-spawn": "^7.0.6",
65
+ "diff": "^8.0.2",
66
+ "fast-glob": "^3.3.3",
67
+ "ink": "^4.4.1",
68
+ "ink-select-input": "^5.0.0",
69
+ "ink-spinner": "^5.0.0",
70
+ "ink-text-input": "^5.0.1",
71
+ "js-tiktoken": "^1.0.21",
72
+ "open": "^10.1.0",
73
+ "react": "^18.3.1",
74
+ "sharp": "^0.34.5",
75
+ "ssh2": "^1.15.0",
76
+ "string-width": "^8.1.0",
77
+ "strip-ansi": "^7.1.0",
78
+ "typescript": "^5.9.3",
79
+ "wrap-ansi": "^9.0.2"
80
+ },
81
+ "devDependencies": {
82
+ "@types/inquirer": "^9.0.9",
83
+ "@types/jest": "^30.0.0",
84
+ "@types/node": "^24.7.2",
85
+ "@types/react": "^18.3.26",
86
+ "@types/ssh2": "^1.15.0",
87
+ "jest": "^30.2.0",
88
+ "prettier": "^3.6.2",
89
+ "ts-jest": "^29.4.6",
90
+ "ts-node": "^10.9.2",
91
+ "tsup": "^8.5.1"
92
+ }
92
93
  }
package/postinstall.js CHANGED
@@ -16,22 +16,15 @@ ${chalk.bold('Quick Start:')}
16
16
  1. Run Centaurus in any directory:
17
17
  ${chalk.cyan('$ centaurus')}
18
18
 
19
- 2. Configure your API keys:
20
- ${chalk.cyan('/config set googleApiKey YOUR_KEY')}
21
-
22
- 3. Start chatting with AI!
23
-
24
- ${chalk.bold('Get API Keys:')}
25
- • Google AI: ${chalk.blue('https://makersuite.google.com/app/apikey')}
26
- • OpenRouter: ${chalk.blue('https://openrouter.ai/keys')}
19
+ 2. Sign in when prompted and start chatting with AI.
27
20
 
28
21
  ${chalk.bold('Documentation:')}
29
- README: ${chalk.blue('https://github.com/yourusername/centaurus-cli')}
30
- Config Guide: Run ${chalk.cyan('centaurus')} and type ${chalk.cyan('/help')}
22
+ Run ${chalk.cyan('centaurus')} and type ${chalk.cyan('/help')}
23
+ Open the web docs from the app when needed
31
24
 
32
25
  ${chalk.bold('Need Help?')}
33
26
  • Type ${chalk.cyan('/help')} in the CLI
34
- Visit: ${chalk.blue('https://github.com/yourusername/centaurus-cli/issues')}
27
+ Use the in-app docs and support links
35
28
 
36
29
  ${chalk.dim('Made with ❤️ by developers, for developers')}
37
30
  `;
@@ -1,255 +0,0 @@
1
- import React, { useState, useEffect, useRef } from "react";
2
- import { Box, Text, useInput } from "ink";
3
- const isWordBoundary = (char) => /[\s\n]/.test(char);
4
- const getVisualLines = (text, width) => {
5
- const logicalLines = text.split("\n");
6
- const visualLines = [];
7
- let currentOffset = 0;
8
- logicalLines.forEach((line, i) => {
9
- if (line.length === 0) {
10
- visualLines.push({ start: currentOffset, end: currentOffset, isHardEnd: true });
11
- currentOffset += 1;
12
- return;
13
- }
14
- let remaining = line;
15
- let lineStartOffset = currentOffset;
16
- while (remaining.length > 0) {
17
- let splitIndex = remaining.length;
18
- let isHardEnd = false;
19
- if (remaining.length > width) {
20
- splitIndex = width;
21
- const lastSpace = remaining.lastIndexOf(" ", width);
22
- if (lastSpace > 0) {
23
- splitIndex = lastSpace + 1;
24
- }
25
- } else {
26
- isHardEnd = true;
27
- }
28
- visualLines.push({
29
- start: lineStartOffset,
30
- end: lineStartOffset + splitIndex,
31
- isHardEnd
32
- });
33
- lineStartOffset += splitIndex;
34
- remaining = remaining.slice(splitIndex);
35
- }
36
- currentOffset += line.length + (i < logicalLines.length - 1 ? 1 : 0);
37
- });
38
- return visualLines;
39
- };
40
- const MultiLineInput = ({
41
- value = "",
42
- onChange,
43
- onSubmit,
44
- placeholder = "",
45
- isActive = true,
46
- minHeight = 3,
47
- maxHeight = 10,
48
- submitOnEnter = true
49
- }) => {
50
- const [cursorOffset, setCursorOffset] = useState(0);
51
- const valueRef = useRef(value);
52
- const cursorOffsetRef = useRef(cursorOffset);
53
- useEffect(() => {
54
- valueRef.current = value;
55
- }, [value]);
56
- useEffect(() => {
57
- cursorOffsetRef.current = cursorOffset;
58
- }, [cursorOffset]);
59
- useEffect(() => {
60
- if (cursorOffset > value.length) {
61
- setCursorOffset(value.length);
62
- }
63
- }, [value, cursorOffset]);
64
- useInput((input, key) => {
65
- if (!isActive) return;
66
- const currentValue = valueRef.current;
67
- const currentCursorOffset = cursorOffsetRef.current;
68
- const normalizedInput = input ? input.toLowerCase() : "";
69
- const isTerminalShiftEnterSequence = input === "\x1B\r" || input === "\x1B\n" || normalizedInput === "\x1B[13;2u" || normalizedInput === "\x1B[13;2~" || normalizedInput === "\x1B[27;2;13~";
70
- const isEnterEvent = key.return || isTerminalShiftEnterSequence;
71
- if (key.backspace || key.delete) {
72
- if (currentCursorOffset > 0) {
73
- const newValue = currentValue.slice(0, currentCursorOffset - 1) + currentValue.slice(currentCursorOffset);
74
- onChange(newValue);
75
- setCursorOffset(currentCursorOffset - 1);
76
- }
77
- return;
78
- }
79
- if (isEnterEvent && (input.length <= 1 || isTerminalShiftEnterSequence)) {
80
- const isBackslashEnterFallback = !key.shift && !key.ctrl && !key.meta && !isTerminalShiftEnterSequence && currentCursorOffset > 0 && currentValue[currentCursorOffset - 1] === "\\";
81
- const shouldInsertNewline = !submitOnEnter || key.shift || key.ctrl || key.meta || input === "\n" || isTerminalShiftEnterSequence || isBackslashEnterFallback;
82
- if (shouldInsertNewline) {
83
- const newValue = isBackslashEnterFallback ? currentValue.slice(0, currentCursorOffset - 1) + "\n" + currentValue.slice(currentCursorOffset) : currentValue.slice(0, currentCursorOffset) + "\n" + currentValue.slice(currentCursorOffset);
84
- const newOffset = isBackslashEnterFallback ? currentCursorOffset : currentCursorOffset + 1;
85
- onChange(newValue);
86
- setCursorOffset(newOffset);
87
- } else {
88
- onSubmit(currentValue);
89
- }
90
- return;
91
- }
92
- if (key.upArrow) {
93
- const width = (process.stdout.columns || 80) - 4;
94
- const visualLines2 = getVisualLines(currentValue, width);
95
- let currentLineIdx = visualLines2.findIndex(
96
- (line) => currentCursorOffset >= line.start && currentCursorOffset < line.end || currentCursorOffset === line.end && line.isHardEnd
97
- );
98
- if (currentLineIdx === -1 && currentCursorOffset === currentValue.length) {
99
- currentLineIdx = visualLines2.length - 1;
100
- }
101
- if (currentLineIdx > 0) {
102
- const currentLine = visualLines2[currentLineIdx];
103
- const targetLine = visualLines2[currentLineIdx - 1];
104
- const offsetInLine = currentCursorOffset - currentLine.start;
105
- const newOffset = targetLine.start + Math.min(offsetInLine, targetLine.end - targetLine.start);
106
- setCursorOffset(newOffset);
107
- } else {
108
- setCursorOffset(0);
109
- }
110
- return;
111
- }
112
- if (key.downArrow) {
113
- const width = (process.stdout.columns || 80) - 4;
114
- const visualLines2 = getVisualLines(currentValue, width);
115
- let currentLineIdx = visualLines2.findIndex(
116
- (line) => currentCursorOffset >= line.start && currentCursorOffset < line.end || currentCursorOffset === line.end && line.isHardEnd
117
- );
118
- if (currentLineIdx === -1 && currentCursorOffset === currentValue.length) {
119
- currentLineIdx = visualLines2.length - 1;
120
- }
121
- if (currentLineIdx < visualLines2.length - 1) {
122
- const currentLine = visualLines2[currentLineIdx];
123
- const targetLine = visualLines2[currentLineIdx + 1];
124
- const offsetInLine = currentCursorOffset - currentLine.start;
125
- const newOffset = targetLine.start + Math.min(offsetInLine, targetLine.end - targetLine.start);
126
- setCursorOffset(newOffset);
127
- } else {
128
- setCursorOffset(currentValue.length);
129
- }
130
- return;
131
- }
132
- if (key.leftArrow) {
133
- if (currentCursorOffset > 0) {
134
- let newOffset = currentCursorOffset;
135
- if (key.ctrl || key.meta) {
136
- while (newOffset > 0 && isWordBoundary(currentValue[newOffset - 1])) {
137
- newOffset--;
138
- }
139
- while (newOffset > 0 && !isWordBoundary(currentValue[newOffset - 1])) {
140
- newOffset--;
141
- }
142
- } else {
143
- newOffset--;
144
- }
145
- setCursorOffset(newOffset);
146
- }
147
- return;
148
- }
149
- if (key.rightArrow) {
150
- if (currentCursorOffset < currentValue.length) {
151
- let newOffset = currentCursorOffset;
152
- if (key.ctrl || key.meta) {
153
- while (newOffset < currentValue.length && !isWordBoundary(currentValue[newOffset])) {
154
- newOffset++;
155
- }
156
- while (newOffset < currentValue.length && isWordBoundary(currentValue[newOffset])) {
157
- newOffset++;
158
- }
159
- } else {
160
- newOffset++;
161
- }
162
- setCursorOffset(newOffset);
163
- }
164
- return;
165
- }
166
- if (key.home) {
167
- const width = (process.stdout.columns || 80) - 4;
168
- const visualLines2 = getVisualLines(currentValue, width);
169
- const currentLine = visualLines2.find(
170
- (line) => currentCursorOffset >= line.start && currentCursorOffset < line.end || currentCursorOffset === line.end && line.isHardEnd
171
- );
172
- if (currentLine) {
173
- setCursorOffset(currentLine.start);
174
- } else {
175
- setCursorOffset(0);
176
- }
177
- return;
178
- }
179
- if (key.end) {
180
- const width = (process.stdout.columns || 80) - 4;
181
- const visualLines2 = getVisualLines(currentValue, width);
182
- const currentLine = visualLines2.find(
183
- (line) => currentCursorOffset >= line.start && currentCursorOffset < line.end || currentCursorOffset === line.end && line.isHardEnd
184
- );
185
- if (currentLine) {
186
- setCursorOffset(currentLine.end);
187
- } else {
188
- setCursorOffset(currentValue.length);
189
- }
190
- return;
191
- }
192
- if (input) {
193
- const cleanedInput = input.replace(/\r\n/g, "\n").replace(/\r/g, "\n");
194
- const newValue = currentValue.slice(0, currentCursorOffset) + cleanedInput + currentValue.slice(currentCursorOffset);
195
- onChange(newValue);
196
- setCursorOffset(currentCursorOffset + cleanedInput.length);
197
- }
198
- });
199
- const termWidth = (process.stdout.columns || 80) - 4;
200
- const visualLines = getVisualLines(value, termWidth);
201
- let cursorVisualLine = 0;
202
- for (let i = 0; i < visualLines.length; i++) {
203
- if (cursorOffset >= visualLines[i].start && cursorOffset <= visualLines[i].end) {
204
- cursorVisualLine = i;
205
- break;
206
- }
207
- }
208
- if (cursorOffset === value.length && visualLines.length > 0) {
209
- cursorVisualLine = visualLines.length - 1;
210
- }
211
- const totalLines = visualLines.length;
212
- const height = Math.min(Math.max(totalLines, minHeight), maxHeight);
213
- let startLine = 0;
214
- if (totalLines > height) {
215
- if (cursorVisualLine < height) {
216
- startLine = 0;
217
- } else {
218
- startLine = cursorVisualLine - height + 1;
219
- }
220
- }
221
- const endLine = Math.min(startLine + height, totalLines);
222
- const visibleLines = visualLines.slice(startLine, endLine);
223
- const topIndicatorCount = startLine > 0 ? 1 : 0;
224
- const bottomIndicatorCount = endLine < totalLines ? 1 : 0;
225
- const fillerLineCount = Math.max(0, height - visibleLines.length - topIndicatorCount - bottomIndicatorCount);
226
- if (value.length === 0 && placeholder) {
227
- return /* @__PURE__ */ React.createElement(Box, { flexDirection: "column", width: "100%", minHeight: height }, /* @__PURE__ */ React.createElement(Text, { color: "gray" }, placeholder), Array.from({ length: Math.max(0, height - 1) }, (_, idx) => /* @__PURE__ */ React.createElement(Text, { key: `placeholder-pad-${idx}` }, " ")));
228
- }
229
- return /* @__PURE__ */ React.createElement(Box, { flexDirection: "column", width: "100%", minHeight: height }, startLine > 0 && /* @__PURE__ */ React.createElement(Text, { color: "gray" }, "\u2191"), visibleLines.map((vLine, idx) => {
230
- const lineContent = value.slice(vLine.start, vLine.end);
231
- const isCursorLine = cursorOffset >= vLine.start && cursorOffset <= vLine.end;
232
- const cursorCol = isCursorLine ? cursorOffset - vLine.start : -1;
233
- if (!isActive) {
234
- return /* @__PURE__ */ React.createElement(Text, { key: idx }, lineContent);
235
- }
236
- const chars = lineContent.split("");
237
- const renderedChars = chars.map((char, charIdx) => {
238
- if (isCursorLine && charIdx === cursorCol) {
239
- return /* @__PURE__ */ React.createElement(Text, { key: charIdx, inverse: true }, char);
240
- }
241
- return /* @__PURE__ */ React.createElement(Text, { key: charIdx }, char);
242
- });
243
- if (isCursorLine && cursorCol === lineContent.length) {
244
- renderedChars.push(/* @__PURE__ */ React.createElement(Text, { key: "cursor", inverse: true }, " "));
245
- }
246
- if (renderedChars.length === 0) {
247
- return /* @__PURE__ */ React.createElement(Text, { key: idx }, " ");
248
- }
249
- return /* @__PURE__ */ React.createElement(Text, { key: idx }, renderedChars);
250
- }), endLine < totalLines && /* @__PURE__ */ React.createElement(Text, { color: "gray" }, "\u2193"), Array.from({ length: fillerLineCount }, (_, idx) => /* @__PURE__ */ React.createElement(Text, { key: `pad-${idx}` }, " ")));
251
- };
252
- export {
253
- MultiLineInput
254
- };
255
- //# sourceMappingURL=MultiLineInput.js.map