@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.
- package/LICENSE +28 -0
- package/README.i18n.yaml +6 -0
- package/README.md +65 -0
- package/README.zh.md +65 -0
- package/lib/client.js +9612 -0
- package/lib/index.js +28 -0
- package/lib/invariant.js +25 -0
- package/lib/types/client/apply.d.ts +16 -0
- package/lib/types/client/chat/AssistantMarkdown.d.ts +19 -0
- package/lib/types/client/chat/AssistantNodeView.d.ts +4 -0
- package/lib/types/client/chat/ChatNodeSeat.d.ts +11 -0
- package/lib/types/client/chat/ChatView.d.ts +7 -0
- package/lib/types/client/chat/CommandNodeView.d.ts +9 -0
- package/lib/types/client/chat/CompactionCommandCard.d.ts +8 -0
- package/lib/types/client/chat/CompactionItem.d.ts +19 -0
- package/lib/types/client/chat/ContextBody.d.ts +130 -0
- package/lib/types/client/chat/ContextInjectionRow.d.ts +26 -0
- package/lib/types/client/chat/GenericCommandCard.d.ts +9 -0
- package/lib/types/client/chat/MessageIconActions.d.ts +30 -0
- package/lib/types/client/chat/MessageImage.d.ts +20 -0
- package/lib/types/client/chat/MessageItem.d.ts +27 -0
- package/lib/types/client/chat/ReasoningRow.d.ts +14 -0
- package/lib/types/client/chat/StatsLine.d.ts +83 -0
- package/lib/types/client/chat/TurnTailNodeView.d.ts +7 -0
- package/lib/types/client/chat/message-chrome.d.ts +49 -0
- package/lib/types/client/chat/register-node-renderers.d.ts +7 -0
- package/lib/types/client/chat/tool-node-reader.d.ts +16 -0
- package/lib/types/client/chat/turn-assistant.d.ts +8 -0
- package/lib/types/client/chat/turn-metrics.d.ts +38 -0
- package/lib/types/client/chat/use-calendar-day.d.ts +6 -0
- package/lib/types/client/chat/use-throttled-visual-update.d.ts +8 -0
- package/lib/types/client/contract/chat-nodes.d.ts +68 -0
- package/lib/types/client/contract/composer-submission.d.ts +8 -0
- package/lib/types/client/contract/queue.d.ts +9 -0
- package/lib/types/client/contract/slots.d.ts +614 -0
- package/lib/types/client/contract/views.d.ts +39 -0
- package/lib/types/client/conversation-nodes/assistant.d.ts +35 -0
- package/lib/types/client/conversation-nodes/chat-snapshot-builder.d.ts +28 -0
- package/lib/types/client/conversation-nodes/command.d.ts +54 -0
- package/lib/types/client/conversation-nodes/common.d.ts +37 -0
- package/lib/types/client/conversation-nodes/compaction.d.ts +21 -0
- package/lib/types/client/conversation-nodes/fallback.d.ts +16 -0
- package/lib/types/client/conversation-nodes/inbox.d.ts +21 -0
- package/lib/types/client/conversation-nodes/message.d.ts +22 -0
- package/lib/types/client/conversation-nodes/register.d.ts +7 -0
- package/lib/types/client/conversation-nodes/retry.d.ts +23 -0
- package/lib/types/client/conversation-nodes/tool.d.ts +23 -0
- package/lib/types/client/conversation-nodes/turn-error.d.ts +27 -0
- package/lib/types/client/conversation-nodes/turn-tail.d.ts +28 -0
- package/lib/types/client/index.d.ts +29 -0
- package/lib/types/client/input/blocks.d.ts +57 -0
- package/lib/types/client/input/contract.d.ts +333 -0
- package/lib/types/client/input/decorations.d.ts +63 -0
- package/lib/types/client/input/facade.d.ts +219 -0
- package/lib/types/client/input/hub.d.ts +88 -0
- package/lib/types/client/input/machine.d.ts +114 -0
- package/lib/types/client/input/submission-policy.d.ts +46 -0
- package/lib/types/client/locales.d.ts +312 -0
- package/lib/types/client/queue/QueueDock.d.ts +29 -0
- package/lib/types/client/queue/store.d.ts +19 -0
- package/lib/types/client/service.d.ts +148 -0
- package/lib/types/client/settings/EnterBehaviorRow.d.ts +21 -0
- package/lib/types/client/skeleton/ApprovalPanel.d.ts +13 -0
- package/lib/types/client/skeleton/ContextMeter.d.ts +14 -0
- package/lib/types/client/skeleton/ConversationRoot.d.ts +5 -0
- package/lib/types/client/skeleton/ConversationSession.d.ts +20 -0
- package/lib/types/client/skeleton/DetailsPanel.d.ts +5 -0
- package/lib/types/client/skeleton/EmptyHero.d.ts +55 -0
- package/lib/types/client/skeleton/ImageLightbox.d.ts +9 -0
- package/lib/types/client/skeleton/InputBar.d.ts +16 -0
- package/lib/types/client/skeleton/PermissionSelect.d.ts +11 -0
- package/lib/types/client/skeleton/TodoPanel.d.ts +28 -0
- package/lib/types/client/stores.d.ts +22 -0
- package/lib/types/index.d.ts +9 -0
- package/lib/types/invariant.d.ts +16 -0
- package/lib/types/submission-settings.d.ts +20 -0
- 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
|