@ahggg/dsh-side-chat 0.7.1 → 0.7.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (171) hide show
  1. package/README.md +3 -3
  2. package/README.zh-CN.md +3 -3
  3. package/lib/client/apply.d.ts +0 -1
  4. package/lib/client/apply.js +0 -1
  5. package/lib/client/contracts.d.ts +0 -1
  6. package/lib/client/contracts.js +0 -1
  7. package/lib/client/index.d.ts +0 -1
  8. package/lib/client/index.js +0 -1
  9. package/lib/client/model-preference.d.ts +0 -1
  10. package/lib/client/model-preference.js +0 -1
  11. package/lib/client/panel/SelectionQuote.d.ts +0 -1
  12. package/lib/client/panel/SelectionQuote.js +0 -1
  13. package/lib/client/panel/SendIcon.d.ts +0 -1
  14. package/lib/client/panel/SendIcon.js +0 -1
  15. package/lib/client/panel/SideChatBody.d.ts +0 -1
  16. package/lib/client/panel/SideChatBody.js +0 -1
  17. package/lib/client/panel/SideChatErrorState.d.ts +0 -1
  18. package/lib/client/panel/SideChatErrorState.js +0 -1
  19. package/lib/client/panel/SideChatHeader.d.ts +0 -1
  20. package/lib/client/panel/SideChatHeader.js +0 -1
  21. package/lib/client/panel/SideChatModelSelect.d.ts +0 -1
  22. package/lib/client/panel/SideChatModelSelect.js +0 -1
  23. package/lib/client/panel/SideChatPanel.d.ts +0 -1
  24. package/lib/client/panel/SideChatPanel.js +0 -1
  25. package/lib/client/panel/StopIcon.d.ts +0 -1
  26. package/lib/client/panel/StopIcon.js +0 -1
  27. package/lib/client/panel/messages.d.ts +0 -1
  28. package/lib/client/panel/messages.js +0 -1
  29. package/lib/client/panel/use-auto-growing-textarea.d.ts +0 -1
  30. package/lib/client/panel/use-auto-growing-textarea.js +0 -1
  31. package/lib/client/parent-composer/ParentConversationAnnotations.d.ts +0 -1
  32. package/lib/client/parent-composer/ParentConversationAnnotations.js +26 -3
  33. package/lib/client/parent-composer/add-to-conversation.d.ts +15 -54
  34. package/lib/client/parent-composer/add-to-conversation.js +308 -63
  35. package/lib/client/parent-composer/annotation-persistence.d.ts +1 -2
  36. package/lib/client/parent-composer/annotation-persistence.js +43 -41
  37. package/lib/client/parent-composer/composer-reference.d.ts +81 -0
  38. package/lib/client/parent-composer/composer-reference.js +89 -0
  39. package/lib/client/parent-composer/referenced-conversation.d.ts +2 -3
  40. package/lib/client/parent-composer/referenced-conversation.js +36 -25
  41. package/lib/client/rc6/ArchivedConversation.d.ts +2 -3
  42. package/lib/client/rc6/ArchivedConversation.js +6 -5
  43. package/lib/client/rc6/Rc6SideChatOverlay.d.ts +0 -1
  44. package/lib/client/rc6/Rc6SideChatOverlay.js +12 -2
  45. package/lib/client/rc6/SideChatTool.d.ts +1 -2
  46. package/lib/client/rc6/SideChatTool.js +18 -9
  47. package/lib/client/rc6/context.d.ts +9 -3
  48. package/lib/client/rc6/context.js +0 -1
  49. package/lib/client/rc6/primitive-labels.d.ts +7 -0
  50. package/lib/client/rc6/primitive-labels.js +60 -0
  51. package/lib/client/rc6/remote-adapter.d.ts +0 -1
  52. package/lib/client/rc6/remote-adapter.js +4 -3
  53. package/lib/client/rc6/runtime-compat.d.ts +120 -0
  54. package/lib/client/rc6/runtime-compat.js +187 -0
  55. package/lib/client/rc6/sessions-adapter.d.ts +9 -4
  56. package/lib/client/rc6/sessions-adapter.js +74 -46
  57. package/lib/client/selection/ConversationAnnotationMarkers.d.ts +0 -1
  58. package/lib/client/selection/ConversationAnnotationMarkers.js +0 -1
  59. package/lib/client/selection/SelectionActions.d.ts +5 -2
  60. package/lib/client/selection/SelectionActions.js +66 -50
  61. package/lib/client/selection/selection-controller.d.ts +0 -1
  62. package/lib/client/selection/selection-controller.js +0 -1
  63. package/lib/client/selection/selection-limits.d.ts +0 -1
  64. package/lib/client/selection/selection-limits.js +0 -1
  65. package/lib/client/selection/selection-normalizer.d.ts +0 -1
  66. package/lib/client/selection/selection-normalizer.js +0 -1
  67. package/lib/client/side-chat-controller.d.ts +0 -1
  68. package/lib/client/side-chat-controller.js +0 -1
  69. package/lib/client.js +1173 -8744
  70. package/lib/host/archived-fork-service.d.ts +0 -1
  71. package/lib/host/archived-fork-service.js +71 -26
  72. package/lib/host/index.d.ts +0 -1
  73. package/lib/host/index.js +0 -1
  74. package/lib/index.d.ts +0 -1
  75. package/lib/index.js +0 -1
  76. package/lib/remote.d.ts +0 -1
  77. package/lib/remote.js +0 -1
  78. package/lib/shared/archived-wire.d.ts +0 -1
  79. package/lib/shared/archived-wire.js +0 -1
  80. package/lib/shared/constants.d.ts +0 -1
  81. package/lib/shared/constants.js +0 -1
  82. package/lib/shared/contracts.d.ts +0 -1
  83. package/lib/shared/contracts.js +0 -1
  84. package/lib/shared/error-codes.d.ts +0 -1
  85. package/lib/shared/error-codes.js +0 -1
  86. package/lib/shared/observable.d.ts +0 -1
  87. package/lib/shared/observable.js +0 -1
  88. package/lib/typert.d.ts +0 -1
  89. package/lib/typert.js +64 -51
  90. package/package.json +60 -38
  91. package/lib/client/apply.d.ts.map +0 -1
  92. package/lib/client/apply.js.map +0 -1
  93. package/lib/client/contracts.d.ts.map +0 -1
  94. package/lib/client/contracts.js.map +0 -1
  95. package/lib/client/index.d.ts.map +0 -1
  96. package/lib/client/index.js.map +0 -1
  97. package/lib/client/model-preference.d.ts.map +0 -1
  98. package/lib/client/model-preference.js.map +0 -1
  99. package/lib/client/panel/SelectionQuote.d.ts.map +0 -1
  100. package/lib/client/panel/SelectionQuote.js.map +0 -1
  101. package/lib/client/panel/SendIcon.d.ts.map +0 -1
  102. package/lib/client/panel/SendIcon.js.map +0 -1
  103. package/lib/client/panel/SideChatBody.d.ts.map +0 -1
  104. package/lib/client/panel/SideChatBody.js.map +0 -1
  105. package/lib/client/panel/SideChatErrorState.d.ts.map +0 -1
  106. package/lib/client/panel/SideChatErrorState.js.map +0 -1
  107. package/lib/client/panel/SideChatHeader.d.ts.map +0 -1
  108. package/lib/client/panel/SideChatHeader.js.map +0 -1
  109. package/lib/client/panel/SideChatModelSelect.d.ts.map +0 -1
  110. package/lib/client/panel/SideChatModelSelect.js.map +0 -1
  111. package/lib/client/panel/SideChatPanel.d.ts.map +0 -1
  112. package/lib/client/panel/SideChatPanel.js.map +0 -1
  113. package/lib/client/panel/StopIcon.d.ts.map +0 -1
  114. package/lib/client/panel/StopIcon.js.map +0 -1
  115. package/lib/client/panel/messages.d.ts.map +0 -1
  116. package/lib/client/panel/messages.js.map +0 -1
  117. package/lib/client/panel/use-auto-growing-textarea.d.ts.map +0 -1
  118. package/lib/client/panel/use-auto-growing-textarea.js.map +0 -1
  119. package/lib/client/parent-composer/ParentConversationAnnotations.d.ts.map +0 -1
  120. package/lib/client/parent-composer/ParentConversationAnnotations.js.map +0 -1
  121. package/lib/client/parent-composer/add-to-conversation.d.ts.map +0 -1
  122. package/lib/client/parent-composer/add-to-conversation.js.map +0 -1
  123. package/lib/client/parent-composer/annotation-persistence.d.ts.map +0 -1
  124. package/lib/client/parent-composer/annotation-persistence.js.map +0 -1
  125. package/lib/client/parent-composer/referenced-conversation.d.ts.map +0 -1
  126. package/lib/client/parent-composer/referenced-conversation.js.map +0 -1
  127. package/lib/client/rc6/ArchivedConversation.d.ts.map +0 -1
  128. package/lib/client/rc6/ArchivedConversation.js.map +0 -1
  129. package/lib/client/rc6/Rc6SideChatOverlay.d.ts.map +0 -1
  130. package/lib/client/rc6/Rc6SideChatOverlay.js.map +0 -1
  131. package/lib/client/rc6/SideChatTool.d.ts.map +0 -1
  132. package/lib/client/rc6/SideChatTool.js.map +0 -1
  133. package/lib/client/rc6/context.d.ts.map +0 -1
  134. package/lib/client/rc6/context.js.map +0 -1
  135. package/lib/client/rc6/remote-adapter.d.ts.map +0 -1
  136. package/lib/client/rc6/remote-adapter.js.map +0 -1
  137. package/lib/client/rc6/sessions-adapter.d.ts.map +0 -1
  138. package/lib/client/rc6/sessions-adapter.js.map +0 -1
  139. package/lib/client/selection/ConversationAnnotationMarkers.d.ts.map +0 -1
  140. package/lib/client/selection/ConversationAnnotationMarkers.js.map +0 -1
  141. package/lib/client/selection/SelectionActions.d.ts.map +0 -1
  142. package/lib/client/selection/SelectionActions.js.map +0 -1
  143. package/lib/client/selection/selection-controller.d.ts.map +0 -1
  144. package/lib/client/selection/selection-controller.js.map +0 -1
  145. package/lib/client/selection/selection-limits.d.ts.map +0 -1
  146. package/lib/client/selection/selection-limits.js.map +0 -1
  147. package/lib/client/selection/selection-normalizer.d.ts.map +0 -1
  148. package/lib/client/selection/selection-normalizer.js.map +0 -1
  149. package/lib/client/side-chat-controller.d.ts.map +0 -1
  150. package/lib/client/side-chat-controller.js.map +0 -1
  151. package/lib/client.js.map +0 -1
  152. package/lib/host/archived-fork-service.d.ts.map +0 -1
  153. package/lib/host/archived-fork-service.js.map +0 -1
  154. package/lib/host/index.d.ts.map +0 -1
  155. package/lib/host/index.js.map +0 -1
  156. package/lib/index.d.ts.map +0 -1
  157. package/lib/index.js.map +0 -1
  158. package/lib/remote.d.ts.map +0 -1
  159. package/lib/remote.js.map +0 -1
  160. package/lib/shared/archived-wire.d.ts.map +0 -1
  161. package/lib/shared/archived-wire.js.map +0 -1
  162. package/lib/shared/constants.d.ts.map +0 -1
  163. package/lib/shared/constants.js.map +0 -1
  164. package/lib/shared/contracts.d.ts.map +0 -1
  165. package/lib/shared/contracts.js.map +0 -1
  166. package/lib/shared/error-codes.d.ts.map +0 -1
  167. package/lib/shared/error-codes.js.map +0 -1
  168. package/lib/shared/observable.d.ts.map +0 -1
  169. package/lib/shared/observable.js.map +0 -1
  170. package/lib/typert.d.ts.map +0 -1
  171. package/lib/typert.js.map +0 -1
