@hienlh/ppm 0.12.12 → 0.13.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (119) hide show
  1. package/CHANGELOG.md +31 -1
  2. package/README.md +11 -0
  3. package/assets/skills/ppm/SKILL.md +74 -0
  4. package/assets/skills/ppm/references/cli-reference.md +728 -0
  5. package/assets/skills/ppm/references/common-tasks.md +139 -0
  6. package/assets/skills/ppm/references/http-api.md +204 -0
  7. package/dist/web/assets/ai-settings-section-QE6nBNgN.js +1 -0
  8. package/dist/web/assets/{api-settings-C3T95dWg.js → api-settings-DAk7D-NP.js} +1 -1
  9. package/dist/web/assets/architecture-PBZL5I3N-DvZbltvY.js +1 -0
  10. package/dist/web/assets/{audio-preview-BkbgGtDH.js → audio-preview--hRMnXRZ.js} +1 -1
  11. package/dist/web/assets/chat-tab-4kL3DNxf.js +12 -0
  12. package/dist/web/assets/{code-editor-BtspASkW.js → code-editor-Caq5_BaF.js} +4 -4
  13. package/dist/web/assets/{conflict-editor-Dgsu6fmj.js → conflict-editor-Dlo25nmt.js} +1 -1
  14. package/dist/web/assets/{csv-preview-DcWCjQkZ.js → csv-preview-HMSavgBb.js} +1 -1
  15. package/dist/web/assets/{database-viewer-C85RxdMV.js → database-viewer-DcBl6OkV.js} +2 -2
  16. package/dist/web/assets/{diff-viewer-2pPy97Tl.js → diff-viewer-CCzPq1o-.js} +1 -1
  17. package/dist/web/assets/{esm-_CLpyLJ_.js → esm-K1XIK4vc.js} +1 -1
  18. package/dist/web/assets/{extension-store-BZDZ9QRc.js → extension-store-3yZYn07W.js} +1 -1
  19. package/dist/web/assets/{extension-webview-U1lMYZ0p.js → extension-webview-D7bGVSEd.js} +1 -1
  20. package/dist/web/assets/{file-store-4BpOJthN.js → file-store-BrbCNyLm.js} +1 -1
  21. package/dist/web/assets/gitGraph-HDMCJU4V-BxhdxFgj.js +1 -0
  22. package/dist/web/assets/{image-preview-BcT1SbY2.js → image-preview-CfkqnhXJ.js} +1 -1
  23. package/dist/web/assets/index-BGFG66Gh.js +27 -0
  24. package/dist/web/assets/index-Bce0weeW.css +2 -0
  25. package/dist/web/assets/info-3K5VOQVL-BwAZ2zd8.js +1 -0
  26. package/dist/web/assets/{input-2eDVjcRZ.js → input-Dk49gO8E.js} +1 -1
  27. package/dist/web/assets/{keybindings-store-BOG1yviy.js → keybindings-store-B-zET-0o.js} +1 -1
  28. package/dist/web/assets/keybindings-store-DaBV6qhz.js +1 -0
  29. package/dist/web/assets/{markdown-renderer-Dbam_-04.js → markdown-renderer-DyAm7zuA.js} +3 -3
  30. package/dist/web/assets/packet-RMMSAZCW-tx2n5Qry.js +1 -0
  31. package/dist/web/assets/{pdf-preview-BmHVGx32.js → pdf-preview-CZPcuy5c.js} +1 -1
  32. package/dist/web/assets/pie-UPGHQEXC-D6S2MqVT.js +1 -0
  33. package/dist/web/assets/plus-51UQ45rf.js +1 -0
  34. package/dist/web/assets/{port-forwarding-tab-Dkq1upWC.js → port-forwarding-tab-3RNozlZ5.js} +1 -1
  35. package/dist/web/assets/{postgres-viewer-BgBJAJ9q.js → postgres-viewer-CXJv4TXc.js} +3 -3
  36. package/dist/web/assets/radar-KQ55EAFF-BviZcL-b.js +1 -0
  37. package/dist/web/assets/{scroll-area-CdxNNnN-.js → scroll-area-BEllam7_.js} +1 -1
  38. package/dist/web/assets/{settings-store-CMAssqyb.js → settings-store-BLLR7ed8.js} +2 -2
  39. package/dist/web/assets/settings-tab-Cnav4g2u.js +1 -0
  40. package/dist/web/assets/{sql-query-editor-b7zJ8XPp.js → sql-query-editor-CVAnRFbi.js} +1 -1
  41. package/dist/web/assets/{sqlite-viewer-4lLAz1es.js → sqlite-viewer-C8WUEFhA.js} +1 -1
  42. package/dist/web/assets/{tab-store-DNBsLdPn.js → tab-store-B3M9hjho.js} +1 -1
  43. package/dist/web/assets/{terminal-tab-BtnqkN1H.js → terminal-tab-CaEsMxp8.js} +1 -1
  44. package/dist/web/assets/treemap-KZPCXAKY-CM54VdaB.js +1 -0
  45. package/dist/web/assets/{use-blob-url-QX-XajU8.js → use-blob-url-e9uTXjv5.js} +1 -1
  46. package/dist/web/assets/{use-monaco-theme-D68oX3XU.js → use-monaco-theme-BkZDwoVd.js} +1 -1
  47. package/dist/web/assets/{vendor-mermaid-sQS4C_iL.js → vendor-mermaid-Dx86tuVP.js} +2 -2
  48. package/dist/web/assets/{video-preview-CkOKvVLt.js → video-preview-Dfz71RGb.js} +1 -1
  49. package/dist/web/index.html +18 -18
  50. package/dist/web/sw.js +1 -1
  51. package/docs/project-changelog.md +15 -1
  52. package/package.json +3 -3
  53. package/scripts/generate-ppm-skill.ts +23 -0
  54. package/scripts/lib/generate-cli-reference.ts +81 -0
  55. package/scripts/lib/generate-common-tasks.ts +14 -0
  56. package/scripts/lib/generate-http-api.ts +145 -0
  57. package/scripts/lib/generate-skill-md.ts +28 -0
  58. package/scripts/lib/write-output.ts +17 -0
  59. package/src/cli/commands/export-cmd.ts +85 -0
  60. package/src/index.ts +167 -153
  61. package/src/server/index.ts +12 -4
  62. package/src/services/autostart-generator.ts +3 -1
  63. package/src/services/autostart-register.ts +17 -0
  64. package/src/services/sd-notify.ts +27 -0
  65. package/src/services/skill-export/backup-existing.ts +33 -0
  66. package/src/services/skill-export/copy-bundled-skill.ts +36 -0
  67. package/src/services/skill-export/generate-db-schema.ts +66 -0
  68. package/src/services/skill-export/index.ts +6 -0
  69. package/src/services/skill-export/resolve-assets-dir.ts +31 -0
  70. package/src/services/skill-export/resolve-target-dir.ts +17 -0
  71. package/src/services/supervisor.ts +31 -5
  72. package/src/web/components/chat/chat-history-bar.tsx +2 -9
  73. package/src/web/components/chat/chat-history-panel.tsx +2 -9
  74. package/src/web/components/chat/chat-tab.tsx +6 -1
  75. package/src/web/components/chat/chat-welcome.tsx +1 -18
  76. package/src/web/components/chat/message-list.tsx +96 -43
  77. package/src/web/components/layout/draggable-tab.tsx +12 -5
  78. package/src/web/hooks/use-chat.ts +37 -1
  79. package/src/web/hooks/use-notification-badge.ts +7 -7
  80. package/src/web/lib/favicon.ts +37 -15
  81. package/src/web/lib/flatten-expansions.ts +36 -0
  82. package/src/web/lib/format-date.ts +21 -0
  83. package/src/web/styles/globals.css +12 -0
  84. package/templates/skill/SKILL.md.tmpl +74 -0
  85. package/templates/skill/common-tasks.md +139 -0
  86. package/assets/skills/ppm-guide/SKILL.md +0 -61
  87. package/bun.lock +0 -2062
  88. package/bunfig.toml +0 -2
  89. package/dist/web/assets/ai-settings-section-NNWp6nw7.js +0 -1
  90. package/dist/web/assets/architecture-PBZL5I3N-DDuzYaUV.js +0 -1
  91. package/dist/web/assets/chat-tab-BZlP1qjX.js +0 -12
  92. package/dist/web/assets/chevron-up-BWBvMZkp.js +0 -1
  93. package/dist/web/assets/gitGraph-HDMCJU4V-BURAevTc.js +0 -1
  94. package/dist/web/assets/index-BWSRKVZn.js +0 -23
  95. package/dist/web/assets/index-b6tIZImC.css +0 -2
  96. package/dist/web/assets/info-3K5VOQVL-tSD4Fpi3.js +0 -1
  97. package/dist/web/assets/keybindings-store-BvdUoEC7.js +0 -1
  98. package/dist/web/assets/packet-RMMSAZCW-DmDLZUrV.js +0 -1
  99. package/dist/web/assets/pie-UPGHQEXC-w03Pc9ZR.js +0 -1
  100. package/dist/web/assets/pre-compact-button-Dp7Hs49L.js +0 -1
  101. package/dist/web/assets/pre-compact-section-DnM5fGSR.js +0 -1
  102. package/dist/web/assets/radar-KQ55EAFF-C9XQvoey.js +0 -1
  103. package/dist/web/assets/settings-tab-zYWKTq5z.js +0 -1
  104. package/dist/web/assets/treemap-KZPCXAKY-lmftxSky.js +0 -1
  105. package/scripts/generate-ppm-guide.ts +0 -92
  106. package/src/web/components/chat/pre-compact-section.tsx +0 -69
  107. /package/dist/web/assets/{api-client-DIhJ5qVW.js → api-client-Dvzcc_EO.js} +0 -0
  108. /package/dist/web/assets/{csv-parser-B5QW8pZ6.js → csv-parser--2WJNgS7.js} +0 -0
  109. /package/dist/web/assets/{dist-GtkSekuX.js → dist-im4ynINo.js} +0 -0
  110. /package/dist/web/assets/{katex-C3cZrCvP.js → katex-CKoArbIw.js} +0 -0
  111. /package/dist/web/assets/{lib-Bu71-TFS.js → lib-DQHnkzGy.js} +0 -0
  112. /package/dist/web/assets/{react-DMIOAtcX.js → react-GqWghJ-L.js} +0 -0
  113. /package/dist/web/assets/{refresh-cw-BjrAbUJe.js → refresh-cw-LlbZDJpO.js} +0 -0
  114. /package/dist/web/assets/{sql-completion-provider-CULTsCqR.js → sql-completion-provider-C3cq9j99.js} +0 -0
  115. /package/dist/web/assets/{table-tf7pRkME.js → table-Dq575bPF.js} +0 -0
  116. /package/dist/web/assets/{text-wrap-BV-R4Vvy.js → text-wrap-Cn6BNQfq.js} +0 -0
  117. /package/dist/web/assets/{trash-2-DjQOpgUV.js → trash-2-CJYoLw7Q.js} +0 -0
  118. /package/dist/web/assets/{utils-CQux7CsO.js → utils-CTg5uAYR.js} +0 -0
  119. /package/dist/web/assets/{vendor-xterm-K3_Xwigj.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-BwzaQ50n.js";import"./api-client-DIhJ5qVW.js";import{L as n}from"./index-BWSRKVZn.js";import{t as r}from"./use-blob-url-QX-XajU8.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-BwzaQ50n.js";import"./api-client-Dvzcc_EO.js";import{I as n}from"./index-BGFG66Gh.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};
