@pi-chamber/web 0.3.0 → 0.3.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.
Files changed (65) hide show
  1. package/bin/lib/cli-startup.js +53 -10
  2. package/bin/lib/cli-startup.test.js +42 -0
  3. package/dist/assets/{CommitSection-BpbMC0et.js → CommitSection-DLIvjYbM.js} +1 -1
  4. package/dist/assets/{DiagramEditor-dFTMKHuO.js → DiagramEditor-Tw3ZWHML.js} +1 -1
  5. package/dist/assets/{DiagramView-DVw_8Px1.js → DiagramView-CK6R7taL.js} +1 -1
  6. package/dist/assets/{DiffView-CkoY1oAM.js → DiffView-vrxi5oWp.js} +2 -2
  7. package/dist/assets/{FilesView-C0hyg2pa.js → FilesView-BD_h3EVr.js} +6 -6
  8. package/dist/assets/{GitView-D36hpDsb.js → GitView-BwNKqK0K.js} +4 -4
  9. package/dist/assets/{JsonTreeView-BF8S-bPN.js → JsonTreeView-CmY7QgEX.js} +1 -1
  10. package/dist/assets/{MarkdownRendererImpl-BVNChdig.js → MarkdownRendererImpl-CpI-25Xk.js} +1 -1
  11. package/dist/assets/{PatchDiff-B--OaNB1.js → PatchDiff-CrIWbYj7.js} +1 -1
  12. package/dist/assets/{PierreDiffViewer-0Qkp9ICt.js → PierreDiffViewer-B410mdbq.js} +2 -2
  13. package/dist/assets/{SessionSwitcherDropdown-cFWgy1td.js → SessionSwitcherDropdown-DROjbyIu.js} +100 -100
  14. package/dist/assets/SettingsView-CsJItYZh.js +4 -0
  15. package/dist/assets/{SettingsWindow-BuJCvYoR.js → SettingsWindow-C9s4AX72.js} +1 -1
  16. package/dist/assets/{ToolOutputDialog-Bi9BoEe7.js → ToolOutputDialog-b_R4tAZu.js} +5 -5
  17. package/dist/assets/{ToolPartDiffPreview-DGX7N4zr.js → ToolPartDiffPreview-CfnliaE9.js} +1 -1
  18. package/dist/assets/{VirtualizedFileDiff-CxraYoDZ.js → VirtualizedFileDiff-CQz2fSZI.js} +4 -4
  19. package/dist/assets/{collapsible-d4-HChej.js → collapsible-CR4U9tjw.js} +1 -1
  20. package/dist/assets/{computeVirtualFileMetrics-BuD14qFL.js → computeVirtualFileMetrics-C7vXPUYT.js} +2 -2
  21. package/dist/assets/{contextFileOpenGuard-DirV-hCs.js → contextFileOpenGuard-DtTHRnq1.js} +1 -1
  22. package/dist/assets/{index-DEYblXCW.js → index-BAqpUCjs.js} +5 -5
  23. package/dist/assets/{index-BWmmf5yJ.js → index-DZG82DE1.js} +1 -1
  24. package/dist/assets/{index-DLKBsLKY.css → index-riABQmQ_.css} +1 -1
  25. package/dist/assets/{isDiffPlainText-LoMmNzmX.js → isDiffPlainText-zTq-4A04.js} +1 -1
  26. package/dist/assets/{isFilePlainText-3Hj9i02t.js → isFilePlainText-CLgIdzE5.js} +1 -1
  27. package/dist/assets/{main-BsszlAdQ.js → main-BVWtJYSk.js} +2 -2
  28. package/dist/assets/main-DXYHsqzA.js +133 -0
  29. package/dist/assets/{markdownCore-sGxk8jrc.js → markdownCore-CN0pApQE.js} +2 -2
  30. package/dist/assets/{miniChat-C6SDQL4G.js → miniChat-BrbRq5NQ.js} +2 -2
  31. package/dist/assets/{mobile-DBW3XDmZ.js → mobile-DTPtCn5N.js} +2 -2
  32. package/dist/assets/{renderElectronMiniChatApp-B1_fTdN-.js → renderElectronMiniChatApp-CM8qBaye.js} +1 -1
  33. package/dist/assets/{renderMobileApp-CFxZc_1a.js → renderMobileApp-KS_pt-qc.js} +4 -4
  34. package/dist/assets/{runtimeSurface-9aJdtQbh.js → runtimeSurface-CkHYYg0E.js} +1 -1
  35. package/dist/assets/{useInlineCommentController-Cl--s6vE.js → useInlineCommentController-CwNNjgc7.js} +2 -2
  36. package/dist/assets/usePanelSlide-DkorgQJ5.js +56 -0
  37. package/dist/assets/{useWindowTitle-C-AZD713.js → useWindowTitle-B9wt_3ZQ.js} +3 -3
  38. package/dist/assets/{vendor-codemirror-language-data-HC9JT4I3.js → vendor-codemirror-language-data-x89A7Wy0.js} +2 -2
  39. package/dist/assets/{vendor-sonner-dWA7qvjr.js → vendor-sonner-CW8w438f.js} +1 -1
  40. package/dist/assets/{web-components-skJ_VpnT.js → web-components-BEPfE4kU.js} +2 -2
  41. package/dist/index.html +4 -4
  42. package/dist/mini-chat.html +3 -3
  43. package/dist/mobile.html +3 -3
  44. package/package.json +1 -1
  45. package/server/index.js +33 -0
  46. package/server/lib/pi/routes.js +24 -2
  47. package/server/lib/pi/routes.test.js +14 -6
  48. package/server/lib/pi/session-daemon/DOCUMENTATION.md +4 -3
  49. package/server/lib/pi/session-daemon/message-entry-aliases.js +100 -0
  50. package/server/lib/pi/session-daemon/session-daemon.js +176 -46
  51. package/server/lib/pi/session-daemon/session-daemon.test.js +364 -6
  52. package/server/lib/pi/session-daemon/supervisor.js +20 -1
  53. package/server/lib/pi/session-daemon/supervisor.test.js +43 -0
  54. package/server/lib/pi/settings-store.js +17 -0
  55. package/server/lib/pi/settings-store.test.js +33 -0
  56. package/server/lib/server/core-routes.js +36 -4
  57. package/server/lib/server/tunnel-service.DOCUMENTATION.md +74 -0
  58. package/server/lib/server/tunnel-service.js +228 -0
  59. package/server/lib/server/tunnel-service.test.js +61 -0
  60. package/server/lib/ui-auth/DOCUMENTATION.md +2 -0
  61. package/server/lib/ui-auth/ui-auth.js +5 -1
  62. package/server/lib/ui-auth/ui-auth.test.js +17 -0
  63. package/dist/assets/SettingsView-D3ZZyjU3.js +0 -4
  64. package/dist/assets/main-CUvZIN16.js +0 -133
  65. package/dist/assets/usePanelSlide-D5ffPTGM.js +0 -56
