mirror of
https://github.com/Kaelio/ktx.git
synced 2026-06-25 08:48:08 +02:00
Initial open-source release
This commit is contained in:
commit
1a42152e6f
1199 changed files with 257054 additions and 0 deletions
123
packages/context/src/llm/debug-request-recorder.test.ts
Normal file
123
packages/context/src/llm/debug-request-recorder.test.ts
Normal file
|
|
@ -0,0 +1,123 @@
|
|||
import { mkdtemp, readFile, rm } from 'node:fs/promises';
|
||||
import { tmpdir } from 'node:os';
|
||||
import { join } from 'node:path';
|
||||
import { afterEach, describe, expect, it } from 'vitest';
|
||||
import {
|
||||
createJsonlKloLlmDebugRequestRecorder,
|
||||
summarizeKloLlmDebugRequest,
|
||||
} from './debug-request-recorder.js';
|
||||
|
||||
describe('summarizeKloLlmDebugRequest', () => {
|
||||
it('records providerOptions positions without message text or tool schemas', () => {
|
||||
const summary = summarizeKloLlmDebugRequest({
|
||||
operationName: 'ingest-bundle-wu',
|
||||
source: 'metabase',
|
||||
jobId: 'job-1',
|
||||
unitKey: 'cards/1',
|
||||
modelRole: 'candidateExtraction',
|
||||
modelId: 'claude-sonnet-4-6',
|
||||
messages: [
|
||||
{
|
||||
role: 'system',
|
||||
content: 'SECRET SYSTEM PROMPT',
|
||||
providerOptions: { anthropic: { cacheControl: { type: 'ephemeral', ttl: '1h' } } },
|
||||
},
|
||||
{
|
||||
role: 'user',
|
||||
content: [
|
||||
{
|
||||
type: 'text',
|
||||
text: 'SECRET USER PROMPT',
|
||||
providerOptions: { anthropic: { cacheControl: { type: 'ephemeral', ttl: '5m' } } },
|
||||
},
|
||||
],
|
||||
},
|
||||
],
|
||||
tools: {
|
||||
emit_candidate: {
|
||||
description: 'SECRET TOOL DESCRIPTION',
|
||||
inputSchema: { secret: true },
|
||||
providerOptions: { anthropic: { cacheControl: { type: 'ephemeral', ttl: '1h' } } },
|
||||
},
|
||||
},
|
||||
});
|
||||
|
||||
expect(summary).toMatchObject({
|
||||
operationName: 'ingest-bundle-wu',
|
||||
source: 'metabase',
|
||||
jobId: 'job-1',
|
||||
unitKey: 'cards/1',
|
||||
modelRole: 'candidateExtraction',
|
||||
modelId: 'claude-sonnet-4-6',
|
||||
messageCount: 2,
|
||||
toolNames: ['emit_candidate'],
|
||||
providerOptions: [
|
||||
{
|
||||
target: 'message',
|
||||
index: 0,
|
||||
role: 'system',
|
||||
providerOptions: { anthropic: { cacheControl: { type: 'ephemeral', ttl: '1h' } } },
|
||||
},
|
||||
{
|
||||
target: 'message-part',
|
||||
index: 1,
|
||||
role: 'user',
|
||||
partIndex: 0,
|
||||
providerOptions: { anthropic: { cacheControl: { type: 'ephemeral', ttl: '5m' } } },
|
||||
},
|
||||
{
|
||||
target: 'tool',
|
||||
name: 'emit_candidate',
|
||||
providerOptions: { anthropic: { cacheControl: { type: 'ephemeral', ttl: '1h' } } },
|
||||
},
|
||||
],
|
||||
});
|
||||
|
||||
const serialized = JSON.stringify(summary);
|
||||
expect(serialized).not.toContain('SECRET SYSTEM PROMPT');
|
||||
expect(serialized).not.toContain('SECRET USER PROMPT');
|
||||
expect(serialized).not.toContain('SECRET TOOL DESCRIPTION');
|
||||
expect(serialized).not.toContain('inputSchema');
|
||||
});
|
||||
});
|
||||
|
||||
describe('createJsonlKloLlmDebugRequestRecorder', () => {
|
||||
let tempDir: string | undefined;
|
||||
|
||||
afterEach(async () => {
|
||||
if (tempDir) {
|
||||
await rm(tempDir, { recursive: true, force: true });
|
||||
tempDir = undefined;
|
||||
}
|
||||
});
|
||||
|
||||
it('appends one JSON object per recorded request', async () => {
|
||||
tempDir = await mkdtemp(join(tmpdir(), 'klo-llm-debug-'));
|
||||
const filePath = join(tempDir, 'nested', 'llm-debug.jsonl');
|
||||
const recorder = createJsonlKloLlmDebugRequestRecorder(filePath);
|
||||
|
||||
await recorder.record({
|
||||
timestamp: '2026-05-04T00:00:00.000Z',
|
||||
operationName: 'ingest-bundle-wu',
|
||||
modelRole: 'candidateExtraction',
|
||||
modelId: 'claude-sonnet-4-6',
|
||||
messageCount: 2,
|
||||
toolNames: ['emit_candidate'],
|
||||
providerOptions: [],
|
||||
});
|
||||
await recorder.record({
|
||||
timestamp: '2026-05-04T00:00:01.000Z',
|
||||
operationName: 'ingest-bundle-reconcile',
|
||||
modelRole: 'reconcile',
|
||||
modelId: 'claude-sonnet-4-6',
|
||||
messageCount: 2,
|
||||
toolNames: [],
|
||||
providerOptions: [],
|
||||
});
|
||||
|
||||
const lines = (await readFile(filePath, 'utf8')).trim().split('\n').map((line) => JSON.parse(line));
|
||||
expect(lines).toHaveLength(2);
|
||||
expect(lines[0]).toMatchObject({ operationName: 'ingest-bundle-wu', modelRole: 'candidateExtraction' });
|
||||
expect(lines[1]).toMatchObject({ operationName: 'ingest-bundle-reconcile', modelRole: 'reconcile' });
|
||||
});
|
||||
});
|
||||
Loading…
Add table
Add a link
Reference in a new issue