@pikku/skills 0.12.9 → 0.12.10

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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@pikku/skills",
3
- "version": "0.12.9",
3
+ "version": "0.12.10",
4
4
  "description": "The Pikku agent skills — the instruction set coding agents read to build, wire and deploy Pikku projects",
5
5
  "author": "yasser.fadl@gmail.com",
6
6
  "license": "MIT",
@@ -320,10 +320,10 @@ wireHTTPRoutes({ basePath: '/api', routes: { todos: todoRoutes } })
320
320
  ### Use in AI Agents
321
321
 
322
322
  ```typescript
323
- import { pikkuAIAgent } from '#pikku/agent/pikku-agent-types.gen.js'
323
+ import { pikkuAgent } from '#pikku/agent/pikku-agent-types.gen.js'
324
324
  import { ref } from '#pikku'
325
325
 
326
- export const todoAgent = pikkuAIAgent({
326
+ export const todoAgent = pikkuAgent({
327
327
  name: 'todo-agent',
328
328
  description: 'Manages a todo list',
329
329
  goal: 'You help users manage their todos.',
@@ -337,4 +337,4 @@ export const todoAgent = pikkuAIAgent({
337
337
  })
338
338
  ```
339
339
 
340
- See `pikku-ai-agent` — an addon function is just another `ref()` in `tools`.
340
+ See `pikku-agent` — an addon function is just another `ref()` in `tools`.
@@ -1,10 +1,10 @@
1
1
  ---
2
- name: pikku-ai-agent
2
+ name: pikku-agent
3
3
  description: >-
4
4
  Use when building AI agents, chatbots, or LLM-powered assistants with Pikku. Covers
5
- pikkuAIAgent, ref() tool registration, memory, streaming, tool approval, thread ownership, and
6
- invocation via rpc.agent. TRIGGER when: code uses pikkuAIAgent/rpc.agent/runAIAgent/
7
- streamAIAgent, user asks about AI agents, chatbots, LLM assistants, tool-calling agents, agent
5
+ pikkuAgent, ref() tool registration, memory, streaming, tool approval, thread ownership, and
6
+ invocation via rpc.agent. TRIGGER when: code uses pikkuAgent/rpc.agent/runAgent/
7
+ streamAgent, user asks about AI agents, chatbots, LLM assistants, tool-calling agents, agent
8
8
  memory/streaming, or `pikku enable agent`. DO NOT TRIGGER when: user asks about MCP tool
9
9
  exposure (use pikku-mcp) or general function definitions (use pikku-concepts).
10
10
  installGroups: [core]
@@ -35,15 +35,15 @@ See `pikku-concepts` for the core mental model.
35
35
 
36
36
  ## API Reference
37
37
 
38
- ### `pikkuAIAgent(config)`
38
+ ### `pikkuAgent(config)`
39
39
 
40
40
  Import it from the generated agent types file — `#pikku` does not re-export it:
41
41
 
42
42
  ```typescript
43
- import { pikkuAIAgent } from '#pikku/agent/pikku-agent-types.gen.js'
43
+ import { pikkuAgent } from '#pikku/agent/pikku-agent-types.gen.js'
44
44
  import { ref } from '#pikku/pikku-types.gen.js'
45
45
 
46
- pikkuAIAgent({
46
+ pikkuAgent({
47
47
  name: string, // Unique agent identifier
48
48
  description: string, // What the agent does (shown in agent listings)
49
49
  summary?: string,
@@ -67,7 +67,7 @@ pikkuAIAgent({
67
67
  agentMode?: 'delegate' | 'supervise',
68
68
 
69
69
  memory?: {
70
- storage?: string, // Service name for persistence (e.g. 'aiStorage')
70
+ storage?: string, // Service name for persistence (e.g. 'agentStorage')
71
71
  vector?: string, // Vector store service name
72
72
  embedder?: string, // Embedding service name
73
73
  lastMessages?: number, // How many messages to retain in context
@@ -88,7 +88,7 @@ pikkuAIAgent({
88
88
 
89
89
  middleware?: PikkuMiddleware[],
90
90
  channelMiddleware?: PikkuChannelMiddleware[],
91
- aiMiddleware?: PikkuAIMiddlewareHooks[],
91
+ agentMiddleware?: PikkuAgentMiddlewareHooks[],
92
92
  })
93
93
  ```
