@akanjs/cli 3.0.0-alpha.67 → 3.0.0-alpha.69

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 (51) hide show
  1. package/.build-stamp +1 -1
  2. package/{agent.command-0p7p9ba8.js → agent.command-964bf8qg.js} +5 -5
  3. package/{application.command-5bafqeva.js → application.command-n45n18sc.js} +4 -4
  4. package/{applicationBuildRunner-jnjag4ay.js → applicationBuildRunner-af0wtspv.js} +5 -2
  5. package/buildBatch.proc.js +2 -2
  6. package/{capacitorApp-6mcsqh9k.js → capacitorApp-vnvnvdhf.js} +2 -2
  7. package/{cloud.command-d111e7st.js → cloud.command-kx1bh5yq.js} +7 -7
  8. package/{context.command-ypb8e1yj.js → context.command-g1a65x6j.js} +12 -12
  9. package/{guideline.command-g6nfb85d.js → guideline.command-xphyhvwh.js} +2 -2
  10. package/guidelines/conventions/conventions.instruction.md +51 -3
  11. package/guidelines/mcpRule/mcpRule.instruction.md +46 -5
  12. package/incrementalBuilder.proc.js +1 -1
  13. package/{index-sfbb92q2.js → index-0ngvvgry.js} +2 -2
  14. package/{index-9kbervcd.js → index-4rw4qhe6.js} +3 -3
  15. package/{index-x8d7krmm.js → index-8gybxemv.js} +5 -5
  16. package/{index-xesyg6bc.js → index-abyjt72y.js} +191 -27
  17. package/{index-amghj6k5.js → index-bqqts262.js} +1 -1
  18. package/{index-4e84gbad.js → index-e31ghfp5.js} +1 -1
  19. package/{index-5nj96dm3.js → index-fahkq20v.js} +3 -3
  20. package/{index-pbb97b16.js → index-hee7egtm.js} +1 -1
  21. package/{index-hjh8czbk.js → index-mkn5qagt.js} +5 -5
  22. package/{index-kvqvzgjq.js → index-nj3w0r34.js} +3 -3
  23. package/{index-vfnmsp1a.js → index-nkwmnqwn.js} +21 -4
  24. package/{index-77s16neb.js → index-p681w089.js} +2 -2
  25. package/{index-h33m7gbq.js → index-qt4nfr0n.js} +10 -10
  26. package/{index-w626d6zw.js → index-rb65xnw9.js} +4 -4
  27. package/{index-fc98hz1w.js → index-rbnpe8cp.js} +3 -3
  28. package/{index-bgjyden1.js → index-v5fdxdre.js} +2 -2
  29. package/{index-n2sz0qq3.js → index-va15r8h5.js} +2 -2
  30. package/{index-w627vcya.js → index-yg3hxk2k.js} +4 -4
  31. package/{index-4h99bj2e.js → index-ytaqtc04.js} +1 -1
  32. package/index.js +18 -18
  33. package/{library.command-j195dmpk.js → library.command-rfpd27yv.js} +3 -3
  34. package/{localRegistry.command-gz6mh6s0.js → localRegistry.command-pyxfe0fs.js} +6 -6
  35. package/{module.command-y306b14r.js → module.command-qhaxad0p.js} +5 -5
  36. package/{package.command-f7gdscaj.js → package.command-2k22q9nt.js} +3 -3
  37. package/package.json +3 -3
  38. package/{page.command-56kkr187.js → page.command-ymk9dqh4.js} +3 -3
  39. package/{primitive.command-9exysfem.js → primitive.command-9k45zpc1.js} +6 -6
  40. package/{quality.command-yace5341.js → quality.command-bf6vkxe5.js} +2 -2
  41. package/{repair.command-fyzwaa7c.js → repair.command-egvvm6xf.js} +5 -5
  42. package/{scalar.command-kdqx816z.js → scalar.command-bt1facyj.js} +4 -4
  43. package/templates/app/env/env.client.debug.ts.template +1 -5
  44. package/templates/app/env/env.client.develop.ts.template +1 -5
  45. package/templates/app/env/env.client.local.ts.template +1 -5
  46. package/templates/app/env/env.client.main.ts.template +1 -5
  47. package/templates/app/env/env.client.testing.ts.template +1 -5
  48. package/templates/app/env/env.client.type.ts +2 -6
  49. package/templates/workspaceRoot/package.json.template +1 -1
  50. package/{workflow.command-vs112teg.js → workflow.command-v1n3wg7v.js} +9 -9
  51. package/{workspace.command-rbzq1e56.js → workspace.command-yvvqvhzz.js} +18 -18
