@hienlh/ppm 0.13.7 → 0.13.9

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (102) hide show
  1. package/CHANGELOG.md +16 -0
  2. package/assets/skills/ppm/SKILL.md +1 -1
  3. package/assets/skills/ppm/references/http-api.md +1 -1
  4. package/dist/web/assets/ai-settings-section-CLNBWLS4.js +1 -0
  5. package/dist/web/assets/{api-settings-t7Leca7J.js → api-settings-D0_eiIYv.js} +1 -1
  6. package/dist/web/assets/architecture-PBZL5I3N-WMbLpD5Y.js +1 -0
  7. package/dist/web/assets/{audio-preview-BR7DoH0l.js → audio-preview-C1p-Q5XZ.js} +1 -1
  8. package/dist/web/assets/{chat-tab-8Bvn7PHt.js → chat-tab-BSJUkgxB.js} +9 -9
  9. package/dist/web/assets/code-editor-rNw5_pXh.js +8 -0
  10. package/dist/web/assets/{conflict-editor-C-lUw4gv.js → conflict-editor-Dcn3HuLD.js} +1 -1
  11. package/dist/web/assets/{csv-preview-C9qGhDlb.js → csv-preview-D5lmgVEy.js} +1 -1
  12. package/dist/web/assets/data-grid-nZfSIop5.js +5 -0
  13. package/dist/web/assets/database-DOWH9-Vv.js +1 -0
  14. package/dist/web/assets/database-viewer-CNoq5Uxp.js +1 -0
  15. package/dist/web/assets/{diff-viewer-I8qs3Nb-.js → diff-viewer-NMLD4V8q.js} +1 -1
  16. package/dist/web/assets/{esm-B3je8j5P.js → esm-nXReYVnB.js} +1 -1
  17. package/dist/web/assets/{extension-webview-Dt9bKs0C.js → extension-webview-DW2dBswj.js} +1 -1
  18. package/dist/web/assets/{file-store-BgZggznw.js → file-store-BrbCNyLm.js} +1 -1
  19. package/dist/web/assets/gitGraph-HDMCJU4V-BdPTuzO3.js +1 -0
  20. package/dist/web/assets/{image-preview-C-w-CK5s.js → image-preview-Dqp1KSus.js} +1 -1
  21. package/dist/web/assets/index-CoMWx5VS.js +27 -0
  22. package/dist/web/assets/index-Dzb3OtrX.css +2 -0
  23. package/dist/web/assets/info-3K5VOQVL-MHX_1JfR.js +1 -0
  24. package/dist/web/assets/{input-bGJExpJZ.js → input-DYWhyaze.js} +1 -1
  25. package/dist/web/assets/keybindings-store-B7nlHmDh.js +1 -0
  26. package/dist/web/assets/{markdown-renderer-ySnJPmc1.js → markdown-renderer-DNIXdY0d.js} +3 -3
  27. package/dist/web/assets/packet-RMMSAZCW-CreFbf9A.js +1 -0
  28. package/dist/web/assets/{pdf-preview-BoQTv6B2.js → pdf-preview-ChC1gaaZ.js} +1 -1
  29. package/dist/web/assets/pie-UPGHQEXC-CnaHXUh8.js +1 -0
  30. package/dist/web/assets/port-forwarding-tab-dLhH_g2l.js +1 -0
  31. package/dist/web/assets/{postgres-viewer-CBntLqXY.js → postgres-viewer-De0pzd1C.js} +3 -3
  32. package/dist/web/assets/radar-KQ55EAFF-UxsdRHvt.js +1 -0
  33. package/dist/web/assets/{scroll-area-D0EQpAH2.js → scroll-area-BEllam7_.js} +1 -1
  34. package/dist/web/assets/{settings-store-CdcSAgEZ.js → settings-store-BHBb62gq.js} +2 -2
  35. package/dist/web/assets/settings-tab-Mrs9uzCZ.js +1 -0
  36. package/dist/web/assets/sparkles-B0mRBy_j.js +1 -0
  37. package/dist/web/assets/{sql-query-editor-vpD0I0KG.js → sql-query-editor-CMQpaOjA.js} +1 -1
  38. package/dist/web/assets/sqlite-viewer-BqtIjvil.js +1 -0
  39. package/dist/web/assets/tab-store-0rGchMXr.js +1 -0
  40. package/dist/web/assets/terminal-tab-CeHEtoE2.js +1 -0
  41. package/dist/web/assets/treemap-KZPCXAKY-CBVPi4NV.js +1 -0
  42. package/dist/web/assets/{use-blob-url-BgxxT-n_.js → use-blob-url-Hn6n1730.js} +1 -1
  43. package/dist/web/assets/{use-monaco-theme-dtPsv6sh.js → use-monaco-theme-CP-vyTF8.js} +1 -1
  44. package/dist/web/assets/{vendor-mermaid-DCxaaPi4.js → vendor-mermaid-CMiurk2b.js} +2 -2
  45. package/dist/web/assets/{video-preview-DxTnfuSQ.js → video-preview-CHPVrMtx.js} +1 -1
  46. package/dist/web/assets/x-OGGXhtlb.js +1 -0
  47. package/dist/web/index.html +18 -18
  48. package/dist/web/sw.js +1 -1
  49. package/package.json +2 -1
  50. package/src/index.ts +0 -0
  51. package/src/server/ws/terminal.ts +4 -0
  52. package/src/services/terminal.service.ts +4 -1
  53. package/src/web/components/database/data-grid.tsx +133 -17
  54. package/src/web/components/database/glide-grid-theme.ts +82 -0
  55. package/src/web/components/database/glide-grid-types.ts +79 -0
  56. package/src/web/components/database/use-glide-cell-content.ts +124 -0
  57. package/src/web/components/database/use-glide-columns.ts +61 -0
  58. package/src/web/components/database/use-glide-selection.ts +48 -0
  59. package/src/web/components/editor/code-editor.tsx +126 -9
  60. package/src/web/components/layout/draggable-tab.tsx +1 -0
  61. package/src/web/components/terminal/terminal-tab.tsx +19 -8
  62. package/src/web/hooks/use-terminal.ts +22 -2
  63. package/src/web/index.html +1 -0
  64. package/src/web/stores/panel-utils.ts +1 -0
  65. package/test.sql +1 -0
  66. package/bun.lock +0 -2062
  67. package/bunfig.toml +0 -2
  68. package/dist/web/assets/ai-settings-section-DeW4WN43.js +0 -1
  69. package/dist/web/assets/architecture-PBZL5I3N-Dy3PgD6O.js +0 -1
  70. package/dist/web/assets/code-editor-B-F5VdzM.js +0 -8
  71. package/dist/web/assets/database-DCT0OjgQ.js +0 -1
  72. package/dist/web/assets/database-viewer-mLY7oMC_.js +0 -2
  73. package/dist/web/assets/gitGraph-HDMCJU4V-Bu1SIFFq.js +0 -1
  74. package/dist/web/assets/index-CEI0tfaL.css +0 -2
  75. package/dist/web/assets/index-CFz4k7zO.js +0 -27
  76. package/dist/web/assets/info-3K5VOQVL-DzfAxmVd.js +0 -1
  77. package/dist/web/assets/keybindings-store-CWX97luK.js +0 -1
  78. package/dist/web/assets/packet-RMMSAZCW-DpzHf4xp.js +0 -1
  79. package/dist/web/assets/pie-UPGHQEXC-BpzFCKJ8.js +0 -1
  80. package/dist/web/assets/plus-51UQ45rf.js +0 -1
  81. package/dist/web/assets/port-forwarding-tab-CjlX-0D2.js +0 -1
  82. package/dist/web/assets/radar-KQ55EAFF-DAxWKxM4.js +0 -1
  83. package/dist/web/assets/settings-tab-Djw-bqxG.js +0 -1
  84. package/dist/web/assets/sqlite-viewer-CjtNrQ7C.js +0 -1
  85. package/dist/web/assets/tab-store-Jvy1eZGM.js +0 -1
  86. package/dist/web/assets/terminal-tab-bKLoy06f.js +0 -1
  87. package/dist/web/assets/treemap-KZPCXAKY-D6dgXbAe.js +0 -1
  88. package/dist/web/assets/x-BtqbfkR7.js +0 -1
  89. /package/dist/web/assets/{api-client-r4nyVy7H.js → api-client-Dvzcc_EO.js} +0 -0
  90. /package/dist/web/assets/{chevron-right-BzAdxJRG.js → chevron-right-DnHIvvcy.js} +0 -0
  91. /package/dist/web/assets/{code-CuravVys.js → code-DGBecc50.js} +0 -0
  92. /package/dist/web/assets/{csv-parser-DxVplKKB.js → csv-parser-DO0dz4x_.js} +0 -0
  93. /package/dist/web/assets/{dist-BqoEabX7.js → dist-CGvx1c8C.js} +0 -0
  94. /package/dist/web/assets/{katex-bpagxk3Z.js → katex-BFE6i_OH.js} +0 -0
  95. /package/dist/web/assets/{lib-BqkcKGFq.js → lib-D_kRA9p6.js} +0 -0
  96. /package/dist/web/assets/{react-BkWDCPD7.js → react-GqWghJ-L.js} +0 -0
  97. /package/dist/web/assets/{sql-completion-provider-EzHOQLfo.js → sql-completion-provider-tCzZfqWs.js} +0 -0
  98. /package/dist/web/assets/{table-DbSviOmw.js → table-Dq575bPF.js} +0 -0
  99. /package/dist/web/assets/{text-wrap-DzvCTq_i.js → text-wrap-Cn6BNQfq.js} +0 -0
  100. /package/dist/web/assets/{trash-2-BgDIBl6f.js → trash-2-CJYoLw7Q.js} +0 -0
  101. /package/dist/web/assets/{utils-ChWX7pZv.js → utils-CTg5uAYR.js} +0 -0
  102. /package/dist/web/assets/{vendor-xterm-D7SePDJp.js → vendor-xterm-u3AZMvTx.js} +0 -0
@@ -1 +1 @@
1
- import{b as e}from"./vendor-markdown-0Mxgxy0L.js";import{t}from"./file-exclamation-point-Baz81y5z.js";import"./api-client-r4nyVy7H.js";import{W as n}from"./index-CFz4k7zO.js";import{t as r}from"./use-blob-url-BgxxT-n_.js";var i=e();function a({filePath:e,projectName:a}){let{blobUrl:o,error:s}=r(e,a);return s?(0,i.jsxs)(`div`,{className:`flex flex-col items-center justify-center h-full gap-3 text-text-secondary`,children:[(0,i.jsx)(t,{className:`size-10 text-text-subtle`}),(0,i.jsx)(`p`,{className:`text-sm`,children:`Failed to load video.`})]}):o?(0,i.jsx)(`div`,{className:`flex items-center justify-center h-full p-4 bg-surface overflow-auto`,children:(0,i.jsx)(`video`,{src:o,controls:!0,className:`max-w-full max-h-full`})}):(0,i.jsx)(`div`,{className:`flex items-center justify-center h-full`,children:(0,i.jsx)(n,{className:`size-5 animate-spin text-text-subtle`})})}export{a as VideoPreview};
1
+ import{b as e}from"./vendor-markdown-0Mxgxy0L.js";import{t}from"./file-exclamation-point-Baz81y5z.js";import"./api-client-Dvzcc_EO.js";import{G as n}from"./index-CoMWx5VS.js";import{t as r}from"./use-blob-url-Hn6n1730.js";var i=e();function a({filePath:e,projectName:a}){let{blobUrl:o,error:s}=r(e,a);return s?(0,i.jsxs)(`div`,{className:`flex flex-col items-center justify-center h-full gap-3 text-text-secondary`,children:[(0,i.jsx)(t,{className:`size-10 text-text-subtle`}),(0,i.jsx)(`p`,{className:`text-sm`,children:`Failed to load video.`})]}):o?(0,i.jsx)(`div`,{className:`flex items-center justify-center h-full p-4 bg-surface overflow-auto`,children:(0,i.jsx)(`video`,{src:o,controls:!0,className:`max-w-full max-h-full`})}):(0,i.jsx)(`div`,{className:`flex items-center justify-center h-full`,children:(0,i.jsx)(n,{className:`size-5 animate-spin text-text-subtle`})})}export{a as VideoPreview};
@@ -0,0 +1 @@
1
+ import{t as e}from"./createLucideIcon-BjHrJDVb.js";var t=e(`chevron-down`,[[`path`,{d:`m6 9 6 6 6-6`,key:`qrunsl`}]]),n=e(`chevron-up`,[[`path`,{d:`m18 15-6-6-6 6`,key:`153udz`}]]),r=e(`download`,[[`path`,{d:`M12 15V3`,key:`m9g1x1`}],[`path`,{d:`M21 15v4a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2v-4`,key:`ih7n3h`}],[`path`,{d:`m7 10 5 5 5-5`,key:`brsn70`}]]),i=e(`eye`,[[`path`,{d:`M2.062 12.348a1 1 0 0 1 0-.696 10.75 10.75 0 0 1 19.876 0 1 1 0 0 1 0 .696 10.75 10.75 0 0 1-19.876 0`,key:`1nclc0`}],[`circle`,{cx:`12`,cy:`12`,r:`3`,key:`1v7zrd`}]]),a=e(`plus`,[[`path`,{d:`M5 12h14`,key:`1ays0h`}],[`path`,{d:`M12 5v14`,key:`s699le`}]]),o=e(`x`,[[`path`,{d:`M18 6 6 18`,key:`1bl5f8`}],[`path`,{d:`m6 6 12 12`,key:`d8bk6v`}]]);export{n as a,r as i,a as n,t as o,i as r,o as t};
@@ -39,32 +39,32 @@
39
39
  <link rel="preconnect" href="https://fonts.googleapis.com" />
