@pushary/agent-hooks 0.95.5 → 0.95.7
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 +14 -0
- package/data/cursor-plugin/.cursor-plugin/plugin.json +1 -1
- package/data/cursor-plugin/CHANGELOG.md +7 -0
- package/data/cursor-plugin/scripts/pushary-gate.mjs +72 -17
- package/data/vscode-plugin/.claude-plugin/plugin.json +1 -1
- package/data/vscode-plugin/CHANGELOG.md +6 -0
- package/data/vscode-plugin/scripts/pushary-gate.mjs +76 -24
- package/dist/bin/pushary-bell-hook.js +18 -18
- package/dist/bin/pushary-bell.js +7 -7
- package/dist/bin/pushary-claude.js +24 -24
- package/dist/bin/pushary-clean.js +18 -18
- package/dist/bin/pushary-codex-bridge.js +29 -12
- package/dist/bin/pushary-codex-hook.js +29 -29
- package/dist/bin/pushary-codex.js +7 -7
- package/dist/bin/pushary-connect.js +8 -8
- package/dist/bin/pushary-cowork.js +5 -5
- package/dist/bin/pushary-daemon.js +24 -24
- package/dist/bin/pushary-disconnect.js +8 -8
- package/dist/bin/pushary-doctor.js +91 -36
- package/dist/bin/pushary-elicitation-hook.js +17 -17
- package/dist/bin/pushary-gemini-bridge.js +9 -9
- package/dist/bin/pushary-gemini-hook.js +65 -50
- package/dist/bin/pushary-hook.js +24 -24
- package/dist/bin/pushary-login.js +9 -9
- package/dist/bin/pushary-logout.js +6 -6
- package/dist/bin/pushary-mode.js +5 -5
- package/dist/bin/pushary-notification-hook.js +19 -19
- package/dist/bin/pushary-opencode-hook.js +29 -29
- package/dist/bin/pushary-permission-denied-hook.js +22 -22
- package/dist/bin/pushary-permission-hook.js +22 -22
- package/dist/bin/pushary-post-hook.js +19 -19
- package/dist/bin/pushary-prompt-hook.js +19 -19
- package/dist/bin/pushary-session-end-hook.js +19 -19
- package/dist/bin/pushary-session-start-hook.js +22 -22
- package/dist/bin/pushary-setup.js +45 -38
- package/dist/bin/pushary-stats.js +4 -4
- package/dist/bin/pushary-status.js +14 -10
- package/dist/bin/pushary-stop-hook.js +19 -19
- package/dist/bin/pushary-stopfailure-hook.js +19 -19
- package/dist/bin/pushary-suggestions.js +2 -2
- package/dist/bin/pushary-transcript-register.js +16 -16
- package/dist/bin/pushary-transcripts.js +7 -7
- package/dist/bin/pushary-upgrade.js +16 -16
- package/dist/bin/pushary-wait.js +8 -7
- package/dist/bin/pushary.js +1 -1
- package/dist/{chunk-N4VNLISN.js → chunk-4OSQZ5TB.js} +2 -2
- package/dist/{chunk-IM2A5H33.js → chunk-54W7ELDQ.js} +1 -1
- package/dist/{chunk-UCS65VVR.js → chunk-5GKNAQTG.js} +1 -1
- package/dist/{chunk-Z2UWFEJW.js → chunk-6W2WGNO5.js} +7 -7
- package/dist/{chunk-2D7BAOMY.js → chunk-7RNY3UHJ.js} +3 -3
- package/dist/{chunk-OW6AZDY2.js → chunk-BGX4QUQF.js} +1 -1
- package/dist/{chunk-I6GZX3FT.js → chunk-BQL7UDIB.js} +1 -1
- package/dist/{chunk-HGUZOUB2.js → chunk-CNUDZS4V.js} +3 -3
- package/dist/chunk-CVWG2N3Y.js +16 -0
- package/dist/{chunk-BMANRGJQ.js → chunk-EMGGUO2Q.js} +1 -1
- package/dist/{chunk-QHWXUNMN.js → chunk-FRXZMCVA.js} +1 -1
- package/dist/{chunk-DLLAWCQB.js → chunk-GOQHN2UH.js} +1 -1
- package/dist/{chunk-HBHEX3JQ.js → chunk-GQRU4KJF.js} +3 -3
- package/dist/{chunk-4RF52LSU.js → chunk-HAXZ6CBF.js} +8 -8
- package/dist/{chunk-OEKFD5BC.js → chunk-IZVK6FKD.js} +1 -1
- package/dist/{chunk-KAVDAZ7A.js → chunk-L7NOG547.js} +1 -1
- package/dist/{chunk-D6PRC3YQ.js → chunk-LZQVAEWP.js} +2 -1
- package/dist/{chunk-WDKHZRAS.js → chunk-MC5WUOJJ.js} +41 -0
- package/dist/{chunk-6VANQN5Q.js → chunk-NKUE5SJB.js} +2 -2
- package/dist/{chunk-QQGNFHIK.js → chunk-PQGLDN4V.js} +2 -2
- package/dist/{chunk-CUEZMPLJ.js → chunk-QJPYJVL3.js} +1 -1
- package/dist/{chunk-RLXVW4AM.js → chunk-SDNTRS76.js} +1 -1
- package/dist/{chunk-4PX4QK2Z.js → chunk-SKPXQRKN.js} +1 -1
- package/dist/{chunk-VTO3TNIB.js → chunk-TY6IJY6I.js} +1 -1
- package/dist/{chunk-HQIVR7MM.js → chunk-U5RIXR7I.js} +1 -1
- package/dist/{chunk-WRDLHR2F.js → chunk-UKMLSQXA.js} +2 -2
- package/dist/{chunk-6AEM5RCS.js → chunk-USWT4PTR.js} +1 -1
- package/dist/{chunk-D62EONG3.js → chunk-VDI645ZX.js} +1 -1
- package/dist/{chunk-OI3DJA7N.js → chunk-VERXHIQF.js} +1 -1
- package/dist/{chunk-67YNQ3QA.js → chunk-VIUOGMT5.js} +18 -14
- package/dist/{chunk-S5CMLR35.js → chunk-VMQU7YEJ.js} +1 -1
- package/dist/{chunk-XLOELLAS.js → chunk-VMZ4SWQD.js} +4 -4
- package/dist/{chunk-32RMQO5Z.js → chunk-WAUAYRUQ.js} +47 -4
- package/dist/{chunk-VOSGZ6PH.js → chunk-WPS5IM7B.js} +3 -3
- package/dist/{chunk-HCMM3BOW.js → chunk-XJQOVWBQ.js} +14 -11
- package/dist/{chunk-KI4PA7MQ.js → chunk-XO3JR3OP.js} +90 -18
- package/dist/{chunk-IVQMNLSA.js → chunk-XUTSZYYJ.js} +1 -1
- package/dist/{chunk-2ZTL3PGN.js → chunk-XZWUOCJZ.js} +1 -1
- package/dist/{chunk-BDI2MXTT.js → chunk-Z4JVEL7R.js} +1 -1
- package/dist/src/index.d.ts +3 -0
- package/dist/src/index.js +10 -10
- package/package.json +1 -1
- package/dist/chunk-IIENZE2J.js +0 -15
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import {
|
|
2
2
|
SETUP_FLAGS
|
|
3
|
-
} from "./chunk-
|
|
3
|
+
} from "./chunk-XZWUOCJZ.js";
|
|
4
4
|
import {
|
|
5
5
|
parseFlags
|
|
6
6
|
} from "./chunk-GMXKITVA.js";
|
|
@@ -14,7 +14,7 @@ import {
|
|
|
14
14
|
CLAUDE_CONNECTOR_URL,
|
|
15
15
|
COWORK_CONNECTOR_LIMIT,
|
|
16
16
|
COWORK_STANDING_INSTRUCTIONS
|
|
17
|
-
} from "./chunk-
|
|
17
|
+
} from "./chunk-MC5WUOJJ.js";
|
|
18
18
|
|
|
19
19
|
// src/cli/cowork.ts
|
|
20
20
|
import { readFileSync } from "fs";
|
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
import {
|
|
2
2
|
defersToNativeMode
|
|
3
|
-
} from "./chunk-
|
|
3
|
+
} from "./chunk-VDI645ZX.js";
|
|
4
4
|
import {
|
|
5
5
|
isGatingMoment,
|
|
6
6
|
recordKeylessMoment
|
|
7
|
-
} from "./chunk-
|
|
7
|
+
} from "./chunk-5GKNAQTG.js";
|
|
8
8
|
import {
|
|
9
9
|
denyReasonFrom,
|
|
10
10
|
isDeferAnswer
|
|
@@ -20,15 +20,7 @@ import {
|
|
|
20
20
|
reportEvent,
|
|
21
21
|
settleQuestionsForToolUse,
|
|
22
22
|
throttlePass
|
|
23
|
-
} from "./chunk-
|
|
24
|
-
import {
|
|
25
|
-
DECISION_STOP_REASON,
|
|
26
|
-
askUser,
|
|
27
|
-
isDecisionStopped,
|
|
28
|
-
isLocalQuestionHandoff,
|
|
29
|
-
sendNotification,
|
|
30
|
-
waitForQuestion
|
|
31
|
-
} from "./chunk-XS33QBJA.js";
|
|
23
|
+
} from "./chunk-XJQOVWBQ.js";
|
|
32
24
|
import {
|
|
33
25
|
UNNAMED_ACTION,
|
|
34
26
|
deriveAction,
|
|
@@ -38,10 +30,18 @@ import {
|
|
|
38
30
|
describeToolCall,
|
|
39
31
|
permissionDeniedAction,
|
|
40
32
|
scopePathFor
|
|
41
|
-
} from "./chunk-
|
|
33
|
+
} from "./chunk-Z4JVEL7R.js";
|
|
34
|
+
import {
|
|
35
|
+
DECISION_STOP_REASON,
|
|
36
|
+
askUser,
|
|
37
|
+
isDecisionStopped,
|
|
38
|
+
isLocalQuestionHandoff,
|
|
39
|
+
sendNotification,
|
|
40
|
+
waitForQuestion
|
|
41
|
+
} from "./chunk-XS33QBJA.js";
|
|
42
42
|
import {
|
|
43
43
|
getMachineId
|
|
44
|
-
} from "./chunk-
|
|
44
|
+
} from "./chunk-4OSQZ5TB.js";
|
|
45
45
|
import {
|
|
46
46
|
getApiKey,
|
|
47
47
|
getBaseUrl
|
|
@@ -53,13 +53,14 @@ import {
|
|
|
53
53
|
effectiveWaitSeconds,
|
|
54
54
|
hookWaitClamped,
|
|
55
55
|
hookWaitDeadline,
|
|
56
|
+
hookWritePath,
|
|
56
57
|
isPermissionRequestOwnedByPreToolUse,
|
|
57
58
|
isPusharyOwnTool,
|
|
58
59
|
parseAgentQuestionAnswers,
|
|
59
60
|
parseAgentQuestions,
|
|
60
61
|
resolveGate,
|
|
61
62
|
stoppedOutput
|
|
62
|
-
} from "./chunk-
|
|
63
|
+
} from "./chunk-MC5WUOJJ.js";
|
|
63
64
|
|
|
64
65
|
// src/decision-episode.ts
|
|
65
66
|
var EPISODE_PATH = "/api/agent/decision-episode";
|
|
@@ -225,6 +226,7 @@ var dispatchModeHandler = async (apiKey, input, toolPolicy, machineId, trainingC
|
|
|
225
226
|
const toolTarget = deriveToolTarget(input.tool_name, input.tool_input);
|
|
226
227
|
const intent = readLastPrompt(sessionId ?? DEFAULT_SESSION) ?? (input.transcript_path ? readLastUserPrompt(input.transcript_path) : void 0);
|
|
227
228
|
const decision = {
|
|
229
|
+
toolPath: hookWritePath(input.tool_name, input.tool_input),
|
|
228
230
|
intent,
|
|
229
231
|
action: deriveAction(input.tool_name, input.tool_input),
|
|
230
232
|
blocker: scopeReason ?? deriveBlocker(toolPolicy.mode),
|
|
@@ -537,6 +539,8 @@ var automodeRetryEnabled = () => {
|
|
|
537
539
|
};
|
|
538
540
|
var reportPermissionDenied = (input) => reportEvent({
|
|
539
541
|
event: "permission_denied",
|
|
542
|
+
occurredAt: (/* @__PURE__ */ new Date()).toISOString(),
|
|
543
|
+
toolUseId: input.tool_use_id,
|
|
540
544
|
agentType: CLAUDE_CODE_AGENT.type,
|
|
541
545
|
agentName: `${CLAUDE_CODE_AGENT.label} - ${basename(input.cwd ?? process.cwd())}`,
|
|
542
546
|
action: permissionDeniedAction(input.tool_name),
|
|
@@ -7,22 +7,22 @@ import {
|
|
|
7
7
|
} from "./chunk-L4ZCFMWW.js";
|
|
8
8
|
import {
|
|
9
9
|
getMachineId
|
|
10
|
-
} from "./chunk-
|
|
10
|
+
} from "./chunk-4OSQZ5TB.js";
|
|
11
11
|
import {
|
|
12
12
|
pusharyDir
|
|
13
|
-
} from "./chunk-
|
|
13
|
+
} from "./chunk-BGX4QUQF.js";
|
|
14
14
|
import {
|
|
15
15
|
getPackageVersion
|
|
16
16
|
} from "./chunk-DINDL2CF.js";
|
|
17
17
|
import {
|
|
18
18
|
readControlMode
|
|
19
|
-
} from "./chunk-
|
|
19
|
+
} from "./chunk-VMQU7YEJ.js";
|
|
20
20
|
import {
|
|
21
21
|
readJsonSafe,
|
|
22
22
|
writeFileAtomic,
|
|
23
23
|
writeJsonAtomic,
|
|
24
24
|
writeJsonAtomicDurable
|
|
25
|
-
} from "./chunk-
|
|
25
|
+
} from "./chunk-L7NOG547.js";
|
|
26
26
|
import {
|
|
27
27
|
getApiKey
|
|
28
28
|
} from "./chunk-2UMNXADU.js";
|
|
@@ -1,9 +1,25 @@
|
|
|
1
|
+
import {
|
|
2
|
+
detectProviderLiveCapabilities,
|
|
3
|
+
hasSpawnProvider,
|
|
4
|
+
resolveControlPolicy
|
|
5
|
+
} from "./chunk-54W7ELDQ.js";
|
|
6
|
+
import {
|
|
7
|
+
daemonHasRemoteProof,
|
|
8
|
+
daemonServiceManagerAvailable,
|
|
9
|
+
hasDaemonServiceDefinition,
|
|
10
|
+
readDaemonNeedsLogin,
|
|
11
|
+
readDaemonStatus
|
|
12
|
+
} from "./chunk-VMZ4SWQD.js";
|
|
1
13
|
import {
|
|
2
14
|
getMachineId
|
|
3
|
-
} from "./chunk-
|
|
15
|
+
} from "./chunk-4OSQZ5TB.js";
|
|
4
16
|
import {
|
|
5
17
|
getPackageVersion
|
|
6
18
|
} from "./chunk-DINDL2CF.js";
|
|
19
|
+
import {
|
|
20
|
+
readControlMode,
|
|
21
|
+
readKeySource
|
|
22
|
+
} from "./chunk-VMQU7YEJ.js";
|
|
7
23
|
import {
|
|
8
24
|
getBaseUrl
|
|
9
25
|
} from "./chunk-2UMNXADU.js";
|
|
@@ -50,7 +66,7 @@ var parseMachine = (value) => {
|
|
|
50
66
|
online: raw.online === true
|
|
51
67
|
};
|
|
52
68
|
};
|
|
53
|
-
var machineReadiness = (machines, machineId, expectedCapabilities) => {
|
|
69
|
+
var machineReadiness = (machines, machineId, expectedCapabilities, now = Date.now()) => {
|
|
54
70
|
const machine = machines.find((item) => item.machineId === machineId);
|
|
55
71
|
if (!machine) return { kind: "not-ready", detail: "this machine has not heartbeated to the server" };
|
|
56
72
|
if (!machine.online) return { kind: "not-ready", detail: "the server reports this machine offline" };
|
|
@@ -60,12 +76,15 @@ var machineReadiness = (machines, machineId, expectedCapabilities) => {
|
|
|
60
76
|
if (machine.lastControlAt === null || !Number.isFinite(Date.parse(machine.lastControlAt))) {
|
|
61
77
|
return { kind: "not-ready", detail: "the server has not observed this machine polling the control queue" };
|
|
62
78
|
}
|
|
79
|
+
if (!daemonHasRemoteProof({ kind: "running", lastSuccessfulHeartbeatAt: machine.lastSeenAt, lastSuccessfulControlAt: machine.lastControlAt }, now)) {
|
|
80
|
+
return { kind: "not-ready", detail: "the heartbeat or control-queue proof is stale; wake this machine and retry pushary doctor" };
|
|
81
|
+
}
|
|
63
82
|
const missing = expectedCapabilities.filter((capability) => !machine.capabilities.includes(capability));
|
|
64
83
|
return missing.length === 0 ? { kind: "ready", machine } : { kind: "not-ready", detail: `the server is missing capabilities: ${missing.join(", ")}` };
|
|
65
84
|
};
|
|
66
85
|
var readMachineReadiness = async (apiKey, expectedCapabilities, deps = {}) => {
|
|
67
86
|
const listed = await listMachines(apiKey, deps);
|
|
68
|
-
return listed.kind === "ok" ? machineReadiness(listed.machines, deps.machineId ?? getMachineId(), expectedCapabilities) : listed.kind === "unsupported" ? { kind: "unsupported", detail: "the server does not report machine readiness yet" } : listed;
|
|
87
|
+
return listed.kind === "ok" ? machineReadiness(listed.machines, deps.machineId ?? getMachineId(), expectedCapabilities, deps.now?.()) : listed.kind === "unsupported" ? { kind: "unsupported", detail: "the server does not report machine readiness yet" } : listed;
|
|
69
88
|
};
|
|
70
89
|
var waitForMachineReadiness = async (apiKey, expectedCapabilities, deps = {}) => {
|
|
71
90
|
const attempts = deps.attempts ?? 21;
|
|
@@ -106,6 +125,29 @@ var describeLastSeen = (iso, now = Date.now()) => {
|
|
|
106
125
|
if (hours < 48) return `${hours}h ago`;
|
|
107
126
|
return `${Math.round(hours / 24)}d ago`;
|
|
108
127
|
};
|
|
128
|
+
var readManagedControlEvidence = (apiKey, providers, serverProof) => {
|
|
129
|
+
const now = Date.now();
|
|
130
|
+
const daemon = readDaemonStatus();
|
|
131
|
+
const capabilities = detectProviderLiveCapabilities(providers);
|
|
132
|
+
const providerAvailable = hasSpawnProvider(capabilities);
|
|
133
|
+
const managerAvailable = daemonServiceManagerAvailable();
|
|
134
|
+
const serviceInstalled = hasDaemonServiceDefinition();
|
|
135
|
+
const keyCurrent = Boolean(apiKey) && readKeySource().key === apiKey && readDaemonNeedsLogin().kind !== "blocked";
|
|
136
|
+
const policy = resolveControlPolicy({ mode: readControlMode(), providerAvailable, managerAvailable, servicePresent: serviceInstalled || daemon.kind !== "absent" });
|
|
137
|
+
const localProof = daemonHasRemoteProof(daemon, now);
|
|
138
|
+
const remote = serverProof?.kind === "ready" ? machineReadiness([serverProof.machine], daemon.machineId ?? "", ["spawn", ...capabilities], now) : serverProof;
|
|
139
|
+
return {
|
|
140
|
+
ready: keyCurrent && policy === "enabled" && providerAvailable && managerAvailable && serviceInstalled && localProof && remote?.kind === "ready",
|
|
141
|
+
keyCurrent,
|
|
142
|
+
providerAvailable,
|
|
143
|
+
managerAvailable,
|
|
144
|
+
serviceInstalled,
|
|
145
|
+
policy,
|
|
146
|
+
localProof,
|
|
147
|
+
serverProof: remote?.kind ?? "unchecked",
|
|
148
|
+
checkedAt: new Date(now).toISOString()
|
|
149
|
+
};
|
|
150
|
+
};
|
|
109
151
|
|
|
110
152
|
export {
|
|
111
153
|
HEARTBEAT_INTERVAL_MS,
|
|
@@ -113,5 +155,6 @@ export {
|
|
|
113
155
|
readMachineReadiness,
|
|
114
156
|
waitForMachineReadiness,
|
|
115
157
|
listMachines,
|
|
116
|
-
describeLastSeen
|
|
158
|
+
describeLastSeen,
|
|
159
|
+
readManagedControlEvidence
|
|
117
160
|
};
|
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
import {
|
|
2
2
|
AGENT_CHOICES
|
|
3
|
-
} from "./chunk-
|
|
3
|
+
} from "./chunk-XZWUOCJZ.js";
|
|
4
4
|
import {
|
|
5
5
|
isBridgeLocator
|
|
6
|
-
} from "./chunk-
|
|
6
|
+
} from "./chunk-QJPYJVL3.js";
|
|
7
7
|
import {
|
|
8
8
|
pusharyHookExecutable
|
|
9
|
-
} from "./chunk-
|
|
9
|
+
} from "./chunk-GQRU4KJF.js";
|
|
10
10
|
import {
|
|
11
11
|
BELL_HOOK_BINARY
|
|
12
12
|
} from "./chunk-GOPIMNVC.js";
|
|
@@ -1,9 +1,3 @@
|
|
|
1
|
-
import {
|
|
2
|
-
cancelQuestion,
|
|
3
|
-
isPolicyConfig,
|
|
4
|
-
sendNotification,
|
|
5
|
-
waitForAnswer
|
|
6
|
-
} from "./chunk-XS33QBJA.js";
|
|
7
1
|
import {
|
|
8
2
|
AGENT_IDENTITIES,
|
|
9
3
|
TEAMMATE_IDLE_ACTION,
|
|
@@ -24,20 +18,26 @@ import {
|
|
|
24
18
|
summarizeStop,
|
|
25
19
|
taskTitleFrom,
|
|
26
20
|
toolResultErrorText
|
|
27
|
-
} from "./chunk-
|
|
21
|
+
} from "./chunk-Z4JVEL7R.js";
|
|
28
22
|
import {
|
|
29
23
|
NOTIFICATION_PUSH_TYPES,
|
|
30
24
|
POSTTOOLUSE_MIRROR_ONLY_TOOLS
|
|
31
|
-
} from "./chunk-
|
|
25
|
+
} from "./chunk-XUTSZYYJ.js";
|
|
26
|
+
import {
|
|
27
|
+
cancelQuestion,
|
|
28
|
+
isPolicyConfig,
|
|
29
|
+
sendNotification,
|
|
30
|
+
waitForAnswer
|
|
31
|
+
} from "./chunk-XS33QBJA.js";
|
|
32
32
|
import {
|
|
33
33
|
getMachineId
|
|
34
|
-
} from "./chunk-
|
|
34
|
+
} from "./chunk-4OSQZ5TB.js";
|
|
35
35
|
import {
|
|
36
36
|
withRetry
|
|
37
37
|
} from "./chunk-EYRGBYZG.js";
|
|
38
38
|
import {
|
|
39
39
|
reportedInstallSource
|
|
40
|
-
} from "./chunk-
|
|
40
|
+
} from "./chunk-L7NOG547.js";
|
|
41
41
|
import {
|
|
42
42
|
getApiKey,
|
|
43
43
|
getBaseUrl
|
|
@@ -54,7 +54,7 @@ import {
|
|
|
54
54
|
pendingCommandEvents,
|
|
55
55
|
resolveAutoResolveOrigin,
|
|
56
56
|
resolvePolicy
|
|
57
|
-
} from "./chunk-
|
|
57
|
+
} from "./chunk-MC5WUOJJ.js";
|
|
58
58
|
|
|
59
59
|
// src/policy.ts
|
|
60
60
|
import { createHash } from "crypto";
|
|
@@ -1004,6 +1004,7 @@ var settleQuestionsForToolUse = async (sessionId, toolUseId) => {
|
|
|
1004
1004
|
for (const answer of late) removePendingQuestion(sessionId, answer.correlationId);
|
|
1005
1005
|
};
|
|
1006
1006
|
var handlePostToolUse = async (input, agent = CLAUDE_CODE_AGENT) => {
|
|
1007
|
+
const occurredAt = (/* @__PURE__ */ new Date()).toISOString();
|
|
1007
1008
|
const deadline = Date.now() + HOOK_BUDGET_MS;
|
|
1008
1009
|
const signal = AbortSignal.timeout(HOOK_BUDGET_MS);
|
|
1009
1010
|
try {
|
|
@@ -1028,6 +1029,8 @@ var handlePostToolUse = async (input, agent = CLAUDE_CODE_AGENT) => {
|
|
|
1028
1029
|
const beacon = !isMirrorOnly && decisionSource === "policy_auto" && throttlePass(`autodecision:${sessionKey}:${lookup.tool}`, AUTO_DECISION_WINDOW_MS) ? deriveAutoDecisionBeacon(lookup.tool, lookup.input, liveMode, agent.type, input.cwd, input.session_id) : void 0;
|
|
1029
1030
|
const toolReport = reportEvent({
|
|
1030
1031
|
event: isError ? "tool_error" : "tool_complete",
|
|
1032
|
+
occurredAt,
|
|
1033
|
+
toolUseId: input.tool_use_id,
|
|
1031
1034
|
agentType: agent.type,
|
|
1032
1035
|
agentName: `${agent.label} - ${projectName}`,
|
|
1033
1036
|
action,
|
|
@@ -15,7 +15,10 @@ import {
|
|
|
15
15
|
} from "./chunk-EYRGBYZG.js";
|
|
16
16
|
import {
|
|
17
17
|
reportedInstallSource
|
|
18
|
-
} from "./chunk-
|
|
18
|
+
} from "./chunk-L7NOG547.js";
|
|
19
|
+
import {
|
|
20
|
+
isAnswerSource
|
|
21
|
+
} from "./chunk-MC5WUOJJ.js";
|
|
19
22
|
|
|
20
23
|
// src/reach.ts
|
|
21
24
|
var reachVerdict = (channels) => {
|
|
@@ -119,7 +122,7 @@ var classifyDelivery = (channels, push) => {
|
|
|
119
122
|
var sendTestNotification = async (apiKey) => {
|
|
120
123
|
const result = await callMcpTool(apiKey, "send_notification", {
|
|
121
124
|
title: "Pushary is connected",
|
|
122
|
-
body: "
|
|
125
|
+
body: "This setup notification reached you. Agent hooks still need a real-agent check.",
|
|
123
126
|
agentName: "Pushary setup"
|
|
124
127
|
}, { timeoutMs: 2e4 });
|
|
125
128
|
const toCount = (value) => typeof value === "number" && Number.isFinite(value) ? value : 0;
|
|
@@ -145,7 +148,7 @@ var describeVerifyOutcome = (outcome) => {
|
|
|
145
148
|
message: "Nothing to deliver to. Agents are configured; approvals will fall back to the terminal.",
|
|
146
149
|
next: [
|
|
147
150
|
"Run pushary connect to add your phone.",
|
|
148
|
-
"Then pushary doctor --roundtrip to test a
|
|
151
|
+
"Then pushary doctor --roundtrip to test a synthetic question and answer."
|
|
149
152
|
]
|
|
150
153
|
};
|
|
151
154
|
case "others-only":
|
|
@@ -174,7 +177,7 @@ var describeVerifyOutcome = (outcome) => {
|
|
|
174
177
|
};
|
|
175
178
|
}
|
|
176
179
|
};
|
|
177
|
-
var ROUND_TRIP_QUESTION = "
|
|
180
|
+
var ROUND_TRIP_QUESTION = "Pushary delivery test. Tap Yes or No to test returning an answer. This does not test your agent hooks.";
|
|
178
181
|
var ROUND_TRIP_TIMEOUT_MS = 55e3;
|
|
179
182
|
var defaultAsk = (apiKey, agentName) => (
|
|
180
183
|
// wait:false so the poll is ours: the blocking form returns on the SITE's
|
|
@@ -195,6 +198,18 @@ var defaultCancel = async (apiKey, correlationId) => {
|
|
|
195
198
|
await callMcpTool(apiKey, "cancel_question", { correlationId }, { timeoutMs: 1e4 }).catch(() => {
|
|
196
199
|
});
|
|
197
200
|
};
|
|
201
|
+
var answeredRoundTrip = (answer, correlationId, latencyMs) => {
|
|
202
|
+
if (answer.value !== "yes" && answer.value !== "no") {
|
|
203
|
+
return { kind: "error", detail: "the server reported an answer without a valid Yes or No value" };
|
|
204
|
+
}
|
|
205
|
+
return {
|
|
206
|
+
kind: "answered",
|
|
207
|
+
value: answer.value,
|
|
208
|
+
latencyMs,
|
|
209
|
+
correlationId,
|
|
210
|
+
...isAnswerSource(answer.answerSource) ? { answerSource: answer.answerSource } : {}
|
|
211
|
+
};
|
|
212
|
+
};
|
|
198
213
|
var verifyRoundTrip = async (apiKey, agentName = "Pushary setup", deps = {}) => {
|
|
199
214
|
const ask = deps.ask ?? defaultAsk;
|
|
200
215
|
const wait = deps.wait ?? defaultWait;
|
|
@@ -207,31 +222,73 @@ var verifyRoundTrip = async (apiKey, agentName = "Pushary setup", deps = {}) =>
|
|
|
207
222
|
} catch (err) {
|
|
208
223
|
return { kind: "error", detail: err instanceof Error ? err.message : "ask failed" };
|
|
209
224
|
}
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
225
|
+
let shutdown;
|
|
226
|
+
const stop = (code) => {
|
|
227
|
+
if (shutdown) return;
|
|
228
|
+
shutdown = (async () => {
|
|
229
|
+
let timer;
|
|
230
|
+
try {
|
|
231
|
+
await Promise.race([
|
|
232
|
+
cancel(apiKey, asked.correlationId).catch(() => {
|
|
233
|
+
}),
|
|
234
|
+
new Promise((resolve) => {
|
|
235
|
+
timer = setTimeout(resolve, 4e3);
|
|
236
|
+
})
|
|
237
|
+
]);
|
|
238
|
+
} finally {
|
|
239
|
+
clearTimeout(timer);
|
|
240
|
+
process.stderr.write("Delivery test interrupted. Cleanup was attempted; an unresolved question expires automatically.\n");
|
|
241
|
+
process.exit(code);
|
|
242
|
+
}
|
|
243
|
+
})();
|
|
244
|
+
};
|
|
245
|
+
const onInterrupt = () => stop(130);
|
|
246
|
+
const onTerminate = () => stop(143);
|
|
247
|
+
if (asked.correlationId) {
|
|
248
|
+
process.on("SIGINT", onInterrupt);
|
|
249
|
+
process.on("SIGTERM", onTerminate);
|
|
215
250
|
}
|
|
216
|
-
let
|
|
251
|
+
let answerObserved = false;
|
|
217
252
|
try {
|
|
218
|
-
|
|
253
|
+
if (asked.noDevices || asked.warning) return { kind: "no-recipients" };
|
|
254
|
+
if (asked.mode === "notify_only" || asked.status === "notified") return { kind: "notify-only" };
|
|
255
|
+
if (!asked.correlationId) return { kind: "error", detail: "no correlationId returned" };
|
|
256
|
+
const answer = asked.answered === true ? asked : await wait(apiKey, asked.correlationId);
|
|
257
|
+
if (answer.answered === true) {
|
|
258
|
+
const outcome = answeredRoundTrip(answer, asked.correlationId, now() - started);
|
|
259
|
+
answerObserved = outcome.kind === "answered";
|
|
260
|
+
return outcome;
|
|
261
|
+
}
|
|
262
|
+
return { kind: "unanswered" };
|
|
219
263
|
} catch (err) {
|
|
220
|
-
await cancel(apiKey, asked.correlationId);
|
|
221
264
|
return { kind: "error", detail: err instanceof Error ? err.message : "wait failed" };
|
|
265
|
+
} finally {
|
|
266
|
+
if (shutdown) await shutdown;
|
|
267
|
+
process.off("SIGINT", onInterrupt);
|
|
268
|
+
process.off("SIGTERM", onTerminate);
|
|
269
|
+
if (!answerObserved && asked.correlationId) await cancel(apiKey, asked.correlationId).catch(() => {
|
|
270
|
+
});
|
|
222
271
|
}
|
|
223
|
-
|
|
224
|
-
|
|
272
|
+
};
|
|
273
|
+
var describeAnswerSource = (source) => {
|
|
274
|
+
switch (source) {
|
|
275
|
+
case "mobile_app":
|
|
276
|
+
case "mobile_background":
|
|
277
|
+
return "A phone answered this synthetic test.";
|
|
278
|
+
case "mac_app":
|
|
279
|
+
return "A Mac answered this synthetic test.";
|
|
280
|
+
case "sandbox":
|
|
281
|
+
return "This was a simulated sandbox answer.";
|
|
282
|
+
default:
|
|
283
|
+
return source ? `Answer source: ${source}. This was a synthetic test.` : "The answering surface was not reported. This was a synthetic test.";
|
|
225
284
|
}
|
|
226
|
-
await cancel(apiKey, asked.correlationId);
|
|
227
|
-
return { kind: "unanswered" };
|
|
228
285
|
};
|
|
229
|
-
var
|
|
286
|
+
var describeRoundTripOutcome = (outcome) => {
|
|
230
287
|
switch (outcome.kind) {
|
|
231
288
|
case "answered":
|
|
232
289
|
return {
|
|
233
290
|
ok: true,
|
|
234
|
-
message: `Answered "${outcome.value}" in ${(outcome.latencyMs / 1e3).toFixed(1)}s.
|
|
291
|
+
message: `Answered "${outcome.value}" in ${(outcome.latencyMs / 1e3).toFixed(1)}s. ${describeAnswerSource(outcome.answerSource)}`,
|
|
235
292
|
next: []
|
|
236
293
|
};
|
|
237
294
|
case "unanswered":
|
|
@@ -266,6 +323,20 @@ var describeRoundTrip = (outcome) => {
|
|
|
266
323
|
};
|
|
267
324
|
}
|
|
268
325
|
};
|
|
326
|
+
var describeRoundTrip = (outcome) => {
|
|
327
|
+
const report = describeRoundTripOutcome(outcome);
|
|
328
|
+
return { ...report, next: [...report.next, "Agent hook activation remains unverified. Restart your agent and check one real approval."] };
|
|
329
|
+
};
|
|
330
|
+
var roundTripEvidence = (outcome) => ({
|
|
331
|
+
kind: outcome?.kind ?? "skipped",
|
|
332
|
+
...outcome?.kind === "answered" ? {
|
|
333
|
+
correlationId: outcome.correlationId ?? null,
|
|
334
|
+
answerSource: outcome.answerSource ?? null,
|
|
335
|
+
value: outcome.value,
|
|
336
|
+
latencyMs: outcome.latencyMs
|
|
337
|
+
} : {},
|
|
338
|
+
hookActivation: "unverified"
|
|
339
|
+
});
|
|
269
340
|
|
|
270
341
|
// src/onboarding.ts
|
|
271
342
|
import qrcodeTerminal from "qrcode-terminal";
|
|
@@ -863,6 +934,7 @@ export {
|
|
|
863
934
|
describeReach,
|
|
864
935
|
verifyRoundTrip,
|
|
865
936
|
describeRoundTrip,
|
|
937
|
+
roundTripEvidence,
|
|
866
938
|
fetchChannels,
|
|
867
939
|
connectDevice,
|
|
868
940
|
confirmAppConnection,
|
|
@@ -6,7 +6,7 @@ import {
|
|
|
6
6
|
} from "./chunk-7QLSKOSU.js";
|
|
7
7
|
import {
|
|
8
8
|
isValidApiKey
|
|
9
|
-
} from "./chunk-
|
|
9
|
+
} from "./chunk-MC5WUOJJ.js";
|
|
10
10
|
|
|
11
11
|
// src/setup/options.ts
|
|
12
12
|
var AGENT_CHOICES = ["claude_code", "codex", "gemini_cli", "hermes", "cursor", "vscode", "opencode", "custom"];
|
package/dist/src/index.d.ts
CHANGED
|
@@ -34,6 +34,8 @@ interface AgentIdentity {
|
|
|
34
34
|
readonly label: string;
|
|
35
35
|
}
|
|
36
36
|
interface AgentEvent {
|
|
37
|
+
occurredAt?: string;
|
|
38
|
+
toolUseId?: string;
|
|
37
39
|
event: string;
|
|
38
40
|
agentType: string;
|
|
39
41
|
agentName?: string;
|
|
@@ -147,6 +149,7 @@ interface AskUserParams {
|
|
|
147
149
|
machineId?: string;
|
|
148
150
|
toolName?: string;
|
|
149
151
|
toolTarget?: string;
|
|
152
|
+
toolPath?: string;
|
|
150
153
|
repoKey?: string;
|
|
151
154
|
intent?: string;
|
|
152
155
|
action?: 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-VIUOGMT5.js";
|
|
4
|
+
import "../chunk-VDI645ZX.js";
|
|
5
|
+
import "../chunk-5GKNAQTG.js";
|
|
6
6
|
import "../chunk-YHG74UFF.js";
|
|
7
7
|
import {
|
|
8
8
|
fetchAccountPublicKey
|
|
@@ -15,28 +15,28 @@ import {
|
|
|
15
15
|
handlePostToolUse,
|
|
16
16
|
handleStop,
|
|
17
17
|
reportEvent
|
|
18
|
-
} from "../chunk-
|
|
18
|
+
} from "../chunk-XJQOVWBQ.js";
|
|
19
|
+
import "../chunk-Z4JVEL7R.js";
|
|
20
|
+
import "../chunk-XUTSZYYJ.js";
|
|
19
21
|
import {
|
|
20
22
|
askUser,
|
|
21
23
|
cancelQuestion,
|
|
22
24
|
waitForAnswer
|
|
23
25
|
} from "../chunk-XS33QBJA.js";
|
|
24
|
-
import "../chunk-
|
|
25
|
-
import "../chunk-
|
|
26
|
-
import "../chunk-N4VNLISN.js";
|
|
27
|
-
import "../chunk-OW6AZDY2.js";
|
|
26
|
+
import "../chunk-4OSQZ5TB.js";
|
|
27
|
+
import "../chunk-BGX4QUQF.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-
|
|
32
|
+
import "../chunk-L7NOG547.js";
|
|
33
33
|
import {
|
|
34
34
|
getApiKey,
|
|
35
35
|
getBaseUrl
|
|
36
36
|
} from "../chunk-2UMNXADU.js";
|
|
37
37
|
import {
|
|
38
38
|
resolvePolicy
|
|
39
|
-
} from "../chunk-
|
|
39
|
+
} from "../chunk-MC5WUOJJ.js";
|
|
40
40
|
export {
|
|
41
41
|
askUser,
|
|
42
42
|
cancelQuestion,
|
package/package.json
CHANGED
package/dist/chunk-IIENZE2J.js
DELETED
|
@@ -1,15 +0,0 @@
|
|
|
1
|
-
// src/wait-ladder.ts
|
|
2
|
-
var describeWaitLadder = (p) => {
|
|
3
|
-
if (p.mode === "terminal_only") return "decide in the terminal, no push";
|
|
4
|
-
if (p.mode === "notify_only") return "send a heads-up, the terminal decides";
|
|
5
|
-
if (p.mode === "push_only") {
|
|
6
|
-
if (p.timeoutAction === "wait") return "wait for your phone, then ask in the terminal";
|
|
7
|
-
const tail = p.timeoutAction === "approve" ? "then auto-approve" : p.timeoutAction === "deny" ? "then auto-deny" : "then ask in the terminal";
|
|
8
|
-
return `wait for your phone up to ${p.timeoutSeconds}s, ${tail}`;
|
|
9
|
-
}
|
|
10
|
-
return `ping your phone ${p.pushFirstSeconds}s, then ask in the terminal`;
|
|
11
|
-
};
|
|
12
|
-
|
|
13
|
-
export {
|
|
14
|
-
describeWaitLadder
|
|
15
|
-
};
|