Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion docs-web/content/docs/user-dashboard-chat.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ To start a new thread, click **+ New thread**. To change the responding agent, o

Each post triggers a routed invocation: the dashboard records the request, dispatches it to the chosen provider via the worker assignment service (routed through the `dashboard_reply` invocation type), and streams the reply back into the thread.

In 3D Chat, idle quick actions send project-scoped prompts directly through the active thread. **Web App** and **Desktop App** quickactions attach create-app metadata with a stable request id, app kind, quicksprint template id, stack summary, and suggestion tags. The backend marks the chat message processed immediately, launches the matching quicksprint in detached `Plan & Start` mode, and posts an app-progress system widget while planning continues. The widget shows the app kind, sprint, stack summary, metadata-driven stages from Planning through Showing each Task to Finish, and suggestion tags for follow-up direction without exposing raw JSON. Non-app quickactions still use the normal routed chat reply path.
In 3D Chat, idle quick actions send project-scoped prompts directly through the active thread. **Web App** and **Desktop App** quickactions attach create-app metadata with a stable request id, app kind, quicksprint template id, stack summary, and suggestion tags. The backend marks the chat message processed immediately, launches the matching quicksprint in detached `Plan & Start` mode, and posts an app-progress system widget while planning continues. Follow-up messages in the same thread are queued until planning finishes when no tasks exist yet, then appended to the sprint goal under `Additional direction from chat`; after tasks exist, follow-ups update the sprint direction immediately and the thread receives a confirmation. The widget shows the app kind, sprint, stack summary, metadata-driven stages from Planning through Showing each Task to Finish, and suggestion tags for follow-up direction without exposing raw JSON. Non-app quickactions still use the normal routed chat reply path.

Planning messages can include a rich sprint status card. When Code UX can match the message to loaded live project data, the card is backed by the current task records and execution snapshot, so it updates as tasks move from queued to running, completed, failed, blocked, or quota-waiting. It shows the sprint key/name, request/task/run materialization, overall progress such as `0/7 · 0%`, queued task count, and a compact task list. If either task records or the execution snapshot are still loading, the chat keeps the generic planning status card until both live records are available for the active project.

Expand Down
2 changes: 1 addition & 1 deletion docs-web/content/docs/user-quicksprints.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -62,7 +62,7 @@ From the **⋯** menu on a template card:
| DELETE | `/api/projects/:projectId/quicksprints/templates/:templateId` | Delete |
| POST | `/api/projects/:projectId/quicksprints/execute` | Execute (returns the new sprint) |

The REST execution route keeps awaited semantics: it returns the sprint only after planning completes or fails. Chat quickactions can use the internal detached quicksprint launch primitive when they need the created sprint immediately and want planning to continue in the background with a `clientRequestId` for tracking.
The REST execution route keeps awaited semantics: it returns the sprint only after planning completes or fails. Chat quickactions can use the internal detached quicksprint launch primitive when they need the created sprint immediately and want planning to continue in the background with a `clientRequestId` and planning promise for tracking. Create-app chat follow-ups use that completion signal to update the app progress widget and append queued direction to the sprint goal without frontend polling.

## Examples

Expand Down
2 changes: 1 addition & 1 deletion docs-web/user/dashboard/chat.md
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ To start a new thread, click **+ New thread**. To change the responding agent, o

Each post is a runtime operation that honors the explicit route chosen (worker route, virtual provider route, automatic live-worker pickup, or fallback). The dashboard exposes in-flight state locally, allowing you to cancel active thread turns or invocations. Failed invocation restarts preserve the failed invocation transcript and expose the existing sanitized error message with a retry action.

