@hienlh/ppm 0.9.0-beta.2 → 0.9.0-beta.3

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 (27) hide show
  1. package/CHANGELOG.md +19 -0
  2. package/dist/web/assets/chat-tab-DxkvWelV.js +7 -0
  3. package/dist/web/assets/{code-editor-CQ7gq0Vj.js → code-editor-D3VJc1tY.js} +1 -1
  4. package/dist/web/assets/{database-viewer-B27aRtdQ.js → database-viewer-qlwORhh0.js} +1 -1
  5. package/dist/web/assets/{diff-viewer-BjtTemkK.js → diff-viewer-D5vGZJnH.js} +1 -1
  6. package/dist/web/assets/{git-graph-BGXo0o-J.js → git-graph-B2fHtKEc.js} +1 -1
  7. package/dist/web/assets/{index-CfClIVo2.js → index-Ccq6zi2E.js} +3 -3
  8. package/dist/web/assets/keybindings-store-e3pqlQbf.js +1 -0
  9. package/dist/web/assets/{markdown-renderer-BtPXdzTv.js → markdown-renderer-DcGMlbRm.js} +1 -1
  10. package/dist/web/assets/{postgres-viewer-BMg-qFcO.js → postgres-viewer-CZzbMFtb.js} +1 -1
  11. package/dist/web/assets/{settings-tab-NPuwQHzs.js → settings-tab-BOmLAhkD.js} +1 -1
  12. package/dist/web/assets/{sqlite-viewer-CAsUczio.js → sqlite-viewer-CrrzHXqq.js} +1 -1
  13. package/dist/web/assets/{terminal-tab--Gw14HP3.js → terminal-tab-DHMITI3S.js} +2 -2
  14. package/dist/web/index.html +1 -1
  15. package/dist/web/sw.js +1 -1
  16. package/package.json +1 -1
  17. package/src/providers/claude-agent-sdk.ts +212 -76
  18. package/src/server/ws/chat.ts +103 -72
  19. package/src/types/api.ts +1 -1
  20. package/src/types/chat.ts +2 -0
  21. package/src/web/components/chat/chat-tab.tsx +3 -3
  22. package/src/web/components/chat/message-input.tsx +41 -4
  23. package/src/web/hooks/use-chat.ts +21 -9
  24. package/dist/web/assets/chat-tab-DmF14O6G.js +0 -7
  25. package/dist/web/assets/keybindings-store-nDbczFnq.js +0 -1
  26. package/snapshot-state.md +0 -1526
  27. package/test-tokens.mjs +0 -212
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":"d727287b574458f5a539d893cd93db9e","url":"index.html"},{"revision":"a0fb34fc84eb148d51812cd62669f20d","url":"icon-512.svg"},{"revision":"a0fb34fc84eb148d51812cd62669f20d","url":"icon-192.svg"},{"revision":"eb9818b9094675c0c5d303168f273345","url":"monacoeditorwork/ts.worker.bundle.js"},{"revision":"9af0be92dcefdc1f1290441cb5ff5d9b","url":"monacoeditorwork/json.worker.bundle.js"},{"revision":"a261b429c39dbb75ae97972d7d005e6d","url":"monacoeditorwork/html.worker.bundle.js"},{"revision":"79953d804e1bbacecfd79b85fd679016","url":"monacoeditorwork/editor.worker.bundle.js"},{"revision":"fdcba0d09aac31df7a0bc652f6e739bd","url":"monacoeditorwork/css.worker.bundle.js"},{"revision":null,"url":"assets/xychartDiagram-JWTSCODW-DhUL86qT.js"},{"revision":null,"url":"assets/vennDiagram-LZ73GAT5-DqbKNRD9.js"},{"revision":null,"url":"assets/utils-btZ8C8-R.js"},{"revision":null,"url":"assets/use-monaco-theme-DHbyUrzJ.js"},{"revision":null,"url":"assets/treemap-KZPCXAKY-2_y-mhkz.js"},{"revision":null,"url":"assets/timeline-definition-YZTLITO2-DYfwJ1jM.js"},{"revision":null,"url":"assets/terminal-tab-BrP-ENHg.css"},{"revision":null,"url":"assets/terminal-tab--Gw14HP3.js"},{"revision":null,"url":"assets/tag-CaC1ng2E.js"},{"revision":null,"url":"assets/table-Yo02WRH-.js"},{"revision":null,"url":"assets/tab-store-dpsCvqhH.js"},{"revision":null,"url":"assets/stateDiagram-v2-FVOUBMTO-CMN4M2Em.js"},{"revision":null,"url":"assets/stateDiagram-RAJIS63D-DfRBcaBu.js"},{"revision":null,"url":"assets/src-BoSBNdA_.js"},{"revision":null,"url":"assets/sqlite-viewer-CAsUczio.js"},{"revision":null,"url":"assets/settings-tab-NPuwQHzs.js"},{"revision":null,"url":"assets/settings-store-Bbhg_ptG.js"},{"revision":null,"url":"assets/sequenceDiagram-2WXFIKYE-fyWIrHiG.js"},{"revision":null,"url":"assets/sankeyDiagram-WA2Y5GQK-BA9EFAAe.js"},{"revision":null,"url":"assets/rough.esm-VLpapkIG.js"},{"revision":null,"url":"assets/requirementDiagram-Z7DCOOCP-D_5GXNRo.js"},{"revision":null,"url":"assets/react-nm2Ru1Pt.js"},{"revision":null,"url":"assets/react-BGf7KNLk.js"},{"revision":null,"url":"assets/radar-KQ55EAFF-C4PnyG7_.js"},{"revision":null,"url":"assets/quadrantDiagram-337W2JSQ-B7zgALOL.js"},{"revision":null,"url":"assets/preload-helper-qlgyTAkD.js"},{"revision":null,"url":"assets/postgres-viewer-BMg-qFcO.js"},{"revision":null,"url":"assets/pieDiagram-SKSYHLDU-Bkh2E4zE.js"},{"revision":null,"url":"assets/pie-UPGHQEXC-Bm5LiD-6.js"},{"revision":null,"url":"assets/path-DZF-JdEe.js"},{"revision":null,"url":"assets/packet-RMMSAZCW-CdYSLjRL.js"},{"revision":null,"url":"assets/ordinal-CCj7PWgZ.js"},{"revision":null,"url":"assets/mindmap-definition-YRQLILUH-DoT7m4Sz.js"},{"revision":null,"url":"assets/mermaid-parser.core-BKiGOTjR.js"},{"revision":null,"url":"assets/math-DwgHI-Cu.js"},{"revision":null,"url":"assets/markdown-renderer-BtPXdzTv.js"},{"revision":null,"url":"assets/linear-BLFWatDe.js"},{"revision":null,"url":"assets/line-DBLLF7lH.js"},{"revision":null,"url":"assets/keybindings-store-nDbczFnq.js"},{"revision":null,"url":"assets/katex-Bbu770d9.js"},{"revision":null,"url":"assets/kanban-definition-K7BYSVSG-BBXbI37U.js"},{"revision":null,"url":"assets/jsx-runtime-BRW_vwa9.js"},{"revision":null,"url":"assets/journeyDiagram-4ABVD52K-CttDH9bb.js"},{"revision":null,"url":"assets/ishikawaDiagram-PHBUUO56-olazD6dZ.js"},{"revision":null,"url":"assets/isEmpty-C0YYdhYj.js"},{"revision":null,"url":"assets/isArrayLikeObject-B4pdpV8V.js"},{"revision":null,"url":"assets/input-Brjz2Vv-.js"},{"revision":null,"url":"assets/init-B8gtcn7T.js"},{"revision":null,"url":"assets/infoDiagram-LFFYTUFH-BzqyoqXw.js"},{"revision":null,"url":"assets/info-3K5VOQVL-ce_pi3En.js"},{"revision":null,"url":"assets/index-CfClIVo2.js"},{"revision":null,"url":"assets/index-BAioKo_2.css"},{"revision":null,"url":"assets/graphlib-DhOZxqsh.js"},{"revision":null,"url":"assets/gitGraphDiagram-K3NZZRJ6-yEWZbdf_.js"},{"revision":null,"url":"assets/gitGraph-HDMCJU4V-CEee2FCA.js"},{"revision":null,"url":"assets/git-graph-BGXo0o-J.js"},{"revision":null,"url":"assets/ganttDiagram-A5KZAMGK-DIX0pLbk.js"},{"revision":null,"url":"assets/flowDiagram-PKNHOUZH-14ohZ1M1.js"},{"revision":null,"url":"assets/erDiagram-INFDFZHY-mCvUFSn6.js"},{"revision":null,"url":"assets/dist-T0Vhi0Mh.js"},{"revision":null,"url":"assets/dist-Cce3efmT.js"},{"revision":null,"url":"assets/diff-viewer-BjtTemkK.js"},{"revision":null,"url":"assets/diagram-P4PSJMXO-D1eW1dkL.js"},{"revision":null,"url":"assets/diagram-IFDJBPK2-ChB_paPo.js"},{"revision":null,"url":"assets/diagram-E7M64L7V-CzKYZM0Y.js"},{"revision":null,"url":"assets/defaultLocale-CRZydyG6.js"},{"revision":null,"url":"assets/database-viewer-B27aRtdQ.js"},{"revision":null,"url":"assets/dagre-KLK3FWXG-ChenfPp1.js"},{"revision":null,"url":"assets/dagre-CNtSxiE_.js"},{"revision":null,"url":"assets/cytoscape.esm-Ccan6xou.js"},{"revision":null,"url":"assets/cose-bilkent-S5V4N54A-CHHjH2dV.js"},{"revision":null,"url":"assets/columns-2-ChOTgl3e.js"},{"revision":null,"url":"assets/code-editor-CQ7gq0Vj.js"},{"revision":null,"url":"assets/clone-BSi6cgDh.js"},{"revision":null,"url":"assets/classDiagram-v2-RAHNMMFH-Bj8gIhkP.js"},{"revision":null,"url":"assets/classDiagram-VBA2DB6C-BpJ6Oog2.js"},{"revision":null,"url":"assets/chunk-YBOYWFTD-Dx_fX35n.js"},{"revision":null,"url":"assets/chunk-XZSTWKYB-BYxFzZwS.js"},{"revision":null,"url":"assets/chunk-XPW4576I-CtcaMb09.js"},{"revision":null,"url":"assets/chunk-XIRO2GV7-kqQ0g6wW.js"},{"revision":null,"url":"assets/chunk-WL4C6EOR-_2CBOJdI.js"},{"revision":null,"url":"assets/chunk-R5LLSJPH-euR2RxLN.js"},{"revision":null,"url":"assets/chunk-QZHKN3VN-DwSXwtjH.js"},{"revision":null,"url":"assets/chunk-PU5JKC2W-B66ELkQm.js"},{"revision":null,"url":"assets/chunk-PQ6SQG4A-BxtUGYhW.js"},{"revision":null,"url":"assets/chunk-OZEHJAEY-YTn24bGg.js"},{"revision":null,"url":"assets/chunk-O4XLMI2P-BurQy8tt.js"},{"revision":null,"url":"assets/chunk-NQ4KR5QH-DLrZwBEm.js"},{"revision":null,"url":"assets/chunk-MX3YWQON-BgjSEzus.js"},{"revision":null,"url":"assets/chunk-L3YUKLVL-3wBgkSvL.js"},{"revision":null,"url":"assets/chunk-KYZI473N-BKO5gMeU.js"},{"revision":null,"url":"assets/chunk-KX2RTZJC-BCxGmbzy.js"},{"revision":null,"url":"assets/chunk-JSJVCQXG-BSrqCL_3.js"},{"revision":null,"url":"assets/chunk-HHEYEP7N-Dld5BpGB.js"},{"revision":null,"url":"assets/chunk-GLR3WWYH-D9pZakqr.js"},{"revision":null,"url":"assets/chunk-GEFDOKGD-DwVPiYfW.js"},{"revision":null,"url":"assets/chunk-FMBD7UC4-C_1aG0eb.js"},{"revision":null,"url":"assets/chunk-EGIJ26TM-D0KJTa_T.js"},{"revision":null,"url":"assets/chunk-CFjPhJqf.js"},{"revision":null,"url":"assets/chunk-C72U2L5F-DOtEiN5f.js"},{"revision":null,"url":"assets/chunk-7R4GIKGN-DXaGAn_K.js"},{"revision":null,"url":"assets/chunk-7E7YKBS2-6xAQfBwa.js"},{"revision":null,"url":"assets/chunk-55IACEB6-C4mUdyio.js"},{"revision":null,"url":"assets/chunk-4BX2VUAB-BptTlTyl.js"},{"revision":null,"url":"assets/chat-tab-DmF14O6G.js"},{"revision":null,"url":"assets/channel-w7yboq56.js"},{"revision":null,"url":"assets/c4Diagram-IC4MRINW-BNP2L9r_.js"},{"revision":null,"url":"assets/blockDiagram-WCTKOSBZ-CKGufRTy.js"},{"revision":null,"url":"assets/array-BGFCBI0e.js"},{"revision":null,"url":"assets/architectureDiagram-2XIMDMQ5-Jq91S_rs.js"},{"revision":null,"url":"assets/architecture-PBZL5I3N-ChOahOB7.js"},{"revision":null,"url":"assets/arc-C2Qaz-ch.js"},{"revision":null,"url":"assets/api-settings--eVrUeZM.js"},{"revision":null,"url":"assets/api-client-DpGMOZNf.js"},{"revision":null,"url":"assets/_baseUniq-ClnvscgW.js"},{"revision":null,"url":"assets/_basePickBy-CZovQgWd.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":"266fd88e14f238a28bd538c7394afe05","url":"index.html"},{"revision":"a0fb34fc84eb148d51812cd62669f20d","url":"icon-512.svg"},{"revision":"a0fb34fc84eb148d51812cd62669f20d","url":"icon-192.svg"},{"revision":"eb9818b9094675c0c5d303168f273345","url":"monacoeditorwork/ts.worker.bundle.js"},{"revision":"9af0be92dcefdc1f1290441cb5ff5d9b","url":"monacoeditorwork/json.worker.bundle.js"},{"revision":"a261b429c39dbb75ae97972d7d005e6d","url":"monacoeditorwork/html.worker.bundle.js"},{"revision":"79953d804e1bbacecfd79b85fd679016","url":"monacoeditorwork/editor.worker.bundle.js"},{"revision":"fdcba0d09aac31df7a0bc652f6e739bd","url":"monacoeditorwork/css.worker.bundle.js"},{"revision":null,"url":"assets/xychartDiagram-JWTSCODW-DhUL86qT.js"},{"revision":null,"url":"assets/vennDiagram-LZ73GAT5-DqbKNRD9.js"},{"revision":null,"url":"assets/utils-btZ8C8-R.js"},{"revision":null,"url":"assets/use-monaco-theme-DHbyUrzJ.js"},{"revision":null,"url":"assets/treemap-KZPCXAKY-2_y-mhkz.js"},{"revision":null,"url":"assets/timeline-definition-YZTLITO2-DYfwJ1jM.js"},{"revision":null,"url":"assets/terminal-tab-DHMITI3S.js"},{"revision":null,"url":"assets/terminal-tab-BrP-ENHg.css"},{"revision":null,"url":"assets/tag-CaC1ng2E.js"},{"revision":null,"url":"assets/table-Yo02WRH-.js"},{"revision":null,"url":"assets/tab-store-dpsCvqhH.js"},{"revision":null,"url":"assets/stateDiagram-v2-FVOUBMTO-CMN4M2Em.js"},{"revision":null,"url":"assets/stateDiagram-RAJIS63D-DfRBcaBu.js"},{"revision":null,"url":"assets/src-BoSBNdA_.js"},{"revision":null,"url":"assets/sqlite-viewer-CrrzHXqq.js"},{"revision":null,"url":"assets/settings-tab-BOmLAhkD.js"},{"revision":null,"url":"assets/settings-store-Bbhg_ptG.js"},{"revision":null,"url":"assets/sequenceDiagram-2WXFIKYE-fyWIrHiG.js"},{"revision":null,"url":"assets/sankeyDiagram-WA2Y5GQK-BA9EFAAe.js"},{"revision":null,"url":"assets/rough.esm-VLpapkIG.js"},{"revision":null,"url":"assets/requirementDiagram-Z7DCOOCP-D_5GXNRo.js"},{"revision":null,"url":"assets/react-nm2Ru1Pt.js"},{"revision":null,"url":"assets/react-BGf7KNLk.js"},{"revision":null,"url":"assets/radar-KQ55EAFF-C4PnyG7_.js"},{"revision":null,"url":"assets/quadrantDiagram-337W2JSQ-B7zgALOL.js"},{"revision":null,"url":"assets/preload-helper-qlgyTAkD.js"},{"revision":null,"url":"assets/postgres-viewer-CZzbMFtb.js"},{"revision":null,"url":"assets/pieDiagram-SKSYHLDU-Bkh2E4zE.js"},{"revision":null,"url":"assets/pie-UPGHQEXC-Bm5LiD-6.js"},{"revision":null,"url":"assets/path-DZF-JdEe.js"},{"revision":null,"url":"assets/packet-RMMSAZCW-CdYSLjRL.js"},{"revision":null,"url":"assets/ordinal-CCj7PWgZ.js"},{"revision":null,"url":"assets/mindmap-definition-YRQLILUH-DoT7m4Sz.js"},{"revision":null,"url":"assets/mermaid-parser.core-BKiGOTjR.js"},{"revision":null,"url":"assets/math-DwgHI-Cu.js"},{"revision":null,"url":"assets/markdown-renderer-DcGMlbRm.js"},{"revision":null,"url":"assets/linear-BLFWatDe.js"},{"revision":null,"url":"assets/line-DBLLF7lH.js"},{"revision":null,"url":"assets/keybindings-store-e3pqlQbf.js"},{"revision":null,"url":"assets/katex-Bbu770d9.js"},{"revision":null,"url":"assets/kanban-definition-K7BYSVSG-BBXbI37U.js"},{"revision":null,"url":"assets/jsx-runtime-BRW_vwa9.js"},{"revision":null,"url":"assets/journeyDiagram-4ABVD52K-CttDH9bb.js"},{"revision":null,"url":"assets/ishikawaDiagram-PHBUUO56-olazD6dZ.js"},{"revision":null,"url":"assets/isEmpty-C0YYdhYj.js"},{"revision":null,"url":"assets/isArrayLikeObject-B4pdpV8V.js"},{"revision":null,"url":"assets/input-Brjz2Vv-.js"},{"revision":null,"url":"assets/init-B8gtcn7T.js"},{"revision":null,"url":"assets/infoDiagram-LFFYTUFH-BzqyoqXw.js"},{"revision":null,"url":"assets/info-3K5VOQVL-ce_pi3En.js"},{"revision":null,"url":"assets/index-Ccq6zi2E.js"},{"revision":null,"url":"assets/index-BAioKo_2.css"},{"revision":null,"url":"assets/graphlib-DhOZxqsh.js"},{"revision":null,"url":"assets/gitGraphDiagram-K3NZZRJ6-yEWZbdf_.js"},{"revision":null,"url":"assets/gitGraph-HDMCJU4V-CEee2FCA.js"},{"revision":null,"url":"assets/git-graph-B2fHtKEc.js"},{"revision":null,"url":"assets/ganttDiagram-A5KZAMGK-DIX0pLbk.js"},{"revision":null,"url":"assets/flowDiagram-PKNHOUZH-14ohZ1M1.js"},{"revision":null,"url":"assets/erDiagram-INFDFZHY-mCvUFSn6.js"},{"revision":null,"url":"assets/dist-T0Vhi0Mh.js"},{"revision":null,"url":"assets/dist-Cce3efmT.js"},{"revision":null,"url":"assets/diff-viewer-D5vGZJnH.js"},{"revision":null,"url":"assets/diagram-P4PSJMXO-D1eW1dkL.js"},{"revision":null,"url":"assets/diagram-IFDJBPK2-ChB_paPo.js"},{"revision":null,"url":"assets/diagram-E7M64L7V-CzKYZM0Y.js"},{"revision":null,"url":"assets/defaultLocale-CRZydyG6.js"},{"revision":null,"url":"assets/database-viewer-qlwORhh0.js"},{"revision":null,"url":"assets/dagre-KLK3FWXG-ChenfPp1.js"},{"revision":null,"url":"assets/dagre-CNtSxiE_.js"},{"revision":null,"url":"assets/cytoscape.esm-Ccan6xou.js"},{"revision":null,"url":"assets/cose-bilkent-S5V4N54A-CHHjH2dV.js"},{"revision":null,"url":"assets/columns-2-ChOTgl3e.js"},{"revision":null,"url":"assets/code-editor-D3VJc1tY.js"},{"revision":null,"url":"assets/clone-BSi6cgDh.js"},{"revision":null,"url":"assets/classDiagram-v2-RAHNMMFH-Bj8gIhkP.js"},{"revision":null,"url":"assets/classDiagram-VBA2DB6C-BpJ6Oog2.js"},{"revision":null,"url":"assets/chunk-YBOYWFTD-Dx_fX35n.js"},{"revision":null,"url":"assets/chunk-XZSTWKYB-BYxFzZwS.js"},{"revision":null,"url":"assets/chunk-XPW4576I-CtcaMb09.js"},{"revision":null,"url":"assets/chunk-XIRO2GV7-kqQ0g6wW.js"},{"revision":null,"url":"assets/chunk-WL4C6EOR-_2CBOJdI.js"},{"revision":null,"url":"assets/chunk-R5LLSJPH-euR2RxLN.js"},{"revision":null,"url":"assets/chunk-QZHKN3VN-DwSXwtjH.js"},{"revision":null,"url":"assets/chunk-PU5JKC2W-B66ELkQm.js"},{"revision":null,"url":"assets/chunk-PQ6SQG4A-BxtUGYhW.js"},{"revision":null,"url":"assets/chunk-OZEHJAEY-YTn24bGg.js"},{"revision":null,"url":"assets/chunk-O4XLMI2P-BurQy8tt.js"},{"revision":null,"url":"assets/chunk-NQ4KR5QH-DLrZwBEm.js"},{"revision":null,"url":"assets/chunk-MX3YWQON-BgjSEzus.js"},{"revision":null,"url":"assets/chunk-L3YUKLVL-3wBgkSvL.js"},{"revision":null,"url":"assets/chunk-KYZI473N-BKO5gMeU.js"},{"revision":null,"url":"assets/chunk-KX2RTZJC-BCxGmbzy.js"},{"revision":null,"url":"assets/chunk-JSJVCQXG-BSrqCL_3.js"},{"revision":null,"url":"assets/chunk-HHEYEP7N-Dld5BpGB.js"},{"revision":null,"url":"assets/chunk-GLR3WWYH-D9pZakqr.js"},{"revision":null,"url":"assets/chunk-GEFDOKGD-DwVPiYfW.js"},{"revision":null,"url":"assets/chunk-FMBD7UC4-C_1aG0eb.js"},{"revision":null,"url":"assets/chunk-EGIJ26TM-D0KJTa_T.js"},{"revision":null,"url":"assets/chunk-CFjPhJqf.js"},{"revision":null,"url":"assets/chunk-C72U2L5F-DOtEiN5f.js"},{"revision":null,"url":"assets/chunk-7R4GIKGN-DXaGAn_K.js"},{"revision":null,"url":"assets/chunk-7E7YKBS2-6xAQfBwa.js"},{"revision":null,"url":"assets/chunk-55IACEB6-C4mUdyio.js"},{"revision":null,"url":"assets/chunk-4BX2VUAB-BptTlTyl.js"},{"revision":null,"url":"assets/chat-tab-DxkvWelV.js"},{"revision":null,"url":"assets/channel-w7yboq56.js"},{"revision":null,"url":"assets/c4Diagram-IC4MRINW-BNP2L9r_.js"},{"revision":null,"url":"assets/blockDiagram-WCTKOSBZ-CKGufRTy.js"},{"revision":null,"url":"assets/array-BGFCBI0e.js"},{"revision":null,"url":"assets/architectureDiagram-2XIMDMQ5-Jq91S_rs.js"},{"revision":null,"url":"assets/architecture-PBZL5I3N-ChOahOB7.js"},{"revision":null,"url":"assets/arc-C2Qaz-ch.js"},{"revision":null,"url":"assets/api-settings--eVrUeZM.js"},{"revision":null,"url":"assets/api-client-DpGMOZNf.js"},{"revision":null,"url":"assets/_baseUniq-ClnvscgW.js"},{"revision":null,"url":"assets/_basePickBy-CZovQgWd.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.9.0-beta.2",
3
+ "version": "0.9.0-beta.3",
4
4
  "description": "Personal Project Manager — mobile-first web IDE with AI assistance",