@@ -1,4 +1,4 @@
1
- import{df as M,ef as V,eg as Y,eh as j,ei as K,ej as X,ek as J,el as $,em as Q,en as Z}from"./SessionSwitcherDropdown-cFWgy1td.js";import{b as ee,j as p,k as I,A as ne,a as G,l as te,m as C}from"./computeVirtualFileMetrics-BuD14qFL.js";import{t as ie}from"./vendor-hast-util-to-html-BKBhbTDb.js";function U(e,n,t){if(e===n||e==null||n==null)return e===n;const i=new Set(t),a=Object.keys(e),r=new Set(Object.keys(n));for(const s of a)if(r.delete(s),!i.has(s)&&(!(s in n)||e[s]!==n[s]))return!1;for(const s of Array.from(r))if(!i.has(s))return!1;return!0}function Te(e,n){const t=e?.theme??M,i=n?.theme??M,a=R(e),r=R(n);return ee(t,i)&&U(e,n,["theme","parseDiffOptions"])&&U(a,r)}function R(e){if(e!=null&&"parseDiffOptions"in e)return e.parseDiffOptions}function H(e,n){return e?.start===n?.start&&e?.end===n?.end&&e?.side===n?.side&&e?.endSide===n?.endSide}function ae(){return p({tagName:"button",properties:{"data-utility-button":"",type:"button"},children:[I({name:"diffs-icon-plus",properties:{"data-icon":""}})]})}function re(e,n){return e.lineNumber===n.lineNumber&&e.side===n.side}var Ie=class{mode;options;hoveredLine;hoveredToken;pre;gutterUtilityLine;gutterUtilityContainer;gutterUtilityButton;gutterUtilitySlot;interactiveLinesAttr=!1;interactiveLineNumbersAttr=!1;hasPointerListeners=!1;hasDocumentPointerListeners=!1;selectedRange=null;activeLineHighlightSide;activeLineNumberOnly=!1;editorAttached=!1;proposedSelectedRange;renderedSelectionRange;selectionAnchor;queuedSelectionRender;pointerSession={mode:"idle"};constructor(e,n){this.mode=e,this.options=n}setOptions(e){this.options=e}cleanUp(){this.pre?.removeEventListener("click",this.handlePointerClick),this.pre?.removeEventListener("pointerdown",this.handlePointerDown),this.pre?.removeEventListener("pointermove",this.handlePointerMove),this.pre?.removeEventListener("pointerleave",this.handlePointerLeave),this.pre?.removeAttribute("data-interactive-lines"),this.pre?.removeAttribute("data-interactive-line-numbers"),this.pre=void 0,this.gutterUtilityContainer?.remove(),this.gutterUtilityLine=void 0,this.gutterUtilityContainer=void 0,this.gutterUtilityButton=void 0,this.gutterUtilitySlot=void 0,this.clearHoveredLine(),this.clearHoveredToken(),this.detachDocumentPointerListeners(),this.clearPointerSession(),this.queuedSelectionRender!=null&&(cancelAnimationFrame(this.queuedSelectionRender),this.queuedSelectionRender=void 0),this.interactiveLinesAttr=!1,this.interactiveLineNumbersAttr=!1,this.hasPointerListeners=!1}setup(e){this.setSelectionDirty();const{usesCustomGutterUtility:n=!1,enableGutterUtility:t=!1}=this.options;this.pre!==e&&(this.cleanUp(),this.pre=e),t?this.ensureGutterUtilityNode(n):this.gutterUtilityContainer!=null&&(this.gutterUtilityContainer.remove(),this.gutterUtilityLine=void 0,this.gutterUtilityContainer=void 0,this.gutterUtilityButton=void 0,this.gutterUtilitySlot=void 0,this.pointerSession.mode==="gutterSelecting"&&(this.clearPointerSession(),this.detachDocumentPointerListeners())),this.syncPointerListeners(e),this.updateInteractiveLineAttributes(),this.renderSelection(),this.placeUtility()}setSelectionDirty(){this.renderedSelectionRange=void 0}setEditorAttached(e){this.editorAttached!==e&&(this.editorAttached=e,this.setSelectionDirty(),this.renderSelection())}isSelectionDirty(){return this.renderedSelectionRange===null}setSelection(e,n){const t=!(e===this.selectedRange||H(e??void 0,this.selectedRange??void 0));!this.isSelectionDirty()&&!t||(this.proposedSelectedRange=void 0,this.selectedRange=e,this.activeLineHighlightSide=n?.activeLineSide,this.activeLineNumberOnly=n?.lineNumberOnly??!1,this.renderSelection(),this.placeUtility(),t&&n?.notify!==!1&&this.notifySelectionCommitted())}getSelection(){return this.selectedRange}getHoveredLine=()=>{const e=this.gutterUtilityLine??this.hoveredLine;if(e!=null){if(this.mode==="diff"&&e.type==="diff-line")return{lineNumber:e.lineNumber,side:e.annotationSide};if(this.mode==="file"&&e.type==="line")return{lineNumber:e.lineNumber}}};handlePointerClick=e=>{const{onHunkExpand:n,onLineClick:t,onLineNumberClick:i,onTokenClick:a,onMergeConflictActionClick:r}=this.options;n==null&&t==null&&i==null&&r==null&&a==null||this.options.onGutterUtilityClick!=null&&E(e.composedPath())||(k(this.options.__debugPointerEvents,"click","FileDiff.DEBUG.handlePointerClick:",e),this.handlePointerEvent({eventType:"click",event:e}))};handlePointerMove=e=>{if(e.pointerType!=="mouse")return;const{lineHoverHighlight:n="disabled",onLineEnter:t,onLineLeave:i,onTokenEnter:a,onTokenLeave:r,enableGutterUtility:s=!1}=this.options;n==="disabled"&&!s&&t==null&&i==null&&a==null&&r==null||(k(this.options.__debugPointerEvents,"move","FileDiff.DEBUG.handlePointerMove:",e),this.handlePointerEvent({eventType:"move",event:e}))};handlePointerLeave=e=>{const{__debugPointerEvents:n}=this.options;if(k(n,"move","FileDiff.DEBUG.handlePointerLeave: no event"),this.hoveredLine==null&&this.hoveredToken==null){k(n,"move","FileDiff.DEBUG.handlePointerLeave: returned early, no hovered line or token");return}this.hoveredToken!=null&&(this.options.onTokenLeave?.(this.hoveredToken,e),this.clearHoveredToken()),this.hoveredLine!=null&&(this.options.onLineLeave?.({...this.hoveredLine,event:e}),this.clearHoveredLine()),this.placeUtility()};handlePointerEvent({eventType:e,event:n}){const{__debugPointerEvents:t}=this.options,i=n.composedPath();k(t,e,"FileDiff.DEBUG.handlePointerEvent:",{eventType:e,composedPath:i});const a=this.resolvePointerTarget(i);k(t,e,"FileDiff.DEBUG.handlePointerEvent: resolvePointerTarget result:",a);const{onLineClick:r,onLineNumberClick:s,onLineEnter:l,onLineLeave:o,onTokenClick:d,onTokenEnter:c,onTokenLeave:m,onHunkExpand:h,onMergeConflictActionClick:f}=this.options;switch(e){case"move":{const u=T(a)&&this.hoveredLine?.lineElement===a.lineElement;A(a)&&this.hoveredToken?.tokenElement===a.tokenElement||(this.hoveredToken!=null&&(m?.(this.hoveredToken,n),this.clearHoveredToken()),A(a)&&(this.setHoveredToken(this.toTokenEventBaseProps(a)),c?.(this.hoveredToken,n))),u||(this.hoveredLine!=null&&(o?.({...this.hoveredLine,event:n}),this.clearHoveredLine()),T(a)?(this.setHoveredLine(this.toEventBaseProps(a)),this.placeUtility(),l?.({...this.hoveredLine,event:n})):this.placeUtility());break}case"click":{if(a==null)break;if(de(a)&&f!=null){f(a);break}if(se(a)&&h!=null){h(a.hunkIndex,a.all||n.shiftKey?"both":a.direction,a.all||n.shiftKey?Number.POSITIVE_INFINITY:void 0);break}if(!T(a))break;A(a)&&d!=null&&d(this.toTokenEventBaseProps(a),n);const u=this.toEventBaseProps(a);s!=null&&a.numberColumn?s({...u,event:n}):r?.({...u,event:n});break}}}syncPointerListeners(e){const{__debugPointerEvents:n,lineHoverHighlight:t="disabled",onLineClick:i,onLineNumberClick:a,onLineEnter:r,onLineLeave:s,onTokenClick:l,onTokenEnter:o,onTokenLeave:d,onHunkExpand:c,onMergeConflictActionClick:m,enableGutterUtility:h=!1,enableLineSelection:f=!1,onGutterUtilityClick:u}=this.options,v=u!=null,b=t!=="disabled"||i!=null||a!=null||r!=null||s!=null||l!=null||o!=null||d!=null||c!=null||m!=null||h||f||v;b&&!this.hasPointerListeners?(e.addEventListener("click",this.handlePointerClick),e.addEventListener("pointerdown",this.handlePointerDown),e.addEventListener("pointermove",this.handlePointerMove),e.addEventListener("pointerleave",this.handlePointerLeave),this.hasPointerListeners=!0,k(n,"click","FileDiff.DEBUG.attachEventListeners: Attaching click events for:",(()=>{const x=[];return(n==="both"||n==="click")&&(i!=null&&x.push("onLineClick"),a!=null&&x.push("onLineNumberClick"),c!=null&&x.push("expandable hunk separators"),m!=null&&x.push("merge conflict actions")),x})()),k(n,"move","FileDiff.DEBUG.attachEventListeners: Attaching pointer move event"),k(n,"move","FileDiff.DEBUG.attachEventListeners: Attaching pointer leave event")):!b&&this.hasPointerListeners&&(e.removeEventListener("click",this.handlePointerClick),e.removeEventListener("pointerdown",this.handlePointerDown),e.removeEventListener("pointermove",this.handlePointerMove),e.removeEventListener("pointerleave",this.handlePointerLeave),this.hasPointerListeners=!1);const g=this.pointerSession.mode==="selecting"||this.pointerSession.mode==="pendingSingleLineUnselect",y=this.pointerSession.mode==="gutterSelecting";(!f&&g||!v&&y)&&(this.clearPointerSession(),this.detachDocumentPointerListeners(),this.selectionAnchor=void 0,this.clearPendingSingleLineState())}updateInteractiveLineAttributes(){if(this.pre==null)return;const{onLineClick:e,onLineNumberClick:n,enableLineSelection:t=!1}=this.options,i=e!=null,a=n!=null||t;i&&!this.interactiveLinesAttr?(this.pre.setAttribute("data-interactive-lines",""),this.interactiveLinesAttr=!0):!i&&this.interactiveLinesAttr&&(this.pre.removeAttribute("data-interactive-lines"),this.interactiveLinesAttr=!1),a&&!this.interactiveLineNumbersAttr?(this.pre.setAttribute("data-interactive-line-numbers",""),this.interactiveLineNumbersAttr=!0):!a&&this.interactiveLineNumbersAttr&&(this.pre.removeAttribute("data-interactive-line-numbers"),this.interactiveLineNumbersAttr=!1)}handlePointerDown=e=>{if(e.pointerType==="mouse"&&e.button!==0||this.pre==null||this.pointerSession.mode!=="idle")return;const n=e.composedPath();E(n)&&this.options.onGutterUtilityClick!=null?this.startGutterSelectionFromPointerDown(e):(e.pointerType!=="mouse"&&this.revealUtilityFromGutterPath(n),this.startLineSelectionFromPointerDown(e))};startLineSelectionFromPointerDown(e){const{enableLineSelection:n=!1}=this.options;if(!n)return;const t=this.resolveSelectionInfo(e,{source:"event-path",requireNumberColumn:!0});if(t==null)return;const{pre:i}=this;if(i==null)return;e.preventDefault();const{lineNumber:a,eventSide:r,lineIndex:s}=t;if(e.shiftKey&&this.selectedRange!=null){const l=this.getIndexesFromSelection(this.selectedRange,i.getAttribute("data-diff-type")==="split");if(l==null)return;const o=l.start<=l.end?s>=l.start:s<=l.end;this.selectionAnchor={lineNumber:o?this.selectedRange.start:this.selectedRange.end,side:o?this.selectedRange.side:this.selectedRange.endSide??this.selectedRange.side},this.updateSelection(a,r,!1),this.notifySelectionStart(this.getCurrentSelectionRange()),this.pointerSession={mode:"selecting",pointerId:e.pointerId},this.attachDocumentPointerListeners();return}if(this.selectedRange?.start===a&&this.selectedRange?.end===a){const l={lineNumber:a,side:r};this.selectionAnchor=l,this.pointerSession={mode:"pendingSingleLineUnselect",pointerId:e.pointerId,anchor:l,pending:l},this.attachDocumentPointerListeners();return}this.options.controlledSelection===!0?this.proposedSelectedRange=null:this.selectedRange=null,this.placeUtility(),this.selectionAnchor={lineNumber:a,side:r},this.updateSelection(a,r,!1),this.notifySelectionStart(this.getCurrentSelectionRange()),this.pointerSession={mode:"selecting",pointerId:e.pointerId},this.attachDocumentPointerListeners()}startGutterSelectionFromPointerDown(e){const{enableLineSelection:n=!1,onGutterUtilityClick:t}=this.options;if(t==null)return;const i=this.currentSelectionEnds(),a=i?.bottom??this.resolveSelectionPoint(e,{source:"event-path",excludeUtility:!1}),r=i?.top??a;a==null||r==null||(e.preventDefault(),e.stopPropagation(),this.pointerSession={mode:"gutterSelecting",pointerId:e.pointerId,anchor:r,current:a},n&&(this.selectionAnchor={lineNumber:r.lineNumber,side:r.side},this.updateSelection(a.lineNumber,a.side,!1),this.notifySelectionStart(this.getCurrentSelectionRange())),this.attachDocumentPointerListeners())}handleDocumentPointerMove=e=>{const{enableLineSelection:n=!1}=this.options;switch(this.pointerSession.mode){case"idle":return;case"gutterSelecting":{if(e.pointerId!==this.pointerSession.pointerId)return;e.preventDefault();const t=this.resolveSelectionPoint(e,{source:"coordinates-first"});if(t==null)return;this.pointerSession.current=t,n===!0&&this.updateSelection(t.lineNumber,t.side);return}case"selecting":{if(e.pointerId!==this.pointerSession.pointerId)return;e.preventDefault();const t=this.resolveSelectionInfo(e,{source:"coordinates-first",requireNumberColumn:!1});if(t==null||this.selectionAnchor==null)return;this.updateSelection(t.lineNumber,t.eventSide);return}case"pendingSingleLineUnselect":{if(e.pointerId!==this.pointerSession.pointerId)return;e.preventDefault();const t=this.resolveSelectionInfo(e,{source:"coordinates-first",requireNumberColumn:!1});if(t==null||this.selectionAnchor==null)return;const i={lineNumber:t.lineNumber,side:t.eventSide};if(re(this.pointerSession.pending,i))return;this.updateSelection(t.lineNumber,t.eventSide,!1),this.notifySelectionStart(this.getCurrentSelectionRange()),this.notifySelectionChangeDelta(),this.pointerSession={mode:"selecting",pointerId:e.pointerId};return}}};handleDocumentPointerUp=e=>{const{enableLineSelection:n=!1,onGutterUtilityClick:t}=this.options;switch(this.pointerSession.mode){case"idle":return;case"gutterSelecting":{if(e.pointerId!==this.pointerSession.pointerId)return;e.preventDefault();const i=this.resolveSelectionPoint(e,{source:"coordinates-first"});i!=null&&(this.pointerSession.current=i,n&&this.updateSelection(i.lineNumber,i.side)),t?.(this.buildSelectedLineRange(this.pointerSession.anchor,this.pointerSession.current)),this.selectionAnchor=void 0,n&&(this.notifySelectionEnd(this.getCurrentSelectionRange()),this.notifySelectionCommitted(),this.clearProposedSelection()),this.clearPointerSession(),this.detachDocumentPointerListeners();return}case"pendingSingleLineUnselect":if(e.pointerId!==this.pointerSession.pointerId)return;e.preventDefault(),this.updateSelection(null,void 0,!1),this.selectionAnchor=void 0,this.clearPendingSingleLineState(),this.detachDocumentPointerListeners(),this.notifySelectionEnd(this.getCurrentSelectionRange()),this.notifySelectionCommitted(),this.clearProposedSelection();return;case"selecting":if(e.pointerId!==this.pointerSession.pointerId)return;e.preventDefault(),this.selectionAnchor=void 0,this.detachDocumentPointerListeners(),this.clearPointerSession(),this.notifySelectionEnd(this.getCurrentSelectionRange()),this.notifySelectionCommitted(),this.clearProposedSelection()}};handleDocumentPointerCancel=e=>{switch(this.pointerSession.mode){case"idle":return;case"gutterSelecting":case"selecting":case"pendingSingleLineUnselect":if("pointerId"in this.pointerSession&&e.pointerId!==this.pointerSession.pointerId)return;this.selectionAnchor=void 0,this.clearProposedSelection(),this.clearPendingSingleLineState(),this.clearPointerSession(),this.detachDocumentPointerListeners()}};clearHoveredLine(){this.hoveredLine!=null&&(this.hoveredLine.lineElement.removeAttribute("data-hovered"),this.hoveredLine.numberElement.removeAttribute("data-hovered"),this.hoveredLine=void 0)}setHoveredLine(e){const{lineHoverHighlight:n="disabled"}=this.options;this.hoveredLine!=null&&this.clearHoveredLine(),this.hoveredLine=e,n!=="disabled"&&((n==="both"||n==="line")&&this.hoveredLine.lineElement.setAttribute("data-hovered",""),(n==="both"||n==="number")&&this.hoveredLine.numberElement.setAttribute("data-hovered",""))}clearHoveredToken(){this.hoveredToken!=null&&(this.hoveredToken=void 0)}setHoveredToken(e){this.hoveredToken!=null&&this.clearHoveredToken(),this.hoveredToken=e}ensureGutterUtilityNode(e){if(this.gutterUtilityContainer==null&&(this.gutterUtilityContainer=document.createElement("div"),this.gutterUtilityContainer.setAttribute("data-gutter-utility-slot","")),e)this.gutterUtilityButton!=null&&(this.gutterUtilityButton.remove(),this.gutterUtilityButton=void 0),this.gutterUtilitySlot==null&&(this.gutterUtilitySlot=document.createElement("slot"),this.gutterUtilitySlot.name="gutter-utility-slot"),this.gutterUtilitySlot.parentNode!==this.gutterUtilityContainer&&this.gutterUtilityContainer.replaceChildren(this.gutterUtilitySlot);else{if(this.gutterUtilitySlot?.remove(),this.gutterUtilitySlot=void 0,this.gutterUtilityButton==null){const n=document.createElement("div");n.innerHTML=ie(ae());const t=n.firstElementChild;if(!(t instanceof HTMLButtonElement))throw new Error("InteractionManager.ensureGutterUtilityNode: Node element should be a button");t.remove(),this.gutterUtilityButton=t}this.gutterUtilityButton.parentNode!==this.gutterUtilityContainer&&this.gutterUtilityContainer.replaceChildren(this.gutterUtilityButton)}}revealUtilityFromGutterPath(e){if(this.placeUtilityFromSelection())return;const n=this.resolvePointerTarget(e);w(n)&&n.numberColumn&&this.showUtilityOnLine(this.toEventBaseProps(n))}placeUtility(){if(!this.placeUtilityFromSelection()){if(this.hoveredLine!=null){this.showUtilityOnLine(this.hoveredLine);return}this.hideUtility()}}placeUtilityFromSelection(){const e=this.currentSelectionEnds();if(e==null)return!1;const n=this.targetForSelectionPoint(e.bottom);return n==null?this.hideUtility():this.showUtilityOnLine(this.toEventBaseProps(n)),!0}showUtilityOnLine(e){this.gutterUtilityContainer!=null&&(this.gutterUtilityLine=e,e.numberElement.appendChild(this.gutterUtilityContainer))}hideUtility(){this.gutterUtilityContainer?.remove(),this.gutterUtilityLine=void 0}currentSelectionEnds(){const e=this.getCurrentSelectionRange();return e==null?void 0:this.selectionEnds(e)}selectionEnds(e){const n={lineNumber:e.start,side:e.side},t={lineNumber:e.end,side:e.endSide??e.side},i=this.selectionPointRowIndex(n),a=this.selectionPointRowIndex(t);if(!(i==null||a==null))return i>a?{top:t,bottom:n}:{top:n,bottom:t}}selectionPointRowIndex(e){const n=this.getLineIndex(e.lineNumber,e.side);if(n!=null)return this.isSplitDiff()?n[1]:n[0]}targetForSelectionPoint(e){if(this.pre==null)return;const n=this.getLineIndex(e.lineNumber,e.side);if(n==null)return;const t=this.mode==="diff"?`${n[0]},${n[1]}`:`${n[0]}`,i=this.pre.querySelectorAll(`[data-column-number="${e.lineNumber}"][data-line-index="${t}"]`);for(const a of i){if(!(a instanceof HTMLElement))continue;const r=this.resolvePointerTarget(L(a));if(w(r)&&!(this.mode==="diff"&&e.side!=null&&r.side!==e.side))return r}}attachDocumentPointerListeners(){this.hasDocumentPointerListeners||(document.addEventListener("pointermove",this.handleDocumentPointerMove),document.addEventListener("pointerup",this.handleDocumentPointerUp),document.addEventListener("pointercancel",this.handleDocumentPointerCancel),this.hasDocumentPointerListeners=!0)}detachDocumentPointerListeners(){this.hasDocumentPointerListeners&&(document.removeEventListener("pointermove",this.handleDocumentPointerMove),document.removeEventListener("pointerup",this.handleDocumentPointerUp),document.removeEventListener("pointercancel",this.handleDocumentPointerCancel),this.hasDocumentPointerListeners=!1)}clearPointerSession(){this.pointerSession={mode:"idle"}}clearPendingSingleLineState(){this.pointerSession.mode==="pendingSingleLineUnselect"&&(this.pointerSession={mode:"idle"})}selectionInfoFromPath(e,n){const t=this.resolvePointerTarget(e);if(w(t)&&!(n&&!t.numberColumn)&&t.splitLineIndex!=null)return{lineIndex:t.splitLineIndex,lineNumber:t.lineNumber,eventSide:this.mode==="diff"?t.side:void 0}}resolveSelectionInfo(e,n){const t=this.resolveSelectionPath(e,n);return t!=null?this.selectionInfoFromPath(t,n.requireNumberColumn):void 0}selectionPointFromPath(e){const n=this.resolvePointerTarget(e);if(w(n))return{lineNumber:n.lineNumber,side:this.mode==="diff"?n.side:void 0}}resolveSelectionPoint(e,n){const t=this.resolveSelectionPath(e,n);return t!=null?this.selectionPointFromPath(t):void 0}resolveSelectionPath(e,n){const t=n.excludeUtility!==!1;switch(n.source){case"event-path":return this.pathFromEventPath(e.composedPath(),t);case"coordinates-first":{const i=this.pathFromCoordinates(e,t);return i!==void 0?i??void 0:this.pathFromEventPath(e.composedPath(),t)}}}pathFromCoordinates(e,n){const t=this.hitTest(e);if(t!==void 0)return t===null?null:this.pathFromElement(t,n)??null}pathFromEventPath(e,n){if(!(n&&E(e))){for(const t of e)if(t instanceof Element)return this.pathFromElement(t,n)}}pathFromElement(e,n){const t=L(e);if(n&&E(t))return;const i=fe(e);return i!=null?L(i):this.pathFromAnnotationSlot(e)}pathFromAnnotationSlot(e){const n=ue(ce(e));if(n==null)return;const t=this.targetForSelectionPoint(n);return t!=null?L(t.lineElement):void 0}hitTest(e){if(!Number.isFinite(e.clientX)||!Number.isFinite(e.clientY))return;const n=this.pre?.getRootNode(),t=z(n)?n:z(document)?document:void 0;if(t!=null)return t.elementFromPoint(e.clientX,e.clientY)}getLineIndex(e,n){const{getLineIndex:t}=this.options;return t!=null?t(e,n):[e-1,e-1]}getCurrentSelectionRange(){return this.proposedSelectedRange!==void 0?this.proposedSelectedRange:this.selectedRange}clearProposedSelection(){this.proposedSelectedRange=void 0}updateSelection(e,n,t=!0){const i=this.getCurrentSelectionRange();let a;if(e==null)a=null;else{const r=this.selectionAnchor?.side??n,s=this.selectionAnchor?.lineNumber??e;a=this.buildSelectionRange(s,e,r,n)}H(i??void 0,a??void 0)||(this.activeLineHighlightSide=void 0,this.activeLineNumberOnly=!1,this.options.controlledSelection===!0?this.proposedSelectedRange=a:(this.selectedRange=a,this.queuedSelectionRender??=requestAnimationFrame(this.renderSelection)),this.placeUtility(),t&&this.notifySelectionChangeDelta())}getIndexesFromSelection(e,n){if(this.pre==null)return;const t=this.getLineIndex(e.start,e.side),i=this.getLineIndex(e.end,e.endSide??e.side);return t!=null&&i!=null?{start:n?t[1]:t[0],end:n?i[1]:i[0]}:void 0}highlightLineNumberOnly(){return this.activeLineHighlightSide!=null?this.activeLineNumberOnly:this.activeLineNumberOnly||this.editorAttached}renderSelection=()=>{if(this.queuedSelectionRender!=null&&(cancelAnimationFrame(this.queuedSelectionRender),this.queuedSelectionRender=void 0),this.pre==null||this.renderedSelectionRange===this.selectedRange)return;const e=this.pre.querySelectorAll("[data-selected-line]");for(const o of e)o.removeAttribute("data-selected-line");if(this.renderedSelectionRange=this.selectedRange,this.selectedRange==null)return;const{children:n}=this.pre;if(n.length===0)return;if(n.length>2)throw console.error(n),new Error("InteractionManager.renderSelection: Somehow there are more than 2 code elements...");const t=this.pre.getAttribute("data-diff-type")==="split",i=this.getIndexesFromSelection(this.selectedRange,t);if(i==null)throw console.error({rowRange:i,selectedRange:this.selectedRange}),new Error("InteractionManager.renderSelection: No valid rowRange");const a=i.start===i.end,r=Math.min(i.start,i.end),s=Math.max(i.start,i.end),l=this.highlightLineNumberOnly();for(const o of n){const d=this.activeLineHighlightSide;if(d!=null&&(d==="additions"&&o.hasAttribute("data-deletions")||d==="deletions"&&o.hasAttribute("data-additions")))continue;const[c,m]=o.children,h=m.children.length;if(h!==c.children.length)throw new Error("InteractionManager.renderSelection: gutter and content children dont match, something is wrong");for(let f=0;f<h;f++){const u=m.children[f],v=c.children[f];if(!(u instanceof HTMLElement)||!(v instanceof HTMLElement))continue;const b=this.parseLineIndex(u,t);if((b??0)>s)break;if(b==null||b<r)continue;let g=a?"single":b===r?"first":b===s?"last":"";v.setAttribute("data-selected-line",g),!l&&(u.setAttribute("data-selected-line",g),v.nextSibling instanceof HTMLElement&&u.nextSibling instanceof HTMLElement&&(u.nextSibling.hasAttribute("data-line-annotation")||u.nextSibling.hasAttribute("data-merge-conflict-actions"))&&(a?(g="last",u.setAttribute("data-selected-line","first")):b===r?g="":b===s&&u.setAttribute("data-selected-line",""),u.nextSibling.setAttribute("data-selected-line",g),v.nextSibling.setAttribute("data-selected-line",g)))}}};notifySelectionCommitted(){this.options.onLineSelected?.(this.getCurrentSelectionRange()??null)}notifySelectionChangeDelta(){this.options.onLineSelectionChange?.(this.getCurrentSelectionRange()??null)}notifySelectionStart(e){this.options.onLineSelectionStart?.(e)}notifySelectionEnd(e){this.options.onLineSelectionEnd?.(e)}toEventBaseProps(e){return this.mode==="file"?{type:"line",lineElement:e.lineElement,lineNumber:e.lineNumber,numberColumn:e.numberColumn,numberElement:e.numberElement}:{type:"diff-line",annotationSide:e.side,lineType:e.lineType,lineElement:e.lineElement,numberElement:e.numberElement,lineNumber:e.lineNumber,numberColumn:e.numberColumn}}toTokenEventBaseProps({lineCharEnd:e,lineCharStart:n,lineNumber:t,side:i,tokenElement:a,tokenText:r}){return this.mode==="file"?{type:"token",lineCharEnd:e,lineCharStart:n,lineNumber:t,tokenElement:a,tokenText:r}:{type:"token",lineCharEnd:e,lineCharStart:n,lineNumber:t,side:i,tokenElement:a,tokenText:r}}buildSelectedLineRange(e,n){return this.buildSelectionRange(e.lineNumber,n.lineNumber,e.side,n.side)}buildSelectionRange(e,n,t,i){return{start:e,end:n,...t!=null?{side:t}:{},...t!==i&&i!=null?{endSide:i}:{}}}resolvePointerTarget(e){let n=!1,t,i,a,r,s,l,o,d,c,m;for(const f of e){if(!(f instanceof HTMLElement))continue;if(m==null&&f.hasAttribute("data-merge-conflict-action")){const g=f.getAttribute("data-merge-conflict-action")??void 0,y=f.getAttribute("data-merge-conflict-conflict-index")??void 0,x=y!=null?Number.parseInt(y,10):NaN;le(g)&&Number.isFinite(x)&&(m={kind:"merge-conflict-action",resolution:g,conflictIndex:x})}if(l==null&&f.hasAttribute("data-char")){l=f;const g=f.getAttribute("data-char");if(g!=null){const y=Number.parseInt(g,10);if(!Number.isNaN(y)){const x=f.textContent??"",N=y+x.length;(x.trim()!==""||this.options.enableTokenInteractionsOnWhitespace===!0)&&(o={tokenElement:l,lineCharStart:y,lineCharEnd:N,tokenText:x});continue}}}const u=s==null?f.getAttribute("data-column-number")??void 0:void 0;if(u!=null){s=f,c=Number.parseInt(u,10),n=!0,t=O(f),r=f.getAttribute("data-line-index")??void 0;continue}const v=a==null?f.getAttribute("data-line")??void 0:void 0;if(v!=null){a=f,c=Number.parseInt(v,10),t=O(f),r=f.getAttribute("data-line-index")??void 0;continue}if(d==null&&(f.hasAttribute("data-expand-button")||f.hasAttribute("data-unmodified-lines"))){d={hunkIndex:void 0,direction:f.hasAttribute("data-expand-up")?"up":f.hasAttribute("data-expand-down")?"down":"both",all:f.hasAttribute("data-expand-all-button")};continue}const b=d!=null?f.getAttribute("data-expand-index")??void 0:void 0;if(d!=null&&b!=null){const g=Number.parseInt(b,10);Number.isNaN(g)||(d.hunkIndex=g);continue}if(i==null&&f.hasAttribute("data-code")){i=f;break}}if(m!=null)return m;if(d?.hunkIndex!=null)return{type:"line-info",hunkIndex:d.hunkIndex,direction:d.direction,all:d.all};if(a??=r!=null?D(i,`[data-line][data-line-index="${r}"]`):void 0,s??=r!=null?D(i,`[data-column-number][data-line-index="${r}"]`):void 0,i==null||a==null||s==null||t==null||c==null||Number.isNaN(c))return;const h=this.parseLineIndex(a,this.isSplitDiff());return o!=null?this.mode==="file"?{kind:"token",lineType:t,lineElement:a,lineNumber:c,numberColumn:n,numberElement:s,side:void 0,splitLineIndex:h,...o}:{kind:"token",lineType:t,lineElement:a,lineNumber:c,numberColumn:n,numberElement:s,side:F(t,i),splitLineIndex:h,...o}:this.mode==="file"?{kind:"line",lineType:t,lineElement:a,lineNumber:c,numberColumn:n,numberElement:s,side:void 0,splitLineIndex:h}:{kind:"line",lineType:t,lineElement:a,lineNumber:c,numberColumn:n,numberElement:s,side:F(t,i),splitLineIndex:h}}isSplitDiff(){return this.pre?.getAttribute("data-diff-type")==="split"}parseLineIndex(e,n){const t=(e.getAttribute("data-line-index")??"").split(",").map(i=>Number.parseInt(i,10)).filter(i=>!Number.isNaN(i));if(n&&t.length===2)return t[1];if(!n)return t[0]}};function Me({enableTokenInteractionsOnWhitespace:e,enableGutterUtility:n,lineHoverHighlight:t,onGutterUtilityClick:i,onLineClick:a,onLineEnter:r,onLineLeave:s,onLineNumberClick:l,onTokenClick:o,onTokenEnter:d,onTokenLeave:c,renderGutterUtility:m,__debugPointerEvents:h,enableLineSelection:f,controlledSelection:u,onLineSelected:v,onLineSelectionStart:b,onLineSelectionChange:g,onLineSelectionEnd:y},x,N,W){return{enableTokenInteractionsOnWhitespace:e,enableGutterUtility:oe({enableGutterUtility:n,renderGutterUtility:m,onGutterUtilityClick:i}),usesCustomGutterUtility:m!=null,lineHoverHighlight:t,onGutterUtilityClick:i,onHunkExpand:x,onMergeConflictActionClick:W,onLineClick:a,onLineEnter:r,onLineLeave:s,onLineNumberClick:l,onTokenClick:o,onTokenEnter:d,onTokenLeave:c,__debugPointerEvents:h,enableLineSelection:f,controlledSelection:u,onLineSelected:v,onLineSelectionStart:b,onLineSelectionChange:g,onLineSelectionEnd:y,getLineIndex:N}}function oe({enableGutterUtility:e,renderGutterUtility:n,onGutterUtilityClick:t}){if(t!=null&&n!=null)throw new Error("Cannot use both 'onGutterUtilityClick' and 'renderGutterUtility'. Use only one gutter utility API.");return e??!1}function w(e){return e!=null&&"kind"in e&&e.kind==="line"}function A(e){return e!=null&&"kind"in e&&e.kind==="token"}function T(e){return w(e)||A(e)}function se(e){return"type"in e&&e.type==="line-info"}function de(e){return"kind"in e&&e.kind==="merge-conflict-action"}function le(e){return e==="current"||e==="incoming"||e==="both"}function D(e,n){const t=e?.querySelector(n);return t instanceof HTMLElement?t:void 0}function L(e){const n=[];let t=e;for(;t!=null;)n.push(t),t=t.parentNode;return n}function fe(e){const n=e.closest("[data-line], [data-column-number]");if(n instanceof HTMLElement)return n;const t=e.closest('[data-line-annotation], [data-gutter-buffer="annotation"]');if(!(t instanceof HTMLElement))return;const i=t.previousElementSibling;return i instanceof HTMLElement&&(i.hasAttribute("data-line")||i.hasAttribute("data-column-number"))?i:void 0}function ce(e){const n=e.closest('[slot^="annotation-"]');if(n instanceof HTMLElement)return n.getAttribute("slot")??void 0;if(e instanceof HTMLElement){const t=e.getAttribute("name")??void 0;return t!=null&&t.startsWith("annotation-")?t:void 0}}function ue(e){if(e==null)return;const n=/^annotation-(?:(additions|deletions)-)?(\d+)$/.exec(e);if(n==null)return;const t=Number.parseInt(n[2],10);if(!(!Number.isFinite(t)||t<=0))return{lineNumber:t,side:n[1]}}function z(e){return e!=null&&typeof e.elementFromPoint=="function"}function F(e,n){switch(e){case"change-deletion":return"deletions";case"change-addition":return"additions";default:return n.hasAttribute("data-deletions")?"deletions":"additions"}}function O(e){const n=e.getAttribute("data-line-type");if(n!=null)switch(n){case"change-deletion":case"change-addition":case"context":case"context-expanded":return n;default:return}}function E(e){for(const n of e)if(n instanceof HTMLElement&&(n.hasAttribute("data-utility-button")||n.hasAttribute("data-gutter-utility-slot")||n.getAttribute("slot")==="gutter-utility-slot"||n.getAttribute("name")==="gutter-utility-slot"))return!0;return!1}function k(e="none",n,...t){switch(e){case"none":return;case"both":break;case"click":if(n!=="click")return;break;case"move":if(n!=="move")return;break}console.log(...t)}var Ue=class S{static resizeObserver;static managersByElement=new Map;static getResizeObserver(){const n=S.resizeObserver??new ResizeObserver(S.handleSharedResizeEntries);return S.resizeObserver=n,n}static handleSharedResizeEntries(n){const t=new Map;for(const i of n){const a=S.managersByElement.get(i.target);if(a==null)continue;const r=t.get(a);r==null?t.set(a,[i]):r.push(i)}for(const[i,a]of t)i.handleResizeEntries(a)}observedNodes=new Map;setup(n,t){const i=new Set;let a=0;const r=new Map(this.observedNodes);this.observedNodes.clear();for(const s of n.children){if(a===2)break;const l=(()=>{if(s instanceof HTMLElement&&s.tagName==="CODE")return s})();if(l==null)continue;a++;let o=r.get(l);if(o!=null&&o.type!=="code")throw new Error("ResizeManager.setup: somehow a code node is being used for an annotation, should be impossible");let d=l.firstElementChild;d instanceof HTMLElement||(d=null),o!=null?(this.observedNodes.set(l,o),r.delete(l),o.numberElement!==d?(o.numberElement!=null&&(this.unobserve(o.numberElement),r.delete(o.numberElement)),d!=null&&(this.observe(d),r.delete(d),this.observedNodes.set(d,o)),o.numberElement=d,o.numberWidth=0):o.numberElement!=null?(r.delete(o.numberElement),this.observedNodes.set(o.numberElement,o)):o.numberWidth=0):(o={type:"code",codeElement:l,numberElement:d,codeWidth:"auto",numberWidth:0},this.observedNodes.set(l,o),this.observe(l),d!=null&&(this.observedNodes.set(d,o),this.observe(d)))}if(a>1&&!t){const s=n.querySelectorAll('[data-line-annotation*=","]'),l=new Map;for(const o of s){if(!(o instanceof HTMLElement))continue;const d=o.getAttribute("data-line-annotation")??"";if(!/^-?\d+,-?\d+$/.test(d)){console.error("DiffFileRenderer.setupResizeObserver: Invalid element or annotation",{lineAnnotation:d,element:o});continue}let c=l.get(d);c==null&&(c=[],l.set(d,c)),c.push(o)}for(const[o,d]of l){if(d.length!==2){console.error("DiffFileRenderer.setupResizeObserver: Bad Pair",o,d);continue}const[c,m]=d,h=c.firstElementChild,f=m.firstElementChild;if(!(c instanceof HTMLElement)||!(m instanceof HTMLElement)||!(h instanceof HTMLElement)||!(f instanceof HTMLElement))continue;let u=r.get(h);if(u!=null){this.observedNodes.set(h,u),this.observedNodes.set(f,u),r.delete(h),r.delete(f);continue}const v=h.getBoundingClientRect().height,b=f.getBoundingClientRect().height;u={type:"annotations",column1:{container:c,child:h,childHeight:v},column2:{container:m,child:f,childHeight:b},currentHeight:"auto"},i.add({child1:h,child2:f,item:u,newHeight:Math.max(v,b)})}for(const o of i)this.applyNewHeight(o.item,o.newHeight),this.observedNodes.set(o.child1,o.item),this.observedNodes.set(o.child2,o.item),this.observe(o.child1),this.observe(o.child2);i.clear()}for(const[s,l]of r)this.unobserve(s),l.type==="code"?ge(l):pe(l);r.clear()}cleanUp(){for(const n of this.observedNodes.keys())this.unobserve(n);this.observedNodes.clear()}observe(n){const{managersByElement:t}=S,i=t.get(n);if(i!==this){if(i!=null&&i!==this)throw new Error("ResizeManager.observe: element is already owned by another ResizeManager");t.set(n,this),S.getResizeObserver().observe(n)}}unobserve(n){const{managersByElement:t,resizeObserver:i}=S,a=t.get(n);if(a!=null){if(a!==this)throw new Error("ResizeManager.unobserve: element is owned by another ResizeManager");t.delete(n),i?.unobserve(n),i!=null&&t.size===0&&(i.disconnect(),S.resizeObserver=void 0)}}handleResizeEntries(n){const t=new Map,i=new Set;for(const a of n){const{target:r,borderBoxSize:s,contentBoxSize:l}=a;if(!(r instanceof HTMLElement)){console.error("ResizeManager.handleResizeEntries: Invalid element for ResizeObserver",a);continue}const o=this.observedNodes.get(r);if(o==null){console.error("ResizeManager.handleResizeEntries: Not a valid observed node",a);continue}if(o.type==="annotations"){const d=(()=>{if(r===o.column1.child)return o.column1;if(r===o.column2.child)return o.column2})();if(d==null){console.error("ResizeManager.handleResizeEntries: Couldn't find a column for",{item:o,target:r});continue}d.childHeight=s[0].blockSize,i.add(o)}else if(o.type==="code"){const d=t.get(o)??{},c=l[0].inlineSize;r===o.codeElement?d.codeInlineSize=c:r===o.numberElement&&(d.numberInlineSize=c),t.set(o,d)}}this.applyAnnotationUpdates(i),i.clear(),this.applyColumnUpdates(t),t.clear()}applyAnnotationUpdates(n){for(const t of n)this.applyNewHeight(t,Math.max(t.column1.childHeight,t.column2.childHeight))}applyColumnUpdates=n=>{for(const[t,i]of n){const a=i.codeInlineSize!=null?he(i.codeInlineSize):t.codeWidth,r=i.numberInlineSize!=null?me(i.numberInlineSize):t.numberWidth,s=a!==t.codeWidth,l=r!==t.numberWidth;if(!(!s&&!l)&&(t.codeWidth=a,t.numberWidth=r,s&&t.codeElement.style.setProperty("--diffs-column-width",`${typeof a=="number"?`${a}px`:"auto"}`),l&&t.codeElement.style.setProperty("--diffs-column-number-width",`${r===0?"auto":`${r}px`}`),s||l&&a!=="auto")){const o=typeof a=="number"?Math.max(a-r,0):0;t.codeElement.style.setProperty("--diffs-column-content-width",`${o>0?`${o}px`:"auto"}`)}}};applyNewHeight(n,t){t!==n.currentHeight&&(n.currentHeight=Math.max(t,0),n.column1.container.style.setProperty("--diffs-annotation-min-height",`${n.currentHeight}px`),n.column2.container.style.setProperty("--diffs-annotation-min-height",`${n.currentHeight}px`))}};function he(e){const n=Math.max(Math.floor(e),0);return n===0?"auto":n}function me(e){return Math.max(Math.ceil(e),0)}function ge(e){e.codeElement.isConnected&&(e.codeElement.style.removeProperty("--diffs-column-content-width"),e.codeElement.style.removeProperty("--diffs-column-number-width"),e.codeElement.style.removeProperty("--diffs-column-width"))}function pe(e){e.column1.container.isConnected&&e.column1.container.style.removeProperty("--diffs-annotation-min-height"),e.column2.container.isConnected&&e.column2.container.style.removeProperty("--diffs-annotation-min-height")}function Re(e){for(const n of Array.isArray(e)?e:[e])if(!(n==="text"||n==="ansi")&&!ne.has(n))return!1;return!0}function He(e){for(const n of G(e))if(!te.has(n))return!1;return!0}function De(e,n){return e==null||n==null?e===n:e.startingLine===n.startingLine&&e.totalLines===n.totalLines&&e.bufferBefore===n.bufferBefore&&e.bufferAfter===n.bufferAfter}function ze(e){return p({tagName:"div",children:[p({tagName:"div",children:e.annotations?.map(n=>p({tagName:"slot",properties:{name:n}})),properties:{"data-annotation-content":""}})],properties:{"data-line-annotation":`${e.hunkIndex},${e.lineIndex}`}})}function be(e){switch(e){case"file":return"diffs-icon-file-code";case"change":return"diffs-icon-symbol-modified";case"new":return"diffs-icon-symbol-added";case"deleted":return"diffs-icon-symbol-deleted";case"rename-pure":case"rename-changed":return"diffs-icon-symbol-moved"}}function Fe({fileOrDiff:e,mode:n,stickyHeader:t}){const i="type"in e?e:void 0,a={"data-diffs-header":n,"data-change-type":i?.type,"data-sticky":t?"":void 0};return p({tagName:"div",children:[n==="custom"?p({tagName:"slot",properties:{name:V}}):ve({name:e.name,prevName:"prevName"in e?e.prevName:void 0,iconType:i?.type??"file"}),...n==="custom"?[]:[xe(i)]],properties:a})}function ve({name:e,prevName:n,iconType:t}){const i=[p({tagName:"slot",properties:{name:Y}}),I({name:be(t),properties:{"data-change-icon":t}})];return n!=null&&(i.push(p({tagName:"div",children:[p({tagName:"bdi",children:[C(n)]})],properties:{"data-prev-name":""}})),i.push(I({name:"diffs-icon-arrow-right-short",properties:{"data-rename-icon":""}}))),i.push(p({tagName:"div",children:[p({tagName:"bdi",children:[C(e)]})],properties:{"data-title":""}})),i.push(p({tagName:"slot",properties:{name:j}})),p({tagName:"div",children:i,properties:{"data-header-content":""}})}function xe(e){const n=[];if(e!=null){let t=0,i=0;for(const a of e.hunks)t+=a.additionLines,i+=a.deletionLines;(i>0||t===0)&&n.push(p({tagName:"span",children:[C(`-${i}`)],properties:{"data-deletions-count":""}})),(t>0||i===0)&&n.push(p({tagName:"span",children:[C(`+${t}`)],properties:{"data-additions-count":""}}))}return n.push(p({tagName:"slot",properties:{name:K}})),p({tagName:"div",children:n,properties:{"data-metadata":""}})}function Oe(e){return p({tagName:"pre",properties:ye(e)})}function ye({diffIndicators:e,disableBackground:n,disableLineNumbers:t,overflow:i,split:a,totalLines:r,type:s,customProperties:l}){return{...l,"data-diff":s==="diff"?"":void 0,"data-file":s==="file"?"":void 0,"data-diff-type":s==="diff"?a?"split":"single":void 0,"data-overflow":i,"data-disable-line-numbers":t?"":void 0,"data-background":n?void 0:"","data-indicators":e==="bars"||e==="classic"?e:void 0,tabIndex:0,style:`--diffs-min-number-column-width-default:${`${r}`.length}ch;`}}function Be(e,{theme:n,preferredHighlighter:t="shiki-js"}){return{langs:[e??"text"],themes:G(n),preferredHighlighter:t}}function $e(e){return`annotation-${"side"in e?`${e.side}-`:""}${e.lineNumber}`}const Ge="-1,-1";function _e(e){return e?.some(n=>n.lineNumber===0)??!1}function qe(e){const n=e[0];return n!=null&&n.length>0?n:void 0}function We(e){return e.startingLine===0&&e.totalLines>0}function Ve(e,n){return p({tagName:"div",children:e,properties:{"data-content":"",style:`grid-row: span ${n}`}})}function Ye(e){return e.useTokenTransformer===!0||e.onTokenClick!=null||e.onTokenEnter!=null||e.onTokenLeave!=null}const je=`<svg data-icon-sprite aria-hidden="true" width="0" height="0">
1
+ import{da as M,dR as V,dS as Y,dT as j,dU as K,es as X,et as J,eu as $,ev as Q,dW as Z}from"./SessionSwitcherDropdown-DROjbyIu.js";import{b as ee,m as p,x as I,A as ne,a as G,y as te,z as C}from"./computeVirtualFileMetrics-C7vXPUYT.js";import{t as ie}from"./vendor-hast-util-to-html-BKBhbTDb.js";function U(e,n,t){if(e===n||e==null||n==null)return e===n;const i=new Set(t),a=Object.keys(e),r=new Set(Object.keys(n));for(const s of a)if(r.delete(s),!i.has(s)&&(!(s in n)||e[s]!==n[s]))return!1;for(const s of Array.from(r))if(!i.has(s))return!1;return!0}function Te(e,n){const t=e?.theme??M,i=n?.theme??M,a=R(e),r=R(n);return ee(t,i)&&U(e,n,["theme","parseDiffOptions"])&&U(a,r)}function R(e){if(e!=null&&"parseDiffOptions"in e)return e.parseDiffOptions}function H(e,n){return e?.start===n?.start&&e?.end===n?.end&&e?.side===n?.side&&e?.endSide===n?.endSide}function ae(){return p({tagName:"button",properties:{"data-utility-button":"",type:"button"},children:[I({name:"diffs-icon-plus",properties:{"data-icon":""}})]})}function re(e,n){return e.lineNumber===n.lineNumber&&e.side===n.side}var Ie=class{mode;options;hoveredLine;hoveredToken;pre;gutterUtilityLine;gutterUtilityContainer;gutterUtilityButton;gutterUtilitySlot;interactiveLinesAttr=!1;interactiveLineNumbersAttr=!1;hasPointerListeners=!1;hasDocumentPointerListeners=!1;selectedRange=null;activeLineHighlightSide;activeLineNumberOnly=!1;editorAttached=!1;proposedSelectedRange;renderedSelectionRange;selectionAnchor;queuedSelectionRender;pointerSession={mode:"idle"};constructor(e,n){this.mode=e,this.options=n}setOptions(e){this.options=e}cleanUp(){this.pre?.removeEventListener("click",this.handlePointerClick),this.pre?.removeEventListener("pointerdown",this.handlePointerDown),this.pre?.removeEventListener("pointermove",this.handlePointerMove),this.pre?.removeEventListener("pointerleave",this.handlePointerLeave),this.pre?.removeAttribute("data-interactive-lines"),this.pre?.removeAttribute("data-interactive-line-numbers"),this.pre=void 0,this.gutterUtilityContainer?.remove(),this.gutterUtilityLine=void 0,this.gutterUtilityContainer=void 0,this.gutterUtilityButton=void 0,this.gutterUtilitySlot=void 0,this.clearHoveredLine(),this.clearHoveredToken(),this.detachDocumentPointerListeners(),this.clearPointerSession(),this.queuedSelectionRender!=null&&(cancelAnimationFrame(this.queuedSelectionRender),this.queuedSelectionRender=void 0),this.interactiveLinesAttr=!1,this.interactiveLineNumbersAttr=!1,this.hasPointerListeners=!1}setup(e){this.setSelectionDirty();const{usesCustomGutterUtility:n=!1,enableGutterUtility:t=!1}=this.options;this.pre!==e&&(this.cleanUp(),this.pre=e),t?this.ensureGutterUtilityNode(n):this.gutterUtilityContainer!=null&&(this.gutterUtilityContainer.remove(),this.gutterUtilityLine=void 0,this.gutterUtilityContainer=void 0,this.gutterUtilityButton=void 0,this.gutterUtilitySlot=void 0,this.pointerSession.mode==="gutterSelecting"&&(this.clearPointerSession(),this.detachDocumentPointerListeners())),this.syncPointerListeners(e),this.updateInteractiveLineAttributes(),this.renderSelection(),this.placeUtility()}setSelectionDirty(){this.renderedSelectionRange=void 0}setEditorAttached(e){this.editorAttached!==e&&(this.editorAttached=e,this.setSelectionDirty(),this.renderSelection())}isSelectionDirty(){return this.renderedSelectionRange===null}setSelection(e,n){const t=!(e===this.selectedRange||H(e??void 0,this.selectedRange??void 0));!this.isSelectionDirty()&&!t||(this.proposedSelectedRange=void 0,this.selectedRange=e,this.activeLineHighlightSide=n?.activeLineSide,this.activeLineNumberOnly=n?.lineNumberOnly??!1,this.renderSelection(),this.placeUtility(),t&&n?.notify!==!1&&this.notifySelectionCommitted())}getSelection(){return this.selectedRange}getHoveredLine=()=>{const e=this.gutterUtilityLine??this.hoveredLine;if(e!=null){if(this.mode==="diff"&&e.type==="diff-line")return{lineNumber:e.lineNumber,side:e.annotationSide};if(this.mode==="file"&&e.type==="line")return{lineNumber:e.lineNumber}}};handlePointerClick=e=>{const{onHunkExpand:n,onLineClick:t,onLineNumberClick:i,onTokenClick:a,onMergeConflictActionClick:r}=this.options;n==null&&t==null&&i==null&&r==null&&a==null||this.options.onGutterUtilityClick!=null&&E(e.composedPath())||(k(this.options.__debugPointerEvents,"click","FileDiff.DEBUG.handlePointerClick:",e),this.handlePointerEvent({eventType:"click",event:e}))};handlePointerMove=e=>{if(e.pointerType!=="mouse")return;const{lineHoverHighlight:n="disabled",onLineEnter:t,onLineLeave:i,onTokenEnter:a,onTokenLeave:r,enableGutterUtility:s=!1}=this.options;n==="disabled"&&!s&&t==null&&i==null&&a==null&&r==null||(k(this.options.__debugPointerEvents,"move","FileDiff.DEBUG.handlePointerMove:",e),this.handlePointerEvent({eventType:"move",event:e}))};handlePointerLeave=e=>{const{__debugPointerEvents:n}=this.options;if(k(n,"move","FileDiff.DEBUG.handlePointerLeave: no event"),this.hoveredLine==null&&this.hoveredToken==null){k(n,"move","FileDiff.DEBUG.handlePointerLeave: returned early, no hovered line or token");return}this.hoveredToken!=null&&(this.options.onTokenLeave?.(this.hoveredToken,e),this.clearHoveredToken()),this.hoveredLine!=null&&(this.options.onLineLeave?.({...this.hoveredLine,event:e}),this.clearHoveredLine()),this.placeUtility()};handlePointerEvent({eventType:e,event:n}){const{__debugPointerEvents:t}=this.options,i=n.composedPath();k(t,e,"FileDiff.DEBUG.handlePointerEvent:",{eventType:e,composedPath:i});const a=this.resolvePointerTarget(i);k(t,e,"FileDiff.DEBUG.handlePointerEvent: resolvePointerTarget result:",a);const{onLineClick:r,onLineNumberClick:s,onLineEnter:l,onLineLeave:o,onTokenClick:d,onTokenEnter:c,onTokenLeave:m,onHunkExpand:h,onMergeConflictActionClick:f}=this.options;switch(e){case"move":{const u=T(a)&&this.hoveredLine?.lineElement===a.lineElement;A(a)&&this.hoveredToken?.tokenElement===a.tokenElement||(this.hoveredToken!=null&&(m?.(this.hoveredToken,n),this.clearHoveredToken()),A(a)&&(this.setHoveredToken(this.toTokenEventBaseProps(a)),c?.(this.hoveredToken,n))),u||(this.hoveredLine!=null&&(o?.({...this.hoveredLine,event:n}),this.clearHoveredLine()),T(a)?(this.setHoveredLine(this.toEventBaseProps(a)),this.placeUtility(),l?.({...this.hoveredLine,event:n})):this.placeUtility());break}case"click":{if(a==null)break;if(de(a)&&f!=null){f(a);break}if(se(a)&&h!=null){h(a.hunkIndex,a.all||n.shiftKey?"both":a.direction,a.all||n.shiftKey?Number.POSITIVE_INFINITY:void 0);break}if(!T(a))break;A(a)&&d!=null&&d(this.toTokenEventBaseProps(a),n);const u=this.toEventBaseProps(a);s!=null&&a.numberColumn?s({...u,event:n}):r?.({...u,event:n});break}}}syncPointerListeners(e){const{__debugPointerEvents:n,lineHoverHighlight:t="disabled",onLineClick:i,onLineNumberClick:a,onLineEnter:r,onLineLeave:s,onTokenClick:l,onTokenEnter:o,onTokenLeave:d,onHunkExpand:c,onMergeConflictActionClick:m,enableGutterUtility:h=!1,enableLineSelection:f=!1,onGutterUtilityClick:u}=this.options,v=u!=null,b=t!=="disabled"||i!=null||a!=null||r!=null||s!=null||l!=null||o!=null||d!=null||c!=null||m!=null||h||f||v;b&&!this.hasPointerListeners?(e.addEventListener("click",this.handlePointerClick),e.addEventListener("pointerdown",this.handlePointerDown),e.addEventListener("pointermove",this.handlePointerMove),e.addEventListener("pointerleave",this.handlePointerLeave),this.hasPointerListeners=!0,k(n,"click","FileDiff.DEBUG.attachEventListeners: Attaching click events for:",(()=>{const x=[];return(n==="both"||n==="click")&&(i!=null&&x.push("onLineClick"),a!=null&&x.push("onLineNumberClick"),c!=null&&x.push("expandable hunk separators"),m!=null&&x.push("merge conflict actions")),x})()),k(n,"move","FileDiff.DEBUG.attachEventListeners: Attaching pointer move event"),k(n,"move","FileDiff.DEBUG.attachEventListeners: Attaching pointer leave event")):!b&&this.hasPointerListeners&&(e.removeEventListener("click",this.handlePointerClick),e.removeEventListener("pointerdown",this.handlePointerDown),e.removeEventListener("pointermove",this.handlePointerMove),e.removeEventListener("pointerleave",this.handlePointerLeave),this.hasPointerListeners=!1);const g=this.pointerSession.mode==="selecting"||this.pointerSession.mode==="pendingSingleLineUnselect",y=this.pointerSession.mode==="gutterSelecting";(!f&&g||!v&&y)&&(this.clearPointerSession(),this.detachDocumentPointerListeners(),this.selectionAnchor=void 0,this.clearPendingSingleLineState())}updateInteractiveLineAttributes(){if(this.pre==null)return;const{onLineClick:e,onLineNumberClick:n,enableLineSelection:t=!1}=this.options,i=e!=null,a=n!=null||t;i&&!this.interactiveLinesAttr?(this.pre.setAttribute("data-interactive-lines",""),this.interactiveLinesAttr=!0):!i&&this.interactiveLinesAttr&&(this.pre.removeAttribute("data-interactive-lines"),this.interactiveLinesAttr=!1),a&&!this.interactiveLineNumbersAttr?(this.pre.setAttribute("data-interactive-line-numbers",""),this.interactiveLineNumbersAttr=!0):!a&&this.interactiveLineNumbersAttr&&(this.pre.removeAttribute("data-interactive-line-numbers"),this.interactiveLineNumbersAttr=!1)}handlePointerDown=e=>{if(e.pointerType==="mouse"&&e.button!==0||this.pre==null||this.pointerSession.mode!=="idle")return;const n=e.composedPath();E(n)&&this.options.onGutterUtilityClick!=null?this.startGutterSelectionFromPointerDown(e):(e.pointerType!=="mouse"&&this.revealUtilityFromGutterPath(n),this.startLineSelectionFromPointerDown(e))};startLineSelectionFromPointerDown(e){const{enableLineSelection:n=!1}=this.options;if(!n)return;const t=this.resolveSelectionInfo(e,{source:"event-path",requireNumberColumn:!0});if(t==null)return;const{pre:i}=this;if(i==null)return;e.preventDefault();const{lineNumber:a,eventSide:r,lineIndex:s}=t;if(e.shiftKey&&this.selectedRange!=null){const l=this.getIndexesFromSelection(this.selectedRange,i.getAttribute("data-diff-type")==="split");if(l==null)return;const o=l.start<=l.end?s>=l.start:s<=l.end;this.selectionAnchor={lineNumber:o?this.selectedRange.start:this.selectedRange.end,side:o?this.selectedRange.side:this.selectedRange.endSide??this.selectedRange.side},this.updateSelection(a,r,!1),this.notifySelectionStart(this.getCurrentSelectionRange()),this.pointerSession={mode:"selecting",pointerId:e.pointerId},this.attachDocumentPointerListeners();return}if(this.selectedRange?.start===a&&this.selectedRange?.end===a){const l={lineNumber:a,side:r};this.selectionAnchor=l,this.pointerSession={mode:"pendingSingleLineUnselect",pointerId:e.pointerId,anchor:l,pending:l},this.attachDocumentPointerListeners();return}this.options.controlledSelection===!0?this.proposedSelectedRange=null:this.selectedRange=null,this.placeUtility(),this.selectionAnchor={lineNumber:a,side:r},this.updateSelection(a,r,!1),this.notifySelectionStart(this.getCurrentSelectionRange()),this.pointerSession={mode:"selecting",pointerId:e.pointerId},this.attachDocumentPointerListeners()}startGutterSelectionFromPointerDown(e){const{enableLineSelection:n=!1,onGutterUtilityClick:t}=this.options;if(t==null)return;const i=this.currentSelectionEnds(),a=i?.bottom??this.resolveSelectionPoint(e,{source:"event-path",excludeUtility:!1}),r=i?.top??a;a==null||r==null||(e.preventDefault(),e.stopPropagation(),this.pointerSession={mode:"gutterSelecting",pointerId:e.pointerId,anchor:r,current:a},n&&(this.selectionAnchor={lineNumber:r.lineNumber,side:r.side},this.updateSelection(a.lineNumber,a.side,!1),this.notifySelectionStart(this.getCurrentSelectionRange())),this.attachDocumentPointerListeners())}handleDocumentPointerMove=e=>{const{enableLineSelection:n=!1}=this.options;switch(this.pointerSession.mode){case"idle":return;case"gutterSelecting":{if(e.pointerId!==this.pointerSession.pointerId)return;e.preventDefault();const t=this.resolveSelectionPoint(e,{source:"coordinates-first"});if(t==null)return;this.pointerSession.current=t,n===!0&&this.updateSelection(t.lineNumber,t.side);return}case"selecting":{if(e.pointerId!==this.pointerSession.pointerId)return;e.preventDefault();const t=this.resolveSelectionInfo(e,{source:"coordinates-first",requireNumberColumn:!1});if(t==null||this.selectionAnchor==null)return;this.updateSelection(t.lineNumber,t.eventSide);return}case"pendingSingleLineUnselect":{if(e.pointerId!==this.pointerSession.pointerId)return;e.preventDefault();const t=this.resolveSelectionInfo(e,{source:"coordinates-first",requireNumberColumn:!1});if(t==null||this.selectionAnchor==null)return;const i={lineNumber:t.lineNumber,side:t.eventSide};if(re(this.pointerSession.pending,i))return;this.updateSelection(t.lineNumber,t.eventSide,!1),this.notifySelectionStart(this.getCurrentSelectionRange()),this.notifySelectionChangeDelta(),this.pointerSession={mode:"selecting",pointerId:e.pointerId};return}}};handleDocumentPointerUp=e=>{const{enableLineSelection:n=!1,onGutterUtilityClick:t}=this.options;switch(this.pointerSession.mode){case"idle":return;case"gutterSelecting":{if(e.pointerId!==this.pointerSession.pointerId)return;e.preventDefault();const i=this.resolveSelectionPoint(e,{source:"coordinates-first"});i!=null&&(this.pointerSession.current=i,n&&this.updateSelection(i.lineNumber,i.side)),t?.(this.buildSelectedLineRange(this.pointerSession.anchor,this.pointerSession.current)),this.selectionAnchor=void 0,n&&(this.notifySelectionEnd(this.getCurrentSelectionRange()),this.notifySelectionCommitted(),this.clearProposedSelection()),this.clearPointerSession(),this.detachDocumentPointerListeners();return}case"pendingSingleLineUnselect":if(e.pointerId!==this.pointerSession.pointerId)return;e.preventDefault(),this.updateSelection(null,void 0,!1),this.selectionAnchor=void 0,this.clearPendingSingleLineState(),this.detachDocumentPointerListeners(),this.notifySelectionEnd(this.getCurrentSelectionRange()),this.notifySelectionCommitted(),this.clearProposedSelection();return;case"selecting":if(e.pointerId!==this.pointerSession.pointerId)return;e.preventDefault(),this.selectionAnchor=void 0,this.detachDocumentPointerListeners(),this.clearPointerSession(),this.notifySelectionEnd(this.getCurrentSelectionRange()),this.notifySelectionCommitted(),this.clearProposedSelection()}};handleDocumentPointerCancel=e=>{switch(this.pointerSession.mode){case"idle":return;case"gutterSelecting":case"selecting":case"pendingSingleLineUnselect":if("pointerId"in this.pointerSession&&e.pointerId!==this.pointerSession.pointerId)return;this.selectionAnchor=void 0,this.clearProposedSelection(),this.clearPendingSingleLineState(),this.clearPointerSession(),this.detachDocumentPointerListeners()}};clearHoveredLine(){this.hoveredLine!=null&&(this.hoveredLine.lineElement.removeAttribute("data-hovered"),this.hoveredLine.numberElement.removeAttribute("data-hovered"),this.hoveredLine=void 0)}setHoveredLine(e){const{lineHoverHighlight:n="disabled"}=this.options;this.hoveredLine!=null&&this.clearHoveredLine(),this.hoveredLine=e,n!=="disabled"&&((n==="both"||n==="line")&&this.hoveredLine.lineElement.setAttribute("data-hovered",""),(n==="both"||n==="number")&&this.hoveredLine.numberElement.setAttribute("data-hovered",""))}clearHoveredToken(){this.hoveredToken!=null&&(this.hoveredToken=void 0)}setHoveredToken(e){this.hoveredToken!=null&&this.clearHoveredToken(),this.hoveredToken=e}ensureGutterUtilityNode(e){if(this.gutterUtilityContainer==null&&(this.gutterUtilityContainer=document.createElement("div"),this.gutterUtilityContainer.setAttribute("data-gutter-utility-slot","")),e)this.gutterUtilityButton!=null&&(this.gutterUtilityButton.remove(),this.gutterUtilityButton=void 0),this.gutterUtilitySlot==null&&(this.gutterUtilitySlot=document.createElement("slot"),this.gutterUtilitySlot.name="gutter-utility-slot"),this.gutterUtilitySlot.parentNode!==this.gutterUtilityContainer&&this.gutterUtilityContainer.replaceChildren(this.gutterUtilitySlot);else{if(this.gutterUtilitySlot?.remove(),this.gutterUtilitySlot=void 0,this.gutterUtilityButton==null){const n=document.createElement("div");n.innerHTML=ie(ae());const t=n.firstElementChild;if(!(t instanceof HTMLButtonElement))throw new Error("InteractionManager.ensureGutterUtilityNode: Node element should be a button");t.remove(),this.gutterUtilityButton=t}this.gutterUtilityButton.parentNode!==this.gutterUtilityContainer&&this.gutterUtilityContainer.replaceChildren(this.gutterUtilityButton)}}revealUtilityFromGutterPath(e){if(this.placeUtilityFromSelection())return;const n=this.resolvePointerTarget(e);w(n)&&n.numberColumn&&this.showUtilityOnLine(this.toEventBaseProps(n))}placeUtility(){if(!this.placeUtilityFromSelection()){if(this.hoveredLine!=null){this.showUtilityOnLine(this.hoveredLine);return}this.hideUtility()}}placeUtilityFromSelection(){const e=this.currentSelectionEnds();if(e==null)return!1;const n=this.targetForSelectionPoint(e.bottom);return n==null?this.hideUtility():this.showUtilityOnLine(this.toEventBaseProps(n)),!0}showUtilityOnLine(e){this.gutterUtilityContainer!=null&&(this.gutterUtilityLine=e,e.numberElement.appendChild(this.gutterUtilityContainer))}hideUtility(){this.gutterUtilityContainer?.remove(),this.gutterUtilityLine=void 0}currentSelectionEnds(){const e=this.getCurrentSelectionRange();return e==null?void 0:this.selectionEnds(e)}selectionEnds(e){const n={lineNumber:e.start,side:e.side},t={lineNumber:e.end,side:e.endSide??e.side},i=this.selectionPointRowIndex(n),a=this.selectionPointRowIndex(t);if(!(i==null||a==null))return i>a?{top:t,bottom:n}:{top:n,bottom:t}}selectionPointRowIndex(e){const n=this.getLineIndex(e.lineNumber,e.side);if(n!=null)return this.isSplitDiff()?n[1]:n[0]}targetForSelectionPoint(e){if(this.pre==null)return;const n=this.getLineIndex(e.lineNumber,e.side);if(n==null)return;const t=this.mode==="diff"?`${n[0]},${n[1]}`:`${n[0]}`,i=this.pre.querySelectorAll(`[data-column-number="${e.lineNumber}"][data-line-index="${t}"]`);for(const a of i){if(!(a instanceof HTMLElement))continue;const r=this.resolvePointerTarget(L(a));if(w(r)&&!(this.mode==="diff"&&e.side!=null&&r.side!==e.side))return r}}attachDocumentPointerListeners(){this.hasDocumentPointerListeners||(document.addEventListener("pointermove",this.handleDocumentPointerMove),document.addEventListener("pointerup",this.handleDocumentPointerUp),document.addEventListener("pointercancel",this.handleDocumentPointerCancel),this.hasDocumentPointerListeners=!0)}detachDocumentPointerListeners(){this.hasDocumentPointerListeners&&(document.removeEventListener("pointermove",this.handleDocumentPointerMove),document.removeEventListener("pointerup",this.handleDocumentPointerUp),document.removeEventListener("pointercancel",this.handleDocumentPointerCancel),this.hasDocumentPointerListeners=!1)}clearPointerSession(){this.pointerSession={mode:"idle"}}clearPendingSingleLineState(){this.pointerSession.mode==="pendingSingleLineUnselect"&&(this.pointerSession={mode:"idle"})}selectionInfoFromPath(e,n){const t=this.resolvePointerTarget(e);if(w(t)&&!(n&&!t.numberColumn)&&t.splitLineIndex!=null)return{lineIndex:t.splitLineIndex,lineNumber:t.lineNumber,eventSide:this.mode==="diff"?t.side:void 0}}resolveSelectionInfo(e,n){const t=this.resolveSelectionPath(e,n);return t!=null?this.selectionInfoFromPath(t,n.requireNumberColumn):void 0}selectionPointFromPath(e){const n=this.resolvePointerTarget(e);if(w(n))return{lineNumber:n.lineNumber,side:this.mode==="diff"?n.side:void 0}}resolveSelectionPoint(e,n){const t=this.resolveSelectionPath(e,n);return t!=null?this.selectionPointFromPath(t):void 0}resolveSelectionPath(e,n){const t=n.excludeUtility!==!1;switch(n.source){case"event-path":return this.pathFromEventPath(e.composedPath(),t);case"coordinates-first":{const i=this.pathFromCoordinates(e,t);return i!==void 0?i??void 0:this.pathFromEventPath(e.composedPath(),t)}}}pathFromCoordinates(e,n){const t=this.hitTest(e);if(t!==void 0)return t===null?null:this.pathFromElement(t,n)??null}pathFromEventPath(e,n){if(!(n&&E(e))){for(const t of e)if(t instanceof Element)return this.pathFromElement(t,n)}}pathFromElement(e,n){const t=L(e);if(n&&E(t))return;const i=fe(e);return i!=null?L(i):this.pathFromAnnotationSlot(e)}pathFromAnnotationSlot(e){const n=ue(ce(e));if(n==null)return;const t=this.targetForSelectionPoint(n);return t!=null?L(t.lineElement):void 0}hitTest(e){if(!Number.isFinite(e.clientX)||!Number.isFinite(e.clientY))return;const n=this.pre?.getRootNode(),t=z(n)?n:z(document)?document:void 0;if(t!=null)return t.elementFromPoint(e.clientX,e.clientY)}getLineIndex(e,n){const{getLineIndex:t}=this.options;return t!=null?t(e,n):[e-1,e-1]}getCurrentSelectionRange(){return this.proposedSelectedRange!==void 0?this.proposedSelectedRange:this.selectedRange}clearProposedSelection(){this.proposedSelectedRange=void 0}updateSelection(e,n,t=!0){const i=this.getCurrentSelectionRange();let a;if(e==null)a=null;else{const r=this.selectionAnchor?.side??n,s=this.selectionAnchor?.lineNumber??e;a=this.buildSelectionRange(s,e,r,n)}H(i??void 0,a??void 0)||(this.activeLineHighlightSide=void 0,this.activeLineNumberOnly=!1,this.options.controlledSelection===!0?this.proposedSelectedRange=a:(this.selectedRange=a,this.queuedSelectionRender??=requestAnimationFrame(this.renderSelection)),this.placeUtility(),t&&this.notifySelectionChangeDelta())}getIndexesFromSelection(e,n){if(this.pre==null)return;const t=this.getLineIndex(e.start,e.side),i=this.getLineIndex(e.end,e.endSide??e.side);return t!=null&&i!=null?{start:n?t[1]:t[0],end:n?i[1]:i[0]}:void 0}highlightLineNumberOnly(){return this.activeLineHighlightSide!=null?this.activeLineNumberOnly:this.activeLineNumberOnly||this.editorAttached}renderSelection=()=>{if(this.queuedSelectionRender!=null&&(cancelAnimationFrame(this.queuedSelectionRender),this.queuedSelectionRender=void 0),this.pre==null||this.renderedSelectionRange===this.selectedRange)return;const e=this.pre.querySelectorAll("[data-selected-line]");for(const o of e)o.removeAttribute("data-selected-line");if(this.renderedSelectionRange=this.selectedRange,this.selectedRange==null)return;const{children:n}=this.pre;if(n.length===0)return;if(n.length>2)throw console.error(n),new Error("InteractionManager.renderSelection: Somehow there are more than 2 code elements...");const t=this.pre.getAttribute("data-diff-type")==="split",i=this.getIndexesFromSelection(this.selectedRange,t);if(i==null)throw console.error({rowRange:i,selectedRange:this.selectedRange}),new Error("InteractionManager.renderSelection: No valid rowRange");const a=i.start===i.end,r=Math.min(i.start,i.end),s=Math.max(i.start,i.end),l=this.highlightLineNumberOnly();for(const o of n){const d=this.activeLineHighlightSide;if(d!=null&&(d==="additions"&&o.hasAttribute("data-deletions")||d==="deletions"&&o.hasAttribute("data-additions")))continue;const[c,m]=o.children,h=m.children.length;if(h!==c.children.length)throw new Error("InteractionManager.renderSelection: gutter and content children dont match, something is wrong");for(let f=0;f<h;f++){const u=m.children[f],v=c.children[f];if(!(u instanceof HTMLElement)||!(v instanceof HTMLElement))continue;const b=this.parseLineIndex(u,t);if((b??0)>s)break;if(b==null||b<r)continue;let g=a?"single":b===r?"first":b===s?"last":"";v.setAttribute("data-selected-line",g),!l&&(u.setAttribute("data-selected-line",g),v.nextSibling instanceof HTMLElement&&u.nextSibling instanceof HTMLElement&&(u.nextSibling.hasAttribute("data-line-annotation")||u.nextSibling.hasAttribute("data-merge-conflict-actions"))&&(a?(g="last",u.setAttribute("data-selected-line","first")):b===r?g="":b===s&&u.setAttribute("data-selected-line",""),u.nextSibling.setAttribute("data-selected-line",g),v.nextSibling.setAttribute("data-selected-line",g)))}}};notifySelectionCommitted(){this.options.onLineSelected?.(this.getCurrentSelectionRange()??null)}notifySelectionChangeDelta(){this.options.onLineSelectionChange?.(this.getCurrentSelectionRange()??null)}notifySelectionStart(e){this.options.onLineSelectionStart?.(e)}notifySelectionEnd(e){this.options.onLineSelectionEnd?.(e)}toEventBaseProps(e){return this.mode==="file"?{type:"line",lineElement:e.lineElement,lineNumber:e.lineNumber,numberColumn:e.numberColumn,numberElement:e.numberElement}:{type:"diff-line",annotationSide:e.side,lineType:e.lineType,lineElement:e.lineElement,numberElement:e.numberElement,lineNumber:e.lineNumber,numberColumn:e.numberColumn}}toTokenEventBaseProps({lineCharEnd:e,lineCharStart:n,lineNumber:t,side:i,tokenElement:a,tokenText:r}){return this.mode==="file"?{type:"token",lineCharEnd:e,lineCharStart:n,lineNumber:t,tokenElement:a,tokenText:r}:{type:"token",lineCharEnd:e,lineCharStart:n,lineNumber:t,side:i,tokenElement:a,tokenText:r}}buildSelectedLineRange(e,n){return this.buildSelectionRange(e.lineNumber,n.lineNumber,e.side,n.side)}buildSelectionRange(e,n,t,i){return{start:e,end:n,...t!=null?{side:t}:{},...t!==i&&i!=null?{endSide:i}:{}}}resolvePointerTarget(e){let n=!1,t,i,a,r,s,l,o,d,c,m;for(const f of e){if(!(f instanceof HTMLElement))continue;if(m==null&&f.hasAttribute("data-merge-conflict-action")){const g=f.getAttribute("data-merge-conflict-action")??void 0,y=f.getAttribute("data-merge-conflict-conflict-index")??void 0,x=y!=null?Number.parseInt(y,10):NaN;le(g)&&Number.isFinite(x)&&(m={kind:"merge-conflict-action",resolution:g,conflictIndex:x})}if(l==null&&f.hasAttribute("data-char")){l=f;const g=f.getAttribute("data-char");if(g!=null){const y=Number.parseInt(g,10);if(!Number.isNaN(y)){const x=f.textContent??"",N=y+x.length;(x.trim()!==""||this.options.enableTokenInteractionsOnWhitespace===!0)&&(o={tokenElement:l,lineCharStart:y,lineCharEnd:N,tokenText:x});continue}}}const u=s==null?f.getAttribute("data-column-number")??void 0:void 0;if(u!=null){s=f,c=Number.parseInt(u,10),n=!0,t=O(f),r=f.getAttribute("data-line-index")??void 0;continue}const v=a==null?f.getAttribute("data-line")??void 0:void 0;if(v!=null){a=f,c=Number.parseInt(v,10),t=O(f),r=f.getAttribute("data-line-index")??void 0;continue}if(d==null&&(f.hasAttribute("data-expand-button")||f.hasAttribute("data-unmodified-lines"))){d={hunkIndex:void 0,direction:f.hasAttribute("data-expand-up")?"up":f.hasAttribute("data-expand-down")?"down":"both",all:f.hasAttribute("data-expand-all-button")};continue}const b=d!=null?f.getAttribute("data-expand-index")??void 0:void 0;if(d!=null&&b!=null){const g=Number.parseInt(b,10);Number.isNaN(g)||(d.hunkIndex=g);continue}if(i==null&&f.hasAttribute("data-code")){i=f;break}}if(m!=null)return m;if(d?.hunkIndex!=null)return{type:"line-info",hunkIndex:d.hunkIndex,direction:d.direction,all:d.all};if(a??=r!=null?D(i,`[data-line][data-line-index="${r}"]`):void 0,s??=r!=null?D(i,`[data-column-number][data-line-index="${r}"]`):void 0,i==null||a==null||s==null||t==null||c==null||Number.isNaN(c))return;const h=this.parseLineIndex(a,this.isSplitDiff());return o!=null?this.mode==="file"?{kind:"token",lineType:t,lineElement:a,lineNumber:c,numberColumn:n,numberElement:s,side:void 0,splitLineIndex:h,...o}:{kind:"token",lineType:t,lineElement:a,lineNumber:c,numberColumn:n,numberElement:s,side:F(t,i),splitLineIndex:h,...o}:this.mode==="file"?{kind:"line",lineType:t,lineElement:a,lineNumber:c,numberColumn:n,numberElement:s,side:void 0,splitLineIndex:h}:{kind:"line",lineType:t,lineElement:a,lineNumber:c,numberColumn:n,numberElement:s,side:F(t,i),splitLineIndex:h}}isSplitDiff(){return this.pre?.getAttribute("data-diff-type")==="split"}parseLineIndex(e,n){const t=(e.getAttribute("data-line-index")??"").split(",").map(i=>Number.parseInt(i,10)).filter(i=>!Number.isNaN(i));if(n&&t.length===2)return t[1];if(!n)return t[0]}};function Me({enableTokenInteractionsOnWhitespace:e,enableGutterUtility:n,lineHoverHighlight:t,onGutterUtilityClick:i,onLineClick:a,onLineEnter:r,onLineLeave:s,onLineNumberClick:l,onTokenClick:o,onTokenEnter:d,onTokenLeave:c,renderGutterUtility:m,__debugPointerEvents:h,enableLineSelection:f,controlledSelection:u,onLineSelected:v,onLineSelectionStart:b,onLineSelectionChange:g,onLineSelectionEnd:y},x,N,W){return{enableTokenInteractionsOnWhitespace:e,enableGutterUtility:oe({enableGutterUtility:n,renderGutterUtility:m,onGutterUtilityClick:i}),usesCustomGutterUtility:m!=null,lineHoverHighlight:t,onGutterUtilityClick:i,onHunkExpand:x,onMergeConflictActionClick:W,onLineClick:a,onLineEnter:r,onLineLeave:s,onLineNumberClick:l,onTokenClick:o,onTokenEnter:d,onTokenLeave:c,__debugPointerEvents:h,enableLineSelection:f,controlledSelection:u,onLineSelected:v,onLineSelectionStart:b,onLineSelectionChange:g,onLineSelectionEnd:y,getLineIndex:N}}function oe({enableGutterUtility:e,renderGutterUtility:n,onGutterUtilityClick:t}){if(t!=null&&n!=null)throw new Error("Cannot use both 'onGutterUtilityClick' and 'renderGutterUtility'. Use only one gutter utility API.");return e??!1}function w(e){return e!=null&&"kind"in e&&e.kind==="line"}function A(e){return e!=null&&"kind"in e&&e.kind==="token"}function T(e){return w(e)||A(e)}function se(e){return"type"in e&&e.type==="line-info"}function de(e){return"kind"in e&&e.kind==="merge-conflict-action"}function le(e){return e==="current"||e==="incoming"||e==="both"}function D(e,n){const t=e?.querySelector(n);return t instanceof HTMLElement?t:void 0}function L(e){const n=[];let t=e;for(;t!=null;)n.push(t),t=t.parentNode;return n}function fe(e){const n=e.closest("[data-line], [data-column-number]");if(n instanceof HTMLElement)return n;const t=e.closest('[data-line-annotation], [data-gutter-buffer="annotation"]');if(!(t instanceof HTMLElement))return;const i=t.previousElementSibling;return i instanceof HTMLElement&&(i.hasAttribute("data-line")||i.hasAttribute("data-column-number"))?i:void 0}function ce(e){const n=e.closest('[slot^="annotation-"]');if(n instanceof HTMLElement)return n.getAttribute("slot")??void 0;if(e instanceof HTMLElement){const t=e.getAttribute("name")??void 0;return t!=null&&t.startsWith("annotation-")?t:void 0}}function ue(e){if(e==null)return;const n=/^annotation-(?:(additions|deletions)-)?(\d+)$/.exec(e);if(n==null)return;const t=Number.parseInt(n[2],10);if(!(!Number.isFinite(t)||t<=0))return{lineNumber:t,side:n[1]}}function z(e){return e!=null&&typeof e.elementFromPoint=="function"}function F(e,n){switch(e){case"change-deletion":return"deletions";case"change-addition":return"additions";default:return n.hasAttribute("data-deletions")?"deletions":"additions"}}function O(e){const n=e.getAttribute("data-line-type");if(n!=null)switch(n){case"change-deletion":case"change-addition":case"context":case"context-expanded":return n;default:return}}function E(e){for(const n of e)if(n instanceof HTMLElement&&(n.hasAttribute("data-utility-button")||n.hasAttribute("data-gutter-utility-slot")||n.getAttribute("slot")==="gutter-utility-slot"||n.getAttribute("name")==="gutter-utility-slot"))return!0;return!1}function k(e="none",n,...t){switch(e){case"none":return;case"both":break;case"click":if(n!=="click")return;break;case"move":if(n!=="move")return;break}console.log(...t)}var Ue=class S{static resizeObserver;static managersByElement=new Map;static getResizeObserver(){const n=S.resizeObserver??new ResizeObserver(S.handleSharedResizeEntries);return S.resizeObserver=n,n}static handleSharedResizeEntries(n){const t=new Map;for(const i of n){const a=S.managersByElement.get(i.target);if(a==null)continue;const r=t.get(a);r==null?t.set(a,[i]):r.push(i)}for(const[i,a]of t)i.handleResizeEntries(a)}observedNodes=new Map;setup(n,t){const i=new Set;let a=0;const r=new Map(this.observedNodes);this.observedNodes.clear();for(const s of n.children){if(a===2)break;const l=(()=>{if(s instanceof HTMLElement&&s.tagName==="CODE")return s})();if(l==null)continue;a++;let o=r.get(l);if(o!=null&&o.type!=="code")throw new Error("ResizeManager.setup: somehow a code node is being used for an annotation, should be impossible");let d=l.firstElementChild;d instanceof HTMLElement||(d=null),o!=null?(this.observedNodes.set(l,o),r.delete(l),o.numberElement!==d?(o.numberElement!=null&&(this.unobserve(o.numberElement),r.delete(o.numberElement)),d!=null&&(this.observe(d),r.delete(d),this.observedNodes.set(d,o)),o.numberElement=d,o.numberWidth=0):o.numberElement!=null?(r.delete(o.numberElement),this.observedNodes.set(o.numberElement,o)):o.numberWidth=0):(o={type:"code",codeElement:l,numberElement:d,codeWidth:"auto",numberWidth:0},this.observedNodes.set(l,o),this.observe(l),d!=null&&(this.observedNodes.set(d,o),this.observe(d)))}if(a>1&&!t){const s=n.querySelectorAll('[data-line-annotation*=","]'),l=new Map;for(const o of s){if(!(o instanceof HTMLElement))continue;const d=o.getAttribute("data-line-annotation")??"";if(!/^-?\d+,-?\d+$/.test(d)){console.error("DiffFileRenderer.setupResizeObserver: Invalid element or annotation",{lineAnnotation:d,element:o});continue}let c=l.get(d);c==null&&(c=[],l.set(d,c)),c.push(o)}for(const[o,d]of l){if(d.length!==2){console.error("DiffFileRenderer.setupResizeObserver: Bad Pair",o,d);continue}const[c,m]=d,h=c.firstElementChild,f=m.firstElementChild;if(!(c instanceof HTMLElement)||!(m instanceof HTMLElement)||!(h instanceof HTMLElement)||!(f instanceof HTMLElement))continue;let u=r.get(h);if(u!=null){this.observedNodes.set(h,u),this.observedNodes.set(f,u),r.delete(h),r.delete(f);continue}const v=h.getBoundingClientRect().height,b=f.getBoundingClientRect().height;u={type:"annotations",column1:{container:c,child:h,childHeight:v},column2:{container:m,child:f,childHeight:b},currentHeight:"auto"},i.add({child1:h,child2:f,item:u,newHeight:Math.max(v,b)})}for(const o of i)this.applyNewHeight(o.item,o.newHeight),this.observedNodes.set(o.child1,o.item),this.observedNodes.set(o.child2,o.item),this.observe(o.child1),this.observe(o.child2);i.clear()}for(const[s,l]of r)this.unobserve(s),l.type==="code"?ge(l):pe(l);r.clear()}cleanUp(){for(const n of this.observedNodes.keys())this.unobserve(n);this.observedNodes.clear()}observe(n){const{managersByElement:t}=S,i=t.get(n);if(i!==this){if(i!=null&&i!==this)throw new Error("ResizeManager.observe: element is already owned by another ResizeManager");t.set(n,this),S.getResizeObserver().observe(n)}}unobserve(n){const{managersByElement:t,resizeObserver:i}=S,a=t.get(n);if(a!=null){if(a!==this)throw new Error("ResizeManager.unobserve: element is owned by another ResizeManager");t.delete(n),i?.unobserve(n),i!=null&&t.size===0&&(i.disconnect(),S.resizeObserver=void 0)}}handleResizeEntries(n){const t=new Map,i=new Set;for(const a of n){const{target:r,borderBoxSize:s,contentBoxSize:l}=a;if(!(r instanceof HTMLElement)){console.error("ResizeManager.handleResizeEntries: Invalid element for ResizeObserver",a);continue}const o=this.observedNodes.get(r);if(o==null){console.error("ResizeManager.handleResizeEntries: Not a valid observed node",a);continue}if(o.type==="annotations"){const d=(()=>{if(r===o.column1.child)return o.column1;if(r===o.column2.child)return o.column2})();if(d==null){console.error("ResizeManager.handleResizeEntries: Couldn't find a column for",{item:o,target:r});continue}d.childHeight=s[0].blockSize,i.add(o)}else if(o.type==="code"){const d=t.get(o)??{},c=l[0].inlineSize;r===o.codeElement?d.codeInlineSize=c:r===o.numberElement&&(d.numberInlineSize=c),t.set(o,d)}}this.applyAnnotationUpdates(i),i.clear(),this.applyColumnUpdates(t),t.clear()}applyAnnotationUpdates(n){for(const t of n)this.applyNewHeight(t,Math.max(t.column1.childHeight,t.column2.childHeight))}applyColumnUpdates=n=>{for(const[t,i]of n){const a=i.codeInlineSize!=null?he(i.codeInlineSize):t.codeWidth,r=i.numberInlineSize!=null?me(i.numberInlineSize):t.numberWidth,s=a!==t.codeWidth,l=r!==t.numberWidth;if(!(!s&&!l)&&(t.codeWidth=a,t.numberWidth=r,s&&t.codeElement.style.setProperty("--diffs-column-width",`${typeof a=="number"?`${a}px`:"auto"}`),l&&t.codeElement.style.setProperty("--diffs-column-number-width",`${r===0?"auto":`${r}px`}`),s||l&&a!=="auto")){const o=typeof a=="number"?Math.max(a-r,0):0;t.codeElement.style.setProperty("--diffs-column-content-width",`${o>0?`${o}px`:"auto"}`)}}};applyNewHeight(n,t){t!==n.currentHeight&&(n.currentHeight=Math.max(t,0),n.column1.container.style.setProperty("--diffs-annotation-min-height",`${n.currentHeight}px`),n.column2.container.style.setProperty("--diffs-annotation-min-height",`${n.currentHeight}px`))}};function he(e){const n=Math.max(Math.floor(e),0);return n===0?"auto":n}function me(e){return Math.max(Math.ceil(e),0)}function ge(e){e.codeElement.isConnected&&(e.codeElement.style.removeProperty("--diffs-column-content-width"),e.codeElement.style.removeProperty("--diffs-column-number-width"),e.codeElement.style.removeProperty("--diffs-column-width"))}function pe(e){e.column1.container.isConnected&&e.column1.container.style.removeProperty("--diffs-annotation-min-height"),e.column2.container.isConnected&&e.column2.container.style.removeProperty("--diffs-annotation-min-height")}function Re(e){for(const n of Array.isArray(e)?e:[e])if(!(n==="text"||n==="ansi")&&!ne.has(n))return!1;return!0}function He(e){for(const n of G(e))if(!te.has(n))return!1;return!0}function De(e,n){return e==null||n==null?e===n:e.startingLine===n.startingLine&&e.totalLines===n.totalLines&&e.bufferBefore===n.bufferBefore&&e.bufferAfter===n.bufferAfter}function ze(e){return p({tagName:"div",children:[p({tagName:"div",children:e.annotations?.map(n=>p({tagName:"slot",properties:{name:n}})),properties:{"data-annotation-content":""}})],properties:{"data-line-annotation":`${e.hunkIndex},${e.lineIndex}`}})}function be(e){switch(e){case"file":return"diffs-icon-file-code";case"change":return"diffs-icon-symbol-modified";case"new":return"diffs-icon-symbol-added";case"deleted":return"diffs-icon-symbol-deleted";case"rename-pure":case"rename-changed":return"diffs-icon-symbol-moved"}}function Fe({fileOrDiff:e,mode:n,stickyHeader:t}){const i="type"in e?e:void 0,a={"data-diffs-header":n,"data-change-type":i?.type,"data-sticky":t?"":void 0};return p({tagName:"div",children:[n==="custom"?p({tagName:"slot",properties:{name:V}}):ve({name:e.name,prevName:"prevName"in e?e.prevName:void 0,iconType:i?.type??"file"}),...n==="custom"?[]:[xe(i)]],properties:a})}function ve({name:e,prevName:n,iconType:t}){const i=[p({tagName:"slot",properties:{name:Y}}),I({name:be(t),properties:{"data-change-icon":t}})];return n!=null&&(i.push(p({tagName:"div",children:[p({tagName:"bdi",children:[C(n)]})],properties:{"data-prev-name":""}})),i.push(I({name:"diffs-icon-arrow-right-short",properties:{"data-rename-icon":""}}))),i.push(p({tagName:"div",children:[p({tagName:"bdi",children:[C(e)]})],properties:{"data-title":""}})),i.push(p({tagName:"slot",properties:{name:j}})),p({tagName:"div",children:i,properties:{"data-header-content":""}})}function xe(e){const n=[];if(e!=null){let t=0,i=0;for(const a of e.hunks)t+=a.additionLines,i+=a.deletionLines;(i>0||t===0)&&n.push(p({tagName:"span",children:[C(`-${i}`)],properties:{"data-deletions-count":""}})),(t>0||i===0)&&n.push(p({tagName:"span",children:[C(`+${t}`)],properties:{"data-additions-count":""}}))}return n.push(p({tagName:"slot",properties:{name:K}})),p({tagName:"div",children:n,properties:{"data-metadata":""}})}function Oe(e){return p({tagName:"pre",properties:ye(e)})}function ye({diffIndicators:e,disableBackground:n,disableLineNumbers:t,overflow:i,split:a,totalLines:r,type:s,customProperties:l}){return{...l,"data-diff":s==="diff"?"":void 0,"data-file":s==="file"?"":void 0,"data-diff-type":s==="diff"?a?"split":"single":void 0,"data-overflow":i,"data-disable-line-numbers":t?"":void 0,"data-background":n?void 0:"","data-indicators":e==="bars"||e==="classic"?e:void 0,tabIndex:0,style:`--diffs-min-number-column-width-default:${`${r}`.length}ch;`}}function Be(e,{theme:n,preferredHighlighter:t="shiki-js"}){return{langs:[e??"text"],themes:G(n),preferredHighlighter:t}}function $e(e){return`annotation-${"side"in e?`${e.side}-`:""}${e.lineNumber}`}const Ge="-1,-1";function _e(e){return e?.some(n=>n.lineNumber===0)??!1}function qe(e){const n=e[0];return n!=null&&n.length>0?n:void 0}function We(e){return e.startingLine===0&&e.totalLines>0}function Ve(e,n){return p({tagName:"div",children:e,properties:{"data-content":"",style:`grid-row: span ${n}`}})}function Ye(e){return e.useTokenTransformer===!0||e.onTokenClick!=null||e.onTokenEnter!=null||e.onTokenLeave!=null}const je=`<svg data-icon-sprite aria-hidden="true" width="0" height="0">
2
2
  <symbol id="diffs-icon-arrow-right-short" viewBox="0 0 16 16">
