aui-agent-builder 0.1.8 → 0.1.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/README.md CHANGED
@@ -71,9 +71,10 @@ Session is invalidated server-side and cleared locally.
71
71
  |---------|-------------|
72
72
  | `aui login` | Sign in (email OTP or access token) |
73
73
  | `aui list-agents` | List all agents in your account |
74
- | `aui create-agent` | Create a new agent on the backend |
75
74
  | `aui import [agent-id]` | Download an agent as local `.aui.json` files |
76
75
  | `aui init [directory]` | Scaffold a new agent project with examples |
76
+ | `aui add-integration` | Add an integration (API, RAG, or MCP) |
77
+ | `aui rag` | List and manage RAG knowledge bases and files |
77
78
  | `aui validate [path]` | Validate `.aui.json` files for errors |
78
79
  | `aui push` | Upload local changes to the backend |
79
80
  | `aui status` | Show session, linked agent, and file summary |
@@ -160,6 +161,31 @@ my-agent/
160
161
 
161
162
  **`rules.aui.json`** — Global rules that apply across tools. Define conditions (when) and actions (then) to control agent behavior like blocking certain actions, requiring confirmation, or activating other tools.
162
163
 
164
+ ## Adding Integrations
165
+
166
+ Add API, RAG, or MCP integrations to your project:
167
+
168
+ ```bash
169
+ aui add-integration
170
+ ```
171
+
172
+ Select the integration type, provide a code name, and the command scaffolds the JSON config with the correct structure and placeholder values. Edit the generated `integrations.aui.json` in your editor to fill in the details.
173
+
174
+ - **API** — generates endpoint URL, method, authentication, request schema, and test curl
175
+ - **RAG** — prompts for knowledge hub (new or existing) and scope (organization, account, or network)
176
+ - **MCP** — generates a minimal config to fill in
177
+
178
+ ## RAG Knowledge Bases
179
+
180
+ Manage RAG knowledge bases and their files:
181
+
182
+ ```bash
183
+ aui rag # List knowledge bases and files by scope
184
+ aui rag --add-file # Add a file or URL to a knowledge hub
185
+ ```
186
+
187
+ After adding a RAG integration, use `aui rag --add-file` to attach local files (PDF, TXT, etc.) or URLs for scraping. Files are tracked locally and will be uploaded when push endpoints are ready. On push, only changed files are re-embedded (diff-based).
188
+
163
189
  ## Validating Changes
164
190
 
165
191
  Check your configuration files for errors before pushing:
@@ -1,26 +1,20 @@
1
1
  /**
2
- * add-integration command - Import integrations from OpenAPI specs or manually
2
+ * add-integration command - Scaffold integration config files
3
3
  *
4
- * Interactive flow:
5
- * 1. Choose source: URL, JSON file, or manual entry
6
- * 2. For OpenAPI: fetch, parse, select endpoints
7
- * 3. For each endpoint: collect curl for testing
8
- * 4. Generate integration configuration
9
- * 5. Save to integrations.aui.json
4
+ * Asks only the essentials (type, code, scope for RAG), then generates
5
+ * the .aui.json file with the correct structure and placeholder values
6
+ * for the user to edit in their editor.
7
+ *
8
+ * For RAG, also supports adding files/URLs to the knowledge hub.
10
9
  *
11
10
  * Usage: aui add-integration
12
- * Options:
13
- * --url <url> URL to OpenAPI spec
14
- * --file <path> Path to OpenAPI JSON file
15
- * --manual Manual integration entry
16
11
  */
17
12
  export interface AddIntegrationOptions {
18
13
  url?: string;
19
14
  file?: string;
20
- manual?: boolean;
21
15
  }
22
16
  /**
23
- * Main add-integration command
17
+ * Scaffold an integration config file
24
18
  */