@@ -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-BWSRKVZn.js"></script>
42
+ <script type="module" crossorigin src="/assets/index-BGFG66Gh.js"></script>
43
43
  <link rel="modulepreload" crossorigin href="/assets/rolldown-runtime-FhOqtrmT.js">
44
- <link rel="modulepreload" crossorigin href="/assets/vendor-mermaid-sQS4C_iL.js">
44
+ <link rel="modulepreload" crossorigin href="/assets/vendor-mermaid-Dx86tuVP.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-CQux7CsO.js">
47
+ <link rel="modulepreload" crossorigin href="/assets/utils-CTg5uAYR.js">
48
48
  <link rel="modulepreload" crossorigin href="/assets/createLucideIcon-BjHrJDVb.js">
49
49
  <link rel="modulepreload" crossorigin href="/assets/x-DlFGzN8d.js">
50
- <link rel="modulepreload" crossorigin href="/assets/input-2eDVjcRZ.js">
51
- <link rel="modulepreload" crossorigin href="/assets/react-DMIOAtcX.js">
52
- <link rel="modulepreload" crossorigin href="/assets/api-client-DIhJ5qVW.js">
53
- <link rel="modulepreload" crossorigin href="/assets/settings-store-CMAssqyb.js">
54
- <link rel="modulepreload" crossorigin href="/assets/scroll-area-CdxNNnN-.js">
50
+ <link rel="modulepreload" crossorigin href="/assets/input-Dk49gO8E.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-BLLR7ed8.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/chevron-up-BWBvMZkp.js">
57
- <link rel="modulepreload" crossorigin href="/assets/refresh-cw-BjrAbUJe.js">
58
- <link rel="modulepreload" crossorigin href="/assets/trash-2-DjQOpgUV.js">
59
- <link rel="modulepreload" crossorigin href="/assets/api-settings-C3T95dWg.js">
60
- <link rel="modulepreload" crossorigin href="/assets/ai-settings-section-NNWp6nw7.js">
56
+ <link rel="modulepreload" crossorigin href="/assets/plus-51UQ45rf.js">
57
+ <link rel="modulepreload" crossorigin href="/assets/refresh-cw-LlbZDJpO.js">
58
+ <link rel="modulepreload" crossorigin href="/assets/trash-2-CJYoLw7Q.js">
59
+ <link rel="modulepreload" crossorigin href="/assets/api-settings-DAk7D-NP.js">
60
+ <link rel="modulepreload" crossorigin href="/assets/ai-settings-section-QE6nBNgN.js">
61
61
  <link rel="modulepreload" crossorigin href="/assets/chevron-right-BzAdxJRG.js">
