@pushary/agent-hooks 0.92.1 → 0.93.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +16 -0
- package/dist/bin/pushary-bell-hook.js +4 -4
- package/dist/bin/pushary-bell.js +5 -5
- package/dist/bin/pushary-claude.js +41 -25
- package/dist/bin/pushary-clean.js +11 -11
- package/dist/bin/pushary-codex-bridge.js +10 -10
- package/dist/bin/pushary-codex-hook.js +48 -14
- package/dist/bin/pushary-codex.js +9 -8
- package/dist/bin/pushary-connect.js +7 -7
- package/dist/bin/pushary-daemon.js +13 -13
- package/dist/bin/pushary-disconnect.js +5 -5
- package/dist/bin/pushary-doctor.js +27 -20
- package/dist/bin/pushary-elicitation-hook.js +5 -5
- package/dist/bin/pushary-gemini-bridge.js +10 -10
- package/dist/bin/pushary-gemini-hook.js +10 -9
- package/dist/bin/pushary-hook.js +12 -12
- package/dist/bin/pushary-login.js +7 -7
- package/dist/bin/pushary-logout.js +4 -4
- package/dist/bin/pushary-mode.js +3 -3
- package/dist/bin/pushary-notification-hook.js +9 -8
- package/dist/bin/pushary-opencode-hook.js +10 -9
- package/dist/bin/pushary-permission-denied-hook.js +12 -12
- package/dist/bin/pushary-permission-hook.js +12 -12
- package/dist/bin/pushary-post-hook.js +9 -8
- package/dist/bin/pushary-prompt-hook.js +9 -8
- package/dist/bin/pushary-session-end-hook.js +9 -8
- package/dist/bin/pushary-session-start-hook.js +13 -13
- package/dist/bin/pushary-setup.js +21 -21
- package/dist/bin/pushary-stats.js +2 -2
- package/dist/bin/pushary-status.js +9 -9
- package/dist/bin/pushary-stop-hook.js +9 -8
- package/dist/bin/pushary-stopfailure-hook.js +9 -8
- package/dist/bin/pushary-transcripts.js +4 -4
- package/dist/bin/pushary-upgrade.js +12 -12
- package/dist/bin/pushary-wait.js +3 -3
- package/dist/{chunk-VHWCVD42.js → chunk-2ORRI66J.js} +1 -1
- package/dist/{chunk-I3ORVBTP.js → chunk-36LR2LOT.js} +5 -5
- package/dist/{chunk-7FE2KABY.js → chunk-46P3VES5.js} +1 -1
- package/dist/{chunk-L4E2BIJ2.js → chunk-4PE2SQVM.js} +57 -4
- package/dist/{chunk-YXDYKECP.js → chunk-5HGLZGI4.js} +138 -86
- package/dist/{chunk-OSALSIUF.js → chunk-6BIMJIRG.js} +1 -1
- package/dist/{chunk-UZNKVRLE.js → chunk-6WYL3XIP.js} +1 -1
- package/dist/{chunk-CELX75MW.js → chunk-BSEAOCCQ.js} +1 -1
- package/dist/{chunk-QZCFVWA7.js → chunk-EQRS3SGM.js} +3 -1
- package/dist/{chunk-BSZYIAZL.js → chunk-EYRGBYZG.js} +2 -1
- package/dist/{chunk-QCXKQJTG.js → chunk-FYOIW5RV.js} +3 -3
- package/dist/{chunk-ZMKKK6DC.js → chunk-HSAVPZ46.js} +3 -3
- package/dist/{chunk-2ACC5M7F.js → chunk-NVPYRDCT.js} +1 -1
- package/dist/{chunk-CNPAT3HL.js → chunk-OB4RF2TF.js} +2 -2
- package/dist/{chunk-JW4KO5AF.js → chunk-ODL52O5V.js} +1 -1
- package/dist/{chunk-I463AEG3.js → chunk-OYNPLEXP.js} +1 -1
- package/dist/{chunk-2XQSN66Q.js → chunk-QGA2ZB4I.js} +1 -1
- package/dist/{chunk-RQPQSJJH.js → chunk-QKNLW7H6.js} +26 -11
- package/dist/{chunk-F7OURW3C.js → chunk-RER3FRTD.js} +7 -7
- package/dist/{chunk-5NAZ7SFS.js → chunk-RH3TM7TO.js} +1 -1
- package/dist/{chunk-PYA4FLKI.js → chunk-ROHFVGXM.js} +2 -2
- package/dist/{chunk-I7W3UTDK.js → chunk-RX75MRGC.js} +10 -8
- package/dist/{chunk-4TFXV5MW.js → chunk-TDUTNYAQ.js} +1 -1
- package/dist/{chunk-BXTJVM7O.js → chunk-UZFVNEEU.js} +6 -6
- package/dist/{chunk-Z6RFZKY4.js → chunk-WY4ALDYN.js} +1 -1
- package/dist/chunk-Y3UGCQQC.js +53 -0
- package/dist/{chunk-CV2YD2JR.js → chunk-Y6XXFXVB.js} +43 -11
- package/dist/{chunk-3HS4YGHB.js → chunk-YANV5TGK.js} +3 -3
- package/dist/{chunk-VNMKIJZB.js → chunk-Z6CP5ZZD.js} +3 -0
- package/dist/{chunk-HDORB7WD.js → chunk-ZO2XG3CX.js} +1 -1
- package/dist/{chunk-SQYBP3QQ.js → chunk-ZTJF6ANY.js} +2 -2
- package/dist/src/index.d.ts +33 -3
- package/dist/src/index.js +13 -13
- package/package.json +2 -2
- package/dist/chunk-2LAHXHBR.js +0 -23
|
@@ -38,16 +38,18 @@ var uploadTranscriptRecords = async (apiKey, params, baseUrl = getBaseUrl()) =>
|
|
|
38
38
|
const body = await res.json().catch(() => null);
|
|
39
39
|
const keyRegistered = body?.keyRegistered === true;
|
|
40
40
|
const keyConflict = body?.keyConflict === true;
|
|
41
|
+
const keyUnavailable = res.status === 503;
|
|
41
42
|
const ids = (value) => Array.isArray(value) ? value.filter((v) => typeof v === "string") : [];
|
|
42
43
|
return {
|
|
43
44
|
ok: res.ok && !keyConflict && (params.dataEncryptionKey === void 0 || keyRegistered),
|
|
44
45
|
keyRegistered,
|
|
45
46
|
keyConflict,
|
|
47
|
+
keyUnavailable,
|
|
46
48
|
settledIds: Array.isArray(body?.settledIds) ? ids(body.settledIds) : null,
|
|
47
49
|
rejectedIds: ids(body?.rejectedIds)
|
|
48
50
|
};
|
|
49
51
|
} catch {
|
|
50
|
-
return { ok: false, keyRegistered: false, keyConflict: false, settledIds: null, rejectedIds: [] };
|
|
52
|
+
return { ok: false, keyRegistered: false, keyConflict: false, keyUnavailable: false, settledIds: null, rejectedIds: [] };
|
|
51
53
|
}
|
|
52
54
|
};
|
|
53
55
|
|
|
@@ -57,6 +57,7 @@ var parseMcpResponse = (body, contentType) => {
|
|
|
57
57
|
};
|
|
58
58
|
var sendMcpRequest = async (apiKey, message, options = {}) => {
|
|
59
59
|
return withRetry(async () => {
|
|
60
|
+
options.signal?.throwIfAborted();
|
|
60
61
|
const baseUrl = options.baseUrl ?? getBaseUrl();
|
|
61
62
|
const fetchFn = options.fetchFn ?? fetch;
|
|
62
63
|
const headers = {
|
|
@@ -71,7 +72,7 @@ var sendMcpRequest = async (apiKey, message, options = {}) => {
|
|
|
71
72
|
method: "POST",
|
|
72
73
|
headers,
|
|
73
74
|
body: JSON.stringify(message),
|
|
74
|
-
signal: options.timeoutMs ? AbortSignal.timeout(options.timeoutMs) :
|
|
75
|
+
signal: options.timeoutMs ? AbortSignal.any([AbortSignal.timeout(options.timeoutMs), ...options.signal ? [options.signal] : []]) : options.signal
|
|
75
76
|
});
|
|
76
77
|
const body = await response.text();
|
|
77
78
|
const contentType = response.headers.get("content-type");
|
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
import {
|
|
2
2
|
isBridgeLocator
|
|
3
|
-
} from "./chunk-
|
|
3
|
+
} from "./chunk-YANV5TGK.js";
|
|
4
4
|
import {
|
|
5
5
|
pusharyHookExecutable
|
|
6
|
-
} from "./chunk-
|
|
6
|
+
} from "./chunk-HSAVPZ46.js";
|
|
7
7
|
import {
|
|
8
8
|
BELL_HOOK_BINARY
|
|
9
9
|
} from "./chunk-DSTLA2TC.js";
|
|
@@ -18,7 +18,7 @@ import {
|
|
|
18
18
|
} from "./chunk-7QLSKOSU.js";
|
|
19
19
|
import {
|
|
20
20
|
isValidApiKey
|
|
21
|
-
} from "./chunk-
|
|
21
|
+
} from "./chunk-Z6CP5ZZD.js";
|
|
22
22
|
|
|
23
23
|
// src/hermes-config.ts
|
|
24
24
|
import { execFileSync } from "child_process";
|
|
@@ -2,15 +2,15 @@ import {
|
|
|
2
2
|
CLAUDE_HOOK_EVENTS,
|
|
3
3
|
GEMINI_HOOK_EVENTS,
|
|
4
4
|
hasGeminiHooks
|
|
5
|
-
} from "./chunk-
|
|
5
|
+
} from "./chunk-RX75MRGC.js";
|
|
6
6
|
import {
|
|
7
7
|
CODEX_HOOK_EVENTS,
|
|
8
8
|
hasCodexHooks
|
|
9
|
-
} from "./chunk-
|
|
9
|
+
} from "./chunk-Y6XXFXVB.js";
|
|
10
10
|
import {
|
|
11
11
|
CURSOR_GATE_EVENTS,
|
|
12
12
|
HOOK_LOCATOR_BINARY
|
|
13
|
-
} from "./chunk-
|
|
13
|
+
} from "./chunk-Z6CP5ZZD.js";
|
|
14
14
|
|
|
15
15
|
// src/diagnostics/wiring.ts
|
|
16
16
|
var record = (value) => value && typeof value === "object" && !Array.isArray(value) ? value : null;
|
|
@@ -3,11 +3,11 @@ import {
|
|
|
3
3
|
decodePublicKey,
|
|
4
4
|
generateSessionKey,
|
|
5
5
|
wrapSessionKey
|
|
6
|
-
} from "./chunk-
|
|
6
|
+
} from "./chunk-46P3VES5.js";
|
|
7
7
|
import {
|
|
8
8
|
fetchTranscriptRecipients,
|
|
9
9
|
uploadTranscriptRecords
|
|
10
|
-
} from "./chunk-
|
|
10
|
+
} from "./chunk-EQRS3SGM.js";
|
|
11
11
|
|
|
12
12
|
// src/live-session.ts
|
|
13
13
|
var MAX_TRANSCRIPT_QUEUE = 100;
|
|
@@ -1,27 +1,25 @@
|
|
|
1
|
-
import {
|
|
2
|
-
PRETOOLUSE_HANDLED_TOOLS,
|
|
3
|
-
PRETOOLUSE_PHONE_ANSWERED_TOOLS
|
|
4
|
-
} from "./chunk-2LAHXHBR.js";
|
|
5
1
|
import {
|
|
6
2
|
defersToNativeMode
|
|
7
|
-
} from "./chunk-
|
|
3
|
+
} from "./chunk-OYNPLEXP.js";
|
|
8
4
|
import {
|
|
9
5
|
isGatingMoment,
|
|
10
6
|
recordKeylessMoment
|
|
11
|
-
} from "./chunk-
|
|
7
|
+
} from "./chunk-2ORRI66J.js";
|
|
12
8
|
import {
|
|
13
9
|
denyReasonFrom,
|
|
14
10
|
isDeferAnswer
|
|
15
11
|
} from "./chunk-YHG74UFF.js";
|
|
16
12
|
import {
|
|
13
|
+
CLAUDE_CODE_AGENT,
|
|
17
14
|
fetchModeState,
|
|
18
15
|
getPolicy,
|
|
19
16
|
readLastPrompt,
|
|
20
17
|
readLastUserPrompt,
|
|
21
18
|
repoKeyFor,
|
|
19
|
+
reportEvent,
|
|
22
20
|
settleQuestionsForToolUse,
|
|
23
21
|
throttlePass
|
|
24
|
-
} from "./chunk-
|
|
22
|
+
} from "./chunk-5HGLZGI4.js";
|
|
25
23
|
import {
|
|
26
24
|
DEFAULT_SESSION,
|
|
27
25
|
askUser,
|
|
@@ -29,7 +27,7 @@ import {
|
|
|
29
27
|
pollForAnswer,
|
|
30
28
|
savePendingQuestion,
|
|
31
29
|
sendNotification
|
|
32
|
-
} from "./chunk-
|
|
30
|
+
} from "./chunk-RER3FRTD.js";
|
|
33
31
|
import {
|
|
34
32
|
UNNAMED_ACTION,
|
|
35
33
|
deriveAction,
|
|
@@ -37,11 +35,16 @@ import {
|
|
|
37
35
|
deriveBlocker,
|
|
38
36
|
deriveToolTarget,
|
|
39
37
|
describeToolCall,
|
|
38
|
+
permissionDeniedAction,
|
|
40
39
|
scopePathFor
|
|
41
|
-
} from "./chunk-
|
|
40
|
+
} from "./chunk-4PE2SQVM.js";
|
|
41
|
+
import {
|
|
42
|
+
PRETOOLUSE_HANDLED_TOOLS,
|
|
43
|
+
PRETOOLUSE_PHONE_ANSWERED_TOOLS
|
|
44
|
+
} from "./chunk-Y3UGCQQC.js";
|
|
42
45
|
import {
|
|
43
46
|
getMachineId
|
|
44
|
-
} from "./chunk-
|
|
47
|
+
} from "./chunk-NVPYRDCT.js";
|
|
45
48
|
import {
|
|
46
49
|
getApiKey,
|
|
47
50
|
getBaseUrl
|
|
@@ -58,7 +61,7 @@ import {
|
|
|
58
61
|
parseAgentQuestions,
|
|
59
62
|
resolveGate,
|
|
60
63
|
stoppedOutput
|
|
61
|
-
} from "./chunk-
|
|
64
|
+
} from "./chunk-Z6CP5ZZD.js";
|
|
62
65
|
|
|
63
66
|
// src/decision-episode.ts
|
|
64
67
|
var EPISODE_PATH = "/api/agent/decision-episode";
|
|
@@ -582,7 +585,19 @@ var automodeRetryEnabled = () => {
|
|
|
582
585
|
const flag = process.env.PUSHARY_AUTOMODE_RETRY;
|
|
583
586
|
return flag === "1" || flag === "true";
|
|
584
587
|
};
|
|
588
|
+
var reportPermissionDenied = (input) => reportEvent({
|
|
589
|
+
event: "permission_denied",
|
|
590
|
+
agentType: CLAUDE_CODE_AGENT.type,
|
|
591
|
+
agentName: `${CLAUDE_CODE_AGENT.label} - ${basename(input.cwd ?? process.cwd())}`,
|
|
592
|
+
action: permissionDeniedAction(input.tool_name),
|
|
593
|
+
sessionId: input.session_id
|
|
594
|
+
// Side report, not a command carrier. Without timeoutMs this takes the phone's
|
|
595
|
+
// queued instruction and acknowledges it delivered, and this hook can print
|
|
596
|
+
// only {retry}. 4s rather than the Notification path's 2.5s because
|
|
597
|
+
// PermissionDenied is given a 60s budget, not 10s.
|
|
598
|
+
}, { timeoutMs: 4e3 }).catch(() => void 0);
|
|
585
599
|
var handlePermissionDenied = async (input) => {
|
|
600
|
+
await reportPermissionDenied(input);
|
|
586
601
|
if (isPusharyOwnTool(input.tool_name)) return void 0;
|
|
587
602
|
let apiKey;
|
|
588
603
|
try {
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import {
|
|
2
2
|
callMcpTool
|
|
3
|
-
} from "./chunk-
|
|
3
|
+
} from "./chunk-EYRGBYZG.js";
|
|
4
4
|
import {
|
|
5
5
|
installProxyDispatcher
|
|
6
6
|
} from "./chunk-SAF6HGAA.js";
|
|
@@ -33,11 +33,11 @@ var askUser = async (apiKey, params, timeoutMs = 15e3) => {
|
|
|
33
33
|
if (!isAskUserResponse(result)) throw new Error("Invalid ask_user response");
|
|
34
34
|
return result;
|
|
35
35
|
};
|
|
36
|
-
var waitForAnswer = async (apiKey, correlationId, timeoutMs = 3e4) => {
|
|
36
|
+
var waitForAnswer = async (apiKey, correlationId, timeoutMs = 3e4, signal) => {
|
|
37
37
|
const result = await callMcpTool(apiKey, "wait_for_answer", {
|
|
38
38
|
correlationId,
|
|
39
39
|
timeoutMs
|
|
40
|
-
}, { timeoutMs: timeoutMs + 1e4 });
|
|
40
|
+
}, { timeoutMs: timeoutMs + 1e4, signal });
|
|
41
41
|
if (!isWaitForAnswerResponse(result)) throw new Error("Invalid wait_for_answer response");
|
|
42
42
|
return result;
|
|
43
43
|
};
|
|
@@ -59,11 +59,11 @@ var pollForAnswer = async (apiKey, correlationId, deadlineMs, pollInterval = 2e3
|
|
|
59
59
|
}
|
|
60
60
|
return { answered: false };
|
|
61
61
|
};
|
|
62
|
-
var cancelQuestion = async (apiKey, correlationId) => {
|
|
63
|
-
await callMcpTool(apiKey, "cancel_question", { correlationId });
|
|
62
|
+
var cancelQuestion = async (apiKey, correlationId, signal) => {
|
|
63
|
+
await callMcpTool(apiKey, "cancel_question", { correlationId }, { signal });
|
|
64
64
|
};
|
|
65
|
-
var sendNotification = async (apiKey, params, timeoutMs = 15e3) => {
|
|
66
|
-
await callMcpTool(apiKey, "send_notification", { ...params }, { maxRetries: 3, timeoutMs });
|
|
65
|
+
var sendNotification = async (apiKey, params, timeoutMs = 15e3, signal) => {
|
|
66
|
+
await callMcpTool(apiKey, "send_notification", { ...params }, { maxRetries: signal ? 1 : 3, timeoutMs, signal });
|
|
67
67
|
};
|
|
68
68
|
|
|
69
69
|
// src/pending.ts
|
|
@@ -12,10 +12,10 @@ import {
|
|
|
12
12
|
} from "./chunk-5RUIFDTP.js";
|
|
13
13
|
import {
|
|
14
14
|
callMcpTool
|
|
15
|
-
} from "./chunk-
|
|
15
|
+
} from "./chunk-EYRGBYZG.js";
|
|
16
16
|
import {
|
|
17
17
|
reportedInstallSource
|
|
18
|
-
} from "./chunk-
|
|
18
|
+
} from "./chunk-ODL52O5V.js";
|
|
19
19
|
|
|
20
20
|
// src/reach.ts
|
|
21
21
|
var reachVerdict = (channels) => {
|
|
@@ -1,17 +1,19 @@
|
|
|
1
|
-
import {
|
|
2
|
-
PRETOOLUSE_GATED_TOOLS,
|
|
3
|
-
PRETOOLUSE_PHONE_ANSWERED_TOOLS
|
|
4
|
-
} from "./chunk-2LAHXHBR.js";
|
|
5
1
|
import {
|
|
6
2
|
guardBinary
|
|
7
3
|
} from "./chunk-EZIEXHYM.js";
|
|
4
|
+
import {
|
|
5
|
+
NOTIFICATION_MATCHED_TYPES,
|
|
6
|
+
POSTTOOLUSE_MIRRORED_TOOLS,
|
|
7
|
+
PRETOOLUSE_GATED_TOOLS,
|
|
8
|
+
PRETOOLUSE_PHONE_ANSWERED_TOOLS
|
|
9
|
+
} from "./chunk-Y3UGCQQC.js";
|
|
8
10
|
import {
|
|
9
11
|
isProtectedByScope
|
|
10
|
-
} from "./chunk-
|
|
12
|
+
} from "./chunk-Y6XXFXVB.js";
|
|
11
13
|
import {
|
|
12
14
|
HOOK_BUDGETS,
|
|
13
15
|
HOOK_LOCATOR_BINARY
|
|
14
|
-
} from "./chunk-
|
|
16
|
+
} from "./chunk-Z6CP5ZZD.js";
|
|
15
17
|
|
|
16
18
|
// src/claude-config.ts
|
|
17
19
|
import { join } from "path";
|
|
@@ -32,7 +34,7 @@ var formatVersion = (version) => version.join(".");
|
|
|
32
34
|
|
|
33
35
|
// src/claude-events.ts
|
|
34
36
|
var GATED_TOOLS = [...PRETOOLUSE_GATED_TOOLS, ...PRETOOLUSE_PHONE_ANSWERED_TOOLS].join("|");
|
|
35
|
-
var MIRRORED_TOOLS =
|
|
37
|
+
var MIRRORED_TOOLS = POSTTOOLUSE_MIRRORED_TOOLS.join("|");
|
|
36
38
|
var ESTABLISHED = [1, 0, 0];
|
|
37
39
|
var OBSERVED = [2, 0, 0];
|
|
38
40
|
var CLAUDE_HOOK_EVENTS = [
|
|
@@ -40,7 +42,7 @@ var CLAUDE_HOOK_EVENTS = [
|
|
|
40
42
|
{ event: "PostToolUse", binary: "pushary-post-hook", matcher: MIRRORED_TOOLS, timeout: 10, delivery: "telemetry", since: ESTABLISHED },
|
|
41
43
|
{ event: "Stop", binary: "pushary-stop-hook", timeout: 10, delivery: "telemetry", since: ESTABLISHED },
|
|
42
44
|
{ event: "UserPromptSubmit", binary: "pushary-prompt-hook", timeout: 10, delivery: "telemetry", since: ESTABLISHED },
|
|
43
|
-
{ event: "Notification", binary: "pushary-notification-hook", matcher: "
|
|
45
|
+
{ event: "Notification", binary: "pushary-notification-hook", matcher: NOTIFICATION_MATCHED_TYPES.join("|"), timeout: 10, delivery: "telemetry", since: ESTABLISHED },
|
|
44
46
|
{ event: "SessionStart", binary: "pushary-session-start-hook", matcher: "startup|resume|clear", timeout: 10, delivery: "telemetry", since: ESTABLISHED },
|
|
45
47
|
{ event: "SessionEnd", binary: "pushary-session-end-hook", timeout: 10, delivery: "telemetry", since: ESTABLISHED },
|
|
46
48
|
{ event: "StopFailure", binary: "pushary-stopfailure-hook", timeout: 10, delivery: "telemetry", since: ESTABLISHED },
|
|
@@ -11,8 +11,9 @@ import {
|
|
|
11
11
|
getBaseUrl
|
|
12
12
|
} from "./chunk-2UMNXADU.js";
|
|
13
13
|
import {
|
|
14
|
-
isValidApiKey
|
|
15
|
-
|
|
14
|
+
isValidApiKey,
|
|
15
|
+
normalizeKeyScope
|
|
16
|
+
} from "./chunk-Z6CP5ZZD.js";
|
|
16
17
|
|
|
17
18
|
// src/session.ts
|
|
18
19
|
var samePusharyAccount = (left, right) => left.kind === "ok" && right.kind === "ok" && left.identity.workspaceId !== "" && left.identity.workspaceId === right.identity.workspaceId && left.identity.siteId === right.identity.siteId;
|
|
@@ -20,7 +21,6 @@ var IDENTITY_PATH = "/api/v1/server/identity";
|
|
|
20
21
|
var DEFAULT_TIMEOUT_MS = 1e4;
|
|
21
22
|
var SUBSCRIPTION_REQUIRED_CODE = "subscription_required";
|
|
22
23
|
var DEFAULT_UPGRADE_PATH = "/dashboard/settings?tab=billing";
|
|
23
|
-
var KEY_SCOPES = ["full_access", "connector", "bound"];
|
|
24
24
|
var SUBSCRIPTION_STATUSES = [
|
|
25
25
|
"active",
|
|
26
26
|
"past_due",
|
|
@@ -31,7 +31,6 @@ var SUBSCRIPTION_STATUSES = [
|
|
|
31
31
|
"none"
|
|
32
32
|
];
|
|
33
33
|
var asString = (value) => typeof value === "string" && value ? value : null;
|
|
34
|
-
var asScope = (value) => KEY_SCOPES.includes(value) ? value : "full_access";
|
|
35
34
|
var asStatus = (value) => SUBSCRIPTION_STATUSES.includes(value) ? value : "none";
|
|
36
35
|
var asCount = (value) => typeof value === "number" && Number.isFinite(value) ? Math.max(0, Math.trunc(value)) : 0;
|
|
37
36
|
var absoluteUrl = (baseUrl, pathOrUrl) => {
|
|
@@ -43,12 +42,13 @@ var toIdentity = (body) => {
|
|
|
43
42
|
const raw = body;
|
|
44
43
|
const keyId = asString(raw.keyId);
|
|
45
44
|
const siteId = asString(raw.siteId);
|
|
46
|
-
|
|
45
|
+
const keyScope = normalizeKeyScope(raw.keyScope);
|
|
46
|
+
if (!keyId || !siteId || !keyScope) return null;
|
|
47
47
|
return {
|
|
48
48
|
keyId,
|
|
49
49
|
keyPrefix: asString(raw.keyPrefix) ?? "",
|
|
50
50
|
keyName: asString(raw.keyName) ?? "",
|
|
51
|
-
keyScope
|
|
51
|
+
keyScope,
|
|
52
52
|
siteId,
|
|
53
53
|
siteSlug: asString(raw.siteSlug) ?? "",
|
|
54
54
|
siteName: asString(raw.siteName) ?? "",
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
import {
|
|
2
|
+
ASKED_IN_EVERY_MODE_TOOLS
|
|
3
|
+
} from "./chunk-Z6CP5ZZD.js";
|
|
4
|
+
|
|
5
|
+
// src/claude-tools.ts
|
|
6
|
+
var PRETOOLUSE_GATED_TOOLS = [
|
|
7
|
+
"Bash",
|
|
8
|
+
"Write",
|
|
9
|
+
"Edit",
|
|
10
|
+
"MultiEdit",
|
|
11
|
+
"NotebookEdit",
|
|
12
|
+
"PowerShell",
|
|
13
|
+
"Monitor"
|
|
14
|
+
];
|
|
15
|
+
var PRETOOLUSE_PHONE_ANSWERED_TOOLS = ASKED_IN_EVERY_MODE_TOOLS;
|
|
16
|
+
var POSTTOOLUSE_MIRROR_ONLY_TOOLS = ["TodoWrite", "Task", "WebFetch", "WebSearch"];
|
|
17
|
+
var POSTTOOLUSE_MIRRORED_TOOLS = [...PRETOOLUSE_GATED_TOOLS, ...POSTTOOLUSE_MIRROR_ONLY_TOOLS];
|
|
18
|
+
var PRETOOLUSE_HANDLED_TOOLS = /* @__PURE__ */ new Set([...PRETOOLUSE_GATED_TOOLS, ...PRETOOLUSE_PHONE_ANSWERED_TOOLS]);
|
|
19
|
+
|
|
20
|
+
// src/claude-notifications.ts
|
|
21
|
+
var NOTIFICATION_MATCHED_TYPES = [
|
|
22
|
+
// Blocks. The agent, or one of its workers, is waiting on a person.
|
|
23
|
+
"permission_prompt",
|
|
24
|
+
"idle_prompt",
|
|
25
|
+
"agent_needs_input",
|
|
26
|
+
"worker_permission_prompt",
|
|
27
|
+
// An MCP server asking the person for a value. The Elicitation hook answers it;
|
|
28
|
+
// this is the feed row saying one is open.
|
|
29
|
+
"elicitation_dialog",
|
|
30
|
+
"elicitation_url_dialog",
|
|
31
|
+
// Turn boundary.
|
|
32
|
+
"agent_completed",
|
|
33
|
+
// Quota. The island already reads plan usage, and these say when a limit hit,
|
|
34
|
+
// went stale, or was turned off, which no polling of the usage endpoint reveals.
|
|
35
|
+
"quota_auto_resume_fired",
|
|
36
|
+
"quota_auto_resume_stale",
|
|
37
|
+
"quota_auto_resume_disabled"
|
|
38
|
+
];
|
|
39
|
+
var NOTIFICATION_PUSH_TYPES = /* @__PURE__ */ new Set([
|
|
40
|
+
"idle_prompt",
|
|
41
|
+
"agent_needs_input",
|
|
42
|
+
"worker_permission_prompt"
|
|
43
|
+
]);
|
|
44
|
+
|
|
45
|
+
export {
|
|
46
|
+
PRETOOLUSE_GATED_TOOLS,
|
|
47
|
+
PRETOOLUSE_PHONE_ANSWERED_TOOLS,
|
|
48
|
+
POSTTOOLUSE_MIRROR_ONLY_TOOLS,
|
|
49
|
+
POSTTOOLUSE_MIRRORED_TOOLS,
|
|
50
|
+
PRETOOLUSE_HANDLED_TOOLS,
|
|
51
|
+
NOTIFICATION_MATCHED_TYPES,
|
|
52
|
+
NOTIFICATION_PUSH_TYPES
|
|
53
|
+
};
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import {
|
|
2
2
|
HOOK_BUDGETS,
|
|
3
3
|
HOOK_LOCATOR_BINARY
|
|
4
|
-
} from "./chunk-
|
|
4
|
+
} from "./chunk-Z6CP5ZZD.js";
|
|
5
5
|
|
|
6
6
|
// src/removal-scope.ts
|
|
7
7
|
var namesAppLocator = (command) => command.includes(HOOK_LOCATOR_BINARY);
|
|
@@ -34,11 +34,23 @@ var CODEX_HOOK_EVENTS = [
|
|
|
34
34
|
{ event: "PostToolUse", matcher: "Bash|apply_patch", delivery: "telemetry", timeout: 10 },
|
|
35
35
|
{ event: "UserPromptSubmit", delivery: "telemetry", timeout: 10 },
|
|
36
36
|
{ event: "Stop", delivery: "telemetry", timeout: 10 },
|
|
37
|
-
|
|
37
|
+
// `clear` alongside startup and resume, matching what we already do on Claude
|
|
38
|
+
// Code. Codex names all three in its own SessionStart sources, and without it a
|
|
39
|
+
// session the person started by clearing is one we never see begin.
|
|
40
|
+
{ event: "SessionStart", matcher: "startup|resume|clear", delivery: "telemetry", timeout: 10 },
|
|
38
41
|
// Codex caps SessionEnd at 3s and defaults it to 1s, unlike every other event
|
|
39
42
|
// here. It also runs synchronously whatever `async` says, so the handler must
|
|
40
43
|
// fit the window rather than assume the 10s Claude Code allows.
|
|
41
|
-
{ event: "SessionEnd", delivery: "telemetry", timeout: 3 }
|
|
44
|
+
{ event: "SessionEnd", delivery: "telemetry", timeout: 3 },
|
|
45
|
+
// Observability only, and the four Codex names we were not registering at all.
|
|
46
|
+
// Every one is in codex-cli 0.151.0's own `HookEventName` enum
|
|
47
|
+
// (subagent_start, subagent_stop, pre_compact, post_compact), and we already
|
|
48
|
+
// carry all four on Claude Code, so the island showed subagent and compaction
|
|
49
|
+
// shape for one agent and not the other. None of them decides anything.
|
|
50
|
+
{ event: "SubagentStart", delivery: "telemetry", timeout: 5 },
|
|
51
|
+
{ event: "SubagentStop", delivery: "telemetry", timeout: 5 },
|
|
52
|
+
{ event: "PreCompact", matcher: "manual|auto", delivery: "telemetry", timeout: 5 },
|
|
53
|
+
{ event: "PostCompact", matcher: "manual|auto", delivery: "telemetry", timeout: 5 }
|
|
42
54
|
];
|
|
43
55
|
var CODEX_EVENT_KEY = {
|
|
44
56
|
PermissionRequest: "permission_request",
|
|
@@ -47,7 +59,11 @@ var CODEX_EVENT_KEY = {
|
|
|
47
59
|
UserPromptSubmit: "user_prompt_submit",
|
|
48
60
|
Stop: "stop",
|
|
49
61
|
SessionStart: "session_start",
|
|
50
|
-
SessionEnd: "session_end"
|
|
62
|
+
SessionEnd: "session_end",
|
|
63
|
+
SubagentStart: "subagent_start",
|
|
64
|
+
SubagentStop: "subagent_stop",
|
|
65
|
+
PreCompact: "pre_compact",
|
|
66
|
+
PostCompact: "post_compact"
|
|
51
67
|
};
|
|
52
68
|
var codexEventKeyOf = (event) => event.replace(/([a-z0-9])([A-Z])/g, "$1_$2").toLowerCase();
|
|
53
69
|
var asRecord = (value) => value && typeof value === "object" && !Array.isArray(value) ? value : void 0;
|
|
@@ -209,14 +225,30 @@ var restoreCodexHookTrust = (config, hooksJsonPath, positions, snapshot) => {
|
|
|
209
225
|
}
|
|
210
226
|
return true;
|
|
211
227
|
};
|
|
212
|
-
var
|
|
228
|
+
var codexTrustGaps = (config, hooksConfig, hooksJsonPath, command, positions) => {
|
|
213
229
|
const state = asRecord(asRecord(config.hooks)?.state);
|
|
214
|
-
|
|
230
|
+
const hooks = asRecord(hooksConfig?.hooks);
|
|
231
|
+
const gaps = [];
|
|
232
|
+
for (const definition of CODEX_HOOK_EVENTS) {
|
|
215
233
|
const position = positions[definition.event];
|
|
216
|
-
if (!position)
|
|
217
|
-
const
|
|
218
|
-
|
|
219
|
-
|
|
234
|
+
if (!position) continue;
|
|
235
|
+
const stored = asRecord(state?.[codexHookStateKey(hooksJsonPath, definition.event, position)])?.trusted_hash;
|
|
236
|
+
const eventKey = CODEX_EVENT_KEY[definition.event] ?? definition.event;
|
|
237
|
+
const onDisk = asRecord(
|
|
238
|
+
asRecord(hooks?.[definition.event]) ?? (Array.isArray(hooks?.[definition.event]) ? hooks[definition.event][position[0]] : void 0)
|
|
239
|
+
);
|
|
240
|
+
const diskHash = onDisk ? codexEntryTrustHash(eventKey, onDisk) : void 0;
|
|
241
|
+
if (stored !== void 0 && diskHash !== void 0 && stored === diskHash) {
|
|
242
|
+
if (diskHash !== codexHookTrustHash(definition, command)) {
|
|
243
|
+
gaps.push({ event: definition.event, kind: "stale" });
|
|
244
|
+
}
|
|
245
|
+
continue;
|
|
246
|
+
}
|
|
247
|
+
if (stored !== (diskHash ?? codexHookTrustHash(definition, command))) {
|
|
248
|
+
gaps.push({ event: definition.event, kind: "untrusted" });
|
|
249
|
+
}
|
|
250
|
+
}
|
|
251
|
+
return gaps;
|
|
220
252
|
};
|
|
221
253
|
var removeCodexMcpServer = (config) => {
|
|
222
254
|
const servers = asRecord(config.mcp_servers);
|
|
@@ -318,7 +350,7 @@ export {
|
|
|
318
350
|
codexHookPositions,
|
|
319
351
|
captureCodexHookTrust,
|
|
320
352
|
restoreCodexHookTrust,
|
|
321
|
-
|
|
353
|
+
codexTrustGaps,
|
|
322
354
|
removeCodexHookTrust,
|
|
323
355
|
removeCodexSettings,
|
|
324
356
|
addCodexHookTrust,
|
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
import {
|
|
2
2
|
openCodeConfigDirFrom
|
|
3
|
-
} from "./chunk-
|
|
3
|
+
} from "./chunk-BSEAOCCQ.js";
|
|
4
4
|
import {
|
|
5
5
|
codexHomeFrom
|
|
6
|
-
} from "./chunk-
|
|
6
|
+
} from "./chunk-Y6XXFXVB.js";
|
|
7
7
|
import {
|
|
8
8
|
HOOK_LOCATOR_BINARY
|
|
9
|
-
} from "./chunk-
|
|
9
|
+
} from "./chunk-Z6CP5ZZD.js";
|
|
10
10
|
|
|
11
11
|
// src/vscode-config.ts
|
|
12
12
|
import { homedir } from "os";
|
|
@@ -1,4 +1,6 @@
|
|
|
1
1
|
// ../contracts/src/index.ts
|
|
2
|
+
var KEY_SCOPES = ["full_access", "agent", "connector", "bound"];
|
|
3
|
+
var normalizeKeyScope = (value) => typeof value === "string" && KEY_SCOPES.includes(value) ? value : null;
|
|
2
4
|
var APPROVAL_MODES = ["push_only", "terminal_only", "push_first", "notify_only"];
|
|
3
5
|
var isApprovalMode = (value) => typeof value === "string" && APPROVAL_MODES.includes(value);
|
|
4
6
|
var MAX_AGENT_QUESTIONS = 4;
|
|
@@ -1347,6 +1349,7 @@ var elicitationContentFromAnswers = (ask, answers) => {
|
|
|
1347
1349
|
};
|
|
1348
1350
|
|
|
1349
1351
|
export {
|
|
1352
|
+
normalizeKeyScope,
|
|
1350
1353
|
parseAgentQuestions,
|
|
1351
1354
|
parseAgentQuestionAnswers,
|
|
1352
1355
|
normalizeInstallSource,
|
|
@@ -7,10 +7,10 @@ import {
|
|
|
7
7
|
} from "./chunk-L4ZCFMWW.js";
|
|
8
8
|
import {
|
|
9
9
|
getMachineId
|
|
10
|
-
} from "./chunk-
|
|
10
|
+
} from "./chunk-NVPYRDCT.js";
|
|
11
11
|
import {
|
|
12
12
|
pusharyDir
|
|
13
|
-
} from "./chunk-
|
|
13
|
+
} from "./chunk-Y6XXFXVB.js";
|
|
14
14
|
import {
|
|
15
15
|
getPackageVersion
|
|
16
16
|
} from "./chunk-DINDL2CF.js";
|
package/dist/src/index.d.ts
CHANGED
|
@@ -16,10 +16,12 @@ declare const handlePreToolUse: (input: ToolInput) => Promise<HookOutput | undef
|
|
|
16
16
|
|
|
17
17
|
declare const getPolicy: (apiKey: string, expectedVersion?: string | null, agent?: string, repoAware?: boolean, sessionId?: string) => Promise<PolicyConfig>;
|
|
18
18
|
|
|
19
|
-
declare const fetchModeState: (apiKey: string, sessionId?: string, reuseWithinMs?: number) => Promise<ModeState>;
|
|
19
|
+
declare const fetchModeState: (apiKey: string, sessionId?: string, reuseWithinMs?: number, signal?: AbortSignal) => Promise<ModeState>;
|
|
20
20
|
declare const fetchModeOverride: (apiKey: string) => Promise<ApprovalMode | null>;
|
|
21
21
|
|
|
22
22
|
interface UsageReport {
|
|
23
|
+
readonly eventId: string;
|
|
24
|
+
readonly reportedAt: number;
|
|
23
25
|
readonly tokensIn: number;
|
|
24
26
|
readonly tokensOut: number;
|
|
25
27
|
readonly costUsd: number;
|
|
@@ -52,8 +54,35 @@ interface AgentEvent {
|
|
|
52
54
|
pid?: number;
|
|
53
55
|
}
|
|
54
56
|
interface ReportEventOptions {
|
|
57
|
+
signal?: AbortSignal;
|
|
55
58
|
maxAttempts?: number;
|
|
56
59
|
timeoutMs?: number;
|
|
60
|
+
/**
|
|
61
|
+
* Total wall clock this call may spend, acknowledge round trip included.
|
|
62
|
+
*
|
|
63
|
+
* Deliberately not `timeoutMs`. That option doubles as the "I am a side report"
|
|
64
|
+
* signal (`clientCanDrain` below is keyed on its absence), so a drain-carrying
|
|
65
|
+
* caller that set it to bound its time would silently stop delivering the
|
|
66
|
+
* instructions a person sent from their phone. This bounds the clock and says
|
|
67
|
+
* nothing about draining.
|
|
68
|
+
*
|
|
69
|
+
* Without it, a single report could spend `timeoutMs ?? 10_000` on the event
|
|
70
|
+
* POST and then a further `timeoutMs ?? 10_000` acknowledging a pending command,
|
|
71
|
+
* which is twice the ceiling the hook was given and, on Codex, twice what the
|
|
72
|
+
* agent will wait before killing the process mid-flight.
|
|
73
|
+
*/
|
|
74
|
+
budgetMs?: number;
|
|
75
|
+
/**
|
|
76
|
+
* Tells the server not to pop a queued instruction for this report.
|
|
77
|
+
*
|
|
78
|
+
* `canDrainCommand: false` is not enough. The route's first disjunct is
|
|
79
|
+
* `event === "session_end" && consumesDrainedCommand(agentType)`, which never
|
|
80
|
+
* reads that flag, so any `session_end` from an agent whose Stop carries text
|
|
81
|
+
* back pops the queue destructively. A subagent's stop is a `session_end` and
|
|
82
|
+
* its caller throws the response away, which is a queued instruction destroyed
|
|
83
|
+
* rather than delivered. `skipCommandDrain` is the route's own first check.
|
|
84
|
+
*/
|
|
85
|
+
skipDrain?: boolean;
|
|
57
86
|
requireOk?: boolean;
|
|
58
87
|
/**
|
|
59
88
|
* Authenticate with this key instead of the ambient one.
|
|
@@ -102,6 +131,7 @@ declare const handleNotification: (input: {
|
|
|
102
131
|
title?: string;
|
|
103
132
|
type?: string;
|
|
104
133
|
notification_type?: string;
|
|
134
|
+
hook_event_name?: string;
|
|
105
135
|
cwd?: string;
|
|
106
136
|
session_id?: string;
|
|
107
137
|
}, agent?: AgentIdentity) => Promise<void>;
|
|
@@ -148,8 +178,8 @@ interface AnswerResult {
|
|
|
148
178
|
note?: string;
|
|
149
179
|
}
|
|
150
180
|
declare const askUser: (apiKey: string, params: AskUserParams, timeoutMs?: number) => Promise<AskUserResponse>;
|
|
151
|
-
declare const waitForAnswer: (apiKey: string, correlationId: string, timeoutMs?: number) => Promise<AnswerResult>;
|
|
152
|
-
declare const cancelQuestion: (apiKey: string, correlationId: string) => Promise<void>;
|
|
181
|
+
declare const waitForAnswer: (apiKey: string, correlationId: string, timeoutMs?: number, signal?: AbortSignal) => Promise<AnswerResult>;
|
|
182
|
+
declare const cancelQuestion: (apiKey: string, correlationId: string, signal?: AbortSignal) => Promise<void>;
|
|
153
183
|
|
|
154
184
|
declare const getApiKey: () => string;
|
|
155
185
|
declare const getBaseUrl: () => string;
|