25
- export declare function addIntegration(options?: AddIntegrationOptions): Promise<void>;
19
+ export declare function addIntegration(_options?: AddIntegrationOptions): Promise<void>;
26
20
  //# sourceMappingURL=add-integration.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"add-integration.d.ts","sourceRoot":"","sources":["../../src/commands/add-integration.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;GAeG;AAUH,MAAM,WAAW,qBAAqB;IACpC,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,MAAM,CAAC,EAAE,OAAO,CAAC;CAClB;AAED;;GAEG;AACH,wBAAsB,cAAc,CAAC,OAAO,GAAE,qBAA0B,GAAG,OAAO,CAAC,IAAI,CAAC,CA4DvF"}
1
+ {"version":3,"file":"add-integration.d.ts","sourceRoot":"","sources":["../../src/commands/add-integration.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AASH,MAAM,WAAW,qBAAqB;IACpC,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,IAAI,CAAC,EAAE,MAAM,CAAC;CACf;AAED;;GAEG;AACH,wBAAsB,cAAc,CAAC,QAAQ,GAAE,qBAA0B,GAAG,OAAO,CAAC,IAAI,CAAC,CAuDxF"}
@@ -1,19 +1,14 @@
1
1
  "use strict";
2
2
  /**
3
- * add-integration command - Import integrations from OpenAPI specs or manually
3
+ * add-integration command - Scaffold integration config files
4
4
  *
5
- * Interactive flow:
6
- * 1. Choose source: URL, JSON file, or manual entry
7
- * 2. For OpenAPI: fetch, parse, select endpoints
8
- * 3. For each endpoint: collect curl for testing
9
- * 4. Generate integration configuration
10
- * 5. Save to integrations.aui.json
5
+ * Asks only the essentials (type, code, scope for RAG), then generates
6
+ * the .aui.json file with the correct structure and placeholder values
7
+ * for the user to edit in their editor.
8
+ *
9
+ * For RAG, also supports adding files/URLs to the knowledge hub.
11
10
  *
12
11
  * Usage: aui add-integration
13
- * Options:
14
- * --url <url> URL to OpenAPI spec
15
- * --file <path> Path to OpenAPI JSON file
16
- * --manual Manual integration entry
17
12
  */
18
13
  var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
19
14
  if (k2 === undefined) k2 = k;
@@ -56,381 +51,173 @@ exports.addIntegration = addIntegration;
56
51
  const fs = __importStar(require("fs"));
57
52
  const path = __importStar(require("path"));
58
53
  const chalk_1 = __importDefault(require("chalk"));
59
- const ora_1 = __importDefault(require("ora"));
60
54
  const inquirer_1 = __importDefault(require("inquirer"));
61
55
  const config_1 = require("../config");
62
56
  /**
63
- * Main add-integration command
57
+ * Scaffold an integration config file
64
58
  */
65
- async function addIntegration(options = {}) {
66
- console.log(chalk_1.default.blue('\n ┌─────────────────────────────────────────┐'));
67
- console.log(chalk_1.default.blue(' │ Add Integration to Agent │'));
68
- console.log(chalk_1.default.blue(' └─────────────────────────────────────────┘\n'));
69
- const projectRoot = (0, config_1.findProjectRoot)();
70
- if (!projectRoot) {
71
- console.log(chalk_1.default.yellow(' Note: No AUI project found. Integration will be saved to current directory.'));
72
- }
73
- try {
74
- // Choose source type
75
- const { sourceType } = await inquirer_1.default.prompt([{
76
- type: 'list',
77
- name: 'sourceType',
78
- message: 'How would you like to add the integration?',
79
- choices: [
80
- { name: 'Manual entry - Define integration fields step by step', value: 'manual' },
81
- { name: 'OpenAPI URL - Import from OpenAPI spec URL', value: 'url' },
82
- { name: 'OpenAPI File - Import from local OpenAPI JSON file', value: 'file' }
83
- ]
84
- }]);
85
- let integration;
86
- if (sourceType === 'manual') {
87
- integration = await createManualIntegration();
88
- }
89
- else if (sourceType === 'url') {
90
- integration = await createFromOpenAPIUrl(options.url);
91
- }
92
- else {
93
- integration = await createFromOpenAPIFile(options.file);
94
- }
95
- // Preview
96
- console.log(chalk_1.default.blue('\n ─── Integration Preview ───\n'));
97
- console.log(chalk_1.default.white(` Type: ${integration.type}`));
98
- console.log(chalk_1.default.white(` Code: ${integration.code}`));
99
- if (integration.settings && 'endpoint' in integration.settings && integration.settings.endpoint) {
100
- console.log(chalk_1.default.white(` Endpoint: ${integration.settings.endpoint.method} ${integration.settings.endpoint.url}`));
101
- }
102
- // Confirm and save
103
- const { confirm } = await inquirer_1.default.prompt([{
104
- type: 'confirm',
105
- name: 'confirm',
106
- message: 'Add this integration to your project?',
107
- default: true
108
- }]);
109
- if (!confirm) {
110
- console.log(chalk_1.default.gray('\n Cancelled.\n'));
111
- return;
112
- }
113
- await saveIntegration(integration, projectRoot);
114
- console.log(chalk_1.default.green(`\n ✓ Integration "${integration.code}" added successfully!\n`));
115
- }
116
- catch (error) {
117
- console.error(chalk_1.default.red(`\n Error: ${error instanceof Error ? error.message : error}`));
118
- }
119
- }
120
- /**
121
- * Create integration manually step by step
122
- */
123
- async function createManualIntegration() {
124
- const answers = await inquirer_1.default.prompt([
125
- {
59
+ async function addIntegration(_options = {}) {
60
+ console.log(chalk_1.default.dim('\n ╭──────────────────────────────────────────────╮'));
61
+ console.log(chalk_1.default.dim(' │') + chalk_1.default.white.bold(' Add Integration') + chalk_1.default.dim(' │'));
62
+ console.log(chalk_1.default.dim(' ╰──────────────────────────────────────────────╯\n'));
63
+ const projectRoot = (0, config_1.findProjectRoot)() || process.cwd();
64
+ // Step 1: Integration type
65
+ const { integrationType } = await inquirer_1.default.prompt([{
126
66
  type: 'list',
127
- name: 'type',
67
+ name: 'integrationType',
128
68
  message: 'Integration type:',
129
69
  choices: [
130
- { name: 'API - REST API endpoint', value: 'API' },
131
- { name: 'RAG - Knowledge base retrieval', value: 'RAG' },
132
- { name: 'MCP - Model Context Protocol', value: 'MCP' }
70
+ { name: 'API REST API endpoint', value: 'API' },
71
+ { name: 'RAG Knowledge base (files / URLs)', value: 'RAG' },
72
+ { name: 'MCP Model Context Protocol', value: 'MCP' }
133
73
  ]
134
- },
135
- {
74
+ }]);
75
+ // Step 2: Code
76
+ const { code } = await inquirer_1.default.prompt([{
136
77
  type: 'input',
137
78
  name: 'code',
138
79
  message: 'Integration code (kebab-case):',
139
80
  validate: (input) => /^[a-z][a-z0-9-]*$/.test(input) || 'Use lowercase letters, numbers, and hyphens'
140
- },
141
- {
142
- type: 'input',
143
- name: 'description',
144
- message: 'Description (optional):'
145
- }
146
- ]);
147
- if (answers.type === 'API') {
148
- return await createAPIIntegration(answers.code, answers.description);
81
+ }]);
82
+ // Step 3: Build the integration based on type
83
+ let integration;
84
+ if (integrationType === 'API') {
85
+ integration = scaffoldAPI(code);
86
+ }
87
+ else if (integrationType === 'RAG') {
88
+ integration = await scaffoldRAG(code);
89
+ }
90
+ else {
91
+ integration = scaffoldMCP(code);
149
92
  }
150
- if (answers.type === 'RAG') {
151
- return await createRAGIntegration(answers.code, answers.description);
93
+ // Step 4: Save to integrations.aui.json
94
+ await saveIntegration(integration, projectRoot);
95
+ const filePath = path.join(projectRoot, 'integrations.aui.json');
96
+ console.log(chalk_1.default.green(`\n ✓ ${integrationType} integration "${code}" created`));
97
+ console.log(chalk_1.default.dim(`\n Edit the configuration:`));
98
+ console.log(chalk_1.default.cyan(` ${filePath}`));
99
+ if (integrationType === 'RAG') {
100
+ console.log(chalk_1.default.dim(`\n Add files to the knowledge hub:`));
101
+ console.log(chalk_1.default.cyan(` aui rag --add-file`));
152
102
  }
153
- // MCP or other
103
+ console.log(chalk_1.default.dim(`\n Then validate and push:`));
104
+ console.log(chalk_1.default.cyan(` aui validate`));
105
+ console.log(chalk_1.default.cyan(` aui push\n`));
106
+ }
107
+ // ─── Scaffolders ───
108
+ function scaffoldAPI(code) {
154
109
  return {
155
- type: answers.type,
156
- code: answers.code,
157
- description: answers.description || undefined,
158
- settings: undefined
110
+ type: 'API',
111
+ code,
112
+ description: '',
113
+ settings: {
114
+ endpoint: {
115
+ url: 'https://api.example.com/endpoint',
116
+ method: 'GET',
117
+ authentication: {
118
+ type: 'API_KEY',
119
+ apiKey: `$${code.toUpperCase().replace(/-/g, '_')}_API_KEY`
120
+ }
121
+ },
122
+ request_schema: [
123
+ {
124
+ key: 'query',
125
+ required: true,
126
+ description: 'Search query or input parameter',
127
+ type: 'STRING',
128
+ value_source: 'dynamic',
129
+ params: [],
130
+ entities: [],
131
+ values: [],
132
+ default_value: ''
133
+ }
134
+ ],
135
+ response_mapping: {},
136
+ test_curl: `curl "https://api.example.com/endpoint?query=test" -H "X-API-Key: YOUR_KEY"`
137
+ }
159
138
  };
160
139
  }
161
- /**
162
- * Create an API integration with endpoint details
163
- */
164
- async function createAPIIntegration(code, description) {
165
- const endpointAnswers = await inquirer_1.default.prompt([
166
- {
167
- type: 'input',
168
- name: 'url',
169
- message: 'Endpoint URL (supports {{param}} placeholders):',
170
- validate: (input) => input.length > 0 || 'URL is required'
171
- },
172
- {
173
- type: 'list',
174
- name: 'method',
175
- message: 'HTTP Method:',
176
- choices: ['GET', 'POST', 'PUT', 'PATCH', 'DELETE']
177
- },
178
- {
140
+ async function scaffoldRAG(code) {
141
+ // RAG needs a few extra questions for the knowledge hub
142
+ const { khSource } = await inquirer_1.default.prompt([{
179
143
  type: 'list',
180
- name: 'authType',
181
- message: 'Authentication:',
144
+ name: 'khSource',
145
+ message: 'Knowledge hub:',
182
146
  choices: [
183
- { name: 'None', value: 'NONE' },
184
- { name: 'API Key', value: 'API_KEY' },
185
- { name: 'Bearer Token', value: 'BEARER_TOKEN' },
186
- { name: 'Basic Auth', value: 'BASIC' }
147
+ { name: 'Create a new knowledge hub', value: 'new' },
148
+ { name: 'Use an existing knowledge hub (enter ID)', value: 'existing' }
187
149
  ]
188
- }
189
- ]);
190
- const endpoint = {
191
- url: endpointAnswers.url,
192
- method: endpointAnswers.method,
193
- };
194
- if (endpointAnswers.authType !== 'NONE') {
195
- if (endpointAnswers.authType === 'API_KEY') {
196
- const { envVar } = await inquirer_1.default.prompt([{
197
- type: 'input',
198
- name: 'envVar',
199
- message: 'Environment variable name for API key:',
200
- default: `${code.toUpperCase().replace(/-/g, '_')}_API_KEY`
201
- }]);
202
- endpoint.authentication = { type: 'API_KEY', apiKey: `$${envVar}` };
203
- }
204
- else if (endpointAnswers.authType === 'BEARER_TOKEN') {
205
- const { envVar } = await inquirer_1.default.prompt([{
206
- type: 'input',
207
- name: 'envVar',
208
- message: 'Environment variable name for token:',
209
- default: `${code.toUpperCase().replace(/-/g, '_')}_TOKEN`
210
- }]);
211
- endpoint.authentication = { type: 'BEARER_TOKEN', token: `$${envVar}` };
212
- }
213
- }
214
- // Request schema fields
215
- const requestSchema = [];
216
- let addMore = true;
217
- console.log(chalk_1.default.gray('\n Define request schema fields (the data this API needs):\n'));
218
- while (addMore) {
219
- const { wantField } = await inquirer_1.default.prompt([{
220
- type: 'confirm',
221
- name: 'wantField',
222
- message: requestSchema.length === 0 ? 'Add a request field?' : 'Add another request field?',
223
- default: requestSchema.length === 0
224
- }]);
225
- if (!wantField) {
226
- addMore = false;
227
- continue;
228
- }
229
- const fieldAnswers = await inquirer_1.default.prompt([
230
- {
150
+ }]);
151
+ let knowledgeHub;
152
+ let knowledgeBaseId = '';
153
+ if (khSource === 'existing') {
154
+ const { id } = await inquirer_1.default.prompt([{
231
155
  type: 'input',
232
- name: 'key',
233
- message: 'Field name:',
234
- validate: (input) => input.length > 0 || 'Field name is required'
235
- },
236
- {
237
- type: 'confirm',
238
- name: 'required',
239
- message: 'Required?',
240
- default: true
241
- },
156
+ name: 'id',
157
+ message: 'Knowledge hub ID:',
158
+ validate: (input) => input.trim().length > 0 || 'ID is required'
159
+ }]);
160
+ knowledgeBaseId = id.trim();
161
+ knowledgeHub = { id: knowledgeBaseId, name: '', scope: 'organization' };
162
+ }
163
+ else {
164
+ const khAnswers = await inquirer_1.default.prompt([
242
165
  {
243
166
  type: 'input',
244
- name: 'description',
245
- message: 'Description:'
167
+ name: 'name',
168
+ message: 'Knowledge hub name:',
169
+ validate: (input) => input.trim().length > 0 || 'Name is required'
246
170
  },
247
171
  {
248
172
  type: 'list',
249
- name: 'type',
250
- message: 'Type:',
251
- choices: ['STRING', 'NUMBER', 'BOOLEAN', 'ENUM', 'OBJECT', 'ARRAY']
252
- },
253
- {
254
- type: 'list',
255
- name: 'valueSource',
256
- message: 'Value source:',
173
+ name: 'scope',
174
+ message: 'Scope:',
257
175
  choices: [
258
- { name: 'Dynamic - LLM determines value', value: 'dynamic' },
259
- { name: 'Default - Fixed value', value: 'default' },
260
- { name: 'User Profile - From user context', value: 'user_profile' },
261
- { name: 'Context - From conversation context', value: 'context' },
262
- { name: 'Entities - From entity data', value: 'entities' }
176
+ { name: 'Organization shared across all accounts and agents', value: 'organization' },
177
+ { name: 'Account shared within this account', value: 'account' },
178
+ { name: 'Network specific to this agent only', value: 'network' }
263
179
  ]
264
180
  }
265
181
  ]);
266
- requestSchema.push({
267
- key: fieldAnswers.key,
268
- required: fieldAnswers.required,
269
- description: fieldAnswers.description,
270
- type: fieldAnswers.type,
271
- value_source: fieldAnswers.valueSource,
272
- params: [],
273
- entities: [],
274
- values: [],
275
- default_value: ''
276
- });
182
+ knowledgeHub = {
183
+ name: khAnswers.name.trim(),
184
+ scope: khAnswers.scope,
185
+ files: []
186
+ };
187
+ // TODO: When knowledge hub creation endpoint is ready:
188
+ // POST /knowledge-hub with { name, scope }
189
+ // Response includes the knowledge_base_id
190
+ knowledgeBaseId = `kh-${code}-pending`;
277
191
  }
278
- // Test curl
279
- const { testCurl } = await inquirer_1.default.prompt([{
280
- type: 'input',
281
- name: 'testCurl',
282
- message: 'Test curl command (optional - used to generate response mapping):'
283
- }]);
284
- return {
285
- type: 'API',
286
- code,
287
- description: description || undefined,
288
- settings: {
289
- endpoint,
290
- request_schema: requestSchema,
291
- response_mapping: {},
292
- test_curl: testCurl || undefined
293
- }
294
- };
295
- }
296
- /**
297
- * Create a RAG integration
298
- */
299
- async function createRAGIntegration(code, description) {
300
- const answers = await inquirer_1.default.prompt([
301
- {
302
- type: 'input',
303
- name: 'knowledgeBaseId',
304
- message: 'Knowledge base ID:',
305
- validate: (input) => input.length > 0 || 'Knowledge base ID is required'
306
- },
307
- {
308
- type: 'number',
309
- name: 'searchTopK',
310
- message: 'Search top-k results:',
311
- default: 7
312
- },
313
- {
314
- type: 'number',
315
- name: 'rankerTopK',
316
- message: 'Ranker top-k results:',
317
- default: 3
318
- },
319
- {
320
- type: 'number',
321
- name: 'confidenceThreshold',
322
- message: 'Confidence threshold (0-1):',
323
- default: 0.3
324
- }
325
- ]);
326
192
  return {
327
193
  type: 'RAG',
328
194
  code,
329
- description: description || undefined,
195
+ description: '',
330
196
  settings: {
331
- search_top_k: answers.searchTopK,
332
- ranker_top_k: answers.rankerTopK,
197
+ search_top_k: 7,
198
+ ranker_top_k: 3,
333
199
  ranker_model: null,
334
- confidence_threshold: answers.confidenceThreshold,
335
- knowledge_base_id: answers.knowledgeBaseId,
200
+ confidence_threshold: 0.3,
201
+ knowledge_base_id: knowledgeBaseId,
336
202
  parent_knowledge_base_ids: [],
337
203
  allow_multiple_calls: false,
338
- placeholders: []
204
+ placeholders: [],
205
+ knowledge_hub: knowledgeHub
339
206
  }
340
207
  };
341
208
  }
342
- /**
343
- * Create integration from OpenAPI URL
344
- */
345
- async function createFromOpenAPIUrl(url) {
346
- if (!url) {
347
- const answers = await inquirer_1.default.prompt([{
348
- type: 'input',
349
- name: 'url',
350
- message: 'OpenAPI spec URL:',
351
- validate: (input) => {
352
- if (!input.startsWith('http://') && !input.startsWith('https://')) {
353
- return 'URL must start with http:// or https://';
354
- }
355
- return true;
356
- }
357
- }]);
358
- url = answers.url;
359
- }
360
- const spinner = (0, ora_1.default)('Fetching OpenAPI spec...').start();
361
- try {
362
- // Note: In production, this would fetch and parse the OpenAPI spec
363
- // For now, we create a placeholder integration
364
- spinner.succeed('OpenAPI spec loaded');
365
- console.log(chalk_1.default.yellow('\n OpenAPI import is a work in progress.'));
366
- console.log(chalk_1.default.yellow(' Creating a placeholder integration from the URL.\n'));
367
- const { code } = await inquirer_1.default.prompt([{
368
- type: 'input',
369
- name: 'code',
370
- message: 'Integration code:',
371
- validate: (input) => /^[a-z][a-z0-9-]*$/.test(input) || 'Use kebab-case'
372
- }]);
373
- return {
374
- type: 'API',
375
- code,
376
- settings: {
377
- endpoint: {
378
- url: url,
379
- method: 'GET'
380
- },
381
- request_schema: [],
382
- response_mapping: {}
383
- }
384
- };
385
- }
386
- catch (error) {
387
- spinner.fail('Failed to fetch OpenAPI spec');
388
- throw error;
389
- }
390
- }
391
- /**
392
- * Create integration from OpenAPI file
393
- */
394
- async function createFromOpenAPIFile(filePath) {
395
- if (!filePath) {
396
- const answers = await inquirer_1.default.prompt([{
397
- type: 'input',
398
- name: 'filePath',
399
- message: 'Path to OpenAPI JSON file:',
400
- validate: (input) => {
401
- if (!fs.existsSync(input))
402
- return `File not found: ${input}`;
403
- return true;
404
- }
405
- }]);
406
- filePath = answers.filePath;
407
- }
408
- console.log(chalk_1.default.yellow('\n OpenAPI file import is a work in progress.'));
409
- console.log(chalk_1.default.yellow(' Creating a placeholder integration.\n'));
410
- const { code } = await inquirer_1.default.prompt([{
411
- type: 'input',
412
- name: 'code',
413
- message: 'Integration code:',
414
- validate: (input) => /^[a-z][a-z0-9-]*$/.test(input) || 'Use kebab-case'
415
- }]);
209
+ function scaffoldMCP(code) {
416
210
  return {
417
- type: 'API',
211
+ type: 'MCP',
418
212
  code,
419
- settings: {
420
- endpoint: null,
421
- request_schema: [],
422
- response_mapping: {}
423
- }
213
+ description: '',
214
+ settings: undefined
424
215
  };
425
216
  }
426
- /**
427
- * Save integration to integrations.aui.json
428
- */
217
+ // ─── Save ───
429
218
  async function saveIntegration(integration, projectRoot) {
430
- const targetDir = projectRoot || process.cwd();
431
- const integrationsPath = path.join(targetDir, 'integrations.aui.json');
219
+ const integrationsPath = path.join(projectRoot, 'integrations.aui.json');
432
220
  let existingIntegrations = [];
433
- // Load existing file
434
221
  if (fs.existsSync(integrationsPath)) {
435
222
  try {
436
223
  const content = fs.readFileSync(integrationsPath, 'utf-8');
@@ -438,7 +225,7 @@ async function saveIntegration(integration, projectRoot) {
438
225
  existingIntegrations = parsed.integrations || [];
439
226
  }
440
227
  catch {
441
- // File exists but couldn't be parsed
228
+ // Start fresh if file is invalid
442
229
  }
443
230
  }
444
231
  // Check for duplicate
@@ -447,38 +234,21 @@ async function saveIntegration(integration, projectRoot) {
447
234
  const { action } = await inquirer_1.default.prompt([{
448
235
  type: 'list',
449
236
  name: 'action',
450
- message: `Integration "${integration.code}" already exists. What would you like to do?`,
237
+ message: `Integration "${integration.code}" already exists.`,
451
238
  choices: [
452
- { name: 'Replace existing', value: 'replace' },
453
- { name: 'Rename new integration', value: 'rename' },
239
+ { name: 'Replace it', value: 'replace' },
454
240
  { name: 'Cancel', value: 'cancel' }
455
241
  ]
456
242
  }]);
457
243
  if (action === 'cancel') {
458
- throw new Error('Cancelled by user');
459
- }
460
- if (action === 'replace') {
461
- existingIntegrations[existingIdx] = integration;
462
- }
463
- else {
464
- const { newCode } = await inquirer_1.default.prompt([{
465
- type: 'input',
466
- name: 'newCode',
467
- message: 'New integration code:',
468
- validate: (input) => /^[a-z][a-z0-9-]*$/.test(input) || 'Use kebab-case'
469
- }]);
470
- integration.code = newCode;
471
- existingIntegrations.push(integration);
244
+ console.log(chalk_1.default.gray('\n Cancelled.\n'));
245
+ return;
472
246
  }
247
+ existingIntegrations[existingIdx] = integration;
473
248
  }
474
249
  else {
475
250
  existingIntegrations.push(integration);
476
251
  }
477
- // Save
478
- const fileContent = {
479
- integrations: existingIntegrations
480
- };
481
- fs.writeFileSync(integrationsPath, JSON.stringify(fileContent, null, 2) + '\n');
482
- console.log(chalk_1.default.gray(` Saved to: ${integrationsPath}`));
252
+ fs.writeFileSync(integrationsPath, JSON.stringify({ integrations: existingIntegrations }, null, 2) + '\n');
483
253
  }
484
254
  //# sourceMappingURL=add-integration.js.map