@akanjs/cli 3.0.0-alpha.102 → 3.0.0-alpha.104
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/{abstractCompactor-byytxs22.js → abstractCompactor-mjh5ppsq.js} +1 -1
- package/{agent.command-v1a4746v.js → agent.command-d2gfxfck.js} +5 -5
- package/{application.command-fzdcnzhg.js → application.command-xgphqs7k.js} +5 -5
- package/{applicationBuildRunner-s4gsk728.js → applicationBuildRunner-3d5q1yn7.js} +2 -2
- package/{applicationReleasePackager-28v9vbzk.js → applicationReleasePackager-4yasxwv9.js} +1 -1
- package/buildBatch.proc.js +2 -2
- package/{capacitorApp-8d6d4zkm.js → capacitorApp-36rbr858.js} +2 -2
- package/{cloud.command-wygy2z05.js → cloud.command-abgkk73f.js} +9 -9
- package/{context.command-4vdt1aqq.js → context.command-ez8a0zyz.js} +13 -13
- package/{devTui-qnf1txdz.js → devTui-70cjjtaw.js} +1 -1
- package/{devTuiView-yzct2cq6.js → devTuiView-71wnkjft.js} +1 -1
- package/{guideline.command-p92dq6ts.js → guideline.command-xmqwx8zm.js} +11 -7
- package/guidelines/agentRule/agentRule.instruction.md +22 -24
- package/guidelines/conventions/conventions.instruction.md +40 -25
- package/guidelines/mcpRule/mcpRule.instruction.md +61 -39
- package/guidelines/ssrRule/ssrRule.instruction.md +15 -13
- package/guidelines/workspaceOnboarding/workspaceOnboarding.instruction.md +4 -3
- package/guidelines/workspaceRecipes/workspaceRecipes.instruction.md +68 -3
- package/incrementalBuilder.proc.js +1 -1
- package/{index-p5neav9b.js → index-0vh9rgxz.js} +1 -1
- package/{index-gq44bqjt.js → index-259dsnz3.js} +2 -2
- package/{index-qsq3q8fy.js → index-2tv3fdx4.js} +21 -10
- package/{index-yks023mb.js → index-4c9ykbfq.js} +6 -6
- package/{index-qkk27bk6.js → index-4edzf1gr.js} +4 -4
- package/{index-yza7zkpt.js → index-600zhnve.js} +10 -10
- package/{index-srdssqj7.js → index-7737gxcp.js} +3 -3
- package/{index-zmjppp25.js → index-8pm30m73.js} +5 -5
- package/{index-0amdxycf.js → index-fz5q3gd7.js} +3 -3
- package/{index-fc1bh0a7.js → index-gyd220p2.js} +1 -1
- package/{index-5svjba73.js → index-j9yhg404.js} +1 -1
- package/{index-c69j78kk.js → index-kn1h7p1x.js} +1 -1
- package/{index-gtmz74tj.js → index-ktb5njgy.js} +2 -2
- package/{index-znynzt5w.js → index-mak3cd28.js} +1 -1
- package/{index-29sxqfaw.js → index-ne2qy0nk.js} +3 -3
- package/{index-hyywke0f.js → index-pnqbkf5p.js} +1 -1
- package/{index-8p8p0cf8.js → index-rwg2aa4f.js} +3 -3
- package/{index-7d6vny25.js → index-ws5e0j51.js} +2 -2
- package/{index-1yxtbmbj.js → index-wt7qrtd4.js} +1 -1
- package/{index-zz5jyd94.js → index-yecdrt9a.js} +9 -9
- package/{index-zxgr3s8s.js → index-yw4xj7pa.js} +4 -4
- package/index.js +19 -19
- package/{library.command-s4fszngs.js → library.command-nbsky672.js} +3 -3
- package/{localRegistry.command-gyw4da9z.js → localRegistry.command-namg61k1.js} +8 -8
- package/{module.command-6n7dwvav.js → module.command-29vqzrh8.js} +6 -6
- package/{package.command-gr82ypnr.js → package.command-axv0abmn.js} +3 -3
- package/package.json +2 -2
- package/{page.command-7gvgb3jb.js → page.command-vs9s3zrh.js} +3 -3
- package/{primitive.command-tk5ckw38.js → primitive.command-cbxmqbtc.js} +7 -7
- package/{quality.command-38v81baf.js → quality.command-gmbs7nws.js} +2 -2
- package/{repair.command-5xbwvsxp.js → repair.command-bqsjptsj.js} +5 -5
- package/{routeSourceValidator-ze6x894c.js → routeSourceValidator-apyqw7wk.js} +90 -17
- package/{scalar.command-0epwcr5k.js → scalar.command-6k1vhe9s.js} +5 -5
- package/{subspace.command-e2t36xb2.js → subspace.command-35a3t6vv.js} +3 -3
- package/templates/app/page/_index.tsx +3 -3
- package/templates/app/page/_layout.tsx +31 -32
- package/templates/appSample/page/task/[taskId]/_index.tsx +22 -27
- package/templates/appSample/page/task/[taskId]/edit.tsx +25 -30
- package/templates/appSample/page/task/_index.tsx +3 -7
- package/templates/appSample/page/task/_layout.tsx +4 -15
- package/templates/appSample/page/task/new.tsx +4 -10
- package/templates/crudPages/[__model__Id]/edit/page.tsx +26 -28
- package/templates/crudPages/[__model__Id]/page.tsx +20 -25
- package/templates/crudPages/new/page.tsx +24 -23
- package/templates/crudPages/page.tsx +25 -24
- package/templates/crudSinglePage/page.tsx +25 -24
- package/{workflow.command-kphbr7eh.js → workflow.command-nwpcdc8p.js} +10 -10
- package/{workspace.command-j1gatz3d.js → workspace.command-kah5jgg5.js} +20 -20
package/.build-stamp
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
|
|
1
|
+
dd9f0e268907504c3c7608ed05e6f95752b6eb2dbfa2f31b3c69c451ff7806d9
|
|
@@ -2,17 +2,17 @@
|
|
|
2
2
|
import {
|
|
3
3
|
Workspace,
|
|
4
4
|
command
|
|
5
|
-
} from "./index-
|
|
5
|
+
} from "./index-mak3cd28.js";
|
|
6
6
|
import"./index-q0y2jq9j.js";
|
|
7
|
-
import"./index-
|
|
7
|
+
import"./index-2tv3fdx4.js";
|
|
8
8
|
import"./index-6wwzs1bc.js";
|
|
9
9
|
import"./index-by5gpp8x.js";
|
|
10
|
-
import"./index-
|
|
11
|
-
import"./index-
|
|
10
|
+
import"./index-gyd220p2.js";
|
|
11
|
+
import"./index-ktb5njgy.js";
|
|
12
12
|
import"./index-h7yw2z9n.js";
|
|
13
13
|
import {
|
|
14
14
|
AgentScript
|
|
15
|
-
} from "./index-
|
|
15
|
+
} from "./index-ne2qy0nk.js";
|
|
16
16
|
|
|
17
17
|
// pkgs/@akanjs/cli/agent/agent.command.ts
|
|
18
18
|
class AgentCommand extends command("agent", [AgentScript], ({ public: target }) => ({
|
|
@@ -6,19 +6,19 @@ import {
|
|
|
6
6
|
Exec,
|
|
7
7
|
Workspace,
|
|
8
8
|
command
|
|
9
|
-
} from "./index-
|
|
9
|
+
} from "./index-mak3cd28.js";
|
|
10
10
|
import"./index-q0y2jq9j.js";
|
|
11
|
-
import"./index-
|
|
11
|
+
import"./index-2tv3fdx4.js";
|
|
12
12
|
import"./index-6wwzs1bc.js";
|
|
13
13
|
import {
|
|
14
14
|
ApplicationScript
|
|
15
|
-
} from "./index-
|
|
16
|
-
import"./index-
|
|
15
|
+
} from "./index-yecdrt9a.js";
|
|
16
|
+
import"./index-259dsnz3.js";
|
|
17
17
|
import"./index-hwkygn9s.js";
|
|
18
18
|
import {
|
|
19
19
|
AbstractDoc
|
|
20
20
|
} from "./index-meh558jy.js";
|
|
21
|
-
import"./index-
|
|
21
|
+
import"./index-j9yhg404.js";
|
|
22
22
|
import {
|
|
23
23
|
getMobileTargetChoices
|
|
24
24
|
} from "./index-47pj3aee.js";
|
|
@@ -1,14 +1,14 @@
|
|
|
1
1
|
// @bun
|
|
2
2
|
import {
|
|
3
3
|
Spinner
|
|
4
|
-
} from "./index-
|
|
4
|
+
} from "./index-2tv3fdx4.js";
|
|
5
5
|
import {
|
|
6
6
|
AllRoutesBuilder,
|
|
7
7
|
CsrArtifactBuilder,
|
|
8
8
|
FontPruner,
|
|
9
9
|
precompressArtifacts,
|
|
10
10
|
SsrBaseArtifactBuilder
|
|
11
|
-
} from "./index-
|
|
11
|
+
} from "./index-0vh9rgxz.js";
|
|
12
12
|
import"./index-w8kmx1b6.js";
|
|
13
13
|
import"./index-q0y2jq9j.js";
|
|
14
14
|
import"./index-hwkygn9s.js";
|
package/buildBatch.proc.js
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
import {
|
|
3
3
|
WorkspaceExecutor,
|
|
4
4
|
AppExecutor
|
|
5
|
-
} from "./index-
|
|
5
|
+
} from "./index-2tv3fdx4.js";
|
|
6
6
|
import"./index-q0y2jq9j.js";
|
|
7
7
|
import"./index-6wwzs1bc.js";
|
|
8
8
|
import {
|
|
@@ -11,7 +11,7 @@ import {
|
|
|
11
11
|
CsrArtifactBuilder,
|
|
12
12
|
FontOptimizer,
|
|
13
13
|
SsrBaseArtifactBuilder
|
|
14
|
-
} from "./index-
|
|
14
|
+
} from "./index-0vh9rgxz.js";
|
|
15
15
|
import"./index-w8kmx1b6.js";
|
|
16
16
|
import"./index-hwkygn9s.js";
|
|
17
17
|
import"./index-n68jx79w.js";
|
|
@@ -2,23 +2,23 @@
|
|
|
2
2
|
import"./index-q0y2jq9j.js";
|
|
3
3
|
import {
|
|
4
4
|
GlobalConfig
|
|
5
|
-
} from "./index-
|
|
5
|
+
} from "./index-kn1h7p1x.js";
|
|
6
6
|
import {
|
|
7
7
|
Workspace,
|
|
8
8
|
command
|
|
9
|
-
} from "./index-
|
|
10
|
-
import"./index-
|
|
9
|
+
} from "./index-mak3cd28.js";
|
|
10
|
+
import"./index-2tv3fdx4.js";
|
|
11
11
|
import"./index-6wwzs1bc.js";
|
|
12
|
-
import"./index-
|
|
13
|
-
import"./index-
|
|
12
|
+
import"./index-yecdrt9a.js";
|
|
13
|
+
import"./index-259dsnz3.js";
|
|
14
14
|
import"./index-hwkygn9s.js";
|
|
15
15
|
import"./index-kcxmv48c.js";
|
|
16
|
-
import"./index-
|
|
17
|
-
import"./index-
|
|
16
|
+
import"./index-ws5e0j51.js";
|
|
17
|
+
import"./index-yw4xj7pa.js";
|
|
18
18
|
import {
|
|
19
19
|
CloudScript
|
|
20
|
-
} from "./index-
|
|
21
|
-
import"./index-
|
|
20
|
+
} from "./index-4c9ykbfq.js";
|
|
21
|
+
import"./index-j9yhg404.js";
|
|
22
22
|
|
|
23
23
|
// pkgs/@akanjs/cli/cloud/cloud.command.ts
|
|
24
24
|
var localRegistryUrl = () => process.env.AKAN_NPM_REGISTRY ?? "http://127.0.0.1:4873";
|
|
@@ -2,25 +2,25 @@
|
|
|
2
2
|
import {
|
|
3
3
|
Workspace,
|
|
4
4
|
command
|
|
5
|
-
} from "./index-
|
|
5
|
+
} from "./index-mak3cd28.js";
|
|
6
6
|
import"./index-q0y2jq9j.js";
|
|
7
|
-
import"./index-
|
|
7
|
+
import"./index-2tv3fdx4.js";
|
|
8
8
|
import"./index-6wwzs1bc.js";
|
|
9
9
|
import"./index-by5gpp8x.js";
|
|
10
|
-
import"./index-
|
|
11
|
-
import"./index-
|
|
10
|
+
import"./index-gyd220p2.js";
|
|
11
|
+
import"./index-ktb5njgy.js";
|
|
12
12
|
import {
|
|
13
13
|
ContextScript
|
|
14
|
-
} from "./index-
|
|
15
|
-
import"./index-
|
|
14
|
+
} from "./index-600zhnve.js";
|
|
15
|
+
import"./index-wt7qrtd4.js";
|
|
16
16
|
import"./index-h7yw2z9n.js";
|
|
17
|
-
import"./index-
|
|
18
|
-
import"./index-
|
|
19
|
-
import"./index-
|
|
20
|
-
import"./index-
|
|
21
|
-
import"./index-
|
|
22
|
-
import"./index-
|
|
23
|
-
import"./index-
|
|
17
|
+
import"./index-fz5q3gd7.js";
|
|
18
|
+
import"./index-7737gxcp.js";
|
|
19
|
+
import"./index-kn1h7p1x.js";
|
|
20
|
+
import"./index-8pm30m73.js";
|
|
21
|
+
import"./index-pnqbkf5p.js";
|
|
22
|
+
import"./index-4edzf1gr.js";
|
|
23
|
+
import"./index-rwg2aa4f.js";
|
|
24
24
|
|
|
25
25
|
// pkgs/@akanjs/cli/context/context.command.ts
|
|
26
26
|
class ContextCommand extends command("context", [ContextScript], ({ public: target }) => ({
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
// @bun
|
|
2
2
|
// pkgs/@akanjs/cli/application/devTuiView.ts
|
|
3
3
|
var createDevTuiView = async (supervisor) => {
|
|
4
|
-
const { DevTui } = await import("./devTui-
|
|
4
|
+
const { DevTui } = await import("./devTui-70cjjtaw.js");
|
|
5
5
|
return new DevTui(supervisor);
|
|
6
6
|
};
|
|
7
7
|
export {
|
|
@@ -4,11 +4,11 @@ import {
|
|
|
4
4
|
runner,
|
|
5
5
|
script,
|
|
6
6
|
command
|
|
7
|
-
} from "./index-
|
|
7
|
+
} from "./index-mak3cd28.js";
|
|
8
8
|
import {
|
|
9
9
|
FileSys
|
|
10
10
|
} from "./index-q0y2jq9j.js";
|
|
11
|
-
import"./index-
|
|
11
|
+
import"./index-2tv3fdx4.js";
|
|
12
12
|
import {
|
|
13
13
|
getDirname2
|
|
14
14
|
} from "./index-6wwzs1bc.js";
|
|
@@ -17,7 +17,7 @@ import {
|
|
|
17
17
|
} from "./index-h7yw2z9n.js";
|
|
18
18
|
import {
|
|
19
19
|
AiSession
|
|
20
|
-
} from "./index-
|
|
20
|
+
} from "./index-kn1h7p1x.js";
|
|
21
21
|
|
|
22
22
|
// pkgs/@akanjs/cli/guideline/guideline.script.ts
|
|
23
23
|
import { Logger } from "akanjs/common";
|
|
@@ -135,9 +135,11 @@ Request: ${updateRequest}
|
|
|
135
135
|
async requestCreateDocumentPage(page) {
|
|
136
136
|
const writePath = this.#resolveDocsPagePath(page);
|
|
137
137
|
if (!await this.workspace.exists(writePath))
|
|
138
|
-
await this.workspace.writeFile(writePath, `
|
|
138
|
+
await this.workspace.writeFile(writePath, `import { page } from "akanjs/client";
|
|
139
|
+
|
|
140
|
+
export default page().render(() => {
|
|
139
141
|
return <div>No Content</div>;
|
|
140
|
-
}
|
|
142
|
+
});
|
|
141
143
|
`);
|
|
142
144
|
const instruction = await Prompter.getInstruction(this.name);
|
|
143
145
|
const pageContent = await this.workspace.getLocalFile(writePath);
|
|
@@ -178,9 +180,11 @@ Please return only the file result in the following format for easy parsing.
|
|
|
178
180
|
async requestUpdateDocumentPage(page, updateRequest) {
|
|
179
181
|
const writePath = this.#resolveDocsPagePath(page);
|
|
180
182
|
if (!await this.workspace.exists(writePath))
|
|
181
|
-
await this.workspace.writeFile(writePath, `
|
|
183
|
+
await this.workspace.writeFile(writePath, `import { page } from "akanjs/client";
|
|
184
|
+
|
|
185
|
+
export default page().render(() => {
|
|
182
186
|
return <div>No Content</div>;
|
|
183
|
-
}
|
|
187
|
+
});
|
|
184
188
|
`);
|
|
185
189
|
const instruction = await Prompter.getInstruction(this.name);
|
|
186
190
|
const pageContent = await this.workspace.getLocalFile(writePath);
|
|
@@ -93,8 +93,7 @@ apps and libs never import it directly (`no-import-external-library`) — everyt
|
|
|
93
93
|
model never saw is one it answers about from the filename. An adaptor declares `accepts: { image, document }` and
|
|
94
94
|
`AgentService.readable` degrades the rest, so a text-only provider needs no attachment code at all — DeepSeek
|
|
95
95
|
declares none, which is why an image against the default provider is refused out loud while an extracted PDF
|
|
96
|
-
works, `text` being readable by every model there is.
|
|
97
|
-
reaches the chat as an attachment rather than the literal `[image]` it used to become. Persisting keeps each
|
|
96
|
+
works, `text` being readable by every model there is. Persisting keeps each
|
|
98
97
|
attachment's name and drops its content: web storage is a few megabytes, one screenshot fills a chunk of it, and
|
|
99
98
|
a save that fails is silent — so keeping the bytes would quietly stop keeping the transcript.
|
|
100
99
|
**The ceilings are the message's, not the file's**: 4 MB per file, 8 MB and five files per message, and the same
|
|
@@ -131,6 +130,11 @@ apps and libs never import it directly (`no-import-external-library`) — everyt
|
|
|
131
130
|
`data-agent-zone` container; guides follow the layout cascade (ancestors and own, never a sibling's). Zone
|
|
132
131
|
membership is positional — there is no per-declaration zone key, so a lib component joins whatever zone the app
|
|
133
132
|
mounts it in.
|
|
133
|
+
- **Two agents' turns run in parallel; their tool calls take turns.** Tool execution is serialized across the
|
|
134
|
+
whole page, because `AgentAbort` and `AgentProgress` reach the running call through a module slot rather than a
|
|
135
|
+
parameter — two calls in flight restore each other's slot and the second one's progress goes nowhere. Only the
|
|
136
|
+
execution queues: a zone parked on an approval card holds nothing up, since waiting for the user sits outside
|
|
137
|
+
the queue, and a call that is aborted releases it.
|
|
134
138
|
- **Everything a zone publishes is named `<id>.<name>`,** and that name is what instructions must use. A bare
|
|
135
139
|
`createVideoProject` inside a zone naming its tool `videoProjectDraft.createVideoProject` is a tool that does
|
|
136
140
|
not exist: the model calls it, the surface answers `Unknown tool`, and a turn is gone. Build the name from the
|
|
@@ -367,18 +371,11 @@ apps and libs never import it directly (`no-import-external-library`) — everyt
|
|
|
367
371
|
useless to a model — that is cheaper than every tool learning to avoid it.
|
|
368
372
|
|
|
369
373
|
## Slash Commands And The Transcript
|
|
370
|
-
-
|
|
371
|
-
|
|
372
|
-
|
|
373
|
-
|
|
374
|
-
is the
|
|
375
|
-
- **The chat answers six slash commands of its own**, listed in the same `/` menu ahead of the prompts:
|
|
376
|
-
`/new` (`/clear`), `/retry`, `/compact`, `/copy`, `/help` and `/tools`. An app writes none of them and cannot add
|
|
377
|
-
one — the extension point for a product's own command is a `prompt()` endpoint, which is guarded and server-side.
|
|
378
|
-
**A built-in wins a name collision with a prompt of the same name**, the mirror image of the tool rule: a
|
|
379
|
-
component's `st.tool` shadows a built-in it means to replace, but no library's prompt may take `/new` away from
|
|
380
|
-
the user who typed it — so a shadowed prompt is dropped from the menu rather than listed twice. `/new` and
|
|
381
|
-
`/copy` are also dispatched *before* the is-a-turn-running check **and before the question card takes the
|
|
374
|
+
- **The `/` menu is the chat's own.** An app's prompts are `page().prompt()` declarations served over MCP to
|
|
375
|
+
external agents; a browser chat lists none of them, so the menu holds the six built-in commands and nothing else.
|
|
376
|
+
- **The chat answers six slash commands of its own**: `/new` (`/clear`), `/retry`, `/compact`, `/copy`, `/help` and
|
|
377
|
+
`/tools`. An app writes none of them and cannot add one — a workflow a person invokes by name belongs to MCP, as
|
|
378
|
+
a `page().prompt()`, where it is guarded by the page it opens. `/new` and `/copy` are dispatched *before* the is-a-turn-running check **and before the question card takes the
|
|
382
379
|
composer**, because mid-turn is exactly when they are reached for and a question the agent asked is the middle
|
|
383
380
|
of a turn like any other — answered as text, `/new` would have reached the model as the user's decision.
|
|
384
381
|
`/new` therefore aborts the turn it is clearing and waits for it to wind down, since the loop clears its own
|
|
@@ -438,16 +435,17 @@ apps and libs never import it directly (`no-import-external-library`) — everyt
|
|
|
438
435
|
row, Tab completing its name, and Escape closing the menu and then, pressed again, the panel.
|
|
439
436
|
|
|
440
437
|
## Built-In Tools
|
|
441
|
-
- The framework publishes five built-ins on every store surface: `navigate` (internal paths only, the same
|
|
442
|
-
|
|
443
|
-
|
|
444
|
-
|
|
445
|
-
|
|
446
|
-
|
|
447
|
-
|
|
448
|
-
|
|
449
|
-
|
|
450
|
-
is worth waiting for — publish an `st.tool` beside the
|
|
438
|
+
- The framework publishes five built-ins on every store surface: `navigate` (internal paths only, the same router
|
|
439
|
+
`Link` rides), `goBack` (this session's history — global, because history is not a control a page owns and a page
|
|
440
|
+
that draws no back link is not one you may not leave — a screen that must not be left withholds them with `builtins`,
|
|
441
|
+
not with prose), `readScreen` (the rendered DOM as compact text — headings, links, control values, and `(disabled)`
|
|
442
|
+
on a control or button that has it; the chat's own UI is skipped via `data-agent-ui`, and a password value is never
|
|
443
|
+
read), `readState(key)` (one masked store key — a key that is unknown or that this screen does not read is refused
|
|
444
|
+
*with the keys it can* read, the way `readScreen` names its sections), and `highlight(target)`. Declaring a hook tool
|
|
445
|
+
under one of those names shadows the built-in, so reuse them only to mean that. **There is no general-purpose wait**:
|
|
446
|
+
a built-in one was reachable on every screen and a model spent it on whatever key it liked, parking turns nobody
|
|
447
|
+
asked to park. Waiting belongs to the screen that knows what is worth waiting for — publish an `st.tool` beside the
|
|
448
|
+
control that starts the work, and let it await the work.
|
|
451
449
|
- **A tool that changes the screen waits for the screen before it answers.** `router.push` returns while the RSC
|
|
452
450
|
payload is still in flight and a store action that fires `void fetch.*` commits a tick later, so `navigate`
|
|
453
451
|
awaits `ScreenSettle.wait()` — DOM quiescence, bounded, because the client router hands its promise to nobody —
|
|
@@ -651,7 +651,7 @@ it.
|
|
|
651
651
|
(`@libs/shared/srvkit`). Never sniff `aud` through a cast.
|
|
652
652
|
- **The refusals are fail-closed**: a declared `mcp: false`, an endpoint with no `guards`, a mutation with no real
|
|
653
653
|
guard, `pubsub` and `message`, an `Any` or `Upload` return, a file upload, a required `Any` argument, and the
|
|
654
|
-
generated `light<Model>` read.
|
|
654
|
+
generated `light<Model>` read. An `enumOf` argument is checked against its values on every path. **Every refusal
|
|
655
655
|
is named in the boot log**, along with every published entry missing a dictionary `.desc()` — an agent picks a
|
|
656
656
|
tool by its description.
|
|
657
657
|
- A refused endpoint answers the *same* "unknown tool" as one that does not exist, and a guard's refusal is
|
|
@@ -659,10 +659,14 @@ it.
|
|
|
659
659
|
- **A `field.visual` field is stripped from every MCP result** and from the readable schema so the two agree.
|
|
660
660
|
- **A structured result ships twice by default** — as `structuredContent` and as the same JSON in the text block.
|
|
661
661
|
`option.setMcp({ legacyTextBlock: false })` leaves a pointer there instead.
|
|
662
|
-
-
|
|
663
|
-
`
|
|
664
|
-
|
|
665
|
-
|
|
662
|
+
- **A prompt is a screen: `page().prompt(name, description)`.** There is no `prompt()` on `endpoint()`.
|
|
663
|
+
`prompts/get` runs the page's body in the RSC worker under the caller's token — nothing is rendered — and answers
|
|
664
|
+
the description, one `resource` per `fetch.*` the page made (masked by the endpoint's return model, addressed by
|
|
665
|
+
its `akan://` uri, one document once whatever shapes read it) and the published tools of the modules it fetched
|
|
666
|
+
from, minus what is already attached; lists — only lists — are cut to `promptBudget`. A guard refusing a query
|
|
667
|
+
inside the body reads as the screen refusing the account, the same way a redirect does. A
|
|
668
|
+
required argument left out answers a pointer to the `<model>List…` tool, never a guess. The description is the
|
|
669
|
+
only instruction, in English — `<Agent.Guide>` never reaches MCP, and the in-page chat lists no page prompts.
|
|
666
670
|
|
|
667
671
|
Full contract — configuration, wire behaviour, resource URIs, OAuth metadata, protocol revisions, and
|
|
668
672
|
`McpProgress.report`: `get_guideline` with `mcpRule`, or `akan guideline show mcpRule`.
|
|
@@ -794,39 +798,50 @@ shape, so `cascade` never means "related" — it means one of exactly these:
|
|
|
794
798
|
- Reserved `_*.tsx` route filenames are limited to `_index.tsx`, `_layout.tsx`, and `_overrides.tsx`; do not add files like `_Component.tsx` or `_helper.tsx`.
|
|
795
799
|
- Page filenames must not start with an uppercase letter. Move helper components like `Component.tsx` to app `ui`, `common`, or `lib` instead.
|
|
796
800
|
- Dynamic segments use `[id]`; route groups use directories like `(user)`, `(public)`, `(tab)`, or `(detail)`.
|
|
797
|
-
-
|
|
801
|
+
- **A route file exports one thing**: `export default page()…render(…)` for a page, `layout()…render(…)` for a
|
|
802
|
+
`_layout.tsx`, `rootLayout()…render(…)` for the app's (or a basePath's) root `_layout.tsx`. Every route setting
|
|
803
|
+
is a stage of the chain — `.param()`, `.search()`, `.config()`, `.head()` / `.metadata()`, `.loading()`;
|
|
804
|
+
`.notFound()` / `.error()` on a layout; `.fonts()` / `.theme()` / `.manifest()` / `.reconnect()` / `.wsConnect()`
|
|
805
|
+
/ `.layoutStyle()` / `.gaTrackingId()` on the root layout; `.prompt()` on a page. A named export beside the chain,
|
|
806
|
+
or `page()` in a `_layout.tsx`, fails the build.
|
|
807
|
+
- **A page names every `[x]` segment of its path with `.param("x", Type)`** and reads a query key only through
|
|
808
|
+
`.search("k", Type)`. Values arrive typed — `ID`/`String` → string, `Int`/`Float` → number, `Boolean`, `Date` →
|
|
809
|
+
Dayjs, an `enumOf` class → its union, `[T]` → array — a path value the type refuses answers not-found, and a
|
|
810
|
+
search value that fails is dropped. A layout may declare a subset. Names are string literals: `akan sync` reads
|
|
811
|
+
them off the source and refuses a `[projectId]` folder whose page declares no `.param("projectId")`. `lang` is
|
|
812
|
+
never declared: every route sits under `/:lang`, and the locale segment reaches every stage as `lang`.
|
|
798
813
|
- `_overrides.tsx` is a logic-free UI-override manifest: imports plus a single `export default override({ Slot: AppComponent })` (from `akanjs/ui`), no `"use client"`. It re-skins framework `akanjs/ui` components for its route subtree; nested manifests merge over ancestors slot-by-slot (closest wins). See the UI Customization reference for the slot list.
|
|
799
|
-
-
|
|
814
|
+
- The legacy shape — `export default async function Page` beside `pageConfig` / `head` / `Loading` exports — still
|
|
815
|
+
loads and logs one deprecation warning per file at boot. Migrate with the `workspaceRecipes` recipe "Migrating
|
|
816
|
+
`page/` to the route chain"; new files are never written in it.
|
|
800
817
|
- `libs/<lib>/page` follows the same rules and ships routes to apps that opt in with `syncPageLibs` in `akan.config.ts`: `true` takes every lib dep that has a `page` folder, an array takes the libs listed, `false` (the default) syncs nothing.
|
|
801
818
|
- `akan sync` links those routes into `apps/<app>/page/(libs)/(<lib>)` — once per basePath when the app declares subRoutes. The folder is generated and gitignored; edit the lib source, never the link.
|
|
802
819
|
- Both path segments are route groups, so a lib route mounts at its own path (`libs/<lib>/page/login/_index.tsx` serves `/login`). Two synced routes that resolve to the same pattern are a sync-time error.
|
|
803
|
-
-
|
|
820
|
+
- `.config({ devOnly: true })` keeps a route out of `akan build` while it keeps serving under `akan start` and keeps being typechecked. On a `_layout.tsx` it excludes every route under that directory too. Write it as a literal `true`/`false` — the build reads it off the source without evaluating the module.
|
|
804
821
|
- Before changing route behavior, check `pkgs/akanjs/server/routeTreeBuilder.ts` and nearby routes for the expected pattern.
|
|
805
822
|
|
|
806
823
|
### Page Body Shape
|
|
807
824
|
|
|
808
825
|
```tsx
|
|
809
|
-
|
|
810
|
-
|
|
811
|
-
}
|
|
812
|
-
|
|
813
|
-
|
|
814
|
-
|
|
815
|
-
|
|
816
|
-
|
|
817
|
-
|
|
818
|
-
return <Task.Zone.Card init={taskInitInOrg} prefix={`/org/${orgId}`} />;
|
|
819
|
-
}
|
|
820
|
-
|
|
821
|
-
export const pageConfig = { transition: "stack" } satisfies PageConfig;
|
|
826
|
+
export default page()
|
|
827
|
+
.param("orgId", ID)
|
|
828
|
+
.config({ transition: "stack" })
|
|
829
|
+
.render(async ({ orgId }) => {
|
|
830
|
+
const { l } = usePage();
|
|
831
|
+
getSelf({ unauthorize: "/signin" });
|
|
832
|
+
const [{ org }, { taskInitInOrg }] = await Promise.all([fetch.viewOrg(orgId), fetch.initTaskInOrg(orgId)]);
|
|
833
|
+
return <Task.Zone.Card init={taskInitInOrg} prefix={`/org/${orgId}`} />;
|
|
834
|
+
});
|
|
822
835
|
```
|
|
823
836
|
|
|
824
|
-
- There is no `loader=` / `render=` page prop
|
|
825
|
-
|
|
826
|
-
- Body order
|
|
837
|
+
- There is no `loader=` / `render=` page prop and no `PageProps` interface: the chain declares the arguments and
|
|
838
|
+
`.render()` receives them flat, typed, with `lang` on every route and `children` added for a layout.
|
|
839
|
+
- Body order inside `.render()`: `usePage()`, auth, fetch, return.
|
|
827
840
|
- Run independent fetches through `Promise.all`, even when there is only one.
|
|
828
841
|
- Gate auth at `_layout.tsx`; repeating `getSelf({ unauthorize: "/signin" })` in the page is fine and common.
|
|
829
|
-
-
|
|
842
|
+
- `async` on the render callback only when the body awaits; the callback is not a React component, so it takes no
|
|
843
|
+
name and no return type.
|
|
844
|
+
- Publish a screen to agents with `.prompt(name, description)` — see MCP Exposure.
|
|
830
845
|
- No `useState`, no `useEffect`, and no comments in page files.
|
|
831
846
|
|
|
832
847
|
## Akan Sync Conventions (`apps/**`, `libs/**`)
|