Skip to content

fill_pdf_form: fill an AcroForm PDF, and say so honestly when the PDF is a flat scan #712

Description

@serge-ivo

Part of the Gmail epic. Independent of the Gmail work — useful anywhere a form must be produced.

Why

There is no code in PAGS that writes a PDF. The only PDF handling is lib/resume-parse.ts, which sends one to Claude to read:

// lib/resume-parse.ts:65
{ type: "document", source: { type: "base64", media_type: "application/pdf", data: bytesToBase64(bytes) } },

Reading is solved; producing a filled form is not attempted anywhere.

Scope

A fill_pdf_form tool, tier: "standard", scope: "read" (it touches no external system), mutates: true (it writes a new file into the instance store).

Input: a source file id in the instance store, plus values as a field-name → value map. Output: a new file id for the filled PDF.

Two paths, because real forms are not all the same:

  1. AcroForm present — fill the named fields with pdf-lib and flatten. Deterministic, and the field names can be listed back to the model first so it knows what it is filling.
  2. No form fields (flat scan) — do NOT silently produce an unchanged PDF, which is the failure mode worth designing against. Report that the source has no fillable fields, and produce a clean typed answer document instead: a generated PDF listing every question and the supplied answer, suitable to attach alongside the original.

A companion read-only inspect_pdf_form that lists the field names (or reports there are none) is what makes path 1 usable — the model must not guess field names.

Risks to check during implementation

  • Bundle size. pdf-lib is roughly 1 MB minified. workers/api is on the paid 10 MB limit, so this should fit, but the built size must be measured before and after rather than assumed, and it should be a dynamic import() on the handler path like lib/crypto.js and lib/gmail.js already are in storage-tools.ts.
  • Worker CPU. Flattening a large scanned PDF is not free. Cap the input size and fail with a clear message rather than hitting the wall.

Not verified

Whether the forms this is actually wanted for are AcroForms. The motivating attachment has not been inspected yet, so path 2 is designed as a first-class outcome rather than an error branch. If real club forms turn out to be flat scans in the common case, path 2 is the product and path 1 is the bonus — worth re-reading this issue once a real sample exists.

Metadata

Metadata

Assignees

No one assigned

    Labels

    backendBackend / Worker / API workenhancementNew feature or request

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions