@sp-editor/native-bridge 1.0.0

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.
@@ -0,0 +1,6 @@
1
+ #!/usr/bin/env node
2
+ // SP Editor native messaging host — spawned directly by Chrome/Edge.
3
+ // Reads length-prefixed JSON from stdin, writes length-prefixed JSON to stdout.
4
+ 'use strict'
5
+
6
+ require('../dist/host')
@@ -0,0 +1,58 @@
1
+ #!/usr/bin/env node
2
+ // SP Editor native bridge — CLI entry point
3
+ // Usage: sp-editor-bridge <install|uninstall|status> [--verbose] [--extension-id <id>]
4
+
5
+ 'use strict'
6
+
7
+ const { install, uninstall, status } = require('../dist/installer')
8
+
9
+ const args = process.argv.slice(2)
10
+ const cmd = args[0]
11
+
12
+ const verbose = args.includes('--verbose')
13
+ const idIndex = args.indexOf('--extension-id')
14
+ const extensionId = idIndex !== -1 ? args[idIndex + 1] : undefined
15
+
16
+ switch (cmd) {
17
+ case 'install':
18
+ try {
19
+ install({ verbose, extensionId })
20
+ } catch (err) {
21
+ console.error('Install failed:', err.message)
22
+ process.exit(1)
23
+ }
24
+ break
25
+
26
+ case 'uninstall':
27
+ try {
28
+ uninstall()
29
+ } catch (err) {
30
+ console.error('Uninstall failed:', err.message)
31
+ process.exit(1)
32
+ }
33
+ break
34
+
35
+ case 'status':
36
+ try {
37
+ status()
38
+ } catch (err) {
39
+ console.error('Status check failed:', err.message)
40
+ process.exit(1)
41
+ }
42
+ break
43
+
44
+ default:
45
+ console.log('SP Editor Native Bridge')
46
+ console.log('')
47
+ console.log('Usage:')
48
+ console.log(' sp-editor-bridge install Install for Chrome/Edge')
49
+ console.log(' sp-editor-bridge install --verbose Show each manifest path')
50
+ console.log(' sp-editor-bridge install --extension-id <id> Use custom extension ID')
51
+ console.log(' sp-editor-bridge uninstall Remove manifests/registry keys')
52
+ console.log(' sp-editor-bridge status Show installation status')
53
+ console.log('')
54
+ console.log('Prerequisites:')
55
+ console.log(' gh auth login Authenticate with GitHub')
56
+ console.log(' gh copilot First-time Copilot CLI setup')
57
+ break
58
+ }
@@ -0,0 +1,32 @@
1
+ /** Returns true if the standalone `copilot` CLI is available in PATH. */
2
+ export declare function isCopilotCliInstalled(): Promise<boolean>;
3
+ /**
4
+ * Returns true if the Copilot CLI has a stored authentication token.
5
+ *
6
+ * Detection strategy (in order):
7
+ * 1. macOS keychain — `security find-generic-password -s copilot-cli`
8
+ * 2. Token file — `~/.copilot/token` (copilot fallback when no keychain)
9
+ */
10
+ export declare function isCopilotAuthenticated(): Promise<boolean>;
11
+ /**
12
+ * Sends a prompt to the standalone `copilot` CLI and returns the plain-text response.
13
+ *
14
+ * Security notes:
15
+ * - The prompt is passed as a discrete argv element, never through a shell.
16
+ * - NO_COLOR=1 / TERM=dumb suppress ANSI / interactive output.
17
+ * - A 60 s hard timeout prevents the host from hanging.
18
+ * - Prompt size is validated by the host before this is called.
19
+ *
20
+ * @param prompt The prompt text to send.
21
+ * @param sessionId Optional session UUID for conversation continuity across calls.
22
+ * @param model Optional model identifier (e.g. 'gpt-5.2', 'claude-sonnet-4-5').
23
+ * Omit or pass 'auto' to let copilot choose the default model.
24
+ */
25
+ export declare function runCopilotPrompt(prompt: string, sessionId?: string, model?: string): Promise<{
26
+ ok: true;
27
+ response: string;
28
+ } | {
29
+ ok: false;
30
+ error: string;
31
+ }>;
32
+ //# sourceMappingURL=copilot.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"copilot.d.ts","sourceRoot":"","sources":["../src/copilot.ts"],"names":[],"mappings":"AAqFA,yEAAyE;AACzE,wBAAsB,qBAAqB,IAAI,OAAO,CAAC,OAAO,CAAC,CAG9D;AAED;;;;;;GAMG;AACH,wBAAsB,sBAAsB,IAAI,OAAO,CAAC,OAAO,CAAC,CAiB/D;AAED;;;;;;;;;;;;;GAaG;AACH,wBAAsB,gBAAgB,CACpC,MAAM,EAAE,MAAM,EACd,SAAS,CAAC,EAAE,MAAM,EAClB,KAAK,CAAC,EAAE,MAAM,GACb,OAAO,CAAC;IAAE,EAAE,EAAE,IAAI,CAAC;IAAC,QAAQ,EAAE,MAAM,CAAA;CAAE,GAAG;IAAE,EAAE,EAAE,KAAK,CAAC;IAAC,KAAK,EAAE,MAAM,CAAA;CAAE,CAAC,CA0CxE"}
@@ -0,0 +1,188 @@
1
+ "use strict";
2
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
+ if (k2 === undefined) k2 = k;
4
+ var desc = Object.getOwnPropertyDescriptor(m, k);
5
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
+ desc = { enumerable: true, get: function() { return m[k]; } };
7
+ }
8
+ Object.defineProperty(o, k2, desc);
9
+ }) : (function(o, m, k, k2) {
10
+ if (k2 === undefined) k2 = k;
11
+ o[k2] = m[k];
12
+ }));
13
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
14
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
15
+ }) : function(o, v) {
16
+ o["default"] = v;
17
+ });
18
+ var __importStar = (this && this.__importStar) || (function () {
19
+ var ownKeys = function(o) {
20
+ ownKeys = Object.getOwnPropertyNames || function (o) {
21
+ var ar = [];
22
+ for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
23
+ return ar;
24
+ };
25
+ return ownKeys(o);
26
+ };
27
+ return function (mod) {
28
+ if (mod && mod.__esModule) return mod;
29
+ var result = {};
30
+ if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
31
+ __setModuleDefault(result, mod);
32
+ return result;
33
+ };
34
+ })();
35
+ var __importDefault = (this && this.__importDefault) || function (mod) {
36
+ return (mod && mod.__esModule) ? mod : { "default": mod };
37
+ };
38
+ Object.defineProperty(exports, "__esModule", { value: true });
39
+ exports.isCopilotCliInstalled = isCopilotCliInstalled;
40
+ exports.isCopilotAuthenticated = isCopilotAuthenticated;
41
+ exports.runCopilotPrompt = runCopilotPrompt;
42
+ const child_process_1 = require("child_process");
43
+ const os_1 = __importDefault(require("os"));
44
+ const path_1 = __importDefault(require("path"));
45
+ const protocol_1 = require("./protocol");
46
+ /** Timeout for a single copilot call (ms). */
47
+ const COPILOT_TIMEOUT_MS = 180000; // 3 minutes — first messages with large system prompts can take longer
48
+ /** Timeout for fast health-check spawns (copilot --version, gh auth token). */
49
+ const CHECK_TIMEOUT_MS = 5000;
50
+ // ANSI escape code pattern
51
+ const ANSI_PATTERN = /\x1B\[[0-9;]*[A-Za-z]|\x1B\][^\x07]*\x07|\x1B[()][AB0-9]/g;
52
+ // Stats footer that copilot CLI appends to every non-interactive response:
53
+ // "\n\nChanges +0 -0\nRequests 1 Premium (5s)\nTokens ↑ 20.9k ..."
54
+ const FOOTER_PATTERN = /\n+Changes\s+\+\d+\s+-\d+[\s\S]*$/;
55
+ function stripAnsi(text) {
56
+ return text.replace(ANSI_PATTERN, '').trim();
57
+ }
58
+ function stripFooter(text) {
59
+ return text.replace(FOOTER_PATTERN, '').trim();
60
+ }
61
+ /**
62
+ * Builds an environment that augments PATH with common binary locations that
63
+ * Chrome's restricted launch environment omits (Homebrew, nvm, etc.).
64
+ */
65
+ function buildEnv(extra) {
66
+ const extraPaths = [
67
+ '/opt/homebrew/bin',
68
+ '/opt/homebrew/sbin',
69
+ '/usr/local/bin',
70
+ '/usr/local/sbin',
71
+ '/usr/bin',
72
+ '/bin',
73
+ // Include the directory of the current node executable so that globally
74
+ // installed npm binaries (e.g. @github/copilot) are always findable even
75
+ // when Chrome launches the host with a stripped-down PATH.
76
+ path_1.default.dirname(process.execPath),
77
+ ];
78
+ const current = process.env.PATH ?? '';
79
+ const parts = current.split(':').filter(Boolean);
80
+ for (const p of extraPaths.reverse()) {
81
+ if (!parts.includes(p))
82
+ parts.unshift(p);
83
+ }
84
+ return { ...process.env, PATH: parts.join(':'), ...extra };
85
+ }
86
+ /**
87
+ * Runs a command and returns { exitCode, stdout, stderr }.
88
+ * Never uses a shell — args are passed as an array to prevent injection.
89
+ */
90
+ function runCommand(cmd, args, timeoutMs, env) {
91
+ return new Promise((resolve) => {
92
+ const proc = (0, child_process_1.spawn)(cmd, args, {
93
+ shell: false,
94
+ cwd: os_1.default.tmpdir(),
95
+ env: buildEnv(env),
96
+ timeout: timeoutMs,
97
+ });
98
+ let stdout = '';
99
+ let stderr = '';
100
+ proc.stdout.on('data', (chunk) => { stdout += chunk.toString(); });
101
+ proc.stderr.on('data', (chunk) => { stderr += chunk.toString(); });
102
+ proc.on('close', (code) => {
103
+ resolve({ exitCode: code ?? 1, stdout, stderr });
104
+ });
105
+ proc.on('error', () => {
106
+ resolve({ exitCode: 1, stdout, stderr });
107
+ });
108
+ });
109
+ }
110
+ /** Returns true if the standalone `copilot` CLI is available in PATH. */
111
+ async function isCopilotCliInstalled() {
112
+ const result = await runCommand('copilot', ['--version'], CHECK_TIMEOUT_MS);
113
+ return result.exitCode === 0;
114
+ }
115
+ /**
116
+ * Returns true if the Copilot CLI has a stored authentication token.
117
+ *
118
+ * Detection strategy (in order):
119
+ * 1. macOS keychain — `security find-generic-password -s copilot-cli`
120
+ * 2. Token file — `~/.copilot/token` (copilot fallback when no keychain)
121
+ */
122
+ async function isCopilotAuthenticated() {
123
+ // 1. macOS Keychain
124
+ const keychainResult = await runCommand('security', ['find-generic-password', '-s', 'copilot-cli'], CHECK_TIMEOUT_MS);
125
+ if (keychainResult.exitCode === 0)
126
+ return true;
127
+ // 2. Plain-text token file (copilot fallback on Linux / headless macOS)
128
+ const tokenFile = path_1.default.join(os_1.default.homedir(), '.copilot', 'token');
129
+ try {
130
+ const fs = await Promise.resolve().then(() => __importStar(require('fs')));
131
+ return fs.existsSync(tokenFile);
132
+ }
133
+ catch {
134
+ return false;
135
+ }
136
+ }
137
+ /**
138
+ * Sends a prompt to the standalone `copilot` CLI and returns the plain-text response.
139
+ *
140
+ * Security notes:
141
+ * - The prompt is passed as a discrete argv element, never through a shell.
142
+ * - NO_COLOR=1 / TERM=dumb suppress ANSI / interactive output.
143
+ * - A 60 s hard timeout prevents the host from hanging.
144
+ * - Prompt size is validated by the host before this is called.
145
+ *
146
+ * @param prompt The prompt text to send.
147
+ * @param sessionId Optional session UUID for conversation continuity across calls.
148
+ * @param model Optional model identifier (e.g. 'gpt-5.2', 'claude-sonnet-4-5').
149
+ * Omit or pass 'auto' to let copilot choose the default model.
150
+ */
151
+ async function runCopilotPrompt(prompt, sessionId, model) {
152
+ if (prompt.length > protocol_1.PROMPT_SIZE_LIMIT) {
153
+ return { ok: false, error: `Prompt exceeds ${protocol_1.PROMPT_SIZE_LIMIT} character limit.` };
154
+ }
155
+ const env = {
156
+ NO_COLOR: '1',
157
+ TERM: 'dumb',
158
+ // Prevent gh from launching a browser / interactive flow
159
+ GH_PROMPT_DISABLED: '1',
160
+ };
161
+ const args = [];
162
+ if (sessionId) {
163
+ args.push('--session-id', sessionId);
164
+ }
165
+ if (model && model !== 'auto') {
166
+ args.push('--model', model);
167
+ }
168
+ args.push('-p', prompt);
169
+ const result = await runCommand('copilot', args, COPILOT_TIMEOUT_MS, env);
170
+ if (result.exitCode !== 0) {
171
+ // Try to recover a response from stdout even on non-zero exit —
172
+ // copilot sometimes exits with code 1 on warnings while still producing output.
173
+ const recoveredContent = stripFooter(stripAnsi(result.stdout));
174
+ if (recoveredContent) {
175
+ return { ok: true, response: recoveredContent };
176
+ }
177
+ // No recoverable content — report a clean error without leaking the raw footer.
178
+ const rawErr = stripFooter(stripAnsi(result.stderr || result.stdout || '')).trim();
179
+ const errText = rawErr || 'copilot did not return a response (exit code ' + result.exitCode + ')';
180
+ return { ok: false, error: errText };
181
+ }
182
+ const response = stripFooter(stripAnsi(result.stdout));
183
+ if (!response) {
184
+ return { ok: false, error: 'copilot returned an empty response' };
185
+ }
186
+ return { ok: true, response };
187
+ }
188
+ //# sourceMappingURL=copilot.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"copilot.js","sourceRoot":"","sources":["../src/copilot.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAsFA,sDAGC;AASD,wDAiBC;AAgBD,4CA8CC;AAjLD,iDAAqC;AACrC,4CAAmB;AACnB,gDAAuB;AACvB,yCAA8C;AAE9C,8CAA8C;AAC9C,MAAM,kBAAkB,GAAG,MAAO,CAAA,CAAE,uEAAuE;AAE3G,+EAA+E;AAC/E,MAAM,gBAAgB,GAAG,IAAK,CAAA;AAE9B,2BAA2B;AAC3B,MAAM,YAAY,GAAG,2DAA2D,CAAA;AAEhF,2EAA2E;AAC3E,8EAA8E;AAC9E,MAAM,cAAc,GAAG,mCAAmC,CAAA;AAE1D,SAAS,SAAS,CAAC,IAAY;IAC7B,OAAO,IAAI,CAAC,OAAO,CAAC,YAAY,EAAE,EAAE,CAAC,CAAC,IAAI,EAAE,CAAA;AAC9C,CAAC;AAED,SAAS,WAAW,CAAC,IAAY;IAC/B,OAAO,IAAI,CAAC,OAAO,CAAC,cAAc,EAAE,EAAE,CAAC,CAAC,IAAI,EAAE,CAAA;AAChD,CAAC;AAED;;;GAGG;AACH,SAAS,QAAQ,CAAC,KAAyB;IACzC,MAAM,UAAU,GAAG;QACjB,mBAAmB;QACnB,oBAAoB;QACpB,gBAAgB;QAChB,iBAAiB;QACjB,UAAU;QACV,MAAM;QACN,wEAAwE;QACxE,yEAAyE;QACzE,2DAA2D;QAC3D,cAAI,CAAC,OAAO,CAAC,OAAO,CAAC,QAAQ,CAAC;KAC/B,CAAA;IACD,MAAM,OAAO,GAAG,OAAO,CAAC,GAAG,CAAC,IAAI,IAAI,EAAE,CAAA;IACtC,MAAM,KAAK,GAAG,OAAO,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,MAAM,CAAC,OAAO,CAAC,CAAA;IAChD,KAAK,MAAM,CAAC,IAAI,UAAU,CAAC,OAAO,EAAE,EAAE,CAAC;QACrC,IAAI,CAAC,KAAK,CAAC,QAAQ,CAAC,CAAC,CAAC;YAAE,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,CAAA;IAC1C,CAAC;IACD,OAAO,EAAE,GAAG,OAAO,CAAC,GAAG,EAAE,IAAI,EAAE,KAAK,CAAC,IAAI,CAAC,GAAG,CAAC,EAAE,GAAG,KAAK,EAAE,CAAA;AAC5D,CAAC;AAED;;;GAGG;AACH,SAAS,UAAU,CACjB,GAAW,EACX,IAAc,EACd,SAAiB,EACjB,GAAuB;IAEvB,OAAO,IAAI,OAAO,CAAC,CAAC,OAAO,EAAE,EAAE;QAC7B,MAAM,IAAI,GAAG,IAAA,qBAAK,EAAC,GAAG,EAAE,IAAI,EAAE;YAC5B,KAAK,EAAE,KAAK;YACZ,GAAG,EAAE,YAAE,CAAC,MAAM,EAAE;YAChB,GAAG,EAAE,QAAQ,CAAC,GAAG,CAAC;YAClB,OAAO,EAAE,SAAS;SACnB,CAAC,CAAA;QAEF,IAAI,MAAM,GAAG,EAAE,CAAA;QACf,IAAI,MAAM,GAAG,EAAE,CAAA;QAEf,IAAI,CAAC,MAAM,CAAC,EAAE,CAAC,MAAM,EAAE,CAAC,KAAa,EAAE,EAAE,GAAG,MAAM,IAAI,KAAK,CAAC,QAAQ,EAAE,CAAA,CAAC,CAAC,CAAC,CAAA;QACzE,IAAI,CAAC,MAAM,CAAC,EAAE,CAAC,MAAM,EAAE,CAAC,KAAa,EAAE,EAAE,GAAG,MAAM,IAAI,KAAK,CAAC,QAAQ,EAAE,CAAA,CAAC,CAAC,CAAC,CAAA;QAEzE,IAAI,CAAC,EAAE,CAAC,OAAO,EAAE,CAAC,IAAI,EAAE,EAAE;YACxB,OAAO,CAAC,EAAE,QAAQ,EAAE,IAAI,IAAI,CAAC,EAAE,MAAM,EAAE,MAAM,EAAE,CAAC,CAAA;QAClD,CAAC,CAAC,CAAA;QAEF,IAAI,CAAC,EAAE,CAAC,OAAO,EAAE,GAAG,EAAE;YACpB,OAAO,CAAC,EAAE,QAAQ,EAAE,CAAC,EAAE,MAAM,EAAE,MAAM,EAAE,CAAC,CAAA;QAC1C,CAAC,CAAC,CAAA;IACJ,CAAC,CAAC,CAAA;AACJ,CAAC;AAED,yEAAyE;AAClE,KAAK,UAAU,qBAAqB;IACzC,MAAM,MAAM,GAAG,MAAM,UAAU,CAAC,SAAS,EAAE,CAAC,WAAW,CAAC,EAAE,gBAAgB,CAAC,CAAA;IAC3E,OAAO,MAAM,CAAC,QAAQ,KAAK,CAAC,CAAA;AAC9B,CAAC;AAED;;;;;;GAMG;AACI,KAAK,UAAU,sBAAsB;IAC1C,oBAAoB;IACpB,MAAM,cAAc,GAAG,MAAM,UAAU,CACrC,UAAU,EACV,CAAC,uBAAuB,EAAE,IAAI,EAAE,aAAa,CAAC,EAC9C,gBAAgB,CACjB,CAAA;IACD,IAAI,cAAc,CAAC,QAAQ,KAAK,CAAC;QAAE,OAAO,IAAI,CAAA;IAE9C,wEAAwE;IACxE,MAAM,SAAS,GAAG,cAAI,CAAC,IAAI,CAAC,YAAE,CAAC,OAAO,EAAE,EAAE,UAAU,EAAE,OAAO,CAAC,CAAA;IAC9D,IAAI,CAAC;QACH,MAAM,EAAE,GAAG,wDAAa,IAAI,GAAC,CAAA;QAC7B,OAAO,EAAE,CAAC,UAAU,CAAC,SAAS,CAAC,CAAA;IACjC,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,KAAK,CAAA;IACd,CAAC;AACH,CAAC;AAED;;;;;;;;;;;;;GAaG;AACI,KAAK,UAAU,gBAAgB,CACpC,MAAc,EACd,SAAkB,EAClB,KAAc;IAEd,IAAI,MAAM,CAAC,MAAM,GAAG,4BAAiB,EAAE,CAAC;QACtC,OAAO,EAAE,EAAE,EAAE,KAAK,EAAE,KAAK,EAAE,kBAAkB,4BAAiB,mBAAmB,EAAE,CAAA;IACrF,CAAC;IAED,MAAM,GAAG,GAAsB;QAC7B,QAAQ,EAAE,GAAG;QACb,IAAI,EAAE,MAAM;QACZ,yDAAyD;QACzD,kBAAkB,EAAE,GAAG;KACxB,CAAA;IAED,MAAM,IAAI,GAAa,EAAE,CAAA;IACzB,IAAI,SAAS,EAAE,CAAC;QACd,IAAI,CAAC,IAAI,CAAC,cAAc,EAAE,SAAS,CAAC,CAAA;IACtC,CAAC;IACD,IAAI,KAAK,IAAI,KAAK,KAAK,MAAM,EAAE,CAAC;QAC9B,IAAI,CAAC,IAAI,CAAC,SAAS,EAAE,KAAK,CAAC,CAAA;IAC7B,CAAC;IACD,IAAI,CAAC,IAAI,CAAC,IAAI,EAAE,MAAM,CAAC,CAAA;IAEvB,MAAM,MAAM,GAAG,MAAM,UAAU,CAAC,SAAS,EAAE,IAAI,EAAE,kBAAkB,EAAE,GAAG,CAAC,CAAA;IAEzE,IAAI,MAAM,CAAC,QAAQ,KAAK,CAAC,EAAE,CAAC;QAC1B,gEAAgE;QAChE,gFAAgF;QAChF,MAAM,gBAAgB,GAAG,WAAW,CAAC,SAAS,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC,CAAA;QAC9D,IAAI,gBAAgB,EAAE,CAAC;YACrB,OAAO,EAAE,EAAE,EAAE,IAAI,EAAE,QAAQ,EAAE,gBAAgB,EAAE,CAAA;QACjD,CAAC;QACD,gFAAgF;QAChF,MAAM,MAAM,GAAG,WAAW,CAAC,SAAS,CAAC,MAAM,CAAC,MAAM,IAAI,MAAM,CAAC,MAAM,IAAI,EAAE,CAAC,CAAC,CAAC,IAAI,EAAE,CAAA;QAClF,MAAM,OAAO,GAAG,MAAM,IAAI,+CAA+C,GAAG,MAAM,CAAC,QAAQ,GAAG,GAAG,CAAA;QACjG,OAAO,EAAE,EAAE,EAAE,KAAK,EAAE,KAAK,EAAE,OAAO,EAAE,CAAA;IACtC,CAAC;IAED,MAAM,QAAQ,GAAG,WAAW,CAAC,SAAS,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC,CAAA;IACtD,IAAI,CAAC,QAAQ,EAAE,CAAC;QACd,OAAO,EAAE,EAAE,EAAE,KAAK,EAAE,KAAK,EAAE,oCAAoC,EAAE,CAAA;IACnE,CAAC;IAED,OAAO,EAAE,EAAE,EAAE,IAAI,EAAE,QAAQ,EAAE,CAAA;AAC/B,CAAC"}
package/dist/host.d.ts ADDED
@@ -0,0 +1,15 @@
1
+ /**
2
+ * Chrome Native Messaging host — stdin/stdout length-prefixed JSON loop.
3
+ *
4
+ * Chrome spawns this process directly. It sends messages as:
5
+ * [4 bytes little-endian length][UTF-8 JSON]
6
+ * And expects responses in the same format.
7
+ *
8
+ * Security:
9
+ * - Only a hard-coded whitelist of message types is accepted.
10
+ * - Oversized payloads are rejected before any I/O with gh.
11
+ * - No shell evaluation; gh is spawned via argv array only.
12
+ * - Content (prompts / responses) is never written to any log.
13
+ */
14
+ export {};
15
+ //# sourceMappingURL=host.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"host.d.ts","sourceRoot":"","sources":["../src/host.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;GAYG"}
package/dist/host.js ADDED
@@ -0,0 +1,112 @@
1
+ "use strict";
2
+ /**
3
+ * Chrome Native Messaging host — stdin/stdout length-prefixed JSON loop.
4
+ *
5
+ * Chrome spawns this process directly. It sends messages as:
6
+ * [4 bytes little-endian length][UTF-8 JSON]
7
+ * And expects responses in the same format.
8
+ *
9
+ * Security:
10
+ * - Only a hard-coded whitelist of message types is accepted.
11
+ * - Oversized payloads are rejected before any I/O with gh.
12
+ * - No shell evaluation; gh is spawned via argv array only.
13
+ * - Content (prompts / responses) is never written to any log.
14
+ */
15
+ Object.defineProperty(exports, "__esModule", { value: true });
16
+ const copilot_1 = require("./copilot");
17
+ const protocol_1 = require("./protocol");
18
+ // ── I/O helpers ──────────────────────────────────────────────────────────────
19
+ function sendMessage(obj) {
20
+ const json = JSON.stringify(obj);
21
+ const encoded = Buffer.from(json, 'utf8');
22
+ const lenBuf = Buffer.alloc(4);
23
+ lenBuf.writeUInt32LE(encoded.length, 0); // byte length, not char length
24
+ process.stdout.write(lenBuf);
25
+ process.stdout.write(encoded);
26
+ }
27
+ function errorResponse(error) {
28
+ return { ok: false, error };
29
+ }
30
+ // ── Message routing ──────────────────────────────────────────────────────────
31
+ async function handleMessage(raw) {
32
+ if (!raw || typeof raw !== 'object') {
33
+ sendMessage(errorResponse('invalid_message'));
34
+ return;
35
+ }
36
+ const msg = raw;
37
+ const type = msg['type'];
38
+ if (type === 'ping') {
39
+ sendMessage({ ok: true });
40
+ return;
41
+ }
42
+ if (type === 'providers.status') {
43
+ const installed = await (0, copilot_1.isCopilotCliInstalled)();
44
+ const authenticated = installed ? await (0, copilot_1.isCopilotAuthenticated)() : false;
45
+ sendMessage({
46
+ ok: true,
47
+ providers: {
48
+ 'github-copilot': { installed, authenticated },
49
+ },
50
+ });
51
+ return;
52
+ }
53
+ if (type === 'ai.complete') {
54
+ const req = msg;
55
+ if (req.provider !== 'github-copilot') {
56
+ sendMessage(errorResponse(`unknown_provider: ${req.provider}`));
57
+ return;
58
+ }
59
+ const { prompt = '', sessionId, model } = req.payload ?? {};
60
+ if (typeof prompt !== 'string') {
61
+ sendMessage(errorResponse('payload_type_error'));
62
+ return;
63
+ }
64
+ if (prompt.length > protocol_1.PROMPT_SIZE_LIMIT) {
65
+ sendMessage(errorResponse(`prompt_too_large: ${prompt.length} > ${protocol_1.PROMPT_SIZE_LIMIT}`));
66
+ return;
67
+ }
68
+ const result = await (0, copilot_1.runCopilotPrompt)(prompt, typeof sessionId === 'string' ? sessionId : undefined, typeof model === 'string' ? model : undefined);
69
+ sendMessage(result.ok ? { ok: true, response: result.response } : errorResponse(result.error));
70
+ return;
71
+ }
72
+ // Unknown type — reject cleanly
73
+ sendMessage(errorResponse(`unknown_type: ${String(type)}`));
74
+ }
75
+ // ── Main loop ────────────────────────────────────────────────────────────────
76
+ let buf = Buffer.alloc(0);
77
+ process.stdin.on('data', (chunk) => {
78
+ buf = Buffer.concat([buf, chunk]);
79
+ processBuffer();
80
+ });
81
+ process.stdin.on('end', () => {
82
+ process.exit(0);
83
+ });
84
+ function processBuffer() {
85
+ // Each message is preceded by a 4-byte little-endian uint32 length.
86
+ while (buf.length >= 4) {
87
+ const len = buf.readUInt32LE(0);
88
+ // Sanity-check: refuse absurdly large messages before buffering them.
89
+ if (len > protocol_1.PROMPT_SIZE_LIMIT + 512) {
90
+ sendMessage(errorResponse('message_too_large'));
91
+ process.exit(1);
92
+ }
93
+ if (buf.length < 4 + len) {
94
+ // Incomplete — wait for more data.
95
+ break;
96
+ }
97
+ const msgBytes = buf.slice(4, 4 + len);
98
+ buf = buf.slice(4 + len);
99
+ let parsed;
100
+ try {
101
+ parsed = JSON.parse(msgBytes.toString('utf8'));
102
+ }
103
+ catch {
104
+ sendMessage(errorResponse('json_parse_error'));
105
+ continue;
106
+ }
107
+ handleMessage(parsed).catch(() => {
108
+ sendMessage(errorResponse('internal_error'));
109
+ });
110
+ }
111
+ }
112
+ //# sourceMappingURL=host.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"host.js","sourceRoot":"","sources":["../src/host.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,9 @@
1
+ export interface InstallOptions {
2
+ /** Override the extension ID (for dev / sideloaded builds). */
3
+ extensionId?: string;
4
+ verbose?: boolean;
5
+ }
6
+ export declare function install(opts?: InstallOptions): void;
7
+ export declare function uninstall(): void;
8
+ export declare function status(): void;
9
+ //# sourceMappingURL=installer.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"installer.d.ts","sourceRoot":"","sources":["../src/installer.ts"],"names":[],"mappings":"AA4EA,MAAM,WAAW,cAAc;IAC7B,+DAA+D;IAC/D,WAAW,CAAC,EAAE,MAAM,CAAA;IACpB,OAAO,CAAC,EAAE,OAAO,CAAA;CAClB;AAED,wBAAgB,OAAO,CAAC,IAAI,GAAE,cAAmB,GAAG,IAAI,CAsBvD;AAmGD,wBAAgB,SAAS,IAAI,IAAI,CAOhC;AAkCD,wBAAgB,MAAM,IAAI,IAAI,CAO7B"}
@@ -0,0 +1,278 @@
1
+ "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ exports.install = install;
7
+ exports.uninstall = uninstall;
8
+ exports.status = status;
9
+ const fs_1 = __importDefault(require("fs"));
10
+ const path_1 = __importDefault(require("path"));
11
+ const os_1 = __importDefault(require("os"));
12
+ const child_process_1 = require("child_process");
13
+ const protocol_1 = require("./protocol");
14
+ const MANIFEST_FILENAME = `${protocol_1.BRIDGE_NAME}.json`;
15
+ function buildManifest(hostExecutablePath) {
16
+ return {
17
+ name: protocol_1.BRIDGE_NAME,
18
+ description: 'SP Editor native messaging bridge for GitHub Copilot CLI',
19
+ path: hostExecutablePath,
20
+ type: 'stdio',
21
+ allowed_origins: [
22
+ `chrome-extension://${protocol_1.EXTENSION_ID}/`,
23
+ ],
24
+ };
25
+ }
26
+ /** Returns the absolute path to the compiled host.js in this package. */
27
+ function getHostJsPath() {
28
+ // __dirname = packages/native-bridge/dist (after compilation)
29
+ // or packages/native-bridge/src (when run directly with ts-node)
30
+ const base = __dirname;
31
+ return path_1.default.resolve(base, 'host.js');
32
+ }
33
+ // ── Platform-specific manifest paths ────────────────────────────────────────
34
+ function getMacOSManifestPaths() {
35
+ const home = os_1.default.homedir();
36
+ return [
37
+ path_1.default.join(home, 'Library', 'Application Support', 'Google', 'Chrome', 'NativeMessagingHosts'),
38
+ path_1.default.join(home, 'Library', 'Application Support', 'Microsoft Edge', 'NativeMessagingHosts'),
39
+ path_1.default.join(home, 'Library', 'Application Support', 'Chromium', 'NativeMessagingHosts'),
40
+ ];
41
+ }
42
+ function getLinuxManifestPaths() {
43
+ const home = os_1.default.homedir();
44
+ return [
45
+ path_1.default.join(home, '.config', 'google-chrome', 'NativeMessagingHosts'),
46
+ path_1.default.join(home, '.config', 'google-chrome-beta', 'NativeMessagingHosts'),
47
+ path_1.default.join(home, '.config', 'chromium', 'NativeMessagingHosts'),
48
+ path_1.default.join(home, '.config', 'microsoft-edge', 'NativeMessagingHosts'),
49
+ path_1.default.join(home, '.config', 'microsoft-edge-beta', 'NativeMessagingHosts'),
50
+ ];
51
+ }
52
+ /** On Windows, native messaging is registered via the registry. */
53
+ function getWindowsRegistryKeys() {
54
+ return [
55
+ `HKCU\\Software\\Google\\Chrome\\NativeMessagingHosts\\${protocol_1.BRIDGE_NAME}`,
56
+ `HKCU\\Software\\Microsoft\\Edge\\NativeMessagingHosts\\${protocol_1.BRIDGE_NAME}`,
57
+ ];
58
+ }
59
+ /** Returns path to the bridge data directory (~/.sp-editor-bridge). */
60
+ function getBridgeDataDir() {
61
+ if (process.platform === 'win32') {
62
+ return path_1.default.join(os_1.default.homedir(), 'AppData', 'Roaming', 'sp-editor-bridge');
63
+ }
64
+ return path_1.default.join(os_1.default.homedir(), '.sp-editor-bridge');
65
+ }
66
+ function install(opts = {}) {
67
+ const { extensionId, verbose } = opts;
68
+ const log = verbose ? console.log : () => { };
69
+ const hostJsPath = getHostJsPath();
70
+ if (!fs_1.default.existsSync(hostJsPath)) {
71
+ throw new Error(`Cannot find compiled host.js at ${hostJsPath}. Run 'npm run build' first.`);
72
+ }
73
+ if (process.platform === 'win32') {
74
+ installWindows(hostJsPath, extensionId, log);
75
+ }
76
+ else {
77
+ installUnix(hostJsPath, extensionId, log);
78
+ }
79
+ console.log(`\n✓ SP Editor native bridge installed successfully.`);
80
+ console.log(` Bridge: ${protocol_1.BRIDGE_NAME}`);
81
+ if (extensionId) {
82
+ console.log(` Extension ID: ${extensionId}`);
83
+ }
84
+ }
85
+ function installUnix(hostJsPath, extensionId, log) {
86
+ // Find the sp-editor-bridge-host.js path
87
+ const hostBinPath = resolveHostBinPath();
88
+ log(`Host JS: ${hostBinPath}`);
89
+ // Chrome spawns native hosts with a minimal PATH (no nvm, homebrew, etc.).
90
+ // We must resolve the absolute node executable now and write a sh wrapper
91
+ // that invokes node directly, so the host can always be found.
92
+ const nodeExec = resolveNodeExecutable();
93
+ log(`Node: ${nodeExec}`);
94
+ // Write wrapper to ~/.sp-editor-bridge/sp-editor-bridge-host.sh
95
+ const dataDir = getBridgeDataDir();
96
+ fs_1.default.mkdirSync(dataDir, { recursive: true });
97
+ const wrapperPath = path_1.default.join(dataDir, 'sp-editor-bridge-host.sh');
98
+ const wrapperContent = `#!/bin/sh\nexec "${nodeExec}" "${hostBinPath}" "$@"\n`;
99
+ fs_1.default.writeFileSync(wrapperPath, wrapperContent, 'utf8');
100
+ fs_1.default.chmodSync(wrapperPath, 0o755);
101
+ log(` Wrote wrapper → ${wrapperPath}`);
102
+ const manifest = buildManifest(wrapperPath);
103
+ if (extensionId) {
104
+ manifest.allowed_origins = [`chrome-extension://${extensionId}/`];
105
+ }
106
+ const manifestJson = JSON.stringify(manifest, null, 2);
107
+ const manifestPaths = process.platform === 'darwin' ? getMacOSManifestPaths() : getLinuxManifestPaths();
108
+ for (const dir of manifestPaths) {
109
+ try {
110
+ fs_1.default.mkdirSync(dir, { recursive: true });
111
+ const dest = path_1.default.join(dir, MANIFEST_FILENAME);
112
+ fs_1.default.writeFileSync(dest, manifestJson, 'utf8');
113
+ log(` Wrote manifest → ${dest}`);
114
+ }
115
+ catch (err) {
116
+ log(` Skipped ${dir}: ${err.message}`);
117
+ }
118
+ }
119
+ }
120
+ function resolveNodeExecutable() {
121
+ // 1. Use the node that's running this installer — it's definitely available.
122
+ if (process.execPath && fs_1.default.existsSync(process.execPath)) {
123
+ return process.execPath;
124
+ }
125
+ // 2. Fall back to searching common static paths
126
+ const candidates = [
127
+ '/opt/homebrew/bin/node',
128
+ '/usr/local/bin/node',
129
+ '/usr/bin/node',
130
+ ];
131
+ for (const p of candidates) {
132
+ if (fs_1.default.existsSync(p))
133
+ return p;
134
+ }
135
+ throw new Error('Cannot locate node executable. Make sure Node.js is installed.');
136
+ }
137
+ function installWindows(hostJsPath, extensionId, log) {
138
+ const dataDir = getBridgeDataDir();
139
+ fs_1.default.mkdirSync(dataDir, { recursive: true });
140
+ // Write a .bat wrapper that calls node with our host script
141
+ const batPath = path_1.default.join(dataDir, 'sp-editor-bridge-host.bat');
142
+ const batContent = `@echo off\nnode "${hostJsPath}" %*\n`;
143
+ fs_1.default.writeFileSync(batPath, batContent, 'utf8');
144
+ log(` Wrote host wrapper → ${batPath}`);
145
+ // Write the manifest JSON
146
+ const manifest = buildManifest(batPath);
147
+ if (extensionId) {
148
+ manifest.allowed_origins = [`chrome-extension://${extensionId}/`];
149
+ }
150
+ const manifestPath = path_1.default.join(dataDir, MANIFEST_FILENAME);
151
+ fs_1.default.writeFileSync(manifestPath, JSON.stringify(manifest, null, 2), 'utf8');
152
+ log(` Wrote manifest → ${manifestPath}`);
153
+ // Register in the Windows registry for Chrome and Edge
154
+ for (const regKey of getWindowsRegistryKeys()) {
155
+ try {
156
+ (0, child_process_1.execSync)(`reg add "${regKey}" /ve /d "${manifestPath}" /f`, { stdio: 'pipe' });
157
+ log(` Registry → ${regKey}`);
158
+ }
159
+ catch (err) {
160
+ log(` Warning: could not write registry key ${regKey}: ${err.message}`);
161
+ }
162
+ }
163
+ }
164
+ function uninstall() {
165
+ if (process.platform === 'win32') {
166
+ uninstallWindows();
167
+ }
168
+ else {
169
+ uninstallUnix();
170
+ }
171
+ console.log('✓ SP Editor native bridge uninstalled.');
172
+ }
173
+ function uninstallUnix() {
174
+ const dirs = process.platform === 'darwin' ? getMacOSManifestPaths() : getLinuxManifestPaths();
175
+ for (const dir of dirs) {
176
+ const f = path_1.default.join(dir, MANIFEST_FILENAME);
177
+ if (fs_1.default.existsSync(f)) {
178
+ fs_1.default.rmSync(f);
179
+ console.log(` Removed ${f}`);
180
+ }
181
+ }
182
+ }
183
+ function uninstallWindows() {
184
+ const dataDir = getBridgeDataDir();
185
+ // Remove registry keys
186
+ for (const regKey of getWindowsRegistryKeys()) {
187
+ try {
188
+ (0, child_process_1.execSync)(`reg delete "${regKey}" /f`, { stdio: 'pipe' });
189
+ console.log(` Registry removed: ${regKey}`);
190
+ }
191
+ catch {
192
+ // Key may not exist
193
+ }
194
+ }
195
+ // Remove data dir
196
+ if (fs_1.default.existsSync(dataDir)) {
197
+ fs_1.default.rmSync(dataDir, { recursive: true });
198
+ console.log(` Removed ${dataDir}`);
199
+ }
200
+ }
201
+ function status() {
202
+ console.log(`Bridge name: ${protocol_1.BRIDGE_NAME}`);
203
+ if (process.platform === 'win32') {
204
+ statusWindows();
205
+ }
206
+ else {
207
+ statusUnix();
208
+ }
209
+ }
210
+ function statusUnix() {
211
+ const dirs = process.platform === 'darwin' ? getMacOSManifestPaths() : getLinuxManifestPaths();
212
+ let found = false;
213
+ for (const dir of dirs) {
214
+ const f = path_1.default.join(dir, MANIFEST_FILENAME);
215
+ if (fs_1.default.existsSync(f)) {
216
+ console.log(` ✓ ${f}`);
217
+ found = true;
218
+ }
219
+ else {
220
+ console.log(` ✗ ${f}`);
221
+ }
222
+ }
223
+ if (!found) {
224
+ console.log('\nNot installed. Run: sp-editor-bridge install');
225
+ }
226
+ }
227
+ function statusWindows() {
228
+ const dataDir = getBridgeDataDir();
229
+ const manifestPath = path_1.default.join(dataDir, MANIFEST_FILENAME);
230
+ console.log(` Manifest: ${fs_1.default.existsSync(manifestPath) ? '✓' : '✗'} ${manifestPath}`);
231
+ for (const regKey of getWindowsRegistryKeys()) {
232
+ try {
233
+ (0, child_process_1.execSync)(`reg query "${regKey}"`, { stdio: 'pipe' });
234
+ console.log(` Registry: ✓ ${regKey}`);
235
+ }
236
+ catch {
237
+ console.log(` Registry: ✗ ${regKey}`);
238
+ }
239
+ }
240
+ }
241
+ // ── Helpers ──────────────────────────────────────────────────────────────────
242
+ /**
243
+ * Resolves the absolute path to `sp-editor-bridge-host.js`.
244
+ * Works whether running from source (ts-node) or from compiled dist via npm bin.
245
+ */
246
+ function resolveHostBinPath() {
247
+ // process.argv[1] is the CLI script (sp-editor-bridge.js)
248
+ // After compilation the layout is:
249
+ // packages/native-bridge/
250
+ // bin/sp-editor-bridge.js
251
+ // bin/sp-editor-bridge-host.js ← what we want
252
+ // dist/*.js
253
+ try {
254
+ const realCli = fs_1.default.realpathSync(process.argv[1]);
255
+ const binDir = path_1.default.dirname(realCli);
256
+ const hostPath = path_1.default.join(binDir, 'sp-editor-bridge-host.js');
257
+ if (fs_1.default.existsSync(hostPath)) {
258
+ return hostPath;
259
+ }
260
+ }
261
+ catch {
262
+ // Fall through to fallback
263
+ }
264
+ // Fallback: try which/where
265
+ try {
266
+ const which = process.platform === 'win32' ? 'where' : 'which';
267
+ const result = (0, child_process_1.execSync)(`${which} sp-editor-bridge-host`, { encoding: 'utf8' });
268
+ const line = result.trim().split('\n')[0];
269
+ if (line)
270
+ return line.trim();
271
+ }
272
+ catch {
273
+ // Ignore
274
+ }
275
+ throw new Error('Cannot locate sp-editor-bridge-host. ' +
276
+ 'Make sure you installed the package globally: npm install -g @sp-editor/native-bridge');
277
+ }
278
+ //# sourceMappingURL=installer.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"installer.js","sourceRoot":"","sources":["../src/installer.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,48 @@
1
+ export interface PingRequest {
2
+ type: 'ping';
3
+ }
4
+ export interface ProviderStatusRequest {
5
+ type: 'providers.status';
6
+ }
7
+ export interface AiCompleteRequest {
8
+ type: 'ai.complete';
9
+ provider: 'github-copilot';
10
+ payload: {
11
+ /** The prompt text to send (system+user for first message, user-only for continuations). */
12
+ prompt: string;
13
+ /** Session UUID for conversation continuity. Omit for a stateless one-shot call. */
14
+ sessionId?: string;
15
+ /** Model identifier, e.g. 'gpt-5.2'. Omit or 'auto' to use the default model. */
16
+ model?: string;
17
+ };
18
+ }
19
+ export type BridgeRequest = PingRequest | ProviderStatusRequest | AiCompleteRequest;
20
+ export interface PingResponse {
21
+ ok: true;
22
+ }
23
+ export interface GithubCopilotStatus {
24
+ installed: boolean;
25
+ authenticated: boolean;
26
+ }
27
+ export interface ProviderStatusResponse {
28
+ ok: true;
29
+ providers: {
30
+ 'github-copilot': GithubCopilotStatus;
31
+ };
32
+ }
33
+ export interface AiCompleteResponse {
34
+ ok: true;
35
+ response: string;
36
+ }
37
+ export interface ErrorResponse {
38
+ ok: false;
39
+ error: string;
40
+ }
41
+ export type BridgeResponse = PingResponse | ProviderStatusResponse | AiCompleteResponse | ErrorResponse;
42
+ /** Maximum combined prompt size in characters (32 KB). Enforced by the host. */
43
+ export declare const PROMPT_SIZE_LIMIT = 32768;
44
+ /** Name used in Chrome / Edge native messaging registration. */
45
+ export declare const BRIDGE_NAME = "fi.fireit.sp_editor_native_bridge";
46
+ /** Published Chrome / Edge extension ID for SP Editor. */
47
+ export declare const EXTENSION_ID = "affnnhcbfmcbbdlcadgkdbfafigmjdkk";
48
+ //# sourceMappingURL=protocol.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"protocol.d.ts","sourceRoot":"","sources":["../src/protocol.ts"],"names":[],"mappings":"AAMA,MAAM,WAAW,WAAW;IAC1B,IAAI,EAAE,MAAM,CAAA;CACb;AAED,MAAM,WAAW,qBAAqB;IACpC,IAAI,EAAE,kBAAkB,CAAA;CACzB;AAED,MAAM,WAAW,iBAAiB;IAChC,IAAI,EAAE,aAAa,CAAA;IACnB,QAAQ,EAAE,gBAAgB,CAAA;IAC1B,OAAO,EAAE;QACP,4FAA4F;QAC5F,MAAM,EAAE,MAAM,CAAA;QACd,oFAAoF;QACpF,SAAS,CAAC,EAAE,MAAM,CAAA;QAClB,iFAAiF;QACjF,KAAK,CAAC,EAAE,MAAM,CAAA;KACf,CAAA;CACF;AAED,MAAM,MAAM,aAAa,GAAG,WAAW,GAAG,qBAAqB,GAAG,iBAAiB,CAAA;AAInF,MAAM,WAAW,YAAY;IAC3B,EAAE,EAAE,IAAI,CAAA;CACT;AAED,MAAM,WAAW,mBAAmB;IAClC,SAAS,EAAE,OAAO,CAAA;IAClB,aAAa,EAAE,OAAO,CAAA;CACvB;AAED,MAAM,WAAW,sBAAsB;IACrC,EAAE,EAAE,IAAI,CAAA;IACR,SAAS,EAAE;QACT,gBAAgB,EAAE,mBAAmB,CAAA;KACtC,CAAA;CACF;AAED,MAAM,WAAW,kBAAkB;IACjC,EAAE,EAAE,IAAI,CAAA;IACR,QAAQ,EAAE,MAAM,CAAA;CACjB;AAED,MAAM,WAAW,aAAa;IAC5B,EAAE,EAAE,KAAK,CAAA;IACT,KAAK,EAAE,MAAM,CAAA;CACd;AAED,MAAM,MAAM,cAAc,GACtB,YAAY,GACZ,sBAAsB,GACtB,kBAAkB,GAClB,aAAa,CAAA;AAIjB,gFAAgF;AAChF,eAAO,MAAM,iBAAiB,QAAS,CAAA;AAEvC,gEAAgE;AAChE,eAAO,MAAM,WAAW,sCAAsC,CAAA;AAE9D,0DAA0D;AAC1D,eAAO,MAAM,YAAY,qCAAqC,CAAA"}
@@ -0,0 +1,14 @@
1
+ "use strict";
2
+ // ─── Shared protocol types for the SP Editor native messaging bridge ──────────
3
+ // These are the message shapes exchanged between the Chrome extension and the
4
+ // native host over stdin/stdout (Chrome native messaging protocol).
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ exports.EXTENSION_ID = exports.BRIDGE_NAME = exports.PROMPT_SIZE_LIMIT = void 0;
7
+ // ── Constants ────────────────────────────────────────────────────────────────
8
+ /** Maximum combined prompt size in characters (32 KB). Enforced by the host. */
9
+ exports.PROMPT_SIZE_LIMIT = 32768;
10
+ /** Name used in Chrome / Edge native messaging registration. */
11
+ exports.BRIDGE_NAME = 'fi.fireit.sp_editor_native_bridge';
12
+ /** Published Chrome / Edge extension ID for SP Editor. */
13
+ exports.EXTENSION_ID = 'affnnhcbfmcbbdlcadgkdbfafigmjdkk';
14
+ //# sourceMappingURL=protocol.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"protocol.js","sourceRoot":"","sources":["../src/protocol.ts"],"names":[],"mappings":";AAAA,iFAAiF;AACjF,8EAA8E;AAC9E,oEAAoE;;;AA6DpE,gFAAgF;AAEhF,gFAAgF;AACnE,QAAA,iBAAiB,GAAG,KAAM,CAAA;AAEvC,gEAAgE;AACnD,QAAA,WAAW,GAAG,mCAAmC,CAAA;AAE9D,0DAA0D;AAC7C,QAAA,YAAY,GAAG,kCAAkC,CAAA"}
package/package.json ADDED
@@ -0,0 +1,33 @@
1
+ {
2
+ "name": "@sp-editor/native-bridge",
3
+ "version": "1.0.0",
4
+ "description": "SP Editor native messaging bridge — routes AI prompts through the local GitHub Copilot CLI",
5
+ "main": "dist/host.js",
6
+ "bin": {
7
+ "sp-editor-bridge": "./bin/sp-editor-bridge.js",
8
+ "sp-editor-bridge-host": "./bin/sp-editor-bridge-host.js"
9
+ },
10
+ "scripts": {
11
+ "build": "tsc",
12
+ "prepublishOnly": "npm run build",
13
+ "test": "node test/harness.js"
14
+ },
15
+ "engines": {
16
+ "node": ">=18"
17
+ },
18
+ "files": [
19
+ "dist",
20
+ "bin"
21
+ ],
22
+ "keywords": [
23
+ "sharepoint",
24
+ "sp-editor",
25
+ "native-messaging",
26
+ "github-copilot"
27
+ ],
28
+ "license": "MIT",
29
+ "devDependencies": {
30
+ "@types/node": "^20.0.0",
31
+ "typescript": "^5.4.0"
32
+ }
33
+ }