@pushary/agent-hooks 1.9.42 → 1.9.44
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 +9 -0
- package/README.md +1 -0
- package/data/SKILL.md +7 -1
- package/data/cowork/SKILL.md +3 -1
- package/data/cursor-plugin/.cursor-plugin/plugin.json +1 -1
- package/data/cursor-plugin/skills/pushary/SKILL.md +6 -0
- package/data/vscode-plugin/skills/pushary/SKILL.md +6 -0
- package/dist/bin/pushary-bell-hook.js +27 -26
- package/dist/bin/pushary-bell.js +11 -11
- package/dist/bin/pushary-claude.js +30 -28
- package/dist/bin/pushary-clean.js +39 -38
- package/dist/bin/pushary-codex-bridge.js +38 -28
- package/dist/bin/pushary-codex-hook.js +35 -33
- package/dist/bin/pushary-codex-session.d.ts +1 -0
- package/dist/bin/pushary-codex-session.js +253 -0
- package/dist/bin/pushary-codex.js +13 -12
- package/dist/bin/pushary-connect.js +28 -27
- package/dist/bin/pushary-cowork.js +6 -6
- package/dist/bin/pushary-daemon.js +48 -47
- package/dist/bin/pushary-disconnect.js +27 -26
- package/dist/bin/pushary-doctor.js +85 -82
- package/dist/bin/pushary-elicitation-hook.js +27 -26
- package/dist/bin/pushary-gemini-bridge.js +22 -22
- package/dist/bin/pushary-gemini-hook.js +32 -30
- package/dist/bin/pushary-hook.js +33 -32
- package/dist/bin/pushary-login.js +16 -16
- package/dist/bin/pushary-logout.js +28 -27
- package/dist/bin/pushary-mcp.js +9 -9
- package/dist/bin/pushary-mode.js +14 -14
- package/dist/bin/pushary-notification-hook.js +26 -25
- package/dist/bin/pushary-opencode-hook.js +31 -29
- package/dist/bin/pushary-permission-denied-hook.js +31 -30
- package/dist/bin/pushary-permission-hook.js +30 -29
- 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 +31 -30
- package/dist/bin/pushary-setup.js +165 -112
- package/dist/bin/pushary-stats.js +5 -5
- package/dist/bin/pushary-status.js +35 -34
- package/dist/bin/pushary-stop-hook.js +26 -25
- package/dist/bin/pushary-stopfailure-hook.js +26 -25
- package/dist/bin/pushary-suggestions.js +14 -14
- package/dist/bin/pushary-transcript-register.js +18 -18
- package/dist/bin/pushary-transcripts.js +7 -7
- package/dist/bin/pushary-upgrade.js +41 -40
- package/dist/bin/pushary-wait.js +14 -14
- package/dist/bin/pushary.js +7 -6
- package/dist/{chunk-ZX3PFROQ.js → chunk-2NVXFWQY.js} +1 -1
- package/dist/{chunk-7L6YSHZO.js → chunk-3IRC3XFG.js} +2 -2
- package/dist/{chunk-IXNVIWNN.js → chunk-42CVAOC5.js} +2 -2
- package/dist/{chunk-EBZK2SJ2.js → chunk-4JHEZ2PV.js} +12 -5
- package/dist/{chunk-JBK47Y2M.js → chunk-4WBAHVBK.js} +11 -11
- package/dist/{chunk-AW4TDBUJ.js → chunk-53UZN7JW.js} +3 -3
- package/dist/{chunk-I7EZMNKI.js → chunk-5ZSBQHCM.js} +12 -173
- package/dist/{chunk-KYFWYPHN.js → chunk-6EV3B5CD.js} +1 -1
- package/dist/{chunk-X7TNLYNZ.js → chunk-75M7NFFC.js} +1 -1
- package/dist/{chunk-AUDM6HU6.js → chunk-7UM4NCUI.js} +2 -2
- package/dist/{chunk-5INZFKHL.js → chunk-ALY7ZBNB.js} +1 -1
- package/dist/{chunk-CGRVIUKE.js → chunk-BKK3JCTD.js} +80 -164
- package/dist/{chunk-K2SSNAUW.js → chunk-CAJCCQ7N.js} +1 -1
- package/dist/{chunk-B7PZBWBU.js → chunk-CESLE4UN.js} +10 -10
- package/dist/{chunk-MI67QQEQ.js → chunk-CEZTYTBN.js} +13 -11
- package/dist/{chunk-6PABNQVH.js → chunk-DD6IBKEJ.js} +4 -4
- package/dist/{chunk-Z4RM54LU.js → chunk-E76QCZIA.js} +2 -2
- package/dist/{chunk-RBUCXUT7.js → chunk-FI2F5KZJ.js} +4 -4
- package/dist/{chunk-IVUP2EE4.js → chunk-FKDZU6YX.js} +4 -4
- package/dist/{chunk-EA5NWDK7.js → chunk-FYNMFSIZ.js} +29 -0
- package/dist/{chunk-M2YE3OEC.js → chunk-GBCR2FH2.js} +3 -3
- package/dist/chunk-GOEIW2VH.js +266 -0
- package/dist/{chunk-JQX2L3ES.js → chunk-GRAPJKDK.js} +1 -1
- package/dist/{chunk-DPISXMLL.js → chunk-HV4TEKNP.js} +4 -4
- package/dist/{chunk-FMYXPJYS.js → chunk-IWHDNMM3.js} +5 -5
- package/dist/{chunk-ORLTWJ2O.js → chunk-JNU3LV47.js} +355 -138
- package/dist/{chunk-ZJY4KON3.js → chunk-KILK6SWZ.js} +7 -7
- package/dist/{chunk-J7OBJZ5S.js → chunk-KYLY6UMN.js} +1 -1
- package/dist/{chunk-T3Q4B6WV.js → chunk-L2ZM7LXN.js} +2 -2
- package/dist/{chunk-PJ3C6IID.js → chunk-LEHBWBCG.js} +4 -4
- package/dist/{chunk-ODPULZZG.js → chunk-M2L7625S.js} +2 -2
- package/dist/{chunk-BDSIE2MT.js → chunk-MIBCRQWK.js} +2 -2
- package/dist/{chunk-MAB6CGL5.js → chunk-MRQJCIFO.js} +1 -1
- package/dist/{chunk-F43LAKAK.js → chunk-OR6KJOHE.js} +2 -2
- package/dist/{chunk-Y3HTWB5S.js → chunk-OSMNLNPF.js} +1 -1
- package/dist/{chunk-CHD6IUNM.js → chunk-OWQOMGBF.js} +1 -1
- package/dist/{chunk-RTM5GVRZ.js → chunk-OZ7MLVDM.js} +15 -15
- package/dist/{chunk-4WM7IVVQ.js → chunk-PGHN5D4N.js} +2 -2
- package/dist/{chunk-OLLWYLQX.js → chunk-PQAFH4DF.js} +3 -11
- package/dist/{chunk-E47JEBUR.js → chunk-RGBTKOCC.js} +45 -8
- package/dist/{chunk-4UCTKLHY.js → chunk-S2ALW446.js} +3 -3
- package/dist/{chunk-3U3FU6ZX.js → chunk-SI2NC6UU.js} +3 -3
- package/dist/chunk-SVCT5D7K.js +196 -0
- package/dist/{chunk-ZVMFRUBD.js → chunk-SWDPCDLT.js} +4 -4
- package/dist/{chunk-DIJ532S7.js → chunk-T3KMJI4W.js} +2 -1
- package/dist/{chunk-NRSTNZYJ.js → chunk-T4CKP47U.js} +5 -5
- package/dist/{chunk-M7VKFAAK.js → chunk-TJZUQRMH.js} +3 -3
- package/dist/{chunk-ZV56INA6.js → chunk-TKTS3SIM.js} +3 -3
- package/dist/{chunk-RETRVO47.js → chunk-TWATOPHK.js} +2 -2
- package/dist/{chunk-WZNRDDC4.js → chunk-UC4PNLMK.js} +6 -6
- package/dist/{chunk-ASXBYX2N.js → chunk-UJXLVH66.js} +1 -1
- package/dist/{chunk-Q3QRD67J.js → chunk-UY5E2UUW.js} +5 -5
- package/dist/{chunk-FP2ZJK3T.js → chunk-UZVF6MP2.js} +5 -5
- package/dist/{chunk-STETTN4K.js → chunk-W2TA4EVZ.js} +5 -5
- package/dist/{chunk-QRNNIDGY.js → chunk-WBD7HZEZ.js} +1 -1
- package/dist/{chunk-QPT4PTUG.js → chunk-WMO2XVG4.js} +1 -1
- package/dist/{chunk-BZIXDIIT.js → chunk-XPQDBTW4.js} +1 -1
- package/dist/{global-upgrade-YEAGJG4G.js → global-upgrade-QSSDYZCZ.js} +6 -6
- package/dist/{paths-HQAICWAF.js → paths-55DDFLY4.js} +2 -2
- package/dist/{reapply-XBEB2B5A.js → reapply-MEU66ALO.js} +23 -22
- package/dist/src/index.js +20 -19
- package/dist/{upgrade-lock-GIO5QZ7E.js → upgrade-lock-YLXAU4AD.js} +3 -3
- package/package.json +5 -2
|
@@ -12,21 +12,21 @@ import {
|
|
|
12
12
|
terminalColumns,
|
|
13
13
|
useColor
|
|
14
14
|
} from "./chunk-FO3MDD26.js";
|
|
15
|
-
import {
|
|
16
|
-
callMcpTool
|
|
17
|
-
} from "./chunk-AW4TDBUJ.js";
|
|
18
15
|
import {
|
|
19
16
|
reportedInstallSource
|
|
20
|
-
} from "./chunk-
|
|
17
|
+
} from "./chunk-M2L7625S.js";
|
|
18
|
+
import {
|
|
19
|
+
callMcpTool
|
|
20
|
+
} from "./chunk-53UZN7JW.js";
|
|
21
21
|
import {
|
|
22
22
|
NPX_LATEST_COMMAND
|
|
23
|
-
} from "./chunk-
|
|
23
|
+
} from "./chunk-T3KMJI4W.js";
|
|
24
24
|
import {
|
|
25
25
|
NO_PAIRING_COMPUTER,
|
|
26
26
|
PAIR_TTL_SECONDS,
|
|
27
27
|
classifyConfirmResponse,
|
|
28
28
|
isAnswerSource
|
|
29
|
-
} from "./chunk-
|
|
29
|
+
} from "./chunk-JNU3LV47.js";
|
|
30
30
|
|
|
31
31
|
// src/reach.ts
|
|
32
32
|
var reachVerdict = (channels) => {
|
|
@@ -972,7 +972,7 @@ var watchSkip = (listener) => {
|
|
|
972
972
|
});
|
|
973
973
|
return { skipped: () => skipped, woken, stop };
|
|
974
974
|
};
|
|
975
|
-
var PHONE_WAIT_REPAIR_LINE = `Open the Pushary app, sign in with the same account, and allow notifications. Then run ${NPX_LATEST_COMMAND} doctor.`;
|
|
975
|
+
var PHONE_WAIT_REPAIR_LINE = `Open the Pushary app, sign in with the same account, and allow notifications. Then run ${NPX_LATEST_COMMAND} doctor --roundtrip. Your agent configuration is saved; no reinstall is needed.`;
|
|
976
976
|
var phoneWaitRepair = (verdict) => verdict.kind === "nobody" ? [PHONE_WAIT_REPAIR_LINE] : describeAppRepair(verdict) ?? [];
|
|
977
977
|
var pollForYourPhone = async (apiKey, firstSeen, options) => {
|
|
978
978
|
const clock = options.clock ?? SYSTEM_PAIR_CLOCK;
|
|
@@ -10,10 +10,10 @@ import {
|
|
|
10
10
|
resolvePackageVersionFromBinary,
|
|
11
11
|
resolvePathBinary,
|
|
12
12
|
resolvePathBinaryAsync
|
|
13
|
-
} from "./chunk-
|
|
13
|
+
} from "./chunk-4JHEZ2PV.js";
|
|
14
14
|
import {
|
|
15
15
|
MANAGED_PROVIDERS
|
|
16
|
-
} from "./chunk-
|
|
16
|
+
} from "./chunk-JNU3LV47.js";
|
|
17
17
|
|
|
18
18
|
// src/setup/codex-install.ts
|
|
19
19
|
var NATIVE_BINARY_MIN_BYTES = 20 * 1024 * 1024;
|
|
@@ -1,18 +1,18 @@
|
|
|
1
1
|
import {
|
|
2
2
|
macAppBridgeAvailable
|
|
3
|
-
} from "./chunk-
|
|
3
|
+
} from "./chunk-UZVF6MP2.js";
|
|
4
4
|
import {
|
|
5
5
|
keyPrefix
|
|
6
|
-
} from "./chunk-
|
|
6
|
+
} from "./chunk-TJZUQRMH.js";
|
|
7
7
|
import {
|
|
8
8
|
bridgeAgentKey
|
|
9
|
-
} from "./chunk-
|
|
9
|
+
} from "./chunk-4JHEZ2PV.js";
|
|
10
10
|
import {
|
|
11
11
|
readJsonSafe
|
|
12
12
|
} from "./chunk-AQFEP65J.js";
|
|
13
13
|
import {
|
|
14
14
|
isValidApiKey
|
|
15
|
-
} from "./chunk-
|
|
15
|
+
} from "./chunk-JNU3LV47.js";
|
|
16
16
|
|
|
17
17
|
// src/shared-mcp-key.ts
|
|
18
18
|
var asRecord = (value) => value !== null && typeof value === "object" && !Array.isArray(value) ? value : void 0;
|
|
@@ -3,10 +3,10 @@ import {
|
|
|
3
3
|
} from "./chunk-KZERVKTD.js";
|
|
4
4
|
import {
|
|
5
5
|
renderCommandHelp
|
|
6
|
-
} from "./chunk-
|
|
6
|
+
} from "./chunk-T3KMJI4W.js";
|
|
7
7
|
import {
|
|
8
8
|
getPackageVersion
|
|
9
|
-
} from "./chunk-
|
|
9
|
+
} from "./chunk-JNU3LV47.js";
|
|
10
10
|
|
|
11
11
|
// src/cli/usage.ts
|
|
12
12
|
var exitOnHelpFlag = (command) => {
|
|
@@ -6,38 +6,38 @@ import {
|
|
|
6
6
|
} from "./chunk-DWQYCOPI.js";
|
|
7
7
|
import {
|
|
8
8
|
ensureDaemonRunning
|
|
9
|
-
} from "./chunk-
|
|
9
|
+
} from "./chunk-W2TA4EVZ.js";
|
|
10
|
+
import {
|
|
11
|
+
hookOwnerOf
|
|
12
|
+
} from "./chunk-T4CKP47U.js";
|
|
13
|
+
import {
|
|
14
|
+
transcriptEnvironmentPreference,
|
|
15
|
+
transcriptsEnabled
|
|
16
|
+
} from "./chunk-WBD7HZEZ.js";
|
|
17
|
+
import {
|
|
18
|
+
readTranscriptPreference
|
|
19
|
+
} from "./chunk-TJZUQRMH.js";
|
|
10
20
|
import {
|
|
11
21
|
buildTranscriptRecords,
|
|
12
22
|
decodePublicKey,
|
|
13
23
|
generateSessionKey,
|
|
14
24
|
wrapSessionKey
|
|
15
|
-
} from "./chunk-
|
|
25
|
+
} from "./chunk-75M7NFFC.js";
|
|
16
26
|
import {
|
|
17
27
|
fetchTranscriptRecipients,
|
|
18
28
|
uploadTranscriptRecords
|
|
19
|
-
} from "./chunk-
|
|
20
|
-
import {
|
|
21
|
-
transcriptEnvironmentPreference,
|
|
22
|
-
transcriptsEnabled
|
|
23
|
-
} from "./chunk-QRNNIDGY.js";
|
|
24
|
-
import {
|
|
25
|
-
hookOwnerOf
|
|
26
|
-
} from "./chunk-NRSTNZYJ.js";
|
|
27
|
-
import {
|
|
28
|
-
readTranscriptPreference
|
|
29
|
-
} from "./chunk-M7VKFAAK.js";
|
|
29
|
+
} from "./chunk-MRQJCIFO.js";
|
|
30
30
|
import {
|
|
31
31
|
codexHome,
|
|
32
32
|
pusharyDir
|
|
33
|
-
} from "./chunk-
|
|
33
|
+
} from "./chunk-4JHEZ2PV.js";
|
|
34
34
|
import {
|
|
35
35
|
writeJsonAtomic
|
|
36
36
|
} from "./chunk-AQFEP65J.js";
|
|
37
37
|
import {
|
|
38
38
|
getApiKey,
|
|
39
39
|
getBaseUrl
|
|
40
|
-
} from "./chunk-
|
|
40
|
+
} from "./chunk-OWQOMGBF.js";
|
|
41
41
|
|
|
42
42
|
// src/transcript-registration.ts
|
|
43
43
|
import { createHash } from "crypto";
|
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
import {
|
|
2
2
|
pusharyDir
|
|
3
|
-
} from "./chunk-
|
|
3
|
+
} from "./chunk-4JHEZ2PV.js";
|
|
4
4
|
import {
|
|
5
5
|
readJsonSafe
|
|
6
6
|
} from "./chunk-AQFEP65J.js";
|
|
7
7
|
import {
|
|
8
8
|
isRecord
|
|
9
|
-
} from "./chunk-
|
|
9
|
+
} from "./chunk-JNU3LV47.js";
|
|
10
10
|
|
|
11
11
|
// src/process-ownership.ts
|
|
12
12
|
import { createHash, randomUUID } from "crypto";
|
|
@@ -3,11 +3,11 @@ import {
|
|
|
3
3
|
decodePublicKey,
|
|
4
4
|
generateSessionKey,
|
|
5
5
|
wrapSessionKey
|
|
6
|
-
} from "./chunk-
|
|
6
|
+
} from "./chunk-75M7NFFC.js";
|
|
7
7
|
import {
|
|
8
8
|
fetchTranscriptRecipients,
|
|
9
9
|
uploadTranscriptRecords
|
|
10
|
-
} from "./chunk-
|
|
10
|
+
} from "./chunk-MRQJCIFO.js";
|
|
11
11
|
|
|
12
12
|
// src/live-session.ts
|
|
13
13
|
var MAX_TRANSCRIPT_QUEUE = 100;
|
|
@@ -24,19 +24,11 @@ var liveSessionSleep = (ms, signal) => new Promise((resolve) => {
|
|
|
24
24
|
signal.addEventListener("abort", done, { once: true });
|
|
25
25
|
});
|
|
26
26
|
var postLiveSession = (options, path, body) => {
|
|
27
|
-
const controller = new AbortController();
|
|
28
|
-
const abort = () => controller.abort();
|
|
29
|
-
const timeout = setTimeout(abort, options.requestTimeoutMs ?? 1e4);
|
|
30
|
-
if (options.signal.aborted) abort();
|
|
31
|
-
else options.signal.addEventListener("abort", abort, { once: true });
|
|
32
27
|
return fetch(`${options.baseUrl}${path}`, {
|
|
33
28
|
method: "POST",
|
|
34
29
|
headers: { Authorization: `Bearer ${options.apiKey}`, "Content-Type": "application/json" },
|
|
35
30
|
body: JSON.stringify(body),
|
|
36
|
-
signal:
|
|
37
|
-
}).finally(() => {
|
|
38
|
-
clearTimeout(timeout);
|
|
39
|
-
options.signal.removeEventListener("abort", abort);
|
|
31
|
+
signal: AbortSignal.any([options.signal, AbortSignal.timeout(options.requestTimeoutMs ?? 1e4)])
|
|
40
32
|
});
|
|
41
33
|
};
|
|
42
34
|
var postLiveSessionUntilAccepted = async (options, path, body) => {
|
|
@@ -1,13 +1,14 @@
|
|
|
1
1
|
import {
|
|
2
2
|
MCP_BRIDGE_BINARY
|
|
3
|
-
} from "./chunk-
|
|
3
|
+
} from "./chunk-TWATOPHK.js";
|
|
4
4
|
import {
|
|
5
5
|
KEY_FILE_MODE
|
|
6
|
-
} from "./chunk-
|
|
6
|
+
} from "./chunk-TJZUQRMH.js";
|
|
7
7
|
import {
|
|
8
|
+
NpmInstallError,
|
|
8
9
|
NpmMissingError,
|
|
9
10
|
NpmPermissionError
|
|
10
|
-
} from "./chunk-
|
|
11
|
+
} from "./chunk-4JHEZ2PV.js";
|
|
11
12
|
import {
|
|
12
13
|
readJsonSafe,
|
|
13
14
|
writeFileAtomic,
|
|
@@ -15,7 +16,10 @@ import {
|
|
|
15
16
|
} from "./chunk-AQFEP65J.js";
|
|
16
17
|
import {
|
|
17
18
|
NPX_LATEST_COMMAND
|
|
18
|
-
} from "./chunk-
|
|
19
|
+
} from "./chunk-T3KMJI4W.js";
|
|
20
|
+
import {
|
|
21
|
+
readSetupAgentFailures
|
|
22
|
+
} from "./chunk-JNU3LV47.js";
|
|
19
23
|
|
|
20
24
|
// src/instruction-file.ts
|
|
21
25
|
import { existsSync, readFileSync, writeFileSync, mkdirSync, rmSync } from "fs";
|
|
@@ -35,6 +39,7 @@ You have Pushary MCP tools that reach the user on their phone. Use them proactiv
|
|
|
35
39
|
- When meaningful work finishes while the user is away, or they requested an alert, call \`send_notification\` so the user knows it is done. Skip trivial completions and duplicate reports to someone already reading. Always pass \`context\` with a \`type\` of "task_complete", "error" or "info": it is what tells Pushary this is a task update, so the user's own setting for where updates land can route it.
|
|
36
40
|
- Confirm notifications can offer lock-screen actions; arbitrary choices and text open the app. The Mac notch handles personal account questions, not Partner customer enrollment.
|
|
37
41
|
- Use \`cancel_question\` to retract a pending question once it is no longer needed.
|
|
42
|
+
- When the user asks to be reminded later, call \`schedule_reminder\` with \`body\` and either \`inMinutes\` or \`at\` with an explicit UTC offset. Confirm the returned time, never guess their timezone, and do not use \`ask_user\` as a reminder. Pushary saves it and delivers after this agent exits. Call with no arguments to list pending reminders or \`cancelReminderId\` to cancel one before dispatch starts.
|
|
38
43
|
- Respect the user's Pushary delivery mode: it decides where an approval is surfaced (phone, terminal, or awareness only), not whether it is required. In Terminal mode do not expect a phone answer; the approval waits in the terminal. If the Pushary hook already gated an action, a single approval is enough, do not ask again.
|
|
39
44
|
|
|
40
45
|
Pass \`agentName\` as "${label} - <project folder name>" so the user knows which session is asking. If a question times out, follow \`handoffAction\` when present, otherwise \`nextAction\`: keep waiting with the same correlationId while pending. A poll ending is not question expiry. Cancel only for an explicit handoff or when the answer is no longer needed. If cancellation returns \`handoffAction: "stop"\`, stop. Otherwise, if cancellation returns false, poll once for 1 second and honor the answer that won the race.`;
|
|
@@ -103,7 +108,8 @@ var FX_TOOL_DISCOVERY_NOTE = 'In fx, these tools are named mcp_pushary_ask_user,
|
|
|
103
108
|
var FX_AGENT_LABEL = "fx";
|
|
104
109
|
var fxInstructionsBody = () => `${renderAgentInstructions(FX_AGENT_LABEL)}
|
|
105
110
|
|
|
106
|
-
${FX_TOOL_DISCOVERY_NOTE}
|
|
111
|
+
${FX_TOOL_DISCOVERY_NOTE}
|
|
112
|
+
For a reminder later, select mcp_pushary_schedule_reminder with mcp_select_tool, then call it. Pushary schedules delivery on its server; fx can exit.`;
|
|
107
113
|
var ALLOW_ACTION = "allow";
|
|
108
114
|
var PERMISSION_KEY = "permission";
|
|
109
115
|
var WORKSPACES_KEY = "workspaces";
|
|
@@ -459,6 +465,23 @@ var fxIgnoresInstructionsFile = (path, fxDir) => {
|
|
|
459
465
|
}
|
|
460
466
|
};
|
|
461
467
|
|
|
468
|
+
// src/setup/config-write.ts
|
|
469
|
+
var AgentConfigWriteError = class extends Error {
|
|
470
|
+
constructor(error) {
|
|
471
|
+
super(error instanceof Error ? error.message : String(error), { cause: error });
|
|
472
|
+
this.name = "AgentConfigWriteError";
|
|
473
|
+
}
|
|
474
|
+
};
|
|
475
|
+
var writeSetupConfigFile = (path, content, mode = 384) => {
|
|
476
|
+
try {
|
|
477
|
+
writeFileAtomic(path, content, mode);
|
|
478
|
+
} catch (error) {
|
|
479
|
+
throw new AgentConfigWriteError(error);
|
|
480
|
+
}
|
|
481
|
+
};
|
|
482
|
+
var writeSetupConfigJson = (path, value, mode) => writeSetupConfigFile(path, `${JSON.stringify(value, null, 2)}
|
|
483
|
+
`, mode);
|
|
484
|
+
|
|
462
485
|
// src/setup/agent-failure.ts
|
|
463
486
|
var AgentConfigError = class extends Error {
|
|
464
487
|
kind;
|
|
@@ -483,7 +506,8 @@ var describedAgentFailure = (agent, kind) => ({
|
|
|
483
506
|
agent,
|
|
484
507
|
kind,
|
|
485
508
|
detail: AGENT_FAILURE_DETAILS[kind],
|
|
486
|
-
remedy: DESCRIBED_FAILURE_REMEDIES[kind]
|
|
509
|
+
remedy: DESCRIBED_FAILURE_REMEDIES[kind],
|
|
510
|
+
stage: kind === "not-wired" ? "hook-validation" : "account-check"
|
|
487
511
|
});
|
|
488
512
|
var NPM_PERMISSION_REMEDIES = {
|
|
489
513
|
"global-prefix": "fix-npm-prefix",
|
|
@@ -494,11 +518,22 @@ var remedyForError = (error) => {
|
|
|
494
518
|
if (error instanceof NpmPermissionError) return NPM_PERMISSION_REMEDIES[error.kind];
|
|
495
519
|
return "retry-agent";
|
|
496
520
|
};
|
|
521
|
+
var setupFailureDiagnostic = (error) => {
|
|
522
|
+
if (error instanceof AgentConfigError) return { stage: "config-read" };
|
|
523
|
+
if (error instanceof AgentConfigWriteError) return { stage: "config-write", diagnosticCode: "config-write-failed" };
|
|
524
|
+
if (error instanceof NpmMissingError) return { stage: "runtime-install", diagnosticCode: "npm-missing" };
|
|
525
|
+
if (error instanceof NpmPermissionError) {
|
|
526
|
+
return { stage: "runtime-install", diagnosticCode: error.kind === "global-prefix" ? "npm-global-prefix-denied" : "npm-file-in-use" };
|
|
527
|
+
}
|
|
528
|
+
if (error instanceof NpmInstallError) return { stage: "runtime-install", diagnosticCode: "npm-install-failed" };
|
|
529
|
+
return { stage: "unknown" };
|
|
530
|
+
};
|
|
497
531
|
var agentFailureFromError = (agent, error, describeError) => ({
|
|
498
532
|
agent,
|
|
499
533
|
kind: error instanceof AgentConfigError ? error.kind : "installer-error",
|
|
500
534
|
detail: describeError(error),
|
|
501
|
-
remedy: remedyForError(error)
|
|
535
|
+
remedy: remedyForError(error),
|
|
536
|
+
...setupFailureDiagnostic(error)
|
|
502
537
|
});
|
|
503
538
|
var retryAgentCommand = (agent) => `${NPX_LATEST_COMMAND} setup --agents ${agent}`;
|
|
504
539
|
var takeOverHooksCommand = (agent) => `${retryAgentCommand(agent)} --take-over-hooks`;
|
|
@@ -511,7 +546,7 @@ var describeMacAccountMismatch = (mismatch) => [
|
|
|
511
546
|
var REMAINING_AGENTS_CONTINUE = "Other agents will continue. Re-run setup to retry.";
|
|
512
547
|
var afterAgentFailureNote = (agentsStillToSetUp) => agentsStillToSetUp > 0 ? REMAINING_AGENTS_CONTINUE : null;
|
|
513
548
|
var failedAgentsContext = (configuredAgentNames) => configuredAgentNames.length > 0 ? `(configured: ${configuredAgentNames.join(", ")})` : null;
|
|
514
|
-
var agentFailureWire = (failures) => failures
|
|
549
|
+
var agentFailureWire = (failures) => readSetupAgentFailures(failures);
|
|
515
550
|
|
|
516
551
|
// src/fx-lifecycle.ts
|
|
517
552
|
import { existsSync as existsSync3 } from "fs";
|
|
@@ -642,6 +677,8 @@ export {
|
|
|
642
677
|
withFxPusharyServer,
|
|
643
678
|
FX_QUESTION_TOOL,
|
|
644
679
|
fxIgnoresInstructionsFile,
|
|
680
|
+
writeSetupConfigFile,
|
|
681
|
+
writeSetupConfigJson,
|
|
645
682
|
AgentConfigError,
|
|
646
683
|
configFailureKind,
|
|
647
684
|
describedAgentFailure,
|
|
@@ -1,16 +1,16 @@
|
|
|
1
1
|
import {
|
|
2
2
|
readExistingMachineId
|
|
3
|
-
} from "./chunk-
|
|
3
|
+
} from "./chunk-WMO2XVG4.js";
|
|
4
4
|
import {
|
|
5
5
|
NetworkError
|
|
6
6
|
} from "./chunk-7QLSKOSU.js";
|
|
7
7
|
import {
|
|
8
8
|
getBaseUrl
|
|
9
|
-
} from "./chunk-
|
|
9
|
+
} from "./chunk-OWQOMGBF.js";
|
|
10
10
|
import {
|
|
11
11
|
clientContextHeaders,
|
|
12
12
|
getPackageVersion
|
|
13
|
-
} from "./chunk-
|
|
13
|
+
} from "./chunk-JNU3LV47.js";
|
|
14
14
|
|
|
15
15
|
// src/cli/net.ts
|
|
16
16
|
import { createRequire } from "module";
|
|
@@ -5,16 +5,16 @@ import {
|
|
|
5
5
|
import {
|
|
6
6
|
NOTIFICATION_MATCHED_TYPES,
|
|
7
7
|
POSTTOOLUSE_MIRRORED_TOOLS
|
|
8
|
-
} from "./chunk-
|
|
8
|
+
} from "./chunk-CAJCCQ7N.js";
|
|
9
9
|
import {
|
|
10
10
|
isProtectedByScope,
|
|
11
11
|
registerHookEntry
|
|
12
|
-
} from "./chunk-
|
|
12
|
+
} from "./chunk-4JHEZ2PV.js";
|
|
13
13
|
import {
|
|
14
14
|
CLAUDE_PRETOOLUSE_MATCHER,
|
|
15
15
|
HOOK_BUDGETS,
|
|
16
16
|
HOOK_LOCATOR_BINARY
|
|
17
|
-
} from "./chunk-
|
|
17
|
+
} from "./chunk-JNU3LV47.js";
|
|
18
18
|
|
|
19
19
|
// src/gemini-config.ts
|
|
20
20
|
var GEMINI_HOOK_BINARY = "pushary-gemini-hook";
|
|
@@ -0,0 +1,196 @@
|
|
|
1
|
+
import {
|
|
2
|
+
liveSessionSleep,
|
|
3
|
+
postLiveSession
|
|
4
|
+
} from "./chunk-PQAFH4DF.js";
|
|
5
|
+
import {
|
|
6
|
+
isWaitForAnswerResponse,
|
|
7
|
+
repoKeyFor,
|
|
8
|
+
writeDegraded
|
|
9
|
+
} from "./chunk-GOEIW2VH.js";
|
|
10
|
+
import {
|
|
11
|
+
callMcpTool
|
|
12
|
+
} from "./chunk-53UZN7JW.js";
|
|
13
|
+
import {
|
|
14
|
+
CODEX_NATIVE_APPROVAL_CAPABILITY,
|
|
15
|
+
CODEX_NATIVE_APPROVAL_METHODS,
|
|
16
|
+
canonicalJsonText,
|
|
17
|
+
codexNativeApprovalResponse,
|
|
18
|
+
parseCodexNativeApproval
|
|
19
|
+
} from "./chunk-JNU3LV47.js";
|
|
20
|
+
|
|
21
|
+
// src/codex-native-approvals.ts
|
|
22
|
+
import { createHash, randomUUID } from "crypto";
|
|
23
|
+
var record = (value) => value !== null && typeof value === "object" && !Array.isArray(value);
|
|
24
|
+
var validId = (id) => typeof id === "string" && id.length > 0 && id.length <= 200 || typeof id === "number" && Number.isSafeInteger(id);
|
|
25
|
+
var PATCH_LIMIT = 32;
|
|
26
|
+
var WAIT_LIMIT_MS = 3e5;
|
|
27
|
+
var CodexNativeApprovals = class {
|
|
28
|
+
constructor(options) {
|
|
29
|
+
this.options = options;
|
|
30
|
+
}
|
|
31
|
+
generation = randomUUID();
|
|
32
|
+
pending = /* @__PURE__ */ new Map();
|
|
33
|
+
retired = /* @__PURE__ */ new Set();
|
|
34
|
+
patches = /* @__PURE__ */ new Map();
|
|
35
|
+
tasks = /* @__PURE__ */ new Set();
|
|
36
|
+
closed = false;
|
|
37
|
+
handle(message, threadId) {
|
|
38
|
+
if (this.closed || !message.method) return false;
|
|
39
|
+
const p = message.params ?? {};
|
|
40
|
+
if (message.id === void 0) {
|
|
41
|
+
this.observe(message.method, p);
|
|
42
|
+
return false;
|
|
43
|
+
}
|
|
44
|
+
if (!validId(message.id) || !CODEX_NATIVE_APPROVAL_METHODS.some((method) => method === message.method)) return false;
|
|
45
|
+
if (this.retired.has(message.id)) return true;
|
|
46
|
+
const changes = this.patches.get(this.patchKey(p));
|
|
47
|
+
const approval = parseCodexNativeApproval({ method: message.method, params: p, ...changes ? { changes } : {} });
|
|
48
|
+
if (!approval || approval.threadId !== threadId) return false;
|
|
49
|
+
const repoKey = repoKeyFor(approval.cwd ?? this.options.cwd);
|
|
50
|
+
const subjectHash = createHash("sha256").update(canonicalJsonText({ request: approval.request, cwd: this.options.cwd, repoKey })).digest("hex");
|
|
51
|
+
const existing = this.pending.get(message.id);
|
|
52
|
+
if (existing) {
|
|
53
|
+
if (existing.owner.subjectHash !== subjectHash) this.retire(message.id, existing, false);
|
|
54
|
+
return true;
|
|
55
|
+
}
|
|
56
|
+
if (this.pending.size >= 8) return false;
|
|
57
|
+
const owner = {
|
|
58
|
+
capability: CODEX_NATIVE_APPROVAL_CAPABILITY,
|
|
59
|
+
machineId: this.options.machineId,
|
|
60
|
+
generation: this.generation,
|
|
61
|
+
threadId: approval.threadId,
|
|
62
|
+
requestId: message.id,
|
|
63
|
+
subjectHash,
|
|
64
|
+
method: approval.request.method
|
|
65
|
+
};
|
|
66
|
+
const pending = { owner, approval, repoKey, controller: new AbortController(), replied: false, creating: true, correlationId: randomUUID() };
|
|
67
|
+
this.pending.set(message.id, pending);
|
|
68
|
+
const task = this.answer(pending).finally(() => {
|
|
69
|
+
this.tasks.delete(task);
|
|
70
|
+
});
|
|
71
|
+
this.tasks.add(task);
|
|
72
|
+
return true;
|
|
73
|
+
}
|
|
74
|
+
async close() {
|
|
75
|
+
this.closed = true;
|
|
76
|
+
for (const [id, pending] of this.pending) this.retire(id, pending, false);
|
|
77
|
+
await Promise.allSettled(this.tasks);
|
|
78
|
+
}
|
|
79
|
+
patchKey(params) {
|
|
80
|
+
return JSON.stringify([params.threadId, params.turnId, params.itemId]);
|
|
81
|
+
}
|
|
82
|
+
observe(method, params) {
|
|
83
|
+
if (method === "item/started" && record(params.item) && params.item.type === "fileChange" && Array.isArray(params.item.changes)) {
|
|
84
|
+
if (this.patches.size >= PATCH_LIMIT) this.patches.delete(this.patches.keys().next().value ?? "");
|
|
85
|
+
this.patches.set(this.patchKey({ ...params, itemId: params.item.id }), params.item.changes);
|
|
86
|
+
}
|
|
87
|
+
for (const [id, pending] of this.pending) {
|
|
88
|
+
const a = pending.approval;
|
|
89
|
+
const resolved = method === "serverRequest/resolved" && params.requestId === id;
|
|
90
|
+
const sameThread = params.threadId === a.threadId;
|
|
91
|
+
const closed = sameThread && (method === "thread/closed" || method === "thread/archived" || method === "turn/completed" && record(params.turn) && params.turn.id === a.turnId || method === "item/completed" && params.turnId === a.turnId && record(params.item) && params.item.id === a.itemId);
|
|
92
|
+
const patchChanged = method === "item/fileChange/patchUpdated" && sameThread && params.turnId === a.turnId && params.itemId === a.itemId;
|
|
93
|
+
if (resolved || closed || patchChanged) this.retire(id, pending, resolved || closed);
|
|
94
|
+
}
|
|
95
|
+
if (method === "item/fileChange/patchUpdated") this.patches.delete(this.patchKey(params));
|
|
96
|
+
if (method === "turn/completed" || method === "thread/closed") this.patches.clear();
|
|
97
|
+
}
|
|
98
|
+
retire(id, pending, nativeClosed) {
|
|
99
|
+
pending.controller.abort();
|
|
100
|
+
this.pending.delete(id);
|
|
101
|
+
this.retired.add(id);
|
|
102
|
+
if (!nativeClosed && !this.closed && !pending.replied && !this.options.shared) {
|
|
103
|
+
this.options.reply(id, codexNativeApprovalResponse(pending.approval, "Deny"));
|
|
104
|
+
pending.replied = true;
|
|
105
|
+
}
|
|
106
|
+
const task = this.cleanup(pending, nativeClosed).finally(() => {
|
|
107
|
+
this.tasks.delete(task);
|
|
108
|
+
});
|
|
109
|
+
this.tasks.add(task);
|
|
110
|
+
}
|
|
111
|
+
async post(pending, operation, signal) {
|
|
112
|
+
const boundedSignal = AbortSignal.any([signal, AbortSignal.timeout(this.options.requestTimeoutMs ?? 1e4)]);
|
|
113
|
+
const response = await postLiveSession({ ...this.options, signal: boundedSignal }, "/api/agent/native-approval", {
|
|
114
|
+
operation,
|
|
115
|
+
owner: pending.owner,
|
|
116
|
+
request: pending.approval.request,
|
|
117
|
+
correlationId: pending.correlationId,
|
|
118
|
+
claimId: pending.claimId,
|
|
119
|
+
localSurfaceAvailable: this.options.shared,
|
|
120
|
+
cwd: this.options.cwd,
|
|
121
|
+
repoKey: pending.repoKey
|
|
122
|
+
});
|
|
123
|
+
const body = await response.json();
|
|
124
|
+
if (!response.ok || !record(body)) throw new Error("Native approval service unavailable");
|
|
125
|
+
return body;
|
|
126
|
+
}
|
|
127
|
+
async cleanup(pending, nativeClosed) {
|
|
128
|
+
if (pending.creating || !pending.correlationId) return;
|
|
129
|
+
try {
|
|
130
|
+
const signal = AbortSignal.timeout(3e3);
|
|
131
|
+
while (!signal.aborted) {
|
|
132
|
+
const result = await this.post(pending, nativeClosed ? "request_closed" : "unavailable", signal);
|
|
133
|
+
if (result.recorded === true) return;
|
|
134
|
+
await liveSessionSleep(100, signal);
|
|
135
|
+
}
|
|
136
|
+
throw new Error("Native approval cleanup not recorded");
|
|
137
|
+
} catch {
|
|
138
|
+
writeDegraded("questions", { reason: "native_approval_cleanup_unconfirmed", fallback: "expiry", event: pending.owner.method });
|
|
139
|
+
}
|
|
140
|
+
}
|
|
141
|
+
async answer(pending) {
|
|
142
|
+
const signal = AbortSignal.any([this.options.signal, pending.controller.signal, AbortSignal.timeout(WAIT_LIMIT_MS)]);
|
|
143
|
+
try {
|
|
144
|
+
let created;
|
|
145
|
+
try {
|
|
146
|
+
created = await this.post(pending, "create", AbortSignal.timeout(this.options.requestTimeoutMs ?? 1e4));
|
|
147
|
+
pending.correlationId = typeof created.correlationId === "string" ? created.correlationId : void 0;
|
|
148
|
+
} finally {
|
|
149
|
+
pending.creating = false;
|
|
150
|
+
}
|
|
151
|
+
if (signal.aborted) return;
|
|
152
|
+
if (created.kind === "deny") {
|
|
153
|
+
this.options.reply(pending.owner.requestId, codexNativeApprovalResponse(pending.approval, "Deny"));
|
|
154
|
+
pending.replied = true;
|
|
155
|
+
return;
|
|
156
|
+
}
|
|
157
|
+
if (created.kind !== "ask" || !pending.correlationId) throw new Error("Native approval unavailable");
|
|
158
|
+
let answer = null;
|
|
159
|
+
while (!signal.aborted) {
|
|
160
|
+
const result = await callMcpTool(
|
|
161
|
+
this.options.apiKey,
|
|
162
|
+
"wait_for_answer",
|
|
163
|
+
{ correlationId: pending.correlationId, timeoutMs: 25e3 },
|
|
164
|
+
{ baseUrl: this.options.baseUrl, signal, timeoutMs: 27e3, maxRetries: 1 }
|
|
165
|
+
);
|
|
166
|
+
if (!isWaitForAnswerResponse(result)) throw new Error("Invalid native approval answer");
|
|
167
|
+
if (result.answered) {
|
|
168
|
+
answer = typeof result.value === "string" ? result.value : null;
|
|
169
|
+
break;
|
|
170
|
+
}
|
|
171
|
+
if (!("status" in result) || result.status !== "pending") throw new Error("Native approval no longer pending");
|
|
172
|
+
await liveSessionSleep(100, signal);
|
|
173
|
+
}
|
|
174
|
+
if (signal.aborted || !answer || !pending.approval.options.includes(answer)) throw new Error("No supported approval answer");
|
|
175
|
+
const claim = await this.post(pending, "claim", signal);
|
|
176
|
+
if (typeof claim.claimId !== "string" || !claim.claimId) throw new Error("Native approval dispatch refused");
|
|
177
|
+
pending.claimId = claim.claimId;
|
|
178
|
+
if (signal.aborted || this.pending.get(pending.owner.requestId) !== pending) return;
|
|
179
|
+
this.options.reply(pending.owner.requestId, codexNativeApprovalResponse(pending.approval, answer));
|
|
180
|
+
pending.replied = true;
|
|
181
|
+
await this.post(pending, "reply_queued", AbortSignal.timeout(3e3));
|
|
182
|
+
} catch {
|
|
183
|
+
if (!pending.controller.signal.aborted && !this.options.signal.aborted && !this.closed && !this.options.shared && !pending.replied) {
|
|
184
|
+
this.options.reply(pending.owner.requestId, codexNativeApprovalResponse(pending.approval, "Deny"));
|
|
185
|
+
pending.replied = true;
|
|
186
|
+
}
|
|
187
|
+
if (!pending.controller.signal.aborted && !this.options.signal.aborted) writeDegraded("questions", { reason: "native_approval_unavailable", fallback: this.options.shared ? "native client" : "refused", event: pending.owner.method });
|
|
188
|
+
} finally {
|
|
189
|
+
if (!pending.claimId || !pending.replied || signal.aborted) await this.cleanup(pending, false);
|
|
190
|
+
}
|
|
191
|
+
}
|
|
192
|
+
};
|
|
193
|
+
|
|
194
|
+
export {
|
|
195
|
+
CodexNativeApprovals
|
|
196
|
+
};
|
|
@@ -2,25 +2,25 @@ import {
|
|
|
2
2
|
SIGNED_OUT_ON_MAC_MESSAGE,
|
|
3
3
|
describeSignedOutKey,
|
|
4
4
|
readSignedOutDiagnosis
|
|
5
|
-
} from "./chunk-
|
|
5
|
+
} from "./chunk-42CVAOC5.js";
|
|
6
6
|
import {
|
|
7
7
|
createIo
|
|
8
8
|
} from "./chunk-FO3MDD26.js";
|
|
9
9
|
import {
|
|
10
10
|
readKeySource
|
|
11
|
-
} from "./chunk-
|
|
11
|
+
} from "./chunk-TJZUQRMH.js";
|
|
12
12
|
import {
|
|
13
13
|
absoluteUrl,
|
|
14
14
|
checkApiKey,
|
|
15
15
|
describeKeyCheck,
|
|
16
16
|
keyCheckFromResponse
|
|
17
|
-
} from "./chunk-
|
|
17
|
+
} from "./chunk-TKTS3SIM.js";
|
|
18
18
|
import {
|
|
19
19
|
EXIT
|
|
20
20
|
} from "./chunk-KZERVKTD.js";
|
|
21
21
|
import {
|
|
22
22
|
getBaseUrl
|
|
23
|
-
} from "./chunk-
|
|
23
|
+
} from "./chunk-OWQOMGBF.js";
|
|
24
24
|
|
|
25
25
|
// src/cli/report-key.ts
|
|
26
26
|
var { dim, yellow } = createIo();
|
|
@@ -2,7 +2,7 @@ import {
|
|
|
2
2
|
DISCONNECT_AGENT_IDS,
|
|
3
3
|
SETUP_AGENT_CHOICES,
|
|
4
4
|
isApprovalMode
|
|
5
|
-
} from "./chunk-
|
|
5
|
+
} from "./chunk-JNU3LV47.js";
|
|
6
6
|
|
|
7
7
|
// src/cli/mode-request.ts
|
|
8
8
|
var parseDuration = (value) => {
|
|
@@ -36,6 +36,7 @@ var describeMode = (mode) => {
|
|
|
36
36
|
var npxLatestCommandFor = (platform) => `${platform === "win32" ? "npx.cmd" : "npx"} pushary@latest`;
|
|
37
37
|
var NPX_LATEST_COMMAND = npxLatestCommandFor(process.platform);
|
|
38
38
|
var COMMAND_LIST = [
|
|
39
|
+
{ name: "codex", module: "pushary-codex-session", summary: "Start a managed Codex terminal session with Pushary native approvals", detail: ["Use --cwd <directory> to choose a project. Existing desktop chats are not attached."] },
|
|
39
40
|
{
|
|
40
41
|
name: "cowork",
|
|
41
42
|
module: "pushary-cowork",
|