@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.
- package/.build-stamp +1 -1
- package/{agent.command-0p7p9ba8.js → agent.command-964bf8qg.js} +5 -5
- package/{application.command-5bafqeva.js → application.command-n45n18sc.js} +4 -4
- package/{applicationBuildRunner-jnjag4ay.js → applicationBuildRunner-af0wtspv.js} +5 -2
- package/buildBatch.proc.js +2 -2
- package/{capacitorApp-6mcsqh9k.js → capacitorApp-vnvnvdhf.js} +2 -2
- package/{cloud.command-d111e7st.js → cloud.command-kx1bh5yq.js} +7 -7
- package/{context.command-ypb8e1yj.js → context.command-g1a65x6j.js} +12 -12
- package/{guideline.command-g6nfb85d.js → guideline.command-xphyhvwh.js} +2 -2
- package/guidelines/conventions/conventions.instruction.md +51 -3
- package/guidelines/mcpRule/mcpRule.instruction.md +46 -5
- package/incrementalBuilder.proc.js +1 -1
- package/{index-sfbb92q2.js → index-0ngvvgry.js} +2 -2
- package/{index-9kbervcd.js → index-4rw4qhe6.js} +3 -3
- package/{index-x8d7krmm.js → index-8gybxemv.js} +5 -5
- package/{index-xesyg6bc.js → index-abyjt72y.js} +191 -27
- package/{index-amghj6k5.js → index-bqqts262.js} +1 -1
- package/{index-4e84gbad.js → index-e31ghfp5.js} +1 -1
- package/{index-5nj96dm3.js → index-fahkq20v.js} +3 -3
- package/{index-pbb97b16.js → index-hee7egtm.js} +1 -1
- package/{index-hjh8czbk.js → index-mkn5qagt.js} +5 -5
- package/{index-kvqvzgjq.js → index-nj3w0r34.js} +3 -3
- package/{index-vfnmsp1a.js → index-nkwmnqwn.js} +21 -4
- package/{index-77s16neb.js → index-p681w089.js} +2 -2
- package/{index-h33m7gbq.js → index-qt4nfr0n.js} +10 -10
- package/{index-w626d6zw.js → index-rb65xnw9.js} +4 -4
- package/{index-fc98hz1w.js → index-rbnpe8cp.js} +3 -3
- package/{index-bgjyden1.js → index-v5fdxdre.js} +2 -2
- package/{index-n2sz0qq3.js → index-va15r8h5.js} +2 -2
- package/{index-w627vcya.js → index-yg3hxk2k.js} +4 -4
- package/{index-4h99bj2e.js → index-ytaqtc04.js} +1 -1
- package/index.js +18 -18
- package/{library.command-j195dmpk.js → library.command-rfpd27yv.js} +3 -3
- package/{localRegistry.command-gz6mh6s0.js → localRegistry.command-pyxfe0fs.js} +6 -6
- package/{module.command-y306b14r.js → module.command-qhaxad0p.js} +5 -5
- package/{package.command-f7gdscaj.js → package.command-2k22q9nt.js} +3 -3
- package/package.json +3 -3
- package/{page.command-56kkr187.js → page.command-ymk9dqh4.js} +3 -3
- package/{primitive.command-9exysfem.js → primitive.command-9k45zpc1.js} +6 -6
- package/{quality.command-yace5341.js → quality.command-bf6vkxe5.js} +2 -2
- package/{repair.command-fyzwaa7c.js → repair.command-egvvm6xf.js} +5 -5
- package/{scalar.command-kdqx816z.js → scalar.command-bt1facyj.js} +4 -4
- package/templates/app/env/env.client.debug.ts.template +1 -5
- package/templates/app/env/env.client.develop.ts.template +1 -5
- package/templates/app/env/env.client.local.ts.template +1 -5
- package/templates/app/env/env.client.main.ts.template +1 -5
- package/templates/app/env/env.client.testing.ts.template +1 -5
- package/templates/app/env/env.client.type.ts +2 -6
- package/templates/workspaceRoot/package.json.template +1 -1
- package/{workflow.command-vs112teg.js → workflow.command-v1n3wg7v.js} +9 -9
- package/{workspace.command-rbzq1e56.js → workspace.command-yvvqvhzz.js} +18 -18
package/.build-stamp
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
|
|
1
|
+
f854deee45ba7fb5cde828e62164657386dfc13e55f0b7da760161ad709daa32
|
|
@@ -1,15 +1,15 @@
|
|
|
1
1
|
// @bun
|
|
2
2
|
import {
|
|
3
3
|
AgentScript
|
|
4
|
-
} from "./index-
|
|
5
|
-
import"./index-
|
|
6
|
-
import"./index-
|
|
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-
|
|
12
|
-
import"./index-
|
|
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-
|
|
8
|
-
import"./index-
|
|
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-
|
|
18
|
+
} from "./index-e31ghfp5.js";
|
|
19
19
|
import"./index-fgc8r6dj.js";
|
|
20
20
|
import"./index-5vy2jzar.js";
|
|
21
|
-
import"./index-
|
|
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-
|
|
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
|
package/buildBatch.proc.js
CHANGED
|
@@ -5,14 +5,14 @@ import {
|
|
|
5
5
|
FontOptimizer,
|
|
6
6
|
PagesBundleBuilder,
|
|
7
7
|
SsrBaseArtifactBuilder
|
|
8
|
-
} from "./index-
|
|
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-
|
|
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-
|
|
28
|
+
} from "./index-hee7egtm.js";
|
|
29
29
|
import"./index-76rn3g2c.js";
|
|
30
|
-
import"./index-
|
|
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-
|
|
5
|
-
import"./index-
|
|
6
|
-
import"./index-
|
|
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-
|
|
11
|
-
import"./index-
|
|
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-
|
|
16
|
+
} from "./index-e31ghfp5.js";
|
|
17
17
|
import"./index-fgc8r6dj.js";
|
|
18
18
|
import"./index-5vy2jzar.js";
|
|
19
|
-
import"./index-
|
|
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-
|
|
5
|
-
import"./index-
|
|
6
|
-
import"./index-
|
|
7
|
-
import"./index-
|
|
8
|
-
import"./index-
|
|
9
|
-
import"./index-
|
|
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-
|
|
12
|
-
import"./index-
|
|
11
|
+
import"./index-bqqts262.js";
|
|
12
|
+
import"./index-hee7egtm.js";
|
|
13
13
|
import"./index-sh01r3pm.js";
|
|
14
|
-
import"./index-
|
|
15
|
-
import"./index-
|
|
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-
|
|
22
|
-
import"./index-
|
|
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";
|
|
@@ -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,
|
|
665
|
-
|
|
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,
|
|
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>/
|
|
148
|
-
|
|
149
|
-
|
|
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
|
|
|
@@ -2,10 +2,10 @@
|
|
|
2
2
|
import {
|
|
3
3
|
runner,
|
|
4
4
|
script
|
|
5
|
-
} from "./index-
|
|
5
|
+
} from "./index-e31ghfp5.js";
|
|
6
6
|
import {
|
|
7
7
|
PkgExecutor
|
|
8
|
-
} from "./index-
|
|
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-
|
|
10
|
+
} from "./index-mkn5qagt.js";
|
|
11
11
|
import {
|
|
12
12
|
runner
|
|
13
|
-
} from "./index-
|
|
13
|
+
} from "./index-e31ghfp5.js";
|
|
14
14
|
import {
|
|
15
15
|
AppExecutor,
|
|
16
16
|
WorkspaceExecutor
|
|
17
|
-
} from "./index-
|
|
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-
|
|
4
|
+
} from "./index-4rw4qhe6.js";
|
|
5
5
|
import {
|
|
6
6
|
PackageScript
|
|
7
|
-
} from "./index-
|
|
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-
|
|
15
|
+
} from "./index-mkn5qagt.js";
|
|
16
16
|
import {
|
|
17
17
|
script
|
|
18
|
-
} from "./index-
|
|
18
|
+
} from "./index-e31ghfp5.js";
|
|
19
19
|
import {
|
|
20
20
|
PkgExecutor
|
|
21
|
-
} from "./index-
|
|
21
|
+
} from "./index-nkwmnqwn.js";
|
|
22
22
|
|
|
23
23
|
// pkgs/@akanjs/cli/cloud/cloud.script.ts
|
|
24
24
|
import { Logger } from "akanjs/common";
|