@pikku/kysely 0.13.19 → 0.13.21
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 +174 -0
- package/dist/src/index.d.ts +3 -2
- package/dist/src/index.js +2 -1
- package/dist/src/kysely-agent-run-state-service.js +2 -2
- package/dist/src/kysely-agent-storage-service.js +2 -2
- package/dist/src/kysely-audit-service.js +2 -2
- package/dist/src/kysely-channel-store.js +2 -2
- package/dist/src/kysely-credential-service.js +2 -2
- package/dist/src/kysely-deployment-service.js +2 -2
- package/dist/src/kysely-scope-service.js +2 -2
- package/dist/src/kysely-secret-service.js +2 -2
- package/dist/src/kysely-session-store.js +2 -2
- package/dist/src/kysely-tables.d.ts +74 -0
- package/dist/src/kysely-virtual-user-run-store.d.ts +7 -19
- package/dist/src/kysely-virtual-user-run-store.js +71 -4
- package/dist/src/kysely-virtual-user-schedule-store.d.ts +33 -0
- package/dist/src/kysely-virtual-user-schedule-store.js +151 -0
- package/dist/src/kysely-webhook-service.js +2 -2
- package/dist/src/kysely-workflow-mirror.d.ts +1 -1
- package/dist/src/kysely-workflow-mirror.js +3 -3
- package/dist/src/kysely-workflow-service.js +2 -2
- package/dist/src/schema/agent.schema.js +1 -0
- package/dist/src/schema/audit.schema.d.ts +5 -4
- package/dist/src/schema/audit.schema.js +6 -4
- package/dist/src/schema/channel.schema.js +1 -0
- package/dist/src/schema/credential.schema.js +1 -0
- package/dist/src/schema/index.d.ts +48 -26
- package/dist/src/schema/index.js +59 -46
- package/dist/src/schema/pikku-schema.types.d.ts +20 -0
- package/dist/src/schema/scope.schema.js +1 -0
- package/dist/src/schema/virtual-user-schedule.schema.d.ts +15 -0
- package/dist/src/schema/virtual-user-schedule.schema.js +43 -0
- package/dist/src/schema/virtual-user.schema.d.ts +2 -1
- package/dist/src/schema/virtual-user.schema.js +41 -2
- package/dist/src/schema/webhook.schema.js +1 -0
- package/dist/src/schema/workflow.schema.js +1 -0
- package/dist/tsconfig.tsbuildinfo +1 -1
- package/package.json +2 -2
- package/src/index.ts +15 -2
- package/src/kysely-agent-run-state-service.ts +2 -2
- package/src/kysely-agent-storage-service.ts +2 -2
- package/src/kysely-audit-service.test.ts +2 -10
- package/src/kysely-audit-service.ts +2 -2
- package/src/kysely-channel-store.ts +2 -2
- package/src/kysely-credential-service.ts +2 -2
- package/src/kysely-deployment-service.ts +2 -2
- package/src/kysely-scope-service.test.ts +2 -0
- package/src/kysely-scope-service.ts +2 -2
- package/src/kysely-secret-service.ts +2 -2
- package/src/kysely-services.test.ts +26 -0
- package/src/kysely-session-store.ts +2 -2
- package/src/kysely-tables.test.ts +1 -12
- package/src/kysely-tables.ts +77 -0
- package/src/kysely-virtual-user-run-store.test.ts +164 -7
- package/src/kysely-virtual-user-run-store.ts +92 -6
- package/src/kysely-virtual-user-schedule-store.test.ts +187 -0
- package/src/kysely-virtual-user-schedule-store.ts +187 -0
- package/src/kysely-webhook-service.test.ts +4 -0
- package/src/kysely-webhook-service.ts +2 -2
- package/src/kysely-workflow-mirror.test.ts +2 -0
- package/src/kysely-workflow-mirror.ts +3 -3
- package/src/kysely-workflow-service.test.ts +3 -1
- package/src/kysely-workflow-service.ts +2 -2
- package/src/schema/agent.schema.ts +1 -0
- package/src/schema/audit.schema.ts +6 -4
- package/src/schema/channel.schema.ts +1 -0
- package/src/schema/credential.schema.ts +1 -0
- package/src/schema/index.ts +70 -52
- package/src/schema/pikku-schema.types.ts +20 -0
- package/src/schema/schema.test.ts +86 -29
- package/src/schema/scope.schema.ts +1 -0
- package/src/schema/virtual-user-schedule.schema.ts +48 -0
- package/src/schema/virtual-user.schema.ts +43 -2
- package/src/schema/webhook.schema.ts +1 -0
- package/src/schema/workflow.schema.ts +1 -0
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import type { PikkuSchema } from './pikku-schema.types.js';
|
|
2
2
|
/**
|
|
3
|
-
* The `virtualUserRun`
|
|
3
|
+
* The `virtualUserRun` and `virtualUserRunStep` tables
|
|
4
|
+
* {@link KyselyVirtualUserRunStore} writes to.
|
|
4
5
|
*
|
|
5
6
|
* Deliberately not in `pikkuSchemas`: the runtime never needs this table, only
|
|
6
7
|
* a project that runs virtual users does, and creating it for everyone would
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { sql } from 'kysely';
|
|
2
2
|
/**
|
|
3
|
-
* The `virtualUserRun`
|
|
3
|
+
* The `virtualUserRun` and `virtualUserRunStep` tables
|
|
4
|
+
* {@link KyselyVirtualUserRunStore} writes to.
|
|
4
5
|
*
|
|
5
6
|
* Deliberately not in `pikkuSchemas`: the runtime never needs this table, only
|
|
6
7
|
* a project that runs virtual users does, and creating it for everyone would
|
|
@@ -17,7 +18,8 @@ import { sql } from 'kysely';
|
|
|
17
18
|
* week's does not depend on which database they were found in.
|
|
18
19
|
*/
|
|
19
20
|
export const virtualUserSchema = {
|
|
20
|
-
name: '
|
|
21
|
+
name: 'virtual-user',
|
|
22
|
+
ownedBy: ['virtualUserRunStore'],
|
|
21
23
|
statements: [
|
|
22
24
|
(db) => db.schema
|
|
23
25
|
.createTable('virtualUserRun')
|
|
@@ -32,6 +34,10 @@ export const virtualUserSchema = {
|
|
|
32
34
|
.addColumn('goals', 'text', (col) => col.defaultTo('[]').notNull())
|
|
33
35
|
.addColumn('memory', 'text', (col) => col.defaultTo('{}').notNull())
|
|
34
36
|
.addColumn('findings', 'text', (col) => col.defaultTo('[]').notNull())
|
|
37
|
+
// What the user set out to do and how far each one got. On the run row
|
|
38
|
+
// rather than beside the steps: there are a handful of them, and every
|
|
39
|
+
// read of the run wants them.
|
|
40
|
+
.addColumn('intents', 'text', (col) => col.defaultTo('[]').notNull())
|
|
35
41
|
// Counts the engine kept: steps, calls, mutations, tokens, elapsed.
|
|
36
42
|
.addColumn('tally', 'text')
|
|
37
43
|
.addColumn('stoppedBy', 'varchar(255)')
|
|
@@ -50,5 +56,38 @@ export const virtualUserSchema = {
|
|
|
50
56
|
.createIndex('idx_virtual_user_run_persona')
|
|
51
57
|
.on('virtualUserRun')
|
|
52
58
|
.columns(['persona', 'createdAt']),
|
|
59
|
+
// One row per turn, kept out of `virtualUserRun` so that listing runs does
|
|
60
|
+
// not drag a budget's worth of transcript along with it. No foreign key
|
|
61
|
+
// onto the run for the same reason `persona` is not one: this table is
|
|
62
|
+
// created by the store at boot on whatever engine the project uses, and a
|
|
63
|
+
// cascade that half the engines enforce differently is worse than the read
|
|
64
|
+
// rule that a step with no run is orphaned.
|
|
65
|
+
(db) => db.schema
|
|
66
|
+
.createTable('virtualUserRunStep')
|
|
67
|
+
.addColumn('runId', 'varchar(36)', (col) => col.notNull())
|
|
68
|
+
// The engine's own step number, which is what the intent records point
|
|
69
|
+
// at — not a surrogate key, so a transcript reads the same after paging.
|
|
70
|
+
// Spelled `stepIndex` because `index` is a reserved word in mysql.
|
|
71
|
+
.addColumn('stepIndex', 'integer', (col) => col.notNull())
|
|
72
|
+
.addColumn('intentId', 'varchar(255)')
|
|
73
|
+
// The action as the engine scheduled it, including the `invalid` shape
|
|
74
|
+
// for a turn the model got wrong — that turn is the interesting one.
|
|
75
|
+
.addColumn('action', 'text', (col) => col.notNull())
|
|
76
|
+
.addColumn('status', 'integer')
|
|
77
|
+
// 0 or 1 rather than a boolean, because a bare sqlite driver cannot
|
|
78
|
+
// bind one at all and `SerializePlugin` is not installed everywhere.
|
|
79
|
+
.addColumn('ok', 'integer')
|
|
80
|
+
// Already truncated by the engine, and stored JSON-encoded rather than
|
|
81
|
+
// raw: a truncated API response usually starts with a brace, which
|
|
82
|
+
// `SerializePlugin` would read back as an object rather than the string
|
|
83
|
+
// the engine actually saw.
|
|
84
|
+
.addColumn('response', 'text')
|
|
85
|
+
.addColumn('findingKinds', 'text')
|
|
86
|
+
.addColumn('tokensIn', 'integer', (col) => col.defaultTo(0).notNull())
|
|
87
|
+
.addColumn('tokensOut', 'integer', (col) => col.defaultTo(0).notNull())
|
|
88
|
+
.addPrimaryKeyConstraint('pk_virtual_user_run_step', [
|
|
89
|
+
'runId',
|
|
90
|
+
'stepIndex',
|
|
91
|
+
]),
|
|
53
92
|
],
|
|
54
93
|
};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"root":["../src/coercion-plugin.ts","../src/create-audited-kysely.ts","../src/index.ts","../src/kysely-agent-run-scores.ts","../src/kysely-agent-run-service.ts","../src/kysely-agent-run-state-service.ts","../src/kysely-agent-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/agent.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/coercion-plugin.ts","../src/create-audited-kysely.ts","../src/index.ts","../src/kysely-agent-run-scores.ts","../src/kysely-agent-run-service.ts","../src/kysely-agent-run-state-service.ts","../src/kysely-agent-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-virtual-user-schedule-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/agent.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-schedule.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.21",
|
|
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.90"
|
|
25
25
|
},
|
|
26
26
|
"dependencies": {
|
|
27
27
|
"kysely": "^0.29.5"
|
package/src/index.ts
CHANGED
|
@@ -18,6 +18,7 @@ export {
|
|
|
18
18
|
} from './create-audited-kysely.js'
|
|
19
19
|
export { KyselyAuditService } from './kysely-audit-service.js'
|
|
20
20
|
export { KyselyVirtualUserRunStore } from './kysely-virtual-user-run-store.js'
|
|
21
|
+
export { KyselyVirtualUserScheduleStore } from './kysely-virtual-user-schedule-store.js'
|
|
21
22
|
|
|
22
23
|
export {
|
|
23
24
|
SerializePlugin,
|
|
@@ -32,12 +33,22 @@ export {
|
|
|
32
33
|
type CreateCoercionPluginOptions,
|
|
33
34
|
} from './coercion-plugin.js'
|
|
34
35
|
export {
|
|
36
|
+
agentSchema,
|
|
35
37
|
auditSchema,
|
|
38
|
+
channelSchema,
|
|
39
|
+
credentialSchema,
|
|
40
|
+
deploymentSchema,
|
|
41
|
+
scopeSchema,
|
|
42
|
+
secretSchema,
|
|
43
|
+
sessionSchema,
|
|
44
|
+
virtualUserSchema,
|
|
45
|
+
webhookSchema,
|
|
46
|
+
workflowSchema,
|
|
36
47
|
pikkuSchemas,
|
|
48
|
+
requiredPikkuSchemas,
|
|
37
49
|
applyPikkuSchemas,
|
|
38
50
|
compilePikkuSchemas,
|
|
39
|
-
|
|
40
|
-
type EnsureOutcome,
|
|
51
|
+
requirePikkuSchema,
|
|
41
52
|
resolveRequirements,
|
|
42
53
|
type PikkuSchema,
|
|
43
54
|
type RequiredTypes,
|
|
@@ -51,4 +62,6 @@ export type { AgentRunService, AgentRunRow } from '@pikku/core/agent'
|
|
|
51
62
|
export type {
|
|
52
63
|
VirtualUserRunStore,
|
|
53
64
|
VirtualUserRunRecord,
|
|
65
|
+
VirtualUserScheduleStore,
|
|
66
|
+
VirtualUserScheduleRecord,
|
|
54
67
|
} from '@pikku/core/virtual-user'
|
|
@@ -9,7 +9,7 @@ import type {
|
|
|
9
9
|
SaveScoreInput,
|
|
10
10
|
} from '@pikku/core/services'
|
|
11
11
|
import type { PendingApproval } from '@pikku/core/agent'
|
|
12
|
-
import {
|
|
12
|
+
import { requirePikkuSchema } from './schema/index.js'
|
|
13
13
|
import { agentSchema } from './schema/agent.schema.js'
|
|
14
14
|
import { getRunScores, saveRunScore } from './kysely-agent-run-scores.js'
|
|
15
15
|
|
|
@@ -20,7 +20,7 @@ export class KyselyAgentRunStateService implements AgentRunStateService {
|
|
|
20
20
|
|
|
21
21
|
async init(): Promise<void> {
|
|
22
22
|
if (this.initialized) return
|
|
23
|
-
await
|
|
23
|
+
await requirePikkuSchema(this.db, agentSchema)
|
|
24
24
|
this.initialized = true
|
|
25
25
|
}
|
|
26
26
|
|
|
@@ -14,7 +14,7 @@ import type { Kysely } from 'kysely'
|
|
|
14
14
|
import type { KyselyPikkuDB } from './kysely-tables.js'
|
|
15
15
|
import { parseJson } from './kysely-json.js'
|
|
16
16
|
import { getRunScores, saveRunScore } from './kysely-agent-run-scores.js'
|
|
17
|
-
import {
|
|
17
|
+
import { requirePikkuSchema } from './schema/index.js'
|
|
18
18
|
import { agentSchema } from './schema/agent.schema.js'
|
|
19
19
|
|
|
20
20
|
export class KyselyAgentStorageService
|
|
@@ -26,7 +26,7 @@ export class KyselyAgentStorageService
|
|
|
26
26
|
|
|
27
27
|
public async init(): Promise<void> {
|
|
28
28
|
if (this.initialized) return
|
|
29
|
-
await
|
|
29
|
+
await requirePikkuSchema(this.db, agentSchema)
|
|
30
30
|
this.initialized = true
|
|
31
31
|
}
|
|
32
32
|
|
|
@@ -309,21 +309,13 @@ describe('KyselyAuditService against a CamelCasePlugin connection', () => {
|
|
|
309
309
|
})
|
|
310
310
|
|
|
311
311
|
describe('KyselyAuditService.init', () => {
|
|
312
|
-
test('
|
|
312
|
+
test('refuses to boot against a database that has none', async () => {
|
|
313
313
|
const fresh = new Kysely<any>({
|
|
314
314
|
dialect: new SqliteDialect({ database: new Database(':memory:') }),
|
|
315
315
|
plugins: [new CamelCasePlugin()],
|
|
316
316
|
})
|
|
317
317
|
const freshService = new KyselyAuditService(fresh)
|
|
318
|
-
await freshService.init()
|
|
319
|
-
await freshService.write([
|
|
320
|
-
event({ eventId: 'e1', type: 't', occurredAt: '2026-01-01' }),
|
|
321
|
-
])
|
|
322
|
-
const { events } = await freshService.query()
|
|
323
|
-
assert.deepEqual(
|
|
324
|
-
events.map((e) => e.eventId),
|
|
325
|
-
['e1']
|
|
326
|
-
)
|
|
318
|
+
await assert.rejects(freshService.init(), /pikku db generate/)
|
|
327
319
|
})
|
|
328
320
|
|
|
329
321
|
// Two boots against one database, and the second must not wipe the first.
|
|
@@ -6,7 +6,7 @@ import type {
|
|
|
6
6
|
AuditQueryResult,
|
|
7
7
|
} from '@pikku/core/services'
|
|
8
8
|
import type { Kysely } from 'kysely'
|
|
9
|
-
import {
|
|
9
|
+
import { requirePikkuSchema } from './schema/index.js'
|
|
10
10
|
import { auditSchema } from './schema/audit.schema.js'
|
|
11
11
|
|
|
12
12
|
const jsonOrNull = (v: unknown): string | null =>
|
|
@@ -103,7 +103,7 @@ export class KyselyAuditService implements AuditService {
|
|
|
103
103
|
*/
|
|
104
104
|
public async init(): Promise<void> {
|
|
105
105
|
if (this.initialized) return
|
|
106
|
-
await
|
|
106
|
+
await requirePikkuSchema(this.db, auditSchema)
|
|
107
107
|
this.initialized = true
|
|
108
108
|
}
|
|
109
109
|
|
|
@@ -3,7 +3,7 @@ import type { Channel } from '@pikku/core/channel'
|
|
|
3
3
|
import type { Kysely } from 'kysely'
|
|
4
4
|
import type { KyselyPikkuDB } from './kysely-tables.js'
|
|
5
5
|
import { parseJson } from './kysely-json.js'
|
|
6
|
-
import {
|
|
6
|
+
import { requirePikkuSchema } from './schema/index.js'
|
|
7
7
|
import { channelSchema } from './schema/channel.schema.js'
|
|
8
8
|
|
|
9
9
|
export class KyselyChannelStore extends ChannelStore {
|
|
@@ -15,7 +15,7 @@ export class KyselyChannelStore extends ChannelStore {
|
|
|
15
15
|
|
|
16
16
|
public async init(): Promise<void> {
|
|
17
17
|
if (this.initialized) return
|
|
18
|
-
await
|
|
18
|
+
await requirePikkuSchema(this.db, channelSchema)
|
|
19
19
|
this.initialized = true
|
|
20
20
|
}
|
|
21
21
|
|
|
@@ -8,7 +8,7 @@ import {
|
|
|
8
8
|
import type { CredentialService } from '@pikku/core/services'
|
|
9
9
|
import type { Kysely } from 'kysely'
|
|
10
10
|
import type { KyselyPikkuDB } from './kysely-tables.js'
|
|
11
|
-
import {
|
|
11
|
+
import { requirePikkuSchema } from './schema/index.js'
|
|
12
12
|
import { credentialSchema } from './schema/credential.schema.js'
|
|
13
13
|
|
|
14
14
|
export interface KyselyCredentialServiceConfig {
|
|
@@ -42,7 +42,7 @@ export class KyselyCredentialService implements CredentialService {
|
|
|
42
42
|
|
|
43
43
|
public async init(): Promise<void> {
|
|
44
44
|
if (this.initialized) return
|
|
45
|
-
await
|
|
45
|
+
await requirePikkuSchema(this.db, credentialSchema)
|
|
46
46
|
this.initialized = true
|
|
47
47
|
}
|
|
48
48
|
|
|
@@ -9,7 +9,7 @@ import type { SecretService } from '@pikku/core/services'
|
|
|
9
9
|
import { getAllFunctionNames } from '@pikku/core/function'
|
|
10
10
|
import type { Kysely } from 'kysely'
|
|
11
11
|
import type { KyselyPikkuDB } from './kysely-tables.js'
|
|
12
|
-
import {
|
|
12
|
+
import { requirePikkuSchema } from './schema/index.js'
|
|
13
13
|
import { deploymentSchema } from './schema/deployment.schema.js'
|
|
14
14
|
|
|
15
15
|
export class KyselyDeploymentService implements DeploymentService {
|
|
@@ -31,7 +31,7 @@ export class KyselyDeploymentService implements DeploymentService {
|
|
|
31
31
|
|
|
32
32
|
public async init(): Promise<void> {
|
|
33
33
|
if (this.initialized) return
|
|
34
|
-
await
|
|
34
|
+
await requirePikkuSchema(this.db, deploymentSchema)
|
|
35
35
|
this.initialized = true
|
|
36
36
|
}
|
|
37
37
|
|
|
@@ -5,6 +5,7 @@ import Database from 'better-sqlite3'
|
|
|
5
5
|
import { SerializePlugin } from './serialize-plugin.js'
|
|
6
6
|
import type { KyselyPikkuDB } from './kysely-tables.js'
|
|
7
7
|
import { KyselyScopeService } from './kysely-scope-service.js'
|
|
8
|
+
import { applyPikkuSchemas, scopeSchema } from './schema/index.js'
|
|
8
9
|
|
|
9
10
|
const SCOPES = [
|
|
10
11
|
{ id: 'admin' },
|
|
@@ -41,6 +42,7 @@ beforeEach(async () => {
|
|
|
41
42
|
plugins: [new CamelCasePlugin(), new SerializePlugin()],
|
|
42
43
|
})
|
|
43
44
|
await createUserTable(db)
|
|
45
|
+
await applyPikkuSchemas(db, [scopeSchema])
|
|
44
46
|
service = new KyselyScopeService(db)
|
|
45
47
|
await service.init()
|
|
46
48
|
await service.syncScopes(SCOPES)
|
|
@@ -8,7 +8,7 @@ import {
|
|
|
8
8
|
} from '@pikku/core/errors'
|
|
9
9
|
import type { Kysely } from 'kysely'
|
|
10
10
|
import type { KyselyPikkuDB } from './kysely-tables.js'
|
|
11
|
-
import {
|
|
11
|
+
import { requirePikkuSchema } from './schema/index.js'
|
|
12
12
|
import { scopeSchema } from './schema/scope.schema.js'
|
|
13
13
|
|
|
14
14
|
/**
|
|
@@ -30,7 +30,7 @@ export class KyselyScopeService implements ScopeService {
|
|
|
30
30
|
|
|
31
31
|
public async init(): Promise<void> {
|
|
32
32
|
if (this.initialized) return
|
|
33
|
-
await
|
|
33
|
+
await requirePikkuSchema(this.db, scopeSchema)
|
|
34
34
|
this.initialized = true
|
|
35
35
|
}
|
|
36
36
|
|
|
@@ -10,7 +10,7 @@ import type { SecretService, SecretValues } from '@pikku/core/services'
|
|
|
10
10
|
import type { SecretValue } from '@pikku/core/classification'
|
|
11
11
|
import type { Kysely } from 'kysely'
|
|
12
12
|
import type { KyselyPikkuDB } from './kysely-tables.js'
|
|
13
|
-
import {
|
|
13
|
+
import { requirePikkuSchema } from './schema/index.js'
|
|
14
14
|
import { secretSchema } from './schema/secret.schema.js'
|
|
15
15
|
|
|
16
16
|
export interface KyselySecretServiceConfig {
|
|
@@ -44,7 +44,7 @@ export class KyselySecretService implements SecretService {
|
|
|
44
44
|
|
|
45
45
|
public async init(): Promise<void> {
|
|
46
46
|
if (this.initialized) return
|
|
47
|
-
await
|
|
47
|
+
await requirePikkuSchema(this.db, secretSchema)
|
|
48
48
|
this.initialized = true
|
|
49
49
|
}
|
|
50
50
|
|
|
@@ -18,6 +18,30 @@ import { KyselyAgentRunService } from './kysely-agent-run-service.js'
|
|
|
18
18
|
import { KyselySecretService } from './kysely-secret-service.js'
|
|
19
19
|
import { KyselyCredentialService } from './kysely-credential-service.js'
|
|
20
20
|
import { KyselySessionStore } from './kysely-session-store.js'
|
|
21
|
+
import {
|
|
22
|
+
agentSchema,
|
|
23
|
+
applyPikkuSchemas,
|
|
24
|
+
channelSchema,
|
|
25
|
+
credentialSchema,
|
|
26
|
+
deploymentSchema,
|
|
27
|
+
secretSchema,
|
|
28
|
+
sessionSchema,
|
|
29
|
+
workflowSchema,
|
|
30
|
+
} from './schema/index.js'
|
|
31
|
+
|
|
32
|
+
/**
|
|
33
|
+
* Every schema the services under test boot against. They no longer create
|
|
34
|
+
* their own tables, so the harness stands in for `pikku db migrate`.
|
|
35
|
+
*/
|
|
36
|
+
const SERVICE_SCHEMAS = [
|
|
37
|
+
channelSchema,
|
|
38
|
+
workflowSchema,
|
|
39
|
+
deploymentSchema,
|
|
40
|
+
agentSchema,
|
|
41
|
+
secretSchema,
|
|
42
|
+
credentialSchema,
|
|
43
|
+
sessionSchema,
|
|
44
|
+
]
|
|
21
45
|
|
|
22
46
|
function createSqliteDb(): Kysely<KyselyPikkuDB> {
|
|
23
47
|
return new Kysely<KyselyPikkuDB>({
|
|
@@ -345,6 +369,7 @@ describe('Kysely Services - SQLite', () => {
|
|
|
345
369
|
|
|
346
370
|
before(async () => {
|
|
347
371
|
db = createSqliteDb()
|
|
372
|
+
await applyPikkuSchemas(db, SERVICE_SCHEMAS)
|
|
348
373
|
})
|
|
349
374
|
|
|
350
375
|
after(async () => {
|
|
@@ -365,6 +390,7 @@ describe(
|
|
|
365
390
|
before(async () => {
|
|
366
391
|
db = createPostgresDb()!
|
|
367
392
|
await dropAllTables(db)
|
|
393
|
+
await applyPikkuSchemas(db, SERVICE_SCHEMAS)
|
|
368
394
|
})
|
|
369
395
|
|
|
370
396
|
after(async () => {
|
|
@@ -3,7 +3,7 @@ import type { CoreUserSession } from '@pikku/core/types'
|
|
|
3
3
|
import type { Kysely } from 'kysely'
|
|
4
4
|
import type { KyselyPikkuDB } from './kysely-tables.js'
|
|
5
5
|
import { parseJson } from './kysely-json.js'
|
|
6
|
-
import {
|
|
6
|
+
import { requirePikkuSchema } from './schema/index.js'
|
|
7
7
|
import { sessionSchema } from './schema/session.schema.js'
|
|
8
8
|
|
|
9
9
|
export class KyselySessionStore implements SessionStore {
|
|
@@ -13,7 +13,7 @@ export class KyselySessionStore implements SessionStore {
|
|
|
13
13
|
|
|
14
14
|
public async init(): Promise<void> {
|
|
15
15
|
if (this.initialized) return
|
|
16
|
-
await
|
|
16
|
+
await requirePikkuSchema(this.db, sessionSchema)
|
|
17
17
|
this.initialized = true
|
|
18
18
|
}
|
|
19
19
|
|
|
@@ -5,15 +5,7 @@ import { join } from 'node:path'
|
|
|
5
5
|
import { Kysely, SqliteDialect } from 'kysely'
|
|
6
6
|
import Database from 'better-sqlite3'
|
|
7
7
|
|
|
8
|
-
import { applyPikkuSchemas
|
|
9
|
-
import { virtualUserSchema } from './schema/virtual-user.schema.js'
|
|
10
|
-
|
|
11
|
-
/**
|
|
12
|
-
* Opt-in schemas that still have an interface in `KyselyPikkuDB`, so the drift
|
|
13
|
-
* check covers them too. A table being opt-in says when it is created, not
|
|
14
|
-
* whether its type is allowed to disagree with its DDL.
|
|
15
|
-
*/
|
|
16
|
-
const OPTIONAL_SCHEMAS = [virtualUserSchema]
|
|
8
|
+
import { applyPikkuSchemas } from './schema/index.js'
|
|
17
9
|
|
|
18
10
|
/**
|
|
19
11
|
* `KyselyPikkuDB` and the schema declaration describe the same tables, and
|
|
@@ -73,9 +65,6 @@ const declaredSchema = async (): Promise<Map<string, Set<string>>> => {
|
|
|
73
65
|
.addColumn('id', 'text', (col) => col.primaryKey())
|
|
74
66
|
.execute()
|
|
75
67
|
await applyPikkuSchemas(db)
|
|
76
|
-
for (const schema of OPTIONAL_SCHEMAS) {
|
|
77
|
-
await ensurePikkuSchema(db, schema)
|
|
78
|
-
}
|
|
79
68
|
|
|
80
69
|
const tables = await db.introspection.getTables()
|
|
81
70
|
return new Map(
|
package/src/kysely-tables.ts
CHANGED
|
@@ -311,6 +311,7 @@ export interface VirtualUserRunTable {
|
|
|
311
311
|
goals: Generated<string>
|
|
312
312
|
memory: Generated<string>
|
|
313
313
|
findings: Generated<string>
|
|
314
|
+
intents: Generated<string>
|
|
314
315
|
tally: string | null
|
|
315
316
|
stoppedBy: string | null
|
|
316
317
|
error: string | null
|
|
@@ -324,6 +325,79 @@ export interface VirtualUserRunTable {
|
|
|
324
325
|
finishedAt: Date | string | null
|
|
325
326
|
}
|
|
326
327
|
|
|
328
|
+
/**
|
|
329
|
+
* One audit event. Every column is text on every engine so a locally-run
|
|
330
|
+
* project and a deployed stage write rows the same reader can read; the JSON
|
|
331
|
+
* columns (`tables`, `changedCols`, `event`, `old`, `data`) are serialised by
|
|
332
|
+
* {@link KyselyAuditService} rather than by a plugin.
|
|
333
|
+
*/
|
|
334
|
+
export interface AuditTable {
|
|
335
|
+
auditId: string
|
|
336
|
+
/** ISO 8601, because string ordering is chronological ordering. */
|
|
337
|
+
occurredAt: string
|
|
338
|
+
type: string
|
|
339
|
+
source: Generated<string>
|
|
340
|
+
outcome: string | null
|
|
341
|
+
functionId: string | null
|
|
342
|
+
wireType: string | null
|
|
343
|
+
traceId: string | null
|
|
344
|
+
transactionId: string | null
|
|
345
|
+
queryId: string | null
|
|
346
|
+
userId: string | null
|
|
347
|
+
orgId: string | null
|
|
348
|
+
pikkuUserId: string | null
|
|
349
|
+
tables: string | null
|
|
350
|
+
changedCols: string | null
|
|
351
|
+
event: string | null
|
|
352
|
+
old: string | null
|
|
353
|
+
data: string | null
|
|
354
|
+
}
|
|
355
|
+
|
|
356
|
+
/**
|
|
357
|
+
* One turn of a run's transcript.
|
|
358
|
+
*
|
|
359
|
+
* Its own table rather than a column on {@link VirtualUserRunTable}: a run at a
|
|
360
|
+
* 500-step budget carries more transcript than every other column together, and
|
|
361
|
+
* the run list would pay for it on every row.
|
|
362
|
+
*/
|
|
363
|
+
export interface VirtualUserRunStepTable {
|
|
364
|
+
runId: string
|
|
365
|
+
/** The engine's step number. `stepIndex` because `index` is reserved in mysql. */
|
|
366
|
+
stepIndex: number
|
|
367
|
+
intentId: string | null
|
|
368
|
+
/** JSON: the action the engine scheduled, or the `invalid` shape. */
|
|
369
|
+
action: string
|
|
370
|
+
status: number | null
|
|
371
|
+
/** 0 or 1: not every driver in this package can bind a boolean. */
|
|
372
|
+
ok: number | null
|
|
373
|
+
/** JSON-encoded, so a brace-leading response is not read back as an object. */
|
|
374
|
+
response: string | null
|
|
375
|
+
/** JSON array, null when the turn produced no finding. */
|
|
376
|
+
findingKinds: string | null
|
|
377
|
+
tokensIn: Generated<number>
|
|
378
|
+
tokensOut: Generated<number>
|
|
379
|
+
}
|
|
380
|
+
|
|
381
|
+
/**
|
|
382
|
+
* One persona's cadence. Nullable timestamps and 0/1 flags for the same driver
|
|
383
|
+
* reasons as {@link VirtualUserRunTable}.
|
|
384
|
+
*/
|
|
385
|
+
export interface VirtualUserScheduleTable {
|
|
386
|
+
persona: string
|
|
387
|
+
/** 0 or 1: not every driver in this package can bind a boolean. */
|
|
388
|
+
enabled: Generated<number>
|
|
389
|
+
disposition: string
|
|
390
|
+
goals: Generated<string>
|
|
391
|
+
/** JSON, or null for the engine's own default budget. */
|
|
392
|
+
budget: string | null
|
|
393
|
+
/** BIGINT, so a driver may hand either back. */
|
|
394
|
+
minIntervalMs: string | number | bigint
|
|
395
|
+
maxIntervalMs: string | number | bigint
|
|
396
|
+
nextRunAt: Date | string
|
|
397
|
+
lastRunId: string | null
|
|
398
|
+
lastRunAt: Date | string | null
|
|
399
|
+
}
|
|
400
|
+
|
|
327
401
|
export interface KyselyPikkuDB {
|
|
328
402
|
pikkuScopes: PikkuScopesTable
|
|
329
403
|
pikkuRoles: PikkuRolesTable
|
|
@@ -354,4 +428,7 @@ export interface KyselyPikkuDB {
|
|
|
354
428
|
webhookDelivery: WebhookDeliveryTable
|
|
355
429
|
webhookDeliveryAttempt: WebhookDeliveryAttemptTable
|
|
356
430
|
virtualUserRun: VirtualUserRunTable
|
|
431
|
+
virtualUserRunStep: VirtualUserRunStepTable
|
|
432
|
+
virtualUserSchedule: VirtualUserScheduleTable
|
|
433
|
+
audit: AuditTable
|
|
357
434
|
}
|