@chrisromp/copilot-bridge 0.6.0 → 0.6.1

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.
@@ -52,6 +52,7 @@ if (!script) {
52
52
  const child = spawn(process.execPath, ['--import', 'tsx/esm', script, ...process.argv.slice(3)], {
53
53
  stdio: 'inherit',
54
54
  cwd: root,
55
+ env: { ...process.env, COPILOT_BRIDGE_CLI: '1' },
55
56
  });
56
57
 
57
58
  child.on('exit', (code) => process.exit(code ?? 1));
package/package.json CHANGED
@@ -1,9 +1,13 @@
1
1
  {
2
2
  "name": "@chrisromp/copilot-bridge",
3
- "version": "0.6.0",
3
+ "version": "0.6.1",
4
4
  "description": "Mattermost ↔ GitHub Copilot bridge",
5
5
  "type": "module",
6
6
  "main": "dist/index.js",
7
+ "repository": {
8
+ "type": "git",
9
+ "url": "https://github.com/ChrisRomp/copilot-bridge.git"
10
+ },
7
11
  "bin": {
8
12
  "copilot-bridge": "bin/copilot-bridge.js"
9
13
  },
@@ -14,11 +18,13 @@
14
18
  "scripts/lib/*.ts",
15
19
  "!scripts/**/*.test.ts",
16
20
  "!scripts/test-admin-api.ts",
21
+ "scripts/com.copilot-bridge.plist",
22
+ "scripts/copilot-bridge.service",
17
23
  "templates/",
18
24
  "config.sample.json"
19
25
  ],
20
26
  "publishConfig": {
21
- "access": "restricted"
27
+ "access": "public"
22
28
  },
23
29
  "engines": {
24
30
  "node": ">=20"
@@ -39,7 +45,7 @@
39
45
  "@github/copilot-sdk": "^0.1.32",
40
46
  "@mattermost/client": "^10.3.0",
41
47
  "@mattermost/types": "^10.3.0",
42
- "better-sqlite3": "^11.7.0",
48
+ "better-sqlite3": "^12.6.2",
43
49
  "cron": "^4.4.0",
44
50
  "cronstrue": "^3.13.0",
45
51
  "luxon": "^3.7.2",
@@ -50,6 +56,6 @@
50
56
  "@types/better-sqlite3": "^7.6.12",
51
57
  "@types/ws": "^8.5.14",
52
58
  "typescript": "^5.7.3",
53
- "vitest": "^3.2.1"
59
+ "vitest": "^4.0.18"
54
60
  }
55
61
  }
package/scripts/check.ts CHANGED
@@ -16,6 +16,7 @@ import { getConfigPath, getConfigDir } from './lib/config-gen.js';
16
16
  import { detectPlatform, getServiceStatus } from './lib/service.js';
17
17
 
