@opentabs-dev/cli 0.0.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.
Files changed (57) hide show
  1. package/dist/cli.d.ts +3 -0
  2. package/dist/cli.d.ts.map +1 -0
  3. package/dist/cli.js +26 -0
  4. package/dist/cli.js.map +1 -0
  5. package/dist/commands/build.d.ts +10 -0
  6. package/dist/commands/build.d.ts.map +1 -0
  7. package/dist/commands/build.js +285 -0
  8. package/dist/commands/build.js.map +1 -0
  9. package/dist/commands/config.d.ts +7 -0
  10. package/dist/commands/config.d.ts.map +1 -0
  11. package/dist/commands/config.js +157 -0
  12. package/dist/commands/config.js.map +1 -0
  13. package/dist/commands/dev.d.ts +10 -0
  14. package/dist/commands/dev.d.ts.map +1 -0
  15. package/dist/commands/dev.js +128 -0
  16. package/dist/commands/dev.js.map +1 -0
  17. package/dist/commands/doctor.d.ts +7 -0
  18. package/dist/commands/doctor.d.ts.map +1 -0
  19. package/dist/commands/doctor.js +212 -0
  20. package/dist/commands/doctor.js.map +1 -0
  21. package/dist/commands/index.d.ts +10 -0
  22. package/dist/commands/index.d.ts.map +1 -0
  23. package/dist/commands/index.js +10 -0
  24. package/dist/commands/index.js.map +1 -0
  25. package/dist/commands/logs.d.ts +10 -0
  26. package/dist/commands/logs.d.ts.map +1 -0
  27. package/dist/commands/logs.js +103 -0
  28. package/dist/commands/logs.js.map +1 -0
  29. package/dist/commands/plugin.d.ts +6 -0
  30. package/dist/commands/plugin.d.ts.map +1 -0
  31. package/dist/commands/plugin.js +199 -0
  32. package/dist/commands/plugin.js.map +1 -0
  33. package/dist/commands/reload.d.ts +7 -0
  34. package/dist/commands/reload.d.ts.map +1 -0
  35. package/dist/commands/reload.js +88 -0
  36. package/dist/commands/reload.js.map +1 -0
  37. package/dist/commands/setup.d.ts +6 -0
  38. package/dist/commands/setup.d.ts.map +1 -0
  39. package/dist/commands/setup.js +70 -0
  40. package/dist/commands/setup.js.map +1 -0
  41. package/dist/commands/status.d.ts +7 -0
  42. package/dist/commands/status.d.ts.map +1 -0
  43. package/dist/commands/status.js +108 -0
  44. package/dist/commands/status.js.map +1 -0
  45. package/dist/config.d.ts +11 -0
  46. package/dist/config.d.ts.map +1 -0
  47. package/dist/config.js +37 -0
  48. package/dist/config.js.map +1 -0
  49. package/dist/parse-port.d.ts +15 -0
  50. package/dist/parse-port.d.ts.map +1 -0
  51. package/dist/parse-port.js +32 -0
  52. package/dist/parse-port.js.map +1 -0
  53. package/dist/scaffold.d.ts +21 -0
  54. package/dist/scaffold.d.ts.map +1 -0
  55. package/dist/scaffold.js +273 -0
  56. package/dist/scaffold.js.map +1 -0
  57. package/package.json +33 -0
