@rexvane/piweb 0.3.12 → 0.3.13

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 (176) hide show
  1. package/.next/BUILD_ID +1 -1
  2. package/.next/app-path-routes-manifest.json +6 -5
  3. package/.next/build-manifest.json +3 -3
  4. package/.next/prerender-manifest.json +3 -3
  5. package/.next/react-loadable-manifest.json +2 -2
  6. package/.next/routes-manifest.json +6 -0
  7. package/.next/server/app/_global-error/page.js +2 -2
  8. package/.next/server/app/_global-error/page_client-reference-manifest.js +1 -1
  9. package/.next/server/app/_global-error.html +1 -1
  10. package/.next/server/app/_global-error.rsc +1 -1
  11. package/.next/server/app/_global-error.segments/_full.segment.rsc +1 -1
  12. package/.next/server/app/_global-error.segments/_global-error/__PAGE__.segment.rsc +1 -1
  13. package/.next/server/app/_global-error.segments/_tree.segment.rsc +1 -1
  14. package/.next/server/app/_not-found/page.js +1 -1
  15. package/.next/server/app/_not-found/page_client-reference-manifest.js +1 -1
  16. package/.next/server/app/_not-found.html +1 -1
  17. package/.next/server/app/_not-found.rsc +1 -1
  18. package/.next/server/app/_not-found.segments/_full.segment.rsc +1 -1
  19. package/.next/server/app/_not-found.segments/_not-found/__PAGE__.segment.rsc +1 -1
  20. package/.next/server/app/_not-found.segments/_tree.segment.rsc +1 -1
  21. package/.next/server/app/api/agent/[id]/events/route.js +2 -2
  22. package/.next/server/app/api/agent/[id]/events/route.js.nft.json +1 -1
  23. package/.next/server/app/api/agent/[id]/route.js +1 -1
  24. package/.next/server/app/api/agent/[id]/route.js.nft.json +1 -1
  25. package/.next/server/app/api/agent/[id]/tree/route.js +1 -1
  26. package/.next/server/app/api/agent/[id]/tree/route.js.nft.json +1 -1
  27. package/.next/server/app/api/agent/new/route.js +1 -1
  28. package/.next/server/app/api/agent/new/route.js.nft.json +1 -1
  29. package/.next/server/app/api/config/route.js +1 -1
  30. package/.next/server/app/api/files/route.js +1 -1
  31. package/.next/server/app/api/git/route.js +2 -2
  32. package/.next/server/app/api/growth/route.js +1 -1
  33. package/.next/server/app/api/growth/route.js.nft.json +1 -1
  34. package/.next/server/app/api/health/route.js +1 -1
  35. package/.next/server/app/api/models/route.js +1 -1
  36. package/.next/server/app/api/models/route.js.nft.json +1 -1
  37. package/.next/server/app/api/pi-settings/route.js +1 -1
  38. package/.next/server/app/api/pi-settings/route.js.nft.json +1 -1
  39. package/.next/server/app/api/plugins/route.js +1 -1
  40. package/.next/server/app/api/plugins/route.js.nft.json +1 -1
  41. package/.next/server/app/api/prompts/route.js +1 -1
  42. package/.next/server/app/api/prompts/route.js.nft.json +1 -1
  43. package/.next/server/app/api/security/route.js +1 -1
  44. package/.next/server/app/api/security/route.js.nft.json +1 -1
  45. package/.next/server/app/api/sessions/[id]/export/route.js +1 -1
  46. package/.next/server/app/api/sessions/[id]/export/route.js.nft.json +1 -1
  47. package/.next/server/app/api/sessions/[id]/route.js +1 -1
  48. package/.next/server/app/api/sessions/[id]/route.js.nft.json +1 -1
  49. package/.next/server/app/api/sessions/import/route.js +6 -0
  50. package/.next/server/app/api/sessions/import/route.js.nft.json +1 -0
  51. package/.next/server/app/api/sessions/import/route_client-reference-manifest.js +1 -0
  52. package/.next/server/app/api/sessions/route.js +1 -1
  53. package/.next/server/app/api/sessions/route.js.nft.json +1 -1
  54. package/.next/server/app/api/skills/route.js +1 -1
  55. package/.next/server/app/api/skills/route.js.nft.json +1 -1
  56. package/.next/server/app/api/update/route.js +2 -2
  57. package/.next/server/app/api/update/route.js.nft.json +1 -1
  58. package/.next/server/app/api/version/route.js +1 -1
  59. package/.next/server/app/api/web-auth/route.js +1 -1
  60. package/.next/server/app/api/workspaces/route.js +1 -1
  61. package/.next/server/app/api/workspaces/route.js.nft.json +1 -1
  62. package/.next/server/app/icon.svg/route.js +1 -1
  63. package/.next/server/app/index.html +1 -1
  64. package/.next/server/app/index.rsc +3 -3
  65. package/.next/server/app/index.segments/__PAGE__.segment.rsc +3 -3
  66. package/.next/server/app/index.segments/_full.segment.rsc +3 -3
  67. package/.next/server/app/index.segments/_tree.segment.rsc +1 -1
  68. package/.next/server/app/login/page.js +1 -1
  69. package/.next/server/app/login/page_client-reference-manifest.js +1 -1
  70. package/.next/server/app/login.html +1 -1
  71. package/.next/server/app/login.rsc +2 -2
  72. package/.next/server/app/login.segments/_full.segment.rsc +2 -2
  73. package/.next/server/app/login.segments/_tree.segment.rsc +1 -1
  74. package/.next/server/app/login.segments/login/__PAGE__.segment.rsc +2 -2
  75. package/.next/server/app/page.js +1 -1
  76. package/.next/server/app/page_client-reference-manifest.js +1 -1
  77. package/.next/server/app-paths-manifest.json +6 -5
  78. package/.next/server/chunks/496.js +1 -1
  79. package/.next/server/chunks/532.js +1 -0
  80. package/.next/server/chunks/686.js +2 -2
  81. package/.next/server/middleware-build-manifest.js +1 -1
  82. package/.next/server/middleware-react-loadable-manifest.js +1 -1
  83. package/.next/server/pages/404.html +1 -1
  84. package/.next/server/pages/500.html +1 -1
  85. package/.next/server/server-reference-manifest.json +1 -1
  86. package/.next/static/chunks/4632.d574c210ad78d065.js +1 -0
  87. package/.next/static/chunks/4686-0a4155f8488314b8.js +1 -0
  88. package/.next/static/chunks/app/_global-error/page-f77e9ede9808b18e.js +1 -0
  89. package/.next/static/chunks/app/api/agent/[id]/events/route-f77e9ede9808b18e.js +1 -0
  90. package/.next/static/chunks/app/api/agent/[id]/route-f77e9ede9808b18e.js +1 -0
  91. package/.next/static/chunks/app/api/agent/[id]/tree/route-f77e9ede9808b18e.js +1 -0
  92. package/.next/static/chunks/app/api/agent/new/route-f77e9ede9808b18e.js +1 -0
  93. package/.next/static/chunks/app/api/config/route-f77e9ede9808b18e.js +1 -0
  94. package/.next/static/chunks/app/api/files/route-f77e9ede9808b18e.js +1 -0
  95. package/.next/static/chunks/app/api/git/route-f77e9ede9808b18e.js +1 -0
  96. package/.next/static/chunks/app/api/growth/route-f77e9ede9808b18e.js +1 -0
  97. package/.next/static/chunks/app/api/health/route-f77e9ede9808b18e.js +1 -0
  98. package/.next/static/chunks/app/api/models/route-f77e9ede9808b18e.js +1 -0
  99. package/.next/static/chunks/app/api/pi-settings/route-f77e9ede9808b18e.js +1 -0
  100. package/.next/static/chunks/app/api/plugins/route-f77e9ede9808b18e.js +1 -0
  101. package/.next/static/chunks/app/api/prompts/route-f77e9ede9808b18e.js +1 -0
  102. package/.next/static/chunks/app/api/security/route-f77e9ede9808b18e.js +1 -0
  103. package/.next/static/chunks/app/api/sessions/[id]/export/route-f77e9ede9808b18e.js +1 -0
  104. package/.next/static/chunks/app/api/sessions/[id]/route-f77e9ede9808b18e.js +1 -0
  105. package/.next/static/chunks/app/api/sessions/import/route-f77e9ede9808b18e.js +1 -0
  106. package/.next/static/chunks/app/api/sessions/route-f77e9ede9808b18e.js +1 -0
  107. package/.next/static/chunks/app/api/skills/route-f77e9ede9808b18e.js +1 -0
  108. package/.next/static/chunks/app/api/update/route-f77e9ede9808b18e.js +1 -0
  109. package/.next/static/chunks/app/api/version/route-f77e9ede9808b18e.js +1 -0
  110. package/.next/static/chunks/app/api/web-auth/route-f77e9ede9808b18e.js +1 -0
  111. package/.next/static/chunks/app/api/workspaces/route-f77e9ede9808b18e.js +1 -0
  112. package/.next/static/chunks/app/page-9a5440047c5a415c.js +1 -0
  113. package/.next/static/chunks/next/dist/client/components/builtin/app-error-f77e9ede9808b18e.js +1 -0
  114. package/.next/static/chunks/next/dist/client/components/builtin/forbidden-f77e9ede9808b18e.js +1 -0
  115. package/.next/static/chunks/next/dist/client/components/builtin/not-found-f77e9ede9808b18e.js +1 -0
  116. package/.next/static/chunks/next/dist/client/components/builtin/unauthorized-f77e9ede9808b18e.js +1 -0
  117. package/.next/static/chunks/{webpack-05a9e85529a18b93.js → webpack-b1a572e319353f5d.js} +1 -1
  118. package/.next/static/olV7jxKRN5VhfEK012WhV/_buildManifest.js +1 -0
  119. package/.next/types/app/api/sessions/import/route.ts +353 -0
  120. package/.next/types/routes.d.ts +2 -1
  121. package/.next/types/validator.ts +9 -0
  122. package/README.md +4 -0
  123. package/package.json +1 -1
  124. package/src/app/api/sessions/import/route.ts +74 -0
  125. package/src/components/PromptPanel.tsx +33 -31
  126. package/src/components/SessionImportSection.tsx +333 -0
  127. package/src/components/SettingsPanel.tsx +4 -1
  128. package/src/i18n.tsx +66 -6
  129. package/src/lib/prompt-sources.ts +29 -1
  130. package/src/lib/session-import/claude.ts +219 -0
  131. package/src/lib/session-import/codex.ts +206 -0
  132. package/src/lib/session-import/dsh-zstd.ts +69 -0
  133. package/src/lib/session-import/dsh.ts +248 -0
  134. package/src/lib/session-import/files.ts +84 -0
  135. package/src/lib/session-import/grok.ts +166 -0
  136. package/src/lib/session-import/index.ts +229 -0
  137. package/src/lib/session-import/oc-family.ts +275 -0
  138. package/src/lib/session-import/opencode.ts +7 -0
  139. package/src/lib/session-import/paths.ts +37 -0
  140. package/src/lib/session-import/sqlite.ts +89 -0
  141. package/src/lib/session-import/types.ts +171 -0
  142. package/src/lib/session-import/writer.ts +259 -0
  143. package/src/lib/session-import/zcode.ts +8 -0
  144. package/.next/server/chunks/118.js +0 -1
  145. package/.next/static/2kt2UiWjv_viXpNlfjvBT/_buildManifest.js +0 -1
  146. package/.next/static/chunks/4127.dff5c3b33c6bfd1b.js +0 -1
  147. package/.next/static/chunks/4686-5bbee099126af797.js +0 -1
  148. package/.next/static/chunks/app/_global-error/page-961c055baebb3872.js +0 -1
  149. package/.next/static/chunks/app/api/agent/[id]/events/route-961c055baebb3872.js +0 -1
  150. package/.next/static/chunks/app/api/agent/[id]/route-961c055baebb3872.js +0 -1
  151. package/.next/static/chunks/app/api/agent/[id]/tree/route-961c055baebb3872.js +0 -1
  152. package/.next/static/chunks/app/api/agent/new/route-961c055baebb3872.js +0 -1
  153. package/.next/static/chunks/app/api/config/route-961c055baebb3872.js +0 -1
  154. package/.next/static/chunks/app/api/files/route-961c055baebb3872.js +0 -1
  155. package/.next/static/chunks/app/api/git/route-961c055baebb3872.js +0 -1
  156. package/.next/static/chunks/app/api/growth/route-961c055baebb3872.js +0 -1
  157. package/.next/static/chunks/app/api/health/route-961c055baebb3872.js +0 -1
  158. package/.next/static/chunks/app/api/models/route-961c055baebb3872.js +0 -1
  159. package/.next/static/chunks/app/api/pi-settings/route-961c055baebb3872.js +0 -1
  160. package/.next/static/chunks/app/api/plugins/route-961c055baebb3872.js +0 -1
  161. package/.next/static/chunks/app/api/prompts/route-961c055baebb3872.js +0 -1
  162. package/.next/static/chunks/app/api/security/route-961c055baebb3872.js +0 -1
  163. package/.next/static/chunks/app/api/sessions/[id]/export/route-961c055baebb3872.js +0 -1
  164. package/.next/static/chunks/app/api/sessions/[id]/route-961c055baebb3872.js +0 -1
  165. package/.next/static/chunks/app/api/sessions/route-961c055baebb3872.js +0 -1
  166. package/.next/static/chunks/app/api/skills/route-961c055baebb3872.js +0 -1
  167. package/.next/static/chunks/app/api/update/route-961c055baebb3872.js +0 -1
  168. package/.next/static/chunks/app/api/version/route-961c055baebb3872.js +0 -1
  169. package/.next/static/chunks/app/api/web-auth/route-961c055baebb3872.js +0 -1
  170. package/.next/static/chunks/app/api/workspaces/route-961c055baebb3872.js +0 -1
  171. package/.next/static/chunks/app/page-00c8ebf40ec5eaca.js +0 -1
  172. package/.next/static/chunks/next/dist/client/components/builtin/app-error-961c055baebb3872.js +0 -1
  173. package/.next/static/chunks/next/dist/client/components/builtin/forbidden-961c055baebb3872.js +0 -1
  174. package/.next/static/chunks/next/dist/client/components/builtin/not-found-961c055baebb3872.js +0 -1
  175. package/.next/static/chunks/next/dist/client/components/builtin/unauthorized-961c055baebb3872.js +0 -1
  176. /package/.next/static/{2kt2UiWjv_viXpNlfjvBT → olV7jxKRN5VhfEK012WhV}/_ssgManifest.js +0 -0
