snow-ai 0.3.14 → 0.3.16

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.
@@ -35,30 +35,24 @@ export class TextBuffer {
35
35
  writable: true,
36
36
  value: void 0
37
37
  });
38
- Object.defineProperty(this, "pasteStorage", {
38
+ Object.defineProperty(this, "placeholderStorage", {
39
39
  enumerable: true,
40
40
  configurable: true,
41
41
  writable: true,
42
42
  value: new Map()
43
- });
44
- Object.defineProperty(this, "pasteCounter", {
43
+ }); // 统一的占位符存储
44
+ Object.defineProperty(this, "textPlaceholderCounter", {
45
45
  enumerable: true,
46
46
  configurable: true,
47
47
  writable: true,
48
48
  value: 0
49
- });
50
- Object.defineProperty(this, "imageStorage", {
51
- enumerable: true,
52
- configurable: true,
53
- writable: true,
54
- value: new Map()
55
- });
56
- Object.defineProperty(this, "imageCounter", {
49
+ }); // 文本占位符计数器
50
+ Object.defineProperty(this, "imagePlaceholderCounter", {
57
51
  enumerable: true,
58
52
  configurable: true,
59
53
  writable: true,
60
54
  value: 0
61
- });
55
+ }); // 图片占位符计数器
62
56
  Object.defineProperty(this, "pasteAccumulator", {
63
57
  enumerable: true,
64
58
  configurable: true,
@@ -126,20 +120,20 @@ export class TextBuffer {
126
120
  clearTimeout(this.pasteTimer);
127
121
  this.pasteTimer = null;
128
122
  }
129
- this.pasteStorage.clear();
130
- this.imageStorage.clear();
123
+ this.placeholderStorage.clear();
131
124
  this.onUpdateCallback = undefined;
132
125
  }
133
126
  get text() {
134
127
  return this.content;
135
128
  }
136
129
  /**
137
- * 获取完整文本,包括替换占位符为原始内容
130
+ * 获取完整文本,包括替换占位符为原始内容(仅文本类型)
138
131
  */
139
132
  getFullText() {
140
133
  let fullText = this.content;
141
- for (const placeholder of this.pasteStorage.values()) {
142
- if (placeholder.placeholder) {
134
+ for (const placeholder of this.placeholderStorage.values()) {
135
+ // 只替换文本类型的占位符
136
+ if (placeholder.type === 'text' && placeholder.placeholder) {
143
137
  fullText = fullText
144
138
  .split(placeholder.placeholder)
145
139
  .join(placeholder.content);
@@ -170,10 +164,9 @@ export class TextBuffer {
170
164
  this.content = sanitized;
171
165
  this.clampCursorIndex();
172
166
  if (sanitized === '') {
173
- this.pasteStorage.clear();
174
- this.pasteCounter = 0;
175
- this.imageStorage.clear();
176
- this.imageCounter = 0;
167
+ this.placeholderStorage.clear();
168
+ this.textPlaceholderCounter = 0;
169
+ this.imagePlaceholderCounter = 0;
177
170
  this.pasteAccumulator = '';
178
171
  if (this.pasteTimer) {
179
172
  clearTimeout(this.pasteTimer);
@@ -250,14 +243,15 @@ export class TextBuffer {
250
243
  this.content = this.content.replace(tempPlaceholderPattern, '');
251
244
  // 只有当累积的字符数超过300时才创建占位符
252
245
  if (totalChars > 300) {
253
- this.pasteCounter++;
254
- const pasteId = `paste_${Date.now()}_${this.pasteCounter}`;
255
- const placeholderText = `[Paste ${totalChars} characters #${this.pasteCounter}]`;
256
- this.pasteStorage.set(pasteId, {
246
+ this.textPlaceholderCounter++;
247
+ const pasteId = `paste_${Date.now()}_${this.textPlaceholderCounter}`;
248
+ const placeholderText = `[Paste ${totalChars} characters #${this.textPlaceholderCounter}]`;
249
+ this.placeholderStorage.set(pasteId, {
257
250
  id: pasteId,
251
+ type: 'text',
258
252
  content: this.pasteAccumulator,
259
253
  charCount: totalChars,
260
- index: this.pasteCounter,
254
+ index: this.textPlaceholderCounter,
261
255
  placeholder: placeholderText,
262
256
  });
263
257
  // 在记录的位置插入占位符
@@ -507,33 +501,57 @@ export class TextBuffer {
507
501
  this.preferredVisualCol = this.visualCursorPos[1];
508
502
  }
509
503
  /**
510
- * 插入图片数据
504
+ * 插入图片数据(使用统一的占位符系统)
511
505
  */
512
506
  insertImage(base64Data, mimeType) {
513
- this.imageCounter++;
514
- const imageId = `image_${Date.now()}_${this.imageCounter}`;
515
- const placeholderText = `[image #${this.imageCounter}]`;
516
- this.imageStorage.set(imageId, {
507
+ // 清理 base64 数据:移除所有空白字符(包括换行符)
508
+ // PowerShell/macOS base64 编码可能包含换行符
509
+ const cleanedBase64 = base64Data.replace(/\s+/g, '');
510
+ this.imagePlaceholderCounter++;
511
+ const imageId = `image_${Date.now()}_${this.imagePlaceholderCounter}`;
512
+ const placeholderText = `[image #${this.imagePlaceholderCounter}]`;
513
+ this.placeholderStorage.set(imageId, {
517
514
  id: imageId,
518
- data: base64Data,
519
- mimeType: mimeType,
520
- index: this.imageCounter,
515
+ type: 'image',
516
+ content: cleanedBase64,
517
+ charCount: cleanedBase64.length,
518
+ index: this.imagePlaceholderCounter,
521
519
  placeholder: placeholderText,
520
+ mimeType: mimeType,
522
521
  });
523
522
  this.insertPlainText(placeholderText);
524
523
  this.scheduleUpdate();
525
524
  }
526
525
  /**
527
- * 获取所有图片数据
526
+ * 获取所有图片数据(还原为 data URL 格式)
528
527
  */
529
528
  getImages() {
530
- return Array.from(this.imageStorage.values()).sort((a, b) => a.index - b.index);
529
+ return Array.from(this.placeholderStorage.values())
530
+ .filter((p) => p.type === 'image')
531
+ .map((p) => {
532
+ const mimeType = p.mimeType || 'image/png';
533
+ // 还原为 data URL 格式
534
+ const dataUrl = `data:${mimeType};base64,${p.content}`;
535
+ return {
536
+ id: p.id,
537
+ data: dataUrl,
538
+ mimeType: mimeType,
539
+ index: p.index,
540
+ placeholder: p.placeholder,
541
+ };
542
+ })
543
+ .sort((a, b) => a.index - b.index);
531
544
  }
532
545
  /**
533
546
  * 清除所有图片
534
547
  */
535
548
  clearImages() {
536
- this.imageStorage.clear();
537
- this.imageCounter = 0;
549
+ // 只清除图片类型的占位符
550
+ for (const [id, placeholder] of this.placeholderStorage.entries()) {
551
+ if (placeholder.type === 'image') {
552
+ this.placeholderStorage.delete(id);
553
+ }
554
+ }
555
+ this.imagePlaceholderCounter = 0;
538
556
  }
539
557
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "snow-ai",
3
- "version": "0.3.14",
3
+ "version": "0.3.16",
4
4
  "description": "Intelligent Command Line Assistant powered by AI",
5
5
  "license": "MIT",
6
6
  "bin": {