centaurus-cli 2.9.1 → 2.9.3

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 (156) hide show
  1. package/dist/cli-adapter.d.ts +76 -3
  2. package/dist/cli-adapter.d.ts.map +1 -1
  3. package/dist/cli-adapter.js +593 -230
  4. package/dist/cli-adapter.js.map +1 -1
  5. package/dist/config/mcp-config-manager.d.ts +21 -0
  6. package/dist/config/mcp-config-manager.d.ts.map +1 -1
  7. package/dist/config/mcp-config-manager.js +184 -1
  8. package/dist/config/mcp-config-manager.js.map +1 -1
  9. package/dist/config/models.d.ts +1 -0
  10. package/dist/config/models.d.ts.map +1 -1
  11. package/dist/config/models.js +9 -2
  12. package/dist/config/models.js.map +1 -1
  13. package/dist/config/slash-commands.d.ts +3 -0
  14. package/dist/config/slash-commands.d.ts.map +1 -1
  15. package/dist/config/slash-commands.js +39 -4
  16. package/dist/config/slash-commands.js.map +1 -1
  17. package/dist/config/types.d.ts +2 -0
  18. package/dist/config/types.d.ts.map +1 -1
  19. package/dist/config/types.js +1 -0
  20. package/dist/config/types.js.map +1 -1
  21. package/dist/index.js +60 -11
  22. package/dist/index.js.map +1 -1
  23. package/dist/mcp/mcp-command-handler.d.ts +34 -3
  24. package/dist/mcp/mcp-command-handler.d.ts.map +1 -1
  25. package/dist/mcp/mcp-command-handler.js +171 -83
  26. package/dist/mcp/mcp-command-handler.js.map +1 -1
  27. package/dist/mcp/mcp-server-manager.d.ts.map +1 -1
  28. package/dist/mcp/mcp-server-manager.js +9 -23
  29. package/dist/mcp/mcp-server-manager.js.map +1 -1
  30. package/dist/mcp/mcp-tool-wrapper.d.ts.map +1 -1
  31. package/dist/mcp/mcp-tool-wrapper.js +42 -5
  32. package/dist/mcp/mcp-tool-wrapper.js.map +1 -1
  33. package/dist/services/ai-autocomplete-agent.d.ts +39 -0
  34. package/dist/services/ai-autocomplete-agent.d.ts.map +1 -0
  35. package/dist/services/ai-autocomplete-agent.js +189 -0
  36. package/dist/services/ai-autocomplete-agent.js.map +1 -0
  37. package/dist/services/ai-service-client.d.ts +25 -0
  38. package/dist/services/ai-service-client.d.ts.map +1 -1
  39. package/dist/services/ai-service-client.js +162 -1
  40. package/dist/services/ai-service-client.js.map +1 -1
  41. package/dist/services/api-client.d.ts +9 -0
  42. package/dist/services/api-client.d.ts.map +1 -1
  43. package/dist/services/api-client.js +25 -0
  44. package/dist/services/api-client.js.map +1 -1
  45. package/dist/services/auth-handler.js +1 -1
  46. package/dist/services/auth-handler.js.map +1 -1
  47. package/dist/services/input-detection-agent.d.ts +40 -0
  48. package/dist/services/input-detection-agent.d.ts.map +1 -0
  49. package/dist/services/input-detection-agent.js +213 -0
  50. package/dist/services/input-detection-agent.js.map +1 -0
  51. package/dist/services/input-requirement-detector.d.ts +28 -0
  52. package/dist/services/input-requirement-detector.d.ts.map +1 -0
  53. package/dist/services/input-requirement-detector.js +203 -0
  54. package/dist/services/input-requirement-detector.js.map +1 -0
  55. package/dist/services/local-chat-storage.d.ts +21 -0
  56. package/dist/services/local-chat-storage.d.ts.map +1 -1
  57. package/dist/services/local-chat-storage.js +138 -43
  58. package/dist/services/local-chat-storage.js.map +1 -1
  59. package/dist/services/monitored-shell-manager.d.ts +120 -0
  60. package/dist/services/monitored-shell-manager.d.ts.map +1 -0
  61. package/dist/services/monitored-shell-manager.js +239 -0
  62. package/dist/services/monitored-shell-manager.js.map +1 -0
  63. package/dist/services/ollama-service.d.ts +197 -0
  64. package/dist/services/ollama-service.d.ts.map +1 -0
  65. package/dist/services/ollama-service.js +324 -0
  66. package/dist/services/ollama-service.js.map +1 -0
  67. package/dist/services/shell-input-agent.d.ts +89 -0
  68. package/dist/services/shell-input-agent.d.ts.map +1 -0
  69. package/dist/services/shell-input-agent.js +361 -0
  70. package/dist/services/shell-input-agent.js.map +1 -0
  71. package/dist/services/sub-agent-manager.d.ts +139 -0
  72. package/dist/services/sub-agent-manager.d.ts.map +1 -0
  73. package/dist/services/sub-agent-manager.js +517 -0
  74. package/dist/services/sub-agent-manager.js.map +1 -0
  75. package/dist/tools/background-command.d.ts.map +1 -1
  76. package/dist/tools/background-command.js +33 -13
  77. package/dist/tools/background-command.js.map +1 -1
  78. package/dist/tools/command.d.ts.map +1 -1
  79. package/dist/tools/command.js +64 -1
  80. package/dist/tools/command.js.map +1 -1
  81. package/dist/tools/file-ops.d.ts.map +1 -1
  82. package/dist/tools/file-ops.js +33 -19
  83. package/dist/tools/file-ops.js.map +1 -1
  84. package/dist/tools/get-diff.js +1 -1
  85. package/dist/tools/get-diff.js.map +1 -1
  86. package/dist/tools/grep-search.d.ts.map +1 -1
  87. package/dist/tools/grep-search.js +41 -15
  88. package/dist/tools/grep-search.js.map +1 -1
  89. package/dist/tools/plan-mode.js +3 -3
  90. package/dist/tools/plan-mode.js.map +1 -1
  91. package/dist/tools/registry.js +1 -1
  92. package/dist/tools/registry.js.map +1 -1
  93. package/dist/tools/sub-agent.d.ts +9 -0
  94. package/dist/tools/sub-agent.d.ts.map +1 -0
  95. package/dist/tools/sub-agent.js +232 -0
  96. package/dist/tools/sub-agent.js.map +1 -0
  97. package/dist/tools/task-complete.d.ts.map +1 -1
  98. package/dist/tools/task-complete.js +14 -26
  99. package/dist/tools/task-complete.js.map +1 -1
  100. package/dist/ui/components/App.d.ts +45 -2
  101. package/dist/ui/components/App.d.ts.map +1 -1
  102. package/dist/ui/components/App.js +605 -96
  103. package/dist/ui/components/App.js.map +1 -1
  104. package/dist/ui/components/CircularSelectInput.d.ts +24 -0
  105. package/dist/ui/components/CircularSelectInput.d.ts.map +1 -0
  106. package/dist/ui/components/CircularSelectInput.js +71 -0
  107. package/dist/ui/components/CircularSelectInput.js.map +1 -0
  108. package/dist/ui/components/ErrorBoundary.d.ts +3 -2
  109. package/dist/ui/components/ErrorBoundary.d.ts.map +1 -1
  110. package/dist/ui/components/ErrorBoundary.js +29 -1
  111. package/dist/ui/components/ErrorBoundary.js.map +1 -1
  112. package/dist/ui/components/InputBox.d.ts +4 -0
  113. package/dist/ui/components/InputBox.d.ts.map +1 -1
  114. package/dist/ui/components/InputBox.js +343 -21
  115. package/dist/ui/components/InputBox.js.map +1 -1
  116. package/dist/ui/components/InteractiveShell.d.ts +6 -0
  117. package/dist/ui/components/InteractiveShell.d.ts.map +1 -1
  118. package/dist/ui/components/InteractiveShell.js +57 -6
  119. package/dist/ui/components/InteractiveShell.js.map +1 -1
  120. package/dist/ui/components/MCPAddScreen.d.ts +13 -0
  121. package/dist/ui/components/MCPAddScreen.d.ts.map +1 -0
  122. package/dist/ui/components/MCPAddScreen.js +54 -0
  123. package/dist/ui/components/MCPAddScreen.js.map +1 -0
  124. package/dist/ui/components/MCPListScreen.d.ts +17 -0
  125. package/dist/ui/components/MCPListScreen.d.ts.map +1 -0
  126. package/dist/ui/components/MCPListScreen.js +50 -0
  127. package/dist/ui/components/MCPListScreen.js.map +1 -0
  128. package/dist/ui/components/MCPServerListScreen.d.ts +16 -0
  129. package/dist/ui/components/MCPServerListScreen.d.ts.map +1 -0
  130. package/dist/ui/components/MCPServerListScreen.js +59 -0
  131. package/dist/ui/components/MCPServerListScreen.js.map +1 -0
  132. package/dist/ui/components/MonitorModeAIPanel.d.ts +23 -0
  133. package/dist/ui/components/MonitorModeAIPanel.d.ts.map +1 -0
  134. package/dist/ui/components/MonitorModeAIPanel.js +69 -0
  135. package/dist/ui/components/MonitorModeAIPanel.js.map +1 -0
  136. package/dist/ui/components/MultiLineInput.d.ts +13 -0
  137. package/dist/ui/components/MultiLineInput.d.ts.map +1 -0
  138. package/dist/ui/components/MultiLineInput.js +289 -0
  139. package/dist/ui/components/MultiLineInput.js.map +1 -0
  140. package/dist/ui/components/StatusBar.d.ts +2 -0
  141. package/dist/ui/components/StatusBar.d.ts.map +1 -1
  142. package/dist/ui/components/StatusBar.js +33 -2
  143. package/dist/ui/components/StatusBar.js.map +1 -1
  144. package/dist/ui/components/ToolExecutionMessage.d.ts.map +1 -1
  145. package/dist/ui/components/ToolExecutionMessage.js +231 -13
  146. package/dist/ui/components/ToolExecutionMessage.js.map +1 -1
  147. package/dist/ui/components/VersionUpdatePrompt.d.ts.map +1 -1
  148. package/dist/ui/components/VersionUpdatePrompt.js +3 -2
  149. package/dist/ui/components/VersionUpdatePrompt.js.map +1 -1
  150. package/dist/utils/command-history.d.ts +12 -2
  151. package/dist/utils/command-history.d.ts.map +1 -1
  152. package/dist/utils/command-history.js +57 -13
  153. package/dist/utils/command-history.js.map +1 -1
  154. package/dist/utils/input-classifier.js +1 -1
  155. package/dist/utils/input-classifier.js.map +1 -1
  156. package/package.json +2 -1
