@north-light/cli 0.3.506 → 0.3.508

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.
@@ -1,2 +1,2 @@
1
- var Q=Object.defineProperty;var d=(s,f)=>Q(s,"name",{value:f,configurable:!0});import{mkdtempSync as V,readFileSync as q,rmSync as E,existsSync as Y}from"node:fs";import{tmpdir as Z}from"node:os";import{join as F}from"node:path";import{cliClient as ee}from"../../commands/api-client.js";import{loadPins as re,savePins as ne}from"../../core/canvas/browse/pins.js";import{detectColorCaps as oe}from"../../core/tui/draw.js";import{getTerminalSize as ie,parseKeypress as te,restoreTerminal as se,setupTerminal as de}from"../../core/tui/terminal.js";import{getPaneOption as le,runShellInBackground as ce,setPaneOption as C,shellQuote as h}from"../../core/runtime/placement-tmux.js";import{matchesTerminalInput as ae,resolveUserKeybindings as fe}from"../../core/keybindings/index.js";import{VIEWER_OWNER_OPTION as S}from"../attach/session/pane-tag.js";import{buildLines as ue,nearestSelectable as M,placements as pe,rootOf as b,stepSelectable as D}from"./model.js";import{listHeight as me,renderDashboard as he}from"./render.js";const ge=2e3,we=250,be=6e3;function P(s){return s.kind==="heading"?null:s.kind==="root"?`root:${s.id}`:`child:${s.rootId}:${s.id}`}d(P,"lineKey");async function Oe(s){const f=process.env.TMUX_PANE;if(f===void 0||f==="")throw new Error("the dashboard runs in a tmux pane (TMUX_PANE is unset)");const m=ee(),R=fe(),j=oe(),c=d((r,n)=>ae(R,r,n),"matches"),k=String(process.pid);C(f,S,k);for(const r of["@crtr_node","@crtr_attach","@crtr_viewer_at"])C(f,r,"");const K=V(F(Z(),"crtr-dashboard-"));let I=!1;const L=d(()=>{if(!I){I=!0;try{se()}catch{}le(f,S)===k&&C(f,S,"");try{E(K,{recursive:!0,force:!0})}catch{}}},"cleanup");process.once("exit",L);for(const r of["SIGTERM","SIGHUP"])process.once(r,()=>{L(),process.exit(0)});const e={rows:[],placed:new Map,pinned:re(),expanded:new Set,lines:[],cursorKey:null,cursor:0,scroll:0,scope:s.profileId===void 0?"all":"profile",profileLabel:s.profileId??"",loaded:!1,help:!1,inputFocused:!1,inputText:"",dirs:[s.cwd],dirIndex:0,dirsLoaded:!1,rename:null,renameTarget:null,confirmClose:null,notice:null,opening:null},x=new Set;let $;const u=d(r=>{e.notice=r,$!==void 0&&clearTimeout($),$=setTimeout(()=>{e.notice=null,l()},be)},"notify"),g=d(()=>{const r=e.rows.filter(t=>!x.has(t.node_id));e.lines=ue(r,e.placed,e.pinned,e.expanded);const n=e.cursorKey===null?-1:e.lines.findIndex(t=>P(t)===e.cursorKey);e.cursor=n>=0?n:M(e.lines,e.cursor),e.cursor<0&&(e.cursor=0);const o=e.lines[e.cursor];e.cursorKey=o===void 0?null:P(o)},"rebuild"),l=d(()=>{if(I)return;const r=ie(),n=me(r.rows)-1;e.cursor<e.scroll&&(e.scroll=e.cursor),e.cursor>=e.scroll+n&&(e.scroll=e.cursor-n+1),e.scroll<0&&(e.scroll=0),process.stdout.write(he({lines:e.lines,cursor:e.cursor,scroll:e.scroll,pinned:e.pinned,scope:e.scope,profileLabel:e.profileLabel,rename:e.rename,inputText:e.inputText,inputFocused:e.inputFocused,chipDir:e.dirs[e.dirIndex]??s.cwd,confirmName:e.confirmClose===null?null:e.rows.find(o=>o.node_id===e.confirmClose)?.name??e.confirmClose,notice:e.notice,opening:e.opening!==null,help:e.help,loaded:e.loaded},r,j))},"paint");let v=!1,y=!1;const p=d(async()=>{if(v){y=!0;return}v=!0;try{const r=await m.liveRoots(e.scope==="profile"&&s.profileId!==void 0?{profile:s.profileId}:{});e.rows=r.rows,e.placed=pe(r.rows,e.placed),e.loaded=!0,g()}catch(r){u(`refresh failed: ${r.message}`)}finally{v=!1}l(),y&&(y=!1,p())},"poll");s.profileId!==void 0&&m.getProfile(s.profileId).then(r=>{e.profileLabel=r.name,l()}).catch(()=>{});const U=d(()=>e.lines[e.cursor],"current"),z=d(r=>{if(e.opening!==null||r.kind==="heading")return;const o=(r.kind==="root"?r.row:e.rows.find(_=>_.node_id===r.rootId)?.children.find(_=>_.node_id===r.id))?.name??r.id,t=r.kind==="root"&&r.row.asks>0?r.row.first_ask_ticket_id:null,i=F(K,`open-${Date.now()}`),T=`${["crtr","surface","node","focus",r.id,"--pane",f,"--in-place","--keep-other-viewers",...t===null?[]:["--open-ticket",t],"--json"].map(h).join(" ")} >${h(`${i}.out`)} 2>${h(`${i}.err`)}; echo $? >${h(`${i}.code`)}; mv ${h(`${i}.code`)} ${h(i)}`;if(!ce(T)){u(`could not open ${o}`),l();return}e.opening={file:i,name:o},l()},"open"),A=d(()=>{const r=e.opening;if(r===null||!Y(r.file))return;const n=d(a=>{try{return q(a,"utf8").trim()}catch{return""}},"read"),o=n(r.file),t=n(`${r.file}.out`),i=n(`${r.file}.err`);for(const a of[r.file,`${r.file}.out`,`${r.file}.err`])E(a,{force:!0});if(e.opening=null,o!=="0")u(i===""?`could not open ${r.name}`:i.split(`
2
- `)[0]);else{let a=!1;try{a=JSON.parse(t).focused===!0}catch{a=!1}a||u(`could not open ${r.name}`)}l(),p()},"finishOpen"),G=d(async()=>{const r=e.inputText.trim();if(r!==""){try{await m.createNode({root:!0,prompt:r,cwd:e.dirs[e.dirIndex]??s.cwd,...s.profileId===void 0?{}:{profile:s.profileId}}),e.inputText="",e.inputFocused=!1,p()}catch(n){u(`could not start: ${n.message}`)}l()}},"startConversation"),H=d(()=>{e.dirsLoaded||s.profileId===void 0||(e.dirsLoaded=!0,m.getProfile(s.profileId).then(r=>{e.dirs=[s.cwd,...r.projects.map(n=>n.path).filter(n=>n!==s.cwd)],l()}).catch(r=>{u(`could not list directories: ${r.message}`),l()}))},"loadDirs"),O=d(async r=>{e.confirmClose=null,x.add(r),g(),l();try{await m.closeNode(r,{finish:!0})}catch(n){u(`could not close: ${n.message}`)}finally{x.delete(r)}p(),l()},"doClose"),W=d(async()=>{const r=e.renameTarget,n=(e.rename??"").trim();if(e.rename=null,e.renameTarget=null,r!==null&&n!==""){try{await m.patchConfig(r,{name:n})}catch(o){u(`could not rename: ${o.message}`)}p()}l()},"commitRename"),X=d(r=>{e.pinned.has(r)?e.pinned.delete(r):e.pinned.add(r),ne(e.pinned),g()},"togglePin"),w=d(r=>{const n=M(e.lines,r);n<0||(e.cursor=n,e.cursorKey=P(e.lines[n]))},"moveTo"),B=d(r=>[...r].filter(n=>n>=" "&&n!=="\x7F").join(""),"printable"),N=d((r,n,o,t)=>{if(n.backspace)return t(o().slice(0,-1)),!0;if(n.ctrl||n.meta)return!0;const i=B(r);return i!==""&&t(o()+i),!0},"onText"),J=d((r,n)=>{const o={input:r,...n};if(e.help){e.help=!1,l();return}if(e.rename!==null){if(n.escape)e.rename=null,e.renameTarget=null;else if(n.return){W();return}else N(r,n,()=>e.rename??"",i=>{e.rename=i});l();return}if(e.inputFocused){if(c("crtr.dashboard.input-cancel",o))e.inputFocused=!1;else if(c("crtr.dashboard.input-submit",o)){G();return}else c("crtr.dashboard.directory-next",o)?e.dirIndex=(e.dirIndex+1)%e.dirs.length:c("crtr.dashboard.directory-previous",o)?e.dirIndex=(e.dirIndex-1+e.dirs.length)%e.dirs.length:N(r,n,()=>e.inputText,i=>{e.inputText=i});l();return}if(e.confirmClose!==null){const i=e.confirmClose;if(c("crtr.dashboard.confirm-close",o)){O(i);return}c("crtr.dashboard.cancel-close",o)&&(e.confirmClose=null,l());return}const t=U();if(c("crtr.dashboard.down",o))w(D(e.lines,e.cursor,1));else if(c("crtr.dashboard.up",o))w(D(e.lines,e.cursor,-1));else if(c("crtr.dashboard.first",o))w(0);else if(c("crtr.dashboard.last",o))w(e.lines.length-1);else if(c("crtr.dashboard.expand",o))t?.kind==="root"&&t.row.children.length>0&&(e.expanded.add(t.id),g());else if(c("crtr.dashboard.collapse",o)){if(t!==void 0&&t.kind!=="heading"){const i=b(t);e.expanded.delete(i),e.cursorKey=`root:${i}`,g()}}else if(c("crtr.dashboard.open",o)){t!==void 0&&z(t);return}else if(c("crtr.dashboard.pin",o)){const i=t===void 0?null:b(t);i!==null&&X(i)}else if(c("crtr.dashboard.rename",o)){const i=t===void 0?null:b(t);i!==null&&(e.renameTarget=i,e.rename=e.rows.find(a=>a.node_id===i)?.name??"")}else if(c("crtr.dashboard.close",o)){const i=t===void 0?null:b(t),a=i===null?void 0:e.rows.find(T=>T.node_id===i);if(a!==void 0)if(a.running_count>0)e.confirmClose=a.node_id;else{O(a.node_id);return}}else c("crtr.dashboard.profile",o)?s.profileId!==void 0&&(e.scope=e.scope==="profile"?"all":"profile",p()):c("crtr.dashboard.input",o)?(e.inputFocused=!0,H()):c("crtr.dashboard.help",o)&&(e.help=!0);l()},"onKey");de(),l(),p(),setInterval(()=>{p()},ge),setInterval(A,we),process.stdout.on("resize",l),await new Promise(()=>{process.stdin.on("data",r=>{try{const{input:n,key:o}=te(r);J(n,o)}catch(n){u(`internal error: ${n.message}`),l()}})})}d(Oe,"runDashboard");export{Oe as runDashboard};
1
+ var Q=Object.defineProperty;var d=(s,f)=>Q(s,"name",{value:f,configurable:!0});import{mkdtempSync as V,readFileSync as q,rmSync as E,existsSync as Y}from"node:fs";import{tmpdir as Z}from"node:os";import{join as F}from"node:path";import{cliClient as ee}from"../../commands/api-client.js";import{loadPins as re,savePins as ne}from"../../core/canvas/browse/pins.js";import{detectColorCaps as oe}from"../../core/tui/draw.js";import{getTerminalSize as ie,parseKeypress as te,restoreTerminal as se,setupTerminal as de}from"../../core/tui/terminal.js";import{getPaneOption as le,runShellInBackground as ce,setPaneOption as C,shellQuote as h}from"../../core/runtime/placement-tmux.js";import{matchesTerminalInput as ae,resolveUserKeybindings as fe}from"../../core/keybindings/index.js";import{VIEWER_OWNER_OPTION as S}from"../attach/session/pane-tag.js";import{buildLines as ue,nearestSelectable as M,placements as pe,rootOf as b,stepSelectable as D}from"./model.js";import{listHeight as me,renderDashboard as he}from"./render.js";const ge=2e3,we=250,be=6e3;function P(s){return s.kind==="heading"?null:s.kind==="root"?`root:${s.id}`:`child:${s.rootId}:${s.id}`}d(P,"lineKey");async function Oe(s){const f=process.env.TMUX_PANE;if(f===void 0||f==="")throw new Error("the dashboard runs in a tmux pane (TMUX_PANE is unset)");const m=ee(),R=fe(),j=oe(),c=d((r,n)=>ae(R,r,n),"matches"),k=String(process.pid);C(f,S,k);for(const r of["@crtr_node","@crtr_attach","@crtr_viewer_at"])C(f,r,"");const K=V(F(Z(),"crtr-dashboard-"));let x=!1;const L=d(()=>{if(!x){x=!0;try{se()}catch{}le(f,S)===k&&C(f,S,"");try{E(K,{recursive:!0,force:!0})}catch{}}},"cleanup");process.once("exit",L);for(const r of["SIGTERM","SIGHUP"])process.once(r,()=>{L(),process.exit(0)});const e={rows:[],placed:new Map,pinned:re(),expanded:new Set,lines:[],cursorKey:null,cursor:0,scroll:0,scope:s.profileId===void 0?"all":"profile",profileLabel:s.profileId??"",loaded:!1,help:!1,inputFocused:!1,inputText:"",dirs:[s.cwd],dirIndex:0,dirsLoaded:!1,rename:null,renameTarget:null,confirmClose:null,notice:null,opening:null},I=new Set;let v;const u=d(r=>{e.notice=r,v!==void 0&&clearTimeout(v),v=setTimeout(()=>{e.notice=null,l()},be)},"notify"),g=d(()=>{const r=e.rows.filter(t=>!I.has(t.node_id));e.lines=ue(r,e.placed,e.pinned,e.expanded);const n=e.cursorKey===null?-1:e.lines.findIndex(t=>P(t)===e.cursorKey);e.cursor=n>=0?n:M(e.lines,e.cursor),e.cursor<0&&(e.cursor=0);const o=e.lines[e.cursor];e.cursorKey=o===void 0?null:P(o)},"rebuild"),l=d(()=>{if(x)return;const r=ie(),n=me(r.rows)-1;e.cursor<e.scroll&&(e.scroll=e.cursor),e.cursor>=e.scroll+n&&(e.scroll=e.cursor-n+1),e.scroll<0&&(e.scroll=0),process.stdout.write(he({lines:e.lines,cursor:e.cursor,scroll:e.scroll,pinned:e.pinned,scope:e.scope,profileLabel:e.profileLabel,rename:e.rename,inputText:e.inputText,inputFocused:e.inputFocused,chipDir:e.dirs[e.dirIndex]??s.cwd,confirmName:e.confirmClose===null?null:e.rows.find(o=>o.node_id===e.confirmClose)?.name??e.confirmClose,notice:e.notice,opening:e.opening!==null,help:e.help,loaded:e.loaded},r,j))},"paint");let $=!1,y=!1;const p=d(async()=>{if($){y=!0;return}$=!0;try{const r=await m.liveRoots(e.scope==="profile"&&s.profileId!==void 0?{profile:s.profileId}:{});e.rows=r.rows,e.placed=pe(r.rows,e.placed),e.loaded=!0,g()}catch(r){u(`refresh failed: ${r.message}`)}finally{$=!1}l(),y&&(y=!1,p())},"poll");s.profileId!==void 0&&m.getProfile(s.profileId).then(r=>{e.profileLabel=r.name,l()}).catch(()=>{});const U=d(()=>e.lines[e.cursor],"current"),z=d(r=>{if(e.opening!==null||r.kind==="heading")return;const o=(r.kind==="root"?r.row:e.rows.find(_=>_.node_id===r.rootId)?.children.find(_=>_.node_id===r.id))?.name??r.id,t=r.kind==="root"&&r.row.asks>0?r.row.first_ask_ticket_id:null,i=F(K,`open-${Date.now()}`),T=`{ ${["crtr","surface","node","focus",r.id,"--pane",f,"--in-place","--keep-other-viewers",...t===null?[]:["--open-ticket",t],"--json"].map(h).join(" ")} >${h(`${i}.out`)} 2>${h(`${i}.err`)}; echo $? >${h(`${i}.code`)} && mv ${h(`${i}.code`)} ${h(i)}; } 2>/dev/null; exit 0`;if(!ce(T)){u(`could not open ${o}`),l();return}e.opening={file:i,name:o},l()},"open"),A=d(()=>{const r=e.opening;if(r===null||!Y(r.file))return;const n=d(a=>{try{return q(a,"utf8").trim()}catch{return""}},"read"),o=n(r.file),t=n(`${r.file}.out`),i=n(`${r.file}.err`);for(const a of[r.file,`${r.file}.out`,`${r.file}.err`])E(a,{force:!0});if(e.opening=null,o!=="0")u(i===""?`could not open ${r.name}`:i.split(`
2
+ `)[0]);else{let a=!1;try{a=JSON.parse(t).focused===!0}catch{a=!1}a||u(`could not open ${r.name}`)}l(),p()},"finishOpen"),G=d(async()=>{const r=e.inputText.trim();if(r!==""){try{await m.createNode({root:!0,prompt:r,cwd:e.dirs[e.dirIndex]??s.cwd,...s.profileId===void 0?{}:{profile:s.profileId}}),e.inputText="",e.inputFocused=!1,p()}catch(n){u(`could not start: ${n.message}`)}l()}},"startConversation"),H=d(()=>{e.dirsLoaded||s.profileId===void 0||(e.dirsLoaded=!0,m.getProfile(s.profileId).then(r=>{e.dirs=[s.cwd,...r.projects.map(n=>n.path).filter(n=>n!==s.cwd)],l()}).catch(r=>{u(`could not list directories: ${r.message}`),l()}))},"loadDirs"),O=d(async r=>{e.confirmClose=null,I.add(r),g(),l();try{await m.closeNode(r,{finish:!0})}catch(n){u(`could not close: ${n.message}`)}finally{I.delete(r)}p(),l()},"doClose"),W=d(async()=>{const r=e.renameTarget,n=(e.rename??"").trim();if(e.rename=null,e.renameTarget=null,r!==null&&n!==""){try{await m.patchConfig(r,{name:n})}catch(o){u(`could not rename: ${o.message}`)}p()}l()},"commitRename"),X=d(r=>{e.pinned.has(r)?e.pinned.delete(r):e.pinned.add(r),ne(e.pinned),g()},"togglePin"),w=d(r=>{const n=M(e.lines,r);n<0||(e.cursor=n,e.cursorKey=P(e.lines[n]))},"moveTo"),B=d(r=>[...r].filter(n=>n>=" "&&n!=="\x7F").join(""),"printable"),N=d((r,n,o,t)=>{if(n.backspace)return t(o().slice(0,-1)),!0;if(n.ctrl||n.meta)return!0;const i=B(r);return i!==""&&t(o()+i),!0},"onText"),J=d((r,n)=>{const o={input:r,...n};if(e.help){e.help=!1,l();return}if(e.rename!==null){if(n.escape)e.rename=null,e.renameTarget=null;else if(n.return){W();return}else N(r,n,()=>e.rename??"",i=>{e.rename=i});l();return}if(e.inputFocused){if(c("crtr.dashboard.input-cancel",o))e.inputFocused=!1;else if(c("crtr.dashboard.input-submit",o)){G();return}else c("crtr.dashboard.directory-next",o)?e.dirIndex=(e.dirIndex+1)%e.dirs.length:c("crtr.dashboard.directory-previous",o)?e.dirIndex=(e.dirIndex-1+e.dirs.length)%e.dirs.length:N(r,n,()=>e.inputText,i=>{e.inputText=i});l();return}if(e.confirmClose!==null){const i=e.confirmClose;if(c("crtr.dashboard.confirm-close",o)){O(i);return}c("crtr.dashboard.cancel-close",o)&&(e.confirmClose=null,l());return}const t=U();if(c("crtr.dashboard.down",o))w(D(e.lines,e.cursor,1));else if(c("crtr.dashboard.up",o))w(D(e.lines,e.cursor,-1));else if(c("crtr.dashboard.first",o))w(0);else if(c("crtr.dashboard.last",o))w(e.lines.length-1);else if(c("crtr.dashboard.expand",o))t?.kind==="root"&&t.row.children.length>0&&(e.expanded.add(t.id),g());else if(c("crtr.dashboard.collapse",o)){if(t!==void 0&&t.kind!=="heading"){const i=b(t);e.expanded.delete(i),e.cursorKey=`root:${i}`,g()}}else if(c("crtr.dashboard.open",o)){t!==void 0&&z(t);return}else if(c("crtr.dashboard.pin",o)){const i=t===void 0?null:b(t);i!==null&&X(i)}else if(c("crtr.dashboard.rename",o)){const i=t===void 0?null:b(t);i!==null&&(e.renameTarget=i,e.rename=e.rows.find(a=>a.node_id===i)?.name??"")}else if(c("crtr.dashboard.close",o)){const i=t===void 0?null:b(t),a=i===null?void 0:e.rows.find(T=>T.node_id===i);if(a!==void 0)if(a.running_count>0)e.confirmClose=a.node_id;else{O(a.node_id);return}}else c("crtr.dashboard.profile",o)?s.profileId!==void 0&&(e.scope=e.scope==="profile"?"all":"profile",p()):c("crtr.dashboard.input",o)?(e.inputFocused=!0,H()):c("crtr.dashboard.help",o)&&(e.help=!0);l()},"onKey");de(),l(),p(),setInterval(()=>{p()},ge),setInterval(A,we),process.stdout.on("resize",l),await new Promise(()=>{process.stdin.on("data",r=>{try{const{input:n,key:o}=te(r);J(n,o)}catch(n){u(`internal error: ${n.message}`),l()}})})}d(Oe,"runDashboard");export{Oe as runDashboard};
@@ -1,3 +1,3 @@
1
- var E=Object.defineProperty;var s=(t,a)=>E(t,"name",{value:a,configurable:!0});import{defineLeaf as _}from"../core/command.js";import{envProfileId as p}from"../shared/env.js";import{getDefaultProfileId as f}from"../core/profiles/default-binding.js";import{SECTION_ORDER as k,SECTION_TITLE as x,sectionOf as R}from"../clients/dashboard/model.js";import{closeWindow as I,currentTmux as T,displayMessage as v,getPaneOption as P,openNodeWindow as N,paneCurrentCommand as C,paneCurrentPath as D,paneLocation as O,paneStartCommand as U,renameWindow as W,respawnPaneSync as L,shellQuote as S,swapPanes as A,viewerSplitEnv as M,windowOfPane as X}from"../core/runtime/placement-tmux.js";import{cliClient as $}from"./api-client.js";const h="CRTR_DASHBOARD_RUN";async function j(t,a,e){if(t!==void 0&&t!=="")return t;const o=a===void 0?void 0:P(a,"@crtr_node");if(o!==void 0&&o!=="")try{const r=(await $().getNode(o)).profile_id;if(r!=null)return r}catch{}return p()??f(e)??void 0}s(j,"profileFor");async function q(t){const a=await $().liveRoots(t===void 0?{}:{profile:t}),e=[];for(const o of k){const r=a.rows.filter(n=>R(n)===o);if(r.length!==0){e.push(`${x[o]} (${r.length})`);for(const n of r){const i=[n.running_count>0?`\u27F3 ${n.running_count}`:"",n.asks>0?`? ${n.asks}`:"",n.fault!==null?"\u26A0":""].filter(d=>d!=="").join(" ");e.push(` ${n.name} ${n.state_line??n.goal??""}${i===""?"":` ${i}`}`)}}}process.stdout.write(`${e.length===0?"no live conversations":e.join(`
1
+ var R=Object.defineProperty;var i=(r,s)=>R(r,"name",{value:s,configurable:!0});import{defineLeaf as N}from"../core/command.js";import{envProfileId as f}from"../shared/env.js";import{getDefaultProfileId as l}from"../core/profiles/default-binding.js";import{SECTION_ORDER as O,SECTION_TITLE as P,sectionOf as T}from"../clients/dashboard/model.js";import{closeWindow as I,currentTmux as C,displayMessage as w,getPaneOption as m,openNodeWindow as D,paneCurrentCommand as U,paneCurrentPath as W,paneLocation as A,paneStartCommand as L,renameWindow as S,respawnPaneSync as M,setPaneOption as X,shellQuote as j,swapPanes as q,viewerSplitEnv as F,windowOfPane as V}from"../core/runtime/placement-tmux.js";import{cliClient as g}from"./api-client.js";const b="CRTR_DASHBOARD_RUN",x="@crtr_dashboard_return";async function B(r,s,e){if(r!==void 0&&r!=="")return r;const n=s===void 0?void 0:m(s,"@crtr_node");if(n!==void 0&&n!=="")try{const a=(await g().getNode(n)).profile_id;if(a!=null)return a}catch{}return f()??l(e)??void 0}i(B,"profileFor");async function H(r){const s=await g().liveRoots(r===void 0?{}:{profile:r}),e=[];for(const n of O){const a=s.rows.filter(o=>T(o)===n);if(a.length!==0){e.push(`${P[n]} (${a.length})`);for(const o of a){const d=[o.running_count>0?`\u27F3 ${o.running_count}`:"",o.asks>0?`? ${o.asks}`:"",o.fault!==null?"\u26A0":""].filter(c=>c!=="").join(" ");e.push(` ${o.name} ${o.state_line??o.goal??""}${d===""?"":` ${d}`}`)}}}process.stdout.write(`${e.length===0?"no live conversations":e.join(`
2
2
  `)}
3
- `)}s(q,"printListing");const G=_({name:"dashboard",description:"show the profile\u2019s live root conversations in a tmux pane \u2014 which need the person, which run, which are idle",whenToUse:"the person asks to see all their running conversations in one place, or you are wiring a key to it. It is a screen for the person, not a read: use `canvas dashboard` for a one-shot tree you can pipe",help:{name:"surface dashboard",summary:"put the dashboard in a tmux pane: live root conversations in Waiting for you / Running / Idle, Enter opens one in that pane, n starts a new background conversation. Outside tmux it prints the same listing as text",params:[{kind:"flag",name:"pane",type:"string",required:!1,constraint:"tmux pane that shows the dashboard. Default: $TMUX_PANE. A pane running a crouter viewer or a dashboard is respawned; any other pane (a shell, an editor) is swapped for a new window that runs the dashboard, and its program keeps running in the background window."},{kind:"flag",name:"profile-id",type:"string",required:!1,constraint:"Exact profile id to list. Default: the profile of the conversation shown in the pane, then $CRTR_PROFILE_ID, then the pane directory\u2019s pinned default profile; absent means all profiles."}],output:[],outputKind:"object",effects:["Respawns the target pane onto the dashboard (a crouter viewer\u2019s engine keeps running), or opens a new tmux window with the dashboard and swaps it into the pane\u2019s place.","Never kills a pane that is not running a crouter viewer or dashboard.","Inside the dashboard, Enter runs `surface node focus` for the chosen conversation, `n` creates a root conversation, `x` finishes one."]},run:s(async t=>{const a=t.profileId;if(process.env[h]==="1"){delete process.env[h];const{runDashboard:c}=await import("../clients/dashboard/app.js"),y=a??p()??f(process.cwd())??void 0;await c({profileId:y,cwd:process.cwd()});return}if(process.env.TMUX===void 0||process.env.TMUX===""){await q(a??p()??f(process.cwd())??void 0);return}const e=t.pane??process.env.TMUX_PANE??T()?.pane;if(e===void 0||e==="")throw v("crtr: no pane to show the dashboard in"),new Error("no tmux pane to show the dashboard in \u2014 pass --pane <id>");const o=s(c=>{throw v(`crtr: ${c}`,e),new Error(c)},"fail"),r=U(e)?.replace(/^"|"$/g,"");if(r===void 0)return o(`pane ${e} is not reachable`);if(r.startsWith("crtr surface dashboard"))return;const n=D(e)??process.cwd(),i=await j(a,e,n),d=`crtr surface dashboard${i===void 0?"":` --profile-id ${S(i)}`}`,l={...M(),[h]:"1"};if(r.startsWith("crtr surface attach to ")){L({pane:e,cwd:n,env:l,command:d})||o(`tmux could not respawn pane ${e}`);return}const w=O(e);if(w===null)return o(`pane ${e} is not in a tmux window`);const u=N({session:w.session,name:"dashboard",cwd:n,env:l,command:d});if(u===null)return o("tmux could not open a window for the dashboard");const m=C(e),g=A(u.pane,e);if(g!==null)return I(u.window),o(`could not show the dashboard: ${g}`);const b=X(e);b!==null&&m!==void 0&&W(b,m)},"run"),render:s(()=>"","render")});export{G as surfaceDashboardLeaf};
3
+ `)}i(H,"printListing");const ne=N({name:"dashboard",description:"show the profile\u2019s live root conversations in a tmux pane \u2014 which need the person, which run, which are idle",whenToUse:"the person asks to see all their running conversations in one place, or you are wiring a key to it. It is a screen for the person, not a read: use `canvas dashboard` for a one-shot tree you can pipe",help:{name:"surface dashboard",summary:"put the dashboard in a tmux pane: live root conversations in Waiting for you / Running / Idle, Enter opens one in that pane, n starts a new background conversation. Outside tmux it prints the same listing as text",params:[{kind:"flag",name:"pane",type:"string",required:!1,constraint:"tmux pane that shows the dashboard. Default: $TMUX_PANE. A pane running a crouter viewer is respawned; any other pane (a shell, an editor) is swapped for a new window that runs the dashboard, and its program keeps running in the background window. A pane already showing the dashboard returns to the conversation it showed before."},{kind:"flag",name:"profile-id",type:"string",required:!1,constraint:"Exact profile id to list. Default: the profile of the conversation shown in the pane, then $CRTR_PROFILE_ID, then the pane directory\u2019s pinned default profile; absent means all profiles."}],output:[],outputKind:"object",effects:["Respawns the target pane onto the dashboard (a crouter viewer\u2019s engine keeps running), or opens a new tmux window with the dashboard and swaps it into the pane\u2019s place.","On a pane already showing the dashboard: opens the conversation that pane showed before the dashboard, in that pane; with none recorded, shows a tmux message and changes nothing.","Never kills a pane that is not running a crouter viewer or dashboard.","Inside the dashboard, Enter runs `surface node focus` for the chosen conversation, `n` creates a root conversation, `x` finishes one."]},run:i(async r=>{const s=r.profileId;if(process.env[b]==="1"){delete process.env[b];const{runDashboard:t}=await import("../clients/dashboard/app.js"),u=s??f()??l(process.cwd())??void 0;await t({profileId:u,cwd:process.cwd()});return}if(process.env.TMUX===void 0||process.env.TMUX===""){await H(s??f()??l(process.cwd())??void 0);return}const e=r.pane??process.env.TMUX_PANE??C()?.pane;if(e===void 0||e==="")throw w("crtr: no pane to show the dashboard in"),new Error("no tmux pane to show the dashboard in \u2014 pass --pane <id>");const n=i(t=>{throw w(`crtr: ${t}`,e),new Error(t)},"fail"),a=L(e)?.replace(/^"|"$/g,"");if(a===void 0)return n(`pane ${e} is not reachable`);if(a.startsWith("crtr surface dashboard")){const t=m(e,x);if(t===void 0||t===""){w("crtr: no conversation to return to from this dashboard",e);return}const u=g(),p=await u.getNode(t).catch(()=>null);if(p===null)return n("the conversation this pane showed before no longer exists");const{focusNode:E}=await import("../core/runtime/focus-viewer.js");(await E(u,p,{pane:e,inPlace:!0,keepOtherViewers:!0})).focused||n(`could not return to ${p.name}`);return}const o=W(e)??process.cwd(),d=await B(s,e,o),c=`crtr surface dashboard${d===void 0?"":` --profile-id ${j(d)}`}`,v={...F(),[b]:"1"};if(a.startsWith("crtr surface attach to ")){const t=m(e,"@crtr_node");t!==void 0&&t!==""&&X(e,x,t),M({pane:e,cwd:o,env:v,command:c})||n(`tmux could not respawn pane ${e}`);return}const $=A(e);if($===null)return n(`pane ${e} is not in a tmux window`);const h=D({session:$.session,name:"dashboard",cwd:o,env:v,command:c});if(h===null)return n("tmux could not open a window for the dashboard");const _=U(e),y=q(h.pane,e);if(y!==null)return I(h.window),n(`could not show the dashboard: ${y}`);const k=V(e);k!==null&&_!==void 0&&S(k,_)},"run"),render:i(()=>"","render")});export{ne as surfaceDashboardLeaf};
@@ -17,6 +17,8 @@ export type Resolution = {
17
17
  export declare function viewOf(db: DatabaseSync, reader: Reader): ObjectRow[];
18
18
  /** The owner types that carry a handle; `<type>:<handle>/<name>` names one exactly. */
19
19
  export declare const HANDLE_TYPES: readonly ["person", "app", "repo", "profile"];
20
+ /** A ref without its `[[ ]]` wrapper. */
21
+ export declare const unwrapRef: (raw: string) => string;
20
22
  /** Every owner a handle names: a node by id, and each handle-carrying owner type
21
23
  * holding that handle (handles are unique per type, not across types). Any owner
22
24
  * also answers to its object id, so `<owner object id>/<name>` names a document
@@ -33,3 +35,8 @@ export interface ResolveContext {
33
35
  readable: (o: ObjectRow) => boolean;
34
36
  }
35
37
  export declare function resolveName(db: DatabaseSync, reader: Reader, raw: string, context?: ResolveContext): Resolution;
38
+ /** Every readable stub of another machine's object that `raw` (`<owner handle>/<name>`, `<type>:<owner handle>/<name>` or a bare name) names:
39
+ * empty when none does, more than one when the name is ambiguous. `resolveName` never answers a stub, so a stub cannot shadow a local
40
+ * object; this is the lookup a forwarding handler makes only after `resolveName` found no local object, to learn that the name belongs
41
+ * to an object another machine homes. */
42
+ export declare function stubsNamed(db: DatabaseSync, reader: Reader, raw: string): ObjectRow[];
@@ -1,3 +1,3 @@
1
- var j=Object.defineProperty;var m=(t,e)=>j(t,"name",{value:e,configurable:!0});import{prepared as R}from"../sqlite-statements.js";import{isSafeNodeId as I}from"../canvas/paths.js";import{canRead as y,toolApps as g}from"./access.js";import{getById as T}from"./objects.js";function _(t,e){const s=R(t,"SELECT * FROM objects WHERE type = 'person' AND name = 'user' AND home_machine IS NULL").get(),l=g(t,e),o=e.class==="node"?[e.node,...e.repos,...e.projectRepos,e.profile,e.app]:e.class==="app"?[e.app]:e.class==="object"?[e.owner,...e.repos,e.app]:[],a=new Set;return[...o,s,...l].filter(r=>!!r&&!a.has(r.rowid)&&!!a.add(r.rowid))}m(_,"viewOf");function E(t,e,s,l){return t.prepare(`SELECT * FROM objects WHERE (type = 'document' OR instr(type, '.') > 0) AND owner = ? AND name = ? AND home_machine IS NULL
2
- AND deleted_at IS ${l?"NOT NULL ORDER BY deleted_at DESC":"NULL"}`).all(e.rowid,s)}m(E,"namedObjects");const F=["person","app","repo","profile"],h=/^(person|app|repo|profile|node):([^/]+)\/(.+)$/;function x(t,e,s){return s==="node"?R(t,"SELECT * FROM objects WHERE type = 'node' AND id = ?").all(e):s?R(t,"SELECT * FROM objects WHERE type = ? AND (name = ? OR id = ?) AND home_machine IS NULL").all(s,e,e):R(t,`SELECT * FROM objects WHERE (type = 'node' AND id = ?)
3
- OR (type IN ('person','app','repo','profile') AND (name = ? OR id = ?) AND home_machine IS NULL)`).all(e,e,e)}m(x,"ownersByHandle");function W(t,e,s,l){let o=s.trim().replace(/^\[\[(.*)\]\]$/,"$1").trim();const a=/^([^:/]+):reports\/(.+?)(?:\.md)?$/.exec(o);a&&!h.test(o)&&(o=`${a[1]}/reports/${a[2]}`);const r=l?.readable??(c=>y(t,e,c)),u=T(t,o);if(u&&r(u))return u.deleted_at?{deleted:u}:{object:u};const L=l?.view??_(t,e);for(const c of L){const i=E(t,c,o,!1).find(r);if(i)return{object:i}}const p=h.exec(o),w=o.indexOf("/");if(p||w>0){const c=p?p[2]:o.slice(0,w),i=p?p[3]:o.slice(w+1),d=x(t,c,p?.[1]),D=m(n=>{const f=L.findIndex(O=>O.rowid===n.rowid);return f<0?1/0:f},"rank"),A=d.filter(n=>D(n)<1/0).sort((n,f)=>D(n)-D(f));for(const n of A){const f=E(t,n,i,!1).find(r);if(f)return{object:f}}const N=d.flatMap(n=>E(t,n,i,!1)).filter(r);if(N.length===1)return{object:N[0]};if(N.length>1)return{ambiguous:N};const S=d.flatMap(n=>E(t,n,i,!0)).find(r);return S?{deleted:S}:!p&&d.length===0&&I(c)?{remote:o}:{missing:!0}}for(const c of L){const i=E(t,c,o,!0).find(r);if(i)return{deleted:i}}return{missing:!0}}m(W,"resolveName");export{F as HANDLE_TYPES,x as ownersByHandle,W as resolveName,_ as viewOf};
1
+ var M=Object.defineProperty;var i=(t,e)=>M(t,"name",{value:e,configurable:!0});import{prepared as w}from"../sqlite-statements.js";import{isSafeNodeId as _}from"../canvas/paths.js";import{canRead as O,toolApps as $}from"./access.js";import{getById as H}from"./objects.js";function y(t,e){const n=w(t,"SELECT * FROM objects WHERE type = 'person' AND name = 'user' AND home_machine IS NULL").get(),p=$(t,e),o=e.class==="node"?[e.node,...e.repos,...e.projectRepos,e.profile,e.app]:e.class==="app"?[e.app]:e.class==="object"?[e.owner,...e.repos,e.app]:[],c=new Set;return[...o,n,...p].filter(r=>!!r&&!c.has(r.rowid)&&!!c.add(r.rowid))}i(y,"viewOf");function d(t,e,n,p,o=!1){return t.prepare(`SELECT * FROM objects WHERE (type = 'document' OR instr(type, '.') > 0) AND owner = ? AND name = ? AND home_machine IS ${o?"NOT NULL":"NULL"}
2
+ AND deleted_at IS ${p?"NOT NULL ORDER BY deleted_at DESC":"NULL"}`).all(e.rowid,n)}i(d,"namedObjects");const B=["person","app","repo","profile"],S=/^(person|app|repo|profile|node):([^/]+)\/(.+)$/,A=i(t=>t.trim().replace(/^\[\[(.*)\]\]$/,"$1").trim(),"unwrapRef");function j(t){const e=S.exec(t);if(e)return{type:e[1],handle:e[2],rest:e[3]};const n=t.indexOf("/");return n>0?{handle:t.slice(0,n),rest:t.slice(n+1)}:null}i(j,"splitOwnerRef");function I(t,e,n){return n==="node"?w(t,"SELECT * FROM objects WHERE type = 'node' AND id = ?").all(e):n?w(t,"SELECT * FROM objects WHERE type = ? AND (name = ? OR id = ?) AND home_machine IS NULL").all(n,e,e):w(t,`SELECT * FROM objects WHERE (type = 'node' AND id = ?)
3
+ OR (type IN ('person','app','repo','profile') AND (name = ? OR id = ?) AND home_machine IS NULL)`).all(e,e,e)}i(I,"ownersByHandle");function Y(t,e,n,p){let o=A(n);const c=/^([^:/]+):reports\/(.+?)(?:\.md)?$/.exec(o);c&&!S.test(o)&&(o=`${c[1]}/reports/${c[2]}`);const r=p?.readable??(f=>O(t,e,f)),a=H(t,o);if(a&&r(a))return a.deleted_at?{deleted:a}:{object:a};const N=p?.view??y(t,e);for(const f of N){const l=d(t,f,o,!1).find(r);if(l)return{object:l}}const m=j(o);if(m){const{type:f,handle:l,rest:L}=m,g=f!==void 0,E=I(t,l,f),h=i(s=>{const u=N.findIndex(T=>T.rowid===s.rowid);return u<0?1/0:u},"rank"),x=E.filter(s=>h(s)<1/0).sort((s,u)=>h(s)-h(u));for(const s of x){const u=d(t,s,L,!1).find(r);if(u)return{object:u}}const R=E.flatMap(s=>d(t,s,L,!1)).filter(r);if(R.length===1)return{object:R[0]};if(R.length>1)return{ambiguous:R};const D=E.flatMap(s=>d(t,s,L,!0)).find(r);return D?{deleted:D}:!g&&E.length===0&&_(l)?{remote:o}:{missing:!0}}for(const f of N){const l=d(t,f,o,!0).find(r);if(l)return{deleted:l}}return{missing:!0}}i(Y,"resolveName");function b(t,e,n){const p=A(n),o=i((a,N)=>a.flatMap(m=>d(t,m,N,!1,!0)).filter(m=>O(t,e,m)),"found"),c=o(y(t,e),p);if(c.length)return c;const r=j(p);return r?o(I(t,r.handle,r.type),r.rest):[]}i(b,"stubsNamed");export{B as HANDLE_TYPES,I as ownersByHandle,Y as resolveName,b as stubsNamed,A as unwrapRef,y as viewOf};
@@ -1,8 +1,8 @@
1
- var R=Object.defineProperty;var s=(r,e)=>R(r,"name",{value:e,configurable:!0});import{WebSocketServer as $}from"ws";import{isSafeNodeId as A}from"../../core/canvas/paths.js";import{getNode as S}from"../../core/canvas/index.js";import{BROKER_READ_CAPS as C,CLIENT_READ_CAPS as T,FrameDecoder as x,FrameOverflowError as B}from"../../core/runtime/broker-protocol.js";import{classify as k}from"../../core/fault-classifier.js";import{clearFault as v,markNodeRead as N,recordFault as g}from"../../core/canvas/recovery.js";import{decideAttachRevive as O}from"../../core/runtime/revive.js";import{connectViewSocket as P,probeViewSocket as F,waitForBrokerViewSocket as U}from"../../core/runtime/view-socket.js";import{isBeneathRefusal as D}from"../../core/spaces/open-beneath.js";import{attachViewer as _,detachViewer as V,presentViewer as L}from"./viewer-presence.js";const H=new $({noServer:!0,maxPayload:C.maxLineBytes}),M=25e3,J=6e4;function W(r,e=M,i=J){let o=!0,n=!1,a=Date.now();const f=s(()=>{o=!0},"acknowledge"),m=s(()=>{n||(n=!0,clearInterval(h),r.off("pong",f))},"stop");r.on("pong",f);const h=setInterval(()=>{if(Date.now()-a>i){o=!0;return}if(!o){m(),r.terminate();return}o=!1;try{r.ping()}catch{m(),r.terminate()}},e);return h.unref(),{stop:m,noteActivity:s(()=>{a=Date.now()},"noteActivity")}}s(W,"startRemoteAttachHeartbeat");function b(r){const e=Buffer.from(r,"utf8");return e.byteLength<=123?r:e.subarray(0,123).toString("utf8")}s(b,"clampReason");function u(r,e,i,o,n){const a=JSON.stringify({error:{code:o,message:n}}),f=`HTTP/1.1 ${e} ${i}\r
1
+ var R=Object.defineProperty;var s=(r,e)=>R(r,"name",{value:e,configurable:!0});import{WebSocketServer as $}from"ws";import{isSafeNodeId as A}from"../../core/canvas/paths.js";import{getNode as S}from"../../core/canvas/index.js";import{BROKER_READ_CAPS as C,CLIENT_READ_CAPS as T,FrameDecoder as x,FrameOverflowError as B}from"../../core/runtime/broker-protocol.js";import{classify as k}from"../../core/fault-classifier.js";import{clearFault as v,markNodeRead as N,recordFault as g}from"../../core/canvas/recovery.js";import{decideAttachRevive as O}from"../../core/runtime/revive.js";import{connectViewSocket as P,probeViewSocket as F,waitForBrokerViewSocket as U}from"../../core/runtime/view-socket.js";import{isBeneathRefusal as D}from"../../core/spaces/open-beneath.js";import{attachViewer as _,detachViewer as V,presentViewer as L}from"./viewer-presence.js";const H=new $({noServer:!0,maxPayload:C.maxLineBytes}),M=25e3,J=6e4;function W(r,e=M,i=J){let n=!0,o=!1,a=Date.now();const f=s(()=>{n=!0},"acknowledge"),m=s(()=>{o||(o=!0,clearInterval(h),r.off("pong",f))},"stop");r.on("pong",f);const h=setInterval(()=>{if(Date.now()-a>i){n=!0;return}if(!n){m(),r.terminate();return}n=!1;try{r.ping()}catch{m(),r.terminate()}},e);return h.unref(),{stop:m,noteActivity:s(()=>{a=Date.now()},"noteActivity")}}s(W,"startRemoteAttachHeartbeat");function b(r){const e=Buffer.from(r,"utf8");return e.byteLength<=123?r:e.subarray(0,123).toString("utf8")}s(b,"clampReason");function u(r,e,i,n,o){const a=JSON.stringify({error:{code:n,message:o,origin:"runtime"}}),f=`HTTP/1.1 ${e} ${i}\r
2
2
  content-type: application/json; charset=utf-8\r
3
3
  content-length: ${Buffer.byteLength(a)}\r
4
4
  connection: close\r
5
5
  \r
6
- `+a;try{r.end(f)}catch{try{r.destroy()}catch{}}}s(u,"refuseUpgrade");function j(r){if(new URL(r.url??"/","http://127.0.0.1").searchParams.get("revive")==="0")return!0;const i=r.headers["x-crtr-attach-revive"];return(Array.isArray(i)?i[0]:i)==="0"}s(j,"reviveOptedOut");function q(r){return new URL(r.url??"/","http://127.0.0.1").searchParams.get("wakeParked")==="1"}s(q,"wakeParkedRequested");function E(r){return r===1e3||r===1001||r===1005}s(E,"isCleanViewerClose");function z(r,e){if(!A(e)){try{r.close(1008,b(`invalid node id: ${e}`))}catch{}return}if(S(e)===null){try{r.close(1011,b(`no node ${e}`))}catch{}return}v(e,{link:"viewer\u2194crtrd"});const i=P(e),o=new x(T);let n=!1,a=!1,f,m=!1,h=!1,d=!1;i.on("connect",()=>{m=!0,!n&&d&&_(e,r),v(e,{link:"relay\u2194broker"})});const p=s((t,l)=>{if(!n){if(n=!0,V(e,r),f?.stop(),!i.destroyed)try{i.destroy()}catch{}try{r.close(t,b(l))}catch{}}},"teardown");f=W(r),i.on("data",t=>{f?.noteActivity();let l;try{l=o.push(t)}catch(c){const y=c instanceof B?`broker sent an oversized frame (${c.message})`:`failed to decode a broker frame for ${e}`;p(1009,y);return}for(const c of l)if(r.readyState===r.OPEN&&(r.send(JSON.stringify(c)),d&&c?.type==="welcome"&&L(e,r)))try{N(e)}catch{}}),i.on("error",t=>{const l=k("relay\u2194broker",t);g(e,{link:"relay\u2194broker",op:"bridge socket",kind:l.kind,retry:{disposition:"manual"},message:t.message});const c=t.code==="ECONNREFUSED"||t.code==="ENOENT"?`no running broker for ${e}`:`view socket error for ${e}: ${t.message}`;p(1011,c)}),i.on("close",t=>{n||t||(v(e,{link:"relay\u2194broker"}),p(1e3,"broker socket closed"))}),r.on("close",(t,l)=>{const c=l.toString("utf8");if(n){E(t)&&v(e,{link:"viewer\u2194crtrd"});return}if(E(t))v(e,{link:"viewer\u2194crtrd"});else if(!a){a=!0;const y=k("viewer\u2194crtrd",{code:t,reason:c});g(e,{link:"viewer\u2194crtrd",op:"remote attach websocket",kind:y.kind,retry:{disposition:"auto"},message:c||`remote attach closed (${t})`})}p(t,c||`remote attach closed (${t})`)}),r.on("error",()=>{if(!a){a=!0;const t=k("viewer\u2194crtrd",{code:1006,reason:"remote attach websocket error"});g(e,{link:"viewer\u2194crtrd",op:"remote attach websocket",kind:t.kind,retry:{disposition:"auto"},message:"remote attach websocket error"})}p(1011,"remote attach websocket error")}),r.on("message",t=>{if(n||i.destroyed)return;f?.noteActivity();const c=(Array.isArray(t)?Buffer.concat(t):Buffer.isBuffer(t)?t:Buffer.from(new Uint8Array(t))).toString("utf8");if(!h)try{const w=JSON.parse(c);w?.type==="hello"&&(h=!0,d=w.attends!==!1,d&&m&&_(e,r))}catch{}const y=c.endsWith(`
6
+ `+a;try{r.end(f)}catch{try{r.destroy()}catch{}}}s(u,"refuseUpgrade");function j(r){if(new URL(r.url??"/","http://127.0.0.1").searchParams.get("revive")==="0")return!0;const i=r.headers["x-crtr-attach-revive"];return(Array.isArray(i)?i[0]:i)==="0"}s(j,"reviveOptedOut");function q(r){return new URL(r.url??"/","http://127.0.0.1").searchParams.get("wakeParked")==="1"}s(q,"wakeParkedRequested");function E(r){return r===1e3||r===1001||r===1005}s(E,"isCleanViewerClose");function z(r,e){if(!A(e)){try{r.close(1008,b(`invalid node id: ${e}`))}catch{}return}if(S(e)===null){try{r.close(1011,b(`no node ${e}`))}catch{}return}v(e,{link:"viewer\u2194crtrd"});const i=P(e),n=new x(T);let o=!1,a=!1,f,m=!1,h=!1,d=!1;i.on("connect",()=>{m=!0,!o&&d&&_(e,r),v(e,{link:"relay\u2194broker"})});const p=s((t,l)=>{if(!o){if(o=!0,V(e,r),f?.stop(),!i.destroyed)try{i.destroy()}catch{}try{r.close(t,b(l))}catch{}}},"teardown");f=W(r),i.on("data",t=>{f?.noteActivity();let l;try{l=n.push(t)}catch(c){const y=c instanceof B?`broker sent an oversized frame (${c.message})`:`failed to decode a broker frame for ${e}`;p(1009,y);return}for(const c of l)if(r.readyState===r.OPEN&&(r.send(JSON.stringify(c)),d&&c?.type==="welcome"&&L(e,r)))try{N(e)}catch{}}),i.on("error",t=>{const l=k("relay\u2194broker",t);g(e,{link:"relay\u2194broker",op:"bridge socket",kind:l.kind,retry:{disposition:"manual"},message:t.message});const c=t.code==="ECONNREFUSED"||t.code==="ENOENT"?`no running broker for ${e}`:`view socket error for ${e}: ${t.message}`;p(1011,c)}),i.on("close",t=>{o||t||(v(e,{link:"relay\u2194broker"}),p(1e3,"broker socket closed"))}),r.on("close",(t,l)=>{const c=l.toString("utf8");if(o){E(t)&&v(e,{link:"viewer\u2194crtrd"});return}if(E(t))v(e,{link:"viewer\u2194crtrd"});else if(!a){a=!0;const y=k("viewer\u2194crtrd",{code:t,reason:c});g(e,{link:"viewer\u2194crtrd",op:"remote attach websocket",kind:y.kind,retry:{disposition:"auto"},message:c||`remote attach closed (${t})`})}p(t,c||`remote attach closed (${t})`)}),r.on("error",()=>{if(!a){a=!0;const t=k("viewer\u2194crtrd",{code:1006,reason:"remote attach websocket error"});g(e,{link:"viewer\u2194crtrd",op:"remote attach websocket",kind:t.kind,retry:{disposition:"auto"},message:"remote attach websocket error"})}p(1011,"remote attach websocket error")}),r.on("message",t=>{if(o||i.destroyed)return;f?.noteActivity();const c=(Array.isArray(t)?Buffer.concat(t):Buffer.isBuffer(t)?t:Buffer.from(new Uint8Array(t))).toString("utf8");if(!h)try{const w=JSON.parse(c);w?.type==="hello"&&(h=!0,d=w.attends!==!1,d&&m&&_(e,r))}catch{}const y=c.endsWith(`
7
7
  `)?c:c+`
8
- `;try{i.write(y)}catch{}})}s(z,"bridgeConnection");async function ne(r,e,i,o){e.on("error",()=>{});try{if(!A(o)){u(e,400,"Bad Request","invalid_node_id",`invalid node id: ${o}`);return}if(S(o)===null){u(e,404,"Not Found","node_not_found",`no node ${o}`);return}if(j(r)){if(!await F(o,250)){u(e,409,"Conflict","node_dormant",`node ${o} is dormant and revive was opted out (?revive=0)`);return}}else{let n;try{const a=await O(o,{resume:!0,capacity:"refuse"},q(r));if(a.parked){u(e,409,"Conflict","node_dormant",`node ${o} is parked; attach with ?wakeParked=1 to wake it`);return}n=a.result.launch?.exited}catch(a){const f=a instanceof Error?a.message:String(a);u(e,409,"Conflict","attach_revive_failed",`attach revive failed: ${f}`);return}if(!await U(o,n)){u(e,409,"Conflict","broker_not_ready",`broker view socket for ${o} did not become listenable after revive`);return}}if(e.destroyed)return;H.handleUpgrade(r,e,i,n=>z(n,o))}catch(n){const a=n instanceof Error?n.message:String(n);if(D(n)){u(e,400,"Bad Request","invalid_request",a);return}u(e,500,"Internal Server Error","internal",`attach upgrade failed: ${a}`)}}s(ne,"handleAttachUpgrade");export{M as REMOTE_ATTACH_HEARTBEAT_MS,J as REMOTE_ATTACH_QUIET_MS,ne as handleAttachUpgrade,E as isCleanViewerClose,u as refuseUpgrade,W as startRemoteAttachHeartbeat};
8
+ `;try{i.write(y)}catch{}})}s(z,"bridgeConnection");async function oe(r,e,i,n){e.on("error",()=>{});try{if(!A(n)){u(e,400,"Bad Request","invalid_node_id",`invalid node id: ${n}`);return}if(S(n)===null){u(e,404,"Not Found","node_not_found",`no node ${n}`);return}if(j(r)){if(!await F(n,250)){u(e,409,"Conflict","node_dormant",`node ${n} is dormant and revive was opted out (?revive=0)`);return}}else{let o;try{const a=await O(n,{resume:!0,capacity:"refuse"},q(r));if(a.parked){u(e,409,"Conflict","node_dormant",`node ${n} is parked; attach with ?wakeParked=1 to wake it`);return}o=a.result.launch?.exited}catch(a){const f=a instanceof Error?a.message:String(a);u(e,409,"Conflict","attach_revive_failed",`attach revive failed: ${f}`);return}if(!await U(n,o)){u(e,409,"Conflict","broker_not_ready",`broker view socket for ${n} did not become listenable after revive`);return}}if(e.destroyed)return;H.handleUpgrade(r,e,i,o=>z(o,n))}catch(o){const a=o instanceof Error?o.message:String(o);if(D(o)){u(e,400,"Bad Request","invalid_request",a);return}u(e,500,"Internal Server Error","internal",`attach upgrade failed: ${a}`)}}s(oe,"handleAttachUpgrade");export{M as REMOTE_ATTACH_HEARTBEAT_MS,J as REMOTE_ATTACH_QUIET_MS,oe as handleAttachUpgrade,E as isCleanViewerClose,u as refuseUpgrade,W as startRemoteAttachHeartbeat};
@@ -1,6 +1,6 @@
1
- var Y=Object.defineProperty;var l=(t,e)=>Y(t,"name",{value:e,configurable:!0});import{gzipSync as V}from"node:zlib";import{browseNodes as F,graphNodes as X,listNodes as G,pruneNodes as Z,pruneToLimit as ee,rosterEdges as w,rosterNodes as te}from"../../../core/canvas/canvas.js";import{activeBackgroundBashJobs as ne}from"../../../core/bash-jobs.js";import{contextDir as se}from"../../../core/canvas/node-agent-paths.js";import{nowIso as $}from"../../../core/fs-utils.js";import{isPidPresent as oe}from"../../../core/canvas/pid.js";import{dashboardRowsAllFromSource as re,enrichRowsFromSource as ie}from"../../../core/canvas/render-source.js";import{localCanvasSource as P}from"../../../core/canvas/source.js";import{ticketCountsForNodes as q,ticketsAcrossCanvas as ae}from"../../../core/canvas/attention.js";import{buildCorpus as de,groupCorpus as le,resolveRef as ce}from"../../../core/canvas/history.js";import{listFocuses as D,reapEmptyNodes as ue}from"../../../core/runtime/placement.js";import{boundFleet as fe}from"../../../core/runtime/fleet.js";import{retentionHold as pe}from"../../reconcilers/live-obligation.js";import{notFound as me,usage as _}from"../../../core/errors.js";import{openDb as he}from"../../../core/canvas/db.js";import{prepared as _e}from"../../../core/sqlite-statements.js";import{view as ye}from"../../../core/canvas/tree.js";import{isFinishedWork as ge,isLiveStatus as be}from"../../../core/canvas/node-order.js";import{readNodeRecap as ve}from"../../../core/canvas/node-recap.js";import{readGoal as ke}from"../../../core/runtime/kickoff.js";import{faultSummary as Se}from"../../../core/canvas/status-glyph.js";import{listPendingAsks as we}from"../../../core/human/requests.js";import{toGraphNodeDTO as Ne}from"../map.js";import{actsAsPerson as Re,canReadNode as O,canReadRun as Ce}from"../router.js";import{ApiError as T}from"../../../api/errors.js";function N(t){return t.principal.class==="person"?null:new Set(G().filter(e=>O(t.principal,e.grantee??"app:terminal",e.node_id)).map(e=>e.node_id))}l(N,"visibleNodes");function H(t){return t.principal.class==="person"?null:new Set(G().filter(e=>e.run_id?Ce(t.principal,e.grantee??"app:terminal",e.node_id):O(t.principal,e.grantee??"app:terminal",e.node_id)).map(e=>e.node_id))}l(H,"visibleHistoryNodes");function Me(t){const e=N(t);return{status:200,body:{items:ae().filter(s=>e===null||e.has(s.node_id)).map(s=>({node_id:s.node_id,name:s.name,cwd:s.cwd,count:s.count,subjects:s.subjects}))}}}l(Me,"handleAttention");function Le(t){const e=t.body;if(e===null||typeof e!="object"||!Array.isArray(e.node_ids))throw _("attention count request requires node_ids: string[]");const n=e.node_ids;if(!n.every(o=>typeof o=="string"))throw _("attention count request node_ids must contain only strings");const s=N(t);return{status:200,body:{counts:q(n.filter(o=>s===null||s.has(o)))}}}l(Le,"handleAttentionCounts");function z(t){return Buffer.from(String(t),"utf8").toString("base64")}l(z,"encodeCursor");function x(t){const e=Number(Buffer.from(t,"base64").toString("utf8"));if(!Number.isInteger(e)||e<0)throw _(`invalid cursor: ${t}`);return e}l(x,"decodeCursor");function $e(t,e,n){const a=t.loadBody().split(`
2
- `);if(e.length>0){const c=a.findIndex(u=>{const f=u.toLowerCase();return e.some(i=>f.includes(i))});if(c!==-1)return a.slice(c,c+n).map(u=>u.trim()).filter(u=>u!=="").join(" \u23CE ")}const o=a.map(c=>c.trim()).filter(c=>c!=="").slice(0,n).join(" \u23CE ");return o!==""?o:t.title}l($e,"snippet");function Be(t,e,n){const s=[...t];return e==="relevance"&&n!==void 0?s.sort((a,o)=>(n.get(o.ref)??0)-(n.get(a.ref)??0)||o.tsMs-a.tsMs||a.ref.localeCompare(o.ref)):e==="oldest"?s.sort((a,o)=>a.tsMs-o.tsMs||a.ref.localeCompare(o.ref)):s.sort((a,o)=>o.tsMs-a.tsMs||a.ref.localeCompare(o.ref)),s}l(Be,"sortArtifacts");function Ee(t){if(t==null)return{};if(typeof t!="object")throw _("history search body must be a JSON object");return t}l(Ee,"parseSearchBody");function Ie(t){if(t===null||typeof t!="object")throw _("history grep body must be a JSON object");const e=t;if(typeof e.pattern!="string"||e.pattern==="")throw _("history grep body requires a non-empty pattern");return e}l(Ie,"parseGrepBody");function j(t,e){const n={cwd:t.cwd,allCwds:t.all_cwds===!0,under:t.under,nodes:t.nodes},s={types:t.types,kinds:t.kinds,statuses:t.statuses,sinceMs:t.since_ms,untilMs:t.until_ms,origins:t.origins,roles:t.roles,from:t.from},a=H(e);return de(n,s).filter(o=>a===null||a.has(o.nodeId))}l(j,"buildCorpusFromQuery");function Oe(t){if(t==null)return{};if(typeof t!="object")throw _("history stats body must be a JSON object");return t}l(Oe,"parseStatsBody");const J=["origin","node","kind","day","type","role"];function Te(t){const e=Oe(t.body),n=e.group_by??"type";if(!J.includes(n))throw _(`--group-by must be one of: ${J.join(", ")}; received: ${String(e.group_by)}`);const s=j(e,t),a=le(s,n);return{status:200,body:{group_by:n,groups:a,total:a.reduce((c,u)=>c+u.count,0),scanned:s.length}}}l(Te,"handleHistoryStats");function je(t){const e=Ie(t.body),n=Math.min(100,Math.max(1,e.limit??20)),s=j(e,t),a=e.cursor!==void 0?x(e.cursor):0;let o;try{o=new RegExp(e.pattern,"i")}catch{throw _(`invalid regex pattern: ${e.pattern}`)}const c=[];for(const r of s)r.loadBody().split(`
3
- `).forEach((y,b)=>{o.test(y)&&c.push({ref:r.ref,node:`${r.nodeName} (${r.nodeId})`,ts:r.ts,line:b+1,text:y.trim()})});c.sort((r,d)=>r.ref.localeCompare(d.ref)||r.line-d.line);const u=c.slice(a,a+n),f=a+n<c.length?z(a+n):null;return{status:200,body:{hits:u,next_cursor:f,total:c.length}}}l(je,"handleHistoryGrep");function Ae(t){const e=Ee(t.body),n=(e.query??"").trim(),s=e.weigh_body===!0,a=e.full===!0,o=Math.max(1,e.snippet_lines??1),c=Math.min(100,Math.max(1,e.limit??20)),u=e.per_node===!0;if(u&&(e.nodes===void 0||e.nodes.length===0))throw new T(400,"invalid_request","`per_node` requires a non-empty `nodes` list",{param:"nodes"});const f=j(e,t),i=e.cursor!==void 0?x(e.cursor):0,r=n.toLowerCase().split(/\s+/).filter(p=>p.length>0);let d=f,y;const b=e.sort??(r.length>0?"relevance":"recency");if(r.length>0&&b==="relevance"){y=new Map;const p=[];for(const h of f){const I=h.title.toLowerCase(),W=h.nodeName.toLowerCase(),Q=h.nodeDesc.toLowerCase(),A=s?h.loadBody().toLowerCase():null;let S=0;for(const L of r)I.includes(L)&&(S+=10),W.includes(L)&&(S+=5),Q.includes(L)&&(S+=3),A!==null&&A.includes(L)&&(S+=1);S>0&&(y.set(h.ref,S),p.push(h))}d=p}else r.length>0&&(d=f.filter(p=>{const h=`${p.title}
4
- ${p.nodeName}
5
- ${p.nodeDesc}${s?`
6
- `+p.loadBody():""}`.toLowerCase();return r.some(I=>h.includes(I))}));let g=Be(d,b,y);if(u){const p=new Set;g=g.filter(h=>!p.has(h.nodeId)&&p.add(h.nodeId))}const M=u?g:g.slice(i,i+c),k=!u&&i+c<g.length?z(i+c):null;return{status:200,body:{hits:M.map(p=>{const h={ref:p.ref,node:`${p.nodeName} (${p.nodeId})`,kind:p.nodeKind,source:p.source,ts:p.ts,...u?{node_id:p.nodeId}:{}};return b==="relevance"&&y!==void 0&&(h.score=y.get(p.ref)??0),a?h.body=p.loadBody():h.snippet=$e(p,r,o),h}),next_cursor:k,total:g.length}}}l(Ae,"handleHistorySearch");function Fe(t){const e=(t.query.get("ref")??"").trim();if(!e.includes(":"))throw _(`ref must be <node-id>:inbox/<n>, <node-id>:session, or <node-id>:session/<n>; received: ${e}`,{received:e,next:"Get a valid ref from `crtr canvas history search`. Reports and documents are `crtr canvas read <name>`."});const n=ce(e);if(n===null)throw me(`no inbox entry or message for ref: ${e}`,{ref:e,next:"Re-run `crtr canvas history search` for a current ref. Reports and documents are `crtr canvas read <name>`."});if(H(t)?.has(n.nodeId)===!1)throw new T(404,"not_found","artifact not found");const s=n.source,o=t.query.get("format")==="raw"&&n.raw!==null?n.raw:n.body;return{status:200,body:{ref:e,node:`${n.nodeName} (${n.nodeId})`,source:s,ts:n.ts,content:o}}}l(Fe,"handleHistoryRead");function Ge(t){for(const[s]of t.query)if(s!=="live")throw _(`unknown snapshot query parameter: ${s}`);const e=t.query.getAll("live");if(e.length>1)throw _("live must appear at most once");const n=e[0];if(n===void 0||n==="false"||n==="0")return!1;if(n==="true"||n==="1")return!0;throw _("live must be true or false")}l(Ge,"snapshotLiveOnly");async function Pe(t){const e=new Set(D().map(r=>r.node_id)),n=N(t),s=(await re(P,e,Ge(t))).filter(r=>n===null||n.has(r.node_id)),a=q(s.map(r=>r.node_id));await ie(P,s,a);const o=s.map(r=>{const d=r.srcRow,y=d?.host_kind??"tmux";return{node_id:r.node_id,name:r.name,title:r.handle??r.name,description:r.description??null,kind:r.kind,mode:r.mode,lifecycle:r.lifecycle??d?.lifecycle,status:r.status,cwd:r.cwd,profile_id:r.profile_id??null,parent:d?.parent??null,created:r.created,host_kind:y,enterable:y==="broker",attention_count:r.asks,...d?.cycles!=null?{cycles:d.cycles}:{},...r.mtimeMs!==void 0?{last_activity:new Date(r.mtimeMs).toISOString()}:{},ctx_tokens:r.ctx_tokens,streaming:r.streaming??!1,jobs_active:d!==void 0&&oe(d.pi_pid)?ne(se(r.node_id)).length:0,waiting_for:d?.waiting_for??null,hanging:r.hanging??null,viewed:r.viewed??!1,final_report:d?.final_report??null,finalized_at:d?.finalized_at??null}}),c=new Map;for(const r of w()){const d=c.get(r.from_id);d===void 0?c.set(r.from_id,[r.to_id]):d.push(r.to_id)}const u=new Set(s.map(r=>r.node_id)),f=Object.fromEntries(s.map(r=>[r.node_id,(c.get(r.node_id)??[]).filter(d=>u.has(d))]));return{status:200,body:{generated_at:$(),nodes:o,subscriptions:f}}}l(Pe,"handleSnapshot");function K(){const t=te().map(n=>{const s=n.host_kind??"tmux";return{node_id:n.node_id,name:n.name,kind:n.kind,mode:n.mode,lifecycle:n.lifecycle,status:n.status,cwd:n.cwd,host_kind:s,enterable:s==="broker",parent:n.parent,created:n.created}}),e=w().map(n=>({from_id:n.from_id,to_id:n.to_id,active:n.active,created:n.created}));return{generated_at:$(),nodes:t,edges:e}}l(K,"buildRoster");let R=null,B=null;function qe(){return R===null?(R=Promise.resolve().then(()=>K()).finally(()=>{R=null}),R):(B===null&&(B=R.then(()=>K()).finally(()=>{B=null})),B)}l(qe,"rosterCoalesced");async function De(t){const e=await qe(),n=N(t);return n===null?{status:200,body:e}:{status:200,body:{...e,nodes:e.nodes.filter(s=>n.has(s.node_id)),edges:e.edges.filter(s=>n.has(s.from_id)&&n.has(s.to_id))}}}l(De,"handleRoster");function U(t){if(t.name!==""&&t.name!==t.kind)return t.name;const e=(t.description??"").trim();return e!==""?e:t.name}l(U,"liveRootName");function He(){const t=F(),e=new Map(t.map(i=>[i.node_id,i])),n=new Map(_e(he(),"SELECT node_id, reply_at, read_at FROM nodes WHERE parent IS NULL").all().map(i=>[i.node_id,i])),s=t.filter(i=>i.parent===null&&i.kind!=="human"&&(be(i.status)||!ge({lifecycle:i.lifecycle,finalized:i.final_report!=null}))),a=we(),o=new Map;for(const i of a)o.set(i.requester_node_id,(o.get(i.requester_node_id)??0)+1);const c=new Map;for(const i of w())c.set(i.from_id,[...c.get(i.from_id)??[],i.to_id]);const u=l(i=>{const r=e.get(i)?.fault;return r&&r.link!=="broker\u2194crtrd"?Se(r):null},"faultOf"),f=s.map(i=>{const r=[i.node_id,...ye(i.node_id)].filter(m=>e.get(m)?.kind!=="human"&&e.has(m)),d=new Set(r),y=a.filter(m=>d.has(m.requester_node_id)),b=n.get(i.node_id),g=b?.reply_at??null,M=b?.read_at??null;let k=i.created;for(const m of r){const v=e.get(m).telemetry_updated_at;v!=null&&v>k&&(k=v)}return g!==null&&g>k&&(k=g),{node_id:i.node_id,name:U(i),cwd:i.cwd,profile_id:i.profile_id,status:i.status,state_line:(()=>{const m=ve(i.node_id)?.state.trim();return m||null})(),goal:ke(i.node_id)?.trim()||null,asks:y.length,first_ask_ticket_id:y[0]?.inbox_ticket_id??null,fault:r.map(u).find(m=>m!==null)??null,running_count:r.filter(m=>e.get(m).streaming===!0).length,unread:g!==null&&(M===null||g>M),last_activity:k,children:(c.get(i.node_id)??[]).filter(m=>e.has(m)&&e.get(m).kind!=="human").map(m=>{const v=e.get(m);return{node_id:m,name:U(v),status:v.status,streaming:v.streaming===!0,asks:o.get(m)??0,fault:u(m)}})}});return{generated_at:$(),rows:f}}l(He,"buildLiveRoots");let C=null,E=null;function ze(){const t=l(()=>Promise.resolve().then(He),"run");return C===null?(C=t().finally(()=>{C=null}),C):(E===null&&(E=C.then(t).finally(()=>{E=null})),E)}l(ze,"liveRootsCoalesced");async function xe(t){if(!Re(t.principal))throw new T(403,"permission_error","only the person reads the dashboard");const e=await ze(),n=t.query.get("profile");return{status:200,body:n===null?e:{...e,rows:e.rows.filter(s=>s.profile_id===n)}}}l(xe,"handleLiveRoots");function Je(t){const e=F().filter(o=>t.principal.class==="person"||O(t.principal,o.grantee??"app:terminal",o.node_id)).map(o=>({node_id:o.node_id,name:o.name,description:o.description,kind:o.kind,mode:o.mode,lifecycle:o.lifecycle,status:o.status,cwd:o.cwd,profile_id:o.profile_id,grantee:o.grantee??"app:terminal",parent:o.parent,created:o.created,frozen_at:o.frozen_at??null,terminal_reason:o.terminal_reason??null,final_report:o.final_report??null,telemetry_tokens_in:o.telemetry_tokens_in??null,telemetry_updated_at:o.telemetry_updated_at??null,fault:o.fault&&o.fault.link!=="broker\u2194crtrd"?{...o.fault,link:o.fault.link}:null,streaming:o.streaming??!1})),n=new Set(e.map(o=>o.node_id)),s=w().filter(o=>n.has(o.from_id)&&n.has(o.to_id));return{status:200,rawBody:V(JSON.stringify({nodes:e,edges:s}),{level:1}),headers:{"content-type":"application/gzip"}}}l(Je,"handleBrowse");function Ke(t){const e=N(t);return{status:200,body:{generated_at:$(),nodes:X().filter(s=>e===null||e.has(s.node_id)).map(Ne),edges:w().filter(s=>e===null||e.has(s.from_id)&&e.has(s.to_id)).map(s=>({from_id:s.from_id,to_id:s.to_id,active:s.active,created:s.created})),focused_node_ids:D().map(s=>s.node_id).filter(s=>e===null||e.has(s))}}}l(Ke,"handleGraph");function Ue(t){if(t==null)return{};if(typeof t!="object")throw _("prune body must be a JSON object");const e=t,n=l(r=>{const d=e[r];if(d!==void 0){if(typeof d!="number"||!Number.isFinite(d))throw _(`${r} must be a number`);return d}},"num"),s=l(r=>{const d=e[r];if(d!==void 0){if(typeof d!="boolean")throw _(`${r} must be a boolean`);return d}},"bool"),a={},o=n("limit");o!==void 0&&(a.limit=o);const c=n("ttl_days");c!==void 0&&(a.ttl_days=c);const u=s("include_stale");u!==void 0&&(a.include_stale=u);const f=s("empty");f!==void 0&&(a.empty=f);const i=s("dry_run");return i!==void 0&&(a.dry_run=i),a}l(Ue,"parsePruneBody");function We(t){const e=Ue(t.body),n=e.ttl_days??14,s=e.dry_run??!1,a=pe(fe());let o;return e.limit!==void 0?o=ee({maxNodes:e.limit,held:a,dryRun:s}).pruned.map(f=>({node_id:f.node_id,status:f.status,created:f.created})):e.empty===!0?o=ue({dryRun:s}).map(f=>({node_id:f,status:"empty",created:""})):o=Z({ttlDays:n,held:a,dryRun:s,includeStale:e.include_stale??!1}).pruned.map(f=>({node_id:f.node_id,status:f.status,created:f.created})),{status:200,body:{pruned:o,dry_run:s,ttl_days:n}}}l(We,"handlePrune");const kt=[{method:"GET",pattern:"/v1/canvas/attention",handler:Me},{method:"POST",pattern:"/v1/canvas/attention/counts",handler:Le},{method:"POST",pattern:"/v1/canvas/history/search",handler:Ae},{method:"POST",pattern:"/v1/canvas/history/grep",handler:je},{method:"GET",pattern:"/v1/canvas/history/read",handler:Fe},{method:"POST",pattern:"/v1/canvas/history/stats",handler:Te},{method:"GET",pattern:"/v1/canvas/snapshot",handler:Pe},{method:"GET",pattern:"/v1/canvas/roster",handler:De},{method:"GET",pattern:"/v1/canvas/live-roots",handler:xe},{method:"GET",pattern:"/v1/canvas/browse",handler:Je},{method:"GET",pattern:"/v1/canvas/graph",handler:Ke},{method:"POST",pattern:"/v1/canvas/prune",ownerOnly:!0,handler:We}];export{kt as canvasRoutes,Je as handleBrowse};
1
+ var Y=Object.defineProperty;var l=(t,e)=>Y(t,"name",{value:e,configurable:!0});import{gzipSync as V}from"node:zlib";import{browseNodes as P,graphNodes as X,listNodes as F,pruneNodes as Z,pruneToLimit as ee,rosterEdges as w,rosterNodes as te}from"../../../core/canvas/canvas.js";import{activeBackgroundBashJobs as ne}from"../../../core/bash-jobs.js";import{contextDir as se}from"../../../core/canvas/node-agent-paths.js";import{nowIso as L}from"../../../core/fs-utils.js";import{isPidPresent as oe}from"../../../core/canvas/pid.js";import{dashboardRowsAllFromSource as re,enrichRowsFromSource as ie}from"../../../core/canvas/render-source.js";import{localCanvasSource as G}from"../../../core/canvas/source.js";import{ticketCountsForNodes as q,ticketsAcrossCanvas as ae}from"../../../core/canvas/attention.js";import{buildCorpus as de,groupCorpus as le,resolveRef as ue}from"../../../core/canvas/history.js";import{listFocuses as D,reapEmptyNodes as ce}from"../../../core/runtime/placement.js";import{boundFleet as fe}from"../../../core/runtime/fleet.js";import{retentionHold as pe}from"../../reconcilers/live-obligation.js";import{notFound as me,usage as _}from"../../../core/errors.js";import{openDb as _e}from"../../../core/canvas/db.js";import{prepared as he}from"../../../core/sqlite-statements.js";import{view as ye}from"../../../core/canvas/tree.js";import{isLiveStatus as ge}from"../../../core/canvas/node-order.js";import{readNodeRecap as be}from"../../../core/canvas/node-recap.js";import{readGoal as ve}from"../../../core/runtime/kickoff.js";import{faultSummary as ke}from"../../../core/canvas/status-glyph.js";import{listPendingAsks as Se}from"../../../core/human/requests.js";import{toGraphNodeDTO as we}from"../map.js";import{actsAsPerson as Re,canReadNode as B,canReadRun as Ne}from"../router.js";import{ApiError as T}from"../../../api/errors.js";function R(t){return t.principal.class==="person"?null:new Set(F().filter(e=>B(t.principal,e.grantee??"app:terminal",e.node_id)).map(e=>e.node_id))}l(R,"visibleNodes");function H(t){return t.principal.class==="person"?null:new Set(F().filter(e=>e.run_id?Ne(t.principal,e.grantee??"app:terminal",e.node_id):B(t.principal,e.grantee??"app:terminal",e.node_id)).map(e=>e.node_id))}l(H,"visibleHistoryNodes");function Ce(t){const e=R(t);return{status:200,body:{items:ae().filter(s=>e===null||e.has(s.node_id)).map(s=>({node_id:s.node_id,name:s.name,cwd:s.cwd,count:s.count,subjects:s.subjects}))}}}l(Ce,"handleAttention");function Me(t){const e=t.body;if(e===null||typeof e!="object"||!Array.isArray(e.node_ids))throw _("attention count request requires node_ids: string[]");const n=e.node_ids;if(!n.every(r=>typeof r=="string"))throw _("attention count request node_ids must contain only strings");const s=R(t);return{status:200,body:{counts:q(n.filter(r=>s===null||s.has(r)))}}}l(Me,"handleAttentionCounts");function x(t){return Buffer.from(String(t),"utf8").toString("base64")}l(x,"encodeCursor");function z(t){const e=Number(Buffer.from(t,"base64").toString("utf8"));if(!Number.isInteger(e)||e<0)throw _(`invalid cursor: ${t}`);return e}l(z,"decodeCursor");function Le(t,e,n){const a=t.loadBody().split(`
2
+ `);if(e.length>0){const u=a.findIndex(p=>{const f=p.toLowerCase();return e.some(h=>f.includes(h))});if(u!==-1)return a.slice(u,u+n).map(p=>p.trim()).filter(p=>p!=="").join(" \u23CE ")}const r=a.map(u=>u.trim()).filter(u=>u!=="").slice(0,n).join(" \u23CE ");return r!==""?r:t.title}l(Le,"snippet");function Ee(t,e,n){const s=[...t];return e==="relevance"&&n!==void 0?s.sort((a,r)=>(n.get(r.ref)??0)-(n.get(a.ref)??0)||r.tsMs-a.tsMs||a.ref.localeCompare(r.ref)):e==="oldest"?s.sort((a,r)=>a.tsMs-r.tsMs||a.ref.localeCompare(r.ref)):s.sort((a,r)=>r.tsMs-a.tsMs||a.ref.localeCompare(r.ref)),s}l(Ee,"sortArtifacts");function Ie(t){if(t==null)return{};if(typeof t!="object")throw _("history search body must be a JSON object");return t}l(Ie,"parseSearchBody");function Oe(t){if(t===null||typeof t!="object")throw _("history grep body must be a JSON object");const e=t;if(typeof e.pattern!="string"||e.pattern==="")throw _("history grep body requires a non-empty pattern");return e}l(Oe,"parseGrepBody");function j(t,e){const n={cwd:t.cwd,allCwds:t.all_cwds===!0,under:t.under,nodes:t.nodes},s={types:t.types,kinds:t.kinds,statuses:t.statuses,sinceMs:t.since_ms,untilMs:t.until_ms,origins:t.origins,roles:t.roles,from:t.from},a=H(e);return de(n,s).filter(r=>a===null||a.has(r.nodeId))}l(j,"buildCorpusFromQuery");function $e(t){if(t==null)return{};if(typeof t!="object")throw _("history stats body must be a JSON object");return t}l($e,"parseStatsBody");const J=["origin","node","kind","day","type","role"];function Be(t){const e=$e(t.body),n=e.group_by??"type";if(!J.includes(n))throw _(`--group-by must be one of: ${J.join(", ")}; received: ${String(e.group_by)}`);const s=j(e,t),a=le(s,n);return{status:200,body:{group_by:n,groups:a,total:a.reduce((u,p)=>u+p.count,0),scanned:s.length}}}l(Be,"handleHistoryStats");function Te(t){const e=Oe(t.body),n=Math.min(100,Math.max(1,e.limit??20)),s=j(e,t),a=e.cursor!==void 0?z(e.cursor):0;let r;try{r=new RegExp(e.pattern,"i")}catch{throw _(`invalid regex pattern: ${e.pattern}`)}const u=[];for(const i of s)i.loadBody().split(`
3
+ `).forEach((c,b)=>{r.test(c)&&u.push({ref:i.ref,node:`${i.nodeName} (${i.nodeId})`,ts:i.ts,line:b+1,text:c.trim()})});u.sort((i,o)=>i.ref.localeCompare(o.ref)||i.line-o.line);const p=u.slice(a,a+n),f=a+n<u.length?x(a+n):null;return{status:200,body:{hits:p,next_cursor:f,total:u.length}}}l(Te,"handleHistoryGrep");function je(t){const e=Ie(t.body),n=(e.query??"").trim(),s=e.weigh_body===!0,a=e.full===!0,r=Math.max(1,e.snippet_lines??1),u=Math.min(100,Math.max(1,e.limit??20)),p=e.per_node===!0;if(p&&(e.nodes===void 0||e.nodes.length===0))throw new T(400,"invalid_request","`per_node` requires a non-empty `nodes` list",{param:"nodes"});const f=j(e,t),h=e.cursor!==void 0?z(e.cursor):0,i=n.toLowerCase().split(/\s+/).filter(d=>d.length>0);let o=f,c;const b=e.sort??(i.length>0?"relevance":"recency");if(i.length>0&&b==="relevance"){c=new Map;const d=[];for(const m of f){const $=m.title.toLowerCase(),Q=m.nodeName.toLowerCase(),W=m.nodeDesc.toLowerCase(),A=s?m.loadBody().toLowerCase():null;let S=0;for(const M of i)$.includes(M)&&(S+=10),Q.includes(M)&&(S+=5),W.includes(M)&&(S+=3),A!==null&&A.includes(M)&&(S+=1);S>0&&(c.set(m.ref,S),d.push(m))}o=d}else i.length>0&&(o=f.filter(d=>{const m=`${d.title}
4
+ ${d.nodeName}
5
+ ${d.nodeDesc}${s?`
6
+ `+d.loadBody():""}`.toLowerCase();return i.some($=>m.includes($))}));let g=Ee(o,b,c);if(p){const d=new Set;g=g.filter(m=>!d.has(m.nodeId)&&d.add(m.nodeId))}const v=p?g:g.slice(h,h+u),y=!p&&h+u<g.length?x(h+u):null;return{status:200,body:{hits:v.map(d=>{const m={ref:d.ref,node:`${d.nodeName} (${d.nodeId})`,kind:d.nodeKind,source:d.source,ts:d.ts,...p?{node_id:d.nodeId}:{}};return b==="relevance"&&c!==void 0&&(m.score=c.get(d.ref)??0),a?m.body=d.loadBody():m.snippet=Le(d,i,r),m}),next_cursor:y,total:g.length}}}l(je,"handleHistorySearch");function Ae(t){const e=(t.query.get("ref")??"").trim();if(!e.includes(":"))throw _(`ref must be <node-id>:inbox/<n>, <node-id>:session, or <node-id>:session/<n>; received: ${e}`,{received:e,next:"Get a valid ref from `crtr canvas history search`. Reports and documents are `crtr canvas read <name>`."});const n=ue(e);if(n===null)throw me(`no inbox entry or message for ref: ${e}`,{ref:e,next:"Re-run `crtr canvas history search` for a current ref. Reports and documents are `crtr canvas read <name>`."});if(H(t)?.has(n.nodeId)===!1)throw new T(404,"not_found","artifact not found");const s=n.source,r=t.query.get("format")==="raw"&&n.raw!==null?n.raw:n.body;return{status:200,body:{ref:e,node:`${n.nodeName} (${n.nodeId})`,source:s,ts:n.ts,content:r}}}l(Ae,"handleHistoryRead");function Pe(t){for(const[s]of t.query)if(s!=="live")throw _(`unknown snapshot query parameter: ${s}`);const e=t.query.getAll("live");if(e.length>1)throw _("live must appear at most once");const n=e[0];if(n===void 0||n==="false"||n==="0")return!1;if(n==="true"||n==="1")return!0;throw _("live must be true or false")}l(Pe,"snapshotLiveOnly");async function Fe(t){const e=new Set(D().map(i=>i.node_id)),n=R(t),s=(await re(G,e,Pe(t))).filter(i=>n===null||n.has(i.node_id)),a=q(s.map(i=>i.node_id));await ie(G,s,a);const r=s.map(i=>{const o=i.srcRow,c=o?.host_kind??"tmux";return{node_id:i.node_id,name:i.name,title:i.handle??i.name,description:i.description??null,kind:i.kind,mode:i.mode,lifecycle:i.lifecycle??o?.lifecycle,status:i.status,cwd:i.cwd,profile_id:i.profile_id??null,parent:o?.parent??null,created:i.created,host_kind:c,enterable:c==="broker",attention_count:i.asks,...o?.cycles!=null?{cycles:o.cycles}:{},...i.mtimeMs!==void 0?{last_activity:new Date(i.mtimeMs).toISOString()}:{},ctx_tokens:i.ctx_tokens,streaming:i.streaming??!1,jobs_active:o!==void 0&&oe(o.pi_pid)?ne(se(i.node_id)).length:0,waiting_for:o?.waiting_for??null,hanging:i.hanging??null,viewed:i.viewed??!1,final_report:o?.final_report??null,finalized_at:o?.finalized_at??null}}),u=new Map;for(const i of w()){const o=u.get(i.from_id);o===void 0?u.set(i.from_id,[i.to_id]):o.push(i.to_id)}const p=new Set(s.map(i=>i.node_id)),f=Object.fromEntries(s.map(i=>[i.node_id,(u.get(i.node_id)??[]).filter(o=>p.has(o))]));return{status:200,body:{generated_at:L(),nodes:r,subscriptions:f}}}l(Fe,"handleSnapshot");function K(){const t=te().map(n=>{const s=n.host_kind??"tmux";return{node_id:n.node_id,name:n.name,kind:n.kind,mode:n.mode,lifecycle:n.lifecycle,status:n.status,cwd:n.cwd,host_kind:s,enterable:s==="broker",parent:n.parent,created:n.created}}),e=w().map(n=>({from_id:n.from_id,to_id:n.to_id,active:n.active,created:n.created}));return{generated_at:L(),nodes:t,edges:e}}l(K,"buildRoster");let N=null,E=null;function Ge(){return N===null?(N=Promise.resolve().then(()=>K()).finally(()=>{N=null}),N):(E===null&&(E=N.then(()=>K()).finally(()=>{E=null})),E)}l(Ge,"rosterCoalesced");async function qe(t){const e=await Ge(),n=R(t);return n===null?{status:200,body:e}:{status:200,body:{...e,nodes:e.nodes.filter(s=>n.has(s.node_id)),edges:e.edges.filter(s=>n.has(s.from_id)&&n.has(s.to_id))}}}l(qe,"handleRoster");function U(t){if(t.name!==""&&t.name!==t.kind)return t.name;const e=(t.description??"").trim();return e!==""?e:t.name}l(U,"liveRootName");const De=1440*6e4;function He(){const t=P(),e=new Map(t.map(o=>[o.node_id,o])),n=new Map(he(_e(),"SELECT node_id, reply_at, read_at, intent FROM nodes WHERE parent IS NULL").all().map(o=>[o.node_id,o])),s=Se(),a=new Map;for(const o of s)a.set(o.requester_node_id,(a.get(o.requester_node_id)??0)+1);const r=new Date(Date.now()-De).toISOString(),u=l(o=>{const c=n.get(o.node_id);return c?.reply_at!=null&&(c.read_at==null||c.reply_at>c.read_at)||(a.get(o.node_id)??0)>0?!0:o.status!=="done"||c?.intent!=="parked"?!1:[o.created,o.telemetry_updated_at,c.reply_at].reduce((v,y)=>y!=null&&y>v?y:v,"")>=r},"keepFinished"),p=t.filter(o=>o.parent===null&&o.kind!=="human"&&(ge(o.status)||u(o))),f=new Map;for(const o of w())f.set(o.from_id,[...f.get(o.from_id)??[],o.to_id]);const h=l(o=>{const c=e.get(o)?.fault;return c&&c.link!=="broker\u2194crtrd"?ke(c):null},"faultOf"),i=p.map(o=>{const c=[o.node_id,...ye(o.node_id)].filter(d=>e.get(d)?.kind!=="human"&&e.has(d)),b=new Set(c),g=s.filter(d=>b.has(d.requester_node_id)),v=n.get(o.node_id),y=v?.reply_at??null,O=v?.read_at??null;let k=o.created;for(const d of c){const m=e.get(d).telemetry_updated_at;m!=null&&m>k&&(k=m)}return y!==null&&y>k&&(k=y),{node_id:o.node_id,name:U(o),cwd:o.cwd,profile_id:o.profile_id,status:o.status,state_line:(()=>{const d=be(o.node_id)?.state.trim();return d||null})(),goal:ve(o.node_id)?.trim()||null,asks:g.length,first_ask_ticket_id:g[0]?.inbox_ticket_id??null,fault:c.map(h).find(d=>d!==null)??null,running_count:c.filter(d=>e.get(d).streaming===!0).length,unread:y!==null&&(O===null||y>O),last_activity:k,children:(f.get(o.node_id)??[]).filter(d=>e.has(d)&&e.get(d).kind!=="human").map(d=>{const m=e.get(d);return{node_id:d,name:U(m),status:m.status,streaming:m.streaming===!0,asks:a.get(d)??0,fault:h(d)}})}});return{generated_at:L(),rows:i}}l(He,"buildLiveRoots");let C=null,I=null;function xe(){const t=l(()=>Promise.resolve().then(He),"run");return C===null?(C=t().finally(()=>{C=null}),C):(I===null&&(I=C.then(t).finally(()=>{I=null})),I)}l(xe,"liveRootsCoalesced");async function ze(t){if(!Re(t.principal))throw new T(403,"permission_error","only the person reads the dashboard");const e=await xe(),n=t.query.get("profile");return{status:200,body:n===null?e:{...e,rows:e.rows.filter(s=>s.profile_id===n)}}}l(ze,"handleLiveRoots");function Je(t){const e=P().filter(r=>t.principal.class==="person"||B(t.principal,r.grantee??"app:terminal",r.node_id)).map(r=>({node_id:r.node_id,name:r.name,description:r.description,kind:r.kind,mode:r.mode,lifecycle:r.lifecycle,status:r.status,cwd:r.cwd,profile_id:r.profile_id,grantee:r.grantee??"app:terminal",parent:r.parent,created:r.created,frozen_at:r.frozen_at??null,terminal_reason:r.terminal_reason??null,final_report:r.final_report??null,telemetry_tokens_in:r.telemetry_tokens_in??null,telemetry_updated_at:r.telemetry_updated_at??null,fault:r.fault&&r.fault.link!=="broker\u2194crtrd"?{...r.fault,link:r.fault.link}:null,streaming:r.streaming??!1})),n=new Set(e.map(r=>r.node_id)),s=w().filter(r=>n.has(r.from_id)&&n.has(r.to_id));return{status:200,rawBody:V(JSON.stringify({nodes:e,edges:s}),{level:1}),headers:{"content-type":"application/gzip"}}}l(Je,"handleBrowse");function Ke(t){const e=R(t);return{status:200,body:{generated_at:L(),nodes:X().filter(s=>e===null||e.has(s.node_id)).map(we),edges:w().filter(s=>e===null||e.has(s.from_id)&&e.has(s.to_id)).map(s=>({from_id:s.from_id,to_id:s.to_id,active:s.active,created:s.created})),focused_node_ids:D().map(s=>s.node_id).filter(s=>e===null||e.has(s))}}}l(Ke,"handleGraph");function Ue(t){if(t==null)return{};if(typeof t!="object")throw _("prune body must be a JSON object");const e=t,n=l(i=>{const o=e[i];if(o!==void 0){if(typeof o!="number"||!Number.isFinite(o))throw _(`${i} must be a number`);return o}},"num"),s=l(i=>{const o=e[i];if(o!==void 0){if(typeof o!="boolean")throw _(`${i} must be a boolean`);return o}},"bool"),a={},r=n("limit");r!==void 0&&(a.limit=r);const u=n("ttl_days");u!==void 0&&(a.ttl_days=u);const p=s("include_stale");p!==void 0&&(a.include_stale=p);const f=s("empty");f!==void 0&&(a.empty=f);const h=s("dry_run");return h!==void 0&&(a.dry_run=h),a}l(Ue,"parsePruneBody");function Qe(t){const e=Ue(t.body),n=e.ttl_days??14,s=e.dry_run??!1,a=pe(fe());let r;return e.limit!==void 0?r=ee({maxNodes:e.limit,held:a,dryRun:s}).pruned.map(f=>({node_id:f.node_id,status:f.status,created:f.created})):e.empty===!0?r=ce({dryRun:s}).map(f=>({node_id:f,status:"empty",created:""})):r=Z({ttlDays:n,held:a,dryRun:s,includeStale:e.include_stale??!1}).pruned.map(f=>({node_id:f.node_id,status:f.status,created:f.created})),{status:200,body:{pruned:r,dry_run:s,ttl_days:n}}}l(Qe,"handlePrune");const kt=[{method:"GET",pattern:"/v1/canvas/attention",handler:Ce},{method:"POST",pattern:"/v1/canvas/attention/counts",handler:Me},{method:"POST",pattern:"/v1/canvas/history/search",handler:je},{method:"POST",pattern:"/v1/canvas/history/grep",handler:Te},{method:"GET",pattern:"/v1/canvas/history/read",handler:Ae},{method:"POST",pattern:"/v1/canvas/history/stats",handler:Be},{method:"GET",pattern:"/v1/canvas/snapshot",handler:Fe},{method:"GET",pattern:"/v1/canvas/roster",handler:qe},{method:"GET",pattern:"/v1/canvas/live-roots",handler:ze},{method:"GET",pattern:"/v1/canvas/browse",handler:Je},{method:"GET",pattern:"/v1/canvas/graph",handler:Ke},{method:"POST",pattern:"/v1/canvas/prune",ownerOnly:!0,handler:Qe}];export{kt as canvasRoutes,Je as handleBrowse};
@@ -1,3 +1,3 @@
1
- var Re=Object.defineProperty;var l=(e,t)=>Re(e,"name",{value:t,configurable:!0});import{prepared as $e}from"../../../core/sqlite-statements.js";import{ApiError as y}from"../../../api/errors.js";import{PRIVACY_LEVELS_DTO as Ie}from"../../../api/dto/objects.js";import{openDb as T,withCanvasWrite as _}from"../../../core/canvas/db.js";import{actorOf as ee}from"../../../core/graph/documents.js";import{readerForObject as D,readerFor as Se}from"../../../core/graph/reader.js";import{resolveName as Ae}from"../../../core/graph/names.js";import{canRead as te,customReachable as Ne,holdsObjectsScope as Fe,mayActAs as ne}from"../../../core/graph/access.js";import{customObjectRef as re,authorizeCustom as oe,fenceArgv as M}from"./custom-objects.js";import{edgesOf as Le}from"../../../core/graph/edges.js";import{publish as G}from"../../../core/graph/events.js";import{objectDTO as g}from"../../../core/graph/kinds/dto.js";import{isKind as We,kindNames as Pe,kindOf as z}from"../../../core/graph/kinds/registry.js";import{listObjects as Ce,searchObjects as ie}from"../../../core/graph/objects.js";import{checkoutsForCwd as De}from"../../../core/graph/repo-sync/repos.js";import{recordWatch as W,unwatch as Me,watchersOf as Ge,watchesOf as ze}from"../../../core/graph/watches.js";import{readerFor as v,resolveRef as H}from"../reader.js";import{readDelegationFor as se,runReadLeaf as He}from"../../plugin-objects/read-leaf.js";import{invalidRequest as P,isRecord as R}from"./validate.js";import{callerNode as ue,callerStub as U,forwardVerb as ae,originates as ce,queryWithoutMachine as V,relayError as C,remoteStub as Ue,unknownError as le,forwarding as F,withMachine as B}from"../../peer/forward.js";import{getById as L,getByRowid as fe}from"../../../core/graph/objects.js";import{ensureNodeStub as Ve,isStub as K,stubOf as Be,withKindDecl as $}from"../../../core/peer/stubs.js";import{isUnreachable as Ke}from"../../../core/peer/client.js";import{normalizeMachineId as I}from"../../../core/peer/directory.js";const S=l(e=>t=>De(e,t),"reposFnFor");function de(e,t){return{...g(e,t),...z(e,t.type).listItem?.(e,t)}}l(de,"listItem");function Ze(e){return`no object named ${e} on this runtime; it may be on another runtime, or the name may be misspelled`}l(Ze,"remoteMessage");function me(e,t,r){try{return q(e,t,r)}catch(n){if(n instanceof y&&n.code==="not_found"&&!n.details?.deleted)return null;throw n}}l(me,"ownerFilter");function q(e,t,r){const n=H(e,t,r);if("remote"in n)throw new y(404,"not_found",Ze(n.remote),{next:"Check the name with `crtr canvas search`."});if("deleted"in n)throw new y(404,"not_found",`${n.deleted.name} is deleted`,{id:n.deleted.id,deleted:!0});return n}l(q,"liveRef");const k=l(e=>decodeURIComponent(e.params.ref),"refParam"),he=l(e=>{const t=e.trim().replace(/^\[\[(.*)\]\]$/,"$1").trim(),r=t.indexOf("/");return r>0?t.slice(0,r):t},"idOf");function pe(e){const t=L(T(),he(e));return t!==null&&K(T(),t)?t.id:null}l(pe,"stubIdOf");function Je(e,t){const r=pe(e);return r!==null?{stub:r,hit:!0}:_(n=>{try{const o=H(n,v(n,t),e);if("remote"in o)return{stub:null,hit:!1};const i="deleted"in o?o.deleted:o;return{stub:K(n,i)?i.id:null,hit:!0}}catch{return{stub:null,hit:!1}}})}l(Je,"resolvedLocally");async function Z(e,t,r){const n=Je(t,e);return n.stub!==null?ae(e,n.stub,r):n.hit||!ce(e.principal)?{kind:"local"}:ae(e,he(t),r)}l(Z,"forwardRef");const J=l(e=>`/v1/objects/${encodeURIComponent(e)}`,"objectPath");function we(e,t,r,n,o){const i=t?.object;!i?.id||!i.type||_(s=>{const u=ue(s,e);if(u===null)return;const c=Ue(s,i.id,i.type,r,{kind:i.kind??null,name:i.name??i.id,...i.preview===void 0?{}:{preview:i.preview},owner:i.owner??null,...i.kind_decl===void 0?{}:{kind_decl:i.kind_decl},...i.privacy===void 0?{}:{privacy:i.privacy}});W(s,u,c,n,o===void 0?{}:{patterns:o})})}l(we,"watchRemote");async function Qe(e){const t=k(e),r=["1","true"].includes(e.query.get("fields")??""),n=await Z(e,t,{method:"GET",path:J(t),query:V(e)});if(n.kind==="unknown")return{state:"unknown",ref:t,unreachable:n.unreachable};if(n.kind==="remote"){if(n.status>=400)throw C(n.status,n.body);return we(e,n.body,n.machine.id,"read"),B(n.body,n.machine)}const o=l(u=>{const c=U(u,e);return c===null?v(u,e):D(u,c,S(u))},"readerOf"),i=_(u=>{const c=o(u),a=H(u,c,t);if("remote"in a)return{state:"remote",remote:a.remote};if("deleted"in a)return{state:"deleted",deleted:g(u,a.deleted)};const f=se(u,a);if(f!==null)return{delegate:f,hitId:a.id};const{data:p,text:b}=z(u,a.type).read(u,c,a,{fields:r,reposFn:S(u)});return{state:"object",type:a.type,object:$(u,a,g(u,a)),text:b,data:p}});if(!("delegate"in i))return i;const s=await He(i.delegate,e.principal);return _(u=>{const c=o(u),a=L(u,i.hitId);if(a===null)throw new y(404,"not_found","object not found");if(a.deleted_at!==null)return{state:"deleted",deleted:g(u,a)};if(!te(u,c,a))throw new y(404,"not_found","object not found");const{data:f,text:p}=z(u,a.type).read(u,c,a,{fields:r,reposFn:S(u)});return se(u,a)===null?{state:"object",type:a.type,object:$(u,a,g(u,a)),text:p,data:f}:{state:"object",type:a.type,object:$(u,a,g(u,a)),text:"markdown"in s?s.markdown:`${p}
2
- content unavailable: ${s.unavailable}`,data:{...f,content:"markdown"in s?"live":"unavailable"}}})}l(Qe,"read");function Q(e,t,r,n){if(e!=null){if(!r.includes(e)){n.push({field:t,problem:`must be one of ${r.join(", ")}`,received:e});return}return e}}l(Q,"oneOf");function ye(e,t,r){if(t!=null){if(typeof t!="string"||!We(e,t)){r.push({field:"type",problem:`must be a kind: one of ${Pe(e).join(", ")}`,received:t});return}return t}}l(ye,"kindName");function ge(e,t,r,n){if(e==null)return n;const o=Number(e);return!Number.isInteger(o)||o<1||o>100?(r.push({field:t,problem:"must be an integer from 1 to 100",received:e}),n):o}l(ge,"limitOf");function be(e){const t=e.query,r=[],n=ye(T(),t.get("type"),r),o=Q(t.get("privacy"),"privacy",Ie,r),i=ge(t.get("limit"),"limit",r,50),s=t.get("cursor");s!==null&&!/^\d+$/.test(s)&&r.push({field:"cursor",problem:"is not a cursor from a previous page",received:s});const u=t.get("deleted");return u!==null&&!["0","1","true","false"].includes(u)&&r.push({field:"deleted",problem:"must be true or false",received:u}),r.length>0&&P("object list request",r),_(c=>{const a=v(c,e),f={...n?{type:n}:{},...o?{privacy:o}:{},...t.get("kind")!==null?{kind:t.get("kind")}:{},...u==="1"||u==="true"?{deleted:!0}:{}},p=t.get("owner");if(p!==null){const m=me(c,a,p);if(m===null)return{items:[],next_cursor:null};f.owner=m}const b=t.get("name"),j=[];let h=s===null?0:Number(s),w=!0;for(;j.length<i&&w;){const m=Ce(c,a,f,{limit:100,after_rowid:h});w=m.length===100;for(const E of m)if(h=E.rowid,(b===null||E.name.startsWith(b))&&j.push(E),j.length===i)break}const d=j.at(-1);return{items:j.map(m=>de(c,m)),next_cursor:j.length===i&&d?String(d.rowid):null}})}l(be,"listLocal");const Ye={ms:3e4},Xe="self",Y=l((e,t)=>e.map(r=>({...r,machine:t})),"labelItems");async function je(e,t,r,n){const o=F.current;try{const i=await o.call(t.id,{method:"GET",path:"/v1/objects",query:r},o.envelope(e.principal),n);if(Ke(i))return{state:"unreachable",items:[],next:null};if(i.status===426)return{state:"too_old",items:[],next:null};const s=i.body;return i.status!==200||!Array.isArray(s?.items)?{state:"unreachable",items:[],next:null}:{state:"ok",items:Y(s.items,t),next:s.next_cursor??null}}catch{return{state:"unreachable",items:[],next:null}}}l(je,"remotePage");async function xe(e){const t=new Promise(r=>e.addEventListener("abort",()=>r(null),{once:!0}));return Promise.race([F.current.machines().catch(()=>null),t])}l(xe,"machinesWithin");async function et(e){const t=e.query.get("machine");if(!ce(e.principal)||!F.current.joined()||t===Xe)return be(_e(e));const n=F.current.self(),o=t!==null&&I(t)!==n,i=o?null:be(_e(e)),s=new AbortController,u=setTimeout(()=>s.abort(),Ye.ms);u.unref?.();try{const c=await xe(s.signal);if(c===null){if(o)throw new y(503,"runtime_unreachable",`The directory did not answer, so ${I(t)} cannot be listed.`,{machine:I(t)});return i}const a=l(d=>({id:d,name:c.find(m=>m.machine_id===d)?.name??d}),"labelOf"),f=a(n),p=c.filter(d=>d.machine_id!==n&&d.kind!=="device"),b=V(e);if(t!==null){if(!o)return{items:Y(i.items,f),next_cursor:i.next_cursor,machines:[{machine_id:n,name:f.name,state:"ok",more:i.next_cursor!==null}]};const d=I(t);if(!p.some(E=>E.machine_id===d))throw new y(404,"not_found",`no machine ${d} on your account`,{machine:d});const m=await je(e,a(d),b,s.signal);return{items:m.items,next_cursor:m.next,machines:[{machine_id:d,name:a(d).name,state:m.state,more:m.next!==null}]}}const{cursor:j,...h}=b,w=await Promise.all(p.map(d=>je(e,a(d.machine_id),h,s.signal)));return{items:[...Y(i.items,f),...w.flatMap(d=>d.items)],next_cursor:i.next_cursor,machines:[{machine_id:n,name:f.name,state:"ok",more:i.next_cursor!==null},...p.map((d,m)=>({machine_id:d.machine_id,name:d.name,state:w[m].state,more:w[m].next!==null}))]}}finally{clearTimeout(u)}}l(et,"list");function _e(e){const t=new URLSearchParams(e.query);return t.delete("machine"),{...e,query:t}}l(_e,"withoutMachine");function tt(e){const t=[],r=R(e.body)?e.body:{};R(e.body)||t.push({field:"body",problem:"must be an object",received:e.body});const n=r.text;(typeof n!="string"||n.trim()==="")&&t.push({field:"text",problem:"is required",received:n});const o=r.grep;if(o!==void 0)if(typeof o!="string")t.push({field:"grep",problem:"must be a regular expression string",received:o});else try{new RegExp(o)}catch(u){t.push({field:"grep",problem:`is not a valid regular expression: ${u.message}`,received:o})}r.body!==void 0&&typeof r.body!="boolean"&&t.push({field:"body",problem:"must be a boolean",received:r.body});const i=ye(T(),r.type,t);r.kind!==void 0&&typeof r.kind!="string"&&t.push({field:"kind",problem:"must be a string",received:r.kind}),r.owner!==void 0&&typeof r.owner!="string"&&t.push({field:"owner",problem:"must be a string",received:r.owner});const s=ge(r.limit,"limit",t,50);return t.length>0&&P("object search request",t),_(u=>{const c=v(u,e),a=typeof r.owner=="string"?me(u,c,r.owner):null;if(typeof r.owner=="string"&&a===null)return{items:[]};const f=ie(u,c,{text:n,body:r.body===!0||typeof o=="string"}),p=new Set(f.map(h=>h.object.rowid));return{items:(typeof o=="string"?ie(u,c,{text:o,grep:!0}).filter(h=>p.has(h.object.rowid)):f).filter(h=>(!i||h.object.type===i)&&(r.kind===void 0||h.object.kind===r.kind)&&(!a||h.object.owner===a.rowid)).slice(0,s).map(h=>({object:de(u,h.object),...h.line!==void 0?{matches:[{line:h.line,text:h.text??""}]}:{}}))}})}l(tt,"search");const ke=["interrupt","steer","after-turn","next-turn"],nt=/^(\*|>|[A-Za-z0-9_-]+)(\.(\*|>|[A-Za-z0-9_-]+))*$/;function rt(e,t){if(e!==void 0){if(!Array.isArray(e)||e.length===0||e.some(r=>typeof r!="string"||!nt.test(r)||r.includes(">")&&!r.endsWith(">"))){t.push({field:"patterns",problem:"must be a non-empty list of event patterns (dot-separated words, `*` for one word, a final `>` for the rest)",received:e});return}return e}}l(rt,"patternsOf");function ot(e,t){if(e===void 0)return;if(!R(e)||Object.keys(e).length===0){t.push({field:"config",problem:"must map levels 1-10 to a delivery",received:e});return}const r=[];for(const[n,o]of Object.entries(e)){const i=Number(n);!Number.isInteger(i)||i<1||i>10?t.push({field:`config.${n}`,problem:"level must be an integer from 1 to 10"}):ke.includes(o)?r.push({threshold:i,delivery:o}):t.push({field:`config.${n}`,problem:`delivery must be one of ${ke.join(", ")}`,received:o})}return r.sort((n,o)=>o.threshold-n.threshold)}l(ot,"configOf");function ve(e){const t=pe(e);if(t!==null)throw new y(400,"invalid_request",`${t} lives on another machine; an explicit watcher cannot watch it from here`,{id:t})}l(ve,"refuseStubWatch");function X(e,t){const r=L(e,t)??(()=>{const n=Ae(e,Se(e,{class:"person"},()=>[]),t);return"object"in n?n.object:null})();return r===null||r.deleted_at!==null||!(r.type.includes(".")||r.type==="node")?null:r}l(X,"findWatcher");const O=l(()=>{throw new y(404,"not_found","watcher not found")},"watcherNotFound");async function Oe(e,t,r){if(typeof t!="string"||r===void 0||r===null)return null;if(typeof r!="string")throw new y(400,"invalid_request","invalid watcher_machine");if(X(e,t)!==null)return null;const n=F.current;let o;try{o=await n.machines()}catch{throw new y(503,"runtime_unreachable","The directory did not answer, so the watcher machine cannot be checked.")}const i=I(r);return(i===n.self()||!o.some(s=>I(s.machine_id)===i))&&O(),i}l(Oe,"remoteWatcherMachine");function Ee(e,t,r,n){if(t.publishToken||t.principal.class==="anonymous")return O();const o=v(e,t);if(o.class==="person")return O();let i;try{i=q(e,o,n)}catch{return O()}const s=i.owner===null?null:fe(e,i.owner);return s===null||!ne(e,o,s)||!Fe(e,o,"link",r)?O():(M(e,t,r),{actor:o.app,object:i})}l(Ee,"linkWatcher");function qe(e,t,r){if(t.publishToken)return!0;if(t.principal.class==="anonymous"||!r.type.includes("."))return!1;const n=v(e,t),o=r.owner===null?null:fe(e,r.owner);return o!==null&&ne(e,n,o)&&Ne(e,n,r)}l(qe,"ownsWatcher");async function it(e){const t=k(e),r=R(e.body)?e.body:{};if(typeof r.watcher=="string"&&ve(t),typeof r.watcher!="string"){const o=await Z(e,t,{method:"POST",path:`${J(t)}/watch`,body:e.body});if(o.kind==="unknown")throw le(t,o.unreachable);if(o.kind==="remote"){if(o.status>=400)throw C(o.status,o.body);const i=o.body.patterns;return we(e,o.body,o.machine.id,"ask",i),B(o.body,o.machine)}}const n=await Oe(T(),r.watcher,r.watcher_machine);return st(e,n)}l(it,"watch");function st(e,t=null){const r=[],n=e.body===void 0?{}:R(e.body)?e.body:(r.push({field:"body",problem:"must be an object"}),{}),o=rt(n.patterns,r),i=ot(n.config,r);return n.filter!==void 0&&!R(n.filter)&&r.push({field:"filter",problem:"must be an object",received:n.filter}),n.watcher!==void 0&&typeof n.watcher!="string"&&r.push({field:"watcher",problem:"must be a custom-object ref",received:n.watcher}),n.watcher_machine!==void 0&&typeof n.watcher_machine!="string"&&r.push({field:"watcher_machine",problem:"must be a machine id",received:n.watcher_machine}),r.length>0&&P("watch request",r),_(s=>{const u=typeof n.watcher=="string";if((e.publishToken||e.principal.class==="anonymous")&&!u)throw new y(404,"not_found","watcher not found");const c=o??[">"],a={patterns:c,...i?{config:i}:{},...n.filter!==void 0?{filter:n.filter}:{}};if(u){const j=n.watcher,h=t===null?null:ut(s,e,j,t),w=h??(e.publishToken?re(s,j):X(s,j));if(w===null)return O();if(h===null&&qe(s,e,w)){const E=oe(s,e,w);M(s,e,w);const x=D(s,w),N=q(s,x,k(e));if(!te(s,x,N))throw new y(404,"not_found","object not found");return W(s,w,N,"act",a),G(s,{event:"watched",object:N,actor:E,attrs:{}},S(s)),{object:$(s,N,g(s,N)),patterns:c}}const{actor:d,object:m}=Ee(s,e,w,k(e));return W(s,w,m,"act",{...a,linkApp:d}),G(s,{event:"watched",object:m,actor:d,attrs:{}},S(s)),{object:$(s,m,g(s,m)),patterns:c}}const f=v(s,e),p=U(s,e)??ee(f),b=q(s,f,k(e));return W(s,p,b,"ask",a),G(s,{event:"watched",object:b,actor:p,attrs:{}},S(s)),{object:$(s,b,g(s,b)),patterns:c}})}l(st,"watchLocal");function ut(e,t,r,n){return t.publishToken||t.principal.class==="anonymous"?O():Ve(e,r,n)}l(ut,"ensureNodeStubFor");function Te(e,t,r,n){const o=l(()=>$e(e,`SELECT count(*) AS n FROM watch_subscriptions s JOIN watches w ON w.rowid = s.watch
3
- WHERE w.watcher = ? AND w.object = ?`).get(t.rowid,r.rowid).n,"count"),i=o();return Me(e,t,r,n??void 0),{object:g(e,r),removed:i-o()}}l(Te,"dropWatch");async function at(e){const t=k(e);if(e.query.get("watcher")&&ve(t),!e.query.get("watcher")){const n=await Z(e,t,{method:"DELETE",path:`${J(t)}/watch`,query:V(e)});if(n.kind==="unknown")throw le(t,n.unreachable);if(n.kind==="remote"){const o=n.status===404?n.body.error?.details:void 0,i=o?.deleted===!0?o.id:void 0;if(n.status>=400&&i===void 0)throw C(n.status,n.body);const s=i??n.body.object?.id,u=_(c=>{const a=ue(c,e),f=s===void 0?null:L(c,s);return a===null||f===null||!K(c,f)?null:Te(c,a,f,e.query.get("pattern"))});if(i!==void 0){if(u===null)throw C(n.status,n.body);return{...u,machine:n.machine}}return B(n.body,n.machine)}}const r=await Oe(T(),e.query.get("watcher")??void 0,e.query.get("watcher_machine")??void 0);return ct(e,r)}l(at,"unwatchRoute");function ct(e,t=null){const r=e.query.get("pattern"),n=e.query.get("watcher");return _(o=>{if((e.publishToken||e.principal.class==="anonymous")&&!n)throw new y(404,"not_found","watcher not found");const i=l((c,a)=>Te(o,c,a,r),"drop");if(n){const c=t===null?null:(()=>{const f=L(o,n);return f!==null&&Be(o,f)!==null?f:null})();if(t!==null&&c===null)return O();const a=c??(e.publishToken?re(o,n):X(o,n));return a===null?O():c===null&&qe(o,e,a)?(oe(o,e,a),M(o,e,a),i(a,q(o,D(o,a),k(e)))):i(a,Ee(o,e,a,k(e)).object)}const s=v(o,e),u=U(o,e)??ee(s);return i(u,q(o,s,k(e)))})}l(ct,"unwatchLocal");function lt(e){const t=[],r=Q(e.query.get("type"),"type",["acted-on","links-to","watches"],t),n=Q(e.query.get("direction"),"direction",["out","in"],t);return t.length>0&&P("edges request",t),_(o=>{const i=v(o,e),s=q(o,i,k(e)),u=[];if(r!=="watches")for(const c of Le(o,i,s,{...r?{type:r}:{},direction:n??"both"}))u.push({type:c.type,src:g(o,c.src),dst:g(o,c.dst),...c.written_as?{written_as:c.written_as}:{}});if(r===void 0||r==="watches"){const c=[...n!=="in"?ze(o,i,s):[],...n!=="out"?Ge(o,i,s):[]];for(const a of c)u.push({type:"watches",src:g(o,a.watcher),dst:g(o,a.object)})}return{items:u}})}l(lt,"edges");const A=l(e=>async t=>({status:200,body:await e(t)}),"ok"),Wt=[{method:"POST",pattern:"/v1/objects/search",handler:A(tt)},{method:"GET",pattern:"/v1/objects/:ref/edges",handler:A(lt)},{method:"POST",pattern:"/v1/objects/:ref/watch",handler:A(it)},{method:"DELETE",pattern:"/v1/objects/:ref/watch",handler:A(at)},{method:"GET",pattern:"/v1/objects/:ref",handler:A(Qe)},{method:"GET",pattern:"/v1/objects",handler:A(et)}];export{Ye as listBudget,Wt as objectRoutes};
1
+ var Te=Object.defineProperty;var l=(e,t)=>Te(e,"name",{value:t,configurable:!0});import{prepared as Ie}from"../../../core/sqlite-statements.js";import{ApiError as p}from"../../../api/errors.js";import{PRIVACY_LEVELS_DTO as Se}from"../../../api/dto/objects.js";import{openDb as q,withCanvasWrite as _}from"../../../core/canvas/db.js";import{actorOf as ee}from"../../../core/graph/documents.js";import{readerForObject as D,readerFor as $e}from"../../../core/graph/reader.js";import{resolveName as Ne,stubsNamed as Ae,unwrapRef as Fe}from"../../../core/graph/names.js";import{canRead as te,customReachable as Le,holdsObjectsScope as We,mayActAs as ne}from"../../../core/graph/access.js";import{customObjectRef as re,authorizeCustom as oe,fenceArgv as M}from"./custom-objects.js";import{edgesOf as Pe}from"../../../core/graph/edges.js";import{publish as G}from"../../../core/graph/events.js";import{objectDTO as b}from"../../../core/graph/kinds/dto.js";import{isKind as Ce,kindNames as De,kindOf as z}from"../../../core/graph/kinds/registry.js";import{listObjects as Me,searchObjects as ie}from"../../../core/graph/objects.js";import{checkoutsForCwd as Ge}from"../../../core/graph/repo-sync/repos.js";import{recordWatch as W,unwatch as ze,watchersOf as He,watchesOf as Ue}from"../../../core/graph/watches.js";import{readerFor as v,resolveRef as H}from"../reader.js";import{readDelegationFor as se,runReadLeaf as Ve}from"../../plugin-objects/read-leaf.js";import{invalidRequest as P,isRecord as T}from"./validate.js";import{callerNode as ue,callerStub as U,forwardVerb as ae,originates as ce,queryWithoutMachine as V,relayError as C,remoteStub as Be,unknownError as le,forwarding as F,withMachine as B}from"../../peer/forward.js";import{getById as L,getByRowid as fe}from"../../../core/graph/objects.js";import{ensureNodeStub as Ke,isStub as K,stubOf as Ze,withKindDecl as I}from"../../../core/peer/stubs.js";import{isUnreachable as Je}from"../../../core/peer/client.js";import{normalizeMachineId as S}from"../../../core/peer/directory.js";const $=l(e=>t=>Ge(e,t),"reposFnFor");function de(e,t){return{...b(e,t),...z(e,t.type).listItem?.(e,t)}}l(de,"listItem");function Qe(e){return`no object named ${e} on this runtime; it may be on another runtime, or the name may be misspelled`}l(Qe,"remoteMessage");function me(e,t,r){try{return R(e,t,r)}catch(n){if(n instanceof p&&n.code==="not_found"&&!n.details?.deleted)return null;throw n}}l(me,"ownerFilter");function R(e,t,r){const n=H(e,t,r);if("remote"in n)throw new p(404,"not_found",Qe(n.remote),{next:"Check the name with `crtr canvas search`."});if("deleted"in n)throw new p(404,"not_found",`${n.deleted.name} is deleted`,{id:n.deleted.id,deleted:!0});return n}l(R,"liveRef");const k=l(e=>decodeURIComponent(e.params.ref),"refParam"),he=l(e=>{const t=Fe(e),r=t.indexOf("/");return r>0?t.slice(0,r):t},"idOf");function pe(e){const t=L(q(),he(e));return t!==null&&K(q(),t)?t.id:null}l(pe,"stubIdOf");function Ye(e,t){const r=pe(e);return r!==null?{stub:r,hit:!0}:_(n=>{try{const o=v(n,t),i=l(()=>{const u=Ae(n,o,e);if(u.length>1)throw new p(409,"ambiguous_name",`'${e}' names more than one remote object`,{candidates:u.map(c=>c.id),next:"Read one by its object id."});return{stub:u[0]?.id??null,hit:!1}},"named");let s;try{s=H(n,o,e)}catch(u){if(u instanceof p&&u.code==="not_found")return i();throw u}if("remote"in s)return i();if("deleted"in s){const u=i();return u.stub===null?{stub:null,hit:!0}:u}return{stub:K(n,s)?s.id:null,hit:!0}}catch(o){if(o instanceof p&&o.code==="ambiguous_name")throw o;return{stub:null,hit:!1}}})}l(Ye,"resolvedLocally");async function Z(e,t,r){const n=Ye(t,e);return n.stub!==null?ae(e,n.stub,r):n.hit||!ce(e.principal)?{kind:"local"}:ae(e,he(t),r)}l(Z,"forwardRef");const J=l(e=>`/v1/objects/${encodeURIComponent(e)}`,"objectPath");function we(e,t,r,n,o){const i=t?.object;!i?.id||!i.type||_(s=>{const u=ue(s,e);if(u===null)return;const c=Be(s,i.id,i.type,r,{kind:i.kind??null,name:i.name??i.id,...i.preview===void 0?{}:{preview:i.preview},owner:i.owner??null,...i.kind_decl===void 0?{}:{kind_decl:i.kind_decl},...i.privacy===void 0?{}:{privacy:i.privacy}});W(s,u,c,n,o===void 0?{}:{patterns:o})})}l(we,"watchRemote");async function Xe(e){const t=k(e),r=["1","true"].includes(e.query.get("fields")??""),n=await Z(e,t,{method:"GET",path:J(t),query:V(e)});if(n.kind==="unknown")return{state:"unknown",ref:t,unreachable:n.unreachable};if(n.kind==="remote"){if(n.status>=400)throw C(n.status,n.body);return we(e,n.body,n.machine.id,"read"),B(n.body,n.machine)}const o=l(u=>{const c=U(u,e);return c===null?v(u,e):D(u,c,$(u))},"readerOf"),i=_(u=>{const c=o(u),a=H(u,c,t);if("remote"in a)return{state:"remote",remote:a.remote};if("deleted"in a)return{state:"deleted",deleted:b(u,a.deleted)};const f=se(u,a);if(f!==null)return{delegate:f,hitId:a.id};const{data:w,text:g}=z(u,a.type).read(u,c,a,{fields:r,reposFn:$(u)});return{state:"object",type:a.type,object:I(u,a,b(u,a)),text:g,data:w}});if(!("delegate"in i))return i;const s=await Ve(i.delegate,e.principal);return _(u=>{const c=o(u),a=L(u,i.hitId);if(a===null)throw new p(404,"not_found","object not found");if(a.deleted_at!==null)return{state:"deleted",deleted:b(u,a)};if(!te(u,c,a))throw new p(404,"not_found","object not found");const{data:f,text:w}=z(u,a.type).read(u,c,a,{fields:r,reposFn:$(u)});return se(u,a)===null?{state:"object",type:a.type,object:I(u,a,b(u,a)),text:w,data:f}:{state:"object",type:a.type,object:I(u,a,b(u,a)),text:"markdown"in s?s.markdown:`${w}
2
+ content unavailable: ${s.unavailable}`,data:{...f,content:"markdown"in s?"live":"unavailable"}}})}l(Xe,"read");function Q(e,t,r,n){if(e!=null){if(!r.includes(e)){n.push({field:t,problem:`must be one of ${r.join(", ")}`,received:e});return}return e}}l(Q,"oneOf");function ye(e,t,r){if(t!=null){if(typeof t!="string"||!Ce(e,t)){r.push({field:"type",problem:`must be a kind: one of ${De(e).join(", ")}`,received:t});return}return t}}l(ye,"kindName");function be(e,t,r,n){if(e==null)return n;const o=Number(e);return!Number.isInteger(o)||o<1||o>100?(r.push({field:t,problem:"must be an integer from 1 to 100",received:e}),n):o}l(be,"limitOf");function ge(e){const t=e.query,r=[],n=ye(q(),t.get("type"),r),o=Q(t.get("privacy"),"privacy",Se,r),i=be(t.get("limit"),"limit",r,50),s=t.get("cursor");s!==null&&!/^\d+$/.test(s)&&r.push({field:"cursor",problem:"is not a cursor from a previous page",received:s});const u=t.get("deleted");return u!==null&&!["0","1","true","false"].includes(u)&&r.push({field:"deleted",problem:"must be true or false",received:u}),r.length>0&&P("object list request",r),_(c=>{const a=v(c,e),f={...n?{type:n}:{},...o?{privacy:o}:{},...t.get("kind")!==null?{kind:t.get("kind")}:{},...u==="1"||u==="true"?{deleted:!0}:{}},w=t.get("owner");if(w!==null){const m=me(c,a,w);if(m===null)return{items:[],next_cursor:null};f.owner=m}const g=t.get("name"),j=[];let h=s===null?0:Number(s),y=!0;for(;j.length<i&&y;){const m=Me(c,a,f,{limit:100,after_rowid:h});y=m.length===100;for(const E of m)if(h=E.rowid,(g===null||E.name.startsWith(g))&&j.push(E),j.length===i)break}const d=j.at(-1);return{items:j.map(m=>de(c,m)),next_cursor:j.length===i&&d?String(d.rowid):null}})}l(ge,"listLocal");const xe={ms:3e4},et="self",Y=l((e,t)=>e.map(r=>({...r,machine:t})),"labelItems");async function je(e,t,r,n){const o=F.current;try{const i=await o.call(t.id,{method:"GET",path:"/v1/objects",query:r},o.envelope(e.principal),n);if(Je(i))return{state:"unreachable",items:[],next:null};if(i.status===426)return{state:"too_old",items:[],next:null};const s=i.body;return i.status!==200||!Array.isArray(s?.items)?{state:"unreachable",items:[],next:null}:{state:"ok",items:Y(s.items,t),next:s.next_cursor??null}}catch{return{state:"unreachable",items:[],next:null}}}l(je,"remotePage");async function tt(e){const t=new Promise(r=>e.addEventListener("abort",()=>r(null),{once:!0}));return Promise.race([F.current.machines().catch(()=>null),t])}l(tt,"machinesWithin");async function nt(e){const t=e.query.get("machine");if(!ce(e.principal)||!F.current.joined()||t===et)return ge(_e(e));const n=F.current.self(),o=t!==null&&S(t)!==n,i=o?null:ge(_e(e)),s=new AbortController,u=setTimeout(()=>s.abort(),xe.ms);u.unref?.();try{const c=await tt(s.signal);if(c===null){if(o)throw new p(503,"runtime_unreachable",`The directory did not answer, so ${S(t)} cannot be listed.`,{machine:S(t)});return i}const a=l(d=>({id:d,name:c.find(m=>m.machine_id===d)?.name??d}),"labelOf"),f=a(n),w=c.filter(d=>d.machine_id!==n&&d.kind!=="device"),g=V(e);if(t!==null){if(!o)return{items:Y(i.items,f),next_cursor:i.next_cursor,machines:[{machine_id:n,name:f.name,state:"ok",more:i.next_cursor!==null}]};const d=S(t);if(!w.some(E=>E.machine_id===d))throw new p(404,"not_found",`no machine ${d} on your account`,{machine:d});const m=await je(e,a(d),g,s.signal);return{items:m.items,next_cursor:m.next,machines:[{machine_id:d,name:a(d).name,state:m.state,more:m.next!==null}]}}const{cursor:j,...h}=g,y=await Promise.all(w.map(d=>je(e,a(d.machine_id),h,s.signal)));return{items:[...Y(i.items,f),...y.flatMap(d=>d.items)],next_cursor:i.next_cursor,machines:[{machine_id:n,name:f.name,state:"ok",more:i.next_cursor!==null},...w.map((d,m)=>({machine_id:d.machine_id,name:d.name,state:y[m].state,more:y[m].next!==null}))]}}finally{clearTimeout(u)}}l(nt,"list");function _e(e){const t=new URLSearchParams(e.query);return t.delete("machine"),{...e,query:t}}l(_e,"withoutMachine");function rt(e){const t=[],r=T(e.body)?e.body:{};T(e.body)||t.push({field:"body",problem:"must be an object",received:e.body});const n=r.text;(typeof n!="string"||n.trim()==="")&&t.push({field:"text",problem:"is required",received:n});const o=r.grep;if(o!==void 0)if(typeof o!="string")t.push({field:"grep",problem:"must be a regular expression string",received:o});else try{new RegExp(o)}catch(u){t.push({field:"grep",problem:`is not a valid regular expression: ${u.message}`,received:o})}r.body!==void 0&&typeof r.body!="boolean"&&t.push({field:"body",problem:"must be a boolean",received:r.body});const i=ye(q(),r.type,t);r.kind!==void 0&&typeof r.kind!="string"&&t.push({field:"kind",problem:"must be a string",received:r.kind}),r.owner!==void 0&&typeof r.owner!="string"&&t.push({field:"owner",problem:"must be a string",received:r.owner});const s=be(r.limit,"limit",t,50);return t.length>0&&P("object search request",t),_(u=>{const c=v(u,e),a=typeof r.owner=="string"?me(u,c,r.owner):null;if(typeof r.owner=="string"&&a===null)return{items:[]};const f=ie(u,c,{text:n,body:r.body===!0||typeof o=="string"}),w=new Set(f.map(h=>h.object.rowid));return{items:(typeof o=="string"?ie(u,c,{text:o,grep:!0}).filter(h=>w.has(h.object.rowid)):f).filter(h=>(!i||h.object.type===i)&&(r.kind===void 0||h.object.kind===r.kind)&&(!a||h.object.owner===a.rowid)).slice(0,s).map(h=>({object:de(u,h.object),...h.line!==void 0?{matches:[{line:h.line,text:h.text??""}]}:{}}))}})}l(rt,"search");const ke=["interrupt","steer","after-turn","next-turn"],ot=/^(\*|>|[A-Za-z0-9_-]+)(\.(\*|>|[A-Za-z0-9_-]+))*$/;function it(e,t){if(e!==void 0){if(!Array.isArray(e)||e.length===0||e.some(r=>typeof r!="string"||!ot.test(r)||r.includes(">")&&!r.endsWith(">"))){t.push({field:"patterns",problem:"must be a non-empty list of event patterns (dot-separated words, `*` for one word, a final `>` for the rest)",received:e});return}return e}}l(it,"patternsOf");function st(e,t){if(e===void 0)return;if(!T(e)||Object.keys(e).length===0){t.push({field:"config",problem:"must map levels 1-10 to a delivery",received:e});return}const r=[];for(const[n,o]of Object.entries(e)){const i=Number(n);!Number.isInteger(i)||i<1||i>10?t.push({field:`config.${n}`,problem:"level must be an integer from 1 to 10"}):ke.includes(o)?r.push({threshold:i,delivery:o}):t.push({field:`config.${n}`,problem:`delivery must be one of ${ke.join(", ")}`,received:o})}return r.sort((n,o)=>o.threshold-n.threshold)}l(st,"configOf");function ve(e){const t=pe(e);if(t!==null)throw new p(400,"invalid_request",`${t} lives on another machine; an explicit watcher cannot watch it from here`,{id:t})}l(ve,"refuseStubWatch");function X(e,t){const r=L(e,t)??(()=>{const n=Ne(e,$e(e,{class:"person"},()=>[]),t);return"object"in n?n.object:null})();return r===null||r.deleted_at!==null||!(r.type.includes(".")||r.type==="node")?null:r}l(X,"findWatcher");const O=l(()=>{throw new p(404,"not_found","watcher not found")},"watcherNotFound");async function Oe(e,t,r){if(typeof t!="string"||r===void 0||r===null)return null;if(typeof r!="string")throw new p(400,"invalid_request","invalid watcher_machine");if(X(e,t)!==null)return null;const n=F.current;let o;try{o=await n.machines()}catch{throw new p(503,"runtime_unreachable","The directory did not answer, so the watcher machine cannot be checked.")}const i=S(r);return(i===n.self()||!o.some(s=>S(s.machine_id)===i))&&O(),i}l(Oe,"remoteWatcherMachine");function Ee(e,t,r,n){if(t.publishToken||t.principal.class==="anonymous")return O();const o=v(e,t);if(o.class==="person")return O();let i;try{i=R(e,o,n)}catch{return O()}const s=i.owner===null?null:fe(e,i.owner);return s===null||!ne(e,o,s)||!We(e,o,"link",r)?O():(M(e,t,r),{actor:o.app,object:i})}l(Ee,"linkWatcher");function Re(e,t,r){if(t.publishToken)return!0;if(t.principal.class==="anonymous"||!r.type.includes("."))return!1;const n=v(e,t),o=r.owner===null?null:fe(e,r.owner);return o!==null&&ne(e,n,o)&&Le(e,n,r)}l(Re,"ownsWatcher");async function ut(e){const t=k(e),r=T(e.body)?e.body:{};if(typeof r.watcher=="string"&&ve(t),typeof r.watcher!="string"){const o=await Z(e,t,{method:"POST",path:`${J(t)}/watch`,body:e.body});if(o.kind==="unknown")throw le(t,o.unreachable);if(o.kind==="remote"){if(o.status>=400)throw C(o.status,o.body);const i=o.body.patterns;return we(e,o.body,o.machine.id,"ask",i),B(o.body,o.machine)}}const n=await Oe(q(),r.watcher,r.watcher_machine);return at(e,n)}l(ut,"watch");function at(e,t=null){const r=[],n=e.body===void 0?{}:T(e.body)?e.body:(r.push({field:"body",problem:"must be an object"}),{}),o=it(n.patterns,r),i=st(n.config,r);return n.filter!==void 0&&!T(n.filter)&&r.push({field:"filter",problem:"must be an object",received:n.filter}),n.watcher!==void 0&&typeof n.watcher!="string"&&r.push({field:"watcher",problem:"must be a custom-object ref",received:n.watcher}),n.watcher_machine!==void 0&&typeof n.watcher_machine!="string"&&r.push({field:"watcher_machine",problem:"must be a machine id",received:n.watcher_machine}),r.length>0&&P("watch request",r),_(s=>{const u=typeof n.watcher=="string";if((e.publishToken||e.principal.class==="anonymous")&&!u)throw new p(404,"not_found","watcher not found");const c=o??[">"],a={patterns:c,...i?{config:i}:{},...n.filter!==void 0?{filter:n.filter}:{}};if(u){const j=n.watcher,h=t===null?null:ct(s,e,j,t),y=h??(e.publishToken?re(s,j):X(s,j));if(y===null)return O();if(h===null&&Re(s,e,y)){const E=oe(s,e,y);M(s,e,y);const x=D(s,y),A=R(s,x,k(e));if(!te(s,x,A))throw new p(404,"not_found","object not found");return W(s,y,A,"act",a),G(s,{event:"watched",object:A,actor:E,attrs:{}},$(s)),{object:I(s,A,b(s,A)),patterns:c}}const{actor:d,object:m}=Ee(s,e,y,k(e));return W(s,y,m,"act",{...a,linkApp:d}),G(s,{event:"watched",object:m,actor:d,attrs:{}},$(s)),{object:I(s,m,b(s,m)),patterns:c}}const f=v(s,e),w=U(s,e)??ee(f),g=R(s,f,k(e));return W(s,w,g,"ask",a),G(s,{event:"watched",object:g,actor:w,attrs:{}},$(s)),{object:I(s,g,b(s,g)),patterns:c}})}l(at,"watchLocal");function ct(e,t,r,n){return t.publishToken||t.principal.class==="anonymous"?O():Ke(e,r,n)}l(ct,"ensureNodeStubFor");function qe(e,t,r,n){const o=l(()=>Ie(e,`SELECT count(*) AS n FROM watch_subscriptions s JOIN watches w ON w.rowid = s.watch
3
+ WHERE w.watcher = ? AND w.object = ?`).get(t.rowid,r.rowid).n,"count"),i=o();return ze(e,t,r,n??void 0),{object:b(e,r),removed:i-o()}}l(qe,"dropWatch");async function lt(e){const t=k(e);if(e.query.get("watcher")&&ve(t),!e.query.get("watcher")){const n=await Z(e,t,{method:"DELETE",path:`${J(t)}/watch`,query:V(e)});if(n.kind==="unknown")throw le(t,n.unreachable);if(n.kind==="remote"){const o=n.status===404?n.body.error?.details:void 0,i=o?.deleted===!0?o.id:void 0;if(n.status>=400&&i===void 0)throw C(n.status,n.body);const s=i??n.body.object?.id,u=_(c=>{const a=ue(c,e),f=s===void 0?null:L(c,s);return a===null||f===null||!K(c,f)?null:qe(c,a,f,e.query.get("pattern"))});if(i!==void 0){if(u===null)throw C(n.status,n.body);return{...u,machine:n.machine}}return B(n.body,n.machine)}}const r=await Oe(q(),e.query.get("watcher")??void 0,e.query.get("watcher_machine")??void 0);return ft(e,r)}l(lt,"unwatchRoute");function ft(e,t=null){const r=e.query.get("pattern"),n=e.query.get("watcher");return _(o=>{if((e.publishToken||e.principal.class==="anonymous")&&!n)throw new p(404,"not_found","watcher not found");const i=l((c,a)=>qe(o,c,a,r),"drop");if(n){const c=t===null?null:(()=>{const f=L(o,n);return f!==null&&Ze(o,f)!==null?f:null})();if(t!==null&&c===null)return O();const a=c??(e.publishToken?re(o,n):X(o,n));return a===null?O():c===null&&Re(o,e,a)?(oe(o,e,a),M(o,e,a),i(a,R(o,D(o,a),k(e)))):i(a,Ee(o,e,a,k(e)).object)}const s=v(o,e),u=U(o,e)??ee(s);return i(u,R(o,s,k(e)))})}l(ft,"unwatchLocal");function dt(e){const t=[],r=Q(e.query.get("type"),"type",["acted-on","links-to","watches"],t),n=Q(e.query.get("direction"),"direction",["out","in"],t);return t.length>0&&P("edges request",t),_(o=>{const i=v(o,e),s=R(o,i,k(e)),u=[];if(r!=="watches")for(const c of Pe(o,i,s,{...r?{type:r}:{},direction:n??"both"}))u.push({type:c.type,src:b(o,c.src),dst:b(o,c.dst),...c.written_as?{written_as:c.written_as}:{}});if(r===void 0||r==="watches"){const c=[...n!=="in"?Ue(o,i,s):[],...n!=="out"?He(o,i,s):[]];for(const a of c)u.push({type:"watches",src:b(o,a.watcher),dst:b(o,a.object)})}return{items:u}})}l(dt,"edges");const N=l(e=>async t=>({status:200,body:await e(t)}),"ok"),Ct=[{method:"POST",pattern:"/v1/objects/search",handler:N(rt)},{method:"GET",pattern:"/v1/objects/:ref/edges",handler:N(dt)},{method:"POST",pattern:"/v1/objects/:ref/watch",handler:N(ut)},{method:"DELETE",pattern:"/v1/objects/:ref/watch",handler:N(lt)},{method:"GET",pattern:"/v1/objects/:ref",handler:N(Xe)},{method:"GET",pattern:"/v1/objects",handler:N(nt)}];export{xe as listBudget,Ct as objectRoutes};
@@ -1,2 +1,2 @@
1
- var g=Object.defineProperty;var r=(e,t)=>g(e,"name",{value:t,configurable:!0});import{join as h}from"node:path";import{readOutputResult as b}from"../../core/runtime/structured-output.js";import{ReviewOperationError as _}from"../../core/review/types.js";import{cronSinkDisplay as y}from"../../core/canvas/crons.js";import{isProfilePaused as c,profileDir as x,sanitizeProfileMetadata as O}from"../../core/profiles/manifest.js";import{nodeMetaPath as D,transcriptPath as T,viewSocketPath as E}from"../../core/canvas/paths.js";import{appForNode as f,contextDir as S,nodeAgentDir as A}from"../../core/canvas/node-agent-paths.js";import{FinalizationError as R}from"../../core/feed/feed.js";import{NodeIdConflictError as z}from"../../core/runtime/nodes.js";import{ScopeDeniedError as N}from"../../core/scopes.js";import{isBeneathRefusal as C}from"../../core/spaces/open-beneath.js";import{CrtrError as s}from"../../core/errors.js";import{WorktreeError as j}from"../../core/worktree.js";import{ApiError as q}from"../../api/errors.js";import{RunError as l}from"../../core/runs/operations.js";import{ExitCode as o}from"../../types.js";function ce(e,t){const{report:n}=e;return{stores:n.stores.map(i=>({root:i.root,owner:{...i.owner},docs:i.docs,...i.skipped===void 0?{}:{skipped:i.skipped}})),counts:n.counts,rewrites:n.rewrites,dropped_fields:n.droppedFields,skipped:n.skipped,resolutions:n.resolutions.map(i=>({kind:i.kind,message:i.message,paths:i.paths})),blockers:e.blockers.map(i=>({kind:i.kind,message:i.message,paths:i.paths})),dryRun:e.dryRun,pending:e.pending,resumed:t.resumed,...t.resumeError===void 0?{}:{resume_error:t.resumeError}}}r(ce,"toMigrateStateDTO");function F(e,t){try{return b(e,t)??null}catch{return null}}r(F,"readStructuredResult");function I(e){return e.outcome_at===null||e.outcome_at===void 0||e.outcome_kind===null||e.outcome_kind===void 0||e.outcome_reason===null||e.outcome_reason===void 0?null:{kind:e.outcome_kind,reason:e.outcome_reason,settled_at:e.outcome_at}}r(I,"toNodeOutcomeSummaryDTO");function p(e){if(e.outcome_at===null||e.outcome_at===void 0||e.outcome_kind===null||e.outcome_kind===void 0||e.outcome_reason===null||e.outcome_reason===void 0)return null;let t=null;if(e.outcome_detail_json!==null&&e.outcome_detail_json!==void 0)try{t=JSON.parse(e.outcome_detail_json)}catch{t=null}const n=e.final_report??null,i={node_id:e.node_id,revision:e.outcome_revision??1,settled_at:e.outcome_at,final_report:n===null?null:`${e.node_id}/${n}`,structured_result:e.outcome_kind==="result"?F(e.node_id,e.grantee):null,detail:t};return e.outcome_kind==="result"?{...i,kind:"result",reason:e.outcome_reason,declined:null}:e.outcome_reason==="declined"?{...i,kind:"failure",reason:"declined",declined:t?.declined??null}:{...i,kind:"failure",reason:e.outcome_reason,declined:null}}r(p,"toNodeOutcomeDTO");function fe(e){const t=p(e);return t===null||t.reason==="parked"?null:t.kind==="result"||t.reason==="finished"?{...t,kind:"result",reason:"finalized",declined:null}:t.reason==="declined"?{...t,reason:"declined",details:t.declined}:t.reason==="deadline_exceeded"?{...t,reason:"deadline_exceeded",declined:null}:t.reason==="cap_exhausted"?{...t,reason:"cap_exhausted",declined:null}:t.reason==="closed"||t.reason==="stranded"||t.reason==="retired"?{...t,reason:"canceled",declined:null}:{...t,reason:"runtime_error",declined:null,details:{crouter_reason:t.reason}}}r(fe,"toRunOutcomeDTO");function pe(e){const t=e.lastFailure;return{node_id:e.nodeId,state:e.state,action:e.actionName,attempt:e.attempt,next_attempt_at:e.nextAttemptAt===0?null:new Date(e.nextAttemptAt).toISOString(),accepted_at:e.acceptedAt===null?null:new Date(e.acceptedAt).toISOString(),permanent_failed_at:e.permanentFailedAt===null?null:new Date(e.permanentFailedAt).toISOString(),last_failure:t===null?null:{kind:t.kind,...t.exitCode===void 0?{}:{exit_code:t.exitCode},...t.signal===void 0?{}:{signal:t.signal},...t.message===void 0?{}:{message:t.message}},created_at:new Date(e.createdAt).toISOString(),updated_at:new Date(e.updatedAt).toISOString()}}r(pe,"toOutcomeDeliveryDTO");function me(e){return{node_id:e.node_id,name:e.name,description:e.description,cycles:e.cycles,kind:e.kind,status:e.status,frozen_at:e.frozen_at,pi_pid:e.pi_pid,telemetry_context_tokens:e.telemetry_context_tokens,telemetry_last_activity:e.telemetry_last_activity,fault:e.fault&&e.fault.link!=="broker\u2194crtrd"?{...e.fault,link:e.fault.link}:null,streaming:e.streaming}}r(me,"toGraphNodeDTO");function ve(e,t=c(e.profile_id)){return{node_id:e.node_id,name:e.name,description:e.description,cycles:e.cycles,kind:e.kind,mode:e.mode,lifecycle:e.lifecycle,status:e.status,cwd:e.cwd,host_kind:e.host_kind,profile_id:e.profile_id,scopes:e.scopes,isolated:e.isolated,grantee:e.grantee??f(e.node_id),profile_paused:t,parent:e.parent,created:e.created,intent:e.intent,waiting_for:e.waiting_for,frozen_at:e.frozen_at??null,terminal_reason:e.terminal_reason??null,pi_pid:e.pi_pid,pi_pid_identity:e.pi_pid_identity,window:e.window,tmux_session:e.tmux_session,pane:e.pane,final_report:e.final_report??null,finalized_at:e.finalized_at??null,deadline_at:e.deadline_at??null,telemetry_tokens_in:e.telemetry_tokens_in??null,telemetry_context_tokens:e.telemetry_context_tokens??null,telemetry_last_activity:e.telemetry_last_activity??null,telemetry_updated_at:e.telemetry_updated_at??null,outcome:I(e),fault:e.fault&&e.fault.link!=="broker\u2194crtrd"?{...e.fault,link:e.fault.link}:null,streaming:e.streaming??!1}}r(ve,"toNodeSummaryDTO");function P(e,t){return{parent:e.parent??null,spawned_by:e.spawned_by??null,subscribes_to:t.subscribesTo.map(n=>n.node_id),subscribers:t.subscribers.map(n=>n.node_id),children:[...t.children]}}r(P,"toNodeEdgesDTO");function U(e,t){return{node_dir:A(e,t),context_dir:S(e,t),meta_path:D(e),transcript_path:T(e),view_socket:E(e)}}r(U,"toNodePathsDTO");function G(e){const t={state:e.state,path:e.path,branch:e.branch,repo_root:e.repo_root,base_ref:e.base_ref,base_sha:e.base_sha,created:e.created};return e.cleanup!==void 0&&(t.cleanup=e.cleanup),e.closed!==void 0&&(t.closed=e.closed),e.abandoned!==void 0&&(t.abandoned={...e.abandoned}),t}r(G,"toNodeWorktreeDTO");function ke(e,t){const n=f(e.node_id),i={node_id:e.node_id,name:e.name,kind:e.kind,mode:e.mode,lifecycle:e.lifecycle,status:e.status,cwd:e.cwd,host_kind:e.host_kind??null,profile_id:e.profile_id??null,scopes:e.scopes??null,isolated:e.isolated===!0,grantee:n,profile_paused:c(e.profile_id),parent:e.parent??null,created:e.created,intent:e.intent??null,waiting_for:e.waiting_for??null,frozen_at:e.frozen_at??null,terminal_reason:e.terminal_reason??null,pi_pid:e.pi_pid??null,pi_pid_identity:e.pi_pid_identity??null,window:e.window??null,tmux_session:e.tmux_session??null,pane:e.pane??null,final_report:e.final_report??null,finalized_at:e.finalized_at??null,deadline_at:e.deadline_at??null,telemetry_tokens_in:e.telemetry_tokens_in??null,telemetry_context_tokens:e.telemetry_context_tokens??null,telemetry_last_activity:e.telemetry_last_activity??null,telemetry_updated_at:e.telemetry_updated_at??null,outcome:p(e),fault:e.fault&&e.fault.link!=="broker\u2194crtrd"?{...e.fault,link:e.fault.link}:null,streaming:e.streaming??!1,creator:e.creator??null,edges:P(e,t),paths:U(e.node_id,n)};return e.description!==void 0&&(i.description=e.description),e.title!==void 0&&(i.title=e.title),e.icon!==void 0&&(i.icon=e.icon),e.cycles!==void 0&&(i.cycles=e.cycles),i.context_tokens=e.telemetry_context_tokens??e.telemetry_tokens_in??null,e.pi_session_id!==void 0&&(i.pi_session_id=e.pi_session_id??null),i.model_override=e.model_override??null,e.pi_session_file!==void 0&&(i.pi_session_file=e.pi_session_file??null),e.review_binding!==void 0&&(i.review_binding=e.review_binding===null?null:{...e.review_binding.kind===void 0?{}:{kind:e.review_binding.kind},review_id:e.review_binding.review_id,origin_node_id:e.review_binding.origin_node_id,branch_file:e.review_binding.branch_file,target_file:e.review_binding.target_file}),e.managed_worktree!=null&&(i.worktree=G(e.managed_worktree)),i}r(ke,"toNodeDetailDTO");function ge(e,t,n,i){return{node_id:e,revived:t.launch!==void 0,resumed:t.resumed,status:n,outcome:t.outcome,ready:i}}r(ge,"toReviveResultDTO");function he(e){return{root:e.root,closed:[...e.closed],spared:[...e.spared]}}r(he,"toCloseResultDTO");function be(e,t,n){const i={report:e.report,notified:[...e.deliveredTo]};return t!==void 0&&(i.transitioned=t),n!==void 0&&(i.worktree_auto_dropped=!0,i.worktree_auto_dropped_path=n),i}r(be,"toReportResultDTO");function ye(e){return{node_id:e.node_id,active:e.active,created:e.created}}r(ye,"toSubscriptionDTO");function M(e){if(e===null||e==="")return[];try{const t=JSON.parse(e);return typeof t=="object"&&t!==null&&!Array.isArray(t)?Object.keys(t):[]}catch{return[]}}r(M,"envKeys");function xe(e,t){return{cron_id:e.cron_id,name:e.name,created_by:e.created_by,command:e.command,grant_id:e.grant_id,scopes:e.scopes,origin_run_id:e.origin_run_id,isolated:e.isolated,fire_at:e.fire_at,recur:e.recur,tz:e.tz,expires_at:e.expires_at,anchor_node:e.anchor_node,cancel_on_wake:e.cancel_on_wake,cwd:e.cwd,profile:e.profile,scope:e.scope,env_keys:M(e.env_json),run_timeout_s:e.run_timeout_s,overlap:e.overlap,on_output:e.on_output,sink:y(e.sink),tier:e.tier,state:e.state,held:e.held,run_state:e.run_state,last_run:t==null?null:{finished:t.finished,exit_code:t.exit_code,delivered:t.delivered},created:e.created,updated:e.updated}}r(xe,"toCronDTO");function Oe(e){return{run_id:e.run_id,started:e.started,finished:e.finished,duration_ms:e.duration_ms,exit_code:e.exit_code,stdout_head:e.stdout_head,stderr_head:e.stderr_head,delivered:e.delivered}}r(Oe,"toCronRunDTO");function De(e){return{id:e.profileId,app:e.manifest.grantee??"app:terminal",name:e.manifest.name,projects:e.manifest.projects.map(t=>({...t})),delivery_limits:{...e.manifest.delivery_limits},paused_at:e.manifest.paused_at,default_kind:e.manifest.default_kind??"general",metadata:O(e.manifest.metadata),default_dir:null,created_at:e.manifest.created_at,last_used_at:e.manifest.last_used_at,profile_path:x(e.profileId)}}r(De,"toProfileDTO");function m(e,t={}){const n={review_id:e.review_id,origin_kind:e.origin_kind,origin_node_id:e.origin_node_id,review_dir:e.review_dir,companion_node_id:e.companion_node_id,file:e.file,state:e.state,created:e.created,source_missing:e.source_missing,anchor_base_sha256:e.anchor_base_sha256};return e.document_name!==null&&(n.document=e.document_name),e.opened_at!==null&&(n.opened_at=e.opened_at),e.submit_requested_at!==null&&(n.submit_requested_at=e.submit_requested_at),e.approved_at!==null&&(n.approved_at=e.approved_at),e.changed!==null&&(n.changed=e.changed),e.comments_total!==null&&(n.comments_total=e.comments_total),e.comments_unresolved!==null&&(n.comments_unresolved=e.comments_unresolved),e.canceled_at!==null&&(n.canceled_at=e.canceled_at),e.cancel_reason!==null&&(n.cancel_reason=e.cancel_reason),e.cancel_actor!==null&&(n.cancel_actor=e.cancel_actor),t.result_path!==void 0&&(n.result_path=t.result_path),e.delivery_error!==null&&(n.delivery_error=e.delivery_error),e.projection_error!==null&&(n.projection_error=e.projection_error),n}r(m,"toReviewDTO");function Te(e){return{comment_id:e.comment_id,review_id:e.review_id,status:e.status,revision:e.revision,text:e.text,anchor:{...e.anchor},anchor_state:e.anchor_state,anchor_line_text:e.anchor_line_text,anchor_doc_hash:e.anchor_doc_hash,author:{kind:e.author.kind,...e.author.node_id===null?{}:{node_id:e.author.node_id}},updated_by:{kind:e.updated_by.kind,...e.updated_by.node_id===null?{}:{node_id:e.updated_by.node_id}},created_at:e.created_at,updated_at:e.updated_at,...e.resolved_at===null?{}:{resolved_at:e.resolved_at},...e.deleted_at===null?{}:{deleted_at:e.deleted_at},created_seq:e.created_seq}}r(Te,"toReviewCommentDTO");function B(e){return{id:e.id,quote:e.quote,...e.context===void 0?{}:{context:e.context},note:e.note,status:e.status,created_at:e.createdAt,...e.resolvedAt===void 0?{}:{resolved_at:e.resolvedAt}}}r(B,"toPageFeedbackCommentDTO");function Ee(e){return{companion_node_id:e.companionNodeId??null,open_count:e.comments.filter(t=>t.status==="open").length,comments:e.comments.map(B)}}r(Ee,"toPageFeedbackDTO");function Se(e){return{seq:e.seq,review_id:e.review_id,comment_id:e.comment_id,kind:e.kind,state_change:e.state_change===1,revision_after:e.revision_after,actor:{kind:e.actor.kind,...e.actor.node_id===null?{}:{node_id:e.actor.node_id}},at:e.at,operation_id:e.operation_id,...e.payload===void 0?{}:{payload:e.payload}}}r(Se,"toReviewCommentEventDTO");function Ae(e){return{file:e.file,submitted:e.submitted,approved:e.approved,comments:e.comments.map(n=>({...n})),submittedAt:e.submittedAt,savedAt:e.savedAt,reviewId:e.review_id,changed:e.changed,baselineSha256:e.baseline_sha256,approvedSha256:e.approved_sha256,companionNodeId:e.companion_node_id,commentsTotal:e.comments_total,commentsUnresolved:e.comments_unresolved}}r(Ae,"toFeedbackResultDTO");const L=!0,W=Object.freeze({review_origin_missing:{status:400,code:"review_origin_unavailable"},review_origin_unforkable:{status:400,code:"review_origin_unavailable"},review_branch_unavailable:{status:409,code:"review_branch_unavailable"},branch_lost:{status:409,code:"review_branch_unavailable"},review_companion_unbound:{status:409,code:"review_companion_unbound"},review_bridge_unsubscribed:{status:409,code:"review_bridge_unavailable"},review_target_unreviewable:{status:400,code:"review_file_unreadable"},source_unreadable:{status:409,code:"review_source_unreadable"},delivery_unroutable:{status:409,code:"review_delivery_unroutable"},unknown_review:{status:404,code:"unknown_review"},review_terminal:{status:409,code:"review_terminal_conflict"},review_required:{status:400,code:"review_required"},stale_document:{status:409,code:"stale_document"},stale_revision:{status:409,code:"stale_revision"},unknown_comment:{status:404,code:"unknown_comment"},comment_deleted:{status:409,code:"comment_deleted"},invalid_anchor:{status:400,code:"invalid_anchor"},anchor_out_of_range:{status:400,code:"anchor_out_of_range"},text_too_long:{status:400,code:"text_too_long"},comment_limit_reached:{status:409,code:"comment_limit_reached"},stale_comment:{status:409,code:"stale_comment"},range_batch_incomplete:{status:409,code:"range_batch_incomplete"},range_batch_stale:{status:409,code:"range_batch_stale"}});function $(e){const t=v(e);if(typeof t=="object"&&t!==null&&typeof t.status=="number"&&typeof t.code=="string")return{status:t.status,code:t.code};if(t instanceof R)return t.code==="unknown_node"?{status:404,code:"node_not_found"}:t.code==="already_finalized"?{status:409,code:"already_finalized"}:{status:409,code:"finalization_forbidden"};if(t instanceof z)return{status:409,code:"node_id_exists"};if(t instanceof N)return{status:403,code:"scope_denied"};if(C(t))return{status:400,code:"invalid_request"};if(t instanceof _)return W[t.code];if(t instanceof s)return["kind_owned","name_taken","hop_limit","not_a_queue"].includes(t.code)?{status:409,code:t.code}:t.code==="invalid_publish_token"?{status:401,code:t.code}:t.code==="forbidden"||t.code==="argv_forbidden"||t.code==="scope_missing"?{status:403,code:t.code}:{status:H(t.exitCode),code:t.code};if(t instanceof Error){const n=t.message;if(/unknown node/i.test(n))return{status:404,code:"node_not_found"};if(/finalization latch/i.test(n))return{status:409,code:"already_finalized"};if(/illegal lifecycle transition/i.test(n))return{status:409,code:"illegal_transition"}}return{status:500,code:"internal"}}r($,"errorToStatus");function v(e){if(!(e instanceof j))return e;const t=e.code==="unknown_node"?o.NOT_FOUND:o.GENERAL,n={error:e.code,message:e.message,next:e.next};return e.detail!==void 0&&(n.received=e.detail),new s(e.code,e.message,t,n)}r(v,"normalizeThrow");function K(e){if(e.code!=="review_terminal")return e.detail;const{review:t,...n}=e.detail;return{...n,review:V(t)}}r(K,"reviewErrorDetails");function V(e){return e.state!=="approved"?m(e):m(e,{result_path:h(e.review_dir,"result.json")})}r(V,"terminalConflictReviewDTO");function H(e){switch(e){case o.NOT_FOUND:return 404;case o.USAGE:return 400;case o.AMBIGUOUS:return 400;case o.NETWORK:return 503;case o.GENERAL:return 400;default:return 500}}r(H,"statusForExitCode");function J(e){const n=(e instanceof Error?e.message:String(e)).split(`
2
- `,1)[0].trim();return n===""?"internal error":n.length>500?`${n.slice(0,497)}\u2026`:n}r(J,"boundedCause");function Re(e){const t=v(e),{status:n,code:i}=$(t);if(n>=500){const a={error:{code:i,message:J(t)}};return t instanceof l&&(a.error.origin="runtime",a.error.retryable=t.retryable),{status:n,body:a}}const k=t instanceof Error?t.message:String(t),u=t instanceof _?K(t):(t instanceof s||t instanceof q||t instanceof l)&&t.details!==void 0?t.details:void 0,d={error:{code:i,message:k}};return u!==void 0&&(d.error.details=u),t instanceof l&&(t.param&&(d.error.param=t.param),t.scope&&(d.error.scope=t.scope),d.error.origin="runtime",d.error.retryable=t.retryable),{status:n,body:d}}r(Re,"toErrorBody");export{W as REVIEW_ERROR_MAP,$ as errorToStatus,he as toCloseResultDTO,xe as toCronDTO,Oe as toCronRunDTO,Re as toErrorBody,Ae as toFeedbackResultDTO,me as toGraphNodeDTO,ce as toMigrateStateDTO,ke as toNodeDetailDTO,P as toNodeEdgesDTO,p as toNodeOutcomeDTO,I as toNodeOutcomeSummaryDTO,U as toNodePathsDTO,ve as toNodeSummaryDTO,G as toNodeWorktreeDTO,pe as toOutcomeDeliveryDTO,B as toPageFeedbackCommentDTO,Ee as toPageFeedbackDTO,De as toProfileDTO,be as toReportResultDTO,Te as toReviewCommentDTO,Se as toReviewCommentEventDTO,m as toReviewDTO,ge as toReviveResultDTO,fe as toRunOutcomeDTO,ye as toSubscriptionDTO};
1
+ var g=Object.defineProperty;var r=(e,t)=>g(e,"name",{value:t,configurable:!0});import{join as h}from"node:path";import{readOutputResult as b}from"../../core/runtime/structured-output.js";import{ReviewOperationError as _}from"../../core/review/types.js";import{cronSinkDisplay as y}from"../../core/canvas/crons.js";import{isProfilePaused as c,profileDir as x,sanitizeProfileMetadata as O}from"../../core/profiles/manifest.js";import{nodeMetaPath as D,transcriptPath as T,viewSocketPath as E}from"../../core/canvas/paths.js";import{appForNode as f,contextDir as S,nodeAgentDir as A}from"../../core/canvas/node-agent-paths.js";import{FinalizationError as R}from"../../core/feed/feed.js";import{NodeIdConflictError as z}from"../../core/runtime/nodes.js";import{ScopeDeniedError as N}from"../../core/scopes.js";import{isBeneathRefusal as C}from"../../core/spaces/open-beneath.js";import{CrtrError as a}from"../../core/errors.js";import{WorktreeError as j}from"../../core/worktree.js";import{ApiError as q}from"../../api/errors.js";import{RunError as s}from"../../core/runs/operations.js";import{ExitCode as o}from"../../types.js";function ce(e,t){const{report:n}=e;return{stores:n.stores.map(i=>({root:i.root,owner:{...i.owner},docs:i.docs,...i.skipped===void 0?{}:{skipped:i.skipped}})),counts:n.counts,rewrites:n.rewrites,dropped_fields:n.droppedFields,skipped:n.skipped,resolutions:n.resolutions.map(i=>({kind:i.kind,message:i.message,paths:i.paths})),blockers:e.blockers.map(i=>({kind:i.kind,message:i.message,paths:i.paths})),dryRun:e.dryRun,pending:e.pending,resumed:t.resumed,...t.resumeError===void 0?{}:{resume_error:t.resumeError}}}r(ce,"toMigrateStateDTO");function F(e,t){try{return b(e,t)??null}catch{return null}}r(F,"readStructuredResult");function I(e){return e.outcome_at===null||e.outcome_at===void 0||e.outcome_kind===null||e.outcome_kind===void 0||e.outcome_reason===null||e.outcome_reason===void 0?null:{kind:e.outcome_kind,reason:e.outcome_reason,settled_at:e.outcome_at}}r(I,"toNodeOutcomeSummaryDTO");function p(e){if(e.outcome_at===null||e.outcome_at===void 0||e.outcome_kind===null||e.outcome_kind===void 0||e.outcome_reason===null||e.outcome_reason===void 0)return null;let t=null;if(e.outcome_detail_json!==null&&e.outcome_detail_json!==void 0)try{t=JSON.parse(e.outcome_detail_json)}catch{t=null}const n=e.final_report??null,i={node_id:e.node_id,revision:e.outcome_revision??1,settled_at:e.outcome_at,final_report:n===null?null:`${e.node_id}/${n}`,structured_result:e.outcome_kind==="result"?F(e.node_id,e.grantee):null,detail:t};return e.outcome_kind==="result"?{...i,kind:"result",reason:e.outcome_reason,declined:null}:e.outcome_reason==="declined"?{...i,kind:"failure",reason:"declined",declined:t?.declined??null}:{...i,kind:"failure",reason:e.outcome_reason,declined:null}}r(p,"toNodeOutcomeDTO");function fe(e){const t=p(e);return t===null||t.reason==="parked"?null:t.kind==="result"||t.reason==="finished"?{...t,kind:"result",reason:"finalized",declined:null}:t.reason==="declined"?{...t,reason:"declined",details:t.declined}:t.reason==="deadline_exceeded"?{...t,reason:"deadline_exceeded",declined:null}:t.reason==="cap_exhausted"?{...t,reason:"cap_exhausted",declined:null}:t.reason==="closed"||t.reason==="stranded"||t.reason==="retired"?{...t,reason:"canceled",declined:null}:{...t,reason:"runtime_error",declined:null,details:{crouter_reason:t.reason}}}r(fe,"toRunOutcomeDTO");function pe(e){const t=e.lastFailure;return{node_id:e.nodeId,state:e.state,action:e.actionName,attempt:e.attempt,next_attempt_at:e.nextAttemptAt===0?null:new Date(e.nextAttemptAt).toISOString(),accepted_at:e.acceptedAt===null?null:new Date(e.acceptedAt).toISOString(),permanent_failed_at:e.permanentFailedAt===null?null:new Date(e.permanentFailedAt).toISOString(),last_failure:t===null?null:{kind:t.kind,...t.exitCode===void 0?{}:{exit_code:t.exitCode},...t.signal===void 0?{}:{signal:t.signal},...t.message===void 0?{}:{message:t.message}},created_at:new Date(e.createdAt).toISOString(),updated_at:new Date(e.updatedAt).toISOString()}}r(pe,"toOutcomeDeliveryDTO");function me(e){return{node_id:e.node_id,name:e.name,description:e.description,cycles:e.cycles,kind:e.kind,status:e.status,frozen_at:e.frozen_at,pi_pid:e.pi_pid,telemetry_context_tokens:e.telemetry_context_tokens,telemetry_last_activity:e.telemetry_last_activity,fault:e.fault&&e.fault.link!=="broker\u2194crtrd"?{...e.fault,link:e.fault.link}:null,streaming:e.streaming}}r(me,"toGraphNodeDTO");function ve(e,t=c(e.profile_id)){return{node_id:e.node_id,name:e.name,description:e.description,cycles:e.cycles,kind:e.kind,mode:e.mode,lifecycle:e.lifecycle,status:e.status,cwd:e.cwd,host_kind:e.host_kind,profile_id:e.profile_id,scopes:e.scopes,isolated:e.isolated,grantee:e.grantee??f(e.node_id),profile_paused:t,parent:e.parent,created:e.created,intent:e.intent,waiting_for:e.waiting_for,frozen_at:e.frozen_at??null,terminal_reason:e.terminal_reason??null,pi_pid:e.pi_pid,pi_pid_identity:e.pi_pid_identity,window:e.window,tmux_session:e.tmux_session,pane:e.pane,final_report:e.final_report??null,finalized_at:e.finalized_at??null,deadline_at:e.deadline_at??null,telemetry_tokens_in:e.telemetry_tokens_in??null,telemetry_context_tokens:e.telemetry_context_tokens??null,telemetry_last_activity:e.telemetry_last_activity??null,telemetry_updated_at:e.telemetry_updated_at??null,outcome:I(e),fault:e.fault&&e.fault.link!=="broker\u2194crtrd"?{...e.fault,link:e.fault.link}:null,streaming:e.streaming??!1}}r(ve,"toNodeSummaryDTO");function P(e,t){return{parent:e.parent??null,spawned_by:e.spawned_by??null,subscribes_to:t.subscribesTo.map(n=>n.node_id),subscribers:t.subscribers.map(n=>n.node_id),children:[...t.children]}}r(P,"toNodeEdgesDTO");function U(e,t){return{node_dir:A(e,t),context_dir:S(e,t),meta_path:D(e),transcript_path:T(e),view_socket:E(e)}}r(U,"toNodePathsDTO");function G(e){const t={state:e.state,path:e.path,branch:e.branch,repo_root:e.repo_root,base_ref:e.base_ref,base_sha:e.base_sha,created:e.created};return e.cleanup!==void 0&&(t.cleanup=e.cleanup),e.closed!==void 0&&(t.closed=e.closed),e.abandoned!==void 0&&(t.abandoned={...e.abandoned}),t}r(G,"toNodeWorktreeDTO");function ke(e,t){const n=f(e.node_id),i={node_id:e.node_id,name:e.name,kind:e.kind,mode:e.mode,lifecycle:e.lifecycle,status:e.status,cwd:e.cwd,host_kind:e.host_kind??null,profile_id:e.profile_id??null,scopes:e.scopes??null,isolated:e.isolated===!0,grantee:n,profile_paused:c(e.profile_id),parent:e.parent??null,created:e.created,intent:e.intent??null,waiting_for:e.waiting_for??null,frozen_at:e.frozen_at??null,terminal_reason:e.terminal_reason??null,pi_pid:e.pi_pid??null,pi_pid_identity:e.pi_pid_identity??null,window:e.window??null,tmux_session:e.tmux_session??null,pane:e.pane??null,final_report:e.final_report??null,finalized_at:e.finalized_at??null,deadline_at:e.deadline_at??null,telemetry_tokens_in:e.telemetry_tokens_in??null,telemetry_context_tokens:e.telemetry_context_tokens??null,telemetry_last_activity:e.telemetry_last_activity??null,telemetry_updated_at:e.telemetry_updated_at??null,outcome:p(e),fault:e.fault&&e.fault.link!=="broker\u2194crtrd"?{...e.fault,link:e.fault.link}:null,streaming:e.streaming??!1,creator:e.creator??null,edges:P(e,t),paths:U(e.node_id,n)};return e.description!==void 0&&(i.description=e.description),e.title!==void 0&&(i.title=e.title),e.icon!==void 0&&(i.icon=e.icon),e.cycles!==void 0&&(i.cycles=e.cycles),i.context_tokens=e.telemetry_context_tokens??e.telemetry_tokens_in??null,e.pi_session_id!==void 0&&(i.pi_session_id=e.pi_session_id??null),i.model_override=e.model_override??null,e.pi_session_file!==void 0&&(i.pi_session_file=e.pi_session_file??null),e.review_binding!==void 0&&(i.review_binding=e.review_binding===null?null:{...e.review_binding.kind===void 0?{}:{kind:e.review_binding.kind},review_id:e.review_binding.review_id,origin_node_id:e.review_binding.origin_node_id,branch_file:e.review_binding.branch_file,target_file:e.review_binding.target_file}),e.managed_worktree!=null&&(i.worktree=G(e.managed_worktree)),i}r(ke,"toNodeDetailDTO");function ge(e,t,n,i){return{node_id:e,revived:t.launch!==void 0,resumed:t.resumed,status:n,outcome:t.outcome,ready:i}}r(ge,"toReviveResultDTO");function he(e){return{root:e.root,closed:[...e.closed],spared:[...e.spared]}}r(he,"toCloseResultDTO");function be(e,t,n){const i={report:e.report,notified:[...e.deliveredTo]};return t!==void 0&&(i.transitioned=t),n!==void 0&&(i.worktree_auto_dropped=!0,i.worktree_auto_dropped_path=n),i}r(be,"toReportResultDTO");function ye(e){return{node_id:e.node_id,active:e.active,created:e.created}}r(ye,"toSubscriptionDTO");function M(e){if(e===null||e==="")return[];try{const t=JSON.parse(e);return typeof t=="object"&&t!==null&&!Array.isArray(t)?Object.keys(t):[]}catch{return[]}}r(M,"envKeys");function xe(e,t){return{cron_id:e.cron_id,name:e.name,created_by:e.created_by,command:e.command,grant_id:e.grant_id,scopes:e.scopes,origin_run_id:e.origin_run_id,isolated:e.isolated,fire_at:e.fire_at,recur:e.recur,tz:e.tz,expires_at:e.expires_at,anchor_node:e.anchor_node,cancel_on_wake:e.cancel_on_wake,cwd:e.cwd,profile:e.profile,scope:e.scope,env_keys:M(e.env_json),run_timeout_s:e.run_timeout_s,overlap:e.overlap,on_output:e.on_output,sink:y(e.sink),tier:e.tier,state:e.state,held:e.held,run_state:e.run_state,last_run:t==null?null:{finished:t.finished,exit_code:t.exit_code,delivered:t.delivered},created:e.created,updated:e.updated}}r(xe,"toCronDTO");function Oe(e){return{run_id:e.run_id,started:e.started,finished:e.finished,duration_ms:e.duration_ms,exit_code:e.exit_code,stdout_head:e.stdout_head,stderr_head:e.stderr_head,delivered:e.delivered}}r(Oe,"toCronRunDTO");function De(e){return{id:e.profileId,app:e.manifest.grantee??"app:terminal",name:e.manifest.name,projects:e.manifest.projects.map(t=>({...t})),delivery_limits:{...e.manifest.delivery_limits},paused_at:e.manifest.paused_at,default_kind:e.manifest.default_kind??"general",metadata:O(e.manifest.metadata),default_dir:null,created_at:e.manifest.created_at,last_used_at:e.manifest.last_used_at,profile_path:x(e.profileId)}}r(De,"toProfileDTO");function m(e,t={}){const n={review_id:e.review_id,origin_kind:e.origin_kind,origin_node_id:e.origin_node_id,review_dir:e.review_dir,companion_node_id:e.companion_node_id,file:e.file,state:e.state,created:e.created,source_missing:e.source_missing,anchor_base_sha256:e.anchor_base_sha256};return e.document_name!==null&&(n.document=e.document_name),e.opened_at!==null&&(n.opened_at=e.opened_at),e.submit_requested_at!==null&&(n.submit_requested_at=e.submit_requested_at),e.approved_at!==null&&(n.approved_at=e.approved_at),e.changed!==null&&(n.changed=e.changed),e.comments_total!==null&&(n.comments_total=e.comments_total),e.comments_unresolved!==null&&(n.comments_unresolved=e.comments_unresolved),e.canceled_at!==null&&(n.canceled_at=e.canceled_at),e.cancel_reason!==null&&(n.cancel_reason=e.cancel_reason),e.cancel_actor!==null&&(n.cancel_actor=e.cancel_actor),t.result_path!==void 0&&(n.result_path=t.result_path),e.delivery_error!==null&&(n.delivery_error=e.delivery_error),e.projection_error!==null&&(n.projection_error=e.projection_error),n}r(m,"toReviewDTO");function Te(e){return{comment_id:e.comment_id,review_id:e.review_id,status:e.status,revision:e.revision,text:e.text,anchor:{...e.anchor},anchor_state:e.anchor_state,anchor_line_text:e.anchor_line_text,anchor_doc_hash:e.anchor_doc_hash,author:{kind:e.author.kind,...e.author.node_id===null?{}:{node_id:e.author.node_id}},updated_by:{kind:e.updated_by.kind,...e.updated_by.node_id===null?{}:{node_id:e.updated_by.node_id}},created_at:e.created_at,updated_at:e.updated_at,...e.resolved_at===null?{}:{resolved_at:e.resolved_at},...e.deleted_at===null?{}:{deleted_at:e.deleted_at},created_seq:e.created_seq}}r(Te,"toReviewCommentDTO");function B(e){return{id:e.id,quote:e.quote,...e.context===void 0?{}:{context:e.context},note:e.note,status:e.status,created_at:e.createdAt,...e.resolvedAt===void 0?{}:{resolved_at:e.resolvedAt}}}r(B,"toPageFeedbackCommentDTO");function Ee(e){return{companion_node_id:e.companionNodeId??null,open_count:e.comments.filter(t=>t.status==="open").length,comments:e.comments.map(B)}}r(Ee,"toPageFeedbackDTO");function Se(e){return{seq:e.seq,review_id:e.review_id,comment_id:e.comment_id,kind:e.kind,state_change:e.state_change===1,revision_after:e.revision_after,actor:{kind:e.actor.kind,...e.actor.node_id===null?{}:{node_id:e.actor.node_id}},at:e.at,operation_id:e.operation_id,...e.payload===void 0?{}:{payload:e.payload}}}r(Se,"toReviewCommentEventDTO");function Ae(e){return{file:e.file,submitted:e.submitted,approved:e.approved,comments:e.comments.map(n=>({...n})),submittedAt:e.submittedAt,savedAt:e.savedAt,reviewId:e.review_id,changed:e.changed,baselineSha256:e.baseline_sha256,approvedSha256:e.approved_sha256,companionNodeId:e.companion_node_id,commentsTotal:e.comments_total,commentsUnresolved:e.comments_unresolved}}r(Ae,"toFeedbackResultDTO");const L=!0,W=Object.freeze({review_origin_missing:{status:400,code:"review_origin_unavailable"},review_origin_unforkable:{status:400,code:"review_origin_unavailable"},review_branch_unavailable:{status:409,code:"review_branch_unavailable"},branch_lost:{status:409,code:"review_branch_unavailable"},review_companion_unbound:{status:409,code:"review_companion_unbound"},review_bridge_unsubscribed:{status:409,code:"review_bridge_unavailable"},review_target_unreviewable:{status:400,code:"review_file_unreadable"},source_unreadable:{status:409,code:"review_source_unreadable"},delivery_unroutable:{status:409,code:"review_delivery_unroutable"},unknown_review:{status:404,code:"unknown_review"},review_terminal:{status:409,code:"review_terminal_conflict"},review_required:{status:400,code:"review_required"},stale_document:{status:409,code:"stale_document"},stale_revision:{status:409,code:"stale_revision"},unknown_comment:{status:404,code:"unknown_comment"},comment_deleted:{status:409,code:"comment_deleted"},invalid_anchor:{status:400,code:"invalid_anchor"},anchor_out_of_range:{status:400,code:"anchor_out_of_range"},text_too_long:{status:400,code:"text_too_long"},comment_limit_reached:{status:409,code:"comment_limit_reached"},stale_comment:{status:409,code:"stale_comment"},range_batch_incomplete:{status:409,code:"range_batch_incomplete"},range_batch_stale:{status:409,code:"range_batch_stale"}});function $(e){const t=v(e);if(typeof t=="object"&&t!==null&&typeof t.status=="number"&&typeof t.code=="string")return{status:t.status,code:t.code};if(t instanceof R)return t.code==="unknown_node"?{status:404,code:"node_not_found"}:t.code==="already_finalized"?{status:409,code:"already_finalized"}:{status:409,code:"finalization_forbidden"};if(t instanceof z)return{status:409,code:"node_id_exists"};if(t instanceof N)return{status:403,code:"scope_denied"};if(C(t))return{status:400,code:"invalid_request"};if(t instanceof _)return W[t.code];if(t instanceof a)return["kind_owned","name_taken","hop_limit","not_a_queue"].includes(t.code)?{status:409,code:t.code}:t.code==="invalid_publish_token"?{status:401,code:t.code}:t.code==="forbidden"||t.code==="argv_forbidden"||t.code==="scope_missing"?{status:403,code:t.code}:{status:H(t.exitCode),code:t.code};if(t instanceof Error){const n=t.message;if(/unknown node/i.test(n))return{status:404,code:"node_not_found"};if(/finalization latch/i.test(n))return{status:409,code:"already_finalized"};if(/illegal lifecycle transition/i.test(n))return{status:409,code:"illegal_transition"}}return{status:500,code:"internal"}}r($,"errorToStatus");function v(e){if(!(e instanceof j))return e;const t=e.code==="unknown_node"?o.NOT_FOUND:o.GENERAL,n={error:e.code,message:e.message,next:e.next};return e.detail!==void 0&&(n.received=e.detail),new a(e.code,e.message,t,n)}r(v,"normalizeThrow");function K(e){if(e.code!=="review_terminal")return e.detail;const{review:t,...n}=e.detail;return{...n,review:V(t)}}r(K,"reviewErrorDetails");function V(e){return e.state!=="approved"?m(e):m(e,{result_path:h(e.review_dir,"result.json")})}r(V,"terminalConflictReviewDTO");function H(e){switch(e){case o.NOT_FOUND:return 404;case o.USAGE:return 400;case o.AMBIGUOUS:return 400;case o.NETWORK:return 503;case o.GENERAL:return 400;default:return 500}}r(H,"statusForExitCode");function J(e){const n=(e instanceof Error?e.message:String(e)).split(`
2
+ `,1)[0].trim();return n===""?"internal error":n.length>500?`${n.slice(0,497)}\u2026`:n}r(J,"boundedCause");function Re(e){const t=v(e),{status:n,code:i}=$(t);if(n>=500){const u={error:{code:i,message:J(t),origin:"runtime"}};return t instanceof s&&(u.error.retryable=t.retryable),{status:n,body:u}}const k=t instanceof Error?t.message:String(t),l=t instanceof _?K(t):(t instanceof a||t instanceof q||t instanceof s)&&t.details!==void 0?t.details:void 0,d={error:{code:i,message:k,origin:"runtime"}};return l!==void 0&&(d.error.details=l),t instanceof s&&(t.param&&(d.error.param=t.param),t.scope&&(d.error.scope=t.scope),d.error.retryable=t.retryable),{status:n,body:d}}r(Re,"toErrorBody");export{W as REVIEW_ERROR_MAP,$ as errorToStatus,he as toCloseResultDTO,xe as toCronDTO,Oe as toCronRunDTO,Re as toErrorBody,Ae as toFeedbackResultDTO,me as toGraphNodeDTO,ce as toMigrateStateDTO,ke as toNodeDetailDTO,P as toNodeEdgesDTO,p as toNodeOutcomeDTO,I as toNodeOutcomeSummaryDTO,U as toNodePathsDTO,ve as toNodeSummaryDTO,G as toNodeWorktreeDTO,pe as toOutcomeDeliveryDTO,B as toPageFeedbackCommentDTO,Ee as toPageFeedbackDTO,De as toProfileDTO,be as toReportResultDTO,Te as toReviewCommentDTO,Se as toReviewCommentEventDTO,m as toReviewDTO,ge as toReviveResultDTO,fe as toRunOutcomeDTO,ye as toSubscriptionDTO};
@@ -1 +1 @@
1
- var W=Object.defineProperty;var a=(e,t)=>W(e,"name",{value:t,configurable:!0});import{toErrorBody as j}from"./map.js";import{emitEvent as p}from"../../core/events/emit.js";import{scopeAllowed as f,ScopeDeniedError as N}from"../../core/scopes.js";import{coveredByAny as J}from"../../shared/env.js";import{ApiError as c}from"../../api/errors.js";import{activeGrant as B,grantFor as x}from"../../core/grants/mirror.js";import{getNode as _}from"../../core/canvas/canvas.js";import{ownedRun as z,RunError as g}from"../../core/runs/operations.js";import{nodeMayReach as H,placeMayReach as S}from"../../core/runs/confinement.js";import{checkCronFire as M}from"../cron/authority.js";import{readConfig as P}from"../../core/config.js";import{SCOPE_VOCABULARY as I}from"../../core/scopes.js";import{operationFor as L}from"./operations.js";import{CONTROL_BODY_MAX_BYTES as F}from"../../core/llm/body-limits.js";import{getRequest as Y,getRequestByInboxTicket as V}from"../../core/human/requests.js";import{requireVisibleReview as R}from"../../core/review/store.js";import{getComment as O}from"../../core/review/comments.js";function D(e,t,o,s,n){const r=e.path,u=n&&typeof n=="object"&&!Array.isArray(n)?n:{};if(r==="/v1/human/requests"||r==="/v1/human/reviews"){const d=r.endsWith("/reviews")?u.origin_node_id:u.requester_node_id,m=r==="/v1/human/requests"&&d==null;if(d!==t.node&&!m)throw new c(403,"other_app_run","a broker may create a human request only for its own node");const h=u.source;if(h&&typeof h=="object"&&"nodeId"in h&&h.nodeId!==t.node)throw new c(403,"other_app_run","request source must name the calling node")}if(r==="/v1/human/reviews/self/comments"&&e.method==="GET"&&s.get("actor_node_id")!==t.node)throw new c(403,"other_app_run","self review requires the calling node");if(r.includes("/comments")&&e.method!=="GET"&&u.actor_node_id!==t.node)throw new c(403,"other_app_run","comment author must be the calling node");if(o.comment_id&&!O(o.comment_id))throw new c(404,"not_found","comment not found")}a(D,"authorizeHumanBody");function y(e){return e.class==="broker"||e.class==="cron"}a(y,"boundedByStoredScopes");function b(e){return e.class==="person"||e.class==="anonymous"||e.class==="machine"?null:e.class==="forwarded"?e.actor.kind==="app"?e.actor.app:null:e.app}a(b,"appOf");function q(e){return e.class==="person"||e.class==="forwarded"&&e.actor.kind==="person"}a(q,"actsAsPerson");function $(e){const t=x(e.actor.app,e.sub);if(!t)throw new c(403,"app_not_granted",`${e.actor.app} holds no active grant for ${e.sub} on this machine`);return t}a($,"forwardedGrant");function v(e){if(e.class==="person"||e.class==="anonymous"||e.class==="machine")return[];if(e.class==="forwarded"){if(e.actor.kind==="person")return[];const{resolved:o}=$(e),s=e.actor.node_scopes;return s===null?o:s.filter(n=>J(o,n))}if(e.class==="app")return e.scopes;if(e.class==="cron"){const o=M({grantee:e.app,sub:e.sub,grant_id:e.grant,scopes:e.scopes});if(o.allowed)return o.effectiveScopes;throw o.reason==="grant_missing"||o.reason==="grant_revoked"?new c(401,"grant_revoked",o.message):new c(403,"scope_missing",o.message)}const t=e.grant?B(e.grant):x(e.app,e.sub);if(t&&t.grantee===e.app&&t.sub===e.sub)return t.resolved;if(e.app==="app:terminal"&&!P("user").runtime?.issuer)return I;throw new c(401,"grant_revoked","the node grant is not active")}a(v,"resolvedScopes");function k(e){return"class"in e?b(e):e.grantee}a(k,"runCallerApp");function l(e,t,o){return t===void 0||!("class"in e)?!0:e.class==="cron"?S({run:e.origin_run??"",isolated:e.isolated},e.app,t,o):e.class==="forwarded"?e.actor.kind!=="app"||S(e.actor.place,e.actor.app,t,o):e.class!=="broker"?!0:H(e.node,e.app,t,o)}a(l,"brokerMayReach");function X(e,t,o){const s=k(e);if(s===t)return l(e,o,t);if(s===null)return!0;const n="class"in e?null:B(e.grant),r="class"in e?v(e):n?.sub===e.sub&&n.grantee===e.grantee?n.resolved:[];return f(r,`crtr:conversations:read:${t}`)&&(!("class"in e)||!y(e)||f(e.scopes,`crtr:conversations:read:${t}`))}a(X,"canReadRun");function Be(e,t,o=!1,s=!1){const n=_(t);if(!n||n.parent!==null||n.run_id!==t||!n.grantee||n.deleting_at&&!s)throw new g(404,"not_found","run not found");if(!X(e,n.grantee,t))throw new g(404,"not_found","run not found");if(o&&k(e)!==null&&k(e)!==n.grantee)throw new g(403,"other_app_run","cannot change another app's run");return z(t,n.grantee,s)}a(Be,"requireRun");function C(e,t,o){return q(e)?!0:e.class==="anonymous"||e.class==="machine"?!1:b(e)===t?l(e,o,t):f(v(e),`crtr:objects:read:${t}`)&&(!y(e)||f(e.scopes,`crtr:objects:read:${t}`))}a(C,"canReadNode");const K=new Set(["messages.post.58","messages.post.59"]);function Q(e,t,o){if(!e.classes.includes(t.class)&&!(t.class!=="anonymous"&&t.class!=="machine"&&t.class!=="forwarded"&&e.classes.includes("anonymous")))throw new c(403,"permission_error","this operation is not available to the caller");if(t.class==="forwarded"&&t.actor.kind==="app"&&$(t),t.class==="person"||t.class==="anonymous"||t.class==="machine"||q(t))return;const s=v(t);if(e.scope&&(!f(s,e.scope)||y(t)&&!f(t.scopes,e.scope)))throw new c(403,"scope_missing",`missing scope ${e.scope}`);if(t.class==="app")return;const n=b(t);t.class==="broker"&&Z(e,t,o,s);const r=o.id;if((e.resource==="node-read"||e.resource==="node-write")&&r!==void 0){const u=_(r);if(!u)return;if(e.resource==="node-write"&&u.grantee!==n&&!(K.has(e.name)&&f(s,`crtr:objects:message:${u.grantee??"app:terminal"}`)))throw new c(403,"other_app_run","cannot change another app's node");if(e.resource==="node-write"&&!l(t,r,u.grantee??"app:terminal"))throw new c(404,"not_found","node not found");if(e.resource==="node-read"&&!C(t,u.grantee??"app:terminal",r))throw new c(404,"not_found","node not found")}}a(Q,"authorizeOperation");function Z(e,t,o,s){if(e.resource==="daemon-bash"&&(!f(s,"crtr:files:rw:user:.")||!f(t.scopes,"crtr:files:rw:user:.")))throw new c(403,"scope_missing","missing scope crtr:files:rw:user:.");if(e.resource==="human"){const r=e.path,u=e.method==="GET";if(!u&&(r.endsWith("/respond")||r.endsWith("/submit")||r.endsWith("/dismiss")||r.endsWith("/progress")||r.endsWith("/comment-ranges")||r.includes("/feedback-comments")))throw new c(403,"permission_error","only the person may answer or edit the human inbox");const d=o.request_id?Y(o.request_id):o.ticket_id?V(o.ticket_id):null,m=o.comment_id?O(o.comment_id):null,h=o.review_id?R(o.review_id):m?R(m.review_id):null,w=d?.requester_node_id??h?.origin_node_id;if(w!=null){const i=_(w);if(i&&(u?!C(t,i.grantee??"app:terminal",w):i.grantee!==t.app))throw new c(u?404:403,u?"not_found":"other_app_run","human request belongs to another app");if(i&&!u&&!l(t,w,i.grantee??"app:terminal"))throw new c(404,"not_found","human request not found")}else if(d||h)throw new c(403,"permission_error","only the person may access a request without a node")}const n=o.id;if(e.resource==="node-own"&&n!==void 0&&n!==t.node)throw new c(403,"other_app_run","the operation requires the calling node")}a(Z,"authorizeBrokerOnly");function ee(e,t){if(!f(e,t))throw new N("the bearer token",t)}a(ee,"assertCeiling");function te(){return new c(403,"owner_only","this operation is owner-only; a scoped token does not reach it")}a(te,"ownerOnlyError");function xe(e){return e.map(t=>({...t,ownerOnly:!0}))}a(xe,"ownerOnly");class Se{static{a(this,"Router")}routes=[];register(t){const o=L(t.method,t.pattern);if(!o)throw new Error(`route has no operation row: ${t.method} ${t.pattern}`);if(this.routes.some(s=>s.method===t.method.toUpperCase()&&s.operation.path===t.pattern))throw new Error(`duplicate route: ${t.method} ${t.pattern}`);return this.routes.push({operation:o,method:t.method.toUpperCase(),segments:A(t.pattern),handler:t.handler,maxBodyBytes:t.maxBodyBytes??F}),this}registerAll(t){for(const o of t)this.register(o);return this}match(t,o){const s=t.toUpperCase(),n=A(o);for(const r of this.routes){if(r.method!==s)continue;const u=oe(r.segments,n);if(u!==null)return{handler:r.handler,params:u,operation:r.operation,maxBodyBytes:r.maxBodyBytes}}return null}async handle(t,o,s,n={class:"person"}){try{const r=new URL(t.url??"/","http://127.0.0.1"),u=(t.method??"GET").toUpperCase(),d=this.match(u,r.pathname);if(d===null){U(o,404,"not_found",`no route for ${u} ${r.pathname}`);return}if(Q(d.operation,n,d.params),s!==null){if(d.operation.classes.length===1&&d.operation.classes[0]==="person")throw te();d.operation.scope&&ee(s,d.operation.scope)}let m;try{m=await ne(t,d.maxBodyBytes)}catch(i){const E=i instanceof T?"payload_too_large":"invalid_request";U(o,E==="payload_too_large"?413:400,E,i.message);return}n.class==="broker"&&d.operation.resource==="human"&&D(d.operation,n,d.params,r.searchParams,m);const h={method:u,path:r.pathname,params:d.params,query:r.searchParams,body:m,ceiling:s,principal:n,...n.class==="anonymous"&&typeof t.headers.authorization=="string"?{publishToken:t.headers.authorization.slice(7)}:{},req:t,res:o},w=await d.handler(h);o.writableEnded||re(o,w)}catch(r){const{status:u,body:d}=j(r);u>=500&&p({event:"api.request.failed",level:"error",error:r instanceof Error?r:new Error(String(r)),...n.class==="broker"?{node_id:n.node}:{},fields:{method:(t.method??"GET").toUpperCase(),path:t.url??""}}),G(o,u,d)}}}function A(e){return e.split("/").filter(t=>t.length>0)}a(A,"splitPath");function oe(e,t){if(e.length!==t.length)return null;const o={};for(let s=0;s<e.length;s++){const n=e[s],r=t[s];if(n.startsWith(":"))o[n.slice(1)]=decodeURIComponent(r);else if(n!==r)return null}return o}a(oe,"matchSegments");class T extends Error{static{a(this,"BodyTooLargeError")}}async function ne(e,t){const o=[];let s=0;for await(const r of e){const u=r;if(s+=u.length,s>t)throw new T(`request body exceeds ${t} bytes`);o.push(u)}if(s===0)return;const n=Buffer.concat(o).toString("utf8").trim();if(n!=="")try{return JSON.parse(n)}catch{throw new Error("request body is not valid JSON")}}a(ne,"readJsonBody");function re(e,t){if(e.headersSent)return;const o={...t.headers??{}};if(t.rawBody!==void 0){e.writeHead(t.status,o),e.end(t.rawBody);return}if(t.status===204||t.body===void 0){e.writeHead(t.status,o),e.end();return}o["content-type"]===void 0&&(o["content-type"]="application/json; charset=utf-8"),e.writeHead(t.status,o),e.end(JSON.stringify(t.body))}a(re,"writeResult");function G(e,t,o){if(e.headersSent){e.end();return}e.writeHead(t,{"content-type":"application/json; charset=utf-8"}),e.end(JSON.stringify(o))}a(G,"writeJson");function U(e,t,o,s){G(e,t,{error:{code:o,message:s}})}a(U,"writeError");export{Se as Router,q as actsAsPerson,b as appOf,ee as assertCeiling,l as brokerMayReach,C as canReadNode,X as canReadRun,xe as ownerOnly,te as ownerOnlyError,Be as requireRun,v as resolvedScopes,k as runCallerApp};
1
+ var W=Object.defineProperty;var a=(e,t)=>W(e,"name",{value:t,configurable:!0});import{toErrorBody as j}from"./map.js";import{emitEvent as p}from"../../core/events/emit.js";import{scopeAllowed as f,ScopeDeniedError as N}from"../../core/scopes.js";import{coveredByAny as J}from"../../shared/env.js";import{ApiError as c}from"../../api/errors.js";import{activeGrant as B,grantFor as x}from"../../core/grants/mirror.js";import{getNode as _}from"../../core/canvas/canvas.js";import{ownedRun as z,RunError as g}from"../../core/runs/operations.js";import{nodeMayReach as H,placeMayReach as S}from"../../core/runs/confinement.js";import{checkCronFire as M}from"../cron/authority.js";import{readConfig as P}from"../../core/config.js";import{SCOPE_VOCABULARY as I}from"../../core/scopes.js";import{operationFor as L}from"./operations.js";import{CONTROL_BODY_MAX_BYTES as F}from"../../core/llm/body-limits.js";import{getRequest as Y,getRequestByInboxTicket as V}from"../../core/human/requests.js";import{requireVisibleReview as R}from"../../core/review/store.js";import{getComment as O}from"../../core/review/comments.js";function D(e,t,o,s,n){const r=e.path,u=n&&typeof n=="object"&&!Array.isArray(n)?n:{};if(r==="/v1/human/requests"||r==="/v1/human/reviews"){const d=r.endsWith("/reviews")?u.origin_node_id:u.requester_node_id,m=r==="/v1/human/requests"&&d==null;if(d!==t.node&&!m)throw new c(403,"other_app_run","a broker may create a human request only for its own node");const h=u.source;if(h&&typeof h=="object"&&"nodeId"in h&&h.nodeId!==t.node)throw new c(403,"other_app_run","request source must name the calling node")}if(r==="/v1/human/reviews/self/comments"&&e.method==="GET"&&s.get("actor_node_id")!==t.node)throw new c(403,"other_app_run","self review requires the calling node");if(r.includes("/comments")&&e.method!=="GET"&&u.actor_node_id!==t.node)throw new c(403,"other_app_run","comment author must be the calling node");if(o.comment_id&&!O(o.comment_id))throw new c(404,"not_found","comment not found")}a(D,"authorizeHumanBody");function y(e){return e.class==="broker"||e.class==="cron"}a(y,"boundedByStoredScopes");function b(e){return e.class==="person"||e.class==="anonymous"||e.class==="machine"?null:e.class==="forwarded"?e.actor.kind==="app"?e.actor.app:null:e.app}a(b,"appOf");function q(e){return e.class==="person"||e.class==="forwarded"&&e.actor.kind==="person"}a(q,"actsAsPerson");function $(e){const t=x(e.actor.app,e.sub);if(!t)throw new c(403,"app_not_granted",`${e.actor.app} holds no active grant for ${e.sub} on this machine`);return t}a($,"forwardedGrant");function v(e){if(e.class==="person"||e.class==="anonymous"||e.class==="machine")return[];if(e.class==="forwarded"){if(e.actor.kind==="person")return[];const{resolved:o}=$(e),s=e.actor.node_scopes;return s===null?o:s.filter(n=>J(o,n))}if(e.class==="app")return e.scopes;if(e.class==="cron"){const o=M({grantee:e.app,sub:e.sub,grant_id:e.grant,scopes:e.scopes});if(o.allowed)return o.effectiveScopes;throw o.reason==="grant_missing"||o.reason==="grant_revoked"?new c(401,"grant_revoked",o.message):new c(403,"scope_missing",o.message)}const t=e.grant?B(e.grant):x(e.app,e.sub);if(t&&t.grantee===e.app&&t.sub===e.sub)return t.resolved;if(e.app==="app:terminal"&&!P("user").runtime?.issuer)return I;throw new c(401,"grant_revoked","the node grant is not active")}a(v,"resolvedScopes");function k(e){return"class"in e?b(e):e.grantee}a(k,"runCallerApp");function l(e,t,o){return t===void 0||!("class"in e)?!0:e.class==="cron"?S({run:e.origin_run??"",isolated:e.isolated},e.app,t,o):e.class==="forwarded"?e.actor.kind!=="app"||S(e.actor.place,e.actor.app,t,o):e.class!=="broker"?!0:H(e.node,e.app,t,o)}a(l,"brokerMayReach");function X(e,t,o){const s=k(e);if(s===t)return l(e,o,t);if(s===null)return!0;const n="class"in e?null:B(e.grant),r="class"in e?v(e):n?.sub===e.sub&&n.grantee===e.grantee?n.resolved:[];return f(r,`crtr:conversations:read:${t}`)&&(!("class"in e)||!y(e)||f(e.scopes,`crtr:conversations:read:${t}`))}a(X,"canReadRun");function Be(e,t,o=!1,s=!1){const n=_(t);if(!n||n.parent!==null||n.run_id!==t||!n.grantee||n.deleting_at&&!s)throw new g(404,"not_found","run not found");if(!X(e,n.grantee,t))throw new g(404,"not_found","run not found");if(o&&k(e)!==null&&k(e)!==n.grantee)throw new g(403,"other_app_run","cannot change another app's run");return z(t,n.grantee,s)}a(Be,"requireRun");function C(e,t,o){return q(e)?!0:e.class==="anonymous"||e.class==="machine"?!1:b(e)===t?l(e,o,t):f(v(e),`crtr:objects:read:${t}`)&&(!y(e)||f(e.scopes,`crtr:objects:read:${t}`))}a(C,"canReadNode");const K=new Set(["messages.post.58","messages.post.59"]);function Q(e,t,o){if(!e.classes.includes(t.class)&&!(t.class!=="anonymous"&&t.class!=="machine"&&t.class!=="forwarded"&&e.classes.includes("anonymous")))throw new c(403,"permission_error","this operation is not available to the caller");if(t.class==="forwarded"&&t.actor.kind==="app"&&$(t),t.class==="person"||t.class==="anonymous"||t.class==="machine"||q(t))return;const s=v(t);if(e.scope&&(!f(s,e.scope)||y(t)&&!f(t.scopes,e.scope)))throw new c(403,"scope_missing",`missing scope ${e.scope}`);if(t.class==="app")return;const n=b(t);t.class==="broker"&&Z(e,t,o,s);const r=o.id;if((e.resource==="node-read"||e.resource==="node-write")&&r!==void 0){const u=_(r);if(!u)return;if(e.resource==="node-write"&&u.grantee!==n&&!(K.has(e.name)&&f(s,`crtr:objects:message:${u.grantee??"app:terminal"}`)))throw new c(403,"other_app_run","cannot change another app's node");if(e.resource==="node-write"&&!l(t,r,u.grantee??"app:terminal"))throw new c(404,"not_found","node not found");if(e.resource==="node-read"&&!C(t,u.grantee??"app:terminal",r))throw new c(404,"not_found","node not found")}}a(Q,"authorizeOperation");function Z(e,t,o,s){if(e.resource==="daemon-bash"&&(!f(s,"crtr:files:rw:user:.")||!f(t.scopes,"crtr:files:rw:user:.")))throw new c(403,"scope_missing","missing scope crtr:files:rw:user:.");if(e.resource==="human"){const r=e.path,u=e.method==="GET";if(!u&&(r.endsWith("/respond")||r.endsWith("/submit")||r.endsWith("/dismiss")||r.endsWith("/progress")||r.endsWith("/comment-ranges")||r.includes("/feedback-comments")))throw new c(403,"permission_error","only the person may answer or edit the human inbox");const d=o.request_id?Y(o.request_id):o.ticket_id?V(o.ticket_id):null,m=o.comment_id?O(o.comment_id):null,h=o.review_id?R(o.review_id):m?R(m.review_id):null,w=d?.requester_node_id??h?.origin_node_id;if(w!=null){const i=_(w);if(i&&(u?!C(t,i.grantee??"app:terminal",w):i.grantee!==t.app))throw new c(u?404:403,u?"not_found":"other_app_run","human request belongs to another app");if(i&&!u&&!l(t,w,i.grantee??"app:terminal"))throw new c(404,"not_found","human request not found")}else if(d||h)throw new c(403,"permission_error","only the person may access a request without a node")}const n=o.id;if(e.resource==="node-own"&&n!==void 0&&n!==t.node)throw new c(403,"other_app_run","the operation requires the calling node")}a(Z,"authorizeBrokerOnly");function ee(e,t){if(!f(e,t))throw new N("the bearer token",t)}a(ee,"assertCeiling");function te(){return new c(403,"owner_only","this operation is owner-only; a scoped token does not reach it")}a(te,"ownerOnlyError");function xe(e){return e.map(t=>({...t,ownerOnly:!0}))}a(xe,"ownerOnly");class Se{static{a(this,"Router")}routes=[];register(t){const o=L(t.method,t.pattern);if(!o)throw new Error(`route has no operation row: ${t.method} ${t.pattern}`);if(this.routes.some(s=>s.method===t.method.toUpperCase()&&s.operation.path===t.pattern))throw new Error(`duplicate route: ${t.method} ${t.pattern}`);return this.routes.push({operation:o,method:t.method.toUpperCase(),segments:A(t.pattern),handler:t.handler,maxBodyBytes:t.maxBodyBytes??F}),this}registerAll(t){for(const o of t)this.register(o);return this}match(t,o){const s=t.toUpperCase(),n=A(o);for(const r of this.routes){if(r.method!==s)continue;const u=oe(r.segments,n);if(u!==null)return{handler:r.handler,params:u,operation:r.operation,maxBodyBytes:r.maxBodyBytes}}return null}async handle(t,o,s,n={class:"person"}){try{const r=new URL(t.url??"/","http://127.0.0.1"),u=(t.method??"GET").toUpperCase(),d=this.match(u,r.pathname);if(d===null){U(o,404,"not_found",`no route for ${u} ${r.pathname}`);return}if(Q(d.operation,n,d.params),s!==null){if(d.operation.classes.length===1&&d.operation.classes[0]==="person")throw te();d.operation.scope&&ee(s,d.operation.scope)}let m;try{m=await ne(t,d.maxBodyBytes)}catch(i){const E=i instanceof T?"payload_too_large":"invalid_request";U(o,E==="payload_too_large"?413:400,E,i.message);return}n.class==="broker"&&d.operation.resource==="human"&&D(d.operation,n,d.params,r.searchParams,m);const h={method:u,path:r.pathname,params:d.params,query:r.searchParams,body:m,ceiling:s,principal:n,...n.class==="anonymous"&&typeof t.headers.authorization=="string"?{publishToken:t.headers.authorization.slice(7)}:{},req:t,res:o},w=await d.handler(h);o.writableEnded||re(o,w)}catch(r){const{status:u,body:d}=j(r);u>=500&&p({event:"api.request.failed",level:"error",error:r instanceof Error?r:new Error(String(r)),...n.class==="broker"?{node_id:n.node}:{},fields:{method:(t.method??"GET").toUpperCase(),path:t.url??""}}),G(o,u,d)}}}function A(e){return e.split("/").filter(t=>t.length>0)}a(A,"splitPath");function oe(e,t){if(e.length!==t.length)return null;const o={};for(let s=0;s<e.length;s++){const n=e[s],r=t[s];if(n.startsWith(":"))o[n.slice(1)]=decodeURIComponent(r);else if(n!==r)return null}return o}a(oe,"matchSegments");class T extends Error{static{a(this,"BodyTooLargeError")}}async function ne(e,t){const o=[];let s=0;for await(const r of e){const u=r;if(s+=u.length,s>t)throw new T(`request body exceeds ${t} bytes`);o.push(u)}if(s===0)return;const n=Buffer.concat(o).toString("utf8").trim();if(n!=="")try{return JSON.parse(n)}catch{throw new Error("request body is not valid JSON")}}a(ne,"readJsonBody");function re(e,t){if(e.headersSent)return;const o={...t.headers??{}};if(t.rawBody!==void 0){e.writeHead(t.status,o),e.end(t.rawBody);return}if(t.status===204||t.body===void 0){e.writeHead(t.status,o),e.end();return}o["content-type"]===void 0&&(o["content-type"]="application/json; charset=utf-8"),e.writeHead(t.status,o),e.end(JSON.stringify(t.body))}a(re,"writeResult");function G(e,t,o){if(e.headersSent){e.end();return}e.writeHead(t,{"content-type":"application/json; charset=utf-8"}),e.end(JSON.stringify(o))}a(G,"writeJson");function U(e,t,o,s){G(e,t,{error:{code:o,message:s,origin:"runtime"}})}a(U,"writeError");export{Se as Router,q as actsAsPerson,b as appOf,ee as assertCeiling,l as brokerMayReach,C as canReadNode,X as canReadRun,xe as ownerOnly,te as ownerOnlyError,Be as requireRun,v as resolvedScopes,k as runCallerApp};