@akanjs/cli 3.0.0-alpha.31 → 3.0.0-alpha.32

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 CHANGED
@@ -1 +1 @@
1
- 6666c78ff8b3c6d6f59ad62c78bd4c8771fbd5e4f66acfa5bb2402f05b6ed982
1
+ 2099eccdeb7239ce6ccf7bf5c6a250594bfac9b4208510043dd0365fe7aa7e8f
@@ -63,6 +63,13 @@ that looks wrong; do not "fix" it back.
63
63
  exempt because neither is an instance: `cnst.<Enum>["value"]`, whose indexed access resolves to a string union, and
64
64
  a `ClientInit` / `ClientView` / `ClientEdit` type argument, which the framework maps to `GetStateObject<…>` plain
65
65
  data. Any *other* indexed access is still flagged — `cnst.Banner["image"]` is a `File`.
66
+ **Only prop positions are read** — a `*Props` interface or type alias, and the inline object type on the
67
+ component's own parameter. A `cnst` type that never leaves the file is not a boundary crossing and stays legal: a
68
+ local annotation, a callback parameter the framework itself types with the model
69
+ (`renderItem={(ticket: cnst.LightTicket) => …}`), a module-scope helper, a non-`Props` local shape, and the props
70
+ of a component nested inside another one. A function-typed prop (`onPick?: (t: cnst.LightTicket) => void`) is
71
+ exempt for the same reason — a closure cannot cross the RSC boundary at all, so whoever passes it is a client
72
+ component already holding the value.
66
73
  - **No deep imports past a barrel** (`no-deep-internal-import.grit`). Cross-module constant references such as
67
74
  `../map/map.constant` are the sanctioned exception.