5
5
  "author": "hienlh",
6
6
  "license": "MIT",
@@ -24,6 +24,84 @@ function getSdkSessionId(ppmId: string): string {
24
24
  return getSessionMapping(ppmId) ?? ppmId;
25
25
  }
26
26
 
27
+ // ── Streaming Input: message channel for persistent query ──
28
+
29
+ interface MessageController {
30
+ push(msg: any): void;
31
+ done(): void;
32
+ }
33
+
34
+ function createMessageChannel(): {
35
+ generator: AsyncGenerator<any, void, undefined>;
36
+ controller: MessageController;
37
+ } {
38
+ const queue: any[] = [];
39
+ let resolve: ((msg: any) => void) | null = null;
40
+ let isDone = false;
41
+
42
+ async function* gen(): AsyncGenerator<any, void, undefined> {
43
+ while (!isDone) {
44
+ if (queue.length > 0) {
45
+ yield queue.shift()!;
46
+ } else {
47
+ const msg = await new Promise<any>((r) => { resolve = r; });
48
+ if (!isDone) yield msg;
49
+ }
50
+ }
51
+ }
52
+
53
+ return {
54
+ generator: gen(),
55
+ controller: {
56
+ push(msg: any) {
57
+ if (isDone) return;
58
+ if (resolve) {
59
+ const r = resolve;
60
+ resolve = null;
61
+ r(msg);
62
+ } else {
63
+ queue.push(msg);
64
+ }
65
+ },
66
+ done() {
67
+ isDone = true;
68
+ if (resolve) {
69
+ const r = resolve;
70
+ resolve = null;
71
+ r(null); // Unblock pending promise; isDone prevents yield
72
+ }
73
+ },
74
+ },
75
+ };
76
+ }
77
+
78
+ /** Build a MessageParam with optional image content blocks */
79
+ function buildMessageParam(
80
+ text: string,
81
+ images?: Array<{ data: string; mediaType: string }>,
82
+ ): { role: 'user'; content: string | any[] } {
83
+ if (!images || images.length === 0) {
84
+ return { role: 'user' as const, content: text };
85
+ }
86
+ const blocks: any[] = [];
87
+ for (const img of images) {
88
+ blocks.push({
89
+ type: 'image',
90
+ source: { type: 'base64', media_type: img.mediaType, data: img.data },
91
+ });
92
+ }
93
+ if (text.trim()) {
94
+ blocks.push({ type: 'text', text });
95
+ }
96
+ return { role: 'user' as const, content: blocks };
97
+ }
98
+
99
+ interface StreamingSession {
100
+ meta: Session;
101
+ query: any;
102
+ controller: MessageController;
103
+ }
104
+
27
105
  /**
28
106
  * Pending approval: canUseTool callback creates a promise,
29
107
  * yields an approval_request event, then awaits resolution from FE.
@@ -49,6 +127,8 @@ export class ClaudeAgentSdkProvider implements AIProvider {
49
127
  private activeQueries = new Map<string, { close: () => void }>();
50
128
  /** Fork source: ppmSessionId → sourceSessionId (used on first message to fork) */
