@av-pi-studio/web-client 0.0.58 → 0.0.59
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/.tsbuildinfo +1 -1
- package/dist/web/assets/{BinaryFallbackViewer-B2VwR_mP.js → BinaryFallbackViewer-BPcn4yCY.js} +2 -2
- package/dist/web/assets/{BinaryFallbackViewer-B2VwR_mP.js.map → BinaryFallbackViewer-BPcn4yCY.js.map} +1 -1
- package/dist/web/assets/BinaryFallbackViewer-BnBkar4_.css +1 -0
- package/dist/web/assets/ChatPanel-8Tj813-O.js +3 -0
- package/dist/web/assets/{ChatPanel-BwrtLljS.js.map → ChatPanel-8Tj813-O.js.map} +1 -1
- package/dist/web/assets/ChatPanel-DBXDoy3Z.css +1 -0
- package/dist/web/assets/CodeView-Bbd7h9aM.css +1 -0
- package/dist/web/assets/{CodeView-m0tfNIht.js → CodeView-DNKpvKfm.js} +2 -2
- package/dist/web/assets/{CodeView-m0tfNIht.js.map → CodeView-DNKpvKfm.js.map} +1 -1
- package/dist/web/assets/DiffView-E-36gscH.js +3 -0
- package/dist/web/assets/{DiffView-dFsrDUgN.js.map → DiffView-E-36gscH.js.map} +1 -1
- package/dist/web/assets/DiffView-txOCMsXo.css +1 -0
- package/dist/web/assets/{FilePanel-BXUoxYr6.js → FilePanel-1jMXusYi.js} +2 -2
- package/dist/web/assets/{FilePanel-BXUoxYr6.js.map → FilePanel-1jMXusYi.js.map} +1 -1
- package/dist/web/assets/FilePanel-CympQkwn.css +1 -0
- package/dist/web/assets/FilePanel.module-CqISrbT-.js +2 -0
- package/dist/web/assets/FilePanel.module-CqISrbT-.js.map +1 -0
- package/dist/web/assets/{ImageViewer-mcjYrMpI.js → ImageViewer-Cimj0SFJ.js} +2 -2
- package/dist/web/assets/{ImageViewer-mcjYrMpI.js.map → ImageViewer-Cimj0SFJ.js.map} +1 -1
- package/dist/web/assets/{MarkdownFileViewer-BJHdXtlX.js → MarkdownFileViewer-BChv2tKK.js} +2 -2
- package/dist/web/assets/{MarkdownFileViewer-BJHdXtlX.js.map → MarkdownFileViewer-BChv2tKK.js.map} +1 -1
- package/dist/web/assets/MoleculeViewerPanel-B-0MaJMt.css +1 -0
- package/dist/web/assets/MoleculeViewerPanel-CtODGGih.js +2 -0
- package/dist/web/assets/{MoleculeViewerPanel-DLhr38Kg.js.map → MoleculeViewerPanel-CtODGGih.js.map} +1 -1
- package/dist/web/assets/StatusBadge-4JuIxBe-.css +1 -0
- package/dist/web/assets/StatusBadge-CJBuPnrc.js +2 -0
- package/dist/web/assets/{StatusBadge-Cripx88K.js.map → StatusBadge-CJBuPnrc.js.map} +1 -1
- package/dist/web/assets/TerminalPanel-BQZ0KqJv.js +2 -0
- package/dist/web/assets/TerminalPanel-BQZ0KqJv.js.map +1 -0
- package/dist/web/assets/TerminalPanel-CfG2gRmZ.css +1 -0
- package/dist/web/assets/{TextViewer-Bw2pi_7l.js → TextViewer-3yEorz3A.js} +2 -2
- package/dist/web/assets/{TextViewer-Bw2pi_7l.js.map → TextViewer-3yEorz3A.js.map} +1 -1
- package/dist/web/assets/TextViewer-Bcv3IFDK.css +1 -0
- package/dist/web/assets/{VideoViewer-f2VQTY2g.js → VideoViewer-CbBaI4CK.js} +2 -2
- package/dist/web/assets/{VideoViewer-f2VQTY2g.js.map → VideoViewer-CbBaI4CK.js.map} +1 -1
- package/dist/web/assets/index-CEP1cIKf.js +3 -0
- package/dist/web/assets/index-CEP1cIKf.js.map +1 -0
- package/dist/web/assets/index-DCtlhAPI.css +1 -0
- package/dist/web/assets/markdown-9_X86EBj.js +2 -0
- package/dist/web/assets/{markdown-BA3kiSJG.js.map → markdown-9_X86EBj.js.map} +1 -1
- package/dist/web/assets/markdown-DEdmq7db.css +1 -0
- package/dist/web/assets/{use-file-download-DzZxLbm7.js → use-file-download-BTSuk1Eh.js} +2 -2
- package/dist/web/assets/{use-file-download-DzZxLbm7.js.map → use-file-download-BTSuk1Eh.js.map} +1 -1
- package/dist/web/assets/{use-file-watch-Hq88QNSC.js → use-file-watch-DZfGlL1N.js} +2 -2
- package/dist/web/assets/{use-file-watch-Hq88QNSC.js.map → use-file-watch-DZfGlL1N.js.map} +1 -1
- package/dist/web/index.html +2 -2
- package/package.json +3 -3
- package/dist/web/assets/BinaryFallbackViewer-tQuWh1gb.css +0 -1
- package/dist/web/assets/ChatPanel-BwrtLljS.js +0 -3
- package/dist/web/assets/ChatPanel-CQLDxTXk.css +0 -1
- package/dist/web/assets/CodeView-BO8BIqVA.css +0 -1
- package/dist/web/assets/DiffView-D4YVGgEU.css +0 -1
- package/dist/web/assets/DiffView-dFsrDUgN.js +0 -3
- package/dist/web/assets/FilePanel-CAeLW13m.css +0 -1
- package/dist/web/assets/FilePanel.module-CZJhfnR7.js +0 -2
- package/dist/web/assets/FilePanel.module-CZJhfnR7.js.map +0 -1
- package/dist/web/assets/MoleculeViewerPanel-DLhr38Kg.js +0 -2
- package/dist/web/assets/MoleculeViewerPanel-DSOV4pHJ.css +0 -1
- package/dist/web/assets/StatusBadge-Cripx88K.js +0 -2
- package/dist/web/assets/StatusBadge-DwC2kTaC.css +0 -1
- package/dist/web/assets/TerminalPanel-BX9bO1dW.js +0 -2
- package/dist/web/assets/TerminalPanel-BX9bO1dW.js.map +0 -1
- package/dist/web/assets/TerminalPanel-D_zUAE5t.css +0 -1
- package/dist/web/assets/TextViewer-BL-M7P0v.css +0 -1
- package/dist/web/assets/index-Bf8G89ZE.css +0 -1
- package/dist/web/assets/index-DtH67PKb.js +0 -3
- package/dist/web/assets/index-DtH67PKb.js.map +0 -1
- package/dist/web/assets/markdown-BA3kiSJG.js +0 -2
- package/dist/web/assets/markdown-DI2EwgWf.css +0 -1
|
@@ -0,0 +1 @@
|
|
|
1
|
+
html,body{margin:0;padding:0}body{min-height:100vh;overflow:hidden;background:var(--pi-color-background, #0a0a0a);color:var(--pi-color-foreground, #fafafa);font-family:var(--pi-font-ui, system-ui, sans-serif)}#root{display:flex;flex-direction:column;min-height:100vh}*,*:before,*:after{box-sizing:border-box}::-webkit-scrollbar{width:6px;height:6px}::-webkit-scrollbar-track{background:transparent}::-webkit-scrollbar-thumb{background:var(--pi-color-border, #353b46);border-radius:3px}._btn_1chbg_4{display:inline-flex;align-items:center;justify-content:center;gap:8px;border-radius:var(--pi-radius-lg, 8px);border:1px solid transparent;font-family:var(--pi-font-ui, system-ui, sans-serif);font-weight:500;cursor:pointer;-webkit-user-select:none;user-select:none;white-space:nowrap;text-decoration:none;outline:none;transition:opacity .12s ease,background-color .12s ease,border-color .12s ease;box-sizing:border-box}._btn_1chbg_4:focus-visible{outline:2px solid var(--pi-color-accent, #2e5cb8);outline-offset:2px}._btn_1chbg_4:disabled,._btn_1chbg_4[aria-disabled=true]{cursor:not-allowed;pointer-events:none}._default_1chbg_35{background-color:var(--pi-color-accent, #2e5cb8);color:var(--pi-color-accentForeground, #ffffff);border-color:var(--pi-color-accent, #2e5cb8)}._default_1chbg_35:hover:not(:disabled){filter:brightness(1.08)}._secondary_1chbg_44{background-color:var(--pi-color-surface3, #3f3f46);color:var(--pi-color-foreground, #fafafa);border-color:var(--pi-color-border, #3f3f46)}._secondary_1chbg_44:hover:not(:disabled){background-color:var(--pi-color-surface2, #27272a)}._outline_1chbg_53{background-color:transparent;color:var(--pi-color-accentBright, #a2b4d7);border-color:var(--pi-color-accent, #2e5cb8)}._outline_1chbg_53:hover:not(:disabled){background-color:var(--pi-color-surface1, #18181b)}._ghost_1chbg_62{background-color:transparent;color:var(--pi-color-foregroundMuted, #a1a1aa);border-color:transparent}._ghost_1chbg_62:hover:not(:disabled){color:var(--pi-color-foreground, #fafafa);background-color:var(--pi-color-surface1, #18181b)}._destructive_1chbg_72{background-color:var(--pi-color-destructive, #991b1b);color:var(--pi-color-destructiveForeground, #fef2f2);border-color:var(--pi-color-destructive, #991b1b)}._destructive_1chbg_72:hover:not(:disabled){filter:brightness(1.1)}._iconOnly_1chbg_82{padding-left:0!important;padding-right:0!important;aspect-ratio:1}._loadingSpinner_1chbg_89{animation:_piSpin_1chbg_1 .75s linear infinite;flex-shrink:0}@keyframes _piSpin_1chbg_1{0%{transform:rotate(0)}to{transform:rotate(360deg)}}._input_ew09y_3{width:100%;padding:8px 12px;border-radius:var(--pi-radius-md, 6px);border:1px solid var(--pi-color-border, #3f3f46);background-color:var(--pi-color-surface2, #27272a);color:var(--pi-color-foreground, #fafafa);font-size:var(--pi-font-size-base);font-family:var(--pi-font-ui, system-ui, sans-serif);outline:none;transition:border-color .12s ease;box-sizing:border-box}._input_ew09y_3::placeholder{color:var(--pi-color-foregroundMuted, #a1a1aa)}._input_ew09y_3:focus{border-color:var(--pi-color-accent, #2e5cb8);outline:2px solid var(--pi-color-accent, #2e5cb8);outline-offset:-1px}._input_ew09y_3:disabled{opacity:.5;cursor:not-allowed}._textarea_ew09y_32{resize:vertical;min-height:80px}._wrap_1jr5f_1{display:inline-flex;align-items:center;gap:6px;font-size:var(--pi-font-size-xs);color:var(--pi-color-foregroundMuted, #9aa0a6)}._dot_1jr5f_8{width:8px;height:8px;border-radius:50%;background:var(--pi-color-foregroundMuted, #9aa0a6);flex-shrink:0}._dot_1jr5f_8._open_1jr5f_15{background:var(--pi-color-statusSuccess, #3ecf8e)}._dot_1jr5f_8._connecting_1jr5f_18{background:var(--pi-color-statusWarning, #e0a030)}._dot_1jr5f_8._closed_1jr5f_21,._dot_1jr5f_8._idle_1jr5f_22,._dot_1jr5f_8._closing_1jr5f_23{background:var(--pi-color-statusDanger, #e5484d)}._toolbar_1oxtj_1{display:flex;align-items:center;gap:10px;padding:6px 10px;border-bottom:1px solid var(--pi-color-border, #353b46);background:var(--pi-color-surface, #16181a);flex-shrink:0}._brand_1oxtj_10{font-weight:600;font-size:var(--pi-font-size-sm);letter-spacing:.02em;white-space:nowrap}._version_1oxtj_16{font-size:var(--pi-font-size-2xs);color:var(--pi-color-foregroundMuted, #7a8394);white-space:nowrap;margin-left:-4px}._sep_1oxtj_22{width:1px;height:18px;background:var(--pi-color-border, #353b46);flex-shrink:0}._host_1oxtj_28{width:190px}._password_1oxtj_31{width:100px}._sidebarToggles_1oxtj_34{display:flex;align-items:center;gap:4px;margin-left:auto}._dot_gfh8u_3{display:inline-block;width:8px;height:8px;border-radius:9999px;flex-shrink:0}._spinner_gfh8u_16{display:inline-block;width:12px;height:12px;border-radius:9999px;border:2px solid var(--pi-color-border, #353b46);flex-shrink:0;animation:_statusSpin_gfh8u_1 .7s linear infinite}@keyframes _statusSpin_gfh8u_1{to{transform:rotate(360deg)}}._wrap_3dtlo_1{display:flex;flex-direction:column;min-height:0;height:100%}._header_3dtlo_7{display:flex;align-items:center;justify-content:space-between;padding:6px 10px;border-bottom:1px solid var(--pi-color-border, #353b46);flex-shrink:0}._openBtn_3dtlo_15{width:20px!important;min-height:20px!important}._header_3dtlo_7 h3{margin:0;font-size:var(--pi-font-size-xs);font-weight:600;color:var(--pi-color-foregroundMuted, #9aa0a6);text-transform:uppercase;letter-spacing:.04em}._list_3dtlo_27{flex:1 1 auto;overflow-y:auto;min-height:0}._item_3dtlo_32{position:relative;padding:8px 10px;cursor:pointer;border-bottom:1px solid transparent}._item_3dtlo_32:hover{background:var(--pi-color-surfaceHover, #1e2124)}._item_3dtlo_32._active_3dtlo_41{background:var(--pi-color-surfaceSunken, #111);box-shadow:inset 2px 0 0 var(--pi-color-accent, #2e5cb8)}._title_3dtlo_45{display:flex;align-items:center;gap:6px;font-size:var(--pi-font-size-sm);overflow:hidden;text-overflow:ellipsis;white-space:nowrap}._meta_3dtlo_54{margin-top:2px;font-size:var(--pi-font-size-2xs);color:var(--pi-color-foregroundMuted, #9aa0a6);overflow:hidden;text-overflow:ellipsis;white-space:nowrap}._menuBtn_3dtlo_62{position:absolute;top:6px;right:6px;opacity:0;padding:2px 4px;background:none;border:none;border-radius:4px;cursor:pointer;color:var(--pi-color-foregroundMuted, #9aa0a6)}._item_3dtlo_32:hover ._menuBtn_3dtlo_62{opacity:1}._menuBtn_3dtlo_62:hover{background:var(--pi-color-surfaceHover, #1e2124)}._workspaceGroup_3dtlo_80{border-bottom:1px solid var(--pi-color-border, #353b46)}._workspaceHeader_3dtlo_83{display:flex;align-items:center;gap:6px;padding:7px 10px;cursor:pointer;font-size:var(--pi-font-size-xs);font-weight:600;color:var(--pi-color-foreground, #e6e6e6);background:var(--pi-color-surfaceWorkspace, #1e2120)}._workspaceHeader_3dtlo_83:hover{background:color-mix(in srgb,var(--pi-color-surfaceWorkspace, #1e2120) 85%,var(--pi-color-foreground, #fafafa) 15%)}._workspaceChevron_3dtlo_108{display:flex;align-items:center;justify-content:center;padding:0;background:none;border:none;cursor:pointer;color:var(--pi-color-foregroundMuted, #9aa0a6);flex-shrink:0}._workspaceIcon_3dtlo_119{color:var(--pi-color-foregroundMuted, #9aa0a6);flex-shrink:0}._workspaceLabel_3dtlo_123{flex:1 1 auto;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}._workspaceCount_3dtlo_129{font-size:var(--pi-font-size-2xs);font-weight:400;color:var(--pi-color-foregroundMuted, #9aa0a6)}._workspaceMenuBtn_3dtlo_134{display:flex;align-items:center;justify-content:center;flex-shrink:0;opacity:0;padding:3px;background:none;border:none;border-radius:4px;cursor:pointer;color:var(--pi-color-foregroundMuted, #9aa0a6)}._workspaceHeader_3dtlo_83:hover ._workspaceMenuBtn_3dtlo_134{opacity:1}._workspaceMenuBtn_3dtlo_134:hover{background:var(--pi-color-surfaceHover, #1e2124);color:var(--pi-color-foreground, #e6e6e6)}._workspaceSessions_3dtlo_154{padding-left:12px}._emptyState_3dtlo_157{padding:12px 10px;font-size:var(--pi-font-size-xs);color:var(--pi-color-foregroundMuted, #9aa0a6)}._trigger_yc3my_1{position:fixed;width:1px;height:1px;padding:0;border:0;background:none;-webkit-appearance:none;-moz-appearance:none;appearance:none;opacity:0;pointer-events:none}._content_yc3my_12{min-width:160px;padding:4px;border-radius:var(--pi-borderRadius-md, 6px);background:var(--pi-color-surface, #16181a);border:1px solid var(--pi-color-border, #353b46);box-shadow:0 8px 24px #0006;z-index:1000}._item_yc3my_21{display:flex;align-items:center;gap:8px;padding:6px 10px;border-radius:4px;font-size:var(--pi-font-size-sm);cursor:pointer;outline:none}._item_yc3my_21:hover,._item_yc3my_21[data-highlighted]{background:var(--pi-color-surfaceHover, #1e2124)}._item_yc3my_21[data-disabled]{opacity:.4;cursor:default}._danger_yc3my_39{color:var(--pi-color-statusDanger, #e5484d)}._sep_yc3my_42{height:1px;margin:4px 0;background:var(--pi-color-border, #353b46)}._strip_tg9sf_1{display:flex;align-items:center;gap:2px;min-height:33px;padding:4px 6px 0;overflow-x:auto;flex-shrink:0;border-bottom:1px solid var(--pi-color-border, #353b46)}._tab_tg9sf_11{display:flex;align-items:center;gap:6px;padding:6px 8px;border-radius:var(--pi-borderRadius-md, 6px) var(--pi-borderRadius-md, 6px) 0 0;font-size:var(--pi-font-size-xs);cursor:pointer;color:var(--pi-color-foregroundMuted, #9aa0a6);white-space:nowrap;flex-shrink:0;-webkit-user-select:none;user-select:none}._tab_tg9sf_11:hover{background:var(--pi-color-surfaceHover, #1e2124)}._active_tg9sf_27{background:var(--pi-color-surfaceSunken, #111);color:var(--pi-color-foreground, #fafafa)}._icon_tg9sf_31{display:flex;align-items:center;flex-shrink:0}._label_tg9sf_36{max-width:160px;overflow:hidden;text-overflow:ellipsis}._close_tg9sf_41{display:flex;align-items:center;border-radius:3px;padding:1px;flex-shrink:0}._close_tg9sf_41:hover{background:var(--pi-color-surfaceHover, #1e2124)}._newTab_tg9sf_51{position:relative;display:flex;align-items:center;justify-content:center;flex-shrink:0;margin:0 4px;width:20px;height:20px;border-radius:var(--pi-borderRadius-sm, 4px);color:var(--pi-color-foregroundMuted, #9aa0a6);background:transparent;border:none;cursor:pointer}._newTab_tg9sf_51:hover:not(:disabled){background:var(--pi-color-surfaceHover, #1e2124);color:var(--pi-color-foreground, #fafafa)}._newTab_tg9sf_51:disabled{opacity:.4;cursor:default}._content_tg9sf_74{min-width:160px;padding:4px;border-radius:var(--pi-borderRadius-md, 6px);background:var(--pi-color-surface, #16181a);border:1px solid var(--pi-color-border, #353b46);box-shadow:0 8px 24px #0006;z-index:1000}._item_tg9sf_83{display:flex;align-items:center;gap:8px;padding:6px 10px;border-radius:4px;font-size:var(--pi-font-size-sm);cursor:pointer;outline:none}._item_tg9sf_83:hover,._item_tg9sf_83[data-highlighted]{background:var(--pi-color-surfaceHover, #1e2124)}._itemIcon_tg9sf_97{flex-shrink:0;color:var(--pi-color-foregroundMuted, #9aa0a6)}._spinner_1tgzp_3{display:inline-block;border-radius:9999px;border-style:solid;border-color:currentColor transparent transparent transparent;animation:_piSpinnerRotate_1tgzp_1 .7s linear infinite;flex-shrink:0}@keyframes _piSpinnerRotate_1tgzp_1{0%{transform:rotate(0)}to{transform:rotate(360deg)}}._area_abmp3_1{position:relative;flex:1 1 auto;min-height:0;overflow:hidden}._panel_abmp3_7{position:absolute;top:0;right:0;bottom:0;left:0;display:none;flex-direction:column;min-height:0}._active_abmp3_14{display:flex}._empty_abmp3_17{display:flex;align-items:center;justify-content:center;height:100%;color:var(--pi-color-foregroundMuted, #9aa0a6);font-size:var(--pi-font-size-sm)}._emptyStack_abmp3_25{display:flex;flex-direction:column;align-items:center;justify-content:center;gap:10px;height:100%;padding:0 16px;text-align:center}._emptyTitle_abmp3_35{font-size:var(--pi-font-size-sm);color:var(--pi-color-foreground, #e6e6e6)}._emptyHint_abmp3_39{font-size:var(--pi-font-size-xs);color:var(--pi-color-foregroundMuted, #9aa0a6)}._container_1d3wg_1{position:relative;height:100%;display:flex;flex-direction:column}._header_1d3wg_7{display:flex;align-items:center;gap:6px;padding:6px 8px;border-bottom:1px solid var(--pi-color-border, #353b46)}._uploadButton_1d3wg_14{display:inline-flex;align-items:center;gap:5px;font-size:var(--pi-font-size-2xs);padding:3px 8px;border-radius:4px;border:1px solid var(--pi-color-border, #353b46);background:var(--pi-color-surface, #1e2124);color:var(--pi-color-foreground, #e4e6eb);cursor:pointer}._uploadButton_1d3wg_14:hover:not(:disabled){background:var(--pi-color-surfaceHover, #2a2e33)}._uploadButton_1d3wg_14:disabled{opacity:.5;cursor:default}._hiddenInput_1d3wg_33{display:none}._status_1d3wg_36,._statusError_1d3wg_37{font-size:var(--pi-font-size-2xs);padding:4px 8px;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}._status_1d3wg_36{color:var(--pi-color-foregroundMuted, #9aa0a6)}._statusError_1d3wg_37{color:var(--pi-color-danger, #e5534b)}._rowAction_1d3wg_50{margin-left:auto;display:none;align-items:center;padding:2px;border:none;background:transparent;color:var(--pi-color-foregroundMuted, #9aa0a6);cursor:pointer;border-radius:3px}._rowAction_1d3wg_50:hover{color:var(--pi-color-foreground, #e4e6eb);background:var(--pi-color-surface, #1e2124)}._item_1d3wg_65:hover ._rowAction_1d3wg_50{display:inline-flex}._list_1d3wg_69{padding:4px 0;flex:1;overflow-y:auto;position:relative}._item_1d3wg_65{height:28px;padding-right:8px;font-size:var(--pi-font-size-xs);border-radius:3px;cursor:pointer;display:flex;align-items:center;gap:6px;user-select:none;-webkit-user-select:none}._item_1d3wg_65:hover{background:var(--pi-color-surfaceHover, #1e2124)}._item_1d3wg_65._active_1d3wg_92{background:var(--pi-color-surfaceSunken, #111);box-shadow:inset 2px 0 0 var(--pi-color-accent, #2e5cb8);border-radius:0}._item_1d3wg_65._selected_1d3wg_97{background:var(--pi-color-surfaceSunken, #111);border-radius:0}._item_1d3wg_65._dropTarget_1d3wg_101{background:color-mix(in srgb,var(--pi-color-accent, #2e5cb8) 22%,transparent);box-shadow:inset 0 0 0 1px var(--pi-color-accent, #2e5cb8);border-radius:3px}._chevronSlot_1d3wg_106{display:flex;align-items:center;justify-content:center;width:14px;flex-shrink:0;color:var(--pi-color-foregroundMuted, #9aa0a6)}._chevron_1d3wg_106{transition:transform .1s ease}._chevronOpen_1d3wg_117{transform:rotate(90deg)}._icon_1d3wg_120{display:flex;align-items:center;width:16px;flex-shrink:0;color:var(--pi-color-foregroundMuted, #9aa0a6)}._name_1d3wg_127{white-space:nowrap;overflow:hidden;text-overflow:ellipsis}._dirName_1d3wg_132{white-space:nowrap;overflow:hidden;text-overflow:ellipsis;color:var(--pi-color-accentBright, #a2b4d7)}._statusRow_1d3wg_138{height:28px;display:flex;align-items:center;padding-right:8px;font-size:var(--pi-font-size-2xs);color:var(--pi-color-foregroundMuted, #9aa0a6);overflow:hidden;text-overflow:ellipsis;white-space:nowrap}._statusRowError_1d3wg_149{color:var(--pi-color-danger, #e5534b)}._emptyState_1d3wg_152{color:var(--pi-color-foregroundMuted, #9aa0a6);font-size:var(--pi-font-size-xs);text-align:center;padding:20px}._draftInput_1d3wg_158{flex:1;min-width:0;height:20px;font:inherit;font-size:var(--pi-font-size-xs);padding:0 4px;color:var(--pi-color-foreground, #e4e6eb);background:var(--pi-color-surfaceSunken, #111);border:1px solid var(--pi-color-accent, #2e5cb8);border-radius:3px;outline:none}._trigger_13ghf_1{position:fixed;width:1px;height:1px;padding:0;border:0;background:none;-webkit-appearance:none;-moz-appearance:none;appearance:none;opacity:0;pointer-events:none}._content_13ghf_12{min-width:140px;padding:4px;border-radius:var(--pi-borderRadius-md, 6px);background:var(--pi-color-surface, #16181a);border:1px solid var(--pi-color-border, #353b46);box-shadow:0 8px 24px #0006;z-index:1000}._item_13ghf_21{display:flex;align-items:center;gap:8px;padding:6px 10px;border-radius:4px;font-size:var(--pi-font-size-sm);cursor:pointer;outline:none}._item_13ghf_21:hover,._item_13ghf_21[data-highlighted]{background:var(--pi-color-surfaceHover, #1e2124)}._danger_13ghf_35{color:var(--pi-color-statusDanger, #e5484d)}._sep_13ghf_38{height:1px;margin:4px 0;background:var(--pi-color-border, #353b46)}._list_10160_1{padding:4px 0}._summary_10160_4{padding:4px 8px;font-size:var(--pi-font-size-2xs);color:var(--pi-color-foregroundMuted, #9aa0a6);border-bottom:1px solid var(--pi-color-border, #353b46);margin-bottom:4px}._item_10160_11{padding:4px 8px;font-size:var(--pi-font-size-xs);border-radius:3px;cursor:pointer;display:flex;align-items:center;gap:6px}._item_10160_11:hover{background:var(--pi-color-surfaceHover, #1e2124)}._badge_10160_23{font-size:var(--pi-font-size-3xs);padding:0 4px;border-radius:3px;font-weight:600;flex-shrink:0}._added_10160_30{background:color-mix(in srgb,var(--pi-color-statusSuccess, #4ade80) 20%,transparent);color:var(--pi-color-statusSuccess, #4ade80)}._modified_10160_34{background:color-mix(in srgb,var(--pi-color-statusWarning, #facc15) 20%,transparent);color:var(--pi-color-statusWarning, #facc15)}._deleted_10160_38{background:color-mix(in srgb,var(--pi-color-statusDanger, #ff8a80) 20%,transparent);color:var(--pi-color-statusDanger, #ff8a80)}._name_10160_42{white-space:nowrap;overflow:hidden;text-overflow:ellipsis}._emptyState_10160_47{color:var(--pi-color-foregroundMuted, #9aa0a6);font-size:var(--pi-font-size-xs);text-align:center;padding:20px}._wrap_3jeq6_1{display:flex;flex-direction:column;height:100%;min-height:0}._tabBar_3jeq6_7{display:flex;align-items:center;border-bottom:1px solid var(--pi-color-border, #353b46);flex-shrink:0}._tabBtn_3jeq6_13{display:flex;align-items:center;gap:6px;font:inherit;font-size:var(--pi-font-size-xs);padding:8px 12px;background:none;border:none;color:var(--pi-color-foregroundMuted, #9aa0a6);cursor:pointer;border-bottom:2px solid transparent}._tabBtn_3jeq6_13:hover{color:var(--pi-color-foreground, #fafafa)}._active_3jeq6_29{color:var(--pi-color-foreground, #fafafa);border-bottom-color:var(--pi-color-accent, #2e5cb8)}._refreshBtn_3jeq6_33{margin-left:auto;margin-right:6px}._content_3jeq6_37{flex:1;overflow-y:auto;padding:8px;min-height:0}._content_14c2k_4{min-width:240px;padding:4px;border-radius:var(--pi-borderRadius-md, 6px);background:var(--pi-color-surface, #16181a);border:1px solid var(--pi-color-border, #353b46);box-shadow:0 8px 24px #0006;z-index:1000;display:flex;flex-direction:column;gap:4px}._search_14c2k_17{width:100%;box-sizing:border-box;padding:6px 8px;border-radius:var(--pi-radius-md, 6px);border:1px solid var(--pi-color-border, #3f3f46);background:var(--pi-color-surface2, #27272a);color:var(--pi-color-foreground, #fafafa);font-size:var(--pi-font-size-xs);outline:none}._search_14c2k_17::placeholder{color:var(--pi-color-foregroundMuted, #9aa0a6)}._search_14c2k_17:focus{border-color:var(--pi-color-accent, #2e5cb8)}._list_14c2k_35{max-height:320px;overflow-y:auto}._item_14c2k_40{display:flex;align-items:center;gap:6px;padding:6px 8px;border-radius:4px;font-size:var(--pi-font-size-sm);cursor:pointer;outline:none}._item_14c2k_40:hover,._item_14c2k_40[data-highlighted],._item_14c2k_40._itemActive_14c2k_54{background:var(--pi-color-surfaceHover, #1e2124)}._checkSlot_14c2k_58{width:16px;flex-shrink:0;display:inline-flex;align-items:center;justify-content:center;color:var(--pi-color-foreground, #fafafa)}._label_14c2k_67{overflow:hidden;text-overflow:ellipsis;white-space:nowrap}._modelId_14c2k_73{color:var(--pi-color-foregroundMuted, #9aa0a6);margin-left:4px;font-size:var(--pi-font-size-xs);white-space:nowrap}._state_14c2k_80{display:flex;align-items:center;justify-content:center;padding:12px;color:var(--pi-color-foregroundMuted, #9aa0a6);font-size:var(--pi-font-size-xs)}._stateError_14c2k_89{padding:8px;color:var(--pi-color-danger, #e5534b);font-size:var(--pi-font-size-xs)}._commandContent_14c2k_99{max-width:420px}._commandList_14c2k_102{display:flex;flex-direction:column;gap:2px}._commandItem_14c2k_107{flex-direction:column;align-items:stretch;gap:4px;padding:8px 10px}._commandItem_14c2k_107:hover{background:color-mix(in srgb,var(--pi-color-surfaceHover, #1e2124) 55%,transparent)}._commandItem_14c2k_107._itemActive_14c2k_54{background:var(--pi-color-surfaceSunken, #111);box-shadow:inset 2px 0 0 var(--pi-color-accent, #2e5cb8);border-radius:0}._commandItemHeader_14c2k_140{display:flex;align-items:center;justify-content:space-between;gap:8px;width:100%}._commandItemHeader_14c2k_140 ._label_14c2k_67{flex:1;min-width:0;font-size:var(--pi-font-size-sm);font-weight:600;color:var(--pi-color-foreground, #fafafa)}._commandKindBadge_14c2k_154{flex-shrink:0;display:inline-flex;align-items:center;padding:0 4px;border-radius:9999px;border:1px solid var(--pi-color-border, #3f3f46);background:var(--pi-color-surface2, #27272a);color:var(--pi-color-foregroundMuted, #9aa0a6);font-size:var(--pi-font-size-4xs);font-weight:600;text-transform:uppercase;letter-spacing:.02em;white-space:nowrap;line-height:1.5}._commandKindExtension_14c2k_173{background:color-mix(in srgb,var(--pi-color-accent, #2e5cb8) 18%,transparent);border-color:color-mix(in srgb,var(--pi-color-accent, #2e5cb8) 45%,transparent);color:var(--pi-color-accent, #2e5cb8)}._commandKindPrompt_14c2k_178{background:color-mix(in srgb,var(--pi-color-statusSuccess, #16a34a) 18%,transparent);border-color:color-mix(in srgb,var(--pi-color-statusSuccess, #16a34a) 45%,transparent);color:var(--pi-color-statusSuccess, #16a34a)}._commandKindSkill_14c2k_183{background:color-mix(in srgb,var(--pi-color-statusMerged, #9333ea) 18%,transparent);border-color:color-mix(in srgb,var(--pi-color-statusMerged, #9333ea) 45%,transparent);color:var(--pi-color-statusMerged, #9333ea)}._commandDescription_14c2k_188{display:-webkit-box;-webkit-box-orient:vertical;-webkit-line-clamp:2;line-clamp:2;overflow:hidden;text-overflow:ellipsis;white-space:normal;line-height:1.4;font-size:var(--pi-font-size-xs);color:var(--pi-color-foregroundMuted, #9aa0a6)}._statusBar_1tlwk_1{height:35px;width:100%;flex-shrink:0;display:flex;align-items:center;gap:2px;padding:0 12px;overflow-x:auto;border-top:1px solid var(--pi-color-border, #353b46);background:var(--pi-color-surface, #16181a);font-size:var(--pi-font-size-xs);color:var(--pi-color-foreground, #e4e6eb);white-space:nowrap}._segmentGroup_1tlwk_16{display:flex;align-items:center}._chevron_1tlwk_20{color:var(--pi-color-border, #353b46);margin:0 4px;flex-shrink:0}._segment_1tlwk_16{display:flex;align-items:center;gap:6px;padding:2px 8px;border-radius:4px;background:var(--pi-color-surfaceRaised, #1c1f22)}._icon_1tlwk_33{display:flex;align-items:center;color:var(--pi-color-foregroundMuted, #7a8394);flex-shrink:0}._modelSegment_1tlwk_39{display:flex;align-items:center;gap:5px;padding:2px 6px 2px 8px;border-radius:4px;border:1px solid var(--pi-color-border, #353b46);background:var(--pi-color-surfaceRaised, #1c1f22);color:inherit;font:inherit;cursor:pointer}._modelSegment_1tlwk_39:hover:not(:disabled){background:var(--pi-color-surfaceHover, #23262b);border-color:var(--pi-color-foregroundMuted, #7a8394)}._modelSegment_1tlwk_39[data-state=open]{background:var(--pi-color-surfaceHover, #23262b);border-color:var(--pi-color-accent, #2e5cb8)}._modelSegment_1tlwk_39:disabled{cursor:default;opacity:.6}._modelChevron_1tlwk_63{color:var(--pi-color-foregroundMuted, #7a8394);flex-shrink:0;transition:transform .15s ease;transform:rotate(180deg)}._modelSegment_1tlwk_39[data-state=open] ._modelChevron_1tlwk_63{transform:rotate(0)}._text_1tlwk_74{overflow:hidden;text-overflow:ellipsis;max-width:320px}._wrapper_oygyv_3{display:inline-flex;align-items:center;gap:8px;cursor:pointer;font-family:var(--pi-font-ui, system-ui);font-size:var(--pi-font-size-md);color:var(--pi-color-foreground, #fafafa)}._wrapper_oygyv_3[data-disabled=true]{opacity:.5;pointer-events:none}._box_oygyv_18{width:16px;height:16px;border-radius:var(--pi-radius-sm, 3px);border:1.5px solid var(--pi-color-border, #3f3f46);background-color:transparent;display:flex;align-items:center;justify-content:center;transition:background-color .1s,border-color .1s;flex-shrink:0}._box_oygyv_18[data-checked=true]{background-color:var(--pi-color-accent, #2e5cb8);border-color:var(--pi-color-accent, #2e5cb8)}._checkmark_oygyv_38{color:var(--pi-color-accentForeground, #ffffff)}._nativeInput_oygyv_43{position:absolute;width:1px;height:1px;padding:0;margin:-1px;overflow:hidden;clip:rect(0,0,0,0);border:0}._select_1vd81_3{-webkit-appearance:none;-moz-appearance:none;appearance:none;background-color:var(--pi-color-surface1, #18181b);border:1px solid var(--pi-color-border, #3f3f46);border-radius:var(--pi-radius-base, 4px);padding:8px 32px 8px 10px;font-family:var(--pi-font-ui, system-ui);font-size:var(--pi-font-size-md);color:var(--pi-color-foreground, #fafafa);width:100%;outline:none;transition:border-color .1s;cursor:pointer;background-image:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='12' height='12' fill='%23a1a1aa' viewBox='0 0 24 24'%3E%3Cpath d='M6 9l6 6 6-6'/%3E%3C/svg%3E");background-repeat:no-repeat;background-position:right 10px center}._select_1vd81_3:focus{border-color:var(--pi-color-accent, #2e5cb8)}._select_1vd81_3:disabled{opacity:.5;cursor:not-allowed}._comboboxWrapper_1vd81_31{position:relative;width:100%}._comboboxInput_1vd81_36{width:100%;background-color:var(--pi-color-surface1, #18181b);border:1px solid var(--pi-color-border, #3f3f46);border-radius:var(--pi-radius-base, 4px);padding:8px 10px;font-family:var(--pi-font-ui, system-ui);font-size:var(--pi-font-size-md);color:var(--pi-color-foreground, #fafafa);outline:none;box-sizing:border-box}._comboboxInput_1vd81_36:focus{border-color:var(--pi-color-accent, #2e5cb8)}._comboboxList_1vd81_53{position:absolute;top:100%;left:0;right:0;z-index:80;max-height:200px;overflow-y:auto;background-color:var(--pi-color-surface1, #18181b);border:1px solid var(--pi-color-border, #3f3f46);border-radius:var(--pi-radius-base, 4px);margin-top:4px;padding:4px;box-shadow:var(--pi-shadow-md, 0 4px 12px rgba(0, 0, 0, .4))}._comboboxOption_1vd81_69{padding:6px 8px;border-radius:var(--pi-radius-sm, 3px);font-size:var(--pi-font-size-md);font-family:var(--pi-font-ui, system-ui);color:var(--pi-color-foreground, #fafafa);cursor:pointer;background:none;border:none;width:100%;text-align:left}._comboboxOption_1vd81_69:hover,._comboboxOptionHighlighted_1vd81_83{background-color:var(--pi-color-surface2, #27272a)}._overlay_1aujk_1{position:fixed;top:0;right:0;bottom:0;left:0;background:#0009;z-index:100}._contentWrapper_1aujk_7{position:fixed;top:0;right:0;bottom:0;left:0;z-index:101;display:flex;align-items:center;justify-content:center;pointer-events:none}._dialog_1aujk_16{pointer-events:auto;width:500px;max-width:90vw;max-height:70vh;background:var(--pi-color-surface, #16181a);border:1px solid var(--pi-color-border, #353b46);border-radius:var(--pi-radius-lg, 8px);display:flex;flex-direction:column;box-shadow:0 8px 32px #00000080}._header_1aujk_28{padding:12px 14px;border-bottom:1px solid var(--pi-color-border, #353b46);display:flex;align-items:center;gap:8px;flex-shrink:0}._title_1aujk_36{font-size:var(--pi-font-size-sm);margin:0;flex:1;color:var(--pi-color-foreground, #fafafa);font-weight:600}._closeBtn_1aujk_43{display:flex;align-items:center;background:none;border:none;color:var(--pi-color-foregroundMuted, #9aa0a6);cursor:pointer;padding:4px;border-radius:4px}._closeBtn_1aujk_43:hover{background:var(--pi-color-surfaceHover, #1e2124);color:var(--pi-color-foreground, #fafafa)}._body_1aujk_57{flex:1;display:flex;flex-direction:column;min-height:0}._footer_1aujk_63{padding:10px 14px;border-top:1px solid var(--pi-color-border, #353b46);display:flex;align-items:center;gap:8px;justify-content:flex-end;flex-shrink:0}._bare_1aujk_72{border:none;background:transparent;box-shadow:none;position:relative}._bareBody_1aujk_78{border-radius:var(--pi-radius-lg, 8px);overflow:hidden}._bareCloseBtn_1aujk_82{position:absolute;top:-12px;right:-12px;display:flex;align-items:center;justify-content:center;width:28px;height:28px;background:var(--pi-color-surface, #16181a);border:1px solid var(--pi-color-border, #353b46);border-radius:50%;color:var(--pi-color-foregroundMuted, #9aa0a6);cursor:pointer}._bareCloseBtn_1aujk_82:hover{background:var(--pi-color-surfaceHover, #1e2124);color:var(--pi-color-foreground, #fafafa)}._visuallyHidden_1aujk_101{position:absolute;width:1px;height:1px;overflow:hidden;clip:rect(0,0,0,0);white-space:nowrap}._handle_1ocv1_1{position:absolute;top:0;bottom:0;width:5px;cursor:col-resize;z-index:5;background:transparent;transition:background .12s ease}._handle_1ocv1_1:hover,._handle_1ocv1_1:active{background:var(--pi-color-accent, #2e5cb8)}._pathRow_kzfmp_1{padding:8px 14px;display:flex;align-items:center;gap:6px;border-bottom:1px solid var(--pi-color-border, #353b46);flex-shrink:0}._pathInput_kzfmp_9{flex:1;font-size:var(--pi-font-size-xs)}._createRow_kzfmp_13{padding:6px 14px;display:flex;align-items:center;gap:6px;border-bottom:1px solid var(--pi-color-border, #353b46);flex-shrink:0}._createInput_kzfmp_21{flex:1;font-size:var(--pi-font-size-xs)}._createError_kzfmp_25{padding:4px 14px 6px;font-size:var(--pi-font-size-2xs);color:var(--pi-color-danger, #e5534b)}._list_kzfmp_30{flex:1;overflow-y:auto;padding:4px 0;min-height:200px;max-height:400px}._item_kzfmp_37{padding:6px 14px;cursor:pointer;display:flex;align-items:center;gap:8px;font-size:var(--pi-font-size-xs);color:var(--pi-color-foreground, #fafafa)}._item_kzfmp_37:hover{background:var(--pi-color-surfaceHover, #1e2124)}._name_kzfmp_49{white-space:nowrap;overflow:hidden;text-overflow:ellipsis}._emptyState_kzfmp_54{color:var(--pi-color-foregroundMuted, #9aa0a6);font-size:var(--pi-font-size-xs);text-align:center;padding:20px}._shell_1ilqr_1{display:flex;flex-direction:column;height:100vh;min-height:0}._main_1ilqr_7{display:flex;flex:1 1 auto;min-height:0;overflow:hidden}._sidebarLeft_1ilqr_13{position:relative;flex-shrink:0;border-right:1px solid var(--pi-color-border, #353b46);display:flex;flex-direction:column;min-width:0;background:var(--pi-color-surfaceSidebar, #141716)}._leftHandle_1ilqr_25{right:-3px}._center_1ilqr_28{flex:1 1 auto;display:flex;flex-direction:column;min-width:0;min-height:0}._sidebarRight_1ilqr_35{position:relative;flex-shrink:0;border-left:1px solid var(--pi-color-border, #353b46);display:flex;flex-direction:column;min-width:0}._rightHandle_1ilqr_43{left:-3px}
|
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
import{r as d,j as s}from"./vendor-react-CWo7Do4s.js";import{c as b}from"./vendor-highlight-Efc6A-g6.js";import{n as I,c as x,d as j,a as f,j as v,k as _,l as w,b as S,h as E,S as T,m as M}from"./index-CEP1cIKf.js";import{M as C,r as y}from"./vendor-markdown-YvkQLm_s.js";const k="github-dark";let m=null;const g=new Set(["plaintext"]);function H(){return m||(m=b({themes:[k],langs:["plaintext"]})),m}async function N(i,e){if(g.has(e))return e;try{return await i.loadLanguage(e),g.add(e),e}catch{return"plaintext"}}async function F(i,e){const t=await H(),n=await N(t,e);return t.codeToHtml(i,{lang:n,theme:k})}const L="_prose_o2vtj_1",U="_inlineCode_o2vtj_32",z="_inlineImage_o2vtj_58",R="_inlineImageSkeleton_o2vtj_67",P="_inlineImageFallback_o2vtj_78",c={prose:L,inlineCode:U,inlineImage:z,inlineImageSkeleton:R,inlineImageFallback:P},W=new Set(["http:","https:","data:","blob:"]),$=/^([a-zA-Z][a-zA-Z0-9+.-]*):/;function A(i,e,t){const n=i.trim();if(!n)return{kind:"unresolvable"};const a=n.split(/[?#]/,1)[0];if(!a)return{kind:"unresolvable"};const l=$.exec(a);if(l){const u=`${l[1].toLowerCase()}:`;return W.has(u)?{kind:"remote"}:{kind:"unresolvable"}}let o;return a.startsWith("/")?o=a:a==="~"||a.startsWith("~/")?o=t?I(a,t):null:o=x(a,e??""),o?j(o)!=="image"?{kind:"unresolvable"}:{kind:"local",path:o}:{kind:"unresolvable"}}function V(i,e,t,n){return i.kind==="remote"?{kind:"remote",src:t||"",alt:n}:i.kind==="unresolvable"?{kind:"unresolvable",fallbackText:n||t||"(image)"}:e.status==="loading"||e.status==="idle"?{kind:"loading"}:e.status==="ready"?{kind:"ready",objectUrl:e.objectUrl,alt:n,path:i.path}:{kind:"error",fallbackText:n||i.path||"(image)"}}function Z(i,e,t){if(!i||!e){t({status:"idle"});return}let n=!1;return t({status:"loading"}),v(i,e).then(a=>{n||t({status:"ready",objectUrl:a.objectUrl})}).catch(a=>{n||t({status:"error",message:a instanceof Error?a.message:String(a)})}),()=>{n=!0,_(i)}}function q(i){const e=f(l=>l.client),t=f(l=>l.daemon),[n,a]=d.useState({status:"idle"});return d.useEffect(()=>Z(i,e&&t?o=>w(t).download(o):null,a),[e,t,i]),n}const B=d.memo(function({src:e,alt:t,assetBase:n}){const a=S(),l=E(p=>p.open),o=d.useMemo(()=>A(e||"",n,a),[e,n,a]),u=q(o.kind==="local"?o.path:null),r=V(o,u,e,t);if(r.kind==="remote")return s.jsx("img",{src:r.src,alt:r.alt,className:c.inlineImage});if(r.kind==="unresolvable"||r.kind==="error")return s.jsx("code",{className:c.inlineImageFallback,children:r.fallbackText});if(r.kind==="loading")return s.jsx("div",{className:c.inlineImageSkeleton,children:s.jsx(T,{size:"sm"})});const h=()=>{l({id:M.file(r.path),kind:"file",label:r.path.split("/").pop()||r.path,closable:!0,data:{path:r.path},workspaceCwd:n||"~"})};return s.jsx("img",{src:r.objectUrl,alt:r.alt,className:c.inlineImage,title:r.path,onClick:h,style:{cursor:"pointer"}})});function D({language:i,code:e}){const[t,n]=d.useState(null);return d.useEffect(()=>{let a=!1;return F(e,i).then(l=>{a||n(l)}),()=>{a=!0}},[e,i]),t?s.jsx("div",{className:c.prose,dangerouslySetInnerHTML:{__html:t}}):s.jsx("pre",{children:s.jsx("code",{children:e})})}function G({className:i,children:e,...t}){const n=/language-(\w+)/.exec(i??""),a=!!n,l=String(e).replace(/\n$/,"");return a&&n?s.jsx(D,{language:n[1]??"plaintext",code:l}):s.jsx("code",{className:c.inlineCode,...t,children:e})}const X=d.memo(function({text:e,assetBase:t=null}){return s.jsx("div",{className:c.prose,children:s.jsx(C,{remarkPlugins:[y],components:{code:G,img:n=>s.jsx(B,{...n,assetBase:t})},children:e})})});export{X as M};
|
|
2
|
+
//# sourceMappingURL=markdown-9_X86EBj.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"markdown-BA3kiSJG.js","sources":["../../../src/timeline/highlight.ts","../../../src/timeline/image-src.ts","../../../src/timeline/inline-image-view.ts","../../../src/hooks/use-inline-image.ts","../../../src/timeline/InlineImage.tsx","../../../src/timeline/markdown.tsx"],"sourcesContent":["/**\n * Shiki wrapper + lang-from-path map. Replaces the POC's CDN `highlight.js`\n * (POC_TO_APP_PLAN_UI.md §2, §4.8). Grammars/themes are loaded lazily and cached — the\n * highlighter is not paid for until a code block/file view actually renders.\n */\n\nimport { createHighlighter, type Highlighter } from \"shiki\";\n\n/** POC `getLangFromPath` extension → language map, ported verbatim. */\nconst EXT_TO_LANG: Record<string, string> = {\n js: \"javascript\",\n ts: \"typescript\",\n jsx: \"javascript\",\n tsx: \"typescript\",\n py: \"python\",\n rb: \"ruby\",\n rs: \"rust\",\n go: \"go\",\n java: \"java\",\n c: \"c\",\n cpp: \"cpp\",\n h: \"c\",\n hpp: \"cpp\",\n cs: \"csharp\",\n html: \"html\",\n css: \"css\",\n scss: \"scss\",\n json: \"json\",\n yaml: \"yaml\",\n yml: \"yaml\",\n toml: \"toml\",\n xml: \"xml\",\n md: \"markdown\",\n sh: \"bash\",\n bash: \"bash\",\n sql: \"sql\",\n swift: \"swift\",\n kt: \"kotlin\",\n dart: \"dart\",\n vue: \"xml\",\n svelte: \"xml\",\n};\n\nexport function langFromPath(path: string): string {\n const ext = path.split(\".\").pop()?.toLowerCase() ?? \"\";\n return EXT_TO_LANG[ext] ?? \"plaintext\";\n}\n\nconst THEME = \"github-dark\";\n\nlet highlighterPromise: Promise<Highlighter> | null = null;\nconst loadedLangs = new Set<string>([\"plaintext\"]);\n\nfunction getHighlighter(): Promise<Highlighter> {\n if (!highlighterPromise) {\n highlighterPromise = createHighlighter({ themes: [THEME], langs: [\"plaintext\"] });\n }\n return highlighterPromise;\n}\n\nasync function ensureLang(highlighter: Highlighter, lang: string): Promise<string> {\n if (loadedLangs.has(lang)) return lang;\n try {\n await highlighter.loadLanguage(lang as never);\n loadedLangs.add(lang);\n return lang;\n } catch {\n return \"plaintext\"; // unknown grammar to Shiki — fall back rather than throw\n }\n}\n\n/** Highlight `code` for `lang` (or a path via `langFromPath`) to sanitized HTML. */\nexport async function highlightToHtml(code: string, lang: string): Promise<string> {\n const highlighter = await getHighlighter();\n const resolved = await ensureLang(highlighter, lang);\n return highlighter.codeToHtml(code, { lang: resolved, theme: THEME });\n}\n","/**\n * Markdown image source classification (features/inline-image-rendering.md § Public Contract →\n * Markdown image source classification, § Asset base). The single gate every `` in a\n * rendered chat message passes through before any network request is even considered — deciding\n * remote (render directly), local (fetch via the daemon's file-transfer path, task-003), or\n * unresolvable (render as plain fallback text, never attempt a request).\n *\n * Pure: no store/hook/network imports, so this file needs no React or client mocks to test.\n */\n\nimport { detectViewerKind } from \"@pi-studio-ui/features/files/viewer-registry.js\";\nimport { normalizeCwd } from \"@pi-studio-ui/features/sessions/workspace-grouping.js\";\nimport { resolveWorkspacePath } from \"@pi-studio-ui/lib/paths.js\";\n\nexport type ImageSrcClassification =\n | { kind: \"remote\" }\n | { kind: \"local\"; path: string }\n | { kind: \"unresolvable\" };\n\nconst REMOTE_SCHEMES = new Set([\"http:\", \"https:\", \"data:\", \"blob:\"]);\n\n/** Matches a leading `scheme:` (e.g. `http:`, `file:`, `mailto:`) — not a Windows drive letter\n * (`C:\\...`) or a bare `:` with no scheme name. */\nconst SCHEME_RE = /^([a-zA-Z][a-zA-Z0-9+.-]*):/;\n\n/**\n * Classifies a markdown image `src`. `base` is the asset base (absolute, tilde-normalized) or\n * `null` when unknown; `homeDir` may be `null` when the daemon's home directory hasn't been\n * learned yet. Order matters — this mirrors the scope's classification table exactly:\n *\n * 1. empty/whitespace → unresolvable\n * 2. `http:`/`https:`/`data:`/`blob:` → remote\n * 3. any other `scheme:` prefix (including `file:`) → unresolvable\n * 4. `/…` → candidate local path as-is\n * 5. `~`/`~/…` → expand against `homeDir` (unknown home dir → unresolvable)\n * 6. `./…`, `../…`, bare relative → resolve against `base` (no base → unresolvable)\n * 7. final gate: the candidate must be an image per `detectViewerKind`, else unresolvable\n */\nexport function classifyImageSrc(\n src: string,\n base: string | null,\n homeDir: string | null,\n): ImageSrcClassification {\n const trimmed = src.trim();\n if (!trimmed) return { kind: \"unresolvable\" };\n\n // Markdown may carry a title/version via `#fragment`/`?query`; strip both before classifying so\n // a trailing `?` never defeats the extension gate below.\n const stripped = trimmed.split(/[?#]/, 1)[0]!;\n if (!stripped) return { kind: \"unresolvable\" };\n\n const schemeMatch = SCHEME_RE.exec(stripped);\n if (schemeMatch) {\n const scheme = `${schemeMatch[1]!.toLowerCase()}:`;\n return REMOTE_SCHEMES.has(scheme) ? { kind: \"remote\" } : { kind: \"unresolvable\" };\n }\n\n let candidate: string | null;\n if (stripped.startsWith(\"/\")) {\n candidate = stripped;\n } else if (stripped === \"~\" || stripped.startsWith(\"~/\")) {\n candidate = homeDir ? normalizeCwd(stripped, homeDir) : null;\n } else {\n candidate = resolveWorkspacePath(stripped, base ?? \"\");\n }\n\n if (!candidate) return { kind: \"unresolvable\" };\n if (detectViewerKind(candidate) !== \"image\") return { kind: \"unresolvable\" };\n return { kind: \"local\", path: candidate };\n}\n","/**\n * Pure, testable logic for rendering inline images — extracted from the component\n * so tests can verify branch logic without JSX rendering (mirror of molecule-reload.ts,\n * text-viewer-state.ts; see AGENTS.md testing conventions).\n *\n * Returns a discriminated union describing what to render: the component switches\n * on it to decide remote passthrough, skeleton, ready image, or text fallback.\n */\n\nimport type { ImageSrcClassification } from \"./image-src.js\";\nimport type { InlineImageState } from \"@pi-studio-ui/hooks/use-inline-image.js\";\n\nexport type InlineImageView =\n | { kind: \"remote\"; src: string; alt?: string }\n | { kind: \"unresolvable\"; fallbackText: string }\n | { kind: \"loading\" }\n | { kind: \"ready\"; objectUrl: string; alt?: string; path: string }\n | { kind: \"error\"; fallbackText: string };\n\n/**\n * Decides what to render for an inline image given its classification and loading state.\n * Pure: no hooks, no store access — all state passed in as arguments.\n */\nexport function selectInlineImageView(\n classification: ImageSrcClassification,\n imageState: InlineImageState,\n src: string | undefined,\n alt: string | undefined,\n): InlineImageView {\n if (classification.kind === \"remote\") {\n return { kind: \"remote\", src: src || \"\", alt };\n }\n\n if (classification.kind === \"unresolvable\") {\n const fallbackText = alt || src || \"(image)\";\n return { kind: \"unresolvable\", fallbackText };\n }\n\n // classification.kind === \"local\"\n if (imageState.status === \"loading\" || imageState.status === \"idle\") {\n return { kind: \"loading\" };\n }\n\n if (imageState.status === \"ready\") {\n return { kind: \"ready\", objectUrl: imageState.objectUrl, alt, path: classification.path };\n }\n\n // imageState.status === \"error\"\n const fallbackText = alt || classification.path || \"(image)\";\n return { kind: \"error\", fallbackText };\n}\n","/**\n * `use-inline-image` — fetches (via the shared ref-counted `inline-image-cache`) and hands back\n * an object URL for an inline chat image (features/inline-image-rendering.md § Inline image fetch\n * + cache). Consumed by the markdown `img` node override (task-004) once a `classifyImageSrc`\n * result is `local`.\n *\n * Deliberately NOT a TanStack Query hook, and therefore no `rpcKeys` entry: the whole point of\n * `inline-image-cache.ts` is a retention policy (revoke only on LRU eviction, never on unmount)\n * that Query's cache cannot express. Do not \"fix\" this into a `useQuery` — see that module's\n * header for why.\n *\n * `loadInlineImage` is the actual effect body, extracted for direct unit testing without\n * rendering — this package has no jsdom/React-Testing-Library environment (`AGENTS.md`'s testing\n * convention; mirrors `use-file-watch.ts`'s `watchFile` extraction).\n */\n\nimport { useEffect, useState } from \"react\";\nimport { useConnectionStore } from \"@pi-studio-ui/lib/connection/connection-store.js\";\nimport { acquireInlineImage, releaseInlineImage } from \"@pi-studio-ui/lib/inline-image-cache.js\";\nimport { transferFor } from \"./file-transfer-instance.js\";\n\nexport type InlineImageState =\n | { status: \"idle\" } // no client yet, or path is null\n | { status: \"loading\" }\n | { status: \"ready\"; objectUrl: string }\n | { status: \"error\"; message: string };\n\n/**\n * Runs one effect cycle: `download === null` (no live connection, or no path) is the idle case —\n * nothing to acquire, nothing to clean up. Otherwise acquires `path`, reports the loading →\n * ready/error transition via `onStateChange`, and returns a cleanup that releases the path and\n * ignores a resolution that lands after it (the `cancelled` flag pattern used across the existing\n * hooks, e.g. `use-checkout-status.ts`).\n */\nexport function loadInlineImage(\n path: string | null,\n download: ((path: string) => Promise<{ bytes: Uint8Array; mimeType?: string }>) | null,\n onStateChange: (state: InlineImageState) => void,\n): (() => void) | void {\n if (!path || !download) {\n onStateChange({ status: \"idle\" });\n return;\n }\n\n let cancelled = false;\n onStateChange({ status: \"loading\" });\n\n acquireInlineImage(path, download)\n .then((entry) => {\n if (!cancelled) onStateChange({ status: \"ready\", objectUrl: entry.objectUrl });\n })\n .catch((error: unknown) => {\n if (!cancelled) {\n onStateChange({\n status: \"error\",\n message: error instanceof Error ? error.message : String(error),\n });\n }\n });\n\n return () => {\n cancelled = true;\n releaseInlineImage(path);\n };\n}\n\nexport function useInlineImage(path: string | null): InlineImageState {\n const client = useConnectionStore((s) => s.client);\n const daemon = useConnectionStore((s) => s.daemon);\n const [state, setState] = useState<InlineImageState>({ status: \"idle\" });\n\n useEffect(() => {\n const download = client && daemon ? (p: string) => transferFor(daemon).download(p) : null;\n return loadInlineImage(path, download, setState);\n }, [client, daemon, path]);\n\n return state;\n}\n","/**\n * `` renderer for finalized assistant markdown (features/inline-image-rendering.md §\n * Behavior & Algorithms → Render pipeline). Handles remote passthrough, local file fetch via\n * useInlineImage (task-003), classification (task-002), and click-to-open file tab.\n *\n * Props are optional (react-markdown may omit them) and must be handled defensively.\n */\n\nimport { memo, useMemo } from \"react\";\nimport { classifyImageSrc } from \"./image-src.js\";\nimport { selectInlineImageView } from \"./inline-image-view.js\";\nimport { useInlineImage } from \"@pi-studio-ui/hooks/use-inline-image.js\";\nimport { useHomeDir } from \"@pi-studio-ui/hooks/use-home-dir.js\";\nimport { useTabStore, tabIds } from \"@pi-studio-ui/stores/tab-store.js\";\nimport { Spinner } from \"@pi-studio-ui/components/primitives/Spinner.js\";\nimport styles from \"./markdown.module.css\";\n\nexport interface InlineImageProps {\n src?: string;\n alt?: string;\n assetBase: string | null;\n}\n\nexport const InlineImage = memo(function InlineImage({ src, alt, assetBase }: InlineImageProps) {\n const homeDir = useHomeDir();\n const openTab = useTabStore((s) => s.open);\n\n // Classify the source once at render time.\n const classification = useMemo(\n () => classifyImageSrc(src || \"\", assetBase, homeDir),\n [src, assetBase, homeDir],\n );\n\n // For local images, fetch and track state.\n const imageState = useInlineImage(classification.kind === \"local\" ? classification.path : null);\n\n // Decide what to render.\n const view = selectInlineImageView(classification, imageState, src, alt);\n\n // Remote images: pass through unchanged (what react-markdown's default would do).\n if (view.kind === \"remote\") {\n return <img src={view.src} alt={view.alt} className={styles.inlineImage} />;\n }\n\n // Unresolvable or error: render text fallback in inline monospace.\n if (view.kind === \"unresolvable\" || view.kind === \"error\") {\n return <code className={styles.inlineImageFallback}>{view.fallbackText}</code>;\n }\n\n // Loading or idle: skeleton.\n if (view.kind === \"loading\") {\n return (\n <div className={styles.inlineImageSkeleton}>\n <Spinner size=\"sm\" />\n </div>\n );\n }\n\n // Ready: render the fetched image with click-to-open handler.\n const handleClick = () => {\n openTab({\n id: tabIds.file(view.path),\n kind: \"file\",\n label: view.path.split(\"/\").pop() || view.path,\n closable: true,\n data: { path: view.path },\n workspaceCwd: assetBase || \"~\",\n });\n };\n\n return (\n <img\n src={view.objectUrl}\n alt={view.alt}\n className={styles.inlineImage}\n title={view.path}\n onClick={handleClick}\n style={{ cursor: \"pointer\" }}\n />\n );\n});\n","/**\n * react-markdown + remark-gfm rendering, replacing the POC's CDN `marked` + `innerHTML`\n * (POC_TO_APP_PLAN_UI.md §4.8). Sanitized by default — react-markdown never injects raw HTML.\n * Fenced code blocks highlight asynchronously via Shiki (`highlight.ts`).\n */\n\nimport { memo, useEffect, useState, type ComponentPropsWithoutRef } from \"react\";\nimport ReactMarkdown from \"react-markdown\";\nimport remarkGfm from \"remark-gfm\";\nimport { highlightToHtml } from \"./highlight.js\";\nimport styles from \"./markdown.module.css\";\nimport { InlineImage } from \"./InlineImage.js\";\n\ninterface CodeBlockProps {\n language: string;\n code: string;\n}\n\nfunction CodeBlock({ language, code }: CodeBlockProps) {\n const [html, setHtml] = useState<string | null>(null);\n\n useEffect(() => {\n let cancelled = false;\n void highlightToHtml(code, language).then((result) => {\n if (!cancelled) setHtml(result);\n });\n return () => {\n cancelled = true;\n };\n }, [code, language]);\n\n if (html) {\n // Shiki's output is generated HTML from a trusted local highlighter (no user HTML is ever\n // injected) — the only risk is `code`, which Shiki escapes internally before tokenizing.\n return <div className={styles.prose} dangerouslySetInnerHTML={{ __html: html }} />;\n }\n return (\n <pre>\n <code>{code}</code>\n </pre>\n );\n}\n\ntype MarkdownCodeProps = ComponentPropsWithoutRef<\"code\"> & { className?: string };\n\nfunction CodeRenderer({ className, children, ...rest }: MarkdownCodeProps) {\n const match = /language-(\\w+)/.exec(className ?? \"\");\n const isBlock = Boolean(match);\n const code = String(children).replace(/\\n$/, \"\");\n if (isBlock && match) {\n return <CodeBlock language={match[1] ?? \"plaintext\"} code={code} />;\n }\n return (\n <code className={styles.inlineCode} {...rest}>\n {children}\n </code>\n );\n}\n\nexport interface MarkdownProps {\n text: string;\n assetBase?: string | null;\n}\n\n/** Renders assistant/tool markdown text. Memoized — text is immutable once a turn finalizes. */\nexport const Markdown = memo(function Markdown({ text, assetBase = null }: MarkdownProps) {\n return (\n <div className={styles.prose}>\n <ReactMarkdown\n remarkPlugins={[remarkGfm]}\n components={{\n code: CodeRenderer,\n img: (props) => <InlineImage {...props} assetBase={assetBase} />,\n }}\n >\n {text}\n </ReactMarkdown>\n </div>\n );\n});\n"],"names":["THEME","highlighterPromise","loadedLangs","getHighlighter","createHighlighter","ensureLang","highlighter","lang","highlightToHtml","code","resolved","REMOTE_SCHEMES","SCHEME_RE","classifyImageSrc","src","base","homeDir","trimmed","stripped","schemeMatch","scheme","candidate","normalizeCwd","resolveWorkspacePath","detectViewerKind","selectInlineImageView","classification","imageState","alt","fallbackText","loadInlineImage","path","download","onStateChange","cancelled","acquireInlineImage","entry","error","releaseInlineImage","useInlineImage","client","useConnectionStore","s","daemon","state","setState","useState","useEffect","p","transferFor","InlineImage","memo","assetBase","useHomeDir","openTab","useTabStore","useMemo","view","jsx","styles","Spinner","handleClick","tabIds","CodeBlock","language","html","setHtml","result","CodeRenderer","className","children","rest","match","isBlock","Markdown","text","ReactMarkdown","remarkGfm","props"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"markdown-9_X86EBj.js","sources":["../../../src/timeline/highlight.ts","../../../src/timeline/image-src.ts","../../../src/timeline/inline-image-view.ts","../../../src/hooks/use-inline-image.ts","../../../src/timeline/InlineImage.tsx","../../../src/timeline/markdown.tsx"],"sourcesContent":["/**\n * Shiki wrapper + lang-from-path map. Replaces the POC's CDN `highlight.js`\n * (POC_TO_APP_PLAN_UI.md §2, §4.8). Grammars/themes are loaded lazily and cached — the\n * highlighter is not paid for until a code block/file view actually renders.\n */\n\nimport { createHighlighter, type Highlighter } from \"shiki\";\n\n/** POC `getLangFromPath` extension → language map, ported verbatim. */\nconst EXT_TO_LANG: Record<string, string> = {\n js: \"javascript\",\n ts: \"typescript\",\n jsx: \"javascript\",\n tsx: \"typescript\",\n py: \"python\",\n rb: \"ruby\",\n rs: \"rust\",\n go: \"go\",\n java: \"java\",\n c: \"c\",\n cpp: \"cpp\",\n h: \"c\",\n hpp: \"cpp\",\n cs: \"csharp\",\n html: \"html\",\n css: \"css\",\n scss: \"scss\",\n json: \"json\",\n yaml: \"yaml\",\n yml: \"yaml\",\n toml: \"toml\",\n xml: \"xml\",\n md: \"markdown\",\n sh: \"bash\",\n bash: \"bash\",\n sql: \"sql\",\n swift: \"swift\",\n kt: \"kotlin\",\n dart: \"dart\",\n vue: \"xml\",\n svelte: \"xml\",\n};\n\nexport function langFromPath(path: string): string {\n const ext = path.split(\".\").pop()?.toLowerCase() ?? \"\";\n return EXT_TO_LANG[ext] ?? \"plaintext\";\n}\n\nconst THEME = \"github-dark\";\n\nlet highlighterPromise: Promise<Highlighter> | null = null;\nconst loadedLangs = new Set<string>([\"plaintext\"]);\n\nfunction getHighlighter(): Promise<Highlighter> {\n if (!highlighterPromise) {\n highlighterPromise = createHighlighter({ themes: [THEME], langs: [\"plaintext\"] });\n }\n return highlighterPromise;\n}\n\nasync function ensureLang(highlighter: Highlighter, lang: string): Promise<string> {\n if (loadedLangs.has(lang)) return lang;\n try {\n await highlighter.loadLanguage(lang as never);\n loadedLangs.add(lang);\n return lang;\n } catch {\n return \"plaintext\"; // unknown grammar to Shiki — fall back rather than throw\n }\n}\n\n/** Highlight `code` for `lang` (or a path via `langFromPath`) to sanitized HTML. */\nexport async function highlightToHtml(code: string, lang: string): Promise<string> {\n const highlighter = await getHighlighter();\n const resolved = await ensureLang(highlighter, lang);\n return highlighter.codeToHtml(code, { lang: resolved, theme: THEME });\n}\n","/**\n * Markdown image source classification (features/inline-image-rendering.md § Public Contract →\n * Markdown image source classification, § Asset base). The single gate every `` in a\n * rendered chat message passes through before any network request is even considered — deciding\n * remote (render directly), local (fetch via the daemon's file-transfer path, task-003), or\n * unresolvable (render as plain fallback text, never attempt a request).\n *\n * Pure: no store/hook/network imports, so this file needs no React or client mocks to test.\n */\n\nimport { detectViewerKind } from \"@pi-studio-ui/features/files/viewer-registry.js\";\nimport { normalizeCwd } from \"@pi-studio-ui/features/sessions/workspace-grouping.js\";\nimport { resolveWorkspacePath } from \"@pi-studio-ui/lib/paths.js\";\n\nexport type ImageSrcClassification =\n | { kind: \"remote\" }\n | { kind: \"local\"; path: string }\n | { kind: \"unresolvable\" };\n\nconst REMOTE_SCHEMES = new Set([\"http:\", \"https:\", \"data:\", \"blob:\"]);\n\n/** Matches a leading `scheme:` (e.g. `http:`, `file:`, `mailto:`) — not a Windows drive letter\n * (`C:\\...`) or a bare `:` with no scheme name. */\nconst SCHEME_RE = /^([a-zA-Z][a-zA-Z0-9+.-]*):/;\n\n/**\n * Classifies a markdown image `src`. `base` is the asset base (absolute, tilde-normalized) or\n * `null` when unknown; `homeDir` may be `null` when the daemon's home directory hasn't been\n * learned yet. Order matters — this mirrors the scope's classification table exactly:\n *\n * 1. empty/whitespace → unresolvable\n * 2. `http:`/`https:`/`data:`/`blob:` → remote\n * 3. any other `scheme:` prefix (including `file:`) → unresolvable\n * 4. `/…` → candidate local path as-is\n * 5. `~`/`~/…` → expand against `homeDir` (unknown home dir → unresolvable)\n * 6. `./…`, `../…`, bare relative → resolve against `base` (no base → unresolvable)\n * 7. final gate: the candidate must be an image per `detectViewerKind`, else unresolvable\n */\nexport function classifyImageSrc(\n src: string,\n base: string | null,\n homeDir: string | null,\n): ImageSrcClassification {\n const trimmed = src.trim();\n if (!trimmed) return { kind: \"unresolvable\" };\n\n // Markdown may carry a title/version via `#fragment`/`?query`; strip both before classifying so\n // a trailing `?` never defeats the extension gate below.\n const stripped = trimmed.split(/[?#]/, 1)[0]!;\n if (!stripped) return { kind: \"unresolvable\" };\n\n const schemeMatch = SCHEME_RE.exec(stripped);\n if (schemeMatch) {\n const scheme = `${schemeMatch[1]!.toLowerCase()}:`;\n return REMOTE_SCHEMES.has(scheme) ? { kind: \"remote\" } : { kind: \"unresolvable\" };\n }\n\n let candidate: string | null;\n if (stripped.startsWith(\"/\")) {\n candidate = stripped;\n } else if (stripped === \"~\" || stripped.startsWith(\"~/\")) {\n candidate = homeDir ? normalizeCwd(stripped, homeDir) : null;\n } else {\n candidate = resolveWorkspacePath(stripped, base ?? \"\");\n }\n\n if (!candidate) return { kind: \"unresolvable\" };\n if (detectViewerKind(candidate) !== \"image\") return { kind: \"unresolvable\" };\n return { kind: \"local\", path: candidate };\n}\n","/**\n * Pure, testable logic for rendering inline images — extracted from the component\n * so tests can verify branch logic without JSX rendering (mirror of molecule-reload.ts,\n * text-viewer-state.ts; see AGENTS.md testing conventions).\n *\n * Returns a discriminated union describing what to render: the component switches\n * on it to decide remote passthrough, skeleton, ready image, or text fallback.\n */\n\nimport type { ImageSrcClassification } from \"./image-src.js\";\nimport type { InlineImageState } from \"@pi-studio-ui/hooks/use-inline-image.js\";\n\nexport type InlineImageView =\n | { kind: \"remote\"; src: string; alt?: string }\n | { kind: \"unresolvable\"; fallbackText: string }\n | { kind: \"loading\" }\n | { kind: \"ready\"; objectUrl: string; alt?: string; path: string }\n | { kind: \"error\"; fallbackText: string };\n\n/**\n * Decides what to render for an inline image given its classification and loading state.\n * Pure: no hooks, no store access — all state passed in as arguments.\n */\nexport function selectInlineImageView(\n classification: ImageSrcClassification,\n imageState: InlineImageState,\n src: string | undefined,\n alt: string | undefined,\n): InlineImageView {\n if (classification.kind === \"remote\") {\n return { kind: \"remote\", src: src || \"\", alt };\n }\n\n if (classification.kind === \"unresolvable\") {\n const fallbackText = alt || src || \"(image)\";\n return { kind: \"unresolvable\", fallbackText };\n }\n\n // classification.kind === \"local\"\n if (imageState.status === \"loading\" || imageState.status === \"idle\") {\n return { kind: \"loading\" };\n }\n\n if (imageState.status === \"ready\") {\n return { kind: \"ready\", objectUrl: imageState.objectUrl, alt, path: classification.path };\n }\n\n // imageState.status === \"error\"\n const fallbackText = alt || classification.path || \"(image)\";\n return { kind: \"error\", fallbackText };\n}\n","/**\n * `use-inline-image` — fetches (via the shared ref-counted `inline-image-cache`) and hands back\n * an object URL for an inline chat image (features/inline-image-rendering.md § Inline image fetch\n * + cache). Consumed by the markdown `img` node override (task-004) once a `classifyImageSrc`\n * result is `local`.\n *\n * Deliberately NOT a TanStack Query hook, and therefore no `rpcKeys` entry: the whole point of\n * `inline-image-cache.ts` is a retention policy (revoke only on LRU eviction, never on unmount)\n * that Query's cache cannot express. Do not \"fix\" this into a `useQuery` — see that module's\n * header for why.\n *\n * `loadInlineImage` is the actual effect body, extracted for direct unit testing without\n * rendering — this package has no jsdom/React-Testing-Library environment (`AGENTS.md`'s testing\n * convention; mirrors `use-file-watch.ts`'s `watchFile` extraction).\n */\n\nimport { useEffect, useState } from \"react\";\nimport { useConnectionStore } from \"@pi-studio-ui/lib/connection/connection-store.js\";\nimport { acquireInlineImage, releaseInlineImage } from \"@pi-studio-ui/lib/inline-image-cache.js\";\nimport { transferFor } from \"./file-transfer-instance.js\";\n\nexport type InlineImageState =\n | { status: \"idle\" } // no client yet, or path is null\n | { status: \"loading\" }\n | { status: \"ready\"; objectUrl: string }\n | { status: \"error\"; message: string };\n\n/**\n * Runs one effect cycle: `download === null` (no live connection, or no path) is the idle case —\n * nothing to acquire, nothing to clean up. Otherwise acquires `path`, reports the loading →\n * ready/error transition via `onStateChange`, and returns a cleanup that releases the path and\n * ignores a resolution that lands after it (the `cancelled` flag pattern used across the existing\n * hooks, e.g. `use-checkout-status.ts`).\n */\nexport function loadInlineImage(\n path: string | null,\n download: ((path: string) => Promise<{ bytes: Uint8Array; mimeType?: string }>) | null,\n onStateChange: (state: InlineImageState) => void,\n): (() => void) | void {\n if (!path || !download) {\n onStateChange({ status: \"idle\" });\n return;\n }\n\n let cancelled = false;\n onStateChange({ status: \"loading\" });\n\n acquireInlineImage(path, download)\n .then((entry) => {\n if (!cancelled) onStateChange({ status: \"ready\", objectUrl: entry.objectUrl });\n })\n .catch((error: unknown) => {\n if (!cancelled) {\n onStateChange({\n status: \"error\",\n message: error instanceof Error ? error.message : String(error),\n });\n }\n });\n\n return () => {\n cancelled = true;\n releaseInlineImage(path);\n };\n}\n\nexport function useInlineImage(path: string | null): InlineImageState {\n const client = useConnectionStore((s) => s.client);\n const daemon = useConnectionStore((s) => s.daemon);\n const [state, setState] = useState<InlineImageState>({ status: \"idle\" });\n\n useEffect(() => {\n const download = client && daemon ? (p: string) => transferFor(daemon).download(p) : null;\n return loadInlineImage(path, download, setState);\n }, [client, daemon, path]);\n\n return state;\n}\n","/**\n * `` renderer for finalized assistant markdown (features/inline-image-rendering.md §\n * Behavior & Algorithms → Render pipeline). Handles remote passthrough, local file fetch via\n * useInlineImage (task-003), classification (task-002), and click-to-open file tab.\n *\n * Props are optional (react-markdown may omit them) and must be handled defensively.\n */\n\nimport { memo, useMemo } from \"react\";\nimport { classifyImageSrc } from \"./image-src.js\";\nimport { selectInlineImageView } from \"./inline-image-view.js\";\nimport { useInlineImage } from \"@pi-studio-ui/hooks/use-inline-image.js\";\nimport { useHomeDir } from \"@pi-studio-ui/hooks/use-home-dir.js\";\nimport { useTabStore, tabIds } from \"@pi-studio-ui/stores/tab-store.js\";\nimport { Spinner } from \"@pi-studio-ui/components/primitives/Spinner.js\";\nimport styles from \"./markdown.module.css\";\n\nexport interface InlineImageProps {\n src?: string;\n alt?: string;\n assetBase: string | null;\n}\n\nexport const InlineImage = memo(function InlineImage({ src, alt, assetBase }: InlineImageProps) {\n const homeDir = useHomeDir();\n const openTab = useTabStore((s) => s.open);\n\n // Classify the source once at render time.\n const classification = useMemo(\n () => classifyImageSrc(src || \"\", assetBase, homeDir),\n [src, assetBase, homeDir],\n );\n\n // For local images, fetch and track state.\n const imageState = useInlineImage(classification.kind === \"local\" ? classification.path : null);\n\n // Decide what to render.\n const view = selectInlineImageView(classification, imageState, src, alt);\n\n // Remote images: pass through unchanged (what react-markdown's default would do).\n if (view.kind === \"remote\") {\n return <img src={view.src} alt={view.alt} className={styles.inlineImage} />;\n }\n\n // Unresolvable or error: render text fallback in inline monospace.\n if (view.kind === \"unresolvable\" || view.kind === \"error\") {\n return <code className={styles.inlineImageFallback}>{view.fallbackText}</code>;\n }\n\n // Loading or idle: skeleton.\n if (view.kind === \"loading\") {\n return (\n <div className={styles.inlineImageSkeleton}>\n <Spinner size=\"sm\" />\n </div>\n );\n }\n\n // Ready: render the fetched image with click-to-open handler.\n const handleClick = () => {\n openTab({\n id: tabIds.file(view.path),\n kind: \"file\",\n label: view.path.split(\"/\").pop() || view.path,\n closable: true,\n data: { path: view.path },\n workspaceCwd: assetBase || \"~\",\n });\n };\n\n return (\n <img\n src={view.objectUrl}\n alt={view.alt}\n className={styles.inlineImage}\n title={view.path}\n onClick={handleClick}\n style={{ cursor: \"pointer\" }}\n />\n );\n});\n","/**\n * react-markdown + remark-gfm rendering, replacing the POC's CDN `marked` + `innerHTML`\n * (POC_TO_APP_PLAN_UI.md §4.8). Sanitized by default — react-markdown never injects raw HTML.\n * Fenced code blocks highlight asynchronously via Shiki (`highlight.ts`).\n */\n\nimport { memo, useEffect, useState, type ComponentPropsWithoutRef } from \"react\";\nimport ReactMarkdown from \"react-markdown\";\nimport remarkGfm from \"remark-gfm\";\nimport { highlightToHtml } from \"./highlight.js\";\nimport styles from \"./markdown.module.css\";\nimport { InlineImage } from \"./InlineImage.js\";\n\ninterface CodeBlockProps {\n language: string;\n code: string;\n}\n\nfunction CodeBlock({ language, code }: CodeBlockProps) {\n const [html, setHtml] = useState<string | null>(null);\n\n useEffect(() => {\n let cancelled = false;\n void highlightToHtml(code, language).then((result) => {\n if (!cancelled) setHtml(result);\n });\n return () => {\n cancelled = true;\n };\n }, [code, language]);\n\n if (html) {\n // Shiki's output is generated HTML from a trusted local highlighter (no user HTML is ever\n // injected) — the only risk is `code`, which Shiki escapes internally before tokenizing.\n return <div className={styles.prose} dangerouslySetInnerHTML={{ __html: html }} />;\n }\n return (\n <pre>\n <code>{code}</code>\n </pre>\n );\n}\n\ntype MarkdownCodeProps = ComponentPropsWithoutRef<\"code\"> & { className?: string };\n\nfunction CodeRenderer({ className, children, ...rest }: MarkdownCodeProps) {\n const match = /language-(\\w+)/.exec(className ?? \"\");\n const isBlock = Boolean(match);\n const code = String(children).replace(/\\n$/, \"\");\n if (isBlock && match) {\n return <CodeBlock language={match[1] ?? \"plaintext\"} code={code} />;\n }\n return (\n <code className={styles.inlineCode} {...rest}>\n {children}\n </code>\n );\n}\n\nexport interface MarkdownProps {\n text: string;\n assetBase?: string | null;\n}\n\n/** Renders assistant/tool markdown text. Memoized — text is immutable once a turn finalizes. */\nexport const Markdown = memo(function Markdown({ text, assetBase = null }: MarkdownProps) {\n return (\n <div className={styles.prose}>\n <ReactMarkdown\n remarkPlugins={[remarkGfm]}\n components={{\n code: CodeRenderer,\n img: (props) => <InlineImage {...props} assetBase={assetBase} />,\n }}\n >\n {text}\n </ReactMarkdown>\n </div>\n );\n});\n"],"names":["THEME","highlighterPromise","loadedLangs","getHighlighter","createHighlighter","ensureLang","highlighter","lang","highlightToHtml","code","resolved","REMOTE_SCHEMES","SCHEME_RE","classifyImageSrc","src","base","homeDir","trimmed","stripped","schemeMatch","scheme","candidate","normalizeCwd","resolveWorkspacePath","detectViewerKind","selectInlineImageView","classification","imageState","alt","fallbackText","loadInlineImage","path","download","onStateChange","cancelled","acquireInlineImage","entry","error","releaseInlineImage","useInlineImage","client","useConnectionStore","s","daemon","state","setState","useState","useEffect","p","transferFor","InlineImage","memo","assetBase","useHomeDir","openTab","useTabStore","useMemo","view","jsx","styles","Spinner","handleClick","tabIds","CodeBlock","language","html","setHtml","result","CodeRenderer","className","children","rest","match","isBlock","Markdown","text","ReactMarkdown","remarkGfm","props"],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
._prose_o2vtj_1{font-size:var(--pi-font-size-md);line-height:1.5;color:var(--pi-color-foreground, #fafafa);word-break:break-word}._prose_o2vtj_1>:first-child{margin-top:0}._prose_o2vtj_1>:last-child{margin-bottom:0}._prose_o2vtj_1 p{margin:.5em 0}._prose_o2vtj_1 a{color:var(--pi-color-accentBright, #a2b4d7)}._prose_o2vtj_1 pre{margin:.5em 0;padding:10px 12px;border-radius:var(--pi-borderRadius-md, 6px);overflow-x:auto;background:var(--pi-color-surfaceSunken, #111)}._prose_o2vtj_1 pre code{font-family:var(--pi-font-mono, ui-monospace, monospace);font-size:var(--pi-font-size-sm);background:none;padding:0}._inlineCode_o2vtj_32{font-family:var(--pi-font-mono, ui-monospace, monospace);font-size:.9em;background:var(--pi-color-surfaceSunken, #111);border-radius:3px;padding:.1em .35em}._prose_o2vtj_1 table{border-collapse:collapse;margin:.5em 0}._prose_o2vtj_1 th,._prose_o2vtj_1 td{border:1px solid var(--pi-color-border, #353b46);padding:4px 8px}._prose_o2vtj_1 blockquote{margin:.5em 0;padding-left:10px;border-left:2px solid var(--pi-color-border, #353b46);color:var(--pi-color-foregroundMuted, #9aa0a6)}._prose_o2vtj_1 ul,._prose_o2vtj_1 ol{padding-left:1.4em}._inlineImage_o2vtj_58{max-width:100%;max-height:60vh;height:auto;border-radius:4px;border:1px solid var(--pi-color-border, #353b46);display:block;margin:.5em 0}._inlineImageSkeleton_o2vtj_67{display:flex;align-items:center;justify-content:center;gap:8px;color:var(--pi-color-foregroundMuted, #9aa0a6);font-size:var(--pi-font-size-xs);padding:20px;min-height:200px;margin:.5em 0}._inlineImageFallback_o2vtj_78{font-family:var(--pi-font-mono, ui-monospace, monospace);font-size:.9em;background:var(--pi-color-surfaceSunken, #111);border-radius:3px;padding:.1em .35em;word-break:break-word}
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import{r as a}from"./vendor-react-CWo7Do4s.js";import{u as f}from"./vendor-query-BGIh-vlp.js";import{a as s,
|
|
2
|
-
//# sourceMappingURL=use-file-download-
|
|
1
|
+
import{r as a}from"./vendor-react-CWo7Do4s.js";import{u as f}from"./vendor-query-BGIh-vlp.js";import{a as s,l as m,r as y}from"./index-CEP1cIKf.js";function p(o,u=!0){var i;const l=s(e=>e.client),n=s(e=>e.daemon),c=f({queryKey:y.fileDownload(o),queryFn:async()=>{if(!l||!n)throw new Error("not connected");const e=await m(n).download(o),t=new Blob([Uint8Array.from(e.bytes)],{type:e.mimeType||"application/octet-stream"});return{objectUrl:URL.createObjectURL(t),mimeType:e.mimeType,fileName:e.fileName}},enabled:!!l&&!!n&&!!o&&u,staleTime:1/0,gcTime:0}),r=a.useRef(null);return a.useEffect(()=>{var t;const e=((t=c.data)==null?void 0:t.objectUrl)??null;e&&r.current&&r.current!==e&&URL.revokeObjectURL(r.current),r.current=e},[(i=c.data)==null?void 0:i.objectUrl]),a.useEffect(()=>()=>{r.current&&URL.revokeObjectURL(r.current)},[]),c}export{p as u};
|
|
2
|
+
//# sourceMappingURL=use-file-download-BTSuk1Eh.js.map
|
package/dist/web/assets/{use-file-download-DzZxLbm7.js.map → use-file-download-BTSuk1Eh.js.map}
RENAMED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"use-file-download-
|
|
1
|
+
{"version":3,"file":"use-file-download-BTSuk1Eh.js","sources":["../../../src/hooks/use-file-download.ts"],"sourcesContent":["/**\n * `use-file-download` — TanStack Query wrapper over the binary file-transfer download path\n * (`file_download_token_request` → `file_download_request` → chunked `Begin`/`Chunk`/`End`\n * binary frames), for viewers that need raw bytes rather than the UTF-8 preview\n * `file_read_request` returns (images, video — POC_TO_APP_PLAN_UI.md §4.5 follow-up: modular\n * file preview). Resolves to an object URL, revoked once superseded by a new one or once this\n * consumer unmounts.\n */\n\nimport { useEffect, useRef } from \"react\";\nimport { useQuery } from \"@tanstack/react-query\";\nimport { useConnectionStore } from \"@pi-studio-ui/lib/connection/connection-store.js\";\nimport { rpcKeys } from \"@pi-studio-ui/lib/connection/rpc-keys.js\";\nimport { transferFor } from \"./file-transfer-instance.js\";\n\nexport interface FileDownload {\n objectUrl: string;\n mimeType?: string;\n fileName?: string;\n}\n\nexport function useFileDownload(path: string, enabled = true) {\n const client = useConnectionStore((s) => s.client);\n const daemon = useConnectionStore((s) => s.daemon);\n\n const query = useQuery({\n queryKey: rpcKeys.fileDownload(path),\n queryFn: async (): Promise<FileDownload> => {\n if (!client || !daemon) throw new Error(\"not connected\");\n const file = await transferFor(daemon).download(path);\n // `Blob`'s DOM typings require an `ArrayBuffer`-backed view; the assembled `Uint8Array`'s\n // `ArrayBufferLike` backing (a decode-time implementation detail) doesn't satisfy that on\n // its own, so copy into a plain `ArrayBuffer`-backed `Uint8Array` first.\n const blob = new Blob([Uint8Array.from(file.bytes)], {\n type: file.mimeType || \"application/octet-stream\",\n });\n return { objectUrl: URL.createObjectURL(blob), mimeType: file.mimeType, fileName: file.fileName };\n },\n enabled: Boolean(client) && Boolean(daemon) && Boolean(path) && enabled,\n // Object URLs are process-local, non-serializable browser resources — never persist them or\n // silently refetch behind this hook's back (that would leak the previous blob's URL).\n staleTime: Infinity,\n gcTime: 0,\n });\n\n // Revoke the previous object URL once a new one supersedes it, and the current one on unmount\n // — TanStack Query's cache has no notion that this value owns a browser resource to release.\n const urlRef = useRef<string | null>(null);\n useEffect(() => {\n const nextUrl = query.data?.objectUrl ?? null;\n if (nextUrl && urlRef.current && urlRef.current !== nextUrl) {\n URL.revokeObjectURL(urlRef.current);\n }\n urlRef.current = nextUrl;\n }, [query.data?.objectUrl]);\n\n useEffect(() => {\n return () => {\n if (urlRef.current) URL.revokeObjectURL(urlRef.current);\n };\n }, []);\n\n return query;\n}\n"],"names":["useFileDownload","path","enabled","client","useConnectionStore","s","daemon","query","useQuery","rpcKeys","file","transferFor","blob","urlRef","useRef","useEffect","nextUrl","_a"],"mappings":"oJAqBO,SAASA,EAAgBC,EAAcC,EAAU,GAAM,OAC5D,MAAMC,EAASC,EAAoBC,GAAMA,EAAE,MAAM,EAC3CC,EAASF,EAAoBC,GAAMA,EAAE,MAAM,EAE3CE,EAAQC,EAAS,CACrB,SAAUC,EAAQ,aAAaR,CAAI,EACnC,QAAS,SAAmC,CAC1C,GAAI,CAACE,GAAU,CAACG,EAAQ,MAAM,IAAI,MAAM,eAAe,EACvD,MAAMI,EAAO,MAAMC,EAAYL,CAAM,EAAE,SAASL,CAAI,EAI9CW,EAAO,IAAI,KAAK,CAAC,WAAW,KAAKF,EAAK,KAAK,CAAC,EAAG,CACnD,KAAMA,EAAK,UAAY,0BAAA,CACxB,EACD,MAAO,CAAE,UAAW,IAAI,gBAAgBE,CAAI,EAAG,SAAUF,EAAK,SAAU,SAAUA,EAAK,QAAA,CACzF,EACA,QAAS,EAAQP,GAAW,EAAQG,GAAW,EAAQL,GAASC,EAGhE,UAAW,IACX,OAAQ,CAAA,CACT,EAIKW,EAASC,EAAAA,OAAsB,IAAI,EACzCC,OAAAA,EAAAA,UAAU,IAAM,OACd,MAAMC,IAAUC,EAAAV,EAAM,OAAN,YAAAU,EAAY,YAAa,KACrCD,GAAWH,EAAO,SAAWA,EAAO,UAAYG,GAClD,IAAI,gBAAgBH,EAAO,OAAO,EAEpCA,EAAO,QAAUG,CACnB,EAAG,EAACC,EAAAV,EAAM,OAAN,YAAAU,EAAY,SAAS,CAAC,EAE1BF,EAAAA,UAAU,IACD,IAAM,CACPF,EAAO,SAAS,IAAI,gBAAgBA,EAAO,OAAO,CACxD,EACC,CAAA,CAAE,EAEEN,CACT"}
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import{r as a}from"./vendor-react-CWo7Do4s.js";import{a as w}from"./index-
|
|
2
|
-
//# sourceMappingURL=use-file-watch-
|
|
1
|
+
import{r as a}from"./vendor-react-CWo7Do4s.js";import{a as w}from"./index-CEP1cIKf.js";function b(e){return typeof e=="object"&&e!==null&&"type"in e&&e.type==="file_changed"&&"path"in e&&typeof e.path=="string"}const l=new WeakMap;function p(e,t,i){let s=l.get(e);s||(s=new Map,l.set(e,s));let o=s.get(t);if(!o){const r={count:0,resolvedPath:null,listeners:new Set,dispose:()=>{}},f=e.connection.onSessionMessage(c=>{const n=c;if(!b(n)||n.path!==t&&n.path!==r.resolvedPath)return;const d=Date.now();for(const h of r.listeners)h(d)});e.connection.request("file_watch_subscribe",{path:t}).then(c=>{const n=c;if((n==null?void 0:n.ok)===!1){console.warn(`watchFile: ${n.error??"subscribe failed"} for "${t}"`);return}typeof(n==null?void 0:n.path)=="string"&&(r.resolvedPath=n.path)}).catch(()=>{}),r.dispose=()=>{f(),e.connection.request("file_watch_unsubscribe",{path:t}).catch(()=>{})},o=r,s.set(t,o)}o.count++,o.listeners.add(i);let u=!1;return()=>{if(u)return;u=!0;const r=s.get(t);r&&(r.listeners.delete(i),r.count--,r.count===0&&(s.delete(t),r.dispose()))}}function v(e){const t=w(o=>o.client),[i,s]=a.useState(null);return a.useEffect(()=>{if(!(!t||!e))return p(t,e,s)},[t,e]),{changedAt:i}}export{v as u};
|
|
2
|
+
//# sourceMappingURL=use-file-watch-DZfGlL1N.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"use-file-watch-
|
|
1
|
+
{"version":3,"file":"use-file-watch-DZfGlL1N.js","sources":["../../../src/hooks/use-file-watch.ts"],"sourcesContent":["/**\n * `use-file-watch` — subscribes to live daemon `file_changed` pushes for a path (task-006's\n * `FileWatchService`), structurally mirroring `use-checkout-status.ts`: subscribe on mount/path\n * change via `file_watch_subscribe`, route matching pushes through `onSessionMessage`, and on\n * cleanup detach the message handler AND send `file_watch_unsubscribe` for the path being left —\n * `use-checkout-status.ts`'s own header comment calls out that leaving either half undone is the\n * leak this pattern exists to avoid.\n *\n * The actual subscribe/route/cleanup wiring lives in `watchFile`, a plain function with no React\n * dependency (mirrors `molecule-source.ts`/`molecule-reload.ts`'s \"extract the testable core\"\n * convention) — this repo has no DOM test environment set up, so it is the seam\n * `use-file-watch.test.ts` exercises directly with a fake client rather than mounting the hook.\n *\n * A `null` path (an empty \"+\"-menu molecule tab, or the absence of a client) subscribes nothing.\n *\n * `watchFile` ref-counts subscriptions per `(client, path)` in a module-level registry (mirrors\n * `file-transfer-instance.ts`'s `WeakMap<DaemonClient, …>` shared-instance convention): more than\n * one component can watch the same file (a file tab and a diff tab on the same path) and share\n * ONE daemon watch, rather than the second `file_watch_unsubscribe` killing it for both — the\n * daemon's `SessionSubscriptions.add` disposes any existing entry for the same resolved-path key.\n * The entry also remembers the RESOLVED path echoed back by `file_watch_subscribe_response.path`\n * (the daemon expands a leading `~` server-side before pushing `file_changed`), and matches a\n * push against either the requested spelling or that resolved path.\n */\n\nimport { useEffect, useState } from \"react\";\nimport type { PiStudioClient } from \"@av-pi-studio/client\";\nimport { useConnectionStore } from \"@pi-studio-ui/lib/connection/connection-store.js\";\n\ninterface FileChangedMessage {\n type: \"file_changed\";\n path: string;\n}\n\nfunction isFileChangedMessage(msg: unknown): msg is FileChangedMessage {\n return (\n typeof msg === \"object\" &&\n msg !== null &&\n \"type\" in msg &&\n msg.type === \"file_changed\" &&\n \"path\" in msg &&\n typeof msg.path === \"string\"\n );\n}\n\ninterface FileWatchSubscribeResponse {\n ok?: boolean;\n error?: string;\n path?: string;\n}\n\ninterface WatchEntry {\n count: number;\n /** Resolved path echoed by `file_watch_subscribe_response.path`; `null` until it arrives. */\n resolvedPath: string | null;\n listeners: Set<(changedAt: number) => void>;\n dispose: () => void;\n}\n\nconst watchesByClient = new WeakMap<Pick<PiStudioClient, \"connection\">, Map<string, WatchEntry>>();\n\n/** Subscribes `path` on `client.connection`, calls `onChanged` for every matching `file_changed`\n * push, and returns a cleanup function that detaches the handler AND sends\n * `file_watch_unsubscribe` for `path` once the LAST subscriber for that `(client, path)` pair\n * releases it. Framework-agnostic on purpose — see module header. */\nexport function watchFile(\n client: Pick<PiStudioClient, \"connection\">,\n path: string,\n onChanged: (changedAt: number) => void,\n): () => void {\n let entries = watchesByClient.get(client);\n if (!entries) {\n entries = new Map<string, WatchEntry>();\n watchesByClient.set(client, entries);\n }\n\n let entry = entries.get(path);\n if (!entry) {\n const created: WatchEntry = {\n count: 0,\n resolvedPath: null,\n listeners: new Set(),\n dispose: () => {},\n };\n\n const unsubscribeMessages = client.connection.onSessionMessage((msg) => {\n const raw: unknown = msg;\n if (!isFileChangedMessage(raw)) return;\n if (raw.path !== path && raw.path !== created.resolvedPath) return;\n const changedAt = Date.now();\n for (const listener of created.listeners) listener(changedAt);\n });\n\n void client.connection\n .request(\"file_watch_subscribe\", { path })\n .then((res) => {\n const response = res as FileWatchSubscribeResponse;\n if (response?.ok === false) {\n console.warn(`watchFile: ${response.error ?? \"subscribe failed\"} for \"${path}\"`);\n return;\n }\n if (typeof response?.path === \"string\") {\n created.resolvedPath = response.path;\n }\n })\n .catch(() => {});\n\n created.dispose = () => {\n unsubscribeMessages();\n void client.connection.request(\"file_watch_unsubscribe\", { path }).catch(() => {});\n };\n\n entry = created;\n entries.set(path, entry);\n }\n\n entry.count++;\n entry.listeners.add(onChanged);\n\n let released = false;\n return () => {\n if (released) return; // Idempotent: a second call must never double-release.\n released = true;\n const current = entries!.get(path);\n if (!current) return;\n current.listeners.delete(onChanged);\n current.count--;\n if (current.count === 0) {\n entries!.delete(path);\n current.dispose();\n }\n };\n}\n\nexport interface UseFileWatchResult {\n /** Monotonic timestamp of the last `file_changed` push for this path; `null` if none yet. */\n changedAt: number | null;\n}\n\nexport function useFileWatch(path: string | null): UseFileWatchResult {\n const client = useConnectionStore((s) => s.client);\n const [changedAt, setChangedAt] = useState<number | null>(null);\n\n useEffect(() => {\n if (!client || !path) return;\n return watchFile(client, path, setChangedAt);\n }, [client, path]);\n\n return { changedAt };\n}\n"],"names":["isFileChangedMessage","msg","watchesByClient","watchFile","client","path","onChanged","entries","entry","created","unsubscribeMessages","raw","changedAt","listener","res","response","released","current","useFileWatch","useConnectionStore","s","setChangedAt","useState","useEffect"],"mappings":"uFAkCA,SAASA,EAAqBC,EAAyC,CACrE,OACE,OAAOA,GAAQ,UACfA,IAAQ,MACR,SAAUA,GACVA,EAAI,OAAS,gBACb,SAAUA,GACV,OAAOA,EAAI,MAAS,QAExB,CAgBA,MAAMC,MAAsB,QAMrB,SAASC,EACdC,EACAC,EACAC,EACY,CACZ,IAAIC,EAAUL,EAAgB,IAAIE,CAAM,EACnCG,IACHA,MAAc,IACdL,EAAgB,IAAIE,EAAQG,CAAO,GAGrC,IAAIC,EAAQD,EAAQ,IAAIF,CAAI,EAC5B,GAAI,CAACG,EAAO,CACV,MAAMC,EAAsB,CAC1B,MAAO,EACP,aAAc,KACd,cAAe,IACf,QAAS,IAAM,CAAC,CAAA,EAGZC,EAAsBN,EAAO,WAAW,iBAAkBH,GAAQ,CACtE,MAAMU,EAAeV,EAErB,GADI,CAACD,EAAqBW,CAAG,GACzBA,EAAI,OAASN,GAAQM,EAAI,OAASF,EAAQ,aAAc,OAC5D,MAAMG,EAAY,KAAK,IAAA,EACvB,UAAWC,KAAYJ,EAAQ,UAAWI,EAASD,CAAS,CAC9D,CAAC,EAEIR,EAAO,WACT,QAAQ,uBAAwB,CAAE,KAAAC,EAAM,EACxC,KAAMS,GAAQ,CACb,MAAMC,EAAWD,EACjB,IAAIC,GAAA,YAAAA,EAAU,MAAO,GAAO,CAC1B,QAAQ,KAAK,cAAcA,EAAS,OAAS,kBAAkB,SAASV,CAAI,GAAG,EAC/E,MACF,CACI,OAAOU,GAAA,YAAAA,EAAU,OAAS,WAC5BN,EAAQ,aAAeM,EAAS,KAEpC,CAAC,EACA,MAAM,IAAM,CAAC,CAAC,EAEjBN,EAAQ,QAAU,IAAM,CACtBC,EAAA,EACKN,EAAO,WAAW,QAAQ,yBAA0B,CAAE,KAAAC,CAAA,CAAM,EAAE,MAAM,IAAM,CAAC,CAAC,CACnF,EAEAG,EAAQC,EACRF,EAAQ,IAAIF,EAAMG,CAAK,CACzB,CAEAA,EAAM,QACNA,EAAM,UAAU,IAAIF,CAAS,EAE7B,IAAIU,EAAW,GACf,MAAO,IAAM,CACX,GAAIA,EAAU,OACdA,EAAW,GACX,MAAMC,EAAUV,EAAS,IAAIF,CAAI,EAC5BY,IACLA,EAAQ,UAAU,OAAOX,CAAS,EAClCW,EAAQ,QACJA,EAAQ,QAAU,IACpBV,EAAS,OAAOF,CAAI,EACpBY,EAAQ,QAAA,GAEZ,CACF,CAOO,SAASC,EAAab,EAAyC,CACpE,MAAMD,EAASe,EAAoBC,GAAMA,EAAE,MAAM,EAC3C,CAACR,EAAWS,CAAY,EAAIC,EAAAA,SAAwB,IAAI,EAE9DC,OAAAA,EAAAA,UAAU,IAAM,CACd,GAAI,GAACnB,GAAU,CAACC,GAChB,OAAOF,EAAUC,EAAQC,EAAMgB,CAAY,CAC7C,EAAG,CAACjB,EAAQC,CAAI,CAAC,EAEV,CAAE,UAAAO,CAAA,CACX"}
|
package/dist/web/index.html
CHANGED
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
<meta charset="utf-8" />
|
|
5
5
|
<meta name="viewport" content="width=device-width, initial-scale=1" />
|
|
6
6
|
<title>Pi-Studio</title>
|
|
7
|
-
<script type="module" crossorigin src="/assets/index-
|
|
7
|
+
<script type="module" crossorigin src="/assets/index-CEP1cIKf.js"></script>
|
|
8
8
|
<link rel="modulepreload" crossorigin href="/assets/vendor-react-CWo7Do4s.js">
|
|
9
9
|
<link rel="modulepreload" crossorigin href="/assets/vendor-query-BGIh-vlp.js">
|
|
10
10
|
<link rel="modulepreload" crossorigin href="/assets/vendor-markdown-YvkQLm_s.js">
|
|
@@ -13,7 +13,7 @@
|
|
|
13
13
|
<link rel="modulepreload" crossorigin href="/assets/vendor-icons-o8-A85LK.js">
|
|
14
14
|
<link rel="modulepreload" crossorigin href="/assets/vendor-overlays-BnmaUbKw.js">
|
|
15
15
|
<link rel="modulepreload" crossorigin href="/assets/vendor-dnd-CH6z-X6S.js">
|
|
16
|
-
<link rel="stylesheet" crossorigin href="/assets/index-
|
|
16
|
+
<link rel="stylesheet" crossorigin href="/assets/index-DCtlhAPI.css">
|
|
17
17
|
</head>
|
|
18
18
|
<body>
|
|
19
19
|
<div id="root"></div>
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@av-pi-studio/web-client",
|
|
3
|
-
"version": "0.0.
|
|
3
|
+
"version": "0.0.59",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"files": [
|
|
6
6
|
"dist"
|
|
@@ -14,8 +14,8 @@
|
|
|
14
14
|
"clean": "rm -rf dist *.tsbuildinfo"
|
|
15
15
|
},
|
|
16
16
|
"dependencies": {
|
|
17
|
-
"@av-pi-studio/client": "^0.0.
|
|
18
|
-
"@av-pi-studio/protocol": "^0.0.
|
|
17
|
+
"@av-pi-studio/client": "^0.0.59",
|
|
18
|
+
"@av-pi-studio/protocol": "^0.0.59",
|
|
19
19
|
"@codemirror/language": "^6.12.4",
|
|
20
20
|
"@codemirror/language-data": "^6.5.2",
|
|
21
21
|
"@codemirror/state": "^6.7.1",
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
._wrap_abb1r_1{display:flex;flex-direction:column;align-items:center;justify-content:center;gap:12px;height:100%;min-height:0;color:var(--pi-color-foregroundMuted, #9aa0a6);font-size:1.0625rem}._name_abb1r_12{color:var(--pi-color-foreground, #fafafa);font-size:1.1875rem;font-weight:600}
|
|
@@ -1,3 +0,0 @@
|
|
|
1
|
-
import{r as g,j as t}from"./vendor-react-CWo7Do4s.js";import{c as pe,d as fe,m as ge,u as _e}from"./vendor-query-BGIh-vlp.js";import{t as ee,u as C,a as q,D as xe,b as je,n as ye,e as te,r as ke,s as f,S as ve,f as Ne,B as R,T as we}from"./index-DtH67PKb.js";import{x as Se,y as Ce,z as be,m as De,d as Ie,B as Be,H as ne,C as Te,I as Ee,J as $e,K as Re,N as Ae,O as Fe,S as Oe}from"./vendor-icons-o8-A85LK.js";import{M as se}from"./markdown-BA3kiSJG.js";import{C as v}from"./vendor-04vXFIXe.js";import{S as ze}from"./StatusBadge-Cripx88K.js";import{D as Pe}from"./DiffView-dFsrDUgN.js";import{R as Me,T as Ke,P as qe,C as He}from"./vendor-overlays-BnmaUbKw.js";import"./vendor-dnd-CH6z-X6S.js";import"./vendor-highlight-Efc6A-g6.js";import"./vendor-markdown-YvkQLm_s.js";const Ue={shell:ne,read:Be,edit:Ie,write:De,search:be,fetch:Ce,task:Se};function Le(e){return Ue[e.kind]??ne}function We(e){return e.kind}function Qe(e){switch(e.kind){case"read":case"write":case"edit":return e.path??null;default:return null}}function Ve(e){return e.kind==="write"||e.kind==="edit"||e.kind==="shell"}function Ge(e){const n=[];if(e.kind==="edit"&&e.diff)n.push({kind:"diff",patch:e.diff});else{const s=ee(e);s&&n.push({kind:"code",text:s})}return e.output&&n.push({kind:"code",text:e.output}),n}function Xe(e){const n=ee(e);if(!n)return"";switch(e.kind){case"read":case"write":case"edit":{const s=n.split("/");return s[s.length-1]||n}case"shell":return n.split(`
|
|
2
|
-
`,1)[0]??n;default:return n}}const Ye=500;let P;function Je(e,n,s,i){clearTimeout(P),P=setTimeout(()=>{P=void 0,e.invalidateQueries({queryKey:["file"]}),e.invalidateQueries({queryKey:["explorer"]}),n&&s&&n.connection.request("checkout_refresh_request",{cwd:s}).catch(()=>{})},Ye)}function Ze({sessionId:e,event:n,client:s,queryClient:i}){const r=C.getState();switch(r.applyStreamEvent(e,n),n.kind){case"turn_started":r.setStatus(e,"running");break;case"turn_completed":r.setStatus(e,"idle");break;case"turn_failed":r.setStatus(e,"error");break;case"turn_canceled":r.setStatus(e,"idle");break;case"tool_call":{if(n.status==="completed"&&Ve(n.tool)){const l=r.sessions[e],c=(l==null?void 0:l.cwd)||null;Je(i,s,c,Qe(n.tool))}break}}}function et(e){const n=q(r=>r.client),s=C(r=>{var l;return((l=r.sessions[e])==null?void 0:l.agentId)??null}),i=pe();g.useEffect(()=>!n||!s?void 0:n.agent(s).timeline.subscribe(l=>{Ze({sessionId:e,event:l,client:n,queryClient:i})}),[n,s,e,i])}const tt="_row_moj0c_3",nt="_who_moj0c_13",st="_queuedBadge_moj0c_22",at="_user_moj0c_40",rt="_userPending_moj0c_47",ot="_userQueued_moj0c_51",it="_userFailed_moj0c_55",ct="_userImages_moj0c_61",lt="_userImage_moj0c_61",ut="_imageDialog_moj0c_77",dt="_imageDialogPreview_moj0c_81",mt="_assistant_moj0c_90",ht="_streaming_moj0c_97",pt="_streamingText_moj0c_101",ft="_cursor_moj0c_106",gt="_blink_moj0c_1",_t="_reasoning_moj0c_121",xt="_tool_moj0c_131",jt="_toolHeader_moj0c_141",yt="_toolChevron_moj0c_159",kt="_toolChevronOpen_moj0c_165",vt="_toolInlineDetail_moj0c_169",Nt="_toolBody_moj0c_179",wt="_toolCode_moj0c_185",St="_toolIcon_moj0c_196",Ct="_running_moj0c_202",bt="_pulse_moj0c_1",Dt="_completed_moj0c_207",It="_error_moj0c_211",Bt="_toolLabel_moj0c_221",Tt="_toolBadge_moj0c_226",Et="_system_moj0c_238",o={row:tt,who:nt,queuedBadge:st,user:at,userPending:rt,userQueued:ot,userFailed:it,userImages:ct,userImage:lt,imageDialog:ut,imageDialogPreview:dt,assistant:mt,streaming:ht,streamingText:pt,cursor:ft,blink:gt,reasoning:_t,tool:xt,toolHeader:jt,toolChevron:yt,toolChevronOpen:kt,toolInlineDetail:vt,toolBody:Nt,toolCode:wt,toolIcon:St,running:Ct,pulse:bt,completed:Dt,error:It,toolLabel:Bt,toolBadge:Tt,system:Et};function $t({row:e,assetBase:n=null}){return t.jsxs("div",{className:`${o.row} ${o.assistant}${e.streaming?` ${o.streaming}`:""}`,children:[t.jsx("span",{className:o.who,children:"assistant"}),e.streaming?t.jsxs("span",{className:o.streamingText,children:[e.text,t.jsx("span",{className:o.cursor,children:"▍"})]}):t.jsx(se,{text:e.text,assetBase:n})]})}function Rt({row:e}){return t.jsxs("div",{className:`${o.row} ${o.reasoning}`,children:[t.jsx("span",{className:o.who,children:"thinking"}),e.streaming?t.jsxs("span",{className:o.streamingText,children:[e.text,t.jsx("span",{className:o.cursor,children:"▍"})]}):t.jsx(se,{text:e.text})]})}const At={running:"muted",completed:"success",error:"error"};function Ft({row:e}){const[n,s]=g.useState(!1),i=Le(e.tool),r=Xe(e.tool),l=Ge(e.tool),c=l.length>0;return t.jsxs("div",{className:v(o.row,o.tool),children:[t.jsxs("button",{type:"button",className:o.toolHeader,onClick:()=>c&&s(h=>!h),"aria-expanded":c?n:void 0,disabled:!c,children:[c&&t.jsx(Te,{size:12,className:v(o.toolChevron,n&&o.toolChevronOpen)}),t.jsx("span",{className:v(o.toolIcon,o[e.status]),children:t.jsx(i,{size:14})}),t.jsx("span",{className:o.toolLabel,children:We(e.tool)}),r&&t.jsx("span",{className:o.toolInlineDetail,title:r,children:r}),t.jsx(ze,{className:o.toolBadge,label:e.status,variant:At[e.status]})]}),n&&c&&t.jsx("div",{className:o.toolBody,children:l.map((h,_)=>h.kind==="diff"?t.jsx(Pe,{patch:h.patch},_):t.jsx("pre",{className:o.toolCode,children:h.text},_))})]})}function Ot({row:e}){const[n,s]=g.useState(null),i=e.failed?o.userFailed:e.pending?o.userPending:e.queued?o.userQueued:"";return t.jsxs("div",{className:`${o.row} ${o.user}${i?` ${i}`:""}`,children:[t.jsxs("span",{className:o.who,children:["you",e.failed?" · failed to send":"",e.queued&&!e.failed&&t.jsxs("span",{className:o.queuedBadge,children:[t.jsx(Ee,{size:9}),"queued"]})]}),e.text,e.images&&e.images.length>0&&t.jsx("div",{className:o.userImages,children:e.images.map((r,l)=>{const c=`data:${r.mimeType??"image/png"};base64,${r.data??""}`;return t.jsx("img",{className:o.userImage,src:c,alt:"",role:"button",tabIndex:0,onClick:()=>s(c),onKeyDown:h=>{(h.key==="Enter"||h.key===" ")&&s(c)}},l)})}),t.jsx(xe,{open:n!==null,onOpenChange:r=>{r||s(null)},title:"Image",width:"auto",bare:!0,className:o.imageDialog,children:n&&t.jsx("img",{className:o.imageDialogPreview,src:n,alt:""})})]})}function zt({row:e}){return t.jsxs("div",{className:`${o.row} ${o.error}`,children:[t.jsx("span",{className:o.who,children:"error"}),e.text]})}function Pt({row:e}){return t.jsx("div",{className:`${o.row} ${o.system}`,children:e.text})}const Mt="_viewport_1yr1a_3",Kt="_inner_1yr1a_10",qt="_rowWrap_1yr1a_15",Ht="_empty_1yr1a_25",Ut="_working_1yr1a_34",Lt="_workingDots_1yr1a_43",k={viewport:Mt,inner:Kt,rowWrap:qt,empty:Ht,working:Ut,workingDots:Lt},Wt=40;function Qt(e,n){switch(e.kind){case"user":return t.jsx(Ot,{row:e});case"assistant":return t.jsx($t,{row:e,assetBase:n});case"reasoning":return t.jsx(Rt,{row:e});case"tool":return t.jsx(Ft,{row:e});case"error":return t.jsx(zt,{row:e});case"system":return t.jsx(Pt,{row:e})}}function Vt({session:e}){const n=e.timeline.rows,s=e.status==="running",i=je(),r=ye(e.cwd,i),l=g.useRef(null),c=g.useRef(!0),h=g.useRef(0),_=fe({count:n.length,getScrollElement:()=>l.current,estimateSize:()=>48,overscan:8,getItemKey:m=>{var u;return((u=n[m])==null?void 0:u.id)??m},measureElement:(m,u,x)=>{if(m.offsetParent!==null)return ge(m,u,x);const b=x.indexFromElement(m),D=x.options.getItemKey(b);return x.itemSizeCache.get(D)??x.options.estimateSize(b)}});function N(){const m=l.current;if(!m)return;const u=m.scrollHeight-m.scrollTop-m.clientHeight;c.current=u<Wt}return g.useEffect(()=>{const m=h.current,u=n.length>m;return h.current=n.length,u&&c.current&&_.scrollToIndex(n.length-1,{align:"end"}),()=>{h.current=m}},[n.length,_]),n.length===0?t.jsx("div",{className:k.viewport,ref:l,children:s?t.jsxs("div",{className:k.working,role:"status","aria-live":"polite",children:[t.jsxs("span",{className:k.workingDots,"aria-hidden":"true",children:[t.jsx("span",{}),t.jsx("span",{}),t.jsx("span",{})]}),"Agent is working…"]}):t.jsx("div",{className:k.empty,children:"No messages yet — say something to start."})}):t.jsxs("div",{className:k.viewport,ref:l,onScroll:N,children:[t.jsx("div",{className:k.inner,style:{height:_.getTotalSize()},children:_.getVirtualItems().map(m=>{const u=n[m.index];return u?t.jsx("div",{ref:_.measureElement,"data-index":m.index,className:k.rowWrap,style:{transform:`translateY(${m.start}px)`},children:Qt(u,r)},m.key):null})}),s&&t.jsxs("div",{className:k.working,role:"status","aria-live":"polite",children:[t.jsxs("span",{className:k.workingDots,"aria-hidden":"true",children:[t.jsx("span",{}),t.jsx("span",{}),t.jsx("span",{})]}),"Agent is working…"]})]})}function Gt(e,n=!0){const s=q(i=>i.client);return _e({queryKey:ke.agentCommands(e),queryFn:async()=>{if(!s)throw new Error("not connected");const i=await te(s,e),{commands:r}=await s.agent(i).listCommands();return r},enabled:!!s&&!!e&&n})}const Xt="_strip_1pf1y_4",Yt="_thumb_1pf1y_11",Jt="_remove_1pf1y_28",M={strip:Xt,thumb:Yt,remove:Jt};function Zt({images:e,onRemove:n}){return e.length===0?null:t.jsx("div",{className:M.strip,children:e.map((s,i)=>t.jsxs("div",{className:M.thumb,children:[t.jsx("img",{src:s.thumbUrl,alt:""}),t.jsx("button",{type:"button",className:M.remove,title:"Remove",onClick:()=>n(i),children:"×"})]},i))})}function en(e){const{promise:n,resolve:s,reject:i}=Promise.withResolvers(),r=new FileReader;return r.onload=()=>{const l=r.result;if(typeof l!="string"){i(new Error("Unexpected FileReader result"));return}const c=l.indexOf(","),h=c>=0?l.slice(c+1):l;s({mimeType:e.type,data:h,thumbUrl:l})},r.onerror=()=>i(r.error??new Error("Failed to read file")),r.readAsDataURL(e),n}const tn={onOpenAutoFocus:e=>e.preventDefault()};function nn(e){switch(e){case"extension":return f.commandKindExtension;case"prompt":return f.commandKindPrompt;case"skill":return f.commandKindSkill;default:return}}function sn({open:e,onOpenChange:n,options:s,highlightedIndex:i,onSelect:r,isLoading:l,isError:c,errorMessage:h,hiddenExtensionCount:_,renderTrigger:N}){const m=g.useRef(null);return g.useEffect(()=>{var u,x;e&&((x=(u=m.current)==null?void 0:u.querySelector('[aria-selected="true"]'))==null||x.scrollIntoView({block:"nearest"}))},[e,i]),t.jsxs(Me,{open:e,onOpenChange:n,modal:!1,children:[t.jsx(Ke,{asChild:!0,children:N()}),t.jsx(qe,{children:t.jsxs(He,{className:v(f.content,f.commandContent),align:"start",side:"top",sideOffset:4,...tn,onCloseAutoFocus:u=>u.preventDefault(),children:[l&&t.jsx("div",{className:f.state,children:t.jsx(ve,{size:"sm"})}),!l&&c&&t.jsx("div",{className:f.stateError,children:h??"Failed to load commands"}),!l&&!c&&s.length===0&&t.jsx("div",{className:f.state,children:"No commands found"}),!l&&!c&&s.length>0&&t.jsx("div",{ref:m,className:v(f.list,f.commandList),children:s.map((u,x)=>t.jsxs("div",{role:"option","aria-selected":x===i,className:v(f.item,f.commandItem,x===i&&f.itemActive),title:u.description,onMouseDown:b=>{b.preventDefault(),r(u.value)},children:[t.jsxs("div",{className:f.commandItemHeader,children:[t.jsx("span",{className:f.label,children:u.label}),u.kind&&t.jsx("span",{className:v(f.commandKindBadge,nn(u.kind)),children:u.kind})]}),u.description&&t.jsx("div",{className:f.commandDescription,children:u.description})]},u.value))}),!l&&!c&&_>0&&t.jsxs("div",{className:f.state,children:[_," extension command(s) unavailable while the agent is running"]})]})})]})}function H(e){if(!e.startsWith("/"))return null;const n=/^\/(\S*)/.exec(e),s=(n==null?void 0:n[1])??"",i=1+s.length,r=/\S/.test(e.slice(i));return{name:s,end:i,hasArgs:r}}function an(e){return/^\/\S*$/.test(e)}function rn(e,n){let s=0;const i=[];for(const r of e){if(n.running&&r.source==="extension"){s+=1;continue}i.push({value:r.name,label:`/${r.name}`,description:r.description,kind:r.source})}return{options:i,hiddenExtensionCount:s}}function on(e,n,s){return s<=0?0:(e+n+s)%s}function cn(e,n){const s=H(e);return s?s.hasArgs?`/${n}${e.slice(s.end)}`:`/${n} `:`/${n} ${e}`}function ln(e,n){const s=H(e);return!s||!n.includes(s.name)?null:{end:s.end}}const un="_composer_10jfp_1",dn="_inputArea_10jfp_13",mn="_textarea_10jfp_21",hn="_attachBtn_10jfp_28",pn="_slashBtn_10jfp_32",fn="_textareaWrap_10jfp_42",gn="_highlightLayer_10jfp_50",_n="_commandMark_10jfp_65",xn="_textareaOverlaid_10jfp_90",jn="_hiddenFileInput_10jfp_94",yn="_actions_10jfp_98",j={composer:un,inputArea:dn,textarea:mn,attachBtn:hn,slashBtn:pn,textareaWrap:fn,highlightLayer:gn,commandMark:_n,textareaOverlaid:xn,hiddenFileInput:jn,actions:yn},kn=160;function F(e){e.style.height="auto",e.style.height=`${Math.min(e.scrollHeight,kn)}px`}function vn(e){return typeof e=="object"&&e!==null&&"ok"in e&&e.ok===!1}function Nn({sessionId:e}){const n=q(a=>a.client),s=C(a=>a.sessions[e]),i=C(a=>a.addOptimisticUserMessage),r=C(a=>a.markUserMessageFailed),l=C(a=>a.setCwd),[c,h]=g.useState(""),[_,N]=g.useState([]),[m,u]=g.useState(!1),[x,b]=g.useState(!1),D=g.useRef(null),U=g.useRef(null),[I,$]=g.useState(!1),[L,O]=g.useState(0),B=(s==null?void 0:s.status)==="running",W=!!n&&!(B?x:m)&&(c.trim().length>0||_.length>0),{data:Q=[],isLoading:ae,isError:re,error:V}=Gt(e,I),{options:G,hiddenExtensionCount:oe}=rn(Q,{running:B}),X=H(c),A=X?Ne(G,X.name):G,ie=Q.map(a=>a.name),w=ln(c,ie);async function Y(a){if(a.type.startsWith("image/"))try{const p=await en(a);N(d=>[...d,p])}catch{}}function ce(a){for(const p of a.target.files??[])Y(p);a.target.value=""}function le(a){for(const p of a.clipboardData.items)if(p.type.startsWith("image/")){a.preventDefault();const d=p.getAsFile();d&&Y(d)}}function ue(a){N(p=>p.filter((d,y)=>y!==a))}function de(a){const p=a.target.value;h(p),F(a.target);const d=an(p);d!==I&&$(d),d&&O(0)}function me(a){var p;if(!I&&w&&a.key==="Backspace"){const d=a.currentTarget,y=d.selectionStart;if(y!==null&&y===d.selectionEnd){const T=w.end+(c[w.end]===" "?1:0);if(y>0&&y<=T){a.preventDefault();const S=c.slice(T);h(S),d.setSelectionRange(0,0),F(d);return}}}if(I&&A.length>0){if(a.key==="ArrowDown"||a.key==="ArrowUp"){a.preventDefault(),O(d=>on(d,a.key==="ArrowDown"?1:-1,A.length));return}if(a.key==="Enter"&&!a.shiftKey||a.key==="Tab"){a.preventDefault();const d=(p=A[L])==null?void 0:p.value;d&&J(d);return}}if(I&&a.key==="Escape"){a.preventDefault(),$(!1);return}a.key==="Enter"&&!a.shiftKey&&(a.preventDefault(),z(B?"steer":"send"))}function J(a){const p=cn(c,a);h(p),$(!1),O(0);const d=D.current;d&&(d.focus(),d.setSelectionRange(p.length,p.length),F(d))}async function z(a){if(!n||!s||(a==="steer"?x:m)||a==="steer"&&!s.agentId)return;const p=c.trim();if(!p&&_.length===0)return;h(""),$(!1),D.current&&F(D.current);const d=_;N([]);const y=p||"Describe this image",T=d.length>0?d.map(E=>({mimeType:E.mimeType,data:E.data})):void 0,S=crypto.randomUUID();i(e,S,y,T,a==="steer");const Z=a==="steer"?b:u;Z(!0);try{if(a==="steer"){const E=await n.agent(s.agentId).steer(y,{clientMessageId:S,images:T});vn(E)&&r(e,S)}else{s.agentId||l(e,s.cwd||"~");const E=await te(n,e);await n.agent(E).send(y,{clientMessageId:S,images:T})}}catch{r(e,S)}finally{Z(!1)}}function he(){s!=null&&s.agentId&&(n==null||n.agent(s.agentId).interrupt())}return t.jsxs("div",{className:j.composer,children:[t.jsx(sn,{open:I,onOpenChange:$,options:A,highlightedIndex:L,onSelect:J,isLoading:ae,isError:re,errorMessage:V instanceof Error?V.message:void 0,hiddenExtensionCount:oe,renderTrigger:()=>t.jsx(R,{className:j.slashBtn,variant:"ghost",size:"md",iconOnly:!0,title:"Slash commands","aria-label":"Slash commands",children:t.jsx($e,{size:16})})}),t.jsxs("div",{className:j.inputArea,children:[t.jsxs("div",{className:j.textareaWrap,children:[t.jsx("div",{className:j.highlightLayer,"aria-hidden":!0,children:w?t.jsxs(t.Fragment,{children:[t.jsx("mark",{className:j.commandMark,children:c.slice(0,w.end)}),c.slice(w.end)]}):c}),t.jsx(we,{ref:D,className:v(j.textarea,w&&j.textareaOverlaid),rows:1,value:c,placeholder:B?"Steer the running turn… (Enter to steer, Shift+Enter for newline)":"Ask anything… (Enter to send, Shift+Enter for newline)",onChange:de,onKeyDown:me,onPaste:le})]}),t.jsx(Zt,{images:_,onRemove:ue})]}),t.jsx(R,{className:j.attachBtn,variant:"ghost",size:"md",iconOnly:!0,title:"Attach image",onClick:()=>{var a;return(a=U.current)==null?void 0:a.click()},children:t.jsx(Re,{size:16})}),t.jsx("input",{ref:U,className:j.hiddenFileInput,type:"file",accept:"image/*",multiple:!0,onChange:ce}),t.jsxs("div",{className:j.actions,children:[B?t.jsx(R,{size:"sm",disabled:!W,onClick:()=>void z("steer"),leftIcon:t.jsx(Ae,{size:14}),children:"Steer"}):t.jsx(R,{size:"sm",disabled:!W,onClick:()=>void z("send"),leftIcon:t.jsx(Fe,{size:14}),children:"Send"}),B&&t.jsx(R,{size:"sm",variant:"destructive",onClick:he,leftIcon:t.jsx(Oe,{size:14}),children:"Stop"})]})]})}const wn="_panel_xqpk6_1",Sn="_empty_xqpk6_8",K={panel:wn,empty:Sn};function Pn({tab:e}){const{sessionId:n}=e.data,s=C(i=>i.sessions[n]);return et(n),s?t.jsxs("div",{className:K.panel,children:[t.jsx(Vt,{session:s}),t.jsx(Nn,{sessionId:s.id})]}):t.jsx("div",{className:K.panel,children:t.jsx("div",{className:K.empty,children:"Session not found."})})}export{Pn as ChatPanel};
|
|
3
|
-
//# sourceMappingURL=ChatPanel-BwrtLljS.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
._row_moj0c_3{padding:8px 12px;border-radius:var(--pi-borderRadius-md, 6px);max-width:85%;white-space:pre-wrap;word-break:break-word;line-height:1.5;font-size:1.0625rem}._who_moj0c_13{display:block;font-size:.875rem;color:var(--pi-color-foregroundMuted, #7a8394);margin-bottom:3px;text-transform:uppercase;letter-spacing:.03em}._queuedBadge_moj0c_22{display:inline-flex;align-items:center;gap:2px;margin-left:6px;padding:0 4px;border-radius:3px;font-size:.8125rem;font-weight:600;text-transform:none;letter-spacing:normal;vertical-align:middle;background:#14141873;color:#c7cbd1}._user_moj0c_40{background:var(--pi-color-accentMuted, #1e3a5f);color:var(--pi-color-foreground, #dbe9ff);align-self:flex-end;border-bottom-right-radius:2px}._userPending_moj0c_47{opacity:.6}._userQueued_moj0c_51{opacity:.88}._userFailed_moj0c_55{background:var(--pi-color-destructive, #3a1515);color:var(--pi-color-destructiveForeground, #ff8a80);opacity:1}._userImages_moj0c_61{display:flex;gap:6px;flex-wrap:wrap;margin-top:6px}._userImage_moj0c_61{max-width:200px;max-height:150px;border-radius:4px;display:block;object-fit:cover;cursor:pointer}._imageDialog_moj0c_77{max-width:90vw}._imageDialogPreview_moj0c_81{display:block;max-width:90vw;max-height:80vh;object-fit:contain}._assistant_moj0c_90{background:var(--pi-color-surface, #1c1f26);color:var(--pi-color-foreground, #d6dae0);align-self:flex-start;border-bottom-left-radius:2px}._assistant_moj0c_90._streaming_moj0c_97{border-left:2px solid var(--pi-color-accent, #2e5cb8)}._streamingText_moj0c_101{white-space:pre-wrap;word-break:break-word}._cursor_moj0c_106{display:inline-block;margin-left:1px;animation:_blink_moj0c_1 1s step-start infinite;color:var(--pi-color-accentBright, #a2b4d7)}@keyframes _blink_moj0c_1{50%{opacity:0}}._reasoning_moj0c_121{background:var(--pi-color-background, #0f1115);color:var(--pi-color-foregroundMuted, #7a8394);font-style:italic;font-size:1rem;align-self:flex-start}._tool_moj0c_131{background:var(--pi-color-surface, #1c1f26);border:1px solid var(--pi-color-border, #2c313b);align-self:flex-start;font-size:1rem;max-width:90%;padding:0;overflow:hidden}._toolHeader_moj0c_141{display:flex;align-items:center;gap:6px;width:100%;padding:8px 12px;background:none;border:none;color:inherit;font:inherit;text-align:left;cursor:pointer}._toolHeader_moj0c_141:disabled{cursor:default}._toolChevron_moj0c_159{flex-shrink:0;color:var(--pi-color-foregroundMuted, #7a8394);transition:transform .12s ease}._toolChevronOpen_moj0c_165{transform:rotate(90deg)}._toolInlineDetail_moj0c_169{overflow:hidden;text-overflow:ellipsis;white-space:nowrap;color:var(--pi-color-foregroundMuted, #9aa0a6);font-family:var(--pi-font-mono, ui-monospace, monospace);min-width:0;flex:1}._toolBody_moj0c_179{border-top:1px solid var(--pi-color-border, #2c313b);max-height:420px;overflow:auto}._toolCode_moj0c_185{margin:0;padding:8px 12px;font-family:var(--pi-font-mono, ui-monospace, monospace);font-size:1rem;line-height:1.5;white-space:pre-wrap;word-break:break-word;color:var(--pi-color-foreground, #dbe3f0)}._toolIcon_moj0c_196{display:flex;align-items:center;flex-shrink:0}._toolIcon_moj0c_196._running_moj0c_202{color:var(--pi-color-accentBright, #a2b4d7);animation:_pulse_moj0c_1 1.2s ease-in-out infinite}._toolIcon_moj0c_196._completed_moj0c_207{color:var(--pi-color-statusSuccess, #27ae60)}._toolIcon_moj0c_196._error_moj0c_211{color:var(--pi-color-statusDanger, #c0392b)}@keyframes _pulse_moj0c_1{50%{opacity:.5}}._toolLabel_moj0c_221{font-weight:600;text-transform:capitalize}._toolBadge_moj0c_226{margin-left:auto}._error_moj0c_211{background:var(--pi-color-destructive, #3a1515);color:var(--pi-color-destructiveForeground, #ff8a80);align-self:flex-start}._system_moj0c_238{background:transparent;color:var(--pi-color-foregroundMuted, #7a8394);font-style:italic;align-self:flex-start;padding:4px 12px}._viewport_1yr1a_3{flex:1 1 auto;overflow-y:auto;min-height:0;padding:16px 20px}._inner_1yr1a_10{position:relative;width:100%}._rowWrap_1yr1a_15{position:absolute;top:0;left:0;width:100%;display:flex;flex-direction:column;padding-bottom:4px}._empty_1yr1a_25{display:flex;align-items:center;justify-content:center;height:100%;color:var(--pi-color-foregroundMuted, #7a8394);font-size:1.0625rem}._working_1yr1a_34{display:flex;align-items:center;gap:8px;padding:8px 2px 4px;color:var(--pi-color-foregroundMuted, #7a8394);font-size:1.0625rem}._workingDots_1yr1a_43{display:inline-flex;gap:4px}._workingDots_1yr1a_43 span{width:6px;height:6px;border-radius:50%;background:var(--pi-color-accentBright, #a2b4d7);animation:_workingBounce_1yr1a_1 1.2s ease-in-out infinite}._workingDots_1yr1a_43 span:nth-child(2){animation-delay:.16s}._workingDots_1yr1a_43 span:nth-child(3){animation-delay:.32s}@keyframes _workingBounce_1yr1a_1{0%,80%,to{opacity:.3;transform:translateY(0)}40%{opacity:1;transform:translateY(-3px)}}._strip_1pf1y_4{display:flex;gap:6px;flex-wrap:wrap;padding:6px 0 0}._thumb_1pf1y_11{position:relative;width:48px;height:48px;border-radius:4px;overflow:hidden;border:1px solid var(--pi-color-border, #2c313b);flex-shrink:0}._thumb_1pf1y_11 img{width:100%;height:100%;object-fit:cover;display:block}._remove_1pf1y_28{position:absolute;top:-2px;right:-2px;width:16px;height:16px;background:var(--pi-color-statusDanger, #c0392b);color:#fff;border:none;border-radius:50%;font-size:.875rem;line-height:16px;text-align:center;cursor:pointer;padding:0}._composer_10jfp_1{padding:10px 16px;border-top:1px solid var(--pi-color-border, #2c313b);background:var(--pi-color-surface, #14161a);display:flex;gap:8px;align-items:center;flex-shrink:0}._inputArea_10jfp_13{flex:1;display:flex;flex-direction:column;gap:0;min-width:0}._textarea_10jfp_21{resize:none;min-height:38px;max-height:160px;overflow-y:auto}._attachBtn_10jfp_28{flex-shrink:0}._slashBtn_10jfp_32{flex-shrink:0;border-color:var(--pi-color-border, #3f3f46)}._textareaWrap_10jfp_42{position:relative;display:flex;min-width:0}._textareaWrap_10jfp_42 ._textarea_10jfp_21{position:relative}._highlightLayer_10jfp_50{position:absolute;top:0;right:0;bottom:0;left:0;padding:8px 12px;border:1px solid transparent;box-sizing:border-box;font-size:var(--pi-font-size-base, 1.25rem);font-family:var(--pi-font-ui, system-ui, sans-serif);line-height:normal;white-space:pre-wrap;overflow-wrap:break-word;overflow:hidden;color:transparent;pointer-events:none}._commandMark_10jfp_65{background:color-mix(in srgb,var(--pi-color-accent, #2e5cb8) 24%,transparent);color:transparent;border-radius:4px;box-shadow:0 0 0 1px color-mix(in srgb,var(--pi-color-accent, #2e5cb8) 55%,transparent),0 0 0 3px color-mix(in srgb,var(--pi-color-accent, #2e5cb8) 24%,transparent)}._textareaOverlaid_10jfp_90{background:transparent!important}._hiddenFileInput_10jfp_94{display:none}._actions_10jfp_98{display:flex;flex-direction:row;gap:4px;flex-shrink:0}._panel_xqpk6_1{display:flex;flex-direction:column;height:100%;min-height:0}._empty_xqpk6_8{display:flex;align-items:center;justify-content:center;height:100%;color:var(--pi-color-foregroundMuted, #7a8394);font-size:1.0625rem}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
._wrap_1gxj7_1{height:100%;min-height:0;overflow:hidden}._wrap_1gxj7_1 .cm-theme,._wrap_1gxj7_1 .cm-editor{height:100%;font-size:var(--pi-font-size-code, .9375rem)}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
._diffView_hmfmp_1{font-size:1.0625rem;line-height:1.6;font-family:var(--pi-font-mono, ui-monospace, monospace);overflow-x:auto}._hunkHeader_hmfmp_7{background:var(--pi-color-surfaceSunken, #111);color:var(--pi-color-accentBright, #a2b4d7);padding:4px 14px;font-size:1rem;border-bottom:1px solid var(--pi-color-border, #353b46)}._line_hmfmp_14{padding:0 14px;white-space:pre-wrap;word-break:break-word}._add_hmfmp_19{background:color-mix(in srgb,var(--pi-color-diffAddition, #4ade80) 15%,transparent);color:var(--pi-color-diffAddition, #4ade80)}._del_hmfmp_23{background:color-mix(in srgb,var(--pi-color-diffDeletion, #ff8a80) 15%,transparent);color:var(--pi-color-diffDeletion, #ff8a80)}._ctx_hmfmp_27{color:var(--pi-color-foregroundMuted, #9aa0a6)}._ln_hmfmp_30{display:inline-block;width:50px;text-align:right;padding-right:10px;color:var(--pi-color-foregroundMuted, #9aa0a6);-webkit-user-select:none;user-select:none;font-size:1rem}
|
|
@@ -1,3 +0,0 @@
|
|
|
1
|
-
import{j as d}from"./vendor-react-CWo7Do4s.js";import{C as h}from"./vendor-04vXFIXe.js";const m="_diffView_hmfmp_1",o="_hunkHeader_hmfmp_7",u="_line_hmfmp_14",_="_add_hmfmp_19",p="_del_hmfmp_23",x="_ctx_hmfmp_27",k="_ln_hmfmp_30",i={diffView:m,hunkHeader:o,line:u,add:_,del:p,ctx:x,ln:k},N=/^@@ -(\d+)(?:,\d+)? \+(\d+)(?:,\d+)? @@/;function W(a){const r=a.split(`
|
|
2
|
-
`),e=[];let n=0,s=0;for(const t of r){if(t.startsWith("diff --git")){e.push({kind:"hunk-header",text:t});continue}if(!(t.startsWith("index ")||t.startsWith("---")||t.startsWith("+++"))){if(t.startsWith("@@")){const c=N.exec(t);if(c){const l=c[1],f=c[2];n=(l?parseInt(l,10):1)-1,s=(f?parseInt(f,10):1)-1}e.push({kind:"hunk-header",text:t});continue}t.startsWith("+")?(s++,e.push({kind:"add",text:t,lineNumber:s})):t.startsWith("-")?(n++,e.push({kind:"del",text:t,lineNumber:n})):(n++,s++,e.push({kind:"ctx",text:t,lineNumber:s}))}}return e}function w({patch:a}){const r=W(a);return d.jsx("div",{className:i.diffView,children:r.map((e,n)=>e.kind==="hunk-header"?d.jsx("div",{className:i.hunkHeader,children:e.text},n):d.jsxs("div",{className:h(i.line,i[e.kind]),children:[d.jsx("span",{className:i.ln,children:e.lineNumber??""}),e.text]},n))})}export{w as D};
|
|
3
|
-
//# sourceMappingURL=DiffView-dFsrDUgN.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
._panel_k3tz8_1{display:flex;flex-direction:column;height:100%;min-height:0}._header_k3tz8_7{display:flex;align-items:center;gap:8px;padding:8px 14px;background:var(--pi-color-surface, #16181a);border-bottom:1px solid var(--pi-color-border, #353b46);font-size:1.0625rem;flex-shrink:0}._path_k3tz8_17{color:var(--pi-color-accentBright, #a2b4d7);flex:1;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}._size_k3tz8_24{color:var(--pi-color-foregroundMuted, #9aa0a6);font-size:1rem;flex-shrink:0}._viewToggle_k3tz8_29{display:flex;gap:2px;flex-shrink:0}._body_k3tz8_34{flex:1;overflow:auto;min-height:0}._emptyState_k3tz8_39{display:flex;align-items:center;justify-content:center;gap:8px;color:var(--pi-color-foregroundMuted, #9aa0a6);font-size:1.0625rem;padding:20px}._diffEmpty_k3tz8_48{padding:30px;text-align:center;color:var(--pi-color-foregroundMuted, #9aa0a6);font-size:1.0625rem}
|
|
@@ -1,2 +0,0 @@
|
|
|
1
|
-
const t="_panel_k3tz8_1",e="_header_k3tz8_7",_="_path_k3tz8_17",o="_size_k3tz8_24",p="_viewToggle_k3tz8_29",a="_body_k3tz8_34",s="_emptyState_k3tz8_39",n="_diffEmpty_k3tz8_48",z={panel:t,header:e,path:_,size:o,viewToggle:p,body:a,emptyState:s,diffEmpty:n};export{z as p};
|
|
2
|
-
//# sourceMappingURL=FilePanel.module-CZJhfnR7.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"FilePanel.module-CZJhfnR7.js","sources":[],"sourcesContent":[],"names":[],"mappings":""}
|
|
@@ -1,2 +0,0 @@
|
|
|
1
|
-
import{r as l,j as o}from"./vendor-react-CWo7Do4s.js";import{a as R,S as q,h as N}from"./index-DtH67PKb.js";import{v as M}from"./vendor-molviewer-CARaM-YQ.js";import{S as x}from"./StatusBadge-Cripx88K.js";import{u as T}from"./use-file-download-DzZxLbm7.js";import{u as A}from"./use-file-watch-Hq88QNSC.js";import"./vendor-query-BGIh-vlp.js";import"./vendor-04vXFIXe.js";import"./vendor-markdown-YvkQLm_s.js";import"./vendor-highlight-Efc6A-g6.js";import"./vendor-icons-o8-A85LK.js";import"./vendor-overlays-BnmaUbKw.js";import"./vendor-dnd-CH6z-X6S.js";function F(e,t){return!e||!t?null:{url:t,name:e.split("/").pop()||e}}function V({changedAt:e,lastAppliedAt:t,modified:a}){return!(e===null||a||e===t)}const L={empty_path:"Nothing to save.",too_large:"File is too large to save (over 5 MiB).",not_found:"The file no longer exists.",unreadable:"The file could not be read.",not_a_file:"That path is not a file."};async function H(e,t,a){const n=await e.connection.request("file_write_request",{path:t,content:a});if(!n.ok){const r=n.error??"";throw new Error(L[r]??r??"Failed to save")}}const I={"--canvas":"var(--pi-color-surface0)","--well":"var(--pi-color-surface0)","--recess":"var(--pi-color-surface1)","--chrome":"var(--pi-color-surface1)","--control":"var(--pi-color-surface2)","--control-hover":"var(--pi-color-surfaceHover)","--control-strong-hover":"var(--pi-color-surfaceHover)","--border-control":"var(--pi-color-border)","--border-input":"var(--pi-color-border)","--popover":"var(--pi-color-surface1)","--popover-item-hover":"var(--pi-color-surfaceHover)","--row-hover":"var(--pi-color-surfaceHover)","--border-popover":"var(--pi-color-border)","--text-primary":"var(--pi-color-foreground)","--text-on-control":"var(--pi-color-foreground)"},B="_wrap_1q72q_1",k="_molViewer_1q72q_8",z="_emptyState_1q72q_12",O="_badges_1q72q_21",c={wrap:B,molViewer:k,emptyState:z,badges:O};function P({path:e,isActive:t,onModifiedChange:a}){var h;const n=R(s=>s.client),r=T(e??"",!!e),{changedAt:i}=A(e),E=l.useRef(null),v=l.useRef(!1),[u,m]=l.useState(null),[d,g]=l.useState(!1),[w,p]=l.useState(null),f=l.useRef(null),b=F(e,(h=r.data)==null?void 0:h.objectUrl);l.useEffect(()=>{V({changedAt:i,lastAppliedAt:f.current,modified:d})&&(f.current=i,r.refetch())},[i,d,r.refetch]);const j=i!==null&&i!==f.current&&d;async function y(s){if(e){if(!n){p("Not connected — cannot save.");return}p(null);try{await H(n,e,s.text()),s.saved()}catch(S){p(S instanceof Error?S.message:"Failed to save")}}}const _=(r.isError?r.error instanceof Error?r.error.message:"download failed":null)??(u==null?void 0:u.message)??null;return e&&r.isPending?o.jsx("div",{className:c.wrap,children:o.jsxs("div",{className:c.emptyState,children:[o.jsx(q,{size:"sm"})," Loading..."]})}):_?o.jsx("div",{className:c.wrap,children:o.jsxs("div",{className:c.emptyState,children:["Error: ",_]})}):o.jsxs("div",{className:c.wrap,"data-molecule-active":t?"true":"false",children:[o.jsxs("div",{className:c.badges,children:[j&&o.jsx(x,{label:"File changed on disk",variant:"muted"}),w&&o.jsx(x,{label:`Save failed: ${w}`,variant:"error"})]}),o.jsx(M,{ref:E,className:c.molViewer,theme:I,source:b,sourceMode:v.current?"update":"replace",onLoad:()=>{v.current=!0,m(null)},onLoadError:s=>m(s.error),onModifiedChange:s=>{g(s),a==null||a(s)},onSave:e?y:void 0})]})}const W="_panel_15zlw_1",$={panel:W};function se({tab:e}){const{path:t}=e.data,n=N(r=>r.activeTabId)===e.id;return o.jsx("div",{className:$.panel,children:o.jsx(P,{path:t,isActive:n})})}export{se as MoleculeViewerPanel};
|
|
2
|
-
//# sourceMappingURL=MoleculeViewerPanel-DLhr38Kg.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
._wrap_1q72q_1{display:flex;flex-direction:column;height:100%;min-height:0;position:relative}._molViewer_1q72q_8{flex:1;min-height:0}._emptyState_1q72q_12{display:flex;align-items:center;justify-content:center;gap:8px;color:var(--pi-color-foregroundMuted, #9aa0a6);font-size:1.0625rem;padding:20px}._badges_1q72q_21{position:absolute;top:8px;right:8px;z-index:1;display:flex;flex-direction:column;align-items:flex-end;gap:4px}._panel_15zlw_1{display:flex;flex-direction:column;height:100%;min-height:0}
|
|
@@ -1,2 +0,0 @@
|
|
|
1
|
-
import{j as n}from"./vendor-react-CWo7Do4s.js";const a="_badge_mw0ed_3",c={badge:a};function u(r){switch(r){case"success":return{token:"statusSuccess"};case"error":return{token:"statusDanger"};case"muted":return{token:"foregroundMuted"}}}function g({label:r,variant:s,className:e}){const{token:o}=u(s),t=`var(--pi-color-${o})`;return n.jsx("span",{className:`${c.badge}${e?` ${e}`:""}`,style:{backgroundColor:`color-mix(in srgb, ${t} 18%, transparent)`,borderColor:`color-mix(in srgb, ${t} 45%, transparent)`,color:t},children:r})}export{g as S};
|
|
2
|
-
//# sourceMappingURL=StatusBadge-Cripx88K.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
._badge_mw0ed_3{display:inline-flex;align-items:center;justify-content:center;padding:1px 6px;border-radius:9999px;border:1px solid;font-size:var(--pi-font-size-xs, .9375rem);font-family:var(--pi-font-ui, system-ui, sans-serif);font-weight:500;white-space:nowrap;line-height:1.5}
|
|
@@ -1,2 +0,0 @@
|
|
|
1
|
-
var A=Object.defineProperty;var I=(n,e,t)=>e in n?A(n,e,{enumerable:!0,configurable:!0,writable:!0,value:t}):n[e]=t;var g=(n,e,t)=>I(n,typeof e!="symbol"?e+"":e,t);import{r as a,j as l}from"./vendor-react-CWo7Do4s.js";import{x as B,a as F}from"./vendor-terminal-BhzX2_ts.js";import{g as E,a as N,h as T,S as D}from"./index-DtH67PKb.js";import"./vendor-04vXFIXe.js";import"./vendor-query-BGIh-vlp.js";import"./vendor-icons-o8-A85LK.js";import"./vendor-overlays-BnmaUbKw.js";import"./vendor-dnd-CH6z-X6S.js";import"./vendor-highlight-Efc6A-g6.js";import"./vendor-markdown-YvkQLm_s.js";class O{constructor(e){g(this,"subscribers",new Map);g(this,"detach",null);this.daemon=e}start(){this.detach||(this.detach=this.daemon.onTerminalFrame(e=>this.dispatch(e)))}stop(){var e;(e=this.detach)==null||e.call(this),this.detach=null}subscribeSlot(e,t){return this.subscribers.set(e,t),()=>{this.subscribers.get(e)===t&&this.subscribers.delete(e)}}hasSlot(e){return this.subscribers.has(e)}sendInput(e,t){this.daemon.sendBinary(E({opcode:"Input",slot:e,data:t}))}sendResize(e,t,m){this.daemon.sendBinary(E({opcode:"Resize",slot:e,rows:t,cols:m}))}dispatch(e){var m,p,u;const t=this.subscribers.get(e.slot);if(t)switch(e.opcode){case"Output":(m=t.onOutput)==null||m.call(t,e.data);return;case"Snapshot":(p=t.onSnapshot)==null||p.call(t,e.data);return;case"Restore":(u=t.onRestore)==null||u.call(t,e.data);return;default:return}}}const C="_wrap_rnunu_1",P="_terminal_rnunu_11",W="_status_rnunu_18",f={wrap:C,terminal:P,status:W},q=new WeakMap;function G(n){let e=q.get(n);return e||(e=new O(n),e.start(),q.set(n,e)),e}const H={background:"#181b1a",foreground:"#fafafa",cursor:"#a2b4d7",cursorAccent:"#181b1a",selectionBackground:"rgba(255,255,255,0.18)",black:"#18181b",red:"#ef4444",green:"#22c55e",yellow:"#f59e0b",blue:"#3b82f6",magenta:"#a855f7",cyan:"#14b8a6",white:"#d4d4d8",brightBlack:"#52525b",brightRed:"#f87171",brightGreen:"#4ade80",brightYellow:"#fbbf24",brightBlue:"#60a5fa",brightMagenta:"#c084fc",brightCyan:"#2dd4bf",brightWhite:"#fafafa"};function te({tab:n}){const e=n.data,t=N(r=>r.client),p=T(r=>r.activeTabId)===n.id,u=a.useRef(null),w=a.useRef(null),h=a.useRef(null),b=a.useRef(e.slot),S=a.useRef(t);S.current=t;const[c,k]=a.useState(e.slot),[_,v]=a.useState(null),d=a.useRef(!1),R=a.useRef(!1);return a.useEffect(()=>{if(d.current=!0,!t||b.current!==null||R.current)return()=>{d.current=!1};R.current=!0;const r=e.cwd||"~";return t.connection.request("create_terminal_request",{workspaceId:"",cwd:r}).then(s=>{const i=s.terminal.slot;if(!d.current){t.connection.request("kill_terminal_request",{slot:i}).catch(()=>{});return}b.current=i,k(i),T.getState().updateData(n.id,{slot:i})}).catch(s=>{d.current&&v(s instanceof Error?s.message:String(s))}).finally(()=>{R.current=!1}),()=>{d.current=!1}},[t,n.id]),a.useEffect(()=>()=>{const r=b.current;r!==null&&setTimeout(()=>{var s;d.current||(s=S.current)==null||s.connection.request("kill_terminal_request",{slot:r}).catch(()=>{})},0)},[]),a.useEffect(()=>{if(!t||c===null||!u.current)return;const r=new B.Terminal({cursorBlink:!0,fontFamily:"ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, monospace",fontSize:16,scrollback:5e3,theme:H,allowProposedApi:!0}),s=new F.FitAddon;r.loadAddon(s),r.open(u.current),s.fit(),w.current=r,h.current=s;const i=G(t.connection),j=i.subscribeSlot(c,{onOutput:o=>r.write(o),onSnapshot:o=>{r.clear(),r.write(o)},onRestore:o=>r.write(o)});t.connection.request("subscribe_terminal_request",{slot:c}).catch(o=>{v(o instanceof Error?o.message:String(o))});const y=r.onData(o=>{i.sendInput(c,new TextEncoder().encode(o))}),z=r.onResize(({cols:o,rows:M})=>{i.sendResize(c,M,o)}),x=new ResizeObserver(()=>{s.fit()});return x.observe(u.current),()=>{x.disconnect(),y.dispose(),z.dispose(),j(),t.connection.request("unsubscribe_terminal_request",{slot:c}).catch(()=>{}),r.dispose(),w.current=null,h.current=null}},[t,c]),a.useEffect(()=>{var r;p&&((r=h.current)==null||r.fit())},[p]),_?l.jsx("div",{className:f.wrap,children:l.jsxs("div",{className:f.status,children:["Terminal error: ",_]})}):c===null?l.jsx("div",{className:f.wrap,children:l.jsxs("div",{className:f.status,children:[l.jsx(D,{size:"sm"})," Starting terminal…"]})}):l.jsx("div",{className:f.wrap,children:l.jsx("div",{ref:u,className:f.terminal})})}export{te as TerminalPanel};
|
|
2
|
-
//# sourceMappingURL=TerminalPanel-BX9bO1dW.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"TerminalPanel-BX9bO1dW.js","sources":["../../../../client/src/terminal-stream-router.ts","../../../src/features/terminal/TerminalPanel.tsx"],"sourcesContent":["import { encodeTerminalFrame, type TerminalFrame } from \"@av-pi-studio/protocol\";\n\nimport type { DaemonClient } from \"./daemon-client.js\";\n\n/**\n * Client-side demux of binary terminal frames to per-slot subscribers, plus outbound input/resize\n * encoding (architecture/client-app-runtime.md § Router; features/terminals.md § Binary stream\n * protocol).\n *\n * Inbound `Output`/`Snapshot`/`Restore` frames are dispatched to the subscriber registered for that\n * `slot`. Outbound `Input`/`Resize` are encoded with the right opcode + slot and sent on the data\n * path.\n */\n\nexport interface TerminalSlotSubscriber {\n /** Live terminal output bytes. */\n onOutput?: (data: Uint8Array) => void;\n /** Full-screen snapshot bytes (sent on (re)subscribe). */\n onSnapshot?: (data: Uint8Array) => void;\n /** Restore snapshot bytes (reflowable/mode-gated). */\n onRestore?: (data: Uint8Array) => void;\n}\n\nexport class TerminalStreamRouter {\n private readonly subscribers = new Map<number, TerminalSlotSubscriber>();\n private detach: (() => void) | null = null;\n\n constructor(private readonly daemon: DaemonClient) {}\n\n /** Begin routing inbound terminal frames. Idempotent. */\n start(): void {\n if (this.detach) return;\n this.detach = this.daemon.onTerminalFrame((frame) => this.dispatch(frame));\n }\n\n /** Stop routing inbound frames (subscribers retained). */\n stop(): void {\n this.detach?.();\n this.detach = null;\n }\n\n /** Register (or replace) the subscriber for a slot. Returns an unsubscribe fn. */\n subscribeSlot(slot: number, subscriber: TerminalSlotSubscriber): () => void {\n this.subscribers.set(slot, subscriber);\n return () => {\n if (this.subscribers.get(slot) === subscriber) this.subscribers.delete(slot);\n };\n }\n\n /** True iff a subscriber is registered for the slot. */\n hasSlot(slot: number): boolean {\n return this.subscribers.has(slot);\n }\n\n // ─── Outbound ─────────────────────────────────────────────────────────────\n\n /** Send raw input bytes to a slot's PTY (opcode `Input = 0x02`). */\n sendInput(slot: number, data: Uint8Array): void {\n this.daemon.sendBinary(encodeTerminalFrame({ opcode: \"Input\", slot, data }));\n }\n\n /** Send a resize (opcode `Resize = 0x03`, JSON `{ rows, cols }` payload). */\n sendResize(slot: number, rows: number, cols: number): void {\n this.daemon.sendBinary(encodeTerminalFrame({ opcode: \"Resize\", slot, rows, cols }));\n }\n\n // ─── Inbound dispatch ───────────────────────────────────────────────────────\n\n private dispatch(frame: TerminalFrame): void {\n const subscriber = this.subscribers.get(frame.slot);\n if (!subscriber) return; // no subscriber for this slot — drop\n switch (frame.opcode) {\n case \"Output\":\n subscriber.onOutput?.(frame.data);\n return;\n case \"Snapshot\":\n subscriber.onSnapshot?.(frame.data);\n return;\n case \"Restore\":\n subscriber.onRestore?.(frame.data);\n return;\n default:\n // Input/Resize are outbound-only; ignore if echoed back.\n return;\n }\n }\n}\n","/**\n * TerminalPanel — @xterm/xterm mount + binary-frame streaming via `TerminalStreamRouter`\n * (POC `initTerminalPanel`, POC_TO_APP_PLAN_UI.md §4.6). Strict upgrade over the POC's 800ms\n * `capture_terminal_request` poll: the daemon pushes `Output`/`Snapshot`/`Restore` binary frames\n * directly over the one shared `DaemonClient` connection, demuxed by slot.\n *\n * Slot lifecycle: created once via `create_terminal_request`, then persisted onto the tab's\n * `TerminalTabData.slot` via `useTabStore.getState().updateData` so switching away and back to\n * this tab (kept mounted-but-hidden by `TabPanelHost`) never recreates the terminal. `TabPanelHost`\n * only unmounts a tab's panel when the tab leaves the store's `tabs[]` (i.e. real tab close, never\n * a tab switch) — this component's true-unmount effect below relies on exactly that invariant to\n * send `kill_terminal_request`, terminating the PTY server-side instead of leaking it forever.\n */\n\nimport { useEffect, useRef, useState } from \"react\";\nimport { Terminal } from \"@xterm/xterm\";\nimport { FitAddon } from \"@xterm/addon-fit\";\nimport \"@xterm/xterm/css/xterm.css\";\nimport type { DaemonClient } from \"@av-pi-studio/client\";\nimport { TerminalStreamRouter } from \"@av-pi-studio/client\";\nimport { useConnectionStore } from \"@pi-studio-ui/lib/connection/connection-store.js\";\nimport { useTabStore } from \"@pi-studio-ui/stores/tab-store.js\";\nimport type { Tab, TerminalTabData } from \"@pi-studio-ui/stores/tab-store.js\";\nimport { Spinner } from \"@pi-studio-ui/components/primitives/Spinner.js\";\nimport styles from \"./TerminalPanel.module.css\";\n\nexport interface TerminalPanelProps {\n tab: Tab;\n}\n\ninterface CreateTerminalResponse {\n terminal: { slot: number };\n}\n\n// One TerminalStreamRouter per daemon connection — multiple terminal tabs share it rather than\n// each opening its own frame demuxer over the same socket.\nconst routerByDaemon = new WeakMap<DaemonClient, TerminalStreamRouter>();\n\nfunction routerFor(daemon: DaemonClient): TerminalStreamRouter {\n let router = routerByDaemon.get(daemon);\n if (!router) {\n router = new TerminalStreamRouter(daemon);\n router.start();\n routerByDaemon.set(daemon, router);\n }\n return router;\n}\n\n/** Dark palette matching the app's github-dark-ish default theme (theme/variants.ts \"dark\"). */\nconst TERMINAL_THEME = {\n background: \"#181b1a\",\n foreground: \"#fafafa\",\n cursor: \"#a2b4d7\",\n cursorAccent: \"#181b1a\",\n selectionBackground: \"rgba(255,255,255,0.18)\",\n black: \"#18181b\",\n red: \"#ef4444\",\n green: \"#22c55e\",\n yellow: \"#f59e0b\",\n blue: \"#3b82f6\",\n magenta: \"#a855f7\",\n cyan: \"#14b8a6\",\n white: \"#d4d4d8\",\n brightBlack: \"#52525b\",\n brightRed: \"#f87171\",\n brightGreen: \"#4ade80\",\n brightYellow: \"#fbbf24\",\n brightBlue: \"#60a5fa\",\n brightMagenta: \"#c084fc\",\n brightCyan: \"#2dd4bf\",\n brightWhite: \"#fafafa\",\n};\n\nexport function TerminalPanel({ tab }: TerminalPanelProps) {\n const data = tab.data as TerminalTabData;\n const client = useConnectionStore((s) => s.client);\n const activeTabId = useTabStore((s) => s.activeTabId);\n const isActive = activeTabId === tab.id;\n\n const containerRef = useRef<HTMLDivElement | null>(null);\n const terminalRef = useRef<Terminal | null>(null);\n const fitAddonRef = useRef<FitAddon | null>(null);\n const slotRef = useRef<number | null>(data.slot);\n // Mirrors `use-checkout-status.ts`'s convention: kept in sync every render so the unmount-only\n // kill effect below always sends the CURRENT client, never a stale mount-time closure (e.g.\n // after a reconnect swaps in a new `PiStudioClient` instance).\n const clientRef = useRef(client);\n clientRef.current = client;\n\n const [slot, setSlot] = useState<number | null>(data.slot);\n const [error, setError] = useState<string | null>(null);\n\n // ─── Slot lifecycle: create once, persist onto the tab so re-opening reuses it ─────────────\n // React StrictMode double-invokes effects in dev: mount → cleanup → remount, synchronously,\n // on the SAME component instance (refs/state persist across all three phases — this is not\n // three separate mounts). Two things must hold across that: (1) the request fires exactly\n // once, and (2) whether to APPLY the eventual response is decided by whether the component is\n // mounted at RESPONSE time, not by a flag captured at REQUEST time.\n //\n // `requestStartedRef` gives (1): set the instant the request fires and never reset, so the\n // phantom-mount's cleanup-then-remount sees it's already in flight and never fires a second\n // `create_terminal_request` (this is what previously spawned two real PTYs from one Ctrl+T).\n //\n // `isMountedRef` gives (2): flipped true at the START of every effect invocation and false in\n // every cleanup, so it always reflects the LATEST phase. StrictMode's remount happens\n // synchronously, before the request's promise can possibly settle, so by response time\n // `isMountedRef.current` is back to `true` for a StrictMode phantom (correctly applies the\n // slot) — but stays `false` for a genuine fast real close (correctly kills the orphaned PTY\n // instead of leaking it or, as the previous buggy version did, killing a terminal that was\n // never actually torn down).\n const isMountedRef = useRef(false);\n const requestStartedRef = useRef(false);\n useEffect(() => {\n isMountedRef.current = true;\n if (!client || slotRef.current !== null || requestStartedRef.current) {\n return () => {\n isMountedRef.current = false;\n };\n }\n requestStartedRef.current = true;\n\n const cwd = data.cwd || \"~\";\n\n void client.connection\n .request<CreateTerminalResponse>(\"create_terminal_request\", { workspaceId: \"\", cwd })\n .then((res) => {\n const created = res.terminal.slot;\n if (!isMountedRef.current) {\n // A real close happened with no remount after it — kill the PTY that finished\n // spawning after the tab was already gone, instead of leaking it.\n void client.connection\n .request(\"kill_terminal_request\", { slot: created })\n .catch(() => {});\n return;\n }\n slotRef.current = created;\n setSlot(created);\n useTabStore.getState().updateData(tab.id, { slot: created });\n })\n .catch((err: unknown) => {\n if (!isMountedRef.current) return;\n setError(err instanceof Error ? err.message : String(err));\n })\n .finally(() => {\n // Reset only after the promise settles — by then StrictMode's synchronous\n // mount→cleanup→remount window has long passed, so this can never reopen the\n // double-fire race. It DOES allow a legitimate retry (e.g. `client` changed because of\n // a reconnect after the first attempt failed) instead of leaving the tab stuck forever.\n requestStartedRef.current = false;\n });\n\n return () => {\n isMountedRef.current = false;\n };\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, [client, tab.id]);\n\n // ─── True unmount only: kill the PTY server-side ───────────────────────────────────────────\n // Runs its cleanup exactly once, when this component itself unmounts (real tab close, per\n // `TabPanelHost`'s \"hidden but alive\" model — a tab switch never unmounts). An empty deps array\n // means React never re-runs the effect body itself; only the cleanup fires, and only on\n // unmount, so this never races the slot-creation effect above or double-kills on a client\n // change. Without this, every closed terminal tab leaked its PTY process forever.\n //\n // For a REATTACH (this tab opened with a non-null `data.slot` from the very first render —\n // `use-terminal-restore.ts`, or the create-effect above once it has resolved) `slotRef.current`\n // is non-null from the start, so StrictMode's synchronous mount→cleanup→remount phantom cycle\n // would fire this cleanup and kill the PTY immediately on mount — unlike a freshly created\n // terminal, where `slotRef.current` is still `null` during that same phantom window (see the\n // create-effect's own comment) and so never hits this path. Deferred via `setTimeout`, exactly\n // like the create-effect's response handler: by the time it fires, StrictMode's remount has\n // already flipped `isMountedRef` back to `true` if this was a phantom unmount, so the kill is\n // skipped; a genuine close never remounts, so `isMountedRef` stays `false` and the kill proceeds.\n useEffect(() => {\n return () => {\n const currentSlot = slotRef.current;\n if (currentSlot === null) return;\n setTimeout(() => {\n if (isMountedRef.current) return; // StrictMode remounted synchronously — not a real close\n void clientRef.current?.connection\n .request(\"kill_terminal_request\", { slot: currentSlot })\n .catch(() => {});\n }, 0);\n };\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, []);\n\n // ─── xterm mount (once slot + container are ready) ─────────────────────────────────────────\n useEffect(() => {\n if (!client || slot === null || !containerRef.current) return;\n\n const terminal = new Terminal({\n cursorBlink: true,\n fontFamily: \"ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, monospace\",\n fontSize: 16,\n scrollback: 5000,\n theme: TERMINAL_THEME,\n allowProposedApi: true,\n });\n const fitAddon = new FitAddon();\n terminal.loadAddon(fitAddon);\n terminal.open(containerRef.current);\n fitAddon.fit();\n\n terminalRef.current = terminal;\n fitAddonRef.current = fitAddon;\n\n const router = routerFor(client.connection);\n const unsubscribeSlot = router.subscribeSlot(slot, {\n onOutput: (chunk) => terminal.write(chunk),\n onSnapshot: (chunk) => {\n terminal.clear();\n terminal.write(chunk);\n },\n onRestore: (chunk) => terminal.write(chunk),\n });\n\n void client.connection.request(\"subscribe_terminal_request\", { slot }).catch((err: unknown) => {\n setError(err instanceof Error ? err.message : String(err));\n });\n\n const dataDisposable = terminal.onData((chunk) => {\n router.sendInput(slot, new TextEncoder().encode(chunk));\n });\n const resizeDisposable = terminal.onResize(({ cols, rows }) => {\n router.sendResize(slot, rows, cols);\n });\n\n const resizeObserver = new ResizeObserver(() => {\n fitAddon.fit();\n });\n resizeObserver.observe(containerRef.current);\n\n return () => {\n resizeObserver.disconnect();\n dataDisposable.dispose();\n resizeDisposable.dispose();\n unsubscribeSlot();\n void client.connection.request(\"unsubscribe_terminal_request\", { slot }).catch(() => {});\n terminal.dispose();\n terminalRef.current = null;\n fitAddonRef.current = null;\n };\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, [client, slot]);\n\n // ─── Re-fit whenever this tab becomes the active (visible) one ────────────────────────────\n useEffect(() => {\n if (!isActive) return;\n fitAddonRef.current?.fit();\n }, [isActive]);\n\n if (error) {\n return (\n <div className={styles.wrap}>\n <div className={styles.status}>Terminal error: {error}</div>\n </div>\n );\n }\n\n if (slot === null) {\n return (\n <div className={styles.wrap}>\n <div className={styles.status}>\n <Spinner size=\"sm\" /> Starting terminal…\n </div>\n </div>\n );\n }\n\n return (\n <div className={styles.wrap}>\n <div ref={containerRef} className={styles.terminal} />\n </div>\n );\n}\n"],"names":["TerminalStreamRouter","daemon","__publicField","frame","_a","slot","subscriber","data","encodeTerminalFrame","rows","cols","_b","_c","routerByDaemon","routerFor","router","TERMINAL_THEME","TerminalPanel","tab","client","useConnectionStore","s","isActive","useTabStore","containerRef","useRef","terminalRef","fitAddonRef","slotRef","clientRef","setSlot","useState","error","setError","isMountedRef","requestStartedRef","useEffect","cwd","res","created","err","currentSlot","terminal","Terminal","fitAddon","FitAddon","unsubscribeSlot","chunk","dataDisposable","resizeDisposable","resizeObserver","jsx","styles","jsxs","Spinner"],"mappings":"ukBAuBO,MAAMA,CAAqB,CAIhC,YAA6BC,EAAsB,CAHlCC,EAAA,uBAAkB,KAC3BA,EAAA,cAA8B,MAET,KAAA,OAAAD,CAAuB,CAGpD,OAAc,CACR,KAAK,SACT,KAAK,OAAS,KAAK,OAAO,gBAAiBE,GAAU,KAAK,SAASA,CAAK,CAAC,EAC3E,CAGA,MAAa,QACXC,EAAA,KAAK,SAAL,MAAAA,EAAA,WACA,KAAK,OAAS,IAChB,CAGA,cAAcC,EAAcC,EAAgD,CAC1E,YAAK,YAAY,IAAID,EAAMC,CAAU,EAC9B,IAAM,CACP,KAAK,YAAY,IAAID,CAAI,IAAMC,GAAY,KAAK,YAAY,OAAOD,CAAI,CAC7E,CACF,CAGA,QAAQA,EAAuB,CAC7B,OAAO,KAAK,YAAY,IAAIA,CAAI,CAClC,CAKA,UAAUA,EAAcE,EAAwB,CAC9C,KAAK,OAAO,WAAWC,EAAoB,CAAE,OAAQ,QAAS,KAAAH,EAAM,KAAAE,CAAA,CAAM,CAAC,CAC7E,CAGA,WAAWF,EAAcI,EAAcC,EAAoB,CACzD,KAAK,OAAO,WAAWF,EAAoB,CAAE,OAAQ,SAAU,KAAAH,EAAM,KAAAI,EAAM,KAAAC,CAAA,CAAM,CAAC,CACpF,CAIQ,SAASP,EAA4B,WAC3C,MAAMG,EAAa,KAAK,YAAY,IAAIH,EAAM,IAAI,EAClD,GAAKG,EACL,OAAQH,EAAM,OAAA,CACZ,IAAK,UACHC,EAAAE,EAAW,WAAX,MAAAF,EAAA,KAAAE,EAAsBH,EAAM,MAC5B,OACF,IAAK,YACHQ,EAAAL,EAAW,aAAX,MAAAK,EAAA,KAAAL,EAAwBH,EAAM,MAC9B,OACF,IAAK,WACHS,EAAAN,EAAW,YAAX,MAAAM,EAAA,KAAAN,EAAuBH,EAAM,MAC7B,OACF,QAEE,MAAA,CAEN,CACF,oGClDMU,MAAqB,QAE3B,SAASC,EAAUb,EAA4C,CAC7D,IAAIc,EAASF,EAAe,IAAIZ,CAAM,EACtC,OAAKc,IACHA,EAAS,IAAIf,EAAqBC,CAAM,EACxCc,EAAO,MAAA,EACPF,EAAe,IAAIZ,EAAQc,CAAM,GAE5BA,CACT,CAGA,MAAMC,EAAiB,CACrB,WAAY,UACZ,WAAY,UACZ,OAAQ,UACR,aAAc,UACd,oBAAqB,yBACrB,MAAO,UACP,IAAK,UACL,MAAO,UACP,OAAQ,UACR,KAAM,UACN,QAAS,UACT,KAAM,UACN,MAAO,UACP,YAAa,UACb,UAAW,UACX,YAAa,UACb,aAAc,UACd,WAAY,UACZ,cAAe,UACf,WAAY,UACZ,YAAa,SACf,EAEO,SAASC,GAAc,CAAE,IAAAC,GAA2B,CACzD,MAAMX,EAAOW,EAAI,KACXC,EAASC,EAAoBC,GAAMA,EAAE,MAAM,EAE3CC,EADcC,EAAaF,GAAMA,EAAE,WAAW,IACnBH,EAAI,GAE/BM,EAAeC,EAAAA,OAA8B,IAAI,EACjDC,EAAcD,EAAAA,OAAwB,IAAI,EAC1CE,EAAcF,EAAAA,OAAwB,IAAI,EAC1CG,EAAUH,EAAAA,OAAsBlB,EAAK,IAAI,EAIzCsB,EAAYJ,EAAAA,OAAON,CAAM,EAC/BU,EAAU,QAAUV,EAEpB,KAAM,CAACd,EAAMyB,CAAO,EAAIC,EAAAA,SAAwBxB,EAAK,IAAI,EACnD,CAACyB,EAAOC,CAAQ,EAAIF,EAAAA,SAAwB,IAAI,EAoBhDG,EAAeT,EAAAA,OAAO,EAAK,EAC3BU,EAAoBV,EAAAA,OAAO,EAAK,EA6ItC,OA5IAW,EAAAA,UAAU,IAAM,CAEd,GADAF,EAAa,QAAU,GACnB,CAACf,GAAUS,EAAQ,UAAY,MAAQO,EAAkB,QAC3D,MAAO,IAAM,CACXD,EAAa,QAAU,EACzB,EAEFC,EAAkB,QAAU,GAE5B,MAAME,EAAM9B,EAAK,KAAO,IAExB,OAAKY,EAAO,WACT,QAAgC,0BAA2B,CAAE,YAAa,GAAI,IAAAkB,CAAA,CAAK,EACnF,KAAMC,GAAQ,CACb,MAAMC,EAAUD,EAAI,SAAS,KAC7B,GAAI,CAACJ,EAAa,QAAS,CAGpBf,EAAO,WACT,QAAQ,wBAAyB,CAAE,KAAMoB,CAAA,CAAS,EAClD,MAAM,IAAM,CAAC,CAAC,EACjB,MACF,CACAX,EAAQ,QAAUW,EAClBT,EAAQS,CAAO,EACfhB,EAAY,SAAA,EAAW,WAAWL,EAAI,GAAI,CAAE,KAAMqB,EAAS,CAC7D,CAAC,EACA,MAAOC,GAAiB,CAClBN,EAAa,SAClBD,EAASO,aAAe,MAAQA,EAAI,QAAU,OAAOA,CAAG,CAAC,CAC3D,CAAC,EACA,QAAQ,IAAM,CAKbL,EAAkB,QAAU,EAC9B,CAAC,EAEI,IAAM,CACXD,EAAa,QAAU,EACzB,CAEF,EAAG,CAACf,EAAQD,EAAI,EAAE,CAAC,EAkBnBkB,EAAAA,UAAU,IACD,IAAM,CACX,MAAMK,EAAcb,EAAQ,QACxBa,IAAgB,MACpB,WAAW,IAAM,OACXP,EAAa,UACZ9B,EAAAyB,EAAU,UAAV,MAAAzB,EAAmB,WACrB,QAAQ,wBAAyB,CAAE,KAAMqC,CAAA,GACzC,MAAM,IAAM,CAAC,EAClB,EAAG,CAAC,CACN,EAEC,CAAA,CAAE,EAGLL,EAAAA,UAAU,IAAM,CACd,GAAI,CAACjB,GAAUd,IAAS,MAAQ,CAACmB,EAAa,QAAS,OAEvD,MAAMkB,EAAW,IAAIC,WAAS,CAC5B,YAAa,GACb,WAAY,mEACZ,SAAU,GACV,WAAY,IACZ,MAAO3B,EACP,iBAAkB,EAAA,CACnB,EACK4B,EAAW,IAAIC,WACrBH,EAAS,UAAUE,CAAQ,EAC3BF,EAAS,KAAKlB,EAAa,OAAO,EAClCoB,EAAS,IAAA,EAETlB,EAAY,QAAUgB,EACtBf,EAAY,QAAUiB,EAEtB,MAAM7B,EAASD,EAAUK,EAAO,UAAU,EACpC2B,EAAkB/B,EAAO,cAAcV,EAAM,CACjD,SAAW0C,GAAUL,EAAS,MAAMK,CAAK,EACzC,WAAaA,GAAU,CACrBL,EAAS,MAAA,EACTA,EAAS,MAAMK,CAAK,CACtB,EACA,UAAYA,GAAUL,EAAS,MAAMK,CAAK,CAAA,CAC3C,EAEI5B,EAAO,WAAW,QAAQ,6BAA8B,CAAE,KAAAd,EAAM,EAAE,MAAOmC,GAAiB,CAC7FP,EAASO,aAAe,MAAQA,EAAI,QAAU,OAAOA,CAAG,CAAC,CAC3D,CAAC,EAED,MAAMQ,EAAiBN,EAAS,OAAQK,GAAU,CAChDhC,EAAO,UAAUV,EAAM,IAAI,cAAc,OAAO0C,CAAK,CAAC,CACxD,CAAC,EACKE,EAAmBP,EAAS,SAAS,CAAC,CAAE,KAAAhC,EAAM,KAAAD,KAAW,CAC7DM,EAAO,WAAWV,EAAMI,EAAMC,CAAI,CACpC,CAAC,EAEKwC,EAAiB,IAAI,eAAe,IAAM,CAC9CN,EAAS,IAAA,CACX,CAAC,EACD,OAAAM,EAAe,QAAQ1B,EAAa,OAAO,EAEpC,IAAM,CACX0B,EAAe,WAAA,EACfF,EAAe,QAAA,EACfC,EAAiB,QAAA,EACjBH,EAAA,EACK3B,EAAO,WAAW,QAAQ,+BAAgC,CAAE,KAAAd,CAAA,CAAM,EAAE,MAAM,IAAM,CAAC,CAAC,EACvFqC,EAAS,QAAA,EACThB,EAAY,QAAU,KACtBC,EAAY,QAAU,IACxB,CAEF,EAAG,CAACR,EAAQd,CAAI,CAAC,EAGjB+B,EAAAA,UAAU,IAAM,OACTd,KACLlB,EAAAuB,EAAY,UAAZ,MAAAvB,EAAqB,MACvB,EAAG,CAACkB,CAAQ,CAAC,EAETU,EAEAmB,EAAAA,IAAC,OAAI,UAAWC,EAAO,KACrB,SAAAC,EAAAA,KAAC,MAAA,CAAI,UAAWD,EAAO,OAAQ,SAAA,CAAA,mBAAiBpB,CAAA,CAAA,CAAM,CAAA,CACxD,EAIA3B,IAAS,KAET8C,EAAAA,IAAC,OAAI,UAAWC,EAAO,KACrB,SAAAC,EAAAA,KAAC,MAAA,CAAI,UAAWD,EAAO,OACrB,SAAA,CAAAD,EAAAA,IAACG,EAAA,CAAQ,KAAK,IAAA,CAAK,EAAE,qBAAA,CAAA,CACvB,CAAA,CACF,EAKFH,EAAAA,IAAC,MAAA,CAAI,UAAWC,EAAO,KACrB,SAAAD,EAAAA,IAAC,MAAA,CAAI,IAAK3B,EAAc,UAAW4B,EAAO,QAAA,CAAU,EACtD,CAEJ"}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
._wrap_rnunu_1{display:flex;flex-direction:column;flex:1 1 auto;min-height:0;height:100%;width:100%;overflow:hidden;background:var(--pi-terminal-bg, #181b1a)}._terminal_rnunu_11{flex:1 1 auto;min-height:0;width:100%;overflow:hidden;padding:6px 8px}._status_rnunu_18{display:flex;align-items:center;justify-content:center;gap:8px;height:100%;color:var(--pi-color-foregroundMuted, #9aa0a6);font-size:1.0625rem}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
._wrap_le8v3_1{display:flex;flex-direction:column;height:100%;min-height:0}._note_le8v3_7{padding:4px 14px;font-size:1rem;color:var(--pi-color-foregroundMuted, #9aa0a6);background:var(--pi-color-surface, #16181a);border-bottom:1px solid var(--pi-color-border, #353b46);flex-shrink:0}._body_le8v3_15{flex:1;min-height:0}._tooLarge_le8v3_19{display:flex;flex-direction:column;align-items:center;gap:12px}
|