@north-light/cli 0.3.420 → 0.3.422
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +3 -2
- package/dist/api/error-codes.d.ts +10 -0
- package/dist/api/error-codes.js +1 -1
- package/dist/clients/attach/viewer.js +480 -480
- package/dist/commands/sys/join.js +1 -1
- package/dist/core/directory/join.d.ts +4 -2
- package/dist/core/directory/join.js +1 -1
- package/dist/core/grants/sync.d.ts +6 -0
- package/dist/core/grants/sync.js +1 -1
- package/dist/core/providers/errors.js +1 -1
- package/dist/core/providers/mint.js +1 -1
- package/dist/core/runtime/host.js +3 -3
- package/dist/core/runtime/nodes.js +1 -1
- package/dist/core/runtime/revive.js +2 -2
- package/dist/core/runtime/run-command.js +1 -1
- package/dist/core/runtime/unsandboxed.d.ts +3 -0
- package/dist/core/runtime/unsandboxed.js +1 -0
- package/dist/core/spaces/process.js +1 -1
- package/dist/daemon/api/app-listener.js +13 -13
- package/dist/daemon/api/vendor-signin.d.ts +3 -0
- package/dist/daemon/api/vendor-signin.js +162 -47
- package/dist/daemon/cron/authority.d.ts +1 -1
- package/dist/daemon/cron/authority.js +1 -1
- package/dist/daemon/crtrd.js +7 -7
- package/dist/types.d.ts +3 -1
- package/package.json +2 -2
- package/packages/crouter-identity/package.json +1 -1
- package/runtime.lock.json +12 -12
|
@@ -1,77 +1,192 @@
|
|
|
1
|
-
var
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
1
|
+
var O=Object.defineProperty;var a=(e,t)=>O(e,"name",{value:t,configurable:!0});import{randomBytes as j}from"node:crypto";import{joinedOwner as E}from"../../core/directory/join.js";import{consumeHandoffJti as z,handoffJtiConsumed as y}from"../../core/model-auth/handoff-jti.js";import{completeModelAuthFlow as I,modelAuthProvider as N,readModelAuthFlow as k,startModelAuthFlow as P,waitModelAuthFlow as L}from"../../core/model-auth/flows.js";import{RunError as d}from"../../core/runs/operations.js";import{LONG_POLL_MAX_WAIT_SECONDS as R}from"../../api/long-poll.js";const l="/signin/vendor",$=900,B=R*1e3,G="https://chatgpt.com/#settings/Security";function ce(e){return e===l||e.startsWith(`${l}/`)}a(ce,"isVendorSignInPath");function u(){return new d(401,"unauthorized","invalid vendor sign-in handoff")}a(u,"unauthorized");async function C(e,t){const n=await e.verifyHandoff(t);let r;try{r=E()}catch{r=null}if(n.sub!==r)throw u();return n}a(C,"verifyOwnerHandoff");function U(e){const t=e.headers.authorization;return t?.startsWith("Bearer ")&&t.length>7?t.slice(7):void 0}a(U,"bearer");function x(e,t){const n=e.getAll(t);return n.length===1?n[0]:void 0}a(x,"single");function H(e,t){const n=new URL(e);return n.searchParams.set("status",t),n.toString()}a(H,"returnUrl");function p(e){return e.replace(/[&<>"']/g,t=>({"&":"&","<":"<",">":">",'"':""","'":"'"})[t])}a(p,"escapeHtml");function h(e,t,n){e.writeHead(t,{"Content-Type":"application/json; charset=utf-8","Cache-Control":"no-store"}),e.end(JSON.stringify(n))}a(h,"sendJson");async function J(e){const t=[];let n=0;for await(const o of e){if(n+=o.length,n>64*1024)throw new d(400,"invalid_request","request body too large");t.push(o)}let r;try{r=JSON.parse(Buffer.concat(t).toString("utf8"))}catch{throw new d(400,"invalid_request","invalid JSON body")}if(typeof r!="object"||r===null||Array.isArray(r))throw new d(400,"invalid_request","request body must be a JSON object");return r}a(J,"jsonBody");const D=`
|
|
2
|
+
:root{color-scheme:light dark;
|
|
3
|
+
--canvas:#f0f2f4;--surface:#fff;--sunken:#e5e7ea;--zone:#e5e7ea;--neutral:#e5e7ea;--neutral-hover:#d7d9dc;--neutral-pressed:#cbcdd0;
|
|
4
|
+
--accent:#1f4fbf;--accent-hover:#1b45a8;--accent-pressed:#173b8f;--accent-border:#1f4fbf;--accent-subtle:#dce6fb;--accent-fg:#1f4fbf;--on-accent:#fff;
|
|
5
|
+
--warning-bg:#fcedd4;--warning-fg:#8f5200;--danger-bg:#fce5e2;--danger-fg:#bf2a1f;--danger-line:#bf2a1f;
|
|
6
|
+
--text:#15171a;--muted:#505256;--disabled:#919498;--line:#d7d9dc;--line-strong:#787b7f;--focus:#1f4fbf;
|
|
7
|
+
--sans:system-ui,-apple-system,'Segoe UI',Roboto,'Helvetica Neue',Arial,sans-serif;
|
|
8
|
+
--mono:ui-monospace,SFMono-Regular,Menlo,Consolas,monospace}
|
|
9
|
+
@media (prefers-color-scheme:dark){:root{
|
|
10
|
+
--canvas:#0e1012;--surface:#181a1d;--sunken:#212326;--zone:#212326;--neutral:#212326;--neutral-hover:#2f3134;--neutral-pressed:#3c3e41;
|
|
11
|
+
--accent:#2a5cd0;--accent-hover:#2452c4;--accent-pressed:#1f4fbf;--accent-border:#5585ec;--accent-subtle:#15233f;--accent-fg:#7aa7ff;--on-accent:#fff;
|
|
12
|
+
--warning-bg:#35260f;--warning-fg:#f4b45a;--danger-bg:#3b1715;--danger-fg:#ff8175;--danger-line:#d0342a;
|
|
13
|
+
--text:#f0f2f4;--muted:#acaeb2;--disabled:#505256;--line:#2f3134;--line-strong:#787b7f;--focus:#7aa7ff}}
|
|
14
|
+
*,*::before,*::after{box-sizing:border-box}
|
|
15
|
+
[hidden]{display:none!important}
|
|
16
|
+
body{margin:0;min-height:100vh;min-height:100dvh;display:flex;flex-direction:column;background:var(--canvas);color:var(--text);font:400 .9375rem/1.5333 var(--sans);-webkit-text-size-adjust:100%}
|
|
17
|
+
p,h1,ol{margin:0}
|
|
18
|
+
a{color:inherit}
|
|
19
|
+
:focus-visible{outline:2px solid var(--focus);outline-offset:2px}
|
|
20
|
+
.top{display:flex;align-items:center;gap:.5rem;height:3.5rem;flex:none;padding:0 1rem;background:var(--surface);border-bottom:1px solid var(--line)}
|
|
21
|
+
.top svg{width:20px;height:20px;color:var(--accent-fg)}
|
|
22
|
+
.top span{font-weight:600}
|
|
23
|
+
main{flex:1;display:flex;flex-direction:column;align-items:center;padding:2.5rem 1rem}
|
|
24
|
+
.col{width:100%;max-width:36rem}
|
|
25
|
+
.card{display:flex;flex-direction:column;gap:1.5rem;padding:1.5rem;background:var(--surface);border:1px solid var(--line);border-radius:12px}
|
|
26
|
+
.head{display:flex;align-items:center;gap:1rem}
|
|
27
|
+
.logo{position:relative;flex:none;width:3.5rem;height:3.5rem;border-radius:12px;overflow:hidden}
|
|
28
|
+
.logo svg{display:block;width:100%;height:100%}
|
|
29
|
+
.logo::after{content:"";position:absolute;inset:0;border:1px solid var(--line);border-radius:inherit}
|
|
30
|
+
.eyebrow{display:block;font-size:.8125rem;line-height:1.2308;font-weight:500;color:var(--muted)}
|
|
31
|
+
h1{margin-top:.25rem;font-size:1.25rem;line-height:1.3;font-weight:600;letter-spacing:-.02em}
|
|
32
|
+
.steps{list-style:none;padding:0;display:flex;flex-direction:column;gap:1.25rem}
|
|
33
|
+
.steps>li{display:flex;gap:.875rem}
|
|
34
|
+
.n{position:relative;flex:none;display:flex;align-items:center;justify-content:center;width:1.75rem;height:1.75rem;border-radius:9999px;background:var(--neutral);font-size:.8125rem;font-weight:500;font-variant-numeric:tabular-nums}
|
|
35
|
+
.n svg{display:none;width:1rem;height:1rem}
|
|
36
|
+
li.done .n{background:var(--accent-subtle);color:var(--accent-fg)}
|
|
37
|
+
li.done .n span{display:none}
|
|
38
|
+
li.done .n svg{display:block}
|
|
39
|
+
.body{flex:1;min-width:0;display:flex;flex-direction:column;gap:.625rem;padding-top:.125rem}
|
|
40
|
+
.title{font-weight:500}
|
|
41
|
+
.small{font-size:.84375rem;line-height:1.4815;color:var(--muted)}
|
|
42
|
+
.ic{flex:none;width:1rem;height:1rem;fill:none;stroke:currentColor;stroke-width:2;stroke-linecap:round;stroke-linejoin:round}
|
|
43
|
+
.btn{display:inline-flex;align-items:center;justify-content:center;gap:.5rem;min-height:2.5rem;padding:.4rem 1.125rem;border:1px solid transparent;border-radius:8px;background:var(--neutral);color:var(--text);font:500 .9375rem/1.3 var(--sans);text-align:center;text-decoration:none;cursor:pointer;overflow-wrap:break-word;transition:background-color .12s cubic-bezier(.2,0,0,1)}
|
|
44
|
+
.btn:hover{background:var(--neutral-hover)}
|
|
45
|
+
.btn:active{background:var(--neutral-pressed)}
|
|
46
|
+
.btn.primary{background:var(--accent);border-color:var(--accent-border);color:var(--on-accent)}
|
|
47
|
+
.btn.primary:hover{background:var(--accent-hover)}
|
|
48
|
+
.btn.primary:active{background:var(--accent-pressed)}
|
|
49
|
+
.btn.sm{min-height:2rem;padding:.25rem .75rem;font-size:.84375rem}
|
|
50
|
+
.btn.lg{min-height:3rem;padding:.5rem 1.375rem}
|
|
51
|
+
.btn.wide{width:100%}
|
|
52
|
+
.btn:disabled,.btn[aria-disabled=true]{opacity:.4;cursor:default;pointer-events:none}
|
|
53
|
+
.field{display:flex;flex-direction:column;gap:.375rem}
|
|
54
|
+
label{width:fit-content;font-size:.8125rem;line-height:1.2308;font-weight:500}
|
|
55
|
+
input[type=text]{width:100%;min-width:0;height:3rem;padding:0 .875rem;background:var(--surface);color:var(--text);border:1px solid var(--line-strong);border-radius:8px;font:400 .9375rem/1.5 var(--mono)}
|
|
56
|
+
input[type=text]:focus{outline:2px solid var(--focus);outline-offset:2px}
|
|
57
|
+
input[type=text][aria-invalid=true]{border-color:var(--danger-line)}
|
|
58
|
+
form{display:flex;flex-direction:column;gap:.75rem}
|
|
59
|
+
.err{display:none;align-items:flex-start;gap:.375rem;color:var(--danger-fg);font-size:.84375rem;line-height:1.4815}
|
|
60
|
+
.err.on{display:flex}
|
|
61
|
+
.err .ic{margin-top:.125rem}
|
|
62
|
+
.alert{display:flex;flex-wrap:wrap;align-items:flex-start;gap:.75rem;padding:.75rem .875rem;border-radius:8px;background:var(--warning-bg);font-size:.84375rem;line-height:1.4815}
|
|
63
|
+
.alert>.ic{width:1.125rem;height:1.125rem;margin-top:1px;color:var(--warning-fg)}
|
|
64
|
+
.alert .text{flex:1 1 12rem;min-width:0}
|
|
65
|
+
.alert strong{display:block;font-weight:600}
|
|
66
|
+
.alert .act{flex:none;align-self:center}
|
|
67
|
+
.codebox{display:flex;flex-wrap:wrap;align-items:center;gap:.75rem;padding:1rem;border-radius:12px;background:var(--sunken)}
|
|
68
|
+
.code{flex:1 1 auto;min-width:0;font:600 clamp(1.25rem,7vw,1.75rem)/1.2143 var(--mono);letter-spacing:.18em;overflow-wrap:anywhere}
|
|
69
|
+
.code.expired{color:var(--disabled);text-decoration:line-through}
|
|
70
|
+
.badge{display:inline-flex;align-items:center;gap:.375rem;height:1.25rem;padding:0 .375rem;border-radius:6px;background:var(--danger-bg);color:var(--danger-fg);font-size:.8125rem;font-weight:500;white-space:nowrap}
|
|
71
|
+
.badge::before{content:"";width:.375rem;height:.375rem;border-radius:9999px;background:currentColor}
|
|
72
|
+
.wait{display:flex;align-items:center;gap:.75rem;padding:.75rem 1rem;border-radius:12px;background:var(--zone)}
|
|
73
|
+
.wait .spin{width:1rem;height:1rem;color:var(--accent-fg);fill:none;stroke:currentColor;stroke-width:3;stroke-linecap:round}
|
|
74
|
+
.wait .msg{flex:1;min-width:0;display:flex;flex-direction:column;font-size:.84375rem;line-height:1.4815}
|
|
75
|
+
.wait .msg b{font-weight:500}
|
|
76
|
+
.wait .msg span{color:var(--muted)}
|
|
77
|
+
.clock{display:flex;align-items:center;gap:.375rem;color:var(--muted);font-size:.84375rem;font-variant-numeric:tabular-nums}
|
|
78
|
+
.clock .ic{width:.875rem;height:.875rem}
|
|
79
|
+
.sr{position:absolute;width:1px;height:1px;margin:-1px;padding:0;overflow:hidden;clip:rect(0 0 0 0);white-space:nowrap;border:0}
|
|
80
|
+
.foot{flex:none;display:flex;justify-content:center;padding:0 1rem 2rem;color:var(--muted);font-size:.84375rem;line-height:1.4815;text-align:center}
|
|
81
|
+
.foot a{color:var(--text);text-underline-offset:2px}
|
|
82
|
+
.foot a:hover{color:var(--accent-fg)}
|
|
83
|
+
@media (prefers-reduced-motion:no-preference){.wait .spin{animation:spin 1s linear infinite}}
|
|
84
|
+
@keyframes spin{to{transform:rotate(360deg)}}
|
|
85
|
+
@media (min-width:40rem){.top{padding:0 1.5rem}main{padding:3.5rem 1rem}}
|
|
86
|
+
@media (max-width:30rem){.card{padding:1.25rem}.btn{padding-left:.875rem;padding-right:.875rem}#device-link{font-size:.84375rem}.steps>li{gap:.75rem}.alert .act{margin-left:1.875rem}}
|
|
87
|
+
`,q=`
|
|
12
88
|
(function(){
|
|
13
89
|
var cfg=JSON.parse(document.getElementById('cfg').textContent);
|
|
14
90
|
history.replaceState(null,'',location.pathname);
|
|
15
91
|
var auth={'Authorization':'Bearer '+cfg.handoff};
|
|
16
92
|
function back(status){var u=new URL(cfg.returnTo);u.searchParams.set('status',status);location.assign(u.toString());}
|
|
17
|
-
function
|
|
18
|
-
var error
|
|
93
|
+
function $(id){return document.getElementById(id);}
|
|
94
|
+
var error=$('error'),errorText=$('error-text');
|
|
95
|
+
function setError(msg){errorText.textContent=msg;error.className=msg?'err on':'err';}
|
|
19
96
|
if(cfg.kind==='anthropic'){
|
|
20
|
-
var form
|
|
97
|
+
var form=$('paste'),input=form.elements.code;
|
|
21
98
|
form.addEventListener('submit',function(e){
|
|
22
99
|
e.preventDefault();
|
|
23
|
-
var button=form.querySelector('button');button.disabled=true;
|
|
24
|
-
|
|
100
|
+
var button=form.querySelector('button');button.disabled=true;setError('');input.removeAttribute('aria-invalid');
|
|
101
|
+
function reject(msg){
|
|
102
|
+
setError(msg);input.setAttribute('aria-invalid','true');button.disabled=false;
|
|
103
|
+
var pre=document.querySelectorAll('[data-pre]');for(var i=0;i<pre.length;i++)pre[i].classList.add('done');
|
|
104
|
+
input.focus();
|
|
105
|
+
}
|
|
106
|
+
fetch(cfg.base,{method:'POST',headers:Object.assign({'Content-Type':'application/json'},auth),body:JSON.stringify({input:input.value})})
|
|
25
107
|
.then(function(r){return r.json().then(function(b){return {ok:r.ok,s:r.status,b:b};});})
|
|
26
108
|
.then(function(x){
|
|
27
109
|
if(x.ok){back(x.b.status==='connected'?'connected':'failed');return;}
|
|
28
110
|
if(x.s===401||x.s===404){back('failed');return;}
|
|
29
|
-
|
|
111
|
+
reject((x.b&&x.b.error&&x.b.error.message)||'That code was not accepted.');
|
|
30
112
|
})
|
|
31
|
-
.catch(function(){
|
|
113
|
+
.catch(function(){reject('Could not reach your runtime. Try again.');});
|
|
32
114
|
});
|
|
33
115
|
}else{
|
|
34
|
-
|
|
35
|
-
|
|
116
|
+
var copyLabel=$('copy-label');
|
|
117
|
+
$('copy').addEventListener('click',function(){
|
|
118
|
+
function done(){copyLabel.textContent='Copied';setTimeout(function(){copyLabel.textContent='Copy';},2000);}
|
|
119
|
+
if(navigator.clipboard&&navigator.clipboard.writeText){navigator.clipboard.writeText(cfg.userCode).then(done,function(){});return;}
|
|
120
|
+
var r=document.createRange();r.selectNodeContents($('user-code'));var s=getSelection();s.removeAllRanges();s.addRange(r);
|
|
121
|
+
});
|
|
122
|
+
$('renew').addEventListener('click',function(){back('failed');});
|
|
123
|
+
var deadline=Date.now()+cfg.remainingSeconds*1000,left=$('left'),said=-1,timer;
|
|
124
|
+
function tick(){
|
|
125
|
+
var s=Math.max(0,Math.ceil((deadline-Date.now())/1000));
|
|
126
|
+
left.textContent=Math.floor(s/60)+':'+('0'+(s%60)).slice(-2);
|
|
127
|
+
var m=Math.ceil(s/60);
|
|
128
|
+
if(m!==said){said=m;$('left-live').textContent='Code expires in '+m+(m===1?' minute':' minutes');}
|
|
129
|
+
}
|
|
130
|
+
tick();timer=setInterval(tick,1000);
|
|
131
|
+
function expire(){
|
|
132
|
+
clearInterval(timer);
|
|
133
|
+
$('user-code').className='code expired';$('copy').hidden=true;$('expired-badge').hidden=false;
|
|
134
|
+
var link=$('device-link');link.removeAttribute('href');link.setAttribute('aria-disabled','true');
|
|
135
|
+
$('settings').hidden=true;$('waiting').hidden=true;$('expired').hidden=false;
|
|
136
|
+
}
|
|
36
137
|
(function poll(){
|
|
37
138
|
fetch(cfg.base+'/wait',{headers:auth})
|
|
38
139
|
.then(function(r){if(r.status===401||r.status===404)return {status:'failed'};if(!r.ok)throw new Error(String(r.status));return r.json();})
|
|
39
140
|
.then(function(b){
|
|
40
141
|
if(b.status==='pending'){poll();return;}
|
|
41
142
|
if(b.status==='connected'){back('connected');return;}
|
|
42
|
-
if(b.status==='expired'){
|
|
143
|
+
if(b.status==='expired'){expire();return;}
|
|
43
144
|
back('failed');
|
|
44
145
|
})
|
|
45
146
|
.catch(function(){setTimeout(poll,3000);});
|
|
46
147
|
})();
|
|
47
148
|
}
|
|
48
149
|
})();
|
|
49
|
-
|
|
150
|
+
`,F={arrow:'<path d="M7 7h10v10"/><path d="M7 17 17 7"/>',copy:'<rect width="14" height="14" x="8" y="8" rx="2" ry="2"/><path d="M4 16c-1.1 0-2-.9-2-2V4c0-1.1.9-2 2-2h10c1.1 0 2 .9 2 2"/>',clock:'<circle cx="12" cy="12" r="10"/><path d="M12 6v6l4 2"/>',warn:'<path d="m21.73 18-8-14a2 2 0 0 0-3.48 0l-8 14A2 2 0 0 0 4 21h16a2 2 0 0 0 1.73-3"/><path d="M12 9v4"/><path d="M12 17h.01"/>',alert:'<circle cx="12" cy="12" r="10"/><path d="M12 8v4"/><path d="M12 16h.01"/>',check:'<path d="M20 6 9 18l-5-5"/>'};function c(e,t=""){return`<svg class="ic${t}" viewBox="0 0 24 24" aria-hidden="true" focusable="false">${F[e]}</svg>`}a(c,"icon");const W='<svg viewBox="0 0 32 32" aria-hidden="true" focusable="false"><path d="M23.4 8.6A10.5 10.5 0 1 0 23.4 23.4" fill="none" stroke="currentColor" stroke-width="3" stroke-linecap="round"/><path d="M16 16 L27.5 16" fill="none" stroke="currentColor" stroke-width="2.4" stroke-linecap="round" stroke-linejoin="round"/><circle cx="16" cy="16" r="3.6" fill="currentColor"/><circle cx="27.5" cy="16" r="3.2" fill="currentColor"/></svg>',V={claude:'<svg viewBox="0 0 24 24" aria-hidden="true" focusable="false"><rect width="24" height="24" fill="#d97757"/><path d="M12 5v14M5 12h14M7 7l10 10M17 7 7 17" stroke="#fff" stroke-width="1.8" stroke-linecap="round"/></svg>',chatgpt:'<svg viewBox="0 0 24 24" aria-hidden="true" focusable="false"><rect width="24" height="24" fill="#141816"/><circle cx="12" cy="12" r="5.5" fill="none" stroke="#fff" stroke-width="1.8"/></svg>'},S="team@northlight.ai";function T(e){const t=JSON.stringify(e.config).replace(/</g,"\\u003c");return`<!doctype html>
|
|
50
151
|
<html lang="en"><head><meta charset="utf-8"><meta name="viewport" content="width=device-width,initial-scale=1">
|
|
51
|
-
<
|
|
52
|
-
<
|
|
152
|
+
<meta name="color-scheme" content="light dark">
|
|
153
|
+
<title>${p(e.title)}</title><style nonce="${e.nonce}">${D}</style></head>
|
|
154
|
+
<body>
|
|
155
|
+
<header class="top">${W}<span>Northlight</span></header>
|
|
156
|
+
<main><div class="col">${e.body}</div></main>
|
|
157
|
+
<footer class="foot"><span>Need help? Email <a href="mailto:${S}">${S}</a></span></footer>
|
|
53
158
|
<script type="application/json" id="cfg">${t}<\/script>
|
|
54
|
-
<script nonce="${e.nonce}">${
|
|
55
|
-
</body></html>`}a(
|
|
56
|
-
|
|
57
|
-
<
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
<
|
|
62
|
-
<
|
|
63
|
-
|
|
64
|
-
<
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
<
|
|
70
|
-
<
|
|
71
|
-
<
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
<
|
|
159
|
+
<script nonce="${e.nonce}">${q}<\/script>
|
|
160
|
+
</body></html>`}a(T,"page");function M(e,t){return`<div class="head"><div class="logo">${V[e]}</div><div><span class="eyebrow">AI subscription</span><h1>Connect your ${t} account</h1></div></div>`}a(M,"header");function f(e,t,n="",r=""){return`<li${r}><span class="n"><span>${e}</span>${c("check")}</span><div class="body"><span class="title">${t}</span>${n}</div></li>`}a(f,"step");function X(e,t,n,r){return T({nonce:t,title:"Connect Claude",body:`<div class="card">
|
|
161
|
+
${M("claude","Claude")}
|
|
162
|
+
<ol class="steps">
|
|
163
|
+
${f(1,"Sign in to Claude in a new tab",`<div><a class="btn" href="${p(e.url)}" target="_blank" rel="noopener noreferrer">Open claude.ai${c("arrow")}</a></div>`," data-pre")}
|
|
164
|
+
${f(2,"Copy the code Claude shows you",""," data-pre")}
|
|
165
|
+
${f(3,"Paste it here",`<form id="paste" autocomplete="off">
|
|
166
|
+
<div class="field"><label for="code">Code from Claude</label>
|
|
167
|
+
<input type="text" id="code" name="code" required spellcheck="false" autocapitalize="off" aria-describedby="error">
|
|
168
|
+
<div id="error" class="err" role="alert">${c("alert")}<span id="error-text"></span></div></div>
|
|
169
|
+
<button class="btn primary lg wide" type="submit">Connect Claude</button>
|
|
170
|
+
</form>`)}
|
|
171
|
+
</ol>
|
|
172
|
+
</div>`,config:{kind:"anthropic",base:`${l}/${encodeURIComponent(e.flow_id)}`,returnTo:n,handoff:r}})}a(X,"anthropicPage");function Y(e,t){const n=Date.parse(e.expires_at)-t;return Math.max(0,Math.floor(Math.min(Number.isNaN(n)?$*1e3:n,$*1e3)/1e3))}a(Y,"codeSecondsLeft");function K(e,t,n,r,o=Date.now()){const i=e.user_code??"";return T({nonce:t,title:"Connect ChatGPT",body:`<div class="card">
|
|
173
|
+
${M("chatgpt","ChatGPT")}
|
|
174
|
+
<div class="alert" id="settings" role="alert">${c("warn")}
|
|
175
|
+
<div class="text"><strong>Turn on device code sign-in first</strong>OpenAI refuses this sign-in unless device code authorization for Codex is on in ChatGPT's Security settings.</div>
|
|
176
|
+
<div class="act"><a class="btn sm" href="${G}" target="_blank" rel="noopener noreferrer">Open settings${c("arrow")}</a></div></div>
|
|
177
|
+
<ol class="steps" id="device">
|
|
178
|
+
${f(1,"Open the OpenAI device page",`<div><a class="btn" id="device-link" href="${p(e.url)}" target="_blank" rel="noopener noreferrer">${p(e.url.replace(/^https:\/\//,""))}${c("arrow")}</a></div>`)}
|
|
179
|
+
${f(2,"Enter this code",`<div class="codebox"><span class="code" id="user-code">${p(i)}</span>
|
|
180
|
+
<span class="badge" id="expired-badge" hidden>Expired</span>
|
|
181
|
+
<button class="btn sm" type="button" id="copy">${c("copy")}<span id="copy-label">Copy</span></button></div>`)}
|
|
182
|
+
${f(3,"Approve the sign-in",`<span class="small">When OpenAI shows an account email, check it's the account you want to use: approving connects that account.</span>`)}
|
|
183
|
+
</ol>
|
|
184
|
+
<div class="wait" id="waiting">
|
|
185
|
+
<svg class="spin" viewBox="0 0 24 24" aria-hidden="true" focusable="false"><path d="M21 12a9 9 0 1 1-9-9"/></svg>
|
|
186
|
+
<div class="msg" aria-live="polite"><b>Waiting for your approval at OpenAI</b><span>This page moves on by itself.</span></div>
|
|
187
|
+
<div class="clock">${c("clock")}<span id="left" aria-hidden="true"></span><span class="sr" id="left-live" aria-live="polite"></span></div>
|
|
76
188
|
</div>
|
|
77
|
-
<
|
|
189
|
+
<div class="alert" id="expired" role="alert" hidden>${c("warn")}
|
|
190
|
+
<div class="text"><strong>The code expired before it was approved</strong>Codes last 15 minutes. Getting a new one starts the sign-in over.</div>
|
|
191
|
+
<div class="act"><button class="btn primary sm" type="button" id="renew">Get a new code</button></div></div>
|
|
192
|
+
</div>`,config:{kind:"openai",base:`${l}/${encodeURIComponent(e.flow_id)}`,returnTo:n,handoff:r,userCode:i,expiresAt:e.expires_at,remainingSeconds:Y(e,o)}})}a(K,"openaiPage");async function Q(e,t,n,r){const o=x(n.searchParams,"handoff"),i=await C(r,o);if(y(i.jti))throw u();const s=x(n.searchParams,"return_to");let b;try{b=s===void 0?void 0:new URL(s).origin}catch{b=void 0}if(s===void 0||b!==new URL(r.issuer).origin)throw new d(400,"invalid_request","return_to must be an absolute URL on the directory origin","return_to");const g=x(n.searchParams,"vendor");if(g!=="anthropic"&&g!=="openai")throw new d(400,"invalid_request","vendor must be anthropic or openai","vendor");if(!z(i.jti,i.exp))throw u();let v;try{v=await P({provider:N(g),jti:i.jti})}catch(w){console.error("[vendor-signin] start failed:",w instanceof Error?w.message:w),t.writeHead(303,{Location:H(s,"failed"),"Cache-Control":"no-store","Referrer-Policy":"no-referrer"}),t.end();return}const m=j(16).toString("base64"),A=g==="anthropic"?X(v,m,s,o):K(v,m,s,o);t.writeHead(200,{"Content-Type":"text/html; charset=utf-8","Cache-Control":"no-store","Referrer-Policy":"no-referrer","X-Content-Type-Options":"nosniff","Content-Security-Policy":`default-src 'none'; script-src 'nonce-${m}'; style-src 'nonce-${m}'; connect-src 'self'; form-action 'none'; base-uri 'none'; frame-ancestors 'none'`}),t.end(A)}a(Q,"startPage");async function _(e,t,n){const r=await C(t,U(e)),o=k(n);if(!o){if(y(r.jti))return!1;throw u()}if(o.jti===void 0||o.jti!==r.jti)throw u();return!0}a(_,"followUpFlow");async function Z(e,t,n,r){if(!await _(e,n,r)){h(t,200,{status:"failed"});return}const o=await J(e);try{await I(r,o.input),h(t,200,{status:"connected"})}catch(i){const s=k(r);if(s&&s.status!=="pending"){h(t,200,{status:"failed"});return}throw i}}a(Z,"submitCode");async function ee(e,t,n,r){if(!await _(e,n,r)){h(t,200,{status:"failed"});return}const o=new AbortController;t.once("close",()=>o.abort());const i=await L(r,B,o.signal);h(t,200,{status:i?.status??"failed"})}a(ee,"waitFlow");async function de(e,t,n,r){const o=e.method??"GET";if(n.pathname===l&&o==="GET"){await Q(e,t,n,r);return}const i=n.pathname.slice(l.length+1).split("/");let s="";try{s=i[0]?decodeURIComponent(i[0]):""}catch{throw new d(404,"not_found","unknown operation")}if(s&&i.length===1&&o==="POST"){await Z(e,t,r,s);return}if(s&&i.length===2&&i[1]==="wait"&&o==="GET"){await ee(e,t,r,s);return}throw new d(404,"not_found","unknown operation")}a(de,"handleVendorSignIn");export{l as VENDOR_SIGNIN_PATH,X as anthropicPage,de as handleVendorSignIn,ce as isVendorSignInPath,K as openaiPage};
|
|
@@ -6,7 +6,7 @@ export interface CronPrincipal {
|
|
|
6
6
|
/** Null = the grant's whole current set (person-armed terminal crons only). */
|
|
7
7
|
scopes: readonly string[] | null;
|
|
8
8
|
}
|
|
9
|
-
export type CronRefusalReason = 'grant_missing' | 'grant_revoked' | 'scope_narrowed' | 'scope_missing';
|
|
9
|
+
export type CronRefusalReason = 'unsandboxed_machine' | 'grant_missing' | 'grant_revoked' | 'scope_narrowed' | 'scope_missing';
|
|
10
10
|
export type CronAuthority =
|
|
11
11
|
/** `effectiveScopes` is the grant's current resolved set. A stored scope list is a second ceiling the caller still applies (as `router.ts` does for a broker). */
|
|
12
12
|
{
|
|
@@ -1 +1 @@
|
|
|
1
|
-
var c=Object.defineProperty;var o=(r,e)=>c(r,"name",{value:e,configurable:!0});import{covers as
|
|
1
|
+
var c=Object.defineProperty;var o=(r,e)=>c(r,"name",{value:e,configurable:!0});import{covers as u}from"@north-light/identity";import{activeRecord as g,grantRecord as d}from"../../core/grants/mirror.js";import{readConfig as l}from"../../core/config.js";import{isUnsandboxedMachine as f}from"../../core/runtime/unsandboxed.js";import{SCOPE_VOCABULARY as m,scopeAllowed as i}from"../../core/scopes.js";function t(r,e){return{allowed:!1,reason:r,message:e}}o(t,"refuse");function _(r){if(r.grantee!=="app:terminal"&&f())return t("unsandboxed_machine",`This computer runs only your own terminal agents; ${r.grantee} runs on your hosted machine.`);let e;if(r.grant_id===null){if(r.grantee!=="app:terminal"||l("user").runtime?.issuer)return t("grant_missing",`cron has no grant for ${r.grantee}; re-arm it from a node of that app`);e=m}else{const n=d(r.grant_id);if(n===null)return t("grant_missing",`grant ${r.grant_id} is not in this runtime's grant mirror`);if(n.status!=="active")return t("grant_revoked",`grant ${r.grant_id} is ${n.status}`);if(n.expires_at!==null&&Date.parse(n.expires_at)<=Date.now())return t("grant_revoked",`grant ${r.grant_id} expired at ${n.expires_at}`);if(n.grantee!==r.grantee||n.sub!==r.sub)return t("grant_revoked",`grant ${r.grant_id} no longer belongs to ${r.grantee} for ${r.sub}`);const s=g(n);if(s===null)return t("grant_revoked",`grant ${r.grant_id} cannot be read`);e=s.resolved}if(r.scopes!==null){const n=r.scopes.find(s=>!e.some(a=>u(a,s)));if(n!==void 0)return t("scope_narrowed",`scope ${n} is no longer covered by the grant`)}return!i(e,"crtr:schedule")||!i(r.scopes,"crtr:schedule")?t("scope_missing","the cron no longer holds crtr:schedule"):{allowed:!0,effectiveScopes:e}}o(_,"checkCronFire");function w(r){const e=_(r);return e.allowed&&(!i(e.effectiveScopes,"crtr:act")||!i(r.scopes,"crtr:act"))?t("scope_missing","the cron no longer holds crtr:act"):e}o(w,"checkCronBirth");function k(r){return{grantee:r.grantee,sub:r.sub,grant_id:r.grant_id,scopes:r.scopes}}o(k,"cronPrincipalOf");export{w as checkCronBirth,_ as checkCronFire,k as cronPrincipalOf};
|
package/dist/daemon/crtrd.js
CHANGED
|
@@ -1,13 +1,13 @@
|
|
|
1
|
-
var Se=Object.defineProperty;var s=(t,o)=>Se(t,"name",{value:o,configurable:!0});import{writeFileSync as _e,readFileSync as ke,rmSync as be,mkdirSync as Y,existsSync as b,chmodSync as Ee}from"node:fs";import{createServer as X}from"node:http";import{dirname as Re}from"node:path";import{envCrtrdTcp as Ie}from"../shared/env.js";import{serveCanvasConversationStore as Pe}from"../core/canvas/sessions.js";import{pollRunObservers as xe}from"./runs/observer.js";import{randomBytes as Te}from"node:crypto";import{apiSocketPath as De,crtrHome as Ce}from"../core/canvas/paths.js";import{activeAppUsers as Le}from"../core/spaces/users.js";import{ensureAppSpace as $e,ensureUserFiles as Ae}from"../core/spaces/space.js";import{LAUNCHER_SOCKET as R}from"../launcher/spec.js";import{launcherRequest as x}from"../launcher/client.js";import{installLauncherEventSink as Ne}from"./launcher-events.js";import{initializeEmptyLayout as Me,layoutNeedsMigration as Ge,socketDir as Z}from"../core/layout.js";import{migrateLooseKeys as Oe}from"../core/layout-migrate/loose-keys.js";import{getNode as Fe,listNodesForSupervision as He,setFrozen as Be}from"../core/canvas/index.js";import{createApiServer as qe}from"./api/server.js";import{createAppListener as je}from"./api/app-listener.js";import{installLocalTerminalGrant as ze}from"../core/grants/local.js";import{onRunEventAppended as We}from"../core/runs/events.js";import{runNotices as Ue}from"./run-notices.js";import{createGrantSync as Ke,GRANT_SYNC_INTERVAL_S as Je}from"../core/grants/sync.js";import{runRemovalCascades as Ve}from"../core/grants/remove.js";import{sweepSandboxes as Qe}from"../core/grants/on-sync.js";import{rebuildCronExecutions as Ye}from"./cron/run-socket.js";import{hasSyncedGrants as Xe}from"../core/grants/mirror.js";import{readConfig as Ze}from"../core/config.js";import{reconcileUndeliveredTickets as er}from"./human/sweep.js";import{resetHandedOffDeliveries as rr}from"../core/canvas/deliveries.js";import{resetHandedOffDaemonActions as tr}from"../core/canvas/daemon-actions.js";import{sweepReviews as or}from"./review/sweep.js";import{pidfilePath as G}from"./pidfile.js";import{rendererWarning as nr}from"../core/runtime/package-health.js";import{DEFAULT_INTERVAL_MS as ir}from"./supervise-cadence.js";import{createResumeDetector as sr}from"./resume-detector.js";import{BrokerSupervisionReconciler as ar}from"./reconcilers/broker-supervision.js";import{ControllerDeathReconciler as cr}from"./reconcilers/controller-death.js";import{NodeLifecycleReconciler as lr}from"./reconcilers/node-lifecycle/tick.js";import{NodeDeadlineReconciler as dr}from"./reconcilers/node-deadline.js";import{CronLaneReconciler as pr}from"./reconcilers/cron-lane.js";import{DeliveryLaneReconciler as mr}from"./reconcilers/delivery-lane.js";import{ActionLaneReconciler as fr}from"./reconcilers/action-lane.js";import{endLiveExecution as ur,migrateLegacyExecutionIdentities as hr}from"../core/canvas/executions.js";import{revokePriorEpochNodeTokens as vr}from"../core/canvas/node-tokens.js";import{PendingReviewSubmitReconciler as wr}from"./reconcilers/pending-review-submit.js";import{StorageMaintenanceReconciler as gr}from"./reconcilers/storage-maintenance.js";import{StorageDueWorkReconciler as yr}from"./reconcilers/storage-due-work.js";import{BashDeadlineReconciler as Sr}from"./reconcilers/bash-deadline.js";import{FaultRetryBackstopReconciler as _r}from"./reconcilers/fault-retry-backstop.js";import{StructuredRequestReconciler as kr}from"./reconcilers/structured-request-lane.js";import{reconcileStructuredRequestSidecars as br}from"./structured-requests/boot.js";import{captureLivenessSnapshot as ee,capturePidCommand as Er,captureTeardownSnapshot as re,isPidAlive as Rr,isAnyPidAlive as te,killProcessTreePids as oe}from"../core/canvas/pid.js";import{bindFleet as Ir,boundFleet as Pr}from"../core/runtime/fleet.js";import{bindDaemonControl as xr,clearDaemonControl as Tr}from"./control.js";import{execDaemon as Dr,spawnDaemon as Cr}from"./manage.js";import{reconcileAndMigrateBoot as Lr}from"../core/canvas/boot.js";import{resolveInstallId as $r}from"../core/canvas/install-id.js";import{setInstallId as Ar}from"../core/runtime/nodes.js";import{claimDaemonOwnership as Nr,releaseDaemonOwnership as ne}from"../core/canvas/daemon-owner.js";import{migrate as Mr,openDb as ie,withCanvasWrite as Gr,bindDaemonCanvasOpenHook as Or,clearDaemonCanvasOpenHook as se}from"../core/canvas/db.js";import{brokerSignalBus as O}from"./broker-signals/bus.js";import{brokerSignalStreams as Fr}from"./api/handlers/broker-signals.js";import{reconcilePackageDocuments as Hr}from"../core/graph/package-docs.js";import{startRepoSync as Br}from"../core/graph/repo-sync/index.js";import{prewarmRecentRecipes as qr,reapStaleSpares as jr}from"../core/runtime/warm-pool.js";import{DaemonFleet as zr}from"./fleet.js";import{BOOT_MIGRATIONS as Wr}from"./boot-migrations.js";import{applyJoinedOwner as Ur}from"./joined-owner.js";import{emitEvent as u}from"../core/events/emit.js";import{operationIdContext as _}from"../core/events/operation-id.js";import{bindDaemonEventSource as Kr}from"../core/events/source.js";import{activateCanvasImport as Jr,MigrationBlockedError as Vr,runForcedCanvasImport as Qr}from"../migrations/activation.js";import{convertLegacyProviderStore as Yr,convertLegacyScopedStore as Xr}from"../core/scoped-state/migrate.js";import{userScopeRoot as Zr}from"../core/scope.js";import{secretsDir as et}from"../core/layout.js";function F(t,o){return t.includes(` --canvas-home ${o} `)}s(F,"brokerCommandDeclaresCanvasHome");function H(t){return/ --epoch (\S+) /.exec(t)?.[1]??null}s(H,"brokerCommandEpoch");const rt=5e3,ae=150;async function tt(t){const o=ee();if(o===null)throw u({level:"error",event:"daemon.census.snapshot_failed",fields:{invariant:"prior-epoch brokers are reaped before readiness"}}),new Error("prior-epoch broker census could not capture the process table");const a=Ce(),m=[];for(const[i,p]of o.processes){const g=p.command;if(p.zombie||!g.includes("broker-cli.js")||!F(g,a)||H(g)===t)continue;const S=g.trim().split(/\s+/).at(-1)??"";S===""||S.endsWith("broker-cli.js")||m.push({pid:i,nodeId:S})}let f=0;const n=[];for(const i of m){const p=Er(i.pid);if(p===null||!p.includes("broker-cli.js")||!F(p,a)||H(p)===t||p.trim().split(/\s+/).at(-1)!==i.nodeId)continue;const g=re(i.pid,null);if(!g.reused){try{process.platform==="linux"&&b(R)?await x({operation:"stop",pid:i.pid}):process.kill(i.pid,"SIGTERM")}catch{continue}f++,n.push({pid:i.pid,snap:g})}}const w=Date.now()+rt;for(;Date.now()<w&&n.some(i=>te(i.snap.tree.length>0?i.snap.tree:[i.pid]));)await new Promise(i=>setTimeout(i,ae));let v=0;for(const i of n){const p=i.snap.tree.length>0?i.snap.tree:[i.pid];te(p)&&(process.platform==="linux"&&b(R)?await x({operation:"stop",pid:i.pid}):oe(p,"SIGKILL",i.snap.identities),v++)}v>0&&await new Promise(i=>setTimeout(i,ae));const l=ee();if(l===null)throw u({level:"error",event:"daemon.census.snapshot_failed",fields:{invariant:"prior-epoch brokers are reaped before readiness",stage:"final"}}),new Error("prior-epoch broker census could not capture the final process table");const d=[];for(const[i,p]of l.processes){const g=p.command;p.zombie||!g.includes("broker-cli.js")||F(g,a)&&H(g)!==t&&d.push(i)}if(d.length>0)throw new Error(`prior-epoch broker census could not prove termination of pid(s): ${d.join(", ")}`);u({level:"info",event:"daemon.census.completed",fields:{prior_epoch_brokers:m.length,sigtermed:f,sigkilled:v}})}s(tt,"reapPriorEpochBrokers");const ot=5e3;async function nt(t){const o=Array.from(t.entries());if(o.length===0)return;for(const[n]of o){const w=Fe(n)?.status;(w==="active"||w==="idle")&&Be(n,new Date().toISOString())}const a=o.map(([,n])=>({pid:n.pid,snap:re(n.pid,null),exited:n.handle.exited}));for(const n of a)if(!n.snap.reused)try{process.platform==="linux"&&b(R)?await x({operation:"stop",pid:n.pid}):process.kill(n.pid,"SIGTERM")}catch{}const m=new Promise(n=>{setTimeout(n,ot).unref()});await Promise.allSettled(a.map(n=>Promise.race([n.exited.then(()=>{}),m])));const f=[];for(const n of a)Rr(n.pid)&&(process.platform==="linux"&&b(R)?await x({operation:"stop",pid:n.pid}):oe(n.snap.tree.length>0?n.snap.tree:[n.pid],"SIGKILL",n.snap.identities),f.push(n));await Promise.all(f.map(n=>n.exited));for(const[n]of o)ur(n,{reason:"daemon-teardown"});u({level:"info",event:"daemon.fleet_teardown.completed",fields:{brokers:a.length,sigkilled:f.length}})}s(nt,"teardownFleet");function ce(){Y(Re(G()),{recursive:!0}),_e(G(),String(process.pid),"utf8")}s(ce,"writePidfile");function le(t){return typeof t=="object"&&t!==null&&t.code==="ENOENT"}s(le,"isMissingPathError");function de(t){const o=G();let a;try{a=ke(o,"utf8")}catch(m){if(le(m))return;throw m}if(a.trim()!==String(t))throw new Error(`daemon readiness mirror does not name this invocation (expected pid ${t})`);try{be(o)}catch(m){if(le(m))return;throw m}}s(de,"removeOwnedPidfileMirror");const it={acceptsDetachedWork:s(()=>!0,"acceptsDetachedWork"),registerDetached:s(t=>{t.catch(()=>{})},"registerDetached")},B=new ar,st=new cr,at=new lr,ct=new dr,lt=new pr,dt=new mr,pt=new fr,mt=new wr,ft=new gr,ut=new yr,ht=new Sr,vt=new _r,wt=new kr;async function gt(t=Date.now(),o=it){const a=Pr(),m=await B.runFleetPreamble(a);let f,n;try{const v=He();f=v.filter(l=>l.status==="active"||l.status==="idle"),n=v.filter(l=>l.status==="done"||l.status==="canceled"||l.status==="dead")}catch(v){u({level:"error",event:"canvas.node_list.failed",error:v});return}await B.run(t,{rows:f,fleet:a,lifecycle:o}),st.run(t,{rows:f});const w=await at.run(t,{rows:[...f,...n],fleet:a});ct.run(t),wt.run(t),lt.run(t,{lifecycle:o}),dt.run(t,{lifecycle:o}),pt.run(t,{lifecycle:o}),mt.run(t,{lifecycle:o}),ft.run(t,{lifecycle:o,fleet:a}),ut.run(t,{lifecycle:o}),xe(),vt.run(t,{fleet:a,lifecycle:o}),await ht.run(t,{rows:f}),B.warnIfSaturated({fleet:a,lifecycle:o,thresholds:m,frozen:w})}s(gt,"superviseTick");async function yt(t){Y(Z(),{recursive:!0,mode:493}),process.platform==="linux"&&Ee(Z(),493);const o=De();if(b(o))throw new Error(`layout refusal cannot bind occupied socket: ${o}`);const a=X((l,d)=>{if(l.method==="GET"&&l.url==="/healthz"){d.writeHead(200,{"content-type":"application/json; charset=utf-8"}),d.end(JSON.stringify({ok:!1,daemon_up:!0,store_accessible:!1,brokers_reconciled:!1,startup_phase:"blocked",startup_blocked:"layout_migration_required"}));return}d.writeHead(503,{"content-type":"application/json; charset=utf-8"}),d.end(JSON.stringify({error:{code:"layout_migration_required",message:"run crtr sys migrate while the runtime is offline",type:"server_error",origin:"runtime",retryable:!1}}))});await new Promise((l,d)=>{a.once("error",d),a.listen(o,()=>{a.off("error",d),l()})});let m;const f=t.tcp??Ie();if(f){const l=/^(.*):(\d+)$/.exec(f);if(!l||Number(l[2])>65535)throw new Error(`invalid refusal TCP address: ${f}`);const d=X(a.listeners("request")[0]);await new Promise((i,p)=>{d.once("error",p),d.listen(Number(l[2]),l[1],()=>{d.off("error",p),i()})}),m=d}ce();let n;const w=s(()=>(n??=(async()=>{a.closeAllConnections(),m?.closeAllConnections(),await Promise.all([a,m].filter(l=>l!==void 0).map(l=>new Promise((d,i)=>l.close(p=>p?i(p):d())))),de(process.pid),process.off("SIGINT",v),process.off("SIGTERM",v)})(),n),"cleanup"),v=s(()=>{w().then(()=>process.exit(0),l=>{process.stderr.write(`[crtrd] layout refusal cleanup failed: ${String(l)}
|
|
2
|
-
`),process.exit(1)})},"onSignal");return process.on("SIGINT",v),process.on("SIGTERM",v),w}s(yt,"serveLayoutRefusal");async function St(t={}){if(Ge())return yt(t);Me();const
|
|
3
|
-
`);else{const r=[
|
|
4
|
-
`),
|
|
1
|
+
var Se=Object.defineProperty;var s=(t,n)=>Se(t,"name",{value:n,configurable:!0});import{writeFileSync as _e,readFileSync as be,rmSync as ke,mkdirSync as Y,existsSync as k,chmodSync as Ee}from"node:fs";import{createServer as X}from"node:http";import{dirname as Re}from"node:path";import{envCrtrdTcp as Ie}from"../shared/env.js";import{serveCanvasConversationStore as xe}from"../core/canvas/sessions.js";import{pollRunObservers as Pe}from"./runs/observer.js";import{randomBytes as Te}from"node:crypto";import{apiSocketPath as De,crtrHome as Ce}from"../core/canvas/paths.js";import{activeAppUsers as Le}from"../core/spaces/users.js";import{ensureAppSpace as $e,ensureUserFiles as Ae}from"../core/spaces/space.js";import{LAUNCHER_SOCKET as R}from"../launcher/spec.js";import{launcherRequest as P}from"../launcher/client.js";import{installLauncherEventSink as Ne}from"./launcher-events.js";import{initializeEmptyLayout as Me,layoutNeedsMigration as Ge,socketDir as Z}from"../core/layout.js";import{migrateLooseKeys as Oe}from"../core/layout-migrate/loose-keys.js";import{getNode as Fe,listNodesForSupervision as He,setFrozen as Be}from"../core/canvas/index.js";import{createApiServer as qe}from"./api/server.js";import{createAppListener as je}from"./api/app-listener.js";import{installLocalTerminalGrant as ze}from"../core/grants/local.js";import{onRunEventAppended as We}from"../core/runs/events.js";import{runNotices as Ue}from"./run-notices.js";import{createGrantSync as Ke,GRANT_SYNC_INTERVAL_S as Je}from"../core/grants/sync.js";import{runRemovalCascades as Ve}from"../core/grants/remove.js";import{sweepSandboxes as Qe}from"../core/grants/on-sync.js";import{rebuildCronExecutions as Ye}from"./cron/run-socket.js";import{hasSyncedGrants as Xe}from"../core/grants/mirror.js";import{readConfig as Ze}from"../core/config.js";import{reconcileUndeliveredTickets as er}from"./human/sweep.js";import{resetHandedOffDeliveries as rr}from"../core/canvas/deliveries.js";import{resetHandedOffDaemonActions as tr}from"../core/canvas/daemon-actions.js";import{sweepReviews as nr}from"./review/sweep.js";import{pidfilePath as G}from"./pidfile.js";import{rendererWarning as or}from"../core/runtime/package-health.js";import{DEFAULT_INTERVAL_MS as ir}from"./supervise-cadence.js";import{createResumeDetector as sr}from"./resume-detector.js";import{BrokerSupervisionReconciler as ar}from"./reconcilers/broker-supervision.js";import{ControllerDeathReconciler as cr}from"./reconcilers/controller-death.js";import{NodeLifecycleReconciler as dr}from"./reconcilers/node-lifecycle/tick.js";import{NodeDeadlineReconciler as lr}from"./reconcilers/node-deadline.js";import{CronLaneReconciler as pr}from"./reconcilers/cron-lane.js";import{DeliveryLaneReconciler as mr}from"./reconcilers/delivery-lane.js";import{ActionLaneReconciler as fr}from"./reconcilers/action-lane.js";import{endLiveExecution as ur,migrateLegacyExecutionIdentities as hr}from"../core/canvas/executions.js";import{revokePriorEpochNodeTokens as vr}from"../core/canvas/node-tokens.js";import{PendingReviewSubmitReconciler as wr}from"./reconcilers/pending-review-submit.js";import{StorageMaintenanceReconciler as gr}from"./reconcilers/storage-maintenance.js";import{StorageDueWorkReconciler as yr}from"./reconcilers/storage-due-work.js";import{BashDeadlineReconciler as Sr}from"./reconcilers/bash-deadline.js";import{FaultRetryBackstopReconciler as _r}from"./reconcilers/fault-retry-backstop.js";import{StructuredRequestReconciler as br}from"./reconcilers/structured-request-lane.js";import{reconcileStructuredRequestSidecars as kr}from"./structured-requests/boot.js";import{captureLivenessSnapshot as ee,capturePidCommand as Er,captureTeardownSnapshot as re,isPidAlive as Rr,isAnyPidAlive as te,killProcessTreePids as ne}from"../core/canvas/pid.js";import{bindFleet as Ir,boundFleet as xr}from"../core/runtime/fleet.js";import{bindDaemonControl as Pr,clearDaemonControl as Tr}from"./control.js";import{execDaemon as Dr,spawnDaemon as Cr}from"./manage.js";import{reconcileAndMigrateBoot as Lr}from"../core/canvas/boot.js";import{resolveInstallId as $r}from"../core/canvas/install-id.js";import{setInstallId as Ar}from"../core/runtime/nodes.js";import{claimDaemonOwnership as Nr,releaseDaemonOwnership as oe}from"../core/canvas/daemon-owner.js";import{migrate as Mr,openDb as ie,withCanvasWrite as Gr,bindDaemonCanvasOpenHook as Or,clearDaemonCanvasOpenHook as se}from"../core/canvas/db.js";import{brokerSignalBus as O}from"./broker-signals/bus.js";import{brokerSignalStreams as Fr}from"./api/handlers/broker-signals.js";import{reconcilePackageDocuments as Hr}from"../core/graph/package-docs.js";import{startRepoSync as Br}from"../core/graph/repo-sync/index.js";import{prewarmRecentRecipes as qr,reapStaleSpares as jr}from"../core/runtime/warm-pool.js";import{DaemonFleet as zr}from"./fleet.js";import{BOOT_MIGRATIONS as Wr}from"./boot-migrations.js";import{applyJoinedOwner as Ur}from"./joined-owner.js";import{emitEvent as u}from"../core/events/emit.js";import{operationIdContext as _}from"../core/events/operation-id.js";import{bindDaemonEventSource as Kr}from"../core/events/source.js";import{activateCanvasImport as Jr,MigrationBlockedError as Vr,runForcedCanvasImport as Qr}from"../migrations/activation.js";import{convertLegacyProviderStore as Yr,convertLegacyScopedStore as Xr}from"../core/scoped-state/migrate.js";import{userScopeRoot as Zr}from"../core/scope.js";import{secretsDir as et}from"../core/layout.js";function F(t,n){return t.includes(` --canvas-home ${n} `)}s(F,"brokerCommandDeclaresCanvasHome");function H(t){return/ --epoch (\S+) /.exec(t)?.[1]??null}s(H,"brokerCommandEpoch");const rt=5e3,ae=150;async function tt(t){const n=ee();if(n===null)throw u({level:"error",event:"daemon.census.snapshot_failed",fields:{invariant:"prior-epoch brokers are reaped before readiness"}}),new Error("prior-epoch broker census could not capture the process table");const a=Ce(),m=[];for(const[i,p]of n.processes){const g=p.command;if(p.zombie||!g.includes("broker-cli.js")||!F(g,a)||H(g)===t)continue;const S=g.trim().split(/\s+/).at(-1)??"";S===""||S.endsWith("broker-cli.js")||m.push({pid:i,nodeId:S})}let f=0;const o=[];for(const i of m){const p=Er(i.pid);if(p===null||!p.includes("broker-cli.js")||!F(p,a)||H(p)===t||p.trim().split(/\s+/).at(-1)!==i.nodeId)continue;const g=re(i.pid,null);if(!g.reused){try{process.platform==="linux"&&k(R)?await P({operation:"stop",pid:i.pid}):process.kill(i.pid,"SIGTERM")}catch{continue}f++,o.push({pid:i.pid,snap:g})}}const w=Date.now()+rt;for(;Date.now()<w&&o.some(i=>te(i.snap.tree.length>0?i.snap.tree:[i.pid]));)await new Promise(i=>setTimeout(i,ae));let v=0;for(const i of o){const p=i.snap.tree.length>0?i.snap.tree:[i.pid];te(p)&&(process.platform==="linux"&&k(R)?await P({operation:"stop",pid:i.pid}):ne(p,"SIGKILL",i.snap.identities),v++)}v>0&&await new Promise(i=>setTimeout(i,ae));const d=ee();if(d===null)throw u({level:"error",event:"daemon.census.snapshot_failed",fields:{invariant:"prior-epoch brokers are reaped before readiness",stage:"final"}}),new Error("prior-epoch broker census could not capture the final process table");const l=[];for(const[i,p]of d.processes){const g=p.command;p.zombie||!g.includes("broker-cli.js")||F(g,a)&&H(g)!==t&&l.push(i)}if(l.length>0)throw new Error(`prior-epoch broker census could not prove termination of pid(s): ${l.join(", ")}`);u({level:"info",event:"daemon.census.completed",fields:{prior_epoch_brokers:m.length,sigtermed:f,sigkilled:v}})}s(tt,"reapPriorEpochBrokers");const nt=5e3;async function ot(t){const n=Array.from(t.entries());if(n.length===0)return;for(const[o]of n){const w=Fe(o)?.status;(w==="active"||w==="idle")&&Be(o,new Date().toISOString())}const a=n.map(([,o])=>({pid:o.pid,snap:re(o.pid,null),exited:o.handle.exited}));for(const o of a)if(!o.snap.reused)try{process.platform==="linux"&&k(R)?await P({operation:"stop",pid:o.pid}):process.kill(o.pid,"SIGTERM")}catch{}const m=new Promise(o=>{setTimeout(o,nt).unref()});await Promise.allSettled(a.map(o=>Promise.race([o.exited.then(()=>{}),m])));const f=[];for(const o of a)Rr(o.pid)&&(process.platform==="linux"&&k(R)?await P({operation:"stop",pid:o.pid}):ne(o.snap.tree.length>0?o.snap.tree:[o.pid],"SIGKILL",o.snap.identities),f.push(o));await Promise.all(f.map(o=>o.exited));for(const[o]of n)ur(o,{reason:"daemon-teardown"});u({level:"info",event:"daemon.fleet_teardown.completed",fields:{brokers:a.length,sigkilled:f.length}})}s(ot,"teardownFleet");function ce(){Y(Re(G()),{recursive:!0}),_e(G(),String(process.pid),"utf8")}s(ce,"writePidfile");function de(t){return typeof t=="object"&&t!==null&&t.code==="ENOENT"}s(de,"isMissingPathError");function le(t){const n=G();let a;try{a=be(n,"utf8")}catch(m){if(de(m))return;throw m}if(a.trim()!==String(t))throw new Error(`daemon readiness mirror does not name this invocation (expected pid ${t})`);try{ke(n)}catch(m){if(de(m))return;throw m}}s(le,"removeOwnedPidfileMirror");const it={acceptsDetachedWork:s(()=>!0,"acceptsDetachedWork"),registerDetached:s(t=>{t.catch(()=>{})},"registerDetached")},B=new ar,st=new cr,at=new dr,ct=new lr,dt=new pr,lt=new mr,pt=new fr,mt=new wr,ft=new gr,ut=new yr,ht=new Sr,vt=new _r,wt=new br;async function gt(t=Date.now(),n=it){const a=xr(),m=await B.runFleetPreamble(a);let f,o;try{const v=He();f=v.filter(d=>d.status==="active"||d.status==="idle"),o=v.filter(d=>d.status==="done"||d.status==="canceled"||d.status==="dead")}catch(v){u({level:"error",event:"canvas.node_list.failed",error:v});return}await B.run(t,{rows:f,fleet:a,lifecycle:n}),st.run(t,{rows:f});const w=await at.run(t,{rows:[...f,...o],fleet:a});ct.run(t),wt.run(t),dt.run(t,{lifecycle:n}),lt.run(t,{lifecycle:n}),pt.run(t,{lifecycle:n}),mt.run(t,{lifecycle:n}),ft.run(t,{lifecycle:n,fleet:a}),ut.run(t,{lifecycle:n}),Pe(),vt.run(t,{fleet:a,lifecycle:n}),await ht.run(t,{rows:f}),B.warnIfSaturated({fleet:a,lifecycle:n,thresholds:m,frozen:w})}s(gt,"superviseTick");async function yt(t){Y(Z(),{recursive:!0,mode:493}),process.platform==="linux"&&Ee(Z(),493);const n=De();if(k(n))throw new Error(`layout refusal cannot bind occupied socket: ${n}`);const a=X((d,l)=>{if(d.method==="GET"&&d.url==="/healthz"){l.writeHead(200,{"content-type":"application/json; charset=utf-8"}),l.end(JSON.stringify({ok:!1,daemon_up:!0,store_accessible:!1,brokers_reconciled:!1,startup_phase:"blocked",startup_blocked:"layout_migration_required"}));return}l.writeHead(503,{"content-type":"application/json; charset=utf-8"}),l.end(JSON.stringify({error:{code:"layout_migration_required",message:"run crtr sys migrate while the runtime is offline",type:"server_error",origin:"runtime",retryable:!1}}))});await new Promise((d,l)=>{a.once("error",l),a.listen(n,()=>{a.off("error",l),d()})});let m;const f=t.tcp??Ie();if(f){const d=/^(.*):(\d+)$/.exec(f);if(!d||Number(d[2])>65535)throw new Error(`invalid refusal TCP address: ${f}`);const l=X(a.listeners("request")[0]);await new Promise((i,p)=>{l.once("error",p),l.listen(Number(d[2]),d[1],()=>{l.off("error",p),i()})}),m=l}ce();let o;const w=s(()=>(o??=(async()=>{a.closeAllConnections(),m?.closeAllConnections(),await Promise.all([a,m].filter(d=>d!==void 0).map(d=>new Promise((l,i)=>d.close(p=>p?i(p):l())))),le(process.pid),process.off("SIGINT",v),process.off("SIGTERM",v)})(),o),"cleanup"),v=s(()=>{w().then(()=>process.exit(0),d=>{process.stderr.write(`[crtrd] layout refusal cleanup failed: ${String(d)}
|
|
2
|
+
`),process.exit(1)})},"onSignal");return process.on("SIGINT",v),process.on("SIGTERM",v),w}s(yt,"serveLayoutRefusal");async function St(t={}){if(Ge())return yt(t);Me();const n=Nr(Te(16).toString("hex"));if(!n.claimed){if(n.reason==="incumbent_alive")process.stderr.write(`[crtrd] already running (pid ${n.incumbentPid??"?"})
|
|
3
|
+
`);else{const r=[n.incumbentPid!==void 0?`pid ${n.incumbentPid}`:void 0,n.verdict!==void 0?`verdict ${n.verdict}`:void 0].filter(c=>c!==void 0),e=r.length>0?` (${r.join(", ")})`:"";process.stderr.write(`[crtrd] claim lost: ${n.reason}${e}
|
|
4
|
+
`),n.reason==="own_identity_indeterminate"&&process.stderr.write("[crtrd] cannot read its own process identity. crouter needs /proc on Linux, or the `ps` command elsewhere (Debian/Ubuntu: apt-get install procps).\n"),(n.reason==="own_identity_indeterminate"||n.reason==="incumbent_malformed")&&(process.exitCode=1)}return async()=>{}}const a=n.claim;let m=null;try{if(await tt(a.token),Xr({kind:"user",root:Zr()}),process.platform==="darwin"){const{readConfig:e,updateConfig:c}=await import("../core/config.js");if(e("user").paths?.user_files===void 0){const{homedir:y}=await import("node:os");c("user",Q=>{Q.paths??={},Q.paths.user_files??=y()})}}await Yr(et());for(const e of Oe())process.stderr.write(`[crtrd] ${e}
|
|
5
5
|
`);Mr(ie()),Or(e=>O.install(e));const r=Gr(e=>Hr(e));for(const e of r.conflicts)process.stderr.write(`[crtrd] plugin documents not reconciled: ${e.message}
|
|
6
6
|
`);for(const e of r.invalid)process.stderr.write(`[crtrd] package file is not a document: ${e.path}: ${e.error}
|
|
7
7
|
`);for(const e of r.quarantined)process.stderr.write(`[crtrd] plugin "${e.name}" has a damaged ${e.file} (${e.reason}); ${e.movedTo!==void 0?`moved to ${e.movedTo}`:"left in place and skipped"}
|
|
8
|
-
`);m=Ur(),process.platform==="linux"&&
|
|
8
|
+
`);m=Ur(),process.platform==="linux"&&k(R)&&(Ne(),await P({operation:"users.sync",users:Le()})),vr(a.token)}catch(r){se(),O.close();try{const{released:e}=oe(a);if(!e)throw new Error("daemon ownership claim was not released")}catch(e){throw new AggregateError([r,e],"daemon startup failed and cleanup also failed")}throw r}let f=!0,o,w=Promise.resolve(),v=!1,d,l;const i=new Set;let p=!1,g=!1,S,L,q=!1,$,T,D;const pe=sr();let I,h={phase:"initializing",message:"daemon startup is running the canvas import and normal services are unavailable",blockerPaths:[]},x="initial startup activation",me=null;function fe(){return h.phase==="ready"?null:{phase:h.phase,message:h.message,blockerPaths:h.blockerPaths}}s(fe,"startupBlock");function b(r){i.add(r),r.finally(()=>{i.delete(r)}).catch(()=>{})}s(b,"registerDetached");const j={acceptsDetachedWork:s(()=>f,"acceptsDetachedWork"),registerDetached:b};Br(j,ie);async function ue(){try{f=!1,Fr.close(),se(),O.close(),d!==void 0&&(clearInterval(d),d=void 0),D!==void 0&&(clearInterval(D),D=void 0);let r;do r=w,await r;while(r!==w);for(;i.size>0;)await Promise.allSettled([...i]);if(l!==void 0&&(await ot(l),l.dispose()),L!==void 0&&!q&&(q=!0,await L.close()),T!==void 0){const e=T;T=void 0,await e.close()}if($!==void 0){const e=$;$=void 0,await e.close()}if(p||(le(process.pid),p=!0),p&&!g){const{released:e}=oe(a);if(!e)throw new Error("daemon ownership claim was not released");g=!0}}finally{Tr(),process.off("SIGINT",U),process.off("SIGTERM",K),process.off("exit",J)}}s(ue,"cleanupAttempt");const A=1e3;let z=!1;function he(){return z?{graceMs:A}:(z=!0,_.fresh(()=>{u({level:"info",event:"daemon.handover.armed",fields:{pid:process.pid,grace_ms:A}})}),setTimeout(()=>{ve()},A),{graceMs:A})}s(he,"requestHandover");async function ve(){try{await E()}catch(r){const e=r instanceof Error?r.stack??r.message:String(r);process.stderr.write(`[crtrd] handover cleanup failed:
|
|
9
9
|
${e}
|
|
10
|
-
`),process.exit(1)}try{process.platform==="linux"&&
|
|
10
|
+
`),process.exit(1)}try{process.platform==="linux"&&k(R)&&(await P({operation:"daemon.handover"}),process.exit(0)),process.pid===1&&await Dr();const r=await Cr();_.fresh(()=>{u({level:"info",event:"daemon.handover.completed",fields:{predecessor_pid:process.pid,successor_pid:r.pid??r.existing_pid??null,spawned:r.started}})})}catch(r){_.fresh(()=>{u({level:"error",event:"daemon.handover.successor_failed",error:r})});const e=r instanceof Error?r.message:String(r);process.stderr.write(`[crtrd] handover successor failed to start: ${e}
|
|
11
11
|
`),process.exit(1)}process.exit(0)}s(ve,"performHandover");function E(){if(S!==void 0)return S;const r=ue();return S=r,r.then(()=>{S===r&&(S=void 0)},()=>{S===r&&(S=void 0)}),r}s(E,"requestCleanup");async function W(r){try{await E(),process.exit(0)}catch(e){process.exitCode=1;const c=e instanceof Error?e.stack??`${e.name}: ${e.message}`:String(e);process.stderr.write(`[crtrd] ${r} cleanup failed:
|
|
12
12
|
${c}
|
|
13
|
-
`),process.exit(1)}}s(W,"handleSignal");function U(){W("SIGINT")}s(U,"onSigint");function K(){W("SIGTERM")}s(K,"onSigterm");function J(){E().catch(()=>{})}s(J,"onExit");function N(r){f&&(w=w.then(r).then(()=>{},e=>{_.fresh(()=>{u({level:"error",event:"daemon.lane_job.failed",error:e})})}))}s(N,"enqueue");function V(){!f||v||(pe.check()&&I&&(u({level:"info",event:"daemon.resume.detected"}),
|
|
13
|
+
`),process.exit(1)}}s(W,"handleSignal");function U(){W("SIGINT")}s(U,"onSigint");function K(){W("SIGTERM")}s(K,"onSigterm");function J(){E().catch(()=>{})}s(J,"onExit");function N(r){f&&(w=w.then(r).then(()=>{},e=>{_.fresh(()=>{u({level:"error",event:"daemon.lane_job.failed",error:e})})}))}s(N,"enqueue");function V(){!f||v||(pe.check()&&I&&(u({level:"info",event:"daemon.resume.detected"}),b(I().catch(()=>{}))),v=!0,N(async()=>{if(v=!1,!!f)try{await gt(Date.now(),j)}catch(r){_.fresh(()=>{u({level:"error",event:"daemon.tick.failed",error:r})})}}))}s(V,"enqueueTick");let C=null;async function we(){if(C!==null)throw{status:500,code:"admission_failed",message:`daemon admission previously failed: ${C instanceof Error?C.message:String(C)}`};if(h.phase==="ready")return{admitted:!1,already_admitted:!0,startup_phase:"ready"};if(h.phase!=="prepared"&&h.phase!=="recovering")throw{status:409,code:"not_prepared",message:h.message};const r=h.phase==="prepared";try{return await M(),h={phase:"ready",message:"",blockerPaths:[]},r?{admitted:!0,already_admitted:!1,startup_phase:"ready"}:{admitted:!1,already_admitted:!0,startup_phase:"ready"}}catch(e){throw C=e,{status:500,code:"admission_failed",message:`daemon admission failed: ${e instanceof Error?e.message:String(e)}`}}}s(we,"admitStartup");async function ge(r){if(x!==null)throw{status:409,code:"migration_in_progress",message:`the canvas import is already running (${x})`};x="repair";try{const e=await Qr({dryRun:r.dryRun});if(r.dryRun||e.pending||h.phase!=="blocked")return{result:e,resumed:!1};if(t.prepare)return h={phase:"prepared",message:"daemon storage is prepared and normal services are unavailable until admission",blockerPaths:[]},{result:e,resumed:!1};try{return await M(),h={phase:"ready",message:"",blockerPaths:[]},{result:e,resumed:!0}}catch(c){const y=c instanceof Error?c.message:String(c);return setTimeout(()=>{E().catch(()=>{})},1e3),{result:e,resumed:!1,resumeError:y}}}finally{x=null}}s(ge,"repairMigrations");async function ye(){o=t.intervalMs??ir;const r=a.token;l=new zr({epoch:r,enqueue:N}),Ir(l),h={phase:"recovering",message:"daemon startup recovery is running and normal services are unavailable",blockerPaths:[]},_.fresh(()=>{u({level:"info",event:"daemon.started",fields:{pid:process.pid,interval_ms:o}})});const e=$r();if(Ar(e),_.fresh(()=>{u({level:"info",event:"daemon.install_id.resolved",fields:{install_id:e}})}),_.fresh(()=>{let c;try{c=or()}catch{return}c!==null&&u({level:"warn",event:"daemon.startup.warning",fields:{stage:"termrender",warning:c.slice(0,2048)}})}),await _.fresh(async()=>{await nr(),await er(),rr(Date.now()),tr(Date.now())}),_.fresh(()=>{const{reconcile:c,migrated:y}=Lr(hr);c.changed&&u({level:"info",event:"daemon.boot_change.reconciled",fields:{cleared_count:c.cleared.length,same_boot_proven:c.sameBootProven}}),y.length>0&&u({level:"info",event:"daemon.pid_identity.migrated",fields:{migrated_count:y.length}})}),_.fresh(()=>{kr();for(const c of Wr){const y=c.apply();y.changed&&u({level:"info",event:"daemon.boot_migration.applied",fields:{migration:c.id,...y.summary}})}}),b(Ye()),I){const c=s(()=>{b(I().catch(()=>{}))},"refresh");b(Ve().catch(()=>{})),b(Qe().then(({completion:y})=>y).catch(y=>{u({level:"error",event:"daemon.grants.sweep_failed",error:y})})),c(),D=setInterval(c,Je*1e3),D.unref()}N(()=>{jr(),qr()}),d=setInterval(V,o),V()}s(ye,"completeStartup");function M(){return me??=ye().catch(r=>{throw h={phase:"initializing",message:"daemon startup recovery failed and normal services are unavailable",blockerPaths:[]},r})}s(M,"resumeStartup");try{process.on("SIGINT",U),process.on("SIGTERM",K),process.on("exit",J),Kr(),m!==null&&u({level:"info",event:"daemon.joined_owner.applied",fields:{owner:m.owner,rows:m.rows}}),$=await xe();const r=a.token;Pr({epoch:r,requestHandover:he,registerDetached:b,startupBlock:fe,admitStartup:we,repairMigrations:ge}),ce(),L=qe({tcp:t.tcp}),await L.ready;const e=Ze("user").runtime;e?.issuer?(I=Ke(e.issuer,b),We(c=>Ue().appended(c))):ze(),e?.unsandboxed===!0&&e.listener!==void 0&&u({level:"warn",event:"daemon.app_listener.refused_unsandboxed",fields:{reason:"runtime.unsandboxed is set; runtime.listener is ignored"}}),e!==void 0&&e.listener!==void 0&&e.unsandboxed!==!0&&(T=je(e,()=>Xe(e.issuer.replace(/\/$/,"")),I),await T.ready);try{await Jr()}catch(c){if(x=null,c instanceof Vr)return h={phase:"blocked",message:c.message,blockerPaths:c.blockerPaths},E;throw c}process.platform==="linux"&&k(R)&&(Ae(),await $e("app:terminal"));try{t.prepare?h={phase:"prepared",message:"daemon storage is prepared and normal services are unavailable until admission",blockerPaths:[]}:(await M(),h={phase:"ready",message:"",blockerPaths:[]})}finally{x=null}return E}catch(r){try{await E()}catch(e){throw new AggregateError([r,e],"daemon startup failed and cleanup also failed")}throw r}}s(St,"runDaemon");var zn=St;export{F as brokerCommandDeclaresCanvasHome,H as brokerCommandEpoch,zn as default,St as runDaemon,gt as superviseTick,ot as teardownFleet};
|
package/dist/types.d.ts
CHANGED
|
@@ -388,10 +388,12 @@ export interface ScopeConfig {
|
|
|
388
388
|
runtime?: {
|
|
389
389
|
issuer: string;
|
|
390
390
|
audience: string;
|
|
391
|
-
listener
|
|
391
|
+
listener?: {
|
|
392
392
|
address: string;
|
|
393
393
|
port: number;
|
|
394
394
|
};
|
|
395
|
+
/** Set by joining as a non-default machine: no app listener; only `app:terminal` nodes run. */
|
|
396
|
+
unsandboxed?: boolean;
|
|
395
397
|
jwksUrl?: string;
|
|
396
398
|
person_uids?: number[];
|
|
397
399
|
/** Hosting file storage: `service_url` is the storage token audience and API
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@north-light/cli",
|
|
3
|
-
"version": "0.3.
|
|
3
|
+
"version": "0.3.422",
|
|
4
4
|
"description": "crtr — agent runtime with memory, plugins, and marketplaces",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "dist/index.js",
|
|
@@ -134,7 +134,7 @@
|
|
|
134
134
|
},
|
|
135
135
|
"license": "UNLICENSED",
|
|
136
136
|
"dependencies": {
|
|
137
|
-
"@north-light/identity": "0.3.
|
|
137
|
+
"@north-light/identity": "0.3.422",
|
|
138
138
|
"@earendil-works/pi-agent-core": "1.1.0",
|
|
139
139
|
"@earendil-works/pi-ai": "1.1.0",
|
|
140
140
|
"@earendil-works/pi-coding-agent": "1.1.0",
|
package/runtime.lock.json
CHANGED
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@north-light/cli",
|
|
3
|
-
"version": "0.3.
|
|
3
|
+
"version": "0.3.422",
|
|
4
4
|
"lockfileVersion": 3,
|
|
5
5
|
"requires": true,
|
|
6
6
|
"packages": {
|
|
7
7
|
"": {
|
|
8
8
|
"name": "@north-light/cli",
|
|
9
|
-
"version": "0.3.
|
|
9
|
+
"version": "0.3.422",
|
|
10
10
|
"hasInstallScript": true,
|
|
11
11
|
"license": "UNLICENSED",
|
|
12
12
|
"workspaces": [
|
|
@@ -18,7 +18,7 @@
|
|
|
18
18
|
"@earendil-works/pi-ai": "1.1.0",
|
|
19
19
|
"@earendil-works/pi-coding-agent": "1.1.0",
|
|
20
20
|
"@earendil-works/pi-tui": "1.1.0",
|
|
21
|
-
"@north-light/identity": "0.3.
|
|
21
|
+
"@north-light/identity": "0.3.422",
|
|
22
22
|
"cron-parser": "^5.6.0",
|
|
23
23
|
"esbuild": "^0.27.7",
|
|
24
24
|
"jose": "^6.2.12",
|
|
@@ -12095,17 +12095,17 @@
|
|
|
12095
12095
|
},
|
|
12096
12096
|
"packages/crouter-api": {
|
|
12097
12097
|
"name": "@north-light/api",
|
|
12098
|
-
"version": "0.3.
|
|
12098
|
+
"version": "0.3.422",
|
|
12099
12099
|
"license": "UNLICENSED"
|
|
12100
12100
|
},
|
|
12101
12101
|
"packages/crouter-env-docker": {
|
|
12102
12102
|
"name": "@north-light/env-docker",
|
|
12103
|
-
"version": "0.3.
|
|
12103
|
+
"version": "0.3.422",
|
|
12104
12104
|
"license": "UNLICENSED"
|
|
12105
12105
|
},
|
|
12106
12106
|
"packages/crouter-identity": {
|
|
12107
12107
|
"name": "@north-light/identity",
|
|
12108
|
-
"version": "0.3.
|
|
12108
|
+
"version": "0.3.422",
|
|
12109
12109
|
"license": "UNLICENSED",
|
|
12110
12110
|
"dependencies": {
|
|
12111
12111
|
"jose": "^6.2.1"
|
|
@@ -12113,20 +12113,20 @@
|
|
|
12113
12113
|
},
|
|
12114
12114
|
"packages/crouter-plugin": {
|
|
12115
12115
|
"name": "@north-light/plugin",
|
|
12116
|
-
"version": "0.3.
|
|
12116
|
+
"version": "0.3.422",
|
|
12117
12117
|
"license": "UNLICENSED",
|
|
12118
12118
|
"dependencies": {
|
|
12119
|
-
"@north-light/api": "0.3.
|
|
12120
|
-
"@north-light/identity": "0.3.
|
|
12119
|
+
"@north-light/api": "0.3.422",
|
|
12120
|
+
"@north-light/identity": "0.3.422"
|
|
12121
12121
|
}
|
|
12122
12122
|
},
|
|
12123
12123
|
"packages/crouter-sdk": {
|
|
12124
12124
|
"name": "@north-light/sdk",
|
|
12125
|
-
"version": "0.3.
|
|
12125
|
+
"version": "0.3.422",
|
|
12126
12126
|
"license": "UNLICENSED",
|
|
12127
12127
|
"dependencies": {
|
|
12128
|
-
"@north-light/api": "0.3.
|
|
12129
|
-
"@north-light/identity": "0.3.
|
|
12128
|
+
"@north-light/api": "0.3.422",
|
|
12129
|
+
"@north-light/identity": "0.3.422",
|
|
12130
12130
|
"jose": "^6.2.1"
|
|
12131
12131
|
},
|
|
12132
12132
|
"bin": {
|