@ahggg/dsh-side-chat 0.7.3 → 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.
- package/README.md +15 -12
- package/README.zh-CN.md +15 -12
- package/lib/client/apply.js +48 -32
- package/lib/client/contracts.d.ts +3 -58
- package/lib/client/dsh/ReadOnlyConversation.d.ts +10 -0
- package/lib/client/dsh/ReadOnlyConversation.js +91 -0
- package/lib/client/dsh/SideChatOverlay.d.ts +7 -0
- package/lib/client/{rc6/Rc6SideChatOverlay.js → dsh/SideChatOverlay.js} +26 -56
- package/lib/client/{rc6 → dsh}/context.d.ts +4 -6
- package/lib/client/dsh/conversation-store.d.ts +22 -0
- package/lib/client/dsh/conversation-store.js +19 -0
- package/lib/client/dsh/primitive-labels.d.ts +2 -0
- package/lib/client/dsh/primitive-labels.js +4 -0
- package/lib/client/{rc6 → dsh}/remote-adapter.d.ts +2 -2
- package/lib/client/dsh/remote-adapter.js +22 -0
- package/lib/client/dsh/sessions-adapter.d.ts +56 -0
- package/lib/client/dsh/sessions-adapter.js +185 -0
- package/lib/client/index.d.ts +2 -2
- package/lib/client/panel/SelectionQuote.js +8 -1
- package/lib/client/panel/SideChatErrorState.js +1 -1
- package/lib/client/panel/SideChatModelSelect.js +37 -18
- package/lib/client/panel/SideChatPanel.js +12 -5
- package/lib/client/panel/messages.d.ts +1 -1
- package/lib/client/panel/messages.js +8 -8
- package/lib/client/parent-composer/ParentConversationAnnotations.d.ts +3 -2
- package/lib/client/parent-composer/ParentConversationAnnotations.js +50 -30
- package/lib/client/parent-composer/add-to-conversation.d.ts +14 -28
- package/lib/client/parent-composer/add-to-conversation.js +131 -545
- package/lib/client/parent-composer/annotation-persistence.d.ts +8 -8
- package/lib/client/parent-composer/annotation-persistence.js +106 -102
- package/lib/client/parent-composer/composer-reference.d.ts +17 -55
- package/lib/client/parent-composer/composer-reference.js +20 -72
- package/lib/client/parent-composer/referenced-conversation.d.ts +5 -7
- package/lib/client/parent-composer/referenced-conversation.js +21 -73
- package/lib/client/selection/ConversationAnnotationMarkers.js +5 -1
- package/lib/client/selection/SelectionActions.js +2 -1
- package/lib/client/selection/conversation-dom.d.ts +5 -0
- package/lib/client/selection/conversation-dom.js +24 -0
- package/lib/client/selection/selection-controller.d.ts +1 -1
- package/lib/client/selection/selection-controller.js +7 -3
- package/lib/client/selection/selection-normalizer.js +1 -1
- package/lib/client/side-chat-controller.d.ts +28 -41
- package/lib/client/side-chat-controller.js +245 -337
- package/lib/client.js +81 -52
- package/lib/host/index.d.ts +1 -1
- package/lib/host/index.js +1 -1
- package/lib/host/read-only-chat-service.d.ts +30 -0
- package/lib/host/read-only-chat-service.js +314 -0
- package/lib/index.d.ts +16 -8
- package/lib/index.js +34 -13
- package/lib/remote.d.ts +23 -14
- package/lib/remote.js +2 -5
- package/lib/shared/constants.d.ts +0 -13
- package/lib/shared/constants.js +0 -13
- package/lib/shared/contracts.d.ts +52 -19
- package/lib/shared/contracts.js +2 -3
- package/lib/shared/error-codes.d.ts +1 -1
- package/lib/shared/error-codes.js +2 -2
- package/lib/shared/{archived-wire.d.ts → side-chat-wire.d.ts} +109 -20
- package/lib/shared/side-chat-wire.js +34 -0
- package/lib/typert.d.ts +3 -68
- package/lib/typert.js +60 -4
- package/package.json +76 -56
- package/lib/client/rc6/ArchivedConversation.d.ts +0 -14
- package/lib/client/rc6/ArchivedConversation.js +0 -231
- package/lib/client/rc6/Rc6SideChatOverlay.d.ts +0 -7
- package/lib/client/rc6/SideChatTool.d.ts +0 -22
- package/lib/client/rc6/SideChatTool.js +0 -404
- package/lib/client/rc6/primitive-labels.d.ts +0 -7
- package/lib/client/rc6/primitive-labels.js +0 -60
- package/lib/client/rc6/remote-adapter.js +0 -34
- package/lib/client/rc6/runtime-compat.d.ts +0 -120
- package/lib/client/rc6/runtime-compat.js +0 -187
- package/lib/client/rc6/sessions-adapter.d.ts +0 -64
- package/lib/client/rc6/sessions-adapter.js +0 -387
- package/lib/host/archived-fork-service.d.ts +0 -28
- package/lib/host/archived-fork-service.js +0 -309
- package/lib/shared/archived-wire.js +0 -47
- /package/lib/client/{rc6 → dsh}/context.js +0 -0
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { jsx as _jsx } from "react/jsx-runtime";
|
|
2
2
|
import { useEffect, useRef, useState } from 'react';
|
|
3
3
|
import { restoreDomConversationSelection } from './selection-controller.js';
|
|
4
|
+
import { conversationChatRoot } from './conversation-dom.js';
|
|
4
5
|
const ANNOTATION_HIGHLIGHT = 'dsh-side-chat-annotations';
|
|
5
6
|
const ACTIVE_ANNOTATION_HIGHLIGHT = 'dsh-side-chat-active-annotation';
|
|
6
7
|
function clamp(value, minimum, maximum) {
|
|
@@ -144,7 +145,8 @@ export function ConversationAnnotationMarkers({ annotations, activeAnnotationInd
|
|
|
144
145
|
let resizeObserver;
|
|
145
146
|
const refresh = () => {
|
|
146
147
|
animationFrame = undefined;
|
|
147
|
-
const
|
|
148
|
+
const sessionId = annotations[0]?.selection.parentSessionId;
|
|
149
|
+
const conversationRoot = sessionId === undefined ? null : conversationChatRoot(sessionId) ?? null;
|
|
148
150
|
if (conversationRoot !== observedConversationRoot) {
|
|
149
151
|
resizeObserver?.disconnect();
|
|
150
152
|
observedConversationRoot = conversationRoot;
|
|
@@ -157,6 +159,8 @@ export function ConversationAnnotationMarkers({ annotations, activeAnnotationInd
|
|
|
157
159
|
const activeRanges = [];
|
|
158
160
|
if (conversationRoot !== null) {
|
|
159
161
|
for (const annotation of annotations) {
|
|
162
|
+
if (annotation.selection.parentSessionId !== sessionId)
|
|
163
|
+
continue;
|
|
160
164
|
const restored = restoreDomConversationSelection({
|
|
161
165
|
selection: annotation.selection,
|
|
162
166
|
conversationRoot,
|
|
@@ -148,7 +148,8 @@ export function SelectionActions({ selection, touchInteraction = false, askDisab
|
|
|
148
148
|
closeEditor();
|
|
149
149
|
return;
|
|
150
150
|
}
|
|
151
|
-
if (event.key === 'Enter' && !event.shiftKey
|
|
151
|
+
if (event.key === 'Enter' && !event.shiftKey && !event.nativeEvent.isComposing
|
|
152
|
+
&& event.keyCode !== 229) {
|
|
152
153
|
event.preventDefault();
|
|
153
154
|
saveAnnotation();
|
|
154
155
|
}
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
import type { SessionId } from '../../shared/contracts.js';
|
|
2
|
+
/** Resolve the exact Session, never the first chat/composer in a multi-panel UI. */
|
|
3
|
+
export declare function conversationElement(sessionId: SessionId): HTMLElement | undefined;
|
|
4
|
+
export declare function conversationChatRoot(sessionId: SessionId): HTMLElement | undefined;
|
|
5
|
+
export declare function focusConversationComposer(sessionId: SessionId): void;
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
/** Resolve the exact Session, never the first chat/composer in a multi-panel UI. */
|
|
2
|
+
export function conversationElement(sessionId) {
|
|
3
|
+
return [...document.querySelectorAll('[data-conversation-session]')]
|
|
4
|
+
.find(element => element.dataset['conversationSession'] === sessionId
|
|
5
|
+
&& element.closest('[data-side-chat-panel], [hidden], [aria-hidden="true"]') === null);
|
|
6
|
+
}
|
|
7
|
+
export function conversationChatRoot(sessionId) {
|
|
8
|
+
return conversationElement(sessionId)?.querySelector('[data-chat-flow]') ?? undefined;
|
|
9
|
+
}
|
|
10
|
+
export function focusConversationComposer(sessionId) {
|
|
11
|
+
// Workspace navigation schedules React rendering; focus after that commit,
|
|
12
|
+
// and never fall back to a different Session's composer.
|
|
13
|
+
window.requestAnimationFrame(() => {
|
|
14
|
+
const input = conversationElement(sessionId)?.querySelector([
|
|
15
|
+
'[data-composer-seat] textarea', '[data-composer-seat] [role="textbox"]',
|
|
16
|
+
'[data-composer-seat] [contenteditable="true"]',
|
|
17
|
+
].join(', '));
|
|
18
|
+
if (input === undefined || input === null)
|
|
19
|
+
return;
|
|
20
|
+
input.focus();
|
|
21
|
+
if (input instanceof HTMLTextAreaElement)
|
|
22
|
+
input.setSelectionRange(input.value.length, input.value.length);
|
|
23
|
+
});
|
|
24
|
+
}
|
|
@@ -20,7 +20,7 @@ export interface RestoredConversationSelection {
|
|
|
20
20
|
readonly browserRange: Range;
|
|
21
21
|
}
|
|
22
22
|
/**
|
|
23
|
-
*
|
|
23
|
+
* Capture against DSH's public Chat anchors. Fail closed unless every
|
|
24
24
|
* selected text node belongs to one public Chat anchor.
|
|
25
25
|
*/
|
|
26
26
|
export declare function captureDomConversationSelection(input: {
|
|
@@ -11,6 +11,10 @@ function excluded(node, root) {
|
|
|
11
11
|
'[data-selection-exclude]',
|
|
12
12
|
'[data-side-chat-panel]',
|
|
13
13
|
'[aria-hidden="true"]',
|
|
14
|
+
'[hidden]',
|
|
15
|
+
'[inert]',
|
|
16
|
+
'script',
|
|
17
|
+
'style',
|
|
14
18
|
'button',
|
|
15
19
|
'textarea',
|
|
16
20
|
'input',
|
|
@@ -23,7 +27,7 @@ function acceptedTextNodes(anchor, root) {
|
|
|
23
27
|
let current = walker.nextNode();
|
|
24
28
|
while (current !== null) {
|
|
25
29
|
const text = current;
|
|
26
|
-
if (!excluded(text, root))
|
|
30
|
+
if (!excluded(text, root) && anchorOf(text) === anchor)
|
|
27
31
|
nodes.push(text);
|
|
28
32
|
current = walker.nextNode();
|
|
29
33
|
}
|
|
@@ -50,7 +54,7 @@ function selectedSlice(range, node) {
|
|
|
50
54
|
return { start, end, text: node.data.slice(start, end) };
|
|
51
55
|
}
|
|
52
56
|
/**
|
|
53
|
-
*
|
|
57
|
+
* Capture against DSH's public Chat anchors. Fail closed unless every
|
|
54
58
|
* selected text node belongs to one public Chat anchor.
|
|
55
59
|
*/
|
|
56
60
|
export async function captureDomConversationSelection(input) {
|
|
@@ -65,7 +69,7 @@ export async function captureDomConversationSelection(input) {
|
|
|
65
69
|
const startAnchor = anchorOf(range.startContainer);
|
|
66
70
|
const endAnchor = anchorOf(range.endContainer);
|
|
67
71
|
if (startAnchor === null || endAnchor === null || startAnchor !== endAnchor) {
|
|
68
|
-
throw new SelectionValidationError('selection_crosses_unsupported_nodes', '
|
|
72
|
+
throw new SelectionValidationError('selection_crosses_unsupported_nodes', 'Select a passage inside one message.');
|
|
69
73
|
}
|
|
70
74
|
const descriptor = input.resolver.resolve(startAnchor);
|
|
71
75
|
if (descriptor === undefined) {
|
|
@@ -27,7 +27,7 @@ export function finalizeConversationSelection(input) {
|
|
|
27
27
|
throw new SelectionValidationError('selection_too_large', 'The selected text is too large.');
|
|
28
28
|
}
|
|
29
29
|
if (!fragment.modelVisible || !fragment.settled) {
|
|
30
|
-
throw new SelectionValidationError('
|
|
30
|
+
throw new SelectionValidationError('context_unavailable', 'Wait for this message to finish before opening Side Chat.');
|
|
31
31
|
}
|
|
32
32
|
if (!Number.isSafeInteger(fragment.seq) || fragment.seq < 0) {
|
|
33
33
|
throw new SelectionValidationError('selection_stale', 'The selected message is no longer available.');
|
|
@@ -1,17 +1,20 @@
|
|
|
1
|
-
import type { ConversationSelection, SessionId, SideChatModelSelection,
|
|
2
|
-
import type {
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
export declare class SideChatController implements HostObservable<SideChatState> {
|
|
1
|
+
import type { ConversationSelection, SessionId, SideChatModelSelection, SideChatRemote, SideChatState } from '../shared/contracts.js';
|
|
2
|
+
import type { SideChatActionResult, SideChatClientSessions } from './contracts.js';
|
|
3
|
+
/** Owns only plugin UI state and a cancellable model stream, never a child Session. */
|
|
4
|
+
export declare class SideChatController {
|
|
6
5
|
private readonly remote;
|
|
7
6
|
private readonly sessions;
|
|
8
7
|
private readonly observable;
|
|
9
|
-
private
|
|
10
|
-
private
|
|
11
|
-
private
|
|
12
|
-
private closing;
|
|
13
|
-
private closeRequested;
|
|
8
|
+
private generation;
|
|
9
|
+
private modelGeneration;
|
|
10
|
+
private requestSequence;
|
|
14
11
|
private disposed;
|
|
12
|
+
private releaseParent;
|
|
13
|
+
private creating;
|
|
14
|
+
private closing;
|
|
15
|
+
private running;
|
|
16
|
+
private cancelling;
|
|
17
|
+
private pendingRequest;
|
|
15
18
|
constructor(remote: SideChatRemote, sessions: SideChatClientSessions);
|
|
16
19
|
getSnapshot: () => SideChatState;
|
|
17
20
|
subscribe: (listener: () => void) => (() => void);
|
|
@@ -19,38 +22,22 @@ export declare class SideChatController implements HostObservable<SideChatState>
|
|
|
19
22
|
readonly parentSessionId?: SessionId;
|
|
20
23
|
readonly selection?: ConversationSelection;
|
|
21
24
|
readonly draft?: string;
|
|
22
|
-
}): SideChatActionResult
|
|
23
|
-
setDraft(draft: string): SideChatActionResult
|
|
24
|
-
clearSelection(): SideChatActionResult
|
|
25
|
-
initializeModel(
|
|
26
|
-
selectModel(
|
|
27
|
-
sendFirst(question: string): Promise<SideChatActionResult
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
} | {
|
|
34
|
-
readonly kind: 'remove';
|
|
35
|
-
} | {
|
|
36
|
-
readonly kind: 'steer';
|
|
37
|
-
}): Promise<SideChatActionResult<void>>;
|
|
38
|
-
cancel(): Promise<SideChatActionResult<void>>;
|
|
39
|
-
respondApproval(interactionId: string, decision: 'approve' | 'decline'): Promise<SideChatActionResult<void>>;
|
|
40
|
-
respondQuestion(interactionId: string, answer: SideChatQuestionAnswer | null): Promise<SideChatActionResult<void>>;
|
|
41
|
-
close(): Promise<SideChatActionResult<void>>;
|
|
42
|
-
retry(): Promise<SideChatActionResult<unknown>>;
|
|
25
|
+
}): SideChatActionResult;
|
|
26
|
+
setDraft(draft: string): SideChatActionResult;
|
|
27
|
+
clearSelection(): SideChatActionResult;
|
|
28
|
+
initializeModel(model: SideChatModelSelection): SideChatActionResult<SideChatModelSelection>;
|
|
29
|
+
selectModel(model: SideChatModelSelection): Promise<SideChatActionResult<SideChatModelSelection>>;
|
|
30
|
+
sendFirst(question: string): Promise<SideChatActionResult>;
|
|
31
|
+
/** Resolves at admission; the independently consumed stream continues to update the transcript. */
|
|
32
|
+
send(question: string): Promise<SideChatActionResult>;
|
|
33
|
+
cancel(): Promise<SideChatActionResult>;
|
|
34
|
+
retry(): Promise<SideChatActionResult>;
|
|
35
|
+
close(): Promise<SideChatActionResult>;
|
|
43
36
|
dispose(): Promise<void>;
|
|
44
|
-
private
|
|
45
|
-
private
|
|
46
|
-
private
|
|
47
|
-
private performClose;
|
|
48
|
-
private bindingTarget;
|
|
49
|
-
private attachLease;
|
|
50
|
-
private detachLease;
|
|
51
|
-
private updateFromChild;
|
|
37
|
+
private consume;
|
|
38
|
+
private streamFailure;
|
|
39
|
+
private closeCurrent;
|
|
52
40
|
private fail;
|
|
41
|
+
private disposeStream;
|
|
53
42
|
private invoke;
|
|
54
|
-
private reset;
|
|
55
|
-
private publish;
|
|
56
43
|
}
|