68
75
  - **Never import across the client/server boundary.** Client files (`ui/`, `webkit/`, `page/`, `*.store.ts`, every
@@ -390,6 +397,15 @@ workflow changes.
390
397
  - Numbers must use `Int` or `Float` — `Number` is rejected (`pkgs/akanjs/signal/endpointInfo.ts`).
391
398
  - `Upload` is valid only inside a mutation flagged for file upload: `mutation([cnst.File], { fileUpload: true }).body("files", [Upload])` (see `libs/shared/lib/file/file.signal.ts`). It is not a model field type.
392
399
 
400
+ ### Mutation HTTP Verb
401
+
402
+ - A `mutation` is `POST`. `{ method: "PATCH" | "PUT" | "DELETE" }` moves it, and one path may carry several verbs
403
+ — a `query` GET and a `mutation` POST on the same custom `path` are mounted side by side. Two endpoints claiming
404
+ the same path **and** verb fail the boot rather than silently shadowing one another.
405
+ - Reach for it only when a foreign wire protocol forces the verb (a client you cannot change that sends
406
+ `PATCH /rest/v1/<table>`). Akan's own `fetch.*` client, the OpenAPI document, and the API explorer all follow
407
+ whatever is declared, so nothing needs restating per caller.
408
+
393
409
  ### Reserved Endpoint Names
394
410
 
395
411
  - Auto-generated CRUD endpoints (e.g. `create<Model>`, `update<Model>`, `remove<Model>`) already exist for every model. Do not declare an `Endpoint`/`Slice` with a name that collides with them.
@@ -648,9 +664,10 @@ apps and libs never import it directly (`no-import-external-library`) — everyt
648
664
  `AKAN_AGENT=false` takes it off — and negotiates streaming via `accept`, so assistant text arrives as it is
649
665
  generated with zero app code. The endpoint is a stateless relay and **never executes tools**: every tool runs in
650
666
  the caller's own browser session, gated by guards and the approval card. Its guard is `AgentRelayAccess`, which
651
- **refuses every call until a policy is registered** — the same answer `None` gives, with no boot warning. A
652
- product with accounts locks it in its `option.ts`, `option.setAgentAccess((ctx) => !!ctx.get("account"))`;
653
- without a policy the chat cannot spend the LLM key.
667
+ **refuses every call until the app names a guard of its own** — the same answer `None` gives, with no boot
668
+ warning. A product with accounts names it in its `option.ts`, `option.setAgentAccess(SignedIn)`, taking the same
669
+ guard classes every endpoint takes (an array is ANDed, `null` clears what a library set); without one the chat
670
+ cannot spend the LLM key.
654
671
  `persist` keeps the transcript across reloads (sessionStorage; `{ storage: "local" }` to outlive the tab),
655
672
  default off. Re-skin through the `AgentChat` slot in `_overrides.tsx`.
656
673
  - **The LLM is configured in `option.ts`, never through the environment.** `option.setLlm({ apiKey, model, host })`
@@ -732,6 +749,27 @@ apps and libs never import it directly (`no-import-external-library`) — everyt
732
749
  - **`prompt()` endpoints double as the chat's slash commands.** There is no listing endpoint — the client reads
733
750
  its own serialized signals — so a prompt's dictionary `.desc()` is what the menu shows, and its guards are
734
751
  enforced by the prompt's own GET at call time.
752
+ - **The chat answers five slash commands of its own**, listed in the same `/` menu ahead of the prompts:
753
+ `/new` (`/clear`), `/retry`, `/copy`, `/help` and `/tools`. An app writes none of them and cannot add one — the
754
+ extension point for a product's own command is a `prompt()` endpoint, which is guarded and server-side.
755
+ **A built-in wins a name collision with a prompt of the same name**, the mirror image of the tool rule: a
756
+ component's `st.tool` shadows a built-in it means to replace, but no library's prompt may take `/new` away from
757
+ the user who typed it — so a shadowed prompt is dropped from the menu rather than listed twice. `/new` and
758
+ `/copy` are also dispatched *before* the is-a-turn-running check, because mid-turn is exactly when they are
759
+ reached for; `/new` therefore aborts the turn it is clearing and waits for it to wind down, since the loop
760
+ clears its own running flag a microtask later and a transcript emptied before that lands is one the dying turn
761
+ appends onto.
762
+ - **A command's output is a `local` message: rendered in the transcript, withheld from the wire.** The transcript
763
+ *is* the model's history, so `/help` text appended plainly would come back next turn as something the assistant
764
+ believes it said. `session.note(text)` is the only way to write one, `session.report(error)` stays what a
765
+ host-side *failure* lands in, and `local` messages are left out of a `/copy` export too — they are the chat
766
+ talking to itself. Their text is user-facing, so it goes through `l("base.*")` like every other chat string.
767
+ - **`/copy` exists because nothing else keeps the transcript.** The relay is stateless and the conversation lives
768
+ only in that browser, so an export is the one path a wrong answer has to whoever could fix it — which is why it
769
+ carries the route and the timestamp. `/retry` replays only the trailing user message, leaving anything before it
770
+ in place, so a prompt's own preamble is not sent twice.
771
+ - **↑ and ↓ in the composer walk what was sent.** A single-line input has nothing of its own on the vertical
772
+ arrows, and the half-written draft they were walked away from comes back at the bottom of the walk.
735
773
  - The framework publishes five built-ins on every store surface: `navigate` (internal paths only, the same
736
774
  router `Link` rides), `goBack` (this session's history — global, because history is not a control a page owns and
737
775
  a page that draws no back link is not one you may not leave), `readScreen` (the rendered DOM as compact text —
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@akanjs/cli",
3
- "version": "3.0.0-alpha.31",
3
+ "version": "3.0.0-alpha.32",
4
4
  "sourceType": "module",
5
5
  "type": "module",
6
6
  "publishConfig": {
@@ -34,7 +34,7 @@
34
34
  "@langchain/openai": "^1.4.6",
35
35
  "@tailwindcss/node": "^4.3.0",
36
36
  "@trapezedev/project": "^7.1.4",
37
- "akanjs": "3.0.0-alpha.31",
37
+ "akanjs": "3.0.0-alpha.32",
38
38
  "chalk": "^5.6.2",
39
39
  "commander": "^14.0.3",
40
40
  "dayjs": "^1.11.20",