3
3
  <path d="M8.47 4.22a.75.75 0 0 0 0 1.06l1.97 1.97H3.75a.75.75 0 0 0 0 1.5h6.69l-1.97 1.97a.75.75 0 1 0 1.06 1.06l3.25-3.25a.75.75 0 0 0 0-1.06L9.53 4.22a.75.75 0 0 0-1.06 0"/>
4
4
  </symbol>
@@ -1387,4 +1387,4 @@ import{df as M,ef as V,eg as Y,eh as j,ei as K,ej as X,ek as J,el as $,em as Q,e
1387
1387
  ${_(t)}
1388
1388
  ${e}
1389
1389
  }
1390
- }`}function nn(e,n){const t=_(n);return e.replace(Le,t)}function Ee(e){return e.replace(/[.*+?^${}()|[\]\\]/g,"\\$&")}function tn({code:e,pre:n,columnType:t,rowSpan:i,containerSize:a=!1}={}){return e==null&&(e=document.createElement("code"),e.setAttribute("data-code",""),t!=null&&e.setAttribute(`data-${t}`,""),n?.appendChild(e)),i!=null?e.style.setProperty("grid-row",`span ${i}`):e.style.removeProperty("grid-row"),a?e.setAttribute("data-container-size",""):e.removeAttribute("data-container-size"),e}function an(e,n){if(n==null)return;const t=e.shadowRoot??e.attachShadow({mode:"open"});t.innerHTML===""&&(t.innerHTML=n)}function rn(e,{type:n,diffIndicators:t,disableBackground:i,disableLineNumbers:a,overflow:r,split:s,totalLines:l,customProperties:o}){if(o!=null)for(const d in o){const c=o[d];c!=null&&e.setAttribute(d,`${c}`)}switch(n==="diff"?(e.setAttribute("data-diff",""),e.removeAttribute("data-file")):(e.setAttribute("data-file",""),e.removeAttribute("data-diff")),t){case"bars":case"classic":e.setAttribute("data-indicators",t);break;case"none":e.removeAttribute("data-indicators");break}return a?e.setAttribute("data-disable-line-numbers",""):e.removeAttribute("data-disable-line-numbers"),i?e.removeAttribute("data-background"):e.setAttribute("data-background",""),n==="diff"?e.setAttribute("data-diff-type",s?"split":"single"):e.removeAttribute("data-diff-type"),e.setAttribute("data-overflow",r),e.tabIndex=0,e.style.setProperty("--diffs-min-number-column-width-default",`${`${l}`.length}ch`),e}function on(e){if(typeof HTMLStyleElement<"u"&&e instanceof HTMLStyleElement)return!0;const n=e.tagName??e.nodeName;return typeof n=="string"&&n.toLowerCase()==="style"}function sn({shadowRoot:e,currentNode:n,themeCSS:t}){if(t.trim()===""){n?.remove();return}return n??=Pe(),n.textContent=t,n.parentNode!==e&&e.appendChild(n),n}function Pe(){const e=document.createElement("style");return e.setAttribute(Q,""),e}if(typeof HTMLElement<"u"&&customElements.get("diffs-container")==null){let e;class n extends HTMLElement{constructor(){if(super(),this.shadowRoot!=null)return;const i=this.attachShadow({mode:"open"});e==null&&(e=new CSSStyleSheet,e.replaceSync(Se)),i.adoptedStyleSheets=[e]}connectedCallback(){we(this.shadowRoot??this.attachShadow({mode:"open"}))}}customElements.define(Z,n)}export{en as A,U as B,_e as C,Ge as F,Ie as I,Ue as R,je as S,Te as a,He as b,ze as c,De as d,Re as e,Oe as f,Be as g,Ve as h,We as i,qe as j,$e as k,Fe as l,an as m,Xe as n,Je as o,Me as p,on as q,Qe as r,Ye as s,we as t,sn as u,nn as v,Ze as w,tn as x,Ke as y,rn as z};
1390
+ }`}function nn(e,n){const t=_(n);return e.replace(Le,t)}function Ee(e){return e.replace(/[.*+?^${}()|[\]\\]/g,"\\$&")}function tn({code:e,pre:n,columnType:t,rowSpan:i,containerSize:a=!1}={}){return e==null&&(e=document.createElement("code"),e.setAttribute("data-code",""),t!=null&&e.setAttribute(`data-${t}`,""),n?.appendChild(e)),i!=null?e.style.setProperty("grid-row",`span ${i}`):e.style.removeProperty("grid-row"),a?e.setAttribute("data-container-size",""):e.removeAttribute("data-container-size"),e}function an(e,n){if(n==null)return;const t=e.shadowRoot??e.attachShadow({mode:"open"});t.innerHTML===""&&(t.innerHTML=n)}function rn(e,{type:n,diffIndicators:t,disableBackground:i,disableLineNumbers:a,overflow:r,split:s,totalLines:l,customProperties:o}){if(o!=null)for(const d in o){const c=o[d];c!=null&&e.setAttribute(d,`${c}`)}switch(n==="diff"?(e.setAttribute("data-diff",""),e.removeAttribute("data-file")):(e.setAttribute("data-file",""),e.removeAttribute("data-diff")),t){case"bars":case"classic":e.setAttribute("data-indicators",t);break;case"none":e.removeAttribute("data-indicators");break}return a?e.setAttribute("data-disable-line-numbers",""):e.removeAttribute("data-disable-line-numbers"),i?e.removeAttribute("data-background"):e.setAttribute("data-background",""),n==="diff"?e.setAttribute("data-diff-type",s?"split":"single"):e.removeAttribute("data-diff-type"),e.setAttribute("data-overflow",r),e.tabIndex=0,e.style.setProperty("--diffs-min-number-column-width-default",`${`${l}`.length}ch`),e}function on(e){if(typeof HTMLStyleElement<"u"&&e instanceof HTMLStyleElement)return!0;const n=e.tagName??e.nodeName;return typeof n=="string"&&n.toLowerCase()==="style"}function sn({shadowRoot:e,currentNode:n,themeCSS:t}){if(t.trim()===""){n?.remove();return}return n??=Pe(),n.textContent=t,n.parentNode!==e&&e.appendChild(n),n}function Pe(){const e=document.createElement("style");return e.setAttribute(Q,""),e}if(typeof HTMLElement<"u"&&customElements.get("diffs-container")==null){let e;class n extends HTMLElement{constructor(){if(super(),this.shadowRoot!=null)return;const i=this.attachShadow({mode:"open"});e==null&&(e=new CSSStyleSheet,e.replaceSync(Se)),i.adoptedStyleSheets=[e]}connectedCallback(){we(this.shadowRoot??this.attachShadow({mode:"open"}))}}customElements.define(Z,n)}export{U as A,Te as B,_e as C,Ge as F,Ie as I,Ue as R,je as S,He as a,De as b,Re as c,We as d,ze as e,$e as f,qe as g,Fe as h,Ve as i,Be as j,Oe as k,an as l,Xe as m,Je as n,Qe as o,Me as p,we as q,en as r,Ye as s,nn as t,sn as u,tn as v,Ze as w,on as x,Ke as y,rn as z};
package/dist/index.html CHANGED
@@ -540,15 +540,15 @@
540
540
  }
