snow-ai 0.3.16 → 0.3.17

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,6 +1,6 @@
1
1
  import React, { useCallback, useEffect, useRef } from 'react';
2
2
  import { Box, Text } from 'ink';
3
- import { cpSlice, cpLen } from '../../utils/textUtils.js';
3
+ import { cpSlice } from '../../utils/textUtils.js';
4
4
  import CommandPanel from './CommandPanel.js';
5
5
  import FileList from './FileList.js';
6
6
  import { useInputBuffer } from '../../hooks/useInputBuffer.js';
@@ -181,101 +181,18 @@ export default function ChatInput({ onSubmit, onCommand, placeholder = 'Type you
181
181
  return React.createElement(Text, null, char);
182
182
  }
183
183
  }, [hasFocus]);
184
- // Render content with cursor and paste placeholders
184
+ // Render content with cursor (treat all text including placeholders as plain text)
185
185
  const renderContent = useCallback(() => {
186
186
  if (buffer.text.length > 0) {
187
- // 使用buffer的内部文本而不是getFullText(),这样可以显示占位符
187
+ // 使用buffer的内部文本,将占位符当作普通文本处理
188
188
  const displayText = buffer.text;
189
189
  const cursorPos = buffer.getCursorPosition();
190
- const hasPastePlaceholder = displayText.includes('[Paste ') &&
191
- displayText.includes(' characters #');
192
- const hasImagePlaceholder = displayText.includes('[image #');
193
- const focusTokenPattern = /(\x1b)?\[[IO]/g;
194
- const cleanedText = displayText.replace(focusTokenPattern, '').trim();
195
- // 检查是否只有换行符或焦点标记
196
- const hasOnlyNewlines = /^[\n\s]*$/.test(displayText.replace(focusTokenPattern, ''));
197
- const isFocusNoise = cleanedText.length === 0 && !hasOnlyNewlines;
198
- if (hasPastePlaceholder || hasImagePlaceholder || isFocusNoise) {
199
- const atCursor = (() => {
200
- const charInfo = buffer.getCharAtCursor();
201
- return charInfo.char === '\n' ? ' ' : charInfo.char;
202
- })();
203
- // 分割文本并高亮占位符(粘贴和图片)
204
- const parts = displayText.split(/(\[Paste \d+ characters #\d+\]|\[image #\d+\])/);
205
- // 先构建带位置信息的数据结构
206
- const partsWithPosition = [];
207
- let processedLength = 0;
208
- for (let i = 0; i < parts.length; i++) {
209
- const part = parts[i] || '';
210
- const isPastePlaceholder = !!part.match(/^\[Paste \d+ characters #\d+\]$/);
211
- const isImagePlaceholder = !!part.match(/^\[image #\d+\]$/);
212
- const partStart = processedLength;
213
- const partEnd = processedLength + cpLen(part);
214
- processedLength = partEnd;
215
- if (part.length > 0) {
216
- partsWithPosition.push({
217
- part,
218
- partStart,
219
- partEnd,
220
- isPastePlaceholder,
221
- isImagePlaceholder,
222
- originalIndex: i,
223
- });
224
- }
225
- }
226
- let cursorRendered = false;
227
- const elements = [];
228
- let elementKey = 0;
229
- for (const item of partsWithPosition) {
230
- const { part, partStart, partEnd, isPastePlaceholder, isImagePlaceholder, originalIndex } = item;
231
- const isPlaceholder = isPastePlaceholder || isImagePlaceholder;
232
- // 检查光标是否在这个部分
233
- if (cursorPos >= partStart && cursorPos < partEnd) {
234
- cursorRendered = true;
235
- const beforeCursorInPart = cpSlice(part, 0, cursorPos - partStart);
236
- const afterCursorInPart = cpSlice(part, cursorPos - partStart + 1);
237
- if (isPlaceholder) {
238
- if (beforeCursorInPart) {
239
- elements.push(React.createElement(Text, { key: `${originalIndex}-before`, color: isImagePlaceholder ? 'magenta' : 'cyan', dimColor: true }, beforeCursorInPart));
240
- }
241
- elements.push(React.createElement(React.Fragment, { key: `cursor-${elementKey++}` }, renderCursor(atCursor)));
242
- if (afterCursorInPart) {
243
- elements.push(React.createElement(Text, { key: `${originalIndex}-after`, color: isImagePlaceholder ? 'magenta' : 'cyan', dimColor: true }, afterCursorInPart));
244
- }
245
- }
246
- else {
247
- if (beforeCursorInPart) {
248
- elements.push(React.createElement(Text, { key: `${originalIndex}-before` }, beforeCursorInPart));
249
- }
250
- elements.push(React.createElement(React.Fragment, { key: `cursor-${elementKey++}` }, renderCursor(atCursor)));
251
- if (afterCursorInPart) {
252
- elements.push(React.createElement(Text, { key: `${originalIndex}-after` }, afterCursorInPart));
253
- }
254
- }
255
- }
256
- else {
257
- if (isPlaceholder) {
258
- elements.push(React.createElement(Text, { key: originalIndex, color: isImagePlaceholder ? 'magenta' : 'cyan', dimColor: true }, part));
259
- }
260
- else {
261
- elements.push(React.createElement(Text, { key: originalIndex }, part));
262
- }
263
- }
264
- }
265
- if (!cursorRendered) {
266
- elements.push(React.createElement(React.Fragment, { key: `cursor-final` }, renderCursor(' ')));
267
- }
268
- return React.createElement(React.Fragment, null, elements);
269
- }
270
- else {
271
- // 普通文本渲染
272
- const charInfo = buffer.getCharAtCursor();
273
- const atCursor = charInfo.char === '\n' ? ' ' : charInfo.char;
274
- return (React.createElement(Text, null,
275
- cpSlice(displayText, 0, cursorPos),
276
- renderCursor(atCursor),
277
- cpSlice(displayText, cursorPos + 1)));
278
- }
190
+ const charInfo = buffer.getCharAtCursor();
191
+ const atCursor = charInfo.char === '\n' ? ' ' : charInfo.char;
192
+ return (React.createElement(Text, null,
193
+ cpSlice(displayText, 0, cursorPos),
194
+ renderCursor(atCursor),
195
+ cpSlice(displayText, cursorPos + 1)));
279
196
  }
280
197
  else {
281
198
  return (React.createElement(React.Fragment, null,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "snow-ai",
3
- "version": "0.3.16",
3
+ "version": "0.3.17",
4
4
  "description": "Intelligent Command Line Assistant powered by AI",
5
5
  "license": "MIT",
6
6
  "bin": {