@pikku/inspector 0.12.59 → 0.12.61

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.
Files changed (132) hide show
  1. package/CHANGELOG.md +373 -0
  2. package/OPTIMIZATION-PLAN.md +19 -19
  3. package/dist/add/add-agent-scorer.d.ts +2 -0
  4. package/dist/add/{add-ai-scorer.js → add-agent-scorer.js} +4 -4
  5. package/dist/add/{add-ai-agent.d.ts → add-agent.d.ts} +1 -1
  6. package/dist/add/{add-ai-agent.js → add-agent.js} +11 -11
  7. package/dist/add/add-auth.js +1 -1
  8. package/dist/add/add-cli.js +5 -0
  9. package/dist/add/add-functions.js +10 -1
  10. package/dist/add/add-http-route.js +18 -18
  11. package/dist/add/add-keyed-wiring.d.ts +2 -0
  12. package/dist/add/add-keyed-wiring.js +3 -1
  13. package/dist/add/add-middleware.js +5 -5
  14. package/dist/add/add-personas.js +3 -0
  15. package/dist/add/add-secret.js +1 -0
  16. package/dist/add/add-variable.js +1 -0
  17. package/dist/add/add-wire-remote-addon.js +2 -1
  18. package/dist/add/add-workflow-graph.js +63 -6
  19. package/dist/error-codes.d.ts +3 -1
  20. package/dist/error-codes.js +3 -1
  21. package/dist/index.d.ts +3 -1
  22. package/dist/index.js +1 -0
  23. package/dist/inspector.js +13 -3
  24. package/dist/types.d.ts +10 -5
  25. package/dist/utils/annotate-http-route-auth.js +2 -1
  26. package/dist/utils/check-secret-sinks.js +2 -1
  27. package/dist/utils/compute-required-schemas.d.ts +1 -1
  28. package/dist/utils/contract-hashes.d.ts +2 -1
  29. package/dist/utils/contract-hashes.js +1 -1
  30. package/dist/utils/extract-function-name.js +1 -1
  31. package/dist/utils/extract-services.d.ts +1 -1
  32. package/dist/utils/extract-surface-usage.d.ts +29 -0
  33. package/dist/utils/extract-surface-usage.js +97 -0
  34. package/dist/utils/filter-inspector-state.js +53 -16
  35. package/dist/utils/filter-utils.d.ts +1 -1
  36. package/dist/utils/get-property-value.js +42 -3
  37. package/dist/utils/load-addon-functions-meta.js +31 -0
  38. package/dist/utils/middleware.d.ts +2 -2
  39. package/dist/utils/middleware.js +5 -5
  40. package/dist/utils/permissions.d.ts +1 -1
  41. package/dist/utils/post-process.d.ts +28 -8
  42. package/dist/utils/post-process.js +83 -18
  43. package/dist/utils/resolve-deploy-target.d.ts +1 -1
  44. package/dist/utils/resolve-function-meta.d.ts +1 -1
  45. package/dist/utils/resolve-function-types.d.ts +1 -1
  46. package/dist/utils/resolve-versions.js +1 -1
  47. package/dist/utils/schema-generator.d.ts +1 -1
  48. package/dist/utils/serialize-inspector-state.d.ts +4 -3
  49. package/dist/utils/serialize-inspector-state.js +6 -4
  50. package/dist/utils/serialize-openapi-json.d.ts +1 -1
  51. package/dist/utils/validate-auth-sessionless.js +2 -1
  52. package/dist/utils/workflow/graph/finalize-workflows.js +1 -1
  53. package/dist/utils/workflow/graph/serialize-workflow-graph.d.ts +6 -1
  54. package/dist/utils/workflow/graph/serialize-workflow-graph.js +26 -2
  55. package/dist/utils/workflow/graph/workflow-graph.types.d.ts +9 -0
  56. package/dist/visit.js +4 -4
  57. package/package.json +10 -10
  58. package/run-tests.sh +0 -0
  59. package/src/add/{add-ai-scorer.test.ts → add-agent-scorer.test.ts} +11 -11
  60. package/src/add/{add-ai-scorer.ts → add-agent-scorer.ts} +4 -4
  61. package/src/add/{add-ai-agent.test.ts → add-agent.test.ts} +1 -1
  62. package/src/add/{add-ai-agent.ts → add-agent.ts} +13 -21
  63. package/src/add/add-auth.ts +2 -2
  64. package/src/add/add-cli.ts +6 -0
  65. package/src/add/add-credential.ts +3 -6
  66. package/src/add/add-file-with-factory.ts +2 -6
  67. package/src/add/add-functions.ts +23 -25
  68. package/src/add/add-http-route-ref.test.ts +149 -0
  69. package/src/add/add-http-route.ts +25 -28
  70. package/src/add/add-keyed-wiring.ts +8 -7
  71. package/src/add/add-middleware.ts +7 -5
  72. package/src/add/add-permission.ts +1 -1
  73. package/src/add/add-personas.test.ts +24 -0
  74. package/src/add/add-personas.ts +3 -1
  75. package/src/add/add-scenario-step.test.ts +35 -0
  76. package/src/add/add-scope.test.ts +4 -4
  77. package/src/add/add-scope.ts +4 -8
  78. package/src/add/add-secret.ts +1 -0
  79. package/src/add/add-system-role.test.ts +8 -8
  80. package/src/add/add-system-role.ts +2 -4
  81. package/src/add/add-variable.ts +1 -0
  82. package/src/add/add-wire-remote-addon.ts +4 -1
  83. package/src/add/add-workflow-graph-foreach.test.ts +174 -0
  84. package/src/add/add-workflow-graph.ts +78 -6
  85. package/src/add/add-workflow-sleep-expression.test.ts +3 -4
  86. package/src/add/addon-contracts.test.ts +1 -1
  87. package/src/add/config-value-metadata.test.ts +94 -0
  88. package/src/add/secret-sink-check.test.ts +4 -1
  89. package/src/error-codes.ts +3 -1
  90. package/src/index.ts +3 -4
  91. package/src/inspector.ts +20 -3
  92. package/src/types.ts +10 -7
  93. package/src/utils/annotate-http-route-auth.test.ts +5 -7
  94. package/src/utils/annotate-http-route-auth.ts +2 -1
  95. package/src/utils/check-secret-sinks.ts +4 -1
  96. package/src/utils/compute-required-schemas.ts +1 -1
  97. package/src/utils/contract-hashes.test.ts +1 -1
  98. package/src/utils/contract-hashes.ts +3 -2
  99. package/src/utils/extract-function-name.ts +1 -1
  100. package/src/utils/extract-services.ts +4 -2
  101. package/src/utils/extract-surface-usage.test.ts +147 -0
  102. package/src/utils/extract-surface-usage.ts +121 -0
  103. package/src/utils/filter-inspector-state.test.ts +138 -12
  104. package/src/utils/filter-inspector-state.ts +82 -21
  105. package/src/utils/filter-utils.ts +1 -1
  106. package/src/utils/get-property-value.ts +43 -5
  107. package/src/utils/load-addon-functions-meta.ts +40 -0
  108. package/src/utils/middleware.test.ts +23 -23
  109. package/src/utils/middleware.ts +6 -6
  110. package/src/utils/permissions.ts +1 -1
  111. package/src/utils/post-process.test.ts +68 -11
  112. package/src/utils/post-process.ts +91 -28
  113. package/src/utils/resolve-deploy-target.ts +1 -1
  114. package/src/utils/resolve-function-meta.ts +1 -1
  115. package/src/utils/resolve-function-types.ts +1 -1
  116. package/src/utils/resolve-versions.ts +1 -1
  117. package/src/utils/schema-generator.ts +2 -1
  118. package/src/utils/serialize-inspector-state.ts +10 -7
  119. package/src/utils/serialize-mcp-json.ts +1 -1
  120. package/src/utils/serialize-openapi-json.ts +1 -1
  121. package/src/utils/validate-auth-sessionless.ts +2 -1
  122. package/src/utils/validate-tags-resolve-to-middleware.test.ts +4 -1
  123. package/src/utils/workflow/dsl/extract-approval-policy.test.ts +4 -1
  124. package/src/utils/workflow/graph/convert-dsl-to-graph-skip.test.ts +1 -1
  125. package/src/utils/workflow/graph/finalize-workflows.ts +6 -2
  126. package/src/utils/workflow/graph/serialize-workflow-graph.ts +34 -3
  127. package/src/utils/workflow/graph/workflow-graph.types.ts +10 -0
  128. package/src/visit.ts +4 -4
  129. package/tsconfig.tsbuildinfo +1 -1
  130. package/dist/add/add-ai-scorer.d.ts +0 -2
  131. package/dist/utils/secret-brokers.d.ts +0 -2
  132. package/dist/utils/secret-brokers.js +0 -9