541
541
  }
542
542
  </style>
543
- <script type="module" crossorigin src="/assets/main-BsszlAdQ.js"></script>
543
+ <script type="module" crossorigin src="/assets/main-BVWtJYSk.js"></script>
544
544
  <link rel="modulepreload" crossorigin href="/assets/vendor-vite-runtime-DD1OZmLC.js">
545
545
  <link rel="modulepreload" crossorigin href="/assets/vendor-scheduler-7OC5HNn7.js">
546
546
  <link rel="modulepreload" crossorigin href="/assets/vendor-react-DYyjh7Q0.js">
547
547
  <link rel="modulepreload" crossorigin href="/assets/vendor-zustand-CnsBKjP5.js">
548
- <link rel="modulepreload" crossorigin href="/assets/index-DEYblXCW.js">
549
- <link rel="modulepreload" crossorigin href="/assets/runtimeSurface-9aJdtQbh.js">
548
+ <link rel="modulepreload" crossorigin href="/assets/index-BAqpUCjs.js">
549
+ <link rel="modulepreload" crossorigin href="/assets/runtimeSurface-CkHYYg0E.js">
550
550
  <link rel="modulepreload" crossorigin href="/assets/vendor-katex-CHD9BdDO.js">
551
- <link rel="stylesheet" crossorigin href="/assets/index-DLKBsLKY.css">
551
+ <link rel="stylesheet" crossorigin href="/assets/index-riABQmQ_.css">
552
552
  <link rel="stylesheet" crossorigin href="/assets/vendor-katex-Cp579UoJ.css">