package/.build-stamp CHANGED
@@ -1 +1 @@
1
- 249086bcf505dc7322c8aa6cb51a76fe4c44d489ec19c4ebb0aaf15634915db8
1
+ f854deee45ba7fb5cde828e62164657386dfc13e55f0b7da760161ad709daa32
@@ -1,15 +1,15 @@
1
1
  // @bun
2
2
  import {
3
3
  AgentScript
4
- } from "./index-fc98hz1w.js";
5
- import"./index-n2sz0qq3.js";
6
- import"./index-4h99bj2e.js";
4
+ } from "./index-rbnpe8cp.js";
5
+ import"./index-va15r8h5.js";
6
+ import"./index-ytaqtc04.js";
7
7
  import"./index-j37qq1f2.js";
8
8
  import {
9
9
  Workspace,
10
10
  command
11
- } from "./index-4e84gbad.js";
12
- import"./index-vfnmsp1a.js";
11
+ } from "./index-e31ghfp5.js";
12
+ import"./index-nkwmnqwn.js";
13
13
  import"./index-f39512t6.js";
14
14
  import"./index-mxvakhsm.js";
15
15
  import"./index-xys926f2.js";
@@ -4,8 +4,8 @@ import {
4
4
  } from "./index-0wae5ebk.js";
5
5
  import {
6
6
  ApplicationScript
7
- } from "./index-hjh8czbk.js";
8
- import"./index-77s16neb.js";
7
+ } from "./index-mkn5qagt.js";
8
+ import"./index-p681w089.js";
9
9
  import {
10
10
  getMobileTargetChoices
11
11
  } from "./index-76rn3g2c.js";
@@ -15,10 +15,10 @@ import {
15
15
  Sys,
16
16
  Workspace,
17
17
  command
18
- } from "./index-4e84gbad.js";
18
+ } from "./index-e31ghfp5.js";
19
19
  import"./index-fgc8r6dj.js";
20
20
  import"./index-5vy2jzar.js";
21
- import"./index-vfnmsp1a.js";
21
+ import"./index-nkwmnqwn.js";
22
22
  import"./index-f39512t6.js";
23
23
  import"./index-mxvakhsm.js";
24
24
  import"./index-1577bej2.js";
@@ -2,9 +2,10 @@
2
2
  import {
3
3
  AllRoutesBuilder,
4
4
  CsrArtifactBuilder,
5
+ FontPruner,
5
6
  SsrBaseArtifactBuilder,
6
7
  precompressArtifacts
7
- } from "./index-xesyg6bc.js";
8
+ } from "./index-abyjt72y.js";
8
9
  import"./index-xjd3rqzj.js";
9
10
  import"./index-qnv0aqmm.js";
10
11
  import"./index-5vy2jzar.js";
@@ -23,6 +24,7 @@ var BUILD_PHASE_EMOJIS = {
23
24
  backend: "\uD83D\uDCE6",
24
25
  ssr: "\uD83E\uDDED",
25
26
  csr: "\uD83C\uDFA8",
27
+ assets: "\u2702\uFE0F",
26
28
  compress: "\uD83D\uDDDC\uFE0F",
27
29
  metadata: "\uD83D\uDCDD"
28
30
  };
