@hienlh/ppm 0.13.9 → 0.13.11

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 (113) hide show
  1. package/CHANGELOG.md +8 -0
  2. package/assets/skills/ppm/SKILL.md +1 -1
  3. package/assets/skills/ppm/references/http-api.md +1 -1
  4. package/bun.lock +2135 -0
  5. package/bunfig.toml +2 -0
  6. package/dist/web/assets/ai-settings-section-ysK_Eixc.js +1 -0
  7. package/dist/web/assets/architecture-PBZL5I3N-By4Nv3Gj.js +1 -0
  8. package/dist/web/assets/{audio-preview-C1p-Q5XZ.js → audio-preview-dOvnFQN8.js} +1 -1
  9. package/dist/web/assets/chat-tab-C6NVtLx3.js +12 -0
  10. package/dist/web/assets/code-editor-3e9UAnzv.js +8 -0
  11. package/dist/web/assets/{conflict-editor-Dcn3HuLD.js → conflict-editor-XMpuwtUv.js} +1 -1
  12. package/dist/web/assets/csv-parser-Dly5nqE1.js +6 -0
  13. package/dist/web/assets/{csv-preview-D5lmgVEy.js → csv-preview-7TsYBQI6.js} +3 -3
  14. package/dist/web/assets/data-grid-overlay-editor-BjjuE4-G.js +1 -0
  15. package/dist/web/assets/data-grid-types-BTQHYBUh.js +1 -0
  16. package/dist/web/assets/database-viewer-GNKYeCIc.js +1 -0
  17. package/dist/web/assets/{diff-viewer-NMLD4V8q.js → diff-viewer-DjFe6idy.js} +1 -1
  18. package/dist/web/assets/dist-0kPgRaVx.js +1 -0
  19. package/dist/web/assets/{esm-nXReYVnB.js → esm-zjerHxpO.js} +1 -1
  20. package/dist/web/assets/{extension-webview-DW2dBswj.js → extension-webview-hgbO93RZ.js} +1 -1
  21. package/dist/web/assets/gitGraph-HDMCJU4V-BLXEKVf1.js +1 -0
  22. package/dist/web/assets/glide-data-grid-nthEL3fk.css +1 -0
  23. package/dist/web/assets/glide-data-grid-uLRTmkwH.js +136 -0
  24. package/dist/web/assets/{image-preview-Dqp1KSus.js → image-preview-CzwOU5op.js} +1 -1
  25. package/dist/web/assets/index-BAPR3hYQ.js +27 -0
  26. package/dist/web/assets/index-COOnLKGB.css +2 -0
  27. package/dist/web/assets/info-3K5VOQVL-CEkPcChg.js +1 -0
  28. package/dist/web/assets/{input-DYWhyaze.js → input-ozrR2DAV.js} +1 -1
  29. package/dist/web/assets/keybindings-store-D9GV2h8K.js +1 -0
  30. package/dist/web/assets/{markdown-renderer-DNIXdY0d.js → markdown-renderer-BD5P19YN.js} +3 -3
  31. package/dist/web/assets/number-overlay-editor-BoRxunFN.js +9 -0
  32. package/dist/web/assets/packet-RMMSAZCW-DECxYTOi.js +1 -0
  33. package/dist/web/assets/{pdf-preview-ChC1gaaZ.js → pdf-preview-DRbBRYIF.js} +1 -1
  34. package/dist/web/assets/pie-UPGHQEXC-cjpNfVG5.js +1 -0
  35. package/dist/web/assets/{port-forwarding-tab-dLhH_g2l.js → port-forwarding-tab-BSFhNv-A.js} +1 -1
  36. package/dist/web/assets/{postgres-viewer-De0pzd1C.js → postgres-viewer-D51L9fxD.js} +3 -3
  37. package/dist/web/assets/radar-KQ55EAFF-Dnpi068b.js +1 -0
  38. package/dist/web/assets/{settings-store-BHBb62gq.js → settings-store-B-OmHo3J.js} +1 -1
  39. package/dist/web/assets/settings-tab-DdbYEmAC.js +1 -0
  40. package/dist/web/assets/sql-query-editor-7pD60nKZ.js +3 -0
  41. package/dist/web/assets/sqlite-viewer-DLNJ_IGM.js +1 -0
  42. package/dist/web/assets/terminal-tab-6T5e8Nar.js +1 -0
  43. package/dist/web/assets/treemap-KZPCXAKY-DRyb1eiw.js +1 -0
  44. package/dist/web/assets/{use-monaco-theme-CP-vyTF8.js → use-monaco-theme-DgzxiZS5.js} +1 -1
  45. package/dist/web/assets/{vendor-mermaid-CMiurk2b.js → vendor-mermaid-CCmA_6Y0.js} +3 -3
  46. package/dist/web/assets/{video-preview-CHPVrMtx.js → video-preview-BwDNFl7v.js} +1 -1
  47. package/dist/web/assets/x-CG-_0yIW.js +1 -0
  48. package/dist/web/index.html +10 -11
  49. package/dist/web/sw.js +1 -1
  50. package/package.json +1 -1
  51. package/src/index.ts +0 -0
  52. package/src/web/components/chat/chat-tab.tsx +4 -1
  53. package/src/web/components/chat/message-input.tsx +28 -14
  54. package/src/web/components/database/database-viewer.tsx +19 -8
  55. package/src/web/components/database/export-button.tsx +38 -18
  56. package/src/web/components/database/glide-column-search.tsx +81 -0
  57. package/src/web/components/database/glide-context-menu.tsx +95 -0
  58. package/src/web/components/database/glide-data-grid.tsx +207 -0
  59. package/src/web/components/database/glide-data-preview-panel.tsx +113 -0
  60. package/src/web/components/database/glide-grid-pagination.tsx +34 -0
  61. package/src/web/components/database/glide-grid-toolbar.tsx +105 -0
  62. package/src/web/components/database/glide-grid-types.ts +2 -0
  63. package/src/web/components/database/glide-header-menu.tsx +111 -0
  64. package/src/web/components/database/glide-save-bar.tsx +33 -0
  65. package/src/web/components/database/sql-query-editor.tsx +14 -4
  66. package/src/web/components/database/use-database.ts +10 -2
  67. package/src/web/components/database/use-glide-cell-content.ts +65 -30
  68. package/src/web/components/database/use-glide-columns.ts +24 -16
  69. package/src/web/components/database/use-glide-grid-actions.ts +164 -0
  70. package/src/web/components/database/use-glide-pending-edits.ts +72 -0
  71. package/src/web/components/database/use-glide-row-pinning.ts +35 -0
  72. package/src/web/components/editor/code-editor.tsx +7 -5
  73. package/src/web/components/layout/editor-panel.tsx +2 -2
  74. package/src/web/components/sqlite/sqlite-viewer.tsx +21 -12
  75. package/src/web/components/sqlite/use-sqlite.ts +1 -1
  76. package/src/web/hooks/use-chat.ts +27 -20
  77. package/src/web/hooks/use-global-keybindings.ts +12 -0
  78. package/src/web/hooks/use-terminal.ts +1 -1
  79. package/dist/web/assets/ai-settings-section-CLNBWLS4.js +0 -1
  80. package/dist/web/assets/architecture-PBZL5I3N-WMbLpD5Y.js +0 -1
  81. package/dist/web/assets/chat-tab-BSJUkgxB.js +0 -12
  82. package/dist/web/assets/code-editor-rNw5_pXh.js +0 -8
  83. package/dist/web/assets/csv-parser-DO0dz4x_.js +0 -6
  84. package/dist/web/assets/data-grid-nZfSIop5.js +0 -5
  85. package/dist/web/assets/database-viewer-CNoq5Uxp.js +0 -1
  86. package/dist/web/assets/gitGraph-HDMCJU4V-BdPTuzO3.js +0 -1
  87. package/dist/web/assets/index-CoMWx5VS.js +0 -27
  88. package/dist/web/assets/index-Dzb3OtrX.css +0 -2
  89. package/dist/web/assets/info-3K5VOQVL-MHX_1JfR.js +0 -1
  90. package/dist/web/assets/keybindings-store-B7nlHmDh.js +0 -1
  91. package/dist/web/assets/packet-RMMSAZCW-CreFbf9A.js +0 -1
  92. package/dist/web/assets/pie-UPGHQEXC-CnaHXUh8.js +0 -1
  93. package/dist/web/assets/radar-KQ55EAFF-UxsdRHvt.js +0 -1
  94. package/dist/web/assets/settings-tab-Mrs9uzCZ.js +0 -1
  95. package/dist/web/assets/sql-completion-provider-tCzZfqWs.js +0 -1
  96. package/dist/web/assets/sql-query-editor-CMQpaOjA.js +0 -3
  97. package/dist/web/assets/sqlite-viewer-BqtIjvil.js +0 -1
  98. package/dist/web/assets/terminal-tab-CeHEtoE2.js +0 -1
  99. package/dist/web/assets/trash-2-CJYoLw7Q.js +0 -1
  100. package/dist/web/assets/treemap-KZPCXAKY-CBVPi4NV.js +0 -1
  101. package/dist/web/assets/x-OGGXhtlb.js +0 -1
  102. /package/dist/web/assets/{arrow-up-Dtrfv490.js → arrow-up-Rcw6_KKu.js} +0 -0
  103. /package/dist/web/assets/{dist-D7KGU7Vl.js → dist-CaKCIxem.js} +0 -0
  104. /package/dist/web/assets/{dist-CGvx1c8C.js → dist-DGSkE2Ml.js} +0 -0
  105. /package/dist/web/assets/{katex-BFE6i_OH.js → katex-BuytEdO1.js} +0 -0
  106. /package/dist/web/assets/{lib-D_kRA9p6.js → lib-DQHnkzGy.js} +0 -0
  107. /package/dist/web/assets/{refresh-cw-CSFrDtiu.js → refresh-cw-LlbZDJpO.js} +0 -0
  108. /package/dist/web/assets/{scroll-area-BEllam7_.js → scroll-area-7H-Q_k8c.js} +0 -0
  109. /package/dist/web/assets/{sparkles-B0mRBy_j.js → sparkles-fWUT5Vzq.js} +0 -0
  110. /package/dist/web/assets/{table-Dq575bPF.js → table-tf7pRkME.js} +0 -0
  111. /package/dist/web/assets/{text-wrap-Cn6BNQfq.js → text-wrap-BV-R4Vvy.js} +0 -0
  112. /package/dist/web/assets/{use-blob-url-Hn6n1730.js → use-blob-url-e9uTXjv5.js} +0 -0
  113. /package/dist/web/assets/{vendor-xterm-u3AZMvTx.js → vendor-xterm-CU2c3f0A.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-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};
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-BAPR3hYQ.js";import{t as r}from"./use-blob-url-e9uTXjv5.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(`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`}]]),n=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`}]]),r=e(`plus`,[[`path`,{d:`M5 12h14`,key:`1ays0h`}],[`path`,{d:`M12 5v14`,key:`s699le`}]]),i=e(`trash-2`,[[`path`,{d:`M10 11v6`,key:`nco0om`}],[`path`,{d:`M14 11v6`,key:`outv1u`}],[`path`,{d:`M19 6v14a2 2 0 0 1-2 2H7a2 2 0 0 1-2-2V6`,key:`miytrc`}],[`path`,{d:`M3 6h18`,key:`d0wm0j`}],[`path`,{d:`M8 6V4a2 2 0 0 1 2-2h4a2 2 0 0 1 2 2v2`,key:`e791ji`}]]),a=e(`x`,[[`path`,{d:`M18 6 6 18`,key:`1bl5f8`}],[`path`,{d:`m6 6 12 12`,key:`d8bk6v`}]]);export{t as a,n as i,i as n,r,a as t};
@@ -39,29 +39,28 @@
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-CoMWx5VS.js"></script>
42
+ <script type="module" crossorigin src="/assets/index-BAPR3hYQ.js"></script>
43
43
  <link rel="modulepreload" crossorigin href="/assets/rolldown-runtime-FhOqtrmT.js">
44
- <link rel="modulepreload" crossorigin href="/assets/vendor-mermaid-CMiurk2b.js">
44
+ <link rel="modulepreload" crossorigin href="/assets/vendor-mermaid-CCmA_6Y0.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
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-OGGXhtlb.js">
50
- <link rel="modulepreload" crossorigin href="/assets/input-DYWhyaze.js">
49
+ <link rel="modulepreload" crossorigin href="/assets/x-CG-_0yIW.js">
50
+ <link rel="modulepreload" crossorigin href="/assets/input-ozrR2DAV.js">
51
51
  <link rel="modulepreload" crossorigin href="/assets/react-GqWghJ-L.js">
52
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
- <link rel="modulepreload" crossorigin href="/assets/dist-D7KGU7Vl.js">
56
- <link rel="modulepreload" crossorigin href="/assets/refresh-cw-CSFrDtiu.js">
57
- <link rel="modulepreload" crossorigin href="/assets/trash-2-CJYoLw7Q.js">
53
+ <link rel="modulepreload" crossorigin href="/assets/settings-store-B-OmHo3J.js">
54
+ <link rel="modulepreload" crossorigin href="/assets/scroll-area-7H-Q_k8c.js">
55
+ <link rel="modulepreload" crossorigin href="/assets/dist-CaKCIxem.js">
56
+ <link rel="modulepreload" crossorigin href="/assets/refresh-cw-LlbZDJpO.js">
58
57
  <link rel="modulepreload" crossorigin href="/assets/api-settings-D0_eiIYv.js">
59
- <link rel="modulepreload" crossorigin href="/assets/ai-settings-section-CLNBWLS4.js">
58
+ <link rel="modulepreload" crossorigin href="/assets/ai-settings-section-ysK_Eixc.js">
60
59
  <link rel="modulepreload" crossorigin href="/assets/database-DOWH9-Vv.js">
61
60
  <link rel="modulepreload" crossorigin href="/assets/chevron-right-DnHIvvcy.js">
62
61
  <link rel="modulepreload" crossorigin href="/assets/file-store-BrbCNyLm.js">
63
62
  <link rel="modulepreload" crossorigin href="/assets/tab-store-0rGchMXr.js">
64
- <link rel="stylesheet" crossorigin href="/assets/index-Dzb3OtrX.css">
63
+ <link rel="stylesheet" crossorigin href="/assets/index-COOnLKGB.css">
65
64
  <link rel="manifest" href="/manifest.webmanifest"><script id="vite-plugin-pwa:register-sw" src="/registerSW.js"></script></head>
66
65
  <body class="bg-[#0f1419] text-[#e5e7eb] font-sans antialiased">
67
66
  <div id="portal" style="position: fixed; left: 0; top: 0; z-index: 9999;" /></div>
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":"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||`/`)}))});
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":"6f6ecec6b82555c721c9eb1c2c52446a","url":"index.html"},{"revision":"a0fb34fc84eb148d51812cd62669f20d","url":"icon-512.svg"},{"revision":null,"url":"assets/audio-preview-dOvnFQN8.js"},{"revision":null,"url":"assets/KaTeX_Fraktur-Bold-CL6g_b3V.woff2"},{"revision":null,"url":"assets/KaTeX_AMS-Regular-BQhdFMY1.woff2"},{"revision":null,"url":"assets/image-preview-CzwOU5op.js"},{"revision":null,"url":"assets/diff-viewer-DjFe6idy.js"},{"revision":null,"url":"assets/index-BAPR3hYQ.js"},{"revision":null,"url":"assets/use-blob-url-e9uTXjv5.js"},{"revision":null,"url":"assets/vendor-xterm-CU2c3f0A.js"},{"revision":null,"url":"assets/settings-store-B-OmHo3J.js"},{"revision":null,"url":"assets/KaTeX_Main-Regular-B22Nviop.woff2"},{"revision":null,"url":"assets/refresh-cw-LlbZDJpO.js"},{"revision":null,"url":"assets/database-viewer-GNKYeCIc.js"},{"revision":null,"url":"assets/conflict-editor-XMpuwtUv.js"},{"revision":null,"url":"assets/react-GqWghJ-L.js"},{"revision":null,"url":"assets/file-exclamation-point-Baz81y5z.js"},{"revision":null,"url":"assets/video-preview-BwDNFl7v.js"},{"revision":null,"url":"assets/github.min-D2BCvnWf.css"},{"revision":null,"url":"assets/database-DOWH9-Vv.js"},{"revision":null,"url":"assets/katex-BuytEdO1.js"},{"revision":null,"url":"assets/KaTeX_Fraktur-Regular-CTYiF6lA.woff2"},{"revision":null,"url":"assets/glide-data-grid-nthEL3fk.css"},{"revision":null,"url":"assets/chat-tab-C6NVtLx3.js"},{"revision":null,"url":"assets/sql-query-editor-7pD60nKZ.js"},{"revision":null,"url":"assets/pie-UPGHQEXC-cjpNfVG5.js"},{"revision":null,"url":"assets/KaTeX_Main-BoldItalic-DxDJ3AOS.woff2"},{"revision":null,"url":"assets/packet-RMMSAZCW-DECxYTOi.js"},{"revision":null,"url":"assets/api-settings-D0_eiIYv.js"},{"revision":null,"url":"assets/vendor-markdown-0Mxgxy0L.js"},{"revision":null,"url":"assets/glide-data-grid-uLRTmkwH.js"},{"revision":null,"url":"assets/ai-settings-section-ysK_Eixc.js"},{"revision":null,"url":"assets/markdown-renderer-BD5P19YN.js"},{"revision":null,"url":"assets/api-client-Dvzcc_EO.js"},{"revision":null,"url":"assets/KaTeX_Main-Italic-NWA7e6Wa.woff2"},{"revision":null,"url":"assets/data-grid-overlay-editor-BjjuE4-G.js"},{"revision":null,"url":"assets/csv-preview-7TsYBQI6.js"},{"revision":null,"url":"assets/tab-store-0rGchMXr.js"},{"revision":null,"url":"assets/KaTeX_Typewriter-Regular-CO6r4hn1.woff2"},{"revision":null,"url":"assets/terminal-tab-6T5e8Nar.js"},{"revision":null,"url":"assets/code-editor-3e9UAnzv.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/x-CG-_0yIW.js"},{"revision":null,"url":"assets/csv-parser-Dly5nqE1.js"},{"revision":null,"url":"assets/rolldown-runtime-FhOqtrmT.js"},{"revision":null,"url":"assets/extension-webview-hgbO93RZ.js"},{"revision":null,"url":"assets/data-grid-types-BTQHYBUh.js"},{"revision":null,"url":"assets/sqlite-viewer-DLNJ_IGM.js"},{"revision":null,"url":"assets/dist-DGSkE2Ml.js"},{"revision":null,"url":"assets/keybindings-store-D9GV2h8K.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/KaTeX_SansSerif-Bold-D1sUS0GD.woff2"},{"revision":null,"url":"assets/KaTeX_Script-Regular-D3wIWfF6.woff2"},{"revision":null,"url":"assets/text-wrap-BV-R4Vvy.js"},{"revision":null,"url":"assets/arrow-up-Rcw6_KKu.js"},{"revision":null,"url":"assets/vendor-mermaid-CCmA_6Y0.js"},{"revision":null,"url":"assets/file-store-BrbCNyLm.js"},{"revision":null,"url":"assets/sparkles-fWUT5Vzq.js"},{"revision":null,"url":"assets/dist-0kPgRaVx.js"},{"revision":null,"url":"assets/index-COOnLKGB.css"},{"revision":null,"url":"assets/postgres-viewer-D51L9fxD.js"},{"revision":null,"url":"assets/treemap-KZPCXAKY-DRyb1eiw.js"},{"revision":null,"url":"assets/utils-CTg5uAYR.js"},{"revision":null,"url":"assets/KaTeX_Main-Bold-Cx986IdX.woff2"},{"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/settings-tab-DdbYEmAC.js"},{"revision":null,"url":"assets/esm-zjerHxpO.js"},{"revision":null,"url":"assets/use-monaco-theme-DgzxiZS5.js"},{"revision":null,"url":"assets/scroll-area-7H-Q_k8c.js"},{"revision":null,"url":"assets/architecture-PBZL5I3N-By4Nv3Gj.js"},{"revision":null,"url":"assets/createLucideIcon-BjHrJDVb.js"},{"revision":null,"url":"assets/radar-KQ55EAFF-Dnpi068b.js"},{"revision":null,"url":"assets/pdf-preview-DRbBRYIF.js"},{"revision":null,"url":"assets/dist-CaKCIxem.js"},{"revision":null,"url":"assets/chevron-right-DnHIvvcy.js"},{"revision":null,"url":"assets/KaTeX_Size4-Regular-Dl5lxZxV.woff2"},{"revision":null,"url":"assets/port-forwarding-tab-BSFhNv-A.js"},{"revision":null,"url":"assets/KaTeX_Math-BoldItalic-CZnvNsCZ.woff2"},{"revision":null,"url":"assets/table-tf7pRkME.js"},{"revision":null,"url":"assets/gitGraph-HDMCJU4V-BLXEKVf1.js"},{"revision":null,"url":"assets/number-overlay-editor-BoRxunFN.js"},{"revision":null,"url":"assets/vendor-ui-B-89Uj8i.js"},{"revision":null,"url":"assets/input-ozrR2DAV.js"},{"revision":null,"url":"assets/vendor-xterm-BrP-ENHg.css"},{"revision":null,"url":"assets/KaTeX_SansSerif-Italic-C3H0VqGB.woff2"},{"revision":null,"url":"assets/info-3K5VOQVL-CEkPcChg.js"},{"revision":null,"url":"assets/lib-DQHnkzGy.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||`/`)}))});
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@hienlh/ppm",
3
- "version": "0.13.9",
3
+ "version": "0.13.11",
4
4
  "description": "Personal Project Manager — mobile-first web IDE with AI assistance",
5
5
  "author": "hienlh",
6
6
  "license": "MIT",
package/src/index.ts CHANGED
File without changes
@@ -288,6 +288,9 @@ export function ChatTab({ metadata, tabId }: ChatTabProps) {
288
288
  setSlashFilter("");
289
289
  }, []);
290
290
 
291
+ // Stable callback: clear external paths once consumed (avoids inline lambda breaking MessageInput memo)
292
+ const handleExternalPathsConsumed = useCallback(() => setExternalPaths(null), []);
293
+
291
294
  // --- Disambiguation picker handler (OS drag resolve with multiple matches) ---
292
295
  const handleDisambiguate = useCallback((matches: FileNode[]) => {
293
296
  setDisambiguateItems(matches);
@@ -470,7 +473,7 @@ export function ChatTab({ metadata, tabId }: ChatTabProps) {
470
473
  fileSelected={fileSelected}
471
474
  externalFiles={externalFiles}
472
475
  externalPaths={externalPaths}
473
- onExternalPathsConsumed={() => setExternalPaths(null)}
476
+ onExternalPathsConsumed={handleExternalPathsConsumed}
474
477
  onDisambiguate={handleDisambiguate}
475
478
  permissionMode={permissionMode}
476
479
  onModeChange={setPermissionMode}
@@ -107,9 +107,9 @@ export const MessageInput = memo(function MessageInput({
107
107
  typeof CSS === "undefined" || !CSS.supports("field-sizing", "content"),
108
108
  );
109
109
 
110
- // File index from store replaces /files/tree?depth=5 fetch
111
- const fileIndex = useFileStore((s) => s.fileIndex);
112
- const indexStatus = useFileStore((s) => s.indexStatus);
110
+ // File index: subscribe imperatively to avoid re-renders on every file store update.
111
+ // The component only needs fileIndex for the effect below (populating fileItemsRef),
112
+ // not for rendering — so we use Zustand's subscribe() instead of selector hooks.
113
113
 
114
114
  /** Write value to both textareas + ref + update hasText state */
115
115
  const writeTextareas = useCallback((newValue: string) => {
@@ -208,18 +208,32 @@ export const MessageInput = memo(function MessageInput({
208
208
  return () => window.removeEventListener("ppm:slash-items-refresh", handler);
209
209
  }, [fetchSlashItems]);
210
210
 
211
- // Sync file picker items from store index — no network call needed
211
+ // Sync file picker items from store index — subscribe imperatively to avoid re-renders.
212
+ // Reads fileIndex on mount + whenever fileIndex/indexStatus changes in the store.
212
213
  useEffect(() => {
213
- if (!projectName) {
214
- fileItemsRef.current = [];
215
- onFileItemsLoaded?.([]);
216
- return;
217
- }
218
- // Convert FileEntry[] to FileNode[] — type field is now present on FileEntry
219
- const nodes: FileNode[] = fileIndex.map((e) => ({ name: e.name, path: e.path, type: e.type }));
220
- fileItemsRef.current = nodes;
221
- onFileItemsLoaded?.(nodes);
222
- }, [projectName, fileIndex, indexStatus]); // eslint-disable-line react-hooks/exhaustive-deps
214
+ const syncFromStore = () => {
215
+ if (!projectName) {
216
+ fileItemsRef.current = [];
217
+ onFileItemsLoaded?.([]);
218
+ return;
219
+ }
220
+ const { fileIndex } = useFileStore.getState();
221
+ const nodes: FileNode[] = fileIndex.map((e) => ({ name: e.name, path: e.path, type: e.type }));
222
+ fileItemsRef.current = nodes;
223
+ onFileItemsLoaded?.(nodes);
224
+ };
225
+ syncFromStore();
226
+ // Track previous values to only sync on relevant changes
227
+ let prevIdx = useFileStore.getState().fileIndex;
228
+ let prevStatus = useFileStore.getState().indexStatus;
229
+ return useFileStore.subscribe((state) => {
230
+ if (state.fileIndex !== prevIdx || state.indexStatus !== prevStatus) {
231
+ prevIdx = state.fileIndex;
232
+ prevStatus = state.indexStatus;
233
+ syncFromStore();
234
+ }
235
+ });
236
+ }, [projectName]); // eslint-disable-line react-hooks/exhaustive-deps
223
237
 
224
238
  // Handle parent selecting a slash item
225
239
  useEffect(() => {
@@ -4,7 +4,7 @@ import { api } from "@/lib/api-client";
4
4
  import { useDatabase, type DbColumnInfo } from "./use-database";
5
5
  import { SqlQueryEditor } from "./sql-query-editor";
6
6
  import { ExportButton } from "./export-button";
7
- import { DataGrid } from "./data-grid";
7
+ import { GlideDataGrid } from "./glide-data-grid";
8
8
  import type { SchemaInfo } from "./sql-completion-provider";
9
9
 
10
10
  /** Parse WHERE "col" ILIKE '%val%' clauses from SQL */
@@ -141,6 +141,10 @@ export function DatabaseViewer({ metadata }: Props) {
141
141
  setShowingQueryResult(false);
142
142
  db.toggleSort(col);
143
143
  }, [db.toggleSort]);
144
+ const handleClearSort = useCallback(() => {
145
+ setShowingQueryResult(false);
146
+ db.clearSort();
147
+ }, [db.clearSort]);
144
148
  const handlePageChange = useCallback((p: number) => {
145
149
  setShowingQueryResult(false);
146
150
  db.setPage(p);
@@ -178,7 +182,8 @@ export function DatabaseViewer({ metadata }: Props) {
178
182
  <div className="shrink-0 border-b border-border" style={{ height: queryHeight }}>
179
183
  <SqlQueryEditor
180
184
  onExecute={handleExecuteQuery} loading={db.queryLoading}
181
- defaultValue={defaultQuery} schemaInfo={schemaInfo} />
185
+ defaultValue={defaultQuery} schemaInfo={schemaInfo}
186
+ cacheKey={connectionId ? String(connectionId) : undefined} />
182
187
  </div>
183
188
 
184
189
  {/* Resize handle */}
@@ -189,10 +194,14 @@ export function DatabaseViewer({ metadata }: Props) {
189
194
 
190
195
  {/* Bottom panel: table data OR query results */}
191
196
  <div className="flex-1 overflow-hidden">
192
- {showTableGrid && (
193
- <DataGrid tableData={db.tableData} schema={db.schema} loading={db.loading}
194
- page={db.page} onPageChange={handlePageChange} onCellUpdate={db.updateCell} onRowDelete={db.deleteRow}
195
- orderBy={db.orderBy} orderDir={db.orderDir} onToggleSort={handleToggleSort}
197
+ {showTableGrid && db.tableData && (
198
+ <GlideDataGrid
199
+ columns={db.tableData.columns} rows={db.tableData.rows}
200
+ total={db.tableData.total} limit={db.tableData.limit}
201
+ schema={db.schema} loading={db.loading}
202
+ page={db.page} onPageChange={handlePageChange}
203
+ onCellUpdate={db.updateCell} onRowDelete={db.deleteRow}
204
+ orderBy={db.orderBy} orderDir={db.orderDir} onToggleSort={handleToggleSort} onClearSort={handleClearSort}
196
205
  onBulkDelete={db.bulkDelete} onInsertRow={db.insertRow}
197
206
  connectionId={connectionId} selectedTable={db.selectedTable} selectedSchema={db.selectedSchema}
198
207
  connectionName={connectionName} columnFilters={columnFilters} onColumnFilter={handleColumnFilter} />
@@ -244,8 +253,10 @@ function QueryResultPanel({ result, error, loading, schema, connectionName }: {
244
253
 
245
254
  {queryTableData && (
246
255
  <div className="flex-1 overflow-hidden">
247
- <DataGrid
248
- tableData={queryTableData} schema={querySchema} loading={!!loading}
256
+ <GlideDataGrid
257
+ columns={queryTableData.columns} rows={queryTableData.rows}
258
+ total={queryTableData.total} limit={queryTableData.limit}
259
+ schema={querySchema} loading={!!loading}
249
260
  page={1} onPageChange={NOOP} onCellUpdate={NOOP}
250
261
  orderBy={null} orderDir="ASC" onToggleSort={NOOP}
251
262
  connectionName={connectionName}
@@ -1,4 +1,5 @@
1
- import { useState, useRef, useEffect } from "react";
1
+ import { useState, useRef, useEffect, useCallback } from "react";
2
+ import { createPortal } from "react-dom";
2
3
  import { Download } from "lucide-react";
3
4
  import { serializeCsv } from "@/lib/csv-parser";
4
5
 
@@ -23,18 +24,22 @@ function downloadFile(name: string, content: string, mimeType: string) {
23
24
  export function ExportButton({ columns, rows, filename = "export", exportAllUrl }: ExportButtonProps) {
24
25
  const [open, setOpen] = useState(false);
25
26
  const [exporting, setExporting] = useState(false);
26
- const ref = useRef<HTMLDivElement>(null);
27
+ const btnRef = useRef<HTMLButtonElement>(null);
28
+ const dropdownRef = useRef<HTMLDivElement>(null);
27
29
 
28
30
  // Close dropdown on outside click
29
31
  useEffect(() => {
30
32
  if (!open) return;
31
33
  const handler = (e: MouseEvent) => {
32
- if (ref.current && !ref.current.contains(e.target as Node)) setOpen(false);
34
+ if (dropdownRef.current && !dropdownRef.current.contains(e.target as Node) &&
35
+ btnRef.current && !btnRef.current.contains(e.target as Node)) setOpen(false);
33
36
  };
34
37
  document.addEventListener("mousedown", handler);
35
38
  return () => document.removeEventListener("mousedown", handler);
36
39
  }, [open]);
37
40
 
41
+ const toggle = useCallback(() => setOpen((v) => !v), []);
42
+
38
43
  const exportPageCsv = () => {
39
44
  const csvRows = rows.map((r) => columns.map((c) => String(r[c] ?? "")));
40
45
  const csv = serializeCsv(columns, csvRows);
@@ -48,6 +53,13 @@ export function ExportButton({ columns, rows, filename = "export", exportAllUrl
48
53
  setOpen(false);
49
54
  };
50
55
 
56
+ const copyToClipboard = async () => {
57
+ const header = columns.join("\t");
58
+ const body = rows.map((r) => columns.map((c) => String(r[c] ?? "")).join("\t")).join("\n");
59
+ await navigator.clipboard.writeText(header + "\n" + body);
60
+ setOpen(false);
61
+ };
62
+
51
63
  const exportAll = async (format: "csv" | "json") => {
52
64
  if (!exportAllUrl) return;
53
65
  setExporting(true);
@@ -63,38 +75,46 @@ export function ExportButton({ columns, rows, filename = "export", exportAllUrl
63
75
 
64
76
  if (columns.length === 0 || rows.length === 0) return null;
65
77
 
78
+ // Compute dropdown position from button
79
+ const rect = btnRef.current?.getBoundingClientRect();
80
+ const portal = document.getElementById("portal");
81
+
66
82
  return (
67
- <div className="relative" ref={ref}>
68
- <button
69
- type="button"
70
- onClick={() => setOpen((v) => !v)}
71
- className="p-1 rounded text-muted-foreground hover:text-foreground transition-colors"
72
- title="Export"
73
- >
83
+ <>
84
+ <button ref={btnRef} type="button" onClick={toggle}
85
+ className="p-1 rounded text-muted-foreground hover:text-foreground transition-colors" title="Export">
74
86
  <Download className="size-3.5" />
75
87
  </button>
76
88
 
77
- {open && (
78
- <div className="absolute right-0 top-full mt-1 z-50 bg-popover border border-border rounded-md shadow-md py-1 min-w-[160px] text-xs">
79
- <button onClick={exportPageCsv} className="w-full text-left px-3 py-1.5 hover:bg-muted transition-colors">
89
+ {open && portal && rect && createPortal(
90
+ <div ref={dropdownRef}
91
+ style={{ position: "fixed", left: Math.min(rect.left, window.innerWidth - 170), top: rect.bottom + 4, zIndex: 10000 }}
92
+ className="bg-popover border border-border rounded-md shadow-md py-1 min-w-[160px] text-xs">
93
+ <button onClick={copyToClipboard} className="w-full text-left px-3 py-1.5 hover:bg-muted transition-colors text-foreground">
94
+ Copy to Clipboard (TSV)
95
+ </button>
96
+ <button onClick={exportPageCsv} className="w-full text-left px-3 py-1.5 hover:bg-muted transition-colors text-foreground">
80
97
  Export Page (CSV)
81
98
  </button>
82
- <button onClick={exportPageJson} className="w-full text-left px-3 py-1.5 hover:bg-muted transition-colors">
99
+ <button onClick={exportPageJson} className="w-full text-left px-3 py-1.5 hover:bg-muted transition-colors text-foreground">
83
100
  Export Page (JSON)
84
101
  </button>
85
102
  {exportAllUrl && (
86
103
  <>
87
104
  <div className="border-t border-border my-1" />
88
- <button onClick={() => exportAll("csv")} disabled={exporting} className="w-full text-left px-3 py-1.5 hover:bg-muted transition-colors disabled:opacity-50">
105
+ <button onClick={() => exportAll("csv")} disabled={exporting}
106
+ className="w-full text-left px-3 py-1.5 hover:bg-muted transition-colors disabled:opacity-50 text-foreground">
89
107
  {exporting ? "Exporting…" : "Export All (CSV)"}
90
108
  </button>
91
- <button onClick={() => exportAll("json")} disabled={exporting} className="w-full text-left px-3 py-1.5 hover:bg-muted transition-colors disabled:opacity-50">
109
+ <button onClick={() => exportAll("json")} disabled={exporting}
110
+ className="w-full text-left px-3 py-1.5 hover:bg-muted transition-colors disabled:opacity-50 text-foreground">
92
111
  {exporting ? "Exporting…" : "Export All (JSON)"}
93
112
  </button>
94
113
  </>
95
114
  )}
96
- </div>
115
+ </div>,
116
+ portal,
97
117
  )}
98
- </div>
118
+ </>
99
119
  );
100
120
  }
@@ -0,0 +1,81 @@
1
+ import { useState, useEffect, useRef, useCallback } from "react";
2
+ import { createPortal } from "react-dom";
3
+
4
+ interface ColumnSearchProps {
5
+ columns: string[];
6
+ onSelect: (colName: string) => void;
7
+ onClose: () => void;
8
+ anchorRect: { x: number; y: number };
9
+ }
10
+
11
+ /** Portal dropdown for searching and jumping to a column in the grid */
12
+ export function GlideColumnSearch({ columns, onSelect, onClose, anchorRect }: ColumnSearchProps) {
13
+ const [search, setSearch] = useState("");
14
+ const [activeIdx, setActiveIdx] = useState(0);
15
+ const ref = useRef<HTMLDivElement>(null);
16
+ const listRef = useRef<HTMLDivElement>(null);
17
+
18
+ const filtered = search
19
+ ? columns.filter((c) => c.toLowerCase().includes(search.toLowerCase()))
20
+ : columns;
21
+
22
+ // Reset active index when filter changes
23
+ useEffect(() => { setActiveIdx(0); }, [search]);
24
+
25
+ // Scroll active item into view
26
+ useEffect(() => {
27
+ const list = listRef.current;
28
+ if (!list) return;
29
+ const active = list.children[activeIdx] as HTMLElement | undefined;
30
+ active?.scrollIntoView({ block: "nearest" });
31
+ }, [activeIdx]);
32
+
33
+ // Close on outside click
34
+ useEffect(() => {
35
+ const handler = (e: MouseEvent) => {
36
+ if (ref.current && !ref.current.contains(e.target as Node)) onClose();
37
+ };
38
+ document.addEventListener("mousedown", handler);
39
+ return () => document.removeEventListener("mousedown", handler);
40
+ }, [onClose]);
41
+
42
+ const handleKeyDown = useCallback((e: React.KeyboardEvent) => {
43
+ if (e.key === "Escape") { onClose(); return; }
44
+ if (e.key === "ArrowDown") { e.preventDefault(); setActiveIdx((i) => Math.min(i + 1, filtered.length - 1)); return; }
45
+ if (e.key === "ArrowUp") { e.preventDefault(); setActiveIdx((i) => Math.max(i - 1, 0)); return; }
46
+ if (e.key === "Enter") {
47
+ e.preventDefault();
48
+ const col = filtered[activeIdx];
49
+ if (col) { onSelect(col); onClose(); }
50
+ }
51
+ }, [filtered, activeIdx, onSelect, onClose]);
52
+
53
+ const portal = document.getElementById("portal");
54
+ if (!portal) return null;
55
+
56
+ return createPortal(
57
+ <div ref={ref} style={{ position: "fixed", left: Math.min(anchorRect.x, window.innerWidth - 216), top: Math.min(anchorRect.y, window.innerHeight - 308), zIndex: 10000 }}
58
+ className="w-[200px] max-h-[300px] bg-popover border border-border rounded-md shadow-lg text-xs overflow-hidden flex flex-col">
59
+ <div className="px-2 py-1.5 border-b border-border">
60
+ <input autoFocus value={search} onChange={(e) => setSearch(e.target.value)}
61
+ onKeyDown={handleKeyDown}
62
+ placeholder="Search columns…"
63
+ className="w-full bg-transparent outline-none text-foreground placeholder:text-muted-foreground text-xs" />
64
+ </div>
65
+ <div ref={listRef} className="overflow-y-auto py-1">
66
+ {filtered.map((col, i) => (
67
+ <button key={col} type="button"
68
+ onClick={() => { onSelect(col); onClose(); }}
69
+ onMouseEnter={() => setActiveIdx(i)}
70
+ className={`w-full text-left px-3 py-1 truncate text-foreground ${i === activeIdx ? "bg-muted" : "hover:bg-muted"}`}>
71
+ {col}
72
+ </button>
73
+ ))}
74
+ {filtered.length === 0 && (
75
+ <div className="px-3 py-2 text-muted-foreground">No columns found</div>
76
+ )}
77
+ </div>
78
+ </div>,
79
+ portal,
80
+ );
81
+ }
@@ -0,0 +1,95 @@
1
+ import { useState, useEffect, useRef } from "react";
2
+ import { createPortal } from "react-dom";
3
+ import { Eye, Pin, PinOff, Trash2, ExternalLink } from "lucide-react";
4
+
5
+ interface ContextMenuProps {
6
+ position: { x: number; y: number };
7
+ isPinned: boolean;
8
+ onViewRow: () => void;
9
+ onViewCell?: () => void;
10
+ onPinRow: () => void;
11
+ onDeleteRow: () => void;
12
+ /** FK navigation: open referenced table filtered by this cell's value */
13
+ onOpenFkTable?: () => void;
14
+ /** Label for FK menu item, e.g. "Open users.id" */
15
+ fkLabel?: string;
16
+ onClose: () => void;
17
+ }
18
+
19
+ /**
20
+ * Right-click / long-press context menu for grid rows.
21
+ * Rendered via portal. Includes View JSON, Pin/Unpin, Delete with confirm.
22
+ */
23
+ export function GlideContextMenu({
24
+ position, isPinned, onViewRow, onViewCell, onPinRow, onDeleteRow, onOpenFkTable, fkLabel, onClose,
25
+ }: ContextMenuProps) {
26
+ const [confirmDelete, setConfirmDelete] = useState(false);
27
+ const ref = useRef<HTMLDivElement>(null);
28
+
29
+ // Close on outside click
30
+ useEffect(() => {
31
+ const handler = (e: MouseEvent) => {
32
+ if (ref.current && !ref.current.contains(e.target as Node)) onClose();
33
+ };
34
+ document.addEventListener("mousedown", handler);
35
+ return () => document.removeEventListener("mousedown", handler);
36
+ }, [onClose]);
37
+
38
+ // Close on Escape
39
+ useEffect(() => {
40
+ const handler = (e: KeyboardEvent) => { if (e.key === "Escape") onClose(); };
41
+ document.addEventListener("keydown", handler);
42
+ return () => document.removeEventListener("keydown", handler);
43
+ }, [onClose]);
44
+
45
+ // Clamp to viewport
46
+ const menuWidth = 180;
47
+ const menuHeight = 130;
48
+ const left = Math.min(position.x, window.innerWidth - menuWidth - 8);
49
+ const top = Math.min(position.y, window.innerHeight - menuHeight - 8);
50
+
51
+ const portal = document.getElementById("portal");
52
+ if (!portal) return null;
53
+
54
+ return createPortal(
55
+ <div ref={ref} style={{ position: "fixed", left, top, zIndex: 10000 }}
56
+ className="w-[180px] bg-popover border border-border rounded-md shadow-lg text-xs overflow-hidden py-1">
57
+ <button type="button" onClick={() => { onViewRow(); onClose(); }}
58
+ className="w-full text-left px-3 py-1.5 hover:bg-muted flex items-center gap-2 text-foreground">
59
+ <Eye className="size-3" /> View as JSON
60
+ </button>
61
+ {onViewCell && (
62
+ <button type="button" onClick={() => { onViewCell(); onClose(); }}
63
+ className="w-full text-left px-3 py-1.5 hover:bg-muted flex items-center gap-2 text-foreground">
64
+ <Eye className="size-3" /> View Cell
65
+ </button>
66
+ )}
67
+ {onOpenFkTable && (
68
+ <button type="button" onClick={() => { onOpenFkTable(); onClose(); }}
69
+ className="w-full text-left px-3 py-1.5 hover:bg-muted flex items-center gap-2 text-blue-400">
70
+ <ExternalLink className="size-3" /> {fkLabel ?? "Open Referenced Table"}
71
+ </button>
72
+ )}
73
+ <button type="button" onClick={() => { onPinRow(); onClose(); }}
74
+ className="w-full text-left px-3 py-1.5 hover:bg-muted flex items-center gap-2 text-foreground">
75
+ {isPinned ? <PinOff className="size-3" /> : <Pin className="size-3" />}
76
+ {isPinned ? "Unpin Row" : "Pin Row"}
77
+ </button>
78
+ <div className="border-t border-border my-0.5" />
79
+ {confirmDelete ? (
80
+ <div className="px-3 py-1.5 flex items-center gap-2">
81
+ <button type="button" onClick={() => { onDeleteRow(); onClose(); }}
82
+ className="text-destructive font-medium hover:underline">Delete?</button>
83
+ <button type="button" onClick={() => setConfirmDelete(false)}
84
+ className="text-muted-foreground hover:underline">Cancel</button>
85
+ </div>
86
+ ) : (
87
+ <button type="button" onClick={() => setConfirmDelete(true)}
88
+ className="w-full text-left px-3 py-1.5 hover:bg-muted flex items-center gap-2 text-destructive">
89
+ <Trash2 className="size-3" /> Delete Row
90
+ </button>
91
+ )}
92
+ </div>,
93
+ portal,
94
+ );
95
+ }