@north-light/cli 0.3.549 → 0.3.551
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/api/contract.d.ts +1 -1
- package/dist/api/contract.js +1 -1
- package/dist/api/dto/custom-objects.d.ts +1 -1
- package/dist/api/dto/docs.d.ts +12 -0
- package/dist/api/dto/objects.d.ts +17 -1
- package/dist/api/dto/objects.js +1 -1
- package/dist/api/dto/permissions.d.ts +76 -0
- package/dist/api/dto/permissions.js +1 -0
- package/dist/api/index.d.ts +3 -2
- package/dist/api/index.js +1 -1
- package/dist/api/routes.d.ts +4 -0
- package/dist/api/routes.js +1 -1
- package/dist/builtin-memory/crouter-concepts/documents.md +1 -1
- package/dist/builtin-memory/crouter-concepts/scopes-and-trust.md +2 -2
- package/dist/builtin-memory/crouter-sdk/release-notes.md +11 -0
- package/dist/builtin-memory/internal/INDEX.md +2 -1
- package/dist/builtin-memory/internal/agent-shaping.md +1 -1
- package/dist/builtin-memory/internal/storage-tiers.md +1 -1
- package/dist/builtin-memory/northlight-apps/guides/files-and-documents.md +3 -3
- package/dist/builtin-memory/northlight-apps/guides/many-users.md +1 -1
- package/dist/builtin-memory/northlight-apps/guides/test-your-app.md +1 -1
- package/dist/clients/attach/viewer.js +9 -9
- package/dist/commands/canvas/list.js +2 -2
- package/dist/commands/canvas/share.d.ts +2 -0
- package/dist/commands/canvas/share.js +2 -0
- package/dist/commands/canvas.js +1 -1
- package/dist/commands/doc/edit.js +1 -1
- package/dist/commands/doc/shared.js +1 -1
- package/dist/commands/doc/write.js +1 -1
- package/dist/commands/sys/sync-skills.js +2 -2
- package/dist/core/canvas/canvas.js +20 -20
- package/dist/core/canvas/db.js +4 -4
- package/dist/core/canvas/export-sqlite.js +2 -2
- package/dist/core/canvas/import-sqlite.js +5 -5
- package/dist/core/canvas/outcome-actions.js +3 -3
- package/dist/core/canvas/person.js +11 -9
- package/dist/core/canvas/schema-pg.sql +49 -5
- package/dist/core/environments.js +1 -1
- package/dist/core/feed/feed.js +1 -1
- package/dist/core/grants/mirror.d.ts +9 -1
- package/dist/core/grants/mirror.js +2 -2
- package/dist/core/grants/sync.js +1 -1
- package/dist/core/graph/access.d.ts +8 -49
- package/dist/core/graph/access.js +4 -7
- package/dist/core/graph/custom.d.ts +5 -2
- package/dist/core/graph/custom.js +9 -9
- package/dist/core/graph/deletion.js +5 -4
- package/dist/core/graph/documents.d.ts +12 -3
- package/dist/core/graph/documents.js +13 -7
- package/dist/core/graph/edges.js +3 -3
- package/dist/core/graph/events.js +12 -8
- package/dist/core/graph/kinds/document.js +4 -4
- package/dist/core/graph/kinds/kind.js +1 -1
- package/dist/core/graph/kinds/node.js +5 -5
- package/dist/core/graph/names.d.ts +16 -1
- package/dist/core/graph/names.js +11 -3
- package/dist/core/graph/objects.d.ts +19 -2
- package/dist/core/graph/objects.js +16 -10
- package/dist/core/graph/package-docs.js +5 -5
- package/dist/core/graph/package-files.js +2 -2
- package/dist/core/graph/reader.js +3 -3
- package/dist/core/graph/repo-sync/exchange.js +2 -2
- package/dist/core/graph/rules.d.ts +7 -5
- package/dist/core/graph/rules.js +3 -3
- package/dist/core/graph/types.d.ts +12 -1
- package/dist/core/graph/types.js +1 -1
- package/dist/core/graph/watches.d.ts +1 -1
- package/dist/core/graph/watches.js +9 -8
- package/dist/core/peer/envelope.d.ts +1 -1
- package/dist/core/peer/envelope.js +1 -1
- package/dist/core/peer/stubs.d.ts +1 -1
- package/dist/core/peer/stubs.js +1 -1
- package/dist/core/permissions/boot.d.ts +17 -0
- package/dist/core/permissions/boot.js +18 -0
- package/dist/core/permissions/builtin.d.ts +8 -0
- package/dist/core/permissions/builtin.js +20 -0
- package/dist/core/permissions/ceiling.d.ts +57 -0
- package/dist/core/permissions/ceiling.js +22 -0
- package/dist/core/permissions/compile.d.ts +14 -0
- package/dist/core/permissions/compile.js +1 -0
- package/dist/core/permissions/errors.d.ts +7 -0
- package/dist/core/permissions/errors.js +1 -0
- package/dist/core/permissions/evaluator.d.ts +28 -0
- package/dist/core/permissions/evaluator.js +6 -0
- package/dist/core/permissions/facts.d.ts +56 -0
- package/dist/core/permissions/facts.js +2 -0
- package/dist/core/permissions/schema-parser.d.ts +29 -0
- package/dist/core/permissions/schema-parser.js +2 -0
- package/dist/core/permissions/schemas.d.ts +21 -0
- package/dist/core/permissions/schemas.js +2 -0
- package/dist/core/permissions/sql.d.ts +16 -0
- package/dist/core/permissions/sql.js +1 -0
- package/dist/core/runtime/broker/frame-client.d.ts +1 -1
- package/dist/core/runtime/broker/frame-client.js +1 -1
- package/dist/core/runtime/broker/frame-dispatch.d.ts +1 -1
- package/dist/core/runtime/broker/frame-dispatch.js +1 -1
- package/dist/core/runtime/broker/frame-read.d.ts +4 -3
- package/dist/core/runtime/broker/frame-read.js +1 -1
- package/dist/core/runtime/broker-protocol.d.ts +1 -1
- package/dist/core/runtime/host.js +3 -3
- package/dist/core/runtime/placement.js +1 -1
- package/dist/core/runtime/roadmap.js +1 -1
- package/dist/core/substrate/delivery/corpus.d.ts +2 -2
- package/dist/core/substrate/delivery/corpus.js +3 -3
- package/dist/core/substrate/delivery/deliver.js +2 -2
- package/dist/core/substrate/delivery/render-event.js +6 -6
- package/dist/core/substrate/subject-fields.d.ts +2 -0
- package/dist/core/substrate/subject.js +1 -1
- package/dist/daemon/api/app-listener.js +12 -12
- package/dist/daemon/api/bridge.d.ts +1 -1
- package/dist/daemon/api/bridge.js +4 -4
- package/dist/daemon/api/handlers/attach.d.ts +4 -1
- package/dist/daemon/api/handlers/attach.js +1 -1
- package/dist/daemon/api/handlers/canvas.js +5 -5
- package/dist/daemon/api/handlers/check.d.ts +2 -0
- package/dist/daemon/api/handlers/check.js +1 -0
- package/dist/daemon/api/handlers/custom-objects.js +2 -2
- package/dist/daemon/api/handlers/docs.js +1 -1
- package/dist/daemon/api/handlers/files.js +1 -1
- package/dist/daemon/api/handlers/memory.js +7 -6
- package/dist/daemon/api/handlers/nodes.js +1 -1
- package/dist/daemon/api/handlers/objects.js +3 -3
- package/dist/daemon/api/handlers/relations.d.ts +2 -0
- package/dist/daemon/api/handlers/relations.js +1 -0
- package/dist/daemon/api/handlers/schemas.d.ts +12 -0
- package/dist/daemon/api/handlers/schemas.js +1 -0
- package/dist/daemon/api/handlers/shares.d.ts +2 -0
- package/dist/daemon/api/handlers/shares.js +1 -0
- package/dist/daemon/api/operations.js +1 -1
- package/dist/daemon/api/router.d.ts +10 -6
- package/dist/daemon/api/router.js +1 -1
- package/dist/daemon/api/server.js +1 -1
- package/dist/daemon/crtrd.js +12 -12
- package/dist/daemon/reconcilers/delivery-lane.js +2 -2
- package/dist/doc-editor/editor.css +1 -1
- package/dist/doc-editor/editor.js +16 -16
- package/dist/migrations/004-canvas-documents/fields.d.ts +1 -1
- package/dist/migrations/004-canvas-documents/fields.js +2 -2
- package/docs/apps/guides/files-and-documents.md +3 -3
- package/docs/apps/guides/many-users.md +1 -1
- package/docs/apps/guides/test-your-app.md +1 -1
- package/docs/cli/documents-and-preferences.md +1 -1
- package/docs/concepts/documents.md +1 -1
- package/docs/concepts/scopes-and-trust.md +2 -2
- package/docs/sdk/release-notes.md +11 -0
- package/package.json +2 -2
- package/packages/crouter-identity/dist/index.js +14 -1
- package/packages/crouter-identity/package.json +1 -1
- package/runtime.lock.json +13 -13
- package/dist/core/graph/spaces/app.d.ts +0 -3
- package/dist/core/graph/spaces/app.js +0 -1
- package/dist/core/graph/spaces/index.d.ts +0 -18
- package/dist/core/graph/spaces/index.js +0 -1
- package/dist/core/graph/spaces/own-memory.d.ts +0 -18
- package/dist/core/graph/spaces/own-memory.js +0 -1
- package/dist/core/graph/spaces/person.d.ts +0 -5
- package/dist/core/graph/spaces/person.js +0 -3
- package/dist/core/graph/spaces/repo.d.ts +0 -14
- package/dist/core/graph/spaces/repo.js +0 -1
- package/dist/core/runs/confinement.d.ts +0 -25
- package/dist/core/runs/confinement.js +0 -2
|
@@ -1,3 +1,3 @@
|
|
|
1
|
-
var
|
|
2
|
-
`;if(n===r&&o!==
|
|
3
|
-
`,{atomic:!0,mode:432}),P(b,oe,432);const ie=w(Z(e),`token-${
|
|
1
|
+
var Pe=Object.defineProperty;var u=(e,t)=>Pe(e,"name",{value:t,configurable:!0});import{assertGranteeRunsHere as Re}from"./unsandboxed.js";import{spawn as xe}from"node:child_process";import{mkdirSync as ue,existsSync as j,unlinkSync as fe,openSync as F,closeSync as N,writeSync as Oe,chmodSync as Te,lstatSync as De}from"node:fs";import{ensureAppSpace as Ne}from"../spaces/space.js";import{sandboxCacheEnv as Ae}from"../spaces/cache-env.js";import{compileLaunch as Ce,launchStillGranted as Le}from"../spaces/mounts.js";import{grantsGeneration as de}from"../grants/mirror.js";import{LAUNCHER_SOCKET as z}from"../../launcher/spec.js";import{launcherRequest as M}from"../../launcher/client.js";import{piAgentDir as Be}from"./package-health.js";import{existsBeneath as V,readFileBeneath as $e,readTextBeneathIfExists as je,setModeBeneath as P,withDirBeneath as X,writeFileBeneath as G}from"../spaces/open-beneath.js";import{dirname as Q,join as w,resolve as Fe,isAbsolute as Me}from"node:path";import{fileURLToPath as me}from"node:url";import{connectViewSocket as Ge}from"./view-socket.js";import{appSpace as K}from"../layout.js";import{readConfig as Ke,readMergedLaunchConfig as He}from"../config.js";import{readRotationConfig as Je}from"../subscription-state.js";import{getNode as _}from"../canvas/index.js";import{scopesFilePath as Y,crtrHome as pe,nodeRunDir as Z,nodeRunJobDir as qe,jobDir as Ue,viewSocketPath as We,nodeAgentDir as ze,contextDir as Ve,nodeHome as Xe}from"../canvas/paths.js";import{encodeFrame as he}from"./broker-protocol.js";import{buildBrokerEnv as Qe}from"./spawn-env.js";import{hostExecPathFresh as Ye}from"./branded-host.js";import{isPidAlive as I,killProcessTreePids as we,isAnyPidAlive as Ze,captureTeardownSnapshot as Ie}from"../canvas/pid.js";import{assertMandatoryCanvasExtensions as er}from"./canvas-extensions.js";import{appMemoryFull as rr,appMemoryTooSmall as tr,boundFleet as nr,brokerCapReached as or,brokerThresholdsForDaemon as ir}from"./fleet.js";import{admitBrokerMemory as sr}from"./memory-admission.js";import{emitEvent as E}from"../events/emit.js";import{bindBrokerEventSource as ar,eventSource as cr}from"../events/source.js";import{envBrokerEngine as lr}from"../../shared/env.js";import{conversationIdFromPath as ur,conversationStore as fr,ConversationNotFoundError as ge,storeAddress as dr}from"../conversation-store/index.js";import{takeNodeToken as mr}from"../canvas/node-tokens.js";import{personId as pr}from"../canvas/person.js";function H(){const e=Q(me(import.meta.url));return w(e,"broker-cli.js")}u(H,"resolveBrokerEntry");const hr="@earendil-works/pi-coding-agent";function wr(e,t){const n=w(Be(),"models.json"),r=w(t,"models.json"),o=je(Q(n),n);if(o===null)return;const d=JSON.parse(o),s=u(f=>Array.isArray(f)?f.map(s):f===null||typeof f!="object"?f:Object.fromEntries(Object.entries(f).filter(([i])=>!/^(apiKey|authorization|headers|token|secret)$/i.test(i)).map(([i,m])=>[i,s(m)])),"scrub"),c=`${JSON.stringify(s(d),null,2)}
|
|
2
|
+
`;if(n===r&&o!==c){if(JSON.stringify(d)!==JSON.stringify(s(d)))throw new Error("terminal models.json contains credentials; move them into daemon secrets");P(e,r,432);return}G(e,r,c,{atomic:!0,mode:432}),P(e,r,432)}u(wr,"writeBrokerModels");function Ee(e){return e.env.CRTR_BROKER_ENGINE??lr()}u(Ee,"resolveEngineSpec");function ke(e){return e.includes("/")||e.endsWith(".jsonl")}u(ke,"isPlainLaunchSessionPath");function gr(e,t){return Me(e)?e:Fe(t,e)}u(gr,"resolvePlainLaunchPath");async function Er(e,t,n,r){if(n==="--session"&&!ke(r))throw new Error(`[broker] refusing to launch ${e}: launch recipe passes bare --session id '${r}' \u2014 the broker fatally rejects bare ids; pass the .jsonl path instead.`);if(!ke(r))return;const o=gr(r,t),d=ur(o);try{if(d===null)throw new ge(o);await fr().header(d)}catch(s){if(!(s instanceof ge))throw s;const c=n==="--session"?"session file":"fork source";throw new Error(`[broker] refusing to launch ${e}: launch recipe references missing ${c} '${r}' (${o})`)}}u(Er,"preflightLaunchSessionArg");async function kr(e,t,n){const r=Z(e);ue(r,{recursive:!0}),process.platform==="linux"&&j(z)&&De(r).uid===process.getuid()&&Te(r,504);const o=w(r,"broker-launch.json"),d={user:Ke("user"),launch:He(n,t.env.CRTR_PROFILE_ID||null),rotation:Je()};G(r,o,JSON.stringify({...t,configSnapshot:d}),{atomic:!0}),t.env.CRTR_SCOPES_FILE!==void 0&&G(r,Y(e),JSON.stringify((await _(e))?.scopes??[]),{atomic:!0});const s=$e(r,o).toString("utf8"),c=JSON.parse(s);if(!Array.isArray(c.argv))throw new Error(`[broker] refusing to launch ${e}: broker-launch.json is missing the argv array`);const f=Ee(t);try{const l=import.meta.resolve(f);if(l.startsWith("file:")&&!j(me(l)))throw new Error(`resolved to missing file ${l}`)}catch(l){throw new Error(`[broker] refusing to launch ${e}: cannot resolve broker engine '${f}' from ${H()} \u2014 ${l.message}`)}const i=c.argv,m=[];for(let l=0;l<i.length;l++){const R=i[l];if(R==="-e"){const A=i[++l];A!==void 0&&m.push(A);continue}if(R!=="--session"&&R!=="--fork")continue;const O=i[++l];O!==void 0&&await Er(e,n,R,O)}try{er(m)}catch(l){throw new Error(`[broker] refusing to launch ${e}: ${l.message}`)}}u(kr,"preflightBrokerLaunch");const vr=2e3,_r=2e3,yr=150;async function J(e,t){const n=Date.now()+t;for(;Ze(e);){const r=n-Date.now();if(r<=0)return!1;await new Promise(o=>setTimeout(o,Math.min(yr,r)))}return!0}u(J,"waitForTreeExit");async function Sr(e,t,n){return e.length===0?{confirmed:!0}:n&&await J(e,vr)?{confirmed:!0}:(we(e,"SIGTERM",t),await J(e,_r)?{confirmed:!0}:(we(e,"SIGKILL",t),await J(e,5e3)?{confirmed:!0}:{confirmed:!1,error:new Error(`broker process tree for ${e.join(", ")} remained alive after SIGKILL`)}))}u(Sr,"terminateBrokerTree");async function ve(e,t){const n=await _(e),r=n?.pi_pid,o=r!=null?Ie(r,n?.pi_pid_identity??null,t.excludePid):null;return o?.reused===!0&&E({level:"warn",event:"broker.teardown.pid_reuse_refused",node_id:e,fields:{recorded_pid:r,expected_identity:n?.pi_pid_identity??null}}),{tree:o?.tree??[],identities:o?.identities??null,nodeId:e,launcherPid:j(z)&&o?.tree.includes(r)?r:null}}u(ve,"prepareBrokerTeardown");async function _e(e){if(e.launcherPid!==null){try{await M({operation:"stop",pid:e.launcherPid})}catch(t){return I(e.launcherPid)?{confirmed:!1,error:t instanceof Error?t:new Error(String(t))}:{confirmed:!0}}return await J([e.launcherPid],5e3)?{confirmed:!0}:{confirmed:!1,error:new Error(`launcher pid ${e.launcherPid} remained alive`)}}return new Promise(t=>{let n=!1,r=!1;const o=u(f=>{r||(r=!0,t(f))},"settle"),d=u(()=>{try{fe(We(e.nodeId))}catch{}},"cleanupSocket"),s=u(f=>{Sr(e.tree,e.identities,f).then(o,i=>o({confirmed:!1,error:i instanceof Error?i:new Error(String(i))}))},"finish"),c=Ge(e.nodeId);c.once("error",()=>{n||(d(),s(!1))}),c.once("connect",()=>{n=!0;try{c.write(he({type:"hello",role:"controller",client_id:`daemon-shutdown-${process.pid}`})),c.write(he({type:"shutdown"}))}catch{}c.end(),d(),s(!0)})})}u(_e,"runPreparedBrokerTeardown");const q=new Map;async function nt(e,t={},n){const r=q.get(e);if(r!==void 0)return n!==void 0&&r.after.push(n),r.completion;let o;const d=new Promise(i=>{o=i}),s={completion:d,resolve:o,after:n===void 0?[]:[n]};q.set(e,s);let c;try{c=await ve(e,t)}catch(i){const m={confirmed:!1,error:i instanceof Error?i:new Error(String(i))};return q.delete(e),E({level:"error",event:"broker.teardown.unconfirmed",node_id:e,error:m.error}),s.resolve(m),d}const f=u(()=>{q.delete(e),_e(c).then(async i=>{if(i.confirmed)for(const m of s.after)try{await m()}catch(l){E({level:"error",event:"broker.teardown.after_failed",node_id:e,error:l})}else E({level:"error",event:"broker.teardown.unconfirmed",node_id:e,error:i.error});s.resolve(i)},i=>{const m={confirmed:!1,error:i instanceof Error?i:new Error(String(i))};E({level:"error",event:"broker.teardown.unconfirmed",node_id:e,error:m.error}),s.resolve(m)})},"run");return t.startAfter===void 0?setImmediate(f):t.startAfter.then(f,f),d}u(nt,"requestBrokerTeardown");function ye(){return process.platform==="linux"&&j(z)}u(ye,"isolatedBrokerLauncherAvailable");const ot={async launch(e,t,n){if(Re((await _(e))?.grantee),(await _(e))?.isolated===!0&&!ye())throw new Error("isolated broker requires the Linux root launcher");await kr(e,t,n.cwd);const r=nr();if(!r.reserveSlot(e))throw or(ir().automaticReviveCap,r.size());let o=null,d,s=!1;try{const c=Ue(e);ue(c,{recursive:!0}),o=F(w(c,"broker.log"),"a");const f=Ee(t),i={...Qe(t),CRTR_BROKER_ENGINE:f,CRTR_STORE_ADDRESS:dr()};if(f!==hr){const a=t.env.NODE_OPTIONS??process.env.NODE_OPTIONS;a!==void 0&&(i.NODE_OPTIONS=a)}cr()===void 0&&ar(e);const m=(await _(e))?.run_id;if(m){const a=await _(m);if(!a||a.deleting_at)throw new Error("run is deleting")}const l=t.env.CRTR_EXECUTION_ID;if(!l)throw new Error("broker launch has no execution id");const R=mr(l),O=ye();if((await _(e))?.isolated===!0&&!O)throw new Error("isolated broker requires the Linux root launcher");if(process.platform==="linux"&&process.env.CRTR_LAUNCHER_SOCKET&&!O)throw new Error("root launcher socket is unavailable; refusing an unsandboxed broker");if(O){const a=await _(e);if(!a)throw new Error(`missing node ${e}`);const h=a.grantee??"app:terminal",x=await sr(e,{useMemo:!1});if(x.verdict==="denied")throw rr(x);if(x.verdict==="too_small")throw tr(x);const y=await Ne(h);Object.assign(i,Ae(h));const S={uid:process.getuid(),gid:y.gid},g=Z(e);for(const[p,k]of[[K(h).nodes,ze(e,h)],[K(h).nodes,Ve(e,h)],[g,qe(e)]])X(p,k,()=>{},!0),P(p,k,1528,S);P(g,w(g,"broker-launch.json"),416,S),V(g,Y(e))&&P(g,Y(e),416,S);const te=w(g,"system-prompt.md");V(g,te)&&P(g,te,432,S);for(const p of["output-schema.json","situational-context.md"]){const k=w(g,p);V(g,k)&&P(g,k,432,S)}const ne=a.isolated===!0,b=Xe(e,h,ne);ne&&(X(K(h).nodes,b,()=>{},!0),P(K(h).nodes,b,1528,S),i.HOME=b,i.PI_CODING_AGENT_DIR=w(b,".pi","agent"));const W=w(b,".pi","agent");X(b,W,()=>{},!0),wr(b,W);const oe=w(W,"settings.json"),Se=w(Q(H()),"../../builtin-pi-packages/pi-crtr-extensions");G(b,oe,`${JSON.stringify({packages:[Se]})}
|
|
3
|
+
`,{atomic:!0,mode:432}),P(b,oe,432);const ie=w(Z(e),`token-${l}`),L=F(ie,"wx+",384);fe(ie),Oe(L,R);const se=[F(`/proc/self/fd/${L}`,"r"),F(`/proc/self/fd/${L}`,"r")];N(L);const ae={nodeId:e,app:h,sub:a.sub??pr(),grantId:a.grant_id??null,scopes:a.scopes??null,isolated:a.isolated===!0,...a.isolated===!0?{cwd:a.cwd}:{},command:[process.execPath,H(),"--canvas-home",pe(),"--epoch",r.epoch(),e],env:Object.fromEntries(Object.entries({...i,...a.isolated===!0?{PWD:a.cwd}:{}}).filter(p=>p[1]!==void 0)),auditMissing:u(p=>E({level:"warn",event:"broker.mount.missing",node_id:e,fields:{source:p}}),"auditMissing")};try{let p;for(const D of se){const B=await de(),v=await Ce(ae);v.broker=!0;const $=await M({operation:"launch",spec:v},[D]);if(!("pid"in $))throw new Error("launcher did not return a pid");if(await de()===B||await Le(ae,v)){p=$.pid;break}E({level:"info",event:"broker.launch.regranted",node_id:e,fields:{pid:$.pid}}),await M({operation:"stop",pid:$.pid,signal:"SIGKILL"}).catch(()=>{})}if(p===void 0)throw new Error("grant changed during every launch attempt");const k=p,be=Date.now(),ce=new Promise(D=>{const B=setInterval(()=>{I(k)||(clearInterval(B),M({operation:"exit.status",pid:k}).then(v=>"oomKilled"in v&&v.oomKilled,()=>!1).then(v=>{E({level:v?"warn":"info",event:"broker.exited",node_id:e,fields:{pid:k,uptime_ms:Date.now()-be,oom_killed:v}}),D({code:null,signal:null,...v?{oomKilled:!0}:{}})}))},250);B.unref()});N(o),o=null;const le={pid:k,exited:ce};return r.register(e,le),s=!0,ce.then(async D=>await r.onChildExit(e,D,l)),le}finally{for(const p of se)N(p)}}const A=await Ye(),T=xe(A,[H(),"--canvas-home",pe(),"--epoch",r.epoch(),e],{cwd:n.cwd,detached:!0,stdio:["ignore",o,o,"pipe"],env:i});d=T;const C=T.stdio[3];if(!C||!("end"in C))throw new Error("broker token pipe did not open");C.on("error",a=>E({event:"broker.token_pipe.failed",level:"error",node_id:e,error:a})),C.end(R),N(o),o=null;const ee=Date.now(),re=new Promise(a=>{let h=!1;const x=u(y=>{h||(h=!0,a(y))},"finish");T.once("exit",(y,S)=>{E({level:y===0?"info":"warn",event:"broker.exited",node_id:e,fields:{code:y,signal:S,uptime_ms:Date.now()-ee}}),x({code:y,signal:S})}),T.once("error",y=>{E({level:"error",event:"broker.launch.failed",node_id:e,error:y,fields:{uptime_ms:Date.now()-ee}}),x({code:null,signal:null})})});T.unref();const U={pid:T.pid??null,exited:re};return U.pid!==null&&(r.register(e,U),s=!0,re.then(async a=>await r.onChildExit(e,a,l))),U}catch(c){if(!s&&d?.pid!=null)try{d.kill("SIGTERM")}catch{}throw c}finally{s||r.releaseReservation(e),o!==null&&N(o)}},async isAlive(e){return I((typeof e=="string"?await _(e):e)?.pi_pid)},async teardown(e,t={}){try{return _e(await ve(e,t))}catch(n){return Promise.resolve({confirmed:!1,error:n instanceof Error?n:new Error(String(n))})}},async signal(e,t){const n=(await _(e))?.pi_pid;if(n!=null)try{process.kill(n,t)}catch{}}};export{ot as headlessBrokerHost,ye as isolatedBrokerLauncherAvailable,kr as preflightBrokerLaunch,nt as requestBrokerTeardown};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
var V=Object.defineProperty;var s=(e,n)=>V(e,"name",{value:n,configurable:!0});import{envNodeId as $}from"../../shared/env.js";import{getNode as m,fullName as H,deleteNode as R,listNodes as M,openFocusRow as z,closeFocusRow as u,getFocusByNode as T,getFocusByPane as _,getFocusById as D,listFocuses as J}from"../canvas/index.js";import{nodeHasAssistantMessage as Q}from"../canvas/render-source.js";import{headlessBrokerHost as k}from"./host.js";import{publishNotice as U}from"./close.js";import{paneExists as p,paneLocation as x,closePane as P,currentTmux as
|
|
1
|
+
var V=Object.defineProperty;var s=(e,n)=>V(e,"name",{value:n,configurable:!0});import{envNodeId as $}from"../../shared/env.js";import{getNode as m,fullName as H,deleteNode as R,listNodes as M,openFocusRow as z,closeFocusRow as u,getFocusByNode as T,getFocusByPane as _,getFocusById as D,listFocuses as J}from"../canvas/index.js";import{nodeHasAssistantMessage as Q}from"../canvas/render-source.js";import{headlessBrokerHost as k}from"./host.js";import{publishNotice as U}from"./close.js";import{paneExists as p,listLivePanesAsync as X,paneLocation as x,closePane as P,currentTmux as j,switchClient as q,selectWindow as G,selectLayout as K,selectPane as A,getPaneOption as Y,setPaneOption as Z,respawnPaneSync as I,windowOfPane as ee,renameWindow as ne}from"./tmux-driver.js";import{openViewerPane as ae,viewerSplitEnv as S,waitForBrokerViewSocket as ie}from"./placement-tmux.js";import{newJobId as te}from"./nodes.js";import{isPidAlive as h}from"../canvas/pid.js";import{splitWindow as Re,breakPane as Te,selectLayout as ke,selectPane as Ae,focusWindow as Se,selectWindow as We,switchClient as be,openNodeWindow as Be,ensureSession as Ee,paneLocation as Le,paneExists as Ce,paneRunning as Ve,paneCurrentPath as $e,currentTmux as He,inTmux as Me,paneOfNode as ze,setPaneOption as De,getPaneOption as Je,piCommand as Qe,shellQuote as Ue,respawnPaneSync as Xe,closePane as je,displayPopup as qe,windowOfPane as Ge,renameWindow as Ke,paneOfWindow as Ye,windowAlive as Ze,listLivePanes as Ie,listLivePanesAsync as en}from"./tmux-driver.js";import{installTmuxBindings as an}from"./tmux-bindings.js";async function g(e,n=null){return e===null?null:e.pane!==null&&!(n!==null?n.has(e.pane):p(e.pane))?(await u(e.focus_id),null):e}s(g,"liveOrPrune");async function w(e){return await g(await T(e))}s(w,"focusOf");async function _e(e){return await w(e)!==null}s(_e,"isFocused");async function se(e){return await g(await _(e))}s(se,"focusByPane");async function xe(){return new Set((await oe()).map(e=>e.node_id))}s(xe,"focusedNodes");async function oe(){const e=[],n=await J(),i=n.some(a=>a.pane!==null)?await X():null;for(const a of n)await g(a,i)!==null&&e.push(a);return e}s(oe,"listFocuses");function re(){return`f-${te()}`}s(re,"newFocusId");async function W(e,n,i,a){const l=await _(n);if(l!==null)return l;const o=await T(e);if(o!==null)return o;const r=re();return await z(r,n,i,e),await D(r)}s(W,"registerViewerFocus");async function b(e,n,i={}){const a=ae(e,n,i);return a===null?null:await W(e,a.pane,a.session,a.window)}s(b,"openViewerWindow");function B(e){const n=x(e)?.window??null;n!==null&&K(n,"even-horizontal"),A(e)}s(B,"surfaceNewPane");async function he(e,n){const i=await m(e);if(i===null)return{focused:!1,session:null,inPlace:!1,revived:!1};const a=n.pane??process.env.TMUX_PANE??j()?.pane;if(a===void 0||a==="")return{focused:!1,session:null,inPlace:!1,revived:!1};const l=h(i.pi_pid??null),o=n.revive(e),r=!l;if(!await ie(e,o?.launch?.exited))return{focused:!1,session:null,inPlace:!1,revived:r};const y=x(a)?.session??null,N=y??"";if(n.inPlace===!0){const t=await w(e);t!==null&&(t.pane!==null&&t.pane!==a&&p(t.pane)&&P(t.pane),await u(t.focus_id));const c=await _(a);c!==null&&c.node_id!==e&&await u(c.focus_id);try{Z(a,"@crtr_node","")}catch{}const v=ee(a),F=c?.node_id,C=F===void 0?S():{...S(),CRTR_ATTACH_ROSTER:F},O=I({pane:a,cwd:i.cwd,env:C,command:`crtr surface attach to ${e}`});return O&&(v!==null&&ne(v,H(i)),await W(e,a,y,v)),{focused:O,session:y,inPlace:!0,revived:r}}if(n.newPane===!0){const t=await w(e);t!==null&&(t.pane!==null&&p(t.pane)&&P(t.pane),await u(t.focus_id));const c=await b(e,N,{cwd:i.cwd,besidePane:a});return c===null?{focused:!1,session:null,inPlace:!1,revived:r}:(c.pane!==null&&B(c.pane),{focused:!0,session:c.session,inPlace:!1,revived:r})}const f=await w(e);if(f!==null&&f.pane!==null)if(Y(f.pane,"@crtr_node")===e){const t=x(f.pane);if(t!==null)return q(t.session),G(t.session,t.window),A(f.pane),{focused:!0,session:t.session,inPlace:!0,revived:r};await u(f.focus_id)}else await u(f.focus_id);const d=await b(e,N,{cwd:i.cwd,besidePane:a});return d===null?{focused:!1,session:null,inPlace:!1,revived:r}:(d.pane!==null&&B(d.pane),{focused:!0,session:d.session,inPlace:!1,revived:r})}s(he,"focus");async function E(e,n){const i=await w(e);i!==null&&(i.pane!==null&&i.pane!==n&&p(i.pane)&&P(i.pane),await u(i.focus_id))}s(E,"tearDownNode");async function ge(e,n){const i=n??(await w(e))?.pane??null;if(i===null||!p(i))return!1;const a=await se(i);a!==null&&await u(a.focus_id);const l=P(i);return await le(e),l}s(ge,"detachToBackground");async function L(e){const n=await m(e);return n===null||n.streaming===!0&&h(n.pi_pid)?!1:!await Q(n.pi_session_file)}s(L,"isEmptyNode");async function le(e,n,i=!0){return(await m(e))?.managed_worktree?.state==="open"||!await L(e)?!1:(i&&k.teardown(e),await E(e,n),(await R(e)).deleted)}s(le,"reapIfEmpty");async function Ne(e={}){const n=e.dryRun??!1,i=$()??"",a=[];for(const l of await M()){const o=l.node_id,r=await m(o);o===i||l.status==="dead"||h(l.pi_pid)||r?.managed_worktree?.state==="open"||!await L(o)||!n&&(await U(o,"notice.close",`Child closed \u2014 ${r?.name??o} (${o}) was closed from the canvas and is no longer running.`,{reason:"child-closed",child:o}),k.teardown(o),await E(o),!(await R(o)).deleted)||a.push(o)}return a}s(Ne,"reapEmptyNodes");export{Te as breakPane,je as closePane,He as currentTmux,ge as detachToBackground,qe as displayPopup,Ee as ensureSession,he as focus,se as focusByPane,w as focusOf,Se as focusWindow,xe as focusedNodes,Je as getPaneOption,Me as inTmux,an as installTmuxBindings,_e as isFocused,oe as listFocuses,Ie as listLivePanes,en as listLivePanesAsync,Be as openNodeWindow,b as openViewerWindow,$e as paneCurrentPath,Ce as paneExists,Le as paneLocation,ze as paneOfNode,Ye as paneOfWindow,Ve as paneRunning,Qe as piCommand,Ne as reapEmptyNodes,le as reapIfEmpty,W as registerViewerFocus,Ke as renameWindow,Xe as respawnPaneSync,ke as selectLayout,Ae as selectPane,We as selectWindow,De as setPaneOption,Ue as shellQuote,Re as splitWindow,be as switchClient,E as tearDownNode,Ze as windowAlive,Ge as windowOfPane};
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
var l=Object.defineProperty;var r=(t,e)=>l(t,"name",{value:e,configurable:!0});import{openDb as u,withCanvasWrite as s}from"../canvas/db.js";import{get as c}from"../graph/bodies.js";import{heads as d,writeDocument as m}from"../graph/documents.js";import{asRuntimeWriter as p}from"../
|
|
1
|
+
var l=Object.defineProperty;var r=(t,e)=>l(t,"name",{value:e,configurable:!0});import{openDb as u,withCanvasWrite as s}from"../canvas/db.js";import{get as c}from"../graph/bodies.js";import{heads as d,writeDocument as m}from"../graph/documents.js";import{asRuntimeWriter as p}from"../permissions/ceiling.js";import{getById as f,liveDocumentNamed as w,nodeObject as h}from"../graph/objects.js";import{readerForNode as y}from"../graph/reader.js";const o="roadmap",g="To understand this node's long-term task and current plan, read this.";function x(t){return t?.split(`
|
|
2
2
|
`).map(n=>n.trim()).find(n=>n!=="")??g}r(x,"roadmapPreview");function P(t){return`${t}/${o}`}r(P,"roadmapRef");async function i(t,e){const n=await f(t,e);return n===null||n.type!=="node"?null:await w(t,n.id,o)}r(i,"roadmapObject");async function $(t){return await i(await u(),t)!==null}r($,"hasRoadmap");async function M(t){const e=await u(),n=await i(e,t);if(n===null)return null;const a=(await d(e,n))[0];if(a===void 0)return null;try{return c(a.body_hash)}catch{return null}}r(M,"readRoadmap");function R(t){return`# Roadmap
|
|
3
3
|
|
|
4
4
|
## Goal
|
|
@@ -13,8 +13,8 @@ export declare function typedLimitKey(owner: ObjectRow): string;
|
|
|
13
13
|
* reader's own profile is never capped, even when a bare key shares its handle
|
|
14
14
|
* with another owner; an owner the profile does not name is uncapped. */
|
|
15
15
|
export declare function deliveryLimitFor(manifest: ProfileManifest | null, owner: ObjectRow, reader?: Reader): Rung;
|
|
16
|
-
/** Documents with a rule on one of `on`
|
|
17
|
-
*
|
|
16
|
+
/** Documents with a rule on one of `on` that the reader may read, in view order. At `boot` a node's own documents come in even without a
|
|
17
|
+
* boot rule. */
|
|
18
18
|
export declare function loadCorpus(db: CanvasDb, reader: Reader, on: RuleOn[]): Promise<DeliveryDoc[]>;
|
|
19
19
|
/** One document as a delivery document for `reader`, with all its rules (an explicit read). */
|
|
20
20
|
export declare function deliveryDocOf(db: CanvasDb, reader: Reader, doc: ObjectRow): Promise<DeliveryDoc>;
|
|
@@ -1,3 +1,3 @@
|
|
|
1
|
-
var
|
|
2
|
-
WHERE o.type = 'document' AND o.deleted_at IS NULL AND ${
|
|
3
|
-
ORDER BY number DESC LIMIT 1`).get(e.id,...
|
|
1
|
+
var S=Object.defineProperty;var a=(n,e)=>S(n,"name",{value:e,configurable:!0});import{permits as D,resolveReader as L}from"../../permissions/evaluator.js";import{bodyOf as M}from"../../graph/bodies.js";import{resolveName as A,viewOf as v,viewResolutions as $}from"../../graph/names.js";import{rulesOn as C,rulesOf as g}from"../../graph/rules.js";import{loadExactProfileManifest as H}from"../../profiles/manifest.js";import{assembleNodeSubject as I}from"../subject.js";import{mapAsync as x}from"../../async-array.js";function R(n){return n.type==="node"?n.id:n.name}a(R,"ownerHandle");function T(n){return`${n.type}:${R(n)}`}a(T,"typedLimitKey");function q(n,e,o){if(o?.class==="node"&&o.profile!==null&&o.profile.id===e.id)return"content";const i=n?.delivery_limits;return i?i[T(e)]??i[R(e)]??"content":"content"}a(q,"deliveryLimitFor");async function N(n,e){if(e.class!=="node"||e.profile===null)return null;const o=await n.prepare("SELECT external_id FROM identities WHERE object = ? AND scheme = 'profile'").get(e.profile.id);if(!o)throw new Error(`profile object ${e.profile.id} has no profile identity`);return H(o.external_id).manifest}a(N,"readerManifest");async function h(n,e,o,i){const t=await D(n,e,"read","o");return await n.prepareUncached(`SELECT o.*, d.heads_key, d.unlisted, d.source_path FROM objects o JOIN documents d ON d.object = o.id
|
|
2
|
+
WHERE o.type = 'document' AND o.deleted_at IS NULL AND ${o} AND ${t.sql} ORDER BY o.seq`).all(...i,...t.params)}a(h,"documentRows");async function F(n,e){const o=e.heads_key.split(","),i=await n.prepareUncached(`SELECT body_hash FROM revisions WHERE document = ? AND rev_id IN (${o.map(()=>"?").join(",")})
|
|
3
|
+
ORDER BY number DESC LIMIT 1`).get(e.id,...o);if(!i)throw new Error(`document ${e.id} has no head revision ${e.heads_key}`);return i.body_hash}a(F,"headBodyHash");async function j(n,e,o){return{view:o,ev:await L(n,e)}}a(j,"resolveContext");async function O(n,e,o,i,t,w,c){const{view:r}=o,p=r.findIndex(k=>k.id===t.owner),d=p>=0?r[p]:await n.prepare("SELECT * FROM objects WHERE id = ?").get(t.owner),u=R(d),m=c?.get(t.name),y=m===void 0?await A(n,e,t.name,o):m===null?{missing:!0}:{object:{id:m}},f=await F(n,t),{heads_key:E,unlisted:s,source_path:l,..._}=t;return{object:_,owner:d,ownerHandle:u,viewRank:p>=0?p:r.length,ownNode:e.class==="node"&&t.owner===e.node.id,shipped:l!==null,kind:t.kind==="preference"?"preference":"knowledge",name:t.name,displayName:"object"in y&&y.object.id===t.id?t.name:`${u}/${t.name}`,preview:t.preview,unlisted:s!==0,headsKey:E,bodyHash:f,body:a(()=>M(f,l),"body"),rules:w,limit:q(i,d,e)}}a(O,"toDeliveryDoc");async function X(n,e,o){const i=await v(n,e),t=await j(n,e,i),w=await N(n,e),c=new Map,r=await D(n,t.ev,"read","o"),p={sql:`${r.sql} AND (NOT EXISTS (SELECT 1 FROM objects own WHERE own.id = o.owner AND own.type = 'node') OR o.owner = ?)`,params:[...r.params,e.class==="node"?e.node.id:""]};for(const s of await C(n,o,p))c.set(s.object,[...c.get(s.object)??[],s]);const d=e.class==="node"&&o.includes("boot")?await h(n,t.ev,"o.owner = ?",[e.node.id]):[],u=[...new Set([...c.keys(),...d.map(s=>s.id)])],m=u.length===0?[]:await h(n,t.ev,`o.id IN (${u.map(()=>"?").join(",")})`,u),y=new Map(i.map((s,l)=>[s.id,l])),f=a(s=>y.get(s.owner)??i.length,"rankOf"),E=await $(n,t,m.map(s=>s.name));return await x(m.sort((s,l)=>f(s)-f(l)||s.seq-l.seq),async s=>await O(n,e,t,w,s,c.get(s.id)??[],E))}a(X,"loadCorpus");async function z(n,e,o){const i=await j(n,e,await v(n,e)),t=(await h(n,i.ev,"o.id = ?",[o.id]))[0];if(!t)throw new Error(`document ${o.id} has no documents row or is not readable`);return await O(n,e,i,await N(n,e),t,await g(n,t))}a(z,"deliveryDocOf");async function G(n,e,o){const i=await j(n,e,await v(n,e)),t=await N(n,e),w=await h(n,i.ev,"o.owner = ? AND d.unlisted = 0",[o.id]),c=await $(n,i,w.map(r=>r.name));return await x(w,async r=>await O(n,e,i,t,r,await g(n,r),c))}a(G,"listingCorpus");async function Q(n,e){if(e.class!=="node")throw new Error(`nodeSubject needs a node reader, got ${e.class}`);const o=await I(e.node.id,[...e.repos,...e.projectRepos]);if(o===null)throw new Error(`no node ${e.node.id}`);return o}a(Q,"nodeSubject");export{z as deliveryDocOf,q as deliveryLimitFor,G as listingCorpus,X as loadCorpus,Q as nodeSubject,R as ownerHandle,T as typedLimitKey};
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
var A=Object.defineProperty;var d=(t,e)=>A(t,"name",{value:e,configurable:!0});import{dirname as L}from"node:path";import{clearLedger as F,demoteTranscript as $,freezePreferences as
|
|
2
|
-
`),delivered:[...e.delivered,...n.delivered]}}d(ye,"hypotheticalBearings");async function C(t,e,n){const r=await J(t,e,n);if("object"in r&&r.object.type==="document")return r.object;throw"ambiguous"in r?new u(409,"ambiguous",`${n} names ${r.ambiguous.length} documents; name one as <type>:<owner>/<name>`):new u(404,"not_found",`no document ${n} the reader can read`)}d(C,"readDocument");const ve=["workspace-open","document-read"];async function Ge(t,e,n){if(ve.includes(n.activity))throw new u(400,"usage",`delivery activity ${n.activity} is available to a dry run only`);const r=f(e).node;n.activity==="boot"&&n.inherited!==!0&&await F(t,r.id);const a=await M(t,r.id),c={db:t,reader:e,subject:await j(t,e),ledger:a,channel:"transcript"},{result:o,delivered:i}=await D(c,n);return await pe(t,e,i),await P(t,a),o}d(Ge,"deliver");const he={boot:"boot","workspace-open":"workspace-open","file-read":"file-read","document-read":"document-read",command:"command","pre-command":"pre-command","slash-command":"slash-command"};async function Xe(t,e){const n=await V(t);if(n===null)throw new u(404,"not_found",`no node ${t}`);return{cwd:e.cwd??n.cwd,profile:e.profile!==void 0?e.profile:n.profile_id,grantee:e.grantee??n.grantee,kind:e.kind??n.kind,mode:e.mode??n.mode,lifecycle:e.lifecycle??n.lifecycle,hasManager:e.hasManager??(n.parent??null)!==null,depth:e.depth??await ee(t)}}d(Xe,"hypotheticalFrom");function
|
|
1
|
+
var A=Object.defineProperty;var d=(t,e)=>A(t,"name",{value:e,configurable:!0});import{dirname as L}from"node:path";import{clearLedger as F,demoteTranscript as $,freezePreferences as g,loadLedger as M,saveLedger as P}from"../../graph/exposures.js";import{recordWatch as T}from"../../graph/watches.js";import{publish as H}from"../../graph/events.js";import{viewOf as x}from"../../graph/names.js";import{checkoutsForCwd as y}from"../../graph/repo-sync/repos.js";import{liveLookups as W,profileObject as Y,viewRepos as B}from"../../graph/reader.js";import{ownerForGrantee as U}from"../../graph/objects.js";import{resolveName as J}from"../../graph/names.js";import{SCOPE_VOCABULARY as K}from"../../scopes.js";import{getNode as V}from"../../canvas/index.js";import{recordMemoryReadsIn as G}from"../../canvas/memory-reads.js";import{lookupProfile as X}from"../../profiles/manifest.js";import{getDefaultProfileId as z}from"../../profiles/default-binding.js";import{effectiveScopes as Q,profileNameFor as Z,scopeForCwd as q}from"../subject-fields.js";import{spineDepth as ee}from"../subject.js";import{appForNode as te}from"../../canvas/node-agent-paths.js";import{interpolateNodePaths as ne}from"../../canvas/paths.js";import{readableProjectForScopes as oe}from"../../spaces/permissions.js";import{ApiError as u}from"../../../api/errors.js";import{buildContextBearings as re}from"../../runtime/bearings.js";import{deliveryDocOf as b,listingCorpus as ae,loadCorpus as w,nodeSubject as j}from"./corpus.js";import{listingPrefixes as ie}from"./listings.js";import{planDelivery as se}from"./plan.js";import{renderEvent as N,renderExplicitRead as k}from"./render-event.js";import{renderConfigDelta as ce,renderKnowledge as de,renderPreferences as O,renderWorkspaceOpen as _}from"./render-boot.js";import{mapAsync as le}from"../../async-array.js";function f(t){if(t.class!=="node")throw new Error(`delivery needs a node reader, got ${t.class}`);return t}d(f,"nodeOf");const S="hypothetical";function v(t){return t.node.id===S}d(v,"isHypothetical");async function R(t,e){if(!v(e))return await te(e.node.id);const n=await t.prepare("SELECT external_id FROM identities WHERE object = ?").get(e.app.id);if(!n)throw new Error(`app object ${e.app.id} has no identity`);return n.external_id}d(R,"granteeOf");async function pe(t,e,n,r=async a=>await y(t,a)){const a=f(e).node,c=new Set,o=new Date().toISOString(),i=[];for(const{doc:s,level:l}of n)l!=="content"||c.has(s.object.id)||(c.add(s.object.id),await T(t,a,s.object,"deliver",{readHeadsKey:s.headsKey}),await H(t,{event:"read",object:s.object,actor:a,attrs:{}},r),i.push({name:s.name,scope:s.ownerHandle,at:o,type:"loaded"}));v(f(e))||await G(t,a.id,i)}d(pe,"recordContentDelivery");async function E(t,e,n){const r=(await y(t,L(n))).filter(a=>!e.repos.some(c=>c.id===a.repo.id));return r.length===0?e:{...e,repos:[...e.repos,...r.map(a=>a.repo)],checkouts:[...e.checkouts,...r]}}d(E,"fileReadReader");async function ue(t,e,n){const r=await R(t,e);if(!(n.startsWith("/")&&(process.platform!=="linux"&&r==="app:terminal"||oe(n,r,e.scopes??[],null))))throw new u(403,"scope_missing","read file is outside the run mounts")}d(ue,"assertReadableFile");async function me(t){const e=f(t.reader),n=e.node,r=await R(t.db,e),a=await w(t.db,t.reader,["slash-command"]),c=a.map(o=>{const i=o.body();return{name:o.displayName,command_name:o.displayName,description:o.preview,canonical_body:i,execution_body:ne(i,n.id,r)}});return{docs:a,commands:c}}d(me,"slashCommands");function fe(t){if(t.shipped)return"builtin";switch(t.owner.type){case"node":return"node";case"repo":return"project";case"profile":return"profile";default:return"user"}}d(fe,"scopeOf");async function we(t,e){const n=[],r=new Set;for(const a of await x(t,e)){const c=await ae(t,e,a);for(const o of c){n.push({name:o.displayName,kind:o.kind,scope:fe(o),shortForm:o.preview,gatewayVisible:!o.shipped}),r.add(o.displayName);const i=o.displayName===o.name?"":`${o.ownerHandle}/`;for(const s of ie(c,o.name))r.add(`${i}${s}`)}}return{refs:n,names:[...r]}}d(we,"composerNames");async function D(t,e){const n=f(t.reader),{db:r,ledger:a}=t,c=d(()=>{if(typeof e.subject!="string"||e.subject==="")throw new u(400,"usage",`delivery activity ${e.activity} requires a subject`);return e.subject},"requireSubject");switch(e.activity){case"boot":{if(e.inherited===!0){for(const[s,l]of a.objects)if(l.transcript===void 0)a.objects.delete(s);else{const{system:p,...m}=l;a.objects.set(s,m)}for(const[s,l]of a.listed)l.transcript===void 0?a.listed.delete(s):a.listed.set(s,{transcript:l.transcript});return a.preferenceSnapshot=null,{result:{content:"",inherited:!0},delivered:[]}}const o=v(n)?await ye(t):await re(n.node.id,t),i=await O({...t,channel:"system"});return g(a,i.content),{result:{content:o.content},delivered:[...o.delivered,...i.delivered]}}case"system-prompt":{if(a.preferenceSnapshot!==null)return{result:{content:a.preferenceSnapshot},delivered:[]};const o=await O({...t,channel:"system"});return{result:{content:g(a,o.content)},delivered:o.delivered}}case"compact":{for(const o of await w(r,n,["pre-command"]))$(a,o.object.id);return{result:{content:""},delivered:[]}}case"persona":{const o=await ce(t);return{result:{content:o.content},delivered:o.delivered}}case"file-read":{const o=c();await ue(r,n,o);const i=await E(r,n,o),s={...t,reader:i},l=await N(s,"file-read",{absoluteFile:o},await w(r,i,["file-read"]));return{result:{content:l.content},delivered:l.delivered}}case"command":case"pre-command":{const o=await N(t,e.activity,{command:c()});return{result:{content:o.content},delivered:o.delivered}}case"slash-command":{const{docs:o,commands:i}=await me(t);if(e.subject===void 0||e.subject==="")return{result:{content:"",commands:i},delivered:[]};const s=o.findIndex(m=>m.displayName===e.subject||m.name===e.subject);if(s<0)throw new u(404,"not_found",`no slash command named ${e.subject}`);const l=o[s],p=await k(t,l,!0);return{result:{content:"",execution_body:i[s].execution_body,blocks:p.attachments===""?[]:[p.attachments]},delivered:[{doc:l,level:"content"},...p.delivered]}}case"workspace-open":{const o=await _(t);return{result:{content:o.content},delivered:o.delivered}}case"document-read":{const o=await C(r,n,c()),i=await k(t,await b(r,n,o),!0);return{result:{content:i.attachments},delivered:i.delivered}}case"names":return{result:{content:"",...await we(r,n)},delivered:[]};default:throw new u(400,"usage",`unknown delivery activity ${String(e.activity)}`)}}d(D,"render");async function ye(t){const e=await de(t),n=await _(t);return{content:[e.content,n.content].filter(r=>r!=="").join(`
|
|
2
|
+
`),delivered:[...e.delivered,...n.delivered]}}d(ye,"hypotheticalBearings");async function C(t,e,n){const r=await J(t,e,n);if("object"in r&&r.object.type==="document")return r.object;throw"ambiguous"in r?new u(409,"ambiguous",`${n} names ${r.ambiguous.length} documents; name one as <type>:<owner>/<name>`):new u(404,"not_found",`no document ${n} the reader can read`)}d(C,"readDocument");const ve=["workspace-open","document-read"];async function Ge(t,e,n){if(ve.includes(n.activity))throw new u(400,"usage",`delivery activity ${n.activity} is available to a dry run only`);const r=f(e).node;n.activity==="boot"&&n.inherited!==!0&&await F(t,r.id);const a=await M(t,r.id),c={db:t,reader:e,subject:await j(t,e),ledger:a,channel:"transcript"},{result:o,delivered:i}=await D(c,n);return await pe(t,e,i),await P(t,a),o}d(Ge,"deliver");const he={boot:"boot","workspace-open":"workspace-open","file-read":"file-read","document-read":"document-read",command:"command","pre-command":"pre-command","slash-command":"slash-command"};async function Xe(t,e){const n=await V(t);if(n===null)throw new u(404,"not_found",`no node ${t}`);return{cwd:e.cwd??n.cwd,profile:e.profile!==void 0?e.profile:n.profile_id,grantee:e.grantee??n.grantee,kind:e.kind??n.kind,mode:e.mode??n.mode,lifecycle:e.lifecycle??n.lifecycle,hasManager:e.hasManager??(n.parent??null)!==null,depth:e.depth??await ee(t)}}d(Xe,"hypotheticalFrom");function ge(t,e){if(t===null)return null;if(t===void 0||t==="")return z(e);const n=X(t);if(n.kind!=="resolved"){const r=`no profile ${t}`;throw new u(404,"not_found",r,{error:"not_found",message:r,next:"List profile ids and names with `crtr profile list`."})}return n.entry.profileId}d(ge,"resolveProfileId");async function ze(t,e){const n=await U(t,e.grantee??"app:terminal"),r=ge(e.profile,e.cwd),a=await B(e.cwd,r,async p=>await y(t,p),W(t)),{repos:c}=a,o=e.mode??"base",s={class:"node",node:{id:S,seq:0,type:"node",kind:e.kind??"general",owner:n.id,privacy:"private",name:"hypothetical",preview:"",created_at:new Date(0).toISOString(),deleted_at:null},app:n,scopes:[...K],cwd:e.cwd,...a,profile:r===null?null:await Y(t,r,n)},l={kind:e.kind??"general",mode:o,lifecycle:e.lifecycle??(o==="orchestrator"?"resident":"terminal"),hasManager:e.hasManager??!0,cwd:e.cwd,scope:q(e.cwd),orchestration:{depth:e.depth??0},profile:Z(r),app:e.grantee??"app:terminal",scopes:Q(null),repo:[...c,...a.projectRepos].map(p=>p.name)};return{reader:s,subject:l}}d(ze,"hypotheticalReader");async function Qe(t,e,n,r,a){const o={node:f(e).node.id,preferenceSnapshot:null,objects:new Map,listed:new Map},i={...a??await j(t,e),...r},s={db:t,reader:e,subject:i,ledger:o,channel:"transcript"},{result:l}=await D(s,n),p=he[n.activity];let m=null;if(p!==void 0){const I=n.activity==="file-read"?{absoluteFile:n.subject}:n.activity==="command"||n.activity==="pre-command"?{command:n.subject}:n.activity==="document-read"&&n.subject!==void 0?{doc:await b(t,e,await C(t,e,n.subject))}:{},h=n.activity==="file-read"&&n.subject!==void 0?await E(t,f(e),n.subject):e;m=await se(t,i,h,await w(t,h,[p]),p,I)}return{result:l,plan:m}}d(Qe,"inspect");async function Ze(t,e,n){const r=await t.prepare(`SELECT o.*, MAX(r.number) AS to_seq, string_agg(DISTINCT a.id, ',') AS authors
|
|
3
3
|
FROM watches w JOIN objects o ON o.id = w.object AND o.type = 'document' AND o.deleted_at IS NULL
|
|
4
4
|
JOIN revisions r ON r.document = o.id LEFT JOIN objects a ON a.id = r.author
|
|
5
5
|
WHERE w.watcher = ? AND r.created_at > ? AND (r.author IS NULL OR r.author != ?)
|
|
@@ -1,8 +1,8 @@
|
|
|
1
|
-
var N=Object.defineProperty;var
|
|
2
|
-
${
|
|
3
|
-
</memory>`}else n==="preview"&&e.preview.trim()!==""&&(t+=` readWhen="${b(e.preview.trim())}"`);return`<memory ${t} />`}
|
|
1
|
+
var N=Object.defineProperty;var a=(e,n)=>N(e,"name",{value:n,configurable:!0});import{permits as D,resolveReader as E}from"../../permissions/evaluator.js";import{heldAtOrAbove as g,hold as v,holdListing as O,listedAtOrAbove as H}from"../../graph/exposures.js";import{deliveryDocOf as K,listingCorpus as L,loadCorpus as w}from"./corpus.js";import{listingBlock as R,ownSetBlock as C,listingKey as P,listingLabel as x,listingPrefixes as k,renderListing as B}from"./listings.js";import{planDelivery as M}from"./plan.js";import{mapAsync as S}from"../../async-array.js";function b(e){return e.replace(/&/g,"&").replace(/"/g,""").replace(/</g,"<").replace(/>/g,">")}a(b,"attr");function W(e,n){let t=`kind="${b(e.kind)}" name="${b(e.displayName)}"`;if(n==="content"){const i=e.body().trim();if(i!=="")return`<memory ${t}>
|
|
2
|
+
${i}
|
|
3
|
+
</memory>`}else n==="preview"&&e.preview.trim()!==""&&(t+=` readWhen="${b(e.preview.trim())}"`);return`<memory ${t} />`}a(W,"renderEnvelope");function $(e){return e.length===0?"":`<auto-loaded-context>
|
|
4
4
|
${e.join(`
|
|
5
5
|
`)}
|
|
6
|
-
</auto-loaded-context>`}
|
|
7
|
-
WHERE e.type = 'links-to' AND e.src = ? AND o.type = 'document' AND o.deleted_at IS NULL AND o.id <> ?
|
|
8
|
-
ORDER BY e.written_as`).all(t.object.id,t.object.id);return await S(
|
|
6
|
+
</auto-loaded-context>`}a($,"wrapAutoLoaded");async function q(e,n){let t=e.members.get(n.owner.id);return t===void 0&&(t=await L(e.ctx.db,e.ctx.reader,n.owner),e.members.set(n.owner.id,t)),t}a(q,"membersOf");async function I(e,n,t){const i=await D(e,await E(e,n),"read","o"),o=await e.prepareUncached(`SELECT o.* FROM edges e JOIN objects o ON o.id = e.dst
|
|
7
|
+
WHERE e.type = 'links-to' AND e.src = ? AND o.type = 'document' AND o.deleted_at IS NULL AND o.id <> ? AND ${i.sql}
|
|
8
|
+
ORDER BY e.written_as`).all(t.object.id,t.object.id,...i.params);return await S(o,async s=>await K(e,n,s))}a(I,"linkedDocs");function U(e,n){return n.owner.id===e.owner.id&&n.name.startsWith(`${e.name}/`)&&!n.name.slice(e.name.length+1).includes("/")}a(U,"underOwnPrefix");async function _(e,n){const{ledger:t,channel:i}=e.ctx,o=[],s=[];for(const r of await I(e.ctx.db,e.ctx.reader,n)){if(U(n,r)&&!r.unlisted)continue;const l={object:r.object.id,headsKey:r.headsKey,contentHash:r.bodyHash};if(g(t,l,"preview"))continue;v(t,i,l,"preview"),e.delivered.push({doc:r,level:"preview",cause:"link preview attached to content delivery"}),s.push(r);const d=r.preview.trim();o.push(d===""?`[[${r.displayName}]]`:`[[${r.displayName}]]: ${d}`)}return{lines:o,linked:s}}a(_,"linkPreviews");async function j(e,n,t){const{ledger:i,channel:o}=e.ctx,s=await q(e,n),r=[];let l,d=[];for(const m of k(s,n.name)){const u=m===n.name,f=P(n,m);if(!(u&&t)&&H(i,f,"preview"))continue;const{lines:c,previewed:p}=B(s,m,i,o,!(u&&t));for(const y of p)e.delivered.push({doc:y,level:"preview",cause:"directory listing attached to content delivery"});c.length!==0&&(O(i,o,f,"preview"),u?d=c:r.push(R(x(n,m),c)))}const h=await _(e,n);return t?d.length>0&&(l=d):d.length+h.lines.length>0&&r.unshift(C(x(n,n.name),d,h.lines)),e.chainCorpus??=await w(e.ctx.db,e.ctx.reader,["document-read"]),r.push(...await A(e,e.chainCorpus,"document-read",{doc:n},"memory-read companion of content delivery")),{blocks:r,...l===void 0?{}:{listing:l},linked:h.linked}}a(j,"attachments");async function A(e,n,t,i,o){const{db:s,reader:r,subject:l,ledger:d,channel:h}=e.ctx,m=await M(s,l,r,n,t,i),u=[];for(const f of m.docs){const c=f.finalRung;if(!f.winner||c==="none")continue;const{doc:p}=f,y={object:p.object.id,headsKey:p.headsKey,contentHash:p.bodyHash};g(d,y,c)||(v(d,h,y,c),e.delivered.push({doc:p,level:c,...o===void 0?{}:{cause:o}}),c==="content"&&u.push(...(await j(e,p,!1)).blocks),u.push(W(p,c)))}return u}a(A,"renderPlan");async function V(e,n,t,i){i??=await w(e.db,e.reader,[n]);const o={ctx:e,delivered:[],members:new Map};return{content:$(await A(o,i,n,t)),delivered:o.delivered}}a(V,"renderEvent");async function X(e,n,t=!1){const i={ctx:e,delivered:[],members:new Map};v(e.ledger,e.channel,{object:n.object.id,headsKey:n.headsKey,contentHash:n.bodyHash},"content");const{blocks:o,listing:s,linked:r}=await j(i,n,!t);return{attachments:$(o),...s===void 0?{}:{listing:s},linked:r,delivered:i.delivered}}a(X,"renderExplicitRead");export{I as linkedDocs,W as renderEnvelope,V as renderEvent,X as renderExplicitRead,$ as wrapAutoLoaded};
|
|
@@ -28,6 +28,8 @@ export interface NodeConfigSubject {
|
|
|
28
28
|
* profile has been deleted or its manifest is unreadable — this is a HOT,
|
|
29
29
|
* every-doc-render path and must never brick boot/on-read gating. */
|
|
30
30
|
profile: string | null;
|
|
31
|
+
/** The run's grantee principal (`app:firstlight`): what a rule's `if: {app: ...}` matches. */
|
|
32
|
+
app: string;
|
|
31
33
|
/** Effective per-run scopes. */
|
|
32
34
|
scopes: readonly string[];
|
|
33
35
|
/** DERIVED: handles of the repos eligible for the node's rules: those enclosing `cwd`
|
|
@@ -1 +1 @@
|
|
|
1
|
-
var
|
|
1
|
+
var i=Object.defineProperty;var a=(r,o)=>i(r,"name",{value:o,configurable:!0});import{getNode as n,getRow as c}from"../canvas/index.js";import{appForNode as s}from"../canvas/node-agent-paths.js";import{openDb as l}from"../canvas/db.js";import{checkoutsForCwd as f}from"../graph/repo-sync/repos.js";import{liveLookups as m,viewRepos as w}from"../graph/reader.js";import{effectiveScopes as u,scopeForCwd as d,profileNameFor as b}from"./subject-fields.js";import{effectiveScopes as D,scopeForCwd as _,profileNameFor as L}from"./subject-fields.js";async function h(r){let o=r;const e=new Set;let t=0;for(;!e.has(o);){e.add(o);const p=await c(o);if(p===null||p.parent==null)break;o=p.parent,t++}return t}a(h,"spineDepth");async function k(r,o){const e=await l(),t=await w(r,o,async p=>await f(e,p),m(e));return[...t.repos,...t.projectRepos]}a(k,"eligibleRepos");async function x(r,o){const e=await n(r);return e===null?null:{kind:e.kind,mode:e.mode,lifecycle:e.lifecycle,hasManager:(e.parent??null)!==null,cwd:e.cwd,scope:d(e.cwd),orchestration:{depth:await h(r)},profile:b(e.profile_id),app:e.grantee??await s(r),scopes:u(e.scopes),repo:(o??await k(e.cwd,e.profile_id??null)).map(t=>t.name)}}a(x,"assembleNodeSubject");export{x as assembleNodeSubject,D as effectiveScopes,L as profileNameFor,_ as scopeForCwd,h as spineDepth};
|
|
@@ -1,24 +1,24 @@
|
|
|
1
|
-
var Y=Object.defineProperty;var i=(e,
|
|
1
|
+
var Y=Object.defineProperty;var i=(e,n)=>Y(e,"name",{value:n,configurable:!0});import{randomUUID as Q}from"node:crypto";import{createServer as W}from"node:http";import{Router as V}from"./router.js";import{toErrorBody as q}from"./map.js";import{objectRoutes as K}from"./handlers/objects.js";import{customObjectRoutes as Z}from"./handlers/custom-objects.js";import{checkRoutes as ee}from"./handlers/check.js";import{docRoutes as te}from"./handlers/docs.js";import{relationRoutes as re}from"./handlers/relations.js";import{schemaRoutes as ne}from"./handlers/schemas.js";import{OPERATIONS as ae}from"./operations.js";import{runtimeReadiness as oe}from"../readiness.js";import{errorCodes as $}from"../../api/error-codes.js";import{MINIMUM_RUNTIME_VERSION_HEADER as ie,RUNTIME_VERSION_HEADER as se,minimumRuntimeRefusal as ue}from"../../api/runtime-version.js";import{CONTRACT_HEADER as ce,CONTRACT_LEVEL as X,REQUIRED_CONTRACT_HEADER as de,contractRefusal as le}from"../../api/contract.js";import{crtrVersion as B}from"../../shared/crtr-version.js";import{newTraceId as me,parseTraceparent as fe}from"../../shared/traceparent.js";import{AppPrincipalResolver as pe}from"./principal.js";import{isDaemonRoute as he,runtimeOwner as we,servePeer as z}from"../peer/ingress.js";import{applySyncNotice as ye}from"./sync-notice.js";import{ownMachineId as _e}from"../../core/peer/directory.js";import{handleRunOperation as ve,integer as ge}from"./handlers/runs.js";import{llmCallerOf as Re,parseLlmRequest as Oe,runLlm as be}from"../../core/llm/run.js";import{parseUsageMonth as Ee,usageFor as Ae}from"../../core/usage/ledger.js";import{capFields as Te}from"./handlers/llm.js";import{CONTROL_BODY_MAX_BYTES as Se,MODEL_CONTEXT_BODY_MAX_BYTES as Ne}from"../../core/llm/body-limits.js";import{RunError as m,runIsRunning as Ce}from"../../core/runs/operations.js";import{requireRun as J}from"./router.js";import{deferHead as Ie}from"./deferred-head.js";import{readRunEvents as G,registerGrantStream as Pe,subscribeRunEvents as ke}from"../../core/runs/events.js";import{activeGrant as F,payerOfGrant as He}from"../../core/grants/mirror.js";async function Me(e){if(await He(e)==="app")throw new m(401,"grant_revoked","this app-paid grant is no longer active");return null}i(Me,"appPaidGone");import{releaseGrantWaiters as De}from"../../core/grants/watch.js";import{emitEvent as je}from"../../core/events/emit.js";import{runNotices as xe}from"../run-notices.js";import{handleVendorSignIn as Be,isVendorSignInPath as Je}from"./vendor-signin.js";import{listAppProfiles as Le}from"./handlers/app-profiles.js";import{handleTransferDownload as Ue,handleTransferOperation as Ve,TRANSFER_OPERATIONS as $e}from"./handlers/transfer.js";import{handleQuestionOperation as Xe,QUESTION_OPERATIONS as ze}from"./handlers/questions.js";import{removeVendorAccount as Ge,vendorStatus as Fe}from"./handlers/vendor-status.js";import{handleMemoryOperation as Ye,MEMORY_OPERATIONS as Qe}from"./handlers/memory.js";import{abortOnClose as We,callerFromApp as qe,handleProviderOperation as Ke,PROVIDER_OPERATIONS as Ze,providerFailure as et}from"./handlers/providers.js";function tt(e){return Object.prototype.hasOwnProperty.call($,e)?$[e]:void 0}i(tt,"fixedRow");function rt(e){const n=tt(e);return n?n.type:e==="stream_gap"||e==="provider_error"||e==="runtime_version_unsupported"?"invalid_request_error":"server_error"}i(rt,"errorType");function nt(e){if(!e||typeof e!="object"||Array.isArray(e)||!("rate_limit"in e))return e;const{rate_limit:n,...o}=e;return o}i(nt,"appDetails");function x(e,n,o){const p=nt(e.details);return{error:{code:e.code,message:e.message,...p===void 0?{}:{details:p},type:rt(e.code),...e.param?{param:e.param}:{},origin:"runtime",retryable:e.retryable||e.code==="stream_dropped",request_id:n,...o?{run_id:o}:{},...e.scope?{scope:e.scope}:{},...e.code==="unauthorized"?{user_action:"reconnect"}:{},...Te(e),...e.code==="all_routes_exhausted"?{retry_after_s:e.details.retry_after_s}:{}}}}i(x,"envelope");function at(e,n,o,p,f){const l=n instanceof m?n:new m(500,"server_failure","runtime request failed");if(n instanceof m||console.error("[app-listener]",`trace_id=${p}`,n),e.headersSent&&!String(e.getHeader("Content-Type")??"").startsWith("text/event-stream")){e.destroy();return}if(e.headersSent){e.end(`event: error
|
|
2
2
|
data: ${JSON.stringify(x(l,o,f))}
|
|
3
3
|
|
|
4
|
-
`);return}e.writeHead(l.status,{"Content-Type":"application/json; charset=utf-8","Request-Id":o,"X-Content-Type-Options":"nosniff",...l.code==="all_routes_exhausted"?{"Retry-After":String(l.details.retry_after_s)}:{}}),e.end(JSON.stringify(x(l,o,f)))}i(
|
|
4
|
+
`);return}e.writeHead(l.status,{"Content-Type":"application/json; charset=utf-8","Request-Id":o,"X-Content-Type-Options":"nosniff",...l.code==="all_routes_exhausted"?{"Retry-After":String(l.details.retry_after_s)}:{}}),e.end(JSON.stringify(x(l,o,f)))}i(at,"fail");function L(e){return Array.isArray(e)?e[0]:e}i(L,"headerValue");function g(e,n,o){e.writeHead(n,{"Content-Type":"application/json; charset=utf-8"}),e.end(JSON.stringify(o))}i(g,"json");async function C(e,n=Se){const o=[];let p=0;for await(const f of e){if(p+=f.length,p>n)throw new m(400,"invalid_request","request body too large");o.push(f)}if(p)try{return JSON.parse(Buffer.concat(o).toString("utf8"))}catch{throw new m(400,"invalid_request","invalid JSON body")}}i(C,"bodyOf");function ot(e,n){const o=e.headers["last-event-id"]??n.get("after");if(Array.isArray(o))throw new m(400,"invalid_request","invalid cursor","after");return ge(o??null,"after",0,Number.MAX_SAFE_INTEGER,0)}i(ot,"cursor");function it(e){return`id: ${e.sequence_number}
|
|
5
5
|
event: ${e.type}
|
|
6
6
|
data: ${JSON.stringify(e)}
|
|
7
7
|
|
|
8
|
-
`}i(
|
|
8
|
+
`}i(it,"frame");const st=6e4;async function ut(e,n,o,p,f,l,E,I={},H){await J(p,o);let w=await G(o,f);if(f>w.latest_sequence)throw new m(400,"invalid_request","cursor is beyond the run","after");if(f<w.latest_sequence&&(w.earliest_sequence===null||f<w.earliest_sequence-1))throw new m(409,"stream_gap","events have expired",void 0,{earliest_sequence:w.earliest_sequence,latest_sequence:w.latest_sequence});if(n.destroyed||e.destroyed)return n.destroy(),Promise.resolve();n.writeHead(200,{"Content-Type":E==="sse"?"text/event-stream":"application/x-ndjson","Cache-Control":"no-cache","X-Accel-Buffering":"no"}),E==="sse"?n.write(`: connected
|
|
9
9
|
|
|
10
|
-
`):
|
|
11
|
-
data: ${JSON.stringify(x(
|
|
10
|
+
`):n.flushHeaders();let T=f;const r=await xe().streamOpened(o);let t=!1,y=!1,O=!1,A;const P=new Promise(c=>{A=c}),_=i(()=>{t||(t=!0,r(T).catch(c=>console.error("[app-listener]",...H===void 0?[]:[`trace_id=${H}`],c)),clearInterval(u),clearInterval(N),k(),D(),n.off("close",_),n.off("drain",h),n.end(),A())},"end"),h=i(()=>{O=!1,a()},"onDrain"),R=i(c=>{t||n.write(E==="sse"?`event: error
|
|
11
|
+
data: ${JSON.stringify(x(c,l,o))}
|
|
12
12
|
|
|
13
|
-
`:`${JSON.stringify({type:"error",...x(
|
|
14
|
-
`),_()},"error"),a=i(async()=>{if(!(t||y)){y=!0;try{if(!await
|
|
15
|
-
`),
|
|
13
|
+
`:`${JSON.stringify({type:"error",...x(c,l,o)})}
|
|
14
|
+
`),_()},"error"),a=i(async()=>{if(!(t||y)){y=!0;try{if(!await S()){M();return}if(await J(p,o),w=await G(o,T),w.backlog_count>1e3||w.backlog_bytes>32*1024*1024){R(new m(503,"stream_dropped","stream reader fell behind",void 0,{last_sequence:T}));return}for(const c of w.events){if(O)break;O=!n.write(E==="sse"?it(c):`${JSON.stringify(c)}
|
|
15
|
+
`),T=c.sequence_number}}catch(c){R(c instanceof m?c:new m(500,"server_failure","stream failed"))}finally{y=!1}}},"flush"),M=i(()=>R(new m(401,"grant_revoked","grant is not active")),"revoked"),S=i(async()=>"class"in p||await F(p.grant)!==null,"grantActive"),k=await ke(o,a),D="class"in p?()=>{}:Pe(p.grant,M),u=setInterval(()=>{!t&&!O&&E==="sse"&&n.write(`: keepalive
|
|
16
16
|
|
|
17
|
-
`)},15e3),j=I.idleMs??
|
|
17
|
+
`)},15e3),j=I.idleMs??st,s=I.isRunning??Ce;let v=Date.now(),d=T;const b=i(async()=>{if(t||E!=="sse")return;const c=Date.now();let U=!0;try{U=await s(o)}catch{}if(!t){if(U||T!==d){v=c,d=T;return}c-v<j||O||(n.write(`event: idle
|
|
18
18
|
data: {}
|
|
19
19
|
|
|
20
|
-
`),_())}},"checkIdle"),N=setInterval(()=>{
|
|
20
|
+
`),_())}},"checkIdle"),N=setInterval(()=>{b().catch(c=>je({level:"error",event:"api.run_stream.idle_check_failed",error:c}))},I.idleCheckMs??1e3);return N.unref(),n.on("drain",h),n.on("close",_),await a(),P}i(ut,"streamRunEvents");async function qt(e,n,o,p={}){const f=e.listener;if(!e.issuer||!e.audience||!f?.address||!Number.isInteger(f.port)||f.port<1||f.port>65535)throw new Error("runtime issuer, audience and listener address/port are required");if(["0.0.0.0","::","[::]"].includes(f.address))throw new Error("runtime listener must bind a specific address");const l=new pe(e.issuer,e.audience,o,e.jwksUrl),E=new V,I=new Map;for(const r of ae.filter(t=>t.stage!==void 0)){const t=i(()=>({status:500}),"handler");E.register({method:r.method,pattern:r.path,handler:t}),I.set(t,r)}const H=new V().registerAll(K).registerAll(Z).registerAll(te).registerAll(ne).registerAll(re).registerAll(ee),w=W((r,t)=>{(async()=>{Ie(r,t,p.deferHead);const y=Q();t.setHeader("Request-Id",y);const O=fe(L(r.headers.traceparent))??me();t.setHeader(se,B()),t.setHeader(ce,X);let A;try{const P=L(r.headers[ie.toLowerCase()]),_=ue(P,B())??le(L(r.headers[de.toLowerCase()]),X,{legacyMinimum:P,runtimeVersion:B()});if(_!==null)throw _.status===400?new m(400,_.code,_.message,_.param):new m(426,_.code,_.message,void 0,_.details);const h=new URL(r.url??"/","http://runtime.local");if(Je(h.pathname)){await Be(r,t,h,l);return}const R=E.match(r.method??"GET",h.pathname),a=R?I.get(R.handler):void 0,M=a?.name==="runtime.sync-notice"||a?.name==="runtime.vendor-status"||a?.name==="runtime.vendor-account-remove";let S,k;if(!M&&r.headers.authorization!==void 0)try{S=await l.verifyCall(r.headers.authorization)}catch(s){k=s}const D={issuer:e.issuer,jwks:l.jwks,audience:i(async()=>e.audience,"audience"),owner:we,self:_e,syncGrants:o,ready:i(async()=>l.isReady()&&await n(),"ready")};if(S?.chain[0]?.sub.startsWith("runtime:")){await z(r,t,D,S);return}if(S===void 0&&a===void 0&&await he(r.method??"GET",h.pathname)){await z(r,t,D,{status:401,code:"unauthorized",message:k===void 0?"a machine token is required":"invalid machine token"});return}if(a?.name==="ready"){const s=await n(),v=await oe({jwksReady:l.isReady(),grantsReady:i(()=>s,"grantsReady")});g(t,v.ready?200:503,v);return}if((r.method!=="GET"||h.pathname!=="/v1/health")&&(!l.isReady()||!await n()))throw new m(503,"runtime_starting","runtime_starting");if(!R||!a)throw new m(404,"not_found","unknown operation");if(A=R.params.run_id,a.name==="health"){g(t,200,{status:"ok",api_version:"2026-09-23"});return}if(a.name==="runtime.sync-notice"){await ye(await l.verifySyncNotice(r.headers.authorization),o,y),t.writeHead(204),t.end();return}if(a.name==="runtime.vendor-status"){await l.verifyDirectoryRead(r.headers.authorization,"vendor_status"),g(t,200,Fe());return}if(a.name==="runtime.vendor-account-remove"){await l.verifyDirectoryRead(r.headers.authorization,"vendor_account_remove"),g(t,200,await Ge(await C(r)));return}if(S===void 0)throw k??new m(401,"unauthorized","a directory access token is required");const u=await l.resolveVerified(S,a.scope);if(t.setHeader("Request-Id",y),A&&await J(u,A,["run.message","run.interrupt","run.cancel","run.rename","run.delete"].includes(a.name),a.name==="run.delete"),a.stage==="objects"){const s=H.match(a.method,h.pathname);if(!s)throw new m(404,"not_found","unknown operation");const v={method:a.method,path:h.pathname,params:s.params,query:h.searchParams,body:await C(r,s.maxBodyBytes),ceiling:u.resolved,principal:{class:"app",app:u.grantee,scopes:u.resolved,sub:u.sub},req:r,res:t};let d;try{d=await s.handler(v)}catch(b){const{status:N,body:c}=q(b);throw N>=500&&console.error("[app-listener]",`trace_id=${O}`,b),new m(N,c.error.code,c.error.message,void 0,c.error.details)}if(t.headersSent)return;if(d.rawBody!==void 0||d.status===204||d.body===void 0){t.writeHead(d.status,d.headers??{}),t.end(d.rawBody);return}t.writeHead(d.status,{"Content-Type":"application/json; charset=utf-8",...d.headers??{}}),t.end(JSON.stringify(d.body));return}if(a.stream==="bytes"){await Ue(r,t,u,h.searchParams);return}if(a.stream){await ut(r,t,A,u,ot(r,h.searchParams),y,"sse",p.stream,O);return}if(a.name==="llm"){const s=Oe(await C(r,Ne)),v=new AbortController,d=i(()=>v.abort(),"abort");t.on("close",d);try{const b=await be(s,v.signal,s.stream?N=>{t.headersSent||t.writeHead(200,{"Content-Type":"text/event-stream","Cache-Control":"no-cache","X-Accel-Buffering":"no"}),t.write(`data: ${JSON.stringify(N)}
|
|
21
21
|
|
|
22
|
-
`)}:void 0,void 0,{grantee:
|
|
22
|
+
`)}:void 0,void 0,{grantee:u.grantee,spend_cap:u.spend_cap},Re(await F(u.grant)??await Me(u.grant)));s.stream?(t.headersSent||t.writeHead(200,{"Content-Type":"text/event-stream","Cache-Control":"no-cache","X-Accel-Buffering":"no"}),t.end(`data: [DONE]
|
|
23
23
|
|
|
24
|
-
`)):g(t,200,
|
|
24
|
+
`)):g(t,200,b.completion)}finally{t.off("close",d)}return}if(a.name==="usage.get"){g(t,200,await Ae(u.grantee,u.spend_cap,Ee(h.searchParams.get("month"))));return}if(a.name==="profile.list"){g(t,200,Le(u));return}if(ze.has(a.name)){const s=await Xe(a.name,u,R.params.question_id,a.method==="POST"?await C(r):void 0);g(t,s.status,s.body);return}if(Ze.has(a.name)){const{signal:s,release:v}=We(t);try{const d=await Ke(a.name,qe(u),{params:R.params,body:a.method==="POST"?await C(r):void 0,query:h.searchParams},{requestId:y,traceId:O,signal:s});g(t,d.status,d.body)}catch(d){const b=et(d,y,!0);t.writeHead(b.status,{"Content-Type":"application/json; charset=utf-8","X-Content-Type-Options":"nosniff",...b.headers}),t.end(JSON.stringify(b.body))}finally{v()}return}if(Qe.has(a.name)){const s=await Ye(a.name,{class:"app",app:u.grantee,scopes:u.resolved},h.searchParams);g(t,s.status,s.body);return}if($e.has(a.name)){const s=await Ve(a,u,R.params,h.searchParams,await C(r));g(t,s.status,s.body);return}const j=await ve(a,u,A,h.searchParams,await C(r),r.headers["idempotency-key"]);g(t,j.status,j.body)}catch(P){at(t,P,y,O,A)}})()});return{ready:new Promise((r,t)=>{w.once("error",t),w.listen(f.port,f.address,()=>{w.off("error",t),r()})}),close:i(async()=>{l.close(),De(),w.closeAllConnections(),await new Promise((r,t)=>w.close(y=>y?t(y):r()))},"close")}}i(qt,"createAppListener");export{st as RUN_STREAM_IDLE_MS,qt as createAppListener,ot as cursor,ut as streamRunEvents};
|
|
@@ -73,4 +73,4 @@ export declare function isCleanViewerClose(code: number): boolean;
|
|
|
73
73
|
* 3. Revive opted out: a single connect probe. Dormant (socket refuses) →
|
|
74
74
|
* refuse 409 (spec §5.3 asymmetry: a dead broker can't stream over WS).
|
|
75
75
|
* 4. Only then upgrade and hand the live WS to {@link bridgeConnection}. */
|
|
76
|
-
export declare function handleAttachUpgrade(req: IncomingMessage, socket: Duplex, head: Buffer, nodeId: string): Promise<void>;
|
|
76
|
+
export declare function handleAttachUpgrade(req: IncomingMessage, socket: Duplex, head: Buffer, nodeId: string, stillMayAttach: (role: 'observer' | 'controller') => Promise<boolean>): Promise<void>;
|
|
@@ -1,8 +1,8 @@
|
|
|
1
|
-
var
|
|
1
|
+
var M=Object.defineProperty;var n=(r,e)=>M(r,"name",{value:e,configurable:!0});import{WebSocketServer as W}from"ws";import{isSafeNodeId as x}from"../../core/canvas/paths.js";import{getNode as B}from"../../core/canvas/index.js";import{BROKER_READ_CAPS as J,CLIENT_READ_CAPS as j,FrameDecoder as q,FrameOverflowError as z}from"../../core/runtime/broker-protocol.js";import{emitEvent as K}from"../../core/events/emit.js";import{classify as S}from"../../core/fault-classifier.js";import{clearFault as v,markNodeRead as Q,recordFault as A}from"../../core/canvas/recovery.js";import{decideAttachRevive as G}from"../../core/runtime/revive.js";import{connectViewSocket as X,probeViewSocket as Y,waitForBrokerViewSocket as Z}from"../../core/runtime/view-socket.js";import{isBeneathRefusal as I}from"../../core/spaces/open-beneath.js";import{attachViewer as N,detachViewer as ee,presentViewer as re}from"./viewer-presence.js";const te=new W({noServer:!0,maxPayload:J.maxLineBytes}),ae=25e3,oe=6e4;function ne(r,e=ae,l=oe){let a=!0,u=!1,o=Date.now();const i=n(()=>{a=!0},"acknowledge"),s=n(()=>{u||(u=!0,clearInterval(y),r.off("pong",i))},"stop");r.on("pong",i);const y=setInterval(()=>{if(Date.now()-o>l){a=!0;return}if(!a){s(),r.terminate();return}a=!1;try{r.ping()}catch{s(),r.terminate()}},e);return y.unref(),{stop:s,noteActivity:n(()=>{o=Date.now()},"noteActivity")}}n(ne,"startRemoteAttachHeartbeat");function R(r){const e=Buffer.from(r,"utf8");return e.byteLength<=123?r:e.subarray(0,123).toString("utf8")}n(R,"clampReason");function d(r,e,l,a,u){const o=JSON.stringify({error:{code:a,message:u,origin:"runtime"}}),i=`HTTP/1.1 ${e} ${l}\r
|
|
2
2
|
content-type: application/json; charset=utf-8\r
|
|
3
|
-
content-length: ${Buffer.byteLength(
|
|
3
|
+
content-length: ${Buffer.byteLength(o)}\r
|
|
4
4
|
connection: close\r
|
|
5
5
|
\r
|
|
6
|
-
`+
|
|
6
|
+
`+o;try{r.end(i)}catch{try{r.destroy()}catch{}}}n(d,"refuseUpgrade");function ie(r){if(new URL(r.url??"/","http://127.0.0.1").searchParams.get("revive")==="0")return!0;const l=r.headers["x-crtr-attach-revive"];return(Array.isArray(l)?l[0]:l)==="0"}n(ie,"reviveOptedOut");function ce(r){return new URL(r.url??"/","http://127.0.0.1").searchParams.get("wakeParked")==="1"}n(ce,"wakeParkedRequested");function O(r){return r===1e3||r===1001||r===1005}n(O,"isCleanViewerClose");function h(r,e,l){l.catch(a=>K({level:"error",event:e,node_id:r,error:a}))}n(h,"detach");async function se(r,e,l){const a=[];let u=n(t=>{a.push(t)},"relayMessage");if(r.on("message",t=>u(t)),!x(e)){try{r.close(1008,R(`invalid node id: ${e}`))}catch{}return}if(await B(e)===null){try{r.close(1011,R(`no node ${e}`))}catch{}return}await v(e,{link:"viewer\u2194crtrd"});const o=X(e),i=new q(j);let s=!1,y=!1,g,$=!1,C=!1,w="controller",T=Promise.resolve(),k=!1;const b=[];let _=!1;o.on("connect",()=>{$=!0,!s&&k&&N(e,r),h(e,"daemon.bridge.connect_failed",v(e,{link:"relay\u2194broker"}))});const m=n((t,f)=>{if(!s){if(s=!0,ee(e,r),g?.stop(),!o.destroyed)try{o.destroy()}catch{}try{r.close(t,R(f))}catch{}}},"teardown");g=ne(r);const P=n(async t=>{g?.noteActivity();let f;try{f=i.push(t)}catch(c){const p=c instanceof z?`broker sent an oversized frame (${c.message})`:`failed to decode a broker frame for ${e}`;m(1009,p);return}b.push(...f),_||await D()},"onData"),D=n(async()=>{_=!0;try{for(;b.length>0&&!s;){const t=b.splice(0);let f;try{f=await l(w)}catch{m(1011,"revoked");return}if(s)return;if(!f){m(1008,"revoked");return}for(const c of t)if(r.readyState===r.OPEN&&(r.send(JSON.stringify(c)),k&&c?.type==="welcome"&&re(e,r)))try{await Q(e)}catch{}}}finally{_=!1}},"drainOutbound");o.on("data",t=>h(e,"daemon.bridge.data_failed",P(t)));const F=n(async t=>{const f=S("relay\u2194broker",t);await A(e,{link:"relay\u2194broker",op:"bridge socket",kind:f.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}`;m(1011,c)},"onSocketError");o.on("error",t=>h(e,"daemon.bridge.socket_error_failed",F(t)));const U=n(async t=>{s||t||(await v(e,{link:"relay\u2194broker"}),m(1e3,"broker socket closed"))},"onSocketClose");o.on("close",t=>h(e,"daemon.bridge.socket_close_failed",U(t)));const V=n(async(t,f)=>{const c=f.toString("utf8");if(s){O(t)&&await v(e,{link:"viewer\u2194crtrd"});return}if(O(t))await v(e,{link:"viewer\u2194crtrd"});else if(!y){y=!0;const p=S("viewer\u2194crtrd",{code:t,reason:c});await A(e,{link:"viewer\u2194crtrd",op:"remote attach websocket",kind:p.kind,retry:{disposition:"auto"},message:c||`remote attach closed (${t})`})}m(t,c||`remote attach closed (${t})`)},"onWsClose");r.on("close",(t,f)=>h(e,"daemon.bridge.ws_close_failed",V(t,f)));const L=n(async()=>{if(!y){y=!0;const t=S("viewer\u2194crtrd",{code:1006,reason:"remote attach websocket error"});await A(e,{link:"viewer\u2194crtrd",op:"remote attach websocket",kind:t.kind,retry:{disposition:"auto"},message:"remote attach websocket error"})}m(1011,"remote attach websocket error")},"onWsError");r.on("error",()=>h(e,"daemon.bridge.ws_error_failed",L())),u=n(t=>{if(s||o.destroyed)return;g?.noteActivity();const c=(Array.isArray(t)?Buffer.concat(t):Buffer.isBuffer(t)?t:Buffer.from(new Uint8Array(t))).toString("utf8");if(!C)try{const E=JSON.parse(c);E?.type==="hello"&&(C=!0,w=E.role==="observer"?"observer":"controller",k=E.attends!==!1,k&&$&&N(e,r))}catch{}const p=c.endsWith(`
|
|
7
7
|
`)?c:c+`
|
|
8
|
-
|
|
8
|
+
`,H=n(()=>{try{o.write(p)}catch{}},"write");T=T.then(async()=>{s||(await l(w)?H():m(1008,"revoked"))}).catch(()=>m(1011,"revoked"))},"relayMessage");for(const t of a.splice(0))u(t)}n(se,"bridgeConnection");async function be(r,e,l,a,u){e.on("error",()=>{});try{if(!x(a)){d(e,400,"Bad Request","invalid_node_id",`invalid node id: ${a}`);return}if(await B(a)===null){d(e,404,"Not Found","node_not_found",`no node ${a}`);return}if(ie(r)){if(!await Y(a,250)){d(e,409,"Conflict","node_dormant",`node ${a} is dormant and revive was opted out (?revive=0)`);return}}else{let o;try{const i=await G(a,{resume:!0,capacity:"refuse"},ce(r));if(i.parked){d(e,409,"Conflict","node_dormant",`node ${a} is parked; attach with ?wakeParked=1 to wake it`);return}o=i.result.launch?.exited}catch(i){const s=i instanceof Error?i.message:String(i);d(e,409,"Conflict","attach_revive_failed",`attach revive failed: ${s}`);return}if(!await Z(a,o)){d(e,409,"Conflict","broker_not_ready",`broker view socket for ${a} did not become listenable after revive`);return}}if(e.destroyed)return;te.handleUpgrade(r,e,l,o=>h(a,"daemon.bridge.connection_failed",se(o,a,u)))}catch(o){const i=o instanceof Error?o.message:String(o);if(I(o)){d(e,400,"Bad Request","invalid_request",i);return}d(e,500,"Internal Server Error","internal",`attach upgrade failed: ${i}`)}}n(be,"handleAttachUpgrade");export{ae as REMOTE_ATTACH_HEARTBEAT_MS,oe as REMOTE_ATTACH_QUIET_MS,be as handleAttachUpgrade,O as isCleanViewerClose,d as refuseUpgrade,ne as startRemoteAttachHeartbeat};
|
|
@@ -1,2 +1,5 @@
|
|
|
1
|
-
import { type RouteTable } from '../router.js';
|
|
1
|
+
import { type RequestPrincipal, type RouteTable } from '../router.js';
|
|
2
|
+
/** What a caller may do on a node's broker: `read` admits an observer, `message` a controller. Admission (no role yet) takes either; the hello's
|
|
3
|
+
* role then needs its own permission (bridge.ts). */
|
|
4
|
+
export declare function mayAttachNode(principal: RequestPrincipal, role: 'observer' | 'controller' | 'either', nodeId: string): Promise<boolean>;
|
|
2
5
|
export declare const attachRoutes: RouteTable;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
var
|
|
1
|
+
var w=Object.defineProperty;var n=(t,e)=>w(t,"name",{value:e,configurable:!0});import{getNode as k}from"../../../core/canvas/canvas.js";import{decideAttachRevive as l}from"../../../core/runtime/revive.js";import{viewSocketPath as v}from"../../../core/canvas/paths.js";import{waitForBrokerViewSocket as h}from"../../../core/runtime/placement-tmux.js";import{notFound as m,usage as i}from"../../../core/errors.js";import{mayOnNode as u,ownerOnly as p}from"../router.js";function b(t){if(t==null)return{resume:!0,revive:!0,wakeParked:!0};if(typeof t!="object")throw i("attach body must be a JSON object { resume?, revive?, wakeParked? }");const e=t.resume,r=t.revive,a=t.wakeParked;if(e!==void 0&&typeof e!="boolean")throw i("resume must be a boolean");if(r!==void 0&&typeof r!="boolean")throw i("revive must be a boolean");if(a!==void 0&&typeof a!="boolean")throw i("wakeParked must be a boolean");return{resume:e??!0,revive:r??!0,wakeParked:a??!0}}n(b,"parseAttachBody");async function y(t,e,r){return e==="controller"?await u(t,"message",r):await u(t,"read",r)?!0:e==="either"&&await u(t,"message",r)}n(y,"mayAttachNode");async function P(t){const e=t.params.id;if(await k(e)===null)throw m(`unknown node: ${e}`,{received:e});if(!await y(t.principal,"either",e))throw m(`unknown node: ${e}`,{received:e});const{resume:r,revive:a,wakeParked:c}=b(t.body);let s=!1,d=!1,f=!1;if(a){const o=await l(e,{resume:r,capacity:"refuse"},c);f=o.parked,o.parked||(s=o.result.launch!==void 0,d=o.result.resumed,await h(e))}return{status:200,body:{node_id:e,socket_path:v(e),revived:s,resumed:d,parked:f}}}n(P,"handleAttach");const R=p([{method:"POST",pattern:"/v1/nodes/:id/attach",handler:P}]);export{R as attachRoutes,y as mayAttachNode};
|