@a5c-ai/hooks-adapter-copilot 5.1.1-staging.52898ebfc24f

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-adapter-copilot
2
+
3
+ GitHub Copilot harness adapter for hooks-adapter.
4
+
5
+ ## Install
6
+
7
+ ```bash
8
+ npm install @a5c-ai/hooks-adapter-copilot @a5c-ai/hooks-adapter-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
+ normalizeCopilotEvent,
19
+ renderCopilotOutput,
20
+ } from "@a5c-ai/hooks-adapter-copilot";
21
+ ```
22
+
23
+ The package exposes Copilot-specific normalization, phase mappings, rendering helpers, and session-resolution utilities for the hooks-adapter execution pipeline.
24
+
25
+ See [`packages/adapters/hooks/README.md`](../README.md) for the workspace overview and `packages/adapters/hooks/docs/adapter-integration-guide.md` for end-to-end integration guidance.
26
+
27
+ ## License
28
+
29
+ MIT © a5c-ai
@@ -0,0 +1,3 @@
1
+ import type { AdapterCapabilities } from '@a5c-ai/hooks-adapter-core';
2
+ export declare function createAdapter(name?: string): AdapterCapabilities;
3
+ //# 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,4BAA4B,CAAC;AAiBtE,wBAAgB,aAAa,CAAC,IAAI,GAAE,MAA6B,GAAG,mBAAmB,CAoBtF"}
@@ -0,0 +1,39 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.createAdapter = createAdapter;
4
+ const catalog_1 = require("@a5c-ai/atlas/catalog");
5
+ /**
6
+ * Creates the GitHub Copilot adapter with its capability metadata.
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
+ * Key characteristics:
12
+ * - Shell-hook family (stdin JSON / stdout JSON)
13
+ * - Synthetic session ID (no stable native session ID exposed)
14
+ * - Pre-tool deny is the only blocking path
15
+ * - Session-start output is ignored by Copilot CLI
16
+ */
17
+ const DEFAULT_ADAPTER_NAME = 'copilot';
18
+ function createAdapter(name = DEFAULT_ADAPTER_NAME) {
19
+ const target = (0, catalog_1.getPluginTargetDescriptor)(name === 'copilot' ? 'github-copilot' : name);
20
+ return {
21
+ name,
22
+ family: target?.hooksMuxFamily ?? 'shell-hook',
23
+ sessionIdQuality: target?.sessionIdQuality ?? 'synthetic',
24
+ supportsOrderedFanout: target?.supportsOrderedFanout ?? true,
25
+ supportsNativeAdditionalContext: target?.supportsNativeAdditionalContext ?? false,
26
+ supportsBlock: target?.supportsBlock ?? true,
27
+ supportsAsk: target?.supportsAsk ?? false,
28
+ supportsToolInputMutation: target?.supportsToolInputMutation ?? false,
29
+ supportsToolResultMutation: target?.supportsToolResultMutation ?? false,
30
+ supportsPersistedEnv: target?.supportsPersistedEnv ?? false,
31
+ envPersistenceMode: target?.envPersistenceMode ?? 'wrapper_only',
32
+ toolInterceptionScope: target?.toolInterceptionScope ?? 'all',
33
+ notes: [
34
+ 'session-start output ignored',
35
+ 'only deny processed for permissionDecision',
36
+ ],
37
+ };
38
+ }
39
+ //# sourceMappingURL=adapter.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"adapter.js","sourceRoot":"","sources":["../src/adapter.ts"],"names":[],"mappings":";;AAiBA,sCAoBC;AApCD,mDAAkE;AAElE;;;;;;;;;;;GAWG;AACH,MAAM,oBAAoB,GAAG,SAAS,CAAC;AAEvC,SAAgB,aAAa,CAAC,OAAe,oBAAoB;IAC/D,MAAM,MAAM,GAAG,IAAA,mCAAyB,EAAC,IAAI,KAAK,SAAS,CAAC,CAAC,CAAC,gBAAgB,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC;IACvF,OAAO;QACL,IAAI;QACJ,MAAM,EAAG,MAAM,EAAE,cAAgD,IAAI,YAAY;QACjF,gBAAgB,EAAG,MAAM,EAAE,gBAA4D,IAAI,WAAW;QACtG,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,8BAA8B;YAC9B,4CAA4C;SAC7C;KACF,CAAC;AACJ,CAAC"}
@@ -0,0 +1,8 @@
1
+ export { createAdapter } from './adapter';
2
+ export { COPILOT_PHASE_MAPPINGS, getMappingByNativeHook, getMappingByPhase } from './mappings';
3
+ export { parseStdin, normalizeCopilotEvent, setAdapterName } from './normalizer';
4
+ export type { CopilotRawInput } from './normalizer';
5
+ export { renderCopilotOutput, serializeOutput } from './renderer';
6
+ export type { CopilotPreToolOutput, CopilotNoopOutput, CopilotNativeOutput } from './renderer';
7
+ export { resolveSyntheticSessionId } from './session-resolver';
8
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,aAAa,EAAE,MAAM,WAAW,CAAC;AAC1C,OAAO,EAAE,sBAAsB,EAAE,sBAAsB,EAAE,iBAAiB,EAAE,MAAM,YAAY,CAAC;AAC/F,OAAO,EAAE,UAAU,EAAE,qBAAqB,EAAE,cAAc,EAAE,MAAM,cAAc,CAAC;AACjF,YAAY,EAAE,eAAe,EAAE,MAAM,cAAc,CAAC;AACpD,OAAO,EAAE,mBAAmB,EAAE,eAAe,EAAE,MAAM,YAAY,CAAC;AAClE,YAAY,EAAE,oBAAoB,EAAE,iBAAiB,EAAE,mBAAmB,EAAE,MAAM,YAAY,CAAC;AAC/F,OAAO,EAAE,yBAAyB,EAAE,MAAM,oBAAoB,CAAC"}
package/dist/index.js ADDED
@@ -0,0 +1,19 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.resolveSyntheticSessionId = exports.serializeOutput = exports.renderCopilotOutput = exports.setAdapterName = exports.normalizeCopilotEvent = exports.parseStdin = exports.getMappingByPhase = exports.getMappingByNativeHook = exports.COPILOT_PHASE_MAPPINGS = exports.createAdapter = void 0;
4
+ var adapter_1 = require("./adapter");
5
+ Object.defineProperty(exports, "createAdapter", { enumerable: true, get: function () { return adapter_1.createAdapter; } });
6
+ var mappings_1 = require("./mappings");
7
+ Object.defineProperty(exports, "COPILOT_PHASE_MAPPINGS", { enumerable: true, get: function () { return mappings_1.COPILOT_PHASE_MAPPINGS; } });
8
+ Object.defineProperty(exports, "getMappingByNativeHook", { enumerable: true, get: function () { return mappings_1.getMappingByNativeHook; } });
9
+ Object.defineProperty(exports, "getMappingByPhase", { enumerable: true, get: function () { return mappings_1.getMappingByPhase; } });
10
+ var normalizer_1 = require("./normalizer");
11
+ Object.defineProperty(exports, "parseStdin", { enumerable: true, get: function () { return normalizer_1.parseStdin; } });
12
+ Object.defineProperty(exports, "normalizeCopilotEvent", { enumerable: true, get: function () { return normalizer_1.normalizeCopilotEvent; } });
13
+ Object.defineProperty(exports, "setAdapterName", { enumerable: true, get: function () { return normalizer_1.setAdapterName; } });
14
+ var renderer_1 = require("./renderer");
15
+ Object.defineProperty(exports, "renderCopilotOutput", { enumerable: true, get: function () { return renderer_1.renderCopilotOutput; } });
16
+ Object.defineProperty(exports, "serializeOutput", { enumerable: true, get: function () { return renderer_1.serializeOutput; } });
17
+ var session_resolver_1 = require("./session-resolver");
18
+ Object.defineProperty(exports, "resolveSyntheticSessionId", { enumerable: true, get: function () { return session_resolver_1.resolveSyntheticSessionId; } });
19
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";;;AAAA,qCAA0C;AAAjC,wGAAA,aAAa,OAAA;AACtB,uCAA+F;AAAtF,kHAAA,sBAAsB,OAAA;AAAE,kHAAA,sBAAsB,OAAA;AAAE,6GAAA,iBAAiB,OAAA;AAC1E,2CAAiF;AAAxE,wGAAA,UAAU,OAAA;AAAE,mHAAA,qBAAqB,OAAA;AAAE,4GAAA,cAAc,OAAA;AAE1D,uCAAkE;AAAzD,+GAAA,mBAAmB,OAAA;AAAE,2GAAA,eAAe,OAAA;AAE7C,uDAA+D;AAAtD,6HAAA,yBAAyB,OAAA"}
@@ -0,0 +1,11 @@
1
+ import type { PhaseMapping } from '@a5c-ai/hooks-adapter-core';
2
+ export declare const COPILOT_PHASE_MAPPINGS: PhaseMapping[];
3
+ /**
4
+ * Lookup a phase mapping by native hook name.
5
+ */
6
+ export declare function getMappingByNativeHook(nativeHook: string): PhaseMapping | undefined;
7
+ /**
8
+ * Lookup a phase mapping by canonical phase.
9
+ */
10
+ export declare function getMappingByPhase(phase: string): PhaseMapping | undefined;
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,4BAA4B,CAAC;AAgD/D,eAAO,MAAM,sBAAsB,EAAE,YAAY,EAAuB,CAAC;AAEzE;;GAEG;AACH,wBAAgB,sBAAsB,CAAC,UAAU,EAAE,MAAM,GAAG,YAAY,GAAG,SAAS,CAEnF;AAED;;GAEG;AACH,wBAAgB,iBAAiB,CAAC,KAAK,EAAE,MAAM,GAAG,YAAY,GAAG,SAAS,CAEzE"}
@@ -0,0 +1,62 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.COPILOT_PHASE_MAPPINGS = void 0;
4
+ exports.getMappingByNativeHook = getMappingByNativeHook;
5
+ exports.getMappingByPhase = getMappingByPhase;
6
+ const catalog_1 = require("@a5c-ai/atlas/catalog");
7
+ /**
8
+ * Copilot native hook names mapped to canonical lifecycle phases.
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
+ const SUPPORT_LEVEL_MAP = {
15
+ supported: 'native',
16
+ native: 'native',
17
+ lossy: 'lossy',
18
+ emulated: 'emulated',
19
+ unsupported: 'unsupported',
20
+ };
21
+ function hookMappingToPhaseMapping(mapping) {
22
+ if (!mapping.canonicalPhase)
23
+ return null;
24
+ return {
25
+ canonicalPhase: mapping.canonicalPhase,
26
+ nativeHook: mapping.nativeName,
27
+ supportLevel: SUPPORT_LEVEL_MAP[mapping.supportLevel] ?? 'native',
28
+ blockCapability: mapping.blockCapability ?? false,
29
+ mutationCapability: mapping.mutationCapability ?? false,
30
+ scope: (mapping.scope ?? 'session'),
31
+ };
32
+ }
33
+ function buildFromCatalog() {
34
+ const mappings = (0, catalog_1.listHookMappingsByAdapterFamily)('copilot');
35
+ if (mappings.length === 0) {
36
+ throw new Error('hooks-adapter adapter-copilot: catalog unavailable or returned no mappings for family "copilot"');
37
+ }
38
+ const phaseMappings = mappings
39
+ .map(hookMappingToPhaseMapping)
40
+ .filter((m) => m !== null);
41
+ const seen = new Set();
42
+ return phaseMappings.filter((m) => {
43
+ if (seen.has(m.nativeHook))
44
+ return false;
45
+ seen.add(m.nativeHook);
46
+ return true;
47
+ });
48
+ }
49
+ exports.COPILOT_PHASE_MAPPINGS = buildFromCatalog();
50
+ /**
51
+ * Lookup a phase mapping by native hook name.
52
+ */
53
+ function getMappingByNativeHook(nativeHook) {
54
+ return exports.COPILOT_PHASE_MAPPINGS.find((m) => m.nativeHook === nativeHook);
55
+ }
56
+ /**
57
+ * Lookup a phase mapping by canonical phase.
58
+ */
59
+ function getMappingByPhase(phase) {
60
+ return exports.COPILOT_PHASE_MAPPINGS.find((m) => m.canonicalPhase === phase);
61
+ }
62
+ //# sourceMappingURL=mappings.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"mappings.js","sourceRoot":"","sources":["../src/mappings.ts"],"names":[],"mappings":";;;AAqDA,wDAEC;AAKD,8CAEC;AA7DD,mDAAwE;AAGxE;;;;;;GAMG;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,yCAA+B,EAAC,SAAS,CAAC,CAAC;IAC5D,IAAI,QAAQ,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QAC1B,MAAM,IAAI,KAAK,CAAC,iGAAiG,CAAC,CAAC;IACrH,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,sBAAsB,GAAmB,gBAAgB,EAAE,CAAC;AAEzE;;GAEG;AACH,SAAgB,sBAAsB,CAAC,UAAkB;IACvD,OAAO,8BAAsB,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,UAAU,KAAK,UAAU,CAAC,CAAC;AACzE,CAAC;AAED;;GAEG;AACH,SAAgB,iBAAiB,CAAC,KAAa;IAC7C,OAAO,8BAAsB,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,cAAc,KAAK,KAAK,CAAC,CAAC;AACxE,CAAC"}
@@ -0,0 +1,48 @@
1
+ import type { UnifiedHookEvent } from '@a5c-ai/hooks-adapter-core';
2
+ /** The default adapter name. */
3
+ export declare const ADAPTER_NAME = "copilot";
4
+ /** Override the adapter name used in normalized events. */
5
+ export declare function setAdapterName(name: string): void;
6
+ /**
7
+ * Shape of raw Copilot stdin JSON for hook events.
8
+ *
9
+ * Copilot delivers JSON on stdin with at least these fields.
10
+ * Additional fields vary by event type.
11
+ */
12
+ export interface CopilotRawInput {
13
+ /** The native hook event name (e.g. 'sessionStart', 'preToolUse'). */
14
+ event?: string;
15
+ /** Working directory at time of invocation. */
16
+ cwd?: string;
17
+ /** Workspace or project root path. */
18
+ workspace?: string;
19
+ /** User prompt text (on userPromptSubmitted). */
20
+ prompt?: string;
21
+ /** Tool name (on preToolUse / postToolUse). */
22
+ toolName?: string;
23
+ /** Tool call ID (on preToolUse / postToolUse). */
24
+ toolCallId?: string;
25
+ /** Tool input data (on preToolUse). */
26
+ toolInput?: unknown;
27
+ /** Tool response data (on postToolUse). */
28
+ toolResponse?: unknown;
29
+ /** Error message (on error events). */
30
+ error?: string;
31
+ /** Arbitrary additional fields. */
32
+ [key: string]: unknown;
33
+ }
34
+ /**
35
+ * Parse raw stdin string into a CopilotRawInput.
36
+ *
37
+ * Returns null if the input is empty or unparseable.
38
+ */
39
+ export declare function parseStdin(raw: string): CopilotRawInput | null;
40
+ /**
41
+ * Normalize a raw Copilot hook input into a UnifiedHookEvent.
42
+ *
43
+ * @param rawInput - Parsed JSON from stdin
44
+ * @param nativeEventName - The native event name (from stdin or CLI flag)
45
+ * @param env - Environment variables at invocation
46
+ */
47
+ export declare function normalizeCopilotEvent(rawInput: CopilotRawInput, nativeEventName: string, env?: Record<string, string>): UnifiedHookEvent;
48
+ //# sourceMappingURL=normalizer.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"normalizer.d.ts","sourceRoot":"","sources":["../src/normalizer.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,4BAA4B,CAAC;AAKnE,gCAAgC;AAChC,eAAO,MAAM,YAAY,YAAY,CAAC;AAKtC,2DAA2D;AAC3D,wBAAgB,cAAc,CAAC,IAAI,EAAE,MAAM,GAAG,IAAI,CAEjD;AAED;;;;;GAKG;AACH,MAAM,WAAW,eAAe;IAC9B,sEAAsE;IACtE,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,+CAA+C;IAC/C,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,sCAAsC;IACtC,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,iDAAiD;IACjD,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,+CAA+C;IAC/C,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,kDAAkD;IAClD,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,uCAAuC;IACvC,SAAS,CAAC,EAAE,OAAO,CAAC;IACpB,2CAA2C;IAC3C,YAAY,CAAC,EAAE,OAAO,CAAC;IACvB,uCAAuC;IACvC,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,mCAAmC;IACnC,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC;CACxB;AAED;;;;GAIG;AACH,wBAAgB,UAAU,CAAC,GAAG,EAAE,MAAM,GAAG,eAAe,GAAG,IAAI,CAa9D;AAED;;;;;;GAMG;AACH,wBAAgB,qBAAqB,CACnC,QAAQ,EAAE,eAAe,EACzB,eAAe,EAAE,MAAM,EACvB,GAAG,GAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAM,GAC/B,gBAAgB,CAmClB"}
@@ -0,0 +1,76 @@
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.normalizeCopilotEvent = normalizeCopilotEvent;
7
+ const hooks_adapter_core_1 = require("@a5c-ai/hooks-adapter-core");
8
+ const mappings_1 = require("./mappings");
9
+ const session_resolver_1 = require("./session-resolver");
10
+ /** The default adapter name. */
11
+ exports.ADAPTER_NAME = 'copilot';
12
+ /** Mutable adapter name, defaulting to the Copilot adapter identity. */
13
+ let _copilotAdapterName = 'copilot';
14
+ /** Override the adapter name used in normalized events. */
15
+ function setAdapterName(name) {
16
+ _copilotAdapterName = name;
17
+ }
18
+ /**
19
+ * Parse raw stdin string into a CopilotRawInput.
20
+ *
21
+ * Returns null if the input is empty or unparseable.
22
+ */
23
+ function parseStdin(raw) {
24
+ const trimmed = raw.trim();
25
+ if (!trimmed)
26
+ return null;
27
+ try {
28
+ const parsed = JSON.parse(trimmed);
29
+ if (typeof parsed !== 'object' || parsed === null || Array.isArray(parsed)) {
30
+ return null;
31
+ }
32
+ return parsed;
33
+ }
34
+ catch {
35
+ return null;
36
+ }
37
+ }
38
+ /**
39
+ * Normalize a raw Copilot hook input into a UnifiedHookEvent.
40
+ *
41
+ * @param rawInput - Parsed JSON from stdin
42
+ * @param nativeEventName - The native event name (from stdin or CLI flag)
43
+ * @param env - Environment variables at invocation
44
+ */
45
+ function normalizeCopilotEvent(rawInput, nativeEventName, env = {}) {
46
+ // Derive session ID: check env overrides, then synthesize from cwd/workspace
47
+ const sessionId = env['AGENT_SESSION_ID'] ??
48
+ env['HOOKS_PROXY_SESSION_ID'] ??
49
+ (0, session_resolver_1.resolveSyntheticSessionId)(rawInput.cwd, rawInput.workspace);
50
+ // Build enriched env with session context
51
+ const enrichedEnv = {
52
+ ...env,
53
+ HOOKS_PROXY_SESSION_ID: sessionId,
54
+ };
55
+ if (rawInput.cwd) {
56
+ enrichedEnv['HOOKS_PROXY_CWD'] = rawInput.cwd;
57
+ }
58
+ if (rawInput.toolName) {
59
+ enrichedEnv['HOOKS_PROXY_TOOL_NAME'] = rawInput.toolName;
60
+ }
61
+ if (rawInput.toolCallId) {
62
+ enrichedEnv['HOOKS_PROXY_TOOL_CALL_ID'] = rawInput.toolCallId;
63
+ }
64
+ // Build payload from raw input, preserving native detail
65
+ const payload = { ...rawInput };
66
+ // Remove the event field from payload since it's the event name
67
+ delete payload['event'];
68
+ return (0, hooks_adapter_core_1.normalizeEvent)({
69
+ adapter: _copilotAdapterName,
70
+ rawEventName: nativeEventName,
71
+ stdinPayload: payload,
72
+ env: enrichedEnv,
73
+ adapterMappings: mappings_1.COPILOT_PHASE_MAPPINGS,
74
+ });
75
+ }
76
+ //# sourceMappingURL=normalizer.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"normalizer.js","sourceRoot":"","sources":["../src/normalizer.ts"],"names":[],"mappings":";;;AAYA,wCAEC;AAoCD,gCAaC;AASD,sDAuCC;AA9GD,mEAA4D;AAC5D,yCAAoD;AACpD,yDAA+D;AAE/D,gCAAgC;AACnB,QAAA,YAAY,GAAG,SAAS,CAAC;AAEtC,wEAAwE;AACxE,IAAI,mBAAmB,GAAW,SAAS,CAAC;AAE5C,2DAA2D;AAC3D,SAAgB,cAAc,CAAC,IAAY;IACzC,mBAAmB,GAAG,IAAI,CAAC;AAC7B,CAAC;AA+BD;;;;GAIG;AACH,SAAgB,UAAU,CAAC,GAAW;IACpC,MAAM,OAAO,GAAG,GAAG,CAAC,IAAI,EAAE,CAAC;IAC3B,IAAI,CAAC,OAAO;QAAE,OAAO,IAAI,CAAC;IAE1B,IAAI,CAAC;QACH,MAAM,MAAM,GAAG,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC;QACnC,IAAI,OAAO,MAAM,KAAK,QAAQ,IAAI,MAAM,KAAK,IAAI,IAAI,KAAK,CAAC,OAAO,CAAC,MAAM,CAAC,EAAE,CAAC;YAC3E,OAAO,IAAI,CAAC;QACd,CAAC;QACD,OAAO,MAAyB,CAAC;IACnC,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,IAAI,CAAC;IACd,CAAC;AACH,CAAC;AAED;;;;;;GAMG;AACH,SAAgB,qBAAqB,CACnC,QAAyB,EACzB,eAAuB,EACvB,MAA8B,EAAE;IAEhC,6EAA6E;IAC7E,MAAM,SAAS,GACb,GAAG,CAAC,kBAAkB,CAAC;QACvB,GAAG,CAAC,wBAAwB,CAAC;QAC7B,IAAA,4CAAyB,EAAC,QAAQ,CAAC,GAAG,EAAE,QAAQ,CAAC,SAAS,CAAC,CAAC;IAE9D,0CAA0C;IAC1C,MAAM,WAAW,GAA2B;QAC1C,GAAG,GAAG;QACN,sBAAsB,EAAE,SAAS;KAClC,CAAC;IAEF,IAAI,QAAQ,CAAC,GAAG,EAAE,CAAC;QACjB,WAAW,CAAC,iBAAiB,CAAC,GAAG,QAAQ,CAAC,GAAG,CAAC;IAChD,CAAC;IACD,IAAI,QAAQ,CAAC,QAAQ,EAAE,CAAC;QACtB,WAAW,CAAC,uBAAuB,CAAC,GAAG,QAAQ,CAAC,QAAQ,CAAC;IAC3D,CAAC;IACD,IAAI,QAAQ,CAAC,UAAU,EAAE,CAAC;QACxB,WAAW,CAAC,0BAA0B,CAAC,GAAG,QAAQ,CAAC,UAAU,CAAC;IAChE,CAAC;IAED,yDAAyD;IACzD,MAAM,OAAO,GAA4B,EAAE,GAAG,QAAQ,EAAE,CAAC;IACzD,gEAAgE;IAChE,OAAO,OAAO,CAAC,OAAO,CAAC,CAAC;IAExB,OAAO,IAAA,mCAAc,EAAC;QACpB,OAAO,EAAE,mBAAmB;QAC5B,YAAY,EAAE,eAAe;QAC7B,YAAY,EAAE,OAAO;QACrB,GAAG,EAAE,WAAW;QAChB,eAAe,EAAE,iCAAsB;KACxC,CAAC,CAAC;AACL,CAAC"}
@@ -0,0 +1,37 @@
1
+ import type { MergedExecutionResult } from '@a5c-ai/hooks-adapter-core';
2
+ /**
3
+ * Copilot native output shape for pre-tool-use hooks.
4
+ *
5
+ * Only the preTool event actually processes output.
6
+ * permissionDecision supports allow|deny|ask in the schema,
7
+ * but only deny is currently processed by Copilot CLI.
8
+ */
9
+ export interface CopilotPreToolOutput {
10
+ permissionDecision?: 'allow' | 'deny' | 'ask';
11
+ reason?: string;
12
+ }
13
+ /**
14
+ * Copilot native output shape for all other events.
15
+ * Output is ignored by Copilot CLI on non-preTool events,
16
+ * so we emit a minimal success object.
17
+ */
18
+ export interface CopilotNoopOutput {
19
+ ok: true;
20
+ }
21
+ export type CopilotNativeOutput = CopilotPreToolOutput | CopilotNoopOutput;
22
+ /**
23
+ * Render a merged execution result into Copilot-native JSON output.
24
+ *
25
+ * Copilot only processes output on preTool events (permissionDecision: deny).
26
+ * All other events get a no-op success response since their output is ignored.
27
+ *
28
+ * @param mergedResult - The merged result from hook handler execution
29
+ * @param nativeEventName - The original native event name
30
+ * @returns JSON-serializable native output
31
+ */
32
+ export declare function renderCopilotOutput(mergedResult: MergedExecutionResult, nativeEventName: string): CopilotNativeOutput;
33
+ /**
34
+ * Serialize Copilot native output to a stdout-ready JSON string.
35
+ */
36
+ export declare function serializeOutput(output: CopilotNativeOutput): string;
37
+ //# 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,4BAA4B,CAAC;AAGxE;;;;;;GAMG;AACH,MAAM,WAAW,oBAAoB;IACnC,kBAAkB,CAAC,EAAE,OAAO,GAAG,MAAM,GAAG,KAAK,CAAC;IAC9C,MAAM,CAAC,EAAE,MAAM,CAAC;CACjB;AAED;;;;GAIG;AACH,MAAM,WAAW,iBAAiB;IAChC,EAAE,EAAE,IAAI,CAAC;CACV;AAED,MAAM,MAAM,mBAAmB,GAAG,oBAAoB,GAAG,iBAAiB,CAAC;AAE3E;;;;;;;;;GASG;AACH,wBAAgB,mBAAmB,CACjC,YAAY,EAAE,qBAAqB,EACnC,eAAe,EAAE,MAAM,GACtB,mBAAmB,CAUrB;AAuBD;;GAEG;AACH,wBAAgB,eAAe,CAAC,MAAM,EAAE,mBAAmB,GAAG,MAAM,CAEnE"}
@@ -0,0 +1,49 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.renderCopilotOutput = renderCopilotOutput;
4
+ exports.serializeOutput = serializeOutput;
5
+ const mappings_1 = require("./mappings");
6
+ /**
7
+ * Render a merged execution result into Copilot-native JSON output.
8
+ *
9
+ * Copilot only processes output on preTool events (permissionDecision: deny).
10
+ * All other events get a no-op success response since their output is ignored.
11
+ *
12
+ * @param mergedResult - The merged result from hook handler execution
13
+ * @param nativeEventName - The original native event name
14
+ * @returns JSON-serializable native output
15
+ */
16
+ function renderCopilotOutput(mergedResult, nativeEventName) {
17
+ const mapping = (0, mappings_1.getMappingByNativeHook)(nativeEventName);
18
+ // Only preTool events can block
19
+ if (mapping?.blockCapability && nativeEventName === 'preToolUse') {
20
+ return renderPreToolOutput(mergedResult);
21
+ }
22
+ // All other events: output is ignored by Copilot
23
+ return { ok: true };
24
+ }
25
+ /**
26
+ * Render output for preTool events.
27
+ *
28
+ * Maps the unified decision to Copilot's permissionDecision field.
29
+ * Only 'deny' is actually processed by Copilot CLI.
30
+ */
31
+ function renderPreToolOutput(mergedResult) {
32
+ const output = {};
33
+ if (mergedResult.decision === 'deny') {
34
+ output.permissionDecision = 'deny';
35
+ if (mergedResult.reason) {
36
+ output.reason = mergedResult.reason;
37
+ }
38
+ }
39
+ // allow and ask are in the schema but not processed;
40
+ // omit permissionDecision to let Copilot proceed with default behavior
41
+ return output;
42
+ }
43
+ /**
44
+ * Serialize Copilot native output to a stdout-ready JSON string.
45
+ */
46
+ function serializeOutput(output) {
47
+ return JSON.stringify(output);
48
+ }
49
+ //# sourceMappingURL=renderer.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"renderer.js","sourceRoot":"","sources":["../src/renderer.ts"],"names":[],"mappings":";;AAoCA,kDAaC;AA0BD,0CAEC;AA5ED,yCAAoD;AAyBpD;;;;;;;;;GASG;AACH,SAAgB,mBAAmB,CACjC,YAAmC,EACnC,eAAuB;IAEvB,MAAM,OAAO,GAAG,IAAA,iCAAsB,EAAC,eAAe,CAAC,CAAC;IAExD,gCAAgC;IAChC,IAAI,OAAO,EAAE,eAAe,IAAI,eAAe,KAAK,YAAY,EAAE,CAAC;QACjE,OAAO,mBAAmB,CAAC,YAAY,CAAC,CAAC;IAC3C,CAAC;IAED,iDAAiD;IACjD,OAAO,EAAE,EAAE,EAAE,IAAI,EAAE,CAAC;AACtB,CAAC;AAED;;;;;GAKG;AACH,SAAS,mBAAmB,CAAC,YAAmC;IAC9D,MAAM,MAAM,GAAyB,EAAE,CAAC;IAExC,IAAI,YAAY,CAAC,QAAQ,KAAK,MAAM,EAAE,CAAC;QACrC,MAAM,CAAC,kBAAkB,GAAG,MAAM,CAAC;QACnC,IAAI,YAAY,CAAC,MAAM,EAAE,CAAC;YACxB,MAAM,CAAC,MAAM,GAAG,YAAY,CAAC,MAAM,CAAC;QACtC,CAAC;IACH,CAAC;IACD,qDAAqD;IACrD,uEAAuE;IAEvE,OAAO,MAAM,CAAC;AAChB,CAAC;AAED;;GAEG;AACH,SAAgB,eAAe,CAAC,MAA2B;IACzD,OAAO,IAAI,CAAC,SAAS,CAAC,MAAM,CAAC,CAAC;AAChC,CAAC"}
@@ -0,0 +1,22 @@
1
+ /**
2
+ * Resolve a synthetic session ID for GitHub Copilot.
3
+ *
4
+ * Copilot CLI does not expose a stable native session ID.
5
+ * We derive a deterministic synthetic ID from cwd + workspace,
6
+ * producing a stable session key for a given project context.
7
+ *
8
+ * Derivation strategy:
9
+ * - Primary key: workspace path (if available), else cwd
10
+ * - Hashed with SHA-256 to produce a fixed-length, filesystem-safe ID
11
+ * - Prefixed with 'copilot-' for easy identification
12
+ *
13
+ * This means all sessions in the same workspace share context,
14
+ * which is acceptable since Copilot hooks are short-lived.
15
+ * The session store handles timestamp-based staleness if needed.
16
+ *
17
+ * @param cwd - Current working directory
18
+ * @param workspace - Workspace or project root path
19
+ * @returns A deterministic synthetic session ID string
20
+ */
21
+ export declare function resolveSyntheticSessionId(cwd?: string, workspace?: string): string;
22
+ //# 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;;;;;;;;;;;;;;;;;;;GAmBG;AACH,wBAAgB,yBAAyB,CACvC,GAAG,CAAC,EAAE,MAAM,EACZ,SAAS,CAAC,EAAE,MAAM,GACjB,MAAM,CAKR"}
@@ -0,0 +1,46 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.resolveSyntheticSessionId = resolveSyntheticSessionId;
4
+ const crypto_1 = require("crypto");
5
+ /**
6
+ * Resolve a synthetic session ID for GitHub Copilot.
7
+ *
8
+ * Copilot CLI does not expose a stable native session ID.
9
+ * We derive a deterministic synthetic ID from cwd + workspace,
10
+ * producing a stable session key for a given project context.
11
+ *
12
+ * Derivation strategy:
13
+ * - Primary key: workspace path (if available), else cwd
14
+ * - Hashed with SHA-256 to produce a fixed-length, filesystem-safe ID
15
+ * - Prefixed with 'copilot-' for easy identification
16
+ *
17
+ * This means all sessions in the same workspace share context,
18
+ * which is acceptable since Copilot hooks are short-lived.
19
+ * The session store handles timestamp-based staleness if needed.
20
+ *
21
+ * @param cwd - Current working directory
22
+ * @param workspace - Workspace or project root path
23
+ * @returns A deterministic synthetic session ID string
24
+ */
25
+ function resolveSyntheticSessionId(cwd, workspace) {
26
+ const key = workspace ?? cwd ?? 'unknown';
27
+ const normalized = normalizePath(key);
28
+ const hash = (0, crypto_1.createHash)('sha256').update(`copilot:${normalized}`).digest('hex').slice(0, 16);
29
+ return `copilot-${hash}`;
30
+ }
31
+ /**
32
+ * Normalize a file path for consistent hashing across platforms.
33
+ * Lowercases on Windows-style paths and normalizes separators.
34
+ */
35
+ function normalizePath(p) {
36
+ // Normalize backslashes to forward slashes
37
+ let normalized = p.replace(/\\/g, '/');
38
+ // Remove trailing slash
39
+ normalized = normalized.replace(/\/$/, '');
40
+ // Lowercase drive letter on Windows paths (e.g. C:/ -> c:/)
41
+ if (/^[A-Z]:\//.test(normalized)) {
42
+ normalized = normalized[0].toLowerCase() + normalized.slice(1);
43
+ }
44
+ return normalized;
45
+ }
46
+ //# sourceMappingURL=session-resolver.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"session-resolver.js","sourceRoot":"","sources":["../src/session-resolver.ts"],"names":[],"mappings":";;AAsBA,8DAQC;AA9BD,mCAAoC;AAEpC;;;;;;;;;;;;;;;;;;;GAmBG;AACH,SAAgB,yBAAyB,CACvC,GAAY,EACZ,SAAkB;IAElB,MAAM,GAAG,GAAG,SAAS,IAAI,GAAG,IAAI,SAAS,CAAC;IAC1C,MAAM,UAAU,GAAG,aAAa,CAAC,GAAG,CAAC,CAAC;IACtC,MAAM,IAAI,GAAG,IAAA,mBAAU,EAAC,QAAQ,CAAC,CAAC,MAAM,CAAC,WAAW,UAAU,EAAE,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC,KAAK,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC;IAC7F,OAAO,WAAW,IAAI,EAAE,CAAC;AAC3B,CAAC;AAED;;;GAGG;AACH,SAAS,aAAa,CAAC,CAAS;IAC9B,2CAA2C;IAC3C,IAAI,UAAU,GAAG,CAAC,CAAC,OAAO,CAAC,KAAK,EAAE,GAAG,CAAC,CAAC;IACvC,wBAAwB;IACxB,UAAU,GAAG,UAAU,CAAC,OAAO,CAAC,KAAK,EAAE,EAAE,CAAC,CAAC;IAC3C,4DAA4D;IAC5D,IAAI,WAAW,CAAC,IAAI,CAAC,UAAU,CAAC,EAAE,CAAC;QACjC,UAAU,GAAG,UAAU,CAAC,CAAC,CAAC,CAAC,WAAW,EAAE,GAAG,UAAU,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC;IACjE,CAAC;IACD,OAAO,UAAU,CAAC;AACpB,CAAC"}
package/package.json ADDED
@@ -0,0 +1,40 @@
1
+ {
2
+ "name": "@a5c-ai/hooks-adapter-copilot",
3
+ "version": "5.1.1-staging.52898ebfc24f",
4
+ "description": "GitHub Copilot harness adapter for the hooks-adapter 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/adapters/hooks/adapter-copilot"
16
+ },
17
+ "homepage": "https://github.com/a5c-ai/babysitter/tree/main/packages/adapters/hooks/adapter-copilot#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-adapter-core": "5.1.1-staging.52898ebfc24f"
34
+ },
35
+ "devDependencies": {
36
+ "rimraf": "^6.0.0",
37
+ "typescript": "^5.7.0",
38
+ "vitest": "^4.1.8"
39
+ }
40
+ }