sparkecoder 0.1.122 → 0.1.124
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.
- package/dist/agent/index.d.ts +3 -3
- package/dist/agent/index.js +67 -14
- package/dist/agent/index.js.map +1 -1
- package/dist/cli.js +201 -66
- package/dist/cli.js.map +1 -1
- package/dist/db/index.d.ts +2 -2
- package/dist/{index-DczYH89U.d.ts → index-Bcz0aCAR.d.ts} +104 -104
- package/dist/index.d.ts +5 -5
- package/dist/index.js +124 -24
- package/dist/index.js.map +1 -1
- package/dist/{schema-DxrKyetI.d.ts → schema-BWbWmfDQ.d.ts} +3 -3
- package/dist/{search-CVVfuBPZ.d.ts → search-DOzC4ojH.d.ts} +4 -4
- package/dist/server/index.js +124 -24
- package/dist/server/index.js.map +1 -1
- package/dist/skills/default/recording.md +2 -2
- package/dist/tools/index.d.ts +3 -3
- package/package.json +1 -1
- package/src/skills/default/recording.md +2 -2
- package/web/.next/BUILD_ID +1 -1
- package/web/.next/standalone/web/.next/BUILD_ID +1 -1
- package/web/.next/standalone/web/.next/build-manifest.json +2 -2
- package/web/.next/standalone/web/.next/prerender-manifest.json +3 -3
- package/web/.next/standalone/web/.next/server/app/(main)/agents/page_client-reference-manifest.js +1 -1
- package/web/.next/standalone/web/.next/server/app/(main)/page_client-reference-manifest.js +1 -1
- package/web/.next/standalone/web/.next/server/app/(main)/session/[id]/page.js.nft.json +1 -1
- package/web/.next/standalone/web/.next/server/app/(main)/session/[id]/page_client-reference-manifest.js +1 -1
- package/web/.next/standalone/web/.next/server/app/(main)/settings/page_client-reference-manifest.js +1 -1
- package/web/.next/standalone/web/.next/server/app/_global-error.html +2 -2
- package/web/.next/standalone/web/.next/server/app/_global-error.rsc +1 -1
- package/web/.next/standalone/web/.next/server/app/_global-error.segments/__PAGE__.segment.rsc +1 -1
- package/web/.next/standalone/web/.next/server/app/_global-error.segments/_full.segment.rsc +1 -1
- package/web/.next/standalone/web/.next/server/app/_global-error.segments/_head.segment.rsc +1 -1
- package/web/.next/standalone/web/.next/server/app/_global-error.segments/_index.segment.rsc +1 -1
- package/web/.next/standalone/web/.next/server/app/_global-error.segments/_tree.segment.rsc +1 -1
- package/web/.next/standalone/web/.next/server/app/_not-found.html +1 -1
- package/web/.next/standalone/web/.next/server/app/_not-found.rsc +1 -1
- package/web/.next/standalone/web/.next/server/app/_not-found.segments/_full.segment.rsc +1 -1
- package/web/.next/standalone/web/.next/server/app/_not-found.segments/_head.segment.rsc +1 -1
- package/web/.next/standalone/web/.next/server/app/_not-found.segments/_index.segment.rsc +1 -1
- package/web/.next/standalone/web/.next/server/app/_not-found.segments/_not-found/__PAGE__.segment.rsc +1 -1
- package/web/.next/standalone/web/.next/server/app/_not-found.segments/_not-found.segment.rsc +1 -1
- package/web/.next/standalone/web/.next/server/app/_not-found.segments/_tree.segment.rsc +1 -1
- package/web/.next/standalone/web/.next/server/app/agents.html +1 -1
- package/web/.next/standalone/web/.next/server/app/agents.rsc +3 -3
- package/web/.next/standalone/web/.next/server/app/agents.segments/!KG1haW4p/agents/__PAGE__.segment.rsc +2 -2
- package/web/.next/standalone/web/.next/server/app/agents.segments/!KG1haW4p/agents.segment.rsc +1 -1
- package/web/.next/standalone/web/.next/server/app/agents.segments/!KG1haW4p.segment.rsc +2 -2
- package/web/.next/standalone/web/.next/server/app/agents.segments/_full.segment.rsc +3 -3
- package/web/.next/standalone/web/.next/server/app/agents.segments/_head.segment.rsc +1 -1
- package/web/.next/standalone/web/.next/server/app/agents.segments/_index.segment.rsc +1 -1
- package/web/.next/standalone/web/.next/server/app/agents.segments/_tree.segment.rsc +1 -1
- package/web/.next/standalone/web/.next/server/app/docs/installation.html +2 -2
- package/web/.next/standalone/web/.next/server/app/docs/installation.rsc +1 -1
- package/web/.next/standalone/web/.next/server/app/docs/installation.segments/_full.segment.rsc +1 -1
- package/web/.next/standalone/web/.next/server/app/docs/installation.segments/_head.segment.rsc +1 -1
- package/web/.next/standalone/web/.next/server/app/docs/installation.segments/_index.segment.rsc +1 -1
- package/web/.next/standalone/web/.next/server/app/docs/installation.segments/_tree.segment.rsc +1 -1
- package/web/.next/standalone/web/.next/server/app/docs/installation.segments/docs/installation/__PAGE__.segment.rsc +1 -1
- package/web/.next/standalone/web/.next/server/app/docs/installation.segments/docs/installation.segment.rsc +1 -1
- package/web/.next/standalone/web/.next/server/app/docs/installation.segments/docs.segment.rsc +1 -1
- package/web/.next/standalone/web/.next/server/app/docs/skills.html +2 -2
- package/web/.next/standalone/web/.next/server/app/docs/skills.rsc +1 -1
- package/web/.next/standalone/web/.next/server/app/docs/skills.segments/_full.segment.rsc +1 -1
- package/web/.next/standalone/web/.next/server/app/docs/skills.segments/_head.segment.rsc +1 -1
- package/web/.next/standalone/web/.next/server/app/docs/skills.segments/_index.segment.rsc +1 -1
- package/web/.next/standalone/web/.next/server/app/docs/skills.segments/_tree.segment.rsc +1 -1
- package/web/.next/standalone/web/.next/server/app/docs/skills.segments/docs/skills/__PAGE__.segment.rsc +1 -1
- package/web/.next/standalone/web/.next/server/app/docs/skills.segments/docs/skills.segment.rsc +1 -1
- package/web/.next/standalone/web/.next/server/app/docs/skills.segments/docs.segment.rsc +1 -1
- package/web/.next/standalone/web/.next/server/app/docs/tools.html +2 -2
- package/web/.next/standalone/web/.next/server/app/docs/tools.rsc +1 -1
- package/web/.next/standalone/web/.next/server/app/docs/tools.segments/_full.segment.rsc +1 -1
- package/web/.next/standalone/web/.next/server/app/docs/tools.segments/_head.segment.rsc +1 -1
- package/web/.next/standalone/web/.next/server/app/docs/tools.segments/_index.segment.rsc +1 -1
- package/web/.next/standalone/web/.next/server/app/docs/tools.segments/_tree.segment.rsc +1 -1
- package/web/.next/standalone/web/.next/server/app/docs/tools.segments/docs/tools/__PAGE__.segment.rsc +1 -1
- package/web/.next/standalone/web/.next/server/app/docs/tools.segments/docs/tools.segment.rsc +1 -1
- package/web/.next/standalone/web/.next/server/app/docs/tools.segments/docs.segment.rsc +1 -1
- package/web/.next/standalone/web/.next/server/app/docs.html +2 -2
- package/web/.next/standalone/web/.next/server/app/docs.rsc +1 -1
- package/web/.next/standalone/web/.next/server/app/docs.segments/_full.segment.rsc +1 -1
- package/web/.next/standalone/web/.next/server/app/docs.segments/_head.segment.rsc +1 -1
- package/web/.next/standalone/web/.next/server/app/docs.segments/_index.segment.rsc +1 -1
- package/web/.next/standalone/web/.next/server/app/docs.segments/_tree.segment.rsc +1 -1
- package/web/.next/standalone/web/.next/server/app/docs.segments/docs/__PAGE__.segment.rsc +1 -1
- package/web/.next/standalone/web/.next/server/app/docs.segments/docs.segment.rsc +1 -1
- package/web/.next/standalone/web/.next/server/app/index.html +1 -1
- package/web/.next/standalone/web/.next/server/app/index.rsc +3 -3
- package/web/.next/standalone/web/.next/server/app/index.segments/!KG1haW4p/__PAGE__.segment.rsc +2 -2
- package/web/.next/standalone/web/.next/server/app/index.segments/!KG1haW4p.segment.rsc +2 -2
- package/web/.next/standalone/web/.next/server/app/index.segments/_full.segment.rsc +3 -3
- package/web/.next/standalone/web/.next/server/app/index.segments/_head.segment.rsc +1 -1
- package/web/.next/standalone/web/.next/server/app/index.segments/_index.segment.rsc +1 -1
- package/web/.next/standalone/web/.next/server/app/index.segments/_tree.segment.rsc +1 -1
- package/web/.next/standalone/web/.next/server/app/settings.html +1 -1
- package/web/.next/standalone/web/.next/server/app/settings.rsc +3 -3
- package/web/.next/standalone/web/.next/server/app/settings.segments/!KG1haW4p/settings/__PAGE__.segment.rsc +2 -2
- package/web/.next/standalone/web/.next/server/app/settings.segments/!KG1haW4p/settings.segment.rsc +1 -1
- package/web/.next/standalone/web/.next/server/app/settings.segments/!KG1haW4p.segment.rsc +2 -2
- package/web/.next/standalone/web/.next/server/app/settings.segments/_full.segment.rsc +3 -3
- package/web/.next/standalone/web/.next/server/app/settings.segments/_head.segment.rsc +1 -1
- package/web/.next/standalone/web/.next/server/app/settings.segments/_index.segment.rsc +1 -1
- package/web/.next/standalone/web/.next/server/app/settings.segments/_tree.segment.rsc +1 -1
- package/web/.next/standalone/web/.next/server/chunks/ssr/{2374f_c87abaf4._.js → 2374f_12d55e68._.js} +1 -1
- package/web/.next/standalone/web/.next/server/chunks/ssr/{2374f_1f3f2d00._.js → 2374f_1c0639c2._.js} +1 -1
- package/web/.next/standalone/web/.next/server/chunks/ssr/{2374f_a0d5caeb._.js → 2374f_28cd6777._.js} +1 -1
- package/web/.next/standalone/web/.next/server/chunks/ssr/{2374f_570c34dc._.js → 2374f_5f47a9b7._.js} +1 -1
- package/web/.next/standalone/web/.next/server/chunks/ssr/{2374f_d8122230._.js → 2374f_aa218457._.js} +1 -1
- package/web/.next/standalone/web/.next/server/chunks/ssr/{2374f_9c560f3a._.js → 2374f_f678a96f._.js} +1 -1
- package/web/.next/standalone/web/.next/server/chunks/ssr/{2374f_38945fd9._.js → 2374f_fac4000d._.js} +1 -1
- package/web/.next/standalone/web/.next/server/chunks/ssr/{[root-of-the-server]__4de426bd._.js → [root-of-the-server]__e5911ea8._.js} +4 -4
- package/web/.next/standalone/web/.next/server/chunks/ssr/{web_62ca4286._.js → web_2966b3a3._.js} +2 -2
- package/web/.next/standalone/web/.next/server/chunks/ssr/web_4fe3c244._.js +1 -1
- package/web/.next/standalone/web/.next/server/pages/404.html +1 -1
- package/web/.next/standalone/web/.next/server/pages/500.html +2 -2
- package/web/.next/standalone/web/.next/server/server-reference-manifest.js +1 -1
- package/web/.next/standalone/web/.next/server/server-reference-manifest.json +1 -1
- package/web/.next/standalone/web/.next/static/chunks/{91988e253d5fa420.js → 4d95c15f712c9e06.js} +5 -5
- package/web/.next/standalone/web/.next/static/chunks/780c93257fac7d43.js +1 -0
- package/web/.next/standalone/web/.next/static/static/chunks/{91988e253d5fa420.js → 4d95c15f712c9e06.js} +5 -5
- package/web/.next/standalone/web/.next/static/static/chunks/780c93257fac7d43.js +1 -0
- package/web/.next/standalone/web/src/components/chat-interface.tsx +112 -1
- package/web/.next/static/chunks/{91988e253d5fa420.js → 4d95c15f712c9e06.js} +5 -5
- package/web/.next/static/chunks/780c93257fac7d43.js +1 -0
- package/web/.next/standalone/web/.next/static/chunks/f0f19357f3fb7cf8.js +0 -1
- package/web/.next/standalone/web/.next/static/static/chunks/f0f19357f3fb7cf8.js +0 -1
- package/web/.next/static/chunks/f0f19357f3fb7cf8.js +0 -1
- /package/web/.next/standalone/web/.next/static/{BEIBC9-dP0_AWGmRy97hJ → cYXZ7UzGc5TttFIXRRcSC}/_buildManifest.js +0 -0
- /package/web/.next/standalone/web/.next/static/{BEIBC9-dP0_AWGmRy97hJ → cYXZ7UzGc5TttFIXRRcSC}/_clientMiddlewareManifest.json +0 -0
- /package/web/.next/standalone/web/.next/static/{BEIBC9-dP0_AWGmRy97hJ → cYXZ7UzGc5TttFIXRRcSC}/_ssgManifest.js +0 -0
- /package/web/.next/standalone/web/.next/static/static/{BEIBC9-dP0_AWGmRy97hJ → cYXZ7UzGc5TttFIXRRcSC}/_buildManifest.js +0 -0
- /package/web/.next/standalone/web/.next/static/static/{BEIBC9-dP0_AWGmRy97hJ → cYXZ7UzGc5TttFIXRRcSC}/_clientMiddlewareManifest.json +0 -0
- /package/web/.next/standalone/web/.next/static/static/{BEIBC9-dP0_AWGmRy97hJ → cYXZ7UzGc5TttFIXRRcSC}/_ssgManifest.js +0 -0
- /package/web/.next/static/{BEIBC9-dP0_AWGmRy97hJ → cYXZ7UzGc5TttFIXRRcSC}/_buildManifest.js +0 -0
- /package/web/.next/static/{BEIBC9-dP0_AWGmRy97hJ → cYXZ7UzGc5TttFIXRRcSC}/_clientMiddlewareManifest.json +0 -0
- /package/web/.next/static/{BEIBC9-dP0_AWGmRy97hJ → cYXZ7UzGc5TttFIXRRcSC}/_ssgManifest.js +0 -0
|
@@ -0,0 +1 @@
|
|
|
1
|
+
(globalThis.TURBOPACK||(globalThis.TURBOPACK=[])).push(["object"==typeof document?document.currentScript:void 0,524741,e=>{"use strict";var t=e.i(739963);function r(){return(0,t.getApiUrl)()}async function n(e){let t=e?.role?`?role=${e.role}`:"",n=await fetch(`${r()}/sessions${t}`);return n.ok&&(await n.json().catch(()=>({}))).sessions||[]}async function o(e,t,n){await fetch(`${r()}/tasks/${e}/questions/${t}/answer`,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({answer:n,answeredBy:"user"})})}async function s(e){if(!e||"undefined"===e||"null"===e)return null;let t=await fetch(`${r()}/sessions/${e}`);if(!t.ok)return null;let n=await t.json().catch(()=>null);return n&&"string"==typeof n.id?n:null}async function a(e){return(await fetch(`${r()}/sessions`,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify(e)})).json()}async function i(e){await fetch(`${r()}/sessions/${e}`,{method:"DELETE"})}async function c(e){return(await fetch(`${r()}/tasks`,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify(e)})).json()}async function l(e){return(await fetch(`${r()}/sessions/${e}/todos`)).json()}async function u(e){return(await fetch(`${r()}/sessions/${e}/plans`)).json()}async function f(e){return(await fetch(`${r()}/sessions/${e}/pending-input`)).json()}async function d(e,t){return(await fetch(`${r()}/sessions/${e}`,{method:"PATCH",headers:{"Content-Type":"application/json"},body:JSON.stringify(t)})).json()}async function g(e,t,r,n){return d(e,{toolApprovals:{[t]:r}})}async function h(e){let t=await fetch(`${r()}/sessions/${e}/messages`);return(await t.json()).messages||[]}async function p(e){let t=await fetch(`${r()}/agents/${e}/approvals`);return(await t.json()).pendingApprovals||[]}async function y(e,t){await fetch(`${r()}/agents/${e}/approve/${t}`,{method:"POST"})}async function w(e,t,n){await fetch(`${r()}/agents/${e}/reject/${t}`,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({reason:n})})}async function S(e){return(await fetch(`${r()}/agents/${e}/stream`)).json()}async function m(e){return(await fetch(`${r()}/agents/${e}/abort`,{method:"POST"})).json()}function E(e,t,r){return new Promise(async(n,o)=>{let s=e.body?.getReader();if(!s){console.error("[SSE] No response body — cannot read stream"),o(Error("No response body"));return}let a=new TextDecoder,i="",c=0,l=0,u=0,f=0,d=0,g=Date.now(),h=!0===window.__sparkeSseDebug;console.log("[SSE] Stream reader started, status:",e.status);try{for(;;){let{done:e,value:n}=await s.read();if(e){console.log(`[SSE] Stream ended. Total events: ${c}, browser frames: ${l}, browser status: ${u}, parse errors: ${f}, bytes: ${d}`);break}d+=n?.byteLength??0;let o=(i+=a.decode(n,{stream:!0})).split("\n");for(let e of(i=o.pop()||"",o))if(e.startsWith("data: ")){let n=e.slice(6);if("[DONE]"===n){console.log("[SSE] Received [DONE] marker");continue}try{let e=JSON.parse(n);c++,"browser-frame"===e.type?(l++,1===l?console.log(`[SSE] First browser-frame received! dataSize=${e.data?.length??0}`):l%50==0&&console.log(`[SSE] Browser frame #${l}`)):"browser-status"===e.type&&(u++,console.log(`[SSE] Browser status event: connected=${e.connected} screencasting=${e.screencasting}`));let o=Date.now();o-g>1e4&&(console.log(`[SSE] Stats: events=${c} browserFrames=${l} bytes=${d} parseErrors=${f}`),g=o),"data-stream-id"===e.type&&r&&(console.log(`[SSE] Stream ID received: ${e.streamId}`),r(e.streamId)),h&&window.dispatchEvent(new CustomEvent("sparke:sse-event",{detail:{type:e.type,size:n.length,label:"string"==typeof e.label?e.label:void 0,toolName:"string"==typeof e.toolName?e.toolName:void 0}})),t(e)}catch(e){f++,console.warn("[SSE] Failed to parse event JSON",{error:e instanceof Error?e.message:String(e),dataLength:n.length,preview:n.slice(0,200),parseErrors:f}),h&&window.dispatchEvent(new CustomEvent("sparke:sse-parse-error",{detail:{error:e instanceof Error?e.message:String(e),size:n.length,preview:n.slice(0,200)}}))}}}n()}catch(e){console.error(`[SSE] Stream read error after ${c} events, ${d} bytes:`,e),o(e)}})}function $(e,t,n,o){let s=new AbortController;console.log(`[STREAM] runAgent: starting stream for session ${e}`);let a={prompt:t};return o?.attachments&&o.attachments.length>0&&(a.attachments=o.attachments),fetch(`${r()}/agents/${e}/run`,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify(a),signal:s.signal}).then(async t=>{console.log(`[STREAM] runAgent: response status=${t.status}, content-type=${t.headers.get("content-type")}`);let r=t.headers.get("x-stream-id");r&&(console.log(`[STREAM] runAgent: received stream ID ${r}`),o?.onStreamId&&o.onStreamId(r)),await E(t,n,o?.onStreamId),console.log(`[STREAM] runAgent: stream completed for session ${e}`)}).catch(t=>{"AbortError"!==t.name?console.error(`[STREAM] runAgent error for session ${e}:`,t):console.log(`[STREAM] runAgent: aborted for session ${e}`)}),()=>{console.log(`[STREAM] runAgent: abort called for session ${e}`),s.abort()}}function v(e,t,n){let o=new AbortController,s=new URLSearchParams;n?.streamId&&s.set("streamId",n.streamId),n?.resumeAt!==void 0&&s.set("resumeAt",String(n.resumeAt));let a=`${r()}/agents/${e}/watch${s.toString()?"?"+s.toString():""}`;return console.log(`[STREAM] watchStream: connecting to ${a}`),fetch(a,{signal:o.signal}).then(async r=>{if(console.log(`[STREAM] watchStream: response status=${r.status}, content-type=${r.headers.get("content-type")}`),!r.ok){let e=await r.json().catch(()=>({error:"Unknown error"}));console.error(`[STREAM] watchStream error: status=${r.status}`,e),t({type:"error",errorText:e.error||"Failed to watch stream"});return}let o=r.headers.get("x-stream-id");o&&(console.log(`[STREAM] watchStream: received stream ID ${o}`),n?.onStreamId&&n.onStreamId(o)),await E(r,t,n?.onStreamId),console.log(`[STREAM] watchStream: completed for session ${e}`)}).catch(t=>{"AbortError"!==t.name?console.error(`[STREAM] watchStream error for session ${e}:`,t):console.log(`[STREAM] watchStream: aborted for session ${e}`)}),()=>{console.log(`[STREAM] watchStream: abort called for session ${e}`),o.abort()}}function T(e,t,n){let o=new AbortController;return console.log(`[TERMINAL] Connecting to terminal stream: ${e}`),(async()=>{try{let s=await fetch(`${r()}/terminals/stream/${e}`,{signal:o.signal});if(!s.ok||!s.body)return void console.error(`[TERMINAL] Failed to connect to terminal stream ${e}: status=${s.status}`);console.log(`[TERMINAL] Connected to terminal stream ${e}`);let a=s.body.getReader(),i=new TextDecoder,c="",l=0;for(;;){let{done:r,value:o}=await a.read();if(r){console.log(`[TERMINAL] Stream ended for ${e} after ${l} output chunks`);break}let s=(c+=i.decode(o,{stream:!0})).split("\n\n");for(let r of(c=s.pop()||"",s)){if(!r.trim())continue;let o=r.match(/event:\s*(\w+)/),s=r.match(/data:\s*(.+)/);if(o&&s){let r=o[1];try{let o=JSON.parse(s[1]);"stdout"===r&&o.data?(l++,t(o.data)):"exit"===r&&(console.log(`[TERMINAL] Exit event for ${e}`),n?.())}catch{}}}}}catch(t){t instanceof Error&&"AbortError"!==t.name&&console.error(`[TERMINAL] Stream error for ${e}:`,t)}})(),()=>{console.log(`[TERMINAL] Aborting terminal stream ${e}`),o.abort()}}async function b(){return(await fetch(`${r()}/health/version`)).json()}async function R(){return(await fetch(`${r()}/health/api-keys`)).json()}async function A(e,t){return(await fetch(`${r()}/health/api-keys`,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({provider:e,apiKey:t})})).json()}async function O(e){let t=await fetch(`${r()}/sessions/${e}/checkpoints`);if(!t.ok)throw Error(`Failed to get checkpoints: ${t.statusText}`);return t.json()}async function k(e,t){let n=await fetch(`${r()}/sessions/${e}/revert/${t}`,{method:"POST"});if(!n.ok)throw Error((await n.json()).error||`Failed to revert: ${n.statusText}`);return n.json()}async function j(e){let t=await fetch(`${r()}/sessions/${e}/diff`);if(!t.ok)throw Error(`Failed to get diff: ${t.statusText}`);return t.json()}async function _(e){let t=await fetch(`${r()}/sessions/${e}/attachments`);if(!t.ok)throw Error(`Failed to get attachments: ${t.statusText}`);return t.json()}async function N(e,t,n){let o=new URLSearchParams;t&&o.set("query",t),n&&o.set("limit",String(n));let s=`${r()}/sessions/${e}/files${o.toString()?"?"+o.toString():""}`,a=await fetch(s);if(!a.ok)throw Error(`Failed to get workspace files: ${a.statusText}`);return a.json()}async function C(e,t){await fetch(`${r()}/agents/${e}/browser-input`,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify(t)})}async function I(e){let t=await fetch(`${r()}/sessions/${e}/session-files`);if(!t.ok){if(404===t.status)return[];throw Error(`Failed to get session files: ${t.statusText}`)}return(await t.json()).files||[]}async function L(e){let t=await fetch(`${r()}/sessions/${e}/browser-recording`);return t.ok&&(await t.json()).recordings||[]}async function M(e){try{let t=await fetch(`${r()}/agents/${e}/browser-stream`);if(!t.ok)return null;return t.json()}catch{return null}}e.s(["abortStream",()=>m,"answerAgentQuestion",()=>o,"approveExecution",()=>y,"checkVersion",()=>b,"createSession",()=>a,"createTask",()=>c,"deleteSession",()=>i,"getActiveStream",()=>S,"getApiKeys",()=>R,"getBrowserRecordings",()=>L,"getBrowserStreamStatus",()=>M,"getPendingApprovals",()=>p,"getPendingInput",()=>f,"getSession",()=>s,"getSessionAttachments",()=>_,"getSessionCheckpoints",()=>O,"getSessionDiff",()=>j,"getSessionFiles",()=>I,"getSessionMessages",()=>h,"getSessionPlans",()=>u,"getSessionTodos",()=>l,"getSessions",()=>n,"getWorkspaceFiles",()=>N,"rejectExecution",()=>w,"revertToCheckpoint",()=>k,"runAgent",()=>$,"sendBrowserInput",()=>C,"setApiKey",()=>A,"streamTerminal",()=>T,"updateSession",()=>d,"updateToolApproval",()=>g,"watchStream",()=>v])},310711,(e,t,r)=>{"use strict";var n=e.r(430878),o="function"==typeof Object.is?Object.is:function(e,t){return e===t&&(0!==e||1/e==1/t)||e!=e&&t!=t},s=n.useState,a=n.useEffect,i=n.useLayoutEffect,c=n.useDebugValue;function l(e){var t=e.getSnapshot;e=e.value;try{var r=t();return!o(e,r)}catch(e){return!0}}var u="u"<typeof window||void 0===window.document||void 0===window.document.createElement?function(e,t){return t()}:function(e,t){var r=t(),n=s({inst:{value:r,getSnapshot:t}}),o=n[0].inst,u=n[1];return i(function(){o.value=r,o.getSnapshot=t,l(o)&&u({inst:o})},[e,r,t]),a(function(){return l(o)&&u({inst:o}),e(function(){l(o)&&u({inst:o})})},[e]),c(r),r};r.useSyncExternalStore=void 0!==n.useSyncExternalStore?n.useSyncExternalStore:u},753257,(e,t,r)=>{"use strict";t.exports=e.r(310711)},262189,103393,e=>{"use strict";let t;var r=e.i(430878),n=e.i(753257);e.s(["ERROR_REVALIDATE_EVENT",()=>3,"FOCUS_EVENT",()=>0,"MUTATE_EVENT",()=>2,"RECONNECT_EVENT",()=>1],786254);var o=Object.prototype.hasOwnProperty;let s=new WeakMap,a=()=>{},i=a(),c=Object,l=e=>e===i,u=(e,t)=>({...e,...t}),f={},d={},g="undefined",h=typeof window!=g,p=typeof document!=g,y=h&&"Deno"in window,w=(e,t)=>{let r=s.get(e);return[()=>!l(t)&&e.get(t)||f,n=>{if(!l(t)){let o=e.get(t);t in d||(d[t]=o),r[5](t,u(o,n),o||f)}},r[6],()=>!l(t)&&t in d?d[t]:!l(t)&&e.get(t)||f]},S=!0,[m,E]=h&&window.addEventListener?[window.addEventListener.bind(window),window.removeEventListener.bind(window)]:[a,a],$={initFocus:e=>(p&&document.addEventListener("visibilitychange",e),m("focus",e),()=>{p&&document.removeEventListener("visibilitychange",e),E("focus",e)}),initReconnect:e=>{let t=()=>{S=!0,e()},r=()=>{S=!1};return m("online",t),m("offline",r),()=>{E("online",t),E("offline",r)}}},v=!r.default.useId,T=!h||y,b=T?r.useEffect:r.useLayoutEffect,R="u">typeof navigator&&navigator.connection,A=!T&&R&&(["slow-2g","2g"].includes(R.effectiveType)||R.saveData),O=new WeakMap,k=(e,t)=>e===`[object ${t}]`,j=0,_=e=>{let t,r,n=typeof e,o=c.prototype.toString.call(e),s=k(o,"Date"),a=k(o,"RegExp"),i=k(o,"Object");if(c(e)!==e||s||a)t=s?e.toJSON():"symbol"==n?e.toString():"string"==n?JSON.stringify(e):""+e;else{if(t=O.get(e))return t;if(t=++j+"~",O.set(e,t),Array.isArray(e)){for(r=0,t="@";r<e.length;r++)t+=_(e[r])+",";O.set(e,t)}if(i){t="#";let n=c.keys(e).sort();for(;!l(r=n.pop());)l(e[r])||(t+=r+":"+_(e[r])+",");O.set(e,t)}}return t},N=e=>{if("function"==typeof e)try{e=e()}catch(t){e=""}let t=e;return[e="string"==typeof e?e:(Array.isArray(e)?e.length:e)?_(e):"",t]},C=0,I=()=>++C;async function L(...e){let[t,r,n,o]=e,a=u({populateCache:!0,throwOnError:!0},"boolean"==typeof o?{revalidate:o}:o||{}),c=a.populateCache,f=a.rollbackOnError,d=a.optimisticData,g=a.throwOnError;if("function"==typeof r){let e=[];for(let n of t.keys())!/^\$(inf|sub)\$/.test(n)&&r(t.get(n)._k)&&e.push(n);return Promise.all(e.map(h))}return h(r);async function h(r){let o,[u]=N(r);if(!u)return;let[h,p]=w(t,u),[y,S,m,E]=s.get(t),$=()=>{let e=y[u];return("function"==typeof a.revalidate?a.revalidate(h().data,r):!1!==a.revalidate)&&(delete m[u],delete E[u],e&&e[0])?e[0](2).then(()=>h().data):h().data};if(e.length<3)return $();let v=n,T=!1,b=I();S[u]=[b,0];let R=!l(d),A=h(),O=A.data,k=A._c,j=l(k)?O:k;if(R&&p({data:d="function"==typeof d?d(j,O):d,_c:j}),"function"==typeof v)try{v=v(j)}catch(e){o=e,T=!0}if(v&&"function"==typeof v.then){let e;if(v=await v.catch(e=>{o=e,T=!0}),b!==S[u][0]){if(T)throw o;return v}T&&R&&(e=o,"function"==typeof f?f(e):!1!==f)&&(c=!0,p({data:j,_c:i}))}if(c&&!T&&("function"==typeof c?p({data:c(v,j),error:i,_c:i}):p({data:v,error:i,_c:i})),S[u][1]=I(),Promise.resolve($()).then(()=>{p({_c:i})}),T){if(g)throw o;return}return v}}let M=(e,t)=>{for(let r in e)e[r][0]&&e[r][0](t)},D=(e,t)=>{if(!s.has(e)){let r=u($,t),n=Object.create(null),o=L.bind(i,e),c=a,l=Object.create(null),f=(e,t)=>{let r=l[e]||[];return l[e]=r,r.push(t),()=>r.splice(r.indexOf(t),1)},d=(t,r,n)=>{e.set(t,r);let o=l[t];if(o)for(let e of o)e(r,n)},g=()=>{if(!s.has(e)&&(s.set(e,[n,Object.create(null),Object.create(null),Object.create(null),o,d,f]),!T)){let t=r.initFocus(setTimeout.bind(i,M.bind(i,n,0))),o=r.initReconnect(setTimeout.bind(i,M.bind(i,n,1)));c=()=>{t&&t(),o&&o(),s.delete(e)}}};return g(),[e,o,g,c]}return[e,s.get(e)[4]]},[P,V]=D(new Map),x=u({onLoadingSlow:a,onSuccess:a,onError:a,onErrorRetry:(e,t,r,n,o)=>{let s=r.errorRetryCount,a=o.retryCount,i=~~((Math.random()+.5)*(1<<(a<8?a:8)))*r.errorRetryInterval;(l(s)||!(a>s))&&setTimeout(n,i,o)},onDiscarded:a,revalidateOnFocus:!0,revalidateOnReconnect:!0,revalidateIfStale:!0,shouldRetryOnError:!0,errorRetryInterval:A?1e4:5e3,focusThrottleInterval:5e3,dedupingInterval:2e3,loadingTimeout:A?5e3:3e3,compare:function e(t,r){var n,s;if(t===r)return!0;if(t&&r&&(n=t.constructor)===r.constructor){if(n===Date)return t.getTime()===r.getTime();if(n===RegExp)return t.toString()===r.toString();if(n===Array){if((s=t.length)===r.length)for(;s--&&e(t[s],r[s]););return -1===s}if(!n||"object"==typeof t){for(n in s=0,t)if(o.call(t,n)&&++s&&!o.call(r,n)||!(n in r)||!e(t[n],r[n]))return!1;return Object.keys(r).length===s}}return t!=t&&r!=r},isPaused:()=>!1,cache:P,mutate:V,fallback:{}},{isOnline:()=>S,isVisible:()=>{let e=p&&document.visibilityState;return l(e)||"hidden"!==e}}),F=(e,t)=>{let r=u(e,t);if(t){let{use:n,fallback:o}=e,{use:s,fallback:a}=t;n&&s&&(r.use=n.concat(s)),o&&a&&(r.fallback=u(o,a))}return r},J=(0,r.createContext)({});var U=e.i(786254);let W=h&&window.__SWR_DEVTOOLS_USE__,B=(W?window.__SWR_DEVTOOLS_USE__:[]).concat(e=>(t,r,n)=>{let o=r&&((...e)=>{let[n]=N(t),[,,,o]=s.get(P);if(n.startsWith("$inf$"))return r(...e);let a=o[n];return l(a)?r(...e):(delete o[n],a)});return e(t,o,n)});W&&(window.__SWR_DEVTOOLS_REACT__=r.default);let q=()=>{},z=q(),K=(new WeakMap,r.default.use||(e=>{switch(e.status){case"pending":throw e;case"fulfilled":return e.value;case"rejected":throw e.reason;default:throw e.status="pending",e.then(t=>{e.status="fulfilled",e.value=t},t=>{e.status="rejected",e.reason=t}),e}})),H={dedupe:!0},Q=Promise.resolve(i);c.defineProperty(e=>{let{value:t}=e,n=(0,r.useContext)(J),o="function"==typeof t,s=(0,r.useMemo)(()=>o?t(n):t,[o,n,t]),a=(0,r.useMemo)(()=>o?s:F(n,s),[o,n,s]),c=s&&s.provider,l=(0,r.useRef)(i);c&&!l.current&&(l.current=D(c(a.cache||P),s));let f=l.current;return f&&(a.cache=f[0],a.mutate=f[1]),b(()=>{if(f)return f[2]&&f[2](),f[3]},[]),(0,r.createElement)(J.Provider,u(e,{value:a}))},"defaultValue",{value:x});let Y=(t=(e,t,o)=>{let{cache:c,compare:f,suspense:d,fallbackData:p,revalidateOnMount:y,revalidateIfStale:S,refreshInterval:m,refreshWhenHidden:E,refreshWhenOffline:$,keepPreviousData:R,strictServerPrefetchWarning:A}=o,[O,k,j,_]=s.get(c),[C,M]=N(e),D=(0,r.useRef)(!1),P=(0,r.useRef)(!1),V=(0,r.useRef)(C),x=(0,r.useRef)(t),F=(0,r.useRef)(o),J=()=>F.current.isVisible()&&F.current.isOnline(),[W,B,q,z]=w(c,C),Y=(0,r.useRef)({}).current,G=l(p)?l(o.fallback)?i:o.fallback[C]:p,X=(e,t)=>{for(let r in Y)if("data"===r){if(!f(e[r],t[r])&&(!l(e[r])||!f(ei,t[r])))return!1}else if(t[r]!==e[r])return!1;return!0},Z=(0,r.useMemo)(()=>{let e=!!C&&!!t&&(l(y)?!F.current.isPaused()&&!d&&!1!==S:y),r=t=>{let r=u(t);return(delete r._k,e)?{isValidating:!0,isLoading:!0,...r}:r},n=W(),o=z(),s=r(n),a=n===o?s:r(o),i=s;return[()=>{let e=r(W());return X(e,i)?(i.data=e.data,i.isLoading=e.isLoading,i.isValidating=e.isValidating,i.error=e.error,i):(i=e,e)},()=>a]},[c,C]),ee=(0,n.useSyncExternalStore)((0,r.useCallback)(e=>q(C,(t,r)=>{X(r,t)||e()}),[c,C]),Z[0],Z[1]),et=!D.current,er=O[C]&&O[C].length>0,en=ee.data,eo=l(en)?G&&"function"==typeof G.then?K(G):G:en,es=ee.error,ea=(0,r.useRef)(eo),ei=R?l(en)?l(ea.current)?eo:ea.current:en:eo,ec=C&&l(eo),el=!T&&(0,n.useSyncExternalStore)(()=>a,()=>!1,()=>!0);A&&el&&!d&&ec&&console.warn(`Missing pre-initiated data for serialized key "${C}" during server-side rendering. Data fethcing should be initiated on the server and provided to SWR via fallback data. You can set "strictServerPrefetchWarning: false" to disable this warning.`);let eu=(!er||!!l(es))&&(et&&!l(y)?y:!F.current.isPaused()&&(d?!l(eo)&&S:l(eo)||S)),ef=!!(C&&t&&et&&eu),ed=l(ee.isValidating)?ef:ee.isValidating,eg=l(ee.isLoading)?ef:ee.isLoading,eh=(0,r.useCallback)(async e=>{let t,r,n=x.current;if(!C||!n||P.current||F.current.isPaused())return!1;let s=!0,a=e||{},c=!j[C]||!a.dedupe,u=()=>v?!P.current&&C===V.current&&D.current:C===V.current,d={isValidating:!1,isLoading:!1},g=()=>{B(d)},h=()=>{let e=j[C];e&&e[1]===r&&delete j[C]},p={isValidating:!0};l(W().data)&&(p.isLoading=!0);try{if(c&&(B(p),o.loadingTimeout&&l(W().data)&&setTimeout(()=>{s&&u()&&F.current.onLoadingSlow(C,o)},o.loadingTimeout),j[C]=[n(M),I()]),[t,r]=j[C],t=await t,c&&setTimeout(h,o.dedupingInterval),!j[C]||j[C][1]!==r)return c&&u()&&F.current.onDiscarded(C),!1;d.error=i;let e=k[C];if(!l(e)&&(r<=e[0]||r<=e[1]||0===e[1]))return g(),c&&u()&&F.current.onDiscarded(C),!1;let a=W().data;d.data=f(a,t)?a:t,c&&u()&&F.current.onSuccess(t,C,o)}catch(r){h();let e=F.current,{shouldRetryOnError:t}=e;!e.isPaused()&&(d.error=r,c&&u())&&(e.onError(r,C,e),(!0===t||"function"==typeof t&&t(r))&&(!F.current.revalidateOnFocus||!F.current.revalidateOnReconnect||J())&&e.onErrorRetry(r,C,e,e=>{let t=O[C];t&&t[0]&&t[0](U.ERROR_REVALIDATE_EVENT,e)},{retryCount:(a.retryCount||0)+1,dedupe:!0}))}return s=!1,g(),!0},[C,c]),ep=(0,r.useCallback)((...e)=>L(c,V.current,...e),[]);if(b(()=>{x.current=t,F.current=o,l(en)||(ea.current=en)}),b(()=>{var e;let t;if(!C)return;let r=eh.bind(i,H),n=0;F.current.revalidateOnFocus&&(n=Date.now()+F.current.focusThrottleInterval);let o=(e=(e,t={})=>{if(e==U.FOCUS_EVENT){let e=Date.now();F.current.revalidateOnFocus&&e>n&&J()&&(n=e+F.current.focusThrottleInterval,r())}else if(e==U.RECONNECT_EVENT)F.current.revalidateOnReconnect&&J()&&r();else if(e==U.MUTATE_EVENT)return eh();else if(e==U.ERROR_REVALIDATE_EVENT)return eh(t)},(t=O[C]||(O[C]=[])).push(e),()=>{let r=t.indexOf(e);r>=0&&(t[r]=t[t.length-1],t.pop())});if(P.current=!1,V.current=C,D.current=!0,B({_k:M}),eu&&!j[C])if(l(eo)||T)r();else h&&typeof window.requestAnimationFrame!=g?window.requestAnimationFrame(r):setTimeout(r,1);return()=>{P.current=!0,o()}},[C]),b(()=>{let e;function t(){let t="function"==typeof m?m(W().data):m;t&&-1!==e&&(e=setTimeout(r,t))}function r(){!W().error&&(E||F.current.isVisible())&&($||F.current.isOnline())?eh(H).then(t):t()}return t(),()=>{e&&(clearTimeout(e),e=-1)}},[m,E,$,C]),(0,r.useDebugValue)(ei),d){if(!v&&T&&ec)throw Error("Fallback data is required when using Suspense in SSR.");ec&&(x.current=t,F.current=o,P.current=!1);let e=_[C];if(K(!l(e)&&ec?ep(e):Q),!l(es)&&ec)throw es;let r=ec?eh(H):Q;!l(ei)&&ec&&(r.status="fulfilled",r.value=!0),K(r)}return{mutate:ep,get data(){return Y.data=!0,ei},get error(){return Y.error=!0,es},get isValidating(){return Y.isValidating=!0,ed},get isLoading(){return Y.isLoading=!0,eg}}},function(...e){let n,o=(n=(0,r.useContext)(J),(0,r.useMemo)(()=>u(x,n),[n])),[s,a,i]="function"==typeof e[1]?[e[0],e[1],e[2]||{}]:[e[0],null,(null===e[1]?e[2]:e[1])||{}],c=F(o,i),l=t,{use:f}=c,d=(f||[]).concat(B);for(let e=d.length;e--;)l=d[e](l);return l(s,a||c.fetcher||null,c)});e.s(["default",()=>Y],262189),e.s(["mutate",()=>V],103393)},300739,e=>{"use strict";var t=e.i(262189),r=e.i(103393),n=e.i(524741);let o="/api/sessions";function s(){let{data:e=[],error:r,isLoading:s}=(0,t.default)(o,n.getSessions,{refreshInterval:2e3,revalidateOnFocus:!0});return{sessions:e,isLoading:s,error:r}}function a(){return(0,r.mutate)(o)}e.s(["mutateSessions",()=>a,"useSessions",()=>s])}]);
|
|
@@ -118,6 +118,9 @@ import {
|
|
|
118
118
|
getSessionFiles,
|
|
119
119
|
getBrowserStreamStatus,
|
|
120
120
|
getBrowserRecordings,
|
|
121
|
+
getSession,
|
|
122
|
+
getSessionDiff,
|
|
123
|
+
getSessionAttachments,
|
|
121
124
|
type SessionFile as ApiSessionFile,
|
|
122
125
|
type BrowserRecordingInfo,
|
|
123
126
|
} from '@/lib/api';
|
|
@@ -132,7 +135,7 @@ import {
|
|
|
132
135
|
SelectTrigger,
|
|
133
136
|
SelectValue,
|
|
134
137
|
} from '@/components/ui/select';
|
|
135
|
-
import { MessageSquare, Copy, RefreshCw, AlertTriangle, Terminal as TerminalIcon, FileCode, Radio, Pencil, Check, Settings, RotateCcw, FolderOpen, PanelLeft, FileIcon, Download, X, ChevronDown, ChevronUp, Play, ArrowUp, Trash2, Monitor, ListChecks, MoreVertical, Globe, Video, ImageIcon } from 'lucide-react';
|
|
138
|
+
import { MessageSquare, Copy, RefreshCw, AlertTriangle, Terminal as TerminalIcon, FileCode, Radio, Pencil, Check, Settings, RotateCcw, FolderOpen, PanelLeft, FileIcon, Download, X, ChevronDown, ChevronUp, Play, ArrowUp, Trash2, Monitor, ListChecks, MoreVertical, Globe, Video, ImageIcon, Bug } from 'lucide-react';
|
|
136
139
|
import { useSidebar } from '@/components/ui/sidebar';
|
|
137
140
|
import {
|
|
138
141
|
Dialog,
|
|
@@ -541,6 +544,80 @@ interface QueuedMessage {
|
|
|
541
544
|
selectedElements?: string | null;
|
|
542
545
|
}
|
|
543
546
|
|
|
547
|
+
/**
|
|
548
|
+
* Gather EVERYTHING a developer might want to debug a session and return it
|
|
549
|
+
* as a single pretty-printed JSON blob suitable for pasting into a bug
|
|
550
|
+
* report. Every field is best-effort — anything that fails to fetch is
|
|
551
|
+
* recorded as `{ __error: '...' }` in its slot so the rest of the dump
|
|
552
|
+
* still arrives.
|
|
553
|
+
*
|
|
554
|
+
* Intentionally chunky: messages include full model-message content,
|
|
555
|
+
* tool inputs/outputs, attachments, todos, plans, checkpoints, working-
|
|
556
|
+
* directory diff, pending approvals, browser recordings, etc. The whole
|
|
557
|
+
* point is "everything we could possibly need."
|
|
558
|
+
*/
|
|
559
|
+
async function buildSessionDebugDump(sessionId: string): Promise<string> {
|
|
560
|
+
const safe = async <T,>(label: string, fn: () => Promise<T>): Promise<T | { __error: string }> => {
|
|
561
|
+
try {
|
|
562
|
+
return await fn();
|
|
563
|
+
} catch (err: any) {
|
|
564
|
+
return { __error: err?.message ?? String(err) };
|
|
565
|
+
}
|
|
566
|
+
};
|
|
567
|
+
|
|
568
|
+
const [
|
|
569
|
+
session,
|
|
570
|
+
messages,
|
|
571
|
+
todos,
|
|
572
|
+
plans,
|
|
573
|
+
checkpoints,
|
|
574
|
+
diff,
|
|
575
|
+
attachments,
|
|
576
|
+
files,
|
|
577
|
+
pendingApprovals,
|
|
578
|
+
pendingInput,
|
|
579
|
+
browserStream,
|
|
580
|
+
browserRecordings,
|
|
581
|
+
] = await Promise.all([
|
|
582
|
+
safe('session', () => getSession(sessionId)),
|
|
583
|
+
safe('messages', () => getSessionMessages(sessionId)),
|
|
584
|
+
safe('todos', () => getSessionTodos(sessionId)),
|
|
585
|
+
safe('plans', () => getSessionPlans(sessionId)),
|
|
586
|
+
safe('checkpoints', () => getSessionCheckpoints(sessionId)),
|
|
587
|
+
safe('diff', () => getSessionDiff(sessionId)),
|
|
588
|
+
safe('attachments', () => getSessionAttachments(sessionId)),
|
|
589
|
+
safe('files', () => getSessionFiles(sessionId)),
|
|
590
|
+
safe('pendingApprovals', () => getPendingApprovals(sessionId)),
|
|
591
|
+
safe('pendingInput', () => getPendingInput(sessionId)),
|
|
592
|
+
safe('browserStream', () => getBrowserStreamStatus(sessionId)),
|
|
593
|
+
safe('browserRecordings', () => getBrowserRecordings(sessionId)),
|
|
594
|
+
]);
|
|
595
|
+
|
|
596
|
+
const dump = {
|
|
597
|
+
__meta: {
|
|
598
|
+
kind: 'sparkecoder-session-debug-dump',
|
|
599
|
+
version: 1,
|
|
600
|
+
capturedAt: new Date().toISOString(),
|
|
601
|
+
sessionId,
|
|
602
|
+
origin: typeof window !== 'undefined' ? window.location.origin : null,
|
|
603
|
+
userAgent: typeof navigator !== 'undefined' ? navigator.userAgent : null,
|
|
604
|
+
},
|
|
605
|
+
session,
|
|
606
|
+
messages,
|
|
607
|
+
todos,
|
|
608
|
+
plans,
|
|
609
|
+
checkpoints,
|
|
610
|
+
diff,
|
|
611
|
+
attachments,
|
|
612
|
+
files,
|
|
613
|
+
pendingApprovals,
|
|
614
|
+
pendingInput,
|
|
615
|
+
browserStream,
|
|
616
|
+
browserRecordings,
|
|
617
|
+
};
|
|
618
|
+
return JSON.stringify(dump, null, 2);
|
|
619
|
+
}
|
|
620
|
+
|
|
544
621
|
export function ChatInterface({ session, isEmbed = false }: ChatInterfaceProps) {
|
|
545
622
|
const { toggleSidebar } = useSidebar();
|
|
546
623
|
const [chatItems, setChatItems] = useState<ChatItem[]>([]);
|
|
@@ -622,6 +699,7 @@ export function ChatInterface({ session, isEmbed = false }: ChatInterfaceProps)
|
|
|
622
699
|
const [sessionFiles, setSessionFiles] = useState<ApiSessionFile[]>([]);
|
|
623
700
|
const [browserRecordingsOpen, setBrowserRecordingsOpen] = useState(false);
|
|
624
701
|
const [browserRecordings, setBrowserRecordings] = useState<BrowserRecordingInfo[]>([]);
|
|
702
|
+
const [copyDebugState, setCopyDebugState] = useState<'idle' | 'copying' | 'copied' | 'error'>('idle');
|
|
625
703
|
|
|
626
704
|
// Load config for available models
|
|
627
705
|
useEffect(() => {
|
|
@@ -2839,6 +2917,39 @@ export function ChatInterface({ session, isEmbed = false }: ChatInterfaceProps)
|
|
|
2839
2917
|
<Video className="size-4 mr-2" />
|
|
2840
2918
|
Browser Recordings
|
|
2841
2919
|
</DropdownMenuItem>
|
|
2920
|
+
<DropdownMenuItem
|
|
2921
|
+
onClick={async () => {
|
|
2922
|
+
setCopyDebugState('copying');
|
|
2923
|
+
try {
|
|
2924
|
+
const json = await buildSessionDebugDump(session.id);
|
|
2925
|
+
await navigator.clipboard.writeText(json);
|
|
2926
|
+
setCopyDebugState('copied');
|
|
2927
|
+
console.log(`[debug-dump] copied ${json.length.toLocaleString()} chars to clipboard for session ${session.id}`);
|
|
2928
|
+
setTimeout(() => setCopyDebugState('idle'), 2500);
|
|
2929
|
+
} catch (err) {
|
|
2930
|
+
console.error('[debug-dump] failed:', err);
|
|
2931
|
+
setCopyDebugState('error');
|
|
2932
|
+
setTimeout(() => setCopyDebugState('idle'), 2500);
|
|
2933
|
+
}
|
|
2934
|
+
}}
|
|
2935
|
+
>
|
|
2936
|
+
{copyDebugState === 'copying' ? (
|
|
2937
|
+
<RefreshCw className="size-4 mr-2 animate-spin" />
|
|
2938
|
+
) : copyDebugState === 'copied' ? (
|
|
2939
|
+
<Check className="size-4 mr-2 text-green-500" />
|
|
2940
|
+
) : copyDebugState === 'error' ? (
|
|
2941
|
+
<AlertTriangle className="size-4 mr-2 text-red-500" />
|
|
2942
|
+
) : (
|
|
2943
|
+
<Bug className="size-4 mr-2" />
|
|
2944
|
+
)}
|
|
2945
|
+
{copyDebugState === 'copying'
|
|
2946
|
+
? 'Gathering…'
|
|
2947
|
+
: copyDebugState === 'copied'
|
|
2948
|
+
? 'Copied to clipboard'
|
|
2949
|
+
: copyDebugState === 'error'
|
|
2950
|
+
? 'Failed — see console'
|
|
2951
|
+
: 'Copy debug JSON'}
|
|
2952
|
+
</DropdownMenuItem>
|
|
2842
2953
|
</DropdownMenuContent>
|
|
2843
2954
|
</DropdownMenu>
|
|
2844
2955
|
</div>
|