-
[OPIK-6456] [BE] feat: add prompt masks for non-destructive prompt resolution (#6731)
发布于
2026-05-19 08:26:31 +00:00 - [OPIK-6456] [BE] feat: add prompt masks for non-destructive prompt resolution
Add version_type ENUM('prompt_version','mask') discriminator column on
prompt_versions, defaulting existing rows to 'prompt_version'. This is
the schema foundation for mask overlays: masks live in the same table
as regular prompt versions but are filtered out of latest_version and
version_count queries, and selectable via mask_id at resolution time.Co-Authored-By: Claude Opus 4.7 (1M context) noreply@anthropic.com
- feat(prompts): add PromptVersionType enum and versionType field
Introduces the PROMPT_VERSION/MASK discriminator at the API layer.
versionType defaults to PROMPT_VERSION so existing clients are
unaffected; mask creation will set it to MASK on the embedded
PromptVersion in CreatePromptVersion.Co-Authored-By: Claude Opus 4.7 (1M context) noreply@anthropic.com
- feat(prompts): filter masks from list/count queries and support mask_id resolution in findById
- prompt_versions.version_type='prompt_version' filters added to:
- latest_version and version_count subqueries in PromptDAO findById/find/findByIds/count
- PromptDAO.findByCommit and findPromptsByCommits (commits are prompt-version-only)
- PromptVersionDAO.find/findCount when listing by prompt_id (id-based lookups still
return any type so masks remain reachable by id) - PromptVersionDAO.findByCommit
- PromptDAO.findById gains an optional mask_id that, when present, populates
requested_version with that version row (service validates it is actually a mask) - INSERT in PromptVersionDAO.save writes the new version_type column
- PromptVersionColumnMapper reads version_type from JSON_OBJECT payloads with a
PROMPT_VERSION fallback for older serialized rows
Co-Authored-By: Claude Opus 4.7 (1M context) noreply@anthropic.com
- feat(prompts): mask-aware getById and bulk retrieveVersionsByIds in service
- getById(UUID, UUID maskId): delegates to PromptDAO.findById with the
optional mask_id. When a mask_id is supplied and no row matches for
the given prompt, throws NotFoundException so callers see a clean 404
instead of a Prompt with a null requestedVersion. - retrieveVersionsByIds(List): bulk version lookup powering the
upcoming POST /v1/private/prompts/retrieve endpoint. Returns versions
in whatever order PromptVersionDAO produces (id DESC); missing ids
are dropped from the response. - Existing getById(UUID) delegates to the new overload with maskId=null,
so all current callers keep their behavior. - Variable enrichment factored into enrichWithVariables() and applied
to both latestVersion and requestedVersion on the resolution path.
Co-Authored-By: Claude Opus 4.7 (1M context) noreply@anthropic.com
- feat(prompts): mask_id query param on GET /prompts/{id} and POST /prompts/retrieve
- GET /v1/private/prompts/{id} accepts an optional mask_id query param.
When set, the response Prompt has requestedVersion populated with the
matching mask version (404 if no such version belongs to this prompt). - POST /v1/private/prompts/retrieve accepts { ids: [...] } and returns
List. Powers the FE flow that resolves multiple mask
overlays in a single round-trip. - PromptVersionIdsRequest validates 1..1000 non-null UUIDs.
Co-Authored-By: Claude Opus 4.7 (1M context) noreply@anthropic.com
- feat(prompts): suppress PROMPT_COMMITTED alerts and lastUpdatedAt bump on mask saves
Masks are non-destructive overlays, not real commits. They should not
trigger PROMPT_COMMITTED alert subscribers and should not move the
parent prompts last_updated_at, which the UI surfaces as recent prompt
activity. Both side effects are now gated on versionType != MASK;
regular prompt_version saves are unchanged.Co-Authored-By: Claude Opus 4.7 (1M context) noreply@anthropic.com
- test(prompts): cover mask creation, isolation, mask_id resolution, bulk retrieve
New PromptMasks nested class in PromptResourceTest:
- mask creation via POST /prompts/versions with version_type=mask
- masks excluded from latestVersion and versionCount on GET /prompts/{id}
- masks excluded from GET /prompts/{id}/versions and from commit-based
lookups (/by-commit and /retrieve-by-commits) - GET /prompts/{id}?mask_id=... populates requestedVersion with the mask
while keeping latestVersion pointed at the latest real version - 404 when mask_id is unknown or belongs to a different prompt
- POST /prompts/retrieve returns versions by id and rejects empty bodies
- creating a mask does not bump the parent prompts lastUpdatedAt
Co-Authored-By: Claude Opus 4.7 (1M context) noreply@anthropic.com
-
remove unused import
-
feat(local-runners): carry multiple prompt masks per job via prompt_masks
Extends CreateLocalRunnerJobRequest and LocalRunnerJob with promptMasks,
a Map<promptId, maskId> that lets a local-runner job overlay masks on
several prompts in a single run. The existing single maskId field stays
in place but is marked @Deprecated for both DTOs.EndpointJobServiceImpl persists prompt_masks as JSON on the Redis job
hash and restores it via parsePromptMasks on every job read path
(nextJob, getJob, listJobs).LocalRunnersResourceTest covers create + claim round-trips for the new
field and that promptMasks is null when not provided.Co-Authored-By: Claude Opus 4.7 (1M context) noreply@anthropic.com
-
bump migration version
-
address comments
-
bump migration number
下载附件