mirror of
https://github.com/whyour/qinglong.git
synced 2026-09-21 01:32:44 +08:00
feat(ql3): establish 3.0 incubation baseline
This commit is contained in:
@@ -0,0 +1,223 @@
|
||||
const assert = require('node:assert/strict');
|
||||
const test = require('node:test');
|
||||
|
||||
const {
|
||||
pluginPackageAutomationPublicationDigest,
|
||||
} = require('@qinglong/runtime-core/plugin-package-automation-publication');
|
||||
const {
|
||||
preparePluginPackagePromptExecution,
|
||||
} = require('../dist/prompt/pluginPackagePromptExecution.js');
|
||||
const {
|
||||
createPluginPackagePromptOutputArtifact,
|
||||
} = require('../dist/prompt-output/pluginPackagePromptOutputArtifact.js');
|
||||
const {
|
||||
PostgresPluginPackagePromptOutputArtifactRepository,
|
||||
} = require('../dist/prompt-output/storage/postgresPluginPackagePromptOutputArtifactRepository.js');
|
||||
|
||||
function publication() {
|
||||
const unsigned = {
|
||||
schema: 'qinglong/plugin-package-automation-publication@v1',
|
||||
target: {
|
||||
projectId: 'project-a',
|
||||
packageName: 'package-a',
|
||||
installationId: 'installation-a',
|
||||
lockDigest: '1'.repeat(64),
|
||||
generation: 1,
|
||||
generationDigest: '2'.repeat(64),
|
||||
materializedRevisionDigest: '3'.repeat(64),
|
||||
},
|
||||
state: 'active',
|
||||
version: 1,
|
||||
previousPublicationDigest: null,
|
||||
lifecycleEventDigest: null,
|
||||
definitions: {
|
||||
workflows: [],
|
||||
prompts: [
|
||||
{
|
||||
schema: 'qinglong/plugin-package-prompt-resource@v1',
|
||||
id: 'summary',
|
||||
name: 'Summary',
|
||||
template: 'Summarize {{subject}}.',
|
||||
parameters: [{ name: 'subject', required: true }],
|
||||
},
|
||||
],
|
||||
},
|
||||
publishedAtMs: 1_000,
|
||||
};
|
||||
return {
|
||||
...unsigned,
|
||||
publicationDigest: pluginPackageAutomationPublicationDigest(unsigned),
|
||||
};
|
||||
}
|
||||
|
||||
function prepared(output) {
|
||||
const active = publication();
|
||||
return preparePluginPackagePromptExecution({
|
||||
publication: active,
|
||||
expectedPublicationDigest: active.publicationDigest,
|
||||
promptId: 'summary',
|
||||
requestId: 'prompt-request-a',
|
||||
traceId: 'trace-a',
|
||||
requestedBySubject: { type: 'user', id: 'user-a' },
|
||||
policyFence: { projectVersion: 1, bindingVersion: 1 },
|
||||
parameters: { subject: 'private input' },
|
||||
provider: 'openai-compatible',
|
||||
model: 'model-a',
|
||||
maxOutputTokens: 64,
|
||||
plannedAtMs: 2_000,
|
||||
deadlineAtMs: 62_000,
|
||||
...(output === undefined ? {} : { output }),
|
||||
});
|
||||
}
|
||||
|
||||
function row(artifact) {
|
||||
return {
|
||||
artifactId: artifact.artifactId,
|
||||
projectId: artifact.projectId,
|
||||
runId: artifact.runId,
|
||||
stepRunId: artifact.stepRunId,
|
||||
invocationId: artifact.invocationId,
|
||||
requestedByType: artifact.requestedBy.type,
|
||||
requestedById: artifact.requestedBy.id,
|
||||
provider: artifact.provider,
|
||||
model: artifact.model,
|
||||
contentDigest: artifact.contentDigest,
|
||||
outputBytes: artifact.outputBytes,
|
||||
retentionPolicyRevision: artifact.retentionPolicy.revision,
|
||||
retentionMs: String(artifact.retentionPolicy.retentionMs),
|
||||
retentionPolicyDigest: artifact.retentionPolicyDigest,
|
||||
retentionEligibleAtMs: String(artifact.retentionEligibleAtMs),
|
||||
keyId: artifact.keyId,
|
||||
algorithm: artifact.algorithm,
|
||||
plaintextBytes: artifact.plaintextBytes,
|
||||
sealedAtMs: String(artifact.sealedAtMs),
|
||||
artifactDigest: artifact.artifactDigest,
|
||||
artifactJson: artifact,
|
||||
};
|
||||
}
|
||||
|
||||
function fakePool(plan) {
|
||||
const queries = [];
|
||||
let stored = null;
|
||||
const client = {
|
||||
async query(sql, parameters = []) {
|
||||
queries.push(sql);
|
||||
if (sql.includes('model_invocation_prompt_admissions')) {
|
||||
return { rows: [{ planJson: plan }] };
|
||||
}
|
||||
if (
|
||||
sql.startsWith('SELECT artifact_id') &&
|
||||
sql.includes('model_invocation_prompt_output_artifacts')
|
||||
) {
|
||||
return {
|
||||
rows: stored && stored.artifactId === parameters[0] ? [stored] : [],
|
||||
};
|
||||
}
|
||||
if (
|
||||
sql.includes('INSERT INTO') &&
|
||||
sql.includes('prompt_output_artifacts')
|
||||
) {
|
||||
const artifact = JSON.parse(parameters[20]);
|
||||
stored = row(artifact);
|
||||
return { rows: [] };
|
||||
}
|
||||
return { rows: [] };
|
||||
},
|
||||
release() {},
|
||||
};
|
||||
return {
|
||||
queries,
|
||||
async connect() {
|
||||
return client;
|
||||
},
|
||||
async query(sql, parameters) {
|
||||
return client.query(sql, parameters);
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
test('PostgreSQL Prompt output Artifact is immutable and plan-bound', async () => {
|
||||
const durable = prepared({
|
||||
mode: 'durable_artifact',
|
||||
retentionPolicy: { revision: 'cluster-v1', retentionMs: 86_400_000 },
|
||||
});
|
||||
const artifact = createPluginPackagePromptOutputArtifact(
|
||||
{
|
||||
projectId: durable.plan.target.projectId,
|
||||
runId: durable.plan.runId,
|
||||
stepRunId: durable.plan.stepRunId,
|
||||
invocationId: durable.plan.invocationId,
|
||||
requestedBy: durable.plan.requestedBySubject,
|
||||
result: {
|
||||
provider: durable.plan.provider,
|
||||
model: durable.plan.model,
|
||||
text: 'private PostgreSQL Artifact output',
|
||||
finishReason: 'stop',
|
||||
usage: { inputTokens: 2, outputTokens: 3, totalTokens: 5 },
|
||||
},
|
||||
retentionPolicy: durable.plan.output.retentionPolicy,
|
||||
keyId: 'cluster-key-1',
|
||||
key: Buffer.alloc(32, 7),
|
||||
sealedAtMs: 3_000,
|
||||
},
|
||||
() => Buffer.alloc(12, 9),
|
||||
);
|
||||
const pool = fakePool(durable.plan);
|
||||
const repository = new PostgresPluginPackagePromptOutputArtifactRepository(
|
||||
pool,
|
||||
);
|
||||
|
||||
assert.deepEqual(await repository.put(artifact), { status: 'inserted' });
|
||||
assert.deepEqual(await repository.put(artifact), { status: 'existing' });
|
||||
assert.deepEqual(await repository.find(artifact.artifactId), artifact);
|
||||
assert.equal(pool.queries.includes('BEGIN'), true);
|
||||
assert.equal(
|
||||
pool.queries.includes('SET TRANSACTION ISOLATION LEVEL SERIALIZABLE'),
|
||||
true,
|
||||
);
|
||||
assert.equal(
|
||||
pool.queries.some((sql) => /FOR (?:UPDATE|SHARE)/.test(sql)),
|
||||
false,
|
||||
);
|
||||
assert.equal(
|
||||
JSON.stringify(row(artifact)).includes(artifact.ciphertext),
|
||||
true,
|
||||
);
|
||||
assert.equal(
|
||||
JSON.stringify(row(artifact)).includes('private PostgreSQL'),
|
||||
false,
|
||||
);
|
||||
|
||||
const live = prepared();
|
||||
const livePool = fakePool(live.plan);
|
||||
const liveRepository =
|
||||
new PostgresPluginPackagePromptOutputArtifactRepository(livePool);
|
||||
const liveArtifact = createPluginPackagePromptOutputArtifact(
|
||||
{
|
||||
projectId: live.plan.target.projectId,
|
||||
runId: live.plan.runId,
|
||||
stepRunId: live.plan.stepRunId,
|
||||
invocationId: live.plan.invocationId,
|
||||
requestedBy: live.plan.requestedBySubject,
|
||||
result: {
|
||||
provider: live.plan.provider,
|
||||
model: live.plan.model,
|
||||
text: 'must remain live only',
|
||||
finishReason: 'stop',
|
||||
usage: { inputTokens: 1, outputTokens: 1, totalTokens: 2 },
|
||||
},
|
||||
retentionPolicy: { revision: 'cluster-v1', retentionMs: 86_400_000 },
|
||||
keyId: 'cluster-key-1',
|
||||
key: Buffer.alloc(32, 7),
|
||||
sealedAtMs: 3_000,
|
||||
},
|
||||
() => Buffer.alloc(12, 9),
|
||||
);
|
||||
await assert.rejects(liveRepository.put(liveArtifact), {
|
||||
code: 'PLUGIN_PACKAGE_PROMPT_OUTPUT_ARTIFACT_CONFLICT',
|
||||
});
|
||||
assert.equal(
|
||||
livePool.queries.some((sql) => sql.includes('INSERT INTO')),
|
||||
false,
|
||||
);
|
||||
});
|
||||
Reference in New Issue
Block a user