@trygocode/notify 0.6.5 → 0.6.6
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/README.md +11 -0
- package/dist/src/claude.js +19 -4
- package/dist/src/cli.js +43 -4
- package/dist/src/version.js +1 -1
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -530,6 +530,17 @@ npm publish, real-device E2E), see
|
|
|
530
530
|
|
|
531
531
|
## Changelog
|
|
532
532
|
|
|
533
|
+
### 0.6.6
|
|
534
|
+
|
|
535
|
+
- **Claude questions are now classified by notification type.** Setup installs
|
|
536
|
+
the `Notification` hook only for `permission_prompt`, `idle_prompt`,
|
|
537
|
+
`elicitation_dialog`, and `agent_needs_input`. The dispatcher repeats that
|
|
538
|
+
check from stdin so existing 0.6.5 hook configs are protected immediately by
|
|
539
|
+
`@latest`, even before setup is rerun.
|
|
540
|
+
- Non-input events such as `auth_success`, `elicitation_complete`,
|
|
541
|
+
`elicitation_response`, and `agent_completed` no longer produce a misleading
|
|
542
|
+
“Agent needs you” notification or duplicate the Claude `Stop` completion.
|
|
543
|
+
|
|
533
544
|
### 0.6.5
|
|
534
545
|
|
|
535
546
|
- **Fixed Cursor lifecycle notifications on current Cursor releases.** The
|
package/dist/src/claude.js
CHANGED
|
@@ -66,6 +66,16 @@ export const CLAUDE_HOOK_COMMANDS = {
|
|
|
66
66
|
Stop: 'npx -y @trygocode/notify@latest on-stop --source claude_code --dedupe-key "$CLAUDE_SESSION_ID-stop" --quiet || true',
|
|
67
67
|
Notification: 'npx -y @trygocode/notify@latest on-notification --source claude_code --dedupe-key "$CLAUDE_SESSION_ID-notify" --quiet || true',
|
|
68
68
|
};
|
|
69
|
+
/**
|
|
70
|
+
* Claude `Notification` types that genuinely require the user's attention.
|
|
71
|
+
* Keep this matcher in lockstep with `CLAUDE_INPUT_NOTIFICATION_TYPES` in
|
|
72
|
+
* `cli.ts`, which provides a defensive payload check for existing 0.6.5
|
|
73
|
+
* installs whose matcher is still empty until setup is rerun.
|
|
74
|
+
*
|
|
75
|
+
* Deliberately excluded: `auth_success`, `elicitation_complete`,
|
|
76
|
+
* `elicitation_response`, and `agent_completed`.
|
|
77
|
+
*/
|
|
78
|
+
export const CLAUDE_NOTIFICATION_MATCHER = "permission_prompt|idle_prompt|elicitation_dialog|agent_needs_input";
|
|
69
79
|
/**
|
|
70
80
|
* The Claude event we DELIBERATELY do not register and actively scrub on every
|
|
71
81
|
* setup. We used to fire a `finished` push on `SubagentStop` ("Subagent done"),
|
|
@@ -193,9 +203,14 @@ function stripOurHooks(groups) {
|
|
|
193
203
|
}
|
|
194
204
|
return { groups: out, removed };
|
|
195
205
|
}
|
|
196
|
-
/** Build the
|
|
197
|
-
function ourHookGroup(command) {
|
|
198
|
-
|
|
206
|
+
/** Build the hook group we add for a single event. */
|
|
207
|
+
function ourHookGroup(event, command) {
|
|
208
|
+
const group = {
|
|
209
|
+
hooks: [{ type: "command", command }],
|
|
210
|
+
};
|
|
211
|
+
if (event === "Notification")
|
|
212
|
+
group.matcher = CLAUDE_NOTIFICATION_MATCHER;
|
|
213
|
+
return group;
|
|
199
214
|
}
|
|
200
215
|
/**
|
|
201
216
|
* Merge our three hook events into `settings.hooks`, preserving the user's own
|
|
@@ -209,7 +224,7 @@ function mergeHooks(settings) {
|
|
|
209
224
|
for (const [event, command] of Object.entries(CLAUDE_HOOK_COMMANDS)) {
|
|
210
225
|
const existing = Array.isArray(hooks[event]) ? hooks[event] : [];
|
|
211
226
|
const preserved = stripOurHooks(existing).groups;
|
|
212
|
-
preserved.push(ourHookGroup(command));
|
|
227
|
+
preserved.push(ourHookGroup(event, command));
|
|
213
228
|
hooks[event] = preserved;
|
|
214
229
|
}
|
|
215
230
|
// Migrate old installs: strip OUR command from any event we no longer install
|
package/dist/src/cli.js
CHANGED
|
@@ -748,12 +748,46 @@ export async function cmdOnStop(args, deps = {}) {
|
|
|
748
748
|
// PRD §0.5 / §4.4: a stop hook must NEVER block the turn — always exit 0.
|
|
749
749
|
return 0;
|
|
750
750
|
}
|
|
751
|
+
/**
|
|
752
|
+
* Claude Notification types that actually mean the agent is waiting for the
|
|
753
|
+
* user. This defensive payload filter protects users who upgraded the executable
|
|
754
|
+
* to 0.6.6 through `@latest` but have not rerun setup yet, so their installed
|
|
755
|
+
* 0.6.5 Notification group still has no matcher.
|
|
756
|
+
*/
|
|
757
|
+
export const CLAUDE_INPUT_NOTIFICATION_TYPES = new Set([
|
|
758
|
+
"permission_prompt",
|
|
759
|
+
"idle_prompt",
|
|
760
|
+
"elicitation_dialog",
|
|
761
|
+
"agent_needs_input",
|
|
762
|
+
]);
|
|
763
|
+
/**
|
|
764
|
+
* Extract Claude Code's notification discriminator. A missing/invalid payload
|
|
765
|
+
* returns undefined so legacy Claude versions (whose Notification stdin did not
|
|
766
|
+
* include `notification_type`) retain the historical awaiting-input behavior.
|
|
767
|
+
*/
|
|
768
|
+
export function parseClaudeNotificationType(hookStdin) {
|
|
769
|
+
if (!hookStdin || hookStdin.trim() === "")
|
|
770
|
+
return undefined;
|
|
771
|
+
try {
|
|
772
|
+
const parsed = JSON.parse(hookStdin);
|
|
773
|
+
if (!parsed || typeof parsed !== "object")
|
|
774
|
+
return undefined;
|
|
775
|
+
const notificationType = parsed.notification_type;
|
|
776
|
+
return typeof notificationType === "string" && notificationType.trim() !== ""
|
|
777
|
+
? notificationType.trim()
|
|
778
|
+
: undefined;
|
|
779
|
+
}
|
|
780
|
+
catch {
|
|
781
|
+
return undefined;
|
|
782
|
+
}
|
|
783
|
+
}
|
|
751
784
|
/**
|
|
752
785
|
* Handle Claude Code's `Notification` hook while avoiding Cursor's third-party
|
|
753
|
-
* import duplicate
|
|
754
|
-
* awaiting-input send.
|
|
755
|
-
*
|
|
756
|
-
*
|
|
786
|
+
* import duplicate and non-input notification classes. Standalone Claude input
|
|
787
|
+
* requests are forwarded to the normal awaiting-input send. Known non-input
|
|
788
|
+
* events (`auth_success`, elicitation completion/response, `agent_completed`)
|
|
789
|
+
* are ignored. Cursor-imported payloads carry `cursor_version` and are ignored
|
|
790
|
+
* because Cursor's native question hook is authoritative when available.
|
|
757
791
|
*/
|
|
758
792
|
export async function cmdOnNotification(args, deps = {}) {
|
|
759
793
|
const flags = parseFlags(args);
|
|
@@ -763,6 +797,11 @@ export async function cmdOnNotification(args, deps = {}) {
|
|
|
763
797
|
: await (deps.readStdin ?? readStdinIfPipe)();
|
|
764
798
|
if (isClaudeHookImportedByCursor(source, hookStdin))
|
|
765
799
|
return 0;
|
|
800
|
+
const notificationType = parseClaudeNotificationType(hookStdin);
|
|
801
|
+
if (notificationType !== undefined &&
|
|
802
|
+
!CLAUDE_INPUT_NOTIFICATION_TYPES.has(notificationType)) {
|
|
803
|
+
return 0;
|
|
804
|
+
}
|
|
766
805
|
const forwarded = [
|
|
767
806
|
"--kind",
|
|
768
807
|
"awaiting_input",
|
package/dist/src/version.js
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
1
|
// Single source of truth for the CLI version. Keep in sync with package.json.
|
|
2
|
-
export const VERSION = "0.6.
|
|
2
|
+
export const VERSION = "0.6.6";
|
package/package.json
CHANGED