@@ -0,0 +1,120 @@
1
+ import type { SessionFace as CurrentSessionFace } from '@deepseek-ai/dsh-api-session-controller/client';
2
+ import type { ChatSnapshot } from '@deepseek-ai/dsh-client-ui-chat/client';
3
+ import type { AssistantBlock, ConversationNode, PartialAssistant, RunningToolCall, ToolCallBlock } from '@deepseek-ai/dsh-client-ui-conversation/client';
4
+ import type { SessionId } from '@deepseek-ai/dsh-session/types';
5
+ import type { AskUserQuestionAnswer, AskUserQuestionItem } from '@deepseek-ai/dsh-user-questions/types';
6
+ export type { AssistantBlock, ConversationNode, RunningToolCall, ToolCallBlock, };
7
+ interface RuntimeFailure {
8
+ readonly code: string;
9
+ readonly message: string;
10
+ }
11
+ export type RuntimeResult<T = unknown> = {
12
+ readonly ok: true;
13
+ readonly value: T;
14
+ } | {
15
+ readonly ok: false;
16
+ readonly error: RuntimeFailure;
17
+ };
18
+ interface ObservableSnapshot<T> {
19
+ readonly getSnapshot: () => T;
20
+ readonly subscribe: (listener: () => void) => () => void;
21
+ }
22
+ export interface SideChatNodeStore {
23
+ get(key: string): {
24
+ readonly key: string;
25
+ readonly kind: string;
26
+ readonly anchorSeq: number;
27
+ readonly visibility: 'visible' | 'hidden';
28
+ readonly location: {
29
+ readonly kind: 'session' | 'unresolved';
30
+ } | {
31
+ readonly kind: 'turn';
32
+ readonly turn: {
33
+ readonly turn: number;
34
+ readonly status: 'open' | 'closed' | 'unknown';
35
+ };
36
+ } | {
37
+ readonly kind: 'step';
38
+ readonly turn: {
39
+ readonly turn: number;
40
+ readonly status: 'open' | 'closed' | 'unknown';
41
+ };
42
+ readonly step: {
43
+ readonly status: 'open' | 'closed' | 'unknown';
44
+ };
45
+ };
46
+ } | undefined;
47
+ }
48
+ export interface SideChatApprovalInteraction {
49
+ readonly kind: 'approval';
50
+ readonly key: string;
51
+ readonly toolName: string;
52
+ readonly reason?: string;
53
+ respond(decision: 'approve' | 'decline'): Promise<boolean>;
54
+ }
55
+ export interface SideChatQuestionInteraction {
56
+ readonly kind: 'question';
57
+ readonly key: string;
58
+ readonly questions: readonly AskUserQuestionItem[];
59
+ respond(answer: AskUserQuestionAnswer | null): Promise<boolean>;
60
+ }
61
+ export type SideChatPendingInteraction = SideChatApprovalInteraction | SideChatQuestionInteraction;
62
+ export interface SideChatQueuedMessage {
63
+ readonly id: string;
64
+ readonly placement: 'queued' | 'steering' | 'context';
65
+ readonly preview: string;
66
+ }
67
+ export interface SideChatConversationSnapshot {
68
+ readonly nodes: readonly ConversationNode[];
69
+ readonly turnEnds: ReadonlyMap<number, number>;
70
+ readonly partial: PartialAssistant | null;
71
+ readonly runningCalls: readonly RunningToolCall[];
72
+ readonly pending: readonly SideChatPendingInteraction[];
73
+ readonly queue: readonly SideChatQueuedMessage[];
74
+ readonly running: boolean;
75
+ readonly openState: 'cold' | 'loading' | 'open' | 'error';
76
+ readonly promptError: {
77
+ readonly error: RuntimeFailure;
78
+ } | null;
79
+ readonly lastAgentError: string | null;
80
+ readonly chatNodes: SideChatNodeStore;
81
+ }
82
+ /** Stable surface consumed by Side Chat on both the monolithic and split DSH clients. */
83
+ export interface SideChatConversationFace extends ObservableSnapshot<SideChatConversationSnapshot> {
84
+ readonly sessionId: SessionId;
85
+ prompt(content: unknown[], mode: 'queue' | 'steer'): Promise<RuntimeResult>;
86
+ updateQueue(itemId: string, action: unknown): Promise<RuntimeResult>;
87
+ cancel(): Promise<RuntimeResult>;
88
+ rename(title: string): Promise<RuntimeResult>;
89
+ open(): Promise<void>;
90
+ }
91
+ interface RuntimeSessionFace {
92
+ readonly sessionId: SessionId;
93
+ getSnapshot(): unknown;
94
+ subscribe(listener: () => void): () => void;
95
+ prompt(content: unknown[], mode: 'queue' | 'steer'): Promise<RuntimeResult>;
96
+ updateQueue(itemId: string, action: unknown): Promise<RuntimeResult>;
97
+ cancel(): Promise<RuntimeResult>;
98
+ rename(title: string): Promise<RuntimeResult>;
99
+ open?: () => Promise<void>;
100
+ }
101
+ /** Bridge DSH <=0.1.1's combined Session snapshot and 0.1.2's split stores. */
102
+ export declare class CompatibleConversationFace implements SideChatConversationFace {
103
+ private readonly session;
104
+ private readonly chat?;
105
+ private readonly pending?;
106
+ readonly sessionId: SessionId;
107
+ private cache;
108
+ constructor(session: RuntimeSessionFace, chat?: ObservableSnapshot<ChatSnapshot | undefined> | undefined, pending?: ObservableSnapshot<ReadonlyMap<SessionId, unknown>> | undefined);
109
+ readonly subscribe: (listener: () => void) => (() => void);
110
+ readonly getSnapshot: () => SideChatConversationSnapshot;
111
+ prompt(content: unknown[], mode: 'queue' | 'steer'): Promise<RuntimeResult>;
112
+ updateQueue(itemId: string, action: unknown): Promise<RuntimeResult>;
113
+ cancel(): Promise<RuntimeResult>;
114
+ rename(title: string): Promise<RuntimeResult>;
115
+ open(): Promise<void>;
116
+ }
117
+ export declare function compatibleConversationFace(session: CurrentSessionFace, sources?: {
118
+ readonly chat?: ObservableSnapshot<ChatSnapshot | undefined>;
119
+ readonly pending?: ObservableSnapshot<ReadonlyMap<SessionId, unknown>>;
120
+ }): CompatibleConversationFace;
@@ -0,0 +1,187 @@
1
+ const EMPTY_NODES = [];
2
+ const EMPTY_TURN_ENDS = new Map();
3
+ const EMPTY_RUNNING_CALLS = [];
4
+ const EMPTY_PENDING = [];
5
+ const EMPTY_NODE_STORE = { get: () => undefined };
6
+ function isLegacySnapshot(snapshot) {
7
+ return typeof snapshot === 'object'
8
+ && snapshot !== null
9
+ && Array.isArray(snapshot.nodes)
10
+ && Array.isArray(snapshot.pending);
11
+ }
12
+ function currentPending(source, sessionId) {
13
+ const pending = source?.get(sessionId);
14
+ if (typeof pending !== 'object' || pending === null)
15
+ return;
16
+ const candidate = pending;
17
+ if (candidate.kind === 'approval'
18
+ && typeof candidate.key === 'string'
19
+ && typeof candidate.toolName === 'string'
20
+ && typeof candidate.answer === 'function') {
21
+ return pending;
22
+ }
23
+ if ((candidate.kind === 'question' || candidate.kind === 'plan-review')
24
+ && typeof candidate.key === 'string'
25
+ && Array.isArray(candidate.questions)
26
+ && typeof candidate.answer === 'function'
27
+ && typeof candidate.cancel === 'function') {
28
+ return pending;
29
+ }
30
+ return undefined;
31
+ }
32
+ function normalizeLegacyPending(wait) {
33
+ if (wait.kind === 'approval') {
34
+ return {
35
+ kind: 'approval',
36
+ key: wait.key,
37
+ toolName: wait.payload.toolName,
38
+ ...(wait.payload.reason === undefined ? {} : { reason: wait.payload.reason }),
39
+ respond: async (decision) => {
40
+ const receipt = await wait.respond({
41
+ ok: true,
42
+ value: {
43
+ sessionId: wait.sessionId,
44
+ approvalId: wait.payload.approvalId,
45
+ outcome: decision === 'approve' ? 'allowed-once' : 'rejected',
46
+ },
47
+ });
48
+ return receipt.accepted;
49
+ },
50
+ };
51
+ }
52
+ return {
53
+ kind: 'question',
54
+ key: wait.key,
55
+ questions: wait.payload.questions,
56
+ respond: async (answer) => {
57
+ const receipt = await wait.respond(answer === null
58
+ ? {
59
+ ok: false,
60
+ error: { code: 'cancelled', message: 'Question cancelled.', details: {} },
61
+ }
62
+ : {
63
+ ok: true,
64
+ value: { sessionId: wait.sessionId, answer },
65
+ });
66
+ return receipt.accepted;
67
+ },
68
+ };
69
+ }
70
+ function normalizeCurrentPending(wait) {
71
+ if (wait.kind === 'approval') {
72
+ return {
73
+ kind: 'approval',
74
+ key: wait.key,
75
+ toolName: wait.toolName,
76
+ ...(wait.reason === undefined ? {} : { reason: wait.reason }),
77
+ respond: async (decision) => {
78
+ await wait.answer(decision === 'approve' ? 'allowed-once' : 'rejected');
79
+ return true;
80
+ },
81
+ };
82
+ }
83
+ return {
84
+ kind: 'question',
85
+ key: wait.key,
86
+ questions: wait.questions,
87
+ respond: async (answer) => {
88
+ if (answer === null)
89
+ await wait.cancel();
90
+ else
91
+ await wait.answer(answer);
92
+ return true;
93
+ },
94
+ };
95
+ }
96
+ /** Bridge DSH <=0.1.1's combined Session snapshot and 0.1.2's split stores. */
97
+ export class CompatibleConversationFace {
98
+ session;
99
+ chat;
100
+ pending;
101
+ sessionId;
102
+ cache;
103
+ constructor(session, chat, pending) {
104
+ this.session = session;
105
+ this.chat = chat;
106
+ this.pending = pending;
107
+ this.sessionId = session.sessionId;
108
+ }
109
+ subscribe = (listener) => {
110
+ const removers = [this.session.subscribe(listener)];
111
+ if (this.chat !== undefined)
112
+ removers.push(this.chat.subscribe(listener));
113
+ if (this.pending !== undefined)
114
+ removers.push(this.pending.subscribe(listener));
115
+ return () => {
116
+ for (const remove of removers)
117
+ remove();
118
+ };
119
+ };
120
+ getSnapshot = () => {
121
+ const session = this.session.getSnapshot();
122
+ if (isLegacySnapshot(session)) {
123
+ if (this.cache?.session === session)
124
+ return this.cache.value;
125
+ const value = {
126
+ nodes: session.nodes,
127
+ turnEnds: session.turnEnds,
128
+ partial: session.partial,
129
+ runningCalls: session.runningCalls,
130
+ pending: session.pending.map(normalizeLegacyPending),
131
+ queue: session.queue,
132
+ running: session.running,
133
+ openState: session.openState,
134
+ promptError: session.promptError,
135
+ lastAgentError: session.lastAgentError,
136
+ chatNodes: session.chat.nodes,
137
+ };
138
+ this.cache = { session, chat: undefined, pending: undefined, value };
139
+ return value;
140
+ }
141
+ const lifecycle = session;
142
+ const chat = this.chat?.getSnapshot();
143
+ const pending = this.pending?.getSnapshot();
144
+ const cached = this.cache;
145
+ if (cached !== undefined
146
+ && cached.session === session
147
+ && cached.chat === chat
148
+ && cached.pending === pending) {
149
+ return cached.value;
150
+ }
151
+ const legacy = chat?.legacy;
152
+ const wait = currentPending(pending, this.sessionId);
153
+ const value = {
154
+ nodes: legacy?.nodes ?? EMPTY_NODES,
155
+ turnEnds: legacy?.turnEnds ?? EMPTY_TURN_ENDS,
156
+ partial: legacy?.partial ?? null,
157
+ runningCalls: legacy?.runningCalls ?? EMPTY_RUNNING_CALLS,
158
+ pending: wait === undefined ? EMPTY_PENDING : [normalizeCurrentPending(wait)],
159
+ queue: lifecycle.queue,
160
+ running: lifecycle.running,
161
+ openState: lifecycle.openState,
162
+ promptError: lifecycle.promptError,
163
+ lastAgentError: lifecycle.lastAgentError,
164
+ chatNodes: chat?.nodes ?? EMPTY_NODE_STORE,
165
+ };
166
+ this.cache = { session, chat, pending, value };
167
+ return value;
168
+ };
169
+ prompt(content, mode) {
170
+ return this.session.prompt(content, mode);
171
+ }
172
+ updateQueue(itemId, action) {
173
+ return this.session.updateQueue(itemId, action);
174
+ }
175
+ cancel() {
176
+ return this.session.cancel();
177
+ }
178
+ rename(title) {
179
+ return this.session.rename(title);
180
+ }
181
+ async open() {
182
+ await this.session.open?.call(this.session);
183
+ }
184
+ }
185
+ export function compatibleConversationFace(session, sources = {}) {
186
+ return new CompatibleConversationFace(session, sources.chat, sources.pending);
187
+ }
@@ -1,14 +1,16 @@
1
- import type { ConversationSnapshot, SessionFace } from '@deepseek-ai/dsh-client-runtime/client';
2
1
  import type { ModelDirectory } from '@deepseek-ai/dsh-client-ui-model-selection/client';
