shadow-claw 1.23.3 → 1.23.4

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (89) hide show
  1. package/bin/assert-version-bump.mjs +60 -38
  2. package/bin/assert-version-bump.test.mjs +74 -11
  3. package/dist/public/agent.worker.js +6 -6
  4. package/dist/public/{app-routes-B0ePT49v.js → app-routes-Bs-riIvr.js} +1 -1
  5. package/dist/public/components/settings/shadow-claw-storage/shadow-claw-storage.html +1 -1
  6. package/dist/public/components/shadow-claw-files/shadow-claw-files.css +1 -1
  7. package/dist/public/components/shadow-claw-files/shadow-claw-files.html +1 -1
  8. package/dist/public/config-BYAuxx3j.js +1 -0
  9. package/dist/public/{configurePeerJs-B7kNU8AQ.js → configurePeerJs-B4Ym9VMj.js} +1 -1
  10. package/dist/public/{connections-xd_66YVU.js → connections-BEn6JYdu.js} +1 -1
  11. package/dist/public/{custom-element-security-CZ92anB8.js → custom-element-security-DdYlUozq.js} +1 -1
  12. package/dist/public/docs/architecture/storage.md +5 -2
  13. package/dist/public/docs/decisions/indexeddb-and-opfs-storage.md +5 -2
  14. package/dist/public/docs/example/article/index.html +2 -2
  15. package/dist/public/docs/publishing/index.html +19 -76
  16. package/dist/public/docs/skill-creator/index.html +2 -2
  17. package/dist/public/{downloadGroupFile-BABv_1mJ.js → downloadGroupFile-Drdvg1Ev.js} +1 -1
  18. package/dist/public/{e2e-bridge-DkS5xFGX.js → e2e-bridge-BQ4KzUt5.js} +1 -1
  19. package/dist/public/{file-viewer-CCSABMsE.js → file-viewer-CcZYw-PS.js} +1 -1
  20. package/dist/public/files/main/~/docs/publishing-to-github-pages.md +17 -82
  21. package/dist/public/{git-BkjrsRXX.js → git-DEUvQTUA.js} +2 -2
  22. package/dist/public/{iframe-sanitizer-L6Jyu__Z.js → iframe-sanitizer-0NS4XLOd.js} +1 -1
  23. package/dist/public/index.html +2 -2
  24. package/dist/public/index.js +1 -1
  25. package/dist/public/{initChatSplitResize-BslPXAXS.js → initChatSplitResize-llGkSJXg.js} +1 -1
  26. package/dist/public/main/index.html +2 -2
  27. package/dist/public/main/memory/index.html +2 -2
  28. package/dist/public/{markdown-6MBrIo-S.js → markdown-CyYR4App.js} +1 -1
  29. package/dist/public/mcp-reconnect-CSx4aMwy.js +1 -0
  30. package/dist/public/{memoryStorage-CjGseKI1.js → memoryStorage-Dwg8NhAZ.js} +1 -1
  31. package/dist/public/{orchestrator-B9KmIj8Q.js → orchestrator-DRfEudXk.js} +18 -18
  32. package/dist/public/orchestrator-o9Fj67BN.js +15 -0
  33. package/dist/public/pages/main/~/docs/publishing-to-github-pages.md +17 -82
  34. package/dist/public/{peerjs-Dv8JNm7v.js → peerjs-CurBuKvk.js} +1 -1
  35. package/dist/public/{push-client-Dqq06wbB.js → push-client-Dii-vPEh.js} +1 -1
  36. package/dist/public/service-worker/fetch-proxy.js +1 -1
  37. package/dist/public/service-worker.js +1 -1
  38. package/dist/public/{shadow-claw-Bd1rfuVC.js → shadow-claw-5IHaDDMJ.js} +2 -2
  39. package/dist/public/{shadow-claw-accounts-DL2l3oM0.js → shadow-claw-accounts-CZvz4iQz.js} +3 -3
  40. package/dist/public/{shadow-claw-channels-BGXDsQ38.js → shadow-claw-channels-BKXFyRS3.js} +1 -1
  41. package/dist/public/{shadow-claw-chat-NXg6zz_l.js → shadow-claw-chat-CCLuhWdI.js} +3 -3
  42. package/dist/public/{shadow-claw-conversations-C8eqGpP9.js → shadow-claw-conversations-DV-87UUh.js} +1 -1
  43. package/dist/public/shadow-claw-file-viewer-Dk2dbAUd.js +577 -0
  44. package/dist/public/shadow-claw-files-BpfpJIuP.js +840 -0
  45. package/dist/public/{shadow-claw-git-C0ntz7aX.js → shadow-claw-git-DRA7_qck.js} +3 -3
  46. package/dist/public/{shadow-claw-integrations-DCXV2r69.js → shadow-claw-integrations-1Xu5snuV.js} +1 -1
  47. package/dist/public/{shadow-claw-llm-CudgFQsS.js → shadow-claw-llm-6Aci1BDP.js} +2 -2
  48. package/dist/public/{shadow-claw-mcp-remote-B8RkpX28.js → shadow-claw-mcp-remote-BUjAeVXC.js} +1 -1
  49. package/dist/public/{shadow-claw-networking-BLiRsrsK.js → shadow-claw-networking-FQe4nCp3.js} +1 -1
  50. package/dist/public/{shadow-claw-notifications-CQhQcjtL.js → shadow-claw-notifications-DV2wibL3.js} +1 -1
  51. package/dist/public/{shadow-claw-page-header-NeRD0tKU.js → shadow-claw-page-header-B63S4HTU.js} +1 -1
  52. package/dist/public/{shadow-claw-pages-DCHnFh6r.js → shadow-claw-pages-DE3jWj5K.js} +3 -3
  53. package/dist/public/{shadow-claw-settings-VAfjKFQg.js → shadow-claw-settings-S6DAKfYx.js} +3 -3
  54. package/dist/public/shadow-claw-storage-DaacA3_K.js +219 -0
  55. package/dist/public/{shadow-claw-task-server-Dk33N_1G.js → shadow-claw-task-server-IjKX042p.js} +1 -1
  56. package/dist/public/{shadow-claw-tasks-xA1VfmWN.js → shadow-claw-tasks-Cy0JYmGU.js} +4 -4
  57. package/dist/public/{shadow-claw-terminal-Du2r0ciq.js → shadow-claw-terminal-znAt7HyP.js} +1 -1
  58. package/dist/public/{shadow-claw-tools-CZj4rq7l.js → shadow-claw-tools-Cutv9Si5.js} +2 -2
  59. package/dist/public/{shadow-claw-webvm-JYUkWICG.js → shadow-claw-webvm-BH8mPDEu.js} +1 -1
  60. package/dist/public/static-main/~/docs/publishing-to-github-pages.md +17 -82
  61. package/dist/public/static-main-manifest.json +1 -1
  62. package/dist/public/{syncWebMcpRegistration-DfpvASnh.js → syncWebMcpRegistration-BqJxaMGR.js} +1 -1
  63. package/package.json +1 -1
  64. package/src/components/settings/shadow-claw-storage/shadow-claw-storage.html +17 -0
  65. package/src/components/settings/shadow-claw-storage/shadow-claw-storage.test.ts +44 -0
  66. package/src/components/settings/shadow-claw-storage/shadow-claw-storage.ts +56 -0
  67. package/src/components/shadow-claw-file-viewer/shadow-claw-file-viewer.test.ts +105 -0
  68. package/src/components/shadow-claw-file-viewer/shadow-claw-file-viewer.ts +11 -9
  69. package/src/components/shadow-claw-files/shadow-claw-files.css +41 -17
  70. package/src/components/shadow-claw-files/shadow-claw-files.html +35 -0
  71. package/src/components/shadow-claw-files/shadow-claw-files.test.ts +219 -0
  72. package/src/components/shadow-claw-files/shadow-claw-files.ts +170 -6
  73. package/src/components/shadow-claw-pages/utils/resolveWorkspaceLinkPath.test.ts +31 -0
  74. package/src/components/shadow-claw-pages/utils/resolveWorkspaceLinkPath.ts +2 -1
  75. package/src/components/shadow-claw-pages/utils/rewriteWorkspacePreviewHtml.test.ts +15 -0
  76. package/src/config/config.test.ts +9 -0
  77. package/src/config/config.ts +5 -0
  78. package/src/core/app-routes.test.ts +56 -0
  79. package/src/core/app-routes.ts +8 -1
  80. package/src/db/openDatabase.test.ts +10 -1
  81. package/src/db/openDatabase.ts +3 -1
  82. package/src/storage/migrateLegacyOpfs.test.ts +327 -0
  83. package/src/storage/migrateLegacyOpfs.ts +117 -0
  84. package/dist/public/config-AL77QAx4.js +0 -1
  85. package/dist/public/mcp-reconnect-DoicazQd.js +0 -1
  86. package/dist/public/orchestrator-4su7iyWj.js +0 -15
  87. package/dist/public/shadow-claw-file-viewer-9Qkwc30T.js +0 -577
  88. package/dist/public/shadow-claw-files-aDyq6Hv7.js +0 -781
  89. package/dist/public/shadow-claw-storage-Cf31np81.js +0 -202
