@hydra-acp/cli 0.1.13 → 0.1.15
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.
- package/dist/cli.js +137 -23
- package/package.json +3 -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 = "
|
|
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
|
|
|
@@ -6093,9 +6118,9 @@ var init_screen = __esm({
|
|
|
6093
6118
|
wrapOne(line, width) {
|
|
6094
6119
|
const id = this.lineIds.get(line);
|
|
6095
6120
|
if (id !== void 0) {
|
|
6096
|
-
const
|
|
6097
|
-
if (
|
|
6098
|
-
return
|
|
6121
|
+
const cached2 = this.wrapCache.get(id);
|
|
6122
|
+
if (cached2) {
|
|
6123
|
+
return cached2;
|
|
6099
6124
|
}
|
|
6100
6125
|
}
|
|
6101
6126
|
const prefix = line.prefix ?? "";
|
|
@@ -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
|
-
|
|
6888
|
-
|
|
6889
|
-
|
|
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 (
|
|
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
|
|
8583
|
-
|
|
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(
|
|
8630
|
+
screen.notify(`unsupported image type: ${path11.basename(token)}`);
|
|
8586
8631
|
continue;
|
|
8587
8632
|
}
|
|
8588
8633
|
try {
|
|
8589
|
-
const buf = await fs15.readFile(
|
|
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(
|
|
8644
|
+
name: path11.basename(token),
|
|
8600
8645
|
sizeBytes: buf.length
|
|
8601
8646
|
});
|
|
8602
8647
|
added++;
|
|
8603
8648
|
} catch (err) {
|
|
8604
|
-
screen.notify(
|
|
8649
|
+
screen.notify(
|
|
8650
|
+
`cannot read ${path11.basename(token)}: ${err.message}`
|
|
8651
|
+
);
|
|
8605
8652
|
}
|
|
8606
8653
|
}
|
|
8607
8654
|
if (added > 0) {
|
|
@@ -13667,7 +13714,55 @@ function injectHydraMeta(msg, additions) {
|
|
|
13667
13714
|
};
|
|
13668
13715
|
}
|
|
13669
13716
|
|
|
13717
|
+
// src/core/update-check.ts
|
|
13718
|
+
init_hydra_version();
|
|
13719
|
+
var PKG_NAME = "@hydra-acp/cli";
|
|
13720
|
+
var cached;
|
|
13721
|
+
function disabled() {
|
|
13722
|
+
if (process.env.NO_UPDATE_NOTIFIER === "1") {
|
|
13723
|
+
return true;
|
|
13724
|
+
}
|
|
13725
|
+
if (process.argv.includes("--no-update-notifier")) {
|
|
13726
|
+
return true;
|
|
13727
|
+
}
|
|
13728
|
+
return false;
|
|
13729
|
+
}
|
|
13730
|
+
async function getPendingUpdate() {
|
|
13731
|
+
if (cached !== void 0) {
|
|
13732
|
+
return cached;
|
|
13733
|
+
}
|
|
13734
|
+
if (disabled()) {
|
|
13735
|
+
cached = null;
|
|
13736
|
+
return cached;
|
|
13737
|
+
}
|
|
13738
|
+
try {
|
|
13739
|
+
const mod = await import("update-notifier");
|
|
13740
|
+
const updateNotifier = mod.default ?? mod;
|
|
13741
|
+
const notifier = updateNotifier({
|
|
13742
|
+
pkg: { name: PKG_NAME, version: HYDRA_VERSION },
|
|
13743
|
+
updateCheckInterval: 1e3 * 60 * 60 * 24
|
|
13744
|
+
});
|
|
13745
|
+
const u = notifier.update;
|
|
13746
|
+
if (u && typeof u.latest === "string" && typeof u.current === "string" && u.latest !== u.current) {
|
|
13747
|
+
cached = {
|
|
13748
|
+
current: u.current,
|
|
13749
|
+
latest: u.latest,
|
|
13750
|
+
type: typeof u.type === "string" ? u.type : "unknown"
|
|
13751
|
+
};
|
|
13752
|
+
} else {
|
|
13753
|
+
cached = null;
|
|
13754
|
+
}
|
|
13755
|
+
} catch {
|
|
13756
|
+
cached = null;
|
|
13757
|
+
}
|
|
13758
|
+
return cached;
|
|
13759
|
+
}
|
|
13760
|
+
function formatUpdateNoticeLine(info) {
|
|
13761
|
+
return `hydra-acp ${info.latest} available (current ${info.current}) \xB7 run: npm update -g ${PKG_NAME}`;
|
|
13762
|
+
}
|
|
13763
|
+
|
|
13670
13764
|
// src/cli.ts
|
|
13765
|
+
var suppressUpdateNotice = false;
|
|
13671
13766
|
async function main() {
|
|
13672
13767
|
const argv = process.argv.slice(2);
|
|
13673
13768
|
const launchIdx = argv.indexOf("launch");
|
|
@@ -13699,6 +13794,7 @@ async function main() {
|
|
|
13699
13794
|
const sessionId2 = typeof flags2.resume === "string" ? flags2.resume : resolveOption(flags2, "session-id");
|
|
13700
13795
|
const name2 = resolveOption(flags2, "name");
|
|
13701
13796
|
const model2 = resolveOption(flags2, "model");
|
|
13797
|
+
suppressUpdateNotice = true;
|
|
13702
13798
|
await runShim({ sessionId: sessionId2, agentId, agentArgs, name: name2, model: model2 });
|
|
13703
13799
|
return;
|
|
13704
13800
|
}
|
|
@@ -13723,6 +13819,7 @@ async function main() {
|
|
|
13723
13819
|
const model = resolveOption(flags, "model");
|
|
13724
13820
|
if (!subcommand) {
|
|
13725
13821
|
if (process.stdout.isTTY) {
|
|
13822
|
+
suppressUpdateNotice = true;
|
|
13726
13823
|
await dispatchTui(flags, {
|
|
13727
13824
|
sessionId,
|
|
13728
13825
|
agentId: agentIdFromFlag,
|
|
@@ -13731,11 +13828,13 @@ async function main() {
|
|
|
13731
13828
|
});
|
|
13732
13829
|
return;
|
|
13733
13830
|
}
|
|
13831
|
+
suppressUpdateNotice = true;
|
|
13734
13832
|
await runShim({ sessionId, name, agentId: agentIdFromFlag, model });
|
|
13735
13833
|
return;
|
|
13736
13834
|
}
|
|
13737
13835
|
switch (subcommand) {
|
|
13738
13836
|
case "shim":
|
|
13837
|
+
suppressUpdateNotice = true;
|
|
13739
13838
|
await runShim({ sessionId, name, agentId: agentIdFromFlag, model });
|
|
13740
13839
|
return;
|
|
13741
13840
|
case "init":
|
|
@@ -13858,6 +13957,7 @@ async function main() {
|
|
|
13858
13957
|
return;
|
|
13859
13958
|
}
|
|
13860
13959
|
case "tui":
|
|
13960
|
+
suppressUpdateNotice = true;
|
|
13861
13961
|
await dispatchTui(flags, {
|
|
13862
13962
|
sessionId,
|
|
13863
13963
|
agentId: agentIdFromFlag,
|
|
@@ -13960,8 +14060,22 @@ function printHelp() {
|
|
|
13960
14060
|
].join("\n")
|
|
13961
14061
|
);
|
|
13962
14062
|
}
|
|
13963
|
-
|
|
14063
|
+
async function maybePrintUpdateNotice() {
|
|
14064
|
+
if (suppressUpdateNotice) {
|
|
14065
|
+
return;
|
|
14066
|
+
}
|
|
14067
|
+
try {
|
|
14068
|
+
const info = await getPendingUpdate();
|
|
14069
|
+
if (info) {
|
|
14070
|
+
process.stderr.write(`\u2728 ${formatUpdateNoticeLine(info)}
|
|
14071
|
+
`);
|
|
14072
|
+
}
|
|
14073
|
+
} catch {
|
|
14074
|
+
}
|
|
14075
|
+
}
|
|
14076
|
+
main().then(maybePrintUpdateNotice).catch(async (err) => {
|
|
13964
14077
|
process.stderr.write(`hydra-acp: ${err.message}
|
|
13965
14078
|
`);
|
|
14079
|
+
await maybePrintUpdateNotice();
|
|
13966
14080
|
process.exit(1);
|
|
13967
14081
|
});
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@hydra-acp/cli",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.15",
|
|
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",
|
|
@@ -61,6 +61,7 @@
|
|
|
61
61
|
"string-width": "^8.2.1",
|
|
62
62
|
"strip-ansi": "^7.2.0",
|
|
63
63
|
"terminal-kit": "^3.1.2",
|
|
64
|
+
"update-notifier": "^7.3.1",
|
|
64
65
|
"wrap-ansi": "^10.0.0",
|
|
65
66
|
"ws": "^8.18.0",
|
|
66
67
|
"zod": "^3.23.0"
|
|
@@ -68,6 +69,7 @@
|
|
|
68
69
|
"devDependencies": {
|
|
69
70
|
"@types/node": "^22.0.0",
|
|
70
71
|
"@types/terminal-kit": "^2.5.7",
|
|
72
|
+
"@types/update-notifier": "^6.0.8",
|
|
71
73
|
"@types/ws": "^8.5.0",
|
|
72
74
|
"tsup": "^8.0.0",
|
|
73
75
|
"tsx": "^4.0.0",
|