553
553
  </head>
554
554
  <body class="h-full bg-background text-foreground">
@@ -89,14 +89,14 @@
89
89
  }
90
90
  </style>
91
91
 
92
- <script type="module" crossorigin src="/assets/miniChat-C6SDQL4G.js"></script>
92
+ <script type="module" crossorigin src="/assets/miniChat-BrbRq5NQ.js"></script>
93
93
  <link rel="modulepreload" crossorigin href="/assets/vendor-vite-runtime-DD1OZmLC.js">
94
94
  <link rel="modulepreload" crossorigin href="/assets/vendor-scheduler-7OC5HNn7.js">
95
95
  <link rel="modulepreload" crossorigin href="/assets/vendor-react-DYyjh7Q0.js">
96
96
  <link rel="modulepreload" crossorigin href="/assets/vendor-zustand-CnsBKjP5.js">
97
- <link rel="modulepreload" crossorigin href="/assets/index-DEYblXCW.js">
97
+ <link rel="modulepreload" crossorigin href="/assets/index-BAqpUCjs.js">
98
98
  <link rel="modulepreload" crossorigin href="/assets/vendor-katex-CHD9BdDO.js">
99
- <link rel="stylesheet" crossorigin href="/assets/index-DLKBsLKY.css">
99
+ <link rel="stylesheet" crossorigin href="/assets/index-riABQmQ_.css">
100
100
  <link rel="stylesheet" crossorigin href="/assets/vendor-katex-Cp579UoJ.css">
