[codex] Add real knowledge document extraction progress - #2727
Conversation
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 6f8ecd11f8
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
| slug: slugs[index], | ||
| sourceReference, | ||
| }, { | ||
| onProgress: (event) => { |
There was a problem hiding this comment.
Skip progress callbacks when nothing can log them
When knowledge ingest runs outside a run context, createKnowledgeIngestEventLogger() returns null, but this still passes a truthy no-op onProgress callback. In Deno, KreuzbergDocumentExtractor.extractInWorker() switches PDFs/PPT/PPTX to the new progress worker solely because options.onProgress exists, so ordinary ingests with no user-visible progress now take the slower/different page-by-page/PPTX XML path and can fail on files the existing native/WASM extractor would handle. Pass the callback only when deps.eventLogger exists.
Useful? React with 👍 / 👎.
| const slidePaths = Object.keys(zip.files) | ||
| .filter((path) => /^ppt\/slides\/slide\d+\.xml$/.test(path)) | ||
| .sort((left, right) => slideNumber(left) - slideNumber(right)); |
There was a problem hiding this comment.
Preserve the PPTX presentation order
For PPTX decks where slides were reordered or deleted and recreated, the numeric ppt/slides/slideN.xml filenames do not define the deck order; the order comes from ppt/presentation.xml and its relationships. This progress extraction path concatenates slide text in filename order, so generated knowledge markdown can put slide content in the wrong sequence for valid decks. Use the presentation slide list and relationship targets before iterating slides.
Useful? React with 👍 / 👎.
There was a problem hiding this comment.
Pull request overview
Adds real-time extraction progress reporting to knowledge document ingestion without changing the existing “one source document -> one markdown file under knowledge/” output contract. This threads an optional progress callback through the compat document-extraction surface and uses a new native progress-capable worker to emit page/slide/file completion events.
Changes:
- Introduces
DocumentExtractionProgressEvent+DocumentExtractionOptionsand plumbsonProgressthrough the knowledge parser and KreuzbergDocumentExtractorworker path. - Adds a native progress extraction worker for Deno that emits per-page PDF progress and per-slide PPTX progress (with file-level completion for formats without granular progress).
- Updates build/packaging to include the new worker and its new dependencies (
pdf-lib,jszip), plus adds tests covering progress forwarding and logging.
Verification:
- Not run in this review environment.
- PR description reports:
deno task test cli/commands/knowledge/command.test.ts,deno test --allow-all extensions/ext-document-kreuzberg/src/index.test.ts, anddeno task verifyin a clean env.
Reviewed changes
Copilot reviewed 16 out of 17 changed files in this pull request and generated 2 comments.
Show a summary per file
| File | Description |
|---|---|
| tests/unit/build/compile-binary-includes.test.ts | Asserts the new native progress worker is included in compiled binaries. |
| src/extensions/compat/native-services.ts | Adds progress event/options types and extends the DocumentExtractor.extractInWorker signature to accept options. |
| src/extensions/compat/index.ts | Re-exports the new compat progress types. |
| scripts/build/npm-package-metadata.ts | Marks jszip and pdf-lib as extension-owned dependencies for npm packaging. |
| scripts/build/compile-binary.ts | Ensures deno compile includes the new worker entrypoint. |
| scripts/build/build-npm-extension-packages.ts | Transpiles both extraction workers into the npm extension package output. |
| extensions/ext-document-kreuzberg/src/native-progress-extraction-worker.ts | New worker that extracts PDFs page-by-page and PPTX slide-by-slide and posts progress events. |
| extensions/ext-document-kreuzberg/src/index.ts | Routes Deno extraction through the new progress worker when onProgress is provided; adds idle/hard timeouts around worker extraction. |
| extensions/ext-document-kreuzberg/src/index.test.ts | Adds unit tests verifying the progress-capable path is selected for PDF/PPTX in Deno. |
| extensions/ext-document-kreuzberg/deno.json | Adds jszip/pdf-lib import mappings for the new worker. |
| deno.lock | Adds new dependency entries (and updates other resolved versions). |
| deno.json | Exposes veryfront/extensions/first-party-import as a public export/import mapping. |
| cli/shared/ensure-content-processor.ts | Switches to importing importFirstPartyExtensionModule via the public veryfront/extensions/first-party-import path. |
| cli/shared/default-contracts.ts | Same public import path update for first-party extension importing. |
| cli/commands/knowledge/parser.ts | Adds optional progress forwarding into Kreuzberg extraction from the knowledge parser path. |
| cli/commands/knowledge/command.ts | Logs structured extraction progress events during ingestion. |
| cli/commands/knowledge/command.test.ts | Adds tests ensuring extraction progress events are logged and the output contract remains one markdown file per source. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
| if (message.type === "progress") { | ||
| resetIdleTimer(); | ||
| try { | ||
| await options.onProgress?.(message.event); | ||
| } catch (error) { | ||
| fail(error instanceof Error ? error : new Error(String(error))); | ||
| } | ||
| return; | ||
| } |
| extractInWorker( | ||
| buffer: ArrayBuffer, | ||
| mimeType: string, | ||
| options?: { onProgress?: DocumentExtractionProgress }, | ||
| ): Promise<string>; |
Critical review — Score: 58 / 100Good intent and clean plumbing, but the core approach introduces two latent regressions and the PR description makes a "no behavior change" claim that the code contradicts. The type/contract work, build/packaging wiring, and plumbing tests are genuinely solid; the risk is concentrated in the new extraction strategy and how it's wired into the default path. What's good
Blocking / high-severity1. The new page-by-page path is now the DEFAULT for every PDF/PPTX ingest — contradicting the PR description. }, { onProgress: (event) => { deps.eventLogger?.info(...) } });The 2. No fallback on extraction failure — this can break the very PDFs it aims to fix. if (options.onProgress && isNativeProgressMimeType(mimeType)) {
try { return await extractWithNativeProgressDeno(...); }
catch (error) { if (!isMissingPackageError(error)) throw error; }
}Only a missing-package error falls back to native/WASM whole-file extraction. Any other failure — 3. PPTX extraction silently diverges from Kreuzberg (quality regression + two engines for one format). Medium4. Slide ordering by filename is not deck order (Codex P2 #2 — valid). 5. Idle timer races the 6. Performance. Page-by-page splits each PDF into N single-page docs via Low / nits
Bottom lineThe direction (real extraction progress) is worth having and the scaffolding is well done, but as written this ships a new, less-robust, differently-behaving extraction path as the default for the exact file types in the originating bug, with no fallback and no correctness tests. Address #1 (gate on logger) and #2 (fall back on any error) before merge; resolve #3/#4 or explicitly document the PPTX behavior change. With those fixed this is a straightforward approve. Automated critical review. Score reflects: strong plumbing/packaging, offset by a default-path behavior change contradicting the description, a robustness regression with no fallback, and untested new extraction logic. |
6f8ecd1 to
725c461
Compare
725c461 to
98aeece
Compare
Re-review (commit
|
98aeece to
a43f2ba
Compare
Re-review (commit
|
Summary
Adds real extraction progress for knowledge document ingestion while keeping the existing one-document-to-one-markdown-file output contract intact.
Refs veryfront/veryfront-studio#5484.
Root Cause
The visible staging failure was a timeout, but the timeout was only the symptom. The Bosch PDF is valid and native Kreuzberg/PDFium can extract it quickly. The problematic path was the Deno/WASM extraction route, which can hang or run slowly enough that ingestion appears stalled and eventually times out without any real document progress signal.
Changes
Contract
The output shape stays the same: one source document still produces one markdown file under
knowledge/; progress never splits output files or changes parser return shape.For PDFs and legacy PPT, progress is additional metadata/logging around native or whole-file extraction. For PPTX, logger-backed progress extraction uses an OpenXML slide-text path so it can emit real per-slide progress. That path preserves presentation order for visible slide text, but it can differ from the opaque Kreuzberg path in formatting/fidelity, for example speaker notes are not included. Programmatic/no-logger callers stay on the existing path unless they explicitly request progress, and failures fall back to the previous opaque extraction behavior.
Verification
deno task test cli/commands/knowledge/command.test.tscd extensions/ext-document-kreuzberg && deno test --allow-all src/index.test.tsenv -u OTEL_EXPORTER_OTLP_ENDPOINT -u OTEL_EXPORTER_OTLP_HEADERS -u OTEL_EXPORTER_OTLP_PROTOCOL -u OTEL_LOGS_EXPORTER -u OTEL_METRICS_EXPORTER -u OTEL_RESOURCE_ATTRIBUTES -u OTEL_TRACES_EXPORTER -u GRAFANA_SERVICE_ACCOUNT_TOKEN -u GRAFANA_URL deno task verify