@deepseek-ai/dsh-client-ui-conversation 0.0.1-rc.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.
Files changed (77) hide show
  1. package/LICENSE +28 -0
  2. package/README.i18n.yaml +6 -0
  3. package/README.md +65 -0
  4. package/README.zh.md +65 -0
  5. package/lib/client.js +9612 -0
  6. package/lib/index.js +28 -0
  7. package/lib/invariant.js +25 -0
  8. package/lib/types/client/apply.d.ts +16 -0
  9. package/lib/types/client/chat/AssistantMarkdown.d.ts +19 -0
  10. package/lib/types/client/chat/AssistantNodeView.d.ts +4 -0
  11. package/lib/types/client/chat/ChatNodeSeat.d.ts +11 -0
  12. package/lib/types/client/chat/ChatView.d.ts +7 -0
  13. package/lib/types/client/chat/CommandNodeView.d.ts +9 -0
  14. package/lib/types/client/chat/CompactionCommandCard.d.ts +8 -0
  15. package/lib/types/client/chat/CompactionItem.d.ts +19 -0
  16. package/lib/types/client/chat/ContextBody.d.ts +130 -0
  17. package/lib/types/client/chat/ContextInjectionRow.d.ts +26 -0
  18. package/lib/types/client/chat/GenericCommandCard.d.ts +9 -0
  19. package/lib/types/client/chat/MessageIconActions.d.ts +30 -0
  20. package/lib/types/client/chat/MessageImage.d.ts +20 -0
  21. package/lib/types/client/chat/MessageItem.d.ts +27 -0
  22. package/lib/types/client/chat/ReasoningRow.d.ts +14 -0
  23. package/lib/types/client/chat/StatsLine.d.ts +83 -0
  24. package/lib/types/client/chat/TurnTailNodeView.d.ts +7 -0
  25. package/lib/types/client/chat/message-chrome.d.ts +49 -0
  26. package/lib/types/client/chat/register-node-renderers.d.ts +7 -0
  27. package/lib/types/client/chat/tool-node-reader.d.ts +16 -0
  28. package/lib/types/client/chat/turn-assistant.d.ts +8 -0
  29. package/lib/types/client/chat/turn-metrics.d.ts +38 -0
  30. package/lib/types/client/chat/use-calendar-day.d.ts +6 -0
  31. package/lib/types/client/chat/use-throttled-visual-update.d.ts +8 -0
  32. package/lib/types/client/contract/chat-nodes.d.ts +68 -0
  33. package/lib/types/client/contract/composer-submission.d.ts +8 -0
  34. package/lib/types/client/contract/queue.d.ts +9 -0
  35. package/lib/types/client/contract/slots.d.ts +614 -0
  36. package/lib/types/client/contract/views.d.ts +39 -0
  37. package/lib/types/client/conversation-nodes/assistant.d.ts +35 -0
  38. package/lib/types/client/conversation-nodes/chat-snapshot-builder.d.ts +28 -0
  39. package/lib/types/client/conversation-nodes/command.d.ts +54 -0
  40. package/lib/types/client/conversation-nodes/common.d.ts +37 -0
  41. package/lib/types/client/conversation-nodes/compaction.d.ts +21 -0
  42. package/lib/types/client/conversation-nodes/fallback.d.ts +16 -0
  43. package/lib/types/client/conversation-nodes/inbox.d.ts +21 -0
  44. package/lib/types/client/conversation-nodes/message.d.ts +22 -0
  45. package/lib/types/client/conversation-nodes/register.d.ts +7 -0
  46. package/lib/types/client/conversation-nodes/retry.d.ts +23 -0
  47. package/lib/types/client/conversation-nodes/tool.d.ts +23 -0
  48. package/lib/types/client/conversation-nodes/turn-error.d.ts +27 -0
  49. package/lib/types/client/conversation-nodes/turn-tail.d.ts +28 -0
  50. package/lib/types/client/index.d.ts +29 -0
  51. package/lib/types/client/input/blocks.d.ts +57 -0
  52. package/lib/types/client/input/contract.d.ts +333 -0
  53. package/lib/types/client/input/decorations.d.ts +63 -0
  54. package/lib/types/client/input/facade.d.ts +219 -0
  55. package/lib/types/client/input/hub.d.ts +88 -0
  56. package/lib/types/client/input/machine.d.ts +114 -0
  57. package/lib/types/client/input/submission-policy.d.ts +46 -0
  58. package/lib/types/client/locales.d.ts +312 -0
  59. package/lib/types/client/queue/QueueDock.d.ts +29 -0
  60. package/lib/types/client/queue/store.d.ts +19 -0
  61. package/lib/types/client/service.d.ts +148 -0
  62. package/lib/types/client/settings/EnterBehaviorRow.d.ts +21 -0
  63. package/lib/types/client/skeleton/ApprovalPanel.d.ts +13 -0
  64. package/lib/types/client/skeleton/ContextMeter.d.ts +14 -0
  65. package/lib/types/client/skeleton/ConversationRoot.d.ts +5 -0
  66. package/lib/types/client/skeleton/ConversationSession.d.ts +20 -0
  67. package/lib/types/client/skeleton/DetailsPanel.d.ts +5 -0
  68. package/lib/types/client/skeleton/EmptyHero.d.ts +55 -0
  69. package/lib/types/client/skeleton/ImageLightbox.d.ts +9 -0
  70. package/lib/types/client/skeleton/InputBar.d.ts +16 -0
  71. package/lib/types/client/skeleton/PermissionSelect.d.ts +11 -0
  72. package/lib/types/client/skeleton/TodoPanel.d.ts +28 -0
  73. package/lib/types/client/stores.d.ts +22 -0
  74. package/lib/types/index.d.ts +9 -0
  75. package/lib/types/invariant.d.ts +16 -0
  76. package/lib/types/submission-settings.d.ts +20 -0
  77. package/package.json +105 -0
