@pikku/skills 0.12.43 → 0.12.46
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/README.md +3 -2
- package/dist/skills.gen.js +2 -2
- package/package.json +1 -1
- package/skills/pikku-auth/references/better-auth.md +8 -7
- package/skills/pikku-blueprint-to-fabric/SKILL.md +72 -72
- package/skills/pikku-build/SKILL.md +3 -2
- package/skills/pikku-build/references/app.md +24 -13
- package/skills/pikku-build/references/multi-app.md +10 -5
- package/skills/pikku-build/references/native-app.md +148 -0
- package/skills/pikku-build/references/ship.md +18 -8
- package/skills/pikku-changes/SKILL.md +37 -15
- package/skills/pikku-concepts/references/bootstrap.md +2 -3
- package/skills/pikku-fabric/SKILL.md +111 -44
- package/skills/pikku-kysely/SKILL.md +29 -4
- package/skills/pikku-react/SKILL.md +1 -1
- package/skills/pikku-react/references/client.md +15 -22
- package/skills/pikku-scenario/references/personas.md +20 -52
- package/skills/pikku-service-backends/SKILL.md +1 -0
- package/skills/pikku-service-backends/references/mongodb.md +17 -2
- package/skills/pikku-service-backends/references/redis.md +50 -12
|
@@ -73,6 +73,7 @@ import {
|
|
|
73
73
|
MongoDBChannelStore,
|
|
74
74
|
MongoDBWorkflowService,
|
|
75
75
|
} from '@pikku/mongodb'
|
|
76
|
+
import { RedisLeaseService } from '@pikku/redis'
|
|
76
77
|
|
|
77
78
|
const createSingletonServices = pikkuServices(async (config) => {
|
|
78
79
|
const logger = new PinoLogger()
|
|
@@ -82,9 +83,23 @@ const createSingletonServices = pikkuServices(async (config) => {
|
|
|
82
83
|
const channelStore = new MongoDBChannelStore(mongo.db)
|
|
83
84
|
await channelStore.init()
|
|
84
85
|
|
|
85
|
-
const
|
|
86
|
+
const leaseService = new RedisLeaseService(config.redisUrl)
|
|
87
|
+
const workflowService = new MongoDBWorkflowService(mongo.db, {
|
|
88
|
+
leaseService,
|
|
89
|
+
})
|
|
86
90
|
await workflowService.init()
|
|
87
91
|
|
|
88
|
-
return {
|
|
92
|
+
return {
|
|
93
|
+
config,
|
|
94
|
+
logger,
|
|
95
|
+
database: mongo,
|
|
96
|
+
channelStore,
|
|
97
|
+
leaseService,
|
|
98
|
+
workflowService,
|
|
99
|
+
}
|
|
89
100
|
})
|
|
90
101
|
```
|
|
102
|
+
|
|
103
|
+
`MongoDBWorkflowService` requires a `leaseService` to lock runs and steps, and
|
|
104
|
+
`@pikku/mongodb` ships none — pair it with Redis, a Kysely lease service, or
|
|
105
|
+
`InMemoryLeaseService` for a single process.
|
|
@@ -9,16 +9,17 @@ Redis-backed implementations of Pikku's core service interfaces, using
|
|
|
9
9
|
connection — an ioredis `Redis` instance, `RedisOptions`, or a connection
|
|
10
10
|
string — in its constructor. None of them need an `init()` call.
|
|
11
11
|
|
|
12
|
-
| Service
|
|
13
|
-
|
|
|
14
|
-
| `RedisChannelStore`
|
|
15
|
-
| `RedisEventHubStore`
|
|
16
|
-
| `RedisWorkflowService`
|
|
17
|
-
| `RedisWorkflowRunService` | `WorkflowRunService`
|
|
18
|
-
| `RedisDeploymentService`
|
|
19
|
-
| `RedisAgentRunService`
|
|
20
|
-
| `RedisSecretService`
|
|
21
|
-
| `RedisSessionStore`
|
|
12
|
+
| Service | Interface | Purpose |
|
|
13
|
+
| ------------------------- | ---------------------- | ---------------------------------------------- |
|
|
14
|
+
| `RedisChannelStore` | `ChannelStore` | WebSocket channel state persistence |
|
|
15
|
+
| `RedisEventHubStore` | `EventHubStore` | Event hub state persistence |
|
|
16
|
+
| `RedisWorkflowService` | `PikkuWorkflowService` | Workflow definition storage |
|
|
17
|
+
| `RedisWorkflowRunService` | `WorkflowRunService` | Workflow execution tracking |
|
|
18
|
+
| `RedisDeploymentService` | `DeploymentService` | Deployment state management |
|
|
19
|
+
| `RedisAgentRunService` | `AgentRunService` | Agent execution tracking |
|
|
20
|
+
| `RedisSecretService` | `SecretService` | Encrypted secret storage (envelope encryption) |
|
|
21
|
+
| `RedisSessionStore` | `SessionStore` | Persisted user sessions |
|
|
22
|
+
| `RedisLeaseService` | `LeaseService` | Named leases with fencing tokens |
|
|
22
23
|
|
|
23
24
|
There is no Redis implementation of `AgentStorageService` — AI conversation
|
|
24
25
|
storage is MongoDB-only.
|
|
@@ -51,11 +52,38 @@ await secrets.rotateKEK(): Promise<number>
|
|
|
51
52
|
await secrets.close(): Promise<void>
|
|
52
53
|
```
|
|
53
54
|
|
|
55
|
+
## `RedisLeaseService`
|
|
56
|
+
|
|
57
|
+
Each lease is a hash Redis expires itself, and every check-and-set is one Lua
|
|
58
|
+
script that reads the time with `TIME`, so a lease is judged — and its
|
|
59
|
+
`expiresAt` reported — on Redis's clock, never the worker's. A fast worker
|
|
60
|
+
clock can neither take a live lease nor stretch its own.
|
|
61
|
+
|
|
62
|
+
The token comes from a counter stored beside the lease that release never
|
|
63
|
+
deletes, so the next holder always gets a higher token. That counter is one
|
|
64
|
+
small key per lease name, kept forever. On a replicated Redis with async
|
|
65
|
+
failover a promoted replica can miss the latest `INCR`, so a token is only as
|
|
66
|
+
durable as the write it rode on.
|
|
67
|
+
|
|
68
|
+
```typescript
|
|
69
|
+
import { RedisLeaseService } from '@pikku/redis'
|
|
70
|
+
import { holdLease } from '@pikku/core/services'
|
|
71
|
+
|
|
72
|
+
const leaseService = new RedisLeaseService(config.redisUrl, {
|
|
73
|
+
keyPrefix: 'pikku', // lease keys are `<prefix>:lease:{<key>}`
|
|
74
|
+
})
|
|
75
|
+
|
|
76
|
+
await holdLease(leaseService, 'nightly-report', async (lease, signal) => {
|
|
77
|
+
// ...
|
|
78
|
+
})
|
|
79
|
+
```
|
|
80
|
+
|
|
54
81
|
## Full setup
|
|
55
82
|
|
|
56
83
|
```typescript
|
|
57
84
|
import {
|
|
58
85
|
RedisChannelStore,
|
|
86
|
+
RedisLeaseService,
|
|
59
87
|
RedisWorkflowService,
|
|
60
88
|
RedisSecretService,
|
|
61
89
|
} from '@pikku/redis'
|
|
@@ -64,12 +92,22 @@ const createSingletonServices = pikkuServices(async (config) => {
|
|
|
64
92
|
const logger = new PinoLogger()
|
|
65
93
|
|
|
66
94
|
const channelStore = new RedisChannelStore(config.redisUrl)
|
|
67
|
-
const
|
|
95
|
+
const leaseService = new RedisLeaseService(config.redisUrl)
|
|
96
|
+
const workflowService = new RedisWorkflowService(config.redisUrl, {
|
|
97
|
+
leaseService,
|
|
98
|
+
})
|
|
68
99
|
|
|
69
100
|
const secrets = new RedisSecretService(config.redisUrl, {
|
|
70
101
|
key: config.kekPassphrase,
|
|
71
102
|
})
|
|
72
103
|
|
|
73
|
-
return {
|
|
104
|
+
return {
|
|
105
|
+
config,
|
|
106
|
+
logger,
|
|
107
|
+
channelStore,
|
|
108
|
+
leaseService,
|
|
109
|
+
workflowService,
|
|
110
|
+
secrets,
|
|
111
|
+
}
|
|
74
112
|
})
|
|
75
113
|
```
|