@@ -1,4 +1,4 @@
1
- import{i as e,r as t,t as n}from"./rolldown-runtime-aKtaBQYM.js";import{c as r,r as i}from"./config-AL77QAx4.js";import{n as a,t as o}from"./txPromise-EBECky1b.js";import{t as s}from"./getConfig-D89uJgo5.js";import{_ as c,g as l,h as u,u as d}from"./custom-element-security-CZ92anB8.js";import{n as f}from"./toast-60iDlgiH.js";import{An as p,Tt as m,a as h,bn as g,jn as _,kn as v,t as y,u as b}from"./orchestrator-B9KmIj8Q.js";import{t as x}from"./setConfig-DFMYnYLE.js";import{t as S}from"./browser-nBz_r6l4.js";import{t as C}from"./buffer-9oRIc-5Z.js";import{a as w,n as T,r as E,t as D}from"./toast-D3gxhZpN.js";import{n as O}from"./e2e-bridge-DkS5xFGX.js";import{t as k}from"./shadow-claw-element-DIrv3P6A.js";import{t as A}from"./effect-BEsuusE8.js";import{i as j,n as M,r as N}from"./prompt-api-OUOP-B-R.js";import"./shadow-claw-page-header-action-button-Bmua3mAb.js";import"./shadow-claw-page-header-NeRD0tKU.js";import{t as P}from"./markdown-6MBrIo-S.js";import{i as F,n as I,o as L}from"./peerjs-Dv8JNm7v.js";import{t as R}from"./downloadGroupFile-BABv_1mJ.js";import{t as z}from"./file-viewer-CCSABMsE.js";import{t as B}from"./config-value-oBfKgLT4.js";import"./shadow-claw-dialog-ByyHgxM9.js"
1
+ import{i as e,r as t,t as n}from"./rolldown-runtime-aKtaBQYM.js";import{c as r,r as i}from"./config-BYAuxx3j.js";import{n as a,t as o}from"./txPromise-EBECky1b.js";import{t as s}from"./getConfig-D89uJgo5.js";import{_ as c,g as l,h as u,u as d}from"./custom-element-security-DdYlUozq.js";import{n as f}from"./toast-60iDlgiH.js";import{An as p,Tt as m,a as h,bn as g,jn as _,kn as v,t as y,u as b}from"./orchestrator-DRfEudXk.js";import{t as x}from"./setConfig-DFMYnYLE.js";import{t as S}from"./browser-nBz_r6l4.js";import{t as C}from"./buffer-9oRIc-5Z.js";import{a as w,n as T,r as E,t as D}from"./toast-D3gxhZpN.js";import{n as O}from"./e2e-bridge-BQ4KzUt5.js";import{t as k}from"./shadow-claw-element-DIrv3P6A.js";import{t as A}from"./effect-BEsuusE8.js";import{i as j,n as M,r as N}from"./prompt-api-OUOP-B-R.js";import{t as P}from"./config-value-oBfKgLT4.js";import"./shadow-claw-page-header-action-button-Bmua3mAb.js";import"./shadow-claw-page-header-B63S4HTU.js";import{t as F}from"./markdown-CyYR4App.js";import{i as I,n as L,o as R}from"./peerjs-CurBuKvk.js";import{t as z}from"./downloadGroupFile-Drdvg1Ev.js";import{t as B}from"./file-viewer-CcZYw-PS.js";import"./shadow-claw-dialog-ByyHgxM9.js"
2
2
  /*!
3
3
 
4
4
  JSZip v3.10.1 - A JavaScript class for generating and reading zip files
@@ -2335,10 +2335,10 @@ dialog.chat__prompt-api-dialog::backdrop {
2335
2335
  <input class="chat__attachment-input" type="file" multiple />
2336
2336
  </section>
2337
2337
  </template>
2338
- `,`text/html`),Re=Le.querySelector(`template`);let ze=[];ze=Re?Array.from(Re.content.children):Array.from(Le.head.children).concat(Array.from(Le.body.children));var Be=ze;const Ve=128*1024,He=8e4;async function Ue(e,t){if(!e||typeof e.transaction!=`function`)return!0;try{return B(await s(e,t),!0)}catch{return!0}}const We=`shadow-claw-chat`;var Ge=class extends k{static styles=Ie;static template=Be;activityLogCollapsedOverride=null;activityLogVisibilityMediaQuery=null;db=null;#e;#t;#n;#r;#i;#a;#o;constructor(){super(),K.reset(),this.db=null,this.#n=0,this.#i=0,this.#a=!1,this.#o=0,this.#r=!0,this.#e=0,this.#t=[]}async connectedCallback(){if(!this.shadowRoot)throw Error(`shadowRoot not found`);this.db=await a(),await this.restoreInputAreaHeight(),this.dispatchTerminalSlotReady(),this.setupEffects(),this.setupActivityLogVisibility(),this.bindEventListeners(),await this.checkPromptApiOnboarding()}disconnectedCallback(){this.activityLogVisibilityCleanup(),K.revokeAttachmentObjectUrls(),K.resetNearBottom(),super.disconnectedCallback()}activityLogVisibilityCleanup=()=>{};applyActivityLogVisibility(){let e=this.shadowRoot;if(!e)return;let t=e.querySelector(`.chat__activity-log`);if(!(t instanceof HTMLElement))return;let n=this.activityLogVisibilityMediaQuery?!this.activityLogVisibilityMediaQuery.matches:!1;(typeof this.activityLogCollapsedOverride==`boolean`?this.activityLogCollapsedOverride:n)?t.classList.add(`chat__activity-log--collapsed`):t.classList.remove(`chat__activity-log--collapsed`)}bindEventListeners(){let e=this.shadowRoot;if(!e)return;let t=e.querySelector(`.chat__messages`);if(t instanceof HTMLElement){t.addEventListener(`scroll`,()=>{this.#a||(this.#o+=1,this.isContainerNearBottom(t)||(this.#r=!1)),K.setNearBottom(this.isContainerNearBottom(t)),this.persistGroupScrollState(t)}),t.addEventListener(`click`,e=>{this.handleMessageLinkClick(e)}),t.addEventListener(`shadow-claw-a2ui-action`,async e=>{let{groupId:t,action:n}=e.detail;if(t.startsWith(`room:`)){await y.orchestrator?.routeRoomA2UIAction(t,n);return}if(t.startsWith(`peer:`)){let e=(y.orchestrator?.router)?.findChannel(t);e&&`sendA2UIAction`in e&&await e.sendA2UIAction(t,n)}let r=JSON.stringify(n.dataModel,null,2),i=`[A2UI ACTION]\nsurfaceId: "${n.surfaceId}"\nactionId: "${n.actionId}"\ndataModel:\n${r}\n\nInstructions: The user triggered the "${n.actionId}" action on surface "${n.surfaceId}". The dataModel above contains the current form values. Use the appropriate tool(s) to fulfill the action based on the actionId and dataModel values. After you have a result, call render_component with action "updateDataModel" on surfaceId "${n.surfaceId}" to update the surface (e.g. patch the output field with the result). Do NOT respond with plain text only — always update the surface via render_component.`;y.sendMessage(i,[],n)}),t.addEventListener(`shadow-claw-a2ui-function-response`,async e=>{let{groupId:t,response:n}=e.detail;if(!t.startsWith(`room:`)&&t.startsWith(`peer:`)){let e=(y.orchestrator?.router)?.findChannel(t);e&&`sendA2UIAction`in e&&await e.sendA2UIAction(t,n)}});let e=new ResizeObserver(()=>{this.shouldAutoFollow(t)&&(this.setMessagesScrollTop(t,t.scrollHeight),this.persistGroupScrollState(t))});e.observe(t),this.addCleanup(()=>e.disconnect())}let n=e.querySelector(`.chat__input`);n instanceof HTMLTextAreaElement&&n.addEventListener(`keydown`,e=>{e.key===`Enter`&&!e.shiftKey&&(e.preventDefault(),this.sendMessage()),e.key===`Enter`&&(e.ctrlKey||e.metaKey)&&(e.preventDefault(),this.sendMessage())});let r=e.querySelector(`.chat__input-area`),i=e.querySelector(`.chat__input-resize-handle`);r instanceof HTMLElement&&i instanceof HTMLElement&&this.bindInputResizeEvents(r,i),e.querySelector(`[data-action="send-message"]`)?.addEventListener(`click`,()=>this.sendMessage()),e.querySelector(`[data-action="attach-files"]`)?.addEventListener(`click`,()=>{let t=e.querySelector(`.chat__attachment-input`);t instanceof HTMLInputElement&&(t.value=``,t.click())}),e.querySelector(`.chat__attachment-input`)?.addEventListener(`change`,e=>{e.target instanceof HTMLInputElement&&this.queueSelectedFiles(e.target)}),e.querySelector(`[data-action="compact-chat"]`)?.addEventListener(`click`,()=>this.handleCompactChat()),e.querySelector(`[data-action="clear-chat"]`)?.addEventListener(`click`,()=>this.handleClearChat()),e.querySelector(`[data-action="stop-chat"]`)?.addEventListener(`click`,()=>this.handleStopChat()),e.querySelector(`[data-action="download-chat"]`)?.addEventListener(`click`,()=>this.downloadChat()),e.querySelector(`[data-action="restore-chat"]`)?.addEventListener(`click`,()=>{let t=e.querySelector(`.chat__restore-input`);t instanceof HTMLInputElement&&t.click()}),e.querySelector(`.chat__restore-input`)?.addEventListener(`change`,e=>{e.target instanceof HTMLInputElement&&this.restoreChat(e.target)});let a=e.querySelector(`.chat__body`);a instanceof HTMLElement&&(a.addEventListener(`dragenter`,e=>{this.hasDroppableData(e.dataTransfer)&&(e.preventDefault(),this.#e+=1,this.setDropOverlayVisible(!0))}),a.addEventListener(`dragover`,e=>{this.hasDroppableData(e.dataTransfer)&&e.preventDefault()}),a.addEventListener(`dragleave`,e=>{this.hasDroppableData(e.dataTransfer)&&(e.preventDefault(),this.#e=Math.max(0,this.#e-1),this.#e===0&&this.setDropOverlayVisible(!1))}),a.addEventListener(`drop`,e=>{this.hasDroppableData(e.dataTransfer)&&(e.preventDefault(),this.#e=0,this.setDropOverlayVisible(!1),this.queueDroppedData(e.dataTransfer))}));let o=e.querySelector(`.chat__prompt-api-form`);o instanceof HTMLFormElement&&o.addEventListener(`submit`,e=>{e.preventDefault(),this.confirmPromptApiOnboarding()});let s=e.querySelector(`[data-action="confirm-prompt-api-onboarding"]`);s instanceof HTMLElement&&s.addEventListener(`click`,e=>{e.preventDefault(),this.confirmPromptApiOnboarding()});let c=e.querySelector(`[data-action="configure-other-provider"]`);c instanceof HTMLElement&&c.addEventListener(`click`,e=>{e.preventDefault(),this.bypassPromptApiOnboardingToSettings()})}bindInputResizeEvents(e,t){t.setAttribute(`tabindex`,`0`),t.setAttribute(`role`,`separator`),t.setAttribute(`aria-orientation`,`horizontal`),t.setAttribute(`aria-label`,`Resize chat input area`);let n=()=>{let t=parseFloat(e.style.getPropertyValue(`--chat-input-area-height`));return Number.isFinite(t)&&t>0?t:40},r=()=>{let e=this.clampInputAreaHeight(2**53-1),r=Math.round(this.clampInputAreaHeight(n()));t.setAttribute(`aria-valuemin`,`40`),t.setAttribute(`aria-valuemax`,String(Math.round(e))),t.setAttribute(`aria-valuenow`,String(r))},i=null,a=0,o=0,s=t=>{if(t.pointerId!==i)return;let n=a-t.clientY,s=o+n;this.setInputAreaHeight(e,s),r()},c=()=>{if(i===null)return;i=null,t.classList.remove(`active`),document.removeEventListener(`pointermove`,s);let n=parseFloat(e.style.getPropertyValue(`--chat-input-area-height`));Number.isFinite(n)&&n>0?this.persistInputAreaHeight(n):this.persistInputAreaHeight(0)},l=e=>{e.pointerId===i&&c()};t.addEventListener(`pointerdown`,n=>{if(n.pointerType===`mouse`&&n.button!==0&&n.button!==-1)return;let r=e.querySelector(`.chat__input-wrapper`);if(!(r instanceof HTMLElement))return;n.preventDefault(),i=n.pointerId,a=n.clientY,e.classList.add(`chat__input-area--resized`);let c=parseFloat(e.style.getPropertyValue(`--chat-input-area-height`));o=Number.isFinite(c)&&c>0?c:r.getBoundingClientRect().height||40,t.classList.add(`active`),t.setPointerCapture(n.pointerId),document.addEventListener(`pointermove`,s)}),t.addEventListener(`pointerup`,l),t.addEventListener(`pointercancel`,c),t.addEventListener(`dblclick`,()=>{this.resetInputAreaHeight(e),this.persistInputAreaHeight(0),r(),this.scrollMessagesToBottomIfNeeded()}),t.addEventListener(`keydown`,t=>{let i=t.shiftKey?32:12,a=n(),o=null;if(t.key===`ArrowUp`?o=a+i:t.key===`ArrowDown`?o=a-i:t.key===`Home`?o=40:t.key===`End`&&(o=this.clampInputAreaHeight(2**53-1)),o===null)return;t.preventDefault(),this.setInputAreaHeight(e,o),r();let s=parseFloat(e.style.getPropertyValue(`--chat-input-area-height`));this.persistInputAreaHeight(Number.isFinite(s)&&s>0?this.clampInputAreaHeight(s):0),this.scrollMessagesToBottomIfNeeded()}),r(),this.addCleanup(()=>{c(),t.removeEventListener(`pointerup`,l),t.removeEventListener(`pointercancel`,c)})}buildQueuedAttachmentsFromFiles(e){return e.map(e=>{let t=e.name||`attachment.bin`;return{id:`${Date.now()}-${Math.random().toString(36).slice(2,10)}`,fileName:t,mimeType:F(t,e.type||``),size:e.size,source:{kind:`local-file`,file:e}}})}clampInputAreaHeight(e){let t=Math.floor(window.innerHeight*.45);return Math.max(40,Math.min(Math.max(40,t),e))}deferWorkspaceImageLoads(e){let t=document.createElement(`div`);t.innerHTML=e;let n=Array.from(t.querySelectorAll(`img[src]`));for(let e of n){let t=e.getAttribute(`src`);if(!t)continue;let n=this.resolveWorkspaceLinkPath(t);n&&(e.setAttribute(`data-inline-workspace-src`,n),e.removeAttribute(`src`))}return t.innerHTML}dispatchTerminalSlotReady(){this.dispatchEvent(new CustomEvent(`shadow-claw-terminal-slot-ready`,{bubbles:!0,composed:!0}))}formatAttachmentSize(e){return e<1024?`${e} B`:e<1024*1024?`${(e/1024).toFixed(1)} KB`:`${(e/(1024*1024)).toFixed(1)} MB`}formatAttachmentSubtitle(e){let t=[];return e.mimeType&&t.push(e.mimeType),typeof e.size==`number`&&t.push(this.formatAttachmentSize(e.size)),t.join(` · `)||`Attachment`}formatTokenCount(e){return typeof e==`number`?e.toLocaleString(`en-US`):`–`}getAttachmentIcon(e=``){let t=e.toLowerCase();return t.startsWith(`image/`)?`IMG`:t.startsWith(`video/`)?`VID`:t.startsWith(`audio/`)?`AUD`:t.includes(`pdf`)?`PDF`:t.startsWith(`text/`)||t.includes(`json`)?`TXT`:t.includes(`zip`)||t.includes(`tar`)?`ZIP`:`BIN`}getAttachmentTransportLabel(e,t,n){let r=p(e,t);return r===`text`?`text`:r===`image`&&(n.images||n.routerByFeatures)||r===`audio`&&(n.audio||n.routerByFeatures)||r===`document`&&(n.documents||n.routerByFeatures)?`native`:`fallback`}getContainerDistanceFromBottom(e){return Math.max(0,e.scrollHeight-e.scrollTop-e.clientHeight)}getMessagesContainer(){let e=this.shadowRoot?.querySelector(`.chat__messages`);return e instanceof HTMLElement?e:null}hasDroppableData(e){if(!e)return!1;if(e.files.length>0)return!0;let t=Array.from(e.types||[]);return t.includes(`Files`)||t.includes(`application/x-moz-file`)||t.includes(`text/plain`)}inferAttachmentModelSupport(e=[]){let t=_(y.orchestrator?.model?.toLowerCase()||``);return e.every(e=>{let n=(e.mimeType||``).toLowerCase();return this.isInlineTextMimeType(n)?!0:n.startsWith(`image/`)?t.images||t.routerByFeatures:n.startsWith(`audio/`)?t.audio||t.routerByFeatures:n.startsWith(`video/`)?t.video||t.routerByFeatures:!1})}injectCopyButtons(e){e.querySelectorAll(`pre`).forEach(e=>{if(e.querySelector(`.chat__code-copy-btn`))return;let t=document.createElement(`button`);t.className=`chat__code-copy-btn`,t.type=`button`,t.setAttribute(`aria-label`,`Copy code to clipboard`),t.textContent=`📋 Copy`,t.addEventListener(`click`,async()=>{let n=e.querySelector(`code`),r=n?n.textContent||``:e.textContent||``;try{await navigator.clipboard.writeText(r),t.textContent=`✅ Copied`,t.classList.add(`chat__code-copy-btn--copied`),setTimeout(()=>{t.textContent=`📋 Copy`,t.classList.remove(`chat__code-copy-btn--copied`)},1500)}catch{t.textContent=`⚠️ Failed`,setTimeout(()=>{t.textContent=`📋 Copy`},1500)}}),e.appendChild(t)})}injectMessageCopyButton(e,t){if(e.querySelector(`.chat__msg-copy-btn`))return;let n=e.querySelector(`.chat__message-content`);if(!n)return;let r=document.createElement(`button`);r.className=`chat__msg-copy-btn`,r.type=`button`,r.setAttribute(`aria-label`,`Copy message to clipboard`);let i=`http://www.w3.org/2000/svg`,a=document.createElementNS(i,`svg`);a.setAttribute(`fill`,`none`),a.setAttribute(`stroke-width`,`1.5`),a.setAttribute(`stroke`,`currentColor`),a.setAttribute(`viewBox`,`0 0 24 24`);let o=document.createElementNS(i,`path`);o.setAttribute(`d`,`M15.75 17.25v3.375c0 .621-.504 1.125-1.125 1.125h-9.75a1.125 1.125 0 0 1-1.125-1.125V7.875c0-.621.504-1.125 1.125-1.125H6.75a9.06 9.06 0 0 1 1.5.124m7.5 10.376h3.375c.621 0 1.125-.504 1.125-1.125V11.25c0-4.46-3.243-8.161-7.5-8.876a9.06 9.06 0 0 0-1.5-.124H9.375c-.621 0-1.125.504-1.125 1.125v3.5m7.5 10.375H9.375a1.125 1.125 0 0 1-1.125-1.125v-9.25m12 6.625v-1.875a3.375 3.375 0 0 0-3.375-3.375h-1.5a1.125 1.125 0 0 1-1.125-1.125v-1.5a3.375 3.375 0 0 0-3.375-3.375H9.75`),o.setAttribute(`stroke-linecap`,`round`),o.setAttribute(`stroke-linejoin`,`round`),a.append(o),r.append(a),r.addEventListener(`click`,async()=>{try{await navigator.clipboard.writeText(t),r.classList.add(`chat__msg-copy-btn--copied`),r.setAttribute(`aria-label`,`Copied!`),setTimeout(()=>{r.classList.remove(`chat__msg-copy-btn--copied`),r.setAttribute(`aria-label`,`Copy message to clipboard`)},1500)}catch{r.setAttribute(`aria-label`,`Copy failed`),setTimeout(()=>{r.setAttribute(`aria-label`,`Copy message to clipboard`)},1500)}}),n.appendChild(r)}injectMessageDeleteButton(e,t){if(e.querySelector(`.chat__msg-delete-btn`))return;let n=e.querySelector(`.chat__message-content`);if(!n)return;let r=document.createElement(`button`);r.className=`chat__msg-delete-btn`,r.type=`button`,r.setAttribute(`aria-label`,`Delete message`);let i=`http://www.w3.org/2000/svg`,a=document.createElementNS(i,`svg`);a.setAttribute(`fill`,`none`),a.setAttribute(`stroke-width`,`1.5`),a.setAttribute(`stroke`,`currentColor`),a.setAttribute(`viewBox`,`0 0 24 24`);let o=document.createElementNS(i,`path`);o.setAttribute(`d`,`M14.74 9l-.346 9m-4.788 0L9.26 9m9.968-3.21c.342.052.682.107 1.022.166m-1.022-.165L18.16 19.673a2.25 2.25 0 01-2.244 2.077H8.084a2.25 2.25 0 01-2.244-2.077L4.772 5.79m14.456 0a48.108 48.108 0 00-3.478-.397m-12 .562c.34-.059.68-.114 1.022-.165m0 0a48.11 48.11 0 013.478-.397m7.5 0v-.916c0-1.18-.91-2.164-2.09-2.201a51.964 51.964 0 00-3.32 0c-1.18.037-2.09 1.022-2.09 2.201v.916m7.5 0a48.667 48.667 0 00-7.5 0`),o.setAttribute(`stroke-linecap`,`round`),o.setAttribute(`stroke-linejoin`,`round`),a.append(o),r.append(a),r.addEventListener(`click`,async()=>{await this.showAttachmentDialog({mode:`confirm`,title:`Delete Message`,message:`Delete this message? This action cannot be undone.`,confirmLabel:`Delete`,cancelLabel:`Cancel`})&&this.db&&await y.deleteMessage(this.db,t)}),n.appendChild(r)}isCollapsedInputAreaHeight(e){return e<=41}isContainerNearBottom(e){let{scrollTop:t,scrollHeight:n,clientHeight:r}=e;return n-t-r<80}isInlineTextMimeType(e){let t=e.toLowerCase();return t.startsWith(`text/`)?!0:t===`application/json`||t===`application/xml`||t===`application/javascript`}isLatestRender(e){return e===this.#n}persistGroupScrollState(e){let t=y.activeGroupId,n=this.isContainerNearBottom(e),r=n?0:this.getContainerDistanceFromBottom(e);K.setGroupScrollState(t,r,n)}removeStreamingBubble(e){e.querySelector(`.chat__message--streaming`)?.remove()}renderAttachmentCapabilitySummary(){let e=this.shadowRoot?.querySelector(`.chat__attachment-capabilities`);if(!(e instanceof HTMLElement))return;let t=y.orchestrator?.model||``;if(!t){e.textContent=``;return}e.textContent=`Model attachment support: ${v(t)}`}renderQueuedAttachments(){let e=this.shadowRoot?.querySelector(`.chat__pending-attachments`);if(!(e instanceof HTMLElement))return;if(this.#t.length===0){e.hidden=!0,e.replaceChildren();return}let t=_((y.orchestrator?.model||``).toLowerCase());e.hidden=!1;let n=document.createDocumentFragment();for(let e of this.#t){let r=document.createElement(`div`);r.className=`chat__pending-attachment`;let i=document.createElement(`span`);i.className=`chat__attachment-icon`,i.setAttribute(`aria-hidden`,`true`),i.textContent=this.getAttachmentIcon(e.mimeType);let a=document.createElement(`div`);a.className=`chat__pending-attachment-meta`;let o=document.createElement(`span`);o.className=`chat__pending-attachment-name`,o.textContent=e.fileName;let s=document.createElement(`span`);s.className=`chat__pending-attachment-detail`,s.textContent=`${e.mimeType} · ${this.formatAttachmentSize(e.size)}`,a.append(o,s);let c=this.getAttachmentTransportLabel(e.mimeType,e.fileName,t),l=document.createElement(`span`);l.className=`chat__transport-badge chat__transport-badge--${c}`,l.setAttribute(`aria-label`,`Transport: ${c}`),l.textContent=c;let u=document.createElement(`button`);u.type=`button`,u.className=`chat__pending-attachment-remove`,u.setAttribute(`aria-label`,`Remove ${e.fileName}`),u.textContent=`x`,u.addEventListener(`click`,()=>{this.#t=this.#t.filter(t=>t.id!==e.id),this.renderQueuedAttachments()}),r.append(i,a,l,u),n.appendChild(r)}e.replaceChildren(n)}resetInputAreaHeight(e){e.classList.remove(`chat__input-area--resized`),e.style.removeProperty(`--chat-input-area-height`)}resolveWorkspaceLinkPath(e){let t=e.trim();if(!t||t.startsWith(`#`)||/^[a-zA-Z][a-zA-Z\d+.-]*:/.test(t)||t.startsWith(`//`))return null;let n=t.split(/[?#]/,1)[0].replace(/\\/g,`/`);if(n=n.replace(/^\/+/,``),n=n.replace(/^\.\//,``),!n)return null;let r=n.split(`/`).filter(Boolean);return r.some(e=>e===`..`)?null:r.join(`/`)}revokeAttachmentObjectUrls(){K.revokeAttachmentObjectUrls()}scheduleBottomSnap(e){let t=()=>{this.isLatestRender(e)&&this.scrollMessagesToBottomIfNeeded()};requestAnimationFrame(()=>{t(),requestAnimationFrame(t)}),setTimeout(t,120)}scrollMessagesToBottomIfNeeded(){let e=this.shadowRoot?.querySelector(`.chat__messages`);e instanceof HTMLElement&&K.isNearBottom&&(this.setMessagesScrollTop(e,e.scrollHeight),K.setNearBottom(this.isContainerNearBottom(e)),this.persistGroupScrollState(e))}setActivityLogCollapsedOverride(e){this.activityLogCollapsedOverride=e,this.applyActivityLogVisibility()}setDropOverlayVisible(e){let t=this.shadowRoot?.querySelector(`[data-drop-overlay]`);t instanceof HTMLElement&&(t.hidden=!e)}setInputAreaHeight(e,t){let n=this.clampInputAreaHeight(t);if(this.isCollapsedInputAreaHeight(n)){this.resetInputAreaHeight(e);return}e.classList.add(`chat__input-area--resized`),e.style.setProperty(`--chat-input-area-height`,`${n}px`)}setMessagesScrollTop(e,t){this.#a=!0,e.scrollTop=t,requestAnimationFrame(()=>{this.#a=!1})}setupActivityLogVisibility(){if(this.shadowRoot){if(typeof globalThis.matchMedia==`function`){this.activityLogVisibilityMediaQuery=globalThis.matchMedia(`(min-width: 56rem) and (min-height: 401px)`);let e=()=>this.applyActivityLogVisibility();this.activityLogVisibilityMediaQuery.addEventListener(`change`,e),this.activityLogVisibilityCleanup=()=>{this.activityLogVisibilityMediaQuery?.removeEventListener(`change`,e)}}this.applyActivityLogVisibility()}}setupEffects(){let e=this.shadowRoot;e&&(this.addCleanup(A(()=>{let t=++this.#n,n=y.activeGroupId,r=y.messages,a=e.querySelector(`.chat__messages`);if(!(a instanceof HTMLElement))return;let o=K.getGroupScrollState(n);o?K.setNearBottom(o.nearBottom):K.setNearBottom(!0);let s=this.shouldAutoFollow(a),c=this.#o,u=s?0:o?.distanceFromBottom??this.getContainerDistanceFromBottom(a);this.revokeAttachmentObjectUrls(),a.replaceChildren(),(async()=>{let e=await Ue(this.db,i.MARKDOWN_FRONTMATTER_CHAT);for(let n of r){if(!this.isLatestRender(t))return!1;if(n.a2uiAction||n.content&&n.content.startsWith(`[A2UI ACTION]`))continue;let r=n.isFromMe?`assistant`:`user`,i=h(`assistantName`)||`ShadowClaw`,o=n.isFromMe?i:n.sender||`You`,c=document.createElement(`article`);c.className=`chat__message chat__message--${r}`;let u=n.timestamp?l(n.timestamp):``,f=await P(n.content,{breaks:!0,renderFrontmatter:e}),p=document.createElement(`div`);p.className=`chat__message-header`;let m=document.createElement(`div`);m.className=`chat__message-sender`,m.textContent=o;let g=document.createElement(`div`);g.className=`chat__message-timestamp`,g.textContent=u,p.append(m,g),c.append(p);let _=document.createElement(`div`);if(_.className=`chat__message-content`,n.content&&(d(_,this.deferWorkspaceImageLoads(f)),await this.resolveImagePaths(n.groupId,_),!this.isLatestRender(t)))return!1;let v=await this.renderMessageAttachments(n);if(v&&_.appendChild(v),n.a2uiEnvelopes&&n.a2uiEnvelopes.length>0){let e=document.createElement(`shadow-claw-a2ui-interceptor`),t=document.createElement(`shadow-claw-a2ui`);t.groupId=n.groupId;for(let e of n.a2uiEnvelopes)t.applyEnvelope(e);e.appendChild(t),_.appendChild(e)}c.appendChild(_),a.appendChild(c),s&&(this.setMessagesScrollTop(a,a.scrollHeight),this.persistGroupScrollState(a)),n.content&&n.id&&(this.injectMessageCopyButton(c,n.content),this.injectMessageDeleteButton(c,n.id)),_ instanceof HTMLElement&&n.content&&this.injectCopyButtons(_)}return!0})().then(async e=>{if(!e||!this.isLatestRender(t))return;let n=this.#o!==c;this.shouldAutoFollow(a)?(this.setMessagesScrollTop(a,a.scrollHeight),K.setNearBottom(this.isContainerNearBottom(a)),this.persistGroupScrollState(a),this.scheduleBottomSnap(t)):n?(K.setNearBottom(this.isContainerNearBottom(a)),this.persistGroupScrollState(a)):(this.setMessagesScrollTop(a,a.scrollHeight-a.clientHeight-u),K.setNearBottom(this.isContainerNearBottom(a)),this.persistGroupScrollState(a))})})),this.addCleanup(A(()=>{let e=y.streamingText;this.renderStreamingBubble(e)})),this.addCleanup(A(()=>{y.ready,y.state,this.renderAttachmentCapabilitySummary()})),this.addCleanup(A(()=>{let t=y.tokenUsageAccumulator,n=e.querySelector(`.chat__token-usage`);if(n instanceof HTMLElement)if(t&&(t.inputTokens||t.outputTokens)){n.classList.add(`chat__token-usage--visible`);let{cacheTokens:e,promptTokens:r,outputTokens:i,totalTokens:a}=q(t),o=document.createElement(`span`);o.textContent=`⬆ ${this.formatTokenCount(r)} in`;let s=document.createElement(`span`);s.textContent=`⬇ ${this.formatTokenCount(i)} out`;let c=document.createElement(`span`);c.textContent=`Σ ${this.formatTokenCount(a)}`;let l=[o,s,c];if(e>0){let t=document.createElement(`span`);t.textContent=`⛁ ${this.formatTokenCount(e)} cached`,l.push(t)}n.replaceChildren(...l)}else n.classList.remove(`chat__token-usage--visible`),n.replaceChildren()})),this.addCleanup(A(()=>{let t=y.contextUsage,n=e.querySelector(`.chat__context-usage`);if(n instanceof HTMLElement)if(t&&t.contextLimit>0){let e=Math.min(t.usagePercent,100),r=e>80?`high`:e>50?`medium`:`low`;n.classList.add(`chat__context-usage--visible`);let i=document.createElement(`span`);i.textContent=`${this.formatTokenCount(t.estimatedTokens)} / ${this.formatTokenCount(t.contextLimit)}`;let a=document.createElement(`div`);a.className=`chat__context-bar`;let o=document.createElement(`div`);o.className=`chat__context-bar-fill chat__context-bar-fill--${r}`,o.style.width=`${e}%`,a.append(o);let s=document.createElement(`span`);s.textContent=`${e.toFixed(0)}%`;let c=[i,a,s];if(t.truncatedCount>0){let e=document.createElement(`span`);e.textContent=`(${t.truncatedCount} msgs trimmed)`,c.push(e)}n.replaceChildren(...c)}else n.classList.remove(`chat__context-usage--visible`),n.replaceChildren()})),this.addCleanup(A(()=>{let t=y.toolActivity,n=y.aguiEvent,r=e.querySelector(`.chat__tool-activity`);r instanceof HTMLElement&&(n?.event?.type===`TOOL_CALL_START`&&n.event.toolCallName?(r.classList.add(`chat__tool-activity--active`),r.textContent=`⚙️ Using ${n.event.toolCallName}...`):t?(r.classList.add(`chat__tool-activity--active`),r.textContent=`⚙️ Using ${t.tool}...`):(r.classList.remove(`chat__tool-activity--active`),r.textContent=`⚙️ Working...`))})),this.addCleanup(A(()=>{let t=y.modelDownloadProgress,n=e.querySelector(`.chat__model-progress`),r=e.querySelector(`.chat__model-progress-label`),i=e.querySelector(`.chat__model-progress-bar`);if(!(n instanceof HTMLElement)||!(r instanceof HTMLElement)||!(i instanceof HTMLElement))return;if(!t){n.classList.remove(`chat__model-progress--active`),r.textContent=`Initializing local model...`,i.style.width=`0%`;return}let a=typeof t.progress==`number`?Math.max(0,Math.min(1,t.progress)):0,o=Math.round(a*100);n.classList.add(`chat__model-progress--active`),r.textContent=t.message||(t.status===`done`?`Model ready.`:`Downloading local model... ${o}%`),i.style.width=`${o}%`})),this.addCleanup(A(()=>{let t=I.get(),n=e.querySelector(`.chat__transfer-progress`),r=e.querySelector(`.chat__transfer-progress-label`),i=e.querySelector(`.chat__transfer-progress-bar`);if(!(n instanceof HTMLElement)||!(r instanceof HTMLElement)||!(i instanceof HTMLElement))return;if(!t||t.total===0){n.classList.remove(`chat__transfer-progress--active`),r.textContent=``,i.style.width=`0%`;return}let a=Math.max(0,Math.min(1,t.count/t.total)),o=Math.round(a*100),s=t.direction===`send`?`Sending`:`Receiving`;n.classList.add(`chat__transfer-progress--active`),r.textContent=`${s} file… ${o}%`,i.style.width=`${o}%`})),this.addCleanup(A(()=>{let t=y.activityLog,n=e.querySelector(`.chat__activity-log`);if(n instanceof HTMLElement)if(t.length>0){n.classList.add(`chat__activity-log--active`);let e=t.map(e=>`[${e.level}] ${e.label||``}: ${e.message}`).join(`
2338
+ `,`text/html`),Re=Le.querySelector(`template`);let ze=[];ze=Re?Array.from(Re.content.children):Array.from(Le.head.children).concat(Array.from(Le.body.children));var Be=ze;const Ve=128*1024,He=8e4;async function Ue(e,t){if(!e||typeof e.transaction!=`function`)return!0;try{return P(await s(e,t),!0)}catch{return!0}}const We=`shadow-claw-chat`;var Ge=class extends k{static styles=Ie;static template=Be;activityLogCollapsedOverride=null;activityLogVisibilityMediaQuery=null;db=null;#e;#t;#n;#r;#i;#a;#o;constructor(){super(),K.reset(),this.db=null,this.#n=0,this.#i=0,this.#a=!1,this.#o=0,this.#r=!0,this.#e=0,this.#t=[]}async connectedCallback(){if(!this.shadowRoot)throw Error(`shadowRoot not found`);this.db=await a(),await this.restoreInputAreaHeight(),this.dispatchTerminalSlotReady(),this.setupEffects(),this.setupActivityLogVisibility(),this.bindEventListeners(),await this.checkPromptApiOnboarding()}disconnectedCallback(){this.activityLogVisibilityCleanup(),K.revokeAttachmentObjectUrls(),K.resetNearBottom(),super.disconnectedCallback()}activityLogVisibilityCleanup=()=>{};applyActivityLogVisibility(){let e=this.shadowRoot;if(!e)return;let t=e.querySelector(`.chat__activity-log`);if(!(t instanceof HTMLElement))return;let n=this.activityLogVisibilityMediaQuery?!this.activityLogVisibilityMediaQuery.matches:!1;(typeof this.activityLogCollapsedOverride==`boolean`?this.activityLogCollapsedOverride:n)?t.classList.add(`chat__activity-log--collapsed`):t.classList.remove(`chat__activity-log--collapsed`)}bindEventListeners(){let e=this.shadowRoot;if(!e)return;let t=e.querySelector(`.chat__messages`);if(t instanceof HTMLElement){t.addEventListener(`scroll`,()=>{this.#a||(this.#o+=1,this.isContainerNearBottom(t)||(this.#r=!1)),K.setNearBottom(this.isContainerNearBottom(t)),this.persistGroupScrollState(t)}),t.addEventListener(`click`,e=>{this.handleMessageLinkClick(e)}),t.addEventListener(`shadow-claw-a2ui-action`,async e=>{let{groupId:t,action:n}=e.detail;if(t.startsWith(`room:`)){await y.orchestrator?.routeRoomA2UIAction(t,n);return}if(t.startsWith(`peer:`)){let e=(y.orchestrator?.router)?.findChannel(t);e&&`sendA2UIAction`in e&&await e.sendA2UIAction(t,n)}let r=JSON.stringify(n.dataModel,null,2),i=`[A2UI ACTION]\nsurfaceId: "${n.surfaceId}"\nactionId: "${n.actionId}"\ndataModel:\n${r}\n\nInstructions: The user triggered the "${n.actionId}" action on surface "${n.surfaceId}". The dataModel above contains the current form values. Use the appropriate tool(s) to fulfill the action based on the actionId and dataModel values. After you have a result, call render_component with action "updateDataModel" on surfaceId "${n.surfaceId}" to update the surface (e.g. patch the output field with the result). Do NOT respond with plain text only — always update the surface via render_component.`;y.sendMessage(i,[],n)}),t.addEventListener(`shadow-claw-a2ui-function-response`,async e=>{let{groupId:t,response:n}=e.detail;if(!t.startsWith(`room:`)&&t.startsWith(`peer:`)){let e=(y.orchestrator?.router)?.findChannel(t);e&&`sendA2UIAction`in e&&await e.sendA2UIAction(t,n)}});let e=new ResizeObserver(()=>{this.shouldAutoFollow(t)&&(this.setMessagesScrollTop(t,t.scrollHeight),this.persistGroupScrollState(t))});e.observe(t),this.addCleanup(()=>e.disconnect())}let n=e.querySelector(`.chat__input`);n instanceof HTMLTextAreaElement&&n.addEventListener(`keydown`,e=>{e.key===`Enter`&&!e.shiftKey&&(e.preventDefault(),this.sendMessage()),e.key===`Enter`&&(e.ctrlKey||e.metaKey)&&(e.preventDefault(),this.sendMessage())});let r=e.querySelector(`.chat__input-area`),i=e.querySelector(`.chat__input-resize-handle`);r instanceof HTMLElement&&i instanceof HTMLElement&&this.bindInputResizeEvents(r,i),e.querySelector(`[data-action="send-message"]`)?.addEventListener(`click`,()=>this.sendMessage()),e.querySelector(`[data-action="attach-files"]`)?.addEventListener(`click`,()=>{let t=e.querySelector(`.chat__attachment-input`);t instanceof HTMLInputElement&&(t.value=``,t.click())}),e.querySelector(`.chat__attachment-input`)?.addEventListener(`change`,e=>{e.target instanceof HTMLInputElement&&this.queueSelectedFiles(e.target)}),e.querySelector(`[data-action="compact-chat"]`)?.addEventListener(`click`,()=>this.handleCompactChat()),e.querySelector(`[data-action="clear-chat"]`)?.addEventListener(`click`,()=>this.handleClearChat()),e.querySelector(`[data-action="stop-chat"]`)?.addEventListener(`click`,()=>this.handleStopChat()),e.querySelector(`[data-action="download-chat"]`)?.addEventListener(`click`,()=>this.downloadChat()),e.querySelector(`[data-action="restore-chat"]`)?.addEventListener(`click`,()=>{let t=e.querySelector(`.chat__restore-input`);t instanceof HTMLInputElement&&t.click()}),e.querySelector(`.chat__restore-input`)?.addEventListener(`change`,e=>{e.target instanceof HTMLInputElement&&this.restoreChat(e.target)});let a=e.querySelector(`.chat__body`);a instanceof HTMLElement&&(a.addEventListener(`dragenter`,e=>{this.hasDroppableData(e.dataTransfer)&&(e.preventDefault(),this.#e+=1,this.setDropOverlayVisible(!0))}),a.addEventListener(`dragover`,e=>{this.hasDroppableData(e.dataTransfer)&&e.preventDefault()}),a.addEventListener(`dragleave`,e=>{this.hasDroppableData(e.dataTransfer)&&(e.preventDefault(),this.#e=Math.max(0,this.#e-1),this.#e===0&&this.setDropOverlayVisible(!1))}),a.addEventListener(`drop`,e=>{this.hasDroppableData(e.dataTransfer)&&(e.preventDefault(),this.#e=0,this.setDropOverlayVisible(!1),this.queueDroppedData(e.dataTransfer))}));let o=e.querySelector(`.chat__prompt-api-form`);o instanceof HTMLFormElement&&o.addEventListener(`submit`,e=>{e.preventDefault(),this.confirmPromptApiOnboarding()});let s=e.querySelector(`[data-action="confirm-prompt-api-onboarding"]`);s instanceof HTMLElement&&s.addEventListener(`click`,e=>{e.preventDefault(),this.confirmPromptApiOnboarding()});let c=e.querySelector(`[data-action="configure-other-provider"]`);c instanceof HTMLElement&&c.addEventListener(`click`,e=>{e.preventDefault(),this.bypassPromptApiOnboardingToSettings()})}bindInputResizeEvents(e,t){t.setAttribute(`tabindex`,`0`),t.setAttribute(`role`,`separator`),t.setAttribute(`aria-orientation`,`horizontal`),t.setAttribute(`aria-label`,`Resize chat input area`);let n=()=>{let t=parseFloat(e.style.getPropertyValue(`--chat-input-area-height`));return Number.isFinite(t)&&t>0?t:40},r=()=>{let e=this.clampInputAreaHeight(2**53-1),r=Math.round(this.clampInputAreaHeight(n()));t.setAttribute(`aria-valuemin`,`40`),t.setAttribute(`aria-valuemax`,String(Math.round(e))),t.setAttribute(`aria-valuenow`,String(r))},i=null,a=0,o=0,s=t=>{if(t.pointerId!==i)return;let n=a-t.clientY,s=o+n;this.setInputAreaHeight(e,s),r()},c=()=>{if(i===null)return;i=null,t.classList.remove(`active`),document.removeEventListener(`pointermove`,s);let n=parseFloat(e.style.getPropertyValue(`--chat-input-area-height`));Number.isFinite(n)&&n>0?this.persistInputAreaHeight(n):this.persistInputAreaHeight(0)},l=e=>{e.pointerId===i&&c()};t.addEventListener(`pointerdown`,n=>{if(n.pointerType===`mouse`&&n.button!==0&&n.button!==-1)return;let r=e.querySelector(`.chat__input-wrapper`);if(!(r instanceof HTMLElement))return;n.preventDefault(),i=n.pointerId,a=n.clientY,e.classList.add(`chat__input-area--resized`);let c=parseFloat(e.style.getPropertyValue(`--chat-input-area-height`));o=Number.isFinite(c)&&c>0?c:r.getBoundingClientRect().height||40,t.classList.add(`active`),t.setPointerCapture(n.pointerId),document.addEventListener(`pointermove`,s)}),t.addEventListener(`pointerup`,l),t.addEventListener(`pointercancel`,c),t.addEventListener(`dblclick`,()=>{this.resetInputAreaHeight(e),this.persistInputAreaHeight(0),r(),this.scrollMessagesToBottomIfNeeded()}),t.addEventListener(`keydown`,t=>{let i=t.shiftKey?32:12,a=n(),o=null;if(t.key===`ArrowUp`?o=a+i:t.key===`ArrowDown`?o=a-i:t.key===`Home`?o=40:t.key===`End`&&(o=this.clampInputAreaHeight(2**53-1)),o===null)return;t.preventDefault(),this.setInputAreaHeight(e,o),r();let s=parseFloat(e.style.getPropertyValue(`--chat-input-area-height`));this.persistInputAreaHeight(Number.isFinite(s)&&s>0?this.clampInputAreaHeight(s):0),this.scrollMessagesToBottomIfNeeded()}),r(),this.addCleanup(()=>{c(),t.removeEventListener(`pointerup`,l),t.removeEventListener(`pointercancel`,c)})}buildQueuedAttachmentsFromFiles(e){return e.map(e=>{let t=e.name||`attachment.bin`;return{id:`${Date.now()}-${Math.random().toString(36).slice(2,10)}`,fileName:t,mimeType:I(t,e.type||``),size:e.size,source:{kind:`local-file`,file:e}}})}clampInputAreaHeight(e){let t=Math.floor(window.innerHeight*.45);return Math.max(40,Math.min(Math.max(40,t),e))}deferWorkspaceImageLoads(e){let t=document.createElement(`div`);t.innerHTML=e;let n=Array.from(t.querySelectorAll(`img[src]`));for(let e of n){let t=e.getAttribute(`src`);if(!t)continue;let n=this.resolveWorkspaceLinkPath(t);n&&(e.setAttribute(`data-inline-workspace-src`,n),e.removeAttribute(`src`))}return t.innerHTML}dispatchTerminalSlotReady(){this.dispatchEvent(new CustomEvent(`shadow-claw-terminal-slot-ready`,{bubbles:!0,composed:!0}))}formatAttachmentSize(e){return e<1024?`${e} B`:e<1024*1024?`${(e/1024).toFixed(1)} KB`:`${(e/(1024*1024)).toFixed(1)} MB`}formatAttachmentSubtitle(e){let t=[];return e.mimeType&&t.push(e.mimeType),typeof e.size==`number`&&t.push(this.formatAttachmentSize(e.size)),t.join(` · `)||`Attachment`}formatTokenCount(e){return typeof e==`number`?e.toLocaleString(`en-US`):`–`}getAttachmentIcon(e=``){let t=e.toLowerCase();return t.startsWith(`image/`)?`IMG`:t.startsWith(`video/`)?`VID`:t.startsWith(`audio/`)?`AUD`:t.includes(`pdf`)?`PDF`:t.startsWith(`text/`)||t.includes(`json`)?`TXT`:t.includes(`zip`)||t.includes(`tar`)?`ZIP`:`BIN`}getAttachmentTransportLabel(e,t,n){let r=p(e,t);return r===`text`?`text`:r===`image`&&(n.images||n.routerByFeatures)||r===`audio`&&(n.audio||n.routerByFeatures)||r===`document`&&(n.documents||n.routerByFeatures)?`native`:`fallback`}getContainerDistanceFromBottom(e){return Math.max(0,e.scrollHeight-e.scrollTop-e.clientHeight)}getMessagesContainer(){let e=this.shadowRoot?.querySelector(`.chat__messages`);return e instanceof HTMLElement?e:null}hasDroppableData(e){if(!e)return!1;if(e.files.length>0)return!0;let t=Array.from(e.types||[]);return t.includes(`Files`)||t.includes(`application/x-moz-file`)||t.includes(`text/plain`)}inferAttachmentModelSupport(e=[]){let t=_(y.orchestrator?.model?.toLowerCase()||``);return e.every(e=>{let n=(e.mimeType||``).toLowerCase();return this.isInlineTextMimeType(n)?!0:n.startsWith(`image/`)?t.images||t.routerByFeatures:n.startsWith(`audio/`)?t.audio||t.routerByFeatures:n.startsWith(`video/`)?t.video||t.routerByFeatures:!1})}injectCopyButtons(e){e.querySelectorAll(`pre`).forEach(e=>{if(e.querySelector(`.chat__code-copy-btn`))return;let t=document.createElement(`button`);t.className=`chat__code-copy-btn`,t.type=`button`,t.setAttribute(`aria-label`,`Copy code to clipboard`),t.textContent=`📋 Copy`,t.addEventListener(`click`,async()=>{let n=e.querySelector(`code`),r=n?n.textContent||``:e.textContent||``;try{await navigator.clipboard.writeText(r),t.textContent=`✅ Copied`,t.classList.add(`chat__code-copy-btn--copied`),setTimeout(()=>{t.textContent=`📋 Copy`,t.classList.remove(`chat__code-copy-btn--copied`)},1500)}catch{t.textContent=`⚠️ Failed`,setTimeout(()=>{t.textContent=`📋 Copy`},1500)}}),e.appendChild(t)})}injectMessageCopyButton(e,t){if(e.querySelector(`.chat__msg-copy-btn`))return;let n=e.querySelector(`.chat__message-content`);if(!n)return;let r=document.createElement(`button`);r.className=`chat__msg-copy-btn`,r.type=`button`,r.setAttribute(`aria-label`,`Copy message to clipboard`);let i=`http://www.w3.org/2000/svg`,a=document.createElementNS(i,`svg`);a.setAttribute(`fill`,`none`),a.setAttribute(`stroke-width`,`1.5`),a.setAttribute(`stroke`,`currentColor`),a.setAttribute(`viewBox`,`0 0 24 24`);let o=document.createElementNS(i,`path`);o.setAttribute(`d`,`M15.75 17.25v3.375c0 .621-.504 1.125-1.125 1.125h-9.75a1.125 1.125 0 0 1-1.125-1.125V7.875c0-.621.504-1.125 1.125-1.125H6.75a9.06 9.06 0 0 1 1.5.124m7.5 10.376h3.375c.621 0 1.125-.504 1.125-1.125V11.25c0-4.46-3.243-8.161-7.5-8.876a9.06 9.06 0 0 0-1.5-.124H9.375c-.621 0-1.125.504-1.125 1.125v3.5m7.5 10.375H9.375a1.125 1.125 0 0 1-1.125-1.125v-9.25m12 6.625v-1.875a3.375 3.375 0 0 0-3.375-3.375h-1.5a1.125 1.125 0 0 1-1.125-1.125v-1.5a3.375 3.375 0 0 0-3.375-3.375H9.75`),o.setAttribute(`stroke-linecap`,`round`),o.setAttribute(`stroke-linejoin`,`round`),a.append(o),r.append(a),r.addEventListener(`click`,async()=>{try{await navigator.clipboard.writeText(t),r.classList.add(`chat__msg-copy-btn--copied`),r.setAttribute(`aria-label`,`Copied!`),setTimeout(()=>{r.classList.remove(`chat__msg-copy-btn--copied`),r.setAttribute(`aria-label`,`Copy message to clipboard`)},1500)}catch{r.setAttribute(`aria-label`,`Copy failed`),setTimeout(()=>{r.setAttribute(`aria-label`,`Copy message to clipboard`)},1500)}}),n.appendChild(r)}injectMessageDeleteButton(e,t){if(e.querySelector(`.chat__msg-delete-btn`))return;let n=e.querySelector(`.chat__message-content`);if(!n)return;let r=document.createElement(`button`);r.className=`chat__msg-delete-btn`,r.type=`button`,r.setAttribute(`aria-label`,`Delete message`);let i=`http://www.w3.org/2000/svg`,a=document.createElementNS(i,`svg`);a.setAttribute(`fill`,`none`),a.setAttribute(`stroke-width`,`1.5`),a.setAttribute(`stroke`,`currentColor`),a.setAttribute(`viewBox`,`0 0 24 24`);let o=document.createElementNS(i,`path`);o.setAttribute(`d`,`M14.74 9l-.346 9m-4.788 0L9.26 9m9.968-3.21c.342.052.682.107 1.022.166m-1.022-.165L18.16 19.673a2.25 2.25 0 01-2.244 2.077H8.084a2.25 2.25 0 01-2.244-2.077L4.772 5.79m14.456 0a48.108 48.108 0 00-3.478-.397m-12 .562c.34-.059.68-.114 1.022-.165m0 0a48.11 48.11 0 013.478-.397m7.5 0v-.916c0-1.18-.91-2.164-2.09-2.201a51.964 51.964 0 00-3.32 0c-1.18.037-2.09 1.022-2.09 2.201v.916m7.5 0a48.667 48.667 0 00-7.5 0`),o.setAttribute(`stroke-linecap`,`round`),o.setAttribute(`stroke-linejoin`,`round`),a.append(o),r.append(a),r.addEventListener(`click`,async()=>{await this.showAttachmentDialog({mode:`confirm`,title:`Delete Message`,message:`Delete this message? This action cannot be undone.`,confirmLabel:`Delete`,cancelLabel:`Cancel`})&&this.db&&await y.deleteMessage(this.db,t)}),n.appendChild(r)}isCollapsedInputAreaHeight(e){return e<=41}isContainerNearBottom(e){let{scrollTop:t,scrollHeight:n,clientHeight:r}=e;return n-t-r<80}isInlineTextMimeType(e){let t=e.toLowerCase();return t.startsWith(`text/`)?!0:t===`application/json`||t===`application/xml`||t===`application/javascript`}isLatestRender(e){return e===this.#n}persistGroupScrollState(e){let t=y.activeGroupId,n=this.isContainerNearBottom(e),r=n?0:this.getContainerDistanceFromBottom(e);K.setGroupScrollState(t,r,n)}removeStreamingBubble(e){e.querySelector(`.chat__message--streaming`)?.remove()}renderAttachmentCapabilitySummary(){let e=this.shadowRoot?.querySelector(`.chat__attachment-capabilities`);if(!(e instanceof HTMLElement))return;let t=y.orchestrator?.model||``;if(!t){e.textContent=``;return}e.textContent=`Model attachment support: ${v(t)}`}renderQueuedAttachments(){let e=this.shadowRoot?.querySelector(`.chat__pending-attachments`);if(!(e instanceof HTMLElement))return;if(this.#t.length===0){e.hidden=!0,e.replaceChildren();return}let t=_((y.orchestrator?.model||``).toLowerCase());e.hidden=!1;let n=document.createDocumentFragment();for(let e of this.#t){let r=document.createElement(`div`);r.className=`chat__pending-attachment`;let i=document.createElement(`span`);i.className=`chat__attachment-icon`,i.setAttribute(`aria-hidden`,`true`),i.textContent=this.getAttachmentIcon(e.mimeType);let a=document.createElement(`div`);a.className=`chat__pending-attachment-meta`;let o=document.createElement(`span`);o.className=`chat__pending-attachment-name`,o.textContent=e.fileName;let s=document.createElement(`span`);s.className=`chat__pending-attachment-detail`,s.textContent=`${e.mimeType} · ${this.formatAttachmentSize(e.size)}`,a.append(o,s);let c=this.getAttachmentTransportLabel(e.mimeType,e.fileName,t),l=document.createElement(`span`);l.className=`chat__transport-badge chat__transport-badge--${c}`,l.setAttribute(`aria-label`,`Transport: ${c}`),l.textContent=c;let u=document.createElement(`button`);u.type=`button`,u.className=`chat__pending-attachment-remove`,u.setAttribute(`aria-label`,`Remove ${e.fileName}`),u.textContent=`x`,u.addEventListener(`click`,()=>{this.#t=this.#t.filter(t=>t.id!==e.id),this.renderQueuedAttachments()}),r.append(i,a,l,u),n.appendChild(r)}e.replaceChildren(n)}resetInputAreaHeight(e){e.classList.remove(`chat__input-area--resized`),e.style.removeProperty(`--chat-input-area-height`)}resolveWorkspaceLinkPath(e){let t=e.trim();if(!t||t.startsWith(`#`)||/^[a-zA-Z][a-zA-Z\d+.-]*:/.test(t)||t.startsWith(`//`))return null;let n=t.split(/[?#]/,1)[0].replace(/\\/g,`/`);if(n=n.replace(/^\/+/,``),n=n.replace(/^\.\//,``),!n)return null;let r=n.split(`/`).filter(Boolean);return r.some(e=>e===`..`)?null:r.join(`/`)}revokeAttachmentObjectUrls(){K.revokeAttachmentObjectUrls()}scheduleBottomSnap(e){let t=()=>{this.isLatestRender(e)&&this.scrollMessagesToBottomIfNeeded()};requestAnimationFrame(()=>{t(),requestAnimationFrame(t)}),setTimeout(t,120)}scrollMessagesToBottomIfNeeded(){let e=this.shadowRoot?.querySelector(`.chat__messages`);e instanceof HTMLElement&&K.isNearBottom&&(this.setMessagesScrollTop(e,e.scrollHeight),K.setNearBottom(this.isContainerNearBottom(e)),this.persistGroupScrollState(e))}setActivityLogCollapsedOverride(e){this.activityLogCollapsedOverride=e,this.applyActivityLogVisibility()}setDropOverlayVisible(e){let t=this.shadowRoot?.querySelector(`[data-drop-overlay]`);t instanceof HTMLElement&&(t.hidden=!e)}setInputAreaHeight(e,t){let n=this.clampInputAreaHeight(t);if(this.isCollapsedInputAreaHeight(n)){this.resetInputAreaHeight(e);return}e.classList.add(`chat__input-area--resized`),e.style.setProperty(`--chat-input-area-height`,`${n}px`)}setMessagesScrollTop(e,t){this.#a=!0,e.scrollTop=t,requestAnimationFrame(()=>{this.#a=!1})}setupActivityLogVisibility(){if(this.shadowRoot){if(typeof globalThis.matchMedia==`function`){this.activityLogVisibilityMediaQuery=globalThis.matchMedia(`(min-width: 56rem) and (min-height: 401px)`);let e=()=>this.applyActivityLogVisibility();this.activityLogVisibilityMediaQuery.addEventListener(`change`,e),this.activityLogVisibilityCleanup=()=>{this.activityLogVisibilityMediaQuery?.removeEventListener(`change`,e)}}this.applyActivityLogVisibility()}}setupEffects(){let e=this.shadowRoot;e&&(this.addCleanup(A(()=>{let t=++this.#n,n=y.activeGroupId,r=y.messages,a=e.querySelector(`.chat__messages`);if(!(a instanceof HTMLElement))return;let o=K.getGroupScrollState(n);o?K.setNearBottom(o.nearBottom):K.setNearBottom(!0);let s=this.shouldAutoFollow(a),c=this.#o,u=s?0:o?.distanceFromBottom??this.getContainerDistanceFromBottom(a);this.revokeAttachmentObjectUrls(),a.replaceChildren(),(async()=>{let e=await Ue(this.db,i.MARKDOWN_FRONTMATTER_CHAT);for(let n of r){if(!this.isLatestRender(t))return!1;if(n.a2uiAction||n.content&&n.content.startsWith(`[A2UI ACTION]`))continue;let r=n.isFromMe?`assistant`:`user`,i=h(`assistantName`)||`ShadowClaw`,o=n.isFromMe?i:n.sender||`You`,c=document.createElement(`article`);c.className=`chat__message chat__message--${r}`;let u=n.timestamp?l(n.timestamp):``,f=await F(n.content,{breaks:!0,renderFrontmatter:e}),p=document.createElement(`div`);p.className=`chat__message-header`;let m=document.createElement(`div`);m.className=`chat__message-sender`,m.textContent=o;let g=document.createElement(`div`);g.className=`chat__message-timestamp`,g.textContent=u,p.append(m,g),c.append(p);let _=document.createElement(`div`);if(_.className=`chat__message-content`,n.content&&(d(_,this.deferWorkspaceImageLoads(f)),await this.resolveImagePaths(n.groupId,_),!this.isLatestRender(t)))return!1;let v=await this.renderMessageAttachments(n);if(v&&_.appendChild(v),n.a2uiEnvelopes&&n.a2uiEnvelopes.length>0){let e=document.createElement(`shadow-claw-a2ui-interceptor`),t=document.createElement(`shadow-claw-a2ui`);t.groupId=n.groupId;for(let e of n.a2uiEnvelopes)t.applyEnvelope(e);e.appendChild(t),_.appendChild(e)}c.appendChild(_),a.appendChild(c),s&&(this.setMessagesScrollTop(a,a.scrollHeight),this.persistGroupScrollState(a)),n.content&&n.id&&(this.injectMessageCopyButton(c,n.content),this.injectMessageDeleteButton(c,n.id)),_ instanceof HTMLElement&&n.content&&this.injectCopyButtons(_)}return!0})().then(async e=>{if(!e||!this.isLatestRender(t))return;let n=this.#o!==c;this.shouldAutoFollow(a)?(this.setMessagesScrollTop(a,a.scrollHeight),K.setNearBottom(this.isContainerNearBottom(a)),this.persistGroupScrollState(a),this.scheduleBottomSnap(t)):n?(K.setNearBottom(this.isContainerNearBottom(a)),this.persistGroupScrollState(a)):(this.setMessagesScrollTop(a,a.scrollHeight-a.clientHeight-u),K.setNearBottom(this.isContainerNearBottom(a)),this.persistGroupScrollState(a))})})),this.addCleanup(A(()=>{let e=y.streamingText;this.renderStreamingBubble(e)})),this.addCleanup(A(()=>{y.ready,y.state,this.renderAttachmentCapabilitySummary()})),this.addCleanup(A(()=>{let t=y.tokenUsageAccumulator,n=e.querySelector(`.chat__token-usage`);if(n instanceof HTMLElement)if(t&&(t.inputTokens||t.outputTokens)){n.classList.add(`chat__token-usage--visible`);let{cacheTokens:e,promptTokens:r,outputTokens:i,totalTokens:a}=q(t),o=document.createElement(`span`);o.textContent=`⬆ ${this.formatTokenCount(r)} in`;let s=document.createElement(`span`);s.textContent=`⬇ ${this.formatTokenCount(i)} out`;let c=document.createElement(`span`);c.textContent=`Σ ${this.formatTokenCount(a)}`;let l=[o,s,c];if(e>0){let t=document.createElement(`span`);t.textContent=`⛁ ${this.formatTokenCount(e)} cached`,l.push(t)}n.replaceChildren(...l)}else n.classList.remove(`chat__token-usage--visible`),n.replaceChildren()})),this.addCleanup(A(()=>{let t=y.contextUsage,n=e.querySelector(`.chat__context-usage`);if(n instanceof HTMLElement)if(t&&t.contextLimit>0){let e=Math.min(t.usagePercent,100),r=e>80?`high`:e>50?`medium`:`low`;n.classList.add(`chat__context-usage--visible`);let i=document.createElement(`span`);i.textContent=`${this.formatTokenCount(t.estimatedTokens)} / ${this.formatTokenCount(t.contextLimit)}`;let a=document.createElement(`div`);a.className=`chat__context-bar`;let o=document.createElement(`div`);o.className=`chat__context-bar-fill chat__context-bar-fill--${r}`,o.style.width=`${e}%`,a.append(o);let s=document.createElement(`span`);s.textContent=`${e.toFixed(0)}%`;let c=[i,a,s];if(t.truncatedCount>0){let e=document.createElement(`span`);e.textContent=`(${t.truncatedCount} msgs trimmed)`,c.push(e)}n.replaceChildren(...c)}else n.classList.remove(`chat__context-usage--visible`),n.replaceChildren()})),this.addCleanup(A(()=>{let t=y.toolActivity,n=y.aguiEvent,r=e.querySelector(`.chat__tool-activity`);r instanceof HTMLElement&&(n?.event?.type===`TOOL_CALL_START`&&n.event.toolCallName?(r.classList.add(`chat__tool-activity--active`),r.textContent=`⚙️ Using ${n.event.toolCallName}...`):t?(r.classList.add(`chat__tool-activity--active`),r.textContent=`⚙️ Using ${t.tool}...`):(r.classList.remove(`chat__tool-activity--active`),r.textContent=`⚙️ Working...`))})),this.addCleanup(A(()=>{let t=y.modelDownloadProgress,n=e.querySelector(`.chat__model-progress`),r=e.querySelector(`.chat__model-progress-label`),i=e.querySelector(`.chat__model-progress-bar`);if(!(n instanceof HTMLElement)||!(r instanceof HTMLElement)||!(i instanceof HTMLElement))return;if(!t){n.classList.remove(`chat__model-progress--active`),r.textContent=`Initializing local model...`,i.style.width=`0%`;return}let a=typeof t.progress==`number`?Math.max(0,Math.min(1,t.progress)):0,o=Math.round(a*100);n.classList.add(`chat__model-progress--active`),r.textContent=t.message||(t.status===`done`?`Model ready.`:`Downloading local model... ${o}%`),i.style.width=`${o}%`})),this.addCleanup(A(()=>{let t=L.get(),n=e.querySelector(`.chat__transfer-progress`),r=e.querySelector(`.chat__transfer-progress-label`),i=e.querySelector(`.chat__transfer-progress-bar`);if(!(n instanceof HTMLElement)||!(r instanceof HTMLElement)||!(i instanceof HTMLElement))return;if(!t||t.total===0){n.classList.remove(`chat__transfer-progress--active`),r.textContent=``,i.style.width=`0%`;return}let a=Math.max(0,Math.min(1,t.count/t.total)),o=Math.round(a*100),s=t.direction===`send`?`Sending`:`Receiving`;n.classList.add(`chat__transfer-progress--active`),r.textContent=`${s} file… ${o}%`,i.style.width=`${o}%`})),this.addCleanup(A(()=>{let t=y.activityLog,n=e.querySelector(`.chat__activity-log`);if(n instanceof HTMLElement)if(t.length>0){n.classList.add(`chat__activity-log--active`);let e=t.map(e=>`[${e.level}] ${e.label||``}: ${e.message}`).join(`
2339
2339
  `),r=document.createElement(`div`);r.className=`chat__activity-log__header`;let i=document.createElement(`span`);i.className=`chat__activity-log__label`,i.textContent=`Activity Log`;let a=document.createElement(`button`);a.className=`chat__activity-log__copy-btn`,a.type=`button`,a.setAttribute(`aria-label`,`Copy activity log to clipboard`);let o=`http://www.w3.org/2000/svg`,s=document.createElementNS(o,`svg`);s.setAttribute(`fill`,`none`),s.setAttribute(`stroke-width`,`1.5`),s.setAttribute(`stroke`,`currentColor`),s.setAttribute(`viewBox`,`0 0 24 24`);let c=document.createElementNS(o,`path`);c.setAttribute(`d`,`M15.75 17.25v3.375c0 .621-.504 1.125-1.125 1.125h-9.75a1.125 1.125 0 0 1-1.125-1.125V7.875c0-.621.504-1.125 1.125-1.125H6.75a9.06 9.06 0 0 1 1.5.124m7.5 10.376h3.375c.621 0 1.125-.504 1.125-1.125V11.25c0-4.46-3.243-8.161-7.5-8.876a9.06 9.06 0 0 0-1.5-.124H9.375c-.621 0-1.125.504-1.125 1.125v3.5m7.5 10.375H9.375a1.125 1.125 0 0 1-1.125-1.125v-9.25m12 6.625v-1.875a3.375 3.375 0 0 0-3.375-3.375h-1.5a1.125 1.125 0 0 1-1.125-1.125v-1.5a3.375 3.375 0 0 0-3.375-3.375H9.75`),c.setAttribute(`stroke-linecap`,`round`),c.setAttribute(`stroke-linejoin`,`round`),s.append(c),a.append(s),a.addEventListener(`click`,async()=>{try{await navigator.clipboard.writeText(e),a.classList.add(`chat__activity-log__copy-btn--copied`),a.setAttribute(`aria-label`,`Copied!`),setTimeout(()=>{a.classList.remove(`chat__activity-log__copy-btn--copied`),a.setAttribute(`aria-label`,`Copy activity log to clipboard`)},1500)}catch{a.setAttribute(`aria-label`,`Copy failed`),setTimeout(()=>{a.setAttribute(`aria-label`,`Copy activity log to clipboard`)},1500)}}),r.append(i,a);let l=document.createElement(`div`);l.className=`chat__activity-log__entries`,t.forEach(e=>{let t=document.createElement(`div`);t.textContent=`[${e.level}] ${e.label||``}: ${e.message}`,l.append(t)}),n.replaceChildren(r,l),l.scrollTop=l.scrollHeight}else n.classList.remove(`chat__activity-log--active`),n.replaceChildren()})),this.addCleanup(A(()=>{let t=y.activeGroupId,n=e.querySelector(`.chat__shared-state`),r=e.querySelector(`.chat__shared-state-code`);if(!(n instanceof HTMLElement)||!(r instanceof HTMLElement))return;let i=y.getPeerState(t);i&&Object.keys(i).length>0?(n.hidden=!1,r.textContent=JSON.stringify(i,null,2)):(n.hidden=!0,r.textContent=``)})),this.addCleanup(A(()=>{let t=y.state,n=y.activeGroupId,r=e.querySelector(`.chat__status-text`),i=e.querySelector(`.chat__status-indicator`),a=e.querySelector(`.chat__typing-indicator`);if(!(r instanceof HTMLElement)||!(i instanceof HTMLElement)||!(a instanceof HTMLElement))return;let o=n.startsWith(`peer:`),s=o&&y.isRemoteAgentTyping(n),c=o?te(y.getRemoteAgentStatus(n),s):t;i.classList.remove(`chat__status-indicator--thinking`,`chat__status-indicator--responding`,`chat__status-indicator--error`),(c===`thinking`||c===`responding`)&&i.classList.add(`chat__status-indicator--${c}`),c===`error`&&i.classList.add(`chat__status-indicator--error`),r.textContent=c.charAt(0).toUpperCase()+c.slice(1),a.toggleAttribute(`hidden`,!s)})),this.addCleanup(A(()=>{let t=y.state,n=e.querySelector(`[data-action="send-message"]`),r=e.querySelector(`[data-action="stop-chat"]`),i=t===`thinking`||t===`responding`;n instanceof HTMLButtonElement&&(n.disabled=i),r instanceof HTMLButtonElement?r.disabled=!i:r?.toggleAttribute(`disabled`,!i)})),this.addCleanup(A(()=>{let e=y.error;e&&(D(e,6e3),y.clearError())})))}shouldAutoFollow(e){let t=y.state,n=t===`thinking`||t===`responding`,r=this.isContainerNearBottom(e);return n?(r&&(this.#r=!0),this.#r):(this.#r=!0,K.nearBottomSnapshot||r)}async buildMessageDraftPayload(e){let t=e.trim(),n=this.#t.map(e=>{let t=e.mimeType===`image/png`?`inline`:`file`;return{id:e.id,fileName:e.fileName,mimeType:e.mimeType,size:e.size,source:e.source,previewDisposition:t}});if(n.length===0)return{text:t,attachments:n};if(n.filter(e=>!this.isInlineTextMimeType(e.mimeType||``)).length>0&&!this.inferAttachmentModelSupport(n)&&!await this.showAttachmentDialog({mode:`confirm`,title:`Limited Attachment Support`,message:`The selected model may not natively read binary attachments (images/audio/video/docs). Files will still be attached to chat history, but responses might be limited.`,confirmLabel:`Send Anyway`,cancelLabel:`Cancel`,details:[`Try a multimodal model for best binary-file results.`,`Text files are inlined automatically when they are reasonably small.`]}))return null;let r=n.map(e=>`- ${e.fileName} (${e.mimeType||`application/octet-stream`}, ${this.formatAttachmentSize(e.size||0)})`),i=[],a=0;for(let e of this.#t){if(!this.isInlineTextMimeType(e.mimeType))continue;if(e.size>Ve){i.push(`File: ${e.fileName}\nSkipped inline content because the file is larger than ${this.formatAttachmentSize(Ve)}.`);continue}if(e.source.kind!==`local-file`)continue;let t=await e.source.file.text();if(a+=t.length,a>He)return await this.showAttachmentDialog({mode:`info`,title:`Attachment Context Too Large`,message:`The dropped text content exceeds the safe prompt budget. Remove some files or send them in smaller batches.`,details:[`Current inline text budget: ${He.toLocaleString()} characters`,`Large text blobs can degrade response quality and exhaust context.`],confirmLabel:`OK`}),null;i.push(`File: ${e.fileName}\n${t}`)}return{text:`${t?`${t}\n\n`:``}${`Attached files:\n${r.join(`
2340
2340
  `)}`}${i.length>0?`\n\nAttached text excerpts:\n\n${i.join(`
2341
2341
 
2342
2342
  ---
2343
2343
 
2344
- `)}`:``}`,attachments:n}}async bypassPromptApiOnboardingToSettings(){let e=this.shadowRoot;if(!e)return;if(this.db||=await a(),this.db)try{await x(this.db,i.PROMPT_API_ONBOARDING_SEEN,`true`)}catch(e){console.warn(`Failed to persist Prompt API onboarding status:`,e)}let t=e.querySelector(`shadow-claw-dialog[dialog-class="chat__prompt-api-dialog"]`);if(t&&typeof t.close==`function`)t.close();else{let t=e.querySelector(`dialog.chat__prompt-api-dialog`);t instanceof HTMLDialogElement&&t.close()}document.dispatchEvent(new CustomEvent(`shadow-claw-navigate`,{detail:{page:`settings`},bubbles:!0,composed:!0}))}async checkPromptApiOnboarding(){if(!(O()&&!globalThis.__SHADOWCLAW_E2E_TEST_ONBOARDING__)&&(this.db||=await a(),this.db))try{let e=await s(this.db,i.PROVIDER);if((typeof e==`string`&&e.trim()?e.trim():`prompt_api`)!==`prompt_api`||B(await s(this.db,i.PROMPT_API_ONBOARDING_SEEN),!1))return;let t=this.shadowRoot;if(!t)return;this.ensureShadowDialogs();let n=M(),a=N(),o=n||a,c=t.querySelector(`.chat__prompt-api-status-card`);c instanceof HTMLElement&&(c.hidden=!o);let l=t.querySelector(`[data-info="prompt-api-status"]`);l instanceof HTMLElement&&d(l,j(n));let u=t.querySelector(`.chat__prompt-api-fallback-card`);u instanceof HTMLElement&&(u.hidden=o);let f=t.querySelector(`[data-setting="prompt-api-onboarding-fallback-model"]`);if(f){let e=await s(this.db,i.PROMPT_API_FALLBACK_MODEL);f.value=typeof e==`string`&&e.trim()?e.trim():r}let p=t.querySelector(`shadow-claw-dialog[dialog-class="chat__prompt-api-dialog"]`);if(p&&typeof p.showModal==`function`)p.showModal();else{let e=t.querySelector(`dialog.chat__prompt-api-dialog`);e instanceof HTMLDialogElement&&(typeof e.showModal==`function`?e.showModal():e.setAttribute(`open`,``))}}catch(e){console.warn(`Failed to check Prompt API onboarding:`,e)}}async confirmPromptApiOnboarding(){let e=this.shadowRoot;if(!e)return;this.db||=await a();let t=e.querySelector(`[data-setting="prompt-api-onboarding-fallback-model"]`)?.value?.trim()||`onnx-community/Qwen3-0.6B-ONNX`;if(this.db)try{await x(this.db,i.PROMPT_API_FALLBACK_MODEL,t),await x(this.db,i.PROMPT_API_ONBOARDING_SEEN,`true`)}catch(e){console.warn(`Failed to persist Prompt API onboarding settings:`,e)}let n=e.querySelector(`shadow-claw-dialog[dialog-class="chat__prompt-api-dialog"]`);if(n&&typeof n.close==`function`)n.close();else{let t=e.querySelector(`dialog.chat__prompt-api-dialog`);t instanceof HTMLDialogElement&&t.close()}E(`Prompt API configured`,2500)}async downloadAttachment(e,t){if(!(!this.db||!t.path))try{await R(this.db,e,t.path)}catch(e){D(`Failed to download attachment: ${e instanceof Error?e.message:String(e)}`,5e3)}}async downloadChat(){if(this.db)try{let e=y.activeGroupId,t=await U(this.db,e);if(!t){D(`Failed to export chat data`,6e3);return}let n=new V.default;n.file(`chat-data.json`,JSON.stringify(t,null,2));let r=await n.generateAsync({type:`blob`}),i=URL.createObjectURL(r),a=document.createElement(`a`);a.href=i,a.download=`chat-${u()}.zip`,document.body.appendChild(a),a.click(),document.body.removeChild(a),URL.revokeObjectURL(i),E(`Chat backup downloaded`,3e3)}catch(e){D(`Failed to download chat: ${e instanceof Error?e.message:String(e)}`,6e3)}}async handleClearChat(){let e=this.shadowRoot;if(!e||!this.db)return;let t=e.querySelector(`.chat__messages`);t instanceof HTMLElement&&t.replaceChildren();try{await y.newSession(this.db)}catch(e){let t=e instanceof Error?e.message:String(e);console.warn(`Failed to clear session:`,t)}}async handleCompactChat(){if(this.db&&await this.showAttachmentDialog({mode:`confirm`,title:`Compact Conversation`,message:`This will summarize the conversation to reduce token usage. The summary replaces the current history. Continue?`,confirmLabel:`Compact`,cancelLabel:`Cancel`}))try{await y.compactContext(this.db),T(`Compacting context...`,2500)}catch(e){D(`Failed to compact chat: ${e instanceof Error?e.message:String(e)}`,6e3)}}async handleMessageLinkClick(e){if(e.defaultPrevented||e.button!==0||e.metaKey||e.ctrlKey||e.shiftKey||e.altKey)return;let t=e.target;if(!(t instanceof Element))return;let n=t.closest(`a`);if(!(n instanceof HTMLAnchorElement))return;let r=n.getAttribute(`href`)||``,i=y.activeGroupId;c(r,``,i)&&e.preventDefault()}async handleStopChat(){try{y.stopCurrentRequest(),T(`Stopped current request`,2200)}catch(e){D(`Failed to stop request: ${e instanceof Error?e.message:String(e)}`,6e3)}}async openAttachment(e,t){if(!(!this.db||!t.path))try{await z.openFile(this.db,t.path,e)}catch(e){D(`Failed to open attachment: ${e instanceof Error?e.message:String(e)}`,5e3)}}async persistInputAreaHeight(e){if(this.db)try{await x(this.db,i.CHAT_INPUT_AREA_HEIGHT,e)}catch{}}async queueDroppedData(e){if(!e)return;let t=this.buildQueuedAttachmentsFromFiles(Array.from(e.files||[])),n=await this.readDroppedPlainText(e);if(n){let e=n.trim();if(e){let n=new Blob([e],{type:`text/plain`});t.push({id:`${Date.now()}-${Math.random().toString(36).slice(2,10)}`,fileName:`dropped-text-${new Date().toISOString().slice(0,19).replace(/[:T]/g,`-`)}.txt`,mimeType:`text/plain`,size:n.size,source:{kind:`local-file`,file:n}})}}t.length!==0&&(this.#t=[...this.#t,...t],this.renderQueuedAttachments(),T(`Queued ${t.length} attachment${t.length===1?``:`s`}.`,2200))}async queueSelectedFiles(e){let t=Array.from(e.files||[]);if(t.length===0){e.value=``;return}let n=this.buildQueuedAttachmentsFromFiles(t);this.#t=[...this.#t,...n],this.renderQueuedAttachments(),T(`Queued ${n.length} attachment${n.length===1?``:`s`}.`,2200),e.value=``}async readDroppedPlainText(e){let t=Array.from(e.items||[]).find(e=>e.kind===`string`&&e.type===`text/plain`);return t?await new Promise(e=>{t.getAsString(t=>{e(t||``)})}):``}async renderInlineAttachmentPreview(e,t){if(!this.db||!t.path)return null;try{let n=await g(this.db,e.groupId,t.path),r=new Uint8Array(n.byteLength);r.set(n);let i=new Blob([r],{type:t.mimeType||`image/png`}),a=URL.createObjectURL(i);K.registerAttachmentObjectUrl(a);let o=document.createElement(`button`);o.className=`chat__attachment-preview-btn`,o.type=`button`,o.setAttribute(`aria-label`,`Open ${t.fileName}`),o.addEventListener(`click`,()=>{this.openAttachment(e.groupId,t)});let s=document.createElement(`img`);return s.className=`chat__attachment-preview`,s.alt=t.fileName,s.src=a,o.appendChild(s),o}catch(e){let t=document.createElement(`div`);return t.className=`chat__attachment-preview-error`,t.textContent=e instanceof Error?e.message:`Attachment preview unavailable.`,t}}async renderMessageAttachments(e){if(!Array.isArray(e.attachments)||e.attachments.length===0)return null;let t=document.createElement(`div`);t.className=`chat__attachments`;for(let n of e.attachments){let r=document.createElement(`section`);if(r.className=`chat__attachment`,L(n)&&n.path){let t=await this.renderInlineAttachmentPreview(e,n);t&&r.appendChild(t)}let i=document.createElement(`div`);i.className=`chat__attachment-meta`;let a=document.createElement(`div`);a.className=`chat__attachment-identity`;let o=document.createElement(`span`);o.className=`chat__attachment-icon`,o.setAttribute(`aria-hidden`,`true`),o.textContent=this.getAttachmentIcon(n.mimeType||``);let s=document.createElement(`button`);s.className=`chat__attachment-title`,s.type=`button`,s.textContent=n.fileName,s.disabled=!n.path||!this.db,s.addEventListener(`click`,()=>{this.openAttachment(e.groupId,n)}),a.append(o,s),i.appendChild(a);let c=document.createElement(`div`);c.className=`chat__attachment-subtitle`,c.textContent=this.formatAttachmentSubtitle(n),i.appendChild(c);let l=document.createElement(`div`);if(l.className=`chat__attachment-actions`,n.path&&this.db){let t=document.createElement(`button`);t.className=`chat__attachment-action`,t.type=`button`,t.textContent=`Open`,t.addEventListener(`click`,()=>{this.openAttachment(e.groupId,n)}),l.appendChild(t);let r=document.createElement(`button`);r.className=`chat__attachment-action`,r.type=`button`,r.textContent=`Download`,r.addEventListener(`click`,()=>{this.downloadAttachment(e.groupId,n)}),l.appendChild(r)}i.appendChild(l),r.appendChild(i),t.appendChild(r)}return t}async renderStreamingBubble(e){let t=++this.#i,n=this.getMessagesContainer();if(!n)return;let r=this.shouldAutoFollow(n);if(!(typeof e==`string`&&e.length>0)){this.removeStreamingBubble(n);return}let i=n.querySelector(`.chat__message--streaming`),a=null;if(!i){let e=h(`assistantName`)||`ShadowClaw`;i=document.createElement(`article`),i.className=`chat__message chat__message--assistant chat__message--streaming`;let t=document.createElement(`div`);t.className=`chat__message-header`;let r=document.createElement(`div`);r.className=`chat__message-sender`,r.textContent=e;let o=document.createElement(`div`);o.className=`chat__message-timestamp`,o.textContent=`streaming…`,t.append(r,o),a=document.createElement(`div`),a.className=`chat__message-content`,i.append(t,a),n.appendChild(i)}else if(a=i.querySelector(`.chat__message-content`),!(a instanceof HTMLElement))return;let o=ee(e).replace(/\n/g,`<br>`).replace(/`([^`]+?)`/g,`<code>$1</code>`).replace(/\*\*([^*]+?)\*\*/g,`<b>$1</b>`);if(t!==this.#i)return;d(a,o);let s=document.createElement(`span`);s.setAttribute(`aria-hidden`,`true`),s.className=`chat__streaming-cursor`,a.append(s),i.querySelector(`.chat__msg-copy-btn`)?.remove(),this.injectMessageCopyButton(i,e),this.injectCopyButtons(a),r&&(this.setMessagesScrollTop(n,n.scrollHeight),K.setNearBottom(this.isContainerNearBottom(n)),this.persistGroupScrollState(n))}async resolveImagePaths(e,t){if(!this.db)return;let n=Array.from(t.querySelectorAll(`img`));for(let t of n){let n=t.getAttribute(`data-inline-workspace-src`)||t.getAttribute(`src`)||``,r=this.resolveWorkspaceLinkPath(n);if(r)try{let n=await g(this.db,e,r),i=new Uint8Array(n.byteLength);i.set(n);let a=r.toLowerCase();if(a.endsWith(`.pdf`)){let e=document.createElement(`shadow-claw-pdf-viewer`);e.file={name:r.split(`/`).pop()||`document.pdf`,binaryContent:i},t.replaceWith(e)}else{let e=`image/png`;a.endsWith(`.jpg`)||a.endsWith(`.jpeg`)?e=`image/jpeg`:a.endsWith(`.gif`)?e=`image/gif`:a.endsWith(`.webp`)?e=`image/webp`:a.endsWith(`.svg`)&&(e=`image/svg+xml`);let n=new Blob([i],{type:e}),r=URL.createObjectURL(n);K.registerAttachmentObjectUrl(r),t.addEventListener(`load`,()=>this.scrollMessagesToBottomIfNeeded(),{once:!0}),t.removeAttribute(`data-inline-workspace-src`),t.src=r}}catch(e){console.warn(`Failed to load inline image: ${r}`,e)}}let r=Array.from(t.querySelectorAll(`a[href]`));for(let t of r){let n=t.getAttribute(`href`)||``,r=this.resolveWorkspaceLinkPath(n);if(!(!r||!r.toLowerCase().endsWith(`.pdf`)))try{let n=await g(this.db,e,r),i=new Uint8Array(n.byteLength);i.set(n);let a=document.createElement(`shadow-claw-pdf-viewer`);a.file={name:r.split(`/`).pop()||`document.pdf`,binaryContent:i},t.insertAdjacentElement(`afterend`,a),requestAnimationFrame(()=>this.scrollMessagesToBottomIfNeeded()),setTimeout(()=>this.scrollMessagesToBottomIfNeeded(),120)}catch(e){console.warn(`Failed to load inline PDF: ${r}`,e)}}}async restoreChat(e){if(!this.db)return;let t=e.files?.[0];if(t){if(!t.name.endsWith(`.zip`)){w(`Please select a .zip file`,3500),e.value=``;return}try{let n=(await V.default.loadAsync(t)).file(`chat-data.json`);if(!n){D(`Invalid chat file: missing chat-data.json`,6e3),e.value=``;return}let r=await n.async(`string`),i=JSON.parse(r);if(!i.messages||!Array.isArray(i.messages)){D(`Invalid chat file: missing messages array`,6e3),e.value=``;return}let a=y.activeGroupId;await G(this.db,a,i),await y.loadHistory(),E(`Chat restored successfully`,3500)}catch(e){D(`Failed to restore chat: ${e instanceof Error?e.message:String(e)}`,6e3)}finally{e.value=``}}}async restoreInputAreaHeight(){let e=this.shadowRoot?.querySelector(`.chat__input-area`);if(e instanceof HTMLElement)try{let t=this.db?await s(this.db,i.CHAT_INPUT_AREA_HEIGHT):void 0;typeof t==`number`&&Number.isFinite(t)&&t>0&&(this.isCollapsedInputAreaHeight(t)?this.resetInputAreaHeight(e):this.setInputAreaHeight(e,t))}catch{}}async sendMessage(){let e=this.shadowRoot;if(!e)return;let t=e.querySelector(`.chat__input`);if(!(t instanceof HTMLTextAreaElement))return;let n=t.value.trim();if(!(!n&&this.#t.length===0)){if(!y.ready){w(`ShadowClaw is still initializing. Please try again.`,3500);return}try{let e=await this.buildMessageDraftPayload(n);if(!e)return;t.value=``,this.#r=!0,K.setNearBottom(!0),y.sendMessage(e.text,e.attachments),this.#t=[],this.renderQueuedAttachments()}catch(e){D(`Error sending message: ${e instanceof Error?e.message:String(e)}`,6e3)}}}async showAttachmentDialog(e){let t=document.querySelector(`shadow-claw`);return t&&typeof t.requestDialog==`function`?await t.requestDialog(e):(e.mode||`confirm`)===`info`?(w(e.message,4500),!0):(w(`${e.title}: ${e.message}`,5e3),!1)}};customElements.get(We)||customElements.define(We,Ge);export{Ge as ShadowClawChat};
2344
+ `)}`:``}`,attachments:n}}async bypassPromptApiOnboardingToSettings(){let e=this.shadowRoot;if(!e)return;if(this.db||=await a(),this.db)try{await x(this.db,i.PROMPT_API_ONBOARDING_SEEN,`true`)}catch(e){console.warn(`Failed to persist Prompt API onboarding status:`,e)}let t=e.querySelector(`shadow-claw-dialog[dialog-class="chat__prompt-api-dialog"]`);if(t&&typeof t.close==`function`)t.close();else{let t=e.querySelector(`dialog.chat__prompt-api-dialog`);t instanceof HTMLDialogElement&&t.close()}document.dispatchEvent(new CustomEvent(`shadow-claw-navigate`,{detail:{page:`settings`},bubbles:!0,composed:!0}))}async checkPromptApiOnboarding(){if(!(O()&&!globalThis.__SHADOWCLAW_E2E_TEST_ONBOARDING__)&&(this.db||=await a(),this.db))try{let e=await s(this.db,i.PROVIDER);if((typeof e==`string`&&e.trim()?e.trim():`prompt_api`)!==`prompt_api`||P(await s(this.db,i.PROMPT_API_ONBOARDING_SEEN),!1))return;let t=this.shadowRoot;if(!t)return;this.ensureShadowDialogs();let n=M(),a=N(),o=n||a,c=t.querySelector(`.chat__prompt-api-status-card`);c instanceof HTMLElement&&(c.hidden=!o);let l=t.querySelector(`[data-info="prompt-api-status"]`);l instanceof HTMLElement&&d(l,j(n));let u=t.querySelector(`.chat__prompt-api-fallback-card`);u instanceof HTMLElement&&(u.hidden=o);let f=t.querySelector(`[data-setting="prompt-api-onboarding-fallback-model"]`);if(f){let e=await s(this.db,i.PROMPT_API_FALLBACK_MODEL);f.value=typeof e==`string`&&e.trim()?e.trim():r}let p=t.querySelector(`shadow-claw-dialog[dialog-class="chat__prompt-api-dialog"]`);if(p&&typeof p.showModal==`function`)p.showModal();else{let e=t.querySelector(`dialog.chat__prompt-api-dialog`);e instanceof HTMLDialogElement&&(typeof e.showModal==`function`?e.showModal():e.setAttribute(`open`,``))}}catch(e){console.warn(`Failed to check Prompt API onboarding:`,e)}}async confirmPromptApiOnboarding(){let e=this.shadowRoot;if(!e)return;this.db||=await a();let t=e.querySelector(`[data-setting="prompt-api-onboarding-fallback-model"]`)?.value?.trim()||`onnx-community/Qwen3-0.6B-ONNX`;if(this.db)try{await x(this.db,i.PROMPT_API_FALLBACK_MODEL,t),await x(this.db,i.PROMPT_API_ONBOARDING_SEEN,`true`)}catch(e){console.warn(`Failed to persist Prompt API onboarding settings:`,e)}let n=e.querySelector(`shadow-claw-dialog[dialog-class="chat__prompt-api-dialog"]`);if(n&&typeof n.close==`function`)n.close();else{let t=e.querySelector(`dialog.chat__prompt-api-dialog`);t instanceof HTMLDialogElement&&t.close()}E(`Prompt API configured`,2500)}async downloadAttachment(e,t){if(!(!this.db||!t.path))try{await z(this.db,e,t.path)}catch(e){D(`Failed to download attachment: ${e instanceof Error?e.message:String(e)}`,5e3)}}async downloadChat(){if(this.db)try{let e=y.activeGroupId,t=await U(this.db,e);if(!t){D(`Failed to export chat data`,6e3);return}let n=new V.default;n.file(`chat-data.json`,JSON.stringify(t,null,2));let r=await n.generateAsync({type:`blob`}),i=URL.createObjectURL(r),a=document.createElement(`a`);a.href=i,a.download=`chat-${u()}.zip`,document.body.appendChild(a),a.click(),document.body.removeChild(a),URL.revokeObjectURL(i),E(`Chat backup downloaded`,3e3)}catch(e){D(`Failed to download chat: ${e instanceof Error?e.message:String(e)}`,6e3)}}async handleClearChat(){let e=this.shadowRoot;if(!e||!this.db)return;let t=e.querySelector(`.chat__messages`);t instanceof HTMLElement&&t.replaceChildren();try{await y.newSession(this.db)}catch(e){let t=e instanceof Error?e.message:String(e);console.warn(`Failed to clear session:`,t)}}async handleCompactChat(){if(this.db&&await this.showAttachmentDialog({mode:`confirm`,title:`Compact Conversation`,message:`This will summarize the conversation to reduce token usage. The summary replaces the current history. Continue?`,confirmLabel:`Compact`,cancelLabel:`Cancel`}))try{await y.compactContext(this.db),T(`Compacting context...`,2500)}catch(e){D(`Failed to compact chat: ${e instanceof Error?e.message:String(e)}`,6e3)}}async handleMessageLinkClick(e){if(e.defaultPrevented||e.button!==0||e.metaKey||e.ctrlKey||e.shiftKey||e.altKey)return;let t=e.target;if(!(t instanceof Element))return;let n=t.closest(`a`);if(!(n instanceof HTMLAnchorElement))return;let r=n.getAttribute(`href`)||``,i=y.activeGroupId;c(r,``,i)&&e.preventDefault()}async handleStopChat(){try{y.stopCurrentRequest(),T(`Stopped current request`,2200)}catch(e){D(`Failed to stop request: ${e instanceof Error?e.message:String(e)}`,6e3)}}async openAttachment(e,t){if(!(!this.db||!t.path))try{await B.openFile(this.db,t.path,e)}catch(e){D(`Failed to open attachment: ${e instanceof Error?e.message:String(e)}`,5e3)}}async persistInputAreaHeight(e){if(this.db)try{await x(this.db,i.CHAT_INPUT_AREA_HEIGHT,e)}catch{}}async queueDroppedData(e){if(!e)return;let t=this.buildQueuedAttachmentsFromFiles(Array.from(e.files||[])),n=await this.readDroppedPlainText(e);if(n){let e=n.trim();if(e){let n=new Blob([e],{type:`text/plain`});t.push({id:`${Date.now()}-${Math.random().toString(36).slice(2,10)}`,fileName:`dropped-text-${new Date().toISOString().slice(0,19).replace(/[:T]/g,`-`)}.txt`,mimeType:`text/plain`,size:n.size,source:{kind:`local-file`,file:n}})}}t.length!==0&&(this.#t=[...this.#t,...t],this.renderQueuedAttachments(),T(`Queued ${t.length} attachment${t.length===1?``:`s`}.`,2200))}async queueSelectedFiles(e){let t=Array.from(e.files||[]);if(t.length===0){e.value=``;return}let n=this.buildQueuedAttachmentsFromFiles(t);this.#t=[...this.#t,...n],this.renderQueuedAttachments(),T(`Queued ${n.length} attachment${n.length===1?``:`s`}.`,2200),e.value=``}async readDroppedPlainText(e){let t=Array.from(e.items||[]).find(e=>e.kind===`string`&&e.type===`text/plain`);return t?await new Promise(e=>{t.getAsString(t=>{e(t||``)})}):``}async renderInlineAttachmentPreview(e,t){if(!this.db||!t.path)return null;try{let n=await g(this.db,e.groupId,t.path),r=new Uint8Array(n.byteLength);r.set(n);let i=new Blob([r],{type:t.mimeType||`image/png`}),a=URL.createObjectURL(i);K.registerAttachmentObjectUrl(a);let o=document.createElement(`button`);o.className=`chat__attachment-preview-btn`,o.type=`button`,o.setAttribute(`aria-label`,`Open ${t.fileName}`),o.addEventListener(`click`,()=>{this.openAttachment(e.groupId,t)});let s=document.createElement(`img`);return s.className=`chat__attachment-preview`,s.alt=t.fileName,s.src=a,o.appendChild(s),o}catch(e){let t=document.createElement(`div`);return t.className=`chat__attachment-preview-error`,t.textContent=e instanceof Error?e.message:`Attachment preview unavailable.`,t}}async renderMessageAttachments(e){if(!Array.isArray(e.attachments)||e.attachments.length===0)return null;let t=document.createElement(`div`);t.className=`chat__attachments`;for(let n of e.attachments){let r=document.createElement(`section`);if(r.className=`chat__attachment`,R(n)&&n.path){let t=await this.renderInlineAttachmentPreview(e,n);t&&r.appendChild(t)}let i=document.createElement(`div`);i.className=`chat__attachment-meta`;let a=document.createElement(`div`);a.className=`chat__attachment-identity`;let o=document.createElement(`span`);o.className=`chat__attachment-icon`,o.setAttribute(`aria-hidden`,`true`),o.textContent=this.getAttachmentIcon(n.mimeType||``);let s=document.createElement(`button`);s.className=`chat__attachment-title`,s.type=`button`,s.textContent=n.fileName,s.disabled=!n.path||!this.db,s.addEventListener(`click`,()=>{this.openAttachment(e.groupId,n)}),a.append(o,s),i.appendChild(a);let c=document.createElement(`div`);c.className=`chat__attachment-subtitle`,c.textContent=this.formatAttachmentSubtitle(n),i.appendChild(c);let l=document.createElement(`div`);if(l.className=`chat__attachment-actions`,n.path&&this.db){let t=document.createElement(`button`);t.className=`chat__attachment-action`,t.type=`button`,t.textContent=`Open`,t.addEventListener(`click`,()=>{this.openAttachment(e.groupId,n)}),l.appendChild(t);let r=document.createElement(`button`);r.className=`chat__attachment-action`,r.type=`button`,r.textContent=`Download`,r.addEventListener(`click`,()=>{this.downloadAttachment(e.groupId,n)}),l.appendChild(r)}i.appendChild(l),r.appendChild(i),t.appendChild(r)}return t}async renderStreamingBubble(e){let t=++this.#i,n=this.getMessagesContainer();if(!n)return;let r=this.shouldAutoFollow(n);if(!(typeof e==`string`&&e.length>0)){this.removeStreamingBubble(n);return}let i=n.querySelector(`.chat__message--streaming`),a=null;if(!i){let e=h(`assistantName`)||`ShadowClaw`;i=document.createElement(`article`),i.className=`chat__message chat__message--assistant chat__message--streaming`;let t=document.createElement(`div`);t.className=`chat__message-header`;let r=document.createElement(`div`);r.className=`chat__message-sender`,r.textContent=e;let o=document.createElement(`div`);o.className=`chat__message-timestamp`,o.textContent=`streaming…`,t.append(r,o),a=document.createElement(`div`),a.className=`chat__message-content`,i.append(t,a),n.appendChild(i)}else if(a=i.querySelector(`.chat__message-content`),!(a instanceof HTMLElement))return;let o=ee(e).replace(/\n/g,`<br>`).replace(/`([^`]+?)`/g,`<code>$1</code>`).replace(/\*\*([^*]+?)\*\*/g,`<b>$1</b>`);if(t!==this.#i)return;d(a,o);let s=document.createElement(`span`);s.setAttribute(`aria-hidden`,`true`),s.className=`chat__streaming-cursor`,a.append(s),i.querySelector(`.chat__msg-copy-btn`)?.remove(),this.injectMessageCopyButton(i,e),this.injectCopyButtons(a),r&&(this.setMessagesScrollTop(n,n.scrollHeight),K.setNearBottom(this.isContainerNearBottom(n)),this.persistGroupScrollState(n))}async resolveImagePaths(e,t){if(!this.db)return;let n=Array.from(t.querySelectorAll(`img`));for(let t of n){let n=t.getAttribute(`data-inline-workspace-src`)||t.getAttribute(`src`)||``,r=this.resolveWorkspaceLinkPath(n);if(r)try{let n=await g(this.db,e,r),i=new Uint8Array(n.byteLength);i.set(n);let a=r.toLowerCase();if(a.endsWith(`.pdf`)){let e=document.createElement(`shadow-claw-pdf-viewer`);e.file={name:r.split(`/`).pop()||`document.pdf`,binaryContent:i},t.replaceWith(e)}else{let e=`image/png`;a.endsWith(`.jpg`)||a.endsWith(`.jpeg`)?e=`image/jpeg`:a.endsWith(`.gif`)?e=`image/gif`:a.endsWith(`.webp`)?e=`image/webp`:a.endsWith(`.svg`)&&(e=`image/svg+xml`);let n=new Blob([i],{type:e}),r=URL.createObjectURL(n);K.registerAttachmentObjectUrl(r),t.addEventListener(`load`,()=>this.scrollMessagesToBottomIfNeeded(),{once:!0}),t.removeAttribute(`data-inline-workspace-src`),t.src=r}}catch(e){console.warn(`Failed to load inline image: ${r}`,e)}}let r=Array.from(t.querySelectorAll(`a[href]`));for(let t of r){let n=t.getAttribute(`href`)||``,r=this.resolveWorkspaceLinkPath(n);if(!(!r||!r.toLowerCase().endsWith(`.pdf`)))try{let n=await g(this.db,e,r),i=new Uint8Array(n.byteLength);i.set(n);let a=document.createElement(`shadow-claw-pdf-viewer`);a.file={name:r.split(`/`).pop()||`document.pdf`,binaryContent:i},t.insertAdjacentElement(`afterend`,a),requestAnimationFrame(()=>this.scrollMessagesToBottomIfNeeded()),setTimeout(()=>this.scrollMessagesToBottomIfNeeded(),120)}catch(e){console.warn(`Failed to load inline PDF: ${r}`,e)}}}async restoreChat(e){if(!this.db)return;let t=e.files?.[0];if(t){if(!t.name.endsWith(`.zip`)){w(`Please select a .zip file`,3500),e.value=``;return}try{let n=(await V.default.loadAsync(t)).file(`chat-data.json`);if(!n){D(`Invalid chat file: missing chat-data.json`,6e3),e.value=``;return}let r=await n.async(`string`),i=JSON.parse(r);if(!i.messages||!Array.isArray(i.messages)){D(`Invalid chat file: missing messages array`,6e3),e.value=``;return}let a=y.activeGroupId;await G(this.db,a,i),await y.loadHistory(),E(`Chat restored successfully`,3500)}catch(e){D(`Failed to restore chat: ${e instanceof Error?e.message:String(e)}`,6e3)}finally{e.value=``}}}async restoreInputAreaHeight(){let e=this.shadowRoot?.querySelector(`.chat__input-area`);if(e instanceof HTMLElement)try{let t=this.db?await s(this.db,i.CHAT_INPUT_AREA_HEIGHT):void 0;typeof t==`number`&&Number.isFinite(t)&&t>0&&(this.isCollapsedInputAreaHeight(t)?this.resetInputAreaHeight(e):this.setInputAreaHeight(e,t))}catch{}}async sendMessage(){let e=this.shadowRoot;if(!e)return;let t=e.querySelector(`.chat__input`);if(!(t instanceof HTMLTextAreaElement))return;let n=t.value.trim();if(!(!n&&this.#t.length===0)){if(!y.ready){w(`ShadowClaw is still initializing. Please try again.`,3500);return}try{let e=await this.buildMessageDraftPayload(n);if(!e)return;t.value=``,this.#r=!0,K.setNearBottom(!0),y.sendMessage(e.text,e.attachments),this.#t=[],this.renderQueuedAttachments()}catch(e){D(`Error sending message: ${e instanceof Error?e.message:String(e)}`,6e3)}}}async showAttachmentDialog(e){let t=document.querySelector(`shadow-claw`);return t&&typeof t.requestDialog==`function`?await t.requestDialog(e):(e.mode||`confirm`)===`info`?(w(e.message,4500),!0):(w(`${e.title}: ${e.message}`,5e3),!1)}};customElements.get(We)||customElements.define(We,Ge);export{Ge as ShadowClawChat};
@@ -1,4 +1,4 @@
1
- import{r as e}from"./config-AL77QAx4.js";import{n as t}from"./txPromise-EBECky1b.js";import{t as n}from"./getConfig-D89uJgo5.js";import{u as r}from"./custom-element-security-CZ92anB8.js";import{K as i,Y as a,gn as o,hn as s,mn as c,t as l}from"./orchestrator-B9KmIj8Q.js";import{t as u}from"./setConfig-DFMYnYLE.js";import{t as d}from"./shadow-claw-element-DIrv3P6A.js";import{t as f}from"./effect-BEsuusE8.js";import{n as p}from"./model-ranking-C60HgQ2c.js";import"./shadow-claw-dialog-ByyHgxM9.js";const m=new CSSStyleSheet;m.replaceSync(`:host {
1
+ import{r as e}from"./config-BYAuxx3j.js";import{n as t}from"./txPromise-EBECky1b.js";import{t as n}from"./getConfig-D89uJgo5.js";import{u as r}from"./custom-element-security-DdYlUozq.js";import{K as i,Y as a,gn as o,hn as s,mn as c,t as l}from"./orchestrator-DRfEudXk.js";import{t as u}from"./setConfig-DFMYnYLE.js";import{t as d}from"./shadow-claw-element-DIrv3P6A.js";import{t as f}from"./effect-BEsuusE8.js";import{n as p}from"./model-ranking-C60HgQ2c.js";import"./shadow-claw-dialog-ByyHgxM9.js";const m=new CSSStyleSheet;m.replaceSync(`:host {
2
2
  display: block;
3
3
  }
4
4