@north-light/cli 0.3.440 → 0.3.442

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,2 +1,2 @@
1
- var T=Object.defineProperty;var n=(e,o)=>T(e,"name",{value:o,configurable:!0});import{DatabaseSync as p}from"node:sqlite";import{forgetPrepared as R}from"../sqlite-statements.js";import{chmodSync as m,existsSync as s,mkdirSync as y,readdirSync as O,rmSync as I,statSync as P,writeFileSync as v}from"node:fs";import{join as i}from"node:path";import j from"proper-lockfile";import{CONFIG_FILE as S,PROFILE_DIR as N,STATE_FILE as f}from"../../types.js";import{withExclusiveDirectoryLock as _}from"../exclusive-lock.js";import{layoutNeedsMigration as k}from"../layout.js";import{providerStore as C,projectStore as D,userStore as G}from"./paths.js";import{createScopedSchema as g,ensureProviderModelCooldowns as $,PROVIDER_SCHEMA_VERSION as w,SCOPED_SCHEMA_VERSION as d}from"./schema.js";const l=new Map,B=/^[a-z0-9]+(?:-[a-z0-9]+)*-[0-9a-f]{8}$/;function F(e,o,r){e.prepare("UPDATE scope_owners SET root=? WHERE owner_key=?").run(r,o)}n(F,"writeOwnerRoot");function c(e){return Number(e.prepare("PRAGMA user_version").get().user_version)}n(c,"version");function L(e,o){const r=c(e);if(r===0)throw new Error(`scoped SQL store is uninitialized: ${o.path}; crtr was updated and \`crtr sys daemon restart\` converts local state`);const t=o.kind==="provider"?w:d;if(r>t)throw new Error(`scoped SQL store ${o.path} uses unsupported schema version ${r}`);if(r!==t)throw new Error(`scoped SQL store ${o.path} requires an explicit conversion`)}n(L,"assertVersion");function x(e,o){if(o.kind==="provider"){c(e)===w&&(e.exec("PRAGMA busy_timeout = 5000"),$(e));return}if(!(c(e)>=d)){e.exec("PRAGMA busy_timeout = 5000; BEGIN IMMEDIATE");try{c(e)===1&&(e.prepare("PRAGMA table_info(profiles)").all().some(({name:t})=>t==="grantee")||e.exec("ALTER TABLE profiles ADD COLUMN grantee TEXT"),e.exec("PRAGMA user_version = 2")),c(e)===2&&(e.prepare("PRAGMA table_info(profiles)").all().some(({name:t})=>t==="home")&&e.exec("ALTER TABLE profiles DROP COLUMN home"),e.exec("PRAGMA user_version = 3")),c(e)===3&&(e.exec("ALTER TABLE profiles ADD COLUMN delivery_limits_json TEXT NOT NULL DEFAULT '{}' CHECK(json_valid(delivery_limits_json))"),e.exec("PRAGMA user_version = 4")),c(e)===4&&(e.exec("CREATE TABLE IF NOT EXISTS legacy_project_caps (profile_id TEXT NOT NULL, path TEXT NOT NULL, memory TEXT NOT NULL CHECK(memory IN ('none','name','preview')), PRIMARY KEY(profile_id,path))"),e.prepare("PRAGMA table_info(profile_projects)").all().some(({name:t})=>t==="memory")&&e.exec(`INSERT INTO legacy_project_caps SELECT profile_id, path, memory FROM profile_projects WHERE memory != 'content';
2
- ALTER TABLE profile_projects DROP COLUMN memory;`),e.exec(`PRAGMA user_version = ${d}`)),e.exec("COMMIT")}catch(r){throw e.exec("ROLLBACK"),r}}}n(x,"upgradeScopedStore");function ne(e){const o=new p(e.path);try{x(o,e),L(o,e)}finally{o.close()}}n(ne,"assertScopedStoreReady");function U(e){if(!M(e))return;const o=new p(e.path,{readOnly:!0});let r;try{r=c(o)}finally{o.close()}if(r===0)for(const t of[e.path,`${e.path}-wal`,`${e.path}-shm`])I(t,{force:!0})}n(U,"discardIncompleteScopedStore");function H(e,o){return _(i(e,".init.lock"),()=>{const r=i(e,f),t=Date.now()+5e3;let a=10;for(;;){let E;try{E=j.lockSync(r,{realpath:!1,retries:0,stale:3e4,update:1e4})}catch(u){if(u.code!=="ELOCKED")throw u;const A=t-Date.now();if(A<=0)throw new Error(`timed out waiting for project state conversion lock: ${r}`,{cause:u});Atomics.wait(new Int32Array(new SharedArrayBuffer(4)),0,0,Math.min(a,A)),a=Math.min(a*2,250);continue}try{return o()}finally{E()}}})}n(H,"withProjectStateLock");function h(e){s(e)&&m(e,384);for(const o of["-wal","-shm"])s(`${e}${o}`)&&m(`${e}${o}`,384)}n(h,"secure");function M(e){return s(e.path)}n(M,"scopedStoreExists");function K(e){if(e.kind==="project")return[i(e.root,f)];if(e.kind==="provider")return[i(e.root,"anthropic-subscriptions.json"),i(e.root,"openai-codex-subscriptions.json"),i(e.root,"provider-rotation.json")];const o=[i(e.root,S),i(e.root,f),i(e.root,"profile-defaults.json")],r=i(e.root,N);if(s(r))for(const t of O(r,{withFileTypes:!0}))t.isDirectory()&&B.test(t.name)&&o.push(i(r,t.name,"profile.json"),i(r,t.name,S),i(r,t.name,f));return o}n(K,"legacyScopedStorePaths");function X(e){const o=e.kind==="user"?G(e.root):e.kind==="project"?D(e.root):C(e.root);o.kind!=="project"&&y(o.root,{recursive:!0,mode:448});const r=n(()=>{if(o.kind==="project"&&U(o),M(o))return;const t=K(o).find(s);if(t!==void 0)throw new Error(`legacy scoped state exists at ${t}; crtr was updated and \`crtr sys daemon restart\` converts local state`);Q(o,a=>{g(a,o.kind),o.kind!=="provider"&&F(a,o.kind,o.root)})},"initialize");o.kind==="project"?H(o.root,r):_(i(o.root,".init.lock"),r)}n(X,"initializeFreshScopedStore");function z(e){if(k())throw new Error("layout_migration_required");const o=l.get(e.path);if(o!==void 0)return o;X(e);const r=new p(e.path);try{return r.exec("PRAGMA busy_timeout = 5000; PRAGMA journal_mode = WAL; PRAGMA foreign_keys = ON;"),x(r,e),L(r,e),h(e.path),l.set(e.path,r),r}catch(t){throw r.close(),t}}n(z,"openScopedStore");function Q(e,o){if(s(e.path))throw new Error(`scoped SQL store already exists: ${e.path}`);if(e.kind!=="project"&&y(e.root,{recursive:!0,mode:448}),!P(e.root).isDirectory())throw new Error(`scoped SQL root is not a directory: ${e.root}`);(e.kind!=="project"||process.platform!=="linux")&&m(e.root,448),v(e.path,"",{mode:384});const r=new p(e.path);try{r.exec("PRAGMA busy_timeout = 5000; PRAGMA journal_mode = WAL; PRAGMA foreign_keys = ON; BEGIN IMMEDIATE;"),o(r),r.exec("COMMIT")}catch(t){try{r.exec("ROLLBACK")}catch{}throw t}finally{h(e.path),r.close()}}n(Q,"createScopedStore");function ie(e,o){const r=z(e);if(r.isTransaction)return o(r);r.exec("BEGIN IMMEDIATE");try{const t=o(r);return r.exec("COMMIT"),h(e.path),t}catch(t){try{r.exec("ROLLBACK")}catch{}throw t}}n(ie,"withScopedWrite");function ce(){for(const e of l.values())R(e),e.close();l.clear()}n(ce,"closeScopedStores");export{B as PROFILE_ID_SHAPE,ne as assertScopedStoreReady,ce as closeScopedStores,Q as createScopedStore,U as discardIncompleteScopedStore,X as initializeFreshScopedStore,K as legacyScopedStorePaths,z as openScopedStore,M as scopedStoreExists,H as withProjectStateLock,ie as withScopedWrite,F as writeOwnerRoot};
1
+ var T=Object.defineProperty;var n=(e,o)=>T(e,"name",{value:o,configurable:!0});import{DatabaseSync as p}from"node:sqlite";import{forgetPrepared as R}from"../sqlite-statements.js";import{chmodSync as m,existsSync as s,mkdirSync as y,readdirSync as O,rmSync as I,statSync as P,writeFileSync as v}from"node:fs";import{join as i}from"node:path";import j from"proper-lockfile";import{CONFIG_FILE as S,PROFILE_DIR as N,STATE_FILE as f}from"../../types.js";import{withExclusiveDirectoryLock as _}from"../exclusive-lock.js";import{syncDirectory as k,syncFile as D}from"../fs-utils.js";import{layoutNeedsMigration as C}from"../layout.js";import{providerStore as G,projectStore as g,userStore as $}from"./paths.js";import{createScopedSchema as B,ensureProviderModelCooldowns as F,PROVIDER_SCHEMA_VERSION as w,SCOPED_SCHEMA_VERSION as d}from"./schema.js";const l=new Map,U=/^[a-z0-9]+(?:-[a-z0-9]+)*-[0-9a-f]{8}$/;function H(e,o,r){e.prepare("UPDATE scope_owners SET root=? WHERE owner_key=?").run(r,o)}n(H,"writeOwnerRoot");function c(e){return Number(e.prepare("PRAGMA user_version").get().user_version)}n(c,"version");function L(e,o){const r=c(e);if(r===0)throw new Error(`scoped SQL store is uninitialized: ${o.path}; crtr was updated and \`crtr sys daemon restart\` converts local state`);const t=o.kind==="provider"?w:d;if(r>t)throw new Error(`scoped SQL store ${o.path} uses unsupported schema version ${r}`);if(r!==t)throw new Error(`scoped SQL store ${o.path} requires an explicit conversion`)}n(L,"assertVersion");function x(e,o){if(o.kind==="provider"){c(e)===w&&(e.exec("PRAGMA busy_timeout = 5000"),F(e));return}if(!(c(e)>=d)){e.exec("PRAGMA busy_timeout = 5000; BEGIN IMMEDIATE");try{c(e)===1&&(e.prepare("PRAGMA table_info(profiles)").all().some(({name:t})=>t==="grantee")||e.exec("ALTER TABLE profiles ADD COLUMN grantee TEXT"),e.exec("PRAGMA user_version = 2")),c(e)===2&&(e.prepare("PRAGMA table_info(profiles)").all().some(({name:t})=>t==="home")&&e.exec("ALTER TABLE profiles DROP COLUMN home"),e.exec("PRAGMA user_version = 3")),c(e)===3&&(e.exec("ALTER TABLE profiles ADD COLUMN delivery_limits_json TEXT NOT NULL DEFAULT '{}' CHECK(json_valid(delivery_limits_json))"),e.exec("PRAGMA user_version = 4")),c(e)===4&&(e.exec("CREATE TABLE IF NOT EXISTS legacy_project_caps (profile_id TEXT NOT NULL, path TEXT NOT NULL, memory TEXT NOT NULL CHECK(memory IN ('none','name','preview')), PRIMARY KEY(profile_id,path))"),e.prepare("PRAGMA table_info(profile_projects)").all().some(({name:t})=>t==="memory")&&e.exec(`INSERT INTO legacy_project_caps SELECT profile_id, path, memory FROM profile_projects WHERE memory != 'content';
2
+ ALTER TABLE profile_projects DROP COLUMN memory;`),e.exec(`PRAGMA user_version = ${d}`)),e.exec("COMMIT")}catch(r){throw e.exec("ROLLBACK"),r}}}n(x,"upgradeScopedStore");function ae(e){const o=new p(e.path);try{x(o,e),L(o,e)}finally{o.close()}}n(ae,"assertScopedStoreReady");function K(e){if(!M(e))return;const o=new p(e.path,{readOnly:!0});let r;try{r=c(o)}finally{o.close()}if(r===0)for(const t of[e.path,`${e.path}-wal`,`${e.path}-shm`])I(t,{force:!0})}n(K,"discardIncompleteScopedStore");function X(e,o){return _(i(e,".init.lock"),()=>{const r=i(e,f),t=Date.now()+5e3;let a=10;for(;;){let E;try{E=j.lockSync(r,{realpath:!1,retries:0,stale:3e4,update:1e4})}catch(u){if(u.code!=="ELOCKED")throw u;const A=t-Date.now();if(A<=0)throw new Error(`timed out waiting for project state conversion lock: ${r}`,{cause:u});Atomics.wait(new Int32Array(new SharedArrayBuffer(4)),0,0,Math.min(a,A)),a=Math.min(a*2,250);continue}try{return o()}finally{E()}}})}n(X,"withProjectStateLock");function h(e){s(e)&&m(e,384);for(const o of["-wal","-shm"])s(`${e}${o}`)&&m(`${e}${o}`,384)}n(h,"secure");function M(e){return s(e.path)}n(M,"scopedStoreExists");function z(e){if(e.kind==="project")return[i(e.root,f)];if(e.kind==="provider")return[i(e.root,"anthropic-subscriptions.json"),i(e.root,"openai-codex-subscriptions.json"),i(e.root,"provider-rotation.json")];const o=[i(e.root,S),i(e.root,f),i(e.root,"profile-defaults.json")],r=i(e.root,N);if(s(r))for(const t of O(r,{withFileTypes:!0}))t.isDirectory()&&U.test(t.name)&&o.push(i(r,t.name,"profile.json"),i(r,t.name,S),i(r,t.name,f));return o}n(z,"legacyScopedStorePaths");function Q(e){const o=e.kind==="user"?$(e.root):e.kind==="project"?g(e.root):G(e.root);o.kind!=="project"&&y(o.root,{recursive:!0,mode:448});const r=n(()=>{if(o.kind==="project"&&K(o),M(o))return;const t=z(o).find(s);if(t!==void 0)throw new Error(`legacy scoped state exists at ${t}; crtr was updated and \`crtr sys daemon restart\` converts local state`);V(o,a=>{B(a,o.kind),o.kind!=="provider"&&H(a,o.kind,o.root)})},"initialize");o.kind==="project"?X(o.root,r):_(i(o.root,".init.lock"),r)}n(Q,"initializeFreshScopedStore");function W(e){if(C())throw new Error("layout_migration_required");const o=l.get(e.path);if(o!==void 0)return o;Q(e);const r=new p(e.path);try{return r.exec("PRAGMA busy_timeout = 5000; PRAGMA journal_mode = WAL; PRAGMA foreign_keys = ON;"),x(r,e),L(r,e),h(e.path),l.set(e.path,r),r}catch(t){throw r.close(),t}}n(W,"openScopedStore");function V(e,o){if(s(e.path))throw new Error(`scoped SQL store already exists: ${e.path}`);if(e.kind!=="project"&&y(e.root,{recursive:!0,mode:448}),!P(e.root).isDirectory())throw new Error(`scoped SQL root is not a directory: ${e.root}`);(e.kind!=="project"||process.platform!=="linux")&&m(e.root,448),v(e.path,"",{mode:384});const r=new p(e.path);try{r.exec("PRAGMA busy_timeout = 5000; PRAGMA journal_mode = WAL; PRAGMA foreign_keys = ON; BEGIN IMMEDIATE;"),o(r),r.exec("COMMIT")}catch(t){try{r.exec("ROLLBACK")}catch{}throw t}finally{h(e.path),r.close()}D(e.path),k(e.root)}n(V,"createScopedStore");function se(e,o){const r=W(e);if(r.isTransaction)return o(r);r.exec("BEGIN IMMEDIATE");try{const t=o(r);return r.exec("COMMIT"),h(e.path),t}catch(t){try{r.exec("ROLLBACK")}catch{}throw t}}n(se,"withScopedWrite");function pe(){for(const e of l.values())R(e),e.close();l.clear()}n(pe,"closeScopedStores");export{U as PROFILE_ID_SHAPE,ae as assertScopedStoreReady,pe as closeScopedStores,V as createScopedStore,K as discardIncompleteScopedStore,Q as initializeFreshScopedStore,z as legacyScopedStorePaths,W as openScopedStore,M as scopedStoreExists,X as withProjectStateLock,se as withScopedWrite,H as writeOwnerRoot};
@@ -21,10 +21,9 @@ export interface ScopedApiToken {
21
21
  created: string;
22
22
  }