@@ -58,7 +60,7 @@ class ApplicationBuildRunner {
58
60
  }
59
61
  async build({ spinner = false } = {}) {
60
62
  const phaseOptions = { spinner };
61
- const { web } = await this.#app.getConfig();
63
+ const { web, assets } = await this.#app.getConfig();
62
64
  await this.#runPhase("prepare", "Preparing output directory", () => this.#app.prepareCommand("build"), undefined, {
63
65
  spinner
64
66
  });
@@ -67,6 +69,7 @@ class ApplicationBuildRunner {
67
69
  await this.#runPhase("backend", "Compiling backend", () => this.#buildBackend(), (result) => `${result.entrypoints} entrypoints, ${result.outputs} outputs`, phaseOptions);
68
70
  await this.#runPhase("ssr", "Building SSR route artifacts", async () => web.ssr ? await this.#buildSsr() : null, (result) => result ? `${result.allRoutes.manifest.routeIds.length} routes, ${result.allRoutes.manifest.knownEntries.length} entries` : web.ssr ? "skipped" : "disabled by akan.config.ts web.ssr", phaseOptions);
69
71
  await this.#runPhase("csr", "Building CSR assets", async () => web.csr ? await this.#buildCsr() : null, (result) => result?.outputDir ?? (web.csr ? "skipped" : "disabled by akan.config.ts web.csr"), phaseOptions);
72
+ await this.#runPhase("assets", "Trimming unread static assets", async () => assets.pruneFonts ? await new FontPruner(this.#app, assets).prune() : null, (result) => result ? `${result.removed.length} font file(s) dropped, ${ApplicationBuildRunner.formatBytes(result.freedBytes)} freed; ${result.kept.length} kept` : "disabled by akan.config.ts assets.pruneFonts", phaseOptions);
70
73
  await this.#runPhase("compress", "Compressing static assets", () => precompressArtifacts(this.#app), (result) => result.files > 0 ? `${result.files} files, ${ApplicationBuildRunner.formatBytes(result.inputBytes)} -> gzip ${ApplicationBuildRunner.formatBytes(result.outputBytes)} / br ${ApplicationBuildRunner.formatBytes(result.brotliBytes)}` : "no files", phaseOptions);
71
74
  await this.#runPhase("metadata", "Writing production metadata", () => this.#buildAppMeta(), undefined, {
72
75
  spinner
@@ -5,14 +5,14 @@ import {
5
5
  FontOptimizer,
6
6
  PagesBundleBuilder,
7
7
  SsrBaseArtifactBuilder
8
- } from "./index-xesyg6bc.js";
8
+ } from "./index-abyjt72y.js";
9
9
  import"./index-xjd3rqzj.js";
10
10
  import"./index-qnv0aqmm.js";
11
11
  import"./index-5vy2jzar.js";
12
12
  import {
13
13
  AppExecutor,
14
14
  WorkspaceExecutor
15
- } from "./index-vfnmsp1a.js";
15
+ } from "./index-nkwmnqwn.js";
16
16
  import"./index-f39512t6.js";
17
17
  import"./index-mxvakhsm.js";
18
18
  import"./index-1577bej2.js";
@@ -25,9 +25,9 @@ import {
25
25
  selectLocalDevHost,
26
26
  sortIosRunTargets,
27
27
  writeRootCapacitorConfig
28
- } from "./index-pbb97b16.js";
28
+ } from "./index-hee7egtm.js";
29
29
  import"./index-76rn3g2c.js";
30
- import"./index-vfnmsp1a.js";
30
+ import"./index-nkwmnqwn.js";
31
31
  import"./index-f39512t6.js";
32
32
  import"./index-mxvakhsm.js";
33
33
  import"./index-1577bej2.js";
@@ -1,22 +1,22 @@
1
1
  // @bun