@@ -0,0 +1,50 @@
1
+ import React from 'react';
2
+ import { Box, Text } from 'ink';
3
+ export const MCPListScreen = ({ servers, onClose }) => {
4
+ // Note: ESC key handling is done in App.tsx
5
+ const getStatusIcon = (server) => {
6
+ if (!server.enabled)
7
+ return '⏸️';
8
+ switch (server.status) {
9
+ case 'connected': return '✓';
10
+ case 'error': return '❌';
11
+ case 'connecting': return '⚠️';
12
+ default: return '⚠️';
13
+ }
14
+ };
15
+ const getStatusText = (server) => {
16
+ if (!server.enabled)
17
+ return 'Disabled';
18
+ switch (server.status) {
19
+ case 'connected': return 'Enabled';
20
+ case 'error': return 'Error';
21
+ case 'connecting': return 'Connecting';
22
+ default: return 'Unknown';
23
+ }
24
+ };
25
+ const renderToolsBox = (tools) => {
26
+ if (tools.length === 0) {
27
+ return (React.createElement(Box, { borderStyle: "round", borderColor: "gray", paddingX: 1, marginTop: 1 },
28
+ React.createElement(Text, { color: "gray" }, "No tools available")));
29
+ }
30
+ // Create a string with all tool names separated by spaces
31
+ const toolNames = tools.map(t => t.name).join(' ');
32
+ return (React.createElement(Box, { borderStyle: "round", borderColor: "gray", paddingX: 1, marginTop: 1, flexWrap: "wrap" },
33
+ React.createElement(Text, { color: "gray" }, toolNames)));
34
+ };
35
+ return (React.createElement(Box, { flexDirection: "column", borderStyle: "round", borderColor: "#00aaff", paddingX: 1 },
36
+ React.createElement(Text, { color: "#00aaff", bold: true }, "MCP Servers and Tools"),
37
+ React.createElement(Text, { dimColor: true }, "View all configured MCP servers and their available tools"),
38
+ React.createElement(Box, { flexDirection: "column", marginTop: 1 }, servers.map((server, index) => (React.createElement(Box, { key: server.name, flexDirection: "column", marginBottom: index < servers.length - 1 ? 1 : 0 },
39
+ React.createElement(Box, null,
40
+ React.createElement(Text, null,
41
+ getStatusIcon(server),
42
+ " ",
43
+ React.createElement(Text, { bold: true }, server.name),
44
+ " - ",
45
+ React.createElement(Text, { color: server.enabled ? 'green' : 'yellow' }, getStatusText(server)))),
46
+ renderToolsBox(server.tools))))),
47
+ React.createElement(Box, { marginTop: 1 },
48
+ React.createElement(Text, { dimColor: true }, "Press ESC to return to chat"))));
49
+ };
50
+ //# sourceMappingURL=MCPListScreen.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"MCPListScreen.js","sourceRoot":"","sources":["../../../src/ui/components/MCPListScreen.tsx"],"names":[],"mappings":"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"}
@@ -0,0 +1,16 @@
1
+ import React from 'react';
2
+ interface MCPServerConfig {
3
+ name: string;
4
+ command: string;
5
+ args?: string[];
6
+ enabled?: boolean;
7
+ }
8
+ interface MCPServerListScreenProps {
9
+ mode: 'remove' | 'enable' | 'disable';
10
+ servers: MCPServerConfig[];
11
+ onSelect: (serverName: string) => void;
12
+ onCancel: () => void;
13
+ }
14
+ export declare const MCPServerListScreen: React.FC<MCPServerListScreenProps>;
15
+ export {};
16
+ //# sourceMappingURL=MCPServerListScreen.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"MCPServerListScreen.d.ts","sourceRoot":"","sources":["../../../src/ui/components/MCPServerListScreen.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,MAAM,OAAO,CAAC;AAI1B,UAAU,eAAe;IACrB,IAAI,EAAE,MAAM,CAAC;IACb,OAAO,EAAE,MAAM,CAAC;IAChB,IAAI,CAAC,EAAE,MAAM,EAAE,CAAC;IAChB,OAAO,CAAC,EAAE,OAAO,CAAC;CACrB;AAED,UAAU,wBAAwB;IAC9B,IAAI,EAAE,QAAQ,GAAG,QAAQ,GAAG,SAAS,CAAC;IACtC,OAAO,EAAE,eAAe,EAAE,CAAC;IAC3B,QAAQ,EAAE,CAAC,UAAU,EAAE,MAAM,KAAK,IAAI,CAAC;IACvC,QAAQ,EAAE,MAAM,IAAI,CAAC;CACxB;AAED,eAAO,MAAM,mBAAmB,EAAE,KAAK,CAAC,EAAE,CAAC,wBAAwB,CA6ElE,CAAC"}
@@ -0,0 +1,59 @@
1
+ import React from 'react';
2
+ import { Box, Text } from 'ink';
3
+ import SelectInput from 'ink-select-input';
4
+ export const MCPServerListScreen = ({ mode, servers, onSelect, onCancel }) => {
5
+ // Note: ESC key handling is done in App.tsx
6
+ const getTitleAndColor = () => {
7
+ switch (mode) {
8
+ case 'remove':
9
+ return { title: 'Remove MCP Server', color: '#ff6666' };
10
+ case 'enable':
11
+ return { title: 'Enable MCP Server', color: '#00cc66' };
12
+ case 'disable':
13
+ return { title: 'Disable MCP Server', color: '#ffaa00' };
14
+ }
15
+ };
16
+ const { title, color } = getTitleAndColor();
17
+ const getDescription = () => {
18
+ switch (mode) {
19
+ case 'remove':
20
+ return 'Select a server to permanently remove from your configuration';
21
+ case 'enable':
22
+ return 'Select a disabled server to enable (AI will be able to use its tools)';
23
+ case 'disable':
24
+ return 'Select an enabled server to disable (AI will not see this server)';
25
+ }
26
+ };
27
+ const items = servers.map((server) => {
28
+ const argsStr = server.args?.join(' ') || '';
29
+ const statusIndicator = server.enabled === false ? '[OFF]' : '[ON]';
30
+ return {
31
+ label: server.name,
32
+ value: server.name,
33
+ command: server.command,
34
+ args: argsStr,
35
+ enabled: server.enabled !== false,
36
+ statusIndicator
37
+ };
38
+ });
39
+ return (React.createElement(Box, { flexDirection: "column", borderStyle: "round", borderColor: color, paddingX: 1 },
40
+ React.createElement(Text, { color: color, bold: true }, title),
41
+ React.createElement(Text, { dimColor: true }, getDescription()),
42
+ React.createElement(Box, { marginTop: 1 },
43
+ React.createElement(SelectInput, { items: items, itemComponent: ({ isSelected, label, command, args, statusIndicator }) => (React.createElement(Box, { flexDirection: "column" },
44
+ React.createElement(Box, null,
45
+ React.createElement(Text, { color: isSelected ? color : 'white', bold: isSelected },
46
+ isSelected ? '> ' : ' ',
47
+ statusIndicator,
48
+ " ",
49
+ label)),
50
+ React.createElement(Box, { paddingLeft: 4 },
51
+ React.createElement(Text, { color: "gray" },
52
+ command,
53
+ args ? ` ${args}` : '')))), onSelect: (item) => {
54
+ onSelect(item.value);
55
+ } })),
56
+ React.createElement(Box, { marginTop: 1 },
57
+ React.createElement(Text, { dimColor: true }, "Press ESC to return to chat"))));
58
+ };
59
+ //# sourceMappingURL=MCPServerListScreen.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"MCPServerListScreen.js","sourceRoot":"","sources":["../../../src/ui/components/MCPServerListScreen.tsx"],"names":[],"mappings":"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"}
@@ -0,0 +1,23 @@
1
+ /**
2
+ * Monitor Mode AI Panel Component
3
+ *
4
+ * Displays AI monitoring messages in the lower half of the screen during
5
+ * agent-controlled shell mode. Shows thinking indicators, tool calls,
6
+ * and text outputs.
7
+ */
8
+ import React from 'react';
9
+ import { MonitorMessage } from '../../services/monitored-shell-manager.js';
10
+ export interface MonitorModeAIPanelProps {
11
+ messages: MonitorMessage[];
12
+ maxHeight: number;
13
+ isActive: boolean;
14
+ }
15
+ /**
16
+ * Monitor Mode AI Panel
17
+ *
18
+ * Displays in the lower half of focus mode when agent control is enabled.
19
+ * Shows only the messages that fit within the available height.
20
+ */
21
+ export declare const MonitorModeAIPanel: React.FC<MonitorModeAIPanelProps>;
22
+ export default MonitorModeAIPanel;
23
+ //# sourceMappingURL=MonitorModeAIPanel.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"MonitorModeAIPanel.d.ts","sourceRoot":"","sources":["../../../src/ui/components/MonitorModeAIPanel.tsx"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH,OAAO,KAAK,MAAM,OAAO,CAAC;AAG1B,OAAO,EAAE,cAAc,EAAE,MAAM,2CAA2C,CAAC;AAE3E,MAAM,WAAW,uBAAuB;IACpC,QAAQ,EAAE,cAAc,EAAE,CAAC;IAC3B,SAAS,EAAE,MAAM,CAAC;IAClB,QAAQ,EAAE,OAAO,CAAC;CACrB;AAoDD;;;;;GAKG;AACH,eAAO,MAAM,kBAAkB,EAAE,KAAK,CAAC,EAAE,CAAC,uBAAuB,CAkDhE,CAAC;AAEF,eAAe,kBAAkB,CAAC"}
@@ -0,0 +1,69 @@
1
+ /**
2
+ * Monitor Mode AI Panel Component
3
+ *
4
+ * Displays AI monitoring messages in the lower half of the screen during
5
+ * agent-controlled shell mode. Shows thinking indicators, tool calls,
6
+ * and text outputs.
7
+ */
8
+ import React from 'react';
9
+ import { Box, Text } from 'ink';
10
+ import Spinner from 'ink-spinner';
11
+ /**
12
+ * Render a single monitoring message
13
+ */
14
+ const MonitorMessageItem = ({ message }) => {
15
+ switch (message.type) {
16
+ case 'thinking':
17
+ // Show tick if answered, spinner if still waiting
18
+ if (message.isAnswered) {
19
+ return (React.createElement(Box, { marginY: 0 },
20
+ React.createElement(Text, { color: "#00cc66" }, "\u2713 "),
21
+ React.createElement(Text, { color: "#00cc66" }, message.content)));
22
+ }
23
+ return (React.createElement(Box, { marginY: 0 },
24
+ React.createElement(Text, { color: "#ffaa00" },
25
+ React.createElement(Spinner, { type: "dots" })),
26
+ React.createElement(Text, { color: "#ffaa00", dimColor: true },
27
+ " ",
28
+ message.content)));
29
+ case 'tool_call':
30
+ return (React.createElement(Box, { marginY: 0 },
31
+ React.createElement(Text, { color: "#00ccff" }, "\u26A1 "),
32
+ React.createElement(Text, { color: "#00ccff" }, message.content)));
33
+ case 'input_sent':
34
+ return (React.createElement(Box, { marginY: 0 },
35
+ React.createElement(Text, { color: "#00cc66" }, "\u2192 "),
36
+ React.createElement(Text, { color: "#00cc66" }, message.content)));
37
+ case 'text':
38
+ default:
39
+ return (React.createElement(Box, { marginY: 0 },
40
+ React.createElement(Text, null, message.content)));
41
+ }
42
+ };
43
+ /**
44
+ * Monitor Mode AI Panel
45
+ *
46
+ * Displays in the lower half of focus mode when agent control is enabled.
47
+ * Shows only the messages that fit within the available height.
48
+ */
49
+ export const MonitorModeAIPanel = ({ messages, maxHeight, isActive }) => {
50
+ if (!isActive) {
51
+ return null;
52
+ }
53
+ // Calculate how many messages to show (estimate 1-2 lines per message)
54
+ // Keep only the most recent messages that fit
55
+ const linesPerMessage = 2;
56
+ const maxMessages = Math.floor(maxHeight / linesPerMessage);
57
+ const visibleMessages = messages.slice(-maxMessages);
58
+ return (React.createElement(Box, { flexDirection: "column", borderStyle: "round", borderColor: "#9945FF", paddingX: 1, height: maxHeight },
59
+ React.createElement(Box, { marginBottom: 1 },
60
+ React.createElement(Text, { color: "#9945FF", bold: true },
61
+ React.createElement(Spinner, { type: "dots" }),
62
+ " Agent Monitor"),
63
+ React.createElement(Text, { color: "#666666", dimColor: true }, " - AI is controlling shell input")),
64
+ React.createElement(Box, { flexDirection: "column", flexGrow: 1 }, visibleMessages.length === 0 ? (React.createElement(Text, { color: "#666666", dimColor: true }, "Monitoring for input prompts...")) : (visibleMessages.map((msg) => (React.createElement(MonitorMessageItem, { key: msg.id, message: msg }))))),
65
+ React.createElement(Box, { marginTop: 1 },
66
+ React.createElement(Text, { color: "#666666", dimColor: true }, "Alt+I to disable agent control"))));
67
+ };
68
+ export default MonitorModeAIPanel;
69
+ //# sourceMappingURL=MonitorModeAIPanel.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"MonitorModeAIPanel.js","sourceRoot":"","sources":["../../../src/ui/components/MonitorModeAIPanel.tsx"],"names":[],"mappings":"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"}
@@ -0,0 +1,13 @@
1
+ import React from 'react';
2
+ interface MultiLineInputProps {
3
+ value?: string;
4
+ onChange: (value: string) => void;
5
+ onSubmit: (value: string) => void;
6
+ placeholder?: string;
7
+ isActive?: boolean;
8
+ minHeight?: number;
9
+ maxHeight?: number;
10
+ }
11
+ export declare const MultiLineInput: React.FC<MultiLineInputProps>;
12
+ export {};
13
+ //# sourceMappingURL=MultiLineInput.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"MultiLineInput.d.ts","sourceRoot":"","sources":["../../../src/ui/components/MultiLineInput.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAsC,MAAM,OAAO,CAAC;AAM3D,UAAU,mBAAmB;IACzB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,QAAQ,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,IAAI,CAAC;IAClC,QAAQ,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,IAAI,CAAC;IAClC,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,SAAS,CAAC,EAAE,MAAM,CAAC;CACtB;AA+CD,eAAO,MAAM,cAAc,EAAE,KAAK,CAAC,EAAE,CAAC,mBAAmB,CAsSxD,CAAC"}
@@ -0,0 +1,289 @@
1
+ import React, { useState, useEffect, useRef } from 'react';
2
+ import { Box, Text, useInput } from 'ink';
3
+ // Helper to determine if a character is a word boundary
4
+ const isWordBoundary = (char) => /[\s\n]/.test(char);
5
+ const getVisualLines = (text, width) => {
6
+ const logicalLines = text.split('\n');
7
+ const visualLines = [];
8
+ let currentOffset = 0;
9
+ logicalLines.forEach((line, i) => {
10
+ if (line.length === 0) {
11
+ visualLines.push({ start: currentOffset, end: currentOffset, isHardEnd: true });
12
+ currentOffset += 1;
13
+ return;
14
+ }
15
+ let remaining = line;
16
+ let lineStartOffset = currentOffset;
17
+ while (remaining.length > 0) {
18
+ let splitIndex = remaining.length;
19
+ let isHardEnd = false;
20
+ if (remaining.length > width) {
21
+ splitIndex = width;
22
+ const lastSpace = remaining.lastIndexOf(' ', width);
23
+ if (lastSpace > 0) {
24
+ splitIndex = lastSpace + 1;
25
+ }
26
+ }
27
+ else {
28
+ isHardEnd = true;
29
+ }
30
+ visualLines.push({
31
+ start: lineStartOffset,
32
+ end: lineStartOffset + splitIndex,
33
+ isHardEnd: isHardEnd
34
+ });
35
+ lineStartOffset += splitIndex;
36
+ remaining = remaining.slice(splitIndex);
37
+ }
38
+ currentOffset += line.length + (i < logicalLines.length - 1 ? 1 : 0);
39
+ });
40
+ return visualLines;
41
+ };
42
+ export const MultiLineInput = ({ value = '', onChange, onSubmit, placeholder = '', isActive = true, minHeight = 3, maxHeight = 10 }) => {
43
+ // Internal cursor state
44
+ const [cursorOffset, setCursorOffset] = useState(0);
45
+ // Refs to prevent stale closures in useInput
46
+ const valueRef = useRef(value);
47
+ const cursorOffsetRef = useRef(cursorOffset);
48
+ // Sync refs with props/state
49
+ useEffect(() => {
50
+ valueRef.current = value;
51
+ }, [value]);
52
+ useEffect(() => {
53
+ cursorOffsetRef.current = cursorOffset;
54
+ }, [cursorOffset]);
55
+ // Ensure cursor stays within bounds if value changes externally
56
+ useEffect(() => {
57
+ if (cursorOffset > value.length) {
58
+ setCursorOffset(value.length);
59
+ }
60
+ }, [value, cursorOffset]);
61
+ useInput((input, key) => {
62
+ if (!isActive)
63
+ return;
64
+ const currentValue = valueRef.current;
65
+ const currentCursorOffset = cursorOffsetRef.current;
66
+ // Handle Backspace
67
+ if (key.backspace || key.delete) {
68
+ if (currentCursorOffset > 0) {
69
+ const newValue = currentValue.slice(0, currentCursorOffset - 1) + currentValue.slice(currentCursorOffset);
70
+ onChange(newValue);
71
+ setCursorOffset(currentCursorOffset - 1);
72
+ }
73
+ return;
74
+ }
75
+ // Handle Return (Submit or Newline)
76
+ if (key.return) {
77
+ // Shift+Enter or just Enter?
78
+ // User requested "same handling as input bar... various enter and newline characters"
79
+ // In InputBox: Enter submits if length <= 1??
80
+ // Wait, for JSON input, we definitely want newlines easily.
81
+ // But usually there is a submit action.
82
+ // Let's make Shift+Enter add newline, and Enter submit?
83
+ // OR checks for validity?
84
+ // The prompt says "[Enter] Validate and Add".
85
+ // If I paste JSON, I might want to edit it.
86
+ // Maybe standard behavior: Enter adds newline, Ctrl+Enter submits?
87
+ // Or matches InputBox: Enter submits.
88
+ // In InputBox, if multiline is needed, Shift+Enter is often used.
89
+ // Let's assume Enter = Submit, unless Shift is pressed?
90
+ // InputBox code: `if (key.return && input.length <= 1 && !key.shift && !key.ctrl)` -> submit.
91
+ // So Shift+Enter is newline.
92
+ if (key.shift) {
93
+ const newValue = currentValue.slice(0, currentCursorOffset) + '\n' + currentValue.slice(currentCursorOffset);
94
+ onChange(newValue);
95
+ setCursorOffset(currentCursorOffset + 1);
96
+ }
97
+ else {
98
+ onSubmit(currentValue);
99
+ }
100
+ return;
101
+ }
102
+ // Handle Arrows
103
+ if (key.upArrow) {
104
+ // Simple up: move back one line roughly?
105
+ // Or use visual lines logic from InputBox for robust navigation
106
+ const width = (process.stdout.columns || 80) - 4; // approximate width correction
107
+ const visualLines = getVisualLines(currentValue, width);
108
+ let currentLineIdx = visualLines.findIndex(line => (currentCursorOffset >= line.start && currentCursorOffset < line.end) ||
109
+ (currentCursorOffset === line.end && line.isHardEnd));
110
+ if (currentLineIdx === -1 && currentCursorOffset === currentValue.length) {
111
+ currentLineIdx = visualLines.length - 1;
112
+ }
113
+ if (currentLineIdx > 0) {
114
+ const currentLine = visualLines[currentLineIdx];
115
+ const targetLine = visualLines[currentLineIdx - 1];
116
+ const offsetInLine = currentCursorOffset - currentLine.start;
117
+ const newOffset = targetLine.start + Math.min(offsetInLine, targetLine.end - targetLine.start);
118
+ setCursorOffset(newOffset);
119
+ }
120
+ else {
121
+ setCursorOffset(0);
122
+ }
123
+ return;
124
+ }
125
+ if (key.downArrow) {
126
+ const width = (process.stdout.columns || 80) - 4;
127
+ const visualLines = getVisualLines(currentValue, width);
128
+ let currentLineIdx = visualLines.findIndex(line => (currentCursorOffset >= line.start && currentCursorOffset < line.end) ||
129
+ (currentCursorOffset === line.end && line.isHardEnd));
130
+ if (currentLineIdx === -1 && currentCursorOffset === currentValue.length) {
131
+ currentLineIdx = visualLines.length - 1;
132
+ }
133
+ if (currentLineIdx < visualLines.length - 1) {
134
+ const currentLine = visualLines[currentLineIdx];
135
+ const targetLine = visualLines[currentLineIdx + 1];
136
+ const offsetInLine = currentCursorOffset - currentLine.start;
137
+ const newOffset = targetLine.start + Math.min(offsetInLine, targetLine.end - targetLine.start);
138
+ setCursorOffset(newOffset);
139
+ }
140
+ else {
141
+ setCursorOffset(currentValue.length);
142
+ }
143
+ return;
144
+ }
145
+ if (key.leftArrow) {
146
+ if (currentCursorOffset > 0) {
147
+ let newOffset = currentCursorOffset;
148
+ if (key.ctrl || key.meta) {
149
+ // Word navigation backwards
150
+ // 1. Skip whitespace backwards
151
+ while (newOffset > 0 && isWordBoundary(currentValue[newOffset - 1])) {
152
+ newOffset--;
153
+ }
154
+ // 2. Skip non-whitespace backwards
155
+ while (newOffset > 0 && !isWordBoundary(currentValue[newOffset - 1])) {
156
+ newOffset--;
157
+ }
158
+ }
159
+ else {
160
+ newOffset--;
161
+ }
162
+ setCursorOffset(newOffset);
163
+ }
164
+ return;
165
+ }
166
+ if (key.rightArrow) {
167
+ if (currentCursorOffset < currentValue.length) {
168
+ let newOffset = currentCursorOffset;
169
+ if (key.ctrl || key.meta) {
170
+ // Word navigation forwards
171
+ // 1. Skip non-whitespace forwards
172
+ while (newOffset < currentValue.length && !isWordBoundary(currentValue[newOffset])) {
173
+ newOffset++;
174
+ }
175
+ // 2. Skip whitespace forwards
176
+ while (newOffset < currentValue.length && isWordBoundary(currentValue[newOffset])) {
177
+ newOffset++;
178
+ }
179
+ }
180
+ else {
181
+ newOffset++;
182
+ }
183
+ setCursorOffset(newOffset);
184
+ }
185
+ return;
186
+ }
187
+ // Home (Start of Line) / End (End of Line)
188
+ // Note: Ink might not strictly type home/end in all versions, but we can check if they exist
189
+ // or check for common ANSI sequences if raw input was available (but useInput gives processed keys)
190
+ // We'll trust key.home/end if available, otherwise rely on OS default behavior which usually sends these keys.
191
+ // @ts-ignore - Ink types might be missing these but they often exist at runtime
192
+ if (key.home) {
193
+ // Find start of current line
194
+ const width = (process.stdout.columns || 80) - 4;
195
+ const visualLines = getVisualLines(currentValue, width);
196
+ const currentLine = visualLines.find(line => (currentCursorOffset >= line.start && currentCursorOffset < line.end) ||
197
+ (currentCursorOffset === line.end && line.isHardEnd));
198
+ if (currentLine) {
199
+ setCursorOffset(currentLine.start);
200
+ }
201
+ else {
202
+ setCursorOffset(0);
203
+ }
204
+ return;
205
+ }
206
+ // @ts-ignore
207
+ if (key.end) {
208
+ // Find end of current line
209
+ const width = (process.stdout.columns || 80) - 4;
210
+ const visualLines = getVisualLines(currentValue, width);
211
+ const currentLine = visualLines.find(line => (currentCursorOffset >= line.start && currentCursorOffset < line.end) ||
212
+ (currentCursorOffset === line.end && line.isHardEnd));
213
+ if (currentLine) {
214
+ setCursorOffset(currentLine.end);
215
+ }
216
+ else {
217
+ setCursorOffset(currentValue.length);
218
+ }
219
+ return;
220
+ }
221
+ // Regular Input (including paste)
222
+ if (input) {
223
+ // Handle paste (newlines are \r\n or \r -> \n)
224
+ const cleanedInput = input.replace(/\r\n/g, '\n').replace(/\r/g, '\n');
225
+ const newValue = currentValue.slice(0, currentCursorOffset) + cleanedInput + currentValue.slice(currentCursorOffset);
226
+ onChange(newValue);
227
+ setCursorOffset(currentCursorOffset + cleanedInput.length);
228
+ }
229
+ });
230
+ // Rendering
231
+ const termWidth = (process.stdout.columns || 80) - 4; // Padding/Border adjustment
232
+ const visualLines = getVisualLines(value, termWidth);
233
+ // Scrolling logic
234
+ // We want to keep cursor visible.
235
+ // Calculate cursor Visual Line
236
+ let cursorVisualLine = 0;
237
+ for (let i = 0; i < visualLines.length; i++) {
238
+ if (cursorOffset >= visualLines[i].start && cursorOffset <= visualLines[i].end) {
239
+ cursorVisualLine = i;
240
+ break;
241
+ }
242
+ }
243
+ if (cursorOffset === value.length && visualLines.length > 0) {
244
+ cursorVisualLine = visualLines.length - 1;
245
+ }
246
+ const totalLines = visualLines.length;
247
+ // Simple scrolling: allow defining min/max height in props
248
+ const height = Math.min(Math.max(totalLines, minHeight), maxHeight);
249
+ let startLine = 0;
250
+ if (totalLines > height) {
251
+ if (cursorVisualLine < height) {
252
+ startLine = 0;
253
+ }
254
+ else {
255
+ startLine = cursorVisualLine - height + 1;
256
+ }
257
+ }
258
+ const endLine = Math.min(startLine + height, totalLines);
259
+ const visibleLines = visualLines.slice(startLine, endLine);
260
+ if (value.length === 0 && placeholder) {
261
+ return React.createElement(Text, { color: "gray" }, placeholder);
262
+ }
263
+ return (React.createElement(Box, { flexDirection: "column" },
264
+ startLine > 0 && React.createElement(Text, { color: "gray" }, "\u2191"),
265
+ visibleLines.map((vLine, idx) => {
266
+ const lineContent = value.slice(vLine.start, vLine.end);
267
+ const isCursorLine = cursorOffset >= vLine.start && cursorOffset <= vLine.end;
268
+ const cursorCol = isCursorLine ? cursorOffset - vLine.start : -1;
269
+ if (!isActive) {
270
+ return React.createElement(Text, { key: idx }, lineContent);
271
+ }
272
+ const chars = lineContent.split('');
273
+ const renderedChars = chars.map((char, charIdx) => {
274
+ if (isCursorLine && charIdx === cursorCol) {
275
+ return React.createElement(Text, { key: charIdx, inverse: true }, char);
276
+ }
277
+ return React.createElement(Text, { key: charIdx }, char);
278
+ });
279
+ if (isCursorLine && cursorCol === lineContent.length) {
280
+ renderedChars.push(React.createElement(Text, { key: "cursor", inverse: true }, " "));
281
+ }
282
+ if (renderedChars.length === 0) {
283
+ return React.createElement(Text, { key: idx }, " ");
284
+ }
285
+ return React.createElement(Text, { key: idx }, renderedChars);
286
+ }),
287
+ endLine < totalLines && React.createElement(Text, { color: "gray" }, "\u2193")));
288
+ };
289
+ //# sourceMappingURL=MultiLineInput.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"MultiLineInput.js","sourceRoot":"","sources":["../../../src/ui/components/MultiLineInput.tsx"],"names":[],"mappings":"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"}
@@ -6,6 +6,8 @@ interface StatusBarProps {
6
6
  loadingMessage?: string;
7
7
  model?: string;
8
8
  subshellContext?: SubshellContext;
9
+ currentTokens?: number;
10
+ maxTokens?: number;
9
11
  }
