@a5c-ai/hooks-mux-adapter-cursor 5.0.1-staging.05ee168a

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 ADDED
@@ -0,0 +1,29 @@
1
+ # @a5c-ai/hooks-mux-adapter-cursor
2
+
3
+ Cursor harness adapter for hooks-mux.
4
+
5
+ ## Install
6
+
7
+ ```bash
8
+ npm install @a5c-ai/hooks-mux-adapter-cursor @a5c-ai/hooks-mux-core
9
+ ```
10
+
11
+ This package ships the built adapter runtime in `dist/` and this package README for npm publish-surface auditing.
12
+
13
+ ## Usage
14
+
15
+ ```ts
16
+ import {
17
+ createAdapter,
18
+ normalizeCursorEvent,
19
+ getActiveProfile,
20
+ } from "@a5c-ai/hooks-mux-adapter-cursor";
21
+ ```
22
+
23
+ The package exposes Cursor-specific normalization, capability profiles, phase mappings, rendering helpers, and session-resolution utilities for the hooks-mux execution pipeline.
24
+
25
+ See [`packages/hooks-mux/README.md`](../README.md) for the workspace overview and `packages/hooks-mux/docs/adapter-integration-guide.md` for end-to-end integration guidance.
26
+
27
+ ## License
28
+
29
+ MIT © a5c-ai
@@ -0,0 +1,13 @@
1
+ import type { AdapterCapabilities } from '@a5c-ai/hooks-mux-core';
2
+ /**
3
+ * Creates the Cursor adapter capability descriptor.
4
+ *
5
+ * Cursor is a shell-hook harness with a now-stable hook surface.
6
+ * Session IDs are derived (not natively provided), blocking
7
+ * is supported on preToolUse and stop, and env propagation
8
+ * is wrapper-based only.
9
+ *
10
+ * Spec section 17.5.
11
+ */
12
+ export declare function createAdapter(): AdapterCapabilities;
13
+ //# sourceMappingURL=adapter.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"adapter.d.ts","sourceRoot":"","sources":["../src/adapter.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,wBAAwB,CAAC;AAElE;;;;;;;;;GASG;AACH,wBAAgB,aAAa,IAAI,mBAAmB,CAmBnD"}
@@ -0,0 +1,34 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.createAdapter = createAdapter;
4
+ /**
5
+ * Creates the Cursor adapter capability descriptor.
6
+ *
7
+ * Cursor is a shell-hook harness with a now-stable hook surface.
8
+ * Session IDs are derived (not natively provided), blocking
9
+ * is supported on preToolUse and stop, and env propagation
10
+ * is wrapper-based only.
11
+ *
12
+ * Spec section 17.5.
13
+ */
14
+ function createAdapter() {
15
+ return {
16
+ name: 'cursor',
17
+ family: 'shell-hook',
18
+ sessionIdQuality: 'derived',
19
+ supportsOrderedFanout: true,
20
+ supportsNativeAdditionalContext: false,
21
+ supportsBlock: true,
22
+ supportsAsk: false,
23
+ supportsToolInputMutation: false,
24
+ supportsToolResultMutation: false,
25
+ supportsPersistedEnv: false,
26
+ envPersistenceMode: 'wrapper_only',
27
+ toolInterceptionScope: 'all',
28
+ notes: [
29
+ 'Hook surface is stable as of Cursor 3.0',
30
+ 'IDE and CLI share the same hook surface',
31
+ ],
32
+ };
33
+ }
34
+ //# sourceMappingURL=adapter.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"adapter.js","sourceRoot":"","sources":["../src/adapter.ts"],"names":[],"mappings":";;AAYA,sCAmBC;AA7BD;;;;;;;;;GASG;AACH,SAAgB,aAAa;IAC3B,OAAO;QACL,IAAI,EAAE,QAAQ;QACd,MAAM,EAAE,YAAY;QACpB,gBAAgB,EAAE,SAAS;QAC3B,qBAAqB,EAAE,IAAI;QAC3B,+BAA+B,EAAE,KAAK;QACtC,aAAa,EAAE,IAAI;QACnB,WAAW,EAAE,KAAK;QAClB,yBAAyB,EAAE,KAAK;QAChC,0BAA0B,EAAE,KAAK;QACjC,oBAAoB,EAAE,KAAK;QAC3B,kBAAkB,EAAE,cAAc;QAClC,qBAAqB,EAAE,KAAK;QAC5B,KAAK,EAAE;YACL,yCAAyC;YACzC,yCAAyC;SAC1C;KACF,CAAC;AACJ,CAAC"}
@@ -0,0 +1,81 @@
1
+ /**
2
+ * Capability profiles for the Cursor adapter.
3
+ *
4
+ * Cursor's hook surface evolves rapidly. This module allows
5
+ * overriding the default capability assumptions when the
6
+ * adapter's built-in profile doesn't match the actual Cursor
7
+ * version/mode being used.
8
+ *
9
+ * Spec section 17.5: "allow adapter version/profile overrides
10
+ * if Cursor behavior changes rapidly."
11
+ */
12
+ /**
13
+ * Describes what the current Cursor version/mode supports.
14
+ */
15
+ export interface CursorCapabilityProfile {
16
+ /** Profile name for diagnostics. */
17
+ name: string;
18
+ /** Cursor version range this profile applies to (informational). */
19
+ cursorVersion?: string;
20
+ /** Whether Cursor is running as IDE or CLI. */
21
+ mode: 'ide' | 'cli' | 'unknown';
22
+ /** Which native hook events are known to fire reliably. */
23
+ reliableEvents: string[];
24
+ /** Which native hook events exist but are unreliable or undocumented. */
25
+ unreliableEvents: string[];
26
+ /** Whether stop hook can actually continue the session. */
27
+ stopCanContinue: boolean;
28
+ /** Whether tool-level hooks are available at all. */
29
+ toolHooksAvailable: boolean;
30
+ /** Free-form notes about this profile's known limitations. */
31
+ notes: string[];
32
+ }
33
+ /**
34
+ * The default profile: based on the documented/stable Cursor
35
+ * hook surface as of mid-2026. All listed events are now
36
+ * documented as native hooks per Cursor's official docs.
37
+ */
38
+ export declare const DEFAULT_PROFILE: CursorCapabilityProfile;
39
+ /**
40
+ * A CLI-specific profile with the same capabilities as default.
41
+ * Retained for backward compatibility.
42
+ */
43
+ export declare const CLI_PERMISSIVE_PROFILE: CursorCapabilityProfile;
44
+ /**
45
+ * Get the currently active capability profile.
46
+ */
47
+ export declare function getActiveProfile(): CursorCapabilityProfile;
48
+ /**
49
+ * Override the active capability profile.
50
+ * Use this when deploying against a known Cursor version/mode
51
+ * that differs from the default conservative assumptions.
52
+ *
53
+ * @param profile - The profile to activate.
54
+ */
55
+ export declare function setActiveProfile(profile: CursorCapabilityProfile): void;
56
+ /**
57
+ * Reset to the default conservative profile.
58
+ */
59
+ export declare function resetProfile(): void;
60
+ /**
61
+ * Check whether a given native event name is considered reliable
62
+ * under the current profile.
63
+ */
64
+ export declare function isEventReliable(nativeEventName: string): boolean;
65
+ /**
66
+ * Check whether a given native event name is known at all
67
+ * (reliable or unreliable) under the current profile.
68
+ */
69
+ export declare function isEventKnown(nativeEventName: string): boolean;
70
+ /**
71
+ * Build a diagnostics summary of profile-related uncertainty
72
+ * for a given event. Used by the normalizer to annotate events.
73
+ */
74
+ export declare function getEventDiagnostics(nativeEventName: string): {
75
+ isReliable: boolean;
76
+ isKnown: boolean;
77
+ profileName: string;
78
+ mode: string;
79
+ warnings: string[];
80
+ };
81
+ //# sourceMappingURL=capability-profile.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"capability-profile.d.ts","sourceRoot":"","sources":["../src/capability-profile.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AAEH;;GAEG;AACH,MAAM,WAAW,uBAAuB;IACtC,oCAAoC;IACpC,IAAI,EAAE,MAAM,CAAC;IACb,oEAAoE;IACpE,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,+CAA+C;IAC/C,IAAI,EAAE,KAAK,GAAG,KAAK,GAAG,SAAS,CAAC;IAChC,2DAA2D;IAC3D,cAAc,EAAE,MAAM,EAAE,CAAC;IACzB,yEAAyE;IACzE,gBAAgB,EAAE,MAAM,EAAE,CAAC;IAC3B,2DAA2D;IAC3D,eAAe,EAAE,OAAO,CAAC;IACzB,qDAAqD;IACrD,kBAAkB,EAAE,OAAO,CAAC;IAC5B,8DAA8D;IAC9D,KAAK,EAAE,MAAM,EAAE,CAAC;CACjB;AAED;;;;GAIG;AACH,eAAO,MAAM,eAAe,EAAE,uBAW7B,CAAC;AAEF;;;GAGG;AACH,eAAO,MAAM,sBAAsB,EAAE,uBAUpC,CAAC;AAKF;;GAEG;AACH,wBAAgB,gBAAgB,IAAI,uBAAuB,CAE1D;AAED;;;;;;GAMG;AACH,wBAAgB,gBAAgB,CAAC,OAAO,EAAE,uBAAuB,GAAG,IAAI,CAEvE;AAED;;GAEG;AACH,wBAAgB,YAAY,IAAI,IAAI,CAEnC;AAED;;;GAGG;AACH,wBAAgB,eAAe,CAAC,eAAe,EAAE,MAAM,GAAG,OAAO,CAEhE;AAED;;;GAGG;AACH,wBAAgB,YAAY,CAAC,eAAe,EAAE,MAAM,GAAG,OAAO,CAK7D;AAED;;;GAGG;AACH,wBAAgB,mBAAmB,CAAC,eAAe,EAAE,MAAM,GAAG;IAC5D,UAAU,EAAE,OAAO,CAAC;IACpB,OAAO,EAAE,OAAO,CAAC;IACjB,WAAW,EAAE,MAAM,CAAC;IACpB,IAAI,EAAE,MAAM,CAAC;IACb,QAAQ,EAAE,MAAM,EAAE,CAAC;CACpB,CA8BA"}
@@ -0,0 +1,117 @@
1
+ "use strict";
2
+ /**
3
+ * Capability profiles for the Cursor adapter.
4
+ *
5
+ * Cursor's hook surface evolves rapidly. This module allows
6
+ * overriding the default capability assumptions when the
7
+ * adapter's built-in profile doesn't match the actual Cursor
8
+ * version/mode being used.
9
+ *
10
+ * Spec section 17.5: "allow adapter version/profile overrides
11
+ * if Cursor behavior changes rapidly."
12
+ */
13
+ Object.defineProperty(exports, "__esModule", { value: true });
14
+ exports.CLI_PERMISSIVE_PROFILE = exports.DEFAULT_PROFILE = void 0;
15
+ exports.getActiveProfile = getActiveProfile;
16
+ exports.setActiveProfile = setActiveProfile;
17
+ exports.resetProfile = resetProfile;
18
+ exports.isEventReliable = isEventReliable;
19
+ exports.isEventKnown = isEventKnown;
20
+ exports.getEventDiagnostics = getEventDiagnostics;
21
+ /**
22
+ * The default profile: based on the documented/stable Cursor
23
+ * hook surface as of mid-2026. All listed events are now
24
+ * documented as native hooks per Cursor's official docs.
25
+ */
26
+ exports.DEFAULT_PROFILE = {
27
+ name: 'default',
28
+ mode: 'unknown',
29
+ reliableEvents: ['sessionStart', 'sessionEnd', 'stop', 'preToolUse', 'postToolUse'],
30
+ unreliableEvents: [],
31
+ stopCanContinue: true,
32
+ toolHooksAvailable: true,
33
+ notes: [
34
+ 'All hook events are documented and stable as of Cursor 3.0',
35
+ 'IDE and CLI share the same event surface',
36
+ ],
37
+ };
38
+ /**
39
+ * A CLI-specific profile with the same capabilities as default.
40
+ * Retained for backward compatibility.
41
+ */
42
+ exports.CLI_PERMISSIVE_PROFILE = {
43
+ name: 'cli-permissive',
44
+ mode: 'cli',
45
+ reliableEvents: ['sessionStart', 'sessionEnd', 'stop', 'preToolUse', 'postToolUse'],
46
+ unreliableEvents: [],
47
+ stopCanContinue: true,
48
+ toolHooksAvailable: true,
49
+ notes: [
50
+ 'CLI mode with full hook support',
51
+ ],
52
+ };
53
+ /** Active profile — defaults to conservative. */
54
+ let activeProfile = { ...exports.DEFAULT_PROFILE };
55
+ /**
56
+ * Get the currently active capability profile.
57
+ */
58
+ function getActiveProfile() {
59
+ return activeProfile;
60
+ }
61
+ /**
62
+ * Override the active capability profile.
63
+ * Use this when deploying against a known Cursor version/mode
64
+ * that differs from the default conservative assumptions.
65
+ *
66
+ * @param profile - The profile to activate.
67
+ */
68
+ function setActiveProfile(profile) {
69
+ activeProfile = { ...profile };
70
+ }
71
+ /**
72
+ * Reset to the default conservative profile.
73
+ */
74
+ function resetProfile() {
75
+ activeProfile = { ...exports.DEFAULT_PROFILE };
76
+ }
77
+ /**
78
+ * Check whether a given native event name is considered reliable
79
+ * under the current profile.
80
+ */
81
+ function isEventReliable(nativeEventName) {
82
+ return activeProfile.reliableEvents.includes(nativeEventName);
83
+ }
84
+ /**
85
+ * Check whether a given native event name is known at all
86
+ * (reliable or unreliable) under the current profile.
87
+ */
88
+ function isEventKnown(nativeEventName) {
89
+ return (activeProfile.reliableEvents.includes(nativeEventName) ||
90
+ activeProfile.unreliableEvents.includes(nativeEventName));
91
+ }
92
+ /**
93
+ * Build a diagnostics summary of profile-related uncertainty
94
+ * for a given event. Used by the normalizer to annotate events.
95
+ */
96
+ function getEventDiagnostics(nativeEventName) {
97
+ const isReliable = activeProfile.reliableEvents.includes(nativeEventName);
98
+ const isKnown = isReliable || activeProfile.unreliableEvents.includes(nativeEventName);
99
+ const warnings = [];
100
+ if (!isKnown) {
101
+ warnings.push(`Event '${nativeEventName}' is not recognized by the '${activeProfile.name}' capability profile`);
102
+ }
103
+ else if (!isReliable) {
104
+ warnings.push(`Event '${nativeEventName}' is known but unreliable under the '${activeProfile.name}' profile`);
105
+ }
106
+ if (activeProfile.mode === 'unknown') {
107
+ warnings.push('Cursor mode (IDE vs CLI) is unknown; event behavior may vary');
108
+ }
109
+ return {
110
+ isReliable,
111
+ isKnown,
112
+ profileName: activeProfile.name,
113
+ mode: activeProfile.mode,
114
+ warnings,
115
+ };
116
+ }
117
+ //# sourceMappingURL=capability-profile.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"capability-profile.js","sourceRoot":"","sources":["../src/capability-profile.ts"],"names":[],"mappings":";AAAA;;;;;;;;;;GAUG;;;AAgEH,4CAEC;AASD,4CAEC;AAKD,oCAEC;AAMD,0CAEC;AAMD,oCAKC;AAMD,kDAoCC;AAzHD;;;;GAIG;AACU,QAAA,eAAe,GAA4B;IACtD,IAAI,EAAE,SAAS;IACf,IAAI,EAAE,SAAS;IACf,cAAc,EAAE,CAAC,cAAc,EAAE,YAAY,EAAE,MAAM,EAAE,YAAY,EAAE,aAAa,CAAC;IACnF,gBAAgB,EAAE,EAAE;IACpB,eAAe,EAAE,IAAI;IACrB,kBAAkB,EAAE,IAAI;IACxB,KAAK,EAAE;QACL,4DAA4D;QAC5D,0CAA0C;KAC3C;CACF,CAAC;AAEF;;;GAGG;AACU,QAAA,sBAAsB,GAA4B;IAC7D,IAAI,EAAE,gBAAgB;IACtB,IAAI,EAAE,KAAK;IACX,cAAc,EAAE,CAAC,cAAc,EAAE,YAAY,EAAE,MAAM,EAAE,YAAY,EAAE,aAAa,CAAC;IACnF,gBAAgB,EAAE,EAAE;IACpB,eAAe,EAAE,IAAI;IACrB,kBAAkB,EAAE,IAAI;IACxB,KAAK,EAAE;QACL,iCAAiC;KAClC;CACF,CAAC;AAEF,iDAAiD;AACjD,IAAI,aAAa,GAA4B,EAAE,GAAG,uBAAe,EAAE,CAAC;AAEpE;;GAEG;AACH,SAAgB,gBAAgB;IAC9B,OAAO,aAAa,CAAC;AACvB,CAAC;AAED;;;;;;GAMG;AACH,SAAgB,gBAAgB,CAAC,OAAgC;IAC/D,aAAa,GAAG,EAAE,GAAG,OAAO,EAAE,CAAC;AACjC,CAAC;AAED;;GAEG;AACH,SAAgB,YAAY;IAC1B,aAAa,GAAG,EAAE,GAAG,uBAAe,EAAE,CAAC;AACzC,CAAC;AAED;;;GAGG;AACH,SAAgB,eAAe,CAAC,eAAuB;IACrD,OAAO,aAAa,CAAC,cAAc,CAAC,QAAQ,CAAC,eAAe,CAAC,CAAC;AAChE,CAAC;AAED;;;GAGG;AACH,SAAgB,YAAY,CAAC,eAAuB;IAClD,OAAO,CACL,aAAa,CAAC,cAAc,CAAC,QAAQ,CAAC,eAAe,CAAC;QACtD,aAAa,CAAC,gBAAgB,CAAC,QAAQ,CAAC,eAAe,CAAC,CACzD,CAAC;AACJ,CAAC;AAED;;;GAGG;AACH,SAAgB,mBAAmB,CAAC,eAAuB;IAOzD,MAAM,UAAU,GAAG,aAAa,CAAC,cAAc,CAAC,QAAQ,CAAC,eAAe,CAAC,CAAC;IAC1E,MAAM,OAAO,GACX,UAAU,IAAI,aAAa,CAAC,gBAAgB,CAAC,QAAQ,CAAC,eAAe,CAAC,CAAC;IAEzE,MAAM,QAAQ,GAAa,EAAE,CAAC;IAE9B,IAAI,CAAC,OAAO,EAAE,CAAC;QACb,QAAQ,CAAC,IAAI,CACX,UAAU,eAAe,+BAA+B,aAAa,CAAC,IAAI,sBAAsB,CACjG,CAAC;IACJ,CAAC;SAAM,IAAI,CAAC,UAAU,EAAE,CAAC;QACvB,QAAQ,CAAC,IAAI,CACX,UAAU,eAAe,wCAAwC,aAAa,CAAC,IAAI,WAAW,CAC/F,CAAC;IACJ,CAAC;IAED,IAAI,aAAa,CAAC,IAAI,KAAK,SAAS,EAAE,CAAC;QACrC,QAAQ,CAAC,IAAI,CACX,8DAA8D,CAC/D,CAAC;IACJ,CAAC;IAED,OAAO;QACL,UAAU;QACV,OAAO;QACP,WAAW,EAAE,aAAa,CAAC,IAAI;QAC/B,IAAI,EAAE,aAAa,CAAC,IAAI;QACxB,QAAQ;KACT,CAAC;AACJ,CAAC"}
@@ -0,0 +1,10 @@
1
+ export { createAdapter } from './adapter';
2
+ export { getActiveProfile, setActiveProfile, resetProfile, isEventReliable, isEventKnown, getEventDiagnostics, DEFAULT_PROFILE, CLI_PERMISSIVE_PROFILE, } from './capability-profile';
3
+ export type { CursorCapabilityProfile } from './capability-profile';
4
+ export { CURSOR_PHASE_MAPPINGS, findMapping, getSupportedPhases } from './mappings';
5
+ export { normalizeCursorEvent, parseStdin, ADAPTER_NAME, } from './normalizer';
6
+ export type { CursorStdinBase, CursorSessionStartPayload, CursorStopPayload, CursorPreToolUsePayload, CursorPostToolUsePayload, } from './normalizer';
7
+ export { renderCursorOutput, isFieldSupportedForEvent } from './renderer';
8
+ export { resolveSessionId, deriveSessionId, isValidSessionId } from './session-resolver';
9
+ export type { SessionResolutionResult } from './session-resolver';
10
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,aAAa,EAAE,MAAM,WAAW,CAAC;AAG1C,OAAO,EACL,gBAAgB,EAChB,gBAAgB,EAChB,YAAY,EACZ,eAAe,EACf,YAAY,EACZ,mBAAmB,EACnB,eAAe,EACf,sBAAsB,GACvB,MAAM,sBAAsB,CAAC;AAC9B,YAAY,EAAE,uBAAuB,EAAE,MAAM,sBAAsB,CAAC;AAGpE,OAAO,EAAE,qBAAqB,EAAE,WAAW,EAAE,kBAAkB,EAAE,MAAM,YAAY,CAAC;AAGpF,OAAO,EACL,oBAAoB,EACpB,UAAU,EACV,YAAY,GACb,MAAM,cAAc,CAAC;AACtB,YAAY,EACV,eAAe,EACf,yBAAyB,EACzB,iBAAiB,EACjB,uBAAuB,EACvB,wBAAwB,GACzB,MAAM,cAAc,CAAC;AAGtB,OAAO,EAAE,kBAAkB,EAAE,wBAAwB,EAAE,MAAM,YAAY,CAAC;AAG1E,OAAO,EAAE,gBAAgB,EAAE,eAAe,EAAE,gBAAgB,EAAE,MAAM,oBAAoB,CAAC;AACzF,YAAY,EAAE,uBAAuB,EAAE,MAAM,oBAAoB,CAAC"}
package/dist/index.js ADDED
@@ -0,0 +1,36 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.isValidSessionId = exports.deriveSessionId = exports.resolveSessionId = exports.isFieldSupportedForEvent = exports.renderCursorOutput = exports.ADAPTER_NAME = exports.parseStdin = exports.normalizeCursorEvent = exports.getSupportedPhases = exports.findMapping = exports.CURSOR_PHASE_MAPPINGS = exports.CLI_PERMISSIVE_PROFILE = exports.DEFAULT_PROFILE = exports.getEventDiagnostics = exports.isEventKnown = exports.isEventReliable = exports.resetProfile = exports.setActiveProfile = exports.getActiveProfile = exports.createAdapter = void 0;
4
+ // Adapter capabilities
5
+ var adapter_1 = require("./adapter");
6
+ Object.defineProperty(exports, "createAdapter", { enumerable: true, get: function () { return adapter_1.createAdapter; } });
7
+ // Capability profile
8
+ var capability_profile_1 = require("./capability-profile");
9
+ Object.defineProperty(exports, "getActiveProfile", { enumerable: true, get: function () { return capability_profile_1.getActiveProfile; } });
10
+ Object.defineProperty(exports, "setActiveProfile", { enumerable: true, get: function () { return capability_profile_1.setActiveProfile; } });
11
+ Object.defineProperty(exports, "resetProfile", { enumerable: true, get: function () { return capability_profile_1.resetProfile; } });
12
+ Object.defineProperty(exports, "isEventReliable", { enumerable: true, get: function () { return capability_profile_1.isEventReliable; } });
13
+ Object.defineProperty(exports, "isEventKnown", { enumerable: true, get: function () { return capability_profile_1.isEventKnown; } });
14
+ Object.defineProperty(exports, "getEventDiagnostics", { enumerable: true, get: function () { return capability_profile_1.getEventDiagnostics; } });
15
+ Object.defineProperty(exports, "DEFAULT_PROFILE", { enumerable: true, get: function () { return capability_profile_1.DEFAULT_PROFILE; } });
16
+ Object.defineProperty(exports, "CLI_PERMISSIVE_PROFILE", { enumerable: true, get: function () { return capability_profile_1.CLI_PERMISSIVE_PROFILE; } });
17
+ // Phase mappings
18
+ var mappings_1 = require("./mappings");
19
+ Object.defineProperty(exports, "CURSOR_PHASE_MAPPINGS", { enumerable: true, get: function () { return mappings_1.CURSOR_PHASE_MAPPINGS; } });
20
+ Object.defineProperty(exports, "findMapping", { enumerable: true, get: function () { return mappings_1.findMapping; } });
21
+ Object.defineProperty(exports, "getSupportedPhases", { enumerable: true, get: function () { return mappings_1.getSupportedPhases; } });
22
+ // Normalizer
23
+ var normalizer_1 = require("./normalizer");
24
+ Object.defineProperty(exports, "normalizeCursorEvent", { enumerable: true, get: function () { return normalizer_1.normalizeCursorEvent; } });
25
+ Object.defineProperty(exports, "parseStdin", { enumerable: true, get: function () { return normalizer_1.parseStdin; } });
26
+ Object.defineProperty(exports, "ADAPTER_NAME", { enumerable: true, get: function () { return normalizer_1.ADAPTER_NAME; } });
27
+ // Renderer
28
+ var renderer_1 = require("./renderer");
29
+ Object.defineProperty(exports, "renderCursorOutput", { enumerable: true, get: function () { return renderer_1.renderCursorOutput; } });
30
+ Object.defineProperty(exports, "isFieldSupportedForEvent", { enumerable: true, get: function () { return renderer_1.isFieldSupportedForEvent; } });
31
+ // Session resolver
32
+ var session_resolver_1 = require("./session-resolver");
33
+ Object.defineProperty(exports, "resolveSessionId", { enumerable: true, get: function () { return session_resolver_1.resolveSessionId; } });
34
+ Object.defineProperty(exports, "deriveSessionId", { enumerable: true, get: function () { return session_resolver_1.deriveSessionId; } });
35
+ Object.defineProperty(exports, "isValidSessionId", { enumerable: true, get: function () { return session_resolver_1.isValidSessionId; } });
36
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";;;AAAA,uBAAuB;AACvB,qCAA0C;AAAjC,wGAAA,aAAa,OAAA;AAEtB,qBAAqB;AACrB,2DAS8B;AAR5B,sHAAA,gBAAgB,OAAA;AAChB,sHAAA,gBAAgB,OAAA;AAChB,kHAAA,YAAY,OAAA;AACZ,qHAAA,eAAe,OAAA;AACf,kHAAA,YAAY,OAAA;AACZ,yHAAA,mBAAmB,OAAA;AACnB,qHAAA,eAAe,OAAA;AACf,4HAAA,sBAAsB,OAAA;AAIxB,iBAAiB;AACjB,uCAAoF;AAA3E,iHAAA,qBAAqB,OAAA;AAAE,uGAAA,WAAW,OAAA;AAAE,8GAAA,kBAAkB,OAAA;AAE/D,aAAa;AACb,2CAIsB;AAHpB,kHAAA,oBAAoB,OAAA;AACpB,wGAAA,UAAU,OAAA;AACV,0GAAA,YAAY,OAAA;AAUd,WAAW;AACX,uCAA0E;AAAjE,8GAAA,kBAAkB,OAAA;AAAE,oHAAA,wBAAwB,OAAA;AAErD,mBAAmB;AACnB,uDAAyF;AAAhF,oHAAA,gBAAgB,OAAA;AAAE,mHAAA,eAAe,OAAA;AAAE,oHAAA,gBAAgB,OAAA"}
@@ -0,0 +1,20 @@
1
+ import type { PhaseMapping } from '@a5c-ai/hooks-mux-core';
2
+ /**
3
+ * Cursor native event to canonical phase mapping table.
4
+ *
5
+ * Cursor's hook surface is now documented and stable for both IDE and CLI.
6
+ * All listed events (sessionStart, sessionEnd, preToolUse, postToolUse, stop)
7
+ * are native hooks per Cursor's official docs.
8
+ *
9
+ * Spec section 17.5.
10
+ */
11
+ export declare const CURSOR_PHASE_MAPPINGS: PhaseMapping[];
12
+ /**
13
+ * Quick lookup from native event name to phase mapping.
14
+ */
15
+ export declare function findMapping(nativeEventName: string): PhaseMapping | undefined;
16
+ /**
17
+ * Get all canonical phases supported by the Cursor adapter.
18
+ */
19
+ export declare function getSupportedPhases(): string[];
20
+ //# sourceMappingURL=mappings.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"mappings.d.ts","sourceRoot":"","sources":["../src/mappings.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,wBAAwB,CAAC;AAE3D;;;;;;;;GAQG;AACH,eAAO,MAAM,qBAAqB,EAAE,YAAY,EAmD/C,CAAC;AAEF;;GAEG;AACH,wBAAgB,WAAW,CAAC,eAAe,EAAE,MAAM,GAAG,YAAY,GAAG,SAAS,CAE7E;AAED;;GAEG;AACH,wBAAgB,kBAAkB,IAAI,MAAM,EAAE,CAE7C"}
@@ -0,0 +1,77 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.CURSOR_PHASE_MAPPINGS = void 0;
4
+ exports.findMapping = findMapping;
5
+ exports.getSupportedPhases = getSupportedPhases;
6
+ /**
7
+ * Cursor native event to canonical phase mapping table.
8
+ *
9
+ * Cursor's hook surface is now documented and stable for both IDE and CLI.
10
+ * All listed events (sessionStart, sessionEnd, preToolUse, postToolUse, stop)
11
+ * are native hooks per Cursor's official docs.
12
+ *
13
+ * Spec section 17.5.
14
+ */
15
+ exports.CURSOR_PHASE_MAPPINGS = [
16
+ // --- Session lifecycle ---
17
+ {
18
+ canonicalPhase: 'session.start',
19
+ nativeHook: 'sessionStart',
20
+ supportLevel: 'native',
21
+ blockCapability: false,
22
+ mutationCapability: false,
23
+ scope: 'session',
24
+ notes: 'Documented and stable. Fires on session initialization.',
25
+ },
26
+ {
27
+ canonicalPhase: 'session.end',
28
+ nativeHook: 'sessionEnd',
29
+ supportLevel: 'native',
30
+ blockCapability: false,
31
+ mutationCapability: false,
32
+ scope: 'session',
33
+ notes: 'Fires on session end. Observer-only.',
34
+ },
35
+ // --- Turn lifecycle ---
36
+ {
37
+ canonicalPhase: 'turn.stop',
38
+ nativeHook: 'stop',
39
+ supportLevel: 'native',
40
+ blockCapability: true,
41
+ mutationCapability: false,
42
+ scope: 'turn',
43
+ notes: 'Documented and stable. Can continue session. Guard against recursion.',
44
+ },
45
+ // --- Tool lifecycle ---
46
+ {
47
+ canonicalPhase: 'tool.before',
48
+ nativeHook: 'preToolUse',
49
+ supportLevel: 'native',
50
+ blockCapability: true,
51
+ mutationCapability: false,
52
+ scope: 'tool',
53
+ notes: 'Documented and stable. Fires before tool execution. Can block (deny).',
54
+ },
55
+ {
56
+ canonicalPhase: 'tool.after',
57
+ nativeHook: 'postToolUse',
58
+ supportLevel: 'native',
59
+ blockCapability: false,
60
+ mutationCapability: false,
61
+ scope: 'tool',
62
+ notes: 'Documented and stable. Observer-only post-tool hook.',
63
+ },
64
+ ];
65
+ /**
66
+ * Quick lookup from native event name to phase mapping.
67
+ */
68
+ function findMapping(nativeEventName) {
69
+ return exports.CURSOR_PHASE_MAPPINGS.find((m) => m.nativeHook === nativeEventName);
70
+ }
71
+ /**
72
+ * Get all canonical phases supported by the Cursor adapter.
73
+ */
74
+ function getSupportedPhases() {
75
+ return exports.CURSOR_PHASE_MAPPINGS.map((m) => m.canonicalPhase);
76
+ }
77
+ //# sourceMappingURL=mappings.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"mappings.js","sourceRoot":"","sources":["../src/mappings.ts"],"names":[],"mappings":";;;AAmEA,kCAEC;AAKD,gDAEC;AA1ED;;;;;;;;GAQG;AACU,QAAA,qBAAqB,GAAmB;IACnD,4BAA4B;IAC5B;QACE,cAAc,EAAE,eAAe;QAC/B,UAAU,EAAE,cAAc;QAC1B,YAAY,EAAE,QAAQ;QACtB,eAAe,EAAE,KAAK;QACtB,kBAAkB,EAAE,KAAK;QACzB,KAAK,EAAE,SAAS;QAChB,KAAK,EAAE,yDAAyD;KACjE;IACD;QACE,cAAc,EAAE,aAAa;QAC7B,UAAU,EAAE,YAAY;QACxB,YAAY,EAAE,QAAQ;QACtB,eAAe,EAAE,KAAK;QACtB,kBAAkB,EAAE,KAAK;QACzB,KAAK,EAAE,SAAS;QAChB,KAAK,EAAE,sCAAsC;KAC9C;IAED,yBAAyB;IACzB;QACE,cAAc,EAAE,WAAW;QAC3B,UAAU,EAAE,MAAM;QAClB,YAAY,EAAE,QAAQ;QACtB,eAAe,EAAE,IAAI;QACrB,kBAAkB,EAAE,KAAK;QACzB,KAAK,EAAE,MAAM;QACb,KAAK,EAAE,uEAAuE;KAC/E;IAED,yBAAyB;IACzB;QACE,cAAc,EAAE,aAAa;QAC7B,UAAU,EAAE,YAAY;QACxB,YAAY,EAAE,QAAQ;QACtB,eAAe,EAAE,IAAI;QACrB,kBAAkB,EAAE,KAAK;QACzB,KAAK,EAAE,MAAM;QACb,KAAK,EAAE,uEAAuE;KAC/E;IACD;QACE,cAAc,EAAE,YAAY;QAC5B,UAAU,EAAE,aAAa;QACzB,YAAY,EAAE,QAAQ;QACtB,eAAe,EAAE,KAAK;QACtB,kBAAkB,EAAE,KAAK;QACzB,KAAK,EAAE,MAAM;QACb,KAAK,EAAE,sDAAsD;KAC9D;CACF,CAAC;AAEF;;GAEG;AACH,SAAgB,WAAW,CAAC,eAAuB;IACjD,OAAO,6BAAqB,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,UAAU,KAAK,eAAe,CAAC,CAAC;AAC7E,CAAC;AAED;;GAEG;AACH,SAAgB,kBAAkB;IAChC,OAAO,6BAAqB,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,cAAc,CAAC,CAAC;AAC5D,CAAC"}
@@ -0,0 +1,56 @@
1
+ import { type UnifiedHookEvent } from '@a5c-ai/hooks-mux-core';
2
+ /** The adapter identifier used in all normalized events. */
3
+ export declare const ADAPTER_NAME = "cursor";
4
+ /**
5
+ * Common fields that may be present on Cursor hook stdin payloads.
6
+ * Cursor's stdin format is not fully documented; fields may be
7
+ * absent or undefined. The normalizer handles all cases gracefully.
8
+ */
9
+ export interface CursorStdinBase {
10
+ cwd?: string;
11
+ workspace?: string;
12
+ model?: string;
13
+ [key: string]: unknown;
14
+ }
15
+ /** SessionStart-specific fields. */
16
+ export interface CursorSessionStartPayload extends CursorStdinBase {
17
+ source?: string;
18
+ }
19
+ /** Stop-specific fields. */
20
+ export interface CursorStopPayload extends CursorStdinBase {
21
+ reason?: string;
22
+ stop_hook_active?: boolean;
23
+ }
24
+ /** PreToolUse-specific fields (when available). */
25
+ export interface CursorPreToolUsePayload extends CursorStdinBase {
26
+ tool_name?: string;
27
+ tool_call_id?: string;
28
+ tool_input?: unknown;
29
+ }
30
+ /** PostToolUse-specific fields (when available). */
31
+ export interface CursorPostToolUsePayload extends CursorStdinBase {
32
+ tool_name?: string;
33
+ tool_call_id?: string;
34
+ tool_input?: unknown;
35
+ tool_response?: unknown;
36
+ }
37
+ /**
38
+ * Parse raw stdin input into a typed object.
39
+ * Cursor hooks receive JSON on stdin. If parsing fails, return empty
40
+ * object (fail-open: Cursor's payload format is not fully documented).
41
+ */
42
+ export declare function parseStdin(raw: unknown): Record<string, unknown>;
43
+ /**
44
+ * Normalize a raw Cursor hook invocation into a UnifiedHookEvent.
45
+ *
46
+ * Cursor's hook surface is experimental. The normalizer:
47
+ * - Parses stdin gracefully (fail-open on missing/malformed fields)
48
+ * - Annotates events with capability profile diagnostics
49
+ * - Enriches env from stdin payload fields
50
+ *
51
+ * @param rawEventName - The native Cursor event name (e.g. 'sessionStart', 'stop')
52
+ * @param stdinPayload - Raw stdin content (string or parsed object)
53
+ * @param env - Environment variables at invocation time
54
+ */
55
+ export declare function normalizeCursorEvent(rawEventName: string, stdinPayload: unknown, env?: Record<string, string>): UnifiedHookEvent;
56
+ //# sourceMappingURL=normalizer.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"normalizer.d.ts","sourceRoot":"","sources":["../src/normalizer.ts"],"names":[],"mappings":"AAAA,OAAO,EAAkB,KAAK,gBAAgB,EAAyB,MAAM,wBAAwB,CAAC;AAItG,4DAA4D;AAC5D,eAAO,MAAM,YAAY,WAAW,CAAC;AAErC;;;;GAIG;AACH,MAAM,WAAW,eAAe;IAC9B,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC;CACxB;AAED,oCAAoC;AACpC,MAAM,WAAW,yBAA0B,SAAQ,eAAe;IAChE,MAAM,CAAC,EAAE,MAAM,CAAC;CACjB;AAED,4BAA4B;AAC5B,MAAM,WAAW,iBAAkB,SAAQ,eAAe;IACxD,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,gBAAgB,CAAC,EAAE,OAAO,CAAC;CAC5B;AAED,mDAAmD;AACnD,MAAM,WAAW,uBAAwB,SAAQ,eAAe;IAC9D,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,UAAU,CAAC,EAAE,OAAO,CAAC;CACtB;AAED,oDAAoD;AACpD,MAAM,WAAW,wBAAyB,SAAQ,eAAe;IAC/D,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,UAAU,CAAC,EAAE,OAAO,CAAC;IACrB,aAAa,CAAC,EAAE,OAAO,CAAC;CACzB;AAED;;;;GAIG;AACH,wBAAgB,UAAU,CAAC,GAAG,EAAE,OAAO,GAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAiBhE;AAgBD;;;;;;;;;;;GAWG;AACH,wBAAgB,oBAAoB,CAClC,YAAY,EAAE,MAAM,EACpB,YAAY,EAAE,OAAO,EACrB,GAAG,GAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAM,GAC/B,gBAAgB,CAoDlB"}
@@ -0,0 +1,104 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.ADAPTER_NAME = void 0;
4
+ exports.parseStdin = parseStdin;
5
+ exports.normalizeCursorEvent = normalizeCursorEvent;
6
+ const hooks_mux_core_1 = require("@a5c-ai/hooks-mux-core");
7
+ const mappings_1 = require("./mappings");
8
+ const capability_profile_1 = require("./capability-profile");
9
+ /** The adapter identifier used in all normalized events. */
10
+ exports.ADAPTER_NAME = 'cursor';
11
+ /**
12
+ * Parse raw stdin input into a typed object.
13
+ * Cursor hooks receive JSON on stdin. If parsing fails, return empty
14
+ * object (fail-open: Cursor's payload format is not fully documented).
15
+ */
16
+ function parseStdin(raw) {
17
+ if (raw == null)
18
+ return {};
19
+ if (typeof raw === 'string') {
20
+ try {
21
+ const parsed = JSON.parse(raw);
22
+ if (typeof parsed === 'object' && parsed !== null && !Array.isArray(parsed)) {
23
+ return parsed;
24
+ }
25
+ }
26
+ catch {
27
+ // fail open -- Cursor payload format is uncertain
28
+ }
29
+ return {};
30
+ }
31
+ if (typeof raw === 'object' && !Array.isArray(raw)) {
32
+ return raw;
33
+ }
34
+ return {};
35
+ }
36
+ /**
37
+ * Extract tool metadata from a preToolUse/postToolUse payload.
38
+ */
39
+ function extractToolFields(payload) {
40
+ const fields = {};
41
+ if (typeof payload['tool_name'] === 'string') {
42
+ fields['HOOKS_PROXY_TOOL_NAME'] = payload['tool_name'];
43
+ }
44
+ if (typeof payload['tool_call_id'] === 'string') {
45
+ fields['HOOKS_PROXY_TOOL_CALL_ID'] = payload['tool_call_id'];
46
+ }
47
+ return fields;
48
+ }
49
+ /**
50
+ * Normalize a raw Cursor hook invocation into a UnifiedHookEvent.
51
+ *
52
+ * Cursor's hook surface is experimental. The normalizer:
53
+ * - Parses stdin gracefully (fail-open on missing/malformed fields)
54
+ * - Annotates events with capability profile diagnostics
55
+ * - Enriches env from stdin payload fields
56
+ *
57
+ * @param rawEventName - The native Cursor event name (e.g. 'sessionStart', 'stop')
58
+ * @param stdinPayload - Raw stdin content (string or parsed object)
59
+ * @param env - Environment variables at invocation time
60
+ */
61
+ function normalizeCursorEvent(rawEventName, stdinPayload, env = {}) {
62
+ const parsed = parseStdin(stdinPayload);
63
+ // Enrich env with Cursor-specific fields extracted from stdin
64
+ const enrichedEnv = { ...env };
65
+ // Cursor does not provide a native session_id -- derive from workspace/cwd
66
+ if (typeof parsed['cwd'] === 'string' && !enrichedEnv['HOOKS_PROXY_CWD']) {
67
+ enrichedEnv['HOOKS_PROXY_CWD'] = parsed['cwd'];
68
+ }
69
+ if (typeof parsed['workspace'] === 'string' && !enrichedEnv['HOOKS_PROXY_WORKTREE']) {
70
+ enrichedEnv['HOOKS_PROXY_WORKTREE'] = parsed['workspace'];
71
+ }
72
+ if (typeof parsed['model'] === 'string' && !enrichedEnv['HOOKS_PROXY_MODEL']) {
73
+ enrichedEnv['HOOKS_PROXY_MODEL'] = parsed['model'];
74
+ }
75
+ if (typeof parsed['source'] === 'string' && !enrichedEnv['HOOKS_PROXY_SOURCE']) {
76
+ enrichedEnv['HOOKS_PROXY_SOURCE'] = parsed['source'];
77
+ }
78
+ // Tool-specific env enrichment
79
+ if (rawEventName === 'preToolUse' || rawEventName === 'postToolUse') {
80
+ const toolFields = extractToolFields(parsed);
81
+ for (const [k, v] of Object.entries(toolFields)) {
82
+ if (!enrichedEnv[k]) {
83
+ enrichedEnv[k] = v;
84
+ }
85
+ }
86
+ }
87
+ const options = {
88
+ adapter: exports.ADAPTER_NAME,
89
+ rawEventName,
90
+ stdinPayload: parsed,
91
+ env: enrichedEnv,
92
+ adapterMappings: mappings_1.CURSOR_PHASE_MAPPINGS,
93
+ };
94
+ const event = (0, hooks_mux_core_1.normalizeEvent)(options);
95
+ // Annotate with capability profile diagnostics
96
+ const diagnostics = (0, capability_profile_1.getEventDiagnostics)(rawEventName);
97
+ event.execution.metadata = {
98
+ ...event.execution.metadata,
99
+ cursorDiagnostics: diagnostics,
100
+ experimental: true,
101
+ };
102
+ return event;
103
+ }
104
+ //# sourceMappingURL=normalizer.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"normalizer.js","sourceRoot":"","sources":["../src/normalizer.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,20 @@
1
+ import type { MergedExecutionResult } from '@a5c-ai/hooks-mux-core';
2
+ /**
3
+ * Render a merged execution result into Cursor-native output JSON.
4
+ *
5
+ * Only includes fields that are known to be processed for the given
6
+ * native event type. Unsupported fields are silently dropped.
7
+ *
8
+ * @param mergedResult - The merged result from multi-hook fan-out
9
+ * @param nativeEventName - The original Cursor event name
10
+ * @returns Cursor-native output object, and list of dropped fields
11
+ */
12
+ export declare function renderCursorOutput(mergedResult: MergedExecutionResult, nativeEventName: string): {
13
+ output: Record<string, unknown>;
14
+ droppedFields: string[];
15
+ };
16
+ /**
17
+ * Check whether a given output field is supported for a native event.
18
+ */
19
+ export declare function isFieldSupportedForEvent(field: string, nativeEventName: string): boolean;
20
+ //# sourceMappingURL=renderer.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"renderer.d.ts","sourceRoot":"","sources":["../src/renderer.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,qBAAqB,EAAE,MAAM,wBAAwB,CAAC;AA4CpE;;;;;;;;;GASG;AACH,wBAAgB,kBAAkB,CAChC,YAAY,EAAE,qBAAqB,EACnC,eAAe,EAAE,MAAM,GACtB;IAAE,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IAAC,aAAa,EAAE,MAAM,EAAE,CAAA;CAAE,CAwB9D;AAED;;GAEG;AACH,wBAAgB,wBAAwB,CAAC,KAAK,EAAE,MAAM,EAAE,eAAe,EAAE,MAAM,GAAG,OAAO,CAGxF"}
@@ -0,0 +1,81 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.renderCursorOutput = renderCursorOutput;
4
+ exports.isFieldSupportedForEvent = isFieldSupportedForEvent;
5
+ /**
6
+ * Cursor native output fields that are documented/supported per event type.
7
+ *
8
+ * Cursor output semantics are limited and not fully documented.
9
+ * Only emit fields that are known to be processed by the Cursor runtime.
10
+ * Unknown/unsupported fields are silently dropped (fail-open, conservative).
11
+ *
12
+ * Spec section 17.5: "render output conservatively, only emitting fields
13
+ * known to be processed."
14
+ */
15
+ /** Output fields supported on stop. */
16
+ const STOP_FIELDS = new Set([
17
+ 'continueSession',
18
+ 'stopReason',
19
+ 'reason',
20
+ ]);
21
+ /** Output fields supported on sessionStart (mostly ignored). */
22
+ const SESSION_START_FIELDS = new Set([
23
+ 'reason',
24
+ ]);
25
+ /** Output fields supported on preToolUse (when available). */
26
+ const PRE_TOOL_USE_FIELDS = new Set([
27
+ 'decision',
28
+ 'reason',
29
+ ]);
30
+ /** Output fields supported on postToolUse (when available). */
31
+ const POST_TOOL_USE_FIELDS = new Set([
32
+ 'reason',
33
+ ]);
34
+ /** Map native event names to their supported output field sets. */
35
+ const SUPPORTED_FIELDS_BY_EVENT = {
36
+ sessionStart: SESSION_START_FIELDS,
37
+ stop: STOP_FIELDS,
38
+ preToolUse: PRE_TOOL_USE_FIELDS,
39
+ postToolUse: POST_TOOL_USE_FIELDS,
40
+ };
41
+ /**
42
+ * Render a merged execution result into Cursor-native output JSON.
43
+ *
44
+ * Only includes fields that are known to be processed for the given
45
+ * native event type. Unsupported fields are silently dropped.
46
+ *
47
+ * @param mergedResult - The merged result from multi-hook fan-out
48
+ * @param nativeEventName - The original Cursor event name
49
+ * @returns Cursor-native output object, and list of dropped fields
50
+ */
51
+ function renderCursorOutput(mergedResult, nativeEventName) {
52
+ const supportedFields = SUPPORTED_FIELDS_BY_EVENT[nativeEventName] ?? new Set();
53
+ const output = {};
54
+ const droppedFields = [];
55
+ // Candidate output fields from the merged result
56
+ const candidates = [
57
+ { key: 'decision', value: mergedResult.decision, isEmpty: mergedResult.decision === 'noop' },
58
+ { key: 'reason', value: mergedResult.reason, isEmpty: !mergedResult.reason },
59
+ { key: 'continueSession', value: mergedResult.continueSession, isEmpty: mergedResult.continueSession === true },
60
+ { key: 'stopReason', value: mergedResult.stopReason, isEmpty: !mergedResult.stopReason },
61
+ ];
62
+ for (const candidate of candidates) {
63
+ if (candidate.isEmpty)
64
+ continue;
65
+ if (supportedFields.has(candidate.key)) {
66
+ output[candidate.key] = candidate.value;
67
+ }
68
+ else {
69
+ droppedFields.push(candidate.key);
70
+ }
71
+ }
72
+ return { output, droppedFields };
73
+ }
74
+ /**
75
+ * Check whether a given output field is supported for a native event.
76
+ */
77
+ function isFieldSupportedForEvent(field, nativeEventName) {
78
+ const supported = SUPPORTED_FIELDS_BY_EVENT[nativeEventName];
79
+ return supported ? supported.has(field) : false;
80
+ }
81
+ //# sourceMappingURL=renderer.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"renderer.js","sourceRoot":"","sources":["../src/renderer.ts"],"names":[],"mappings":";;AAsDA,gDA2BC;AAKD,4DAGC;AAvFD;;;;;;;;;GASG;AAEH,uCAAuC;AACvC,MAAM,WAAW,GAAG,IAAI,GAAG,CAAC;IAC1B,iBAAiB;IACjB,YAAY;IACZ,QAAQ;CACT,CAAC,CAAC;AAEH,gEAAgE;AAChE,MAAM,oBAAoB,GAAG,IAAI,GAAG,CAAC;IACnC,QAAQ;CACT,CAAC,CAAC;AAEH,8DAA8D;AAC9D,MAAM,mBAAmB,GAAG,IAAI,GAAG,CAAC;IAClC,UAAU;IACV,QAAQ;CACT,CAAC,CAAC;AAEH,+DAA+D;AAC/D,MAAM,oBAAoB,GAAG,IAAI,GAAG,CAAC;IACnC,QAAQ;CACT,CAAC,CAAC;AAEH,mEAAmE;AACnE,MAAM,yBAAyB,GAAgC;IAC7D,YAAY,EAAE,oBAAoB;IAClC,IAAI,EAAE,WAAW;IACjB,UAAU,EAAE,mBAAmB;IAC/B,WAAW,EAAE,oBAAoB;CAClC,CAAC;AAEF;;;;;;;;;GASG;AACH,SAAgB,kBAAkB,CAChC,YAAmC,EACnC,eAAuB;IAEvB,MAAM,eAAe,GAAG,yBAAyB,CAAC,eAAe,CAAC,IAAI,IAAI,GAAG,EAAU,CAAC;IACxF,MAAM,MAAM,GAA4B,EAAE,CAAC;IAC3C,MAAM,aAAa,GAAa,EAAE,CAAC;IAEnC,iDAAiD;IACjD,MAAM,UAAU,GAA6D;QAC3E,EAAE,GAAG,EAAE,UAAU,EAAE,KAAK,EAAE,YAAY,CAAC,QAAQ,EAAE,OAAO,EAAE,YAAY,CAAC,QAAQ,KAAK,MAAM,EAAE;QAC5F,EAAE,GAAG,EAAE,QAAQ,EAAE,KAAK,EAAE,YAAY,CAAC,MAAM,EAAE,OAAO,EAAE,CAAC,YAAY,CAAC,MAAM,EAAE;QAC5E,EAAE,GAAG,EAAE,iBAAiB,EAAE,KAAK,EAAE,YAAY,CAAC,eAAe,EAAE,OAAO,EAAE,YAAY,CAAC,eAAe,KAAK,IAAI,EAAE;QAC/G,EAAE,GAAG,EAAE,YAAY,EAAE,KAAK,EAAE,YAAY,CAAC,UAAU,EAAE,OAAO,EAAE,CAAC,YAAY,CAAC,UAAU,EAAE;KACzF,CAAC;IAEF,KAAK,MAAM,SAAS,IAAI,UAAU,EAAE,CAAC;QACnC,IAAI,SAAS,CAAC,OAAO;YAAE,SAAS;QAEhC,IAAI,eAAe,CAAC,GAAG,CAAC,SAAS,CAAC,GAAG,CAAC,EAAE,CAAC;YACvC,MAAM,CAAC,SAAS,CAAC,GAAG,CAAC,GAAG,SAAS,CAAC,KAAK,CAAC;QAC1C,CAAC;aAAM,CAAC;YACN,aAAa,CAAC,IAAI,CAAC,SAAS,CAAC,GAAG,CAAC,CAAC;QACpC,CAAC;IACH,CAAC;IAED,OAAO,EAAE,MAAM,EAAE,aAAa,EAAE,CAAC;AACnC,CAAC;AAED;;GAEG;AACH,SAAgB,wBAAwB,CAAC,KAAa,EAAE,eAAuB;IAC7E,MAAM,SAAS,GAAG,yBAAyB,CAAC,eAAe,CAAC,CAAC;IAC7D,OAAO,SAAS,CAAC,CAAC,CAAC,SAAS,CAAC,GAAG,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC;AAClD,CAAC"}
@@ -0,0 +1,36 @@
1
+ /**
2
+ * Resolve session ID from Cursor hook invocation context.
3
+ *
4
+ * Cursor does NOT provide a native session_id in stdin payloads,
5
+ * giving it 'derived' sessionIdQuality in the capability model.
6
+ * The session ID is derived from workspace/cwd as a stable hash.
7
+ *
8
+ * Resolution precedence (per spec 9.2):
9
+ * 1. Explicit AGENT_SESSION_ID env var
10
+ * 2. CURSOR_SESSION_ID env var (Cursor-specific, if ever provided)
11
+ * 3. Derived from workspace or cwd via stable hash
12
+ * 4. null (no session available)
13
+ */
14
+ export interface SessionResolutionResult {
15
+ sessionId: string | null;
16
+ source: 'explicit_env' | 'cursor_env' | 'derived' | 'none';
17
+ /** Whether the ID was derived (hashed) rather than provided natively. */
18
+ isDerived: boolean;
19
+ }
20
+ /**
21
+ * Resolve the session ID for a Cursor hook invocation.
22
+ *
23
+ * @param stdinPayload - Parsed stdin JSON payload from Cursor
24
+ * @param env - Environment variables at invocation time
25
+ */
26
+ export declare function resolveSessionId(stdinPayload: Record<string, unknown>, env?: Record<string, string>): SessionResolutionResult;
27
+ /**
28
+ * Derive a stable session ID from a workspace or directory path.
29
+ * Uses a truncated SHA-256 hash prefixed with 'cursor-' for identifiability.
30
+ */
31
+ export declare function deriveSessionId(path: string): string;
32
+ /**
33
+ * Validate that a session ID looks reasonable.
34
+ */
35
+ export declare function isValidSessionId(sessionId: string): boolean;
36
+ //# sourceMappingURL=session-resolver.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"session-resolver.d.ts","sourceRoot":"","sources":["../src/session-resolver.ts"],"names":[],"mappings":"AAEA;;;;;;;;;;;;GAYG;AAEH,MAAM,WAAW,uBAAuB;IACtC,SAAS,EAAE,MAAM,GAAG,IAAI,CAAC;IACzB,MAAM,EAAE,cAAc,GAAG,YAAY,GAAG,SAAS,GAAG,MAAM,CAAC;IAC3D,yEAAyE;IACzE,SAAS,EAAE,OAAO,CAAC;CACpB;AAED;;;;;GAKG;AACH,wBAAgB,gBAAgB,CAC9B,YAAY,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EACrC,GAAG,GAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAM,GAC/B,uBAAuB,CA6BzB;AAED;;;GAGG;AACH,wBAAgB,eAAe,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAGpD;AAED;;GAEG;AACH,wBAAgB,gBAAgB,CAAC,SAAS,EAAE,MAAM,GAAG,OAAO,CAE3D"}
@@ -0,0 +1,53 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.resolveSessionId = resolveSessionId;
4
+ exports.deriveSessionId = deriveSessionId;
5
+ exports.isValidSessionId = isValidSessionId;
6
+ const crypto_1 = require("crypto");
7
+ /**
8
+ * Resolve the session ID for a Cursor hook invocation.
9
+ *
10
+ * @param stdinPayload - Parsed stdin JSON payload from Cursor
11
+ * @param env - Environment variables at invocation time
12
+ */
13
+ function resolveSessionId(stdinPayload, env = {}) {
14
+ // Priority 1: explicit env override
15
+ const explicit = env['AGENT_SESSION_ID'];
16
+ if (typeof explicit === 'string' && explicit.length > 0) {
17
+ return { sessionId: explicit, source: 'explicit_env', isDerived: false };
18
+ }
19
+ // Priority 2: Cursor-specific env var (if Cursor ever adds one)
20
+ const cursorEnv = env['CURSOR_SESSION_ID'];
21
+ if (typeof cursorEnv === 'string' && cursorEnv.length > 0) {
22
+ return { sessionId: cursorEnv, source: 'cursor_env', isDerived: false };
23
+ }
24
+ // Priority 3: derive from workspace or cwd
25
+ const workspace = typeof stdinPayload['workspace'] === 'string'
26
+ ? stdinPayload['workspace']
27
+ : undefined;
28
+ const cwd = typeof stdinPayload['cwd'] === 'string'
29
+ ? stdinPayload['cwd']
30
+ : env['PWD'] ?? env['HOMEDRIVE'] ?? undefined;
31
+ const derivationSource = workspace ?? cwd;
32
+ if (derivationSource) {
33
+ const derived = deriveSessionId(derivationSource);
34
+ return { sessionId: derived, source: 'derived', isDerived: true };
35
+ }
36
+ // Priority 4: no session
37
+ return { sessionId: null, source: 'none', isDerived: false };
38
+ }
39
+ /**
40
+ * Derive a stable session ID from a workspace or directory path.
41
+ * Uses a truncated SHA-256 hash prefixed with 'cursor-' for identifiability.
42
+ */
43
+ function deriveSessionId(path) {
44
+ const hash = (0, crypto_1.createHash)('sha256').update(path).digest('hex').slice(0, 16);
45
+ return `cursor-${hash}`;
46
+ }
47
+ /**
48
+ * Validate that a session ID looks reasonable.
49
+ */
50
+ function isValidSessionId(sessionId) {
51
+ return sessionId.length > 0 && sessionId.length <= 256;
52
+ }
53
+ //# sourceMappingURL=session-resolver.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"session-resolver.js","sourceRoot":"","sources":["../src/session-resolver.ts"],"names":[],"mappings":";;AA6BA,4CAgCC;AAMD,0CAGC;AAKD,4CAEC;AA7ED,mCAAoC;AAuBpC;;;;;GAKG;AACH,SAAgB,gBAAgB,CAC9B,YAAqC,EACrC,MAA8B,EAAE;IAEhC,oCAAoC;IACpC,MAAM,QAAQ,GAAG,GAAG,CAAC,kBAAkB,CAAC,CAAC;IACzC,IAAI,OAAO,QAAQ,KAAK,QAAQ,IAAI,QAAQ,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;QACxD,OAAO,EAAE,SAAS,EAAE,QAAQ,EAAE,MAAM,EAAE,cAAc,EAAE,SAAS,EAAE,KAAK,EAAE,CAAC;IAC3E,CAAC;IAED,gEAAgE;IAChE,MAAM,SAAS,GAAG,GAAG,CAAC,mBAAmB,CAAC,CAAC;IAC3C,IAAI,OAAO,SAAS,KAAK,QAAQ,IAAI,SAAS,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;QAC1D,OAAO,EAAE,SAAS,EAAE,SAAS,EAAE,MAAM,EAAE,YAAY,EAAE,SAAS,EAAE,KAAK,EAAE,CAAC;IAC1E,CAAC;IAED,2CAA2C;IAC3C,MAAM,SAAS,GAAG,OAAO,YAAY,CAAC,WAAW,CAAC,KAAK,QAAQ;QAC7D,CAAC,CAAC,YAAY,CAAC,WAAW,CAAC;QAC3B,CAAC,CAAC,SAAS,CAAC;IACd,MAAM,GAAG,GAAG,OAAO,YAAY,CAAC,KAAK,CAAC,KAAK,QAAQ;QACjD,CAAC,CAAC,YAAY,CAAC,KAAK,CAAC;QACrB,CAAC,CAAC,GAAG,CAAC,KAAK,CAAC,IAAI,GAAG,CAAC,WAAW,CAAC,IAAI,SAAS,CAAC;IAEhD,MAAM,gBAAgB,GAAG,SAAS,IAAI,GAAG,CAAC;IAC1C,IAAI,gBAAgB,EAAE,CAAC;QACrB,MAAM,OAAO,GAAG,eAAe,CAAC,gBAAgB,CAAC,CAAC;QAClD,OAAO,EAAE,SAAS,EAAE,OAAO,EAAE,MAAM,EAAE,SAAS,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC;IACpE,CAAC;IAED,yBAAyB;IACzB,OAAO,EAAE,SAAS,EAAE,IAAI,EAAE,MAAM,EAAE,MAAM,EAAE,SAAS,EAAE,KAAK,EAAE,CAAC;AAC/D,CAAC;AAED;;;GAGG;AACH,SAAgB,eAAe,CAAC,IAAY;IAC1C,MAAM,IAAI,GAAG,IAAA,mBAAU,EAAC,QAAQ,CAAC,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC,KAAK,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC;IAC1E,OAAO,UAAU,IAAI,EAAE,CAAC;AAC1B,CAAC;AAED;;GAEG;AACH,SAAgB,gBAAgB,CAAC,SAAiB;IAChD,OAAO,SAAS,CAAC,MAAM,GAAG,CAAC,IAAI,SAAS,CAAC,MAAM,IAAI,GAAG,CAAC;AACzD,CAAC"}
package/package.json ADDED
@@ -0,0 +1,40 @@
1
+ {
2
+ "name": "@a5c-ai/hooks-mux-adapter-cursor",
3
+ "version": "5.0.1-staging.05ee168a",
4
+ "description": "Cursor harness adapter for the hooks-mux system",
5
+ "license": "MIT",
6
+ "type": "commonjs",
7
+ "main": "dist/index.js",
8
+ "types": "dist/index.d.ts",
9
+ "publishConfig": {
10
+ "access": "public"
11
+ },
12
+ "repository": {
13
+ "type": "git",
14
+ "url": "git+https://github.com/a5c-ai/babysitter.git",
15
+ "directory": "packages/hooks-mux/adapter-cursor"
16
+ },
17
+ "homepage": "https://github.com/a5c-ai/babysitter/tree/main/packages/hooks-mux/adapter-cursor#readme",
18
+ "bugs": {
19
+ "url": "https://github.com/a5c-ai/babysitter/issues"
20
+ },
21
+ "files": [
22
+ "dist",
23
+ "README.md"
24
+ ],
25
+ "scripts": {
26
+ "build": "tsc -p tsconfig.json",
27
+ "clean": "rimraf dist",
28
+ "lint": "eslint \"src/**/*.ts\" --max-warnings=0",
29
+ "test": "vitest run",
30
+ "test:watch": "vitest"
31
+ },
32
+ "dependencies": {
33
+ "@a5c-ai/hooks-mux-core": "5.0.1-staging.05ee168a"
34
+ },
35
+ "devDependencies": {
36
+ "typescript": "^5.7.0",
37
+ "vitest": "^3.0.0",
38
+ "rimraf": "^6.0.0"
39
+ }
40
+ }