2
2
  import {
3
3
  CloudScript
4
- } from "./index-x8d7krmm.js";
5
- import"./index-9kbervcd.js";
6
- import"./index-sfbb92q2.js";
4
+ } from "./index-8gybxemv.js";
5
+ import"./index-4rw4qhe6.js";
6
+ import"./index-0ngvvgry.js";
7
7
  import {
8
8
  GlobalConfig
9
9
  } from "./index-sh01r3pm.js";
10
- import"./index-hjh8czbk.js";
11
- import"./index-77s16neb.js";
10
+ import"./index-mkn5qagt.js";
11
+ import"./index-p681w089.js";
12
12
  import"./index-76rn3g2c.js";
13
13
  import {
14
14
  Workspace,
15
15
  command
16
- } from "./index-4e84gbad.js";
16
+ } from "./index-e31ghfp5.js";
17
17
  import"./index-fgc8r6dj.js";
18
18
  import"./index-5vy2jzar.js";
19
- import"./index-vfnmsp1a.js";
19
+ import"./index-nkwmnqwn.js";
20
20
  import"./index-f39512t6.js";
21
21
  import"./index-mxvakhsm.js";
22
22
  import"./index-1577bej2.js";
@@ -1,25 +1,25 @@
1
1
  // @bun
2
2
  import {
3
3
  ContextScript
4
- } from "./index-h33m7gbq.js";
5
- import"./index-kvqvzgjq.js";
6
- import"./index-5nj96dm3.js";
7
- import"./index-bgjyden1.js";
8
- import"./index-w626d6zw.js";
9
- import"./index-w627vcya.js";
4
+ } from "./index-qt4nfr0n.js";
5
+ import"./index-nj3w0r34.js";
6
+ import"./index-fahkq20v.js";
7
+ import"./index-v5fdxdre.js";
8
+ import"./index-rb65xnw9.js";
9
+ import"./index-yg3hxk2k.js";
10
10
  import"./index-ss469dec.js";
11
- import"./index-amghj6k5.js";
12
- import"./index-pbb97b16.js";
11
+ import"./index-bqqts262.js";
12
+ import"./index-hee7egtm.js";
13
13
  import"./index-sh01r3pm.js";
14
- import"./index-n2sz0qq3.js";
15
- import"./index-4h99bj2e.js";
14
+ import"./index-va15r8h5.js";
15
+ import"./index-ytaqtc04.js";
16
16
  import"./index-j37qq1f2.js";
17
17
  import"./index-76rn3g2c.js";
18
18
  import {
19
19
  Workspace,
20
20
  command
21
- } from "./index-4e84gbad.js";
22
- import"./index-vfnmsp1a.js";
21
+ } from "./index-e31ghfp5.js";
22
+ import"./index-nkwmnqwn.js";
23
23
  import"./index-f39512t6.js";
24
24
  import"./index-mxvakhsm.js";
25
25
  import"./index-xys926f2.js";
@@ -10,8 +10,8 @@ import {
10
10
  command,
11
11
  runner,
12
12
  script
13
- } from "./index-4e84gbad.js";
14
- import"./index-vfnmsp1a.js";
13
+ } from "./index-e31ghfp5.js";
14
+ import"./index-nkwmnqwn.js";
15
15
  import"./index-f39512t6.js";
16
16
  import"./index-mxvakhsm.js";
