[kit] Add PageIndex NotebookLM for vectorless tree-structured RAG#113
[kit] Add PageIndex NotebookLM for vectorless tree-structured RAG#113Skt329 wants to merge 29 commits intoLamatic:mainfrom
Conversation
…and chat functionality.
…upload, chat, list, and tree retrieval functionalities.
…uding document upload, chat, and tree index visualization.
…the PageIndex NotebookLM kit.
…eneration, and data saving flow.
…-with-pdf` flow.
…face for document interaction.
…agement and chat capabilities
…document interaction
|
Note Reviews pausedIt looks like this branch is under active development. To avoid overwhelming you with review comments due to an influx of new commits, CodeRabbit has automatically paused this review. You can configure this behavior by changing the Use the following commands to manage reviews:
Use the checkboxes below for quick actions:
WalkthroughThis PR adds a complete PageIndex NotebookLM Next.js kit: Lamatic flows (upload/index, chat/retrieve, list, get/delete), a Next frontend with components/styles, Lamatic client and orchestration helpers, types/utilities, configuration, and documentation. (Mission brief complete.) Changes
Suggested reviewers
🚥 Pre-merge checks | ✅ 2 | ❌ 1❌ Failed checks (1 warning)
✅ Passed checks (2 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ Finishing Touches🧪 Generate unit tests (beta)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
There was a problem hiding this comment.
Actionable comments posted: 28
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.
Inline comments:
In `@kits/assistant/pageindex-notebooklm/actions/orchestrate.ts`:
- Around line 117-129: deleteDocument currently calls lamaticClient.executeFlow
without any authorization checks; update it to require and verify a JWT and to
enforce ownership/permission before deleting. Specifically, accept the caller's
token/request context into deleteDocument, validate the JWT using your project's
verifyJwt (or an equivalent auth utility) to get the caller's user id, then
check permissions/ownership for the target doc_id (e.g., via a
getDocumentOwner(doc_id) or hasPermission(userId, doc_id) helper) and only call
lamaticClient.executeFlow(FLOW_ID_TREE, ...) when authorized; otherwise throw a
401/403 error.
- Line 44: The runtime check in orchestrate.ts that throws if
process.env.FLOW_ID_CHAT is redundant because the lamatic-client.ts module
already validates and throws on missing FLOW_ID_CHAT at import; remove the
duplicate check in orchestrate.ts (the line containing the FLOW_ID_CHAT throw)
so initialization relies on the single source of truth in lamatic-client.ts, or
if you prefer consistent defensive checks keep the validation only in a shared
helper used by both modules instead of duplicating it in the orchestrate.ts
file.
- Around line 52-62: The console.log calls in orchestrate.ts currently print
full payload and response (payload, data) which can expose sensitive
user/document data; update the logging around lamaticClient.executeFlow (and use
of process.env.FLOW_ID_CHAT) to avoid dumping raw content in production by
gating verbose logs behind a DEBUG or NODE_ENV check and/or redacting PII before
logging (e.g., log only metadata, flow id, sizes, or a masked summary instead of
payload/data). Ensure the console.log("[chatWithDocument] SENDING →", ...) and
console.log("[chatWithDocument] RECEIVED ←", ...) are replaced with conditional
or reduced-verbosity logs that never emit full user queries or document
contents.
In `@kits/assistant/pageindex-notebooklm/app/globals.css`:
- Around line 110-243: The file defines many hand-written component utilities
(.btn, .badge, .tab, .input, .glass, .badge-accent, .btn-accent, .noise::before,
.accent-line::after, etc.); refactor by moving these into a Tailwind `@layer`
components block and replace repetitive declarations with `@apply` of Tailwind
utility classes (e.g., compose .btn, .badge, .tab, .input using `@apply` px-4 py-2
rounded border font-medium flex items-center gap-2, etc.), preserve unique rules
that can’t be expressed via `@apply` (backdrop-filter, pseudo-element SVG
background, box-shadow/glow) inline inside the same component block, and keep
existing CSS variables for colors and radii; this centralizes styles into
Tailwind’s component layer while keeping selectors like .noise::before and
.accent-line::after intact.
In `@kits/assistant/pageindex-notebooklm/app/page.tsx`:
- Around line 69-72: The file contains inline SVGs (the two-book path SVG block)
that should be replaced with lucide-react icons for consistency; import the
appropriate lucide-react icon (e.g., BookOpen or Books) at the top of page.tsx
and replace the inline <svg> block with the corresponding JSX icon component,
preserving any sizing/props (width/height/stroke color/className) previously
applied and removing the raw SVG markup; ensure the new import is added and used
wherever similar inline SVGs appear in this file.
- Around line 178-186: The onDeleted handler currently reads the stale
outer-scope documents array; instead change the onDeleted callback to accept the
deleted doc_id from DocumentList and use that to clear selection: update
DocumentList to call onDeleted(deletedDocId) when deletion finishes, change the
onDeleted implementation here to onDeleted={(deletedDocId) => {
fetchDocuments(); setSelectedDoc(prev => prev?.doc_id === deletedDocId ? null :
prev); }} so you no longer rely on the captured documents array; keep
fetchDocuments() call as-is.
In `@kits/assistant/pageindex-notebooklm/components/ChatWindow.tsx`:
- Around line 8-35: The renderMarkdown function returns raw HTML and must be
sanitized to prevent XSS: integrate a sanitizer such as DOMPurify and call it on
the HTML produced by renderMarkdown before returning or before using
dangerouslySetInnerHTML; update the renderMarkdown flow (function name:
renderMarkdown) to produce the same HTML string but pass the result through
DOMPurify.sanitize(...) and return the sanitized string, and ensure any other
places that inject HTML (e.g., the component code that uses
dangerouslySetInnerHTML around these lines) also sanitize output with DOMPurify
before rendering.
- Around line 179-181: Replace the inline SVG in the ChatWindow component with
the appropriate lucide-react icon component (e.g., MessageSquare) and update
imports accordingly: add "MessageSquare" to the import from 'lucide-react' at
the top of ChatWindow.tsx, remove the inline <svg> block, and render
<MessageSquare /> with equivalent sizing and styling (use size or className and
tailwind/CSS variables to match stroke color and dimensions). Ensure any other
inline icons in this file follow the same pattern (swap to the suggested
lucide-react components like Bot, Search, ChevronDown, Send where present) so
the component uses lucide-react consistently.
- Around line 130-138: The ChatWindow component is using inline style for the
main container and a custom collapsible sources panel; replace these with
shadcn/ui (and Radix) primitives to follow kit guidelines: swap the top-level
styled div in ChatWindow and its inline styling for a shadcn container component
(e.g., Card/Panel/Shell) using existing CSS variables and className patterns,
and replace the custom collapsible implementation around the sources panel with
shadcn/ui's Collapsible (Radix Collapsible) so theming, spacing, and
accessibility are consistent with the rest of the kit; update the JSX to import
and use Collapsible, move inline styles into className utility classes, and
ensure existing bottom input/button class names are preserved.
- Around line 104-118: The silent JSON.parse failure when reading
result.messages should be logged for diagnostics: in the parsing block where
parsed is computed from result.messages (the try/catch that currently returns
null on error), catch the exception and call console.warn (or a logger) with the
error and the original result.messages string so you can see malformed payloads;
ensure this still results in parsed being null and preserves the existing
fallback that builds nextHistory and calls setLamaticHistory(nextHistory).
In `@kits/assistant/pageindex-notebooklm/components/DocumentList.tsx`:
- Around line 24-26: The empty catch in DocumentList.tsx swallows deletion
errors; update the catch to capture the error (e.g., catch (err)) and surface it
— log it (console.error or your logging utility) and/or set a component error
state (e.g., setDeleteError) so the UI can show feedback. Locate the try/catch
around the delete/remove operation in DocumentList (the delete handler or
function that calls the API) and change the catch to record the error and set a
user-visible error message before the finally block so users are informed when
deletion fails.
- Around line 214-217: The inline <style> tag that sets hover rules for
.doc-delete-btn is currently rendered inside the DocumentList component's
per-item rendering (inside the .map loop), causing a duplicate <style> injection
for every document; move that CSS out of the item render — either place the
style block once at the top-level of the DocumentList component (above/around
the .map) or put the rules into an external CSS/CSS module and reference the
class from the list items so the styles are defined only once; update the render
logic around the .map and ensure the class names (doc-delete-btn) remain
unchanged.
In `@kits/assistant/pageindex-notebooklm/components/DocumentUpload.tsx`:
- Around line 16-21: In processFile replace the loose file.type.includes("pdf")
check with an explicit allowed-mime list (e.g.,
["application/pdf","text/markdown","text/x-markdown"]) and verify file.type is
one of those OR the filename endsWith(".md"); update the validation in the
processFile function to use that allowedTypes.includes(file.type) check while
retaining the .md extension fallback so Markdown remains supported when browsers
report inconsistent MIME types.
- Around line 35-36: The auto-reset setTimeout call (setTimeout(() => {
setStatus("idle"); setMessage(""); }, 3500)) can clash with a subsequent upload;
capture the timer id when calling setTimeout, store it in a ref (e.g.,
resetTimerRef) or state, and call clearTimeout(resetTimerRef.current) before
starting a new upload and in a cleanup (useEffect return) so a previous timer
can't reset setStatus/setMessage mid-flight; update any upload-starting function
to clear the prior timer before scheduling a new one.
In `@kits/assistant/pageindex-notebooklm/components/TreeViewer.tsx`:
- Around line 78-95: Replace the inline SVG and custom dot span with
lucide-react icons for consistency: import { ChevronRight, Circle } from
'lucide-react' at the top of TreeViewer.tsx, then render <ChevronRight size={12}
strokeWidth={2.5} style={{ transform: open ? "rotate(90deg)" : "rotate(0)",
transition: "transform 0.2s var(--ease)", color: isHighlighted ? "var(--amber)"
: "var(--text-3)" }} /> when hasChildren is true, and render <Circle size={5}
style={{ color: isHighlighted ? "var(--amber)" : "var(--border-md)", margin:
"4px 4.5px" }} /> when hasChildren is false; keep references to hasChildren,
isHighlighted and open to preserve behavior and adjust styling props to match
the previous visuals.
- Line 53: The current per-node check uses highlightedIds.includes(node.node_id)
which is O(n); update TreeViewer to use O(1) lookups by converting
highlightedIds into a Set once (e.g., derive highlightedIdSet via useMemo when
highlightedIds changes) and then replace highlightedIds.includes(node.node_id)
with highlightedIdSet.has(node.node_id); ensure you reference the prop/variable
name highlightedIds and the local isHighlighted computation so only the lookup
logic changes.
In `@kits/assistant/pageindex-notebooklm/config.json`:
- Around line 62-66: Update the JSON config by populating the empty demoUrl
field with the live preview URL "https://pageindex-notebooklm.vercel.app/";
locate the properties demoUrl, deployUrl, documentationUrl, and imageUrl in the
config.json and set demoUrl to that value (and optionally fill deployUrl,
documentationUrl, and imageUrl with appropriate links or remove them if not
applicable) so the kit's discoverability reflects the PR description.
In `@kits/assistant/pageindex-notebooklm/flows/chat-with-pdf/meta.json`:
- Around line 3-8: Populate the flow metadata in meta.json by adding a clear,
one- or two-sentence "description" summarizing the flow purpose (e.g.,
chat-with-pdf using NotebookLM), a short list in "tags" for discoverability
(e.g., ["pdf", "notebooklm", "assistant", "document-search"]), a representative
"testInput" string that demonstrates expected input for automated tests, and
valid URLs for "githubUrl", "documentationUrl", and "deployUrl" (or placeholder
links to corresponding docs/CI if not yet available); update the keys
"description", "tags", "testInput", "githubUrl", "documentationUrl", and
"deployUrl" in kits/assistant/pageindex-notebooklm/flows/chat-with-pdf/meta.json
so other contributors and CI can find and validate the flow.
In
`@kits/assistant/pageindex-notebooklm/flows/flow-1-upload-pdf-build-tree-save/config.json`:
- Around line 159-163: The variables mapping in variablesNode_617 has a typo:
the key "tre_node_count" should be "tree_node_count"; update the mapping string
under the "mapping" value to rename "tre_node_count" to "tree_node_count" so it
matches InstructorLLMNode_tree.output.tree_node_count and remains consistent
with downstream references (e.g., any code or nodes expecting tree_node_count).
- Around line 192-195: The Save to Supabase code node is using the wrong output
field name for the uploaded file URL; update the fileUrl assignment in the
codeNode_save values to use codeNode_630.output.resolved_url (not resolver_url)
so fileUrl is populated correctly before building the payload and sending to
Supabase.
In
`@kits/assistant/pageindex-notebooklm/flows/flow-1-upload-pdf-build-tree-save/meta.json`:
- Around line 3-8: The meta.json currently has empty metadata fields; populate
"description" with a concise summary of the flow purpose, fill "tags" with
relevant keywords (e.g., "upload", "pdf", "pageindex", "notebooklm"), add a
realistic "testInput" example string that exercises the flow, and provide valid
"githubUrl", "documentationUrl", and "deployUrl" values or placeholder links so
the asset is discoverable and deployable; update these keys in the same JSON
object to improve cataloging and operational readiness.
In
`@kits/assistant/pageindex-notebooklm/flows/flow-4-get-tree-structure/meta.json`:
- Around line 1-9: The file containing the flow metadata (the JSON object with
"name": "Flow 4 Get tree structure") is missing a trailing newline; please add a
single newline character at the end of the file so the file ends with a newline
to avoid "No newline at end of file" warnings from linters and tools.
In
`@kits/assistant/pageindex-notebooklm/flows/flow-list-all-documents/config.json`:
- Around line 57-65: The API Response node's outputMapping incorrectly sets
"total" to postgresNode_831.output.status (a status string) causing
Number(data?.total) in orchestrate.ts to yield NaN; update the API Response
outputMapping so "total" is mapped to the actual array length
(postgresNode_831.output.queryResult.length) instead of .status (edit the
outputMapping for node id responseNode_triggerNode_1 / key "outputMapping" in
Lamatic Studio), or add a small Code node after postgresNode_831 that sets a
numeric total from queryResult.length and map to that computed field if Studio
prevents direct length expressions.
In `@kits/assistant/pageindex-notebooklm/flows/flow-list-all-documents/meta.json`:
- Around line 1-9: The meta.json file for the "flow list all documents" flow is
missing a trailing newline; update the file (meta.json containing the "name":
"flow list all documents" entry) to add a single newline character after the
closing brace so the file ends with a newline to satisfy Unix text file
conventions and avoid tooling warnings.
In `@kits/assistant/pageindex-notebooklm/lib/types.ts`:
- Around line 51-56: UploadResponse.tree_node_count is incorrectly declared as
string while Document.tree_node_count and TreeResponse.tree_node_count are
numbers; change the UploadResponse interface's tree_node_count type to number
(i.e., update UploadResponse to use tree_node_count: number) and, if the API
actually returns a string, adjust the deserialization/parsing code that creates
UploadResponse instances to parseInt/Number the value before assigning so the
type stays consistent with Document and TreeResponse.
In `@kits/assistant/pageindex-notebooklm/package.json`:
- Around line 11-27: Update package.json to use fully pinned versions instead of
caret ranges so this kit doesn't inherit unintended upgrades: replace entries
under "dependencies" (clsx, lamatic, lucide-react, next, react, react-dom,
tailwindcss) and "devDependencies" (`@tailwindcss/postcss`, `@types/node`,
`@types/react`, `@types/react-dom`, postcss, typescript) with exact version strings
(no ^ or ~), ensuring each package line in the dependencies and devDependencies
blocks is updated to a specific fixed version.
In `@kits/assistant/pageindex-notebooklm/README.md`:
- Around line 194-217: The project structure diagram lacks language/framework
classification; update the README tree to annotate that this kit uses TypeScript
and Next.js/React (TSX) so readers immediately know the tech stack—e.g., label
files like orchestrate.ts, lamatic-client.ts, types.ts as TypeScript and files
like layout.tsx, page.tsx, ChatWindow.tsx, DocumentList.tsx, DocumentUpload.tsx,
TreeViewer.tsx as TSX/React, and add a short parent note such as “(TypeScript ·
Next.js/React)” near the top of the pageindex-notebooklm/ header to make the
language explicit.
- Around line 27-55: The fenced ASCII diagram in the README.md is missing a code
block language specifier; update the opening fence for the diagram block (the
triple-backtick before the ASCII art) to include a language identifier such as
"text" so the block becomes ```text, ensuring proper rendering and accessibility
for the diagram in kits/assistant/pageindex-notebooklm/README.md.
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: Repository UI (base), Organization UI (inherited)
Review profile: ASSERTIVE
Plan: Pro
Run ID: ad87f7a1-40c7-4442-9cff-b4bb71e1f4ba
⛔ Files ignored due to path filters (1)
kits/assistant/pageindex-notebooklm/package-lock.jsonis excluded by!**/package-lock.json
📒 Files selected for processing (36)
kits/assistant/pageindex-notebooklm/.env.examplekits/assistant/pageindex-notebooklm/.gitignorekits/assistant/pageindex-notebooklm/README.mdkits/assistant/pageindex-notebooklm/actions/orchestrate.tskits/assistant/pageindex-notebooklm/app/globals.csskits/assistant/pageindex-notebooklm/app/layout.tsxkits/assistant/pageindex-notebooklm/app/page.tsxkits/assistant/pageindex-notebooklm/components.jsonkits/assistant/pageindex-notebooklm/components/ChatWindow.tsxkits/assistant/pageindex-notebooklm/components/DocumentList.tsxkits/assistant/pageindex-notebooklm/components/DocumentUpload.tsxkits/assistant/pageindex-notebooklm/components/TreeViewer.tsxkits/assistant/pageindex-notebooklm/config.jsonkits/assistant/pageindex-notebooklm/flows/chat-with-pdf/README.mdkits/assistant/pageindex-notebooklm/flows/chat-with-pdf/config.jsonkits/assistant/pageindex-notebooklm/flows/chat-with-pdf/inputs.jsonkits/assistant/pageindex-notebooklm/flows/chat-with-pdf/meta.jsonkits/assistant/pageindex-notebooklm/flows/flow-1-upload-pdf-build-tree-save/README.mdkits/assistant/pageindex-notebooklm/flows/flow-1-upload-pdf-build-tree-save/config.jsonkits/assistant/pageindex-notebooklm/flows/flow-1-upload-pdf-build-tree-save/inputs.jsonkits/assistant/pageindex-notebooklm/flows/flow-1-upload-pdf-build-tree-save/meta.jsonkits/assistant/pageindex-notebooklm/flows/flow-4-get-tree-structure/README.mdkits/assistant/pageindex-notebooklm/flows/flow-4-get-tree-structure/config.jsonkits/assistant/pageindex-notebooklm/flows/flow-4-get-tree-structure/inputs.jsonkits/assistant/pageindex-notebooklm/flows/flow-4-get-tree-structure/meta.jsonkits/assistant/pageindex-notebooklm/flows/flow-list-all-documents/README.mdkits/assistant/pageindex-notebooklm/flows/flow-list-all-documents/config.jsonkits/assistant/pageindex-notebooklm/flows/flow-list-all-documents/inputs.jsonkits/assistant/pageindex-notebooklm/flows/flow-list-all-documents/meta.jsonkits/assistant/pageindex-notebooklm/lib/lamatic-client.tskits/assistant/pageindex-notebooklm/lib/types.tskits/assistant/pageindex-notebooklm/next-env.d.tskits/assistant/pageindex-notebooklm/next.config.mjskits/assistant/pageindex-notebooklm/package.jsonkits/assistant/pageindex-notebooklm/postcss.config.mjskits/assistant/pageindex-notebooklm/tsconfig.json
kits/assistant/pageindex-notebooklm/flows/flow-list-all-documents/meta.json
Outdated
Show resolved
Hide resolved
|
Hi @Skt329! 👋 Before this PR can be reviewed by maintainers, please resolve all comments and requested changes from the CodeRabbit automated review. Steps to follow:
This helps keep the review process efficient for everyone. Thank you! 🙏 |
…th upload, list, and chat capabilities
…d markdown rendering for document interaction
…nd tree visualization
…less tree-structured RAG flows
PR Review Response — PageIndex NotebookLM AuditThank you for the thorough review! I've gone through every finding and addressed them all. Below is a point-by-point response with the resolution status for each item.
|
| Category | Total | ✅ Resolved | |
|---|---|---|---|
| Security | 3 | 2 | 1 (auth — demo design) |
| Code Quality | 8 | 8 | 0 |
| UI / Icons | 5 | 5 | 0 |
| Config / Metadata | 9 | 9 | 0 |
| Types & Deps | 3 | 3 | 0 |
| Documentation | 2 | 2 | 0 |
| Total | 30 | 29 | 1 |
The single deferred item (deleteDocument JWT auth) is an intentional architectural decision for a demo kit — documented in-code with clear production guidance. All other findings are fully resolved.
There was a problem hiding this comment.
Actionable comments posted: 19
♻️ Duplicate comments (1)
kits/assistant/pageindex-notebooklm/actions/orchestrate.ts (1)
123-132:⚠️ Potential issue | 🔴 CriticalMission critical:
deleteDocumentis still an unauthenticated destructive action.This server action accepts any
doc_idand executes the delete flow directly. Any client that can invoke it can delete documents it does not own.🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@kits/assistant/pageindex-notebooklm/actions/orchestrate.ts` around lines 123 - 132, The deleteDocument function currently invokes lamaticClient.executeFlow with any doc_id and is unauthenticated; before calling deleteDocument's deletion flow (deleteDocument and lamaticClient.executeFlow), validate the caller's JWT and authorize ownership: verify the token (e.g., verifyJwt(token)) to extract the user id, then check the document owner (e.g., getDocumentOwner(doc_id)) against that user id and only proceed to call lamaticClient.executeFlow when they match; if verification/authorization fails, return/throw an appropriate 401/403 error and do not call the flow.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.
Inline comments:
In `@kits/assistant/pageindex-notebooklm/actions/orchestrate.ts`:
- Around line 20-28: Validate the upload contract in uploadDocument before
calling lamaticClient.executeFlow: ensure exactly one of options.file_url or
options.file_base64 is present (reject if both or neither), and if
options.file_base64 is provided require options.mime_type to be present; throw a
descriptive error (or return/reject) so the FLOW_ID_UPLOAD call is never made
with an invalid options object.
In `@kits/assistant/pageindex-notebooklm/app/page.tsx`:
- Around line 45-54: The handleSelectDoc function can suffer a race where an
earlier getDocumentTree(doc.doc_id) resolves after a later selection and
overwrites state; fix by attaching a request token (e.g., incrementing requestId
or using an AbortController) when starting the fetch and capture it in a local
variable, then before calling setTree or setTreeLoading(false) verify the token
still matches the latest (or the controller wasn't aborted) and only apply the
result if it does; reference handleSelectDoc, getDocumentTree, setTree,
setTreeLoading, and selectedDoc/doc.doc_id when adding the token check or abort
logic.
In `@kits/assistant/pageindex-notebooklm/components/ChatWindow.tsx`:
- Around line 135-139: The branch only updates state when result.retrieved_nodes
has length, leaving previous retrieval UI/states stale when an empty result
arrives; change the logic around setLastNodes, setLastThinking, and
onRetrievedNodes so that you always update/clear them when
result.retrieved_nodes is present (or is an array) — e.g., if
Array.isArray(result.retrieved_nodes) then call
setLastNodes(result.retrieved_nodes) (which may be []),
setLastThinking(result.thinking || ""), and invoke
onRetrievedNodes?.(result.retrieved_nodes) so empty turns clear the sources
panel and highlights instead of keeping previous values.
- Around line 97-100: Install react-hook-form and zod, then refactor the
ChatWindow form to use the kit-standard form pattern: replace the manual input
state and the handleSend function logic with a react-hook-form form using
FormProvider/useFormContext and a schema created with zod; use Controller for
the input component and perform validation via the zod resolver so submission
uses form.handleSubmit instead of e.preventDefault in handleSend, and update the
submit-related code referenced around handleSend and the block at lines ~371-395
to call the same submit handler from useForm (ensuring Message creation and
loading checks remain inside the form submit handler).
In `@kits/assistant/pageindex-notebooklm/components/DocumentList.tsx`:
- Around line 57-60: The delete control (class "doc-delete-btn") in
DocumentList.tsx is currently a non-focusable div that only appears on hover,
making it inaccessible to keyboard users; change that element into a real
<button> (or a semantic button element) placed outside the row-level button (the
row click handler) so it is not nested inside another interactive element, add
an accessible label (aria-label) and keyboard activation, and update the CSS to
reveal the button on :focus-visible and :focus-within as well as :hover so
keyboard users can discover and trigger deletion; apply the same fixes for the
other instance referenced around lines 132-153.
In `@kits/assistant/pageindex-notebooklm/components/DocumentUpload.tsx`:
- Around line 21-24: The early-return branch in DocumentUpload.tsx that handles
unsupported file types sets status to "error" and message but never schedules
the reset used elsewhere, leaving the picker stuck; update the invalid-file
branch in the upload/handleFile logic to either reset status back to "idle"
before returning or reuse the same reset timer/cleanup used by the success and
error paths (the code that calls setStatus and the reset used around line 61),
so the file picker can be reopened after an invalid selection; reference
setStatus, setMessage, and the existing reset/timer logic in this component when
implementing the fix.
- Around line 59-94: The clickable upload container in DocumentUpload is
currently a non-focusable <div>, blocking keyboard/assistive users; update the
container (the element using isIdle, inputRef, processFile, dragging, status) to
be an actual <button> or at minimum add tabIndex={0}, role="button", aria-label
and a key handler that calls inputRef.current?.click() for Enter/Space (mirror
the onClick behavior only when isIdle), and ensure keydown prevents default and
respects setDragging/state like the mouse handlers; also keep clearing
e.target.value in the input onChange and preserve visual focus styles for
accessibility.
- Around line 20-23: The uploader currently allows Markdown via allowedTypes and
filename checks (file.type, file.name) but the downstream flow
flows/flow-1-upload-pdf-build-tree-save only handles PDFs, causing guaranteed
failures; either remove Markdown from allowedTypes and update the user message
in the DocumentUpload component (where setStatus and setMessage are used) to say
"Only PDF files are supported," or implement a Markdown handling path in the
flow (add a Markdown extraction branch in
flows/flow-1-upload-pdf-build-tree-save) and ensure the upload handler routes
.md files to that branch.
In `@kits/assistant/pageindex-notebooklm/components/TreeViewer.tsx`:
- Around line 17-42: buildTree currently blindly links nodes and will
infinite-recurse on self-loops or cycles (e.g., A→B→A); add cycle detection and
reject cyclic graphs before returning roots by performing a DFS on the
constructed Map of TreeNodeResolved (use functions/identifiers buildTree,
TreeNodeResolved, TreeNode, totalNodes, and the recursive row renderer as points
to protect). Specifically, after creating map entries but before populating
children or before returning roots, run a traversal that tracks a visitation
state (unvisited/visiting/visited) for each node_id, detect any self-loop or
back-edge (visiting encountered again) and throw or return an explicit error
indicating a cycle (include offending node ids), so downstream totalNodes() and
the row renderer never receive cyclic structures. Ensure the check is applied in
buildTree and used the same validation on any code paths that populate nodes
(e.g., where nodes arrays are assigned) to prevent cycles from slipping in.
- Around line 63-78: Replace the interactive <div> wrapper in TreeViewer.tsx
with a semantic <button> so keyboard users and screen readers can interact; keep
the same inline styles and click behavior tied to hasChildren and setOpen, add
aria-expanded={open} to expose state, and add an onKeyDown handler that toggles
setOpen when Enter or Space is pressed (while preventing default for Space) so
keyboard activation works the same as the mouse click; preserve the
onMouseEnter/onMouseLeave visual logic and cursor logic (cursor should still
reflect hasChildren).
In `@kits/assistant/pageindex-notebooklm/components/ui/card.tsx`:
- Around line 1-92: Rename the file from card.tsx to Card.tsx to follow
PascalCase component filename convention; ensure the exported components (Card,
CardHeader, CardFooter, CardTitle, CardAction, CardDescription, CardContent)
remain unchanged and the default export list stays the same; update any imports
elsewhere that reference "./card" or "card" to use "./Card" (or the correct path
with capital C) so consumers resolve the renamed module; run the build/typecheck
to catch any missed import paths.
In `@kits/assistant/pageindex-notebooklm/components/ui/collapsible.tsx`:
- Around line 1-33: Rename the component file to PascalCase to match the
exported React components (the file should start with an uppercase name matching
the components), and update all imports that reference the old lowercase
filename; specifically ensure the file name aligns with the exported symbols
Collapsible, CollapsibleTrigger, and CollapsibleContent and adjust any import
statements across the codebase to reference the new filename so builds and type
checks succeed.
In
`@kits/assistant/pageindex-notebooklm/flows/flow-1-upload-pdf-build-tree-save/config.json`:
- Line 39: The current node uploads PDFs and returns a public URL (publicUrl)
which makes files world-readable or invalid for private buckets; change the flow
to keep the Supabase bucket private, upload using the existing upload logic
(storagePath, uploadResp) but do not set output.resolved_url to the /public/...
URL; instead generate and return a short-lived signed URL (use Supabase signed
URL endpoint or create a signed download token using serviceKey) and set
output.resolved_url to that signed/authenticated URL, keeping
uploaded_to_storage true; after you update the node in Lamatic Studio export the
flow from the Studio UI rather than hand-editing config.json.
- Line 194: The save code always sets status: "completed" and hides failures;
update the post-write logic in the code that builds payload/response (symbols:
payload, response, result, output, sanitize) to set payload.status to
"completed" only when response.ok, otherwise set payload.status to "failed" (or
"error") and populate output.success = false and output.error with result.error
|| result || response.statusText; then either throw an Error containing the
response status/result or return the failing output so the flow/node
(codeNode_save) surfaces errors to DocumentUpload.tsx instead of reporting
success for 4xx/5xx responses. Ensure response.ok is checked before using
result[0] and include the actual error details in output.
- Line 100: The save node is persisting the wrong payload: instead of saving the
formatted string created at codeNode_format.output.raw_text you’re saving
extractFromFileNode_1.output.files[0].data (the page array); update the
codeNode_save configuration to use the already-built formatted raw text
(reference codeNode_format.output.raw_text) when writing to storage so Lamatic
Studio persists the [PAGE N] annotated string (not the original pages array from
extractFromFileNode_1); re-export the flow from Lamatic Studio (do not hand-edit
other flow/edges) after making this change.
In
`@kits/assistant/pageindex-notebooklm/flows/flow-list-all-documents/config.json`:
- Line 35: The current SQL in config.json returns all rows and sensitive
file_url values; change the "query" to include a WHERE clause that scopes
results to the current user/session (e.g. "WHERE owner_id = :ownerId" or "WHERE
session_key = :sessionKey" and bind that parameter from Lamatic Studio), remove
or restrict file_url if not needed, and then re-export the flow from Lamatic
Studio so the config.json matches the node/edge schema (do not hand-edit
further).
In `@kits/assistant/pageindex-notebooklm/lib/types.ts`:
- Around line 44-49: The ChatResponse type is out of sync with chatWithDocument:
the action returns messages (and currently omits doc_id) but ChatResponse
declares doc_id and no messages; update the contract so consumers remain
type-safe by modifying ChatResponse (in types.ts) to include a messages property
(e.g. messages: unknown[] or the proper Message type) and make doc_id optional
or remove it to match chatWithDocument’s actual return value; alternatively, if
doc_id must be part of the contract, change chatWithDocument to return doc_id as
well—adjust ChatWindow usage (remove the unsafe cast) accordingly and keep
RetrievedNode referenced as-is.
In `@kits/assistant/pageindex-notebooklm/README.md`:
- Around line 140-141: The README currently advises enabling RLS and then
creating a permissive policy with create policy "service_access" on documents
for all using (true), which exposes documents to all client roles; instead keep
RLS enabled and replace that permissive policy with one that only allows the
Supabase service role (e.g., check auth.role() = 'service_role') and/or the
document owner, so only server-side access or the rightful owner can read/write
the documents; update the README instructions to show the policy should restrict
to service_role (and mention owner-based condition if applicable) rather than
using (true).
- Around line 155-160: The README currently lists SUPABASE_URL and
SUPABASE_ANON_KEY but is missing SUPABASE_SERVICE_ROLE_KEY; update the README
secrets table to include SUPABASE_SERVICE_ROLE_KEY (used by
flow-1-upload-pdf-build-tree-save for storage upload and POST to
/rest/v1/documents) and add a note that this key must be stored server-side in
Lamatic Secrets only (do not expose client-side).
---
Duplicate comments:
In `@kits/assistant/pageindex-notebooklm/actions/orchestrate.ts`:
- Around line 123-132: The deleteDocument function currently invokes
lamaticClient.executeFlow with any doc_id and is unauthenticated; before calling
deleteDocument's deletion flow (deleteDocument and lamaticClient.executeFlow),
validate the caller's JWT and authorize ownership: verify the token (e.g.,
verifyJwt(token)) to extract the user id, then check the document owner (e.g.,
getDocumentOwner(doc_id)) against that user id and only proceed to call
lamaticClient.executeFlow when they match; if verification/authorization fails,
return/throw an appropriate 401/403 error and do not call the flow.
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: Repository UI (base), Organization UI (inherited)
Review profile: ASSERTIVE
Plan: Pro
Run ID: 305417ab-775d-476e-8cbf-eacbd37c793a
⛔ Files ignored due to path filters (1)
kits/assistant/pageindex-notebooklm/package-lock.jsonis excluded by!**/package-lock.json
📒 Files selected for processing (20)
kits/assistant/pageindex-notebooklm/README.mdkits/assistant/pageindex-notebooklm/actions/orchestrate.tskits/assistant/pageindex-notebooklm/app/globals.csskits/assistant/pageindex-notebooklm/app/page.tsxkits/assistant/pageindex-notebooklm/components/ChatWindow.tsxkits/assistant/pageindex-notebooklm/components/DocumentList.tsxkits/assistant/pageindex-notebooklm/components/DocumentUpload.tsxkits/assistant/pageindex-notebooklm/components/TreeViewer.tsxkits/assistant/pageindex-notebooklm/components/ui/card.tsxkits/assistant/pageindex-notebooklm/components/ui/collapsible.tsxkits/assistant/pageindex-notebooklm/config.jsonkits/assistant/pageindex-notebooklm/flows/chat-with-pdf/meta.jsonkits/assistant/pageindex-notebooklm/flows/flow-1-upload-pdf-build-tree-save/config.jsonkits/assistant/pageindex-notebooklm/flows/flow-1-upload-pdf-build-tree-save/meta.jsonkits/assistant/pageindex-notebooklm/flows/flow-4-get-tree-structure/meta.jsonkits/assistant/pageindex-notebooklm/flows/flow-list-all-documents/config.jsonkits/assistant/pageindex-notebooklm/flows/flow-list-all-documents/meta.jsonkits/assistant/pageindex-notebooklm/lib/types.tskits/assistant/pageindex-notebooklm/lib/utils.tskits/assistant/pageindex-notebooklm/package.json
kits/assistant/pageindex-notebooklm/flows/flow-1-upload-pdf-build-tree-save/config.json
Outdated
Show resolved
Hide resolved
kits/assistant/pageindex-notebooklm/flows/flow-list-all-documents/config.json
Show resolved
Hide resolved
fix(pageindex-notebooklm): security, accessibility & correctness auditSummaryAddresses all actionable findings from the inline code review audit of the PageIndex NotebookLM kit. Fixed 12 issues across 8 files covering input validation, race conditions, accessibility, type safety, and documentation security. 6 audit items are intentionally left unfixed — each is explained below. What Changed1.
|
| File | Changes |
|---|---|
actions/orchestrate.ts |
Upload contract validation (3 guards) |
app/page.tsx |
Race condition fix (treeRequestIdRef), Markdown mention removed from empty state |
components/ChatWindow.tsx |
Stale sources guard fixed |
components/DocumentList.tsx |
Delete button moved outside row button, aria-label, focus-visible CSS |
components/DocumentUpload.tsx |
Reset timer on bad type, keyboard a11y, PDF-only |
components/TreeViewer.tsx |
Cycle detection DFS, semantic <button> toggle with aria-expanded |
lib/types.ts |
ChatResponse: removed doc_id, added messages?: unknown |
README.md |
Service-role RLS policy, SUPABASE_SERVICE_ROLE_KEY added to secrets table |
There was a problem hiding this comment.
Actionable comments posted: 4
♻️ Duplicate comments (1)
kits/assistant/pageindex-notebooklm/app/page.tsx (1)
142-144: 🧹 Nitpick | 🔵 TrivialPartial equipment standardization detected, Agent.
Good work importing
BookOpenfrom lucide-react, but several inline SVGs remain (warning icon, refresh icon, tab icons, spinner). Consider completing the migration for consistency.As per coding guidelines: "Use lucide-react for icons throughout kits"
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@kits/assistant/pageindex-notebooklm/app/page.tsx` around lines 142 - 144, Replace remaining inline SVG icons with lucide-react components for consistency: locate the inline warning SVG (the circle/exclamation markup shown), the refresh icons, the tab icons, and the spinner in page.tsx (you already import BookOpen from lucide-react), remove the inline <svg> blocks and use the matching lucide-react exports (e.g., AlertCircle or Info/Refresh/Chevrons/Loader equivalents) with the same sizing, stroke color, and className/style props so visual behavior is preserved; add the necessary imports from 'lucide-react' at the top (alongside BookOpen) and ensure props like size/strokeWidth/className replace the inline attributes.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.
Inline comments:
In `@kits/assistant/pageindex-notebooklm/components/DocumentList.tsx`:
- Around line 39-44: The component DocumentList.tsx contains inline SVG elements
(e.g., the empty state icon SVG with <path> and <polyline> and other inline
icons like file icons, spinner, and trash) which must be replaced with standard
lucide-react icons; import the appropriate icons from 'lucide-react' at the top
of the file and swap each inline <svg> block for the matching lucide component
(for example replace the empty state inline SVG with the corresponding Lucide
icon component), pass through the same visual props (size, className or style,
and stroke color like "var(--text-3)") so styling remains identical, and remove
the old inline SVG markup from DocumentList.tsx.
In `@kits/assistant/pageindex-notebooklm/components/DocumentUpload.tsx`:
- Around line 120-122: The inline SVG icons in DocumentUpload.tsx (spinner,
checkmark, error, upload) must be replaced with lucide-react components: import
Loader2, Check, AlertCircle, Upload from "lucide-react" and use those components
instead of the raw <svg> elements (e.g., replace the spinner SVG with <Loader2
/>). Ensure you pass the existing sizing, color, and animation via
props/className (e.g., size/width/height or className for color and the "spin"
animation) so behavior and styling (spinner animation, stroke color
var(--accent), etc.) remain the same; remove the old inline SVGs and update the
import list accordingly.
In `@kits/assistant/pageindex-notebooklm/components/TreeViewer.tsx`:
- Around line 51-53: The TreeViewer currently lets buildTree throw (e.g., the
cycle-detection throw referencing child.node_id) which will crash rendering;
wrap the call to buildTree inside TreeViewer in a try/catch, catch errors from
buildTree, and return a small error UI (e.g., a div with padding and red text
stating "Invalid tree structure detected. Please re-upload the document.")
instead of letting the exception bubble; ensure the fallback is used only when
buildTree throws and does not swallow other unrelated errors (rethrow if needed
or log the caught error via console/error logger).
- Around line 265-267: Replace the inline SVG search icon in the footer of
TreeViewer.tsx (the small circle+line SVG) with lucide-react's Search icon: add
an import for Search from 'lucide-react' near other icon imports and swap the
inline <svg> element in the "NODES USED IN LAST ANSWER" footer with the <Search>
component, preserving size and styling (use the same width/height or size prop
and apply the existing CSS variable stroke color, e.g., via className or stroke
prop) so the visual and theme match the original.
---
Duplicate comments:
In `@kits/assistant/pageindex-notebooklm/app/page.tsx`:
- Around line 142-144: Replace remaining inline SVG icons with lucide-react
components for consistency: locate the inline warning SVG (the
circle/exclamation markup shown), the refresh icons, the tab icons, and the
spinner in page.tsx (you already import BookOpen from lucide-react), remove the
inline <svg> blocks and use the matching lucide-react exports (e.g., AlertCircle
or Info/Refresh/Chevrons/Loader equivalents) with the same sizing, stroke color,
and className/style props so visual behavior is preserved; add the necessary
imports from 'lucide-react' at the top (alongside BookOpen) and ensure props
like size/strokeWidth/className replace the inline attributes.
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: Repository UI (base), Organization UI (inherited)
Review profile: ASSERTIVE
Plan: Pro
Run ID: 4df1bf85-35bd-4d08-bda1-c1d994c046d0
📒 Files selected for processing (8)
kits/assistant/pageindex-notebooklm/README.mdkits/assistant/pageindex-notebooklm/actions/orchestrate.tskits/assistant/pageindex-notebooklm/app/page.tsxkits/assistant/pageindex-notebooklm/components/ChatWindow.tsxkits/assistant/pageindex-notebooklm/components/DocumentList.tsxkits/assistant/pageindex-notebooklm/components/DocumentUpload.tsxkits/assistant/pageindex-notebooklm/components/TreeViewer.tsxkits/assistant/pageindex-notebooklm/lib/types.ts
kits/assistant/pageindex-notebooklm/components/DocumentList.tsx
Outdated
Show resolved
Hide resolved
kits/assistant/pageindex-notebooklm/components/DocumentUpload.tsx
Outdated
Show resolved
Hide resolved
…omponents for NotebookLM-style page indexing
Refactor: Replace inline SVGs with
|
There was a problem hiding this comment.
Actionable comments posted: 2
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.
Inline comments:
In `@kits/assistant/pageindex-notebooklm/components/DocumentUpload.tsx`:
- Around line 36-38: The code unsafely asserts the response from uploadDocument
to UploadResponse and assumes result.tree_node_count is a number; change the
handling in the upload block (where uploadDocument(...) is called and result is
assigned) to avoid the blind cast and coerce/validate tree_node_count before
using it — for example, read the raw response into a generic type, parse or
Number(result.tree_node_count) with a fallback (e.g., 0) and then call
setMessage(`${coercedCount} nodes indexed`); alternatively add a small type
guard that ensures tree_node_count is numeric and uses parseInt/Number when it
is a string, referencing the uploadDocument call and the result variable in
DocumentUpload.tsx.
In `@kits/assistant/pageindex-notebooklm/components/TreeViewer.tsx`:
- Around line 203-219: The hook call useMemo that creates highlightedIdSet must
be moved so it executes unconditionally before the try/catch that may
early-return; update TreeViewer to compute highlightedIdSet via useMemo(new
Set(highlightedIds), [highlightedIds]) above the buildTree() try/catch (refer to
useMemo, highlightedIdSet, and buildTree) so hooks order remains stable across
renders and then proceed with resolving roots and totalNodes as before.
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: Repository UI (base), Organization UI (inherited)
Review profile: ASSERTIVE
Plan: Pro
Run ID: ab8ebe8e-1400-4904-b61c-dfd05c7cb2d6
📒 Files selected for processing (5)
kits/assistant/pageindex-notebooklm/actions/orchestrate.tskits/assistant/pageindex-notebooklm/app/page.tsxkits/assistant/pageindex-notebooklm/components/DocumentList.tsxkits/assistant/pageindex-notebooklm/components/DocumentUpload.tsxkits/assistant/pageindex-notebooklm/components/TreeViewer.tsx
…tion with cycle detection and highlighting
|
fix(TreeViewer): move Problem
Concretely:
Fix Moved export default function TreeViewer({ tree, fileName, highlightedIds }: Props) {
// Must be declared before any early return to satisfy Rules of Hooks
const highlightedIdSet = useMemo(() => new Set(highlightedIds), [highlightedIds]);
let resolvedRoots: TreeNodeResolved[];
try {
resolvedRoots = buildTree(tree);
} catch (err) {
// early return is now safe — all hooks already ran
return <div>Invalid tree structure...</div>;
}
...
}Impact: No behaviour change on the happy path. Eliminates a class of hook-order crash that would surface in production when a malformed tree is uploaded followed by a valid one. |
There was a problem hiding this comment.
Actionable comments posted: 3
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.
Inline comments:
In `@kits/assistant/pageindex-notebooklm/components/TreeViewer.tsx`:
- Around line 121-122: The hover-only background change is applied on the inner
div via onMouseEnter/onMouseLeave so keyboard users won't see it when the
focusable element (the button) receives focus; update the styling to also apply
the same visual state for keyboard focus by adding a :focus-visible or
:focus-within rule (or a focus style on the button) that sets background to
var(--surface-2) when not isHighlighted, and ensure the logic that currently
checks isHighlighted (refer to the inner div mouse handlers and the button
element) is respected so the focus style matches the hover appearance for
keyboard navigation.
- Around line 91-109: Add an explicit type attribute to the toggle button in
TreeViewer.tsx: update the button element (the onClick/onKeyDown toggle handler
that uses hasChildren and setOpen) to include type="button" so it won't default
to type="submit" if the component is rendered inside a form.
- Around line 219-220: The totalNodes function (const totalNodes = (nodes:
TreeNodeResolved[]) => ...) is recreated each render; move or memoize its result
to avoid re-computation for large trees — either hoist the pure recursive helper
out of the component or wrap the computed total in a React.useMemo that depends
on the root nodes array (e.g., useMemo(() => totalNodes(rootNodes),
[rootNodes])); ensure you reference the existing totalNodes function name and
the TreeNodeResolved type when making the change.
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: Repository UI (base), Organization UI (inherited)
Review profile: ASSERTIVE
Plan: Pro
Run ID: f3b31040-7997-4507-b329-5028a344715a
📒 Files selected for processing (1)
kits/assistant/pageindex-notebooklm/components/TreeViewer.tsx
…ization with cycle detection and highlighting support
|
fix(TreeViewer): button type, keyboard focus parity, and hoist totalNodes Three minor issues addressed — all verified against the current code before fixing. 1. Buttons without an explicit // before
<button onClick={...}>
// after
<button type="button" onClick={...}>2. Keyboard focus has no hover visual (Trivial — accessibility) The hover background effect was applied via onFocus={(e) => {
if (!isHighlighted)
(e.currentTarget.firstElementChild as HTMLElement).style.background = "var(--surface-2)";
}}
onBlur={(e) => {
if (!isHighlighted)
(e.currentTarget.firstElementChild as HTMLElement).style.background = "transparent";
}}3. The function was a pure recursive helper with no closure dependencies, yet was redefined on every render. Hoisted to module level — same call site, zero behaviour change, no wasted allocations per render. // module level — defined once
function totalNodes(nodes: TreeNodeResolved[]): number {
return nodes.reduce((acc, n) => acc + 1 + totalNodes(n.nodes), 0);
}
export default function TreeViewer(...) {
// ...
// call unchanged
totalNodes(resolvedRoots)
}All three findings were verified against the actual code before applying any change. |
|
fix(flow-1/codeNode_save): surface Supabase write failures + fix resolver_url typo Verified against the live YAML config. Two bugs found in Bug 1 — Typo: // before — undefined on every run
const fileUrl = {{codeNode_630.output.resolver_url}}
// after
const fileUrl = {{cparams.output.resolved_url}};
Bug 2 — Silent failure: The original Fixed by:
Other nodes reviewed and unchanged: |
… PageIndex notebooklm
|
fix(flow-1/codeNode_save + flow-4/meta.json): correct raw_text source + trailing newline 1. File ended at 2. Verified against both the // BEFORE — saves the raw page array from extractFromFileNode
const rawText = {{extractFromFileNode_1.output.files[0].data}};
// AFTER — saves the [PAGE N]-annotated string built by codeNode_format
const rawText = {{codeNode_format.output.raw_text}};Impact of the bug: Why the fix is safe — nothing else needs to change:
|
PR Checklist
1. Select Contribution Type
kits/<category>/<kit-name>/)bundles/<bundle-name>/)templates/<template-name>/)2. General Requirements
kebab-caseand matches the flow IDREADME.md(purpose, setup, usage)3. File Structure (Check what applies)
config.jsonpresent with valid metadata (name, description, tags, steps, author, env keys)flows/<flow-name>/(where applicable) include:config.json(Lamatic flow export)inputs.jsonmeta.jsonREADME.md.env.examplewith placeholder values only (kits only)config.jsonnode graphs (changes via Lamatic Studio export)4. Validation
npm install && npm run devworks locally (kits: UI runs; bundles/templates: flows are valid)[kit] Add <name> for <use case>)What This Kit Does
Upload PDFs and chat with them using vectorless, tree-structured RAG.
Lamatic's Extract from File node reads the PDF's native TOC metadata,
builds a hierarchical document tree with exact page ranges per section,
and stores it in Supabase. At query time, Groq navigates the tree to
select only the relevant sections and Gemini answers using verbatim
page content. No vector database, no embeddings, no chunking.
Providers & Prerequisites
How to Run Locally
cd kits/assistant/pageindex-notebooklmnpm installcp .env.example .env.localand fill in valuesnpm run dev→ http://localhost:3000Live Preview
https://pageindex-notebooklm.vercel.app/
Lamatic Flows
Kit root
App / frontend
UI components
Server / libs
Flows (kits/assistant/pageindex-notebooklm/flows) — four Lamatic flows added; node types and high-level behavior:
flow-1-upload-pdf-build-tree-save
chat-with-pdf
flow-list-all-documents
flow-4-get-tree-structure
Retrieval design summary
Misc / artifacts