veryfront 0.1.82 → 0.1.84

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.
Files changed (93) hide show
  1. package/esm/cli/commands/knowledge/command.d.ts +10 -13
  2. package/esm/cli/commands/knowledge/command.d.ts.map +1 -1
  3. package/esm/cli/commands/knowledge/command.js +294 -110
  4. package/esm/cli/commands/knowledge/parser-source.d.ts.map +1 -1
  5. package/esm/cli/commands/knowledge/parser-source.js +52 -0
  6. package/esm/cli/commands/knowledge/result.d.ts +54 -0
  7. package/esm/cli/commands/knowledge/result.d.ts.map +1 -0
  8. package/esm/cli/commands/knowledge/result.js +22 -0
  9. package/esm/cli/commands/knowledge/source-policy.d.ts +11 -0
  10. package/esm/cli/commands/knowledge/source-policy.d.ts.map +1 -0
  11. package/esm/cli/commands/knowledge/source-policy.js +135 -0
  12. package/esm/deno.js +1 -1
  13. package/esm/src/jobs/index.d.ts +1 -1
  14. package/esm/src/jobs/index.d.ts.map +1 -1
  15. package/esm/src/jobs/index.js +1 -1
  16. package/esm/src/jobs/schemas.d.ts +1104 -185
  17. package/esm/src/jobs/schemas.d.ts.map +1 -1
  18. package/esm/src/jobs/schemas.js +81 -8
  19. package/esm/src/platform/adapters/base.d.ts +4 -1
  20. package/esm/src/platform/adapters/base.d.ts.map +1 -1
  21. package/esm/src/platform/adapters/fs/github/adapter.d.ts +2 -1
  22. package/esm/src/platform/adapters/fs/github/adapter.d.ts.map +1 -1
  23. package/esm/src/platform/adapters/fs/github/adapter.js +2 -2
  24. package/esm/src/platform/adapters/fs/github/stat-operations.d.ts +2 -1
  25. package/esm/src/platform/adapters/fs/github/stat-operations.d.ts.map +1 -1
  26. package/esm/src/platform/adapters/fs/github/stat-operations.js +2 -2
  27. package/esm/src/platform/adapters/fs/veryfront/adapter.d.ts +2 -2
  28. package/esm/src/platform/adapters/fs/veryfront/adapter.d.ts.map +1 -1
  29. package/esm/src/platform/adapters/fs/veryfront/adapter.js +17 -2
  30. package/esm/src/platform/adapters/fs/veryfront/multi-project-adapter.d.ts +2 -2
  31. package/esm/src/platform/adapters/fs/veryfront/multi-project-adapter.d.ts.map +1 -1
  32. package/esm/src/platform/adapters/fs/veryfront/multi-project-adapter.js +2 -2
  33. package/esm/src/platform/adapters/fs/veryfront/read-operations.d.ts +1 -0
  34. package/esm/src/platform/adapters/fs/veryfront/read-operations.d.ts.map +1 -1
  35. package/esm/src/platform/adapters/fs/veryfront/stat-operations.d.ts +6 -2
  36. package/esm/src/platform/adapters/fs/veryfront/stat-operations.d.ts.map +1 -1
  37. package/esm/src/platform/adapters/fs/veryfront/stat-operations.js +131 -21
  38. package/esm/src/platform/adapters/fs/veryfront/types.d.ts +2 -1
  39. package/esm/src/platform/adapters/fs/veryfront/types.d.ts.map +1 -1
  40. package/esm/src/platform/adapters/fs/wrapper.d.ts +2 -2
  41. package/esm/src/platform/adapters/fs/wrapper.d.ts.map +1 -1
  42. package/esm/src/platform/adapters/fs/wrapper.js +2 -2
  43. package/esm/src/proxy/error-response.d.ts +7 -0
  44. package/esm/src/proxy/error-response.d.ts.map +1 -0
  45. package/esm/src/proxy/error-response.js +26 -0
  46. package/esm/src/proxy/handler.d.ts.map +1 -1
  47. package/esm/src/proxy/handler.js +25 -0
  48. package/esm/src/proxy/main.js +2 -23
  49. package/esm/src/rendering/app-route-resolver.js +0 -9
  50. package/esm/src/rendering/orchestrator/file-resolver/index.d.ts.map +1 -1
  51. package/esm/src/rendering/orchestrator/file-resolver/index.js +17 -0
  52. package/esm/src/rendering/page-resolution/page-resolver.d.ts.map +1 -1
  53. package/esm/src/rendering/page-resolution/page-resolver.js +19 -6
  54. package/esm/src/rendering/router-detection.d.ts +1 -0
  55. package/esm/src/rendering/router-detection.d.ts.map +1 -1
  56. package/esm/src/rendering/router-detection.js +3 -0
  57. package/esm/src/transforms/esm/http-cache-helpers.d.ts.map +1 -1
  58. package/esm/src/transforms/esm/http-cache-helpers.js +7 -1
  59. package/esm/src/transforms/import-rewriter/strategies/bare-strategy.d.ts.map +1 -1
  60. package/esm/src/transforms/import-rewriter/strategies/bare-strategy.js +11 -8
  61. package/esm/src/transforms/shared/package-specifier.d.ts +7 -0
  62. package/esm/src/transforms/shared/package-specifier.d.ts.map +1 -0
  63. package/esm/src/transforms/shared/package-specifier.js +19 -0
  64. package/esm/src/types/entities/getEntityInfo.d.ts.map +1 -1
  65. package/esm/src/types/entities/getEntityInfo.js +59 -42
  66. package/package.json +1 -1
  67. package/src/cli/commands/knowledge/command.ts +375 -139
  68. package/src/cli/commands/knowledge/parser-source.ts +52 -0
  69. package/src/cli/commands/knowledge/result.ts +88 -0
  70. package/src/cli/commands/knowledge/source-policy.ts +164 -0
  71. package/src/deno.js +1 -1
  72. package/src/src/jobs/index.ts +16 -0
  73. package/src/src/jobs/schemas.ts +105 -8
  74. package/src/src/platform/adapters/base.ts +5 -1
  75. package/src/src/platform/adapters/fs/github/adapter.ts +3 -2
  76. package/src/src/platform/adapters/fs/github/stat-operations.ts +3 -2
  77. package/src/src/platform/adapters/fs/veryfront/adapter.ts +24 -3
  78. package/src/src/platform/adapters/fs/veryfront/multi-project-adapter.ts +6 -3
  79. package/src/src/platform/adapters/fs/veryfront/read-operations.ts +1 -0
  80. package/src/src/platform/adapters/fs/veryfront/stat-operations.ts +161 -25
  81. package/src/src/platform/adapters/fs/veryfront/types.ts +2 -1
  82. package/src/src/platform/adapters/fs/wrapper.ts +10 -3
  83. package/src/src/proxy/error-response.ts +33 -0
  84. package/src/src/proxy/handler.ts +43 -0
  85. package/src/src/proxy/main.ts +2 -27
  86. package/src/src/rendering/app-route-resolver.ts +0 -8
  87. package/src/src/rendering/orchestrator/file-resolver/index.ts +19 -0
  88. package/src/src/rendering/page-resolution/page-resolver.ts +26 -17
  89. package/src/src/rendering/router-detection.ts +7 -0
  90. package/src/src/transforms/esm/http-cache-helpers.ts +12 -1
  91. package/src/src/transforms/import-rewriter/strategies/bare-strategy.ts +11 -12
  92. package/src/src/transforms/shared/package-specifier.ts +29 -0
  93. package/src/src/types/entities/getEntityInfo.ts +78 -59