23
23
  export declare function readSecrets(scope: Scope): SecretsStore;
24
- /** Writes secrets.json directly (never via `fs-utils.writeJson`, which has no
25
- * mode control) so the file is created 0600 from the first byte, then
26
- * `chmodSync`s belt-and-suspenders in case the file pre-existed with looser
27
- * permissions (e.g. hand-copied from another machine). */
24
+ /** Replaces secrets.json whole (temp file, fsync, rename, directory fsync) at mode 0600 -- forced even
25
+ * over a pre-existing looser file, e.g. one hand-copied from another machine -- so a killed VM or a
26
+ * volume handoff never leaves the relay tokens empty or partial. */
28
27
  export declare function writeSecrets(scope: Scope, store: SecretsStore): void;
29
28
  export declare function getRelayToken(ref: string, scope: Scope): string | undefined;
30
29
  export declare function setRelayToken(ref: string, token: string, scope: Scope): void;
@@ -1,2 +1 @@
1
- var f=Object.defineProperty;var t=(e,o)=>f(e,"name",{value:o,configurable:!0});import{createHash as u}from"node:crypto";import{existsSync as y,readFileSync as d,writeFileSync as l,chmodSync as A}from"node:fs";import{join as m}from"node:path";import{scopeRoot as S,requireScopeRoot as g,userScopeRoot as a}from"./scope.js";import{secretsDir as k}from"./layout.js";import{ensureDir as x}from"./fs-utils.js";const h="secrets.json";function T(e){return m(e===a()?k():e,h)}t(T,"secretsPathFor");function s(e){const o=S(e);if(!o)return{relayTokens:{}};const n=T(o);if(!y(n))return{relayTokens:{}};try{const r=JSON.parse(d(n,"utf8")),c=Array.isArray(r.scopedApiTokens)?r.scopedApiTokens.filter(i=>typeof i?.token=="string"&&i.token!==""&&typeof i.grantee=="string"&&/^app:[a-zA-Z0-9][a-zA-Z0-9._-]*$/.test(i.grantee)&&Array.isArray(i.scopes)&&typeof i.created=="string"):[];return{relayTokens:r.relayTokens??{},...typeof r.apiToken=="string"&&r.apiToken!==""?{apiToken:r.apiToken}:{},...c.length>0?{scopedApiTokens:c}:{}}}catch{return{relayTokens:{}}}}t(s,"readSecrets");function p(e,o){const n=g(e),r=T(n);x(n===a()?k():n),l(r,JSON.stringify(o,null,2)+`
2
- `,{mode:384}),A(r,384)}t(p,"writeSecrets");function J(e,o){return s(o).relayTokens[e]}t(J,"getRelayToken");function N(e,o,n){const r=s(n);r.relayTokens[e]=o,p(n,r)}t(N,"setRelayToken");function O(e,o){const n=s(o);delete n.relayTokens[e],p(o,n)}t(O,"deleteRelayToken");function Z(e){return s(e).apiToken}t(Z,"getApiToken");function _(e,o){const n=s(o);n.apiToken=e,p(o,n)}t(_,"setApiToken");function q(e){return s(e).scopedApiTokens??[]}t(q,"listScopedApiTokens");function C(e,o){const n=s(o);n.scopedApiTokens=[...n.scopedApiTokens??[],e],p(o,n)}t(C,"addScopedApiToken");function H(e){return u("sha256").update(e).digest("hex").slice(0,12)}t(H,"fingerprint");export{C as addScopedApiToken,O as deleteRelayToken,H as fingerprint,Z as getApiToken,J as getRelayToken,q as listScopedApiTokens,s as readSecrets,_ as setApiToken,N as setRelayToken,p as writeSecrets};
1
+ var u=Object.defineProperty;var t=(e,o)=>u(e,"name",{value:o,configurable:!0});import{createHash as f}from"node:crypto";import{existsSync as y,readFileSync as d}from"node:fs";import{join as l}from"node:path";import{scopeRoot as A,requireScopeRoot as m,userScopeRoot as a}from"./scope.js";import{secretsDir as k}from"./layout.js";import{atomicWriteJson as x,ensureDir as g}from"./fs-utils.js";const S="secrets.json";function T(e){return l(e===a()?k():e,S)}t(T,"secretsPathFor");function s(e){const o=A(e);if(!o)return{relayTokens:{}};const r=T(o);if(!y(r))return{relayTokens:{}};try{const n=JSON.parse(d(r,"utf8")),c=Array.isArray(n.scopedApiTokens)?n.scopedApiTokens.filter(i=>typeof i?.token=="string"&&i.token!==""&&typeof i.grantee=="string"&&/^app:[a-zA-Z0-9][a-zA-Z0-9._-]*$/.test(i.grantee)&&Array.isArray(i.scopes)&&typeof i.created=="string"):[];return{relayTokens:n.relayTokens??{},...typeof n.apiToken=="string"&&n.apiToken!==""?{apiToken:n.apiToken}:{},...c.length>0?{scopedApiTokens:c}:{}}}catch{return{relayTokens:{}}}}t(s,"readSecrets");function p(e,o){const r=m(e),n=T(r);g(r===a()?k():r),x(n,o,{mode:384,durable:!0})}t(p,"writeSecrets");function J(e,o){return s(o).relayTokens[e]}t(J,"getRelayToken");function Z(e,o,r){const n=s(r);n.relayTokens[e]=o,p(r,n)}t(Z,"setRelayToken");function _(e,o){const r=s(o);delete r.relayTokens[e],p(o,r)}t(_,"deleteRelayToken");function b(e){return s(e).apiToken}t(b,"getApiToken");function q(e,o){const r=s(o);r.apiToken=e,p(o,r)}t(q,"setApiToken");function w(e){return s(e).scopedApiTokens??[]}t(w,"listScopedApiTokens");function C(e,o){const r=s(o);r.scopedApiTokens=[...r.scopedApiTokens??[],e],p(o,r)}t(C,"addScopedApiToken");function H(e){return f("sha256").update(e).digest("hex").slice(0,12)}t(H,"fingerprint");export{C as addScopedApiToken,_ as deleteRelayToken,H as fingerprint,b as getApiToken,J as getRelayToken,w as listScopedApiTokens,s as readSecrets,q as setApiToken,Z as setRelayToken,p as writeSecrets};
@@ -1 +1 @@
1
- var v=Object.defineProperty;var f=(r,i)=>v(r,"name",{value:i,configurable:!0});import{covers as h,parseScope as F}from"@north-light/identity";import{activeGrant as S,grantFor as j}from"../grants/mirror.js";import{appSpace as d,userFilesRoot as A}from"../layout.js";import{contains as y}from"./file-root.js";import{join as E,resolve as u}from"node:path";import{lstatSync as z,realpathSync as $}from"node:fs";function g(r,i,o,e){return R(r,i,o?S(o):j(r,i),e)}f(g,"permissionsForRun");function R(r,i,o,e){if(!o||o.grantee!==r||o.sub!==i)throw new Error(`no active grant for ${r}`);if(e!==null&&!Array.isArray(e))throw new Error("invalid launched scopes");const t=[],s=[];let c=e===null;const a=e??o.resolved;for(const n of a){if(typeof n!="string")throw new Error("invalid launched scope");F(n);const x=n===`crtr:memory:read:${r}`||n===`crtr:memory:rw:${r}`||n.startsWith(`crtr:memory:read:${r}:`)||n.startsWith(`crtr:memory:rw:${r}:`);if(e!==null&&!x&&!o.resolved.some(m=>h(m,n)))throw new Error(`launched scope not in grant: ${n}`);const p=/^crtr:files:(read|rw):(user|app:[A-Za-z0-9_-]{1,64}):(.+)$/.exec(n);if(p){const[,m,w,b]=p;if(w===r)throw new Error(`own-app files cannot narrow a run: ${n}`);t.push({holder:w,path:b,writable:m==="rw"})}const l=/^crtr:objects:read:(app:[A-Za-z0-9_-]{1,64})$/.exec(n);l&&l[1]!==r&&s.push(l[1])}return{app:r,ownNodes:c,otherFiles:t,otherNodes:s}}f(R,"permissionsForGrant");function Z(r,i){const o=u(r);for(const e of i){const t=u(e);if(y(t,o))try{if($(o)!==o||$(t)!==t)continue;let s=o;for(;y(t,s)&&!z(s).isSymbolicLink();){if(s===t)return!0;s=u(s,"..")}}catch{}}return!1}f(Z,"readableProject");function q(r,i,o,e){const t=[d(i).files];for(const s of e??o){if(e!==null&&!o.some(a=>h(a,s)))continue;const c=/^crtr:files:(?:read|rw):(user|app:[A-Za-z0-9_-]{1,64}):(.+)$/.exec(s);c&&t.push(E(c[1]==="user"?A():d(c[1]).files,c[2]==="."?"":c[2]))}return Z(r,t)}f(q,"readableProjectForScopes");import{fileRoot as D}from"./file-root.js";export{D as fileRoot,R as permissionsForGrant,g as permissionsForRun,Z as readableProject,q as readableProjectForScopes};
1
+ var v=Object.defineProperty;var f=(r,i)=>v(r,"name",{value:i,configurable:!0});import{parseScope as A}from"@north-light/identity";import{coveredByAny as u}from"../../shared/env.js";import{activeGrant as F,grantFor as S}from"../grants/mirror.js";import{appSpace as w,userFilesRoot as j}from"../layout.js";import{contains as h}from"./file-root.js";import{join as E,resolve as l}from"node:path";import{lstatSync as z,realpathSync as y}from"node:fs";function g(r,i,o,e){return R(r,i,o?F(o):S(r,i),e)}f(g,"permissionsForRun");function R(r,i,o,e){if(!o||o.grantee!==r||o.sub!==i)throw new Error(`no active grant for ${r}`);if(e!==null&&!Array.isArray(e))throw new Error("invalid launched scopes");const t=[],n=[];let c=e===null;const d=e??o.resolved;for(const s of d){if(typeof s!="string")throw new Error("invalid launched scope");A(s);const $=s===`crtr:memory:read:${r}`||s===`crtr:memory:rw:${r}`||s.startsWith(`crtr:memory:read:${r}:`)||s.startsWith(`crtr:memory:rw:${r}:`);if(e!==null&&!$&&!u(o.resolved,s))throw new Error(`launched scope not in grant: ${s}`);const m=/^crtr:files:(read|rw):(user|app:[A-Za-z0-9_-]{1,64}):(.+)$/.exec(s);if(m){const[,x,p,b]=m;if(p===r)throw new Error(`own-app files cannot narrow a run: ${s}`);t.push({holder:p,path:b,writable:x==="rw"})}const a=/^crtr:objects:read:(app:[A-Za-z0-9_-]{1,64})$/.exec(s);a&&a[1]!==r&&n.push(a[1])}return{app:r,ownNodes:c,otherFiles:t,otherNodes:n}}f(R,"permissionsForGrant");function Z(r,i){const o=l(r);for(const e of i){const t=l(e);if(h(t,o))try{if(y(o)!==o||y(t)!==t)continue;let n=o;for(;h(t,n)&&!z(n).isSymbolicLink();){if(n===t)return!0;n=l(n,"..")}}catch{}}return!1}f(Z,"readableProject");function q(r,i,o,e){const t=[w(i).files];for(const n of e??o){if(e!==null&&!u(o,n))continue;const c=/^crtr:files:(?:read|rw):(user|app:[A-Za-z0-9_-]{1,64}):(.+)$/.exec(n);c&&t.push(E(c[1]==="user"?j():w(c[1]).files,c[2]==="."?"":c[2]))}return Z(r,t)}f(q,"readableProjectForScopes");import{fileRoot as H}from"./file-root.js";export{H as fileRoot,R as permissionsForGrant,g as permissionsForRun,Z as readableProject,q as readableProjectForScopes};
@@ -1,4 +1,6 @@
1
1
  import { type LauncherReply, type LauncherRequest, type LimitEvent } from './spec.js';