10
12
  export declare const StatusBar: React.FC<StatusBarProps>;
11
13
  export {};
@@ -1 +1 @@
1
- {"version":3,"file":"StatusBar.d.ts","sourceRoot":"","sources":["../../../src/ui/components/StatusBar.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,MAAM,OAAO,CAAC;AAG1B,OAAO,EAAE,eAAe,EAAE,MAAM,wBAAwB,CAAC;AAEzD,UAAU,cAAc;IACtB,cAAc,EAAE,OAAO,CAAC;IACxB,SAAS,EAAE,OAAO,CAAC;IACnB,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,eAAe,CAAC,EAAE,eAAe,CAAC;CACnC;AAID,eAAO,MAAM,SAAS,EAAE,KAAK,CAAC,EAAE,CAAC,cAAc,CA4F9C,CAAC"}
1
+ {"version":3,"file":"StatusBar.d.ts","sourceRoot":"","sources":["../../../src/ui/components/StatusBar.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,MAAM,OAAO,CAAC;AAG1B,OAAO,EAAE,eAAe,EAAE,MAAM,wBAAwB,CAAC;AAEzD,UAAU,cAAc;IACtB,cAAc,EAAE,OAAO,CAAC;IACxB,SAAS,EAAE,OAAO,CAAC;IACnB,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,eAAe,CAAC,EAAE,eAAe,CAAC;IAClC,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB;AAID,eAAO,MAAM,SAAS,EAAE,KAAK,CAAC,EAAE,CAAC,cAAc,CA+H9C,CAAC"}
@@ -2,8 +2,30 @@ import React from 'react';
2
2
  import { Box, Text } from 'ink';
3
3
  import Spinner from 'ink-spinner';
4
4
  import { useConnectivity } from '../../hooks/useConnectivity.js';
5
- export const StatusBar = ({ autoAcceptMode, isLoading, loadingMessage = 'Processing...', model, subshellContext }) => {
5
+ export const StatusBar = ({ autoAcceptMode, isLoading, loadingMessage = 'Processing...', model, subshellContext, currentTokens, maxTokens }) => {
6
6
  const isConnected = useConnectivity();
7
+ // Calculate token usage percentage
8
+ const tokenUsagePercent = currentTokens && maxTokens && maxTokens > 0
9
+ ? Math.round((currentTokens / maxTokens) * 100)
10
+ : 0;
11
+ // Determine color based on usage
12
+ const getTokenColor = () => {
13
+ if (tokenUsagePercent >= 90)
14
+ return 'red';
15
+ if (tokenUsagePercent >= 75)
16
+ return 'yellow';
17
+ return '#00ccff';
18
+ };
19
+ // Format token count with K/M suffix
20
+ const formatTokenCount = (count) => {
21
+ if (count >= 1000000) {
22
+ return `${(count / 1000000).toFixed(1)}M`;
23
+ }
24
+ if (count >= 1000) {
25
+ return `${(count / 1000).toFixed(1)}K`;
26
+ }
27
+ return count.toString();
28
+ };
7
29
  // Get subshell type prefix with appropriate color
8
30
  const getSubshellPrefix = () => {
9
31
  if (!subshellContext || subshellContext.type === 'local') {
@@ -49,7 +71,16 @@ export const StatusBar = ({ autoAcceptMode, isLoading, loadingMessage = 'Process
49
71
  loadingMessage))),
50
72
  !isLoading && model && (React.createElement(Box, { marginRight: 1 },
51
73
  React.createElement(Text, { color: "#666666" }, "Model: "),
52
- React.createElement(Text, { color: "#00ccff" }, model)))),
74
+ React.createElement(Text, { color: "#00ccff" }, model))),
75
+ currentTokens !== undefined && maxTokens !== undefined && maxTokens > 0 && (React.createElement(Box, { marginRight: 1 },
76
+ React.createElement(Text, { color: "#666666" }, "Context: "),
77
+ React.createElement(Text, { color: getTokenColor() },
78
+ formatTokenCount(currentTokens),
79
+ "/",
80
+ formatTokenCount(maxTokens),
81
+ " (",
82
+ tokenUsagePercent,
83
+ "%)")))),
53
84
  React.createElement(Box, null,
54
85
  !isConnected && (React.createElement(Box, { marginRight: 2 },
55
86
  React.createElement(Text, { color: "red", bold: true }, "No internet connection"))),