101
101
  </head>
102
102
  <body class="h-full bg-background text-foreground">
package/dist/mobile.html CHANGED
@@ -63,14 +63,14 @@
63
63
  })();
64
64
  </script>
65
65
 
66
- <script type="module" crossorigin src="/assets/mobile-DBW3XDmZ.js"></script>
66
+ <script type="module" crossorigin src="/assets/mobile-DTPtCn5N.js"></script>
67
67
  <link rel="modulepreload" crossorigin href="/assets/vendor-vite-runtime-DD1OZmLC.js">
68
68
  <link rel="modulepreload" crossorigin href="/assets/vendor-scheduler-7OC5HNn7.js">
69
69
  <link rel="modulepreload" crossorigin href="/assets/vendor-react-DYyjh7Q0.js">
70
70
  <link rel="modulepreload" crossorigin href="/assets/vendor-zustand-CnsBKjP5.js">
71
- <link rel="modulepreload" crossorigin href="/assets/index-DEYblXCW.js">
71
+ <link rel="modulepreload" crossorigin href="/assets/index-BAqpUCjs.js">
72
72
  <link rel="modulepreload" crossorigin href="/assets/vendor-katex-CHD9BdDO.js">
73
- <link rel="stylesheet" crossorigin href="/assets/index-DLKBsLKY.css">
73
+ <link rel="stylesheet" crossorigin href="/assets/index-riABQmQ_.css">
74
74
  <link rel="stylesheet" crossorigin href="/assets/vendor-katex-Cp579UoJ.css">
