dsh-thoughtdag 0.4.18 → 0.4.19
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/README.md +8 -8
- package/dist-app/assets/canonical-C8GEhZR5.js +2 -0
- package/dist-app/assets/{canvas-record-Uj_EllzJ.js → canvas-record-6cBZqSEI.js} +1 -1
- package/dist-app/assets/{claude-code-session-D8ULjNtv.js → claude-code-session-D7tlxs4D.js} +1 -1
- package/dist-app/assets/{codex-session-D8ZZHLnx.js → codex-session-DJn3XLgK.js} +1 -1
- package/dist-app/assets/{dsh-session-IBrxF_lC.js → dsh-session-DWyrhHLx.js} +1 -1
- package/dist-app/assets/{experiment-loop-CtCFBVPU.js → experiment-loop-BB8N8okB.js} +1 -1
- package/dist-app/assets/http-bridge-DqMM7zer.js +1 -0
- package/dist-app/assets/{index-BC-rF3gw.js → index-BGRoRzbH.js} +3 -3
- package/dist-app/assets/index-C9qk6fjz.css +1 -0
- package/dist-app/assets/{index-DTQiL090.js → index-DLrvVMFh.js} +1 -1
- package/dist-app/assets/{index-BFREplWz.js → index-DRLN4EE4.js} +1 -1
- package/dist-app/assets/{index-tIP9lf-g.js → index-DWMhL6gr.js} +130 -129
- package/dist-app/assets/{live-mirror-QfnNBagO.js → live-mirror-DLoRGse9.js} +2 -2
- package/dist-app/assets/{pi-session-FEplLVy8.js → pi-session-5Tb178Vi.js} +1 -1
- package/dist-app/assets/{sensitive-scan-C3rz7OZK.js → sensitive-scan-DoCoBRf1.js} +1 -1
- package/dist-app/assets/{session-handoff-6eOs2FiL.js → session-handoff-BssCXpUd.js} +2 -2
- package/dist-app/assets/{shared-C4tOpQEv.js → shared-CDDxGtwj.js} +1 -1
- package/dist-app/assets/{turndown-plugin-gfm.cjs-GaD2jPKz.js → turndown-plugin-gfm.cjs-CyxpTA69.js} +1 -1
- package/dist-app/assets/{update-check-DWzpvP3c.js → update-check-CwxfRcEJ.js} +1 -1
- package/dist-app/index.html +2 -2
- package/lib/client.js +31 -60
- package/lib/index.js +37 -8
- package/lib/runtime/agents/http.cjs +5 -0
- package/lib/runtime/agents/ops.cjs +35 -1
- package/package.json +4 -4
- package/dist-app/assets/canonical-BOx5kAea.js +0 -2
- package/dist-app/assets/http-bridge-mmwHcDuo.js +0 -1
- package/dist-app/assets/index-BLoL8TBc.css +0 -1
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
const __vite__mapDeps=(i,m=__vite__mapDeps,d=(m.f||(m.f=["assets/index-
|
|
2
|
-
import{_ as l,i as b,t as p,a as h,f as R}from"./index-
|
|
1
|
+
const __vite__mapDeps=(i,m=__vite__mapDeps,d=(m.f||(m.f=["assets/index-DWMhL6gr.js","assets/index-C9qk6fjz.css","assets/experiment-loop-BB8N8okB.js","assets/index-BGRoRzbH.js","assets/canonical-C8GEhZR5.js"])))=>i.map(i=>d[i]);
|
|
2
|
+
import{_ as l,i as b,t as p,a as h,f as R}from"./index-DWMhL6gr.js";function K(d,S){return d.find(y=>(y.rel.split("/").pop()??y.rel).includes(S))}let j=!1,I=null;function H(){I?.()}function z(){const d=window.desktopSessions;if(!d||j)return;j=!0,d.watchStart();let S=!1,y=null;const g=async s=>{if(S){y=s;return}S=!0;try{window.dispatchEvent(new CustomEvent("td:sessions-changed"));const{useProjects:a,subscribedSessionIds:i}=await l(async()=>{const{useProjects:w,subscribedSessionIds:E}=await import("./index-DWMhL6gr.js").then(D=>D.H);return{useProjects:w,subscribedSessionIds:E}},__vite__mapDeps([0,1])),{activeId:c,projects:o}=a.getState(),m=o.find(w=>w.id===c),t=await d.head(s.rootKey,s.rel,262144).catch(()=>"");if(!t)return;const e=b(t);if(!e)return;const f=!!m&&i(m).includes(e);let r=null;if(!f){if(o.some(v=>i(v).includes(e)))return;const{useStore:E}=await l(async()=>{const{useStore:v}=await import("./index-DWMhL6gr.js").then(A=>A.G);return{useStore:v}},__vite__mapDeps([0,1]));if(!E.getState().nodes.some(v=>v.data.importSource?.sessionId===e)){const{parseAnchor:v}=await l(async()=>{const{parseAnchor:k}=await import("./experiment-loop-BB8N8okB.js");return{parseAnchor:k}},__vite__mapDeps([2,0,1])),A=v(t);if(!A||!o.some(k=>k.id===A.project))return;if(r=A.project,r!==c){p("info",h("atlas.mountPending"),9e3);return}}}const{streamRunnerConversation:n}=await l(async()=>{const{streamRunnerConversation:w}=await import("./index-BGRoRzbH.js");return{streamRunnerConversation:w}},__vite__mapDeps([3,0,1])),{importOrAppendConversation:u,shellSessionReader:_}=await l(async()=>{const{importOrAppendConversation:w,shellSessionReader:E}=await import("./canonical-C8GEhZR5.js");return{importOrAppendConversation:w,shellSessionReader:E}},__vite__mapDeps([4,0,1])),V=await n(_(s.rootKey,s.rel)).catch(()=>null),P=await u(V);P?.kind==="appended"?p("success",R(h("atlas.liveAppended"),{n:P.turns}),8e3):P?.kind==="mounted"&&p("success",R(h(P.mode==="continue"?"atlas.mountedChapter":"atlas.mountedBranch"),{n:P.turns}),9e3)}finally{if(S=!1,y){const a=y;y=null,g(a)}}};d.onSessionsChanged(s=>{g(s)});const C=async s=>{if(!s)return;const{useStore:a}=await l(async()=>{const{useStore:o}=await import("./index-DWMhL6gr.js").then(m=>m.G);return{useStore:o}},__vite__mapDeps([0,1])),{useUiStore:i}=await l(async()=>{const{useUiStore:o}=await import("./index-DWMhL6gr.js").then(m=>m.D);return{useUiStore:o}},__vite__mapDeps([0,1])),c=a.getState().nodes.find(o=>o.data.importSource?.itemIds?.includes(s));c&&i.getState().setArrivalFocusNodeId(c.id)},T=async(s,a)=>{const{useProjects:i,switchProject:c}=await l(async()=>{const{useProjects:e,switchProject:f}=await import("./index-DWMhL6gr.js").then(r=>r.H);return{useProjects:e,switchProject:f}},__vite__mapDeps([0,1])),o=i.getState().projects,m=o.filter(e=>e.name===s),t=o.find(e=>e.id===s)??(m.length===1?m[0]:void 0);if(!t){p("error",h("handoff.deeplinkMiss"));return}if(await c(t.id),a){const{useStore:e}=await l(async()=>{const{useStore:r}=await import("./index-DWMhL6gr.js").then(n=>n.G);return{useStore:r}},__vite__mapDeps([0,1])),{useUiStore:f}=await l(async()=>{const{useUiStore:r}=await import("./index-DWMhL6gr.js").then(n=>n.D);return{useUiStore:r}},__vite__mapDeps([0,1]));e.getState().nodes.some(r=>r.id===a)&&f.getState().setArrivalFocusNodeId(a)}},O=async s=>{let a="",i="";try{const n=new URL(s),u=n.searchParams.get("canvas");if(u){await T(u,n.searchParams.get("node")??"");return}a=n.searchParams.get("session")??"",i=n.searchParams.get("turn")??""}catch{return}if(!/^[A-Za-z0-9_-]{8,}$/.test(a))return;/^[A-Za-z0-9_-]*$/.test(i)||(i="");const c=await d.roots().catch(()=>[]);let o=null;for(const n of c){const u=await d.list(n.key).catch(()=>[]),_=K(u,a);if(_){o={rootKey:n.key,rel:_.rel};break}}if(!o){const n=[];for(const u of c)for(const _ of await d.list(u.key).catch(()=>[]))n.push({rootKey:u.key,rel:_.rel,mtime:_.mtime});n.sort((u,_)=>_.mtime-u.mtime);for(const u of n.slice(0,40)){const _=await d.head(u.rootKey,u.rel,262144).catch(()=>"");if(_&&b(_)===a){o=u;break}}}if(!o){p("error",h("handoff.deeplinkMiss"));return}const{streamRunnerConversation:m}=await l(async()=>{const{streamRunnerConversation:n}=await import("./index-BGRoRzbH.js");return{streamRunnerConversation:n}},__vite__mapDeps([3,0,1])),{importOrAppendConversation:t,shellSessionReader:e}=await l(async()=>{const{importOrAppendConversation:n,shellSessionReader:u}=await import("./canonical-C8GEhZR5.js");return{importOrAppendConversation:n,shellSessionReader:u}},__vite__mapDeps([4,0,1])),f=await m(e(o.rootKey,o.rel)).catch(()=>null),r=await t(f);r?r.kind==="appended"?p("success",R(h("atlas.liveAppended"),{n:r.turns}),8e3):r.kind==="mounted"?p("success",R(h(r.mode==="continue"?"atlas.mountedChapter":"atlas.mountedBranch"),{n:r.turns}),9e3):r.kind==="imported"&&p("success",R(h("toast.importedChats"),{n:1,m:r.nodeCount}),8e3):p("error",h("handoff.notASession")),r&&i&&await C(i)};d.onDeepLink?.(s=>{O(s)}),(async()=>{const{bootProjects:s}=await l(async()=>{const{bootProjects:i}=await import("./index-DWMhL6gr.js").then(c=>c.H);return{bootProjects:i}},__vite__mapDeps([0,1]));await s();const a=await d.pendingDeepLink?.().catch(()=>null);a&&O(a)})();const L="thoughtdag.atlas.sweepmark";I=async()=>{const{bootProjects:s}=await l(async()=>{const{bootProjects:t}=await import("./index-DWMhL6gr.js").then(e=>e.H);return{bootProjects:t}},__vite__mapDeps([0,1]));await s();const a=await d.roots().catch(()=>[]),i=[];for(const t of a){const e=await d.list(t.key).catch(()=>[]);for(const f of e)i.push({rootKey:t.key,rel:f.rel,mtime:f.mtime,size:f.size})}let c={};try{c=JSON.parse(localStorage.getItem(L)??"{}")}catch{}const o=Object.keys(c).length===0;i.sort((t,e)=>e.mtime-t.mtime);const m=i.filter((t,e)=>{const f=`${t.mtime}|${t.size}`;return c[`${t.rootKey}|${t.rel}`]===f?!1:o?e<30:!0});for(const t of m)await g({rootKey:t.rootKey,rel:t.rel});for(const t of i)c[`${t.rootKey}|${t.rel}`]=`${t.mtime}|${t.size}`;localStorage.setItem(L,JSON.stringify(c))},I()}export{K as pickSessionFile,z as startLiveMirror,H as sweepRecentSessions};
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import{v as w,B as x,o as T}from"./index-
|
|
1
|
+
import{v as w,B as x,o as T}from"./index-DWMhL6gr.js";import{t as A,a as I,e as l,d as C,T as L,A as h,g as m,f as O,s as S}from"./shared-CDDxGtwj.js";const f=r=>typeof r=="string"?r:Array.isArray(r)?r.filter(t=>t&&t.type==="text"&&typeof t.text=="string").map(t=>t.text).join(`
|
|
2
2
|
`):"";function b(r,t){const s=t&&typeof t=="object"?t:{},e=I(r),n=typeof s.path=="string"&&s.path&&(e==="read"||e==="edit"||e==="write")?[s.path]:[];let o;if(e==="read"&&(typeof s.offset=="number"||typeof s.limit=="number")){const c=Math.max(1,typeof s.offset=="number"?s.offset:1),d=typeof s.limit=="number"?c+Math.max(0,s.limit)-1:c;o={lines:[c,Math.max(c,d)]}}if(e==="write"&&typeof s.content=="string")return{...l(`${s.path??""}
|
|
3
3
|
|
|
4
4
|
${s.content}`,h),paths:n};if(e==="edit"){const c=Array.isArray(s.edits)?s.edits:typeof s.newText=="string"?[{oldText:s.oldText,newText:s.newText}]:[];if(c.length){const d=c.map(i=>`${s.path??""}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import{f as c,a,w as g}from"./index-
|
|
1
|
+
import{f as c,a,w as g}from"./index-DWMhL6gr.js";const k=[{kind:"sk-… key",re:/\bsk-[A-Za-z0-9_-]{16,}\b/g},{kind:"GitHub token",re:/\bgh[pousr]_[A-Za-z0-9]{20,}\b/g},{kind:"AWS access key",re:/\bAKIA[0-9A-Z]{16}\b/g},{kind:"Slack token",re:/\bxox[baprs]-[A-Za-z0-9-]{10,}\b/g},{kind:"Google API key",re:/\bAIza[0-9A-Za-z_-]{35}\b/g},{kind:"JWT",re:/\beyJ[A-Za-z0-9_-]{10,}\.[A-Za-z0-9_-]{10,}\.[A-Za-z0-9_-]{6,}\b/g},{kind:"private key block",re:/-----BEGIN [A-Z ]*PRIVATE KEY-----/g},{kind:"token assignment",re:/\b(?:API_KEY|APIKEY|SECRET|TOKEN|PASSWORD|ACCESS_KEY|AUTH_TOKEN)[A-Z_]*\s*[=:]\s*['"]?[A-Za-z0-9_/+-]{16,}/g},{kind:"HuggingFace token",re:/\bhf_[A-Za-z0-9]{30,}\b/g},{kind:"npm token",re:/\bnpm_[A-Za-z0-9]{30,}\b/g}],f=t=>t.length<=10?`${t.slice(0,4)}…`:`${t.slice(0,6)}…${t.slice(-2)}`;function o(t,e,s){if(t)for(const{kind:i,re:n}of k){n.lastIndex=0;const r=n.exec(t);if(r&&s.push({where:e,kind:i,sample:f(r[0])}),s.length>=20)return}}function l(t){const e=[];for(const s of t){const i=(s.data.question||s.data.summaries?.[0]||s.id).replace(/\s+/g," ").slice(0,28);o(s.data.question,i,e);for(const n of s.data.responses??[])o(n,i,e);for(const n of s.data.attachments??[])n.type.startsWith("image/")||o(n.content,`${i} · ${n.name}`,e);if(e.length>=20)break}return e}async function b(t){const e=l(t);if(e.length===0)return!0;const s=e.slice(0,5).map(n=>`· ${n.where} — ${n.kind}(${n.sample})`).join(`
|
|
2
2
|
`),i=e.length>5?`
|
|
3
3
|
${c(a("sensitive.more"),{n:e.length-5})}`:"";return g({title:a("sensitive.title"),message:`${c(a("sensitive.body"),{n:e.length})}
|
|
4
4
|
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
const __vite__mapDeps=(i,m=__vite__mapDeps,d=(m.f||(m.f=["assets/canonical-
|
|
2
|
-
import{t as n,a as e,_ as p,f as a,u as h}from"./index-
|
|
1
|
+
const __vite__mapDeps=(i,m=__vite__mapDeps,d=(m.f||(m.f=["assets/canonical-C8GEhZR5.js","assets/index-DWMhL6gr.js","assets/index-C9qk6fjz.css"])))=>i.map(i=>d[i]);
|
|
2
|
+
import{t as n,a as e,_ as p,f as a,u as h}from"./index-DWMhL6gr.js";const l=/^http:\/\/(127\.0\.0\.1|localhost|\[::1\])(:\d+)?\//i;async function w(){const s=window.location.hash,r=s.match(/[#&]import-url=([^&]+)/);if(!r)return;const c=/[#&]mode=harvest\b/.test(s);history.replaceState(null,"",window.location.pathname+window.location.search);const i=decodeURIComponent(r[1]);if(!l.test(i)){n("error",e("handoff.notLoopback"),9e3);return}try{const o=await fetch(i);if(!o.ok)throw new Error(`HTTP ${o.status}`);const d=await o.text(),{importOrAppendSession:f}=await p(async()=>{const{importOrAppendSession:u}=await import("./canonical-C8GEhZR5.js");return{importOrAppendSession:u}},__vite__mapDeps([0,1,2])),t=await f(d);if(!t)throw new Error(e("handoff.notASession"));t.kind==="appended"?n("success",a(e("atlas.appended"),{n:t.turns}),9e3):t.kind==="mounted"?n("success",a(e(t.mode==="continue"?"atlas.mountedChapter":"atlas.mountedBranch"),{n:t.turns}),12e3):t.kind==="opened"?n("info",e("atlas.upToDate"),6e3):n("info",a(e("handoff.saved"),{n:t.nodeCount}),12e3,{label:e("handoff.backupAction"),run:()=>h.getState().setBackupDialogOpen(!0)})}catch(o){n("error",a(e("handoff.failed"),{msg:o instanceof Error?o.message:String(o)}),12e3)}}export{w as consumeSessionHandoff};
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import{v as m,o as p,B as h,C as g}from"./index-
|
|
1
|
+
import{v as m,o as p,B as h,C as g}from"./index-DWMhL6gr.js";const _=[[/^(Read|NotebookRead|read_file|view_image)$/i,"read"],[/^(Write|write_file)$/i,"write"],[/^(Edit|MultiEdit|NotebookEdit|apply_patch)$/i,"edit"],[/^(Bash|BashOutput|Shell|exec_command|local_shell|write_stdin)$/i,"run"],[/^(Grep|Glob|LS|Search|WebSearch|web_search)$/i,"search"],[/^(WebFetch|Fetch)$/i,"fetch"],[/^(Task|Agent)$/i,"agent"]];function y(e){return _.find(([t])=>t.test(e))?.[1]??"other"}const x=800,O=32e3,S=4e3,I=(e,t)=>e.length>t?{text:`${e.slice(0,t)}
|
|
2
2
|
…[truncated, ${e.length} chars total]`,truncated:!0}:{text:e,truncated:!1},$=["<command-name>/thoughtdag</command-name>","[[thoughtdag:command]]"];function M(e){return e.filter(t=>!$.some(n=>t.question.includes(n)))}function w(e){e.width=460}function b(e){const t=g(e.data.response,90);t&&(e.data.summaries=[t])}function L(e){return e.tools.map(t=>({id:p(),name:`tool: ${t.name}${t.truncated?" (truncated)":""}`,type:"text/plain",size:t.call.length+t.result.length,content:`[call] ${t.call}
|
|
3
3
|
[result]
|
|
4
4
|
${t.result}`,...t.paths?.length?{paths:t.paths}:{},...t.op?{op:t.op}:{}}))}function k(e,t,n,s,i){if(e.length===0)return null;const r=[],l=[];let u={id:s.id};for(const o of e){const a=m(o.question||"(tool-only turn)",o.response,!1);a.data.importSource={runner:n,sessionId:t,itemIds:o.itemIds,...i?{cwd:i}:{}},a.data.source={question:a.data.question,response:a.data.response},a.data.attachments=L(o),b(a),r.length===0&&(a.data.isBranch=!0),r.push(a),l.push({id:p(),source:u.id,target:a.id,type:"smoothstep"}),u=a}const c=h(r,l.filter(o=>o.source!==s.id)),f=Math.min(...c.map(o=>o.position.x)),d=Math.min(...c.map(o=>o.position.y));for(const o of c)o.position={x:o.position.x-f+s.x+560,y:o.position.y-d+s.y};return{nodes:c,edges:l,turnCount:e.length}}function A(e){const t=e??{},n={};typeof t.url=="string"&&/^https?:\/\//.test(t.url)&&(n.url=t.url);const s={};if(typeof t.pages=="string"&&t.pages.trim()&&(s.pages=t.pages.trim()),typeof t.offset=="number"||typeof t.limit=="number"){const i=Math.max(1,typeof t.offset=="number"?t.offset:1),r=typeof t.limit=="number"?i+Math.max(0,t.limit)-1:i;s.lines=[i,Math.max(i,r)]}return Object.keys(s).length&&(n.locator=s),n}function C(e){const t=e??{},n=t.file_path??t.notebook_path;return typeof n=="string"&&n?[n]:[]}function q(e,t){const n=t??{},s=y(e);return s==="write"&&typeof n.content=="string"?`${n.file_path??""}
|
package/dist-app/assets/{turndown-plugin-gfm.cjs-GaD2jPKz.js → turndown-plugin-gfm.cjs-CyxpTA69.js}
RENAMED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import{A as W}from"./index-
|
|
1
|
+
import{A as W}from"./index-DWMhL6gr.js";function Y(d,p){for(var g=0;g<p.length;g++){const s=p[g];if(typeof s!="string"&&!Array.isArray(s)){for(const c in s)if(c!=="default"&&!(c in d)){const o=Object.getOwnPropertyDescriptor(s,c);o&&Object.defineProperty(d,c,o.get?o:{enumerable:!0,get:()=>s[c]})}}}return Object.freeze(Object.defineProperty(d,Symbol.toStringTag,{value:"Module"}))}var u={},E;function J(){if(E)return u;E=1,Object.defineProperty(u,"__esModule",{value:!0});var d=/highlight-(?:text|source)-([a-z0-9]+)/;function p(t){t.addRule("highlightedCodeBlock",{filter:function(e){var r=e.firstChild;return e.nodeName==="DIV"&&d.test(e.className)&&r&&r.nodeName==="PRE"},replacement:function(e,r,n){var l=r.className||"",i=(l.match(d)||[null,""])[1];return`
|
|
2
2
|
|
|
3
3
|
`+n.fence+i+`
|
|
4
4
|
`+r.firstChild.textContent+`
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import{t as u,a as n,f}from"./index-
|
|
1
|
+
import{t as u,a as n,f}from"./index-DWMhL6gr.js";const h=15*6e4;let i=!1;const d=new URLSearchParams(window.location.search),s=d.get("dv"),p=d.get("su")==="1",w=30*6e4;let c=!1,r=0;async function a(){if(!(!s||p||c)&&!(Date.now()-r<w)){r=Date.now();try{const t=await fetch("https://api.github.com/repos/chenxiachan/thoughtdag/releases?per_page=1");if(!t.ok)return;const o=(await t.json())?.[0]?.tag_name?.replace(/^v/,"");if(!o||o===s)return;c=!0,u("info",f(n("update.desktopAvailable"),{v:o}),0,{label:n("update.desktopDownload"),run:()=>window.open("https://chenxiachan.github.io/thoughtdag/#download","_blank")})}catch{}}}function v(){for(const t of document.querySelectorAll("script[src]")){const e=t.src.match(/assets\/index-[^/?#]+\.js/);if(e)return e[0]}return null}async function m(){try{const t=await fetch(`${window.location.pathname}?u=${Date.now()}`,{cache:"no-store"});if(!t.ok)return null;const e=(await t.text()).match(/assets\/index-[^"'?#]+\.js/);return e?e[0]:null}catch{return null}}async function l(){if(i)return;const t=v();if(!t)return;const e=await m();e&&e!==t&&(i=!0,u("info",n("update.available"),0,{label:n("update.refresh"),run:()=>window.location.reload()}))}function b(){document.addEventListener("visibilitychange",()=>{document.visibilityState==="visible"&&(l(),a())}),setInterval(()=>{l(),a()},h),s&&setTimeout(()=>{a()},5e3)}export{b as bootUpdateCheck};
|
package/dist-app/index.html
CHANGED
|
@@ -22,8 +22,8 @@
|
|
|
22
22
|
<meta name="twitter:title" content="ThoughtDAG — Your thinking deserves a map" />
|
|
23
23
|
<meta name="twitter:description" content="Wires are the context: an infinite canvas where LLM conversations grow into an editable thought graph. No signup; the example canvas needs no key." />
|
|
24
24
|
<meta name="twitter:image" content="https://app.thoughtdag.workers.dev/og-twitter.jpg" />
|
|
25
|
-
<script type="module" crossorigin src="/thoughtdag/assets/index-
|
|
26
|
-
<link rel="stylesheet" crossorigin href="/thoughtdag/assets/index-
|
|
25
|
+
<script type="module" crossorigin src="/thoughtdag/assets/index-DWMhL6gr.js"></script>
|
|
26
|
+
<link rel="stylesheet" crossorigin href="/thoughtdag/assets/index-C9qk6fjz.css">
|
|
27
27
|
</head>
|
|
28
28
|
<body>
|
|
29
29
|
<div id="root"></div>
|
package/lib/client.js
CHANGED
|
@@ -1,26 +1,24 @@
|
|
|
1
1
|
// dsh-thoughtdag client half — the lightest possible browser shim.
|
|
2
|
-
// It renders a "对话 | 思维图" switch
|
|
3
|
-
// `conversation.session.header.actions`, so it flows with the native layout
|
|
4
|
-
// on desktop and mobile web instead of floating over the title bar) and, on
|
|
2
|
+
// It renders a floating "对话 | 思维图" switch over the harness UI and, on
|
|
5
3
|
// "思维图", shows a full-screen SAME-ORIGIN iframe at /thoughtdag/ (the SPA
|
|
6
4
|
// is served by the host half on the same web server — no CORS, no second
|
|
7
|
-
// origin)
|
|
8
|
-
//
|
|
5
|
+
// origin). The switch floats on purpose: it is there before any session is
|
|
6
|
+
// open, and it is the same control in both views (0.4.18 moved it into the
|
|
7
|
+
// session header, which hid it on the empty page and left a separate
|
|
8
|
+
// capsule over the canvas; both went back in 0.4.19). All conversation smarts live inside the ThoughtDAG app; this file
|
|
9
9
|
// only opens the door and forwards the current session id so the canvas can
|
|
10
10
|
// offer to mirror it.
|
|
11
11
|
//
|
|
12
12
|
// Same pattern as dsh-synapse: window.__ModuleLoader__.load with a module
|
|
13
|
-
// whose inject lists the client services it reads (sessions
|
|
14
|
-
//
|
|
15
|
-
// require answers it from the module table, so the bundle stays tiny.
|
|
13
|
+
// whose inject lists the client services it reads (sessions) and whose apply
|
|
14
|
+
// touches the DOM.
|
|
16
15
|
|
|
17
16
|
window.__ModuleLoader__.load({
|
|
18
17
|
id: 'dsh-thoughtdag',
|
|
19
|
-
factory:
|
|
18
|
+
factory: () => {
|
|
20
19
|
const module = { exports: {} }
|
|
21
|
-
const React = require('react')
|
|
22
20
|
|
|
23
|
-
module.exports.inject = ['sessions'
|
|
21
|
+
module.exports.inject = ['sessions']
|
|
24
22
|
module.exports.apply = ctx => {
|
|
25
23
|
const currentSession = () => {
|
|
26
24
|
const snapshot = ctx.sessions.list.getSnapshot()
|
|
@@ -31,26 +29,29 @@ window.__ModuleLoader__.load({
|
|
|
31
29
|
}
|
|
32
30
|
|
|
33
31
|
const style = document.createElement('style')
|
|
34
|
-
style.textContent = '.dsh-td-switch{display:
|
|
32
|
+
style.textContent = '.dsh-td-switch{position:fixed;z-index:120;top:12px;left:50%;display:flex;gap:2px;transform:translateX(-50%);border:1px solid #d1d5db;border-radius:999px;background:rgba(255,255,255,.96);padding:3px;backdrop-filter:blur(10px)}.dsh-td-switch button{height:28px;border:0;border-radius:999px;background:transparent;padding:0 11px;color:#6b7280;font:600 12px Inter,system-ui,sans-serif;cursor:pointer;white-space:nowrap}.dsh-td-switch button:hover{background:#f3f4f6;color:#111827}.dsh-td-switch button.active{background:#111827;color:#fff}.dsh-td-overlay{position:fixed;z-index:100;inset:0;background:#faf9f7}.dsh-td-overlay[hidden]{display:none}.dsh-td-overlay iframe{display:block;width:100%;height:100%;border:0}'
|
|
35
33
|
document.head.append(style)
|
|
36
34
|
|
|
37
|
-
const
|
|
38
|
-
|
|
39
|
-
document.body.append(
|
|
40
|
-
const overlay = overlayHost.querySelector('.dsh-td-overlay')
|
|
41
|
-
const frame = overlayHost.querySelector('iframe')
|
|
42
|
-
const backBtn = overlayHost.querySelector('.dsh-td-back')
|
|
35
|
+
const host = document.createElement('div')
|
|
36
|
+
host.innerHTML = '<div class="dsh-td-switch" role="group" aria-label="view switch"><button type="button" data-view="dialog" class="active" aria-pressed="true">对话</button><button type="button" data-view="map" aria-pressed="false">思维图</button></div><section class="dsh-td-overlay" hidden><iframe title="ThoughtDAG" data-src="/thoughtdag/"></iframe></section>'
|
|
37
|
+
document.body.append(host)
|
|
43
38
|
|
|
44
39
|
// the plugin's version, for the canvas's update dialog and release history
|
|
45
40
|
let pluginVersion = null
|
|
46
41
|
fetch('/thoughtdag/api/version').then(r => (r.ok ? r.json() : null)).then(j => { if (j && typeof j.version === 'string') pluginVersion = j.version }).catch(() => {})
|
|
47
42
|
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
const mapSubscribers = new Set()
|
|
43
|
+
const dialogBtn = host.querySelector('[data-view="dialog"]')
|
|
44
|
+
const mapBtn = host.querySelector('[data-view="map"]')
|
|
45
|
+
const overlay = host.querySelector('.dsh-td-overlay')
|
|
46
|
+
const frame = host.querySelector('iframe')
|
|
53
47
|
|
|
48
|
+
const setView = map => {
|
|
49
|
+
dialogBtn.classList.toggle('active', !map)
|
|
50
|
+
dialogBtn.setAttribute('aria-pressed', String(!map))
|
|
51
|
+
mapBtn.classList.toggle('active', map)
|
|
52
|
+
mapBtn.setAttribute('aria-pressed', String(map))
|
|
53
|
+
}
|
|
54
|
+
const close = () => { overlay.hidden = true; setView(false); send('td:view', { shown: false }) }
|
|
54
55
|
const send = (type, payload) => frame.contentWindow?.postMessage({ source: 'dsh-thoughtdag', type, ...payload }, location.origin)
|
|
55
56
|
|
|
56
57
|
const syncCurrent = () => {
|
|
@@ -58,11 +59,9 @@ window.__ModuleLoader__.load({
|
|
|
58
59
|
send('td:current-session', { session })
|
|
59
60
|
}
|
|
60
61
|
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
for (const notify of mapSubscribers) notify(map)
|
|
65
|
-
if (!map) { send('td:view', { shown: false }); return }
|
|
62
|
+
mapBtn.addEventListener('click', () => {
|
|
63
|
+
overlay.hidden = false
|
|
64
|
+
setView(true)
|
|
66
65
|
// the SPA boots on first open, never while hidden: a canvas that
|
|
67
66
|
// measures itself inside a display:none frame fits its view to a 0×0
|
|
68
67
|
// box and shows nothing when revealed
|
|
@@ -71,40 +70,12 @@ window.__ModuleLoader__.load({
|
|
|
71
70
|
send('td:view', { shown: true })
|
|
72
71
|
// let the SPA boot, then re-sync so its listener is ready
|
|
73
72
|
window.setTimeout(() => { syncCurrent(); send('td:view', { shown: true }) }, 400)
|
|
74
|
-
}
|
|
75
|
-
|
|
76
|
-
const Switch = () => {
|
|
77
|
-
const [map, setMapState] = React.useState(mapState)
|
|
78
|
-
React.useEffect(() => {
|
|
79
|
-
const notify = m => setMapState(m)
|
|
80
|
-
mapSubscribers.add(notify)
|
|
81
|
-
return () => { mapSubscribers.delete(notify) }
|
|
82
|
-
}, [])
|
|
83
|
-
return React.createElement('div', { className: 'dsh-td-switch', role: 'group', 'aria-label': 'view switch' },
|
|
84
|
-
React.createElement('button', {
|
|
85
|
-
type: 'button', 'data-view': 'dialog', className: map ? '' : 'active', 'aria-pressed': String(!map),
|
|
86
|
-
onClick: () => setMap(false),
|
|
87
|
-
}, '对话'),
|
|
88
|
-
React.createElement('button', {
|
|
89
|
-
type: 'button', 'data-view': 'map', className: map ? 'active' : '', 'aria-pressed': String(map),
|
|
90
|
-
onClick: () => setMap(true),
|
|
91
|
-
}, '思维图'),
|
|
92
|
-
)
|
|
93
|
-
}
|
|
94
|
-
|
|
95
|
-
ctx.slots.inject('conversation.session.header.actions', () =>
|
|
96
|
-
ctx.slots.register({
|
|
97
|
-
name: 'conversation.session.header.actions',
|
|
98
|
-
id: 'thoughtdag-view-switch',
|
|
99
|
-
order: 90,
|
|
100
|
-
}, Switch),
|
|
101
|
-
)
|
|
102
|
-
|
|
103
|
-
backBtn.addEventListener('click', () => setMap(false))
|
|
73
|
+
})
|
|
74
|
+
dialogBtn.addEventListener('click', close)
|
|
104
75
|
|
|
105
76
|
window.addEventListener('message', event => {
|
|
106
77
|
if (event.origin !== location.origin || event.data?.source !== 'dsh-thoughtdag') return
|
|
107
|
-
if (event.data.type === 'td:close') return
|
|
78
|
+
if (event.data.type === 'td:close') return close()
|
|
108
79
|
if (event.data.type === 'td:request-current') return syncCurrent()
|
|
109
80
|
// the canvas forked or continued a session: stage it and go back to the
|
|
110
81
|
// chat, which now shows exactly the context the canvas produced
|
|
@@ -113,7 +84,7 @@ window.__ModuleLoader__.load({
|
|
|
113
84
|
// older runtimes (0.1.1) still call it select
|
|
114
85
|
const select = ctx.sessions.open ?? ctx.sessions.select
|
|
115
86
|
select.call(ctx.sessions, event.data.session)
|
|
116
|
-
if (event.data.close !== false)
|
|
87
|
+
if (event.data.close !== false) close()
|
|
117
88
|
syncCurrent()
|
|
118
89
|
}
|
|
119
90
|
})
|
package/lib/index.js
CHANGED
|
@@ -723,7 +723,8 @@ async function runAgentTurn(ctx, body, emit, isClosed, { answerApprovals = true
|
|
|
723
723
|
const picked = agentTargetOf(body?.model)
|
|
724
724
|
if (picked && !hasImages) await ctx.sessionController.selectModel({ sessionId, provider: picked.provider, model: picked.model }).catch(() => {})
|
|
725
725
|
const agent = await agentOf(ctx, sessionId)
|
|
726
|
-
let sawChunk = false
|
|
726
|
+
let sawChunk = false // text deltas reached us live
|
|
727
|
+
let sawReasoning = false // reasoning deltas reached us live
|
|
727
728
|
let fullText = ''
|
|
728
729
|
let done
|
|
729
730
|
const finished = new Promise(resolve => { done = resolve })
|
|
@@ -740,6 +741,26 @@ async function runAgentTurn(ctx, body, emit, isClosed, { answerApprovals = true
|
|
|
740
741
|
const claimTurn = (turn) => { ourTurn = turn; turnEntry.turn = turn }
|
|
741
742
|
const isOurs = (event) => ourTurn !== null && (typeof event.data?.turn === 'number' ? event.data.turn === ourTurn : currentTurn === ourTurn)
|
|
742
743
|
turnEntry.current = () => currentTurn
|
|
744
|
+
const onDelta = (c) => {
|
|
745
|
+
if (c?.type === 'text-delta' && c.text) { sawChunk = true; fullText += c.text; emit({ text: c.text }) }
|
|
746
|
+
else if (c?.type === 'reasoning-delta' && c.text) { sawReasoning = true; emit({ reasoning: c.text }) }
|
|
747
|
+
}
|
|
748
|
+
// Since 0.1.5-rc.3 the deltas are no longer rows of the session log: the
|
|
749
|
+
// loop publishes them process-locally as agent/assistant-stream frames
|
|
750
|
+
// (start names the turn and step, chunk carries one model delta, end
|
|
751
|
+
// points at the committed assistant/message). Only OUR turn's attempts
|
|
752
|
+
// are followed; the committed message still arrives on the log and is
|
|
753
|
+
// then skipped as already streamed. On an older runtime this event never
|
|
754
|
+
// fires and the log rows above carry the deltas as before.
|
|
755
|
+
const attemptTurn = new Map()
|
|
756
|
+
const offStream = ctx.on('agent/assistant-stream', ({ agent, frame }) => {
|
|
757
|
+
if (agent?.session?.id !== sessionId || !frame) return
|
|
758
|
+
if (frame.type === 'start') { if (typeof frame.turn === 'number') attemptTurn.set(frame.attemptId, frame.turn); return }
|
|
759
|
+
const turn = attemptTurn.get(frame.attemptId)
|
|
760
|
+
if (frame.type === 'end') { attemptTurn.delete(frame.attemptId); return }
|
|
761
|
+
if (turn === undefined || ourTurn === null || turn !== ourTurn) return
|
|
762
|
+
if (frame.type === 'chunk') onDelta(frame.chunk)
|
|
763
|
+
})
|
|
743
764
|
const off = ctx.on('session/event', (session, event) => {
|
|
744
765
|
if (session?.id !== sessionId || !event) return
|
|
745
766
|
if (event.type === 'turn/start') {
|
|
@@ -762,13 +783,20 @@ async function runAgentTurn(ctx, body, emit, isClosed, { answerApprovals = true
|
|
|
762
783
|
}
|
|
763
784
|
if (!isOurs(event)) return
|
|
764
785
|
if (event.type === 'assistant/chunk') {
|
|
765
|
-
|
|
766
|
-
|
|
767
|
-
|
|
768
|
-
|
|
769
|
-
//
|
|
770
|
-
const
|
|
771
|
-
if (
|
|
786
|
+
// up to 0.1.5-rc.2 the deltas are rows of the session log
|
|
787
|
+
onDelta(event.data?.chunk)
|
|
788
|
+
} else if (event.type === 'assistant/message') {
|
|
789
|
+
// deltas did not reach us live (a compacted row, or a runtime whose
|
|
790
|
+
// stream we do not know): the whole step at once, reasoning first
|
|
791
|
+
const blocks = event.data?.message?.content ?? []
|
|
792
|
+
if (!sawReasoning) {
|
|
793
|
+
const reasoning = blocks.filter(b => b.type === 'reasoning').map(b => (typeof b.text === 'string' ? b.text : '')).join('')
|
|
794
|
+
if (reasoning) emit({ reasoning })
|
|
795
|
+
}
|
|
796
|
+
if (!sawChunk) {
|
|
797
|
+
const text = blocks.filter(b => b.type === 'text').map(b => b.text).join('')
|
|
798
|
+
if (text) { fullText += text; emit({ text }) }
|
|
799
|
+
}
|
|
772
800
|
} else if (event.type === 'tool/call' || event.type === 'tool/code-dispatch-start') {
|
|
773
801
|
if (event.data?.callId) turnEntry.calls.set(event.data.callId, { name: event.data?.name ?? 'tool', arguments: event.data?.arguments })
|
|
774
802
|
emit({ tool: { name: event.data?.name ?? 'tool', query: toolQuery(event.data?.name, event.data?.arguments) } })
|
|
@@ -791,6 +819,7 @@ async function runAgentTurn(ctx, body, emit, isClosed, { answerApprovals = true
|
|
|
791
819
|
if (isClosed()) { try { agent.cancel({ kind: 'user' }) } catch { /* best effort */ } }
|
|
792
820
|
} finally {
|
|
793
821
|
if (typeof off === 'function') off()
|
|
822
|
+
if (typeof offStream === 'function') offStream()
|
|
794
823
|
if (canvasTurns.get(sessionId) === turnEntry) canvasTurns.delete(sessionId)
|
|
795
824
|
}
|
|
796
825
|
return { sessionId, text: fullText }
|
|
@@ -77,6 +77,11 @@ function createAgentsHttp({ workspaceRoot = path.join(os.homedir(), '.thoughtdag
|
|
|
77
77
|
const id = String(body?.runId ?? '');
|
|
78
78
|
return json(res, 200, { ok: runtime(owners.get(id)).answer(id, String(body?.requestId ?? ''), body?.response) }), true;
|
|
79
79
|
}
|
|
80
|
+
if (p === '/agents/dirs' && method === 'GET') {
|
|
81
|
+
// the directory browser's one level; a bad path is a 404 the client shows in place
|
|
82
|
+
try { return json(res, 200, await ops.listDirectory(url.searchParams.get('path') ?? '')), true; }
|
|
83
|
+
catch (e) { return json(res, 404, { error: String(e?.message ?? e) }), true; }
|
|
84
|
+
}
|
|
80
85
|
if (p === '/agents/workspace' && method === 'POST') return json(res, 200, { dir: await ops.workspaceFor(workspaceRoot, String(body?.canvasId ?? 'default')) }), true;
|
|
81
86
|
if (p === '/agents/guard' && method === 'POST') return json(res, 200, { ok: await ops.writeGuard(String(body?.cwd ?? ''), body?.config) }), true;
|
|
82
87
|
if (p === '/agents/materials' && method === 'POST') return json(res, 200, await ops.writeMaterials(String(body?.cwd ?? ''), body?.files)), true;
|
|
@@ -4,6 +4,7 @@
|
|
|
4
4
|
// the harness plugin host and the local server alike.
|
|
5
5
|
'use strict';
|
|
6
6
|
const path = require('node:path');
|
|
7
|
+
const os = require('node:os');
|
|
7
8
|
const fsp = require('node:fs/promises');
|
|
8
9
|
|
|
9
10
|
const WORKSPACE_ID = /^[\w.-]{1,80}$/;
|
|
@@ -51,4 +52,37 @@ async function writeGuard(cwd, config) {
|
|
|
51
52
|
return true;
|
|
52
53
|
}
|
|
53
54
|
|
|
54
|
-
|
|
55
|
+
/** How many child directories one listing reports at most; the rest is the
|
|
56
|
+
* name-sorted tail and the listing says it was cut. */
|
|
57
|
+
const DIR_LIST_LIMIT = 400;
|
|
58
|
+
|
|
59
|
+
/** One level of the host's filesystem, for a browser the person walks to
|
|
60
|
+
* pick a working directory: the directory itself, its ancestry as crumbs
|
|
61
|
+
* (every one a jump target), its child directories name-sorted (symlinks
|
|
62
|
+
* to directories included, hidden ones flagged and left to the client),
|
|
63
|
+
* and the home directory to root a "Home" crumb. No path given lists the
|
|
64
|
+
* home directory; an unreadable or missing one throws. */
|
|
65
|
+
async function listDirectory(target) {
|
|
66
|
+
const home = os.homedir();
|
|
67
|
+
const dir = path.resolve(typeof target === 'string' && target.trim() ? target.trim() : home);
|
|
68
|
+
const st = await fsp.stat(dir);
|
|
69
|
+
if (!st.isDirectory()) throw new Error('not a directory');
|
|
70
|
+
const crumbs = [];
|
|
71
|
+
for (let cur = dir; ; cur = path.dirname(cur)) {
|
|
72
|
+
const parent = path.dirname(cur);
|
|
73
|
+
crumbs.unshift({ name: parent === cur ? cur : path.basename(cur), path: cur, hidden: false });
|
|
74
|
+
if (parent === cur) break;
|
|
75
|
+
}
|
|
76
|
+
const dirents = await fsp.readdir(dir, { withFileTypes: true });
|
|
77
|
+
const entries = [];
|
|
78
|
+
for (const d of dirents) {
|
|
79
|
+
let isDir = d.isDirectory();
|
|
80
|
+
if (!isDir && d.isSymbolicLink()) { try { isDir = (await fsp.stat(path.join(dir, d.name))).isDirectory(); } catch { isDir = false; } }
|
|
81
|
+
if (isDir) entries.push({ name: d.name, path: path.join(dir, d.name), hidden: d.name.startsWith('.') });
|
|
82
|
+
}
|
|
83
|
+
entries.sort((a, b) => a.name.localeCompare(b.name));
|
|
84
|
+
const truncated = entries.length > DIR_LIST_LIMIT;
|
|
85
|
+
return { path: dir, home, crumbs, entries: truncated ? entries.slice(0, DIR_LIST_LIMIT) : entries, truncated };
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
module.exports = { workspaceFor, writeMaterials, writeGuard, listDirectory };
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "dsh-thoughtdag",
|
|
3
|
-
"version": "0.4.
|
|
3
|
+
"version": "0.4.19",
|
|
4
4
|
"description": "ThoughtDAG for DeepSeek Harness: turn the current DSH session into an editable thought graph on an infinite canvas.",
|
|
5
5
|
"author": "Xia Chen",
|
|
6
6
|
"repository": {
|
|
@@ -42,8 +42,7 @@
|
|
|
42
42
|
"inject": [
|
|
43
43
|
"@deepseek-ai/dsh-client-modules",
|
|
44
44
|
"@deepseek-ai/dsh-api-session-controller",
|
|
45
|
-
"@deepseek-ai/dsh-client-connection"
|
|
46
|
-
"@deepseek-ai/dsh-client-ui-conversation"
|
|
45
|
+
"@deepseek-ai/dsh-client-connection"
|
|
47
46
|
],
|
|
48
47
|
"immediately": false
|
|
49
48
|
},
|
|
@@ -51,7 +50,8 @@
|
|
|
51
50
|
"dshReleases": {
|
|
52
51
|
"0.1.2-rc.1": "compatible",
|
|
53
52
|
"0.1.5-rc.1": "compatible",
|
|
54
|
-
"0.1.5-rc.2": "compatible"
|
|
53
|
+
"0.1.5-rc.2": "compatible",
|
|
54
|
+
"0.1.5-rc.3": "compatible"
|
|
55
55
|
}
|
|
56
56
|
}
|
|
57
57
|
},
|
|
@@ -1,2 +0,0 @@
|
|
|
1
|
-
const __vite__mapDeps=(i,m=__vite__mapDeps,d=(m.f||(m.f=["assets/index-BC-rF3gw.js","assets/index-tIP9lf-g.js","assets/index-BLoL8TBc.css","assets/experiment-loop-CtCFBVPU.js"])))=>i.map(i=>d[i]);
|
|
2
|
-
import{c as N,b as y,_ as E,p as q,r as M,h as O,a as H,u as j,j as X,s as B,k as Q,l as z,f as U,m as $,n as W,t as Y,o as F,q as Z,v as tt}from"./index-tIP9lf-g.js";const et=190;async function dt(o){const{anyRunnerSessionConversation:n}=await E(async()=>{const{anyRunnerSessionConversation:a}=await import("./index-BC-rF3gw.js");return{anyRunnerSessionConversation:a}},__vite__mapDeps([0,1,2])),e=await n(o);return V(e)}function at(o,n){let a=0,s=!1;return async()=>{if(s)return null;const c=await window.desktopSessions.readRange(o,n,a,8388608);return a=c.nextStart,c.eof&&(s=!0),c.text}}function L(o){if(!o)return null;for(const n of N.getState().projects){const e=n.sourceSession;if(!e)continue;if(e.sessionId===o)return{project:n,entry:e};const a=e.chapters?.find(c=>c.sessionId===o);if(a)return{project:n,entry:a};const s=e.branches?.find(c=>c.sessionId===o);if(s)return{project:n,entry:s}}return null}function K(o,n,e,a,s){const c=a.position.x+(s?560:0),m=c-40,d=c+580,t=o.nodes.reduce((w,S)=>{const x=S.width??S.measured?.width??540;if(S.position.x+x<m||S.position.x>d)return w;const l=S.height??S.measured?.height??300;return Math.max(w,S.position.y+l)},s?a.position.y-300:a.position.y+(a.height??140)),u=c-n[0].position.x,f=Math.max(t+et,s?a.position.y:-1/0)-n[0].position.y,i=n.map(w=>({...w,position:{x:w.position.x+u,y:w.position.y+f}})),h=[{id:F(),source:a.id,target:i[0].id,type:"smoothstep"},...e];return{moved:i,edges:h}}async function V(o){if(!o)return null;const n=o.build(),e=n.nodes.filter(m=>m.data.importSource),a=e.at(-1)?.id??n.nodes.at(-1)?.id??"";if(n.nodes.length===0)return null;const s=L(o.sessionId);if(s)return G(o,n,e,a,s);if(o.sessionId){const m=await st(o.sessionId);if(m){let d=-1,t="";if(e.forEach((u,f)=>{const i=u.data.importSource?.itemIds?.[0],h=i?m.byFirstId.get(i):void 0;h&&(d=f,t=h)}),d>=0){await M(m.projectId,"chapter",{sessionId:o.sessionId,runner:o.source,importedCount:d+1,tailNodeId:t});const u=L(o.sessionId);if(u)return G(o,n,e,a,u)}}}if(o.sessionId&&e.length>0){const{parseAnchor:m}=await E(async()=>{const{parseAnchor:t}=await import("./experiment-loop-CtCFBVPU.js");return{parseAnchor:t}},__vite__mapDeps([3,1,2])),d=m(e[0].data.question??"");if(d&&N.getState().projects.some(t=>t.id===d.project)){await O(d.project);const t=y.getState(),u=N.getState().projects.find(i=>i.id===d.project);let f=t.nodes.find(i=>i.id===d.node)??null;if(!f&&d.mode==="continue"&&u.sourceSession?.sessionId){const i=u.sourceSession;f=t.nodes.find(h=>h.id===i.tailNodeId)??t.nodes.filter(h=>h.data.importSource?.sessionId===i.sessionId).at(-1)??null}if(f){const i=n.nodes.find(l=>l.data.importSource&&l.data.stepKind!=="note");if(i&&m(i.data.question??"")){const l=H("exp.openerMark");i.data={...i.data,question:l,source:i.data.source?{...i.data.source,question:l}:i.data.source}}const h=new Set(n.nodes.map(l=>l.id)),w=n.edges.filter(l=>h.has(l.source)&&h.has(l.target)),S=d.mode!=="continue",x=K(t,n.nodes,w,f,S);if(S){const l=x.moved.find(_=>_.data.importSource&&_.data.stepKind!=="note");l&&(l.data={...l.data,isBranch:!0})}return t.pushHistory(),y.setState(l=>({nodes:[...l.nodes,...x.moved],edges:[...l.edges,...x.edges]})),await M(d.project,S?"branch":"chapter",{sessionId:o.sessionId,runner:o.source,importedCount:e.length,tailNodeId:a,anchorNodeId:f.id}),j.getState().setArrivalFocusNodeId(x.moved[x.moved.length-1].id),{kind:"mounted",mode:S?"branch":"continue",turns:e.length}}}}const c=crypto.randomUUID();return await X(q(c),JSON.stringify({state:{nodes:B(n.nodes),edges:n.edges},version:1})),j.getState().setArrivalFocusNodeId(n.nodes[n.nodes.length-1].id),await Q(c,o.title.slice(0,60),"chat",o.sessionId?{sourceSession:{sessionId:o.sessionId,runner:o.source,importedCount:e.length,tailNodeId:a}}:void 0),{kind:"imported",nodeCount:n.nodes.length}}async function ct(o,n){if(!o||!o.sessionId)return null;if(L(o.sessionId))return V(o);const e=o.build(),a=e.nodes.filter(i=>i.data.importSource);if(e.nodes.length===0)return null;await O(n);const s=y.getState(),c=N.getState().projects.find(i=>i.id===n);if(!c)return null;const m=c.sourceSession,d=(m?.sessionId?s.nodes.find(i=>i.id===m.tailNodeId)??s.nodes.filter(i=>i.data.importSource?.sessionId===m.sessionId).at(-1):null)??s.nodes.at(-1)??null;if(!d)return null;const t=new Set(e.nodes.map(i=>i.id)),u=e.edges.filter(i=>t.has(i.source)&&t.has(i.target)),f=K(s,e.nodes,u,d,!1);return s.pushHistory(),y.setState(i=>({nodes:[...i.nodes,...f.moved],edges:[...i.edges,...f.edges]})),await M(n,"chapter",{sessionId:o.sessionId,runner:o.source,importedCount:a.length,tailNodeId:a.at(-1)?.id??e.nodes.at(-1).id,anchorNodeId:d.id}),j.getState().setArrivalFocusNodeId(f.moved[f.moved.length-1].id),{kind:"mounted",mode:"continue",turns:a.length}}async function st(o){const{projects:n,activeId:e}=N.getState(),a=[...n].sort((s,c)=>s.id===e?-1:c.id===e?1:c.updatedAt-s.updatedAt);for(const s of a){if(s.id!==e&&s.provenanceSessions&&!s.provenanceSessions.includes(o))continue;let c;if(s.id===e)c=y.getState().nodes;else try{const{get:d}=await E(async()=>{const{get:f}=await import("./index-tIP9lf-g.js").then(i=>i.F);return{get:f}},__vite__mapDeps([1,2])),t=await d(q(s.id));c=(typeof t=="string"?JSON.parse(t):t)?.state?.nodes??[]}catch{continue}if(s.id!==e&&!s.provenanceSessions){const d=[...new Set(c.map(t=>t.data.importSource?.sessionId).filter(t=>!!t))];N.setState(t=>({projects:t.projects.map(u=>u.id===s.id?{...u,provenanceSessions:d}:u)}))}const m=new Map;for(const d of c)if(d.data.importSource?.sessionId===o&&d.data.stepKind!=="note"){const t=d.data.importSource.itemIds?.[0];t&&m.set(t,d.id)}if(m.size>0)return{projectId:s.id,byFirstId:m}}return null}async function G(o,n,e,a,s){await O(s.project.id);const c=y.getState(),m=c.nodes.filter(p=>p.data.importSource?.sessionId===o.sessionId),d=c.nodes.find(p=>p.id===s.entry.tailNodeId)??m.at(-1)??null,t=s.entry.importedCount>0&&e.length>=s.entry.importedCount?e[s.entry.importedCount-1]:null;if(t){const p=t.data.importSource?.itemIds?.[0],r=p?m.find(C=>C.data.importSource?.itemIds?.[0]===p):void 0,g=r?.data.source,k=!!g&&r.data.question===g.question&&(r.data.response??"")===(g.response??""),I=t.data,D=!!r&&(I.question!==r.data.question||(I.response??"")!==(r.data.response??"")),A=r?.data.attachments??[],T=I.attachments??[],J=!!r&&T.length>A.length&&A.every((C,R)=>T[R]?.name===C.name);if(r&&k&&(D||J)){const C=D?I.attachments:[...A,...T.slice(A.length)];y.setState(R=>({nodes:R.nodes.map(P=>P.id===r.id?{...P,data:{...P.data,question:I.question,response:I.response,responses:I.responses,responseIndex:I.responseIndex,tokenCount:I.tokenCount,attachments:C,importSource:I.importSource,source:I.source}}:P)})),y.getState().recomputeStaleness()}}if(e.length<=s.entry.importedCount)return j.getState().setArrivalFocusNodeId(d?.id??null),{kind:"opened"};const u=e[s.entry.importedCount],f=n.nodes.findIndex(p=>p.id===u.id),i=n.nodes.slice(f),h=new Set(i.map(p=>p.id)),w=n.edges.filter(p=>h.has(p.source)&&h.has(p.target)),S=new Map;for(const p of m){const r=p.data.importSource?.itemIds?.[0];r&&S.set(r,p.id)}const x=new Map;for(const p of n.nodes){const r=p.data.importSource?.itemIds?.[0];r&&!h.has(p.id)&&x.set(p.id,r)}const l=[];for(const p of n.edges){if(!h.has(p.target)||h.has(p.source))continue;const r=x.get(p.source),g=r?S.get(r):void 0;g&&l.push({...p,id:F(),source:g})}const _=new Set(l.map(p=>p.target));let v,b;if(d){const p=K(c,i,w,d,!1);v=p.moved;const r=new Set(w.map(g=>g.target));b=p.edges.filter(g=>!(g.source===d.id&&_.has(g.target)));for(const g of v)g.id!==v[0].id&&!r.has(g.id)&&!_.has(g.id)&&g.data.stepKind!=="note"&&b.push({id:F(),source:d.id,target:g.id,type:"smoothstep"});b=[...b,...l]}else{const r=(c.nodes.length?Math.max(...c.nodes.map(I=>I.position.x)):0)+560-i[0].position.x,g=-i[0].position.y;v=i.map(I=>({...I,position:{x:I.position.x+r,y:I.position.y+g}}));const k=nt(ot(e.length-s.entry.importedCount),v[0]);v=[k,...v],b=[{id:F(),source:k.id,target:v[1].id,type:"smoothstep"},...w]}return c.pushHistory(),y.setState(p=>({nodes:[...p.nodes,...v],edges:[...p.edges,...b]})),await Z(s.project.id,o.sessionId,{importedCount:e.length,tailNodeId:a}),j.getState().setArrivalFocusNodeId(v[d?0:1].id),{kind:"appended",turns:e.length-s.entry.importedCount}}function ot(o){return`[Mirror] The source session grew by ${o} turn(s); the earlier mirrored turns were removed from this canvas by hand, so the new turns land here on their own.`}function nt(o,n){const e=tt(o,"",!1);return e.data.stepKind="note",e.data.importSource=n.data.importSource?{...n.data.importSource,itemIds:[]}:void 0,e.width=460,e.position={x:n.position.x-520,y:n.position.y},e}async function ut(o){const{projects:n,activeId:e}=N.getState(),a=n.find(t=>t.id===o);if(!a?.sourceSession)return"native";if((a.sourceSession.chapters?.length??0)>0||(a.sourceSession.branches?.length??0)>0)return"diverged-mirror";let s;if(o===e)s=y.getState().nodes;else{const{get:t}=await E(async()=>{const{get:f}=await import("./index-tIP9lf-g.js").then(i=>i.F);return{get:f}},__vite__mapDeps([1,2])),u=await t(q(o));try{s=(typeof u=="string"?JSON.parse(u):u)?.state?.nodes??[]}catch{return"diverged-mirror"}}const c=a.sourceSession.sessionId,m=s.filter(t=>t.data.importSource?.sessionId===c);return s.some(t=>!t.data.importSource)||s.some(t=>t.data.importSource&&t.data.importSource.sessionId!==c)||m.filter(t=>t.data.source).length<a.sourceSession.importedCount||m.some(t=>t.data.source&&(t.data.question!==t.data.source.question||t.data.response!==t.data.source.response))?"diverged-mirror":"pristine-mirror"}async function pt(){const{bootProjects:o}=await E(async()=>{const{bootProjects:u}=await import("./index-tIP9lf-g.js").then(f=>f.H);return{bootProjects:u}},__vite__mapDeps([1,2]));await o();const{projects:n,activeId:e}=N.getState(),a=n.find(u=>u.id===e);if(!a?.sourceSession)return;const s=$(a);if(s.length===0)return;const c=new Set;for(const u of y.getState().nodes){const f=u.data.importSource?.sessionId;f&&c.add(f)}const m=s.filter(u=>!c.has(u));if(m.length===0)return;for(const u of m)await W(a.id,u);const t=N.getState().projects.find(u=>u.id===a.id)?.sourceSession?"toast.unsubscribed":"toast.unsubscribedNative";Y("info",U(H(t),{n:m.length}),8e3)}async function mt(o,n){const e=o.filter(d=>!!d&&!!d.sessionId);if(e.length===0)return null;const a=n??await z(U(H("atlas.mergedName"),{title:e[0].title.slice(0,24),n:e.length}));await O(a),y.getState().pushHistory();let s=0,c=0;for(const d of e){const t=d.sessionId;if(L(t)){c++;continue}const u=d.build();if(u.nodes.length===0){c++;continue}const f=u.nodes.filter(r=>r.data.importSource),i=y.getState().nodes,h=i.reduce((r,g)=>Math.max(r,g.position.x+(g.width??g.measured?.width??540)),-1/0),w=i.reduce((r,g)=>Math.min(r,g.position.y),1/0),S=Math.min(...u.nodes.map(r=>r.position.x)),x=Math.min(...u.nodes.map(r=>r.position.y)),l=(Number.isFinite(h)?h+180:0)-S,_=(Number.isFinite(w)?w:0)-x,v=u.nodes.map(r=>({...r,position:{x:r.position.x+l,y:r.position.y+_}})),b=new Set(v.map(r=>r.id)),p=u.edges.filter(r=>b.has(r.source)&&b.has(r.target));y.setState(r=>({nodes:[...r.nodes,...v],edges:[...r.edges,...p]})),await M(a,"chapter",{sessionId:t,runner:d.source,importedCount:f.length,tailNodeId:f.at(-1)?.id??v[v.length-1].id}),s++}y.getState().pushHistory();const m=y.getState().nodes.at(-1);return s>0&&m&&j.getState().setArrivalFocusNodeId(m.id),{mounted:s,skipped:c,projectId:a}}export{ut as canvasUniqueness,V as importOrAppendConversation,dt as importOrAppendSession,mt as mergeSessionsIntoProject,ct as mountConversationToProject,at as shellSessionReader,$ as subscribedSessionIds,pt as unsubscribeOrphanedSessions};
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
async function d(l){if(window.desktopAgents)return!0;const s=l.replace(/\/+$/,"");let o;try{const e=await fetch(s+"/agents/available",{credentials:"same-origin"});if(!e.ok)return!1;o=await e.json()}catch{return!1}const n=async(e,a)=>{const t=await fetch(s+e,{method:"POST",headers:{"Content-Type":"application/json"},credentials:"same-origin",body:JSON.stringify(a??{})});if(!t.ok)throw new Error(`${e}: ${t.status}`);return t.json()},i=[];let r=null;const c=()=>{r||(r=new EventSource(s+"/agents/events"),r.onmessage=e=>{try{const a=JSON.parse(e.data);for(const t of i)t(a)}catch{}})};return window.desktopAgents={capabilities:{nativePicker:!1},available:async()=>o,models:async e=>(await fetch(s+"/agents/models"+(e?`?runtime=${encodeURIComponent(e)}`:""),{credentials:"same-origin"})).json(),run:async e=>(c(),(await n("/agents/run",e)).runId),abort:async e=>(await n("/agents/abort",{runId:e})).ok,answer:async(e,a,t)=>(await n("/agents/answer",{runId:e,requestId:a,response:t})).ok,workspace:async e=>(await n("/agents/workspace",{canvasId:e})).dir,pickCwd:async()=>null,guardWrite:async(e,a)=>(await n("/agents/guard",{cwd:e,config:a})).ok,writeMaterials:async(e,a)=>n("/agents/materials",{cwd:e,files:a}),onEvent:e=>{i.push(e),c()}},!0}export{d as installAgentsHttpBridge};
|