@toothfairyai/cli 1.0.13 → 1.0.14

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/src/config.js CHANGED
@@ -4,147 +4,216 @@ const os = require('os');
4
4
  const yaml = require('js-yaml');
5
5
 
6
6
  class ToothFairyConfig {
7
- constructor(baseUrl, aiUrl, aiStreamUrl, apiKey, workspaceId) {
8
- this.baseUrl = baseUrl;
9
- this.aiUrl = aiUrl;
10
- this.aiStreamUrl = aiStreamUrl;
11
- this.apiKey = apiKey;
12
- this.workspaceId = workspaceId;
7
+ constructor(baseUrl, aiUrl, aiStreamUrl, apiKey, workspaceId, userId) {
8
+ this.baseUrl = baseUrl;
9
+ this.aiUrl = aiUrl;
10
+ this.aiStreamUrl = aiStreamUrl;
11
+ this.apiKey = apiKey;
12
+ this.workspaceId = workspaceId;
13
+ this.userId = userId;
14
+ }
15
+
16
+ static fromEnv() {
17
+ return new ToothFairyConfig(
18
+ process.env.TF_BASE_URL || 'https://api.toothfairyai.com',
19
+ process.env.TF_AI_URL || 'https://ai.toothfairyai.com',
20
+ process.env.TF_AI_STREAM_URL || 'https://ais.toothfairyai.com',
21
+ process.env.TF_API_KEY || '',
22
+ process.env.TF_WORKSPACE_ID || '',
23
+ process.env.TF_USER_ID || ''
24
+ );
25
+ }
26
+
27
+ static fromFile(configPath) {
28
+ if (!fs.existsSync(configPath)) {
29
+ throw new Error(`Config file not found: ${configPath}`);
13
30
  }
14
31
 
15
- static fromEnv() {
16
- return new ToothFairyConfig(
17
- process.env.TF_BASE_URL || 'https://api.toothfairyai.com',
18
- process.env.TF_AI_URL || 'https://ai.toothfairyai.com',
19
- process.env.TF_AI_STREAM_URL || 'https://ais.toothfairyai.com',
20
- process.env.TF_API_KEY || '',
21
- process.env.TF_WORKSPACE_ID || ''
22
- );
23
- }
24
-
25
- static fromFile(configPath) {
26
- if (!fs.existsSync(configPath)) {
27
- throw new Error(`Config file not found: ${configPath}`);
28
- }
29
-
30
- const content = fs.readFileSync(configPath, 'utf8');
31
- let data;
32
-
33
- if (configPath.endsWith('.yml') || configPath.endsWith('.yaml')) {
34
- data = yaml.load(content);
35
- } else {
36
- data = JSON.parse(content);
37
- }
38
-
39
- return new ToothFairyConfig(
40
- data.base_url || 'https://api.toothfairyai.com',
41
- data.ai_url || 'https://ai.toothfairyai.com',
42
- data.ai_stream_url || 'https://ais.toothfairyai.com',
43
- data.api_key || '',
44
- data.workspace_id || ''
45
- );
46
- }
32
+ const content = fs.readFileSync(configPath, 'utf8');
33
+ let data;
47
34
 
48
- validate() {
49
- return !!(this.apiKey && this.workspaceId);
35
+ if (configPath.endsWith('.yml') || configPath.endsWith('.yaml')) {
36
+ data = yaml.load(content);
37
+ } else {
38
+ data = JSON.parse(content);
50
39
  }
51
40
 
52
- toObject() {
53
- return {
54
- base_url: this.baseUrl,
55
- ai_url: this.aiUrl,
56
- ai_stream_url: this.aiStreamUrl,
57
- api_key: this.apiKey,
58
- workspace_id: this.workspaceId
59
- };
60
- }
41
+ return new ToothFairyConfig(
42
+ data.base_url || 'https://api.toothfairyai.com',
43
+ data.ai_url || 'https://ai.toothfairyai.com',
44
+ data.ai_stream_url || 'https://ais.toothfairyai.com',
45
+ data.api_key || '',
46
+ data.workspace_id || '',
47
+ data.user_id || ''
48
+ );
49
+ }
50
+
51
+ validate() {
52
+ return !!(this.apiKey && this.workspaceId);
53
+ }
54
+
55
+ validateForDocumentOperations() {
56
+ return !!(this.apiKey && this.workspaceId && this.userId);
57
+ }
58
+
59
+ toObject() {
60
+ return {
61
+ base_url: this.baseUrl,
62
+ ai_url: this.aiUrl,
63
+ ai_stream_url: this.aiStreamUrl,
64
+ api_key: this.apiKey,
65
+ workspace_id: this.workspaceId,
66
+ user_id: this.userId,
67
+ };
68
+ }
61
69
  }
62
70
 
63
71
  function getConfigPath() {
64
- return path.join(os.homedir(), '.toothfairy', 'config.yml');
72
+ return path.join(os.homedir(), '.toothfairy', 'config.yml');
65
73
  }
66
74
 
67
75
  function loadConfig(configPath = null) {
68
- // Priority order:
69
- // 1. Provided config file path
70
- // 2. Default config file (~/.toothfairy/config.yml)
71
- // 3. Environment variables
72
-
73
- if (configPath) {
74
- return ToothFairyConfig.fromFile(configPath);
75
- }
76
-
77
- const defaultConfig = getConfigPath();
78
- if (fs.existsSync(defaultConfig)) {
79
- return ToothFairyConfig.fromFile(defaultConfig);
80
- }
81
-
82
- const config = ToothFairyConfig.fromEnv();
83
- if (!config.validate()) {
84
- throw new Error(
85
- 'Configuration incomplete. Please provide configuration via:\n' +
86
- '1. Config file at ~/.toothfairy/config.yml\n' +
87
- '2. Environment variables: TF_API_KEY, TF_WORKSPACE_ID\n' +
88
- '3. CLI arguments\n' +
89
- 'Note: TF_BASE_URL and TF_AI_URL default to production endpoints'
90
- );
91
- }
92
-
93
- return config;
76
+ // Priority order:
77
+ // 1. Provided config file path
78
+ // 2. Default config file (~/.toothfairy/config.yml)
79
+ // 3. Environment variables
80
+
81
+ if (configPath) {
82
+ return ToothFairyConfig.fromFile(configPath);
83
+ }
84
+
85
+ const defaultConfig = getConfigPath();
86
+ if (fs.existsSync(defaultConfig)) {
87
+ return ToothFairyConfig.fromFile(defaultConfig);
88
+ }
89
+
90
+ const config = ToothFairyConfig.fromEnv();
91
+ if (!config.validate()) {
92
+ throw new Error(
93
+ 'Configuration incomplete. Please provide configuration via:\n' +
94
+ '1. Config file at ~/.toothfairy/config.yml\n' +
95
+ '2. Environment variables: TF_API_KEY, TF_WORKSPACE_ID\n' +
96
+ '3. CLI arguments\n' +
97
+ 'Note: TF_BASE_URL and TF_AI_URL default to production endpoints'
98
+ );
99
+ }
100
+
101
+ return config;
94
102
  }
95
103
 
96
104
  function saveConfig(config, configPath = null) {
97
- const filePath = configPath || getConfigPath();
98
- const dir = path.dirname(filePath);
105
+ const filePath = configPath || getConfigPath();
106
+ const dir = path.dirname(filePath);
99
107
 
100
- // Create directory if it doesn't exist
101
- if (!fs.existsSync(dir)) {
102
- fs.mkdirSync(dir, { recursive: true });
103
- }
108
+ // Create directory if it doesn't exist
109
+ if (!fs.existsSync(dir)) {
110
+ fs.mkdirSync(dir, { recursive: true });
111
+ }
104
112
 
105
- const content = yaml.dump(config.toObject());
106
- fs.writeFileSync(filePath, content, 'utf8');
113
+ const content = yaml.dump(config.toObject());
114
+ fs.writeFileSync(filePath, content, 'utf8');
107
115
  }
108
116
 
109
117
  function validateConfiguration(config) {
110
- const missingFields = [];
111
-
118
+ const missingFields = [];
119
+
120
+ if (!config.apiKey) {
121
+ missingFields.push('API Key');
122
+ }
123
+ if (!config.workspaceId) {
124
+ missingFields.push('Workspace ID');
125
+ }
126
+
127
+ if (missingFields.length > 0) {
128
+ const missingStr = missingFields.join(' and ');
129
+ const chalk = require('chalk');
130
+
131
+ console.error(
132
+ chalk.red(`Error: Missing required configuration: ${missingStr}`)
133
+ );
134
+ console.error();
135
+ console.error(chalk.yellow('To fix this, run the configure command:'));
136
+ console.error(
137
+ chalk.dim(
138
+ 'tf configure --api-key YOUR_API_KEY --workspace-id YOUR_WORKSPACE_ID'
139
+ )
140
+ );
141
+ console.error();
142
+ console.error(chalk.yellow('Or set environment variables:'));
143
+ if (!config.apiKey) {
144
+ console.error(chalk.dim('export TF_API_KEY=\'your-api-key\''));
145
+ }
146
+ if (!config.workspaceId) {
147
+ console.error(chalk.dim('export TF_WORKSPACE_ID=\'your-workspace-id\''));
148
+ }
149
+ console.error();
150
+ console.error(
151
+ chalk.yellow('Or create a config file at ~/.toothfairy/config.yml:')
152
+ );
153
+ console.error(chalk.dim('api_key: your-api-key'));
154
+ console.error(chalk.dim('workspace_id: your-workspace-id'));
155
+
156
+ throw new Error(`Configuration incomplete: missing ${missingStr}`);
157
+ }
158
+ }
159
+
160
+ function validateDocumentConfiguration(config) {
161
+ const missingFields = [];
162
+
163
+ if (!config.apiKey) {
164
+ missingFields.push('API Key');
165
+ }
166
+ if (!config.workspaceId) {
167
+ missingFields.push('Workspace ID');
168
+ }
169
+ if (!config.userId) {
170
+ missingFields.push('User ID');
171
+ }
172
+
173
+ if (missingFields.length > 0) {
174
+ const missingStr = missingFields.join(' and ');
175
+ const chalk = require('chalk');
176
+
177
+ console.error(
178
+ chalk.red(
179
+ `Error: Missing required configuration for document operations: ${missingStr}`
180
+ )
181
+ );
182
+ console.error();
183
+ console.error(chalk.yellow('To fix this, run the configure command:'));
184
+ console.error(
185
+ chalk.dim(
186
+ 'tf configure --api-key YOUR_API_KEY --workspace-id YOUR_WORKSPACE_ID --user-id YOUR_USER_ID'
187
+ )
188
+ );
189
+ console.error();
190
+ console.error(chalk.yellow('Or set environment variables:'));
112
191
  if (!config.apiKey) {
113
- missingFields.push('API Key');
192
+ console.error(chalk.dim('export TF_API_KEY=\'your-api-key\''));
114
193
  }
115
194
  if (!config.workspaceId) {
116
- missingFields.push('Workspace ID');
195
+ console.error(chalk.dim('export TF_WORKSPACE_ID=\'your-workspace-id\''));
117
196
  }
118
-
119
- if (missingFields.length > 0) {
120
- const missingStr = missingFields.join(' and ');
121
- const chalk = require('chalk');
122
-
123
- console.error(chalk.red(`Error: Missing required configuration: ${missingStr}`));
124
- console.error();
125
- console.error(chalk.yellow('To fix this, run the configure command:'));
126
- console.error(chalk.dim('tf configure --api-key YOUR_API_KEY --workspace-id YOUR_WORKSPACE_ID'));
127
- console.error();
128
- console.error(chalk.yellow('Or set environment variables:'));
129
- if (!config.apiKey) {
130
- console.error(chalk.dim('export TF_API_KEY=\'your-api-key\''));
131
- }
132
- if (!config.workspaceId) {
133
- console.error(chalk.dim('export TF_WORKSPACE_ID=\'your-workspace-id\''));
134
- }
135
- console.error();
136
- console.error(chalk.yellow('Or create a config file at ~/.toothfairy/config.yml:'));
137
- console.error(chalk.dim('api_key: your-api-key'));
138
- console.error(chalk.dim('workspace_id: your-workspace-id'));
139
-
140
- throw new Error(`Configuration incomplete: missing ${missingStr}`);
197
+ if (!config.userId) {
198
+ console.error(chalk.dim('export TF_USER_ID=\'your-user-id\''));
141
199
  }
200
+ console.error();
201
+ console.error(
202
+ chalk.yellow('Or create a config file at ~/.toothfairy/config.yml:')
203
+ );
204
+ console.error(chalk.dim('api_key: your-api-key'));
205
+ console.error(chalk.dim('workspace_id: your-workspace-id'));
206
+ console.error(chalk.dim('user_id: your-user-id'));
207
+
208
+ throw new Error(`Configuration incomplete: missing ${missingStr}`);
209
+ }
142
210
  }
143
211
 
144
212
  module.exports = {
145
- ToothFairyConfig,
146
- loadConfig,
147
- saveConfig,
148
- getConfigPath,
149
- validateConfiguration
150
- };
213
+ ToothFairyConfig,
214
+ loadConfig,
215
+ saveConfig,
216
+ getConfigPath,
217
+ validateConfiguration,
218
+ validateDocumentConfiguration,
219
+ };