2
+ /** The most one launcher packet carries (`send_fds` in src/native/linux/addon.c). */
3
+ export declare const LAUNCHER_PACKET_MAX_BYTES = 65535;
2
4
  /** The daemon registers where launcher diagnostics (limit applications, OOM kills, skipped limits) become canonical events. */
3
5
  export declare function setLauncherEventSink(sink: ((events: LimitEvent[]) => void) | undefined): void;
4
6
  export declare function launcherRequest(request: LauncherRequest, fds?: number[], path?: string): Promise<LauncherReply>;
@@ -1,3 +1,3 @@
1
- var w=Object.defineProperty;var s=(o,a)=>w(o,"name",{value:a,configurable:!0});import{connect as p}from"node:net";import{loadLinuxNative as v}from"../native/linux.js";import{LAUNCHER_SOCKET as m,LaunchRefused as y}from"./spec.js";const u=v();let d;function k(o){d=o}s(k,"setLauncherEventSink");async function N(o,a=[],f=m){if(!u)throw new Error("Linux launcher client requires the native addon");const e=p(f);try{await new Promise((r,t)=>{e.once("connect",r),e.once("error",t)});const c=e._handle?.fd;if(c===void 0||c<0)throw new Error("launcher socket fd unavailable");u.sendFds(c,JSON.stringify(o),a);const l=await new Promise((r,t)=>{let i="";e.on("data",h=>{i+=h.toString(),i.includes(`
2
- `)&&r(i.slice(0,i.indexOf(`
3
- `)))}),e.once("end",()=>t(new Error("launcher disconnected without reply"))),e.once("error",t)}),n=JSON.parse(l);if("refusal"in n)throw new y(n.refusal,`launcher refused ${n.refusal}`);if("events"in n&&n.events!==void 0){const{events:r,...t}=n;if(r.length>0)try{d?.(r)}catch{}return t}return n}finally{e.destroy()}}s(N,"launcherRequest");export{N as launcherRequest,k as setLauncherEventSink};
1
+ var y=Object.defineProperty;var u=(o,s)=>y(o,"name",{value:s,configurable:!0});import{connect as m}from"node:net";import{loadLinuxNative as E}from"../native/linux.js";import{LAUNCHER_SOCKET as L,LaunchRefused as l}from"./spec.js";const f=E(),d=65535;let h;function x(o){h=o}u(x,"setLauncherEventSink");async function b(o,s=[],p=L){if(!f)throw new Error("Linux launcher client requires the native addon");const e=m(p);try{await new Promise((t,r)=>{e.once("connect",t),e.once("error",r)});const a=e._handle?.fd;if(a===void 0||a<0)throw new Error("launcher socket fd unavailable");const c=JSON.stringify(o);if(Buffer.byteLength(c)>d)throw new l("invalid_spec",`launcher request is ${Buffer.byteLength(c)} bytes, over the ${d}-byte packet limit; large values (such as a run's scope list) must travel in a file, not the launch environment`);f.sendFds(a,c,s);const v=await new Promise((t,r)=>{let i="";e.on("data",w=>{i+=w.toString(),i.includes(`
2
+ `)&&t(i.slice(0,i.indexOf(`
3
+ `)))}),e.once("end",()=>r(new Error("launcher disconnected without reply"))),e.once("error",r)}),n=JSON.parse(v);if("refusal"in n)throw new l(n.refusal,`launcher refused ${n.refusal}`);if("events"in n&&n.events!==void 0){const{events:t,...r}=n;if(t.length>0)try{h?.(t)}catch{}return r}return n}finally{e.destroy()}}u(b,"launcherRequest");export{d as LAUNCHER_PACKET_MAX_BYTES,b as launcherRequest,x as setLauncherEventSink};
@@ -1,9 +1,9 @@
1
- var f=Object.defineProperty;var c=(t,o)=>f(t,"name",{value:o,configurable:!0});import{envNodeId as d}from"../shared/env.js";import{execFile as l}from"node:child_process";import{createHash as m}from"node:crypto";import{mkdirSync as p,readFileSync as h,writeFileSync as x}from"node:fs";import{homedir as y}from"node:os";import{dirname as g,join as S}from"node:path";import{promisify as $}from"node:util";const _=$(l),s=15e3,O=`
1
+ var f=Object.defineProperty;var c=(t,o)=>f(t,"name",{value:o,configurable:!0});import{envNodeId as d,envScopes as l}from"../shared/env.js";import{execFile as m}from"node:child_process";import{createHash as p}from"node:crypto";import{mkdirSync as h,readFileSync as x,writeFileSync as y}from"node:fs";import{homedir as g}from"node:os";import{dirname as $,join as S}from"node:path";import{promisify as _}from"node:util";const w=_(m),s=15e3,O=`
2
2
 
