@a5c-ai/hooks-mux-adapter-cursor 5.0.1-staging.00fa5317c
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 +29 -0
- package/dist/adapter.d.ts +3 -0
- package/dist/adapter.d.ts.map +1 -0
- package/dist/adapter.js +35 -0
- package/dist/adapter.js.map +1 -0
- package/dist/capability-profile.d.ts +81 -0
- package/dist/capability-profile.d.ts.map +1 -0
- package/dist/capability-profile.js +117 -0
- package/dist/capability-profile.js.map +1 -0
- package/dist/index.d.ts +10 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +37 -0
- package/dist/index.js.map +1 -0
- package/dist/mappings.d.ts +11 -0
- package/dist/mappings.d.ts.map +1 -0
- package/dist/mappings.js +64 -0
- package/dist/mappings.js.map +1 -0
- package/dist/normalizer.d.ts +58 -0
- package/dist/normalizer.d.ts.map +1 -0
- package/dist/normalizer.js +111 -0
- package/dist/normalizer.js.map +1 -0
- package/dist/renderer.d.ts +20 -0
- package/dist/renderer.d.ts.map +1 -0
- package/dist/renderer.js +81 -0
- package/dist/renderer.js.map +1 -0
- package/dist/session-resolver.d.ts +36 -0
- package/dist/session-resolver.d.ts.map +1 -0
- package/dist/session-resolver.js +53 -0
- package/dist/session-resolver.js.map +1 -0
- package/package.json +40 -0
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 @@
|
|
|
1
|
+
{"version":3,"file":"adapter.d.ts","sourceRoot":"","sources":["../src/adapter.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,wBAAwB,CAAC;AAalE,wBAAgB,aAAa,CAAC,IAAI,GAAE,MAA6B,GAAG,mBAAmB,CAoBtF"}
|
package/dist/adapter.js
ADDED
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.createAdapter = createAdapter;
|
|
4
|
+
const agent_catalog_1 = require("@a5c-ai/agent-catalog");
|
|
5
|
+
/**
|
|
6
|
+
* Creates the Cursor adapter capability descriptor.
|
|
7
|
+
*
|
|
8
|
+
* Reads capability data from the Atlas graph via the agent-catalog.
|
|
9
|
+
* Falls back to hardcoded defaults if the catalog is unavailable.
|
|
10
|
+
*
|
|
11
|
+
* Spec section 17.5.
|
|
12
|
+
*/
|
|
13
|
+
const DEFAULT_ADAPTER_NAME = 'cursor';
|
|
14
|
+
function createAdapter(name = DEFAULT_ADAPTER_NAME) {
|
|
15
|
+
const target = (0, agent_catalog_1.getPluginTargetDescriptor)(name);
|
|
16
|
+
return {
|
|
17
|
+
name,
|
|
18
|
+
family: target?.hooksMuxFamily ?? 'shell-hook',
|
|
19
|
+
sessionIdQuality: target?.sessionIdQuality ?? 'derived',
|
|
20
|
+
supportsOrderedFanout: target?.supportsOrderedFanout ?? true,
|
|
21
|
+
supportsNativeAdditionalContext: target?.supportsNativeAdditionalContext ?? false,
|
|
22
|
+
supportsBlock: target?.supportsBlock ?? true,
|
|
23
|
+
supportsAsk: target?.supportsAsk ?? false,
|
|
24
|
+
supportsToolInputMutation: target?.supportsToolInputMutation ?? false,
|
|
25
|
+
supportsToolResultMutation: target?.supportsToolResultMutation ?? false,
|
|
26
|
+
supportsPersistedEnv: target?.supportsPersistedEnv ?? false,
|
|
27
|
+
envPersistenceMode: target?.envPersistenceMode ?? 'wrapper_only',
|
|
28
|
+
toolInterceptionScope: target?.toolInterceptionScope ?? 'all',
|
|
29
|
+
notes: [
|
|
30
|
+
'Hook surface is stable as of Cursor 3.0',
|
|
31
|
+
'IDE and CLI share the same hook surface',
|
|
32
|
+
],
|
|
33
|
+
};
|
|
34
|
+
}
|
|
35
|
+
//# sourceMappingURL=adapter.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"adapter.js","sourceRoot":"","sources":["../src/adapter.ts"],"names":[],"mappings":";;AAaA,sCAoBC;AAhCD,yDAAkE;AAElE;;;;;;;GAOG;AACH,MAAM,oBAAoB,GAAG,QAAQ,CAAC;AAEtC,SAAgB,aAAa,CAAC,OAAe,oBAAoB;IAC/D,MAAM,MAAM,GAAG,IAAA,yCAAyB,EAAC,IAAI,CAAC,CAAC;IAC/C,OAAO;QACL,IAAI;QACJ,MAAM,EAAG,MAAM,EAAE,cAAgD,IAAI,YAAY;QACjF,gBAAgB,EAAG,MAAM,EAAE,gBAA4D,IAAI,SAAS;QACpG,qBAAqB,EAAE,MAAM,EAAE,qBAAqB,IAAI,IAAI;QAC5D,+BAA+B,EAAE,MAAM,EAAE,+BAA+B,IAAI,KAAK;QACjF,aAAa,EAAE,MAAM,EAAE,aAAa,IAAI,IAAI;QAC5C,WAAW,EAAE,MAAM,EAAE,WAAW,IAAI,KAAK;QACzC,yBAAyB,EAAE,MAAM,EAAE,yBAAyB,IAAI,KAAK;QACrE,0BAA0B,EAAE,MAAM,EAAE,0BAA0B,IAAI,KAAK;QACvE,oBAAoB,EAAE,MAAM,EAAE,oBAAoB,IAAI,KAAK;QAC3D,kBAAkB,EAAG,MAAM,EAAE,kBAAgE,IAAI,cAAc;QAC/G,qBAAqB,EAAG,MAAM,EAAE,qBAAsE,IAAI,KAAK;QAC/G,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"}
|
package/dist/index.d.ts
ADDED
|
@@ -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, setAdapterName, 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,cAAc,EACd,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,37 @@
|
|
|
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.setAdapterName = 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, "setAdapterName", { enumerable: true, get: function () { return normalizer_1.setAdapterName; } });
|
|
27
|
+
Object.defineProperty(exports, "ADAPTER_NAME", { enumerable: true, get: function () { return normalizer_1.ADAPTER_NAME; } });
|
|
28
|
+
// Renderer
|
|
29
|
+
var renderer_1 = require("./renderer");
|
|
30
|
+
Object.defineProperty(exports, "renderCursorOutput", { enumerable: true, get: function () { return renderer_1.renderCursorOutput; } });
|
|
31
|
+
Object.defineProperty(exports, "isFieldSupportedForEvent", { enumerable: true, get: function () { return renderer_1.isFieldSupportedForEvent; } });
|
|
32
|
+
// Session resolver
|
|
33
|
+
var session_resolver_1 = require("./session-resolver");
|
|
34
|
+
Object.defineProperty(exports, "resolveSessionId", { enumerable: true, get: function () { return session_resolver_1.resolveSessionId; } });
|
|
35
|
+
Object.defineProperty(exports, "deriveSessionId", { enumerable: true, get: function () { return session_resolver_1.deriveSessionId; } });
|
|
36
|
+
Object.defineProperty(exports, "isValidSessionId", { enumerable: true, get: function () { return session_resolver_1.isValidSessionId; } });
|
|
37
|
+
//# 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,2CAKsB;AAJpB,kHAAA,oBAAoB,OAAA;AACpB,wGAAA,UAAU,OAAA;AACV,4GAAA,cAAc,OAAA;AACd,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,11 @@
|
|
|
1
|
+
import type { PhaseMapping } from '@a5c-ai/hooks-mux-core';
|
|
2
|
+
export declare const CURSOR_PHASE_MAPPINGS: PhaseMapping[];
|
|
3
|
+
/**
|
|
4
|
+
* Quick lookup from native event name to phase mapping.
|
|
5
|
+
*/
|
|
6
|
+
export declare function findMapping(nativeEventName: string): PhaseMapping | undefined;
|
|
7
|
+
/**
|
|
8
|
+
* Get all canonical phases supported by the Cursor adapter.
|
|
9
|
+
*/
|
|
10
|
+
export declare function getSupportedPhases(): string[];
|
|
11
|
+
//# 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;AAkD3D,eAAO,MAAM,qBAAqB,EAAE,YAAY,EAAuB,CAAC;AAExE;;GAEG;AACH,wBAAgB,WAAW,CAAC,eAAe,EAAE,MAAM,GAAG,YAAY,GAAG,SAAS,CAE7E;AAED;;GAEG;AACH,wBAAgB,kBAAkB,IAAI,MAAM,EAAE,CAE7C"}
|
package/dist/mappings.js
ADDED
|
@@ -0,0 +1,64 @@
|
|
|
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
|
+
const agent_catalog_1 = require("@a5c-ai/agent-catalog");
|
|
7
|
+
/**
|
|
8
|
+
* Cursor native event to canonical phase mapping table.
|
|
9
|
+
*
|
|
10
|
+
* Phase mappings are built from the Atlas graph HookMapping records
|
|
11
|
+
* via the agent-catalog. Falls back to hardcoded defaults if the
|
|
12
|
+
* catalog is unavailable.
|
|
13
|
+
*
|
|
14
|
+
* Spec section 17.5.
|
|
15
|
+
*/
|
|
16
|
+
const SUPPORT_LEVEL_MAP = {
|
|
17
|
+
supported: 'native',
|
|
18
|
+
native: 'native',
|
|
19
|
+
lossy: 'lossy',
|
|
20
|
+
emulated: 'emulated',
|
|
21
|
+
unsupported: 'unsupported',
|
|
22
|
+
};
|
|
23
|
+
function hookMappingToPhaseMapping(mapping) {
|
|
24
|
+
if (!mapping.canonicalPhase)
|
|
25
|
+
return null;
|
|
26
|
+
return {
|
|
27
|
+
canonicalPhase: mapping.canonicalPhase,
|
|
28
|
+
nativeHook: mapping.nativeName,
|
|
29
|
+
supportLevel: SUPPORT_LEVEL_MAP[mapping.supportLevel] ?? 'native',
|
|
30
|
+
blockCapability: mapping.blockCapability ?? false,
|
|
31
|
+
mutationCapability: mapping.mutationCapability ?? false,
|
|
32
|
+
scope: (mapping.scope ?? 'session'),
|
|
33
|
+
};
|
|
34
|
+
}
|
|
35
|
+
function buildFromCatalog() {
|
|
36
|
+
const mappings = (0, agent_catalog_1.listHookMappingsByAdapterFamily)('cursor');
|
|
37
|
+
if (mappings.length === 0) {
|
|
38
|
+
throw new Error('hooks-mux adapter-cursor: catalog unavailable or returned no mappings for family "cursor"');
|
|
39
|
+
}
|
|
40
|
+
const phaseMappings = mappings
|
|
41
|
+
.map(hookMappingToPhaseMapping)
|
|
42
|
+
.filter((m) => m !== null);
|
|
43
|
+
const seen = new Set();
|
|
44
|
+
return phaseMappings.filter((m) => {
|
|
45
|
+
if (seen.has(m.nativeHook))
|
|
46
|
+
return false;
|
|
47
|
+
seen.add(m.nativeHook);
|
|
48
|
+
return true;
|
|
49
|
+
});
|
|
50
|
+
}
|
|
51
|
+
exports.CURSOR_PHASE_MAPPINGS = buildFromCatalog();
|
|
52
|
+
/**
|
|
53
|
+
* Quick lookup from native event name to phase mapping.
|
|
54
|
+
*/
|
|
55
|
+
function findMapping(nativeEventName) {
|
|
56
|
+
return exports.CURSOR_PHASE_MAPPINGS.find((m) => m.nativeHook === nativeEventName);
|
|
57
|
+
}
|
|
58
|
+
/**
|
|
59
|
+
* Get all canonical phases supported by the Cursor adapter.
|
|
60
|
+
*/
|
|
61
|
+
function getSupportedPhases() {
|
|
62
|
+
return exports.CURSOR_PHASE_MAPPINGS.map((m) => m.canonicalPhase);
|
|
63
|
+
}
|
|
64
|
+
//# sourceMappingURL=mappings.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"mappings.js","sourceRoot":"","sources":["../src/mappings.ts"],"names":[],"mappings":";;;AAuDA,kCAEC;AAKD,gDAEC;AA/DD,yDAAwE;AAGxE;;;;;;;;GAQG;AAEH,MAAM,iBAAiB,GAAiD;IACtE,SAAS,EAAE,QAAQ;IACnB,MAAM,EAAE,QAAQ;IAChB,KAAK,EAAE,OAAO;IACd,QAAQ,EAAE,UAAU;IACpB,WAAW,EAAE,aAAa;CAC3B,CAAC;AAEF,SAAS,yBAAyB,CAAC,OAA8B;IAC/D,IAAI,CAAC,OAAO,CAAC,cAAc;QAAE,OAAO,IAAI,CAAC;IACzC,OAAO;QACL,cAAc,EAAE,OAAO,CAAC,cAAgD;QACxE,UAAU,EAAE,OAAO,CAAC,UAAU;QAC9B,YAAY,EAAE,iBAAiB,CAAC,OAAO,CAAC,YAAY,CAAC,IAAI,QAAQ;QACjE,eAAe,EAAE,OAAO,CAAC,eAAe,IAAI,KAAK;QACjD,kBAAkB,EAAE,OAAO,CAAC,kBAAkB,IAAI,KAAK;QACvD,KAAK,EAAE,CAAC,OAAO,CAAC,KAAK,IAAI,SAAS,CAA0B;KAC7D,CAAC;AACJ,CAAC;AAED,SAAS,gBAAgB;IACvB,MAAM,QAAQ,GAAG,IAAA,+CAA+B,EAAC,QAAQ,CAAC,CAAC;IAC3D,IAAI,QAAQ,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QAC1B,MAAM,IAAI,KAAK,CAAC,2FAA2F,CAAC,CAAC;IAC/G,CAAC;IACD,MAAM,aAAa,GAAG,QAAQ;SAC3B,GAAG,CAAC,yBAAyB,CAAC;SAC9B,MAAM,CAAC,CAAC,CAAC,EAAqB,EAAE,CAAC,CAAC,KAAK,IAAI,CAAC,CAAC;IAChD,MAAM,IAAI,GAAG,IAAI,GAAG,EAAU,CAAC;IAC/B,OAAO,aAAa,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE;QAChC,IAAI,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC,UAAU,CAAC;YAAE,OAAO,KAAK,CAAC;QACzC,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC,UAAU,CAAC,CAAC;QACvB,OAAO,IAAI,CAAC;IACd,CAAC,CAAC,CAAC;AACL,CAAC;AAEY,QAAA,qBAAqB,GAAmB,gBAAgB,EAAE,CAAC;AAExE;;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,58 @@
|
|
|
1
|
+
import { type UnifiedHookEvent } from '@a5c-ai/hooks-mux-core';
|
|
2
|
+
/** The default adapter identifier used in all normalized events. */
|
|
3
|
+
export declare const ADAPTER_NAME = "cursor";
|
|
4
|
+
/** Override the adapter name used in normalized events. */
|
|
5
|
+
export declare function setAdapterName(name: string): void;
|
|
6
|
+
/**
|
|
7
|
+
* Common fields that may be present on Cursor hook stdin payloads.
|
|
8
|
+
* Cursor's stdin format is not fully documented; fields may be
|
|
9
|
+
* absent or undefined. The normalizer handles all cases gracefully.
|
|
10
|
+
*/
|
|
11
|
+
export interface CursorStdinBase {
|
|
12
|
+
cwd?: string;
|
|
13
|
+
workspace?: string;
|
|
14
|
+
model?: string;
|
|
15
|
+
[key: string]: unknown;
|
|
16
|
+
}
|
|
17
|
+
/** SessionStart-specific fields. */
|
|
18
|
+
export interface CursorSessionStartPayload extends CursorStdinBase {
|
|
19
|
+
source?: string;
|
|
20
|
+
}
|
|
21
|
+
/** Stop-specific fields. */
|
|
22
|
+
export interface CursorStopPayload extends CursorStdinBase {
|
|
23
|
+
reason?: string;
|
|
24
|
+
stop_hook_active?: boolean;
|
|
25
|
+
}
|
|
26
|
+
/** PreToolUse-specific fields (when available). */
|
|
27
|
+
export interface CursorPreToolUsePayload extends CursorStdinBase {
|
|
28
|
+
tool_name?: string;
|
|
29
|
+
tool_call_id?: string;
|
|
30
|
+
tool_input?: unknown;
|
|
31
|
+
}
|
|
32
|
+
/** PostToolUse-specific fields (when available). */
|
|
33
|
+
export interface CursorPostToolUsePayload extends CursorStdinBase {
|
|
34
|
+
tool_name?: string;
|
|
35
|
+
tool_call_id?: string;
|
|
36
|
+
tool_input?: unknown;
|
|
37
|
+
tool_response?: unknown;
|
|
38
|
+
}
|
|
39
|
+
/**
|
|
40
|
+
* Parse raw stdin input into a typed object.
|
|
41
|
+
* Cursor hooks receive JSON on stdin. If parsing fails, return empty
|
|
42
|
+
* object (fail-open: Cursor's payload format is not fully documented).
|
|
43
|
+
*/
|
|
44
|
+
export declare function parseStdin(raw: unknown): Record<string, unknown>;
|
|
45
|
+
/**
|
|
46
|
+
* Normalize a raw Cursor hook invocation into a UnifiedHookEvent.
|
|
47
|
+
*
|
|
48
|
+
* Cursor's hook surface is experimental. The normalizer:
|
|
49
|
+
* - Parses stdin gracefully (fail-open on missing/malformed fields)
|
|
50
|
+
* - Annotates events with capability profile diagnostics
|
|
51
|
+
* - Enriches env from stdin payload fields
|
|
52
|
+
*
|
|
53
|
+
* @param rawEventName - The native Cursor event name (e.g. 'sessionStart', 'stop')
|
|
54
|
+
* @param stdinPayload - Raw stdin content (string or parsed object)
|
|
55
|
+
* @param env - Environment variables at invocation time
|
|
56
|
+
*/
|
|
57
|
+
export declare function normalizeCursorEvent(rawEventName: string, stdinPayload: unknown, env?: Record<string, string>): UnifiedHookEvent;
|
|
58
|
+
//# 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,oEAAoE;AACpE,eAAO,MAAM,YAAY,WAAW,CAAC;AAKrC,2DAA2D;AAC3D,wBAAgB,cAAc,CAAC,IAAI,EAAE,MAAM,GAAG,IAAI,CAEjD;AAED;;;;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,111 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.ADAPTER_NAME = void 0;
|
|
4
|
+
exports.setAdapterName = setAdapterName;
|
|
5
|
+
exports.parseStdin = parseStdin;
|
|
6
|
+
exports.normalizeCursorEvent = normalizeCursorEvent;
|
|
7
|
+
const hooks_mux_core_1 = require("@a5c-ai/hooks-mux-core");
|
|
8
|
+
const mappings_1 = require("./mappings");
|
|
9
|
+
const capability_profile_1 = require("./capability-profile");
|
|
10
|
+
/** The default adapter identifier used in all normalized events. */
|
|
11
|
+
exports.ADAPTER_NAME = 'cursor';
|
|
12
|
+
/** Mutable adapter name, defaulting to the cursor adapter identity. */
|
|
13
|
+
let _adapterName = 'cursor';
|
|
14
|
+
/** Override the adapter name used in normalized events. */
|
|
15
|
+
function setAdapterName(name) {
|
|
16
|
+
_adapterName = name;
|
|
17
|
+
}
|
|
18
|
+
/**
|
|
19
|
+
* Parse raw stdin input into a typed object.
|
|
20
|
+
* Cursor hooks receive JSON on stdin. If parsing fails, return empty
|
|
21
|
+
* object (fail-open: Cursor's payload format is not fully documented).
|
|
22
|
+
*/
|
|
23
|
+
function parseStdin(raw) {
|
|
24
|
+
if (raw == null)
|
|
25
|
+
return {};
|
|
26
|
+
if (typeof raw === 'string') {
|
|
27
|
+
try {
|
|
28
|
+
const parsed = JSON.parse(raw);
|
|
29
|
+
if (typeof parsed === 'object' && parsed !== null && !Array.isArray(parsed)) {
|
|
30
|
+
return parsed;
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
catch {
|
|
34
|
+
// fail open -- Cursor payload format is uncertain
|
|
35
|
+
}
|
|
36
|
+
return {};
|
|
37
|
+
}
|
|
38
|
+
if (typeof raw === 'object' && !Array.isArray(raw)) {
|
|
39
|
+
return raw;
|
|
40
|
+
}
|
|
41
|
+
return {};
|
|
42
|
+
}
|
|
43
|
+
/**
|
|
44
|
+
* Extract tool metadata from a preToolUse/postToolUse payload.
|
|
45
|
+
*/
|
|
46
|
+
function extractToolFields(payload) {
|
|
47
|
+
const fields = {};
|
|
48
|
+
if (typeof payload['tool_name'] === 'string') {
|
|
49
|
+
fields['HOOKS_PROXY_TOOL_NAME'] = payload['tool_name'];
|
|
50
|
+
}
|
|
51
|
+
if (typeof payload['tool_call_id'] === 'string') {
|
|
52
|
+
fields['HOOKS_PROXY_TOOL_CALL_ID'] = payload['tool_call_id'];
|
|
53
|
+
}
|
|
54
|
+
return fields;
|
|
55
|
+
}
|
|
56
|
+
/**
|
|
57
|
+
* Normalize a raw Cursor hook invocation into a UnifiedHookEvent.
|
|
58
|
+
*
|
|
59
|
+
* Cursor's hook surface is experimental. The normalizer:
|
|
60
|
+
* - Parses stdin gracefully (fail-open on missing/malformed fields)
|
|
61
|
+
* - Annotates events with capability profile diagnostics
|
|
62
|
+
* - Enriches env from stdin payload fields
|
|
63
|
+
*
|
|
64
|
+
* @param rawEventName - The native Cursor event name (e.g. 'sessionStart', 'stop')
|
|
65
|
+
* @param stdinPayload - Raw stdin content (string or parsed object)
|
|
66
|
+
* @param env - Environment variables at invocation time
|
|
67
|
+
*/
|
|
68
|
+
function normalizeCursorEvent(rawEventName, stdinPayload, env = {}) {
|
|
69
|
+
const parsed = parseStdin(stdinPayload);
|
|
70
|
+
// Enrich env with Cursor-specific fields extracted from stdin
|
|
71
|
+
const enrichedEnv = { ...env };
|
|
72
|
+
// Cursor does not provide a native session_id -- derive from workspace/cwd
|
|
73
|
+
if (typeof parsed['cwd'] === 'string' && !enrichedEnv['HOOKS_PROXY_CWD']) {
|
|
74
|
+
enrichedEnv['HOOKS_PROXY_CWD'] = parsed['cwd'];
|
|
75
|
+
}
|
|
76
|
+
if (typeof parsed['workspace'] === 'string' && !enrichedEnv['HOOKS_PROXY_WORKTREE']) {
|
|
77
|
+
enrichedEnv['HOOKS_PROXY_WORKTREE'] = parsed['workspace'];
|
|
78
|
+
}
|
|
79
|
+
if (typeof parsed['model'] === 'string' && !enrichedEnv['HOOKS_PROXY_MODEL']) {
|
|
80
|
+
enrichedEnv['HOOKS_PROXY_MODEL'] = parsed['model'];
|
|
81
|
+
}
|
|
82
|
+
if (typeof parsed['source'] === 'string' && !enrichedEnv['HOOKS_PROXY_SOURCE']) {
|
|
83
|
+
enrichedEnv['HOOKS_PROXY_SOURCE'] = parsed['source'];
|
|
84
|
+
}
|
|
85
|
+
// Tool-specific env enrichment
|
|
86
|
+
if (rawEventName === 'preToolUse' || rawEventName === 'postToolUse') {
|
|
87
|
+
const toolFields = extractToolFields(parsed);
|
|
88
|
+
for (const [k, v] of Object.entries(toolFields)) {
|
|
89
|
+
if (!enrichedEnv[k]) {
|
|
90
|
+
enrichedEnv[k] = v;
|
|
91
|
+
}
|
|
92
|
+
}
|
|
93
|
+
}
|
|
94
|
+
const options = {
|
|
95
|
+
adapter: _adapterName,
|
|
96
|
+
rawEventName,
|
|
97
|
+
stdinPayload: parsed,
|
|
98
|
+
env: enrichedEnv,
|
|
99
|
+
adapterMappings: mappings_1.CURSOR_PHASE_MAPPINGS,
|
|
100
|
+
};
|
|
101
|
+
const event = (0, hooks_mux_core_1.normalizeEvent)(options);
|
|
102
|
+
// Annotate with capability profile diagnostics
|
|
103
|
+
const diagnostics = (0, capability_profile_1.getEventDiagnostics)(rawEventName);
|
|
104
|
+
event.execution.metadata = {
|
|
105
|
+
...event.execution.metadata,
|
|
106
|
+
cursorDiagnostics: diagnostics,
|
|
107
|
+
experimental: true,
|
|
108
|
+
};
|
|
109
|
+
return event;
|
|
110
|
+
}
|
|
111
|
+
//# 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"}
|
package/dist/renderer.js
ADDED
|
@@ -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.00fa5317c",
|
|
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.00fa5317c"
|
|
34
|
+
},
|
|
35
|
+
"devDependencies": {
|
|
36
|
+
"typescript": "^5.7.0",
|
|
37
|
+
"vitest": "^3.0.0",
|
|
38
|
+
"rimraf": "^6.0.0"
|
|
39
|
+
}
|
|
40
|
+
}
|