intentiai 0.1.0

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.
@@ -0,0 +1,164 @@
1
+ const inquirer = require('inquirer');
2
+ const chalk = require('chalk');
3
+ const ora = require('ora');
4
+ const Table = require('cli-table3');
5
+ const fs = require('fs');
6
+ const path = require('path');
7
+ const FormData = require('form-data');
8
+ const api = require('../lib/api');
9
+ const config = require('../lib/config');
10
+
11
+ function requireProject() {
12
+ const projectKey = config.getCurrentProject();
13
+ if (!projectKey) {
14
+ console.error(chalk.red('No project selected'));
15
+ console.log(chalk.gray('Select a project with:'), chalk.cyan('gatellm project select'));
16
+ process.exit(1);
17
+ }
18
+ return projectKey;
19
+ }
20
+
21
+ module.exports = (program) => {
22
+ const docs = program.command('docs').description('Document management for RAG');
23
+
24
+ // Upload documents
25
+ docs
26
+ .command('upload <files...>')
27
+ .description('Upload documents to knowledge base')
28
+ .option('-i, --intent <intent>', 'Associate with specific intent')
29
+ .action(async (files, options) => {
30
+ requireProject();
31
+
32
+ try {
33
+ const uploadResults = [];
34
+
35
+ for (const file of files) {
36
+ const filePath = path.resolve(file);
37
+
38
+ if (!fs.existsSync(filePath)) {
39
+ console.error(chalk.red('File not found:'), filePath);
40
+ continue;
41
+ }
42
+
43
+ const stats = fs.statSync(filePath);
44
+ if (!stats.isFile()) {
45
+ console.error(chalk.red('Not a file:'), filePath);
46
+ continue;
47
+ }
48
+
49
+ const spinner = ora(`Uploading ${path.basename(filePath)}...`).start();
50
+
51
+ try {
52
+ const formData = new FormData();
53
+ formData.append('file', fs.createReadStream(filePath));
54
+
55
+ if (options.intent) {
56
+ formData.append('intent_name', options.intent);
57
+ }
58
+
59
+ await api.uploadDocument(formData);
60
+
61
+ spinner.succeed(chalk.green(`Uploaded ${path.basename(filePath)}`));
62
+ uploadResults.push({ file: filePath, status: 'success' });
63
+ } catch (error) {
64
+ spinner.fail(chalk.red(`Failed to upload ${path.basename(filePath)}`));
65
+ console.error(chalk.red(' Error:'), error.message);
66
+ uploadResults.push({ file: filePath, status: 'failed', error: error.message });
67
+ }
68
+ }
69
+
70
+ // Summary
71
+ const succeeded = uploadResults.filter(r => r.status === 'success').length;
72
+ const failed = uploadResults.filter(r => r.status === 'failed').length;
73
+
74
+ console.log(chalk.gray('\nUpload Summary:'));
75
+ console.log(chalk.green(` Succeeded: ${succeeded}`));
76
+ if (failed > 0) {
77
+ console.log(chalk.red(` Failed: ${failed}`));
78
+ }
79
+ } catch (error) {
80
+ console.error(chalk.red('Upload failed:'), error.message);
81
+ process.exit(1);
82
+ }
83
+ });
84
+
85
+ // List documents
86
+ docs
87
+ .command('list')
88
+ .alias('ls')
89
+ .description('List all documents')
90
+ .option('-i, --intent <intent>', 'Filter by intent')
91
+ .action(async (options) => {
92
+ requireProject();
93
+
94
+ try {
95
+ const spinner = ora('Fetching documents...').start();
96
+
97
+ const documents = await api.listDocuments(options.intent);
98
+
99
+ spinner.stop();
100
+
101
+ if (documents.length === 0) {
102
+ console.log(chalk.yellow('No documents found'));
103
+ console.log(chalk.gray('Upload one with:'), chalk.cyan('gatellm docs upload <file>'));
104
+ return;
105
+ }
106
+
107
+ const table = new Table({
108
+ head: [chalk.cyan('ID'), chalk.cyan('Filename'), chalk.cyan('Intent'), chalk.cyan('Chunks'), chalk.cyan('Uploaded')],
109
+ colWidths: [8, 30, 20, 10, 20]
110
+ });
111
+
112
+ documents.forEach(doc => {
113
+ table.push([
114
+ doc.id,
115
+ doc.filename,
116
+ doc.intent_name || chalk.gray('(global)'),
117
+ doc.chunk_count || 0,
118
+ new Date(doc.uploaded_at).toLocaleDateString()
119
+ ]);
120
+ });
121
+
122
+ console.log(table.toString());
123
+ console.log(chalk.gray(`\nTotal: ${documents.length} document(s)`));
124
+ } catch (error) {
125
+ console.error(chalk.red('Failed to list documents:'), error.message);
126
+ process.exit(1);
127
+ }
128
+ });
129
+
130
+ // Delete document
131
+ docs
132
+ .command('delete <id>')
133
+ .alias('rm')
134
+ .description('Delete a document')
135
+ .option('-y, --yes', 'Skip confirmation')
136
+ .action(async (id, options) => {
137
+ requireProject();
138
+
139
+ try {
140
+ if (!options.yes) {
141
+ const answers = await inquirer.prompt([
142
+ {
143
+ type: 'confirm',
144
+ name: 'confirm',
145
+ message: `Are you sure you want to delete document ${id}?`,
146
+ default: false
147
+ }
148
+ ]);
149
+
150
+ if (!answers.confirm) {
151
+ console.log(chalk.yellow('Cancelled'));
152
+ return;
153
+ }
154
+ }
155
+
156
+ const spinner = ora('Deleting document...').start();
157
+ await api.deleteDocument(id);
158
+ spinner.succeed(chalk.green('Document deleted successfully'));
159
+ } catch (error) {
160
+ console.error(chalk.red('Failed to delete document:'), error.message);
161
+ process.exit(1);
162
+ }
163
+ });
164
+ };
@@ -0,0 +1,251 @@
1
+ const inquirer = require('inquirer');
2
+ const chalk = require('chalk');
3
+ const ora = require('ora');
4
+ const Table = require('cli-table3');
5
+ const api = require('../lib/api');
6
+ const config = require('../lib/config');
7
+
8
+ function requireProject() {
9
+ const projectKey = config.getCurrentProject();
10
+ if (!projectKey) {
11
+ console.error(chalk.red('No project selected'));
12
+ console.log(chalk.gray('Select a project with:'), chalk.cyan('gatellm project select'));
13
+ process.exit(1);
14
+ }
15
+ return projectKey;
16
+ }
17
+
18
+ module.exports = (program) => {
19
+ const intent = program.command('intent').description('Intent management commands');
20
+
21
+ // Add intent
22
+ intent
23
+ .command('add <name>')
24
+ .description('Add a new intent')
25
+ .option('-d, --description <description>', 'Intent description')
26
+ .option('-e, --examples <examples...>', 'Example queries (comma-separated or multiple -e flags)')
27
+ .action(async (name, options) => {
28
+ requireProject();
29
+
30
+ try {
31
+ let { description, examples } = options;
32
+
33
+ // Prompt for description if not provided
34
+ if (!description) {
35
+ const answers = await inquirer.prompt([
36
+ {
37
+ type: 'input',
38
+ name: 'description',
39
+ message: 'Intent description:',
40
+ validate: (input) => input.length > 0 || 'Description is required'
41
+ }
42
+ ]);
43
+ description = answers.description;
44
+ }
45
+
46
+ // Parse examples
47
+ const examplesList = examples || [];
48
+
49
+ const spinner = ora('Creating intent...').start();
50
+
51
+ await api.createIntent(name, description, examplesList);
52
+
53
+ spinner.succeed(chalk.green('Intent created successfully!'));
54
+ console.log(chalk.gray('Name:'), name);
55
+ console.log(chalk.gray('Description:'), description);
56
+ if (examplesList.length > 0) {
57
+ console.log(chalk.gray('Examples:'), examplesList.length);
58
+ }
59
+
60
+ console.log('\n' + chalk.yellow('Next steps:'));
61
+ console.log(chalk.gray(' 1. Add routing rule:'), chalk.cyan(`gatellm route add --intent "${name}"`));
62
+ console.log(chalk.gray(' 2. Set system prompt:'), chalk.cyan(`gatellm prompt set --intent "${name}"`));
63
+ } catch (error) {
64
+ spinner.fail(chalk.red('Failed to create intent'));
65
+ console.error(chalk.red('Error:'), error.message);
66
+ process.exit(1);
67
+ }
68
+ });
69
+
70
+ // List intents
71
+ intent
72
+ .command('list')
73
+ .alias('ls')
74
+ .description('List all intents')
75
+ .action(async () => {
76
+ requireProject();
77
+
78
+ try {
79
+ const spinner = ora('Fetching intents...').start();
80
+
81
+ const intents = await api.listIntents();
82
+
83
+ spinner.stop();
84
+
85
+ if (intents.length === 0) {
86
+ console.log(chalk.yellow('No intents found'));
87
+ console.log(chalk.gray('Create one with:'), chalk.cyan('gatellm intent add <name>'));
88
+ return;
89
+ }
90
+
91
+ const table = new Table({
92
+ head: [chalk.cyan('Name'), chalk.cyan('Description'), chalk.cyan('Examples'), chalk.cyan('Created')],
93
+ colWidths: [25, 40, 12, 20]
94
+ });
95
+
96
+ intents.forEach(intent => {
97
+ table.push([
98
+ chalk.green(intent.name),
99
+ intent.description || chalk.gray('(no description)'),
100
+ intent.example_count || 0,
101
+ new Date(intent.created_at).toLocaleDateString()
102
+ ]);
103
+ });
104
+
105
+ console.log(table.toString());
106
+ console.log(chalk.gray(`\nTotal: ${intents.length} intent(s)`));
107
+ } catch (error) {
108
+ console.error(chalk.red('Failed to list intents:'), error.message);
109
+ process.exit(1);
110
+ }
111
+ });
112
+
113
+ // Get intent details
114
+ intent
115
+ .command('get <name>')
116
+ .description('Get intent details')
117
+ .action(async (name) => {
118
+ requireProject();
119
+
120
+ try {
121
+ const spinner = ora('Fetching intent...').start();
122
+ const intent = await api.getIntent(name);
123
+ spinner.stop();
124
+
125
+ console.log(chalk.green('Intent Details:'));
126
+ console.log(chalk.gray(' Name:'), intent.name);
127
+ console.log(chalk.gray(' Description:'), intent.description);
128
+ console.log(chalk.gray(' Created:'), new Date(intent.created_at).toLocaleString());
129
+
130
+ if (intent.examples && intent.examples.length > 0) {
131
+ console.log(chalk.gray(' Examples:'));
132
+ intent.examples.forEach((ex, i) => {
133
+ console.log(chalk.gray(` ${i + 1}. ${ex}`));
134
+ });
135
+ }
136
+ } catch (error) {
137
+ console.error(chalk.red('Failed to get intent:'), error.message);
138
+ process.exit(1);
139
+ }
140
+ });
141
+
142
+ // Delete intent
143
+ intent
144
+ .command('delete <name>')
145
+ .alias('rm')
146
+ .description('Delete an intent')
147
+ .option('-y, --yes', 'Skip confirmation')
148
+ .action(async (name, options) => {
149
+ requireProject();
150
+
151
+ try {
152
+ if (!options.yes) {
153
+ const answers = await inquirer.prompt([
154
+ {
155
+ type: 'confirm',
156
+ name: 'confirm',
157
+ message: `Are you sure you want to delete intent "${name}"?`,
158
+ default: false
159
+ }
160
+ ]);
161
+
162
+ if (!answers.confirm) {
163
+ console.log(chalk.yellow('Cancelled'));
164
+ return;
165
+ }
166
+ }
167
+
168
+ const spinner = ora('Deleting intent...').start();
169
+ await api.deleteIntent(name);
170
+ spinner.succeed(chalk.green('Intent deleted successfully'));
171
+ } catch (error) {
172
+ console.error(chalk.red('Failed to delete intent:'), error.message);
173
+ process.exit(1);
174
+ }
175
+ });
176
+
177
+ // Batch add intents from JSON or TOON file
178
+ intent
179
+ .command('batch <file>')
180
+ .description('Batch create intents from JSON or TOON file')
181
+ .action(async (file) => {
182
+ requireProject();
183
+
184
+ try {
185
+ const fs = require('fs');
186
+ const path = require('path');
187
+
188
+ const filePath = path.resolve(file);
189
+
190
+ if (!fs.existsSync(filePath)) {
191
+ console.error(chalk.red('File not found:'), filePath);
192
+ process.exit(1);
193
+ }
194
+
195
+ const ext = path.extname(filePath).toLowerCase();
196
+ let intents;
197
+
198
+ if (ext === '.toon') {
199
+ // Parse TOON format (39.6% more token-efficient!)
200
+ console.log(chalk.gray('Parsing TOON format file...'));
201
+
202
+ // Load TOON parser from agent-skill
203
+ const toonParserPath = path.join(__dirname, '../../agent-skill/lib/toon-parser.js');
204
+
205
+ if (fs.existsSync(toonParserPath)) {
206
+ const toonParser = require(toonParserPath);
207
+ const parsed = toonParser.parseFile(filePath);
208
+ intents = parsed.intents;
209
+
210
+ if (!intents || !Array.isArray(intents)) {
211
+ console.error(chalk.red('Invalid TOON format: No intents array found'));
212
+ process.exit(1);
213
+ }
214
+
215
+ console.log(chalk.green(`✓ Parsed ${intents.length} intents from TOON file`));
216
+ } else {
217
+ console.error(chalk.red('TOON parser not found. Install agent-skill package.'));
218
+ process.exit(1);
219
+ }
220
+ } else {
221
+ // Parse JSON format
222
+ console.log(chalk.gray('Parsing JSON format file...'));
223
+ const content = fs.readFileSync(filePath, 'utf8');
224
+ intents = JSON.parse(content);
225
+
226
+ if (!Array.isArray(intents)) {
227
+ console.error(chalk.red('Invalid format: Expected an array of intents'));
228
+ process.exit(1);
229
+ }
230
+ }
231
+
232
+ const spinner = ora(`Creating ${intents.length} intents...`).start();
233
+
234
+ const response = await api.batchCreateIntents(intents);
235
+
236
+ spinner.succeed(chalk.green(`Created ${response.created} intents successfully!`));
237
+
238
+ if (response.failed > 0) {
239
+ console.log(chalk.yellow(`Failed: ${response.failed}`));
240
+ if (response.errors) {
241
+ response.errors.forEach(err => {
242
+ console.log(chalk.red(` - ${err}`));
243
+ });
244
+ }
245
+ }
246
+ } catch (error) {
247
+ console.error(chalk.red('Failed to batch create intents:'), error.message);
248
+ process.exit(1);
249
+ }
250
+ });
251
+ };
@@ -0,0 +1,193 @@
1
+ const inquirer = require('inquirer');
2
+ const chalk = require('chalk');
3
+ const ora = require('ora');
4
+ const Table = require('cli-table3');
5
+ const api = require('../lib/api');
6
+ const config = require('../lib/config');
7
+
8
+ module.exports = (program) => {
9
+ const project = program.command('project').description('Project management commands');
10
+
11
+ // Create project
12
+ project
13
+ .command('create <name>')
14
+ .description('Create a new project')
15
+ .option('-d, --description <description>', 'Project description')
16
+ .action(async (name, options) => {
17
+ try {
18
+ const spinner = ora('Creating project...').start();
19
+
20
+ const response = await api.createProject(name, options.description || '');
21
+
22
+ // Auto-select the new project
23
+ config.setCurrentProject(response.project_key);
24
+
25
+ spinner.succeed(chalk.green('Project created successfully!'));
26
+ console.log(chalk.gray('Name:'), name);
27
+ console.log(chalk.gray('Project Key:'), chalk.cyan(response.project_key));
28
+ console.log(chalk.gray('Status:'), chalk.green('Active (selected)'));
29
+
30
+ console.log('\n' + chalk.yellow('Next steps:'));
31
+ console.log(chalk.gray(' 1. Add intents:'), chalk.cyan('gatellm intent add "intent_name"'));
32
+ console.log(chalk.gray(' 2. Configure routes:'), chalk.cyan('gatellm route add'));
33
+ console.log(chalk.gray(' 3. Train model:'), chalk.cyan('gatellm train'));
34
+ } catch (error) {
35
+ spinner.fail(chalk.red('Failed to create project'));
36
+ console.error(chalk.red('Error:'), error.message);
37
+ process.exit(1);
38
+ }
39
+ });
40
+
41
+ // List projects
42
+ project
43
+ .command('list')
44
+ .alias('ls')
45
+ .description('List all projects')
46
+ .action(async () => {
47
+ try {
48
+ const spinner = ora('Fetching projects...').start();
49
+
50
+ const projects = await api.listProjects();
51
+ const currentProject = config.getCurrentProject();
52
+
53
+ spinner.stop();
54
+
55
+ if (projects.length === 0) {
56
+ console.log(chalk.yellow('No projects found'));
57
+ console.log(chalk.gray('Create one with:'), chalk.cyan('gatellm project create <name>'));
58
+ return;
59
+ }
60
+
61
+ const table = new Table({
62
+ head: [chalk.cyan('Name'), chalk.cyan('Project Key'), chalk.cyan('Description'), chalk.cyan('Status')],
63
+ colWidths: [25, 40, 35, 10]
64
+ });
65
+
66
+ projects.forEach(proj => {
67
+ const isActive = proj.project_key === currentProject;
68
+ table.push([
69
+ isActive ? chalk.green(`${proj.name} *`) : proj.name,
70
+ proj.project_key,
71
+ proj.description || chalk.gray('(no description)'),
72
+ isActive ? chalk.green('Active') : chalk.gray('---')
73
+ ]);
74
+ });
75
+
76
+ console.log(table.toString());
77
+ console.log(chalk.gray('\n* = Currently selected project'));
78
+ } catch (error) {
79
+ console.error(chalk.red('Failed to list projects:'), error.message);
80
+ process.exit(1);
81
+ }
82
+ });
83
+
84
+ // Select project
85
+ project
86
+ .command('select [projectKey]')
87
+ .description('Select a project to work with')
88
+ .action(async (projectKey) => {
89
+ try {
90
+ if (!projectKey) {
91
+ // Show interactive selection
92
+ const projects = await api.listProjects();
93
+
94
+ if (projects.length === 0) {
95
+ console.log(chalk.yellow('No projects found'));
96
+ return;
97
+ }
98
+
99
+ const answers = await inquirer.prompt([
100
+ {
101
+ type: 'list',
102
+ name: 'projectKey',
103
+ message: 'Select a project:',
104
+ choices: projects.map(p => ({
105
+ name: `${p.name} (${p.project_key})`,
106
+ value: p.project_key
107
+ }))
108
+ }
109
+ ]);
110
+
111
+ projectKey = answers.projectKey;
112
+ }
113
+
114
+ // Verify project exists
115
+ const project = await api.getProject(projectKey);
116
+
117
+ config.setCurrentProject(projectKey);
118
+
119
+ console.log(chalk.green('Project selected:'), project.name);
120
+ console.log(chalk.gray('Project Key:'), chalk.cyan(projectKey));
121
+ } catch (error) {
122
+ console.error(chalk.red('Failed to select project:'), error.message);
123
+ process.exit(1);
124
+ }
125
+ });
126
+
127
+ // Show current project
128
+ project
129
+ .command('current')
130
+ .description('Show currently selected project')
131
+ .action(async () => {
132
+ const projectKey = config.getCurrentProject();
133
+
134
+ if (!projectKey) {
135
+ console.log(chalk.yellow('No project selected'));
136
+ console.log(chalk.gray('Select one with:'), chalk.cyan('gatellm project select'));
137
+ return;
138
+ }
139
+
140
+ try {
141
+ const spinner = ora('Fetching project details...').start();
142
+ const project = await api.getProject(projectKey);
143
+ spinner.stop();
144
+
145
+ console.log(chalk.green('Current Project:'));
146
+ console.log(chalk.gray(' Name:'), project.name);
147
+ console.log(chalk.gray(' Project Key:'), chalk.cyan(project.project_key));
148
+ console.log(chalk.gray(' Description:'), project.description || chalk.gray('(no description)'));
149
+ console.log(chalk.gray(' Created:'), new Date(project.created_at).toLocaleString());
150
+ } catch (error) {
151
+ console.error(chalk.red('Failed to get project:'), error.message);
152
+ process.exit(1);
153
+ }
154
+ });
155
+
156
+ // Delete project
157
+ project
158
+ .command('delete <projectKey>')
159
+ .description('Delete a project')
160
+ .option('-y, --yes', 'Skip confirmation')
161
+ .action(async (projectKey, options) => {
162
+ try {
163
+ if (!options.yes) {
164
+ const answers = await inquirer.prompt([
165
+ {
166
+ type: 'confirm',
167
+ name: 'confirm',
168
+ message: `Are you sure you want to delete project ${projectKey}?`,
169
+ default: false
170
+ }
171
+ ]);
172
+
173
+ if (!answers.confirm) {
174
+ console.log(chalk.yellow('Cancelled'));
175
+ return;
176
+ }
177
+ }
178
+
179
+ const spinner = ora('Deleting project...').start();
180
+ await api.deleteProject(projectKey);
181
+
182
+ // Clear current project if it's the one being deleted
183
+ if (config.getCurrentProject() === projectKey) {
184
+ config.setCurrentProject(null);
185
+ }
186
+
187
+ spinner.succeed(chalk.green('Project deleted successfully'));
188
+ } catch (error) {
189
+ console.error(chalk.red('Failed to delete project:'), error.message);
190
+ process.exit(1);
191
+ }
192
+ });
193
+ };