@ghl-ai/aw 0.1.50-beta.1 → 0.1.50

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.
@@ -1,254 +0,0 @@
1
- // commands/integrations.mjs — CLI command: aw integrations add/remove/list/bundle
2
-
3
- import * as p from '@clack/prompts';
4
- import * as fmt from '../fmt.mjs';
5
- import { chalk } from '../fmt.mjs';
6
- import {
7
- INTEGRATIONS,
8
- BUNDLES,
9
- installIntegration,
10
- removeIntegration,
11
- getInstalledList,
12
- } from '../integrations.mjs';
13
-
14
- export async function integrationsCommand(args) {
15
- const subcommand = args._positional[0];
16
-
17
- switch (subcommand) {
18
- case 'add':
19
- return cmdAdd(args);
20
- case 'remove':
21
- return cmdRemove(args);
22
- case 'bundle':
23
- return cmdBundle(args);
24
- case 'list':
25
- case undefined:
26
- return cmdList();
27
- default:
28
- fmt.cancel(`Unknown subcommand: ${subcommand}`);
29
- }
30
- }
31
-
32
- // ────────────────────────────────────────────────────────────────────────────────
33
- // aw integrations list
34
- // ────────────────────────────────────────────────────────────────────────────────
35
-
36
- async function cmdList() {
37
- fmt.banner('Integrations', {
38
- icon: '🔗',
39
- subtitle: ' Available tools and MCP servers',
40
- });
41
-
42
- const installed = getInstalledList();
43
-
44
- // Group by type
45
- const plugins = Object.entries(INTEGRATIONS).filter(
46
- ([, i]) => i.type === 'plugin'
47
- );
48
- const remoteRcps = Object.entries(INTEGRATIONS).filter(
49
- ([, i]) => i.type === 'remote-mcp'
50
- );
51
- const universalInstallers = Object.entries(INTEGRATIONS).filter(
52
- ([, i]) => i.type === 'universal-installer'
53
- );
54
- const pythonClis = Object.entries(INTEGRATIONS).filter(
55
- ([, i]) => i.type === 'python-cli'
56
- );
57
-
58
- const typeIcon = (type) =>
59
- type === 'plugin' ? '🔌' : type === 'remote-mcp' ? '🌐' : type === 'universal-installer' ? '🪨' : '⚙️';
60
-
61
- // Installed section
62
- if (installed.length > 0) {
63
- fmt.logMessage(`\n${chalk.bold.underline('Installed')}`);
64
- for (const key of installed) {
65
- const integration = INTEGRATIONS[key];
66
- if (!integration) continue;
67
- fmt.logSuccess(` ${typeIcon(integration.type)} ${integration.label}`);
68
- }
69
- }
70
-
71
- // Available Plugins
72
- fmt.logMessage(`\n${chalk.bold.underline('Available Plugins')}`);
73
- for (const [key, integration] of plugins) {
74
- if (!installed.includes(key)) {
75
- fmt.logMessage(
76
- ` 🔌 ${integration.label.padEnd(25)} — ${integration.description}`
77
- );
78
- }
79
- }
80
-
81
- // Available Remote MCPs
82
- fmt.logMessage(`\n${chalk.bold.underline('Available Remote MCPs')}`);
83
- for (const [key, integration] of remoteRcps) {
84
- if (!installed.includes(key)) {
85
- fmt.logMessage(
86
- ` 🌐 ${integration.label.padEnd(25)} — ${integration.description}`
87
- );
88
- }
89
- }
90
-
91
- // Universal Installers
92
- if (universalInstallers.length > 0) {
93
- fmt.logMessage(`\n${chalk.bold.underline('Universal Tools')}`);
94
- for (const [key, integration] of universalInstallers) {
95
- if (!installed.includes(key)) {
96
- fmt.logMessage(
97
- ` 🪨 ${integration.label.padEnd(25)} — ${integration.description}`
98
- );
99
- }
100
- }
101
- }
102
-
103
- // Python CLIs
104
- if (pythonClis.length > 0) {
105
- fmt.logMessage(`\n${chalk.bold.underline('Available Python Tools')}`);
106
- for (const [key, integration] of pythonClis) {
107
- if (!installed.includes(key)) {
108
- fmt.logMessage(
109
- ` 🐍 ${integration.label.padEnd(25)} — ${integration.description}`
110
- );
111
- }
112
- }
113
- }
114
-
115
- // Bundles
116
- fmt.logMessage(`\n${chalk.bold.underline('Bundles')}`);
117
- for (const [bundleKey, bundle] of Object.entries(BUNDLES)) {
118
- fmt.logMessage(
119
- ` 📦 ${bundle.label.padEnd(25)} — ${bundle.description}`
120
- );
121
- fmt.logMessage(
122
- ` Includes: ${bundle.includes.map((k) => INTEGRATIONS[k].label).join(', ')}`
123
- );
124
- }
125
-
126
- fmt.logMessage(`\n${chalk.dim('Commands:')}`);
127
- fmt.logMessage(` aw integrations add <key> Install a specific tool`);
128
- fmt.logMessage(` aw integrations remove <key> Remove a tool`);
129
- fmt.logMessage(` aw integrations bundle <name> Install a preset bundle`);
130
- }
131
-
132
- // ────────────────────────────────────────────────────────────────────────────────
133
- // aw integrations add <key>
134
- // ────────────────────────────────────────────────────────────────────────────────
135
-
136
- async function cmdAdd(args) {
137
- const key = args._positional[1];
138
-
139
- if (!key) {
140
- fmt.cancel('Usage: aw integrations add <key>');
141
- }
142
-
143
- if (!INTEGRATIONS[key]) {
144
- // Suggest similar keys
145
- const available = Object.keys(INTEGRATIONS);
146
- fmt.cancel(
147
- [
148
- `Unknown integration: ${chalk.red(key)}`,
149
- '',
150
- `Available: ${available.join(', ')}`,
151
- ].join('\n')
152
- );
153
- }
154
-
155
- const integration = INTEGRATIONS[key];
156
- fmt.intro(`Installing ${integration.label}`);
157
-
158
- const success = await installIntegration(key, { silent: false });
159
-
160
- if (success) {
161
- fmt.outro(`✓ ${integration.label} installed successfully`);
162
- } else {
163
- fmt.cancel(`Failed to install ${integration.label}`);
164
- }
165
- }
166
-
167
- // ────────────────────────────────────────────────────────────────────────────────
168
- // aw integrations remove <key>
169
- // ────────────────────────────────────────────────────────────────────────────────
170
-
171
- async function cmdRemove(args) {
172
- const key = args._positional[1];
173
-
174
- if (!key) {
175
- fmt.cancel('Usage: aw integrations remove <key>');
176
- }
177
-
178
- if (!INTEGRATIONS[key]) {
179
- const available = Object.keys(INTEGRATIONS);
180
- fmt.cancel(
181
- [
182
- `Unknown integration: ${chalk.red(key)}`,
183
- '',
184
- `Available: ${available.join(', ')}`,
185
- ].join('\n')
186
- );
187
- }
188
-
189
- const integration = INTEGRATIONS[key];
190
- fmt.intro(`Removing ${integration.label}`);
191
-
192
- const success = await removeIntegration(key, { silent: false });
193
-
194
- if (success) {
195
- fmt.outro(`✓ ${integration.label} removed successfully`);
196
- } else {
197
- fmt.cancel(`Failed to remove ${integration.label}`);
198
- }
199
- }
200
-
201
- // ────────────────────────────────────────────────────────────────────────────────
202
- // aw integrations bundle <bundleName>
203
- // ────────────────────────────────────────────────────────────────────────────────
204
-
205
- async function cmdBundle(args) {
206
- const bundleName = args._positional[1];
207
-
208
- if (!bundleName) {
209
- fmt.cancel('Usage: aw integrations bundle <name>');
210
- }
211
-
212
- if (!BUNDLES[bundleName]) {
213
- const available = Object.keys(BUNDLES);
214
- fmt.cancel(
215
- [
216
- `Unknown bundle: ${chalk.red(bundleName)}`,
217
- '',
218
- `Available: ${available.join(', ')}`,
219
- ].join('\n')
220
- );
221
- }
222
-
223
- const bundle = BUNDLES[bundleName];
224
- fmt.intro(`Installing bundle: ${bundle.label}`);
225
-
226
- fmt.logMessage(`${bundle.description}\n`);
227
- fmt.logMessage(`Includes:`);
228
- for (const key of bundle.includes) {
229
- const integration = INTEGRATIONS[key];
230
- fmt.logMessage(` • ${integration.label}`);
231
- }
232
-
233
- const confirm = await p.default.confirm({
234
- message: `Continue installing ${bundle.includes.length} tool(s)?`,
235
- initialValue: true,
236
- });
237
-
238
- if (p.default.isCancel(confirm) || !confirm) {
239
- fmt.cancel('Cancelled');
240
- }
241
-
242
- fmt.logMessage('');
243
-
244
- // Install all
245
- let successCount = 0;
246
- for (const key of bundle.includes) {
247
- const success = await installIntegration(key, { silent: false });
248
- if (success) successCount++;
249
- }
250
-
251
- fmt.outro(
252
- `✓ Bundle installation complete (${successCount}/${bundle.includes.length} installed)`
253
- );
254
- }
package/commands/mcp.mjs DELETED
@@ -1,90 +0,0 @@
1
- import { homedir } from 'node:os';
2
-
3
- import * as fmt from '../fmt.mjs';
4
- import { chalk } from '../fmt.mjs';
5
- import {
6
- getMcpStatus,
7
- removeMcpConfig,
8
- saveMcpPreferences,
9
- setupMcp,
10
- } from '../mcp.mjs';
11
-
12
- const HOME = homedir();
13
-
14
- function isTruthyEnv(value) {
15
- return ['1', 'true', 'yes', 'on'].includes(String(value || '').trim().toLowerCase());
16
- }
17
-
18
- export async function mcpCommand(args) {
19
- const action = String(args._positional?.[0] || 'status').toLowerCase();
20
-
21
- if (!['status', 'enable', 'disable'].includes(action)) {
22
- fmt.cancel(`Unknown MCP action: ${action}. Use: aw mcp status|enable|disable`);
23
- return;
24
- }
25
-
26
- fmt.intro(`aw mcp ${action}`);
27
-
28
- if (action === 'status') {
29
- return renderStatus();
30
- }
31
-
32
- if (action === 'disable') {
33
- saveMcpPreferences('disabled', HOME);
34
- const removed = removeMcpConfig();
35
- const status = getMcpStatus(HOME);
36
- fmt.outro([
37
- '⟁ MCP disabled',
38
- '',
39
- ` ${chalk.green('✓')} Preference saved: ${chalk.dim(status.preferencesPath.replace(`${HOME}/`, '~/'))}`,
40
- ` ${chalk.green('✓')} Removed AW-managed MCP server from ${removed} config file${removed === 1 ? '' : 's'}`,
41
- ].join('\n'));
42
- return;
43
- }
44
-
45
- saveMcpPreferences('enabled', HOME);
46
- const silent = !!args['--silent'] || isTruthyEnv(process.env.CI);
47
- const updatedFiles = await setupMcp(HOME, null, { silent });
48
- const status = getMcpStatus(HOME);
49
- if (status.effectiveMode === 'disabled') {
50
- fmt.outro([
51
- '⟁ MCP preference enabled',
52
- '',
53
- ` ${chalk.green('✓')} Preference saved: ${chalk.dim(status.preferencesPath.replace(`${HOME}/`, '~/'))}`,
54
- ` ${chalk.yellow('!')} ${status.envDisableMcpName}=1 override is still active`,
55
- ].join('\n'));
56
- return;
57
- }
58
- fmt.outro([
59
- '⟁ MCP enabled',
60
- '',
61
- ` ${chalk.green('✓')} Preference saved: ${chalk.dim(status.preferencesPath.replace(`${HOME}/`, '~/'))}`,
62
- updatedFiles.length > 0
63
- ? ` ${chalk.green('✓')} Updated ${updatedFiles.length} MCP config file${updatedFiles.length === 1 ? '' : 's'}`
64
- : ` ${chalk.dim('Note:')} MCP config files already up to date`,
65
- ].join('\n'));
66
- }
67
-
68
- function renderStatus() {
69
- const status = getMcpStatus(HOME);
70
- const modeLabel = status.envDisableMcp
71
- ? `${status.effectiveMode} (${status.envDisableMcpName}=1 override; saved preference: ${status.mode})`
72
- : status.mode;
73
-
74
- fmt.note([
75
- `${chalk.dim('mode:')} ${modeLabel}`,
76
- `${chalk.dim('prefs:')} ${status.preferencesPath.replace(`${HOME}/`, '~/')}`,
77
- `${chalk.dim('claude MCP:')} ${formatHealth(status.claude)}`,
78
- `${chalk.dim('cursor MCP:')} ${formatHealth(status.cursor)}`,
79
- `${chalk.dim('codex MCP:')} ${formatHealth(status.codex)}`,
80
- `${chalk.dim('aw-ecc Codex MCP source:')} ${formatHealth(status.eccCodex)}`,
81
- ].join('\n'), 'MCP');
82
-
83
- fmt.outro('⟁ MCP status complete');
84
- }
85
-
86
- function formatHealth(health) {
87
- if (!health.present) return 'disabled';
88
- if (health.url && health.authorization) return 'enabled';
89
- return `incomplete (url=${health.url}, authorization=${health.authorization})`;
90
- }