3
2
  import type { SideChatClientSessions, SideChatSessionLease } from '../contracts.js';
4
3
  import type { ConversationSelection, SessionId, SideChatModelSelection } from '../../shared/contracts.js';
5
4
  import type { ParentComposerInputSnapshot } from '../parent-composer/add-to-conversation.js';
6
5
  import { type ReferencedSideChatConversation } from '../parent-composer/referenced-conversation.js';
7
6
  import type { Rc6ClientContext } from './context.js';
7
+ import { type SideChatConversationFace, type SideChatConversationSnapshot } from './runtime-compat.js';
8
8
  /** Adapter over rc.6's public SessionRuntime and exported concrete Session type. */
9
9
  export declare class Rc6SideChatSessions implements SideChatClientSessions {
10
10
  private readonly ctx;
11
11
  private readonly renamed;
12
+ private readonly faces;
13
+ private readonly parentInputs;
12
14
  private readonly annotationPersistence;
13
15
  private readonly modelPreferences;
14
16
  constructor(ctx: Rc6ClientContext);
@@ -24,6 +26,8 @@ export declare class Rc6SideChatSessions implements SideChatClientSessions {
24
26
  addSelectionToConversation(selection: ConversationSelection, comment?: string): boolean;
25
27
  /** Add one immutable Side Chat transcript to its parent Session's composer. */
26
28
  addSideChatToConversation(parentSessionId: SessionId, reference: ReferencedSideChatConversation): boolean;
29
+ /** Remove one existing unsent annotation from the aggregated occurrence. */
30
+ removeConversationAnnotation(annotationIndex: number): boolean;
27
31
  /** Update an existing unsent annotation without adding a duplicate passage. */
28
32
  updateConversationAnnotation(annotationIndex: number, comment?: string): boolean;
29
33
  /** Mirror or recover the current Session's unsent annotation occurrence. */
@@ -38,16 +42,18 @@ export declare class Rc6SideChatSessions implements SideChatClientSessions {
38
42
  readonly kind: 'status' | 'warning';
39
43
  readonly text: string;
40
44
  }): void;
41
- face(sessionId: SessionId): SessionFace | undefined;
45
+ face(sessionId: SessionId): SideChatConversationFace | undefined;
42
46
  title(sessionId: SessionId): string | undefined;
43
47
  cwd(sessionId: SessionId): string | undefined;
44
48
  modelDirectory(sessionId: SessionId): ModelDirectory | undefined;
45
49
  sideChatModelPreference(): SideChatModelSelection | undefined;
46
50
  rememberSideChatModelPreference(selection: SideChatModelSelection): void;
51
+ private adaptedFace;
47
52
  private currentParentInput;
53
+ private parentInput;
48
54
  private waitForBinding;
49
55
  }