@@ -1 +1 @@
1
- (()=>{"use strict";var e,t,r,o,n,a,i,l,c,u={},s={};function f(e){var t=s[e];if(void 0!==t)return t.exports;var r=s[e]={exports:{}},o=!0;try{u[e].call(r.exports,r,r.exports,f),o=!1}finally{o&&delete s[e]}return r.exports}f.m=u,e=[],f.O=(t,r,o,n)=>{if(r){n=n||0;for(var a=e.length;a>0&&e[a-1][2]>n;a--)e[a]=e[a-1];e[a]=[r,o,n];return}for(var i=1/0,a=0;a<e.length;a++){for(var[r,o,n]=e[a],l=!0,c=0;c<r.length;c++)(!1&n||i>=n)&&Object.keys(f.O).every(e=>f.O[e](r[c]))?r.splice(c--,1):(l=!1,n<i&&(i=n));if(l){e.splice(a--,1);var u=o();void 0!==u&&(t=u)}}return t},f.n=e=>{var t=e&&e.__esModule?()=>e.default:()=>e;return f.d(t,{a:t}),t},r=Object.getPrototypeOf?e=>Object.getPrototypeOf(e):e=>e.__proto__,f.t=function(e,o){if(1&o&&(e=this(e)),8&o||"object"==typeof e&&e&&(4&o&&e.__esModule||16&o&&"function"==typeof e.then))return e;var n=Object.create(null);f.r(n);var a={};t=t||[null,r({}),r([]),r(r)];for(var i=2&o&&e;"object"==typeof i&&!~t.indexOf(i);i=r(i))Object.getOwnPropertyNames(i).forEach(t=>a[t]=()=>e[t]);return a.default=()=>e,f.d(n,a),n},f.d=(e,t)=>{for(var r in t)f.o(t,r)&&!f.o(e,r)&&Object.defineProperty(e,r,{enumerable:!0,get:t[r]})},f.f={},f.e=e=>Promise.all(Object.keys(f.f).reduce((t,r)=>(f.f[r](e,t),t),[])),f.u=e=>"static/chunks/"+e+"."+({618:"ee5d5bf1c647e483",2155:"2f27fe7098987699",2608:"ec8ff1f5767c9056",2716:"a9e808190a4e2424",4127:"dff5c3b33c6bfd1b",4673:"d3d0a7f2599080fb"})[e]+".js",f.miniCssF=e=>"static/css/"+({7250:"08815507594e8b8d",8114:"2959bd6b626b7ffe"})[e]+".css",f.g=function(){if("object"==typeof globalThis)return globalThis;try{return this||Function("return this")()}catch(e){if("object"==typeof window)return window}}(),f.o=(e,t)=>Object.prototype.hasOwnProperty.call(e,t),o={},f.l=(e,t,r,n)=>{if(o[e])return void o[e].push(t);if(void 0!==r)for(var a,i,l=document.getElementsByTagName("script"),c=0;c<l.length;c++){var u=l[c];if(u.getAttribute("src")==e||u.getAttribute("data-webpack")=="_N_E:"+r){a=u;break}}a||(i=!0,(a=document.createElement("script")).charset="utf-8",a.timeout=120,f.nc&&a.setAttribute("nonce",f.nc),a.setAttribute("data-webpack","_N_E:"+r),a.src=f.tu(e)),o[e]=[t];var s=(t,r)=>{a.onerror=a.onload=null,clearTimeout(d);var n=o[e];if(delete o[e],a.parentNode&&a.parentNode.removeChild(a),n&&n.forEach(e=>e(r)),t)return t(r)},d=setTimeout(s.bind(null,void 0,{type:"timeout",target:a}),12e4);a.onerror=s.bind(null,a.onerror),a.onload=s.bind(null,a.onload),i&&document.head.appendChild(a)},f.r=e=>{"u">typeof Symbol&&Symbol.toStringTag&&Object.defineProperty(e,Symbol.toStringTag,{value:"Module"}),Object.defineProperty(e,"__esModule",{value:!0})},f.tt=()=>(void 0===n&&(n={createScriptURL:e=>e},"u">typeof trustedTypes&&trustedTypes.createPolicy&&(n=trustedTypes.createPolicy("nextjs#bundler",n))),n),f.tu=e=>f.tt().createScriptURL(e),f.p="/_next/",a={8068:0},f.f.miniCss=(e,t)=>{if(a[e])t.push(a[e]);else 0!==a[e]&&({7250:1,8114:1})[e]&&t.push(a[e]=new Promise((t,r)=>{var o=f.miniCssF(e),n=f.p+o;if(((e,t)=>{for(var r=document.getElementsByTagName("link"),o=0;o<r.length;o++){var n=r[o],a=n.getAttribute("data-href")||n.getAttribute("href");if("stylesheet"===n.rel&&(a===e||a===t))return n}for(var i=document.getElementsByTagName("style"),o=0;o<i.length;o++){var n=i[o],a=n.getAttribute("data-href");if(a===e||a===t)return n}})(o,n))return t();((e,t,r,o)=>{var n=document.createElement("link");n.rel="stylesheet",n.type="text/css",n.onerror=n.onload=a=>{if(n.onerror=n.onload=null,"load"===a.type)r();else{var i=a&&("load"===a.type?"missing":a.type),l=a&&a.target&&a.target.href||t,c=Error("Loading CSS chunk "+e+" failed.\n("+l+")");c.code="CSS_CHUNK_LOAD_FAILED",c.type=i,c.request=l,n.parentNode.removeChild(n),o(c)}},n.href=t;if("function"==typeof _N_E_STYLE_LOAD){var a=n.href,i=n.onload,l=n.onerror;_N_E_STYLE_LOAD(0===a.indexOf(window.location.origin)?new URL(a).pathname:a).then(function(){i&&i.call(n,{type:"load"})},function(){l&&l.call(n,{})})}else document.head.appendChild(n)})(e,n,t,r)}).then(()=>{a[e]=0},t=>{throw delete a[e],t}))},i={8068:0,5483:0,7086:0,3334:0},f.f.j=(e,t)=>{var r=f.o(i,e)?i[e]:void 0;if(0!==r)if(r)t.push(r[2]);else if(/^(3334|5483|7086|7250|8068|8114)$/.test(e))i[e]=0;else{var o=new Promise((t,o)=>r=i[e]=[t,o]);t.push(r[2]=o);var n=f.p+f.u(e),a=Error();f.l(n,t=>{if(f.o(i,e)&&(0!==(r=i[e])&&(i[e]=void 0),r)){var o=t&&("load"===t.type?"missing":t.type),n=t&&t.target&&t.target.src;a.message="Loading chunk "+e+" failed.\n("+o+": "+n+")",a.name="ChunkLoadError",a.type=o,a.request=n,r[1](a)}},"chunk-"+e,e)}},f.O.j=e=>0===i[e],l=(e,t)=>{var r,o,[n,a,l]=t,c=0;if(n.some(e=>0!==i[e])){for(r in a)f.o(a,r)&&(f.m[r]=a[r]);if(l)var u=l(f)}for(e&&e(t);c<n.length;c++)o=n[c],f.o(i,o)&&i[o]&&i[o][0](),i[o]=0;return f.O(u)},(c=self.webpackChunk_N_E=self.webpackChunk_N_E||[]).forEach(l.bind(null,0)),c.push=l.bind(null,c.push.bind(c))})();
1
+ (()=>{"use strict";var e,t,r,o,n,a,i,l,c,u={},s={};function d(e){var t=s[e];if(void 0!==t)return t.exports;var r=s[e]={exports:{}},o=!0;try{u[e].call(r.exports,r,r.exports,d),o=!1}finally{o&&delete s[e]}return r.exports}d.m=u,e=[],d.O=(t,r,o,n)=>{if(r){n=n||0;for(var a=e.length;a>0&&e[a-1][2]>n;a--)e[a]=e[a-1];e[a]=[r,o,n];return}for(var i=1/0,a=0;a<e.length;a++){for(var[r,o,n]=e[a],l=!0,c=0;c<r.length;c++)(!1&n||i>=n)&&Object.keys(d.O).every(e=>d.O[e](r[c]))?r.splice(c--,1):(l=!1,n<i&&(i=n));if(l){e.splice(a--,1);var u=o();void 0!==u&&(t=u)}}return t},d.n=e=>{var t=e&&e.__esModule?()=>e.default:()=>e;return d.d(t,{a:t}),t},r=Object.getPrototypeOf?e=>Object.getPrototypeOf(e):e=>e.__proto__,d.t=function(e,o){if(1&o&&(e=this(e)),8&o||"object"==typeof e&&e&&(4&o&&e.__esModule||16&o&&"function"==typeof e.then))return e;var n=Object.create(null);d.r(n);var a={};t=t||[null,r({}),r([]),r(r)];for(var i=2&o&&e;"object"==typeof i&&!~t.indexOf(i);i=r(i))Object.getOwnPropertyNames(i).forEach(t=>a[t]=()=>e[t]);return a.default=()=>e,d.d(n,a),n},d.d=(e,t)=>{for(var r in t)d.o(t,r)&&!d.o(e,r)&&Object.defineProperty(e,r,{enumerable:!0,get:t[r]})},d.f={},d.e=e=>Promise.all(Object.keys(d.f).reduce((t,r)=>(d.f[r](e,t),t),[])),d.u=e=>"static/chunks/"+e+"."+({618:"ee5d5bf1c647e483",2155:"2f27fe7098987699",2608:"ec8ff1f5767c9056",2716:"a9e808190a4e2424",4632:"d574c210ad78d065",4673:"d3d0a7f2599080fb"})[e]+".js",d.miniCssF=e=>"static/css/"+({7250:"08815507594e8b8d",8114:"2959bd6b626b7ffe"})[e]+".css",d.g=function(){if("object"==typeof globalThis)return globalThis;try{return this||Function("return this")()}catch(e){if("object"==typeof window)return window}}(),d.o=(e,t)=>Object.prototype.hasOwnProperty.call(e,t),o={},d.l=(e,t,r,n)=>{if(o[e])return void o[e].push(t);if(void 0!==r)for(var a,i,l=document.getElementsByTagName("script"),c=0;c<l.length;c++){var u=l[c];if(u.getAttribute("src")==e||u.getAttribute("data-webpack")=="_N_E:"+r){a=u;break}}a||(i=!0,(a=document.createElement("script")).charset="utf-8",a.timeout=120,d.nc&&a.setAttribute("nonce",d.nc),a.setAttribute("data-webpack","_N_E:"+r),a.src=d.tu(e)),o[e]=[t];var s=(t,r)=>{a.onerror=a.onload=null,clearTimeout(f);var n=o[e];if(delete o[e],a.parentNode&&a.parentNode.removeChild(a),n&&n.forEach(e=>e(r)),t)return t(r)},f=setTimeout(s.bind(null,void 0,{type:"timeout",target:a}),12e4);a.onerror=s.bind(null,a.onerror),a.onload=s.bind(null,a.onload),i&&document.head.appendChild(a)},d.r=e=>{"u">typeof Symbol&&Symbol.toStringTag&&Object.defineProperty(e,Symbol.toStringTag,{value:"Module"}),Object.defineProperty(e,"__esModule",{value:!0})},d.tt=()=>(void 0===n&&(n={createScriptURL:e=>e},"u">typeof trustedTypes&&trustedTypes.createPolicy&&(n=trustedTypes.createPolicy("nextjs#bundler",n))),n),d.tu=e=>d.tt().createScriptURL(e),d.p="/_next/",a={8068:0},d.f.miniCss=(e,t)=>{if(a[e])t.push(a[e]);else 0!==a[e]&&({7250:1,8114:1})[e]&&t.push(a[e]=new Promise((t,r)=>{var o=d.miniCssF(e),n=d.p+o;if(((e,t)=>{for(var r=document.getElementsByTagName("link"),o=0;o<r.length;o++){var n=r[o],a=n.getAttribute("data-href")||n.getAttribute("href");if("stylesheet"===n.rel&&(a===e||a===t))return n}for(var i=document.getElementsByTagName("style"),o=0;o<i.length;o++){var n=i[o],a=n.getAttribute("data-href");if(a===e||a===t)return n}})(o,n))return t();((e,t,r,o)=>{var n=document.createElement("link");n.rel="stylesheet",n.type="text/css",n.onerror=n.onload=a=>{if(n.onerror=n.onload=null,"load"===a.type)r();else{var i=a&&("load"===a.type?"missing":a.type),l=a&&a.target&&a.target.href||t,c=Error("Loading CSS chunk "+e+" failed.\n("+l+")");c.code="CSS_CHUNK_LOAD_FAILED",c.type=i,c.request=l,n.parentNode.removeChild(n),o(c)}},n.href=t;if("function"==typeof _N_E_STYLE_LOAD){var a=n.href,i=n.onload,l=n.onerror;_N_E_STYLE_LOAD(0===a.indexOf(window.location.origin)?new URL(a).pathname:a).then(function(){i&&i.call(n,{type:"load"})},function(){l&&l.call(n,{})})}else document.head.appendChild(n)})(e,n,t,r)}).then(()=>{a[e]=0},t=>{throw delete a[e],t}))},i={8068:0,5483:0,7086:0,3334:0},d.f.j=(e,t)=>{var r=d.o(i,e)?i[e]:void 0;if(0!==r)if(r)t.push(r[2]);else if(/^(3334|5483|7086|7250|8068|8114)$/.test(e))i[e]=0;else{var o=new Promise((t,o)=>r=i[e]=[t,o]);t.push(r[2]=o);var n=d.p+d.u(e),a=Error();d.l(n,t=>{if(d.o(i,e)&&(0!==(r=i[e])&&(i[e]=void 0),r)){var o=t&&("load"===t.type?"missing":t.type),n=t&&t.target&&t.target.src;a.message="Loading chunk "+e+" failed.\n("+o+": "+n+")",a.name="ChunkLoadError",a.type=o,a.request=n,r[1](a)}},"chunk-"+e,e)}},d.O.j=e=>0===i[e],l=(e,t)=>{var r,o,[n,a,l]=t,c=0;if(n.some(e=>0!==i[e])){for(r in a)d.o(a,r)&&(d.m[r]=a[r]);if(l)var u=l(d)}for(e&&e(t);c<n.length;c++)o=n[c],d.o(i,o)&&i[o]&&i[o][0](),i[o]=0;return d.O(u)},(c=self.webpackChunk_N_E=self.webpackChunk_N_E||[]).forEach(l.bind(null,0)),c.push=l.bind(null,c.push.bind(c))})();
@@ -0,0 +1 @@
1
+ self.__BUILD_MANIFEST={__rewrites:{afterFiles:[],beforeFiles:[],fallback:[]},__routerFilterStatic:{numItems:23,errorRate:1e-4,numBits:441,numHashes:14,bitArray:[1,0,1,0,0,0,0,1,0,1,1,1,1,0,1,0,1,1,1,0,0,1,0,0,0,0,1,0,1,0,0,1,0,0,1,0,1,0,1,0,0,0,1,1,1,0,0,0,1,1,1,0,1,1,0,0,1,1,0,1,1,1,0,1,1,0,0,1,0,1,0,0,1,0,1,1,1,1,1,0,0,1,1,0,0,1,1,1,0,0,1,0,1,1,1,0,0,0,0,1,1,0,0,0,1,0,1,0,1,0,1,0,0,1,0,0,0,0,0,0,0,0,1,1,0,0,0,0,1,0,1,1,0,1,1,1,0,1,0,0,0,1,0,0,1,0,0,0,0,0,1,0,1,1,0,1,0,1,0,1,1,1,1,0,0,1,0,1,1,0,1,1,1,1,1,0,1,0,1,1,0,0,0,0,1,1,0,0,1,1,0,0,1,0,1,1,0,0,0,1,1,0,1,0,0,1,0,0,1,1,1,1,1,1,1,0,0,0,0,1,1,0,1,1,1,1,0,0,1,1,1,1,0,0,1,1,0,1,0,1,0,1,0,0,0,0,1,0,1,1,0,0,1,0,1,0,0,1,0,1,1,1,0,1,0,1,1,0,1,1,1,1,1,1,1,0,1,1,0,0,0,0,1,1,0,0,0,0,0,1,1,1,1,0,1,0,0,1,1,1,1,1,0,0,0,1,1,1,0,0,0,1,1,1,1,1,1,0,0,0,1,1,0,1,0,1,0,0,1,1,0,1,1,0,0,0,1,1,0,1,0,0,1,0,0,1,1,1,1,1,0,1,0,0,0,0,0,1,1,0,0,0,0,1,1,1,0,0,0,0,0,1,1,0,0,0,0,0,0,0,1,0,0,0,1,1,1,1,1,0,0,1,0,0,1,0,1,1,0,1,0,1,1,0,0,1,1,1,0,1,1,0,0,0,1,0,1,0,0,1,1,1,0,0,1,1,1,1,0,1,1,1,0,1,0,1,1,1,0,1,0]},__routerFilterDynamic:{numItems:2,errorRate:1e-4,numBits:39,numHashes:14,bitArray:[1,0,1,0,0,0,0,0,1,1,0,1,1,1,1,1,0,0,1,0,0,1,0,0,0,1,0,1,1,0,1,1,0,1,0,1,1,0,0]},sortedPages:["/_app"]},self.__BUILD_MANIFEST_CB&&self.__BUILD_MANIFEST_CB();
@@ -0,0 +1,353 @@
1
+ // File: /home/runner/work/PiWeb/PiWeb/src/app/api/sessions/import/route.ts
2
+ import * as entry from '../../../../../../src/app/api/sessions/import/route.js'
3
+ import type { NextRequest } from 'next/server.js'
4
+
5
+ import type { InstantConfigForTypeCheckInternal, Prefetch } from 'next/dist/build/segment-config/app/app-segment-config.js'
6
+
7
+ type TEntry = typeof import('../../../../../../src/app/api/sessions/import/route.js')
8
+
9
+ type SegmentParams<T extends Object = any> = T extends Record<string, any>
10
+ ? { [K in keyof T]: T[K] extends string ? string | string[] | undefined : never }
11
+ : T
12
+
13
+ // Check that the entry is a valid entry
14
+ checkFields<Diff<{
15
+ GET?: Function
16
+ HEAD?: Function
17
+ OPTIONS?: Function
18
+ POST?: Function
19
+ PUT?: Function
20
+ DELETE?: Function
21
+ PATCH?: Function
22
+ config?: {}
23
+ generateStaticParams?: Function
24
+ instant?: InstantConfigForTypeCheckInternal
25
+ prefetch?: Prefetch
26
+ unstable_dynamicStaleTime?: number
27
+ revalidate?: RevalidateRange<TEntry> | false
28
+ dynamic?: 'auto' | 'force-dynamic' | 'error' | 'force-static'
29
+ dynamicParams?: boolean
30
+ fetchCache?: 'auto' | 'force-no-store' | 'only-no-store' | 'default-no-store' | 'default-cache' | 'only-cache' | 'force-cache'
31
+ /** @deprecated The `preferredRegion` config is deprecated. Remove this export. */
32
+ preferredRegion?: 'auto' | 'global' | 'home' | string | string[]
33
+ runtime?: 'nodejs' | 'experimental-edge' | 'edge'
34
+ maxDuration?: number
35
+
36
+ }, TEntry, ''>>()
37
+
38
+ type RouteContext = { params: Promise<SegmentParams> }
39
+ // Check the prop type of the entry function
40
+ if ('GET' in entry) {
41
+ checkFields<
42
+ Diff<
43
+ ParamCheck<Request | NextRequest>,
44
+ {
45
+ __tag__: 'GET'
46
+ __param_position__: 'first'
47
+ __param_type__: FirstArg<MaybeField<TEntry, 'GET'>>
48
+ },
49
+ 'GET'
50
+ >
51
+ >()
52
+ checkFields<
53
+ Diff<
54
+ ParamCheck<RouteContext>,
55
+ {
56
+ __tag__: 'GET'
57
+ __param_position__: 'second'
58
+ __param_type__: SecondArg<MaybeField<TEntry, 'GET'>>
59
+ },
60
+ 'GET'
61
+ >
62
+ >()
63
+
64
+ checkFields<
65
+ Diff<
66
+ {
67
+ __tag__: 'GET',
68
+ __return_type__: Response | void | never | Promise<Response | void | never>
69
+ },
70
+ {
71
+ __tag__: 'GET',
72
+ __return_type__: ReturnType<MaybeField<TEntry, 'GET'>>
73
+ },
74
+ 'GET'
75
+ >
76
+ >()
77
+ }
78
+ // Check the prop type of the entry function
79
+ if ('HEAD' in entry) {
80
+ checkFields<
81
+ Diff<
82
+ ParamCheck<Request | NextRequest>,
83
+ {
84
+ __tag__: 'HEAD'
85
+ __param_position__: 'first'
86
+ __param_type__: FirstArg<MaybeField<TEntry, 'HEAD'>>
87
+ },
88
+ 'HEAD'
89
+ >
90
+ >()
91
+ checkFields<
92
+ Diff<
93
+ ParamCheck<RouteContext>,
94
+ {
95
+ __tag__: 'HEAD'
96
+ __param_position__: 'second'
97
+ __param_type__: SecondArg<MaybeField<TEntry, 'HEAD'>>
98
+ },
99
+ 'HEAD'
100
+ >
101
+ >()
102
+
103
+ checkFields<
104
+ Diff<
105
+ {
106
+ __tag__: 'HEAD',
107
+ __return_type__: Response | void | never | Promise<Response | void | never>
108
+ },
109
+ {
110
+ __tag__: 'HEAD',
111
+ __return_type__: ReturnType<MaybeField<TEntry, 'HEAD'>>
112
+ },
113
+ 'HEAD'
114
+ >
115
+ >()
116
+ }
117
+ // Check the prop type of the entry function
118
+ if ('OPTIONS' in entry) {
119
+ checkFields<
120
+ Diff<
121
+ ParamCheck<Request | NextRequest>,
122
+ {
123
+ __tag__: 'OPTIONS'
124
+ __param_position__: 'first'
125
+ __param_type__: FirstArg<MaybeField<TEntry, 'OPTIONS'>>
126
+ },
127
+ 'OPTIONS'
128
+ >
129
+ >()
130
+ checkFields<
131
+ Diff<
132
+ ParamCheck<RouteContext>,
133
+ {
134
+ __tag__: 'OPTIONS'
135
+ __param_position__: 'second'
136
+ __param_type__: SecondArg<MaybeField<TEntry, 'OPTIONS'>>
137
+ },
138
+ 'OPTIONS'
139
+ >
140
+ >()
141
+
142
+ checkFields<
143
+ Diff<
144
+ {
145
+ __tag__: 'OPTIONS',
146
+ __return_type__: Response | void | never | Promise<Response | void | never>
147
+ },
148
+ {
149
+ __tag__: 'OPTIONS',
150
+ __return_type__: ReturnType<MaybeField<TEntry, 'OPTIONS'>>
151
+ },
152
+ 'OPTIONS'
153
+ >
154
+ >()
155
+ }
156
+ // Check the prop type of the entry function
157
+ if ('POST' in entry) {
158
+ checkFields<
159
+ Diff<
160
+ ParamCheck<Request | NextRequest>,
161
+ {
162
+ __tag__: 'POST'
163
+ __param_position__: 'first'
164
+ __param_type__: FirstArg<MaybeField<TEntry, 'POST'>>
165
+ },
166
+ 'POST'
167
+ >
168
+ >()
169
+ checkFields<
170
+ Diff<
171
+ ParamCheck<RouteContext>,
172
+ {
173
+ __tag__: 'POST'
174
+ __param_position__: 'second'
175
+ __param_type__: SecondArg<MaybeField<TEntry, 'POST'>>
176
+ },
177
+ 'POST'
178
+ >
179
+ >()
180
+
181
+ checkFields<
182
+ Diff<
183
+ {
184
+ __tag__: 'POST',
185
+ __return_type__: Response | void | never | Promise<Response | void | never>
186
+ },
187
+ {
188
+ __tag__: 'POST',
189
+ __return_type__: ReturnType<MaybeField<TEntry, 'POST'>>
190
+ },
191
+ 'POST'
192
+ >
193
+ >()
194
+ }
195
+ // Check the prop type of the entry function
196
+ if ('PUT' in entry) {
197
+ checkFields<
198
+ Diff<
199
+ ParamCheck<Request | NextRequest>,
200
+ {
201
+ __tag__: 'PUT'
202
+ __param_position__: 'first'
203
+ __param_type__: FirstArg<MaybeField<TEntry, 'PUT'>>
204
+ },
205
+ 'PUT'
206
+ >
207
+ >()
208
+ checkFields<
209
+ Diff<
210
+ ParamCheck<RouteContext>,
211
+ {
212
+ __tag__: 'PUT'
213
+ __param_position__: 'second'
214
+ __param_type__: SecondArg<MaybeField<TEntry, 'PUT'>>
215
+ },
216
+ 'PUT'
217
+ >
218
+ >()
219
+
220
+ checkFields<
221
+ Diff<
222
+ {
223
+ __tag__: 'PUT',
224
+ __return_type__: Response | void | never | Promise<Response | void | never>
225
+ },
226
+ {
227
+ __tag__: 'PUT',
228
+ __return_type__: ReturnType<MaybeField<TEntry, 'PUT'>>
229
+ },
230
+ 'PUT'
231
+ >
232
+ >()
233
+ }
234
+ // Check the prop type of the entry function
235
+ if ('DELETE' in entry) {
236
+ checkFields<
237
+ Diff<
238
+ ParamCheck<Request | NextRequest>,
239
+ {
240
+ __tag__: 'DELETE'
241
+ __param_position__: 'first'
242
+ __param_type__: FirstArg<MaybeField<TEntry, 'DELETE'>>
243
+ },
244
+ 'DELETE'
245
+ >
246
+ >()
247
+ checkFields<
248
+ Diff<
249
+ ParamCheck<RouteContext>,
250
+ {
251
+ __tag__: 'DELETE'
252
+ __param_position__: 'second'
253
+ __param_type__: SecondArg<MaybeField<TEntry, 'DELETE'>>
254
+ },
255
+ 'DELETE'
256
+ >
257
+ >()
258
+
259
+ checkFields<
260
+ Diff<
261
+ {
262
+ __tag__: 'DELETE',
263
+ __return_type__: Response | void | never | Promise<Response | void | never>
264
+ },
265
+ {
266
+ __tag__: 'DELETE',
267
+ __return_type__: ReturnType<MaybeField<TEntry, 'DELETE'>>
268
+ },
269
+ 'DELETE'
270
+ >
271
+ >()
272
+ }
273
+ // Check the prop type of the entry function
274
+ if ('PATCH' in entry) {
275
+ checkFields<
276
+ Diff<
277
+ ParamCheck<Request | NextRequest>,
278
+ {
279
+ __tag__: 'PATCH'
280
+ __param_position__: 'first'
281
+ __param_type__: FirstArg<MaybeField<TEntry, 'PATCH'>>
282
+ },
283
+ 'PATCH'
284
+ >
285
+ >()
286
+ checkFields<
287
+ Diff<
288
+ ParamCheck<RouteContext>,
289
+ {
290
+ __tag__: 'PATCH'
291
+ __param_position__: 'second'
292
+ __param_type__: SecondArg<MaybeField<TEntry, 'PATCH'>>
293
+ },
294
+ 'PATCH'
295
+ >
296
+ >()
297
+
298
+ checkFields<
299
+ Diff<
300
+ {
301
+ __tag__: 'PATCH',
302
+ __return_type__: Response | void | never | Promise<Response | void | never>
303
+ },
304
+ {
305
+ __tag__: 'PATCH',
306
+ __return_type__: ReturnType<MaybeField<TEntry, 'PATCH'>>
307
+ },
308
+ 'PATCH'
309
+ >
310
+ >()
311
+ }
312
+
313
+ // Check the arguments and return type of the generateStaticParams function
314
+ if ('generateStaticParams' in entry) {
315
+ checkFields<Diff<{ params: SegmentParams }, FirstArg<MaybeField<TEntry, 'generateStaticParams'>>, 'generateStaticParams'>>()
316
+ checkFields<Diff<{ __tag__: 'generateStaticParams', __return_type__: any[] | Promise<any[]> }, { __tag__: 'generateStaticParams', __return_type__: ReturnType<MaybeField<TEntry, 'generateStaticParams'>> }>>()
317
+ }
318
+
319
+ export interface PageProps {
320
+ params?: Promise<SegmentParams>
321
+ searchParams?: Promise<any>
322
+ }
323
+ export interface LayoutProps {
324
+ children?: React.ReactNode
325
+
326
+ params?: Promise<SegmentParams>
327
+ }
328
+
329
+ // =============
330
+ // Utility types
331
+ type RevalidateRange<T> = T extends { revalidate: any } ? NonNegative<T['revalidate']> : never
332
+
333
+ // If T is unknown or any, it will be an empty {} type. Otherwise, it will be the same as Omit<T, keyof Base>.
334
+ type OmitWithTag<T, K extends keyof any, _M> = Omit<T, K>
335
+ type Diff<Base, T extends Base, Message extends string = ''> = 0 extends (1 & T) ? {} : OmitWithTag<T, keyof Base, Message>
336
+
337
+ type FirstArg<T extends Function> = T extends (...args: [infer T, any]) => any ? unknown extends T ? any : T : never
338
+ type SecondArg<T extends Function> = T extends (...args: [any, infer T]) => any ? unknown extends T ? any : T : never
339
+ type MaybeField<T, K extends string> = T extends { [k in K]: infer G } ? G extends Function ? G : never : never
340
+
341
+ type ParamCheck<T> = {
342
+ __tag__: string
343
+ __param_position__: string
344
+ __param_type__: T
345
+ }
346
+
347
+ function checkFields<_ extends { [k in keyof any]: never }>() {}
348
+
349
+ // https://github.com/sindresorhus/type-fest
350
+ type Numeric = number | bigint
351
+ type Zero = 0 | 0n
352
+ type Negative<T extends Numeric> = T extends Zero ? never : `${T}` extends `-${string}` ? T : never
353
+ type NonNegative<T extends Numeric> = T extends Zero ? T : Negative<T> extends never ? T : '__invalid_negative_number__'
@@ -2,7 +2,7 @@
2
2
  // Do not edit this file manually