40
40
  <link rel="preconnect" href="https://fonts.gstatic.com" crossorigin />
41
41
  <link href="https://fonts.googleapis.com/css2?family=Geist+Mono:wght@400;500;600;700&family=Geist:wght@400;500;600;700&display=swap" rel="stylesheet" />
42
- <script type="module" crossorigin src="/assets/index-CFz4k7zO.js"></script>
42
+ <script type="module" crossorigin src="/assets/index-CoMWx5VS.js"></script>
43
43
  <link rel="modulepreload" crossorigin href="/assets/rolldown-runtime-FhOqtrmT.js">
44
- <link rel="modulepreload" crossorigin href="/assets/vendor-mermaid-DCxaaPi4.js">
44
+ <link rel="modulepreload" crossorigin href="/assets/vendor-mermaid-CMiurk2b.js">
45
45
  <link rel="modulepreload" crossorigin href="/assets/vendor-markdown-0Mxgxy0L.js">
46
46
  <link rel="modulepreload" crossorigin href="/assets/vendor-ui-B-89Uj8i.js">
47
- <link rel="modulepreload" crossorigin href="/assets/utils-ChWX7pZv.js">
47
+ <link rel="modulepreload" crossorigin href="/assets/utils-CTg5uAYR.js">
48
48
  <link rel="modulepreload" crossorigin href="/assets/createLucideIcon-BjHrJDVb.js">
49
- <link rel="modulepreload" crossorigin href="/assets/x-BtqbfkR7.js">
50
- <link rel="modulepreload" crossorigin href="/assets/input-bGJExpJZ.js">
51
- <link rel="modulepreload" crossorigin href="/assets/react-BkWDCPD7.js">
52
- <link rel="modulepreload" crossorigin href="/assets/api-client-r4nyVy7H.js">
53
- <link rel="modulepreload" crossorigin href="/assets/settings-store-CdcSAgEZ.js">
54
- <link rel="modulepreload" crossorigin href="/assets/scroll-area-D0EQpAH2.js">
49
+ <link rel="modulepreload" crossorigin href="/assets/x-OGGXhtlb.js">
50
+ <link rel="modulepreload" crossorigin href="/assets/input-DYWhyaze.js">
51
+ <link rel="modulepreload" crossorigin href="/assets/react-GqWghJ-L.js">
52
+ <link rel="modulepreload" crossorigin href="/assets/api-client-Dvzcc_EO.js">
53
+ <link rel="modulepreload" crossorigin href="/assets/settings-store-BHBb62gq.js">
54
+ <link rel="modulepreload" crossorigin href="/assets/scroll-area-BEllam7_.js">
55
55
  <link rel="modulepreload" crossorigin href="/assets/dist-D7KGU7Vl.js">
56
- <link rel="modulepreload" crossorigin href="/assets/plus-51UQ45rf.js">
57
56
  <link rel="modulepreload" crossorigin href="/assets/refresh-cw-CSFrDtiu.js">
58
- <link rel="modulepreload" crossorigin href="/assets/trash-2-BgDIBl6f.js">
59
- <link rel="modulepreload" crossorigin href="/assets/api-settings-t7Leca7J.js">
60
- <link rel="modulepreload" crossorigin href="/assets/ai-settings-section-DeW4WN43.js">
61
- <link rel="modulepreload" crossorigin href="/assets/chevron-right-BzAdxJRG.js">
62
- <link rel="modulepreload" crossorigin href="/assets/database-DCT0OjgQ.js">
63
- <link rel="modulepreload" crossorigin href="/assets/file-store-BgZggznw.js">
64
- <link rel="modulepreload" crossorigin href="/assets/tab-store-Jvy1eZGM.js">
65
- <link rel="stylesheet" crossorigin href="/assets/index-CEI0tfaL.css">
57
+ <link rel="modulepreload" crossorigin href="/assets/trash-2-CJYoLw7Q.js">
58
+ <link rel="modulepreload" crossorigin href="/assets/api-settings-D0_eiIYv.js">
59
+ <link rel="modulepreload" crossorigin href="/assets/ai-settings-section-CLNBWLS4.js">
60
+ <link rel="modulepreload" crossorigin href="/assets/database-DOWH9-Vv.js">
61
+ <link rel="modulepreload" crossorigin href="/assets/chevron-right-DnHIvvcy.js">
62
+ <link rel="modulepreload" crossorigin href="/assets/file-store-BrbCNyLm.js">
63
+ <link rel="modulepreload" crossorigin href="/assets/tab-store-0rGchMXr.js">
64
+ <link rel="stylesheet" crossorigin href="/assets/index-Dzb3OtrX.css">
66
65
  <link rel="manifest" href="/manifest.webmanifest"><script id="vite-plugin-pwa:register-sw" src="/registerSW.js"></script></head>
67
66
  <body class="bg-[#0f1419] text-[#e5e7eb] font-sans antialiased">
67
+ <div id="portal" style="position: fixed; left: 0; top: 0; z-index: 9999;" /></div>
68
68
  <div id="root"></div>
69
69
  </body>
70
70
  </html>
