yaml-flow 7.0.0 → 7.1.0
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/browser/asset-integrity.json +1 -1
- package/browser/board-livecards-client.js +1 -1
- package/browser/board-livecards-client.js.map +1 -1
- package/browser/board-livecards-localstorage.js +5 -5
- package/browser/board-livecards-localstorage.js.map +1 -1
- package/browser/live-cards.js +3 -1
- package/dist/{board-live-cards-public-CW5074xr.d.cts → board-live-cards-public-5n1-syA3.d.cts} +1 -2
- package/dist/{board-live-cards-public-hnZo0mAf.d.ts → board-live-cards-public-CK_J8uv0.d.ts} +1 -2
- package/dist/cli/browser-api/board-live-cards-browser-adapter.cjs +2 -2
- package/dist/cli/browser-api/board-live-cards-browser-adapter.cjs.map +1 -1
- package/dist/cli/browser-api/board-live-cards-browser-adapter.d.cts +2 -2
- package/dist/cli/browser-api/board-live-cards-browser-adapter.d.ts +2 -2
- package/dist/cli/browser-api/board-live-cards-browser-adapter.js +2 -2
- package/dist/cli/browser-api/board-live-cards-browser-adapter.js.map +1 -1
- package/dist/cli/browser-api/card-store-browser-api.cjs.map +1 -1
- package/dist/cli/browser-api/card-store-browser-api.js.map +1 -1
- package/dist/cli/node/artifacts-store-cli.cjs +5 -5
- package/dist/cli/node/artifacts-store-cli.cjs.map +1 -1
- package/dist/cli/node/artifacts-store-cli.js +5 -5
- package/dist/cli/node/artifacts-store-cli.js.map +1 -1
- package/dist/cli/node/board-live-cards-cli.cjs +7 -7
- package/dist/cli/node/board-live-cards-cli.cjs.map +1 -1
- package/dist/cli/node/board-live-cards-cli.js +7 -7
- package/dist/cli/node/board-live-cards-cli.js.map +1 -1
- package/dist/cli/node/card-store-cli.cjs +4 -4
- package/dist/cli/node/card-store-cli.cjs.map +1 -1
- package/dist/cli/node/card-store-cli.js +4 -4
- package/dist/cli/node/card-store-cli.js.map +1 -1
- package/dist/cli/node/execution-adapter.cjs +1 -1
- package/dist/cli/node/execution-adapter.cjs.map +1 -1
- package/dist/cli/node/execution-adapter.js +1 -1
- package/dist/cli/node/execution-adapter.js.map +1 -1
- package/dist/cli/node/fs-board-adapter.cjs +7 -7
- package/dist/cli/node/fs-board-adapter.cjs.map +1 -1
- package/dist/cli/node/fs-board-adapter.d.cts +2 -2
- package/dist/cli/node/fs-board-adapter.d.ts +2 -2
- package/dist/cli/node/fs-board-adapter.js +7 -7
- package/dist/cli/node/fs-board-adapter.js.map +1 -1
- package/dist/cli/node/source-cli-task-executor.cjs +2 -2
- package/dist/cli/node/source-cli-task-executor.cjs.map +1 -1
- package/dist/cli/node/source-cli-task-executor.js +2 -2
- package/dist/cli/node/source-cli-task-executor.js.map +1 -1
- package/dist/execution-refs.cjs +2 -2
- package/dist/execution-refs.cjs.map +1 -1
- package/dist/execution-refs.d.cts +9 -4
- package/dist/execution-refs.d.ts +9 -4
- package/dist/execution-refs.js +2 -2
- package/dist/execution-refs.js.map +1 -1
- package/dist/server-runtime/index.cjs +4 -4
- package/dist/server-runtime/index.cjs.map +1 -1
- package/dist/server-runtime/index.d.cts +3 -3
- package/dist/server-runtime/index.d.ts +3 -3
- package/dist/server-runtime/index.js +4 -4
- package/dist/server-runtime/index.js.map +1 -1
- package/dist/step-machine-public/index.cjs +2 -1
- package/dist/step-machine-public/index.cjs.map +1 -1
- package/dist/step-machine-public/index.d.cts +7 -0
- package/dist/step-machine-public/index.d.ts +7 -0
- package/dist/step-machine-public/index.js +2 -1
- package/dist/step-machine-public/index.js.map +1 -1
- package/dist/storage-refs.cjs +2 -2
- package/dist/storage-refs.cjs.map +1 -1
- package/dist/storage-refs.d.cts +1 -2
- package/dist/storage-refs.d.ts +1 -2
- package/dist/storage-refs.js +2 -2
- package/dist/storage-refs.js.map +1 -1
- package/dist/{types-BxEFcVK9.d.cts → types-CU3DjTKL.d.cts} +1 -1
- package/dist/{types-B1ZRa4aI.d.ts → types-HGDTWIun.d.ts} +1 -1
- package/examples/browser/boards/portfolio-tracker/portfolio-tracker-http-test.js +13 -0
- package/examples/browser/boards/portfolio-tracker/portfolio-tracker-http-test.py +398 -0
- package/examples/cli/step-machine-cli/portfolio-tracker/portfolio-tracker.flow.yaml +4 -4
- package/examples/cli/step-machine-demo/jsonata-init-board.flow.yaml +1 -1
- package/examples/cli/step-machine-demo/one-step-cli-only.flow.yaml +1 -1
- package/examples/cli/step-machine-demo/two-step-mixed.flow.yaml +1 -1
- package/examples/example-board/agent-instructions.md +1 -1
- package/examples/example-board/cards/{card-market-prices.json → cardT-market-prices.json} +2 -2
- package/examples/example-board/cards/{card-portfolio.json → cardT-portfolio.json} +3 -13
- package/examples/example-board/demo-server-config.json +1 -1
- package/examples/example-board/demo-server.js +48 -25
- package/examples/example-board/demo-shell-localstorage.html +3 -3
- package/examples/example-board/demo-shell-with-server.html +2 -2
- package/examples/example-board/demo-task-executor.js +4 -8
- package/package.json +2 -2
- package/step-machine-cli.js +1 -1
- package/examples/example-board/cards/_index.json +0 -47
- /package/examples/example-board/cards/{card-portfolio-value.json → cardT-portfolio-value.json} +0 -0
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
var BoardLiveCardsClient=(function(exports){'use strict';function X(e){return e==="running"||e==="in-progress"?"loading":e==="failed"?"error":"fresh"}function he(e,n){let o=n&&typeof n=="object"&&!Array.isArray(n)?n:{};return {schema_version:o.schema_version||"v1",card_id:typeof o.card_id=="string"?o.card_id:e,card_data:o.card_data&&typeof o.card_data=="object"&&!Array.isArray(o.card_data)?structuredClone(o.card_data):{},computed_values:o.computed_values&&typeof o.computed_values=="object"&&!Array.isArray(o.computed_values)?structuredClone(o.computed_values):{}}}function L(e,n){if(!e||typeof e!="object")throw new Error("payload must be an object");if(!n)throw new Error("cardId is required");let g=(Array.isArray(e.cardDefinitions)?e.cardDefinitions:[]).find(k=>k.id===n);if(!g)throw new Error(`cardDefinitions has no entry with id ${n}`);let m=e.statusSnapshot&&typeof e.statusSnapshot=="object"?e.statusSnapshot:{},l=e.cardRuntimeById&&typeof e.cardRuntimeById=="object"?e.cardRuntimeById:{},c=e.dataObjectsByToken&&typeof e.dataObjectsByToken=="object"?e.dataObjectsByToken:{},s=(Array.isArray(m.cards)?m.cards:[]).find(k=>k.name===n),d=structuredClone(g),r=he(n,l[n]),t={...d.card_data&&typeof d.card_data=="object"&&!Array.isArray(d.card_data)?d.card_data:{},...r.card_data||{},status:X(s?.status),lastRun:s?.runtime?.last_transition_at??null};s?.error?.message&&(t.error=s.error.message);let i=s?{task_status:s.status??null,card_status:X(s.status),runtime:structuredClone(s.runtime??{}),error:s.error?structuredClone(s.error):null,blocked_by:Array.isArray(s.blocked_by)?structuredClone(s.blocked_by):[],requires_missing:Array.isArray(s.requires_missing)?structuredClone(s.requires_missing):[]}:{task_status:null,card_status:t.status??"fresh",runtime:{last_transition_at:t.lastRun??null},error:t.error?{message:t.error}:null,blocked_by:[],requires_missing:[]},y=Array.isArray(d.requires)?d.requires:[],S={};for(let[k,G]of Object.entries(c))S[k]=structuredClone(G);for(let k of y)Object.prototype.hasOwnProperty.call(S,k)||(S[k]=null);return {id:n,card:d,card_data:t,requires:S,computed_values:r.computed_values,runtime_state:i}}function U(e){if(!e||typeof e!="object")throw new Error("payload must be an object");return (Array.isArray(e.cardDefinitions)?e.cardDefinitions:[]).map(o=>L(e,o.id))}function H(e){return JSON.parse(JSON.stringify(e))}function j(e,n){if(e===n)return e;try{if(JSON.stringify(e)===JSON.stringify(n))return e}catch{}return n}function _(e,n){if(e===n)return true;try{return JSON.stringify(e)===JSON.stringify(n)}catch{return false}}function ve(e){return e==="running"||e==="in-progress"?"loading":e==="failed"?"error":"fresh"}function J(e,n,o){let g=e,l=(g&&Array.isArray(g.cardDefinitions)?g.cardDefinitions:[]).map(s=>s.id),c=n&&n.modelsById||{},h={};for(let s of l){let d=o(e,s),r=c[s];if(!r){h[s]=d;continue}let a={id:d.id,card:j(r.card,d.card),card_data:j(r.card_data,d.card_data),requires:j(r.requires,d.requires),computed_values:j(r.computed_values,d.computed_values),runtime_state:j(r.runtime_state,d.runtime_state)};h[s]=a.card===r.card&&a.card_data===r.card_data&&a.requires===r.requires&&a.computed_values===r.computed_values&&a.runtime_state===r.runtime_state?r:a;}return {payload:e,cardIds:l,modelsById:h}}function Y(e,n,o,g){if(!e||!Array.isArray(n)||n.length===0)return e;let m=e.modelsById,l=e.cardIds,c=false,h=false,s={};for(let r of l){let a=m[r],t=a&&a.requires;if(t&&typeof t=="object")for(let i of Object.keys(t))(s[i]=s[i]||[]).push(r);}function d(){c||(m={...m},c=true);}for(let r of n)if(!(!r||!r.kind)){if(r.kind==="computed_values"){let a=r.cardId,t=m[a];if(!t)continue;let i=r.values||{};if(_(t.computed_values,i))continue;d(),m[a]={...t,computed_values:i},h=true;}else if(r.kind==="data_object"){let a=r.key,t=r.payload,i=s[a]||[];for(let y of i){let S=m[y];if(!S)continue;let k=S.requires||{};_(k[a],t)||(d(),m[y]={...S,requires:{...k,[a]:t}},h=true);}}else if(r.kind==="card_refreshed"){let a=r.cardId,t=null;try{let y=g();y&&(t=o(y,a));}catch{}if(!t)continue;let i=m[a];if(i&&_(i.card,t.card)&&_(i.card_data,t.card_data)&&_(i.requires,t.requires)&&_(i.computed_values,t.computed_values)&&_(i.runtime_state,t.runtime_state))continue;d(),m[a]=t,l.includes(a)||(l=[...l,a]),h=true;}else if(r.kind==="status"){let a=r.status?.cards??[];for(let t of a){let i=t?.name;if(!i||!m[i])continue;let y=m[i],S=ve(t.status),k={...y.card_data||{},status:S,lastRun:t.runtime?.last_transition_at??null,...t.error?.message?{error:t.error.message}:{}};t.error?.message||delete k.error;let G={task_status:t.status??null,card_status:S,runtime:t.runtime?H(t.runtime):{},error:t.error?H(t.error):null,blocked_by:Array.isArray(t.blocked_by)?H(t.blocked_by):[],requires_missing:Array.isArray(t.requires_missing)?H(t.requires_missing):[]};_(y.card_data,k)&&_(y.runtime_state,G)||(d(),m[i]={...y,card_data:k,runtime_state:G},h=true);}}}return h?{payload:e.payload,cardIds:l,modelsById:m}:e}function un(e){let o=`/api/boards/${encodeURIComponent(e||"default")}`;return {initBoard:`${o}/init-board`,stream:`${o}/sse`,patchCard:g=>`${o}/cards/${encodeURIComponent(g)}`,cardAction:g=>`${o}/cards/${encodeURIComponent(g)}/actions`,cardFile:g=>`${o}/cards/${encodeURIComponent(g)}/files`,cardChats:g=>`${o}/cards/${encodeURIComponent(g)}/chats`}}function ln(e){if(!e||typeof e!="object")throw new Error("options are required");let{fetchServer:n,boardPaths:o,getServerOrigin:g}=e;if(typeof n!="function")throw new Error("options.fetchServer is required");if(typeof o!="function")throw new Error("options.boardPaths is required");if(typeof g!="function")throw new Error("options.getServerOrigin is required");let m=e.canvas&&typeof e.canvas=="object"?e.canvas:{height:"72vh",overflow:"auto"},l={current:null},c=null,h=null,s=String(e.initialMode||"board");function d(){return l.current?l.current.payload:null}async function r(p,b,w,x){if(!w)return null;let T=x?.inChat===true,C=typeof w.name=="string"?w.name:"upload.bin",N=w.type||"application/octet-stream",E=o(p),A=T?`${E.cardFile(b)}?inChat=true`:E.cardFile(b),O=await n(A,{method:"POST",headers:{"content-type":N,"x-file-name":encodeURIComponent(C)},body:w});if(!O.ok){let q=await O.text();throw new Error(`Upload failed (${O.status}): ${q||"unknown error"}`)}return (await O.json())?.file??null}async function a(p,b,w,x){if(w!=="chat-send"&&w!=="file-upload")return x||{};let T={...x||{}},C=Array.isArray(T.files)?T.files:[];if(!C.length)return T.files=[],T;let N=[];for(let E of C){let A=await r(p,b,E,{inChat:w==="chat-send"});A&&N.push(A);}return T.files=w==="chat-send"?[]:N,T}async function t(p){let b=String(p?.boardId||"default"),w=typeof p?.taskExecutorPath=="string"?p.taskExecutorPath.trim():"",x=String(p?.mode||s||"board"),T=p?.rootElement;if(!T)throw new Error("bootstrapBoard requires params.rootElement");let C=o(b),N=w?`${C.initBoard}?taskExecutorPath=${encodeURIComponent(w)}`:C.initBoard,E=await n(N);if(!E.ok)throw new Error(`Server init-board failed (${E.status}).`);let A=g();if(!A)throw new Error("Server origin not resolved before SSE start");let O=await new Promise((u,f)=>{let R=new EventSource(`${A}${C.stream}`);h=R;let v=false,I=setTimeout(()=>{v||f(new Error("SSE initial payload timeout (15s)"));},15e3);R.onmessage=z=>{try{let B=JSON.parse(z.data||"{}");!v&&(B?.cardDefinitions||U(B))&&(v=!0,clearTimeout(I),u(B));}catch{}},R.onerror=()=>{v||(clearTimeout(I),f(new Error("SSE connection failed during bootstrap")));};});if(!U(O))throw new Error("SSE payload missing published runtime artifacts");l.current=J(O,null,L);let D=globalThis.LiveCard;if(!D)throw new Error("LiveCard global not loaded \u2014 include live-cards.js before this script");let q=D.init({resolve:u=>l.current?.modelsById[u],chartLib:globalThis.Chart??null,markdown:globalThis.marked?u=>globalThis.marked.parse(u):null,sanitize:globalThis.DOMPurify?u=>globalThis.DOMPurify.sanitize(u):null,onPatchState:async(u,f)=>{await n(C.patchCard(u),{method:"PATCH",headers:{"content-type":"application/json"},body:JSON.stringify(f||{})});},onRefresh:async u=>{await n(C.patchCard(u),{method:"PATCH",headers:{"content-type":"application/json"},body:JSON.stringify({})});},onAction:async(u,f,R)=>{let v=await a(b,u,f,R);await n(C.cardAction(u),{method:"POST",headers:{"content-type":"application/json"},body:JSON.stringify({actionType:f,payload:v||{}})});},getChatMessages:async u=>{let f=await n(C.cardChats(u));return f.ok?((await f.json())?.messages??[]).map(v=>({role:typeof v?.role=="string"?v.role:"system",text:typeof v?.text=="string"?v.text:"",files:[]})):[]}});return T.innerHTML="",c=D.Board(q,T,{initialState:l.current,getNodeIds:u=>u.cardIds,selectNode:(u,f)=>u.modelsById[f],mode:x,canvas:m}),s=x,h.onmessage=u=>{try{let f=JSON.parse(u.data||"{}");if(f?.kind==="notification-batch"&&Array.isArray(f.notifications))c&&c.setState(v=>{let I=Y(v,f.notifications,L,d);return l.current=I,I});else if(f?.cardDefinitions){let v=J(f,l.current,L);l.current=v,c&&c.setState(()=>v);}let R=c&&c.engine;R&&typeof R.onServerSseEvent=="function"?R.onServerSseEvent():R&&typeof R.refreshOpenChatModal=="function"&&R.refreshOpenChatModal();}catch(f){console.warn("Bad SSE payload",f);}},c}function i(){h&&(h.close(),h=null),c=null,l.current=null;}function y(p){s=String(p||"board");let b=c&&c.core;b&&typeof b.setMode=="function"&&b.setMode(s);}function S(){if(!c)return;s="canvas";let p=c.core;p&&typeof p.setMode=="function"&&p.setMode("canvas"),p&&typeof p.autoLayout=="function"&&p.autoLayout();}function k(p){let b=c&&c.core;b&&typeof b.setDevMode=="function"&&b.setDevMode(!!p);}function G(){return s}return {bootstrapBoard:t,dispose:i,setMode:y,autoLayout:S,setDevMode:k,getCurrentMode:G}}exports.applyNotification=Y;exports.buildBoardState=J;exports.createBoardRuntimeClient=ln;exports.defaultBoardPaths=un;exports.selectAllLiveCardModels=U;exports.selectLiveCardModel=L;return exports;})({});//# sourceMappingURL=board-livecards-client.js.map
|
|
1
|
+
var BoardLiveCardsClient=(function(exports){'use strict';function X(e){return e==="running"||e==="in-progress"?"loading":e==="failed"?"error":"fresh"}function he(e,r){let a=r&&typeof r=="object"&&!Array.isArray(r)?r:{};return {schema_version:a.schema_version||"v1",card_id:typeof a.card_id=="string"?a.card_id:e,card_data:a.card_data&&typeof a.card_data=="object"&&!Array.isArray(a.card_data)?structuredClone(a.card_data):{},computed_values:a.computed_values&&typeof a.computed_values=="object"&&!Array.isArray(a.computed_values)?structuredClone(a.computed_values):{}}}function L(e,r){if(!e||typeof e!="object")throw new Error("payload must be an object");if(!r)throw new Error("cardId is required");let m=(Array.isArray(e.cardDefinitions)?e.cardDefinitions:[]).find(h=>h.id===r);if(!m)throw new Error(`cardDefinitions has no entry with id ${r}`);let k=e.statusSnapshot&&typeof e.statusSnapshot=="object"?e.statusSnapshot:{},f=e.cardRuntimeById&&typeof e.cardRuntimeById=="object"?e.cardRuntimeById:{},d=e.dataObjectsByToken&&typeof e.dataObjectsByToken=="object"?e.dataObjectsByToken:{},o=(Array.isArray(k.cards)?k.cards:[]).find(h=>h.name===r),u=structuredClone(m),n=he(r,f[r]),t={...u.card_data&&typeof u.card_data=="object"&&!Array.isArray(u.card_data)?u.card_data:{},...n.card_data||{},status:X(o?.status),lastRun:o?.runtime?.last_transition_at??null};o?.error?.message&&(t.error=o.error.message);let i=o?{task_status:o.status??null,card_status:X(o.status),runtime:structuredClone(o.runtime??{}),error:o.error?structuredClone(o.error):null,blocked_by:Array.isArray(o.blocked_by)?structuredClone(o.blocked_by):[],requires_missing:Array.isArray(o.requires_missing)?structuredClone(o.requires_missing):[]}:{task_status:null,card_status:t.status??"fresh",runtime:{last_transition_at:t.lastRun??null},error:t.error?{message:t.error}:null,blocked_by:[],requires_missing:[]},v=Array.isArray(u.requires)?u.requires:[],s={};for(let[h,x]of Object.entries(d))s[h]=structuredClone(x);for(let h of v)Object.prototype.hasOwnProperty.call(s,h)||(s[h]=null);return {id:r,card:u,card_data:t,requires:s,computed_values:n.computed_values,runtime_state:i}}function U(e){if(!e||typeof e!="object")throw new Error("payload must be an object");return (Array.isArray(e.cardDefinitions)?e.cardDefinitions:[]).map(a=>L(e,a.id))}function H(e){return JSON.parse(JSON.stringify(e))}function j(e,r){if(e===r)return e;try{if(JSON.stringify(e)===JSON.stringify(r))return e}catch{}return r}function _(e,r){if(e===r)return true;try{return JSON.stringify(e)===JSON.stringify(r)}catch{return false}}function ve(e){return e==="running"||e==="in-progress"?"loading":e==="failed"?"error":"fresh"}function J(e,r,a){let m=e,f=(m&&Array.isArray(m.cardDefinitions)?m.cardDefinitions:[]).map(o=>o.id),d=r&&r.modelsById||{},b={};for(let o of f){let u=a(e,o),n=d[o];if(!n){b[o]=u;continue}let c={id:u.id,card:j(n.card,u.card),card_data:j(n.card_data,u.card_data),requires:j(n.requires,u.requires),computed_values:j(n.computed_values,u.computed_values),runtime_state:j(n.runtime_state,u.runtime_state)};b[o]=c.card===n.card&&c.card_data===n.card_data&&c.requires===n.requires&&c.computed_values===n.computed_values&&c.runtime_state===n.runtime_state?n:c;}return {payload:e,cardIds:f,modelsById:b}}function Y(e,r,a,m){if(!e||!Array.isArray(r)||r.length===0)return e;let k=e.modelsById,f=e.cardIds,d=false,b=false,o={};for(let n of f){let c=k[n],t=c&&c.requires;if(t&&typeof t=="object")for(let i of Object.keys(t))(o[i]=o[i]||[]).push(n);}function u(){d||(k={...k},d=true);}for(let n of r)if(!(!n||!n.kind)){if(n.kind==="computed_values"){let c=n.cardId,t=k[c];if(!t)continue;let i=n.values||{};if(_(t.computed_values,i))continue;u(),k[c]={...t,computed_values:i},b=true;}else if(n.kind==="data_object"){let c=n.key,t=n.payload,i=o[c]||[];for(let v of i){let s=k[v];if(!s)continue;let h=s.requires||{};_(h[c],t)||(u(),k[v]={...s,requires:{...h,[c]:t}},b=true);}}else if(n.kind==="card_refreshed"){let c=n.cardId,t=null,i=k[c],v=n.card;if(i&&v&&typeof v=="object"&&!Array.isArray(v)){let s=v,h=s.card_data&&typeof s.card_data=="object"&&!Array.isArray(s.card_data)?s.card_data:i.card_data,x=s.requires&&typeof s.requires=="object"&&!Array.isArray(s.requires)?s.requires:i.requires,l=s.computed_values&&typeof s.computed_values=="object"&&!Array.isArray(s.computed_values)?s.computed_values:i.computed_values,y=s.runtime_state&&typeof s.runtime_state=="object"&&!Array.isArray(s.runtime_state)?s.runtime_state:i.runtime_state;t={...i,card:v,card_data:h,requires:x,computed_values:l,runtime_state:y};}if(!t)try{let s=m();s&&(t=a(s,c));}catch{}if(!t||i&&_(i.card,t.card)&&_(i.card_data,t.card_data)&&_(i.requires,t.requires)&&_(i.computed_values,t.computed_values)&&_(i.runtime_state,t.runtime_state))continue;u(),k[c]=t,f.includes(c)||(f=[...f,c]),b=true;}else if(n.kind==="status"){let c=n.status?.cards??[];for(let t of c){let i=t?.name;if(!i||!k[i])continue;let v=k[i],s=ve(t.status),h={...v.card_data||{},status:s,lastRun:t.runtime?.last_transition_at??null,...t.error?.message?{error:t.error.message}:{}};t.error?.message||delete h.error;let x={task_status:t.status??null,card_status:s,runtime:t.runtime?H(t.runtime):{},error:t.error?H(t.error):null,blocked_by:Array.isArray(t.blocked_by)?H(t.blocked_by):[],requires_missing:Array.isArray(t.requires_missing)?H(t.requires_missing):[]};_(v.card_data,h)&&_(v.runtime_state,x)||(u(),k[i]={...v,card_data:h,runtime_state:x},b=true);}}}return b?{payload:e.payload,cardIds:f,modelsById:k}:e}function dr(e){let a=`/api/boards/${encodeURIComponent(e||"default")}`;return {initBoard:`${a}/init-board`,stream:`${a}/sse`,patchCard:m=>`${a}/cards/${encodeURIComponent(m)}`,cardAction:m=>`${a}/cards/${encodeURIComponent(m)}/actions`,cardFile:m=>`${a}/cards/${encodeURIComponent(m)}/files`,cardChats:m=>`${a}/cards/${encodeURIComponent(m)}/chats`}}function ur(e){if(!e||typeof e!="object")throw new Error("options are required");let{fetchServer:r,boardPaths:a,getServerOrigin:m}=e;if(typeof r!="function")throw new Error("options.fetchServer is required");if(typeof a!="function")throw new Error("options.boardPaths is required");if(typeof m!="function")throw new Error("options.getServerOrigin is required");let k=e.canvas&&typeof e.canvas=="object"?e.canvas:{height:"72vh",overflow:"auto"},f={current:null},d=null,b=null,o=String(e.initialMode||"board");function u(){return f.current?f.current.payload:null}async function n(l,y,w,A){if(!w)return null;let T=A?.inChat===true,C=typeof w.name=="string"?w.name:"upload.bin",N=w.type||"application/octet-stream",E=a(l),O=T?`${E.cardFile(y)}?inChat=true`:E.cardFile(y),G=await r(O,{method:"POST",headers:{"content-type":N,"x-file-name":encodeURIComponent(C)},body:w});if(!G.ok){let q=await G.text();throw new Error(`Upload failed (${G.status}): ${q||"unknown error"}`)}return (await G.json())?.file??null}async function c(l,y,w,A){if(w!=="chat-send"&&w!=="file-upload")return A||{};let T={...A||{}},C=Array.isArray(T.files)?T.files:[];if(!C.length)return T.files=[],T;let N=[];for(let E of C){let O=await n(l,y,E,{inChat:w==="chat-send"});O&&N.push(O);}return T.files=w==="chat-send"?[]:N,T}async function t(l){let y=String(l?.boardId||"default"),w=typeof l?.taskExecutorPath=="string"?l.taskExecutorPath.trim():"",A=String(l?.mode||o||"board"),T=l?.rootElement;if(!T)throw new Error("bootstrapBoard requires params.rootElement");let C=a(y),N=w?`${C.initBoard}?taskExecutorPath=${encodeURIComponent(w)}`:C.initBoard,E=await r(N);if(!E.ok)throw new Error(`Server init-board failed (${E.status}).`);let O=m();if(!O)throw new Error("Server origin not resolved before SSE start");let G=await new Promise((p,g)=>{let R=new EventSource(`${O}${C.stream}`);b=R;let S=false,I=setTimeout(()=>{S||g(new Error("SSE initial payload timeout (15s)"));},15e3);R.onmessage=z=>{try{let B=JSON.parse(z.data||"{}");!S&&(B?.cardDefinitions||U(B))&&(S=!0,clearTimeout(I),p(B));}catch{}},R.onerror=()=>{S||(clearTimeout(I),g(new Error("SSE connection failed during bootstrap")));};});if(!U(G))throw new Error("SSE payload missing published runtime artifacts");f.current=J(G,null,L);let D=globalThis.LiveCard;if(!D)throw new Error("LiveCard global not loaded \u2014 include live-cards.js before this script");let q=D.init({resolve:p=>f.current?.modelsById[p],chartLib:globalThis.Chart??null,markdown:globalThis.marked?p=>globalThis.marked.parse(p):null,sanitize:globalThis.DOMPurify?p=>globalThis.DOMPurify.sanitize(p):null,onPatchState:async(p,g)=>{await r(C.patchCard(p),{method:"PATCH",headers:{"content-type":"application/json"},body:JSON.stringify(g||{})});},onRefresh:async p=>{await r(C.patchCard(p),{method:"PATCH",headers:{"content-type":"application/json"},body:JSON.stringify({})});},onAction:async(p,g,R)=>{let S=await c(y,p,g,R);await r(C.cardAction(p),{method:"POST",headers:{"content-type":"application/json"},body:JSON.stringify({actionType:g,payload:S||{}})});},getChatMessages:async p=>{let g=await r(C.cardChats(p));return g.ok?((await g.json())?.messages??[]).map(S=>({role:typeof S?.role=="string"?S.role:"system",text:typeof S?.text=="string"?S.text:"",files:[]})):[]}});return T.innerHTML="",d=D.Board(q,T,{initialState:f.current,getNodeIds:p=>p.cardIds,selectNode:(p,g)=>p.modelsById[g],mode:A,canvas:k}),o=A,b.onmessage=p=>{try{let g=JSON.parse(p.data||"{}");if(g?.kind==="notification-batch"&&Array.isArray(g.notifications))d&&d.setState(S=>{let I=Y(S,g.notifications,L,u);return f.current=I,I});else if(g?.cardDefinitions){let S=J(g,f.current,L);f.current=S,d&&d.setState(()=>S);}let R=d&&d.engine;R&&typeof R.onServerSseEvent=="function"?R.onServerSseEvent():R&&typeof R.refreshOpenChatModal=="function"&&R.refreshOpenChatModal();}catch(g){console.warn("Bad SSE payload",g);}},d}function i(){b&&(b.close(),b=null),d=null,f.current=null;}function v(l){o=String(l||"board");let y=d&&d.core;y&&typeof y.setMode=="function"&&y.setMode(o);}function s(){if(!d)return;o="canvas";let l=d.core;l&&typeof l.setMode=="function"&&l.setMode("canvas"),l&&typeof l.autoLayout=="function"&&l.autoLayout();}function h(l){let y=d&&d.core;y&&typeof y.setDevMode=="function"&&y.setDevMode(!!l);}function x(){return o}return {bootstrapBoard:t,dispose:i,setMode:v,autoLayout:s,setDevMode:h,getCurrentMode:x}}exports.applyNotification=Y;exports.buildBoardState=J;exports.createBoardRuntimeClient=ur;exports.defaultBoardPaths=dr;exports.selectAllLiveCardModels=U;exports.selectLiveCardModel=L;return exports;})({});//# sourceMappingURL=board-livecards-client.js.map
|
|
2
2
|
//# sourceMappingURL=board-livecards-client.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/board-livegraph-runtime/index.ts","../src/cli/common/board-state-reducer.ts","../src/board-livecards-client/index.ts"],"names":["taskStatusToCardStatus","taskStatus","normalizeCardRuntimeArtifact","cardId","artifact","safe","selectLiveCardModel","payload","cardDefinition","c","statusSnapshot","cardRuntimeById","dataObjectsByToken","statusCard","card","runtimeArtifact","card_data","runtime_state","requiresTokens","requires","token","value","selectAllLiveCardModels","clone","x","stableEq","prev","next","deepEqJson","a","b","buildBoardState","prevState","p","cardIds","prevModels","modelsById","id","fresh","stab","applyNotification","notifications","getFullPayload","cloned","changed","consumersByToken","cid","m","reqs","t","ensureClone","note","nextValues","key","notePayload","consumers","prevC","prevReqs","fp","existing","statusCards","sid","prevS","nextCardStatus","nextCardData","nextRuntimeState","defaultBoardPaths","boardId","base","createBoardRuntimeClient","options","fetchServer","boardPaths","getServerOrigin","canvas","stateRef","board","sse","currentMode","uploadCardFile","file","opts","inChat","fileName","contentType","paths","uploadPath","upload","errText","uploadActionFiles","actionType","nextPayload","rawFiles","uploaded","fileMeta","bootstrapBoard","params","taskExecutorPath","mode","rootEl","initBoardPath","initBoardRes","origin","initialPayload","resolve","reject","sseConn","gotInitialPayload","timeout","evt","update","LiveCard","engine","text","html","patch","actionPayload","uploadedPayload","res","s","eng","err","dispose","setMode","core","autoLayout","setDevMode","enabled","getCurrentMode"],"mappings":"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","file":"board-livecards-client.js","sourcesContent":["import type { GraphConfig, GraphEvent, TaskConfig } from '../event-graph/types.js';\nimport { CardCompute } from '../card-compute/index.js';\nimport type { ComputeNode } from '../card-compute/index.js';\nimport {\n createReactiveGraph,\n type ReactiveGraph,\n type ReactiveGraphOptions,\n type TaskHandlerFn,\n type TaskHandlerInput,\n type TaskHandlerReturn,\n type LiveGraph,\n schedule,\n} from '../continuous-event-graph/index.js';\nimport type { LiveCard, LiveBoard } from '../continuous-event-graph/live-cards-bridge.js';\n\nexport interface BrowserSourceAdapterContext {\n card: LiveCard;\n input: TaskHandlerInput;\n}\n\nexport type BrowserSourceAdapter =\n (ctx: BrowserSourceAdapterContext) => Promise<Record<string, unknown>> | Record<string, unknown>;\n\nexport interface BoardTaskExecutorContext {\n card: LiveCard;\n input: TaskHandlerInput;\n}\n\n/**\n * Opaque task executor hook.\n * Runtime does not interpret source descriptors — executor owns that contract.\n * For source cards, return a map keyed by source.bindTo.\n */\nexport type BoardTaskExecutor =\n (ctx: BoardTaskExecutorContext) => Promise<Record<string, unknown> | undefined> | Record<string, unknown> | undefined;\n\nexport interface BoardLiveGraphRuntimeOptions {\n /** Preferred opaque source/task executor. */\n taskExecutor?: BoardTaskExecutor;\n /** Per-card source adapters keyed by card ID. */\n sourceAdapters?: Record<string, BrowserSourceAdapter>;\n /** Default source adapter applied when no per-card adapter matches. */\n defaultSourceAdapter?: BrowserSourceAdapter;\n reactiveOptions?: Partial<Omit<ReactiveGraphOptions, 'handlers'>>;\n graphSettings?: Partial<GraphConfig['settings']>;\n executionId?: string;\n}\n\nexport interface LiveCardRuntimeModel {\n id: string;\n card: LiveCard;\n card_data: Record<string, unknown>;\n requires: Record<string, unknown>;\n computed_values: Record<string, unknown>;\n runtime_state: Record<string, unknown>;\n}\n\nexport interface BoardRuntimeView {\n id?: string;\n title?: string;\n mode?: 'board' | 'canvas';\n positions?: Record<string, { x?: number; y?: number; w?: number; h?: number }>;\n settings?: Partial<GraphConfig['settings']>;\n nodes: LiveCardRuntimeModel[];\n}\n\nexport interface BoardLiveGraphRuntimeUpdate {\n events: GraphEvent[];\n graph: LiveGraph;\n nodes: LiveCardRuntimeModel[];\n}\n\nexport interface BoardLiveGraphRuntime {\n getGraph(): ReactiveGraph;\n getState(): LiveGraph;\n getNodes(): LiveCardRuntimeModel[];\n getBoard(): BoardRuntimeView;\n getSchedule(): ReturnType<typeof schedule>;\n subscribe(listener: (update: BoardLiveGraphRuntimeUpdate) => void): () => void;\n addCard(card: LiveCard): void;\n upsertCard(card: LiveCard): void;\n removeCard(cardId: string): void;\n patchCardState(cardId: string, patch: Record<string, unknown>): void;\n retrigger(cardId: string): void;\n retriggerAll(): void;\n push(event: GraphEvent): void;\n pushAll(events: GraphEvent[]): void;\n dispose(): void;\n}\n\nfunction deepClone<T>(value: T): T {\n return JSON.parse(JSON.stringify(value)) as T;\n}\n\nfunction toTaskConfig(card: LiveCard): TaskConfig {\n const provides = (card.provides && card.provides.length > 0)\n ? card.provides.map(p => p.bindTo)\n : [card.id];\n\n return {\n requires: card.requires && card.requires.length > 0 ? [...card.requires] : undefined,\n provides,\n taskHandlers: [card.id],\n description: card.meta?.title ?? card.id,\n };\n}\n\nfunction buildTokenProviders(cards: Map<string, LiveCard>): Map<string, string> {\n const tokenToCardId = new Map<string, string>();\n for (const [cardId, card] of cards.entries()) {\n const bindings = card.provides && card.provides.length > 0\n ? card.provides\n : [{ bindTo: cardId, ref: 'card_data' }];\n for (const binding of bindings) tokenToCardId.set(binding.bindTo, cardId);\n }\n return tokenToCardId;\n}\n\nfunction validateRequires(cards: Map<string, LiveCard>, changedCardId: string): void {\n const tokenProviders = buildTokenProviders(cards);\n const card = cards.get(changedCardId);\n if (!card) return;\n\n for (const req of card.requires ?? []) {\n if (!tokenProviders.has(req)) {\n throw new Error(`Card \"${changedCardId}\" requires token \"${req}\" but no card provides it`);\n }\n }\n}\n\n/**\n * LocalStorageService — browser-side persistence layer for card artifacts\n * Mirrors CLI's file-based persistence (cards, computed artifacts, status)\n * \n * Keys:\n * - 'yf:cards:<id>' → card definitions (mirrors tmp/cards/<id>.json)\n * - 'yf:runtime-out:cards:<id>' → computed artifacts (mirrors runtime-out/cards/<id>.computed.json)\n * - 'yf:runtime-out:status' → board status snapshot (mirrors runtime-out/board-livegraph-status.json)\n */\nexport const LocalStorageService = {\n // Keys\n CARD_PREFIX: 'yf:cards:',\n RUNTIME_OUT_PREFIX: 'yf:runtime-out:cards:',\n STATUS_KEY: 'yf:runtime-out:status',\n\n // Read/write cards (mirrors tmp/cards/<id>.json)\n writeCard(cardId: string, cardObject: Record<string, unknown>): void {\n try {\n localStorage.setItem(this.CARD_PREFIX + cardId, JSON.stringify(cardObject));\n } catch (e) {\n console.warn(`Failed to write card ${cardId} to localStorage:`, e);\n }\n },\n readCard(cardId: string): Record<string, unknown> | null {\n try {\n const raw = localStorage.getItem(this.CARD_PREFIX + cardId);\n return raw ? JSON.parse(raw) : null;\n } catch (e) {\n console.warn(`Failed to read card ${cardId} from localStorage:`, e);\n return null;\n }\n },\n readAllCards(cardIds: string[]): Record<string, Record<string, unknown>> {\n const result: Record<string, Record<string, unknown>> = {};\n for (const id of cardIds) {\n const card = this.readCard(id);\n if (card) result[id] = card;\n }\n return result;\n },\n\n // Read/write computed artifacts (mirrors runtime-out/cards/<id>.computed.json)\n writeComputedArtifact(artifact: Record<string, unknown>): void {\n if (!artifact || !artifact.card_id) return;\n try {\n localStorage.setItem(\n this.RUNTIME_OUT_PREFIX + String(artifact.card_id),\n JSON.stringify(artifact)\n );\n } catch (e) {\n console.warn(`Failed to write computed artifact ${artifact.card_id}:`, e);\n }\n },\n readComputedArtifact(cardId: string): Record<string, unknown> | null {\n try {\n const raw = localStorage.getItem(this.RUNTIME_OUT_PREFIX + cardId);\n return raw ? JSON.parse(raw) : null;\n } catch (e) {\n console.warn(`Failed to read computed artifact ${cardId}:`, e);\n return null;\n }\n },\n readAllComputedArtifacts(cardIds: string[]): Record<string, Record<string, unknown>> {\n const result: Record<string, Record<string, unknown>> = {};\n for (const id of cardIds) {\n const artifact = this.readComputedArtifact(id);\n if (artifact) result[id] = artifact;\n }\n return result;\n },\n\n // Read/write board status snapshot (mirrors runtime-out/board-livegraph-status.json)\n writeStatusSnapshot(snapshot: Record<string, unknown>): void {\n try {\n localStorage.setItem(this.STATUS_KEY, JSON.stringify(snapshot));\n } catch (e) {\n console.warn('Failed to write status snapshot to localStorage:', e);\n }\n },\n readStatusSnapshot(): Record<string, unknown> | null {\n try {\n const raw = localStorage.getItem(this.STATUS_KEY);\n return raw ? JSON.parse(raw) : null;\n } catch (e) {\n console.warn('Failed to read status snapshot from localStorage:', e);\n return null;\n }\n },\n\n // Clear all (useful for reset/demo)\n clear(): void {\n const keysToDelete: string[] = [];\n for (let i = 0; i < localStorage.length; i++) {\n const key = localStorage.key(i);\n if (key && (key.startsWith(this.CARD_PREFIX) || key.startsWith(this.RUNTIME_OUT_PREFIX) || key === this.STATUS_KEY)) {\n keysToDelete.push(key);\n }\n }\n for (const key of keysToDelete) {\n localStorage.removeItem(key);\n }\n }\n};\n\nexport function createBoardLiveGraphRuntime(\n input: LiveCard[] | LiveBoard,\n options: BoardLiveGraphRuntimeOptions = {},\n): BoardLiveGraphRuntime {\n const boardMeta: Pick<LiveBoard, 'id' | 'title' | 'mode' | 'positions' | 'settings'> = Array.isArray(input)\n ? {}\n : {\n id: input.id,\n title: input.title,\n mode: input.mode,\n positions: input.positions,\n settings: input.settings,\n };\n\n const initialCards = Array.isArray(input) ? input : input.nodes;\n const cards = new Map<string, LiveCard>();\n for (const card of initialCards) {\n if (cards.has(card.id)) throw new Error(`Duplicate card ID: \"${card.id}\"`);\n cards.set(card.id, deepClone(card));\n }\n\n const listeners = new Set<(update: BoardLiveGraphRuntimeUpdate) => void>();\n const taskExecutor = options.taskExecutor;\n const sourceAdapters = options.sourceAdapters ?? {};\n const defaultSourceAdapter = options.defaultSourceAdapter;\n\n let graphRef: ReactiveGraph | null = null;\n\n const notifyListeners = (events: GraphEvent[], graph: LiveGraph): void => {\n const update: BoardLiveGraphRuntimeUpdate = {\n events,\n graph,\n nodes: getRenderableNodes(),\n };\n for (const listener of listeners) listener(update);\n };\n\n const makeHandler = (cardId: string): TaskHandlerFn => {\n return async (inputArgs: TaskHandlerInput): Promise<TaskHandlerReturn> => {\n const card = cards.get(cardId);\n if (!card) return 'task-initiate-failure';\n\n const requiresData: Record<string, unknown> = {};\n for (const token of card.requires ?? []) {\n const upstream = inputArgs.state[token] as Record<string, unknown> | undefined;\n if (!upstream || typeof upstream !== 'object') continue;\n const providesData = upstream.provides_data as Record<string, unknown> | undefined;\n if (!providesData || typeof providesData !== 'object') continue;\n if (!Object.prototype.hasOwnProperty.call(providesData, token)) continue;\n requiresData[token] = providesData[token];\n }\n\n const sourcesData: Record<string, unknown> = {};\n if (card.source_defs && card.source_defs.length > 0) {\n const adapter = sourceAdapters[cardId] ?? defaultSourceAdapter;\n const fetched = taskExecutor\n ? await taskExecutor({ card, input: inputArgs })\n : (adapter ? await adapter({ card, input: inputArgs }) : undefined);\n if (fetched && typeof fetched === 'object') {\n for (const src of card.source_defs) {\n if (Object.prototype.hasOwnProperty.call(fetched, src.bindTo)) {\n sourcesData[src.bindTo] = fetched[src.bindTo];\n } else if (card.source_defs.length === 1) {\n sourcesData[src.bindTo] = fetched;\n }\n }\n }\n }\n\n const computeNode: ComputeNode = {\n id: card.id,\n card_data: deepClone(card.card_data ?? {}),\n requires: requiresData,\n source_defs: card.source_defs,\n compute: card.compute as ComputeNode['compute'] | undefined,\n };\n computeNode._sourcesData = sourcesData;\n\n if (computeNode.compute && computeNode.compute.length > 0) {\n await CardCompute.run(computeNode, { sourcesData });\n }\n\n const providesData: Record<string, unknown> = {};\n if (card.provides && card.provides.length > 0) {\n for (const { bindTo, ref } of card.provides) {\n providesData[bindTo] = CardCompute.resolve(computeNode, ref);\n }\n } else {\n providesData[card.id] = {\n ...(computeNode.card_data ?? {}),\n ...(computeNode.computed_values ?? {}),\n ...(computeNode._sourcesData ?? {}),\n };\n }\n\n const resultData: Record<string, unknown> = {\n provides_data: providesData,\n card_data: computeNode.card_data ?? {},\n computed_values: computeNode.computed_values ?? {},\n fetched_sources: sourcesData,\n requires: requiresData,\n };\n\n graphRef?.resolveCallback(inputArgs.callbackToken, resultData);\n return 'task-initiated';\n };\n };\n\n const tasks: Record<string, TaskConfig> = {};\n const handlers: Record<string, TaskHandlerFn> = {};\n for (const [cardId, card] of cards.entries()) {\n validateRequires(cards, cardId);\n tasks[cardId] = toTaskConfig(card);\n handlers[cardId] = makeHandler(cardId);\n }\n\n const config: GraphConfig = {\n id: boardMeta.id ?? `browser-board-${Date.now()}`,\n settings: {\n completion: 'manual',\n execution_mode: 'eligibility-mode',\n ...(boardMeta.settings ?? {}),\n ...(options.graphSettings ?? {}),\n },\n tasks,\n };\n\n const userOnDrain = options.reactiveOptions?.onDrain;\n const graph = createReactiveGraph(\n config,\n {\n ...(options.reactiveOptions ?? {}),\n handlers,\n onDrain: (events, live, scheduleResult) => {\n userOnDrain?.(events, live, scheduleResult);\n notifyListeners(events, live);\n },\n },\n options.executionId,\n );\n graphRef = graph;\n\n function getRenderableNodes(): LiveCardRuntimeModel[] {\n const live = graph.getState();\n const out: LiveCardRuntimeModel[] = [];\n\n for (const [cardId, baseCard] of cards.entries()) {\n const data = live.state.tasks[cardId]?.data as Record<string, unknown> | undefined;\n const runtimeState = live.state.tasks[cardId];\n\n const mergedCardData = {\n ...(baseCard.card_data ?? {}),\n ...(data && typeof data.card_data === 'object' ? data.card_data as Record<string, unknown> : {}),\n };\n\n const cardStatus = runtimeState?.status === 'running' ? 'loading' : runtimeState?.status;\n const cardDataForView = {\n ...mergedCardData,\n ...(cardStatus ? { status: cardStatus } : {}),\n ...(runtimeState?.lastUpdated ? { lastRun: runtimeState.lastUpdated } : {}),\n ...(runtimeState?.status === 'failed' && runtimeState.error ? { error: runtimeState.error } : {}),\n };\n\n out.push({\n id: cardId,\n card: deepClone(baseCard),\n card_data: cardDataForView,\n requires: data && typeof data.requires === 'object' ? deepClone(data.requires as Record<string, unknown>) : {},\n computed_values: data && typeof data.computed_values === 'object' ? deepClone(data.computed_values as Record<string, unknown>) : {},\n runtime_state: runtimeState ? deepClone(runtimeState as unknown as Record<string, unknown>) : {},\n });\n }\n\n return out;\n }\n\n const runtime: BoardLiveGraphRuntime = {\n getGraph: () => graph,\n getState: () => graph.getState(),\n getSchedule: () => graph.getSchedule(),\n getNodes: () => getRenderableNodes(),\n getBoard: () => ({\n ...boardMeta,\n nodes: getRenderableNodes(),\n }),\n subscribe(listener: (update: BoardLiveGraphRuntimeUpdate) => void): () => void {\n listeners.add(listener);\n listener({ events: [], graph: graph.getState(), nodes: getRenderableNodes() });\n return () => listeners.delete(listener);\n },\n addCard(card: LiveCard): void {\n if (cards.has(card.id)) throw new Error(`Card \"${card.id}\" already exists`);\n cards.set(card.id, deepClone(card));\n validateRequires(cards, card.id);\n graph.registerHandler(card.id, makeHandler(card.id));\n graph.addNode(card.id, toTaskConfig(card));\n },\n upsertCard(card: LiveCard): void {\n cards.set(card.id, deepClone(card));\n validateRequires(cards, card.id);\n graph.registerHandler(card.id, makeHandler(card.id));\n graph.addNode(card.id, toTaskConfig(card));\n },\n removeCard(cardId: string): void {\n cards.delete(cardId);\n graph.unregisterHandler(cardId);\n graph.removeNode(cardId);\n },\n patchCardState(cardId: string, patch: Record<string, unknown>): void {\n const card = cards.get(cardId);\n if (!card) throw new Error(`Card \"${cardId}\" not found`);\n card.card_data = { ...(card.card_data ?? {}), ...patch };\n graph.retrigger(cardId);\n },\n retrigger(cardId: string): void {\n graph.retrigger(cardId);\n },\n retriggerAll(): void {\n graph.retriggerAll(Array.from(cards.keys()));\n },\n push(event: GraphEvent): void {\n graph.push(event);\n },\n pushAll(events: GraphEvent[]): void {\n graph.pushAll(events);\n },\n dispose(): void {\n listeners.clear();\n graph.dispose();\n },\n };\n\n return runtime;\n}\n\n// ---------------------------------------------------------------------------\n// Runtime-artifacts adapter (ported from reusable-runtime-artifacts-adapter.js)\n// ---------------------------------------------------------------------------\n\nexport interface CardRuntimeArtifact {\n schema_version?: string;\n card_id?: string;\n card_data?: Record<string, unknown>;\n computed_values?: Record<string, unknown>;\n}\n\nexport interface BoardRuntimeArtifactsPayload {\n cardDefinitions: LiveCard[];\n cardRuntimeById?: Record<string, CardRuntimeArtifact>;\n dataObjectsByToken?: Record<string, unknown>;\n statusSnapshot?: {\n cards?: Array<{\n name: string;\n status?: string;\n error?: { message?: string } | null;\n runtime?: { last_transition_at?: string | null };\n blocked_by?: string[];\n requires_missing?: string[];\n }>;\n };\n}\n\nfunction taskStatusToCardStatus(taskStatus: string | null | undefined): string {\n if (taskStatus === 'running' || taskStatus === 'in-progress') return 'loading';\n if (taskStatus === 'failed') return 'error';\n if (taskStatus === 'completed') return 'fresh';\n return 'fresh';\n}\n\nfunction cardStatusToTaskStatus(cardStatus: string | null | undefined): string {\n if (cardStatus === 'loading') return 'in-progress';\n if (cardStatus === 'error') return 'failed';\n if (cardStatus === 'stale') return 'pending';\n if (cardStatus === 'fresh') return 'completed';\n return 'pending';\n}\n\nfunction normalizeCardRuntimeArtifact(cardId: string, artifact: CardRuntimeArtifact | undefined): Required<CardRuntimeArtifact> {\n const safe = artifact && typeof artifact === 'object' && !Array.isArray(artifact) ? artifact : {};\n return {\n schema_version: (safe.schema_version as string) || 'v1',\n card_id: typeof safe.card_id === 'string' ? safe.card_id : cardId,\n card_data: safe.card_data && typeof safe.card_data === 'object' && !Array.isArray(safe.card_data)\n ? structuredClone(safe.card_data) : {},\n computed_values: safe.computed_values && typeof safe.computed_values === 'object' && !Array.isArray(safe.computed_values)\n ? structuredClone(safe.computed_values) : {},\n };\n}\n\n/**\n * Selects a single per-card render model from a runtime state payload.\n * Pure: same input → same output. Used by reactive Board to recompute\n * only the slice for one card.\n */\nexport function selectLiveCardModel(\n payload: BoardRuntimeArtifactsPayload,\n cardId: string,\n): LiveCardRuntimeModel {\n if (!payload || typeof payload !== 'object') throw new Error('payload must be an object');\n if (!cardId) throw new Error('cardId is required');\n\n const cardDefinitions = Array.isArray(payload.cardDefinitions) ? payload.cardDefinitions : [];\n const cardDefinition = cardDefinitions.find((c) => (c as { id?: string }).id === cardId);\n if (!cardDefinition) throw new Error(`cardDefinitions has no entry with id ${cardId}`);\n\n const statusSnapshot = payload.statusSnapshot && typeof payload.statusSnapshot === 'object' ? payload.statusSnapshot : {};\n const cardRuntimeById = payload.cardRuntimeById && typeof payload.cardRuntimeById === 'object' ? payload.cardRuntimeById : {};\n const dataObjectsByToken = payload.dataObjectsByToken && typeof payload.dataObjectsByToken === 'object' ? payload.dataObjectsByToken : {};\n const statusCards = Array.isArray((statusSnapshot as { cards?: unknown[] }).cards)\n ? (statusSnapshot as { cards: Array<{ name: string; status?: string; error?: { message?: string } | null; runtime?: { last_transition_at?: string | null }; blocked_by?: string[]; requires_missing?: string[] }> }).cards\n : [];\n const statusCard = statusCards.find((c) => c.name === cardId);\n\n const card = structuredClone(cardDefinition) as LiveCard & Record<string, unknown>;\n const runtimeArtifact = normalizeCardRuntimeArtifact(cardId, cardRuntimeById[cardId]);\n\n const baseCardData = card.card_data && typeof card.card_data === 'object' && !Array.isArray(card.card_data)\n ? card.card_data as Record<string, unknown> : {};\n\n const card_data: Record<string, unknown> = {\n ...baseCardData,\n ...(runtimeArtifact.card_data || {}),\n status: taskStatusToCardStatus(statusCard?.status),\n lastRun: (statusCard?.runtime?.last_transition_at) ?? null,\n };\n if (statusCard?.error?.message) card_data['error'] = statusCard.error.message;\n\n const runtime_state: Record<string, unknown> = statusCard\n ? {\n task_status: statusCard.status ?? null,\n card_status: taskStatusToCardStatus(statusCard.status),\n runtime: structuredClone(statusCard.runtime ?? {}),\n error: statusCard.error ? structuredClone(statusCard.error) : null,\n blocked_by: Array.isArray(statusCard.blocked_by) ? structuredClone(statusCard.blocked_by) : [],\n requires_missing: Array.isArray(statusCard.requires_missing) ? structuredClone(statusCard.requires_missing) : [],\n }\n : {\n task_status: null,\n card_status: card_data['status'] ?? 'fresh',\n runtime: { last_transition_at: card_data['lastRun'] ?? null },\n error: card_data['error'] ? { message: card_data['error'] } : null,\n blocked_by: [],\n requires_missing: [],\n };\n\n const requiresTokens = Array.isArray((card as { requires?: unknown }).requires) ? (card as { requires: string[] }).requires : [];\n // Include ALL data objects in the state, not just the statically declared requires tokens.\n // This handles dynamic requires, runtime token additions, and cards whose declared requires\n // may not reflect what data is currently available. The board's stable-ref diff handles\n // no-op cases where a card doesn't actually use a given token.\n const requires: Record<string, unknown> = {};\n for (const [token, value] of Object.entries(dataObjectsByToken as Record<string, unknown>)) {\n requires[token] = structuredClone(value);\n }\n // Also seed declared tokens not yet present in dataObjectsByToken as null,\n // so the applyNotification consumer map is always fully wired from init.\n for (const token of requiresTokens) {\n if (!Object.prototype.hasOwnProperty.call(requires, token)) {\n requires[token] = null;\n }\n }\n\n return {\n id: cardId,\n card: card as LiveCard,\n card_data,\n requires,\n computed_values: runtimeArtifact.computed_values,\n runtime_state,\n };\n}\n\n/**\n * Build per-card render models for every card in the payload.\n */\nexport function selectAllLiveCardModels(payload: BoardRuntimeArtifactsPayload): LiveCardRuntimeModel[] {\n if (!payload || typeof payload !== 'object') throw new Error('payload must be an object');\n const cardDefinitions = Array.isArray(payload.cardDefinitions) ? payload.cardDefinitions : [];\n return cardDefinitions.map((c) => selectLiveCardModel(payload, (c as { id: string }).id));\n}\n\nexport interface BuildBrowserArtifactsOptions {\n boardPath?: string;\n cardDefinitions: LiveCard[];\n runtimeModels: LiveCardRuntimeModel[];\n graphState: LiveGraph;\n}\n\n/**\n * Converts browser-runtime state (LiveCardRuntimeModel[] + LiveGraph) back into\n * the runtime payload shape consumed by selectLiveCardModel / selectAllLiveCardModels.\n * Used by the browser-only shell to keep the same selector path as the server shell.\n */\nexport function buildBrowserArtifactsFromRuntime({\n boardPath,\n cardDefinitions,\n runtimeModels,\n graphState,\n}: BuildBrowserArtifactsOptions): BoardRuntimeArtifactsPayload {\n const safeCardDefs = Array.isArray(cardDefinitions) ? cardDefinitions : [];\n const safeModels = Array.isArray(runtimeModels) ? runtimeModels : [];\n const runtimeModelById = new Map(safeModels.map((m) => [m.id, m]));\n type TaskEntry = { data?: { provides_data?: Record<string, unknown> }; status?: string; error?: string; executionCount?: number; retryCount?: number; startedAt?: string; lastUpdated?: string; completedAt?: string; failedAt?: string };\n const graphStateAny = graphState as { state?: { tasks?: Record<string, TaskEntry> } };\n const taskStates: Record<string, TaskEntry> = graphStateAny.state?.tasks ?? {};\n\n const cardRuntimeById: Record<string, CardRuntimeArtifact> = {};\n for (const model of safeModels) {\n if (!model?.id) continue;\n cardRuntimeById[model.id] = {\n schema_version: 'v1',\n card_id: model.id,\n card_data: structuredClone(model.card_data ?? {}),\n computed_values: structuredClone(model.computed_values ?? {}),\n };\n }\n\n const dataObjectsByToken: Record<string, unknown> = {};\n for (const taskName of Object.keys(taskStates)) {\n const providesData = taskStates[taskName]?.data?.provides_data;\n if (providesData && typeof providesData === 'object') {\n for (const token of Object.keys(providesData)) {\n dataObjectsByToken[token] = structuredClone(providesData[token]);\n }\n }\n }\n\n const statusCards = safeCardDefs.map((cardDef) => {\n const model = runtimeModelById.get(cardDef.id) ?? {} as Partial<LiveCardRuntimeModel>;\n const taskState = taskStates[cardDef.id];\n const taskStatus = typeof taskState?.status === 'string'\n ? taskState.status\n : cardStatusToTaskStatus((model.card_data as Record<string, unknown> | undefined)?.['status'] as string | undefined);\n const errorMessage = typeof taskState?.error === 'string'\n ? taskState.error\n : typeof (model.card_data as Record<string, unknown> | undefined)?.['error'] === 'string'\n ? (model.card_data as Record<string, unknown>)['error'] as string\n : null;\n return {\n name: cardDef.id,\n status: taskStatus,\n ...(errorMessage ? { error: { message: errorMessage, code: 'TASK_FAILED', at: taskState?.failedAt ?? null, source: 'browser-runtime' } } : {}),\n requires: Array.isArray((cardDef as { requires?: unknown }).requires) ? (cardDef as { requires: string[] }).requires : [],\n requires_satisfied: [] as string[],\n requires_missing: [] as string[],\n provides_declared: Array.isArray((cardDef as { provides?: Array<{ bindTo: string }> }).provides)\n ? (cardDef as { provides: Array<{ bindTo: string }> }).provides.map((e) => e.bindTo)\n : [cardDef.id],\n provides_runtime: Object.keys(taskState?.data?.provides_data ?? {}).sort(),\n blocked_by: [] as string[],\n unblocks: [] as string[],\n runtime: {\n attempt_count: taskState?.executionCount ?? 0,\n restart_count: taskState?.retryCount ?? 0,\n in_progress_since: taskStatus === 'in-progress' ? (taskState?.startedAt ?? null) : null,\n last_transition_at: taskState?.lastUpdated ?? (model.card_data as Record<string, unknown> | undefined)?.['lastRun'] as string ?? null,\n last_completed_at: taskState?.completedAt ?? null,\n last_restarted_at: taskState?.startedAt ?? null,\n status_age_ms: null as null,\n },\n };\n });\n\n return {\n cardDefinitions: structuredClone(safeCardDefs) as LiveCard[],\n cardRuntimeById,\n dataObjectsByToken,\n statusSnapshot: {\n schema_version: 'v1',\n meta: { board: { path: boardPath ?? 'browser-runtime' } },\n summary: {\n card_count: statusCards.length,\n completed: statusCards.filter((c) => c.status === 'completed').length,\n eligible: 0,\n pending: statusCards.filter((c) => c.status === 'pending').length,\n blocked: 0,\n unresolved: 0,\n failed: statusCards.filter((c) => c.status === 'failed').length,\n in_progress: statusCards.filter((c) => c.status === 'in-progress').length,\n orphan_cards: 0,\n topology: { edge_count: 0, max_fan_out_card: null, max_fan_out: 0 },\n },\n cards: statusCards,\n } as BoardRuntimeArtifactsPayload['statusSnapshot'],\n };\n}\n","/**\n * board-state-reducer — shared reactive state helpers for browser board shells.\n *\n * Used by both:\n * - board-livecards-localstorage-runtime (in-browser full engine)\n * - board-livecards-server-runtime-client (SSE/HTTP thin client)\n *\n * Pure functions; no side effects; no DOM/localStorage/fetch dependencies.\n */\n\n// ============================================================================\n// Types\n// ============================================================================\n\nexport interface CardModel {\n id: string;\n card: unknown;\n card_data: unknown;\n requires: unknown;\n computed_values: unknown;\n runtime_state: unknown;\n}\n\nexport interface BoardState {\n payload: unknown;\n cardIds: string[];\n modelsById: Record<string, CardModel>;\n}\n\nexport type SelectLiveCardModelFn = (payload: unknown, cardId: string) => CardModel;\n\n// ============================================================================\n// Helpers\n// ============================================================================\n\nfunction clone<T>(x: T): T {\n return JSON.parse(JSON.stringify(x)) as T;\n}\n\nfunction stableEq<T>(prev: T, next: T): T {\n if (prev === next) return prev;\n try {\n if (JSON.stringify(prev) === JSON.stringify(next)) return prev;\n } catch (_) { /* ignore */ }\n return next;\n}\n\nfunction deepEqJson(a: unknown, b: unknown): boolean {\n if (a === b) return true;\n try { return JSON.stringify(a) === JSON.stringify(b); } catch (_) { return false; }\n}\n\nfunction taskStatusToCardStatus(taskStatus: string | null | undefined): string {\n if (taskStatus === 'running' || taskStatus === 'in-progress') return 'loading';\n if (taskStatus === 'failed') return 'error';\n return 'fresh';\n}\n\n// ============================================================================\n// buildBoardState — full rebuild from a runtime payload snapshot\n// ============================================================================\n\nexport function buildBoardState(\n payload: unknown,\n prevState: BoardState | null,\n selectLiveCardModel: SelectLiveCardModelFn,\n): BoardState {\n const p = payload as { cardDefinitions?: Array<{ id: string }> } | null;\n const cardDefs = (p && Array.isArray(p.cardDefinitions)) ? p.cardDefinitions : [];\n const cardIds = cardDefs.map((c) => c.id);\n const prevModels = (prevState && prevState.modelsById) || {};\n const modelsById: Record<string, CardModel> = {};\n\n for (const id of cardIds) {\n const fresh = selectLiveCardModel(payload, id);\n const prev = prevModels[id];\n if (!prev) {\n modelsById[id] = fresh;\n continue;\n }\n const stab: CardModel = {\n id: fresh.id,\n card: stableEq(prev.card, fresh.card),\n card_data: stableEq(prev.card_data, fresh.card_data),\n requires: stableEq(prev.requires, fresh.requires),\n computed_values: stableEq(prev.computed_values, fresh.computed_values),\n runtime_state: stableEq(prev.runtime_state, fresh.runtime_state),\n };\n modelsById[id] = (\n stab.card === prev.card &&\n stab.card_data === prev.card_data &&\n stab.requires === prev.requires &&\n stab.computed_values === prev.computed_values &&\n stab.runtime_state === prev.runtime_state\n ) ? prev : stab;\n }\n\n return { payload, cardIds, modelsById };\n}\n\n// ============================================================================\n// applyNotification — incremental state reducer\n// ============================================================================\n\nexport function applyNotification(\n prevState: BoardState,\n notifications: Array<{ kind: string; [key: string]: unknown }>,\n selectLiveCardModel: SelectLiveCardModelFn,\n getFullPayload: () => unknown,\n): BoardState {\n if (!prevState || !Array.isArray(notifications) || notifications.length === 0) return prevState;\n\n let modelsById = prevState.modelsById;\n let cardIds = prevState.cardIds;\n let cloned = false;\n let changed = false;\n\n // Build token → [cardId, ...] map from current requires keys\n const consumersByToken: Record<string, string[]> = {};\n for (const cid of cardIds) {\n const m = modelsById[cid];\n const reqs = m && m.requires;\n if (reqs && typeof reqs === 'object') {\n for (const t of Object.keys(reqs as object)) {\n (consumersByToken[t] = consumersByToken[t] || []).push(cid);\n }\n }\n }\n\n function ensureClone() {\n if (!cloned) { modelsById = { ...modelsById }; cloned = true; }\n }\n\n for (const note of notifications) {\n if (!note || !note.kind) continue;\n\n if (note.kind === 'computed_values') {\n const cardId = note.cardId as string;\n const prev = modelsById[cardId];\n if (!prev) continue;\n const nextValues = (note.values || {}) as unknown;\n if (deepEqJson(prev.computed_values, nextValues)) continue;\n ensureClone();\n modelsById[cardId] = { ...prev, computed_values: nextValues };\n changed = true;\n\n } else if (note.kind === 'data_object') {\n const key = note.key as string;\n const notePayload = note.payload;\n const consumers = consumersByToken[key] || [];\n for (const cid of consumers) {\n const prevC = modelsById[cid];\n if (!prevC) continue;\n const prevReqs = (prevC.requires || {}) as Record<string, unknown>;\n if (deepEqJson(prevReqs[key], notePayload)) continue;\n ensureClone();\n modelsById[cid] = { ...prevC, requires: { ...prevReqs, [key]: notePayload } };\n changed = true;\n }\n\n } else if (note.kind === 'card_refreshed') {\n const cardId = note.cardId as string;\n let fresh: CardModel | null = null;\n try {\n const fp = getFullPayload();\n if (fp) fresh = selectLiveCardModel(fp, cardId);\n } catch (_) { /* ignore */ }\n if (!fresh) continue;\n const existing = modelsById[cardId];\n if (existing &&\n deepEqJson(existing.card, fresh.card) &&\n deepEqJson(existing.card_data, fresh.card_data) &&\n deepEqJson(existing.requires, fresh.requires) &&\n deepEqJson(existing.computed_values, fresh.computed_values) &&\n deepEqJson(existing.runtime_state, fresh.runtime_state)) {\n continue;\n }\n ensureClone();\n modelsById[cardId] = fresh;\n if (!cardIds.includes(cardId)) cardIds = [...cardIds, cardId];\n changed = true;\n\n } else if (note.kind === 'status') {\n const statusCards = (note.status as { cards?: Array<{\n name?: string;\n status?: string;\n runtime?: { last_transition_at?: string | null };\n error?: { message?: string } | null;\n blocked_by?: string[];\n requires_missing?: string[];\n }> })?.cards ?? [];\n\n for (const statusCard of statusCards) {\n const sid = statusCard?.name;\n if (!sid || !modelsById[sid]) continue;\n const prevS = modelsById[sid];\n const nextCardStatus = taskStatusToCardStatus(statusCard.status);\n const nextCardData = {\n ...(prevS.card_data as object || {}),\n status: nextCardStatus,\n lastRun: statusCard.runtime?.last_transition_at ?? null,\n ...(statusCard.error?.message ? { error: statusCard.error.message } : {}),\n };\n // Remove error key if no error\n if (!statusCard.error?.message) {\n delete (nextCardData as { error?: string }).error;\n }\n const nextRuntimeState = {\n task_status: statusCard.status ?? null,\n card_status: nextCardStatus,\n runtime: statusCard.runtime ? clone(statusCard.runtime) : {},\n error: statusCard.error ? clone(statusCard.error) : null,\n blocked_by: Array.isArray(statusCard.blocked_by) ? clone(statusCard.blocked_by) : [],\n requires_missing: Array.isArray(statusCard.requires_missing) ? clone(statusCard.requires_missing) : [],\n };\n if (deepEqJson(prevS.card_data, nextCardData) && deepEqJson(prevS.runtime_state, nextRuntimeState)) continue;\n ensureClone();\n modelsById[sid] = { ...prevS, card_data: nextCardData, runtime_state: nextRuntimeState };\n changed = true;\n }\n }\n }\n\n if (!changed) return prevState;\n return { payload: prevState.payload, cardIds, modelsById };\n}\n","/**\n * board-livecards-client — browser IIFE bundle.\n *\n * Two layers in one bundle:\n * 1. Platform-free state: buildBoardState, applyNotification, selectLiveCardModel,\n * selectAllLiveCardModels — usable with any transport (Firebase, WebSocket, SSE, etc.)\n * 2. SSE/HTTP transport: createBoardRuntimeClient — for yaml-flow server runtime.\n *\n * Usage (SSE/HTTP mode):\n * <script src=\"board-livecards-client.js\"></script>\n * <script>\n * const client = BoardLiveCardsClient.createBoardRuntimeClient({\n * fetchServer, boardPaths: BoardLiveCardsClient.defaultBoardPaths, getServerOrigin,\n * });\n * await client.bootstrapBoard({ boardId: 'default', rootElement: el });\n * </script>\n *\n * Usage (custom transport — e.g. Firebase):\n * <script src=\"board-livecards-client.js\"></script>\n * <script>\n * const { buildBoardState, applyNotification, selectLiveCardModel } = BoardLiveCardsClient;\n * // apply your own transport; drive UI state with these primitives.\n * </script>\n *\n * Global: window.BoardLiveCardsClient\n */\n\nimport { selectLiveCardModel, selectAllLiveCardModels } from '../board-livegraph-runtime/index.js';\nimport { buildBoardState, applyNotification, type BoardState, type CardModel } from '../cli/common/board-state-reducer.js';\n\n// ============================================================================\n// Platform-free state exports\n// Re-exported so consumers using any transport (Firebase, WS, SSE) can drive\n// the LiveCard UI without loading the full localstorage bundle.\n// ============================================================================\nexport { buildBoardState, applyNotification, selectLiveCardModel, selectAllLiveCardModels };\nexport type { BoardState, CardModel };\n\n// ============================================================================\n// Public types\n// ============================================================================\n\nexport interface BoardPaths {\n initBoard: string;\n stream: string;\n patchCard: (id: string) => string;\n cardAction: (id: string) => string;\n cardChats: (id: string) => string;\n cardFile: (id: string) => string;\n}\n\nexport interface BoardRuntimeClientOptions {\n /** Authenticated fetch wrapper (handles origin resolution, auth headers, etc). */\n fetchServer: (path: string, init?: RequestInit) => Promise<Response>;\n /** Returns the canonical BoardPaths for a given boardId. */\n boardPaths: (boardId: string) => BoardPaths;\n /** Returns the resolved server origin (e.g. 'http://localhost:7799'). Used for SSE URL. */\n getServerOrigin: () => string | null;\n /** Initial board render mode. Defaults to 'board'. */\n initialMode?: string;\n /** Canvas dimensions. Defaults to { height: '72vh', overflow: 'auto' }. */\n canvas?: { height?: string; overflow?: string };\n}\n\nexport interface BootstrapBoardParams {\n boardId?: string;\n /** Optional path passed to init-board for server-side executor resolution. */\n taskExecutorPath?: string;\n mode?: string;\n rootElement: HTMLElement;\n}\n\n/**\n * Build the standard BoardPaths for a yaml-flow server runtime board.\n *\n * Covers only the paths owned by the server runtime (SSE, patch, action, files, chats,\n * init-board). Demo-server-specific endpoints (demo-setup, board registry\n * CRUD) are not included — add those in the consumer if needed.\n *\n * @example\n * const client = createBoardRuntimeClient({\n * fetchServer,\n * boardPaths: defaultBoardPaths,\n * getServerOrigin: () => activeOrigin,\n * });\n */\nexport function defaultBoardPaths(boardId: string): BoardPaths {\n const b = encodeURIComponent(boardId || 'default');\n const base = `/api/boards/${b}`;\n return {\n initBoard: `${base}/init-board`,\n stream: `${base}/sse`,\n patchCard: (id: string) => `${base}/cards/${encodeURIComponent(id)}`,\n cardAction: (id: string) => `${base}/cards/${encodeURIComponent(id)}/actions`,\n cardFile: (id: string) => `${base}/cards/${encodeURIComponent(id)}/files`,\n cardChats: (id: string) => `${base}/cards/${encodeURIComponent(id)}/chats`,\n };\n}\n\nexport interface BoardRuntimeClient {\n /** Bootstrap the board: init-board → bootstrap-cards → LiveCard.Board + SSE. */\n bootstrapBoard(params: BootstrapBoardParams): Promise<unknown>;\n /** Tear down SSE and release references. */\n dispose(): void;\n setMode(mode: string): void;\n autoLayout(): void;\n setDevMode(enabled: boolean): void;\n getCurrentMode(): string;\n}\n\n// ============================================================================\n// createBoardRuntimeClient\n// ============================================================================\n\nexport function createBoardRuntimeClient(options: BoardRuntimeClientOptions): BoardRuntimeClient {\n if (!options || typeof options !== 'object') throw new Error('options are required');\n\n const { fetchServer, boardPaths, getServerOrigin } = options;\n if (typeof fetchServer !== 'function') throw new Error('options.fetchServer is required');\n if (typeof boardPaths !== 'function') throw new Error('options.boardPaths is required');\n if (typeof getServerOrigin !== 'function') throw new Error('options.getServerOrigin is required');\n\n const canvas = (options.canvas && typeof options.canvas === 'object')\n ? options.canvas\n : { height: '72vh', overflow: 'auto' };\n\n // Reactive state — single source of truth\n const stateRef: { current: BoardState | null } = { current: null };\n let board: { setState: (fn: (prev: BoardState) => BoardState) => void; core?: unknown; engine?: unknown } | null = null;\n let sse: EventSource | null = null;\n let currentMode = String(options.initialMode || 'board');\n\n function getFullPayload() {\n return stateRef.current ? stateRef.current.payload : null;\n }\n\n // ── File upload helpers ───────────────────────────────────────────────────\n\n async function uploadCardFile(\n boardId: string,\n cardId: string,\n file: File,\n opts?: { inChat?: boolean },\n ): Promise<unknown | null> {\n if (!file) return null;\n const inChat = opts?.inChat === true;\n const fileName = typeof file.name === 'string' ? file.name : 'upload.bin';\n const contentType = file.type || 'application/octet-stream';\n const paths = boardPaths(boardId);\n const uploadPath = inChat\n ? `${paths.cardFile(cardId)}?inChat=true`\n : paths.cardFile(cardId);\n\n const upload = await fetchServer(uploadPath, {\n method: 'POST',\n headers: {\n 'content-type': contentType,\n 'x-file-name': encodeURIComponent(fileName),\n },\n body: file,\n });\n\n if (!upload.ok) {\n const errText = await upload.text();\n throw new Error(`Upload failed (${upload.status}): ${errText || 'unknown error'}`);\n }\n\n const payload = await upload.json() as { file?: unknown };\n return payload?.file ?? null;\n }\n\n async function uploadActionFiles(\n boardId: string,\n cardId: string,\n actionType: string,\n payload: Record<string, unknown> | null,\n ): Promise<Record<string, unknown>> {\n if (actionType !== 'chat-send' && actionType !== 'file-upload') return payload || {};\n const nextPayload: Record<string, unknown> = { ...(payload || {}) };\n const rawFiles = Array.isArray(nextPayload.files) ? nextPayload.files as File[] : [];\n if (!rawFiles.length) {\n nextPayload.files = [];\n return nextPayload;\n }\n\n const uploaded: unknown[] = [];\n for (const file of rawFiles) {\n const fileMeta = await uploadCardFile(boardId, cardId, file, { inChat: actionType === 'chat-send' });\n if (fileMeta) uploaded.push(fileMeta);\n }\n\n // For chat uploads, server-side file API already records metadata and emits system chat logs.\n nextPayload.files = actionType === 'chat-send' ? [] : uploaded;\n return nextPayload;\n }\n\n // ── bootstrapBoard ────────────────────────────────────────────────────────\n\n async function bootstrapBoard(params: BootstrapBoardParams): Promise<unknown> {\n const boardId = String(params?.boardId || 'default');\n const taskExecutorPath = typeof params?.taskExecutorPath === 'string' ? params.taskExecutorPath.trim() : '';\n const mode = String(params?.mode || currentMode || 'board');\n const rootEl = params?.rootElement;\n if (!rootEl) throw new Error('bootstrapBoard requires params.rootElement');\n\n const paths = boardPaths(boardId);\n\n const initBoardPath = taskExecutorPath\n ? `${paths.initBoard}?taskExecutorPath=${encodeURIComponent(taskExecutorPath)}`\n : paths.initBoard;\n const initBoardRes = await fetchServer(initBoardPath);\n if (!initBoardRes.ok) throw new Error(`Server init-board failed (${initBoardRes.status}).`);\n\n const origin = getServerOrigin();\n if (!origin) throw new Error('Server origin not resolved before SSE start');\n\n // Open SSE first and wait for the initial full-payload frame.\n // The /sse endpoint calls bootstrapBoard() server-side, publishes the\n // persisted state snapshot via the notification channel, then sends the\n // full runtime payload as the first SSE frame.\n const initialPayload = await new Promise<unknown>((resolve, reject) => {\n const sseConn = new EventSource(`${origin}${paths.stream}`);\n sse = sseConn;\n let gotInitialPayload = false;\n const timeout = setTimeout(() => {\n if (!gotInitialPayload) reject(new Error('SSE initial payload timeout (15s)'));\n }, 15_000);\n sseConn.onmessage = (evt) => {\n try {\n const update = JSON.parse(evt.data || '{}');\n if (!gotInitialPayload && (update?.cardDefinitions || selectAllLiveCardModels(update))) {\n gotInitialPayload = true;\n clearTimeout(timeout);\n resolve(update);\n }\n } catch { /* wait for valid frame */ }\n };\n sseConn.onerror = () => {\n if (!gotInitialPayload) {\n clearTimeout(timeout);\n reject(new Error('SSE connection failed during bootstrap'));\n }\n };\n });\n\n if (!selectAllLiveCardModels(initialPayload)) throw new Error('SSE payload missing published runtime artifacts');\n\n // Build initial reactive state using bundled selectLiveCardModel\n stateRef.current = buildBoardState(initialPayload, null, selectLiveCardModel as Parameters<typeof buildBoardState>[2]);\n\n const LiveCard = (globalThis as unknown as { LiveCard?: { init: (opts: unknown) => unknown; Board: (engine: unknown, el: HTMLElement, opts: unknown) => typeof board } }).LiveCard;\n if (!LiveCard) throw new Error('LiveCard global not loaded — include live-cards.js before this script');\n\n const engine = LiveCard.init({\n resolve: (id: string) => stateRef.current?.modelsById[id],\n chartLib: (globalThis as { Chart?: unknown }).Chart ?? null,\n markdown: (globalThis as { marked?: { parse: (t: string) => string } }).marked\n ? (text: string) => (globalThis as { marked: { parse: (t: string) => string } }).marked.parse(text)\n : null,\n sanitize: (globalThis as { DOMPurify?: { sanitize: (h: string) => string } }).DOMPurify\n ? (html: string) => (globalThis as { DOMPurify: { sanitize: (h: string) => string } }).DOMPurify.sanitize(html)\n : null,\n onPatchState: async (id: string, patch: Record<string, unknown>) => {\n await fetchServer(paths.patchCard(id), {\n method: 'PATCH',\n headers: { 'content-type': 'application/json' },\n body: JSON.stringify(patch || {}),\n });\n },\n onRefresh: async (id: string) => {\n await fetchServer(paths.patchCard(id), {\n method: 'PATCH',\n headers: { 'content-type': 'application/json' },\n body: JSON.stringify({}),\n });\n },\n onAction: async (id: string, actionType: string, actionPayload: Record<string, unknown> | null) => {\n const uploadedPayload = await uploadActionFiles(boardId, id, actionType, actionPayload);\n await fetchServer(paths.cardAction(id), {\n method: 'POST',\n headers: { 'content-type': 'application/json' },\n body: JSON.stringify({ actionType, payload: uploadedPayload || {} }),\n });\n },\n getChatMessages: async (id: string) => {\n const res = await fetchServer(paths.cardChats(id));\n if (!res.ok) return [];\n const chatPayload = await res.json() as { messages?: Array<{ role?: string; text?: string }> };\n return (chatPayload?.messages ?? []).map((m) => ({\n role: typeof m?.role === 'string' ? m.role : 'system',\n text: typeof m?.text === 'string' ? m.text : '',\n files: [],\n }));\n },\n });\n\n rootEl.innerHTML = '';\n board = LiveCard.Board(engine, rootEl, {\n initialState: stateRef.current,\n getNodeIds: (s: BoardState) => s.cardIds,\n selectNode: (s: BoardState, id: string) => s.modelsById[id],\n mode,\n canvas,\n });\n currentMode = mode;\n\n // Wire up the ongoing SSE message handler on the already-open connection.\n sse!.onmessage = (evt) => {\n try {\n const update = JSON.parse(evt.data || '{}') as {\n kind?: string;\n notifications?: Array<{ kind: string; [k: string]: unknown }>;\n cardDefinitions?: unknown[];\n engine?: { onServerSseEvent?: () => void; refreshOpenChatModal?: () => void };\n };\n\n if (update?.kind === 'notification-batch' && Array.isArray(update.notifications)) {\n if (board) {\n board.setState((prev: BoardState) => {\n const next = applyNotification(\n prev,\n update.notifications!,\n selectLiveCardModel as Parameters<typeof applyNotification>[2],\n getFullPayload,\n );\n stateRef.current = next;\n return next;\n });\n }\n } else if (update?.cardDefinitions) {\n const next = buildBoardState(update, stateRef.current, selectLiveCardModel as Parameters<typeof buildBoardState>[2]);\n stateRef.current = next;\n if (board) board.setState(() => next);\n }\n\n const eng = board && (board as { engine?: { onServerSseEvent?: () => void; refreshOpenChatModal?: () => void } }).engine;\n if (eng && typeof eng.onServerSseEvent === 'function') {\n eng.onServerSseEvent();\n } else if (eng && typeof eng.refreshOpenChatModal === 'function') {\n eng.refreshOpenChatModal();\n }\n } catch (err) {\n console.warn('Bad SSE payload', err);\n }\n };\n\n return board;\n }\n\n // ── Control methods ───────────────────────────────────────────────────────\n\n function dispose() {\n if (sse) { sse.close(); sse = null; }\n board = null;\n stateRef.current = null;\n }\n\n function setMode(mode: string) {\n currentMode = String(mode || 'board');\n const core = board && (board as { core?: { setMode?: (m: string) => void } }).core;\n if (core && typeof core.setMode === 'function') core.setMode(currentMode);\n }\n\n function autoLayout() {\n if (!board) return;\n currentMode = 'canvas';\n const core = (board as { core?: { setMode?: (m: string) => void; autoLayout?: () => void } }).core;\n if (core && typeof core.setMode === 'function') core.setMode('canvas');\n if (core && typeof core.autoLayout === 'function') core.autoLayout();\n }\n\n function setDevMode(enabled: boolean) {\n const core = board && (board as { core?: { setDevMode?: (e: boolean) => void } }).core;\n if (core && typeof core.setDevMode === 'function') core.setDevMode(Boolean(enabled));\n }\n\n function getCurrentMode() { return currentMode; }\n\n return { bootstrapBoard, dispose, setMode, autoLayout, setDevMode, getCurrentMode };\n}\n"]}
|
|
1
|
+
{"version":3,"sources":["../src/board-livegraph-runtime/index.ts","../src/cli/common/board-state-reducer.ts","../src/board-livecards-client/index.ts"],"names":["taskStatusToCardStatus","taskStatus","normalizeCardRuntimeArtifact","cardId","artifact","safe","selectLiveCardModel","payload","cardDefinition","c","statusSnapshot","cardRuntimeById","dataObjectsByToken","statusCard","card","runtimeArtifact","card_data","runtime_state","requiresTokens","requires","token","value","selectAllLiveCardModels","clone","x","stableEq","prev","next","deepEqJson","a","b","buildBoardState","prevState","p","cardIds","prevModels","modelsById","id","fresh","stab","applyNotification","notifications","getFullPayload","cloned","changed","consumersByToken","cid","m","reqs","t","ensureClone","note","nextValues","key","notePayload","consumers","prevC","prevReqs","existing","noteCard","cardObj","nextCardData","nextRequires","nextComputedValues","nextRuntimeState","fp","statusCards","sid","prevS","nextCardStatus","defaultBoardPaths","boardId","base","createBoardRuntimeClient","options","fetchServer","boardPaths","getServerOrigin","canvas","stateRef","board","sse","currentMode","uploadCardFile","file","opts","inChat","fileName","contentType","paths","uploadPath","upload","errText","uploadActionFiles","actionType","nextPayload","rawFiles","uploaded","fileMeta","bootstrapBoard","params","taskExecutorPath","mode","rootEl","initBoardPath","initBoardRes","origin","initialPayload","resolve","reject","sseConn","gotInitialPayload","timeout","evt","update","LiveCard","engine","text","html","patch","actionPayload","uploadedPayload","res","s","eng","err","dispose","setMode","core","autoLayout","setDevMode","enabled","getCurrentMode"],"mappings":"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","file":"board-livecards-client.js","sourcesContent":["import type { GraphConfig, GraphEvent, TaskConfig } from '../event-graph/types.js';\nimport { CardCompute } from '../card-compute/index.js';\nimport type { ComputeNode } from '../card-compute/index.js';\nimport {\n createReactiveGraph,\n type ReactiveGraph,\n type ReactiveGraphOptions,\n type TaskHandlerFn,\n type TaskHandlerInput,\n type TaskHandlerReturn,\n type LiveGraph,\n schedule,\n} from '../continuous-event-graph/index.js';\nimport type { LiveCard, LiveBoard } from '../continuous-event-graph/live-cards-bridge.js';\n\nexport interface BrowserSourceAdapterContext {\n card: LiveCard;\n input: TaskHandlerInput;\n}\n\nexport type BrowserSourceAdapter =\n (ctx: BrowserSourceAdapterContext) => Promise<Record<string, unknown>> | Record<string, unknown>;\n\nexport interface BoardTaskExecutorContext {\n card: LiveCard;\n input: TaskHandlerInput;\n}\n\n/**\n * Opaque task executor hook.\n * Runtime does not interpret source descriptors — executor owns that contract.\n * For source cards, return a map keyed by source.bindTo.\n */\nexport type BoardTaskExecutor =\n (ctx: BoardTaskExecutorContext) => Promise<Record<string, unknown> | undefined> | Record<string, unknown> | undefined;\n\nexport interface BoardLiveGraphRuntimeOptions {\n /** Preferred opaque source/task executor. */\n taskExecutor?: BoardTaskExecutor;\n /** Per-card source adapters keyed by card ID. */\n sourceAdapters?: Record<string, BrowserSourceAdapter>;\n /** Default source adapter applied when no per-card adapter matches. */\n defaultSourceAdapter?: BrowserSourceAdapter;\n reactiveOptions?: Partial<Omit<ReactiveGraphOptions, 'handlers'>>;\n graphSettings?: Partial<GraphConfig['settings']>;\n executionId?: string;\n}\n\nexport interface LiveCardRuntimeModel {\n id: string;\n card: LiveCard;\n card_data: Record<string, unknown>;\n requires: Record<string, unknown>;\n computed_values: Record<string, unknown>;\n runtime_state: Record<string, unknown>;\n}\n\nexport interface BoardRuntimeView {\n id?: string;\n title?: string;\n mode?: 'board' | 'canvas';\n positions?: Record<string, { x?: number; y?: number; w?: number; h?: number }>;\n settings?: Partial<GraphConfig['settings']>;\n nodes: LiveCardRuntimeModel[];\n}\n\nexport interface BoardLiveGraphRuntimeUpdate {\n events: GraphEvent[];\n graph: LiveGraph;\n nodes: LiveCardRuntimeModel[];\n}\n\nexport interface BoardLiveGraphRuntime {\n getGraph(): ReactiveGraph;\n getState(): LiveGraph;\n getNodes(): LiveCardRuntimeModel[];\n getBoard(): BoardRuntimeView;\n getSchedule(): ReturnType<typeof schedule>;\n subscribe(listener: (update: BoardLiveGraphRuntimeUpdate) => void): () => void;\n addCard(card: LiveCard): void;\n upsertCard(card: LiveCard): void;\n removeCard(cardId: string): void;\n patchCardState(cardId: string, patch: Record<string, unknown>): void;\n retrigger(cardId: string): void;\n retriggerAll(): void;\n push(event: GraphEvent): void;\n pushAll(events: GraphEvent[]): void;\n dispose(): void;\n}\n\nfunction deepClone<T>(value: T): T {\n return JSON.parse(JSON.stringify(value)) as T;\n}\n\nfunction toTaskConfig(card: LiveCard): TaskConfig {\n const provides = (card.provides && card.provides.length > 0)\n ? card.provides.map(p => p.bindTo)\n : [card.id];\n\n return {\n requires: card.requires && card.requires.length > 0 ? [...card.requires] : undefined,\n provides,\n taskHandlers: [card.id],\n description: card.meta?.title ?? card.id,\n };\n}\n\nfunction buildTokenProviders(cards: Map<string, LiveCard>): Map<string, string> {\n const tokenToCardId = new Map<string, string>();\n for (const [cardId, card] of cards.entries()) {\n const bindings = card.provides && card.provides.length > 0\n ? card.provides\n : [{ bindTo: cardId, ref: 'card_data' }];\n for (const binding of bindings) tokenToCardId.set(binding.bindTo, cardId);\n }\n return tokenToCardId;\n}\n\nfunction validateRequires(cards: Map<string, LiveCard>, changedCardId: string): void {\n const tokenProviders = buildTokenProviders(cards);\n const card = cards.get(changedCardId);\n if (!card) return;\n\n for (const req of card.requires ?? []) {\n if (!tokenProviders.has(req)) {\n throw new Error(`Card \"${changedCardId}\" requires token \"${req}\" but no card provides it`);\n }\n }\n}\n\n/**\n * LocalStorageService — browser-side persistence layer for card artifacts\n * Mirrors CLI's file-based persistence (cards, computed artifacts, status)\n * \n * Keys:\n * - 'yf:cards:<id>' → card definitions (mirrors tmp/cards/<id>.json)\n * - 'yf:runtime-out:cards:<id>' → computed artifacts (mirrors runtime-out/cards/<id>.computed.json)\n * - 'yf:runtime-out:status' → board status snapshot (mirrors runtime-out/board-livegraph-status.json)\n */\nexport const LocalStorageService = {\n // Keys\n CARD_PREFIX: 'yf:cards:',\n RUNTIME_OUT_PREFIX: 'yf:runtime-out:cards:',\n STATUS_KEY: 'yf:runtime-out:status',\n\n // Read/write cards (mirrors tmp/cards/<id>.json)\n writeCard(cardId: string, cardObject: Record<string, unknown>): void {\n try {\n localStorage.setItem(this.CARD_PREFIX + cardId, JSON.stringify(cardObject));\n } catch (e) {\n console.warn(`Failed to write card ${cardId} to localStorage:`, e);\n }\n },\n readCard(cardId: string): Record<string, unknown> | null {\n try {\n const raw = localStorage.getItem(this.CARD_PREFIX + cardId);\n return raw ? JSON.parse(raw) : null;\n } catch (e) {\n console.warn(`Failed to read card ${cardId} from localStorage:`, e);\n return null;\n }\n },\n readAllCards(cardIds: string[]): Record<string, Record<string, unknown>> {\n const result: Record<string, Record<string, unknown>> = {};\n for (const id of cardIds) {\n const card = this.readCard(id);\n if (card) result[id] = card;\n }\n return result;\n },\n\n // Read/write computed artifacts (mirrors runtime-out/cards/<id>.computed.json)\n writeComputedArtifact(artifact: Record<string, unknown>): void {\n if (!artifact || !artifact.card_id) return;\n try {\n localStorage.setItem(\n this.RUNTIME_OUT_PREFIX + String(artifact.card_id),\n JSON.stringify(artifact)\n );\n } catch (e) {\n console.warn(`Failed to write computed artifact ${artifact.card_id}:`, e);\n }\n },\n readComputedArtifact(cardId: string): Record<string, unknown> | null {\n try {\n const raw = localStorage.getItem(this.RUNTIME_OUT_PREFIX + cardId);\n return raw ? JSON.parse(raw) : null;\n } catch (e) {\n console.warn(`Failed to read computed artifact ${cardId}:`, e);\n return null;\n }\n },\n readAllComputedArtifacts(cardIds: string[]): Record<string, Record<string, unknown>> {\n const result: Record<string, Record<string, unknown>> = {};\n for (const id of cardIds) {\n const artifact = this.readComputedArtifact(id);\n if (artifact) result[id] = artifact;\n }\n return result;\n },\n\n // Read/write board status snapshot (mirrors runtime-out/board-livegraph-status.json)\n writeStatusSnapshot(snapshot: Record<string, unknown>): void {\n try {\n localStorage.setItem(this.STATUS_KEY, JSON.stringify(snapshot));\n } catch (e) {\n console.warn('Failed to write status snapshot to localStorage:', e);\n }\n },\n readStatusSnapshot(): Record<string, unknown> | null {\n try {\n const raw = localStorage.getItem(this.STATUS_KEY);\n return raw ? JSON.parse(raw) : null;\n } catch (e) {\n console.warn('Failed to read status snapshot from localStorage:', e);\n return null;\n }\n },\n\n // Clear all (useful for reset/demo)\n clear(): void {\n const keysToDelete: string[] = [];\n for (let i = 0; i < localStorage.length; i++) {\n const key = localStorage.key(i);\n if (key && (key.startsWith(this.CARD_PREFIX) || key.startsWith(this.RUNTIME_OUT_PREFIX) || key === this.STATUS_KEY)) {\n keysToDelete.push(key);\n }\n }\n for (const key of keysToDelete) {\n localStorage.removeItem(key);\n }\n }\n};\n\nexport function createBoardLiveGraphRuntime(\n input: LiveCard[] | LiveBoard,\n options: BoardLiveGraphRuntimeOptions = {},\n): BoardLiveGraphRuntime {\n const boardMeta: Pick<LiveBoard, 'id' | 'title' | 'mode' | 'positions' | 'settings'> = Array.isArray(input)\n ? {}\n : {\n id: input.id,\n title: input.title,\n mode: input.mode,\n positions: input.positions,\n settings: input.settings,\n };\n\n const initialCards = Array.isArray(input) ? input : input.nodes;\n const cards = new Map<string, LiveCard>();\n for (const card of initialCards) {\n if (cards.has(card.id)) throw new Error(`Duplicate card ID: \"${card.id}\"`);\n cards.set(card.id, deepClone(card));\n }\n\n const listeners = new Set<(update: BoardLiveGraphRuntimeUpdate) => void>();\n const taskExecutor = options.taskExecutor;\n const sourceAdapters = options.sourceAdapters ?? {};\n const defaultSourceAdapter = options.defaultSourceAdapter;\n\n let graphRef: ReactiveGraph | null = null;\n\n const notifyListeners = (events: GraphEvent[], graph: LiveGraph): void => {\n const update: BoardLiveGraphRuntimeUpdate = {\n events,\n graph,\n nodes: getRenderableNodes(),\n };\n for (const listener of listeners) listener(update);\n };\n\n const makeHandler = (cardId: string): TaskHandlerFn => {\n return async (inputArgs: TaskHandlerInput): Promise<TaskHandlerReturn> => {\n const card = cards.get(cardId);\n if (!card) return 'task-initiate-failure';\n\n const requiresData: Record<string, unknown> = {};\n for (const token of card.requires ?? []) {\n const upstream = inputArgs.state[token] as Record<string, unknown> | undefined;\n if (!upstream || typeof upstream !== 'object') continue;\n const providesData = upstream.provides_data as Record<string, unknown> | undefined;\n if (!providesData || typeof providesData !== 'object') continue;\n if (!Object.prototype.hasOwnProperty.call(providesData, token)) continue;\n requiresData[token] = providesData[token];\n }\n\n const sourcesData: Record<string, unknown> = {};\n if (card.source_defs && card.source_defs.length > 0) {\n const adapter = sourceAdapters[cardId] ?? defaultSourceAdapter;\n const fetched = taskExecutor\n ? await taskExecutor({ card, input: inputArgs })\n : (adapter ? await adapter({ card, input: inputArgs }) : undefined);\n if (fetched && typeof fetched === 'object') {\n for (const src of card.source_defs) {\n if (Object.prototype.hasOwnProperty.call(fetched, src.bindTo)) {\n sourcesData[src.bindTo] = fetched[src.bindTo];\n } else if (card.source_defs.length === 1) {\n sourcesData[src.bindTo] = fetched;\n }\n }\n }\n }\n\n const computeNode: ComputeNode = {\n id: card.id,\n card_data: deepClone(card.card_data ?? {}),\n requires: requiresData,\n source_defs: card.source_defs,\n compute: card.compute as ComputeNode['compute'] | undefined,\n };\n computeNode._sourcesData = sourcesData;\n\n if (computeNode.compute && computeNode.compute.length > 0) {\n await CardCompute.run(computeNode, { sourcesData });\n }\n\n const providesData: Record<string, unknown> = {};\n if (card.provides && card.provides.length > 0) {\n for (const { bindTo, ref } of card.provides) {\n providesData[bindTo] = CardCompute.resolve(computeNode, ref);\n }\n } else {\n providesData[card.id] = {\n ...(computeNode.card_data ?? {}),\n ...(computeNode.computed_values ?? {}),\n ...(computeNode._sourcesData ?? {}),\n };\n }\n\n const resultData: Record<string, unknown> = {\n provides_data: providesData,\n card_data: computeNode.card_data ?? {},\n computed_values: computeNode.computed_values ?? {},\n fetched_sources: sourcesData,\n requires: requiresData,\n };\n\n graphRef?.resolveCallback(inputArgs.callbackToken, resultData);\n return 'task-initiated';\n };\n };\n\n const tasks: Record<string, TaskConfig> = {};\n const handlers: Record<string, TaskHandlerFn> = {};\n for (const [cardId, card] of cards.entries()) {\n validateRequires(cards, cardId);\n tasks[cardId] = toTaskConfig(card);\n handlers[cardId] = makeHandler(cardId);\n }\n\n const config: GraphConfig = {\n id: boardMeta.id ?? `browser-board-${Date.now()}`,\n settings: {\n completion: 'manual',\n execution_mode: 'eligibility-mode',\n ...(boardMeta.settings ?? {}),\n ...(options.graphSettings ?? {}),\n },\n tasks,\n };\n\n const userOnDrain = options.reactiveOptions?.onDrain;\n const graph = createReactiveGraph(\n config,\n {\n ...(options.reactiveOptions ?? {}),\n handlers,\n onDrain: (events, live, scheduleResult) => {\n userOnDrain?.(events, live, scheduleResult);\n notifyListeners(events, live);\n },\n },\n options.executionId,\n );\n graphRef = graph;\n\n function getRenderableNodes(): LiveCardRuntimeModel[] {\n const live = graph.getState();\n const out: LiveCardRuntimeModel[] = [];\n\n for (const [cardId, baseCard] of cards.entries()) {\n const data = live.state.tasks[cardId]?.data as Record<string, unknown> | undefined;\n const runtimeState = live.state.tasks[cardId];\n\n const mergedCardData = {\n ...(baseCard.card_data ?? {}),\n ...(data && typeof data.card_data === 'object' ? data.card_data as Record<string, unknown> : {}),\n };\n\n const cardStatus = runtimeState?.status === 'running' ? 'loading' : runtimeState?.status;\n const cardDataForView = {\n ...mergedCardData,\n ...(cardStatus ? { status: cardStatus } : {}),\n ...(runtimeState?.lastUpdated ? { lastRun: runtimeState.lastUpdated } : {}),\n ...(runtimeState?.status === 'failed' && runtimeState.error ? { error: runtimeState.error } : {}),\n };\n\n out.push({\n id: cardId,\n card: deepClone(baseCard),\n card_data: cardDataForView,\n requires: data && typeof data.requires === 'object' ? deepClone(data.requires as Record<string, unknown>) : {},\n computed_values: data && typeof data.computed_values === 'object' ? deepClone(data.computed_values as Record<string, unknown>) : {},\n runtime_state: runtimeState ? deepClone(runtimeState as unknown as Record<string, unknown>) : {},\n });\n }\n\n return out;\n }\n\n const runtime: BoardLiveGraphRuntime = {\n getGraph: () => graph,\n getState: () => graph.getState(),\n getSchedule: () => graph.getSchedule(),\n getNodes: () => getRenderableNodes(),\n getBoard: () => ({\n ...boardMeta,\n nodes: getRenderableNodes(),\n }),\n subscribe(listener: (update: BoardLiveGraphRuntimeUpdate) => void): () => void {\n listeners.add(listener);\n listener({ events: [], graph: graph.getState(), nodes: getRenderableNodes() });\n return () => listeners.delete(listener);\n },\n addCard(card: LiveCard): void {\n if (cards.has(card.id)) throw new Error(`Card \"${card.id}\" already exists`);\n cards.set(card.id, deepClone(card));\n validateRequires(cards, card.id);\n graph.registerHandler(card.id, makeHandler(card.id));\n graph.addNode(card.id, toTaskConfig(card));\n },\n upsertCard(card: LiveCard): void {\n cards.set(card.id, deepClone(card));\n validateRequires(cards, card.id);\n graph.registerHandler(card.id, makeHandler(card.id));\n graph.addNode(card.id, toTaskConfig(card));\n },\n removeCard(cardId: string): void {\n cards.delete(cardId);\n graph.unregisterHandler(cardId);\n graph.removeNode(cardId);\n },\n patchCardState(cardId: string, patch: Record<string, unknown>): void {\n const card = cards.get(cardId);\n if (!card) throw new Error(`Card \"${cardId}\" not found`);\n card.card_data = { ...(card.card_data ?? {}), ...patch };\n graph.retrigger(cardId);\n },\n retrigger(cardId: string): void {\n graph.retrigger(cardId);\n },\n retriggerAll(): void {\n graph.retriggerAll(Array.from(cards.keys()));\n },\n push(event: GraphEvent): void {\n graph.push(event);\n },\n pushAll(events: GraphEvent[]): void {\n graph.pushAll(events);\n },\n dispose(): void {\n listeners.clear();\n graph.dispose();\n },\n };\n\n return runtime;\n}\n\n// ---------------------------------------------------------------------------\n// Runtime-artifacts adapter (ported from reusable-runtime-artifacts-adapter.js)\n// ---------------------------------------------------------------------------\n\nexport interface CardRuntimeArtifact {\n schema_version?: string;\n card_id?: string;\n card_data?: Record<string, unknown>;\n computed_values?: Record<string, unknown>;\n}\n\nexport interface BoardRuntimeArtifactsPayload {\n cardDefinitions: LiveCard[];\n cardRuntimeById?: Record<string, CardRuntimeArtifact>;\n dataObjectsByToken?: Record<string, unknown>;\n statusSnapshot?: {\n cards?: Array<{\n name: string;\n status?: string;\n error?: { message?: string } | null;\n runtime?: { last_transition_at?: string | null };\n blocked_by?: string[];\n requires_missing?: string[];\n }>;\n };\n}\n\nfunction taskStatusToCardStatus(taskStatus: string | null | undefined): string {\n if (taskStatus === 'running' || taskStatus === 'in-progress') return 'loading';\n if (taskStatus === 'failed') return 'error';\n if (taskStatus === 'completed') return 'fresh';\n return 'fresh';\n}\n\nfunction cardStatusToTaskStatus(cardStatus: string | null | undefined): string {\n if (cardStatus === 'loading') return 'in-progress';\n if (cardStatus === 'error') return 'failed';\n if (cardStatus === 'stale') return 'pending';\n if (cardStatus === 'fresh') return 'completed';\n return 'pending';\n}\n\nfunction normalizeCardRuntimeArtifact(cardId: string, artifact: CardRuntimeArtifact | undefined): Required<CardRuntimeArtifact> {\n const safe = artifact && typeof artifact === 'object' && !Array.isArray(artifact) ? artifact : {};\n return {\n schema_version: (safe.schema_version as string) || 'v1',\n card_id: typeof safe.card_id === 'string' ? safe.card_id : cardId,\n card_data: safe.card_data && typeof safe.card_data === 'object' && !Array.isArray(safe.card_data)\n ? structuredClone(safe.card_data) : {},\n computed_values: safe.computed_values && typeof safe.computed_values === 'object' && !Array.isArray(safe.computed_values)\n ? structuredClone(safe.computed_values) : {},\n };\n}\n\n/**\n * Selects a single per-card render model from a runtime state payload.\n * Pure: same input → same output. Used by reactive Board to recompute\n * only the slice for one card.\n */\nexport function selectLiveCardModel(\n payload: BoardRuntimeArtifactsPayload,\n cardId: string,\n): LiveCardRuntimeModel {\n if (!payload || typeof payload !== 'object') throw new Error('payload must be an object');\n if (!cardId) throw new Error('cardId is required');\n\n const cardDefinitions = Array.isArray(payload.cardDefinitions) ? payload.cardDefinitions : [];\n const cardDefinition = cardDefinitions.find((c) => (c as { id?: string }).id === cardId);\n if (!cardDefinition) throw new Error(`cardDefinitions has no entry with id ${cardId}`);\n\n const statusSnapshot = payload.statusSnapshot && typeof payload.statusSnapshot === 'object' ? payload.statusSnapshot : {};\n const cardRuntimeById = payload.cardRuntimeById && typeof payload.cardRuntimeById === 'object' ? payload.cardRuntimeById : {};\n const dataObjectsByToken = payload.dataObjectsByToken && typeof payload.dataObjectsByToken === 'object' ? payload.dataObjectsByToken : {};\n const statusCards = Array.isArray((statusSnapshot as { cards?: unknown[] }).cards)\n ? (statusSnapshot as { cards: Array<{ name: string; status?: string; error?: { message?: string } | null; runtime?: { last_transition_at?: string | null }; blocked_by?: string[]; requires_missing?: string[] }> }).cards\n : [];\n const statusCard = statusCards.find((c) => c.name === cardId);\n\n const card = structuredClone(cardDefinition) as LiveCard & Record<string, unknown>;\n const runtimeArtifact = normalizeCardRuntimeArtifact(cardId, cardRuntimeById[cardId]);\n\n const baseCardData = card.card_data && typeof card.card_data === 'object' && !Array.isArray(card.card_data)\n ? card.card_data as Record<string, unknown> : {};\n\n const card_data: Record<string, unknown> = {\n ...baseCardData,\n ...(runtimeArtifact.card_data || {}),\n status: taskStatusToCardStatus(statusCard?.status),\n lastRun: (statusCard?.runtime?.last_transition_at) ?? null,\n };\n if (statusCard?.error?.message) card_data['error'] = statusCard.error.message;\n\n const runtime_state: Record<string, unknown> = statusCard\n ? {\n task_status: statusCard.status ?? null,\n card_status: taskStatusToCardStatus(statusCard.status),\n runtime: structuredClone(statusCard.runtime ?? {}),\n error: statusCard.error ? structuredClone(statusCard.error) : null,\n blocked_by: Array.isArray(statusCard.blocked_by) ? structuredClone(statusCard.blocked_by) : [],\n requires_missing: Array.isArray(statusCard.requires_missing) ? structuredClone(statusCard.requires_missing) : [],\n }\n : {\n task_status: null,\n card_status: card_data['status'] ?? 'fresh',\n runtime: { last_transition_at: card_data['lastRun'] ?? null },\n error: card_data['error'] ? { message: card_data['error'] } : null,\n blocked_by: [],\n requires_missing: [],\n };\n\n const requiresTokens = Array.isArray((card as { requires?: unknown }).requires) ? (card as { requires: string[] }).requires : [];\n // Include ALL data objects in the state, not just the statically declared requires tokens.\n // This handles dynamic requires, runtime token additions, and cards whose declared requires\n // may not reflect what data is currently available. The board's stable-ref diff handles\n // no-op cases where a card doesn't actually use a given token.\n const requires: Record<string, unknown> = {};\n for (const [token, value] of Object.entries(dataObjectsByToken as Record<string, unknown>)) {\n requires[token] = structuredClone(value);\n }\n // Also seed declared tokens not yet present in dataObjectsByToken as null,\n // so the applyNotification consumer map is always fully wired from init.\n for (const token of requiresTokens) {\n if (!Object.prototype.hasOwnProperty.call(requires, token)) {\n requires[token] = null;\n }\n }\n\n return {\n id: cardId,\n card: card as LiveCard,\n card_data,\n requires,\n computed_values: runtimeArtifact.computed_values,\n runtime_state,\n };\n}\n\n/**\n * Build per-card render models for every card in the payload.\n */\nexport function selectAllLiveCardModels(payload: BoardRuntimeArtifactsPayload): LiveCardRuntimeModel[] {\n if (!payload || typeof payload !== 'object') throw new Error('payload must be an object');\n const cardDefinitions = Array.isArray(payload.cardDefinitions) ? payload.cardDefinitions : [];\n return cardDefinitions.map((c) => selectLiveCardModel(payload, (c as { id: string }).id));\n}\n\nexport interface BuildBrowserArtifactsOptions {\n boardPath?: string;\n cardDefinitions: LiveCard[];\n runtimeModels: LiveCardRuntimeModel[];\n graphState: LiveGraph;\n}\n\n/**\n * Converts browser-runtime state (LiveCardRuntimeModel[] + LiveGraph) back into\n * the runtime payload shape consumed by selectLiveCardModel / selectAllLiveCardModels.\n * Used by the browser-only shell to keep the same selector path as the server shell.\n */\nexport function buildBrowserArtifactsFromRuntime({\n boardPath,\n cardDefinitions,\n runtimeModels,\n graphState,\n}: BuildBrowserArtifactsOptions): BoardRuntimeArtifactsPayload {\n const safeCardDefs = Array.isArray(cardDefinitions) ? cardDefinitions : [];\n const safeModels = Array.isArray(runtimeModels) ? runtimeModels : [];\n const runtimeModelById = new Map(safeModels.map((m) => [m.id, m]));\n type TaskEntry = { data?: { provides_data?: Record<string, unknown> }; status?: string; error?: string; executionCount?: number; retryCount?: number; startedAt?: string; lastUpdated?: string; completedAt?: string; failedAt?: string };\n const graphStateAny = graphState as { state?: { tasks?: Record<string, TaskEntry> } };\n const taskStates: Record<string, TaskEntry> = graphStateAny.state?.tasks ?? {};\n\n const cardRuntimeById: Record<string, CardRuntimeArtifact> = {};\n for (const model of safeModels) {\n if (!model?.id) continue;\n cardRuntimeById[model.id] = {\n schema_version: 'v1',\n card_id: model.id,\n card_data: structuredClone(model.card_data ?? {}),\n computed_values: structuredClone(model.computed_values ?? {}),\n };\n }\n\n const dataObjectsByToken: Record<string, unknown> = {};\n for (const taskName of Object.keys(taskStates)) {\n const providesData = taskStates[taskName]?.data?.provides_data;\n if (providesData && typeof providesData === 'object') {\n for (const token of Object.keys(providesData)) {\n dataObjectsByToken[token] = structuredClone(providesData[token]);\n }\n }\n }\n\n const statusCards = safeCardDefs.map((cardDef) => {\n const model = runtimeModelById.get(cardDef.id) ?? {} as Partial<LiveCardRuntimeModel>;\n const taskState = taskStates[cardDef.id];\n const taskStatus = typeof taskState?.status === 'string'\n ? taskState.status\n : cardStatusToTaskStatus((model.card_data as Record<string, unknown> | undefined)?.['status'] as string | undefined);\n const errorMessage = typeof taskState?.error === 'string'\n ? taskState.error\n : typeof (model.card_data as Record<string, unknown> | undefined)?.['error'] === 'string'\n ? (model.card_data as Record<string, unknown>)['error'] as string\n : null;\n return {\n name: cardDef.id,\n status: taskStatus,\n ...(errorMessage ? { error: { message: errorMessage, code: 'TASK_FAILED', at: taskState?.failedAt ?? null, source: 'browser-runtime' } } : {}),\n requires: Array.isArray((cardDef as { requires?: unknown }).requires) ? (cardDef as { requires: string[] }).requires : [],\n requires_satisfied: [] as string[],\n requires_missing: [] as string[],\n provides_declared: Array.isArray((cardDef as { provides?: Array<{ bindTo: string }> }).provides)\n ? (cardDef as { provides: Array<{ bindTo: string }> }).provides.map((e) => e.bindTo)\n : [cardDef.id],\n provides_runtime: Object.keys(taskState?.data?.provides_data ?? {}).sort(),\n blocked_by: [] as string[],\n unblocks: [] as string[],\n runtime: {\n attempt_count: taskState?.executionCount ?? 0,\n restart_count: taskState?.retryCount ?? 0,\n in_progress_since: taskStatus === 'in-progress' ? (taskState?.startedAt ?? null) : null,\n last_transition_at: taskState?.lastUpdated ?? (model.card_data as Record<string, unknown> | undefined)?.['lastRun'] as string ?? null,\n last_completed_at: taskState?.completedAt ?? null,\n last_restarted_at: taskState?.startedAt ?? null,\n status_age_ms: null as null,\n },\n };\n });\n\n return {\n cardDefinitions: structuredClone(safeCardDefs) as LiveCard[],\n cardRuntimeById,\n dataObjectsByToken,\n statusSnapshot: {\n schema_version: 'v1',\n meta: { board: { path: boardPath ?? 'browser-runtime' } },\n summary: {\n card_count: statusCards.length,\n completed: statusCards.filter((c) => c.status === 'completed').length,\n eligible: 0,\n pending: statusCards.filter((c) => c.status === 'pending').length,\n blocked: 0,\n unresolved: 0,\n failed: statusCards.filter((c) => c.status === 'failed').length,\n in_progress: statusCards.filter((c) => c.status === 'in-progress').length,\n orphan_cards: 0,\n topology: { edge_count: 0, max_fan_out_card: null, max_fan_out: 0 },\n },\n cards: statusCards,\n } as BoardRuntimeArtifactsPayload['statusSnapshot'],\n };\n}\n","/**\n * board-state-reducer — shared reactive state helpers for browser board shells.\n *\n * Used by both:\n * - board-livecards-localstorage-runtime (in-browser full engine)\n * - board-livecards-server-runtime-client (SSE/HTTP thin client)\n *\n * Pure functions; no side effects; no DOM/localStorage/fetch dependencies.\n */\n\n// ============================================================================\n// Types\n// ============================================================================\n\nexport interface CardModel {\n id: string;\n card: unknown;\n card_data: unknown;\n requires: unknown;\n computed_values: unknown;\n runtime_state: unknown;\n}\n\nexport interface BoardState {\n payload: unknown;\n cardIds: string[];\n modelsById: Record<string, CardModel>;\n}\n\nexport type SelectLiveCardModelFn = (payload: unknown, cardId: string) => CardModel;\n\n// ============================================================================\n// Helpers\n// ============================================================================\n\nfunction clone<T>(x: T): T {\n return JSON.parse(JSON.stringify(x)) as T;\n}\n\nfunction stableEq<T>(prev: T, next: T): T {\n if (prev === next) return prev;\n try {\n if (JSON.stringify(prev) === JSON.stringify(next)) return prev;\n } catch (_) { /* ignore */ }\n return next;\n}\n\nfunction deepEqJson(a: unknown, b: unknown): boolean {\n if (a === b) return true;\n try { return JSON.stringify(a) === JSON.stringify(b); } catch (_) { return false; }\n}\n\nfunction taskStatusToCardStatus(taskStatus: string | null | undefined): string {\n if (taskStatus === 'running' || taskStatus === 'in-progress') return 'loading';\n if (taskStatus === 'failed') return 'error';\n return 'fresh';\n}\n\n// ============================================================================\n// buildBoardState — full rebuild from a runtime payload snapshot\n// ============================================================================\n\nexport function buildBoardState(\n payload: unknown,\n prevState: BoardState | null,\n selectLiveCardModel: SelectLiveCardModelFn,\n): BoardState {\n const p = payload as { cardDefinitions?: Array<{ id: string }> } | null;\n const cardDefs = (p && Array.isArray(p.cardDefinitions)) ? p.cardDefinitions : [];\n const cardIds = cardDefs.map((c) => c.id);\n const prevModels = (prevState && prevState.modelsById) || {};\n const modelsById: Record<string, CardModel> = {};\n\n for (const id of cardIds) {\n const fresh = selectLiveCardModel(payload, id);\n const prev = prevModels[id];\n if (!prev) {\n modelsById[id] = fresh;\n continue;\n }\n const stab: CardModel = {\n id: fresh.id,\n card: stableEq(prev.card, fresh.card),\n card_data: stableEq(prev.card_data, fresh.card_data),\n requires: stableEq(prev.requires, fresh.requires),\n computed_values: stableEq(prev.computed_values, fresh.computed_values),\n runtime_state: stableEq(prev.runtime_state, fresh.runtime_state),\n };\n modelsById[id] = (\n stab.card === prev.card &&\n stab.card_data === prev.card_data &&\n stab.requires === prev.requires &&\n stab.computed_values === prev.computed_values &&\n stab.runtime_state === prev.runtime_state\n ) ? prev : stab;\n }\n\n return { payload, cardIds, modelsById };\n}\n\n// ============================================================================\n// applyNotification — incremental state reducer\n// ============================================================================\n\nexport function applyNotification(\n prevState: BoardState,\n notifications: Array<{ kind: string; [key: string]: unknown }>,\n selectLiveCardModel: SelectLiveCardModelFn,\n getFullPayload: () => unknown,\n): BoardState {\n if (!prevState || !Array.isArray(notifications) || notifications.length === 0) return prevState;\n\n let modelsById = prevState.modelsById;\n let cardIds = prevState.cardIds;\n let cloned = false;\n let changed = false;\n\n // Build token → [cardId, ...] map from current requires keys\n const consumersByToken: Record<string, string[]> = {};\n for (const cid of cardIds) {\n const m = modelsById[cid];\n const reqs = m && m.requires;\n if (reqs && typeof reqs === 'object') {\n for (const t of Object.keys(reqs as object)) {\n (consumersByToken[t] = consumersByToken[t] || []).push(cid);\n }\n }\n }\n\n function ensureClone() {\n if (!cloned) { modelsById = { ...modelsById }; cloned = true; }\n }\n\n for (const note of notifications) {\n if (!note || !note.kind) continue;\n\n if (note.kind === 'computed_values') {\n const cardId = note.cardId as string;\n const prev = modelsById[cardId];\n if (!prev) continue;\n const nextValues = (note.values || {}) as unknown;\n if (deepEqJson(prev.computed_values, nextValues)) continue;\n ensureClone();\n modelsById[cardId] = { ...prev, computed_values: nextValues };\n changed = true;\n\n } else if (note.kind === 'data_object') {\n const key = note.key as string;\n const notePayload = note.payload;\n const consumers = consumersByToken[key] || [];\n for (const cid of consumers) {\n const prevC = modelsById[cid];\n if (!prevC) continue;\n const prevReqs = (prevC.requires || {}) as Record<string, unknown>;\n if (deepEqJson(prevReqs[key], notePayload)) continue;\n ensureClone();\n modelsById[cid] = { ...prevC, requires: { ...prevReqs, [key]: notePayload } };\n changed = true;\n }\n\n } else if (note.kind === 'card_refreshed') {\n const cardId = note.cardId as string;\n let fresh: CardModel | null = null;\n const existing = modelsById[cardId];\n const noteCard = note.card;\n\n // Prefer authoritative card payload from notification to avoid stale\n // getFullPayload snapshots during server-runtime incremental updates.\n if (existing && noteCard && typeof noteCard === 'object' && !Array.isArray(noteCard)) {\n const cardObj = noteCard as Record<string, unknown>;\n const nextCardData = (\n cardObj.card_data && typeof cardObj.card_data === 'object' && !Array.isArray(cardObj.card_data)\n )\n ? cardObj.card_data\n : existing.card_data;\n const nextRequires = (\n cardObj.requires && typeof cardObj.requires === 'object' && !Array.isArray(cardObj.requires)\n )\n ? cardObj.requires\n : existing.requires;\n const nextComputedValues = (\n cardObj.computed_values && typeof cardObj.computed_values === 'object' && !Array.isArray(cardObj.computed_values)\n )\n ? cardObj.computed_values\n : existing.computed_values;\n const nextRuntimeState = (\n cardObj.runtime_state && typeof cardObj.runtime_state === 'object' && !Array.isArray(cardObj.runtime_state)\n )\n ? cardObj.runtime_state\n : existing.runtime_state;\n fresh = {\n ...existing,\n card: noteCard,\n card_data: nextCardData,\n requires: nextRequires,\n computed_values: nextComputedValues,\n runtime_state: nextRuntimeState,\n };\n }\n\n if (!fresh) {\n try {\n const fp = getFullPayload();\n if (fp) fresh = selectLiveCardModel(fp, cardId);\n } catch (_) { /* ignore */ }\n }\n\n if (!fresh) continue;\n if (existing &&\n deepEqJson(existing.card, fresh.card) &&\n deepEqJson(existing.card_data, fresh.card_data) &&\n deepEqJson(existing.requires, fresh.requires) &&\n deepEqJson(existing.computed_values, fresh.computed_values) &&\n deepEqJson(existing.runtime_state, fresh.runtime_state)) {\n continue;\n }\n ensureClone();\n modelsById[cardId] = fresh;\n if (!cardIds.includes(cardId)) cardIds = [...cardIds, cardId];\n changed = true;\n\n } else if (note.kind === 'status') {\n const statusCards = (note.status as { cards?: Array<{\n name?: string;\n status?: string;\n runtime?: { last_transition_at?: string | null };\n error?: { message?: string } | null;\n blocked_by?: string[];\n requires_missing?: string[];\n }> })?.cards ?? [];\n\n for (const statusCard of statusCards) {\n const sid = statusCard?.name;\n if (!sid || !modelsById[sid]) continue;\n const prevS = modelsById[sid];\n const nextCardStatus = taskStatusToCardStatus(statusCard.status);\n const nextCardData = {\n ...(prevS.card_data as object || {}),\n status: nextCardStatus,\n lastRun: statusCard.runtime?.last_transition_at ?? null,\n ...(statusCard.error?.message ? { error: statusCard.error.message } : {}),\n };\n // Remove error key if no error\n if (!statusCard.error?.message) {\n delete (nextCardData as { error?: string }).error;\n }\n const nextRuntimeState = {\n task_status: statusCard.status ?? null,\n card_status: nextCardStatus,\n runtime: statusCard.runtime ? clone(statusCard.runtime) : {},\n error: statusCard.error ? clone(statusCard.error) : null,\n blocked_by: Array.isArray(statusCard.blocked_by) ? clone(statusCard.blocked_by) : [],\n requires_missing: Array.isArray(statusCard.requires_missing) ? clone(statusCard.requires_missing) : [],\n };\n if (deepEqJson(prevS.card_data, nextCardData) && deepEqJson(prevS.runtime_state, nextRuntimeState)) continue;\n ensureClone();\n modelsById[sid] = { ...prevS, card_data: nextCardData, runtime_state: nextRuntimeState };\n changed = true;\n }\n }\n }\n\n if (!changed) return prevState;\n return { payload: prevState.payload, cardIds, modelsById };\n}\n","/**\n * board-livecards-client — browser IIFE bundle.\n *\n * Two layers in one bundle:\n * 1. Platform-free state: buildBoardState, applyNotification, selectLiveCardModel,\n * selectAllLiveCardModels — usable with any transport (Firebase, WebSocket, SSE, etc.)\n * 2. SSE/HTTP transport: createBoardRuntimeClient — for yaml-flow server runtime.\n *\n * Usage (SSE/HTTP mode):\n * <script src=\"board-livecards-client.js\"></script>\n * <script>\n * const client = BoardLiveCardsClient.createBoardRuntimeClient({\n * fetchServer, boardPaths: BoardLiveCardsClient.defaultBoardPaths, getServerOrigin,\n * });\n * await client.bootstrapBoard({ boardId: 'default', rootElement: el });\n * </script>\n *\n * Usage (custom transport — e.g. Firebase):\n * <script src=\"board-livecards-client.js\"></script>\n * <script>\n * const { buildBoardState, applyNotification, selectLiveCardModel } = BoardLiveCardsClient;\n * // apply your own transport; drive UI state with these primitives.\n * </script>\n *\n * Global: window.BoardLiveCardsClient\n */\n\nimport { selectLiveCardModel, selectAllLiveCardModels } from '../board-livegraph-runtime/index.js';\nimport { buildBoardState, applyNotification, type BoardState, type CardModel } from '../cli/common/board-state-reducer.js';\n\n// ============================================================================\n// Platform-free state exports\n// Re-exported so consumers using any transport (Firebase, WS, SSE) can drive\n// the LiveCard UI without loading the full localstorage bundle.\n// ============================================================================\nexport { buildBoardState, applyNotification, selectLiveCardModel, selectAllLiveCardModels };\nexport type { BoardState, CardModel };\n\n// ============================================================================\n// Public types\n// ============================================================================\n\nexport interface BoardPaths {\n initBoard: string;\n stream: string;\n patchCard: (id: string) => string;\n cardAction: (id: string) => string;\n cardChats: (id: string) => string;\n cardFile: (id: string) => string;\n}\n\nexport interface BoardRuntimeClientOptions {\n /** Authenticated fetch wrapper (handles origin resolution, auth headers, etc). */\n fetchServer: (path: string, init?: RequestInit) => Promise<Response>;\n /** Returns the canonical BoardPaths for a given boardId. */\n boardPaths: (boardId: string) => BoardPaths;\n /** Returns the resolved server origin (e.g. 'http://localhost:7799'). Used for SSE URL. */\n getServerOrigin: () => string | null;\n /** Initial board render mode. Defaults to 'board'. */\n initialMode?: string;\n /** Canvas dimensions. Defaults to { height: '72vh', overflow: 'auto' }. */\n canvas?: { height?: string; overflow?: string };\n}\n\nexport interface BootstrapBoardParams {\n boardId?: string;\n /** Optional path passed to init-board for server-side executor resolution. */\n taskExecutorPath?: string;\n mode?: string;\n rootElement: HTMLElement;\n}\n\n/**\n * Build the standard BoardPaths for a yaml-flow server runtime board.\n *\n * Covers only the paths owned by the server runtime (SSE, patch, action, files, chats,\n * init-board). Demo-server-specific endpoints (demo-setup, board registry\n * CRUD) are not included — add those in the consumer if needed.\n *\n * @example\n * const client = createBoardRuntimeClient({\n * fetchServer,\n * boardPaths: defaultBoardPaths,\n * getServerOrigin: () => activeOrigin,\n * });\n */\nexport function defaultBoardPaths(boardId: string): BoardPaths {\n const b = encodeURIComponent(boardId || 'default');\n const base = `/api/boards/${b}`;\n return {\n initBoard: `${base}/init-board`,\n stream: `${base}/sse`,\n patchCard: (id: string) => `${base}/cards/${encodeURIComponent(id)}`,\n cardAction: (id: string) => `${base}/cards/${encodeURIComponent(id)}/actions`,\n cardFile: (id: string) => `${base}/cards/${encodeURIComponent(id)}/files`,\n cardChats: (id: string) => `${base}/cards/${encodeURIComponent(id)}/chats`,\n };\n}\n\nexport interface BoardRuntimeClient {\n /** Bootstrap the board: init-board → bootstrap-cards → LiveCard.Board + SSE. */\n bootstrapBoard(params: BootstrapBoardParams): Promise<unknown>;\n /** Tear down SSE and release references. */\n dispose(): void;\n setMode(mode: string): void;\n autoLayout(): void;\n setDevMode(enabled: boolean): void;\n getCurrentMode(): string;\n}\n\n// ============================================================================\n// createBoardRuntimeClient\n// ============================================================================\n\nexport function createBoardRuntimeClient(options: BoardRuntimeClientOptions): BoardRuntimeClient {\n if (!options || typeof options !== 'object') throw new Error('options are required');\n\n const { fetchServer, boardPaths, getServerOrigin } = options;\n if (typeof fetchServer !== 'function') throw new Error('options.fetchServer is required');\n if (typeof boardPaths !== 'function') throw new Error('options.boardPaths is required');\n if (typeof getServerOrigin !== 'function') throw new Error('options.getServerOrigin is required');\n\n const canvas = (options.canvas && typeof options.canvas === 'object')\n ? options.canvas\n : { height: '72vh', overflow: 'auto' };\n\n // Reactive state — single source of truth\n const stateRef: { current: BoardState | null } = { current: null };\n let board: { setState: (fn: (prev: BoardState) => BoardState) => void; core?: unknown; engine?: unknown } | null = null;\n let sse: EventSource | null = null;\n let currentMode = String(options.initialMode || 'board');\n\n function getFullPayload() {\n return stateRef.current ? stateRef.current.payload : null;\n }\n\n // ── File upload helpers ───────────────────────────────────────────────────\n\n async function uploadCardFile(\n boardId: string,\n cardId: string,\n file: File,\n opts?: { inChat?: boolean },\n ): Promise<unknown | null> {\n if (!file) return null;\n const inChat = opts?.inChat === true;\n const fileName = typeof file.name === 'string' ? file.name : 'upload.bin';\n const contentType = file.type || 'application/octet-stream';\n const paths = boardPaths(boardId);\n const uploadPath = inChat\n ? `${paths.cardFile(cardId)}?inChat=true`\n : paths.cardFile(cardId);\n\n const upload = await fetchServer(uploadPath, {\n method: 'POST',\n headers: {\n 'content-type': contentType,\n 'x-file-name': encodeURIComponent(fileName),\n },\n body: file,\n });\n\n if (!upload.ok) {\n const errText = await upload.text();\n throw new Error(`Upload failed (${upload.status}): ${errText || 'unknown error'}`);\n }\n\n const payload = await upload.json() as { file?: unknown };\n return payload?.file ?? null;\n }\n\n async function uploadActionFiles(\n boardId: string,\n cardId: string,\n actionType: string,\n payload: Record<string, unknown> | null,\n ): Promise<Record<string, unknown>> {\n if (actionType !== 'chat-send' && actionType !== 'file-upload') return payload || {};\n const nextPayload: Record<string, unknown> = { ...(payload || {}) };\n const rawFiles = Array.isArray(nextPayload.files) ? nextPayload.files as File[] : [];\n if (!rawFiles.length) {\n nextPayload.files = [];\n return nextPayload;\n }\n\n const uploaded: unknown[] = [];\n for (const file of rawFiles) {\n const fileMeta = await uploadCardFile(boardId, cardId, file, { inChat: actionType === 'chat-send' });\n if (fileMeta) uploaded.push(fileMeta);\n }\n\n // For chat uploads, server-side file API already records metadata and emits system chat logs.\n nextPayload.files = actionType === 'chat-send' ? [] : uploaded;\n return nextPayload;\n }\n\n // ── bootstrapBoard ────────────────────────────────────────────────────────\n\n async function bootstrapBoard(params: BootstrapBoardParams): Promise<unknown> {\n const boardId = String(params?.boardId || 'default');\n const taskExecutorPath = typeof params?.taskExecutorPath === 'string' ? params.taskExecutorPath.trim() : '';\n const mode = String(params?.mode || currentMode || 'board');\n const rootEl = params?.rootElement;\n if (!rootEl) throw new Error('bootstrapBoard requires params.rootElement');\n\n const paths = boardPaths(boardId);\n\n const initBoardPath = taskExecutorPath\n ? `${paths.initBoard}?taskExecutorPath=${encodeURIComponent(taskExecutorPath)}`\n : paths.initBoard;\n const initBoardRes = await fetchServer(initBoardPath);\n if (!initBoardRes.ok) throw new Error(`Server init-board failed (${initBoardRes.status}).`);\n\n const origin = getServerOrigin();\n if (!origin) throw new Error('Server origin not resolved before SSE start');\n\n // Open SSE first and wait for the initial full-payload frame.\n // The /sse endpoint calls bootstrapBoard() server-side, publishes the\n // persisted state snapshot via the notification channel, then sends the\n // full runtime payload as the first SSE frame.\n const initialPayload = await new Promise<unknown>((resolve, reject) => {\n const sseConn = new EventSource(`${origin}${paths.stream}`);\n sse = sseConn;\n let gotInitialPayload = false;\n const timeout = setTimeout(() => {\n if (!gotInitialPayload) reject(new Error('SSE initial payload timeout (15s)'));\n }, 15_000);\n sseConn.onmessage = (evt) => {\n try {\n const update = JSON.parse(evt.data || '{}');\n if (!gotInitialPayload && (update?.cardDefinitions || selectAllLiveCardModels(update))) {\n gotInitialPayload = true;\n clearTimeout(timeout);\n resolve(update);\n }\n } catch { /* wait for valid frame */ }\n };\n sseConn.onerror = () => {\n if (!gotInitialPayload) {\n clearTimeout(timeout);\n reject(new Error('SSE connection failed during bootstrap'));\n }\n };\n });\n\n if (!selectAllLiveCardModels(initialPayload)) throw new Error('SSE payload missing published runtime artifacts');\n\n // Build initial reactive state using bundled selectLiveCardModel\n stateRef.current = buildBoardState(initialPayload, null, selectLiveCardModel as Parameters<typeof buildBoardState>[2]);\n\n const LiveCard = (globalThis as unknown as { LiveCard?: { init: (opts: unknown) => unknown; Board: (engine: unknown, el: HTMLElement, opts: unknown) => typeof board } }).LiveCard;\n if (!LiveCard) throw new Error('LiveCard global not loaded — include live-cards.js before this script');\n\n const engine = LiveCard.init({\n resolve: (id: string) => stateRef.current?.modelsById[id],\n chartLib: (globalThis as { Chart?: unknown }).Chart ?? null,\n markdown: (globalThis as { marked?: { parse: (t: string) => string } }).marked\n ? (text: string) => (globalThis as { marked: { parse: (t: string) => string } }).marked.parse(text)\n : null,\n sanitize: (globalThis as { DOMPurify?: { sanitize: (h: string) => string } }).DOMPurify\n ? (html: string) => (globalThis as { DOMPurify: { sanitize: (h: string) => string } }).DOMPurify.sanitize(html)\n : null,\n onPatchState: async (id: string, patch: Record<string, unknown>) => {\n await fetchServer(paths.patchCard(id), {\n method: 'PATCH',\n headers: { 'content-type': 'application/json' },\n body: JSON.stringify(patch || {}),\n });\n },\n onRefresh: async (id: string) => {\n await fetchServer(paths.patchCard(id), {\n method: 'PATCH',\n headers: { 'content-type': 'application/json' },\n body: JSON.stringify({}),\n });\n },\n onAction: async (id: string, actionType: string, actionPayload: Record<string, unknown> | null) => {\n const uploadedPayload = await uploadActionFiles(boardId, id, actionType, actionPayload);\n await fetchServer(paths.cardAction(id), {\n method: 'POST',\n headers: { 'content-type': 'application/json' },\n body: JSON.stringify({ actionType, payload: uploadedPayload || {} }),\n });\n },\n getChatMessages: async (id: string) => {\n const res = await fetchServer(paths.cardChats(id));\n if (!res.ok) return [];\n const chatPayload = await res.json() as { messages?: Array<{ role?: string; text?: string }> };\n return (chatPayload?.messages ?? []).map((m) => ({\n role: typeof m?.role === 'string' ? m.role : 'system',\n text: typeof m?.text === 'string' ? m.text : '',\n files: [],\n }));\n },\n });\n\n rootEl.innerHTML = '';\n board = LiveCard.Board(engine, rootEl, {\n initialState: stateRef.current,\n getNodeIds: (s: BoardState) => s.cardIds,\n selectNode: (s: BoardState, id: string) => s.modelsById[id],\n mode,\n canvas,\n });\n currentMode = mode;\n\n // Wire up the ongoing SSE message handler on the already-open connection.\n sse!.onmessage = (evt) => {\n try {\n const update = JSON.parse(evt.data || '{}') as {\n kind?: string;\n notifications?: Array<{ kind: string; [k: string]: unknown }>;\n cardDefinitions?: unknown[];\n engine?: { onServerSseEvent?: () => void; refreshOpenChatModal?: () => void };\n };\n\n if (update?.kind === 'notification-batch' && Array.isArray(update.notifications)) {\n if (board) {\n board.setState((prev: BoardState) => {\n const next = applyNotification(\n prev,\n update.notifications!,\n selectLiveCardModel as Parameters<typeof applyNotification>[2],\n getFullPayload,\n );\n stateRef.current = next;\n return next;\n });\n }\n } else if (update?.cardDefinitions) {\n const next = buildBoardState(update, stateRef.current, selectLiveCardModel as Parameters<typeof buildBoardState>[2]);\n stateRef.current = next;\n if (board) board.setState(() => next);\n }\n\n const eng = board && (board as { engine?: { onServerSseEvent?: () => void; refreshOpenChatModal?: () => void } }).engine;\n if (eng && typeof eng.onServerSseEvent === 'function') {\n eng.onServerSseEvent();\n } else if (eng && typeof eng.refreshOpenChatModal === 'function') {\n eng.refreshOpenChatModal();\n }\n } catch (err) {\n console.warn('Bad SSE payload', err);\n }\n };\n\n return board;\n }\n\n // ── Control methods ───────────────────────────────────────────────────────\n\n function dispose() {\n if (sse) { sse.close(); sse = null; }\n board = null;\n stateRef.current = null;\n }\n\n function setMode(mode: string) {\n currentMode = String(mode || 'board');\n const core = board && (board as { core?: { setMode?: (m: string) => void } }).core;\n if (core && typeof core.setMode === 'function') core.setMode(currentMode);\n }\n\n function autoLayout() {\n if (!board) return;\n currentMode = 'canvas';\n const core = (board as { core?: { setMode?: (m: string) => void; autoLayout?: () => void } }).core;\n if (core && typeof core.setMode === 'function') core.setMode('canvas');\n if (core && typeof core.autoLayout === 'function') core.autoLayout();\n }\n\n function setDevMode(enabled: boolean) {\n const core = board && (board as { core?: { setDevMode?: (e: boolean) => void } }).core;\n if (core && typeof core.setDevMode === 'function') core.setDevMode(Boolean(enabled));\n }\n\n function getCurrentMode() { return currentMode; }\n\n return { bootstrapBoard, dispose, setMode, autoLayout, setDevMode, getCurrentMode };\n}\n"]}
|