3
3
 
4
4
  type AppRoutes = "/" | "/login"
5
- type AppRouteHandlerRoutes = "/api/agent/[id]" | "/api/agent/[id]/events" | "/api/agent/[id]/tree" | "/api/agent/new" | "/api/config" | "/api/files" | "/api/git" | "/api/growth" | "/api/health" | "/api/models" | "/api/pi-settings" | "/api/plugins" | "/api/prompts" | "/api/security" | "/api/sessions" | "/api/sessions/[id]" | "/api/sessions/[id]/export" | "/api/skills" | "/api/update" | "/api/version" | "/api/web-auth" | "/api/workspaces"
5
+ type AppRouteHandlerRoutes = "/api/agent/[id]" | "/api/agent/[id]/events" | "/api/agent/[id]/tree" | "/api/agent/new" | "/api/config" | "/api/files" | "/api/git" | "/api/growth" | "/api/health" | "/api/models" | "/api/pi-settings" | "/api/plugins" | "/api/prompts" | "/api/security" | "/api/sessions" | "/api/sessions/[id]" | "/api/sessions/[id]/export" | "/api/sessions/import" | "/api/skills" | "/api/update" | "/api/version" | "/api/web-auth" | "/api/workspaces"
6
6
  type PageRoutes = never
7
7
  type LayoutRoutes = "/"