51
129
  private forkSources = new Map<string, string>();
130
+ /** Streaming sessions: persistent query + message channel per session */
131
+ private streamingSessions = new Map<string, StreamingSession>();
52
132
 
53
133
  /** Auth-related env keys for diagnostic logging */
54
134
  private readonly AUTH_ENV_KEYS = ["ANTHROPIC_API_KEY", "ANTHROPIC_BASE_URL", "ANTHROPIC_AUTH_TOKEN"];
@@ -219,6 +299,7 @@ export class ClaudeAgentSdkProvider implements AIProvider {
219
299
  }
220
300
 
221
301
  async deleteSession(sessionId: string): Promise<void> {
302
+ this.closeStreamingSession(sessionId);
222
303
  this.activeSessions.delete(sessionId);
223
304
  this.messageCount.delete(sessionId);
224
305
  }
@@ -251,11 +332,63 @@ export class ClaudeAgentSdkProvider implements AIProvider {
251
332
  }
252
333
  }
253
334
 
335
+ /**
336
+ * Push a follow-up message into an existing streaming session's generator.
337
+ * Called by WS handler for follow-up messages (Phase 2).
338
+ */
339
+ pushMessage(sessionId: string, content: string, opts?: { priority?: 'now' | 'next' | 'later'; images?: Array<{ data: string; mediaType: string }> }): void {
340
+ const ss = this.streamingSessions.get(sessionId);
341
+ if (!ss) {
342
+ console.warn(`[sdk] pushMessage: no streaming session for ${sessionId}`);
343
+ return;
344
+ }
345
+ const msgContent = buildMessageParam(content, opts?.images);
346
+ ss.controller.push({
347
+ type: 'user',
348
+ message: msgContent,
349
+ parent_tool_use_id: null,
350
+ session_id: sessionId,
351
+ priority: opts?.priority ?? 'next',
352
+ });
353
+ console.log(`[sdk] pushMessage: session=${sessionId} priority=${opts?.priority ?? 'next'}`);
354
+ }
355
+
356
+ /** Close a streaming session — generator + query cleanup */
357
+ closeStreamingSession(sessionId: string): void {
358
+ const ss = this.streamingSessions.get(sessionId);
359
+ if (ss) {
360
+ ss.controller.done();
361
+ ss.query.close();
362
+ this.streamingSessions.delete(sessionId);
363
+ console.log(`[sdk] closeStreamingSession: session=${sessionId}`);
364
+ }
365
+ }
366
+
367
+ /** Check if a streaming session is active for a given session ID */
368
+ hasStreamingSession(sessionId: string): boolean {
369
+ return this.streamingSessions.has(sessionId);
370
+ }
371
+
254
372
  async *sendMessage(
255
373
  sessionId: string,
256
374
  message: string,
257
- opts?: import("./provider.interface.ts").SendMessageOpts & { forkSession?: boolean },
375
+ opts?: import("./provider.interface.ts").SendMessageOpts & { forkSession?: boolean; priority?: 'now' | 'next' | 'later'; images?: Array<{ data: string; mediaType: string }> },
258
376
  ): AsyncIterable<ChatEvent> {
377
+ // Follow-up: push into existing streaming session, yield nothing
378
+ const existingStream = this.streamingSessions.get(sessionId);
379
+ if (existingStream) {
380
+ const msgContent = buildMessageParam(message, opts?.images);
381
+ existingStream.controller.push({
382
+ type: 'user',
383
+ message: msgContent,
384
+ parent_tool_use_id: null,
385
+ session_id: sessionId,
386
+ priority: opts?.priority ?? 'next',
387
+ });
388
+ console.log(`[sdk] sendMessage follow-up: session=${sessionId} pushed to generator`);
389
+ return; // Events flow through first-message's consumer loop
390
+ }
391
+
259
392
  if (!this.activeSessions.has(sessionId)) {
260
393
  await this.resumeSession(sessionId);
261
394
  }
@@ -378,6 +511,7 @@ export class ClaudeAgentSdkProvider implements AIProvider {
378
511
  let resultSubtype: string | undefined;
379
512
  let resultNumTurns: number | undefined;
380
513
  let resultContextWindowPct: number | undefined;
514
+ let yieldedDone = false;
381
515
  try {
382
516
  // Resolve SDK's actual session ID for resume (may differ from PPM's UUID)
383
517
  // For fork: use the source session's SDK id
@@ -449,14 +583,25 @@ export class ClaudeAgentSdkProvider implements AIProvider {
449
583
  includePartialMessages: true,
450
584
  };
451
585
 
586
+ // Streaming input: create message channel and persistent query
587
+ const { generator: streamGen, controller: streamCtrl } = createMessageChannel();
588
+ const firstMsg = {
589
+ type: 'user' as const,
590
+ message: buildMessageParam(message),
591
+ parent_tool_use_id: null,
592
+ session_id: sessionId,
593
+ };
594
+ streamCtrl.push(firstMsg);
595
+
452
596
  const q = query({
453
- prompt: message,
597
+ prompt: streamGen,
454
598
  options: {
455
599
  ...queryOptions,
456
600
  ...(permissionHooks && { hooks: permissionHooks }),
457
601
  canUseTool,
458
602
  } as any,
459
603
  });
604
+ this.streamingSessions.set(sessionId, { meta, query: q, controller: streamCtrl });
460
605
  this.activeQueries.set(sessionId, q);
461
606
  let eventSource: AsyncIterable<any> = q;
462
607
 
@@ -471,22 +616,29 @@ export class ClaudeAgentSdkProvider implements AIProvider {
471
616
  let retryCount = 0;
472
617
  let authRetried = false;
473
618
 
619
+ let hadAnyEvents = false;
474
620
  retryLoop: while (true) {
475
621
  let sdkEventCount = 0;
476
622
  for await (const msg of eventSource) {
477
623
  sdkEventCount++;
624
+ hadAnyEvents = true;
478
625
  if (sdkEventCount === 1) {
479
626
  console.log(`[sdk] first event received: type=${(msg as any).type} subtype=${(msg as any).subtype ?? "none"}`);
480
627
  // Detect immediate failure: first event is a result with error + 0 turns
481
628
  if ((msg as any).type === "result" && (msg as any).subtype === "error_during_execution" && ((msg as any).num_turns ?? 0) === 0 && retryCount < MAX_RETRIES) {
482
629
  retryCount++;
483
630
  console.warn(`[sdk] transient error on first event — retrying (attempt ${retryCount}/${MAX_RETRIES})`);
484
- // Re-create query for retry don't reuse sessionId in case SDK partially created it
631
+ // Close failed query and old channel, create new channel + query for retry
632
+ streamCtrl.done();
633
+ q.close();
634
+ const { generator: retryGen, controller: retryCtrl } = createMessageChannel();
635
+ retryCtrl.push(firstMsg);
485
636
  const retryOpts = { ...queryOptions, sessionId: undefined, resume: undefined };
486
637
  const rq = query({
487
- prompt: message,
638
+ prompt: retryGen,
488
639
  options: { ...retryOpts, ...(permissionHooks && { hooks: permissionHooks }), canUseTool } as any,
489
640
  });
641
+ this.streamingSessions.set(sessionId, { meta, query: rq, controller: retryCtrl });
490
642
  this.activeQueries.set(sessionId, rq);
491
643
  eventSource = rq;
492
644
  continue retryLoop;
@@ -632,11 +784,17 @@ export class ClaudeAgentSdkProvider implements AIProvider {
632
784
  const refreshedAccount = accountService.getWithTokens(account.id);
633
785
  if (refreshedAccount) {
634
786
  const retryEnv = this.buildQueryEnv(meta.projectPath, refreshedAccount);
787
+ // Close failed query and old channel, create new channel + query with refreshed token
788
+ streamCtrl.done();
789
+ q.close();
790
+ const { generator: authRetryGen, controller: authRetryCtrl } = createMessageChannel();
791
+ authRetryCtrl.push(firstMsg);
635
792
  const retryOpts = { ...queryOptions, sessionId: undefined, resume: undefined, env: retryEnv };
636
793
  const rq = query({
637
- prompt: message,
794
+ prompt: authRetryGen,
638
795
  options: { ...retryOpts, ...(permissionHooks && { hooks: permissionHooks }), canUseTool } as any,
639
796
  });
797
+ this.streamingSessions.set(sessionId, { meta, query: rq, controller: authRetryCtrl });
640
798
  this.activeQueries.set(sessionId, rq);
641
799
  eventSource = rq;
642
800
  continue retryLoop;
@@ -708,9 +866,9 @@ export class ClaudeAgentSdkProvider implements AIProvider {
708
866
  const errCode = this.detectResultErrorCode(msg);
709
867
  if (errCode === 429) {
710
868
  accountSelector.onRateLimit(account.id);
711
- // Post-stream 429 already has content — surface error to user
869
+ // Post-stream 429 — surface error, continue waiting for next turn
712
870
  yield { type: "error", message: "Rate limited. This account is now on cooldown. Please retry." };
713
- break;
871
+ continue;
714
872
  } else if (errCode === 401) {
715
873
  // Try refresh once
716
874
  try {
@@ -818,7 +976,26 @@ export class ClaudeAgentSdkProvider implements AIProvider {
818
976
  }
819
977
  }
820
978
  }
821
- break;
979
+
980
+ // Streaming input: yield done for this turn, then continue for next turn
981
+ yieldedDone = true;
982
+ yield {
983
+ type: "done",
984
+ sessionId,
985
+ resultSubtype: resultSubtype as any,
986
+ numTurns: resultNumTurns,
987
+ contextWindowPct: resultContextWindowPct,
988
+ };
989
+
990
+ // Reset per-turn state for next turn
991
+ lastPartialText = "";
992
+ pendingToolCount = 0;
993
+ assistantContent = "";
994
+ resultSubtype = undefined;
995
+ resultNumTurns = undefined;
996
+ resultContextWindowPct = undefined;
997
+ sdkEventCount = 0;
998
+ continue; // Wait for next turn from generator
822
999
  }
823
1000
  }
824
1001
 
@@ -827,7 +1004,7 @@ export class ClaudeAgentSdkProvider implements AIProvider {
827
1004
  yield approvalEvents.shift()!;
828
1005
  }
829
1006
 
830
- if (sdkEventCount === 0) {
1007
+ if (!hadAnyEvents) {
831
1008
  yield { type: "error", message: "Claude did not respond. Check that 'claude' CLI works in your terminal." };
832
1009
  }
833
1010
  break; // Exit retryLoop — normal completion
@@ -837,88 +1014,47 @@ export class ClaudeAgentSdkProvider implements AIProvider {
837
1014
  console.error(`[sdk] session=${sessionId} cwd=${meta.projectPath} error: ${msg}`);
838
1015
  if (msg.includes("abort") || msg.includes("closed")) {
839
1016
  // User-initiated abort or WS closed — nothing to report
840
- } else if (!isFirstMessage && msg.includes("exited with code")) {
841
- // SDK subprocess crashed during session resume retry as fresh session
842
- console.warn(`[sdk] session resume failed, retrying as fresh session`);
843
- try {
844
- const providerConfig = this.getProviderConfig();
845
- const effectiveCwd = meta.projectPath || homedir();
846
- const retryAccount = accountSelector.isEnabled() ? accountSelector.next() : null;
847
- const queryEnv = this.buildQueryEnv(meta.projectPath, retryAccount);
848
- const retryOptions = {
849
- ...(process.platform === "win32" && { executable: "node" }),
850
- cwd: effectiveCwd,
851
- systemPrompt: systemPromptOpt,
852
- settingSources: ["user", "project"],
853
- env: queryEnv,
854
- settings: { permissions: { allow: [], deny: [] } },
855
- allowedTools,
856
- permissionMode,
857
- allowDangerouslySkipPermissions: isBypass,
858
- ...(providerConfig.model && { model: providerConfig.model }),
859
- maxTurns: providerConfig.max_turns ?? 100,
860
- includePartialMessages: true,
861
- };
862
- const retryQuery = query({
863
- prompt: message,
864
- options: {
865
- ...retryOptions,
866
- ...(permissionHooks && { hooks: permissionHooks }),
867
- canUseTool,
868
- } as any,
869
- });
870
- this.activeQueries.set(sessionId, retryQuery);
871
- for await (const retryMsg of retryQuery) {
872
- if (retryMsg.type === "system") continue;
873
- if (retryMsg.type === "result") {
874
- const r = retryMsg as any;
875
- if (r.subtype && r.subtype !== "success") {
876
- const retryErrors = Array.isArray(r.errors) ? r.errors.join("\n") : "";
877
- yield { type: "error", message: retryErrors || `Agent stopped: ${r.subtype}` };
878
- }
879
- resultSubtype = r.subtype;
880
- resultNumTurns = r.num_turns;
881
- break;
882
- }
883
- if ((retryMsg as any).type === "assistant") {
884
- const content = (retryMsg as any).message?.content;
885
- if (Array.isArray(content)) {
886
- for (const block of content) {
887
- if (block.type === "text" && typeof block.text === "string") {
888
- yield { type: "text", content: block.text };
889
- }
890
- }
891
- }
892
- }
893
- }
894
- } catch (retryErr) {
895
- const retryMsg = (retryErr as Error).message ?? String(retryErr);
896
- console.error(`[sdk] retry also failed: ${retryMsg}`);
897
- yield { type: "error", message: `SDK error: ${msg}` };
898
- }
1017
+ } else if (msg.includes("exited with code")) {
1018
+ // Subprocess crashed session will auto-recover on next message
1019
+ console.warn(`[sdk] session=${sessionId} subprocess crashed: ${msg}`);
1020
+ yield { type: "error", message: `SDK subprocess crashed. Send another message to auto-recover.` };
899
1021
  } else {
900
1022
  yield { type: "error", message: `SDK error: ${msg}` };
901
1023
  }
902
1024
  } finally {
903
1025
  this.activeQueries.delete(sessionId);
1026
+ this.streamingSessions.delete(sessionId);
1027
+ console.log(`[sdk] session=${sessionId} streaming session ended`);
904
1028
  }
905
1029
 
906
- yield {
907
- type: "done",
908
- sessionId,
909
- resultSubtype: resultSubtype as any,
910
- numTurns: resultNumTurns,
911
- contextWindowPct: resultContextWindowPct,
912
- };
1030
+ // Final done event when query ends (crash, close, generator done)
1031
+ // Skip if we already yielded done from the result handler (avoid duplicate)
1032
+ if (!yieldedDone) {
1033
+ yield {
1034
+ type: "done",
1035
+ sessionId,
1036
+ resultSubtype: resultSubtype as any,
1037
+ numTurns: resultNumTurns,
1038
+ contextWindowPct: resultContextWindowPct,
1039
+ };
1040
+ }
913
1041
  }
914
1042
 
915
1043
 
916
- /** Abort an active query for a session */
1044
+ /** Interrupt the current turn — session stays alive for the next message */
917
1045
  abortQuery(sessionId: string): void {
1046
+ const ss = this.streamingSessions.get(sessionId);
1047
+ if (ss && typeof ss.query.interrupt === "function") {
1048
+ ss.query.interrupt().catch(() => {});
1049
+ console.log(`[sdk] abortQuery: interrupted session=${sessionId}`);
1050
+ return;
1051
+ }
1052
+ // Fallback: close query entirely and clean up streaming session
918
1053
  const q = this.activeQueries.get(sessionId);
919
1054
  if (q) {
920
1055
  q.close();
921
1056
  this.activeQueries.delete(sessionId);
1057
+ this.streamingSessions.delete(sessionId);
922
1058
  }
923
1059
  }
924
1060