50
- export declare function selectionDescriptor(snapshot: ConversationSnapshot, anchorKey: string): {
56
+ export declare function selectionDescriptor(snapshot: SideChatConversationSnapshot, anchorKey: string): {
51
57
  readonly nodeKey: string;
52
58
  readonly nodeKind: string;
53
59
  readonly turnKey: string;
@@ -56,4 +62,3 @@ export declare function selectionDescriptor(snapshot: ConversationSnapshot, anch
56
62
  readonly modelVisible: boolean;
57
63
  readonly settled: boolean;
58
64
  } | undefined;
59
- //# sourceMappingURL=sessions-adapter.d.ts.map
@@ -1,14 +1,17 @@
1
1
  import { SessionId as sideChatSessionId } from '../../shared/contracts.js';
2
- import { addSelectionToConversation as addSelectionToParentComposer, conversationAnnotations, removeConversationAnnotations as removeParentConversationAnnotations, updateConversationAnnotation as updateParentConversationAnnotation, } from '../parent-composer/add-to-conversation.js';
2
+ import { addSelectionToConversation as addSelectionToParentComposer, conversationAnnotations, removeConversationAnnotation as removeParentConversationAnnotation, removeConversationAnnotations as removeParentConversationAnnotations, updateConversationAnnotation as updateParentConversationAnnotation, } from '../parent-composer/add-to-conversation.js';
3
3
  import { ConversationAnnotationPersistence } from '../parent-composer/annotation-persistence.js';
4
4
  import { addReferencedSideChatToConversation as addReferencedSideChatToParentComposer, } from '../parent-composer/referenced-conversation.js';
5
5
  import { SideChatModelPreferences } from '../model-preference.js';
6
+ import { compatibleConversationFace, } from './runtime-compat.js';
6
7
  const BINDING_WAIT_MS = 8_000;
7
8
  function sideChatError(error, fallback) {
9
+ const badRequest = error.code === 'bad-request' || error.code === 'gateway/bad-request';
10
+ const missing = error.code === 'session-not-found' || error.code === 'session/not-found';
8
11
  return {
9
- code: error.code === 'session-not-found' ? 'side_chat_not_found' : fallback,
12
+ code: missing ? 'side_chat_not_found' : fallback,
10
13
  message: error.message,
11
- recoverable: error.code !== 'bad-request',
14
+ recoverable: !badRequest,
12
15
  };
13
16
  }
14
17
  function operationError(code, message) {
@@ -83,21 +86,12 @@ class Rc6SessionBinding {
83
86
  : { ok: false, error: sideChatError(result.error, 'side_chat_interrupt_failed') };
84
87
  }
85
88
  async respondApproval(interactionId, decision) {
86
- const wait = this.face.getSnapshot().pending
87
- .find(item => item.key === interactionId && item.kind === 'approval');
89
+ const wait = this.face.getSnapshot().pending.find((item) => item.key === interactionId && item.kind === 'approval');
88
90
  if (wait === undefined) {
89
91
  return { ok: false, error: operationError('invalid_request', 'The approval is no longer pending.') };
90
92
  }
91
93
  try {
92
- const receipt = await wait.respond({
93
- ok: true,
94
- value: {
95
- sessionId: wait.sessionId,
96
- approvalId: wait.payload.approvalId,
97
- outcome: decision === 'approve' ? 'allowed-once' : 'rejected',
98
- },
99
- });
100
- return receipt.accepted
94
+ return await wait.respond(decision)
101
95
  ? { ok: true }
102
96
  : { ok: false, error: operationError('transport_error', 'The approval response arrived too late.') };
103
97
  }
@@ -106,32 +100,21 @@ class Rc6SessionBinding {
106
100
  }
107
101
  }
108
102
  async respondQuestion(interactionId, answer) {
109
- const wait = this.face.getSnapshot().pending
110
- .find(item => item.key === interactionId && item.kind === 'question');
103
+ const wait = this.face.getSnapshot().pending.find((item) => item.key === interactionId && item.kind === 'question');
111
104
  if (wait === undefined) {
112
105
  return { ok: false, error: operationError('invalid_request', 'The question is no longer pending.') };
113
106
  }
114
107
  try {
115
- const result = answer === null
116
- ? {
117
- ok: false,
118
- error: { code: 'cancelled', message: 'Question cancelled.', details: {} },
119
- }
108
+ const normalized = answer === null
109
+ ? null
120
110
  : {
121
- ok: true,
122
- value: {
123
- sessionId: wait.sessionId,
124
- answer: {
125
- answers: answer.answers.map(item => ({
126
- id: item.id,
127
- selected: [...item.selected],
128
- ...(item.custom === undefined ? {} : { custom: item.custom }),
129
- })),
130
- },
131
- },
111
+ answers: answer.answers.map(item => ({
112
+ id: item.id,
113
+ selected: [...item.selected],
114
+ ...(item.custom === undefined ? {} : { custom: item.custom }),
115
+ })),
132
116
  };
133
- const receipt = await wait.respond(result);
134
- return receipt.accepted
117
+ return await wait.respond(normalized)
135
118
  ? { ok: true }
136
119
  : { ok: false, error: operationError('transport_error', 'The question response arrived too late.') };
137
120
  }
@@ -144,6 +127,8 @@ class Rc6SessionBinding {
144
127
  export class Rc6SideChatSessions {
145
128
  ctx;
146
129
  renamed = new Set();
130
+ faces = new Map();
131
+ parentInputs = new WeakMap();
147
132
  annotationPersistence = new ConversationAnnotationPersistence();
148
133
  modelPreferences = new SideChatModelPreferences();
149
134
  constructor(ctx) {
@@ -179,17 +164,17 @@ export class Rc6SideChatSessions {
179
164
  return current === undefined ? undefined : sideChatSessionId(current);
180
165
  }
181
166
  lastCompletedSeq(parentSessionId) {
182
- const snapshot = this.ctx.sessions.binding(dshSessionId(parentSessionId))?.session.getSnapshot();
167
+ const snapshot = this.face(parentSessionId)?.getSnapshot();
183
168
  return snapshot === undefined ? undefined : latestCompleted(snapshot);
184
169
  }
185
170
  selectionIsCurrent(selection) {
186
171
  if (this.currentSessionId() !== selection.parentSessionId)
187
172
  return false;
188
- const snapshot = this.ctx.sessions.binding(dshSessionId(selection.parentSessionId))?.session.getSnapshot();
173
+ const snapshot = this.face(selection.parentSessionId)?.getSnapshot();
189
174
  if (snapshot === undefined)
190
175
  return false;
191
176
  return selection.fragments.every((fragment) => {
192
- const node = snapshot.chat.nodes.get(fragment.nodeKey);
177
+ const node = snapshot.chatNodes.get(fragment.nodeKey);
193
178
  return node !== undefined
194
179
  && node.visibility === 'visible'
195
180
  && node.kind === fragment.nodeKind
@@ -210,12 +195,23 @@ export class Rc6SideChatSessions {
210
195
  /** Add one immutable Side Chat transcript to its parent Session's composer. */
211
196
  addSideChatToConversation(parentSessionId, reference) {
212
197
  const scope = this.ctx.sessions.scope(dshSessionId(parentSessionId));
213
- const input = scope === undefined ? undefined : this.ctx.conversation.input.for(scope);
198
+ const input = scope === undefined ? undefined : this.parentInput(scope);
214
199
  if (input === undefined || !addReferencedSideChatToParentComposer(input, reference))
215
200
  return false;
216
201
  this.annotationPersistence.reconcile(parentSessionId, input);
217
202
  return true;
218
203
  }
204
+ /** Remove one existing unsent annotation from the aggregated occurrence. */
205
+ removeConversationAnnotation(annotationIndex) {
206
+ const sessionId = this.currentSessionId();
207
+ const input = this.currentParentInput();
208
+ if (sessionId === undefined
209
+ || input === undefined
210
+ || !removeParentConversationAnnotation(input, annotationIndex))
211
+ return false;
212
+ this.annotationPersistence.reconcile(sessionId, input);
213
+ return true;
214
+ }
219
215
  /** Update an existing unsent annotation without adding a duplicate passage. */
220
216
  updateConversationAnnotation(annotationIndex, comment) {
221
217
  const sessionId = this.currentSessionId();
@@ -253,15 +249,15 @@ export class Rc6SideChatSessions {
253
249
  }
254
250
  async retain(sessionId) {
255
251
  const binding = await this.waitForBinding(dshSessionId(sessionId));
256
- const concrete = binding.session;
257
- await concrete.open();
252
+ const face = this.adaptedFace(binding.session);
253
+ await face.open();
258
254
  if (!this.renamed.has(sessionId)) {
259
255
  this.renamed.add(sessionId);
260
256
  const parentTitle = this.ctx.sessions.list.getSnapshot().byId[dshSessionId(sessionId)]?.displayTitle;
261
257
  const title = parentTitle === undefined ? 'Side Chat' : `Side Chat · ${parentTitle}`;
262
- await binding.session.rename(title.slice(0, 160)).catch(() => undefined);
258
+ await face.rename(title.slice(0, 160)).catch(() => undefined);
263
259
  }
264
- const adapted = new Rc6SessionBinding(binding.session);
260
+ const adapted = new Rc6SessionBinding(face);
265
261
  return { sessionId, binding: adapted, release: () => { } };
266
262
  }
267
263
  async openSession(sessionId) {
@@ -272,7 +268,8 @@ export class Rc6SideChatSessions {
272
268
  console[method](`[dsh-side-chat] ${message.text}`);
273
269
  }
274
270
  face(sessionId) {
275
- return this.ctx.sessions.binding(dshSessionId(sessionId))?.session;
271
+ const source = this.ctx.sessions.binding(dshSessionId(sessionId))?.session;
272
+ return source === undefined ? undefined : this.adaptedFace(source);
276
273
  }
277
274
  title(sessionId) {
278
275
  return this.ctx.sessions.list.getSnapshot().byId[dshSessionId(sessionId)]?.displayTitle;
@@ -294,12 +291,44 @@ export class Rc6SideChatSessions {
294
291
  rememberSideChatModelPreference(selection) {
295
292
  this.modelPreferences.set(selection);
296
293
  }
294
+ adaptedFace(source) {
295
+ const existing = this.faces.get(source.sessionId);
296
+ if (existing?.source === source)
297
+ return existing.compatible;
298
+ const uiConversation = this.ctx.get('uiConversation');
299
+ const uiSession = this.ctx.get('uiSession');
300
+ const chat = uiConversation?.binding(source.sessionId).target('chat');
301
+ const pending = uiSession?.pendingInteractions;
302
+ const compatible = compatibleConversationFace(source, {
303
+ ...(chat === undefined ? {} : { chat }),
304
+ ...(pending === undefined ? {} : { pending }),
305
+ });
306
+ this.faces.set(source.sessionId, { source, compatible });
307
+ return compatible;
308
+ }
297
309
  currentParentInput() {
298
310
  const sessionId = this.currentSessionId();
299
311
  if (sessionId === undefined)
300
312
  return;
301
313
  const scope = this.ctx.sessions.scope(dshSessionId(sessionId));
302
- return scope === undefined ? undefined : this.ctx.conversation.input.for(scope);
314
+ return scope === undefined ? undefined : this.parentInput(scope);
315
+ }
316
+ parentInput(scope) {
317
+ const source = this.ctx.conversation.input.for(scope);
318
+ if (source === undefined || this.ctx.get('uiConversation') === undefined)
319
+ return source;
320
+ const existing = this.parentInputs.get(source);
321
+ if (existing !== undefined)
322
+ return existing;
323
+ const adapted = {
324
+ referenceMode: 'lexical',
325
+ state: source.state,
326
+ setDraft: text => { source.setDraft(text); },
327
+ insertReference: (reference, span) => source.insertReference(reference, span),
328
+ replaceText: (text, span) => scope.bail(scope, 'slash/input-insert-text', { text, span }) === true,
329
+ };
330
+ this.parentInputs.set(source, adapted);
331
+ return adapted;
303
332
  }
304
333
  waitForBinding(sessionId) {
305
334
  const immediate = this.ctx.sessions.binding(sessionId);
@@ -331,7 +360,7 @@ export class Rc6SideChatSessions {
331
360
  }
332
361
  }
333
362
  export function selectionDescriptor(snapshot, anchorKey) {
334
- const node = snapshot.chat.nodes.get(anchorKey);
363
+ const node = snapshot.chatNodes.get(anchorKey);
335
364
  if (node === undefined || node.visibility !== 'visible')
336
365
  return undefined;
337
366
  const source = node.kind === 'user' || node.kind === 'steering'
@@ -356,4 +385,3 @@ export function selectionDescriptor(snapshot, anchorKey) {
356
385
  settled: locationSettled(node.location),
357
386
  };
358
387
  }
359
- //# sourceMappingURL=sessions-adapter.js.map
@@ -6,4 +6,3 @@ export declare function ConversationAnnotationMarkers({ annotations, activeAnnot
6
6
  readonly activeAnnotationIndex?: number;
7
7
  readonly onEdit: (annotation: ConversationSelectionAnnotation, selection: ConversationSelection) => void;
8
8
  }): (import("react/jsx-runtime").JSX.Element | null)[];
9
- //# sourceMappingURL=ConversationAnnotationMarkers.d.ts.map
@@ -238,4 +238,3 @@ export function ConversationAnnotationMarkers({ annotations, activeAnnotationInd
238
238
  }, onClick: activate, children: badge }, `${annotation.selection.parentSessionId}:${annotation.selection.fragments[0]?.nodeKey ?? ''}:${String(annotation.annotationIndex)}`));
239
239
  });
240
240
  }
241
- //# sourceMappingURL=ConversationAnnotationMarkers.js.map
@@ -13,6 +13,8 @@ export interface SelectionActionsProps {
13
13
  readonly onMoreDetails: (selection: ConversationSelection) => void;
14
14
  readonly onAskInSideChat: (selection: ConversationSelection) => void;
15
15
  readonly onAnnotationEditorChange?: (open: boolean) => void;
16
+ /** Explicit destructive action offered only while editing a persisted annotation. */
17
+ readonly onRemoveAnnotation?: () => void;
16
18
  readonly onDismiss: () => void;
17
19
  }
18
20
  export declare function calculateSelectionActionsPosition(rect: ConversationSelection['rect'], size: {
@@ -21,9 +23,10 @@ export declare function calculateSelectionActionsPosition(rect: ConversationSele
21
23
  }, touch: boolean, viewport?: {
22
24
  readonly width: number;
23
25
  readonly height: number;
26
+ readonly offsetLeft?: number;
27
+ readonly offsetTop?: number;
24
28
  }): {
25
29
  readonly left: number;
26
30
  readonly top: number;
27
31
  };
28
- export declare function SelectionActions({ selection, touchInteraction, askDisabledReason, annotationNumber, annotationEditor, onAddToChat, onMoreDetails, onAskInSideChat, onAnnotationEditorChange, onDismiss, }: SelectionActionsProps): import("react/jsx-runtime").JSX.Element;
29
- //# sourceMappingURL=SelectionActions.d.ts.map
32
+ export declare function SelectionActions({ selection, touchInteraction, askDisabledReason, annotationNumber, annotationEditor, onAddToChat, onMoreDetails, onAskInSideChat, onAnnotationEditorChange, onRemoveAnnotation, onDismiss, }: SelectionActionsProps): import("react/jsx-runtime").JSX.Element;