17
17
  import {
@@ -366,6 +366,40 @@ const config: AppConfig = { docker: "FROM oven/bun:1-slim\n…" }; // verbatim,
366
366
  - `AkanAppConfig.docker` is the resolved declaration; `AkanAppConfig.dockerfile` is the text `akan build` writes
367
367
  to `dist/apps/<app>/Dockerfile`.
368
368
 
369
+ ## Shipped Assets — `assets` In `akan.config.ts`
370
+
371
+ `akan build` copies the whole `public/` tree into `dist`, lib assets dereferenced, and that copy is the image.
372
+ **`assets: { pruneFonts, keepFonts }`** trims the fonts out of it that nothing reads. **Source trees are never
373
+ touched** — an app's and a lib's own `public/` keep every file, because one shared font folder is picked over
374
+ differently by every app that mounts it and by other repos.
375
+
376
+ ```ts
377
+ const config: LibConfig = { assets: { keepFonts: ["fonts/Assistant-*.woff2"] } }; // libs/<lib>/akan.config.ts
378
+ const config: AppConfig = { assets: { pruneFonts: false } }; // emergency valve, not the normal escape hatch
379
+ ```
380
+
381
+ - **A font with `optimize` on is a build input, not a runtime asset.** `FontOptimizer` subsets it into
382
+ `.akan/artifact/fonts` and the emitted CSS points at `/_akan/fonts/*`, which `WebRouter` serves from the
383
+ artifact — so the source in `public/` is never opened again. That is the bulk of what this drops, and it
384
+ applies to the fonts the app *does* use, not only the ones it does not.
385
+ - **The keep-set is derived per app, per build; there is no list of fonts to drop.** An exclude list would rot
386
+ the moment another app or repo started using one of them, and nobody would know to update it. A font survives
387
+ because ① its font declares `optimize: false`, so `FontCss.getRuntimeCss` emits the raw src; ② something
388
+ references its filename — anything under `public/`, the compiled stylesheet, a client/server bundle, the CSR
389
+ shell; or ③ a `keepFonts` glob names it.
390
+ - **`keepFonts` belongs to the `akan.config.ts` that owns the font**, written against that lib's or app's own
391
+ `public/` (`"fonts/X.woff2"`, resolved to `libs/<lib>/fonts/X.woff2`). A lib shared across repos carries the
392
+ reason its own CSS needs a font, instead of every mounting app rediscovering it in production.
393
+ - **A reference from a build bundle is ignored for an already-subset font.** Every route file's `fonts`
394
+ declaration is inlined into the pages bundle, the client chunks and the CSR shell, so a declared source is in
395
+ all three whether or not anything loads it. `public/` and the compiled CSS are read as authoritative.
396
+ - **A generated manifest that lists every public asset keeps every font it names** — a service-worker precache
397
+ file is the usual one. That is a real reference, not a false positive, so the build reports it at `info`:
398
+ read the `[font-prune] kept …` line before concluding the prune does nothing.
399
+ - Matching is by filename, including the percent-encoded spelling, so a `url()` survives however it is written.
400
+ - The phase is `assets`, between `csr` and `compress`. An api-only build (`web: false`) copies no `public/` and
401
+ the phase finds nothing to do.
402
+
369
403
  ## React Components And Styling (`**/*.tsx`)
370
404
 
371
405
  - Components are `export const X = ({ … }: XProps) => { return (…); };` — arrow const with a block body. `export default` is reserved for pages, layouts, and `lazy()` targets.
@@ -657,12 +691,26 @@ that declares a real guard is published; one that declares none is refused, and
657
691
  `Public`. The guards are already the authorization decision, so a second switch would say nothing they do not —
658
692
  while guaranteeing that every endpoint added later is invisible to agents until somebody remembers it.
659
693
 
694
+ - **`mcp: false` keeps an endpoint off the shelf without touching its guards.** Guards answer "may an agent call
695
+ this"; they cannot answer "does this belong on a shelf", and a step of a UI-driven state machine
696
+ (`requestPhoneCodeForSignin`) is perfectly guarded and still a mistake for a model to reach. Write it in the
697
+ signal option (`mutation(Boolean, { guards: [Every], mcp: false })`, `init({ guards: [SignedIn], mcp: false })`
698
+ — which covers that slice's list and insight together), or as an `mcp` map on `slice()` that **mirrors the
699
+ `guards` map key for key** (`mcp: { cru: false }`), with the same `cru` fallbacks and the same scope: the root
700
+ slice and generated CRUD only, never a named slice or a custom endpoint. It is an opt-**out**, so everything
701
+ added later still publishes. **It is curation, not authorization — HTTP serves the endpoint exactly as before.**
702
+ - **Narrow by cost, and read the boot log first.** MCP has no shared component section and forbids a `$ref` across
703
+ entries, so every entry inlines the full schema of every model it mentions, and the listing is re-sent whole to
704
+ every agent that connects. `MCP catalogue: … · listing 214KB` plus a per-signal `MCP catalogue cost:` line says
705
+ where it went. A plain 21-field model costs 12.6KB over eight entries; `mcp: { cru: false }` takes it to 4.7KB,
706
+ because the generated writes carry the input *and* the full model.
660
707
  - Settings live in the app's `lib/option.ts` — `option.setMcp({ enabled, readOnly, path, version, instructions,
661
708
  allowedOrigins, pageSize, language, auth })`, **not `main.ts`**. Every lib's option is read in mount order with
662
709
  the app's last, and each field has an `AKAN_MCP_*` env spelling the option overrides.
663
- - **The refusals are fail-closed**: an endpoint with no `guards`, a mutation with no real guard (`[Public]` is
664
- having none), `pubsub` and `message`, an `Any` or `Upload` return, a file upload, and a required `Any` argument.
665
- A `prompt` also refuses a list argument and any `Any` argument.
710
+ - **The refusals are fail-closed**: a declared `mcp: false`, an endpoint with no `guards`, a mutation with no real guard (`[Public]` is
711
+ having none), `pubsub` and `message`, an `Any` or `Upload` return, a file upload, a required `Any` argument, and
712
+ the generated `light<Model>` read — it is `<Model>` in a smaller shape, so one read never costs two entries of
713
+ every listing. A `prompt` also refuses a list argument and any `Any` argument.
666
714
  - **Every refusal is named in the boot log**, with a `MCP catalogue: tools=… prompts=…` count. Read that line
667
715
  first when a tool you expected is missing — with no opt-in to notice, it is the only place the answer exists.
668
716
  The boot log also names every published entry with no dictionary `.desc()`: an agent picks a tool by its
@@ -14,6 +14,36 @@ authorization decision and `filterForAccount` re-reads them per caller on every
14
14
  switch says nothing the guards do not — while guaranteeing that every endpoint added later is invisible to agents
15
15
  until somebody remembers it.
16
16
 
17
+ ## Keeping An Endpoint Off The Shelf — `mcp: false`
18
+
19
+ Guards answer "may an agent call this". They do not answer "does this belong on a shelf", and those are different
20
+ questions: a step of a UI-driven state machine (`requestPhoneCodeForSignin`, `setPasswordInPrepareUser`) is
21
+ perfectly guarded, perfectly callable, and a model would only ever call it by mistake. **`mcp: false` is that
22
+ second answer, and it is an opt-*out*: everything still publishes by default, so an endpoint added later is
23
+ visible without anyone remembering it.**
24
+
25
+ ```ts
26
+ requestPhoneCodeForSignin: mutation(Boolean, { guards: [Every], mcp: false }),
27
+ inTodo: init({ guards: [SignedIn], mcp: false }), // the slice's list and insight together
28
+ export class FileSlice extends slice(srv.file, {
29
+ guards: { root: Admin, get: SignedIn, cru: SignedIn },
30
+ mcp: { cru: false }, // reads yes, generated writes no
31
+ }) {}
32
+ ```
33
+
34
+ - **It is curation, not authorization.** HTTP serves the endpoint exactly as before and the guards are still the
35
+ only thing deciding who may call it. Never write `mcp: false` where you meant a guard.
36
+ - **The `mcp` map on `slice()` mirrors the `guards` map above it** — same keys (`root`, `get`, `cru`, `create`,
37
+ `update`, `remove`), same fallbacks (`create`/`update`/`remove` inherit `cru`), and the same scope: it narrows
38
+ the root slice and the generated CRUD, and never reaches a named slice or a custom endpoint. Those declare
39
+ their own `mcp` beside their own `guards`. The bare `mcp: false` is every key at once, still within that scope.
40
+ - **`mcp: true` is the default and is a no-op**; write it only to say out loud that an entry is deliberately on
41
+ the shelf. It does not override a shape refusal (an `Any` return stays refused) and it cannot publish something
42
+ the guard rules keep out.
43
+ - **Reach for it by cost, not by taste.** Every entry inlines the schema of every model it mentions, so a plain
44
+ 21-field model with one named slice costs 12.6KB across its eight entries. `mcp: { cru: false }` on that model
45
+ takes it to 4.7KB — the write entries carry both the input *and* the full model, and are 63% of it.
46
+
17
47
  ## Configuration
18
48
  Settings live in the app's `lib/option.ts` — `option.setMcp({ … })`, taking `enabled`, `readOnly`, `path`,
19
49
  `version`, `instructions`, `allowedOrigins`, `pageSize`, `language`, `legacyTextBlock`, and `auth`. **Not `main.ts`**: the gateway
@@ -67,13 +97,23 @@ export class TaskEndpoint extends endpoint(srv.task, ({ mutation, prompt }) => (
67
97
  ```
