@opentabs-dev/cli 0.0.66 → 0.0.68

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/package.json CHANGED
@@ -1,6 +1,7 @@
1
1
  {
2
2
  "name": "@opentabs-dev/cli",
3
- "version": "0.0.66",
3
+ "version": "0.0.68",
4
+ "license": "MIT",
4
5
  "engines": {
5
6
  "node": ">= 22.0.0"
6
7
  },
@@ -1,16 +0,0 @@
1
- /**
2
- * `opentabs build` command — generates the plugin manifest and bundles the adapter IIFE.
3
- * With `--watch`, rebuilds automatically when tsc output in `dist/` changes.
4
- */
5
- import type { OpenTabsPlugin, ToolDefinition } from '@opentabs-dev/plugin-sdk';
6
- import type { Command } from 'commander';
7
- declare const validatePlugin: (plugin: OpenTabsPlugin) => string[];
8
- declare const convertToolSchemas: (tool: ToolDefinition) => {
9
- inputSchema: Record<string, unknown>;
10
- outputSchema: Record<string, unknown>;
11
- };
12
- declare const formatBytes: (bytes: number) => string;
13
- declare const formatTimestamp: () => string;
14
- declare const registerBuildCommand: (program: Command) => void;
15
- export { convertToolSchemas, formatBytes, formatTimestamp, registerBuildCommand, validatePlugin };
16
- //# sourceMappingURL=build.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"build.d.ts","sourceRoot":"","sources":["../../src/commands/build.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAOH,OAAO,KAAK,EAA0B,cAAc,EAAE,cAAc,EAAE,MAAM,0BAA0B,CAAC;AACvG,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAKzC,QAAA,MAAM,cAAc,GAAI,QAAQ,cAAc,KAAG,MAAM,EA8DtD,CAAC;AAEF,QAAA,MAAM,kBAAkB,GAAI,MAAM,cAAc;;;CA2B/C,CAAC;AAqEF,QAAA,MAAM,WAAW,GAAI,OAAO,MAAM,KAAG,MAIpC,CAAC;AAEF,QAAA,MAAM,eAAe,QAAO,MAM3B,CAAC;AAsKF,QAAA,MAAM,oBAAoB,GAAI,SAAS,OAAO,KAAG,IAahD,CAAC;AAEF,OAAO,EAAE,kBAAkB,EAAE,WAAW,EAAE,eAAe,EAAE,oBAAoB,EAAE,cAAc,EAAE,CAAC"}
@@ -1,328 +0,0 @@
1
- /**
2
- * `opentabs build` command — generates the plugin manifest and bundles the adapter IIFE.
3
- * With `--watch`, rebuilds automatically when tsc output in `dist/` changes.
4
- */
5
- import { validatePluginName, validateUrlPattern, LUCIDE_ICON_NAMES } from '@opentabs-dev/plugin-sdk';
6
- import pc from 'picocolors';
7
- import { z } from 'zod';
8
- import { mkdirSync, watch } from 'node:fs';
9
- import { resolve, join, relative } from 'node:path';
10
- const DEBOUNCE_MS = 100;
11
- const validatePlugin = (plugin) => {
12
- const errors = [];
13
- // Name
14
- const nameError = validatePluginName(plugin.name);
15
- if (nameError)
16
- errors.push(nameError);
17
- // Version — must be valid semver (e.g., "1.0.0", "0.1.0-beta.1")
18
- if (plugin.version.length === 0) {
19
- errors.push('Plugin version is required');
20
- }
21
- else if (!/^\d+\.\d+\.\d+(-[a-zA-Z0-9-]+(\.[a-zA-Z0-9-]+)*)?(\+[a-zA-Z0-9-]+(\.[a-zA-Z0-9-]+)*)?$/.test(plugin.version)) {
22
- errors.push(`Plugin version "${plugin.version}" is not valid semver (expected: MAJOR.MINOR.PATCH)`);
23
- }
24
- // Display name
25
- if (plugin.displayName.length === 0)
26
- errors.push('Plugin displayName is required');
27
- // Description
28
- if (plugin.description.length === 0)
29
- errors.push('Plugin description is required');
30
- // URL patterns
31
- if (plugin.urlPatterns.length === 0) {
32
- errors.push('At least one URL pattern is required');
33
- }
34
- else {
35
- for (const pattern of plugin.urlPatterns) {
36
- const patternError = validateUrlPattern(pattern);
37
- if (patternError)
38
- errors.push(patternError);
39
- }
40
- }
41
- // Tools
42
- if (plugin.tools.length === 0) {
43
- errors.push('At least one tool is required');
44
- }
45
- else {
46
- const TOOL_NAME_REGEX = /^[a-z][a-z0-9]*(_[a-z0-9]+)*$/;
47
- const toolNames = new Set();
48
- for (const tool of plugin.tools) {
49
- if (tool.name.length === 0) {
50
- errors.push('Tool name is required');
51
- }
52
- else if (!TOOL_NAME_REGEX.test(tool.name)) {
53
- errors.push(`Tool name "${tool.name}" must be snake_case (lowercase alphanumeric with underscores, e.g., "send_message")`);
54
- }
55
- if (!tool.displayName || tool.displayName.length === 0)
56
- errors.push(`Tool "${tool.name || '(unnamed)'}" is missing a displayName`);
57
- if (tool.description.length === 0)
58
- errors.push(`Tool "${tool.name || '(unnamed)'}" is missing a description`);
59
- if (!LUCIDE_ICON_NAMES.has(tool.icon)) {
60
- errors.push(`Tool "${tool.name || '(unnamed)'}" has invalid icon "${tool.icon}" — must be a valid Lucide icon name (kebab-case). See https://lucide.dev/icons`);
61
- }
62
- if (tool.name.length > 0 && toolNames.has(tool.name)) {
63
- errors.push(`Duplicate tool name "${tool.name}"`);
64
- }
65
- if (tool.name.length > 0)
66
- toolNames.add(tool.name);
67
- }
68
- }
69
- return errors;
70
- };
71
- const convertToolSchemas = (tool) => {
72
- let inputSchema;
73
- try {
74
- inputSchema = z.toJSONSchema(tool.input);
75
- }
76
- catch (err) {
77
- throw new Error(`Tool "${tool.name}" input schema failed to serialize to JSON Schema. ` +
78
- `Schemas cannot use .transform(), .pipe(), or .preprocess() — these produce runtime-only behavior ` +
79
- `that cannot be represented in JSON Schema. ${err instanceof Error ? err.message : String(err)}`);
80
- }
81
- let outputSchema;
82
- try {
83
- outputSchema = z.toJSONSchema(tool.output);
84
- }
85
- catch (err) {
86
- throw new Error(`Tool "${tool.name}" output schema failed to serialize to JSON Schema. ` +
87
- `Schemas cannot use .transform(), .pipe(), or .preprocess() — these produce runtime-only behavior ` +
88
- `that cannot be represented in JSON Schema. ${err instanceof Error ? err.message : String(err)}`);
89
- }
90
- delete inputSchema['$schema'];
91
- delete outputSchema['$schema'];
92
- return { inputSchema, outputSchema };
93
- };
94
- const generateManifest = (plugin) => {
95
- const tools = plugin.tools.map(tool => {
96
- const { inputSchema, outputSchema } = convertToolSchemas(tool);
97
- return {
98
- name: tool.name,
99
- displayName: tool.displayName,
100
- description: tool.description,
101
- icon: tool.icon,
102
- input_schema: inputSchema,
103
- output_schema: outputSchema,
104
- };
105
- });
106
- return {
107
- name: plugin.name,
108
- version: plugin.version,
109
- displayName: plugin.displayName,
110
- description: plugin.description,
111
- url_patterns: plugin.urlPatterns,
112
- tools,
113
- };
114
- };
115
- const bundleIIFE = async (sourceEntry, outDir, pluginName) => {
116
- // Create a temporary wrapper entry that imports the plugin and registers it
117
- // on window.__openTabs.adapters. This is bundled as an IIFE so the adapter
118
- // is available when executed in MAIN world.
119
- const wrapperPath = join(outDir, `_adapter_entry_${crypto.randomUUID()}.ts`);
120
- const relativeImport = './' + relative(outDir, sourceEntry).replace(/\.ts$/, '.js');
121
- const wrapperCode = `import plugin from ${JSON.stringify(relativeImport)};
122
- (globalThis as any).__openTabs = (globalThis as any).__openTabs || {};
123
- (globalThis as any).__openTabs.adapters = (globalThis as any).__openTabs.adapters || {};
124
- const adapters = (globalThis as any).__openTabs.adapters;
125
- const existing = adapters[${JSON.stringify(pluginName)}];
126
- if (existing && typeof existing.teardown === 'function') {
127
- try { existing.teardown(); } catch (e) { console.warn('[OpenTabs] teardown failed for ' + ${JSON.stringify(pluginName)} + ':', e); }
128
- }
129
- Reflect.deleteProperty(adapters, ${JSON.stringify(pluginName)});
130
- adapters[${JSON.stringify(pluginName)}] = plugin;
131
- `;
132
- await Bun.write(wrapperPath, wrapperCode);
133
- try {
134
- const result = await Bun.build({
135
- entrypoints: [wrapperPath],
136
- outdir: outDir,
137
- format: 'iife',
138
- target: 'browser',
139
- minify: false,
140
- naming: 'adapter.iife.js',
141
- external: [],
142
- });
143
- if (!result.success) {
144
- const messages = result.logs.map(log => (log.message ? log.message : JSON.stringify(log))).join('\n');
145
- throw new Error(`IIFE bundling failed:\n${messages}`);
146
- }
147
- }
148
- finally {
149
- try {
150
- await Bun.file(wrapperPath).delete();
151
- }
152
- catch {
153
- // best-effort cleanup
154
- }
155
- }
156
- };
157
- const formatBytes = (bytes) => {
158
- if (bytes < 1024)
159
- return `${bytes} B`;
160
- if (bytes < 1024 * 1024)
161
- return `${(bytes / 1024).toFixed(1)} KB`;
162
- return `${(bytes / (1024 * 1024)).toFixed(1)} MB`;
163
- };
164
- const formatTimestamp = () => {
165
- const now = new Date();
166
- const h = String(now.getHours()).padStart(2, '0');
167
- const m = String(now.getMinutes()).padStart(2, '0');
168
- const s = String(now.getSeconds()).padStart(2, '0');
169
- return `${h}:${m}:${s}`;
170
- };
171
- /**
172
- * Core build pipeline. Throws on errors instead of calling process.exit,
173
- * so callers can decide how to handle failures (exit in one-shot mode,
174
- * continue watching in watch mode).
175
- */
176
- const runBuild = async (projectDir) => {
177
- const startTime = performance.now();
178
- // Step 1: Verify plugin project has package.json
179
- const pkgJsonFile = Bun.file(join(projectDir, 'package.json'));
180
- if (!(await pkgJsonFile.exists())) {
181
- throw new Error('No valid package.json found in current directory. Run this command from a plugin directory.');
182
- }
183
- try {
184
- JSON.parse(await pkgJsonFile.text());
185
- }
186
- catch {
187
- throw new Error('No valid package.json found in current directory. Run this command from a plugin directory.');
188
- }
189
- // Determine entry point — look for compiled output in dist/
190
- const entryPoint = resolve(projectDir, 'dist', 'index.js');
191
- const sourceEntry = resolve(projectDir, 'src', 'index.ts');
192
- if (!(await Bun.file(entryPoint).exists())) {
193
- throw new Error(`Compiled entry point not found at ${entryPoint}. Run tsc first, then retry opentabs build.`);
194
- }
195
- // Step 2: Dynamically import the plugin module (cache-bust for watch mode rebuilds)
196
- console.log(pc.dim('Loading plugin module...'));
197
- const mod = (await import(`${entryPoint}?t=${String(Date.now())}`));
198
- const defaultExport = mod.default;
199
- if (!defaultExport) {
200
- throw new Error('Plugin module must export a default instance of OpenTabsPlugin.');
201
- }
202
- const plugin = defaultExport;
203
- // Step 3: Validate
204
- console.log(pc.dim('Validating plugin...'));
205
- const errors = validatePlugin(plugin);
206
- if (errors.length > 0) {
207
- throw new Error(`Validation failed:\n${errors.map(e => ` - ${e}`).join('\n')}`);
208
- }
209
- // Step 4: Bundle IIFE (before manifest, so adapterHash can be included)
210
- console.log(pc.dim('Bundling adapter IIFE...'));
211
- const distDir = join(projectDir, 'dist');
212
- mkdirSync(distDir, { recursive: true });
213
- await bundleIIFE(sourceEntry, distDir, plugin.name);
214
- // Read the bundled IIFE and compute its SHA-256 hash. The hash is computed
215
- // from the core IIFE content (before the __adapterHash setter is appended).
216
- const iifePath = join(distDir, 'adapter.iife.js');
217
- const iifeContent = await Bun.file(iifePath).text();
218
- const adapterHash = new Bun.CryptoHasher('sha256').update(iifeContent).digest('hex');
219
- // Append a self-contained snippet that sets the adapter hash and then freezes
220
- // the adapter entry to prevent cross-adapter tampering. The freeze must happen
221
- // AFTER the hash is set (since frozen objects reject new properties). The
222
- // property descriptor uses writable:false + configurable:true so that:
223
- // - Simple assignment by page scripts fails (non-writable)
224
- // - Re-injection via Object.defineProperty succeeds (configurable)
225
- // - Extension cleanup via Reflect.deleteProperty succeeds (configurable)
226
- const hashAndFreeze = `
227
- (function(){var o=(globalThis).__openTabs;if(o&&o.adapters&&o.adapters[${JSON.stringify(plugin.name)}]){var a=o.adapters[${JSON.stringify(plugin.name)}];a.__adapterHash=${JSON.stringify(adapterHash)};if(a.tools&&Array.isArray(a.tools)){for(var i=0;i<a.tools.length;i++){Object.freeze(a.tools[i]);}Object.freeze(a.tools);}Object.freeze(a);Object.defineProperty(o.adapters,${JSON.stringify(plugin.name)},{value:a,writable:false,configurable:true,enumerable:true});}})();
228
- `;
229
- await Bun.write(iifePath, iifeContent + hashAndFreeze);
230
- const iifeSize = (await Bun.file(iifePath).stat()).size;
231
- console.log(` Written: ${pc.bold('dist/adapter.iife.js')} (${formatBytes(iifeSize)})`);
232
- // Step 5: Generate manifest (includes adapterHash from the IIFE)
233
- console.log(pc.dim('Generating manifest...'));
234
- const manifest = generateManifest(plugin);
235
- manifest.adapterHash = adapterHash;
236
- const manifestPath = join(projectDir, 'opentabs-plugin.json');
237
- await Bun.write(manifestPath, JSON.stringify(manifest, null, 2) + '\n');
238
- console.log(` Written: ${pc.bold('opentabs-plugin.json')} (${manifest.tools.length} tool${manifest.tools.length === 1 ? '' : 's'})`);
239
- const elapsed = ((performance.now() - startTime) / 1000).toFixed(1);
240
- console.log('');
241
- console.log(pc.green(`Build complete for plugin "${plugin.name}" v${plugin.version} in ${elapsed}s`));
242
- };
243
- const handleBuild = async (options) => {
244
- const projectDir = process.cwd();
245
- // Initial build — always runs
246
- try {
247
- await runBuild(projectDir);
248
- }
249
- catch (err) {
250
- console.error(pc.red(`Error: ${err instanceof Error ? err.message : String(err)}`));
251
- process.exit(1);
252
- }
253
- if (!options.watch)
254
- return;
255
- // Watch mode: watch dist/ for changes to .js files and rebuild
256
- const distDir = join(projectDir, 'dist');
257
- let debounceTimer = null;
258
- let building = false;
259
- let pendingRebuild = false;
260
- const rebuild = async () => {
261
- if (building) {
262
- pendingRebuild = true;
263
- return;
264
- }
265
- building = true;
266
- console.log('');
267
- console.log(pc.dim(`[${formatTimestamp()}] Change detected, rebuilding...`));
268
- try {
269
- await runBuild(projectDir);
270
- }
271
- catch (err) {
272
- console.error(pc.red(`[${formatTimestamp()}] Rebuild failed: ${err instanceof Error ? err.message : String(err)}`));
273
- }
274
- finally {
275
- building = false;
276
- if (pendingRebuild) {
277
- pendingRebuild = false;
278
- void rebuild();
279
- }
280
- }
281
- };
282
- let watcher;
283
- try {
284
- watcher = watch(distDir, { recursive: true }, (_event, filename) => {
285
- // Only react to .js file changes (tsc output), skip adapter.iife.js
286
- // and temporary wrapper files to avoid rebuild loops
287
- if (!filename ||
288
- !filename.endsWith('.js') ||
289
- filename === 'adapter.iife.js' ||
290
- filename.startsWith('_adapter_entry_'))
291
- return;
292
- if (debounceTimer)
293
- clearTimeout(debounceTimer);
294
- debounceTimer = setTimeout(() => void rebuild(), DEBOUNCE_MS);
295
- });
296
- }
297
- catch {
298
- console.error(pc.red(`Error: Could not watch ${distDir}. Ensure the dist/ directory exists.`));
299
- process.exit(1);
300
- }
301
- console.log('');
302
- console.log(pc.cyan(`Watching ${pc.bold('dist/')} for changes... (Ctrl+C to stop)`));
303
- const cleanup = () => {
304
- if (debounceTimer)
305
- clearTimeout(debounceTimer);
306
- watcher.close();
307
- console.log('');
308
- console.log(pc.dim('Watcher stopped.'));
309
- process.exit(0);
310
- };
311
- process.on('SIGINT', cleanup);
312
- process.on('SIGTERM', cleanup);
313
- // Keep the process alive
314
- await new Promise(() => { });
315
- };
316
- const registerBuildCommand = (program) => {
317
- program
318
- .command('build')
319
- .description('Build the current plugin directory (manifest + adapter IIFE)')
320
- .option('-w, --watch', 'Watch dist/ for changes and rebuild automatically')
321
- .addHelpText('after', `
322
- Examples:
323
- $ opentabs build
324
- $ opentabs build --watch`)
325
- .action((options) => handleBuild(options));
326
- };
327
- export { convertToolSchemas, formatBytes, formatTimestamp, registerBuildCommand, validatePlugin };
328
- //# sourceMappingURL=build.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"build.js","sourceRoot":"","sources":["../../src/commands/build.ts"],"names":[],"mappings":"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"}
@@ -1,10 +0,0 @@
1
- /**
2
- * `opentabs dev` command — starts the MCP server with hot reload.
3
- *
4
- * Server output is written to both the terminal and a log file at
5
- * ~/.opentabs/server.log (or $OPENTABS_CONFIG_DIR/server.log).
6
- * The `opentabs logs` command tails this file.
7
- */
8
- import type { Command } from 'commander';
9
- export declare const registerDevCommand: (program: Command) => void;
10
- //# sourceMappingURL=dev.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"dev.d.ts","sourceRoot":"","sources":["../../src/commands/dev.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AASH,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAgHzC,eAAO,MAAM,kBAAkB,GAAI,SAAS,OAAO,KAAG,IA8BrD,CAAC"}
@@ -1,128 +0,0 @@
1
- /**
2
- * `opentabs dev` command — starts the MCP server with hot reload.
3
- *
4
- * Server output is written to both the terminal and a log file at
5
- * ~/.opentabs/server.log (or $OPENTABS_CONFIG_DIR/server.log).
6
- * The `opentabs logs` command tails this file.
7
- */
8
- import { getConfigDir, getLogFilePath } from '../config.js';
9
- import { parsePort, resolvePort } from '../parse-port.js';
10
- import { InvalidArgumentError } from 'commander';
11
- import pc from 'picocolors';
12
- import { mkdirSync, createWriteStream } from 'node:fs';
13
- import { resolve, dirname } from 'node:path';
14
- import { fileURLToPath } from 'node:url';
15
- const LOG_LEVELS = ['debug', 'info', 'warn', 'error', 'silent'];
16
- const resolveServerEntry = () => {
17
- try {
18
- return fileURLToPath(import.meta.resolve('@opentabs-dev/mcp-server'));
19
- }
20
- catch {
21
- const cliDir = dirname(fileURLToPath(import.meta.url));
22
- return resolve(cliDir, '..', '..', '..', 'mcp-server', 'dist', 'index.js');
23
- }
24
- };
25
- const isPortInUse = async (port) => {
26
- try {
27
- await fetch(`http://localhost:${port}/health`, {
28
- signal: AbortSignal.timeout(1_000),
29
- });
30
- return true;
31
- }
32
- catch {
33
- return false;
34
- }
35
- };
36
- /**
37
- * Pipe a readable stream to both a terminal writable and a log file stream.
38
- * Returns when the readable stream ends.
39
- */
40
- const teeStream = async (readable, terminal, logFile) => {
41
- const reader = readable.getReader();
42
- for (;;) {
43
- const { done, value } = await reader.read();
44
- if (done)
45
- break;
46
- terminal.write(value);
47
- logFile.write(value);
48
- }
49
- };
50
- const handleDev = async (options) => {
51
- const serverEntry = resolveServerEntry();
52
- if (!(await Bun.file(serverEntry).exists())) {
53
- console.error(pc.red(`Error: MCP server entry not found at ${serverEntry}`));
54
- console.error('Run bun run build from the project root first.');
55
- process.exit(1);
56
- }
57
- const port = resolvePort(options);
58
- if (await isPortInUse(port)) {
59
- console.error(pc.red(`Error: Port ${port} is already in use.`));
60
- console.error(port === 9515
61
- ? 'Another OpenTabs server may already be running. Use --port to specify a different port.'
62
- : `Use a different port with: opentabs dev --port <number>`);
63
- process.exit(1);
64
- }
65
- const env = { ...process.env };
66
- env.PORT = String(port);
67
- if (options.verbose)
68
- env.OPENTABS_LOG_LEVEL = 'debug';
69
- else if (options.logLevel)
70
- env.OPENTABS_LOG_LEVEL = options.logLevel;
71
- const logFilePath = getLogFilePath();
72
- mkdirSync(getConfigDir(), { recursive: true });
73
- const logStream = createWriteStream(logFilePath, { flags: 'a' });
74
- console.log(`Starting OpenTabs MCP server on port ${pc.bold(String(port))}...`);
75
- console.log('');
76
- console.log(` ${pc.cyan('MCP endpoint:')} http://localhost:${port}/mcp`);
77
- console.log(` ${pc.cyan('Health check:')} http://localhost:${port}/health`);
78
- console.log(` ${pc.cyan('Log file:')} ${logFilePath}`);
79
- console.log('');
80
- console.log(pc.dim(' MCP client config (~/.claude/settings/mcp.json):'));
81
- console.log(pc.dim(` { "mcpServers": { "opentabs": { "type": "streamable-http", "url": "http://127.0.0.1:${port}/mcp" } } }`));
82
- console.log('');
83
- if (options.verbose)
84
- console.log(pc.yellow(' Debug logging enabled'));
85
- console.log(pc.dim(' Press Ctrl+C to stop'));
86
- console.log('');
87
- const proc = Bun.spawn(['bun', '--hot', serverEntry], {
88
- env: env,
89
- stdio: ['inherit', 'pipe', 'pipe'],
90
- });
91
- const stdoutPipe = teeStream(proc.stdout, process.stdout, logStream);
92
- const stderrPipe = teeStream(proc.stderr, process.stderr, logStream);
93
- process.on('SIGINT', () => proc.kill('SIGINT'));
94
- process.on('SIGTERM', () => proc.kill('SIGTERM'));
95
- await Promise.all([stdoutPipe, stderrPipe]);
96
- logStream.end();
97
- const exitCode = await proc.exited;
98
- process.exit(exitCode);
99
- };
100
- export const registerDevCommand = (program) => {
101
- program
102
- .command('dev')
103
- .description('Start the MCP server with hot reload')
104
- .option('--port <number>', 'Server port (default: 9515)', parsePort)
105
- .option('--verbose', 'Enable debug logging (shorthand for --log-level debug)')
106
- .option('--log-level <level>', 'Set log level', (value) => {
107
- if (!LOG_LEVELS.includes(value)) {
108
- throw new InvalidArgumentError(`Must be one of: ${LOG_LEVELS.join(', ')}`);
109
- }
110
- return value;
111
- })
112
- .addHelpText('after', `
113
- Examples:
114
- $ opentabs dev
115
- $ opentabs dev --port 3000
116
- $ opentabs dev --verbose
117
- $ opentabs dev --log-level warn`)
118
- .action((_options, command) => {
119
- const opts = command.optsWithGlobals();
120
- if (opts.verbose && opts.logLevel) {
121
- console.error(pc.red('Error: --verbose and --log-level cannot be used together.'));
122
- console.error('Use --verbose for debug logging, or --log-level to set a specific level.');
123
- process.exit(1);
124
- }
125
- return handleDev(opts);
126
- });
127
- };
128
- //# sourceMappingURL=dev.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"dev.js","sourceRoot":"","sources":["../../src/commands/dev.ts"],"names":[],"mappings":"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"}
@@ -1,7 +0,0 @@
1
- /**
2
- * `opentabs reload` command — triggers server config/plugin rediscovery or extension reload.
3
- */
4
- import type { Command } from 'commander';
5
- declare const registerReloadCommand: (program: Command) => void;
6
- export { registerReloadCommand };
7
- //# sourceMappingURL=reload.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"reload.d.ts","sourceRoot":"","sources":["../../src/commands/reload.ts"],"names":[],"mappings":"AAAA;;GAEG;AAKH,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AA2EzC,QAAA,MAAM,qBAAqB,GAAI,SAAS,OAAO,KAAG,IAejD,CAAC;AAEF,OAAO,EAAE,qBAAqB,EAAE,CAAC"}
@@ -1,88 +0,0 @@
1
- /**
2
- * `opentabs reload` command — triggers server config/plugin rediscovery or extension reload.
3
- */
4
- import { isConnectionRefused } from '../config.js';
5
- import { parsePort, resolvePort } from '../parse-port.js';
6
- import pc from 'picocolors';
7
- const handleReload = async (options) => {
8
- const port = resolvePort(options);
9
- if (options.extension) {
10
- await reloadExtension(port);
11
- }
12
- else {
13
- await reloadServer(port);
14
- }
15
- };
16
- const reloadServer = async (port) => {
17
- const url = `http://localhost:${port}/reload`;
18
- try {
19
- const res = await fetch(url, { method: 'POST', signal: AbortSignal.timeout(10_000) });
20
- const data = (await res.json());
21
- if (data.ok) {
22
- console.log(pc.green('Server reloaded successfully'));
23
- if (data.plugins !== undefined && data.durationMs !== undefined) {
24
- console.log(pc.dim(` ${data.plugins} plugin(s) discovered in ${data.durationMs}ms`));
25
- }
26
- }
27
- else {
28
- console.error(pc.red(`Reload failed: ${data.error ?? 'unknown error'}`));
29
- process.exit(1);
30
- }
31
- }
32
- catch (err) {
33
- if (isConnectionRefused(err)) {
34
- console.error(pc.red('Server not running'));
35
- const portSuffix = port !== 9515 ? ` --port ${port}` : '';
36
- console.error(pc.dim(`Start it with: opentabs dev${portSuffix}`));
37
- }
38
- else {
39
- const message = err instanceof Error ? err.message : String(err);
40
- console.error(pc.red(`Error: ${message}`));
41
- }
42
- process.exit(1);
43
- }
44
- };
45
- const reloadExtension = async (port) => {
46
- const url = `http://localhost:${port}/extension/reload`;
47
- try {
48
- const res = await fetch(url, { method: 'POST', signal: AbortSignal.timeout(5_000) });
49
- const data = (await res.json());
50
- if (data.ok) {
51
- console.log(pc.green('Extension reload signal sent'));
52
- if (data.message) {
53
- console.log(pc.dim(` ${data.message}`));
54
- }
55
- }
56
- else {
57
- console.error(pc.red(`Extension reload failed: ${data.error ?? 'unknown error'}`));
58
- process.exit(1);
59
- }
60
- }
61
- catch (err) {
62
- if (isConnectionRefused(err)) {
63
- console.error(pc.red('Server not running'));
64
- const portSuffix = port !== 9515 ? ` --port ${port}` : '';
65
- console.error(pc.dim(`Start it with: opentabs dev${portSuffix}`));
66
- }
67
- else {
68
- const message = err instanceof Error ? err.message : String(err);
69
- console.error(pc.red(`Error: ${message}`));
70
- }
71
- process.exit(1);
72
- }
73
- };
74
- const registerReloadCommand = (program) => {
75
- program
76
- .command('reload')
77
- .description('Reload server config/plugins or trigger extension reload')
78
- .option('--port <number>', 'MCP server port (default: 9515)', parsePort)
79
- .option('--extension', 'Reload the Chrome extension instead of server config')
80
- .addHelpText('after', `
81
- Examples:
82
- $ opentabs reload # Reload server config and plugins
83
- $ opentabs reload --extension # Reload the Chrome extension
84
- $ opentabs reload --port 3000 # Reload server on custom port`)
85
- .action((_options, command) => handleReload(command.optsWithGlobals()));
86
- };
87
- export { registerReloadCommand };
88
- //# sourceMappingURL=reload.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"reload.js","sourceRoot":"","sources":["../../src/commands/reload.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,EAAE,mBAAmB,EAAE,MAAM,cAAc,CAAC;AACnD,OAAO,EAAE,SAAS,EAAE,WAAW,EAAE,MAAM,kBAAkB,CAAC;AAC1D,OAAO,EAAE,MAAM,YAAY,CAAC;AAQ5B,MAAM,YAAY,GAAG,KAAK,EAAE,OAAsB,EAAiB,EAAE;IACnE,MAAM,IAAI,GAAG,WAAW,CAAC,OAAO,CAAC,CAAC;IAElC,IAAI,OAAO,CAAC,SAAS,EAAE,CAAC;QACtB,MAAM,eAAe,CAAC,IAAI,CAAC,CAAC;IAC9B,CAAC;SAAM,CAAC;QACN,MAAM,YAAY,CAAC,IAAI,CAAC,CAAC;IAC3B,CAAC;AACH,CAAC,CAAC;AAEF,MAAM,YAAY,GAAG,KAAK,EAAE,IAAY,EAAiB,EAAE;IACzD,MAAM,GAAG,GAAG,oBAAoB,IAAI,SAAS,CAAC;IAE9C,IAAI,CAAC;QACH,MAAM,GAAG,GAAG,MAAM,KAAK,CAAC,GAAG,EAAE,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,WAAW,CAAC,OAAO,CAAC,MAAM,CAAC,EAAE,CAAC,CAAC;QACtF,MAAM,IAAI,GAAG,CAAC,MAAM,GAAG,CAAC,IAAI,EAAE,CAA2E,CAAC;QAE1G,IAAI,IAAI,CAAC,EAAE,EAAE,CAAC;YACZ,OAAO,CAAC,GAAG,CAAC,EAAE,CAAC,KAAK,CAAC,8BAA8B,CAAC,CAAC,CAAC;YACtD,IAAI,IAAI,CAAC,OAAO,KAAK,SAAS,IAAI,IAAI,CAAC,UAAU,KAAK,SAAS,EAAE,CAAC;gBAChE,OAAO,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,CAAC,KAAK,IAAI,CAAC,OAAO,4BAA4B,IAAI,CAAC,UAAU,IAAI,CAAC,CAAC,CAAC;YACxF,CAAC;QACH,CAAC;aAAM,CAAC;YACN,OAAO,CAAC,KAAK,CAAC,EAAE,CAAC,GAAG,CAAC,kBAAkB,IAAI,CAAC,KAAK,IAAI,eAAe,EAAE,CAAC,CAAC,CAAC;YACzE,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;QAClB,CAAC;IACH,CAAC;IAAC,OAAO,GAAY,EAAE,CAAC;QACtB,IAAI,mBAAmB,CAAC,GAAG,CAAC,EAAE,CAAC;YAC7B,OAAO,CAAC,KAAK,CAAC,EAAE,CAAC,GAAG,CAAC,oBAAoB,CAAC,CAAC,CAAC;YAC5C,MAAM,UAAU,GAAG,IAAI,KAAK,IAAI,CAAC,CAAC,CAAC,WAAW,IAAI,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;YAC1D,OAAO,CAAC,KAAK,CAAC,EAAE,CAAC,GAAG,CAAC,8BAA8B,UAAU,EAAE,CAAC,CAAC,CAAC;QACpE,CAAC;aAAM,CAAC;YACN,MAAM,OAAO,GAAG,GAAG,YAAY,KAAK,CAAC,CAAC,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC;YACjE,OAAO,CAAC,KAAK,CAAC,EAAE,CAAC,GAAG,CAAC,UAAU,OAAO,EAAE,CAAC,CAAC,CAAC;QAC7C,CAAC;QACD,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IAClB,CAAC;AACH,CAAC,CAAC;AAEF,MAAM,eAAe,GAAG,KAAK,EAAE,IAAY,EAAiB,EAAE;IAC5D,MAAM,GAAG,GAAG,oBAAoB,IAAI,mBAAmB,CAAC;IAExD,IAAI,CAAC;QACH,MAAM,GAAG,GAAG,MAAM,KAAK,CAAC,GAAG,EAAE,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,WAAW,CAAC,OAAO,CAAC,KAAK,CAAC,EAAE,CAAC,CAAC;QACrF,MAAM,IAAI,GAAG,CAAC,MAAM,GAAG,CAAC,IAAI,EAAE,CAAsD,CAAC;QAErF,IAAI,IAAI,CAAC,EAAE,EAAE,CAAC;YACZ,OAAO,CAAC,GAAG,CAAC,EAAE,CAAC,KAAK,CAAC,8BAA8B,CAAC,CAAC,CAAC;YACtD,IAAI,IAAI,CAAC,OAAO,EAAE,CAAC;gBACjB,OAAO,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,CAAC,KAAK,IAAI,CAAC,OAAO,EAAE,CAAC,CAAC,CAAC;YAC3C,CAAC;QACH,CAAC;aAAM,CAAC;YACN,OAAO,CAAC,KAAK,CAAC,EAAE,CAAC,GAAG,CAAC,4BAA4B,IAAI,CAAC,KAAK,IAAI,eAAe,EAAE,CAAC,CAAC,CAAC;YACnF,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;QAClB,CAAC;IACH,CAAC;IAAC,OAAO,GAAY,EAAE,CAAC;QACtB,IAAI,mBAAmB,CAAC,GAAG,CAAC,EAAE,CAAC;YAC7B,OAAO,CAAC,KAAK,CAAC,EAAE,CAAC,GAAG,CAAC,oBAAoB,CAAC,CAAC,CAAC;YAC5C,MAAM,UAAU,GAAG,IAAI,KAAK,IAAI,CAAC,CAAC,CAAC,WAAW,IAAI,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;YAC1D,OAAO,CAAC,KAAK,CAAC,EAAE,CAAC,GAAG,CAAC,8BAA8B,UAAU,EAAE,CAAC,CAAC,CAAC;QACpE,CAAC;aAAM,CAAC;YACN,MAAM,OAAO,GAAG,GAAG,YAAY,KAAK,CAAC,CAAC,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC;YACjE,OAAO,CAAC,KAAK,CAAC,EAAE,CAAC,GAAG,CAAC,UAAU,OAAO,EAAE,CAAC,CAAC,CAAC;QAC7C,CAAC;QACD,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IAClB,CAAC;AACH,CAAC,CAAC;AAEF,MAAM,qBAAqB,GAAG,CAAC,OAAgB,EAAQ,EAAE;IACvD,OAAO;SACJ,OAAO,CAAC,QAAQ,CAAC;SACjB,WAAW,CAAC,0DAA0D,CAAC;SACvE,MAAM,CAAC,iBAAiB,EAAE,iCAAiC,EAAE,SAAS,CAAC;SACvE,MAAM,CAAC,aAAa,EAAE,sDAAsD,CAAC;SAC7E,WAAW,CACV,OAAO,EACP;;;;oEAI8D,CAC/D;SACA,MAAM,CAAC,CAAC,QAAuB,EAAE,OAAgB,EAAE,EAAE,CAAC,YAAY,CAAC,OAAO,CAAC,eAAe,EAAE,CAAC,CAAC,CAAC;AACpG,CAAC,CAAC;AAEF,OAAO,EAAE,qBAAqB,EAAE,CAAC"}