3
- Guidelines:`;function T(t){const o=m("sha1").update(`${t}\0${process.env.CRTR_SCOPES??""}`).digest("hex").slice(0,16);return S(y(),".cache","crouter",`crtr-tool-guide-${o}.json`)}c(T,"helpCacheFile");function a(t,o){const r=`<crtr-tool-guide>
3
+ Guidelines:`;function T(t){const o=p("sha1").update(`${t}\0${l()?.join(",")??""}`).digest("hex").slice(0,16);return S(g(),".cache","crouter",`crtr-tool-guide-${o}.json`)}c(T,"helpCacheFile");function a(t,o){const r=`<crtr-tool-guide>
4
4
  ${o}
5
5
  </crtr-tool-guide>`,n=t.indexOf(O);return n===-1?`${t}
6
6
 
7
7
  ${r}`:`${t.slice(0,n)}
8
8
 
9
- ${r}${t.slice(n)}`}c(a,"injectToolGuide");function w(t){const o=d();if(o===void 0||o.trim()==="")return;let r="",n=0;async function u(){if(r!==""&&Date.now()-n<s)return;const i=T(process.cwd());try{const e=JSON.parse(h(i,"utf8"));if(typeof e.text=="string"&&e.text!==""&&typeof e.at=="number"&&Date.now()-e.at<s){r=e.text,n=e.at;return}}catch{}try{const{stdout:e}=await _("crtr",["-h"],{timeout:1e4});r=e.trim(),n=Date.now();try{p(g(i),{recursive:!0}),x(i,JSON.stringify({text:r,at:n}),"utf8")}catch{}}catch(e){console.error("[canvas-tool-guide] crtr -h capture failed:",e)}}c(u,"refresh"),t.on("session_start",u),t.on("before_agent_start",i=>{if(r!=="")return{systemPrompt:a(i.systemPrompt,r)}})}c(w,"registerCanvasToolGuide");var R=w;export{R as default,a as injectToolGuide,w as registerCanvasToolGuide};
9
+ ${r}${t.slice(n)}`}c(a,"injectToolGuide");function v(t){const o=d();if(o===void 0||o.trim()==="")return;let r="",n=0;async function u(){if(r!==""&&Date.now()-n<s)return;const i=T(process.cwd());try{const e=JSON.parse(x(i,"utf8"));if(typeof e.text=="string"&&e.text!==""&&typeof e.at=="number"&&Date.now()-e.at<s){r=e.text,n=e.at;return}}catch{}try{const{stdout:e}=await w("crtr",["-h"],{timeout:1e4});r=e.trim(),n=Date.now();try{h($(i),{recursive:!0}),y(i,JSON.stringify({text:r,at:n}),"utf8")}catch{}}catch(e){console.error("[canvas-tool-guide] crtr -h capture failed:",e)}}c(u,"refresh"),t.on("session_start",u),t.on("before_agent_start",i=>{if(r!=="")return{systemPrompt:a(i.systemPrompt,r)}})}c(v,"registerCanvasToolGuide");var A=v;export{A as default,a as injectToolGuide,v as registerCanvasToolGuide};
@@ -18,10 +18,17 @@ export declare function envGrantee(): string | undefined;
18
18
  * that variable is not this signal. */