18
18
  async function main() {
19
+ const isCli = process.env.COPILOT_BRIDGE_CLI === '1';
19
20
  console.log();
20
21
  heading('🔍 copilot-bridge check');
21
22
  dim('Validating your installation...\n');
@@ -38,7 +39,9 @@ async function main() {
38
39
  const result: CheckResult = { status: 'fail', label: 'Config file', detail: `not found at ${configPath}` };
39
40
  printCheck(result);
40
41
  results.push(result);
41
- info('Run "npm run init" to create a config file.');
42
+ info(isCli
43
+ ? 'Run "copilot-bridge init" to create a config file.'
44
+ : 'Run "npm run init" to create a config file.');
42
45
  printSummary(results);
43
46
  process.exit(results.some(r => r.status === 'fail') ? 1 : 0);
44
47
  }
@@ -227,10 +230,10 @@ async function main() {
227
230
  } else {
228
231
  const platform = detectPlatform();
229
232
  const serviceHint = platform === 'macos'
230
- ? 'install with: npm run install-service'
233
+ ? `install with: ${isCli ? 'copilot-bridge install-service' : 'npm run install-service'}`
231
234
  : platform === 'linux'
232
- ? 'install with: npm run install-service (requires sudo)'
233
- : 'start with: npm run dev (or npm start)';
235
+ ? `install with: ${isCli ? 'copilot-bridge install-service' : 'npm run install-service'} (requires sudo)`
236
+ : `start with: ${isCli ? 'copilot-bridge start' : 'npm run dev (or npm start)'}`;
234
237
  const result: CheckResult = { status: 'warn', label: 'Service not running', detail: serviceHint };
235
238
  printCheck(result);
236
239
  results.push(result);
@@ -0,0 +1,41 @@
1
+ <?xml version="1.0" encoding="UTF-8"?>
2
+ <!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
3
+ <plist version="1.0">
4
+ <dict>
5
+ <key>Label</key>
6
+ <string>com.copilot-bridge</string>
7
+
8
+ <key>ProgramArguments</key>
9
+ <array>
10
+ <string>/opt/homebrew/bin/npx</string>
11
+ <string>tsx</string>
12
+ <string>src/index.ts</string>
13
+ </array>
14
+
15
+ <key>WorkingDirectory</key>
16
+ <string>/Users/USERNAME/path/to/copilot-bridge</string>
17
+
18
+ <key>EnvironmentVariables</key>
19
+ <dict>
20
+ <key>PATH</key>
21
+ <string>/opt/homebrew/bin:/opt/homebrew/sbin:/usr/local/bin:/usr/bin:/bin:/usr/sbin:/sbin</string>
22
+ <key>HOME</key>
23
+ <string>/Users/USERNAME</string>
24
+ </dict>
25
+
26
+ <key>RunAtLoad</key>
27
+ <true/>
28
+
29
+ <key>KeepAlive</key>
30
+ <true/>
31
+
32
+ <key>ThrottleInterval</key>
33
+ <integer>10</integer>
34
+
35
+ <key>StandardOutPath</key>
36
+ <string>/tmp/copilot-bridge.log</string>
37
+
38
+ <key>StandardErrorPath</key>
39
+ <string>/tmp/copilot-bridge.log</string>
40
+ </dict>
41
+ </plist>
@@ -0,0 +1,30 @@
1
+ # copilot-bridge systemd service
2
+ #
3
+ # Install:
4
+ # sudo cp scripts/copilot-bridge.service /etc/systemd/system/
5
+ # # Edit ExecStart, WorkingDirectory, User, and HOME below
6
+ # sudo systemctl daemon-reload
7
+ # sudo systemctl enable --now copilot-bridge
8
+ #
9
+ # Logs:
10
+ # sudo journalctl -u copilot-bridge -f
11
+ #
12
+ # Restart:
13
+ # sudo systemctl restart copilot-bridge
14
+
15
+ [Unit]
16
+ Description=Copilot Bridge
17
+ After=network.target
18
+
19
+ [Service]
20
+ Type=simple
21
+ User=username
22
+ ExecStart=/usr/local/bin/node /path/to/copilot-bridge/node_modules/.bin/tsx dist/index.js
23
+ WorkingDirectory=/path/to/copilot-bridge
24
+ Environment=HOME=/home/username
25
+ Environment=PATH=/usr/local/bin:/usr/bin:/bin:/usr/sbin:/sbin
26
+ Restart=always
27
+ RestartSec=10
28
+
29
+ [Install]
30
+ WantedBy=multi-user.target
package/scripts/init.ts CHANGED
@@ -16,6 +16,7 @@ import { buildConfig, writeConfig, configExists, getConfigPath, getConfigDir, ty
16
16
  import { detectPlatform } from './lib/service.js';
17
17
 
18
18
  async function main() {
19
+ const isCli = process.env.COPILOT_BRIDGE_CLI === '1';
19
20
  console.log();
20
21
  heading('🚀 copilot-bridge setup');
21
22
  dim('Interactive wizard to configure copilot-bridge.\n');
@@ -50,7 +51,9 @@ async function main() {
50
51
  blank();
51
52
  warn(`Existing config found at ${getConfigPath()}`);
52
53
  if (!await confirm('Overwrite with a new config?', false)) {
53
- info('Run "npm run check" to validate your existing config.');
54
+ info(isCli
55
+ ? 'Run "copilot-bridge check" to validate your existing config.'
56
+ : 'Run "npm run check" to validate your existing config.');
54
57
  closePrompts();
55
58
  process.exit(0);
56
59
  }
@@ -103,7 +106,9 @@ async function main() {
103
106
  });
104
107
  success(`Added bot "${validation.bot.username}"${isAdmin ? ' (admin)' : ''}`);
105
108
  } else {
106
- warn('Token validation failed. The token was still added — verify it later with "npm run check".');
109
+ warn(isCli
110
+ ? 'Token validation failed. The token was still added — verify it later with "copilot-bridge check".'
111
+ : 'Token validation failed. The token was still added — verify it later with "npm run check".');
107
112
  let name = await askRequired('Bot username (for config)');
108
113
  name = name.replace(/^@/, '');
109
114
  bots.push({ name, token, admin: false });
@@ -214,14 +219,16 @@ async function main() {
214
219
  const osPlatform = detectPlatform();
215
220
  if (osPlatform === 'macos') {
216
221
  info('To run as a launchd service (auto-start at login):');
217
- dim(' npm run install-service\n');
222
+ dim(isCli ? ' copilot-bridge install-service\n' : ' npm run install-service\n');
218
223
  } else if (osPlatform === 'linux') {
219
224
  info('To run as a systemd service (auto-start at boot):');
220
- dim(' npm run install-service');
225
+ dim(isCli ? ' copilot-bridge install-service' : ' npm run install-service');
221
226
  dim(' (requires sudo — installs to /etc/systemd/system/)\n');
222
- dim(' Note: build first with npm run build\n');
227
+ if (!isCli) dim(' Note: build first with npm run build\n');
223
228
  } else {
224
- info('Run the bridge manually: npm run dev (development) or npm start (production)');
229
+ info(isCli
230
+ ? 'Run the bridge manually: copilot-bridge start'
231
+ : 'Run the bridge manually: npm run dev (development) or npm start (production)');
225
232
  }
226
233
 
227
234
  // --- Done ---
@@ -232,12 +239,19 @@ async function main() {
232
239
  if (channels.length > 0) info(`Channels: ${channels.length} configured`);
233
240
  info('DMs: enabled automatically');
234
241
  blank();
242
+
235
243
  dim('Next steps:');
236
- dim(' npm run dev Start in development mode (watch)');
237
- dim(' npm run check Validate your setup');
238
- dim(' npm run install-service Install as a system service');
239
- dim(' npm run build Build for production');
240
- dim(' npm start Start production server');
244
+ if (isCli) {
245
+ dim(' copilot-bridge check Validate your setup');
246
+ dim(' copilot-bridge start Start the bridge');
247
+ dim(' copilot-bridge install-service Install as a system service');
248
+ } else {
249
+ dim(' npm run dev Start in development mode (watch)');
250
+ dim(' npm run check Validate your setup');
251
+ dim(' npm run install-service Install as a system service');
252
+ dim(' npm run build Build for production');
253
+ dim(' npm start Start production server');
254
+ }
241
255
  blank();
242
256
 
243
257
  closePrompts();
@@ -21,6 +21,7 @@ import {
21
21
  import { execSync } from 'node:child_process';
22
22
 
23
23
  function main() {
24
+ const isCli = process.env.COPILOT_BRIDGE_CLI === '1';
24
25
  const osPlatform = detectPlatform();
25
26
  const bridgePath = process.cwd();
26
27
  const homePath = os.homedir();
@@ -35,7 +36,9 @@ function main() {
35
36
 
36
37
  const distPath = path.join(bridgePath, 'dist', 'index.js');
37
38
  if (!fs.existsSync(distPath)) {
38
- fail('dist/index.js not found. Run "npm run build" first.');
39
+ fail(isCli
40
+ ? 'dist/index.js not found. Package may be corrupted — try reinstalling.'
41
+ : 'dist/index.js not found. Run "npm run build" first.');
39
42
  process.exit(1);
40
43
  }
41
44
 
@@ -67,10 +70,11 @@ function main() {
67
70
  info('Linux detected — installing systemd service (system-scoped).');
68
71
  dim('The service starts at boot and restarts on crash.\n');
69
72
 
70
- // Check if dist/index.js exists
71
73
  const distPath = path.join(bridgePath, 'dist', 'index.js');
72
74
  if (!fs.existsSync(distPath)) {
73
- fail('dist/index.js not found. Run "npm run build" first.');
75
+ fail(isCli
76
+ ? 'dist/index.js not found. Package may be corrupted — try reinstalling.'
77
+ : 'dist/index.js not found. Run "npm run build" first.');
74
78
  process.exit(1);
75
79
  }
76
80
 
@@ -115,7 +119,9 @@ function main() {
115
119
 
116
120
  } else {
117
121
  fail('Unsupported platform for automatic service install.');
118
- info('Run the bridge manually: npm run dev (development) or npm start (production)');
122
+ info(isCli
123
+ ? 'Run the bridge manually: copilot-bridge start'
124
+ : 'Run the bridge manually: npm run dev (development) or npm start (production)');
119
125
  process.exit(1);
120
126
  }
121
127
  }