@deepseek-ai/dsh-client-ui-conversation 0.2.0-rc.2 → 0.2.1-alpha.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.
@@ -160,6 +160,12 @@ export interface ConversationContextReader {
160
160
  export type ConversationPublication = 'none' | 'animation-frame' | 'immediate';
161
161
  /** Engine-owned Location data publication phase. */
162
162
  export type ConversationLocationDataScope = 'step' | 'turn';
163
+ /**
164
+ * Extract a stable business identity using only the current event.
165
+ * @param event - durable or transient Client event.
166
+ * @returns identity and lifecycle role, or null when unrelated.
167
+ */
168
+ export type ConversationMatchHandler = (event: SessionEventLike) => ConversationMatchResult | null;
163
169
  /** One independently registered business Event-to-Node state machine. */
164
170
  export interface ConversationNodeDefinition<State = unknown> {
165
171
  readonly kind: string;
@@ -213,6 +219,10 @@ export interface ConversationNodeDefinition<State = unknown> {
213
219
  */
214
220
  buildViewNode?(context: ConversationNodeContext<State>): ConversationViewNode | null;
215
221
  }
222
+ /** Registration accepts a function or an immutable table of own event-type handlers. */
223
+ export type ConversationNodeDefinitionInput<State = unknown> = Omit<ConversationNodeDefinition<State>, 'match'> & {
224
+ readonly match: ConversationMatchHandler | Readonly<Record<string, ConversationMatchHandler>>;
225
+ };
216
226
  /** Reference-stable Turn/Step facts published beside view Nodes. */
217
227
  export interface ConversationTimelineSnapshot {
218
228
  readonly turnOrder: readonly number[];
@@ -16,6 +16,18 @@ export interface ReferenceInsert {
16
16
  readonly appearance?: 'session' | 'file' | 'folder';
17
17
  readonly clipboardText: string;
18
18
  }
19
+ /** Persisted reference data without the current editor's occurrence identity. */
20
+ export type DraftReference = Omit<Occurrence, 'occurrenceId'>;
21
+ /**
22
+ * Editor-independent content. Reference spans are ordered, non-overlapping UTF-16
23
+ * ranges whose text equals clipboardText; runtime node identities are excluded.
24
+ */
25
+ export interface DraftSnapshot {
26
+ readonly text: string;
27
+ readonly references: readonly DraftReference[];
28
+ }
29
+ /** Plain initial text or an existing document with explicit reference identities. */
30
+ export type DraftInput = string | DraftSnapshot;
19
31
  /** Keyboard keys intercepted by an open trigger menu. */
20
32
  export type ArbitrateKey = 'up' | 'down' | 'enter' | 'escape' | 'tab' | 'tabBack';
21
33
  /** Trigger-menu keyboard routing result. */
@@ -7,6 +7,7 @@
7
7
  * here is the submit plane (phase, claim, attempt) alone.
8
8
  */
9
9
  import type { Context } from '@deepseek-ai/cordis';
10
+ import type { SessionBinding } from '@deepseek-ai/dsh-api-session-controller/client';
10
11
  import type { InboxState } from '@deepseek-ai/dsh-agent/types';
11
12
  import type { ObservableSnapshot, SnapshotStore } from '@deepseek-ai/dsh-client-store';
12
13
  import type { Branded } from '@deepseek-ai/dsh-brand';
@@ -161,7 +162,7 @@ export interface InputTarget {
161
162
  }
162
163
  /** Per-session input facade owned by the conversation wiring layer. */
163
164
  export interface SessionInput extends InputTarget {
164
- /** Replace the whole draft (persisted-draft seed and programmatic writes). */
165
+ /** Replace the whole draft with plain text, removing inline reference chips. */
165
166
  setDraft(text: string): void;
166
167
  /** Append ordered browser-owned attachment ids; busy admission phases refuse. */
167
168
  addAttachments(ids: readonly DraftAttachmentId[]): boolean;
@@ -196,7 +197,22 @@ export interface SessionInput extends InputTarget {
196
197
  export interface SessionInputResolver {
197
198
  /** Resolve the facade for one session-scope ctx. */
198
199
  for(actx: Context): SessionInput;
200
+ /**
201
+ * Prepare the exact retained Session before navigation publishes it.
202
+ * @param binding - target Session generation, already retained by the caller.
203
+ * @param options - content to adopt and explicit permission to replace existing text.
204
+ * @returns applied, preserved, or blocked by a pending submission or disposal.
205
+ * @throws when binding is not the currently retained Session generation.
206
+ */
207
+ requestDraftInitialization(binding: SessionBinding, options: DraftInitializationOptions): DraftInitializationResult;
208
+ }
209
+ /** Initial text for a target Session; attachments remain under their existing owner. */
210
+ export interface DraftInitializationOptions {
211
+ readonly prompt?: string;
212
+ readonly clearPreviousDraft?: boolean;
199
213
  }
214
+ /** An initialization request never waits for a React mount or a remote catalog. */
215
+ export type DraftInitializationResult = 'applied' | 'preserved' | 'blocked';
200
216
  /**
201
217
  * The public input action face provided to every session-scope slot
202
218
  * component: stable-identity void callbacks, mirroring the
@@ -213,8 +229,10 @@ export interface InputActions {
213
229
  * @returns false when the draft changed or submission locked the editor.
214
230
  */
215
231
  insertText(text: string, span: TokenSpan): boolean;
216
- /** Replace the whole draft (persisted-draft seed and programmatic writes). */
232
+ /** Replace the whole draft with plain text, removing inline reference chips. */
217
233
  setDraft(text: string): void;
234
+ /** Write the current semantic document through the mounted persistence callback. */
235
+ persistDraft(): void;
218
236
  /** Append ordered browser-owned attachment ids; busy admission phases refuse. */
219
237
  addAttachments(ids: readonly DraftAttachmentId[]): boolean;
220
238
  /** Remove one browser-owned attachment id; busy admission phases refuse. */
@@ -5,6 +5,7 @@ import type { ImageAttachmentRef } from '@deepseek-ai/dsh-attachment';
5
5
  import type { LlmRetryEventData } from '@deepseek-ai/dsh-llm-retry/types';
6
6
  import type { TodoItem } from '@deepseek-ai/dsh-tool-todo/client';
7
7
  import type { ContextProducerView, KnownContextForm } from './context-producer.ts';
8
+ import type { PartialArguments } from '@deepseek-ai/dsh-util-values';
8
9
  export type { TodoItem };
9
10
  /** Request configuration recorded for one provider call. */
10
11
  export interface AssistantRequestConfig {
@@ -156,6 +157,10 @@ export interface ToolResultNode {
156
157
  callId: string;
157
158
  /** Parent Tool call for a PTC dispatch result; absent on a root Session result. */
158
159
  parentCallId?: string;
160
+ /** Wire tool name from the paired tool/call; empty when that call left the loaded window. */
161
+ name: string;
162
+ /** The argument view of the paired call; see {@link ToolArgs}. */
163
+ args: ToolArgs;
159
164
  /** Call head backfilled from the in-window tool/call; null when window truncation left the call outside (card head shows callId). */
160
165
  call: {
161
166
  name: string;
@@ -256,8 +261,21 @@ interface ToolCallHead {
256
261
  time: number;
257
262
  /** Child calls owned by this call, in dispatch order. */
258
263
  subCalls: readonly ToolCallBlock[];
264
+ /** The argument view; see {@link ToolArgs}. */
265
+ args: ToolArgs;
259
266
  }
260
- /** A named model call whose arguments are not yet available to tool views. */
267
+ /**
268
+ * Lazy top-level argument readers shared by preparing, start, and result;
269
+ * {@link PartialArguments} defines field, prefix, length, and completion reads.
270
+ * A preparing view grows in place. Read it during render or view construction,
271
+ * not into independent state keyed only by the args or block object identity.
272
+ * The Definition publishes the initial named block, then republishes when an
273
+ * observed answer changes. Unread fields alone do not request republication.
274
+ * Dispatched views are sealed over finished text or parsed values. The view is
275
+ * empty for a result whose `tool/call` left the loaded window.
276
+ */
277
+ export type ToolArgs = PartialArguments;
278
+ /** A named model call whose complete arguments are not yet available to tool views. */
261
279
  export interface PreparingToolCall extends ToolCallHead {
262
280
  readonly phase: 'preparing';
263
281
  }
@@ -11,7 +11,7 @@ import type { SessionId } from '@deepseek-ai/dsh-session/types';
11
11
  import type { WorkspaceId } from '@deepseek-ai/dsh-workspace/types';
12
12
  import type { ComposerBlock } from './composer-blocks.ts';
13
13
  import type { DraftAttachmentId, InputActions, InputNotice, InputState } from './input.ts';
14
- import type { ComposerKeyboard, EditSelection } from './draft-editor.ts';
14
+ import type { ComposerKeyboard, DraftSnapshot, EditSelection } from './draft-editor.ts';
15
15
  import type { createConversationStore } from '../stores.ts';
16
16
  import type { BusyEnterBehavior } from './composer-submission.ts';
17
17
  import type { ConversationSnapshot } from './snapshot.ts';
@@ -410,7 +410,7 @@ export interface ConversationSessionInjected {
410
410
  readonly inspectCall: ObservableSnapshot<ConvViewOwnerProps['inspectCall']>;
411
411
  };
412
412
  /** Bind input draft persistence to the Session-owned store instance. */
413
- bindDraftMirror: (write: (text: string) => void) => () => void;
413
+ bindDraftPersistence: (write: (draft: DraftSnapshot) => void) => () => void;
414
414
  /** Select and activate one View while addressing an opaque focus request to it. */
415
415
  openView: (view: string, focus: string) => void;
416
416
  }
@@ -1,4 +1,5 @@
1
1
  /** Conversation view and session-local presentation state. */
2
+ import type { DraftInput } from './draft-editor.ts';
2
3
  /**
3
4
  * One conversation view tab, projected from a 'conversation.view' slot
4
5
  * entry's registration options (label falls back to the entry id).
@@ -17,7 +18,7 @@ export interface ConversationViewRequest {
17
18
  /** Per-session state owned by the target-neutral Conversation shell. */
18
19
  export interface ConversationStoreState {
19
20
  /** Composer draft (persisted; survives session switches and reloads). */
20
- draft: string;
21
+ draft: DraftInput;
21
22
  /** Preferred `conversation.view` entry id; null resolves to Chat when registered. */
22
23
  view: string | null;
23
24
  /** Focus request consumed and acknowledged by the addressed View. */
@@ -2,8 +2,9 @@ import type { SessionAssistantSettlementEntry, SessionEventLikeEntry } from '@de
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
4
  import type { ConversationGroupData, ConversationGroupDefinition, ConversationGroupedView } from '../contract/groups.ts';
5
+ import type { ConversationEventRegistry } from './event-registry.ts';
5
6
  /** Event Registry subset consumed by a Session-owned Assembler. */
6
- export interface ConversationEventDefinitions {
7
+ export interface ConversationEventDefinitions extends Partial<Pick<ConversationEventRegistry, 'forEvent'>> {
7
8
  /** @returns ordinary Definitions in registration order. */
8
9
  entries(): readonly ConversationNodeDefinition[];
9
10
  /** @returns unmatched-event fallback, when registered. */
@@ -1,24 +1,40 @@
1
- import type { ConversationNodeDefinition } from '../contract/conversation.ts';
1
+ import type { ConversationMatchHandler, ConversationNodeDefinition, ConversationNodeDefinitionInput } from '../contract/conversation.ts';
2
2
  import { ConversationDefinitionRegistry } from './definition-registry.ts';
3
+ /** A registered Definition and its event-type-selected handler. */
4
+ export interface ConversationEventRoute {
5
+ readonly definition: ConversationNodeDefinition;
6
+ readonly match: ConversationMatchHandler;
7
+ }
3
8
  /** Runtime registry of independently owned Conversation business Definitions. */
4
9
  export declare class ConversationEventRegistry extends ConversationDefinitionRegistry<ConversationNodeDefinition> {
5
10
  private fallback;
11
+ private routes;
12
+ private unrestricted;
13
+ private readonly tables;
6
14
  /**
7
15
  * Register a uniquely named business Definition for the caller's lifetime.
8
16
  * @param definition - Definition contribution.
9
17
  * @returns idempotent disposer.
10
18
  */
11
- register(definition: ConversationNodeDefinition): () => void;
19
+ register(definition: ConversationNodeDefinitionInput): () => void;
12
20
  /**
13
21
  * Register the sole fallback used only when no ordinary Definition matches.
14
- * @param definition - fallback Definition.
22
+ * @param input - fallback Definition.
15
23
  * @returns idempotent disposer.
16
24
  */
17
- registerFallback(definition: ConversationNodeDefinition): () => void;
25
+ registerFallback(input: ConversationNodeDefinitionInput): () => void;
18
26
  /**
19
27
  * Return the current unmatched-event fallback.
20
28
  * @returns installed fallback, when present.
21
29
  */
22
30
  fallbackEntry(): ConversationNodeDefinition | undefined;
31
+ /**
32
+ * Read precomputed candidates in registration order; the returned Set is borrowed read-only.
33
+ * @param type - current event type.
34
+ * @returns table handlers for this type together with all function-form handlers.
35
+ */
36
+ forEvent(type: string): ReadonlySet<ConversationEventRoute>;
37
+ private resolve;
38
+ protected refresh(): void;
23
39
  }
24
40
  //# sourceMappingURL=event-registry.d.ts.map
@@ -10,8 +10,8 @@ export interface ConversationLocationDataChange {
10
10
  /** Session-owned Turn/Step timeline and event-to-Location index. */
11
11
  export declare class ConversationLocationIndex {
12
12
  private coordinates;
13
- private locations;
14
13
  private seqsByTurn;
14
+ private readonly stepsByTurn;
15
15
  private timeline;
16
16
  private readonly turnDataStores;
17
17
  private readonly stepDataStores;
@@ -65,7 +65,7 @@ export declare class ConversationLocationIndex {
65
65
  */
66
66
  appendBoundary(event: SessionEvent): ReadonlySet<number>;
67
67
  /**
68
- * Index one non-boundary tail event without rescanning the window.
68
+ * Index one non-boundary tail event without scanning the window or the Turn's Steps.
69
69
  * @param event - contiguous appended event.
70
70
  */
71
71
  appendNonBoundary(event: SessionEventLike): void;
@@ -0,0 +1,21 @@
1
+ import type { DraftInput, DraftSnapshot, Occurrence } from './contract/draft-editor.ts';
2
+ /**
3
+ * Copy input into the semantic draft representation without editor runtime identities.
4
+ * @param input - plain text or caller-owned structured content.
5
+ * @returns an owned snapshot ready for editor import.
6
+ */
7
+ export declare function resolveDraftInput(input: DraftInput): DraftSnapshot;
8
+ /**
9
+ * Decode persisted drafts, accepting the earlier plain-string representation.
10
+ * @param value - JSON value read from browser storage.
11
+ * @returns the decoded draft, or undefined for invalid data.
12
+ */
13
+ export declare function parseStoredDraft(value: unknown): DraftSnapshot | undefined;
14
+ /**
15
+ * Export reference identities without their editor-local occurrence ids.
16
+ * @param text - current clipboard projection.
17
+ * @param occurrences - matching reference projections from the same document revision.
18
+ * @returns an editor-independent snapshot.
19
+ */
20
+ export declare function snapshotDraft(text: string, occurrences: readonly Occurrence[]): DraftSnapshot;
21
+ //# sourceMappingURL=draft.d.ts.map
@@ -7,10 +7,10 @@ export type { ConversationGroupRegistry } from './conversation/group-registry.ts
7
7
  export type { ConversationGroupContext, ConversationGroupData, ConversationGroupDataMap, ConversationGroupDefinition, ConversationGroupedView, ConversationGroupInput, GroupKey, GroupNodePosition, GroupReference, GroupSnapshot, GroupUpdate, NodeChange, NodeKey, NodeReference, RenderEntry, } from './contract/groups.ts';
8
8
  export { ConversationController, UnsupportedImageMediaTypeError } from './service.ts';
9
9
  export type { IConversation } from './service.ts';
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';
10
+ export type { ConversationContextReader, ConversationLocation, ConversationLocationData, ConversationLocationDataScope, ConversationLocationDataSource, ConversationLocationDataStore, ConversationMatch, ConversationMatchHandler, ConversationMatchResult, ConversationNodeContext, ConversationNodeDefinition, ConversationNodeDefinitionInput, ConversationPreviousContext, ConversationPublication, ConversationStartMatch, ConversationStepDataMap, ConversationTimelineSnapshot, ConversationTurnDataMap, ConversationViewBuilder, ConversationViewDefinition, ConversationViewNode, ConversationViewSnapshotMap, ConversationViewSnapshotStore, StepLocation, TurnLocation, } from './contract/conversation.ts';
11
11
  export { EMPTY_CONVERSATION_SNAPSHOT, conversationPhase } from './contract/snapshot.ts';
12
12
  export type { ConversationPhase, ConversationSnapshot, } from './contract/snapshot.ts';
13
- export type { AssistantBlock, AssistantMessageNode, AssistantProviderMetadataView, AssistantRequestConfig, AssistantTiming, CommandNode, CompactionSummaryNode, ContextMessageNode, ConversationNode, ModelRetryNode, PartialAssistant, PreparingToolCall, RunningToolCall, StartedToolCall, SteeringMessageNode, TodoItem, ToolCallBlock, ToolResultNode, TurnErrorNode, TurnMaxTokensNode, UnknownSurfaceNode, UserMessageNode, } from './contract/records.ts';
13
+ export type { AssistantBlock, AssistantMessageNode, AssistantProviderMetadataView, AssistantRequestConfig, AssistantTiming, CommandNode, CompactionSummaryNode, ContextMessageNode, ConversationNode, ModelRetryNode, PartialAssistant, PreparingToolCall, RunningToolCall, StartedToolCall, SteeringMessageNode, TodoItem, ToolCallBlock, ToolArgs, ToolResultNode, TurnErrorNode, TurnMaxTokensNode, UnknownSurfaceNode, UserMessageNode, } from './contract/records.ts';
14
14
  export type { ContextProducerView, ContextRole, KnownContextForm, } from './contract/context-producer.ts';
15
15
  export type { ConversationPromptSnapshot, RequestInspectionSnapshot, RequestPromptChange, RequestPromptInspection, RequestPromptInspector, RequestView, SystemPromptNode, } from './contract/request-inspection.ts';
16
16
  export { inspectRequestPrompt } from './contract/request-inspection.ts';
@@ -25,8 +25,8 @@ export type { ConversationLocationDataChange } from './conversation/location-ind
25
25
  export { ConversationViewRegistry } from './conversation/view-registry.ts';
26
26
  export type { ConversationKey } from './locales.ts';
27
27
  export type { ComposerAttachment, ComposerAttachmentsOwnerProps, ComposerAttachmentsProps, ComposerFileAttachment, ComposerImageAttachment, DraftFileUpload, DraftFileUploads, ComposerBarInjected, ComposerBarOwnerProps, ComposerBarProps, ComposerChainProps, ConversationHeaderActionOwnerProps, ConversationHeaderCornerOwnerProps, ConversationHeaderLineageOwnerProps, ConversationContentInputProps, ConversationContentProps, ConversationInjected, ConversationSessionHeaderInjected, ConversationSessionHeaderSlotProps, ConversationSessionInjected, ConversationSessionSlotProps, ConversationSlotProps, ConversationViewsProps, ConversationWidthControlsInputProps, ConversationWidthControlsProps, ConversationStore, ConvViewOwnerProps, ConvViewProps, EmptyWorkspaceOwnerProps, HeroAgentPresetOwnerProps, HeroBrandMarkOwnerProps, InputControlOwnerProps, InputZone, MessageImageLoader, MessageImageSource, MessageImagesOwnerProps, RenderMessageImages, UseConversation, UseConversationViews, } from './contract/slots.ts';
28
- export type { BeginCommandRequest, CommandClaim, ConsumeTokenRequest, DraftAttachmentId, InputActions, InputState, InsertReferenceRequest, InsertTextRequest, PickOutcome, SessionInput, SessionInputResolver, SubmitAttachment, SubmitOutcome, } from './contract/input.ts';
29
- export type { ArbitrateKey, ArbitrateOutcome, ReferenceInsert, TokenSpan } from './contract/draft-editor.ts';
28
+ export type { BeginCommandRequest, CommandClaim, ConsumeTokenRequest, DraftAttachmentId, DraftInitializationOptions, DraftInitializationResult, InputActions, InputState, InsertReferenceRequest, InsertTextRequest, PickOutcome, SessionInput, SessionInputResolver, SubmitAttachment, SubmitOutcome, } from './contract/input.ts';
29
+ export type { ArbitrateKey, ArbitrateOutcome, DraftInput, DraftReference, DraftSnapshot, ReferenceInsert, TokenSpan } from './contract/draft-editor.ts';
30
30
  export type { ComposerBlock, ComposerBlocks } from './contract/composer-blocks.ts';
31
31
  declare module '@deepseek-ai/cordis' {
32
32
  interface Context {
@@ -25,7 +25,7 @@ export interface TextRefRange {
25
25
  * exact lexicon member; a `/name` token must end at whitespace or the draft
26
26
  * end ('/name/x' is a path, '/name。' is prose).
27
27
  * @param draft - draft text.
28
- * @param lexicon - per-trigger name lists (a missing trigger scans nothing).
28
+ * @param lexicon - per-trigger name lists; missing catalogs match no named tokens.
29
29
  * @returns matched ranges in draft order.
30
30
  */
31
31
  export declare function scanTextRefs(draft: string, lexicon: ReadonlyMap<'/' | '@', readonly string[]>): TextRefRange[];
@@ -1,7 +1,7 @@
1
1
  /** The Composer model's private Lexical editor, projections, and node operations. */
2
2
  import type { ObservableSnapshot } from '@deepseek-ai/dsh-client-store';
3
3
  import type { LexicalEditor } from 'lexical';
4
- import type { Occurrence, ReferenceInsert } from '../../contract/draft-editor.ts';
4
+ import type { DraftReference, ReferenceInsert } from '../../contract/draft-editor.ts';
5
5
  import type { EditorProjection } from './projection.ts';
6
6
  import type { DetectSpan } from './span-map.ts';
7
7
  type Lexicon = ReadonlyMap<'/' | '@', readonly string[]>;
@@ -24,6 +24,7 @@ export declare class DraftEditorRuntime {
24
24
  private occurrenceSeq;
25
25
  /** Live lexicon subscription disposer; undefined until the controller resolves. */
26
26
  private lexiconOff;
27
+ private lexiconSource;
27
28
  /** @param deps - model callbacks used by editor listeners and transforms. */
28
29
  constructor(deps: DraftEditorRuntimeDeps);
29
30
  /**
@@ -44,12 +45,10 @@ export declare class DraftEditorRuntime {
44
45
  */
45
46
  private applyEdit;
46
47
  /**
47
- * Subscribe the text-ref re-scan to the controller's lexicon once the
48
- * controller resolves. The deps thunk cannot resolve at construction (the
49
- * shell is created inside the sessions provide materialization), so the
50
- * first interactive updates retry until it can.
48
+ * Reconnect decorations when the optional trigger provider changes.
49
+ * The rescan reads the current editor and does not replace its content.
51
50
  */
52
- private ensureLexiconSubscription;
51
+ refreshLexiconSubscription(): void;
53
52
  /**
54
53
  * Re-project inside the existing editor update callback.
55
54
  * @returns the projection preceding this read.
@@ -117,11 +116,11 @@ export declare class DraftEditorRuntime {
117
116
  */
118
117
  clearCommittedDraft(prefixLength: (clipboardText: string) => number | null): void;
119
118
  /**
120
- * Rebuild one model-selected failure snapshot, creating fresh reference nodes.
119
+ * Import semantic content or a model-selected failure snapshot with fresh reference nodes.
121
120
  * @param draft - clipboard text.
122
121
  * @param occurrences - reference occurrences in clipboard order.
123
122
  */
124
- restoreDraft(draft: string, occurrences: readonly Occurrence[]): void;
123
+ restoreDraft(draft: string, occurrences: readonly DraftReference[]): void;
125
124
  /** Cut the editor's undo history after a committed clear or restoration. */
126
125
  clearHistory(): void;
127
126
  }
@@ -12,18 +12,17 @@ import type { Context } from '@deepseek-ai/cordis';
12
12
  import type { InboxState } from '@deepseek-ai/dsh-agent/types';
13
13
  import { type ObservableSnapshot, type SnapshotStore } from '@deepseek-ai/dsh-client-store';
14
14
  import type { LexicalEditor } from 'lexical';
15
- import type { CommandClaim, ConsumeTokenRequest, DraftAttachmentId, InputActions, InputNotice, InputState, InputTriggerController, SessionInput, SubmitAttachment, SubmitOutcome } from '../contract/input.ts';
16
- import type { ArbitrateKey, ArbitrateOutcome, ComposerKeyboard, ReferenceInsert, TokenSpan } from '../contract/draft-editor.ts';
15
+ import type { CommandClaim, ConsumeTokenRequest, DraftAttachmentId, DraftInitializationOptions, DraftInitializationResult, InputActions, InputNotice, InputState, InputTriggerController, SessionInput, SubmitAttachment, SubmitOutcome } from '../contract/input.ts';
16
+ import type { ArbitrateKey, ArbitrateOutcome, ComposerKeyboard, DraftInput, DraftSnapshot, ReferenceInsert, TokenSpan } from '../contract/draft-editor.ts';
17
17
  import type { InputSubmitMode, MessageSubmission, MessageSubmissionState } from '../contract/composer-submission.ts';
18
18
  /** Popup face the shell needs (dismissal only; typed structurally to avoid a value import). */
19
19
  export interface PopupDismissFace {
20
20
  dismiss(): void;
21
21
  }
22
22
  /**
23
- * Construction dependencies of one facade. The slash/popup faces are THUNKS: the
24
- * shell is created inside the sessions provide materialization (before the
25
- * scope record is queryable), where `slash.sessionOf`/`command.popupFor`
26
- * cannot resolve yet — resolution defers to first interactive use.
23
+ * Construction dependencies of one input model. Trigger and popup callbacks
24
+ * resolve the currently available Session-scoped services on demand. InputHub
25
+ * owns the lexicon subscription through the Session scope's inject lifecycle.
27
26
  */
28
27
  export interface SessionInputDeps {
29
28
  /** Session-scope ctx handed to claim.submit transactions. */
@@ -76,11 +75,12 @@ export declare class SessionInputShell implements SessionInput {
76
75
  private rev;
77
76
  private readonly unregister;
78
77
  private noticeSeq;
79
- private lastMirroredDraft;
78
+ private lastPublishedDraft;
79
+ private draftSnapshotCache;
80
80
  private attachmentIds;
81
81
  private disposed;
82
- /** Draft persistence mirror (Conversation store write; receives the clipboard projection). */
83
- private mirrorFn;
82
+ /** Conversation store writer for the current semantic document. */
83
+ private persistDraft;
84
84
  /** The mounted composer's file-picker opener (scoped pick-files event target). */
85
85
  private filePicker;
86
86
  /** Default sends retained until admission settles or scope disposal releases their attachments. */
@@ -101,9 +101,23 @@ export declare class SessionInputShell implements SessionInput {
101
101
  * Replace the whole draft (persisted-draft seed and programmatic writes).
102
102
  * Placeholder-sanitized; newlines split paragraphs; the caret lands at the
103
103
  * end. Merged into history so a seed is not an undoable step of its own.
104
- * @param text - the full next draft.
104
+ * @param text - plain text or the complete semantic document.
105
105
  */
106
- setDraft(text: string): void;
106
+ setDraft(text: DraftInput): void;
107
+ /** Reconnect optional catalog notifications without waiting for another edit. */
108
+ refreshLexiconSubscription(): void;
109
+ /** Current semantic document, stable until its content revision changes. */
110
+ get draftSnapshot(): DraftSnapshot;
111
+ /** Persist the latest document without changing the editor or binding a writer. */
112
+ persistCurrentDraft(): void;
113
+ /**
114
+ * Apply one new-task request to this already-initialized input model.
115
+ * @param options - replacement content and explicit permission to clear existing text.
116
+ * @returns applied when the requested text is adopted, even if unchanged;
117
+ * preserved when the current draft is kept; blocked after disposal or during a pending submission.
118
+ */
119
+ requestDraftInitialization(options: DraftInitializationOptions): DraftInitializationResult;
120
+ private draftInitializationBlocked;
107
121
  /** Append ordered attachment ids unless an admission transaction is locked. */
108
122
  addAttachments(ids: readonly DraftAttachmentId[]): boolean;
109
123
  /**
@@ -245,14 +259,11 @@ export declare class SessionInputShell implements SessionInput {
245
259
  /** Read the live input state (guard derivation reads here). */
246
260
  get snapshot(): InputState;
247
261
  /**
248
- * Bind the draft persistence mirror (Conversation store write). Adopt-on-bind: the
249
- * store draft may hold a persisted value from a previous mount; the caller
250
- * seeds it via setDraft BEFORE binding, and afterwards every editor-adopted
251
- * draft mirrors out.
252
- * @param write - store draft write.
262
+ * Bind the Conversation store writer without importing or saving content.
263
+ * @param write - semantic draft writer; persistCurrentDraft flushes the initial value.
253
264
  * @returns the unbind disposer.
254
265
  */
255
- bindMirror(write: (text: string) => void): () => void;
266
+ bindDraftPersistence(write: (draft: DraftSnapshot) => void): () => void;
256
267
  /**
257
268
  * Bind the mounted composer's file action and live intake availability.
258
269
  * @param picker - availability query and native file-dialog opener.
@@ -2,7 +2,7 @@ import type { Context } from '@deepseek-ai/cordis';
2
2
  import type { SessionBinding } from '@deepseek-ai/dsh-api-session-controller/client';
3
3
  import type { SessionId } from '@deepseek-ai/dsh-session/types';
4
4
  import type { TranslateNS } from '@deepseek-ai/dsh-client-locale/client';
5
- import type { InputTriggerController, SessionInputResolver, SessionInput } from '../contract/input.ts';
5
+ import type { DraftInitializationOptions, DraftInitializationResult, InputTriggerController, SessionInputResolver, SessionInput } from '../contract/input.ts';
6
6
  import type { ComposerKeyboard } from '../contract/draft-editor.ts';
7
7
  import { SessionInputShell } from './facade.ts';
8
8
  /** Session-addressed input facade registry (SessionInputResolver face + composer-layer extras). */
@@ -21,11 +21,11 @@ export declare class InputHub implements SessionInputResolver {
21
21
  * @returns the resident per-session facade.
22
22
  */
23
23
  for(actx: Context): SessionInput;
24
+ requestDraftInitialization(binding: SessionBinding, options: DraftInitializationOptions): DraftInitializationResult;
24
25
  /**
25
- * Resident shell for one session binding — the provide-channel entry
26
- * (called during scope materialization, BEFORE the scope record is
27
- * queryable, hence binding-fed and hence the thunked slash/popup deps).
28
- * Wires the scoped event listeners + teardown into the session scope.
26
+ * Resolve the resident shell for an already-retained, addressable Session binding.
27
+ * Draft import completes before return. The Session scope owns input listeners,
28
+ * the inject-managed catalog subscription, and shell teardown.
29
29
  * @param binding - session assembly handle.
30
30
  * @returns the shell.
31
31
  */
@@ -1,9 +1,9 @@
1
1
  import type { ConversationSessionSlotProps } from '../contract/slots.ts';
2
2
  /**
3
3
  * Renders the active Session view inside the resident scrollport and keeps
4
- * the input draft mirrored while blank Hero chrome is visible.
4
+ * the input draft persisted while blank Hero chrome is visible.
5
5
  * @param props - Strict Session input/store, view ledger, and render shares.
6
6
  * @returns the active view area, or null while the Session remains blank.
7
7
  */
8
- export declare function DefaultConversationViews({ view, useSession, useConversation, useConversationViews, useInput, inputActions, useStore, actions, renderSlot, bindDraftMirror, openView, useInspectCall, }: ConversationSessionSlotProps): import("react").JSX.Element | null;
8
+ export declare function DefaultConversationViews({ view, useSession, useConversation, useConversationViews, inputActions, useStore, actions, renderSlot, bindDraftPersistence, openView, useInspectCall, }: ConversationSessionSlotProps): import("react").JSX.Element | null;
9
9
  //# sourceMappingURL=DefaultConversationViews.d.ts.map
@@ -2,9 +2,10 @@
2
2
  import { type EngineStoreHandle } from '@deepseek-ai/dsh-client-store';
3
3
  import type { SessionId } from '@deepseek-ai/dsh-session/types';
4
4
  import type { ConversationStoreState } from './contract/views.ts';
5
+ import type { DraftInput, DraftSnapshot } from './contract/draft-editor.ts';
5
6
  /** Declared write set for the Conversation shell. */
6
7
  type ConversationActions = {
7
- setDraft: (draft: ConversationStoreState, text: string) => void;
8
+ setDraft: (draft: ConversationStoreState, text: DraftInput) => void;
8
9
  setView: (draft: ConversationStoreState, view: string) => void;
9
10
  openView: (draft: ConversationStoreState, view: string, focus: string) => void;
10
11
  completeViewRequest: (draft: ConversationStoreState) => void;
@@ -14,6 +15,12 @@ type ConversationActions = {
14
15
  * @returns the store handle.
15
16
  */
16
17
  export declare function createConversationStore(): EngineStoreHandle<ConversationStoreState, ConversationActions>;
18
+ /**
19
+ * Read a Session's draft before its input source is published to React.
20
+ * @param sessionId - Session-scoped persistence suffix.
21
+ * @returns saved semantic content, or an empty document when storage is absent or invalid.
22
+ */
23
+ export declare function readConversationDraft(sessionId: SessionId): DraftSnapshot;
17
24
  /**
18
25
  * Read the persisted View preference before the Slot store is materialized.
19
26
  * @param sessionId - Session-scoped persistence suffix.
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@deepseek-ai/dsh-client-ui-conversation",
3
3
  "description": "Target-neutral Conversation assembly, shell, composer, queue, and view navigation",
4
- "version": "0.2.0-rc.2",
4
+ "version": "0.2.1-alpha.1",
5
5
  "publishConfig": {
6
6
  "access": "public"
7
7
  },
@@ -42,10 +42,10 @@
42
42
  },
43
43
  "license": "MIT",
44
44
  "dependencies": {
45
- "@deepseek-ai/schemastery": "~3.18.4"
45
+ "@deepseek-ai/schemastery": "~3.18.5-alpha.1"
46
46
  },
47
47
  "peerDependencies": {
48
- "@deepseek-ai/cordis": "~4.0.4"
48
+ "@deepseek-ai/cordis": "~4.0.5-alpha.1"
49
49
  },
50
50
  "devDependencies": {
51
51
  "@types/react": "~18.3.1",
@@ -60,40 +60,40 @@
60
60
  "@lexical/text": "^0.49.0",
61
61
  "@lexical/plain-text": "^0.49.0",
62
62
  "@lexical/history": "^0.49.0",
63
- "@deepseek-ai/cordis": "~4.0.4",
64
- "@deepseek-ai/dsh-api-remotes": "0.2.0-rc.2",
65
- "@deepseek-ai/dsh-api-session-controller": "0.2.0-rc.2",
66
- "@deepseek-ai/dsh-api-workspace-controller": "0.2.0-rc.2",
67
- "@deepseek-ai/dsh-attachment": "0.2.0-rc.2",
68
- "@deepseek-ai/dsh-client-locale": "0.2.0-rc.2",
69
- "@deepseek-ai/dsh-brand": "0.2.0-rc.2",
70
- "@deepseek-ai/dsh-client-file-upload": "0.2.0-rc.2",
71
- "@deepseek-ai/dsh-client-store": "0.2.0-rc.2",
72
- "@deepseek-ai/dsh-client-test-runtime": "0.2.0-rc.2",
73
- "@deepseek-ai/dsh-client-ui-layout": "0.2.0-rc.2",
74
- "@deepseek-ai/dsh-client-ui-primitives": "0.2.0-rc.2",
75
- "@deepseek-ai/dsh-client-ui-session": "0.2.0-rc.2",
76
- "@deepseek-ai/dsh-client-ui-settings": "0.2.0-rc.2",
77
- "@deepseek-ai/dsh-client-ui-workspace": "0.2.0-rc.2",
78
- "@deepseek-ai/dsh-client-ui-slots": "0.2.0-rc.2",
79
- "@deepseek-ai/dsh-commands": "0.2.0-rc.2",
80
- "@deepseek-ai/dsh-goal": "0.2.0-rc.2",
81
- "@deepseek-ai/dsh-llm": "0.2.0-rc.2",
82
- "@deepseek-ai/dsh-llm-retry": "0.2.0-rc.2",
83
- "@deepseek-ai/dsh-plan-mode": "0.2.0-rc.2",
84
- "@deepseek-ai/dsh-session": "0.2.0-rc.2",
85
- "@deepseek-ai/dsh-client-ui-renderer": "0.2.0-rc.2",
86
- "@deepseek-ai/dsh-util-values": "0.2.0-rc.2",
87
- "@deepseek-ai/dsh-token-meter": "0.2.0-rc.2",
88
- "@deepseek-ai/dsh-tool-todo": "0.2.0-rc.2",
89
- "@deepseek-ai/dsh-util-crypto": "0.2.0-rc.2",
90
- "@deepseek-ai/dsh-workspace": "0.2.0-rc.2",
91
- "@deepseek-ai/dsh-file-reference": "0.2.0-rc.2",
92
- "@deepseek-ai/dsh-util-workspace-path": "0.2.0-rc.2",
93
- "@deepseek-ai/dsh-agent": "0.2.0-rc.2",
94
- "@deepseek-ai/dsh-settings": "0.2.0-rc.2",
95
- "@deepseek-ai/dsh-client-shortcuts": "0.2.0-rc.2",
96
- "@deepseek-ai/dsh-client-product-analytics": "0.2.0-rc.2"
63
+ "@deepseek-ai/dsh-api-session-controller": "0.2.1-alpha.1",
64
+ "@deepseek-ai/dsh-api-remotes": "0.2.1-alpha.1",
65
+ "@deepseek-ai/cordis": "~4.0.5-alpha.1",
66
+ "@deepseek-ai/dsh-api-workspace-controller": "0.2.1-alpha.1",
67
+ "@deepseek-ai/dsh-attachment": "0.2.1-alpha.1",
68
+ "@deepseek-ai/dsh-brand": "0.2.1-alpha.1",
69
+ "@deepseek-ai/dsh-client-file-upload": "0.2.1-alpha.1",
70
+ "@deepseek-ai/dsh-client-store": "0.2.1-alpha.1",
71
+ "@deepseek-ai/dsh-client-test-runtime": "0.2.1-alpha.1",
72
+ "@deepseek-ai/dsh-client-ui-layout": "0.2.1-alpha.1",
73
+ "@deepseek-ai/dsh-client-ui-primitives": "0.2.1-alpha.1",
74
+ "@deepseek-ai/dsh-client-ui-renderer": "0.2.1-alpha.1",
75
+ "@deepseek-ai/dsh-client-locale": "0.2.1-alpha.1",
76
+ "@deepseek-ai/dsh-client-ui-settings": "0.2.1-alpha.1",
77
+ "@deepseek-ai/dsh-client-ui-workspace": "0.2.1-alpha.1",
78
+ "@deepseek-ai/dsh-client-ui-slots": "0.2.1-alpha.1",
79
+ "@deepseek-ai/dsh-commands": "0.2.1-alpha.1",
80
+ "@deepseek-ai/dsh-goal": "0.2.1-alpha.1",
81
+ "@deepseek-ai/dsh-llm": "0.2.1-alpha.1",
82
+ "@deepseek-ai/dsh-client-ui-session": "0.2.1-alpha.1",
83
+ "@deepseek-ai/dsh-plan-mode": "0.2.1-alpha.1",
84
+ "@deepseek-ai/dsh-session": "0.2.1-alpha.1",
85
+ "@deepseek-ai/dsh-util-values": "0.2.1-alpha.1",
86
+ "@deepseek-ai/dsh-token-meter": "0.2.1-alpha.1",
87
+ "@deepseek-ai/dsh-tool-todo": "0.2.1-alpha.1",
88
+ "@deepseek-ai/dsh-util-crypto": "0.2.1-alpha.1",
89
+ "@deepseek-ai/dsh-workspace": "0.2.1-alpha.1",
90
+ "@deepseek-ai/dsh-file-reference": "0.2.1-alpha.1",
91
+ "@deepseek-ai/dsh-util-workspace-path": "0.2.1-alpha.1",
92
+ "@deepseek-ai/dsh-llm-retry": "0.2.1-alpha.1",
93
+ "@deepseek-ai/dsh-settings": "0.2.1-alpha.1",
94
+ "@deepseek-ai/dsh-client-shortcuts": "0.2.1-alpha.1",
95
+ "@deepseek-ai/dsh-client-product-analytics": "0.2.1-alpha.1",
96
+ "@deepseek-ai/dsh-agent": "0.2.1-alpha.1"
97
97
  },
98
98
  "files": [
99
99
  "lib/index.js",