In 3D Chat, idle quick actions send project-scoped prompts directly through the active thread. **Web App** and **Desktop App** quickactions attach create-app metadata with a stable request id, app kind, quicksprint template id, stack summary, and suggestion tags. The backend marks the chat message processed immediately, launches the matching quicksprint in detached `Plan & Start` mode, and posts an app-progress system widget while planning continues. The widget shows the app kind, sprint, stack summary, metadata-driven stages from Planning through Showing each Task to Finish, and suggestion tags for follow-up direction without exposing raw JSON. Non-app quickactions still use the normal routed chat reply path.
In 3D Chat, idle quick actions send project-scoped prompts directly through the active thread. **Web App** and **Desktop App** quickactions attach create-app metadata with a stable request id, app kind, quicksprint template id, stack summary, and suggestion tags. The backend marks the chat message processed immediately, launches the matching quicksprint in detached `Plan & Start` mode, and posts an app-progress system widget while planning continues. Follow-up messages in the same thread are queued until planning finishes when no tasks exist yet, then appended to the sprint goal under `Additional direction from chat`; after tasks exist, follow-ups update the sprint direction immediately and the thread receives a confirmation. The backend preserves follow-ups posted while planning resolves by merging the latest thread state before it clears the active planning marker, and it re-checks task count after queue writes so direction is applied immediately if tasks materialized during the write. The widget shows the app kind, sprint, stack summary, metadata-driven stages from Planning through Showing each Task to Finish, and suggestion tags for follow-up direction without exposing raw JSON. Non-app quickactions still use the normal routed chat reply path.

Planning messages can include a rich sprint status card. When Code UX can match the message to loaded live project data, the card is backed by the current task records and execution snapshot, so it updates as tasks move from queued to running, completed, failed, blocked, or quota-waiting. It shows the sprint key/name, request/task/run materialization, overall progress such as `0/7 · 0%`, queued task count, and a compact task list. If either task records or the execution snapshot are still loading, the chat keeps the generic planning status card until both live records are available for the active project.

Expand Down
2 changes: 2 additions & 0 deletions docs/architecture/chat-thread-runtime.md
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,8 @@ This keeps the chat page's explicit route selector authoritative for new-thread

Message posting is an awaited runtime operation. `POST /api/projects/:projectId/conversations/messages` waits for the chat runtime to finish routing the dashboard turn before returning the stored dashboard message, so provider/runtime errors are handled inside the same request lifecycle instead of continuing as detached background work.

Create-app dashboard quickactions are the narrow exception to normal provider reply routing. The runtime marks the quickaction message processed, launches the matching quicksprint in detached plan-and-start mode, stores the active sprint id, app kind, planning status, progress widget message id, and queued follow-up messages in thread `runtimeState.createAppQuickaction`, and returns after the app progress widget is posted. Plain chat messages in the same thread while planning is still running and the sprint has no tasks are stored as queued follow-ups and acknowledged with a system message. When the detached planning promise settles, the backend updates the app progress widget to `completed` or `failed`, clears only the active planning request marker, and on success appends queued follow-ups to the sprint-level goal under `## Additional direction from chat`. The create-app runtime-state writer re-reads the thread immediately before each queued follow-up or planning-completion write so concurrent `queuedFollowUps`, `planningStatus`, and `activePlanningRequestId` changes are merged instead of overwritten by stale snapshots. It also re-checks sprint task count after a queued follow-up write; if tasks appeared during that write, the queued direction is flushed to the sprint immediately instead of waiting for planning completion. If the sprint already has tasks when a follow-up arrives, the same delimited section is appended immediately and the thread receives a system confirmation. Failed planning keeps queued follow-up text in runtime state for recovery.

The dashboard can also cancel the currently running turn for a specific thread through `POST /api/conversations/threads/:threadId/cancel`. That aborts only the matching in-flight thread turn and leaves other thread executions alone.

