@ahggg/dsh-side-chat 0.7.0 → 0.7.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +0 -2
- package/README.zh-CN.md +0 -2
- package/lib/client/parent-composer/add-to-conversation.d.ts +14 -50
- package/lib/client/parent-composer/add-to-conversation.d.ts.map +1 -1
- package/lib/client/parent-composer/add-to-conversation.js +217 -22
- package/lib/client/parent-composer/add-to-conversation.js.map +1 -1
- package/lib/client/parent-composer/annotation-persistence.d.ts +1 -1
- package/lib/client/parent-composer/annotation-persistence.d.ts.map +1 -1
- package/lib/client/parent-composer/annotation-persistence.js +50 -12
- package/lib/client/parent-composer/annotation-persistence.js.map +1 -1
- package/lib/client/parent-composer/composer-reference.d.ts +72 -0
- package/lib/client/parent-composer/composer-reference.d.ts.map +1 -0
- package/lib/client/parent-composer/composer-reference.js +57 -0
- package/lib/client/parent-composer/composer-reference.js.map +1 -0
- package/lib/client/parent-composer/referenced-conversation.d.ts +1 -1
- package/lib/client/parent-composer/referenced-conversation.d.ts.map +1 -1
- package/lib/client/parent-composer/referenced-conversation.js +11 -18
- package/lib/client/parent-composer/referenced-conversation.js.map +1 -1
- package/lib/client/rc6/Rc6SideChatOverlay.d.ts.map +1 -1
- package/lib/client/rc6/Rc6SideChatOverlay.js +12 -1
- package/lib/client/rc6/Rc6SideChatOverlay.js.map +1 -1
- package/lib/client/rc6/sessions-adapter.d.ts +2 -0
- package/lib/client/rc6/sessions-adapter.d.ts.map +1 -1
- package/lib/client/rc6/sessions-adapter.js +12 -1
- package/lib/client/rc6/sessions-adapter.js.map +1 -1
- package/lib/client/selection/SelectionActions.d.ts +5 -1
- package/lib/client/selection/SelectionActions.d.ts.map +1 -1
- package/lib/client/selection/SelectionActions.js +66 -49
- package/lib/client/selection/SelectionActions.js.map +1 -1
- package/lib/client.js +334 -91
- package/lib/client.js.map +1 -1
- package/lib/shared/constants.d.ts +1 -1
- package/lib/shared/constants.d.ts.map +1 -1
- package/lib/shared/constants.js +1 -1
- package/lib/shared/constants.js.map +1 -1
- package/package.json +36 -29
package/lib/client.js
CHANGED
|
@@ -9,10 +9,58 @@ window.__ModuleLoader__.load({
|
|
|
9
9
|
let _deepseek_ai_dsh_client_ui_primitives = require("@deepseek-ai/dsh-client-ui-primitives");
|
|
10
10
|
//#region \0dsh-side-chat-css:L2hvbWUvcnVubmVyL3dvcmsvZHNoLXNpZGUtY2hhdC9kc2gtc2lkZS1jaGF0L3NyYy9jbGllbnQvcGFuZWwvc2lkZS1jaGF0LmNzcw
|
|
11
11
|
var _dsh_side_chat_css_L2hvbWUvcnVubmVyL3dvcmsvZHNoLXNpZGUtY2hhdC9kc2gtc2lkZS1jaGF0L3NyYy9jbGllbnQvcGFuZWwvc2lkZS1jaGF0LmNzcw_default = ".dsh-side-chat-overlay,\n.dsh-side-chat-parent-annotation-dock,\n.dsh-side-chat-parent-user-message {\n /* DSH rc.6 themes publish the semantic alias layer. Keep the legacy tokens\n as fallbacks for older hosts instead of falling through to light colors\n while the host has selected its dark palette. */\n --side-chat-border: var(--dsw-alias-border-l2, var(--dsw-border, #d8d8de));\n --side-chat-bg: var(--dsw-alias-bg-layer-2, var(--dsw-surface, #ffffff));\n --side-chat-muted: var(--dsw-alias-label-tertiary, var(--dsw-text-muted, #62636a));\n --side-chat-text: var(--dsw-alias-label-primary, var(--dsw-text, #19191d));\n --side-chat-accent: var(--dsw-alias-state-business-primary, #1473e6);\n --side-chat-accent-fill: var(--dsw-alias-button-info-fill, #4176e6);\n --side-chat-accent-hover: var(--dsw-alias-button-info-hover, #3467d6);\n --side-chat-accent-text: var(--dsw-alias-label-primary-foreground, #ffffff);\n color: var(--side-chat-text);\n}\n\n.dsh-side-chat-overlay {\n pointer-events: none;\n}\n\n.dsh-side-chat-overlay > * {\n pointer-events: auto;\n}\n\n.dsh-side-chat-panel {\n position: fixed;\n z-index: 70;\n right: clamp(12px, 2vw, 20px);\n bottom: clamp(12px, 2vw, 20px);\n display: flex;\n width: min(840px, calc(100vw - 32px));\n height: clamp(460px, 62dvh, 980px);\n max-height: calc(100dvh - 32px);\n min-width: 0;\n min-height: 0;\n box-sizing: border-box;\n flex-direction: column;\n overflow: hidden;\n border: 1px solid var(--side-chat-border);\n border-radius: 28px;\n background: var(--side-chat-bg);\n color: var(--side-chat-text);\n box-shadow: 0 12px 36px rgb(0 0 0 / 11%), 0 2px 8px rgb(0 0 0 / 6%);\n}\n\n.dsh-side-chat-conversation {\n display: flex;\n height: 100%;\n min-height: 0;\n flex-direction: column;\n overflow: hidden;\n}\n\n.dsh-side-chat-transcript {\n display: flex;\n min-height: 0;\n flex: 1;\n flex-direction: column;\n gap: 12px;\n overflow-x: hidden;\n overflow-y: auto;\n padding: 18px 20px 24px;\n scrollbar-color: color-mix(in srgb, var(--side-chat-muted) 34%, transparent) transparent;\n scrollbar-width: thin;\n}\n\n.dsh-side-chat-message {\n max-width: 92%;\n padding: 10px 12px;\n border: 1px solid var(--side-chat-border);\n border-radius: 12px;\n background: var(--dsw-alias-bg-layer-3, var(--dsw-surface-subtle, #f7f7f9));\n}\n\n.dsh-side-chat-message[data-role=\"user\"] {\n align-self: end;\n background: var(--dsw-specific-bubble, var(--dsw-accent-soft, #eef4ff));\n}\n\n.dsh-side-chat-message[data-role=\"assistant\"] {\n align-self: start;\n min-width: 0;\n max-width: 100%;\n border-color: transparent;\n background: transparent;\n overflow-wrap: anywhere;\n}\n.dsh-side-chat-message-role,\n.dsh-side-chat-message-note { display: block; margin-bottom: 5px; color: var(--side-chat-muted); font-size: 12px; }\n.dsh-side-chat-message-text { white-space: pre-wrap; overflow-wrap: anywhere; }\n.dsh-side-chat-message pre,\n.dsh-side-chat-turn-notice pre { overflow: auto; white-space: pre-wrap; overflow-wrap: anywhere; }\n.dsh-side-chat-message[data-role=\"assistant\"] :where(table) {\n display: block;\n max-width: 100%;\n overflow-x: auto;\n}\n.dsh-side-chat-reasoning {\n display: flex;\n flex-direction: column;\n}\n.dsh-side-chat-reasoning-row {\n position: relative;\n overflow: hidden;\n}\n.dsh-side-chat-reasoning[data-state=\"running\"] .dsh-side-chat-reasoning-row::after {\n position: absolute;\n inset-block: 0;\n left: 0;\n width: 300px;\n background: linear-gradient(\n 90deg,\n transparent 0%,\n color-mix(in srgb, var(--dsw-alias-bg-base, #fff) 60%, transparent) 55%,\n transparent 100%\n );\n content: '';\n pointer-events: none;\n animation: dsh-side-chat-reasoning-sweep 2.6s ease-out infinite;\n}\n@keyframes dsh-side-chat-reasoning-sweep {\n 0% { left: -300px; }\n 90%, 100% { left: 100%; }\n}\n.dsh-side-chat-reasoning-leading { flex-shrink: 0; }\n.dsh-side-chat-reasoning-chevron { color: var(--dsw-alias-label-secondary, var(--side-chat-muted)); }\n.dsh-side-chat-reasoning-title { font-weight: 400; }\n.dsh-side-chat-reasoning-separator {\n width: 2px;\n height: 2px;\n flex: none;\n margin: 0 8px;\n border-radius: 1px;\n background: var(--dsw-alias-label-caption, #a1a1aa);\n}\n.dsh-side-chat-reasoning-summary {\n min-width: 0;\n flex: auto;\n overflow: hidden;\n color: var(--dsw-alias-label-tertiary, var(--side-chat-muted));\n font-size: 14px;\n line-height: 24px;\n text-overflow: ellipsis;\n white-space: nowrap;\n}\n.dsh-side-chat-reasoning-summary[data-follow-end] { text-overflow: clip; }\n.dsh-side-chat-reasoning-body {\n padding: 4px 0 4px 22px;\n color: var(--dsw-alias-label-tertiary, var(--side-chat-muted));\n font-size: 14px;\n line-height: 24px;\n white-space: pre-wrap;\n word-break: break-word;\n}\n.dsh-side-chat-reasoning-visually-hidden {\n position: absolute;\n width: 1px;\n height: 1px;\n overflow: hidden;\n clip: rect(0 0 0 0);\n white-space: nowrap;\n}\n.dsh-side-chat-tool-branch {\n min-width: 0;\n max-width: 100%;\n flex: 0 0 auto;\n}\n.dsh-side-chat-tool {\n display: flex;\n min-width: 0;\n max-width: 100%;\n flex: 0 0 auto;\n flex-direction: column;\n border-radius: 6px;\n}\n.dsh-side-chat-tool-row {\n position: relative;\n overflow: hidden;\n}\n.dsh-side-chat-tool[data-state=\"running\"] .dsh-side-chat-tool-row::after,\n.dsh-side-chat-tool[data-state=\"pending\"] .dsh-side-chat-tool-row::after {\n position: absolute;\n top: 0;\n bottom: 0;\n left: 0;\n width: 300px;\n background: linear-gradient(\n 90deg,\n transparent 0%,\n color-mix(in srgb, var(--dsw-alias-bg-base, #fff) 60%, transparent) 55%,\n transparent 100%\n );\n content: '';\n pointer-events: none;\n animation: dsh-side-chat-tool-sweep 2.6s ease-out infinite;\n}\n@keyframes dsh-side-chat-tool-sweep {\n 0% { left: -300px; }\n 90%, 100% { left: 100%; }\n}\n.dsh-side-chat-tool-row:focus-visible {\n border-radius: 4px;\n outline: 2px solid color-mix(in srgb, var(--side-chat-accent) 42%, transparent);\n outline-offset: 1px;\n}\n.dsh-side-chat-tool-leading { flex-shrink: 0; }\n.dsh-side-chat-tool-chevron { color: var(--dsw-alias-label-secondary, var(--side-chat-muted)); }\n.dsh-side-chat-tool-title { font-weight: 400; }\n.dsh-side-chat-tool-separator {\n width: 2px;\n height: 2px;\n flex: none;\n margin: 0 8px;\n border-radius: 1px;\n background: var(--dsw-alias-label-caption, #a1a1aa);\n}\n.dsh-side-chat-tool-summary {\n flex: 1 1 auto;\n min-width: 0;\n overflow: hidden;\n color: var(--dsw-alias-label-tertiary, var(--side-chat-muted));\n font-size: 14px;\n line-height: 24px;\n text-overflow: ellipsis;\n white-space: nowrap;\n}\n.dsh-side-chat-tool-error-summary { color: var(--dsw-alias-state-error-primary, var(--dsw-danger, #b42318)); }\n.dsh-side-chat-tool-body-wrap {\n display: flex;\n min-width: 0;\n flex-direction: column;\n}\n.dsh-side-chat-tool-code,\n.dsh-side-chat-tool-diff,\n.dsh-side-chat-tool-read,\n.dsh-side-chat-tool-search,\n.dsh-side-chat-tool-terminal,\n.dsh-side-chat-tool-web {\n margin: 4px 0 4px 4px;\n}\n.dsh-side-chat-tool-code { --dsl-code-block-content-font: var(--dsw-font-markdown-code-block-small); }\n.dsh-side-chat-tool-terminal {\n --dsl-terminal-font: var(--dsw-font-markdown-code-block-small);\n --dsl-terminal-line-height: 18px;\n --dsl-terminal-output-max-height: 224px;\n border: 1px solid var(--dsw-alias-border-l1, var(--side-chat-border));\n}\n.dsh-side-chat-tool-io-card {\n display: flex;\n flex-direction: column;\n margin: 4px 0 4px 4px;\n border: 1px solid var(--dsw-alias-border-l1, var(--side-chat-border));\n border-radius: 12px;\n background: var(--dsw-alias-markdown-code-block, #f6f6f7);\n font: var(--dsw-font-markdown-code-block-small, 12px/18px ui-monospace, SFMono-Regular, Consolas, monospace);\n}\n.dsh-side-chat-tool-io-section {\n display: grid;\n max-height: 150px;\n grid-template-columns: max-content minmax(0, 1fr);\n column-gap: 14px;\n align-items: baseline;\n overflow-y: auto;\n padding: 12px 16px;\n}\n.dsh-side-chat-tool-io-divider {\n height: 1px;\n flex: none;\n background: var(--dsw-alias-border-l2, var(--side-chat-border));\n}\n.dsh-side-chat-tool-io-label {\n position: sticky;\n top: 0;\n align-self: start;\n color: var(--dsw-alias-label-caption, #8d8d95);\n}\n.dsh-side-chat-tool-io-text {\n min-width: 0;\n white-space: pre-wrap;\n word-break: break-word;\n color: var(--dsw-alias-label-secondary, #4b4b52);\n}\n.dsh-side-chat-tool-io-text[data-error] { color: var(--dsw-alias-state-error-primary, var(--dsw-danger, #b42318)); }\n.dsh-side-chat-tool-subcalls {\n display: flex;\n flex-direction: column;\n gap: 4px;\n margin: 4px 0 2px 22px;\n padding-left: 8px;\n border-left: 1px solid var(--dsw-alias-border-l2, var(--side-chat-border));\n}\n.dsh-side-chat-tool-visually-hidden {\n position: absolute;\n width: 1px;\n height: 1px;\n overflow: hidden;\n clip: rect(0 0 0 0);\n white-space: nowrap;\n}\n.dsh-side-chat-turn-notice,\n.dsh-side-chat-interaction,\n.dsh-side-chat-queue { padding: 10px; border: 1px solid var(--side-chat-border); border-radius: 10px; }\n.dsh-side-chat-interaction fieldset { margin: 8px 0; border: 1px solid var(--side-chat-border); border-radius: 8px; }\n.dsh-side-chat-question-option { display: flex; gap: 8px; margin: 8px 0; }\n.dsh-side-chat-interaction textarea { width: 100%; box-sizing: border-box; resize: vertical; }\n.dsh-side-chat-interaction-actions,\n.dsh-side-chat-queue > div { display: flex; justify-content: end; gap: 8px; }\n.dsh-side-chat-interaction button,\n.dsh-side-chat-queue button { min-height: 32px; border: 1px solid var(--side-chat-border); border-radius: 7px; background: var(--dsw-alias-interactive-bg-hover-solid, var(--dsw-control, #f7f7f9)); color: inherit; cursor: pointer; }\n.dsh-side-chat-composer {\n display: grid;\n grid-template-columns: minmax(0, 1fr);\n gap: 6px;\n align-items: end;\n margin: 0 12px 12px;\n padding: 8px 8px 8px 12px;\n border: 1px solid var(--side-chat-border);\n border-radius: 24px;\n background: var(--side-chat-bg);\n box-shadow: 0 2px 8px rgb(0 0 0 / 5%);\n}\n.dsh-side-chat-composer textarea {\n grid-column: 1 / -1;\n width: 100%;\n height: auto;\n min-height: 24px;\n max-height: 160px;\n box-sizing: border-box;\n resize: none;\n overflow-y: hidden;\n padding: 6px;\n border: 0;\n outline: 0;\n background: transparent;\n color: inherit;\n font: inherit;\n line-height: 1.5;\n}\n.dsh-side-chat-composer-actions,\n.dsh-side-chat-draft-actions {\n display: flex;\n min-width: 0;\n align-items: center;\n justify-content: flex-end;\n gap: 6px;\n}\n.dsh-side-chat-model-root {\n position: relative;\n min-width: 0;\n}\n.dsh-side-chat-model-trigger {\n display: flex;\n width: auto;\n height: 28px;\n min-height: 28px;\n max-width: 220px;\n align-items: center;\n gap: 4px;\n padding: 0 4px 0 8px;\n border: 0;\n border-radius: 24px;\n outline: 0;\n background: transparent;\n color: var(--dsw-alias-label-secondary, var(--side-chat-muted));\n cursor: pointer;\n font: inherit;\n font-size: 13px;\n font-weight: 500;\n line-height: 20px;\n}\n.dsh-side-chat-model-trigger:hover:not(:disabled) {\n background: var(--dsw-alias-interactive-bg-hover, var(--dsw-surface-subtle, #f3f3f5));\n}\n.dsh-side-chat-model-trigger:focus-visible {\n box-shadow: 0 0 0 2px var(--dsw-alias-border-l3, var(--side-chat-border));\n}\n.dsh-side-chat-model-trigger:disabled {\n color: var(--dsw-alias-label-dimmed, #a1a1aa);\n cursor: default;\n}\n.dsh-side-chat-model-trigger-label {\n min-width: 0;\n overflow: hidden;\n text-overflow: ellipsis;\n white-space: nowrap;\n}\n.dsh-side-chat-model-trigger-effort {\n flex: none;\n color: var(--dsw-alias-label-caption, #8d8d95);\n}\n.dsh-side-chat-model-chevron {\n flex: none;\n color: var(--dsw-alias-label-caption, #8d8d95);\n transition: transform 120ms ease;\n}\n.dsh-side-chat-model-chevron-open { transform: rotate(180deg); }\n.dsh-side-chat-model-menu {\n position: absolute;\n z-index: 20;\n right: 0;\n bottom: calc(100% + 8px);\n display: flex;\n width: min(240px, calc(100vw - 32px));\n max-height: min(360px, calc(100dvh - 96px));\n flex-direction: column;\n overflow: hidden;\n padding: 4px;\n border: 1px solid var(--dsw-alias-border-inverted, var(--side-chat-border));\n border-radius: 12px;\n background: var(--dsw-specific-menu, var(--side-chat-bg));\n box-shadow: var(--dsw-shadow-lv3, 0 8px 24px rgb(0 0 0 / 16%));\n color: var(--dsw-alias-label-primary, inherit);\n --dsh-scrollbar-thumb: var(--dsw-alias-scrollbar-bg-l2, #a1a1aa);\n --dsh-scrollbar-thumb-hover: var(--dsw-alias-scrollbar-hover-l2, #71717a);\n}\n.dsh-side-chat-model-status,\n.dsh-side-chat-model-empty {\n padding: 10px;\n color: var(--dsw-alias-label-tertiary, var(--side-chat-muted));\n font-size: 13px;\n line-height: 20px;\n}\n.dsh-side-chat-model-error,\n.dsh-side-chat-model-warning {\n display: flex;\n align-items: flex-start;\n justify-content: space-between;\n gap: 8px;\n margin-bottom: 4px;\n padding: 7px 8px;\n border-radius: 8px;\n background: var(--dsw-alias-interactive-bg-hover-danger, #fff1f0);\n color: var(--dsw-alias-state-error-primary, var(--dsw-danger, #b42318));\n font-size: 12px;\n line-height: 18px;\n}\n.dsh-side-chat-model-warning {\n background: var(--dsw-alias-bg-module-platform, #fff8e6);\n color: var(--dsw-alias-state-warn-label, #8a5a00);\n}\n.dsh-side-chat-model-retry {\n min-height: 0;\n flex: none;\n padding: 0;\n border: 0;\n background: transparent;\n color: inherit;\n cursor: pointer;\n font: inherit;\n font-weight: 600;\n}\n.dsh-side-chat-model-groups {\n min-height: 0;\n overflow-y: auto;\n}\n.dsh-side-chat-model-group + .dsh-side-chat-model-group { margin-top: 4px; }\n.dsh-side-chat-model-group-title {\n position: sticky;\n z-index: 1;\n top: 0;\n padding: 5px 8px 3px;\n background: var(--dsw-specific-menu, var(--side-chat-bg));\n color: var(--dsw-alias-label-tertiary, var(--side-chat-muted));\n font-size: 12px;\n font-weight: 500;\n line-height: 18px;\n}\n.dsh-side-chat-model-option {\n display: flex;\n width: 100%;\n min-height: 38px;\n align-items: center;\n gap: 8px;\n padding: 6px 8px;\n border: 0;\n border-radius: 10px;\n outline: 0;\n background: transparent;\n color: inherit;\n cursor: pointer;\n font: inherit;\n text-align: left;\n}\n.dsh-side-chat-model-option:hover:not(:disabled),\n.dsh-side-chat-model-option:focus-visible {\n background: var(--dsw-alias-interactive-bg-hover, var(--dsw-surface-subtle, #f3f3f5));\n}\n.dsh-side-chat-model-selected { background: transparent; }\n.dsh-side-chat-model-option:disabled {\n color: var(--dsw-alias-label-dimmed, #a1a1aa);\n cursor: default;\n}\n.dsh-side-chat-model-option-copy {\n display: flex;\n min-width: 0;\n flex: 1;\n flex-direction: column;\n}\n.dsh-side-chat-model-name {\n overflow: hidden;\n color: inherit;\n font-size: 14px;\n font-weight: 500;\n line-height: 20px;\n text-overflow: ellipsis;\n white-space: nowrap;\n}\n.dsh-side-chat-model-description {\n overflow: hidden;\n color: var(--dsw-alias-label-tertiary, var(--side-chat-muted));\n font-size: 12px;\n line-height: 18px;\n text-overflow: ellipsis;\n white-space: nowrap;\n}\n.dsh-side-chat-model-check {\n display: grid;\n flex: 0 0 18px;\n place-items: center;\n color: var(--dsw-alias-label-primary, inherit);\n}\n.dsh-side-chat-model-cell {\n display: flex;\n width: 100%;\n height: 40px;\n align-items: center;\n gap: 8px;\n padding: 0 10px;\n border: 0;\n border-radius: 10px;\n background: transparent;\n color: var(--dsw-alias-label-primary, inherit);\n cursor: pointer;\n font: inherit;\n font-size: 14px;\n line-height: 22px;\n text-align: left;\n}\n.dsh-side-chat-model-cell:hover {\n background: var(--dsw-alias-interactive-bg-hover, var(--dsw-surface-subtle, #f3f3f5));\n}\n.dsh-side-chat-model-cell-label {\n min-width: 0;\n flex: auto;\n overflow: hidden;\n text-overflow: ellipsis;\n white-space: nowrap;\n}\n.dsh-side-chat-model-cell-value {\n min-width: 0;\n flex: 0 auto;\n overflow: hidden;\n color: var(--dsw-alias-label-tertiary, var(--side-chat-muted));\n text-overflow: ellipsis;\n white-space: nowrap;\n}\n.dsh-side-chat-model-cell-chevron {\n flex: none;\n color: var(--dsw-alias-label-tertiary, var(--side-chat-muted));\n}\n.dsh-side-chat-loading { display: grid; height: 100%; place-items: center; color: var(--side-chat-muted); }\n\n.dsh-side-chat-header {\n display: grid;\n grid-template-columns: minmax(0, 1fr) auto;\n gap: 8px 12px;\n align-items: center;\n flex: 0 0 auto;\n min-height: 46px;\n box-sizing: border-box;\n padding: 5px 10px 5px 16px;\n border-bottom: 1px solid var(--side-chat-border);\n background: var(--side-chat-bg);\n}\n\n.dsh-side-chat-heading { display: flex; min-width: 0; flex-direction: column; }\n.dsh-side-chat-heading strong { font-size: 14px; font-weight: 600; }\n.dsh-side-chat-footer { color: var(--side-chat-muted); font-size: 12px; }\n.dsh-side-chat-header button,\n.dsh-side-chat-inline-actions button,\n.dsh-side-chat-error button,\n.dsh-side-chat-selection-actions button {\n min-height: 32px;\n border: 1px solid var(--side-chat-border);\n border-radius: 7px;\n background: var(--dsw-alias-interactive-bg-hover-solid, var(--dsw-control, #f7f7f9));\n color: inherit;\n cursor: pointer;\n}\n.dsh-side-chat-header button:disabled { cursor: not-allowed; opacity: .55; }\n.dsh-side-chat-header .dsh-side-chat-heading {\n align-items: flex-start;\n min-height: 0;\n padding: 4px 0;\n border: 0;\n background: transparent;\n text-align: left;\n}\n.dsh-side-chat-header-actions {\n display: flex;\n min-width: 0;\n align-items: center;\n justify-content: flex-end;\n gap: 4px;\n}\n.dsh-side-chat-header .dsh-side-chat-add-to-conversation {\n display: inline-flex;\n min-width: 0;\n align-items: center;\n gap: 6px;\n padding: 0 9px;\n border: 0;\n border-radius: 999px;\n background: transparent;\n color: var(--dsw-alias-label-secondary, var(--side-chat-muted));\n font: inherit;\n font-size: 13px;\n white-space: nowrap;\n}\n.dsh-side-chat-add-to-conversation:hover:not(:disabled),\n.dsh-side-chat-add-to-conversation:focus-visible {\n background: var(--dsw-alias-interactive-bg-hover, var(--dsw-surface-subtle, #f3f3f5));\n color: var(--side-chat-text);\n}\n.dsh-side-chat-add-to-conversation-icon {\n width: 18px;\n height: 18px;\n flex: none;\n fill: none;\n stroke: currentColor;\n stroke-linecap: round;\n stroke-linejoin: round;\n stroke-width: 1.5;\n}\n.dsh-side-chat-header .dsh-side-chat-close {\n width: 32px;\n min-height: 32px;\n padding: 0;\n border: 0;\n border-radius: 999px;\n background: transparent;\n font-size: 20px;\n line-height: 1;\n}\n.dsh-side-chat-close:hover:not(:disabled) { background: var(--dsw-alias-interactive-bg-hover, var(--dsw-surface-subtle, #f3f3f5)); }\n\n.dsh-side-chat-quote { position: relative; max-width: 100%; align-self: flex-start; }\n.dsh-side-chat-quote-chip {\n display: inline-flex;\n min-height: 36px;\n align-items: center;\n overflow: hidden;\n padding: 0;\n border: 1px solid var(--side-chat-border);\n border-radius: 999px;\n background: var(--side-chat-bg);\n transition: background-color 120ms ease;\n}\n.dsh-side-chat-quote:hover .dsh-side-chat-quote-chip,\n.dsh-side-chat-quote:focus-within .dsh-side-chat-quote-chip,\n.dsh-side-chat-quote[data-expanded] .dsh-side-chat-quote-chip { background: var(--dsw-alias-interactive-bg-hover, var(--dsw-surface-subtle, #f3f3f5)); }\n.dsh-side-chat-quote-chip .dsh-side-chat-quote-trigger {\n display: inline-flex;\n min-height: 34px;\n align-items: center;\n gap: 8px;\n padding: 0 11px;\n border: 0;\n border-radius: 0;\n background: transparent;\n color: inherit;\n cursor: pointer;\n font: inherit;\n}\n.dsh-side-chat-quote-trigger strong { font-size: 13px; font-weight: 500; line-height: 1; }\n.dsh-side-chat-quote-icon {\n width: 16px;\n height: 16px;\n flex: 0 0 auto;\n color: var(--side-chat-muted);\n fill: none;\n stroke: currentColor;\n stroke-linecap: round;\n stroke-linejoin: round;\n stroke-width: 1.7;\n}\n.dsh-side-chat-quote-chip .dsh-side-chat-quote-remove {\n display: grid;\n width: 0;\n height: 34px;\n min-height: 34px;\n box-sizing: border-box;\n flex: 0 0 auto;\n place-items: center;\n overflow: hidden;\n padding: 0;\n border: 0;\n border-radius: 0;\n background: transparent;\n color: var(--side-chat-muted);\n cursor: pointer;\n font: inherit;\n font-size: 18px;\n line-height: 1;\n opacity: 0;\n pointer-events: none;\n transition: width 120ms ease, margin-left 120ms ease, opacity 100ms ease, background-color 100ms ease;\n}\n.dsh-side-chat-quote:hover .dsh-side-chat-quote-remove,\n.dsh-side-chat-quote:focus-within .dsh-side-chat-quote-remove {\n width: 30px;\n opacity: 1;\n pointer-events: auto;\n}\n.dsh-side-chat-quote-remove:hover { background: var(--dsw-alias-interactive-bg-hover, rgb(0 0 0 / 6%)); color: inherit; }\n.dsh-side-chat-quote-details {\n position: absolute;\n z-index: 10;\n bottom: calc(100% + 8px);\n left: 0;\n width: min(520px, calc(100vw - 64px));\n max-width: calc(100vw - 48px);\n box-sizing: border-box;\n padding: 14px 16px;\n border: 1px solid var(--side-chat-border);\n border-radius: 16px;\n background: var(--side-chat-bg);\n box-shadow: 0 4px 14px rgb(0 0 0 / 8%);\n font-size: 14px;\n line-height: 1.45;\n opacity: 0;\n pointer-events: none;\n transform: translate(var(--dsh-side-chat-quote-offset-x, 0px), 4px);\n visibility: hidden;\n transition: opacity 100ms ease, transform 120ms ease, visibility 100ms ease;\n}\n.dsh-side-chat-quote-details::before {\n content: '';\n position: absolute;\n right: 0;\n bottom: -8px;\n left: 0;\n height: 8px;\n}\n.dsh-side-chat-quote[data-hovered] .dsh-side-chat-quote-details,\n.dsh-side-chat-quote[data-expanded] .dsh-side-chat-quote-details {\n opacity: 1;\n pointer-events: auto;\n transform: translate(var(--dsh-side-chat-quote-offset-x, 0px), 0);\n visibility: visible;\n}\n.dsh-side-chat-annotated-user-message .dsh-side-chat-quote-details {\n top: calc(100% + 8px);\n right: 0;\n bottom: auto;\n left: auto;\n}\n.dsh-side-chat-annotated-user-message .dsh-side-chat-quote-details::before {\n top: -8px;\n bottom: auto;\n}\n.dsh-side-chat-quote-details-header { display: flex; align-items: center; justify-content: space-between; gap: 12px; }\n.dsh-side-chat-quote-details-header strong { color: var(--side-chat-muted); font-size: 13px; font-weight: 500; }\n.dsh-side-chat-quote-detail + .dsh-side-chat-quote-detail {\n margin-top: 12px;\n padding-top: 12px;\n border-top: 1px solid var(--side-chat-border);\n}\n.dsh-side-chat-quote pre {\n max-height: 180px;\n margin: 4px 0 0;\n overflow: auto;\n white-space: pre-wrap;\n font: inherit;\n}\n.dsh-side-chat-quote-comment {\n margin-top: 9px;\n}\n.dsh-side-chat-quote-comment > strong { color: var(--side-chat-muted); font-size: 13px; font-weight: 500; }\n.dsh-side-chat-quote-comment > pre { margin-top: 4px; }\n.dsh-side-chat-error { margin: 10px 16px 0; padding: 10px 12px; border: 1px solid var(--side-chat-border); border-radius: 14px; background: var(--dsw-alias-interactive-bg-hover-danger, var(--dsw-surface-subtle, #f7f7f9)); }\n.dsh-side-chat-error { border-color: var(--dsw-alias-state-error-primary, var(--dsw-danger, #b42318)); }\n.dsh-side-chat-body { min-height: 0; flex: 1; overflow: hidden; }\n.dsh-side-chat-annotated-user-message {\n display: flex;\n max-width: 92%;\n align-self: end;\n align-items: flex-start;\n flex-direction: column;\n gap: 8px;\n}\n.dsh-side-chat-annotated-user-message .dsh-side-chat-message { max-width: 100%; align-self: stretch; }\n\n/* The DSH occurrence remains the durable serialization carrier, while this\n plugin-owned capsule supplies the visible and interactive projection. */\n[data-composer-seat] [data-decoration=\"chip\"][title=\"__dsh_side_chat_annotations__\"] {\n visibility: hidden;\n}\n.dsh-side-chat-parent-annotation-dock {\n position: relative;\n z-index: 20;\n width: calc(100% - 32px);\n max-width: var(--dsh-composer-card-max-width, 780px);\n height: 0;\n /* The terminal zero-height dock would otherwise add a second gap between\n Todo/Goal/Queue and the input card. Its child still lands 10px inside the\n following card: -gap + top:16px against the card's own 6px gap. */\n margin: calc(0px - var(--dsh-composer-stack-gap, 6px)) auto 0;\n pointer-events: none;\n}\n.dsh-side-chat-parent-annotation-dock > .dsh-side-chat-quote {\n position: absolute;\n top: 16px;\n left: 16px;\n pointer-events: auto;\n}\n.dsh-side-chat-parent-user-message {\n display: flex;\n width: 100%;\n min-width: 0;\n flex-direction: column;\n align-items: stretch;\n gap: 8px;\n}\n.dsh-side-chat-parent-user-message > .dsh-side-chat-quote { align-self: flex-end; }\n/* rc.6 caps its inner user stack at 82%; give that percentage the full chat\n column as its containing width instead of the annotation chip's shrink width. */\n.dsh-side-chat-parent-user-message-body { width: 100%; min-width: 0; }\n.dsh-side-chat-parent-user-message > .dsh-side-chat-quote .dsh-side-chat-quote-details {\n right: 0;\n left: auto;\n}\n.dsh-side-chat-draft {\n display: grid;\n grid-template-columns: minmax(0, 1fr);\n min-height: 0;\n flex: 0 0 auto;\n gap: 6px;\n align-items: end;\n margin: auto 12px 12px;\n padding: 12px;\n border: 1px solid var(--side-chat-border);\n border-radius: 24px;\n background: var(--side-chat-bg);\n box-shadow: 0 2px 8px rgb(0 0 0 / 5%);\n}\n.dsh-side-chat-draft > .dsh-side-chat-quote { grid-column: 1 / -1; }\n.dsh-side-chat-draft label {\n position: absolute;\n width: 1px;\n height: 1px;\n overflow: hidden;\n clip-path: inset(50%);\n}\n.dsh-side-chat-draft textarea {\n grid-column: 1 / -1;\n width: 100%;\n height: auto;\n min-height: 24px;\n max-height: 160px;\n box-sizing: border-box;\n resize: none;\n overflow-y: hidden;\n padding: 6px 2px;\n border: 0;\n outline: 0;\n background: transparent;\n color: inherit;\n font: inherit;\n line-height: 1.5;\n}\n.dsh-side-chat-panel .dsh-side-chat-send-button,\n.dsh-side-chat-panel .dsh-side-chat-stop-button {\n display: grid;\n width: 34px;\n height: 34px;\n min-height: 34px;\n flex: none;\n place-items: center;\n padding: 1px 6px;\n border: 0;\n border-radius: 999px;\n background: var(--side-chat-accent-fill);\n color: var(--side-chat-accent-text);\n cursor: pointer;\n line-height: 1;\n transform: translateY(-2px);\n transition: background-color 100ms ease;\n}\n.dsh-side-chat-panel .dsh-side-chat-send-button:hover:not(:disabled),\n.dsh-side-chat-panel .dsh-side-chat-stop-button:hover:not(:disabled) {\n background: var(--side-chat-accent-hover);\n}\n.dsh-side-chat-panel .dsh-side-chat-send-button:disabled,\n.dsh-side-chat-panel .dsh-side-chat-stop-button:disabled { cursor: default; opacity: .4; }\n.dsh-side-chat-footer { display: none; }\n.dsh-side-chat-announcer { position: absolute; width: 1px; height: 1px; overflow: hidden; clip-path: inset(50%); }\n\n.dsh-side-chat-selection-actions {\n position: fixed;\n z-index: 90;\n display: flex;\n width: max-content;\n max-width: calc(100vw - 16px);\n box-sizing: border-box;\n flex-wrap: wrap;\n gap: 0;\n padding: 0;\n border: 1px solid var(--side-chat-border);\n border-radius: 999px;\n background: var(--dsw-alias-button-floating-fill, var(--side-chat-bg));\n box-shadow: 0 4px 14px rgb(0 0 0 / 12%);\n color: var(--side-chat-text);\n overflow: hidden;\n}\n.dsh-side-chat-selection-actions button {\n min-height: 36px;\n padding: 0 14px;\n border: 0;\n border-radius: 0;\n background: transparent;\n color: inherit;\n transition: background-color 120ms ease;\n}\n.dsh-side-chat-selection-actions button:hover:not(:disabled),\n.dsh-side-chat-selection-actions button:focus-visible {\n background: var(--dsw-alias-interactive-bg-hover, var(--dsw-surface-subtle, #f3f3f5));\n}\n.dsh-side-chat-selection-actions button + button {\n border-left: 1px solid var(--side-chat-border);\n border-radius: 0;\n}\n.dsh-side-chat-selection-actions[data-touch] button {\n min-height: 42px;\n padding-inline: 14px;\n touch-action: manipulation;\n white-space: nowrap;\n}\n\n::highlight(dsh-side-chat-annotations) {\n background: color-mix(in srgb, var(--dsw-alias-state-business-primary, #1473e6) 18%, transparent);\n}\n::highlight(dsh-side-chat-active-annotation) {\n background: color-mix(in srgb, var(--dsw-alias-state-business-primary, #1473e6) 32%, transparent);\n text-decoration: underline;\n text-decoration-color: color-mix(in srgb, var(--dsw-alias-state-business-primary, #1473e6) 70%, transparent);\n text-decoration-thickness: 1px;\n}\n\n.dsh-side-chat-annotation-marker,\n.dsh-side-chat-selection-marker {\n position: fixed;\n z-index: 91;\n display: grid;\n width: 22px;\n height: 22px;\n min-height: 22px;\n box-sizing: border-box;\n place-items: center;\n padding: 0;\n border: 0;\n border-radius: 999px;\n background: var(--side-chat-accent-fill);\n box-shadow: 0 2px 6px rgb(0 0 0 / 14%);\n color: var(--side-chat-accent-text);\n font: inherit;\n font-size: 11px;\n font-weight: 600;\n line-height: 1;\n}\n.dsh-side-chat-annotation-marker { cursor: pointer; }\n.dsh-side-chat-selection-marker { pointer-events: none; }\n.dsh-side-chat-annotation-marker[data-large],\n.dsh-side-chat-selection-marker[data-large] { font-size: 9px; }\n.dsh-side-chat-annotation-marker[data-active] {\n background: var(--side-chat-accent-hover);\n}\n.dsh-side-chat-annotation-marker:focus-visible {\n outline: 2px solid color-mix(in srgb, var(--side-chat-accent) 32%, transparent);\n outline-offset: 1px;\n}\n\n.dsh-side-chat-selection-comment {\n position: fixed;\n z-index: 92;\n display: grid;\n max-width: calc(100vw - 16px);\n box-sizing: border-box;\n gap: 10px;\n padding: 12px;\n border: 1px solid var(--side-chat-border);\n border-radius: 20px;\n background: var(--side-chat-bg);\n box-shadow: 0 5px 18px rgb(0 0 0 / 9%);\n color: var(--side-chat-text);\n}\n.dsh-side-chat-selection-comment textarea {\n width: 100%;\n min-height: 48px;\n max-height: 128px;\n box-sizing: border-box;\n resize: none;\n padding: 6px 8px;\n overflow-y: auto;\n border: 0;\n outline: 0;\n background: transparent;\n color: inherit;\n font: inherit;\n line-height: 1.45;\n}\n.dsh-side-chat-selection-comment-actions {\n display: flex;\n justify-content: flex-end;\n gap: 8px;\n}\n.dsh-side-chat-selection-comment-actions button {\n min-height: 32px;\n padding: 0 14px;\n border: 1px solid var(--side-chat-border);\n border-radius: 999px;\n background: var(--side-chat-bg);\n color: inherit;\n cursor: pointer;\n font: inherit;\n}\n.dsh-side-chat-selection-comment-actions button:hover { background: var(--dsw-alias-interactive-bg-hover, var(--dsw-surface-subtle, #f3f3f5)); }\n.dsh-side-chat-selection-comment-actions .dsh-side-chat-selection-comment-save {\n border-color: transparent;\n background: var(--side-chat-accent-fill);\n color: var(--side-chat-accent-text);\n}\n.dsh-side-chat-selection-comment-actions .dsh-side-chat-selection-comment-save:hover {\n background: var(--side-chat-accent-hover);\n}\n\n@media (max-width: 900px) {\n .dsh-side-chat-panel {\n right: 12px;\n bottom: 12px;\n width: calc(100vw - 24px);\n max-height: calc(100dvh - 24px);\n border-radius: 24px;\n }\n}\n\n@media (max-width: 720px) {\n .dsh-side-chat-panel {\n right: 8px;\n bottom: 8px;\n width: calc(100vw - 16px);\n height: min(78dvh, 760px);\n max-height: calc(100dvh - 16px);\n border-radius: 22px;\n }\n .dsh-side-chat-transcript { padding: 14px 14px 20px; }\n .dsh-side-chat-header { padding-left: 14px; }\n .dsh-side-chat-error { margin-inline: 12px; }\n}\n\n@media (max-height: 620px) {\n .dsh-side-chat-panel {\n bottom: 8px;\n height: calc(100dvh - 16px);\n max-height: calc(100dvh - 16px);\n }\n}\n\n@media (prefers-reduced-motion: reduce) {\n .dsh-side-chat-reasoning[data-state=\"running\"] .dsh-side-chat-reasoning-row::after { animation: none; }\n}\n\n@media (prefers-reduced-motion: no-preference) {\n .dsh-side-chat-panel { animation: dsh-side-chat-enter 160ms ease-out; }\n @keyframes dsh-side-chat-enter { from { transform: translateY(18px) scale(.985); opacity: .7; } }\n}\n\n@media (forced-colors: active) {\n.dsh-side-chat-panel,\n.dsh-side-chat-selection-actions,\n.dsh-side-chat-selection-comment,\n.dsh-side-chat-annotation-marker { border: 1px solid CanvasText; }\n}\n";
|
|
12
|
+
function referenceDisplayText(label) {
|
|
13
|
+
return `@${label}`;
|
|
14
|
+
}
|
|
15
|
+
/**
|
|
16
|
+
* Resolve one occurrence's occupied draft range across both DSH reference
|
|
17
|
+
* representations: current full `@label` text with `length`, and the legacy
|
|
18
|
+
* one-code-unit U+FFFC placeholder without it.
|
|
19
|
+
*/
|
|
20
|
+
function occurrenceRange(snapshot, occurrence, expectedLabel) {
|
|
21
|
+
const start = occurrence.offset;
|
|
22
|
+
if (!Number.isSafeInteger(start) || start < 0 || start > snapshot.draft.length) return;
|
|
23
|
+
if (occurrence.length !== void 0 && Number.isSafeInteger(occurrence.length) && occurrence.length > 0 && start + occurrence.length <= snapshot.draft.length) return {
|
|
24
|
+
start,
|
|
25
|
+
end: start + occurrence.length
|
|
26
|
+
};
|
|
27
|
+
if (snapshot.draft.startsWith("", start)) return {
|
|
28
|
+
start,
|
|
29
|
+
end: start + 1
|
|
30
|
+
};
|
|
31
|
+
const display = referenceDisplayText(expectedLabel);
|
|
32
|
+
if (snapshot.draft.startsWith(display, start)) return {
|
|
33
|
+
start,
|
|
34
|
+
end: start + display.length
|
|
35
|
+
};
|
|
36
|
+
}
|
|
37
|
+
function occurrenceMatchesDraft(snapshot, occurrence, expectedLabel) {
|
|
38
|
+
const range = occurrenceRange(snapshot, occurrence, expectedLabel);
|
|
39
|
+
if (range === void 0) return false;
|
|
40
|
+
const text = snapshot.draft.slice(range.start, range.end);
|
|
41
|
+
return text === "" || text === referenceDisplayText(expectedLabel);
|
|
42
|
+
}
|
|
43
|
+
/** Find the exact occurrence minted by one synchronous insertReference call. */
|
|
44
|
+
function newlyInsertedOccurrence(before, after, source, ref) {
|
|
45
|
+
const previousIds = new Set(before.occurrences.map((occurrence) => occurrence.occurrenceId));
|
|
46
|
+
const inserted = after.occurrences.filter((occurrence) => !previousIds.has(occurrence.occurrenceId) && occurrence.source === source && occurrence.ref === ref);
|
|
47
|
+
return inserted.length === 1 ? inserted[0] : void 0;
|
|
48
|
+
}
|
|
49
|
+
/** Remove one occurrence's display range and, optionally, its separating ASCII gap. */
|
|
50
|
+
function draftWithoutOccurrence(snapshot, occurrence, expectedLabel, options = {}) {
|
|
51
|
+
const range = occurrenceRange(snapshot, occurrence, expectedLabel);
|
|
52
|
+
if (range === void 0) return;
|
|
53
|
+
let { start, end } = range;
|
|
54
|
+
if (options.consumeAdjacentSpace === true) {
|
|
55
|
+
if (snapshot.draft[end] === " ") end += 1;
|
|
56
|
+
else if (start > 0 && snapshot.draft[start - 1] === " ") start -= 1;
|
|
57
|
+
}
|
|
58
|
+
return snapshot.draft.slice(0, start) + snapshot.draft.slice(end);
|
|
59
|
+
}
|
|
12
60
|
//#endregion
|
|
13
61
|
//#region src/client/parent-composer/add-to-conversation.ts
|
|
14
62
|
const SELECTION_REFERENCE_SOURCE = "dsh-side-chat-selection";
|
|
15
|
-
const
|
|
63
|
+
const SELECTION_REFERENCE_LABEL = "__dsh_side_chat_annotations__";
|
|
16
64
|
function escapeXmlText(value) {
|
|
17
65
|
return value.replaceAll("&", "&").replaceAll("<", "<").replaceAll(">", ">");
|
|
18
66
|
}
|
|
@@ -127,11 +175,19 @@ window.__ModuleLoader__.load({
|
|
|
127
175
|
}
|
|
128
176
|
function draftWithoutSelectionOccurrences(snapshot) {
|
|
129
177
|
const occurrences = [...selectionOccurrences(snapshot)].sort((a, b) => b.offset - a.offset);
|
|
130
|
-
let
|
|
131
|
-
for (const occurrence of occurrences)
|
|
178
|
+
let current = snapshot;
|
|
179
|
+
for (const occurrence of occurrences) {
|
|
180
|
+
const draft = draftWithoutOccurrence(current, occurrence, SELECTION_REFERENCE_LABEL);
|
|
181
|
+
if (draft === void 0) continue;
|
|
182
|
+
current = {
|
|
183
|
+
...current,
|
|
184
|
+
draft
|
|
185
|
+
};
|
|
186
|
+
}
|
|
187
|
+
let draft = current.draft;
|
|
132
188
|
if (occurrences.some((occurrence) => occurrence.offset === 0)) {
|
|
133
189
|
if (draft.startsWith("\n\n")) draft = draft.slice(2);
|
|
134
|
-
else if (draft.startsWith("\n")) draft = draft.slice(1);
|
|
190
|
+
else if (draft.startsWith("\n") || draft.startsWith(" ")) draft = draft.slice(1);
|
|
135
191
|
}
|
|
136
192
|
return draft;
|
|
137
193
|
}
|
|
@@ -159,11 +215,12 @@ window.__ModuleLoader__.load({
|
|
|
159
215
|
};
|
|
160
216
|
function writeConversationAnnotations(input, before, annotations) {
|
|
161
217
|
const draft = draftWithoutSelectionOccurrences(before);
|
|
162
|
-
if (selectionOccurrences(before).length > 0) input.setDraft(draft);
|
|
163
218
|
const insertionState = input.state.getSnapshot();
|
|
219
|
+
if (insertionState.draftRev !== before.draftRev || insertionState.draft !== before.draft) return false;
|
|
220
|
+
const ref = encodeSelectionReference(annotations);
|
|
164
221
|
if (!input.insertReference({
|
|
165
222
|
source: SELECTION_REFERENCE_SOURCE,
|
|
166
|
-
ref
|
|
223
|
+
ref,
|
|
167
224
|
label: "__dsh_side_chat_annotations__",
|
|
168
225
|
clipboardText: annotations.map((annotation) => annotation.text).join("\n\n")
|
|
169
226
|
}, {
|
|
@@ -171,14 +228,63 @@ window.__ModuleLoader__.load({
|
|
|
171
228
|
end: 0,
|
|
172
229
|
draftRev: insertionState.draftRev
|
|
173
230
|
})) return false;
|
|
174
|
-
input.
|
|
175
|
-
|
|
231
|
+
const afterInsert = input.state.getSnapshot();
|
|
232
|
+
const occurrence = newlyInsertedOccurrence(insertionState, afterInsert, SELECTION_REFERENCE_SOURCE, ref);
|
|
233
|
+
const rollbackInsertion = () => {
|
|
234
|
+
const current = input.state.getSnapshot();
|
|
235
|
+
const insertedOccurrence = occurrence === void 0 ? void 0 : current.occurrences.find((candidate) => candidate.occurrenceId === occurrence.occurrenceId);
|
|
236
|
+
if (insertedOccurrence === void 0 || insertedOccurrence.offset !== 0) return;
|
|
237
|
+
const insertedRange = occurrenceRange(current, insertedOccurrence, SELECTION_REFERENCE_LABEL);
|
|
238
|
+
if (insertedRange === void 0 || insertedRange.start !== 0) return;
|
|
239
|
+
let tail = current.draft.slice(insertedRange.end);
|
|
240
|
+
if (tail.startsWith(" ") && tail.slice(1) === before.draft) tail = before.draft;
|
|
241
|
+
else if (tail !== before.draft) return;
|
|
242
|
+
input.setDraft(tail);
|
|
243
|
+
};
|
|
244
|
+
if (occurrence === void 0 || occurrence.offset !== 0) {
|
|
245
|
+
rollbackInsertion();
|
|
246
|
+
return false;
|
|
247
|
+
}
|
|
248
|
+
const range = occurrenceRange(afterInsert, occurrence, SELECTION_REFERENCE_LABEL);
|
|
249
|
+
if (range === void 0 || range.start !== 0) {
|
|
250
|
+
rollbackInsertion();
|
|
251
|
+
return false;
|
|
252
|
+
}
|
|
253
|
+
let rest = afterInsert.draft.slice(range.end);
|
|
254
|
+
if (rest.startsWith(" ") && rest.slice(1) === before.draft) rest = before.draft;
|
|
255
|
+
else if (rest !== before.draft) {
|
|
256
|
+
rollbackInsertion();
|
|
257
|
+
return false;
|
|
258
|
+
}
|
|
259
|
+
const normalizedDraft = `${afterInsert.draft.slice(range.start, range.end)}\n\n${draft}`;
|
|
260
|
+
const current = input.state.getSnapshot();
|
|
261
|
+
const currentOccurrence = current.occurrences.find((candidate) => candidate.occurrenceId === occurrence.occurrenceId);
|
|
262
|
+
if (current.draftRev !== afterInsert.draftRev || current.draft !== afterInsert.draft || currentOccurrence === void 0 || currentOccurrence.source !== SELECTION_REFERENCE_SOURCE || currentOccurrence.ref !== ref || !occurrenceMatchesDraft(current, currentOccurrence, "__dsh_side_chat_annotations__")) {
|
|
263
|
+
rollbackInsertion();
|
|
264
|
+
return false;
|
|
265
|
+
}
|
|
266
|
+
input.setDraft(normalizedDraft);
|
|
267
|
+
const normalized = input.state.getSnapshot();
|
|
268
|
+
const retained = normalized.occurrences.find((candidate) => candidate.occurrenceId === occurrence.occurrenceId);
|
|
269
|
+
return normalized.draft === normalizedDraft && retained !== void 0 && retained.source === SELECTION_REFERENCE_SOURCE && retained.ref === ref && retained.offset === 0 && occurrenceMatchesDraft(normalized, retained, "__dsh_side_chat_annotations__");
|
|
176
270
|
}
|
|
177
271
|
/** Add one passage to the parent composer's aggregated annotation occurrence. */
|
|
178
272
|
function addSelectionToConversation(input, selection, comment) {
|
|
179
273
|
const before = input.state.getSnapshot();
|
|
180
274
|
return writeConversationAnnotations(input, before, [...storedConversationAnnotations(before), annotationFromSelection(selection, comment)]);
|
|
181
275
|
}
|
|
276
|
+
/** Remove one unsent selected-passage annotation, retaining the aggregate when needed. */
|
|
277
|
+
function removeConversationAnnotation(input, annotationIndex) {
|
|
278
|
+
const before = input.state.getSnapshot();
|
|
279
|
+
const annotations = [...storedConversationAnnotations(before)];
|
|
280
|
+
if (!Number.isSafeInteger(annotationIndex) || annotations[annotationIndex] === void 0) return false;
|
|
281
|
+
annotations.splice(annotationIndex, 1);
|
|
282
|
+
if (annotations.length === 0) {
|
|
283
|
+
input.setDraft(draftWithoutSelectionOccurrences(before));
|
|
284
|
+
return selectionOccurrences(input.state.getSnapshot()).length === 0;
|
|
285
|
+
}
|
|
286
|
+
return writeConversationAnnotations(input, before, annotations);
|
|
287
|
+
}
|
|
182
288
|
/** Replace the optional comment on one unsent selected-passage annotation. */
|
|
183
289
|
function updateConversationAnnotation(input, annotationIndex, comment) {
|
|
184
290
|
const before = input.state.getSnapshot();
|
|
@@ -193,10 +299,71 @@ window.__ModuleLoader__.load({
|
|
|
193
299
|
};
|
|
194
300
|
return writeConversationAnnotations(input, before, annotations);
|
|
195
301
|
}
|
|
302
|
+
function exactClipboardProjection(snapshot, annotationOccurrence, annotationClipboardText) {
|
|
303
|
+
let projected = "";
|
|
304
|
+
let cursor = 0;
|
|
305
|
+
const occurrences = [...snapshot.occurrences].sort((left, right) => left.offset - right.offset);
|
|
306
|
+
for (const occurrence of occurrences) {
|
|
307
|
+
const expectedLabel = occurrence.occurrenceId === annotationOccurrence.occurrenceId ? SELECTION_REFERENCE_LABEL : occurrence.label;
|
|
308
|
+
if (occurrence.length === void 0 && !snapshot.draft.startsWith("", occurrence.offset) && expectedLabel === void 0) return;
|
|
309
|
+
const range = occurrenceRange(snapshot, occurrence, expectedLabel ?? "");
|
|
310
|
+
if (range === void 0 || range.start < cursor) return;
|
|
311
|
+
const clipboardText = occurrence.occurrenceId === annotationOccurrence.occurrenceId ? annotationClipboardText : occurrence.clipboardText;
|
|
312
|
+
if (clipboardText === void 0) return;
|
|
313
|
+
projected += snapshot.draft.slice(cursor, range.start) + clipboardText;
|
|
314
|
+
cursor = range.end;
|
|
315
|
+
}
|
|
316
|
+
return projected + snapshot.draft.slice(cursor);
|
|
317
|
+
}
|
|
318
|
+
function annotationSeparator(draftTail) {
|
|
319
|
+
if (draftTail.startsWith("\n\n")) return "\n\n";
|
|
320
|
+
if (draftTail.startsWith("\n")) return "\n";
|
|
321
|
+
if (draftTail.startsWith(" ")) return " ";
|
|
322
|
+
return "";
|
|
323
|
+
}
|
|
324
|
+
function baseDraftFromMirror(mirrorDraft, clipboardText, expectedBaseDraft) {
|
|
325
|
+
const separators = [
|
|
326
|
+
"\n\n",
|
|
327
|
+
"\n",
|
|
328
|
+
" ",
|
|
329
|
+
""
|
|
330
|
+
];
|
|
331
|
+
if (expectedBaseDraft !== void 0) return separators.some((separator) => mirrorDraft === clipboardText + separator + expectedBaseDraft) ? expectedBaseDraft : void 0;
|
|
332
|
+
for (const separator of separators.slice(0, -1)) {
|
|
333
|
+
const prefix = clipboardText + separator;
|
|
334
|
+
if (mirrorDraft.startsWith(prefix)) return mirrorDraft.slice(prefix.length);
|
|
335
|
+
}
|
|
336
|
+
return mirrorDraft === clipboardText ? "" : void 0;
|
|
337
|
+
}
|
|
338
|
+
/** Describe both the display draft and DSH's persisted clipboard projection. */
|
|
339
|
+
function conversationAnnotationRecoveryRecord(snapshot) {
|
|
340
|
+
const occurrence = selectionOccurrences(snapshot).find((candidate) => candidate.offset === 0);
|
|
341
|
+
const ref = conversationAnnotationReference(snapshot);
|
|
342
|
+
if (occurrence === void 0 || ref === void 0) return;
|
|
343
|
+
const range = occurrenceRange(snapshot, occurrence, SELECTION_REFERENCE_LABEL);
|
|
344
|
+
if (range === void 0 || range.start !== 0) return;
|
|
345
|
+
let annotations;
|
|
346
|
+
try {
|
|
347
|
+
annotations = decodeStoredSelectionReference(ref);
|
|
348
|
+
} catch {
|
|
349
|
+
return;
|
|
350
|
+
}
|
|
351
|
+
const clipboardText = annotations.map((annotation) => annotation.text).join("\n\n");
|
|
352
|
+
const mirrorDraft = exactClipboardProjection(snapshot, occurrence, clipboardText);
|
|
353
|
+
if (mirrorDraft === void 0) return;
|
|
354
|
+
const mirrorPrefix = clipboardText + annotationSeparator(snapshot.draft.slice(range.end));
|
|
355
|
+
if (!mirrorDraft.startsWith(mirrorPrefix)) return;
|
|
356
|
+
return {
|
|
357
|
+
ref,
|
|
358
|
+
displayDraft: snapshot.draft,
|
|
359
|
+
mirrorDraft,
|
|
360
|
+
baseDraft: mirrorDraft.slice(mirrorPrefix.length)
|
|
361
|
+
};
|
|
362
|
+
}
|
|
196
363
|
/** Return the valid aggregated reference currently occupying the leading draft slot. */
|
|
197
364
|
function conversationAnnotationReference(snapshot) {
|
|
198
365
|
const occurrence = selectionOccurrences(snapshot).find((candidate) => candidate.offset === 0);
|
|
199
|
-
if (occurrence === void 0 || !snapshot
|
|
366
|
+
if (occurrence === void 0 || !occurrenceMatchesDraft(snapshot, occurrence, "__dsh_side_chat_annotations__")) return;
|
|
200
367
|
try {
|
|
201
368
|
decodeStoredSelectionReference(occurrence.ref);
|
|
202
369
|
return occurrence.ref;
|
|
@@ -205,9 +372,16 @@ window.__ModuleLoader__.load({
|
|
|
205
372
|
}
|
|
206
373
|
}
|
|
207
374
|
function draftWithoutOrphanedAnnotationPrefix(snapshot) {
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
return snapshot.draft.slice(
|
|
375
|
+
if (snapshot.occurrences.some((occurrence) => occurrence.offset === 0)) return;
|
|
376
|
+
const legacyPrefix = `\n\n`;
|
|
377
|
+
if (snapshot.draft.startsWith(legacyPrefix)) return snapshot.draft.slice(legacyPrefix.length);
|
|
378
|
+
const display = referenceDisplayText(SELECTION_REFERENCE_LABEL);
|
|
379
|
+
if (!snapshot.draft.startsWith(display)) return;
|
|
380
|
+
let rest = snapshot.draft.slice(display.length);
|
|
381
|
+
if (rest.startsWith("\n\n")) rest = rest.slice(2);
|
|
382
|
+
else if (rest.startsWith(" ")) rest = rest.slice(1);
|
|
383
|
+
else return;
|
|
384
|
+
return rest;
|
|
211
385
|
}
|
|
212
386
|
/** Remove the plugin-owned prefix when rc.6 restored its draft without occurrences. */
|
|
213
387
|
function removeOrphanedConversationAnnotationPlaceholder(input) {
|
|
@@ -216,18 +390,26 @@ window.__ModuleLoader__.load({
|
|
|
216
390
|
input.setDraft(draft);
|
|
217
391
|
return true;
|
|
218
392
|
}
|
|
219
|
-
/** Rehydrate a lost
|
|
220
|
-
function restoreConversationAnnotationReference(input, ref) {
|
|
393
|
+
/** Rehydrate a lost occurrence over either its display draft or exact mirror projection. */
|
|
394
|
+
function restoreConversationAnnotationReference(input, ref, expectedMirrorDraft, expectedBaseDraft) {
|
|
221
395
|
let annotations;
|
|
222
396
|
try {
|
|
223
397
|
annotations = decodeStoredSelectionReference(ref);
|
|
224
398
|
} catch {
|
|
225
399
|
return false;
|
|
226
400
|
}
|
|
227
|
-
const
|
|
401
|
+
const snapshot = input.state.getSnapshot();
|
|
402
|
+
const orphanDraft = draftWithoutOrphanedAnnotationPrefix(snapshot);
|
|
403
|
+
const clipboardText = annotations.map((annotation) => annotation.text).join("\n\n");
|
|
404
|
+
const mirrorBaseDraft = expectedMirrorDraft === void 0 ? void 0 : baseDraftFromMirror(expectedMirrorDraft, clipboardText, expectedBaseDraft);
|
|
405
|
+
const draft = orphanDraft ?? (expectedMirrorDraft !== void 0 && snapshot.occurrences.length === 0 && snapshot.draft === expectedMirrorDraft && mirrorBaseDraft !== void 0 ? mirrorBaseDraft : void 0);
|
|
228
406
|
if (draft === void 0) return false;
|
|
229
|
-
input.setDraft(draft);
|
|
230
|
-
|
|
407
|
+
if (draft !== snapshot.draft) input.setDraft(draft);
|
|
408
|
+
const beforeWrite = input.state.getSnapshot();
|
|
409
|
+
if (beforeWrite.draft !== draft || beforeWrite.occurrences.length !== 0) return false;
|
|
410
|
+
if (writeConversationAnnotations(input, beforeWrite, annotations)) return true;
|
|
411
|
+
if (input.state.getSnapshot().occurrences.length === 0 && expectedMirrorDraft !== void 0) input.setDraft(expectedMirrorDraft);
|
|
412
|
+
return false;
|
|
231
413
|
}
|
|
232
414
|
function unescapeXmlText(value) {
|
|
233
415
|
return value.replaceAll("<", "<").replaceAll(">", ">").replaceAll("&", "&");
|
|
@@ -566,23 +748,18 @@ window.__ModuleLoader__.load({
|
|
|
566
748
|
}
|
|
567
749
|
});
|
|
568
750
|
}
|
|
569
|
-
function occurrenceLength(occurrence) {
|
|
570
|
-
if (occurrence.length !== void 0 && Number.isSafeInteger(occurrence.length) && occurrence.length > 0) return occurrence.length;
|
|
571
|
-
try {
|
|
572
|
-
return `@${decodeReferencedConversation(occurrence.ref).title}`.length;
|
|
573
|
-
} catch {
|
|
574
|
-
return 1;
|
|
575
|
-
}
|
|
576
|
-
}
|
|
577
751
|
function removeOccurrence(input, occurrenceId) {
|
|
578
752
|
const snapshot = input.state.getSnapshot();
|
|
579
753
|
const occurrence = snapshot.occurrences.find((candidate) => candidate.occurrenceId === occurrenceId);
|
|
580
754
|
if (occurrence === void 0) return;
|
|
581
|
-
let
|
|
582
|
-
|
|
583
|
-
|
|
584
|
-
|
|
585
|
-
|
|
755
|
+
let title;
|
|
756
|
+
try {
|
|
757
|
+
title = decodeReferencedConversation(occurrence.ref).title;
|
|
758
|
+
} catch {
|
|
759
|
+
return;
|
|
760
|
+
}
|
|
761
|
+
const draft = draftWithoutOccurrence(snapshot, occurrence, title, { consumeAdjacentSpace: true });
|
|
762
|
+
if (draft !== void 0) input.setDraft(draft);
|
|
586
763
|
}
|
|
587
764
|
/** Insert or refresh one Side Chat label without duplicating an older snapshot. */
|
|
588
765
|
function addReferencedSideChatToConversation(input, reference) {
|
|
@@ -6561,86 +6738,102 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
|
|
|
6561
6738
|
const edge = 8;
|
|
6562
6739
|
const width = Math.max(0, size.width);
|
|
6563
6740
|
const height = Math.max(0, size.height);
|
|
6564
|
-
const
|
|
6741
|
+
const viewportLeft = viewport.offsetLeft ?? 0;
|
|
6742
|
+
const viewportTop = viewport.offsetTop ?? 0;
|
|
6743
|
+
const viewportRight = viewportLeft + viewport.width;
|
|
6744
|
+
const viewportBottom = viewportTop + viewport.height;
|
|
6745
|
+
const left = clamp(rect.x + rect.width / 2 - width / 2, viewportLeft + edge, viewportRight - width - edge);
|
|
6565
6746
|
const belowGap = touch ? 12 : 8;
|
|
6566
6747
|
const aboveGap = touch ? 64 : 8;
|
|
6567
6748
|
const below = rect.y + rect.height + belowGap;
|
|
6568
6749
|
const above = rect.y - height - aboveGap;
|
|
6569
|
-
const belowFits = below + height <=
|
|
6570
|
-
const aboveFits = above >= edge;
|
|
6750
|
+
const belowFits = below + height <= viewportBottom - edge;
|
|
6751
|
+
const aboveFits = above >= viewportTop + edge;
|
|
6571
6752
|
let top;
|
|
6572
|
-
if (
|
|
6753
|
+
if (belowFits) top = below;
|
|
6573
6754
|
else if (aboveFits) top = above;
|
|
6574
|
-
else
|
|
6575
|
-
else top = rect.y - aboveGap - edge >= viewport.height - edge - rect.y - rect.height - belowGap ? above : below;
|
|
6755
|
+
else top = rect.y - aboveGap - viewportTop - edge >= viewportBottom - edge - rect.y - rect.height - belowGap ? above : below;
|
|
6576
6756
|
return {
|
|
6577
6757
|
left,
|
|
6578
|
-
top: clamp(top, edge,
|
|
6758
|
+
top: clamp(top, viewportTop + edge, viewportBottom - height - edge)
|
|
6579
6759
|
};
|
|
6580
6760
|
}
|
|
6581
|
-
function SelectionActions({ selection, touchInteraction = false, askDisabledReason, annotationNumber = 1, annotationEditor, onAddToChat, onMoreDetails, onAskInSideChat, onAnnotationEditorChange, onDismiss }) {
|
|
6761
|
+
function SelectionActions({ selection, touchInteraction = false, askDisabledReason, annotationNumber = 1, annotationEditor, onAddToChat, onMoreDetails, onAskInSideChat, onAnnotationEditorChange, onRemoveAnnotation, onDismiss }) {
|
|
6582
6762
|
const [editingAnnotation, setEditingAnnotation] = (0, react.useState)(annotationEditor !== void 0);
|
|
6583
6763
|
const [comment, setComment] = (0, react.useState)(annotationEditor?.initialComment ?? "");
|
|
6584
|
-
const [
|
|
6764
|
+
const [toolbarSize, setToolbarSize] = (0, react.useState)(() => ({
|
|
6585
6765
|
width: 0,
|
|
6586
|
-
height: 0
|
|
6587
|
-
|
|
6588
|
-
|
|
6766
|
+
height: 0
|
|
6767
|
+
}));
|
|
6768
|
+
const [viewport, setViewport] = (0, react.useState)(() => ({
|
|
6769
|
+
width: selection.rect.viewportWidth,
|
|
6770
|
+
height: selection.rect.viewportHeight,
|
|
6771
|
+
offsetLeft: 0,
|
|
6772
|
+
offsetTop: 0
|
|
6589
6773
|
}));
|
|
6590
6774
|
const commentRef = (0, react.useRef)(null);
|
|
6591
6775
|
const toolbarRef = (0, react.useRef)(null);
|
|
6592
6776
|
const touchActivationRef = (0, react.useRef)(null);
|
|
6593
|
-
const toolbarPosition = calculateSelectionActionsPosition(selection.rect,
|
|
6594
|
-
width: toolbarGeometry.viewportWidth,
|
|
6595
|
-
height: toolbarGeometry.viewportHeight
|
|
6596
|
-
});
|
|
6777
|
+
const toolbarPosition = calculateSelectionActionsPosition(selection.rect, toolbarSize, touchInteraction, viewport);
|
|
6597
6778
|
const style = {
|
|
6598
6779
|
left: toolbarPosition.left,
|
|
6599
6780
|
top: toolbarPosition.top
|
|
6600
6781
|
};
|
|
6601
|
-
const
|
|
6602
|
-
const
|
|
6782
|
+
const viewportLeft = viewport.offsetLeft;
|
|
6783
|
+
const viewportTop = viewport.offsetTop;
|
|
6784
|
+
const viewportRight = viewportLeft + viewport.width;
|
|
6785
|
+
const viewportBottom = viewportTop + viewport.height;
|
|
6786
|
+
const editorEdge = 8;
|
|
6787
|
+
const editorHeight = 118;
|
|
6788
|
+
const editorWidth = Math.max(0, Math.min(420, viewport.width - 16));
|
|
6789
|
+
const editorAbove = selection.rect.y - editorHeight;
|
|
6790
|
+
const editorBelow = selection.rect.y + selection.rect.height + 12;
|
|
6603
6791
|
const editorStyle = {
|
|
6604
|
-
left: clamp(selection.rect.x + selection.rect.width + 28,
|
|
6605
|
-
top: editorAbove >=
|
|
6792
|
+
left: clamp(selection.rect.x + selection.rect.width + 28, viewportLeft + editorEdge, viewportRight - editorWidth - editorEdge),
|
|
6793
|
+
top: clamp(editorAbove >= viewportTop + editorEdge ? editorAbove : editorBelow, viewportTop + editorEdge, viewportBottom - editorHeight - editorEdge),
|
|
6606
6794
|
width: editorWidth
|
|
6607
6795
|
};
|
|
6796
|
+
const markerEdge = 4;
|
|
6797
|
+
const markerSize = 22;
|
|
6608
6798
|
const markerStyle = {
|
|
6609
|
-
left: clamp(selection.rect.x + selection.rect.width + 3,
|
|
6610
|
-
top: clamp(selection.rect.y - 12,
|
|
6799
|
+
left: clamp(selection.rect.x + selection.rect.width + 3, viewportLeft + markerEdge, viewportRight - markerSize - markerEdge),
|
|
6800
|
+
top: clamp(selection.rect.y - 12, viewportTop + markerEdge, viewportBottom - markerSize - markerEdge)
|
|
6611
6801
|
};
|
|
6612
6802
|
const markerNumber = annotationNumber > 99 ? "99+" : String(annotationNumber);
|
|
6613
6803
|
const keepSelection = (event) => {
|
|
6614
6804
|
event.preventDefault();
|
|
6615
6805
|
};
|
|
6616
6806
|
(0, react.useLayoutEffect)(() => {
|
|
6617
|
-
|
|
6618
|
-
const toolbar = toolbarRef.current;
|
|
6619
|
-
if (toolbar === null) return;
|
|
6807
|
+
const visualViewport = window.visualViewport;
|
|
6620
6808
|
const measure = () => {
|
|
6809
|
+
const nextViewport = {
|
|
6810
|
+
width: visualViewport?.width ?? window.innerWidth ?? selection.rect.viewportWidth,
|
|
6811
|
+
height: visualViewport?.height ?? window.innerHeight ?? selection.rect.viewportHeight,
|
|
6812
|
+
offsetLeft: visualViewport?.offsetLeft ?? 0,
|
|
6813
|
+
offsetTop: visualViewport?.offsetTop ?? 0
|
|
6814
|
+
};
|
|
6815
|
+
setViewport((current) => current.width === nextViewport.width && current.height === nextViewport.height && current.offsetLeft === nextViewport.offsetLeft && current.offsetTop === nextViewport.offsetTop ? current : nextViewport);
|
|
6816
|
+
const toolbar = toolbarRef.current;
|
|
6817
|
+
if (toolbar === null) return;
|
|
6621
6818
|
const bounds = toolbar.getBoundingClientRect();
|
|
6622
|
-
const
|
|
6623
|
-
const viewportWidth = visualViewport?.width ?? window.innerWidth ?? selection.rect.viewportWidth;
|
|
6624
|
-
const viewportHeight = visualViewport?.height ?? window.innerHeight ?? selection.rect.viewportHeight;
|
|
6625
|
-
const next = {
|
|
6819
|
+
const nextSize = {
|
|
6626
6820
|
width: bounds.width,
|
|
6627
|
-
height: bounds.height
|
|
6628
|
-
viewportWidth,
|
|
6629
|
-
viewportHeight
|
|
6821
|
+
height: bounds.height
|
|
6630
6822
|
};
|
|
6631
|
-
|
|
6823
|
+
setToolbarSize((current) => current.width === nextSize.width && current.height === nextSize.height ? current : nextSize);
|
|
6632
6824
|
};
|
|
6633
6825
|
measure();
|
|
6826
|
+
const toolbar = toolbarRef.current;
|
|
6634
6827
|
const observer = typeof ResizeObserver === "undefined" ? void 0 : new ResizeObserver(measure);
|
|
6635
|
-
observer?.observe(toolbar);
|
|
6828
|
+
if (toolbar !== null) observer?.observe(toolbar);
|
|
6636
6829
|
window.addEventListener("resize", measure);
|
|
6637
|
-
|
|
6638
|
-
|
|
6830
|
+
visualViewport?.addEventListener("resize", measure);
|
|
6831
|
+
visualViewport?.addEventListener("scroll", measure);
|
|
6639
6832
|
return () => {
|
|
6640
6833
|
observer?.disconnect();
|
|
6641
6834
|
window.removeEventListener("resize", measure);
|
|
6642
|
-
|
|
6643
|
-
|
|
6835
|
+
visualViewport?.removeEventListener("resize", measure);
|
|
6836
|
+
visualViewport?.removeEventListener("scroll", measure);
|
|
6644
6837
|
};
|
|
6645
6838
|
}, [
|
|
6646
6839
|
editingAnnotation,
|
|
@@ -6654,7 +6847,7 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
|
|
|
6654
6847
|
setEditingAnnotation(false);
|
|
6655
6848
|
setComment("");
|
|
6656
6849
|
onAnnotationEditorChange?.(false);
|
|
6657
|
-
|
|
6850
|
+
onDismiss();
|
|
6658
6851
|
};
|
|
6659
6852
|
const saveAnnotation = () => {
|
|
6660
6853
|
const trimmed = comment.trim();
|
|
@@ -6739,15 +6932,23 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
|
|
|
6739
6932
|
onKeyDown: annotationKeyDown
|
|
6740
6933
|
}), /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
6741
6934
|
className: "dsh-side-chat-selection-comment-actions",
|
|
6742
|
-
children: [
|
|
6743
|
-
|
|
6744
|
-
|
|
6745
|
-
|
|
6746
|
-
|
|
6747
|
-
|
|
6748
|
-
|
|
6749
|
-
|
|
6750
|
-
|
|
6935
|
+
children: [
|
|
6936
|
+
annotationEditor !== void 0 && onRemoveAnnotation !== void 0 && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
|
|
6937
|
+
type: "button",
|
|
6938
|
+
onClick: onRemoveAnnotation,
|
|
6939
|
+
children: "Remove"
|
|
6940
|
+
}),
|
|
6941
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
|
|
6942
|
+
type: "button",
|
|
6943
|
+
onClick: closeEditor,
|
|
6944
|
+
children: "Cancel"
|
|
6945
|
+
}),
|
|
6946
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
|
|
6947
|
+
type: "submit",
|
|
6948
|
+
className: "dsh-side-chat-selection-comment-save",
|
|
6949
|
+
children: "Save"
|
|
6950
|
+
})
|
|
6951
|
+
]
|
|
6751
6952
|
})]
|
|
6752
6953
|
})] });
|
|
6753
6954
|
return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
@@ -7812,14 +8013,19 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
|
|
|
7812
8013
|
return `${STORAGE_PREFIX}${encodeURIComponent(sessionId)}`;
|
|
7813
8014
|
}
|
|
7814
8015
|
function recordOf(snapshot) {
|
|
7815
|
-
const
|
|
7816
|
-
return
|
|
7817
|
-
version:
|
|
7818
|
-
|
|
7819
|
-
ref
|
|
8016
|
+
const record = conversationAnnotationRecoveryRecord(snapshot);
|
|
8017
|
+
return record === void 0 ? void 0 : {
|
|
8018
|
+
version: 2,
|
|
8019
|
+
...record
|
|
7820
8020
|
};
|
|
7821
8021
|
}
|
|
7822
|
-
|
|
8022
|
+
function displayDraft(record) {
|
|
8023
|
+
return record.version === 1 ? record.draft : record.displayDraft;
|
|
8024
|
+
}
|
|
8025
|
+
function mirrorDraft(record) {
|
|
8026
|
+
return record.version === 1 ? record.projection : record.mirrorDraft;
|
|
8027
|
+
}
|
|
8028
|
+
/** Tab-scoped recovery for drafts persisted as a reference clipboard projection. */
|
|
7823
8029
|
var ConversationAnnotationPersistence = class {
|
|
7824
8030
|
storage;
|
|
7825
8031
|
observedSessions = /* @__PURE__ */ new Set();
|
|
@@ -7836,12 +8042,18 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
|
|
|
7836
8042
|
return;
|
|
7837
8043
|
}
|
|
7838
8044
|
const stored = this.read(key);
|
|
7839
|
-
if (stored !== void 0
|
|
7840
|
-
|
|
7841
|
-
|
|
7842
|
-
|
|
7843
|
-
|
|
7844
|
-
|
|
8045
|
+
if (stored !== void 0) {
|
|
8046
|
+
const exactDisplayDraft = snapshot.draft === displayDraft(stored);
|
|
8047
|
+
const storedMirrorDraft = mirrorDraft(stored);
|
|
8048
|
+
const exactMirrorDraft = storedMirrorDraft !== void 0 && snapshot.draft === storedMirrorDraft;
|
|
8049
|
+
if (exactDisplayDraft || exactMirrorDraft) {
|
|
8050
|
+
this.observedSessions.add(key);
|
|
8051
|
+
if (restoreConversationAnnotationReference(input, stored.ref, storedMirrorDraft, stored.version === 2 ? stored.baseDraft : void 0)) return;
|
|
8052
|
+
if (storedMirrorDraft !== void 0 && input.state.getSnapshot().draft === storedMirrorDraft) return;
|
|
8053
|
+
this.remove(key);
|
|
8054
|
+
removeOrphanedConversationAnnotationPlaceholder(input);
|
|
8055
|
+
return;
|
|
8056
|
+
}
|
|
7845
8057
|
}
|
|
7846
8058
|
if (this.observedSessions.has(key)) {
|
|
7847
8059
|
this.remove(key);
|
|
@@ -7858,9 +8070,17 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
|
|
|
7858
8070
|
const raw = this.storage.getItem(key);
|
|
7859
8071
|
if (raw === null) return;
|
|
7860
8072
|
const value = JSON.parse(raw);
|
|
7861
|
-
|
|
8073
|
+
if (value.version === 1 && typeof value.draft === "string" && typeof value.ref === "string" && (value.projection === void 0 || typeof value.projection === "string")) return {
|
|
7862
8074
|
version: 1,
|
|
7863
8075
|
draft: value.draft,
|
|
8076
|
+
...value.projection === void 0 ? {} : { projection: value.projection },
|
|
8077
|
+
ref: value.ref
|
|
8078
|
+
};
|
|
8079
|
+
return value.version === 2 && typeof value.displayDraft === "string" && typeof value.mirrorDraft === "string" && typeof value.baseDraft === "string" && typeof value.ref === "string" ? {
|
|
8080
|
+
version: 2,
|
|
8081
|
+
displayDraft: value.displayDraft,
|
|
8082
|
+
mirrorDraft: value.mirrorDraft,
|
|
8083
|
+
baseDraft: value.baseDraft,
|
|
7864
8084
|
ref: value.ref
|
|
7865
8085
|
} : void 0;
|
|
7866
8086
|
} catch {
|
|
@@ -8133,6 +8353,14 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
|
|
|
8133
8353
|
this.annotationPersistence.reconcile(parentSessionId, input);
|
|
8134
8354
|
return true;
|
|
8135
8355
|
}
|
|
8356
|
+
/** Remove one existing unsent annotation from the aggregated occurrence. */
|
|
8357
|
+
removeConversationAnnotation(annotationIndex) {
|
|
8358
|
+
const sessionId = this.currentSessionId();
|
|
8359
|
+
const input = this.currentParentInput();
|
|
8360
|
+
if (sessionId === void 0 || input === void 0 || !removeConversationAnnotation(input, annotationIndex)) return false;
|
|
8361
|
+
this.annotationPersistence.reconcile(sessionId, input);
|
|
8362
|
+
return true;
|
|
8363
|
+
}
|
|
8136
8364
|
/** Update an existing unsent annotation without adding a duplicate passage. */
|
|
8137
8365
|
updateConversationAnnotation(annotationIndex, comment) {
|
|
8138
8366
|
const sessionId = this.currentSessionId();
|
|
@@ -8623,6 +8851,21 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
|
|
|
8623
8851
|
onAnnotationEditorChange: (open) => {
|
|
8624
8852
|
annotationEditing.current = open;
|
|
8625
8853
|
},
|
|
8854
|
+
onRemoveAnnotation: () => {
|
|
8855
|
+
try {
|
|
8856
|
+
if (!sessions.removeConversationAnnotation(editingAnnotation.annotationIndex)) sessions.notify({
|
|
8857
|
+
kind: "warning",
|
|
8858
|
+
text: "Could not remove the annotation."
|
|
8859
|
+
});
|
|
8860
|
+
} catch {
|
|
8861
|
+
sessions.notify({
|
|
8862
|
+
kind: "warning",
|
|
8863
|
+
text: "Could not remove the annotation."
|
|
8864
|
+
});
|
|
8865
|
+
}
|
|
8866
|
+
annotationEditing.current = false;
|
|
8867
|
+
setEditingAnnotation(null);
|
|
8868
|
+
},
|
|
8626
8869
|
onMoreDetails: () => {},
|
|
8627
8870
|
onAskInSideChat: () => {},
|
|
8628
8871
|
onDismiss: () => {
|