94
94
 
@@ -140,15 +140,15 @@ asking the user for identifiers it could have been handed.
140
140
  }
141
141
  ```
142
142
 
143
- `runAIAgent` / `streamAIAgent` from `@pikku/core/ai-agent` are the layer beneath
144
- this. Their third argument is `RunAIAgentParams` (`{ sessionService?,
143
+ `runAgent` / `streamAgent` from `@pikku/core/agent` are the layer beneath
144
+ this. Their third argument is `RunAgentParams` (`{ sessionService?,
145
145
  getCredential?, anonymousOwnerResourceId? }`) — **not** `{ singletonServices }`.
146
146
  Reach for them only outside a wired function; inside one, `rpc.agent` is the
147
147
  supported path.
148
148
 
149
149
  ### Stream events
150
150
 
151
- `rpc.agent.stream` pushes `AIStreamEvent`s onto the channel:
151
+ `rpc.agent.stream` pushes `AgentStreamEvent`s onto the channel:
152
152
 
153
153
  ```typescript
154
154
  // { type: 'step-start', stepNumber }
@@ -178,10 +178,10 @@ than folding it into the parent's transcript.
178
178
  ### Define an Agent
179
179
 
180
180
  ```typescript
181
- import { pikkuAIAgent } from '#pikku/agent/pikku-agent-types.gen.js'
181
+ import { pikkuAgent } from '#pikku/agent/pikku-agent-types.gen.js'
182
182
  import { ref } from '#pikku/pikku-types.gen.js'
183
183
 
184
- export const todoAgent = pikkuAIAgent({
184
+ export const todoAgent = pikkuAgent({
185
185
  name: 'todo-agent',
186
186
  description: 'Manages a todo list',
187
187
  goal: 'You help users manage their todos. You can list, add, complete and delete them.',
@@ -192,7 +192,7 @@ export const todoAgent = pikkuAIAgent({
192
192
  ref('todos:completeTodo'),
193
193
  ref('graph:sleep'),
194
194
  ],
195
- memory: { storage: 'aiStorage', lastMessages: 20 },
195
+ memory: { storage: 'agentStorage', lastMessages: 20 },
196
196
  maxSteps: 10,
197
197
  toolChoice: 'auto',
198
198
  })
@@ -216,7 +216,7 @@ tools** — with a tool present the runner falls back to free text, silently. If
216
216
  you need both, split the classification into its own tool-free agent.
217
217
 
218
218
  ```typescript
219
- export const structuredAgent = pikkuAIAgent({
219
+ export const structuredAgent = pikkuAgent({
220
220
  name: 'structured-agent',
221
221
  description: 'Classifies a message and returns a structured verdict',
222
222
  goal: 'You classify the sentiment of the user message.',
@@ -234,14 +234,14 @@ rather than signalling that it was short-circuited.
234
234
 
235
235
  ```typescript
236
236
  prepareStep: ({ stepNumber, tools }) => {
237
- if (stepNumber >= 1) tools.length = 0 // withdraw tools after the first step
237
+ if (stepNumber >= 1) tools.length = 0 // withdraw tools after the first step
238
238
  }
239
239
  ```
240
240
 
241
241
  ### Tool approval
242
242
 
243
243
  A tool that should pause for a human sets `approvalRequired: true` (with an
244
- optional `approvalDescription`) on the *function*, not on the agent. The run then
244
+ optional `approvalDescription`) on the _function_, not on the agent. The run then
245
245
  resolves with `status: 'suspended'` and `pendingApprovals`, and streaming emits
246
246
  `approval-request`. Answer with `rpc.agent.approve(runId, approvals)`.
247
247
 
@@ -282,10 +282,10 @@ export const completeTodo = pikkuFunc({
282
282
  })
283
283
 
284
284
  // agents/todo-assistant.agent.ts
285
- import { pikkuAIAgent } from '#pikku/agent/pikku-agent-types.gen.js'
285
+ import { pikkuAgent } from '#pikku/agent/pikku-agent-types.gen.js'
286
286
  import { ref } from '#pikku/pikku-types.gen.js'
287
287
 
288
- export const todoAssistant = pikkuAIAgent({
288
+ export const todoAssistant = pikkuAgent({
289
289
  name: 'todo-assistant',
290
290
  description: 'A helpful assistant that manages todos',
291
291
  role: 'You are an assistant that manages a user’s todo list.',
@@ -299,7 +299,7 @@ export const todoAssistant = pikkuAIAgent({
299
299
  ref('todos:createTodo'),
300
300
  ref('todos:completeTodo'),
301
301
  ],
302
- memory: { storage: 'aiStorage', lastMessages: 20 },
302
+ memory: { storage: 'agentStorage', lastMessages: 20 },
303
303
  maxSteps: 5,
304
304
  temperature: 0.7,
305
305
  })
@@ -2,9 +2,9 @@
2
2
  name: pikku-ai-vercel
3
3
  description: >-
4
4
  Use when setting up AI agent execution with the Vercel AI SDK in a Pikku app. Covers
5
- VercelAIAgentRunner for streaming and non-streaming AI agent steps. TRIGGER when: code uses
6
- VercelAIAgentRunner, user asks about Vercel AI SDK integration, AI agent runners, or
7
- @pikku/ai-vercel. DO NOT TRIGGER when: user asks about AI agent wiring (use pikku-ai-agent) or
5
+ VercelAgentRunner for streaming and non-streaming AI agent steps. TRIGGER when: code uses
6
+ VercelAgentRunner, user asks about Vercel AI SDK integration, AI agent runners, or
7
+ @pikku/ai-vercel. DO NOT TRIGGER when: user asks about AI agent wiring (use pikku-agent) or
8
8
  voice I/O (use pikku-ai-voice).
9
9
  installGroups: [core]
10
10
  ---
@@ -21,7 +21,7 @@ Use this skill as an execution checklist, not reference material.
21
21
  4. Validate with the narrowest relevant command first, then run `pikku-verify` or `pikku all` when functions, wirings, schemas, or generated clients may have changed.
22
22
  5. If validation fails, fix the source cause and rerun validation. Do not paper over generated errors by editing generated files.
23
23
 
24
- `@pikku/ai-vercel` provides an AI agent runner backed by the [Vercel AI SDK](https://sdk.vercel.ai/). Implements `AIAgentRunnerService` from `@pikku/core`.
24
+ `@pikku/ai-vercel` provides an AI agent runner backed by the [Vercel AI SDK](https://sdk.vercel.ai/). Implements `AgentRunnerService` from `@pikku/core`.
25
25
 
26
26
  ## Installation
27
27
 
@@ -31,12 +31,12 @@ yarn add @pikku/ai-vercel ai @ai-sdk/openai # or any AI SDK provider
31
31
 
32
32
  ## API Reference
33
33
 
34
- ### `VercelAIAgentRunner`
34
+ ### `VercelAgentRunner`
35
35
 
36
36
  ```typescript
37
- import { VercelAIAgentRunner } from '@pikku/ai-vercel'
37
+ import { VercelAgentRunner } from '@pikku/ai-vercel'
38
38
 
39
- const runner = new VercelAIAgentRunner(
39
+ const runner = new VercelAgentRunner(
40
40
  providers: Record<string, any>, // provider name → AI SDK provider
41
41
  providerFactory?: (apiKey: string) => Record<string, any>,
42
42
  allowedAttachmentHosts?: string[]
@@ -45,8 +45,8 @@ const runner = new VercelAIAgentRunner(
45
45
 
46
46
  **Methods:**
47
47
 
48
- - `stream(params: AIAgentRunnerParams, channel: AIStreamChannel): Promise<AIAgentStepResult>` — Stream AI responses with tool calls
49
- - `run(params: AIAgentRunnerParams): Promise<AIAgentStepResult>` — Execute a single AI step (non-streaming)
48
+ - `stream(params: AgentRunnerParams, channel: AgentStreamChannel): Promise<AgentStepResult>` — Stream AI responses with tool calls
49
+ - `run(params: AgentRunnerParams): Promise<AgentStepResult>` — Execute a single AI step (non-streaming)
50
50
  - `transcribe({ model, audio, … })` / `generateSpeech({ model, text, voice, … })` — what `voiceInput`/`voiceOutput` call; see `pikku-ai-voice`
51
51
  - `generateImage`, `embed`, `embedMany`, `rerank` — the remaining AI SDK surfaces
52
52
  - `withApiKey(apiKey)` — returns a **new** runner built from `providerFactory`; returns `this` unchanged when no factory was supplied or the key is blank. This is the per-user-credential path
@@ -75,7 +75,7 @@ gateway-routed providers after construction.
75
75
  ### Basic Setup
76
76
 
77
77
  ```typescript
78
- import { VercelAIAgentRunner } from '@pikku/ai-vercel'
78
+ import { VercelAgentRunner } from '@pikku/ai-vercel'
79
79
  import { createOpenAI } from '@ai-sdk/openai'
80
80
  import { createAnthropic } from '@ai-sdk/anthropic'
81
81
 
@@ -86,19 +86,19 @@ const createSingletonServices = pikkuServices(async (config, { secrets }) => {
86
86
  apiKey: (await secrets.getSecret('OPENAI_API_KEY')).reveal(),
87
87
  })
88
88
  }
89
- return { config, aiAgentRunner: new VercelAIAgentRunner(providers) }
89
+ return { config, agentRunner: new VercelAgentRunner(providers) }
90
90
  })
91
91
  ```
92
92
 
93
- The service key is **`aiAgentRunner`** — that is the name the agent wiring looks
93
+ The service key is **`agentRunner`** — that is the name the agent wiring looks
94
94
  up. Registering it as `aiRunner` leaves every agent unable to call a model.
95
95
 
96
96
  ### With an agent
97
97
 
98
98
  ```typescript
99
- import { pikkuAIAgent } from '#pikku/agent/pikku-agent-types.gen.js'
99
+ import { pikkuAgent } from '#pikku/agent/pikku-agent-types.gen.js'
100
100
 
101
- export const assistant = pikkuAIAgent({
101
+ export const assistant = pikkuAgent({
102
102
  name: 'assistant',
103
103
  description: 'Answers questions',
104
104
  goal: 'You are a helpful assistant.',
@@ -106,16 +106,16 @@ export const assistant = pikkuAIAgent({
106
106
  })
107
107
  ```
108
108
 
109
- There is no `wireAIAgent` — agents are declared with `pikkuAIAgent` from the
110
- generated agent types. See `pikku-ai-agent` for the full config.
109
+ There is no `wireAgent` — agents are declared with `pikkuAgent` from the
110
+ generated agent types. See `pikku-agent` for the full config.
111
111
 
112
112
  ### Testing without a real provider
113
113
 
114
- Replacing the *provider* rather than the runner keeps every code path under test
114
+ Replacing the _provider_ rather than the runner keeps every code path under test
115
115
  real — tool loop, streaming, memory, approvals — and only scripts the replies.
116
116
  Sealing it with `'*'` means no model string, including ones added later, can
117
117
  reach a live endpoint:
118
118
 
119
119
  ```typescript
120
- new VercelAIAgentRunner({ '*': createMockLlmProvider() })
120
+ new VercelAgentRunner({ '*': createMockLlmProvider() })
121
121
  ```
@@ -2,10 +2,10 @@
2
2
  name: pikku-ai-voice
3
3
  description: >-
4
4
  Use when adding voice input (speech-to-text) or voice output (text-to-speech) to AI agents in a
5
- Pikku app. Covers the voiceInput/voiceOutput AI middleware from @pikku/core/ai-agent, per-script
5
+ Pikku app. Covers the voiceInput/voiceOutput AI middleware from @pikku/core/agent, per-script
6
6
  voices, and barge-in. TRIGGER when: code uses voiceInput, voiceOutput, or user asks about voice
7
7
  agents, speech-to-text, text-to-speech, transcription, or @pikku/ai-voice. DO NOT TRIGGER when:
8
- user asks about AI agent wiring generally (use pikku-ai-agent) or the runner itself (use
8
+ user asks about AI agent wiring generally (use pikku-agent) or the runner itself (use
9
9
  pikku-ai-vercel).
10
10
  ---
11
11
 
@@ -27,14 +27,14 @@ The package still publishes, but its entire source is `export {}` — there are
27
27
  `STTService`/`TTSService` interfaces and nothing to import. Do not add it as a
28
28
  dependency.
29
29
 
30
- Voice now lives in **`@pikku/core/ai-agent`** as two AI middlewares, and the
31
- speech models are reached through the `aiAgentRunner` (`transcribe` /
30
+ Voice now lives in **`@pikku/core/agent`** as two AI middlewares, and the
31
+ speech models are reached through the `agentRunner` (`transcribe` /
32
32
  `generateSpeech`) rather than through separate services. See `pikku-ai-vercel`.
33
33
 
34
34
  ## API Reference
35
35
 
36
36
  ```typescript
37
- import { voiceInput, voiceOutput } from '@pikku/core/ai-agent'
37
+ import { voiceInput, voiceOutput } from '@pikku/core/agent'
38
38
 
39
39
  voiceInput(config?: {
40
40
  model?: string // transcription model — required in practice
@@ -54,9 +54,9 @@ voiceOutput(config?: {
54
54
  })
55
55
  ```
56
56
 
57
- Both attach through the agent's **`aiMiddleware`** array, not a
58
- `middlewareHooks` option, and the agent is declared with `pikkuAIAgent` — there
59
- is no `wireAIAgent`.
57
+ Both attach through the agent's **`agentMiddleware`** array, not a
58
+ `middlewareHooks` option, and the agent is declared with `pikkuAgent` — there
59
+ is no `wireAgent`.
60
60
 
61
61
  ### `voiceInput` — audio in, text in its place
62
62
 
@@ -74,7 +74,7 @@ spoken, which is why it records two shared-notes keys on the way past:
74
74
 
75
75
  Behaviours that decide how a voice loop should be written:
76
76
 
77
- - **It is a no-op without `aiAgentRunner.transcribe`** — no error, the audio
77
+ - **It is a no-op without `agentRunner.transcribe`** — no error, the audio
78
78
  simply passes through untouched.
79
79
  - **`config.model` is required once audio actually arrives**, and throws then
80
80
  rather than at wiring time.
@@ -84,7 +84,7 @@ Behaviours that decide how a voice loop should be written:
84
84
  distinct from a transcription failure, which is worth reporting.
85
85
  - **Non-speech means an empty transcript, and nothing cleverer.** There was a
86
86
  per-segment confidence gate here and it was removed: Whisper is
87
- subtitle-trained, so it is *confident* when it invents ("Thank you." scored
87
+ subtitle-trained, so it is _confident_ when it invents ("Thank you." scored
88
88
  better than the real sentence beside it). Pick an ASR that returns an empty
89
89
  string on silence rather than trying to filter one that doesn't.
90
90
  - Audio arrives either inline (base64 `data`) or as a `url` fetched through
@@ -112,7 +112,7 @@ awaits the chain, and emits `audio-done` before the `done` event.
112
112
  ### `speakableScripts` — declare what the model can pronounce
113
113
 
114
114
  Handed a script it has no voice for, a speech model typically neither fails nor
115
- stays quiet: Kokoro reads out the *letter names* — 24 seconds of "Arabic meem,
115
+ stays quiet: Kokoro reads out the _letter names_ — 24 seconds of "Arabic meem,
116
116
  Arabic ra" for a one-line sentence. Declaring the range leaves anything outside
117
117
  it unspoken and reports it once per reply as a `voice-unsupported` data event.
118
118
 
@@ -133,15 +133,15 @@ fallback)` are exported if you need the same decision outside the middleware.
133
133
  ## Usage Pattern
134
134
 
135
135
  ```typescript
136
- import { pikkuAIAgent } from '#pikku/agent/pikku-agent-types.gen.js'
137
- import { voiceInput, voiceOutput } from '@pikku/core/ai-agent'
136
+ import { pikkuAgent } from '#pikku/agent/pikku-agent-types.gen.js'
137
+ import { voiceInput, voiceOutput } from '@pikku/core/agent'
138
138
 
139
- export const voiceAssistant = pikkuAIAgent({
139
+ export const voiceAssistant = pikkuAgent({
140
140
  name: 'voice-assistant',
141
141
  description: 'Holds a spoken conversation',
142
142
  goal: 'You are a voice assistant. You are being listened to, not read.',
143
143
  model: 'openai/gpt-5-mini',
144
- aiMiddleware: [
144
+ agentMiddleware: [
145
145
  voiceInput({ model: 'deepinfra/openai/whisper-large-v3-turbo' }),
146
146
  voiceOutput({
147
147
  model: 'deepinfra/hexgrad/Kokoro-82M',
@@ -27,7 +27,7 @@ Pikku is a TypeScript framework that separates business logic from transport mec
27
27
 
28
28
  For deep-dive on each topic, see the dedicated skills:
29
29
 
30
- - **Wiring**: `pikku-http`, `pikku-websocket`, `pikku-rpc`, `pikku-mcp`, `pikku-queue`, `pikku-cron`, `pikku-trigger`, `pikku-cli`, `pikku-ai-agent`, `pikku-workflow`
30
+ - **Wiring**: `pikku-http`, `pikku-websocket`, `pikku-rpc`, `pikku-mcp`, `pikku-queue`, `pikku-cron`, `pikku-trigger`, `pikku-cli`, `pikku-agent`, `pikku-workflow`
31
31
  - **Authorization**: `pikku-security` (authentication/sessions), `pikku-permissions` (permission checks, scopes), `pikku-middleware` (global/tag/route middleware)
32
32
  - **Infrastructure**: `pikku-services`, `pikku-config`
33
33
  - **Project introspection**: `pikku-info`
@@ -44,7 +44,7 @@ pikkuFunc (pure business logic)
44
44
  ├── wireMCPTool → Model Context Protocol (AI tools)
45
45
  ├── wireCLI → CLI commands
46
46
  ├── wireTrigger → Event-driven (Redis pub/sub, PG LISTEN/NOTIFY)
47
- ├── pikkuAIAgent → AI agents / chatbots
47
+ ├── pikkuAgent → AI agents / chatbots
48
48
  ├── pikkuWorkflow → Multi-step durable workflows
49
49
  └── wire.rpc → Internal function-to-function calls
50
50
  ```
@@ -122,7 +122,7 @@ pikkuFunc({
122
122
  permissionsInBody?: boolean, // Last resort; needs allow.permissionsInBody in config
123
123
  middleware?: PikkuMiddleware[], // See pikku-middleware
124
124
 
125
- // Agent tooling — see pikku-ai-agent
125
+ // Agent tooling — see pikku-agent
126
126
  approvalRequired?: boolean,
127
127
  approvalDescription?: (services, data) => Promise<string>,
128
128
 
@@ -144,7 +144,7 @@ reject every caller it exists to serve. Gate those with `permissions`, which
144
144
  receive the optional session and may pass anonymous.
145
145
 
146
146
  **Generics XOR `input`/`output` — never both.** A function's data and return
147
- types come from *one* source: either the `input`/`output` schemas (preferred —
147
+ types come from _one_ source: either the `input`/`output` schemas (preferred —
148
148
  they double as runtime validation and OpenAPI) or type generics
149
149
  (`pikkuFunc<In, Out>({ ... })`). Passing both makes the two disagree and forces
150
150
  `as any` casts. Do not annotate the `func` return type inline either — let the
@@ -230,7 +230,7 @@ await server.start()
230
230
 
231
231
  **Lifecycle hooks do not run on this path** — only `pikku dev` and `pikku serve` invoke them. Do your startup work directly in the entrypoint instead.
232
232
 
233
- `pikku validate` warns when a project starts a server by hand *and* depends on no runtime adapter, since that combination means path 1 was available and unused. Silence it with `"lint": { "customServerBootstrap": "off" }` in `pikku.config.json`.
233
+ `pikku validate` warns when a project starts a server by hand _and_ depends on no runtime adapter, since that combination means path 1 was available and unused. Silence it with `"lint": { "customServerBootstrap": "off" }` in `pikku.config.json`.
234
234
 
235
235
  ## Code Generation
236
236
 
@@ -42,14 +42,14 @@ export default createCloudflareHandler(
42
42
  )
43
43
  ```
44
44
 
45
- | Factory | For |
46
- | --- | --- |
47
- | `createCloudflareHandler(factories, handlerTypes)` | combined `fetch`/`queue`/`scheduled` |
48
- | `createCloudflareWorkerHandler(factories)` | HTTP / agent / RPC / workflow-orchestrator units |
49
- | `createCloudflareCronHandler(factories)` | cron units |
50
- | `createCloudflareQueueHandler(factories)` | queue-consumer and workflow-step units |
51
- | `createCloudflareMCPHandler(factories)` | MCP units (same HTTP transport) |
52
- | `createCloudflareWebSocketHandler(factories)` | channel units, delegating to the DO |
45
+ | Factory | For |
46
+ | -------------------------------------------------- | ------------------------------------------------ |
47
+ | `createCloudflareHandler(factories, handlerTypes)` | combined `fetch`/`queue`/`scheduled` |
48
+ | `createCloudflareWorkerHandler(factories)` | HTTP / agent / RPC / workflow-orchestrator units |
49
+ | `createCloudflareCronHandler(factories)` | cron units |
50
+ | `createCloudflareQueueHandler(factories)` | queue-consumer and workflow-step units |
51
+ | `createCloudflareMCPHandler(factories)` | MCP units (same HTTP transport) |
52
+ | `createCloudflareWebSocketHandler(factories)` | channel units, delegating to the DO |
53
53
 
54
54
  `factories` is `{ createConfig, createSingletonServices, createPlatformServices? }`.
55
55
 
@@ -71,7 +71,7 @@ const services = await setupServices(env, {
71
71
  **Do not hand-roll this.** Beyond building `LocalVariablesService` /
72
72
  `LocalSecretService` and caching the result, it calls `setSingletonServices()` —
73
73
  and the core runners (`fetchData`, `runQueueJob`, `runScheduled`) resolve
74
- services through that global slot, *not* through the value you were returned. A
74
+ services through that global slot, _not_ through the value you were returned. A
75
75
  setup function that only returns the services leaves every request throwing
76
76
  "Singleton services not initialized" as a CF `1101`. It also stashes the env via
77
77
  `setCloudflareEnv`, which `getCloudflareEnv()` reads for bindings.
@@ -102,14 +102,17 @@ yarn add @pikku/ws
102
102
  ```
103
103
 
104
104
  ```typescript
105
- import { pikkuWebsocketHandler } from '@pikku/ws'
105
+ import { DEFAULT_WS_MAX_PAYLOAD, pikkuWebsocketHandler } from '@pikku/ws'
106
106
  import { stopSingletonServices } from '@pikku/core'
107
107
  import { Server } from 'http'
108
108
  import { WebSocketServer } from 'ws'
109
109
  import './.pikku/pikku-bootstrap.gen.js'
110
110
 
111
111
  const server = new Server()
112
- const wss = new WebSocketServer({ noServer: true })
112
+ const wss = new WebSocketServer({
113
+ noServer: true,
114
+ maxPayload: DEFAULT_WS_MAX_PAYLOAD,
115
+ })
113
116
 
114
117
  pikkuWebsocketHandler({
115
118
  server,
@@ -4,8 +4,11 @@ description: >-
4
4
  Use for the Pikku dependency security audit: the `pikku audit` CLI command, the
5
5
  `.pikku/audit.json` artifact, the `SecurityAuditReport` type in @pikku/core, and the console
6
6
  Security screen (getSecurityAudit / runSecurityAudit / updateDependency + SecurityAuditView).
7
- TRIGGER when: user asks about `pikku audit`, dependency vulnerabilities/advisories, outdated
8
- dependencies, the Security screen/page in the console, updating a vulnerable dependency, or
7
+ Also covers `pikku update`, which moves the @pikku/* dependency set forward and reports the
8
+ peers those versions need.
9
+ TRIGGER when: user asks about `pikku audit` or `pikku update`, dependency
10
+ vulnerabilities/advisories, outdated dependencies, upgrading Pikku itself, peer dependency
11
+ conflicts, the Security screen/page in the console, updating a vulnerable dependency, or
9
12
  reading/rendering audit.json. DO NOT TRIGGER when: user asks about authentication/sessions/JWT
10
13
  (use pikku-security), permissions (use pikku-permissions), or secrets/env vars (use
11
14
  pikku-config).
@@ -43,11 +46,47 @@ installGroups: [core]
43
46
  `bun outdated`, normalised into one `SecurityAuditReport` with per-severity /
44
47
  per-update-level counts). Other PMs are detected but **stubbed** with a `note`
45
48
  field until their shapes are normalised — issues/updates come back empty.
46
- - `bun audit` exits non-zero when it *finds* advisories but still writes the
49
+ - `bun audit` exits non-zero when it _finds_ advisories but still writes the
47
50
  payload to stdout, so a non-zero exit **with output** is data. A non-zero exit
48
51
  with **no** output — or a launch failure, timeout, or a blown 32MB buffer —
49
52
  throws, precisely so a failed run can't masquerade as "0 advisories".
50
53
 
54
+ ## The `pikku update` command
55
+
56
+ Narrower than `audit --outdated`, and the only one that writes: it moves the
57
+ **@pikku/\* set** forward and reports the peers those versions need. Use `audit`
58
+ to learn a dependency is vulnerable; use `update` to move Pikku itself.
59
+
60
+ - `pikku update` — reports only. Nothing is written without `--update`.
61
+ - `pikku update --update` — writes the new ranges into every covered
62
+ package.json, then runs an install. `--no-install` writes and stops.
63
+ - `pikku update --update-peers` — implies `--update` and additionally writes the
64
+ ranges unsatisfied peers require, **for peers the project already declares**.
65
+ A peer it does not declare is reported and never added — adding a dependency
66
+ is not an update. Separate from `--update` because a peer bump can cross a
67
+ **major** of a third-party package (`ai` 5 → 6), which is not a call to make
68
+ on the user's behalf.
69
+ - `--tag <dist-tag>` (default `latest`) reads each package's own dist-tag, so
70
+ `--tag next` moves the whole set onto prereleases. `--registry <url>` defaults
71
+ to `npm_config_registry`.
72
+ - Coverage is the nearest package.json walking up from the project root, plus
73
+ every workspace it declares — a monorepo updates in one pass. All four
74
+ dependency fields are read, `peerDependencies` included, so an addon's own
75
+ declared peer range moves with it.
76
+
77
+ Statuses, per dependency: `outdated` (the range floor is behind latest — this is
78
+ what `--update` writes), `stale-install` (the range already admits latest but
79
+ node_modules is behind — an install fixes it, no edit needed), `linked` (a
80
+ `workspace:`/`file:`/`link:`/`portal:` range — a deliberate local checkout,
81
+ counted but never listed), `manual` (a registry range we refuse to substitute
82
+ into: a union, an x-range, a `*`), `unresolved` (the registry had no such tag —
83
+ this must **never** read as "current", the same rule as a failed audit).
84
+
85
+ Peers are read off the version the run **lands on**, not the one installed —
86
+ the point is what the target needs. An @pikku peer the same run already brings
87
+ forward is not reported, and an unsatisfied _optional_ peer the project never
88
+ declared is skipped.
89
+
51
90
  ## Console integration (@pikku/addon-console)
52
91
 
53
92
  Three RPCs, all reading/writing the same artifact via the meta service. Shared