@hydra-acp/cli 0.1.13 → 0.1.14

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 (2) hide show
  1. package/dist/cli.js +66 -19
  2. package/package.json +1 -1
package/dist/cli.js CHANGED
@@ -3887,7 +3887,7 @@ function readTermWidth(term) {
3887
3887
  return term.width ?? 80;
3888
3888
  }
3889
3889
  function formatNewSessionLabel(cwd, maxWidth) {
3890
- const prefix = "+ New session in ";
3890
+ const prefix = "New session in ";
3891
3891
  const budget = Math.max(1, maxWidth - prefix.length);
3892
3892
  return prefix + truncateMiddle(shortenHomePath(cwd), budget);
3893
3893
  }
@@ -3931,6 +3931,23 @@ function mimeFromExtension(p) {
3931
3931
  function isSupportedImagePath(p) {
3932
3932
  return mimeFromExtension(p) !== null;
3933
3933
  }
3934
+ function parseDataUriImage(uri) {
3935
+ const match = uri.match(/^data:(image\/[a-z0-9.+\-]+);base64,([A-Za-z0-9+/=]+)$/);
3936
+ if (!match) {
3937
+ return null;
3938
+ }
3939
+ const mimeType = match[1].toLowerCase();
3940
+ if (!SUPPORTED_MIMES.has(mimeType)) {
3941
+ return null;
3942
+ }
3943
+ const data = match[2];
3944
+ const padding = data.endsWith("==") ? 2 : data.endsWith("=") ? 1 : 0;
3945
+ const sizeBytes = Math.floor(data.length * 3 / 4) - padding;
3946
+ return { mimeType, data, sizeBytes };
3947
+ }
3948
+ function isSupportedDataUriImage(uri) {
3949
+ return parseDataUriImage(uri) !== null;
3950
+ }
3934
3951
  function formatSize(bytes) {
3935
3952
  if (bytes >= 1024 * 1024) {
3936
3953
  return `${(bytes / (1024 * 1024)).toFixed(1)}MB`;
@@ -3978,6 +3995,13 @@ function parseImageDropPaste(raw) {
3978
3995
  }
3979
3996
  }
3980
3997
  }
3998
+ if (token.startsWith("data:")) {
3999
+ if (!isSupportedDataUriImage(token)) {
4000
+ return null;
4001
+ }
4002
+ tokens.push(token);
4003
+ continue;
4004
+ }
3981
4005
  let normalized = token;
3982
4006
  if (normalized.startsWith("file://")) {
3983
4007
  normalized = decodeURI(normalized.slice("file://".length));
@@ -3992,7 +4016,7 @@ function parseImageDropPaste(raw) {
3992
4016
  }
3993
4017
  return tokens.length > 0 ? tokens : null;
3994
4018
  }
3995
- var MAX_ATTACHMENT_BYTES, EXTENSION_TO_MIME;
4019
+ var MAX_ATTACHMENT_BYTES, EXTENSION_TO_MIME, SUPPORTED_MIMES;
3996
4020
  var init_attachments = __esm({
3997
4021
  "src/tui/attachments.ts"() {
3998
4022
  "use strict";
@@ -4004,6 +4028,7 @@ var init_attachments = __esm({
4004
4028
  ".gif": "image/gif",
4005
4029
  ".webp": "image/webp"
4006
4030
  };
4031
+ SUPPORTED_MIMES = new Set(Object.values(EXTENSION_TO_MIME));
4007
4032
  }
4008
4033
  });
4009
4034
 
@@ -6879,21 +6904,20 @@ var init_input = __esm({
6879
6904
  return [{ type: "scroll-to-bottom" }];
6880
6905
  }
6881
6906
  handleCtrlC() {
6907
+ if (this.queueIndex >= 0) {
6908
+ const index = this.queueIndex;
6909
+ this.queueIndex = -1;
6910
+ this.restoreDraft();
6911
+ return [{ type: "queue-remove", index }];
6912
+ }
6882
6913
  if (!this.bufferIsEmpty() || this.attachments.length > 0) {
6883
6914
  this.buffer = [""];
6884
6915
  this.row = 0;
6885
6916
  this.col = 0;
6886
6917
  this.attachments = [];
6887
- if (this.queueIndex === -1) {
6888
- this.historyIndex = -1;
6889
- this.savedDraft = null;
6890
- this.savedAttachments = null;
6891
- }
6892
- return [];
6893
- }
6894
- if (this.queueIndex >= 0) {
6895
- this.queueIndex = -1;
6896
- this.restoreDraft();
6918
+ this.historyIndex = -1;
6919
+ this.savedDraft = null;
6920
+ this.savedAttachments = null;
6897
6921
  return [];
6898
6922
  }
6899
6923
  if (this.turnRunning) {
@@ -8573,20 +8597,41 @@ async function runSession(term, config, opts, exitHint) {
8573
8597
  return;
8574
8598
  }
8575
8599
  };
8576
- const handleAttachmentPaths = async (paths2) => {
8600
+ const handleAttachmentPaths = async (tokens) => {
8577
8601
  if (!agentAcceptsImages) {
8578
8602
  screen.notify("agent does not accept image attachments");
8579
8603
  return;
8580
8604
  }
8581
8605
  let added = 0;
8582
- for (const p of paths2) {
8583
- const mimeType = mimeFromExtension(p);
8606
+ for (const token of tokens) {
8607
+ if (token.startsWith("data:")) {
8608
+ const parsed = parseDataUriImage(token);
8609
+ if (!parsed) {
8610
+ screen.notify("unsupported data: URI");
8611
+ continue;
8612
+ }
8613
+ if (parsed.sizeBytes > MAX_ATTACHMENT_BYTES) {
8614
+ screen.notify(
8615
+ `image too large (${formatSize(parsed.sizeBytes)}, max ${formatSize(MAX_ATTACHMENT_BYTES)})`
8616
+ );
8617
+ continue;
8618
+ }
8619
+ dispatcher.addAttachment({
8620
+ mimeType: parsed.mimeType,
8621
+ data: parsed.data,
8622
+ name: "pasted image",
8623
+ sizeBytes: parsed.sizeBytes
8624
+ });
8625
+ added++;
8626
+ continue;
8627
+ }
8628
+ const mimeType = mimeFromExtension(token);
8584
8629
  if (!mimeType) {
8585
- screen.notify(`unsupported image type: ${path11.basename(p)}`);
8630
+ screen.notify(`unsupported image type: ${path11.basename(token)}`);
8586
8631
  continue;
8587
8632
  }
8588
8633
  try {
8589
- const buf = await fs15.readFile(p);
8634
+ const buf = await fs15.readFile(token);
8590
8635
  if (buf.length > MAX_ATTACHMENT_BYTES) {
8591
8636
  screen.notify(
8592
8637
  `image too large (${formatSize(buf.length)}, max ${formatSize(MAX_ATTACHMENT_BYTES)})`
@@ -8596,12 +8641,14 @@ async function runSession(term, config, opts, exitHint) {
8596
8641
  dispatcher.addAttachment({
8597
8642
  mimeType,
8598
8643
  data: buf.toString("base64"),
8599
- name: path11.basename(p),
8644
+ name: path11.basename(token),
8600
8645
  sizeBytes: buf.length
8601
8646
  });
8602
8647
  added++;
8603
8648
  } catch (err) {
8604
- screen.notify(`cannot read ${path11.basename(p)}: ${err.message}`);
8649
+ screen.notify(
8650
+ `cannot read ${path11.basename(token)}: ${err.message}`
8651
+ );
8605
8652
  }
8606
8653
  }
8607
8654
  if (added > 0) {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@hydra-acp/cli",
3
- "version": "0.1.13",
3
+ "version": "0.1.14",
4
4
  "description": "Multi-client ACP session daemon: spawn agents, attach over WSS, multiplex sessions across editors.",
5
5
  "license": "MIT",
6
6
  "type": "module",