@@ -14,6 +14,53 @@ def yaml_quote(value: Any) -> str:
14
14
 
15
15
 
16
16
  CODE_FENCE = chr(96) * 3
17
+ TEXT_FILE_EXTENSIONS = {
18
+ ".c",
19
+ ".cc",
20
+ ".conf",
21
+ ".cpp",
22
+ ".cs",
23
+ ".css",
24
+ ".go",
25
+ ".h",
26
+ ".hpp",
27
+ ".ini",
28
+ ".java",
29
+ ".js",
30
+ ".jsonl",
31
+ ".jsx",
32
+ ".kt",
33
+ ".less",
34
+ ".lua",
35
+ ".mjs",
36
+ ".ndjson",
37
+ ".php",
38
+ ".pl",
39
+ ".py",
40
+ ".r",
41
+ ".rb",
42
+ ".rs",
43
+ ".sass",
44
+ ".scala",
45
+ ".scss",
46
+ ".sh",
47
+ ".sql",
48
+ ".swift",
49
+ ".toml",
50
+ ".ts",
51
+ ".tsx",
52
+ ".xml",
53
+ ".yaml",
54
+ ".yml",
55
+ ".zsh",
56
+ }
57
+ TEXT_FILE_NAMES = {
58
+ "dockerfile",
59
+ "makefile",
60
+ "readme",
61
+ "license",
62
+ "changelog",
63
+ }
17
64
 
18
65
 
19
66
  def slugify(value: str) -> str:
@@ -406,6 +453,7 @@ def parse_json(path: str):
406
453
 
407
454
  def select_parser(path: Path):
408
455
  ext = path.suffix.lower()
