codeep 1.1.12 → 1.1.13

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 (45) hide show
  1. package/bin/codeep.js +1 -1
  2. package/dist/config/index.js +10 -10
  3. package/dist/renderer/App.d.ts +430 -0
  4. package/dist/renderer/App.js +2712 -0
  5. package/dist/renderer/ChatUI.d.ts +71 -0
  6. package/dist/renderer/ChatUI.js +286 -0
  7. package/dist/renderer/Input.d.ts +72 -0
  8. package/dist/renderer/Input.js +371 -0
  9. package/dist/renderer/Screen.d.ts +79 -0
  10. package/dist/renderer/Screen.js +278 -0
  11. package/dist/renderer/ansi.d.ts +99 -0
  12. package/dist/renderer/ansi.js +176 -0
  13. package/dist/renderer/components/Box.d.ts +64 -0
  14. package/dist/renderer/components/Box.js +90 -0
  15. package/dist/renderer/components/Help.d.ts +30 -0
  16. package/dist/renderer/components/Help.js +195 -0
  17. package/dist/renderer/components/Intro.d.ts +12 -0
  18. package/dist/renderer/components/Intro.js +128 -0
  19. package/dist/renderer/components/Login.d.ts +42 -0
  20. package/dist/renderer/components/Login.js +178 -0
  21. package/dist/renderer/components/Modal.d.ts +43 -0
  22. package/dist/renderer/components/Modal.js +207 -0
  23. package/dist/renderer/components/Permission.d.ts +20 -0
  24. package/dist/renderer/components/Permission.js +113 -0
  25. package/dist/renderer/components/SelectScreen.d.ts +26 -0
  26. package/dist/renderer/components/SelectScreen.js +101 -0
  27. package/dist/renderer/components/Settings.d.ts +37 -0
  28. package/dist/renderer/components/Settings.js +333 -0
  29. package/dist/renderer/components/Status.d.ts +18 -0
  30. package/dist/renderer/components/Status.js +78 -0
  31. package/dist/renderer/demo-app.d.ts +6 -0
  32. package/dist/renderer/demo-app.js +85 -0
  33. package/dist/renderer/demo.d.ts +6 -0
  34. package/dist/renderer/demo.js +52 -0
  35. package/dist/renderer/index.d.ts +16 -0
  36. package/dist/renderer/index.js +17 -0
  37. package/dist/renderer/main.d.ts +6 -0
  38. package/dist/renderer/main.js +1634 -0
  39. package/dist/utils/agent.d.ts +21 -0
  40. package/dist/utils/agent.js +29 -0
  41. package/dist/utils/clipboard.d.ts +15 -0
  42. package/dist/utils/clipboard.js +95 -0
  43. package/package.json +7 -11
  44. package/dist/utils/console.d.ts +0 -55
  45. package/dist/utils/console.js +0 -188
