mirror of
https://github.com/whyour/qinglong.git
synced 2026-09-21 01:00:24 +08:00
feat(ql3): establish 3.0 incubation baseline
This commit is contained in:
@@ -0,0 +1,190 @@
|
||||
const assert = require('node:assert/strict');
|
||||
const { createHash } = require('node:crypto');
|
||||
const { DatabaseSync } = require('node:sqlite');
|
||||
const { test } = require('node:test');
|
||||
|
||||
const {
|
||||
ToolInvocationArtifactConflictError,
|
||||
ToolInvocationArtifactUnavailableError,
|
||||
createToolInvocationInputArtifact,
|
||||
createToolInvocationPreviewArtifact,
|
||||
} = require('@qinglong/runtime-core/tool-invocation-artifact');
|
||||
const {
|
||||
LocalSqliteOperationAuthority,
|
||||
} = require('../dist/authority/operationAuthority');
|
||||
const { migrateLocalSqliteDatabase } = require('../dist/migration/migration');
|
||||
const {
|
||||
LocalSqliteToolInvocationArtifactRepository,
|
||||
} = require('../dist/tool-execution/toolInvocationArtifactRepository');
|
||||
|
||||
const KEY = Buffer.alloc(32, 7);
|
||||
const NONCE = Buffer.alloc(12, 9);
|
||||
const INVOCATION_ACTION_DIGEST = 'a'.repeat(64);
|
||||
const ACTION_DIGEST = 'b'.repeat(64);
|
||||
const REDACTION_DIGEST = 'c'.repeat(64);
|
||||
|
||||
function digest(value) {
|
||||
return createHash('sha256').update(JSON.stringify(value)).digest('hex');
|
||||
}
|
||||
|
||||
function artifacts(index = 1, overrides = {}) {
|
||||
const input = {
|
||||
runId: `run-${String(index).padStart(3, '0')}`,
|
||||
token: 'secret-value',
|
||||
};
|
||||
const common = {
|
||||
projectId: 'project-001',
|
||||
actionRef: `tool-plan:${input.runId}`,
|
||||
sealedAtMs: 1_000 + index,
|
||||
...overrides.common,
|
||||
};
|
||||
const inputArtifact = createToolInvocationInputArtifact(
|
||||
{
|
||||
artifactId: `artifact-input-${index}`,
|
||||
requestedBy: { type: 'user', id: 'usr-owner' },
|
||||
tool: { name: 'demo.compare', version: '1.0.0' },
|
||||
input,
|
||||
inputDigest: digest(input),
|
||||
invocationActionDigest: INVOCATION_ACTION_DIGEST,
|
||||
keyId: 'tool-key-test',
|
||||
key: KEY,
|
||||
...common,
|
||||
...overrides.input,
|
||||
},
|
||||
() => NONCE,
|
||||
);
|
||||
const previewArtifact = createToolInvocationPreviewArtifact({
|
||||
artifactId: `artifact-preview-${index}`,
|
||||
actionDigest: ACTION_DIGEST,
|
||||
redactionContractDigest: REDACTION_DIGEST,
|
||||
preview: {
|
||||
title: 'Compare Run',
|
||||
summary: 'Reads one bounded Run projection',
|
||||
fields: [
|
||||
{ kind: 'identifier', label: 'Run', value: input.runId },
|
||||
{ kind: 'redacted', label: 'Credential', value: null },
|
||||
],
|
||||
warnings: [],
|
||||
},
|
||||
...common,
|
||||
...overrides.preview,
|
||||
});
|
||||
return { inputArtifact, previewArtifact };
|
||||
}
|
||||
|
||||
async function harness() {
|
||||
const client = new DatabaseSync(':memory:');
|
||||
client.exec('PRAGMA foreign_keys = ON');
|
||||
await migrateLocalSqliteDatabase(client);
|
||||
client
|
||||
.prepare(
|
||||
`INSERT INTO "QingLong3Projects" (
|
||||
id, name, slug, status, version, created_at_ms, updated_at_ms
|
||||
) VALUES ('project-001', 'Project', 'project-001', 'active', 1, 1, 1)`,
|
||||
)
|
||||
.run();
|
||||
const authority = new LocalSqliteOperationAuthority(client);
|
||||
return {
|
||||
client,
|
||||
repository: new LocalSqliteToolInvocationArtifactRepository(authority),
|
||||
close: () => authority.close(),
|
||||
};
|
||||
}
|
||||
|
||||
test('atomically inserts and exactly replays one Artifact pair', async (t) => {
|
||||
const current = await harness();
|
||||
t.after(current.close);
|
||||
const pair = artifacts();
|
||||
assert.deepEqual(
|
||||
await current.repository.put(pair.inputArtifact, pair.previewArtifact),
|
||||
{ status: 'inserted' },
|
||||
);
|
||||
assert.deepEqual(
|
||||
await current.repository.put(pair.inputArtifact, pair.previewArtifact),
|
||||
{ status: 'existing' },
|
||||
);
|
||||
assert.deepEqual(
|
||||
await current.repository.findInput(pair.inputArtifact.artifactId),
|
||||
pair.inputArtifact,
|
||||
);
|
||||
assert.deepEqual(
|
||||
await current.repository.findPreview(pair.previewArtifact.artifactId),
|
||||
pair.previewArtifact,
|
||||
);
|
||||
assert.equal(
|
||||
JSON.stringify(
|
||||
current.client
|
||||
.prepare(
|
||||
`SELECT artifact_json FROM "ToolInvocationInputArtifacts"`,
|
||||
)
|
||||
.get(),
|
||||
).includes('secret-value'),
|
||||
false,
|
||||
);
|
||||
});
|
||||
|
||||
test('rejects pair drift and rolls back both rows', async (t) => {
|
||||
const current = await harness();
|
||||
t.after(current.close);
|
||||
const pair = artifacts();
|
||||
const detached = artifacts(2, {
|
||||
common: {
|
||||
projectId: 'project-001',
|
||||
actionRef: 'tool-plan:detached',
|
||||
sealedAtMs: 1_002,
|
||||
},
|
||||
});
|
||||
await assert.rejects(
|
||||
current.repository.put(pair.inputArtifact, detached.previewArtifact),
|
||||
ToolInvocationArtifactConflictError,
|
||||
);
|
||||
assert.equal(
|
||||
current.client
|
||||
.prepare(
|
||||
`SELECT count(*) AS count FROM "ToolInvocationInputArtifacts"`,
|
||||
)
|
||||
.get().count,
|
||||
0,
|
||||
);
|
||||
assert.equal(
|
||||
current.client
|
||||
.prepare(
|
||||
`SELECT count(*) AS count FROM "ToolInvocationPreviewArtifacts"`,
|
||||
)
|
||||
.get().count,
|
||||
0,
|
||||
);
|
||||
});
|
||||
|
||||
test('fails closed when a stored projection is corrupted', async (t) => {
|
||||
const current = await harness();
|
||||
t.after(current.close);
|
||||
const pair = artifacts();
|
||||
await current.repository.put(pair.inputArtifact, pair.previewArtifact);
|
||||
current.client.exec('PRAGMA ignore_check_constraints = ON');
|
||||
current.client
|
||||
.prepare(
|
||||
`UPDATE "ToolInvocationInputArtifacts"
|
||||
SET input_digest = ?
|
||||
WHERE artifact_id = ?`,
|
||||
)
|
||||
.run('d'.repeat(64), pair.inputArtifact.artifactId);
|
||||
current.client.exec('PRAGMA ignore_check_constraints = OFF');
|
||||
await assert.rejects(
|
||||
current.repository.findInput(pair.inputArtifact.artifactId),
|
||||
ToolInvocationArtifactUnavailableError,
|
||||
);
|
||||
});
|
||||
|
||||
test('publishes only the explicit adapter subpath', () => {
|
||||
const root = require('../dist');
|
||||
const subpath = require('@qinglong/local-sqlite/tool-invocation-artifact');
|
||||
assert.equal(
|
||||
root.LocalSqliteToolInvocationArtifactRepository,
|
||||
LocalSqliteToolInvocationArtifactRepository,
|
||||
);
|
||||
assert.equal(
|
||||
subpath.LocalSqliteToolInvocationArtifactRepository,
|
||||
LocalSqliteToolInvocationArtifactRepository,
|
||||
);
|
||||
});
|
||||
Reference in New Issue
Block a user