68
98
 
69
99
  ## Refusals And Wire Behaviour
100
+ - **`mcp: false` is read first**, because it is the one answer nobody had to derive — somebody stated it. Its
101
+ reason says "HTTP still serves it", because that is the sentence that stops the next reader treating it as a lock.
70
102
  - **The refusals are fail-closed**: **an endpoint that declares no `guards` at all** (nobody decided who may reach
71
103
  it), **a mutation with no real `guards`** (`[Public]` is having none, spelled out — it answers true
72
104
  unconditionally), `pubsub` and `message` (their internal args read a socket an MCP request does not have), an
73
- `Any` or `Upload` return, a file upload, and **an argument typed `Any` that must be filled**.
105
+ `Any` or `Upload` return, a file upload, **an argument typed `Any` that must be filled**, and the generated
106
+ **`light<Model>` read** — it returns the same document as `<Model>` under the same guards, in a shape trimmed
107
+ for a page's payload, so publishing both put two entries per model in a listing an agent pays for every turn
108
+ and gave it nothing but the word "light" to choose between them.
74
109
  A `prompt` refuses two more, because its `arguments` is one string per name with no schema beside it: a **list
75
110
  argument**, which could never carry a second value, and **any `Any` argument** — a tool leaves that out of its
76
111
  schema, and a prompt has no schema to leave it out of.
