codeep 1.2.11 → 1.2.12

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 (88) hide show
  1. package/dist/api/index.js +7 -7
  2. package/dist/config/index.js +3 -3
  3. package/dist/config/providers.d.ts +6 -0
  4. package/dist/config/providers.js +41 -2
  5. package/dist/config/providers.test.js +31 -2
  6. package/dist/hooks/index.js +1 -1
  7. package/dist/hooks/useAgent.js +3 -3
  8. package/dist/renderer/App.js +8 -8
  9. package/dist/renderer/ChatUI.js +3 -3
  10. package/dist/renderer/Screen.js +1 -1
  11. package/dist/renderer/components/Export.js +1 -1
  12. package/dist/renderer/components/Help.js +1 -1
  13. package/dist/renderer/components/Intro.js +1 -1
  14. package/dist/renderer/components/Login.js +3 -3
  15. package/dist/renderer/components/Logout.js +1 -1
  16. package/dist/renderer/components/Modal.js +2 -2
  17. package/dist/renderer/components/Permission.js +2 -2
  18. package/dist/renderer/components/Search.js +1 -1
  19. package/dist/renderer/components/SelectScreen.js +1 -1
  20. package/dist/renderer/components/Settings.js +3 -3
  21. package/dist/renderer/components/Status.js +1 -1
  22. package/dist/renderer/demo-app.js +1 -1
  23. package/dist/renderer/demo.js +1 -1
  24. package/dist/renderer/index.js +9 -9
  25. package/dist/renderer/main.js +31 -31
  26. package/dist/utils/agent.js +10 -10
  27. package/dist/utils/agent.test.js +1 -1
  28. package/dist/utils/codeReview.js +1 -1
  29. package/dist/utils/context.js +1 -1
  30. package/dist/utils/git.test.js +1 -1
  31. package/dist/utils/gitignore.test.js +1 -1
  32. package/dist/utils/keychain.js +1 -1
  33. package/dist/utils/project.test.js +1 -1
  34. package/dist/utils/ratelimit.js +1 -1
  35. package/dist/utils/ratelimit.test.js +1 -1
  36. package/dist/utils/retry.test.js +1 -1
  37. package/dist/utils/smartContext.js +1 -1
  38. package/dist/utils/smartContext.test.js +1 -1
  39. package/dist/utils/taskPlanner.js +2 -2
  40. package/dist/utils/tools.d.ts +64 -4
  41. package/dist/utils/tools.js +212 -7
  42. package/dist/utils/tools.test.js +1 -1
  43. package/dist/utils/validation.test.js +1 -1
  44. package/dist/utils/verify.js +1 -1
  45. package/package.json +1 -1
  46. package/bin/codeep.js +0 -2
  47. package/dist/app.d.ts +0 -2
  48. package/dist/app.js +0 -1501
  49. package/dist/components/AgentActions.d.ts +0 -18
  50. package/dist/components/AgentActions.js +0 -122
  51. package/dist/components/AgentProgress.d.ts +0 -59
  52. package/dist/components/AgentProgress.js +0 -368
  53. package/dist/components/Export.d.ts +0 -8
  54. package/dist/components/Export.js +0 -27
  55. package/dist/components/Help.d.ts +0 -6
  56. package/dist/components/Help.js +0 -7
  57. package/dist/components/Input.d.ts +0 -9
  58. package/dist/components/Input.js +0 -334
  59. package/dist/components/Loading.d.ts +0 -17
  60. package/dist/components/Loading.js +0 -52
  61. package/dist/components/Login.d.ts +0 -7
  62. package/dist/components/Login.js +0 -77
  63. package/dist/components/Logo.d.ts +0 -8
  64. package/dist/components/Logo.js +0 -89
  65. package/dist/components/LogoutPicker.d.ts +0 -8
  66. package/dist/components/LogoutPicker.js +0 -61
  67. package/dist/components/Message.d.ts +0 -10
  68. package/dist/components/Message.js +0 -242
  69. package/dist/components/MessageList.d.ts +0 -10
  70. package/dist/components/MessageList.js +0 -42
  71. package/dist/components/ProjectPermission.d.ts +0 -7
  72. package/dist/components/ProjectPermission.js +0 -65
  73. package/dist/components/Search.d.ts +0 -10
  74. package/dist/components/Search.js +0 -30
  75. package/dist/components/SessionPicker.d.ts +0 -9
  76. package/dist/components/SessionPicker.js +0 -88
  77. package/dist/components/Sessions.d.ts +0 -12
  78. package/dist/components/Sessions.js +0 -119
  79. package/dist/components/Settings.d.ts +0 -9
  80. package/dist/components/Settings.js +0 -198
  81. package/dist/components/Spinner.d.ts +0 -34
  82. package/dist/components/Spinner.js +0 -38
  83. package/dist/components/Status.d.ts +0 -2
  84. package/dist/components/Status.js +0 -13
  85. package/dist/components/StreamingMessage.d.ts +0 -14
  86. package/dist/components/StreamingMessage.js +0 -19
  87. package/dist/index.d.ts +0 -2
  88. package/dist/index.js +0 -42
