@pushary/agent-hooks 1.4.2 → 1.5.1
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 +21 -0
- package/README.md +28 -0
- package/data/vscode-plugin/README.md +1 -1
- package/data/vscode-plugin/scripts/pushary-gate.mjs +2 -2
- package/dist/bin/pushary-bell-hook.js +22 -21
- package/dist/bin/pushary-bell.js +10 -10
- package/dist/bin/pushary-claude.js +28 -24
- package/dist/bin/pushary-clean.js +25 -25
- package/dist/bin/pushary-codex-bridge.js +16 -14
- package/dist/bin/pushary-codex-hook.js +32 -27
- package/dist/bin/pushary-codex.js +15 -10
- package/dist/bin/pushary-connect.js +11 -11
- package/dist/bin/pushary-cowork.js +6 -6
- package/dist/bin/pushary-daemon.js +32 -28
- package/dist/bin/pushary-disconnect.js +16 -16
- package/dist/bin/pushary-doctor.js +111 -40
- package/dist/bin/pushary-elicitation-hook.js +23 -22
- package/dist/bin/pushary-gemini-bridge.js +13 -11
- package/dist/bin/pushary-gemini-hook.js +29 -24
- package/dist/bin/pushary-hook.js +30 -30
- package/dist/bin/pushary-login.js +14 -14
- package/dist/bin/pushary-logout.js +8 -8
- package/dist/bin/pushary-mode.js +7 -7
- package/dist/bin/pushary-notification-hook.js +26 -25
- package/dist/bin/pushary-opencode-hook.js +25 -24
- package/dist/bin/pushary-permission-denied-hook.js +30 -29
- package/dist/bin/pushary-permission-hook.js +29 -28
- package/dist/bin/pushary-post-hook.js +26 -25
- package/dist/bin/pushary-prompt-hook.js +26 -25
- package/dist/bin/pushary-session-end-hook.js +26 -25
- package/dist/bin/pushary-session-start-hook.js +33 -27
- package/dist/bin/pushary-setup.js +94 -88
- package/dist/bin/pushary-stats.js +6 -6
- package/dist/bin/pushary-status.js +15 -15
- package/dist/bin/pushary-stop-hook.js +26 -25
- package/dist/bin/pushary-stopfailure-hook.js +26 -25
- package/dist/bin/pushary-suggestions.js +4 -4
- package/dist/bin/pushary-transcript-register.js +20 -19
- package/dist/bin/pushary-transcripts.js +8 -8
- package/dist/bin/pushary-upgrade.js +269 -45
- package/dist/bin/pushary-wait.js +7 -7
- package/dist/bin/pushary.js +8 -8
- package/dist/{chunk-LPYCPFBZ.js → chunk-2AUIEZYS.js} +3 -3
- package/dist/{chunk-4BROEAKH.js → chunk-2QT3GCU4.js} +1 -1
- package/dist/{chunk-55KW4FLG.js → chunk-3ZSGKLSO.js} +2 -2
- package/dist/{chunk-NY6XQ6CA.js → chunk-43LJSM4F.js} +2 -2
- package/dist/{chunk-LEAAERSQ.js → chunk-43ZDACBO.js} +1 -1
- package/dist/{chunk-II7PUMPB.js → chunk-4ERLRNOK.js} +3 -3
- package/dist/{chunk-M5CTUFF3.js → chunk-5HYNICS7.js} +1 -1
- package/dist/{chunk-MW6ZPC6R.js → chunk-5UQ5ATIE.js} +1 -1
- package/dist/{chunk-TYEO6T5J.js → chunk-5ZZG76S2.js} +2 -2
- package/dist/{chunk-EQRS3SGM.js → chunk-66H2QQAK.js} +1 -1
- package/dist/chunk-6EEANS74.js +300 -0
- package/dist/{chunk-TRLFZKVG.js → chunk-6IU45EHE.js} +49 -26
- package/dist/{chunk-JVTOML54.js → chunk-6QFEQIPM.js} +2 -2
- package/dist/chunk-BY2CRWBO.js +38 -0
- package/dist/{chunk-G653QPTR.js → chunk-D573TLP6.js} +7 -7
- package/dist/{chunk-25RTLTQD.js → chunk-DTQNDR7C.js} +1 -1
- package/dist/{chunk-FAH3D74E.js → chunk-EA3IELHP.js} +6 -0
- package/dist/{chunk-EYRGBYZG.js → chunk-HETOKNIL.js} +1 -1
- package/dist/{chunk-UM5J3J4V.js → chunk-HU5LSYL2.js} +2 -2
- package/dist/{chunk-PC6DU5C4.js → chunk-HUAOMX4U.js} +1 -1
- package/dist/{chunk-2V2IKOGJ.js → chunk-HVBF35GT.js} +2 -2
- package/dist/{chunk-DINDL2CF.js → chunk-HWJW3CPO.js} +25 -5
- package/dist/{chunk-VW66JEGU.js → chunk-IV3RHICU.js} +8 -8
- package/dist/{chunk-ACYIZ3KH.js → chunk-JKBDGZFL.js} +12 -6
- package/dist/{chunk-ZVY25BMK.js → chunk-K3QVDAZW.js} +1 -1
- package/dist/{chunk-MUVTZNJW.js → chunk-KHXVTWYS.js} +3 -3
- package/dist/{chunk-T5SZ4PML.js → chunk-KJRALILH.js} +7 -4
- package/dist/{chunk-VOMOZ4D5.js → chunk-M2LMXPJZ.js} +1 -1
- package/dist/{chunk-SUWRZYQG.js → chunk-MDJJW3LP.js} +3 -3
- package/dist/chunk-MU3WU2FO.js +166 -0
- package/dist/{chunk-2UMNXADU.js → chunk-OSJEMXSR.js} +5 -1
- package/dist/{chunk-TWWLVOPB.js → chunk-P4BNYJ5Q.js} +5 -5
- package/dist/{chunk-XDP3UYH5.js → chunk-PJ27EHCD.js} +8 -8
- package/dist/{chunk-LGXUGYUH.js → chunk-PYCQXCI5.js} +2 -2
- package/dist/{chunk-VIOL2DJS.js → chunk-R5KY3PBN.js} +5 -5
- package/dist/{chunk-SOUZBGYJ.js → chunk-T4QY64OR.js} +15 -14
- package/dist/{chunk-DY4ILT6L.js → chunk-TFKBFQCE.js} +1 -1
- package/dist/{chunk-GZ7E6VOB.js → chunk-TIWURSLS.js} +1 -1
- package/dist/{chunk-F4UWL4NY.js → chunk-TUXFIVOH.js} +1 -1
- package/dist/{chunk-UJBZIKSY.js → chunk-TZGCUNOX.js} +8 -8
- package/dist/{chunk-FU2DFEAZ.js → chunk-USQDVBEV.js} +2 -2
- package/dist/{chunk-YXP3WPAI.js → chunk-UYDTFCHW.js} +1 -1
- package/dist/{chunk-4ZDKSDVW.js → chunk-WNJSGZY7.js} +4 -4
- package/dist/{chunk-NHTAHAIS.js → chunk-WOLPADR6.js} +1 -1
- package/dist/{chunk-BZ4GDOJX.js → chunk-X7FESZTD.js} +7 -7
- package/dist/{chunk-NOWZUGZW.js → chunk-XWEONSLV.js} +1 -1
- package/dist/{chunk-Y3MM6PYN.js → chunk-YAWXKL2X.js} +1 -1
- package/dist/{chunk-GKIUEIDX.js → chunk-YQMFGWBD.js} +1 -1
- package/dist/{chunk-WPVHRUDT.js → chunk-Z4VGIBJ7.js} +3 -3
- package/dist/{reapply-J527BCJG.js → reapply-5CZSTJZI.js} +13 -8
- package/dist/src/index.js +18 -16
- package/package.json +1 -1
|
@@ -0,0 +1,300 @@
|
|
|
1
|
+
import {
|
|
2
|
+
spawnClaude
|
|
3
|
+
} from "./chunk-XHKBHWLX.js";
|
|
4
|
+
import {
|
|
5
|
+
codexHome,
|
|
6
|
+
codexHooksJsonIn,
|
|
7
|
+
isPusharyCodexCommand,
|
|
8
|
+
resolvePathBinary
|
|
9
|
+
} from "./chunk-6IU45EHE.js";
|
|
10
|
+
import {
|
|
11
|
+
getPackageVersion
|
|
12
|
+
} from "./chunk-HWJW3CPO.js";
|
|
13
|
+
|
|
14
|
+
// src/codex-app-server.ts
|
|
15
|
+
import { existsSync, realpathSync } from "fs";
|
|
16
|
+
import { join } from "path";
|
|
17
|
+
var CODEX_HOOK_STATUS = {
|
|
18
|
+
trusted: "trusted",
|
|
19
|
+
untrusted: "untrusted",
|
|
20
|
+
modified: "modified",
|
|
21
|
+
managed: "managed",
|
|
22
|
+
disabled: "disabled",
|
|
23
|
+
notListed: "not listed"
|
|
24
|
+
};
|
|
25
|
+
var CODEX_APP_SERVER_ARGS = ["app-server"];
|
|
26
|
+
var CODEX_APP_SERVER_TIMEOUT_MS = 1e4;
|
|
27
|
+
var TERMINATE_GRACE_MS = 1e3;
|
|
28
|
+
var MAX_RPC_LINE = 4 * 1024 * 1024;
|
|
29
|
+
var STDERR_TAIL_LIMIT = 400;
|
|
30
|
+
var PUSHARY_CLIENT_NAME = "pushary";
|
|
31
|
+
var METHOD_INITIALIZE = "initialize";
|
|
32
|
+
var METHOD_INITIALIZED = "initialized";
|
|
33
|
+
var METHOD_HOOKS_LIST = "hooks/list";
|
|
34
|
+
var METHOD_CONFIG_BATCH_WRITE = "config/batchWrite";
|
|
35
|
+
var HOOKS_STATE_KEY_PATH = "hooks.state";
|
|
36
|
+
var CODEX_INSTALLATION_ID_FILE = "installation_id";
|
|
37
|
+
var CODEX_NOT_ASKED = {
|
|
38
|
+
notInteractive: "Pushary only starts Codex when you run setup, upgrade or doctor yourself at a terminal",
|
|
39
|
+
noCodexOnPath: "there is no codex command on PATH",
|
|
40
|
+
neverOpened: "Codex has not been opened on this machine yet"
|
|
41
|
+
};
|
|
42
|
+
var UNRECOGNISED_LISTING = "Codex answered hooks/list in a shape Pushary does not recognise";
|
|
43
|
+
var isRecord = (value) => typeof value === "object" && value !== null && !Array.isArray(value);
|
|
44
|
+
var isCodexListedHook = (value) => isRecord(value) && typeof value.key === "string" && typeof value.eventName === "string" && typeof value.command === "string" && typeof value.sourcePath === "string" && typeof value.enabled === "boolean" && typeof value.isManaged === "boolean" && typeof value.currentHash === "string" && typeof value.trustStatus === "string";
|
|
45
|
+
var listedHookFields = (hook) => ({
|
|
46
|
+
key: hook.key,
|
|
47
|
+
eventName: hook.eventName,
|
|
48
|
+
command: hook.command,
|
|
49
|
+
sourcePath: hook.sourcePath,
|
|
50
|
+
enabled: hook.enabled,
|
|
51
|
+
isManaged: hook.isManaged,
|
|
52
|
+
currentHash: hook.currentHash,
|
|
53
|
+
trustStatus: hook.trustStatus
|
|
54
|
+
});
|
|
55
|
+
var diagnosticMessages = (value) => {
|
|
56
|
+
if (!Array.isArray(value)) return [];
|
|
57
|
+
return value.flatMap((entry) => {
|
|
58
|
+
if (typeof entry === "string") return [entry];
|
|
59
|
+
if (isRecord(entry) && typeof entry.message === "string") return [entry.message];
|
|
60
|
+
return [];
|
|
61
|
+
});
|
|
62
|
+
};
|
|
63
|
+
var hooksListingOf = (result) => {
|
|
64
|
+
if (!isRecord(result) || !Array.isArray(result.data)) return null;
|
|
65
|
+
const hooks = [];
|
|
66
|
+
const warnings = [];
|
|
67
|
+
for (const layer of result.data) {
|
|
68
|
+
if (!isRecord(layer) || !Array.isArray(layer.hooks)) return null;
|
|
69
|
+
hooks.push(...layer.hooks.filter(isCodexListedHook).map(listedHookFields));
|
|
70
|
+
warnings.push(...diagnosticMessages(layer.warnings), ...diagnosticMessages(layer.errors));
|
|
71
|
+
}
|
|
72
|
+
return { hooks, warnings };
|
|
73
|
+
};
|
|
74
|
+
var isPusharyHookIn = (hooksJsonPath, hook) => hook.sourcePath === hooksJsonPath && isPusharyCodexCommand(hook.command);
|
|
75
|
+
var isTrustableByPushary = (hook) => hook.enabled && !hook.isManaged && hook.trustStatus !== CODEX_HOOK_STATUS.managed;
|
|
76
|
+
var pusharyHooksIn = (hooks, hooksJsonPath) => hooks.filter((hook) => isPusharyHookIn(hooksJsonPath, hook));
|
|
77
|
+
var selectPusharyCodexHooks = (hooks, hooksJsonPath) => pusharyHooksIn(hooks, hooksJsonPath).filter(isTrustableByPushary);
|
|
78
|
+
var codexTrustVerdict = (hooks, hooksJsonPath) => {
|
|
79
|
+
if (pusharyHooksIn(hooks, hooksJsonPath).length === 0) return { kind: "unlisted" };
|
|
80
|
+
const untrusted = selectPusharyCodexHooks(hooks, hooksJsonPath).filter((hook) => hook.trustStatus !== CODEX_HOOK_STATUS.trusted);
|
|
81
|
+
return untrusted.length === 0 ? { kind: "trusted" } : { kind: "untrusted", hooks: untrusted };
|
|
82
|
+
};
|
|
83
|
+
var codexTrustEdit = (hooks) => ({
|
|
84
|
+
edits: [{
|
|
85
|
+
keyPath: HOOKS_STATE_KEY_PATH,
|
|
86
|
+
mergeStrategy: "upsert",
|
|
87
|
+
value: Object.fromEntries(hooks.map((hook) => [hook.key, { trusted_hash: hook.currentHash }]))
|
|
88
|
+
}],
|
|
89
|
+
reloadUserConfig: true
|
|
90
|
+
});
|
|
91
|
+
var initializeParams = (clientVersion) => ({
|
|
92
|
+
clientInfo: { name: PUSHARY_CLIENT_NAME, title: null, version: clientVersion }
|
|
93
|
+
});
|
|
94
|
+
var hooksListParams = (cwd) => ({ cwds: [cwd] });
|
|
95
|
+
var hookEventOf = (eventName) => eventName.charAt(0).toUpperCase() + eventName.slice(1);
|
|
96
|
+
var readingOf = (hook) => ({
|
|
97
|
+
event: hookEventOf(hook.eventName),
|
|
98
|
+
status: hook.enabled ? hook.trustStatus : CODEX_HOOK_STATUS.disabled
|
|
99
|
+
});
|
|
100
|
+
var codexHookTrustByEvent = (events, hooks) => events.map((event) => hooks.map(readingOf).find((reading) => reading.event === event) ?? { event, status: CODEX_HOOK_STATUS.notListed });
|
|
101
|
+
var CODEX_TRUST_FAILURES = /* @__PURE__ */ new Set([CODEX_HOOK_STATUS.untrusted, CODEX_HOOK_STATUS.modified]);
|
|
102
|
+
var isCodexTrustFailure = (reading) => CODEX_TRUST_FAILURES.has(reading.status);
|
|
103
|
+
var eventsWithStatus = (readings, status) => readings.filter((reading) => reading.status === status).map((reading) => reading.event);
|
|
104
|
+
var assessCodexHookTrust = (events, hooks) => {
|
|
105
|
+
const readings = codexHookTrustByEvent(events, hooks);
|
|
106
|
+
const notListed = eventsWithStatus(readings, CODEX_HOOK_STATUS.notListed);
|
|
107
|
+
if (readings.length > 0 && notListed.length === readings.length) return { kind: "unlisted" };
|
|
108
|
+
const disabled = eventsWithStatus(readings, CODEX_HOOK_STATUS.disabled);
|
|
109
|
+
const failures = readings.filter(isCodexTrustFailure);
|
|
110
|
+
if (failures.length > 0) return { kind: "untrusted", failures, notListed, disabled };
|
|
111
|
+
const trusted = eventsWithStatus(readings, CODEX_HOOK_STATUS.trusted).length;
|
|
112
|
+
return { kind: "trusted", trusted, total: readings.length, notListed, disabled };
|
|
113
|
+
};
|
|
114
|
+
var mayAskCodex = (conditions) => {
|
|
115
|
+
if (!conditions.interactive) return { kind: "skipped", reason: CODEX_NOT_ASKED.notInteractive };
|
|
116
|
+
if (!conditions.codexOnPath) return { kind: "skipped", reason: CODEX_NOT_ASKED.noCodexOnPath };
|
|
117
|
+
if (!conditions.codexOpenedBefore) return { kind: "skipped", reason: CODEX_NOT_ASKED.neverOpened };
|
|
118
|
+
return { kind: "ask", binary: conditions.codexOnPath };
|
|
119
|
+
};
|
|
120
|
+
var canonicalPath = (path) => {
|
|
121
|
+
try {
|
|
122
|
+
return realpathSync(path);
|
|
123
|
+
} catch {
|
|
124
|
+
return path;
|
|
125
|
+
}
|
|
126
|
+
};
|
|
127
|
+
var withCanonicalSources = (hooks) => hooks.map((hook) => ({ ...hook, sourcePath: canonicalPath(hook.sourcePath) }));
|
|
128
|
+
var hasExited = (child) => child.exitCode !== null || child.signalCode !== null;
|
|
129
|
+
var waitForExit = (child, ms) => new Promise((resolve) => {
|
|
130
|
+
if (hasExited(child)) return resolve(true);
|
|
131
|
+
const timer = setTimeout(() => resolve(false), ms);
|
|
132
|
+
child.once("exit", () => {
|
|
133
|
+
clearTimeout(timer);
|
|
134
|
+
resolve(true);
|
|
135
|
+
});
|
|
136
|
+
});
|
|
137
|
+
var terminate = async (child) => {
|
|
138
|
+
if (child.pid === void 0 || hasExited(child)) return;
|
|
139
|
+
child.stdin?.end();
|
|
140
|
+
child.kill("SIGTERM");
|
|
141
|
+
if (await waitForExit(child, TERMINATE_GRACE_MS)) return;
|
|
142
|
+
child.kill("SIGKILL");
|
|
143
|
+
await waitForExit(child, TERMINATE_GRACE_MS);
|
|
144
|
+
};
|
|
145
|
+
var rpcErrorMessage = (error) => isRecord(error) && typeof error.message === "string" ? error.message : "Codex returned an error";
|
|
146
|
+
var describeExit = (code, signal, stderr) => {
|
|
147
|
+
const how = signal ? `signal ${signal}` : `code ${code ?? "unknown"}`;
|
|
148
|
+
const tail = stderr.trim();
|
|
149
|
+
return tail ? `Codex app-server exited (${how}): ${tail}` : `Codex app-server exited (${how})`;
|
|
150
|
+
};
|
|
151
|
+
var runCodexAppServer = (launch, conversation) => {
|
|
152
|
+
const child = spawnClaude(launch.binary, CODEX_APP_SERVER_ARGS, {
|
|
153
|
+
cwd: launch.codexHome,
|
|
154
|
+
env: { ...process.env, CODEX_HOME: launch.codexHome },
|
|
155
|
+
stdio: ["pipe", "pipe", "pipe"],
|
|
156
|
+
windowsHide: true
|
|
157
|
+
});
|
|
158
|
+
const pending = /* @__PURE__ */ new Map();
|
|
159
|
+
let nextId = 1;
|
|
160
|
+
let buffer = "";
|
|
161
|
+
let stderrTail = "";
|
|
162
|
+
let stoppedReason = null;
|
|
163
|
+
let stop = () => {
|
|
164
|
+
};
|
|
165
|
+
const stopped = new Promise((resolve) => {
|
|
166
|
+
stop = (reason) => {
|
|
167
|
+
if (stoppedReason !== null) return;
|
|
168
|
+
stoppedReason = reason;
|
|
169
|
+
for (const settle of pending.values()) settle({ kind: "error", message: reason });
|
|
170
|
+
pending.clear();
|
|
171
|
+
resolve({ kind: "unavailable", reason });
|
|
172
|
+
};
|
|
173
|
+
});
|
|
174
|
+
const write = (message) => {
|
|
175
|
+
if (stoppedReason === null) child.stdin?.write(`${JSON.stringify(message)}
|
|
176
|
+
`);
|
|
177
|
+
};
|
|
178
|
+
const handleLine = (line) => {
|
|
179
|
+
let message;
|
|
180
|
+
try {
|
|
181
|
+
message = JSON.parse(line);
|
|
182
|
+
} catch {
|
|
183
|
+
return;
|
|
184
|
+
}
|
|
185
|
+
if (!isRecord(message) || typeof message.id !== "number" || "method" in message) return;
|
|
186
|
+
const settle = pending.get(message.id);
|
|
187
|
+
if (!settle) return;
|
|
188
|
+
pending.delete(message.id);
|
|
189
|
+
settle("error" in message && message.error !== void 0 && message.error !== null ? { kind: "error", message: rpcErrorMessage(message.error) } : { kind: "result", value: message.result });
|
|
190
|
+
};
|
|
191
|
+
child.stdin?.on("error", () => {
|
|
192
|
+
});
|
|
193
|
+
child.stdout?.setEncoding("utf8");
|
|
194
|
+
child.stdout?.on("data", (chunk) => {
|
|
195
|
+
buffer += chunk;
|
|
196
|
+
let newline = buffer.indexOf("\n");
|
|
197
|
+
while (newline >= 0) {
|
|
198
|
+
handleLine(buffer.slice(0, newline));
|
|
199
|
+
buffer = buffer.slice(newline + 1);
|
|
200
|
+
newline = buffer.indexOf("\n");
|
|
201
|
+
}
|
|
202
|
+
if (buffer.length > MAX_RPC_LINE) stop("Codex app-server sent an oversized message");
|
|
203
|
+
});
|
|
204
|
+
child.stderr?.setEncoding("utf8");
|
|
205
|
+
child.stderr?.on("data", (chunk) => {
|
|
206
|
+
stderrTail = (stderrTail + chunk).slice(-STDERR_TAIL_LIMIT);
|
|
207
|
+
});
|
|
208
|
+
child.once("error", (error) => stop(`could not start ${launch.binary}: ${error.message}`));
|
|
209
|
+
child.once("close", (code, signal) => stop(describeExit(code, signal, stderrTail)));
|
|
210
|
+
const timer = setTimeout(
|
|
211
|
+
() => stop(`Codex app-server did not answer within ${launch.timeoutMs / 1e3}s`),
|
|
212
|
+
launch.timeoutMs
|
|
213
|
+
);
|
|
214
|
+
const session = {
|
|
215
|
+
request: (method, params) => {
|
|
216
|
+
if (stoppedReason !== null) return Promise.resolve({ kind: "error", message: stoppedReason });
|
|
217
|
+
const id = nextId++;
|
|
218
|
+
return new Promise((resolve) => {
|
|
219
|
+
pending.set(id, resolve);
|
|
220
|
+
write({ id, method, params });
|
|
221
|
+
});
|
|
222
|
+
},
|
|
223
|
+
notify: (method) => write({ method })
|
|
224
|
+
};
|
|
225
|
+
const conversed = conversation(session).catch((error) => ({
|
|
226
|
+
kind: "unavailable",
|
|
227
|
+
reason: error instanceof Error ? error.message : String(error)
|
|
228
|
+
}));
|
|
229
|
+
return Promise.race([conversed, stopped]).finally(async () => {
|
|
230
|
+
clearTimeout(timer);
|
|
231
|
+
await terminate(child);
|
|
232
|
+
});
|
|
233
|
+
};
|
|
234
|
+
var launchOf = (options) => {
|
|
235
|
+
const home = options.codexHome ?? codexHome();
|
|
236
|
+
const decision = mayAskCodex({
|
|
237
|
+
interactive: options.interactive ?? process.stdout.isTTY === true,
|
|
238
|
+
codexOnPath: options.codexOnPath === void 0 ? resolvePathBinary("codex") ?? null : options.codexOnPath,
|
|
239
|
+
codexOpenedBefore: existsSync(join(home, CODEX_INSTALLATION_ID_FILE))
|
|
240
|
+
});
|
|
241
|
+
if (decision.kind === "skipped") return decision;
|
|
242
|
+
return { binary: decision.binary, codexHome: home, timeoutMs: options.timeoutMs ?? CODEX_APP_SERVER_TIMEOUT_MS };
|
|
243
|
+
};
|
|
244
|
+
var isSkipped = (value) => "kind" in value && value.kind === "skipped";
|
|
245
|
+
var openSession = async (session) => {
|
|
246
|
+
const initialized = await session.request(METHOD_INITIALIZE, initializeParams(getPackageVersion()));
|
|
247
|
+
if (initialized.kind === "error") return { kind: "unavailable", reason: `Codex refused initialize: ${initialized.message}` };
|
|
248
|
+
session.notify(METHOD_INITIALIZED);
|
|
249
|
+
return null;
|
|
250
|
+
};
|
|
251
|
+
var listHooks = async (session, launch) => {
|
|
252
|
+
const listed = await session.request(METHOD_HOOKS_LIST, hooksListParams(launch.codexHome));
|
|
253
|
+
if (listed.kind === "error") return { kind: "unavailable", reason: `Codex could not list hooks: ${listed.message}` };
|
|
254
|
+
const listing = hooksListingOf(listed.value);
|
|
255
|
+
if (!listing) return { kind: "unavailable", reason: UNRECOGNISED_LISTING };
|
|
256
|
+
return { hooks: withCanonicalSources(listing.hooks), warnings: listing.warnings };
|
|
257
|
+
};
|
|
258
|
+
var isListing = (value) => !("kind" in value);
|
|
259
|
+
var confirmationAfterWrite = (listing, hooksJsonPath, writeError) => {
|
|
260
|
+
const verdict = codexTrustVerdict(listing.hooks, hooksJsonPath);
|
|
261
|
+
if (verdict.kind === "trusted") return { kind: "verified", wrote: true };
|
|
262
|
+
if (verdict.kind === "unlisted") return { kind: "unlisted", warnings: listing.warnings };
|
|
263
|
+
return { kind: "refused", hooks: verdict.hooks.map(readingOf), writeError };
|
|
264
|
+
};
|
|
265
|
+
var trustConversation = (launch, hooksJsonPath) => async (session) => {
|
|
266
|
+
const unavailable = await openSession(session);
|
|
267
|
+
if (unavailable) return unavailable;
|
|
268
|
+
const before = await listHooks(session, launch);
|
|
269
|
+
if (!isListing(before)) return before;
|
|
270
|
+
const verdict = codexTrustVerdict(before.hooks, hooksJsonPath);
|
|
271
|
+
if (verdict.kind === "trusted") return { kind: "verified", wrote: false };
|
|
272
|
+
if (verdict.kind === "unlisted") return { kind: "unlisted", warnings: before.warnings };
|
|
273
|
+
const written = await session.request(METHOD_CONFIG_BATCH_WRITE, codexTrustEdit(verdict.hooks));
|
|
274
|
+
const after = await listHooks(session, launch);
|
|
275
|
+
if (!isListing(after)) return after;
|
|
276
|
+
return confirmationAfterWrite(after, hooksJsonPath, written.kind === "error" ? written.message : null);
|
|
277
|
+
};
|
|
278
|
+
var listingConversation = (launch, hooksJsonPath) => async (session) => {
|
|
279
|
+
const unavailable = await openSession(session);
|
|
280
|
+
if (unavailable) return unavailable;
|
|
281
|
+
const listing = await listHooks(session, launch);
|
|
282
|
+
if (!isListing(listing)) return listing;
|
|
283
|
+
return { kind: "listed", hooks: pusharyHooksIn(listing.hooks, hooksJsonPath) };
|
|
284
|
+
};
|
|
285
|
+
var ensureCodexTrustsPusharyHooks = async (options = {}) => {
|
|
286
|
+
const launch = launchOf(options);
|
|
287
|
+
if (isSkipped(launch)) return launch;
|
|
288
|
+
return runCodexAppServer(launch, trustConversation(launch, canonicalPath(codexHooksJsonIn(launch.codexHome))));
|
|
289
|
+
};
|
|
290
|
+
var readCodexTrustForPusharyHooks = async (options = {}) => {
|
|
291
|
+
const launch = launchOf(options);
|
|
292
|
+
if (isSkipped(launch)) return launch;
|
|
293
|
+
return runCodexAppServer(launch, listingConversation(launch, canonicalPath(codexHooksJsonIn(launch.codexHome))));
|
|
294
|
+
};
|
|
295
|
+
|
|
296
|
+
export {
|
|
297
|
+
assessCodexHookTrust,
|
|
298
|
+
ensureCodexTrustsPusharyHooks,
|
|
299
|
+
readCodexTrustForPusharyHooks
|
|
300
|
+
};
|
|
@@ -2,12 +2,19 @@ import {
|
|
|
2
2
|
HOOK_BUDGETS,
|
|
3
3
|
HOOK_LOCATOR_BINARY,
|
|
4
4
|
withHookHoldBudget
|
|
5
|
-
} from "./chunk-
|
|
5
|
+
} from "./chunk-T4QY64OR.js";
|
|
6
|
+
import {
|
|
7
|
+
isReleaseVersion
|
|
8
|
+
} from "./chunk-HWJW3CPO.js";
|
|
6
9
|
|
|
7
10
|
// src/npm.ts
|
|
8
11
|
import { execFileSync, execSync } from "child_process";
|
|
9
12
|
import { existsSync, readFileSync, realpathSync } from "fs";
|
|
10
13
|
import { dirname, isAbsolute, join, relative, resolve } from "path";
|
|
14
|
+
var AGENT_HOOKS_PACKAGE = "@pushary/agent-hooks";
|
|
15
|
+
var LATEST_RELEASE_URL = `https://registry.npmjs.org/${AGENT_HOOKS_PACKAGE}/latest`;
|
|
16
|
+
var REGISTRY_TIMEOUT_MS = 5e3;
|
|
17
|
+
var LATEST_TAG = "latest";
|
|
11
18
|
var cleanNpmEnv = () => {
|
|
12
19
|
const env = {};
|
|
13
20
|
for (const [key, value] of Object.entries(process.env)) {
|
|
@@ -16,10 +23,11 @@ var cleanNpmEnv = () => {
|
|
|
16
23
|
}
|
|
17
24
|
return env;
|
|
18
25
|
};
|
|
26
|
+
var NPM_ERROR_METADATA = /^(code|syscall|path|dest|errno)\s/i;
|
|
19
27
|
var npmErrorMessage = (err) => {
|
|
20
28
|
const e = err;
|
|
21
29
|
const text = [e?.stderr, e?.stdout].map((part) => part ? part.toString() : "").join("\n");
|
|
22
|
-
const line = text.split("\n").map((l) => l.replace(/^npm error\s*/i, "").trim()).find((l) => l && !l.startsWith("A complete log") &&
|
|
30
|
+
const line = text.split("\n").map((l) => l.replace(/^npm error\s*/i, "").trim()).find((l) => l && !l.startsWith("A complete log") && !NPM_ERROR_METADATA.test(l));
|
|
23
31
|
return line || e?.message || String(err);
|
|
24
32
|
};
|
|
25
33
|
var execNpm = (args, options = {}) => {
|
|
@@ -143,6 +151,26 @@ var resolveGlobalBinDir = (probe) => {
|
|
|
143
151
|
return resolved ? resolved.slice(0, resolved.length - probe.length - 1) : void 0;
|
|
144
152
|
};
|
|
145
153
|
var quoteIfNeeded = (path) => /\s/.test(path) ? `"${path}"` : path;
|
|
154
|
+
var fetchLatestPublishedVersion = async (request = {}) => {
|
|
155
|
+
try {
|
|
156
|
+
const response = await (request.fetchImpl ?? fetch)(LATEST_RELEASE_URL, {
|
|
157
|
+
signal: AbortSignal.timeout(request.timeoutMs ?? REGISTRY_TIMEOUT_MS)
|
|
158
|
+
});
|
|
159
|
+
if (!response.ok) return void 0;
|
|
160
|
+
const body = await response.json();
|
|
161
|
+
const version = body && typeof body === "object" && "version" in body ? body.version : void 0;
|
|
162
|
+
return typeof version === "string" && isReleaseVersion(version) ? version : void 0;
|
|
163
|
+
} catch {
|
|
164
|
+
return void 0;
|
|
165
|
+
}
|
|
166
|
+
};
|
|
167
|
+
var POSIX_SHELL_WORD = /^[\w@%+=:,./-]+$/;
|
|
168
|
+
var quoteForPosixShell = (value) => POSIX_SHELL_WORD.test(value) ? value : `'${value.replaceAll("'", `'\\''`)}'`;
|
|
169
|
+
var installAgentHooksGlobally = (request, runNpm = execNpm) => {
|
|
170
|
+
const prefixFlag = request.prefix === void 0 ? "" : ` --prefix ${quoteForPosixShell(request.prefix)}`;
|
|
171
|
+
const spec = quoteForPosixShell(`${AGENT_HOOKS_PACKAGE}@${request.version}`);
|
|
172
|
+
runNpm(`install -g --no-workspaces${prefixFlag} ${spec}`, { timeout: request.timeoutMs });
|
|
173
|
+
};
|
|
146
174
|
var needsGlobalInstall = (requested, installed, binaryPresent) => requested !== installed || !binaryPresent;
|
|
147
175
|
var installState;
|
|
148
176
|
var installGlobally = (options) => {
|
|
@@ -153,13 +181,13 @@ var installGlobally = (options) => {
|
|
|
153
181
|
const pinned = process.env.PUSHARY_PIN_GLOBAL_VERSION !== "0";
|
|
154
182
|
if (pinned && !needsGlobalInstall(
|
|
155
183
|
options.version,
|
|
156
|
-
resolveGlobalPackageVersion(
|
|
157
|
-
globalPackageBinsPresent(
|
|
184
|
+
resolveGlobalPackageVersion(AGENT_HOOKS_PACKAGE),
|
|
185
|
+
globalPackageBinsPresent(AGENT_HOOKS_PACKAGE)
|
|
158
186
|
)) {
|
|
159
187
|
return "skipped";
|
|
160
188
|
}
|
|
161
|
-
const
|
|
162
|
-
|
|
189
|
+
const version = pinned && options.version && options.version !== "0.0.0" ? options.version : LATEST_TAG;
|
|
190
|
+
installAgentHooksGlobally({ version, timeoutMs: options.timeoutMs ?? 12e4 });
|
|
163
191
|
return "installed";
|
|
164
192
|
})();
|
|
165
193
|
installState = started;
|
|
@@ -286,7 +314,8 @@ var CODEX_HOOK_BINARY = "pushary-codex-hook";
|
|
|
286
314
|
var codexHome = () => codexHomeFrom(homedir());
|
|
287
315
|
var codexHomeFrom = (home) => process.env.CODEX_HOME?.trim() || join2(home, ".codex");
|
|
288
316
|
var codexConfigToml = () => join2(codexHome(), "config.toml");
|
|
289
|
-
var
|
|
317
|
+
var codexHooksJsonIn = (home) => join2(home, "hooks.json");
|
|
318
|
+
var codexHooksJson = () => codexHooksJsonIn(codexHome());
|
|
290
319
|
var codexAgentsMd = () => join2(codexHome(), "AGENTS.md");
|
|
291
320
|
var codexSkillDir = () => join2(codexHome(), "skills", "pushary");
|
|
292
321
|
var CODEX_HOOK_EVENTS = [
|
|
@@ -358,10 +387,11 @@ var readCodexMcpAuth = (config) => {
|
|
|
358
387
|
if (typeof pushary.bearer_token === "string") return { method: "legacy-bearer" };
|
|
359
388
|
return void 0;
|
|
360
389
|
};
|
|
390
|
+
var isPusharyCodexCommand = (command) => command.includes(CODEX_HOOK_BINARY) || command.includes(HOOK_LOCATOR_BINARY);
|
|
361
391
|
var isPusharyCommand = (hook, scope) => {
|
|
362
392
|
const command = String(asRecord2(hook)?.command ?? "");
|
|
363
393
|
if (isProtectedByScope(command, scope)) return false;
|
|
364
|
-
return
|
|
394
|
+
return isPusharyCodexCommand(command);
|
|
365
395
|
};
|
|
366
396
|
var isPusharyCodexHook = (entry, scope) => {
|
|
367
397
|
const hooks = asRecord2(entry)?.hooks;
|
|
@@ -435,23 +465,6 @@ var codexEntryTrustHash = (eventKey, entry) => {
|
|
|
435
465
|
if (typeof entry.matcher === "string") identity.matcher = entry.matcher;
|
|
436
466
|
return "sha256:" + createHash("sha256").update(canonicalJson(identity), "utf8").digest("hex");
|
|
437
467
|
};
|
|
438
|
-
var codexTrustSchemeAgrees = (hooksConfig, config, hooksJsonPath) => {
|
|
439
|
-
const hooks = asRecord2(hooksConfig?.hooks);
|
|
440
|
-
const state = asRecord2(asRecord2(config.hooks)?.state);
|
|
441
|
-
if (!hooks || !state) return false;
|
|
442
|
-
for (const [event, entries] of Object.entries(hooks)) {
|
|
443
|
-
if (!Array.isArray(entries)) continue;
|
|
444
|
-
const eventKey = CODEX_EVENT_KEY[event] ?? codexEventKeyOf(event);
|
|
445
|
-
for (const [index, entry] of entries.entries()) {
|
|
446
|
-
const record = asRecord2(entry);
|
|
447
|
-
if (!record) continue;
|
|
448
|
-
const stored = asRecord2(state[`${hooksJsonPath}:${eventKey}:${index}:0`])?.trusted_hash;
|
|
449
|
-
if (typeof stored !== "string") continue;
|
|
450
|
-
if (stored === codexEntryTrustHash(eventKey, record)) return true;
|
|
451
|
-
}
|
|
452
|
-
}
|
|
453
|
-
return false;
|
|
454
|
-
};
|
|
455
468
|
var codexHookPositions = (hooksConfig) => {
|
|
456
469
|
const hooks = asRecord2(hooksConfig?.hooks);
|
|
457
470
|
const positions = {};
|
|
@@ -609,6 +622,9 @@ var claudeSettingsLocal = () => join3(homedir2(), ".claude", "settings.local.jso
|
|
|
609
622
|
var pusharyDir = () => join3(homedir2(), ".pushary");
|
|
610
623
|
var claudeMcpReceipt = () => join3(pusharyDir(), "setup", "claude-mcp.json");
|
|
611
624
|
var bridgeAgentKey = () => join3(pusharyDir(), "bridge-auth", "agent-key.json");
|
|
625
|
+
var autoUpdateState = () => join3(pusharyDir(), "auto-update.json");
|
|
626
|
+
var autoUpdateLock = () => join3(pusharyDir(), "auto-update.lock");
|
|
627
|
+
var autoUpdateLog = () => join3(pusharyDir(), "logs", "auto-update.log");
|
|
612
628
|
var claudeRegistrationReceipt = () => join3(pusharyDir(), "setup", "claude-registration.json");
|
|
613
629
|
var hermesConfigReceipt = () => join3(pusharyDir(), "setup", "hermes-config.json");
|
|
614
630
|
var hookTakeoverReceipt = (agent) => join3(pusharyDir(), "setup", `hook-takeover-${agent}.json`);
|
|
@@ -622,6 +638,7 @@ export {
|
|
|
622
638
|
registeredCommands,
|
|
623
639
|
namesOurBinary,
|
|
624
640
|
registrationHolderOf,
|
|
641
|
+
LATEST_TAG,
|
|
625
642
|
npmErrorMessage,
|
|
626
643
|
execNpm,
|
|
627
644
|
resolveGlobalBinary,
|
|
@@ -630,6 +647,8 @@ export {
|
|
|
630
647
|
resolvePackageVersionFromBinary,
|
|
631
648
|
resolveGlobalPackageVersion,
|
|
632
649
|
resolveGlobalBinDir,
|
|
650
|
+
fetchLatestPublishedVersion,
|
|
651
|
+
installAgentHooksGlobally,
|
|
633
652
|
installGlobally,
|
|
634
653
|
holdBudgetOf,
|
|
635
654
|
guardBinary,
|
|
@@ -642,18 +661,19 @@ export {
|
|
|
642
661
|
codexHome,
|
|
643
662
|
codexHomeFrom,
|
|
644
663
|
codexConfigToml,
|
|
664
|
+
codexHooksJsonIn,
|
|
645
665
|
codexHooksJson,
|
|
646
666
|
codexAgentsMd,
|
|
647
667
|
codexSkillDir,
|
|
648
668
|
CODEX_HOOK_EVENTS,
|
|
649
669
|
addCodexMcpServer,
|
|
650
670
|
readCodexMcpAuth,
|
|
671
|
+
isPusharyCodexCommand,
|
|
651
672
|
codexRegistrationHolder,
|
|
652
673
|
addCodexHooks,
|
|
653
674
|
removeCodexHooks,
|
|
654
675
|
hasCodexHooks,
|
|
655
676
|
missingCodexHookEvents,
|
|
656
|
-
codexTrustSchemeAgrees,
|
|
657
677
|
codexHookPositions,
|
|
658
678
|
codexVacatedIndexes,
|
|
659
679
|
dropVacatedCodexHookTrust,
|
|
@@ -675,6 +695,9 @@ export {
|
|
|
675
695
|
pusharyDir,
|
|
676
696
|
claudeMcpReceipt,
|
|
677
697
|
bridgeAgentKey,
|
|
698
|
+
autoUpdateState,
|
|
699
|
+
autoUpdateLock,
|
|
700
|
+
autoUpdateLog,
|
|
678
701
|
claudeRegistrationReceipt,
|
|
679
702
|
hermesConfigReceipt,
|
|
680
703
|
hookTakeoverReceipt,
|
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
import {
|
|
2
2
|
registerTranscript
|
|
3
|
-
} from "./chunk-
|
|
3
|
+
} from "./chunk-TZGCUNOX.js";
|
|
4
4
|
import {
|
|
5
5
|
degradedLine
|
|
6
|
-
} from "./chunk-
|
|
6
|
+
} from "./chunk-T4QY64OR.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"];
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
import {
|
|
2
|
+
NPX_LATEST_COMMAND
|
|
3
|
+
} from "./chunk-EA3IELHP.js";
|
|
4
|
+
|
|
5
|
+
// src/setup/codex-trust.ts
|
|
6
|
+
var CODEX_TRUST_TELEMETRY = {
|
|
7
|
+
verified: "verified",
|
|
8
|
+
refused: "manual",
|
|
9
|
+
unlisted: "manual",
|
|
10
|
+
skipped: "unverified",
|
|
11
|
+
unavailable: "unverified"
|
|
12
|
+
};
|
|
13
|
+
var isUnanswered = (confirmation) => confirmation.kind === "skipped" || confirmation.kind === "unavailable";
|
|
14
|
+
var codexTrustOutcome = (confirmation, portedTrustWritten) => isUnanswered(confirmation) && !portedTrustWritten ? "manual" : CODEX_TRUST_TELEMETRY[confirmation.kind];
|
|
15
|
+
var CODEX_TRUST_REFUSED = "Codex did not accept the trust Pushary asked for, so its hooks are not trusted yet. Open Codex, run /hooks, and choose Trust for the Pushary hooks.";
|
|
16
|
+
var describeUnlistedCodexHooks = (warnings) => {
|
|
17
|
+
const said = warnings[0] ? ` Codex said: ${warnings[0]}` : "";
|
|
18
|
+
return `Codex does not list the Pushary hooks, so it will not run them.${said} Run ${NPX_LATEST_COMMAND} doctor for details.`;
|
|
19
|
+
};
|
|
20
|
+
var describeCodexTrustConfirmation = (confirmation) => {
|
|
21
|
+
switch (confirmation.kind) {
|
|
22
|
+
case "verified":
|
|
23
|
+
return confirmation.wrote ? "Codex trusted the Pushary hooks when asked, and confirmed it." : "Codex confirms the Pushary hooks are trusted.";
|
|
24
|
+
case "refused":
|
|
25
|
+
return confirmation.writeError ? `${CODEX_TRUST_REFUSED} Codex said: ${confirmation.writeError}` : CODEX_TRUST_REFUSED;
|
|
26
|
+
case "unlisted":
|
|
27
|
+
return describeUnlistedCodexHooks(confirmation.warnings);
|
|
28
|
+
case "skipped":
|
|
29
|
+
return `Pushary did not ask Codex to confirm the trust: ${confirmation.reason}.`;
|
|
30
|
+
case "unavailable":
|
|
31
|
+
return `Codex could not be asked to confirm the Pushary hooks are trusted (${confirmation.reason}).`;
|
|
32
|
+
}
|
|
33
|
+
};
|
|
34
|
+
|
|
35
|
+
export {
|
|
36
|
+
codexTrustOutcome,
|
|
37
|
+
describeCodexTrustConfirmation
|
|
38
|
+
};
|
|
@@ -1,26 +1,26 @@
|
|
|
1
1
|
import {
|
|
2
2
|
NOTIFICATION_PUSH_TYPES,
|
|
3
3
|
POSTTOOLUSE_MIRROR_ONLY_TOOLS
|
|
4
|
-
} from "./chunk-
|
|
4
|
+
} from "./chunk-UYDTFCHW.js";
|
|
5
5
|
import {
|
|
6
6
|
cancelQuestion,
|
|
7
7
|
isPolicyConfig,
|
|
8
8
|
sendNotification,
|
|
9
9
|
waitForAnswer
|
|
10
|
-
} from "./chunk-
|
|
10
|
+
} from "./chunk-PYCQXCI5.js";
|
|
11
11
|
import {
|
|
12
12
|
getMachineId
|
|
13
|
-
} from "./chunk-
|
|
13
|
+
} from "./chunk-WOLPADR6.js";
|
|
14
14
|
import {
|
|
15
15
|
withRetry
|
|
16
|
-
} from "./chunk-
|
|
16
|
+
} from "./chunk-HETOKNIL.js";
|
|
17
17
|
import {
|
|
18
18
|
reportedInstallSource
|
|
19
|
-
} from "./chunk-
|
|
19
|
+
} from "./chunk-HU5LSYL2.js";
|
|
20
20
|
import {
|
|
21
21
|
getApiKey,
|
|
22
22
|
getBaseUrl
|
|
23
|
-
} from "./chunk-
|
|
23
|
+
} from "./chunk-OSJEMXSR.js";
|
|
24
24
|
import {
|
|
25
25
|
ACTION_BODY_MAX,
|
|
26
26
|
AGENT_LABELS_BY_TYPE,
|
|
@@ -44,7 +44,7 @@ import {
|
|
|
44
44
|
resolveAutoResolveOrigin,
|
|
45
45
|
resolvePolicy,
|
|
46
46
|
toToolLookup
|
|
47
|
-
} from "./chunk-
|
|
47
|
+
} from "./chunk-T4QY64OR.js";
|
|
48
48
|
|
|
49
49
|
// src/policy.ts
|
|
50
50
|
import { createHash } from "crypto";
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
// src/cli/commands.ts
|
|
2
|
+
var NPX_LATEST_COMMAND = "npx @pushary/agent-hooks@latest";
|
|
2
3
|
var COMMAND_LIST = [
|
|
3
4
|
{
|
|
4
5
|
name: "cowork",
|
|
@@ -132,6 +133,10 @@ var COMMAND_OPTIONS = {
|
|
|
132
133
|
["--bundle", "Write a redacted diagnostics file you can attach to a support thread"]
|
|
133
134
|
],
|
|
134
135
|
suggestions: [["accept <id>", "Turn a mined suggestion into an always-allow rule"]],
|
|
136
|
+
upgrade: [
|
|
137
|
+
["--auto=off", "Stop Pushary updating itself in the background"],
|
|
138
|
+
["--auto=on", "Update in the background again: once a day at session start, within the same major version"]
|
|
139
|
+
],
|
|
135
140
|
bell: [
|
|
136
141
|
["(no flags)", "Turn the bell on for Claude Code"],
|
|
137
142
|
["--test", "Ring once, now, so you can hear what it does"],
|
|
@@ -232,6 +237,7 @@ var renderCommandHelp = (name, version) => {
|
|
|
232
237
|
};
|
|
233
238
|
|
|
234
239
|
export {
|
|
240
|
+
NPX_LATEST_COMMAND,
|
|
235
241
|
COMMANDS,
|
|
236
242
|
isCommandName,
|
|
237
243
|
renderHelp,
|
|
@@ -3,11 +3,11 @@ import {
|
|
|
3
3
|
decodePublicKey,
|
|
4
4
|
generateSessionKey,
|
|
5
5
|
wrapSessionKey
|
|
6
|
-
} from "./chunk-
|
|
6
|
+
} from "./chunk-TIWURSLS.js";
|
|
7
7
|
import {
|
|
8
8
|
fetchTranscriptRecipients,
|
|
9
9
|
uploadTranscriptRecords
|
|
10
|
-
} from "./chunk-
|
|
10
|
+
} from "./chunk-66H2QQAK.js";
|
|
11
11
|
|
|
12
12
|
// src/live-session.ts
|
|
13
13
|
var MAX_TRANSCRIPT_QUEUE = 100;
|