@pikku/skills 0.12.64 → 0.12.67
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/dist/skills.gen.js +1 -1
- package/package.json +1 -1
- package/skills/pikku-addon/SKILL.md +36 -8
- package/skills/pikku-addon/references/openapi.md +20 -3
- package/skills/pikku-deploy/references/cloudflare.md +2 -2
- package/skills/pikku-deploy/references/lambda.md +1 -1
- package/skills/pikku-wiring/references/channel.md +6 -0
- package/skills/pikku-wiring/references/queue.md +28 -0
- package/skills/pikku-wiring/references/scheduler.md +6 -0
- package/skills/pikku-workflow/SKILL.md +13 -0
package/package.json
CHANGED
|
@@ -200,7 +200,10 @@ npx pikku new addon stripe --display-name Stripe --category Payments --dir addon
|
|
|
200
200
|
```
|
|
201
201
|
|
|
202
202
|
**Handed an OpenAPI or Swagger spec?** Don't hand-write the functions —
|
|
203
|
-
`pikku new addon <name> --openapi <spec>` generates one function per operation
|
|
203
|
+
`pikku new addon <name> --openapi <spec>` generates one function per operation
|
|
204
|
+
(`<spec>` is a path, a URL, or a registry catalogue name such as
|
|
205
|
+
`amazonaws.com:applicationcostprofiler`; inside an app,
|
|
206
|
+
`pikku addons add <catalogue-name>` does the same and picks `--auth` for you),
|
|
204
207
|
with its schemas, service and credential. Read `references/openapi.md`.
|
|
205
208
|
|
|
206
209
|
This generates `package.json` (exports `.pikku/*` + `dist/`), `pikku.config.json` (`addon: true`), `tsconfig.json` (`#pikku` path mapping), `src/services.ts`, `src/functions/`, and `types/application-types.d.ts`. For the full file contents/exports you rarely hand-edit, read `references/addon-package-manifest.md`.
|
|
@@ -378,7 +381,7 @@ At runtime an unmapped alias, or the wired name called directly, throws
|
|
|
378
381
|
### Studio screens
|
|
379
382
|
|
|
380
383
|
An addon declares the screens it adds to Pikku Studio with `definePlugin`, in
|
|
381
|
-
`src/screens.ts` (`pikku new addon
|
|
384
|
+
`src/screens.ts` (`pikku new addon <name> --ui` scaffolds one). It replaces
|
|
382
385
|
`defineScreens`, which no longer exists.
|
|
383
386
|
|
|
384
387
|
```typescript
|
|
@@ -421,18 +424,43 @@ export default definePlugin({
|
|
|
421
424
|
addons only; Studio enforces that). `layout: 'bare'` renders without the shell.
|
|
422
425
|
- Titles are message keys in the addon's `messages/{locale}.json`, found by
|
|
423
426
|
convention next to its `package.json`; there is no field for them.
|
|
427
|
+
- `agent: 'name'` makes that agent answer in Studio's chat panel (a second tab
|
|
428
|
+
beside the general chat) while the screen is open. It resolves to
|
|
429
|
+
`agents/<name>.md` at the addon's package root: the agent's instructions,
|
|
430
|
+
which name the skills it follows (plain folders `skills/<name>/SKILL.md`).
|
|
431
|
+
`agent: 'studio:<name>'` instead picks an agent Studio ships; `pikku all` only
|
|
432
|
+
checks the format and looks up no file.
|
|
433
|
+
The file starts with frontmatter whose `title` and `description` are message
|
|
434
|
+
keys in `messages/en.json`. The name matches `/^[a-z][a-z0-9-]*$/`.
|
|
435
|
+
- `defaultChat: false` hides Studio's general Chat tab on the screen, so the
|
|
436
|
+
screen's `agent` is its only chat (with no `agent`, the screen has no chat).
|
|
437
|
+
It defaults to `true`, must be a boolean literal, and is only written to the
|
|
438
|
+
metadata when declared.
|
|
439
|
+
- `agents/` and `skills/` ship in the published package. If `package.json` has a
|
|
440
|
+
`files` list, it must include them (`"files": ["dist", "messages", "agents",
|
|
441
|
+
"skills"]`, which `pikku new addon <name> --ui` scaffolds). A root glob such as
|
|
442
|
+
`**/*.md` does not count, so list the folder as well. With no `files` field
|
|
443
|
+
nothing is checked, so make sure `.npmignore`, or `.gitignore` when there is no
|
|
444
|
+
`.npmignore`, does not exclude them.
|
|
445
|
+
- `package.json` carries a `studio` block, `{ "addon": "<name>", "ui": "./src",
|
|
446
|
+
"messages": "./messages/{locale}.json" }`. Studio only links (and loads the
|
|
447
|
+
agents and skills of) a package with `studio.addon`; it is the addon's short
|
|
448
|
+
name, the `<addon>` in an agent's scope `agent:<addon>:<name>`. The `--ui`
|
|
449
|
+
scaffold writes it with `addon` set to the addon's name.
|
|
424
450
|
- `scopes` only hide the screen. The addon's functions must enforce the same
|
|
425
451
|
scopes.
|
|
426
452
|
|
|
427
453
|
The inspector reads every field statically, so each must be a literal.
|
|
428
454
|
`pikku all` fails on:
|
|
429
455
|
|
|
430
|
-
| Code | When
|
|
431
|
-
| ------ |
|
|
432
|
-
| PKU345 | a field is not a literal (variable, call, spread, bad value)
|
|
433
|
-
| PKU357 | two screens of the addon use the same path
|
|
434
|
-
| PKU358 | a title key is missing from `messages/en.json`
|
|
435
|
-
| PKU359 | `nav.badge` names no function of the addon
|
|
456
|
+
| Code | When |
|
|
457
|
+
| ------ | ---------------------------------------------------------------------------------------------------- |
|
|
458
|
+
| PKU345 | a field is not a literal (variable, call, spread, bad value) |
|
|
459
|
+
| PKU357 | two screens of the addon use the same path |
|
|
460
|
+
| PKU358 | a title or agent frontmatter key is missing from `messages/en.json` |
|
|
461
|
+
| PKU359 | `nav.badge` names no function of the addon |
|
|
462
|
+
| PKU365 | `agent` is neither a name nor `studio:<name>`, or a name has no non-empty `agents/<name>.md`, or no frontmatter `title` and `description` |
|
|
463
|
+
| PKU366 | `package.json` `files` leaves out `agents/` while a screen names a valid (no PKU365) non-`studio:` agent, or `skills/` while the addon has a `skills/<name>/SKILL.md` |
|
|
436
464
|
|
|
437
465
|
A key missing from another locale's catalog is a warning.
|
|
438
466
|
|
|
@@ -11,7 +11,8 @@
|
|
|
11
11
|
- 6 — Check the spec against the real API
|
|
12
12
|
- Then
|
|
13
13
|
|
|
14
|
-
When you are handed an OpenAPI or Swagger spec — a file,
|
|
14
|
+
When you are handed an OpenAPI or Swagger spec — a file, a URL to one, or the
|
|
15
|
+
name of one in the registry's catalogue (`https://www.pikku.dev/openapis`) — the
|
|
15
16
|
API it describes becomes an addon: one function per operation, each with its
|
|
16
17
|
input and output schemas, behind one service that makes the HTTP calls. Say so
|
|
17
18
|
before starting ("This is an OpenAPI spec — I'll turn it into an addon first"),
|
|
@@ -26,7 +27,23 @@ A JSON or YAML document with a top-level `openapi` key (3.x) or `swagger` key
|
|
|
26
27
|
|
|
27
28
|
## 1 — Look at the spec first
|
|
28
29
|
|
|
29
|
-
`--openapi` takes a path
|
|
30
|
+
`--openapi` takes a path, a URL, or a catalogue name such as
|
|
31
|
+
`amazonaws.com:applicationcostprofiler`. A name is anything that is neither a
|
|
32
|
+
URL, a path, nor a `.json`/`.yaml` file; it is looked up in the registry
|
|
33
|
+
(`--registry`, else `pikku.config.json`'s `registry`, else
|
|
34
|
+
`https://api.pikkustudio.app`) and generated from the entry's spec URL. A name
|
|
35
|
+
the registry does not know is refused before anything is written. On the
|
|
36
|
+
website the page URL is a slug (`amazonaws-com-applicationcostprofiler`); the
|
|
37
|
+
name to pass is the one the page's command shows, with its `.` and `:`.
|
|
38
|
+
|
|
39
|
+
For a catalogue entry inside an app, the short form is
|
|
40
|
+
`pikku addons add amazonaws.com:applicationcostprofiler`. It names the addon
|
|
41
|
+
after the entry (`amazonaws-applicationcostprofiler`) and takes `--auth` from
|
|
42
|
+
what the registry records: `none` for a public API, `user` for OAuth or a key
|
|
43
|
+
each user brings, `shared` for a key the app holds, and `user` when the registry
|
|
44
|
+
does not know. It prints the mode it picked; pass `--auth` to override it.
|
|
45
|
+
|
|
46
|
+
A spec published only to signed-in callers
|
|
30
47
|
takes the key the way the API reads it: `--openapi-header "NAME: value"`
|
|
31
48
|
(repeatable), or in the URL's query string when the API reads it there
|
|
32
49
|
(Dolibarr's explorer takes `?DOLAPIKEY=`). A 401 while fetching says which.
|
|
@@ -40,7 +57,7 @@ Keep a copy in `specs/` as the record of what the addon was generated from.
|
|
|
40
57
|
## 2 — Generate, from the app's root
|
|
41
58
|
|
|
42
59
|
```bash
|
|
43
|
-
bunx --bun pikku new addon <name> --openapi <path-or-
|
|
60
|
+
bunx --bun pikku new addon <name> --openapi <path-url-or-catalogue-name>
|
|
44
61
|
```
|
|
45
62
|
|
|
46
63
|
One command. Inside an app it writes `packages/addon-<name>` as
|
|
@@ -71,8 +71,8 @@ CF `1101`. It also stashes the env via `setCloudflareEnv`, which
|
|
|
71
71
|
- A `GET` with `Upgrade: websocket` is routed to the hibernation server. Without
|
|
72
72
|
one passed in it answers **426**, so a channel worker that forgets the second
|
|
73
73
|
argument fails every upgrade while plain HTTP keeps working.
|
|
74
|
-
- `CF-Ray`
|
|
75
|
-
trace
|
|
74
|
+
- `CF-Ray` does not set the traceId: it is not a W3C trace id. Core starts a new
|
|
75
|
+
trace, or continues a verified mesh caller's.
|
|
76
76
|
- `options.exposeErrors` defaults to **`false`** — error detail is withheld from
|
|
77
77
|
responses unless you opt in.
|
|
78
78
|
|
|
@@ -92,7 +92,7 @@ export const scheduled: ScheduledHandler = async (event) => {
|
|
|
92
92
|
```
|
|
93
93
|
|
|
94
94
|
`runLambdaScheduled` runs **every** scheduled task registered in the bundle,
|
|
95
|
-
each
|
|
95
|
+
each on its own new trace, and logs rather than rethrows a task
|
|
96
96
|
failure — so one bad task cannot fail the invocation or stop the others. The
|
|
97
97
|
event itself is ignored; which tasks run is decided by what the unit bundled,
|
|
98
98
|
not by which EventBridge rule fired.
|
|
@@ -243,3 +243,9 @@ wireChannel({
|
|
|
243
243
|
},
|
|
244
244
|
})
|
|
245
245
|
```
|
|
246
|
+
|
|
247
|
+
## Tracing
|
|
248
|
+
|
|
249
|
+
A channel has one trace per connection: `onConnect`, `onDisconnect`, each message and each `channel.remote` call are spans in it, read from `wire.trace`. A client's `traceparent` is ignored. A serverless channel keeps the trace in `ChannelStore`, so a custom store must return the `traceparent` it was added with.
|
|
250
|
+
|
|
251
|
+
A reverse RPC carries `traceparent`, which `createChannelRPCResponder` ignores unless you pass `trustInboundTraceparent: true`. Only pass it for a peer you have authenticated.
|
|
@@ -81,6 +81,34 @@ Options:
|
|
|
81
81
|
}
|
|
82
82
|
```
|
|
83
83
|
|
|
84
|
+
### Tracing
|
|
85
|
+
|
|
86
|
+
A job continues the trace of the function that enqueued it. Inside a function,
|
|
87
|
+
`queueService.add` stamps `JobOptions.traceparent` from the wire, and the worker
|
|
88
|
+
gets the same trace id in a new span on `wire.trace`. Pass `traceparent` yourself
|
|
89
|
+
only to override it.
|
|
90
|
+
|
|
91
|
+
Nothing stamps a job added from a singleton service, or from a queue service
|
|
92
|
+
captured at start-up. That job starts a new trace. Pass `traceparent:
|
|
93
|
+
rpc.traceparent` when you need to carry it through one of those.
|
|
94
|
+
|
|
95
|
+
A custom `QueueService` must carry `traceparent` and set it on `QueueJob`. A
|
|
96
|
+
missing or invalid one starts a new trace; it is never an error.
|
|
97
|
+
|
|
98
|
+
### Running a job as a user
|
|
99
|
+
|
|
100
|
+
Pass `pikkuUserId` in the job options and wrap the queue service in
|
|
101
|
+
`SignedQueueService`. The worker then runs with `wire.pikkuUserId` and the user's
|
|
102
|
+
stored session, on every adapter. An unsigned or forged id is dropped and the job
|
|
103
|
+
runs with neither.
|
|
104
|
+
|
|
105
|
+
Never take the id from client input. If the session has gone by the time the job
|
|
106
|
+
runs, `wire.pikkuUserId` is still set and `wire.session` is not.
|
|
107
|
+
|
|
108
|
+
A custom `QueueService` must carry `pikkuUserId` next to the payload and set it on
|
|
109
|
+
`QueueJob`, leaving `job.data` as it was. Check it with
|
|
110
|
+
`defineQueueIdentityTransportTests` from `@pikku/core/testing`.
|
|
111
|
+
|
|
84
112
|
## Usage Patterns
|
|
85
113
|
|
|
86
114
|
### Basic Queue Worker
|
|
@@ -63,6 +63,12 @@ will catch a skip and report it as a failure. If your middleware distinguishes
|
|
|
63
63
|
success from failure, let the skip pass through rather than logging it as an
|
|
64
64
|
error.
|
|
65
65
|
|
|
66
|
+
### Tracing
|
|
67
|
+
|
|
68
|
+
Each cron firing starts a new trace, on `wire.trace`. A delayed call fires on the
|
|
69
|
+
trace passed as the last argument of `scheduleRPC`: a workflow sleep passes the
|
|
70
|
+
run's, and nothing passes it for you elsewhere, so use `wire.rpc.traceparent`.
|
|
71
|
+
|
|
66
72
|
### Cron Expression Reference
|
|
67
73
|
|
|
68
74
|
```
|
|
@@ -371,6 +371,19 @@ export const userOnboarding = pikkuWorkflowGraph({
|
|
|
371
371
|
})
|
|
372
372
|
```
|
|
373
373
|
|
|
374
|
+
### Tracing
|
|
375
|
+
|
|
376
|
+
A run owns one trace, stored on `run.wire.traceparent`. It starts from the wire or
|
|
377
|
+
the caller's `rpc`; a start with neither, such as a trigger, gets a new trace. Every
|
|
378
|
+
step, retry, sleep wake-up, resume, child workflow, recovery and job a step
|
|
379
|
+
enqueues stays on it. Each hop is a new span whose parent is the span that started
|
|
380
|
+
the run. An agent's tool calls are the exception: they are not on the run's trace
|
|
381
|
+
yet.
|
|
382
|
+
|
|
383
|
+
### Restarts
|
|
384
|
+
|
|
385
|
+
A run survives a crash or deploy. `pikku dev` and `pikku serve` recover it at startup and every 30s: a sleep keeps its deadline, and a step caught in flight runs again as a new attempt. A settled step never reruns. So a step can run more than once: make its side effects idempotent on `workflowStep.invocationId`, which stays the same across attempts. A step with `retries: 0` caught in flight fails instead. Any other host calls `workflowService.startRecovery()` once the queue is consuming. Set `workflow.recovery: false` to turn it off.
|
|
386
|
+
|
|
374
387
|
## File conventions
|
|
375
388
|
|
|
376
389
|
- Place workflows in `packages/functions/src/wirings/*.workflow.ts`; export the variable so the inspector discovers it (no manual registration).
|