Files
anonymizer/CHANGELOG.md
Mobiletic f5c9f0fbd4 feat: make openAICompatibleProvider work with Infomaniak out of the box (0.3.0)
- response_format is omitted by default (Infomaniak rejects the legacy
  json_object → HTTP 422); opt in via the new `responseFormat` option
  ({type:'json_object'} or a json_schema object). BREAKING for endpoints
  that relied on the forced json_object.
- parse LLM JSON leniently (tolerate markdown fences / surrounding prose)
- fold strict-coherence rules into DEFAULT_SYSTEM_PROMPT (exact
  placeholder<->mapping-key identity, values are originals, strict format,
  mask value not adjacent label) → reliable output across models

Verified live against Gemma 4 (google/gemma-4-31B-it, Infomaniak v2): all
demo phrases anonymize with clean round-trips, no custom provider needed.
36 tests passing.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-07-01 09:43:19 +01:00

62 lines
3.6 KiB
Markdown

# Changelog
All notable changes to this project are documented here. The format is based on
[Keep a Changelog](https://keepachangelog.com/en/1.1.0/), and this project adheres to
[Semantic Versioning](https://semver.org/spec/v2.0.0.html).
## [0.3.0] - Unreleased
### Changed
- **`openAICompatibleProvider` now works with Infomaniak (and other open-model endpoints) out of the box.**
`response_format` is **omitted by default** instead of hard-coding `{ type: 'json_object' }`, which
current Infomaniak rejects (HTTP 422). Pass the new `responseFormat` option (e.g. `{ type: 'json_object' }`
or a `json_schema` object) for endpoints that support/require it. **Breaking** for endpoints that relied
on the previous forced `json_object`.
- JSON responses are now **parsed leniently** — a fenced JSON code block or surrounding prose is tolerated
(the outermost `{ … }` is extracted), so models without an enforced `response_format` don't cause
spurious parse failures.
- The default prompt gained a **COHÉRENCE** block (exact placeholder↔mapping-key identity, values are the
original data never another placeholder, strict `[TYPE_N…]` format, mask the value not the adjacent
label) to improve reliability across models.
## [0.2.0] - Unreleased
### Added
- **`legend`** on every result — abbreviation → French meaning (`PER``Personne`, `M``Masculin`), safe to
forward to a downstream LLM so it understands the placeholder tokens. Backed by a built-in
`DEFAULT_LEGEND` so coverage is guaranteed even if the model omits entries.
- The default prompt now lets the model **coin new uppercase abbreviations** for entities/attributes/
context it discovers and return their meanings in `legende`.
- `PatternDef.meaning` — optional human label for a tag, surfaced in the `legend`. `presets.swiss`/
`presets.generic` ship French meanings.
- `AnonymizationError` (exported) — thrown when anonymization can't complete and no fallback exists;
carries the originating error in `.cause`.
### Changed (breaking)
- **Regex fallback is now opt-in.** `patterns` no longer defaults to `presets.swiss`. With no fallback,
an LLM failure throws `AnonymizationError` (fail-closed) and the pre-filter is bypassed. At least one of
`llm` or `patterns` is required, or the constructor throws.
- `AnonymizationResult` gained a required `legend` field; `LlmProvider.anonymizeBatch` returns `legend`.
- `anonymizeChunks(chunks, seed)``seed` is now `{ mapping, legend? }` (was the bare mapping) and the
return includes `legend`.
## [0.1.0] - Unreleased
### Added
- Initial public release.
- `Anonymizer` — pre-filter → LLM → regex fallback, bidirectional validation, deterministic coreference,
and de-collision across question and retrieved chunks (`anonymize`, `anonymizeChunks`, `deanonymize`).
- `makeStreamDeanonymizer` — streaming-safe de-anonymization that never leaks a split placeholder.
- `openAICompatibleProvider` — pluggable LLM detection over any OpenAI-compatible Chat Completions API.
- `presets.swiss` and `presets.generic` regex pattern sets; fully configurable custom patterns.
- Regex-only mode (no LLM provider required).
- `PatternDef.validate` — optional second-stage predicate to cut false positives; `presets.generic` uses
it for a Luhn check on credit-card candidates, and de-overlaps its phone/date/IP patterns.
- `openAICompatibleProvider` retries transient failures (network/timeout/429/5xx) via `retries` and
`retryDelayMs` options; non-transient 4xx and malformed responses are not retried.
- Hardened the `nameHint` heuristic: `g`/`y` flags are stripped internally so `.test()` is stateless.