@qualcomm-ui/mdx-vite 2.5.2 → 2.5.4
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/dist/cli.js +558 -136
- package/dist/cli.js.map +4 -4
- package/dist/open-web-ui-knowledge/api.d.ts +153 -0
- package/dist/open-web-ui-knowledge/api.d.ts.map +1 -0
- package/dist/open-web-ui-knowledge/common.d.ts +0 -36
- package/dist/open-web-ui-knowledge/common.d.ts.map +1 -1
- package/dist/open-web-ui-knowledge/download-knowledge.d.ts.map +1 -1
- package/dist/open-web-ui-knowledge/generate-knowledge.d.ts.map +1 -1
- package/dist/open-web-ui-knowledge/knowledge-cleaner.d.ts +10 -0
- package/dist/open-web-ui-knowledge/knowledge-cleaner.d.ts.map +1 -0
- package/dist/open-web-ui-knowledge/upload-knowledge.d.ts.map +1 -1
- package/dist/tsbuildinfo +1 -1
- package/package.json +2 -2
package/dist/cli.js
CHANGED
|
@@ -5168,138 +5168,359 @@ function addGeneratePageMapCommand() {
|
|
|
5168
5168
|
import { mkdir, writeFile as writeFile2 } from "node:fs/promises";
|
|
5169
5169
|
import { resolve as resolve2 } from "node:path";
|
|
5170
5170
|
|
|
5171
|
-
// src/open-web-ui-knowledge/
|
|
5172
|
-
|
|
5173
|
-
|
|
5174
|
-
const options = program.optsWithGlobals();
|
|
5175
|
-
console.debug(options);
|
|
5176
|
-
if (options.env) {
|
|
5177
|
-
config({ path: options.env });
|
|
5178
|
-
} else {
|
|
5179
|
-
config();
|
|
5180
|
-
}
|
|
5181
|
-
}
|
|
5182
|
-
function getConfigFromEnv() {
|
|
5183
|
-
const openWebUiUrl = process.env.WEB_UI_URL;
|
|
5184
|
-
const openWebUiKey = process.env.WEB_UI_KEY;
|
|
5185
|
-
const knowledgeId = process.env.KNOWLEDGE_ID;
|
|
5186
|
-
if (!openWebUiUrl || !openWebUiKey || !knowledgeId) {
|
|
5187
|
-
throw new Error("WEB_UI_URL, WEB_UI_KEY, and KNOWLEDGE_ID must be set");
|
|
5188
|
-
}
|
|
5189
|
-
return {
|
|
5190
|
-
knowledgeId,
|
|
5191
|
-
webUiKey: openWebUiKey,
|
|
5192
|
-
webUiUrl: openWebUiUrl
|
|
5193
|
-
};
|
|
5171
|
+
// src/open-web-ui-knowledge/api.ts
|
|
5172
|
+
function isErrorResponse(response) {
|
|
5173
|
+
return typeof response === "object" && response !== null && "detail" in response;
|
|
5194
5174
|
}
|
|
5195
|
-
var
|
|
5175
|
+
var FilesApi = class {
|
|
5196
5176
|
config;
|
|
5197
|
-
knowledgeCache = null;
|
|
5198
5177
|
constructor(config2) {
|
|
5199
5178
|
this.config = config2;
|
|
5200
5179
|
}
|
|
5201
5180
|
get headers() {
|
|
5202
5181
|
return {
|
|
5203
|
-
Authorization: `Bearer ${this.config.
|
|
5182
|
+
Authorization: `Bearer ${this.config.apiKey}`
|
|
5204
5183
|
};
|
|
5205
5184
|
}
|
|
5206
|
-
|
|
5207
|
-
|
|
5208
|
-
|
|
5185
|
+
get jsonHeaders() {
|
|
5186
|
+
return {
|
|
5187
|
+
...this.headers,
|
|
5188
|
+
"Content-Type": "application/json"
|
|
5189
|
+
};
|
|
5190
|
+
}
|
|
5191
|
+
async handleResponse(response) {
|
|
5192
|
+
const data = await response.json();
|
|
5193
|
+
if (isErrorResponse(data)) {
|
|
5194
|
+
throw new Error(data.detail);
|
|
5195
|
+
}
|
|
5196
|
+
return data;
|
|
5197
|
+
}
|
|
5198
|
+
async upload(file, filename, options) {
|
|
5199
|
+
const formData = new FormData();
|
|
5200
|
+
let blob;
|
|
5201
|
+
if (file instanceof Blob) {
|
|
5202
|
+
blob = file;
|
|
5203
|
+
} else if (file instanceof ArrayBuffer) {
|
|
5204
|
+
blob = new Blob([file]);
|
|
5205
|
+
} else {
|
|
5206
|
+
const copy = new Uint8Array(file).buffer;
|
|
5207
|
+
blob = new Blob([copy]);
|
|
5208
|
+
}
|
|
5209
|
+
formData.append("file", blob, filename);
|
|
5210
|
+
if (options?.metadata) {
|
|
5211
|
+
formData.append("metadata", JSON.stringify(options.metadata));
|
|
5212
|
+
}
|
|
5213
|
+
const params = new URLSearchParams();
|
|
5214
|
+
if (options?.process !== void 0) {
|
|
5215
|
+
params.set("process", String(options.process));
|
|
5216
|
+
}
|
|
5217
|
+
if (options?.processInBackground !== void 0) {
|
|
5218
|
+
params.set("process_in_background", String(options.processInBackground));
|
|
5209
5219
|
}
|
|
5210
|
-
const
|
|
5211
|
-
|
|
5220
|
+
const url = `${this.config.baseUrl}/api/v1/files/${params.toString() ? `?${params}` : ""}`;
|
|
5221
|
+
const response = await fetch(url, {
|
|
5222
|
+
body: formData,
|
|
5223
|
+
headers: this.headers,
|
|
5224
|
+
method: "POST"
|
|
5225
|
+
});
|
|
5226
|
+
return this.handleResponse(response);
|
|
5227
|
+
}
|
|
5228
|
+
async list(includeContent = true) {
|
|
5229
|
+
const params = new URLSearchParams({ content: String(includeContent) });
|
|
5230
|
+
const response = await fetch(
|
|
5231
|
+
`${this.config.baseUrl}/api/v1/files/?${params}`,
|
|
5212
5232
|
{
|
|
5213
|
-
headers:
|
|
5214
|
-
...this.headers,
|
|
5215
|
-
Accept: "application/json"
|
|
5216
|
-
}
|
|
5233
|
+
headers: this.headers
|
|
5217
5234
|
}
|
|
5218
|
-
)
|
|
5219
|
-
|
|
5220
|
-
|
|
5221
|
-
|
|
5222
|
-
|
|
5235
|
+
);
|
|
5236
|
+
return this.handleResponse(response);
|
|
5237
|
+
}
|
|
5238
|
+
async search(pattern, includeContent = true) {
|
|
5239
|
+
const params = new URLSearchParams({
|
|
5240
|
+
content: String(includeContent),
|
|
5241
|
+
filename: pattern
|
|
5242
|
+
});
|
|
5243
|
+
const response = await fetch(
|
|
5244
|
+
`${this.config.baseUrl}/api/v1/files/search?${params}`,
|
|
5245
|
+
{ headers: this.headers }
|
|
5246
|
+
);
|
|
5247
|
+
if (response.status === 404) {
|
|
5248
|
+
return [];
|
|
5223
5249
|
}
|
|
5224
|
-
return this.
|
|
5250
|
+
return this.handleResponse(response);
|
|
5251
|
+
}
|
|
5252
|
+
async deleteAll() {
|
|
5253
|
+
const response = await fetch(`${this.config.baseUrl}/api/v1/files/all`, {
|
|
5254
|
+
headers: this.headers,
|
|
5255
|
+
method: "DELETE"
|
|
5256
|
+
});
|
|
5257
|
+
return this.handleResponse(response);
|
|
5258
|
+
}
|
|
5259
|
+
async getById(id) {
|
|
5260
|
+
const response = await fetch(`${this.config.baseUrl}/api/v1/files/${id}`, {
|
|
5261
|
+
headers: this.headers
|
|
5262
|
+
});
|
|
5263
|
+
return this.handleResponse(response);
|
|
5225
5264
|
}
|
|
5226
|
-
async
|
|
5227
|
-
const
|
|
5228
|
-
`${this.config.
|
|
5265
|
+
async getProcessStatus(id) {
|
|
5266
|
+
const response = await fetch(
|
|
5267
|
+
`${this.config.baseUrl}/api/v1/files/${id}/process/status`,
|
|
5268
|
+
{ headers: this.headers }
|
|
5269
|
+
);
|
|
5270
|
+
return this.handleResponse(response);
|
|
5271
|
+
}
|
|
5272
|
+
async waitForProcessing(id, options) {
|
|
5273
|
+
const maxAttempts = options?.maxAttempts ?? 120;
|
|
5274
|
+
const intervalMs = options?.intervalMs ?? 1e3;
|
|
5275
|
+
for (let i = 0; i < maxAttempts; i++) {
|
|
5276
|
+
const status = await this.getProcessStatus(id);
|
|
5277
|
+
if (status.status === "completed" || status.status === "failed") {
|
|
5278
|
+
return status;
|
|
5279
|
+
}
|
|
5280
|
+
await new Promise((resolve9) => setTimeout(resolve9, intervalMs));
|
|
5281
|
+
}
|
|
5282
|
+
throw new Error(`File processing timed out after ${maxAttempts} attempts`);
|
|
5283
|
+
}
|
|
5284
|
+
async getDataContent(id) {
|
|
5285
|
+
const response = await fetch(
|
|
5286
|
+
`${this.config.baseUrl}/api/v1/files/${id}/data/content`,
|
|
5287
|
+
{ headers: this.headers }
|
|
5288
|
+
);
|
|
5289
|
+
return this.handleResponse(response);
|
|
5290
|
+
}
|
|
5291
|
+
async updateDataContent(id, content) {
|
|
5292
|
+
const response = await fetch(
|
|
5293
|
+
`${this.config.baseUrl}/api/v1/files/${id}/data/content/update`,
|
|
5229
5294
|
{
|
|
5230
|
-
|
|
5231
|
-
|
|
5232
|
-
|
|
5233
|
-
}
|
|
5295
|
+
body: JSON.stringify({ content }),
|
|
5296
|
+
headers: this.jsonHeaders,
|
|
5297
|
+
method: "POST"
|
|
5234
5298
|
}
|
|
5235
|
-
)
|
|
5236
|
-
return
|
|
5299
|
+
);
|
|
5300
|
+
return this.handleResponse(response);
|
|
5237
5301
|
}
|
|
5238
|
-
async
|
|
5302
|
+
async getContent(id, asAttachment = false) {
|
|
5303
|
+
const params = new URLSearchParams({ attachment: String(asAttachment) });
|
|
5239
5304
|
return fetch(
|
|
5240
|
-
`${this.config.
|
|
5305
|
+
`${this.config.baseUrl}/api/v1/files/${id}/content?${params}`,
|
|
5241
5306
|
{
|
|
5242
|
-
|
|
5243
|
-
headers: {
|
|
5244
|
-
...this.headers,
|
|
5245
|
-
"Content-Type": "application/json"
|
|
5246
|
-
},
|
|
5247
|
-
method: "POST"
|
|
5307
|
+
headers: this.headers
|
|
5248
5308
|
}
|
|
5249
|
-
)
|
|
5309
|
+
);
|
|
5250
5310
|
}
|
|
5251
|
-
async
|
|
5252
|
-
|
|
5253
|
-
|
|
5254
|
-
|
|
5255
|
-
|
|
5256
|
-
|
|
5311
|
+
async getContentAsText(id) {
|
|
5312
|
+
const response = await this.getContent(id);
|
|
5313
|
+
if (!response.ok) {
|
|
5314
|
+
const error = await response.json();
|
|
5315
|
+
throw new Error(error.detail || "Failed to get file content");
|
|
5316
|
+
}
|
|
5317
|
+
return response.text();
|
|
5318
|
+
}
|
|
5319
|
+
async delete(id) {
|
|
5320
|
+
const response = await fetch(`${this.config.baseUrl}/api/v1/files/${id}`, {
|
|
5321
|
+
headers: this.headers,
|
|
5257
5322
|
method: "DELETE"
|
|
5258
|
-
})
|
|
5323
|
+
});
|
|
5324
|
+
return this.handleResponse(response);
|
|
5259
5325
|
}
|
|
5260
|
-
|
|
5261
|
-
|
|
5262
|
-
|
|
5263
|
-
|
|
5264
|
-
|
|
5265
|
-
body: formData,
|
|
5266
|
-
headers: {
|
|
5267
|
-
...this.headers,
|
|
5268
|
-
Accept: "application/json"
|
|
5269
|
-
},
|
|
5270
|
-
method: "POST"
|
|
5271
|
-
}).then((res) => res.json());
|
|
5326
|
+
};
|
|
5327
|
+
var KnowledgeApi = class {
|
|
5328
|
+
config;
|
|
5329
|
+
constructor(config2) {
|
|
5330
|
+
this.config = config2;
|
|
5272
5331
|
}
|
|
5273
|
-
|
|
5274
|
-
return
|
|
5275
|
-
|
|
5332
|
+
get headers() {
|
|
5333
|
+
return {
|
|
5334
|
+
Authorization: `Bearer ${this.config.apiKey}`
|
|
5335
|
+
};
|
|
5336
|
+
}
|
|
5337
|
+
get jsonHeaders() {
|
|
5338
|
+
return {
|
|
5339
|
+
...this.headers,
|
|
5340
|
+
"Content-Type": "application/json"
|
|
5341
|
+
};
|
|
5342
|
+
}
|
|
5343
|
+
async handleResponse(response) {
|
|
5344
|
+
const data = await response.json();
|
|
5345
|
+
if (isErrorResponse(data)) {
|
|
5346
|
+
throw new Error(data.detail);
|
|
5347
|
+
}
|
|
5348
|
+
return data;
|
|
5349
|
+
}
|
|
5350
|
+
async list() {
|
|
5351
|
+
const response = await fetch(`${this.config.baseUrl}/api/v1/knowledge/`, {
|
|
5352
|
+
headers: this.headers
|
|
5353
|
+
});
|
|
5354
|
+
return this.handleResponse(response);
|
|
5355
|
+
}
|
|
5356
|
+
async listWritable() {
|
|
5357
|
+
const response = await fetch(
|
|
5358
|
+
`${this.config.baseUrl}/api/v1/knowledge/list`,
|
|
5359
|
+
{
|
|
5360
|
+
headers: this.headers
|
|
5361
|
+
}
|
|
5362
|
+
);
|
|
5363
|
+
return this.handleResponse(response);
|
|
5364
|
+
}
|
|
5365
|
+
async create(form) {
|
|
5366
|
+
const response = await fetch(
|
|
5367
|
+
`${this.config.baseUrl}/api/v1/knowledge/create`,
|
|
5368
|
+
{
|
|
5369
|
+
body: JSON.stringify(form),
|
|
5370
|
+
headers: this.jsonHeaders,
|
|
5371
|
+
method: "POST"
|
|
5372
|
+
}
|
|
5373
|
+
);
|
|
5374
|
+
return this.handleResponse(response);
|
|
5375
|
+
}
|
|
5376
|
+
async reindex() {
|
|
5377
|
+
const response = await fetch(
|
|
5378
|
+
`${this.config.baseUrl}/api/v1/knowledge/reindex`,
|
|
5379
|
+
{
|
|
5380
|
+
headers: this.jsonHeaders,
|
|
5381
|
+
method: "POST"
|
|
5382
|
+
}
|
|
5383
|
+
);
|
|
5384
|
+
return this.handleResponse(response);
|
|
5385
|
+
}
|
|
5386
|
+
async getById(id) {
|
|
5387
|
+
const response = await fetch(
|
|
5388
|
+
`${this.config.baseUrl}/api/v1/knowledge/${id}`,
|
|
5389
|
+
{
|
|
5390
|
+
headers: this.headers
|
|
5391
|
+
}
|
|
5392
|
+
);
|
|
5393
|
+
return this.handleResponse(response);
|
|
5394
|
+
}
|
|
5395
|
+
async update(id, form) {
|
|
5396
|
+
const response = await fetch(
|
|
5397
|
+
`${this.config.baseUrl}/api/v1/knowledge/${id}/update`,
|
|
5398
|
+
{
|
|
5399
|
+
body: JSON.stringify(form),
|
|
5400
|
+
headers: this.jsonHeaders,
|
|
5401
|
+
method: "POST"
|
|
5402
|
+
}
|
|
5403
|
+
);
|
|
5404
|
+
return this.handleResponse(response);
|
|
5405
|
+
}
|
|
5406
|
+
async addFile(knowledgeId, fileId) {
|
|
5407
|
+
const response = await fetch(
|
|
5408
|
+
`${this.config.baseUrl}/api/v1/knowledge/${knowledgeId}/file/add`,
|
|
5409
|
+
{
|
|
5410
|
+
body: JSON.stringify({ file_id: fileId }),
|
|
5411
|
+
headers: this.jsonHeaders,
|
|
5412
|
+
method: "POST"
|
|
5413
|
+
}
|
|
5414
|
+
);
|
|
5415
|
+
return this.handleResponse(response);
|
|
5416
|
+
}
|
|
5417
|
+
async updateFile(knowledgeId, fileId) {
|
|
5418
|
+
const response = await fetch(
|
|
5419
|
+
`${this.config.baseUrl}/api/v1/knowledge/${knowledgeId}/file/update`,
|
|
5276
5420
|
{
|
|
5277
5421
|
body: JSON.stringify({ file_id: fileId }),
|
|
5278
|
-
headers:
|
|
5279
|
-
|
|
5280
|
-
|
|
5281
|
-
|
|
5422
|
+
headers: this.jsonHeaders,
|
|
5423
|
+
method: "POST"
|
|
5424
|
+
}
|
|
5425
|
+
);
|
|
5426
|
+
return this.handleResponse(response);
|
|
5427
|
+
}
|
|
5428
|
+
async removeFile(knowledgeId, fileId, deleteFile = true) {
|
|
5429
|
+
const params = new URLSearchParams({ delete_file: String(deleteFile) });
|
|
5430
|
+
const response = await fetch(
|
|
5431
|
+
`${this.config.baseUrl}/api/v1/knowledge/${knowledgeId}/file/remove?${params}`,
|
|
5432
|
+
{
|
|
5433
|
+
body: JSON.stringify({ file_id: fileId }),
|
|
5434
|
+
headers: this.jsonHeaders,
|
|
5435
|
+
method: "POST"
|
|
5436
|
+
}
|
|
5437
|
+
);
|
|
5438
|
+
return this.handleResponse(response);
|
|
5439
|
+
}
|
|
5440
|
+
async delete(id) {
|
|
5441
|
+
const response = await fetch(
|
|
5442
|
+
`${this.config.baseUrl}/api/v1/knowledge/${id}/delete`,
|
|
5443
|
+
{
|
|
5444
|
+
headers: this.headers,
|
|
5445
|
+
method: "DELETE"
|
|
5446
|
+
}
|
|
5447
|
+
);
|
|
5448
|
+
return this.handleResponse(response);
|
|
5449
|
+
}
|
|
5450
|
+
async reset(id) {
|
|
5451
|
+
const response = await fetch(
|
|
5452
|
+
`${this.config.baseUrl}/api/v1/knowledge/${id}/reset`,
|
|
5453
|
+
{
|
|
5454
|
+
headers: this.jsonHeaders,
|
|
5455
|
+
method: "POST"
|
|
5456
|
+
}
|
|
5457
|
+
);
|
|
5458
|
+
return this.handleResponse(response);
|
|
5459
|
+
}
|
|
5460
|
+
async addFilesBatch(knowledgeId, fileIds) {
|
|
5461
|
+
const response = await fetch(
|
|
5462
|
+
`${this.config.baseUrl}/api/v1/knowledge/${knowledgeId}/files/batch/add`,
|
|
5463
|
+
{
|
|
5464
|
+
body: JSON.stringify(fileIds.map((file_id) => ({ file_id }))),
|
|
5465
|
+
headers: this.jsonHeaders,
|
|
5282
5466
|
method: "POST"
|
|
5283
5467
|
}
|
|
5284
|
-
)
|
|
5468
|
+
);
|
|
5469
|
+
return this.handleResponse(response);
|
|
5285
5470
|
}
|
|
5286
5471
|
};
|
|
5287
5472
|
|
|
5473
|
+
// src/open-web-ui-knowledge/common.ts
|
|
5474
|
+
import { config } from "dotenv";
|
|
5475
|
+
function loadEnv() {
|
|
5476
|
+
const options = program.optsWithGlobals();
|
|
5477
|
+
console.debug(options);
|
|
5478
|
+
if (options.env) {
|
|
5479
|
+
config({ path: options.env });
|
|
5480
|
+
} else {
|
|
5481
|
+
config();
|
|
5482
|
+
}
|
|
5483
|
+
}
|
|
5484
|
+
function getConfigFromEnv() {
|
|
5485
|
+
const openWebUiUrl = process.env.WEB_UI_URL;
|
|
5486
|
+
const openWebUiKey = process.env.WEB_UI_KEY;
|
|
5487
|
+
const knowledgeId = process.env.KNOWLEDGE_ID;
|
|
5488
|
+
if (!openWebUiUrl || !openWebUiKey || !knowledgeId) {
|
|
5489
|
+
throw new Error("WEB_UI_URL, WEB_UI_KEY, and KNOWLEDGE_ID must be set");
|
|
5490
|
+
}
|
|
5491
|
+
return {
|
|
5492
|
+
knowledgeId,
|
|
5493
|
+
webUiKey: openWebUiKey,
|
|
5494
|
+
webUiUrl: openWebUiUrl
|
|
5495
|
+
};
|
|
5496
|
+
}
|
|
5497
|
+
|
|
5288
5498
|
// src/open-web-ui-knowledge/download-knowledge.ts
|
|
5289
5499
|
function addDownloadKnowledgeCommand() {
|
|
5290
5500
|
program.command("download-knowledge").description("Download files from an Open Web UI knowledge base").requiredOption("-o, --output-dir <outputDir>", "Folder path").action(async (opts) => {
|
|
5291
5501
|
loadEnv();
|
|
5292
5502
|
await mkdir(opts.outputDir, { recursive: true }).catch();
|
|
5293
|
-
const
|
|
5294
|
-
const
|
|
5295
|
-
|
|
5296
|
-
|
|
5297
|
-
|
|
5298
|
-
|
|
5299
|
-
|
|
5300
|
-
|
|
5301
|
-
|
|
5302
|
-
|
|
5503
|
+
const config2 = getConfigFromEnv();
|
|
5504
|
+
const apiConfig = { apiKey: config2.webUiKey, baseUrl: config2.webUiUrl };
|
|
5505
|
+
const knowledgeApi = new KnowledgeApi(apiConfig);
|
|
5506
|
+
const filesApi = new FilesApi(apiConfig);
|
|
5507
|
+
const knowledge = await knowledgeApi.getById(config2.knowledgeId);
|
|
5508
|
+
for (const file of knowledge.files ?? []) {
|
|
5509
|
+
const fileName = file.meta?.name;
|
|
5510
|
+
if (!fileName) {
|
|
5511
|
+
continue;
|
|
5512
|
+
}
|
|
5513
|
+
try {
|
|
5514
|
+
const content = await filesApi.getDataContent(file.id);
|
|
5515
|
+
if (content?.content) {
|
|
5516
|
+
await writeFile2(
|
|
5517
|
+
resolve2(opts.outputDir, fileName),
|
|
5518
|
+
content.content,
|
|
5519
|
+
"utf-8"
|
|
5520
|
+
);
|
|
5521
|
+
}
|
|
5522
|
+
} catch {
|
|
5523
|
+
console.warn(`Failed to download ${fileName}`);
|
|
5303
5524
|
}
|
|
5304
5525
|
}
|
|
5305
5526
|
});
|
|
@@ -5657,6 +5878,12 @@ var replaceNpmInstallTabs = () => {
|
|
|
5657
5878
|
done();
|
|
5658
5879
|
};
|
|
5659
5880
|
};
|
|
5881
|
+
function getPath(obj, path) {
|
|
5882
|
+
return path.split(".").reduce(
|
|
5883
|
+
(acc, key) => acc && typeof acc === "object" ? acc[key] : void 0,
|
|
5884
|
+
obj
|
|
5885
|
+
);
|
|
5886
|
+
}
|
|
5660
5887
|
var KnowledgeGenerator = class {
|
|
5661
5888
|
config;
|
|
5662
5889
|
docProps = null;
|
|
@@ -5919,6 +6146,69 @@ ${codeText}
|
|
|
5919
6146
|
required: extractRequired(propInfo, isPartial) || void 0
|
|
5920
6147
|
};
|
|
5921
6148
|
}
|
|
6149
|
+
/**
|
|
6150
|
+
* Creates a remark plugin that replaces TypeDocProps JSX elements with JSON
|
|
6151
|
+
* code blocks containing component prop documentation.
|
|
6152
|
+
*/
|
|
6153
|
+
async replaceThemeNodes() {
|
|
6154
|
+
let themes = null;
|
|
6155
|
+
try {
|
|
6156
|
+
themes = await import("@qualcomm-ui/tailwind-plugin/theme");
|
|
6157
|
+
} catch {
|
|
6158
|
+
return () => {
|
|
6159
|
+
};
|
|
6160
|
+
}
|
|
6161
|
+
const handlers = {
|
|
6162
|
+
ColorTable: (node) => {
|
|
6163
|
+
const path = this.getAttrExpression(node, "data");
|
|
6164
|
+
return path && getPath(themes, path);
|
|
6165
|
+
},
|
|
6166
|
+
FontTable: (node) => {
|
|
6167
|
+
const path = this.getAttrExpression(node, "data");
|
|
6168
|
+
return path && getPath(themes, path);
|
|
6169
|
+
},
|
|
6170
|
+
ThemePropertyTable: (node) => {
|
|
6171
|
+
const path = this.getAttrExpression(node, "data");
|
|
6172
|
+
const property = this.getAttrExpression(node, "cssProperty");
|
|
6173
|
+
const data = path && getPath(themes, path);
|
|
6174
|
+
return path && property ? { cssPropertyName: property, data } : void 0;
|
|
6175
|
+
}
|
|
6176
|
+
};
|
|
6177
|
+
return () => (tree, _file, done) => {
|
|
6178
|
+
visit7(tree, "mdxJsxFlowElement", (node) => {
|
|
6179
|
+
const handler = node.name && handlers[node.name];
|
|
6180
|
+
if (!handler) {
|
|
6181
|
+
return;
|
|
6182
|
+
}
|
|
6183
|
+
const data = handler(node);
|
|
6184
|
+
if (!data) {
|
|
6185
|
+
console.warn(`No theme data for ${node.name}`);
|
|
6186
|
+
return;
|
|
6187
|
+
}
|
|
6188
|
+
Object.assign(node, {
|
|
6189
|
+
lang: "json",
|
|
6190
|
+
meta: null,
|
|
6191
|
+
type: "code",
|
|
6192
|
+
value: JSON.stringify(data, null, 2)
|
|
6193
|
+
});
|
|
6194
|
+
});
|
|
6195
|
+
done();
|
|
6196
|
+
};
|
|
6197
|
+
}
|
|
6198
|
+
getAttrExpression(node, name) {
|
|
6199
|
+
const attr = node.attributes?.find(
|
|
6200
|
+
(a) => a.type === "mdxJsxAttribute" && a.name === name
|
|
6201
|
+
);
|
|
6202
|
+
if (!attr?.value) {
|
|
6203
|
+
return null;
|
|
6204
|
+
}
|
|
6205
|
+
if (typeof attr.value === "string") {
|
|
6206
|
+
return attr.value;
|
|
6207
|
+
} else if (typeof attr.value === "object" && "value" in attr.value) {
|
|
6208
|
+
return attr.value.value;
|
|
6209
|
+
}
|
|
6210
|
+
return null;
|
|
6211
|
+
}
|
|
5922
6212
|
/**
|
|
5923
6213
|
* Creates a remark plugin that replaces TypeDocProps JSX elements with JSON
|
|
5924
6214
|
* code blocks containing component prop documentation.
|
|
@@ -6088,7 +6378,7 @@ ${codeText}
|
|
|
6088
6378
|
/\[([^\]]+)\]\(\.\/#([^)]+)\)/g,
|
|
6089
6379
|
(_, text, anchor) => pageUrl && this.config.outputMode === "per-page" ? `[${text}](${pageUrl}#${anchor})` : text
|
|
6090
6380
|
);
|
|
6091
|
-
const processor = unified4().use(remarkParse4).use(remarkMdx3).use(this.replaceTypeDocProps()).use(this.replaceDemos(demosFolder, demoFiles)).use(remarkStringify3);
|
|
6381
|
+
const processor = unified4().use(remarkParse4).use(remarkMdx3).use(this.replaceTypeDocProps()).use(await this.replaceThemeNodes()).use(this.replaceDemos(demosFolder, demoFiles)).use(remarkStringify3);
|
|
6092
6382
|
const processed = await processor.process(processedContent);
|
|
6093
6383
|
processedContent = String(processed);
|
|
6094
6384
|
processedContent = processedContent.replace(/\n\s*\n\s*\n/g, "\n\n");
|
|
@@ -6278,29 +6568,76 @@ function addGenerateKnowledgeCommand() {
|
|
|
6278
6568
|
|
|
6279
6569
|
// src/open-web-ui-knowledge/upload-knowledge.ts
|
|
6280
6570
|
import { createHash as createHash2 } from "node:crypto";
|
|
6571
|
+
import { writeFileSync } from "node:fs";
|
|
6281
6572
|
import { access as access2, readdir as readdir2, readFile as readFile2, stat as stat2 } from "node:fs/promises";
|
|
6282
6573
|
import { resolve as resolve6 } from "node:path";
|
|
6283
6574
|
import { setTimeout as setTimeout2 } from "node:timers/promises";
|
|
6284
6575
|
import ora from "ora";
|
|
6576
|
+
|
|
6577
|
+
// src/open-web-ui-knowledge/knowledge-cleaner.ts
|
|
6578
|
+
var KnowledgeCleaner = class {
|
|
6579
|
+
filesApi;
|
|
6580
|
+
knowledgeApi;
|
|
6581
|
+
constructor(config2) {
|
|
6582
|
+
const apiConfig = {
|
|
6583
|
+
apiKey: config2.webUiKey,
|
|
6584
|
+
baseUrl: config2.webUiUrl
|
|
6585
|
+
};
|
|
6586
|
+
this.filesApi = new FilesApi(apiConfig);
|
|
6587
|
+
this.knowledgeApi = new KnowledgeApi(apiConfig);
|
|
6588
|
+
}
|
|
6589
|
+
async cleanUpOrphanedFiles() {
|
|
6590
|
+
const files = await this.filesApi.list();
|
|
6591
|
+
const knowledgeBases = await this.knowledgeApi.list();
|
|
6592
|
+
const knowledgeIds = knowledgeBases.map((k) => k.id);
|
|
6593
|
+
for (const file of files) {
|
|
6594
|
+
const collectionName = file.meta?.collection_name;
|
|
6595
|
+
if (collectionName && !knowledgeIds.includes(collectionName)) {
|
|
6596
|
+
await this.filesApi.delete(file.id);
|
|
6597
|
+
} else if (file.data?.status === "failed") {
|
|
6598
|
+
await this.filesApi.delete(file.id);
|
|
6599
|
+
}
|
|
6600
|
+
}
|
|
6601
|
+
}
|
|
6602
|
+
};
|
|
6603
|
+
|
|
6604
|
+
// src/open-web-ui-knowledge/upload-knowledge.ts
|
|
6605
|
+
function toKnowledgeFile(file) {
|
|
6606
|
+
return {
|
|
6607
|
+
id: file.id,
|
|
6608
|
+
meta: { name: file.meta?.name }
|
|
6609
|
+
};
|
|
6610
|
+
}
|
|
6285
6611
|
function calculateFileHash(fileData) {
|
|
6286
6612
|
const normalized = fileData.normalize("NFC").replace(/\r\n/g, "\n").replace(/\r/g, "\n").replace(/\n+$/, "");
|
|
6287
6613
|
return createHash2("sha256").update(normalized).digest("hex");
|
|
6288
6614
|
}
|
|
6289
6615
|
var Uploader = class {
|
|
6290
6616
|
config;
|
|
6291
|
-
|
|
6617
|
+
knowledgeApi;
|
|
6618
|
+
filesApi;
|
|
6292
6619
|
fileHashCache = /* @__PURE__ */ new Map();
|
|
6293
6620
|
knowledgeFilesCache = null;
|
|
6621
|
+
cleaner;
|
|
6294
6622
|
constructor(config2) {
|
|
6295
6623
|
this.config = config2;
|
|
6296
|
-
|
|
6624
|
+
const apiConfig = {
|
|
6625
|
+
apiKey: config2.webUiKey,
|
|
6626
|
+
baseUrl: config2.webUiUrl
|
|
6627
|
+
};
|
|
6628
|
+
this.knowledgeApi = new KnowledgeApi(apiConfig);
|
|
6629
|
+
this.filesApi = new FilesApi(apiConfig);
|
|
6630
|
+
this.cleaner = new KnowledgeCleaner(config2);
|
|
6297
6631
|
}
|
|
6298
6632
|
async buildHashCache(files) {
|
|
6299
6633
|
const results = await Promise.allSettled(
|
|
6300
6634
|
files.map(async (f) => {
|
|
6301
|
-
|
|
6302
|
-
|
|
6303
|
-
|
|
6635
|
+
try {
|
|
6636
|
+
const content = await this.filesApi.getDataContent(f.id);
|
|
6637
|
+
if (content?.content) {
|
|
6638
|
+
this.fileHashCache.set(f.id, calculateFileHash(content.content));
|
|
6639
|
+
}
|
|
6640
|
+
} catch {
|
|
6304
6641
|
}
|
|
6305
6642
|
})
|
|
6306
6643
|
);
|
|
@@ -6313,11 +6650,11 @@ var Uploader = class {
|
|
|
6313
6650
|
const spinner = ora(`File changed, deleting ${fileName}`).start();
|
|
6314
6651
|
for (let i = 0; i < maxAttempts; i++) {
|
|
6315
6652
|
this.knowledgeFilesCache = null;
|
|
6316
|
-
const knowledge = await this.
|
|
6653
|
+
const knowledge = await this.knowledgeApi.getById(this.config.knowledgeId);
|
|
6317
6654
|
const stillExists = (knowledge.files ?? []).some((f) => f.id === fileId);
|
|
6318
6655
|
if (!stillExists) {
|
|
6319
6656
|
this.fileHashCache.delete(fileId);
|
|
6320
|
-
spinner.succeed(`File ${fileId}
|
|
6657
|
+
spinner.succeed(`File deleted: ${fileId}`);
|
|
6321
6658
|
return true;
|
|
6322
6659
|
}
|
|
6323
6660
|
await setTimeout2(100 * (i + 1));
|
|
@@ -6332,10 +6669,19 @@ var Uploader = class {
|
|
|
6332
6669
|
if (result.success) {
|
|
6333
6670
|
return result;
|
|
6334
6671
|
}
|
|
6335
|
-
if (result.
|
|
6672
|
+
if (result.error?.detail?.includes("Duplicate content detected")) {
|
|
6336
6673
|
console.warn(
|
|
6337
6674
|
`Duplicate content: ${name} is already in knowledge base, skipping`
|
|
6338
6675
|
);
|
|
6676
|
+
if (result.error.fileId) {
|
|
6677
|
+
try {
|
|
6678
|
+
console.debug(`Removing duplicate file: ${result.error.fileId}`);
|
|
6679
|
+
await this.filesApi.delete(result.error.fileId);
|
|
6680
|
+
await this.waitForFileDeletion(result.error.fileId, name);
|
|
6681
|
+
} catch (e) {
|
|
6682
|
+
console.debug("Failed to remove duplicate file", e);
|
|
6683
|
+
}
|
|
6684
|
+
}
|
|
6339
6685
|
return { skipped: true, success: true };
|
|
6340
6686
|
}
|
|
6341
6687
|
if (attempt < maxRetries - 1) {
|
|
@@ -6349,11 +6695,6 @@ var Uploader = class {
|
|
|
6349
6695
|
console.debug(`Failed to upload ${name}`);
|
|
6350
6696
|
return { success: false };
|
|
6351
6697
|
}
|
|
6352
|
-
get headers() {
|
|
6353
|
-
return {
|
|
6354
|
-
Authorization: `Bearer ${this.config.webUiKey}`
|
|
6355
|
-
};
|
|
6356
|
-
}
|
|
6357
6698
|
async uploadDirectory() {
|
|
6358
6699
|
const fileNames = await readdir2(this.config.knowledgeFilePath);
|
|
6359
6700
|
const files = await Promise.all(
|
|
@@ -6365,8 +6706,8 @@ var Uploader = class {
|
|
|
6365
6706
|
name
|
|
6366
6707
|
}))
|
|
6367
6708
|
);
|
|
6368
|
-
const knowledge = await this.
|
|
6369
|
-
this.knowledgeFilesCache = knowledge.files ?? [];
|
|
6709
|
+
const knowledge = await this.knowledgeApi.getById(this.config.knowledgeId);
|
|
6710
|
+
this.knowledgeFilesCache = (knowledge.files ?? []).map(toKnowledgeFile);
|
|
6370
6711
|
await this.buildHashCache(this.knowledgeFilesCache);
|
|
6371
6712
|
let skippedCount = 0;
|
|
6372
6713
|
let successCount = 0;
|
|
@@ -6405,27 +6746,59 @@ var Uploader = class {
|
|
|
6405
6746
|
}
|
|
6406
6747
|
}
|
|
6407
6748
|
if (knowledgeFile) {
|
|
6408
|
-
|
|
6409
|
-
|
|
6749
|
+
try {
|
|
6750
|
+
const fileId = knowledgeFile.id;
|
|
6751
|
+
const fileString = await readFile2(
|
|
6752
|
+
resolve6(this.config.knowledgeFilePath, name),
|
|
6753
|
+
"utf-8"
|
|
6754
|
+
);
|
|
6755
|
+
const spinner2 = ora(`Updating ${name}`).start();
|
|
6756
|
+
await this.filesApi.updateDataContent(fileId, fileString);
|
|
6757
|
+
await this.knowledgeApi.updateFile(this.config.knowledgeId, fileId);
|
|
6758
|
+
spinner2.succeed(`Updated ${name}`);
|
|
6759
|
+
return { success: true };
|
|
6760
|
+
} catch (e) {
|
|
6761
|
+
console.warn(`Failed to update existing file ${name}:`, e);
|
|
6762
|
+
return { success: false };
|
|
6763
|
+
}
|
|
6410
6764
|
}
|
|
6411
6765
|
const spinner = ora(`Uploading ${name}`).start();
|
|
6412
6766
|
const fileBuffer = await readFile2(
|
|
6413
6767
|
resolve6(this.config.knowledgeFilePath, name)
|
|
6414
6768
|
);
|
|
6415
|
-
|
|
6416
|
-
|
|
6769
|
+
let uploadedFileId = void 0;
|
|
6770
|
+
try {
|
|
6771
|
+
const uploadResponse = await this.filesApi.upload(fileBuffer, name, {
|
|
6772
|
+
processInBackground: false
|
|
6773
|
+
});
|
|
6774
|
+
uploadedFileId = uploadResponse.id;
|
|
6775
|
+
if (!uploadResponse.id || !uploadResponse.filename) {
|
|
6776
|
+
spinner.fail(`Error uploading ${name}`);
|
|
6777
|
+
return {
|
|
6778
|
+
error: { fileId: uploadResponse.id, uploadResponse },
|
|
6779
|
+
success: false
|
|
6780
|
+
};
|
|
6781
|
+
}
|
|
6782
|
+
spinner.text = `Associating ${name} with knowledge base`;
|
|
6783
|
+
const addResponse = await this.knowledgeApi.addFile(
|
|
6784
|
+
this.config.knowledgeId,
|
|
6785
|
+
uploadResponse.id
|
|
6786
|
+
);
|
|
6787
|
+
if (addResponse.name) {
|
|
6788
|
+
spinner.succeed(`${name} associated with knowledge base`);
|
|
6789
|
+
this.fileHashCache.set(uploadResponse.id, contentHash);
|
|
6790
|
+
return { success: true };
|
|
6791
|
+
} else {
|
|
6792
|
+
spinner.stop();
|
|
6793
|
+
return {
|
|
6794
|
+
error: { addResponse, fileId: uploadResponse.id },
|
|
6795
|
+
success: false
|
|
6796
|
+
};
|
|
6797
|
+
}
|
|
6798
|
+
} catch (e) {
|
|
6417
6799
|
spinner.fail(`Error uploading ${name}`);
|
|
6418
|
-
|
|
6419
|
-
|
|
6420
|
-
spinner.text = `Associating ${name} with knowledge base`;
|
|
6421
|
-
const addResponse = await this.api.associateFile(uploadResponse.id);
|
|
6422
|
-
if (addResponse.name) {
|
|
6423
|
-
spinner.succeed(`${name} associated with knowledge base`);
|
|
6424
|
-
this.fileHashCache.set(uploadResponse.id, contentHash);
|
|
6425
|
-
return { success: true };
|
|
6426
|
-
} else {
|
|
6427
|
-
spinner.stop();
|
|
6428
|
-
return { response: addResponse, success: false };
|
|
6800
|
+
const detail = e instanceof Error ? e.message : String(e);
|
|
6801
|
+
return { error: { detail, fileId: uploadedFileId }, success: false };
|
|
6429
6802
|
}
|
|
6430
6803
|
}
|
|
6431
6804
|
async uploadKnowledge() {
|
|
@@ -6437,28 +6810,77 @@ var Uploader = class {
|
|
|
6437
6810
|
if (stats.isDirectory()) {
|
|
6438
6811
|
return this.uploadDirectory();
|
|
6439
6812
|
} else {
|
|
6813
|
+
console.error("Not a directory, can't upload.");
|
|
6440
6814
|
}
|
|
6441
6815
|
}
|
|
6442
6816
|
};
|
|
6443
6817
|
function addUploadKnowledgeCommand() {
|
|
6444
|
-
|
|
6445
|
-
"--force",
|
|
6446
|
-
"force upload files, even if their contents have not changed"
|
|
6447
|
-
).action(async (options) => {
|
|
6448
|
-
loadEnv();
|
|
6818
|
+
function getUploader(knowledgePath, forceUpload) {
|
|
6449
6819
|
const sharedConfig = getConfigFromEnv();
|
|
6450
|
-
const knowledgeFilePath =
|
|
6820
|
+
const knowledgeFilePath = knowledgePath || process.env.KNOWLEDGE_OUTPUT_PATH;
|
|
6451
6821
|
if (!knowledgeFilePath) {
|
|
6452
6822
|
throw new Error(
|
|
6453
6823
|
"KNOWLEDGE_FILE_PATH must be set or provided as the --path option"
|
|
6454
6824
|
);
|
|
6455
6825
|
}
|
|
6456
|
-
|
|
6826
|
+
return new Uploader({
|
|
6457
6827
|
...sharedConfig,
|
|
6458
|
-
force:
|
|
6828
|
+
force: forceUpload,
|
|
6459
6829
|
knowledgeFilePath
|
|
6460
6830
|
});
|
|
6461
|
-
|
|
6831
|
+
}
|
|
6832
|
+
program.name("upload-knowledge").description("Upload files to OpenWebUI knowledge base").command("upload-knowledge").option("-p, --path <path>", "Path to file or folder relative to script").option(
|
|
6833
|
+
"--force",
|
|
6834
|
+
"force upload files, even if their contents have not changed"
|
|
6835
|
+
).action(async (options) => {
|
|
6836
|
+
loadEnv();
|
|
6837
|
+
return getUploader(options.path, options.force).uploadKnowledge();
|
|
6838
|
+
});
|
|
6839
|
+
program.command("get-knowledge-files").description("Get files from OpenWebUI knowledge base").option("-p, --path <path>", "Path to file or folder relative to script").action(async (options) => {
|
|
6840
|
+
loadEnv();
|
|
6841
|
+
const uploader = getUploader(options.path);
|
|
6842
|
+
const files = await uploader.filesApi.search("*");
|
|
6843
|
+
console.debug(`found ${files.length} files`);
|
|
6844
|
+
writeFileSync(
|
|
6845
|
+
resolve6(uploader.config.knowledgeFilePath, "files.json"),
|
|
6846
|
+
JSON.stringify(files, null, 2),
|
|
6847
|
+
"utf-8"
|
|
6848
|
+
);
|
|
6849
|
+
});
|
|
6850
|
+
program.command("clear-knowledge").description("Remove all files from the knowledge base collection").action(async () => {
|
|
6851
|
+
loadEnv();
|
|
6852
|
+
const sharedConfig = getConfigFromEnv();
|
|
6853
|
+
const apiConfig = {
|
|
6854
|
+
apiKey: sharedConfig.webUiKey,
|
|
6855
|
+
baseUrl: sharedConfig.webUiUrl
|
|
6856
|
+
};
|
|
6857
|
+
const filesApi = new FilesApi(apiConfig);
|
|
6858
|
+
const knowledgeApi = new KnowledgeApi(apiConfig);
|
|
6859
|
+
const cleaner = new KnowledgeCleaner(sharedConfig);
|
|
6860
|
+
await cleaner.cleanUpOrphanedFiles();
|
|
6861
|
+
const knowledge = await knowledgeApi.getById(sharedConfig.knowledgeId);
|
|
6862
|
+
const knowledgeFiles = knowledge.files ?? [];
|
|
6863
|
+
if (!knowledge) {
|
|
6864
|
+
console.log("Knowledge base not found");
|
|
6865
|
+
return;
|
|
6866
|
+
}
|
|
6867
|
+
const files = await filesApi.list(false).then(
|
|
6868
|
+
(files2) => files2.filter((file) => file.meta?.collection_name === knowledge.id)
|
|
6869
|
+
);
|
|
6870
|
+
if (files.length === 0) {
|
|
6871
|
+
console.log("No files in knowledge base");
|
|
6872
|
+
return;
|
|
6873
|
+
}
|
|
6874
|
+
console.log(`Removing ${files.length} files from knowledge base...`);
|
|
6875
|
+
for (const file of files) {
|
|
6876
|
+
if (knowledgeFiles.some((f) => f.id === file.id)) {
|
|
6877
|
+
await knowledgeApi.removeFile(knowledge.id, file.id, true);
|
|
6878
|
+
} else {
|
|
6879
|
+
await filesApi.delete(file.id);
|
|
6880
|
+
}
|
|
6881
|
+
console.log(`Removed ${file.id}`);
|
|
6882
|
+
}
|
|
6883
|
+
console.log(`Removed ${files.length} files`);
|
|
6462
6884
|
});
|
|
6463
6885
|
}
|
|
6464
6886
|
|