@@ -1,18 +0,0 @@
1
- /**
2
- * Agent Actions component - displays actions in the chat area
3
- * Removed Static component as it renders at top of terminal
4
- */
5
- import React from 'react';
6
- import { ActionLog } from '../utils/tools';
7
- interface AgentActionsProps {
8
- actions: ActionLog[];
9
- isRunning: boolean;
10
- currentStep: number;
11
- dryRun?: boolean;
12
- }
13
- /**
14
- * Agent Actions display - renders in chat area
15
- * Shows only the last few actions to prevent too much jumping
16
- */
17
- export declare const AgentActions: React.FC<AgentActionsProps>;
18
- export {};
@@ -1,122 +0,0 @@
1
- import { jsxs as _jsxs, jsx as _jsx, Fragment as _Fragment } from "react/jsx-runtime";
2
- /**
3
- * Agent Actions component - displays actions in the chat area
4
- * Removed Static component as it renders at top of terminal
5
- */
6
- import { useState, useEffect, memo } from 'react';
7
- import { Box, Text } from 'ink';
8
- // Spinner frames
9
- const SPINNER_FRAMES = ['/', '-', '\\', '|'];
10
- /**
11
- * Isolated spinner - doesn't cause parent re-renders
12
- */
13
- const Spinner = memo(({ color = '#f02a30' }) => {
14
- const [frame, setFrame] = useState(0);
15
- useEffect(() => {
16
- const timer = setInterval(() => {
17
- setFrame(f => (f + 1) % SPINNER_FRAMES.length);
18
- }, 100);
19
- return () => clearInterval(timer);
20
- }, []);
21
- return _jsxs(Text, { color: color, children: ["[", SPINNER_FRAMES[frame], "]"] });
22
- });
23
- Spinner.displayName = 'Spinner';
24
- /**
25
- * Format action for display
26
- */
27
- function formatAction(action) {
28
- const filename = action.target.split('/').pop() || action.target;
29
- const lineCount = action.details ? action.details.split('\n').length : 0;
30
- const lineInfo = lineCount > 0 ? ` (${lineCount} lines)` : '';
31
- switch (action.type) {
32
- case 'write':
33
- return {
34
- icon: action.result === 'success' ? '✓' : '✗',
35
- color: action.result === 'success' ? 'green' : 'red',
36
- text: `Created ${filename}${lineInfo}`,
37
- };
38
- case 'edit':
39
- return {
40
- icon: action.result === 'success' ? '✓' : '✗',
41
- color: action.result === 'success' ? 'yellow' : 'red',
42
- text: `Edited ${filename}${lineInfo}`,
43
- };
44
- case 'read':
45
- return {
46
- icon: '→',
47
- color: 'blue',
48
- text: `Reading ${filename}`,
49
- };
50
- case 'delete':
51
- return {
52
- icon: action.result === 'success' ? '✓' : '✗',
53
- color: 'red',
54
- text: `Deleted ${filename}`,
55
- };
56
- case 'command':
57
- const cmd = action.target.length > 30 ? action.target.slice(0, 30) + '...' : action.target;
58
- return {
59
- icon: action.result === 'success' ? '✓' : '✗',
60
- color: action.result === 'success' ? 'magenta' : 'red',
61
- text: `Ran \`${cmd}\``,
62
- };
63
- case 'search':
64
- return {
65
- icon: '→',
66
- color: 'cyan',
67
- text: `Searching ${filename}`,
68
- };
69
- case 'mkdir':
70
- return {
71
- icon: action.result === 'success' ? '✓' : '✗',
72
- color: 'blue',
73
- text: `Created dir ${filename}`,
74
- };
75
- case 'fetch':
76
- return {
77
- icon: '→',
78
- color: 'cyan',
79
- text: `Fetching ${filename}`,
80
- };
81
- case 'list':
82
- return {
83
- icon: '→',
84
- color: 'gray',
85
- text: `Listing ${filename}`,
86
- };
87
- default:
88
- return {
89
- icon: '◦',
90
- color: 'white',
91
- text: `${action.type}: ${filename}`,
92
- };
93
- }
94
- }
95
- /**
96
- * Single action line component
97
- */
98
- const ActionLine = memo(({ action }) => {
99
- const { icon, color, text } = formatAction(action);
100
- return (_jsxs(Text, { children: [_jsx(Text, { color: color, children: icon }), _jsxs(Text, { children: [" ", text] })] }));
101
- });
102
- ActionLine.displayName = 'ActionLine';
103
- /**
104
- * Agent Actions display - renders in chat area
105
- * Shows only the last few actions to prevent too much jumping
106
- */
107
- export const AgentActions = memo(({ actions, isRunning, currentStep, dryRun, }) => {
108
- const color = dryRun ? 'yellow' : '#f02a30';
109
- const label = dryRun ? 'DRY RUN' : 'AGENT';
110
- // Only show last 5 completed actions to minimize re-render area
111
- const MAX_VISIBLE_ACTIONS = 5;
112
- const completedActions = actions.filter(a => a.result === 'success' || a.result === 'error');
113
- const visibleActions = completedActions.slice(-MAX_VISIBLE_ACTIONS);
114
- const hiddenCount = completedActions.length - visibleActions.length;
115
- // Current action (last one if result is pending or the running state)
116
- const currentAction = actions.length > 0 ? actions[actions.length - 1] : null;
117
- if (!isRunning && actions.length === 0) {
118
- return null;
119
- }
120
- return (_jsxs(Box, { flexDirection: "column", marginY: 1, children: [hiddenCount > 0 && (_jsxs(Text, { color: "gray", children: ["... ", hiddenCount, " earlier action(s) ..."] })), visibleActions.map((action, i) => (_jsx(ActionLine, { action: action }, `action-${hiddenCount + i}-${action.timestamp}`))), isRunning && (_jsxs(Box, { children: [_jsx(Spinner, { color: color }), _jsxs(Text, { color: color, bold: true, children: [" ", label, " "] }), _jsxs(Text, { color: "cyan", children: ["Step ", currentStep] }), currentAction && (_jsxs(_Fragment, { children: [_jsx(Text, { color: "gray", children: " | " }), _jsx(Text, { children: formatAction(currentAction).text })] }))] }))] }));
121
- });
122
- AgentActions.displayName = 'AgentActions';
@@ -1,59 +0,0 @@
1
- /**
2
- * Agent progress display component
3
- * Optimized with isolated spinner animation and memoization
4
- */
5
- import React from 'react';
6
- import { ActionLog } from '../utils/tools';
7
- interface AgentProgressProps {
8
- isRunning: boolean;
9
- iteration: number;
10
- maxIterations: number;
11
- actions: ActionLog[];
12
- currentThinking?: string;
13
- dryRun?: boolean;
14
- }
15
- export declare const AgentProgress: React.FC<AgentProgressProps>;
16
- /**
17
- * Live Statistics component - shows real-time agent progress
18
- *
19
- * KEY DESIGN: Always renders exactly FIXED_HEIGHT lines to prevent terminal jumping
20
- * - While running: shows current action + live statistics
21
- * - When finished: shows final summary (same height)
22
- * - NEVER returns null - always renders the same box structure
23
- */
24
- interface LiveCodeStreamProps {
25
- actions: ActionLog[];
26
- isRunning: boolean;
27
- terminalWidth?: number;
28
- }
29
- export declare const LiveCodeStream: React.FC<LiveCodeStreamProps>;
30
- /**
31
- * Agent summary component - shown when agent completes
32
- */
33
- interface AgentSummaryProps {
34
- success: boolean;
35
- iterations: number;
36
- actions: ActionLog[];
37
- error?: string;
38
- aborted?: boolean;
39
- }
40
- export declare const AgentSummary: React.FC<AgentSummaryProps>;
41
- /**
42
- * Changes list component - for /changes command
43
- */
44
- interface ChangesListProps {
45
- actions: ActionLog[];
46
- }
47
- export declare const ChangesList: React.FC<ChangesListProps>;
48
- /**
49
- * Agent Status Bar - fixed height, with spinner animation
50
- * Shows above input, doesn't cause chat jumping
51
- */
52
- interface AgentStatusBarProps {
53
- iteration: number;
54
- actionsCount: number;
55
- dryRun?: boolean;
56
- currentAction?: string;
57
- }
58
- export declare const AgentStatusBar: React.FC<AgentStatusBarProps>;
59
- export {};
@@ -1,368 +0,0 @@
1
- import { jsxs as _jsxs, jsx as _jsx, Fragment as _Fragment } from "react/jsx-runtime";
2
- /**
3
- * Agent progress display component
4
- * Optimized with isolated spinner animation and memoization
5
- */
6
- import { useState, useEffect, memo, useMemo } from 'react';
7
- import { Box, Text } from 'ink';
8
- // Spinner frames for animation (no emojis)
9
- const SPINNER_FRAMES = ['/', '-', '\\', '|'];
10
- /**
11
- * Isolated spinner component - animation doesn't cause parent re-renders
12
- */
13
- const AgentSpinner = memo(({ color = '#f02a30' }) => {
14
- const [frame, setFrame] = useState(0);
15
- useEffect(() => {
16
- const timer = setInterval(() => {
17
- setFrame(f => (f + 1) % SPINNER_FRAMES.length);
18
- }, 150);
19
- return () => clearInterval(timer);
20
- }, []);
21
- return _jsxs(Text, { color: color, children: ["[", SPINNER_FRAMES[frame], "]"] });
22
- });
23
- AgentSpinner.displayName = 'AgentSpinner';
24
- export const AgentProgress = memo(({ isRunning, iteration, maxIterations, actions, currentThinking, dryRun, }) => {
25
- // Don't show anything if not running and no actions
26
- if (!isRunning && actions.length === 0) {
27
- return null;
28
- }
29
- // Show last 5 actions (more compact)
30
- const recentActions = actions.slice(-5);
31
- // Get current/last action for prominent display
32
- const currentAction = actions.length > 0 ? actions[actions.length - 1] : null;
33
- // Count actions by type
34
- const actionCounts = {
35
- reads: actions.filter(a => a.type === 'read').length,
36
- writes: actions.filter(a => a.type === 'write').length,
37
- edits: actions.filter(a => a.type === 'edit').length,
38
- commands: actions.filter(a => a.type === 'command').length,
39
- searches: actions.filter(a => a.type === 'search').length,
40
- };
41
- // Count file changes
42
- const fileChanges = {
43
- created: actions.filter(a => a.type === 'write' && a.result === 'success').length,
44
- modified: actions.filter(a => a.type === 'edit' && a.result === 'success').length,
45
- deleted: actions.filter(a => a.type === 'delete' && a.result === 'success').length,
46
- };
47
- const totalFileChanges = fileChanges.created + fileChanges.modified + fileChanges.deleted;
48
- return (_jsxs(Box, { flexDirection: "column", borderStyle: "round", borderColor: dryRun ? 'yellow' : '#f02a30', paddingX: 1, marginY: 1, children: [_jsx(Box, { children: isRunning ? (_jsxs(_Fragment, { children: [_jsx(AgentSpinner, { color: dryRun ? 'yellow' : '#f02a30' }), _jsxs(Text, { color: dryRun ? 'yellow' : '#f02a30', bold: true, children: [' ', dryRun ? 'DRY RUN' : 'AGENT', ' '] }), _jsx(Text, { color: "cyan", children: "|" }), _jsxs(Text, { color: "cyan", children: [" step ", iteration] }), _jsx(Text, { color: "cyan", children: " | " }), actionCounts.reads > 0 && _jsxs(Text, { color: "blue", children: [actionCounts.reads, "R "] }), actionCounts.writes > 0 && _jsxs(Text, { color: "green", children: [actionCounts.writes, "W "] }), actionCounts.edits > 0 && _jsxs(Text, { color: "yellow", children: [actionCounts.edits, "E "] }), actionCounts.commands > 0 && _jsxs(Text, { color: "magenta", children: [actionCounts.commands, "C "] }), actionCounts.searches > 0 && _jsxs(Text, { color: "cyan", children: [actionCounts.searches, "S "] }), actions.length === 0 && _jsx(Text, { color: "cyan", children: "0 actions" })] })) : (_jsxs(_Fragment, { children: [_jsx(Text, { color: "green", bold: true, children: "[DONE] " }), _jsx(Text, { children: "Agent completed" }), _jsx(Text, { color: "cyan", children: " | " }), _jsxs(Text, { color: "white", children: [actions.length, " actions"] })] })) }), isRunning && currentAction && (_jsxs(Box, { marginTop: 1, children: [_jsx(Text, { color: "white", bold: true, children: "Now: " }), _jsxs(Text, { color: getActionColor(currentAction.type), children: [getActionLabel(currentAction.type), " "] }), _jsx(Text, { color: "white", children: formatTarget(currentAction.target) })] })), _jsx(Text, { color: "cyan", children: '─'.repeat(50) }), recentActions.length > 1 && (_jsxs(Box, { flexDirection: "column", children: [_jsx(Text, { color: "cyan", dimColor: true, children: "Recent:" }), recentActions.slice(0, -1).map((action, i) => (_jsx(ActionItem, { action: action }, i)))] })), isRunning && totalFileChanges > 0 && (_jsxs(Box, { marginTop: 1, children: [_jsx(Text, { color: "cyan", children: "Changes: " }), fileChanges.created > 0 && _jsxs(Text, { color: "green", children: ["+", fileChanges.created, " "] }), fileChanges.modified > 0 && _jsxs(Text, { color: "yellow", children: ["~", fileChanges.modified, " "] }), fileChanges.deleted > 0 && _jsxs(Text, { color: "red", children: ["-", fileChanges.deleted] })] })), isRunning && currentThinking && (_jsx(Box, { marginTop: 1, children: _jsxs(Text, { color: "cyan", wrap: "truncate-end", children: ["> ", currentThinking.slice(0, 80), currentThinking.length > 80 ? '...' : ''] }) })), isRunning && (_jsxs(Box, { marginTop: 1, children: [_jsx(Text, { color: "cyan", children: "Press " }), _jsx(Text, { color: "#f02a30", children: "Esc" }), _jsx(Text, { color: "cyan", children: " to stop" })] })), !isRunning && totalFileChanges > 0 && (_jsxs(Box, { flexDirection: "column", marginTop: 1, children: [_jsx(Text, { bold: true, children: "File Changes:" }), fileChanges.created > 0 && (_jsxs(Text, { color: "green", children: [" + ", fileChanges.created, " file(s) created"] })), fileChanges.modified > 0 && (_jsxs(Text, { color: "yellow", children: [" ~ ", fileChanges.modified, " file(s) modified"] })), fileChanges.deleted > 0 && (_jsxs(Text, { color: "red", children: [" - ", fileChanges.deleted, " file(s) deleted"] }))] }))] }));
49
- });
50
- AgentProgress.displayName = 'AgentProgress';
51
- // Get file extension for language detection
52
- const getFileExtension = (filename) => {
53
- const parts = filename.split('.');
54
- return parts.length > 1 ? parts[parts.length - 1].toLowerCase() : '';
55
- };
56
- // Get language label from extension
57
- const getLanguageLabel = (ext) => {
58
- const langMap = {
59
- 'js': 'JavaScript',
60
- 'jsx': 'React JSX',
61
- 'ts': 'TypeScript',
62
- 'tsx': 'React TSX',
63
- 'html': 'HTML',
64
- 'css': 'CSS',
65
- 'scss': 'SCSS',
66
- 'json': 'JSON',
67
- 'md': 'Markdown',
68
- 'py': 'Python',
69
- 'rb': 'Ruby',
70
- 'go': 'Go',
71
- 'rs': 'Rust',
72
- 'java': 'Java',
73
- 'kt': 'Kotlin',
74
- 'swift': 'Swift',
75
- 'php': 'PHP',
76
- 'sql': 'SQL',
77
- 'sh': 'Shell',
78
- 'bash': 'Bash',
79
- 'yml': 'YAML',
80
- 'yaml': 'YAML',
81
- 'xml': 'XML',
82
- 'vue': 'Vue',
83
- 'svelte': 'Svelte',
84
- };
85
- return langMap[ext] || ext.toUpperCase();
86
- };
87
- // Enhanced syntax highlighting with more colors
88
- const getCodeColor = (line, ext) => {
89
- const trimmed = line.trim();
90
- // Empty lines
91
- if (!trimmed)
92
- return 'gray';
93
- // Comments - multiple styles
94
- if (trimmed.startsWith('//') || trimmed.startsWith('#') || trimmed.startsWith('/*') ||
95
- trimmed.startsWith('*') || trimmed.startsWith('<!--') || trimmed.startsWith('"""') ||
96
- trimmed.startsWith("'''")) {
97
- return 'gray';
98
- }
99
- // Import/export statements
100
- if (/^(import|export|from|require)\b/.test(trimmed)) {
101
- return 'magenta';
102
- }
103
- // Function/class definitions
104
- if (/^(function|class|interface|type|enum|const\s+\w+\s*=\s*(\(|async)|def |class |fn |func |pub fn)\b/.test(trimmed)) {
105
- return 'yellow';
106
- }
107
- // Control flow keywords
108
- if (/^(if|else|for|while|switch|case|try|catch|finally|return|throw|break|continue|async|await)\b/.test(trimmed)) {
109
- return 'blue';
110
- }
111
- // Variable declarations
112
- if (/^(const|let|var|val|mut)\b/.test(trimmed)) {
113
- return 'cyan';
114
- }
115
- // HTML/JSX tags
116
- if ((ext === 'html' || ext === 'jsx' || ext === 'tsx' || ext === 'vue' || ext === 'svelte') &&
117
- (trimmed.startsWith('<') || trimmed.startsWith('</'))) {
118
- return 'cyan';
119
- }
120
- // CSS selectors and properties
121
- if ((ext === 'css' || ext === 'scss') && (trimmed.includes('{') || trimmed.includes(':'))) {
122
- return 'green';
123
- }
124
- // JSON keys
125
- if (ext === 'json' && trimmed.includes(':')) {
126
- return 'cyan';
127
- }
128
- // Strings (but not the whole line)
129
- if (/["'`]/.test(trimmed)) {
130
- return 'green';
131
- }
132
- return 'white';
133
- };
134
- // Check if line is a section separator (empty or comment-only)
135
- const isSectionBreak = (line, prevLine) => {
136
- const trimmed = line.trim();
137
- const prevTrimmed = prevLine?.trim() || '';
138
- // Empty line after non-empty line
139
- if (!trimmed && prevTrimmed)
140
- return true;
141
- // Comment after code
142
- if ((trimmed.startsWith('//') || trimmed.startsWith('#') || trimmed.startsWith('/*')) &&
143
- prevTrimmed && !prevTrimmed.startsWith('//') && !prevTrimmed.startsWith('#')) {
144
- return true;
145
- }
146
- return false;
147
- };
148
- const FIXED_HEIGHT = 6; // Fixed number of content lines (excluding border)
149
- export const LiveCodeStream = memo(({ actions, isRunning, terminalWidth = 80 }) => {
150
- const currentAction = actions.length > 0 ? actions[actions.length - 1] : null;
151
- // Calculate statistics from all actions
152
- const stats = useMemo(() => {
153
- const filesCreated = actions.filter(a => a.type === 'write' && a.result === 'success');
154
- const filesEdited = actions.filter(a => a.type === 'edit' && a.result === 'success');
155
- const filesDeleted = actions.filter(a => a.type === 'delete' && a.result === 'success');
156
- const filesRead = actions.filter(a => a.type === 'read');
157
- const commands = actions.filter(a => a.type === 'command');
158
- const searches = actions.filter(a => a.type === 'search');
159
- const errors = actions.filter(a => a.result === 'error');
160
- // Calculate total lines written
161
- let totalLinesWritten = 0;
162
- for (const action of [...filesCreated, ...filesEdited]) {
163
- if (action.details) {
164
- totalLinesWritten += action.details.split('\n').length;
165
- }
166
- }
167
- return {
168
- filesCreated: filesCreated.length,
169
- filesEdited: filesEdited.length,
170
- filesDeleted: filesDeleted.length,
171
- filesRead: filesRead.length,
172
- commands: commands.length,
173
- searches: searches.length,
174
- errors: errors.length,
175
- totalLinesWritten,
176
- totalActions: actions.length,
177
- };
178
- }, [actions]);
179
- const boxWidth = Math.min(terminalWidth - 4, 60);
180
- // Build content lines array - always exactly FIXED_HEIGHT lines
181
- const contentLines = [];
182
- if (isRunning) {
183
- // Line 1: Current action
184
- if (currentAction) {
185
- contentLines.push(_jsxs(Box, { children: [_jsxs(Text, { color: getActionColor(currentAction.type), bold: true, children: [getActionLabel(currentAction.type), " "] }), _jsx(Text, { color: "white", children: formatTarget(currentAction.target, boxWidth - 15) })] }, "current"));
186
- }
187
- else {
188
- contentLines.push(_jsx(Text, { color: "gray", children: "Starting..." }, "current"));
189
- }
190
- // Line 2: Separator
191
- contentLines.push(_jsx(Text, { color: "gray", dimColor: true, children: '─'.repeat(boxWidth - 4) }, "sep"));
192
- // Line 3: File changes stats
193
- const changesParts = [];
194
- if (stats.filesCreated > 0)
195
- changesParts.push(`+${stats.filesCreated} created`);
196
- if (stats.filesEdited > 0)
197
- changesParts.push(`~${stats.filesEdited} edited`);
198
- if (stats.filesDeleted > 0)
199
- changesParts.push(`-${stats.filesDeleted} deleted`);
200
- if (changesParts.length > 0) {
201
- contentLines.push(_jsxs(Box, { children: [_jsx(Text, { color: "cyan", children: "Files: " }), _jsx(Text, { color: "green", children: changesParts.join(' ') })] }, "changes"));
202
- }
203
- else {
204
- contentLines.push(_jsx(Text, { color: "gray", dimColor: true, children: "Files: no changes yet" }, "changes"));
205
- }
206
- // Line 4: Other stats
207
- const otherParts = [];
208
- if (stats.filesRead > 0)
209
- otherParts.push(`${stats.filesRead}R`);
210
- if (stats.commands > 0)
211
- otherParts.push(`${stats.commands}C`);
212
- if (stats.searches > 0)
213
- otherParts.push(`${stats.searches}S`);
214
- if (stats.totalLinesWritten > 0)
215
- otherParts.push(`${stats.totalLinesWritten}L`);
216
- contentLines.push(_jsxs(Box, { children: [_jsx(Text, { color: "cyan", children: "Stats: " }), _jsx(Text, { color: "gray", children: otherParts.length > 0 ? otherParts.join(' | ') : 'gathering...' })] }, "other"));
217
- // Line 5: Errors if any
218
- if (stats.errors > 0) {
219
- contentLines.push(_jsxs(Text, { color: "red", children: [stats.errors, " error(s)"] }, "errors"));
220
- }
221
- else {
222
- contentLines.push(_jsx(Text, { color: "gray", dimColor: true, children: " " }, "errors"));
223
- }
224
- // Line 6: Help text
225
- contentLines.push(_jsx(Text, { color: "gray", dimColor: true, children: "Press Esc to stop" }, "help"));
226
- }
227
- else {
228
- // FINISHED STATE
229
- // Line 1: Complete header
230
- contentLines.push(_jsxs(Text, { color: stats.errors > 0 ? 'red' : 'green', bold: true, children: [stats.errors > 0 ? 'Completed with errors' : 'Completed', " (", stats.totalActions, " actions)"] }, "header"));
231
- // Line 2: Separator
232
- contentLines.push(_jsx(Text, { color: "gray", dimColor: true, children: '─'.repeat(boxWidth - 4) }, "sep"));
233
- // Line 3: File changes
234
- const changesParts = [];
235
- if (stats.filesCreated > 0)
236
- changesParts.push(`+${stats.filesCreated} created`);
237
- if (stats.filesEdited > 0)
238
- changesParts.push(`~${stats.filesEdited} edited`);
239
- if (stats.filesDeleted > 0)
240
- changesParts.push(`-${stats.filesDeleted} deleted`);
241
- if (changesParts.length > 0) {
242
- contentLines.push(_jsxs(Box, { children: [_jsx(Text, { color: "cyan", children: "Files: " }), _jsx(Text, { color: "green", children: changesParts.join(' ') })] }, "changes"));
243
- }
244
- else {
245
- contentLines.push(_jsx(Text, { color: "gray", children: "Files: no changes made" }, "changes"));
246
- }
247
- // Line 4: Lines written
248
- if (stats.totalLinesWritten > 0) {
249
- contentLines.push(_jsxs(Box, { children: [_jsx(Text, { color: "cyan", children: "Lines: " }), _jsxs(Text, { color: "white", children: [stats.totalLinesWritten, " written"] })] }, "lines"));
250
- }
251
- else {
252
- contentLines.push(_jsx(Text, { color: "gray", dimColor: true, children: " " }, "lines"));
253
- }
254
- // Line 5: Other stats
255
- const otherParts = [];
256
- if (stats.filesRead > 0)
257
- otherParts.push(`${stats.filesRead} read`);
258
- if (stats.commands > 0)
259
- otherParts.push(`${stats.commands} commands`);
260
- if (stats.searches > 0)
261
- otherParts.push(`${stats.searches} searches`);
262
- if (otherParts.length > 0) {
263
- contentLines.push(_jsxs(Text, { color: "gray", dimColor: true, children: ["Also: ", otherParts.join(', ')] }, "other"));
264
- }
265
- else {
266
- contentLines.push(_jsx(Text, { color: "gray", dimColor: true, children: " " }, "other"));
267
- }
268
- // Line 6: Errors
269
- if (stats.errors > 0) {
270
- contentLines.push(_jsxs(Text, { color: "red", children: [stats.errors, " error(s) occurred"] }, "errors"));
271
- }
272
- else {
273
- contentLines.push(_jsx(Text, { color: "gray", dimColor: true, children: " " }, "errors"));
274
- }
275
- }
276
- // Pad to fixed height if needed
277
- while (contentLines.length < FIXED_HEIGHT) {
278
- contentLines.push(_jsx(Text, { color: "gray", dimColor: true, children: " " }, `pad-${contentLines.length}`));
279
- }
280
- return (_jsx(Box, { flexDirection: "column", borderStyle: "round", borderColor: isRunning ? 'cyan' : (stats.errors > 0 ? 'red' : 'green'), paddingX: 1, marginBottom: 1, width: boxWidth, children: contentLines }));
281
- });
282
- LiveCodeStream.displayName = 'LiveCodeStream';
283
- // Helper functions for action display
284
- const getActionColor = (type) => {
285
- switch (type) {
286
- case 'read': return 'blue';
287
- case 'write': return 'green';
288
- case 'edit': return 'yellow';
289
- case 'delete': return 'red';
290
- case 'command': return 'magenta';
291
- case 'search': return 'cyan';
292
- case 'list': return 'white';
293
- case 'mkdir': return 'blue';
294
- case 'fetch': return 'cyan';
295
- default: return 'white';
296
- }
297
- };
298
- const getActionLabel = (type) => {
299
- switch (type) {
300
- case 'read': return 'Reading';
301
- case 'write': return 'Creating';
302
- case 'edit': return 'Editing';
303
- case 'delete': return 'Deleting';
304
- case 'command': return 'Running';
305
- case 'search': return 'Searching';
306
- case 'list': return 'Listing';
307
- case 'mkdir': return 'Creating dir';
308
- case 'fetch': return 'Fetching';
309
- default: return type.toUpperCase();
310
- }
311
- };
312
- const formatTarget = (target, maxLen = 50) => {
313
- // For file paths, show just the filename or last part
314
- if (target.includes('/')) {
315
- const parts = target.split('/');
316
- const filename = parts[parts.length - 1];
317
- if (parts.length > 2) {
318
- const short = `.../${parts[parts.length - 2]}/${filename}`;
319
- return short.length > maxLen ? '...' + short.slice(-(maxLen - 3)) : short;
320
- }
321
- return target.length > maxLen ? '...' + target.slice(-(maxLen - 3)) : target;
322
- }
323
- return target.length > maxLen ? target.slice(0, maxLen - 3) + '...' : target;
324
- };
325
- /**
326
- * Single action item display
327
- */
328
- const ActionItem = ({ action }) => {
329
- const getStatusIndicator = () => {
330
- switch (action.result) {
331
- case 'success':
332
- return _jsx(Text, { color: "green", children: "\u2713" });
333
- case 'error':
334
- return _jsx(Text, { color: "red", children: "\u2717" });
335
- default:
336
- return _jsx(Text, { color: "yellow", children: "\u00B7" });
337
- }
338
- };
339
- return (_jsxs(Text, { children: [getStatusIndicator(), ' ', _jsx(Text, { color: getActionColor(action.type), children: getActionLabel(action.type).padEnd(10) }), ' ', _jsx(Text, { color: "cyan", children: formatTarget(action.target) })] }));
340
- };
341
- export const AgentSummary = memo(({ success, iterations, actions, error, aborted, }) => {
342
- const filesWritten = actions.filter(a => a.type === 'write' && a.result === 'success');
343
- const filesEdited = actions.filter(a => a.type === 'edit' && a.result === 'success');
344
- const filesDeleted = actions.filter(a => a.type === 'delete' && a.result === 'success');
345
- const dirsCreated = actions.filter(a => a.type === 'mkdir' && a.result === 'success');
346
- const commandsRun = actions.filter(a => a.type === 'command' && a.result === 'success');
347
- const errors = actions.filter(a => a.result === 'error');
348
- const hasFileChanges = filesWritten.length > 0 || filesEdited.length > 0 ||
349
- filesDeleted.length > 0 || dirsCreated.length > 0;
350
- return (_jsxs(Box, { flexDirection: "column", borderStyle: "round", borderColor: success ? 'green' : aborted ? 'yellow' : 'red', padding: 1, marginY: 1, children: [_jsxs(Box, { children: [success ? (_jsx(Text, { color: "green", bold: true, children: "[OK] Agent completed" })) : aborted ? (_jsx(Text, { color: "yellow", bold: true, children: "[--] Agent stopped" })) : (_jsx(Text, { color: "red", bold: true, children: "[!!] Agent failed" })), _jsxs(Text, { color: "cyan", children: [" | ", iterations, " iterations | ", actions.length, " actions"] })] }), error && (_jsxs(Text, { color: "red", children: ["Error: ", error] })), hasFileChanges && (_jsxs(_Fragment, { children: [_jsx(Text, { color: "cyan", children: '─'.repeat(40) }), _jsx(Text, { bold: true, children: "Changes:" }), filesWritten.length > 0 && (_jsxs(Box, { flexDirection: "column", children: [_jsxs(Text, { color: "green", children: ["+ Created (", filesWritten.length, "):"] }), filesWritten.map((f, i) => (_jsxs(Text, { color: "green", children: [" ", f.target] }, i)))] })), filesEdited.length > 0 && (_jsxs(Box, { flexDirection: "column", children: [_jsxs(Text, { color: "yellow", children: ["~ Modified (", filesEdited.length, "):"] }), filesEdited.map((f, i) => (_jsxs(Text, { color: "yellow", children: [" ", f.target] }, i)))] })), filesDeleted.length > 0 && (_jsxs(Box, { flexDirection: "column", children: [_jsxs(Text, { color: "red", children: ["- Deleted (", filesDeleted.length, "):"] }), filesDeleted.map((f, i) => (_jsxs(Text, { color: "red", children: [" ", f.target] }, i)))] })), dirsCreated.length > 0 && (_jsxs(Text, { color: "blue", children: ["+ ", dirsCreated.length, " director(ies) created"] }))] })), commandsRun.length > 0 && (_jsxs(Text, { color: "magenta", children: [commandsRun.length, " command(s) executed"] })), errors.length > 0 && (_jsxs(Text, { color: "red", children: [errors.length, " error(s) occurred"] }))] }));
351
- });
352
- AgentSummary.displayName = 'AgentSummary';
353
- export const ChangesList = ({ actions }) => {
354
- const writes = actions.filter(a => a.type === 'write' && a.result === 'success');
355
- const edits = actions.filter(a => a.type === 'edit' && a.result === 'success');
356
- const deletes = actions.filter(a => a.type === 'delete' && a.result === 'success');
357
- const mkdirs = actions.filter(a => a.type === 'mkdir' && a.result === 'success');
358
- const totalChanges = writes.length + edits.length + deletes.length + mkdirs.length;
359
- if (totalChanges === 0) {
360
- return (_jsx(Box, { children: _jsx(Text, { color: "cyan", children: "No file changes in current session" }) }));
361
- }
362
- return (_jsxs(Box, { flexDirection: "column", borderStyle: "round", borderColor: "cyan", padding: 1, children: [_jsxs(Text, { color: "cyan", bold: true, children: ["Session Changes (", totalChanges, " total)"] }), _jsx(Text, { color: "cyan", children: '─'.repeat(40) }), writes.length > 0 && (_jsxs(Box, { flexDirection: "column", marginTop: 1, children: [_jsxs(Text, { color: "green", bold: true, children: ["Created (", writes.length, "):"] }), writes.map((w, i) => (_jsxs(Text, { children: [" + ", w.target] }, i)))] })), edits.length > 0 && (_jsxs(Box, { flexDirection: "column", marginTop: 1, children: [_jsxs(Text, { color: "yellow", bold: true, children: ["Modified (", edits.length, "):"] }), edits.map((e, i) => (_jsxs(Text, { children: [" ~ ", e.target] }, i)))] })), deletes.length > 0 && (_jsxs(Box, { flexDirection: "column", marginTop: 1, children: [_jsxs(Text, { color: "red", bold: true, children: ["Deleted (", deletes.length, "):"] }), deletes.map((d, i) => (_jsxs(Text, { children: [" - ", d.target] }, i)))] })), mkdirs.length > 0 && (_jsxs(Box, { flexDirection: "column", marginTop: 1, children: [_jsxs(Text, { color: "blue", bold: true, children: ["Directories (", mkdirs.length, "):"] }), mkdirs.map((m, i) => (_jsxs(Text, { children: [" + ", m.target, "/"] }, i)))] }))] }));
363
- };
364
- export const AgentStatusBar = memo(({ iteration, actionsCount, dryRun, currentAction }) => {
365
- const color = dryRun ? 'yellow' : '#f02a30';
366
- return (_jsxs(Box, { borderStyle: "round", borderColor: color, paddingX: 1, marginY: 1, height: 3, children: [_jsx(AgentSpinner, { color: color }), _jsxs(Text, { color: color, bold: true, children: [" ", dryRun ? 'DRY RUN' : 'AGENT', " "] }), _jsxs(Text, { color: "cyan", children: ["Step ", iteration] }), _jsx(Text, { color: "gray", children: " | " }), _jsxs(Text, { color: "white", children: [actionsCount, " actions"] }), currentAction && (_jsxs(_Fragment, { children: [_jsx(Text, { color: "gray", children: " | " }), _jsx(Text, { color: "cyan", children: currentAction })] })), _jsx(Text, { color: "gray", children: " | Press " }), _jsx(Text, { color: color, children: "Esc" }), _jsx(Text, { color: "gray", children: " to stop" })] }));
367
- });
368
- AgentStatusBar.displayName = 'AgentStatusBar';
@@ -1,8 +0,0 @@
1
- import React from 'react';
2
- import { ExportFormat } from '../utils/export';
3
- interface ExportProps {
4
- onExport: (format: ExportFormat) => void;
5
- onCancel: () => void;
6
- }
7
- export declare const Export: React.FC<ExportProps>;
8
- export {};
@@ -1,27 +0,0 @@
1
- import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
- import { useState } from 'react';
3
- import { Box, Text, useInput } from 'ink';
4
- export const Export = ({ onExport, onCancel }) => {
5
- const [selectedIndex, setSelectedIndex] = useState(0);
6
- const formats = [
7
- { id: 'md', name: 'Markdown', description: 'Formatted with headers and separators' },
8
- { id: 'json', name: 'JSON', description: 'Structured data format' },
9
- { id: 'txt', name: 'Plain Text', description: 'Simple text format' },
10
- ];
11
- useInput((input, key) => {
12
- if (key.escape) {
13
- onCancel();
14
- return;
15
- }
16
- if (key.upArrow) {
17
- setSelectedIndex((prev) => (prev > 0 ? prev - 1 : formats.length - 1));
18
- }
19
- if (key.downArrow) {
20
- setSelectedIndex((prev) => (prev < formats.length - 1 ? prev + 1 : 0));
21
- }
22
- if (key.return) {
23
- onExport(formats[selectedIndex].id);
24
- }
25
- });
26
- return (_jsxs(Box, { flexDirection: "column", borderStyle: "round", borderColor: "green", padding: 1, children: [_jsx(Text, { color: "green", bold: true, children: "Export Chat" }), _jsx(Text, { children: " " }), _jsx(Text, { children: "Select export format:" }), _jsx(Text, { children: " " }), formats.map((format, index) => (_jsx(Box, { flexDirection: "column", children: _jsxs(Text, { children: [selectedIndex === index ? '› ' : ' ', _jsx(Text, { color: selectedIndex === index ? 'green' : 'white', bold: selectedIndex === index, children: format.name }), _jsxs(Text, { children: [" - ", format.description] })] }) }, format.id))), _jsx(Text, { children: " " }), _jsx(Text, { children: "\u2191/\u2193 Navigate \u2022 Enter Export \u2022 Esc Cancel" })] }));
27
- };
@@ -1,6 +0,0 @@
1
- import React from 'react';
2
- interface HelpProps {
3
- projectPath?: string;
4
- }
5
- export declare const Help: React.FC<HelpProps>;
6
- export {};
@@ -1,7 +0,0 @@
1
- import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
2
- import { Text, Box } from 'ink';
3
- import { detectProjectFeatures } from '../utils/project.js';
4
- export const Help = ({ projectPath }) => {
5
- const features = projectPath ? detectProjectFeatures(projectPath) : null;
6
- return (_jsxs(Box, { flexDirection: "column", children: [_jsx(Text, { color: "#f02a30", bold: true, children: "Codeep Commands" }), _jsx(Text, { children: " " }), _jsx(Text, { color: "cyan", bold: true, children: "General" }), _jsxs(Box, { flexDirection: "row", gap: 4, children: [_jsxs(Box, { flexDirection: "column", children: [_jsxs(Text, { children: [_jsx(Text, { color: "#f02a30", children: "/help" }), " - Show this help"] }), _jsxs(Text, { children: [_jsx(Text, { color: "#f02a30", children: "/status" }), " - Current status"] }), _jsxs(Text, { children: [_jsx(Text, { color: "#f02a30", children: "/version" }), " - Show version"] })] }), _jsxs(Box, { flexDirection: "column", children: [_jsxs(Text, { children: [_jsx(Text, { color: "#f02a30", children: "/update" }), " - Check for updates"] }), _jsxs(Text, { children: [_jsx(Text, { color: "#f02a30", children: "/clear" }), " - Clear chat"] }), _jsxs(Text, { children: [_jsx(Text, { color: "#f02a30", children: "/exit" }), " - Quit"] })] })] }), _jsx(Text, { children: " " }), _jsx(Text, { color: "cyan", bold: true, children: "Agent & AI" }), _jsxs(Box, { flexDirection: "row", gap: 4, children: [_jsxs(Box, { flexDirection: "column", children: [_jsxs(Text, { children: [_jsx(Text, { color: "#f02a30", children: "/agent" }), " ", '<task>', " - Run AI agent"] }), _jsxs(Text, { children: [_jsx(Text, { color: "#f02a30", children: "/agent-dry" }), " - Preview agent actions"] }), _jsxs(Text, { children: [_jsx(Text, { color: "#f02a30", children: "/agent-stop" }), " - Stop running agent"] })] }), _jsxs(Box, { flexDirection: "column", children: [_jsxs(Text, { children: [_jsx(Text, { color: "#f02a30", children: "/grant" }), " - Grant write permission"] }), _jsxs(Text, { children: [_jsx(Text, { color: "#f02a30", children: "/scan" }), " - Scan project for AI"] }), _jsxs(Text, { children: [_jsx(Text, { color: "#f02a30", children: "/skills" }), " - List available skills"] })] })] }), _jsx(Text, { children: " " }), _jsx(Text, { color: "cyan", bold: true, children: "Git" }), _jsxs(Box, { flexDirection: "row", gap: 4, children: [_jsxs(Box, { flexDirection: "column", children: [_jsxs(Text, { children: [_jsx(Text, { color: "#f02a30", children: "/diff" }), " - Review git changes"] }), _jsxs(Text, { children: [_jsx(Text, { color: "#f02a30", children: "/diff --staged" }), " - Review staged"] })] }), _jsxs(Box, { flexDirection: "column", children: [_jsxs(Text, { children: [_jsx(Text, { color: "#f02a30", children: "/commit" }), " - Generate commit msg"] }), _jsxs(Text, { children: [_jsx(Text, { color: "#f02a30", children: "/apply" }), " - Apply file changes"] })] })] }), _jsx(Text, { children: " " }), _jsx(Text, { color: "cyan", bold: true, children: "Configuration" }), _jsxs(Box, { flexDirection: "row", gap: 4, children: [_jsxs(Box, { flexDirection: "column", children: [_jsxs(Text, { children: [_jsx(Text, { color: "#f02a30", children: "/model" }), " - Switch AI model"] }), _jsxs(Text, { children: [_jsx(Text, { color: "#f02a30", children: "/provider" }), " - Switch provider"] })] }), _jsxs(Box, { flexDirection: "column", children: [_jsxs(Text, { children: [_jsx(Text, { color: "#f02a30", children: "/settings" }), " - Adjust settings"] }), _jsxs(Text, { children: [_jsx(Text, { color: "#f02a30", children: "/lang" }), " - Set language"] })] })] }), _jsx(Text, { children: " " }), _jsx(Text, { color: "cyan", bold: true, children: "Sessions" }), _jsxs(Box, { flexDirection: "row", gap: 4, children: [_jsxs(Box, { flexDirection: "column", children: [_jsxs(Text, { children: [_jsx(Text, { color: "#f02a30", children: "/sessions" }), " - Manage sessions"] }), _jsxs(Text, { children: [_jsx(Text, { color: "#f02a30", children: "/rename" }), " - Rename session"] })] }), _jsxs(Box, { flexDirection: "column", children: [_jsxs(Text, { children: [_jsx(Text, { color: "#f02a30", children: "/search" }), " - Search history"] }), _jsxs(Text, { children: [_jsx(Text, { color: "#f02a30", children: "/export" }), " - Export chat"] })] })] }), _jsx(Text, { children: " " }), _jsx(Text, { color: "cyan", bold: true, children: "Clipboard" }), _jsxs(Box, { flexDirection: "row", gap: 4, children: [_jsx(Box, { flexDirection: "column", children: _jsxs(Text, { children: [_jsx(Text, { color: "#f02a30", children: "/copy" }), " [n] - Copy code block"] }) }), _jsx(Box, { flexDirection: "column", children: _jsxs(Text, { children: [_jsx(Text, { color: "#f02a30", children: "/paste" }), " - Paste from clipboard"] }) })] }), _jsx(Text, { children: " " }), _jsx(Text, { color: "cyan", bold: true, children: "Account" }), _jsxs(Box, { flexDirection: "row", gap: 4, children: [_jsx(Box, { flexDirection: "column", children: _jsxs(Text, { children: [_jsx(Text, { color: "#f02a30", children: "/login" }), " - Change API key"] }) }), _jsx(Box, { flexDirection: "column", children: _jsxs(Text, { children: [_jsx(Text, { color: "#f02a30", children: "/logout" }), " - Logout"] }) })] }), features && (features.hasGit || features.hasPackageJson || features.hasPython || features.hasCargo || features.hasGoMod) && (_jsxs(_Fragment, { children: [_jsx(Text, { children: " " }), _jsx(Text, { color: "green", bold: true, children: "Suggested for this project:" }), _jsxs(Box, { flexDirection: "column", marginLeft: 1, children: [features.hasGit && (_jsxs(Text, { children: [_jsx(Text, { color: "green", children: "/diff" }), " - Review your uncommitted changes"] })), features.hasGit && (_jsxs(Text, { children: [_jsx(Text, { color: "green", children: "/commit" }), " - AI-generated commit message"] })), features.hasPackageJson && (_jsxs(Text, { children: [_jsx(Text, { color: "green", children: "/agent npm run build" }), " - Build Node.js project"] })), features.hasPython && (_jsxs(Text, { children: [_jsx(Text, { color: "green", children: "/agent pytest" }), " - Run Python tests"] })), features.hasCargo && (_jsxs(Text, { children: [_jsx(Text, { color: "green", children: "/agent cargo build" }), " - Build Rust project"] })), features.hasGoMod && (_jsxs(Text, { children: [_jsx(Text, { color: "green", children: "/agent go build" }), " - Build Go project"] }))] })] })), _jsx(Text, { children: " " }), _jsx(Text, { color: "cyan", children: "Type / for autocomplete | Docs: github.com/VladoIvankovic/Codeep" })] }));
7
- };