75
75
  </head>
76
76
  <body class="h-full bg-background text-foreground">
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@pi-chamber/web",
3
- "version": "0.3.0",
3
+ "version": "0.3.2",
4
4
  "private": false,
5
5
  "type": "module",
6
6
  "repository": {
package/server/index.js CHANGED
@@ -10,6 +10,7 @@ import { fileURLToPath } from 'node:url';
10
10
  import { createClientPairingRuntime } from './lib/client-auth/pairing.js';
11
11
  import { createRemoteClientAuthRuntime } from './lib/client-auth/remote-clients.js';
12
12
  import { resolvePiChamberDataDir } from './lib/pichamber-data-dir.js';
13
+ import { createTunnelService } from './lib/server/tunnel-service.js';
13
14
  import { registerPiRuntimeRoutes } from './lib/pi/routes.js';
14
15
  import { registerWorkspaceIntegrations } from './lib/workspace/host.js';
15
16
  import { createPiSessionDaemonSupervisor } from './lib/pi/session-daemon/supervisor.js';
@@ -114,6 +115,15 @@ export async function startWebUiServer(options = {}) {
114
115
  const tunnelAuthController = createTunnelAuth();
115
116
  const uiAuthController = createUiAuth({ password: uiPassword, readSettingsFromDiskMigrated: async () => ({}) , clientAuthController: remoteClientAuthRuntime });
116
117
  const piSessionDaemonRuntime = createPiSessionDaemonSupervisor({ dataDir: PICHAMBER_DATA_DIR });
118
+ const tunnelService = createTunnelService({
119
+ dataDir: PICHAMBER_DATA_DIR,
120
+ getPort: () => {
121
+ const address = server.address();
122
+ return typeof address === 'object' && address ? address.port : null;
123
+ },
124
+ tunnelAuthController,
125
+ getServerLabel: () => os.hostname() || 'PiChamber',
126
+ });
117
127
  let stopped = false;
118
128
 
119
129
  app.set('trust proxy', true);
@@ -157,6 +167,29 @@ export async function startWebUiServer(options = {}) {
157
167
  getServerLabel: () => os.hostname() || 'PiChamber',
158
168
  });
159
169
  registerPiRuntimeRoutes(app, { getPiSessionDaemonRuntime: () => piSessionDaemonRuntime });
170
+ // Cloudflare Tunnel external access (manual token + quick modes).
171
+ const requireTunnelAuth = (req, res, next) => uiAuthController.requireAuth(req, res, next);
172
+ app.get('/api/pichamber/tunnel/status', requireTunnelAuth, async (_req, res) => {
173
+ try { res.json(await tunnelService.getStatus()); } catch (error) { res.status(500).json({ error: error?.message || 'Failed to get tunnel status' }); }
174
+ });
175
+ app.get('/api/pichamber/tunnel/check', requireTunnelAuth, async (req, res) => {
176
+ try { res.json(await tunnelService.check(req.query?.provider)); } catch (error) { res.status(500).json({ error: error?.message || 'Tunnel check failed' }); }
177
+ });
178
+ app.get('/api/pichamber/tunnel/providers', requireTunnelAuth, async (_req, res) => {
179
+ res.json({ providers: [{ provider: 'cloudflare', modes: [{ key: 'quick' }, { key: 'managed-remote' }, { key: 'managed-local' }] }] });
180
+ });
181
+ app.post('/api/pichamber/tunnel/start', express.json({ limit: '64kb' }), requireTunnelAuth, async (req, res) => {
182
+ try { const result = await tunnelService.start(req.body ?? {}); res.json(result); } catch (error) { const code = error?.code === 'missing_dependency' ? 400 : error?.code === 'validation_error' ? 422 : 500; res.status(code).json({ ok: false, error: error?.message || 'Failed to start tunnel', code: error?.code }); }
183
+ });
184
+ app.post('/api/pichamber/tunnel/stop', requireTunnelAuth, async (_req, res) => {
185
+ try { res.json(await tunnelService.stop()); } catch (error) { res.status(500).json({ error: error?.message || 'Failed to stop tunnel' }); }
186
+ });
187
+ app.put('/api/pichamber/tunnel/managed-remote-token', express.json({ limit: '64kb' }), requireTunnelAuth, async (req, res) => {
188
+ try { res.json(await tunnelService.saveManagedRemoteToken(req.body ?? {})); } catch (error) { const code = error?.code === 'validation_error' ? 400 : 500; res.status(code).json({ ok: false, error: error?.message || 'Failed to save token' }); }
189
+ });
190
+ app.get('/api/pichamber/tunnel/doctor', requireTunnelAuth, async (req, res) => {
191
+ try { const status = await tunnelService.getStatus(); const checkResult = await tunnelService.check(); res.json({ ok: true, status, check: checkResult, query: req.query }); } catch (error) { res.status(500).json({ ok: false, error: error?.message || 'Doctor failed' }); }
192
+ });
160
193
  registerWorkspaceIntegrations({ app, server, express, uiAuthController });
161
194
  registerStaticRoutes(app, { apiOnly });
162
195
 
@@ -135,6 +135,15 @@ const projectUsage = (raw) => {
135
135
  };
136
136
  };
137
137
 