112
+ - **The boot log sizes the catalogue and says which signals it went to** — `MCP catalogue: tools=48 … · listing
113
+ 214KB` and `MCP catalogue cost: user 27/71KB · file 6/22KB · …`, heaviest first. Read it before narrowing
114
+ anything: the number is nobody's intuition, because MCP has no shared component section and forbids a `$ref`
115
+ across entries, so **every entry inlines the full schema of every model it mentions** and a listing is re-sent
116
+ whole to every agent that connects, before its first turn. Past 100KB it says so as a `warn`.
77
117
  - **Every refusal is named in the boot log**: one `warn` per endpoint plus a `MCP catalogue: tools=… prompts=…`
78
118
  count. Read that line first when a tool you expected is missing — and it is the *only* place the answer exists,
79
119
  because there is no absent opt-in to notice. The API explorer badges the same rule per endpoint (`MCP` /
@@ -144,10 +184,11 @@ export class TaskEndpoint extends endpoint(srv.task, ({ mutation, prompt }) => (
144
184
  - **An expired or wrongly-audienced bearer token is refused up front**, so an agent is told to authenticate rather
145
185
  than that the tool does not exist. Its **signature is not checked** — that needs your app's own secret — so a
146
186
  token signed wrong, like an opaque one, still degrades to an anonymous caller.
147
- - **Resource URIs**: `akan://<model>/{id}`, `akan://<model>/light/{id}`, `akan://<model>/list` for the model's own
148
- list, and `akan://<model>/list/<sliceKey>` for a slice's. The root list takes no third segment on purpose — any
149
- token there is one a slice could also be named. **Those four are the whole set**, so only the generated reads are
150
- addressable: a custom endpoint keeps its tool and gets no resource template.
187
+ - **Resource URIs**: `akan://<model>/{id}`, `akan://<model>/list` for the model's own list, and
188
+ `akan://<model>/list/<sliceKey>` for a slice's. The root list takes no third segment on purpose — any token
189
+ there is one a slice could also be named. **Those three are the whole set**, so only the generated reads that
190
+ publish are addressable: a custom endpoint keeps its tool and gets no resource template, and the refused
191
+ `light<Model>` read has no address either.
151
192
  - **The catalogue is one language**, `en` unless `language` says otherwise: it is built once at boot and cached by
152
193
  clients, so there is no `Accept-Language` negotiation.
153
194
 
@@ -16,7 +16,7 @@ import {
16
16
  import {
17
17
  AppExecutor,
18
18
  WorkspaceExecutor
19
- } from "./index-vfnmsp1a.js";
19
+ } from "./index-nkwmnqwn.js";
20
20
  import"./index-f39512t6.js";
21
21
  import"./index-mxvakhsm.js";
22
22
  import"./index-1577bej2.js";
@@ -2,10 +2,10 @@
2
2
  import {
3
3
  runner,
4
4
  script
5
- } from "./index-4e84gbad.js";
5
+ } from "./index-e31ghfp5.js";
6
6
  import {
7
7
  PkgExecutor
8
- } from "./index-vfnmsp1a.js";
8
+ } from "./index-nkwmnqwn.js";
9
9
  import {
10
10
  TypeScriptDependencyScanner
11
11
  } from "./index-46tjzh6s.js";
@@ -7,14 +7,14 @@ import {
7
7
  } from "./index-sh01r3pm.js";
8
8
  import {
9
9
  openBrowser
10
- } from "./index-hjh8czbk.js";
10
+ } from "./index-mkn5qagt.js";
11
11
  import {
12
12
  runner
13
- } from "./index-4e84gbad.js";
13
+ } from "./index-e31ghfp5.js";
14
14
  import {
15
15
  AppExecutor,
16
16
  WorkspaceExecutor
17
- } from "./index-vfnmsp1a.js";
17
+ } from "./index-nkwmnqwn.js";
18
18
 
