@bubblebrain-ai/bubble 0.0.20 → 0.0.21

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 (49) hide show
  1. package/dist/agent.d.ts +1 -0
  2. package/dist/agent.js +5 -1
  3. package/dist/checkpoints.d.ts +57 -0
  4. package/dist/checkpoints.js +0 -0
  5. package/dist/feishu/agent-host/run-driver.js +1 -0
  6. package/dist/main.js +54 -13
  7. package/dist/session.d.ts +31 -0
  8. package/dist/session.js +69 -0
  9. package/dist/slash-commands/commands.js +80 -0
  10. package/dist/slash-commands/types.d.ts +4 -0
  11. package/dist/tools/bash.js +4 -0
  12. package/dist/tools/edit.d.ts +2 -1
  13. package/dist/tools/edit.js +2 -1
  14. package/dist/tools/index.d.ts +7 -0
  15. package/dist/tools/index.js +2 -2
  16. package/dist/tools/write.d.ts +2 -1
  17. package/dist/tools/write.js +2 -1
  18. package/dist/tui/image-paste.d.ts +18 -0
  19. package/dist/tui/image-paste.js +60 -0
  20. package/dist/tui/run.js +309 -69
  21. package/dist/tui/trace-groups.d.ts +16 -0
  22. package/dist/tui/trace-groups.js +42 -1
  23. package/dist/tui/transcript-scroll.d.ts +25 -0
  24. package/dist/tui/transcript-scroll.js +20 -0
  25. package/dist/tui-ink/app.d.ts +4 -1
  26. package/dist/tui-ink/app.js +301 -247
  27. package/dist/tui-ink/display-history.d.ts +16 -1
  28. package/dist/tui-ink/display-history.js +50 -21
  29. package/dist/tui-ink/footer.d.ts +6 -12
  30. package/dist/tui-ink/footer.js +10 -29
  31. package/dist/tui-ink/image-paste.d.ts +59 -0
  32. package/dist/tui-ink/image-paste.js +277 -0
  33. package/dist/tui-ink/input-box.d.ts +26 -1
  34. package/dist/tui-ink/input-box.js +171 -41
  35. package/dist/tui-ink/message-list.d.ts +1 -1
  36. package/dist/tui-ink/message-list.js +46 -29
  37. package/dist/tui-ink/run.d.ts +7 -2
  38. package/dist/tui-ink/run.js +73 -23
  39. package/dist/tui-ink/terminal-mouse.d.ts +1 -0
  40. package/dist/tui-ink/terminal-mouse.js +4 -0
  41. package/dist/tui-ink/trace-groups.d.ts +16 -0
  42. package/dist/tui-ink/trace-groups.js +50 -2
  43. package/dist/tui-ink/transcript-viewport-math.d.ts +11 -0
  44. package/dist/tui-ink/transcript-viewport-math.js +17 -0
  45. package/dist/tui-ink/transcript-viewport.d.ts +24 -0
  46. package/dist/tui-ink/transcript-viewport.js +83 -0
  47. package/dist/tui-ink/welcome.d.ts +9 -7
  48. package/dist/tui-ink/welcome.js +7 -33
  49. package/package.json +1 -1
@@ -65,6 +65,15 @@ export function removeImagePathTokens(input, tokens) {
65
65
  export function imageAttachmentLabel(att, index) {
66
66
  return `image#${index}${imageExtension(att)}`;
67
67
  }
68
+ /**
69
+ * Label for an image path before ingestion runs. Matches what
70
+ * imageAttachmentLabel produces for the same file, so a label inserted at
71
+ * paste time stays a valid key once the attachment is registered.
72
+ */
73
+ export function imageLabelForPath(rawPath, index) {
74
+ const ext = path.extname(unescapeShell(rawPath.trim())).toLowerCase() || ".png";
75
+ return `image#${index}${ext}`;
76
+ }
68
77
  export function imageAttachmentReference(att, index) {
69
78
  return `[${imageAttachmentLabel(att, index)}]`;
70
79
  }
@@ -155,6 +164,30 @@ export function splitPastedPaths(pasted) {
155
164
  }
156
165
  return out;
157
166
  }
167
+ /**
168
+ * True when a pasted blob consists solely of image file paths (drag from
169
+ * Finder, or a terminal that converts clipboard images to temp-file paths).
170
+ */
171
+ export function isImagePathPaste(pasted) {
172
+ const pieces = splitPastedPaths(pasted);
173
+ return pieces.length > 0 && pieces.every((piece) => isImageFilePath(piece));
174
+ }
175
+ /**
176
+ * Bare image filename with no directory, e.g. "Screenshot ... AM.png".
177
+ * Copying an image file in Finder puts only the file's NAME in the
178
+ * clipboard's plain-text flavor — the actual bits arrive as a file-url or
179
+ * image flavor that must be read from the clipboard separately.
180
+ */
181
+ export function bareImageFilenameFromPaste(pasted) {
182
+ const s = pasted.trim();
183
+ if (!s || s.length > 255)
184
+ return null;
185
+ if (/[\n\r/\\]/.test(s))
186
+ return null;
187
+ if (!IMAGE_EXT.test(s))
188
+ return null;
189
+ return s;
190
+ }
158
191
  function mediaTypeFromExt(p) {
159
192
  const ext = path.extname(p).toLowerCase();
160
193
  if (ext === ".jpg" || ext === ".jpeg")
@@ -384,6 +417,14 @@ export async function ingestImagePath(p) {
384
417
  return { attachment: sized };
385
418
  }
386
419
  export async function ingestClipboardImage() {
420
+ // A file reference wins over bitmap flavors: for a copied FILE, coercing
421
+ // the clipboard to PNGf yields the file's generic ICON, not the image.
422
+ const filePath = await getClipboardFilePath();
423
+ if (filePath) {
424
+ if (isImageFilePath(filePath))
425
+ return ingestImagePath(filePath);
426
+ return { error: `clipboard file is not an image: ${filePath}` };
427
+ }
387
428
  const raw = await getImageFromClipboard();
388
429
  if (!raw)
389
430
  return { error: "clipboard has no image" };
@@ -393,6 +434,25 @@ export async function ingestClipboardImage() {
393
434
  return { error: validation.reason };
394
435
  return { attachment: sized };
395
436
  }
437
+ async function getClipboardFilePath() {
438
+ if (process.platform !== "darwin")
439
+ return null;
440
+ try {
441
+ // Probe first — AppleScript happily coerces plain TEXT into a file URL,
442
+ // so only trust «class furl» when the clipboard really carries one.
443
+ const probe = await execFileAsync("osascript", ["-e", "clipboard info for «class furl»"], {
444
+ timeout: 5000,
445
+ });
446
+ if (!String(probe.stdout).includes("furl"))
447
+ return null;
448
+ const result = await execFileAsync("osascript", ["-e", "POSIX path of (the clipboard as «class furl»)"], { timeout: 5000 });
449
+ const p = String(result.stdout).trim();
450
+ return p || null;
451
+ }
452
+ catch {
453
+ return null;
454
+ }
455
+ }
396
456
  export async function resolveImageInput(input, options = {}) {
397
457
  const tokens = extractImagePathTokens(input);
398
458
  if (tokens.length === 0) {