lecodes-sdk 0.20.2 → 1.0.0
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/dist/global.d.ts +17 -5
- package/dist/types/canvas/Canvas.d.ts +2 -0
- package/dist/types/gl/DecalSet.d.ts +48 -3
- package/dist/types/gl/Geometry.d.ts +12 -0
- package/dist/types/gl/Lightmap.d.ts +9 -0
- package/dist/types/gl/Material.d.ts +4 -0
- package/dist/types/gl/Mesh.d.ts +7 -1
- package/dist/types/gl/Model.d.ts +34 -0
- package/dist/types/gl/Particles.d.ts +13 -0
- package/dist/types/gl/Scene.d.ts +1 -1
- package/dist/types/gl/animation/DynamicBone.d.ts +173 -0
- package/dist/types/gl/{IK.d.ts → animation/IK.d.ts} +4 -4
- package/dist/types/gl/{Locomotion.d.ts → animation/Locomotion.d.ts} +6 -6
- package/dist/types/gl/{AudioSource.d.ts → audio/AudioSource.d.ts} +6 -6
- package/dist/types/gl/{AudioZone.d.ts → audio/AudioZone.d.ts} +4 -4
- package/dist/types/gl/{SceneAudio.d.ts → audio/SceneAudio.d.ts} +1 -1
- package/dist/types/gl/{NavAgent.d.ts → nav/NavAgent.d.ts} +4 -4
- package/dist/types/gl/{NavMesh.d.ts → nav/NavMesh.d.ts} +4 -4
- package/dist/types/gl/{CharacterController.d.ts → physics/CharacterController.d.ts} +5 -5
- package/dist/types/gl/{Physics.d.ts → physics/Physics.d.ts} +6 -5
- package/dist/types/gl/{Ragdoll.d.ts → physics/Ragdoll.d.ts} +4 -4
- package/dist/types/gl/{Shape.d.ts → physics/Shape.d.ts} +3 -3
- package/dist/types/gl/{Trigger.d.ts → physics/Trigger.d.ts} +2 -2
- package/dist/types/gl/{Terrain.d.ts → terrain/Terrain.d.ts} +6 -6
- package/dist/types/gl/{terrainMesh.d.ts → terrain/terrainMesh.d.ts} +1 -1
- package/dist/types/gl/vehicle/Vehicle.d.ts +300 -0
- package/dist/types/gl/vehicle/Wheel.d.ts +147 -0
- package/dist/types/inject.d.ts +28 -26
- package/dist/types/runtime/files.d.ts +24 -1
- package/dist/types/scene/defineScene.d.ts +10 -3
- package/dist/types.json +1 -1
- package/package.json +1 -1
- package/prompts/README.md +142 -142
- package/src/bridges.d.ts +1599 -1481
- package/src/canvas/Canvas.ts +21 -0
- package/src/compile/__tests__/compile.test.ts +11 -0
- package/src/compile/header.ts +6 -3
- package/src/compile/index.ts +1 -0
- package/src/compile/sceneEditor.ts +42 -1
- package/src/gl/DecalSet.ts +132 -5
- package/src/gl/Geometry.ts +348 -284
- package/src/gl/Lightmap.ts +32 -5
- package/src/gl/Material.ts +21 -0
- package/src/gl/Mesh.ts +120 -102
- package/src/gl/Model.ts +33 -1
- package/src/gl/Node.ts +1 -1
- package/src/gl/Particles.ts +21 -3
- package/src/gl/Scene.ts +1 -1
- package/src/gl/animation/DynamicBone.ts +459 -0
- package/src/gl/{IK.ts → animation/IK.ts} +4 -4
- package/src/gl/{Locomotion.ts → animation/Locomotion.ts} +7 -7
- package/src/gl/{AudioSource.ts → audio/AudioSource.ts} +7 -7
- package/src/gl/{AudioZone.ts → audio/AudioZone.ts} +75 -75
- package/src/gl/{SceneAudio.ts → audio/SceneAudio.ts} +2 -2
- package/src/gl/{NavAgent.ts → nav/NavAgent.ts} +5 -5
- package/src/gl/{NavMesh.ts → nav/NavMesh.ts} +8 -8
- package/src/gl/{CharacterController.ts → physics/CharacterController.ts} +5 -5
- package/src/gl/{Physics.ts → physics/Physics.ts} +12 -5
- package/src/gl/{Ragdoll.ts → physics/Ragdoll.ts} +8 -6
- package/src/gl/{Shape.ts → physics/Shape.ts} +3 -3
- package/src/gl/{Trigger.ts → physics/Trigger.ts} +45 -45
- package/src/gl/{physicsEvents.ts → physics/physicsEvents.ts} +1 -1
- package/src/gl/{Terrain.ts → terrain/Terrain.ts} +10 -10
- package/src/gl/{terrainMesh.ts → terrain/terrainMesh.ts} +1 -1
- package/src/gl/vehicle/Vehicle.ts +666 -0
- package/src/gl/vehicle/Wheel.ts +290 -0
- package/src/inject.ts +226 -224
- package/src/runtime/files.ts +32 -2
- package/src/scene/defineScene.ts +26 -10
- package/src/scene/level.ts +2 -2
- package/dist/types/gl/Gearbox.d.ts +0 -86
- package/dist/types/gl/Vehicle.d.ts +0 -191
- package/dist/types/gl/Wheel.d.ts +0 -95
- package/src/gl/Gearbox.ts +0 -212
- package/src/gl/Vehicle.ts +0 -473
- package/src/gl/Wheel.ts +0 -240
- /package/dist/types/gl/{physicsEvents.d.ts → physics/physicsEvents.d.ts} +0 -0
package/package.json
CHANGED
package/prompts/README.md
CHANGED
|
@@ -1,142 +1,142 @@
|
|
|
1
|
-
# Codegen prompts
|
|
2
|
-
|
|
3
|
-
> **Scope: the le.codes PLATFORM assistant only.** These prompts are bundled into `dist/` and served
|
|
4
|
-
> by claude-proxy to the in-editor chat. They are NOT used by local development — Claude Code and
|
|
5
|
-
> `lecodes-cli` never read them; those get the SDK surface from `.lecodes/types` (the d.ts bundle),
|
|
6
|
-
> the generated project `CLAUDE.md` (`lecodes-cli/src/commands/
|
|
7
|
-
> A change meant for local development belongs there, not here.
|
|
8
|
-
|
|
9
|
-
The system prompt(s) sent to Claude for LeCodes code generation, split into composable modules so
|
|
10
|
-
a request only pays for the API areas it can actually use. Facts come from `../docs/` (the source
|
|
11
|
-
of truth) — when the SDK changes, update docs first, then mirror the change here.
|
|
12
|
-
|
|
13
|
-
**Consumers:**
|
|
14
|
-
- `claude-proxy/prompts/*.md` — deployed copies of `dist/` + `router.md` (see its README); the
|
|
15
|
-
proxy injects them per the `x-lecodes-bundle` header (`claude-proxy/src/proxy/bundles.ts`). An
|
|
16
|
-
unknown/missing header is a **400** (no silent fallback), and the proxy's `/health` exposes a
|
|
17
|
-
sha256-12 per bundle — `bun run check:prompts` (repo root) compares them against `dist/` to
|
|
18
|
-
catch deploy drift (`--dir <proxy>/prompts` checks a local checkout instead).
|
|
19
|
-
- `packages/frontend/.../chat/engine/bundleSelect.ts` — a thin adapter over `select.ts` (imported
|
|
20
|
-
as `sdk/prompts/select`); the selection logic itself is not duplicated anywhere.
|
|
21
|
-
|
|
22
|
-
## Layout
|
|
23
|
-
|
|
24
|
-
```
|
|
25
|
-
core.md shared foundation: response format, entry-point rule, runtime, math, tweens
|
|
26
|
-
index.md one-line map of EVERY global — always included (anti-hallucination anchor)
|
|
27
|
-
canvas.md Canvas drawing surface — engine-independent, in every bundle (each engine
|
|
28
|
-
module documents its own hookup: Sprite texture / UIImage src / Texture)
|
|
29
|
-
ui.md UI module (screens, router, styling, widgets, lists)
|
|
30
|
-
2d.md 2D engine module (sprites, tilemaps, Box2D physics, aspects, Canvas)
|
|
31
|
-
3d.md SHARED 3D content (nodes, meshes, models, materials, physics, particles)
|
|
32
|
-
3d-scene.md non-AR scenes: Scene construction, camera control, CharacterController, example
|
|
33
|
-
3d-scene-files.md declarative .scene.ts files (defineScene/use/ref/make, SceneHandle, HUD-over-scene)
|
|
34
|
-
— the visual scene editor's format; non-AR only (camera nodes, skybox env)
|
|
35
|
-
ar.md AR scenes: ARScene, anchors, placement controls, example — never with 3d-scene.md
|
|
36
|
-
core-design.md design mode's core: directives/context/reports, no runtime APIs (no timers/network)
|
|
37
|
-
ui-design.md design mode's UI: curated static-mockup subset of ui.md (KEEP IN SYNC with it)
|
|
38
|
-
design.md design mode: canvas conventions — kit-first, states, design_map tool, tab bar
|
|
39
|
-
concept.md concept mode: product-shaping conversation, writes ONLY design/spec.md
|
|
40
|
-
compose.ts builds dist/<bundle>.md from the modules
|
|
41
|
-
select.ts deterministic bundle detection from project code
|
|
42
|
-
router-prompt.md fallback classifier prompt (empty projects only)
|
|
43
|
-
namer-prompt.md project name + icon-emoji generator (first request of a new project)
|
|
44
|
-
intake-prompt.md new-project intake: clarifying questions + confirmable brief (two Haiku turns)
|
|
45
|
-
```
|
|
46
|
-
|
|
47
|
-
## Bundles (`bun run prompts/compose.ts` → `dist/`)
|
|
48
|
-
|
|
49
|
-
| Bundle | Modules | For |
|
|
50
|
-
|---|---|---|
|
|
51
|
-
| `ui-app` | core + index + canvas + ui | apps: screens, forms, lists, chat, commerce |
|
|
52
|
-
| `2d-game` | core + index + canvas + 2d + ui | flat games, drawing toys |
|
|
53
|
-
| `3d-app` | core + index + canvas + 3d + 3d-scene + 3d-scene-files + ui | 3D games/viewers, scene-editor projects |
|
|
54
|
-
| `ar-app` | core + index + canvas + 3d + ar + ui | AR experiences |
|
|
55
|
-
| `design` | core-design + ui-design + design | design mode: the design/ prototyping canvas |
|
|
56
|
-
| `concept` | concept | concept mode: shape the idea, maintain design/spec.md (~0.8k tokens) |
|
|
57
|
-
|
|
58
|
-
Fixed bundles (not per-request assembly) are deliberate: **each bundle is a stable prompt prefix**,
|
|
59
|
-
so Anthropic prompt caching hits on every generation after the first (~10× cheaper input, lower
|
|
60
|
-
latency). Per-request cherry-picking would produce near-unique prefixes and always pay full price.
|
|
61
|
-
Game bundles include the full UI module because games need HUDs/menus; the ui-app bundle omits the
|
|
62
|
-
engines entirely.
|
|
63
|
-
|
|
64
|
-
## Selecting the bundle
|
|
65
|
-
|
|
66
|
-
`design` and `concept` are different from the engine bundles: they are selected EXPLICITLY by the
|
|
67
|
-
client from the editor's mode switcher (Concept / Design / Build — `x-lecodes-bundle: design` or
|
|
68
|
-
`concept`) — never routed, detected from code, or reachable via the `<bundle>` escalation. The
|
|
69
|
-
engine ladder below applies to Build mode only. Concept turns also carry no code context (design
|
|
70
|
-
excerpts + file names only) and the client enforces each mode's write boundary (concept:
|
|
71
|
-
design/spec.md only; design: design/ only). Any bundle may end a reply with `<mode>x</mode>` — the
|
|
72
|
-
client strips it and renders a "Switch to …" button; the mode never switches itself.
|
|
73
|
-
|
|
74
|
-
For the engine bundles — three signals, in this order:
|
|
75
|
-
|
|
76
|
-
**1. Project code — `select.ts` (primary, deterministic).**
|
|
77
|
-
`detectBundle(files)` scans the project's `.ts` sources for engine globals (comments and string
|
|
78
|
-
literals stripped) and returns the bundle. This is language-independent — it doesn't matter what
|
|
79
|
-
language the user writes in, because it never reads the user's words at all. It covers every
|
|
80
|
-
request against an existing project, i.e. the vast majority of traffic. Priority: AR > 3D > 2D;
|
|
81
|
-
sources with no engine references → `ui-app`. This mirrors the engine-kind detection the compiler
|
|
82
|
-
already does for project icons — if that detection is exposed server-side, reuse it instead.
|
|
83
|
-
|
|
84
|
-
**0. Intake — `intake-prompt.md` (new projects, preferred over the router).**
|
|
85
|
-
The session's first request against a project with no app code runs the intake instead of building:
|
|
86
|
-
one Haiku call returns 2–4 clarifying questions with tappable options (including the app kind when
|
|
87
|
-
the request is ambiguous between kinds), a second call turns the answers into a short brief the
|
|
88
|
-
user confirms. The confirmed kind sets the first build turn's bundle explicitly (`x-lecodes-bundle`
|
|
89
|
-
sent by the client — the router below never runs), and the brief seeds `design/spec.md` as the
|
|
90
|
-
project concept. Intake failure or the user's Skip degrades to the flow below — it never blocks.
|
|
91
|
-
Client side: `frontend/.../chat/engine/intake.ts` + the intake card in `chatController.ts`.
|
|
92
|
-
|
|
93
|
-
**2. Router model — `router-prompt.md` (fallback: intake skipped/failed on empty projects).**
|
|
94
|
-
When `detectBundle` returns `null` (no code yet), classify the user's first message with one cheap
|
|
95
|
-
call: `claude-haiku-4-5`, temperature 0, `max_tokens: 8`, reply is a single word `ui|2d|3d|ar`.
|
|
96
|
-
The prompt is meaning-based and multilingual (EN/RU examples included). Parse defensively; any
|
|
97
|
-
garbage → `ui`. Cost/latency: ~1k input tokens, a few output tokens, ~200–400 ms — negligible, and
|
|
98
|
-
it runs at most once per project's life.
|
|
99
|
-
|
|
100
|
-
**Stickiness.** Cache the chosen bundle per conversation and only move UP
|
|
101
|
-
(`upgradeBundle(current, detected)`: ui → 2d/3d → ar), re-running `detectBundle` over files the
|
|
102
|
-
assistant itself just generated. Never downgrade mid-conversation — it would invalidate the prompt
|
|
103
|
-
cache and confuse in-flight context. Wrong-but-bigger is harmless; wrong-but-smaller causes
|
|
104
|
-
hallucinated APIs.
|
|
105
|
-
|
|
106
|
-
**3. Escalation — the `<bundle>` directive (recovery from a misroute).**
|
|
107
|
-
Code-based detection can never recover from a wrong-but-smaller bundle on its own: a model that
|
|
108
|
-
wasn't shown an engine never emits its globals, so the upgrade never triggers. core.md ("Missing
|
|
109
|
-
engine") therefore instructs the generator to reply with ONLY `<bundle>ar</bundle>` (or `3d`/`2d`)
|
|
110
|
-
when the request needs engine APIs its prompt doesn't document. The client (`parseBundleDirective`
|
|
111
|
-
in `select.ts`) discards that reply, upgrades the pinned bundle, and re-sends the same request
|
|
112
|
-
once — upgrade-only here too; a non-upgradable directive (e.g. a 3D project asking for the 2D
|
|
113
|
-
engine) surfaces as a plain explanation instead. Relatedly, the router's classifier input must be
|
|
114
|
-
ONLY the user's words: the proxy cuts everything before the frontend's `[Request]` marker, so e.g.
|
|
115
|
-
a `.glb` in the project snapshot can't drag an explicit AR request toward `3d`.
|
|
116
|
-
|
|
117
|
-
## Naming new projects
|
|
118
|
-
|
|
119
|
-
`namer-prompt.md` is unrelated to bundle selection but lives here with the other model prompts:
|
|
120
|
-
an assistant request made while the project has NO CODE yet (no non-empty `.ts` file — uploaded
|
|
121
|
-
assets like a `.glb` model don't count as "started") also fires one extra Haiku call in parallel
|
|
122
|
-
(`x-lecodes-bundle: namer`, `chat/engine/projectNamer.ts`) that returns bare JSON `{name, emoji}`;
|
|
123
|
-
the result is saved via the normal project-update API (name + `iconEmoji`, drawn by
|
|
124
|
-
`VProjectIcon`). Uncached — the prompt is far below Haiku's minimum cacheable prefix. Parsing is
|
|
125
|
-
defensive: a garbled reply must never rename the project, so it's rejected rather than truncated
|
|
126
|
-
into place; a rename while the call is in flight also wins over the generated name.
|
|
127
|
-
|
|
128
|
-
**Why not route every request with a model?** It adds a failure mode (misroute → the generator
|
|
129
|
-
confidently invents APIs it wasn't shown), latency, and cost on 100% of traffic to solve a problem
|
|
130
|
-
that exists only for the ~one request per project where no code exists. Residual misroutes are
|
|
131
|
-
recoverable: the index.md map means the generator always knows what exists, and the `<bundle>`
|
|
132
|
-
escalation directive (above) lets it swap in the right engine module instead of guessing.
|
|
133
|
-
|
|
134
|
-
## Keeping prompts honest
|
|
135
|
-
|
|
136
|
-
- `index.md` must list every global exported from `sdk/src/inject.ts` — same contract as
|
|
137
|
-
`docs/check.mjs`. When a global is added, update docs, then the module, then index.md.
|
|
138
|
-
- Known corrections baked into these prompts (do not regress; see `docs/AUTHORING.md`):
|
|
139
|
-
`onEndReached(thresholdPx, cb)` (threshold first), `bgSize: cover|contain|tile` (no `fill`),
|
|
140
|
-
track `deltaX/deltaY` are per-move, engine colors are hex/packed-int only, `animate` can't
|
|
141
|
-
tween strings/colors, `node.physics` (not `.body`), no `Camera2D.follow`, no
|
|
142
|
-
`UIScrollable.scrollTo`, models can't be cloned.
|
|
1
|
+
# Codegen prompts
|
|
2
|
+
|
|
3
|
+
> **Scope: the le.codes PLATFORM assistant only.** These prompts are bundled into `dist/` and served
|
|
4
|
+
> by claude-proxy to the in-editor chat. They are NOT used by local development — Claude Code and
|
|
5
|
+
> `lecodes-cli` never read them; those get the SDK surface from `.lecodes/types` (the d.ts bundle),
|
|
6
|
+
> the generated project `CLAUDE.md` (`lecodes-cli/src/commands/init/templates.ts`) and `sdk/docs`.
|
|
7
|
+
> A change meant for local development belongs there, not here.
|
|
8
|
+
|
|
9
|
+
The system prompt(s) sent to Claude for LeCodes code generation, split into composable modules so
|
|
10
|
+
a request only pays for the API areas it can actually use. Facts come from `../docs/` (the source
|
|
11
|
+
of truth) — when the SDK changes, update docs first, then mirror the change here.
|
|
12
|
+
|
|
13
|
+
**Consumers:**
|
|
14
|
+
- `claude-proxy/prompts/*.md` — deployed copies of `dist/` + `router.md` (see its README); the
|
|
15
|
+
proxy injects them per the `x-lecodes-bundle` header (`claude-proxy/src/proxy/bundles.ts`). An
|
|
16
|
+
unknown/missing header is a **400** (no silent fallback), and the proxy's `/health` exposes a
|
|
17
|
+
sha256-12 per bundle — `bun run check:prompts` (repo root) compares them against `dist/` to
|
|
18
|
+
catch deploy drift (`--dir <proxy>/prompts` checks a local checkout instead).
|
|
19
|
+
- `packages/frontend/.../chat/engine/bundleSelect.ts` — a thin adapter over `select.ts` (imported
|
|
20
|
+
as `sdk/prompts/select`); the selection logic itself is not duplicated anywhere.
|
|
21
|
+
|
|
22
|
+
## Layout
|
|
23
|
+
|
|
24
|
+
```
|
|
25
|
+
core.md shared foundation: response format, entry-point rule, runtime, math, tweens
|
|
26
|
+
index.md one-line map of EVERY global — always included (anti-hallucination anchor)
|
|
27
|
+
canvas.md Canvas drawing surface — engine-independent, in every bundle (each engine
|
|
28
|
+
module documents its own hookup: Sprite texture / UIImage src / Texture)
|
|
29
|
+
ui.md UI module (screens, router, styling, widgets, lists)
|
|
30
|
+
2d.md 2D engine module (sprites, tilemaps, Box2D physics, aspects, Canvas)
|
|
31
|
+
3d.md SHARED 3D content (nodes, meshes, models, materials, physics, particles)
|
|
32
|
+
3d-scene.md non-AR scenes: Scene construction, camera control, CharacterController, example
|
|
33
|
+
3d-scene-files.md declarative .scene.ts files (defineScene/use/ref/make, SceneHandle, HUD-over-scene)
|
|
34
|
+
— the visual scene editor's format; non-AR only (camera nodes, skybox env)
|
|
35
|
+
ar.md AR scenes: ARScene, anchors, placement controls, example — never with 3d-scene.md
|
|
36
|
+
core-design.md design mode's core: directives/context/reports, no runtime APIs (no timers/network)
|
|
37
|
+
ui-design.md design mode's UI: curated static-mockup subset of ui.md (KEEP IN SYNC with it)
|
|
38
|
+
design.md design mode: canvas conventions — kit-first, states, design_map tool, tab bar
|
|
39
|
+
concept.md concept mode: product-shaping conversation, writes ONLY design/spec.md
|
|
40
|
+
compose.ts builds dist/<bundle>.md from the modules
|
|
41
|
+
select.ts deterministic bundle detection from project code
|
|
42
|
+
router-prompt.md fallback classifier prompt (empty projects only)
|
|
43
|
+
namer-prompt.md project name + icon-emoji generator (first request of a new project)
|
|
44
|
+
intake-prompt.md new-project intake: clarifying questions + confirmable brief (two Haiku turns)
|
|
45
|
+
```
|
|
46
|
+
|
|
47
|
+
## Bundles (`bun run prompts/compose.ts` → `dist/`)
|
|
48
|
+
|
|
49
|
+
| Bundle | Modules | For |
|
|
50
|
+
|---|---|---|
|
|
51
|
+
| `ui-app` | core + index + canvas + ui | apps: screens, forms, lists, chat, commerce |
|
|
52
|
+
| `2d-game` | core + index + canvas + 2d + ui | flat games, drawing toys |
|
|
53
|
+
| `3d-app` | core + index + canvas + 3d + 3d-scene + 3d-scene-files + ui | 3D games/viewers, scene-editor projects |
|
|
54
|
+
| `ar-app` | core + index + canvas + 3d + ar + ui | AR experiences |
|
|
55
|
+
| `design` | core-design + ui-design + design | design mode: the design/ prototyping canvas |
|
|
56
|
+
| `concept` | concept | concept mode: shape the idea, maintain design/spec.md (~0.8k tokens) |
|
|
57
|
+
|
|
58
|
+
Fixed bundles (not per-request assembly) are deliberate: **each bundle is a stable prompt prefix**,
|
|
59
|
+
so Anthropic prompt caching hits on every generation after the first (~10× cheaper input, lower
|
|
60
|
+
latency). Per-request cherry-picking would produce near-unique prefixes and always pay full price.
|
|
61
|
+
Game bundles include the full UI module because games need HUDs/menus; the ui-app bundle omits the
|
|
62
|
+
engines entirely.
|
|
63
|
+
|
|
64
|
+
## Selecting the bundle
|
|
65
|
+
|
|
66
|
+
`design` and `concept` are different from the engine bundles: they are selected EXPLICITLY by the
|
|
67
|
+
client from the editor's mode switcher (Concept / Design / Build — `x-lecodes-bundle: design` or
|
|
68
|
+
`concept`) — never routed, detected from code, or reachable via the `<bundle>` escalation. The
|
|
69
|
+
engine ladder below applies to Build mode only. Concept turns also carry no code context (design
|
|
70
|
+
excerpts + file names only) and the client enforces each mode's write boundary (concept:
|
|
71
|
+
design/spec.md only; design: design/ only). Any bundle may end a reply with `<mode>x</mode>` — the
|
|
72
|
+
client strips it and renders a "Switch to …" button; the mode never switches itself.
|
|
73
|
+
|
|
74
|
+
For the engine bundles — three signals, in this order:
|
|
75
|
+
|
|
76
|
+
**1. Project code — `select.ts` (primary, deterministic).**
|
|
77
|
+
`detectBundle(files)` scans the project's `.ts` sources for engine globals (comments and string
|
|
78
|
+
literals stripped) and returns the bundle. This is language-independent — it doesn't matter what
|
|
79
|
+
language the user writes in, because it never reads the user's words at all. It covers every
|
|
80
|
+
request against an existing project, i.e. the vast majority of traffic. Priority: AR > 3D > 2D;
|
|
81
|
+
sources with no engine references → `ui-app`. This mirrors the engine-kind detection the compiler
|
|
82
|
+
already does for project icons — if that detection is exposed server-side, reuse it instead.
|
|
83
|
+
|
|
84
|
+
**0. Intake — `intake-prompt.md` (new projects, preferred over the router).**
|
|
85
|
+
The session's first request against a project with no app code runs the intake instead of building:
|
|
86
|
+
one Haiku call returns 2–4 clarifying questions with tappable options (including the app kind when
|
|
87
|
+
the request is ambiguous between kinds), a second call turns the answers into a short brief the
|
|
88
|
+
user confirms. The confirmed kind sets the first build turn's bundle explicitly (`x-lecodes-bundle`
|
|
89
|
+
sent by the client — the router below never runs), and the brief seeds `design/spec.md` as the
|
|
90
|
+
project concept. Intake failure or the user's Skip degrades to the flow below — it never blocks.
|
|
91
|
+
Client side: `frontend/.../chat/engine/intake.ts` + the intake card in `chatController.ts`.
|
|
92
|
+
|
|
93
|
+
**2. Router model — `router-prompt.md` (fallback: intake skipped/failed on empty projects).**
|
|
94
|
+
When `detectBundle` returns `null` (no code yet), classify the user's first message with one cheap
|
|
95
|
+
call: `claude-haiku-4-5`, temperature 0, `max_tokens: 8`, reply is a single word `ui|2d|3d|ar`.
|
|
96
|
+
The prompt is meaning-based and multilingual (EN/RU examples included). Parse defensively; any
|
|
97
|
+
garbage → `ui`. Cost/latency: ~1k input tokens, a few output tokens, ~200–400 ms — negligible, and
|
|
98
|
+
it runs at most once per project's life.
|
|
99
|
+
|
|
100
|
+
**Stickiness.** Cache the chosen bundle per conversation and only move UP
|
|
101
|
+
(`upgradeBundle(current, detected)`: ui → 2d/3d → ar), re-running `detectBundle` over files the
|
|
102
|
+
assistant itself just generated. Never downgrade mid-conversation — it would invalidate the prompt
|
|
103
|
+
cache and confuse in-flight context. Wrong-but-bigger is harmless; wrong-but-smaller causes
|
|
104
|
+
hallucinated APIs.
|
|
105
|
+
|
|
106
|
+
**3. Escalation — the `<bundle>` directive (recovery from a misroute).**
|
|
107
|
+
Code-based detection can never recover from a wrong-but-smaller bundle on its own: a model that
|
|
108
|
+
wasn't shown an engine never emits its globals, so the upgrade never triggers. core.md ("Missing
|
|
109
|
+
engine") therefore instructs the generator to reply with ONLY `<bundle>ar</bundle>` (or `3d`/`2d`)
|
|
110
|
+
when the request needs engine APIs its prompt doesn't document. The client (`parseBundleDirective`
|
|
111
|
+
in `select.ts`) discards that reply, upgrades the pinned bundle, and re-sends the same request
|
|
112
|
+
once — upgrade-only here too; a non-upgradable directive (e.g. a 3D project asking for the 2D
|
|
113
|
+
engine) surfaces as a plain explanation instead. Relatedly, the router's classifier input must be
|
|
114
|
+
ONLY the user's words: the proxy cuts everything before the frontend's `[Request]` marker, so e.g.
|
|
115
|
+
a `.glb` in the project snapshot can't drag an explicit AR request toward `3d`.
|
|
116
|
+
|
|
117
|
+
## Naming new projects
|
|
118
|
+
|
|
119
|
+
`namer-prompt.md` is unrelated to bundle selection but lives here with the other model prompts:
|
|
120
|
+
an assistant request made while the project has NO CODE yet (no non-empty `.ts` file — uploaded
|
|
121
|
+
assets like a `.glb` model don't count as "started") also fires one extra Haiku call in parallel
|
|
122
|
+
(`x-lecodes-bundle: namer`, `chat/engine/projectNamer.ts`) that returns bare JSON `{name, emoji}`;
|
|
123
|
+
the result is saved via the normal project-update API (name + `iconEmoji`, drawn by
|
|
124
|
+
`VProjectIcon`). Uncached — the prompt is far below Haiku's minimum cacheable prefix. Parsing is
|
|
125
|
+
defensive: a garbled reply must never rename the project, so it's rejected rather than truncated
|
|
126
|
+
into place; a rename while the call is in flight also wins over the generated name.
|
|
127
|
+
|
|
128
|
+
**Why not route every request with a model?** It adds a failure mode (misroute → the generator
|
|
129
|
+
confidently invents APIs it wasn't shown), latency, and cost on 100% of traffic to solve a problem
|
|
130
|
+
that exists only for the ~one request per project where no code exists. Residual misroutes are
|
|
131
|
+
recoverable: the index.md map means the generator always knows what exists, and the `<bundle>`
|
|
132
|
+
escalation directive (above) lets it swap in the right engine module instead of guessing.
|
|
133
|
+
|
|
134
|
+
## Keeping prompts honest
|
|
135
|
+
|
|
136
|
+
- `index.md` must list every global exported from `sdk/src/inject.ts` — same contract as
|
|
137
|
+
`docs/check.mjs`. When a global is added, update docs, then the module, then index.md.
|
|
138
|
+
- Known corrections baked into these prompts (do not regress; see `docs/AUTHORING.md`):
|
|
139
|
+
`onEndReached(thresholdPx, cb)` (threshold first), `bgSize: cover|contain|tile` (no `fill`),
|
|
140
|
+
track `deltaX/deltaY` are per-move, engine colors are hex/packed-int only, `animate` can't
|
|
141
|
+
tween strings/colors, `node.physics` (not `.body`), no `Camera2D.follow`, no
|
|
142
|
+
`UIScrollable.scrollTo`, models can't be cloned.
|