dsh-thoughtdag 0.4.16 → 0.4.18
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-app/assets/{canonical-ChxvAi6N.js → canonical-BOx5kAea.js} +2 -2
- package/dist-app/assets/{canvas-record-Be2aKIf8.js → canvas-record-Uj_EllzJ.js} +1 -1
- package/dist-app/assets/{claude-code-session-B51keZPd.js → claude-code-session-D8ULjNtv.js} +1 -1
- package/dist-app/assets/{codex-session-BR_x_Fzf.js → codex-session-D8ZZHLnx.js} +1 -1
- package/dist-app/assets/{dsh-session-D0yZa0_o.js → dsh-session-IBrxF_lC.js} +1 -1
- package/dist-app/assets/{experiment-loop-pAs6MwPV.js → experiment-loop-CtCFBVPU.js} +1 -1
- package/dist-app/assets/{index-_B6z8_Ff.js → index-BC-rF3gw.js} +3 -3
- package/dist-app/assets/{index-DvBTIsHr.js → index-BFREplWz.js} +1 -1
- package/dist-app/assets/{index-C3fERes9.css → index-BLoL8TBc.css} +1 -1
- package/dist-app/assets/{index-962V9CYS.js → index-DTQiL090.js} +1 -1
- package/dist-app/assets/{index-JMt9ljo3.js → index-tIP9lf-g.js} +54 -54
- package/dist-app/assets/{live-mirror-C9sTXAvv.js → live-mirror-QfnNBagO.js} +2 -2
- package/dist-app/assets/{pi-session-B7frsRRp.js → pi-session-FEplLVy8.js} +1 -1
- package/dist-app/assets/{sensitive-scan-Cwg4RAEk.js → sensitive-scan-C3rz7OZK.js} +1 -1
- package/dist-app/assets/{session-handoff-BXosSY-e.js → session-handoff-6eOs2FiL.js} +2 -2
- package/dist-app/assets/{shared-L3KzXorg.js → shared-C4tOpQEv.js} +1 -1
- package/dist-app/assets/{turndown-plugin-gfm.cjs-pG4f1F8S.js → turndown-plugin-gfm.cjs-GaD2jPKz.js} +1 -1
- package/dist-app/assets/{update-check-lHz7ROW6.js → update-check-DWzpvP3c.js} +1 -1
- package/dist-app/index.html +2 -2
- package/lib/index.js +48 -12
- package/package.json +3 -2
|
@@ -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-tIP9lf-g.js","assets/index-BLoL8TBc.css","assets/experiment-loop-CtCFBVPU.js","assets/index-BC-rF3gw.js","assets/canonical-BOx5kAea.js"])))=>i.map(i=>d[i]);
|
|
2
|
+
import{_ as l,i as b,t as p,a as h,f as R}from"./index-tIP9lf-g.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-tIP9lf-g.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-tIP9lf-g.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-CtCFBVPU.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-BC-rF3gw.js");return{streamRunnerConversation:w}},__vite__mapDeps([3,0,1])),{importOrAppendConversation:u,shellSessionReader:_}=await l(async()=>{const{importOrAppendConversation:w,shellSessionReader:E}=await import("./canonical-BOx5kAea.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-tIP9lf-g.js").then(m=>m.G);return{useStore:o}},__vite__mapDeps([0,1])),{useUiStore:i}=await l(async()=>{const{useUiStore:o}=await import("./index-tIP9lf-g.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-tIP9lf-g.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-tIP9lf-g.js").then(n=>n.G);return{useStore:r}},__vite__mapDeps([0,1])),{useUiStore:f}=await l(async()=>{const{useUiStore:r}=await import("./index-tIP9lf-g.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-BC-rF3gw.js");return{streamRunnerConversation:n}},__vite__mapDeps([3,0,1])),{importOrAppendConversation:t,shellSessionReader:e}=await l(async()=>{const{importOrAppendConversation:n,shellSessionReader:u}=await import("./canonical-BOx5kAea.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-tIP9lf-g.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-tIP9lf-g.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-tIP9lf-g.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-C4tOpQEv.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-tIP9lf-g.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-BOx5kAea.js","assets/index-tIP9lf-g.js","assets/index-BLoL8TBc.css"])))=>i.map(i=>d[i]);
|
|
2
|
+
import{t as n,a as e,_ as p,f as a,u as h}from"./index-tIP9lf-g.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-BOx5kAea.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-tIP9lf-g.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-pG4f1F8S.js → turndown-plugin-gfm.cjs-GaD2jPKz.js}
RENAMED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import{A as W}from"./index-
|
|
1
|
+
import{A as W}from"./index-tIP9lf-g.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-tIP9lf-g.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-tIP9lf-g.js"></script>
|
|
26
|
+
<link rel="stylesheet" crossorigin href="/thoughtdag/assets/index-BLoL8TBc.css">
|
|
27
27
|
</head>
|
|
28
28
|
<body>
|
|
29
29
|
<div id="root"></div>
|
package/lib/index.js
CHANGED
|
@@ -288,7 +288,12 @@ function decompressZstdToText(raw) {
|
|
|
288
288
|
} catch { return '' }
|
|
289
289
|
}
|
|
290
290
|
|
|
291
|
-
/** Walk $DSH_HOME/sessions for session
|
|
291
|
+
/** Walk $DSH_HOME/sessions for the session log (2 levels deep). DSH writes the
|
|
292
|
+
* session format version into the file name: early builds used
|
|
293
|
+
* `session.jsonl.zstd`, while session format V3 (0.1.5-rc.2 and later) uses
|
|
294
|
+
* `session.v3.jsonl.zstd`. Probe the known names, newest first, so a listing
|
|
295
|
+
* keeps working across both. */
|
|
296
|
+
const SESSION_LOG_NAMES = ['session.v3.jsonl.zstd', 'session.jsonl.zstd']
|
|
292
297
|
async function findSessionFiles(dshHome) {
|
|
293
298
|
const root = join(dshHome, 'sessions')
|
|
294
299
|
const out = []
|
|
@@ -300,11 +305,14 @@ async function findSessionFiles(dshHome) {
|
|
|
300
305
|
try { sessions = await readdir(join(root, ws.name), { withFileTypes: true }) } catch { continue }
|
|
301
306
|
for (const s of sessions) {
|
|
302
307
|
if (!s.isDirectory()) continue
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
308
|
+
let log
|
|
309
|
+
let st
|
|
310
|
+
for (const name of SESSION_LOG_NAMES) {
|
|
311
|
+
const candidate = join(root, ws.name, s.name, name)
|
|
312
|
+
try { st = await stat(candidate); log = candidate; break } catch { /* try the next format */ }
|
|
313
|
+
}
|
|
314
|
+
if (log === undefined || st === undefined) continue
|
|
315
|
+
out.push({ dir: ws.name, sessionDir: s.name, log, size: st.size, mtime: st.mtimeMs })
|
|
308
316
|
}
|
|
309
317
|
}
|
|
310
318
|
return out
|
|
@@ -639,6 +647,9 @@ function installApprovalAnswerer(ctx) {
|
|
|
639
647
|
ctx.on('approval/request', async function (req, next) {
|
|
640
648
|
const entry = canvasTurns.get(req?.agent?.id)
|
|
641
649
|
if (!entry) return next()
|
|
650
|
+
// an approval raised by another turn of the same session (the person's
|
|
651
|
+
// own tool call, running before or after ours) stays with the harness UI
|
|
652
|
+
if (entry.turn === null || entry.current() !== entry.turn) return next()
|
|
642
653
|
const id = 'td-' + randomUUID()
|
|
643
654
|
const call = req.callId !== undefined ? entry.calls.get(req.callId) : undefined
|
|
644
655
|
const name = call?.name ?? req.toolName
|
|
@@ -698,7 +709,9 @@ async function runAgentTurn(ctx, body, emit, isClosed, { answerApprovals = true
|
|
|
698
709
|
emit({ harnessSession: sessionId, continued: sessionId === continueId, ...(forkedFrom ? { forkedFrom } : {}) })
|
|
699
710
|
// a streaming caller can show and answer approvals; a one-shot caller
|
|
700
711
|
// (/claude) cannot, so its requests fall through to the harness's own panel
|
|
701
|
-
|
|
712
|
+
// turn/current are filled once our message enters the session: the approval
|
|
713
|
+
// answerer uses them to take only the approvals our turn raises
|
|
714
|
+
const turnEntry = { emit, isClosed, calls: new Map(), turn: null, current: () => null }
|
|
702
715
|
if (answerApprovals) canvasTurns.set(sessionId, turnEntry)
|
|
703
716
|
const hasImages = Array.isArray(body?.images) && body.images.length > 0
|
|
704
717
|
if (hasImages) {
|
|
@@ -714,17 +727,40 @@ async function runAgentTurn(ctx, body, emit, isClosed, { answerApprovals = true
|
|
|
714
727
|
let fullText = ''
|
|
715
728
|
let done
|
|
716
729
|
const finished = new Promise(resolve => { done = resolve })
|
|
730
|
+
// The session is shared with the person chatting in the harness: their
|
|
731
|
+
// turns may run before, after or around ours (ours is queued behind
|
|
732
|
+
// whatever is running). Everything below is scoped to OUR turn. dsh stamps
|
|
733
|
+
// the prompt's requestId on the user message it creates (source.rpcId), so
|
|
734
|
+
// that message is recognised exactly; it names our turn, and only that
|
|
735
|
+
// turn's text, tool calls, approvals and end belong to this node (#42).
|
|
736
|
+
const requestId = 'td-' + randomUUID()
|
|
717
737
|
let currentTurn = null
|
|
738
|
+
let ourTurn = null
|
|
739
|
+
let ourMessagePending = false
|
|
740
|
+
const claimTurn = (turn) => { ourTurn = turn; turnEntry.turn = turn }
|
|
741
|
+
const isOurs = (event) => ourTurn !== null && (typeof event.data?.turn === 'number' ? event.data.turn === ourTurn : currentTurn === ourTurn)
|
|
742
|
+
turnEntry.current = () => currentTurn
|
|
718
743
|
const off = ctx.on('session/event', (session, event) => {
|
|
719
744
|
if (session?.id !== sessionId || !event) return
|
|
720
|
-
if (event.type === 'turn/start') {
|
|
745
|
+
if (event.type === 'turn/start') {
|
|
746
|
+
currentTurn = event.data?.turn ?? null
|
|
747
|
+
if (ourMessagePending && currentTurn !== null) { ourMessagePending = false; claimTurn(currentTurn) }
|
|
748
|
+
return
|
|
749
|
+
}
|
|
721
750
|
// the person's question entering the surface: THIS is the turn the
|
|
722
751
|
// canvas node stands for — with its id the canvas marks the node as the
|
|
723
|
-
// mirror of that turn, and the live mirror does not append it a second
|
|
724
|
-
|
|
725
|
-
|
|
752
|
+
// mirror of that turn, and the live mirror does not append it a second
|
|
753
|
+
// time. Only our own message counts; a message the person typed in the
|
|
754
|
+
// chat meanwhile belongs to their turn, not to this node.
|
|
755
|
+
if (event.type === 'user/message') {
|
|
756
|
+
const source = event.data?.source
|
|
757
|
+
if (ourTurn === null && !ourMessagePending && (source?.kind ?? 'user') === 'user' && source?.rpcId === requestId) {
|
|
758
|
+
if (currentTurn === null) ourMessagePending = true; else claimTurn(currentTurn)
|
|
759
|
+
emit({ harnessTurn: { session: sessionId, turn: currentTurn, userMessageId: event.data?.id ?? null, seq: event.seq ?? null } })
|
|
760
|
+
}
|
|
726
761
|
return
|
|
727
762
|
}
|
|
763
|
+
if (!isOurs(event)) return
|
|
728
764
|
if (event.type === 'assistant/chunk') {
|
|
729
765
|
const c = event.data?.chunk
|
|
730
766
|
if (c?.type === 'text-delta' && c.text) { sawChunk = true; fullText += c.text; emit({ text: c.text }) }
|
|
@@ -748,7 +784,7 @@ async function runAgentTurn(ctx, body, emit, isClosed, { answerApprovals = true
|
|
|
748
784
|
for (const img of Array.isArray(body?.images) ? body.images : []) {
|
|
749
785
|
if (img && typeof img.data === 'string' && IMAGE_MEDIA.has(img.mimeType)) promptContent.push({ type: 'image', mediaType: img.mimeType, data: img.data })
|
|
750
786
|
}
|
|
751
|
-
await ctx.sessionController.prompt({ requestId
|
|
787
|
+
await ctx.sessionController.prompt({ requestId, sessionId, mode: 'queue', content: promptContent }, AbortSignal.timeout(30000))
|
|
752
788
|
const timeout = new Promise(resolve => setTimeout(resolve, 20 * 60 * 1000))
|
|
753
789
|
const closed = new Promise(resolve => { const t = setInterval(() => { if (isClosed()) { clearInterval(t); resolve() } }, 500); finished.then(() => clearInterval(t)) })
|
|
754
790
|
await Promise.race([finished, agent.whenIdle().then(() => finished), timeout, closed])
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "dsh-thoughtdag",
|
|
3
|
-
"version": "0.4.
|
|
3
|
+
"version": "0.4.18",
|
|
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": {
|
|
@@ -50,7 +50,8 @@
|
|
|
50
50
|
"compatibility": {
|
|
51
51
|
"dshReleases": {
|
|
52
52
|
"0.1.2-rc.1": "compatible",
|
|
53
|
-
"0.1.5-rc.1": "compatible"
|
|
53
|
+
"0.1.5-rc.1": "compatible",
|
|
54
|
+
"0.1.5-rc.2": "compatible"
|
|
54
55
|
}
|
|
55
56
|
}
|
|
56
57
|
},
|