package/dist/web/sw.js CHANGED
@@ -1 +1 @@
1
- try{self[`workbox:core:7.3.0`]&&_()}catch{}var e=(e,...t)=>{let n=e;return t.length>0&&(n+=` :: ${JSON.stringify(t)}`),n},t=class extends Error{constructor(t,n){let r=e(t,n);super(r),this.name=t,this.details=n}},n={googleAnalytics:`googleAnalytics`,precache:`precache-v2`,prefix:`workbox`,runtime:`runtime`,suffix:typeof registration<`u`?registration.scope:``},r=e=>[n.prefix,e,n.suffix].filter(e=>e&&e.length>0).join(`-`),i=e=>{for(let t of Object.keys(n))e(t)},a={updateDetails:e=>{i(t=>{typeof e[t]==`string`&&(n[t]=e[t])})},getGoogleAnalyticsName:e=>e||r(n.googleAnalytics),getPrecacheName:e=>e||r(n.precache),getPrefix:()=>n.prefix,getRuntimeName:e=>e||r(n.runtime),getSuffix:()=>n.suffix};function o(e,t){let n=t();return e.waitUntil(n),n}try{self[`workbox:precaching:7.3.0`]&&_()}catch{}var s=`__WB_REVISION__`;function c(e){if(!e)throw new t(`add-to-cache-list-unexpected-type`,{entry:e});if(typeof e==`string`){let t=new URL(e,location.href);return{cacheKey:t.href,url:t.href}}let{revision:n,url:r}=e;if(!r)throw new t(`add-to-cache-list-unexpected-type`,{entry:e});if(!n){let e=new URL(r,location.href);return{cacheKey:e.href,url:e.href}}let i=new URL(r,location.href),a=new URL(r,location.href);return i.searchParams.set(s,n),{cacheKey:i.href,url:a.href}}var l=class{constructor(){this.updatedURLs=[],this.notUpdatedURLs=[],this.handlerWillStart=async({request:e,state:t})=>{t&&(t.originalRequest=e)},this.cachedResponseWillBeUsed=async({event:e,state:t,cachedResponse:n})=>{if(e.type===`install`&&t&&t.originalRequest&&t.originalRequest instanceof Request){let e=t.originalRequest.url;n?this.notUpdatedURLs.push(e):this.updatedURLs.push(e)}return n}}},u=class{constructor({precacheController:e}){this.cacheKeyWillBeUsed=async({request:e,params:t})=>{let n=t?.cacheKey||this._precacheController.getCacheKeyForURL(e.url);return n?new Request(n,{headers:e.headers}):e},this._precacheController=e}},d;function f(){if(d===void 0){let e=new Response(``);if(`body`in e)try{new Response(e.body),d=!0}catch{d=!1}d=!1}return d}async function p(e,n){let r=null;if(e.url&&(r=new URL(e.url).origin),r!==self.location.origin)throw new t(`cross-origin-copy-response`,{origin:r});let i=e.clone(),a={headers:new Headers(i.headers),status:i.status,statusText:i.statusText},o=n?n(a):a,s=f()?i.body:await i.blob();return new Response(s,o)}var m=e=>new URL(String(e),location.href).href.replace(RegExp(`^${location.origin}`),``);function h(e,t){let n=new URL(e);for(let e of t)n.searchParams.delete(e);return n.href}async function g(e,t,n,r){let i=h(t.url,n);if(t.url===i)return e.match(t,r);let a=Object.assign(Object.assign({},r),{ignoreSearch:!0}),o=await e.keys(t,a);for(let t of o)if(i===h(t.url,n))return e.match(t,r)}var v=class{constructor(){this.promise=new Promise((e,t)=>{this.resolve=e,this.reject=t})}},y=new Set;async function b(){for(let e of y)await e()}function x(e){return new Promise(t=>setTimeout(t,e))}try{self[`workbox:strategies:7.3.0`]&&_()}catch{}function S(e){return typeof e==`string`?new Request(e):e}var C=class{constructor(e,t){this._cacheKeys={},Object.assign(this,t),this.event=t.event,this._strategy=e,this._handlerDeferred=new v,this._extendLifetimePromises=[],this._plugins=[...e.plugins],this._pluginStateMap=new Map;for(let e of this._plugins)this._pluginStateMap.set(e,{});this.event.waitUntil(this._handlerDeferred.promise)}async fetch(e){let{event:n}=this,r=S(e);if(r.mode===`navigate`&&n instanceof FetchEvent&&n.preloadResponse){let e=await n.preloadResponse;if(e)return e}let i=this.hasCallback(`fetchDidFail`)?r.clone():null;try{for(let e of this.iterateCallbacks(`requestWillFetch`))r=await e({request:r.clone(),event:n})}catch(e){if(e instanceof Error)throw new t(`plugin-error-request-will-fetch`,{thrownErrorMessage:e.message})}let a=r.clone();try{let e;e=await fetch(r,r.mode===`navigate`?void 0:this._strategy.fetchOptions);for(let t of this.iterateCallbacks(`fetchDidSucceed`))e=await t({event:n,request:a,response:e});return e}catch(e){throw i&&await this.runCallbacks(`fetchDidFail`,{error:e,event:n,originalRequest:i.clone(),request:a.clone()}),e}}async fetchAndCachePut(e){let t=await this.fetch(e),n=t.clone();return this.waitUntil(this.cachePut(e,n)),t}async cacheMatch(e){let t=S(e),n,{cacheName:r,matchOptions:i}=this._strategy,a=await this.getCacheKey(t,`read`),o=Object.assign(Object.assign({},i),{cacheName:r});n=await caches.match(a,o);for(let e of this.iterateCallbacks(`cachedResponseWillBeUsed`))n=await e({cacheName:r,matchOptions:i,cachedResponse:n,request:a,event:this.event})||void 0;return n}async cachePut(e,n){let r=S(e);await x(0);let i=await this.getCacheKey(r,`write`);if(!n)throw new t(`cache-put-with-no-response`,{url:m(i.url)});let a=await this._ensureResponseSafeToCache(n);if(!a)return!1;let{cacheName:o,matchOptions:s}=this._strategy,c=await self.caches.open(o),l=this.hasCallback(`cacheDidUpdate`),u=l?await g(c,i.clone(),[`__WB_REVISION__`],s):null;try{await c.put(i,l?a.clone():a)}catch(e){if(e instanceof Error)throw e.name===`QuotaExceededError`&&await b(),e}for(let e of this.iterateCallbacks(`cacheDidUpdate`))await e({cacheName:o,oldResponse:u,newResponse:a.clone(),request:i,event:this.event});return!0}async getCacheKey(e,t){let n=`${e.url} | ${t}`;if(!this._cacheKeys[n]){let r=e;for(let e of this.iterateCallbacks(`cacheKeyWillBeUsed`))r=S(await e({mode:t,request:r,event:this.event,params:this.params}));this._cacheKeys[n]=r}return this._cacheKeys[n]}hasCallback(e){for(let t of this._strategy.plugins)if(e in t)return!0;return!1}async runCallbacks(e,t){for(let n of this.iterateCallbacks(e))await n(t)}*iterateCallbacks(e){for(let t of this._strategy.plugins)if(typeof t[e]==`function`){let n=this._pluginStateMap.get(t);yield r=>{let i=Object.assign(Object.assign({},r),{state:n});return t[e](i)}}}waitUntil(e){return this._extendLifetimePromises.push(e),e}async doneWaiting(){for(;this._extendLifetimePromises.length;){let e=this._extendLifetimePromises.splice(0),t=(await Promise.allSettled(e)).find(e=>e.status===`rejected`);if(t)throw t.reason}}destroy(){this._handlerDeferred.resolve(null)}async _ensureResponseSafeToCache(e){let t=e,n=!1;for(let e of this.iterateCallbacks(`cacheWillUpdate`))if(t=await e({request:this.request,response:t,event:this.event})||void 0,n=!0,!t)break;return n||t&&t.status!==200&&(t=void 0),t}},w=class{constructor(e={}){this.cacheName=a.getRuntimeName(e.cacheName),this.plugins=e.plugins||[],this.fetchOptions=e.fetchOptions,this.matchOptions=e.matchOptions}handle(e){let[t]=this.handleAll(e);return t}handleAll(e){e instanceof FetchEvent&&(e={event:e,request:e.request});let t=e.event,n=typeof e.request==`string`?new Request(e.request):e.request,r=`params`in e?e.params:void 0,i=new C(this,{event:t,request:n,params:r}),a=this._getResponse(i,n,t);return[a,this._awaitComplete(a,i,n,t)]}async _getResponse(e,n,r){await e.runCallbacks(`handlerWillStart`,{event:r,request:n});let i;try{if(i=await this._handle(n,e),!i||i.type===`error`)throw new t(`no-response`,{url:n.url})}catch(t){if(t instanceof Error){for(let a of e.iterateCallbacks(`handlerDidError`))if(i=await a({error:t,event:r,request:n}),i)break}if(!i)throw t}for(let t of e.iterateCallbacks(`handlerWillRespond`))i=await t({event:r,request:n,response:i});return i}async _awaitComplete(e,t,n,r){let i,a;try{i=await e}catch{}try{await t.runCallbacks(`handlerDidRespond`,{event:r,request:n,response:i}),await t.doneWaiting()}catch(e){e instanceof Error&&(a=e)}if(await t.runCallbacks(`handlerDidComplete`,{event:r,request:n,response:i,error:a}),t.destroy(),a)throw a}},T=class e extends w{constructor(t={}){t.cacheName=a.getPrecacheName(t.cacheName),super(t),this._fallbackToNetwork=t.fallbackToNetwork!==!1,this.plugins.push(e.copyRedirectedCacheableResponsesPlugin)}async _handle(e,t){return await t.cacheMatch(e)||(t.event&&t.event.type===`install`?await this._handleInstall(e,t):await this._handleFetch(e,t))}async _handleFetch(e,n){let r,i=n.params||{};if(this._fallbackToNetwork){let t=i.integrity,a=e.integrity,o=!a||a===t;r=await n.fetch(new Request(e,{integrity:e.mode===`no-cors`?void 0:a||t})),t&&o&&e.mode!==`no-cors`&&(this._useDefaultCacheabilityPluginIfNeeded(),await n.cachePut(e,r.clone()))}else throw new t(`missing-precache-entry`,{cacheName:this.cacheName,url:e.url});return r}async _handleInstall(e,n){this._useDefaultCacheabilityPluginIfNeeded();let r=await n.fetch(e);if(!await n.cachePut(e,r.clone()))throw new t(`bad-precaching-response`,{url:e.url,status:r.status});return r}_useDefaultCacheabilityPluginIfNeeded(){let t=null,n=0;for(let[r,i]of this.plugins.entries())i!==e.copyRedirectedCacheableResponsesPlugin&&(i===e.defaultPrecacheCacheabilityPlugin&&(t=r),i.cacheWillUpdate&&n++);n===0?this.plugins.push(e.defaultPrecacheCacheabilityPlugin):n>1&&t!==null&&this.plugins.splice(t,1)}};T.defaultPrecacheCacheabilityPlugin={async cacheWillUpdate({response:e}){return!e||e.status>=400?null:e}},T.copyRedirectedCacheableResponsesPlugin={async cacheWillUpdate({response:e}){return e.redirected?await p(e):e}};var E=class{constructor({cacheName:e,plugins:t=[],fallbackToNetwork:n=!0}={}){this._urlsToCacheKeys=new Map,this._urlsToCacheModes=new Map,this._cacheKeysToIntegrities=new Map,this._strategy=new T({cacheName:a.getPrecacheName(e),plugins:[...t,new u({precacheController:this})],fallbackToNetwork:n}),this.install=this.install.bind(this),this.activate=this.activate.bind(this)}get strategy(){return this._strategy}precache(e){this.addToCacheList(e),this._installAndActiveListenersAdded||=(self.addEventListener(`install`,this.install),self.addEventListener(`activate`,this.activate),!0)}addToCacheList(e){let n=[];for(let r of e){typeof r==`string`?n.push(r):r&&r.revision===void 0&&n.push(r.url);let{cacheKey:e,url:i}=c(r),a=typeof r!=`string`&&r.revision?`reload`:`default`;if(this._urlsToCacheKeys.has(i)&&this._urlsToCacheKeys.get(i)!==e)throw new t(`add-to-cache-list-conflicting-entries`,{firstEntry:this._urlsToCacheKeys.get(i),secondEntry:e});if(typeof r!=`string`&&r.integrity){if(this._cacheKeysToIntegrities.has(e)&&this._cacheKeysToIntegrities.get(e)!==r.integrity)throw new t(`add-to-cache-list-conflicting-integrities`,{url:i});this._cacheKeysToIntegrities.set(e,r.integrity)}if(this._urlsToCacheKeys.set(i,e),this._urlsToCacheModes.set(i,a),n.length>0){let e=`Workbox is precaching URLs without revision info: ${n.join(`, `)}\nThis is generally NOT safe. Learn more at https://bit.ly/wb-precache`;console.warn(e)}}}install(e){return o(e,async()=>{let t=new l;this.strategy.plugins.push(t);for(let[t,n]of this._urlsToCacheKeys){let r=this._cacheKeysToIntegrities.get(n),i=this._urlsToCacheModes.get(t),a=new Request(t,{integrity:r,cache:i,credentials:`same-origin`});await Promise.all(this.strategy.handleAll({params:{cacheKey:n},request:a,event:e}))}let{updatedURLs:n,notUpdatedURLs:r}=t;return{updatedURLs:n,notUpdatedURLs:r}})}activate(e){return o(e,async()=>{let e=await self.caches.open(this.strategy.cacheName),t=await e.keys(),n=new Set(this._urlsToCacheKeys.values()),r=[];for(let i of t)n.has(i.url)||(await e.delete(i),r.push(i.url));return{deletedURLs:r}})}getURLsToCacheKeys(){return this._urlsToCacheKeys}getCachedURLs(){return[...this._urlsToCacheKeys.keys()]}getCacheKeyForURL(e){let t=new URL(e,location.href);return this._urlsToCacheKeys.get(t.href)}getIntegrityForCacheKey(e){return this._cacheKeysToIntegrities.get(e)}async matchPrecache(e){let t=e instanceof Request?e.url:e,n=this.getCacheKeyForURL(t);if(n)return(await self.caches.open(this.strategy.cacheName)).match(n)}createHandlerBoundToURL(e){let n=this.getCacheKeyForURL(e);if(!n)throw new t(`non-precached-url`,{url:e});return t=>(t.request=new Request(e),t.params=Object.assign({cacheKey:n},t.params),this.strategy.handle(t))}},D,O=()=>(D||=new E,D);try{self[`workbox:routing:7.3.0`]&&_()}catch{}var k=e=>e&&typeof e==`object`?e:{handle:e},A=class{constructor(e,t,n=`GET`){this.handler=k(t),this.match=e,this.method=n}setCatchHandler(e){this.catchHandler=k(e)}},j=class extends A{constructor(e,t,n){super(({url:t})=>{let n=e.exec(t.href);if(n&&!(t.origin!==location.origin&&n.index!==0))return n.slice(1)},t,n)}},M=class{constructor(){this._routes=new Map,this._defaultHandlerMap=new Map}get routes(){return this._routes}addFetchListener(){self.addEventListener(`fetch`,(e=>{let{request:t}=e,n=this.handleRequest({request:t,event:e});n&&e.respondWith(n)}))}addCacheListener(){self.addEventListener(`message`,(e=>{if(e.data&&e.data.type===`CACHE_URLS`){let{payload:t}=e.data,n=Promise.all(t.urlsToCache.map(t=>{typeof t==`string`&&(t=[t]);let n=new Request(...t);return this.handleRequest({request:n,event:e})}));e.waitUntil(n),e.ports&&e.ports[0]&&n.then(()=>e.ports[0].postMessage(!0))}}))}handleRequest({request:e,event:t}){let n=new URL(e.url,location.href);if(!n.protocol.startsWith(`http`))return;let r=n.origin===location.origin,{params:i,route:a}=this.findMatchingRoute({event:t,request:e,sameOrigin:r,url:n}),o=a&&a.handler,s=e.method;if(!o&&this._defaultHandlerMap.has(s)&&(o=this._defaultHandlerMap.get(s)),!o)return;let c;try{c=o.handle({url:n,request:e,event:t,params:i})}catch(e){c=Promise.reject(e)}let l=a&&a.catchHandler;return c instanceof Promise&&(this._catchHandler||l)&&(c=c.catch(async r=>{if(l)try{return await l.handle({url:n,request:e,event:t,params:i})}catch(e){e instanceof Error&&(r=e)}if(this._catchHandler)return this._catchHandler.handle({url:n,request:e,event:t});throw r})),c}findMatchingRoute({url:e,sameOrigin:t,request:n,event:r}){let i=this._routes.get(n.method)||[];for(let a of i){let i,o=a.match({url:e,sameOrigin:t,request:n,event:r});if(o)return i=o,(Array.isArray(i)&&i.length===0||o.constructor===Object&&Object.keys(o).length===0||typeof o==`boolean`)&&(i=void 0),{route:a,params:i}}return{}}setDefaultHandler(e,t=`GET`){this._defaultHandlerMap.set(t,k(e))}setCatchHandler(e){this._catchHandler=k(e)}registerRoute(e){this._routes.has(e.method)||this._routes.set(e.method,[]),this._routes.get(e.method).push(e)}unregisterRoute(e){if(!this._routes.has(e.method))throw new t(`unregister-route-but-not-found-with-method`,{method:e.method});let n=this._routes.get(e.method).indexOf(e);if(n>-1)this._routes.get(e.method).splice(n,1);else throw new t(`unregister-route-route-not-registered`)}},N,P=()=>(N||(N=new M,N.addFetchListener(),N.addCacheListener()),N);function F(e,n,r){let i;if(typeof e==`string`){let t=new URL(e,location.href);i=new A(({url:e})=>e.href===t.href,n,r)}else if(e instanceof RegExp)i=new j(e,n,r);else if(typeof e==`function`)i=new A(e,n,r);else if(e instanceof A)i=e;else throw new t(`unsupported-route-type`,{moduleName:`workbox-routing`,funcName:`registerRoute`,paramName:`capture`});return P().registerRoute(i),i}function I(e,t=[]){for(let n of[...e.searchParams.keys()])t.some(e=>e.test(n))&&e.searchParams.delete(n);return e}function*L(e,{ignoreURLParametersMatching:t=[/^utm_/,/^fbclid$/],directoryIndex:n=`index.html`,cleanURLs:r=!0,urlManipulation:i}={}){let a=new URL(e,location.href);a.hash=``,yield a.href;let o=I(a,t);if(yield o.href,n&&o.pathname.endsWith(`/`)){let e=new URL(o.href);e.pathname+=n,yield e.href}if(r){let e=new URL(o.href);e.pathname+=`.html`,yield e.href}if(i){let e=i({url:a});for(let t of e)yield t.href}}var R=class extends A{constructor(e,t){super(({request:n})=>{let r=e.getURLsToCacheKeys();for(let i of L(n.url,t)){let t=r.get(i);if(t)return{cacheKey:t,integrity:e.getIntegrityForCacheKey(t)}}},e.strategy)}};function z(e){F(new R(O(),e))}function B(e){O().precache(e)}function V(e,t){B(e),z(t)}V([{"revision":"1872c500de691dce40960bb85481de07","url":"registerSW.js"},{"revision":"a0fb34fc84eb148d51812cd62669f20d","url":"icon-192.svg"},{"revision":"799a9d7b8dd64119616c0b2d70cd7a95","url":"index.html"},{"revision":"a0fb34fc84eb148d51812cd62669f20d","url":"icon-512.svg"},{"revision":null,"url":"assets/lib-BqkcKGFq.js"},{"revision":null,"url":"assets/dist-D7KGU7Vl.js"},{"revision":null,"url":"assets/KaTeX_Fraktur-Bold-CL6g_b3V.woff2"},{"revision":null,"url":"assets/KaTeX_AMS-Regular-BQhdFMY1.woff2"},{"revision":null,"url":"assets/tab-store-Jvy1eZGM.js"},{"revision":null,"url":"assets/architecture-PBZL5I3N-Dy3PgD6O.js"},{"revision":null,"url":"assets/pdf-preview-BoQTv6B2.js"},{"revision":null,"url":"assets/sql-query-editor-vpD0I0KG.js"},{"revision":null,"url":"assets/conflict-editor-C-lUw4gv.js"},{"revision":null,"url":"assets/packet-RMMSAZCW-DpzHf4xp.js"},{"revision":null,"url":"assets/code-editor-B-F5VdzM.js"},{"revision":null,"url":"assets/KaTeX_Main-Regular-B22Nviop.woff2"},{"revision":null,"url":"assets/scroll-area-D0EQpAH2.js"},{"revision":null,"url":"assets/vendor-xterm-D7SePDJp.js"},{"revision":null,"url":"assets/settings-tab-Djw-bqxG.js"},{"revision":null,"url":"assets/file-exclamation-point-Baz81y5z.js"},{"revision":null,"url":"assets/github.min-D2BCvnWf.css"},{"revision":null,"url":"assets/sqlite-viewer-CjtNrQ7C.js"},{"revision":null,"url":"assets/csv-preview-C9qGhDlb.js"},{"revision":null,"url":"assets/KaTeX_Fraktur-Regular-CTYiF6lA.woff2"},{"revision":null,"url":"assets/chevron-right-BzAdxJRG.js"},{"revision":null,"url":"assets/file-store-BgZggznw.js"},{"revision":null,"url":"assets/x-BtqbfkR7.js"},{"revision":null,"url":"assets/KaTeX_Main-BoldItalic-DxDJ3AOS.woff2"},{"revision":null,"url":"assets/ai-settings-section-DeW4WN43.js"},{"revision":null,"url":"assets/pie-UPGHQEXC-BpzFCKJ8.js"},{"revision":null,"url":"assets/vendor-mermaid-DCxaaPi4.js"},{"revision":null,"url":"assets/vendor-markdown-0Mxgxy0L.js"},{"revision":null,"url":"assets/database-viewer-mLY7oMC_.js"},{"revision":null,"url":"assets/KaTeX_Main-Italic-NWA7e6Wa.woff2"},{"revision":null,"url":"assets/trash-2-BgDIBl6f.js"},{"revision":null,"url":"assets/use-blob-url-BgxxT-n_.js"},{"revision":null,"url":"assets/KaTeX_Typewriter-Regular-CO6r4hn1.woff2"},{"revision":null,"url":"assets/dist-BqoEabX7.js"},{"revision":null,"url":"assets/port-forwarding-tab-CjlX-0D2.js"},{"revision":null,"url":"assets/input-bGJExpJZ.js"},{"revision":null,"url":"assets/diff-viewer-I8qs3Nb-.js"},{"revision":null,"url":"assets/plus-51UQ45rf.js"},{"revision":null,"url":"assets/api-settings-t7Leca7J.js"},{"revision":null,"url":"assets/KaTeX_Caligraphic-Bold-Dq_IR9rO.woff2"},{"revision":null,"url":"assets/KaTeX_Caligraphic-Regular-Di6jR-x-.woff2"},{"revision":null,"url":"assets/arrow-up-Dtrfv490.js"},{"revision":null,"url":"assets/refresh-cw-CSFrDtiu.js"},{"revision":null,"url":"assets/rolldown-runtime-FhOqtrmT.js"},{"revision":null,"url":"assets/radar-KQ55EAFF-DAxWKxM4.js"},{"revision":null,"url":"assets/markdown-renderer-ySnJPmc1.js"},{"revision":null,"url":"assets/KaTeX_Math-Italic-t53AETM-.woff2"},{"revision":null,"url":"assets/github-dark-dimmed.min-BrpRStFV.css"},{"revision":null,"url":"assets/KaTeX_SansSerif-Bold-D1sUS0GD.woff2"},{"revision":null,"url":"assets/KaTeX_Script-Regular-D3wIWfF6.woff2"},{"revision":null,"url":"assets/sql-completion-provider-EzHOQLfo.js"},{"revision":null,"url":"assets/esm-B3je8j5P.js"},{"revision":null,"url":"assets/image-preview-C-w-CK5s.js"},{"revision":null,"url":"assets/treemap-KZPCXAKY-D6dgXbAe.js"},{"revision":null,"url":"assets/extension-webview-Dt9bKs0C.js"},{"revision":null,"url":"assets/KaTeX_Main-Bold-Cx986IdX.woff2"},{"revision":null,"url":"assets/chat-tab-8Bvn7PHt.js"},{"revision":null,"url":"assets/react-BkWDCPD7.js"},{"revision":null,"url":"assets/database-DCT0OjgQ.js"},{"revision":null,"url":"assets/KaTeX_Size2-Regular-Dy4dx90m.woff2"},{"revision":null,"url":"assets/gitGraph-HDMCJU4V-Bu1SIFFq.js"},{"revision":null,"url":"assets/KaTeX_SansSerif-Regular-DDBCnlJ7.woff2"},{"revision":null,"url":"assets/KaTeX_Size1-Regular-mCD8mA8B.woff2"},{"revision":null,"url":"assets/api-client-r4nyVy7H.js"},{"revision":null,"url":"assets/createLucideIcon-BjHrJDVb.js"},{"revision":null,"url":"assets/keybindings-store-CWX97luK.js"},{"revision":null,"url":"assets/info-3K5VOQVL-DzfAxmVd.js"},{"revision":null,"url":"assets/settings-store-CdcSAgEZ.js"},{"revision":null,"url":"assets/KaTeX_Size4-Regular-Dl5lxZxV.woff2"},{"revision":null,"url":"assets/terminal-tab-bKLoy06f.js"},{"revision":null,"url":"assets/code-CuravVys.js"},{"revision":null,"url":"assets/index-CEI0tfaL.css"},{"revision":null,"url":"assets/katex-bpagxk3Z.js"},{"revision":null,"url":"assets/index-CFz4k7zO.js"},{"revision":null,"url":"assets/KaTeX_Math-BoldItalic-CZnvNsCZ.woff2"},{"revision":null,"url":"assets/video-preview-DxTnfuSQ.js"},{"revision":null,"url":"assets/vendor-ui-B-89Uj8i.js"},{"revision":null,"url":"assets/utils-ChWX7pZv.js"},{"revision":null,"url":"assets/audio-preview-BR7DoH0l.js"},{"revision":null,"url":"assets/text-wrap-DzvCTq_i.js"},{"revision":null,"url":"assets/csv-parser-DxVplKKB.js"},{"revision":null,"url":"assets/postgres-viewer-CBntLqXY.js"},{"revision":null,"url":"assets/vendor-xterm-BrP-ENHg.css"},{"revision":null,"url":"assets/use-monaco-theme-dtPsv6sh.js"},{"revision":null,"url":"assets/KaTeX_SansSerif-Italic-C3H0VqGB.woff2"},{"revision":null,"url":"assets/table-DbSviOmw.js"},{"revision":"d0f94ce046cf8cf09605ee7664dac557","url":"monacoeditorwork/html.worker.bundle.js"},{"revision":"a424156a79b9c1b907db93aa3180585a","url":"monacoeditorwork/editor.worker.bundle.js"},{"revision":"b3a7f967560c9816492a1567b3f7f0dc","url":"monacoeditorwork/css.worker.bundle.js"},{"revision":"a5d8a1acfc29c2a4c882a54ffc93def3","url":"monacoeditorwork/json.worker.bundle.js"},{"revision":"948e060affb598c339be40d69e1f6f9c","url":"monacoeditorwork/ts.worker.bundle.js"},{"revision":"79c8870653c8f419f2e3323085e1f4be","url":"manifest.webmanifest"}]),self.addEventListener(`push`,e=>{e.waitUntil(self.clients.matchAll({type:`window`,includeUncontrolled:!0}).then(t=>{if(t.some(e=>e.visibilityState===`visible`))return;let n=e.data?.json()??{title:`PPM`,body:`Chat completed`};return self.registration.showNotification(n.title,{body:n.body,icon:`/icon-192.png`,badge:`/icon-192.png`,tag:`ppm-chat-done`,silent:!1,data:{url:self.location.origin}})}))}),self.addEventListener(`notificationclick`,e=>{e.notification.close(),e.waitUntil(self.clients.matchAll({type:`window`,includeUncontrolled:!0}).then(t=>{for(let e of t)if(e.url.includes(self.location.origin)&&`focus`in e)return e.focus();return self.clients.openWindow(e.notification.data?.url||`/`)}))});
1
+ try{self[`workbox:core:7.3.0`]&&_()}catch{}var e=(e,...t)=>{let n=e;return t.length>0&&(n+=` :: ${JSON.stringify(t)}`),n},t=class extends Error{constructor(t,n){let r=e(t,n);super(r),this.name=t,this.details=n}},n={googleAnalytics:`googleAnalytics`,precache:`precache-v2`,prefix:`workbox`,runtime:`runtime`,suffix:typeof registration<`u`?registration.scope:``},r=e=>[n.prefix,e,n.suffix].filter(e=>e&&e.length>0).join(`-`),i=e=>{for(let t of Object.keys(n))e(t)},a={updateDetails:e=>{i(t=>{typeof e[t]==`string`&&(n[t]=e[t])})},getGoogleAnalyticsName:e=>e||r(n.googleAnalytics),getPrecacheName:e=>e||r(n.precache),getPrefix:()=>n.prefix,getRuntimeName:e=>e||r(n.runtime),getSuffix:()=>n.suffix};function o(e,t){let n=t();return e.waitUntil(n),n}try{self[`workbox:precaching:7.3.0`]&&_()}catch{}var s=`__WB_REVISION__`;function c(e){if(!e)throw new t(`add-to-cache-list-unexpected-type`,{entry:e});if(typeof e==`string`){let t=new URL(e,location.href);return{cacheKey:t.href,url:t.href}}let{revision:n,url:r}=e;if(!r)throw new t(`add-to-cache-list-unexpected-type`,{entry:e});if(!n){let e=new URL(r,location.href);return{cacheKey:e.href,url:e.href}}let i=new URL(r,location.href),a=new URL(r,location.href);return i.searchParams.set(s,n),{cacheKey:i.href,url:a.href}}var l=class{constructor(){this.updatedURLs=[],this.notUpdatedURLs=[],this.handlerWillStart=async({request:e,state:t})=>{t&&(t.originalRequest=e)},this.cachedResponseWillBeUsed=async({event:e,state:t,cachedResponse:n})=>{if(e.type===`install`&&t&&t.originalRequest&&t.originalRequest instanceof Request){let e=t.originalRequest.url;n?this.notUpdatedURLs.push(e):this.updatedURLs.push(e)}return n}}},u=class{constructor({precacheController:e}){this.cacheKeyWillBeUsed=async({request:e,params:t})=>{let n=t?.cacheKey||this._precacheController.getCacheKeyForURL(e.url);return n?new Request(n,{headers:e.headers}):e},this._precacheController=e}},d;function f(){if(d===void 0){let e=new Response(``);if(`body`in e)try{new Response(e.body),d=!0}catch{d=!1}d=!1}return d}async function p(e,n){let r=null;if(e.url&&(r=new URL(e.url).origin),r!==self.location.origin)throw new t(`cross-origin-copy-response`,{origin:r});let i=e.clone(),a={headers:new Headers(i.headers),status:i.status,statusText:i.statusText},o=n?n(a):a,s=f()?i.body:await i.blob();return new Response(s,o)}var m=e=>new URL(String(e),location.href).href.replace(RegExp(`^${location.origin}`),``);function h(e,t){let n=new URL(e);for(let e of t)n.searchParams.delete(e);return n.href}async function g(e,t,n,r){let i=h(t.url,n);if(t.url===i)return e.match(t,r);let a=Object.assign(Object.assign({},r),{ignoreSearch:!0}),o=await e.keys(t,a);for(let t of o)if(i===h(t.url,n))return e.match(t,r)}var v=class{constructor(){this.promise=new Promise((e,t)=>{this.resolve=e,this.reject=t})}},y=new Set;async function b(){for(let e of y)await e()}function x(e){return new Promise(t=>setTimeout(t,e))}try{self[`workbox:strategies:7.3.0`]&&_()}catch{}function S(e){return typeof e==`string`?new Request(e):e}var C=class{constructor(e,t){this._cacheKeys={},Object.assign(this,t),this.event=t.event,this._strategy=e,this._handlerDeferred=new v,this._extendLifetimePromises=[],this._plugins=[...e.plugins],this._pluginStateMap=new Map;for(let e of this._plugins)this._pluginStateMap.set(e,{});this.event.waitUntil(this._handlerDeferred.promise)}async fetch(e){let{event:n}=this,r=S(e);if(r.mode===`navigate`&&n instanceof FetchEvent&&n.preloadResponse){let e=await n.preloadResponse;if(e)return e}let i=this.hasCallback(`fetchDidFail`)?r.clone():null;try{for(let e of this.iterateCallbacks(`requestWillFetch`))r=await e({request:r.clone(),event:n})}catch(e){if(e instanceof Error)throw new t(`plugin-error-request-will-fetch`,{thrownErrorMessage:e.message})}let a=r.clone();try{let e;e=await fetch(r,r.mode===`navigate`?void 0:this._strategy.fetchOptions);for(let t of this.iterateCallbacks(`fetchDidSucceed`))e=await t({event:n,request:a,response:e});return e}catch(e){throw i&&await this.runCallbacks(`fetchDidFail`,{error:e,event:n,originalRequest:i.clone(),request:a.clone()}),e}}async fetchAndCachePut(e){let t=await this.fetch(e),n=t.clone();return this.waitUntil(this.cachePut(e,n)),t}async cacheMatch(e){let t=S(e),n,{cacheName:r,matchOptions:i}=this._strategy,a=await this.getCacheKey(t,`read`),o=Object.assign(Object.assign({},i),{cacheName:r});n=await caches.match(a,o);for(let e of this.iterateCallbacks(`cachedResponseWillBeUsed`))n=await e({cacheName:r,matchOptions:i,cachedResponse:n,request:a,event:this.event})||void 0;return n}async cachePut(e,n){let r=S(e);await x(0);let i=await this.getCacheKey(r,`write`);if(!n)throw new t(`cache-put-with-no-response`,{url:m(i.url)});let a=await this._ensureResponseSafeToCache(n);if(!a)return!1;let{cacheName:o,matchOptions:s}=this._strategy,c=await self.caches.open(o),l=this.hasCallback(`cacheDidUpdate`),u=l?await g(c,i.clone(),[`__WB_REVISION__`],s):null;try{await c.put(i,l?a.clone():a)}catch(e){if(e instanceof Error)throw e.name===`QuotaExceededError`&&await b(),e}for(let e of this.iterateCallbacks(`cacheDidUpdate`))await e({cacheName:o,oldResponse:u,newResponse:a.clone(),request:i,event:this.event});return!0}async getCacheKey(e,t){let n=`${e.url} | ${t}`;if(!this._cacheKeys[n]){let r=e;for(let e of this.iterateCallbacks(`cacheKeyWillBeUsed`))r=S(await e({mode:t,request:r,event:this.event,params:this.params}));this._cacheKeys[n]=r}return this._cacheKeys[n]}hasCallback(e){for(let t of this._strategy.plugins)if(e in t)return!0;return!1}async runCallbacks(e,t){for(let n of this.iterateCallbacks(e))await n(t)}*iterateCallbacks(e){for(let t of this._strategy.plugins)if(typeof t[e]==`function`){let n=this._pluginStateMap.get(t);yield r=>{let i=Object.assign(Object.assign({},r),{state:n});return t[e](i)}}}waitUntil(e){return this._extendLifetimePromises.push(e),e}async doneWaiting(){for(;this._extendLifetimePromises.length;){let e=this._extendLifetimePromises.splice(0),t=(await Promise.allSettled(e)).find(e=>e.status===`rejected`);if(t)throw t.reason}}destroy(){this._handlerDeferred.resolve(null)}async _ensureResponseSafeToCache(e){let t=e,n=!1;for(let e of this.iterateCallbacks(`cacheWillUpdate`))if(t=await e({request:this.request,response:t,event:this.event})||void 0,n=!0,!t)break;return n||t&&t.status!==200&&(t=void 0),t}},w=class{constructor(e={}){this.cacheName=a.getRuntimeName(e.cacheName),this.plugins=e.plugins||[],this.fetchOptions=e.fetchOptions,this.matchOptions=e.matchOptions}handle(e){let[t]=this.handleAll(e);return t}handleAll(e){e instanceof FetchEvent&&(e={event:e,request:e.request});let t=e.event,n=typeof e.request==`string`?new Request(e.request):e.request,r=`params`in e?e.params:void 0,i=new C(this,{event:t,request:n,params:r}),a=this._getResponse(i,n,t);return[a,this._awaitComplete(a,i,n,t)]}async _getResponse(e,n,r){await e.runCallbacks(`handlerWillStart`,{event:r,request:n});let i;try{if(i=await this._handle(n,e),!i||i.type===`error`)throw new t(`no-response`,{url:n.url})}catch(t){if(t instanceof Error){for(let a of e.iterateCallbacks(`handlerDidError`))if(i=await a({error:t,event:r,request:n}),i)break}if(!i)throw t}for(let t of e.iterateCallbacks(`handlerWillRespond`))i=await t({event:r,request:n,response:i});return i}async _awaitComplete(e,t,n,r){let i,a;try{i=await e}catch{}try{await t.runCallbacks(`handlerDidRespond`,{event:r,request:n,response:i}),await t.doneWaiting()}catch(e){e instanceof Error&&(a=e)}if(await t.runCallbacks(`handlerDidComplete`,{event:r,request:n,response:i,error:a}),t.destroy(),a)throw a}},T=class e extends w{constructor(t={}){t.cacheName=a.getPrecacheName(t.cacheName),super(t),this._fallbackToNetwork=t.fallbackToNetwork!==!1,this.plugins.push(e.copyRedirectedCacheableResponsesPlugin)}async _handle(e,t){return await t.cacheMatch(e)||(t.event&&t.event.type===`install`?await this._handleInstall(e,t):await this._handleFetch(e,t))}async _handleFetch(e,n){let r,i=n.params||{};if(this._fallbackToNetwork){let t=i.integrity,a=e.integrity,o=!a||a===t;r=await n.fetch(new Request(e,{integrity:e.mode===`no-cors`?void 0:a||t})),t&&o&&e.mode!==`no-cors`&&(this._useDefaultCacheabilityPluginIfNeeded(),await n.cachePut(e,r.clone()))}else throw new t(`missing-precache-entry`,{cacheName:this.cacheName,url:e.url});return r}async _handleInstall(e,n){this._useDefaultCacheabilityPluginIfNeeded();let r=await n.fetch(e);if(!await n.cachePut(e,r.clone()))throw new t(`bad-precaching-response`,{url:e.url,status:r.status});return r}_useDefaultCacheabilityPluginIfNeeded(){let t=null,n=0;for(let[r,i]of this.plugins.entries())i!==e.copyRedirectedCacheableResponsesPlugin&&(i===e.defaultPrecacheCacheabilityPlugin&&(t=r),i.cacheWillUpdate&&n++);n===0?this.plugins.push(e.defaultPrecacheCacheabilityPlugin):n>1&&t!==null&&this.plugins.splice(t,1)}};T.defaultPrecacheCacheabilityPlugin={async cacheWillUpdate({response:e}){return!e||e.status>=400?null:e}},T.copyRedirectedCacheableResponsesPlugin={async cacheWillUpdate({response:e}){return e.redirected?await p(e):e}};var E=class{constructor({cacheName:e,plugins:t=[],fallbackToNetwork:n=!0}={}){this._urlsToCacheKeys=new Map,this._urlsToCacheModes=new Map,this._cacheKeysToIntegrities=new Map,this._strategy=new T({cacheName:a.getPrecacheName(e),plugins:[...t,new u({precacheController:this})],fallbackToNetwork:n}),this.install=this.install.bind(this),this.activate=this.activate.bind(this)}get strategy(){return this._strategy}precache(e){this.addToCacheList(e),this._installAndActiveListenersAdded||=(self.addEventListener(`install`,this.install),self.addEventListener(`activate`,this.activate),!0)}addToCacheList(e){let n=[];for(let r of e){typeof r==`string`?n.push(r):r&&r.revision===void 0&&n.push(r.url);let{cacheKey:e,url:i}=c(r),a=typeof r!=`string`&&r.revision?`reload`:`default`;if(this._urlsToCacheKeys.has(i)&&this._urlsToCacheKeys.get(i)!==e)throw new t(`add-to-cache-list-conflicting-entries`,{firstEntry:this._urlsToCacheKeys.get(i),secondEntry:e});if(typeof r!=`string`&&r.integrity){if(this._cacheKeysToIntegrities.has(e)&&this._cacheKeysToIntegrities.get(e)!==r.integrity)throw new t(`add-to-cache-list-conflicting-integrities`,{url:i});this._cacheKeysToIntegrities.set(e,r.integrity)}if(this._urlsToCacheKeys.set(i,e),this._urlsToCacheModes.set(i,a),n.length>0){let e=`Workbox is precaching URLs without revision info: ${n.join(`, `)}\nThis is generally NOT safe. Learn more at https://bit.ly/wb-precache`;console.warn(e)}}}install(e){return o(e,async()=>{let t=new l;this.strategy.plugins.push(t);for(let[t,n]of this._urlsToCacheKeys){let r=this._cacheKeysToIntegrities.get(n),i=this._urlsToCacheModes.get(t),a=new Request(t,{integrity:r,cache:i,credentials:`same-origin`});await Promise.all(this.strategy.handleAll({params:{cacheKey:n},request:a,event:e}))}let{updatedURLs:n,notUpdatedURLs:r}=t;return{updatedURLs:n,notUpdatedURLs:r}})}activate(e){return o(e,async()=>{let e=await self.caches.open(this.strategy.cacheName),t=await e.keys(),n=new Set(this._urlsToCacheKeys.values()),r=[];for(let i of t)n.has(i.url)||(await e.delete(i),r.push(i.url));return{deletedURLs:r}})}getURLsToCacheKeys(){return this._urlsToCacheKeys}getCachedURLs(){return[...this._urlsToCacheKeys.keys()]}getCacheKeyForURL(e){let t=new URL(e,location.href);return this._urlsToCacheKeys.get(t.href)}getIntegrityForCacheKey(e){return this._cacheKeysToIntegrities.get(e)}async matchPrecache(e){let t=e instanceof Request?e.url:e,n=this.getCacheKeyForURL(t);if(n)return(await self.caches.open(this.strategy.cacheName)).match(n)}createHandlerBoundToURL(e){let n=this.getCacheKeyForURL(e);if(!n)throw new t(`non-precached-url`,{url:e});return t=>(t.request=new Request(e),t.params=Object.assign({cacheKey:n},t.params),this.strategy.handle(t))}},D,O=()=>(D||=new E,D);try{self[`workbox:routing:7.3.0`]&&_()}catch{}var k=e=>e&&typeof e==`object`?e:{handle:e},A=class{constructor(e,t,n=`GET`){this.handler=k(t),this.match=e,this.method=n}setCatchHandler(e){this.catchHandler=k(e)}},j=class extends A{constructor(e,t,n){super(({url:t})=>{let n=e.exec(t.href);if(n&&!(t.origin!==location.origin&&n.index!==0))return n.slice(1)},t,n)}},M=class{constructor(){this._routes=new Map,this._defaultHandlerMap=new Map}get routes(){return this._routes}addFetchListener(){self.addEventListener(`fetch`,(e=>{let{request:t}=e,n=this.handleRequest({request:t,event:e});n&&e.respondWith(n)}))}addCacheListener(){self.addEventListener(`message`,(e=>{if(e.data&&e.data.type===`CACHE_URLS`){let{payload:t}=e.data,n=Promise.all(t.urlsToCache.map(t=>{typeof t==`string`&&(t=[t]);let n=new Request(...t);return this.handleRequest({request:n,event:e})}));e.waitUntil(n),e.ports&&e.ports[0]&&n.then(()=>e.ports[0].postMessage(!0))}}))}handleRequest({request:e,event:t}){let n=new URL(e.url,location.href);if(!n.protocol.startsWith(`http`))return;let r=n.origin===location.origin,{params:i,route:a}=this.findMatchingRoute({event:t,request:e,sameOrigin:r,url:n}),o=a&&a.handler,s=e.method;if(!o&&this._defaultHandlerMap.has(s)&&(o=this._defaultHandlerMap.get(s)),!o)return;let c;try{c=o.handle({url:n,request:e,event:t,params:i})}catch(e){c=Promise.reject(e)}let l=a&&a.catchHandler;return c instanceof Promise&&(this._catchHandler||l)&&(c=c.catch(async r=>{if(l)try{return await l.handle({url:n,request:e,event:t,params:i})}catch(e){e instanceof Error&&(r=e)}if(this._catchHandler)return this._catchHandler.handle({url:n,request:e,event:t});throw r})),c}findMatchingRoute({url:e,sameOrigin:t,request:n,event:r}){let i=this._routes.get(n.method)||[];for(let a of i){let i,o=a.match({url:e,sameOrigin:t,request:n,event:r});if(o)return i=o,(Array.isArray(i)&&i.length===0||o.constructor===Object&&Object.keys(o).length===0||typeof o==`boolean`)&&(i=void 0),{route:a,params:i}}return{}}setDefaultHandler(e,t=`GET`){this._defaultHandlerMap.set(t,k(e))}setCatchHandler(e){this._catchHandler=k(e)}registerRoute(e){this._routes.has(e.method)||this._routes.set(e.method,[]),this._routes.get(e.method).push(e)}unregisterRoute(e){if(!this._routes.has(e.method))throw new t(`unregister-route-but-not-found-with-method`,{method:e.method});let n=this._routes.get(e.method).indexOf(e);if(n>-1)this._routes.get(e.method).splice(n,1);else throw new t(`unregister-route-route-not-registered`)}},N,P=()=>(N||(N=new M,N.addFetchListener(),N.addCacheListener()),N);function F(e,n,r){let i;if(typeof e==`string`){let t=new URL(e,location.href);i=new A(({url:e})=>e.href===t.href,n,r)}else if(e instanceof RegExp)i=new j(e,n,r);else if(typeof e==`function`)i=new A(e,n,r);else if(e instanceof A)i=e;else throw new t(`unsupported-route-type`,{moduleName:`workbox-routing`,funcName:`registerRoute`,paramName:`capture`});return P().registerRoute(i),i}function I(e,t=[]){for(let n of[...e.searchParams.keys()])t.some(e=>e.test(n))&&e.searchParams.delete(n);return e}function*L(e,{ignoreURLParametersMatching:t=[/^utm_/,/^fbclid$/],directoryIndex:n=`index.html`,cleanURLs:r=!0,urlManipulation:i}={}){let a=new URL(e,location.href);a.hash=``,yield a.href;let o=I(a,t);if(yield o.href,n&&o.pathname.endsWith(`/`)){let e=new URL(o.href);e.pathname+=n,yield e.href}if(r){let e=new URL(o.href);e.pathname+=`.html`,yield e.href}if(i){let e=i({url:a});for(let t of e)yield t.href}}var R=class extends A{constructor(e,t){super(({request:n})=>{let r=e.getURLsToCacheKeys();for(let i of L(n.url,t)){let t=r.get(i);if(t)return{cacheKey:t,integrity:e.getIntegrityForCacheKey(t)}}},e.strategy)}};function z(e){F(new R(O(),e))}function B(e){O().precache(e)}function V(e,t){B(e),z(t)}V([{"revision":"1872c500de691dce40960bb85481de07","url":"registerSW.js"},{"revision":"a0fb34fc84eb148d51812cd62669f20d","url":"icon-192.svg"},{"revision":"b828c433c952d5869f7f8c6f4f241f09","url":"index.html"},{"revision":"a0fb34fc84eb148d51812cd62669f20d","url":"icon-512.svg"},{"revision":null,"url":"assets/diff-viewer-NMLD4V8q.js"},{"revision":null,"url":"assets/dist-D7KGU7Vl.js"},{"revision":null,"url":"assets/KaTeX_Fraktur-Bold-CL6g_b3V.woff2"},{"revision":null,"url":"assets/audio-preview-C1p-Q5XZ.js"},{"revision":null,"url":"assets/KaTeX_AMS-Regular-BQhdFMY1.woff2"},{"revision":null,"url":"assets/scroll-area-BEllam7_.js"},{"revision":null,"url":"assets/gitGraph-HDMCJU4V-BdPTuzO3.js"},{"revision":null,"url":"assets/terminal-tab-CeHEtoE2.js"},{"revision":null,"url":"assets/chat-tab-BSJUkgxB.js"},{"revision":null,"url":"assets/pie-UPGHQEXC-CnaHXUh8.js"},{"revision":null,"url":"assets/port-forwarding-tab-dLhH_g2l.js"},{"revision":null,"url":"assets/KaTeX_Main-Regular-B22Nviop.woff2"},{"revision":null,"url":"assets/settings-tab-Mrs9uzCZ.js"},{"revision":null,"url":"assets/settings-store-BHBb62gq.js"},{"revision":null,"url":"assets/react-GqWghJ-L.js"},{"revision":null,"url":"assets/file-exclamation-point-Baz81y5z.js"},{"revision":null,"url":"assets/github.min-D2BCvnWf.css"},{"revision":null,"url":"assets/database-DOWH9-Vv.js"},{"revision":null,"url":"assets/KaTeX_Fraktur-Regular-CTYiF6lA.woff2"},{"revision":null,"url":"assets/info-3K5VOQVL-MHX_1JfR.js"},{"revision":null,"url":"assets/lib-D_kRA9p6.js"},{"revision":null,"url":"assets/dist-CGvx1c8C.js"},{"revision":null,"url":"assets/KaTeX_Main-BoldItalic-DxDJ3AOS.woff2"},{"revision":null,"url":"assets/api-settings-D0_eiIYv.js"},{"revision":null,"url":"assets/treemap-KZPCXAKY-CBVPi4NV.js"},{"revision":null,"url":"assets/csv-preview-D5lmgVEy.js"},{"revision":null,"url":"assets/vendor-markdown-0Mxgxy0L.js"},{"revision":null,"url":"assets/radar-KQ55EAFF-UxsdRHvt.js"},{"revision":null,"url":"assets/api-client-Dvzcc_EO.js"},{"revision":null,"url":"assets/architecture-PBZL5I3N-WMbLpD5Y.js"},{"revision":null,"url":"assets/KaTeX_Main-Italic-NWA7e6Wa.woff2"},{"revision":null,"url":"assets/table-Dq575bPF.js"},{"revision":null,"url":"assets/tab-store-0rGchMXr.js"},{"revision":null,"url":"assets/KaTeX_Typewriter-Regular-CO6r4hn1.woff2"},{"revision":null,"url":"assets/index-Dzb3OtrX.css"},{"revision":null,"url":"assets/code-editor-rNw5_pXh.js"},{"revision":null,"url":"assets/sql-query-editor-CMQpaOjA.js"},{"revision":null,"url":"assets/KaTeX_Caligraphic-Bold-Dq_IR9rO.woff2"},{"revision":null,"url":"assets/image-preview-Dqp1KSus.js"},{"revision":null,"url":"assets/data-grid-nZfSIop5.js"},{"revision":null,"url":"assets/KaTeX_Caligraphic-Regular-Di6jR-x-.woff2"},{"revision":null,"url":"assets/arrow-up-Dtrfv490.js"},{"revision":null,"url":"assets/refresh-cw-CSFrDtiu.js"},{"revision":null,"url":"assets/postgres-viewer-De0pzd1C.js"},{"revision":null,"url":"assets/rolldown-runtime-FhOqtrmT.js"},{"revision":null,"url":"assets/esm-nXReYVnB.js"},{"revision":null,"url":"assets/code-DGBecc50.js"},{"revision":null,"url":"assets/KaTeX_Math-Italic-t53AETM-.woff2"},{"revision":null,"url":"assets/github-dark-dimmed.min-BrpRStFV.css"},{"revision":null,"url":"assets/text-wrap-Cn6BNQfq.js"},{"revision":null,"url":"assets/katex-BFE6i_OH.js"},{"revision":null,"url":"assets/KaTeX_SansSerif-Bold-D1sUS0GD.woff2"},{"revision":null,"url":"assets/KaTeX_Script-Regular-D3wIWfF6.woff2"},{"revision":null,"url":"assets/trash-2-CJYoLw7Q.js"},{"revision":null,"url":"assets/extension-webview-DW2dBswj.js"},{"revision":null,"url":"assets/use-monaco-theme-CP-vyTF8.js"},{"revision":null,"url":"assets/file-store-BrbCNyLm.js"},{"revision":null,"url":"assets/use-blob-url-Hn6n1730.js"},{"revision":null,"url":"assets/pdf-preview-ChC1gaaZ.js"},{"revision":null,"url":"assets/utils-CTg5uAYR.js"},{"revision":null,"url":"assets/KaTeX_Main-Bold-Cx986IdX.woff2"},{"revision":null,"url":"assets/conflict-editor-Dcn3HuLD.js"},{"revision":null,"url":"assets/vendor-mermaid-CMiurk2b.js"},{"revision":null,"url":"assets/KaTeX_Size2-Regular-Dy4dx90m.woff2"},{"revision":null,"url":"assets/KaTeX_SansSerif-Regular-DDBCnlJ7.woff2"},{"revision":null,"url":"assets/KaTeX_Size1-Regular-mCD8mA8B.woff2"},{"revision":null,"url":"assets/database-viewer-CNoq5Uxp.js"},{"revision":null,"url":"assets/ai-settings-section-CLNBWLS4.js"},{"revision":null,"url":"assets/csv-parser-DO0dz4x_.js"},{"revision":null,"url":"assets/createLucideIcon-BjHrJDVb.js"},{"revision":null,"url":"assets/input-DYWhyaze.js"},{"revision":null,"url":"assets/chevron-right-DnHIvvcy.js"},{"revision":null,"url":"assets/video-preview-CHPVrMtx.js"},{"revision":null,"url":"assets/KaTeX_Size4-Regular-Dl5lxZxV.woff2"},{"revision":null,"url":"assets/markdown-renderer-DNIXdY0d.js"},{"revision":null,"url":"assets/index-CoMWx5VS.js"},{"revision":null,"url":"assets/KaTeX_Math-BoldItalic-CZnvNsCZ.woff2"},{"revision":null,"url":"assets/x-OGGXhtlb.js"},{"revision":null,"url":"assets/sparkles-B0mRBy_j.js"},{"revision":null,"url":"assets/vendor-ui-B-89Uj8i.js"},{"revision":null,"url":"assets/vendor-xterm-u3AZMvTx.js"},{"revision":null,"url":"assets/packet-RMMSAZCW-CreFbf9A.js"},{"revision":null,"url":"assets/keybindings-store-B7nlHmDh.js"},{"revision":null,"url":"assets/sql-completion-provider-tCzZfqWs.js"},{"revision":null,"url":"assets/vendor-xterm-BrP-ENHg.css"},{"revision":null,"url":"assets/sqlite-viewer-BqtIjvil.js"},{"revision":null,"url":"assets/KaTeX_SansSerif-Italic-C3H0VqGB.woff2"},{"revision":"d0f94ce046cf8cf09605ee7664dac557","url":"monacoeditorwork/html.worker.bundle.js"},{"revision":"a424156a79b9c1b907db93aa3180585a","url":"monacoeditorwork/editor.worker.bundle.js"},{"revision":"b3a7f967560c9816492a1567b3f7f0dc","url":"monacoeditorwork/css.worker.bundle.js"},{"revision":"a5d8a1acfc29c2a4c882a54ffc93def3","url":"monacoeditorwork/json.worker.bundle.js"},{"revision":"948e060affb598c339be40d69e1f6f9c","url":"monacoeditorwork/ts.worker.bundle.js"},{"revision":"79c8870653c8f419f2e3323085e1f4be","url":"manifest.webmanifest"}]),self.addEventListener(`push`,e=>{e.waitUntil(self.clients.matchAll({type:`window`,includeUncontrolled:!0}).then(t=>{if(t.some(e=>e.visibilityState===`visible`))return;let n=e.data?.json()??{title:`PPM`,body:`Chat completed`};return self.registration.showNotification(n.title,{body:n.body,icon:`/icon-192.png`,badge:`/icon-192.png`,tag:`ppm-chat-done`,silent:!1,data:{url:self.location.origin}})}))}),self.addEventListener(`notificationclick`,e=>{e.notification.close(),e.waitUntil(self.clients.matchAll({type:`window`,includeUncontrolled:!0}).then(t=>{for(let e of t)if(e.url.includes(self.location.origin)&&`focus`in e)return e.focus();return self.clients.openWindow(e.notification.data?.url||`/`)}))});
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@hienlh/ppm",
3
- "version": "0.13.7",
3
+ "version": "0.13.9",
4
4
  "description": "Personal Project Manager — mobile-first web IDE with AI assistance",
