@akanjs/cli 3.0.0-alpha.50 → 3.0.0-alpha.52
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-nqs3bw0g.js → agent.command-tsx1nsdj.js} +6 -5
- package/{application.command-k2v46pxf.js → application.command-n8ex8g9h.js} +5 -4
- package/{applicationBuildRunner-t5v6tcrm.js → applicationBuildRunner-x8h12rp0.js} +2 -1
- package/buildBatch.proc.js +3 -2
- package/{capacitorApp-927ahhz2.js → capacitorApp-8mv9e537.js} +3 -2
- package/{cloud.command-7jwmxtez.js → cloud.command-eqafzn1a.js} +8 -7
- package/{context.command-6kn3tady.js → context.command-s7a41qjs.js} +13 -12
- package/{guideline.command-pjdrndqk.js → guideline.command-qrw84ttb.js} +3 -2
- package/guidelines/agentRule/agentRule.instruction.md +47 -3
- package/guidelines/conventions/conventions.instruction.md +22 -1
- package/guidelines/mcpRule/mcpRule.instruction.md +18 -6
- package/incrementalBuilder.proc.js +2 -1
- package/{index-7w5vv8jk.js → index-4mtyaqj2.js} +2 -2
- package/{index-90zyjrby.js → index-681sx6nt.js} +6 -1
- package/{index-97cw8sg1.js → index-cc1mgv1f.js} +4 -4
- package/{index-zgkey4d0.js → index-ce9755av.js} +1 -1
- package/{index-8rr621r2.js → index-ckpwq052.js} +1 -1
- package/{index-k7sm38v6.js → index-dvg362vq.js} +3 -3
- package/{index-866yqz3y.js → index-ek4mkwxp.js} +10 -10
- package/{index-6bs24rb4.js → index-f0t3wjyr.js} +2 -2
- package/index-f39512t6.js +255 -0
- package/{index-5em412h5.js → index-g44fykfw.js} +1 -1
- package/{index-xe3ychw5.js → index-h0mnt0b0.js} +3 -3
- package/{index-4z05haak.js → index-kkya2ped.js} +1 -1
- package/{index-7etegaht.js → index-r8z20vnj.js} +5 -5
- package/{index-5fe016p2.js → index-ryns915y.js} +3 -3
- package/{index-y59x51f1.js → index-ssrz6xr1.js} +5 -5
- package/{index-xrdrttjb.js → index-tn46rr6w.js} +4 -4
- package/{index-24h5bqpj.js → index-wc19q8mb.js} +2 -2
- package/{index-bwt525ne.js → index-wmwcwn1f.js} +3 -3
- package/{index-7zd96bng.js → index-x1dbhd80.js} +2 -2
- package/{index-wr999y03.js → index-xj5b8c0w.js} +102 -352
- package/index.js +19 -18
- package/{library.command-7h3yezwc.js → library.command-p3jgf5h2.js} +4 -3
- package/{localRegistry.command-vnkc41gj.js → localRegistry.command-jewr722x.js} +7 -6
- package/{module.command-4g11k3xd.js → module.command-hb3xm07r.js} +6 -5
- package/{package.command-z7dd6vy2.js → package.command-fbpa6r4w.js} +4 -3
- package/package.json +2 -2
- package/{page.command-y996708m.js → page.command-92vrmw96.js} +4 -3
- package/{primitive.command-4fcn8k83.js → primitive.command-k6b9jfxr.js} +7 -6
- package/{quality.command-hx5af2yn.js → quality.command-89vwmjvf.js} +3 -2
- package/{repair.command-ysxd8pef.js → repair.command-nh9jn8rh.js} +6 -5
- package/{scalar.command-3chgxybs.js → scalar.command-zcsjgvax.js} +5 -4
- package/{workflow.command-endxfzv5.js → workflow.command-jj0cphfm.js} +10 -9
- package/{workspace.command-5f2nmmd5.js → workspace.command-zg8me6fg.js} +19 -18
package/.build-stamp
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
|
|
1
|
+
01ea8ed0ffbaa2533de87a90a0f930f8914cabb255e887095d14f13152decabd
|
|
@@ -1,15 +1,16 @@
|
|
|
1
1
|
// @bun
|
|
2
2
|
import {
|
|
3
3
|
AgentScript
|
|
4
|
-
} from "./index-
|
|
5
|
-
import"./index-
|
|
6
|
-
import"./index-
|
|
4
|
+
} from "./index-h0mnt0b0.js";
|
|
5
|
+
import"./index-wc19q8mb.js";
|
|
6
|
+
import"./index-g44fykfw.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-ckpwq052.js";
|
|
12
|
+
import"./index-681sx6nt.js";
|
|
13
|
+
import"./index-f39512t6.js";
|
|
13
14
|
import"./index-mxvakhsm.js";
|
|
14
15
|
import"./index-xys926f2.js";
|
|
15
16
|
import"./index-1577bej2.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-r8z20vnj.js";
|
|
8
|
+
import"./index-f0t3wjyr.js";
|
|
9
9
|
import {
|
|
10
10
|
getMobileTargetChoices
|
|
11
11
|
} from "./index-76rn3g2c.js";
|
|
@@ -15,10 +15,11 @@ import {
|
|
|
15
15
|
Sys,
|
|
16
16
|
Workspace,
|
|
17
17
|
command
|
|
18
|
-
} from "./index-
|
|
18
|
+
} from "./index-ckpwq052.js";
|
|
19
19
|
import"./index-fgc8r6dj.js";
|
|
20
20
|
import"./index-5vy2jzar.js";
|
|
21
|
-
import"./index-
|
|
21
|
+
import"./index-681sx6nt.js";
|
|
22
|
+
import"./index-f39512t6.js";
|
|
22
23
|
import"./index-mxvakhsm.js";
|
|
23
24
|
import"./index-1577bej2.js";
|
|
24
25
|
import"./index-67546d0j.js";
|
|
@@ -4,10 +4,11 @@ import {
|
|
|
4
4
|
CsrArtifactBuilder,
|
|
5
5
|
SsrBaseArtifactBuilder,
|
|
6
6
|
precompressArtifacts
|
|
7
|
-
} from "./index-
|
|
7
|
+
} from "./index-xj5b8c0w.js";
|
|
8
8
|
import"./index-xjd3rqzj.js";
|
|
9
9
|
import"./index-qnv0aqmm.js";
|
|
10
10
|
import"./index-5vy2jzar.js";
|
|
11
|
+
import"./index-f39512t6.js";
|
|
11
12
|
import {
|
|
12
13
|
Spinner
|
|
13
14
|
} from "./index-mxvakhsm.js";
|
package/buildBatch.proc.js
CHANGED
|
@@ -5,14 +5,15 @@ import {
|
|
|
5
5
|
FontOptimizer,
|
|
6
6
|
PagesBundleBuilder,
|
|
7
7
|
SsrBaseArtifactBuilder
|
|
8
|
-
} from "./index-
|
|
8
|
+
} from "./index-xj5b8c0w.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-681sx6nt.js";
|
|
16
|
+
import"./index-f39512t6.js";
|
|
16
17
|
import"./index-mxvakhsm.js";
|
|
17
18
|
import"./index-1577bej2.js";
|
|
18
19
|
import"./index-67546d0j.js";
|
|
@@ -25,9 +25,10 @@ import {
|
|
|
25
25
|
selectLocalDevHost,
|
|
26
26
|
sortIosRunTargets,
|
|
27
27
|
writeRootCapacitorConfig
|
|
28
|
-
} from "./index-
|
|
28
|
+
} from "./index-ce9755av.js";
|
|
29
29
|
import"./index-76rn3g2c.js";
|
|
30
|
-
import"./index-
|
|
30
|
+
import"./index-681sx6nt.js";
|
|
31
|
+
import"./index-f39512t6.js";
|
|
31
32
|
import"./index-mxvakhsm.js";
|
|
32
33
|
import"./index-1577bej2.js";
|
|
33
34
|
import"./index-67546d0j.js";
|
|
@@ -1,22 +1,23 @@
|
|
|
1
1
|
// @bun
|
|
2
2
|
import {
|
|
3
3
|
CloudScript
|
|
4
|
-
} from "./index-
|
|
5
|
-
import"./index-
|
|
6
|
-
import"./index-
|
|
4
|
+
} from "./index-ssrz6xr1.js";
|
|
5
|
+
import"./index-wmwcwn1f.js";
|
|
6
|
+
import"./index-x1dbhd80.js";
|
|
7
7
|
import {
|
|
8
8
|
GlobalConfig
|
|
9
9
|
} from "./index-sh01r3pm.js";
|
|
10
|
-
import"./index-
|
|
11
|
-
import"./index-
|
|
10
|
+
import"./index-r8z20vnj.js";
|
|
11
|
+
import"./index-f0t3wjyr.js";
|
|
12
12
|
import"./index-76rn3g2c.js";
|
|
13
13
|
import {
|
|
14
14
|
Workspace,
|
|
15
15
|
command
|
|
16
|
-
} from "./index-
|
|
16
|
+
} from "./index-ckpwq052.js";
|
|
17
17
|
import"./index-fgc8r6dj.js";
|
|
18
18
|
import"./index-5vy2jzar.js";
|
|
19
|
-
import"./index-
|
|
19
|
+
import"./index-681sx6nt.js";
|
|
20
|
+
import"./index-f39512t6.js";
|
|
20
21
|
import"./index-mxvakhsm.js";
|
|
21
22
|
import"./index-1577bej2.js";
|
|
22
23
|
import"./index-46tjzh6s.js";
|
|
@@ -1,25 +1,26 @@
|
|
|
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-ek4mkwxp.js";
|
|
5
|
+
import"./index-ryns915y.js";
|
|
6
|
+
import"./index-dvg362vq.js";
|
|
7
|
+
import"./index-4mtyaqj2.js";
|
|
8
|
+
import"./index-cc1mgv1f.js";
|
|
9
|
+
import"./index-tn46rr6w.js";
|
|
10
10
|
import"./index-ss469dec.js";
|
|
11
|
-
import"./index-
|
|
12
|
-
import"./index-
|
|
11
|
+
import"./index-kkya2ped.js";
|
|
12
|
+
import"./index-ce9755av.js";
|
|
13
13
|
import"./index-sh01r3pm.js";
|
|
14
|
-
import"./index-
|
|
15
|
-
import"./index-
|
|
14
|
+
import"./index-wc19q8mb.js";
|
|
15
|
+
import"./index-g44fykfw.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-ckpwq052.js";
|
|
22
|
+
import"./index-681sx6nt.js";
|
|
23
|
+
import"./index-f39512t6.js";
|
|
23
24
|
import"./index-mxvakhsm.js";
|
|
24
25
|
import"./index-xys926f2.js";
|
|
25
26
|
import"./index-1577bej2.js";
|
|
@@ -10,8 +10,9 @@ import {
|
|
|
10
10
|
command,
|
|
11
11
|
runner,
|
|
12
12
|
script
|
|
13
|
-
} from "./index-
|
|
14
|
-
import"./index-
|
|
13
|
+
} from "./index-ckpwq052.js";
|
|
14
|
+
import"./index-681sx6nt.js";
|
|
15
|
+
import"./index-f39512t6.js";
|
|
15
16
|
import"./index-mxvakhsm.js";
|
|
16
17
|
import {
|
|
17
18
|
getDirname
|
|
@@ -29,8 +29,22 @@ apps and libs never import it directly (`no-import-external-library`) — everyt
|
|
|
29
29
|
default off, and `shortcut={false}` gives the browser back the Cmd/Ctrl+L the launcher otherwise captures.
|
|
30
30
|
**A session the chat made ends when the chat unmounts** — nothing renders its approvals once it is gone, so a
|
|
31
31
|
turn left running would drive a screen the user has navigated away from; a session handed down by an
|
|
32
|
-
`AgentProvider` or an `Agent.Zone` belongs to whoever provided it.
|
|
33
|
-
|
|
32
|
+
`AgentProvider` or an `Agent.Zone` belongs to whoever provided it.
|
|
33
|
+
- **The panel is customized in three widening steps, and most designs stop at the first.** Props first:
|
|
34
|
+
`open` / `onOpenChange` drive it from the app's own control (`launcher={false}` then draws no launcher of its
|
|
35
|
+
own), `launcherClassName` / `panelClassName` reach one surface each where `className` reaches both, `intro`
|
|
36
|
+
replaces the empty-state line — where starter questions go — and `header` adds controls beside the built-in
|
|
37
|
+
clear and close. Then the slots: `AgentLauncher`, `AgentBubble`, `AgentComposer`, `AgentApproval`,
|
|
38
|
+
`AgentQuestion`, `AgentMenu`, `AgentMarkdown` and `AgentCode` each replace one part in `_overrides.tsx`, and
|
|
39
|
+
`akanjs/ui` exports every default beside them (`DefaultBubble`, `DefaultComposer`, …) so a skin composes the
|
|
40
|
+
one it is replacing. `AgentCode` is where a highlighter binds — the fence's language reaches it — and a
|
|
41
|
+
replacement for `AgentBubble` carries its own `memo`, since the transcript re-renders on every delta. Only then
|
|
42
|
+
`AgentChat`, which replaces the panel whole: it also replaces the slash commands, the compaction notice and the
|
|
43
|
+
approval gate, so reach for it when the *layout* differs, not when the look does.
|
|
44
|
+
- **The composer is a textarea**: Enter sends, Shift+Enter writes a newline, and it grows to a few lines before
|
|
45
|
+
it scrolls. The vertical arrows still walk what was sent, but only from the first or last line — anywhere else
|
|
46
|
+
the caret is the textarea's own. On a phone the panel is the whole screen (it is a card from `sm:` up) and it
|
|
47
|
+
lifts above the on-screen keyboard, which only `visualViewport` reports.
|
|
34
48
|
- **The LLM is configured in `option.ts`, never through the environment.** `option.setLlm({ apiKey, model, host })`
|
|
35
49
|
— or `setLlm((options) => …)` to read the key out of the app's own env object, which is where a secret belongs —
|
|
36
50
|
fills whichever adaptor holds `LlmAdaptorRole`, reaching it as the `llmOption` use. The settings are the role's
|
|
@@ -269,6 +283,13 @@ apps and libs never import it directly (`no-import-external-library`) — everyt
|
|
|
269
283
|
strings a *user* reads: Chat's own buttons go through `l("base.*")`, the model's text never does.
|
|
270
284
|
- A masked model never crosses the boundary: a value whose `hidden`/`secret` fields are populated is refused at
|
|
271
285
|
read unless a `mask:` model is named — the same rule and wording as `AgentBridge.read`.
|
|
286
|
+
- **A field the page needs and an agent does not is `field.visual`.** `abstractData: field.visual(String)` — a blur
|
|
287
|
+
placeholder, a rendered HTML body, a serialized geometry: real data the screen renders, and hundreds of tokens per
|
|
288
|
+
record no question is answered from. It is stripped by `mask`, so it leaves every agent-facing read and every MCP
|
|
289
|
+
result, and it is left alone by `resolveReturn`, so the browser still receives it. Unlike `hidden`/`secret` it is
|
|
290
|
+
cost rather than secrecy: nothing is *refused* over one, and it stays an ordinary stored `property`, so
|
|
291
|
+
persistence, search, forms and the page response are untouched. Reach for it whenever a field is bulky and
|
|
292
|
+
useless to a model — that is cheaper than every tool learning to avoid it.
|
|
272
293
|
|
|
273
294
|
## Slash Commands And The Transcript
|
|
274
295
|
- **`prompt()` endpoints double as the chat's slash commands.** There is no listing endpoint — the client reads
|
|
@@ -315,7 +336,15 @@ apps and libs never import it directly (`no-import-external-library`) — everyt
|
|
|
315
336
|
this transcript can shrink. One that *landed* and shrank nothing does, so that one is not retried until another
|
|
316
337
|
threshold's worth has been added. On the
|
|
317
338
|
wire a summary wears the user's role because the wire has no other, so a provider mapping frames it as a system
|
|
318
|
-
message and `/retry` steps over it — replaying it would send the notes back as a question.
|
|
339
|
+
message and `/retry` steps over it — replaying it would send the notes back as a question. **While a summary is
|
|
340
|
+
being written the transcript says so** (`session.isCompacting`, distinct from `isRunning`, which an
|
|
341
|
+
auto-compaction runs inside): that turn takes as long as any other and answers nothing the user asked, so a chat
|
|
342
|
+
that only shows the running dot reads as a question being ignored.
|
|
343
|
+
- **The transcript shows what each turn costs, because nothing else can.** The header carries the whole
|
|
344
|
+
conversation's estimated tokens (`session.tokens`), and every settled tool row carries its own and **opens onto
|
|
345
|
+
the value the model was handed** — a tool result is the one part of a transcript neither the user nor the app
|
|
346
|
+
author ever sees, being the app's own return value. A window that filled after four messages is explained by
|
|
347
|
+
*which* row cost a million tokens and by nothing else, so that is the question the row answers in one click.
|
|
319
348
|
- **A stopped turn answers the calls it never ran, because an unanswered call ends the conversation.** Every
|
|
320
349
|
provider dialect refuses an assistant message whose `tool_calls` have no results — on that turn and on every
|
|
321
350
|
later one — so Stop landing between a call and its result would leave a transcript nothing can be sent from,
|
|
@@ -385,6 +414,21 @@ apps and libs never import it directly (`no-import-external-library`) — everyt
|
|
|
385
414
|
`highlight` scrolls its target into view and flashes it **once the scroll lands**, since a smooth scroll across a
|
|
386
415
|
long page outlasts the flash; it is the one built-in that exists for the *user's* benefit, because showing where
|
|
387
416
|
a control is beats writing directions to it.
|
|
417
|
+
- **`<Agent.Skip label="site footer">` leaves a region out of the default read** — chrome that costs tokens and
|
|
418
|
+
answers nothing: a footer, a cookie banner, a nav that repeats on every route. What stands in its place is
|
|
419
|
+
`[skipped: site footer]`, never nothing, because a deleted region reads as an absent one and an agent asked about
|
|
420
|
+
the footer would answer that the page has none. The marker's name **is** a `section`, so naming it reads the
|
|
421
|
+
region after all: what the marker withholds is the *default* read, not the region. It renders a wrapper div, so
|
|
422
|
+
where that would move a flex or grid layout put `data-agent-skip="<name>"` on the element the page already
|
|
423
|
+
renders — an unlabelled attribute falls back to the tag name, which is why the raw form belongs on a `<footer>`
|
|
424
|
+
or `<nav>` and the component insists on a label. A region that is hidden anyway leaves no marker claiming it is
|
|
425
|
+
there. **It hides text, not behaviour**: tools and state keys are declarations rather than markup, so an
|
|
426
|
+
`st.tool` inside is published exactly as before and `highlight` still reaches a control in there. This is
|
|
427
|
+
`field.visual` one layer up — cost, not secrecy.
|
|
428
|
+
- **Reach for it second.** A read narrows from the other side too: `Agent.Zone` and `readScreen({ section })` scope
|
|
429
|
+
to one container, which beats blocklisting five regions on a screen that is mostly chrome. And a footer is last
|
|
430
|
+
in the document, so on a page long enough to truncate it was already past the cut — the regions worth marking are
|
|
431
|
+
the ones *above* the content.
|
|
388
432
|
- **Every tool's return value is bounded at 20,000 characters before it enters the transcript** (`ToolOutput.limit`,
|
|
389
433
|
clipped with a note that gives the real size and tells the model to read a narrower part). `readScreen` caps
|
|
390
434
|
itself; nothing else did, and a store key is sized for a screen rather than for a model's window — one
|
|
@@ -89,6 +89,13 @@ back.
|
|
|
89
89
|
implements the boundary and is where the two graphs legitimately meet.
|
|
90
90
|
- **Server-component discipline** is enforced on `page/**`, `*.Unit.tsx`, and `*.View.tsx`
|
|
91
91
|
(`no-import-client-functions.grit`, `no-use-client-in-server.grit`, `non-scalar-props-restricted.grit`).
|
|
92
|
+
- **Never write an async component outside `page/`** (`no-async-component-in-ui.grit`, scoped to
|
|
93
|
+
`{apps,libs}/**/ui/**/*.tsx`). React has no async client component, so a `ui/` component that awaits breaks as
|
|
94
|
+
soon as a client parent renders it, and the load drops below the route, which could have started it before the
|
|
95
|
+
first byte. Await in the page — or hand an unawaited `fetch.*` to a `Zone` as an `init` / `view` prop — and take
|
|
96
|
+
the resolved data as a prop. A component is a PascalCase binding whose own initializer is `async`, so an async
|
|
97
|
+
handler declared inside a synchronous component, an inline `onClick={async () => …}`, and
|
|
98
|
+
`lazy(async () => import(…))` are all untouched.
|
|
92
99
|
- `noArrayIndexKey` and `useExhaustiveDependencies` are **off** on purpose: `key={idx}` for embedded scalars and
|
|
93
100
|
short dependency arrays are intentional, not oversights.
|
|
94
101
|
- **A grit plugin diagnostic is suppressed as `lint/plugin`, not `plugin`** — `// biome-ignore lint/plugin: <reason>`
|
|
@@ -490,6 +497,12 @@ while guaranteeing that every endpoint added later is invisible to agents until
|
|
|
490
497
|
- A refused endpoint answers the *same* "unknown tool" as one that does not exist, and a guard's refusal is
|
|
491
498
|
generalized to `You are not permitted to perform this action.` Never make either message more helpful — the
|
|
492
499
|
difference is what enumerates your private surface.
|
|
500
|
+
- **A `field.visual` field is stripped from every MCP result**, and from the readable schema so the two agree — the
|
|
501
|
+
model-level answer to a field the page needs and an agent does not. `resolveReturn` leaves it alone, so the
|
|
502
|
+
browser still receives it.
|
|
503
|
+
- **A structured result ships twice by default** — once as `structuredContent`, once as the same JSON in the text
|
|
504
|
+
block, which is what the spec asks for clients predating the structured field and is also a flat doubling of what
|
|
505
|
+
every model-returning tool costs. `option.setMcp({ legacyTextBlock: false })` leaves a pointer there instead.
|
|
493
506
|
- `AKAN_MCP_READONLY=true` is the read-only-deployment valve, not the exposure switch; `AKAN_MCP=false` takes the
|
|
494
507
|
whole surface off.
|
|
495
508
|
- **`prompt()`** is invoked by the *user* as a slash command, never chosen by the model. `exec` returns
|
|
@@ -536,7 +549,14 @@ package; apps and libs never import it directly (`no-import-external-library`)
|
|
|
536
549
|
for a screen and not for a model's window: one `readState` of a list whose rows carry inlined bytes is megabytes,
|
|
537
550
|
and from there it rides *every* later turn. Each tool row in the chat carries its own estimated token cost and
|
|
538
551
|
opens onto the value the model was handed — that row is where a conversation that filled up in four messages
|
|
539
|
-
explains itself.
|
|
552
|
+
explains itself. A field that is bulky and useless to a model is fixed once at the model instead:
|
|
553
|
+
`field.visual(String)` keeps it on the page and out of every agent-facing read and MCP result.
|
|
554
|
+
- **`<Agent.Skip label="site footer">` leaves a region out of the default `readScreen`** — a footer, a cookie
|
|
555
|
+
banner, a nav that repeats on every route. `[skipped: site footer]` stands in its place rather than nothing, since
|
|
556
|
+
a deleted region reads as an absent one, and the marker's name is a `section` that reads the region on request.
|
|
557
|
+
Put `data-agent-skip="<name>"` on the element the page already renders where a wrapper div would move the layout.
|
|
558
|
+
It hides **text, not behaviour**: an `st.tool` inside is published as before. Narrowing from the other side —
|
|
559
|
+
`Agent.Zone`, `readScreen({ section })` — is the better move on a screen that is mostly chrome.
|
|
540
560
|
- **Route guidance is `<Agent.Guide instructions="..." />`** rendered from a `_layout.tsx` or page — the render
|
|
541
561
|
tree is the cascade. It is a component, not a `pageConfig` field, and `*.abstract.md` is never served to agents.
|
|
542
562
|
- The framework publishes five built-ins on every store surface — `navigate`, `goBack`, `readScreen`,
|
|
@@ -558,6 +578,7 @@ commands, transcript compaction, and the built-in tool semantics: `get_guideline
|
|
|
558
578
|
- Follow the established model layering pattern in this order: `Input`, `Object`, `Light<Model>`, full `<Model>`, and `<Model>Insight`. Write all five, and write `<Model>Insight` even when it is empty.
|
|
559
579
|
- Put display and predicate logic on the `Light<Model>` class rather than in a util module — see Module File Playbook.
|
|
560
580
|
- Defaults are a literal for scalars and a thunk for anything constructed. Arrays are `field([T])`; optional is the postfix `.optional()`.
|
|
581
|
+
- **`field.visual(T)` is a field the page renders and an agent never sees** — a blur placeholder, a rendered HTML body, a serialized geometry. It stays an ordinary stored `property` (persistence, search, forms and the page response untouched) and is stripped wherever a value is masked for an AI caller: every in-page-agent read and every MCP result, along with the MCP readable schema. Unlike `hidden`/`secret` it is cost, not secrecy — nothing is refused over one. Reach for it whenever a field is bulky and useless to a model; that is cheaper than every tool learning to avoid it.
|
|
561
582
|
|
|
562
583
|
### Scalar & Field Type Reference
|
|
563
584
|
|
|
@@ -16,13 +16,13 @@ until somebody remembers it.
|
|
|
16
16
|
|
|
17
17
|
## Configuration
|
|
18
18
|
Settings live in the app's `lib/option.ts` — `option.setMcp({ … })`, taking `enabled`, `readOnly`, `path`,
|
|
19
|
-
`version`, `instructions`, `allowedOrigins`, `pageSize`, `language`, and `auth`. **Not `main.ts`**: the gateway
|
|
19
|
+
`version`, `instructions`, `allowedOrigins`, `pageSize`, `language`, `legacyTextBlock`, and `auth`. **Not `main.ts`**: the gateway
|
|
20
20
|
there only spawns children, and `option.ts` is the app-authored file `server.ts` already hands to the process that
|
|
21
21
|
mounts `/mcp`. Every lib's option is read in mount order with the app's last, so an app tightens what a library
|
|
22
22
|
declared without restating it. Each field also has an env spelling (`AKAN_MCP`, `AKAN_MCP_READONLY`,
|
|
23
23
|
`AKAN_MCP_PATH`, `AKAN_MCP_VERSION`, `AKAN_MCP_INSTRUCTIONS`, `AKAN_MCP_ALLOWED_ORIGINS`, `AKAN_MCP_PAGE_SIZE`,
|
|
24
|
-
`AKAN_MCP_LANGUAGE`, `AKAN_MCP_AUTH_SERVERS`, `AKAN_MCP_SCOPES`, `AKAN_MCP_RESOURCE`) for a
|
|
25
|
-
configures what the source does not, which the option overrides.
|
|
24
|
+
`AKAN_MCP_LANGUAGE`, `AKAN_MCP_LEGACY_TEXT`, `AKAN_MCP_AUTH_SERVERS`, `AKAN_MCP_SCOPES`, `AKAN_MCP_RESOURCE`) for a
|
|
25
|
+
deployment that configures what the source does not, which the option overrides.
|
|
26
26
|
The two booleans answer to `AKAN_PUBLIC_MCP` / `AKAN_PUBLIC_MCP_READONLY` too, the same pairing `AKAN_OPENAPI`
|
|
27
27
|
has, and a value written in code wins over the env of the same name — an explicit `undefined` is not a value.
|
|
28
28
|
`AKAN_MCP_PATH` is normalized to a leading `/`, because the route key and the OAuth metadata path are both built by
|
|
@@ -87,9 +87,21 @@ export class TaskEndpoint extends endpoint(srv.task, ({ mutation, prompt }) => (
|
|
|
87
87
|
can — a list is wrapped as `{ items: … }` for the same reason — and a declared schema obliges every result to
|
|
88
88
|
match it, so a client SDK throws on the first call that finds nothing. A nullable *list* keeps its schema, and a
|
|
89
89
|
scalar return has no structured half at all: it ships as the value itself, not as JSON.
|
|
90
|
-
- **An `outputSchema` names no `hidden` or `
|
|
91
|
-
promises a property no answer can carry — and on a model like `user` the names are the leak.
|
|
92
|
-
keeps
|
|
90
|
+
- **An `outputSchema` names no `hidden`, `secret`, or `visual` field.** Every response has the first two stripped,
|
|
91
|
+
so publishing them promises a property no answer can carry — and on a model like `user` the names are the leak.
|
|
92
|
+
Your *input* schema keeps all three: they are legal to send, and the same model describes a request body.
|
|
93
|
+
- **A `field.visual` is stripped from every MCP result.** It is the marker for a field the page renders and no
|
|
94
|
+
question is answered from — a blur placeholder, a rendered HTML body — and it is cost rather than secrecy, so
|
|
95
|
+
nothing is refused over one. The strip happens in the MCP dispatcher rather than in `resolveReturn`, which every
|
|
96
|
+
ordinary HTTP response also passes through: the whole point is that a browser still receives it. That is also why
|
|
97
|
+
the readable schema drops it — a non-optional visual field would otherwise be listed `required` and a validating
|
|
98
|
+
client would refuse a result that correctly omits it.
|
|
99
|
+
- **A structured result ships twice by default**, once as `structuredContent` and once as the same JSON in the text
|
|
100
|
+
block, which is what the spec asks of a server for clients predating the structured field. It is also a flat
|
|
101
|
+
doubling of what every model-returning tool costs a model. `option.setMcp({ legacyTextBlock: false })` — or
|
|
102
|
+
`AKAN_MCP_LEGACY_TEXT=false` — leaves a one-line pointer in the text block instead, for a deployment whose
|
|
103
|
+
clients read the structured half. A scalar return is unaffected: it has no structured half to point at, so it
|
|
104
|
+
ships as the value itself either way.
|
|
93
105
|
- A refused endpoint answers the *same* "unknown tool" as one that does not exist. Never make that
|
|
94
106
|
message more helpful — the difference is what enumerates your private surface. A guard's refusal is generalized
|
|
95
107
|
the same way: the caller reads `You are not permitted to perform this action.`, never `Access denied by guard:
|
|
@@ -9,14 +9,14 @@ import {
|
|
|
9
9
|
createPassedPrimitiveReport,
|
|
10
10
|
generatedFilesForSync,
|
|
11
11
|
scalarChangedFiles
|
|
12
|
-
} from "./index-
|
|
12
|
+
} from "./index-g44fykfw.js";
|
|
13
13
|
import {
|
|
14
14
|
Prompter
|
|
15
15
|
} from "./index-j37qq1f2.js";
|
|
16
16
|
import {
|
|
17
17
|
runner,
|
|
18
18
|
script
|
|
19
|
-
} from "./index-
|
|
19
|
+
} from "./index-ckpwq052.js";
|
|
20
20
|
|
|
21
21
|
// pkgs/@akanjs/cli/scalar/scalar.prompt.ts
|
|
22
22
|
import { input } from "@inquirer/prompts";
|
|
@@ -1,4 +1,8 @@
|
|
|
1
1
|
// @bun
|
|
2
|
+
import {
|
|
3
|
+
getRootBoundarySegments,
|
|
4
|
+
isRootBoundarySegments
|
|
5
|
+
} from "./index-f39512t6.js";
|
|
2
6
|
import {
|
|
3
7
|
Spinner
|
|
4
8
|
} from "./index-mxvakhsm.js";
|
|
@@ -2746,7 +2750,8 @@ class AppExecutor extends SysExecutor {
|
|
|
2746
2750
|
}
|
|
2747
2751
|
if (!owner)
|
|
2748
2752
|
owners.set(routeId, { absPath, fromLib });
|
|
2749
|
-
const
|
|
2753
|
+
const layoutSegments = getRootBoundarySegments(key);
|
|
2754
|
+
const isRootLayout = layoutSegments !== null && isRootBoundarySegments(layoutSegments, akanConfig2.basePaths);
|
|
2750
2755
|
const routeSource = await Bun.file(absPath).text();
|
|
2751
2756
|
const validator = await AppExecutor.#getRouteSourceValidator();
|
|
2752
2757
|
if (parsed.kind === "overrides")
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
// @bun
|
|
2
2
|
import {
|
|
3
3
|
ModuleScript
|
|
4
|
-
} from "./index-
|
|
4
|
+
} from "./index-tn46rr6w.js";
|
|
5
5
|
import {
|
|
6
6
|
addFieldUiPolicyForType,
|
|
7
7
|
coerceFieldDefault,
|
|
@@ -34,15 +34,15 @@ import {
|
|
|
34
34
|
sourceFile,
|
|
35
35
|
validationCommandsForTarget,
|
|
36
36
|
viaBuilderParameterName
|
|
37
|
-
} from "./index-
|
|
37
|
+
} from "./index-g44fykfw.js";
|
|
38
38
|
import {
|
|
39
39
|
script
|
|
40
|
-
} from "./index-
|
|
40
|
+
} from "./index-ckpwq052.js";
|
|
41
41
|
import {
|
|
42
42
|
AppExecutor,
|
|
43
43
|
LibExecutor,
|
|
44
44
|
ModuleExecutor
|
|
45
|
-
} from "./index-
|
|
45
|
+
} from "./index-681sx6nt.js";
|
|
46
46
|
|
|
47
47
|
// pkgs/@akanjs/cli/primitive/primitive.script.ts
|
|
48
48
|
import { capitalize } from "akanjs/common";
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
// @bun
|
|
2
2
|
import {
|
|
3
3
|
AkanContextAnalyzer
|
|
4
|
-
} from "./index-
|
|
4
|
+
} from "./index-wc19q8mb.js";
|
|
5
5
|
import {
|
|
6
6
|
WorkflowExecutor,
|
|
7
7
|
compactWorkflowInputs,
|
|
@@ -23,10 +23,10 @@ import {
|
|
|
23
23
|
workflowCommandsForPlan,
|
|
24
24
|
workflowPlanApproval,
|
|
25
25
|
writeWorkflowRunArtifact
|
|
26
|
-
} from "./index-
|
|
26
|
+
} from "./index-g44fykfw.js";
|
|
27
27
|
import {
|
|
28
28
|
runner
|
|
29
|
-
} from "./index-
|
|
29
|
+
} from "./index-ckpwq052.js";
|
|
30
30
|
|
|
31
31
|
// pkgs/@akanjs/cli/workflow/workflow.runner.ts
|
|
32
32
|
import { mkdir, readFile, writeFile } from "fs/promises";
|
|
@@ -1,22 +1,22 @@
|
|
|
1
1
|
// @bun
|
|
2
2
|
import {
|
|
3
3
|
RepairRunner
|
|
4
|
-
} from "./index-
|
|
4
|
+
} from "./index-ryns915y.js";
|
|
5
5
|
import {
|
|
6
6
|
WorkflowRunner
|
|
7
|
-
} from "./index-
|
|
7
|
+
} from "./index-dvg362vq.js";
|
|
8
8
|
import {
|
|
9
9
|
ScalarScript
|
|
10
|
-
} from "./index-
|
|
10
|
+
} from "./index-4mtyaqj2.js";
|
|
11
11
|
import {
|
|
12
12
|
PrimitiveScript
|
|
13
|
-
} from "./index-
|
|
13
|
+
} from "./index-cc1mgv1f.js";
|
|
14
14
|
import {
|
|
15
15
|
ModuleScript
|
|
16
|
-
} from "./index-
|
|
16
|
+
} from "./index-tn46rr6w.js";
|
|
17
17
|
import {
|
|
18
18
|
isPlaceholderAppId
|
|
19
|
-
} from "./index-
|
|
19
|
+
} from "./index-ce9755av.js";
|
|
20
20
|
import {
|
|
21
21
|
AkanContextAnalyzer,
|
|
22
22
|
akanMcpInstallConfigPaths,
|
|
@@ -27,14 +27,14 @@ import {
|
|
|
27
27
|
renderDoctorText,
|
|
28
28
|
resourceList,
|
|
29
29
|
upsertCodexMcpServerBlock
|
|
30
|
-
} from "./index-
|
|
30
|
+
} from "./index-wc19q8mb.js";
|
|
31
31
|
import {
|
|
32
32
|
buildAkanModuleContextIndex,
|
|
33
33
|
createWorkflowBaselineSummary,
|
|
34
34
|
createWorkflowStepRegistry,
|
|
35
35
|
jsonText,
|
|
36
36
|
toolingRolloutGate
|
|
37
|
-
} from "./index-
|
|
37
|
+
} from "./index-g44fykfw.js";
|
|
38
38
|
import {
|
|
39
39
|
Prompter
|
|
40
40
|
} from "./index-j37qq1f2.js";
|
|
@@ -45,10 +45,10 @@ import {
|
|
|
45
45
|
CommandContainer,
|
|
46
46
|
runner,
|
|
47
47
|
script
|
|
48
|
-
} from "./index-
|
|
48
|
+
} from "./index-ckpwq052.js";
|
|
49
49
|
import {
|
|
50
50
|
AppExecutor
|
|
51
|
-
} from "./index-
|
|
51
|
+
} from "./index-681sx6nt.js";
|
|
52
52
|
|
|
53
53
|
// pkgs/@akanjs/cli/context/context.script.ts
|
|
54
54
|
import { Logger } from "akanjs/common";
|
|
@@ -2,10 +2,10 @@
|
|
|
2
2
|
import {
|
|
3
3
|
runner,
|
|
4
4
|
script
|
|
5
|
-
} from "./index-
|
|
5
|
+
} from "./index-ckpwq052.js";
|
|
6
6
|
import {
|
|
7
7
|
LibExecutor
|
|
8
|
-
} from "./index-
|
|
8
|
+
} from "./index-681sx6nt.js";
|
|
9
9
|
|
|
10
10
|
// pkgs/@akanjs/cli/semver.ts
|
|
11
11
|
var stripRangeOperator = (version) => version.replace(/^[\s^~>=<v]+/, "").trim();
|