@opentabs-dev/cli 0.0.9 → 0.0.11
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/dist/cli.js +5 -8
- package/dist/cli.js.map +1 -1
- package/dist/commands/build.d.ts +13 -3
- package/dist/commands/build.d.ts.map +1 -1
- package/dist/commands/build.js +45 -32
- package/dist/commands/build.js.map +1 -1
- package/dist/commands/config.d.ts.map +1 -1
- package/dist/commands/config.js +7 -30
- package/dist/commands/config.js.map +1 -1
- package/dist/commands/doctor.d.ts.map +1 -1
- package/dist/commands/doctor.js +21 -19
- package/dist/commands/doctor.js.map +1 -1
- package/dist/commands/index.d.ts +1 -4
- package/dist/commands/index.d.ts.map +1 -1
- package/dist/commands/index.js +1 -4
- package/dist/commands/index.js.map +1 -1
- package/dist/commands/logs.d.ts +1 -1
- package/dist/commands/logs.js +2 -2
- package/dist/commands/logs.js.map +1 -1
- package/dist/commands/plugin.d.ts +3 -2
- package/dist/commands/plugin.d.ts.map +1 -1
- package/dist/commands/plugin.js +4 -159
- package/dist/commands/plugin.js.map +1 -1
- package/dist/commands/setup.d.ts +23 -3
- package/dist/commands/setup.d.ts.map +1 -1
- package/dist/commands/setup.js +35 -34
- package/dist/commands/setup.js.map +1 -1
- package/dist/commands/start.d.ts +14 -0
- package/dist/commands/start.d.ts.map +1 -0
- package/dist/commands/start.js +151 -0
- package/dist/commands/start.js.map +1 -0
- package/dist/commands/status.d.ts.map +1 -1
- package/dist/commands/status.js +11 -2
- package/dist/commands/status.js.map +1 -1
- package/dist/config.d.ts +7 -1
- package/dist/config.d.ts.map +1 -1
- package/dist/config.js +21 -1
- package/dist/config.js.map +1 -1
- package/dist/scaffold.d.ts.map +1 -1
- package/dist/scaffold.js +107 -58
- package/dist/scaffold.js.map +1 -1
- package/package.json +5 -5
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"logs.js","sourceRoot":"","sources":["../../src/commands/logs.ts"],"names":[],"mappings":"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
|
|
1
|
+
{"version":3,"file":"logs.js","sourceRoot":"","sources":["../../src/commands/logs.ts"],"names":[],"mappings":"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"}
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* `opentabs plugin` command —
|
|
2
|
+
* `opentabs plugin` command — plugin management (create).
|
|
3
3
|
*/
|
|
4
4
|
import type { Command } from 'commander';
|
|
5
|
-
|
|
5
|
+
declare const registerPluginCommand: (program: Command) => void;
|
|
6
|
+
export { registerPluginCommand };
|
|
6
7
|
//# sourceMappingURL=plugin.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"plugin.d.ts","sourceRoot":"","sources":["../../src/commands/plugin.ts"],"names":[],"mappings":"AAAA;;GAEG;
|
|
1
|
+
{"version":3,"file":"plugin.d.ts","sourceRoot":"","sources":["../../src/commands/plugin.ts"],"names":[],"mappings":"AAAA;;GAEG;AAIH,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAIzC,QAAA,MAAM,qBAAqB,GAAI,SAAS,OAAO,KAAG,IAsCjD,CAAC;AAEF,OAAO,EAAE,qBAAqB,EAAE,CAAC"}
|
package/dist/commands/plugin.js
CHANGED
|
@@ -1,142 +1,13 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* `opentabs plugin` command —
|
|
2
|
+
* `opentabs plugin` command — plugin management (create).
|
|
3
3
|
*/
|
|
4
|
-
import { getConfigPath, getPluginsFromConfig, readConfig, resolvePluginPath } from '../config.js';
|
|
5
4
|
import { scaffoldPlugin, ScaffoldError } from '../scaffold.js';
|
|
6
5
|
import pc from 'picocolors';
|
|
7
|
-
import { existsSync, mkdirSync } from 'node:fs';
|
|
8
|
-
import { dirname, join, relative, resolve } from 'node:path';
|
|
9
|
-
const readManifest = async (resolvedPath) => {
|
|
10
|
-
const manifestPath = join(resolvedPath, 'opentabs-plugin.json');
|
|
11
|
-
if (!existsSync(manifestPath))
|
|
12
|
-
return null;
|
|
13
|
-
try {
|
|
14
|
-
const data = await Bun.file(manifestPath).json();
|
|
15
|
-
if (data !== null && typeof data === 'object' && 'name' in data && 'version' in data && 'tools' in data) {
|
|
16
|
-
const d = data;
|
|
17
|
-
return { name: d.name, version: d.version, toolCount: Array.isArray(d.tools) ? d.tools.length : 0 };
|
|
18
|
-
}
|
|
19
|
-
return null;
|
|
20
|
-
}
|
|
21
|
-
catch {
|
|
22
|
-
return null;
|
|
23
|
-
}
|
|
24
|
-
};
|
|
25
|
-
const handlePluginList = async (options) => {
|
|
26
|
-
const configPath = getConfigPath();
|
|
27
|
-
const config = await readConfig(configPath);
|
|
28
|
-
if (!config) {
|
|
29
|
-
console.error(pc.red(`No config found at ${configPath}`));
|
|
30
|
-
console.error('Run opentabs dev to create one automatically.');
|
|
31
|
-
process.exit(1);
|
|
32
|
-
}
|
|
33
|
-
const plugins = getPluginsFromConfig(config);
|
|
34
|
-
if (plugins.length === 0) {
|
|
35
|
-
console.log('No plugins configured.');
|
|
36
|
-
console.log('Add one with: opentabs plugin add <path>');
|
|
37
|
-
return;
|
|
38
|
-
}
|
|
39
|
-
if (options.json) {
|
|
40
|
-
const entries = await Promise.all(plugins.map(async (pluginPath) => {
|
|
41
|
-
const resolvedPath = resolvePluginPath(pluginPath, configPath);
|
|
42
|
-
const exists = existsSync(resolvedPath);
|
|
43
|
-
const manifest = exists ? await readManifest(resolvedPath) : null;
|
|
44
|
-
return {
|
|
45
|
-
path: pluginPath,
|
|
46
|
-
resolvedPath,
|
|
47
|
-
exists,
|
|
48
|
-
hasManifest: manifest !== null,
|
|
49
|
-
name: manifest?.name,
|
|
50
|
-
version: manifest?.version,
|
|
51
|
-
toolCount: manifest?.toolCount,
|
|
52
|
-
};
|
|
53
|
-
}));
|
|
54
|
-
console.log(JSON.stringify(entries, null, 2));
|
|
55
|
-
return;
|
|
56
|
-
}
|
|
57
|
-
console.log('Configured plugins:');
|
|
58
|
-
console.log('');
|
|
59
|
-
for (const pluginPath of plugins) {
|
|
60
|
-
const resolvedPath = resolvePluginPath(pluginPath, configPath);
|
|
61
|
-
const exists = existsSync(resolvedPath);
|
|
62
|
-
const manifest = exists ? await readManifest(resolvedPath) : null;
|
|
63
|
-
if (manifest) {
|
|
64
|
-
const indicator = pc.green('+');
|
|
65
|
-
const name = pc.bold(manifest.name);
|
|
66
|
-
const version = pc.dim(`v${manifest.version}`);
|
|
67
|
-
const tools = pc.dim(`${manifest.toolCount} tool${manifest.toolCount === 1 ? '' : 's'}`);
|
|
68
|
-
console.log(` ${indicator} ${name} ${version} ${tools} ${pc.dim(pluginPath)}`);
|
|
69
|
-
}
|
|
70
|
-
else if (exists) {
|
|
71
|
-
console.log(` ${pc.yellow('~')} ${pluginPath} ${pc.yellow('(not built)')}`);
|
|
72
|
-
}
|
|
73
|
-
else {
|
|
74
|
-
console.log(` ${pc.red('!')} ${pluginPath} ${pc.red('(not found)')}`);
|
|
75
|
-
}
|
|
76
|
-
}
|
|
77
|
-
console.log('');
|
|
78
|
-
console.log(` ${pc.green('+')} ready ${pc.yellow('~')} no manifest ${pc.red('!')} not found`);
|
|
79
|
-
};
|
|
80
|
-
const handlePluginAdd = async (pathArg) => {
|
|
81
|
-
const configPath = getConfigPath();
|
|
82
|
-
const configDir = dirname(configPath);
|
|
83
|
-
const existing = await readConfig(configPath);
|
|
84
|
-
let config;
|
|
85
|
-
if (existing) {
|
|
86
|
-
config = existing;
|
|
87
|
-
}
|
|
88
|
-
else {
|
|
89
|
-
mkdirSync(configDir, { recursive: true });
|
|
90
|
-
config = { plugins: [], tools: {}, secret: crypto.randomUUID() };
|
|
91
|
-
}
|
|
92
|
-
if (!Array.isArray(config.plugins))
|
|
93
|
-
config.plugins = [];
|
|
94
|
-
const plugins = config.plugins;
|
|
95
|
-
// Resolve the new path to an absolute path (relative paths resolve against CWD)
|
|
96
|
-
const resolvedNew = resolve(pathArg);
|
|
97
|
-
// Normalize to a relative-to-config-dir form for portable storage
|
|
98
|
-
const normalizedNew = relative(configDir, resolvedNew);
|
|
99
|
-
// Check for duplicates by comparing resolved absolute paths
|
|
100
|
-
const isDuplicate = plugins.some(existing => resolvePluginPath(existing, configPath) === resolvedNew);
|
|
101
|
-
if (isDuplicate) {
|
|
102
|
-
console.log('Plugin path already configured.');
|
|
103
|
-
return;
|
|
104
|
-
}
|
|
105
|
-
if (!existsSync(resolvedNew)) {
|
|
106
|
-
console.warn(pc.yellow(`Warning: Path does not exist: ${normalizedNew}`));
|
|
107
|
-
}
|
|
108
|
-
plugins.push(normalizedNew);
|
|
109
|
-
await Bun.write(configPath, JSON.stringify(config, null, 2) + '\n');
|
|
110
|
-
console.log(pc.green(`Added: ${normalizedNew}`));
|
|
111
|
-
console.log('Restart the MCP server to pick up the new plugin.');
|
|
112
|
-
};
|
|
113
|
-
const handlePluginRemove = async (nameOrPath) => {
|
|
114
|
-
const configPath = getConfigPath();
|
|
115
|
-
const config = await readConfig(configPath);
|
|
116
|
-
if (!config) {
|
|
117
|
-
console.error(pc.red(`No config found at ${configPath}`));
|
|
118
|
-
console.error('Run opentabs dev to create one automatically.');
|
|
119
|
-
process.exit(1);
|
|
120
|
-
}
|
|
121
|
-
if (!Array.isArray(config.plugins))
|
|
122
|
-
config.plugins = [];
|
|
123
|
-
const plugins = config.plugins;
|
|
124
|
-
const idx = plugins.findIndex(p => p === nameOrPath || p.endsWith('/' + nameOrPath) || p.endsWith('\\' + nameOrPath));
|
|
125
|
-
if (idx === -1) {
|
|
126
|
-
console.error(pc.red('Plugin not found in config.'));
|
|
127
|
-
console.error('Run opentabs plugin list to see configured plugins.');
|
|
128
|
-
process.exit(1);
|
|
129
|
-
}
|
|
130
|
-
const removed = plugins.splice(idx, 1)[0];
|
|
131
|
-
await Bun.write(configPath, JSON.stringify(config, null, 2) + '\n');
|
|
132
|
-
console.log(pc.green(`Removed: ${removed}`));
|
|
133
|
-
console.log('Restart the MCP server to pick up the change.');
|
|
134
|
-
};
|
|
135
6
|
// --- Command registration ---
|
|
136
|
-
|
|
7
|
+
const registerPluginCommand = (program) => {
|
|
137
8
|
const pluginCmd = program
|
|
138
9
|
.command('plugin')
|
|
139
|
-
.description('Manage plugins
|
|
10
|
+
.description('Manage plugins')
|
|
140
11
|
.action(() => {
|
|
141
12
|
pluginCmd.help();
|
|
142
13
|
});
|
|
@@ -168,32 +39,6 @@ Examples:
|
|
|
168
39
|
throw err;
|
|
169
40
|
}
|
|
170
41
|
});
|
|
171
|
-
pluginCmd
|
|
172
|
-
.command('list')
|
|
173
|
-
.description('List configured plugins and their status')
|
|
174
|
-
.option('--json', 'Output plugin info as JSON')
|
|
175
|
-
.addHelpText('after', `
|
|
176
|
-
Examples:
|
|
177
|
-
$ opentabs plugin list
|
|
178
|
-
$ opentabs plugin list --json`)
|
|
179
|
-
.action((options) => handlePluginList(options));
|
|
180
|
-
pluginCmd
|
|
181
|
-
.command('add')
|
|
182
|
-
.description('Add a plugin path to the config')
|
|
183
|
-
.argument('<path>', 'Path to the plugin directory')
|
|
184
|
-
.addHelpText('after', `
|
|
185
|
-
Examples:
|
|
186
|
-
$ opentabs plugin add ./my-plugin
|
|
187
|
-
$ opentabs plugin add /absolute/path/to/plugin`)
|
|
188
|
-
.action((pathArg) => handlePluginAdd(pathArg));
|
|
189
|
-
pluginCmd
|
|
190
|
-
.command('remove')
|
|
191
|
-
.description('Remove a plugin path from the config')
|
|
192
|
-
.argument('<path-or-name>', 'Exact path or plugin directory name to match')
|
|
193
|
-
.addHelpText('after', `
|
|
194
|
-
Examples:
|
|
195
|
-
$ opentabs plugin remove ./my-plugin
|
|
196
|
-
$ opentabs plugin remove my-plugin`)
|
|
197
|
-
.action((nameOrPath) => handlePluginRemove(nameOrPath));
|
|
198
42
|
};
|
|
43
|
+
export { registerPluginCommand };
|
|
199
44
|
//# sourceMappingURL=plugin.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"plugin.js","sourceRoot":"","sources":["../../src/commands/plugin.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,EAAE,
|
|
1
|
+
{"version":3,"file":"plugin.js","sourceRoot":"","sources":["../../src/commands/plugin.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,EAAE,cAAc,EAAE,aAAa,EAAE,MAAM,gBAAgB,CAAC;AAC/D,OAAO,EAAE,MAAM,YAAY,CAAC;AAG5B,+BAA+B;AAE/B,MAAM,qBAAqB,GAAG,CAAC,OAAgB,EAAQ,EAAE;IACvD,MAAM,SAAS,GAAG,OAAO;SACtB,OAAO,CAAC,QAAQ,CAAC;SACjB,WAAW,CAAC,gBAAgB,CAAC;SAC7B,MAAM,CAAC,GAAG,EAAE;QACX,SAAS,CAAC,IAAI,EAAE,CAAC;IACnB,CAAC,CAAC,CAAC;IAEL,SAAS;SACN,OAAO,CAAC,QAAQ,CAAC;SACjB,WAAW,CAAC,+BAA+B,CAAC;SAC5C,QAAQ,CAAC,QAAQ,EAAE,gDAAgD,CAAC;SACpE,cAAc,CAAC,mBAAmB,EAAE,gDAAgD,CAAC;SACrF,MAAM,CAAC,kBAAkB,EAAE,4BAA4B,CAAC;SACxD,MAAM,CAAC,sBAAsB,EAAE,oBAAoB,CAAC;SACpD,WAAW,CACV,OAAO,EACP;;;qEAG+D,CAChE;SACA,MAAM,CAAC,KAAK,EAAE,IAAY,EAAE,OAAmE,EAAE,EAAE;QAClG,IAAI,CAAC;YACH,MAAM,cAAc,CAAC;gBACnB,IAAI;gBACJ,MAAM,EAAE,OAAO,CAAC,MAAM;gBACtB,OAAO,EAAE,OAAO,CAAC,OAAO;gBACxB,WAAW,EAAE,OAAO,CAAC,WAAW;aACjC,CAAC,CAAC;QACL,CAAC;QAAC,OAAO,GAAY,EAAE,CAAC;YACtB,IAAI,GAAG,YAAY,aAAa,EAAE,CAAC;gBACjC,OAAO,CAAC,KAAK,CAAC,EAAE,CAAC,GAAG,CAAC,UAAU,GAAG,CAAC,OAAO,EAAE,CAAC,CAAC,CAAC;gBAC/C,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;YAClB,CAAC;YACD,MAAM,GAAG,CAAC;QACZ,CAAC;IACH,CAAC,CAAC,CAAC;AACP,CAAC,CAAC;AAEF,OAAO,EAAE,qBAAqB,EAAE,CAAC"}
|
package/dist/commands/setup.d.ts
CHANGED
|
@@ -1,6 +1,26 @@
|
|
|
1
1
|
/**
|
|
2
|
-
*
|
|
2
|
+
* Browser extension installation logic.
|
|
3
|
+
*
|
|
4
|
+
* The installExtension() function is called by `opentabs start` for
|
|
5
|
+
* auto-initialization on first run.
|
|
3
6
|
*/
|
|
4
|
-
|
|
5
|
-
|
|
7
|
+
interface InstallExtensionResult {
|
|
8
|
+
/** Whether the extension was installed or updated (false = already up-to-date) */
|
|
9
|
+
installed: boolean;
|
|
10
|
+
/** Whether this was the first installation (no prior extension directory) */
|
|
11
|
+
firstTime: boolean;
|
|
12
|
+
/** The destination directory */
|
|
13
|
+
extensionDest: string;
|
|
14
|
+
/** The installed version */
|
|
15
|
+
version: string;
|
|
16
|
+
}
|
|
17
|
+
/**
|
|
18
|
+
* Install or update the browser extension to ~/.opentabs/extension/.
|
|
19
|
+
*
|
|
20
|
+
* Skips installation if the extension is already installed at the current version.
|
|
21
|
+
* The configDir parameter specifies the base directory (defaults to ~/.opentabs).
|
|
22
|
+
*/
|
|
23
|
+
declare const installExtension: (configDir: string) => Promise<InstallExtensionResult>;
|
|
24
|
+
export { installExtension };
|
|
25
|
+
export type { InstallExtensionResult };
|
|
6
26
|
//# sourceMappingURL=setup.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"setup.d.ts","sourceRoot":"","sources":["../../src/commands/setup.ts"],"names":[],"mappings":"AAAA
|
|
1
|
+
{"version":3,"file":"setup.d.ts","sourceRoot":"","sources":["../../src/commands/setup.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAsBH,UAAU,sBAAsB;IAC9B,kFAAkF;IAClF,SAAS,EAAE,OAAO,CAAC;IACnB,6EAA6E;IAC7E,SAAS,EAAE,OAAO,CAAC;IACnB,gCAAgC;IAChC,aAAa,EAAE,MAAM,CAAC;IACtB,4BAA4B;IAC5B,OAAO,EAAE,MAAM,CAAC;CACjB;AAED;;;;;GAKG;AACH,QAAA,MAAM,gBAAgB,GAAU,WAAW,MAAM,KAAG,OAAO,CAAC,sBAAsB,CA8CjF,CAAC;AAEF,OAAO,EAAE,gBAAgB,EAAE,CAAC;AAC5B,YAAY,EAAE,sBAAsB,EAAE,CAAC"}
|
package/dist/commands/setup.js
CHANGED
|
@@ -1,11 +1,12 @@
|
|
|
1
1
|
/**
|
|
2
|
-
*
|
|
2
|
+
* Browser extension installation logic.
|
|
3
|
+
*
|
|
4
|
+
* The installExtension() function is called by `opentabs start` for
|
|
5
|
+
* auto-initialization on first run.
|
|
3
6
|
*/
|
|
4
7
|
import { EXTENSION_COPY_EXCLUDE_PATTERN } from '@opentabs-dev/shared';
|
|
5
|
-
import pc from 'picocolors';
|
|
6
8
|
import { cpSync, existsSync, mkdirSync } from 'node:fs';
|
|
7
|
-
import {
|
|
8
|
-
import { resolve, join, dirname, relative } from 'node:path';
|
|
9
|
+
import { join, dirname, relative, resolve } from 'node:path';
|
|
9
10
|
import { fileURLToPath } from 'node:url';
|
|
10
11
|
const resolveExtensionDir = () => {
|
|
11
12
|
try {
|
|
@@ -16,22 +17,36 @@ const resolveExtensionDir = () => {
|
|
|
16
17
|
return resolve(cliDir, '..', '..', '..', 'browser-extension');
|
|
17
18
|
}
|
|
18
19
|
};
|
|
19
|
-
const
|
|
20
|
+
const getCliVersion = async () => {
|
|
21
|
+
const cliPkgPath = join(dirname(fileURLToPath(import.meta.url)), '..', '..', 'package.json');
|
|
22
|
+
const pkgJson = JSON.parse(await Bun.file(cliPkgPath).text());
|
|
23
|
+
return pkgJson.version;
|
|
24
|
+
};
|
|
25
|
+
/**
|
|
26
|
+
* Install or update the browser extension to ~/.opentabs/extension/.
|
|
27
|
+
*
|
|
28
|
+
* Skips installation if the extension is already installed at the current version.
|
|
29
|
+
* The configDir parameter specifies the base directory (defaults to ~/.opentabs).
|
|
30
|
+
*/
|
|
31
|
+
const installExtension = async (configDir) => {
|
|
20
32
|
const extensionSrc = resolveExtensionDir();
|
|
21
33
|
// Verify the extension source exists
|
|
22
34
|
if (!(await Bun.file(join(extensionSrc, 'manifest.json')).exists())) {
|
|
23
|
-
|
|
24
|
-
console.error('Run bun run build from the project root to build the extension.');
|
|
25
|
-
process.exit(1);
|
|
35
|
+
throw new Error(`Browser extension not found at ${extensionSrc}. Run bun run build from the project root first.`);
|
|
26
36
|
}
|
|
27
|
-
|
|
28
|
-
const
|
|
29
|
-
const
|
|
30
|
-
const
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
37
|
+
const version = await getCliVersion();
|
|
38
|
+
const extensionDest = join(configDir, 'extension');
|
|
39
|
+
const versionMarkerPath = join(extensionDest, '.opentabs-version');
|
|
40
|
+
const firstTime = !existsSync(join(extensionDest, 'manifest.json'));
|
|
41
|
+
// Check if already up-to-date
|
|
42
|
+
if (!firstTime) {
|
|
43
|
+
const versionFile = Bun.file(versionMarkerPath);
|
|
44
|
+
if (await versionFile.exists()) {
|
|
45
|
+
const installedVersion = (await versionFile.text()).trim();
|
|
46
|
+
if (installedVersion === version) {
|
|
47
|
+
return { installed: false, firstTime: false, extensionDest, version };
|
|
48
|
+
}
|
|
49
|
+
}
|
|
35
50
|
}
|
|
36
51
|
// Copy extension directory, skipping node_modules, src, .git, tsconfig*
|
|
37
52
|
cpSync(extensionSrc, extensionDest, {
|
|
@@ -45,26 +60,12 @@ const handleSetup = async () => {
|
|
|
45
60
|
// Create adapters directory for plugins
|
|
46
61
|
mkdirSync(join(extensionDest, 'adapters'), { recursive: true });
|
|
47
62
|
// Write version marker
|
|
48
|
-
await Bun.write(
|
|
63
|
+
await Bun.write(versionMarkerPath, version);
|
|
49
64
|
// Verify installation
|
|
50
65
|
if (!existsSync(join(extensionDest, 'manifest.json'))) {
|
|
51
|
-
|
|
52
|
-
process.exit(1);
|
|
66
|
+
throw new Error('Installation verification failed — manifest.json missing from destination.');
|
|
53
67
|
}
|
|
54
|
-
|
|
55
|
-
console.log('');
|
|
56
|
-
console.log('To load the extension in Chrome:');
|
|
57
|
-
console.log(` 1. Open ${pc.cyan('chrome://extensions/')}`);
|
|
58
|
-
console.log(` 2. Enable "Developer mode" (top-right toggle)`);
|
|
59
|
-
console.log(` 3. Click "Load unpacked" and select: ${pc.cyan(extensionDest)}`);
|
|
60
|
-
};
|
|
61
|
-
export const registerSetupCommand = (program) => {
|
|
62
|
-
program
|
|
63
|
-
.command('setup')
|
|
64
|
-
.description('Install the browser extension to ~/.opentabs/')
|
|
65
|
-
.addHelpText('after', `
|
|
66
|
-
Examples:
|
|
67
|
-
$ opentabs setup`)
|
|
68
|
-
.action(() => handleSetup());
|
|
68
|
+
return { installed: true, firstTime, extensionDest, version };
|
|
69
69
|
};
|
|
70
|
+
export { installExtension };
|
|
70
71
|
//# sourceMappingURL=setup.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"setup.js","sourceRoot":"","sources":["../../src/commands/setup.ts"],"names":[],"mappings":"AAAA
|
|
1
|
+
{"version":3,"file":"setup.js","sourceRoot":"","sources":["../../src/commands/setup.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* `opentabs start` command — starts the MCP server in production mode.
|
|
3
|
+
*
|
|
4
|
+
* On first run, auto-initializes ~/.opentabs/ with a config file and
|
|
5
|
+
* installs the browser extension. Prints first-time setup instructions
|
|
6
|
+
* after the server starts.
|
|
7
|
+
*
|
|
8
|
+
* Server output is written to both the terminal and a log file at
|
|
9
|
+
* ~/.opentabs/server.log (or $OPENTABS_CONFIG_DIR/server.log).
|
|
10
|
+
* The `opentabs logs` command tails this file.
|
|
11
|
+
*/
|
|
12
|
+
import type { Command } from 'commander';
|
|
13
|
+
export declare const registerStartCommand: (program: Command) => void;
|
|
14
|
+
//# sourceMappingURL=start.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"start.d.ts","sourceRoot":"","sources":["../../src/commands/start.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AASH,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAiKzC,eAAO,MAAM,oBAAoB,GAAI,SAAS,OAAO,KAAG,IAavD,CAAC"}
|
|
@@ -0,0 +1,151 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* `opentabs start` command — starts the MCP server in production mode.
|
|
3
|
+
*
|
|
4
|
+
* On first run, auto-initializes ~/.opentabs/ with a config file and
|
|
5
|
+
* installs the browser extension. Prints first-time setup instructions
|
|
6
|
+
* after the server starts.
|
|
7
|
+
*
|
|
8
|
+
* Server output is written to both the terminal and a log file at
|
|
9
|
+
* ~/.opentabs/server.log (or $OPENTABS_CONFIG_DIR/server.log).
|
|
10
|
+
* The `opentabs logs` command tails this file.
|
|
11
|
+
*/
|
|
12
|
+
import { installExtension } from './setup.js';
|
|
13
|
+
import { getConfigDir, getLogFilePath } from '../config.js';
|
|
14
|
+
import { parsePort, resolvePort } from '../parse-port.js';
|
|
15
|
+
import pc from 'picocolors';
|
|
16
|
+
import { mkdirSync, createWriteStream } from 'node:fs';
|
|
17
|
+
import { resolve, dirname } from 'node:path';
|
|
18
|
+
import { fileURLToPath } from 'node:url';
|
|
19
|
+
const resolveServerEntry = () => {
|
|
20
|
+
try {
|
|
21
|
+
return fileURLToPath(import.meta.resolve('@opentabs-dev/mcp-server'));
|
|
22
|
+
}
|
|
23
|
+
catch {
|
|
24
|
+
const cliDir = dirname(fileURLToPath(import.meta.url));
|
|
25
|
+
return resolve(cliDir, '..', '..', '..', 'mcp-server', 'dist', 'index.js');
|
|
26
|
+
}
|
|
27
|
+
};
|
|
28
|
+
const isPortInUse = async (port) => {
|
|
29
|
+
try {
|
|
30
|
+
await fetch(`http://localhost:${port}/health`, {
|
|
31
|
+
signal: AbortSignal.timeout(1_000),
|
|
32
|
+
});
|
|
33
|
+
return true;
|
|
34
|
+
}
|
|
35
|
+
catch {
|
|
36
|
+
return false;
|
|
37
|
+
}
|
|
38
|
+
};
|
|
39
|
+
/**
|
|
40
|
+
* Pipe a readable stream to both a terminal writable and a log file stream.
|
|
41
|
+
* Returns when the readable stream ends.
|
|
42
|
+
*/
|
|
43
|
+
const teeStream = async (readable, terminal, logFile) => {
|
|
44
|
+
const reader = readable.getReader();
|
|
45
|
+
for (;;) {
|
|
46
|
+
const { done, value } = await reader.read();
|
|
47
|
+
if (done)
|
|
48
|
+
break;
|
|
49
|
+
terminal.write(value);
|
|
50
|
+
logFile.write(value);
|
|
51
|
+
}
|
|
52
|
+
};
|
|
53
|
+
/**
|
|
54
|
+
* Auto-initialize the config directory and install the browser extension.
|
|
55
|
+
* Returns true if this is the first-time setup (extension was newly installed).
|
|
56
|
+
*/
|
|
57
|
+
const autoInitialize = async (configDir) => {
|
|
58
|
+
mkdirSync(configDir, { recursive: true });
|
|
59
|
+
try {
|
|
60
|
+
const result = await installExtension(configDir);
|
|
61
|
+
if (result.installed && result.firstTime) {
|
|
62
|
+
console.log(pc.green(`Extension installed to ${result.extensionDest} (v${result.version})`));
|
|
63
|
+
return true;
|
|
64
|
+
}
|
|
65
|
+
else if (result.installed) {
|
|
66
|
+
console.log(pc.dim(`Extension updated to v${result.version}`));
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
catch (err) {
|
|
70
|
+
// Extension install is non-fatal — the server can still start without it.
|
|
71
|
+
console.warn(pc.yellow(`Warning: Could not install extension: ${err instanceof Error ? err.message : String(err)}`));
|
|
72
|
+
console.warn(pc.dim('Restart opentabs start to retry extension installation.'));
|
|
73
|
+
}
|
|
74
|
+
return false;
|
|
75
|
+
};
|
|
76
|
+
const printFirstTimeInstructions = (extensionDest, port) => {
|
|
77
|
+
console.log('');
|
|
78
|
+
console.log(pc.bold('First-time setup:'));
|
|
79
|
+
console.log('');
|
|
80
|
+
console.log(' 1. Load the extension in Chrome:');
|
|
81
|
+
console.log(` a. Open ${pc.cyan('chrome://extensions/')}`);
|
|
82
|
+
console.log(` b. Enable "Developer mode" (top-right toggle)`);
|
|
83
|
+
console.log(` c. Click "Load unpacked" and select: ${pc.cyan(extensionDest)}`);
|
|
84
|
+
console.log('');
|
|
85
|
+
console.log(' 2. Configure your MCP client (~/.claude/settings/mcp.json):');
|
|
86
|
+
console.log(pc.dim(` { "mcpServers": { "opentabs": { "type": "streamable-http", "url": "http://127.0.0.1:${port}/mcp" } } }`));
|
|
87
|
+
console.log('');
|
|
88
|
+
};
|
|
89
|
+
const handleStart = async (options) => {
|
|
90
|
+
const serverEntry = resolveServerEntry();
|
|
91
|
+
if (!(await Bun.file(serverEntry).exists())) {
|
|
92
|
+
console.error(pc.red(`Error: MCP server entry not found at ${serverEntry}`));
|
|
93
|
+
console.error('Run bun run build from the project root first.');
|
|
94
|
+
process.exit(1);
|
|
95
|
+
}
|
|
96
|
+
const port = resolvePort(options);
|
|
97
|
+
if (await isPortInUse(port)) {
|
|
98
|
+
console.error(pc.red(`Error: Port ${port} is already in use.`));
|
|
99
|
+
console.error(port === 9515
|
|
100
|
+
? 'Another OpenTabs server may already be running. Use --port to specify a different port.'
|
|
101
|
+
: `Use a different port with: opentabs start --port <number>`);
|
|
102
|
+
process.exit(1);
|
|
103
|
+
}
|
|
104
|
+
const configDir = getConfigDir();
|
|
105
|
+
const isFirstTime = await autoInitialize(configDir);
|
|
106
|
+
const env = { ...process.env };
|
|
107
|
+
env.PORT = String(port);
|
|
108
|
+
const logFilePath = getLogFilePath();
|
|
109
|
+
const logStream = createWriteStream(logFilePath, { flags: 'a' });
|
|
110
|
+
console.log(`Starting OpenTabs MCP server on port ${pc.bold(String(port))}...`);
|
|
111
|
+
console.log('');
|
|
112
|
+
console.log(` ${pc.cyan('MCP endpoint:')} http://localhost:${port}/mcp`);
|
|
113
|
+
console.log(` ${pc.cyan('Health check:')} http://localhost:${port}/health`);
|
|
114
|
+
console.log(` ${pc.cyan('Log file:')} ${logFilePath}`);
|
|
115
|
+
console.log('');
|
|
116
|
+
if (isFirstTime) {
|
|
117
|
+
const extensionDest = resolve(configDir, 'extension');
|
|
118
|
+
printFirstTimeInstructions(extensionDest, port);
|
|
119
|
+
}
|
|
120
|
+
else {
|
|
121
|
+
console.log(pc.dim(' MCP client config (~/.claude/settings/mcp.json):'));
|
|
122
|
+
console.log(pc.dim(` { "mcpServers": { "opentabs": { "type": "streamable-http", "url": "http://127.0.0.1:${port}/mcp" } } }`));
|
|
123
|
+
console.log('');
|
|
124
|
+
}
|
|
125
|
+
console.log(pc.dim(' Press Ctrl+C to stop'));
|
|
126
|
+
console.log('');
|
|
127
|
+
const proc = Bun.spawn(['bun', serverEntry], {
|
|
128
|
+
env: env,
|
|
129
|
+
stdio: ['inherit', 'pipe', 'pipe'],
|
|
130
|
+
});
|
|
131
|
+
const stdoutPipe = teeStream(proc.stdout, process.stdout, logStream);
|
|
132
|
+
const stderrPipe = teeStream(proc.stderr, process.stderr, logStream);
|
|
133
|
+
process.on('SIGINT', () => proc.kill('SIGINT'));
|
|
134
|
+
process.on('SIGTERM', () => proc.kill('SIGTERM'));
|
|
135
|
+
await Promise.all([stdoutPipe, stderrPipe]);
|
|
136
|
+
logStream.end();
|
|
137
|
+
const exitCode = await proc.exited;
|
|
138
|
+
process.exit(exitCode);
|
|
139
|
+
};
|
|
140
|
+
export const registerStartCommand = (program) => {
|
|
141
|
+
program
|
|
142
|
+
.command('start')
|
|
143
|
+
.description('Start the MCP server')
|
|
144
|
+
.option('--port <number>', 'Server port (default: 9515)', parsePort)
|
|
145
|
+
.addHelpText('after', `
|
|
146
|
+
Examples:
|
|
147
|
+
$ opentabs start
|
|
148
|
+
$ opentabs start --port 3000`)
|
|
149
|
+
.action((_options, command) => handleStart(command.optsWithGlobals()));
|
|
150
|
+
};
|
|
151
|
+
//# sourceMappingURL=start.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"start.js","sourceRoot":"","sources":["../../src/commands/start.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AAEH,OAAO,EAAE,gBAAgB,EAAE,MAAM,YAAY,CAAC;AAC9C,OAAO,EAAE,YAAY,EAAE,cAAc,EAAE,MAAM,cAAc,CAAC;AAC5D,OAAO,EAAE,SAAS,EAAE,WAAW,EAAE,MAAM,kBAAkB,CAAC;AAC1D,OAAO,EAAE,MAAM,YAAY,CAAC;AAC5B,OAAO,EAAE,SAAS,EAAE,iBAAiB,EAAE,MAAM,SAAS,CAAC;AACvD,OAAO,EAAE,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAC7C,OAAO,EAAE,aAAa,EAAE,MAAM,UAAU,CAAC;AAQzC,MAAM,kBAAkB,GAAG,GAAW,EAAE;IACtC,IAAI,CAAC;QACH,OAAO,aAAa,CAAC,MAAM,CAAC,IAAI,CAAC,OAAO,CAAC,0BAA0B,CAAC,CAAC,CAAC;IACxE,CAAC;IAAC,MAAM,CAAC;QACP,MAAM,MAAM,GAAG,OAAO,CAAC,aAAa,CAAC,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC;QACvD,OAAO,OAAO,CAAC,MAAM,EAAE,IAAI,EAAE,IAAI,EAAE,IAAI,EAAE,YAAY,EAAE,MAAM,EAAE,UAAU,CAAC,CAAC;IAC7E,CAAC;AACH,CAAC,CAAC;AAEF,MAAM,WAAW,GAAG,KAAK,EAAE,IAAY,EAAoB,EAAE;IAC3D,IAAI,CAAC;QACH,MAAM,KAAK,CAAC,oBAAoB,IAAI,SAAS,EAAE;YAC7C,MAAM,EAAE,WAAW,CAAC,OAAO,CAAC,KAAK,CAAC;SACnC,CAAC,CAAC;QACH,OAAO,IAAI,CAAC;IACd,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,KAAK,CAAC;IACf,CAAC;AACH,CAAC,CAAC;AAEF;;;GAGG;AACH,MAAM,SAAS,GAAG,KAAK,EACrB,QAAoC,EACpC,QAA4B,EAC5B,OAAoB,EACL,EAAE;IACjB,MAAM,MAAM,GAAG,QAAQ,CAAC,SAAS,EAAE,CAAC;IACpC,SAAS,CAAC;QACR,MAAM,EAAE,IAAI,EAAE,KAAK,EAAE,GAAG,MAAM,MAAM,CAAC,IAAI,EAAE,CAAC;QAC5C,IAAI,IAAI;YAAE,MAAM;QAChB,QAAQ,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC;QACtB,OAAO,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC;IACvB,CAAC;AACH,CAAC,CAAC;AAEF;;;GAGG;AACH,MAAM,cAAc,GAAG,KAAK,EAAE,SAAiB,EAAoB,EAAE;IACnE,SAAS,CAAC,SAAS,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;IAE1C,IAAI,CAAC;QACH,MAAM,MAAM,GAAG,MAAM,gBAAgB,CAAC,SAAS,CAAC,CAAC;QAEjD,IAAI,MAAM,CAAC,SAAS,IAAI,MAAM,CAAC,SAAS,EAAE,CAAC;YACzC,OAAO,CAAC,GAAG,CAAC,EAAE,CAAC,KAAK,CAAC,0BAA0B,MAAM,CAAC,aAAa,MAAM,MAAM,CAAC,OAAO,GAAG,CAAC,CAAC,CAAC;YAC7F,OAAO,IAAI,CAAC;QACd,CAAC;aAAM,IAAI,MAAM,CAAC,SAAS,EAAE,CAAC;YAC5B,OAAO,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,CAAC,yBAAyB,MAAM,CAAC,OAAO,EAAE,CAAC,CAAC,CAAC;QACjE,CAAC;IACH,CAAC;IAAC,OAAO,GAAG,EAAE,CAAC;QACb,0EAA0E;QAC1E,OAAO,CAAC,IAAI,CACV,EAAE,CAAC,MAAM,CAAC,yCAAyC,GAAG,YAAY,KAAK,CAAC,CAAC,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,GAAG,CAAC,EAAE,CAAC,CACvG,CAAC;QACF,OAAO,CAAC,IAAI,CAAC,EAAE,CAAC,GAAG,CAAC,yDAAyD,CAAC,CAAC,CAAC;IAClF,CAAC;IAED,OAAO,KAAK,CAAC;AACf,CAAC,CAAC;AAEF,MAAM,0BAA0B,GAAG,CAAC,aAAqB,EAAE,IAAY,EAAQ,EAAE;IAC/E,OAAO,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC;IAChB,OAAO,CAAC,GAAG,CAAC,EAAE,CAAC,IAAI,CAAC,mBAAmB,CAAC,CAAC,CAAC;IAC1C,OAAO,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC;IAChB,OAAO,CAAC,GAAG,CAAC,oCAAoC,CAAC,CAAC;IAClD,OAAO,CAAC,GAAG,CAAC,gBAAgB,EAAE,CAAC,IAAI,CAAC,sBAAsB,CAAC,EAAE,CAAC,CAAC;IAC/D,OAAO,CAAC,GAAG,CAAC,oDAAoD,CAAC,CAAC;IAClE,OAAO,CAAC,GAAG,CAAC,6CAA6C,EAAE,CAAC,IAAI,CAAC,aAAa,CAAC,EAAE,CAAC,CAAC;IACnF,OAAO,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC;IAChB,OAAO,CAAC,GAAG,CAAC,+DAA+D,CAAC,CAAC;IAC7E,OAAO,CAAC,GAAG,CACT,EAAE,CAAC,GAAG,CACJ,4FAA4F,IAAI,aAAa,CAC9G,CACF,CAAC;IACF,OAAO,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC;AAClB,CAAC,CAAC;AAEF,MAAM,WAAW,GAAG,KAAK,EAAE,OAAqB,EAAiB,EAAE;IACjE,MAAM,WAAW,GAAG,kBAAkB,EAAE,CAAC;IAEzC,IAAI,CAAC,CAAC,MAAM,GAAG,CAAC,IAAI,CAAC,WAAW,CAAC,CAAC,MAAM,EAAE,CAAC,EAAE,CAAC;QAC5C,OAAO,CAAC,KAAK,CAAC,EAAE,CAAC,GAAG,CAAC,wCAAwC,WAAW,EAAE,CAAC,CAAC,CAAC;QAC7E,OAAO,CAAC,KAAK,CAAC,gDAAgD,CAAC,CAAC;QAChE,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IAClB,CAAC;IAED,MAAM,IAAI,GAAG,WAAW,CAAC,OAAO,CAAC,CAAC;IAElC,IAAI,MAAM,WAAW,CAAC,IAAI,CAAC,EAAE,CAAC;QAC5B,OAAO,CAAC,KAAK,CAAC,EAAE,CAAC,GAAG,CAAC,eAAe,IAAI,qBAAqB,CAAC,CAAC,CAAC;QAChE,OAAO,CAAC,KAAK,CACX,IAAI,KAAK,IAAI;YACX,CAAC,CAAC,yFAAyF;YAC3F,CAAC,CAAC,2DAA2D,CAChE,CAAC;QACF,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IAClB,CAAC;IAED,MAAM,SAAS,GAAG,YAAY,EAAE,CAAC;IACjC,MAAM,WAAW,GAAG,MAAM,cAAc,CAAC,SAAS,CAAC,CAAC;IAEpD,MAAM,GAAG,GAAuC,EAAE,GAAG,OAAO,CAAC,GAAG,EAAE,CAAC;IACnE,GAAG,CAAC,IAAI,GAAG,MAAM,CAAC,IAAI,CAAC,CAAC;IAExB,MAAM,WAAW,GAAG,cAAc,EAAE,CAAC;IACrC,MAAM,SAAS,GAAG,iBAAiB,CAAC,WAAW,EAAE,EAAE,KAAK,EAAE,GAAG,EAAE,CAAC,CAAC;IAEjE,OAAO,CAAC,GAAG,CAAC,wCAAwC,EAAE,CAAC,IAAI,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC,KAAK,CAAC,CAAC;IAChF,OAAO,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC;IAChB,OAAO,CAAC,GAAG,CAAC,KAAK,EAAE,CAAC,IAAI,CAAC,eAAe,CAAC,sBAAsB,IAAI,MAAM,CAAC,CAAC;IAC3E,OAAO,CAAC,GAAG,CAAC,KAAK,EAAE,CAAC,IAAI,CAAC,eAAe,CAAC,sBAAsB,IAAI,SAAS,CAAC,CAAC;IAC9E,OAAO,CAAC,GAAG,CAAC,KAAK,EAAE,CAAC,IAAI,CAAC,WAAW,CAAC,QAAQ,WAAW,EAAE,CAAC,CAAC;IAC5D,OAAO,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC;IAEhB,IAAI,WAAW,EAAE,CAAC;QAChB,MAAM,aAAa,GAAG,OAAO,CAAC,SAAS,EAAE,WAAW,CAAC,CAAC;QACtD,0BAA0B,CAAC,aAAa,EAAE,IAAI,CAAC,CAAC;IAClD,CAAC;SAAM,CAAC;QACN,OAAO,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,CAAC,oDAAoD,CAAC,CAAC,CAAC;QAC1E,OAAO,CAAC,GAAG,CACT,EAAE,CAAC,GAAG,CACJ,yFAAyF,IAAI,aAAa,CAC3G,CACF,CAAC;QACF,OAAO,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC;IAClB,CAAC;IAED,OAAO,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,CAAC,wBAAwB,CAAC,CAAC,CAAC;IAC9C,OAAO,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC;IAEhB,MAAM,IAAI,GAAG,GAAG,CAAC,KAAK,CAAC,CAAC,KAAK,EAAE,WAAW,CAAC,EAAE;QAC3C,GAAG,EAAE,GAA6B;QAClC,KAAK,EAAE,CAAC,SAAS,EAAE,MAAM,EAAE,MAAM,CAAC;KACnC,CAAC,CAAC;IAEH,MAAM,UAAU,GAAG,SAAS,CAAC,IAAI,CAAC,MAAM,EAAE,OAAO,CAAC,MAAM,EAAE,SAAS,CAAC,CAAC;IACrE,MAAM,UAAU,GAAG,SAAS,CAAC,IAAI,CAAC,MAAM,EAAE,OAAO,CAAC,MAAM,EAAE,SAAS,CAAC,CAAC;IAErE,OAAO,CAAC,EAAE,CAAC,QAAQ,EAAE,GAAG,EAAE,CAAC,IAAI,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC,CAAC;IAChD,OAAO,CAAC,EAAE,CAAC,SAAS,EAAE,GAAG,EAAE,CAAC,IAAI,CAAC,IAAI,CAAC,SAAS,CAAC,CAAC,CAAC;IAElD,MAAM,OAAO,CAAC,GAAG,CAAC,CAAC,UAAU,EAAE,UAAU,CAAC,CAAC,CAAC;IAC5C,SAAS,CAAC,GAAG,EAAE,CAAC;IAEhB,MAAM,QAAQ,GAAG,MAAM,IAAI,CAAC,MAAM,CAAC;IACnC,OAAO,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC;AACzB,CAAC,CAAC;AAEF,MAAM,CAAC,MAAM,oBAAoB,GAAG,CAAC,OAAgB,EAAQ,EAAE;IAC7D,OAAO;SACJ,OAAO,CAAC,OAAO,CAAC;SAChB,WAAW,CAAC,sBAAsB,CAAC;SACnC,MAAM,CAAC,iBAAiB,EAAE,6BAA6B,EAAE,SAAS,CAAC;SACnE,WAAW,CACV,OAAO,EACP;;;+BAGyB,CAC1B;SACA,MAAM,CAAC,CAAC,QAAsB,EAAE,OAAgB,EAAE,EAAE,CAAC,WAAW,CAAC,OAAO,CAAC,eAAe,EAAE,CAAC,CAAC,CAAC;AAClG,CAAC,CAAC"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"status.d.ts","sourceRoot":"","sources":["../../src/commands/status.ts"],"names":[],"mappings":"AAAA;;GAEG;AAKH,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;
|
|
1
|
+
{"version":3,"file":"status.d.ts","sourceRoot":"","sources":["../../src/commands/status.ts"],"names":[],"mappings":"AAAA;;GAEG;AAKH,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAsBzC,QAAA,MAAM,YAAY,GAAI,SAAS,MAAM,KAAG,MAWvC,CAAC;AAEF,QAAA,MAAM,aAAa,GAAI,UAAU,MAAM,KAAG,MAIzC,CAAC;AAEF,QAAA,MAAM,SAAS,GAAI,KAAK,OAAO,KAAG,OAAqE,CAAC;AA4ExG,QAAA,MAAM,qBAAqB,GAAI,SAAS,OAAO,KAAG,IAejD,CAAC;AAEF,OAAO,EAAE,aAAa,EAAE,YAAY,EAAE,SAAS,EAAE,qBAAqB,EAAE,CAAC"}
|
package/dist/commands/status.js
CHANGED
|
@@ -64,13 +64,22 @@ const handleStatus = async (options) => {
|
|
|
64
64
|
for (const p of pluginDetails) {
|
|
65
65
|
const state = colorTabState(p.tabState);
|
|
66
66
|
const tools = pc.dim(`${p.toolCount} tool${p.toolCount === 1 ? '' : 's'}`);
|
|
67
|
-
|
|
67
|
+
const sourceLabel = p.source === 'local' ? ` ${pc.dim('(local)')}` : ` ${pc.dim('(npm)')}`;
|
|
68
|
+
console.log(` ${p.displayName}${sourceLabel} ${pc.dim('—')} ${state} ${pc.dim('·')} ${tools}`);
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
const failedPlugins = Array.isArray(data.failedPlugins) ? data.failedPlugins : [];
|
|
72
|
+
if (failedPlugins.length > 0) {
|
|
73
|
+
console.log('');
|
|
74
|
+
console.log(pc.bold(' Failed Plugins'));
|
|
75
|
+
for (const f of failedPlugins) {
|
|
76
|
+
console.log(` ${pc.red(f.path)} ${pc.dim('—')} ${f.error}`);
|
|
68
77
|
}
|
|
69
78
|
}
|
|
70
79
|
}
|
|
71
80
|
}
|
|
72
81
|
catch (err) {
|
|
73
|
-
const startHint = `Start it with: opentabs
|
|
82
|
+
const startHint = `Start it with: opentabs start${port !== 9515 ? ` --port ${port}` : ''}`;
|
|
74
83
|
if (isConnectionRefused(err)) {
|
|
75
84
|
console.error(pc.red('Server not running'));
|
|
76
85
|
console.error(pc.dim(startHint));
|