456
+ name = path.name.lower()
409
457
  if ext == ".pdf":
410
458
  return "pdf", prefer_kreuzberg("pdf", parse_pdf)
411
459
  if ext in {".csv", ".tsv"}:
@@ -424,6 +472,10 @@ def select_parser(path: Path):
424
472
  return ext.lstrip("."), parse_text
425
473
  if ext == ".json":
426
474
  return "json", parse_json
475
+ if ext in TEXT_FILE_EXTENSIONS:
476
+ return ext.lstrip("."), parse_text
477
+ if not ext and name in TEXT_FILE_NAMES:
478
+ return "text", parse_text
427
479
  raise ValueError(f"Unsupported file type: {ext}")
428
480
 
429
481
 
@@ -0,0 +1,88 @@
1
+ export type KnowledgeIngestSkipReason =
2
+ | "hidden_path"
3
+ | "ignored_directory"
4
+ | "unsupported_file_type";
5
+
6
+ export type KnowledgeIngestFailureReason =
7
+ | "parser_error"
8
+ | "upload_error";
9
+
10
+ export interface KnowledgeIngestFileResult {
11
+ source: string;
12
+ localSourcePath: string;
13
+ outputPath: string;
14
+ remotePath: string;
15
+ slug: string;
16
+ sourceType: string;
17
+ summary: string;
18
+ stats: Record<string, unknown>;
19
+ warnings: string[];
20
+ }
21
+
22
+ export interface KnowledgeIngestSkippedFileResult {
23
+ source: string;
24
+ localSourcePath: string | null;
25
+ reason: KnowledgeIngestSkipReason;
26
+ message: string;
27
+ }
28
+
29
+ export interface KnowledgeIngestFailedFileResult {
30
+ source: string;
31
+ localSourcePath: string;
32
+ reason: KnowledgeIngestFailureReason;
33
+ message: string;
34
+ }
35
+
36
+ export interface KnowledgeIngestSummary {
37
+ requested_count: number;
38
+ ingested_count: number;
39
+ skipped_count: number;
40
+ failed_count: number;
41
+ }
42
+
43
+ export interface KnowledgeIngestResultMetadata {
44
+ requested_count: number;
45
+ source_mode: "explicit_sources" | "path_prefix";
46
+ knowledge_path: string;
47
+ }
48
+
49
+ export interface KnowledgeIngestJobResult {
50
+ kind: "knowledge_ingest";
51
+ version: 1;
52
+ metadata: KnowledgeIngestResultMetadata;
53
+ summary: KnowledgeIngestSummary;
54
+ ingested: KnowledgeIngestFileResult[];
55
+ skipped: KnowledgeIngestSkippedFileResult[];
56
+ failed: KnowledgeIngestFailedFileResult[];
57
+ }
58
+
59
+ export function buildKnowledgeIngestJobResult(input: {
60
+ requestedCount: number;
61
+ sourceMode: KnowledgeIngestResultMetadata["source_mode"];
62
+ knowledgePath: string;
63
+ ingested: KnowledgeIngestFileResult[];
64
+ skipped?: KnowledgeIngestSkippedFileResult[];
65
+ failed?: KnowledgeIngestFailedFileResult[];
66
+ }): KnowledgeIngestJobResult {
67
+ const skipped = input.skipped ?? [];
68
+ const failed = input.failed ?? [];
69
+
70
+ return {
71
+ kind: "knowledge_ingest",
72
+ version: 1,
73
+ metadata: {
74
+ requested_count: input.requestedCount,
75
+ source_mode: input.sourceMode,
76
+ knowledge_path: input.knowledgePath,
77
+ },
78
+ summary: {
79
+ requested_count: input.requestedCount,
80
+ ingested_count: input.ingested.length,
81
+ skipped_count: skipped.length,
82
+ failed_count: failed.length,
83
+ },
84
+ ingested: input.ingested,
85
+ skipped,
86
+ failed,
87
+ };
88
+ }
@@ -0,0 +1,164 @@
1
+ import { basename, extname, normalize } from "../../../src/platform/compat/path/index.js";
2
+ import type { KnowledgeIngestSkipReason } from "./result.js";
3
+
4
+ const RICH_FILE_EXTENSIONS = new Set([
5
+ ".pdf",
6
+ ".csv",
7
+ ".tsv",
8
+ ".docx",
9
+ ".xlsx",
10
+ ".xls",
11
+ ".pptx",
12
+ ".html",
13
+ ".htm",
14
+ ".txt",
15
+ ".json",
16
+ ".md",
17
+ ".mdx",
18
+ ]);
19
+
20
+ const TEXT_FALLBACK_EXTENSIONS = new Set([
21
+ ".c",
22
+ ".cc",
23
+ ".conf",
24
+ ".cpp",
25
+ ".cs",
26
+ ".css",
27
+ ".go",
28
+ ".h",
29
+ ".hpp",
30
+ ".ini",
31
+ ".java",
32
+ ".js",
33
+ ".jsonl",
34
+ ".jsx",
35
+ ".kt",
36
+ ".less",
37
+ ".lua",
38
+ ".mjs",
39
+ ".ndjson",
40
+ ".php",
41
+ ".pl",
42
+ ".py",
43
+ ".r",
44
+ ".rb",
45
+ ".rs",
46
+ ".sass",
47
+ ".scala",
48
+ ".scss",
49
+ ".sh",
50
+ ".sql",
51
+ ".swift",
52
+ ".toml",
53
+ ".tsx",
54
+ ".ts",
55
+ ".xml",
56
+ ".yaml",
57
+ ".yml",
58
+ ".zsh",
59
+ ]);
60
+
61
+ const TEXT_FALLBACK_FILENAMES = new Set([
62
+ "dockerfile",
63
+ "makefile",
64
+ "readme",
65
+ "license",
66
+ "changelog",
67
+ ]);
68
+
69
+ const IGNORED_DIRECTORY_NAMES = new Set([
70
+ "node_modules",
71
+ ]);
72
+
73
+ export type KnowledgeIngestSourceDecision =
74
+ | { kind: "ingest" }
75
+ | {
76
+ kind: "skip";
77
+ reason: KnowledgeIngestSkipReason;
78
+ message: string;
79
+ };
80
+
81
+ function normalizePathSegments(value: string): string[] {
82
+ return normalize(value)
83
+ .replaceAll("\\", "/")
84
+ .split("/")
85
+ .map((segment) => segment.trim())
86
+ .filter((segment) => segment.length > 0 && segment !== "." && segment !== "..");
87
+ }
88
+
89
+ function findHiddenSegment(segments: string[]): string | null {
90
+ for (const segment of segments) {
91
+ if (segment.startsWith(".")) {
92
+ return segment;
93
+ }
94
+ }
95
+
96
+ return null;
97
+ }
98
+
99
+ function findIgnoredDirectory(segments: string[]): string | null {
100
+ for (const segment of segments) {
101
+ if (IGNORED_DIRECTORY_NAMES.has(segment.toLowerCase())) {
102
+ return segment;
103
+ }
104
+ }
105
+
106
+ return null;
107
+ }
108
+
109
+ function isSupportedKnowledgeFile(path: string): boolean {
110
+ const extension = extname(path).toLowerCase();
111
+ if (
112
+ extension && (RICH_FILE_EXTENSIONS.has(extension) || TEXT_FALLBACK_EXTENSIONS.has(extension))
113
+ ) {
114
+ return true;
115
+ }
116
+
117
+ const fileName = basename(path).toLowerCase();
118
+ return TEXT_FALLBACK_FILENAMES.has(fileName);
119
+ }
120
+
121
+ function classifyCommonKnowledgePath(path: string): KnowledgeIngestSourceDecision | null {
122
+ const segments = normalizePathSegments(path);
123
+ const hiddenSegment = findHiddenSegment(segments);
124
+ if (hiddenSegment != null) {
125
+ return {
126
+ kind: "skip",
127
+ reason: "hidden_path",
128
+ message: `Hidden file or directory skipped: ${hiddenSegment}`,
129
+ };
130
+ }
131
+
132
+ const ignoredDirectory = findIgnoredDirectory(segments);
133
+ if (ignoredDirectory != null) {
134
+ return {
135
+ kind: "skip",
136
+ reason: "ignored_directory",
137
+ message: `Ignored directory skipped: ${ignoredDirectory}`,
138
+ };
139
+ }
140
+
141
+ return null;
142
+ }
143
+
144
+ export function classifyKnowledgeDirectoryPath(path: string): KnowledgeIngestSourceDecision {
145
+ return classifyCommonKnowledgePath(path) ?? { kind: "ingest" };
146
+ }
147
+
148
+ export function classifyKnowledgeSourcePath(path: string): KnowledgeIngestSourceDecision {
149
+ const commonDecision = classifyCommonKnowledgePath(path);
150
+ if (commonDecision != null) {
151
+ return commonDecision;
152
+ }
153
+
154
+ if (!isSupportedKnowledgeFile(path)) {
155
+ const extension = extname(path).toLowerCase();
156
+ return {
157
+ kind: "skip",
158
+ reason: "unsupported_file_type",
159
+ message: `Unsupported file type: ${extension || basename(path)}`,
160
+ };
161
+ }
162
+
163
+ return { kind: "ingest" };
164
+ }
package/src/deno.js CHANGED
@@ -1,6 +1,6 @@
1
1
  export default {
2
2
  "name": "veryfront",
3
- "version": "0.1.82",
3
+ "version": "0.1.84",
4
4
  "license": "Apache-2.0",
5
5
  "nodeModulesDir": "auto",
6
6
  "exclude": [
@@ -60,10 +60,16 @@ export {
60
60
  JobEventSchema,
61
61
  type JobEventsResponse,
62
62
  JobEventsResponseSchema,
63
+ type JobKind,
64
+ JobKindSchema,
65
+ type JobListItem,
66
+ JobListItemSchema,
63
67
  type JobLogsResponse,
64
68
  JobLogsResponseSchema,
65
69
  type JobResult,
66
70
  JobResultSchema,
71
+ type JobResultSummary,
72
+ JobResultSummarySchema,
67
73
  JobSchema,
68
74
  type JobStatus,
69
75
  JobStatusSchema,
@@ -73,8 +79,18 @@ export {
73
79
  JobTargetDefinitionsResponseSchema,
74
80
  type KnowledgeIngestBatchSource,
75
81
  KnowledgeIngestBatchSourceSchema,
82
+ type KnowledgeIngestBatchSourceWithMessage,
83
+ KnowledgeIngestBatchSourceWithMessageSchema,
84
+ type KnowledgeIngestFailedFileResult,
85
+ KnowledgeIngestFailedFileResultSchema,
76
86
  type KnowledgeIngestFileResult,
77
87
  KnowledgeIngestFileResultSchema,
88
+ type KnowledgeIngestJobResult,
89
+ KnowledgeIngestJobResultCountsSchema,
90
+ KnowledgeIngestJobResultMetadataSchema,
91
+ KnowledgeIngestJobResultSchema,
92
+ type KnowledgeIngestSkippedFileResult,
93
+ KnowledgeIngestSkippedFileResultSchema,
78
94
  PageInfoSchema,
79
95
  type PaginatedCronJobsResponse,
80
96
  PaginatedCronJobsResponseSchema,
@@ -9,6 +9,7 @@ export const JobStatusSchema = z.enum([
9
9
  ]);
10
10
 
11
11
  export const CronJobStatusSchema = z.enum(["active", "paused", "deleting"]);
12
+ export const JobKindSchema = z.enum(["knowledge_ingest"]).nullable();
12
13
 
13
14
  export const ReservedJobTargetFamilySchema = z.enum(["task:*", "workflow:*", "deploy:*"]);
14
15
 
@@ -20,6 +21,12 @@ export const PageInfoSchema = z.object({
20
21
  });
21
22
 
22
23
  const JsonObjectSchema = z.record(z.unknown());
24
+ const KnowledgeIngestSkipReasonSchema = z.enum([
25
+ "hidden_path",
26
+ "ignored_directory",
27
+ "unsupported_file_type",
28
+ ]);
29
+ const KnowledgeIngestFailureReasonSchema = z.enum(["parser_error", "upload_error"]);
23
30
 
24
31
  export const KnowledgeIngestFileResultSchema = z.object({
25
32
  source: z.string(),
@@ -33,27 +40,82 @@ export const KnowledgeIngestFileResultSchema = z.object({
33
40
  warnings: z.array(z.string()),
34
41
  });
35
42
 
43
+ export const KnowledgeIngestSkippedFileResultSchema = z.object({
44
+ source: z.string(),
45
+ localSourcePath: z.string().nullable(),
46
+ reason: KnowledgeIngestSkipReasonSchema,
47
+ message: z.string(),
48
+ });
49
+
50
+ export const KnowledgeIngestFailedFileResultSchema = z.object({
51
+ source: z.string(),
52
+ localSourcePath: z.string(),
53
+ reason: KnowledgeIngestFailureReasonSchema,
54
+ message: z.string(),
55
+ });
56
+
57
+ export const KnowledgeIngestJobResultMetadataSchema = z.object({
58
+ requested_count: z.number().int().nonnegative(),
59
+ source_mode: z.enum(["explicit_sources", "path_prefix"]),
60
+ knowledge_path: z.string(),
61
+ });
62
+
63
+ export const KnowledgeIngestJobResultCountsSchema = z.object({
64
+ requested_count: z.number().int().nonnegative(),
65
+ ingested_count: z.number().int().nonnegative(),
66
+ skipped_count: z.number().int().nonnegative(),
67
+ failed_count: z.number().int().nonnegative(),
68
+ });
69
+
70
+ export const KnowledgeIngestJobResultSchema = z.object({
71
+ kind: z.literal("knowledge_ingest"),
72
+ version: z.literal(1),
73
+ metadata: KnowledgeIngestJobResultMetadataSchema,
74
+ summary: KnowledgeIngestJobResultCountsSchema,
75
+ ingested: z.array(KnowledgeIngestFileResultSchema),
76
+ skipped: z.array(KnowledgeIngestSkippedFileResultSchema),
77
+ failed: z.array(KnowledgeIngestFailedFileResultSchema),
78
+ });
79
+
36
80
  export const JobResultSchema = z
81
+ .discriminatedUnion("kind", [
82
+ KnowledgeIngestJobResultSchema,
83
+ z.object({
84
+ kind: z.literal("value"),
85
+ value: z.unknown(),
86
+ }),
87
+ z.object({
88
+ kind: z.literal("artifacts"),
89
+ artifacts: z.array(z.unknown()),
90
+ }),
91
+ ])
92
+ .nullable();
93
+
94
+ export const JobResultSummarySchema = z
37
95
  .discriminatedUnion("kind", [
38
96
  z.object({
39
97
  kind: z.literal("knowledge_ingest"),
40
- files: z.array(KnowledgeIngestFileResultSchema),
98
+ state: z.enum(["success", "partial_success", "failed"]),
99
+ requested_count: z.number().int().nonnegative(),
100
+ ingested_count: z.number().int().nonnegative(),
101
+ skipped_count: z.number().int().nonnegative(),
102
+ failed_count: z.number().int().nonnegative(),
41
103
  }),
42
104
  z.object({
43
105
  kind: z.literal("value"),
44
- value: z.unknown(),
45
106
  }),
46
107
  z.object({
47
108
  kind: z.literal("artifacts"),
48
- artifacts: z.array(z.unknown()),
109
+ artifact_count: z.number().int().nonnegative(),
49
110
  }),
50
111
  ])
51
112
  .nullable();
52
113
 
53
- export const JobSchema = z.object({
114
+ const BaseJobSchema = z.object({
54
115
  id: z.string().uuid(),
55
116
  project_id: z.string().uuid(),
56
117
  environment_id: z.string().uuid().nullable(),
118
+ branch_id: z.string().nullable().optional().default(null),
57
119
  cron_job_id: z.string().uuid().nullable(),
58
120
  batch_id: z.string().uuid().nullable(),
59
121
  name: z.string(),
@@ -64,9 +126,6 @@ export const JobSchema = z.object({
64
126
  timeout_seconds: z.number(),
65
127
  backoff_limit: z.number(),
66
128
  exit_code: z.number().nullable(),
67
- failed_reason: z.string().nullable(),
68
- failure_detail: z.string().nullable(),
69
- result: JobResultSchema,
70
129
  started_at: z.string().nullable(),
71
130
  completed_at: z.string().nullable(),
72
131
  created_by: z.string().uuid().nullable(),
@@ -74,8 +133,22 @@ export const JobSchema = z.object({
74
133
  updated_at: z.string(),
75
134
  });
76
135
 
136
+ export const JobSchema = BaseJobSchema.extend({
137
+ failed_reason: z.string().nullable().optional().default(null),
138
+ kind: JobKindSchema.optional().default(null),
139
+ failure_detail: z.string().nullable().optional().default(null),
140
+ result_summary: JobResultSummarySchema.optional().default(null),
141
+ result: JobResultSchema.optional().default(null),
142
+ });
143
+
144
+ export const JobListItemSchema = BaseJobSchema.extend({
145
+ kind: JobKindSchema.optional().default(null),
146
+ failure_detail: z.string().nullable().optional().default(null),
147
+ result_summary: JobResultSummarySchema.optional().default(null),
148
+ });
149
+
77
150
  export const PaginatedJobsResponseSchema = z.object({
78
- data: z.array(JobSchema),
151
+ data: z.array(JobListItemSchema),
79
152
  page_info: PageInfoSchema,
80
153
  });
81
154
 
@@ -111,6 +184,10 @@ export const KnowledgeIngestBatchSourceSchema = z.object({
111
184
  warning_count: z.number().int().nonnegative(),
112
185
  });
113
186
 
187
+ export const KnowledgeIngestBatchSourceWithMessageSchema = KnowledgeIngestBatchSourceSchema.extend({
188
+ message: z.string(),
189
+ });
190
+
114
191
  export const JobBatchStatusCountsSchema = z.object({
115
192
  submitted: z.number().int().nonnegative(),
116
193
  working: z.number().int().nonnegative(),
@@ -125,8 +202,12 @@ export const JobBatchResultSchema = z
125
202
  kind: z.literal("knowledge_ingest"),
126
203
  total_count: z.number().int().nonnegative(),
127
204
  completed_count: z.number().int().nonnegative(),
205
+ skipped_count: z.number().int().nonnegative(),
206
+ failed_count: z.number().int().nonnegative(),
128
207
  processing: z.array(KnowledgeIngestBatchSourceSchema),
129
208
  completed: z.array(KnowledgeIngestBatchSourceSchema),
209
+ skipped: z.array(KnowledgeIngestBatchSourceWithMessageSchema),
210
+ failed: z.array(KnowledgeIngestBatchSourceWithMessageSchema),
130
211
  remaining: z.array(KnowledgeIngestBatchSourceSchema),
131
212
  remaining_label: z.enum(["Remaining Files", "Not Ingested Files"]),
132
213
  }),
@@ -161,6 +242,7 @@ export const CronJobSchema = z.object({
161
242
  id: z.string().uuid(),
162
243
  project_id: z.string().uuid(),
163
244
  environment_id: z.string().uuid().nullable(),
245
+ branch_id: z.string().nullable().optional().default(null),
164
246
  name: z.string(),
165
247
  status: CronJobStatusSchema,
166
248
  target: z.string(),
@@ -184,17 +266,32 @@ export const PaginatedCronJobsResponseSchema = z.object({
184
266
 
185
267
  export type JobStatus = z.infer<typeof JobStatusSchema>;
186
268
  export type CronJobStatus = z.infer<typeof CronJobStatusSchema>;
269
+ export type JobKind = z.infer<typeof JobKindSchema>;
187
270
  export type ReservedJobTargetFamily = z.infer<typeof ReservedJobTargetFamilySchema>;
188
271
 
189
272
  export type KnowledgeIngestFileResult = z.infer<typeof KnowledgeIngestFileResultSchema>;
273
+ export type KnowledgeIngestSkippedFileResult = z.infer<
274
+ typeof KnowledgeIngestSkippedFileResultSchema
275
+ >;
276
+ export type KnowledgeIngestFailedFileResult = z.infer<typeof KnowledgeIngestFailedFileResultSchema>;
277
+ export type KnowledgeIngestJobResultMetadata = z.infer<
278
+ typeof KnowledgeIngestJobResultMetadataSchema
279
+ >;
280
+ export type KnowledgeIngestJobResultCounts = z.infer<typeof KnowledgeIngestJobResultCountsSchema>;
281
+ export type KnowledgeIngestJobResult = z.infer<typeof KnowledgeIngestJobResultSchema>;
190
282
  export type JobResult = z.infer<typeof JobResultSchema>;
283
+ export type JobResultSummary = z.infer<typeof JobResultSummarySchema>;
191
284
  export type Job = z.infer<typeof JobSchema>;
285
+ export type JobListItem = z.infer<typeof JobListItemSchema>;
192
286
  export type PaginatedJobsResponse = z.infer<typeof PaginatedJobsResponseSchema>;
193
287
  export type JobEvent = z.infer<typeof JobEventSchema>;
194
288
  export type JobEventsResponse = z.infer<typeof JobEventsResponseSchema>;
195
289
  export type JobLogsResponse = z.infer<typeof JobLogsResponseSchema>;
196
290
 
197
291
  export type KnowledgeIngestBatchSource = z.infer<typeof KnowledgeIngestBatchSourceSchema>;
292
+ export type KnowledgeIngestBatchSourceWithMessage = z.infer<
293
+ typeof KnowledgeIngestBatchSourceWithMessageSchema
294
+ >;
198
295
  export type JobBatchStatusCounts = z.infer<typeof JobBatchStatusCountsSchema>;
199
296
  export type JobBatchResult = z.infer<typeof JobBatchResultSchema>;
200
297
  export type JobBatch = z.infer<typeof JobBatchSchema>;
@@ -117,7 +117,11 @@ export interface FileSystemAdapter {
117
117
  makeTempDir(prefix: string): Promise<string>;
118
118
  watch(paths: string | string[], options?: WatchOptions): FileWatcher;
119
119
  /** Resolve a file path with extension fallback (e.g., pages/test → pages/test.mdx) */
120
- resolveFile?(basePath: string): Promise<string | null>;
120
+ resolveFile?(basePath: string, options?: ResolveFileOptions): Promise<string | null>;
121
+ }
122
+
123
+ export interface ResolveFileOptions {
124
+ allowPagesPrefix?: boolean;
121
125
  }
122
126
 
123
127
  export interface DirEntry {
@@ -1,6 +1,7 @@
1
1
  import { logger } from "../../../../utils/index.js";
2
2
  import { CONFIG_INVALID } from "../../../../errors/index.js";
3
3
  import { getEnv } from "../../../compat/process.js";
4
+ import type { ResolveFileOptions } from "../../base.js";
4
5
  import { FileCache } from "../cache/file-cache.js";
5
6
  import type { FSAdapter, FSAdapterConfig } from "../veryfront/types.js";
6
7
  import { GitHubApiClient } from "./github-api-client.js";
@@ -115,9 +116,9 @@ export class GitHubFSAdapter implements FSAdapter {
115
116
  return this.dirOps.readdir(path);
116
117
  }
117
118
 
118
- async resolveFile(basePath: string): Promise<string | null> {
119
+ async resolveFile(basePath: string, options?: ResolveFileOptions): Promise<string | null> {
119
120
  await this.ensureInitialized();
120
- return this.statOps.resolveFile(basePath);
121
+ return this.statOps.resolveFile(basePath, options);
121
122
  }
122
123
 
123
124
  getCacheStats(): {
@@ -5,6 +5,7 @@ import {
5
5
  buildGitHubStatCacheKey,
6
6
  buildGitHubTreeCacheKey,
7
7
  } from "../../../../cache/index.js";
8
+ import type { ResolveFileOptions } from "../../base.js";
8
9
  import type { FileCache } from "../cache/file-cache.js";
9
10
  import type { GitHubApiClient } from "./github-api-client.js";
10
11
  import type { FileIndexEntry, FileInfo, GitHubTreeEntry, ResolvedGitHubConfig } from "./types.js";
@@ -176,7 +177,7 @@ export class GitHubStatOperations {
176
177
  }
177
178
  }
178
179
 
179
- async resolveFile(basePath: string): Promise<string | null> {
180
+ async resolveFile(basePath: string, options?: ResolveFileOptions): Promise<string | null> {
180
181
  await this.ensureIndex();
181
182
 
182
183
  const normalizedPath = normalizeGitHubPath(basePath, this.projectDir);
@@ -185,7 +186,7 @@ export class GitHubStatOperations {
185
186
  if (cached !== undefined) return cached;
186
187
 
187
188
  const resolved = this.tryResolve(normalizedPath) ??
188
- this.tryResolveWithPagesPrefix(normalizedPath);
189
+ (options?.allowPagesPrefix === false ? null : this.tryResolveWithPagesPrefix(normalizedPath));
189
190
 
190
191
  this.cache.set(cacheKey, resolved);
191
192
  return resolved;
@@ -9,7 +9,7 @@ import type {
9
9
  InvalidationCallbacks,
10
10
  ResolvedContentContext,
11
11
  } from "./types.js";
12
- import type { FileInfo } from "../../base.js";
12
+ import type { FileInfo, ResolveFileOptions } from "../../base.js";
13
13
  import { VeryfrontApiClient } from "../../veryfront-api-client/index.js";
14
14
  import type { Project } from "../../veryfront-api-client/index.js";
15
15
  import { FileCache } from "../cache/file-cache.js";
@@ -142,6 +142,24 @@ export class VeryfrontFSAdapter implements FSAdapter {
142
142
 
143
143
  return result;
144
144
  },
145
+ hasCachedFileList: async () => {
146
+ if (!this.contentContext) {
147
+ logger.debug("hasCachedFileList: no contentContext");
148
+ return false;
149
+ }
150
+
151
+ const cacheKey = buildFileListCacheKey(this.contentContext);
152
+ const result = await this.cache.getAsync<Array<{ path: string }>>(cacheKey);
153
+ const hasResult = Array.isArray(result) && result.length > 0;
154
+
155
+ logger.debug("hasCachedFileList lookup", {
156
+ cacheKey,
157
+ hasResult,
158
+ resultSize: result?.length ?? 0,
159
+ });
160
+
161
+ return hasResult;
162
+ },
145
163
  isPersistentCacheInvalidated: (prefix: string) => this.isPersistentCacheInvalidated(prefix),
146
164
  isReleaseBeingInvalidated: (releaseId: string) =>
147
165
  this.isPersistentCacheInvalidated(
@@ -410,9 +428,12 @@ export class VeryfrontFSAdapter implements FSAdapter {
410
428
  return this.statOps.exists(path);
411
429
  }
412
430
 
413
- async resolveFile(basePath: string): Promise<string | null> {
431
+ async resolveFile(
432
+ basePath: string,
433
+ options?: ResolveFileOptions,
434
+ ): Promise<string | null> {
414
435
  await this.ensureInitialized();
415
- return this.statOps.resolveFile(basePath);
436
+ return this.statOps.resolveFile(basePath, options);
416
437
  }
417
438
 
418
439
  dispose(): void {