Skip to content

M5 — @thinkfleet/piece-agentmark Activepieces piece - #7

Merged
rrader26 merged 1 commit into
feat/v0.7-mcp-serverfrom
feat/m5-activepieces-piece
May 10, 2026
Merged

M5 — @thinkfleet/piece-agentmark Activepieces piece#7
rrader26 merged 1 commit into
feat/v0.7-mcp-serverfrom
feat/m5-activepieces-piece

Conversation

@rrader26

Copy link
Copy Markdown
Contributor

Summary

Sibling package in `pieces/agentmark/` that wraps the core AgentMark library as an Activepieces piece. Drop into any flow to convert web pages or PDFs into AgentMark snapshots and fill PDF forms — no code, no SDK install for the flow author.

Stacked on top of #6 (v0.7 MCP server). Merge #2#3#4#5#6 → this PR.

Three actions (v1)

Action What it does Use case
Capture Web Page URL → AgentMark snapshot. Launches Chromium, snapshots, closes. Hand off page state to an AI step in the same flow.
Capture PDF PDF (URL / path / data URI / base64) → AgentMark with `kind: document` or `form`. Optional OCR via Tesseract + Poppler. Read scanned forms, insurance quotes, county docs.
Fill PDF Form Atomic AcroForm fill. Accepts field values by action ID OR original field name. Returns base64 / data URI; optional flatten. Fill vendor applications / claim forms with CRM data.

Why this matters

  • Growth OS gets it for free — Growth OS is built on Activepieces, so installing this piece adds AgentMark as a flow primitive immediately.
  • Every other Activepieces deployment (community + commercial) can install independently.
  • Flow authors don't need to learn the AgentMark SDK — they drag actions onto the canvas.

Tests (13 + 1 gated)

  • Piece-shape assertions (display name, minimum release, action props)
  • `fill_pdf_form` end-to-end:
    • Fill by action ID, by original field name
    • Unknown keys reported via `fields_skipped` (no throw)
    • `return_format: 'base64'` vs `'data_uri'`
    • `flatten` removes the form (verified by re-reading with pdf-lib)
    • Accepts `data:` URI source (no temp file)
  • `snapshot_pdf` end-to-end (text PDF): produces `kind: form`
  • `snapshot_web_page`: gated on `AGENTMARK_INTEGRATION=1` with a local HTTP server (no external network)

Cross-package hygiene fixes

Two real bugs caught during development:

  1. Symlinked node_modules → duplicate modules. The piece's `node_modules/@thinkfleet/agentmark` symlinks back to the root, which made vitest pick up root tests twice (once normally, once via the symlink as a different module instance), breaking `instanceof` checks. Fixed via `vitest.config.ts` excluding `pieces/**` from root test discovery.
  2. TypeScript emitting into parent `src/`. The piece's `tsc` followed the symlink and wrote compiled `.js` / `.d.ts` files into the parent's `src/`, which then shadowed the source files at test time. Fixed by setting `rootDir: ./src` and `preserveSymlinks: true` in the piece's tsconfig.

Architecture

```
pieces/agentmark/
├── package.json (file:../.. dep on parent during dev)
├── tsconfig.lib.json (rootDir: ./src + preserveSymlinks: true)
├── README.md
├── src/
│ ├── index.ts (createPiece export)
│ └── lib/
│ ├── common.ts (resolveBytes — URL/path/base64/data URI)
│ └── actions/
│ ├── snapshot-web-page.ts
│ ├── snapshot-pdf.ts
│ └── fill-pdf-form.ts
└── test/piece.test.ts (13 unit + 1 gated)
```

Distribution path

When v0.7 publishes to npm:

  1. Bump `@thinkfleet/agentmark` from `file:../..` to `^0.7.0` in `pieces/agentmark/package.json`
  2. `cd pieces/agentmark && npm publish --access public`

The piece can then be added to any Activepieces deployment via `@thinkfleet/piece-agentmark`.

Test plan

🤖 Generated with Claude Code

Sibling package in pieces/agentmark/ that wraps the core AgentMark library
as an Activepieces piece. Drop into any flow to convert web pages or PDFs
into AgentMark snapshots and fill PDF forms — no code, no SDK install for
the flow author.

Three actions (v1)
- Capture Web Page (snapshot_web_page)
    URL → AgentMark snapshot. Launches Chromium, snapshots the page,
    closes browser. Configurable wait_until + timeout + headless.
    Output: { agentmark, url, title, kind, action_count, bytes,
              captured_at }
- Capture PDF (snapshot_pdf)
    PDF source (URL / file path / file:// / data: URI / bare base64) →
    AgentMark snapshot with kind: 'document' or 'form'. Optional OCR
    (Tesseract + Poppler) for scanned and "Print To PDF" outputs.
    Output: { agentmark, source_url, bytes, ocr_used }
- Fill PDF Form (fill_pdf_form)
    Atomic PDF fill operation. Accepts field values keyed by either
    AgentMark action ID (act_field_N) or original PDF field name —
    matches whichever the caller has. Returns the filled PDF as base64
    data URI or raw base64. Optional flatten (bake values into page
    content; resulting PDF no longer fillable).
    Output: { filled_pdf, bytes, fields_applied[], fields_skipped[],
              flattened }

Architecture
- pieces/agentmark/ — sibling package in the same repo, builds + tests
  independently from the core library.
- pieces/agentmark/src/lib/common.ts — shared resolveBytes() helper that
  accepts URL/path/data URI/base64 strings so all PDF actions take a
  uniform `source` prop.
- pieces/agentmark/src/lib/actions/*.ts — one file per action.
- Depends on @thinkfleet/agentmark via file:.. for monorepo dev; bump
  to ^0.7.0 (or whatever version is on npm) before publishing.
- Uses @activepieces/pieces-framework for the createPiece + createAction
  API; matches conventions from the official AI piece in
  activepieces-main.

Tests (13 piece tests + 1 gated browser test)
- Piece-shape assertions: display name, minimum release, exposed
  actions, prop schemas
- fill_pdf_form end-to-end:
    - Fill by action ID
    - Fill by original field name (resolution)
    - Unknown keys reported via fields_skipped (no throw)
    - return_format=base64 vs data_uri
    - flatten removes the form
    - Accepts data: URI source (no temp file)
- snapshot_pdf end-to-end (text PDF, no OCR): produces kind: form
- snapshot_web_page: gated on AGENTMARK_INTEGRATION=1 with a local
  HTTP server (no external network)

Cross-package hygiene
- Root vitest.config.ts excludes pieces/** from root test discovery
  to prevent the symlinked node_modules/@thinkfleet/agentmark from
  causing duplicate-module instanceof failures.
- Piece's tsconfig sets rootDir: ./src and preserveSymlinks: true so
  TypeScript never emits compiled JS into the parent's src/ via the
  monorepo symlink.

Known limitations (deferred)
- No multi-step "browser_workflow" action yet — for now each web action
  launches a fresh browser. Stateful flows need to fit in a single
  action call. Multi-step is on the v1.1 roadmap.
- No AP piece-auth (auth: PieceAuth.None()) — none of the v1 actions
  need credentials. Future Mistral OCR integration would add custom
  auth for the API key.

Distribution unlocks
- Growth OS (built on Activepieces) gets AgentMark as a flow primitive
  for free once this piece is registered.
- Every other Activepieces deployment (community + commercial) can
  install the piece independently.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
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.

2 participants