19
19
  // pkgs/@akanjs/cli/npmRegistry.ts
20
20
  var defaultNpmRegistry = "https://registry.npmjs.org";
@@ -1,10 +1,10 @@
1
1
  // @bun
2
2
  import {
3
3
  CloudRunner
4
- } from "./index-9kbervcd.js";
4
+ } from "./index-4rw4qhe6.js";
5
5
  import {
6
6
  PackageScript
7
- } from "./index-sfbb92q2.js";
7
+ } from "./index-0ngvvgry.js";
8
8
  import {
9
9
  AiSession,
10
10
  CloudApi,
@@ -12,13 +12,13 @@ import {
12
12
  } from "./index-sh01r3pm.js";
13
13
  import {
14
14
  ApplicationScript
15
- } from "./index-hjh8czbk.js";
15
+ } from "./index-mkn5qagt.js";
16
16
  import {
17
17
  script
18
- } from "./index-4e84gbad.js";
18
+ } from "./index-e31ghfp5.js";
19
19
  import {
20
20
  PkgExecutor
21
- } from "./index-vfnmsp1a.js";
21
+ } from "./index-nkwmnqwn.js";
22
22
 
23
23
  // pkgs/@akanjs/cli/cloud/cloud.script.ts
24
24
  import { Logger } from "akanjs/common";