@pushary/agent-hooks 1.7.1 → 1.7.2
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/CHANGELOG.md +17 -0
- package/dist/bin/pushary-bell-hook.js +23 -23
- package/dist/bin/pushary-bell.js +10 -10
- package/dist/bin/pushary-claude.js +46 -35
- package/dist/bin/pushary-clean.js +107 -60
- package/dist/bin/pushary-codex-bridge.js +18 -17
- package/dist/bin/pushary-codex-hook.js +53 -39
- package/dist/bin/pushary-codex.js +14 -12
- package/dist/bin/pushary-connect.js +16 -16
- package/dist/bin/pushary-cowork.js +5 -5
- package/dist/bin/pushary-daemon.js +27 -27
- package/dist/bin/pushary-disconnect.js +19 -17
- package/dist/bin/pushary-doctor.js +63 -35
- package/dist/bin/pushary-elicitation-hook.js +35 -26
- package/dist/bin/pushary-gemini-bridge.js +12 -12
- package/dist/bin/pushary-gemini-hook.js +47 -32
- package/dist/bin/pushary-hook.js +34 -32
- package/dist/bin/pushary-login.js +16 -16
- package/dist/bin/pushary-logout.js +8 -8
- package/dist/bin/pushary-mcp.js +9 -8
- package/dist/bin/pushary-mode.js +10 -10
- package/dist/bin/pushary-notification-hook.js +29 -27
- package/dist/bin/pushary-opencode-hook.js +46 -32
- package/dist/bin/pushary-permission-denied-hook.js +34 -32
- package/dist/bin/pushary-permission-hook.js +33 -31
- package/dist/bin/pushary-post-hook.js +29 -27
- package/dist/bin/pushary-prompt-hook.js +29 -27
- package/dist/bin/pushary-session-end-hook.js +29 -27
- package/dist/bin/pushary-session-start-hook.js +33 -31
- package/dist/bin/pushary-setup.js +69 -56
- package/dist/bin/pushary-stats.js +5 -5
- package/dist/bin/pushary-status.js +19 -19
- package/dist/bin/pushary-stop-hook.js +29 -27
- package/dist/bin/pushary-stopfailure-hook.js +29 -27
- package/dist/bin/pushary-suggestions.js +5 -5
- package/dist/bin/pushary-transcript-register.js +19 -19
- package/dist/bin/pushary-transcripts.js +7 -7
- package/dist/bin/pushary-upgrade.js +20 -20
- package/dist/bin/pushary-wait.js +10 -10
- package/dist/bin/pushary.js +6 -6
- package/dist/{chunk-WM3U2RUK.js → chunk-2B4XCMH6.js} +75 -232
- package/dist/{chunk-ZIIYTQHC.js → chunk-2XOHXZRC.js} +12 -4
- package/dist/{chunk-3QE3BHBW.js → chunk-3NSRL5E7.js} +2 -2
- package/dist/{chunk-7GI6QC3M.js → chunk-3RO2UWJQ.js} +2 -2
- package/dist/{chunk-AAGLDXH4.js → chunk-4S7CCOXB.js} +5 -5
- package/dist/{chunk-6SJQ442W.js → chunk-5GIBNUBD.js} +2 -2
- package/dist/chunk-5OP5MQI7.js +45 -0
- package/dist/{chunk-EIZW73P5.js → chunk-65RN6ZCO.js} +1 -1
- package/dist/{chunk-6PV2JQ64.js → chunk-6NHXKTQU.js} +2 -2
- package/dist/{chunk-KSNAAMU5.js → chunk-6QZK4O36.js} +4 -4
- package/dist/{chunk-WZWXBTRF.js → chunk-A6WQF7FQ.js} +3 -3
- package/dist/{chunk-62TEPRWQ.js → chunk-AWZNDM3B.js} +1 -1
- package/dist/{chunk-NQFGVAT6.js → chunk-D4OGEWLH.js} +19 -2
- package/dist/{chunk-SVEMF2VO.js → chunk-E3PLF7YB.js} +4 -4
- package/dist/{chunk-MCNS4725.js → chunk-F6BMJOSW.js} +1 -1
- package/dist/{chunk-P5CBNSYL.js → chunk-HOIGXMI7.js} +1 -1
- package/dist/{chunk-XMN37YJH.js → chunk-I7B2DNVU.js} +1 -1
- package/dist/{chunk-ZEMSCGDD.js → chunk-INR3RVQ3.js} +8 -3
- package/dist/{chunk-3QORH5EJ.js → chunk-IZVAVXHQ.js} +6 -4
- package/dist/{chunk-MWVCDP64.js → chunk-JMSB6CJT.js} +1 -1
- package/dist/{chunk-WSC53O7I.js → chunk-KAJT6HPI.js} +3 -3
- package/dist/{chunk-XPMOCJHN.js → chunk-KLXYMPTM.js} +1 -1
- package/dist/{chunk-XDASEYRS.js → chunk-L6IF4JOF.js} +3 -3
- package/dist/{chunk-UPKP67TA.js → chunk-LI3C2IQY.js} +2 -2
- package/dist/{chunk-H6JV44TE.js → chunk-M2JGLFFS.js} +1 -1
- package/dist/chunk-MY3UZO5U.js +99 -0
- package/dist/chunk-N6IOSZOE.js +185 -0
- package/dist/{chunk-454KMJHF.js → chunk-NYBZJ44G.js} +34 -1
- package/dist/{chunk-QPR33SHS.js → chunk-OJRB5QKN.js} +6 -6
- package/dist/{chunk-3T35OE7C.js → chunk-OXEF6JHD.js} +4 -4
- package/dist/{chunk-SNWNA3MQ.js → chunk-PWNQGITG.js} +1 -1
- package/dist/{chunk-XPTCPU6V.js → chunk-Q7CDBJXU.js} +1 -1
- package/dist/{chunk-OTZHT34O.js → chunk-QSZ37ROP.js} +1 -1
- package/dist/{chunk-O5JD7UI5.js → chunk-R7ZETVNR.js} +1 -1
- package/dist/{chunk-4C4NRDIC.js → chunk-RLRDPZG4.js} +1 -1
- package/dist/{chunk-IGBDOZUO.js → chunk-SEIZQZEE.js} +1 -1
- package/dist/{chunk-OAL44FM2.js → chunk-SJN64NJX.js} +1 -1
- package/dist/{chunk-NID4UZDN.js → chunk-SKEW3TQX.js} +1 -1
- package/dist/{chunk-NAAZCNKI.js → chunk-SKMWPXGV.js} +351 -37
- package/dist/{chunk-KBLIVEFJ.js → chunk-T3PRPFDY.js} +5 -5
- package/dist/{chunk-2FU43B5Q.js → chunk-TVJYGZXB.js} +2 -2
- package/dist/{chunk-Y6GKOZBT.js → chunk-U3MS6D5X.js} +1 -1
- package/dist/{chunk-O5PRIYFZ.js → chunk-U4TMAANR.js} +3 -0
- package/dist/{chunk-JTQDP4ZL.js → chunk-UFNBKYWT.js} +3 -3
- package/dist/{chunk-42XR73I2.js → chunk-UUTWHVSV.js} +35 -35
- package/dist/{chunk-43SSQCWO.js → chunk-VQDJ6KB3.js} +3 -3
- package/dist/{chunk-YZKS3ME3.js → chunk-VSGKQ3HI.js} +2 -2
- package/dist/{chunk-XFNVG3OV.js → chunk-WWTLAZQA.js} +24 -7
- package/dist/{chunk-VCMFKZON.js → chunk-WXIVUIXA.js} +2 -2
- package/dist/{chunk-AHWJHLG5.js → chunk-YLCSKVQQ.js} +7 -5
- package/dist/{chunk-Q7QRR6YL.js → chunk-YNJ2H2FD.js} +2 -2
- package/dist/{chunk-BYVB3RX3.js → chunk-YU4222G2.js} +2 -2
- package/dist/{chunk-YQN7S57T.js → chunk-YU54LNC6.js} +6 -6
- package/dist/{chunk-7GYGVQBU.js → chunk-ZMWX5SDA.js} +8 -8
- package/dist/{chunk-55RO62FV.js → chunk-ZUKZJQGR.js} +1 -1
- package/dist/{reapply-66GQIBXN.js → reapply-D6RSDYCK.js} +9 -9
- package/dist/src/index.d.ts +1 -0
- package/dist/src/index.js +22 -20
- package/package.json +2 -1
- package/dist/chunk-JMBG47WV.js +0 -336
- package/dist/chunk-YHG74UFF.js +0 -12
|
@@ -1,30 +1,42 @@
|
|
|
1
|
+
import {
|
|
2
|
+
DEFAULT_SESSION,
|
|
3
|
+
isDefaultSession,
|
|
4
|
+
listPendingQuestions,
|
|
5
|
+
listPendingQuestionsForToolUse,
|
|
6
|
+
markPendingCommandDelivered,
|
|
7
|
+
readPendingCommand,
|
|
8
|
+
removePendingCommand,
|
|
9
|
+
removePendingQuestion,
|
|
10
|
+
removePendingSession,
|
|
11
|
+
savePendingCommand
|
|
12
|
+
} from "./chunk-N6IOSZOE.js";
|
|
1
13
|
import {
|
|
2
14
|
NOTIFICATION_PUSH_TYPES,
|
|
3
15
|
POSTTOOLUSE_MIRROR_ONLY_TOOLS
|
|
4
|
-
} from "./chunk-
|
|
16
|
+
} from "./chunk-RLRDPZG4.js";
|
|
5
17
|
import {
|
|
6
18
|
cancelQuestion,
|
|
7
19
|
isPolicyConfig,
|
|
8
20
|
sendNotification,
|
|
9
21
|
waitForAnswer
|
|
10
|
-
} from "./chunk-
|
|
22
|
+
} from "./chunk-2XOHXZRC.js";
|
|
11
23
|
import {
|
|
12
24
|
clientErrorKindOf,
|
|
13
25
|
reportClientError
|
|
14
|
-
} from "./chunk-
|
|
26
|
+
} from "./chunk-6QZK4O36.js";
|
|
15
27
|
import {
|
|
16
28
|
withRetry
|
|
17
|
-
} from "./chunk-
|
|
29
|
+
} from "./chunk-D4OGEWLH.js";
|
|
18
30
|
import {
|
|
19
31
|
getMachineId
|
|
20
|
-
} from "./chunk-
|
|
32
|
+
} from "./chunk-HOIGXMI7.js";
|
|
21
33
|
import {
|
|
22
34
|
reportedInstallSource
|
|
23
|
-
} from "./chunk-
|
|
35
|
+
} from "./chunk-LI3C2IQY.js";
|
|
24
36
|
import {
|
|
25
37
|
getApiKey,
|
|
26
38
|
getBaseUrl
|
|
27
|
-
} from "./chunk-
|
|
39
|
+
} from "./chunk-SJN64NJX.js";
|
|
28
40
|
import {
|
|
29
41
|
ACTION_BODY_MAX,
|
|
30
42
|
AGENT_LABELS_BY_TYPE,
|
|
@@ -48,7 +60,7 @@ import {
|
|
|
48
60
|
resolveAutoResolveOrigin,
|
|
49
61
|
resolvePolicy,
|
|
50
62
|
toToolLookup
|
|
51
|
-
} from "./chunk-
|
|
63
|
+
} from "./chunk-WWTLAZQA.js";
|
|
52
64
|
|
|
53
65
|
// src/policy.ts
|
|
54
66
|
import { createHash } from "crypto";
|
|
@@ -865,190 +877,19 @@ var codexReviewerDenialsSince = (reviews, since) => {
|
|
|
865
877
|
});
|
|
866
878
|
};
|
|
867
879
|
|
|
868
|
-
// src/pending.ts
|
|
869
|
-
import { join as join2 } from "path";
|
|
870
|
-
import { homedir, tmpdir as tmpdir2 } from "os";
|
|
871
|
-
import { createHash as createHash2 } from "crypto";
|
|
872
|
-
import { existsSync as existsSync2, mkdirSync, writeFileSync as writeFileSync2, readFileSync as readFileSync2, readdirSync, renameSync, unlinkSync, rmSync, statSync } from "fs";
|
|
873
|
-
var PENDING_DIR = join2(tmpdir2(), "pushary-pending");
|
|
874
|
-
var commandRoot = () => process.env.PUSHARY_COMMAND_DIR?.trim() || join2(homedir(), ".pushary", "run", "commands");
|
|
875
|
-
var DEFAULT_SESSION = "_no_session";
|
|
876
|
-
var GRACE_MS = 10 * 60 * 1e3;
|
|
877
|
-
var sanitize = (sessionId) => sessionId.replace(/[^A-Za-z0-9_-]/g, "_").slice(0, 128) || DEFAULT_SESSION;
|
|
878
|
-
var dirFor = (sessionId) => join2(PENDING_DIR, sanitize(sessionId));
|
|
879
|
-
var commandDirFor = (sessionId, namespace = "") => join2(
|
|
880
|
-
commandRoot(),
|
|
881
|
-
createHash2("sha256").update(namespace).digest("hex").slice(0, 16),
|
|
882
|
-
sanitize(sessionId)
|
|
883
|
-
);
|
|
884
|
-
var legacyCommandFile = (sessionId, namespace = "") => join2(commandDirFor(sessionId, namespace), "command.json");
|
|
885
|
-
var commandFile = (sessionId, id, namespace = "") => join2(commandDirFor(sessionId, namespace), `${createHash2("sha256").update(id).digest("hex")}.json`);
|
|
886
|
-
var readCommandFile = (file) => {
|
|
887
|
-
try {
|
|
888
|
-
const value = JSON.parse(readFileSync2(file, "utf-8"));
|
|
889
|
-
if (typeof value.id !== "string" || typeof value.text !== "string" || typeof value.expiresAtMs !== "number") return null;
|
|
890
|
-
if (value.expiresAtMs <= Date.now()) {
|
|
891
|
-
unlinkSync(file);
|
|
892
|
-
return null;
|
|
893
|
-
}
|
|
894
|
-
return {
|
|
895
|
-
...value,
|
|
896
|
-
delivered: value.delivered === true,
|
|
897
|
-
...value.failed === true ? { failed: true } : {}
|
|
898
|
-
};
|
|
899
|
-
} catch {
|
|
900
|
-
return null;
|
|
901
|
-
}
|
|
902
|
-
};
|
|
903
|
-
var readPendingCommandById = (sessionId, id, namespace = "") => {
|
|
904
|
-
const current = readCommandFile(commandFile(sessionId, id, namespace));
|
|
905
|
-
if (current?.id === id) return current;
|
|
906
|
-
const legacy = readCommandFile(legacyCommandFile(sessionId, namespace));
|
|
907
|
-
return legacy?.id === id ? legacy : null;
|
|
908
|
-
};
|
|
909
|
-
var pruneExpiredCommands = (dir) => {
|
|
910
|
-
let files;
|
|
911
|
-
try {
|
|
912
|
-
files = readdirSync(dir).filter((file) => file.endsWith(".json"));
|
|
913
|
-
} catch {
|
|
914
|
-
return [];
|
|
915
|
-
}
|
|
916
|
-
return files.flatMap((file) => {
|
|
917
|
-
const command = readCommandFile(join2(dir, file));
|
|
918
|
-
return command ? [command] : [];
|
|
919
|
-
});
|
|
920
|
-
};
|
|
921
|
-
var pruneExpiredCommandStore = () => {
|
|
922
|
-
let namespaces;
|
|
923
|
-
try {
|
|
924
|
-
namespaces = readdirSync(commandRoot(), { withFileTypes: true });
|
|
925
|
-
} catch {
|
|
926
|
-
return;
|
|
927
|
-
}
|
|
928
|
-
for (const namespace of namespaces.filter((entry) => entry.isDirectory())) {
|
|
929
|
-
const namespaceDir = join2(commandRoot(), namespace.name);
|
|
930
|
-
let sessions;
|
|
931
|
-
try {
|
|
932
|
-
sessions = readdirSync(namespaceDir, { withFileTypes: true });
|
|
933
|
-
} catch {
|
|
934
|
-
continue;
|
|
935
|
-
}
|
|
936
|
-
for (const session of sessions.filter((entry) => entry.isDirectory())) {
|
|
937
|
-
pruneExpiredCommands(join2(namespaceDir, session.name));
|
|
938
|
-
}
|
|
939
|
-
}
|
|
940
|
-
};
|
|
941
|
-
var readPendingCommand = (sessionId, namespace = "") => {
|
|
942
|
-
const commands = pruneExpiredCommands(commandDirFor(sessionId, namespace));
|
|
943
|
-
return commands.find((command) => !command.delivered && !command.failed) ?? commands[0] ?? null;
|
|
944
|
-
};
|
|
945
|
-
var savePendingCommand = (sessionId, command, namespace = "") => {
|
|
946
|
-
const dir = commandDirFor(sessionId, namespace);
|
|
947
|
-
try {
|
|
948
|
-
mkdirSync(dir, { recursive: true, mode: 448 });
|
|
949
|
-
pruneExpiredCommandStore();
|
|
950
|
-
if (readPendingCommandById(sessionId, command.id, namespace)) return false;
|
|
951
|
-
writeFileSync2(commandFile(sessionId, command.id, namespace), JSON.stringify(command), { encoding: "utf-8", mode: 384, flag: "wx" });
|
|
952
|
-
return true;
|
|
953
|
-
} catch {
|
|
954
|
-
return false;
|
|
955
|
-
}
|
|
956
|
-
};
|
|
957
|
-
var updatePendingCommand = (sessionId, id, update, namespace = "") => {
|
|
958
|
-
const command = readPendingCommandById(sessionId, id, namespace);
|
|
959
|
-
if (!command) return false;
|
|
960
|
-
const currentFile = commandFile(sessionId, id, namespace);
|
|
961
|
-
const file = existsSync2(currentFile) ? currentFile : legacyCommandFile(sessionId, namespace);
|
|
962
|
-
const temporary = `${file}.${process.pid}.tmp`;
|
|
963
|
-
try {
|
|
964
|
-
writeFileSync2(temporary, JSON.stringify({ ...command, ...update, text: "" }), { encoding: "utf-8", mode: 384 });
|
|
965
|
-
renameSync(temporary, file);
|
|
966
|
-
return true;
|
|
967
|
-
} catch {
|
|
968
|
-
try {
|
|
969
|
-
unlinkSync(temporary);
|
|
970
|
-
} catch {
|
|
971
|
-
}
|
|
972
|
-
return false;
|
|
973
|
-
}
|
|
974
|
-
};
|
|
975
|
-
var markPendingCommandDelivered = (sessionId, id, namespace = "") => updatePendingCommand(sessionId, id, { delivered: true, failed: void 0 }, namespace);
|
|
976
|
-
var markPendingCommandFailed = (sessionId, id, namespace = "") => updatePendingCommand(sessionId, id, { delivered: false, failed: true }, namespace);
|
|
977
|
-
var removePendingCommand = (sessionId, id, namespace = "") => {
|
|
978
|
-
if (!readPendingCommandById(sessionId, id, namespace)) return;
|
|
979
|
-
try {
|
|
980
|
-
unlinkSync(commandFile(sessionId, id, namespace));
|
|
981
|
-
} catch {
|
|
982
|
-
}
|
|
983
|
-
try {
|
|
984
|
-
if (readCommandFile(legacyCommandFile(sessionId, namespace))?.id === id) {
|
|
985
|
-
unlinkSync(legacyCommandFile(sessionId, namespace));
|
|
986
|
-
}
|
|
987
|
-
} catch {
|
|
988
|
-
}
|
|
989
|
-
};
|
|
990
|
-
var isDefaultSession = (sessionId) => sanitize(sessionId) === DEFAULT_SESSION;
|
|
991
|
-
var listPendingQuestionsForToolUse = (sessionId, toolUseId) => {
|
|
992
|
-
if (!toolUseId) return [];
|
|
993
|
-
const dir = dirFor(sessionId);
|
|
994
|
-
let files;
|
|
995
|
-
try {
|
|
996
|
-
files = readdirSync(dir);
|
|
997
|
-
} catch {
|
|
998
|
-
return [];
|
|
999
|
-
}
|
|
1000
|
-
return files.filter((name) => {
|
|
1001
|
-
try {
|
|
1002
|
-
return readFileSync2(join2(dir, name), "utf-8") === toolUseId;
|
|
1003
|
-
} catch {
|
|
1004
|
-
return false;
|
|
1005
|
-
}
|
|
1006
|
-
});
|
|
1007
|
-
};
|
|
1008
|
-
var listPendingQuestions = (sessionId) => {
|
|
1009
|
-
const dir = dirFor(sessionId);
|
|
1010
|
-
let files;
|
|
1011
|
-
try {
|
|
1012
|
-
files = readdirSync(dir);
|
|
1013
|
-
} catch {
|
|
1014
|
-
return [];
|
|
1015
|
-
}
|
|
1016
|
-
if (!isDefaultSession(sessionId)) return files;
|
|
1017
|
-
const cutoff = Date.now() - GRACE_MS;
|
|
1018
|
-
return files.filter((name) => {
|
|
1019
|
-
try {
|
|
1020
|
-
return statSync(join2(dir, name)).mtimeMs < cutoff;
|
|
1021
|
-
} catch {
|
|
1022
|
-
return false;
|
|
1023
|
-
}
|
|
1024
|
-
});
|
|
1025
|
-
};
|
|
1026
|
-
var removePendingQuestion = (sessionId, correlationId) => {
|
|
1027
|
-
try {
|
|
1028
|
-
unlinkSync(join2(dirFor(sessionId), correlationId));
|
|
1029
|
-
} catch {
|
|
1030
|
-
}
|
|
1031
|
-
};
|
|
1032
|
-
var removePendingSession = (sessionId) => {
|
|
1033
|
-
try {
|
|
1034
|
-
rmSync(dirFor(sessionId), { recursive: true, force: true });
|
|
1035
|
-
} catch {
|
|
1036
|
-
}
|
|
1037
|
-
};
|
|
1038
|
-
|
|
1039
880
|
// src/repo.ts
|
|
1040
|
-
import { existsSync as
|
|
1041
|
-
import { basename as basename2, dirname, isAbsolute as isAbsolute2, join as
|
|
881
|
+
import { existsSync as existsSync2, readFileSync as readFileSync2, statSync } from "fs";
|
|
882
|
+
import { basename as basename2, dirname, isAbsolute as isAbsolute2, join as join2, resolve as resolve2 } from "path";
|
|
1042
883
|
var MAX_PARENT_WALK = 64;
|
|
1043
884
|
var GIT_FILE_PREFIX = "gitdir:";
|
|
1044
885
|
var findGitDir = (startDir) => {
|
|
1045
886
|
let current = resolve2(startDir);
|
|
1046
887
|
for (let depth = 0; depth < MAX_PARENT_WALK; depth += 1) {
|
|
1047
|
-
const candidate =
|
|
888
|
+
const candidate = join2(current, ".git");
|
|
1048
889
|
try {
|
|
1049
|
-
if (
|
|
1050
|
-
if (
|
|
1051
|
-
const pointer =
|
|
890
|
+
if (existsSync2(candidate)) {
|
|
891
|
+
if (statSync(candidate).isDirectory()) return candidate;
|
|
892
|
+
const pointer = readFileSync2(candidate, "utf-8").trim();
|
|
1052
893
|
if (pointer.startsWith(GIT_FILE_PREFIX)) {
|
|
1053
894
|
const target = pointer.slice(GIT_FILE_PREFIX.length).trim();
|
|
1054
895
|
return isAbsolute2(target) ? target : resolve2(current, target);
|
|
@@ -1064,7 +905,7 @@ var findGitDir = (startDir) => {
|
|
|
1064
905
|
};
|
|
1065
906
|
var configPathFor = (gitDir) => {
|
|
1066
907
|
const index = gitDir.replace(/\\/g, "/").indexOf("/worktrees/");
|
|
1067
|
-
return index === -1 ?
|
|
908
|
+
return index === -1 ? join2(gitDir, "config") : join2(gitDir.slice(0, index), "config");
|
|
1068
909
|
};
|
|
1069
910
|
var ORIGIN_SECTION = /^\[remote "origin"\]/;
|
|
1070
911
|
var SECTION_HEADER = /^\[/;
|
|
@@ -1072,9 +913,9 @@ var URL_LINE = /^url\s*=\s*(.+)$/;
|
|
|
1072
913
|
var readOriginRemote = (gitDir) => {
|
|
1073
914
|
try {
|
|
1074
915
|
const configPath = configPathFor(gitDir);
|
|
1075
|
-
if (!
|
|
916
|
+
if (!existsSync2(configPath)) return void 0;
|
|
1076
917
|
let inOrigin = false;
|
|
1077
|
-
for (const rawLine of
|
|
918
|
+
for (const rawLine of readFileSync2(configPath, "utf-8").split("\n")) {
|
|
1078
919
|
const line = rawLine.trim();
|
|
1079
920
|
if (SECTION_HEADER.test(line)) {
|
|
1080
921
|
inOrigin = ORIGIN_SECTION.test(line);
|
|
@@ -1121,10 +962,10 @@ var repoKeyFor = (cwd) => {
|
|
|
1121
962
|
};
|
|
1122
963
|
|
|
1123
964
|
// src/usage.ts
|
|
1124
|
-
import { closeSync, mkdirSync
|
|
1125
|
-
import { createHash as
|
|
1126
|
-
import { join as
|
|
1127
|
-
import { tmpdir as
|
|
965
|
+
import { closeSync, mkdirSync, openSync, readFileSync as readFileSync3, readSync, statSync as statSync2, writeFileSync as writeFileSync2 } from "fs";
|
|
966
|
+
import { createHash as createHash2 } from "crypto";
|
|
967
|
+
import { join as join3 } from "path";
|
|
968
|
+
import { tmpdir as tmpdir2 } from "os";
|
|
1128
969
|
var DEFAULT_PRICES = [
|
|
1129
970
|
{ match: "opus-4-1", in: 15, out: 75 },
|
|
1130
971
|
{ match: "opus-4-0", in: 15, out: 75 },
|
|
@@ -1159,12 +1000,12 @@ var estimateCostUsd = (usage, model) => {
|
|
|
1159
1000
|
const perTokenOut = price.out / 1e6;
|
|
1160
1001
|
return usage.inputTokens * perTokenIn + usage.outputTokens * perTokenOut + usage.cacheCreationTokens * perTokenIn * CACHE_WRITE_MULTIPLIER + usage.cacheReadTokens * perTokenIn * CACHE_READ_MULTIPLIER;
|
|
1161
1002
|
};
|
|
1162
|
-
var stateDir = () => process.env.PUSHARY_USAGE_DIR?.trim() ||
|
|
1163
|
-
var stateFile = (sessionId) =>
|
|
1003
|
+
var stateDir = () => process.env.PUSHARY_USAGE_DIR?.trim() || join3(tmpdir2(), "pushary-usage");
|
|
1004
|
+
var stateFile = (sessionId) => join3(stateDir(), sessionId.replace(/[^a-zA-Z0-9_-]/g, "_"));
|
|
1164
1005
|
var emptyState = () => ({ offset: 0, tokensIn: 0, tokensOut: 0, costUsd: 0, recentIds: [] });
|
|
1165
1006
|
var readState = (path) => {
|
|
1166
1007
|
try {
|
|
1167
|
-
const parsed = JSON.parse(
|
|
1008
|
+
const parsed = JSON.parse(readFileSync3(path, "utf-8"));
|
|
1168
1009
|
if (typeof parsed.offset === "number" && parsed.offset >= 0 && typeof parsed.tokensIn === "number" && typeof parsed.tokensOut === "number" && typeof parsed.costUsd === "number" && Array.isArray(parsed.recentIds)) {
|
|
1169
1010
|
return {
|
|
1170
1011
|
offset: parsed.offset,
|
|
@@ -1239,7 +1080,7 @@ var extractUserText = (content) => {
|
|
|
1239
1080
|
};
|
|
1240
1081
|
var readLastUserPrompt = (transcriptPath) => {
|
|
1241
1082
|
try {
|
|
1242
|
-
const size =
|
|
1083
|
+
const size = statSync2(transcriptPath).size;
|
|
1243
1084
|
const start = Math.max(0, size - USER_PROMPT_TAIL_BYTES);
|
|
1244
1085
|
const lines = readRange(transcriptPath, start, size).toString("utf-8").split("\n");
|
|
1245
1086
|
for (let i = lines.length - 1; i >= 0; i -= 1) {
|
|
@@ -1262,7 +1103,7 @@ var readLastUserPrompt = (transcriptPath) => {
|
|
|
1262
1103
|
};
|
|
1263
1104
|
var readNewUsage = (transcriptPath, sessionId) => {
|
|
1264
1105
|
try {
|
|
1265
|
-
const file =
|
|
1106
|
+
const file = statSync2(transcriptPath);
|
|
1266
1107
|
const size = file.size;
|
|
1267
1108
|
const path = stateFile(sessionId);
|
|
1268
1109
|
let state = readState(path);
|
|
@@ -1280,14 +1121,14 @@ var readNewUsage = (transcriptPath, sessionId) => {
|
|
|
1280
1121
|
state.offset += lastNewline + 1;
|
|
1281
1122
|
}
|
|
1282
1123
|
}
|
|
1283
|
-
|
|
1284
|
-
|
|
1124
|
+
mkdirSync(stateDir(), { recursive: true });
|
|
1125
|
+
writeFileSync2(path, JSON.stringify(state), "utf-8");
|
|
1285
1126
|
if (state.tokensIn === 0 && state.tokensOut === 0) return null;
|
|
1286
1127
|
return {
|
|
1287
1128
|
// Identical cursor-range reports share an identity across transport retries.
|
|
1288
1129
|
// Native message identity distinguishes an in-place rotation of the range.
|
|
1289
1130
|
// This does not serialize readers of different, potentially overlapping ranges.
|
|
1290
|
-
eventId:
|
|
1131
|
+
eventId: createHash2("sha256").update(JSON.stringify([
|
|
1291
1132
|
sessionId,
|
|
1292
1133
|
file.dev,
|
|
1293
1134
|
file.ino,
|
|
@@ -1372,57 +1213,58 @@ var phoneDrivenEnv = (base) => ({
|
|
|
1372
1213
|
});
|
|
1373
1214
|
|
|
1374
1215
|
// src/throttle.ts
|
|
1375
|
-
import { join as
|
|
1376
|
-
import { tmpdir as
|
|
1377
|
-
import { createHash as
|
|
1378
|
-
import { existsSync as
|
|
1379
|
-
var THROTTLE_DIR =
|
|
1380
|
-
var markerPath = (key) =>
|
|
1216
|
+
import { join as join4 } from "path";
|
|
1217
|
+
import { tmpdir as tmpdir3 } from "os";
|
|
1218
|
+
import { createHash as createHash3 } from "crypto";
|
|
1219
|
+
import { existsSync as existsSync3, mkdirSync as mkdirSync2, statSync as statSync3, writeFileSync as writeFileSync3, rmSync } from "fs";
|
|
1220
|
+
var THROTTLE_DIR = join4(tmpdir3(), "pushary-throttle");
|
|
1221
|
+
var markerPath = (key) => join4(THROTTLE_DIR, createHash3("sha256").update(key).digest("hex").slice(0, 16));
|
|
1381
1222
|
var claimThrottle = (key, windowMs) => {
|
|
1382
1223
|
try {
|
|
1383
1224
|
const path = markerPath(key);
|
|
1384
|
-
if (
|
|
1385
|
-
|
|
1386
|
-
|
|
1225
|
+
if (existsSync3(path) && Date.now() - statSync3(path).mtimeMs < windowMs) return "throttled";
|
|
1226
|
+
mkdirSync2(THROTTLE_DIR, { recursive: true });
|
|
1227
|
+
writeFileSync3(path, "", "utf-8");
|
|
1387
1228
|
return "passed";
|
|
1388
1229
|
} catch {
|
|
1389
1230
|
return "unavailable";
|
|
1390
1231
|
}
|
|
1391
1232
|
};
|
|
1392
1233
|
var releaseThrottle = (key) => {
|
|
1393
|
-
|
|
1234
|
+
rmSync(markerPath(key), { force: true });
|
|
1394
1235
|
};
|
|
1395
1236
|
|
|
1396
1237
|
// src/events.ts
|
|
1397
|
-
import { basename as basename3, join as
|
|
1398
|
-
import { existsSync as
|
|
1399
|
-
import { tmpdir as
|
|
1400
|
-
var INTENT_DIR =
|
|
1238
|
+
import { basename as basename3, join as join5 } from "path";
|
|
1239
|
+
import { existsSync as existsSync4, mkdirSync as mkdirSync3, readFileSync as readFileSync4, statSync as statSync4, writeFileSync as writeFileSync4 } from "fs";
|
|
1240
|
+
import { tmpdir as tmpdir4 } from "os";
|
|
1241
|
+
var INTENT_DIR = join5(tmpdir4(), "pushary-intent");
|
|
1401
1242
|
var INTENT_MAX_BYTES = 2048;
|
|
1402
1243
|
var INTENT_GRACE_MS = 10 * 60 * 1e3;
|
|
1403
1244
|
var sanitizeSession = (sessionId) => sessionId.replace(/[^A-Za-z0-9_-]/g, "_").slice(0, 128) || DEFAULT_SESSION;
|
|
1404
|
-
var intentFile = (sessionId) =>
|
|
1245
|
+
var intentFile = (sessionId) => join5(INTENT_DIR, sanitizeSession(sessionId));
|
|
1405
1246
|
var saveLastPrompt = (sessionId, prompt) => {
|
|
1406
1247
|
try {
|
|
1407
1248
|
const trimmed = prompt.replace(/\s+/g, " ").trim().slice(0, INTENT_MAX_BYTES);
|
|
1408
1249
|
if (!trimmed) return;
|
|
1409
|
-
|
|
1410
|
-
|
|
1250
|
+
mkdirSync3(INTENT_DIR, { recursive: true });
|
|
1251
|
+
writeFileSync4(intentFile(sessionId), trimmed, "utf-8");
|
|
1411
1252
|
} catch {
|
|
1412
1253
|
}
|
|
1413
1254
|
};
|
|
1414
1255
|
var readLastPrompt = (sessionId) => {
|
|
1415
1256
|
try {
|
|
1416
1257
|
const path = intentFile(sessionId);
|
|
1417
|
-
if (isDefaultSession(sessionId) &&
|
|
1418
|
-
const value =
|
|
1258
|
+
if (isDefaultSession(sessionId) && statSync4(path).mtimeMs < Date.now() - INTENT_GRACE_MS) return void 0;
|
|
1259
|
+
const value = readFileSync4(path, "utf-8").trim();
|
|
1419
1260
|
return value.length > 0 ? value : void 0;
|
|
1420
1261
|
} catch {
|
|
1421
1262
|
return void 0;
|
|
1422
1263
|
}
|
|
1423
1264
|
};
|
|
1424
|
-
var pendingQuestionsToSettle = (sessionId, toolUseId) => {
|
|
1265
|
+
var pendingQuestionsToSettle = (sessionId, toolUseId, insideSubagent = false) => {
|
|
1425
1266
|
const settledElsewhere = toolUseId ? listPendingQuestionsForToolUse(sessionId, toolUseId) : [];
|
|
1267
|
+
if (insideSubagent) return settledElsewhere;
|
|
1426
1268
|
return [.../* @__PURE__ */ new Set([...settledElsewhere, ...listPendingQuestions(sessionId)])];
|
|
1427
1269
|
};
|
|
1428
1270
|
var reconcileQuestions = async (sessionId, files, signal) => {
|
|
@@ -1478,8 +1320,8 @@ var POLICY_CACHE_TTL_MS = 5 * 60 * 1e3;
|
|
|
1478
1320
|
var readFreshCachedPolicy = (apiKey, agentType, sessionId) => {
|
|
1479
1321
|
const request = policyRequestFor(agentType);
|
|
1480
1322
|
const path = policyCacheFile(apiKey, request.agent, request.repoAware);
|
|
1481
|
-
if (!
|
|
1482
|
-
const cached = JSON.parse(
|
|
1323
|
+
if (!existsSync4(path)) return null;
|
|
1324
|
+
const cached = JSON.parse(readFileSync4(path, "utf-8"));
|
|
1483
1325
|
if (!isPolicyConfig(cached)) return null;
|
|
1484
1326
|
if ((cached._sessionId ?? null) !== (sessionId ?? null)) return null;
|
|
1485
1327
|
if (!cached._cachedAt || Date.now() - cached._cachedAt >= POLICY_CACHE_TTL_MS) return null;
|
|
@@ -1575,7 +1417,7 @@ var reportEvent = async (event, options = {}) => {
|
|
|
1575
1417
|
const machineId = event.machineId ?? getMachineId();
|
|
1576
1418
|
const sessionKey = event.sessionId || DEFAULT_SESSION;
|
|
1577
1419
|
const receiptNamespace = `${apiKey}:${machineId}:${event.agentType}`;
|
|
1578
|
-
const clientCanDrain = consumesActivityContext(event.agentType) && options.timeoutMs === void 0;
|
|
1420
|
+
const clientCanDrain = consumesActivityContext(event.agentType) && options.timeoutMs === void 0 && options.skipDrain !== true;
|
|
1579
1421
|
const deadlineMs = options.budgetMs === void 0 ? void 0 : Date.now() + options.budgetMs;
|
|
1580
1422
|
const ackReserveMs = deadlineMs === void 0 ? 0 : Math.min(ACK_RESERVE_MS, Math.floor((options.budgetMs ?? 0) * 0.4));
|
|
1581
1423
|
const postTimeoutMs = (fallback) => deadlineMs === void 0 ? fallback : Math.max(0, Math.min(fallback, deadlineMs - ackReserveMs - Date.now()));
|
|
@@ -1675,6 +1517,7 @@ var settleQuestionsForToolUse = async (sessionId, toolUseId) => {
|
|
|
1675
1517
|
const late = await reconcileQuestions(sessionId, listPendingQuestionsForToolUse(sessionId, toolUseId));
|
|
1676
1518
|
for (const answer of late) removePendingQuestion(sessionId, answer.correlationId);
|
|
1677
1519
|
};
|
|
1520
|
+
var ranInsideSubagent = (input) => sessionIdentityOf(input).parentSessionId !== void 0;
|
|
1678
1521
|
var handlePostToolUse = async (input, agent = CLAUDE_CODE_AGENT) => {
|
|
1679
1522
|
const occurredAt = (/* @__PURE__ */ new Date()).toISOString();
|
|
1680
1523
|
const deadline = Date.now() + HOOK_BUDGET_MS;
|
|
@@ -1687,9 +1530,11 @@ var handlePostToolUse = async (input, agent = CLAUDE_CODE_AGENT) => {
|
|
|
1687
1530
|
const isError = isToolResultError(toolResult);
|
|
1688
1531
|
const receiptsEnabled = process.env.PUSHARY_RECEIPTS !== "off";
|
|
1689
1532
|
const sessionKey = input.session_id || DEFAULT_SESSION;
|
|
1533
|
+
const insideSubagent = ranInsideSubagent(input);
|
|
1534
|
+
const questionsToSettle = pendingQuestionsToSettle(sessionKey, input.tool_use_id, insideSubagent);
|
|
1690
1535
|
const [liveMode, late] = await Promise.all([
|
|
1691
1536
|
fetchModeState(getApiKey(), input.session_id, MODE_REUSE_MS, signal),
|
|
1692
|
-
|
|
1537
|
+
reconcileQuestions(sessionKey, questionsToSettle, signal)
|
|
1693
1538
|
]);
|
|
1694
1539
|
let additionalContext;
|
|
1695
1540
|
if (late.length > 0 && agent.type === CLAUDE_CODE_AGENT.type) {
|
|
@@ -1712,7 +1557,12 @@ var handlePostToolUse = async (input, agent = CLAUDE_CODE_AGENT) => {
|
|
|
1712
1557
|
...beacon ? { decisionOrigin: beacon.decisionOrigin, toolName: beacon.toolName, toolTarget: beacon.toolTarget } : {},
|
|
1713
1558
|
meta: receiptsEnabled ? deriveReceiptMeta(lookup.tool, lookup.input, toolResult, input.cwd ?? process.cwd()) : void 0,
|
|
1714
1559
|
usage: deriveUsage(input.transcript_path, input.session_id)
|
|
1715
|
-
}, {
|
|
1560
|
+
}, {
|
|
1561
|
+
maxAttempts: 1,
|
|
1562
|
+
budgetMs: Math.min(DRAINING_REPORT_BUDGET_MS, Math.max(0, deadline - Date.now())),
|
|
1563
|
+
signal,
|
|
1564
|
+
skipDrain: insideSubagent
|
|
1565
|
+
});
|
|
1716
1566
|
const extraReports = [];
|
|
1717
1567
|
if (claimThrottle(`hookactive:${sessionKey}`, HOOK_ACTIVE_WINDOW_MS) === "passed") {
|
|
1718
1568
|
extraReports.push(
|
|
@@ -1992,13 +1842,6 @@ export {
|
|
|
1992
1842
|
isCodexGuardianRolloutHead,
|
|
1993
1843
|
scanCodexGuardianReviews,
|
|
1994
1844
|
codexReviewerDenialsSince,
|
|
1995
|
-
DEFAULT_SESSION,
|
|
1996
|
-
readPendingCommandById,
|
|
1997
|
-
readPendingCommand,
|
|
1998
|
-
savePendingCommand,
|
|
1999
|
-
markPendingCommandDelivered,
|
|
2000
|
-
markPendingCommandFailed,
|
|
2001
|
-
removePendingCommand,
|
|
2002
1845
|
repoKeyFor,
|
|
2003
1846
|
claimThrottle,
|
|
2004
1847
|
releaseThrottle,
|
|
@@ -1,16 +1,17 @@
|
|
|
1
1
|
import {
|
|
2
2
|
clientErrorKindOf,
|
|
3
3
|
reportClientError
|
|
4
|
-
} from "./chunk-
|
|
4
|
+
} from "./chunk-6QZK4O36.js";
|
|
5
5
|
import {
|
|
6
|
+
SubscriptionRequiredError,
|
|
6
7
|
callMcpTool
|
|
7
|
-
} from "./chunk-
|
|
8
|
+
} from "./chunk-D4OGEWLH.js";
|
|
8
9
|
import {
|
|
9
10
|
installNetworkDefaults
|
|
10
|
-
} from "./chunk-
|
|
11
|
+
} from "./chunk-UFNBKYWT.js";
|
|
11
12
|
import {
|
|
12
13
|
getBaseUrl
|
|
13
|
-
} from "./chunk-
|
|
14
|
+
} from "./chunk-SJN64NJX.js";
|
|
14
15
|
|
|
15
16
|
// src/api.ts
|
|
16
17
|
import { randomUUID } from "crypto";
|
|
@@ -53,6 +54,11 @@ var DECISION_STOP_REASON = "Approval was cancelled or became unavailable. Retry
|
|
|
53
54
|
var isDecisionStopped = (result) => result.handoffAction === "stop" || ["cancelled", "unavailable", "stopped", "missing"].includes(result.status ?? "");
|
|
54
55
|
var isLocalQuestionHandoff = (result) => result.suppressed === true || result.noDevices === true || result.status === "terminal" || result.status === "notified";
|
|
55
56
|
var STOPPED = { answered: false, handoffAction: "stop" };
|
|
57
|
+
var UNVERIFIABLE_APPROVAL_REASON = "Pushary could not create a verifiable approval. Retry the action.";
|
|
58
|
+
var unavailableQuestionUnlessSubscriptionRequired = (error) => {
|
|
59
|
+
if (error instanceof SubscriptionRequiredError) throw error;
|
|
60
|
+
return { correlationId: "", status: "unavailable" };
|
|
61
|
+
};
|
|
56
62
|
var askUser = async (apiKey, params, timeoutMs = 15e3) => {
|
|
57
63
|
const identified = params.toolUseId || params.requestId ? params : { ...params, requestId: randomUUID() };
|
|
58
64
|
const result = await callMcpTool(apiKey, "ask_user", { ...identified, wait: false }, { maxRetries: 3, timeoutMs });
|
|
@@ -156,6 +162,8 @@ export {
|
|
|
156
162
|
DECISION_STOP_REASON,
|
|
157
163
|
isDecisionStopped,
|
|
158
164
|
isLocalQuestionHandoff,
|
|
165
|
+
UNVERIFIABLE_APPROVAL_REASON,
|
|
166
|
+
unavailableQuestionUnlessSubscriptionRequired,
|
|
159
167
|
askUser,
|
|
160
168
|
waitForAnswer,
|
|
161
169
|
nextLongPollMs,
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import {
|
|
2
2
|
SETUP_FLAGS
|
|
3
|
-
} from "./chunk-
|
|
3
|
+
} from "./chunk-I7B2DNVU.js";
|
|
4
4
|
import {
|
|
5
5
|
parseFlags
|
|
6
6
|
} from "./chunk-GMXKITVA.js";
|
|
@@ -14,7 +14,7 @@ import {
|
|
|
14
14
|
CLAUDE_CONNECTOR_URL,
|
|
15
15
|
COWORK_CONNECTOR_LIMIT,
|
|
16
16
|
COWORK_STANDING_INSTRUCTIONS
|
|
17
|
-
} from "./chunk-
|
|
17
|
+
} from "./chunk-WWTLAZQA.js";
|
|
18
18
|
|
|
19
19
|
// src/cli/cowork.ts
|
|
20
20
|
import { readFileSync } from "fs";
|
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
import {
|
|
2
2
|
registerTranscript
|
|
3
|
-
} from "./chunk-
|
|
3
|
+
} from "./chunk-ZMWX5SDA.js";
|
|
4
4
|
import {
|
|
5
5
|
writeDegraded
|
|
6
|
-
} from "./chunk-
|
|
6
|
+
} from "./chunk-6QZK4O36.js";
|
|
7
7
|
|
|
8
8
|
// src/tool-hook-input.ts
|
|
9
9
|
var OPTIONAL_TEXT_FIELDS = ["hook_event_name", "session_id", "cwd", "transcript_path", "tool_use_id", "permission_mode"];
|
|
@@ -4,14 +4,14 @@ import {
|
|
|
4
4
|
} from "./chunk-XHKBHWLX.js";
|
|
5
5
|
import {
|
|
6
6
|
readControlMode
|
|
7
|
-
} from "./chunk-
|
|
7
|
+
} from "./chunk-VSGKQ3HI.js";
|
|
8
8
|
import {
|
|
9
9
|
getMachineId
|
|
10
|
-
} from "./chunk-
|
|
10
|
+
} from "./chunk-HOIGXMI7.js";
|
|
11
11
|
import {
|
|
12
12
|
pusharyDir,
|
|
13
13
|
resolveGlobalBinary
|
|
14
|
-
} from "./chunk-
|
|
14
|
+
} from "./chunk-NYBZJ44G.js";
|
|
15
15
|
import {
|
|
16
16
|
readJsonSafe,
|
|
17
17
|
writeFileAtomic,
|
|
@@ -20,10 +20,10 @@ import {
|
|
|
20
20
|
} from "./chunk-T7E75EKA.js";
|
|
21
21
|
import {
|
|
22
22
|
getApiKey
|
|
23
|
-
} from "./chunk-
|
|
23
|
+
} from "./chunk-SJN64NJX.js";
|
|
24
24
|
import {
|
|
25
25
|
getPackageVersion
|
|
26
|
-
} from "./chunk-
|
|
26
|
+
} from "./chunk-WWTLAZQA.js";
|
|
27
27
|
|
|
28
28
|
// src/daemon-lifecycle.ts
|
|
29
29
|
import { dirname, join, win32 as win32Path } from "path";
|
|
@@ -6,10 +6,10 @@ import {
|
|
|
6
6
|
codexHooksJsonIn,
|
|
7
7
|
isPusharyCodexCommand,
|
|
8
8
|
resolvePathBinary
|
|
9
|
-
} from "./chunk-
|
|
9
|
+
} from "./chunk-NYBZJ44G.js";
|
|
10
10
|
import {
|
|
11
11
|
getPackageVersion
|
|
12
|
-
} from "./chunk-
|
|
12
|
+
} from "./chunk-WWTLAZQA.js";
|
|
13
13
|
|
|
14
14
|
// src/codex-app-server.ts
|
|
15
15
|
import { existsSync, realpathSync } from "fs";
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
import {
|
|
2
|
+
DEFAULT_SESSION
|
|
3
|
+
} from "./chunk-N6IOSZOE.js";
|
|
4
|
+
|
|
5
|
+
// src/answer.ts
|
|
6
|
+
var denyReasonFrom = (value, note) => {
|
|
7
|
+
const trimmed = note?.trim();
|
|
8
|
+
if (trimmed) return `Denied from your phone: ${trimmed}`;
|
|
9
|
+
return value && value !== "no" && value !== "yes" ? `Denied from your phone: ${value}` : "Denied via push notification";
|
|
10
|
+
};
|
|
11
|
+
var isDeferAnswer = (value) => value === "defer";
|
|
12
|
+
|
|
13
|
+
// src/session-notice.ts
|
|
14
|
+
import { existsSync, writeFileSync } from "fs";
|
|
15
|
+
import { tmpdir } from "os";
|
|
16
|
+
import { join } from "path";
|
|
17
|
+
var SUBSCRIPTION_REQUIRED_NOTICE_KIND = "subscription-required";
|
|
18
|
+
var oncePerSession = (kind, sessionId) => {
|
|
19
|
+
try {
|
|
20
|
+
const key = (sessionId || DEFAULT_SESSION).replace(/[^a-zA-Z0-9_-]/g, "");
|
|
21
|
+
const marker = join(tmpdir(), `pushary-${kind}-${key}`);
|
|
22
|
+
if (existsSync(marker)) return false;
|
|
23
|
+
writeFileSync(marker, "1", "utf-8");
|
|
24
|
+
return true;
|
|
25
|
+
} catch {
|
|
26
|
+
return false;
|
|
27
|
+
}
|
|
28
|
+
};
|
|
29
|
+
var subscriptionRequiredNotice = (upgradeUrl) => `[pushary] Your Pushary workspace has no active subscription, so approvals stay with your agent. Subscribe: ${upgradeUrl}`;
|
|
30
|
+
var announceSubscriptionRequired = (upgradeUrl, sessionId) => {
|
|
31
|
+
try {
|
|
32
|
+
if (!oncePerSession(SUBSCRIPTION_REQUIRED_NOTICE_KIND, sessionId)) return;
|
|
33
|
+
process.stderr.write(`${subscriptionRequiredNotice(upgradeUrl)}
|
|
34
|
+
`);
|
|
35
|
+
} catch {
|
|
36
|
+
return;
|
|
37
|
+
}
|
|
38
|
+
};
|
|
39
|
+
|
|
40
|
+
export {
|
|
41
|
+
denyReasonFrom,
|
|
42
|
+
isDeferAnswer,
|
|
43
|
+
oncePerSession,
|
|
44
|
+
announceSubscriptionRequired
|
|
45
|
+
};
|
|
@@ -3,10 +3,10 @@ import {
|
|
|
3
3
|
} from "./chunk-KZERVKTD.js";
|
|
4
4
|
import {
|
|
5
5
|
renderCommandHelp
|
|
6
|
-
} from "./chunk-
|
|
6
|
+
} from "./chunk-65RN6ZCO.js";
|
|
7
7
|
import {
|
|
8
8
|
getPackageVersion
|
|
9
|
-
} from "./chunk-
|
|
9
|
+
} from "./chunk-WWTLAZQA.js";
|
|
10
10
|
|
|
11
11
|
// src/cli/usage.ts
|
|
12
12
|
var exitOnHelpFlag = (command) => {
|