dsh-thoughtdag 0.4.4 → 0.4.5
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 +22 -6
- package/cordis.patch.yml +5 -0
- package/dist-app/assets/{canonical-DbPqsMYz.js → canonical-DDfsxGbh.js} +2 -2
- package/dist-app/assets/{canvas-record-C1A8ExlM.js → canvas-record-vunI4XSG.js} +1 -1
- package/dist-app/assets/{claude-code-session-DQRgWy00.js → claude-code-session-w7XeYCbv.js} +1 -1
- package/dist-app/assets/{codex-session--KVj3_vb.js → codex-session-BteJdhnJ.js} +1 -1
- package/dist-app/assets/{dsh-session-6OCSm4h5.js → dsh-session-DtVkAUjy.js} +1 -1
- package/dist-app/assets/{experiment-loop-BfxITu2e.js → experiment-loop-cKs-OaUA.js} +1 -1
- package/dist-app/assets/{index-6m02Pb4Q.js → index-BgFLKHxw.js} +10 -10
- package/dist-app/assets/{index-BH-U0zVI.js → index-CZgf0TxH.js} +1 -1
- package/dist-app/assets/{index-D-BTv0n0.js → index-DbmziCje.js} +3 -3
- package/dist-app/assets/{index-BL39OXsY.js → index-ZY9zV6mj.js} +1 -1
- package/dist-app/assets/{live-mirror-BElcCk_a.js → live-mirror-Cil__utB.js} +2 -2
- package/dist-app/assets/{sensitive-scan-L0rFzufE.js → sensitive-scan-NBqP2Srd.js} +1 -1
- package/dist-app/assets/{session-handoff-CGrowwZp.js → session-handoff-C_88Qy1y.js} +2 -2
- package/dist-app/assets/{shared-CURSZnXt.js → shared-0Cyt1YSM.js} +1 -1
- package/dist-app/assets/{turndown-plugin-gfm.cjs-p3SpZgsj.js → turndown-plugin-gfm.cjs-BkQZDlXD.js} +1 -1
- package/dist-app/assets/{update-check-D5daO3Cz.js → update-check-Ca6SiYKC.js} +1 -1
- package/dist-app/index.html +1 -1
- package/lib/index.js +95 -2
- package/lib/why.mjs +2588 -0
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -62,17 +62,33 @@ full-screen iframe.
|
|
|
62
62
|
|
|
63
63
|
### Canvas-side import
|
|
64
64
|
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
65
|
+
Inside the iframe the canvas runs with this bridge as its session source
|
|
66
|
+
(the SPA is built with `VITE_DSH_BRIDGE=/thoughtdag/api`): Session Atlas
|
|
67
|
+
lists the harness's sessions beside Claude Code's and Codex's (served by
|
|
68
|
+
this host from their directories), opens one as a graph, and follows it
|
|
69
|
+
live by polling the session's seq. The client half tells the canvas which
|
|
70
|
+
session the chat shows (`td:current-session`) and switches the chat when the
|
|
71
|
+
canvas names one (`td:select-session`).
|
|
72
|
+
|
|
73
|
+
## The why layer inside the harness
|
|
74
|
+
|
|
75
|
+
The plugin bundles the `thoughtdag` CLI's library (`lib/why.mjs`, built at pack time) and answers the same four questions over the same `~/.thoughtdag` index — no CLI or MCP install needed:
|
|
76
|
+
|
|
77
|
+
| Surface | What |
|
|
78
|
+
|---|---|
|
|
79
|
+
| Native tools | `why_check(path)`, `why_file(path, include_read?, limit?)`, `why_find(phrase, in?, limit?)`, `why_recall(session, turn)` — the agent calls them like any harness tool; relative paths resolve against the session's working directory |
|
|
80
|
+
| `/why <path \| url \| arxiv:id>` | a person asks from the chat; the answer is the CLI's `why` output, no model message |
|
|
81
|
+
| System-prompt section | four lines telling the model to `why_check` before editing a file with history and how to read the other three |
|
|
82
|
+
|
|
83
|
+
Both are on by default; `whyTools: false` / `whyPrompt: false` in the plugin config turn them off.
|
|
69
84
|
|
|
70
85
|
## Not yet (roadmap)
|
|
71
86
|
|
|
87
|
+
- Canvas why panel (a node's file → its history through `/thoughtdag/api`)
|
|
72
88
|
- Canvas UI for the write bridge: name a fork point on a node, hand a compiled context to `inject`, continue with `followup`; the client already switches the chat to a session the canvas names (`td:select-session`)
|
|
73
89
|
- `replace`: shadow a surface range from the canvas (DSH's compaction primitive); needs a live check of how the chat renders a replaced range
|
|
74
|
-
- Theme
|
|
75
|
-
-
|
|
90
|
+
- Theme and language sync with the harness UI
|
|
91
|
+
- Open the chat's current session on the canvas automatically when the view switches
|
|
76
92
|
|
|
77
93
|
## Development
|
|
78
94
|
|
package/cordis.patch.yml
CHANGED
|
@@ -9,3 +9,8 @@
|
|
|
9
9
|
# Extra authorities the /thoughtdag/api Host check accepts; localhost
|
|
10
10
|
# and 127.0.0.1 are always allowed.
|
|
11
11
|
trustedHosts: []
|
|
12
|
+
# The why layer as native harness tools (why_check, why_file, why_find,
|
|
13
|
+
# why_recall) and a /why command. Set false to leave them out.
|
|
14
|
+
whyTools: true
|
|
15
|
+
# A short system-prompt section telling the model when to ask why.
|
|
16
|
+
whyPrompt: true
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
const __vite__mapDeps=(i,m=__vite__mapDeps,d=(m.f||(m.f=["assets/index-
|
|
2
|
-
import{c as N,b as y,_ as E,p as q,r as M,h as O,a as D,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-6m02Pb4Q.js";const et=190;async function dt(o){const{anyRunnerSessionConversation:n}=await E(async()=>{const{anyRunnerSessionConversation:a}=await import("./index-D-BTv0n0.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 H(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-BfxITu2e.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=D("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=H(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=H(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-6m02Pb4Q.js").then(i=>i.D);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,K=!!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&&(K||J)){const C=K?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=H(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-6m02Pb4Q.js").then(i=>i.D);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-6m02Pb4Q.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(D(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(D("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
|
+
const __vite__mapDeps=(i,m=__vite__mapDeps,d=(m.f||(m.f=["assets/index-DbmziCje.js","assets/index-BgFLKHxw.js","assets/index-DEHbIrRr.css","assets/experiment-loop-cKs-OaUA.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 D,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-BgFLKHxw.js";const et=190;async function dt(o){const{anyRunnerSessionConversation:n}=await E(async()=>{const{anyRunnerSessionConversation:a}=await import("./index-DbmziCje.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 H(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-cKs-OaUA.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=D("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=H(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=H(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-BgFLKHxw.js").then(i=>i.D);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,K=!!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&&(K||J)){const C=K?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=H(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-BgFLKHxw.js").then(i=>i.D);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-BgFLKHxw.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(D(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(D("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 +1 @@
|
|
|
1
|
-
import{b as c,c as p,E as m,s as v,d as w,e as h,g}from"./index-
|
|
1
|
+
import{b as c,c as p,E as m,s as v,d as w,e as h,g}from"./index-BgFLKHxw.js";const S=6e4,T=4e3;function y(e){const s=(e.data.attachments??[]).map(t=>({id:t.id,name:t.name,type:t.type,size:t.size,content:"",...t.addedAt?{addedAt:t.addedAt}:{},...t.extractedText?{extractedText:t.extractedText.slice(0,T)}:{},...t.paths?{paths:t.paths}:{},...t.op?{op:t.op}:{}}));return{...e,data:{...e.data,attachments:s}}}function j(){const{nodes:e,edges:s,events:t}=c.getState(),{projects:u,activeId:a}=p.getState();if(!a||e.length===0)return null;const r=u.find(l=>l.id===a),f=JSON.stringify({version:m,name:w(),projectId:a,exportedAt:new Date().toISOString(),record:"thoughtdag-canvas-record",instantiatedFrom:r?.instantiatedFrom,sourceSession:r?.sourceSession,nodes:v(e).map(y),edges:s,events:t});return{projectId:a,json:f}}let n=null,o=!1;async function d(){n&&(clearTimeout(n),n=null),o=!1;const e=window.desktopCanvas;if(!e)return!1;const s=j();return s?!!(await e.write(s.projectId,s.json).catch(()=>({ok:!1}))).ok:!1}function x(){o=!0,n&&clearTimeout(n),n=setTimeout(()=>{n=null,o&&d().catch(e=>console.warn("[thoughtdag] canvas record write failed:",e))},S)}let i=!1;function E(){i||h||typeof window>"u"||!window.desktopCanvas||(i=!0,c.subscribe((e,s)=>{(e.nodes!==s.nodes||e.edges!==s.edges||e.events!==s.events)&&x()}),g.push(async()=>{o&&await d()}),window.addEventListener("pagehide",()=>{o&&d()}))}async function R(e){await window.desktopCanvas?.remove(e).catch(()=>{})}export{j as canvasRecordPayload,d as flushCanvasRecord,R as removeCanvasRecord,E as startCanvasRecord};
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import{v as I,B as g,o as T}from"./index-
|
|
1
|
+
import{v as I,B as g,o as T}from"./index-BgFLKHxw.js";import{t as C,a as _,r as A,b as x,c as w,d as L,e as v,s as S,f as k,m as O,T as b,A as B,g as M}from"./shared-0Cyt1YSM.js";const q=16e3;function f(o){return typeof o=="string"?o:Array.isArray(o)?o.filter(t=>t.type==="text"&&t.text).map(t=>t.text).join(`
|
|
2
2
|
`):""}function N(o){return typeof o=="string"?o:Array.isArray(o)?o.map(t=>t.type==="text"&&t.text?t.text:t.type==="image"?"[image result omitted]":"").filter(Boolean).join(`
|
|
3
3
|
`):""}const p=v;class ${turns=[];pendingTools=new Map;current=null;pendingCompaction;sessionId=null;customTitle=null;summary=null;slug=null;firstQuestion=null;cwd=null;mode=null;feedLine(t){const s=t.trim();if(!s)return;let n;try{n=JSON.parse(s)}catch{return}this.feed(n)}flush(){const t=this.current;t&&(t.question||t.response||t.tools.length)&&this.turns.push(t),this.current=null}feed(t){if(t.type==="custom-title"&&t.customTitle&&(this.customTitle=t.customTitle),t.type==="summary"&&t.summary&&!this.summary&&(this.summary=t.summary),t.slug&&!this.slug&&(this.slug=t.slug),t.cwd&&!this.cwd&&(this.cwd=t.cwd),this.mode===null&&(t.type==="user"||t.type==="assistant")&&t.uuid&&(this.mode=t.isSidechain&&t.agentId?"sidechain":"main",this.mode==="sidechain"&&(this.sessionId=t.agentId)),!!t.isSidechain==(this.mode==="sidechain")){if(t.type==="system"&&t.subtype==="compact_boundary"){this.flush();const s=t.compactMetadata;this.pendingCompaction=`[Compaction] The source runner compacted its history here${s?.preTokens?` (${s.preTokens} → ${s.postTokens??"?"} tokens)`:""}. Everything above this point reached later turns only as a summary.`;return}if((t.type==="user"||t.type==="assistant")&&t.uuid&&t.sessionId&&!this.sessionId&&(this.sessionId=t.sessionId),t.type==="user"){const s=t.message?.content;if(Array.isArray(s)){for(const e of s)if(e.type==="tool_result"&&e.tool_use_id){const i=this.pendingTools.get(e.tool_use_id);if(i&&this.current){const a=p(N(e.content),b);this.current.tools.push({name:i.name,call:i.call,result:a.text,truncated:a.truncated,...i.paths.length?{paths:i.paths}:{},op:i.op,nativeCallId:e.tool_use_id,...i.url?{url:i.url}:{},...i.locator?{locator:i.locator}:{}}),this.pendingTools.delete(e.tool_use_id)}}}const n=f(s);if(!n.trim())return;if(/^\s*<task-notification>/.test(n)){if(this.current){const e=p(n,q);this.current.tools.push({name:"Agent",call:"(task notification)",result:e.text,truncated:e.truncated,op:"agent"})}return}this.flush(),this.firstQuestion||(this.firstQuestion=n.trim()),this.current={question:n,response:"",itemIds:t.uuid?[t.uuid]:[],tools:[],parentItemId:t.parentUuid??void 0,...t.timestamp?{at:t.timestamp}:{}},this.pendingCompaction&&(this.current.compactionBefore=this.pendingCompaction,this.pendingCompaction=void 0);return}if(t.type==="assistant"&&this.current){t.uuid&&this.current.itemIds.push(t.uuid);const s=t.message?.content,n=f(s);if(n.trim()&&(this.current.response=this.current.response?`${this.current.response}
|
|
4
4
|
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import{v as p,o as d,B as m}from"./index-
|
|
1
|
+
import{v as p,o as d,B as m}from"./index-BgFLKHxw.js";import{t as y,a as _,d as g,e as I,m as x,f as T,s as C,A as w,g as v,T as A}from"./shared-0Cyt1YSM.js";function B(n){const t=[];for(const e of n.matchAll(/^\*\*\* (?:Add|Update|Delete) File: (.+)$/gm))t.push(e[1].trim());return t}const h=I,L=n=>(n??[]).filter(t=>t.text&&(t.type==="input_text"||t.type==="output_text"||t.type==="text")).map(t=>t.text).join(`
|
|
2
2
|
`),S=/^\s*<\/?[a-zA-Z_][\w-]*[^>]*>/,q=n=>S.test(n)||n.trimStart().startsWith("# AGENTS.md instructions for "),O=n=>(n??[]).filter(t=>t.text&&(t.type==="input_text"||t.type==="text")&&!q(t.text)).map(t=>t.text).join(`
|
|
3
3
|
`),N=n=>typeof n=="string"?n:Array.isArray(n)?n.map(t=>t?.text??"").filter(Boolean).join(`
|
|
4
4
|
`):n==null?"":JSON.stringify(n);class ${turns=[];pendingCalls=new Map;current=null;pendingCompaction;sessionId=null;cwd="";day="";sawItems=!1;firstQuestion=null;parentThreadId=null;feedLine(t){const e=t.trim();if(!e)return;let s;try{s=JSON.parse(e)}catch{return}this.feed(s)}flush(){const t=this.current;t&&(t.question||t.response||t.tools.length)&&this.turns.push(t),this.current=null}ensure(){return this.current||(this.current={question:"",response:"",itemIds:[],tools:[]},this.pendingCompaction&&(this.current.compactionBefore=this.pendingCompaction,this.pendingCompaction=void 0)),this.current}feed(t){const e=t.payload??{};if(t.type==="session_meta"&&e.id&&!this.sessionId){this.sessionId=e.id,this.cwd=e.cwd??"",this.day=e.timestamp?.slice(0,10)??"",this.parentThreadId=e.parent_thread_id??null;return}if((t.type==="response_item"||t.type==="event_msg")&&(this.sawItems=!0),t.type==="compacted"){this.flush(),this.pendingCompaction="[Compaction] The source runner compacted its history here. Everything above this point reached later turns only as a summary.";return}if(t.type==="turn_context"||t.type==="event_msg"&&e.type==="task_started"){this.flush();const s=this.ensure();e.turn_id&&s.itemIds.push(e.turn_id);return}if(t.type==="response_item"){if(e.type==="message"){if(e.role==="user"){const s=O(e.content);if(s.trim()){this.firstQuestion||(this.firstQuestion=s.trim());const o=this.ensure();!o.at&&t.timestamp&&(o.at=t.timestamp),o.question=o.question?`${o.question}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import{v as T,B as w,o as C}from"./index-
|
|
1
|
+
import{v as T,B as w,o as C}from"./index-BgFLKHxw.js";import{t as x,a as l,b as f,c as p,e as d,r as g,d as L,T as m,A as h,g as I,f as S,s as A}from"./shared-0Cyt1YSM.js";function c(o,s=0){return typeof o=="string"?o:!Array.isArray(o)||s>2?"":o.map(t=>{if(!t||typeof t!="object")return"";const e=t;return e.type==="text"&&typeof e.text=="string"?e.text:e.type==="image"?"[image omitted]":e.type==="reasoning"?"":c(e.text??e.content,s+1)}).filter(Boolean).join(`
|
|
2
2
|
`)}function O(o,s,t){const e=l(o);if(e==="run"||/^run_code$/i.test(o)){const r=t??{};return d(typeof r.code=="string"?r.code:s,h)}const n=t&&typeof t=="object"?g(o,t):s;return d(n,e==="write"||e==="edit"?h:I)}const b=o=>{try{return JSON.parse(o??"")}catch{return}};class q{turns=[];pendingTools=new Map;current=null;sessionId=null;cwd=null;title=null;firstQuestion=null;feedLine(s){const t=s.trim();if(!t)return;let e;try{e=JSON.parse(t)}catch{return}this.feed(e)}flush(){const s=this.current;s&&(s.question||s.response||s.tools.length)&&this.turns.push(s),this.current=null}ensure(){return this.current||(this.current={question:"",response:"",itemIds:[],tools:[]}),this.current}feed(s){if(s.type==="session"&&s.id){this.sessionId||(this.sessionId=s.id),s.cwd&&!this.cwd&&(this.cwd=s.cwd);return}if(s.type==="session/title"&&s.data?.title&&!this.title){this.title=s.data.title;return}if(s.type==="user/message"){const t=s,e=t.data?.source?.kind;if(e&&e!=="user")return;const n=c(t.data?.content).trim();if(!n)return;this.firstQuestion||(this.firstQuestion=n.split(`
|
|
3
3
|
`)[0].slice(0,80)),this.flush();const r=this.ensure();r.question=n,r.itemIds=[t.data?.id??`u${t.seq}`],t.time&&(r.at=new Date(t.time).toISOString());return}if(s.type==="assistant/message"&&this.current){const t=s,e=t.data?.message?.content,n=c(e).trim(),r=t.data?.message?.id;r&&this.current.itemIds.push(r),n&&(this.current.response=this.current.response?`${this.current.response}
|
|
4
4
|
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import{a as c,b as l,c as p,x as h,t as u,f as m}from"./index-
|
|
1
|
+
import{a as c,b as l,c as p,x as h,t as u,f as m}from"./index-BgFLKHxw.js";const b=/\[ThoughtDAG anchor: project=([\w-]+) node=([\w-]+) bundle=([\w-]+)(?: mode=(branch|continue))?\]/;function f(o){const n=o.match(b);return n?{project:n[1],node:n[2],bundle:n[3],mode:n[4]==="continue"?"continue":"branch"}:null}function g(o,n){const e=[];e.push(c("exp.mdIntro")),e.push("");for(const s of o.context.messages){const t=s.content[0].text;switch(s.source.layer){case"system":e.push(`**${c("exp.mdRole")}** ${t}`);break;case"chain":e.push(s.role==="assistant"?`**A:** ${t}`:`**Q:** ${t}`);break;default:e.push(t)}e.push("")}return e.push("---"),e.push(c("exp.mdOutro")),e.push(""),e.push(`[ThoughtDAG anchor: project=${n.project} node=${n.node} bundle=${n.bundle}${n.mode==="continue"?" mode=continue":""}]`),e.join(`
|
|
2
2
|
`)}async function w(o,n="branch"){const e=l.getState(),s=p.getState().activeId??"default",t=await h(o,e.nodes,e.edges,{now:new Date().toISOString(),projectId:s,staleIds:e.staleIds}),d={project:s,node:o,bundle:t.id,mode:n},i=g(t,d);try{await navigator.clipboard.writeText(i)}catch{return u("error",c("exp.clipboardFailed")),!1}{const a=[...new Set(t.context.messages.map(r=>r.source?.node_id).filter(r=>!!r))];e.logEvent("commit",o,{kind:"bundle",sha:t.integrity.content_hash,bundle:t.id,n:t.context.messages.length,...a.length?{m:a.slice(0,200).join(",")}:{},...a.length>200?{more:!0}:{}})}return u("success",m(c("exp.copied"),{n:t.context.messages.length,tok:t.budget.estimated_tokens}),12e3),!0}export{f as parseAnchor,g as renderHandoffMarkdown,w as takeToExperiment};
|