5
5
  "author": "hienlh",
6
6
  "license": "MIT",
@@ -45,6 +45,7 @@
45
45
  "dependencies": {
46
46
  "@anthropic-ai/claude-agent-sdk": "^0.2.81",
47
47
  "@codemirror/lang-sql": "^6.10.0",
48
+ "@glideapps/glide-data-grid": "^6.0.3",
48
49
  "@inquirer/prompts": "^8.3.0",
49
50
  "@monaco-editor/react": "^4.7.0",
50
51
  "@radix-ui/react-switch": "^1.2.6",
package/src/index.ts CHANGED
File without changes
@@ -83,6 +83,10 @@ export const terminalWebSocket = {
83
83
 
84
84
  close(ws: { data: { type: string; id: string } }) {
85
85
  const sessionId = ws.data.id;
86
+ const session = terminalService.get(sessionId);
87
+ // Only clean up if this WS is still the active connection.
88
+ // Prevents race: stale WS close fires after new WS open, removing the new listener.
89
+ if (!session || session.ws !== ws) return;
86
90
  terminalService.removeOutputListener(sessionId);
87
91
  terminalService.setDisconnected(sessionId);
88
92
  },
@@ -144,7 +144,10 @@ class TerminalService {
144
144
  };
145
145
  const onExit = () => {
146
146
  const listener = this.outputListeners.get(id);
147
- if (listener) listener(id, "\r\n[Process exited]\r\n");
147
+ if (listener) {
148
+ listener(id, "\r\n[Process exited]\r\n");
149
+ listener(id, JSON.stringify({ type: "exited" }));
150
+ }
148
151
  };
149
152
 
150
153
  const pty = isWindows
@@ -1,7 +1,9 @@
1
1
  import { useState, useCallback, useMemo, useRef, memo, useEffect } from "react";
2
- import { Loader2, ChevronLeft, ChevronRight, ChevronUp, ChevronDown, Trash2, Plus, Search, X, Eye, Filter, Pin, PinOff, Columns3 } from "lucide-react";
2
+ import Editor from "@monaco-editor/react";
3
+ import { Loader2, ChevronLeft, ChevronRight, ChevronUp, ChevronDown, Trash2, Plus, Search, X, Eye, ExternalLink, WrapText, Sparkles, GripHorizontal, Filter, Pin, PinOff, Columns3 } from "lucide-react";
3
4
  import { useShallow } from "zustand/react/shallow";
4
5
  import { useTabStore } from "@/stores/tab-store";
6
+ import { useMonacoTheme } from "@/lib/use-monaco-theme";
5
7
  import type { DbColumnInfo } from "./use-database";
6
8
  import { ExportButton } from "./export-button";
7
9
 
@@ -44,15 +46,14 @@ export function DataGrid({
44
46
  const [insertError, setInsertError] = useState<string | null>(null);
45
47
  const [confirmBulkDelete, setConfirmBulkDelete] = useState(false);
46
48
  const { openTab } = useTabStore(useShallow((s) => ({ openTab: s.openTab })));
47
- const openCellViewer = useCallback((cell: { col: string; value: string }) => {
48
- openTab({
49
- type: "editor",
50
- title: cell.col,
51
- projectId: null,
52
- closable: true,
53
- metadata: { inlineContent: cell.value, inlineLanguage: detectLang(cell.value) },
54
- });
55
- }, [openTab]);
49
+ const [previewData, setPreviewData] = useState<{ title: string; content: string; language: string; viewerKey: string } | null>(null);
50
+ const openCellViewer = useCallback((cell: { col: string; value: string; pkVal: string }) => {
51
+ const table = selectedTable ?? "";
52
+ const lang = detectLang(cell.value);
53
+ const key = `${connectionId ?? "local"}:${table}:${cell.col}:${cell.pkVal}`;
54
+ const title = table ? `${cell.col} #${cell.pkVal} — ${table}` : `${cell.col} #${cell.pkVal}`;
55
+ setPreviewData({ title, content: cell.value, language: lang, viewerKey: key });
56
+ }, [connectionId, selectedTable]);
56
57
  const [pinnedCols, setPinnedCols] = useState<Set<string>>(new Set());
57
58
  const [pinnedRows, setPinnedRows] = useState<Set<number>>(new Set());
58
59
  const [filterOpenCol, setFilterOpenCol] = useState<string | null>(null);
@@ -69,14 +70,21 @@ export function DataGrid({
69
70
  const openRowViewer = useCallback((row: Record<string, unknown>) => {
70
71
  const json = JSON.stringify(row, null, 2);
71
72
  const pk = pkCol ? String(row[pkCol] ?? "") : "";
73
+ const table = selectedTable ?? "";
74
+ const key = `${connectionId ?? "local"}:${table}:row:${pk || "unknown"}`;
75
+ const title = pk ? `Row #${pk}${table ? ` — ${table}` : ""}` : `Row${table ? ` — ${table}` : ""}`;
76
+ setPreviewData({ title, content: json, language: "json", viewerKey: key });
77
+ }, [pkCol, connectionId, selectedTable]);
78
+ const openPreviewInTab = useCallback(() => {
79
+ if (!previewData) return;
72
80
  openTab({
73
81
  type: "editor",
74
- title: pk ? `Row ${pk}` : "Row",
82
+ title: previewData.title,
75
83
  projectId: null,
76
84
  closable: true,
77
- metadata: { inlineContent: json, inlineLanguage: "json" },
85
+ metadata: { inlineContent: previewData.content, inlineLanguage: previewData.language, viewerKey: previewData.viewerKey },
78
86
  });
79
- }, [openTab, pkCol]);
87
+ }, [openTab, previewData]);
80
88
 
81
89
  // Refs for cell renderers — avoid column memo rebuild on every state change
82
90
  const editingRef = useRef(editingCell);
@@ -196,7 +204,7 @@ export function DataGrid({
196
204
  if (!el) return;
197
205
  const handler = (e: KeyboardEvent) => {
198
206
  // Escape closes column search from anywhere
199
- if (e.key === "Escape") { setColSearchOpen(false); return; }
207
+ if (e.key === "Escape") { setColSearchOpen(false); setPreviewData(null); return; }
200
208
 
201
209
  // Skip if focus is in an input/textarea
202
210
  const tag = (e.target as HTMLElement)?.tagName;
@@ -433,7 +441,7 @@ export function DataGrid({
433
441
  )}
434
442
 
435
443
  {/* Table */}
436
- <div ref={scrollRef} className="flex-1 overflow-auto relative">
444
+ <div ref={scrollRef} className="flex-1 overflow-auto relative min-h-0">
437
445
  {loading && (
438
446
  <div className="absolute inset-0 z-30 flex items-center justify-center bg-background/60">
439
447
  <Loader2 className="size-5 animate-spin text-primary" />
@@ -540,6 +548,11 @@ export function DataGrid({
540
548
  </table>
541
549
  </div>
542
550
 
551
+ {/* Inline preview panel */}
552
+ {previewData && (
553
+ <DataPreviewPanel data={previewData} onClose={() => setPreviewData(null)} onOpenInTab={openPreviewInTab} />
554
+ )}
555
+
543
556
  {/* Footer: row count + pagination */}
544
557
  <div className="flex items-center justify-between px-3 py-1.5 border-t border-border bg-background shrink-0 text-xs text-muted-foreground">
545
558
  <span>{tableData.total.toLocaleString()} rows</span>
@@ -596,6 +609,109 @@ function detectLang(text: string): string {
596
609
  return "plaintext";
597
610
  }
598
611
 
612
+ /** Inline preview panel for cell/row content with Monaco editor */
613
+ function DataPreviewPanel({ data, onClose, onOpenInTab }: {
614
+ data: { title: string; content: string; language: string };
615
+ onClose: () => void;
616
+ onOpenInTab: () => void;
617
+ }) {
618
+ const monacoTheme = useMonacoTheme();
619
+ const [wordWrap, setWordWrap] = useState(true);
620
+ const [displayContent, setDisplayContent] = useState(data.content);
621
+ const [beautified, setBeautified] = useState(false);
622
+ const canBeautify = data.language === "json" || data.language === "xml";
623
+
624
+ // Reset state when data changes
625
+ const prevKey = useRef(data.title);
626
+ if (prevKey.current !== data.title) {
627
+ prevKey.current = data.title;
628
+ setDisplayContent(data.content);
629
+ setBeautified(false);
630
+ }
631
+
632
+ const toggleBeautify = useCallback(() => {
633
+ if (beautified) {
634
+ setDisplayContent(data.content);
635
+ setBeautified(false);
636
+ } else {
637
+ if (data.language === "json") {
638
+ try { setDisplayContent(JSON.stringify(JSON.parse(data.content.trim()), null, 2)); setBeautified(true); } catch { /* invalid */ }
639
+ } else if (data.language === "xml") {
640
+ // Simple XML indent
641
+ let depth = 0;
642
+ const formatted = data.content.trim().replace(/>\s*</g, ">\n<").split("\n").map((line) => {
643
+ const trimmed = line.trim();
644
+ if (trimmed.startsWith("</")) depth = Math.max(0, depth - 1);
645
+ const indented = " ".repeat(depth) + trimmed;
646
+ if (trimmed.startsWith("<") && !trimmed.startsWith("</") && !trimmed.endsWith("/>") && !trimmed.startsWith("<?")) depth++;
647
+ return indented;
648
+ }).join("\n");
649
+ setDisplayContent(formatted);
650
+ setBeautified(true);
651
+ }
652
+ }
653
+ }, [beautified, data.content, data.language]);
654
+
655
+ const [panelHeight, setPanelHeight] = useState(200);
656
+ const handleDrag = useCallback((e: React.MouseEvent) => {
657
+ e.preventDefault();
658
+ const startY = e.clientY;
659
+ const startH = panelHeight;
660
+ const onMove = (ev: MouseEvent) => setPanelHeight(Math.max(80, startH + (startY - ev.clientY)));
661
+ const onUp = () => { document.removeEventListener("mousemove", onMove); document.removeEventListener("mouseup", onUp); };
662
+ document.addEventListener("mousemove", onMove);
663
+ document.addEventListener("mouseup", onUp);
664
+ }, [panelHeight]);
665
+
666
+ return (
667
+ <div className="shrink-0 border-t border-border flex flex-col" style={{ height: panelHeight }}>
668
+ {/* Resize handle */}
669
+ <div onMouseDown={handleDrag}
670
+ className="shrink-0 h-1.5 cursor-row-resize bg-border/50 hover:bg-primary/30 flex items-center justify-center transition-colors">
671
+ <GripHorizontal className="size-3 text-muted-foreground/50" />
672
+ </div>
673
+ <div className="flex items-center gap-1 px-2 py-1 bg-muted/50 border-b border-border shrink-0">
674
+ <Eye className="size-3 text-muted-foreground" />
675
+ <span className="text-xs font-medium text-foreground truncate flex-1">{data.title}</span>
676
+ {canBeautify && (
677
+ <button type="button" onClick={toggleBeautify} title={beautified ? "Raw" : "Beautify"}
678
+ className={`p-0.5 rounded transition-colors ${beautified ? "text-primary" : "text-muted-foreground hover:text-foreground"}`}>
679
+ <Sparkles className="size-3" />
680
+ </button>
681
+ )}
682
+ <button type="button" onClick={() => setWordWrap(!wordWrap)} title={wordWrap ? "No wrap" : "Word wrap"}
683
+ className={`p-0.5 rounded transition-colors ${wordWrap ? "text-primary" : "text-muted-foreground hover:text-foreground"}`}>
684
+ <WrapText className="size-3" />
685
+ </button>
686
+ <button type="button" onClick={onOpenInTab} title="Open in new tab"
687
+ className="flex items-center gap-1 px-1.5 py-0.5 rounded text-[10px] text-muted-foreground hover:text-foreground hover:bg-muted transition-colors">
688
+ <ExternalLink className="size-3" />
689
+ <span className="hidden sm:inline">Open in Tab</span>
690
+ </button>
691
+ <button type="button" onClick={onClose} title="Close preview (Esc)"
692
+ className="p-0.5 rounded text-muted-foreground hover:text-foreground transition-colors">
693
+ <X className="size-3" />
694
+ </button>
695
+ </div>
696
+ <div className="flex-1 min-h-0">
697
+ <Editor
698
+ height="100%"
699
+ language={data.language === "plaintext" ? undefined : data.language}
700
+ value={displayContent}
701
+ theme={monacoTheme}
702
+ options={{
703
+ readOnly: true, minimap: { enabled: false }, scrollBeyondLastLine: false,
704
+ wordWrap: wordWrap ? "on" : "off", lineNumbers: "on", fontSize: 12,
705
+ folding: true, bracketPairColorization: { enabled: true },
706
+ domReadOnly: true, contextmenu: false, overviewRulerLanes: 0,
707
+ }}
708
+ loading={<Loader2 className="size-4 animate-spin text-muted-foreground" />}
709
+ />
710
+ </div>
711
+ </div>
712
+ );
713
+ }
714
+
599
715
  /** Column search dropdown — owns query/index state internally to avoid re-rendering DataGrid */
600
716
  function ColumnSearchDropdown({ columns, onSelect, onClose }: {
601
717
  columns: string[]; onSelect: (col: string) => void; onClose: () => void;
@@ -651,7 +767,7 @@ const DataRow = memo(function DataRow({ row, rowIdx, columns, selected, onToggle
651
767
  onSetEditValue: (v: string) => void;
652
768
  showDelete: boolean; confirmingDelete: boolean;
653
769
  onDelete: (i: number) => void; onConfirmDelete: (i: number | null) => void;
654
- onViewCell: (cell: { col: string; value: string }) => void;
770
+ onViewCell: (cell: { col: string; value: string; pkVal: string }) => void;
655
771
  onViewRow: (row: Record<string, unknown>) => void;
656
772
  pinned: boolean; onTogglePin: (i: number) => void;
657
773
  pinnedCols: Set<string>; pinnedColOffsets: Map<string, number>;
@@ -702,7 +818,7 @@ const DataRow = memo(function DataRow({ row, rowIdx, columns, selected, onToggle
702
818
  </span>
703
819
  {showEye && (
704
820
  <button type="button" title="View full content"
705
- onClick={() => onViewCell({ col, value: formatCellValue(val) })}
821
+ onClick={() => onViewCell({ col, value: formatCellValue(val), pkVal: pkCol ? String(row[pkCol] ?? rowIdx) : String(rowIdx) })}
706
822
  className="shrink-0 p-0.5 rounded text-muted-foreground/50 hover:text-foreground transition-colors">
707
823
  <Eye className="size-3" />
708
824
  </button>
@@ -0,0 +1,82 @@
1
+ import { useState, useEffect, useMemo } from "react";
2
+ import type { Theme } from "@glideapps/glide-data-grid";
3
+ import "@glideapps/glide-data-grid/dist/index.css";
4
+
5
+ /** Read a CSS custom property from :root */
6
+ function cssVar(name: string): string {
7
+ return getComputedStyle(document.documentElement).getPropertyValue(name).trim();
8
+ }
9
+
10
+ /** Add alpha channel to a hex/rgb color string */
11
+ function withAlpha(color: string, alpha: number): string {
12
+ if (color.startsWith("#")) {
13
+ const hex = color.slice(1);
14
+ const r = parseInt(hex.slice(0, 2), 16);
15
+ const g = parseInt(hex.slice(2, 4), 16);
16
+ const b = parseInt(hex.slice(4, 6), 16);
17
+ return `rgba(${r}, ${g}, ${b}, ${alpha})`;
18
+ }
19
+ return color;
20
+ }
21
+
22
+ /** Build Glide theme from current CSS variables */
23
+ function buildTheme(): Partial<Theme> {
24
+ const bg = cssVar("--color-background");
25
+ const fg = cssVar("--color-foreground");
26
+ const muted = cssVar("--color-muted");
27
+ const mutedFg = cssVar("--color-muted-foreground");
28
+ const primary = cssVar("--color-primary");
29
+ const primaryFg = cssVar("--color-primary-foreground");
30
+ const border = cssVar("--color-border");
31
+ const accent = cssVar("--color-accent");
32
+ const textSecondary = cssVar("--color-text-secondary");
33
+ const textSubtle = cssVar("--color-text-subtle");
34
+ const fontSans = cssVar("--font-sans") || "Geist, system-ui, sans-serif";
35
+
36
+ return {
37
+ bgCell: bg,
38
+ bgCellMedium: muted,
39
+ bgHeader: muted,
40
+ bgHeaderHasFocus: accent,
41
+ bgHeaderHovered: accent,
42
+ bgBubble: accent,
43
+ bgBubbleSelected: primary,
44
+ textDark: fg,
45
+ textMedium: textSecondary,
46
+ textLight: textSubtle,
47
+ textHeader: mutedFg,
48
+ textGroupHeader: mutedFg,
49
+ textHeaderSelected: fg,
50
+ textBubble: fg,
51
+ accentColor: primary,
52
+ accentFg: primaryFg,
53
+ accentLight: withAlpha(primary, 0.12),
54
+ borderColor: border,
55
+ horizontalBorderColor: border,
56
+ fontFamily: fontSans,
57
+ baseFontStyle: "13px",
58
+ headerFontStyle: "600 12px",
59
+ editorFontSize: "13px",
60
+ lineHeight: 1.5,
61
+ cellHorizontalPadding: 8,
62
+ cellVerticalPadding: 4,
63
+ headerIconSize: 16,
64
+ };
65
+ }
66
+
67
+ /**
68
+ * Hook that returns a Glide Data Grid theme synced to PPM's dark/light mode.
69
+ * Watches <html> class changes via MutationObserver to rebuild on theme toggle.
70
+ */
71
+ export function useGlideTheme(): Partial<Theme> {
72
+ // Bump counter on theme class change to trigger rebuild
73
+ const [rev, setRev] = useState(0);
74
+
75
+ useEffect(() => {
76
+ const observer = new MutationObserver(() => setRev((r) => r + 1));
77
+ observer.observe(document.documentElement, { attributes: true, attributeFilter: ["class"] });
78
+ return () => observer.disconnect();
79
+ }, []);
80
+
81
+ return useMemo(() => buildTheme(), [rev]); // eslint-disable-line react-hooks/exhaustive-deps
82
+ }
@@ -0,0 +1,79 @@
1
+ /** Shared types for Glide Data Grid wrapper used by database-viewer and sqlite-viewer */
2
+
3
+ /** Unified column schema — superset of DbColumnInfo and sqlite ColumnInfo */
4
+ export interface GridColumnSchema {
5
+ name: string;
6
+ type: string;
7
+ nullable: boolean;
8
+ pk: boolean;
9
+ defaultValue?: string | null;
10
+ }
11
+
12
+ /** Unified props interface for the Glide Data Grid wrapper component */
13
+ export interface GlideGridProps {
14
+ /** Column names in display order */
15
+ columns: string[];
16
+ /** Row data array (current page) */
17
+ rows: Record<string, unknown>[];
18
+ /** Total row count across all pages */
19
+ total: number;
20
+ /** Rows per page */
21
+ limit: number;
22
+ /** Column schema metadata */
23
+ schema: GridColumnSchema[];
24
+ /** Whether data is currently loading */
25
+ loading: boolean;
26
+ /** Current page number (1-based) */
27
+ page: number;
28
+ onPageChange: (page: number) => void;
29
+ /** Cell edit: (pkColumn, pkValue, editedColumn, newValue) */
30
+ onCellUpdate: (pkCol: string, pkVal: unknown, col: string, val: unknown) => void;
31
+ onRowDelete?: (pkCol: string, pkVal: unknown) => void;
32
+ onBulkDelete?: (pkCol: string, pkValues: unknown[]) => void;
33
+ onInsertRow?: (values: Record<string, unknown>) => Promise<void>;
34
+ /** Current sort column */
35
+ orderBy?: string | null;
36
+ orderDir?: "ASC" | "DESC";
37
+ onToggleSort?: (column: string) => void;
38
+ /** Per-column ILIKE filters (server-side) */
39
+ columnFilters?: Record<string, string>;
40
+ onColumnFilter?: (filters: Record<string, string>) => void;
41
+ /** Metadata for export/viewer features */
42
+ connectionId?: number;
43
+ selectedTable?: string | null;
44
+ selectedSchema?: string;
45
+ connectionName?: string;
46
+ }
47
+
48
+ /** Threshold in bytes for showing cell viewer (eye button) */
49
+ export const LARGE_THRESHOLD = 200;
50
+
51
+ /** Check if a cell value needs the large data viewer */
52
+ export function needsViewer(val: unknown): boolean {
53
+ if (val == null) return false;
54
+ if (typeof val === "object") return true;
55
+ const s = String(val);
56
+ if (s.length >= LARGE_THRESHOLD) return true;
57
+ const trimmed = s.trimStart();
58
+ if ((trimmed[0] === "{" || trimmed[0] === "[") && (trimmed.endsWith("}") || trimmed.endsWith("]"))) return true;
59
+ if (trimmed.startsWith("<?xml") || (trimmed.startsWith("<") && trimmed.endsWith(">"))) return true;
60
+ return false;
61
+ }
62
+
63
+ /** Format cell value for display — JSON-stringify objects, otherwise String() */
64
+ export function formatCellValue(val: unknown): string {
65
+ if (val == null) return "NULL";
66
+ if (typeof val === "object") return JSON.stringify(val);
67
+ return String(val);
68
+ }
69
+
70
+ /** Detect language from cell content for syntax highlighting in viewer */
71
+ export function detectLang(text: string): string {
72
+ const t = text.trimStart();
73
+ if (t[0] === "{" || t[0] === "[") {
74
+ try { JSON.parse(t); return "json"; } catch { /* not json */ }
75
+ }
76
+ if (t.startsWith("<?xml") || (t.startsWith("<") && /<\/\w+>/.test(t))) return "xml";
77
+ if (t.startsWith("---") || /^\w+:\s/m.test(t)) return "yaml";
78
+ return "plaintext";
79
+ }