@ahggg/dsh-side-chat 0.7.2 → 1.0.0

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 (185) hide show
  1. package/README.md +16 -13
  2. package/README.zh-CN.md +16 -13
  3. package/lib/client/apply.d.ts +0 -1
  4. package/lib/client/apply.js +48 -33
  5. package/lib/client/contracts.d.ts +3 -59
  6. package/lib/client/contracts.js +0 -1
  7. package/lib/client/dsh/ReadOnlyConversation.d.ts +10 -0
  8. package/lib/client/dsh/ReadOnlyConversation.js +91 -0
  9. package/lib/client/dsh/SideChatOverlay.d.ts +7 -0
  10. package/lib/client/{rc6/Rc6SideChatOverlay.js → dsh/SideChatOverlay.js} +26 -57
  11. package/lib/client/{rc6 → dsh}/context.d.ts +7 -3
  12. package/lib/client/dsh/context.js +1 -0
  13. package/lib/client/dsh/conversation-store.d.ts +22 -0
  14. package/lib/client/dsh/conversation-store.js +19 -0
  15. package/lib/client/dsh/primitive-labels.d.ts +2 -0
  16. package/lib/client/dsh/primitive-labels.js +4 -0
  17. package/lib/client/{rc6 → dsh}/remote-adapter.d.ts +2 -3
  18. package/lib/client/dsh/remote-adapter.js +22 -0
  19. package/lib/client/dsh/sessions-adapter.d.ts +56 -0
  20. package/lib/client/dsh/sessions-adapter.js +185 -0
  21. package/lib/client/index.d.ts +2 -3
  22. package/lib/client/index.js +0 -1
  23. package/lib/client/model-preference.d.ts +0 -1
  24. package/lib/client/model-preference.js +0 -1
  25. package/lib/client/panel/SelectionQuote.d.ts +0 -1
  26. package/lib/client/panel/SelectionQuote.js +8 -2
  27. package/lib/client/panel/SendIcon.d.ts +0 -1
  28. package/lib/client/panel/SendIcon.js +0 -1
  29. package/lib/client/panel/SideChatBody.d.ts +0 -1
  30. package/lib/client/panel/SideChatBody.js +0 -1
  31. package/lib/client/panel/SideChatErrorState.d.ts +0 -1
  32. package/lib/client/panel/SideChatErrorState.js +1 -2
  33. package/lib/client/panel/SideChatHeader.d.ts +0 -1
  34. package/lib/client/panel/SideChatHeader.js +0 -1
  35. package/lib/client/panel/SideChatModelSelect.d.ts +0 -1
  36. package/lib/client/panel/SideChatModelSelect.js +37 -19
  37. package/lib/client/panel/SideChatPanel.d.ts +0 -1
  38. package/lib/client/panel/SideChatPanel.js +12 -6
  39. package/lib/client/panel/StopIcon.d.ts +0 -1
  40. package/lib/client/panel/StopIcon.js +0 -1
  41. package/lib/client/panel/messages.d.ts +1 -2
  42. package/lib/client/panel/messages.js +8 -9
  43. package/lib/client/panel/use-auto-growing-textarea.d.ts +0 -1
  44. package/lib/client/panel/use-auto-growing-textarea.js +0 -1
  45. package/lib/client/parent-composer/ParentConversationAnnotations.d.ts +3 -3
  46. package/lib/client/parent-composer/ParentConversationAnnotations.js +71 -28
  47. package/lib/client/parent-composer/add-to-conversation.d.ts +14 -29
  48. package/lib/client/parent-composer/add-to-conversation.js +134 -457
  49. package/lib/client/parent-composer/annotation-persistence.d.ts +8 -9
  50. package/lib/client/parent-composer/annotation-persistence.js +106 -103
  51. package/lib/client/parent-composer/composer-reference.d.ts +19 -48
  52. package/lib/client/parent-composer/composer-reference.js +26 -46
  53. package/lib/client/parent-composer/referenced-conversation.d.ts +5 -8
  54. package/lib/client/parent-composer/referenced-conversation.js +27 -61
  55. package/lib/client/selection/ConversationAnnotationMarkers.d.ts +0 -1
  56. package/lib/client/selection/ConversationAnnotationMarkers.js +5 -2
  57. package/lib/client/selection/SelectionActions.d.ts +0 -1
  58. package/lib/client/selection/SelectionActions.js +2 -2
  59. package/lib/client/selection/conversation-dom.d.ts +5 -0
  60. package/lib/client/selection/conversation-dom.js +24 -0
  61. package/lib/client/selection/selection-controller.d.ts +1 -2
  62. package/lib/client/selection/selection-controller.js +7 -4
  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 +1 -2
  67. package/lib/client/side-chat-controller.d.ts +28 -42
  68. package/lib/client/side-chat-controller.js +245 -338
  69. package/lib/client.js +1202 -8951
  70. package/lib/host/index.d.ts +1 -2
  71. package/lib/host/index.js +1 -2
  72. package/lib/host/read-only-chat-service.d.ts +30 -0
  73. package/lib/host/read-only-chat-service.js +314 -0
  74. package/lib/index.d.ts +16 -9
  75. package/lib/index.js +34 -14
  76. package/lib/remote.d.ts +23 -15
  77. package/lib/remote.js +2 -6
  78. package/lib/shared/constants.d.ts +0 -14
  79. package/lib/shared/constants.js +0 -14
  80. package/lib/shared/contracts.d.ts +52 -20
  81. package/lib/shared/contracts.js +2 -4
  82. package/lib/shared/error-codes.d.ts +1 -2
  83. package/lib/shared/error-codes.js +2 -3
  84. package/lib/shared/observable.d.ts +0 -1
  85. package/lib/shared/observable.js +0 -1
  86. package/lib/shared/{archived-wire.d.ts → side-chat-wire.d.ts} +109 -21
  87. package/lib/shared/side-chat-wire.js +34 -0
  88. package/lib/typert.d.ts +3 -69
  89. package/lib/typert.js +120 -51
  90. package/package.json +80 -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/composer-reference.d.ts.map +0 -1
  126. package/lib/client/parent-composer/composer-reference.js.map +0 -1
  127. package/lib/client/parent-composer/referenced-conversation.d.ts.map +0 -1
  128. package/lib/client/parent-composer/referenced-conversation.js.map +0 -1
  129. package/lib/client/rc6/ArchivedConversation.d.ts +0 -15
  130. package/lib/client/rc6/ArchivedConversation.d.ts.map +0 -1
  131. package/lib/client/rc6/ArchivedConversation.js +0 -230
  132. package/lib/client/rc6/ArchivedConversation.js.map +0 -1
  133. package/lib/client/rc6/Rc6SideChatOverlay.d.ts +0 -8
  134. package/lib/client/rc6/Rc6SideChatOverlay.d.ts.map +0 -1
  135. package/lib/client/rc6/Rc6SideChatOverlay.js.map +0 -1
  136. package/lib/client/rc6/SideChatTool.d.ts +0 -23
  137. package/lib/client/rc6/SideChatTool.d.ts.map +0 -1
  138. package/lib/client/rc6/SideChatTool.js +0 -395
  139. package/lib/client/rc6/SideChatTool.js.map +0 -1
  140. package/lib/client/rc6/context.d.ts.map +0 -1
  141. package/lib/client/rc6/context.js +0 -2
  142. package/lib/client/rc6/context.js.map +0 -1
  143. package/lib/client/rc6/remote-adapter.d.ts.map +0 -1
  144. package/lib/client/rc6/remote-adapter.js +0 -33
  145. package/lib/client/rc6/remote-adapter.js.map +0 -1
  146. package/lib/client/rc6/sessions-adapter.d.ts +0 -61
  147. package/lib/client/rc6/sessions-adapter.d.ts.map +0 -1
  148. package/lib/client/rc6/sessions-adapter.js +0 -370
  149. package/lib/client/rc6/sessions-adapter.js.map +0 -1
  150. package/lib/client/selection/ConversationAnnotationMarkers.d.ts.map +0 -1
  151. package/lib/client/selection/ConversationAnnotationMarkers.js.map +0 -1
  152. package/lib/client/selection/SelectionActions.d.ts.map +0 -1
  153. package/lib/client/selection/SelectionActions.js.map +0 -1
  154. package/lib/client/selection/selection-controller.d.ts.map +0 -1
  155. package/lib/client/selection/selection-controller.js.map +0 -1
  156. package/lib/client/selection/selection-limits.d.ts.map +0 -1
  157. package/lib/client/selection/selection-limits.js.map +0 -1
  158. package/lib/client/selection/selection-normalizer.d.ts.map +0 -1
  159. package/lib/client/selection/selection-normalizer.js.map +0 -1
  160. package/lib/client/side-chat-controller.d.ts.map +0 -1
  161. package/lib/client/side-chat-controller.js.map +0 -1
  162. package/lib/client.js.map +0 -1
  163. package/lib/host/archived-fork-service.d.ts +0 -29
  164. package/lib/host/archived-fork-service.d.ts.map +0 -1
  165. package/lib/host/archived-fork-service.js +0 -264
  166. package/lib/host/archived-fork-service.js.map +0 -1
  167. package/lib/host/index.d.ts.map +0 -1
  168. package/lib/host/index.js.map +0 -1
  169. package/lib/index.d.ts.map +0 -1
  170. package/lib/index.js.map +0 -1
  171. package/lib/remote.d.ts.map +0 -1
  172. package/lib/remote.js.map +0 -1
  173. package/lib/shared/archived-wire.d.ts.map +0 -1
  174. package/lib/shared/archived-wire.js +0 -48
  175. package/lib/shared/archived-wire.js.map +0 -1
  176. package/lib/shared/constants.d.ts.map +0 -1
  177. package/lib/shared/constants.js.map +0 -1
  178. package/lib/shared/contracts.d.ts.map +0 -1
  179. package/lib/shared/contracts.js.map +0 -1
  180. package/lib/shared/error-codes.d.ts.map +0 -1
  181. package/lib/shared/error-codes.js.map +0 -1
  182. package/lib/shared/observable.d.ts.map +0 -1
  183. package/lib/shared/observable.js.map +0 -1
  184. package/lib/typert.d.ts.map +0 -1
  185. package/lib/typert.js.map +0 -1