62
62
  <link rel="modulepreload" crossorigin href="/assets/database-D4DIhgi-.js">
63
- <link rel="modulepreload" crossorigin href="/assets/extension-store-BZDZ9QRc.js">
64
- <link rel="modulepreload" crossorigin href="/assets/file-store-4BpOJthN.js">
65
- <link rel="modulepreload" crossorigin href="/assets/keybindings-store-BOG1yviy.js">
66
- <link rel="modulepreload" crossorigin href="/assets/tab-store-DNBsLdPn.js">
67
- <link rel="stylesheet" crossorigin href="/assets/index-b6tIZImC.css">
63
+ <link rel="modulepreload" crossorigin href="/assets/extension-store-3yZYn07W.js">
64
+ <link rel="modulepreload" crossorigin href="/assets/file-store-BrbCNyLm.js">
65
+ <link rel="modulepreload" crossorigin href="/assets/keybindings-store-B-zET-0o.js">
66
+ <link rel="modulepreload" crossorigin href="/assets/tab-store-B3M9hjho.js">
67
+ <link rel="stylesheet" crossorigin href="/assets/index-Bce0weeW.css">
68
68
  <link rel="manifest" href="/manifest.webmanifest"><script id="vite-plugin-pwa:register-sw" src="/registerSW.js"></script></head>
69
69
  <body class="bg-[#0f1419] text-[#e5e7eb] font-sans antialiased">
