@pikku/kysely 0.13.13 → 0.13.15
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +34 -0
- package/dist/src/index.d.ts +2 -5
- package/dist/src/index.js +2 -3
- package/dist/src/kysely-ai-run-scores.d.ts +10 -0
- package/dist/src/kysely-ai-run-scores.js +34 -0
- package/dist/src/kysely-ai-run-state-service.d.ts +4 -1
- package/dist/src/kysely-ai-run-state-service.js +7 -0
- package/dist/src/kysely-ai-storage-service.d.ts +4 -1
- package/dist/src/kysely-ai-storage-service.js +7 -0
- package/dist/src/kysely-tables.d.ts +12 -0
- package/dist/src/schema/ai.schema.js +13 -0
- package/dist/tsconfig.tsbuildinfo +1 -1
- package/package.json +2 -2
- package/src/index.ts +0 -15
- package/src/kysely-ai-run-scores.ts +47 -0
- package/src/kysely-ai-run-state-service.ts +15 -1
- package/src/kysely-ai-storage-service.ts +11 -0
- package/src/kysely-services.test.ts +1 -0
- package/src/kysely-tables.ts +13 -0
- package/src/schema/ai.schema.ts +21 -0
package/CHANGELOG.md
CHANGED
|
@@ -1,3 +1,37 @@
|
|
|
1
|
+
## 0.13.15
|
|
2
|
+
|
|
3
|
+
### Patch Changes
|
|
4
|
+
|
|
5
|
+
- fd9d834: Stop publishing internals that only their own package or file used. The declarations stay; only the entrypoint re-export is removed, so nothing that imported a name from where it is declared is affected.
|
|
6
|
+
- Updated dependencies [063f43a]
|
|
7
|
+
- Updated dependencies [ce66bf8]
|
|
8
|
+
- Updated dependencies [d0307a8]
|
|
9
|
+
- Updated dependencies [ce66bf8]
|
|
10
|
+
- Updated dependencies [3ad2131]
|
|
11
|
+
- Updated dependencies [b930dca]
|
|
12
|
+
- Updated dependencies [b95e77d]
|
|
13
|
+
- Updated dependencies [fd9d834]
|
|
14
|
+
- Updated dependencies [8978fbd]
|
|
15
|
+
- @pikku/core@0.12.82
|
|
16
|
+
|
|
17
|
+
## 0.13.14
|
|
18
|
+
|
|
19
|
+
### Patch Changes
|
|
20
|
+
|
|
21
|
+
- e110c55: Add runtime scoring for AI agents: `pikkuAIScorer` for heuristic grades and
|
|
22
|
+
`pikkuAIJudge` for LLM-judged ones, graded off the request path on two queue
|
|
23
|
+
lanes so a slow judge cannot starve the cheap checks. Grades are sampled
|
|
24
|
+
deterministically per `(run, scorer)` and persisted to `ai_run_score`.
|
|
25
|
+
- Updated dependencies [e110c55]
|
|
26
|
+
- Updated dependencies [e110c55]
|
|
27
|
+
- Updated dependencies [e110c55]
|
|
28
|
+
- Updated dependencies [acc8077]
|
|
29
|
+
- Updated dependencies [905f737]
|
|
30
|
+
- Updated dependencies [3cc6428]
|
|
31
|
+
- Updated dependencies [c524adf]
|
|
32
|
+
- Updated dependencies [e110c55]
|
|
33
|
+
- @pikku/core@0.12.81
|
|
34
|
+
|
|
1
35
|
## 0.13.13
|
|
2
36
|
|
|
3
37
|
### Patch Changes
|
package/dist/src/index.d.ts
CHANGED
|
@@ -8,18 +8,15 @@ export { KyselyAIStorageService } from './kysely-ai-storage-service.js';
|
|
|
8
8
|
export { KyselyAgentRunService } from './kysely-ai-agent-run-service.js';
|
|
9
9
|
export { KyselyAIRunStateService } from './kysely-ai-run-state-service.js';
|
|
10
10
|
export { KyselySecretService } from './kysely-secret-service.js';
|
|
11
|
-
export type { KyselySecretServiceConfig } from './kysely-secret-service.js';
|
|
12
11
|
export { KyselyCredentialService } from './kysely-credential-service.js';
|
|
13
|
-
export type { KyselyCredentialServiceConfig } from './kysely-credential-service.js';
|
|
14
12
|
export { KyselySessionStore } from './kysely-session-store.js';
|
|
15
13
|
export { KyselyScopeService } from './kysely-scope-service.js';
|
|
16
14
|
export { KyselyWebhookService } from './kysely-webhook-service.js';
|
|
17
15
|
export { createAuditedKysely, type CreateAuditedKyselyOptions, } from './create-audited-kysely.js';
|
|
18
16
|
export { KyselyAuditService } from './kysely-audit-service.js';
|
|
19
17
|
export { KyselyVirtualUserRunStore } from './kysely-virtual-user-run-store.js';
|
|
20
|
-
export { SerializePlugin, SqliteSerializePlugin, BaseSerializePlugin,
|
|
21
|
-
export {
|
|
22
|
-
export { auditSchema, pikkuSchemas, applyPikkuSchemas, compilePikkuSchemas, ensurePikkuSchema, type EnsureOutcome, resolveRequirements, unsatisfiedRequirements, rawStatement, requiredType, type PikkuSchema, type RequiredTypes, type SchemaRequirement, type UnmetRequirement, type SchemaStatement, type SchemaStatementFactory, } from './schema/index.js';
|
|
18
|
+
export { SerializePlugin, SqliteSerializePlugin, BaseSerializePlugin, type Serializer, type Deserializer, } from './serialize-plugin.js';
|
|
19
|
+
export { auditSchema, pikkuSchemas, applyPikkuSchemas, compilePikkuSchemas, ensurePikkuSchema, type EnsureOutcome, resolveRequirements, type PikkuSchema, type RequiredTypes, type UnmetRequirement, type SchemaStatementFactory, } from './schema/index.js';
|
|
23
20
|
export type { KyselyPikkuDB } from './kysely-tables.js';
|
|
24
21
|
export type { WorkflowRunService } from '@pikku/core/workflow';
|
|
25
22
|
export type { AgentRunService, AgentRunRow } from '@pikku/core/ai-agent';
|
package/dist/src/index.js
CHANGED
|
@@ -15,6 +15,5 @@ export { KyselyWebhookService } from './kysely-webhook-service.js';
|
|
|
15
15
|
export { createAuditedKysely, } from './create-audited-kysely.js';
|
|
16
16
|
export { KyselyAuditService } from './kysely-audit-service.js';
|
|
17
17
|
export { KyselyVirtualUserRunStore } from './kysely-virtual-user-run-store.js';
|
|
18
|
-
export { SerializePlugin, SqliteSerializePlugin, BaseSerializePlugin,
|
|
19
|
-
export {
|
|
20
|
-
export { auditSchema, pikkuSchemas, applyPikkuSchemas, compilePikkuSchemas, ensurePikkuSchema, resolveRequirements, unsatisfiedRequirements, rawStatement, requiredType, } from './schema/index.js';
|
|
18
|
+
export { SerializePlugin, SqliteSerializePlugin, BaseSerializePlugin, } from './serialize-plugin.js';
|
|
19
|
+
export { auditSchema, pikkuSchemas, applyPikkuSchemas, compilePikkuSchemas, ensurePikkuSchema, resolveRequirements, } from './schema/index.js';
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import type { Kysely } from 'kysely';
|
|
2
|
+
import type { KyselyPikkuDB } from './kysely-tables.js';
|
|
3
|
+
import type { SaveScoreInput } from '@pikku/core/services';
|
|
4
|
+
import type { AIRunScore } from '@pikku/core/ai-scorer';
|
|
5
|
+
/**
|
|
6
|
+
* Shared by the two Kysely services that implement `AIRunStateService` — they
|
|
7
|
+
* differ in how they store approvals, not in how they store grades.
|
|
8
|
+
*/
|
|
9
|
+
export declare const saveRunScore: (db: Kysely<KyselyPikkuDB>, score: SaveScoreInput) => Promise<void>;
|
|
10
|
+
export declare const getRunScores: (db: Kysely<KyselyPikkuDB>, runId: string) => Promise<AIRunScore[]>;
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
import { parseJson } from './kysely-json.js';
|
|
2
|
+
/**
|
|
3
|
+
* Shared by the two Kysely services that implement `AIRunStateService` — they
|
|
4
|
+
* differ in how they store approvals, not in how they store grades.
|
|
5
|
+
*/
|
|
6
|
+
export const saveRunScore = async (db, score) => {
|
|
7
|
+
await db
|
|
8
|
+
.insertInto('aiRunScore')
|
|
9
|
+
.values({
|
|
10
|
+
id: crypto.randomUUID(),
|
|
11
|
+
runId: score.runId,
|
|
12
|
+
scorerName: score.scorerName,
|
|
13
|
+
score: score.score,
|
|
14
|
+
reason: score.reason ?? null,
|
|
15
|
+
metadata: score.metadata ? JSON.stringify(score.metadata) : null,
|
|
16
|
+
})
|
|
17
|
+
.execute();
|
|
18
|
+
};
|
|
19
|
+
export const getRunScores = async (db, runId) => {
|
|
20
|
+
const rows = await db
|
|
21
|
+
.selectFrom('aiRunScore')
|
|
22
|
+
.selectAll()
|
|
23
|
+
.where('runId', '=', runId)
|
|
24
|
+
.orderBy('createdAt', 'asc')
|
|
25
|
+
.execute();
|
|
26
|
+
return rows.map((row) => ({
|
|
27
|
+
runId: row.runId,
|
|
28
|
+
scorerName: row.scorerName,
|
|
29
|
+
score: Number(row.score),
|
|
30
|
+
reason: row.reason ?? undefined,
|
|
31
|
+
metadata: parseJson(row.metadata),
|
|
32
|
+
createdAt: new Date(row.createdAt),
|
|
33
|
+
}));
|
|
34
|
+
};
|
|
@@ -1,7 +1,8 @@
|
|
|
1
1
|
import type { Kysely } from 'kysely';
|
|
2
2
|
import type { KyselyPikkuDB } from './kysely-tables.js';
|
|
3
|
-
import type { AIRunStateService, CreateRunInput } from '@pikku/core/services';
|
|
3
|
+
import type { AIRunStateService, CreateRunInput, SaveScoreInput } from '@pikku/core/services';
|
|
4
4
|
import type { AgentRunState, PendingApproval } from '@pikku/core/ai-agent';
|
|
5
|
+
import type { AIRunScore } from '@pikku/core/ai-scorer';
|
|
5
6
|
export declare class KyselyAIRunStateService implements AIRunStateService {
|
|
6
7
|
private db;
|
|
7
8
|
private initialized;
|
|
@@ -16,5 +17,7 @@ export declare class KyselyAIRunStateService implements AIRunStateService {
|
|
|
16
17
|
run: AgentRunState;
|
|
17
18
|
approval: PendingApproval;
|
|
18
19
|
} | null>;
|
|
20
|
+
saveScore(score: SaveScoreInput): Promise<void>;
|
|
21
|
+
getScores(runId: string): Promise<AIRunScore[]>;
|
|
19
22
|
private toRunState;
|
|
20
23
|
}
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { sql } from 'kysely';
|
|
2
2
|
import { ensurePikkuSchema } from './schema/index.js';
|
|
3
3
|
import { aiSchema } from './schema/ai.schema.js';
|
|
4
|
+
import { getRunScores, saveRunScore } from './kysely-ai-run-scores.js';
|
|
4
5
|
export class KyselyAIRunStateService {
|
|
5
6
|
db;
|
|
6
7
|
initialized = false;
|
|
@@ -137,6 +138,12 @@ export class KyselyAIRunStateService {
|
|
|
137
138
|
}
|
|
138
139
|
return null;
|
|
139
140
|
}
|
|
141
|
+
async saveScore(score) {
|
|
142
|
+
await saveRunScore(this.db, score);
|
|
143
|
+
}
|
|
144
|
+
async getScores(runId) {
|
|
145
|
+
return getRunScores(this.db, runId);
|
|
146
|
+
}
|
|
140
147
|
toRunState(row) {
|
|
141
148
|
return {
|
|
142
149
|
runId: row.runId,
|
|
@@ -1,5 +1,6 @@
|
|
|
1
|
-
import type { AIStorageService, AIRunStateService, CreateRunInput } from '@pikku/core/services';
|
|
1
|
+
import type { AIStorageService, AIRunStateService, CreateRunInput, SaveScoreInput } from '@pikku/core/services';
|
|
2
2
|
import type { AIThread, AIMessage, AgentRunState } from '@pikku/core/ai-agent';
|
|
3
|
+
import type { AIRunScore } from '@pikku/core/ai-scorer';
|
|
3
4
|
import type { Kysely } from 'kysely';
|
|
4
5
|
import type { KyselyPikkuDB } from './kysely-tables.js';
|
|
5
6
|
export declare class KyselyAIStorageService implements AIStorageService, AIRunStateService {
|
|
@@ -33,5 +34,7 @@ export declare class KyselyAIStorageService implements AIStorageService, AIRunSt
|
|
|
33
34
|
approval: NonNullable<AgentRunState['pendingApprovals']>[number];
|
|
34
35
|
} | null>;
|
|
35
36
|
resolveApproval(toolCallId: string, status: 'approved' | 'denied'): Promise<boolean>;
|
|
37
|
+
saveScore(score: SaveScoreInput): Promise<void>;
|
|
38
|
+
getScores(runId: string): Promise<AIRunScore[]>;
|
|
36
39
|
close(): Promise<void>;
|
|
37
40
|
}
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { parseJson } from './kysely-json.js';
|
|
2
|
+
import { getRunScores, saveRunScore } from './kysely-ai-run-scores.js';
|
|
2
3
|
import { ensurePikkuSchema } from './schema/index.js';
|
|
3
4
|
import { aiSchema } from './schema/ai.schema.js';
|
|
4
5
|
export class KyselyAIStorageService {
|
|
@@ -519,5 +520,11 @@ export class KyselyAIStorageService {
|
|
|
519
520
|
.executeTakeFirst();
|
|
520
521
|
return Number(result?.numUpdatedRows ?? 0) > 0;
|
|
521
522
|
}
|
|
523
|
+
async saveScore(score) {
|
|
524
|
+
await saveRunScore(this.db, score);
|
|
525
|
+
}
|
|
526
|
+
async getScores(runId) {
|
|
527
|
+
return getRunScores(this.db, runId);
|
|
528
|
+
}
|
|
522
529
|
async close() { }
|
|
523
530
|
}
|
|
@@ -133,6 +133,17 @@ export interface AIRunTable {
|
|
|
133
133
|
createdAt: Generated<Date>;
|
|
134
134
|
updatedAt: Generated<Date>;
|
|
135
135
|
}
|
|
136
|
+
export interface AIRunScoreTable {
|
|
137
|
+
id: string;
|
|
138
|
+
runId: string;
|
|
139
|
+
scorerName: string;
|
|
140
|
+
/** 0..1, so grades are comparable across scorers. */
|
|
141
|
+
score: number;
|
|
142
|
+
reason: string | null;
|
|
143
|
+
/** JSON-serialized structured detail the scorer returned alongside the score. */
|
|
144
|
+
metadata: string | null;
|
|
145
|
+
createdAt: Generated<Date>;
|
|
146
|
+
}
|
|
136
147
|
export interface PikkuDeploymentsTable {
|
|
137
148
|
deploymentId: string;
|
|
138
149
|
endpoint: string;
|
|
@@ -295,6 +306,7 @@ export interface KyselyPikkuDB {
|
|
|
295
306
|
aiToolCall: AIToolCallTable;
|
|
296
307
|
aiWorkingMemory: AIWorkingMemoryTable;
|
|
297
308
|
aiRun: AIRunTable;
|
|
309
|
+
aiRunScore: AIRunScoreTable;
|
|
298
310
|
pikkuDeployments: PikkuDeploymentsTable;
|
|
299
311
|
pikkuDeploymentFunctions: PikkuDeploymentFunctionsTable;
|
|
300
312
|
secrets: SecretsTable;
|
|
@@ -85,5 +85,18 @@ export const aiSchema = {
|
|
|
85
85
|
.createIndex('idx_ai_run_thread')
|
|
86
86
|
.on('aiRun')
|
|
87
87
|
.columns(['threadId', 'createdAt']),
|
|
88
|
+
(db) => db.schema
|
|
89
|
+
.createTable('aiRunScore')
|
|
90
|
+
.addColumn('id', 'varchar(36)', (col) => col.primaryKey())
|
|
91
|
+
.addColumn('runId', 'varchar(36)', (col) => col.notNull().references('aiRun.runId').onDelete('cascade'))
|
|
92
|
+
.addColumn('scorerName', 'varchar(255)', (col) => col.notNull())
|
|
93
|
+
.addColumn('score', 'real', (col) => col.notNull())
|
|
94
|
+
.addColumn('reason', 'text')
|
|
95
|
+
.addColumn('metadata', 'text')
|
|
96
|
+
.addColumn('createdAt', 'timestamp', (col) => col.defaultTo(sql `CURRENT_TIMESTAMP`).notNull()),
|
|
97
|
+
(db) => db.schema
|
|
98
|
+
.createIndex('idx_ai_run_score_run')
|
|
99
|
+
.on('aiRunScore')
|
|
100
|
+
.columns(['runId', 'createdAt']),
|
|
88
101
|
],
|
|
89
102
|
};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"root":["../src/create-audited-kysely.ts","../src/index.ts","../src/kysely-ai-agent-run-service.ts","../src/kysely-ai-run-state-service.ts","../src/kysely-ai-storage-service.ts","../src/kysely-audit-service.ts","../src/kysely-channel-store.ts","../src/kysely-credential-service.ts","../src/kysely-deployment-service.ts","../src/kysely-eventhub-store.ts","../src/kysely-json.ts","../src/kysely-scope-service.ts","../src/kysely-secret-service.ts","../src/kysely-session-store.ts","../src/kysely-tables.ts","../src/kysely-virtual-user-run-store.ts","../src/kysely-webhook-service.ts","../src/kysely-workflow-mirror.ts","../src/kysely-workflow-run-service.ts","../src/kysely-workflow-service.ts","../src/serialize-plugin.ts","../src/schema/ai.schema.ts","../src/schema/audit.schema.ts","../src/schema/channel.schema.ts","../src/schema/credential.schema.ts","../src/schema/deployment.schema.ts","../src/schema/index.ts","../src/schema/pikku-schema.types.ts","../src/schema/scope.schema.ts","../src/schema/secret.schema.ts","../src/schema/session.schema.ts","../src/schema/virtual-user.schema.ts","../src/schema/webhook.schema.ts","../src/schema/workflow.schema.ts","../bin/pikku-kysely-pure.ts"],"version":"6.0.3"}
|
|
1
|
+
{"root":["../src/create-audited-kysely.ts","../src/index.ts","../src/kysely-ai-agent-run-service.ts","../src/kysely-ai-run-scores.ts","../src/kysely-ai-run-state-service.ts","../src/kysely-ai-storage-service.ts","../src/kysely-audit-service.ts","../src/kysely-channel-store.ts","../src/kysely-credential-service.ts","../src/kysely-deployment-service.ts","../src/kysely-eventhub-store.ts","../src/kysely-json.ts","../src/kysely-scope-service.ts","../src/kysely-secret-service.ts","../src/kysely-session-store.ts","../src/kysely-tables.ts","../src/kysely-virtual-user-run-store.ts","../src/kysely-webhook-service.ts","../src/kysely-workflow-mirror.ts","../src/kysely-workflow-run-service.ts","../src/kysely-workflow-service.ts","../src/serialize-plugin.ts","../src/schema/ai.schema.ts","../src/schema/audit.schema.ts","../src/schema/channel.schema.ts","../src/schema/credential.schema.ts","../src/schema/deployment.schema.ts","../src/schema/index.ts","../src/schema/pikku-schema.types.ts","../src/schema/scope.schema.ts","../src/schema/secret.schema.ts","../src/schema/session.schema.ts","../src/schema/virtual-user.schema.ts","../src/schema/webhook.schema.ts","../src/schema/workflow.schema.ts","../bin/pikku-kysely-pure.ts"],"version":"6.0.3"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@pikku/kysely",
|
|
3
|
-
"version": "0.13.
|
|
3
|
+
"version": "0.13.15",
|
|
4
4
|
"description": "Kysely-backed Pikku services — workflow state, secrets, sessions, scopes and audit",
|
|
5
5
|
"author": "yasser.fadl@gmail.com",
|
|
6
6
|
"license": "MIT",
|
|
@@ -21,7 +21,7 @@
|
|
|
21
21
|
"prepublishOnly": "yarn build"
|
|
22
22
|
},
|
|
23
23
|
"peerDependencies": {
|
|
24
|
-
"@pikku/core": "^0.12.
|
|
24
|
+
"@pikku/core": "^0.12.82"
|
|
25
25
|
},
|
|
26
26
|
"dependencies": {
|
|
27
27
|
"kysely": "^0.29.0"
|
package/src/index.ts
CHANGED
|
@@ -8,9 +8,7 @@ export { KyselyAIStorageService } from './kysely-ai-storage-service.js'
|
|
|
8
8
|
export { KyselyAgentRunService } from './kysely-ai-agent-run-service.js'
|
|
9
9
|
export { KyselyAIRunStateService } from './kysely-ai-run-state-service.js'
|
|
10
10
|
export { KyselySecretService } from './kysely-secret-service.js'
|
|
11
|
-
export type { KyselySecretServiceConfig } from './kysely-secret-service.js'
|
|
12
11
|
export { KyselyCredentialService } from './kysely-credential-service.js'
|
|
13
|
-
export type { KyselyCredentialServiceConfig } from './kysely-credential-service.js'
|
|
14
12
|
export { KyselySessionStore } from './kysely-session-store.js'
|
|
15
13
|
export { KyselyScopeService } from './kysely-scope-service.js'
|
|
16
14
|
export { KyselyWebhookService } from './kysely-webhook-service.js'
|
|
@@ -25,17 +23,9 @@ export {
|
|
|
25
23
|
SerializePlugin,
|
|
26
24
|
SqliteSerializePlugin,
|
|
27
25
|
BaseSerializePlugin,
|
|
28
|
-
defaultSerializer,
|
|
29
|
-
defaultDeserializer,
|
|
30
|
-
maybeJson,
|
|
31
|
-
skipTransform,
|
|
32
|
-
dateRegex,
|
|
33
26
|
type Serializer,
|
|
34
27
|
type Deserializer,
|
|
35
|
-
type SerializePluginOptions,
|
|
36
28
|
} from './serialize-plugin.js'
|
|
37
|
-
|
|
38
|
-
export { virtualUserSchema } from './schema/virtual-user.schema.js'
|
|
39
29
|
export {
|
|
40
30
|
auditSchema,
|
|
41
31
|
pikkuSchemas,
|
|
@@ -44,14 +34,9 @@ export {
|
|
|
44
34
|
ensurePikkuSchema,
|
|
45
35
|
type EnsureOutcome,
|
|
46
36
|
resolveRequirements,
|
|
47
|
-
unsatisfiedRequirements,
|
|
48
|
-
rawStatement,
|
|
49
|
-
requiredType,
|
|
50
37
|
type PikkuSchema,
|
|
51
38
|
type RequiredTypes,
|
|
52
|
-
type SchemaRequirement,
|
|
53
39
|
type UnmetRequirement,
|
|
54
|
-
type SchemaStatement,
|
|
55
40
|
type SchemaStatementFactory,
|
|
56
41
|
} from './schema/index.js'
|
|
57
42
|
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
import type { Kysely } from 'kysely'
|
|
2
|
+
import type { KyselyPikkuDB } from './kysely-tables.js'
|
|
3
|
+
import type { SaveScoreInput } from '@pikku/core/services'
|
|
4
|
+
import type { AIRunScore } from '@pikku/core/ai-scorer'
|
|
5
|
+
import { parseJson } from './kysely-json.js'
|
|
6
|
+
|
|
7
|
+
/**
|
|
8
|
+
* Shared by the two Kysely services that implement `AIRunStateService` — they
|
|
9
|
+
* differ in how they store approvals, not in how they store grades.
|
|
10
|
+
*/
|
|
11
|
+
export const saveRunScore = async (
|
|
12
|
+
db: Kysely<KyselyPikkuDB>,
|
|
13
|
+
score: SaveScoreInput
|
|
14
|
+
): Promise<void> => {
|
|
15
|
+
await db
|
|
16
|
+
.insertInto('aiRunScore')
|
|
17
|
+
.values({
|
|
18
|
+
id: crypto.randomUUID(),
|
|
19
|
+
runId: score.runId,
|
|
20
|
+
scorerName: score.scorerName,
|
|
21
|
+
score: score.score,
|
|
22
|
+
reason: score.reason ?? null,
|
|
23
|
+
metadata: score.metadata ? JSON.stringify(score.metadata) : null,
|
|
24
|
+
})
|
|
25
|
+
.execute()
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
export const getRunScores = async (
|
|
29
|
+
db: Kysely<KyselyPikkuDB>,
|
|
30
|
+
runId: string
|
|
31
|
+
): Promise<AIRunScore[]> => {
|
|
32
|
+
const rows = await db
|
|
33
|
+
.selectFrom('aiRunScore')
|
|
34
|
+
.selectAll()
|
|
35
|
+
.where('runId', '=', runId)
|
|
36
|
+
.orderBy('createdAt', 'asc')
|
|
37
|
+
.execute()
|
|
38
|
+
|
|
39
|
+
return rows.map((row) => ({
|
|
40
|
+
runId: row.runId,
|
|
41
|
+
scorerName: row.scorerName,
|
|
42
|
+
score: Number(row.score),
|
|
43
|
+
reason: row.reason ?? undefined,
|
|
44
|
+
metadata: parseJson(row.metadata),
|
|
45
|
+
createdAt: new Date(row.createdAt),
|
|
46
|
+
}))
|
|
47
|
+
}
|
|
@@ -1,10 +1,16 @@
|
|
|
1
1
|
import { sql } from 'kysely'
|
|
2
2
|
import type { Kysely } from 'kysely'
|
|
3
3
|
import type { KyselyPikkuDB } from './kysely-tables.js'
|
|
4
|
-
import type {
|
|
4
|
+
import type {
|
|
5
|
+
AIRunStateService,
|
|
6
|
+
CreateRunInput,
|
|
7
|
+
SaveScoreInput,
|
|
8
|
+
} from '@pikku/core/services'
|
|
5
9
|
import type { AgentRunState, PendingApproval } from '@pikku/core/ai-agent'
|
|
10
|
+
import type { AIRunScore } from '@pikku/core/ai-scorer'
|
|
6
11
|
import { ensurePikkuSchema } from './schema/index.js'
|
|
7
12
|
import { aiSchema } from './schema/ai.schema.js'
|
|
13
|
+
import { getRunScores, saveRunScore } from './kysely-ai-run-scores.js'
|
|
8
14
|
|
|
9
15
|
export class KyselyAIRunStateService implements AIRunStateService {
|
|
10
16
|
private initialized = false
|
|
@@ -160,6 +166,14 @@ export class KyselyAIRunStateService implements AIRunStateService {
|
|
|
160
166
|
return null
|
|
161
167
|
}
|
|
162
168
|
|
|
169
|
+
async saveScore(score: SaveScoreInput): Promise<void> {
|
|
170
|
+
await saveRunScore(this.db, score)
|
|
171
|
+
}
|
|
172
|
+
|
|
173
|
+
async getScores(runId: string): Promise<AIRunScore[]> {
|
|
174
|
+
return getRunScores(this.db, runId)
|
|
175
|
+
}
|
|
176
|
+
|
|
163
177
|
private toRunState(row: any): AgentRunState {
|
|
164
178
|
return {
|
|
165
179
|
runId: row.runId,
|
|
@@ -2,11 +2,14 @@ import type {
|
|
|
2
2
|
AIStorageService,
|
|
3
3
|
AIRunStateService,
|
|
4
4
|
CreateRunInput,
|
|
5
|
+
SaveScoreInput,
|
|
5
6
|
} from '@pikku/core/services'
|
|
6
7
|
import type { AIThread, AIMessage, AgentRunState } from '@pikku/core/ai-agent'
|
|
8
|
+
import type { AIRunScore } from '@pikku/core/ai-scorer'
|
|
7
9
|
import type { Kysely } from 'kysely'
|
|
8
10
|
import type { KyselyPikkuDB } from './kysely-tables.js'
|
|
9
11
|
import { parseJson } from './kysely-json.js'
|
|
12
|
+
import { getRunScores, saveRunScore } from './kysely-ai-run-scores.js'
|
|
10
13
|
import { ensurePikkuSchema } from './schema/index.js'
|
|
11
14
|
import { aiSchema } from './schema/ai.schema.js'
|
|
12
15
|
|
|
@@ -607,5 +610,13 @@ export class KyselyAIStorageService
|
|
|
607
610
|
return Number(result?.numUpdatedRows ?? 0) > 0
|
|
608
611
|
}
|
|
609
612
|
|
|
613
|
+
async saveScore(score: SaveScoreInput): Promise<void> {
|
|
614
|
+
await saveRunScore(this.db, score)
|
|
615
|
+
}
|
|
616
|
+
|
|
617
|
+
async getScores(runId: string): Promise<AIRunScore[]> {
|
|
618
|
+
return getRunScores(this.db, runId)
|
|
619
|
+
}
|
|
620
|
+
|
|
610
621
|
public async close(): Promise<void> {}
|
|
611
622
|
}
|
package/src/kysely-tables.ts
CHANGED
|
@@ -151,6 +151,18 @@ export interface AIRunTable {
|
|
|
151
151
|
updatedAt: Generated<Date>
|
|
152
152
|
}
|
|
153
153
|
|
|
154
|
+
export interface AIRunScoreTable {
|
|
155
|
+
id: string
|
|
156
|
+
runId: string
|
|
157
|
+
scorerName: string
|
|
158
|
+
/** 0..1, so grades are comparable across scorers. */
|
|
159
|
+
score: number
|
|
160
|
+
reason: string | null
|
|
161
|
+
/** JSON-serialized structured detail the scorer returned alongside the score. */
|
|
162
|
+
metadata: string | null
|
|
163
|
+
createdAt: Generated<Date>
|
|
164
|
+
}
|
|
165
|
+
|
|
154
166
|
export interface PikkuDeploymentsTable {
|
|
155
167
|
deploymentId: string
|
|
156
168
|
endpoint: string
|
|
@@ -329,6 +341,7 @@ export interface KyselyPikkuDB {
|
|
|
329
341
|
aiToolCall: AIToolCallTable
|
|
330
342
|
aiWorkingMemory: AIWorkingMemoryTable
|
|
331
343
|
aiRun: AIRunTable
|
|
344
|
+
aiRunScore: AIRunScoreTable
|
|
332
345
|
pikkuDeployments: PikkuDeploymentsTable
|
|
333
346
|
pikkuDeploymentFunctions: PikkuDeploymentFunctionsTable
|
|
334
347
|
secrets: SecretsTable
|
package/src/schema/ai.schema.ts
CHANGED
|
@@ -136,5 +136,26 @@ export const aiSchema: PikkuSchema = {
|
|
|
136
136
|
.createIndex('idx_ai_run_thread')
|
|
137
137
|
.on('aiRun')
|
|
138
138
|
.columns(['threadId', 'createdAt']),
|
|
139
|
+
|
|
140
|
+
(db) =>
|
|
141
|
+
db.schema
|
|
142
|
+
.createTable('aiRunScore')
|
|
143
|
+
.addColumn('id', 'varchar(36)', (col) => col.primaryKey())
|
|
144
|
+
.addColumn('runId', 'varchar(36)', (col) =>
|
|
145
|
+
col.notNull().references('aiRun.runId').onDelete('cascade')
|
|
146
|
+
)
|
|
147
|
+
.addColumn('scorerName', 'varchar(255)', (col) => col.notNull())
|
|
148
|
+
.addColumn('score', 'real', (col) => col.notNull())
|
|
149
|
+
.addColumn('reason', 'text')
|
|
150
|
+
.addColumn('metadata', 'text')
|
|
151
|
+
.addColumn('createdAt', 'timestamp', (col) =>
|
|
152
|
+
col.defaultTo(sql`CURRENT_TIMESTAMP`).notNull()
|
|
153
|
+
),
|
|
154
|
+
|
|
155
|
+
(db) =>
|
|
156
|
+
db.schema
|
|
157
|
+
.createIndex('idx_ai_run_score_run')
|
|
158
|
+
.on('aiRunScore')
|
|
159
|
+
.columns(['runId', 'createdAt']),
|
|
139
160
|
],
|
|
140
161
|
}
|