@pushary/agent-hooks 0.90.1 → 0.91.0
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 +27 -0
- package/dist/bin/pushary-bell.js +6 -61
- package/dist/bin/pushary-claude.js +5 -5
- package/dist/bin/pushary-clean.js +98 -14
- package/dist/bin/pushary-codex-bridge.js +3 -3
- package/dist/bin/pushary-codex-hook.js +3 -3
- package/dist/bin/pushary-codex.js +3 -3
- package/dist/bin/pushary-connect.js +2 -2
- package/dist/bin/pushary-daemon.js +9 -9
- package/dist/bin/pushary-disconnect.js +2 -2
- package/dist/bin/pushary-doctor.js +13 -13
- package/dist/bin/pushary-elicitation-hook.js +2 -2
- package/dist/bin/pushary-gemini-bridge.js +3 -3
- package/dist/bin/pushary-gemini-hook.js +3 -3
- package/dist/bin/pushary-hook.js +4 -4
- package/dist/bin/pushary-login.js +4 -4
- package/dist/bin/pushary-logout.js +1 -1
- package/dist/bin/pushary-mode.js +2 -2
- package/dist/bin/pushary-notification-hook.js +3 -3
- package/dist/bin/pushary-opencode-hook.js +3 -3
- package/dist/bin/pushary-permission-denied-hook.js +4 -4
- package/dist/bin/pushary-permission-hook.js +4 -4
- package/dist/bin/pushary-post-hook.js +3 -3
- package/dist/bin/pushary-prompt-hook.js +3 -3
- package/dist/bin/pushary-session-end-hook.js +3 -3
- package/dist/bin/pushary-session-start-hook.js +3 -3
- package/dist/bin/pushary-setup.js +127 -180
- package/dist/bin/pushary-status.js +4 -4
- package/dist/bin/pushary-stop-hook.js +3 -3
- package/dist/bin/pushary-stopfailure-hook.js +3 -3
- package/dist/bin/pushary-upgrade.js +8 -8
- package/dist/bin/pushary-wait.js +2 -2
- package/dist/{chunk-B6H2KAQC.js → chunk-4IEW4ZRF.js} +2 -2
- package/dist/{chunk-54ELC7D7.js → chunk-AWHCZOZO.js} +1 -1
- package/dist/chunk-B65JGBIZ.js +539 -0
- package/dist/{chunk-KUZWXPUS.js → chunk-BVNYTQ5I.js} +23 -0
- package/dist/{chunk-AJYV3VGU.js → chunk-BXTJVM7O.js} +2 -0
- package/dist/{chunk-FQL5E6NG.js → chunk-CRVJCKIN.js} +85 -2
- package/dist/chunk-DSTLA2TC.js +68 -0
- package/dist/{chunk-GL3FFM7A.js → chunk-ELHCIEMM.js} +1 -1
- package/dist/{chunk-Y6BWPERV.js → chunk-GQ5ZC2QY.js} +1 -1
- package/dist/chunk-GU3EJCVV.js +43 -0
- package/dist/{chunk-4LOPSGLP.js → chunk-TVZQMPB7.js} +1 -1
- package/dist/{chunk-BQBEH6TV.js → chunk-VAMBUKXH.js} +4 -4
- package/dist/{chunk-DZDI62LY.js → chunk-WGKC6PU2.js} +2 -2
- package/dist/{chunk-7TPQEWUZ.js → chunk-YTD6PJM7.js} +1 -1
- package/dist/{chunk-H2QZRQR2.js → chunk-YTDH3XCE.js} +1 -1
- package/dist/{chunk-F2ICEWZL.js → chunk-Z4XCN2HH.js} +2 -2
- package/dist/{chunk-DYP6SMOR.js → chunk-Z6RFZKY4.js} +1 -1
- package/dist/src/index.js +4 -4
- package/package.json +1 -1
- package/dist/chunk-AZPIQG4G.js +0 -274
- package/dist/chunk-S6LYP7QA.js +0 -127
|
@@ -4,40 +4,54 @@ import {
|
|
|
4
4
|
} from "../chunk-Z3Z4VK5F.js";
|
|
5
5
|
import {
|
|
6
6
|
detectClaudeVersion
|
|
7
|
-
} from "../chunk-
|
|
7
|
+
} from "../chunk-YTDH3XCE.js";
|
|
8
8
|
import {
|
|
9
9
|
describeVersionManagerPin,
|
|
10
|
-
isBridgeLocator,
|
|
11
10
|
versionManagerOf
|
|
12
|
-
} from "../chunk-
|
|
11
|
+
} from "../chunk-GU3EJCVV.js";
|
|
13
12
|
import {
|
|
14
13
|
waitForMachineReadiness
|
|
15
|
-
} from "../chunk-
|
|
14
|
+
} from "../chunk-YTD6PJM7.js";
|
|
16
15
|
import {
|
|
16
|
+
AGENT_CHOICES,
|
|
17
17
|
HERMES_CONFIG_SCRIPT,
|
|
18
|
+
HERMES_PIP_PACKAGE,
|
|
19
|
+
KEEP_HINT,
|
|
20
|
+
captureHookTakeover,
|
|
21
|
+
captureMcpServer,
|
|
22
|
+
describeAppOwnership,
|
|
23
|
+
describeHookOwnership,
|
|
18
24
|
describeSetupSideEffects,
|
|
25
|
+
effectiveControlMode,
|
|
26
|
+
effectiveVerify,
|
|
27
|
+
hookOwnerOf,
|
|
19
28
|
isHermesConfigReceipt,
|
|
29
|
+
mcpBearerKey,
|
|
30
|
+
parseSetupOptions,
|
|
31
|
+
planHooks,
|
|
20
32
|
resolveHermesPython,
|
|
21
33
|
runHermesPythonScript
|
|
22
|
-
} from "../chunk-
|
|
34
|
+
} from "../chunk-B65JGBIZ.js";
|
|
23
35
|
import {
|
|
24
36
|
describeDetection,
|
|
25
37
|
detectAllAgents,
|
|
26
38
|
isDetected,
|
|
39
|
+
liveBridgeProbe,
|
|
27
40
|
pluginLocationSnippet,
|
|
28
41
|
registerPluginLocation,
|
|
29
42
|
renderAgentInstructions,
|
|
30
43
|
renderProjectAgentInstructions,
|
|
44
|
+
resolveBridgeStub,
|
|
31
45
|
shortenHome,
|
|
32
46
|
vscodeSettingsTargets,
|
|
33
47
|
writeInstructionBlock
|
|
34
|
-
} from "../chunk-
|
|
48
|
+
} from "../chunk-CRVJCKIN.js";
|
|
35
49
|
import {
|
|
36
50
|
claudeWired,
|
|
37
51
|
codexWired,
|
|
38
52
|
geminiWired,
|
|
39
53
|
pusharyHookExecutable
|
|
40
|
-
} from "../chunk-
|
|
54
|
+
} from "../chunk-WGKC6PU2.js";
|
|
41
55
|
import {
|
|
42
56
|
OPENCODE_HOOK_BINARY,
|
|
43
57
|
addOpenCodeMcpServer,
|
|
@@ -61,8 +75,9 @@ import {
|
|
|
61
75
|
isClaudeMcpSnapshot,
|
|
62
76
|
parseVersion,
|
|
63
77
|
updateClaudeMcpSnapshot
|
|
64
|
-
} from "../chunk-
|
|
78
|
+
} from "../chunk-ELHCIEMM.js";
|
|
65
79
|
import "../chunk-2LAHXHBR.js";
|
|
80
|
+
import "../chunk-DSTLA2TC.js";
|
|
66
81
|
import {
|
|
67
82
|
guardBinary,
|
|
68
83
|
guardCursorGate,
|
|
@@ -80,7 +95,7 @@ import {
|
|
|
80
95
|
replaceDaemonService,
|
|
81
96
|
stopDaemonService,
|
|
82
97
|
waitForDaemonRemoteProof
|
|
83
|
-
} from "../chunk-
|
|
98
|
+
} from "../chunk-Z4XCN2HH.js";
|
|
84
99
|
import {
|
|
85
100
|
detectProviderLiveCapabilities,
|
|
86
101
|
hasSpawnProvider,
|
|
@@ -98,14 +113,15 @@ import {
|
|
|
98
113
|
} from "../chunk-L4ZCFMWW.js";
|
|
99
114
|
import {
|
|
100
115
|
reportEvent
|
|
101
|
-
} from "../chunk-
|
|
116
|
+
} from "../chunk-TVZQMPB7.js";
|
|
102
117
|
import "../chunk-F7OURW3C.js";
|
|
103
118
|
import "../chunk-L4E2BIJ2.js";
|
|
104
|
-
import "../chunk-
|
|
119
|
+
import "../chunk-AWHCZOZO.js";
|
|
105
120
|
import {
|
|
106
121
|
addCodexHookTrust,
|
|
107
122
|
addCodexHooks,
|
|
108
123
|
addCodexMcpServer,
|
|
124
|
+
captureCodexHookTrust,
|
|
109
125
|
claudeJson,
|
|
110
126
|
claudeMcpReceipt,
|
|
111
127
|
claudeSettings,
|
|
@@ -118,12 +134,17 @@ import {
|
|
|
118
134
|
codexTrustSchemeAgrees,
|
|
119
135
|
cursorPluginDir,
|
|
120
136
|
cursorUserHooks,
|
|
137
|
+
cursorUserMcp,
|
|
121
138
|
geminiMd,
|
|
122
139
|
geminiSettings,
|
|
123
140
|
hermesConfigReceipt,
|
|
141
|
+
hookTakeoverReceipt,
|
|
124
142
|
pusharyConfigFile,
|
|
125
|
-
|
|
126
|
-
|
|
143
|
+
pusharyDir,
|
|
144
|
+
readCodexMcpAuth,
|
|
145
|
+
vscodePluginDir,
|
|
146
|
+
vscodePluginMcp
|
|
147
|
+
} from "../chunk-BVNYTQ5I.js";
|
|
127
148
|
import {
|
|
128
149
|
confirmAppConnection,
|
|
129
150
|
connectDevice,
|
|
@@ -136,17 +157,16 @@ import {
|
|
|
136
157
|
import "../chunk-3EGEA4KH.js";
|
|
137
158
|
import {
|
|
138
159
|
checkApiKey,
|
|
139
|
-
describeKeyCheck
|
|
140
|
-
|
|
160
|
+
describeKeyCheck,
|
|
161
|
+
samePusharyAccount
|
|
162
|
+
} from "../chunk-BXTJVM7O.js";
|
|
141
163
|
import {
|
|
142
164
|
setHumanStream
|
|
143
165
|
} from "../chunk-QCGNGEGE.js";
|
|
144
166
|
import {
|
|
145
167
|
useColor
|
|
146
168
|
} from "../chunk-5RUIFDTP.js";
|
|
147
|
-
import
|
|
148
|
-
parseFlags
|
|
149
|
-
} from "../chunk-GMXKITVA.js";
|
|
169
|
+
import "../chunk-GMXKITVA.js";
|
|
150
170
|
import {
|
|
151
171
|
renderCommandHelp
|
|
152
172
|
} from "../chunk-43GMYSS4.js";
|
|
@@ -185,6 +205,7 @@ import {
|
|
|
185
205
|
import "../chunk-2UMNXADU.js";
|
|
186
206
|
import {
|
|
187
207
|
CURSOR_GATE_EVENTS,
|
|
208
|
+
HOOK_LOCATOR_BINARY,
|
|
188
209
|
isValidApiKey
|
|
189
210
|
} from "../chunk-VNMKIJZB.js";
|
|
190
211
|
|
|
@@ -534,153 +555,10 @@ var reportSetupAbortWith = async (deps, reason, exitCode, keyCheck = "unknown")
|
|
|
534
555
|
});
|
|
535
556
|
var reportSetupAbort = (reason, exitCode, keyCheck) => reportSetupAbortWith(defaultDeps, reason, exitCode, keyCheck);
|
|
536
557
|
|
|
537
|
-
// src/setup/
|
|
538
|
-
var
|
|
539
|
-
|
|
540
|
-
|
|
541
|
-
var parseConnectMode = (raw) => {
|
|
542
|
-
const value = raw.trim().toLowerCase();
|
|
543
|
-
if (Object.hasOwn(CONNECT_ALIASES, value)) return CONNECT_ALIASES[value];
|
|
544
|
-
if (CONNECT_MODES.includes(value)) return value;
|
|
545
|
-
throw new UsageError(`--connect must be one of: ${CONNECT_MODES.join(", ")} (got ${raw})`);
|
|
546
|
-
};
|
|
547
|
-
var VERIFY_MODES = ["roundtrip", "push", "none"];
|
|
548
|
-
var parseVerifyMode = (raw) => {
|
|
549
|
-
const value = raw.trim().toLowerCase();
|
|
550
|
-
if (VERIFY_MODES.includes(value)) return value;
|
|
551
|
-
throw new UsageError(`--verify must be one of: ${VERIFY_MODES.join(", ")} (got ${raw})`);
|
|
552
|
-
};
|
|
553
|
-
var CONTROL_MODES = ["auto", "on", "off"];
|
|
554
|
-
var parseControlMode = (raw) => {
|
|
555
|
-
const value = raw.trim().toLowerCase();
|
|
556
|
-
if (CONTROL_MODES.includes(value)) return value;
|
|
557
|
-
throw new UsageError(`--control must be one of: ${CONTROL_MODES.join(", ")} (got ${raw})`);
|
|
558
|
-
};
|
|
559
|
-
var effectiveVerify = (options, context) => {
|
|
560
|
-
if (options.verifyExplicit) return options.verify;
|
|
561
|
-
if (options.verify === "roundtrip") return "roundtrip";
|
|
562
|
-
return context.paired ? "roundtrip" : options.verify;
|
|
563
|
-
};
|
|
564
|
-
var SETUP_FLAGS = {
|
|
565
|
-
bools: ["key-stdin", "skip-phone", "yes", "y", "json", "dry-run", "take-over-hooks", "help", "h"],
|
|
566
|
-
values: ["key", "connect", "agents", "verify", "control", "transcripts"]
|
|
567
|
-
};
|
|
568
|
-
var effectiveControlMode = (options, stored, configPresent) => options.controlExplicit ? options.control : stored ?? (configPresent ? null : options.control);
|
|
569
|
-
var isAgentChoice = (value) => AGENT_CHOICES.includes(value);
|
|
570
|
-
var parseAgentSelection = (raw, yes) => {
|
|
571
|
-
if (raw === void 0) {
|
|
572
|
-
return yes ? { kind: "auto" } : { kind: "ask" };
|
|
573
|
-
}
|
|
574
|
-
const value = raw.trim().toLowerCase();
|
|
575
|
-
if (value === "auto") return { kind: "auto" };
|
|
576
|
-
if (value === "none") return { kind: "none" };
|
|
577
|
-
const parts = value.split(",").map((part) => part.trim()).filter((part) => part !== "");
|
|
578
|
-
if (parts.length === 0) throw new UsageError("--agents needs a value");
|
|
579
|
-
const unknown = parts.filter((part) => !isAgentChoice(part));
|
|
580
|
-
if (unknown.length > 0) {
|
|
581
|
-
throw new UsageError(
|
|
582
|
-
`--agents does not know: ${unknown.join(", ")}. Use auto, none, or any of: ${AGENT_CHOICES.join(", ")}`
|
|
583
|
-
);
|
|
584
|
-
}
|
|
585
|
-
return { kind: "explicit", agents: [...new Set(parts)] };
|
|
586
|
-
};
|
|
587
|
-
var parseSetupOptions = (input2) => {
|
|
588
|
-
const flags = parseFlags(input2.argv, SETUP_FLAGS);
|
|
589
|
-
const stray = [
|
|
590
|
-
...flags.command !== void 0 && flags.command !== "setup" ? [flags.command] : [],
|
|
591
|
-
...flags.rest
|
|
592
|
-
];
|
|
593
|
-
if (stray.length > 0) {
|
|
594
|
-
throw new UsageError(
|
|
595
|
-
`setup takes no positional arguments (got ${stray.join(", ")}). Did you mean --agents ${stray[0]}?`
|
|
596
|
-
);
|
|
597
|
-
}
|
|
598
|
-
const yes = flags.bools.has("yes") || flags.bools.has("y");
|
|
599
|
-
const help = flags.bools.has("help") || flags.bools.has("h");
|
|
600
|
-
const agentsFlag = flags.values.get("agents");
|
|
601
|
-
const agents = parseAgentSelection(agentsFlag, yes);
|
|
602
|
-
const connectRaw = flags.values.get("connect");
|
|
603
|
-
const connectMode = connectRaw === void 0 ? "app" : parseConnectMode(connectRaw);
|
|
604
|
-
const verifyRaw = flags.values.get("verify");
|
|
605
|
-
const controlRaw = flags.values.get("control");
|
|
606
|
-
const transcriptsRaw = flags.values.get("transcripts")?.trim().toLowerCase();
|
|
607
|
-
if (transcriptsRaw !== void 0 && transcriptsRaw !== "on" && transcriptsRaw !== "off") {
|
|
608
|
-
throw new UsageError(`--transcripts must be one of: on, off (got ${transcriptsRaw})`);
|
|
609
|
-
}
|
|
610
|
-
const nonInteractive = yes || agentsFlag !== void 0 || flags.bools.has("json") || !input2.stdinIsTty;
|
|
611
|
-
const verify = verifyRaw !== void 0 ? parseVerifyMode(verifyRaw) : nonInteractive ? "push" : "roundtrip";
|
|
612
|
-
const key = flags.values.get("key")?.trim() || null;
|
|
613
|
-
const keyStdin = flags.bools.has("key-stdin");
|
|
614
|
-
if (key && keyStdin) {
|
|
615
|
-
throw new UsageError("Pass either --key or --key-stdin, not both");
|
|
616
|
-
}
|
|
617
|
-
if (key && !isValidApiKey(key)) {
|
|
618
|
-
throw new UsageError("--key is not a valid API key. Expected the pk_xxx.xxx shape from pushary.com/dashboard/agent/settings");
|
|
619
|
-
}
|
|
620
|
-
return {
|
|
621
|
-
connectMode,
|
|
622
|
-
connectExplicit: connectRaw !== void 0,
|
|
623
|
-
// `--connect none` and `--skip-phone` are the same instruction, so they
|
|
624
|
-
// resolve to the same field rather than being checked separately at the two
|
|
625
|
-
// call sites that would inevitably drift apart.
|
|
626
|
-
skipPhone: flags.bools.has("skip-phone") || connectMode === "none",
|
|
627
|
-
// Anything that means "there is nobody to answer a prompt". A non-TTY stdin
|
|
628
|
-
// is included because that is the case that used to hang: it is better to
|
|
629
|
-
// take the defaults and say so than to wait forever for a keypress.
|
|
630
|
-
//
|
|
631
|
-
// --json counts. Under it stdout carries exactly one object and every human
|
|
632
|
-
// line is redirected to stderr, so a prompt has nowhere to render: the
|
|
633
|
-
// question goes to stderr while the run blocks on a keypress the caller
|
|
634
|
-
// cannot see it is waiting for, and whatever is reading stdout waits forever
|
|
635
|
-
// for an object that never arrives. Asking for machine-readable output is
|
|
636
|
-
// itself a statement that no human is watching.
|
|
637
|
-
nonInteractive,
|
|
638
|
-
json: flags.bools.has("json"),
|
|
639
|
-
dryRun: flags.bools.has("dry-run"),
|
|
640
|
-
help,
|
|
641
|
-
agents,
|
|
642
|
-
key,
|
|
643
|
-
keyStdin,
|
|
644
|
-
verify,
|
|
645
|
-
verifyExplicit: verifyRaw !== void 0,
|
|
646
|
-
control: controlRaw === void 0 ? "auto" : parseControlMode(controlRaw),
|
|
647
|
-
controlExplicit: controlRaw !== void 0,
|
|
648
|
-
transcripts: transcriptsRaw === void 0 ? null : transcriptsRaw === "on",
|
|
649
|
-
takeOverHooks: flags.bools.has("take-over-hooks")
|
|
650
|
-
};
|
|
651
|
-
};
|
|
652
|
-
|
|
653
|
-
// src/setup/hook-ownership.ts
|
|
654
|
-
var commandsIn = (value) => {
|
|
655
|
-
if (Array.isArray(value)) return value.flatMap(commandsIn);
|
|
656
|
-
if (!value || typeof value !== "object") return [];
|
|
657
|
-
return Object.entries(value).flatMap(([key, item]) => key === "command" && typeof item === "string" ? [item] : commandsIn(item));
|
|
658
|
-
};
|
|
659
|
-
var hookOwnerOf = (document) => {
|
|
660
|
-
const hooks = document && typeof document === "object" ? document.hooks : void 0;
|
|
661
|
-
const executables = commandsIn(hooks).map(pusharyHookExecutable).filter((executable) => executable !== null);
|
|
662
|
-
if (executables.some(isBridgeLocator)) return "app";
|
|
663
|
-
if (executables.length > 0) return "cli";
|
|
664
|
-
return "none";
|
|
665
|
-
};
|
|
666
|
-
var planHooks = (context) => {
|
|
667
|
-
if (context.owner !== "app") return "install";
|
|
668
|
-
if (context.takeOverHooks) return "install";
|
|
669
|
-
return context.nonInteractive ? "keep" : "ask";
|
|
670
|
-
};
|
|
671
|
-
var describeAppOwnership = (agentName) => `The Pushary Mac app owns ${agentName}'s hooks.`;
|
|
672
|
-
var takeoverQuestion = (agentName) => `Replace them with the CLI's? The app stops answering for ${agentName} and the notch loses its terminal jump there.`;
|
|
673
|
-
var KEEP_HINT = "Left as they are. Pass --take-over-hooks to have the CLI own them instead.";
|
|
674
|
-
var OWNER_LABELS = {
|
|
675
|
-
app: "the Pushary Mac app",
|
|
676
|
-
cli: "the CLI"
|
|
677
|
-
};
|
|
678
|
-
var describeHookOwnership = (entries, names) => {
|
|
679
|
-
const owned = entries.filter((entry) => entry.owner !== "none");
|
|
680
|
-
if (owned.length === 0) return null;
|
|
681
|
-
const parts = owned.map((entry) => `${names[entry.agent]} by ${OWNER_LABELS[entry.owner]}${entry.kept ? " (kept)" : ""}`);
|
|
682
|
-
return `Hooks: ${parts.join(", ")}.`;
|
|
683
|
-
};
|
|
558
|
+
// src/setup/app-key.ts
|
|
559
|
+
var pickAppKey = (candidates) => candidates.fromAgents.find(
|
|
560
|
+
(candidate) => typeof candidate === "string" && candidate !== candidates.storedKey && candidate !== candidates.envKey && isValidApiKey(candidate)
|
|
561
|
+
) ?? null;
|
|
684
562
|
|
|
685
563
|
// bin/pushary-setup.ts
|
|
686
564
|
var CLAUDE_SETTINGS = claudeSettings();
|
|
@@ -690,6 +568,7 @@ var HERMES_CONFIG_RECEIPT = hermesConfigReceipt();
|
|
|
690
568
|
var CURSOR_PLUGIN_DIR = cursorPluginDir();
|
|
691
569
|
var CURSOR_USER_HOOKS = cursorUserHooks();
|
|
692
570
|
var VSCODE_PLUGIN_DIR = vscodePluginDir();
|
|
571
|
+
var VSCODE_PLUGIN_MCP = vscodePluginMcp();
|
|
693
572
|
var CLAUDE_SKILL_DIR = claudeSkillDir();
|
|
694
573
|
var CODEX_HOME = codexHome();
|
|
695
574
|
var CODEX_SKILL_DIR = codexSkillDir();
|
|
@@ -947,16 +826,16 @@ var setupHermes = async (_apiKey) => {
|
|
|
947
826
|
const python = resolveHermesPython();
|
|
948
827
|
if (!python) {
|
|
949
828
|
console.log(` ${yellow("!")} Could not locate the Python that Hermes runs in. Skipping.`);
|
|
950
|
-
noteManual(
|
|
829
|
+
noteManual(`Install the Hermes plugin by hand: <hermes-python> -m pip install ${HERMES_PIP_PACKAGE}`);
|
|
951
830
|
return "skipped";
|
|
952
831
|
}
|
|
953
832
|
const existingReceipt = readJsonSafe(HERMES_CONFIG_RECEIPT);
|
|
954
833
|
if (existingReceipt.kind !== "missing" && (existingReceipt.kind !== "ok" || !isHermesConfigReceipt(existingReceipt.value))) {
|
|
955
834
|
throw new Error(`Cannot safely configure Hermes: ${HERMES_CONFIG_RECEIPT} is unreadable or invalid.`);
|
|
956
835
|
}
|
|
957
|
-
await spinner(
|
|
836
|
+
await spinner(`Installing ${HERMES_PIP_PACKAGE} into Hermes\u2019 environment`, async () => {
|
|
958
837
|
ensurePip(python);
|
|
959
|
-
execSync2(`"${python}" -m pip install --upgrade
|
|
838
|
+
execSync2(`"${python}" -m pip install --upgrade ${HERMES_PIP_PACKAGE}`, { stdio: "pipe", timeout: 18e4 });
|
|
960
839
|
});
|
|
961
840
|
let pluginEnabled = false;
|
|
962
841
|
await spinner("Enabling plugin + routing questions to push", async () => {
|
|
@@ -1410,7 +1289,7 @@ var setupVsCode = async (apiKey) => {
|
|
|
1410
1289
|
}
|
|
1411
1290
|
});
|
|
1412
1291
|
await spinner("Linking your API key", async () => {
|
|
1413
|
-
const mcpPath =
|
|
1292
|
+
const mcpPath = VSCODE_PLUGIN_MCP;
|
|
1414
1293
|
const mcp = readAgentJson(mcpPath);
|
|
1415
1294
|
const servers = mcp.mcpServers ?? {};
|
|
1416
1295
|
if (servers.pushary) {
|
|
@@ -1585,16 +1464,43 @@ var HOOK_FILES = {
|
|
|
1585
1464
|
cursor: () => CURSOR_USER_HOOKS,
|
|
1586
1465
|
vscode: () => join3(VSCODE_PLUGIN_DIR, "hooks", "hooks.json")
|
|
1587
1466
|
};
|
|
1588
|
-
var hookOwnerFor = (agent) => {
|
|
1467
|
+
var hookOwnerFor = (agent, appAvailable = true) => {
|
|
1589
1468
|
const file = HOOK_FILES[agent]?.();
|
|
1590
1469
|
if (!file) return "none";
|
|
1591
1470
|
const document = readJsonSafe(file);
|
|
1592
|
-
return hookOwnerOf(document.kind === "ok" ? document.value : null);
|
|
1471
|
+
return hookOwnerOf(document.kind === "ok" ? document.value : null, appAvailable);
|
|
1593
1472
|
};
|
|
1594
|
-
var
|
|
1595
|
-
|
|
1596
|
-
|
|
1597
|
-
|
|
1473
|
+
var appMcpKeyFor = (agent) => {
|
|
1474
|
+
if (agent === "codex") {
|
|
1475
|
+
const auth = readCodexMcpAuth(readAgentToml(codexConfigToml()));
|
|
1476
|
+
return auth?.method === "embedded" ? auth.key : null;
|
|
1477
|
+
}
|
|
1478
|
+
const file = agent === "claude_code" ? CLAUDE_JSON : agent === "gemini_cli" ? GEMINI_SETTINGS : agent === "cursor" ? cursorUserMcp() : agent === "vscode" ? VSCODE_PLUGIN_MCP : null;
|
|
1479
|
+
return file ? mcpBearerKey(readAgentJson(file), "mcpServers", "headers") : null;
|
|
1480
|
+
};
|
|
1481
|
+
var appMcpKeyIfReadable = (agent) => {
|
|
1482
|
+
try {
|
|
1483
|
+
return appMcpKeyFor(agent);
|
|
1484
|
+
} catch {
|
|
1485
|
+
return null;
|
|
1486
|
+
}
|
|
1487
|
+
};
|
|
1488
|
+
var captureTakeoverReceipt = (agent) => {
|
|
1489
|
+
const hookFile = HOOK_FILES[agent]?.();
|
|
1490
|
+
if (!hookFile) return;
|
|
1491
|
+
const document = readAgentJson(hookFile);
|
|
1492
|
+
const captured = captureHookTakeover(agent, document);
|
|
1493
|
+
if (!captured) throw new Error(`Cannot safely take over ${AGENT_NAMES[agent]}'s hooks: no Mac app wiring was found.`);
|
|
1494
|
+
const codexConfig = agent === "codex" ? readAgentToml(codexConfigToml()) : null;
|
|
1495
|
+
const mcp = agent === "claude_code" ? [readAgentJson(CLAUDE_JSON), "mcpServers"] : agent === "codex" ? [codexConfig, "mcp_servers"] : agent === "gemini_cli" ? [document, "mcpServers"] : agent === "vscode" ? [readAgentJson(VSCODE_PLUGIN_MCP), "mcpServers"] : null;
|
|
1496
|
+
const receipt = {
|
|
1497
|
+
...captured,
|
|
1498
|
+
...codexConfig ? {
|
|
1499
|
+
codexTrust: captureCodexHookTrust(codexConfig, hookFile, codexHookPositions(document))
|
|
1500
|
+
} : {},
|
|
1501
|
+
...mcp ? { mcpServer: captureMcpServer(mcp[0], mcp[1]) } : {}
|
|
1502
|
+
};
|
|
1503
|
+
writeJsonAtomic(hookTakeoverReceipt(agent), receipt, 384);
|
|
1598
1504
|
};
|
|
1599
1505
|
var agentIsWired = (agent) => {
|
|
1600
1506
|
const readJson2 = (path) => {
|
|
@@ -1629,7 +1535,7 @@ var agentIsWired = (agent) => {
|
|
|
1629
1535
|
case "cursor":
|
|
1630
1536
|
return existsSync(join3(CURSOR_PLUGIN_DIR, "mcp.json"));
|
|
1631
1537
|
case "vscode":
|
|
1632
|
-
return existsSync(
|
|
1538
|
+
return existsSync(VSCODE_PLUGIN_MCP);
|
|
1633
1539
|
case "opencode":
|
|
1634
1540
|
return openCodeWired();
|
|
1635
1541
|
default:
|
|
@@ -1820,7 +1726,7 @@ var AGENT_TARGETS = {
|
|
|
1820
1726
|
gemini_cli: [GEMINI_SETTINGS, GEMINI_MD],
|
|
1821
1727
|
hermes: ["the Hermes virtualenv (pip install pushary-hermes)"],
|
|
1822
1728
|
cursor: [join3(CURSOR_PLUGIN_DIR, "mcp.json"), CURSOR_USER_HOOKS],
|
|
1823
|
-
vscode: [
|
|
1729
|
+
vscode: [VSCODE_PLUGIN_MCP, ...vscodeSettingsTargets(existsSync)],
|
|
1824
1730
|
opencode: [
|
|
1825
1731
|
openCodePluginFile(),
|
|
1826
1732
|
join3(openCodePluginDir(), "package.json"),
|
|
@@ -1914,6 +1820,8 @@ var main = async () => {
|
|
|
1914
1820
|
const envCheck = ambientEligible && envKey && isValidApiKey(envKey) ? await usableStoredKey(envKey) : null;
|
|
1915
1821
|
const storedCheck = ambientEligible && envCheck === null && storedKey !== null && isValidApiKey(storedKey) && // login writes both, so without this the same key is probed twice.
|
|
1916
1822
|
storedKey !== envKey ? await usableStoredKey(storedKey) : null;
|
|
1823
|
+
const appKey = ambientEligible && envCheck === null && storedCheck === null ? pickAppKey({ fromAgents: AGENT_CHOICES.map(appMcpKeyIfReadable), storedKey, envKey }) : null;
|
|
1824
|
+
const appKeyCheck = appKey === null ? null : await usableStoredKey(appKey);
|
|
1917
1825
|
let storedKeyCheck = null;
|
|
1918
1826
|
if (flagKey) {
|
|
1919
1827
|
const masked = `${flagKey.slice(0, 8)}...${flagKey.slice(-4)}`;
|
|
@@ -1939,6 +1847,12 @@ var main = async () => {
|
|
|
1939
1847
|
const apiKey = await input({ message: "API key:" });
|
|
1940
1848
|
trimmedKey = apiKey.trim();
|
|
1941
1849
|
}
|
|
1850
|
+
} else if (appKey !== null && appKeyCheck !== null) {
|
|
1851
|
+
const masked = `${appKey.slice(0, 8)}...${appKey.slice(-4)}`;
|
|
1852
|
+
console.log(` ${check} Using the key the Pushary Mac app is signed in with: ${dim(masked)}`);
|
|
1853
|
+
console.log();
|
|
1854
|
+
trimmedKey = appKey;
|
|
1855
|
+
storedKeyCheck = appKeyCheck;
|
|
1942
1856
|
} else if (options.dryRun) {
|
|
1943
1857
|
console.log(` ${dim("No key on this machine. A real run would connect one first.")}`);
|
|
1944
1858
|
console.log();
|
|
@@ -2044,6 +1958,29 @@ var main = async () => {
|
|
|
2044
1958
|
}
|
|
2045
1959
|
const rc = await saveApiKey(trimmedKey, controlMode, transcriptSync);
|
|
2046
1960
|
const context = { rc };
|
|
1961
|
+
const appBridgeAvailable = resolveBridgeStub(
|
|
1962
|
+
join3(pusharyDir(), "bin", HOOK_LOCATOR_BINARY),
|
|
1963
|
+
liveBridgeProbe()
|
|
1964
|
+
).kind === "bundle";
|
|
1965
|
+
const accountChecks = /* @__PURE__ */ new Map();
|
|
1966
|
+
if (keyCheck) accountChecks.set(trimmedKey, Promise.resolve(keyCheck));
|
|
1967
|
+
const accountCheckFor = (key) => {
|
|
1968
|
+
const existing = accountChecks.get(key);
|
|
1969
|
+
if (existing) return existing;
|
|
1970
|
+
const pending = checkApiKey(key);
|
|
1971
|
+
accountChecks.set(key, pending);
|
|
1972
|
+
return pending;
|
|
1973
|
+
};
|
|
1974
|
+
const appAccountMatches = async (agent) => {
|
|
1975
|
+
const appKey2 = appMcpKeyFor(agent);
|
|
1976
|
+
if (!appKey2) return false;
|
|
1977
|
+
if (appKey2 === trimmedKey) return true;
|
|
1978
|
+
const [cliAccount, appAccount] = await Promise.all([
|
|
1979
|
+
accountCheckFor(trimmedKey),
|
|
1980
|
+
accountCheckFor(appKey2)
|
|
1981
|
+
]);
|
|
1982
|
+
return samePusharyAccount(cliAccount, appAccount);
|
|
1983
|
+
};
|
|
2047
1984
|
if (envKey && envKey !== trimmedKey) {
|
|
2048
1985
|
noteManual(
|
|
2049
1986
|
`This shell still exports the previous key (${keyPrefix(envKey)}), and it wins over the one just saved. Open a new terminal before starting an agent here, or re-export PUSHARY_API_KEY.`
|
|
@@ -2062,22 +1999,32 @@ var main = async () => {
|
|
|
2062
1999
|
for (const agent of agents) {
|
|
2063
2000
|
markStep(`configure:${agent}`);
|
|
2064
2001
|
try {
|
|
2065
|
-
const ownerBefore = hookOwnerFor(agent);
|
|
2002
|
+
const ownerBefore = hookOwnerFor(agent, appBridgeAvailable);
|
|
2066
2003
|
const plan = planHooks({ owner: ownerBefore, takeOverHooks: options.takeOverHooks, nonInteractive: options.nonInteractive });
|
|
2067
|
-
const keepAppWiring = plan === "keep"
|
|
2004
|
+
const keepAppWiring = plan === "keep";
|
|
2068
2005
|
if (keepAppWiring) {
|
|
2006
|
+
if (!await appAccountMatches(agent)) {
|
|
2007
|
+
hookOwners.push({ agent, owner: "app", kept: true });
|
|
2008
|
+
failed.push(agent.replace("_", " "));
|
|
2009
|
+
console.log(`
|
|
2010
|
+
${yellow("!")} ${AGENT_NAMES[agent]}: Mac app hooks kept, but their Pushary account could not be matched to this setup.`);
|
|
2011
|
+
console.log(` ${dim("Sign the Mac app into the same account and repair this agent, then re-run setup.")}`);
|
|
2012
|
+
console.log(` ${dim("Or pass --take-over-hooks if you intentionally want the CLI to own these hooks.")}`);
|
|
2013
|
+
continue;
|
|
2014
|
+
}
|
|
2069
2015
|
console.log(`
|
|
2070
2016
|
${check} ${AGENT_NAMES[agent]}: ${describeAppOwnership(AGENT_NAMES[agent])} ${dim(KEEP_HINT)}`);
|
|
2071
2017
|
hookOwners.push({ agent, owner: "app", kept: true });
|
|
2072
2018
|
completed.push(agent);
|
|
2073
2019
|
continue;
|
|
2074
2020
|
}
|
|
2021
|
+
if (ownerBefore === "app") captureTakeoverReceipt(agent);
|
|
2075
2022
|
const outcome = await AGENT_SETUP[agent](trimmedKey, context);
|
|
2076
2023
|
if (outcome === "skipped") {
|
|
2077
2024
|
skipped.push(agent);
|
|
2078
2025
|
} else if (agentIsWired(agent)) {
|
|
2079
2026
|
completed.push(agent);
|
|
2080
|
-
hookOwners.push({ agent, owner: hookOwnerFor(agent), kept: false });
|
|
2027
|
+
hookOwners.push({ agent, owner: hookOwnerFor(agent, appBridgeAvailable), kept: false });
|
|
2081
2028
|
} else {
|
|
2082
2029
|
failed.push(agent.replace("_", " "));
|
|
2083
2030
|
console.log(` ${yellow("!")} ${agent.replace("_", " ")} reported success but its config is not there.`);
|
|
@@ -2,9 +2,9 @@
|
|
|
2
2
|
import {
|
|
3
3
|
describeLastSeen,
|
|
4
4
|
listMachines
|
|
5
|
-
} from "../chunk-
|
|
6
|
-
import "../chunk-
|
|
7
|
-
import "../chunk-
|
|
5
|
+
} from "../chunk-YTD6PJM7.js";
|
|
6
|
+
import "../chunk-AWHCZOZO.js";
|
|
7
|
+
import "../chunk-BVNYTQ5I.js";
|
|
8
8
|
import {
|
|
9
9
|
describeReach,
|
|
10
10
|
fetchChannels,
|
|
@@ -14,7 +14,7 @@ import "../chunk-3EGEA4KH.js";
|
|
|
14
14
|
import {
|
|
15
15
|
checkApiKey,
|
|
16
16
|
describeKeyCheck
|
|
17
|
-
} from "../chunk-
|
|
17
|
+
} from "../chunk-BXTJVM7O.js";
|
|
18
18
|
import "../chunk-QCGNGEGE.js";
|
|
19
19
|
import {
|
|
20
20
|
createIo
|
|
@@ -6,11 +6,11 @@ import {
|
|
|
6
6
|
handleStop,
|
|
7
7
|
handleSubagentStop,
|
|
8
8
|
isSubagentStop
|
|
9
|
-
} from "../chunk-
|
|
9
|
+
} from "../chunk-TVZQMPB7.js";
|
|
10
10
|
import "../chunk-F7OURW3C.js";
|
|
11
11
|
import "../chunk-L4E2BIJ2.js";
|
|
12
|
-
import "../chunk-
|
|
13
|
-
import "../chunk-
|
|
12
|
+
import "../chunk-AWHCZOZO.js";
|
|
13
|
+
import "../chunk-BVNYTQ5I.js";
|
|
14
14
|
import "../chunk-BSZYIAZL.js";
|
|
15
15
|
import "../chunk-SAF6HGAA.js";
|
|
16
16
|
import "../chunk-7QLSKOSU.js";
|
|
@@ -4,11 +4,11 @@ import {
|
|
|
4
4
|
} from "../chunk-6CUUA7HO.js";
|
|
5
5
|
import {
|
|
6
6
|
handleStopFailure
|
|
7
|
-
} from "../chunk-
|
|
7
|
+
} from "../chunk-TVZQMPB7.js";
|
|
8
8
|
import "../chunk-F7OURW3C.js";
|
|
9
9
|
import "../chunk-L4E2BIJ2.js";
|
|
10
|
-
import "../chunk-
|
|
11
|
-
import "../chunk-
|
|
10
|
+
import "../chunk-AWHCZOZO.js";
|
|
11
|
+
import "../chunk-BVNYTQ5I.js";
|
|
12
12
|
import "../chunk-BSZYIAZL.js";
|
|
13
13
|
import "../chunk-SAF6HGAA.js";
|
|
14
14
|
import "../chunk-7QLSKOSU.js";
|
|
@@ -1,13 +1,13 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
import {
|
|
3
3
|
reapplyAllAgents
|
|
4
|
-
} from "../chunk-
|
|
5
|
-
import "../chunk-
|
|
4
|
+
} from "../chunk-VAMBUKXH.js";
|
|
5
|
+
import "../chunk-YTDH3XCE.js";
|
|
6
6
|
import {
|
|
7
7
|
waitForMachineReadiness
|
|
8
|
-
} from "../chunk-
|
|
9
|
-
import "../chunk-
|
|
10
|
-
import "../chunk-
|
|
8
|
+
} from "../chunk-YTD6PJM7.js";
|
|
9
|
+
import "../chunk-WGKC6PU2.js";
|
|
10
|
+
import "../chunk-ELHCIEMM.js";
|
|
11
11
|
import "../chunk-2LAHXHBR.js";
|
|
12
12
|
import "../chunk-EZIEXHYM.js";
|
|
13
13
|
import {
|
|
@@ -20,7 +20,7 @@ import {
|
|
|
20
20
|
replaceDaemonService,
|
|
21
21
|
stopDaemonService,
|
|
22
22
|
waitForDaemonRemoteProof
|
|
23
|
-
} from "../chunk-
|
|
23
|
+
} from "../chunk-Z4XCN2HH.js";
|
|
24
24
|
import {
|
|
25
25
|
detectProviderLiveCapabilities,
|
|
26
26
|
hasSpawnProvider,
|
|
@@ -34,14 +34,14 @@ import {
|
|
|
34
34
|
npmErrorMessage,
|
|
35
35
|
resolveGlobalBinary
|
|
36
36
|
} from "../chunk-L4ZCFMWW.js";
|
|
37
|
-
import "../chunk-
|
|
37
|
+
import "../chunk-AWHCZOZO.js";
|
|
38
38
|
import {
|
|
39
39
|
claudeJson,
|
|
40
40
|
codexConfigToml,
|
|
41
41
|
cursorPluginDir,
|
|
42
42
|
geminiSettings,
|
|
43
43
|
vscodePluginDir
|
|
44
|
-
} from "../chunk-
|
|
44
|
+
} from "../chunk-BVNYTQ5I.js";
|
|
45
45
|
import {
|
|
46
46
|
exitOnHelpFlag
|
|
47
47
|
} from "../chunk-BVBEURWJ.js";
|
package/dist/bin/pushary-wait.js
CHANGED
|
@@ -4,8 +4,8 @@ import {
|
|
|
4
4
|
} from "../chunk-IIENZE2J.js";
|
|
5
5
|
import {
|
|
6
6
|
exitOnFailedResponse
|
|
7
|
-
} from "../chunk-
|
|
8
|
-
import "../chunk-
|
|
7
|
+
} from "../chunk-Z6RFZKY4.js";
|
|
8
|
+
import "../chunk-BXTJVM7O.js";
|
|
9
9
|
import {
|
|
10
10
|
createIo
|
|
11
11
|
} from "../chunk-5RUIFDTP.js";
|
|
@@ -21,7 +21,7 @@ import {
|
|
|
21
21
|
repoKeyFor,
|
|
22
22
|
settleQuestionsForToolUse,
|
|
23
23
|
throttlePass
|
|
24
|
-
} from "./chunk-
|
|
24
|
+
} from "./chunk-TVZQMPB7.js";
|
|
25
25
|
import {
|
|
26
26
|
DEFAULT_SESSION,
|
|
27
27
|
askUser,
|
|
@@ -41,7 +41,7 @@ import {
|
|
|
41
41
|
} from "./chunk-L4E2BIJ2.js";
|
|
42
42
|
import {
|
|
43
43
|
getMachineId
|
|
44
|
-
} from "./chunk-
|
|
44
|
+
} from "./chunk-AWHCZOZO.js";
|
|
45
45
|
import {
|
|
46
46
|
getApiKey,
|
|
47
47
|
getBaseUrl
|