70
70
  <div id="root"></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":"d710532a61c26061cd24e7558883cbfd","url":"index.html"},{"revision":"a0fb34fc84eb148d51812cd62669f20d","url":"icon-512.svg"},{"revision":null,"url":"assets/refresh-cw-BjrAbUJe.js"},{"revision":null,"url":"assets/chevron-up-BWBvMZkp.js"},{"revision":null,"url":"assets/pie-UPGHQEXC-w03Pc9ZR.js"},{"revision":null,"url":"assets/csv-parser-B5QW8pZ6.js"},{"revision":null,"url":"assets/info-3K5VOQVL-tSD4Fpi3.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/database-D4DIhgi-.js"},{"revision":null,"url":"assets/csv-preview-DcWCjQkZ.js"},{"revision":null,"url":"assets/use-blob-url-QX-XajU8.js"},{"revision":null,"url":"assets/x-DlFGzN8d.js"},{"revision":null,"url":"assets/port-forwarding-tab-Dkq1upWC.js"},{"revision":null,"url":"assets/extension-store-BZDZ9QRc.js"},{"revision":null,"url":"assets/use-monaco-theme-D68oX3XU.js"},{"revision":null,"url":"assets/KaTeX_Main-Regular-B22Nviop.woff2"},{"revision":null,"url":"assets/vendor-mermaid-sQS4C_iL.js"},{"revision":null,"url":"assets/extension-webview-U1lMYZ0p.js"},{"revision":null,"url":"assets/image-preview-BcT1SbY2.js"},{"revision":null,"url":"assets/gitGraph-HDMCJU4V-BURAevTc.js"},{"revision":null,"url":"assets/index-BWSRKVZn.js"},{"revision":null,"url":"assets/github.min-D2BCvnWf.css"},{"revision":null,"url":"assets/terminal-tab-BtnqkN1H.js"},{"revision":null,"url":"assets/KaTeX_Fraktur-Regular-CTYiF6lA.woff2"},{"revision":null,"url":"assets/database-viewer-C85RxdMV.js"},{"revision":null,"url":"assets/postgres-viewer-BgBJAJ9q.js"},{"revision":null,"url":"assets/chevron-right-BzAdxJRG.js"},{"revision":null,"url":"assets/audio-preview-BkbgGtDH.js"},{"revision":null,"url":"assets/esm-_CLpyLJ_.js"},{"revision":null,"url":"assets/pre-compact-button-Dp7Hs49L.js"},{"revision":null,"url":"assets/KaTeX_Main-BoldItalic-DxDJ3AOS.woff2"},{"revision":null,"url":"assets/packet-RMMSAZCW-DmDLZUrV.js"},{"revision":null,"url":"assets/index-b6tIZImC.css"},{"revision":null,"url":"assets/vendor-markdown-0Mxgxy0L.js"},{"revision":null,"url":"assets/diff-viewer-2pPy97Tl.js"},{"revision":null,"url":"assets/KaTeX_Main-Italic-NWA7e6Wa.woff2"},{"revision":null,"url":"assets/trash-2-DjQOpgUV.js"},{"revision":null,"url":"assets/vendor-xterm-K3_Xwigj.js"},{"revision":null,"url":"assets/KaTeX_Typewriter-Regular-CO6r4hn1.woff2"},{"revision":null,"url":"assets/markdown-renderer-Dbam_-04.js"},{"revision":null,"url":"assets/settings-store-CMAssqyb.js"},{"revision":null,"url":"assets/dist-GtkSekuX.js"},{"revision":null,"url":"assets/tab-store-DNBsLdPn.js"},{"revision":null,"url":"assets/file-store-4BpOJthN.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/react-DMIOAtcX.js"},{"revision":null,"url":"assets/lib-Bu71-TFS.js"},{"revision":null,"url":"assets/utils-CQux7CsO.js"},{"revision":null,"url":"assets/rolldown-runtime-FhOqtrmT.js"},{"revision":null,"url":"assets/katex-C3cZrCvP.js"},{"revision":null,"url":"assets/ai-settings-section-NNWp6nw7.js"},{"revision":null,"url":"assets/KaTeX_Math-Italic-t53AETM-.woff2"},{"revision":null,"url":"assets/pdf-preview-BmHVGx32.js"},{"revision":null,"url":"assets/github-dark-dimmed.min-BrpRStFV.css"},{"revision":null,"url":"assets/keybindings-store-BOG1yviy.js"},{"revision":null,"url":"assets/treemap-KZPCXAKY-lmftxSky.js"},{"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/file-exclamation-point-BwzaQ50n.js"},{"revision":null,"url":"assets/chat-tab-BZlP1qjX.js"},{"revision":null,"url":"assets/api-client-DIhJ5qVW.js"},{"revision":null,"url":"assets/input-2eDVjcRZ.js"},{"revision":null,"url":"assets/architecture-PBZL5I3N-DDuzYaUV.js"},{"revision":null,"url":"assets/scroll-area-CdxNNnN-.js"},{"revision":null,"url":"assets/sql-completion-provider-CULTsCqR.js"},{"revision":null,"url":"assets/sql-query-editor-b7zJ8XPp.js"},{"revision":null,"url":"assets/columns-2-4fQcE4PF.js"},{"revision":null,"url":"assets/KaTeX_Main-Bold-Cx986IdX.woff2"},{"revision":null,"url":"assets/KaTeX_Size2-Regular-Dy4dx90m.woff2"},{"revision":null,"url":"assets/sqlite-viewer-4lLAz1es.js"},{"revision":null,"url":"assets/KaTeX_SansSerif-Regular-DDBCnlJ7.woff2"},{"revision":null,"url":"assets/KaTeX_Size1-Regular-mCD8mA8B.woff2"},{"revision":null,"url":"assets/createLucideIcon-BjHrJDVb.js"},{"revision":null,"url":"assets/conflict-editor-Dgsu6fmj.js"},{"revision":null,"url":"assets/keybindings-store-BvdUoEC7.js"},{"revision":null,"url":"assets/KaTeX_Size4-Regular-Dl5lxZxV.woff2"},{"revision":null,"url":"assets/code-CuravVys.js"},{"revision":null,"url":"assets/KaTeX_Math-BoldItalic-CZnvNsCZ.woff2"},{"revision":null,"url":"assets/table-tf7pRkME.js"},{"revision":null,"url":"assets/api-settings-C3T95dWg.js"},{"revision":null,"url":"assets/pre-compact-section-DnM5fGSR.js"},{"revision":null,"url":"assets/vendor-ui-B-89Uj8i.js"},{"revision":null,"url":"assets/radar-KQ55EAFF-C9XQvoey.js"},{"revision":null,"url":"assets/vendor-xterm-BrP-ENHg.css"},{"revision":null,"url":"assets/video-preview-CkOKvVLt.js"},{"revision":null,"url":"assets/settings-tab-zYWKTq5z.js"},{"revision":null,"url":"assets/KaTeX_SansSerif-Italic-C3H0VqGB.woff2"},{"revision":null,"url":"assets/code-editor-BtspASkW.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":"0d69cc15d70d51bbdea08a77bc5db646","url":"index.html"},{"revision":"a0fb34fc84eb148d51812cd62669f20d","url":"icon-512.svg"},{"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/scroll-area-BEllam7_.js"},{"revision":null,"url":"assets/database-D4DIhgi-.js"},{"revision":null,"url":"assets/csv-parser--2WJNgS7.js"},{"revision":null,"url":"assets/x-DlFGzN8d.js"},{"revision":null,"url":"assets/audio-preview--hRMnXRZ.js"},{"revision":null,"url":"assets/keybindings-store-B-zET-0o.js"},{"revision":null,"url":"assets/port-forwarding-tab-3RNozlZ5.js"},{"revision":null,"url":"assets/use-blob-url-e9uTXjv5.js"},{"revision":null,"url":"assets/index-Bce0weeW.css"},{"revision":null,"url":"assets/radar-KQ55EAFF-BviZcL-b.js"},{"revision":null,"url":"assets/vendor-xterm-CU2c3f0A.js"},{"revision":null,"url":"assets/input-Dk49gO8E.js"},{"revision":null,"url":"assets/sqlite-viewer-C8WUEFhA.js"},{"revision":null,"url":"assets/KaTeX_Main-Regular-B22Nviop.woff2"},{"revision":null,"url":"assets/refresh-cw-LlbZDJpO.js"},{"revision":null,"url":"assets/diff-viewer-CCzPq1o-.js"},{"revision":null,"url":"assets/pie-UPGHQEXC-D6S2MqVT.js"},{"revision":null,"url":"assets/chat-tab-4kL3DNxf.js"},{"revision":null,"url":"assets/treemap-KZPCXAKY-CM54VdaB.js"},{"revision":null,"url":"assets/react-GqWghJ-L.js"},{"revision":null,"url":"assets/github.min-D2BCvnWf.css"},{"revision":null,"url":"assets/vendor-mermaid-Dx86tuVP.js"},{"revision":null,"url":"assets/ai-settings-section-QE6nBNgN.js"},{"revision":null,"url":"assets/csv-preview-HMSavgBb.js"},{"revision":null,"url":"assets/katex-CKoArbIw.js"},{"revision":null,"url":"assets/KaTeX_Fraktur-Regular-CTYiF6lA.woff2"},{"revision":null,"url":"assets/info-3K5VOQVL-BwAZ2zd8.js"},{"revision":null,"url":"assets/chevron-right-BzAdxJRG.js"},{"revision":null,"url":"assets/extension-store-3yZYn07W.js"},{"revision":null,"url":"assets/code-editor-Caq5_BaF.js"},{"revision":null,"url":"assets/KaTeX_Main-BoldItalic-DxDJ3AOS.woff2"},{"revision":null,"url":"assets/vendor-markdown-0Mxgxy0L.js"},{"revision":null,"url":"assets/api-client-Dvzcc_EO.js"},{"revision":null,"url":"assets/database-viewer-DcBl6OkV.js"},{"revision":null,"url":"assets/dist-im4ynINo.js"},{"revision":null,"url":"assets/KaTeX_Main-Italic-NWA7e6Wa.woff2"},{"revision":null,"url":"assets/table-Dq575bPF.js"},{"revision":null,"url":"assets/KaTeX_Typewriter-Regular-CO6r4hn1.woff2"},{"revision":null,"url":"assets/packet-RMMSAZCW-tx2n5Qry.js"},{"revision":null,"url":"assets/plus-51UQ45rf.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/api-settings-DAk7D-NP.js"},{"revision":null,"url":"assets/architecture-PBZL5I3N-DvZbltvY.js"},{"revision":null,"url":"assets/rolldown-runtime-FhOqtrmT.js"},{"revision":null,"url":"assets/settings-store-BLLR7ed8.js"},{"revision":null,"url":"assets/markdown-renderer-DyAm7zuA.js"},{"revision":null,"url":"assets/use-monaco-theme-BkZDwoVd.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_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/file-exclamation-point-BwzaQ50n.js"},{"revision":null,"url":"assets/file-store-BrbCNyLm.js"},{"revision":null,"url":"assets/extension-webview-D7bGVSEd.js"},{"revision":null,"url":"assets/utils-CTg5uAYR.js"},{"revision":null,"url":"assets/columns-2-4fQcE4PF.js"},{"revision":null,"url":"assets/KaTeX_Main-Bold-Cx986IdX.woff2"},{"revision":null,"url":"assets/postgres-viewer-CXJv4TXc.js"},{"revision":null,"url":"assets/KaTeX_Size2-Regular-Dy4dx90m.woff2"},{"revision":null,"url":"assets/pdf-preview-CZPcuy5c.js"},{"revision":null,"url":"assets/KaTeX_SansSerif-Regular-DDBCnlJ7.woff2"},{"revision":null,"url":"assets/KaTeX_Size1-Regular-mCD8mA8B.woff2"},{"revision":null,"url":"assets/tab-store-B3M9hjho.js"},{"revision":null,"url":"assets/keybindings-store-DaBV6qhz.js"},{"revision":null,"url":"assets/createLucideIcon-BjHrJDVb.js"},{"revision":null,"url":"assets/index-BGFG66Gh.js"},{"revision":null,"url":"assets/settings-tab-Cnav4g2u.js"},{"revision":null,"url":"assets/KaTeX_Size4-Regular-Dl5lxZxV.woff2"},{"revision":null,"url":"assets/code-CuravVys.js"},{"revision":null,"url":"assets/terminal-tab-CaEsMxp8.js"},{"revision":null,"url":"assets/KaTeX_Math-BoldItalic-CZnvNsCZ.woff2"},{"revision":null,"url":"assets/sql-completion-provider-C3cq9j99.js"},{"revision":null,"url":"assets/vendor-ui-B-89Uj8i.js"},{"revision":null,"url":"assets/image-preview-CfkqnhXJ.js"},{"revision":null,"url":"assets/conflict-editor-Dlo25nmt.js"},{"revision":null,"url":"assets/esm-K1XIK4vc.js"},{"revision":null,"url":"assets/gitGraph-HDMCJU4V-BxhdxFgj.js"},{"revision":null,"url":"assets/vendor-xterm-BrP-ENHg.css"},{"revision":null,"url":"assets/video-preview-Dfz71RGb.js"},{"revision":null,"url":"assets/KaTeX_SansSerif-Italic-C3H0VqGB.woff2"},{"revision":null,"url":"assets/lib-DQHnkzGy.js"},{"revision":null,"url":"assets/sql-query-editor-CVAnRFbi.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||`/`)}))});