@@ -1,10 +1,13 @@
1
1
  import type { Context } from '@deepseek-ai/cordis';
2
2
  import type { ClientRemote } from '@deepseek-ai/dsh-api-remotes/client';
3
- import type { ISessions, SlotRegistry } from '@deepseek-ai/dsh-client-runtime/client';
3
+ import type { ISessions } from '@deepseek-ai/dsh-api-session-controller/client';
4
+ import type { UiConversation } from '@deepseek-ai/dsh-client-ui-conversation/client';
4
5
  import type { ModelDirectoryResolver } from '@deepseek-ai/dsh-client-ui-model-selection/client';
6
+ import type { SlotRegistry } from '@deepseek-ai/dsh-client-ui-renderer/client';
7
+ import type { UiWorkspace } from '@deepseek-ai/dsh-client-ui-workspace/client';
5
8
  import type { ParentConversationService, SelectionReferenceSource } from '../parent-composer/add-to-conversation.js';
6
9
  /** Browser-only Cordis view for a package that also compiles the Host half. */
7
- export type Rc6ClientContext = Omit<Context, 'conversation' | 'inputTriggers' | 'modelDirectories' | 'remote' | 'sessions' | 'slots'> & {
10
+ export type DshClientContext = Omit<Context, 'conversation' | 'inputTriggers' | 'modelDirectories' | 'remote' | 'sessions' | 'slots' | 'uiConversation' | 'uiWorkspace'> & {
8
11
  readonly conversation: ParentConversationService;
9
12
  readonly inputTriggers: {
10
13
  registerSource(source: SelectionReferenceSource): () => void;
@@ -13,5 +16,6 @@ export type Rc6ClientContext = Omit<Context, 'conversation' | 'inputTriggers' |
13
16
  readonly remote: ClientRemote;
14
17
  readonly sessions: ISessions;
15
18
  readonly slots: SlotRegistry;
19
+ readonly uiWorkspace: UiWorkspace;
20
+ readonly uiConversation: Pick<UiConversation, 'binding'>;
16
21
  };
17
- //# sourceMappingURL=context.d.ts.map
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1,22 @@
1
+ import type { ChatSnapshot } from '@deepseek-ai/dsh-client-ui-chat/client';
2
+ export type SideChatNodeStore = ChatSnapshot['nodes'];
3
+ export interface ParentConversationSnapshot {
4
+ readonly turnEnds: ReadonlyMap<number, number>;
5
+ readonly chatNodes: Pick<SideChatNodeStore, 'get'>;
6
+ }
7
+ export interface ParentConversationFace {
8
+ getSnapshot(): ParentConversationSnapshot;
9
+ subscribe(listener: () => void): () => void;
10
+ }
11
+ /** Read-only parent Chat projection, used only for selection anchors and turn boundaries. */
12
+ export declare class DshParentConversation implements ParentConversationFace {
13
+ private readonly chat;
14
+ private source;
15
+ private snapshot;
16
+ constructor(chat: {
17
+ getSnapshot(): ChatSnapshot | undefined;
18
+ subscribe(listener: () => void): () => void;
19
+ });
20
+ subscribe: (listener: () => void) => (() => void);
21
+ getSnapshot: () => ParentConversationSnapshot;
22
+ }
@@ -0,0 +1,19 @@
1
+ const EMPTY = { turnEnds: new Map(), chatNodes: { get: () => undefined } };
2
+ /** Read-only parent Chat projection, used only for selection anchors and turn boundaries. */
3
+ export class DshParentConversation {
4
+ chat;
5
+ source;
6
+ snapshot = EMPTY;
7
+ constructor(chat) {
8
+ this.chat = chat;
9
+ }
10
+ subscribe = (listener) => this.chat.subscribe(listener);
11
+ getSnapshot = () => {
12
+ const source = this.chat.getSnapshot();
13
+ if (source !== this.source) {
14
+ this.source = source;
15
+ this.snapshot = source === undefined ? EMPTY : { turnEnds: source.legacy.turnEnds, chatNodes: source.nodes };
16
+ }
17
+ return this.snapshot;
18
+ };
19
+ }
@@ -0,0 +1,2 @@
1
+ import type { MarkdownLabels } from '@deepseek-ai/dsh-client-ui-primitives';
2
+ export declare const MARKDOWN_LABELS: MarkdownLabels;
@@ -0,0 +1,4 @@
1
+ export const MARKDOWN_LABELS = {
2
+ code: { copyLabel: 'Copy', copiedLabel: 'Copied' },
3
+ footnotes: 'Footnotes',
4
+ };
@@ -1,7 +1,6 @@
1
1
  import type { SideChatRemote } from '../../shared/contracts.js';
2
- import type { Rc6ClientContext } from './context.js';
3
- export declare function mountArchivedRemote(ctx: Rc6ClientContext): Promise<{
2
+ import type { DshClientContext } from './context.js';
3
+ export declare function mountSideChatRemote(ctx: DshClientContext): Promise<{
4
4
  readonly remote: SideChatRemote;
5
5
  readonly dispose: () => Promise<void>;
6
6
  }>;
7
- //# sourceMappingURL=remote-adapter.d.ts.map
@@ -0,0 +1,22 @@
1
+ import TYPERT_REMOTE from '../../remote.js';
2
+ function remoteFailure(error) {
3
+ const code = error.code;
4
+ const badRequest = code === 'bad-request' || code === 'gateway/bad-request';
5
+ return { code: badRequest ? 'invalid_request' : 'transport_error',
6
+ message: error.message || 'The Side Chat RPC failed.', recoverable: !badRequest };
7
+ }
8
+ async function unwrap(result) {
9
+ const value = await result;
10
+ return value.ok ? value.value : { ok: false, error: remoteFailure(value.error) };
11
+ }
12
+ export async function mountSideChatRemote(ctx) {
13
+ const dispose = await ctx.remote.$mount(TYPERT_REMOTE);
14
+ const rpc = ctx.get('remote.sideChat');
15
+ return { remote: {
16
+ create: request => unwrap(rpc.create(request)),
17
+ selectModel: request => unwrap(rpc.selectModel(request)),
18
+ stream: request => rpc.stream(request),
19
+ cancel: request => unwrap(rpc.cancel(request)),
20
+ close: request => unwrap(rpc.close(request)),
21
+ }, dispose };
22
+ }
@@ -0,0 +1,56 @@
1
+ import type { ModelDirectory } from '@deepseek-ai/dsh-client-ui-model-selection/client';
2
+ import type { SideChatClientSessions } from '../contracts.js';
3
+ import { SessionId, type ConversationSelection, type SideChatModelSelection } from '../../shared/contracts.js';
4
+ import { type ParentComposerInputSnapshot } from '../parent-composer/add-to-conversation.js';
5
+ import { type ReferencedSideChatConversation } from '../parent-composer/referenced-conversation.js';
6
+ import type { DshClientContext } from './context.js';
7
+ import { type ParentConversationFace, type ParentConversationSnapshot } from './conversation-store.js';
8
+ declare module '@deepseek-ai/dsh-api-session-controller/client' {
9
+ interface SessionReferenceSourceMap {
10
+ sideChat: unknown;
11
+ }
12
+ }
13
+ /** The only Session touched by the plugin is the parent: read its Chat, retain its editor, and insert explicit references. */
14
+ export declare class DshSideChatSessions implements SideChatClientSessions {
15
+ private readonly ctx;
16
+ private readonly faces;
17
+ private readonly parentInputs;
18
+ private readonly annotationPersistence;
19
+ private readonly modelPreferences;
20
+ constructor(ctx: DshClientContext);
21
+ readonly subscribeList: (listener: () => void) => (() => void);
22
+ readonly subscribeConversationInput: (listener: () => void) => (() => void);
23
+ readonly currentConversationInputSnapshot: () => ParentComposerInputSnapshot | undefined;
24
+ currentSessionId(): SessionId | undefined;
25
+ lastCompletedSeq(parentSessionId: SessionId): number | undefined;
26
+ selectionIsCurrent(selection: ConversationSelection): boolean;
27
+ addSelectionToConversation(selection: ConversationSelection, comment?: string): boolean;
28
+ addSideChatToConversation(parentSessionId: SessionId, reference: ReferencedSideChatConversation): boolean;
29
+ removeConversationAnnotation(index: number): boolean;
30
+ updateConversationAnnotation(index: number, comment?: string): boolean;
31
+ reconcileConversationAnnotationPersistence(): void;
32
+ nextConversationAnnotationNumber(): number;
33
+ removeConversationAnnotations(id?: SessionId | undefined): boolean;
34
+ retainParent(id: SessionId): () => void;
35
+ openSession(id: SessionId): Promise<void>;
36
+ notify(message: {
37
+ readonly kind: 'status' | 'warning';
38
+ readonly text: string;
39
+ }): void;
40
+ face(id: SessionId): ParentConversationFace | undefined;
41
+ title(id: SessionId): string | undefined;
42
+ modelDirectory(id: SessionId): ModelDirectory | undefined;
43
+ sideChatModelPreference(): SideChatModelSelection | undefined;
44
+ rememberSideChatModelPreference(model: SideChatModelSelection): void;
45
+ private currentParentInput;
46
+ private parentInput;
47
+ }
48
+ export declare function selectionDescriptor(snapshot: ParentConversationSnapshot, anchorKey: string): {
49
+ readonly nodeKey: string;
50
+ readonly nodeKind: string;
51
+ readonly turnKey: string;
52
+ readonly seq: number;
53
+ readonly source: 'user' | 'assistant' | 'context' | 'code';
54
+ readonly modelVisible: boolean;
55
+ readonly settled: boolean;
56
+ } | undefined;
@@ -0,0 +1,185 @@
1
+ import { SessionId } from '../../shared/contracts.js';
2
+ import { addSelectionToConversation as addSelection, conversationAnnotations, removeConversationAnnotation as removeAnnotation, removeConversationAnnotations as removeAnnotations, updateConversationAnnotation as updateAnnotation, } from '../parent-composer/add-to-conversation.js';
3
+ import { ConversationAnnotationPersistence } from '../parent-composer/annotation-persistence.js';
4
+ import { addReferencedSideChatToConversation } from '../parent-composer/referenced-conversation.js';
5
+ import { SideChatModelPreferences } from '../model-preference.js';
6
+ import { DshParentConversation } from './conversation-store.js';
7
+ function dshId(id) { return id; }
8
+ function locationSettled(location) {
9
+ if (location.kind === 'turn')
10
+ return location.turn.status === 'closed';
11
+ if (location.kind === 'step')
12
+ return location.turn.status === 'closed' && location.step.status === 'closed';
13
+ return false;
14
+ }
15
+ /** The only Session touched by the plugin is the parent: read its Chat, retain its editor, and insert explicit references. */
16
+ export class DshSideChatSessions {
17
+ ctx;
18
+ faces = new WeakMap();
19
+ parentInputs = new WeakMap();
20
+ annotationPersistence = new ConversationAnnotationPersistence();
21
+ modelPreferences = new SideChatModelPreferences();
22
+ constructor(ctx) {
23
+ this.ctx = ctx;
24
+ }
25
+ subscribeList = (listener) => this.ctx.sessions.list.subscribe(listener);
26
+ subscribeConversationInput = (listener) => {
27
+ let input;
28
+ let removeInput = () => { };
29
+ const bind = () => {
30
+ const next = this.currentParentInput();
31
+ if (next === input)
32
+ return;
33
+ removeInput();
34
+ input = next;
35
+ removeInput = input?.state.subscribe(listener) ?? (() => { });
36
+ };
37
+ bind();
38
+ const removeList = this.ctx.sessions.list.subscribe(() => { bind(); listener(); });
39
+ return () => { removeList(); removeInput(); };
40
+ };
41
+ currentConversationInputSnapshot = () => this.currentParentInput()?.state.getSnapshot();
42
+ currentSessionId() {
43
+ const current = Object.entries(this.ctx.sessions.list.getSnapshot().byId)
44
+ .find(([, summary]) => (summary.retainedBy.mainView ?? 0) > 0)?.[0];
45
+ return current === undefined ? undefined : SessionId(current);
46
+ }
47
+ lastCompletedSeq(parentSessionId) {
48
+ const snapshot = this.face(parentSessionId)?.getSnapshot();
49
+ let latest;
50
+ for (const seq of snapshot?.turnEnds.values() ?? [])
51
+ if (latest === undefined || seq > latest)
52
+ latest = seq;
53
+ return latest;
54
+ }
55
+ selectionIsCurrent(selection) {
56
+ const snapshot = this.face(selection.parentSessionId)?.getSnapshot();
57
+ if (snapshot === undefined)
58
+ return false;
59
+ return selection.fragments.every(fragment => {
60
+ const node = snapshot.chatNodes.get(fragment.nodeKey);
61
+ return node !== undefined && node.visibility === 'visible' && node.kind === fragment.nodeKind
62
+ && node.anchorSeq === fragment.seq && locationSettled(node.location);
63
+ });
64
+ }
65
+ addSelectionToConversation(selection, comment) {
66
+ if (this.currentSessionId() !== selection.parentSessionId)
67
+ return false;
68
+ const input = this.currentParentInput();
69
+ if (input === undefined || !addSelection(input, selection, comment))
70
+ return false;
71
+ this.annotationPersistence.reconcile(selection.parentSessionId, input);
72
+ return true;
73
+ }
74
+ addSideChatToConversation(parentSessionId, reference) {
75
+ const scope = this.ctx.sessions.scope(dshId(parentSessionId));
76
+ const input = scope === undefined ? undefined : this.parentInput(scope);
77
+ if (input === undefined || !addReferencedSideChatToConversation(input, reference))
78
+ return false;
79
+ this.annotationPersistence.reconcile(parentSessionId, input);
80
+ return true;
81
+ }
82
+ removeConversationAnnotation(index) {
83
+ const id = this.currentSessionId();
84
+ const input = this.currentParentInput();
85
+ if (id === undefined || input === undefined || !removeAnnotation(input, index))
86
+ return false;
87
+ this.annotationPersistence.reconcile(id, input);
88
+ return true;
89
+ }
90
+ updateConversationAnnotation(index, comment) {
91
+ const id = this.currentSessionId();
92
+ const input = this.currentParentInput();
93
+ if (id === undefined || input === undefined || !updateAnnotation(input, index, comment))
94
+ return false;
95
+ this.annotationPersistence.reconcile(id, input);
96
+ return true;
97
+ }
98
+ reconcileConversationAnnotationPersistence() {
99
+ const id = this.currentSessionId();
100
+ const input = this.currentParentInput();
101
+ if (id !== undefined && input !== undefined)
102
+ this.annotationPersistence.reconcile(id, input);
103
+ }
104
+ nextConversationAnnotationNumber() {
105
+ const snapshot = this.currentConversationInputSnapshot();
106
+ return snapshot === undefined ? 1 : conversationAnnotations(snapshot).length + 1;
107
+ }
108
+ removeConversationAnnotations(id = this.currentSessionId()) {
109
+ const scope = id === undefined ? undefined : this.ctx.sessions.scope(dshId(id));
110
+ const input = scope === undefined ? undefined : this.parentInput(scope);
111
+ if (id === undefined || input === undefined || !removeAnnotations(input))
112
+ return false;
113
+ this.annotationPersistence.reconcile(id, input);
114
+ return true;
115
+ }
116
+ retainParent(id) {
117
+ const reference = this.ctx.sessions.retain(dshId(id), { source: 'sideChat' });
118
+ let active = true;
119
+ void reference.ready.catch(() => { if (active)
120
+ this.notify({ kind: 'warning', text: 'The parent conversation could not be loaded.' }); });
121
+ return () => { active = false; reference.release(); };
122
+ }
123
+ async openSession(id) { this.ctx.uiWorkspace.openSession(dshId(id)); }
124
+ notify(message) {
125
+ console[message.kind === 'warning' ? 'warn' : 'info'](`[dsh-side-chat] ${message.text}`);
126
+ this.currentParentInput()?.notify?.(message.kind === 'warning' ? 'error' : 'info', message.text);
127
+ }
128
+ face(id) {
129
+ const source = this.ctx.sessions.binding(dshId(id))?.session;
130
+ if (source === undefined)
131
+ return;
132
+ const existing = this.faces.get(source);
133
+ if (existing !== undefined)
134
+ return existing;
135
+ const conversation = this.ctx.uiConversation.binding(source.sessionId);
136
+ conversation.activate('chat');
137
+ const face = new DshParentConversation(conversation.target('chat'));
138
+ this.faces.set(source, face);
139
+ return face;
140
+ }
141
+ title(id) { return this.ctx.sessions.list.getSnapshot().byId[dshId(id)]?.displayTitle; }
142
+ modelDirectory(id) {
143
+ try {
144
+ return this.ctx.modelDirectories.directoryFor(dshId(id));
145
+ }
146
+ catch {
147
+ return undefined;
148
+ }
149
+ }
150
+ sideChatModelPreference() { return this.modelPreferences.get(); }
151
+ rememberSideChatModelPreference(model) { this.modelPreferences.set(model); }
152
+ currentParentInput() {
153
+ const id = this.currentSessionId();
154
+ const scope = id === undefined ? undefined : this.ctx.sessions.scope(dshId(id));
155
+ return scope === undefined ? undefined : this.parentInput(scope);
156
+ }
157
+ parentInput(scope) {
158
+ const source = this.ctx.conversation.input.for(scope);
159
+ if (source === undefined)
160
+ return;
161
+ const existing = this.parentInputs.get(source);
162
+ if (existing !== undefined)
163
+ return existing;
164
+ const input = {
165
+ state: source.state, setDraft: text => { source.setDraft(text); },
166
+ notify: (level, text) => source.notify?.(level, text),
167
+ insertReference: (reference, span) => source.insertReference(reference, span),
168
+ replaceText: (text, span) => scope.bail(scope, 'slash/input-insert-text', { text, span }) === true,
169
+ };
170
+ this.parentInputs.set(source, input);
171
+ return input;
172
+ }
173
+ }
174
+ export function selectionDescriptor(snapshot, anchorKey) {
175
+ const node = snapshot.chatNodes.get(anchorKey);
176
+ if (node === undefined || node.visibility !== 'visible')
177
+ return;
178
+ const source = node.kind === 'user' || node.kind === 'steering' ? 'user'
179
+ : node.kind === 'assistant-step' ? 'assistant' : node.kind === 'context' ? 'context' : undefined;
180
+ const turn = node.location.kind === 'turn' || node.location.kind === 'step' ? node.location.turn.turn : undefined;
181
+ if (source === undefined || turn === undefined)
182
+ return;
183
+ return { nodeKey: node.key, nodeKind: node.kind, turnKey: `turn:${String(turn)}`, seq: node.anchorSeq,
184
+ source, modelVisible: true, settled: locationSettled(node.location) };
185
+ }
@@ -1,5 +1,5 @@
1
1
  export { apply, inject, name } from './apply.js';
2
- export type { SideChatActionResult, SideChatClientSessions, SideChatSessionBinding, SideChatSessionLease, SideChatSessionSnapshot, } from './contracts.js';
2
+ export type { SideChatActionResult, SideChatClientSessions, } from './contracts.js';
3
3
  export { SideChatController } from './side-chat-controller.js';
4
4
  export { buildSideChatPrompt } from './parent-composer/add-to-conversation.js';
5
5
  export { SideChatPanel, type SideChatPanelProps } from './panel/SideChatPanel.js';
@@ -7,5 +7,4 @@ export { SelectionActions, type SelectionActionsProps } from './selection/Select
7
7
  export { captureDomConversationSelection, restoreDomConversationSelection, type RestoredConversationSelection, type SelectionAnchorResolver, type SelectionNodeDescriptor, } from './selection/selection-controller.js';
8
8
  export { selectionFitsLimit, summarizeSelection, utf8ByteLength } from './selection/selection-limits.js';
9
9
  export { assertSelectionCurrent, finalizeConversationSelection, normalizeSelectedText, SelectionValidationError, type ConversationSelectionInput, } from './selection/selection-normalizer.js';
10
- export type { ConversationSelection, SelectionFragment, SelectionRect, SideChatModelSelection, SideChatState, } from '../shared/contracts.js';
11
- //# sourceMappingURL=index.d.ts.map
10
+ export type { ConversationSelection, SelectionFragment, SelectionRect, SideChatModelSelection, SideChatMessage, SideChatId, SideChatState, } from '../shared/contracts.js';
@@ -6,4 +6,3 @@ export { SelectionActions } from './selection/SelectionActions.js';
6
6
  export { captureDomConversationSelection, restoreDomConversationSelection, } from './selection/selection-controller.js';
7
7
  export { selectionFitsLimit, summarizeSelection, utf8ByteLength } from './selection/selection-limits.js';
8
8
  export { assertSelectionCurrent, finalizeConversationSelection, normalizeSelectedText, SelectionValidationError, } from './selection/selection-normalizer.js';
9
- //# sourceMappingURL=index.js.map
@@ -11,4 +11,3 @@ export declare class SideChatModelPreferences {
11
11
  set(selection: SideChatModelSelection): void;
12
12
  }
13
13
  export {};
14
- //# sourceMappingURL=model-preference.d.ts.map
@@ -57,4 +57,3 @@ export class SideChatModelPreferences {
57
57
  }
58
58
  }
59
59
  }
60
- //# sourceMappingURL=model-preference.js.map
@@ -9,4 +9,3 @@ export declare function SelectionQuote({ selections, messages, onRemove, }: {
9
9
  readonly messages: SideChatMessages;
10
10
  readonly onRemove?: () => void;
11
11
  }): import("react/jsx-runtime").JSX.Element;
12
- //# sourceMappingURL=SelectionQuote.d.ts.map
@@ -60,7 +60,14 @@ export function SelectionQuote({ selections, messages, onRemove, }) {
60
60
  return (_jsxs("section", { ref: quoteRef, className: "dsh-side-chat-quote", "aria-label": messages.selectedPassage, "data-expanded": expanded || undefined, "data-hovered": hovered || undefined, onMouseEnter: () => {
61
61
  keepHoverOpen();
62
62
  constrainDetailsToBoundary();
63
- }, onMouseLeave: closeHoverAfterGrace, onFocusCapture: constrainDetailsToBoundary, children: [_jsxs("div", { className: "dsh-side-chat-quote-chip", children: [_jsxs("button", { type: "button", className: "dsh-side-chat-quote-trigger", "aria-expanded": expanded, "aria-label": `${expanded ? messages.collapse : messages.expand}: ${messages.selectedPassage}`, onClick: () => {
63
+ }, onMouseLeave: closeHoverAfterGrace, onFocusCapture: constrainDetailsToBoundary, onKeyDown: (event) => {
64
+ if (event.key !== 'Escape' || (!expanded && !hovered))
65
+ return;
66
+ event.preventDefault();
67
+ event.stopPropagation();
68
+ setExpanded(false);
69
+ setHovered(false);
70
+ }, children: [_jsxs("div", { className: "dsh-side-chat-quote-chip", children: [_jsxs("button", { type: "button", className: "dsh-side-chat-quote-trigger", "aria-expanded": expanded, "aria-label": `${expanded ? messages.collapse : messages.expand}: ${messages.selectedPassage}`, onClick: () => {
64
71
  if (expanded) {
65
72
  if (leaveTimerRef.current !== undefined)
66
73
  window.clearTimeout(leaveTimerRef.current);
@@ -70,4 +77,3 @@ export function SelectionQuote({ selections, messages, onRemove, }) {
70
77
  setExpanded(value => !value);
71
78
  }, children: [_jsxs("svg", { className: "dsh-side-chat-quote-icon", viewBox: "0 0 24 24", "aria-hidden": "true", children: [_jsx("path", { d: "M21 15a4 4 0 0 1-4 4H7l-4 4V7a4 4 0 0 1 4-4h10a4 4 0 0 1 4 4Z" }), _jsx("path", { d: "M8 8h8M8 12h5" })] }), _jsx("strong", { children: messages.selectionAttachments(selections.length) })] }), onRemove !== undefined && (_jsx("button", { type: "button", className: "dsh-side-chat-quote-remove", "aria-label": messages.removeSelection, onClick: onRemove, children: "\u00D7" }))] }), _jsx("div", { ref: detailsRef, className: "dsh-side-chat-quote-details", role: "tooltip", children: selections.map((selection, index) => (_jsxs("div", { className: "dsh-side-chat-quote-detail", children: [_jsx("div", { className: "dsh-side-chat-quote-details-header", children: _jsxs("strong", { children: [String(index + 1), ". ", messages.selectionPreviewLabel, ":"] }) }), _jsx("pre", { children: selection.text }), selection.comment !== undefined && (_jsxs("div", { className: "dsh-side-chat-quote-comment", children: [_jsxs("strong", { children: [messages.selectionCommentLabel, ":"] }), _jsx("pre", { children: selection.comment })] }))] }, `${String(index)}-${selection.text}`))) })] }));
72
79
  }
73
- //# sourceMappingURL=SelectionQuote.js.map
@@ -1,3 +1,2 @@
1
1
  /** Arrow used by DSH's native 34px primary send button. */
2
2
  export declare function SendIcon(): import("react/jsx-runtime").JSX.Element;
3
- //# sourceMappingURL=SendIcon.d.ts.map
@@ -3,4 +3,3 @@ import { jsx as _jsx } from "react/jsx-runtime";
3
3
  export function SendIcon() {
4
4
  return (_jsx("svg", { viewBox: "0 0 16 16", width: "16", height: "16", "aria-hidden": "true", children: _jsx("path", { d: "M8.3125 0.980183C8.66767 1.0531 8.97902 1.20418 9.2627 1.43233C9.48724 1.61297 9.73029 1.85793 9.97949 2.10714L14.707 6.83468L13.293 8.24874L9 3.95577V15.0417H7V3.95577L2.70703 8.24874L1.29297 6.83468L6.02051 2.10714C6.26971 1.85793 6.51277 1.61297 6.7373 1.43233C6.97662 1.23986 7.28445 1.04402 7.6875 0.980183C7.8973 0.947006 8.1031 0.95516 8.3125 0.980183Z", fill: "currentColor" }) }));
5
5
  }
6
- //# sourceMappingURL=SendIcon.js.map
@@ -3,4 +3,3 @@ import type { ReactNode } from 'react';
3
3
  export declare function SideChatBody({ children }: {
4
4
  readonly children: ReactNode;
5
5
  }): import("react/jsx-runtime").JSX.Element;
6
- //# sourceMappingURL=SideChatBody.d.ts.map
@@ -3,4 +3,3 @@ import { jsx as _jsx } from "react/jsx-runtime";
3
3
  export function SideChatBody({ children }) {
4
4
  return _jsx("div", { className: "dsh-side-chat-body", children: children });
5
5
  }
6
- //# sourceMappingURL=SideChatBody.js.map
@@ -6,4 +6,3 @@ export declare function SideChatErrorState({ error, messages, onRetry, }: {
6
6
  readonly messages: SideChatMessages;
7
7
  readonly onRetry: () => void;
8
8
  }): import("react/jsx-runtime").JSX.Element;
9
- //# sourceMappingURL=SideChatErrorState.d.ts.map
@@ -1,6 +1,5 @@
1
1
  import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
2
  /** Error strip with one direct retry action. */
3
3
  export function SideChatErrorState({ error, messages, onRetry, }) {
4
- return (_jsxs("section", { className: "dsh-side-chat-error", role: "alert", children: [_jsx("strong", { children: error.code === 'side_chat_destroy_failed' ? messages.closeError : messages.genericError }), _jsx("p", { children: error.message }), error.recoverable && _jsx("button", { type: "button", onClick: onRetry, children: messages.retry })] }));
4
+ return (_jsxs("section", { className: "dsh-side-chat-error", role: "alert", children: [_jsx("strong", { children: error.operation === 'close' ? messages.closeError : messages.genericError }), _jsx("p", { children: error.message }), error.recoverable && _jsx("button", { type: "button", onClick: onRetry, children: messages.retry })] }));
5
5
  }
6
- //# sourceMappingURL=SideChatErrorState.js.map
@@ -8,4 +8,3 @@ export declare function SideChatHeader({ phase, messages, addToConversationDisab
8
8
  readonly onFocusParent: () => void;
9
9
  readonly onClose: () => void;
10
10
  }): import("react/jsx-runtime").JSX.Element;
11
- //# sourceMappingURL=SideChatHeader.d.ts.map
@@ -5,4 +5,3 @@ function AddToConversationIcon() {
5
5
  export function SideChatHeader({ phase, messages, addToConversationDisabled = false, onAddToConversation, onFocusParent, onClose, }) {
6
6
  return (_jsxs("header", { className: "dsh-side-chat-header", children: [_jsx("button", { type: "button", className: "dsh-side-chat-heading", onClick: onFocusParent, children: _jsx("strong", { children: messages.title }) }), _jsxs("div", { className: "dsh-side-chat-header-actions", children: [onAddToConversation !== undefined && (_jsxs("button", { type: "button", className: "dsh-side-chat-add-to-conversation", disabled: addToConversationDisabled, onClick: onAddToConversation, children: [_jsx(AddToConversationIcon, {}), _jsx("span", { children: messages.addToConversation })] })), _jsx("button", { type: "button", className: "dsh-side-chat-close", "aria-label": messages.close, disabled: phase === 'closing', onClick: onClose, children: "\u00D7" })] })] }));
7
7
  }
8
- //# sourceMappingURL=SideChatHeader.js.map
@@ -14,4 +14,3 @@ export interface SideChatModelSelectProps {
14
14
  }
15
15
  /** Side Chat projection of DSH Web's native composer model selector. */
16
16
  export declare function SideChatModelSelect({ directory, selection, locked, validateInitialSelection, locale, onInitialize, onSelect, }: SideChatModelSelectProps): import("react/jsx-runtime").JSX.Element;
17
- //# sourceMappingURL=SideChatModelSelect.d.ts.map
@@ -1,6 +1,6 @@
1
1
  import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
2
2
  import { useEffect, useId, useMemo, useRef, useState, useSyncExternalStore, } from 'react';
3
- import { IconCheckOutline16, IconChevronDownOutline14, IconChevronRightOutline14, IconWarningOutline16, Toast, } from '@deepseek-ai/dsh-client-ui-primitives';
3
+ import { IconCheckOutlineRegular as IconCheckOutline16, IconChevronDownOutlineRegular as IconChevronDownOutline14, IconChevronRightOutlineRegular as IconChevronRightOutline14, IconWarningOutlineRegular as IconWarningOutline16, Toast, } from '@deepseek-ai/dsh-client-ui-primitives';
4
4
  const MODEL_MESSAGES = {
5
5
  en: {
6
6
  selectModel: 'Select model',
@@ -74,6 +74,7 @@ export function SideChatModelSelect({ directory, selection, locked, validateInit
74
74
  const initialized = useRef(false);
75
75
  const operation = useRef(0);
76
76
  const toastSequence = useRef(0);
77
+ const selectionPending = useRef(false);
77
78
  const id = useId();
78
79
  const choices = useMemo(() => state.groups.flatMap(group => group.models.map(model => ({ group, model }))), [state.groups]);
79
80
  const current = selection ?? state.current ?? undefined;
@@ -98,14 +99,20 @@ export function SideChatModelSelect({ directory, selection, locked, validateInit
98
99
  ...(effort.description === undefined ? {} : { description: effort.description }),
99
100
  })),
100
101
  ], [messages.providerDefault, reasoning]);
101
- const modelLabel = currentChoice?.model.name ?? messages.selectModel;
102
+ const modelLabel = currentChoice?.model.name ?? current?.model ?? messages.selectModel;
102
103
  const triggerLabel = effortLabel === undefined ? modelLabel : `${modelLabel} · ${effortLabel}`;
103
104
  const reload = () => {
104
105
  void directory.load().catch(() => undefined);
105
106
  };
106
- useEffect(() => { reload(); }, [directory]);
107
107
  useEffect(() => {
108
- if (initialized.current)
108
+ initialized.current = false;
109
+ reload();
110
+ return () => { ++operation.current; };
111
+ }, [directory]);
112
+ useEffect(() => { if (locked)
113
+ setOpen(false); }, [locked]);
114
+ useEffect(() => {
115
+ if (initialized.current || locked)
109
116
  return;
110
117
  if (selection !== undefined && !validateInitialSelection) {
111
118
  initialized.current = true;
@@ -125,13 +132,13 @@ export function SideChatModelSelect({ directory, selection, locked, validateInit
125
132
  onInitialize(directoryCurrent, { remember: false });
126
133
  return;
127
134
  }
128
- if (state.status !== 'ready')
135
+ if (state.status !== 'ready' || state.error !== null || state.failures.length > 0)
129
136
  return;
130
137
  initialized.current = true;
131
138
  const repaired = repairSelection(selection, choices, directoryCurrent);
132
139
  if (!sameSelection(selection, repaired))
133
140
  onInitialize(repaired, { remember: true });
134
- }, [choices, onInitialize, selection, state.current, state.status, validateInitialSelection]);
141
+ }, [choices, locked, onInitialize, selection, state.current, state.status, state.error, state.failures, validateInitialSelection]);
135
142
  useEffect(() => {
136
143
  if (!open)
137
144
  return;
@@ -163,6 +170,7 @@ export function SideChatModelSelect({ directory, selection, locked, validateInit
163
170
  const onKeyDown = (event) => {
164
171
  if (event.key === 'Escape' && open) {
165
172
  event.preventDefault();
173
+ event.stopPropagation();
166
174
  if (pane !== 'root')
167
175
  setPane('root');
168
176
  else
@@ -180,21 +188,32 @@ export function SideChatModelSelect({ directory, selection, locked, validateInit
180
188
  close();
181
189
  };
182
190
  const submitSelection = async (next) => {
191
+ if (locked || selectionPending.current)
192
+ return;
183
193
  const generation = ++operation.current;
194
+ selectionPending.current = true;
184
195
  setSelecting(true);
185
- const result = await onSelect(next);
186
- if (generation !== operation.current)
187
- return;
188
- setSelecting(false);
189
- if (!result.ok) {
190
- toastSequence.current += 1;
196
+ try {
197
+ const result = await onSelect(next);
198
+ if (generation !== operation.current)
199
+ return;
200
+ if (!result.ok)
201
+ throw new Error(result.error.message);
202
+ close(true);
203
+ }
204
+ catch (error) {
205
+ if (generation !== operation.current)
206
+ return;
191
207
  setToast({
192
- seq: toastSequence.current,
193
- text: messages.operationFailed(result.error.message),
208
+ seq: ++toastSequence.current,
209
+ text: messages.operationFailed(error instanceof Error ? error.message : 'Could not select the model.'),
194
210
  });
195
- return;
196
211
  }
197
- close(true);
212
+ finally {
213
+ selectionPending.current = false;
214
+ if (generation === operation.current)
215
+ setSelecting(false);
216
+ }
198
217
  };
199
218
  const chooseModel = (group, model) => {
200
219
  if (sameModel(current, group.id, model.id)) {
@@ -235,13 +254,12 @@ export function SideChatModelSelect({ directory, selection, locked, validateInit
235
254
  const headingId = `${id}-${group.id}`;
236
255
  return (_jsxs("section", { role: "group", "aria-labelledby": headingId, className: "dsh-side-chat-model-group", children: [_jsx("div", { id: headingId, className: "dsh-side-chat-model-group-title", children: group.name }), group.models.map(model => {
237
256
  const selected = sameModel(current, group.id, model.id);
238
- return (_jsxs("button", { ref: itemRef(), type: "button", role: "menuitemradio", "aria-checked": selected, className: `dsh-side-chat-model-option${selected ? ' dsh-side-chat-model-selected' : ''}`, title: model.name, disabled: selecting, onClick: () => { chooseModel(group, model); }, children: [_jsxs("span", { className: "dsh-side-chat-model-option-copy", children: [_jsx("span", { className: "dsh-side-chat-model-name", children: model.name }), model.description !== undefined && (_jsx("span", { className: "dsh-side-chat-model-description", children: model.description }))] }), _jsx("span", { className: "dsh-side-chat-model-check", children: selected ? _jsx(IconCheckOutline16, {}) : null })] }, model.id));
257
+ return (_jsxs("button", { ref: itemRef(), type: "button", role: "menuitemradio", "aria-checked": selected, className: `dsh-side-chat-model-option${selected ? ' dsh-side-chat-model-selected' : ''}`, title: model.name, disabled: locked || selecting, onClick: () => { chooseModel(group, model); }, children: [_jsxs("span", { className: "dsh-side-chat-model-option-copy", children: [_jsx("span", { className: "dsh-side-chat-model-name", children: model.name }), model.description !== undefined && (_jsx("span", { className: "dsh-side-chat-model-description", children: model.description }))] }), _jsx("span", { className: "dsh-side-chat-model-check", children: selected ? _jsx(IconCheckOutline16, {}) : null })] }, model.id));
239
258
  })] }, group.id));
240
259
  }) }), state.status === 'ready' && choices.length === 0 && (_jsx("div", { className: "dsh-side-chat-model-empty", children: messages.emptyModels }))] })), pane === 'effort' && (effortChoices.length === 0
241
260
  ? _jsx("div", { className: "dsh-side-chat-model-empty", children: messages.emptyEfforts })
242
261
  : effortChoices.map(level => {
243
262
  const selected = effectiveEffort === level.effort;
244
- return (_jsxs("button", { ref: itemRef(), type: "button", role: "menuitemradio", "aria-checked": selected, className: `dsh-side-chat-model-option${selected ? ' dsh-side-chat-model-selected' : ''}`, disabled: selecting, onClick: () => { chooseEffort(level.effort); }, children: [_jsxs("span", { className: "dsh-side-chat-model-option-copy", children: [_jsx("span", { className: "dsh-side-chat-model-name", children: level.label }), level.description !== undefined && (_jsx("span", { className: "dsh-side-chat-model-description", children: level.description }))] }), _jsx("span", { className: "dsh-side-chat-model-check", children: selected ? _jsx(IconCheckOutline16, {}) : null })] }, level.key));
263
+ return (_jsxs("button", { ref: itemRef(), type: "button", role: "menuitemradio", "aria-checked": selected, className: `dsh-side-chat-model-option${selected ? ' dsh-side-chat-model-selected' : ''}`, disabled: locked || selecting, onClick: () => { chooseEffort(level.effort); }, children: [_jsxs("span", { className: "dsh-side-chat-model-option-copy", children: [_jsx("span", { className: "dsh-side-chat-model-name", children: level.label }), level.description !== undefined && (_jsx("span", { className: "dsh-side-chat-model-description", children: level.description }))] }), _jsx("span", { className: "dsh-side-chat-model-check", children: selected ? _jsx(IconCheckOutline16, {}) : null })] }, level.key));
245
264
  }))] })), toast !== null && (_jsx(Toast, { text: toast.text, icon: _jsx(IconWarningOutline16, {}), anchor: rootRef.current?.closest('[data-composer-card]') ?? null, onDone: () => { setToast(null); } }, toast.seq))] }));
246
265
  }
247
- //# sourceMappingURL=SideChatModelSelect.js.map
@@ -16,4 +16,3 @@ export interface SideChatPanelProps {
16
16
  readonly onRemoveSelection?: () => void;
17
17
  }
18
18
  export declare function SideChatPanel({ state, locale, embeddedConversation, modelControl, onDraftChange, onFirstSend, onClose, onRetry, onFocusParent, onAddToConversation, addToConversationDisabled, onRemoveSelection, }: SideChatPanelProps): import("react/jsx-runtime").JSX.Element;
19
- //# sourceMappingURL=SideChatPanel.d.ts.map