feat(ql3): execute copilot diagnosis models

This commit is contained in:
whyour
2026-08-15 20:38:17 +08:00
parent 9c90c6ce82
commit 453a7679b2
26 changed files with 2872 additions and 132 deletions
@@ -33,16 +33,9 @@ import {
type ModelInvocationPriceQuote,
} from '../pricing/pricing';
import {
isPluginPackagePromptOutputCompletionRepository,
type PluginPackagePromptOutputCompletionRepository,
} from '../prompt-output/pluginPackagePromptOutputCompletion';
import {
PluginPackagePromptOutputArtifactConflictError,
normalizePluginPackagePromptOutputArtifact,
pluginPackagePromptOutputArtifactReference,
type PluginPackagePromptOutputArtifact,
type PluginPackagePromptOutputArtifactReference,
} from '../prompt-output/pluginPackagePromptOutputArtifact';
normalizeModelInvocationAtomicSuccess,
type ModelInvocationAtomicSuccess,
} from './modelInvocationAtomicSuccess';
const MAX_COORDINATOR_ATTEMPTS = 3;
@@ -242,32 +235,21 @@ export class DurableModelInvocationCoordinator
return this.#admit(record, admission, quote);
}
async recordWithPromptOutputArtifact(
async recordWithAtomicSuccess<TReference>(
record: Readonly<ModelInvocationAuditRecord>,
artifactValue: PluginPackagePromptOutputArtifact,
extensionValue: ModelInvocationAtomicSuccess<TReference>,
): Promise<
Readonly<{
status: 'created' | 'existing';
reference: Readonly<PluginPackagePromptOutputArtifactReference>;
reference: Readonly<TReference>;
}>
> {
const artifact = normalizePluginPackagePromptOutputArtifact(artifactValue);
if (
record.phase !== 'completed' ||
record.requestId !== artifact.invocationId ||
record.projectId !== artifact.projectId ||
record.runId !== artifact.runId ||
record.stepRunId !== artifact.stepRunId ||
record.provider !== artifact.provider ||
record.model !== artifact.model ||
record.outputBytes !== artifact.outputBytes ||
!isPluginPackagePromptOutputCompletionRepository(this.repository)
) {
throw new PluginPackagePromptOutputArtifactConflictError();
}
const result = await this.#complete(record, artifact);
const extension = normalizeModelInvocationAtomicSuccess(extensionValue);
if (record.phase !== 'completed') throw extension.conflict();
extension.assertAudit(record);
const result = await this.#complete(record, extension);
if (!result.reference) {
throw new PluginPackagePromptOutputArtifactConflictError();
throw extension.conflict();
}
return Object.freeze({
status: result.status,
@@ -383,22 +365,18 @@ export class DurableModelInvocationCoordinator
throw new ModelInvocationConflictError();
}
async #complete(
async #complete<TReference = never>(
audit: Readonly<ModelInvocationAuditRecord>,
artifactValue?: Readonly<PluginPackagePromptOutputArtifact>,
extensionValue?: ModelInvocationAtomicSuccess<TReference>,
): Promise<
Readonly<
ModelInvocationAuditDisposition & {
reference?: Readonly<PluginPackagePromptOutputArtifactReference>;
reference?: Readonly<TReference>;
}
>
> {
const artifact = artifactValue
? normalizePluginPackagePromptOutputArtifact(artifactValue)
: undefined;
const artifactRepository = artifact
? (this.repository as ModelInvocationRepository &
PluginPackagePromptOutputCompletionRepository)
const extension = extensionValue
? normalizeModelInvocationAtomicSuccess(extensionValue)
: undefined;
const startValue = await this.repository.findStart(audit.requestId);
if (!startValue) throw new ModelInvocationConflictError();
@@ -406,16 +384,14 @@ export class DurableModelInvocationCoordinator
const existing = await this.repository.findCompletion(audit.requestId);
if (existing) {
assertCompletionMatchesAudit(existing, start, audit);
if (artifact && artifactRepository) {
const stored = await artifactRepository.findPromptOutputArtifact(
artifact.artifactId,
);
if (!stored || JSON.stringify(stored) !== JSON.stringify(artifact)) {
throw new PluginPackagePromptOutputArtifactConflictError();
if (extension) {
const stored = await extension.find(this.repository);
if (!stored || !extension.matches(stored)) {
throw extension.conflict();
}
return Object.freeze({
status: 'existing' as const,
reference: pluginPackagePromptOutputArtifactReference(stored),
reference: stored,
});
}
return Object.freeze({ status: 'existing' as const });
@@ -430,7 +406,7 @@ export class DurableModelInvocationCoordinator
) {
throw new ModelInvocationConflictError();
}
const transition = completionTransition(audit, artifact?.artifactId);
const transition = completionTransition(audit, extension?.outputRef);
const mutationIdentity = createModelInvocationMutationIdentity(
audit.requestId,
'completion',
@@ -464,7 +440,7 @@ export class DurableModelInvocationCoordinator
actor: { type: 'executor', id: 'model-gateway' },
},
),
artifact?.artifactId,
extension?.outputRef,
);
try {
const pricingAware = isPricingAwareModelInvocationRepository(
@@ -479,42 +455,32 @@ export class DurableModelInvocationCoordinator
const reservation = quotaAware
? await this.repository.findQuotaReservation(audit.requestId)
: null;
const result =
artifactRepository && artifact
? await artifactRepository.completeWithPromptOutputArtifact(
command,
artifact,
)
: pricingAware && quote
if (extension) {
const result = await extension.commit(this.repository, command);
return Object.freeze({
status: result.status,
reference: result.reference,
});
}
const result = pricingAware && quote
? await this.repository.completeWithPricing(command)
: quotaAware && reservation
? await this.repository.completeWithQuota(command)
: await this.repository.complete(command);
return Object.freeze({
status: result.status,
...(artifact && artifactRepository
? {
reference: pluginPackagePromptOutputArtifactReference(artifact),
}
: {}),
});
} catch (error) {
const stored = await this.#completionAfterFailure(
start,
audit,
error,
artifact,
artifactRepository,
extension,
);
if (stored) {
return Object.freeze({
status: 'existing' as const,
...(artifact
? {
reference:
pluginPackagePromptOutputArtifactReference(artifact),
}
: {}),
...(extension ? { reference: stored.reference } : {}),
});
}
if (
@@ -569,31 +535,29 @@ export class DurableModelInvocationCoordinator
}
}
async #completionAfterFailure(
async #completionAfterFailure<TReference = never>(
start: Readonly<ModelInvocationStartRecord>,
audit: Readonly<ModelInvocationAuditRecord>,
original: unknown,
artifact?: Readonly<PluginPackagePromptOutputArtifact>,
artifactRepository?: PluginPackagePromptOutputCompletionRepository,
): Promise<Readonly<ModelInvocationCompletionRecord> | null> {
extension?: ModelInvocationAtomicSuccess<TReference>,
): Promise<
Readonly<{
completion: Readonly<ModelInvocationCompletionRecord>;
reference?: Readonly<TReference>;
}> | null
> {
try {
const stored = await this.repository.findCompletion(audit.requestId);
if (!stored) return null;
const completion = assertCompletionMatchesAudit(stored, start, audit);
if (artifact) {
if (!artifactRepository) throw original;
const storedArtifact =
await artifactRepository.findPromptOutputArtifact(
artifact.artifactId,
);
if (
!storedArtifact ||
JSON.stringify(storedArtifact) !== JSON.stringify(artifact)
) {
if (extension) {
const reference = await extension.find(this.repository);
if (!reference || !extension.matches(reference)) {
throw original;
}
return Object.freeze({ completion, reference });
}
return completion;
return Object.freeze({ completion });
} catch {
throw original;
}
@@ -0,0 +1,55 @@
import type {
ModelInvocationAuditRecord,
ModelInvocationAuditDisposition,
} from '../model-gateway/model';
import type {
ModelInvocationCompletionCommand,
ModelInvocationRepository,
} from './modelInvocation';
export interface ModelInvocationAtomicSuccessCommit<TReference> {
readonly status: ModelInvocationAuditDisposition['status'];
readonly reference: Readonly<TReference>;
}
/**
* Domain-owned extension for one encrypted successful Model output.
*
* The generic Model coordinator owns the StepRun/usage/pricing protocol while
* this extension owns the output identity, exact replay check and dialect
* transaction that persists the encrypted output beside that protocol.
*/
export interface ModelInvocationAtomicSuccess<TReference> {
readonly outputRef: string;
assertAudit(record: Readonly<ModelInvocationAuditRecord>): void;
find(
repository: ModelInvocationRepository,
): Promise<Readonly<TReference> | null>;
matches(reference: Readonly<TReference>): boolean;
commit(
repository: ModelInvocationRepository,
command: Readonly<ModelInvocationCompletionCommand>,
): Promise<Readonly<ModelInvocationAtomicSuccessCommit<TReference>>>;
conflict(): Error;
}
export function normalizeModelInvocationAtomicSuccess<TReference>(
value: ModelInvocationAtomicSuccess<TReference>,
): ModelInvocationAtomicSuccess<TReference> {
if (
!value ||
typeof value !== 'object' ||
Array.isArray(value) ||
typeof value.outputRef !== 'string' ||
value.outputRef.length < 1 ||
value.outputRef.length > 512 ||
typeof value.assertAudit !== 'function' ||
typeof value.find !== 'function' ||
typeof value.matches !== 'function' ||
typeof value.commit !== 'function' ||
typeof value.conflict !== 'function'
) {
throw new TypeError('Model invocation atomic success is invalid');
}
return value;
}
@@ -1,4 +1,4 @@
import type { PostgresPool } from '@qinglong/runtime-core';
import type { PostgresClient, PostgresPool } from '@qinglong/runtime-core';
import { createModelInvocationPriceSettlement } from '../../pricing/pricing';
import { type PluginPackagePromptOutputArtifact } from '../../prompt-output/pluginPackagePromptOutputArtifact';
@@ -315,17 +315,36 @@ export async function completeWithPricingOperation(
});
}
export async function completeWithPromptOutputArtifactOperation(
export interface PostgresModelInvocationAtomicOutputBinding<
TArtifact,
TReference,
> {
readonly artifact: Readonly<TArtifact>;
readonly reference: Readonly<TReference>;
read(client: PostgresClient): Promise<Readonly<TArtifact> | null>;
put(client: PostgresClient): Promise<Readonly<TArtifact>>;
matches(stored: Readonly<TArtifact>): boolean;
}
export interface CommitPostgresModelInvocationAtomicOutputResult<
TArtifact,
TReference,
> extends CommitModelInvocationResult<ModelInvocationCompletionRecord> {
readonly artifact: Readonly<TArtifact>;
readonly reference: Readonly<TReference>;
}
export async function completeWithAtomicOutputOperation<TArtifact, TReference>(
pool: PostgresPool,
commandValue: ModelInvocationCompletionCommand,
artifactValue: PluginPackagePromptOutputArtifact,
): Promise<Readonly<CommitPluginPackagePromptOutputResult>> {
binding: PostgresModelInvocationAtomicOutputBinding<TArtifact, TReference>,
): Promise<
Readonly<
CommitPostgresModelInvocationAtomicOutputResult<TArtifact, TReference>
>
> {
const command = normalizeModelInvocationCompletionCommand(commandValue);
const completion = command.completion;
const binding = assertPluginPackagePromptOutputCompletionBinding(
command,
artifactValue,
);
const expectedUsage = createModelInvocationUsageLedgerRecord(
command.start,
completion,
@@ -377,10 +396,7 @@ export async function completeWithPromptOutputArtifactOperation(
if (existing[0]) {
const [storedArtifact, usage, priceSettlements, quotaSettlements] =
await Promise.all([
readPostgresPluginPackagePromptOutputArtifactInTransaction(
client,
binding.artifact.artifactId,
),
binding.read(client),
usageRows(client, 'usage.invocation_id = $1', [
completion.invocationId,
]),
@@ -395,7 +411,7 @@ export async function completeWithPromptOutputArtifactOperation(
if (
JSON.stringify(stored) !== JSON.stringify(completion) ||
!storedArtifact ||
JSON.stringify(storedArtifact) !== JSON.stringify(binding.artifact) ||
!binding.matches(storedArtifact) ||
usage.length !== (expectedUsage ? 1 : 0) ||
(expectedUsage &&
JSON.stringify(parseUsage(usage[0]!)) !==
@@ -434,12 +450,6 @@ export async function completeWithPromptOutputArtifactOperation(
throw new ModelInvocationConflictError();
}
await assertCurrent(client, command.stepRunMutation, completion.projectId);
const artifact = (
await putPostgresPluginPackagePromptOutputArtifactInTransaction(
client,
binding.artifact,
)
).artifact;
await applyMutation(client, command.stepRunMutation);
await insertCompletion(client, completion);
if (expectedUsage) await insertUsage(client, expectedUsage);
@@ -449,6 +459,7 @@ export async function completeWithPromptOutputArtifactOperation(
if (expectedQuotaSettlement) {
await insertQuotaSettlement(client, expectedQuotaSettlement);
}
const artifact = await binding.put(client);
return Object.freeze({
status: 'created' as const,
record: completion,
@@ -457,3 +468,33 @@ export async function completeWithPromptOutputArtifactOperation(
});
});
}
export async function completeWithPromptOutputArtifactOperation(
pool: PostgresPool,
commandValue: ModelInvocationCompletionCommand,
artifactValue: PluginPackagePromptOutputArtifact,
): Promise<Readonly<CommitPluginPackagePromptOutputResult>> {
const command = normalizeModelInvocationCompletionCommand(commandValue);
const binding = assertPluginPackagePromptOutputCompletionBinding(
command,
artifactValue,
);
return completeWithAtomicOutputOperation(pool, command, {
artifact: binding.artifact,
reference: binding.reference,
read: (client) =>
readPostgresPluginPackagePromptOutputArtifactInTransaction(
client,
binding.artifact.artifactId,
),
put: async (client) =>
(
await putPostgresPluginPackagePromptOutputArtifactInTransaction(
client,
binding.artifact,
)
).artifact,
matches: (stored) =>
JSON.stringify(stored) === JSON.stringify(binding.artifact),
});
}