package/dist/cli.d.ts ADDED
@@ -0,0 +1,3 @@
1
+ #!/usr/bin/env bun
2
+ export {};
3
+ //# sourceMappingURL=cli.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"cli.d.ts","sourceRoot":"","sources":["../src/cli.ts"],"names":[],"mappings":""}
package/dist/cli.js ADDED
@@ -0,0 +1,26 @@
1
+ #!/usr/bin/env bun
2
+ import { registerBuildCommand, registerConfigCommand, registerDevCommand, registerDoctorCommand, registerLogsCommand, registerPluginCommand, registerReloadCommand, registerSetupCommand, registerStatusCommand, } from './commands/index.js';
3
+ import { parsePort } from './parse-port.js';
4
+ import { Command } from 'commander';
5
+ import { dirname, join } from 'node:path';
6
+ import { fileURLToPath } from 'node:url';
7
+ const cliDir = dirname(fileURLToPath(import.meta.url));
8
+ const pkgJson = JSON.parse(await Bun.file(join(cliDir, '..', 'package.json')).text());
9
+ const program = new Command('opentabs')
10
+ .version(pkgJson.version, '-V, --version')
11
+ .description('OpenTabs CLI — develop, build, and manage plugins')
12
+ .option('--port <number>', 'MCP server port (env: OPENTABS_PORT, default: 9515)', parsePort)
13
+ .action(() => {
14
+ program.help();
15
+ });
16
+ registerBuildCommand(program);
17
+ registerConfigCommand(program);
18
+ registerDevCommand(program);
19
+ registerDoctorCommand(program);
20
+ registerLogsCommand(program);
21
+ registerReloadCommand(program);
22
+ registerStatusCommand(program);
23
+ registerSetupCommand(program);
24
+ registerPluginCommand(program);
25
+ await program.parseAsync();
26
+ //# sourceMappingURL=cli.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"cli.js","sourceRoot":"","sources":["../src/cli.ts"],"names":[],"mappings":";AAEA,OAAO,EACL,oBAAoB,EACpB,qBAAqB,EACrB,kBAAkB,EAClB,qBAAqB,EACrB,mBAAmB,EACnB,qBAAqB,EACrB,qBAAqB,EACrB,oBAAoB,EACpB,qBAAqB,GACtB,MAAM,qBAAqB,CAAC;AAC7B,OAAO,EAAE,SAAS,EAAE,MAAM,iBAAiB,CAAC;AAC5C,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AACpC,OAAO,EAAE,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AAC1C,OAAO,EAAE,aAAa,EAAE,MAAM,UAAU,CAAC;AAEzC,MAAM,MAAM,GAAG,OAAO,CAAC,aAAa,CAAC,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC;AACvD,MAAM,OAAO,GAAG,IAAI,CAAC,KAAK,CAAC,MAAM,GAAG,CAAC,IAAI,CAAC,IAAI,CAAC,MAAM,EAAE,IAAI,EAAE,cAAc,CAAC,CAAC,CAAC,IAAI,EAAE,CAAwB,CAAC;AAE7G,MAAM,OAAO,GAAG,IAAI,OAAO,CAAC,UAAU,CAAC;KACpC,OAAO,CAAC,OAAO,CAAC,OAAO,EAAE,eAAe,CAAC;KACzC,WAAW,CAAC,mDAAmD,CAAC;KAChE,MAAM,CAAC,iBAAiB,EAAE,qDAAqD,EAAE,SAAS,CAAC;KAC3F,MAAM,CAAC,GAAG,EAAE;IACX,OAAO,CAAC,IAAI,EAAE,CAAC;AACjB,CAAC,CAAC,CAAC;AAEL,oBAAoB,CAAC,OAAO,CAAC,CAAC;AAC9B,qBAAqB,CAAC,OAAO,CAAC,CAAC;AAC/B,kBAAkB,CAAC,OAAO,CAAC,CAAC;AAC5B,qBAAqB,CAAC,OAAO,CAAC,CAAC;AAC/B,mBAAmB,CAAC,OAAO,CAAC,CAAC;AAC7B,qBAAqB,CAAC,OAAO,CAAC,CAAC;AAC/B,qBAAqB,CAAC,OAAO,CAAC,CAAC;AAC/B,oBAAoB,CAAC,OAAO,CAAC,CAAC;AAC9B,qBAAqB,CAAC,OAAO,CAAC,CAAC;AAE/B,MAAM,OAAO,CAAC,UAAU,EAAE,CAAC"}
@@ -0,0 +1,10 @@
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 } from '@opentabs-dev/plugin-sdk';
6
+ import type { Command } from 'commander';
7
+ declare const validatePlugin: (plugin: OpenTabsPlugin) => string[];
8
+ declare const registerBuildCommand: (program: Command) => void;
9
+ export { registerBuildCommand, validatePlugin };
10
+ //# sourceMappingURL=build.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"build.d.ts","sourceRoot":"","sources":["../../src/commands/build.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAOH,OAAO,KAAK,EAA0B,cAAc,EAAkB,MAAM,0BAA0B,CAAC;AACvG,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAKzC,QAAA,MAAM,cAAc,GAAI,QAAQ,cAAc,KAAG,MAAM,EAoDtD,CAAC;AA8OF,QAAA,MAAM,oBAAoB,GAAI,SAAS,OAAO,KAAG,IAahD,CAAC;AAEF,OAAO,EAAE,oBAAoB,EAAE,cAAc,EAAE,CAAC"}
@@ -0,0 +1,285 @@
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 } from '@opentabs-dev/plugin-sdk';
6
+ import pc from 'picocolors';
7
+ import { zodToJsonSchema } from 'zod-to-json-schema';
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
+ // Description
25
+ if (plugin.description.length === 0)
26
+ errors.push('Plugin description is required');
27
+ // URL patterns
28
+ if (plugin.urlPatterns.length === 0) {
29
+ errors.push('At least one URL pattern is required');
30
+ }
31
+ else {
32
+ for (const pattern of plugin.urlPatterns) {
33
+ const patternError = validateUrlPattern(pattern);
34
+ if (patternError)
35
+ errors.push(patternError);
36
+ }
37
+ }
38
+ // Tools
39
+ if (plugin.tools.length === 0) {
40
+ errors.push('At least one tool is required');
41
+ }
42
+ else {
43
+ const TOOL_NAME_REGEX = /^[a-z][a-z0-9]*(_[a-z0-9]+)*$/;
44
+ const toolNames = new Set();
45
+ for (const tool of plugin.tools) {
46
+ if (tool.name.length === 0) {
47
+ errors.push('Tool name is required');
48
+ }
49
+ else if (!TOOL_NAME_REGEX.test(tool.name)) {
50
+ errors.push(`Tool name "${tool.name}" must be snake_case (lowercase alphanumeric with underscores, e.g., "send_message")`);
51
+ }
52
+ if (tool.description.length === 0)
53
+ errors.push(`Tool "${tool.name || '(unnamed)'}" is missing a description`);
54
+ if (tool.name.length > 0 && toolNames.has(tool.name)) {
55
+ errors.push(`Duplicate tool name "${tool.name}"`);
56
+ }
57
+ if (tool.name.length > 0)
58
+ toolNames.add(tool.name);
59
+ }
60
+ }
61
+ return errors;
62
+ };
63
+ const convertToolSchemas = (tool) => {
64
+ const inputSchema = zodToJsonSchema(tool.input, { target: 'openApi3', $refStrategy: 'none' });
65
+ const outputSchema = zodToJsonSchema(tool.output, { target: 'openApi3', $refStrategy: 'none' });
66
+ // Remove the $schema property that zod-to-json-schema adds
67
+ delete inputSchema['$schema'];
68
+ delete outputSchema['$schema'];
69
+ return { inputSchema, outputSchema };
70
+ };
71
+ const generateManifest = (plugin) => {
72
+ const tools = plugin.tools.map(tool => {
73
+ const { inputSchema, outputSchema } = convertToolSchemas(tool);
74
+ return {
75
+ name: tool.name,
76
+ description: tool.description,
77
+ input_schema: inputSchema,
78
+ output_schema: outputSchema,
79
+ };
80
+ });
81
+ return {
82
+ name: plugin.name,
83
+ version: plugin.version,
84
+ displayName: plugin.displayName ?? plugin.name,
85
+ description: plugin.description,
86
+ url_patterns: plugin.urlPatterns,
87
+ tools,
88
+ };
89
+ };
90
+ const bundleIIFE = async (sourceEntry, outDir, pluginName) => {
91
+ // Create a temporary wrapper entry that imports the plugin and registers it
92
+ // on window.__openTabs.adapters. This is bundled as an IIFE so the adapter
93
+ // is available when executed in MAIN world.
94
+ const wrapperPath = join(outDir, `_adapter_entry_${Date.now()}.ts`);
95
+ const relativeImport = './' + relative(outDir, sourceEntry).replace(/\.ts$/, '.js');
96
+ const wrapperCode = `import plugin from ${JSON.stringify(relativeImport)};
97
+ (globalThis as any).__openTabs = (globalThis as any).__openTabs || {};
98
+ (globalThis as any).__openTabs.adapters = (globalThis as any).__openTabs.adapters || {};
99
+ const adapters = (globalThis as any).__openTabs.adapters;
100
+ const existing = adapters[${JSON.stringify(pluginName)}];
101
+ if (existing && typeof existing.teardown === 'function') {
102
+ try { existing.teardown(); } catch (e) { console.warn('[OpenTabs] teardown failed for ' + ${JSON.stringify(pluginName)} + ':', e); }
103
+ }
104
+ adapters[${JSON.stringify(pluginName)}] = plugin;
105
+ `;
106
+ await Bun.write(wrapperPath, wrapperCode);
107
+ try {
108
+ const result = await Bun.build({
109
+ entrypoints: [wrapperPath],
110
+ outdir: outDir,
111
+ format: 'iife',
112
+ target: 'browser',
113
+ minify: false,
114
+ naming: 'adapter.iife.js',
115
+ external: [],
116
+ });
117
+ if (!result.success) {
118
+ const messages = result.logs.map(log => (log.message ? log.message : JSON.stringify(log))).join('\n');
119
+ throw new Error(`IIFE bundling failed:\n${messages}`);
120
+ }
121
+ }
122
+ finally {
123
+ try {
124
+ await Bun.file(wrapperPath).delete();
125
+ }
126
+ catch {
127
+ // best-effort cleanup
128
+ }
129
+ }
130
+ };
131
+ const formatBytes = (bytes) => {
132
+ if (bytes < 1024)
133
+ return `${bytes} B`;
134
+ if (bytes < 1024 * 1024)
135
+ return `${(bytes / 1024).toFixed(1)} KB`;
136
+ return `${(bytes / (1024 * 1024)).toFixed(1)} MB`;
137
+ };
138
+ const formatTimestamp = () => {
139
+ const now = new Date();
140
+ const h = String(now.getHours()).padStart(2, '0');
141
+ const m = String(now.getMinutes()).padStart(2, '0');
142
+ const s = String(now.getSeconds()).padStart(2, '0');
143
+ return `${h}:${m}:${s}`;
144
+ };
145
+ /**
146
+ * Core build pipeline. Throws on errors instead of calling process.exit,
147
+ * so callers can decide how to handle failures (exit in one-shot mode,
148
+ * continue watching in watch mode).
149
+ */
150
+ const runBuild = async (projectDir) => {
151
+ const startTime = performance.now();
152
+ // Step 1: Verify plugin project has package.json
153
+ const pkgJsonFile = Bun.file(join(projectDir, 'package.json'));
154
+ if (!(await pkgJsonFile.exists())) {
155
+ throw new Error('No valid package.json found in current directory. Run this command from a plugin directory.');
156
+ }
157
+ try {
158
+ JSON.parse(await pkgJsonFile.text());
159
+ }
160
+ catch {
161
+ throw new Error('No valid package.json found in current directory. Run this command from a plugin directory.');
162
+ }
163
+ // Determine entry point — look for compiled output in dist/
164
+ const entryPoint = resolve(projectDir, 'dist', 'index.js');
165
+ const sourceEntry = resolve(projectDir, 'src', 'index.ts');
166
+ if (!(await Bun.file(entryPoint).exists())) {
167
+ throw new Error(`Compiled entry point not found at ${entryPoint}. Run tsc first, then retry opentabs build.`);
168
+ }
169
+ // Step 2: Dynamically import the plugin module (cache-bust for watch mode rebuilds)
170
+ console.log(pc.dim('Loading plugin module...'));
171
+ const mod = (await import(`${entryPoint}?t=${String(Date.now())}`));
172
+ const defaultExport = mod.default;
173
+ if (!defaultExport) {
174
+ throw new Error('Plugin module must export a default instance of OpenTabsPlugin.');
175
+ }
176
+ const plugin = defaultExport;
177
+ // Step 3: Validate
178
+ console.log(pc.dim('Validating plugin...'));
179
+ const errors = validatePlugin(plugin);
180
+ if (errors.length > 0) {
181
+ throw new Error(`Validation failed:\n${errors.map(e => ` - ${e}`).join('\n')}`);
182
+ }
183
+ // Step 4: Bundle IIFE (before manifest, so adapterHash can be included)
184
+ console.log(pc.dim('Bundling adapter IIFE...'));
185
+ const distDir = join(projectDir, 'dist');
186
+ mkdirSync(distDir, { recursive: true });
187
+ await bundleIIFE(sourceEntry, distDir, plugin.name);
188
+ // Read the bundled IIFE and compute its SHA-256 hash. The hash is computed
189
+ // from the core IIFE content (before the __adapterHash setter is appended).
190
+ const iifePath = join(distDir, 'adapter.iife.js');
191
+ const iifeContent = await Bun.file(iifePath).text();
192
+ const adapterHash = new Bun.CryptoHasher('sha256').update(iifeContent).digest('hex');
193
+ // Append a self-contained snippet that exposes the hash on the adapter object
194
+ const hashSetter = `\n(function(){var o=(globalThis).__openTabs;if(o&&o.adapters&&o.adapters[${JSON.stringify(plugin.name)}])o.adapters[${JSON.stringify(plugin.name)}].__adapterHash=${JSON.stringify(adapterHash)};})();\n`;
195
+ await Bun.write(iifePath, iifeContent + hashSetter);
196
+ const iifeSize = (await Bun.file(iifePath).stat()).size;
197
+ console.log(` Written: ${pc.bold('dist/adapter.iife.js')} (${formatBytes(iifeSize)})`);
198
+ // Step 5: Generate manifest (includes adapterHash from the IIFE)
199
+ console.log(pc.dim('Generating manifest...'));
200
+ const manifest = generateManifest(plugin);
201
+ manifest.adapterHash = adapterHash;
202
+ const manifestPath = join(projectDir, 'opentabs-plugin.json');
203
+ await Bun.write(manifestPath, JSON.stringify(manifest, null, 2) + '\n');
204
+ console.log(` Written: ${pc.bold('opentabs-plugin.json')} (${manifest.tools.length} tool${manifest.tools.length === 1 ? '' : 's'})`);
205
+ const elapsed = ((performance.now() - startTime) / 1000).toFixed(1);
206
+ console.log('');
207
+ console.log(pc.green(`Build complete for plugin "${plugin.name}" v${plugin.version} in ${elapsed}s`));
208
+ };
209
+ const handleBuild = async (options) => {
210
+ const projectDir = process.cwd();
211
+ // Initial build — always runs
212
+ try {
213
+ await runBuild(projectDir);
214
+ }
215
+ catch (err) {
216
+ console.error(pc.red(`Error: ${err instanceof Error ? err.message : String(err)}`));
217
+ process.exit(1);
218
+ }
219
+ if (!options.watch)
220
+ return;
221
+ // Watch mode: watch dist/ for changes to .js files and rebuild
222
+ const distDir = join(projectDir, 'dist');
223
+ let debounceTimer = null;
224
+ let building = false;
225
+ const rebuild = async () => {
226
+ if (building)
227
+ return;
228
+ building = true;
229
+ console.log('');
230
+ console.log(pc.dim(`[${formatTimestamp()}] Change detected, rebuilding...`));
231
+ try {
232
+ await runBuild(projectDir);
233
+ }
234
+ catch (err) {
235
+ console.error(pc.red(`[${formatTimestamp()}] Rebuild failed: ${err instanceof Error ? err.message : String(err)}`));
236
+ }
237
+ building = false;
238
+ };
239
+ let watcher;
240
+ try {
241
+ watcher = watch(distDir, { recursive: true }, (_event, filename) => {
242
+ // Only react to .js file changes (tsc output), skip adapter.iife.js
243
+ // and temporary wrapper files to avoid rebuild loops
244
+ if (!filename ||
245
+ !filename.endsWith('.js') ||
246
+ filename === 'adapter.iife.js' ||
247
+ filename.startsWith('_adapter_entry_'))
248
+ return;
249
+ if (debounceTimer)
250
+ clearTimeout(debounceTimer);
251
+ debounceTimer = setTimeout(() => void rebuild(), DEBOUNCE_MS);
252
+ });
253
+ }
254
+ catch {
255
+ console.error(pc.red(`Error: Could not watch ${distDir}. Ensure the dist/ directory exists.`));
256
+ process.exit(1);
257
+ }
258
+ console.log('');
259
+ console.log(pc.cyan(`Watching ${pc.bold('dist/')} for changes... (Ctrl+C to stop)`));
260
+ const cleanup = () => {
261
+ if (debounceTimer)
262
+ clearTimeout(debounceTimer);
263
+ watcher.close();
264
+ console.log('');
265
+ console.log(pc.dim('Watcher stopped.'));
266
+ process.exit(0);
267
+ };
268
+ process.on('SIGINT', cleanup);
269
+ process.on('SIGTERM', cleanup);
270
+ // Keep the process alive
271
+ await new Promise(() => { });
272
+ };
273
+ const registerBuildCommand = (program) => {
274
+ program
275
+ .command('build')
276
+ .description('Build the current plugin directory (manifest + adapter IIFE)')
277
+ .option('-w, --watch', 'Watch dist/ for changes and rebuild automatically')
278
+ .addHelpText('after', `
279
+ Examples:
280
+ $ opentabs build
281
+ $ opentabs build --watch`)
282
+ .action((options) => handleBuild(options));
283
+ };
284
+ export { registerBuildCommand, validatePlugin };
285
+ //# sourceMappingURL=build.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"build.js","sourceRoot":"","sources":["../../src/commands/build.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,7 @@
1
+ /**
2
+ * `opentabs config` command — view and manage configuration.
3
+ */
4
+ import type { Command } from 'commander';
5
+ declare const registerConfigCommand: (program: Command) => void;
6
+ export { registerConfigCommand };
7
+ //# sourceMappingURL=config.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"config.d.ts","sourceRoot":"","sources":["../../src/commands/config.ts"],"names":[],"mappings":"AAAA;;GAEG;AAKH,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAwIzC,QAAA,MAAM,qBAAqB,GAAI,SAAS,OAAO,KAAG,IAwDjD,CAAC;AAEF,OAAO,EAAE,qBAAqB,EAAE,CAAC"}
@@ -0,0 +1,157 @@
1
+ /**
2
+ * `opentabs config` command — view and manage configuration.
3
+ */
4
+ import { getConfigDir, getConfigPath, readConfig } from '../config.js';
5
+ import pc from 'picocolors';
6
+ import { existsSync, mkdirSync } from 'node:fs';
7
+ const REDACTED = '***';
8
+ const redactSecret = (config) => {
9
+ if (typeof config.secret === 'string') {
10
+ return { ...config, secret: REDACTED };
11
+ }
12
+ return config;
13
+ };
14
+ const handleConfigPath = () => {
15
+ console.log(getConfigPath());
16
+ };
17
+ const handleConfigInit = async (options) => {
18
+ const configPath = getConfigPath();
19
+ if (existsSync(configPath) && !options.force) {
20
+ console.log(pc.yellow(`Config already exists at ${configPath}`));
21
+ console.log('Use --force to overwrite.');
22
+ return;
23
+ }
24
+ const configDir = getConfigDir();
25
+ mkdirSync(configDir, { recursive: true });
26
+ const config = { plugins: [], tools: {}, secret: crypto.randomUUID() };
27
+ await Bun.write(configPath, JSON.stringify(config, null, 2) + '\n');
28
+ console.log(pc.green(`Config created at ${configPath}`));
29
+ };
30
+ const handleConfigShow = async (options) => {
31
+ const configPath = getConfigPath();
32
+ const config = await readConfig(configPath);
33
+ if (!config) {
34
+ console.error(pc.red(`No config found at ${configPath}`));
35
+ console.error('Run opentabs dev to create one automatically.');
36
+ process.exit(1);
37
+ }
38
+ const redacted = redactSecret(config);
39
+ if (options.json) {
40
+ console.log(JSON.stringify(redacted, null, 2));
41
+ }
42
+ else {
43
+ console.log(pc.bold('OpenTabs Config'));
44
+ console.log(pc.dim(configPath));
45
+ console.log('');
46
+ for (const [key, value] of Object.entries(redacted)) {
47
+ if (key === 'plugins' && Array.isArray(value)) {
48
+ console.log(` ${pc.cyan('plugins')}`);
49
+ if (value.length === 0) {
50
+ console.log(` ${pc.dim('(none)')}`);
51
+ }
52
+ else {
53
+ for (const p of value) {
54
+ console.log(` - ${String(p)}`);
55
+ }
56
+ }
57
+ }
58
+ else if (key === 'tools' && typeof value === 'object' && value !== null) {
59
+ const entries = Object.entries(value);
60
+ console.log(` ${pc.cyan('tools')}`);
61
+ if (entries.length === 0) {
62
+ console.log(` ${pc.dim('(none)')}`);
63
+ }
64
+ else {
65
+ for (const [toolName, enabled] of entries) {
66
+ const indicator = enabled ? pc.green('enabled') : pc.red('disabled');
67
+ console.log(` ${toolName}: ${indicator}`);
68
+ }
69
+ }
70
+ }
71
+ else {
72
+ const display = typeof value === 'string' || typeof value === 'number' || typeof value === 'boolean'
73
+ ? String(value)
74
+ : JSON.stringify(value);
75
+ console.log(` ${pc.cyan(key)} ${display}`);
76
+ }
77
+ }
78
+ }
79
+ };
80
+ const TOOL_PREFIX = 'tool.';
81
+ const handleConfigSet = async (key, value) => {
82
+ if (!key.startsWith(TOOL_PREFIX)) {
83
+ console.error(pc.red(`Unknown config key: ${key}`));
84
+ console.error(`Supported keys: tool.<plugin>_<tool>`);
85
+ process.exit(1);
86
+ }
87
+ const toolName = key.slice(TOOL_PREFIX.length);
88
+ if (!toolName || !toolName.includes('_')) {
89
+ console.error(pc.red(`Invalid tool name: ${toolName || '(empty)'}`));
90
+ console.error('Tool names use the format <plugin>_<tool>, e.g. slack_send_message');
91
+ process.exit(1);
92
+ }
93
+ if (value !== 'enabled' && value !== 'disabled') {
94
+ console.error(pc.red(`Invalid value: ${value}`));
95
+ console.error('Value must be "enabled" or "disabled".');
96
+ process.exit(1);
97
+ }
98
+ const configPath = getConfigPath();
99
+ const config = await readConfig(configPath);
100
+ if (!config) {
101
+ console.error(pc.red(`No config found at ${configPath}`));
102
+ console.error('Run opentabs config init to create one.');
103
+ process.exit(1);
104
+ }
105
+ if (!config.tools || typeof config.tools !== 'object' || Array.isArray(config.tools)) {
106
+ config.tools = {};
107
+ }
108
+ const tools = config.tools;
109
+ const enabled = value === 'enabled';
110
+ tools[toolName] = enabled;
111
+ await Bun.write(configPath, JSON.stringify(config, null, 2) + '\n');
112
+ const indicator = enabled ? pc.green('enabled') : pc.red('disabled');
113
+ console.log(`${toolName}: ${indicator}`);
114
+ };
115
+ const registerConfigCommand = (program) => {
116
+ const configCmd = program
117
+ .command('config')
118
+ .description('View configuration details')
119
+ .action(() => {
120
+ configCmd.help();
121
+ });
122
+ configCmd
123
+ .command('init')
124
+ .description('Create config file with sensible defaults')
125
+ .option('--force', 'Overwrite existing config')
126
+ .addHelpText('after', `
127
+ Examples:
128
+ $ opentabs config init
129
+ $ opentabs config init --force`)
130
+ .action((options) => handleConfigInit(options));
131
+ configCmd
132
+ .command('set <key> <value>')
133
+ .description('Set a config value (e.g. tool.slack_send_message enabled)')
134
+ .addHelpText('after', `
135
+ Examples:
136
+ $ opentabs config set tool.slack_send_message disabled
137
+ $ opentabs config set tool.slack_send_message enabled`)
138
+ .action((key, value) => handleConfigSet(key, value));
139
+ configCmd
140
+ .command('path')
141
+ .description('Print the config file path')
142
+ .addHelpText('after', `
143
+ Examples:
144
+ $ opentabs config path`)
145
+ .action(() => handleConfigPath());
146
+ configCmd
147
+ .command('show')
148
+ .description('Show config contents (secret redacted)')
149
+ .option('--json', 'Output config as JSON')
150
+ .addHelpText('after', `
151
+ Examples:
152
+ $ opentabs config show
153
+ $ opentabs config show --json`)
154
+ .action((options) => handleConfigShow(options));
155
+ };
156
+ export { registerConfigCommand };
157
+ //# sourceMappingURL=config.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"config.js","sourceRoot":"","sources":["../../src/commands/config.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,10 @@
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
@@ -0,0 +1 @@
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"}