Skip to content

Add compliance overrides, scoped-key CRUD, register, and search#10

Merged
gradill22 merged 8 commits into
mainfrom
feat/policy-keys-register-search
Jul 23, 2026
Merged

Add compliance overrides, scoped-key CRUD, register, and search#10
gradill22 merged 8 commits into
mainfrom
feat/policy-keys-register-search

Conversation

@gradill22

Copy link
Copy Markdown
Contributor

Mirrors the Python SDK so both stay in lockstep with the API.

What's here

  • Compliance overrides (allowDomains / denyPatterns / respectRobots) on extract/bulk/crawl. JSON.stringify drops undefined, so unset overrides are omitted and can only narrow the key's policy — never clobber it. (A real semantic difference from Python, where None would serialize to null and would clobber.)
  • Scoped-key CRUD: createKey / listKeys / revokeKey, plus getLogs, with the matching types.
  • Static register(): self-provision a free, extract-only key.
  • search(): web search + extraction in one synchronous call. SearchResult carries a per-page status, so a page that failed extraction is marked rather than silently dropped.

Notes

  • Error mapping is by HTTP status, so the new API error codes needed no new error classes.

Verification

npm run typecheck clean and 66 tests pass (63 + 3 new for search). CI runs the Node 18/20/22 matrix with typecheck + test + build.

Merge/release order matters: this package must be published to npm before the MCP repo, whose CI installs the published wellmarked and needs search()/SearchResults to typecheck.

🤖 Generated with Claude Code

Mirrors the Python SDK so both stay in lockstep with the API:

- Compliance policy overrides (allowDomains / denyPatterns /
  respectRobots) on extract/bulk/crawl. JSON.stringify drops undefined,
  so unset overrides are omitted and can never clobber the key's policy.
- Scoped API keys: createKey / listKeys / revokeKey, plus getLogs, with
  CreatedKey / ApiKeyInfo / RevokedKey / LogEntry / LogsPage.
- Static register(): self-provision a free, extract-only key.
- search(): web search plus extraction in one synchronous call, with
  SearchResult / SearchResults carrying a per-page status.

Error mapping is by HTTP status, so the new API error codes needed no
new error classes.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
gradill22 and others added 7 commits July 20, 2026 16:53
The repo pins typescript ^6.0.3, but a stale local node_modules had
5.9.3, so both of these passed locally and failed in CI:

- lib ES2020 doesn't declare Array.prototype.at, which the tests use.
  Raised the type surface to ES2022 (emit stays at the ES2020 target);
  the package supports Node >=18, which has it.
- The CJS build passes --moduleResolution node (node10), deprecated in
  TS 6 and a hard error. Silenced with ignoreDeprecations for now;
  moving the CJS output to node16 resolution is a separate change.

Verified against the pinned toolchain (npm ci) this time: typecheck,
test (66), and build all exit 0.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
vitest 4 imports node:util styleText, added in Node 20.12, so the
runner dies at startup on 18. The library itself still supports Node
>=18.17 per package.json engines, and that floor stays covered by
install + typecheck + build; only the runner is skipped.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
extract/bulk/crawl accept `format` (markdown | json | chunks | html |
links). ExtractResult, BulkItem and CrawlItem now extend a shared
`Content` interface carrying the five format-dependent fields plus
`metrics`; exactly one is populated per result and `markdown` still holds
the default.

New exports: OutputFormat, Content, ContentBlock, Chunk, ContentMetrics,
and `contentOf()` for reading whichever field came back.

`ok` keys on `error` + contentOf rather than on `markdown` — the old form
reported every successful links/html/chunks item as failed.

The API's snake_case chunk offsets (start_token/end_token) map to
camelCase (startToken/endToken); a test pins that contiguity survives the
translation.

typecheck, 70 tests and build all clean.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Product decision: users get no capability to point WellMarked anywhere but
the hosted API. baseUrl leaves both option interfaces, and the injected
fetch goes with it (a custom fetch is the same capability by another door).
The client now resolves globalThis.fetch lazily at call time — the
constructor can't fail in odd environments, and test runners stub the
global exactly as the runtime resolves it.

Tests migrate from the fetch option to vi.stubGlobal("fetch", ...), plus a
negative control: a baseUrl smuggled past the types with a cast is ignored
and the request still hits api.wellmarked.io.

BREAKING vs the published package: both options were public.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
SearchOptions extends PolicyOverrideOptions and gains format; SearchResult
extends Content so non-markdown formats land in their own fields (with
metrics) via the shared contentFromDict path. Tool docs note the Pro+ gate
on json/chunks.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
retry: server-side re-attempts on target_timeout, fresh connection per
attempt, default 0, no upper bound. Not offered on search() — the API's
15s per-hit deadline can't absorb one. Distinct from the client's own
maxRetries (transport retries between the SDK and the API).

crawl({ maxPages: N }) narrows the plan's page cap (sent as max_pages);
omitted = plan cap alone.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
retry's value stays uncapped, but the server stops re-attempting once a
job's 6-hour lifetime is spent — state it where the option is documented
so the JSDoc promise matches the API's behavior.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
@gradill22 gradill22 self-assigned this Jul 23, 2026
@gradill22
gradill22 merged commit e272d99 into main Jul 23, 2026
3 checks passed
@gradill22
gradill22 deleted the feat/policy-keys-register-search branch July 23, 2026 04:37
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