19
19
  export declare const INBOX_BETWEEN_TURNS_ENV = "CRTR_INBOX_BETWEEN_TURNS";
20
20
  export declare function envInboxBetweenTurns(): boolean;
21
+ /** Path of the JSON file holding the run's scope allow-list (set by `nodeEnv`). */
22
+ export declare const SCOPES_FILE_ENV = "CRTR_SCOPES_FILE";
21
23
  /** The current run's scope allow-list; null means the row inherits everything. */
22
24
  export declare function envScopes(): readonly string[] | null;
23
25
  /** Whether a launched scope list covers a capability. Null means not narrowed. */
24
26
  export declare function scopeAllowed(scopes: readonly string[] | null | undefined, scope: string): boolean;
27
+ /** Whether any held scope covers `scope`. A held scope equal to the request always covers it, so the
28
+ * common case of a run narrowed to a subset of its grant is a string scan instead of `covers` on every
29
+ * pair (a 10,000-scope grant checked against 10,000 scopes is otherwise ~15 s). A request `covers`
30
+ * would reject as unparseable still throws. */
31
+ export declare function coveredByAny(held: readonly string[], scope: string): boolean;
25
32
  export declare function envExecutionId(): string | undefined;
26
33
  /** The current node's target profile id (`CRTR_PROFILE_ID`), or undefined. */
