opalserve 3.1.1 → 3.2.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.
- package/README.md +38 -7
- package/dist/cli/commands/add.d.ts +7 -0
- package/dist/cli/commands/add.d.ts.map +1 -0
- package/dist/cli/commands/add.js +79 -0
- package/dist/cli/commands/add.js.map +1 -0
- package/dist/cli/commands/default.d.ts +7 -0
- package/dist/cli/commands/default.d.ts.map +1 -0
- package/dist/cli/commands/default.js +75 -0
- package/dist/cli/commands/default.js.map +1 -0
- package/dist/cli/commands/doctor.d.ts +2 -0
- package/dist/cli/commands/doctor.d.ts.map +1 -0
- package/dist/cli/commands/doctor.js +107 -0
- package/dist/cli/commands/doctor.js.map +1 -0
- package/dist/cli/commands/init.d.ts.map +1 -1
- package/dist/cli/commands/init.js +43 -4
- package/dist/cli/commands/init.js.map +1 -1
- package/dist/cli/commands/link.d.ts +11 -0
- package/dist/cli/commands/link.d.ts.map +1 -0
- package/dist/cli/commands/link.js +135 -0
- package/dist/cli/commands/link.js.map +1 -0
- package/dist/cli/commands/mcp.d.ts +7 -0
- package/dist/cli/commands/mcp.d.ts.map +1 -0
- package/dist/cli/commands/mcp.js +46 -0
- package/dist/cli/commands/mcp.js.map +1 -0
- package/dist/cli/commands/start.d.ts +1 -0
- package/dist/cli/commands/start.d.ts.map +1 -1
- package/dist/cli/commands/start.js +13 -0
- package/dist/cli/commands/start.js.map +1 -1
- package/dist/cli/editors/base.d.ts +23 -0
- package/dist/cli/editors/base.d.ts.map +1 -0
- package/dist/cli/editors/base.js +75 -0
- package/dist/cli/editors/base.js.map +1 -0
- package/dist/cli/editors/claude.d.ts +8 -0
- package/dist/cli/editors/claude.d.ts.map +1 -0
- package/dist/cli/editors/claude.js +31 -0
- package/dist/cli/editors/claude.js.map +1 -0
- package/dist/cli/editors/cline.d.ts +14 -0
- package/dist/cli/editors/cline.d.ts.map +1 -0
- package/dist/cli/editors/cline.js +32 -0
- package/dist/cli/editors/cline.js.map +1 -0
- package/dist/cli/editors/cursor.d.ts +8 -0
- package/dist/cli/editors/cursor.d.ts.map +1 -0
- package/dist/cli/editors/cursor.js +14 -0
- package/dist/cli/editors/cursor.js.map +1 -0
- package/dist/cli/editors/index.d.ts +14 -0
- package/dist/cli/editors/index.d.ts.map +1 -0
- package/dist/cli/editors/index.js +34 -0
- package/dist/cli/editors/index.js.map +1 -0
- package/dist/cli/editors/types.d.ts +33 -0
- package/dist/cli/editors/types.d.ts.map +1 -0
- package/dist/cli/editors/types.js +2 -0
- package/dist/cli/editors/types.js.map +1 -0
- package/dist/cli/index.js +43 -4
- package/dist/cli/index.js.map +1 -1
- package/dist/constants.d.ts +1 -1
- package/dist/constants.js +1 -1
- package/dist/utils/browser.d.ts +7 -0
- package/dist/utils/browser.d.ts.map +1 -0
- package/dist/utils/browser.js +34 -0
- package/dist/utils/browser.js.map +1 -0
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -95,13 +95,35 @@ opalserve server add --name files --stdio "npx -y @modelcontextprotocol/server-f
|
|
|
95
95
|
|
|
96
96
|
# 5. Discover available tools
|
|
97
97
|
opalserve tools search "read file"
|
|
98
|
+
|
|
99
|
+
# 6. Wire OpalServe into your AI editor
|
|
100
|
+
opalserve link claude # or: cursor, cline
|
|
101
|
+
# (restart the editor; OpalServe shows up as the "opalserve" MCP server)
|
|
98
102
|
```
|
|
99
103
|
|
|
100
|
-
> **Tip:** OpalServe runs on port **3456** by default. The dashboard ships inside the npm package and is served from `http://localhost:3456/dashboard
|
|
104
|
+
> **Tip:** OpalServe runs on port **3456** by default. The dashboard ships inside the npm package, opens automatically on `start`, and is served from `http://localhost:3456/dashboard`.
|
|
105
|
+
|
|
106
|
+
## Wire-Up — One Command
|
|
107
|
+
|
|
108
|
+
`opalserve link <editor>` writes the OpalServe MCP gateway into your editor's config so its AI assistant gets every tool you've registered. Supports **Claude Desktop**, **Cursor**, and **Cline (VS Code)**.
|
|
109
|
+
|
|
110
|
+
```bash
|
|
111
|
+
opalserve link cursor # link a single editor
|
|
112
|
+
opalserve link --all # link every detected editor
|
|
113
|
+
opalserve link --status # see what's linked, no changes
|
|
114
|
+
opalserve unlink cursor # remove later
|
|
115
|
+
opalserve doctor # diagnose port, gateway, links, secrets
|
|
116
|
+
```
|
|
117
|
+
|
|
118
|
+
Under the hood the editor spawns `npx -y opalserve mcp` as its MCP stdio process. Override with `OPALSERVE_LINK_COMMAND` env var if you want it to invoke a specific binary path instead.
|
|
119
|
+
|
|
120
|
+
## Releases
|
|
121
|
+
|
|
122
|
+
**3.2.1 — Coherence polish (current)**: smart `opalserve add <thing>` that detects URL → server, file → context doc, email → invite. Bare `opalserve` is now context-aware (shows status, hints, or first-run guide). Init wizard detects installed AI editors and offers to wire them up at the end.
|
|
101
123
|
|
|
102
|
-
|
|
124
|
+
**3.2.0 — Coherence**: `opalserve link <editor>` wires OpalServe into Claude Desktop / Cursor / Cline with one command, plus `opalserve doctor` for self-serve diagnostics, the `opalserve mcp` stdio entry-point, and auto-open of the dashboard on `start`.
|
|
103
125
|
|
|
104
|
-
|
|
126
|
+
**3.1.1 — Trust Patch**: hardens the auth and HTTP surface.
|
|
105
127
|
|
|
106
128
|
- **API keys** now use HMAC-SHA256 with a per-installation server secret (was unsalted SHA-256). Legacy keys are rehashed transparently on first use.
|
|
107
129
|
- **Auth bypass** (env-var fallback that silently disabled auth in non-team mode) removed. The registry's mode is now the single source of truth.
|
|
@@ -113,11 +135,11 @@ Disclosure policy: see [SECURITY.md](SECURITY.md).
|
|
|
113
135
|
|
|
114
136
|
```bash
|
|
115
137
|
opalserve --version
|
|
116
|
-
# 3.1
|
|
138
|
+
# 3.2.1
|
|
117
139
|
|
|
118
140
|
opalserve start
|
|
119
141
|
# HTTP API http://127.0.0.1:3456
|
|
120
|
-
# Dashboard http://127.0.0.1:3456/dashboard
|
|
142
|
+
# Dashboard http://127.0.0.1:3456/dashboard (opens in browser automatically)
|
|
121
143
|
```
|
|
122
144
|
|
|
123
145
|
For source builds, the same release checks are used locally and in CI:
|
|
@@ -254,9 +276,18 @@ http://localhost:3456/dashboard
|
|
|
254
276
|
|
|
255
277
|
| Command | Description |
|
|
256
278
|
|---|---|
|
|
257
|
-
| `opalserve
|
|
258
|
-
| `opalserve
|
|
279
|
+
| `opalserve` (no args) | Context-aware welcome: status if running, hints if not, first-run guide if fresh |
|
|
280
|
+
| `opalserve add <thing>` | Smart-add — URL → MCP server, file → context doc, email → invite |
|
|
281
|
+
| `opalserve init` | Interactive setup wizard -- configures mode, port, first server, links editors |
|
|
282
|
+
| `opalserve start` | Start the registry server (HTTP API + MCP gateway); opens dashboard in browser |
|
|
283
|
+
| `opalserve start --no-browser` | Start without auto-opening the dashboard |
|
|
259
284
|
| `opalserve status` | Show server status, connected servers, and tool counts |
|
|
285
|
+
| `opalserve doctor` | Self-diagnose port, gateway, registered servers, editor links, secrets |
|
|
286
|
+
| `opalserve link <editor>` | Wire OpalServe into Claude Desktop, Cursor, or Cline |
|
|
287
|
+
| `opalserve link --all` | Link every detected AI editor in one shot |
|
|
288
|
+
| `opalserve link --status` | Show editor link status (no changes) |
|
|
289
|
+
| `opalserve unlink <editor>` | Remove OpalServe from an editor's MCP config |
|
|
290
|
+
| `opalserve mcp` | Run as a stdio MCP server (used internally by linked editors) |
|
|
260
291
|
| `opalserve health` | Health check all registered servers |
|
|
261
292
|
| `opalserve health --server <name>` | Health check a specific server |
|
|
262
293
|
| `opalserve login` | Authenticate with a team server |
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"add.d.ts","sourceRoot":"","sources":["../../../src/cli/commands/add.ts"],"names":[],"mappings":"AAkCA,UAAU,UAAU;IAClB,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,SAAS,CAAC,EAAE,KAAK,GAAG,iBAAiB,CAAC;CACvC;AAED,wBAAsB,UAAU,CAAC,KAAK,EAAE,MAAM,GAAG,SAAS,EAAE,OAAO,EAAE,UAAU,GAAG,OAAO,CAAC,IAAI,CAAC,CAmD9F"}
|
|
@@ -0,0 +1,79 @@
|
|
|
1
|
+
import { existsSync, statSync } from 'node:fs';
|
|
2
|
+
import { resolve } from 'node:path';
|
|
3
|
+
import chalk from 'chalk';
|
|
4
|
+
import { showMiniBanner, showError, showInfo } from '../ui/banner.js';
|
|
5
|
+
import { contextAddCommand } from './context.js';
|
|
6
|
+
import { serverAddCommand } from './server.js';
|
|
7
|
+
import { adminInviteCommand } from './admin.js';
|
|
8
|
+
const URL_PATTERN = /^(?:https?|sse):\/\//i;
|
|
9
|
+
const EMAIL_PATTERN = /^[\w.+-]+@[\w-]+(?:\.[\w-]+)+$/;
|
|
10
|
+
function classify(input) {
|
|
11
|
+
const trimmed = input.trim();
|
|
12
|
+
if (URL_PATTERN.test(trimmed))
|
|
13
|
+
return { kind: 'server', url: trimmed };
|
|
14
|
+
if (EMAIL_PATTERN.test(trimmed))
|
|
15
|
+
return { kind: 'invite', email: trimmed };
|
|
16
|
+
if (!trimmed.includes('\0')) {
|
|
17
|
+
const resolved = resolve(trimmed);
|
|
18
|
+
if (existsSync(resolved)) {
|
|
19
|
+
try {
|
|
20
|
+
const stat = statSync(resolved);
|
|
21
|
+
if (stat.isFile() || stat.isDirectory())
|
|
22
|
+
return { kind: 'context', path: trimmed };
|
|
23
|
+
}
|
|
24
|
+
catch { /* fall through */ }
|
|
25
|
+
}
|
|
26
|
+
}
|
|
27
|
+
return { kind: 'unknown', input: trimmed };
|
|
28
|
+
}
|
|
29
|
+
export async function addCommand(input, options) {
|
|
30
|
+
if (!input) {
|
|
31
|
+
showMiniBanner();
|
|
32
|
+
showInfo(`Usage: ${chalk.cyan('opalserve add <thing>')}`);
|
|
33
|
+
console.log('');
|
|
34
|
+
console.log(` Smart-detects the kind of thing you're adding:`);
|
|
35
|
+
console.log(` ${chalk.cyan('https://...')} → MCP server (SSE / Streamable HTTP)`);
|
|
36
|
+
console.log(` ${chalk.cyan('./path/file.md')} → context document for the knowledge base`);
|
|
37
|
+
console.log(` ${chalk.cyan('user@team.com')} → invite a user (team mode)`);
|
|
38
|
+
console.log('');
|
|
39
|
+
console.log(` For stdio servers use ${chalk.cyan('opalserve server add')} (the sub-command still works).`);
|
|
40
|
+
console.log('');
|
|
41
|
+
return;
|
|
42
|
+
}
|
|
43
|
+
const target = classify(input);
|
|
44
|
+
switch (target.kind) {
|
|
45
|
+
case 'server': {
|
|
46
|
+
await serverAddCommand({
|
|
47
|
+
name: options.name,
|
|
48
|
+
url: target.url,
|
|
49
|
+
transport: options.transport ?? 'sse',
|
|
50
|
+
});
|
|
51
|
+
return;
|
|
52
|
+
}
|
|
53
|
+
case 'context': {
|
|
54
|
+
await contextAddCommand(target.path);
|
|
55
|
+
return;
|
|
56
|
+
}
|
|
57
|
+
case 'invite': {
|
|
58
|
+
await adminInviteCommand(target.email);
|
|
59
|
+
return;
|
|
60
|
+
}
|
|
61
|
+
case 'unknown': {
|
|
62
|
+
showMiniBanner();
|
|
63
|
+
showError(`Could not infer what to do with "${target.input}".`);
|
|
64
|
+
console.log('');
|
|
65
|
+
console.log(` Tried:`);
|
|
66
|
+
console.log(` URL pattern (${chalk.dim('http(s)://...')}) no match`);
|
|
67
|
+
console.log(` file path (${chalk.dim('not found on disk')})`);
|
|
68
|
+
console.log(` email pattern (${chalk.dim('not a@b.c')})`);
|
|
69
|
+
console.log('');
|
|
70
|
+
console.log(` Use one of the explicit subcommands instead:`);
|
|
71
|
+
console.log(` ${chalk.cyan('opalserve server add')}`);
|
|
72
|
+
console.log(` ${chalk.cyan('opalserve context add <file>')}`);
|
|
73
|
+
console.log(` ${chalk.cyan('opalserve admin invite <email>')}`);
|
|
74
|
+
console.log('');
|
|
75
|
+
process.exit(1);
|
|
76
|
+
}
|
|
77
|
+
}
|
|
78
|
+
}
|
|
79
|
+
//# sourceMappingURL=add.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"add.js","sourceRoot":"","sources":["../../../src/cli/commands/add.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Bare `opalserve` (no subcommand) — context-aware welcome.
|
|
3
|
+
* Doesn't auto-run anything destructive; surfaces what to do next based on
|
|
4
|
+
* what's on disk and whether the gateway is already running.
|
|
5
|
+
*/
|
|
6
|
+
export declare function defaultCommand(): Promise<void>;
|
|
7
|
+
//# sourceMappingURL=default.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"default.d.ts","sourceRoot":"","sources":["../../../src/cli/commands/default.ts"],"names":[],"mappings":"AAsBA;;;;GAIG;AACH,wBAAsB,cAAc,IAAI,OAAO,CAAC,IAAI,CAAC,CAsDpD"}
|
|
@@ -0,0 +1,75 @@
|
|
|
1
|
+
import { existsSync } from 'node:fs';
|
|
2
|
+
import { createConnection } from 'node:net';
|
|
3
|
+
import chalk from 'chalk';
|
|
4
|
+
import { showBanner, showInfo, showWarning } from '../ui/banner.js';
|
|
5
|
+
import { listInstalledEditors, OPALSERVE_ENTRY_NAME } from '../editors/index.js';
|
|
6
|
+
import { OpalServeRegistry } from '../../core/registry.js';
|
|
7
|
+
import { getDefaultDbPath } from '../../config/defaults.js';
|
|
8
|
+
function probePort(host, port, timeoutMs = 500) {
|
|
9
|
+
return new Promise(resolve => {
|
|
10
|
+
const socket = createConnection({ host, port });
|
|
11
|
+
const done = (live) => {
|
|
12
|
+
socket.removeAllListeners();
|
|
13
|
+
socket.destroy();
|
|
14
|
+
resolve(live);
|
|
15
|
+
};
|
|
16
|
+
const timer = setTimeout(() => done(false), timeoutMs);
|
|
17
|
+
socket.once('connect', () => { clearTimeout(timer); done(true); });
|
|
18
|
+
socket.once('error', () => { clearTimeout(timer); done(false); });
|
|
19
|
+
});
|
|
20
|
+
}
|
|
21
|
+
/**
|
|
22
|
+
* Bare `opalserve` (no subcommand) — context-aware welcome.
|
|
23
|
+
* Doesn't auto-run anything destructive; surfaces what to do next based on
|
|
24
|
+
* what's on disk and whether the gateway is already running.
|
|
25
|
+
*/
|
|
26
|
+
export async function defaultCommand() {
|
|
27
|
+
showBanner();
|
|
28
|
+
const dbPath = getDefaultDbPath();
|
|
29
|
+
const firstRun = !existsSync(dbPath);
|
|
30
|
+
if (firstRun) {
|
|
31
|
+
showInfo(chalk.bold('Looks like the first run on this machine.'));
|
|
32
|
+
console.log('');
|
|
33
|
+
console.log(` ${chalk.cyan('opalserve init')} Two-question setup wizard`);
|
|
34
|
+
console.log(` ${chalk.cyan('opalserve add <url>')} Smart-add an MCP server, context doc, or invite`);
|
|
35
|
+
console.log(` ${chalk.cyan('opalserve link <editor>')} Wire OpalServe into Claude Desktop, Cursor, or Cline`);
|
|
36
|
+
console.log(` ${chalk.cyan('opalserve doctor')} Check the install`);
|
|
37
|
+
console.log('');
|
|
38
|
+
return;
|
|
39
|
+
}
|
|
40
|
+
let registry = null;
|
|
41
|
+
try {
|
|
42
|
+
registry = await OpalServeRegistry.create({ logging: { level: 'silent' } });
|
|
43
|
+
}
|
|
44
|
+
catch {
|
|
45
|
+
showWarning('Could not load configuration — try `opalserve init` to start fresh.');
|
|
46
|
+
console.log('');
|
|
47
|
+
return;
|
|
48
|
+
}
|
|
49
|
+
const port = registry.config.gateway.port;
|
|
50
|
+
const host = registry.config.gateway.host === '0.0.0.0' ? '127.0.0.1' : registry.config.gateway.host;
|
|
51
|
+
const live = await probePort(host, port);
|
|
52
|
+
const servers = registry.listServers();
|
|
53
|
+
const tools = registry.listTools();
|
|
54
|
+
const linkedEditors = listInstalledEditors().filter(e => e.isLinked(OPALSERVE_ENTRY_NAME));
|
|
55
|
+
console.log(` ${chalk.bold('Status')}`);
|
|
56
|
+
console.log(` Server ${live ? chalk.green('running') + chalk.dim(` http://${host}:${port}`) : chalk.dim('idle (not running)')}`);
|
|
57
|
+
console.log(` Servers ${chalk.cyan(String(servers.length))} registered, ${chalk.cyan(String(servers.filter(s => s.status === 'connected').length))} connected`);
|
|
58
|
+
console.log(` Tools ${chalk.cyan(String(tools.length))} discovered`);
|
|
59
|
+
console.log(` Linked editors ${linkedEditors.length > 0 ? chalk.cyan(linkedEditors.map(e => e.id).join(', ')) : chalk.dim('none')}`);
|
|
60
|
+
console.log('');
|
|
61
|
+
console.log(` ${chalk.bold('Next:')}`);
|
|
62
|
+
if (!live) {
|
|
63
|
+
console.log(` ${chalk.cyan('opalserve start')} Start the registry (auto-opens dashboard)`);
|
|
64
|
+
}
|
|
65
|
+
else {
|
|
66
|
+
console.log(` Open the dashboard at ${chalk.cyan(`http://${host}:${port}/dashboard`)}`);
|
|
67
|
+
}
|
|
68
|
+
if (linkedEditors.length === 0) {
|
|
69
|
+
console.log(` ${chalk.cyan('opalserve link --all')} Wire detected AI editors`);
|
|
70
|
+
}
|
|
71
|
+
console.log(` ${chalk.cyan('opalserve doctor')} Diagnostic check`);
|
|
72
|
+
console.log('');
|
|
73
|
+
await registry.stop();
|
|
74
|
+
}
|
|
75
|
+
//# sourceMappingURL=default.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"default.js","sourceRoot":"","sources":["../../../src/cli/commands/default.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"doctor.d.ts","sourceRoot":"","sources":["../../../src/cli/commands/doctor.ts"],"names":[],"mappings":"AAwBA,wBAAsB,aAAa,IAAI,OAAO,CAAC,IAAI,CAAC,CA2FnD"}
|
|
@@ -0,0 +1,107 @@
|
|
|
1
|
+
import { existsSync } from 'node:fs';
|
|
2
|
+
import { createConnection } from 'node:net';
|
|
3
|
+
import chalk from 'chalk';
|
|
4
|
+
import { OpalServeRegistry } from '../../core/registry.js';
|
|
5
|
+
import { getApiKeySecretPath, getDefaultDbPath } from '../../config/defaults.js';
|
|
6
|
+
import { SUPPORTED_EDITORS, OPALSERVE_ENTRY_NAME } from '../editors/index.js';
|
|
7
|
+
import { showMiniBanner, showSuccess, showError, showInfo, showWarning } from '../ui/banner.js';
|
|
8
|
+
function isPortFree(host, port, timeoutMs = 800) {
|
|
9
|
+
return new Promise(resolve => {
|
|
10
|
+
const socket = createConnection({ host, port });
|
|
11
|
+
const done = (free) => {
|
|
12
|
+
socket.removeAllListeners();
|
|
13
|
+
socket.destroy();
|
|
14
|
+
resolve(free);
|
|
15
|
+
};
|
|
16
|
+
const timer = setTimeout(() => done(true), timeoutMs);
|
|
17
|
+
socket.once('connect', () => { clearTimeout(timer); done(false); });
|
|
18
|
+
socket.once('error', () => { clearTimeout(timer); done(true); });
|
|
19
|
+
});
|
|
20
|
+
}
|
|
21
|
+
export async function doctorCommand() {
|
|
22
|
+
showMiniBanner();
|
|
23
|
+
console.log(chalk.bold(' Running diagnostics...\n'));
|
|
24
|
+
const checks = [];
|
|
25
|
+
try {
|
|
26
|
+
const registry = await OpalServeRegistry.create({ logging: { level: 'silent' } });
|
|
27
|
+
checks.push({
|
|
28
|
+
name: 'config',
|
|
29
|
+
ok: true,
|
|
30
|
+
level: 'info',
|
|
31
|
+
detail: `mode=${registry.config.mode}, port=${registry.config.gateway.port}`,
|
|
32
|
+
});
|
|
33
|
+
const dbPath = registry.config.storage.path || getDefaultDbPath();
|
|
34
|
+
checks.push({
|
|
35
|
+
name: 'database',
|
|
36
|
+
ok: existsSync(dbPath),
|
|
37
|
+
level: existsSync(dbPath) ? 'info' : 'warn',
|
|
38
|
+
detail: dbPath,
|
|
39
|
+
});
|
|
40
|
+
const secretPath = getApiKeySecretPath();
|
|
41
|
+
checks.push({
|
|
42
|
+
name: 'api-key secret',
|
|
43
|
+
ok: existsSync(secretPath) || !!process.env.OPALSERVE_API_KEY_SECRET,
|
|
44
|
+
level: 'info',
|
|
45
|
+
detail: process.env.OPALSERVE_API_KEY_SECRET ? '(from env)' : secretPath,
|
|
46
|
+
});
|
|
47
|
+
const port = registry.config.gateway.port;
|
|
48
|
+
const host = registry.config.gateway.host;
|
|
49
|
+
const portFree = await isPortFree(host, port);
|
|
50
|
+
checks.push({
|
|
51
|
+
name: `port ${port}`,
|
|
52
|
+
ok: true,
|
|
53
|
+
level: portFree ? 'info' : 'warn',
|
|
54
|
+
detail: portFree ? 'available' : 'in use (server may already be running)',
|
|
55
|
+
});
|
|
56
|
+
const servers = registry.listServers();
|
|
57
|
+
checks.push({
|
|
58
|
+
name: 'registered servers',
|
|
59
|
+
ok: servers.length > 0,
|
|
60
|
+
level: servers.length > 0 ? 'info' : 'warn',
|
|
61
|
+
detail: servers.length === 0
|
|
62
|
+
? 'none registered yet — try `opalserve add` or `opalserve init`'
|
|
63
|
+
: `${servers.length} (${servers.filter(s => s.status === 'connected').length} connected)`,
|
|
64
|
+
});
|
|
65
|
+
for (const editor of SUPPORTED_EDITORS) {
|
|
66
|
+
const status = editor.status(OPALSERVE_ENTRY_NAME);
|
|
67
|
+
checks.push({
|
|
68
|
+
name: `editor: ${editor.displayName}`,
|
|
69
|
+
ok: status.linked,
|
|
70
|
+
level: status.installed ? (status.linked ? 'info' : 'warn') : 'info',
|
|
71
|
+
detail: !status.installed
|
|
72
|
+
? 'not installed on this machine'
|
|
73
|
+
: status.linked
|
|
74
|
+
? `linked → ${status.configPath}`
|
|
75
|
+
: `installed but not linked — run \`opalserve link ${editor.id}\``,
|
|
76
|
+
});
|
|
77
|
+
}
|
|
78
|
+
await registry.stop();
|
|
79
|
+
}
|
|
80
|
+
catch (err) {
|
|
81
|
+
checks.push({
|
|
82
|
+
name: 'registry',
|
|
83
|
+
ok: false,
|
|
84
|
+
level: 'error',
|
|
85
|
+
detail: err instanceof Error ? err.message : String(err),
|
|
86
|
+
});
|
|
87
|
+
}
|
|
88
|
+
for (const c of checks) {
|
|
89
|
+
if (c.level === 'error')
|
|
90
|
+
showError(`${c.name.padEnd(28)} ${c.detail ? chalk.dim(c.detail) : ''}`);
|
|
91
|
+
else if (c.level === 'warn')
|
|
92
|
+
showWarning(`${c.name.padEnd(28)} ${c.detail ? chalk.dim(c.detail) : ''}`);
|
|
93
|
+
else if (c.ok)
|
|
94
|
+
showSuccess(`${c.name.padEnd(28)} ${c.detail ? chalk.dim(c.detail) : ''}`);
|
|
95
|
+
else
|
|
96
|
+
showInfo(`${c.name.padEnd(28)} ${c.detail ? chalk.dim(c.detail) : ''}`);
|
|
97
|
+
}
|
|
98
|
+
const errors = checks.filter(c => c.level === 'error').length;
|
|
99
|
+
console.log('');
|
|
100
|
+
if (errors > 0) {
|
|
101
|
+
showError(`${errors} error(s) found.`);
|
|
102
|
+
process.exit(1);
|
|
103
|
+
}
|
|
104
|
+
showSuccess('All checks passed.');
|
|
105
|
+
console.log('');
|
|
106
|
+
}
|
|
107
|
+
//# sourceMappingURL=doctor.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"doctor.js","sourceRoot":"","sources":["../../../src/cli/commands/doctor.ts"],"names":[],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"init.d.ts","sourceRoot":"","sources":["../../../src/cli/commands/init.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"init.d.ts","sourceRoot":"","sources":["../../../src/cli/commands/init.ts"],"names":[],"mappings":"AAaA,wBAAsB,WAAW,IAAI,OAAO,CAAC,IAAI,CAAC,CA2DjD"}
|
|
@@ -1,9 +1,10 @@
|
|
|
1
1
|
import { writeFileSync } from 'node:fs';
|
|
2
2
|
import { resolve } from 'node:path';
|
|
3
3
|
import chalk from 'chalk';
|
|
4
|
-
import { select } from '@inquirer/prompts';
|
|
4
|
+
import { select, checkbox } from '@inquirer/prompts';
|
|
5
5
|
import { showBox, showSuccess, showInfo } from '../ui/banner.js';
|
|
6
6
|
import { promptServerName, promptTransportType, promptStdioCommand, promptUrl, promptEnvVars, promptConfirm, promptPort } from '../ui/prompts.js';
|
|
7
|
+
import { SUPPORTED_EDITORS, OPALSERVE_ENTRY_NAME, buildOpalserveEntry, } from '../editors/index.js';
|
|
7
8
|
export async function initCommand() {
|
|
8
9
|
showBox(`Welcome to ${chalk.bold('OpalServe')} Setup\n\n` +
|
|
9
10
|
'This wizard will help you configure OpalServe\n' +
|
|
@@ -43,13 +44,51 @@ export async function initCommand() {
|
|
|
43
44
|
mkdirSync(dirname(configPath), { recursive: true });
|
|
44
45
|
writeFileSync(configPath, JSON.stringify(config, null, 2) + '\n');
|
|
45
46
|
showSuccess(`Configuration saved to ${chalk.cyan(configPath)}`);
|
|
47
|
+
await offerEditorLink();
|
|
46
48
|
console.log('');
|
|
47
49
|
showInfo('Next steps:');
|
|
48
|
-
console.log(` ${chalk.cyan('opalserve start')} Start the registry`);
|
|
49
|
-
console.log(` ${chalk.cyan('opalserve
|
|
50
|
-
console.log(` ${chalk.cyan('opalserve
|
|
50
|
+
console.log(` ${chalk.cyan('opalserve start')} Start the registry (auto-opens dashboard)`);
|
|
51
|
+
console.log(` ${chalk.cyan('opalserve add <thing>')} Smart-add a server / context doc / invite`);
|
|
52
|
+
console.log(` ${chalk.cyan('opalserve doctor')} Diagnostic check`);
|
|
51
53
|
console.log('');
|
|
52
54
|
}
|
|
55
|
+
async function offerEditorLink() {
|
|
56
|
+
const detected = SUPPORTED_EDITORS.filter(e => e.detect());
|
|
57
|
+
if (detected.length === 0)
|
|
58
|
+
return;
|
|
59
|
+
console.log('');
|
|
60
|
+
showInfo(`Detected ${detected.length} AI editor(s) on this machine: ${chalk.cyan(detected.map(e => e.displayName).join(', '))}`);
|
|
61
|
+
const wire = await promptConfirm('Wire OpalServe into them now? (you can do this later with `opalserve link`)', true);
|
|
62
|
+
if (!wire)
|
|
63
|
+
return;
|
|
64
|
+
const choices = detected.map(e => ({
|
|
65
|
+
name: `${e.displayName} ${chalk.dim(`(${e.getConfigPath()})`)}`,
|
|
66
|
+
value: e.id,
|
|
67
|
+
checked: true,
|
|
68
|
+
}));
|
|
69
|
+
const selected = await checkbox({
|
|
70
|
+
message: 'Pick the editors to link:',
|
|
71
|
+
choices,
|
|
72
|
+
});
|
|
73
|
+
if (selected.length === 0)
|
|
74
|
+
return;
|
|
75
|
+
const entry = buildOpalserveEntry();
|
|
76
|
+
for (const id of selected) {
|
|
77
|
+
const adapter = detected.find(e => e.id === id);
|
|
78
|
+
if (!adapter)
|
|
79
|
+
continue;
|
|
80
|
+
try {
|
|
81
|
+
const prior = adapter.link(OPALSERVE_ENTRY_NAME, entry);
|
|
82
|
+
const verb = prior ? 'updated' : 'wired up';
|
|
83
|
+
showSuccess(`${adapter.displayName} ${verb}`);
|
|
84
|
+
}
|
|
85
|
+
catch (err) {
|
|
86
|
+
console.log(` ${chalk.red('✗')} ${adapter.displayName}: ${err instanceof Error ? err.message : String(err)}`);
|
|
87
|
+
}
|
|
88
|
+
}
|
|
89
|
+
console.log('');
|
|
90
|
+
showInfo('Restart your editor for it to pick up the new MCP server.');
|
|
91
|
+
}
|
|
53
92
|
async function promptServerConfig() {
|
|
54
93
|
const name = await promptServerName();
|
|
55
94
|
const transportType = await promptTransportType();
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"init.js","sourceRoot":"","sources":["../../../src/cli/commands/init.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,aAAa,EAAE,MAAM,SAAS,CAAC;AACxC,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AACpC,OAAO,KAAK,MAAM,OAAO,CAAC;AAC1B,OAAO,EAAE,MAAM,EAAE,MAAM,mBAAmB,CAAC;
|
|
1
|
+
{"version":3,"file":"init.js","sourceRoot":"","sources":["../../../src/cli/commands/init.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
interface LinkOptions {
|
|
2
|
+
all?: boolean;
|
|
3
|
+
status?: boolean;
|
|
4
|
+
}
|
|
5
|
+
interface UnlinkOptions {
|
|
6
|
+
all?: boolean;
|
|
7
|
+
}
|
|
8
|
+
export declare function linkCommand(editorId: string | undefined, options: LinkOptions): Promise<void>;
|
|
9
|
+
export declare function unlinkCommand(editorId: string | undefined, options: UnlinkOptions): Promise<void>;
|
|
10
|
+
export {};
|
|
11
|
+
//# sourceMappingURL=link.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"link.d.ts","sourceRoot":"","sources":["../../../src/cli/commands/link.ts"],"names":[],"mappings":"AAUA,UAAU,WAAW;IACnB,GAAG,CAAC,EAAE,OAAO,CAAC;IACd,MAAM,CAAC,EAAE,OAAO,CAAC;CAClB;AAED,UAAU,aAAa;IACrB,GAAG,CAAC,EAAE,OAAO,CAAC;CACf;AA0CD,wBAAsB,WAAW,CAAC,QAAQ,EAAE,MAAM,GAAG,SAAS,EAAE,OAAO,EAAE,WAAW,GAAG,OAAO,CAAC,IAAI,CAAC,CA0DnG;AAED,wBAAsB,aAAa,CAAC,QAAQ,EAAE,MAAM,GAAG,SAAS,EAAE,OAAO,EAAE,aAAa,GAAG,OAAO,CAAC,IAAI,CAAC,CAsCvG"}
|
|
@@ -0,0 +1,135 @@
|
|
|
1
|
+
import chalk from 'chalk';
|
|
2
|
+
import { SUPPORTED_EDITORS, OPALSERVE_ENTRY_NAME, buildOpalserveEntry, getEditor, } from '../editors/index.js';
|
|
3
|
+
import { showMiniBanner, showSuccess, showError, showInfo, showWarning, showBox } from '../ui/banner.js';
|
|
4
|
+
function formatStatusLine(adapter) {
|
|
5
|
+
const status = adapter.status(OPALSERVE_ENTRY_NAME);
|
|
6
|
+
const presence = status.installed
|
|
7
|
+
? chalk.green('detected')
|
|
8
|
+
: chalk.dim('not detected');
|
|
9
|
+
const linked = status.linked
|
|
10
|
+
? chalk.cyan('linked')
|
|
11
|
+
: chalk.gray('not linked');
|
|
12
|
+
return ` ${chalk.bold(adapter.displayName.padEnd(20))} ${presence} · ${linked}\n ${chalk.dim(status.configPath)}`;
|
|
13
|
+
}
|
|
14
|
+
function showStatusTable() {
|
|
15
|
+
console.log('');
|
|
16
|
+
console.log(chalk.bold(' AI editor status:'));
|
|
17
|
+
console.log('');
|
|
18
|
+
for (const editor of SUPPORTED_EDITORS) {
|
|
19
|
+
console.log(formatStatusLine(editor));
|
|
20
|
+
}
|
|
21
|
+
console.log('');
|
|
22
|
+
}
|
|
23
|
+
function linkOne(adapter) {
|
|
24
|
+
try {
|
|
25
|
+
const entry = buildOpalserveEntry();
|
|
26
|
+
const prior = adapter.link(OPALSERVE_ENTRY_NAME, entry);
|
|
27
|
+
return { ok: true, replaced: prior !== null };
|
|
28
|
+
}
|
|
29
|
+
catch (err) {
|
|
30
|
+
return { ok: false, replaced: false, error: err instanceof Error ? err.message : String(err) };
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
function unlinkOne(adapter) {
|
|
34
|
+
try {
|
|
35
|
+
const removed = adapter.unlink(OPALSERVE_ENTRY_NAME);
|
|
36
|
+
return { ok: true, removed };
|
|
37
|
+
}
|
|
38
|
+
catch (err) {
|
|
39
|
+
return { ok: false, removed: false, error: err instanceof Error ? err.message : String(err) };
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
export async function linkCommand(editorId, options) {
|
|
43
|
+
showMiniBanner();
|
|
44
|
+
if (options.status) {
|
|
45
|
+
showStatusTable();
|
|
46
|
+
return;
|
|
47
|
+
}
|
|
48
|
+
let targets = [];
|
|
49
|
+
if (editorId) {
|
|
50
|
+
const adapter = getEditor(editorId);
|
|
51
|
+
if (!adapter) {
|
|
52
|
+
showError(`Unknown editor "${editorId}". Supported: ${SUPPORTED_EDITORS.map(e => e.id).join(', ')}`);
|
|
53
|
+
process.exit(1);
|
|
54
|
+
}
|
|
55
|
+
targets = [adapter];
|
|
56
|
+
}
|
|
57
|
+
else if (options.all) {
|
|
58
|
+
targets = SUPPORTED_EDITORS.filter(e => e.detect());
|
|
59
|
+
if (targets.length === 0) {
|
|
60
|
+
showWarning('No supported AI editors detected on this machine.');
|
|
61
|
+
showStatusTable();
|
|
62
|
+
return;
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
else {
|
|
66
|
+
showStatusTable();
|
|
67
|
+
showInfo('Run `opalserve link <editor>` to link a specific editor, or `opalserve link --all` for every detected one.');
|
|
68
|
+
return;
|
|
69
|
+
}
|
|
70
|
+
console.log('');
|
|
71
|
+
for (const adapter of targets) {
|
|
72
|
+
if (!adapter.detect()) {
|
|
73
|
+
showWarning(`${adapter.displayName} not detected — linking anyway (config will be created at ${adapter.getConfigPath()}).`);
|
|
74
|
+
}
|
|
75
|
+
const result = linkOne(adapter);
|
|
76
|
+
if (result.ok) {
|
|
77
|
+
const verb = result.replaced ? 'updated' : 'wired up';
|
|
78
|
+
showSuccess(`${adapter.displayName} ${verb}: ${chalk.dim(adapter.getConfigPath())}`);
|
|
79
|
+
if (result.replaced) {
|
|
80
|
+
showInfo(` Prior \`${OPALSERVE_ENTRY_NAME}\` entry overwritten.`);
|
|
81
|
+
}
|
|
82
|
+
}
|
|
83
|
+
else {
|
|
84
|
+
showError(`${adapter.displayName}: ${result.error}`);
|
|
85
|
+
}
|
|
86
|
+
}
|
|
87
|
+
console.log('');
|
|
88
|
+
showBox([
|
|
89
|
+
`OpalServe is now reachable to ${targets.length === 1 ? 'this editor' : 'these editors'} as the MCP server "${chalk.cyan(OPALSERVE_ENTRY_NAME)}".`,
|
|
90
|
+
'',
|
|
91
|
+
chalk.bold('Next:'),
|
|
92
|
+
` 1. ${chalk.dim('Restart the editor for it to pick up the new MCP server.')}`,
|
|
93
|
+
` 2. ${chalk.dim('Try asking your AI: "what tools are available via opalserve?"')}`,
|
|
94
|
+
].join('\n'), 'Linked');
|
|
95
|
+
}
|
|
96
|
+
export async function unlinkCommand(editorId, options) {
|
|
97
|
+
showMiniBanner();
|
|
98
|
+
let targets = [];
|
|
99
|
+
if (editorId) {
|
|
100
|
+
const adapter = getEditor(editorId);
|
|
101
|
+
if (!adapter) {
|
|
102
|
+
showError(`Unknown editor "${editorId}". Supported: ${SUPPORTED_EDITORS.map(e => e.id).join(', ')}`);
|
|
103
|
+
process.exit(1);
|
|
104
|
+
}
|
|
105
|
+
targets = [adapter];
|
|
106
|
+
}
|
|
107
|
+
else if (options.all) {
|
|
108
|
+
targets = SUPPORTED_EDITORS.filter(e => e.isLinked(OPALSERVE_ENTRY_NAME));
|
|
109
|
+
if (targets.length === 0) {
|
|
110
|
+
showInfo('No editors currently linked.');
|
|
111
|
+
return;
|
|
112
|
+
}
|
|
113
|
+
}
|
|
114
|
+
else {
|
|
115
|
+
showStatusTable();
|
|
116
|
+
showInfo('Run `opalserve unlink <editor>` to unlink, or `opalserve unlink --all` to unlink everywhere.');
|
|
117
|
+
return;
|
|
118
|
+
}
|
|
119
|
+
console.log('');
|
|
120
|
+
for (const adapter of targets) {
|
|
121
|
+
const result = unlinkOne(adapter);
|
|
122
|
+
if (!result.ok) {
|
|
123
|
+
showError(`${adapter.displayName}: ${result.error}`);
|
|
124
|
+
continue;
|
|
125
|
+
}
|
|
126
|
+
if (result.removed) {
|
|
127
|
+
showSuccess(`${adapter.displayName} unlinked`);
|
|
128
|
+
}
|
|
129
|
+
else {
|
|
130
|
+
showInfo(`${adapter.displayName} was not linked — nothing to remove.`);
|
|
131
|
+
}
|
|
132
|
+
}
|
|
133
|
+
console.log('');
|
|
134
|
+
}
|
|
135
|
+
//# sourceMappingURL=link.js.map
|