@deepseek-ai/dsh-client-ui-conversation 0.1.6-alpha.2 → 0.1.7-alpha.2
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.i18n.yaml +2 -2
- package/README.md +20 -6
- package/README.zh.md +20 -6
- package/lib/client.js +1374 -370
- package/lib/index.js +9 -8
- package/lib/types/client/contract/conversation.d.ts +19 -0
- package/lib/types/client/contract/groups.d.ts +116 -0
- package/lib/types/client/contract/input.d.ts +9 -0
- package/lib/types/client/contract/records.d.ts +3 -7
- package/lib/types/client/contract/slots.d.ts +51 -17
- package/lib/types/client/conversation/assembler.d.ts +16 -1
- package/lib/types/client/conversation/assembly.d.ts +3 -0
- package/lib/types/client/conversation/group-registry.d.ts +30 -0
- package/lib/types/client/conversation/group-store.d.ts +29 -0
- package/lib/types/client/conversation/location-index.d.ts +6 -0
- package/lib/types/client/index.d.ts +3 -1
- package/lib/types/client/input/editor/claim-decor.d.ts +2 -2
- package/lib/types/client/input/editor/keymap.d.ts +6 -2
- package/lib/types/client/input/editor/runtime.d.ts +13 -0
- package/lib/types/client/input/editor/view-binding.d.ts +1 -1
- package/lib/types/client/input/facade.d.ts +7 -0
- package/lib/types/client/input/submission-policy.d.ts +6 -6
- package/lib/types/client/locales.d.ts +384 -4
- package/lib/types/client/queue/QueueDock.d.ts +1 -1
- package/lib/types/client/service.d.ts +6 -0
- package/lib/types/client/skeleton/ConversationHeader.d.ts +8 -0
- package/lib/types/client/skeleton/ConversationSession.d.ts +1 -1
- package/lib/types/client/skeleton/DefaultConversationViews.d.ts +1 -1
- package/lib/types/client/skeleton/control-row-layout.d.ts +10 -0
- package/lib/types/client/view-selection.d.ts +4 -0
- package/lib/types/index.d.ts +16 -5
- package/lib/types/submission-settings.d.ts +9 -1
- package/package.json +35 -34
package/lib/index.js
CHANGED
|
@@ -10,18 +10,19 @@ const BUSY_ENTER_BEHAVIORS = ["queue", "steer"];
|
|
|
10
10
|
/** Default preserves Enter-as-Queue for running conversations. */
|
|
11
11
|
const DEFAULT_BUSY_ENTER_BEHAVIOR = "queue";
|
|
12
12
|
/** Durable conversation schema; also the wire envelope the browser scope validates against. */
|
|
13
|
-
const
|
|
13
|
+
const ConversationSettingsFields = { [BUSY_ENTER_FIELD]: z.union([...BUSY_ENTER_BEHAVIORS]).default(DEFAULT_BUSY_ENTER_BEHAVIOR) };
|
|
14
|
+
z.object(ConversationSettingsFields);
|
|
14
15
|
//#endregion
|
|
15
16
|
//#region lib/types/index.js
|
|
16
|
-
/**
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
* @param ctx
|
|
17
|
+
/** Live preferences projected to the browser. */
|
|
18
|
+
const Config = z.object({ [BUSY_ENTER_FIELD]: ConversationSettingsFields[BUSY_ENTER_FIELD].volatile() });
|
|
19
|
+
/** Host preferences are consumed through the configuration form projection.
|
|
20
|
+
* @param ctx Plugin context used for optional settings presentation.
|
|
20
21
|
*/
|
|
21
22
|
function apply(ctx) {
|
|
22
|
-
ctx.inject(["settings"], (
|
|
23
|
-
|
|
23
|
+
ctx.inject(["settings"], (child) => {
|
|
24
|
+
child.effect(() => child.settings.configure({ auto: false }, ctx.fiber));
|
|
24
25
|
});
|
|
25
26
|
}
|
|
26
27
|
//#endregion
|
|
27
|
-
export { BUSY_ENTER_BEHAVIORS, BUSY_ENTER_FIELD, CONVERSATION_SETTINGS_NAMESPACE, DEFAULT_BUSY_ENTER_BEHAVIOR, apply };
|
|
28
|
+
export { BUSY_ENTER_BEHAVIORS, BUSY_ENTER_FIELD, CONVERSATION_SETTINGS_NAMESPACE, Config, DEFAULT_BUSY_ENTER_BEHAVIOR, apply };
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import type { SessionEventLike } from '@deepseek-ai/dsh-api-session-controller/client';
|
|
2
2
|
import type { SessionEvent } from '@deepseek-ai/dsh-session/types';
|
|
3
|
+
import type { ConversationGroupData, ConversationGroupedView, ConversationGroupInput } from './groups.ts';
|
|
3
4
|
/** Definition-local identity and lifecycle role extracted from one event. */
|
|
4
5
|
export interface ConversationMatchResult {
|
|
5
6
|
readonly id: string;
|
|
@@ -119,6 +120,12 @@ export interface ConversationViewSnapshotMap {
|
|
|
119
120
|
export interface ConversationViewSnapshotStore {
|
|
120
121
|
/** @param target - registered view target. @returns its current snapshot. */
|
|
121
122
|
get<Target extends Extract<keyof ConversationViewSnapshotMap, string>>(target: Target): ConversationViewSnapshotMap[Target] | undefined;
|
|
123
|
+
/**
|
|
124
|
+
* Read grouping for an activated target without activating another target.
|
|
125
|
+
* @param target - registered View target.
|
|
126
|
+
* @returns its grouped reader, when a Group Definition is active.
|
|
127
|
+
*/
|
|
128
|
+
grouped<Target extends string>(target: Target): ConversationGroupedView<ConversationGroupData<Target>> | undefined;
|
|
122
129
|
}
|
|
123
130
|
/** Immutable public view of an assembled business Context. */
|
|
124
131
|
export interface ConversationNodeContext<State = unknown> {
|
|
@@ -222,6 +229,7 @@ export interface ConversationViewBuilder<Node extends ConversationViewNode = Con
|
|
|
222
229
|
replace(input: {
|
|
223
230
|
readonly nodes: readonly Node[];
|
|
224
231
|
readonly timeline: ConversationTimelineSnapshot;
|
|
232
|
+
readonly changedTurns?: readonly number[];
|
|
225
233
|
}): Snapshot;
|
|
226
234
|
/**
|
|
227
235
|
* Apply only Nodes whose materialized values changed in this transaction.
|
|
@@ -231,11 +239,22 @@ export interface ConversationViewBuilder<Node extends ConversationViewNode = Con
|
|
|
231
239
|
apply(input: {
|
|
232
240
|
readonly upserts: readonly Node[];
|
|
233
241
|
readonly timeline: ConversationTimelineSnapshot;
|
|
242
|
+
readonly changedTurns?: readonly number[];
|
|
234
243
|
}): Snapshot;
|
|
244
|
+
/** @returns the latest target-processed Node inputs; required only for a grouped target. */
|
|
245
|
+
groupInput?(): ConversationGroupInput<Node>;
|
|
246
|
+
/** Publish local sources after all target snapshots and grouping results have been installed. */
|
|
247
|
+
publish?(): void;
|
|
235
248
|
}
|
|
236
249
|
/** Registry contribution that creates an isolated builder when a Session first uses this target. */
|
|
237
250
|
export interface ConversationViewDefinition<Node extends ConversationViewNode = ConversationViewNode, Snapshot = unknown> {
|
|
238
251
|
readonly target: string;
|
|
252
|
+
/**
|
|
253
|
+
* Address a tool call in this target's inspector; absent for non-inspection views.
|
|
254
|
+
* @param callId - tool-call identity from the Session.
|
|
255
|
+
* @returns the target's opaque focus identity.
|
|
256
|
+
*/
|
|
257
|
+
toolCallFocus?(callId: string): string;
|
|
239
258
|
/** @returns a new Session-owned incremental builder. */
|
|
240
259
|
create(): ConversationViewBuilder<Node, Snapshot>;
|
|
241
260
|
/**
|
|
@@ -0,0 +1,116 @@
|
|
|
1
|
+
/** Definition-owned grouping over a target's already materialized Nodes. */
|
|
2
|
+
import type { Branded } from '@deepseek-ai/dsh-brand';
|
|
3
|
+
import type { ObservableSnapshot } from '@deepseek-ai/dsh-client-store';
|
|
4
|
+
import type { ConversationTimelineSnapshot, ConversationViewNode } from './conversation.ts';
|
|
5
|
+
/** Existing Node identity, without allocating another execution Node. */
|
|
6
|
+
export type NodeKey = Branded<'ConversationNodeKey'>;
|
|
7
|
+
/** Definition-local group identity within one Session and target. */
|
|
8
|
+
export type GroupKey = Branded<'ConversationGroupKey'>;
|
|
9
|
+
/** One whole Node or a renderer-owned part of that Node. */
|
|
10
|
+
export interface NodeReference {
|
|
11
|
+
readonly kind: 'node';
|
|
12
|
+
readonly key: NodeKey;
|
|
13
|
+
readonly groupPart?: string;
|
|
14
|
+
}
|
|
15
|
+
/** Root-list reference to a separately observed group. */
|
|
16
|
+
export interface GroupReference {
|
|
17
|
+
readonly kind: 'group';
|
|
18
|
+
readonly key: GroupKey;
|
|
19
|
+
}
|
|
20
|
+
/** The two supported root rendering positions. */
|
|
21
|
+
export type RenderEntry = NodeReference | GroupReference;
|
|
22
|
+
/** Immutable group data and its ordered, non-nested Node references. */
|
|
23
|
+
export interface GroupSnapshot<Data> {
|
|
24
|
+
readonly key: GroupKey;
|
|
25
|
+
readonly data: Data;
|
|
26
|
+
readonly members: readonly NodeReference[];
|
|
27
|
+
}
|
|
28
|
+
/**
|
|
29
|
+
* One atomic grouping update. Replacement input requires entries and a complete
|
|
30
|
+
* group replacement; apply input may omit entries to preserve the root list.
|
|
31
|
+
* Group removal never deletes source Nodes.
|
|
32
|
+
*/
|
|
33
|
+
export interface GroupUpdate<Data> {
|
|
34
|
+
/** Complete root sequence; only its Node references and referenced group members render. */
|
|
35
|
+
readonly entries?: readonly RenderEntry[];
|
|
36
|
+
readonly groups: {
|
|
37
|
+
readonly kind: 'replace';
|
|
38
|
+
readonly snapshots: readonly GroupSnapshot<Data>[];
|
|
39
|
+
} | {
|
|
40
|
+
readonly kind: 'apply';
|
|
41
|
+
readonly upserts: readonly GroupSnapshot<Data>[];
|
|
42
|
+
readonly removes: readonly GroupKey[];
|
|
43
|
+
};
|
|
44
|
+
}
|
|
45
|
+
/** Target-processed Node values before and after one update. */
|
|
46
|
+
export interface NodeChange<Node> {
|
|
47
|
+
readonly previous: Node | undefined;
|
|
48
|
+
readonly current: Node;
|
|
49
|
+
}
|
|
50
|
+
/** Owning Turn and immediate neighbours in the target's visible Node order. */
|
|
51
|
+
export interface GroupNodePosition {
|
|
52
|
+
readonly turn: number | undefined;
|
|
53
|
+
readonly previous: NodeKey | undefined;
|
|
54
|
+
readonly next: NodeKey | undefined;
|
|
55
|
+
}
|
|
56
|
+
interface GroupInputNodes<Node> {
|
|
57
|
+
readonly order: readonly NodeKey[];
|
|
58
|
+
/** @param key - target Node identity. @returns its current value during this synchronous update. */
|
|
59
|
+
readonly readNode: (key: NodeKey) => Node | undefined;
|
|
60
|
+
/** @param turn - owning Turn. @returns its visible keys in target order; empty when absent. */
|
|
61
|
+
readonly readTurn: (turn: number) => readonly NodeKey[];
|
|
62
|
+
/** @param key - target Node identity. @returns its visible position, or absence outside the target order. */
|
|
63
|
+
readonly readPosition: (key: NodeKey) => GroupNodePosition | undefined;
|
|
64
|
+
readonly timeline: ConversationTimelineSnapshot;
|
|
65
|
+
}
|
|
66
|
+
/** Target-local inputs; apply includes lifecycle changes without Node upserts. */
|
|
67
|
+
export type ConversationGroupInput<Node> = GroupInputNodes<Node> & ({
|
|
68
|
+
readonly kind: 'replace';
|
|
69
|
+
} | {
|
|
70
|
+
readonly kind: 'apply';
|
|
71
|
+
readonly changes: readonly NodeChange<Node>[];
|
|
72
|
+
readonly changedTurns: readonly number[];
|
|
73
|
+
/** Turns whose visible keys or immediate neighbours changed, including removal and cross-Turn moves. */
|
|
74
|
+
readonly changedTurnOrders: readonly number[];
|
|
75
|
+
});
|
|
76
|
+
/** Framework-owned State for one Session's registered Group Definition. */
|
|
77
|
+
export interface ConversationGroupContext<State> {
|
|
78
|
+
readonly state: State;
|
|
79
|
+
}
|
|
80
|
+
/** Business grouping rules, driven after the target Builder has installed Nodes. */
|
|
81
|
+
export interface ConversationGroupDefinition<Node extends ConversationViewNode = ConversationViewNode, State = unknown, Data = unknown> {
|
|
82
|
+
readonly kind: string;
|
|
83
|
+
readonly target: string;
|
|
84
|
+
/** @returns initial Session-local grouping State. */
|
|
85
|
+
create(): State;
|
|
86
|
+
/**
|
|
87
|
+
* Consume target Node changes, not raw Session events or presentation modes.
|
|
88
|
+
* @param context - current Session-local State.
|
|
89
|
+
* @param input - current target inputs; its readers are valid only during this call.
|
|
90
|
+
* @returns State adopted by the framework.
|
|
91
|
+
*/
|
|
92
|
+
update(context: ConversationGroupContext<State>, input: ConversationGroupInput<Node>): State;
|
|
93
|
+
/**
|
|
94
|
+
* Materialize pending grouping changes without changing the business State.
|
|
95
|
+
* @param context - State adopted after update.
|
|
96
|
+
* @returns complete output for replace input; an update or null when unchanged for apply input.
|
|
97
|
+
*/
|
|
98
|
+
buildGroups(context: ConversationGroupContext<State>): GroupUpdate<Data> | null;
|
|
99
|
+
}
|
|
100
|
+
/** Merge-extensible group data associated with each registered target. */
|
|
101
|
+
export interface ConversationGroupDataMap {
|
|
102
|
+
}
|
|
103
|
+
/** Group data declared by a target; undeclared targets have no group payload. */
|
|
104
|
+
export type ConversationGroupData<Target extends string> = Target extends keyof ConversationGroupDataMap ? ConversationGroupDataMap[Target] : never;
|
|
105
|
+
/** Stable grouped reader; data-only updates preserve entries and member arrays. */
|
|
106
|
+
export interface ConversationGroupedView<Data> {
|
|
107
|
+
readonly entries: readonly RenderEntry[];
|
|
108
|
+
/**
|
|
109
|
+
* Observe a group without subscribing to the root sequence.
|
|
110
|
+
* @param key - group identity within this target.
|
|
111
|
+
* @returns an identity-stable source, whose value is absent after removal.
|
|
112
|
+
*/
|
|
113
|
+
groupSource(key: GroupKey): ObservableSnapshot<GroupSnapshot<Data> | undefined>;
|
|
114
|
+
}
|
|
115
|
+
export {};
|
|
116
|
+
//# sourceMappingURL=groups.d.ts.map
|
|
@@ -204,6 +204,15 @@ export interface SessionInputResolver {
|
|
|
204
204
|
* paste/…) stay InputBar-private and never ride this face.
|
|
205
205
|
*/
|
|
206
206
|
export interface InputActions {
|
|
207
|
+
/** @returns a revision-guarded copy of the current editor selection. */
|
|
208
|
+
captureInsertion(): TokenSpan;
|
|
209
|
+
/**
|
|
210
|
+
* Insert asynchronous text without replacing subsequent edits or reference chips.
|
|
211
|
+
* @param text - plain text to insert in one undo step.
|
|
212
|
+
* @param span - captured selection and draft revision.
|
|
213
|
+
* @returns false when the draft changed or submission locked the editor.
|
|
214
|
+
*/
|
|
215
|
+
insertText(text: string, span: TokenSpan): boolean;
|
|
207
216
|
/** Replace the whole draft (persisted-draft seed and programmatic writes). */
|
|
208
217
|
setDraft(text: string): void;
|
|
209
218
|
/** Append ordered browser-owned attachment ids; busy admission phases refuse. */
|
|
@@ -198,13 +198,9 @@ export interface CompactionSummaryNode {
|
|
|
198
198
|
shadowedTokenCount: number | null;
|
|
199
199
|
}
|
|
200
200
|
/**
|
|
201
|
-
* Fallback for surface events
|
|
202
|
-
*
|
|
203
|
-
*
|
|
204
|
-
* because `isAppendSurfaceEvent` admits only the four types in core's
|
|
205
|
-
* `SurfaceEventType`, and each has its own arm (`system/message` is claimed by
|
|
206
|
-
* a Chat Definition that renders no transcript row) — and it exists so widening
|
|
207
|
-
* that set core-side degrades to a raw row instead of dropping the event silently.
|
|
201
|
+
* Fallback for unclaimed append-surface events. The merge-extensible
|
|
202
|
+
* SessionEventMap permits unfamiliar events to retain a raw presentation.
|
|
203
|
+
* Known unsupported developer events throw before fallback selection.
|
|
208
204
|
*/
|
|
209
205
|
export interface UnknownSurfaceNode {
|
|
210
206
|
kind: 'unknown';
|
|
@@ -56,8 +56,12 @@ export interface ComposerAttachmentsOwnerProps {
|
|
|
56
56
|
attachments: readonly ComposerAttachment[];
|
|
57
57
|
/** Whether a document-level file drop may add attachments now. */
|
|
58
58
|
canAcceptDrop: boolean;
|
|
59
|
-
/**
|
|
60
|
-
|
|
59
|
+
/**
|
|
60
|
+
* Add one dropped batch through the composer's validation path.
|
|
61
|
+
* @param files - dropped, pasted, or picked browser files in source order.
|
|
62
|
+
* @param directories - members of `files` the drop source identified as directories.
|
|
63
|
+
*/
|
|
64
|
+
onAddFiles: (files: readonly File[], directories?: ReadonlySet<File>) => void;
|
|
61
65
|
/** Remove one draft attachment through the Conversation service. */
|
|
62
66
|
onRemoveAttachment: (id: DraftAttachmentId) => void;
|
|
63
67
|
/** Current per-draft upload states for file-kind attachments. */
|
|
@@ -127,10 +131,19 @@ declare module '@deepseek-ai/dsh-client-ui-slots' {
|
|
|
127
131
|
view?: string;
|
|
128
132
|
};
|
|
129
133
|
};
|
|
134
|
+
/** Resident navigation container, including when no Session is selected. */
|
|
135
|
+
'conversation.header': {
|
|
136
|
+
kind: 'single';
|
|
137
|
+
scope: 'session-maybe';
|
|
138
|
+
};
|
|
130
139
|
/** Strict per-Session title, actions, and View navigation. */
|
|
131
140
|
'conversation.session.header': {
|
|
132
141
|
kind: 'single';
|
|
133
142
|
scope: 'session';
|
|
143
|
+
owner: {
|
|
144
|
+
/** Parent-owned visibility shared with the header container styling. */
|
|
145
|
+
hideChrome: boolean;
|
|
146
|
+
};
|
|
134
147
|
};
|
|
135
148
|
/** Optional replacement for one Session breadcrumb title. */
|
|
136
149
|
'conversation.session.header.lineage': {
|
|
@@ -150,16 +163,10 @@ declare module '@deepseek-ai/dsh-client-ui-slots' {
|
|
|
150
163
|
scope: 'session';
|
|
151
164
|
owner: ConversationHeaderActionOwnerProps;
|
|
152
165
|
};
|
|
153
|
-
/**
|
|
154
|
-
|
|
155
|
-
* controls (macOS desktop sidebar reopen and New Session while the sidebar
|
|
156
|
-
* is hidden). The seat is laid out only while its occupant renders
|
|
157
|
-
* something, and it stays mounted through the blank-session state so a
|
|
158
|
-
* hidden sidebar always keeps a reopen control on screen.
|
|
159
|
-
*/
|
|
160
|
-
'conversation.session.header.leading': {
|
|
166
|
+
/** Global navigation before the Session title, available without a Session. */
|
|
167
|
+
'conversation.header.leading': {
|
|
161
168
|
kind: 'single';
|
|
162
|
-
scope: '
|
|
169
|
+
scope: 'root';
|
|
163
170
|
owner: ConversationHeaderLeadingOwnerProps;
|
|
164
171
|
};
|
|
165
172
|
/**
|
|
@@ -229,6 +236,12 @@ declare module '@deepseek-ai/dsh-client-ui-slots' {
|
|
|
229
236
|
kind: 'list';
|
|
230
237
|
scope: 'session';
|
|
231
238
|
};
|
|
239
|
+
/** Compact action after the model selector; it can expand across the toolbar while retaining the editor and submit action. */
|
|
240
|
+
'conversation.input.activity': {
|
|
241
|
+
kind: 'single';
|
|
242
|
+
scope: 'session';
|
|
243
|
+
owner: InputActivityOwnerProps;
|
|
244
|
+
};
|
|
232
245
|
/** Resident composer body, including the no-Session inert state. */
|
|
233
246
|
'conversation.composer.bar': {
|
|
234
247
|
kind: 'single';
|
|
@@ -253,7 +266,11 @@ declare module '@deepseek-ai/dsh-client-ui-slots' {
|
|
|
253
266
|
scope: 'session';
|
|
254
267
|
owner: InputControlOwnerProps;
|
|
255
268
|
};
|
|
256
|
-
/**
|
|
269
|
+
/**
|
|
270
|
+
* Model selector inside the composer tool row. When expanded controls cannot
|
|
271
|
+
* share a line, the row sets --dsh-composer-model-text-display to none and
|
|
272
|
+
* --dsh-composer-model-icon-display to block for an occupant's compact display.
|
|
273
|
+
*/
|
|
257
274
|
'conversation.input.model': {
|
|
258
275
|
kind: 'single';
|
|
259
276
|
scope: 'session';
|
|
@@ -344,7 +361,7 @@ export interface ConversationHeaderCornerOwnerProps {
|
|
|
344
361
|
/** Marker field: the occupant receives no owner-specific values. */
|
|
345
362
|
children?: never;
|
|
346
363
|
}
|
|
347
|
-
/** The leading seat
|
|
364
|
+
/** The leading seat exposes global navigation independently of a Session. */
|
|
348
365
|
export interface ConversationHeaderLeadingOwnerProps {
|
|
349
366
|
/** Marker field: the occupant receives no owner-specific values. */
|
|
350
367
|
children?: never;
|
|
@@ -365,6 +382,8 @@ export interface InputZone {
|
|
|
365
382
|
}
|
|
366
383
|
/** Conversation View entries obtain their data from registered standard hooks. */
|
|
367
384
|
export interface ConvViewOwnerProps {
|
|
385
|
+
/** Open a tool call's inspector when an inspection target is available. */
|
|
386
|
+
inspectCall: ((callId: string) => void) | undefined;
|
|
368
387
|
/** Focus request addressed to the selected View. */
|
|
369
388
|
viewRequest: import('./views.ts').ConversationViewRequest | null;
|
|
370
389
|
/** Select a View and address one opaque focus identity to it. */
|
|
@@ -388,6 +407,7 @@ export interface ConversationSessionInjected {
|
|
|
388
407
|
/** Package-owned View roster source bound only for the Conversation body. */
|
|
389
408
|
readonly hooks: {
|
|
390
409
|
readonly conversationViews: ObservableSnapshot<readonly ViewTab[]>;
|
|
410
|
+
readonly inspectCall: ObservableSnapshot<ConvViewOwnerProps['inspectCall']>;
|
|
391
411
|
};
|
|
392
412
|
/** Bind input draft persistence to the Session-owned store instance. */
|
|
393
413
|
bindDraftMirror: (write: (text: string) => void) => () => void;
|
|
@@ -426,7 +446,14 @@ export interface ComposerBarOwnerProps {
|
|
|
426
446
|
/** Package-private operations injected into the resident composer bar. */
|
|
427
447
|
export interface ComposerBarInjected {
|
|
428
448
|
keyboard: ComposerKeyboard | undefined;
|
|
429
|
-
|
|
449
|
+
/**
|
|
450
|
+
* Register one picked batch; resolves to the rejection copy or null. Where
|
|
451
|
+
* the browser shell reports host paths (the Desktop application), files
|
|
452
|
+
* and folders with a real path become `@path` references in the draft
|
|
453
|
+
* instead of uploads; `directories` names the members the drop source
|
|
454
|
+
* identified as directories.
|
|
455
|
+
*/
|
|
456
|
+
addFiles: ((files: readonly File[], directories?: ReadonlySet<File>) => string | null) | undefined;
|
|
430
457
|
removeAttachment: ((id: DraftAttachmentId) => void) | undefined;
|
|
431
458
|
resolveDraftAttachments: ((ids: readonly DraftAttachmentId[]) => readonly ComposerAttachment[]) | undefined;
|
|
432
459
|
/** Restart one failed file upload; absent without a session. */
|
|
@@ -451,8 +478,13 @@ export interface InputControlOwnerProps {
|
|
|
451
478
|
/** Whether the composer currently refuses interaction. */
|
|
452
479
|
locked: boolean;
|
|
453
480
|
}
|
|
481
|
+
/** A toolbar activity hides ordinary accessory controls while expanded; its occupant must release expansion on unmount. */
|
|
482
|
+
export interface InputActivityOwnerProps extends InputControlOwnerProps {
|
|
483
|
+
/** @param active - whether the occupant needs the toolbar width before the submit action. */
|
|
484
|
+
onActiveChange: (active: boolean) => void;
|
|
485
|
+
}
|
|
454
486
|
/** Full props of the resident composer bar. */
|
|
455
|
-
export type ComposerBarProps = PropsRuntime<'conversation.composer.bar'> & PropsRenderSlots<'conversation.input.attachments' | 'conversation.input.overlay' | 'conversation.input.permission' | 'conversation.input.left' | 'conversation.input.plan' | 'conversation.input.right' | 'conversation.input.model' | 'conversation.composer.dock'> & InjectFace<ComposerBarInjected> & PropsLocale<'conversation'>;
|
|
487
|
+
export type ComposerBarProps = PropsRuntime<'conversation.composer.bar'> & PropsRenderSlots<'conversation.input.attachments' | 'conversation.input.overlay' | 'conversation.input.permission' | 'conversation.input.left' | 'conversation.input.plan' | 'conversation.input.right' | 'conversation.input.model' | 'conversation.input.activity' | 'conversation.composer.dock'> & InjectFace<ComposerBarInjected> & PropsLocale<'conversation'>;
|
|
456
488
|
/** Owner values used to elect a composer takeover. */
|
|
457
489
|
export interface ComposerChainProps {
|
|
458
490
|
/** Current Session identity used by temporary business-owned entries. */
|
|
@@ -470,7 +502,7 @@ export interface HeroBrandMarkOwnerProps {
|
|
|
470
502
|
className?: string | undefined;
|
|
471
503
|
}
|
|
472
504
|
/** Full props of the resident optional-Session Conversation shell. */
|
|
473
|
-
export type ConversationSlotProps = PropsRuntime<'main.conversation'> & PropsRenderSlots<'conversation.
|
|
505
|
+
export type ConversationSlotProps = PropsRuntime<'main.conversation'> & PropsRenderSlots<'conversation.header'> & PropsRenderFactories;
|
|
474
506
|
/** Inputs shared by main and embedded Conversation content occurrences. */
|
|
475
507
|
export interface ConversationContentInputProps {
|
|
476
508
|
variant: 'main' | 'embedded';
|
|
@@ -494,8 +526,10 @@ export type ConversationViewsProps = FactoryLocalComponentPropsOf<'conversation.
|
|
|
494
526
|
export type ConversationWidthControlsProps = FactoryLocalComponentPropsOf<'conversation.content', 'widthControls'>;
|
|
495
527
|
/** Full props of the strict Session body. */
|
|
496
528
|
export type ConversationSessionSlotProps = PropsRuntime<'conversation.session'> & PropsRenderSlots<'conversation.view'> & PropsStore<ConversationStore> & InjectFace<ConversationSessionInjected>;
|
|
529
|
+
/** Full props of the resident navigation header. */
|
|
530
|
+
export type ConversationHeaderProps = PropsRuntime<'conversation.header'> & PropsRenderSlots<'conversation.header.leading' | 'conversation.session.header'>;
|
|
497
531
|
/** Full props of the strict Session header. */
|
|
498
|
-
export type ConversationSessionHeaderSlotProps = PropsRuntime<'conversation.session.header'> & PropsRenderSlots<'conversation.session.header.lineage' | 'conversation.session.header.
|
|
532
|
+
export type ConversationSessionHeaderSlotProps = PropsRuntime<'conversation.session.header'> & PropsRenderSlots<'conversation.session.header.lineage' | 'conversation.session.header.actions' | 'conversation.session.header.utilities' | 'conversation.session.header.corner'> & PropsStore<ConversationStore> & InjectFace<ConversationSessionHeaderInjected> & PropsLocale<'conversation'>;
|
|
499
533
|
/** Full props of the draft-attachment renderer. */
|
|
500
534
|
export type ComposerAttachmentsProps = PropsRuntime<'conversation.input.attachments'> & PropsLocale<'conversation'>;
|
|
501
535
|
/** Owner share common to blank-session Workspace pickers. */
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import type { SessionAssistantSettlementEntry, SessionEventLikeEntry } from '@deepseek-ai/dsh-api-session-controller/client';
|
|
2
2
|
import type { LlmAttemptId } from '@deepseek-ai/dsh-llm/brand';
|
|
3
3
|
import type { ConversationNodeDefinition, ConversationPublication, ConversationViewDefinition, ConversationViewSnapshotMap, ConversationViewSnapshotStore } from '../contract/conversation.ts';
|
|
4
|
+
import type { ConversationGroupData, ConversationGroupDefinition, ConversationGroupedView } from '../contract/groups.ts';
|
|
4
5
|
/** Event Registry subset consumed by a Session-owned Assembler. */
|
|
5
6
|
export interface ConversationEventDefinitions {
|
|
6
7
|
/** @returns ordinary Definitions in registration order. */
|
|
@@ -13,6 +14,13 @@ export interface ConversationViewDefinitions {
|
|
|
13
14
|
/** @returns view builder factories in registration order. */
|
|
14
15
|
entries(): readonly ConversationViewDefinition[];
|
|
15
16
|
}
|
|
17
|
+
/** Registered grouping rules consumed by the target-neutral assembler. */
|
|
18
|
+
export interface ConversationGroupDefinitions {
|
|
19
|
+
/** @returns grouping Definitions in registration order. */
|
|
20
|
+
entries(): readonly ConversationGroupDefinition[];
|
|
21
|
+
/** @param target - View target. @returns its optional Group Definition. */
|
|
22
|
+
forTarget(target: string): ConversationGroupDefinition | undefined;
|
|
23
|
+
}
|
|
16
24
|
/**
|
|
17
25
|
* Session-owned incremental engine that assembles business Contexts from a
|
|
18
26
|
* contiguous Event window and materializes registered view snapshots.
|
|
@@ -20,6 +28,7 @@ export interface ConversationViewDefinitions {
|
|
|
20
28
|
export declare class ConversationNodeAssembler implements ConversationViewSnapshotStore {
|
|
21
29
|
private readonly eventDefinitions;
|
|
22
30
|
private readonly viewDefinitions;
|
|
31
|
+
private readonly groupDefinitions;
|
|
23
32
|
private readonly contexts;
|
|
24
33
|
private readonly contextsByKind;
|
|
25
34
|
private readonly contextsBySeq;
|
|
@@ -31,6 +40,8 @@ export declare class ConversationNodeAssembler implements ConversationViewSnapsh
|
|
|
31
40
|
private readonly revised;
|
|
32
41
|
private readonly dependents;
|
|
33
42
|
private readonly views;
|
|
43
|
+
private readonly groups;
|
|
44
|
+
private readonly pendingGroupStores;
|
|
34
45
|
private readonly activeTargets;
|
|
35
46
|
private hasMore;
|
|
36
47
|
private replacePending;
|
|
@@ -38,8 +49,9 @@ export declare class ConversationNodeAssembler implements ConversationViewSnapsh
|
|
|
38
49
|
/**
|
|
39
50
|
* @param eventDefinitions - live Event Definition registry.
|
|
40
51
|
* @param viewDefinitions - live view builder registry.
|
|
52
|
+
* @param groupDefinitions - optional registered grouping rules, independent of presentation modes.
|
|
41
53
|
*/
|
|
42
|
-
constructor(eventDefinitions: ConversationEventDefinitions, viewDefinitions: ConversationViewDefinitions);
|
|
54
|
+
constructor(eventDefinitions: ConversationEventDefinitions, viewDefinitions: ConversationViewDefinitions, groupDefinitions?: ConversationGroupDefinitions);
|
|
43
55
|
/**
|
|
44
56
|
* Replace the complete loaded window after open, resync, or gap repair.
|
|
45
57
|
* @param entries - complete contiguous window.
|
|
@@ -91,6 +103,7 @@ export declare class ConversationNodeAssembler implements ConversationViewSnapsh
|
|
|
91
103
|
*/
|
|
92
104
|
snapshot(target: string): unknown;
|
|
93
105
|
get<Target extends Extract<keyof ConversationViewSnapshotMap, string>>(target: Target): ConversationViewSnapshotMap[Target] | undefined;
|
|
106
|
+
grouped<Target extends string>(target: Target): ConversationGroupedView<ConversationGroupData<Target>> | undefined;
|
|
94
107
|
/**
|
|
95
108
|
* Read targets whose owners classify their latest snapshot as visible activity.
|
|
96
109
|
* @returns target ids contributing visible activity.
|
|
@@ -118,6 +131,8 @@ export declare class ConversationNodeAssembler implements ConversationViewSnapsh
|
|
|
118
131
|
private refreshMatchLocations;
|
|
119
132
|
private buildNode;
|
|
120
133
|
private replaceView;
|
|
134
|
+
private updateView;
|
|
135
|
+
private publishViews;
|
|
121
136
|
private buildTargetNodes;
|
|
122
137
|
private buildTargetUpserts;
|
|
123
138
|
private buildLocationData;
|
|
@@ -10,6 +10,7 @@ import type { ConversationPromptSnapshot, RequestPromptInspection, SystemPromptN
|
|
|
10
10
|
import { type SystemPromptState } from '../contract/system-prompt.ts';
|
|
11
11
|
import { ConversationEventRegistry } from './event-registry.ts';
|
|
12
12
|
import { ConversationViewRegistry } from './view-registry.ts';
|
|
13
|
+
import { ConversationGroupRegistry } from './group-registry.ts';
|
|
13
14
|
/** Observable faces published for one Session's Conversation assembly. */
|
|
14
15
|
export interface ConversationBinding {
|
|
15
16
|
readonly snapshot: ObservableSnapshot<ConversationSnapshot>;
|
|
@@ -34,6 +35,8 @@ export declare class UiConversation extends Service {
|
|
|
34
35
|
readonly events: ConversationEventRegistry;
|
|
35
36
|
/** Registry of target View definitions. */
|
|
36
37
|
readonly views: ConversationViewRegistry;
|
|
38
|
+
/** Business grouping rules over already materialized target Nodes. */
|
|
39
|
+
readonly groups: ConversationGroupRegistry;
|
|
37
40
|
private readonly bindings;
|
|
38
41
|
private readonly images;
|
|
39
42
|
/**
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
/** Target-indexed business grouping registrations with the existing effect lifecycle. */
|
|
2
|
+
import type { Context } from '@deepseek-ai/cordis';
|
|
3
|
+
import type { ConversationViewNode } from '../contract/conversation.ts';
|
|
4
|
+
import type { ConversationGroupData, ConversationGroupDefinition } from '../contract/groups.ts';
|
|
5
|
+
import { ConversationDefinitionRegistry } from './definition-registry.ts';
|
|
6
|
+
import type { ConversationViewRegistry } from './view-registry.ts';
|
|
7
|
+
/** One Group Definition per target; registration never instantiates its Builder. */
|
|
8
|
+
export declare class ConversationGroupRegistry extends ConversationDefinitionRegistry<ConversationGroupDefinition> {
|
|
9
|
+
private readonly views;
|
|
10
|
+
/**
|
|
11
|
+
* @param ctx - owning plugin context.
|
|
12
|
+
* @param views - registered target Builder definitions.
|
|
13
|
+
*/
|
|
14
|
+
constructor(ctx: Context, views: ConversationViewRegistry);
|
|
15
|
+
/**
|
|
16
|
+
* Register grouping rules for an existing target.
|
|
17
|
+
* @param definition - business State and grouping output for the declared target data.
|
|
18
|
+
* @returns the effect-owned, idempotent registration disposer.
|
|
19
|
+
*/
|
|
20
|
+
register<Node extends ConversationViewNode, State, Target extends string>(definition: ConversationGroupDefinition<Node, State, ConversationGroupData<Target>> & {
|
|
21
|
+
readonly target: Target;
|
|
22
|
+
}): () => void;
|
|
23
|
+
/**
|
|
24
|
+
* Find the grouping rules registered for one target.
|
|
25
|
+
* @param target - View target.
|
|
26
|
+
* @returns its grouping Definition, when registered.
|
|
27
|
+
*/
|
|
28
|
+
forTarget(target: string): ConversationGroupDefinition | undefined;
|
|
29
|
+
}
|
|
30
|
+
//# sourceMappingURL=group-registry.d.ts.map
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
/** Keyed group publication and incremental validation of rendering positions. */
|
|
2
|
+
import { type ObservableSnapshot } from '@deepseek-ai/dsh-client-store';
|
|
3
|
+
import type { ConversationViewNode } from '../contract/conversation.ts';
|
|
4
|
+
import type { ConversationGroupedView, GroupKey, GroupSnapshot, GroupUpdate, NodeKey, RenderEntry } from '../contract/groups.ts';
|
|
5
|
+
/** Validates a complete batch before installing its group and root-list changes. */
|
|
6
|
+
export declare class ConversationGroupStore<Data> implements ConversationGroupedView<Data> {
|
|
7
|
+
private root;
|
|
8
|
+
private rootGroups;
|
|
9
|
+
private readonly groups;
|
|
10
|
+
private readonly placements;
|
|
11
|
+
private readonly sources;
|
|
12
|
+
private readonly dirty;
|
|
13
|
+
/** @returns the identity-stable ordered root references. */
|
|
14
|
+
get entries(): readonly RenderEntry[];
|
|
15
|
+
groupSource(key: GroupKey): ObservableSnapshot<GroupSnapshot<Data> | undefined>;
|
|
16
|
+
/**
|
|
17
|
+
* Install one validated update without notifying readers.
|
|
18
|
+
* @param update - root replacement and complete or incremental group records.
|
|
19
|
+
* @param readNode - synchronous reader of the current target Nodes.
|
|
20
|
+
*/
|
|
21
|
+
prepareAndInstall(update: GroupUpdate<Data>, readNode: (key: NodeKey) => ConversationViewNode | undefined): void;
|
|
22
|
+
/** Publish changed group sources after all related target data has been installed. */
|
|
23
|
+
publish(): void;
|
|
24
|
+
/** Remove grouping without deleting its source Nodes; publication remains deferred. */
|
|
25
|
+
clear(): void;
|
|
26
|
+
private collectRootGroups;
|
|
27
|
+
private collectChanges;
|
|
28
|
+
}
|
|
29
|
+
//# sourceMappingURL=group-store.d.ts.map
|
|
@@ -16,6 +16,7 @@ export declare class ConversationLocationIndex {
|
|
|
16
16
|
private readonly turnDataStores;
|
|
17
17
|
private readonly stepDataStores;
|
|
18
18
|
private readonly dirtyDataStores;
|
|
19
|
+
private readonly changedTurns;
|
|
19
20
|
private currentTurn;
|
|
20
21
|
private currentStep;
|
|
21
22
|
/**
|
|
@@ -23,6 +24,11 @@ export declare class ConversationLocationIndex {
|
|
|
23
24
|
* @returns current timeline snapshot.
|
|
24
25
|
*/
|
|
25
26
|
snapshot(): ConversationTimelineSnapshot;
|
|
27
|
+
/**
|
|
28
|
+
* Drain the Turn changes accumulated for one assembly flush.
|
|
29
|
+
* @returns Turn identities changed since the preceding drain.
|
|
30
|
+
*/
|
|
31
|
+
takeChangedTurns(): readonly number[];
|
|
26
32
|
/**
|
|
27
33
|
* Replace all Definition-owned Location values while preserving reader identities.
|
|
28
34
|
* @param entries - complete current set of Definition-owned Location values.
|
|
@@ -3,6 +3,8 @@ export { apply, Config, inject } from './apply.ts';
|
|
|
3
3
|
export type { Config as ConversationConfig } from './apply.ts';
|
|
4
4
|
export { UiConversation } from './conversation/assembly.ts';
|
|
5
5
|
export type { ConversationBinding } from './conversation/assembly.ts';
|
|
6
|
+
export type { ConversationGroupRegistry } from './conversation/group-registry.ts';
|
|
7
|
+
export type { ConversationGroupContext, ConversationGroupData, ConversationGroupDataMap, ConversationGroupDefinition, ConversationGroupedView, ConversationGroupInput, GroupKey, GroupNodePosition, GroupReference, GroupSnapshot, GroupUpdate, NodeChange, NodeKey, NodeReference, RenderEntry, } from './contract/groups.ts';
|
|
6
8
|
export { ConversationController, UnsupportedImageMediaTypeError } from './service.ts';
|
|
7
9
|
export type { IConversation } from './service.ts';
|
|
8
10
|
export type { ConversationContextReader, ConversationLocation, ConversationLocationData, ConversationLocationDataScope, ConversationLocationDataSource, ConversationLocationDataStore, ConversationMatch, ConversationMatchResult, ConversationNodeContext, ConversationNodeDefinition, ConversationPreviousContext, ConversationPublication, ConversationStartMatch, ConversationStepDataMap, ConversationTimelineSnapshot, ConversationTurnDataMap, ConversationViewBuilder, ConversationViewDefinition, ConversationViewNode, ConversationViewSnapshotMap, ConversationViewSnapshotStore, StepLocation, TurnLocation, } from './contract/conversation.ts';
|
|
@@ -15,7 +17,7 @@ export { inspectRequestPrompt } from './contract/request-inspection.ts';
|
|
|
15
17
|
export type { SystemPromptState, SystemPromptInspector } from './contract/system-prompt.ts';
|
|
16
18
|
export type { ConversationStoreState, ConversationViewRequest, ViewTab } from './contract/views.ts';
|
|
17
19
|
export { ConversationNodeAssembler } from './conversation/assembler.ts';
|
|
18
|
-
export type { ConversationEventDefinitions, ConversationViewDefinitions, } from './conversation/assembler.ts';
|
|
20
|
+
export type { ConversationEventDefinitions, ConversationGroupDefinitions, ConversationViewDefinitions, } from './conversation/assembler.ts';
|
|
19
21
|
export { ConversationDefinitionRegistry } from './conversation/definition-registry.ts';
|
|
20
22
|
export { ConversationEventRegistry } from './conversation/event-registry.ts';
|
|
21
23
|
export { ConversationLocationIndex } from './conversation/location-index.ts';
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* Claim-token highlight: while a command claim holds, the draft's leading
|
|
3
|
-
* token renders in the
|
|
4
|
-
* its own styled node (splitting when typing merges text into it), and the
|
|
3
|
+
* token renders in the business accent. A TextNode transform keeps the token
|
|
4
|
+
* in its own styled node (splitting when typing merges text into it), and the
|
|
5
5
|
* shell nudges the first leaf dirty when the claim flips so entering and
|
|
6
6
|
* leaving claimed restyles without a text edit.
|
|
7
7
|
*/
|
|
@@ -28,8 +28,12 @@ export interface ComposerKeymapHandlers {
|
|
|
28
28
|
canSubmit(): boolean;
|
|
29
29
|
/** The Enter gesture after every guard passed; `accelerated` = Ctrl/Cmd held. */
|
|
30
30
|
submit(accelerated: boolean): void;
|
|
31
|
-
/**
|
|
32
|
-
|
|
31
|
+
/**
|
|
32
|
+
* Pasted files with directory metadata supplied by the clipboard entry API.
|
|
33
|
+
* @param files - browser files in clipboard order.
|
|
34
|
+
* @param directories - known directory members; absent when no entry identifies a directory.
|
|
35
|
+
*/
|
|
36
|
+
intakeFiles(files: readonly File[], directories?: ReadonlySet<File>): void;
|
|
33
37
|
/** Pasted plain text (sanitized insertion through the shell). */
|
|
34
38
|
pasteText(text: string): void;
|
|
35
39
|
}
|
|
@@ -88,6 +88,13 @@ export declare class DraftEditorRuntime {
|
|
|
88
88
|
* @returns whether the range mapped and the edit applied.
|
|
89
89
|
*/
|
|
90
90
|
replaceText(span: DetectSpan, text: string): boolean;
|
|
91
|
+
/**
|
|
92
|
+
* Insert an asynchronous text result as one independent undo operation.
|
|
93
|
+
* @param span - owner-validated insertion range.
|
|
94
|
+
* @param text - text sanitized with the same rules as paste.
|
|
95
|
+
* @returns whether the range mapped and the edit applied.
|
|
96
|
+
*/
|
|
97
|
+
insertAsyncText(span: DetectSpan, text: string): boolean;
|
|
91
98
|
/**
|
|
92
99
|
* Insert a reference chip with the existing trailing-space rule.
|
|
93
100
|
* @param span - detect-coordinate range.
|
|
@@ -96,6 +103,12 @@ export declare class DraftEditorRuntime {
|
|
|
96
103
|
* @returns whether the range mapped and the edit applied.
|
|
97
104
|
*/
|
|
98
105
|
insertReference(span: DetectSpan, ref: ReferenceInsert, tail: string): boolean;
|
|
106
|
+
/**
|
|
107
|
+
* Insert an ordered file-reference batch after the live selection without deleting it.
|
|
108
|
+
* @param references - validated references in source order.
|
|
109
|
+
* @returns whether the live insertion position accepted the batch.
|
|
110
|
+
*/
|
|
111
|
+
insertFileReferences(references: readonly ReferenceInsert[]): boolean;
|
|
99
112
|
/** Refresh claim-token decoration after the model's claim changes. */
|
|
100
113
|
refreshClaimDecoration(): void;
|
|
101
114
|
/**
|
|
@@ -11,7 +11,7 @@ interface DraftViewGate {
|
|
|
11
11
|
running: boolean;
|
|
12
12
|
steeringAvailable: boolean;
|
|
13
13
|
busyEnter: BusyEnterBehavior;
|
|
14
|
-
intakeFiles: (files: readonly File[]) => void;
|
|
14
|
+
intakeFiles: (files: readonly File[], directories?: ReadonlySet<File>) => void;
|
|
15
15
|
uploadsPending: boolean;
|
|
16
16
|
showToast: (text: string) => void;
|
|
17
17
|
t: ComposerBarProps['t'];
|