@@ -0,0 +1,71 @@
1
+ /**
2
+ * Simple Chat UI - Proof of Concept
3
+ * Demonstrates custom renderer without Ink
4
+ */
5
+ export interface ChatMessage {
6
+ role: 'user' | 'assistant' | 'system';
7
+ content: string;
8
+ }
9
+ export interface ChatUIOptions {
10
+ onSubmit: (message: string) => void;
11
+ onExit: () => void;
12
+ }
13
+ export declare class ChatUI {
14
+ private screen;
15
+ private input;
16
+ private editor;
17
+ private messages;
18
+ private streamingContent;
19
+ private isStreaming;
20
+ private options;
21
+ private scrollOffset;
22
+ constructor(options: ChatUIOptions);
23
+ /**
24
+ * Start the UI
25
+ */
26
+ start(): void;
27
+ /**
28
+ * Stop the UI
29
+ */
30
+ stop(): void;
31
+ /**
32
+ * Add a message to chat
33
+ */
34
+ addMessage(message: ChatMessage): void;
35
+ /**
36
+ * Start streaming response
37
+ */
38
+ startStreaming(): void;
39
+ /**
40
+ * Add chunk to streaming response
41
+ */
42
+ addStreamChunk(chunk: string): void;
43
+ /**
44
+ * End streaming and add as message
45
+ */
46
+ endStreaming(): void;
47
+ /**
48
+ * Handle keyboard input
49
+ */
50
+ private handleKey;
51
+ /**
52
+ * Render the entire UI
53
+ */
54
+ render(): void;
55
+ /**
56
+ * Full render (alias for render, used on start)
57
+ */
58
+ private fullRender;
59
+ /**
60
+ * Format a message into lines
61
+ */
62
+ private formatMessage;
63
+ /**
64
+ * Get messages formatted for visible area (including streaming)
65
+ */
66
+ private getVisibleMessages;
67
+ /**
68
+ * Simple word wrap
69
+ */
70
+ private wordWrap;
71
+ }
@@ -0,0 +1,286 @@
1
+ /**
2
+ * Simple Chat UI - Proof of Concept
3
+ * Demonstrates custom renderer without Ink
4
+ */
5
+ import { Screen } from './Screen.js';
6
+ import { Input, LineEditor } from './Input.js';
7
+ import { fg } from './ansi.js';
8
+ export class ChatUI {
9
+ screen;
10
+ input;
11
+ editor;
12
+ messages = [];
13
+ streamingContent = '';
14
+ isStreaming = false;
15
+ options;
16
+ scrollOffset = 0;
17
+ constructor(options) {
18
+ this.screen = new Screen();
19
+ this.input = new Input();
20
+ this.editor = new LineEditor();
21
+ this.options = options;
22
+ }
23
+ /**
24
+ * Start the UI
25
+ */
26
+ start() {
27
+ this.screen.init();
28
+ this.input.start();
29
+ // Handle keyboard input
30
+ this.input.onKey((event) => this.handleKey(event));
31
+ // Initial render - use full render first time
32
+ this.fullRender();
33
+ }
34
+ /**
35
+ * Stop the UI
36
+ */
37
+ stop() {
38
+ this.input.stop();
39
+ this.screen.cleanup();
40
+ }
41
+ /**
42
+ * Add a message to chat
43
+ */
44
+ addMessage(message) {
45
+ this.messages.push(message);
46
+ this.scrollOffset = 0; // Reset scroll to bottom
47
+ this.render();
48
+ }
49
+ /**
50
+ * Start streaming response
51
+ */
52
+ startStreaming() {
53
+ this.isStreaming = true;
54
+ this.streamingContent = '';
55
+ this.render();
56
+ }
57
+ /**
58
+ * Add chunk to streaming response
59
+ */
60
+ addStreamChunk(chunk) {
61
+ this.streamingContent += chunk;
62
+ this.render();
63
+ }
64
+ /**
65
+ * End streaming and add as message
66
+ */
67
+ endStreaming() {
68
+ if (this.streamingContent) {
69
+ this.messages.push({
70
+ role: 'assistant',
71
+ content: this.streamingContent,
72
+ });
73
+ }
74
+ this.streamingContent = '';
75
+ this.isStreaming = false;
76
+ this.render();
77
+ }
78
+ /**
79
+ * Handle keyboard input
80
+ */
81
+ handleKey(event) {
82
+ // Ctrl+C or Ctrl+D to exit
83
+ if (event.ctrl && (event.key === 'c' || event.key === 'd')) {
84
+ this.stop();
85
+ this.options.onExit();
86
+ return;
87
+ }
88
+ // Escape to cancel streaming
89
+ if (event.key === 'escape' && this.isStreaming) {
90
+ this.endStreaming();
91
+ return;
92
+ }
93
+ // Ctrl+L to clear
94
+ if (event.ctrl && event.key === 'l') {
95
+ this.messages = [];
96
+ this.render();
97
+ return;
98
+ }
99
+ // Page up/down for scrolling
100
+ if (event.key === 'pageup') {
101
+ this.scrollOffset = Math.min(this.scrollOffset + 5, this.messages.length - 1);
102
+ this.render();
103
+ return;
104
+ }
105
+ if (event.key === 'pagedown') {
106
+ this.scrollOffset = Math.max(this.scrollOffset - 5, 0);
107
+ this.render();
108
+ return;
109
+ }
110
+ // Enter to submit
111
+ if (event.key === 'enter') {
112
+ const value = this.editor.getValue().trim();
113
+ if (value) {
114
+ this.editor.addToHistory(value);
115
+ this.editor.clear();
116
+ // Add user message
117
+ this.addMessage({ role: 'user', content: value });
118
+ // Callback
119
+ this.options.onSubmit(value);
120
+ }
121
+ this.render();
122
+ return;
123
+ }
124
+ // Handle editor keys
125
+ if (this.editor.handleKey(event)) {
126
+ this.render();
127
+ }
128
+ }
129
+ /**
130
+ * Render the entire UI
131
+ */
132
+ render() {
133
+ const { width, height } = this.screen.getSize();
134
+ this.screen.clear();
135
+ // Layout:
136
+ // - Line 0: Header
137
+ // - Lines 1 to height-4: Messages
138
+ // - Line height-3: Separator
139
+ // - Line height-2: Input
140
+ // - Line height-1: Status bar
141
+ const headerLine = 0;
142
+ const messagesStart = 1;
143
+ const messagesEnd = height - 4;
144
+ const separatorLine = height - 3;
145
+ const inputLine = height - 2;
146
+ const statusLine = height - 1;
147
+ // Header
148
+ const header = ' Codeep Chat ';
149
+ const headerPadding = '─'.repeat(Math.max(0, (width - header.length) / 2));
150
+ this.screen.writeLine(headerLine, headerPadding + header + headerPadding, fg.cyan);
151
+ // Messages area (including streaming content)
152
+ const messagesHeight = messagesEnd - messagesStart + 1;
153
+ const messagesToRender = this.getVisibleMessages(messagesHeight, width - 2);
154
+ let y = messagesStart;
155
+ for (const line of messagesToRender) {
156
+ if (y > messagesEnd)
157
+ break;
158
+ this.screen.writeLine(y, line.text, line.style);
159
+ y++;
160
+ }
161
+ // Separator
162
+ this.screen.horizontalLine(separatorLine, '─', fg.gray);
163
+ // Input line
164
+ const prompt = '> ';
165
+ const inputValue = this.editor.getValue();
166
+ const cursorPos = this.editor.getCursorPos();
167
+ const maxInputWidth = width - prompt.length - 1;
168
+ // Calculate what part of input to show and where cursor should be
169
+ let displayValue;
170
+ let cursorX;
171
+ if (inputValue.length <= maxInputWidth) {
172
+ // Input fits - show all, cursor at actual position
173
+ displayValue = inputValue;
174
+ cursorX = prompt.length + cursorPos;
175
+ }
176
+ else {
177
+ // Input too long - scroll to keep cursor visible
178
+ // Keep cursor roughly in the middle-right of visible area
179
+ const visibleStart = Math.max(0, cursorPos - Math.floor(maxInputWidth * 0.7));
180
+ const visibleEnd = visibleStart + maxInputWidth;
181
+ if (visibleStart > 0) {
182
+ displayValue = '…' + inputValue.slice(visibleStart + 1, visibleEnd);
183
+ }
184
+ else {
185
+ displayValue = inputValue.slice(0, maxInputWidth);
186
+ }
187
+ // Cursor position relative to visible portion
188
+ cursorX = prompt.length + (cursorPos - visibleStart);
189
+ if (visibleStart > 0) {
190
+ cursorX = prompt.length + (cursorPos - visibleStart);
191
+ }
192
+ }
193
+ this.screen.writeLine(inputLine, prompt + displayValue, fg.green);
194
+ // Position cursor
195
+ this.screen.setCursor(cursorX, inputLine);
196
+ this.screen.showCursor(true);
197
+ // Status bar
198
+ const statusLeft = ` ${this.messages.length} messages`;
199
+ const statusRight = this.isStreaming ? 'Streaming... (Esc to cancel)' : 'Enter to send | Ctrl+C to exit';
200
+ const statusPadding = ' '.repeat(Math.max(0, width - statusLeft.length - statusRight.length));
201
+ this.screen.writeLine(statusLine, statusLeft + statusPadding + statusRight, fg.gray);
202
+ // Render to terminal (use fullRender for now - more reliable)
203
+ this.screen.fullRender();
204
+ }
205
+ /**
206
+ * Full render (alias for render, used on start)
207
+ */
208
+ fullRender() {
209
+ this.render();
210
+ }
211
+ /**
212
+ * Format a message into lines
213
+ */
214
+ formatMessage(role, content, maxWidth) {
215
+ const lines = [];
216
+ // Role indicator
217
+ const roleStyle = role === 'user' ? fg.green : role === 'assistant' ? fg.cyan : fg.yellow;
218
+ const roleLabel = role === 'user' ? '> ' : role === 'assistant' ? ' ' : '# ';
219
+ // Split content into lines
220
+ const contentLines = content.split('\n');
221
+ for (let i = 0; i < contentLines.length; i++) {
222
+ const line = contentLines[i];
223
+ const prefix = i === 0 ? roleLabel : ' ';
224
+ const prefixStyle = i === 0 ? roleStyle : '';
225
+ // Word wrap long lines
226
+ if (line.length > maxWidth - prefix.length) {
227
+ const wrapped = this.wordWrap(line, maxWidth - prefix.length);
228
+ for (let j = 0; j < wrapped.length; j++) {
229
+ lines.push({
230
+ text: (j === 0 ? prefix : ' ') + wrapped[j],
231
+ style: j === 0 ? prefixStyle : '',
232
+ });
233
+ }
234
+ }
235
+ else {
236
+ lines.push({
237
+ text: prefix + line,
238
+ style: prefixStyle,
239
+ });
240
+ }
241
+ }
242
+ // Add empty line after message
243
+ lines.push({ text: '', style: '' });
244
+ return lines;
245
+ }
246
+ /**
247
+ * Get messages formatted for visible area (including streaming)
248
+ */
249
+ getVisibleMessages(height, width) {
250
+ const allLines = [];
251
+ for (const msg of this.messages) {
252
+ const msgLines = this.formatMessage(msg.role, msg.content, width);
253
+ allLines.push(...msgLines);
254
+ }
255
+ // Add streaming content if active
256
+ if (this.isStreaming && this.streamingContent) {
257
+ const streamLines = this.formatMessage('assistant', this.streamingContent + '▊', width);
258
+ allLines.push(...streamLines);
259
+ }
260
+ // Apply scroll offset and return last 'height' lines
261
+ const startIndex = Math.max(0, allLines.length - height - this.scrollOffset);
262
+ const endIndex = allLines.length - this.scrollOffset;
263
+ return allLines.slice(startIndex, endIndex);
264
+ }
265
+ /**
266
+ * Simple word wrap
267
+ */
268
+ wordWrap(text, maxWidth) {
269
+ const words = text.split(' ');
270
+ const lines = [];
271
+ let currentLine = '';
272
+ for (const word of words) {
273
+ if (currentLine.length + word.length + 1 > maxWidth && currentLine) {
274
+ lines.push(currentLine);
275
+ currentLine = word;
276
+ }
277
+ else {
278
+ currentLine += (currentLine ? ' ' : '') + word;
279
+ }
280
+ }
281
+ if (currentLine) {
282
+ lines.push(currentLine);
283
+ }
284
+ return lines.length > 0 ? lines : [''];
285
+ }
286
+ }
@@ -0,0 +1,72 @@
1
+ /**
2
+ * Raw input handling for terminal
3
+ * Handles keypresses, special keys, and line editing
4
+ */
5
+ export interface KeyEvent {
6
+ key: string;
7
+ ctrl: boolean;
8
+ alt: boolean;
9
+ shift: boolean;
10
+ raw: string;
11
+ isPaste?: boolean;
12
+ }
13
+ export type KeyHandler = (event: KeyEvent) => void;
14
+ export declare class Input {
15
+ private handlers;
16
+ private rl;
17
+ /**
18
+ * Start listening for input
19
+ */
20
+ start(): void;
21
+ /**
22
+ * Stop listening
23
+ */
24
+ stop(): void;
25
+ /**
26
+ * Add key handler
27
+ */
28
+ onKey(handler: KeyHandler): () => void;
29
+ /**
30
+ * Emit key event to all handlers
31
+ */
32
+ private emit;
33
+ /**
34
+ * Parse raw input into KeyEvent
35
+ */
36
+ private parseKey;
37
+ }
38
+ /**
39
+ * Simple line editor with cursor support
40
+ */
41
+ export declare class LineEditor {
42
+ private value;
43
+ private cursorPos;
44
+ private history;
45
+ private historyIndex;
46
+ private tempValue;
47
+ getValue(): string;
48
+ getCursorPos(): number;
49
+ setValue(value: string): void;
50
+ clear(): void;
51
+ /**
52
+ * Insert text at cursor position
53
+ */
54
+ insert(text: string): void;
55
+ /**
56
+ * Set cursor position
57
+ */
58
+ setCursorPos(pos: number): void;
59
+ /**
60
+ * Delete word backward (Ctrl+W)
61
+ */
62
+ deleteWordBackward(): void;
63
+ /**
64
+ * Delete to end of line (Ctrl+K)
65
+ */
66
+ deleteToEnd(): void;
67
+ addToHistory(value: string): void;
68
+ /**
69
+ * Handle key event, returns true if value changed
70
+ */
71
+ handleKey(event: KeyEvent): boolean;
72
+ }