138
+ const projectRetryInfo = (value) => {
139
+ if (!value || typeof value !== 'object') return null;
140
+ return {
141
+ ...(Number.isSafeInteger(value.attempt) && value.attempt > 0 ? { attempt: value.attempt } : {}),
142
+ ...(Number.isFinite(value.next) && value.next >= 0 ? { next: value.next } : {}),
143
+ ...(typeof value.message === 'string' ? { message: value.message } : {}),
144
+ };
145
+ };
146
+
138
147
  const sanitizeNavigation = (value) => {
139
148
  if (!value || typeof value !== 'object' || typeof value.targetEntryId !== 'string' || value.targetEntryId.length === 0) return null;
140
149
  const previousLeafId = value.previousLeafId === null ? null : (typeof value.previousLeafId === 'string' ? value.previousLeafId : null);
@@ -202,12 +211,16 @@ const projectSessionDetail = (value) => {
202
211
  const lifecycle = ['idle', 'busy', 'retry', 'error', 'interrupted'].includes(value.lifecycle)
203
212
  ? value.lifecycle
204
213
  : (isStreaming ? 'busy' : 'idle');
214
+ const retry = lifecycle === 'retry' ? projectRetryInfo(value.retry) : null;
205
215
  return {
206
216
  session: projectSession(value.session),
207
217
  messages,
208
218
  lastSequence: value.lastSequence,
209
219
  isStreaming,
210
220
  lifecycle,
221
+ ...(retry ? { retry } : {}),
222
+ ...(Number.isFinite(value.runStartedAt) ? { runStartedAt: Math.floor(value.runStartedAt) } : {}),
223
+ ...(Number.isFinite(value.serverNow) ? { serverNow: Math.floor(value.serverNow) } : {}),
211
224
  };
212
225
  };
213
226
 
@@ -358,18 +371,26 @@ const projectEventFrame = (frame) => {
358
371
  switch (frame.event) {
359
372
  case 'session.snapshot': {
360
373
  const snapshot = frame.payload;
374
+ const lifecycle = ['idle', 'busy', 'retry', 'error', 'interrupted'].includes(snapshot.lifecycle) ? snapshot.lifecycle : 'idle';
375
+ const retry = lifecycle === 'retry' ? projectRetryInfo(snapshot.retry) : null;
361
376
  return { ...common, payload: { snapshot: {
362
377
  sessionId, directory, isStreaming: snapshot.isStreaming === true,
363
- lifecycle: ['idle', 'busy', 'retry', 'error', 'interrupted'].includes(snapshot.lifecycle) ? snapshot.lifecycle : 'idle',
378
+ lifecycle,
379
+ ...(retry ? { retry } : {}),
364
380
  queue: { steering: Number.isSafeInteger(snapshot.queue?.steering) ? snapshot.queue.steering : 0, followUp: Number.isSafeInteger(snapshot.queue?.followUp) ? snapshot.queue.followUp : 0 },
365
381
  ...(snapshot.model && typeof snapshot.model.providerId === 'string' && typeof snapshot.model.modelId === 'string' ? { model: { providerId: snapshot.model.providerId, modelId: snapshot.model.modelId } } : {}),
366
382
  ...(typeof snapshot.thinking === 'string' ? { thinking: snapshot.thinking } : {}),
367
383
  ...(typeof snapshot.lastText === 'string' ? { lastText: snapshot.lastText } : {}),
368
384
  ...(typeof snapshot.lastThinking === 'string' ? { lastThinking: snapshot.lastThinking } : {}),
385
+ ...(Number.isFinite(snapshot.runStartedAt) ? { runStartedAt: Math.floor(snapshot.runStartedAt) } : {}),
386
+ ...(Number.isFinite(snapshot.serverNow) ? { serverNow: Math.floor(snapshot.serverNow) } : {}),
369
387
  lastSequence: Number.isSafeInteger(snapshot.lastSequence) ? snapshot.lastSequence : frame.sequence,
370
388
  } } };
371
389
  }
372
- case 'session.lifecycle': return { ...common, payload: { state: frame.payload.state } };
390
+ case 'session.lifecycle': {
391
+ const retry = frame.payload.state === 'retry' ? projectRetryInfo(frame.payload) : null;
392
+ return { ...common, payload: { state: frame.payload.state, ...(retry ?? {}), ...(Number.isFinite(frame.payload.runStartedAt) ? { runStartedAt: Math.floor(frame.payload.runStartedAt) } : {}), ...(Number.isFinite(frame.payload.serverNow) ? { serverNow: Math.floor(frame.payload.serverNow) } : {}) } };
393
+ }
373
394
  case 'session.updated': {
374
395
  if (typeof frame.payload.title !== 'string') return null;
375
396
  const title = frame.payload.title.trim();
@@ -386,6 +407,7 @@ const projectEventFrame = (frame) => {
386
407
  ...(typeof frame.payload.text === 'string' ? { text: frame.payload.text } : {}),
387
408
  ...(typeof frame.payload.thinking === 'string' ? { thinking: frame.payload.thinking } : {}),
388
409
  ...(Number.isFinite(frame.payload.durationMs) ? { durationMs: frame.payload.durationMs } : {}),
410
+ ...(frame.payload.continuing === true ? { continuing: true } : {}),
389
411
  ...(frame.payload.error && typeof frame.payload.error.code === 'string'
390
412
  ? {
391
413
  error: {
@@ -443,6 +443,9 @@ describe('Pi runtime route', () => {
443
443
  parts: [{ type: 'text', id: 'entry-1:0', index: 0, text: 'hello', privatePath: '/private' }],
444
444
  }],
445
445
  lastSequence: 9,
446
+ isStreaming: true,
447
+ lifecycle: 'retry',
448
+ retry: { attempt: 2, next: 5_000, message: 'provider request timed out' },
446
449
  };
447
450
  const runtime = {
448
451
  health: async () => ({ state: 'ready', protocolVersion: 1, capabilities: [] }),
@@ -467,8 +470,9 @@ describe('Pi runtime route', () => {
467
470
  parts: [{ type: 'text', id: 'entry-1:0', index: 0, text: 'hello' }],
468
471
  }],
469
472
  lastSequence: 9,
470
- isStreaming: false,
471
- lifecycle: 'idle',
473
+ isStreaming: true,
474
+ lifecycle: 'retry',
475
+ retry: { attempt: 2, next: 5_000, message: 'provider request timed out' },
472
476
  });
473
477
  const promptResponse = await fetch(`http://127.0.0.1:${server.address().port}/api/pi/sessions/pi-session-4/prompt`, {
474
478
  method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ sessionId: 'other', text: 'hello' }),
@@ -539,10 +543,11 @@ describe('Pi runtime route', () => {
539
543
  const runtime = {
540
544
  health: async () => ({ state: 'ready', protocolVersion: 1, capabilities: [] }),
541
545
  subscribe: async ({ onEvent }) => {
542
- onEvent({ protocolVersion: 1, kind: 'event', event: 'session.snapshot', sequence: 4, payload: { sessionId: 'pi-session-5', directory: '/workspace', isStreaming: false, lifecycle: 'idle', queue: { steering: 0, followUp: 0 }, lastSequence: 4, endpoint: '/private/socket' } });
546
+ onEvent({ protocolVersion: 1, kind: 'event', event: 'session.snapshot', sequence: 4, payload: { sessionId: 'pi-session-5', directory: '/workspace', isStreaming: true, lifecycle: 'retry', retry: { attempt: 1, next: 4_000, message: 'provider request timed out' }, queue: { steering: 0, followUp: 0 }, lastSequence: 4, endpoint: '/private/socket' } });
543
547
  onEvent({ protocolVersion: 1, kind: 'event', event: 'assistant.message.start', sequence: 5, payload: { sessionId: 'pi-session-5', directory: '/workspace', messageId: 'assistant-1', parentId: 'user-1', role: 'assistant', startedAt: 1 } });
544
- onEvent({ protocolVersion: 1, kind: 'event', event: 'assistant.message.end', sequence: 6, payload: { sessionId: 'pi-session-5', directory: '/workspace', messageId: 'assistant-1', durationMs: 42, error: { code: 'ASSISTANT_ERROR', message: 'provider request timed out' } } });
545
- onEvent({ protocolVersion: 1, kind: 'event', event: 'session.error', sequence: 7, payload: { sessionId: 'pi-session-5', directory: '/workspace', code: 'ASSISTANT_ERROR', message: 'provider request timed out' } });
548
+ onEvent({ protocolVersion: 1, kind: 'event', event: 'assistant.message.end', sequence: 6, payload: { sessionId: 'pi-session-5', directory: '/workspace', messageId: 'assistant-1', durationMs: 42, continuing: true, error: { code: 'ASSISTANT_ERROR', message: 'provider request timed out' } } });
549
+ onEvent({ protocolVersion: 1, kind: 'event', event: 'session.lifecycle', sequence: 7, payload: { sessionId: 'pi-session-5', directory: '/workspace', state: 'retry', attempt: 2, next: 8_000, message: 'provider request timed out' } });
550
+ onEvent({ protocolVersion: 1, kind: 'event', event: 'session.error', sequence: 8, payload: { sessionId: 'pi-session-5', directory: '/workspace', code: 'ASSISTANT_ERROR', message: 'provider request timed out' } });
546
551
  return () => {};
547
552
  },
548
553
  };
@@ -553,7 +558,7 @@ describe('Pi runtime route', () => {
553
558
  const reader = response.body.getReader();
554
559
  const first = await reader.read();
555
560
  let text = new TextDecoder().decode(first.value);
556
- while (!text.includes('"message":"provider request timed out"')) {
561
+ while (!text.includes('"state":"retry"')) {
557
562
  const next = await reader.read();
558
563
  if (next.done) break;
559
564
  text += new TextDecoder().decode(next.value);
@@ -561,8 +566,11 @@ describe('Pi runtime route', () => {
561
566
  await reader.cancel();
562
567
  expect(text).toContain('"name":"session.snapshot"');
563
568
  expect(text).toContain('"lastSequence":4');
569
+ expect(text).toContain('"retry":{"attempt":1,"next":4000,"message":"provider request timed out"}');
564
570
  expect(text).toContain('"parentId":"user-1"');
565
571
  expect(text).toContain('"durationMs":42');
572
+ expect(text).toContain('"continuing":true');
573
+ expect(text).toContain('"state":"retry","attempt":2,"next":8000,"message":"provider request timed out"');
566
574
  expect(text).toContain('"message":"provider request timed out"');
567
575
  expect(text).not.toContain('/private/socket');
568
576
  });
@@ -25,13 +25,14 @@ This module is the Pi-owned session-daemon foundation. A detached local daemon p
25
25
  - The public health route deliberately whitelists its response fields. It never returns a daemon endpoint, credential, PID, cwd, agent directory, or transcript data. Public transcript and event projections preserve daemon-redacted assistant error messages so the UI can distinguish provider/runtime failures instead of reducing every failure to `ASSISTANT_ERROR`.
26
26
  - A client must send an `authenticate` frame carrying the host-private daemon credential before it can issue a request. Credentials are never logged or returned.
27
27
  - Frames are LF-delimited JSON. They have a 1 MiB maximum buffered size. A malformed, oversized, unauthenticated, or invalid request closes the connection.
28
- - The private core commands are `runtime.health`, `projects.list/select`, `providers.list/config.get/models.set/status/login/login.respond/login.status/logout`, `settings.get/set`, `resources.list/update/prompts.create/prompts.delete`, and session list/create/open/rename/delete/tree/navigate/fork/clone/prompt/steer/followUp/abort/model/thinking/compact operations. Resource lists use opaque IDs and never disclose server paths. Only top-level Pi prompt templates and applicable AGENTS.md sources are editable; package/path resources and skills are browse-only. Resource writes are rejected while a session streams, use an atomic replace, then recreate the idle runtime. Project trust changes are persisted in Pi trust.json and likewise recreate an idle runtime; extensions remain disabled regardless of trust. Provider login submits API keys only across authenticated private IPC or brokers Pi's OAuth/device/manual-code interaction; public projections contain only opaque login IDs, prompts, URLs/device codes, model catalog/configuration, and stable states, never credentials or write-only headers. `providers.models.set` is rejected while a session streams, atomically persists Pi's `models.json`, then rehydrates the idle runtime so the catalog is authoritative immediately. `providers.list` projects only catalog and authentication-status metadata, including Pi-supported `thinkingLevels` (`null` map entries hidden, `xhigh`/`max` opt-in). Session thinking overrides are clamped to the live model's supported levels. `sessions.list` checks each cwd JSONL header (not the full transcript) so a project with large session logs cannot spend tens of seconds on startup. SDK `SessionManager.list` is not used for that path; `listPiSessionJsonlDirectory` reads a header, a bounded prefix for the first user prompt, and a tail for the latest rename. Concurrent lists of the same directory share one in-flight result. Concurrent `sessions.open` of the same id share one in-flight runtime create; a duplicate that finishes later disposes itself and returns the registered runtime instead of `SESSION_RUNTIME_CONFLICT`. Full-file JSONL validation stays on open of a chosen session. The browser explicitly selects an existing user-chosen project directory before listing it; the daemon's startup cwd is an internal fallback, not a user-visible default project. Unnamed persisted sessions use their first prompt as a readable list title when available. `sessions.open` and `getSession` project the last assistant `provider`/`model`/`thinkingLevel` onto the session record so reopening a chat keeps that cache identity. Session selection validates a persisted JSONL path before Pi opens it; inactive mutations are never directed by a browser-supplied path. `sessions.open` resolves an id by Pi's `timestamp_<id>.jsonl` filename first so a missing deep link 404s without listing or fully reading every transcript in every cwd; SDK list and header scan remain the fallback for non-standard names. Directory-wide JSONL checks on list/create/startup are header-only; full-file validation stays on open of a chosen transcript. Attachment paths originate in the server-local upload map and cross only private IPC into Pi's tool context. Pi may persist or echo those paths in its authoritative JSONL transcript, so every public projection redacts them recursively: session titles/previews, user and assistant text/thinking, tool arguments, errors, snapshots, and live message events never expose the server-local path. The daemon maps Pi message lifecycle, deltas, tools, queue changes, model/thinking, compaction, interruption state, and session title updates (`session.updated` on create-with-title, first-prompt auto-title, and rename) to canonical events. Tool events carry redacted input arguments, cumulative partial-output snapshots, final output, error text, renderer metadata (edit diffs, truncation notes), and start/end timestamps. Persisted `toolResult` entries merge into their assistant `toolCall` parts as output/error/end time so hydrated sessions render complete tool cards; tool-result entries never surface as standalone messages. Assistant message projections and start events carry the owning user-message id so the restored turn renderer can group and display replies; all assistant entries in a tool loop remain attached to the latest user turn. Assistant message projections also pass through Pi's per-turn `Usage` (input, output, cacheRead, cacheWrite, totalTokens, and the same five numeric cost fields). The daemon sanitizes the raw payload through `projectUsage` before publication: every numeric must be finite and non-negative, the whole object is omitted when any field is missing or wrong type, and unknown keys are never copied. The `assistant.message.end` event carries the same sanitized usage so the last turn updates without waiting for a full `getSession` refetch. The public route whitelist re-applies the same sanitizer on each projection so a stale or malformed payload from a different daemon version cannot surface as `NaN` or `Infinity` in the reducer.
28
+ - The private core commands are `runtime.health`, `projects.list/select`, `providers.list/config.get/models.set/status/login/login.respond/login.status/logout`, `settings.get/set`, `resources.list/update/prompts.create/prompts.delete`, and session list/create/open/rename/delete/tree/navigate/fork/clone/prompt/steer/followUp/abort/model/thinking/compact operations. Resource lists use opaque IDs and never disclose server paths. Only top-level Pi prompt templates and applicable AGENTS.md sources are editable; package/path resources and skills are browse-only. Resource writes are rejected while a session streams, use an atomic replace, then recreate the idle runtime. Project trust changes are persisted in Pi trust.json and likewise recreate an idle runtime; extensions remain disabled regardless of trust. Provider login submits API keys only across authenticated private IPC or brokers Pi's OAuth/device/manual-code interaction; public projections contain only opaque login IDs, prompts, URLs/device codes, model catalog/configuration, and stable states, never credentials or write-only headers. `providers.models.set` is rejected while a session streams, atomically persists Pi's `models.json`, then rehydrates the idle runtime so the catalog is authoritative immediately. `providers.list` projects only catalog and authentication-status metadata, including Pi-supported `thinkingLevels` (`null` map entries hidden, `xhigh`/`max` opt-in). Session thinking overrides are clamped to the live model's supported levels. `sessions.list` checks each cwd JSONL header (not the full transcript) so a project with large session logs cannot spend tens of seconds on startup. SDK `SessionManager.list` is not used for that path; `listPiSessionJsonlDirectory` reads a header, a bounded prefix for the first user prompt, and a tail for the latest rename. Concurrent lists of the same directory share one in-flight result. Concurrent `sessions.open` of the same id share one in-flight runtime create; a duplicate that finishes later disposes itself and returns the registered runtime instead of `SESSION_RUNTIME_CONFLICT`. Full-file JSONL validation stays on open of a chosen session. The browser explicitly selects an existing user-chosen project directory before listing it; the daemon's startup cwd is an internal fallback, not a user-visible default project. Unnamed persisted sessions use their first prompt as a readable list title when available. `sessions.open` and `getSession` project the last assistant `provider`/`model`/`thinkingLevel` onto the session record so reopening a chat keeps that cache identity. Session selection validates a persisted JSONL path before Pi opens it; inactive mutations are never directed by a browser-supplied path. `sessions.open` resolves an id by Pi's `timestamp_<id>.jsonl` filename first so a missing deep link 404s without listing or fully reading every transcript in every cwd; SDK list and header scan remain the fallback for non-standard names. Directory-wide JSONL checks on list/create/startup are header-only; full-file validation stays on open of a chosen transcript. Attachment paths originate in the server-local upload map and cross only private IPC into Pi's tool context. Pi may persist or echo those paths in its authoritative JSONL transcript, so every public projection redacts them recursively: session titles/previews, user and assistant text/thinking, tool arguments, errors, snapshots, and live message events never expose the server-local path. Persisted projection first checks for the attachment marker, then redacts matching tokens with a delimiter scan whose work stays linear for large encoded strings and tool payloads. The daemon maps Pi message lifecycle, deltas, tools, queue changes, model/thinking, compaction, interruption state, and session title updates (`session.updated` on create-with-title, first-prompt auto-title, and rename) to canonical events. Tool events carry redacted input arguments, cumulative partial-output snapshots, final output, error text, renderer metadata (edit diffs, truncation notes), and start/end timestamps. Persisted `toolResult` entries merge into their assistant `toolCall` parts as output/error/end time so hydrated sessions render complete tool cards; tool-result entries never surface as standalone messages. Assistant message projections and start events carry the owning user-message id so the restored turn renderer can group and display replies; all assistant entries in a tool loop and every retry/compaction continuation remain attached to the latest user turn until `agent_settled` closes the run. Assistant message projections also pass through Pi's per-turn `Usage` (input, output, cacheRead, cacheWrite, totalTokens, and the same five numeric cost fields). The daemon sanitizes the raw payload through `projectUsage` before publication: every numeric must be finite and non-negative, the whole object is omitted when any field is missing or wrong type, and unknown keys are never copied. The `assistant.message.end` event carries the same sanitized usage so the last turn updates without waiting for a full `getSession` refetch. The public route whitelist re-applies the same sanitizer on each projection so a stale or malformed payload from a different daemon version cannot surface as `NaN` or `Infinity` in the reducer.
29
+ - Live `message_start` events use daemon-generated browser message IDs because Pi has not appended the corresponding session entry yet. Pi agent-core emits streaming assistant starts as shallow copies, not as the finalized object it later persists. At `message_end`, `message-entry-aliases.js` therefore rebinds the synthetic ID to the finalized event object, then maps that object by identity to Pi's appended entry in a microtask. `sessions.navigate` and `sessions.fork` resolve the mapping after stripping any part suffix. Alias keys include cwd and session ID, survive idle runtime disposal, and clear only on explicit session deletion or daemon shutdown. Hydrated message projections continue to use the Pi entry ID directly.
29
30
  - Each event and reconnect snapshot has a monotonic sequence. A reconnect receives a bounded contiguous replay after its cursor when available, otherwise an authoritative `session.snapshot`; unavailable runtimes are not represented as empty sessions.
30
- - Prompt, steer, and follow-up requests acknowledge acceptance immediately after Pi accepts the call; the daemon owns the still-running send promise and publishes any asynchronous rejection as `session.error`. A later prompt on the same session invalidates that rejection so it cannot error the new turn. If the rejected send left Pi streaming, the daemon aborts it. Steer/follow-up against an idle session starts a new prompt instead of `SESSION_NOT_RUNNING`. Agent completion is never held behind the 30-second public/private request budgets. Pi retryable provider failures remain live: an `agent_end` with `willRetry` does not publish terminal `session.error`, and `auto_retry_start` projects Pi's attempt, next-attempt time, and redacted error text through `session.lifecycle: retry`. `agent_settled` remains the authoritative idle boundary after retry success, exhaustion, or cancellation.
31
+ - Prompt, steer, and follow-up requests acknowledge acceptance immediately after Pi accepts the call; the daemon owns the still-running send promise and publishes any asynchronous rejection as `session.error`. A later prompt on the same session invalidates that rejection so it cannot error the new turn. If the rejected send left Pi streaming, the daemon aborts it. Steer/follow-up against an idle session starts a new prompt instead of `SESSION_NOT_RUNNING`. Agent completion is never held behind the 30-second public/private request budgets. Pi retryable provider failures remain live: an `agent_end` with `willRetry` does not publish terminal `session.error`, and `auto_retry_start` projects Pi's attempt, next-attempt time, and redacted error text through `session.lifecycle: retry`. Retry metadata is retained in reconnect and `getSession` snapshots until the next `agent_start` begins the attempt. `agent_settled` remains the authoritative idle boundary after retry success, exhaustion, or cancellation and clears the run's user/assistant ownership.
31
32
  - Registry keys combine the SDK session ID with its cwd. A replacement subscription is rebound to the replacement session so old-session events cannot be published under the new identity. A collision is a visible error; it never replaces or disposes an unrelated runtime.
32
33
  - After `agent_settled`, the daemon disposes an idle runtime after five minutes (injectable for tests). Disposal never deletes Pi JSONL; the daemon remembers the selected session file and recreates that runtime on the next private prompt. A new agent start cancels a pending disposal.
33
34
  - A startup validation failure writes only a stable failure code to the owner-only non-secret state sidecar. It never records a transcript, session path, or credential. The supervisor surfaces that code as unavailable instead of claiming an empty or idle session.
34
- - After a forced crash, the next health, request, or subscription probe re-runs supervised startup. Daemon readiness has its own 15-second bounded budget, separate from the shorter lock and shutdown budget, because loading Pi settings and provider/model catalogs can legitimately exceed five seconds. The supervisor removes an existing POSIX socket only when its recorded daemon PID is dead, the endpoint is a socket, and authenticated IPC deterministically refuses or times out. An endpoint that responds, authenticates incorrectly, returns malformed protocol data, or cannot be classified remains `DAEMON_ENDPOINT_UNVERIFIED`.
35
+ - After a forced crash, the next health, request, or subscription probe re-runs supervised startup. Each private health probe uses the supervisor's five-second operation budget; it must not inherit the general 30-second command timeout and hold every browser request until the browser aborts. Daemon readiness has its own 15-second bounded budget, separate from the shorter probe, lock, and shutdown budget, because loading Pi settings and provider/model catalogs can legitimately exceed five seconds. The supervisor removes an existing POSIX socket only when its recorded daemon PID is dead, the endpoint is a socket, and authenticated IPC deterministically refuses or times out. An endpoint that responds, authenticates incorrectly, returns malformed protocol data, or cannot be classified remains `DAEMON_ENDPOINT_UNVERIFIED`.
35
36
  - The web server starts warming the supervisor immediately after HTTP listen without awaiting Pi provider/model initialization. A first request arriving during that warmup shares the supervisor's `startPromise`.
36
37
  - The daemon owns the runtime after clients disconnect. Disconnecting the web-server client cannot stop active Pi work.
37
38