codeep 1.0.35 → 1.0.37

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.
@@ -1,7 +1,6 @@
1
1
  import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
- import { useState, useMemo, useEffect, useRef } from 'react';
3
- import { Text, Box, useInput } from 'ink';
4
- import clipboard from 'clipboardy';
2
+ import { useState, useMemo, useEffect } from 'react';
3
+ import { Text, Box, useInput, useStdin } from 'ink';
5
4
  const COMMANDS = [
6
5
  { cmd: '/help', desc: 'Show help' },
7
6
  { cmd: '/status', desc: 'Show status' },
@@ -33,8 +32,7 @@ export const ChatInput = ({ onSubmit, disabled, history = [], clearTrigger = 0 }
33
32
  const [selectedIndex, setSelectedIndex] = useState(0);
34
33
  const [pasteInfo, setPasteInfo] = useState(null);
35
34
  const [historyIndex, setHistoryIndex] = useState(-1);
36
- const lastInputTime = useRef(0);
37
- const inputBuffer = useRef('');
35
+ const { stdin } = useStdin();
38
36
  // Clear input when clearTrigger changes
39
37
  useEffect(() => {
40
38
  if (clearTrigger > 0) {
@@ -57,37 +55,33 @@ export const ChatInput = ({ onSubmit, disabled, history = [], clearTrigger = 0 }
57
55
  setSelectedIndex(0);
58
56
  }
59
57
  }, [suggestions.length]);
60
- // Detect paste by checking for rapid input (multiple chars in < 50ms)
61
- const detectPaste = (newChars) => {
62
- const now = Date.now();
63
- const timeDiff = now - lastInputTime.current;
64
- // If multiple characters arrive very quickly, it's likely a paste
65
- if (timeDiff < 50 && newChars.length > 0) {
66
- inputBuffer.current += newChars;
67
- return true;
68
- }
69
- // Process any buffered paste
70
- if (inputBuffer.current.length > 5) {
71
- // This was a paste that just finished
72
- const pastedText = inputBuffer.current;
73
- inputBuffer.current = '';
74
- handlePastedText(pastedText);
75
- lastInputTime.current = now;
76
- return true;
77
- }
78
- inputBuffer.current = newChars;
79
- lastInputTime.current = now;
80
- return false;
81
- };
82
- const handlePastedText = (text) => {
58
+ // Listen for raw stdin data to detect paste (multiple chars at once)
59
+ useEffect(() => {
60
+ if (disabled || !stdin)
61
+ return;
62
+ const handleData = (data) => {
63
+ const str = data.toString();
64
+ // Detect paste: multiple printable characters arriving at once
65
+ // Exclude control sequences (start with ESC)
66
+ if (str.length > 1 && !str.startsWith('\x1b') && !str.startsWith('\x16')) {
67
+ // This is likely a paste - multiple chars at once
68
+ handlePastedText(str, true);
69
+ }
70
+ };
71
+ stdin.on('data', handleData);
72
+ return () => {
73
+ stdin.off('data', handleData);
74
+ };
75
+ }, [disabled, stdin]);
76
+ const handlePastedText = (text, fromCtrlV = false) => {
83
77
  const trimmed = text.trim();
84
78
  if (!trimmed)
85
79
  return;
86
80
  const lines = trimmed.split(/\r?\n/);
87
81
  const lineCount = lines.length;
88
82
  const charCount = trimmed.length;
89
- // For multi-line or long pastes, store info
90
- if (lineCount > 1 || charCount > 100) {
83
+ // For multi-line, long pastes, or explicit Ctrl+V - show indicator
84
+ if (lineCount > 1 || charCount > 100 || (fromCtrlV && charCount > 20)) {
91
85
  const firstLine = lines[0].substring(0, 60);
92
86
  const preview = firstLine + (lines[0].length > 60 ? '...' : '');
93
87
  setPasteInfo({
@@ -97,7 +91,7 @@ export const ChatInput = ({ onSubmit, disabled, history = [], clearTrigger = 0 }
97
91
  fullText: trimmed,
98
92
  });
99
93
  // Show only indicator in input field, NOT the actual pasted text
100
- const indicator = `📋 [${lineCount} lines, ${charCount} chars]`;
94
+ const indicator = `📋 Paste: ${charCount} chars`;
101
95
  // Replace entire value with just the indicator (don't append pasted text)
102
96
  setValue(indicator);
103
97
  setCursorPos(indicator.length);
@@ -113,22 +107,13 @@ export const ChatInput = ({ onSubmit, disabled, history = [], clearTrigger = 0 }
113
107
  useInput((input, key) => {
114
108
  if (disabled)
115
109
  return;
116
- // Handle Ctrl+V paste
117
- if (key.ctrl && input === 'v') {
118
- clipboard.read().then(text => {
119
- if (text) {
120
- handlePastedText(text);
121
- }
122
- }).catch(() => { });
123
- return;
124
- }
125
110
  // Handle Enter - submit
126
111
  if (key.return) {
127
112
  if (value.trim()) {
128
113
  let submitValue = value.trim();
129
114
  // Replace paste indicator with actual content
130
- if (pasteInfo && submitValue.includes('📋 [')) {
131
- submitValue = submitValue.replace(/📋 \[\d+ lines, \d+ chars\]/, pasteInfo.fullText);
115
+ if (pasteInfo && submitValue.includes('📋 Paste:')) {
116
+ submitValue = submitValue.replace(/📋 Paste: \d+ chars/, pasteInfo.fullText);
132
117
  }
133
118
  onSubmit(submitValue);
134
119
  setValue('');
@@ -142,7 +127,7 @@ export const ChatInput = ({ onSubmit, disabled, history = [], clearTrigger = 0 }
142
127
  if (key.escape) {
143
128
  if (pasteInfo) {
144
129
  // Remove paste indicator from value
145
- setValue(prev => prev.replace(/📋 \[\d+ lines, \d+ chars\]/, ''));
130
+ setValue(prev => prev.replace(/📋 Paste: \d+ chars/, ''));
146
131
  setPasteInfo(null);
147
132
  }
148
133
  else if (value) {
@@ -157,7 +142,7 @@ export const ChatInput = ({ onSubmit, disabled, history = [], clearTrigger = 0 }
157
142
  setValue(prev => prev.slice(0, cursorPos - 1) + prev.slice(cursorPos));
158
143
  setCursorPos(prev => prev - 1);
159
144
  // Clear paste info if we deleted the indicator
160
- if (pasteInfo && !value.includes('📋 [')) {
145
+ if (pasteInfo && !value.includes('📋 Paste:')) {
161
146
  setPasteInfo(null);
162
147
  }
163
148
  }
@@ -254,23 +239,6 @@ export const ChatInput = ({ onSubmit, disabled, history = [], clearTrigger = 0 }
254
239
  setCursorPos(prev => prev + input.length);
255
240
  }
256
241
  }, { isActive: !disabled });
257
- // Process any remaining buffered input after a delay
258
- useEffect(() => {
259
- const timer = setTimeout(() => {
260
- if (inputBuffer.current.length > 0) {
261
- const buffered = inputBuffer.current;
262
- inputBuffer.current = '';
263
- if (buffered.length > 5) {
264
- handlePastedText(buffered);
265
- }
266
- else {
267
- setValue(prev => prev + buffered);
268
- setCursorPos(prev => prev + buffered.length);
269
- }
270
- }
271
- }, 100);
272
- return () => clearTimeout(timer);
273
- }, [value]);
274
242
  // Render input with cursor
275
243
  const renderInput = () => {
276
244
  if (!value) {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "codeep",
3
- "version": "1.0.35",
3
+ "version": "1.0.37",
4
4
  "description": "AI-powered coding assistant built for the terminal. Multiple LLM providers, project-aware context, and a seamless development workflow.",
5
5
  "type": "module",
6
6
  "main": "dist/index.js",