@@ -0,0 +1,614 @@
1
+ /** Conversation slot declarations and their composed component props. */
2
+ import type { ReactNode, RefObject } from 'react';
3
+ import type { ImageAttachmentRef } from '@deepseek-ai/dsh-attachment';
4
+ import type { InjectFace, MaybeSnapshotSelectorHook, PropsLocale, PropsRenderSlots, PropsRuntime, PropsStore, SlotHookFactory, SnapshotSelectorHook } from '@deepseek-ai/dsh-client-ui-slots';
5
+ import type { CommandNode, CompactionSummaryNode, ConversationSnapshot, ConversationTurnDataMap, ObservableSnapshot, PendingInteraction, PendingWait, SessionId, ToolCallBlock, TurnLocation, WorkspaceId } from '@deepseek-ai/dsh-client-runtime/client';
6
+ import type { MarkdownFileMentions } from '@deepseek-ai/dsh-client-ui-primitives';
7
+ import type { ComposerBlock } from '../input/blocks.ts';
8
+ import type { ComposerKeyboard, DraftAttachmentId, EditSelection, InputActions, InputNotice, InputState } from '../input/contract.ts';
9
+ import type { createChatStore } from '../stores.ts';
10
+ import type { ComposerSubmitGesture, InputSubmitMode } from './composer-submission.ts';
11
+ import type { ChatNode, ChatNodeKind } from './chat-nodes.ts';
12
+ import type { CallId, SelectionTarget, ViewTab } from './views.ts';
13
+ /** Browser-owned image that has not crossed the durable host boundary. */
14
+ export interface ComposerAttachment {
15
+ kind: 'image';
16
+ id: DraftAttachmentId;
17
+ file: File;
18
+ previewUrl: string;
19
+ }
20
+ declare module '@deepseek-ai/dsh-client-ui-slots' {
21
+ interface SlotMap {
22
+ /**
23
+ * Strict-session body inside the resident conversation scrollport. It
24
+ * owns the per-session draft mirror and active view ring.
25
+ */
26
+ 'conversation.session': {
27
+ kind: 'single';
28
+ scope: 'session';
29
+ };
30
+ /** Strict-session header above the resident conversation scrollport. */
31
+ 'conversation.session.header': {
32
+ kind: 'single';
33
+ scope: 'session';
34
+ };
35
+ /**
36
+ * Session-header actions contributed by feature plugins. Entries render
37
+ * by ascending `order`; negative values are reserved for static session
38
+ * context that precedes interactive actions.
39
+ */
40
+ 'conversation.session.header.actions': {
41
+ kind: 'list';
42
+ scope: 'session';
43
+ owner: ConversationHeaderActionOwnerProps;
44
+ };
45
+ /**
46
+ * The conversation view ring: one list entry per view tab (chat here;
47
+ * trajectory/waterfall from ui-trajectory), rendered one-at-a-time by
48
+ * the session body via `only: <active id>`. Declared by this package's
49
+ * body entry (declaring is claiming). Session scope: views read the
50
+ * conversation snapshot through the standard kit.
51
+ */
52
+ 'conversation.view': {
53
+ kind: 'list';
54
+ scope: 'session';
55
+ owner: ConvViewOwnerProps;
56
+ };
57
+ /** Final business node renderer, dispatched by `ChatConversationViewNode.kind`. */
58
+ 'conversation.chat.node': {
59
+ kind: 'keyed';
60
+ scope: 'session';
61
+ owner: ChatNodeOwnerProps;
62
+ keyProps: {
63
+ [Kind in ChatNodeKind]: {
64
+ node: ChatNode<Kind>;
65
+ };
66
+ };
67
+ hookContext: string;
68
+ inject: ChatNodeTurnDataInjected;
69
+ };
70
+ /**
71
+ * The chat view's per-command row hole: keyed dispatch on the command
72
+ * name (`command/run.name`; a run-less cross-window node has none and
73
+ * always lands on the fallback). Declared by the chat view entry; the
74
+ * render site dispatches via `entryKey: name` with GenericCommandCard as
75
+ * the `fallback` — a slash command renders durably with zero
76
+ * registration, and a domain upgrades by registering one row component.
77
+ */
78
+ 'conversation.chat.commandview': {
79
+ kind: 'keyed';
80
+ scope: 'session';
81
+ owner: CommandRowOwnerProps;
82
+ };
83
+ /**
84
+ * The completed Turn Node's extension chain, rendered before that Node's
85
+ * IconActions. Entries derive a match from the engine-owned Turn and
86
+ * closing seq before mounting, so presentation components never mount
87
+ * only to return null; an all-declined chain renders nothing.
88
+ */
89
+ 'conversation.chat.turnTail': {
90
+ kind: 'chain';
91
+ scope: 'session';
92
+ owner: TurnTailOwnerProps;
93
+ };
94
+ /** Selected Tool call output inside the details panel. */
95
+ 'conversation.details.tool': {
96
+ kind: 'single';
97
+ scope: 'session';
98
+ owner: DetailsToolOwnerProps;
99
+ };
100
+ /**
101
+ * The composer takeover chain: entries are selector-routed replacements
102
+ * of the default InputBar. Declared by this package's 'conversation'
103
+ * entry; the owner dispatches the {@link ComposerChainProps} currency and
104
+ * routing lives in entry selectors — new takeover kinds register with
105
+ * zero owner changes.
106
+ */
107
+ 'conversation.composer': {
108
+ kind: 'chain';
109
+ scope: 'session';
110
+ owner: ComposerChainProps;
111
+ };
112
+ /**
113
+ * The hero-phase Workspace picker hole: rendered by ConversationRoot
114
+ * while the session is blank (picking another workspace switches to that
115
+ * workspace's blank session, draft carried). Root scope: the picker
116
+ * reads the global workspace list.
117
+ */
118
+ 'conversation.hero.workspace': {
119
+ kind: 'single';
120
+ scope: 'root';
121
+ owner: EmptyWorkspaceOwnerProps;
122
+ };
123
+ /**
124
+ * The agent-preset chip beside the workspace picker on the new-session
125
+ * screen. Root scope: no session exists yet, so the choice is staged for
126
+ * the next one rather than applied to a current one.
127
+ */
128
+ 'conversation.hero.agentPreset': {
129
+ kind: 'single';
130
+ scope: 'root';
131
+ owner: HeroAgentPresetOwnerProps;
132
+ };
133
+ /**
134
+ * Stacked strip above the input (queue rows / GoalBar / attachments;
135
+ * entries coexist in fixed order).
136
+ */
137
+ 'conversation.input.dock': {
138
+ kind: 'list';
139
+ scope: 'session';
140
+ owner: InputZone;
141
+ };
142
+ /** The band under the composer card (stats line family), rendered inside the bar's width column via the `footer` owner prop. */
143
+ 'conversation.composer.dock': {
144
+ kind: 'list';
145
+ scope: 'session';
146
+ owner: InputZone;
147
+ };
148
+ /** Tool-row left region inside the input card (existing chrome stays in place beside entries). */
149
+ 'conversation.input.left': {
150
+ kind: 'list';
151
+ scope: 'session';
152
+ owner: InputZone;
153
+ };
154
+ /** Tool-row right region inside the input card. */
155
+ 'conversation.input.right': {
156
+ kind: 'list';
157
+ scope: 'session';
158
+ owner: InputZone;
159
+ };
160
+ /**
161
+ * The default composer body: a single slot rendered as the composer
162
+ * chain's fallback (a real entry, not a chain rider, so a
163
+ * takeover election hides rather than unmounts it and the textarea DOM
164
+ * survives). Session-maybe: the bar stays mounted across the
165
+ * no-session/session transition — the no-workspace hero renders the SAME
166
+ * textarea DOM disabled instead of a parallel inert tree — with the
167
+ * machine hooks absent until a session is current. InputBar registers
168
+ * here from this package's apply; its machine state arrives through the
169
+ * standard provide channel (useInput + inputActions), the keyboard
170
+ * command face through its own inject.
171
+ */
172
+ 'conversation.composer.bar': {
173
+ kind: 'single';
174
+ scope: 'session-maybe';
175
+ owner: ComposerBarOwnerProps;
176
+ };
177
+ /**
178
+ * The Plan-mode status seat in the composer tool row (left group,
179
+ * right of the access-mode control). Declared by the composer-bar
180
+ * entry; empty until a plan plugin registers (no placeholder
181
+ * fallback).
182
+ */
183
+ 'conversation.input.plan': {
184
+ kind: 'single';
185
+ scope: 'session';
186
+ owner: InputControlOwnerProps;
187
+ };
188
+ /**
189
+ * The model-select seat in the composer tool row (right group). Same
190
+ * empty-until-registered contract as the plan seat.
191
+ */
192
+ 'conversation.input.model': {
193
+ kind: 'single';
194
+ scope: 'session';
195
+ owner: InputControlOwnerProps;
196
+ };
197
+ }
198
+ /**
199
+ * ui-conversation's members of the session standard kit, provided through
200
+ * `sessions.provide`: every session-scope slot component
201
+ * receives the input machine's state hook and the two public actions.
202
+ */
203
+ interface SessionStandardProps {
204
+ /** Selector hook over the session's live input machine state. */
205
+ useInput: SnapshotSelectorHook<InputState>;
206
+ /** The public input action face (stable identity per session). */
207
+ inputActions: InputActions;
208
+ }
209
+ /** Input members for the resident composer while current session is optional. */
210
+ interface SessionMaybeStandardProps {
211
+ useInput: MaybeSnapshotSelectorHook<InputState>;
212
+ inputActions: InputActions | undefined;
213
+ }
214
+ }
215
+ /** Owner share of the hero agent-preset chip: the shell supplies nothing. */
216
+ export interface HeroAgentPresetOwnerProps {
217
+ /** Marker field: the chip owns its own roster, staging, and menu state. */
218
+ children?: never;
219
+ }
220
+ /** Owner share of the strict session content seat. */
221
+ export interface ConversationSessionOwnerProps {
222
+ /**
223
+ * Wrap the view ring in the transcript scrollport that also hosts the
224
+ * sticky composer seat (whole `'conversation.composer'` chain output).
225
+ * Supplied for every real session (hero/settling/active) so the composer
226
+ * keeps one tree seat across the blank → active flip; the header stays
227
+ * outside that wrapper as ordinary column chrome (`flex: none`), while
228
+ * active CSS sticks the seat to the bottom of the same scrollport so wheel
229
+ * over the footer scrolls the flow.
230
+ * @param view - the session view-ring content (null while blank chrome is hidden).
231
+ * @returns the scrollport containing `view` and the sticky composer seat.
232
+ */
233
+ wrapActiveBody?: (view: ReactNode) => ReactNode;
234
+ }
235
+ /** Header actions derive their state from the standard session/global kit. */
236
+ export interface ConversationHeaderActionOwnerProps {
237
+ }
238
+ /**
239
+ * The input-region slot currency: dock/left/right entries read
240
+ * the conversation snapshot and the live input state as owner props (both
241
+ * are point-in-time snapshots — the dispatching skeleton re-renders on
242
+ * either store's change, so entries stay current without subscribing).
243
+ */
244
+ export interface InputZone {
245
+ readonly session: ConversationSnapshot;
246
+ readonly input: InputState;
247
+ }
248
+ /**
249
+ * View-slot owner share: the cross-view inspect handoff (otherwise views need
250
+ * nothing from the render site — sessionId and the snapshot hook arrive as
251
+ * framework-standard props; tool rows go through each view's own declared
252
+ * toolview hole).
253
+ */
254
+ export interface ConvViewOwnerProps {
255
+ /** One-shot inspect request from another view (chat's Inspect button); null when idle. */
256
+ inspect?: {
257
+ callId: CallId;
258
+ } | null;
259
+ /** Acknowledge the inspect request once applied (clears the store field). */
260
+ onInspectDone?: () => void;
261
+ }
262
+ /**
263
+ * Optional prose file-mention provider, consumed via `ctx.get('chatFileMentions')`
264
+ * (optional-service convention): the chat view asks it for a closing message's
265
+ * inline-code vocabulary and threads the result into MarkdownText. Absent
266
+ * service — the providing plugin composed out of cordis.yml — turns the
267
+ * surface off; the prose renders inert code.
268
+ */
269
+ export interface ChatFileMentions {
270
+ /**
271
+ * Mention vocabulary for the closing message the owner currency names.
272
+ * @param owner - Turn-tail owner currency (Turn data, closing seq, opener).
273
+ * @returns The resolver MarkdownText consumes, or undefined when the turn
274
+ * produced nothing worth linking.
275
+ */
276
+ forClosing(owner: TurnTailOwnerProps): MarkdownFileMentions | undefined;
277
+ }
278
+ declare module '@deepseek-ai/cordis' {
279
+ interface Context {
280
+ /** Prose file-mention provider (ui-deliverables); reach via ctx.get — optional. */
281
+ chatFileMentions: ChatFileMentions;
282
+ }
283
+ }
284
+ /**
285
+ * Owner currency of the chat view's turn-tail hole: the engine-owned Turn and
286
+ * the closing assistant's anchor. Registrants read their own typed Turn data
287
+ * and open files through the same opener the tool rows use.
288
+ */
289
+ export interface TurnTailOwnerProps {
290
+ /** Engine-owned closing Turn boundary. */
291
+ turn: TurnLocation;
292
+ /** The closing assistant's seq — the anchor the tail renders under. */
293
+ seq: number;
294
+ /**
295
+ * Open a filesystem path through the Host (tool-row semantics; the chat
296
+ * view resolves relative paths against the session cwd).
297
+ */
298
+ openFile: (path: string) => void;
299
+ }
300
+ /** Hook constrained to business data published on the current Chat Node's Turn. */
301
+ export type UseChatNodeTurnData = <Key extends Extract<keyof ConversationTurnDataMap, string>>(key: Key) => Readonly<ConversationTurnDataMap[Key]> | undefined;
302
+ /** Slot-level Hook factory used by renderers reading their Node's Turn data. */
303
+ export interface ChatNodeTurnDataInjected {
304
+ hooks: {
305
+ turnData: SlotHookFactory<'conversation.chat.node', UseChatNodeTurnData>;
306
+ };
307
+ }
308
+ /** Stable owner currency delivered to one keyed Chat business renderer. */
309
+ export interface ChatNodeOwnerProps {
310
+ /** Selected Tool call, when the shared details store names one. */
311
+ selectedCallId?: CallId | undefined;
312
+ /** Session workspace root; Tool summaries display paths relative to it. */
313
+ cwd?: string | undefined;
314
+ openFile: (path: string) => void;
315
+ inspectCall: (callId: CallId) => void;
316
+ forkAt: (seq: number) => void;
317
+ /** Resolve a session-authorized historical image for inline display. */
318
+ loadImage: (attachment: ImageAttachmentRef) => Promise<string>;
319
+ fileMentions: (owner: TurnTailOwnerProps) => MarkdownFileMentions | undefined;
320
+ }
321
+ /** Full props of one registered keyed Chat business renderer. */
322
+ export type ChatNodeViewProps<Kind extends ChatNodeKind = ChatNodeKind> = PropsRuntime<'conversation.chat.node', Kind> & PropsLocale<'conversation'>;
323
+ /** Owner currency of the details panel's Tool output renderer. */
324
+ export interface DetailsToolOwnerProps {
325
+ /** Frozen selected call slice. */
326
+ block: ToolCallBlock;
327
+ /** Session workspace root for card cwd and relative-path display. */
328
+ cwd?: string | undefined;
329
+ }
330
+ /**
331
+ * Owner share of the per-command row slot: the frozen {@link CommandNode}
332
+ * slice off the snapshot (cache-stable reference — memo premise). The node
333
+ * carries the whole lifecycle (structured name/args, pairing id, and
334
+ * outcome-or-executing). A successful domain command may also carry the
335
+ * explicitly linked projection node needed to fold two log records into one
336
+ * presentation row.
337
+ */
338
+ export interface CommandRowOwnerProps {
339
+ /** Folded command lifecycle node (run + optional done). */
340
+ node: CommandNode;
341
+ /** Explicitly linked compaction checkpoint for the settled `/compact` presentation. */
342
+ compaction?: CompactionSummaryNode;
343
+ }
344
+ /** Full props of a registered command-row component. */
345
+ export type CommandRowProps = PropsRuntime<'conversation.chat.commandview'>;
346
+ /**
347
+ * Base props of a conversation view entry: the framework standard kit for the
348
+ * session-scope 'conversation.view' slot (useSession narrowed to the
349
+ * conversation snapshot by the runtime merge, sessionId, useSessions).
350
+ * Entries declaring the shared store or an inject face compose their shares
351
+ * on top (the chat entry's {@link ChatViewSlotProps}); store-less pure
352
+ * readers (ui-trajectory) take this base alone.
353
+ */
354
+ export type ConvViewProps = PropsRuntime<'conversation.view'>;
355
+ /** The shared chat store handle type declared by the Session header/body, details, and chat-view registrations. */
356
+ export type ChatStore = ReturnType<typeof createChatStore>;
357
+ /** Business callbacks injected into the conversation slot. */
358
+ export interface ConversationInjected {
359
+ /**
360
+ * Connect the selected Workspace and open its reusable/new blank session.
361
+ * When a blank session is already current, carry its draft to the target.
362
+ */
363
+ selectWorkspace: (workspaceId: WorkspaceId) => Promise<void>;
364
+ /**
365
+ * Framework-bound sources. `composerBlock` is this session's block when a
366
+ * plugin raised one; the reason is the blocker's own localized copy, which
367
+ * the root renders as the inert composer's placeholder.
368
+ */
369
+ hooks: {
370
+ composerBlock: ObservableSnapshot<ComposerBlock | undefined>;
371
+ };
372
+ }
373
+ /** Business callbacks injected into the strict Session body seat. */
374
+ export interface ConversationSessionInjected {
375
+ /** Views projected from the `conversation.view` slot ledger. */
376
+ views: {
377
+ list: () => readonly ViewTab[];
378
+ subscribe: (fn: () => void) => () => void;
379
+ version: () => number;
380
+ };
381
+ /** Release historical image URLs when this rendered session scope unmounts. */
382
+ releaseSessionImages: (sessionId: SessionId) => void;
383
+ /** Bind the input machine's draft persistence mirror to the session store. */
384
+ bindDraftMirror: (write: (text: string) => void) => () => void;
385
+ }
386
+ /** Business callbacks injected into the strict session header seat. */
387
+ export interface ConversationSessionHeaderInjected {
388
+ /** Views projected from the `conversation.view` slot ledger. */
389
+ views: {
390
+ list: () => readonly ViewTab[];
391
+ subscribe: (fn: () => void) => () => void;
392
+ version: () => number;
393
+ };
394
+ /** Select a real Session through the runtime navigation owner. */
395
+ open: (sessionId: SessionId) => void;
396
+ }
397
+ /**
398
+ * Owner share of the composer-bar slot: ConversationRoot's layout-phase
399
+ * inputs plus the input-region child-slot content it renders (the region
400
+ * slots stay declared/rendered by the conversation entry; the bar hosts the
401
+ * results as chrome).
402
+ */
403
+ export interface ComposerBarOwnerProps {
404
+ /** Hero = empty-state centered card; composer = resident bottom bar. */
405
+ variant: 'hero' | 'composer';
406
+ /**
407
+ * A block another plugin raised for this session: the bar refuses input and
408
+ * shows the blocker's reason as the placeholder, but — unlike `disabled` —
409
+ * keeps the model seat live. Every block this contract has is one the user
410
+ * clears by choosing a model, so locking that seat too would leave the
411
+ * composer telling them to do the one thing it prevents.
412
+ */
413
+ blocked?: {
414
+ readonly reason: string;
415
+ };
416
+ /**
417
+ * Inert no-workspace state: the bar renders its normal DOM fully disabled
418
+ * (textarea, add, send) so the workspace pick transitions in place instead
419
+ * of swapping component trees.
420
+ */
421
+ disabled?: boolean;
422
+ placeholder?: string;
423
+ /** Optional content rendered above the textarea. */
424
+ accessory?: ReactNode;
425
+ /** Floating overlay anchor content (menu / popup shell entries), rendered inside the card. */
426
+ overlay?: ReactNode;
427
+ /** input.left slot entries (tool row, beside the resident chrome). */
428
+ leftItems?: ReactNode;
429
+ /** input.right slot entries (tool row, before the primary button). */
430
+ rightItems?: ReactNode;
431
+ /** composer.dock entries (stats line), rendered under the card inside the bar's width column. */
432
+ footer?: ReactNode;
433
+ }
434
+ /** Injected share of the composer-bar entry (package-internal faces). */
435
+ export interface ComposerBarInjected {
436
+ /** The InputBar-exclusive keyboard/DOM command face (private plane); absent with the session. */
437
+ keyboard: ComposerKeyboard | undefined;
438
+ /** Create previews and append image ids to the session input. */
439
+ addImages: ((files: readonly File[]) => string | null) | undefined;
440
+ /** Release one preview and remove its id from session input. */
441
+ removeImage: ((id: DraftAttachmentId) => void) | undefined;
442
+ /** Resolve ordered input ids to browser-owned draft images. */
443
+ draftImages: ((ids: readonly DraftAttachmentId[]) => readonly ComposerAttachment[]) | undefined;
444
+ /** Resolve one keyboard submission gesture against the current running state and persisted preference. */
445
+ resolveSubmitMode: (running: boolean, gesture: ComposerSubmitGesture, steeringAvailable: boolean) => InputSubmitMode;
446
+ /** Toggle the shared slash menu with only its command source; absent without ui-slash or a session. */
447
+ toggleCommandMenu: ((selection: EditSelection) => void) | undefined;
448
+ /** Cancel the in-flight turn; absent with the session. */
449
+ stop: (() => void) | undefined;
450
+ /**
451
+ * Submit one slash-command line against this session's agent (the chrome
452
+ * controls' write path — the permission chip submits `/permission <preset>`);
453
+ * absent with the session.
454
+ * Resolves admission: false = rejected/unmatched/transport failure.
455
+ */
456
+ command: ((line: string) => Promise<boolean>) | undefined;
457
+ /**
458
+ * Registrant hooks compartment: the renderer binds these to
459
+ * useNotices/useLexicon (static absent sources without a session — hook
460
+ * order stays constant).
461
+ */
462
+ hooks: {
463
+ /** Latest surfaced notice (null after none; seq keys re-render of repeats). */
464
+ notices: ObservableSnapshot<InputNotice | null>;
465
+ /** Hot plain-text reference lexicon for the decoration scan (plain-text-reference decision;
466
+ * see .agents/notes/implemented/architecture/2026-07-25-web-input-machine-and-slash-pipeline.md). */
467
+ lexicon: ObservableSnapshot<ReadonlyMap<'/' | '@', readonly string[]>>;
468
+ /** Source name opened by the programmatic menu launcher, or null. */
469
+ menuLauncher: ObservableSnapshot<string | null>;
470
+ };
471
+ }
472
+ /**
473
+ * Owner share of the two named composer control seats (plan / model): the
474
+ * bar passes its disable state; the filling entry owns everything else.
475
+ */
476
+ export interface InputControlOwnerProps {
477
+ /** Session-removed lock (the bar's chrome disable state). */
478
+ locked: boolean;
479
+ }
480
+ /** Full composer-bar props: standard kit & owner share & control-seat render share & injected share (hooks bound) & locale seat. */
481
+ export type ComposerBarProps = PropsRuntime<'conversation.composer.bar'> & PropsRenderSlots<'conversation.input.plan' | 'conversation.input.model'> & InjectFace<ComposerBarInjected> & PropsLocale<'conversation'>;
482
+ /**
483
+ * Composer chain currency: what ConversationRoot dispatches at its
484
+ * renderSlotChain site. The owner declares the currency only — never a
485
+ * per-entry contract; takeover packages narrow it in their own selectors
486
+ * (`interactions.find(i => i.kind === ...)`), so new takeover kinds register
487
+ * with zero owner changes.
488
+ */
489
+ export interface ComposerChainProps {
490
+ interactions: readonly PendingInteraction[];
491
+ /** Current conversation facts for feature-owned takeover selectors. */
492
+ session: ConversationSnapshot | undefined;
493
+ }
494
+ /**
495
+ * Full conversation-slot component props: runtime & child-render (view ring
496
+ * + composer chain/bar + input-region + hero picker slots) & store & injected
497
+ * shares & the locale seat.
498
+ */
499
+ export type ConversationSlotProps = PropsRuntime<'conversation'> & PropsRenderSlots<'conversation.session' | 'conversation.session.header' | 'conversation.composer' | 'conversation.composer.bar' | 'conversation.input.overlay' | 'conversation.input.dock' | 'conversation.composer.dock' | 'conversation.input.left' | 'conversation.input.right' | 'conversation.hero.workspace' | 'conversation.hero.agentPreset'> & InjectFace<ConversationInjected> & PropsLocale<'conversation'>;
500
+ /** Full strict-session body props: per-session store, view ring, and draft mirror. */
501
+ export type ConversationSessionSlotProps = PropsRuntime<'conversation.session'> & PropsRenderSlots<'conversation.view'> & PropsStore<ChatStore> & ConversationSessionInjected;
502
+ /** Full strict-session header props: shared store, tabs/actions render shares, navigation, and locale. */
503
+ export type ConversationSessionHeaderSlotProps = PropsRuntime<'conversation.session.header'> & PropsRenderSlots<'conversation.session.header.actions'> & PropsStore<ChatStore> & ConversationSessionHeaderInjected & PropsLocale<'conversation'>;
504
+ /** The pending approval carrier the owner dispatches into the composer chain. */
505
+ export type ApprovalWait = PendingWait<'approval'>;
506
+ /**
507
+ * Approval domain face over the carrier (the ui-question PendingQuestion
508
+ * pattern): render identity and question material forwarded transparently;
509
+ * answer owns the wire encoding — the ApprovalResponsePayload value shape
510
+ * with the audit correlation the host reconciles — and turns a rejected
511
+ * carrier receipt into a thrown error. Minted per carrier via useMemo.
512
+ */
513
+ export declare class PendingApproval {
514
+ private readonly wait;
515
+ /**
516
+ * @param wait - the runtime carrier for one pending approval question.
517
+ */
518
+ constructor(wait: ApprovalWait);
519
+ /** Opaque render identity (React key / one-shot latch remount axis), forwarded from the carrier. */
520
+ get key(): string;
521
+ /** The tool the question is about (headline fallback), forwarded from the carrier payload. */
522
+ get toolName(): string;
523
+ /** The asker's human-readable WHY (headline when present), forwarded from the carrier payload. */
524
+ get reason(): string | undefined;
525
+ /** The paired tool call's id when the ask names one (command-line lookup key), forwarded from the carrier payload. */
526
+ get callId(): string | undefined;
527
+ /**
528
+ * Deliver the user's decision; a rejected carrier receipt throws. Panel
529
+ * removal stays frame-driven: the broadcast `approval/resolved` settles the
530
+ * wait and drops it from the pending list.
531
+ * @param outcome - the only two client-answerable outcomes.
532
+ */
533
+ answer(outcome: 'allowed-once' | 'rejected'): Promise<void>;
534
+ }
535
+ /**
536
+ * Full approval-composer props: the framework runtime share (chain currency +
537
+ * session/global standard kit) plus the chain `matched` share — the entry's
538
+ * selector result, already narrowed to the approval carrier — plus the
539
+ * standard locale seat. No injected share: the carrier plus the domain face
540
+ * above carry the whole behavior surface; the paired command line derives
541
+ * from useSession in-component.
542
+ */
543
+ export type ApprovalComposerProps = PropsRuntime<'conversation.composer'> & {
544
+ matched: ApprovalWait;
545
+ } & PropsLocale<'conversation'>;
546
+ /** In-memory reader position resilient to transcript width reflow. */
547
+ export interface ChatScrollPosition {
548
+ /** Stable rendered node/call identity nearest the visible reading edge. */
549
+ readonly anchorKey: string;
550
+ /** Anchor top relative to the transcript scrollport when saved. */
551
+ readonly anchorTop: number;
552
+ /** Approximate offset used before the semantic anchor is measured. */
553
+ readonly scrollTop: number;
554
+ }
555
+ /**
556
+ * Injected share of the chat view entry: the two callbacks whose targets live
557
+ * outside the view (layout orchestration; the session object layer).
558
+ */
559
+ export interface ChatViewInjected {
560
+ /** Selection write + details panel opening in one gesture (store action + layout orchestration). */
561
+ openDetails: (target: SelectionTarget) => void;
562
+ /**
563
+ * Open a tool-arg filesystem path with the host OS default application
564
+ * (relative paths resolve against the session cwd).
565
+ */
566
+ openFile: (path: string) => void;
567
+ loadOlder: () => void;
568
+ /** Resolve a session-authorized historical image for inline display. */
569
+ loadImage: (attachment: ImageAttachmentRef) => Promise<string>;
570
+ /** Hand a call off to the trajectory view: write the one-shot inspect target and switch tabs. */
571
+ inspectCall: (callId: CallId) => void;
572
+ /**
573
+ * Per-session scroll memory surviving view switches (in-memory, never
574
+ * persisted): the view saves on every scroll and restores on remount; a
575
+ * fresh page load starts empty and keeps the open-jump-to-bottom default.
576
+ */
577
+ chatScroll: {
578
+ /** Record a semantic reader position; null clears it when pinned. */
579
+ save: (position: ChatScrollPosition | null) => void;
580
+ /** Last reader position, or null when pinned or never recorded. */
581
+ read: () => ChatScrollPosition | null;
582
+ };
583
+ /** Fork through the completed turn ending at the eligible message `seq`, then open the child. */
584
+ forkAt: (seq: number) => void;
585
+ /**
586
+ * Prose file-mention vocabulary for one closing message, from the optional
587
+ * {@link ChatFileMentions} service (resolved lazily per call, so composing
588
+ * the provider in or out takes effect live). Undefined when the service is
589
+ * absent or the turn produced nothing worth linking.
590
+ */
591
+ fileMentions: (owner: TurnTailOwnerProps) => MarkdownFileMentions | undefined;
592
+ }
593
+ /** Full chat-view component props: runtime & its Tool/command/tail render shares & store & injected & locale seat. */
594
+ export type ChatViewSlotProps = PropsRuntime<'conversation.view'> & PropsRenderSlots<'conversation.chat.node'> & PropsStore<ChatStore> & ChatViewInjected & PropsLocale<'conversation'>;
595
+ /**
596
+ * Injected share of the details slot: the panel is otherwise a pure reader of
597
+ * the shared chat store, but its close button is a layout orchestration call.
598
+ */
599
+ export interface DetailsInjected {
600
+ /** Close the details panel (layout geometry stays with ctx.layout). */
601
+ closeDetails: () => void;
602
+ }
603
+ /** Full details-slot props: selection store, Tool output seat, injected close callback, and locale. */
604
+ export type DetailsSlotProps = PropsRuntime<'details'> & PropsRenderSlots<'conversation.details.tool'> & PropsStore<ChatStore> & DetailsInjected & PropsLocale<'conversation'>;
605
+ /** Owner share common to the hero / New-Session Workspace pickers. */
606
+ export interface EmptyWorkspaceOwnerProps {
607
+ open: boolean;
608
+ anchorRef?: RefObject<HTMLElement>;
609
+ /** Currently active workspace (renders a trailing check in the picker list). */
610
+ selectedId?: WorkspaceId | undefined;
611
+ onPick: (workspaceId: WorkspaceId) => void;
612
+ onClose: () => void;
613
+ }
614
+ //# sourceMappingURL=slots.d.ts.map
@@ -0,0 +1,39 @@
1
+ /** Shared conversation view, selection, and store-state contracts. */
2
+ /** Tool call identity as carried on the wire (branded upstream in connection). */
3
+ export type CallId = string;
4
+ /** Selection target for the details linkage channel (toolcall is the step special case). */
5
+ export interface SelectionTarget {
6
+ turnSeq: number;
7
+ stepSeq?: number;
8
+ callId?: CallId;
9
+ toolName?: string;
10
+ }
11
+ /**
12
+ * One conversation view tab, projected from a 'conversation.view' slot
13
+ * entry's registration options (label falls back to the entry id).
14
+ */
15
+ export interface ViewTab {
16
+ id: string;
17
+ label: string;
18
+ }
19
+ /**
20
+ * Per-session state shared by conversation, chat-view, and details slots.
21
+ * Unknown persisted view ids fall back to the first registered view.
22
+ */
23
+ export interface ChatStoreState {
24
+ /** Details-linkage channel (conversation writes, details reads). */
25
+ selection: SelectionTarget | null;
26
+ /** Composer draft (persisted; survives session switches and reloads). */
27
+ draft: string;
28
+ /** Active conversation view id ('conversation.view' entry id); null falls back to the first view. */
29
+ view: string | null;
30
+ /**
31
+ * One-shot inspect handoff: chat writes the call to reveal, the trajectory
32
+ * view consumes it and acknowledges by clearing. Read with `?? null` —
33
+ * persisted snapshots from before this field rehydrate without it.
34
+ */
35
+ inspect: {
36
+ callId: CallId;
37
+ } | null;
38
+ }
39
+ //# sourceMappingURL=views.d.ts.map