Thread and invocation controls expose their in-flight state locally. Sending a message, cancelling an active turn, compacting a thread, deleting a thread, cancelling an invocation, and restarting/continuing a failed invocation disable duplicate submissions, announce busy status through button labels/`aria-busy`, and keep retryable feedback in `ActionFeedbackRegion` when the server returns an error. Failed message sends keep the draft restored in the composer; failed invocation restarts preserve the failed invocation transcript and expose the existing sanitized error message with a retry action.
Expand Down
2 changes: 1 addition & 1 deletion docs/dashboard/design-system-chat.md
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@ The chat page opens in a cinematic "3D Chat" stage (`components/chat/cinematic/C
- **Floating composer**: a bottom-center glass pill shared with the Threads data flow — Enter sends, first send auto-creates the thread, ArrowUp/Down recalls history.
- **Expressions catalog**: the avatar vocabulary (SVG + WebGL, kept in sync) now includes `curious`, `thinking`, `excited`, `laughing`, `surprised`, `wink`, `dance`, and `proud` in addition to the original eight.
- **Work tools**: while the runtime is in the working phase the bot pulls an animated 3D tool from its toolbox beside itself — cordless screwdriver (spinning bit), jackhammer (hammering chisel + judder), wrench (ratcheting swing), welding torch (flickering glow) — swapping every ~7s (`tool` prop on `AgentAvatarScene`; pin one for design review with `/chat?stageTool=<kind>`).
- **Idle quick actions**: six glass chips float around the idle bot (web app setup, desktop app setup, status report, sprint progress, what's failing, plan next steps). Clicking **sends the prompt immediately** via `handleSend(overrideText)` — no composer round-trip. Web and desktop app quickactions can attach `create_app` metadata with a stable request id, app kind, quicksprint template id, stack summary, and suggestion tags; the backend marks the chat message processed, launches the matching detached quicksprint with `submitMode: "plan_and_start"`, and posts an `app_progress` system widget while planning continues. Non-app quickactions still use the normal routed chat reply path. They hide while sending/working/error and on small screens.
- **Idle quick actions**: six glass chips float around the idle bot (web app setup, desktop app setup, status report, sprint progress, what's failing, plan next steps). Clicking **sends the prompt immediately** via `handleSend(overrideText)` — no composer round-trip. Web and desktop app quickactions can attach `create_app` metadata with a stable request id, app kind, quicksprint template id, stack summary, and suggestion tags; the backend marks the chat message processed, launches the matching detached quicksprint with `submitMode: "plan_and_start"`, and posts an `app_progress` system widget while planning continues. Plain follow-up chat in the same thread is queued until planning finishes if no tasks exist yet, then appended to the sprint-level goal under `Additional direction from chat`; once tasks exist, follow-ups append immediately and the backend posts a confirmation. The backend re-reads the thread before writing queued follow-ups or planning-completion state, and re-checks task count after queue writes, so follow-ups posted as planning resolves or as tasks materialize are preserved and appended. The widget metadata moves to `completed` or `failed` when detached planning settles. Non-app quickactions still use the normal routed chat reply path. They hide while sending/working/error and on small screens.
- **Reduced motion**: the scene falls back to the static SVG bot; aurora, thinking dots, quick-action float, and drift animations are disabled via `prefers-reduced-motion`.

### Stage widget vocabulary (agent-facing)
Expand Down
2 changes: 1 addition & 1 deletion docs/dashboard/quicksprint-templates.md
Original file line number Diff line number Diff line change
Expand Up @@ -105,7 +105,7 @@ The REST API and MCP `manage_quicksprints` tool expose these actions:
- `execute`: Plans a quicksprint. Payload supports `taskCount`, `noTaskLimit`, `submitMode`, `routeOverride`, and `modelOverride`. Defaults to `submitMode: "plan_only"`.
- `start`: Alias for execution defaulting to `submitMode: "plan_and_start"`.

`QuicksprintService.launchDetachedQuicksprint` is the internal primitive for chat quickactions that need a sprint record immediately while planning continues in the background. It creates the sprint synchronously, starts the same planning flow with the same prompt composition and override resolution as `execute`, and returns a planning request descriptor with `projectId`, `sprintId`, `templateId`, `submitMode`, `clientRequestId`, and planner options for request tracking. The existing REST `/api/projects/:projectId/quicksprints/execute` route and MCP `execute` / `start` actions remain awaited: they return only after planning completes or fails.
`QuicksprintService.launchDetachedQuicksprint` is the internal primitive for chat quickactions that need a sprint record immediately while planning continues in the background. It creates the sprint synchronously, starts the same planning flow with the same prompt composition and override resolution as `execute`, and returns a planning request descriptor with `projectId`, `sprintId`, `templateId`, `submitMode`, `clientRequestId`, planner options for request tracking, and the detached planning promise. Chat create-app quickactions attach to that promise so the backend can update the app progress widget and append any queued thread follow-ups to the sprint goal after planning resolves, without frontend polling. The existing REST `/api/projects/:projectId/quicksprints/execute` route and MCP `execute` / `start` actions remain awaited: they return only after planning completes or fails.

Current built-in purpose set:
- `Fullstack JS App`
Expand Down
29 changes: 29 additions & 0 deletions provider-last-message-cli-codex-mrahup7i-568aa7aa.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
Implemented the create-app follow-up persistence flow.

Changed:
- Added durable create-app quickaction runtime state in `src/contracts/connection-chat-types.ts`.
- Exposed the detached quicksprint `planningPromise` in `src/contracts/quicksprint-types.ts` and `src/services/quicksprint-service.ts`.
- Updated `ChatThreadRuntimeService` to:
- queue follow-up chat while planning is running and no tasks exist
- append follow-ups immediately once tasks exist
- append queued follow-ups after detached planning completes
- update app progress widget metadata to `completed` / `failed`
- preserve queued text on planning failure
- avoid marking failed follow-up messages as processed
- Added message metadata update/read helpers plus `conversation.message.updated` realtime events.
- Updated focused backend tests and affected docs, including public docs-web pages.
- Created `.task-learnings.md`.

Verification:
- Passed: `pnpm exec vitest run tests/backend/services/chat-thread-runtime-service.test.ts` (`25 passed`)
- Passed: `pnpm exec vitest run tests/backend/server/dashboard-chat-api.test.ts` (`4 passed`)
- Passed: `pnpm exec vitest run tests/backend/services/quicksprint-service.test.ts` (`30 passed`)
- Passed: `pnpm run lint`
- Passed: `pnpm run build`

Requested broad commands:
- `pnpm run test:backend -- tests/backend/services/chat-thread-runtime-service.test.ts` failed because the script ran the full backend suite and unrelated sprint preview tests could not find free ports in `5555-5560`.
- `pnpm run test:backend -- tests/backend/server/dashboard-chat-api.test.ts` failed for the same unrelated sprint preview port issue plus an unrelated planning-agent retry assertion.

Also checked docs:
- `pnpm run check:docs-web` still reports broad generated-doc drift across 28 files. I updated only the affected public docs pages directly to keep this task scoped.
23 changes: 23 additions & 0 deletions src/contracts/connection-chat-types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,7 @@ export interface ConversationRuntimeState {
approvalMessage: string;
proposedAt: string;
} | null;
createAppQuickaction?: DashboardCreateAppQuickactionRuntimeState | null;
}

export const DASHBOARD_CREATE_APP_QUICKACTION_KINDS = ["web_app", "desktop_app"] as const;
Expand Down Expand Up @@ -92,6 +93,28 @@ export interface DashboardCreateAppQuickactionMetadata {
};
}

export type DashboardCreateAppQuickactionPlanningStatus = "running" | "completed" | "failed";

export interface DashboardCreateAppQueuedFollowUp {
messageId: string;
bodyMarkdown: string;
createdAt: string;
}

export interface DashboardCreateAppQuickactionRuntimeState {
activeSprintId: string;
appKind: DashboardCreateAppQuickactionKind;
planningStatus: DashboardCreateAppQuickactionPlanningStatus;
queuedFollowUps: DashboardCreateAppQueuedFollowUp[];
quickactionRequestId: string;
clientRequestId: string;
activePlanningRequestId?: string;
progressMessageId?: string | null;
planningError?: string | null;
completedAt?: string;
failedAt?: string;
}

export interface DashboardAppProgressPlanningStage {
id: "planning" | "plan" | "start" | "finish";
label: "Planning" | "Plan" | "Start" | "Finish";
Expand Down
1 change: 1 addition & 0 deletions src/contracts/quicksprint-types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -71,4 +71,5 @@ export interface DetachedQuicksprintPlanningRequest {
export interface DetachedQuicksprintLaunchResult {
sprint: SprintRecord;
planningRequest: DetachedQuicksprintPlanningRequest;
planningPromise: Promise<unknown>;
}
Loading