@@ -2,7 +2,21 @@
2
2
 
3
3
  All notable changes to PPM are documented here. Format follows [Keep a Changelog](https://keepachangelog.com/).
4
4
 
5
- **Current Version:** v0.11.10
5
+ **Current Version:** v0.13.0
6
+
7
+ ---
8
+
9
+ ## [0.13.0] — 2026-04-21 — PPM Export Skill
10
+
11
+ ### Added
12
+ - **`ppm export skill`** — self-describe for external AI. Installs a Claude Code skill at `~/.claude/skills/ppm/` (or `<project>/.claude/skills/ppm/` with `--scope project`, or custom `--output <dir>`) so external AI agents can autonomously control PPM via its CLI, HTTP API, and SQLite config DB. Skill package contains `SKILL.md` + `references/{cli-reference,http-api,db-schema,common-tasks}.md`.
13
+ - **Build-time generators** (`scripts/generate-ppm-skill.ts` + `scripts/lib/`): walk the Commander tree for CLI reference and regex-scan `src/server/index.ts` + `src/server/routes/*.ts` for HTTP API reference. Zero-side-effect static introspection.
14
+ - **Runtime generator** (`src/services/skill-export/generate-db-schema.ts`): opens `~/.ppm/ppm.db` readonly via `bun:sqlite` and emits markdown tables per PRAGMA table_info.
15
+ - **Re-install safety**: existing skill files renamed to `<name>.bak-<YYYYMMDDHHmm>` before overwrite; never destructive.
16
+ - **`buildProgram()` export** in `src/index.ts` — the assembled Commander tree without `.parse()`, enabling build-time doc tools.
17
+
18
+ ### Changed
19
+ - `scripts/generate-ppm-guide.ts` → `scripts/generate-ppm-skill.ts`; `assets/skills/ppm-guide/` → `assets/skills/ppm/`; `generate:guide` npm script → `generate:skill`.
6
20
 
7
21
  ---
8
22
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@hienlh/ppm",
3
- "version": "0.12.12",
3
+ "version": "0.13.2",
4
4
  "description": "Personal Project Manager — mobile-first web IDE with AI assistance",
5
5
  "author": "hienlh",
6
6
  "license": "MIT",
@@ -19,8 +19,8 @@
19
19
  "start": "bun run src/index.ts start",
20
20
  "typecheck": "bunx tsc --noEmit",
21
21
  "generate:bot": "bun scripts/generate-bot-coordinator.ts --update",
22
- "generate:guide": "bun scripts/generate-ppm-guide.ts",
23
- "prepublishOnly": "bun run generate:guide && bun run build:web"
22
+ "generate:skill": "bun scripts/generate-ppm-skill.ts",
23
+ "prepublishOnly": "bun run generate:skill && bun run build:web"
24
24
  },
