Skip to content

Folders on chat: chat(folder_id=) and folder_context() - #499

Merged
rejojer merged 1 commit into
feat/document-contextfrom
feat/folder-context
Sep 10, 2026
Merged

Folders on chat: chat(folder_id=) and folder_context()#499
rejojer merged 1 commit into
feat/document-contextfrom
feat/folder-context

Conversation

@rejojer

@rejojer rejojer commented Sep 10, 2026

Copy link
Copy Markdown
Member

Stacked on #495 (base feat/document-context); merge after it.

What

  • client.folder_context(folder_id): the folder targeting text for the first user message, the folder analogue of document_context().
  • chat(folder_id=), also on chat_completions() and the responses / messages protocol lanes: places it, or on the managed lane sends the field the server already accepts.

Wire truth

  • The managed /chat/completions takes folder_id (ChatCompletionRequest.folder_id, pageindex-compute server/api/api.py:491) and renders "The user has specified folder: ..." ahead of the document block (api.py:3182); the metadata row is the server's FolderContext: id, name, description (server/lib/db/folders.py:50). The SDK renders the same text.
  • /folders/ lists the same partition the chat validates against (userId + api_surface_sql, no LIMIT), so what the helper finds is what the server accepts; it carries require_folder_plan, so a non-Max key fails at the helper, not mid-run.

Decisions

  • "root" (and "") is the library itself: folder_context returns "", chat places nothing, on every lane and in every mode, as the server treats folder_id="root".
  • Own-model lanes: one leading user message, folder block then document block, joined with a blank line as the server joins them.
  • folder_id joins the prompt-cache key, for the reason doc_id does.
  • Keyword-only on chat(), trailing on every other signature: no positional call shifts.
  • Cloud-only: a local client raises before any model call, like create_folder / list_folders.

Verification

  • 437/437 in test_client / test_agent_tools / test_local_chat, full suite green (one live-network test flaked on a proxy SSL EOF and passed on rerun); the without-frameworks leg passes.
  • pyright: zero new diagnostics against the base branch.
  • Live: managed chat(q, folder_id=F) lists the folder's documents; folder_id="root" answers normally; own-model over cloud tools calls browse_documents(folder_id=F, recursive=true) first and gives the same list.

Docs: VectifyAI/pageindex-docs#53.

https://claude.ai/code/session_01NsQjN5HMmmX4n5NVsZWYaw

The managed /chat/completions already takes folder_id and renders a
folder targeting block ahead of the document block (pageindex-compute
api.py:491, :3182); the SDK had no way to send it, and own-model chat
had no folder analogue of document_context(). Both land here.

folder_context(folder_id) renders that block as the managed chat
renders its own: the name, an id/name/description metadata row (the
server's FolderContext), and the directive to discover the folder's
documents with browse_documents / search_documents(folder_id=...,
recursive=true). One list_folders() call picks the folder by id: the
endpoint has no LIMIT and lists the same userId + api_surface
partition the managed chat validates against, so what the helper finds
is what the server accepts, and it carries the same plan gate, so a
non-Max key fails here rather than mid-run. A missing folder raises.
Cloud-only: local libraries have no folders.

chat(folder_id=) places it. The managed lane sends the field and lets
the server render and gate it; the three own-model lanes lead the
conversation with one user message, folder block then document block,
joined as the server joins them. folder_id joins the prompt-cache key
for the reason doc_id does: the block is byte-identical for every
conversation about a folder.

"root" (and "") targets nothing on every lane and in every mode, as
the server treats folder_id="root": folder_context returns "" and chat
places nothing. folder_id is keyword-only on chat() and trailing on
every other signature, so no positional call shifts.

Tests: the wire field on the managed lane; block order and root/"" on
the shared renderer; folder_id threaded through the chat, responses
and messages engines; the local cloud-only refusal.

Claude-Session: https://claude.ai/code/session_01NsQjN5HMmmX4n5NVsZWYaw
@rejojer
rejojer merged commit d439b19 into feat/document-context Sep 10, 2026
5 checks passed
@rejojer
rejojer deleted the feat/folder-context branch September 10, 2026 05:25
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant