@pushary/agent-hooks 1.7.0 → 1.7.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +28 -0
- package/dist/bin/pushary-bell-hook.js +23 -23
- package/dist/bin/pushary-bell.js +10 -10
- package/dist/bin/pushary-claude.js +46 -35
- package/dist/bin/pushary-clean.js +194 -102
- package/dist/bin/pushary-codex-bridge.js +18 -17
- package/dist/bin/pushary-codex-hook.js +53 -39
- package/dist/bin/pushary-codex.js +14 -12
- package/dist/bin/pushary-connect.js +16 -16
- package/dist/bin/pushary-cowork.js +5 -5
- package/dist/bin/pushary-daemon.js +27 -27
- package/dist/bin/pushary-disconnect.js +19 -17
- package/dist/bin/pushary-doctor.js +99 -43
- package/dist/bin/pushary-elicitation-hook.js +35 -26
- package/dist/bin/pushary-gemini-bridge.js +12 -12
- package/dist/bin/pushary-gemini-hook.js +47 -32
- package/dist/bin/pushary-hook.js +34 -32
- package/dist/bin/pushary-login.js +16 -16
- package/dist/bin/pushary-logout.js +8 -8
- package/dist/bin/pushary-mcp.js +9 -8
- package/dist/bin/pushary-mode.js +10 -10
- package/dist/bin/pushary-notification-hook.js +29 -27
- package/dist/bin/pushary-opencode-hook.js +46 -32
- package/dist/bin/pushary-permission-denied-hook.js +34 -32
- package/dist/bin/pushary-permission-hook.js +33 -31
- package/dist/bin/pushary-post-hook.js +29 -27
- package/dist/bin/pushary-prompt-hook.js +29 -27
- package/dist/bin/pushary-session-end-hook.js +29 -27
- package/dist/bin/pushary-session-start-hook.js +33 -31
- package/dist/bin/pushary-setup.js +143 -105
- package/dist/bin/pushary-stats.js +5 -5
- package/dist/bin/pushary-status.js +19 -19
- package/dist/bin/pushary-stop-hook.js +29 -27
- package/dist/bin/pushary-stopfailure-hook.js +29 -27
- package/dist/bin/pushary-suggestions.js +5 -5
- package/dist/bin/pushary-transcript-register.js +19 -19
- package/dist/bin/pushary-transcripts.js +7 -7
- package/dist/bin/pushary-upgrade.js +20 -20
- package/dist/bin/pushary-wait.js +10 -10
- package/dist/bin/pushary.js +6 -6
- package/dist/{chunk-IJ6ECPA6.js → chunk-2B4XCMH6.js} +75 -232
- package/dist/{chunk-EGKXSQCY.js → chunk-2XOHXZRC.js} +12 -4
- package/dist/{chunk-D6BULEJW.js → chunk-3NSRL5E7.js} +2 -2
- package/dist/{chunk-UC65FJJT.js → chunk-3RO2UWJQ.js} +2 -2
- package/dist/{chunk-73T6MSU5.js → chunk-4S7CCOXB.js} +5 -5
- package/dist/{chunk-7OS4IHGI.js → chunk-5GIBNUBD.js} +2 -2
- package/dist/chunk-5OP5MQI7.js +45 -0
- package/dist/{chunk-B3UXMSMW.js → chunk-65RN6ZCO.js} +1 -1
- package/dist/{chunk-2PS6QWDW.js → chunk-6NHXKTQU.js} +2 -2
- package/dist/{chunk-V6QRSU2G.js → chunk-6QZK4O36.js} +4 -4
- package/dist/{chunk-ZQ7IDOKY.js → chunk-A6WQF7FQ.js} +3 -3
- package/dist/{chunk-QXAK5RFU.js → chunk-AWZNDM3B.js} +1 -1
- package/dist/{chunk-JNXVOU6Y.js → chunk-D4OGEWLH.js} +19 -2
- package/dist/{chunk-R2XCLT6I.js → chunk-E3PLF7YB.js} +4 -4
- package/dist/{chunk-2C7CCWVX.js → chunk-F6BMJOSW.js} +1 -1
- package/dist/{chunk-XNCMT7YY.js → chunk-HOIGXMI7.js} +1 -1
- package/dist/{chunk-CVALVGA7.js → chunk-I7B2DNVU.js} +1 -1
- package/dist/{chunk-S3UD4V6W.js → chunk-INR3RVQ3.js} +13 -3
- package/dist/{chunk-52NVBNJT.js → chunk-IZVAVXHQ.js} +6 -4
- package/dist/{chunk-5HLTWFJ6.js → chunk-JMSB6CJT.js} +1 -1
- package/dist/{chunk-KYQXUGH7.js → chunk-KAJT6HPI.js} +3 -3
- package/dist/{chunk-VKVIAZQO.js → chunk-KLXYMPTM.js} +1 -1
- package/dist/{chunk-PQ4F64M2.js → chunk-L6IF4JOF.js} +3 -3
- package/dist/{chunk-ROQK7IN3.js → chunk-LI3C2IQY.js} +2 -2
- package/dist/{chunk-B234346F.js → chunk-M2JGLFFS.js} +1 -1
- package/dist/chunk-MY3UZO5U.js +99 -0
- package/dist/chunk-N6IOSZOE.js +185 -0
- package/dist/{chunk-DNJUSFBL.js → chunk-NYBZJ44G.js} +40 -5
- package/dist/{chunk-BBKNJJVX.js → chunk-OJRB5QKN.js} +6 -6
- package/dist/{chunk-PUDBG3GM.js → chunk-OXEF6JHD.js} +4 -4
- package/dist/{chunk-LEZFOTMI.js → chunk-PWNQGITG.js} +1 -1
- package/dist/{chunk-B76WVEDX.js → chunk-Q7CDBJXU.js} +1 -1
- package/dist/{chunk-KXMZMZD3.js → chunk-QSZ37ROP.js} +1 -1
- package/dist/{chunk-BH2SKSSK.js → chunk-R7ZETVNR.js} +1 -1
- package/dist/{chunk-DZURML2D.js → chunk-RLRDPZG4.js} +1 -1
- package/dist/{chunk-J2355HR7.js → chunk-SEIZQZEE.js} +1 -1
- package/dist/{chunk-V4AQBAVG.js → chunk-SJN64NJX.js} +1 -1
- package/dist/{chunk-B3YQANFN.js → chunk-SKEW3TQX.js} +1 -1
- package/dist/{chunk-L4H2Q2S4.js → chunk-SKMWPXGV.js} +500 -46
- package/dist/{chunk-WUNZAE7I.js → chunk-T3PRPFDY.js} +5 -5
- package/dist/{chunk-YYINL576.js → chunk-TVJYGZXB.js} +2 -2
- package/dist/{chunk-O2LEPIU6.js → chunk-U3MS6D5X.js} +1 -1
- package/dist/{chunk-5RUIFDTP.js → chunk-U4TMAANR.js} +33 -2
- package/dist/{chunk-KW2RRR7D.js → chunk-UFNBKYWT.js} +3 -3
- package/dist/{chunk-DVQDPI3T.js → chunk-UUTWHVSV.js} +35 -35
- package/dist/{chunk-X6KDKOV5.js → chunk-VQDJ6KB3.js} +3 -3
- package/dist/{chunk-UOAQ6QMP.js → chunk-VSGKQ3HI.js} +2 -2
- package/dist/{chunk-YROGUPOZ.js → chunk-WWTLAZQA.js} +25 -8
- package/dist/{chunk-SQRWHALT.js → chunk-WXIVUIXA.js} +2 -2
- package/dist/{chunk-HDRNWNVP.js → chunk-YLCSKVQQ.js} +9 -28
- package/dist/{chunk-JXUAXO74.js → chunk-YNJ2H2FD.js} +2 -2
- package/dist/{chunk-BWYJ6AAF.js → chunk-YU4222G2.js} +2 -2
- package/dist/{chunk-4F46VIEE.js → chunk-YU54LNC6.js} +6 -6
- package/dist/{chunk-EAQMWJPG.js → chunk-ZMWX5SDA.js} +8 -8
- package/dist/{chunk-6ADZQFVW.js → chunk-ZUKZJQGR.js} +1 -1
- package/dist/{reapply-6PH3FMPX.js → reapply-D6RSDYCK.js} +9 -9
- package/dist/src/index.d.ts +1 -0
- package/dist/src/index.js +22 -20
- package/package.json +2 -1
- package/dist/chunk-DANOZVZK.js +0 -307
- package/dist/chunk-P32LPT2L.js +0 -6
- package/dist/chunk-YHG74UFF.js +0 -12
|
@@ -4,18 +4,18 @@ import {
|
|
|
4
4
|
} from "./chunk-POFBE6ZY.js";
|
|
5
5
|
import {
|
|
6
6
|
isNetworkFailure
|
|
7
|
-
} from "./chunk-
|
|
7
|
+
} from "./chunk-UFNBKYWT.js";
|
|
8
8
|
import {
|
|
9
9
|
clientReportClaims
|
|
10
|
-
} from "./chunk-
|
|
10
|
+
} from "./chunk-NYBZJ44G.js";
|
|
11
11
|
import {
|
|
12
12
|
getApiKey,
|
|
13
13
|
getBaseUrl
|
|
14
|
-
} from "./chunk-
|
|
14
|
+
} from "./chunk-SJN64NJX.js";
|
|
15
15
|
import {
|
|
16
16
|
CLIENT_REPORT_PATH,
|
|
17
17
|
degradedLine
|
|
18
|
-
} from "./chunk-
|
|
18
|
+
} from "./chunk-WWTLAZQA.js";
|
|
19
19
|
|
|
20
20
|
// src/client-report-claim.ts
|
|
21
21
|
import { createHash } from "crypto";
|
|
@@ -1,16 +1,16 @@
|
|
|
1
1
|
import {
|
|
2
2
|
NOTIFICATION_MATCHED_TYPES,
|
|
3
3
|
POSTTOOLUSE_MIRRORED_TOOLS
|
|
4
|
-
} from "./chunk-
|
|
4
|
+
} from "./chunk-RLRDPZG4.js";
|
|
5
5
|
import {
|
|
6
6
|
isProtectedByScope,
|
|
7
7
|
registerHookEntry
|
|
8
|
-
} from "./chunk-
|
|
8
|
+
} from "./chunk-NYBZJ44G.js";
|
|
9
9
|
import {
|
|
10
10
|
CLAUDE_PRETOOLUSE_MATCHER,
|
|
11
11
|
HOOK_BUDGETS,
|
|
12
12
|
HOOK_LOCATOR_BINARY
|
|
13
|
-
} from "./chunk-
|
|
13
|
+
} from "./chunk-WWTLAZQA.js";
|
|
14
14
|
|
|
15
15
|
// src/gemini-config.ts
|
|
16
16
|
var GEMINI_HOOK_BINARY = "pushary-gemini-hook";
|
|
@@ -1,9 +1,12 @@
|
|
|
1
|
+
import {
|
|
2
|
+
keyCheckFromResponse
|
|
3
|
+
} from "./chunk-VQDJ6KB3.js";
|
|
1
4
|
import {
|
|
2
5
|
installNetworkDefaults
|
|
3
|
-
} from "./chunk-
|
|
6
|
+
} from "./chunk-UFNBKYWT.js";
|
|
4
7
|
import {
|
|
5
8
|
getBaseUrl
|
|
6
|
-
} from "./chunk-
|
|
9
|
+
} from "./chunk-SJN64NJX.js";
|
|
7
10
|
|
|
8
11
|
// src/retry.ts
|
|
9
12
|
var isRetryable = (err) => {
|
|
@@ -35,6 +38,17 @@ var withRetry = async (fn, options = {}) => {
|
|
|
35
38
|
|
|
36
39
|
// src/mcp-http.ts
|
|
37
40
|
installNetworkDefaults();
|
|
41
|
+
var SUBSCRIPTION_REQUIRED_MESSAGE = "Pushary MCP error: 403 Subscription required";
|
|
42
|
+
var SubscriptionRequiredError = class extends Error {
|
|
43
|
+
plan;
|
|
44
|
+
upgradeUrl;
|
|
45
|
+
constructor(plan, upgradeUrl) {
|
|
46
|
+
super(SUBSCRIPTION_REQUIRED_MESSAGE);
|
|
47
|
+
this.name = "SubscriptionRequiredError";
|
|
48
|
+
this.plan = plan;
|
|
49
|
+
this.upgradeUrl = upgradeUrl;
|
|
50
|
+
}
|
|
51
|
+
};
|
|
38
52
|
var parseSseMessages = (body) => {
|
|
39
53
|
const messages = [];
|
|
40
54
|
for (const event of body.split(/\r?\n\r?\n/)) {
|
|
@@ -77,6 +91,8 @@ var sendMcpRequest = async (apiKey, message, options = {}) => {
|
|
|
77
91
|
body: JSON.stringify(message),
|
|
78
92
|
signal: options.timeoutMs ? AbortSignal.any([AbortSignal.timeout(options.timeoutMs), ...options.signal ? [options.signal] : []]) : options.signal
|
|
79
93
|
});
|
|
94
|
+
const lock = response.ok ? null : await keyCheckFromResponse(response, baseUrl);
|
|
95
|
+
if (lock?.kind === "locked") throw new SubscriptionRequiredError(lock.plan, lock.upgradeUrl);
|
|
80
96
|
const body = await response.text();
|
|
81
97
|
const contentType = response.headers.get("content-type");
|
|
82
98
|
let data = null;
|
|
@@ -115,6 +131,7 @@ var callMcpTool = async (apiKey, toolName, params, options = {}) => {
|
|
|
115
131
|
|
|
116
132
|
export {
|
|
117
133
|
withRetry,
|
|
134
|
+
SubscriptionRequiredError,
|
|
118
135
|
parseSseMessages,
|
|
119
136
|
sendMcpRequest,
|
|
120
137
|
callMcpTool
|
|
@@ -1,15 +1,15 @@
|
|
|
1
1
|
import {
|
|
2
2
|
AGENT_CHOICES
|
|
3
|
-
} from "./chunk-
|
|
3
|
+
} from "./chunk-I7B2DNVU.js";
|
|
4
4
|
import {
|
|
5
5
|
isBridgeLocator
|
|
6
|
-
} from "./chunk-
|
|
6
|
+
} from "./chunk-JMSB6CJT.js";
|
|
7
7
|
import {
|
|
8
8
|
pusharyHookExecutable
|
|
9
|
-
} from "./chunk-
|
|
9
|
+
} from "./chunk-L6IF4JOF.js";
|
|
10
10
|
import {
|
|
11
11
|
BELL_HOOK_BINARY
|
|
12
|
-
} from "./chunk-
|
|
12
|
+
} from "./chunk-KLXYMPTM.js";
|
|
13
13
|
|
|
14
14
|
// src/setup/hook-ownership.ts
|
|
15
15
|
var commandsIn = (value) => {
|
|
@@ -1,6 +1,9 @@
|
|
|
1
|
+
import {
|
|
2
|
+
NpmMissingError
|
|
3
|
+
} from "./chunk-NYBZJ44G.js";
|
|
1
4
|
import {
|
|
2
5
|
NPX_LATEST_COMMAND
|
|
3
|
-
} from "./chunk-
|
|
6
|
+
} from "./chunk-65RN6ZCO.js";
|
|
4
7
|
|
|
5
8
|
// src/setup/agent-failure.ts
|
|
6
9
|
var AgentConfigError = class extends Error {
|
|
@@ -21,14 +24,19 @@ var AGENT_FAILURE_DETAILS = {
|
|
|
21
24
|
var describedAgentFailure = (agent, kind) => ({
|
|
22
25
|
agent,
|
|
23
26
|
kind,
|
|
24
|
-
detail: AGENT_FAILURE_DETAILS[kind]
|
|
27
|
+
detail: AGENT_FAILURE_DETAILS[kind],
|
|
28
|
+
remedy: "retry-agent"
|
|
25
29
|
});
|
|
26
30
|
var agentFailureFromError = (agent, error, describeError) => ({
|
|
27
31
|
agent,
|
|
28
32
|
kind: error instanceof AgentConfigError ? error.kind : "installer-error",
|
|
29
|
-
detail: describeError(error)
|
|
33
|
+
detail: describeError(error),
|
|
34
|
+
remedy: error instanceof NpmMissingError ? "install-node" : "retry-agent"
|
|
30
35
|
});
|
|
31
36
|
var retryAgentCommand = (agent) => `${NPX_LATEST_COMMAND} setup --agents ${agent}`;
|
|
37
|
+
var REMAINING_AGENTS_CONTINUE = "Other agents will continue. Re-run setup to retry.";
|
|
38
|
+
var afterAgentFailureNote = (agentsStillToSetUp) => agentsStillToSetUp > 0 ? REMAINING_AGENTS_CONTINUE : null;
|
|
39
|
+
var failedAgentsContext = (configuredAgentNames) => configuredAgentNames.length > 0 ? `(configured: ${configuredAgentNames.join(", ")})` : null;
|
|
32
40
|
var agentFailureWire = (failures) => failures.map(({ agent, kind }) => ({ agent, kind }));
|
|
33
41
|
|
|
34
42
|
// src/diagnostics/service-runtime.ts
|
|
@@ -75,6 +83,8 @@ export {
|
|
|
75
83
|
describedAgentFailure,
|
|
76
84
|
agentFailureFromError,
|
|
77
85
|
retryAgentCommand,
|
|
86
|
+
afterAgentFailureNote,
|
|
87
|
+
failedAgentsContext,
|
|
78
88
|
agentFailureWire,
|
|
79
89
|
readServiceExecPath,
|
|
80
90
|
versionManagerOf,
|
|
@@ -1,16 +1,18 @@
|
|
|
1
1
|
import {
|
|
2
2
|
AUTO_DECISION_WINDOW_MS,
|
|
3
|
-
DEFAULT_SESSION,
|
|
4
3
|
canonicalGateInputs,
|
|
5
4
|
claimThrottle,
|
|
6
5
|
deriveToolTarget,
|
|
7
6
|
permissionDeniedAction,
|
|
8
7
|
releaseThrottle,
|
|
9
8
|
reportEvent
|
|
10
|
-
} from "./chunk-
|
|
9
|
+
} from "./chunk-2B4XCMH6.js";
|
|
10
|
+
import {
|
|
11
|
+
DEFAULT_SESSION
|
|
12
|
+
} from "./chunk-N6IOSZOE.js";
|
|
11
13
|
import {
|
|
12
14
|
canonicalJson
|
|
13
|
-
} from "./chunk-
|
|
15
|
+
} from "./chunk-NYBZJ44G.js";
|
|
14
16
|
import {
|
|
15
17
|
writeFileAtomic
|
|
16
18
|
} from "./chunk-T7E75EKA.js";
|
|
@@ -20,7 +22,7 @@ import {
|
|
|
20
22
|
machineDecisionFor,
|
|
21
23
|
shouldDeferToNativeMode,
|
|
22
24
|
wireVerdictFor
|
|
23
|
-
} from "./chunk-
|
|
25
|
+
} from "./chunk-WWTLAZQA.js";
|
|
24
26
|
|
|
25
27
|
// src/machine-decision-audit.ts
|
|
26
28
|
import { basename } from "path";
|
|
@@ -1,17 +1,17 @@
|
|
|
1
1
|
import {
|
|
2
2
|
CLAUDE_HOOK_EVENTS,
|
|
3
3
|
supportedClaudeEvents
|
|
4
|
-
} from "./chunk-
|
|
4
|
+
} from "./chunk-A6WQF7FQ.js";
|
|
5
5
|
import {
|
|
6
6
|
guardBinary,
|
|
7
7
|
holdBudgetOf,
|
|
8
8
|
isProtectedByScope,
|
|
9
9
|
registerHookEntry
|
|
10
|
-
} from "./chunk-
|
|
10
|
+
} from "./chunk-NYBZJ44G.js";
|
|
11
11
|
import {
|
|
12
12
|
HOOK_LOCATOR_BINARY,
|
|
13
13
|
withHookHoldBudget
|
|
14
|
-
} from "./chunk-
|
|
14
|
+
} from "./chunk-WWTLAZQA.js";
|
|
15
15
|
|
|
16
16
|
// src/claude-config.ts
|
|
17
17
|
import { join } from "path";
|
|
@@ -2,17 +2,17 @@ import {
|
|
|
2
2
|
CLAUDE_HOOK_EVENTS,
|
|
3
3
|
GEMINI_HOOK_EVENTS,
|
|
4
4
|
hasGeminiHooks
|
|
5
|
-
} from "./chunk-
|
|
5
|
+
} from "./chunk-A6WQF7FQ.js";
|
|
6
6
|
import {
|
|
7
7
|
CODEX_HOOK_EVENTS,
|
|
8
8
|
hasCodexHooks,
|
|
9
9
|
holdBudgetOf
|
|
10
|
-
} from "./chunk-
|
|
10
|
+
} from "./chunk-NYBZJ44G.js";
|
|
11
11
|
import {
|
|
12
12
|
CURSOR_GATE_EVENTS,
|
|
13
13
|
HOOK_LOCATOR_BINARY,
|
|
14
14
|
hookCommandHoldBudget
|
|
15
|
-
} from "./chunk-
|
|
15
|
+
} from "./chunk-WWTLAZQA.js";
|
|
16
16
|
|
|
17
17
|
// src/diagnostics/wiring.ts
|
|
18
18
|
var record = (value) => value && typeof value === "object" && !Array.isArray(value) ? value : null;
|
|
@@ -0,0 +1,99 @@
|
|
|
1
|
+
import {
|
|
2
|
+
pusharyHookExecutable
|
|
3
|
+
} from "./chunk-L6IF4JOF.js";
|
|
4
|
+
import {
|
|
5
|
+
isProtectedByScope,
|
|
6
|
+
registerHookEntry
|
|
7
|
+
} from "./chunk-NYBZJ44G.js";
|
|
8
|
+
|
|
9
|
+
// src/skills-cli.ts
|
|
10
|
+
import { execSync } from "child_process";
|
|
11
|
+
var PUSHARY_SKILL_SOURCE = "Pushary/pushary-skill";
|
|
12
|
+
var PUSHARY_SKILL_NAME = "pushary";
|
|
13
|
+
var installSkillViaSkillsCli = (agent) => {
|
|
14
|
+
try {
|
|
15
|
+
execSync(`npx -y skills@latest add ${PUSHARY_SKILL_SOURCE}@${PUSHARY_SKILL_NAME} -y -g --agent ${agent}`, {
|
|
16
|
+
stdio: "pipe",
|
|
17
|
+
timeout: 9e4
|
|
18
|
+
});
|
|
19
|
+
return true;
|
|
20
|
+
} catch {
|
|
21
|
+
return false;
|
|
22
|
+
}
|
|
23
|
+
};
|
|
24
|
+
var installAgentSkill = async (request, effects) => {
|
|
25
|
+
if (request.skillsCliInUse) {
|
|
26
|
+
const startedAt = effects.now();
|
|
27
|
+
if (effects.runSkillsCli(request.agent)) {
|
|
28
|
+
const modifiedAt = effects.skillModifiedAt(request.agentSkillDir);
|
|
29
|
+
if (modifiedAt !== null && modifiedAt >= startedAt) return "skills-cli";
|
|
30
|
+
}
|
|
31
|
+
}
|
|
32
|
+
await effects.writePackagedSkill(request.agentSkillDir);
|
|
33
|
+
return "packaged-copy";
|
|
34
|
+
};
|
|
35
|
+
|
|
36
|
+
// src/cursor-config.ts
|
|
37
|
+
var hookCommandOf = (entry) => {
|
|
38
|
+
const command = entry && typeof entry === "object" && !Array.isArray(entry) ? entry.command : void 0;
|
|
39
|
+
return typeof command === "string" ? command : "";
|
|
40
|
+
};
|
|
41
|
+
var isPusharyCursorEntry = (entry) => pusharyHookExecutable(hookCommandOf(entry)) !== null;
|
|
42
|
+
var registerCursorGate = (existing, entry) => registerHookEntry(existing, isPusharyCursorEntry, entry);
|
|
43
|
+
var withoutPusharyCursorHooks = (hooks, scope) => {
|
|
44
|
+
let removed = 0;
|
|
45
|
+
const kept = {};
|
|
46
|
+
for (const [event, entries] of Object.entries(hooks)) {
|
|
47
|
+
if (!Array.isArray(entries)) {
|
|
48
|
+
kept[event] = entries;
|
|
49
|
+
continue;
|
|
50
|
+
}
|
|
51
|
+
const others = entries.filter((entry) => !isPusharyCursorEntry(entry) || isProtectedByScope(hookCommandOf(entry), scope));
|
|
52
|
+
removed += entries.length - others.length;
|
|
53
|
+
if (others.length > 0 || entries.length === 0) kept[event] = others;
|
|
54
|
+
}
|
|
55
|
+
return { hooks: kept, removed };
|
|
56
|
+
};
|
|
57
|
+
|
|
58
|
+
// src/cli/dry-run.ts
|
|
59
|
+
import { execFileSync } from "child_process";
|
|
60
|
+
import { rmSync, writeFileSync } from "fs";
|
|
61
|
+
var createGuards = (isDryRun, note) => ({
|
|
62
|
+
write: (path, contents) => {
|
|
63
|
+
if (isDryRun()) return note("rewrite", path);
|
|
64
|
+
writeFileSync(path, contents, "utf-8");
|
|
65
|
+
},
|
|
66
|
+
remove: (path, options = {}) => {
|
|
67
|
+
if (isDryRun()) return note("remove ", path);
|
|
68
|
+
rmSync(path, { recursive: true, force: options.force ?? false });
|
|
69
|
+
},
|
|
70
|
+
execFile: (file, args, options, describe) => {
|
|
71
|
+
if (isDryRun()) return note("run ", describe);
|
|
72
|
+
execFileSync(file, args, options);
|
|
73
|
+
}
|
|
74
|
+
});
|
|
75
|
+
var describeService = (effects) => {
|
|
76
|
+
if (effects.controlMode === "off") return "skip the phone-start background service (--control off)";
|
|
77
|
+
const where = effects.serviceDefinitionPath ?? "the phone-start service definition";
|
|
78
|
+
const condition = effects.controlMode === "on" ? "" : ", when a supported agent and a service manager are present";
|
|
79
|
+
return `write ${where} and register it with the OS${condition}`;
|
|
80
|
+
};
|
|
81
|
+
var describeSetupSideEffects = (effects) => [
|
|
82
|
+
`run npm install -g @pushary/agent-hooks@${effects.version} (the hooks run from the global copy; up to two minutes)`,
|
|
83
|
+
`write ${effects.configFile} (the API key, mode 600)`,
|
|
84
|
+
effects.rcPath ? `edit ${effects.rcPath} (export PUSHARY_API_KEY)` : "print the export line for your shell, since no rc file was found",
|
|
85
|
+
describeService(effects),
|
|
86
|
+
"ask Add Pushary instructions to this project's CLAUDE.md/AGENTS.md? (default no)",
|
|
87
|
+
"ask Alias claude to pushary claude? (default no)"
|
|
88
|
+
];
|
|
89
|
+
|
|
90
|
+
export {
|
|
91
|
+
PUSHARY_SKILL_SOURCE,
|
|
92
|
+
PUSHARY_SKILL_NAME,
|
|
93
|
+
installSkillViaSkillsCli,
|
|
94
|
+
installAgentSkill,
|
|
95
|
+
registerCursorGate,
|
|
96
|
+
withoutPusharyCursorHooks,
|
|
97
|
+
createGuards,
|
|
98
|
+
describeSetupSideEffects
|
|
99
|
+
};
|
|
@@ -0,0 +1,185 @@
|
|
|
1
|
+
// src/pending.ts
|
|
2
|
+
import { join } from "path";
|
|
3
|
+
import { homedir, tmpdir } from "os";
|
|
4
|
+
import { createHash } from "crypto";
|
|
5
|
+
import { existsSync, mkdirSync, writeFileSync, readFileSync, readdirSync, renameSync, unlinkSync, rmSync, statSync } from "fs";
|
|
6
|
+
var PENDING_DIR = join(tmpdir(), "pushary-pending");
|
|
7
|
+
var commandRoot = () => process.env.PUSHARY_COMMAND_DIR?.trim() || join(homedir(), ".pushary", "run", "commands");
|
|
8
|
+
var DEFAULT_SESSION = "_no_session";
|
|
9
|
+
var GRACE_MS = 10 * 60 * 1e3;
|
|
10
|
+
var sanitize = (sessionId) => sessionId.replace(/[^A-Za-z0-9_-]/g, "_").slice(0, 128) || DEFAULT_SESSION;
|
|
11
|
+
var dirFor = (sessionId) => join(PENDING_DIR, sanitize(sessionId));
|
|
12
|
+
var commandDirFor = (sessionId, namespace = "") => join(
|
|
13
|
+
commandRoot(),
|
|
14
|
+
createHash("sha256").update(namespace).digest("hex").slice(0, 16),
|
|
15
|
+
sanitize(sessionId)
|
|
16
|
+
);
|
|
17
|
+
var legacyCommandFile = (sessionId, namespace = "") => join(commandDirFor(sessionId, namespace), "command.json");
|
|
18
|
+
var commandFile = (sessionId, id, namespace = "") => join(commandDirFor(sessionId, namespace), `${createHash("sha256").update(id).digest("hex")}.json`);
|
|
19
|
+
var readCommandFile = (file) => {
|
|
20
|
+
try {
|
|
21
|
+
const value = JSON.parse(readFileSync(file, "utf-8"));
|
|
22
|
+
if (typeof value.id !== "string" || typeof value.text !== "string" || typeof value.expiresAtMs !== "number") return null;
|
|
23
|
+
if (value.expiresAtMs <= Date.now()) {
|
|
24
|
+
unlinkSync(file);
|
|
25
|
+
return null;
|
|
26
|
+
}
|
|
27
|
+
return {
|
|
28
|
+
...value,
|
|
29
|
+
delivered: value.delivered === true,
|
|
30
|
+
...value.failed === true ? { failed: true } : {}
|
|
31
|
+
};
|
|
32
|
+
} catch {
|
|
33
|
+
return null;
|
|
34
|
+
}
|
|
35
|
+
};
|
|
36
|
+
var readPendingCommandById = (sessionId, id, namespace = "") => {
|
|
37
|
+
const current = readCommandFile(commandFile(sessionId, id, namespace));
|
|
38
|
+
if (current?.id === id) return current;
|
|
39
|
+
const legacy = readCommandFile(legacyCommandFile(sessionId, namespace));
|
|
40
|
+
return legacy?.id === id ? legacy : null;
|
|
41
|
+
};
|
|
42
|
+
var pruneExpiredCommands = (dir) => {
|
|
43
|
+
let files;
|
|
44
|
+
try {
|
|
45
|
+
files = readdirSync(dir).filter((file) => file.endsWith(".json"));
|
|
46
|
+
} catch {
|
|
47
|
+
return [];
|
|
48
|
+
}
|
|
49
|
+
return files.flatMap((file) => {
|
|
50
|
+
const command = readCommandFile(join(dir, file));
|
|
51
|
+
return command ? [command] : [];
|
|
52
|
+
});
|
|
53
|
+
};
|
|
54
|
+
var pruneExpiredCommandStore = () => {
|
|
55
|
+
let namespaces;
|
|
56
|
+
try {
|
|
57
|
+
namespaces = readdirSync(commandRoot(), { withFileTypes: true });
|
|
58
|
+
} catch {
|
|
59
|
+
return;
|
|
60
|
+
}
|
|
61
|
+
for (const namespace of namespaces.filter((entry) => entry.isDirectory())) {
|
|
62
|
+
const namespaceDir = join(commandRoot(), namespace.name);
|
|
63
|
+
let sessions;
|
|
64
|
+
try {
|
|
65
|
+
sessions = readdirSync(namespaceDir, { withFileTypes: true });
|
|
66
|
+
} catch {
|
|
67
|
+
continue;
|
|
68
|
+
}
|
|
69
|
+
for (const session of sessions.filter((entry) => entry.isDirectory())) {
|
|
70
|
+
pruneExpiredCommands(join(namespaceDir, session.name));
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
};
|
|
74
|
+
var readPendingCommand = (sessionId, namespace = "") => {
|
|
75
|
+
const commands = pruneExpiredCommands(commandDirFor(sessionId, namespace));
|
|
76
|
+
return commands.find((command) => !command.delivered && !command.failed) ?? commands[0] ?? null;
|
|
77
|
+
};
|
|
78
|
+
var savePendingCommand = (sessionId, command, namespace = "") => {
|
|
79
|
+
const dir = commandDirFor(sessionId, namespace);
|
|
80
|
+
try {
|
|
81
|
+
mkdirSync(dir, { recursive: true, mode: 448 });
|
|
82
|
+
pruneExpiredCommandStore();
|
|
83
|
+
if (readPendingCommandById(sessionId, command.id, namespace)) return false;
|
|
84
|
+
writeFileSync(commandFile(sessionId, command.id, namespace), JSON.stringify(command), { encoding: "utf-8", mode: 384, flag: "wx" });
|
|
85
|
+
return true;
|
|
86
|
+
} catch {
|
|
87
|
+
return false;
|
|
88
|
+
}
|
|
89
|
+
};
|
|
90
|
+
var updatePendingCommand = (sessionId, id, update, namespace = "") => {
|
|
91
|
+
const command = readPendingCommandById(sessionId, id, namespace);
|
|
92
|
+
if (!command) return false;
|
|
93
|
+
const currentFile = commandFile(sessionId, id, namespace);
|
|
94
|
+
const file = existsSync(currentFile) ? currentFile : legacyCommandFile(sessionId, namespace);
|
|
95
|
+
const temporary = `${file}.${process.pid}.tmp`;
|
|
96
|
+
try {
|
|
97
|
+
writeFileSync(temporary, JSON.stringify({ ...command, ...update, text: "" }), { encoding: "utf-8", mode: 384 });
|
|
98
|
+
renameSync(temporary, file);
|
|
99
|
+
return true;
|
|
100
|
+
} catch {
|
|
101
|
+
try {
|
|
102
|
+
unlinkSync(temporary);
|
|
103
|
+
} catch {
|
|
104
|
+
}
|
|
105
|
+
return false;
|
|
106
|
+
}
|
|
107
|
+
};
|
|
108
|
+
var markPendingCommandDelivered = (sessionId, id, namespace = "") => updatePendingCommand(sessionId, id, { delivered: true, failed: void 0 }, namespace);
|
|
109
|
+
var markPendingCommandFailed = (sessionId, id, namespace = "") => updatePendingCommand(sessionId, id, { delivered: false, failed: true }, namespace);
|
|
110
|
+
var removePendingCommand = (sessionId, id, namespace = "") => {
|
|
111
|
+
if (!readPendingCommandById(sessionId, id, namespace)) return;
|
|
112
|
+
try {
|
|
113
|
+
unlinkSync(commandFile(sessionId, id, namespace));
|
|
114
|
+
} catch {
|
|
115
|
+
}
|
|
116
|
+
try {
|
|
117
|
+
if (readCommandFile(legacyCommandFile(sessionId, namespace))?.id === id) {
|
|
118
|
+
unlinkSync(legacyCommandFile(sessionId, namespace));
|
|
119
|
+
}
|
|
120
|
+
} catch {
|
|
121
|
+
}
|
|
122
|
+
};
|
|
123
|
+
var isDefaultSession = (sessionId) => sanitize(sessionId) === DEFAULT_SESSION;
|
|
124
|
+
var listPendingQuestionsForToolUse = (sessionId, toolUseId) => {
|
|
125
|
+
if (!toolUseId) return [];
|
|
126
|
+
const dir = dirFor(sessionId);
|
|
127
|
+
let files;
|
|
128
|
+
try {
|
|
129
|
+
files = readdirSync(dir);
|
|
130
|
+
} catch {
|
|
131
|
+
return [];
|
|
132
|
+
}
|
|
133
|
+
return files.filter((name) => {
|
|
134
|
+
try {
|
|
135
|
+
return readFileSync(join(dir, name), "utf-8") === toolUseId;
|
|
136
|
+
} catch {
|
|
137
|
+
return false;
|
|
138
|
+
}
|
|
139
|
+
});
|
|
140
|
+
};
|
|
141
|
+
var listPendingQuestions = (sessionId) => {
|
|
142
|
+
const dir = dirFor(sessionId);
|
|
143
|
+
let files;
|
|
144
|
+
try {
|
|
145
|
+
files = readdirSync(dir);
|
|
146
|
+
} catch {
|
|
147
|
+
return [];
|
|
148
|
+
}
|
|
149
|
+
if (!isDefaultSession(sessionId)) return files;
|
|
150
|
+
const cutoff = Date.now() - GRACE_MS;
|
|
151
|
+
return files.filter((name) => {
|
|
152
|
+
try {
|
|
153
|
+
return statSync(join(dir, name)).mtimeMs < cutoff;
|
|
154
|
+
} catch {
|
|
155
|
+
return false;
|
|
156
|
+
}
|
|
157
|
+
});
|
|
158
|
+
};
|
|
159
|
+
var removePendingQuestion = (sessionId, correlationId) => {
|
|
160
|
+
try {
|
|
161
|
+
unlinkSync(join(dirFor(sessionId), correlationId));
|
|
162
|
+
} catch {
|
|
163
|
+
}
|
|
164
|
+
};
|
|
165
|
+
var removePendingSession = (sessionId) => {
|
|
166
|
+
try {
|
|
167
|
+
rmSync(dirFor(sessionId), { recursive: true, force: true });
|
|
168
|
+
} catch {
|
|
169
|
+
}
|
|
170
|
+
};
|
|
171
|
+
|
|
172
|
+
export {
|
|
173
|
+
DEFAULT_SESSION,
|
|
174
|
+
readPendingCommandById,
|
|
175
|
+
readPendingCommand,
|
|
176
|
+
savePendingCommand,
|
|
177
|
+
markPendingCommandDelivered,
|
|
178
|
+
markPendingCommandFailed,
|
|
179
|
+
removePendingCommand,
|
|
180
|
+
isDefaultSession,
|
|
181
|
+
listPendingQuestionsForToolUse,
|
|
182
|
+
listPendingQuestions,
|
|
183
|
+
removePendingQuestion,
|
|
184
|
+
removePendingSession
|
|
185
|
+
};
|