veryfront 0.1.83 → 0.1.85
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/esm/cli/commands/knowledge/command.d.ts +10 -13
- package/esm/cli/commands/knowledge/command.d.ts.map +1 -1
- package/esm/cli/commands/knowledge/command.js +294 -110
- package/esm/cli/commands/knowledge/parser-source.d.ts.map +1 -1
- package/esm/cli/commands/knowledge/parser-source.js +52 -0
- package/esm/cli/commands/knowledge/result.d.ts +54 -0
- package/esm/cli/commands/knowledge/result.d.ts.map +1 -0
- package/esm/cli/commands/knowledge/result.js +22 -0
- package/esm/cli/commands/knowledge/source-policy.d.ts +11 -0
- package/esm/cli/commands/knowledge/source-policy.d.ts.map +1 -0
- package/esm/cli/commands/knowledge/source-policy.js +135 -0
- package/esm/deno.js +1 -1
- package/esm/src/jobs/index.d.ts +1 -1
- package/esm/src/jobs/index.d.ts.map +1 -1
- package/esm/src/jobs/index.js +1 -1
- package/esm/src/jobs/schemas.d.ts +1104 -185
- package/esm/src/jobs/schemas.d.ts.map +1 -1
- package/esm/src/jobs/schemas.js +81 -8
- package/esm/src/proxy/error-response.d.ts +7 -0
- package/esm/src/proxy/error-response.d.ts.map +1 -0
- package/esm/src/proxy/error-response.js +26 -0
- package/esm/src/proxy/handler.d.ts.map +1 -1
- package/esm/src/proxy/handler.js +25 -0
- package/esm/src/proxy/main.js +2 -23
- package/esm/src/rendering/orchestrator/css-candidate-manifest.d.ts +11 -0
- package/esm/src/rendering/orchestrator/css-candidate-manifest.d.ts.map +1 -1
- package/esm/src/rendering/orchestrator/css-candidate-manifest.js +23 -12
- package/esm/src/server/handlers/dev/styles-candidate-scanner.d.ts.map +1 -1
- package/esm/src/server/handlers/dev/styles-candidate-scanner.js +25 -8
- package/esm/src/server/handlers/dev/styles-css.handler.d.ts +1 -0
- package/esm/src/server/handlers/dev/styles-css.handler.d.ts.map +1 -1
- package/esm/src/server/handlers/dev/styles-css.handler.js +15 -5
- package/esm/src/transforms/esm/http-cache-helpers.d.ts.map +1 -1
- package/esm/src/transforms/esm/http-cache-helpers.js +7 -1
- package/esm/src/transforms/import-rewriter/strategies/bare-strategy.d.ts.map +1 -1
- package/esm/src/transforms/import-rewriter/strategies/bare-strategy.js +11 -8
- package/esm/src/transforms/shared/package-specifier.d.ts +7 -0
- package/esm/src/transforms/shared/package-specifier.d.ts.map +1 -0
- package/esm/src/transforms/shared/package-specifier.js +19 -0
- package/package.json +1 -1
- package/src/cli/commands/knowledge/command.ts +375 -139
- package/src/cli/commands/knowledge/parser-source.ts +52 -0
- package/src/cli/commands/knowledge/result.ts +88 -0
- package/src/cli/commands/knowledge/source-policy.ts +164 -0
- package/src/deno.js +1 -1
- package/src/src/jobs/index.ts +16 -0
- package/src/src/jobs/schemas.ts +105 -8
- package/src/src/proxy/error-response.ts +33 -0
- package/src/src/proxy/handler.ts +43 -0
- package/src/src/proxy/main.ts +2 -27
- package/src/src/rendering/orchestrator/css-candidate-manifest.ts +40 -14
- package/src/src/server/handlers/dev/styles-candidate-scanner.ts +37 -11
- package/src/src/server/handlers/dev/styles-css.handler.ts +25 -4
- package/src/src/transforms/esm/http-cache-helpers.ts +12 -1
- package/src/src/transforms/import-rewriter/strategies/bare-strategy.ts +11 -12
- package/src/src/transforms/shared/package-specifier.ts +29 -0
|
@@ -2,6 +2,7 @@ import { z } from "zod";
|
|
|
2
2
|
import { type ApiClient } from "../../shared/config.js";
|
|
3
3
|
import type { ParsedArgs } from "../../shared/types.js";
|
|
4
4
|
import { type Logger } from "../../../src/utils/index.js";
|
|
5
|
+
import { type KnowledgeIngestFailedFileResult, type KnowledgeIngestFileResult, type KnowledgeIngestSkippedFileResult } from "./result.js";
|
|
5
6
|
export interface KnowledgeParserResult {
|
|
6
7
|
success: true;
|
|
7
8
|
source_path: string;
|
|
@@ -16,17 +17,6 @@ export interface KnowledgeParserResult {
|
|
|
16
17
|
stats: Record<string, unknown>;
|
|
17
18
|
warnings: string[];
|
|
18
19
|
}
|
|
19
|
-
export interface KnowledgeIngestFileResult {
|
|
20
|
-
source: string;
|
|
21
|
-
localSourcePath: string;
|
|
22
|
-
outputPath: string;
|
|
23
|
-
remotePath: string;
|
|
24
|
-
slug: string;
|
|
25
|
-
sourceType: string;
|
|
26
|
-
summary: string;
|
|
27
|
-
stats: Record<string, unknown>;
|
|
28
|
-
warnings: string[];
|
|
29
|
-
}
|
|
30
20
|
type KnowledgeSource = {
|
|
31
21
|
kind: "local";
|
|
32
22
|
input: string;
|
|
@@ -37,6 +27,10 @@ type KnowledgeSource = {
|
|
|
37
27
|
uploadPath: string;
|
|
38
28
|
localPath: string;
|
|
39
29
|
};
|
|
30
|
+
export interface KnowledgeSourceCollection {
|
|
31
|
+
sources: KnowledgeSource[];
|
|
32
|
+
skipped: KnowledgeIngestSkippedFileResult[];
|
|
33
|
+
}
|
|
40
34
|
type DownloadResult = {
|
|
41
35
|
uploadPath: string;
|
|
42
36
|
localPath: string;
|
|
@@ -135,7 +129,7 @@ export declare function collectKnowledgeSources(options: Pick<KnowledgeIngestOpt
|
|
|
135
129
|
client: ApiClient;
|
|
136
130
|
projectSlug: string;
|
|
137
131
|
downloadUploads: (uploadPaths: string[]) => Promise<DownloadResult[]>;
|
|
138
|
-
}): Promise<
|
|
132
|
+
}): Promise<KnowledgeSourceCollection>;
|
|
139
133
|
export declare function ingestResolvedSources(sources: KnowledgeSource[], options: KnowledgeIngestOptions, deps: {
|
|
140
134
|
client: ApiClient;
|
|
141
135
|
projectSlug: string;
|
|
@@ -145,7 +139,10 @@ export declare function ingestResolvedSources(sources: KnowledgeSource[], option
|
|
|
145
139
|
path: string;
|
|
146
140
|
}>;
|
|
147
141
|
eventLogger?: Logger | null;
|
|
148
|
-
}): Promise<
|
|
142
|
+
}): Promise<{
|
|
143
|
+
ingested: KnowledgeIngestFileResult[];
|
|
144
|
+
failed: KnowledgeIngestFailedFileResult[];
|
|
145
|
+
}>;
|
|
149
146
|
export declare function knowledgeCommand(args: ParsedArgs): Promise<void>;
|
|
150
147
|
export {};
|
|
151
148
|
//# sourceMappingURL=command.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"command.d.ts","sourceRoot":"","sources":["../../../../src/cli/commands/knowledge/command.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAKxB,OAAO,EAAE,KAAK,SAAS,EAA0C,MAAM,wBAAwB,CAAC;AAChG,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,uBAAuB,CAAC;AAIxD,OAAO,EAAuB,KAAK,MAAM,EAAgB,MAAM,6BAA6B,CAAC;
|
|
1
|
+
{"version":3,"file":"command.d.ts","sourceRoot":"","sources":["../../../../src/cli/commands/knowledge/command.ts"],"names":[],"mappings":"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"}
|
|
@@ -10,21 +10,8 @@ import { putRemoteFileFromLocal } from "../files/command.js";
|
|
|
10
10
|
import { knowledgeIngestPythonSource } from "./parser-source.js";
|
|
11
11
|
import { createJobUserLogger, serverLogger } from "../../../src/utils/index.js";
|
|
12
12
|
import { writeJobResultIfConfigured } from "../../utils/write-job-result.js";
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
".csv",
|
|
16
|
-
".tsv",
|
|
17
|
-
".docx",
|
|
18
|
-
".xlsx",
|
|
19
|
-
".xls",
|
|
20
|
-
".pptx",
|
|
21
|
-
".html",
|
|
22
|
-
".htm",
|
|
23
|
-
".txt",
|
|
24
|
-
".json",
|
|
25
|
-
".md",
|
|
26
|
-
".mdx",
|
|
27
|
-
]);
|
|
13
|
+
import { classifyKnowledgeDirectoryPath, classifyKnowledgeSourcePath } from "./source-policy.js";
|
|
14
|
+
import { buildKnowledgeIngestJobResult, } from "./result.js";
|
|
28
15
|
const knowledgeJobLogger = serverLogger.component("knowledge-ingest");
|
|
29
16
|
const KnowledgeIngestArgsSchema = z.object({
|
|
30
17
|
projectSlug: z.string().optional(),
|
|
@@ -149,6 +136,15 @@ export function formatKnowledgeUploadSource(uploadPath) {
|
|
|
149
136
|
? normalizedPath
|
|
150
137
|
: `uploads/${normalizedPath}`;
|
|
151
138
|
}
|
|
139
|
+
function resolveExplicitUploadPath(inputPath) {
|
|
140
|
+
const normalizedInput = normalizeKnowledgeInputPath(inputPath);
|
|
141
|
+
const displayInput = inputPath.replace(/\\/g, "/");
|
|
142
|
+
const uploadPath = normalizeProjectUploadPath(inputPath);
|
|
143
|
+
if (!uploadPath || normalizedInput.endsWith("/")) {
|
|
144
|
+
throw new Error(`Directory upload references require --path <prefix> --all: ${displayInput}`);
|
|
145
|
+
}
|
|
146
|
+
return uploadPath;
|
|
147
|
+
}
|
|
152
148
|
export function isLikelyLocalPath(value) {
|
|
153
149
|
return value.startsWith("/") || value.startsWith("./") || value.startsWith("../") ||
|
|
154
150
|
/^[A-Za-z]:[\\/]/.test(value);
|
|
@@ -159,9 +155,6 @@ function isProjectUploadReference(value) {
|
|
|
159
155
|
const normalizedValue = normalize(value).replace(/\\/g, "/").replace(/^\/+/, "");
|
|
160
156
|
return normalizedValue === "uploads" || normalizedValue.startsWith("uploads/");
|
|
161
157
|
}
|
|
162
|
-
function isSupportedKnowledgeFile(path) {
|
|
163
|
-
return SUPPORTED_EXTENSIONS.has(extname(path).toLowerCase());
|
|
164
|
-
}
|
|
165
158
|
function slugify(value) {
|
|
166
159
|
return value.toLowerCase().replace(/[^a-z0-9]+/g, "-").replace(/^-+|-+$/g, "") || "document";
|
|
167
160
|
}
|
|
@@ -171,32 +164,108 @@ function defaultOutputRoot() {
|
|
|
171
164
|
export function resolveKnowledgeDownloadOutputDir(outputDir) {
|
|
172
165
|
return join(outputDir, ".uploads");
|
|
173
166
|
}
|
|
167
|
+
function createSkippedKnowledgeSource(input) {
|
|
168
|
+
return {
|
|
169
|
+
source: input.source,
|
|
170
|
+
localSourcePath: input.localSourcePath ?? null,
|
|
171
|
+
message: input.message,
|
|
172
|
+
reason: input.reason,
|
|
173
|
+
};
|
|
174
|
+
}
|
|
175
|
+
function createFailedKnowledgeSource(input) {
|
|
176
|
+
return {
|
|
177
|
+
source: input.source,
|
|
178
|
+
localSourcePath: input.localSourcePath,
|
|
179
|
+
message: input.message,
|
|
180
|
+
reason: input.reason,
|
|
181
|
+
};
|
|
182
|
+
}
|
|
183
|
+
function classifySourceOrSkip(input) {
|
|
184
|
+
const decision = classifyKnowledgeSourcePath(input.source);
|
|
185
|
+
if (decision.kind === "ingest") {
|
|
186
|
+
return null;
|
|
187
|
+
}
|
|
188
|
+
return createSkippedKnowledgeSource({
|
|
189
|
+
source: input.source,
|
|
190
|
+
localSourcePath: input.localSourcePath,
|
|
191
|
+
message: decision.message,
|
|
192
|
+
reason: decision.reason,
|
|
193
|
+
});
|
|
194
|
+
}
|
|
195
|
+
function classifyDirectoryOrSkip(input) {
|
|
196
|
+
const decision = classifyKnowledgeDirectoryPath(input.source);
|
|
197
|
+
if (decision.kind === "ingest") {
|
|
198
|
+
return null;
|
|
199
|
+
}
|
|
200
|
+
return createSkippedKnowledgeSource({
|
|
201
|
+
source: input.source,
|
|
202
|
+
localSourcePath: null,
|
|
203
|
+
message: decision.message,
|
|
204
|
+
reason: decision.reason,
|
|
205
|
+
});
|
|
206
|
+
}
|
|
174
207
|
async function collectLocalFiles(root, recursive) {
|
|
175
208
|
const fs = createFileSystem();
|
|
176
209
|
const stat = await fs.stat(root);
|
|
177
|
-
if (stat.isFile)
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
210
|
+
if (stat.isFile) {
|
|
211
|
+
const skipped = classifySourceOrSkip({ source: root, localSourcePath: root });
|
|
212
|
+
return skipped == null
|
|
213
|
+
? {
|
|
214
|
+
sources: [{ kind: "local", input: root, localPath: root }],
|
|
215
|
+
skipped: [],
|
|
216
|
+
}
|
|
217
|
+
: {
|
|
218
|
+
sources: [],
|
|
219
|
+
skipped: [skipped],
|
|
220
|
+
};
|
|
221
|
+
}
|
|
222
|
+
if (!stat.isDirectory) {
|
|
223
|
+
return { sources: [], skipped: [] };
|
|
224
|
+
}
|
|
225
|
+
const skippedRootDirectory = classifyDirectoryOrSkip({ source: root });
|
|
226
|
+
if (skippedRootDirectory != null) {
|
|
227
|
+
return {
|
|
228
|
+
sources: [],
|
|
229
|
+
skipped: [skippedRootDirectory],
|
|
230
|
+
};
|
|
231
|
+
}
|
|
232
|
+
const collection = {
|
|
233
|
+
sources: [],
|
|
234
|
+
skipped: [],
|
|
235
|
+
};
|
|
182
236
|
async function walk(dir) {
|
|
183
237
|
for await (const entry of fs.readDir(dir)) {
|
|
184
238
|
const entryPath = join(dir, entry.name);
|
|
185
239
|
if (entry.isDirectory) {
|
|
240
|
+
const skipped = classifyDirectoryOrSkip({ source: entryPath });
|
|
241
|
+
if (skipped != null) {
|
|
242
|
+
collection.skipped.push(skipped);
|
|
243
|
+
continue;
|
|
244
|
+
}
|
|
186
245
|
if (recursive)
|
|
187
246
|
await walk(entryPath);
|
|
188
247
|
continue;
|
|
189
248
|
}
|
|
190
|
-
if (entry.isFile
|
|
191
|
-
|
|
249
|
+
if (!entry.isFile) {
|
|
250
|
+
continue;
|
|
251
|
+
}
|
|
252
|
+
const skipped = classifySourceOrSkip({ source: entryPath, localSourcePath: entryPath });
|
|
253
|
+
if (skipped != null) {
|
|
254
|
+
collection.skipped.push(skipped);
|
|
255
|
+
continue;
|
|
192
256
|
}
|
|
257
|
+
collection.sources.push({ kind: "local", input: root, localPath: entryPath });
|
|
193
258
|
}
|
|
194
259
|
}
|
|
195
260
|
await walk(root);
|
|
196
|
-
|
|
261
|
+
collection.sources.sort((left, right) => left.localPath.localeCompare(right.localPath));
|
|
262
|
+
collection.skipped.sort((left, right) => left.source.localeCompare(right.source));
|
|
263
|
+
return collection;
|
|
197
264
|
}
|
|
198
265
|
function buildSourceReference(source) {
|
|
199
|
-
return source.kind === "upload"
|
|
266
|
+
return source.kind === "upload"
|
|
267
|
+
? formatKnowledgeUploadSource(source.uploadPath)
|
|
268
|
+
: source.localPath;
|
|
200
269
|
}
|
|
201
270
|
function buildSuggestedSlug(source, index) {
|
|
202
271
|
const normalized = normalize(source.kind === "upload" ? source.uploadPath : source.localPath).replace(/\\/g, "/");
|
|
@@ -259,35 +328,44 @@ export async function runKnowledgeParser(input) {
|
|
|
259
328
|
const outputJsonPath = `${tempDir}/output.json`;
|
|
260
329
|
const scriptPath = `${tempDir}/ingest_document_to_knowledge.py`;
|
|
261
330
|
try {
|
|
262
|
-
await dntShim.Deno.writeTextFile(inputJsonPath, JSON.stringify({
|
|
263
|
-
file_path: input.filePath,
|
|
264
|
-
output_dir: input.outputDir,
|
|
265
|
-
description: input.description,
|
|
266
|
-
slug: input.slug,
|
|
267
|
-
source_reference: input.sourceReference,
|
|
268
|
-
}));
|
|
269
|
-
await dntShim.Deno.writeTextFile(scriptPath, knowledgeIngestPythonSource);
|
|
270
|
-
let result;
|
|
271
331
|
try {
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
332
|
+
await dntShim.Deno.writeTextFile(inputJsonPath, JSON.stringify({
|
|
333
|
+
file_path: input.filePath,
|
|
334
|
+
output_dir: input.outputDir,
|
|
335
|
+
description: input.description,
|
|
336
|
+
slug: input.slug,
|
|
337
|
+
source_reference: input.sourceReference,
|
|
338
|
+
}));
|
|
339
|
+
await dntShim.Deno.writeTextFile(scriptPath, knowledgeIngestPythonSource);
|
|
340
|
+
let result;
|
|
341
|
+
try {
|
|
342
|
+
result = await new dntShim.Deno.Command("python3", {
|
|
343
|
+
args: [scriptPath, "--input-json", inputJsonPath, "--output-json", outputJsonPath],
|
|
344
|
+
...(input.env ? { env: input.env } : {}),
|
|
345
|
+
stdout: "piped",
|
|
346
|
+
stderr: "piped",
|
|
347
|
+
}).output();
|
|
348
|
+
}
|
|
349
|
+
catch (error) {
|
|
350
|
+
if (error instanceof dntShim.Deno.errors.NotFound) {
|
|
351
|
+
throw new Error("python3 is required. Install python3 and the supported parser packages, or run the command inside the Veryfront sandbox.");
|
|
352
|
+
}
|
|
353
|
+
throw error;
|
|
354
|
+
}
|
|
355
|
+
if (result.code !== 0) {
|
|
356
|
+
const stderr = new TextDecoder().decode(result.stderr).trim();
|
|
357
|
+
throw new Error(stderr || "parser exited unsuccessfully");
|
|
358
|
+
}
|
|
359
|
+
const raw = await dntShim.Deno.readTextFile(outputJsonPath);
|
|
360
|
+
return JSON.parse(raw);
|
|
278
361
|
}
|
|
279
362
|
catch (error) {
|
|
280
|
-
if (error instanceof
|
|
281
|
-
throw
|
|
363
|
+
if (error instanceof Error && error.message.startsWith("knowledge ingest parser failed")) {
|
|
364
|
+
throw error;
|
|
282
365
|
}
|
|
283
|
-
|
|
366
|
+
const message = error instanceof Error ? error.message : String(error);
|
|
367
|
+
throw new Error(`knowledge ingest parser failed: ${message}`);
|
|
284
368
|
}
|
|
285
|
-
if (result.code !== 0) {
|
|
286
|
-
const stderr = new TextDecoder().decode(result.stderr).trim();
|
|
287
|
-
throw new Error(`knowledge ingest parser failed${stderr ? `: ${stderr}` : ""}`);
|
|
288
|
-
}
|
|
289
|
-
const raw = await dntShim.Deno.readTextFile(outputJsonPath);
|
|
290
|
-
return JSON.parse(raw);
|
|
291
369
|
}
|
|
292
370
|
finally {
|
|
293
371
|
await dntShim.Deno.remove(tempDir, { recursive: true }).catch(() => undefined);
|
|
@@ -298,21 +376,27 @@ export async function collectKnowledgeSources(options, deps) {
|
|
|
298
376
|
if (options.sources.length > 0) {
|
|
299
377
|
const explicitSources = [];
|
|
300
378
|
const uploadTargets = [];
|
|
379
|
+
const skipped = [];
|
|
301
380
|
for (const input of options.sources) {
|
|
302
381
|
if (!isProjectUploadReference(input) && await fs.exists(input)) {
|
|
303
|
-
const
|
|
304
|
-
if (!localFiles.length)
|
|
305
|
-
throw new Error(`No supported files found at ${input}`);
|
|
382
|
+
const collection = await collectLocalFiles(input, options.recursive);
|
|
306
383
|
explicitSources.push({
|
|
307
384
|
kind: "local",
|
|
308
|
-
|
|
385
|
+
collection,
|
|
309
386
|
});
|
|
310
387
|
continue;
|
|
311
388
|
}
|
|
312
389
|
if (isLikelyLocalPath(input)) {
|
|
313
390
|
throw new Error(`Local file not found: ${input}`);
|
|
314
391
|
}
|
|
315
|
-
const uploadPath =
|
|
392
|
+
const uploadPath = resolveExplicitUploadPath(input);
|
|
393
|
+
const skippedUpload = classifySourceOrSkip({
|
|
394
|
+
source: formatKnowledgeUploadSource(uploadPath),
|
|
395
|
+
});
|
|
396
|
+
if (skippedUpload != null) {
|
|
397
|
+
skipped.push(skippedUpload);
|
|
398
|
+
continue;
|
|
399
|
+
}
|
|
316
400
|
explicitSources.push({ kind: "upload", input, uploadPath });
|
|
317
401
|
uploadTargets.push(uploadPath);
|
|
318
402
|
}
|
|
@@ -326,7 +410,14 @@ export async function collectKnowledgeSources(options, deps) {
|
|
|
326
410
|
const resolvedSources = [];
|
|
327
411
|
for (const source of explicitSources) {
|
|
328
412
|
if (source.kind === "local") {
|
|
329
|
-
|
|
413
|
+
for (const localSource of source.collection.sources) {
|
|
414
|
+
resolvedSources.push({
|
|
415
|
+
kind: "local",
|
|
416
|
+
input: localSource.input,
|
|
417
|
+
localPath: localSource.localPath,
|
|
418
|
+
});
|
|
419
|
+
}
|
|
420
|
+
skipped.push(...source.collection.skipped);
|
|
330
421
|
continue;
|
|
331
422
|
}
|
|
332
423
|
const matchingDownloads = downloadsByPath.get(source.uploadPath);
|
|
@@ -341,16 +432,16 @@ export async function collectKnowledgeSources(options, deps) {
|
|
|
341
432
|
localPath: download.localPath,
|
|
342
433
|
});
|
|
343
434
|
}
|
|
344
|
-
return
|
|
435
|
+
return {
|
|
436
|
+
sources: resolvedSources,
|
|
437
|
+
skipped,
|
|
438
|
+
};
|
|
345
439
|
}
|
|
346
440
|
if (!options.path || !options.all) {
|
|
347
441
|
throw new Error("Provide one or more source paths or use --path with --all.");
|
|
348
442
|
}
|
|
349
443
|
if (!isProjectUploadReference(options.path) && await fs.exists(options.path)) {
|
|
350
|
-
|
|
351
|
-
if (!localFiles.length)
|
|
352
|
-
throw new Error(`No supported files found under ${options.path}`);
|
|
353
|
-
return localFiles.map((localPath) => ({ kind: "local", input: options.path, localPath }));
|
|
444
|
+
return collectLocalFiles(options.path, options.recursive);
|
|
354
445
|
}
|
|
355
446
|
const displayUploadPrefix = normalizeKnowledgeInputPath(options.path);
|
|
356
447
|
const uploadPrefix = normalizeProjectUploadPath(options.path);
|
|
@@ -360,74 +451,131 @@ export async function collectKnowledgeSources(options, deps) {
|
|
|
360
451
|
limit: 100,
|
|
361
452
|
});
|
|
362
453
|
let uploads = await listUploadsForPrefix(uploadPrefix || undefined);
|
|
454
|
+
let skipped = uploads.flatMap((item) => {
|
|
455
|
+
if (item.type === "folder") {
|
|
456
|
+
return [];
|
|
457
|
+
}
|
|
458
|
+
const skippedUpload = classifySourceOrSkip({
|
|
459
|
+
source: formatKnowledgeUploadSource(item.path),
|
|
460
|
+
});
|
|
461
|
+
return skippedUpload == null ? [] : [skippedUpload];
|
|
462
|
+
});
|
|
363
463
|
let uploadTargets = uploads
|
|
364
|
-
.filter((item) => item.type !== "folder"
|
|
365
|
-
.map((item) => item.path)
|
|
464
|
+
.filter((item) => item.type !== "folder")
|
|
465
|
+
.map((item) => item.path)
|
|
466
|
+
.filter((uploadPath) => classifySourceOrSkip({ source: formatKnowledgeUploadSource(uploadPath) }) == null);
|
|
366
467
|
if (!uploadTargets.length && uploadPrefix && !uploadPrefix.endsWith("/")) {
|
|
367
468
|
uploads = await listUploadsForPrefix(`${uploadPrefix}/`);
|
|
469
|
+
skipped = uploads.flatMap((item) => {
|
|
470
|
+
if (item.type === "folder") {
|
|
471
|
+
return [];
|
|
472
|
+
}
|
|
473
|
+
const skippedUpload = classifySourceOrSkip({
|
|
474
|
+
source: formatKnowledgeUploadSource(item.path),
|
|
475
|
+
});
|
|
476
|
+
return skippedUpload == null ? [] : [skippedUpload];
|
|
477
|
+
});
|
|
368
478
|
uploadTargets = uploads
|
|
369
|
-
.filter((item) => item.type !== "folder"
|
|
370
|
-
.map((item) => item.path)
|
|
479
|
+
.filter((item) => item.type !== "folder")
|
|
480
|
+
.map((item) => item.path)
|
|
481
|
+
.filter((uploadPath) => classifySourceOrSkip({ source: formatKnowledgeUploadSource(uploadPath) }) == null);
|
|
371
482
|
}
|
|
372
|
-
if (!uploadTargets.length) {
|
|
483
|
+
if (!uploadTargets.length && skipped.length === 0) {
|
|
373
484
|
throw new Error(`No supported uploads found under ${displayUploadPrefix}`);
|
|
374
485
|
}
|
|
375
486
|
const downloads = await deps.downloadUploads(uploadTargets);
|
|
376
|
-
return
|
|
377
|
-
|
|
378
|
-
|
|
379
|
-
|
|
380
|
-
|
|
381
|
-
|
|
487
|
+
return {
|
|
488
|
+
sources: downloads.map((download) => ({
|
|
489
|
+
kind: "upload",
|
|
490
|
+
input: options.path,
|
|
491
|
+
uploadPath: download.uploadPath,
|
|
492
|
+
localPath: download.localPath,
|
|
493
|
+
})),
|
|
494
|
+
skipped,
|
|
495
|
+
};
|
|
382
496
|
}
|
|
383
497
|
export async function ingestResolvedSources(sources, options, deps) {
|
|
384
498
|
if (options.slug && sources.length !== 1) {
|
|
385
499
|
throw new Error("--slug can only be used with a single explicit source.");
|
|
386
500
|
}
|
|
387
501
|
const slugs = options.slug ? [options.slug] : ensureUniqueSlugs(sources);
|
|
388
|
-
const
|
|
389
|
-
|
|
390
|
-
|
|
391
|
-
|
|
502
|
+
const ingested = [];
|
|
503
|
+
const failed = [];
|
|
504
|
+
const recordSourceFailure = (source, sourceReference, index, message, reason) => {
|
|
505
|
+
deps.eventLogger?.error("Knowledge source failed", {
|
|
506
|
+
phase: "file_failed",
|
|
392
507
|
progress_current: index + 1,
|
|
393
508
|
progress_total: sources.length,
|
|
394
509
|
source_name: buildKnowledgeSourceName(source),
|
|
510
|
+
error: message,
|
|
395
511
|
});
|
|
396
|
-
|
|
397
|
-
|
|
398
|
-
|
|
399
|
-
|
|
400
|
-
|
|
401
|
-
|
|
402
|
-
|
|
403
|
-
|
|
404
|
-
const
|
|
405
|
-
deps.eventLogger?.info("
|
|
406
|
-
phase: "
|
|
512
|
+
failed.push(createFailedKnowledgeSource({
|
|
513
|
+
source: sourceReference,
|
|
514
|
+
localSourcePath: source.localPath,
|
|
515
|
+
message,
|
|
516
|
+
reason,
|
|
517
|
+
}));
|
|
518
|
+
};
|
|
519
|
+
for (const [index, source] of sources.entries()) {
|
|
520
|
+
const sourceReference = buildSourceReference(source);
|
|
521
|
+
deps.eventLogger?.info("Processing knowledge source", {
|
|
522
|
+
phase: "file_processing",
|
|
407
523
|
progress_current: index + 1,
|
|
408
524
|
progress_total: sources.length,
|
|
409
525
|
source_name: buildKnowledgeSourceName(source),
|
|
410
|
-
remote_path: uploaded.path,
|
|
411
|
-
warning_count: parser.warnings.length,
|
|
412
526
|
});
|
|
413
|
-
|
|
414
|
-
|
|
415
|
-
|
|
527
|
+
let parser;
|
|
528
|
+
try {
|
|
529
|
+
parser = await deps.runParser({
|
|
530
|
+
filePath: source.localPath,
|
|
531
|
+
outputDir: deps.outputDir,
|
|
532
|
+
description: options.description,
|
|
533
|
+
slug: slugs[index],
|
|
534
|
+
sourceReference,
|
|
535
|
+
});
|
|
536
|
+
}
|
|
537
|
+
catch (error) {
|
|
538
|
+
const message = error instanceof Error ? error.message : String(error);
|
|
539
|
+
recordSourceFailure(source, sourceReference, index, message, "parser_error");
|
|
540
|
+
continue;
|
|
541
|
+
}
|
|
542
|
+
try {
|
|
543
|
+
const remotePath = deriveKnowledgeRemotePath(parser.sandbox_output_path, deps.outputDir, options.knowledgePath);
|
|
544
|
+
const uploaded = await deps.uploadKnowledgeFile(remotePath, parser.sandbox_output_path);
|
|
545
|
+
deps.eventLogger?.info("Knowledge source ingested", {
|
|
546
|
+
phase: "file_completed",
|
|
416
547
|
progress_current: index + 1,
|
|
417
548
|
progress_total: sources.length,
|
|
418
549
|
source_name: buildKnowledgeSourceName(source),
|
|
550
|
+
remote_path: uploaded.path,
|
|
419
551
|
warning_count: parser.warnings.length,
|
|
420
552
|
});
|
|
553
|
+
if (parser.warnings.length > 0) {
|
|
554
|
+
deps.eventLogger?.warn("Knowledge source emitted warnings", {
|
|
555
|
+
phase: "file_warning",
|
|
556
|
+
progress_current: index + 1,
|
|
557
|
+
progress_total: sources.length,
|
|
558
|
+
source_name: buildKnowledgeSourceName(source),
|
|
559
|
+
warning_count: parser.warnings.length,
|
|
560
|
+
});
|
|
561
|
+
}
|
|
562
|
+
ingested.push(createKnowledgeIngestResult({
|
|
563
|
+
source: sourceReference,
|
|
564
|
+
localSourcePath: source.localPath,
|
|
565
|
+
outputPath: parser.sandbox_output_path,
|
|
566
|
+
remotePath: uploaded.path,
|
|
567
|
+
parser,
|
|
568
|
+
}));
|
|
569
|
+
}
|
|
570
|
+
catch (error) {
|
|
571
|
+
const message = error instanceof Error ? error.message : String(error);
|
|
572
|
+
recordSourceFailure(source, sourceReference, index, message, "upload_error");
|
|
421
573
|
}
|
|
422
|
-
results.push(createKnowledgeIngestResult({
|
|
423
|
-
source: buildSourceReference(source),
|
|
424
|
-
localSourcePath: source.localPath,
|
|
425
|
-
outputPath: parser.sandbox_output_path,
|
|
426
|
-
remotePath: uploaded.path,
|
|
427
|
-
parser,
|
|
428
|
-
}));
|
|
429
574
|
}
|
|
430
|
-
return
|
|
575
|
+
return {
|
|
576
|
+
ingested,
|
|
577
|
+
failed,
|
|
578
|
+
};
|
|
431
579
|
}
|
|
432
580
|
export async function knowledgeCommand(args) {
|
|
433
581
|
const subcommand = typeof args._[1] === "string" ? args._[1] : undefined;
|
|
@@ -452,20 +600,33 @@ export async function knowledgeCommand(args) {
|
|
|
452
600
|
const downloadOutputDir = resolveKnowledgeDownloadOutputDir(outputDir);
|
|
453
601
|
const eventLogger = createKnowledgeIngestEventLogger();
|
|
454
602
|
try {
|
|
603
|
+
const sourceMode = options.path ? "path_prefix" : "explicit_sources";
|
|
455
604
|
eventLogger?.info("Starting knowledge ingest", {
|
|
456
605
|
phase: "started",
|
|
457
|
-
mode:
|
|
606
|
+
mode: sourceMode,
|
|
458
607
|
});
|
|
459
|
-
const
|
|
608
|
+
const collection = await collectKnowledgeSources(options, {
|
|
460
609
|
client,
|
|
461
610
|
projectSlug: config.projectSlug,
|
|
462
611
|
downloadUploads: (uploadPaths) => Promise.all(uploadPaths.map((uploadPath) => downloadUploadToFile(client, config.projectSlug, uploadPath, downloadOutputDir))),
|
|
463
612
|
});
|
|
613
|
+
const requestedCount = collection.sources.length + collection.skipped.length;
|
|
614
|
+
if (requestedCount === 0) {
|
|
615
|
+
throw new Error("No supported knowledge sources were found.");
|
|
616
|
+
}
|
|
464
617
|
eventLogger?.info("Resolved knowledge sources", {
|
|
465
618
|
phase: "sources_resolved",
|
|
466
|
-
progress_total:
|
|
619
|
+
progress_total: requestedCount,
|
|
620
|
+
ingestable_count: collection.sources.length,
|
|
621
|
+
skipped_count: collection.skipped.length,
|
|
467
622
|
});
|
|
468
|
-
|
|
623
|
+
if (collection.skipped.length > 0) {
|
|
624
|
+
eventLogger?.warn("Skipped knowledge sources", {
|
|
625
|
+
phase: "sources_skipped",
|
|
626
|
+
skipped_count: collection.skipped.length,
|
|
627
|
+
});
|
|
628
|
+
}
|
|
629
|
+
const results = await ingestResolvedSources(collection.sources, options, {
|
|
469
630
|
client,
|
|
470
631
|
projectSlug: config.projectSlug,
|
|
471
632
|
outputDir,
|
|
@@ -473,22 +634,45 @@ export async function knowledgeCommand(args) {
|
|
|
473
634
|
eventLogger,
|
|
474
635
|
uploadKnowledgeFile: (remotePath, localPath) => putRemoteFileFromLocal(client, config.projectSlug, remotePath, localPath),
|
|
475
636
|
});
|
|
637
|
+
const jobResult = buildKnowledgeIngestJobResult({
|
|
638
|
+
requestedCount,
|
|
639
|
+
sourceMode,
|
|
640
|
+
knowledgePath: options.knowledgePath,
|
|
641
|
+
ingested: results.ingested,
|
|
642
|
+
skipped: collection.skipped,
|
|
643
|
+
failed: results.failed,
|
|
644
|
+
});
|
|
476
645
|
eventLogger?.info("Completed knowledge ingest", {
|
|
477
646
|
phase: "completed",
|
|
478
|
-
progress_current:
|
|
479
|
-
progress_total:
|
|
647
|
+
progress_current: requestedCount,
|
|
648
|
+
progress_total: requestedCount,
|
|
649
|
+
ingested_count: jobResult.summary.ingested_count,
|
|
650
|
+
skipped_count: jobResult.summary.skipped_count,
|
|
651
|
+
failed_count: jobResult.summary.failed_count,
|
|
480
652
|
});
|
|
481
|
-
await writeJobResultIfConfigured(
|
|
653
|
+
await writeJobResultIfConfigured(jobResult);
|
|
482
654
|
if (options.json) {
|
|
483
|
-
printJson(
|
|
655
|
+
printJson(jobResult);
|
|
484
656
|
return;
|
|
485
657
|
}
|
|
486
|
-
for (const result of
|
|
658
|
+
for (const result of jobResult.ingested) {
|
|
487
659
|
if (!options.quiet) {
|
|
488
660
|
cliLogger.info(`Ingested ${result.source} -> ${result.remotePath}`);
|
|
489
661
|
cliLogger.info(` ${result.summary}`);
|
|
490
662
|
}
|
|
491
663
|
}
|
|
664
|
+
for (const skipped of jobResult.skipped) {
|
|
665
|
+
if (!options.quiet) {
|
|
666
|
+
cliLogger.warn(`Skipped ${skipped.source}`);
|
|
667
|
+
cliLogger.warn(` ${skipped.message}`);
|
|
668
|
+
}
|
|
669
|
+
}
|
|
670
|
+
for (const failure of jobResult.failed) {
|
|
671
|
+
if (!options.quiet) {
|
|
672
|
+
cliLogger.error(`Failed ${failure.source}`);
|
|
673
|
+
cliLogger.error(` ${failure.message}`);
|
|
674
|
+
}
|
|
675
|
+
}
|
|
492
676
|
}
|
|
493
677
|
catch (error) {
|
|
494
678
|
eventLogger?.error("Knowledge ingest failed", {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"parser-source.d.ts","sourceRoot":"","sources":["../../../../src/cli/commands/knowledge/parser-source.ts"],"names":[],"mappings":"AAAA,eAAO,MAAM,2BAA2B,
|
|
1
|
+
{"version":3,"file":"parser-source.d.ts","sourceRoot":"","sources":["../../../../src/cli/commands/knowledge/parser-source.ts"],"names":[],"mappings":"AAAA,eAAO,MAAM,2BAA2B,QA2jBvC,CAAC"}
|