@ahggg/dsh-side-chat 0.7.1 → 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/lib/client/parent-composer/add-to-conversation.d.ts +15 -53
- package/lib/client/parent-composer/add-to-conversation.d.ts.map +1 -1
- package/lib/client/parent-composer/add-to-conversation.js +214 -60
- 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 +43 -40
- 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 +331 -124
- package/lib/client.js.map +1 -1
- package/package.json +1 -1
package/lib/client.js
CHANGED
|
@@ -9,10 +9,57 @@ 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 OBJECT_REPLACEMENT_CHARACTER = "";
|
|
16
63
|
const SELECTION_REFERENCE_LABEL = "__dsh_side_chat_annotations__";
|
|
17
64
|
function escapeXmlText(value) {
|
|
18
65
|
return value.replaceAll("&", "&").replaceAll("<", "<").replaceAll(">", ">");
|
|
@@ -100,9 +147,6 @@ window.__ModuleLoader__.load({
|
|
|
100
147
|
function selectionOccurrences(snapshot) {
|
|
101
148
|
return snapshot.occurrences.filter((occurrence) => occurrence.source === SELECTION_REFERENCE_SOURCE);
|
|
102
149
|
}
|
|
103
|
-
function occurrenceLength$1(occurrence) {
|
|
104
|
-
return occurrence.length !== void 0 && Number.isSafeInteger(occurrence.length) && occurrence.length > 0 ? occurrence.length : 1;
|
|
105
|
-
}
|
|
106
150
|
function storedConversationAnnotations(snapshot) {
|
|
107
151
|
return selectionOccurrences(snapshot).flatMap((occurrence) => {
|
|
108
152
|
try {
|
|
@@ -131,11 +175,19 @@ window.__ModuleLoader__.load({
|
|
|
131
175
|
}
|
|
132
176
|
function draftWithoutSelectionOccurrences(snapshot) {
|
|
133
177
|
const occurrences = [...selectionOccurrences(snapshot)].sort((a, b) => b.offset - a.offset);
|
|
134
|
-
let
|
|
135
|
-
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;
|
|
136
188
|
if (occurrences.some((occurrence) => occurrence.offset === 0)) {
|
|
137
189
|
if (draft.startsWith("\n\n")) draft = draft.slice(2);
|
|
138
|
-
else if (draft.startsWith("\n")) draft = draft.slice(1);
|
|
190
|
+
else if (draft.startsWith("\n") || draft.startsWith(" ")) draft = draft.slice(1);
|
|
139
191
|
}
|
|
140
192
|
return draft;
|
|
141
193
|
}
|
|
@@ -161,42 +213,78 @@ window.__ModuleLoader__.load({
|
|
|
161
213
|
}
|
|
162
214
|
}
|
|
163
215
|
};
|
|
164
|
-
function annotationClipboardText(annotations) {
|
|
165
|
-
return annotations.map((annotation) => annotation.text).join("\n\n");
|
|
166
|
-
}
|
|
167
216
|
function writeConversationAnnotations(input, before, annotations) {
|
|
168
217
|
const draft = draftWithoutSelectionOccurrences(before);
|
|
169
|
-
if (selectionOccurrences(before).length > 0) input.setDraft(draft);
|
|
170
218
|
const insertionState = input.state.getSnapshot();
|
|
219
|
+
if (insertionState.draftRev !== before.draftRev || insertionState.draft !== before.draft) return false;
|
|
171
220
|
const ref = encodeSelectionReference(annotations);
|
|
172
221
|
if (!input.insertReference({
|
|
173
222
|
source: SELECTION_REFERENCE_SOURCE,
|
|
174
223
|
ref,
|
|
175
224
|
label: "__dsh_side_chat_annotations__",
|
|
176
|
-
clipboardText:
|
|
225
|
+
clipboardText: annotations.map((annotation) => annotation.text).join("\n\n")
|
|
177
226
|
}, {
|
|
178
227
|
start: 0,
|
|
179
228
|
end: 0,
|
|
180
229
|
draftRev: insertionState.draftRev
|
|
181
230
|
})) return false;
|
|
182
|
-
const
|
|
183
|
-
const occurrence =
|
|
184
|
-
const
|
|
185
|
-
|
|
186
|
-
|
|
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();
|
|
187
246
|
return false;
|
|
188
247
|
}
|
|
189
|
-
const
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
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__");
|
|
194
270
|
}
|
|
195
271
|
/** Add one passage to the parent composer's aggregated annotation occurrence. */
|
|
196
272
|
function addSelectionToConversation(input, selection, comment) {
|
|
197
273
|
const before = input.state.getSnapshot();
|
|
198
274
|
return writeConversationAnnotations(input, before, [...storedConversationAnnotations(before), annotationFromSelection(selection, comment)]);
|
|
199
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
|
+
}
|
|
200
288
|
/** Replace the optional comment on one unsent selected-passage annotation. */
|
|
201
289
|
function updateConversationAnnotation(input, annotationIndex, comment) {
|
|
202
290
|
const before = input.state.getSnapshot();
|
|
@@ -211,10 +299,71 @@ window.__ModuleLoader__.load({
|
|
|
211
299
|
};
|
|
212
300
|
return writeConversationAnnotations(input, before, annotations);
|
|
213
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
|
+
}
|
|
214
363
|
/** Return the valid aggregated reference currently occupying the leading draft slot. */
|
|
215
364
|
function conversationAnnotationReference(snapshot) {
|
|
216
365
|
const occurrence = selectionOccurrences(snapshot).find((candidate) => candidate.offset === 0);
|
|
217
|
-
if (occurrence === void 0 ||
|
|
366
|
+
if (occurrence === void 0 || !occurrenceMatchesDraft(snapshot, occurrence, "__dsh_side_chat_annotations__")) return;
|
|
218
367
|
try {
|
|
219
368
|
decodeStoredSelectionReference(occurrence.ref);
|
|
220
369
|
return occurrence.ref;
|
|
@@ -222,34 +371,45 @@ window.__ModuleLoader__.load({
|
|
|
222
371
|
return;
|
|
223
372
|
}
|
|
224
373
|
}
|
|
225
|
-
function draftWithoutOrphanedAnnotationPrefix(snapshot
|
|
374
|
+
function draftWithoutOrphanedAnnotationPrefix(snapshot) {
|
|
226
375
|
if (snapshot.occurrences.some((occurrence) => occurrence.offset === 0)) return;
|
|
227
|
-
const
|
|
228
|
-
if (
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
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;
|
|
385
|
+
}
|
|
386
|
+
/** Remove the plugin-owned prefix when rc.6 restored its draft without occurrences. */
|
|
235
387
|
function removeOrphanedConversationAnnotationPlaceholder(input) {
|
|
236
388
|
const draft = draftWithoutOrphanedAnnotationPrefix(input.state.getSnapshot());
|
|
237
389
|
if (draft === void 0) return false;
|
|
238
390
|
input.setDraft(draft);
|
|
239
391
|
return true;
|
|
240
392
|
}
|
|
241
|
-
/** Rehydrate a lost occurrence
|
|
242
|
-
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) {
|
|
243
395
|
let annotations;
|
|
244
396
|
try {
|
|
245
397
|
annotations = decodeStoredSelectionReference(ref);
|
|
246
398
|
} catch {
|
|
247
399
|
return false;
|
|
248
400
|
}
|
|
249
|
-
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);
|
|
250
406
|
if (draft === void 0) return false;
|
|
251
|
-
input.setDraft(draft);
|
|
252
|
-
|
|
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;
|
|
253
413
|
}
|
|
254
414
|
function unescapeXmlText(value) {
|
|
255
415
|
return value.replaceAll("<", "<").replaceAll(">", ">").replaceAll("&", "&");
|
|
@@ -588,23 +748,18 @@ window.__ModuleLoader__.load({
|
|
|
588
748
|
}
|
|
589
749
|
});
|
|
590
750
|
}
|
|
591
|
-
function occurrenceLength(occurrence) {
|
|
592
|
-
if (occurrence.length !== void 0 && Number.isSafeInteger(occurrence.length) && occurrence.length > 0) return occurrence.length;
|
|
593
|
-
try {
|
|
594
|
-
return `@${decodeReferencedConversation(occurrence.ref).title}`.length;
|
|
595
|
-
} catch {
|
|
596
|
-
return 1;
|
|
597
|
-
}
|
|
598
|
-
}
|
|
599
751
|
function removeOccurrence(input, occurrenceId) {
|
|
600
752
|
const snapshot = input.state.getSnapshot();
|
|
601
753
|
const occurrence = snapshot.occurrences.find((candidate) => candidate.occurrenceId === occurrenceId);
|
|
602
754
|
if (occurrence === void 0) return;
|
|
603
|
-
let
|
|
604
|
-
|
|
605
|
-
|
|
606
|
-
|
|
607
|
-
|
|
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);
|
|
608
763
|
}
|
|
609
764
|
/** Insert or refresh one Side Chat label without duplicating an older snapshot. */
|
|
610
765
|
function addReferencedSideChatToConversation(input, reference) {
|
|
@@ -6583,86 +6738,102 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
|
|
|
6583
6738
|
const edge = 8;
|
|
6584
6739
|
const width = Math.max(0, size.width);
|
|
6585
6740
|
const height = Math.max(0, size.height);
|
|
6586
|
-
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);
|
|
6587
6746
|
const belowGap = touch ? 12 : 8;
|
|
6588
6747
|
const aboveGap = touch ? 64 : 8;
|
|
6589
6748
|
const below = rect.y + rect.height + belowGap;
|
|
6590
6749
|
const above = rect.y - height - aboveGap;
|
|
6591
|
-
const belowFits = below + height <=
|
|
6592
|
-
const aboveFits = above >= edge;
|
|
6750
|
+
const belowFits = below + height <= viewportBottom - edge;
|
|
6751
|
+
const aboveFits = above >= viewportTop + edge;
|
|
6593
6752
|
let top;
|
|
6594
|
-
if (
|
|
6753
|
+
if (belowFits) top = below;
|
|
6595
6754
|
else if (aboveFits) top = above;
|
|
6596
|
-
else
|
|
6597
|
-
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;
|
|
6598
6756
|
return {
|
|
6599
6757
|
left,
|
|
6600
|
-
top: clamp(top, edge,
|
|
6758
|
+
top: clamp(top, viewportTop + edge, viewportBottom - height - edge)
|
|
6601
6759
|
};
|
|
6602
6760
|
}
|
|
6603
|
-
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 }) {
|
|
6604
6762
|
const [editingAnnotation, setEditingAnnotation] = (0, react.useState)(annotationEditor !== void 0);
|
|
6605
6763
|
const [comment, setComment] = (0, react.useState)(annotationEditor?.initialComment ?? "");
|
|
6606
|
-
const [
|
|
6764
|
+
const [toolbarSize, setToolbarSize] = (0, react.useState)(() => ({
|
|
6607
6765
|
width: 0,
|
|
6608
|
-
height: 0
|
|
6609
|
-
|
|
6610
|
-
|
|
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
|
|
6611
6773
|
}));
|
|
6612
6774
|
const commentRef = (0, react.useRef)(null);
|
|
6613
6775
|
const toolbarRef = (0, react.useRef)(null);
|
|
6614
6776
|
const touchActivationRef = (0, react.useRef)(null);
|
|
6615
|
-
const toolbarPosition = calculateSelectionActionsPosition(selection.rect,
|
|
6616
|
-
width: toolbarGeometry.viewportWidth,
|
|
6617
|
-
height: toolbarGeometry.viewportHeight
|
|
6618
|
-
});
|
|
6777
|
+
const toolbarPosition = calculateSelectionActionsPosition(selection.rect, toolbarSize, touchInteraction, viewport);
|
|
6619
6778
|
const style = {
|
|
6620
6779
|
left: toolbarPosition.left,
|
|
6621
6780
|
top: toolbarPosition.top
|
|
6622
6781
|
};
|
|
6623
|
-
const
|
|
6624
|
-
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;
|
|
6625
6791
|
const editorStyle = {
|
|
6626
|
-
left: clamp(selection.rect.x + selection.rect.width + 28,
|
|
6627
|
-
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),
|
|
6628
6794
|
width: editorWidth
|
|
6629
6795
|
};
|
|
6796
|
+
const markerEdge = 4;
|
|
6797
|
+
const markerSize = 22;
|
|
6630
6798
|
const markerStyle = {
|
|
6631
|
-
left: clamp(selection.rect.x + selection.rect.width + 3,
|
|
6632
|
-
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)
|
|
6633
6801
|
};
|
|
6634
6802
|
const markerNumber = annotationNumber > 99 ? "99+" : String(annotationNumber);
|
|
6635
6803
|
const keepSelection = (event) => {
|
|
6636
6804
|
event.preventDefault();
|
|
6637
6805
|
};
|
|
6638
6806
|
(0, react.useLayoutEffect)(() => {
|
|
6639
|
-
|
|
6640
|
-
const toolbar = toolbarRef.current;
|
|
6641
|
-
if (toolbar === null) return;
|
|
6807
|
+
const visualViewport = window.visualViewport;
|
|
6642
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;
|
|
6643
6818
|
const bounds = toolbar.getBoundingClientRect();
|
|
6644
|
-
const
|
|
6645
|
-
const viewportWidth = visualViewport?.width ?? window.innerWidth ?? selection.rect.viewportWidth;
|
|
6646
|
-
const viewportHeight = visualViewport?.height ?? window.innerHeight ?? selection.rect.viewportHeight;
|
|
6647
|
-
const next = {
|
|
6819
|
+
const nextSize = {
|
|
6648
6820
|
width: bounds.width,
|
|
6649
|
-
height: bounds.height
|
|
6650
|
-
viewportWidth,
|
|
6651
|
-
viewportHeight
|
|
6821
|
+
height: bounds.height
|
|
6652
6822
|
};
|
|
6653
|
-
|
|
6823
|
+
setToolbarSize((current) => current.width === nextSize.width && current.height === nextSize.height ? current : nextSize);
|
|
6654
6824
|
};
|
|
6655
6825
|
measure();
|
|
6826
|
+
const toolbar = toolbarRef.current;
|
|
6656
6827
|
const observer = typeof ResizeObserver === "undefined" ? void 0 : new ResizeObserver(measure);
|
|
6657
|
-
observer?.observe(toolbar);
|
|
6828
|
+
if (toolbar !== null) observer?.observe(toolbar);
|
|
6658
6829
|
window.addEventListener("resize", measure);
|
|
6659
|
-
|
|
6660
|
-
|
|
6830
|
+
visualViewport?.addEventListener("resize", measure);
|
|
6831
|
+
visualViewport?.addEventListener("scroll", measure);
|
|
6661
6832
|
return () => {
|
|
6662
6833
|
observer?.disconnect();
|
|
6663
6834
|
window.removeEventListener("resize", measure);
|
|
6664
|
-
|
|
6665
|
-
|
|
6835
|
+
visualViewport?.removeEventListener("resize", measure);
|
|
6836
|
+
visualViewport?.removeEventListener("scroll", measure);
|
|
6666
6837
|
};
|
|
6667
6838
|
}, [
|
|
6668
6839
|
editingAnnotation,
|
|
@@ -6676,7 +6847,7 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
|
|
|
6676
6847
|
setEditingAnnotation(false);
|
|
6677
6848
|
setComment("");
|
|
6678
6849
|
onAnnotationEditorChange?.(false);
|
|
6679
|
-
|
|
6850
|
+
onDismiss();
|
|
6680
6851
|
};
|
|
6681
6852
|
const saveAnnotation = () => {
|
|
6682
6853
|
const trimmed = comment.trim();
|
|
@@ -6761,15 +6932,23 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
|
|
|
6761
6932
|
onKeyDown: annotationKeyDown
|
|
6762
6933
|
}), /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
6763
6934
|
className: "dsh-side-chat-selection-comment-actions",
|
|
6764
|
-
children: [
|
|
6765
|
-
|
|
6766
|
-
|
|
6767
|
-
|
|
6768
|
-
|
|
6769
|
-
|
|
6770
|
-
|
|
6771
|
-
|
|
6772
|
-
|
|
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
|
+
]
|
|
6773
6952
|
})]
|
|
6774
6953
|
})] });
|
|
6775
6954
|
return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
@@ -7833,28 +8012,20 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
|
|
|
7833
8012
|
function storageKey(sessionId) {
|
|
7834
8013
|
return `${STORAGE_PREFIX}${encodeURIComponent(sessionId)}`;
|
|
7835
8014
|
}
|
|
7836
|
-
function clipboardProjection(snapshot) {
|
|
7837
|
-
let draft = snapshot.draft;
|
|
7838
|
-
const occurrences = [...snapshot.occurrences].sort((a, b) => b.offset - a.offset);
|
|
7839
|
-
for (const occurrence of occurrences) {
|
|
7840
|
-
const length = occurrence.length ?? 1;
|
|
7841
|
-
if (!Number.isSafeInteger(occurrence.offset) || occurrence.offset < 0 || !Number.isSafeInteger(length) || length <= 0 || occurrence.offset + length > draft.length || occurrence.clipboardText === void 0) return;
|
|
7842
|
-
draft = draft.slice(0, occurrence.offset) + occurrence.clipboardText + draft.slice(occurrence.offset + length);
|
|
7843
|
-
}
|
|
7844
|
-
return draft;
|
|
7845
|
-
}
|
|
7846
8015
|
function recordOf(snapshot) {
|
|
7847
|
-
const
|
|
7848
|
-
|
|
7849
|
-
|
|
7850
|
-
|
|
7851
|
-
version: 1,
|
|
7852
|
-
draft: snapshot.draft,
|
|
7853
|
-
...projection === void 0 ? {} : { projection },
|
|
7854
|
-
ref
|
|
8016
|
+
const record = conversationAnnotationRecoveryRecord(snapshot);
|
|
8017
|
+
return record === void 0 ? void 0 : {
|
|
8018
|
+
version: 2,
|
|
8019
|
+
...record
|
|
7855
8020
|
};
|
|
7856
8021
|
}
|
|
7857
|
-
|
|
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. */
|
|
7858
8029
|
var ConversationAnnotationPersistence = class {
|
|
7859
8030
|
storage;
|
|
7860
8031
|
observedSessions = /* @__PURE__ */ new Set();
|
|
@@ -7871,12 +8042,18 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
|
|
|
7871
8042
|
return;
|
|
7872
8043
|
}
|
|
7873
8044
|
const stored = this.read(key);
|
|
7874
|
-
if (stored !== void 0
|
|
7875
|
-
|
|
7876
|
-
|
|
7877
|
-
|
|
7878
|
-
|
|
7879
|
-
|
|
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
|
+
}
|
|
7880
8057
|
}
|
|
7881
8058
|
if (this.observedSessions.has(key)) {
|
|
7882
8059
|
this.remove(key);
|
|
@@ -7893,11 +8070,18 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
|
|
|
7893
8070
|
const raw = this.storage.getItem(key);
|
|
7894
8071
|
if (raw === null) return;
|
|
7895
8072
|
const value = JSON.parse(raw);
|
|
7896
|
-
|
|
8073
|
+
if (value.version === 1 && typeof value.draft === "string" && typeof value.ref === "string" && (value.projection === void 0 || typeof value.projection === "string")) return {
|
|
7897
8074
|
version: 1,
|
|
7898
8075
|
draft: value.draft,
|
|
7899
8076
|
...value.projection === void 0 ? {} : { projection: value.projection },
|
|
7900
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,
|
|
8084
|
+
ref: value.ref
|
|
7901
8085
|
} : void 0;
|
|
7902
8086
|
} catch {
|
|
7903
8087
|
return;
|
|
@@ -8169,6 +8353,14 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
|
|
|
8169
8353
|
this.annotationPersistence.reconcile(parentSessionId, input);
|
|
8170
8354
|
return true;
|
|
8171
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
|
+
}
|
|
8172
8364
|
/** Update an existing unsent annotation without adding a duplicate passage. */
|
|
8173
8365
|
updateConversationAnnotation(annotationIndex, comment) {
|
|
8174
8366
|
const sessionId = this.currentSessionId();
|
|
@@ -8659,6 +8851,21 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
|
|
|
8659
8851
|
onAnnotationEditorChange: (open) => {
|
|
8660
8852
|
annotationEditing.current = open;
|
|
8661
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
|
+
},
|
|
8662
8869
|
onMoreDetails: () => {},
|
|
8663
8870
|
onAskInSideChat: () => {},
|
|
8664
8871
|
onDismiss: () => {
|