25
25
  "devDependencies": {
26
26
  "@tailwindcss/vite": "^4.2.1",
@@ -0,0 +1,23 @@
1
+ #!/usr/bin/env bun
2
+ /**
3
+ * Build-time generator: emits assets/skills/ppm/ package (SKILL.md + references/*.md).
4
+ * Runs on prepublishOnly so the bundled skill ships with the npm package.
5
+ * Usage: bun scripts/generate-ppm-skill.ts
6
+ */
7
+ import { resolve, dirname } from "node:path";
8
+ import { writeFiles } from "./lib/write-output.ts";
9
+ import { generateSkillMd } from "./lib/generate-skill-md.ts";
10
+ import { generateCliReference } from "./lib/generate-cli-reference.ts";
11
+ import { generateHttpApi } from "./lib/generate-http-api.ts";
12
+ import { generateCommonTasks } from "./lib/generate-common-tasks.ts";
13
+
14
+ const ROOT = resolve(dirname(import.meta.path), "..");
15
+ const OUT = resolve(ROOT, "assets/skills/ppm");
16
+
17
+ const files = [
18
+ ...generateSkillMd(ROOT),
19
+ ...(await generateCliReference(ROOT)),
20
+ ...generateHttpApi(ROOT),
21
+ ...generateCommonTasks(ROOT),
22
+ ];
23
+ writeFiles(OUT, files);
@@ -0,0 +1,81 @@
1
+ // Walk the Commander tree produced by buildProgram() and emit a markdown reference.
2
+ // No side effects — buildProgram() assembles commands but does not invoke any `action` callback.
3
+ import type { Command, Option } from "commander";
4
+ import { buildProgram } from "../../src/index.ts";
5
+ import type { OutputFile } from "./write-output.ts";
6
+
7
+ export async function generateCliReference(_root: string): Promise<OutputFile[]> {
8
+ const program = await buildProgram();
9
+ const header = "# PPM CLI Reference\n\n_Auto-generated. Do not edit._\n\nRoot binary: `ppm`. Run `ppm <command> --help` for full usage.\n";
10
+
11
+ // Global options section (root-level options only, excluding implicit -V/-h).
12
+ const globalOptsMd = renderRootOptions(program);
13
+
14
+ // Child commands sorted alphabetically for deterministic output.
15
+ const children = [...program.commands].filter((c) => !isHidden(c)).sort((a, b) => a.name().localeCompare(b.name()));
16
+ const sections = children.map((c) => renderCommand(c, 2)).join("\n");
17
+
18
+ const content = `${header}\n${globalOptsMd}\n## Commands\n\n${sections}`;
19
+ return [{ relPath: "references/cli-reference.md", content }];
20
+ }
21
+
22
+ function isHidden(cmd: Command): boolean {
23
+ // Commander's internal flag. Public typings omit `_hidden`; access defensively.
24
+ return Boolean((cmd as unknown as { _hidden?: boolean })._hidden);
25
+ }
26
+
27
+ function renderRootOptions(program: Command): string {
28
+ const opts = program.options.filter((o) => !o.hidden);
29
+ if (opts.length === 0) return "";
30
+ const rows = opts.map((o) => `- \`${o.flags}\` — ${o.description || "_(no description)_"}`).join("\n");
31
+ return `## Global Options\n\n${rows}\n`;
32
+ }
33
+
34
+ function renderCommand(cmd: Command, depth: number): string {
35
+ const heading = "#".repeat(Math.min(depth, 6));
36
+ const pathName = commandPath(cmd);
37
+ const desc = cmd.description() || "_(no description)_";
38
+
39
+ const parts: string[] = [];
40
+ parts.push(`${heading} \`ppm ${pathName}\``);
41
+ parts.push("");
42
+ parts.push(desc);
43
+
44
+ const opts = cmd.options.filter((o: Option) => !o.hidden);
45
+ if (opts.length > 0) {
46
+ parts.push("");
47
+ parts.push("**Options:**");
48
+ for (const o of opts) {
49
+ const d = o.description || "_(no description)_";
50
+ const def = o.defaultValue !== undefined ? ` (default: \`${JSON.stringify(o.defaultValue)}\`)` : "";
51
+ parts.push(`- \`${o.flags}\` — ${d}${def}`);
52
+ }
53
+ }
54
+
55
+ const usage = cmd.usage();
56
+ if (usage && usage !== "[options]") {
57
+ parts.push("");
58
+ parts.push(`**Usage:** \`ppm ${pathName} ${usage}\``);
59
+ }
60
+
61
+ parts.push("");
62
+
63
+ // Recurse into subcommands (preserve registration order per phase 2 spec).
64
+ const subs = cmd.commands.filter((c) => !isHidden(c));
65
+ for (const sub of subs) {
66
+ parts.push(renderCommand(sub, depth + 1));
67
+ }
68
+
69
+ return parts.join("\n");
70
+ }
71
+
72
+ function commandPath(cmd: Command): string {
73
+ // Walk up parents to construct e.g. `db list` instead of just `list`.
74
+ const chain: string[] = [];
75
+ let cur: Command | null = cmd;
76
+ while (cur && cur.parent) {
77
+ chain.unshift(cur.name());
78
+ cur = cur.parent;
79
+ }
80
+ return chain.join(" ");
81
+ }
@@ -0,0 +1,14 @@
1
+ // Phase 4 populates. Phase 1 stub.
2
+ import { readFileSync, existsSync } from "node:fs";
3
+ import { resolve } from "node:path";
4
+ import type { OutputFile } from "./write-output.ts";
5
+
6
+ export function generateCommonTasks(root: string): OutputFile[] {
7
+ const tmplPath = resolve(root, "templates/skill/common-tasks.md");
8
+ if (existsSync(tmplPath)) {
9
+ const content = readFileSync(tmplPath, "utf-8");
10
+ return [{ relPath: "references/common-tasks.md", content }];
11
+ }
12
+ const stub = "# PPM Common Tasks\n\n_TODO: populated in phase 4._\n";
13
+ return [{ relPath: "references/common-tasks.md", content: stub }];
14
+ }
@@ -0,0 +1,145 @@
1
+ // Static scan of Hono route definitions. Two-pass:
2
+ // 1. Parse src/server/index.ts → mount map { mountPath: routerIdent } + import { routerIdent: relFile }.
3
+ // 2. For each mounted route file, regex-scan HTTP method calls, group by mount prefix.
4
+ // No code execution — all data comes from string parsing.
5
+ import { readFileSync, existsSync } from "node:fs";
6
+ import { resolve } from "node:path";
7
+ import type { OutputFile } from "./write-output.ts";
8
+
9
+ const METHOD_RE = /\.(get|post|put|patch|delete|all)\s*\(\s*["'`]([^"'`]+)["'`]/g;
10
+ const MOUNT_RE = /\.route\s*\(\s*["'`]([^"'`]+)["'`]\s*,\s*(\w+)\s*\)/g;
11
+ const IMPORT_RE = /import\s*\{\s*([\w,\s]+)\s*\}\s*from\s*["'`]([^"'`]+)["'`]/g;
12
+
13
+ interface RouteEntry {
14
+ method: string;
15
+ path: string;
16
+ desc?: string;
17
+ }
18
+
19
+ export function generateHttpApi(root: string): OutputFile[] {
20
+ const serverIndexPath = resolve(root, "src/server/index.ts");
21
+ if (!existsSync(serverIndexPath)) {
22
+ return [{ relPath: "references/http-api.md", content: "# PPM HTTP API\n\n_Server index not found._\n" }];
23
+ }
24
+
25
+ const serverSrc = readFileSync(serverIndexPath, "utf-8");
26
+ const importMap = parseImports(serverSrc);
27
+ const mounts = parseMounts(serverSrc);
28
+
29
+ // Group routes by mount prefix
30
+ const grouped: Record<string, RouteEntry[]> = {};
31
+ const warnings: string[] = [];
32
+
33
+ for (const [prefix, routerIdent] of mounts) {
34
+ const rel = importMap.get(routerIdent);
35
+ if (!rel) {
36
+ warnings.push(`Unresolved import for router '${routerIdent}' (mount: ${prefix})`);
37
+ continue;
38
+ }
39
+ const routeFile = resolveImport(serverIndexPath, rel);
40
+ if (!existsSync(routeFile)) {
41
+ warnings.push(`Route file not found: ${routeFile} (router: ${routerIdent})`);
42
+ continue;
43
+ }
44
+ const entries = scanRoutes(readFileSync(routeFile, "utf-8"));
45
+ if (!grouped[prefix]) grouped[prefix] = [];
46
+ grouped[prefix].push(...entries);
47
+ }
48
+
49
+ // Build markdown
50
+ const parts: string[] = [];
51
+ parts.push("# PPM HTTP API");
52
+ parts.push("");
53
+ parts.push("_Auto-generated. Do not edit._");
54
+ parts.push("");
55
+ parts.push("_Base URL: `http://localhost:8080` (default; override via `ppm config set port <n>`)._");
56
+ parts.push("");
57
+
58
+ const sortedPrefixes = Object.keys(grouped).sort();
59
+ for (const prefix of sortedPrefixes) {
60
+ const routes = grouped[prefix];
61
+ if (!routes || routes.length === 0) continue;
62
+ parts.push(`## ${prefix || "/"}`);
63
+ parts.push("");
64
+ for (const r of routes) {
65
+ const fullPath = joinPath(prefix, r.path);
66
+ const method = r.method.toUpperCase().padEnd(6);
67
+ parts.push(`- \`${method} ${fullPath}\`${r.desc ? ` — ${r.desc}` : ""}`);
68
+ }
69
+ parts.push("");
70
+ }
71
+
72
+ parts.push("## WebSocket");
73
+ parts.push("");
74
+ parts.push("- `ws://<host>/ws/chat` — AI chat stream (Claude Agent SDK)");
75
+ parts.push("- `ws://<host>/ws/terminal` — PTY terminal multiplexer");
76
+ parts.push("- `ws://<host>/ws/extensions` — extension host channel");
77
+ parts.push("");
78
+
79
+ const pkg = JSON.parse(readFileSync(resolve(root, "package.json"), "utf-8")) as { version: string };
80
+ parts.push(`<!-- Generated from src/server/routes/ for PPM v${pkg.version} -->`);
81
+
82
+ if (warnings.length > 0) {
83
+ parts.push("");
84
+ parts.push("<!--");
85
+ parts.push("Scanner warnings (build-time):");
86
+ for (const w of warnings) parts.push(` - ${w}`);
87
+ parts.push("-->");
88
+ }
89
+
90
+ return [{ relPath: "references/http-api.md", content: parts.join("\n") + "\n" }];
91
+ }
92
+
93
+ function parseImports(src: string): Map<string, string> {
94
+ const map = new Map<string, string>();
95
+ let m: RegExpExecArray | null;
96
+ const re = new RegExp(IMPORT_RE);
97
+ while ((m = re.exec(src)) !== null) {
98
+ const ids = (m[1] ?? "").split(",").map((s) => s.trim()).filter(Boolean);
99
+ const path = m[2] ?? "";
100
+ for (const id of ids) map.set(id, path);
101
+ }
102
+ return map;
103
+ }
104
+
105
+ function parseMounts(src: string): Array<[string, string]> {
106
+ const out: Array<[string, string]> = [];
107
+ let m: RegExpExecArray | null;
108
+ const re = new RegExp(MOUNT_RE);
109
+ while ((m = re.exec(src)) !== null) {
110
+ out.push([m[1] ?? "", m[2] ?? ""]);
111
+ }
112
+ return out;
113
+ }
114
+
115
+ function resolveImport(fromFile: string, spec: string): string {
116
+ // Resolve relative import from a source file. Preserve `.ts` suffix if present.
117
+ const fromDir = resolve(fromFile, "..");
118
+ let abs = resolve(fromDir, spec);
119
+ if (!abs.endsWith(".ts") && !abs.endsWith(".js")) {
120
+ abs += ".ts";
121
+ }
122
+ return abs;
123
+ }
124
+
125
+ function scanRoutes(src: string): RouteEntry[] {
126
+ const entries: RouteEntry[] = [];
127
+ let m: RegExpExecArray | null;
128
+ const re = new RegExp(METHOD_RE);
129
+ while ((m = re.exec(src)) !== null) {
130
+ const method = m[1] ?? "";
131
+ const path = m[2] ?? "";
132
+ // Skip obviously-bogus matches (e.g. "http://" in URLs — regex already avoids these since path can't start with http:).
133
+ if (path.startsWith("http:") || path.startsWith("https:")) continue;
134
+ entries.push({ method, path });
135
+ }
136
+ return entries;
137
+ }
138
+
139
+ function joinPath(prefix: string, routePath: string): string {
140
+ if (!prefix || prefix === "/") return routePath;
141
+ if (routePath === "/" || routePath === "") return prefix;
142
+ const p = prefix.endsWith("/") ? prefix.slice(0, -1) : prefix;
143
+ const r = routePath.startsWith("/") ? routePath : `/${routePath}`;
144
+ return p + r;
145
+ }
@@ -0,0 +1,28 @@
1
+ // Phase 4 populates. Phase 1 stub returns a placeholder SKILL.md.
2
+ import { readFileSync, existsSync } from "node:fs";
3
+ import { resolve } from "node:path";
4
+ import type { OutputFile } from "./write-output.ts";
5
+
6
+ export function generateSkillMd(root: string): OutputFile[] {
7
+ const tmplPath = resolve(root, "templates/skill/SKILL.md.tmpl");
8
+ if (existsSync(tmplPath)) {
9
+ const tmpl = readFileSync(tmplPath, "utf-8");
10
+ const pkgJson = JSON.parse(readFileSync(resolve(root, "package.json"), "utf-8")) as { version: string };
11
+ const footer = `<!-- Generated for PPM v${pkgJson.version} at build time. Re-run \`ppm export skill --install\` to refresh. -->`;
12
+ const content = tmpl.replace("<!-- AUTO:version_footer -->", footer);
13
+ return [{ relPath: "SKILL.md", content }];
14
+ }
15
+ // Stub fallback when template not yet authored (used during phase 1)
16
+ const stub = [
17
+ "---",
18
+ "name: ppm",
19
+ "description: Control PPM via CLI, HTTP API, and SQLite config DB.",
20
+ "---",
21
+ "",
22
+ "# PPM Skill",
23
+ "",
24
+ "_Stub — template pending (phase 4)._",
25
+ "",
26
+ ].join("\n");
27
+ return [{ relPath: "SKILL.md", content: stub }];
28
+ }
@@ -0,0 +1,17 @@
1
+ // Shared helper: recursively create dirs then write files. Used by skill package generator.
2
+ import { mkdirSync, writeFileSync } from "node:fs";
3
+ import { dirname, resolve } from "node:path";
4
+
5
+ export interface OutputFile {
6
+ relPath: string;
7
+ content: string;
8
+ }
9
+
10
+ export function writeFiles(rootDir: string, files: OutputFile[]): void {
11
+ for (const f of files) {
12
+ const abs = resolve(rootDir, f.relPath);
13
+ mkdirSync(dirname(abs), { recursive: true });
14
+ writeFileSync(abs, f.content, "utf-8");
15
+ }
16
+ console.log(`[generate-ppm-skill] wrote ${files.length} files to ${rootDir}`);
17
+ }
@@ -0,0 +1,85 @@
1
+ // `ppm export skill` — install bundled skill package to ~/.claude/skills/ppm/ (or custom path)
2
+ // so external AI tools (Claude Code, compatible agents) can control PPM.
3
+ import type { Command } from "commander";
4
+ import { readFileSync, writeFileSync, existsSync, mkdirSync } from "node:fs";
5
+ import { resolve } from "node:path";
6
+ import {
7
+ resolveTargetDir,
8
+ resolveAssetsDir,
9
+ backupExisting,
10
+ copyBundledSkill,
11
+ generateDbSchemaMarkdown,
12
+ type SkillScope,
13
+ } from "../../services/skill-export/index.ts";
14
+
15
+ interface ExportSkillOpts {
16
+ install?: boolean;
17
+ scope: SkillScope;
18
+ output?: string;
19
+ format: string;
20
+ }
21
+
22
+ export function registerExportCommands(program: Command): void {
23
+ const exp = program
24
+ .command("export")
25
+ .description("Export PPM metadata for external tools (AI agents, editors)");
26
+
27
+ exp
28
+ .command("skill")
29
+ .description("Export Claude Code skill for controlling PPM from external AI tools")
30
+ .option("--install", "Install to target dir (default scope=user → ~/.claude/skills/ppm/)")
31
+ .option("--scope <scope>", "Install scope: user | project", "user")
32
+ .option("--output <dir>", "Custom output directory (overrides --scope)")
33
+ .option("--format <fmt>", "Output format", "claude-code")
34
+ .action(async (opts: ExportSkillOpts) => {
35
+ if (opts.format !== "claude-code") {
36
+ console.error(`Unsupported format: ${opts.format}. Only 'claude-code' is supported in v1.`);
37
+ process.exit(1);
38
+ }
39
+ if (opts.scope && opts.scope !== "user" && opts.scope !== "project") {
40
+ console.error(`Invalid scope: ${opts.scope}. Use 'user' or 'project'.`);
41
+ process.exit(1);
42
+ }
43
+
44
+ let assetsDir: string;
45
+ try {
46
+ assetsDir = resolveAssetsDir();
47
+ } catch (e) {
48
+ console.error(e instanceof Error ? e.message : String(e));
49
+ process.exit(2);
50
+ }
51
+
52
+ // Preview mode: print merged SKILL.md to stdout.
53
+ if (!opts.install && !opts.output) {
54
+ const skillPath = resolve(assetsDir, "SKILL.md");
55
+ process.stdout.write(readFileSync(skillPath, "utf-8"));
56
+ return;
57
+ }
58
+
59
+ const target = resolveTargetDir({ scope: opts.scope, output: opts.output });
60
+
61
+ try {
62
+ const backedUp = backupExisting(target);
63
+ mkdirSync(target, { recursive: true });
64
+ copyBundledSkill(assetsDir, target);
65
+
66
+ // Runtime DB schema (reads ~/.ppm/ppm.db readonly)
67
+ const refsDir = resolve(target, "references");
68
+ mkdirSync(refsDir, { recursive: true });
69
+ writeFileSync(resolve(refsDir, "db-schema.md"), generateDbSchemaMarkdown(), "utf-8");
70
+
71
+ console.log(`✓ Installed PPM skill → ${target}`);
72
+ if (backedUp.length > 0) {
73
+ console.log(` Backed up ${backedUp.length} existing file(s) with .bak-<timestamp> suffix.`);
74
+ console.log(` Safe to delete those backups if not needed.`);
75
+ }
76
+ if (!existsSync(resolve(target, "SKILL.md"))) {
77
+ console.error("Post-install verification failed: SKILL.md missing in target.");
78
+ process.exit(1);
79
+ }
80
+ } catch (e) {
81
+ console.error(`Install failed: ${e instanceof Error ? e.message : String(e)}`);
82
+ process.exit(1);
83
+ }
84
+ });
85
+ }