27
34
  export declare function envProfileId(): string | undefined;
@@ -1,2 +1,2 @@
1
- var _=Object.defineProperty;var e=(n,r)=>_(n,"name",{value:r,configurable:!0});import{lstatSync as R,readFileSync as p,readdirSync as T}from"node:fs";import{join as u}from"node:path";import{covers as E}from"@north-light/identity";function L(){return process.env.CRTR_NODE_ID}e(L,"envNodeId");function f(n){for(const r of["broker-launch.json","cron-launch.json"]){const t=u(n,r);if(R(t,{throwIfNoEntry:!1})?.isFile())return t}}e(f,"launchSnapshotFile");function d(){if(process.platform==="linux")try{const n="/run/crtr/nodes",r=new Set(p("/proc/self/mountinfo","utf8").split(`
2
- `).map(s=>s.split(" ")[4])),t=T(n,{withFileTypes:!0}).filter(s=>s.isDirectory()&&/^[a-zA-Z0-9][a-zA-Z0-9-]{0,127}$/.test(s.name)&&r.has(u(n,s.name))&&f(u(n,s.name))!==void 0);return t.length===1?t[0].name:void 0}catch{return}}e(d,"sandboxCliNodeId");function P(){return d()!==void 0}e(P,"isSandboxedNode");function F(){return process.env.CRTR_GRANTEE}e(F,"envGrantee");const v="CRTR_INBOX_BETWEEN_TURNS";function W(){return process.env[v]==="1"}e(W,"envInboxBetweenTurns");function h(){const n=process.env.CRTR_SCOPES;return n===void 0?null:n===""?[]:n.split(",")}e(h,"envScopes");function H(n,r){return n==null?!0:n.some(t=>E(t,r))}e(H,"scopeAllowed");function G(){return process.env.CRTR_EXECUTION_ID}e(G,"envExecutionId");function K(){return process.env.CRTR_PROFILE_ID}e(K,"envProfileId");function b(){return process.env.CRTR_NODE_CWD}e(b,"envNodeCwd");function k(){return process.env.CRTR_MODEL_INTENT}e(k,"envModelIntent");function g(){return process.env.CRTR_MODEL_EXACT==="1"}e(g,"envModelExact");function V(){return process.env.CRTR_HOME}e(V,"envHomeOverride");function w(){return process.env.CRTR_RUNTIME_HOME}e(w,"envRuntimeHomeOverride");function o(n,r){if(n===void 0)return r;const t=Number(n);return Number.isFinite(t)&&t>0?t:r}e(o,"parsePositiveMs");const C=5*6e4;function y(){return o(process.env.CRTR_STREAM_WATCHDOG_MS,C)}e(y,"envStreamWatchdogMs");const A=800;function X(){return o(process.env.CRTR_WATCHER_TICK_MS,A)}e(X,"envWatcherTickMs");const a=6e4;function j(){return o(process.env.CRTR_WATCHER_BACKSTOP_MS,a)}e(j,"envWatcherBackstopMs");const M=1e3;function Y(){return o(process.env.CRTR_WATCHER_DEBOUNCE_MS,M)}e(Y,"envWatcherDebounceMs");const S=6e4;function z(){return o(process.env.CRTR_RECAP_IDLE_MS,S)}e(z,"envRecapIdleMs");function Z(){const n=process.env.CRTR_RECAP_MODEL;return n!==void 0&&n.trim()!==""?n.trim():void 0}e(Z,"envRecapModelOverride");const x=300*1e3;function $(){return o(process.env.CRTR_BASH_VALVE_MS,x)}e($,"envBashValveMs");const N=60*1e3;function q(){return o(process.env.CRTR_BASH_AUTO_BG_DEADLINE_MS,N)}e(q,"envBashAutoBgDeadlineMs");function J(){const n=process.env.CRTR_PIDFILE;return n!==void 0&&n!==""?n:void 0}e(J,"envPidfileOverride");const D="@earendil-works/pi-coding-agent";function Q(){return process.env.CRTR_BROKER_ENGINE??D}e(Q,"envBrokerEngine");function ee(){return process.env.CRTR_PI_BINARY}e(ee,"envPiBinaryOverride");function ne(){return process.env.CRTR_NO_DAEMON_AUTOSTART==="1"}e(ne,"envNoDaemonAutostart");function re(){return process.env.CRTRD_TCP}e(re,"envCrtrdTcp");function te(){const n=process.env.CRTRD_TOKEN;return n!==void 0&&n!==""?n:void 0}e(te,"envCrtrdToken");function oe(){return process.env.CRTR_NO_EXPORTS==="1"}e(oe,"envNoExports");function se(){return process.env.CRTR_DEBUG==="1"}e(se,"envDebug");function c(n){if(n===void 0||n==="")return;const r=Number(n);return Number.isSafeInteger(r)&&r>=1?r:void 0}e(c,"parsePositiveInteger");function ue(){return c(process.env.CRTR_MAX_LIVE_BROKERS)}e(ue,"envMaxLiveBrokers");function ie(){return c(process.env.CRTR_WARN_LIVE_BROKERS)}e(ie,"envWarnLiveBrokers");function i(n){if(n===void 0)return;const r=Number(n);return Number.isFinite(r)&&r>0?r:void 0}e(i,"parsePositiveMsNoDefault");function ce(){return i(process.env.CRTR_TEST_UNATTENDED_PARK_MS)}e(ce,"envTestUnattendedParkMs");function _e(){return i(process.env.CRTR_UNATTENDED_PARK_MS)}e(_e,"envUnattendedParkMs");function O(){return i(process.env.CRTR_TEST_PARK_SUMMARY_GRACE_MS)}e(O,"envTestParkSummaryGraceMs");const m=5*6e4;function Re(){return O()??m}e(Re,"parkSummaryGraceMs");export{v as INBOX_BETWEEN_TURNS_ENV,q as envBashAutoBgDeadlineMs,$ as envBashValveMs,Q as envBrokerEngine,re as envCrtrdTcp,te as envCrtrdToken,se as envDebug,G as envExecutionId,F as envGrantee,V as envHomeOverride,W as envInboxBetweenTurns,ue as envMaxLiveBrokers,g as envModelExact,k as envModelIntent,ne as envNoDaemonAutostart,oe as envNoExports,b as envNodeCwd,L as envNodeId,ee as envPiBinaryOverride,J as envPidfileOverride,K as envProfileId,z as envRecapIdleMs,Z as envRecapModelOverride,w as envRuntimeHomeOverride,h as envScopes,y as envStreamWatchdogMs,O as envTestParkSummaryGraceMs,ce as envTestUnattendedParkMs,_e as envUnattendedParkMs,ie as envWarnLiveBrokers,j as envWatcherBackstopMs,Y as envWatcherDebounceMs,X as envWatcherTickMs,P as isSandboxedNode,f as launchSnapshotFile,Re as parkSummaryGraceMs,d as sandboxCliNodeId,H as scopeAllowed};
1
+ var p=Object.defineProperty;var e=(n,r)=>p(n,"name",{value:r,configurable:!0});import{lstatSync as f,readFileSync as c,readdirSync as E}from"node:fs";import{join as u}from"node:path";import{covers as _}from"@north-light/identity";function F(){return process.env.CRTR_NODE_ID}e(F,"envNodeId");function T(n){for(const r of["broker-launch.json","cron-launch.json"]){const t=u(n,r);if(f(t,{throwIfNoEntry:!1})?.isFile())return t}}e(T,"launchSnapshotFile");function d(){if(process.platform==="linux")try{const n="/run/crtr/nodes",r=new Set(c("/proc/self/mountinfo","utf8").split(`
2
+ `).map(o=>o.split(" ")[4])),t=E(n,{withFileTypes:!0}).filter(o=>o.isDirectory()&&/^[a-zA-Z0-9][a-zA-Z0-9-]{0,127}$/.test(o.name)&&r.has(u(n,o.name))&&T(u(n,o.name))!==void 0);return t.length===1?t[0].name:void 0}catch{return}}e(d,"sandboxCliNodeId");function W(){return d()!==void 0}e(W,"isSandboxedNode");function h(){return process.env.CRTR_GRANTEE}e(h,"envGrantee");const v="CRTR_INBOX_BETWEEN_TURNS";function H(){return process.env[v]==="1"}e(H,"envInboxBetweenTurns");const C="CRTR_SCOPES_FILE";function G(){const n=process.env[C];if(n!==void 0&&n!==""){const t=JSON.parse(c(n,"utf8"));if(!Array.isArray(t)||t.some(o=>typeof o!="string"))throw new Error(`invalid scopes file ${n}`);return t}const r=process.env.CRTR_SCOPES;return r===void 0?null:r===""?[]:r.split(",")}e(G,"envScopes");function K(n,r){return n==null?!0:a(n,r)}e(K,"scopeAllowed");function a(n,r){return n.includes(r)?(_(r,r),!0):n.some(t=>_(t,r))}e(a,"coveredByAny");function y(){return process.env.CRTR_EXECUTION_ID}e(y,"envExecutionId");function b(){return process.env.CRTR_PROFILE_ID}e(b,"envProfileId");function k(){return process.env.CRTR_NODE_CWD}e(k,"envNodeCwd");function g(){return process.env.CRTR_MODEL_INTENT}e(g,"envModelIntent");function w(){return process.env.CRTR_MODEL_EXACT==="1"}e(w,"envModelExact");function V(){return process.env.CRTR_HOME}e(V,"envHomeOverride");function X(){return process.env.CRTR_RUNTIME_HOME}e(X,"envRuntimeHomeOverride");function s(n,r){if(n===void 0)return r;const t=Number(n);return Number.isFinite(t)&&t>0?t:r}e(s,"parsePositiveMs");const A=5*6e4;function j(){return s(process.env.CRTR_STREAM_WATCHDOG_MS,A)}e(j,"envStreamWatchdogMs");const S=800;function Y(){return s(process.env.CRTR_WATCHER_TICK_MS,S)}e(Y,"envWatcherTickMs");const M=6e4;function z(){return s(process.env.CRTR_WATCHER_BACKSTOP_MS,M)}e(z,"envWatcherBackstopMs");const x=1e3;function Z(){return s(process.env.CRTR_WATCHER_DEBOUNCE_MS,x)}e(Z,"envWatcherDebounceMs");const N=6e4;function $(){return s(process.env.CRTR_RECAP_IDLE_MS,N)}e($,"envRecapIdleMs");function J(){const n=process.env.CRTR_RECAP_MODEL;return n!==void 0&&n.trim()!==""?n.trim():void 0}e(J,"envRecapModelOverride");const D=300*1e3;function q(){return s(process.env.CRTR_BASH_VALVE_MS,D)}e(q,"envBashValveMs");const O=60*1e3;function Q(){return s(process.env.CRTR_BASH_AUTO_BG_DEADLINE_MS,O)}e(Q,"envBashAutoBgDeadlineMs");function ee(){const n=process.env.CRTR_PIDFILE;return n!==void 0&&n!==""?n:void 0}e(ee,"envPidfileOverride");const l="@earendil-works/pi-coding-agent";function ne(){return process.env.CRTR_BROKER_ENGINE??l}e(ne,"envBrokerEngine");function re(){return process.env.CRTR_PI_BINARY}e(re,"envPiBinaryOverride");function te(){return process.env.CRTR_NO_DAEMON_AUTOSTART==="1"}e(te,"envNoDaemonAutostart");function oe(){return process.env.CRTRD_TCP}e(oe,"envCrtrdTcp");function se(){const n=process.env.CRTRD_TOKEN;return n!==void 0&&n!==""?n:void 0}e(se,"envCrtrdToken");function ue(){return process.env.CRTR_NO_EXPORTS==="1"}e(ue,"envNoExports");function ie(){return process.env.CRTR_DEBUG==="1"}e(ie,"envDebug");function R(n){if(n===void 0||n==="")return;const r=Number(n);return Number.isSafeInteger(r)&&r>=1?r:void 0}e(R,"parsePositiveInteger");function ce(){return R(process.env.CRTR_MAX_LIVE_BROKERS)}e(ce,"envMaxLiveBrokers");function _e(){return R(process.env.CRTR_WARN_LIVE_BROKERS)}e(_e,"envWarnLiveBrokers");function i(n){if(n===void 0)return;const r=Number(n);return Number.isFinite(r)&&r>0?r:void 0}e(i,"parsePositiveMsNoDefault");function Re(){return i(process.env.CRTR_TEST_UNATTENDED_PARK_MS)}e(Re,"envTestUnattendedParkMs");function pe(){return i(process.env.CRTR_UNATTENDED_PARK_MS)}e(pe,"envUnattendedParkMs");function I(){return i(process.env.CRTR_TEST_PARK_SUMMARY_GRACE_MS)}e(I,"envTestParkSummaryGraceMs");const m=5*6e4;function fe(){return I()??m}e(fe,"parkSummaryGraceMs");export{v as INBOX_BETWEEN_TURNS_ENV,C as SCOPES_FILE_ENV,a as coveredByAny,Q as envBashAutoBgDeadlineMs,q as envBashValveMs,ne as envBrokerEngine,oe as envCrtrdTcp,se as envCrtrdToken,ie as envDebug,y as envExecutionId,h as envGrantee,V as envHomeOverride,H as envInboxBetweenTurns,ce as envMaxLiveBrokers,w as envModelExact,g as envModelIntent,te as envNoDaemonAutostart,ue as envNoExports,k as envNodeCwd,F as envNodeId,re as envPiBinaryOverride,ee as envPidfileOverride,b as envProfileId,$ as envRecapIdleMs,J as envRecapModelOverride,X as envRuntimeHomeOverride,G as envScopes,j as envStreamWatchdogMs,I as envTestParkSummaryGraceMs,Re as envTestUnattendedParkMs,pe as envUnattendedParkMs,_e as envWarnLiveBrokers,z as envWatcherBackstopMs,Z as envWatcherDebounceMs,Y as envWatcherTickMs,W as isSandboxedNode,T as launchSnapshotFile,fe as parkSummaryGraceMs,d as sandboxCliNodeId,K as scopeAllowed};
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@north-light/cli",
3
- "version": "0.3.440",
3
+ "version": "0.3.442",
4
4
  "description": "crtr — agent runtime with memory, plugins, and marketplaces",
