@pushary/agent-hooks 0.95.2 → 0.95.5
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 +19 -0
- package/README.md +1 -1
- package/data/cursor-plugin/.cursor-plugin/plugin.json +1 -1
- package/data/cursor-plugin/CHANGELOG.md +5 -0
- package/data/cursor-plugin/README.md +6 -8
- package/data/cursor-plugin/hooks/hooks.json +56 -1
- package/data/cursor-plugin/scripts/pushary-gate.mjs +120 -71
- package/data/vscode-plugin/.claude-plugin/plugin.json +1 -1
- package/data/vscode-plugin/CHANGELOG.md +5 -0
- package/data/vscode-plugin/README.md +7 -15
- package/data/vscode-plugin/hooks/hooks.json +49 -0
- package/data/vscode-plugin/scripts/pushary-gate.mjs +208 -88
- package/dist/bin/pushary-bell-hook.js +20 -22
- package/dist/bin/pushary-bell.js +9 -11
- package/dist/bin/pushary-claude.js +58 -46
- package/dist/bin/pushary-clean.js +21 -20
- package/dist/bin/pushary-codex-bridge.js +120 -25
- package/dist/bin/pushary-codex-hook.js +43 -63
- package/dist/bin/pushary-codex.js +11 -10
- package/dist/bin/pushary-connect.js +8 -10
- package/dist/bin/pushary-cowork.js +5 -5
- package/dist/bin/pushary-daemon.js +26 -28
- package/dist/bin/pushary-disconnect.js +11 -10
- package/dist/bin/pushary-doctor.js +25 -25
- package/dist/bin/pushary-elicitation-hook.js +30 -31
- package/dist/bin/pushary-gemini-bridge.js +9 -11
- package/dist/bin/pushary-gemini-hook.js +45 -79
- package/dist/bin/pushary-hook.js +27 -29
- package/dist/bin/pushary-login.js +57 -31
- package/dist/bin/pushary-logout.js +6 -8
- package/dist/bin/pushary-mode.js +5 -5
- package/dist/bin/pushary-notification-hook.js +22 -24
- package/dist/bin/pushary-opencode-hook.js +38 -74
- package/dist/bin/pushary-permission-denied-hook.js +25 -27
- package/dist/bin/pushary-permission-hook.js +25 -27
- package/dist/bin/pushary-post-hook.js +22 -24
- package/dist/bin/pushary-prompt-hook.js +22 -24
- package/dist/bin/pushary-session-end-hook.js +22 -24
- package/dist/bin/pushary-session-start-hook.js +25 -27
- package/dist/bin/pushary-setup.js +78 -55
- package/dist/bin/pushary-stats.js +4 -4
- package/dist/bin/pushary-status.js +10 -12
- package/dist/bin/pushary-stop-hook.js +22 -24
- package/dist/bin/pushary-stopfailure-hook.js +22 -24
- package/dist/bin/pushary-suggestions.js +2 -2
- package/dist/bin/pushary-transcript-register.js +18 -20
- package/dist/bin/pushary-transcripts.js +7 -9
- package/dist/bin/pushary-upgrade.js +17 -19
- package/dist/bin/pushary-wait.js +5 -5
- package/dist/bin/pushary.js +1 -1
- package/dist/{chunk-7LUFYRH4.js → chunk-2D7BAOMY.js} +7 -7
- package/dist/{chunk-3ZUTNTZA.js → chunk-2ZTL3PGN.js} +1 -1
- package/dist/{chunk-EPFDN2ZT.js → chunk-32RMQO5Z.js} +1 -1
- package/dist/{chunk-EZIEXHYM.js → chunk-3AJIK5AO.js} +5 -2
- package/dist/{chunk-IPHOUBTU.js → chunk-4PX4QK2Z.js} +1 -1
- package/dist/{chunk-UW4LWAWY.js → chunk-4RF52LSU.js} +8 -8
- package/dist/{chunk-UOTSWS5N.js → chunk-67YNQ3QA.js} +43 -98
- package/dist/{chunk-G4TL4YWH.js → chunk-6AEM5RCS.js} +1 -1
- package/dist/{chunk-G24SEVCI.js → chunk-6VANQN5Q.js} +3 -7
- package/dist/{chunk-CKOLDI47.js → chunk-BDI2MXTT.js} +2 -2
- package/dist/{chunk-YKLCWWEI.js → chunk-BMANRGJQ.js} +1 -1
- package/dist/{chunk-2XUPP4WM.js → chunk-CUEZMPLJ.js} +1 -1
- package/dist/{chunk-A4R6BZCK.js → chunk-D62EONG3.js} +1 -1
- package/dist/{chunk-ZDAT5KMU.js → chunk-D6PRC3YQ.js} +1 -1
- package/dist/{chunk-MOY5X6HJ.js → chunk-DLLAWCQB.js} +1 -1
- package/dist/{chunk-DSTLA2TC.js → chunk-GOPIMNVC.js} +1 -1
- package/dist/{chunk-CH6DTGQR.js → chunk-HBHEX3JQ.js} +3 -3
- package/dist/{chunk-DNVDKHQD.js → chunk-HCMM3BOW.js} +226 -58
- package/dist/{chunk-76XICHYT.js → chunk-HGUZOUB2.js} +4 -4
- package/dist/{chunk-E3NF5CL2.js → chunk-HQIVR7MM.js} +6 -3
- package/dist/{chunk-JDFB3YKG.js → chunk-I6GZX3FT.js} +3 -3
- package/dist/{chunk-3OXHYPZG.js → chunk-IM2A5H33.js} +4 -1
- package/dist/{chunk-V27AHID3.js → chunk-IVQMNLSA.js} +3 -14
- package/dist/{chunk-4LL6LG5X.js → chunk-KAVDAZ7A.js} +43 -1
- package/dist/chunk-KBITFQST.js +6 -0
- package/dist/{chunk-AMZJ3CKW.js → chunk-KI4PA7MQ.js} +1 -1
- package/dist/{chunk-IAEXPTXA.js → chunk-N4VNLISN.js} +2 -2
- package/dist/{chunk-VX3BWMC5.js → chunk-OEKFD5BC.js} +1 -1
- package/dist/{chunk-QF4RI5CD.js → chunk-OI3DJA7N.js} +1 -1
- package/dist/{chunk-WB2C7VPF.js → chunk-OW6AZDY2.js} +3 -3
- package/dist/{chunk-4XXUHWIK.js → chunk-QHWXUNMN.js} +1 -1
- package/dist/{chunk-M7WWEFG6.js → chunk-QQGNFHIK.js} +2 -2
- package/dist/{chunk-YJAQRKH5.js → chunk-RLXVW4AM.js} +1 -1
- package/dist/{chunk-GUVCYYDK.js → chunk-S5CMLR35.js} +94 -15
- package/dist/{chunk-EUAQ4YAN.js → chunk-UCS65VVR.js} +1 -1
- package/dist/{chunk-WM5XMCID.js → chunk-VOSGZ6PH.js} +4 -4
- package/dist/{chunk-QUE76J4H.js → chunk-VTO3TNIB.js} +1 -1
- package/dist/{chunk-6FAHPGCZ.js → chunk-WDKHZRAS.js} +183 -25
- package/dist/{chunk-5GLPYGKS.js → chunk-WRDLHR2F.js} +2 -2
- package/dist/{chunk-RVSEGFPD.js → chunk-XLOELLAS.js} +9 -4
- package/dist/chunk-XS33QBJA.js +112 -0
- package/dist/{chunk-FQUV5KTM.js → chunk-Z2UWFEJW.js} +8 -8
- package/dist/src/index.d.ts +8 -1
- package/dist/src/index.js +11 -12
- package/package.json +1 -1
- package/dist/chunk-BC3VCZ3E.js +0 -86
- package/dist/chunk-RER3FRTD.js +0 -265
- package/dist/chunk-X7YWD6IS.js +0 -44
|
@@ -0,0 +1,112 @@
|
|
|
1
|
+
import {
|
|
2
|
+
callMcpTool
|
|
3
|
+
} from "./chunk-EYRGBYZG.js";
|
|
4
|
+
import {
|
|
5
|
+
installProxyDispatcher
|
|
6
|
+
} from "./chunk-SAF6HGAA.js";
|
|
7
|
+
|
|
8
|
+
// src/api.ts
|
|
9
|
+
import { randomUUID } from "crypto";
|
|
10
|
+
|
|
11
|
+
// src/validate.ts
|
|
12
|
+
var isPolicyConfig = (data) => {
|
|
13
|
+
if (!data || typeof data !== "object") return false;
|
|
14
|
+
const d = data;
|
|
15
|
+
return (d.resolvedAgent === void 0 || typeof d.resolvedAgent === "string") && Array.isArray(d.policies) && typeof d.defaultTimeoutSeconds === "number" && typeof d.defaultTimeoutAction === "string";
|
|
16
|
+
};
|
|
17
|
+
var isAskUserResponse = (data) => {
|
|
18
|
+
if (!data || typeof data !== "object") return false;
|
|
19
|
+
const d = data;
|
|
20
|
+
return typeof d.correlationId === "string" && typeof d.status === "string" && (d.answered === void 0 || typeof d.answered === "boolean") && (d.value === void 0 || typeof d.value === "string") && (d.note === void 0 || typeof d.note === "string") && (d.waitEndsAt === void 0 || typeof d.waitEndsAt === "string");
|
|
21
|
+
};
|
|
22
|
+
var isWaitForAnswerResponse = (data) => {
|
|
23
|
+
if (!data || typeof data !== "object") return false;
|
|
24
|
+
const d = data;
|
|
25
|
+
return typeof d.answered === "boolean";
|
|
26
|
+
};
|
|
27
|
+
|
|
28
|
+
// src/api.ts
|
|
29
|
+
installProxyDispatcher();
|
|
30
|
+
var DECISION_STOP_REASON = "Approval was cancelled or became unavailable. Retry only after resolving it.";
|
|
31
|
+
var isDecisionStopped = (result) => result.handoffAction === "stop" || ["cancelled", "unavailable", "stopped", "missing"].includes(result.status ?? "");
|
|
32
|
+
var isLocalQuestionHandoff = (result) => result.suppressed === true || result.noDevices === true || result.status === "terminal" || result.status === "notified";
|
|
33
|
+
var STOPPED = { answered: false, handoffAction: "stop" };
|
|
34
|
+
var askUser = async (apiKey, params, timeoutMs = 15e3) => {
|
|
35
|
+
const identified = params.toolUseId || params.requestId ? params : { ...params, requestId: randomUUID() };
|
|
36
|
+
const result = await callMcpTool(apiKey, "ask_user", { ...identified, wait: false }, { maxRetries: 3, timeoutMs });
|
|
37
|
+
if (!isAskUserResponse(result)) throw new Error("Invalid ask_user response");
|
|
38
|
+
return result;
|
|
39
|
+
};
|
|
40
|
+
var waitForAnswer = async (apiKey, correlationId, timeoutMs = 3e4, signal) => {
|
|
41
|
+
const result = await callMcpTool(apiKey, "wait_for_answer", {
|
|
42
|
+
correlationId,
|
|
43
|
+
timeoutMs
|
|
44
|
+
}, { timeoutMs: timeoutMs + 1e4, signal });
|
|
45
|
+
if (!isWaitForAnswerResponse(result)) throw new Error("Invalid wait_for_answer response");
|
|
46
|
+
return result;
|
|
47
|
+
};
|
|
48
|
+
var WAIT_RESPONSE_GRACE_MS = 2e3;
|
|
49
|
+
var MIN_LONG_POLL_MS = 1e3;
|
|
50
|
+
var MAX_LONG_POLL_MS = 3e4;
|
|
51
|
+
var nextLongPollMs = (deadlineMs, nowMs) => {
|
|
52
|
+
const hold = Math.min(deadlineMs - nowMs - WAIT_RESPONSE_GRACE_MS, MAX_LONG_POLL_MS);
|
|
53
|
+
return hold >= MIN_LONG_POLL_MS ? hold : null;
|
|
54
|
+
};
|
|
55
|
+
var pollForAnswer = async (apiKey, correlationId, deadlineMs, pollInterval = 2e3) => {
|
|
56
|
+
const sleep = (ms) => new Promise((resolve) => setTimeout(resolve, ms));
|
|
57
|
+
while (Date.now() < deadlineMs) {
|
|
58
|
+
const hold = nextLongPollMs(deadlineMs, Date.now());
|
|
59
|
+
if (hold === null) {
|
|
60
|
+
await sleep(Math.max(0, deadlineMs - Date.now()));
|
|
61
|
+
continue;
|
|
62
|
+
}
|
|
63
|
+
let answer;
|
|
64
|
+
try {
|
|
65
|
+
answer = await waitForAnswer(apiKey, correlationId, hold, AbortSignal.timeout(Math.max(1, deadlineMs - Date.now())));
|
|
66
|
+
} catch {
|
|
67
|
+
const late = await withdrawQuestion(apiKey, correlationId);
|
|
68
|
+
return late.answered ? late : STOPPED;
|
|
69
|
+
}
|
|
70
|
+
if (isDecisionStopped(answer) || answer.answered) return answer;
|
|
71
|
+
if (answer.status === "expired") return STOPPED;
|
|
72
|
+
await sleep(Math.min(pollInterval, Math.max(0, deadlineMs - Date.now())));
|
|
73
|
+
}
|
|
74
|
+
return withdrawQuestion(apiKey, correlationId);
|
|
75
|
+
};
|
|
76
|
+
var cancelQuestion = async (apiKey, correlationId, signal) => {
|
|
77
|
+
return callMcpTool(apiKey, "cancel_question", { correlationId }, { signal, timeoutMs: 4e3, maxRetries: 1 });
|
|
78
|
+
};
|
|
79
|
+
var withdrawQuestion = async (apiKey, correlationId, transport = { cancelQuestion, waitForAnswer }) => {
|
|
80
|
+
try {
|
|
81
|
+
const cancelled = await transport.cancelQuestion(apiKey, correlationId, AbortSignal.timeout(4e3));
|
|
82
|
+
if (!cancelled || isDecisionStopped(cancelled)) return STOPPED;
|
|
83
|
+
if (cancelled.cancelled === true) return { answered: false, status: "withdrawn" };
|
|
84
|
+
const late = await transport.waitForAnswer(apiKey, correlationId, 1e3, AbortSignal.timeout(2e3));
|
|
85
|
+
if (late.answered || isDecisionStopped(late)) return late;
|
|
86
|
+
return late.status === "expired" ? { answered: false, status: "withdrawn" } : STOPPED;
|
|
87
|
+
} catch {
|
|
88
|
+
return STOPPED;
|
|
89
|
+
}
|
|
90
|
+
};
|
|
91
|
+
var waitForQuestion = async (apiKey, question, deadlineMs, pollInterval = 2e3) => {
|
|
92
|
+
if (isDecisionStopped(question) || question.answered) return { ...question, answered: !!question.answered };
|
|
93
|
+
if (question.status === "expired") return STOPPED;
|
|
94
|
+
return isLocalQuestionHandoff(question) ? withdrawQuestion(apiKey, question.correlationId) : pollForAnswer(apiKey, question.correlationId, deadlineMs, pollInterval);
|
|
95
|
+
};
|
|
96
|
+
var sendNotification = async (apiKey, params, timeoutMs = 15e3, signal) => {
|
|
97
|
+
await callMcpTool(apiKey, "send_notification", { ...params }, { maxRetries: signal ? 1 : 3, timeoutMs, signal });
|
|
98
|
+
};
|
|
99
|
+
|
|
100
|
+
export {
|
|
101
|
+
isPolicyConfig,
|
|
102
|
+
DECISION_STOP_REASON,
|
|
103
|
+
isDecisionStopped,
|
|
104
|
+
isLocalQuestionHandoff,
|
|
105
|
+
askUser,
|
|
106
|
+
waitForAnswer,
|
|
107
|
+
nextLongPollMs,
|
|
108
|
+
cancelQuestion,
|
|
109
|
+
withdrawQuestion,
|
|
110
|
+
waitForQuestion,
|
|
111
|
+
sendNotification
|
|
112
|
+
};
|
|
@@ -1,16 +1,16 @@
|
|
|
1
1
|
import {
|
|
2
2
|
detectClaudeVersion
|
|
3
|
-
} from "./chunk-
|
|
3
|
+
} from "./chunk-6AEM5RCS.js";
|
|
4
4
|
import {
|
|
5
5
|
addClaudeMcpServer,
|
|
6
6
|
addPusharyHooks,
|
|
7
7
|
addPusharyToolPermissions
|
|
8
|
-
} from "./chunk-
|
|
8
|
+
} from "./chunk-HGUZOUB2.js";
|
|
9
9
|
import {
|
|
10
10
|
claudeWired,
|
|
11
11
|
codexWired,
|
|
12
12
|
geminiWired
|
|
13
|
-
} from "./chunk-
|
|
13
|
+
} from "./chunk-HBHEX3JQ.js";
|
|
14
14
|
import {
|
|
15
15
|
CLAUDE_HOOK_EVENTS,
|
|
16
16
|
GEMINI_HOOK_BINARY,
|
|
@@ -21,10 +21,10 @@ import {
|
|
|
21
21
|
needsReregistration,
|
|
22
22
|
registrationSignatures,
|
|
23
23
|
supportedClaudeEvents
|
|
24
|
-
} from "./chunk-
|
|
24
|
+
} from "./chunk-2D7BAOMY.js";
|
|
25
25
|
import {
|
|
26
26
|
guardBinary
|
|
27
|
-
} from "./chunk-
|
|
27
|
+
} from "./chunk-3AJIK5AO.js";
|
|
28
28
|
import {
|
|
29
29
|
resolveGlobalBinDir,
|
|
30
30
|
resolveGlobalBinary
|
|
@@ -40,14 +40,14 @@ import {
|
|
|
40
40
|
codexHooksJson,
|
|
41
41
|
hasCodexHooks,
|
|
42
42
|
vscodePluginMcp
|
|
43
|
-
} from "./chunk-
|
|
43
|
+
} from "./chunk-OW6AZDY2.js";
|
|
44
44
|
import {
|
|
45
45
|
readJsonSafe,
|
|
46
46
|
writeJsonAtomic
|
|
47
|
-
} from "./chunk-
|
|
47
|
+
} from "./chunk-KAVDAZ7A.js";
|
|
48
48
|
import {
|
|
49
49
|
HOOK_LOCATOR_BINARY
|
|
50
|
-
} from "./chunk-
|
|
50
|
+
} from "./chunk-WDKHZRAS.js";
|
|
51
51
|
|
|
52
52
|
// src/reapply.ts
|
|
53
53
|
import { join } from "path";
|
package/dist/src/index.d.ts
CHANGED
|
@@ -160,6 +160,7 @@ interface AskUserParams {
|
|
|
160
160
|
interface AskUserResponse {
|
|
161
161
|
correlationId: string;
|
|
162
162
|
status: string;
|
|
163
|
+
handoffAction?: string;
|
|
163
164
|
delivery?: {
|
|
164
165
|
web: number;
|
|
165
166
|
mobile: number;
|
|
@@ -173,13 +174,19 @@ interface AskUserResponse {
|
|
|
173
174
|
answerUrl?: string;
|
|
174
175
|
}
|
|
175
176
|
interface AnswerResult {
|
|
177
|
+
status?: string;
|
|
178
|
+
handoffAction?: string;
|
|
176
179
|
answered: boolean;
|
|
177
180
|
value?: string;
|
|
178
181
|
note?: string;
|
|
179
182
|
}
|
|
180
183
|
declare const askUser: (apiKey: string, params: AskUserParams, timeoutMs?: number) => Promise<AskUserResponse>;
|
|
181
184
|
declare const waitForAnswer: (apiKey: string, correlationId: string, timeoutMs?: number, signal?: AbortSignal) => Promise<AnswerResult>;
|
|
182
|
-
declare const cancelQuestion: (apiKey: string, correlationId: string, signal?: AbortSignal) => Promise<
|
|
185
|
+
declare const cancelQuestion: (apiKey: string, correlationId: string, signal?: AbortSignal) => Promise<{
|
|
186
|
+
cancelled?: boolean;
|
|
187
|
+
status?: string;
|
|
188
|
+
handoffAction?: string;
|
|
189
|
+
}>;
|
|
183
190
|
|
|
184
191
|
declare const getApiKey: () => string;
|
|
185
192
|
declare const getBaseUrl: () => string;
|
package/dist/src/index.js
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
import {
|
|
2
2
|
handlePreToolUse
|
|
3
|
-
} from "../chunk-
|
|
4
|
-
import "../chunk-
|
|
5
|
-
import "../chunk-
|
|
3
|
+
} from "../chunk-67YNQ3QA.js";
|
|
4
|
+
import "../chunk-D62EONG3.js";
|
|
5
|
+
import "../chunk-UCS65VVR.js";
|
|
6
6
|
import "../chunk-YHG74UFF.js";
|
|
7
7
|
import {
|
|
8
8
|
fetchAccountPublicKey
|
|
@@ -15,29 +15,28 @@ import {
|
|
|
15
15
|
handlePostToolUse,
|
|
16
16
|
handleStop,
|
|
17
17
|
reportEvent
|
|
18
|
-
} from "../chunk-
|
|
18
|
+
} from "../chunk-HCMM3BOW.js";
|
|
19
19
|
import {
|
|
20
20
|
askUser,
|
|
21
21
|
cancelQuestion,
|
|
22
22
|
waitForAnswer
|
|
23
|
-
} from "../chunk-
|
|
24
|
-
import "../chunk-
|
|
25
|
-
import "../chunk-
|
|
26
|
-
import "../chunk-
|
|
27
|
-
import "../chunk-
|
|
23
|
+
} from "../chunk-XS33QBJA.js";
|
|
24
|
+
import "../chunk-BDI2MXTT.js";
|
|
25
|
+
import "../chunk-IVQMNLSA.js";
|
|
26
|
+
import "../chunk-N4VNLISN.js";
|
|
27
|
+
import "../chunk-OW6AZDY2.js";
|
|
28
28
|
import "../chunk-EYRGBYZG.js";
|
|
29
29
|
import "../chunk-SAF6HGAA.js";
|
|
30
30
|
import "../chunk-7QLSKOSU.js";
|
|
31
31
|
import "../chunk-KZERVKTD.js";
|
|
32
|
-
import "../chunk-
|
|
33
|
-
import "../chunk-4LL6LG5X.js";
|
|
32
|
+
import "../chunk-KAVDAZ7A.js";
|
|
34
33
|
import {
|
|
35
34
|
getApiKey,
|
|
36
35
|
getBaseUrl
|
|
37
36
|
} from "../chunk-2UMNXADU.js";
|
|
38
37
|
import {
|
|
39
38
|
resolvePolicy
|
|
40
|
-
} from "../chunk-
|
|
39
|
+
} from "../chunk-WDKHZRAS.js";
|
|
41
40
|
export {
|
|
42
41
|
askUser,
|
|
43
42
|
cancelQuestion,
|
package/package.json
CHANGED
package/dist/chunk-BC3VCZ3E.js
DELETED
|
@@ -1,86 +0,0 @@
|
|
|
1
|
-
// src/shell-alias.ts
|
|
2
|
-
import { homedir } from "os";
|
|
3
|
-
import { existsSync, readFileSync, appendFileSync, writeFileSync } from "fs";
|
|
4
|
-
import { join } from "path";
|
|
5
|
-
var MARKER_START = "# >>> pushary >>>";
|
|
6
|
-
var MARKER_END = "# <<< pushary <<<";
|
|
7
|
-
var CANDIDATE_RCS = [".zshrc", ".zprofile", ".bashrc", ".bash_profile"];
|
|
8
|
-
var aliasBlock = () => `${MARKER_START}
|
|
9
|
-
# Make \`claude\` reachable from your phone when idle (runs it through Pushary).
|
|
10
|
-
# Remove this block, or run \`pushary clean\`, to undo.
|
|
11
|
-
alias claude='pushary claude'
|
|
12
|
-
${MARKER_END}
|
|
13
|
-
`;
|
|
14
|
-
var hasClaudeAlias = (content) => content.includes(MARKER_START) || /alias\s+claude=['"]?pushary claude/.test(content);
|
|
15
|
-
var stripPusharyBlock = (content) => {
|
|
16
|
-
const lines = content.split("\n");
|
|
17
|
-
const out = [];
|
|
18
|
-
let inBlock = false;
|
|
19
|
-
for (const line of lines) {
|
|
20
|
-
const trimmed = line.trim();
|
|
21
|
-
if (trimmed === MARKER_START) {
|
|
22
|
-
inBlock = true;
|
|
23
|
-
continue;
|
|
24
|
-
}
|
|
25
|
-
if (trimmed === MARKER_END) {
|
|
26
|
-
inBlock = false;
|
|
27
|
-
continue;
|
|
28
|
-
}
|
|
29
|
-
if (!inBlock) out.push(line);
|
|
30
|
-
}
|
|
31
|
-
return out.join("\n").replace(/\n{3,}/g, "\n\n");
|
|
32
|
-
};
|
|
33
|
-
var resolveShellRc = () => {
|
|
34
|
-
if (process.platform === "win32") return null;
|
|
35
|
-
const shell = (process.env.SHELL ?? "").split("/").pop() ?? "";
|
|
36
|
-
const home = homedir();
|
|
37
|
-
if (shell === "zsh") return { path: join(home, ".zshrc"), shell };
|
|
38
|
-
if (shell === "bash") {
|
|
39
|
-
const bashrc = join(home, ".bashrc");
|
|
40
|
-
const profile = join(home, ".bash_profile");
|
|
41
|
-
if (process.platform === "darwin") return { path: profile, shell };
|
|
42
|
-
return { path: existsSync(bashrc) ? bashrc : profile, shell };
|
|
43
|
-
}
|
|
44
|
-
return null;
|
|
45
|
-
};
|
|
46
|
-
var installClaudeAlias = () => {
|
|
47
|
-
const rc = resolveShellRc();
|
|
48
|
-
if (!rc) return { installed: false, reason: "unsupported-shell" };
|
|
49
|
-
let content = "";
|
|
50
|
-
try {
|
|
51
|
-
content = readFileSync(rc.path, "utf-8");
|
|
52
|
-
} catch {
|
|
53
|
-
}
|
|
54
|
-
if (hasClaudeAlias(content)) return { installed: false, path: rc.path, reason: "exists" };
|
|
55
|
-
const gap = content.length > 0 && !content.endsWith("\n") ? "\n\n" : content.length > 0 ? "\n" : "";
|
|
56
|
-
appendFileSync(rc.path, `${gap}${aliasBlock()}`, "utf-8");
|
|
57
|
-
return { installed: true, path: rc.path };
|
|
58
|
-
};
|
|
59
|
-
var removeClaudeAlias = () => {
|
|
60
|
-
const removed = [];
|
|
61
|
-
for (const name of CANDIDATE_RCS) {
|
|
62
|
-
const path = join(homedir(), name);
|
|
63
|
-
if (!existsSync(path)) continue;
|
|
64
|
-
let content;
|
|
65
|
-
try {
|
|
66
|
-
content = readFileSync(path, "utf-8");
|
|
67
|
-
} catch {
|
|
68
|
-
continue;
|
|
69
|
-
}
|
|
70
|
-
const stripped = stripPusharyBlock(content);
|
|
71
|
-
if (stripped !== content) {
|
|
72
|
-
try {
|
|
73
|
-
writeFileSync(path, stripped, "utf-8");
|
|
74
|
-
removed.push(path);
|
|
75
|
-
} catch {
|
|
76
|
-
}
|
|
77
|
-
}
|
|
78
|
-
}
|
|
79
|
-
return removed;
|
|
80
|
-
};
|
|
81
|
-
|
|
82
|
-
export {
|
|
83
|
-
resolveShellRc,
|
|
84
|
-
installClaudeAlias,
|
|
85
|
-
removeClaudeAlias
|
|
86
|
-
};
|
package/dist/chunk-RER3FRTD.js
DELETED
|
@@ -1,265 +0,0 @@
|
|
|
1
|
-
import {
|
|
2
|
-
callMcpTool
|
|
3
|
-
} from "./chunk-EYRGBYZG.js";
|
|
4
|
-
import {
|
|
5
|
-
installProxyDispatcher
|
|
6
|
-
} from "./chunk-SAF6HGAA.js";
|
|
7
|
-
|
|
8
|
-
// src/api.ts
|
|
9
|
-
import { randomUUID } from "crypto";
|
|
10
|
-
|
|
11
|
-
// src/validate.ts
|
|
12
|
-
var isPolicyConfig = (data) => {
|
|
13
|
-
if (!data || typeof data !== "object") return false;
|
|
14
|
-
const d = data;
|
|
15
|
-
return Array.isArray(d.policies) && typeof d.defaultTimeoutSeconds === "number" && typeof d.defaultTimeoutAction === "string";
|
|
16
|
-
};
|
|
17
|
-
var isAskUserResponse = (data) => {
|
|
18
|
-
if (!data || typeof data !== "object") return false;
|
|
19
|
-
const d = data;
|
|
20
|
-
return typeof d.correlationId === "string" && typeof d.status === "string" && (d.answered === void 0 || typeof d.answered === "boolean") && (d.value === void 0 || typeof d.value === "string") && (d.note === void 0 || typeof d.note === "string") && (d.waitEndsAt === void 0 || typeof d.waitEndsAt === "string");
|
|
21
|
-
};
|
|
22
|
-
var isWaitForAnswerResponse = (data) => {
|
|
23
|
-
if (!data || typeof data !== "object") return false;
|
|
24
|
-
const d = data;
|
|
25
|
-
return typeof d.answered === "boolean";
|
|
26
|
-
};
|
|
27
|
-
|
|
28
|
-
// src/api.ts
|
|
29
|
-
installProxyDispatcher();
|
|
30
|
-
var askUser = async (apiKey, params, timeoutMs = 15e3) => {
|
|
31
|
-
const identified = params.toolUseId || params.requestId ? params : { ...params, requestId: randomUUID() };
|
|
32
|
-
const result = await callMcpTool(apiKey, "ask_user", { ...identified, wait: false }, { maxRetries: 3, timeoutMs });
|
|
33
|
-
if (!isAskUserResponse(result)) throw new Error("Invalid ask_user response");
|
|
34
|
-
return result;
|
|
35
|
-
};
|
|
36
|
-
var waitForAnswer = async (apiKey, correlationId, timeoutMs = 3e4, signal) => {
|
|
37
|
-
const result = await callMcpTool(apiKey, "wait_for_answer", {
|
|
38
|
-
correlationId,
|
|
39
|
-
timeoutMs
|
|
40
|
-
}, { timeoutMs: timeoutMs + 1e4, signal });
|
|
41
|
-
if (!isWaitForAnswerResponse(result)) throw new Error("Invalid wait_for_answer response");
|
|
42
|
-
return result;
|
|
43
|
-
};
|
|
44
|
-
var pollForAnswer = async (apiKey, correlationId, deadlineMs, pollInterval = 2e3) => {
|
|
45
|
-
const sleep = (ms) => new Promise((resolve) => setTimeout(resolve, ms));
|
|
46
|
-
while (Date.now() < deadlineMs) {
|
|
47
|
-
const remaining = Math.min(Math.max(deadlineMs - Date.now(), 1e3), 3e4);
|
|
48
|
-
let answer;
|
|
49
|
-
try {
|
|
50
|
-
answer = await waitForAnswer(apiKey, correlationId, remaining);
|
|
51
|
-
} catch {
|
|
52
|
-
if (Date.now() + pollInterval >= deadlineMs) break;
|
|
53
|
-
await sleep(pollInterval);
|
|
54
|
-
continue;
|
|
55
|
-
}
|
|
56
|
-
if (answer.answered) return answer;
|
|
57
|
-
if (Date.now() + pollInterval >= deadlineMs) break;
|
|
58
|
-
await sleep(pollInterval);
|
|
59
|
-
}
|
|
60
|
-
return { answered: false };
|
|
61
|
-
};
|
|
62
|
-
var cancelQuestion = async (apiKey, correlationId, signal) => {
|
|
63
|
-
await callMcpTool(apiKey, "cancel_question", { correlationId }, { signal });
|
|
64
|
-
};
|
|
65
|
-
var sendNotification = async (apiKey, params, timeoutMs = 15e3, signal) => {
|
|
66
|
-
await callMcpTool(apiKey, "send_notification", { ...params }, { maxRetries: signal ? 1 : 3, timeoutMs, signal });
|
|
67
|
-
};
|
|
68
|
-
|
|
69
|
-
// src/pending.ts
|
|
70
|
-
import { join } from "path";
|
|
71
|
-
import { homedir, tmpdir } from "os";
|
|
72
|
-
import { createHash } from "crypto";
|
|
73
|
-
import { existsSync, mkdirSync, writeFileSync, readFileSync, readdirSync, renameSync, unlinkSync, rmSync, statSync } from "fs";
|
|
74
|
-
var PENDING_DIR = join(tmpdir(), "pushary-pending");
|
|
75
|
-
var commandRoot = () => process.env.PUSHARY_COMMAND_DIR?.trim() || join(homedir(), ".pushary", "run", "commands");
|
|
76
|
-
var DEFAULT_SESSION = "_no_session";
|
|
77
|
-
var GRACE_MS = 10 * 60 * 1e3;
|
|
78
|
-
var sanitize = (sessionId) => sessionId.replace(/[^A-Za-z0-9_-]/g, "_").slice(0, 128) || DEFAULT_SESSION;
|
|
79
|
-
var dirFor = (sessionId) => join(PENDING_DIR, sanitize(sessionId));
|
|
80
|
-
var commandDirFor = (sessionId, namespace = "") => join(
|
|
81
|
-
commandRoot(),
|
|
82
|
-
createHash("sha256").update(namespace).digest("hex").slice(0, 16),
|
|
83
|
-
sanitize(sessionId)
|
|
84
|
-
);
|
|
85
|
-
var legacyCommandFile = (sessionId, namespace = "") => join(commandDirFor(sessionId, namespace), "command.json");
|
|
86
|
-
var commandFile = (sessionId, id, namespace = "") => join(commandDirFor(sessionId, namespace), `${createHash("sha256").update(id).digest("hex")}.json`);
|
|
87
|
-
var readCommandFile = (file) => {
|
|
88
|
-
try {
|
|
89
|
-
const value = JSON.parse(readFileSync(file, "utf-8"));
|
|
90
|
-
if (typeof value.id !== "string" || typeof value.text !== "string" || typeof value.expiresAtMs !== "number") return null;
|
|
91
|
-
if (value.expiresAtMs <= Date.now()) {
|
|
92
|
-
unlinkSync(file);
|
|
93
|
-
return null;
|
|
94
|
-
}
|
|
95
|
-
return {
|
|
96
|
-
...value,
|
|
97
|
-
delivered: value.delivered === true,
|
|
98
|
-
...value.failed === true ? { failed: true } : {}
|
|
99
|
-
};
|
|
100
|
-
} catch {
|
|
101
|
-
return null;
|
|
102
|
-
}
|
|
103
|
-
};
|
|
104
|
-
var readPendingCommandById = (sessionId, id, namespace = "") => {
|
|
105
|
-
const current = readCommandFile(commandFile(sessionId, id, namespace));
|
|
106
|
-
if (current?.id === id) return current;
|
|
107
|
-
const legacy = readCommandFile(legacyCommandFile(sessionId, namespace));
|
|
108
|
-
return legacy?.id === id ? legacy : null;
|
|
109
|
-
};
|
|
110
|
-
var pruneExpiredCommands = (dir) => {
|
|
111
|
-
let files;
|
|
112
|
-
try {
|
|
113
|
-
files = readdirSync(dir).filter((file) => file.endsWith(".json"));
|
|
114
|
-
} catch {
|
|
115
|
-
return [];
|
|
116
|
-
}
|
|
117
|
-
return files.flatMap((file) => {
|
|
118
|
-
const command = readCommandFile(join(dir, file));
|
|
119
|
-
return command ? [command] : [];
|
|
120
|
-
});
|
|
121
|
-
};
|
|
122
|
-
var pruneExpiredCommandStore = () => {
|
|
123
|
-
let namespaces;
|
|
124
|
-
try {
|
|
125
|
-
namespaces = readdirSync(commandRoot(), { withFileTypes: true });
|
|
126
|
-
} catch {
|
|
127
|
-
return;
|
|
128
|
-
}
|
|
129
|
-
for (const namespace of namespaces.filter((entry) => entry.isDirectory())) {
|
|
130
|
-
const namespaceDir = join(commandRoot(), namespace.name);
|
|
131
|
-
let sessions;
|
|
132
|
-
try {
|
|
133
|
-
sessions = readdirSync(namespaceDir, { withFileTypes: true });
|
|
134
|
-
} catch {
|
|
135
|
-
continue;
|
|
136
|
-
}
|
|
137
|
-
for (const session of sessions.filter((entry) => entry.isDirectory())) {
|
|
138
|
-
pruneExpiredCommands(join(namespaceDir, session.name));
|
|
139
|
-
}
|
|
140
|
-
}
|
|
141
|
-
};
|
|
142
|
-
var readPendingCommand = (sessionId, namespace = "") => {
|
|
143
|
-
const commands = pruneExpiredCommands(commandDirFor(sessionId, namespace));
|
|
144
|
-
return commands.find((command) => !command.delivered && !command.failed) ?? commands[0] ?? null;
|
|
145
|
-
};
|
|
146
|
-
var savePendingCommand = (sessionId, command, namespace = "") => {
|
|
147
|
-
const dir = commandDirFor(sessionId, namespace);
|
|
148
|
-
try {
|
|
149
|
-
mkdirSync(dir, { recursive: true, mode: 448 });
|
|
150
|
-
pruneExpiredCommandStore();
|
|
151
|
-
if (readPendingCommandById(sessionId, command.id, namespace)) return false;
|
|
152
|
-
writeFileSync(commandFile(sessionId, command.id, namespace), JSON.stringify(command), { encoding: "utf-8", mode: 384, flag: "wx" });
|
|
153
|
-
return true;
|
|
154
|
-
} catch {
|
|
155
|
-
return false;
|
|
156
|
-
}
|
|
157
|
-
};
|
|
158
|
-
var updatePendingCommand = (sessionId, id, update, namespace = "") => {
|
|
159
|
-
const command = readPendingCommandById(sessionId, id, namespace);
|
|
160
|
-
if (!command) return false;
|
|
161
|
-
const currentFile = commandFile(sessionId, id, namespace);
|
|
162
|
-
const file = existsSync(currentFile) ? currentFile : legacyCommandFile(sessionId, namespace);
|
|
163
|
-
const temporary = `${file}.${process.pid}.tmp`;
|
|
164
|
-
try {
|
|
165
|
-
writeFileSync(temporary, JSON.stringify({ ...command, ...update, text: "" }), { encoding: "utf-8", mode: 384 });
|
|
166
|
-
renameSync(temporary, file);
|
|
167
|
-
return true;
|
|
168
|
-
} catch {
|
|
169
|
-
try {
|
|
170
|
-
unlinkSync(temporary);
|
|
171
|
-
} catch {
|
|
172
|
-
}
|
|
173
|
-
return false;
|
|
174
|
-
}
|
|
175
|
-
};
|
|
176
|
-
var markPendingCommandDelivered = (sessionId, id, namespace = "") => updatePendingCommand(sessionId, id, { delivered: true, failed: void 0 }, namespace);
|
|
177
|
-
var markPendingCommandFailed = (sessionId, id, namespace = "") => updatePendingCommand(sessionId, id, { delivered: false, failed: true }, namespace);
|
|
178
|
-
var removePendingCommand = (sessionId, id, namespace = "") => {
|
|
179
|
-
if (!readPendingCommandById(sessionId, id, namespace)) return;
|
|
180
|
-
try {
|
|
181
|
-
unlinkSync(commandFile(sessionId, id, namespace));
|
|
182
|
-
} catch {
|
|
183
|
-
}
|
|
184
|
-
try {
|
|
185
|
-
if (readCommandFile(legacyCommandFile(sessionId, namespace))?.id === id) {
|
|
186
|
-
unlinkSync(legacyCommandFile(sessionId, namespace));
|
|
187
|
-
}
|
|
188
|
-
} catch {
|
|
189
|
-
}
|
|
190
|
-
};
|
|
191
|
-
var isDefaultSession = (sessionId) => sanitize(sessionId) === DEFAULT_SESSION;
|
|
192
|
-
var savePendingQuestion = (sessionId, correlationId, toolUseId) => {
|
|
193
|
-
const dir = dirFor(sessionId);
|
|
194
|
-
if (!existsSync(dir)) mkdirSync(dir, { recursive: true });
|
|
195
|
-
writeFileSync(join(dir, correlationId), toolUseId ?? "", "utf-8");
|
|
196
|
-
};
|
|
197
|
-
var listPendingQuestionsForToolUse = (sessionId, toolUseId) => {
|
|
198
|
-
if (!toolUseId) return [];
|
|
199
|
-
const dir = dirFor(sessionId);
|
|
200
|
-
let files;
|
|
201
|
-
try {
|
|
202
|
-
files = readdirSync(dir);
|
|
203
|
-
} catch {
|
|
204
|
-
return [];
|
|
205
|
-
}
|
|
206
|
-
return files.filter((name) => {
|
|
207
|
-
try {
|
|
208
|
-
return readFileSync(join(dir, name), "utf-8") === toolUseId;
|
|
209
|
-
} catch {
|
|
210
|
-
return false;
|
|
211
|
-
}
|
|
212
|
-
});
|
|
213
|
-
};
|
|
214
|
-
var listPendingQuestions = (sessionId) => {
|
|
215
|
-
const dir = dirFor(sessionId);
|
|
216
|
-
let files;
|
|
217
|
-
try {
|
|
218
|
-
files = readdirSync(dir);
|
|
219
|
-
} catch {
|
|
220
|
-
return [];
|
|
221
|
-
}
|
|
222
|
-
if (!isDefaultSession(sessionId)) return files;
|
|
223
|
-
const cutoff = Date.now() - GRACE_MS;
|
|
224
|
-
return files.filter((name) => {
|
|
225
|
-
try {
|
|
226
|
-
return statSync(join(dir, name)).mtimeMs < cutoff;
|
|
227
|
-
} catch {
|
|
228
|
-
return false;
|
|
229
|
-
}
|
|
230
|
-
});
|
|
231
|
-
};
|
|
232
|
-
var removePendingQuestion = (sessionId, correlationId) => {
|
|
233
|
-
try {
|
|
234
|
-
unlinkSync(join(dirFor(sessionId), correlationId));
|
|
235
|
-
} catch {
|
|
236
|
-
}
|
|
237
|
-
};
|
|
238
|
-
var removePendingSession = (sessionId) => {
|
|
239
|
-
try {
|
|
240
|
-
rmSync(dirFor(sessionId), { recursive: true, force: true });
|
|
241
|
-
} catch {
|
|
242
|
-
}
|
|
243
|
-
};
|
|
244
|
-
|
|
245
|
-
export {
|
|
246
|
-
isPolicyConfig,
|
|
247
|
-
askUser,
|
|
248
|
-
waitForAnswer,
|
|
249
|
-
pollForAnswer,
|
|
250
|
-
cancelQuestion,
|
|
251
|
-
sendNotification,
|
|
252
|
-
DEFAULT_SESSION,
|
|
253
|
-
readPendingCommandById,
|
|
254
|
-
readPendingCommand,
|
|
255
|
-
savePendingCommand,
|
|
256
|
-
markPendingCommandDelivered,
|
|
257
|
-
markPendingCommandFailed,
|
|
258
|
-
removePendingCommand,
|
|
259
|
-
isDefaultSession,
|
|
260
|
-
savePendingQuestion,
|
|
261
|
-
listPendingQuestionsForToolUse,
|
|
262
|
-
listPendingQuestions,
|
|
263
|
-
removePendingQuestion,
|
|
264
|
-
removePendingSession
|
|
265
|
-
};
|
package/dist/chunk-X7YWD6IS.js
DELETED
|
@@ -1,44 +0,0 @@
|
|
|
1
|
-
import {
|
|
2
|
-
configFilePath
|
|
3
|
-
} from "./chunk-2UMNXADU.js";
|
|
4
|
-
import {
|
|
5
|
-
normalizeInstallSource
|
|
6
|
-
} from "./chunk-6FAHPGCZ.js";
|
|
7
|
-
|
|
8
|
-
// src/install-source.ts
|
|
9
|
-
import { readFileSync } from "fs";
|
|
10
|
-
var ENV_OVERRIDE = "PUSHARY_INSTALL_SOURCE";
|
|
11
|
-
var PLUGIN_ROOT = "CLAUDE_PLUGIN_ROOT";
|
|
12
|
-
var EDITOR_PLUGIN_MARKERS = ["cursor-plugin", "vscode-plugin"];
|
|
13
|
-
var detectInstallSource = (env = process.env, argv = process.argv) => {
|
|
14
|
-
const declared = env[ENV_OVERRIDE]?.trim();
|
|
15
|
-
if (declared) return normalizeInstallSource(declared);
|
|
16
|
-
const pluginRoot = env[PLUGIN_ROOT]?.trim();
|
|
17
|
-
if (pluginRoot) {
|
|
18
|
-
return EDITOR_PLUGIN_MARKERS.some((marker) => pluginRoot.includes(marker)) ? "editor_plugin" : "claude_plugin";
|
|
19
|
-
}
|
|
20
|
-
const entry = argv[1] ?? "";
|
|
21
|
-
if (entry.includes("_npx")) return "npx";
|
|
22
|
-
if (entry) return "npm";
|
|
23
|
-
return "unknown";
|
|
24
|
-
};
|
|
25
|
-
var storedInstallSource = () => {
|
|
26
|
-
try {
|
|
27
|
-
const parsed = JSON.parse(readFileSync(configFilePath(), "utf-8"));
|
|
28
|
-
const stored = parsed.installSource;
|
|
29
|
-
return typeof stored === "string" && stored ? normalizeInstallSource(stored) : void 0;
|
|
30
|
-
} catch {
|
|
31
|
-
return void 0;
|
|
32
|
-
}
|
|
33
|
-
};
|
|
34
|
-
var resolveInstallSourceFor = (config) => {
|
|
35
|
-
const stored = config.installSource;
|
|
36
|
-
if (typeof stored === "string" && stored) return normalizeInstallSource(stored);
|
|
37
|
-
return detectInstallSource();
|
|
38
|
-
};
|
|
39
|
-
var reportedInstallSource = () => storedInstallSource() ?? detectInstallSource();
|
|
40
|
-
|
|
41
|
-
export {
|
|
42
|
-
resolveInstallSourceFor,
|
|
43
|
-
reportedInstallSource
|
|
44
|
-
};
|