package/CHANGELOG.md CHANGED
@@ -1,3 +1,376 @@
1
+ ## 0.12.61
2
+
3
+ ### Patch Changes
4
+
5
+ - ab52d8e: Raise an addon's deploy conflict only where the consuming app wires it. A
6
+ function an addon publishes as `deploy: 'serverless'` while naming one of its
7
+ own services serverless-incompatible previously failed the build of any app
8
+ that merely declared the addon, whether or not that function was used.
9
+ - a281de6: A CLI option's type now drives how it is parsed, and it comes from the command function's input schema rather than a second hand-written declaration.
10
+
11
+ `CLIOption` gains `type?: 'string' | 'number' | 'boolean' | 'string[]'` (replacing the never-honoured `array` flag). Declared, it wins over whatever the schema says; left unset, the parser reads the type off the command function's input schema — the same schema the function is validated against — falling back to `default` and then to `'string'`. A `'string[]'` option consumes one token and splits it on commas; every other non-boolean option consumes the next token verbatim, so values that begin with `-` (base64url tokens, negative numbers, dash-leading name patterns) parse correctly. A boolean option is a flag: it consumes the next token only when that token is an explicit literal (`true`/`false`/`1`/`0`/`yes`/`no`), so `--watch false` still turns a default-on flag off instead of leaving `false` behind as a positional.
12
+
13
+ Because the schema is now what types an option, `pikku serve --console --port 4077` no longer reads `--port` as the value of `--console`, and a numeric option arrives as a number instead of a string. An explicit `type` is mostly needed for options that belong to no function input — the `pikku all` filters, which the config factory reads straight off the CLI data, are declared `string[]`, and the CLI's ad-hoc `parseCommaSeparated` normalisation is gone.
14
+
15
+ An array option takes either one comma list or the flag repeated. It never consumes more than one token, because `--tags alpha beta` cannot be told apart from an option followed by a positional; the stray token is reported as an unexpected argument rather than dropped.
16
+
17
+ - 266e3bc: One door per name: `@pikku/core/ecosystem/*` and the package root are gone
18
+
19
+ `@pikku/core` published every module twice. `ecosystem/http` re-exported
20
+ `./http`, `ecosystem/services` re-exported `./services`, and a name was
21
+ reachable through either — so every addition had to be made in two places, and a
22
+ consumer's import said nothing about what it actually used. The package root was
23
+ the same problem at a larger scale: a single barrel of 206 names that no bundler
24
+ could take apart, and the one specifier that revealed nothing at all.
25
+
26
+ Both are deleted. Every name now lives on the subpath that owns it, and every
27
+ import carries that subpath — `@pikku/core/http`, `@pikku/core/services`,
28
+ `@pikku/core/errors`, `@pikku/core/types`.
29
+
30
+ Deleting the facades meant the raw subpaths had to become a superset of them,
31
+ which they were not: the facade tree had accumulated 25 names with no raw home
32
+ and about 26 more filed under a different area than the module they came from.
33
+ Those names moved to the area that owns them, and three areas were published as
34
+ new entry points rather than left on a root that is going away — `./types` (the
35
+ shared type surface, the largest single destination), `./state` and
36
+ `./classification`.
37
+
38
+ `./classification` is one door onto one subject: what a value is and how it must
39
+ be handled. Its three halves would each have been an entry point — the brands
40
+ and manifest types, the stored-form helpers (`hashToken`, `unsafeAsSealed` and
41
+ friends), and `SecretValue` — split by whether a name happens to be a type or a
42
+ value, which is the same defect as the facades. The duration and versioned-id
43
+ helpers went to `./utils`, which already published, and `PikkuRequest` went to
44
+ `./function`: it is the transport-agnostic request base, not an HTTP one — HTTP
45
+ has `PikkuHTTPAbstractRequest`, and the only thing outside core that extends
46
+ `PikkuRequest` is Azure's timer request.
47
+
48
+ `./types` inherited the root barrel's habit before it inherited its contents, so
49
+ the names with an owner elsewhere were moved off it. The middleware types and the
50
+ five middleware factories — `pikkuMiddleware`, `pikkuMiddlewareFactory`,
51
+ `pikkuChannelMiddleware`, `pikkuChannelMiddlewareFactory` and
52
+ `pikkuAgentMiddleware`, runtime values on a types entry point — are now
53
+ `@pikku/core/middleware`; the function meta types are `@pikku/core/function`;
54
+ `SerializedError` is `@pikku/core/errors`; and the generic TypeScript helpers
55
+ (`MakeRequired`, `PickRequired`, `PickOptional`, `RequireAtLeastOne`,
56
+ `JSONPrimitive`, `JSONValue`) are `@pikku/core/utils`. What is left on `./types`
57
+ is the vocabulary the wirings share, which no single module owns.
58
+
59
+ `pikku` was itself a root barrel — `export * from '@pikku/core'` — and
60
+ now exports only the services it bundles.
61
+
62
+ One module survives at the old specifier, and only for the bootstrap:
63
+ `packages/cli` is generated by the _published_ CLI pinned in its `build.sh`, and
64
+ that CLI still writes a bare `@pikku/core` into the files it generates for the
65
+ CLI itself. `bootstrap-compat/root.ts` carries the eight types it names, a test
66
+ in core fails if that list grows, and it goes when the pin moves to a CLI
67
+ released from this branch. The adapter names the pinned CLI reaches for —
68
+ `pikkuState` and `CreateWireServices` — are rewritten to `@pikku/core/state` and
69
+ `@pikku/core/types` by the same `build.sh` patch pass, so no second shim is
70
+ needed for them.
71
+
72
+ A guard test keeps the root shut: it parses imports and rejects a bare
73
+ `@pikku/core` rather than grepping for it, because several tests hold a user's
74
+ file as a template literal, where `import … from '@pikku/core'` is fixture text
75
+ rather than an import this repo makes.
76
+
77
+ An agent scaffold a project generated under an older CLI is refreshed rather
78
+ than left to fail: `pikku all` already deleted one importing an entry point
79
+ `@pikku/core` no longer publishes, and the `#pikku` hub joins that list.
80
+ Without it a project that scaffolds the agent endpoint but
81
+ declares no agents keeps the old file forever — the generator that would rewrite
82
+ it only runs when agents exist, and the file being present is what stops it
83
+ being regenerated as missing.
84
+
85
+ `pikku new addon` also wrote a tsconfig `paths` map naming only the deleted hub.
86
+ An addon's `imports` map points into `dist`, so `paths` is what resolves
87
+ `#pikku/<leaf>` for the addon's own source build — it now names the two leaf
88
+ patterns, in both the addon and its test harness.
89
+
90
+ - 6eef0a0: Bump every dependency to its latest compatible minor/patch across the monorepo.
91
+ - 20d8a39: Drop better-auth's `admin()` plugin.
92
+
93
+ `admin()` bundles three unrelated things: a `role` column, fifteen HTTP
94
+ endpoints authorized against that column, and the enforcement that stops a
95
+ banned user from getting a session. Pikku only ever wanted the third. The
96
+ endpoints were never reachable directly — each sat behind a pikku function with
97
+ its own `admin:users:*` scope — so all the plugin added was a second gate on a
98
+ column that had to be kept in step with the scopes it duplicated. That sync
99
+ (`syncProjectedAdminRole`, run on every authenticated request) is now gone
100
+ along with the column.
101
+
102
+ User administration is implemented against better-auth's internal adapter
103
+ instead, exported from `@pikku/better-auth` so `@pikku/addon-admin` and the
104
+ `scaffold.userAdmin` generator share one implementation:
105
+
106
+ ```ts
107
+ import {
108
+ createAuthUser,
109
+ deleteAuthUser,
110
+ revokeAuthUserSessions,
111
+ setAuthUserBanned,
112
+ setAuthUserPassword,
113
+ } from '@pikku/better-auth'
114
+ ```
115
+
116
+ Ban keeps its schema and its enforcement, in a plugin that does nothing else:
117
+
118
+ ```ts
119
+ import { ban } from '@pikku/better-auth'
120
+
121
+ betterAuth({ plugins: [ban()] })
122
+ ```
123
+
124
+ `ban()` adds `banned`, `banReason` and `banExpires` to `user`, refuses to create
125
+ a session for a banned user, and lapses an expired ban at the sign-in that would
126
+ otherwise be refused. It makes no authorization decision of its own, so it never
127
+ needs to know about scopes.
128
+
129
+ Breaking:
130
+
131
+ - Remove `admin()` from your better-auth `plugins`, and add `ban()` if you ban
132
+ users. `pikku db generate` writes the migration; `user.role` and
133
+ `session.impersonatedBy` are no longer declared by anything.
134
+ - `callAdminApi`, `AdminApiHttpWire`, `syncProjectedAdminRole`,
135
+ `projectedAdminRole` and `ADMIN_ROLE_SCOPES` are removed. `ADMIN_SCOPES`,
136
+ `ADMIN_SCOPE_ROOT` and `ADMIN_SCOPE_TREE` are unchanged.
137
+ - The `scaffold.userAdmin` codegen no longer fails without `admin()`. It now
138
+ fails only when there is no better-auth at all, and warns when `ban()` is
139
+ missing — banning is one capability of six, so the other five still generate.
140
+ - The scope on each function is now the whole authorization decision. Anywhere
141
+ that relied on `user.role` as a backstop no longer has one.
142
+
143
+ - 727671b: Make the public surface an artifact the CLI produces.
144
+
145
+ `@pikku/cli` now ships `surface.json`, computed when the CLI is built by
146
+ generating one application and one addon and reading what each `#pikku/*` leaf
147
+ exports, plus a curated `@pikku/core` entry point for people building on the
148
+ ecosystem. Consumers resolve it as `@pikku/cli/surface.json`.
149
+
150
+ `pikku all` writes the matching per-project overlay to
151
+ `<outDir>/surface-usage.gen.json`: how often each export is imported and which
152
+ source areas it was seen in. The counting happens inside the sweep the inspector
153
+ already makes over every source file, so a prebuild pays no extra pass.
154
+
155
+ - f25f4a2: Fix seven defects found taking one project through `pikku fabric` to deploy
156
+
157
+ **`deploy plan` rewrote the project's own scaffold.** Per-unit codegen re-runs
158
+ `pikku all` with `--outDir` pointed at a unit's `.pikku`, and scaffold imports
159
+ are computed against `config.outDir` — so `console.gen.ts` came back importing
160
+ `../../../../../.deploy/cloudflare/units/<unit>/.pikku/pikku-types.gen.js` and
161
+ the source stopped typechecking until the next ordinary `pikku all`.
162
+
163
+ A guard for this already existed in four generators and had never once fired:
164
+ `LocalVariablesService.get` runs values through `JSON.parse`, so
165
+ `PIKKU_DEPLOY_CODEGEN=1` arrived as the number `1` and every `=== '1'` test
166
+ was false. The comparison is fixed behind a shared `isDeployCodegen`, and the
167
+ real guard now sits in the file writer, which refuses writes _and removals_
168
+ under the scaffold directory for the duration of a per-unit run. Guarding the
169
+ writer rather than each generator matters here: seven further generators had no
170
+ guard at all, several write scaffold source and `.pikku` artifacts in the same
171
+ pass (so an early return would skip too much), and the legacy-scaffold pruners
172
+ delete from the source tree without going through a generator.
173
+
174
+ **`fabric validate` passed on a project that could not deploy.** Deploy clones
175
+ the repository, so a `pikkufabric.config.json` that exists only in the working
176
+ tree is absent exactly when it is needed, and the build container aborts with
177
+ `pikkufabric.config.json not found in repository root`. Validate now reports
178
+ that as an error, and its success line distinguishes "can be linked" from
179
+ "will deploy" instead of reporting unqualified success at a project that is not
180
+ linked yet.
181
+
182
+ **`description` reached `infra.json` as raw source.** `getPropertyValue` fell
183
+ back to `node.getText()`, which is indistinguishable from the value for a lone
184
+ literal — so nobody noticed that a description written as `'a ' + 'b'` arrived
185
+ with the quotes and the `+` still in it, and rendered that way in the console.
186
+ Compile-time constant strings are now folded, checker-free, so a node that
187
+ cannot be resolved statically still takes the old path.
188
+
189
+ **A wired addon that was not installed failed silently.** A missing package
190
+ makes `resolveAddonMeta` return null, which was caught and downgraded to a
191
+ warning; every `ref('<namespace>:…')` then resolved to nothing and the surface
192
+ was dead at runtime with nothing in the build output saying why. The generated
193
+ console is the common case. `wireAddon` now requires its package to be
194
+ installed (`PKU340`), the mirror of the existing `wireRemoteAddon` check whose
195
+ own docs already described this half as if it existed.
196
+
197
+ **The audit-table check demanded an unquoted identifier.** Kysely's schema
198
+ builder always quotes, so `create table "audit"` read as missing on the
199
+ projects most likely to have it. Both this and the better-auth table checks now
200
+ share one matcher that accepts each dialect's quoting — matched pairs only, so
201
+ `"audit'` is not a hit — plus an optional schema qualifier.
202
+
203
+ **Cloudflare bundles kept `pg`.** `getStubModules()` named `postgres` and
204
+ `kysely-postgres-js` but not `pg`, which is the more common driver in
205
+ application code, equally unreachable on a Worker, and additionally pulls at
206
+ `net`/`tls` and `pg-native`, which a Worker build cannot resolve at all.
207
+
208
+ **The deploy plan listed one secret twice.** Two `defineSecret` calls may
209
+ legally share a `secretId` under different local names — the auth scaffold's
210
+ `betterAuthSecret` alongside a hand-written one is the everyday case — and the
211
+ manifest mapped them straight through, so the plan printed two identical
212
+ `create` lines for one resource and `countUnchanged` counted it twice. Secrets
213
+ and variables are now deduplicated in the manifest itself, where variables were
214
+ already being collapsed by accident downstream.
215
+
216
+ - 20d8a39: Generate the schemas a first build used to leave out.
217
+
218
+ A contract type reaches the schema generator only through a file that imports
219
+ it, and for a type exported by nothing but its own function file that file is
220
+ the RPC internal map — which `pikku all` writes _after_ schemas. On a first
221
+ build there is no map to read yet, so those schemas came out missing from a run
222
+ that otherwise succeeded, and the RPC failed with `MissingSchemaError` on its
223
+ first call in a deployment. A second `pikku all` fixed it, which is why this
224
+ only ever bit fresh checkouts and CI.
225
+
226
+ `pikku all` now re-inspects and re-generates schemas when the build that just
227
+ wrote the RPC internal map for the first time left contract references
228
+ unresolved — the condition PKU463 already reports. Confined to that build: a
229
+ project whose references are unresolved for some other reason would otherwise
230
+ pay a second inspection on every run for a re-generation that cannot help it.
231
+
232
+ `@pikku/inspector` exports `unresolvedSchemaReferences(state)`, the check behind
233
+ PKU463, so the decision can be made without re-deriving it.
234
+
235
+ - 3561d67: feat(graph): per-item `forEach` fanout for declarative workflow graphs
236
+
237
+ A graph node can now run once per element of an upstream array:
238
+
239
+ ```ts
240
+ postVideo: {
241
+ forEach: 'getMyVideo', // or (ref) => ref('getMyVideo', 'rows')
242
+ mode: 'sequential', // optional, defaults to 'parallel'
243
+ input: (ref, template, $item) => ({ url: $item('URL VIDEO') }),
244
+ }
245
+ ```
246
+
247
+ Each element runs as its own step instance (`postVideo[0]`, `postVideo[1]`, …)
248
+ and the node's result is the ordered array of per-item results, so a fanned node
249
+ chains straight into another `forEach`. Downstream nodes wait for every item. A
250
+ non-array source fails the run loudly instead of coercing.
251
+
252
+ The change is additive: `forEach` and `mode` are new optional node fields, and
253
+ `$item` is appended after `template` so existing `input: (ref) => …` and
254
+ `input: (ref, template) => …` nodes are unchanged.
255
+
256
+ - a91c433: HTTP routes wired with `ref('ns:fn')` now record the addon function id as their own `pikkuFuncId`, the same way the CLI and channel wirings already do, instead of minting a per-route wrapper function and linking it back through `refTarget`. The `refTarget` field is gone from `HTTPWiringMeta`, and the runtime resolves a namespaced route function against the addon package's own metadata.
257
+ - 2b57ca8: A persona can name the `app` they sign into, and a browser run takes a url per app (`--app-url <app>=<url>`, or `appUrls` on the environment). Each actor's browser context navigates against its own app's base, so a product that is more than one frontend can be proved in one run — including a scenario that crosses from one app to the other. A run whose personas name an app nobody gave a url for is refused rather than browsing the wrong app's pages.
258
+ - 456c88b: Keep an addon function's contract on a route that reaches it through `ref()`, whether or not `.pikku` already exists.
259
+
260
+ The input and output types were read off the type checker, which can only see them once the consumer's own RPC map already lists the addon's functions — that is, on the second run. A first, cold generation widened the route's input to the whole `FlattenedRPCMap`, so the same sources produced a different http-map on CI than on a developer's machine, and a client compiled against the good one failed to build against the other. The addon's own metadata says what the contract is either way, and its published declaration file is where those names live.
261
+
262
+ - 727671b: `wireAddon` and `wireRemoteAddon` move from `#pikku/function` to `#pikku/addon`.
263
+
264
+ Installing an addon and authoring one are the same concept from opposite ends,
265
+ so they are one import: an application's `#pikku/addon` carries the two install
266
+ functions, an addon package's carries `pikkuAddonConfig`, `pikkuAddonServices`,
267
+ `pikkuAddonWireServices` and `AddonBaseServices`.
268
+
269
+ Two generation fixes came with it:
270
+
271
+ - `CredentialsMap` is generated as a type alias rather than an interface. An
272
+ interface has no implicit index signature, so it was never assignable to the
273
+ `Record<string, unknown>` that `GetCredential` is constrained by, and every
274
+ generated project reported two errors on its own function types.
275
+ - An unresolved `SingletonServices` type is now `PKU724` instead of a services
276
+ map with no entries in it. Written out, the empty map made every service
277
+ optional and the real failure resurfaced as unrelated "possibly undefined"
278
+ errors in files nobody had touched.
279
+
280
+ - Updated dependencies [7722ceb]
281
+ - Updated dependencies [375c1ff]
282
+ - Updated dependencies [02a70cd]
283
+ - Updated dependencies [aeef159]
284
+ - Updated dependencies [a281de6]
285
+ - Updated dependencies [266e3bc]
286
+ - Updated dependencies [02a70cd]
287
+ - Updated dependencies [786dae5]
288
+ - Updated dependencies [6eef0a0]
289
+ - Updated dependencies [3561d67]
290
+ - Updated dependencies [a91c433]
291
+ - Updated dependencies [02a70cd]
292
+ - Updated dependencies [9537f74]
293
+ - Updated dependencies [2b57ca8]
294
+ - Updated dependencies [266e3bc]
295
+ - Updated dependencies [9fce0f1]
296
+ - Updated dependencies [83683a0]
297
+ - Updated dependencies [456c88b]
298
+ - Updated dependencies [456c88b]
299
+ - Updated dependencies [c127273]
300
+ - @pikku/core@0.12.85
301
+
302
+ ## 0.12.60
303
+
304
+ ### Patch Changes
305
+
306
+ - 7406bfe: Rename the agent runtime from `AI*` to `Agent*` (#596)
307
+
308
+ `AI` described the model provider, not the thing being named. Every symbol that
309
+ belongs to the agent runtime now says `Agent`; the symbols that genuinely wrap a
310
+ model provider — `AIEmbeddingService`, `AIProviderOptions`, `AIEmbedParams`,
311
+ `AITranscriptionParams`, `AIGenerateImageParams` and their siblings, and the
312
+ `@pikku/ai-vercel` / `@pikku/ai-deepinfra` / `@pikku/ai-voice` packages — keep
313
+ their names.
314
+
315
+ **Wiring**
316
+ - `pikkuAIAgent` → `pikkuAgent`, `pikkuAIScorer` → `pikkuAgentScorer`,
317
+ `pikkuAIJudge` → `pikkuAgentJudge`
318
+ - `CoreAIAgent` → `CoreAgent`, `AIAgentInput` → `AgentInput`, `AIAgentStep` →
319
+ `AgentStep`, `AIMessage` → `AgentMessage`, and the rest of the agent types
320
+ - `AIAgentRunnerService` → `AgentRunnerService`, `AIStorageService` →
321
+ `AgentStorageService`, `AIRunStateService` → `AgentRunStateService`
322
+
323
+ **Entry points**
324
+
325
+ `@pikku/core/agent` → `@pikku/core/agent`, `@pikku/core/agent-scorer` →
326
+ `@pikku/core/agent-scorer`.
327
+
328
+ **Queues**
329
+
330
+ The scorer queues are now `agent-score-fast` and `agent-score-slow`. Drain the
331
+ old `ai-score-fast` / `ai-score-slow` queues before deploying — jobs still
332
+ sitting on them when the new workers start will never be picked up.
333
+
334
+ **Scaffolds**
335
+
336
+ The agent scaffold pikku wrote for your project — `<scaffold>/agent/agent.gen.ts`
337
+ and its schemas file — imports `@pikku/core/ai-agent`, which no longer exists. A
338
+ scaffold is normally written once and then left alone, so `pikku all` would find
339
+ it present and leave the broken import in place. It now deletes an agent scaffold
340
+ importing either removed entry point and regenerates it in the same run. Anything
341
+ you added to that file goes with it, so move local edits out first.
342
+
343
+ **Database**
344
+
345
+ The agent tables are renamed: `ai_threads`, `ai_message`, `ai_tool_call`,
346
+ `ai_working_memory`, `ai_run` and `ai_run_score` become `agent_threads`,
347
+ `agent_message`, `agent_tool_call`, `agent_working_memory`, `agent_run` and
348
+ `agent_run_score`, along with their indexes and the `ai_working_memory_pk`
349
+ constraint. The same rename applies to the MongoDB collections.
350
+
351
+ `ensurePikkuSchema` creates tables it cannot find, so an existing database will
352
+ get empty `agent_*` tables and leave the old data stranded in `ai_*`. Rename
353
+ them before the first boot on the new version:
354
+
355
+ ```sql
356
+ ALTER TABLE ai_threads RENAME TO agent_threads;
357
+ ALTER TABLE ai_message RENAME TO agent_message;
358
+ ALTER TABLE ai_tool_call RENAME TO agent_tool_call;
359
+ ALTER TABLE ai_working_memory RENAME TO agent_working_memory;
360
+ ALTER TABLE ai_run RENAME TO agent_run;
361
+ ALTER TABLE ai_run_score RENAME TO agent_run_score;
362
+ ```
363
+
364
+ - 6794681: Publish the ecosystem surface as per-area sub-barrels under `@pikku/core/ecosystem/*`, and point generated code, the CLI, the inspector and the runtime adapters at them.
365
+
366
+ 348 names that only generated code, the toolchain or a runtime adapter ever imports now have a second home on `@pikku/core/ecosystem/<area>` — one sub-barrel per area, matching how core already publishes its entrypoints, so no single barrel grows without bound and a consumer only pulls in the area it uses.
367
+
368
+ This step is additive: every name is still exported from the entrypoint it was published from before, so nothing downstream breaks. Removing them from the app-facing barrels is a later change, and needs a release carrying `./ecosystem/*` first.
369
+
370
+ - Updated dependencies [7406bfe]
371
+ - Updated dependencies [6794681]
372
+ - @pikku/core@0.12.84
373
+
1
374
  ## 0.12.59
2
375
 
3
376
  ### Patch Changes
@@ -44,25 +44,25 @@ node --import tsx src/benchmark.ts <target-dir> <iterations>
44
44
 
45
45
  **Dispatch map for `visitRoutes`** (all handlers expect CallExpression + Identifier):
46
46
 
47
- | Identifier | Handler |
48
- | ---------------------- | --------------------- |
49
- | `wireHTTP` | `addHTTPRoute` |
50
- | `wireHTTPRoutes` | `addHTTPRoutes` |
51
- | `wireScheduler` | `addSchedule` |
52
- | `wireTrigger` | `addTrigger` |
53
- | `wireTriggerSource` | `addTrigger` |
54
- | `wireQueueWorker` | `addQueueWorker` |
55
- | `wireChannel` | `addChannel` |
56
- | `wireCLI` | `addCLI` |
57
- | `pikkuCLIRender` | `addCLIRenderers` |
58
- | `wireMCPResource` | `addMCPResource` |
59
- | `wireMCPTool` | `addMCPTool` |
60
- | `wireMCPPrompt` | `addMCPPrompt` |
61
- | `wireWorkflowGraph` | `addWorkflowGraph` |
62
- | `defineSecret` | `addSecret` |
63
- | `defineCredential` | `addCredential` |
64
- | `defineScope` | `addScope` |
65
- | `defineVariable` | `addVariable` |
47
+ | Identifier | Handler |
48
+ | ------------------- | ------------------ |
49
+ | `wireHTTP` | `addHTTPRoute` |
50
+ | `wireHTTPRoutes` | `addHTTPRoutes` |
51
+ | `wireScheduler` | `addSchedule` |
52
+ | `wireTrigger` | `addTrigger` |
53
+ | `wireTriggerSource` | `addTrigger` |
54
+ | `wireQueueWorker` | `addQueueWorker` |
55
+ | `wireChannel` | `addChannel` |
56
+ | `wireCLI` | `addCLI` |
57
+ | `pikkuCLIRender` | `addCLIRenderers` |
58
+ | `wireMCPResource` | `addMCPResource` |
59
+ | `wireMCPTool` | `addMCPTool` |
60
+ | `wireMCPPrompt` | `addMCPPrompt` |
61
+ | `wireWorkflowGraph` | `addWorkflowGraph` |
62
+ | `defineSecret` | `addSecret` |
63
+ | `defineCredential` | `addCredential` |
64
+ | `defineScope` | `addScope` |
65
+ | `defineVariable` | `addVariable` |
66
66
 
67
67
  `addAuth` stays outside the map: it matches several identifiers
68
68
  (`betterAuthStatelessSession`, `betterAuthSession`) and gates them on
@@ -0,0 +1,2 @@
1
+ import type { AddWiring } from '../types.js';
2
+ export declare const addAgentScorer: AddWiring;
@@ -3,15 +3,15 @@ import { getPropertyValue } from '../utils/get-property-value.js';
3
3
  import { extractFunctionName } from '../utils/extract-function-name.js';
4
4
  import { ErrorCode } from '../error-codes.js';
5
5
  /**
6
- * `pikkuAIScorer` grades in code and `pikkuAIJudge` grades with a model, which
6
+ * `pikkuAgentScorer` grades in code and `pikkuAgentJudge` grades with a model, which
7
7
  * is the whole difference between the two lanes — so the lane is read off which
8
8
  * constructor was called rather than from a field an author could contradict.
9
9
  */
10
10
  const LANES = {
11
- pikkuAIScorer: 'fast',
12
- pikkuAIJudge: 'slow',
11
+ pikkuAgentScorer: 'fast',
12
+ pikkuAgentJudge: 'slow',
13
13
  };
14
- export const addAIScorer = (logger, node, checker, state) => {
14
+ export const addAgentScorer = (logger, node, checker, state) => {
15
15
  if (!ts.isCallExpression(node))
16
16
  return;
17
17
  const expression = node.expression;
@@ -1,4 +1,4 @@
1
1
  import * as ts from 'typescript';
2
2
  import type { AddWiring, InspectorLogger } from '../types.js';
3
3
  export declare function resolveWorkflowReferences(obj: ts.ObjectLiteralExpression, checker: ts.TypeChecker, agentName: string, logger: InspectorLogger): string[] | null;
4
- export declare const addAIAgent: AddWiring;
4
+ export declare const addAgent: AddWiring;
@@ -2,7 +2,7 @@ import * as ts from 'typescript';
2
2
  import { getPropertyValue, getCommonWireMetaData, } from '../utils/get-property-value.js';
3
3
  import { extractWireNames } from '../utils/post-process.js';
4
4
  import { extractFunctionName, funcIdToTypeName, } from '../utils/extract-function-name.js';
5
- import { resolveMiddleware, resolveChannelMiddleware, resolveAIMiddleware, } from '../utils/middleware.js';
5
+ import { resolveMiddleware, resolveChannelMiddleware, resolveAgentMiddleware, } from '../utils/middleware.js';
6
6
  import { resolvePermissions } from '../utils/permissions.js';
7
7
  import { ErrorCode } from '../error-codes.js';
8
8
  import { detectSchemaVendorOrError } from '../utils/detect-schema-vendor.js';
@@ -68,7 +68,7 @@ function resolveAgentReferences(obj, checker, agentName, logger) {
68
68
  for (const element of initializer.elements) {
69
69
  if (ts.isStringLiteral(element)) {
70
70
  logger.critical(ErrorCode.INVALID_VALUE, `AI agent '${agentName}' agents array contains a string literal '${element.text}'. ` +
71
- `Use an agent reference instead (e.g., import the pikkuAIAgent variable).`);
71
+ `Use an agent reference instead (e.g., import the pikkuAgent variable).`);
72
72
  continue;
73
73
  }
74
74
  if (ts.isIdentifier(element)) {
@@ -78,7 +78,7 @@ function resolveAgentReferences(obj, checker, agentName, logger) {
78
78
  continue;
79
79
  }
80
80
  logger.critical(ErrorCode.INVALID_VALUE, `AI agent '${agentName}' agents array contains identifier '${element.text}' ` +
81
- `that could not be resolved to a pikkuAIAgent.`);
81
+ `that could not be resolved to a pikkuAgent.`);
82
82
  }
83
83
  }
84
84
  return resolved.length > 0 ? resolved : null;
@@ -209,7 +209,7 @@ function resolveIdentifierToAgentName(identifier, checker) {
209
209
  if (ts.isVariableDeclaration(decl) && decl.initializer) {
210
210
  if (ts.isCallExpression(decl.initializer) &&
211
211
  ts.isIdentifier(decl.initializer.expression) &&
212
- decl.initializer.expression.text === 'pikkuAIAgent') {
212
+ decl.initializer.expression.text === 'pikkuAgent') {
213
213
  if (ts.isIdentifier(decl.name)) {
214
214
  return decl.name.text;
215
215
  }
@@ -240,14 +240,14 @@ function resolveScorerNames(obj, agentName, logger) {
240
240
  }
241
241
  return names.length > 0 ? names : null;
242
242
  }
243
- export const addAIAgent = (logger, node, checker, state, options) => {
243
+ export const addAgent = (logger, node, checker, state, options) => {
244
244
  if (!ts.isCallExpression(node)) {
245
245
  return;
246
246
  }
247
247
  const args = node.arguments;
248
248
  const firstArg = args[0];
249
249
  const expression = node.expression;
250
- if (!ts.isIdentifier(expression) || expression.text !== 'pikkuAIAgent') {
250
+ if (!ts.isIdentifier(expression) || expression.text !== 'pikkuAgent') {
251
251
  return;
252
252
  }
253
253
  if (!firstArg) {
@@ -383,7 +383,7 @@ export const addAIAgent = (logger, node, checker, state, options) => {
383
383
  }
384
384
  const middleware = resolveMiddleware(state, obj, tags, checker);
385
385
  const channelMiddleware = resolveChannelMiddleware(state, obj, tags, checker);
386
- const aiMiddleware = resolveAIMiddleware(state, obj, checker);
386
+ const agentMiddleware = resolveAgentMiddleware(state, obj, checker);
387
387
  const permissions = resolvePermissions(state, obj, tags, checker);
388
388
  state.serviceAggregation.usedFunctions.add(agentKey);
389
389
  extractWireNames(middleware).forEach((name) => state.serviceAggregation.usedMiddleware.add(name));
@@ -420,7 +420,7 @@ export const addAIAgent = (logger, node, checker, state, options) => {
420
420
  workingMemorySchema,
421
421
  middleware,
422
422
  channelMiddleware,
423
- aiMiddleware,
423
+ agentMiddleware,
424
424
  permissions,
425
425
  };
426
426
  // AI agent functions require platform services that aren't visible
@@ -428,10 +428,10 @@ export const addAIAgent = (logger, node, checker, state, options) => {
428
428
  const funcMeta = state.functions.meta[agentKey];
429
429
  if (funcMeta?.services) {
430
430
  for (const svc of [
431
- 'aiStorage',
432
- 'aiRunState',
431
+ 'agentStorage',
432
+ 'agentRunState',
433
433
  'agentRunService',
434
- 'aiAgentRunner',
434
+ 'agentRunner',
435
435
  ]) {
436
436
  if (!funcMeta.services.services.includes(svc)) {
437
437
  funcMeta.services.services.push(svc);
@@ -62,7 +62,7 @@ const readArrayProp = (obj, name) => {
62
62
  };
63
63
  /**
64
64
  * Read the callee name of a `plugins: [...]` entry. better-auth plugins are
65
- * factory calls (`bearer()`, `twoFactor({ ... })`, `admin()`); the entry's id
65
+ * factory calls (`bearer()`, `twoFactor({ ... })`, `ban()`); the entry's id
66
66
  * is the called function's name. Member-expression callees (`foo.bar()`) and
67
67
  * non-call entries are ignored.
68
68
  */
@@ -392,6 +392,11 @@ function processOptions(logger, node, typeChecker, inspectorState, inspectorOpti
392
392
  option.short = optProp.initializer.text;
393
393
  }
394
394
  break;
395
+ case 'type':
396
+ if (ts.isStringLiteral(optProp.initializer)) {
397
+ option.type = optProp.initializer.text;
398
+ }
399
+ break;
395
400
  case 'default':
396
401
  // Extract default value from expression
397
402
  if (ts.isStringLiteral(optProp.initializer)) {
@@ -3,7 +3,7 @@ import { detectSchemaVendorOrError } from '../utils/detect-schema-vendor.js';
3
3
  import { extractFunctionName, funcIdToTypeName, } from '../utils/extract-function-name.js';
4
4
  import { extractFunctionNode } from '../utils/extract-function-node.js';
5
5
  import { extractUsedWires } from '../utils/extract-services.js';
6
- import { formatVersionedId, parseVersionedId } from '@pikku/core';
6
+ import { formatVersionedId, parseVersionedId } from '@pikku/core/utils';
7
7
  /** Binding keys a `pikkuScenarioStep` may declare, in report order. */
8
8
  const SCENARIO_SURFACE_KEYS = [
9
9
  'browser',
@@ -415,6 +415,7 @@ export const addFunctions = (logger, node, checker, state, options) => {
415
415
  let workflowRetries;
416
416
  let workflowTimeout;
417
417
  let scenarioStepSurfaces;
418
+ let scenarioStepRequiresActor;
418
419
  let scenarioStepAddon;
419
420
  let scenarioStepTemplate;
420
421
  let scopes;
@@ -549,6 +550,13 @@ export const addFunctions = (logger, node, checker, state, options) => {
549
550
  scenarioStepSurfaces = declaredSurfaces.length
550
551
  ? declaredSurfaces
551
552
  : undefined;
553
+ // A browser binding cannot be provisioned without a window to open, so it
554
+ // requires an actor whether or not the step said so.
555
+ scenarioStepRequiresActor =
556
+ getPropertyValue(firstArg, 'actor') === true ||
557
+ declaredSurfaces.includes('browser')
558
+ ? true
559
+ : undefined;
552
560
  }
553
561
  scenarioStepTemplate = getPropertyValue(firstArg, 'template');
554
562
  scopes = getArrayPropertyValue(firstArg, 'scopes') ?? undefined;
@@ -992,6 +1000,7 @@ export const addFunctions = (logger, node, checker, state, options) => {
992
1000
  workflowRetries: workflowRetries ?? undefined,
993
1001
  workflowTimeout: workflowTimeout ?? undefined,
994
1002
  scenarioStepSurfaces,
1003
+ scenarioStepRequiresActor,
995
1004
  // `persona` is the default reading of an unmarked step, so it is left off
996
1005
  // rather than written into every step meta a project already has.
997
1006
  scenarioStepKind: scenarioStepKind && scenarioStepKind !== 'persona'