@aaronsb/kg-cli 0.9.3 → 0.9.5
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 +43 -14
- package/dist/api/client.d.ts +4 -0
- package/dist/api/client.d.ts.map +1 -1
- package/dist/api/client.js +10 -0
- package/dist/api/client.js.map +1 -1
- package/dist/cli/ai-config/embedding.d.ts +2 -2
- package/dist/cli/ai-config/embedding.d.ts.map +1 -1
- package/dist/cli/ai-config/embedding.js +262 -129
- package/dist/cli/ai-config/embedding.js.map +1 -1
- package/dist/cli/jobs.d.ts.map +1 -1
- package/dist/cli/jobs.js +42 -27
- package/dist/cli/jobs.js.map +1 -1
- package/dist/cli/program.d.ts.map +1 -1
- package/dist/cli/program.js +7 -1
- package/dist/cli/program.js.map +1 -1
- package/dist/cli/vocabulary/consolidate.d.ts +2 -0
- package/dist/cli/vocabulary/consolidate.d.ts.map +1 -1
- package/dist/cli/vocabulary/consolidate.js +18 -14
- package/dist/cli/vocabulary/consolidate.js.map +1 -1
- package/dist/mcp/formatters/concept.d.ts.map +1 -1
- package/dist/mcp/formatters/concept.js +6 -1
- package/dist/mcp/formatters/concept.js.map +1 -1
- package/dist/mcp/graph-operations.d.ts.map +1 -1
- package/dist/mcp/graph-operations.js +15 -7
- package/dist/mcp/graph-operations.js.map +1 -1
- package/dist/mcp-server.js +54 -16
- package/dist/mcp-server.js.map +1 -1
- package/dist/version.d.ts +3 -3
- package/dist/version.js +3 -3
- package/package.json +1 -1
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
/**
|
|
3
|
-
* Embedding Commands (ADR-039)
|
|
4
|
-
* Manages embedding model
|
|
3
|
+
* Embedding Commands (ADR-039 + Migration 055)
|
|
4
|
+
* Manages embedding profile configuration (text + image model slots)
|
|
5
5
|
*/
|
|
6
6
|
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
7
7
|
if (k2 === undefined) k2 = k;
|
|
@@ -42,59 +42,183 @@ const commander_1 = require("commander");
|
|
|
42
42
|
const colors = __importStar(require("../colors"));
|
|
43
43
|
const colors_1 = require("../colors");
|
|
44
44
|
const utils_1 = require("./utils");
|
|
45
|
+
const fs = __importStar(require("fs"));
|
|
45
46
|
/**
|
|
46
|
-
* Create a new embedding
|
|
47
|
+
* Create a new embedding profile
|
|
47
48
|
*/
|
|
48
49
|
function createEmbeddingCreateCommand(client) {
|
|
49
50
|
return new commander_1.Command('create')
|
|
50
|
-
.description('Create a new embedding
|
|
51
|
-
.option('--
|
|
52
|
-
.option('--
|
|
53
|
-
.option('--
|
|
54
|
-
.option('--
|
|
51
|
+
.description('Create a new embedding profile (inactive)')
|
|
52
|
+
.option('--name <name>', 'Profile name')
|
|
53
|
+
.option('--vector-space <tag>', 'Vector space compatibility tag')
|
|
54
|
+
.option('--multimodal', 'Text model handles both text and image', false)
|
|
55
|
+
.option('--provider <provider>', 'Text provider: local or openai (shorthand for --text-provider)')
|
|
56
|
+
.option('--model <model>', 'Text model name (shorthand for --text-model)')
|
|
57
|
+
.option('--dimensions <dims>', 'Text embedding dimensions (shorthand for --text-dimensions)', parseInt)
|
|
58
|
+
.option('--precision <precision>', 'Text precision: float16 or float32')
|
|
59
|
+
.option('--text-provider <provider>', 'Text provider: local or openai')
|
|
60
|
+
.option('--text-model <model>', 'Text model name')
|
|
61
|
+
.option('--text-dimensions <dims>', 'Text embedding dimensions', parseInt)
|
|
62
|
+
.option('--text-loader <loader>', 'Text loader: sentence-transformers, transformers, api')
|
|
63
|
+
.option('--text-revision <rev>', 'Text model revision/commit hash')
|
|
64
|
+
.option('--text-trust-remote-code', 'Trust remote code for text model', false)
|
|
65
|
+
.option('--image-provider <provider>', 'Image provider')
|
|
66
|
+
.option('--image-model <model>', 'Image model name')
|
|
67
|
+
.option('--image-dimensions <dims>', 'Image embedding dimensions', parseInt)
|
|
68
|
+
.option('--image-loader <loader>', 'Image loader: sentence-transformers, transformers, api')
|
|
69
|
+
.option('--image-revision <rev>', 'Image model revision/commit hash')
|
|
70
|
+
.option('--image-trust-remote-code', 'Trust remote code for image model', false)
|
|
71
|
+
.option('--text-query-prefix <prefix>', 'Text prefix for search queries (e.g. "search_query: ")')
|
|
72
|
+
.option('--text-document-prefix <prefix>', 'Text prefix for document ingestion (e.g. "search_document: ")')
|
|
55
73
|
.option('--device <device>', 'Device: cpu, cuda, mps')
|
|
56
74
|
.option('--memory <mb>', 'Max memory in MB', parseInt)
|
|
57
75
|
.option('--threads <n>', 'Number of threads', parseInt)
|
|
58
76
|
.option('--batch-size <n>', 'Batch size', parseInt)
|
|
77
|
+
.option('--from-json <file>', 'Import profile from JSON file')
|
|
59
78
|
.action(async (options) => {
|
|
60
79
|
try {
|
|
61
80
|
console.log('\n' + (0, colors_1.separator)());
|
|
62
|
-
console.log(colors.ui.title('
|
|
81
|
+
console.log(colors.ui.title('Create Embedding Profile'));
|
|
63
82
|
console.log((0, colors_1.separator)());
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
config.
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
83
|
+
let config = {};
|
|
84
|
+
// Handle JSON import
|
|
85
|
+
if (options.fromJson) {
|
|
86
|
+
const jsonContent = fs.readFileSync(options.fromJson, 'utf-8');
|
|
87
|
+
const imported = JSON.parse(jsonContent);
|
|
88
|
+
// Accept either { profile: { ... } } or raw profile object
|
|
89
|
+
const profile = imported.profile || imported;
|
|
90
|
+
config.name = profile.name;
|
|
91
|
+
config.vector_space = profile.vector_space;
|
|
92
|
+
config.multimodal = profile.multimodal || false;
|
|
93
|
+
// Text slot
|
|
94
|
+
if (profile.text) {
|
|
95
|
+
config.text_provider = profile.text.provider;
|
|
96
|
+
config.text_model_name = profile.text.model_name;
|
|
97
|
+
config.text_loader = profile.text.loader;
|
|
98
|
+
config.text_revision = profile.text.revision;
|
|
99
|
+
config.text_dimensions = profile.text.dimensions;
|
|
100
|
+
config.text_precision = profile.text.precision;
|
|
101
|
+
config.text_trust_remote_code = profile.text.trust_remote_code;
|
|
102
|
+
config.text_query_prefix = profile.text.query_prefix;
|
|
103
|
+
config.text_document_prefix = profile.text.document_prefix;
|
|
104
|
+
}
|
|
105
|
+
// Image slot
|
|
106
|
+
if (profile.image) {
|
|
107
|
+
config.image_provider = profile.image.provider;
|
|
108
|
+
config.image_model_name = profile.image.model_name;
|
|
109
|
+
config.image_loader = profile.image.loader;
|
|
110
|
+
config.image_revision = profile.image.revision;
|
|
111
|
+
config.image_dimensions = profile.image.dimensions;
|
|
112
|
+
config.image_precision = profile.image.precision;
|
|
113
|
+
config.image_trust_remote_code = profile.image.trust_remote_code;
|
|
114
|
+
}
|
|
115
|
+
// Resources
|
|
116
|
+
if (profile.resources) {
|
|
117
|
+
config.device = profile.resources.device;
|
|
118
|
+
config.max_memory_mb = profile.resources.max_memory_mb;
|
|
119
|
+
config.num_threads = profile.resources.num_threads;
|
|
120
|
+
config.batch_size = profile.resources.batch_size;
|
|
121
|
+
config.max_seq_length = profile.resources.max_seq_length;
|
|
122
|
+
config.normalize_embeddings = profile.resources.normalize_embeddings;
|
|
123
|
+
}
|
|
124
|
+
console.log(colors.status.info(`\nImporting from: ${options.fromJson}`));
|
|
125
|
+
}
|
|
126
|
+
else {
|
|
127
|
+
// Build config from CLI flags
|
|
128
|
+
if (options.name)
|
|
129
|
+
config.name = options.name;
|
|
130
|
+
if (options.vectorSpace)
|
|
131
|
+
config.vector_space = options.vectorSpace;
|
|
132
|
+
if (options.multimodal)
|
|
133
|
+
config.multimodal = true;
|
|
134
|
+
// Text slot (explicit or shorthand)
|
|
135
|
+
if (options.textProvider)
|
|
136
|
+
config.text_provider = options.textProvider;
|
|
137
|
+
else if (options.provider)
|
|
138
|
+
config.provider = options.provider;
|
|
139
|
+
if (options.textModel)
|
|
140
|
+
config.text_model_name = options.textModel;
|
|
141
|
+
else if (options.model)
|
|
142
|
+
config.model_name = options.model;
|
|
143
|
+
if (options.textDimensions)
|
|
144
|
+
config.text_dimensions = options.textDimensions;
|
|
145
|
+
else if (options.dimensions)
|
|
146
|
+
config.embedding_dimensions = options.dimensions;
|
|
147
|
+
if (options.textLoader)
|
|
148
|
+
config.text_loader = options.textLoader;
|
|
149
|
+
if (options.textRevision)
|
|
150
|
+
config.text_revision = options.textRevision;
|
|
151
|
+
if (options.textTrustRemoteCode)
|
|
152
|
+
config.text_trust_remote_code = true;
|
|
153
|
+
if (options.textQueryPrefix)
|
|
154
|
+
config.text_query_prefix = options.textQueryPrefix;
|
|
155
|
+
if (options.textDocumentPrefix)
|
|
156
|
+
config.text_document_prefix = options.textDocumentPrefix;
|
|
157
|
+
if (options.precision)
|
|
158
|
+
config.text_precision = options.precision;
|
|
159
|
+
// Image slot
|
|
160
|
+
if (options.imageProvider)
|
|
161
|
+
config.image_provider = options.imageProvider;
|
|
162
|
+
if (options.imageModel)
|
|
163
|
+
config.image_model_name = options.imageModel;
|
|
164
|
+
if (options.imageDimensions)
|
|
165
|
+
config.image_dimensions = options.imageDimensions;
|
|
166
|
+
if (options.imageLoader)
|
|
167
|
+
config.image_loader = options.imageLoader;
|
|
168
|
+
if (options.imageRevision)
|
|
169
|
+
config.image_revision = options.imageRevision;
|
|
170
|
+
if (options.imageTrustRemoteCode)
|
|
171
|
+
config.image_trust_remote_code = true;
|
|
172
|
+
// Resources
|
|
173
|
+
if (options.device)
|
|
174
|
+
config.device = options.device;
|
|
175
|
+
if (options.memory)
|
|
176
|
+
config.max_memory_mb = options.memory;
|
|
177
|
+
if (options.threads)
|
|
178
|
+
config.num_threads = options.threads;
|
|
179
|
+
if (options.batchSize)
|
|
180
|
+
config.batch_size = options.batchSize;
|
|
181
|
+
}
|
|
182
|
+
// Remove undefined values
|
|
183
|
+
config = Object.fromEntries(Object.entries(config).filter(([_, v]) => v !== undefined && v !== null));
|
|
81
184
|
if (Object.keys(config).length === 0) {
|
|
82
|
-
console.error(colors.status.error('\n
|
|
185
|
+
console.error(colors.status.error('\n No configuration options provided'));
|
|
83
186
|
console.log(colors.status.dim(' Use --help to see available options\n'));
|
|
84
187
|
process.exit(1);
|
|
85
188
|
}
|
|
86
189
|
const result = await client.updateEmbeddingConfig(config);
|
|
87
|
-
console.log('\n' + colors.status.success('
|
|
88
|
-
console.log(`\n ${colors.ui.key('
|
|
190
|
+
console.log('\n' + colors.status.success(' Profile created successfully'));
|
|
191
|
+
console.log(`\n ${colors.ui.key('Profile ID:')} ${colors.ui.value(result.config_id)}`);
|
|
89
192
|
console.log(` ${colors.ui.key('Status:')} ${colors.status.dim('Inactive')}`);
|
|
90
|
-
console.log('\n' + colors.status.warning('
|
|
193
|
+
console.log('\n' + colors.status.warning(' Next steps:'));
|
|
91
194
|
console.log(colors.status.dim(` 1. Review: kg admin embedding list`));
|
|
92
195
|
console.log(colors.status.dim(` 2. Activate: kg admin embedding activate ${result.config_id}`));
|
|
93
196
|
console.log(colors.status.dim(` 3. Apply: kg admin embedding reload\n`));
|
|
94
197
|
console.log((0, colors_1.separator)() + '\n');
|
|
95
198
|
}
|
|
96
199
|
catch (error) {
|
|
97
|
-
console.error(colors.status.error('
|
|
200
|
+
console.error(colors.status.error(' Failed to create embedding profile'));
|
|
201
|
+
console.error(colors.status.error(error.response?.data?.detail || error.message));
|
|
202
|
+
process.exit(1);
|
|
203
|
+
}
|
|
204
|
+
});
|
|
205
|
+
}
|
|
206
|
+
/**
|
|
207
|
+
* Export an embedding profile as JSON
|
|
208
|
+
*/
|
|
209
|
+
function createEmbeddingExportCommand(client) {
|
|
210
|
+
return new commander_1.Command('export')
|
|
211
|
+
.description('Export an embedding profile as JSON')
|
|
212
|
+
.argument('<profile-id>', 'Profile ID', parseInt)
|
|
213
|
+
.option('--profile-only', 'Strip metadata (id, timestamps)', false)
|
|
214
|
+
.action(async (profileId, options) => {
|
|
215
|
+
try {
|
|
216
|
+
const result = await client.exportEmbeddingProfile(profileId, options.profileOnly);
|
|
217
|
+
// Output as pretty-printed JSON to stdout
|
|
218
|
+
console.log(JSON.stringify(result, null, 2));
|
|
219
|
+
}
|
|
220
|
+
catch (error) {
|
|
221
|
+
console.error(colors.status.error(' Failed to export profile'));
|
|
98
222
|
console.error(colors.status.error(error.response?.data?.detail || error.message));
|
|
99
223
|
process.exit(1);
|
|
100
224
|
}
|
|
@@ -109,11 +233,11 @@ function createEmbeddingReloadCommand(client) {
|
|
|
109
233
|
.action(async () => {
|
|
110
234
|
try {
|
|
111
235
|
console.log('\n' + (0, colors_1.separator)());
|
|
112
|
-
console.log(colors.ui.title('
|
|
236
|
+
console.log(colors.ui.title('Hot Reload Embedding Model'));
|
|
113
237
|
console.log((0, colors_1.separator)());
|
|
114
|
-
console.log(colors.status.info('\nReloading model from
|
|
238
|
+
console.log(colors.status.info('\nReloading model from active profile...'));
|
|
115
239
|
const result = await client.reloadEmbeddingModel();
|
|
116
|
-
console.log('\n' + colors.status.success('
|
|
240
|
+
console.log('\n' + colors.status.success(' Hot reload successful'));
|
|
117
241
|
console.log(`\n ${colors.ui.key('Provider:')} ${colors.ui.value(result.provider)}`);
|
|
118
242
|
if (result.model) {
|
|
119
243
|
console.log(` ${colors.ui.key('Model:')} ${colors.ui.value(result.model)}`);
|
|
@@ -125,41 +249,60 @@ function createEmbeddingReloadCommand(client) {
|
|
|
125
249
|
console.log('\n' + (0, colors_1.separator)() + '\n');
|
|
126
250
|
}
|
|
127
251
|
catch (error) {
|
|
128
|
-
console.error(colors.status.error('
|
|
252
|
+
console.error(colors.status.error(' Hot reload failed'));
|
|
129
253
|
console.error(colors.status.error(error.response?.data?.detail || error.message));
|
|
130
254
|
process.exit(1);
|
|
131
255
|
}
|
|
132
256
|
});
|
|
133
257
|
}
|
|
134
258
|
/**
|
|
135
|
-
* List all embedding
|
|
259
|
+
* List all embedding profiles
|
|
136
260
|
*/
|
|
137
261
|
function createEmbeddingListCommand(client) {
|
|
138
262
|
return new commander_1.Command('list')
|
|
139
|
-
.description('List all embedding
|
|
263
|
+
.description('List all embedding profiles')
|
|
140
264
|
.action(async () => {
|
|
141
265
|
try {
|
|
142
266
|
console.log('\n' + (0, colors_1.separator)());
|
|
143
|
-
console.log(colors.ui.title('
|
|
267
|
+
console.log(colors.ui.title('Embedding Profiles'));
|
|
144
268
|
console.log((0, colors_1.separator)());
|
|
145
269
|
const configs = await client.listEmbeddingConfigs();
|
|
146
270
|
if (configs.length === 0) {
|
|
147
|
-
console.log(colors.status.dim('\n No
|
|
271
|
+
console.log(colors.status.dim('\n No profiles found\n'));
|
|
148
272
|
}
|
|
149
273
|
else {
|
|
150
274
|
console.log('');
|
|
151
275
|
for (const config of configs) {
|
|
152
|
-
const activeMarker = config.active ? colors.status.success('
|
|
153
|
-
const deleteProtected = config.delete_protected ? '
|
|
154
|
-
const changeProtected = config.change_protected ? '
|
|
155
|
-
const protection = [deleteProtected, changeProtected].filter(p => p).join('
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
276
|
+
const activeMarker = config.active ? colors.status.success('ACTIVE') : colors.status.dim('Inactive');
|
|
277
|
+
const deleteProtected = config.delete_protected ? 'D' : '';
|
|
278
|
+
const changeProtected = config.change_protected ? 'C' : '';
|
|
279
|
+
const protection = [deleteProtected, changeProtected].filter(p => p).join('');
|
|
280
|
+
const protectionStr = protection ? ` [${protection}]` : '';
|
|
281
|
+
const name = config.name || `Profile ${config.id}`;
|
|
282
|
+
const multimodalTag = config.multimodal ? colors.status.info(' [multimodal]') : '';
|
|
283
|
+
console.log(` ${activeMarker} ${colors.ui.header(name)}${multimodalTag}${protectionStr}`);
|
|
284
|
+
console.log(` ${colors.ui.key('ID:')} ${colors.ui.value(config.id)}`);
|
|
285
|
+
console.log(` ${colors.ui.key('Vector Space:')} ${colors.ui.value(config.vector_space || 'unset')}`);
|
|
286
|
+
// Text slot
|
|
287
|
+
console.log(` ${colors.ui.key('Text:')} ${colors.ui.value(config.text_provider || config.provider)} / ${colors.ui.value(config.text_model_name || config.model_name || 'N/A')}`);
|
|
288
|
+
if (config.text_dimensions || config.embedding_dimensions) {
|
|
289
|
+
console.log(` ${colors.ui.key('Dims:')} ${colors.ui.value((config.text_dimensions || config.embedding_dimensions).toString())} ${colors.ui.key('Loader:')} ${colors.ui.value(config.text_loader || 'auto')}`);
|
|
290
|
+
}
|
|
291
|
+
if (config.text_query_prefix || config.text_document_prefix) {
|
|
292
|
+
console.log(` ${colors.ui.key('Prefixes:')} query=${colors.ui.value(JSON.stringify(config.text_query_prefix || ''))} doc=${colors.ui.value(JSON.stringify(config.text_document_prefix || ''))}`);
|
|
293
|
+
}
|
|
294
|
+
// Image slot
|
|
295
|
+
if (!config.multimodal && config.image_model_name) {
|
|
296
|
+
console.log(` ${colors.ui.key('Image:')} ${colors.ui.value(config.image_provider)} / ${colors.ui.value(config.image_model_name)}`);
|
|
297
|
+
if (config.image_dimensions) {
|
|
298
|
+
console.log(` ${colors.ui.key('Dims:')} ${colors.ui.value(config.image_dimensions.toString())} ${colors.ui.key('Loader:')} ${colors.ui.value(config.image_loader || 'auto')}`);
|
|
299
|
+
}
|
|
160
300
|
}
|
|
161
|
-
if (config.
|
|
162
|
-
console.log(` ${colors.ui.key('
|
|
301
|
+
else if (config.multimodal) {
|
|
302
|
+
console.log(` ${colors.ui.key('Image:')} ${colors.status.dim('(uses text model)')}`);
|
|
303
|
+
}
|
|
304
|
+
else {
|
|
305
|
+
console.log(` ${colors.ui.key('Image:')} ${colors.status.dim('(none)')}`);
|
|
163
306
|
}
|
|
164
307
|
if (config.delete_protected || config.change_protected) {
|
|
165
308
|
const flags = [];
|
|
@@ -169,15 +312,14 @@ function createEmbeddingListCommand(client) {
|
|
|
169
312
|
flags.push('change-protected');
|
|
170
313
|
console.log(` ${colors.ui.key('Protection:')} ${colors.status.warning(flags.join(', '))}`);
|
|
171
314
|
}
|
|
172
|
-
console.log(` ${colors.status.dim('Updated: ' + new Date(config.updated_at).toLocaleString())}`);
|
|
173
|
-
console.log(` ${colors.status.dim('By: ' + config.updated_by)}`);
|
|
315
|
+
console.log(` ${colors.status.dim('Updated: ' + new Date(config.updated_at).toLocaleString() + ' by ' + (config.updated_by || 'unknown'))}`);
|
|
174
316
|
console.log('');
|
|
175
317
|
}
|
|
176
318
|
}
|
|
177
319
|
console.log((0, colors_1.separator)() + '\n');
|
|
178
320
|
}
|
|
179
321
|
catch (error) {
|
|
180
|
-
console.error(colors.status.error('
|
|
322
|
+
console.error(colors.status.error(' Failed to list embedding profiles'));
|
|
181
323
|
console.error(colors.status.error(error.response?.data?.detail || error.message));
|
|
182
324
|
process.exit(1);
|
|
183
325
|
}
|
|
@@ -188,33 +330,33 @@ function createEmbeddingListCommand(client) {
|
|
|
188
330
|
*/
|
|
189
331
|
function createEmbeddingProtectCommand(client) {
|
|
190
332
|
return new commander_1.Command('protect')
|
|
191
|
-
.description('Enable protection flags on an embedding
|
|
192
|
-
.argument('<config-id>', '
|
|
333
|
+
.description('Enable protection flags on an embedding profile')
|
|
334
|
+
.argument('<config-id>', 'Profile ID', parseInt)
|
|
193
335
|
.option('--delete', 'Enable delete protection')
|
|
194
336
|
.option('--change', 'Enable change protection')
|
|
195
337
|
.action(async (configId, options) => {
|
|
196
338
|
try {
|
|
197
339
|
console.log('\n' + (0, colors_1.separator)());
|
|
198
|
-
console.log(colors.ui.title(
|
|
340
|
+
console.log(colors.ui.title(`Protect Profile ${configId}`));
|
|
199
341
|
console.log((0, colors_1.separator)());
|
|
200
342
|
if (!options.delete && !options.change) {
|
|
201
|
-
console.error(colors.status.error('\n
|
|
343
|
+
console.error(colors.status.error('\n Must specify at least one protection flag'));
|
|
202
344
|
console.log(colors.status.dim(' Use --delete and/or --change\n'));
|
|
203
345
|
process.exit(1);
|
|
204
346
|
}
|
|
205
347
|
const result = await client.protectEmbeddingConfig(configId, options.delete ? true : undefined, options.change ? true : undefined);
|
|
206
|
-
console.log('\n' + colors.status.success('
|
|
348
|
+
console.log('\n' + colors.status.success(' Protection enabled'));
|
|
207
349
|
const flags = [];
|
|
208
350
|
if (options.delete)
|
|
209
351
|
flags.push('delete-protected');
|
|
210
352
|
if (options.change)
|
|
211
353
|
flags.push('change-protected');
|
|
212
|
-
console.log(`\n ${colors.ui.key('
|
|
354
|
+
console.log(`\n ${colors.ui.key('Profile ID:')} ${colors.ui.value(configId)}`);
|
|
213
355
|
console.log(` ${colors.ui.key('Flags:')} ${colors.status.warning(flags.join(', '))}`);
|
|
214
356
|
console.log('\n' + (0, colors_1.separator)() + '\n');
|
|
215
357
|
}
|
|
216
358
|
catch (error) {
|
|
217
|
-
console.error(colors.status.error('
|
|
359
|
+
console.error(colors.status.error(' Failed to set protection'));
|
|
218
360
|
console.error(colors.status.error(error.response?.data?.detail || error.message));
|
|
219
361
|
process.exit(1);
|
|
220
362
|
}
|
|
@@ -225,62 +367,62 @@ function createEmbeddingProtectCommand(client) {
|
|
|
225
367
|
*/
|
|
226
368
|
function createEmbeddingUnprotectCommand(client) {
|
|
227
369
|
return new commander_1.Command('unprotect')
|
|
228
|
-
.description('Disable protection flags on an embedding
|
|
229
|
-
.argument('<config-id>', '
|
|
370
|
+
.description('Disable protection flags on an embedding profile')
|
|
371
|
+
.argument('<config-id>', 'Profile ID', parseInt)
|
|
230
372
|
.option('--delete', 'Disable delete protection')
|
|
231
373
|
.option('--change', 'Disable change protection')
|
|
232
374
|
.action(async (configId, options) => {
|
|
233
375
|
try {
|
|
234
376
|
console.log('\n' + (0, colors_1.separator)());
|
|
235
|
-
console.log(colors.ui.title(
|
|
377
|
+
console.log(colors.ui.title(`Unprotect Profile ${configId}`));
|
|
236
378
|
console.log((0, colors_1.separator)());
|
|
237
379
|
if (!options.delete && !options.change) {
|
|
238
|
-
console.error(colors.status.error('\n
|
|
380
|
+
console.error(colors.status.error('\n Must specify at least one protection flag'));
|
|
239
381
|
console.log(colors.status.dim(' Use --delete and/or --change\n'));
|
|
240
382
|
process.exit(1);
|
|
241
383
|
}
|
|
242
384
|
const result = await client.protectEmbeddingConfig(configId, options.delete ? false : undefined, options.change ? false : undefined);
|
|
243
|
-
console.log('\n' + colors.status.success('
|
|
385
|
+
console.log('\n' + colors.status.success(' Protection disabled'));
|
|
244
386
|
const flags = [];
|
|
245
387
|
if (options.delete)
|
|
246
388
|
flags.push('delete-protection');
|
|
247
389
|
if (options.change)
|
|
248
390
|
flags.push('change-protection');
|
|
249
|
-
console.log(`\n ${colors.ui.key('
|
|
391
|
+
console.log(`\n ${colors.ui.key('Profile ID:')} ${colors.ui.value(configId)}`);
|
|
250
392
|
console.log(` ${colors.ui.key('Removed:')} ${colors.status.dim(flags.join(', '))}`);
|
|
251
393
|
console.log('\n' + (0, colors_1.separator)() + '\n');
|
|
252
394
|
}
|
|
253
395
|
catch (error) {
|
|
254
|
-
console.error(colors.status.error('
|
|
396
|
+
console.error(colors.status.error(' Failed to remove protection'));
|
|
255
397
|
console.error(colors.status.error(error.response?.data?.detail || error.message));
|
|
256
398
|
process.exit(1);
|
|
257
399
|
}
|
|
258
400
|
});
|
|
259
401
|
}
|
|
260
402
|
/**
|
|
261
|
-
* Activate an embedding
|
|
403
|
+
* Activate an embedding profile
|
|
262
404
|
*/
|
|
263
405
|
function createEmbeddingActivateCommand(client) {
|
|
264
406
|
return new commander_1.Command('activate')
|
|
265
|
-
.description('Activate an embedding
|
|
266
|
-
.argument('<config-id>', '
|
|
407
|
+
.description('Activate an embedding profile (with automatic protection)')
|
|
408
|
+
.argument('<config-id>', 'Profile ID', parseInt)
|
|
267
409
|
.option('--force', 'Force activation even with dimension mismatch (dangerous!)')
|
|
268
410
|
.action(async (configId, options) => {
|
|
269
411
|
try {
|
|
270
412
|
console.log('\n' + (0, colors_1.separator)());
|
|
271
|
-
console.log(colors.ui.title(
|
|
413
|
+
console.log(colors.ui.title(`Activate Profile ${configId}`));
|
|
272
414
|
console.log((0, colors_1.separator)());
|
|
273
415
|
if (options.force) {
|
|
274
|
-
console.log(colors.status.warning('\n
|
|
416
|
+
console.log(colors.status.warning('\n FORCE MODE: Bypassing dimension safety check'));
|
|
275
417
|
console.log(colors.status.dim(' This may break vector search if dimensions change!\n'));
|
|
276
418
|
}
|
|
277
|
-
console.log(colors.status.info('\nActivating
|
|
278
|
-
console.log(colors.status.dim('
|
|
279
|
-
console.log(colors.status.dim('
|
|
280
|
-
console.log(colors.status.dim('
|
|
419
|
+
console.log(colors.status.info('\nActivating profile...'));
|
|
420
|
+
console.log(colors.status.dim(' Unlocking current profile (change protection)'));
|
|
421
|
+
console.log(colors.status.dim(' Switching to new profile'));
|
|
422
|
+
console.log(colors.status.dim(' Locking new profile (delete + change protection)'));
|
|
281
423
|
const result = await client.activateEmbeddingConfig(configId, options.force);
|
|
282
|
-
console.log('\n' + colors.status.success('
|
|
283
|
-
console.log(`\n ${colors.ui.key('
|
|
424
|
+
console.log('\n' + colors.status.success(' Profile activated successfully'));
|
|
425
|
+
console.log(`\n ${colors.ui.key('Profile ID:')} ${colors.ui.value(result.config_id)}`);
|
|
284
426
|
console.log(` ${colors.ui.key('Provider:')} ${colors.ui.value(result.provider)}`);
|
|
285
427
|
if (result.model) {
|
|
286
428
|
console.log(` ${colors.ui.key('Model:')} ${colors.ui.value(result.model)}`);
|
|
@@ -288,12 +430,12 @@ function createEmbeddingActivateCommand(client) {
|
|
|
288
430
|
if (result.dimensions) {
|
|
289
431
|
console.log(` ${colors.ui.key('Dimensions:')} ${colors.ui.value(result.dimensions)}`);
|
|
290
432
|
}
|
|
291
|
-
console.log('\n' + colors.status.warning('
|
|
433
|
+
console.log('\n' + colors.status.warning(' Next step: Hot reload to apply changes'));
|
|
292
434
|
console.log(colors.status.dim(' Run: kg admin embedding reload\n'));
|
|
293
435
|
console.log((0, colors_1.separator)() + '\n');
|
|
294
436
|
}
|
|
295
437
|
catch (error) {
|
|
296
|
-
console.error(colors.status.error('
|
|
438
|
+
console.error(colors.status.error(' Failed to activate profile'));
|
|
297
439
|
console.error(colors.status.error(error.response?.data?.detail || error.message));
|
|
298
440
|
process.exit(1);
|
|
299
441
|
}
|
|
@@ -304,26 +446,26 @@ function createEmbeddingActivateCommand(client) {
|
|
|
304
446
|
*/
|
|
305
447
|
function createEmbeddingDeleteCommand(client) {
|
|
306
448
|
return new commander_1.Command('delete')
|
|
307
|
-
.description('Delete an embedding
|
|
308
|
-
.argument('<config-id>', '
|
|
449
|
+
.description('Delete an embedding profile')
|
|
450
|
+
.argument('<config-id>', 'Profile ID', parseInt)
|
|
309
451
|
.action(async (configId) => {
|
|
310
452
|
try {
|
|
311
453
|
console.log('\n' + (0, colors_1.separator)());
|
|
312
|
-
console.log(colors.ui.title(
|
|
454
|
+
console.log(colors.ui.title(`Delete Profile ${configId}`));
|
|
313
455
|
console.log((0, colors_1.separator)());
|
|
314
456
|
// Confirm deletion
|
|
315
|
-
const confirm = await (0, utils_1.prompt)(`\nDelete embedding
|
|
457
|
+
const confirm = await (0, utils_1.prompt)(`\nDelete embedding profile ${configId}? (yes/no): `);
|
|
316
458
|
if (confirm.toLowerCase() !== 'yes') {
|
|
317
459
|
console.log(colors.status.dim('Cancelled\n'));
|
|
318
460
|
process.exit(0);
|
|
319
461
|
}
|
|
320
462
|
const result = await client.deleteEmbeddingConfig(configId);
|
|
321
|
-
console.log('\n' + colors.status.success('
|
|
322
|
-
console.log(`\n ${colors.ui.key('
|
|
463
|
+
console.log('\n' + colors.status.success(' Profile deleted'));
|
|
464
|
+
console.log(`\n ${colors.ui.key('Profile ID:')} ${colors.ui.value(configId)}`);
|
|
323
465
|
console.log('\n' + (0, colors_1.separator)() + '\n');
|
|
324
466
|
}
|
|
325
467
|
catch (error) {
|
|
326
|
-
console.error(colors.status.error('
|
|
468
|
+
console.error(colors.status.error(' Failed to delete profile'));
|
|
327
469
|
console.error(colors.status.error(error.response?.data?.detail || error.message));
|
|
328
470
|
process.exit(1);
|
|
329
471
|
}
|
|
@@ -339,7 +481,7 @@ function createEmbeddingStatusCommand(client) {
|
|
|
339
481
|
.action(async (options) => {
|
|
340
482
|
try {
|
|
341
483
|
console.log((0, colors_1.separator)());
|
|
342
|
-
console.log(colors.ui.title('
|
|
484
|
+
console.log(colors.ui.title('Embedding Coverage Status'));
|
|
343
485
|
if (options.ontology) {
|
|
344
486
|
console.log(colors.status.dim(` Ontology: ${options.ontology}`));
|
|
345
487
|
}
|
|
@@ -349,52 +491,52 @@ function createEmbeddingStatusCommand(client) {
|
|
|
349
491
|
if (status.active_config) {
|
|
350
492
|
console.log();
|
|
351
493
|
console.log(colors.ui.header('Active Embedding Configuration:'));
|
|
352
|
-
console.log(` ${colors.ui.key('Provider:')} ${colors.ui.value(status.active_config.provider)}`);
|
|
353
|
-
console.log(` ${colors.ui.key('Model:')} ${colors.ui.value(status.active_config.model_name)}`);
|
|
354
|
-
console.log(` ${colors.ui.key('Dimensions:')} ${colors.ui.value(status.active_config.embedding_dimensions.toString())}`);
|
|
494
|
+
console.log(` ${colors.ui.key('Provider:')} ${colors.ui.value(status.active_config.provider || status.active_config.text_provider)}`);
|
|
495
|
+
console.log(` ${colors.ui.key('Model:')} ${colors.ui.value(status.active_config.model_name || status.active_config.text_model_name)}`);
|
|
496
|
+
console.log(` ${colors.ui.key('Dimensions:')} ${colors.ui.value((status.active_config.embedding_dimensions || status.active_config.text_dimensions).toString())}`);
|
|
355
497
|
}
|
|
356
498
|
// Concepts
|
|
357
499
|
console.log();
|
|
358
500
|
console.log(colors.ui.header('Concepts (AGE Graph Nodes):'));
|
|
359
501
|
console.log(` ${colors.ui.key('Total:')} ${colors.ui.value(status.concepts.total.toString())}`);
|
|
360
|
-
console.log(` ${colors.status.success('
|
|
502
|
+
console.log(` ${colors.status.success('With embeddings:')} ${colors.ui.value(status.concepts.with_embeddings.toString())} (${status.concepts.percentage}%)`);
|
|
361
503
|
if (status.concepts.without_embeddings > 0) {
|
|
362
|
-
console.log(` ${colors.status.warning('
|
|
504
|
+
console.log(` ${colors.status.warning('Without embeddings:')} ${colors.ui.value(status.concepts.without_embeddings.toString())}`);
|
|
363
505
|
}
|
|
364
506
|
if (status.concepts.incompatible_embeddings > 0) {
|
|
365
|
-
console.log(` ${colors.status.error('
|
|
507
|
+
console.log(` ${colors.status.error('Incompatible:')} ${colors.ui.value(status.concepts.incompatible_embeddings.toString())} (model/dimension mismatch)`);
|
|
366
508
|
}
|
|
367
509
|
// Sources
|
|
368
510
|
console.log();
|
|
369
511
|
console.log(colors.ui.header('Sources (Text Chunks):'));
|
|
370
512
|
console.log(` ${colors.ui.key('Total:')} ${colors.ui.value(status.sources.total.toString())}`);
|
|
371
|
-
console.log(` ${colors.status.success('
|
|
513
|
+
console.log(` ${colors.status.success('With embeddings:')} ${colors.ui.value(status.sources.with_embeddings.toString())} (${status.sources.percentage}%)`);
|
|
372
514
|
if (status.sources.without_embeddings > 0) {
|
|
373
|
-
console.log(` ${colors.status.warning('
|
|
515
|
+
console.log(` ${colors.status.warning('Without embeddings:')} ${colors.ui.value(status.sources.without_embeddings.toString())}`);
|
|
374
516
|
}
|
|
375
517
|
if (status.sources.stale_embeddings > 0) {
|
|
376
|
-
console.log(` ${colors.status.error('
|
|
518
|
+
console.log(` ${colors.status.error('Stale embeddings:')} ${colors.ui.value(status.sources.stale_embeddings.toString())} (hash mismatch)`);
|
|
377
519
|
}
|
|
378
520
|
if (status.sources.incompatible_embeddings > 0) {
|
|
379
|
-
console.log(` ${colors.status.error('
|
|
521
|
+
console.log(` ${colors.status.error('Incompatible:')} ${colors.ui.value(status.sources.incompatible_embeddings.toString())} (model/dimension mismatch)`);
|
|
380
522
|
}
|
|
381
523
|
// Vocabulary
|
|
382
524
|
console.log();
|
|
383
525
|
console.log(colors.ui.header('Vocabulary (Relationship Types):'));
|
|
384
526
|
console.log(` ${colors.ui.key('Total:')} ${colors.ui.value(status.vocabulary.total.toString())}`);
|
|
385
|
-
console.log(` ${colors.status.success('
|
|
527
|
+
console.log(` ${colors.status.success('With embeddings:')} ${colors.ui.value(status.vocabulary.with_embeddings.toString())} (${status.vocabulary.percentage}%)`);
|
|
386
528
|
if (status.vocabulary.without_embeddings > 0) {
|
|
387
|
-
console.log(` ${colors.status.warning('
|
|
529
|
+
console.log(` ${colors.status.warning('Without embeddings:')} ${colors.ui.value(status.vocabulary.without_embeddings.toString())}`);
|
|
388
530
|
}
|
|
389
531
|
if (status.vocabulary.incompatible_embeddings > 0) {
|
|
390
|
-
console.log(` ${colors.status.error('
|
|
532
|
+
console.log(` ${colors.status.error('Incompatible:')} ${colors.ui.value(status.vocabulary.incompatible_embeddings.toString())} (model/dimension mismatch)`);
|
|
391
533
|
}
|
|
392
|
-
// Images
|
|
534
|
+
// Images
|
|
393
535
|
if (status.images && status.images.total > 0) {
|
|
394
536
|
console.log();
|
|
395
537
|
console.log(colors.ui.header('Images:'));
|
|
396
538
|
console.log(` ${colors.ui.key('Total:')} ${colors.ui.value(status.images.total.toString())}`);
|
|
397
|
-
console.log(` ${colors.status.success('
|
|
539
|
+
console.log(` ${colors.status.success('With embeddings:')} ${colors.ui.value(status.images.with_embeddings.toString())} (${status.images.percentage}%)`);
|
|
398
540
|
}
|
|
399
541
|
else if (status.images && status.images.note) {
|
|
400
542
|
console.log();
|
|
@@ -406,19 +548,19 @@ function createEmbeddingStatusCommand(client) {
|
|
|
406
548
|
console.log((0, colors_1.separator)());
|
|
407
549
|
console.log(colors.ui.header('Overall Summary:'));
|
|
408
550
|
console.log(` ${colors.ui.key('Total Entities:')} ${colors.ui.value(status.summary.total_entities.toString())}`);
|
|
409
|
-
console.log(` ${colors.status.success('
|
|
551
|
+
console.log(` ${colors.status.success('With Embeddings:')} ${colors.ui.value(status.summary.total_with_embeddings.toString())} (${status.summary.overall_percentage}%)`);
|
|
410
552
|
if (status.summary.total_without_embeddings > 0) {
|
|
411
|
-
console.log(` ${colors.status.warning('
|
|
553
|
+
console.log(` ${colors.status.warning('Without Embeddings:')} ${colors.ui.value(status.summary.total_without_embeddings.toString())}`);
|
|
412
554
|
}
|
|
413
555
|
if (status.summary.total_incompatible > 0) {
|
|
414
|
-
console.log(` ${colors.status.error('
|
|
556
|
+
console.log(` ${colors.status.error('Incompatible:')} ${colors.ui.value(status.summary.total_incompatible.toString())} (requires regeneration)`);
|
|
415
557
|
}
|
|
416
558
|
console.log((0, colors_1.separator)());
|
|
417
559
|
console.log();
|
|
418
560
|
}
|
|
419
561
|
catch (error) {
|
|
420
562
|
console.error();
|
|
421
|
-
console.error(colors.status.error('
|
|
563
|
+
console.error(colors.status.error(' Failed to get embedding status'));
|
|
422
564
|
console.error(colors.status.dim(` ${error.message || error}`));
|
|
423
565
|
console.error();
|
|
424
566
|
process.exit(1);
|
|
@@ -447,7 +589,7 @@ function createEmbeddingRegenerateCommand(client) {
|
|
|
447
589
|
// If no --type provided, show help and exit
|
|
448
590
|
if (!options.type) {
|
|
449
591
|
console.log();
|
|
450
|
-
console.log(colors.status.warning('
|
|
592
|
+
console.log(colors.status.warning(' No --type specified'));
|
|
451
593
|
console.log();
|
|
452
594
|
console.log(colors.ui.header('Usage:'));
|
|
453
595
|
console.log(' kg admin embedding regenerate --type <type> [options]');
|
|
@@ -474,58 +616,49 @@ function createEmbeddingRegenerateCommand(client) {
|
|
|
474
616
|
}
|
|
475
617
|
// Normal regeneration flow
|
|
476
618
|
try {
|
|
477
|
-
// Validate embedding type
|
|
478
619
|
const validTypes = ['concept', 'source', 'vocabulary', 'all'];
|
|
479
620
|
const embeddingType = options.type;
|
|
480
621
|
if (!validTypes.includes(embeddingType)) {
|
|
481
622
|
console.error();
|
|
482
|
-
console.error(colors.status.error(
|
|
623
|
+
console.error(colors.status.error(` Invalid --type: ${embeddingType}`));
|
|
483
624
|
console.error(colors.status.dim(` Valid types: ${validTypes.join(', ')}`));
|
|
484
625
|
console.error();
|
|
485
626
|
process.exit(1);
|
|
486
627
|
}
|
|
487
|
-
// Validate flag combination
|
|
488
628
|
if (options.onlyMissing && options.onlyIncompatible) {
|
|
489
629
|
console.error();
|
|
490
|
-
console.error(colors.status.error('
|
|
630
|
+
console.error(colors.status.error(' Cannot use both --only-missing and --only-incompatible'));
|
|
491
631
|
console.error(colors.status.dim(' Choose one: missing (no embeddings) or incompatible (wrong model/dimensions)'));
|
|
492
632
|
console.error();
|
|
493
633
|
process.exit(1);
|
|
494
634
|
}
|
|
495
635
|
console.log((0, colors_1.separator)());
|
|
496
|
-
console.log(colors.ui.title(
|
|
636
|
+
console.log(colors.ui.title(`Regenerating ${embeddingType.charAt(0).toUpperCase() + embeddingType.slice(1)} Embeddings`));
|
|
497
637
|
console.log((0, colors_1.separator)());
|
|
498
638
|
const params = {
|
|
499
639
|
embedding_type: embeddingType,
|
|
500
640
|
only_missing: options.onlyMissing || false,
|
|
501
641
|
only_incompatible: options.onlyIncompatible || false
|
|
502
642
|
};
|
|
503
|
-
if (options.ontology)
|
|
643
|
+
if (options.ontology)
|
|
504
644
|
params.ontology = options.ontology;
|
|
505
|
-
|
|
506
|
-
if (options.limit) {
|
|
645
|
+
if (options.limit)
|
|
507
646
|
params.limit = options.limit;
|
|
508
|
-
}
|
|
509
647
|
console.log();
|
|
510
648
|
console.log(colors.status.info('Starting regeneration...'));
|
|
511
649
|
console.log(colors.status.dim(` Type: ${embeddingType}`));
|
|
512
|
-
if (options.ontology)
|
|
650
|
+
if (options.ontology)
|
|
513
651
|
console.log(colors.status.dim(` Ontology: ${options.ontology}`));
|
|
514
|
-
|
|
515
|
-
if (options.onlyMissing) {
|
|
652
|
+
if (options.onlyMissing)
|
|
516
653
|
console.log(colors.status.dim(' Mode: Only missing embeddings'));
|
|
517
|
-
|
|
518
|
-
if (options.onlyIncompatible) {
|
|
654
|
+
if (options.onlyIncompatible)
|
|
519
655
|
console.log(colors.status.dim(' Mode: Only incompatible embeddings (model migration)'));
|
|
520
|
-
|
|
521
|
-
if (options.limit) {
|
|
656
|
+
if (options.limit)
|
|
522
657
|
console.log(colors.status.dim(` Limit: ${options.limit} entities`));
|
|
523
|
-
}
|
|
524
658
|
console.log();
|
|
525
659
|
const result = await client.regenerateEmbeddings(params);
|
|
526
660
|
console.log((0, colors_1.separator)());
|
|
527
|
-
console.log(colors.status.success('
|
|
528
|
-
// Handle 'all' type response (has totals and per-type results)
|
|
661
|
+
console.log(colors.status.success(' Regeneration completed'));
|
|
529
662
|
if (embeddingType === 'all' && result.totals) {
|
|
530
663
|
console.log(` ${colors.stats.label('Total Processed:')} ${colors.stats.value(result.totals.processed_count.toString())} / ${result.totals.target_count}`);
|
|
531
664
|
if (result.totals.failed_count > 0) {
|
|
@@ -545,7 +678,6 @@ function createEmbeddingRegenerateCommand(client) {
|
|
|
545
678
|
}
|
|
546
679
|
}
|
|
547
680
|
else {
|
|
548
|
-
// Single type response
|
|
549
681
|
console.log(` ${colors.stats.label('Processed:')} ${colors.stats.value(result.processed_count.toString())} / ${result.target_count}`);
|
|
550
682
|
if (result.failed_count > 0) {
|
|
551
683
|
console.log(` ${colors.status.error('Failed:')} ${result.failed_count}`);
|
|
@@ -570,7 +702,7 @@ function createEmbeddingRegenerateCommand(client) {
|
|
|
570
702
|
}
|
|
571
703
|
catch (error) {
|
|
572
704
|
console.error();
|
|
573
|
-
console.error(colors.status.error('
|
|
705
|
+
console.error(colors.status.error(' Failed to regenerate embeddings'));
|
|
574
706
|
console.error(colors.status.dim(` ${error.message || error}`));
|
|
575
707
|
console.error();
|
|
576
708
|
process.exit(1);
|
|
@@ -583,9 +715,10 @@ function createEmbeddingRegenerateCommand(client) {
|
|
|
583
715
|
*/
|
|
584
716
|
function createEmbeddingCommand(client) {
|
|
585
717
|
const embeddingCommand = new commander_1.Command('embedding')
|
|
586
|
-
.description('Manage embedding model configuration
|
|
718
|
+
.description('Manage embedding profiles (text + image model configuration)');
|
|
587
719
|
embeddingCommand.addCommand(createEmbeddingListCommand(client));
|
|
588
720
|
embeddingCommand.addCommand(createEmbeddingCreateCommand(client));
|
|
721
|
+
embeddingCommand.addCommand(createEmbeddingExportCommand(client));
|
|
589
722
|
embeddingCommand.addCommand(createEmbeddingActivateCommand(client));
|
|
590
723
|
embeddingCommand.addCommand(createEmbeddingReloadCommand(client));
|
|
591
724
|
embeddingCommand.addCommand(createEmbeddingProtectCommand(client));
|