8
8
  type RedirectRoutes = never
@@ -29,6 +29,7 @@ interface ParamMap {
29
29
  "/api/sessions": {}
30
30
  "/api/sessions/[id]": { "id": string; }
31
31
  "/api/sessions/[id]/export": { "id": string; }
32
+ "/api/sessions/import": {}
32
33
  "/api/skills": {}
33
34
  "/api/update": {}
34
35
  "/api/version": {}
@@ -209,6 +209,15 @@ type RouteHandlerConfig<Route extends AppRouteHandlerRoutes = AppRouteHandlerRou
209
209
  type __Unused = __Check
210
210
  }
211
211
 
212
+ // Validate ../../src/app/api/sessions/import/route.ts
213
+ {
214
+ type __IsExpected<Specific extends RouteHandlerConfig<"/api/sessions/import">> = Specific
215
+ const handler = {} as typeof import("../../src/app/api/sessions/import/route.js")
216
+ type __Check = __IsExpected<typeof handler>
217
+ // @ts-ignore
218
+ type __Unused = __Check
219
+ }
220
+
212
221
  // Validate ../../src/app/api/sessions/route.ts
213
222
  {
214
223
  type __IsExpected<Specific extends RouteHandlerConfig<"/api/sessions">> = Specific
package/README.md CHANGED
@@ -28,6 +28,10 @@ Full SSE snapshots with ordered deltas and automatic replay via `Last-Event-ID`.
28
28
 
29
29
  Sessions grouped by project folder, with a native folder picker (Windows / macOS / Linux), rename and archive. Session tree branches, draft recovery, and JSONL / HTML export.
30
30
 
31
+ ### Import Local Sessions
32
+
33
+ Bring conversation history from Codex, Claude Code, Grok, ZCode, dsh, and opencode on this machine into pi sessions without loss: text, thinking, tool calls and their results, timestamps, and usage are all kept, and the source data is **read-only** — nothing in the other tools is modified. If the original project directory still exists locally the session lands in that workspace; otherwise it falls back to one you pick. Find it under Settings → Import sessions. The 15 most recent conversations per source are listed, and anything already imported is marked and cannot be imported twice.
34
+
31
35
  ### Project Growth Tree
32
36
 
33
37
  Every step the agent takes on your codebase is snapshotted: navigate the timeline round by round, see added/modified/deleted files, and open line-level diffs for any file at any step — even if the workspace has no git history of its own.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@rexvane/piweb",
3
- "version": "0.3.12",
3
+ "version": "0.3.13",
4
4
  "license": "MIT",
5
5
  "type": "module",
6
6
  "description": "Modern web UI for the pi coding agent, driven by the official pi SDK without modifying pi",
@@ -0,0 +1,74 @@
1
+ import { NextResponse } from "next/server";
2
+ import { getAgentDir } from "@/lib/pi";
3
+ import { registerCwds } from "@/lib/workspace-store";
4
+ import { IMPORT_SOURCES, type ExternalSessionSummary, type ImportSource } from "@/lib/session-import/types";
5
+ import { importSessions, scanAllSources, type ImportSelection } from "@/lib/session-import";
6
+
7
+ export const dynamic = "force-dynamic";
8
+
9
+ /** 单次导入上限:一次点太多会把内存和磁盘写爆,也让界面报告失去意义 */
10
+ const MAX_SELECTION = 500;
11
+
12
+ /** 内部定位信息(文件路径 / 库+行)只用于服务端再扫描,不下发到浏览器 */
13
+ function publicSummary(summary: ExternalSessionSummary): Omit<ExternalSessionSummary, "location"> {
14
+ const { location: _location, ...rest } = summary;
15
+ return rest;
16
+ }
17
+
18
+ export async function GET() {
19
+ try {
20
+ const report = await scanAllSources(getAgentDir());
21
+ return NextResponse.json({
22
+ success: true,
23
+ data: {
24
+ sessions: report.summaries.map(publicSummary),
25
+ errors: report.errors,
26
+ imported: report.imported,
27
+ sources: IMPORT_SOURCES,
28
+ },
29
+ });
30
+ } catch (error) {
31
+ return NextResponse.json({ success: false, error: error instanceof Error ? error.message : String(error) }, { status: 500 });
32
+ }
33
+ }
34
+
35
+ export async function POST(req: Request) {
36
+ let body: unknown;
37
+ try {
38
+ body = await req.json();
39
+ } catch {
40
+ return NextResponse.json({ success: false, error: "invalid JSON body" }, { status: 400 });
41
+ }
42
+ if (!body || typeof body !== "object" || Array.isArray(body)) {
43
+ return NextResponse.json({ success: false, error: "expected an object body" }, { status: 400 });
44
+ }
45
+ const { sessions, fallbackCwd } = body as { sessions?: unknown; fallbackCwd?: unknown };
46
+ if (!Array.isArray(sessions)) return NextResponse.json({ success: false, error: "sessions must be an array" }, { status: 400 });
47
+ if (!sessions.length) return NextResponse.json({ success: false, error: "nothing selected" }, { status: 400 });
48
+ if (sessions.length > MAX_SELECTION) return NextResponse.json({ success: false, error: `too many sessions (max ${MAX_SELECTION})` }, { status: 400 });
49
+ if (fallbackCwd !== undefined && (typeof fallbackCwd !== "string" || fallbackCwd.length > 4096)) {
50
+ return NextResponse.json({ success: false, error: "invalid fallbackCwd" }, { status: 400 });
51
+ }
52
+
53
+ // 只接受 {source, externalId}:服务端按来源重新扫描定位,客户端给的路径一律不采信
54
+ const selection: ImportSelection[] = [];
55
+ for (const raw of sessions) {
56
+ if (!raw || typeof raw !== "object") return NextResponse.json({ success: false, error: "invalid selection entry" }, { status: 400 });
57
+ const { source, externalId } = raw as { source?: unknown; externalId?: unknown };
58
+ if (typeof source !== "string" || !IMPORT_SOURCES.includes(source as ImportSource)) {
59
+ return NextResponse.json({ success: false, error: `unknown source: ${String(source)}` }, { status: 400 });
60
+ }
61
+ if (typeof externalId !== "string" || !externalId || externalId.length > 400) {
62
+ return NextResponse.json({ success: false, error: "invalid externalId" }, { status: 400 });
63
+ }
64
+ selection.push({ source: source as ImportSource, externalId });
65
+ }
66
+
67
+ try {
68
+ const report = await importSessions(selection, { agentDir: getAgentDir(), fallbackCwd: typeof fallbackCwd === "string" ? fallbackCwd : undefined });
69
+ if (report.workspaces.length) await registerCwds(report.workspaces);
70
+ return NextResponse.json({ success: true, data: report });
71
+ } catch (error) {
72
+ return NextResponse.json({ success: false, error: error instanceof Error ? error.message : String(error) }, { status: 500 });
73
+ }
74
+ }
@@ -8,8 +8,7 @@
8
8
  */
9
9
  import { useCallback, useEffect, useState } from "react";
10
10
  import { useI18n } from "@/i18n";
11
- import { IconCopyOutline16, IconCheckOutline14, IconRefreshOutline14, IconCloseOutline14 } from "@/components/icons";
12
- import { copyText } from "@/lib/clipboard";
11
+ import { IconRefreshOutline14, IconCloseOutline14 } from "@/components/icons";
13
12
 
14
13
  export type PromptSourceKind = "system" | "append" | "agents" | "skill" | "template" | "tool" | "assembled";
15
14
 
@@ -37,6 +36,8 @@ export interface PromptToolView {
37
36
  export interface PromptSourcesData {
38
37
  sources: PromptSource[];
39
38
  assembledSystemPrompt?: string;
39
+ /** 压缩摘要(同样进入上下文) */
40
+ compactedSummary?: string;
40
41
  tools?: PromptToolView[];
41
42
  sessionReady: boolean;
42
43
  }
@@ -70,8 +71,6 @@ export function PromptPanel({
70
71
  const [error, setError] = useState<string | null>(null);
71
72
  const [busy, setBusy] = useState(false);
72
73
  const [opening, setOpening] = useState<string | null>(null);
73
- const [inline, setInline] = useState<{ title: string; content: string } | null>(null);
74
- const [copied, setCopied] = useState(false);
75
74
 
76
75
  const load = useCallback(async () => {
77
76
  setBusy(true);
@@ -199,7 +198,21 @@ export function PromptPanel({
199
198
  type="button"
200
199
  className="flex w-full items-center gap-2 rounded-lg px-2 py-1.5 text-left"
201
200
  style={{ border: "0.5px solid var(--dsw-border-l2)" }}
202
- onClick={() => setInline({ title: `${tool.name}`, content: [tool.description ?? "", tool.promptGuidelines?.join("\n") ?? "", tool.parameters ? JSON.stringify(tool.parameters, null, 2) : ""].filter(Boolean).join("\n\n") })}
201
+ title={tool.name}
202
+ onClick={() =>
203
+ onOpenContent?.(
204
+ `tool-${tool.name}.md`,
205
+ [
206
+ `# ${tool.name}`,
207
+ tool.source === "builtin" ? t.promptToolBuiltin : t.promptToolExtension,
208
+ tool.description ?? "",
209
+ ...(tool.promptGuidelines?.length ? [t.promptGuidelines, ...tool.promptGuidelines.map((line) => `- ${line}`)] : []),
210
+ ...(tool.parameters ? [t.promptParameters, "```json", JSON.stringify(tool.parameters, null, 2), "```"] : []),
211
+ ]
212
+ .filter(Boolean)
213
+ .join("\n\n"),
214
+ )
215
+ }
203
216
  >
204
217
  <span className="min-w-0 flex-1 truncate" style={{ color: "var(--dsw-label-primary)" }}>{tool.name}</span>
205
218
  <span className="flex-none rounded-md px-1.5 py-0.5" style={{ fontSize: 10.5, border: "0.5px solid var(--dsw-border-l3)", color: "var(--dsw-label-tertiary)" }}>
@@ -218,38 +231,27 @@ export function PromptPanel({
218
231
  type="button"
219
232
  className="w-full rounded-lg px-2 py-1.5 text-left"
220
233
  style={{ border: "0.5px solid var(--dsw-border-l2)" }}
221
- onClick={() => setInline({ title: t.promptKindAssembled, content: data.assembledSystemPrompt ?? "" })}
234
+ title={t.promptAssembledKey}
235
+ onClick={() => onOpenContent?.("system-prompt.md", data.assembledSystemPrompt ?? "")}
222
236
  >
223
237
  <span className="truncate" style={{ color: "var(--dsw-label-primary)" }}>{t.promptAssembledKey}</span>
224
238
  </button>
225
239
  </section>
226
240
  )}
227
241
 
228
- {inline && (
229
- <div className="mt-2">
230
- <div className="mb-1 flex items-center gap-2">
231
- <span className="min-w-0 flex-1 truncate" style={{ fontSize: 11.5, color: "var(--dsw-label-caption)" }}>{inline.title}</span>
232
- <button
233
- type="button"
234
- className="icon-btn"
235
- style={{ width: 24, height: 24 }}
236
- title={copied ? t.copySuccess : t.copy}
237
- aria-label={t.copy}
238
- onClick={() => {
239
- void copyText(inline.content).then((ok) => {
240
- setCopied(ok);
241
- setTimeout(() => setCopied(false), 1200);
242
- });
243
- }}
244
- >
245
- {copied ? <IconCheckOutline14 size={13} /> : <IconCopyOutline16 size={13} />}
246
- </button>
247
- <button type="button" className="icon-btn" style={{ width: 24, height: 24 }} title={t.close} aria-label={t.close} onClick={() => setInline(null)}>
248
- <IconCloseOutline14 size={13} />
249
- </button>
250
- </div>
251
- <pre className="pw-output" style={{ maxHeight: 420, overflow: "auto", margin: 0 }}>{inline.content}</pre>
252
- </div>
242
+ {data?.compactedSummary && (
243
+ <section className="mb-3">
244
+ <div className="mb-1 px-1" style={{ fontSize: 11.5, color: "var(--dsw-label-caption)" }}>{t.promptKindCompacted}</div>
245
+ <button
246
+ type="button"
247
+ className="w-full rounded-lg px-2 py-1.5 text-left"
248
+ style={{ border: "0.5px solid var(--dsw-border-l2)" }}
249
+ title={t.promptCompactedKey}
250
+ onClick={() => onOpenContent?.("compacted-summary.md", data.compactedSummary ?? "")}
251
+ >
252
+ <span className="truncate" style={{ color: "var(--dsw-label-primary)" }}>{t.promptCompactedKey}</span>
253
+ </button>
254
+ </section>
253
255
  )}
254
256
  </div>
255
257
  </div>