ship method
Stores version and makes it answer.
A stored version carries wording, not shape: the call site was compiled against the inputs and output it has. And a number already used, by the compiled prompt, the lockfile or the store, cannot carry other text.
Implementation
Future<void> ship(DVPromptVersion version) async {
final DVPromptVersion? compiled = _compiled[version.id];
if (compiled == null) {
throw ArgumentError.value(version.id, 'version',
'no compiled prompt has this id, so no call site can use it');
}
if (version.shape != compiled.shape) {
throw ArgumentError.value(
version,
'version',
'changes the inputs, output or schema the call site was compiled '
'against; a stored version changes wording only');
}
String? usedBy;
if (compiled.version == version.version &&
compiled.fingerprint != version.fingerprint) {
usedBy = 'the compiled prompt';
}
final DVPromptLockEntry? locked = lock?.entry(version.id, version.version);
if (locked != null && locked.fingerprint != version.fingerprint) {
usedBy ??= 'the lockfile';
}
for (final DVPromptVersion existing in await store.versions(version.id)) {
if (existing.version == version.version &&
existing.fingerprint != version.fingerprint) {
usedBy ??= 'an earlier stored version';
}
}
if (usedBy != null) {
throw DVAIOpsError(
'DV-AIOPS-006',
'prompt "${version.id}" version ${version.version} is already '
'$usedBy with other text; a changed prompt takes a new version',
);
}
await store.put(version);
}