@molecule/app-ide-react 1.0.0 → 1.0.1
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/README.md
ADDED
|
@@ -0,0 +1,2751 @@
|
|
|
1
|
+
<!--
|
|
2
|
+
AUTO-GENERATED — DO NOT EDIT THIS FILE.
|
|
3
|
+
Generated by `mlcl sync-docs` from the package's src/index.ts JSDoc + mlcl/registry.json.
|
|
4
|
+
Edits here are overwritten on the next commit (molecule's pre-commit hook regenerates).
|
|
5
|
+
To change this document, edit the module-level JSDoc in src/index.ts.
|
|
6
|
+
Generated: 2026-08-04T01:51:04.596Z
|
|
7
|
+
-->
|
|
8
|
+
|
|
9
|
+
# @molecule/app-ide-react
|
|
10
|
+
|
|
11
|
+
> **Auto-generated, AI-first package reference** for the [molecule.dev](https://molecule.dev) ecosystem.
|
|
12
|
+
> It is written to be read by coding agents as much as by people, and is generated from this
|
|
13
|
+
> package's source — edit `src/index.ts` JSDoc, not this file.
|
|
14
|
+
|
|
15
|
+
`@molecule/app-ide-react` — React components for an AI-powered IDE
|
|
16
|
+
workspace: `WorkspaceLayout` (resizable panel row), `ChatPanel` (streaming
|
|
17
|
+
AI chat with tool-call cards, @ file mentions, / commands), `EditorPanel`
|
|
18
|
+
(tabbed Monaco editor), `PreviewPanel` (live-preview iframe with device
|
|
19
|
+
frames + crash/blank recovery), `FileExplorer`, `CommandPalette`,
|
|
20
|
+
`QuickOpen`, `TabBar`, plus `registerCustomEventCard()` for app-specific
|
|
21
|
+
chat cards and `useKeyboardShortcuts()`.
|
|
22
|
+
|
|
23
|
+
## Quick Start
|
|
24
|
+
|
|
25
|
+
```tsx
|
|
26
|
+
import { ChatPanel, EditorPanel, PreviewPanel, WorkspaceLayout } from '@molecule/app-ide-react'
|
|
27
|
+
|
|
28
|
+
;<WorkspaceLayout>
|
|
29
|
+
<ChatPanel
|
|
30
|
+
projectId="proj_abc123"
|
|
31
|
+
onFileOpen={(path) => console.log('open', path)}
|
|
32
|
+
onFileChange={(path, content) => console.log('changed', path, content.length)}
|
|
33
|
+
onReadyToBuild={() => console.log('boot sandbox')}
|
|
34
|
+
/>
|
|
35
|
+
<EditorPanel
|
|
36
|
+
onActiveFileChange={(path) => console.log('active', path)}
|
|
37
|
+
onFixWithAI={(req) => console.log('fix', req)}
|
|
38
|
+
/>
|
|
39
|
+
<PreviewPanel onPreviewError={(errs) => console.error(errs)} />
|
|
40
|
+
</WorkspaceLayout>
|
|
41
|
+
```
|
|
42
|
+
|
|
43
|
+
## Type
|
|
44
|
+
|
|
45
|
+
`feature`
|
|
46
|
+
|
|
47
|
+
## Installation
|
|
48
|
+
|
|
49
|
+
```bash
|
|
50
|
+
npm install @molecule/app-ide-react @molecule/app-ai-chat @molecule/app-ai-models @molecule/app-ai-voice @molecule/app-code-editor @molecule/app-country-flags @molecule/app-i18n @molecule/app-icons @molecule/app-ide @molecule/app-live-preview @molecule/app-logger @molecule/app-react @molecule/app-storage @molecule/app-ui @molecule/app-ui-react material-file-icons react react-dom
|
|
51
|
+
npm install -D @types/react
|
|
52
|
+
```
|
|
53
|
+
|
|
54
|
+
## API
|
|
55
|
+
|
|
56
|
+
### Interfaces
|
|
57
|
+
|
|
58
|
+
#### `Activity`
|
|
59
|
+
|
|
60
|
+
A single captured activity. Mirrors the SSE `activity.activity` payload; the
|
|
61
|
+
REST list endpoint additionally returns `payload` and `result` for the
|
|
62
|
+
expanded detail view.
|
|
63
|
+
|
|
64
|
+
```typescript
|
|
65
|
+
interface Activity {
|
|
66
|
+
id: string
|
|
67
|
+
type: ActivityType
|
|
68
|
+
status: ActivityStatus
|
|
69
|
+
recipient?: string
|
|
70
|
+
summary?: string
|
|
71
|
+
/** ISO 8601 timestamp. */
|
|
72
|
+
timestamp: string
|
|
73
|
+
/** Full captured payload — only present on the REST detail response (dev only). */
|
|
74
|
+
payload?: unknown
|
|
75
|
+
/** Provider result / synthetic success record — only present on the REST detail response. */
|
|
76
|
+
result?: unknown
|
|
77
|
+
}
|
|
78
|
+
```
|
|
79
|
+
|
|
80
|
+
#### `ActivityCardProps`
|
|
81
|
+
|
|
82
|
+
Props for the inline {@link ActivityCard}.
|
|
83
|
+
|
|
84
|
+
```typescript
|
|
85
|
+
interface ActivityCardProps {
|
|
86
|
+
/** The captured activity to render. */
|
|
87
|
+
activity: Activity
|
|
88
|
+
/** Called when the card is clicked — should open the Activity panel filtered to this activity. */
|
|
89
|
+
onActivityClick?: (activity: Activity) => void
|
|
90
|
+
}
|
|
91
|
+
```
|
|
92
|
+
|
|
93
|
+
#### `AutoCommitState`
|
|
94
|
+
|
|
95
|
+
The countdown's state.
|
|
96
|
+
|
|
97
|
+
`intervalSeconds` is the configured cadence (`0` = disabled). `remaining` is
|
|
98
|
+
the live count: a positive number while counting down, `0` at the instant a
|
|
99
|
+
commit is due, and `null` while disabled or paused (after a commit, awaiting
|
|
100
|
+
the next file change to re-arm).
|
|
101
|
+
|
|
102
|
+
```typescript
|
|
103
|
+
interface AutoCommitState {
|
|
104
|
+
/** Configured countdown length in seconds; `0` when auto-commit is off. */
|
|
105
|
+
intervalSeconds: number
|
|
106
|
+
/** Seconds left until the next auto-commit; `null` when disabled or paused. */
|
|
107
|
+
remaining: number | null
|
|
108
|
+
}
|
|
109
|
+
```
|
|
110
|
+
|
|
111
|
+
#### `ChatEventCard`
|
|
112
|
+
|
|
113
|
+
A chat system card: a short message with an optional action (or actions). Mirrors
|
|
114
|
+
the system-card shape ChatPanel renders for upgrade prompts, guest reminders, etc.
|
|
115
|
+
|
|
116
|
+
```typescript
|
|
117
|
+
interface ChatEventCard {
|
|
118
|
+
/** The card's text. */
|
|
119
|
+
text: string
|
|
120
|
+
/** An optional action button (or buttons): a link (`href`) and/or a click handler. */
|
|
121
|
+
action?: ChatEventCardAction | ChatEventCardAction[]
|
|
122
|
+
/**
|
|
123
|
+
* Composable inline body for a `tone` (tip) card: an ordered list of segments rendered
|
|
124
|
+
* in sequence — plain strings as text, {@link ChatEventCardAction}s as inline underlined
|
|
125
|
+
* links — so prose and links interleave freely (e.g. text → an inline link → a trailing
|
|
126
|
+
* period). When set, the renderer uses this INSTEAD of `text` + appended `action`s, so a
|
|
127
|
+
* link can sit mid-sentence rather than only at the end. Segments carry their own spacing
|
|
128
|
+
* (no auto-space is inserted between them). Keep `text` populated with a plain-text
|
|
129
|
+
* equivalent for accessibility / non-toned consumers. Only honored when `tone` is set.
|
|
130
|
+
*/
|
|
131
|
+
content?: ChatEventCardSegment[]
|
|
132
|
+
/**
|
|
133
|
+
* When true, ChatPanel renders the card as a stand-out tip box rather than muted inline
|
|
134
|
+
* text. Prefer setting {@link ChatEventCard.tone} (which implies emphasis AND picks the
|
|
135
|
+
* accent colour + icon); `emphasized` without a `tone` falls back to the neutral `info`
|
|
136
|
+
* tone. The app opts in; the shared package never infers emphasis from a card's copy.
|
|
137
|
+
*/
|
|
138
|
+
emphasized?: boolean
|
|
139
|
+
/**
|
|
140
|
+
* The card's tip TONE — picks its accent colour + default icon so every notice card
|
|
141
|
+
* shares ONE consistent box (icon + tinted body + a uniform 1px border + actions),
|
|
142
|
+
* differing only by colour/icon per kind:
|
|
143
|
+
* - `info` — blue, info glyph (neutral notice)
|
|
144
|
+
* - `gold` — amber, lightbulb (an honest tip / onboarding note)
|
|
145
|
+
* - `upgrade` — amber, clock (a plan/limit/budget nudge)
|
|
146
|
+
* - `success` — green, check (a completed action, e.g. a saved script)
|
|
147
|
+
* - `signup` — primary, sign-in (an auth nudge)
|
|
148
|
+
*
|
|
149
|
+
* Setting `tone` implies emphasis. Cards that supply composable {@link ChatEventCard.content}
|
|
150
|
+
* render their inline links in the box; cards that supply `action`(s) render them as a
|
|
151
|
+
* consistent row of accent buttons. Omit `tone` (and `emphasized`) for a plain muted line.
|
|
152
|
+
*/
|
|
153
|
+
tone?: 'info' | 'gold' | 'upgrade' | 'success' | 'signup'
|
|
154
|
+
/**
|
|
155
|
+
* Optional icon-name override (a `@molecule/app-icons` glyph) — defaults to the tone's
|
|
156
|
+
* icon. Use only a name that exists in the bonded set (`getIcon` throws otherwise);
|
|
157
|
+
* sets with extra glyphs register them via `CustomIconNames` augmentation.
|
|
158
|
+
*/
|
|
159
|
+
icon?: IconName
|
|
160
|
+
}
|
|
161
|
+
```
|
|
162
|
+
|
|
163
|
+
#### `ChatEventCardAction`
|
|
164
|
+
|
|
165
|
+
A single call-to-action on a chat card: a labelled link (`href`) and/or click
|
|
166
|
+
handler. The app supplies any route/copy — the shared package never hardcodes one.
|
|
167
|
+
|
|
168
|
+
```typescript
|
|
169
|
+
interface ChatEventCardAction {
|
|
170
|
+
/** Button label (already localized by the app). */
|
|
171
|
+
label: string
|
|
172
|
+
/** Link target. App-owned — e.g. the host's own pricing/auth route. */
|
|
173
|
+
href?: string
|
|
174
|
+
/** Click handler (alternative to, or alongside, `href`). */
|
|
175
|
+
onClick?: () => void
|
|
176
|
+
/**
|
|
177
|
+
* Render the action's label as inline monospace code — a command/identifier like
|
|
178
|
+
* `/report` or a skill name — so it stands out from prose while staying clickable.
|
|
179
|
+
*/
|
|
180
|
+
code?: boolean
|
|
181
|
+
}
|
|
182
|
+
```
|
|
183
|
+
|
|
184
|
+
#### `ChatEventCardCode`
|
|
185
|
+
|
|
186
|
+
A non-interactive inline monospace code span in a card body — a command or identifier
|
|
187
|
+
the prose refers to (`/report`, a skill name) that should read as code but isn't
|
|
188
|
+
clickable. For a _clickable_ command, use {@link ChatEventCardAction} with `code: true`.
|
|
189
|
+
|
|
190
|
+
```typescript
|
|
191
|
+
interface ChatEventCardCode {
|
|
192
|
+
/** The code text, rendered monospaced/tinted. */
|
|
193
|
+
code: string
|
|
194
|
+
}
|
|
195
|
+
```
|
|
196
|
+
|
|
197
|
+
#### `ChatMessageItemProps`
|
|
198
|
+
|
|
199
|
+
Properties for the chat message item component.
|
|
200
|
+
|
|
201
|
+
```typescript
|
|
202
|
+
interface ChatMessageItemProps {
|
|
203
|
+
message: ChatMessage
|
|
204
|
+
className?: string
|
|
205
|
+
}
|
|
206
|
+
```
|
|
207
|
+
|
|
208
|
+
#### `ChatPanelProps`
|
|
209
|
+
|
|
210
|
+
Props for the {@link ChatPanel} component — the IDE chat surface plus the
|
|
211
|
+
callbacks the host app uses to react to AI activity (file changes, boot, client
|
|
212
|
+
actions, etc.).
|
|
213
|
+
|
|
214
|
+
```typescript
|
|
215
|
+
interface ChatPanelProps {
|
|
216
|
+
projectId: string
|
|
217
|
+
endpoint?: string
|
|
218
|
+
/** If provided, auto-send this message once on mount (e.g., prompt from landing page). */
|
|
219
|
+
initialMessage?: string
|
|
220
|
+
/** Called after the initial message has been sent — used to clear router state. */
|
|
221
|
+
onInitialMessageSent?: () => void
|
|
222
|
+
/** Called to open a file as a preview tab. `opts.focus === false` opens it quietly (no pane switch) — e.g. a saved plan or a system-initiated open while the user is busy. */
|
|
223
|
+
onFileOpen?: (path: string, opts?: { focus?: boolean }) => void
|
|
224
|
+
/** Called when a filename in a tool call is double-clicked — should pin the tab. */
|
|
225
|
+
onFileDoubleClick?: (path: string) => void
|
|
226
|
+
/** Called when a file in the uncommitted list is clicked for diff view. */
|
|
227
|
+
onFileDiff?: (path: string, diff?: { original: string; modified: string }) => void
|
|
228
|
+
/** Called to undo/redo a file change — writes the given content to the file path. */
|
|
229
|
+
onFileRevert?: (path: string, content: string) => Promise<void>
|
|
230
|
+
/** Called when the AI creates or modifies a file — should refresh the editor if the file is open. */
|
|
231
|
+
onFileChange?: (path: string, content: string) => void
|
|
232
|
+
/** Called when a file is removed from disk (e.g. reverting an untracked file). */
|
|
233
|
+
onFileDeleted?: (path: string) => void
|
|
234
|
+
/** Called after a successful commit — should refresh file explorer git status. */
|
|
235
|
+
onCommit?: () => void
|
|
236
|
+
/** Called when an inline activity card is clicked — should open the Activity panel filtered to this activity. */
|
|
237
|
+
onActivityClick?: (activity: ActivityFromCard) => void
|
|
238
|
+
/**
|
|
239
|
+
* Called when a user avatar in the chat timeline is clicked — the host opens
|
|
240
|
+
* that user's profile (e.g. molecule.dev's profile modal). Receives the clicked
|
|
241
|
+
* user's {@link ChatUserIdentity}. Omit it (the default) to render the avatars
|
|
242
|
+
* non-interactive (static image/icon, exactly as before). Only real user
|
|
243
|
+
* avatars are clickable — the molecule glyph on auto-sent messages is not.
|
|
244
|
+
*/
|
|
245
|
+
onProfileClick?: (user: ChatUserIdentity) => void
|
|
246
|
+
/** Called when the server signals (via the `ready_to_build` stream event) that discovery is complete and the sandbox should boot. */
|
|
247
|
+
onReadyToBuild?: () => void
|
|
248
|
+
/**
|
|
249
|
+
* True while the plan has finished streaming but the sandbox is still booting
|
|
250
|
+
* (after `ready_to_build`, before the post-boot build kickoff). When set and no
|
|
251
|
+
* message is actively streaming, the chat shows a "waiting for the development
|
|
252
|
+
* environment" indicator so the conversation doesn't appear to silently stall.
|
|
253
|
+
*/
|
|
254
|
+
awaitingSandboxBoot?: boolean
|
|
255
|
+
/** Called when the agent requests a UI action via the `client_action` stream event (reload/navigate the preview, open a file). */
|
|
256
|
+
onClientAction?: (action: IdeClientAction) => void
|
|
257
|
+
/** Called on each stream `done` — host uses it to keep the boot view up until the parallel during-boot plan stream finishes. */
|
|
258
|
+
onTurnComplete?: () => void
|
|
259
|
+
/**
|
|
260
|
+
* Called whenever the chat's loading state changes — true when a turn (plan or build) is in
|
|
261
|
+
* progress, false when idle. The host uses this as the authoritative "the agent is actively
|
|
262
|
+
* building" signal to drive the preview's "Building your app…" overlay, so a half-built /
|
|
263
|
+
* blank preview during a long build always shows progress instead of a bare white screen.
|
|
264
|
+
*/
|
|
265
|
+
onLoadingChange?: (loading: boolean) => void
|
|
266
|
+
/**
|
|
267
|
+
* Navigates the live preview to a route path. Wired so a `[label](/route)` markdown link in
|
|
268
|
+
* an assistant message (e.g. the agent's "your app is ready" handoff) jumps the preview to
|
|
269
|
+
* that page on click. User-initiated, so the host should navigate unconditionally (it is not
|
|
270
|
+
* the rate-limited agent `navigate_preview` action).
|
|
271
|
+
*/
|
|
272
|
+
onNavigatePreview?: (path: string) => void
|
|
273
|
+
/**
|
|
274
|
+
* Called on mount with a handler the parent invokes to deliver a broadcast chat event
|
|
275
|
+
* from another project member (the push channel); called with null on unmount.
|
|
276
|
+
*/
|
|
277
|
+
onRegisterPushHandler?: (
|
|
278
|
+
handler: ((conversationId: string, event: ChatStreamEvent) => void) | null,
|
|
279
|
+
) => void
|
|
280
|
+
/** Changing this value submits the current input draft — used to send a prefilled prompt after the prompt→chat morph docks. */
|
|
281
|
+
autoSubmitSignal?: number
|
|
282
|
+
/** Seeds the input with this text on mount (prompt→chat morph), so the chat input shows the prompt before it is sent. */
|
|
283
|
+
initialInputValue?: string
|
|
284
|
+
/** Hide the conversation-selector header (e.g. during discovery, before any history is worth showing). */
|
|
285
|
+
hideConversationMenu?: boolean
|
|
286
|
+
/**
|
|
287
|
+
* Whether to render the built-in conversation header (the picker + searchable
|
|
288
|
+
* history dropdown, the share / bug-report / settings buttons, and the
|
|
289
|
+
* new-chat "+"). Defaults to `true` (the package owns that chrome). Pass
|
|
290
|
+
* `false` to operate **headless** — the host renders those controls itself
|
|
291
|
+
* (e.g. molecule.dev's Workspace top bar) and drives the chat through the
|
|
292
|
+
* controlled props below: {@link ChatPanelProps.conversationId} /
|
|
293
|
+
* {@link ChatPanelProps.chatKey} / {@link ChatPanelProps.onConversationId} for
|
|
294
|
+
* the conversation, and {@link ChatPanelProps.openShareSignal} /
|
|
295
|
+
* {@link ChatPanelProps.openReportSignal} to open the in-chat modals.
|
|
296
|
+
*/
|
|
297
|
+
renderConversationHeader?: boolean
|
|
298
|
+
/**
|
|
299
|
+
* Host-controlled active conversation id (headless mode). Drives the chat
|
|
300
|
+
* endpoint's `?conversationId=`. When `undefined` (the default) the panel owns
|
|
301
|
+
* the active conversation internally (localStorage-backed). `null` is a valid
|
|
302
|
+
* controlled value meaning "no conversation yet".
|
|
303
|
+
*/
|
|
304
|
+
conversationId?: string | null
|
|
305
|
+
/**
|
|
306
|
+
* Host-controlled remount key for the inner chat (headless mode). Changing it
|
|
307
|
+
* remounts the conversation timeline (a new chat or a switch); the backend
|
|
308
|
+
* assigning an id mid-stream must NOT change it (that would drop in-flight
|
|
309
|
+
* messages). Falls back to the internal key when omitted.
|
|
310
|
+
*/
|
|
311
|
+
chatKey?: string
|
|
312
|
+
/**
|
|
313
|
+
* Called whenever the active conversation id changes — the backend assigns one
|
|
314
|
+
* mid-stream and the host needs it to keep its own picker in sync WITHOUT
|
|
315
|
+
* remounting (do not change {@link ChatPanelProps.chatKey} in response).
|
|
316
|
+
*/
|
|
317
|
+
onConversationId?: (id: string | null) => void
|
|
318
|
+
/** Changing this opens the in-chat `/share` modal (host-driven, e.g. a top-bar share button). Overrides the built-in header's share button signal. */
|
|
319
|
+
openShareSignal?: number
|
|
320
|
+
/** Changing this opens the in-chat `/report` modal (host-driven). Overrides the built-in header's bug-report button signal. */
|
|
321
|
+
openReportSignal?: number
|
|
322
|
+
/** Changing this opens the in-chat `/settings` view (host-driven). Overrides the built-in header's settings button signal. */
|
|
323
|
+
openSettingsSignal?: number
|
|
324
|
+
/**
|
|
325
|
+
* When provided, the `/model` picker shows an "Add or manage your own
|
|
326
|
+
* models…" row at the bottom of the list; choosing it closes the picker and
|
|
327
|
+
* invokes this callback (the host opens its own custom-provider management
|
|
328
|
+
* surface). Omit to hide the row — the shared package stays host-agnostic.
|
|
329
|
+
*/
|
|
330
|
+
onManageCustomModels?: () => void
|
|
331
|
+
/** Spinner/busy indicator node to show for in-chat loading states (e.g. the "designing" indicator). Falls back to a built-in dots animation. */
|
|
332
|
+
spinner?: ReactNode
|
|
333
|
+
/** Path of the currently focused file in the editor (shown first in @ picker). */
|
|
334
|
+
activeFile?: string | null
|
|
335
|
+
/** Paths of all open editor tabs (shown after active file in @ picker). */
|
|
336
|
+
openTabs?: string[]
|
|
337
|
+
/** Incremented to trigger a git status refresh (e.g. after file create/rename/delete). */
|
|
338
|
+
gitStatusTick?: number
|
|
339
|
+
/** Message to auto-send (e.g. from "Fix with AI"). Sent when pendingMessageKey changes. */
|
|
340
|
+
pendingMessage?: string
|
|
341
|
+
/** Incremented to trigger sending pendingMessage. */
|
|
342
|
+
pendingMessageKey?: number
|
|
343
|
+
/** When true, the pending message is sent on the user's behalf (e.g. the post-boot build kickoff) and is NOT shown as a user bubble — phase markers convey what's happening instead. */
|
|
344
|
+
pendingMessageSuppressUser?: boolean
|
|
345
|
+
/**
|
|
346
|
+
* When true, the pending message was directly requested by the user (e.g. the
|
|
347
|
+
* editor's or broken-preview overlay's "Fix with AI" button) rather than
|
|
348
|
+
* dispatched autonomously (preview-health / preview-error auto-fix). A user
|
|
349
|
+
* Stop suppresses autonomous automatic sends until the user re-engages; a
|
|
350
|
+
* user-initiated pending message IS that re-engagement, so it always sends.
|
|
351
|
+
*/
|
|
352
|
+
pendingMessageUserInitiated?: boolean
|
|
353
|
+
/** File path the user just edited in the editor — triggers auto-deletion of queued autofix messages. */
|
|
354
|
+
userEditedFile?: string
|
|
355
|
+
/** Incremented to trigger the user-edit check (same path may be edited multiple times). */
|
|
356
|
+
userEditedFileKey?: number
|
|
357
|
+
/**
|
|
358
|
+
* Whether the current user is anonymous. The shared IDE no longer renders any
|
|
359
|
+
* built-in sign-up/guest card itself — guest reminders now arrive as a `custom`
|
|
360
|
+
* stream event the host registers via {@link registerCustomEventCard}, and upgrade
|
|
361
|
+
* call-to-actions come from {@link ChatPanelProps.buildUpgradeCta}. Retained so the
|
|
362
|
+
* host can still pass it; the host's own `buildUpgradeCta` closure decides whether
|
|
363
|
+
* an anonymous user should sign up vs. upgrade.
|
|
364
|
+
*/
|
|
365
|
+
isAnonymous?: boolean
|
|
366
|
+
/** When true, user has a paid plan and can use all models (drives locked-model display). */
|
|
367
|
+
isPro?: boolean
|
|
368
|
+
/**
|
|
369
|
+
* Retained for call-site compatibility. The periodic "sign up to keep your work"
|
|
370
|
+
* reminder is no longer generated client-side — the host's backend decides when to
|
|
371
|
+
* emit it as a `guest_reminder` `custom` stream event (so it can be suppressed during
|
|
372
|
+
* discovery server-side). This prop no longer drives any built-in behavior.
|
|
373
|
+
* @deprecated Guest reminders moved to the host-emitted `custom` event + registry.
|
|
374
|
+
*/
|
|
375
|
+
suppressGuestReminder?: boolean
|
|
376
|
+
/**
|
|
377
|
+
* Builds the call-to-action button(s) shown when the chat surfaces an upgrade /
|
|
378
|
+
* sign-in nudge — a locked model the user can't select, or a usage/resource limit
|
|
379
|
+
* the backend reported. The shared IDE owns NO pricing or auth routes, so the host
|
|
380
|
+
* supplies the button(s) here (e.g. its own `/pricing` or `/signup`). Return
|
|
381
|
+
* `null`/`undefined` (the default) to render the nudge text with no button.
|
|
382
|
+
* `requiresSignup`, when set, is the backend's flag that the user must sign up
|
|
383
|
+
* rather than upgrade an existing plan; when unset the host's own auth state decides.
|
|
384
|
+
*/
|
|
385
|
+
buildUpgradeCta?: (context: {
|
|
386
|
+
requiresSignup?: boolean
|
|
387
|
+
}) => ChatEventCardAction | ChatEventCardAction[] | null | undefined
|
|
388
|
+
/**
|
|
389
|
+
* Optional app-specific section appended to the `/help` output — e.g. a plan /
|
|
390
|
+
* upgrade blurb. The shared IDE has no pricing or plan copy, so the host supplies
|
|
391
|
+
* the (already-localized) lines plus any call-to-action. Return `null` (the default)
|
|
392
|
+
* to append nothing.
|
|
393
|
+
*/
|
|
394
|
+
buildHelpUpgradeSection?: () =>
|
|
395
|
+
{ lines: string[]; action?: ChatEventCardAction | ChatEventCardAction[] } | null | undefined
|
|
396
|
+
/**
|
|
397
|
+
* The signed-in user's profile avatar (SOC1) — an inline `data:image/*` URI or
|
|
398
|
+
* an `http(s)` URL — rendered beside their own messages in the chat timeline.
|
|
399
|
+
* The host passes whatever value its user metadata holds; the shared IDE gates
|
|
400
|
+
* it (`resolveUserAvatar`) so only a safe, renderable source reaches the DOM and
|
|
401
|
+
* falls back to a generic icon otherwise. Omit it (the default) to always show
|
|
402
|
+
* the icon.
|
|
403
|
+
*/
|
|
404
|
+
userAvatar?: string | null
|
|
405
|
+
/**
|
|
406
|
+
* Display name of the AI coding agent, interpolated into all shared chat copy
|
|
407
|
+
* that refers to it (the stalled-stream notice, sound-event descriptions, the
|
|
408
|
+
* `/help` body, tips, `/settings` and command descriptions, the `/scripts`
|
|
409
|
+
* empty state). The shared IDE owns NO product branding, so the host passes its
|
|
410
|
+
* own agent brand name. Defaults to the neutral `'the assistant'`
|
|
411
|
+
* (`DEFAULT_AGENT_NAME` from `@molecule/app-react`) so the package alone never
|
|
412
|
+
* names a specific product.
|
|
413
|
+
*/
|
|
414
|
+
agentName?: string
|
|
415
|
+
/**
|
|
416
|
+
* Display name of the host product / IDE, interpolated into shared chat copy
|
|
417
|
+
* that refers to the product (the `/help` intro, the report-confirmation and
|
|
418
|
+
* report-modal subheading, the command-menu version line). The host passes its
|
|
419
|
+
* own product brand name; defaults to the neutral `'the IDE'`
|
|
420
|
+
* (`DEFAULT_PRODUCT_NAME` from `@molecule/app-react`).
|
|
421
|
+
*/
|
|
422
|
+
productName?: string
|
|
423
|
+
/**
|
|
424
|
+
* The host's current app/build version (e.g. `'0.1.0'`), shown in the `/version`
|
|
425
|
+
* command's menu description and its output. The shared IDE has no build version
|
|
426
|
+
* of its own, so when omitted it falls back to the package default constant.
|
|
427
|
+
*/
|
|
428
|
+
version?: string
|
|
429
|
+
/**
|
|
430
|
+
* URL the command-menu "Report a problem" link points at (the host's own issue
|
|
431
|
+
* tracker / feedback page). The shared IDE owns no product URLs, so when this
|
|
432
|
+
* is omitted (the default) the link is not rendered. The in-chat `/report`
|
|
433
|
+
* modal — which POSTs to the project's own backend — is unaffected.
|
|
434
|
+
*/
|
|
435
|
+
feedbackUrl?: string
|
|
436
|
+
className?: string
|
|
437
|
+
}
|
|
438
|
+
```
|
|
439
|
+
|
|
440
|
+
#### `ChatUserIdentity`
|
|
441
|
+
|
|
442
|
+
Identity of the user whose avatar was clicked in the chat timeline, passed to
|
|
443
|
+
{@link ChatPanelProps.onProfileClick} so the host can open that user's profile.
|
|
444
|
+
|
|
445
|
+
Today the chat is solo — the only avatar shown is the signed-in user's own —
|
|
446
|
+
so the only known field is the avatar value. The interface is intentionally
|
|
447
|
+
forward-compatible: collaborator fields (id, name) can be added here when
|
|
448
|
+
multi-user chat lands, without changing the callback signature.
|
|
449
|
+
|
|
450
|
+
```typescript
|
|
451
|
+
interface ChatUserIdentity {
|
|
452
|
+
/** The clicked user's avatar value (data-URI / URL), if any. */
|
|
453
|
+
avatar?: string | null
|
|
454
|
+
}
|
|
455
|
+
```
|
|
456
|
+
|
|
457
|
+
#### `ClientInfo`
|
|
458
|
+
|
|
459
|
+
Client-side diagnostics attached to a report so triage can see the running
|
|
460
|
+
environment without asking the user. Every field is optional — only what
|
|
461
|
+
could be read in the current environment is present (see
|
|
462
|
+
{@link collectClientInfo}).
|
|
463
|
+
|
|
464
|
+
```typescript
|
|
465
|
+
interface ClientInfo {
|
|
466
|
+
/** The running build version. */
|
|
467
|
+
appVersion?: string
|
|
468
|
+
/** `navigator.userAgent` (browser + OS). */
|
|
469
|
+
userAgent?: string
|
|
470
|
+
/** `navigator.platform`. */
|
|
471
|
+
platform?: string
|
|
472
|
+
/** `navigator.language`. */
|
|
473
|
+
language?: string
|
|
474
|
+
/** Inner viewport size, `${innerWidth}×${innerHeight}`. */
|
|
475
|
+
viewport?: string
|
|
476
|
+
/** Physical screen size, `${screen.width}×${screen.height}`. */
|
|
477
|
+
screen?: string
|
|
478
|
+
/** Active theme — `'light'` or `'dark'`. */
|
|
479
|
+
theme?: string
|
|
480
|
+
/** The current page URL (`window.location.href`). */
|
|
481
|
+
url?: string
|
|
482
|
+
}
|
|
483
|
+
```
|
|
484
|
+
|
|
485
|
+
#### `Command`
|
|
486
|
+
|
|
487
|
+
A command available in the command palette.
|
|
488
|
+
|
|
489
|
+
```typescript
|
|
490
|
+
interface Command {
|
|
491
|
+
/** Unique identifier. */
|
|
492
|
+
id: string
|
|
493
|
+
/** Display label. */
|
|
494
|
+
label: string
|
|
495
|
+
/** Keyboard shortcut hint (e.g. "Cmd+P"). */
|
|
496
|
+
shortcut?: string
|
|
497
|
+
/** Handler invoked when the command is executed. */
|
|
498
|
+
execute: () => void
|
|
499
|
+
/** Category prefix (e.g. "View", "File"). */
|
|
500
|
+
category?: string
|
|
501
|
+
}
|
|
502
|
+
```
|
|
503
|
+
|
|
504
|
+
#### `CommandCategory`
|
|
505
|
+
|
|
506
|
+
A command category with its display label.
|
|
507
|
+
|
|
508
|
+
```typescript
|
|
509
|
+
interface CommandCategory {
|
|
510
|
+
/** Stable category key referenced by {@link CommandDef.category}. */
|
|
511
|
+
key: CommandCategoryKey
|
|
512
|
+
/** Human-readable category heading (English default; wrapped in `t()` at render). */
|
|
513
|
+
label: string
|
|
514
|
+
}
|
|
515
|
+
```
|
|
516
|
+
|
|
517
|
+
#### `CommandDef`
|
|
518
|
+
|
|
519
|
+
Metadata describing a single slash command.
|
|
520
|
+
|
|
521
|
+
```typescript
|
|
522
|
+
interface CommandDef {
|
|
523
|
+
/** Command id (the part after the slash, e.g. `'help'`). */
|
|
524
|
+
id: string
|
|
525
|
+
/** Display label including the leading slash (e.g. `'/help'`). */
|
|
526
|
+
label: string
|
|
527
|
+
/**
|
|
528
|
+
* Short description shown in the menu and in `/help` (English default). May
|
|
529
|
+
* contain the `{{agentName}}` interpolation token, filled in by the render
|
|
530
|
+
* sites (command menu, `/help`, `/settings` card) from the host's agent
|
|
531
|
+
* identity (neutral default: "the assistant").
|
|
532
|
+
*/
|
|
533
|
+
description: string
|
|
534
|
+
/** Category this command is grouped under. */
|
|
535
|
+
category: CommandCategoryKey
|
|
536
|
+
/**
|
|
537
|
+
* Argument syntax for commands that take options, shown in the `/settings`
|
|
538
|
+
* command reference (English default). `[…]` = optional, `<…>` = required.
|
|
539
|
+
* Omit for commands that take no arguments.
|
|
540
|
+
*/
|
|
541
|
+
usage?: string
|
|
542
|
+
}
|
|
543
|
+
```
|
|
544
|
+
|
|
545
|
+
#### `CommandGroup`
|
|
546
|
+
|
|
547
|
+
A category paired with the commands that belong to it.
|
|
548
|
+
|
|
549
|
+
```typescript
|
|
550
|
+
interface CommandGroup {
|
|
551
|
+
/** The category metadata (key + label). */
|
|
552
|
+
category: CommandCategory
|
|
553
|
+
/** Commands in this category, in registry order. */
|
|
554
|
+
commands: CommandDef[]
|
|
555
|
+
}
|
|
556
|
+
```
|
|
557
|
+
|
|
558
|
+
#### `CommandPaletteProps`
|
|
559
|
+
|
|
560
|
+
Properties for the command palette.
|
|
561
|
+
|
|
562
|
+
```typescript
|
|
563
|
+
interface CommandPaletteProps {
|
|
564
|
+
/** Available commands. */
|
|
565
|
+
commands: Command[]
|
|
566
|
+
/** Called when the palette is dismissed. */
|
|
567
|
+
onDismiss: () => void
|
|
568
|
+
}
|
|
569
|
+
```
|
|
570
|
+
|
|
571
|
+
#### `DeviceDimensions`
|
|
572
|
+
|
|
573
|
+
Per-frame iframe sizing. `width`/`height` are the PORTRAIT CSS sizes; a
|
|
574
|
+
fixed-frame (`rotatable`) device swaps them in landscape. `'100%'` width with
|
|
575
|
+
a `null` height means "fluid" — fill the available preview area (responsive /
|
|
576
|
+
desktop have no fixed frame to rotate).
|
|
577
|
+
|
|
578
|
+
```typescript
|
|
579
|
+
interface DeviceDimensions {
|
|
580
|
+
/** Portrait CSS width (e.g. `'768px'`, or `'100%'` for a fluid frame). */
|
|
581
|
+
readonly width: string
|
|
582
|
+
/** Portrait CSS height in px (e.g. `'1024px'`), or `null` to fill the area. */
|
|
583
|
+
readonly height: string | null
|
|
584
|
+
/** Whether the frame has a fixed size that can be rotated portrait ⇄ landscape. */
|
|
585
|
+
readonly rotatable: boolean
|
|
586
|
+
}
|
|
587
|
+
```
|
|
588
|
+
|
|
589
|
+
#### `DeviceFrameSelectorProps`
|
|
590
|
+
|
|
591
|
+
Properties for device frame selector.
|
|
592
|
+
|
|
593
|
+
```typescript
|
|
594
|
+
interface DeviceFrameSelectorProps {
|
|
595
|
+
current: DeviceFrame
|
|
596
|
+
onChange: (device: DeviceFrame) => void
|
|
597
|
+
className?: string
|
|
598
|
+
}
|
|
599
|
+
```
|
|
600
|
+
|
|
601
|
+
#### `EditorPanelProps`
|
|
602
|
+
|
|
603
|
+
Properties for the editor panel component.
|
|
604
|
+
|
|
605
|
+
```typescript
|
|
606
|
+
interface EditorPanelProps {
|
|
607
|
+
className?: string
|
|
608
|
+
/** Called whenever the active file changes (tab switch, file open, file close). */
|
|
609
|
+
onActiveFileChange?: (path: string | null) => void
|
|
610
|
+
/** Called once after the editor is fully mounted and ready to accept files. */
|
|
611
|
+
onEditorReady?: () => void
|
|
612
|
+
/** Called whenever the open tab list changes (file opened or closed). */
|
|
613
|
+
onTabsChange?: (paths: string[]) => void
|
|
614
|
+
/** Maps file path to git status for coloring tab filenames. */
|
|
615
|
+
fileStatuses?: Record<string, string>
|
|
616
|
+
/** Path of the file currently being formatted, for visual indicator. */
|
|
617
|
+
formattingFile?: string | null
|
|
618
|
+
/** Path of the file with an active save debounce countdown. */
|
|
619
|
+
countdownFile?: string | null
|
|
620
|
+
/** Incremented each keystroke to restart the countdown animation. */
|
|
621
|
+
countdownKey?: number
|
|
622
|
+
/** Estimated format duration in ms (rolling average, default 2000). */
|
|
623
|
+
formatEstimate?: number
|
|
624
|
+
/** Called when the user triggers "Fix with AI" from the editor's lightbulb or context menu. */
|
|
625
|
+
onFixWithAI?: (request: FixWithAIRequest) => void
|
|
626
|
+
/** Override double-click on a tab. Return `true` to skip the default pin behavior. */
|
|
627
|
+
onTabDoubleClick?: (path: string) => boolean
|
|
628
|
+
}
|
|
629
|
+
```
|
|
630
|
+
|
|
631
|
+
#### `FileExplorerProps`
|
|
632
|
+
|
|
633
|
+
Properties for file explorer.
|
|
634
|
+
|
|
635
|
+
```typescript
|
|
636
|
+
interface FileExplorerProps {
|
|
637
|
+
files: FileNode[]
|
|
638
|
+
onFileSelect: (path: string) => void
|
|
639
|
+
onFileDoubleClick?: (path: string) => void
|
|
640
|
+
onDirExpand?: (path: string) => void
|
|
641
|
+
/** Called when the user chooses "Rename" from the context menu. */
|
|
642
|
+
onRename?: (path: string) => void
|
|
643
|
+
/** Called when the user chooses "Delete" from the context menu. */
|
|
644
|
+
onDelete?: (path: string) => void
|
|
645
|
+
/** Called when the user deletes multiple selected files/folders via context menu or keyboard. */
|
|
646
|
+
onDeleteMultiple?: (paths: string[]) => void
|
|
647
|
+
/** Called when the user moves files via drag-and-drop or cut+paste. */
|
|
648
|
+
onMoveFiles?: (moves: Array<{ oldPath: string; newPath: string }>) => void
|
|
649
|
+
/** Called when the user chooses "New File" from the context menu. */
|
|
650
|
+
onNewFile?: (dirPath: string) => void
|
|
651
|
+
/** Called when the user chooses "New Folder" from the context menu. */
|
|
652
|
+
onNewFolder?: (dirPath: string) => void
|
|
653
|
+
/** Called when the user chooses "Collapse All" from the context menu. */
|
|
654
|
+
onCollapseAll?: () => void
|
|
655
|
+
className?: string
|
|
656
|
+
/** localStorage key for persisting expand/collapse state across reloads. */
|
|
657
|
+
persistKey?: string
|
|
658
|
+
/** Path of the currently active file — highlighted in the tree. */
|
|
659
|
+
activeFile?: string | null
|
|
660
|
+
/** Maps file path to git status — used to color directory names by highest-priority child status. */
|
|
661
|
+
fileStatuses?: Record<string, string>
|
|
662
|
+
}
|
|
663
|
+
```
|
|
664
|
+
|
|
665
|
+
#### `FileNode`
|
|
666
|
+
|
|
667
|
+
File Node interface.
|
|
668
|
+
|
|
669
|
+
```typescript
|
|
670
|
+
interface FileNode {
|
|
671
|
+
name: string
|
|
672
|
+
path: string
|
|
673
|
+
type: 'file' | 'directory'
|
|
674
|
+
children?: FileNode[]
|
|
675
|
+
isDimmed?: boolean
|
|
676
|
+
gitStatus?: 'modified' | 'added' | 'deleted' | 'untracked'
|
|
677
|
+
/** If this entry is a symlink, the target it points to. */
|
|
678
|
+
symlinkTarget?: string
|
|
679
|
+
}
|
|
680
|
+
```
|
|
681
|
+
|
|
682
|
+
#### `IconProps`
|
|
683
|
+
|
|
684
|
+
Props for {@link Icon}. Extends `SVGProps` so callers can forward any SVG/HTML
|
|
685
|
+
attribute (`data-mol-id`, `aria-*`, `role`, event handlers, `style`) to the
|
|
686
|
+
root `<svg>` without the component enumerating them.
|
|
687
|
+
|
|
688
|
+
```typescript
|
|
689
|
+
interface IconProps extends Omit<SVGProps<SVGSVGElement>, 'width' | 'height' | 'viewBox' | 'fill'> {
|
|
690
|
+
/** Name of the glyph to look up in the bonded icon set (e.g. `'sync'`). */
|
|
691
|
+
name: IconName
|
|
692
|
+
/** Width and height of the rendered SVG in pixels. Defaults to 16. */
|
|
693
|
+
size?: number
|
|
694
|
+
/** Class name forwarded to the root `<svg>`. */
|
|
695
|
+
className?: string
|
|
696
|
+
}
|
|
697
|
+
```
|
|
698
|
+
|
|
699
|
+
#### `IdeClientAction`
|
|
700
|
+
|
|
701
|
+
A non-mutating UI action the AI agent asks the IDE to perform — reload or
|
|
702
|
+
navigate the live preview, open a file in the editor, or drive the preview's
|
|
703
|
+
interaction bridge (`preview_ui`). Delivered via the `client_action`
|
|
704
|
+
chat-stream event (and, for `preview_ui`, also via the host's collab socket
|
|
705
|
+
so a mid-build tab reload can't orphan it).
|
|
706
|
+
|
|
707
|
+
```typescript
|
|
708
|
+
interface IdeClientAction {
|
|
709
|
+
action: 'reload_preview' | 'navigate_preview' | 'open_file' | 'preview_ui'
|
|
710
|
+
/** navigate_preview: a URL path (e.g. "/dashboard"). open_file: a file path. */
|
|
711
|
+
path?: string
|
|
712
|
+
/** preview_ui: correlates the command with its ui-result round-trip. */
|
|
713
|
+
requestId?: string
|
|
714
|
+
/** preview_ui: the interaction the preview bridge should perform. */
|
|
715
|
+
command?: 'snapshot' | 'click' | 'fill' | 'select' | 'waitFor'
|
|
716
|
+
/** preview_ui: the `data-mol-id` of the target element (preferred). */
|
|
717
|
+
molId?: string
|
|
718
|
+
/** preview_ui: CSS-selector fallback when no molId is available. */
|
|
719
|
+
selector?: string
|
|
720
|
+
/** preview_ui: visible-label match for apps whose elements carry no molId. */
|
|
721
|
+
text?: string
|
|
722
|
+
/** preview_ui: value to set for fill/select. */
|
|
723
|
+
value?: string
|
|
724
|
+
}
|
|
725
|
+
```
|
|
726
|
+
|
|
727
|
+
#### `KeyboardShortcut`
|
|
728
|
+
|
|
729
|
+
A keyboard shortcut definition.
|
|
730
|
+
|
|
731
|
+
```typescript
|
|
732
|
+
interface KeyboardShortcut {
|
|
733
|
+
/** Key combo string, e.g. `"mod+p"`, `"mod+shift+f"`. `mod` = Cmd (Mac) / Ctrl (others). */
|
|
734
|
+
keys: string
|
|
735
|
+
/** Handler invoked when the shortcut fires. */
|
|
736
|
+
handler: () => void
|
|
737
|
+
/** If true, fires even when an `<input>` / `<textarea>` is focused. */
|
|
738
|
+
allowInInput?: boolean
|
|
739
|
+
/** If true, fires even when the Monaco editor is focused. */
|
|
740
|
+
allowInEditor?: boolean
|
|
741
|
+
/** Human-readable label for display in the command palette. */
|
|
742
|
+
label?: string
|
|
743
|
+
}
|
|
744
|
+
```
|
|
745
|
+
|
|
746
|
+
#### `KeyboardShortcutsPanelProps`
|
|
747
|
+
|
|
748
|
+
Properties for the keyboard shortcuts reference panel.
|
|
749
|
+
|
|
750
|
+
```typescript
|
|
751
|
+
interface KeyboardShortcutsPanelProps {
|
|
752
|
+
/** List of shortcuts to display. */
|
|
753
|
+
shortcuts: ShortcutEntry[]
|
|
754
|
+
/** Called when the panel is dismissed. */
|
|
755
|
+
onDismiss: () => void
|
|
756
|
+
}
|
|
757
|
+
```
|
|
758
|
+
|
|
759
|
+
#### `PreviewPanelProps`
|
|
760
|
+
|
|
761
|
+
Props for the {@link PreviewPanel} — the live app preview (iframe + device frame + URL bar).
|
|
762
|
+
|
|
763
|
+
```typescript
|
|
764
|
+
interface PreviewPanelProps {
|
|
765
|
+
/** Custom loading indicator shown while the dev server is starting. */
|
|
766
|
+
loadingIndicator?: ReactNode
|
|
767
|
+
/**
|
|
768
|
+
* The current UI command the host wants performed in the preview iframe (AI-driven
|
|
769
|
+
* end-to-end verification). The panel posts it to the iframe's interaction bridge when it
|
|
770
|
+
* CHANGES (keyed on `id`, so each new command fires exactly once). The panel only relays it;
|
|
771
|
+
* the host owns what to send and what to do with the result.
|
|
772
|
+
*/
|
|
773
|
+
uiCommand?: PreviewUiCommand | null
|
|
774
|
+
/** Called when the iframe replies to a {@link PreviewUiCommand}, keyed by the command `id`. */
|
|
775
|
+
onUiResult?: (id: string, result: PreviewUiResult) => void
|
|
776
|
+
/** Custom loading indicator shown when the dev server restarts mid-session. Falls back to loadingIndicator if not provided. */
|
|
777
|
+
restartingIndicator?: ReactNode
|
|
778
|
+
/** Called when the preview iframe reports runtime JS errors. */
|
|
779
|
+
onPreviewError?: (
|
|
780
|
+
errors: Array<{ message: string; source?: string; line?: number; column?: number }>,
|
|
781
|
+
) => void
|
|
782
|
+
/** Incremented when AI edits files. Triggers an iframe reload only when the preview is broken. */
|
|
783
|
+
fileChangeTick?: number
|
|
784
|
+
/**
|
|
785
|
+
* Active-build hint (e.g. a basename like `GuestMenu.tsx`) the host sets while the
|
|
786
|
+
* AI is editing files. When non-null the overlay is forced on — covering the
|
|
787
|
+
* blank-white iframe reload a build triggers — and shows "Updating `<hint>`…" so
|
|
788
|
+
* the user sees what's being worked on. Null when no build edit is in flight.
|
|
789
|
+
*/
|
|
790
|
+
buildingHint?: string | null
|
|
791
|
+
/**
|
|
792
|
+
* Whether the AI agent is actively building right now (a chat turn is in progress).
|
|
793
|
+
* The host derives this from the chat's loading state. While true, the preview keeps a
|
|
794
|
+
* "Building your app…" status overlay up whenever the app has NOT confirmed it rendered
|
|
795
|
+
* content (no `molecule:ready`) — so a half-built / blank / white iframe during a long
|
|
796
|
+
* build always shows progress instead of a bare white screen. A confirmed render still
|
|
797
|
+
* reveals the live app (HMR updates stay visible), so this never hides a working preview.
|
|
798
|
+
*/
|
|
799
|
+
isBuilding?: boolean
|
|
800
|
+
/**
|
|
801
|
+
* Timestamp (ms since epoch) of when the preview's backing server/sandbox was last
|
|
802
|
+
* woken from sleep or restarted, or 0/undefined when it never was. While this is
|
|
803
|
+
* recent, the panel treats the preview like a fresh cold boot: the dev server behind
|
|
804
|
+
* it is restarting and recompiling, so a document that reloads to blank (or a
|
|
805
|
+
* transient error page that never runs the bridge) is EXPECTED for a while and must
|
|
806
|
+
* NOT trip the fast "preview is blank" accusation — the honest starting/loading
|
|
807
|
+
* status stays up, and only the generous never-rendered ceiling can accuse. A real
|
|
808
|
+
* render (`molecule:ready`) clears the patience immediately, so a healthy wake
|
|
809
|
+
* reveals as fast as ever.
|
|
810
|
+
*/
|
|
811
|
+
wakeAt?: number
|
|
812
|
+
/**
|
|
813
|
+
* Called when the preview gives up showing the running app — after exhausting reload
|
|
814
|
+
* recovery, at the absolute readiness ceiling, OR when the heartbeat watchdog detects a
|
|
815
|
+
* frozen (locked-thread) app. Receives a {@link PreviewStuckReport} (failure class +
|
|
816
|
+
* route) so the host can drive recovery UI AND hand the agent an actionable, targeted
|
|
817
|
+
* fix request. The argument is optional for backward compatibility with no-arg callers.
|
|
818
|
+
*/
|
|
819
|
+
onPreviewStuck?: (report?: PreviewStuckReport) => void
|
|
820
|
+
/**
|
|
821
|
+
* Called when the preview's render verdict changes ({@link PreviewRenderState}) — and
|
|
822
|
+
* with the current location so the host can report WHERE. The host forwards this to the
|
|
823
|
+
* server so Synthase's post-loop verification can confirm the app actually rendered (not
|
|
824
|
+
* just that it compiled + served) before calling a build done.
|
|
825
|
+
*/
|
|
826
|
+
onRenderState?: (state: PreviewRenderState, url?: string) => void
|
|
827
|
+
className?: string
|
|
828
|
+
}
|
|
829
|
+
```
|
|
830
|
+
|
|
831
|
+
#### `PreviewStuckReport`
|
|
832
|
+
|
|
833
|
+
Structured report passed to {@link PreviewPanelProps.onPreviewStuck} when the preview
|
|
834
|
+
gives up. Carries the failure class + the route it happened on so the host can compose
|
|
835
|
+
an actionable, agent-fixable message instead of a bare "preview is stuck".
|
|
836
|
+
|
|
837
|
+
```typescript
|
|
838
|
+
interface PreviewStuckReport {
|
|
839
|
+
/** The failure class — what left the preview unable to show the running app. */
|
|
840
|
+
reason: PreviewStuckReason
|
|
841
|
+
/** The preview's current location (route) when the failure was detected, if known. */
|
|
842
|
+
url?: string
|
|
843
|
+
}
|
|
844
|
+
```
|
|
845
|
+
|
|
846
|
+
#### `PreviewUiCommand`
|
|
847
|
+
|
|
848
|
+
A live-preview interaction the host asks the panel to perform inside the iframe, so an AI
|
|
849
|
+
agent can verify a feature end-to-end by DRIVING the app the user is watching (no headless
|
|
850
|
+
browser). The panel just relays it to the iframe's interaction bridge — generic, so it
|
|
851
|
+
carries no host/API specifics.
|
|
852
|
+
|
|
853
|
+
```typescript
|
|
854
|
+
interface PreviewUiCommand {
|
|
855
|
+
/** Correlates this command with its result; the host round-trips on it. */
|
|
856
|
+
id: string
|
|
857
|
+
/** `snapshot` the interactive UI, or act on an element. */
|
|
858
|
+
action: 'snapshot' | 'click' | 'fill' | 'select' | 'waitFor'
|
|
859
|
+
/** `data-mol-id` of the target element (preferred over selector). */
|
|
860
|
+
molId?: string
|
|
861
|
+
/** CSS-selector fallback when no molId is available. */
|
|
862
|
+
selector?: string
|
|
863
|
+
/** Visible-label match — targets apps whose elements carry no `data-mol-id`. */
|
|
864
|
+
text?: string
|
|
865
|
+
/** Value to set for `fill` / `select`. */
|
|
866
|
+
value?: string
|
|
867
|
+
/**
|
|
868
|
+
* `snapshot` only — the moment the host pointed the preview at a new URL (`Date.now()`).
|
|
869
|
+
* Only a document that loaded at or after it may answer, so a navigation snapshot can never
|
|
870
|
+
* come from the OUTGOING page still sitting in the iframe. Set it ONLY when a new document
|
|
871
|
+
* is genuinely loading (the URL actually changed) — otherwise nothing can satisfy it and the
|
|
872
|
+
* command goes unanswered. Omit for a plain read.
|
|
873
|
+
*/
|
|
874
|
+
minLoadedAt?: number
|
|
875
|
+
}
|
|
876
|
+
```
|
|
877
|
+
|
|
878
|
+
#### `PreviewUiResult`
|
|
879
|
+
|
|
880
|
+
The preview interaction bridge's reply to a {@link PreviewUiCommand}.
|
|
881
|
+
|
|
882
|
+
```typescript
|
|
883
|
+
interface PreviewUiResult {
|
|
884
|
+
ok: boolean
|
|
885
|
+
/** Interactive-element list + url/title from the preview (present on a snapshot / success). */
|
|
886
|
+
snapshot?: unknown
|
|
887
|
+
found?: boolean
|
|
888
|
+
error?: string
|
|
889
|
+
/**
|
|
890
|
+
* Failed network requests from the last ~10s (method, url, status, bounded response body),
|
|
891
|
+
* captured in-page — so a click that 4xx'd explains itself in the same result.
|
|
892
|
+
*/
|
|
893
|
+
recentNetworkErrors?: string[]
|
|
894
|
+
/**
|
|
895
|
+
* Present when the bridge gave up on a settle budget instead of observing the page settle —
|
|
896
|
+
* it names what was still pending (document parsing, an empty root, an unreached route,
|
|
897
|
+
* in-flight requests). The snapshot may be incomplete, so a race stays distinguishable from
|
|
898
|
+
* a genuinely broken page.
|
|
899
|
+
*/
|
|
900
|
+
stillSettling?: string
|
|
901
|
+
}
|
|
902
|
+
```
|
|
903
|
+
|
|
904
|
+
#### `QuickOpenProps`
|
|
905
|
+
|
|
906
|
+
Properties for the quick-open file finder.
|
|
907
|
+
|
|
908
|
+
```typescript
|
|
909
|
+
interface QuickOpenProps {
|
|
910
|
+
/** Project ID used for API calls. */
|
|
911
|
+
projectId: string
|
|
912
|
+
/** Called when the user selects a file. */
|
|
913
|
+
onFileOpen: (path: string) => void
|
|
914
|
+
/** Called when the picker is dismissed. */
|
|
915
|
+
onDismiss: () => void
|
|
916
|
+
}
|
|
917
|
+
```
|
|
918
|
+
|
|
919
|
+
#### `QuickPickerItem`
|
|
920
|
+
|
|
921
|
+
An item in the quick picker list.
|
|
922
|
+
|
|
923
|
+
```typescript
|
|
924
|
+
interface QuickPickerItem {
|
|
925
|
+
/** Unique identifier. */
|
|
926
|
+
id: string
|
|
927
|
+
/** Primary label. */
|
|
928
|
+
label: string
|
|
929
|
+
/** Secondary text shown beside the label. */
|
|
930
|
+
detail?: string
|
|
931
|
+
/** Optional icon element. */
|
|
932
|
+
icon?: ReactNode
|
|
933
|
+
}
|
|
934
|
+
```
|
|
935
|
+
|
|
936
|
+
#### `QuickPickerProps`
|
|
937
|
+
|
|
938
|
+
Properties for the reusable quick picker overlay.
|
|
939
|
+
|
|
940
|
+
```typescript
|
|
941
|
+
interface QuickPickerProps {
|
|
942
|
+
/** Items to display and filter. */
|
|
943
|
+
items: QuickPickerItem[]
|
|
944
|
+
/** Placeholder text for the search input. */
|
|
945
|
+
placeholder?: string
|
|
946
|
+
/** Called when the user selects an item. */
|
|
947
|
+
onSelect: (item: QuickPickerItem) => void
|
|
948
|
+
/** Called when the user dismisses the picker (Escape or backdrop click). */
|
|
949
|
+
onDismiss: () => void
|
|
950
|
+
/** Show a loading indicator. */
|
|
951
|
+
loading?: boolean
|
|
952
|
+
/** Pre-fill the search input. */
|
|
953
|
+
initialQuery?: string
|
|
954
|
+
className?: string
|
|
955
|
+
}
|
|
956
|
+
```
|
|
957
|
+
|
|
958
|
+
#### `ReportFormState`
|
|
959
|
+
|
|
960
|
+
The report modal's form state.
|
|
961
|
+
|
|
962
|
+
```typescript
|
|
963
|
+
interface ReportFormState {
|
|
964
|
+
/** Short summary / issue title. */
|
|
965
|
+
title: string
|
|
966
|
+
/** Detailed description of the problem or request. */
|
|
967
|
+
description: string
|
|
968
|
+
/** Optional reproduction steps (free text). */
|
|
969
|
+
steps: string
|
|
970
|
+
/** Whether to attach the recent conversation to the report. */
|
|
971
|
+
includeChat: boolean
|
|
972
|
+
}
|
|
973
|
+
```
|
|
974
|
+
|
|
975
|
+
#### `ReportPayload`
|
|
976
|
+
|
|
977
|
+
The `POST /projects/:id/report` request body.
|
|
978
|
+
|
|
979
|
+
```typescript
|
|
980
|
+
interface ReportPayload {
|
|
981
|
+
/** Short summary / issue title. */
|
|
982
|
+
title: string
|
|
983
|
+
/** Detailed description. */
|
|
984
|
+
description: string
|
|
985
|
+
/** Reproduction steps — omitted entirely when blank. */
|
|
986
|
+
steps?: string
|
|
987
|
+
/** Whether the backend should attach the recent conversation. */
|
|
988
|
+
includeChat: boolean
|
|
989
|
+
/** Client diagnostics — omitted entirely when none could be collected. */
|
|
990
|
+
clientInfo?: ClientInfo
|
|
991
|
+
}
|
|
992
|
+
```
|
|
993
|
+
|
|
994
|
+
#### `ReportResult`
|
|
995
|
+
|
|
996
|
+
The `POST /projects/:id/report` response.
|
|
997
|
+
|
|
998
|
+
```typescript
|
|
999
|
+
interface ReportResult {
|
|
1000
|
+
/** Whether the report was recorded. */
|
|
1001
|
+
ok: boolean
|
|
1002
|
+
/** Link to the created issue, when one was filed. */
|
|
1003
|
+
url?: string
|
|
1004
|
+
/** The persisted DB row id. */
|
|
1005
|
+
id?: string
|
|
1006
|
+
}
|
|
1007
|
+
```
|
|
1008
|
+
|
|
1009
|
+
#### `ResizeHandleProps`
|
|
1010
|
+
|
|
1011
|
+
Properties for resize handle.
|
|
1012
|
+
|
|
1013
|
+
```typescript
|
|
1014
|
+
interface ResizeHandleProps {
|
|
1015
|
+
onResize: (delta: number) => void
|
|
1016
|
+
direction?: 'horizontal' | 'vertical'
|
|
1017
|
+
className?: string
|
|
1018
|
+
}
|
|
1019
|
+
```
|
|
1020
|
+
|
|
1021
|
+
#### `SearchPanelProps`
|
|
1022
|
+
|
|
1023
|
+
Properties for the search-in-files panel.
|
|
1024
|
+
|
|
1025
|
+
```typescript
|
|
1026
|
+
interface SearchPanelProps {
|
|
1027
|
+
/** Project ID used for API calls. */
|
|
1028
|
+
projectId: string
|
|
1029
|
+
/** Called when the user clicks a search result. */
|
|
1030
|
+
onResultClick?: (path: string, line: number) => void
|
|
1031
|
+
className?: string
|
|
1032
|
+
/**
|
|
1033
|
+
* The project's excluded directory names (VS Code `search.exclude`
|
|
1034
|
+
* semantics). Displayed and editable in the panel; the backend applies the
|
|
1035
|
+
* SAME set server-side to every search surface (panel + AI tools), so this
|
|
1036
|
+
* prop is display/edit state — searches don't send it per query. When
|
|
1037
|
+
* omitted, the panel shows {@link DEFAULT_SEARCH_EXCLUDED_DIRS}.
|
|
1038
|
+
*/
|
|
1039
|
+
excludedDirs?: string[]
|
|
1040
|
+
/** Persist an edited excluded-dir set (the host owns storage). */
|
|
1041
|
+
onExcludedDirsChange?: (dirs: string[]) => void
|
|
1042
|
+
}
|
|
1043
|
+
```
|
|
1044
|
+
|
|
1045
|
+
#### `SearchResponse`
|
|
1046
|
+
|
|
1047
|
+
Response from the search API endpoint.
|
|
1048
|
+
|
|
1049
|
+
```typescript
|
|
1050
|
+
interface SearchResponse {
|
|
1051
|
+
/** The search pattern used. */
|
|
1052
|
+
pattern: string
|
|
1053
|
+
/** Grouped results by file. */
|
|
1054
|
+
results: SearchResult[]
|
|
1055
|
+
/** Total number of matches across all files. */
|
|
1056
|
+
totalCount: number
|
|
1057
|
+
/** Whether results were truncated. */
|
|
1058
|
+
truncated: boolean
|
|
1059
|
+
}
|
|
1060
|
+
```
|
|
1061
|
+
|
|
1062
|
+
#### `SearchResult`
|
|
1063
|
+
|
|
1064
|
+
A single file's search results.
|
|
1065
|
+
|
|
1066
|
+
```typescript
|
|
1067
|
+
interface SearchResult {
|
|
1068
|
+
/** Relative file path. */
|
|
1069
|
+
file: string
|
|
1070
|
+
/** Matching lines within the file. */
|
|
1071
|
+
matches: Array<{ line: number; content: string }>
|
|
1072
|
+
}
|
|
1073
|
+
```
|
|
1074
|
+
|
|
1075
|
+
#### `SettingMeta`
|
|
1076
|
+
|
|
1077
|
+
Canonical, value-free metadata for a single user-controllable setting.
|
|
1078
|
+
|
|
1079
|
+
```typescript
|
|
1080
|
+
interface SettingMeta {
|
|
1081
|
+
/** Stable id (also the i18n key suffix, e.g. `'effort'`). */
|
|
1082
|
+
id: SettingKey
|
|
1083
|
+
/** Human-readable label (English default; wrapped in `t()` at render). */
|
|
1084
|
+
label: string
|
|
1085
|
+
/**
|
|
1086
|
+
* One-line explanation of what the setting does (English default). May
|
|
1087
|
+
* contain the `{{agentName}}` interpolation token, filled in at render from
|
|
1088
|
+
* the host's agent identity (neutral default: "the assistant").
|
|
1089
|
+
*/
|
|
1090
|
+
description: string
|
|
1091
|
+
/**
|
|
1092
|
+
* The slash command that edits this setting client-side. Drives the inline
|
|
1093
|
+
* "Edit" affordance and cross-links the setting to its command. Omitted only
|
|
1094
|
+
* for read-only settings.
|
|
1095
|
+
*/
|
|
1096
|
+
editCommand?: CommandId
|
|
1097
|
+
/**
|
|
1098
|
+
* The exact slash-command input to prefill when editing, for settings whose
|
|
1099
|
+
* bare {@link SettingMeta.editCommand} is not specific enough — e.g. the
|
|
1100
|
+
* per-mode model rows both run the `model` command but must scope it to a
|
|
1101
|
+
* mode (`/model --plan`, `/model --execute`). Omit when running the bare
|
|
1102
|
+
* command suffices.
|
|
1103
|
+
*/
|
|
1104
|
+
editInput?: string
|
|
1105
|
+
}
|
|
1106
|
+
```
|
|
1107
|
+
|
|
1108
|
+
#### `ShareLinkResult`
|
|
1109
|
+
|
|
1110
|
+
The `POST /projects/:projectId/shares` response — the created public link.
|
|
1111
|
+
Mirrors the relevant fields of the `@molecule/api-resource-share` `ShareLink`.
|
|
1112
|
+
|
|
1113
|
+
```typescript
|
|
1114
|
+
interface ShareLinkResult {
|
|
1115
|
+
/** The link's unique id (used by the revoke route). */
|
|
1116
|
+
id?: string
|
|
1117
|
+
/** Opaque slug embedded in the public URL. */
|
|
1118
|
+
slug: string
|
|
1119
|
+
/** The role this link grants. */
|
|
1120
|
+
role: ShareRole
|
|
1121
|
+
/**
|
|
1122
|
+
* A fully-qualified share URL, when the backend supplies one. Preferred over
|
|
1123
|
+
* client-side construction so the canonical origin (e.g. a custom domain)
|
|
1124
|
+
* wins over the current page origin.
|
|
1125
|
+
*/
|
|
1126
|
+
url?: string
|
|
1127
|
+
}
|
|
1128
|
+
```
|
|
1129
|
+
|
|
1130
|
+
#### `SharePayload`
|
|
1131
|
+
|
|
1132
|
+
The `POST /projects/:projectId/shares` request body.
|
|
1133
|
+
|
|
1134
|
+
```typescript
|
|
1135
|
+
interface SharePayload {
|
|
1136
|
+
/** Role granted to anyone who opens the link. */
|
|
1137
|
+
role: ShareRole
|
|
1138
|
+
}
|
|
1139
|
+
```
|
|
1140
|
+
|
|
1141
|
+
#### `ShortcutEntry`
|
|
1142
|
+
|
|
1143
|
+
A shortcut entry for display in the keyboard shortcuts panel.
|
|
1144
|
+
|
|
1145
|
+
```typescript
|
|
1146
|
+
interface ShortcutEntry {
|
|
1147
|
+
/** Human-readable label describing the action. */
|
|
1148
|
+
label: string
|
|
1149
|
+
/** Display string for the key combo (e.g. "⌘P", "⌘⇧F"). */
|
|
1150
|
+
keys: string
|
|
1151
|
+
/** Optional grouping category. */
|
|
1152
|
+
category?: string
|
|
1153
|
+
/** Handler invoked when the row is clicked. */
|
|
1154
|
+
execute?: () => void
|
|
1155
|
+
}
|
|
1156
|
+
```
|
|
1157
|
+
|
|
1158
|
+
#### `SidebarTabsProps`
|
|
1159
|
+
|
|
1160
|
+
Properties for the sidebar tab switcher.
|
|
1161
|
+
|
|
1162
|
+
```typescript
|
|
1163
|
+
interface SidebarTabsProps {
|
|
1164
|
+
/** Currently active sidebar tab. */
|
|
1165
|
+
activeTab: 'files' | 'search'
|
|
1166
|
+
/** Called when the user switches tabs. */
|
|
1167
|
+
onTabChange: (tab: 'files' | 'search') => void
|
|
1168
|
+
/** Tab content rendered below the tab buttons. */
|
|
1169
|
+
children: ReactNode
|
|
1170
|
+
className?: string
|
|
1171
|
+
}
|
|
1172
|
+
```
|
|
1173
|
+
|
|
1174
|
+
#### `TabBarProps`
|
|
1175
|
+
|
|
1176
|
+
Properties for tab bar.
|
|
1177
|
+
|
|
1178
|
+
```typescript
|
|
1179
|
+
interface TabBarProps {
|
|
1180
|
+
tabs: EditorTab[]
|
|
1181
|
+
activeFile: string | null
|
|
1182
|
+
onSelect: (path: string) => void
|
|
1183
|
+
onClose: (path: string) => void
|
|
1184
|
+
onDoubleClick?: (path: string) => void
|
|
1185
|
+
/** Maps file path to git status for coloring tab filenames. */
|
|
1186
|
+
fileStatuses?: Record<string, string>
|
|
1187
|
+
className?: string
|
|
1188
|
+
}
|
|
1189
|
+
```
|
|
1190
|
+
|
|
1191
|
+
#### `ToolCallCardProps`
|
|
1192
|
+
|
|
1193
|
+
Properties for tool call card.
|
|
1194
|
+
|
|
1195
|
+
```typescript
|
|
1196
|
+
interface ToolCallCardProps {
|
|
1197
|
+
id: string
|
|
1198
|
+
name: string
|
|
1199
|
+
input?: unknown
|
|
1200
|
+
output?: unknown
|
|
1201
|
+
status: 'pending' | 'running' | 'done' | 'error'
|
|
1202
|
+
/** Snapshot of original/modified file content captured at tool-call time. */
|
|
1203
|
+
fileDiff?: { original: string; modified: string }
|
|
1204
|
+
/** Externally controlled undo state — when true, the card displays as undone. */
|
|
1205
|
+
isUndone?: boolean
|
|
1206
|
+
/** Called when the undo/redo button is toggled on this tool call. */
|
|
1207
|
+
onUndoToggle?: (id: string, undone: boolean) => void
|
|
1208
|
+
/** Called when a filename in the card is clicked — should open the file as a preview tab. */
|
|
1209
|
+
onFileOpen?: (path: string) => void
|
|
1210
|
+
/** Called when a filename in the card is double-clicked — should pin the tab. */
|
|
1211
|
+
onFileDoubleClick?: (path: string) => void
|
|
1212
|
+
/** Called when a file-changing card is clicked — should open the file diff in the editor. */
|
|
1213
|
+
onFileDiff?: (path: string, diff?: { original: string; modified: string }) => void
|
|
1214
|
+
/** Called to undo/redo a file change — writes the given content to the file path. */
|
|
1215
|
+
onFileRevert?: (path: string, content: string) => Promise<void>
|
|
1216
|
+
/** Called when the user responds to an `ask_user` tool call (clicks an option or submits free text). */
|
|
1217
|
+
onAskUserResponse?: (response: string) => void
|
|
1218
|
+
className?: string
|
|
1219
|
+
}
|
|
1220
|
+
```
|
|
1221
|
+
|
|
1222
|
+
#### `UserAvatarProps`
|
|
1223
|
+
|
|
1224
|
+
Props for {@link UserAvatar}.
|
|
1225
|
+
|
|
1226
|
+
```typescript
|
|
1227
|
+
interface UserAvatarProps {
|
|
1228
|
+
/**
|
|
1229
|
+
* The signed-in user's avatar — an inline `data:image/*` URI or an `http(s)`
|
|
1230
|
+
* URL from their profile metadata. Unsafe / unset / oversized values are
|
|
1231
|
+
* ignored (see {@link resolveUserAvatar}) and the generic icon is shown.
|
|
1232
|
+
*/
|
|
1233
|
+
userAvatar?: string | null
|
|
1234
|
+
/** Diameter of the avatar in pixels. Defaults to 24. */
|
|
1235
|
+
size?: number
|
|
1236
|
+
/**
|
|
1237
|
+
* Optional click handler. When supplied, the avatar becomes an interactive
|
|
1238
|
+
* button (pointer cursor, hover/focus ring, keyboard- and screen-reader
|
|
1239
|
+
* accessible) that opens the user's profile — the host decides what to show.
|
|
1240
|
+
* When omitted (the default) the avatar renders exactly as before: a static,
|
|
1241
|
+
* non-interactive image/icon, so existing call sites are unaffected.
|
|
1242
|
+
*/
|
|
1243
|
+
onClick?: () => void
|
|
1244
|
+
}
|
|
1245
|
+
```
|
|
1246
|
+
|
|
1247
|
+
#### `WorkspaceLayoutProps`
|
|
1248
|
+
|
|
1249
|
+
Properties for workspace layout.
|
|
1250
|
+
|
|
1251
|
+
```typescript
|
|
1252
|
+
interface WorkspaceLayoutProps {
|
|
1253
|
+
children: ReactNode
|
|
1254
|
+
className?: string
|
|
1255
|
+
}
|
|
1256
|
+
```
|
|
1257
|
+
|
|
1258
|
+
### Types
|
|
1259
|
+
|
|
1260
|
+
#### `ActivityStatus`
|
|
1261
|
+
|
|
1262
|
+
Lifecycle status of a captured activity.
|
|
1263
|
+
|
|
1264
|
+
```typescript
|
|
1265
|
+
type ActivityStatus = 'captured' | 'sent' | 'delivered' | 'failed'
|
|
1266
|
+
```
|
|
1267
|
+
|
|
1268
|
+
#### `ActivityType`
|
|
1269
|
+
|
|
1270
|
+
Channel categories a captured activity can belong to.
|
|
1271
|
+
|
|
1272
|
+
```typescript
|
|
1273
|
+
type ActivityType = 'email' | 'sms' | 'push' | 'webhook' | 'channel'
|
|
1274
|
+
```
|
|
1275
|
+
|
|
1276
|
+
#### `AutoCommitAction`
|
|
1277
|
+
|
|
1278
|
+
Actions the countdown reducer accepts.
|
|
1279
|
+
|
|
1280
|
+
- `set` — apply a `/autocommit <seconds>` command (`seconds <= 0` disables);
|
|
1281
|
+
arms AND starts a fresh countdown (an explicit, just-now user choice).
|
|
1282
|
+
- `hydrate` — restore a cadence persisted on the project (e.g. on reload),
|
|
1283
|
+
enabled but PAUSED (`seconds <= 0` disables). Unlike `set`, it does NOT
|
|
1284
|
+
start counting down — the countdown only re-arms on the next file change —
|
|
1285
|
+
so reopening a project never auto-commits a tree the user hasn't touched.
|
|
1286
|
+
- `reset` — a file changed; restart the full countdown (no-op when disabled).
|
|
1287
|
+
- `tick` — one second elapsed; decrement toward zero (no-op when paused).
|
|
1288
|
+
- `fired` — a commit was just dispatched; pause until the next file change.
|
|
1289
|
+
|
|
1290
|
+
```typescript
|
|
1291
|
+
type AutoCommitAction =
|
|
1292
|
+
| { type: 'set'; seconds: number }
|
|
1293
|
+
| { type: 'hydrate'; seconds: number }
|
|
1294
|
+
| { type: 'reset' }
|
|
1295
|
+
| { type: 'tick' }
|
|
1296
|
+
| { type: 'fired' }
|
|
1297
|
+
```
|
|
1298
|
+
|
|
1299
|
+
#### `ChatEventCardFactory`
|
|
1300
|
+
|
|
1301
|
+
Turns a custom event's `data` payload into a chat card, or returns null to render
|
|
1302
|
+
nothing for that event.
|
|
1303
|
+
|
|
1304
|
+
```typescript
|
|
1305
|
+
type ChatEventCardFactory = (data: Record<string, unknown> | undefined) => ChatEventCard | null
|
|
1306
|
+
```
|
|
1307
|
+
|
|
1308
|
+
#### `ChatEventCardSegment`
|
|
1309
|
+
|
|
1310
|
+
One inline segment of a card's composable body: literal text, an inline monospace
|
|
1311
|
+
{@link ChatEventCardCode} span, or a labelled link/action ({@link ChatEventCardAction}).
|
|
1312
|
+
See {@link ChatEventCard.content}.
|
|
1313
|
+
|
|
1314
|
+
```typescript
|
|
1315
|
+
type ChatEventCardSegment = string | ChatEventCardCode | ChatEventCardAction
|
|
1316
|
+
```
|
|
1317
|
+
|
|
1318
|
+
#### `CommandCategoryKey`
|
|
1319
|
+
|
|
1320
|
+
Category keys used to group commands in the menu and in `/help`.
|
|
1321
|
+
|
|
1322
|
+
```typescript
|
|
1323
|
+
type CommandCategoryKey = 'context' | 'code' | 'collaborate' | 'model' | 'settings' | 'support'
|
|
1324
|
+
```
|
|
1325
|
+
|
|
1326
|
+
#### `CommandId`
|
|
1327
|
+
|
|
1328
|
+
Union of all command ids (loosely `string`, since {@link CommandDef.id} is a string).
|
|
1329
|
+
|
|
1330
|
+
```typescript
|
|
1331
|
+
type CommandId = CommandDef['id']
|
|
1332
|
+
```
|
|
1333
|
+
|
|
1334
|
+
#### `DeviceOrientation`
|
|
1335
|
+
|
|
1336
|
+
Preview-only iframe orientation. Portrait is the natural orientation of a
|
|
1337
|
+
fixed-frame device; landscape swaps its width/height. This is a visual
|
|
1338
|
+
preview concern that lives in {@link PreviewPanel}'s local state — it is NOT
|
|
1339
|
+
part of the live-preview core state.
|
|
1340
|
+
|
|
1341
|
+
```typescript
|
|
1342
|
+
type DeviceOrientation = 'portrait' | 'landscape'
|
|
1343
|
+
```
|
|
1344
|
+
|
|
1345
|
+
#### `PreviewRenderState`
|
|
1346
|
+
|
|
1347
|
+
The preview's live render verdict, derived from the iframe bridges — the one preview
|
|
1348
|
+
fact the server can't observe itself (it has no browser). The host forwards it to the
|
|
1349
|
+
server so the post-loop verification won't pass a build while the app isn't actually
|
|
1350
|
+
rendering ("compiles + serves" ≠ "renders").
|
|
1351
|
+
|
|
1352
|
+
- `rendered` — the app drew content (`molecule:ready`).
|
|
1353
|
+
- `blank` — loaded but showed nothing (gave up / `#root` empty after settling).
|
|
1354
|
+
- `frozen` — rendered then locked up (heartbeats stopped).
|
|
1355
|
+
- `loading` — still loading / not yet determined.
|
|
1356
|
+
|
|
1357
|
+
```typescript
|
|
1358
|
+
type PreviewRenderState = 'rendered' | 'blank' | 'frozen' | 'loading'
|
|
1359
|
+
```
|
|
1360
|
+
|
|
1361
|
+
#### `PreviewStuckReason`
|
|
1362
|
+
|
|
1363
|
+
Why the preview could not show the running app — the failure CLASS the host hands
|
|
1364
|
+
to its AI agent so a fix can be targeted (and so the agent isn't told "it's broken"
|
|
1365
|
+
with no hint of how). Distinct from a JS error (`onPreviewError`): these are states
|
|
1366
|
+
the iframe itself can't report once it's in them.
|
|
1367
|
+
|
|
1368
|
+
```typescript
|
|
1369
|
+
type PreviewStuckReason =
|
|
1370
|
+
// Heartbeats stopped after a render — the app's main thread is locked (an infinite
|
|
1371
|
+
// loop / runaway render). The iframe can post nothing else once frozen, so only the
|
|
1372
|
+
// host's heartbeat-silence watchdog can detect it.
|
|
1373
|
+
| 'frozen'
|
|
1374
|
+
// Repeated reload/remount cycles never produced a confirmed render — the document
|
|
1375
|
+
// loads but the app never mounts (e.g. a route that throws on every attempt).
|
|
1376
|
+
| 'load-failed'
|
|
1377
|
+
// The absolute readiness ceiling elapsed with no confirmed render and no active
|
|
1378
|
+
// build — a catch-all backstop so the preview can never spin forever.
|
|
1379
|
+
| 'load-timeout'
|
|
1380
|
+
```
|
|
1381
|
+
|
|
1382
|
+
#### `SettingKey`
|
|
1383
|
+
|
|
1384
|
+
Stable ids for each user-controllable setting (also the i18n key suffix).
|
|
1385
|
+
|
|
1386
|
+
```typescript
|
|
1387
|
+
type SettingKey =
|
|
1388
|
+
| 'model'
|
|
1389
|
+
| 'planModel'
|
|
1390
|
+
| 'executeModel'
|
|
1391
|
+
| 'commitModel'
|
|
1392
|
+
| 'compactModel'
|
|
1393
|
+
| 'mode'
|
|
1394
|
+
| 'effort'
|
|
1395
|
+
| 'maxLoops'
|
|
1396
|
+
| 'autoFix'
|
|
1397
|
+
| 'autoCommit'
|
|
1398
|
+
| 'hooks'
|
|
1399
|
+
| 'autoApproveCommands'
|
|
1400
|
+
| 'sounds'
|
|
1401
|
+
```
|
|
1402
|
+
|
|
1403
|
+
#### `ShareCommand`
|
|
1404
|
+
|
|
1405
|
+
The parsed result of a `/share` command:
|
|
1406
|
+
|
|
1407
|
+
- `create` — POST a link at a valid role (`/share`, defaulting to `viewer`,
|
|
1408
|
+
or `/share <role>` with a recognized role).
|
|
1409
|
+
- `invalid` — an unrecognized role argument was given (the caller shows usage).
|
|
1410
|
+
|
|
1411
|
+
```typescript
|
|
1412
|
+
type ShareCommand = { kind: 'create'; role: ShareRole } | { kind: 'invalid'; arg: string }
|
|
1413
|
+
```
|
|
1414
|
+
|
|
1415
|
+
#### `ShareRole`
|
|
1416
|
+
|
|
1417
|
+
A role granted by a share link.
|
|
1418
|
+
|
|
1419
|
+
```typescript
|
|
1420
|
+
type ShareRole = (typeof SHARE_ROLES)[number]
|
|
1421
|
+
```
|
|
1422
|
+
|
|
1423
|
+
### Functions
|
|
1424
|
+
|
|
1425
|
+
#### `ActivityCard(props)`
|
|
1426
|
+
|
|
1427
|
+
Compact, clickable inline card for a single captured activity.
|
|
1428
|
+
|
|
1429
|
+
```typescript
|
|
1430
|
+
function ActivityCard({ activity, onActivityClick }: ActivityCardProps): JSX.Element
|
|
1431
|
+
```
|
|
1432
|
+
|
|
1433
|
+
- `props` — Component props.
|
|
1434
|
+
|
|
1435
|
+
**Returns:** The rendered activity card element.
|
|
1436
|
+
|
|
1437
|
+
#### `activityFromEvent(raw)`
|
|
1438
|
+
|
|
1439
|
+
Maps a raw SSE `activity` event payload into a normalized {@link Activity}.
|
|
1440
|
+
Tolerates missing optional fields and supplies an id/timestamp if absent.
|
|
1441
|
+
|
|
1442
|
+
```typescript
|
|
1443
|
+
function activityFromEvent(raw: {
|
|
1444
|
+
id?: string
|
|
1445
|
+
type?: string
|
|
1446
|
+
status?: string
|
|
1447
|
+
recipient?: string
|
|
1448
|
+
summary?: string
|
|
1449
|
+
timestamp?: string
|
|
1450
|
+
}): Activity
|
|
1451
|
+
```
|
|
1452
|
+
|
|
1453
|
+
- `raw` — The `activity` field from the SSE event.
|
|
1454
|
+
- `raw.id` — Activity id; generated if absent.
|
|
1455
|
+
- `raw.type` — Channel type; defaults to `webhook` if absent.
|
|
1456
|
+
- `raw.status` — Lifecycle status; defaults to `captured` if absent.
|
|
1457
|
+
- `raw.recipient` — Optional recipient.
|
|
1458
|
+
- `raw.summary` — Optional short summary.
|
|
1459
|
+
- `raw.timestamp` — ISO timestamp; defaults to now if absent.
|
|
1460
|
+
|
|
1461
|
+
**Returns:** A normalized Activity object.
|
|
1462
|
+
|
|
1463
|
+
#### `activityIconName(type)`
|
|
1464
|
+
|
|
1465
|
+
Returns the bonded-icon-set glyph NAME for an activity type — pass it to
|
|
1466
|
+
`<Icon name={…} />` to render the themed SVG. Unknown/future types (which
|
|
1467
|
+
{@link activityFromEvent} normalizes to `webhook`) reuse the `link` glyph
|
|
1468
|
+
rather than risk a `getIcon` throw.
|
|
1469
|
+
|
|
1470
|
+
```typescript
|
|
1471
|
+
function activityIconName(type: ActivityType): IconName
|
|
1472
|
+
```
|
|
1473
|
+
|
|
1474
|
+
- `type` — The activity channel type.
|
|
1475
|
+
|
|
1476
|
+
**Returns:** The icon-set glyph name for the type.
|
|
1477
|
+
|
|
1478
|
+
#### `activityStatusColors(status)`
|
|
1479
|
+
|
|
1480
|
+
Resolves the status-pill colors for a given status. Uses RGBA literals (not
|
|
1481
|
+
ClassMap classes) because these semantic status hues are not part of the
|
|
1482
|
+
surface/text token set — the same approach `VerificationBadge` takes for its
|
|
1483
|
+
pass/fail coloring.
|
|
1484
|
+
|
|
1485
|
+
```typescript
|
|
1486
|
+
function activityStatusColors(status: ActivityStatus): { fg: string; bg: string }
|
|
1487
|
+
```
|
|
1488
|
+
|
|
1489
|
+
- `status` — The activity status.
|
|
1490
|
+
|
|
1491
|
+
**Returns:** An object with `fg` (text) and `bg` (background) CSS color strings.
|
|
1492
|
+
|
|
1493
|
+
#### `activityStatusLabel(status)`
|
|
1494
|
+
|
|
1495
|
+
Human-readable, translated label for a status (shown in the status pill).
|
|
1496
|
+
|
|
1497
|
+
```typescript
|
|
1498
|
+
function activityStatusLabel(status: ActivityStatus): string
|
|
1499
|
+
```
|
|
1500
|
+
|
|
1501
|
+
- `status` — The activity status.
|
|
1502
|
+
|
|
1503
|
+
**Returns:** The translated status label.
|
|
1504
|
+
|
|
1505
|
+
#### `activitySummaryLine(activity)`
|
|
1506
|
+
|
|
1507
|
+
Builds the one-line summary shown on the inline card: the activity's own
|
|
1508
|
+
summary, with the recipient appended after an arrow when present
|
|
1509
|
+
(e.g. `Welcome email → user@example.com`). Falls back to a translated,
|
|
1510
|
+
type-specific default when no summary was captured.
|
|
1511
|
+
|
|
1512
|
+
```typescript
|
|
1513
|
+
function activitySummaryLine(activity: Pick<Activity, 'type' | 'recipient' | 'summary'>): string
|
|
1514
|
+
```
|
|
1515
|
+
|
|
1516
|
+
- `activity` — The activity to summarize.
|
|
1517
|
+
|
|
1518
|
+
**Returns:** The single-line summary string.
|
|
1519
|
+
|
|
1520
|
+
#### `activityTypeLabel(type)`
|
|
1521
|
+
|
|
1522
|
+
Human-readable, translated label for a channel type (used as filter-tab labels).
|
|
1523
|
+
|
|
1524
|
+
```typescript
|
|
1525
|
+
function activityTypeLabel(type: ActivityType): string
|
|
1526
|
+
```
|
|
1527
|
+
|
|
1528
|
+
- `type` — The activity channel type.
|
|
1529
|
+
|
|
1530
|
+
**Returns:** The translated channel label.
|
|
1531
|
+
|
|
1532
|
+
#### `autoCommitReducer(state, action)`
|
|
1533
|
+
|
|
1534
|
+
Pure reducer for the auto-commit countdown. Deterministic and side-effect
|
|
1535
|
+
free: the component performs the actual commit when {@link isAutoCommitDue}
|
|
1536
|
+
becomes true, then dispatches `fired`.
|
|
1537
|
+
|
|
1538
|
+
```typescript
|
|
1539
|
+
function autoCommitReducer(state: AutoCommitState, action: AutoCommitAction): AutoCommitState
|
|
1540
|
+
```
|
|
1541
|
+
|
|
1542
|
+
- `state` — The current countdown state.
|
|
1543
|
+
- `action` — The action to apply.
|
|
1544
|
+
|
|
1545
|
+
**Returns:** The next countdown state.
|
|
1546
|
+
|
|
1547
|
+
#### `buildReportPayload(form, clientInfo)`
|
|
1548
|
+
|
|
1549
|
+
Builds the `POST /projects/:id/report` body from the form state, trimming all
|
|
1550
|
+
text fields and omitting `steps` entirely when it is blank. When `clientInfo`
|
|
1551
|
+
is supplied and non-empty, it is attached; an `undefined` or empty diagnostics
|
|
1552
|
+
object is omitted from the payload.
|
|
1553
|
+
|
|
1554
|
+
```typescript
|
|
1555
|
+
function buildReportPayload(form: ReportFormState, clientInfo?: ClientInfo): ReportPayload
|
|
1556
|
+
```
|
|
1557
|
+
|
|
1558
|
+
- `form` — The report form state.
|
|
1559
|
+
- `clientInfo` — Optional client diagnostics from {@link collectClientInfo}.
|
|
1560
|
+
|
|
1561
|
+
**Returns:** The normalized report payload.
|
|
1562
|
+
|
|
1563
|
+
#### `buildSharePayload(role)`
|
|
1564
|
+
|
|
1565
|
+
Builds the `POST /projects/:projectId/shares` body for a role.
|
|
1566
|
+
|
|
1567
|
+
```typescript
|
|
1568
|
+
function buildSharePayload(role?: 'viewer' | 'commenter' | 'editor' | 'owner'): SharePayload
|
|
1569
|
+
```
|
|
1570
|
+
|
|
1571
|
+
- `role` — The role to grant (defaults to {@link DEFAULT_SHARE_ROLE}).
|
|
1572
|
+
|
|
1573
|
+
**Returns:** The normalized share payload.
|
|
1574
|
+
|
|
1575
|
+
#### `buildShareUrl(result, origin)`
|
|
1576
|
+
|
|
1577
|
+
Resolves the copyable public URL for a created share link. Prefers the
|
|
1578
|
+
backend-supplied `url` (canonical origin / custom domain); otherwise builds
|
|
1579
|
+
`<origin>/share/<slug>` from the given origin, tolerating a trailing slash.
|
|
1580
|
+
|
|
1581
|
+
```typescript
|
|
1582
|
+
function buildShareUrl(result: ShareLinkResult, origin: string): string
|
|
1583
|
+
```
|
|
1584
|
+
|
|
1585
|
+
- `result` — The created link from the share endpoint.
|
|
1586
|
+
- `origin` — The current page origin (e.g. `window.location.origin`).
|
|
1587
|
+
|
|
1588
|
+
**Returns:** The absolute, copyable share URL.
|
|
1589
|
+
|
|
1590
|
+
#### `ChatPanel(props)`
|
|
1591
|
+
|
|
1592
|
+
AI chat panel with conversation history dropdown and Claude Code-style tool display.
|
|
1593
|
+
|
|
1594
|
+
```typescript
|
|
1595
|
+
function ChatPanel({
|
|
1596
|
+
projectId,
|
|
1597
|
+
endpoint,
|
|
1598
|
+
initialMessage,
|
|
1599
|
+
onInitialMessageSent,
|
|
1600
|
+
activeFile,
|
|
1601
|
+
openTabs,
|
|
1602
|
+
onFileOpen,
|
|
1603
|
+
onFileDoubleClick,
|
|
1604
|
+
onFileDiff,
|
|
1605
|
+
onFileRevert,
|
|
1606
|
+
onFileChange,
|
|
1607
|
+
onFileDeleted,
|
|
1608
|
+
onCommit,
|
|
1609
|
+
onActivityClick,
|
|
1610
|
+
onProfileClick,
|
|
1611
|
+
onReadyToBuild,
|
|
1612
|
+
awaitingSandboxBoot,
|
|
1613
|
+
onClientAction,
|
|
1614
|
+
onTurnComplete,
|
|
1615
|
+
onLoadingChange,
|
|
1616
|
+
onNavigatePreview,
|
|
1617
|
+
onRegisterPushHandler,
|
|
1618
|
+
autoSubmitSignal,
|
|
1619
|
+
initialInputValue,
|
|
1620
|
+
hideConversationMenu,
|
|
1621
|
+
renderConversationHeader = true,
|
|
1622
|
+
conversationId: controlledConversationId,
|
|
1623
|
+
chatKey: controlledChatKey,
|
|
1624
|
+
onConversationId: controlledOnConversationId,
|
|
1625
|
+
openShareSignal: controlledShareSignal,
|
|
1626
|
+
openReportSignal: controlledReportSignal,
|
|
1627
|
+
openSettingsSignal: controlledSettingsSignal,
|
|
1628
|
+
onManageCustomModels,
|
|
1629
|
+
gitStatusTick,
|
|
1630
|
+
pendingMessage,
|
|
1631
|
+
pendingMessageKey,
|
|
1632
|
+
pendingMessageSuppressUser,
|
|
1633
|
+
pendingMessageUserInitiated,
|
|
1634
|
+
userEditedFile,
|
|
1635
|
+
userEditedFileKey,
|
|
1636
|
+
isPro,
|
|
1637
|
+
buildUpgradeCta,
|
|
1638
|
+
buildHelpUpgradeSection,
|
|
1639
|
+
userAvatar,
|
|
1640
|
+
agentName,
|
|
1641
|
+
productName,
|
|
1642
|
+
version,
|
|
1643
|
+
feedbackUrl,
|
|
1644
|
+
className,
|
|
1645
|
+
}: ChatPanelProps): JSX.Element
|
|
1646
|
+
```
|
|
1647
|
+
|
|
1648
|
+
- `props` — Component props (see {@link MessageItemProps}).
|
|
1649
|
+
|
|
1650
|
+
**Returns:** The rendered chat panel element.
|
|
1651
|
+
|
|
1652
|
+
#### `clampPanelSize(currentSize, deltaPx, containerWidth, min, max)`
|
|
1653
|
+
|
|
1654
|
+
Clamp a panel's new size after a pixel drag delta.
|
|
1655
|
+
|
|
1656
|
+
```typescript
|
|
1657
|
+
function clampPanelSize(
|
|
1658
|
+
currentSize: number,
|
|
1659
|
+
deltaPx: number,
|
|
1660
|
+
containerWidth: number,
|
|
1661
|
+
min?: number,
|
|
1662
|
+
max?: number,
|
|
1663
|
+
): number
|
|
1664
|
+
```
|
|
1665
|
+
|
|
1666
|
+
- `currentSize` — The panel's current size as a percentage.
|
|
1667
|
+
- `deltaPx` — The drag delta in pixels (positive = grow the left panel).
|
|
1668
|
+
- `containerWidth` — The layout container width in pixels.
|
|
1669
|
+
- `min` — Minimum allowed percentage. Defaults to {@link MIN_PANEL_PERCENT}.
|
|
1670
|
+
- `max` — Maximum allowed percentage. Defaults to {@link MAX_PANEL_PERCENT}.
|
|
1671
|
+
|
|
1672
|
+
**Returns:** The new size as a percentage, clamped to `[min, max]`.
|
|
1673
|
+
|
|
1674
|
+
#### `collectClientInfo(opts)`
|
|
1675
|
+
|
|
1676
|
+
Collects client-side diagnostics for a report. Reads `navigator`
|
|
1677
|
+
(userAgent/platform/language), `window` (inner viewport size, screen size,
|
|
1678
|
+
location href), plus the caller-supplied app version and theme. Every access
|
|
1679
|
+
is guarded (`typeof window/navigator !== 'undefined'` and per-property
|
|
1680
|
+
presence) so it is SSR-safe and never throws — it returns only the fields it
|
|
1681
|
+
could actually read, so the result may be partial or (in a headless
|
|
1682
|
+
environment) empty.
|
|
1683
|
+
|
|
1684
|
+
```typescript
|
|
1685
|
+
function collectClientInfo(opts?: { appVersion?: string; theme?: string }): ClientInfo
|
|
1686
|
+
```
|
|
1687
|
+
|
|
1688
|
+
- `opts` — Caller-supplied context.
|
|
1689
|
+
- `opts.appVersion` — The running build version, if known.
|
|
1690
|
+
- `opts.theme` — The active theme (`'light'` | `'dark'`), if known.
|
|
1691
|
+
|
|
1692
|
+
**Returns:** The populated subset of {@link ClientInfo}.
|
|
1693
|
+
|
|
1694
|
+
#### `CommandPalette(props)`
|
|
1695
|
+
|
|
1696
|
+
Command Palette overlay.
|
|
1697
|
+
|
|
1698
|
+
```typescript
|
|
1699
|
+
function CommandPalette({ commands, onDismiss }: CommandPaletteProps): JSX.Element
|
|
1700
|
+
```
|
|
1701
|
+
|
|
1702
|
+
- `props` — Component props.
|
|
1703
|
+
|
|
1704
|
+
**Returns:** The command palette element.
|
|
1705
|
+
|
|
1706
|
+
#### `DeviceFrameSelector(props)`
|
|
1707
|
+
|
|
1708
|
+
A dropdown that selects the preview device frame and hosts the Rotate +
|
|
1709
|
+
Open-in-new-tab actions.
|
|
1710
|
+
|
|
1711
|
+
```typescript
|
|
1712
|
+
function DeviceFrameSelector({
|
|
1713
|
+
current,
|
|
1714
|
+
onChange,
|
|
1715
|
+
className,
|
|
1716
|
+
canRotate,
|
|
1717
|
+
rotated,
|
|
1718
|
+
onRotate,
|
|
1719
|
+
onOpenExternal,
|
|
1720
|
+
}: DeviceFrameSelectorWithActionsProps): JSX.Element
|
|
1721
|
+
```
|
|
1722
|
+
|
|
1723
|
+
- `props` — Component props (see {@link DeviceFrameSelectorWithActionsProps}).
|
|
1724
|
+
|
|
1725
|
+
**Returns:** The rendered device-frame selector element.
|
|
1726
|
+
|
|
1727
|
+
#### `deviceIconName(device)`
|
|
1728
|
+
|
|
1729
|
+
Returns the icon-set glyph name for a device frame.
|
|
1730
|
+
|
|
1731
|
+
```typescript
|
|
1732
|
+
function deviceIconName(device: DeviceFrame): string
|
|
1733
|
+
```
|
|
1734
|
+
|
|
1735
|
+
- `device` — The device frame.
|
|
1736
|
+
|
|
1737
|
+
**Returns:** The icon name registered in the bonded icon set.
|
|
1738
|
+
|
|
1739
|
+
#### `EditorPanel(props)`
|
|
1740
|
+
|
|
1741
|
+
Code editor panel with tab bar and Monaco integration.
|
|
1742
|
+
|
|
1743
|
+
```typescript
|
|
1744
|
+
function EditorPanel({
|
|
1745
|
+
className,
|
|
1746
|
+
onActiveFileChange,
|
|
1747
|
+
onEditorReady,
|
|
1748
|
+
onTabsChange,
|
|
1749
|
+
fileStatuses,
|
|
1750
|
+
formattingFile,
|
|
1751
|
+
countdownFile,
|
|
1752
|
+
countdownKey,
|
|
1753
|
+
formatEstimate = 2000,
|
|
1754
|
+
onFixWithAI,
|
|
1755
|
+
onTabDoubleClick,
|
|
1756
|
+
}: EditorPanelProps): JSX.Element
|
|
1757
|
+
```
|
|
1758
|
+
|
|
1759
|
+
- `props` — Component props.
|
|
1760
|
+
|
|
1761
|
+
**Returns:** The rendered editor panel element.
|
|
1762
|
+
|
|
1763
|
+
#### `FileExplorer(props)`
|
|
1764
|
+
|
|
1765
|
+
Tree-view file explorer component with multi-select, keyboard navigation, and drag-and-drop.
|
|
1766
|
+
|
|
1767
|
+
```typescript
|
|
1768
|
+
function FileExplorer({
|
|
1769
|
+
files,
|
|
1770
|
+
onFileSelect,
|
|
1771
|
+
onFileDoubleClick,
|
|
1772
|
+
onDirExpand,
|
|
1773
|
+
onRename,
|
|
1774
|
+
onDelete,
|
|
1775
|
+
onDeleteMultiple,
|
|
1776
|
+
onMoveFiles,
|
|
1777
|
+
onNewFile,
|
|
1778
|
+
onNewFolder,
|
|
1779
|
+
onCollapseAll,
|
|
1780
|
+
className,
|
|
1781
|
+
persistKey,
|
|
1782
|
+
activeFile,
|
|
1783
|
+
fileStatuses,
|
|
1784
|
+
}: FileExplorerProps): JSX.Element
|
|
1785
|
+
```
|
|
1786
|
+
|
|
1787
|
+
- `props` — Component props (see {@link FileTreeItemProps}).
|
|
1788
|
+
|
|
1789
|
+
**Returns:** The rendered file explorer element.
|
|
1790
|
+
|
|
1791
|
+
#### `filterActivitiesByType(activities, type)`
|
|
1792
|
+
|
|
1793
|
+
Filters a list of activities by channel type. `null` (the "All" tab) returns
|
|
1794
|
+
every activity unchanged.
|
|
1795
|
+
|
|
1796
|
+
```typescript
|
|
1797
|
+
function filterActivitiesByType(activities: Activity[], type: ActivityType | null): Activity[]
|
|
1798
|
+
```
|
|
1799
|
+
|
|
1800
|
+
- `activities` — The activities to filter.
|
|
1801
|
+
- `type` — The channel type to keep, or `null` for all.
|
|
1802
|
+
|
|
1803
|
+
**Returns:** The filtered list (a new array unless `type` is null).
|
|
1804
|
+
|
|
1805
|
+
#### `formatAutoCommitBadge(state)`
|
|
1806
|
+
|
|
1807
|
+
Formats the countdown's remaining seconds for the compact badge (e.g. `"12s"`).
|
|
1808
|
+
Returns `''` when there is nothing to show (disabled or paused).
|
|
1809
|
+
|
|
1810
|
+
```typescript
|
|
1811
|
+
function formatAutoCommitBadge(state: AutoCommitState): string
|
|
1812
|
+
```
|
|
1813
|
+
|
|
1814
|
+
- `state` — The countdown state.
|
|
1815
|
+
|
|
1816
|
+
**Returns:** The badge label, or `''`.
|
|
1817
|
+
|
|
1818
|
+
#### `formatReportConfirmation(result)`
|
|
1819
|
+
|
|
1820
|
+
Builds the confirmation message shown after a report is submitted. Returns the
|
|
1821
|
+
English defaults; the component passes these through `t()` at render. The
|
|
1822
|
+
success `defaultValue` may contain the `{{productName}}` interpolation token,
|
|
1823
|
+
which the caller fills in from the host's product identity (neutral default:
|
|
1824
|
+
"the IDE"). When the result is not `ok`, returns the failure message.
|
|
1825
|
+
|
|
1826
|
+
```typescript
|
|
1827
|
+
function formatReportConfirmation(result: ReportResult): { key: string; defaultValue: string }
|
|
1828
|
+
```
|
|
1829
|
+
|
|
1830
|
+
- `result` — The `POST /projects/:id/report` response.
|
|
1831
|
+
|
|
1832
|
+
**Returns:** `{ key, defaultValue }` for the confirmation/failure message.
|
|
1833
|
+
|
|
1834
|
+
#### `getCustomEventCardFactory(name)`
|
|
1835
|
+
|
|
1836
|
+
Resolve the registered card factory for a custom event name, if any.
|
|
1837
|
+
|
|
1838
|
+
```typescript
|
|
1839
|
+
function getCustomEventCardFactory(name: string): ChatEventCardFactory | undefined
|
|
1840
|
+
```
|
|
1841
|
+
|
|
1842
|
+
- `name` — The custom event `name`.
|
|
1843
|
+
|
|
1844
|
+
**Returns:** The registered factory, or undefined if none is registered.
|
|
1845
|
+
|
|
1846
|
+
#### `groupCommandsByCategory(commands, categories)`
|
|
1847
|
+
|
|
1848
|
+
Groups commands under their categories, preserving category and command
|
|
1849
|
+
order and dropping empty categories. Used by the `/settings` command
|
|
1850
|
+
reference (and any other view that lists commands by section) so the
|
|
1851
|
+
grouping stays in sync with the registry automatically.
|
|
1852
|
+
|
|
1853
|
+
```typescript
|
|
1854
|
+
function groupCommandsByCategory(
|
|
1855
|
+
commands?: readonly CommandDef[],
|
|
1856
|
+
categories?: readonly CommandCategory[],
|
|
1857
|
+
): CommandGroup[]
|
|
1858
|
+
```
|
|
1859
|
+
|
|
1860
|
+
- `commands` — Command registry to group (defaults to {@link COMMANDS}).
|
|
1861
|
+
- `categories` — Ordered categories (defaults to {@link COMMAND_CATEGORIES}).
|
|
1862
|
+
|
|
1863
|
+
**Returns:** One {@link CommandGroup} per non-empty category, in category order.
|
|
1864
|
+
|
|
1865
|
+
#### `hasRenderableAvatar(avatar)`
|
|
1866
|
+
|
|
1867
|
+
Whether a stored avatar value is renderable (vs. needing the icon fallback).
|
|
1868
|
+
|
|
1869
|
+
```typescript
|
|
1870
|
+
function hasRenderableAvatar(avatar?: string | null): boolean
|
|
1871
|
+
```
|
|
1872
|
+
|
|
1873
|
+
- `avatar` — The avatar value from user metadata.
|
|
1874
|
+
|
|
1875
|
+
**Returns:** `true` when {@link resolveUserAvatar} would return a src.
|
|
1876
|
+
|
|
1877
|
+
#### `Icon(props)`
|
|
1878
|
+
|
|
1879
|
+
Renders the named glyph from the bonded icon set.
|
|
1880
|
+
|
|
1881
|
+
```typescript
|
|
1882
|
+
function Icon({ name, size = 16, className, ...rest }: IconProps): JSX.Element
|
|
1883
|
+
```
|
|
1884
|
+
|
|
1885
|
+
- `props` — {@link IconProps}.
|
|
1886
|
+
|
|
1887
|
+
**Returns:** An `<svg>` element rendering the named glyph.
|
|
1888
|
+
|
|
1889
|
+
#### `isAutoCommitArmed(state)`
|
|
1890
|
+
|
|
1891
|
+
Whether the countdown is actively armed (counting down), i.e. a 1s tick
|
|
1892
|
+
interval should be running. False when disabled or paused after a commit.
|
|
1893
|
+
|
|
1894
|
+
```typescript
|
|
1895
|
+
function isAutoCommitArmed(state: AutoCommitState): boolean
|
|
1896
|
+
```
|
|
1897
|
+
|
|
1898
|
+
- `state` — The countdown state.
|
|
1899
|
+
|
|
1900
|
+
**Returns:** `true` when `remaining` is a number.
|
|
1901
|
+
|
|
1902
|
+
#### `isAutoCommitCountdownVisible(state)`
|
|
1903
|
+
|
|
1904
|
+
Whether the countdown is in its visible window — armed and within the final
|
|
1905
|
+
{@link AUTO_COMMIT_COUNTDOWN_VISIBLE_SECONDS} seconds — i.e. the commit
|
|
1906
|
+
button should render the live "Auto-commit in Ns" label instead of "Commit".
|
|
1907
|
+
|
|
1908
|
+
```typescript
|
|
1909
|
+
function isAutoCommitCountdownVisible(state: AutoCommitState): boolean
|
|
1910
|
+
```
|
|
1911
|
+
|
|
1912
|
+
- `state` — The countdown state.
|
|
1913
|
+
|
|
1914
|
+
**Returns:** `true` when armed with at most the visible-window seconds left.
|
|
1915
|
+
|
|
1916
|
+
#### `isAutoCommitDue(state)`
|
|
1917
|
+
|
|
1918
|
+
Whether a commit is due this instant (the countdown has reached zero). The
|
|
1919
|
+
component reacts to this by running `/commit` and dispatching `fired`.
|
|
1920
|
+
|
|
1921
|
+
```typescript
|
|
1922
|
+
function isAutoCommitDue(state: AutoCommitState): boolean
|
|
1923
|
+
```
|
|
1924
|
+
|
|
1925
|
+
- `state` — The countdown state.
|
|
1926
|
+
|
|
1927
|
+
**Returns:** `true` when `remaining === 0`.
|
|
1928
|
+
|
|
1929
|
+
#### `isAutoCommitEnabled(state)`
|
|
1930
|
+
|
|
1931
|
+
Whether auto-commit is enabled (a positive cadence is configured), regardless
|
|
1932
|
+
of whether it is currently counting down or paused.
|
|
1933
|
+
|
|
1934
|
+
```typescript
|
|
1935
|
+
function isAutoCommitEnabled(state: AutoCommitState): boolean
|
|
1936
|
+
```
|
|
1937
|
+
|
|
1938
|
+
- `state` — The countdown state.
|
|
1939
|
+
|
|
1940
|
+
**Returns:** `true` when `intervalSeconds > 0`.
|
|
1941
|
+
|
|
1942
|
+
#### `isDeviceRotatable(device)`
|
|
1943
|
+
|
|
1944
|
+
Whether a device frame can be rotated (true only for fixed-frame devices —
|
|
1945
|
+
tablet and mobile). Responsive and desktop are full-width with nothing to
|
|
1946
|
+
rotate, so the "Rotate" control is enabled only "where possible".
|
|
1947
|
+
|
|
1948
|
+
```typescript
|
|
1949
|
+
function isDeviceRotatable(device: DeviceFrame): boolean
|
|
1950
|
+
```
|
|
1951
|
+
|
|
1952
|
+
- `device` — The device frame.
|
|
1953
|
+
|
|
1954
|
+
**Returns:** `true` if the frame has a fixed size that can be rotated.
|
|
1955
|
+
|
|
1956
|
+
#### `isInputFocused(e)`
|
|
1957
|
+
|
|
1958
|
+
Returns true when the event target is an interactive input element
|
|
1959
|
+
where shortcuts should be suppressed by default.
|
|
1960
|
+
|
|
1961
|
+
```typescript
|
|
1962
|
+
function isInputFocused(e: KeyboardEvent): boolean
|
|
1963
|
+
```
|
|
1964
|
+
|
|
1965
|
+
- `e` — The keyboard event.
|
|
1966
|
+
|
|
1967
|
+
**Returns:** Whether an input-like element is focused.
|
|
1968
|
+
|
|
1969
|
+
#### `isMonacoFocused(e)`
|
|
1970
|
+
|
|
1971
|
+
Returns true when focus is inside a Monaco editor instance.
|
|
1972
|
+
|
|
1973
|
+
```typescript
|
|
1974
|
+
function isMonacoFocused(e: KeyboardEvent): boolean
|
|
1975
|
+
```
|
|
1976
|
+
|
|
1977
|
+
- `e` — The keyboard event.
|
|
1978
|
+
|
|
1979
|
+
**Returns:** Whether the target is inside `.monaco-editor`.
|
|
1980
|
+
|
|
1981
|
+
#### `isReportFormValid(form)`
|
|
1982
|
+
|
|
1983
|
+
Whether the report form has the minimum required fields: a non-empty title
|
|
1984
|
+
and a non-empty description.
|
|
1985
|
+
|
|
1986
|
+
```typescript
|
|
1987
|
+
function isReportFormValid(form: ReportFormState): boolean
|
|
1988
|
+
```
|
|
1989
|
+
|
|
1990
|
+
- `form` — The report form state.
|
|
1991
|
+
|
|
1992
|
+
**Returns:** `true` when the form can be submitted.
|
|
1993
|
+
|
|
1994
|
+
#### `isShareRole(value)`
|
|
1995
|
+
|
|
1996
|
+
Type guard for a valid {@link ShareRole} (case-insensitive callers should
|
|
1997
|
+
lower-case first).
|
|
1998
|
+
|
|
1999
|
+
```typescript
|
|
2000
|
+
function isShareRole(value: string): boolean
|
|
2001
|
+
```
|
|
2002
|
+
|
|
2003
|
+
- `value` — The candidate value.
|
|
2004
|
+
|
|
2005
|
+
**Returns:** `true` when `value` is one of the {@link SHARE_ROLES}.
|
|
2006
|
+
|
|
2007
|
+
#### `KeyboardShortcutsPanel(props)`
|
|
2008
|
+
|
|
2009
|
+
Keyboard shortcuts reference panel.
|
|
2010
|
+
|
|
2011
|
+
```typescript
|
|
2012
|
+
function KeyboardShortcutsPanel({ shortcuts, onDismiss }: KeyboardShortcutsPanelProps): JSX.Element
|
|
2013
|
+
```
|
|
2014
|
+
|
|
2015
|
+
- `props` — Component props.
|
|
2016
|
+
|
|
2017
|
+
**Returns:** The keyboard shortcuts panel element.
|
|
2018
|
+
|
|
2019
|
+
#### `livePanelSize(layout, panelConfigs, index)`
|
|
2020
|
+
|
|
2021
|
+
The live size (percentage) of the visible panel at `index`, read from
|
|
2022
|
+
`layout.sizes` keyed by the panel's position group (where `resizePanel`
|
|
2023
|
+
writes), falling back to the panel's `defaultSize`, then to an equal split.
|
|
2024
|
+
|
|
2025
|
+
```typescript
|
|
2026
|
+
function livePanelSize(layout: WorkspaceLayout, panelConfigs: PanelConfig[], index: number): number
|
|
2027
|
+
```
|
|
2028
|
+
|
|
2029
|
+
- `layout` — The current workspace layout.
|
|
2030
|
+
- `panelConfigs` — The visible panel configs, in render order.
|
|
2031
|
+
- `index` — The index of the panel within `panelConfigs`.
|
|
2032
|
+
|
|
2033
|
+
**Returns:** The panel size as a percentage.
|
|
2034
|
+
|
|
2035
|
+
#### `normalizeKeys(keys)`
|
|
2036
|
+
|
|
2037
|
+
Normalize a shortcut definition string into the same format produced by
|
|
2038
|
+
`serializeEvent`. Accepts `mod+shift+f` style strings (case-insensitive).
|
|
2039
|
+
|
|
2040
|
+
```typescript
|
|
2041
|
+
function normalizeKeys(keys: string): string
|
|
2042
|
+
```
|
|
2043
|
+
|
|
2044
|
+
- `keys` — Raw shortcut string.
|
|
2045
|
+
|
|
2046
|
+
**Returns:** Normalized lowercase combo string.
|
|
2047
|
+
|
|
2048
|
+
#### `parseAutoCommitCommand(input)`
|
|
2049
|
+
|
|
2050
|
+
Parses an `/autocommit [seconds]` command.
|
|
2051
|
+
|
|
2052
|
+
Returns `{ seconds: null }` when `/autocommit` is typed with no argument (the
|
|
2053
|
+
caller shows usage/current state), `{ seconds: n }` for a non-negative integer
|
|
2054
|
+
argument (`0` cancels), or `null` when the input is not the command.
|
|
2055
|
+
|
|
2056
|
+
```typescript
|
|
2057
|
+
function parseAutoCommitCommand(input: string): { seconds: number | null } | null
|
|
2058
|
+
```
|
|
2059
|
+
|
|
2060
|
+
- `input` — The raw chat input.
|
|
2061
|
+
|
|
2062
|
+
**Returns:** The parsed command, or `null` when it is not `/autocommit`.
|
|
2063
|
+
|
|
2064
|
+
#### `parseReportCommand(input)`
|
|
2065
|
+
|
|
2066
|
+
Parses a `/report [title]` or `/bug [title]` command. Returns the (possibly
|
|
2067
|
+
empty) trimmed title used to seed the modal when the input is one of those
|
|
2068
|
+
commands, else `null`.
|
|
2069
|
+
|
|
2070
|
+
```typescript
|
|
2071
|
+
function parseReportCommand(input: string): { title: string } | null
|
|
2072
|
+
```
|
|
2073
|
+
|
|
2074
|
+
- `input` — The raw chat input.
|
|
2075
|
+
|
|
2076
|
+
**Returns:** `{ title }` when it's a `/report` or `/bug` command, else `null`.
|
|
2077
|
+
|
|
2078
|
+
#### `parseShareCommand(input)`
|
|
2079
|
+
|
|
2080
|
+
Parses a `/share [role]` command. Bare `/share` creates a link at the default
|
|
2081
|
+
`viewer` role; `/share <role>` uses the named role when valid (any case); an
|
|
2082
|
+
unrecognized role is reported as invalid so the caller can show usage. Returns
|
|
2083
|
+
`null` when the input is not the `/share` command.
|
|
2084
|
+
|
|
2085
|
+
```typescript
|
|
2086
|
+
function parseShareCommand(input: string): ShareCommand | null
|
|
2087
|
+
```
|
|
2088
|
+
|
|
2089
|
+
- `input` — The raw chat input.
|
|
2090
|
+
|
|
2091
|
+
**Returns:** The parsed {@link ShareCommand}, or `null`.
|
|
2092
|
+
|
|
2093
|
+
#### `PreviewPanel(props)`
|
|
2094
|
+
|
|
2095
|
+
Live preview panel with iframe, device frame selector, and URL bar.
|
|
2096
|
+
|
|
2097
|
+
```typescript
|
|
2098
|
+
function PreviewPanel({
|
|
2099
|
+
loadingIndicator,
|
|
2100
|
+
restartingIndicator,
|
|
2101
|
+
className,
|
|
2102
|
+
onPreviewError,
|
|
2103
|
+
onPreviewStuck,
|
|
2104
|
+
onRenderState,
|
|
2105
|
+
uiCommand,
|
|
2106
|
+
onUiResult,
|
|
2107
|
+
fileChangeTick,
|
|
2108
|
+
buildingHint,
|
|
2109
|
+
isBuilding,
|
|
2110
|
+
wakeAt,
|
|
2111
|
+
}: PreviewPanelProps): JSX.Element
|
|
2112
|
+
```
|
|
2113
|
+
|
|
2114
|
+
- `props` — Component props.
|
|
2115
|
+
|
|
2116
|
+
**Returns:** The rendered preview panel element.
|
|
2117
|
+
|
|
2118
|
+
#### `QuickOpen(props)`
|
|
2119
|
+
|
|
2120
|
+
Quick Open file finder overlay.
|
|
2121
|
+
|
|
2122
|
+
```typescript
|
|
2123
|
+
function QuickOpen({ projectId, onFileOpen, onDismiss }: QuickOpenProps): JSX.Element
|
|
2124
|
+
```
|
|
2125
|
+
|
|
2126
|
+
- `props` — Component props.
|
|
2127
|
+
|
|
2128
|
+
**Returns:** The quick open element.
|
|
2129
|
+
|
|
2130
|
+
#### `QuickPicker(props)`
|
|
2131
|
+
|
|
2132
|
+
Quick picker overlay with keyboard navigation.
|
|
2133
|
+
|
|
2134
|
+
```typescript
|
|
2135
|
+
function QuickPicker({
|
|
2136
|
+
items,
|
|
2137
|
+
placeholder,
|
|
2138
|
+
onSelect,
|
|
2139
|
+
onDismiss,
|
|
2140
|
+
loading,
|
|
2141
|
+
initialQuery,
|
|
2142
|
+
className,
|
|
2143
|
+
}: QuickPickerProps): JSX.Element
|
|
2144
|
+
```
|
|
2145
|
+
|
|
2146
|
+
- `props` — Component props.
|
|
2147
|
+
|
|
2148
|
+
**Returns:** The quick picker element.
|
|
2149
|
+
|
|
2150
|
+
#### `registerCustomEventCard(name, factory)`
|
|
2151
|
+
|
|
2152
|
+
Register a renderer for a custom chat-stream event. Consuming apps call this at
|
|
2153
|
+
startup so their own `{ type: 'custom', name }` events surface as chat cards —
|
|
2154
|
+
keeping app-specific events out of the core ai-chat union and this package's
|
|
2155
|
+
ChatPanel. Re-registering the same name overwrites the previous factory.
|
|
2156
|
+
|
|
2157
|
+
```typescript
|
|
2158
|
+
function registerCustomEventCard(name: string, factory: ChatEventCardFactory): void
|
|
2159
|
+
```
|
|
2160
|
+
|
|
2161
|
+
- `name` — The custom event `name` to handle (matches the emitted event's `name`).
|
|
2162
|
+
- `factory` — Builds the card from the event's `data` (or returns null to skip).
|
|
2163
|
+
|
|
2164
|
+
#### `ReportModal(props)`
|
|
2165
|
+
|
|
2166
|
+
The bug-report / feedback modal opened by `/report`, `/bug`, and the header
|
|
2167
|
+
bug-report button.
|
|
2168
|
+
|
|
2169
|
+
```typescript
|
|
2170
|
+
function ReportModal({
|
|
2171
|
+
projectId,
|
|
2172
|
+
conversationId,
|
|
2173
|
+
initialTitle,
|
|
2174
|
+
onClose,
|
|
2175
|
+
onSubmitted,
|
|
2176
|
+
productName = DEFAULT_PRODUCT_NAME,
|
|
2177
|
+
appVersion,
|
|
2178
|
+
}: {
|
|
2179
|
+
projectId: string
|
|
2180
|
+
conversationId?: string | null
|
|
2181
|
+
initialTitle?: string
|
|
2182
|
+
onClose: () => void
|
|
2183
|
+
onSubmitted: (result: ReportResult) => void
|
|
2184
|
+
productName?: string
|
|
2185
|
+
appVersion?: string
|
|
2186
|
+
}): JSX.Element
|
|
2187
|
+
```
|
|
2188
|
+
|
|
2189
|
+
- `props` — Component props.
|
|
2190
|
+
|
|
2191
|
+
**Returns:** The rendered report modal.
|
|
2192
|
+
|
|
2193
|
+
#### `ResizeHandle(props)`
|
|
2194
|
+
|
|
2195
|
+
Draggable handle for resizing adjacent panels. Uses Pointer Events so it works
|
|
2196
|
+
with mouse, touch, and pen (an iPad drag resizes just like a desktop drag); a
|
|
2197
|
+
wide invisible grab zone wraps a thin visible line that brightens to the
|
|
2198
|
+
primary color on hover/drag for a clear affordance. Arrow keys nudge the split
|
|
2199
|
+
for keyboard users.
|
|
2200
|
+
|
|
2201
|
+
```typescript
|
|
2202
|
+
function ResizeHandle({
|
|
2203
|
+
onResize,
|
|
2204
|
+
direction = 'horizontal',
|
|
2205
|
+
className,
|
|
2206
|
+
}: ResizeHandleProps): JSX.Element
|
|
2207
|
+
```
|
|
2208
|
+
|
|
2209
|
+
- `props` — Component props.
|
|
2210
|
+
|
|
2211
|
+
**Returns:** The rendered resize handle element.
|
|
2212
|
+
|
|
2213
|
+
#### `resolveAutoCommitSeconds(saved)`
|
|
2214
|
+
|
|
2215
|
+
Resolves the persisted `project.settings.autoCommitSeconds` value to the
|
|
2216
|
+
effective cadence. A finite number is an explicit user choice: positive
|
|
2217
|
+
values floor to whole seconds, non-positive values mean "the user turned
|
|
2218
|
+
auto-commit off" (`0`). Anything else — missing, never configured, or
|
|
2219
|
+
invalid — falls back to {@link DEFAULT_AUTO_COMMIT_SECONDS}, because
|
|
2220
|
+
auto-commit is on by default.
|
|
2221
|
+
|
|
2222
|
+
```typescript
|
|
2223
|
+
function resolveAutoCommitSeconds(saved: unknown): number
|
|
2224
|
+
```
|
|
2225
|
+
|
|
2226
|
+
- `saved` — The raw persisted setting value.
|
|
2227
|
+
|
|
2228
|
+
**Returns:** The effective cadence in whole seconds (`0` = off).
|
|
2229
|
+
|
|
2230
|
+
#### `resolveDeviceSize(device, orientation)`
|
|
2231
|
+
|
|
2232
|
+
Resolves the concrete iframe `width`/`height` for a device frame at a given
|
|
2233
|
+
orientation. Fluid frames (responsive/desktop) ignore orientation and fill
|
|
2234
|
+
the preview area (`width` from dims, `height: '100%'`). Fixed frames render
|
|
2235
|
+
at their pixel size in portrait and at the swapped size in landscape.
|
|
2236
|
+
|
|
2237
|
+
```typescript
|
|
2238
|
+
function resolveDeviceSize(
|
|
2239
|
+
device: DeviceFrame,
|
|
2240
|
+
orientation: DeviceOrientation,
|
|
2241
|
+
): { width: string; height: string }
|
|
2242
|
+
```
|
|
2243
|
+
|
|
2244
|
+
- `device` — The device frame.
|
|
2245
|
+
- `orientation` — The preview orientation.
|
|
2246
|
+
|
|
2247
|
+
**Returns:** The CSS `width` and `height` to apply to the preview iframe.
|
|
2248
|
+
|
|
2249
|
+
#### `resolveUserAvatar(avatar)`
|
|
2250
|
+
|
|
2251
|
+
Resolve a stored avatar value to a safe `<img>` src, or `null` to fall back to
|
|
2252
|
+
the generic icon.
|
|
2253
|
+
|
|
2254
|
+
```typescript
|
|
2255
|
+
function resolveUserAvatar(avatar?: string | null): string | null
|
|
2256
|
+
```
|
|
2257
|
+
|
|
2258
|
+
- `avatar` — The avatar value from user metadata (data-URI, URL, or absent).
|
|
2259
|
+
|
|
2260
|
+
**Returns:** A safe image src string, or `null` when there is no renderable avatar.
|
|
2261
|
+
|
|
2262
|
+
#### `SearchPanel(props)`
|
|
2263
|
+
|
|
2264
|
+
Search-in-files panel for the IDE sidebar with find-and-replace support.
|
|
2265
|
+
|
|
2266
|
+
```typescript
|
|
2267
|
+
function SearchPanel({
|
|
2268
|
+
projectId,
|
|
2269
|
+
onResultClick,
|
|
2270
|
+
className,
|
|
2271
|
+
excludedDirs,
|
|
2272
|
+
onExcludedDirsChange,
|
|
2273
|
+
}: SearchPanelProps): JSX.Element
|
|
2274
|
+
```
|
|
2275
|
+
|
|
2276
|
+
- `props` — Component props.
|
|
2277
|
+
|
|
2278
|
+
**Returns:** The search panel element.
|
|
2279
|
+
|
|
2280
|
+
#### `serializeEvent(e, isMac)`
|
|
2281
|
+
|
|
2282
|
+
Serialize a `KeyboardEvent` into a normalized combo string.
|
|
2283
|
+
Format: modifier keys in order `mod+ctrl+alt+shift+key` (lowercase).
|
|
2284
|
+
`mod` maps to Meta on Mac, Control elsewhere.
|
|
2285
|
+
|
|
2286
|
+
```typescript
|
|
2287
|
+
function serializeEvent(e: KeyboardEvent, isMac?: boolean): string
|
|
2288
|
+
```
|
|
2289
|
+
|
|
2290
|
+
- `e` — The keyboard event.
|
|
2291
|
+
- `isMac` — Override platform detection (for testing).
|
|
2292
|
+
|
|
2293
|
+
**Returns:** Serialized combo string.
|
|
2294
|
+
|
|
2295
|
+
#### `ShareModal(props)`
|
|
2296
|
+
|
|
2297
|
+
The share-link modal opened by `/share`, `/share <role>`, and the header
|
|
2298
|
+
share button.
|
|
2299
|
+
|
|
2300
|
+
```typescript
|
|
2301
|
+
function ShareModal({
|
|
2302
|
+
projectId,
|
|
2303
|
+
initialRole = DEFAULT_SHARE_ROLE,
|
|
2304
|
+
onClose,
|
|
2305
|
+
onCreated,
|
|
2306
|
+
}: {
|
|
2307
|
+
projectId: string
|
|
2308
|
+
initialRole?: ShareRole
|
|
2309
|
+
onClose: () => void
|
|
2310
|
+
onCreated?: (result: ShareLinkResult) => void
|
|
2311
|
+
}): JSX.Element
|
|
2312
|
+
```
|
|
2313
|
+
|
|
2314
|
+
- `props` — Component props.
|
|
2315
|
+
|
|
2316
|
+
**Returns:** The rendered share modal.
|
|
2317
|
+
|
|
2318
|
+
#### `SidebarTabs(props)`
|
|
2319
|
+
|
|
2320
|
+
Sidebar tab strip with file explorer and search icons.
|
|
2321
|
+
|
|
2322
|
+
```typescript
|
|
2323
|
+
function SidebarTabs({ activeTab, onTabChange, children, className }: SidebarTabsProps): JSX.Element
|
|
2324
|
+
```
|
|
2325
|
+
|
|
2326
|
+
- `props` — Component props.
|
|
2327
|
+
|
|
2328
|
+
**Returns:** The sidebar tabs element.
|
|
2329
|
+
|
|
2330
|
+
#### `TabBar(props)`
|
|
2331
|
+
|
|
2332
|
+
Horizontally scrollable tab bar for open editor files.
|
|
2333
|
+
|
|
2334
|
+
```typescript
|
|
2335
|
+
function TabBar({
|
|
2336
|
+
tabs,
|
|
2337
|
+
activeFile,
|
|
2338
|
+
onSelect,
|
|
2339
|
+
onClose,
|
|
2340
|
+
onDoubleClick,
|
|
2341
|
+
fileStatuses,
|
|
2342
|
+
className,
|
|
2343
|
+
}: TabBarProps): JSX.Element | null
|
|
2344
|
+
```
|
|
2345
|
+
|
|
2346
|
+
- `props` — Component props (see {@link TabItemProps}).
|
|
2347
|
+
|
|
2348
|
+
**Returns:** The rendered tab bar element, or null if no tabs are open.
|
|
2349
|
+
|
|
2350
|
+
#### `useCoarsePointer()`
|
|
2351
|
+
|
|
2352
|
+
Whether the primary pointer is coarse (touch). Use for interaction
|
|
2353
|
+
decisions: ≥44px touch targets, always-visible controls that desktop
|
|
2354
|
+
reveals on hover (hover does not exist on touch).
|
|
2355
|
+
|
|
2356
|
+
```typescript
|
|
2357
|
+
function useCoarsePointer(): boolean
|
|
2358
|
+
```
|
|
2359
|
+
|
|
2360
|
+
**Returns:** True on touch-first devices.
|
|
2361
|
+
|
|
2362
|
+
#### `useKeyboardShortcuts(shortcuts)`
|
|
2363
|
+
|
|
2364
|
+
Registers global keyboard shortcuts on the document.
|
|
2365
|
+
|
|
2366
|
+
```typescript
|
|
2367
|
+
function useKeyboardShortcuts(shortcuts: KeyboardShortcut[]): void
|
|
2368
|
+
```
|
|
2369
|
+
|
|
2370
|
+
- `shortcuts` — Array of shortcut definitions. Callers should wrap the array in `useMemo` to avoid unnecessary re-subscriptions.
|
|
2371
|
+
|
|
2372
|
+
#### `useMediaQueryMatch(query)`
|
|
2373
|
+
|
|
2374
|
+
Subscribes to a CSS media query. SSR-safe: reports `false` until mounted in
|
|
2375
|
+
a browser.
|
|
2376
|
+
|
|
2377
|
+
```typescript
|
|
2378
|
+
function useMediaQueryMatch(query: string): boolean
|
|
2379
|
+
```
|
|
2380
|
+
|
|
2381
|
+
- `query` — A media query string, e.g. `'(max-width: 767px)'`.
|
|
2382
|
+
|
|
2383
|
+
**Returns:** Whether the query currently matches.
|
|
2384
|
+
|
|
2385
|
+
#### `useNarrowViewport()`
|
|
2386
|
+
|
|
2387
|
+
Whether the viewport is phone-width (below 768px). Use for layout-density
|
|
2388
|
+
decisions: bigger type, taller rows, `dvh`-capped popovers.
|
|
2389
|
+
|
|
2390
|
+
```typescript
|
|
2391
|
+
function useNarrowViewport(): boolean
|
|
2392
|
+
```
|
|
2393
|
+
|
|
2394
|
+
**Returns:** True on phone-width viewports.
|
|
2395
|
+
|
|
2396
|
+
#### `UserAvatar(props)`
|
|
2397
|
+
|
|
2398
|
+
Renders the user's avatar image, or the generic `user` icon when there is no
|
|
2399
|
+
safe, renderable avatar. When {@link UserAvatarProps.onClick} is provided the
|
|
2400
|
+
visual is wrapped in an accessible button so the avatar can open the user's
|
|
2401
|
+
profile.
|
|
2402
|
+
|
|
2403
|
+
```typescript
|
|
2404
|
+
function UserAvatar({ userAvatar, size = 24, onClick }: UserAvatarProps): JSX.Element
|
|
2405
|
+
```
|
|
2406
|
+
|
|
2407
|
+
- `props` — {@link UserAvatarProps}.
|
|
2408
|
+
|
|
2409
|
+
**Returns:** The avatar image or icon fallback, optionally wrapped in a button.
|
|
2410
|
+
|
|
2411
|
+
#### `WorkspaceLayout(props)`
|
|
2412
|
+
|
|
2413
|
+
Top-level workspace layout that arranges child panels in a row with draggable
|
|
2414
|
+
vertical dividers between them. Each divider resizes its left panel; the new
|
|
2415
|
+
size is written back through `resizePanel`, so it persists in workspace state.
|
|
2416
|
+
|
|
2417
|
+
```typescript
|
|
2418
|
+
function WorkspaceLayout({ children, className }: WorkspaceLayoutProps): JSX.Element
|
|
2419
|
+
```
|
|
2420
|
+
|
|
2421
|
+
- `props` — Component props.
|
|
2422
|
+
|
|
2423
|
+
**Returns:** The rendered workspace layout element.
|
|
2424
|
+
|
|
2425
|
+
### Constants
|
|
2426
|
+
|
|
2427
|
+
#### `ACTIVITY_TYPES`
|
|
2428
|
+
|
|
2429
|
+
All channel types, in the order their filter tabs should appear.
|
|
2430
|
+
|
|
2431
|
+
```typescript
|
|
2432
|
+
const ACTIVITY_TYPES: ActivityType[]
|
|
2433
|
+
```
|
|
2434
|
+
|
|
2435
|
+
#### `AUTO_COMMIT_COUNTDOWN_VISIBLE_SECONDS`
|
|
2436
|
+
|
|
2437
|
+
How many final seconds of the countdown are DISPLAYED as a live countdown.
|
|
2438
|
+
Until the countdown drops to this threshold, the commit-bar button stays a
|
|
2439
|
+
plain green "Commit" (a bare "12s" pill told users nothing); the countdown
|
|
2440
|
+
label only takes over for these last seconds, right before the auto-commit
|
|
2441
|
+
fires. Cadences at or below the threshold show the countdown the whole time.
|
|
2442
|
+
|
|
2443
|
+
```typescript
|
|
2444
|
+
const AUTO_COMMIT_COUNTDOWN_VISIBLE_SECONDS: 3
|
|
2445
|
+
```
|
|
2446
|
+
|
|
2447
|
+
#### `AUTO_COMMIT_DISABLED`
|
|
2448
|
+
|
|
2449
|
+
The disabled (off) countdown state — the reducer's initial value.
|
|
2450
|
+
|
|
2451
|
+
```typescript
|
|
2452
|
+
const AUTO_COMMIT_DISABLED: AutoCommitState
|
|
2453
|
+
```
|
|
2454
|
+
|
|
2455
|
+
#### `COARSE_POINTER_QUERY`
|
|
2456
|
+
|
|
2457
|
+
The touch-first media query — matches when the PRIMARY pointer is coarse
|
|
2458
|
+
(finger), i.e. phones/tablets, regardless of viewport width.
|
|
2459
|
+
|
|
2460
|
+
```typescript
|
|
2461
|
+
const COARSE_POINTER_QUERY: '(pointer: coarse)'
|
|
2462
|
+
```
|
|
2463
|
+
|
|
2464
|
+
#### `COMMAND_CATEGORIES`
|
|
2465
|
+
|
|
2466
|
+
Ordered list of command categories used as section headings.
|
|
2467
|
+
|
|
2468
|
+
```typescript
|
|
2469
|
+
const COMMAND_CATEGORIES: readonly CommandCategory[]
|
|
2470
|
+
```
|
|
2471
|
+
|
|
2472
|
+
#### `COMMANDS`
|
|
2473
|
+
|
|
2474
|
+
Every available slash command, grouped by category order. This is the
|
|
2475
|
+
authoritative list — the menu, key handling, `/help`, AND the system prompt's
|
|
2476
|
+
"Available Commands" section all read from it.
|
|
2477
|
+
|
|
2478
|
+
```typescript
|
|
2479
|
+
const COMMANDS: readonly CommandDef[]
|
|
2480
|
+
```
|
|
2481
|
+
|
|
2482
|
+
#### `DEFAULT_AUTO_COMMIT_SECONDS`
|
|
2483
|
+
|
|
2484
|
+
The default auto-commit cadence in seconds — auto-commit is ON by default.
|
|
2485
|
+
Projects that have never persisted `autoCommitSeconds` hydrate to this
|
|
2486
|
+
cadence (paused, arming on the first file change); only an explicit `0`
|
|
2487
|
+
(the user cancelled) keeps auto-commit off.
|
|
2488
|
+
|
|
2489
|
+
The value is the TOTAL debounce after the last file change (once the agent's
|
|
2490
|
+
turn has finished): a short quiet period, then the final
|
|
2491
|
+
{@link AUTO_COMMIT_COUNTDOWN_VISIBLE_SECONDS} seconds render as a live
|
|
2492
|
+
countdown on the commit button. 5s = 2s quiet + 3s visible countdown.
|
|
2493
|
+
|
|
2494
|
+
```typescript
|
|
2495
|
+
const DEFAULT_AUTO_COMMIT_SECONDS: 5
|
|
2496
|
+
```
|
|
2497
|
+
|
|
2498
|
+
#### `DEFAULT_SEARCH_EXCLUDED_DIRS`
|
|
2499
|
+
|
|
2500
|
+
Default search-excluded directory names shown when the host supplies none —
|
|
2501
|
+
VS Code's `search.exclude`/`files.exclude` defaults plus the platform's
|
|
2502
|
+
vendored/build dirs. MUST stay in sync with the API-side list in
|
|
2503
|
+
`@molecule/api-ai-tools` (utilities.ts) — the cross-stack import boundary
|
|
2504
|
+
forces the duplication.
|
|
2505
|
+
|
|
2506
|
+
```typescript
|
|
2507
|
+
const DEFAULT_SEARCH_EXCLUDED_DIRS: readonly [
|
|
2508
|
+
'node_modules',
|
|
2509
|
+
'bower_components',
|
|
2510
|
+
'.git',
|
|
2511
|
+
'.svn',
|
|
2512
|
+
'.hg',
|
|
2513
|
+
'CVS',
|
|
2514
|
+
'dist',
|
|
2515
|
+
'.next',
|
|
2516
|
+
'.vite',
|
|
2517
|
+
'molecule',
|
|
2518
|
+
]
|
|
2519
|
+
```
|
|
2520
|
+
|
|
2521
|
+
#### `DEFAULT_SHARE_ROLE`
|
|
2522
|
+
|
|
2523
|
+
The default (and safest) role when `/share` is run with no argument.
|
|
2524
|
+
|
|
2525
|
+
```typescript
|
|
2526
|
+
const DEFAULT_SHARE_ROLE: 'viewer' | 'commenter' | 'editor' | 'owner'
|
|
2527
|
+
```
|
|
2528
|
+
|
|
2529
|
+
#### `DEVICE_DIMENSIONS`
|
|
2530
|
+
|
|
2531
|
+
The fixed pixel frame each device renders the preview iframe at. `none`
|
|
2532
|
+
(responsive) and `desktop` are fluid — full width, full height, nothing to
|
|
2533
|
+
rotate. `tablet` (768×1024) and `mobile` (375×667) are fixed frames that can
|
|
2534
|
+
be rotated to landscape (swapping width/height).
|
|
2535
|
+
|
|
2536
|
+
```typescript
|
|
2537
|
+
const DEVICE_DIMENSIONS: Record<DeviceFrame, DeviceDimensions>
|
|
2538
|
+
```
|
|
2539
|
+
|
|
2540
|
+
#### `DEVICE_FRAMES`
|
|
2541
|
+
|
|
2542
|
+
The device frames the selector dropdown lists, in display order.
|
|
2543
|
+
`none` = responsive (no fixed frame, full width).
|
|
2544
|
+
|
|
2545
|
+
```typescript
|
|
2546
|
+
const DEVICE_FRAMES: readonly DeviceFrame[]
|
|
2547
|
+
```
|
|
2548
|
+
|
|
2549
|
+
#### `DEVICE_META`
|
|
2550
|
+
|
|
2551
|
+
Per-frame display metadata: the icon-set glyph name and the i18n label
|
|
2552
|
+
(key + English default) shown in the dropdown trigger + menu items.
|
|
2553
|
+
|
|
2554
|
+
```typescript
|
|
2555
|
+
const DEVICE_META: Record<
|
|
2556
|
+
DeviceFrame,
|
|
2557
|
+
{ readonly icon: IconName; readonly labelKey: string; readonly label: string }
|
|
2558
|
+
>
|
|
2559
|
+
```
|
|
2560
|
+
|
|
2561
|
+
#### `EMPTY_REPORT_FORM`
|
|
2562
|
+
|
|
2563
|
+
An empty report form (the modal's initial state).
|
|
2564
|
+
|
|
2565
|
+
```typescript
|
|
2566
|
+
const EMPTY_REPORT_FORM: ReportFormState
|
|
2567
|
+
```
|
|
2568
|
+
|
|
2569
|
+
#### `IS_MAC`
|
|
2570
|
+
|
|
2571
|
+
Detect macOS / iOS for Cmd vs Ctrl.
|
|
2572
|
+
|
|
2573
|
+
```typescript
|
|
2574
|
+
const IS_MAC: boolean
|
|
2575
|
+
```
|
|
2576
|
+
|
|
2577
|
+
#### `MAX_AVATAR_SRC_LENGTH`
|
|
2578
|
+
|
|
2579
|
+
Maximum avatar source length we will render inline (~256 KB data-URI).
|
|
2580
|
+
|
|
2581
|
+
```typescript
|
|
2582
|
+
const MAX_AVATAR_SRC_LENGTH: 262144
|
|
2583
|
+
```
|
|
2584
|
+
|
|
2585
|
+
#### `MAX_PANEL_PERCENT`
|
|
2586
|
+
|
|
2587
|
+
Largest a panel may grow to, as a percentage of the container.
|
|
2588
|
+
|
|
2589
|
+
```typescript
|
|
2590
|
+
const MAX_PANEL_PERCENT: 80
|
|
2591
|
+
```
|
|
2592
|
+
|
|
2593
|
+
#### `MIN_PANEL_PERCENT`
|
|
2594
|
+
|
|
2595
|
+
Smallest a panel may shrink to, as a percentage of the container.
|
|
2596
|
+
|
|
2597
|
+
```typescript
|
|
2598
|
+
const MIN_PANEL_PERCENT: 10
|
|
2599
|
+
```
|
|
2600
|
+
|
|
2601
|
+
#### `NARROW_VIEWPORT_QUERY`
|
|
2602
|
+
|
|
2603
|
+
The phone-width media query — matches viewports below 768px, mirroring the
|
|
2604
|
+
host workspace's single-pane mobile breakpoint.
|
|
2605
|
+
|
|
2606
|
+
```typescript
|
|
2607
|
+
const NARROW_VIEWPORT_QUERY: '(max-width: 767px)'
|
|
2608
|
+
```
|
|
2609
|
+
|
|
2610
|
+
#### `SETTINGS`
|
|
2611
|
+
|
|
2612
|
+
Every user-controllable setting, in display order. The authoritative list —
|
|
2613
|
+
the `/settings` view (via `buildSettingsList`) and the system prompt both read
|
|
2614
|
+
from it, so they cannot drift. The default `model` and the per-mode
|
|
2615
|
+
`planModel` / `executeModel` rows are kept distinct (rather than collapsed
|
|
2616
|
+
into one "Model" row); `effort`, `autoCommit`, and `hooks` are each listed
|
|
2617
|
+
alongside (or in `hooks`' case, instead of) the command the panel references —
|
|
2618
|
+
so a user's actual configuration is never understated and the panel never
|
|
2619
|
+
shows a command for a setting it hides.
|
|
2620
|
+
|
|
2621
|
+
```typescript
|
|
2622
|
+
const SETTINGS: readonly SettingMeta[]
|
|
2623
|
+
```
|
|
2624
|
+
|
|
2625
|
+
#### `SHARE_ROLE_LABELS`
|
|
2626
|
+
|
|
2627
|
+
Short English labels per role (the component wraps these in `t()` at render).
|
|
2628
|
+
|
|
2629
|
+
```typescript
|
|
2630
|
+
const SHARE_ROLE_LABELS: Record<'viewer' | 'commenter' | 'editor' | 'owner', string>
|
|
2631
|
+
```
|
|
2632
|
+
|
|
2633
|
+
#### `SHARE_ROLES`
|
|
2634
|
+
|
|
2635
|
+
Share roles, ordered least- to most-privileged. Mirrors the
|
|
2636
|
+
`@molecule/api-resource-share` `SHARE_ROLES` contract; duplicated here (rather
|
|
2637
|
+
than imported) because an `app-*` package may not import an `api-*` package
|
|
2638
|
+
across the stack boundary.
|
|
2639
|
+
|
|
2640
|
+
```typescript
|
|
2641
|
+
const SHARE_ROLES: readonly ['viewer', 'commenter', 'editor', 'owner']
|
|
2642
|
+
```
|
|
2643
|
+
|
|
2644
|
+
#### `ToolCallCard`
|
|
2645
|
+
|
|
2646
|
+
Compact tool-call row with status dot, label, summary, and expandable detail pane.
|
|
2647
|
+
|
|
2648
|
+
```typescript
|
|
2649
|
+
const ToolCallCard: MemoExoticComponent<
|
|
2650
|
+
({
|
|
2651
|
+
id,
|
|
2652
|
+
name,
|
|
2653
|
+
input,
|
|
2654
|
+
output,
|
|
2655
|
+
status,
|
|
2656
|
+
fileDiff,
|
|
2657
|
+
isUndone: isUndoneProp,
|
|
2658
|
+
onUndoToggle,
|
|
2659
|
+
onFileOpen,
|
|
2660
|
+
onFileDoubleClick,
|
|
2661
|
+
onFileDiff,
|
|
2662
|
+
onFileRevert,
|
|
2663
|
+
onAskUserResponse,
|
|
2664
|
+
className,
|
|
2665
|
+
}: ToolCallCardProps) => JSX.Element | null
|
|
2666
|
+
>
|
|
2667
|
+
```
|
|
2668
|
+
|
|
2669
|
+
## Injection Notes
|
|
2670
|
+
|
|
2671
|
+
### Requirements
|
|
2672
|
+
|
|
2673
|
+
Peer dependencies:
|
|
2674
|
+
|
|
2675
|
+
- `@molecule/app-ai-chat` ^1.0.1
|
|
2676
|
+
- `@molecule/app-ai-models` ^1.0.1
|
|
2677
|
+
- `@molecule/app-ai-voice` ^1.0.1
|
|
2678
|
+
- `@molecule/app-code-editor` ^1.0.1
|
|
2679
|
+
- `@molecule/app-country-flags` ^1.0.1
|
|
2680
|
+
- `@molecule/app-i18n` ^1.0.1
|
|
2681
|
+
- `@molecule/app-icons` ^1.0.1
|
|
2682
|
+
- `@molecule/app-ide` ^1.0.1
|
|
2683
|
+
- `@molecule/app-live-preview` ^1.0.1
|
|
2684
|
+
- `@molecule/app-logger` ^1.0.1
|
|
2685
|
+
- `@molecule/app-react` ^1.0.1
|
|
2686
|
+
- `@molecule/app-storage` ^1.0.1
|
|
2687
|
+
- `@molecule/app-ui` ^1.0.1
|
|
2688
|
+
- `@molecule/app-ui-react` ^1.0.1
|
|
2689
|
+
- `react` ^18.0.0 || ^19.0.0
|
|
2690
|
+
- `react-dom` ^18.0.0 || ^19.0.0
|
|
2691
|
+
|
|
2692
|
+
### Runtime Dependencies
|
|
2693
|
+
|
|
2694
|
+
- `@molecule/app-ai-chat`
|
|
2695
|
+
- `@molecule/app-ai-models`
|
|
2696
|
+
- `@molecule/app-ai-voice`
|
|
2697
|
+
- `@molecule/app-code-editor`
|
|
2698
|
+
- `@molecule/app-country-flags`
|
|
2699
|
+
- `@molecule/app-i18n`
|
|
2700
|
+
- `@molecule/app-icons`
|
|
2701
|
+
- `@molecule/app-ide`
|
|
2702
|
+
- `@molecule/app-live-preview`
|
|
2703
|
+
- `@molecule/app-logger`
|
|
2704
|
+
- `@molecule/app-react`
|
|
2705
|
+
- `@molecule/app-storage`
|
|
2706
|
+
- `@molecule/app-ui`
|
|
2707
|
+
- `@molecule/app-ui-react`
|
|
2708
|
+
- `material-file-icons`
|
|
2709
|
+
- `react`
|
|
2710
|
+
- `react-dom`
|
|
2711
|
+
|
|
2712
|
+
- The panels are hook-driven and THROW without provider wiring: wrap the
|
|
2713
|
+
tree in `@molecule/app-react`'s `WorkspaceProvider`, `EditorProvider`,
|
|
2714
|
+
`ChatProvider`, and `PreviewProvider` (or the umbrella
|
|
2715
|
+
`MoleculeProvider`), each wired to a bond — typically
|
|
2716
|
+
`@molecule/app-ide-default` (workspace/layout state + persistence),
|
|
2717
|
+
`@molecule/app-code-editor-monaco`, `@molecule/app-ai-chat-http`
|
|
2718
|
+
(streaming chat endpoint), and `@molecule/app-live-preview-iframe`.
|
|
2719
|
+
`ChatPanel` additionally needs the bonded HTTP client
|
|
2720
|
+
(`useHttpClient`) and `I18nProvider`; `getClassMap()` needs a ClassMap
|
|
2721
|
+
bond.
|
|
2722
|
+
- `WorkspaceLayout` takes panels as CHILDREN and matches them in order to
|
|
2723
|
+
the workspace provider's panel configs (extra configs are ignored, so
|
|
2724
|
+
rendering 2 children against the default 3-panel layout works). Panel
|
|
2725
|
+
sizes persist through the workspace provider's `resizePanel`.
|
|
2726
|
+
- App-specific chat/stream events do NOT belong in this package — emit
|
|
2727
|
+
`{ type: 'custom', name, data }` events and register a card with
|
|
2728
|
+
`registerCustomEventCard(name, factory)` in the consuming app.
|
|
2729
|
+
- `ReportModal` and `ShareModal` are exported so a HOST can mount them
|
|
2730
|
+
itself. They need only `projectId` + the bonded HTTP client — no
|
|
2731
|
+
workspace/editor/preview provider, no chat, no running sandbox — because
|
|
2732
|
+
they POST to `/projects/:id/report` and `/projects/:id/shares` on the
|
|
2733
|
+
platform API. Do NOT route a host's "report a bug" / "share" button
|
|
2734
|
+
through `ChatPanel`'s `openReportSignal` / `openShareSignal` alone: those
|
|
2735
|
+
props are observed inside the panel, so in any phase where the host does
|
|
2736
|
+
not mount a `ChatPanel` (a hibernating sandbox, an error screen) the
|
|
2737
|
+
button silently does nothing. Mount the modal directly in those phases.
|
|
2738
|
+
`ChatPanel` renders its own copies for `/report` and `/share`; a host that
|
|
2739
|
+
mounts them too must gate on whether the panel is mounted so the modal
|
|
2740
|
+
never opens twice.
|
|
2741
|
+
- `ReportModal` does NOT show its own success state — it calls `onSubmitted`
|
|
2742
|
+
and closes, so a host that mounts it MUST surface the confirmation itself
|
|
2743
|
+
(`formatReportConfirmation(result)` returns the i18n key + default copy,
|
|
2744
|
+
and `result.url` is the filed issue). `ShareModal` does show the created
|
|
2745
|
+
link inline, but only until it is closed.
|
|
2746
|
+
- Text routes through `t('ide.*')` — `@molecule/app-locales-ide` supplies
|
|
2747
|
+
translations.
|
|
2748
|
+
|
|
2749
|
+
## Translations
|
|
2750
|
+
|
|
2751
|
+
Translation strings are provided by `@molecule/app-locales-ide`.
|