5
5
  "type": "module",
6
6
  "main": "dist/index.js",
@@ -137,7 +137,7 @@
137
137
  },
138
138
  "license": "UNLICENSED",
139
139
  "dependencies": {
140
- "@north-light/identity": "0.3.440",
140
+ "@north-light/identity": "0.3.442",
141
141
  "@earendil-works/pi-agent-core": "1.1.0",
142
142
  "@earendil-works/pi-ai": "1.1.0",
143
143
  "@earendil-works/pi-coding-agent": "1.1.0",
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@north-light/identity",
3
- "version": "0.3.440",
3
+ "version": "0.3.442",
4
4
  "description": "Northlight access-token verification and scope rules",
5
5
  "type": "module",
6
6
  "main": "./dist/index.js",
package/runtime.lock.json CHANGED
@@ -1,12 +1,12 @@
1
1
  {
2
2
  "name": "@north-light/cli",
3
- "version": "0.3.440",
3
+ "version": "0.3.442",
4
4
  "lockfileVersion": 3,
5
5
  "requires": true,
6
6
  "packages": {
7
7
  "": {
8
8
  "name": "@north-light/cli",
9
- "version": "0.3.440",
9
+ "version": "0.3.442",
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.440",
21
+ "@north-light/identity": "0.3.442",
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.440",
12098
+ "version": "0.3.442",
12099
12099
  "license": "UNLICENSED"
12100
12100
  },
12101
12101
  "packages/crouter-env-docker": {
12102
12102
  "name": "@north-light/env-docker",
12103
- "version": "0.3.440",
12103
+ "version": "0.3.442",
12104
12104
  "license": "UNLICENSED"
12105
12105
  },
12106
12106
  "packages/crouter-identity": {
12107
12107
  "name": "@north-light/identity",
12108
- "version": "0.3.440",
12108
+ "version": "0.3.442",
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.440",
12116
+ "version": "0.3.442",
12117
12117
  "license": "UNLICENSED",
12118
12118
  "dependencies": {
12119
- "@north-light/api": "0.3.440",
12120
- "@north-light/identity": "0.3.440"
12119
+ "@north-light/api": "0.3.442",
12120
+ "@north-light/identity": "0.3.442"
12121
12121
  }
12122
12122
  },
12123
12123
  "packages/crouter-sdk": {
12124
12124
  "name": "@north-light/sdk",
12125
- "version": "0.3.440",
12125
+ "version": "0.3.442",
12126
12126
  "license": "UNLICENSED",
12127
12127
  "dependencies": {
12128
- "@north-light/api": "0.3.440",
12129
- "@north-light/identity": "0.3.440",
12128
+ "@north-light/api": "0.3.442",
12129
+ "@north-light/identity": "0.3.442",
12130
12130
  "jose": "^6.2.1"
12131
12131
  },
12132
12132
  "bin": {