Canvas AI: Client-side orchestration loop for Canvas AI(POC)
## Problem
Every Canvas AI request is a single synchronous PHP call. The full chain — orchestrator → sub-agent → tool calls → validation — must complete before the server responds. This causes two concrete failures:
- **Timeouts on hosted platforms (e.g. DrupalForge).** A full page build exceeds the request time limit. The user gets nothing.
- **Full regeneration on any error.** If one component in a large response fails validation, the entire response is regenerated — wasting time and tokens.
There is no streaming and no partial feedback.
## How `ai_chatbot` already solves this
The `ai_chatbot` module's DeepChat integration avoids this problem by moving the agent loop to the client. Instead of one long-running PHP request that drives the full agent chain, it works as follows:
1. **The server does one unit of work per request.** Each PHP request runs a single agent step (one tool call or sub-agent invocation), then returns immediately with two things: the intermediate result (e.g. "Calling component agent…") and a `should_continue: true` flag.
2. **The client drives the loop.** When `should_continue` is `true`, the browser's `responseInterceptor` in `deepchat-init.js` immediately fires another request to the same endpoint. This continues request by request until the server returns `should_continue: false`, meaning the agent is done.
3. **The UI updates after every step.** Each intermediate response is rendered in the chat (as a collapsible "Details" block) so the user sees progress in real time, not a blank wait.
The key insight: **no single request stays open long enough to time out**. Each one is short-lived and returns quickly; the browser reconnects immediately for the next step.
## Goal of this POC
Explore whether Canvas AI can adopt the same client-side loop pattern for page building, so that:
- Page builds no longer time out on DrupalForge or similar platforms.
- Components appear in the Canvas editor incrementally as each section is placed, rather than all at once at the end.
- A validation failure on one component triggers a retry of only that component, not the entire page.
## The key challenge Canvas AI adds
In `ai_chatbot`, when a sub-agent performs backend work — creating a content type, adding fields — the only real-time feedback needed is a chat message. The work happens entirely on the server and the browser just displays text.
Canvas AI is different. Components are placed in the page editor by dispatching operations to the Redux `layoutModel` in the browser. There is no server-side placement — the editor state lives in the client. This means incremental placement cannot be solved by chat messages alone. Each agent step that places a component must also return structured layout operations that `AiWizard.tsx` dispatches immediately, so the component actually appears in the editor before the next step begins.
## Approach
Adapt the `should_continue` loop pattern from `ai_chatbot` to `CanvasBuilder.php` and `AiWizard.tsx`:
- **Server:** `CanvasBuilder.php` returns after each discrete agent step with a `should_continue` flag. If the step placed components, the response also includes the corresponding layout operations (the same `ADD` operation structure that `AiWizard.tsx` already understands).
- **Client:** `AiWizard.tsx` checks `should_continue`, dispatches any layout operations in the response to Redux immediately (so the component appears in the editor), then re-sends the request for the next step.
- **Incremental placement:** the agent places one top-level section per step rather than generating the full page structure before placing anything. The user sees the page build up row by row in real time.
Additionally, evaluate replacing AI-generated YAML with a minimal DSL that is less error-prone to parse, reducing the validation failures that currently force full regeneration (see #3584087).
_Issue summary generated with the assistance of an LLM._
issue