@north-light/cli 0.3.471 → 0.3.472

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.
@@ -9,6 +9,18 @@ when-and-why-to-read: When you need Release notes, this knowledge should be read
9
9
 
10
10
  Changes to `@north-light/sdk` that can change what an existing app sees. Newest first.
11
11
 
12
+ ## 0.3.472
13
+
14
+ ### `npx @north-light/sdk init`, `skill` and `env --client-id` (additive, no app change)
15
+
16
+ The `crouter-sdk` bin gains three commands that need neither crtr nor a joined machine:
17
+
18
+ - `init [dir] [--agent claude|agents|all] [--global-skill]` scaffolds an app in an empty or new directory (`package.json` with `@north-light/sdk` pinned to the CLI's own version plus `tsx`, `server.ts`, `.gitignore`, `local/app.env`, a signing key in `local/app-key.json`) and installs the `northlight` Agent Skill into `.agents/skills` and `.claude/skills`. In a directory that already has a `package.json` it writes no app code: it runs `npm i --save-exact @north-light/sdk@<this version>`, makes a key if `local/app-key.json` is missing, and installs the skill. It never overwrites a file; it exits 1 and names the file it refused.
19
+ - `skill [--agent claude|agents|all] [--global] [--print]` writes the skill that ships in the package, replacing an older copy. The skill's `metadata.sdk-version` is the package version; run `skill` again after changing the pinned SDK version.
20
+ - `env --client-id <id> [--origin <url>] [--issuer <url>] [--out <path>]` writes `CROUTER_ISSUER`, `CROUTER_CLIENT_ID` and `APP_ORIGIN` into `local/app.env` and keeps every other line, with no network call. `env --app <id>` still reads them through crtr; passing both is a usage error.
21
+
22
+ `keygen` is unchanged. The package still has one bin, so `npx @north-light/sdk <command>` keeps working. A bare `npx @north-light/sdk`, `--help` and an unknown command print the command list (exit 1 for the unknown command).
23
+
12
24
  ## 0.3.462
13
25
 
14
26
  ### `ProfileDTO.memory_path` is removed (profile objects carry only `profile_path`)
@@ -51,6 +51,8 @@ export declare class ProviderPanel implements SetupPanel {
51
51
  private openBrowser;
52
52
  private openCatalog;
53
53
  private startLogin;
54
+ /** True when the cursor sits on the `+ Add provider` row, where Enter opens the catalog. */
55
+ isAddRowSelected(): boolean;
54
56
  isNestedFlowActive(): boolean;
55
57
  dispose(): void;
56
58
  private runMutation;
@@ -1 +1 @@
1
- var R=Object.defineProperty;var m=(u,e)=>R(u,"name",{value:e,configurable:!0});import{LoginDialogComponent as E}from"@earendil-works/pi-coding-agent";import{Input as B,matchesKey as d,truncateToWidth as D}from"@earendil-works/pi-tui";import{execFile as N}from"node:child_process";import{dialogAuthInteraction as T}from"../../../core/auth-interaction.js";import{isProviderCredentialConfigured as F}from"../../../core/provider-credential.js";import{formatCooldowns as _,isManagedProvider as L,promoteSubscription as U,readSubscriptionPool as k,renameSubscription as V}from"../../../core/subscription-state.js";import{removeProviderRow as j}from"../../../core/provider-management.js";import{cliClient as q}from"../../api-client.js";import{loginProvider as K}from"../provider-login.js";import{fitTail as P,theme as a,visibleRange as S}from"../../../core/tui/panel.js";function M(u,e){const t=u.getProviders().filter(i=>i.auth.oauth!==void 0),n=new Set(t.map(i=>i.id)),o=new Set;return[...t.map(i=>({providerId:i.id,name:i.name,managed:L(i.id),authType:"oauth"})),...e.getAll().map(i=>({providerId:i.provider,name:e.getProviderDisplayName(i.provider),managed:L(i.provider),authType:n.has(i.provider)?"oauth":"api_key"}))].filter(i=>!o.has(i.providerId)&&!!o.add(i.providerId))}m(M,"buildProviderCatalog");function O(u,e){return e||u instanceof Error&&u.name==="AbortError"?"Login cancelled":`Login error: ${u instanceof Error?u.message:String(u)}`}m(O,"classifyLoginFailure");class ie{static{m(this,"ProviderPanel")}tui;agentDir;runtime;registry;renameInput=new B;rows=[];selected=0;mode="list";notice="";catalog=[];catalogIndex=0;loginProvider;loginFlow;mutationInFlight=!1;onChange;constructor(e,t,n,o){this.tui=e,this.agentDir=t,this.runtime=n,this.registry=o,this.renameInput.onSubmit=()=>this.rename(),this.renameInput.onEscape=()=>{this.mode="list"},this.reload()}notifyChange(){this.onChange?.(),this.tui.requestRender()}reloadAfterAuthChange(){this.reload(),this.registry.refresh().then(()=>{this.reload(),this.notifyChange()})}reload(){const e=this.registry,t=[];for(const n of M(this.runtime,e)){const o=e.getProviderAuthStatus(n.providerId);if(n.managed){const i=k(n.providerId);if(i.length===0&&!o.source)continue;t.push({...n,configured:F(n.providerId,e),source:o.source,sourceLabel:o.label}),i.forEach((r,c)=>t.push({...n,label:r.label,preferred:c===0,cooldownUntil:r.rateLimitedUntil,...r.modelCooldowns?{modelCooldowns:r.modelCooldowns}:{},accountId:r.accountId}));continue}o.source&&t.push({...n,configured:F(n.providerId,e),source:o.source,sourceLabel:o.label})}this.rows=t,this.selected=Math.min(this.selected,Math.max(0,t.length))}selectedRow(){return this.rows[this.selected]}openBrowser(e){const t=process.platform==="darwin"?"open":process.platform==="win32"?"cmd":"xdg-open",n=process.platform==="win32"?["/c","start","",e]:[e];N(t,n,{timeout:5e3},()=>{})}openCatalog(){this.catalog=M(this.runtime,this.registry),this.catalogIndex=0,this.mode="catalog"}startLogin(e,t){this.loginProvider=e;let n;const o=m(s=>{!n.active||this.loginFlow!==n||(n.active=!1,this.loginFlow=void 0,this.mode="list",this.notice=s,this.reloadAfterAuthChange(),this.notifyChange())},"complete"),i=new E(this.tui,e.providerId,(s,p)=>{s||o(p?`Login failed: ${p}`:"Login cancelled")},e.name);n={dialog:i,active:!0,committing:!1},this.loginFlow=n,this.mode="login";const r=i.handleInput.bind(i);i.handleInput=s=>{n.committing||r(s)};const c=m(()=>n.active&&this.loginFlow===n&&!i.signal.aborted,"isActive"),h=m(()=>c()?(n.committing=!0,i.showDetails(["Saving credentials\u2026"]),!0):!1,"beginCommit"),g=m(s=>{o(O(s,i.signal.aborted))},"fail");if(e.authType==="api_key"){i.showPrompt(`Enter API key for ${e.name}:`,"sk-...").then(async s=>{if(c()){if(!s.trim()){o("No key entered \u2014 login cancelled");return}h()&&(await q().installCredential(e.providerId,{kind:"api_key",api_key:s.trim()}),o(`API key saved for ${e.name}`))}}).catch(g);return}const $=T(i,{openBrowser:m(s=>this.openBrowser(s),"openBrowser"),onChange:m(()=>this.notifyChange(),"onChange"),isActive:c});K(this.runtime,e.providerId,$,{label:t,beforeInstall:h}).then(s=>{s&&c()&&o(`Logged in to ${e.name}`)}).catch(g)}isNestedFlowActive(){return this.mode==="login"}dispose(){const e=this.loginFlow;e&&(e.active=!1,this.loginFlow=void 0,e.dialog.handleInput("\x1B"))}runMutation(e){this.mutationInFlight||(this.mutationInFlight=!0,e().catch(t=>{this.notice=t instanceof Error?t.message:String(t)}).finally(()=>{this.mutationInFlight=!1,this.notifyChange()}))}suggestedAccountLabel(e){const t=new Set((L(e)?k(e):[]).map(o=>o.label.toLowerCase()));if(!t.has("default"))return"default";let n=2;for(;t.has(`account-${n}`);)n+=1;return`account-${n}`}rename(){const e=this.selectedRow();!e?.managed||!e.label||(this.mode="list",this.runMutation(async()=>{await V(e.providerId,e.label,this.renameInput.getValue()),this.notice=`Renamed ${e.name} account`,this.reload()}))}remove(e){this.runMutation(async()=>{this.notice=await j(this.agentDir,e),this.reloadAfterAuthChange()})}promote(e){this.runMutation(async()=>{await U(e.providerId,e.label),this.notice=`Preferred ${e.name} account`,this.reload()})}handleInput(e){if(this.mode==="login")return this.loginFlow?.dialog.handleInput(e),!0;if(this.mutationInFlight)return!0;if(this.mode==="rename"||this.mode==="label")return this.renameInput.handleInput(e),!0;if(this.mode==="catalog"){if(d(e,"escape"))return this.mode="list",!0;if(d(e,"j")||d(e,"down"))return this.catalogIndex=Math.min(this.catalog.length-1,this.catalogIndex+1),!0;if(d(e,"k")||d(e,"up"))return this.catalogIndex=Math.max(0,this.catalogIndex-1),!0;if(d(e,"enter")){const o=this.catalog[this.catalogIndex];if(o.managed){this.loginProvider=o;const i=this.suggestedAccountLabel(o.providerId);this.renameInput.setValue(i),this.renameInput.onSubmit=()=>{this.startLogin(o,this.renameInput.getValue().trim()||i)},this.mode="label"}else this.startLogin(o);return!0}return!0}if(this.mode==="remove"){if(d(e,"y")||d(e,"enter")){const o=this.selectedRow();o&&(o.managed||o.configured)&&this.remove(o)}return this.mode="list",!0}if(d(e,"j")||d(e,"down"))return this.selected=Math.min(this.rows.length,this.selected+1),!0;if(d(e,"k")||d(e,"up"))return this.selected=Math.max(0,this.selected-1),!0;const t=this.selectedRow();if(d(e,"p")&&t?.managed&&t.label)return this.promote(t),!0;if(d(e,"r")&&t?.managed&&t.label)return this.renameInput.setValue(t.label),this.renameInput.onSubmit=()=>this.rename(),this.mode="rename",!0;if(d(e,"x")&&(t?.managed||t?.configured))return this.mode="remove",!0;if(d(e,"a"))return this.openCatalog(),!0;const n=t?.source==="environment"||t?.source==="runtime";return d(e,"l")&&t&&!n?(t.managed&&t.label?this.startLogin(t,t.label):this.startLogin(t),!0):d(e,"enter")?(t&&!n?this.startLogin(t,t.managed&&t.label?t.label:void 0):t||this.openCatalog(),!0):!1}badge(){return String(this.rows.filter(e=>e.label===void 0).length)}render(e,t){const n=a.fg("accent",a.bold("Providers")),o=a.fg("dim",`${this.rows.filter(c=>c.label===void 0).length} configured`),i=Math.max(1,t);let r;if(this.mode==="login")r=P(this.loginFlow?.dialog.render(e)??[],i);else if(this.mode==="rename"||this.mode==="label")r=P([n,o,"",a.fg("accent",this.mode==="rename"?"Rename account":`Name the ${this.loginProvider?.name??"provider"} account`),...this.mode==="label"?[a.fg("dim","Names this credential \u2014 keep work and personal accounts on one provider apart")]:[],...this.renameInput.render(Math.max(1,e-8))],i);else if(this.mode==="remove"){const c=this.selectedRow(),h=c?.label??(c?.managed?`${c.name} \xB7 all accounts`:c?.name??"account");r=P([n,o,"",a.fg("warning",`Remove ${h}? y/enter confirm \xB7 any other key cancel`)],i)}else{const c=[n,o].slice(0,Math.max(0,i-1)),h=i-c.length;if(r=[...c],this.mode==="catalog"){const g=this.catalog.length,s=g>h&&h>=2,p=s?h-1:h,{start:I,end:v}=S(g,this.catalogIndex,p);let w=h-(v-I)-(s?1:0);w>0&&(r.push(a.fg("dim","Select a provider to add \xB7 esc back")),w-=1);for(let f=I;f<v;f++){const C=this.catalog[f];r.push(`${f===this.catalogIndex?a.fg("accent","\u25B6"):" "} ${C.name}`)}s&&r.push(a.fg("dim",`(${this.catalogIndex+1}/${g})`))}else{const g=this.rows.length+1,s=g>h&&h>=2,p=s?h-1:h,{start:I,end:v}=S(g,this.selected,p);let w=h-(v-I)-(s?1:0);const f=this.rows.length===0&&w>0;f&&(w-=1);const C=!!this.notice&&w>0;f&&r.push(a.fg("warning","No provider configured yet."));for(let b=I;b<v;b++){if(b===this.rows.length){r.push(`${this.selected===this.rows.length?a.fg("accent","\u25B6"):" "} ${a.fg("accent","\uFF0B Add provider")}`);continue}const l=this.rows[b],A=b===this.selected?a.fg("accent","\u25B6"):" ";if(l.label){const x=_({rateLimitedUntil:l.cooldownUntil??0,modelCooldowns:l.modelCooldowns})??"ready",y=l.accountId?` \xB7 ${l.accountId.length>12?`${l.accountId.slice(0,8)}\u2026${l.accountId.slice(-4)}`:l.accountId}`:"";r.push(`${A} ${l.preferred?a.fg("success","\u25CF"):" "} ${l.label}${a.fg("dim",y)} ${a.fg("dim",x)}${l.preferred?a.fg("accent"," preferred"):""}`)}else{const x=l.managed?`${this.rows.filter(y=>y.providerId===l.providerId&&y.label).length} accounts`:l.source==="environment"||l.source==="runtime"?`${l.source}${l.sourceLabel?` \xB7 ${l.sourceLabel}`:""} (view only)`:"configured";r.push(`${A} ${a.fg("accent",l.name)}${a.fg("dim",` ${x}`)}`)}}s&&r.push(a.fg("dim",`(${this.selected+1}/${g})`)),C&&r.push(a.fg("dim",this.notice))}}return r.map(c=>D(c,e))}}export{ie as ProviderPanel,M as buildProviderCatalog,O as classifyLoginFailure};
1
+ var R=Object.defineProperty;var g=(u,e)=>R(u,"name",{value:e,configurable:!0});import{LoginDialogComponent as E}from"@earendil-works/pi-coding-agent";import{Input as B,matchesKey as d,truncateToWidth as D}from"@earendil-works/pi-tui";import{execFile as N}from"node:child_process";import{dialogAuthInteraction as T}from"../../../core/auth-interaction.js";import{isProviderCredentialConfigured as F}from"../../../core/provider-credential.js";import{formatCooldowns as _,isManagedProvider as L,promoteSubscription as U,readSubscriptionPool as S,renameSubscription as V}from"../../../core/subscription-state.js";import{removeProviderRow as j}from"../../../core/provider-management.js";import{cliClient as q}from"../../api-client.js";import{loginProvider as K}from"../provider-login.js";import{fitTail as P,theme as a,visibleRange as k}from"../../../core/tui/panel.js";function M(u,e){const t=u.getProviders().filter(i=>i.auth.oauth!==void 0),n=new Set(t.map(i=>i.id)),o=new Set;return[...t.map(i=>({providerId:i.id,name:i.name,managed:L(i.id),authType:"oauth"})),...e.getAll().map(i=>({providerId:i.provider,name:e.getProviderDisplayName(i.provider),managed:L(i.provider),authType:n.has(i.provider)?"oauth":"api_key"}))].filter(i=>!o.has(i.providerId)&&!!o.add(i.providerId))}g(M,"buildProviderCatalog");function O(u,e){return e||u instanceof Error&&u.name==="AbortError"?"Login cancelled":`Login error: ${u instanceof Error?u.message:String(u)}`}g(O,"classifyLoginFailure");class ie{static{g(this,"ProviderPanel")}tui;agentDir;runtime;registry;renameInput=new B;rows=[];selected=0;mode="list";notice="";catalog=[];catalogIndex=0;loginProvider;loginFlow;mutationInFlight=!1;onChange;constructor(e,t,n,o){this.tui=e,this.agentDir=t,this.runtime=n,this.registry=o,this.renameInput.onSubmit=()=>this.rename(),this.renameInput.onEscape=()=>{this.mode="list"},this.reload()}notifyChange(){this.onChange?.(),this.tui.requestRender()}reloadAfterAuthChange(){this.reload(),this.registry.refresh().then(()=>{this.reload(),this.notifyChange()})}reload(){const e=this.registry,t=[];for(const n of M(this.runtime,e)){const o=e.getProviderAuthStatus(n.providerId);if(n.managed){const i=S(n.providerId);if(i.length===0&&!o.source)continue;t.push({...n,configured:F(n.providerId,e),source:o.source,sourceLabel:o.label}),i.forEach((r,c)=>t.push({...n,label:r.label,preferred:c===0,cooldownUntil:r.rateLimitedUntil,...r.modelCooldowns?{modelCooldowns:r.modelCooldowns}:{},accountId:r.accountId}));continue}o.source&&t.push({...n,configured:F(n.providerId,e),source:o.source,sourceLabel:o.label})}this.rows=t,this.selected=Math.min(this.selected,Math.max(0,t.length))}selectedRow(){return this.rows[this.selected]}openBrowser(e){const t=process.platform==="darwin"?"open":process.platform==="win32"?"cmd":"xdg-open",n=process.platform==="win32"?["/c","start","",e]:[e];N(t,n,{timeout:5e3},()=>{})}openCatalog(){this.catalog=M(this.runtime,this.registry),this.catalogIndex=0,this.mode="catalog"}startLogin(e,t){this.loginProvider=e;let n;const o=g(s=>{!n.active||this.loginFlow!==n||(n.active=!1,this.loginFlow=void 0,this.mode="list",this.notice=s,this.reloadAfterAuthChange(),this.notifyChange())},"complete"),i=new E(this.tui,e.providerId,(s,p)=>{s||o(p?`Login failed: ${p}`:"Login cancelled")},e.name);n={dialog:i,active:!0,committing:!1},this.loginFlow=n,this.mode="login";const r=i.handleInput.bind(i);i.handleInput=s=>{n.committing||r(s)};const c=g(()=>n.active&&this.loginFlow===n&&!i.signal.aborted,"isActive"),h=g(()=>c()?(n.committing=!0,i.showDetails(["Saving credentials\u2026"]),!0):!1,"beginCommit"),m=g(s=>{o(O(s,i.signal.aborted))},"fail");if(e.authType==="api_key"){i.showPrompt(`Enter API key for ${e.name}:`,"sk-...").then(async s=>{if(c()){if(!s.trim()){o("No key entered \u2014 login cancelled");return}h()&&(await q().installCredential(e.providerId,{kind:"api_key",api_key:s.trim()}),o(`API key saved for ${e.name}`))}}).catch(m);return}const $=T(i,{openBrowser:g(s=>this.openBrowser(s),"openBrowser"),onChange:g(()=>this.notifyChange(),"onChange"),isActive:c});K(this.runtime,e.providerId,$,{label:t,beforeInstall:h}).then(s=>{s&&c()&&o(`Logged in to ${e.name}`)}).catch(m)}isAddRowSelected(){return this.mode==="list"&&this.selectedRow()===void 0}isNestedFlowActive(){return this.mode==="login"}dispose(){const e=this.loginFlow;e&&(e.active=!1,this.loginFlow=void 0,e.dialog.handleInput("\x1B"))}runMutation(e){this.mutationInFlight||(this.mutationInFlight=!0,e().catch(t=>{this.notice=t instanceof Error?t.message:String(t)}).finally(()=>{this.mutationInFlight=!1,this.notifyChange()}))}suggestedAccountLabel(e){const t=new Set((L(e)?S(e):[]).map(o=>o.label.toLowerCase()));if(!t.has("default"))return"default";let n=2;for(;t.has(`account-${n}`);)n+=1;return`account-${n}`}rename(){const e=this.selectedRow();!e?.managed||!e.label||(this.mode="list",this.runMutation(async()=>{await V(e.providerId,e.label,this.renameInput.getValue()),this.notice=`Renamed ${e.name} account`,this.reload()}))}remove(e){this.runMutation(async()=>{this.notice=await j(this.agentDir,e),this.reloadAfterAuthChange()})}promote(e){this.runMutation(async()=>{await U(e.providerId,e.label),this.notice=`Preferred ${e.name} account`,this.reload()})}handleInput(e){if(this.mode==="login")return this.loginFlow?.dialog.handleInput(e),!0;if(this.mutationInFlight)return!0;if(this.mode==="rename"||this.mode==="label")return this.renameInput.handleInput(e),!0;if(this.mode==="catalog"){if(d(e,"escape"))return this.mode="list",!0;if(d(e,"j")||d(e,"down"))return this.catalogIndex=Math.min(this.catalog.length-1,this.catalogIndex+1),!0;if(d(e,"k")||d(e,"up"))return this.catalogIndex=Math.max(0,this.catalogIndex-1),!0;if(d(e,"enter")){const o=this.catalog[this.catalogIndex];if(o.managed){this.loginProvider=o;const i=this.suggestedAccountLabel(o.providerId);this.renameInput.setValue(i),this.renameInput.onSubmit=()=>{this.startLogin(o,this.renameInput.getValue().trim()||i)},this.mode="label"}else this.startLogin(o);return!0}return!0}if(this.mode==="remove"){if(d(e,"y")||d(e,"enter")){const o=this.selectedRow();o&&(o.managed||o.configured)&&this.remove(o)}return this.mode="list",!0}if(d(e,"j")||d(e,"down"))return this.selected=Math.min(this.rows.length,this.selected+1),!0;if(d(e,"k")||d(e,"up"))return this.selected=Math.max(0,this.selected-1),!0;const t=this.selectedRow();if(d(e,"p")&&t?.managed&&t.label)return this.promote(t),!0;if(d(e,"r")&&t?.managed&&t.label)return this.renameInput.setValue(t.label),this.renameInput.onSubmit=()=>this.rename(),this.mode="rename",!0;if(d(e,"x")&&(t?.managed||t?.configured))return this.mode="remove",!0;if(d(e,"a"))return this.openCatalog(),!0;const n=t?.source==="environment"||t?.source==="runtime";return d(e,"l")&&t&&!n?(t.managed&&t.label?this.startLogin(t,t.label):this.startLogin(t),!0):d(e,"enter")&&!t?(this.openCatalog(),!0):!1}badge(){return String(this.rows.filter(e=>e.label===void 0).length)}render(e,t){const n=a.fg("accent",a.bold("Providers")),o=a.fg("dim",`${this.rows.filter(c=>c.label===void 0).length} configured`),i=Math.max(1,t);let r;if(this.mode==="login")r=P(this.loginFlow?.dialog.render(e)??[],i);else if(this.mode==="rename"||this.mode==="label")r=P([n,o,"",a.fg("accent",this.mode==="rename"?"Rename account":`Name the ${this.loginProvider?.name??"provider"} account`),...this.mode==="label"?[a.fg("dim","Names this credential \u2014 keep work and personal accounts on one provider apart")]:[],...this.renameInput.render(Math.max(1,e-8))],i);else if(this.mode==="remove"){const c=this.selectedRow(),h=c?.label??(c?.managed?`${c.name} \xB7 all accounts`:c?.name??"account");r=P([n,o,"",a.fg("warning",`Remove ${h}? y/enter confirm \xB7 any other key cancel`)],i)}else{const c=[n,o].slice(0,Math.max(0,i-1)),h=i-c.length;if(r=[...c],this.mode==="catalog"){const m=this.catalog.length,s=m>h&&h>=2,p=s?h-1:h,{start:I,end:v}=k(m,this.catalogIndex,p);let w=h-(v-I)-(s?1:0);w>0&&(r.push(a.fg("dim","Select a provider to add \xB7 esc back")),w-=1);for(let f=I;f<v;f++){const C=this.catalog[f];r.push(`${f===this.catalogIndex?a.fg("accent","\u25B6"):" "} ${C.name}`)}s&&r.push(a.fg("dim",`(${this.catalogIndex+1}/${m})`))}else{const m=this.rows.length+1,s=m>h&&h>=2,p=s?h-1:h,{start:I,end:v}=k(m,this.selected,p);let w=h-(v-I)-(s?1:0);const f=this.rows.length===0&&w>0;f&&(w-=1);const C=!!this.notice&&w>0;f&&r.push(a.fg("warning","No provider configured yet."));for(let b=I;b<v;b++){if(b===this.rows.length){r.push(`${this.selected===this.rows.length?a.fg("accent","\u25B6"):" "} ${a.fg("accent","\uFF0B Add provider")}`);continue}const l=this.rows[b],A=b===this.selected?a.fg("accent","\u25B6"):" ";if(l.label){const x=_({rateLimitedUntil:l.cooldownUntil??0,modelCooldowns:l.modelCooldowns})??"ready",y=l.accountId?` \xB7 ${l.accountId.length>12?`${l.accountId.slice(0,8)}\u2026${l.accountId.slice(-4)}`:l.accountId}`:"";r.push(`${A} ${l.preferred?a.fg("success","\u25CF"):" "} ${l.label}${a.fg("dim",y)} ${a.fg("dim",x)}${l.preferred?a.fg("accent"," preferred"):""}`)}else{const x=l.managed?`${this.rows.filter(y=>y.providerId===l.providerId&&y.label).length} accounts`:l.source==="environment"||l.source==="runtime"?`${l.source}${l.sourceLabel?` \xB7 ${l.sourceLabel}`:""} (view only)`:"configured";r.push(`${A} ${a.fg("accent",l.name)}${a.fg("dim",` ${x}`)}`)}}s&&r.push(a.fg("dim",`(${this.selected+1}/${m})`)),C&&r.push(a.fg("dim",this.notice))}}return r.map(c=>D(c,e))}}export{ie as ProviderPanel,M as buildProviderCatalog,O as classifyLoginFailure};
@@ -1 +1 @@
1
- var P=Object.defineProperty;var p=(h,e)=>P(h,"name",{value:e,configurable:!0});import{matchesKey as b,truncateToWidth as c,visibleWidth as g}from"@earendil-works/pi-tui";import{formatGesture as v,formatMovePair as k,matchesPiTuiInput as $}from"../../core/keybindings/index.js";import{buildSetupInitialState as y,executeSetupSubmission as I,formatSetupExecutionSummary as w,packagePlanAction as A,reconcileInboxFrontDoor as x,renderSetupStaticInstructions as T,setupPluginEnvFields as C}from"./setup-core.js";import{runSetupSettingsProcess as W}from"./setup-settings-runner.js";import{DependenciesPanel as D}from"./panels/dependencies-panel.js";import{PAGE_CHROME_ROWS as L,pageFrame as F,theme as r}from"../../core/tui/panel.js";import{PluginsPanel as H}from"./panels/plugins-panel.js";import{ProviderPanel as O}from"./panels/provider-panel.js";import{PluginEnvPanel as _}from"./panels/plugin-env-panel.js";import{TerminalPanel as z}from"./panels/terminal-panel.js";import{describeEdit as M,planOptionAsAlt as N}from"./terminal-option.js";import{homedir as R}from"node:os";import{cliClient as S}from"../api-client.js";const E=["Providers","Plugins","Plugin env","Dependencies"],j="Option key";class B{static{p(this,"SetupWizard")}bindings;terminalRows;providers;plugins;pluginEnv;dependencies;terminal;steps;step=0;confirming=!1;cachedWidth;cachedHeight;cachedLines;_focused=!1;installedPackageIds;onSubmit;onCancel;constructor(e,i,s,t,n,a,u,o,m,f,d=null){this.bindings=o,this.terminalRows=m,this.installedPackageIds=i;const l=p(()=>this.invalidate(),"invalidate");this.providers=new O(t,n,a,u),this.providers.onChange=l,this.plugins=new H(e,i,l),this.pluginEnv=new _(f,l),this.dependencies=new D(s,l),this.terminal=d===null?void 0:new z(d,l),this.steps=this.terminal===void 0?E:[...E,j]}set focused(e){this._focused=e}get focused(){return this._focused}invalidate(){this.cachedWidth=void 0,this.cachedHeight=void 0,this.cachedLines=void 0}matches(e,i){return $(this.bindings,e,i,(s,t)=>b(s,t))}label(e){const i=this.bindings.gestures(e);return i.length===0?"disabled":v(i[0].split(" > ").pop())}fieldSafeLabel(e){const i=this.bindings.gestures(e).filter(s=>{if(s.includes(" > "))return!0;const t=s.split("+").pop();return!(t==="up"||t==="down"||t==="left"||t==="right")&&(t.length>1||s.includes("+"))});return i.length===0?"Disabled":i.map(v).join(" / ")}setStep(e){e===2&&this.step!==2&&this.pluginEnv.setFields(C(this.plugins.selected)),this.step=e,this.invalidate()}moveStep(e){this.setStep((this.step+e+this.steps.length)%this.steps.length)}advance(){this.step===this.steps.length-1?this.finalize():(this.step!==2||this.pluginEnv.complete)&&this.moveStep(1)}cancel(){if(this.confirming){this.confirming=!1,this.invalidate();return}this.onCancel?.()}dispose(){this.providers.dispose()}hasPendingInstalls(){return this.plugins.selected.some(e=>!this.installedPackageIds.has(e.id))||this.dependencies.selected.length>0||this.terminal?.selectedEdit!==void 0}buildSubmission(){return{packages:[...this.plugins.selected],installedPackageIds:new Set(this.installedPackageIds),systemDeps:[...this.dependencies.selected],pluginEnv:new Map(this.pluginEnv.values),...this.terminal?.selectedEdit===void 0?{}:{terminalEdit:this.terminal.selectedEdit}}}finalize(){if(this.confirming||!this.hasPendingInstalls()){this.onSubmit?.(this.buildSubmission());return}this.confirming=!0,this.invalidate()}currentPanel(){return this.step===0?this.providers:this.step===1?this.plugins:this.step===2?this.pluginEnv:this.step===3?this.dependencies:this.terminal}handleInput(e){const i=this.currentPanel(),s=p((n,a)=>this.matches(n,a),"match");if(this.step===0&&this.providers.isNestedFlowActive()){i.handleInput(e,s)&&this.invalidate();return}if(this.confirming){this.matches("crtr.setup.confirm.accept",e)?this.onSubmit?.(this.buildSubmission()):this.matches("crtr.setup.confirm.back",e)&&(this.confirming=!1,this.invalidate());return}if(this.step===2&&this.pluginEnv.handleInput(e)){this.invalidate();return}if(this.matches("crtr.setup.cancel",e)){this.cancel();return}if(this.matches("crtr.setup.tab-next",e)){if(this.step===2&&!this.pluginEnv.complete)return;this.moveStep(1);return}if(this.matches("crtr.setup.tab-previous",e)){this.moveStep(-1);return}if(i.handleInput(e,s)){this.invalidate();return}this.matches("crtr.setup.advance",e)&&this.advance()}renderTrail(e){const s=this.steps.map((t,n)=>{if(n===this.step)return r.bg("selectedBg",` ${n+1} ${t} `);const a=n<this.step?r.fg("success","\u2713"):`${n+1}`;return r.fg("dim",` ${a} ${t} `)}).join(r.fg("dim","\u203A"));return g(s)<=e?[c(s,e),""]:[c(`${r.fg("dim",`Step ${this.step+1} of ${this.steps.length}`)} ${r.fg("accent",r.bold(this.steps[this.step]))}`,e),""]}footer(e){const i=`${this.fieldSafeLabel("crtr.setup.tab-next")}/${this.fieldSafeLabel("crtr.setup.tab-previous")} step \xB7 ${this.label("crtr.setup.cancel")} cancel`,s=k(this.bindings,"crtr.setup.list-down","crtr.setup.list-up");let t;this.confirming?t=`${this.label("crtr.setup.confirm.accept")} confirm \xB7 ${this.label("crtr.setup.confirm.back")} go back`:this.step===0?t=this.providers.isNestedFlowActive()?"OAuth in progress \xB7 esc cancel":`${s} select \xB7 a add \xB7 p prefer \xB7 r rename \xB7 l re-login \xB7 x remove \xB7 ${this.label("crtr.setup.advance")} next`:this.step===1?t=`${s} move \xB7 ${this.label("crtr.setup.toggle")} toggle \xB7 ${this.label("crtr.setup.details")} details \xB7 ${this.label("crtr.setup.advance")} next`:this.step===2?t=`type value \xB7 Enter save/skip \xB7 ${this.pluginEnv.complete?`${this.label("crtr.setup.advance")} next`:"complete keys to continue"}`:this.step===3?t=`${s} move \xB7 ${this.label("crtr.setup.toggle")} toggle \xB7 ${this.label("crtr.setup.advance")} ${this.steps.length>4?"next":"finish"}`:t=`${this.terminal?.canApply?`${this.label("crtr.setup.toggle")} apply for me \xB7 `:""}${this.label("crtr.setup.advance")} finish`;const n=e-g(t)-g(i);return n>=2?`${r.fg("dim",t)}${" ".repeat(n)}${r.fg("dim",i)}`:r.fg("dim",t)}renderConfirm(e){const i=this.buildSubmission(),s=[c(r.fg("warning",r.bold("Confirm installs")),e),""];if(i.packages.length===0&&i.systemDeps.length===0&&i.terminalEdit===void 0)return[...s,c(r.fg("success",`Nothing to install; ${this.label("crtr.setup.confirm.accept")} finish.`),e)];if(i.packages.length){s.push(c(r.fg("accent","Packages"),e));for(const t of i.packages)s.push(c(` \u2022 ${t.name} ${r.fg("dim","\u2192")} ${this.installedPackageIds.has(t.id)?r.fg("success","skip (already installed)"):r.fg("muted",A(t))}`,e))}if(i.systemDeps.length){s.push(c(r.fg("accent","System deps"),e));for(const t of i.systemDeps)s.push(c(` \u2022 ${t.tool} ${r.fg("dim","\u2192")} ${r.fg("muted",t.command??t.hint)}`,e))}if(i.terminalEdit!==void 0){s.push(c(r.fg("accent","Terminal config"),e));for(const t of M(i.terminalEdit))s.push(c(r.fg("muted",` ${t}`),e))}return s}render(e){const i=this.step===0,s=this.terminalRows();if(!i&&this.cachedLines&&this.cachedWidth===e&&this.cachedHeight===s)return this.cachedLines;const t=this.currentPanel(),n=Math.max(1,s-L),a=this.confirming||n<=2?[]:this.renderTrail(e),u=Math.max(1,n-a.length),o=F({width:e,height:s,title:"crouter setup",meta:this.confirming?"review":`step ${this.step+1} of ${this.steps.length}`,body:[...a,...this.confirming?this.renderConfirm(e):t.render(e,u)],footer:this.footer(e)});return i||(this.cachedWidth=e,this.cachedHeight=s,this.cachedLines=o),o}}function G(){process.stdout.write("\x1B[2J\x1B[H")}p(G,"clearWizardFrame");async function re(){const h=y();let e=!1;if(await x(),!process.stdout.isTTY)return process.stdout.write(T(h)),"skipped";const i=new Set((await S().listAppEnv()).names),s=await W(({tui:n,terminal:a,agentDir:u,runtime:o,registry:m,bindings:f},d)=>{const l=new B(h.manifest,h.installedPackageIds,h.systemPlans,n,u,o,m,f,()=>a.rows,i,N({env:process.env,platform:process.platform,home:R()}));return l.onCancel=d.cancel,l.onSubmit=d.submit,l},(n,a)=>n===""?(e=!0,!0):n.length>0&&n.charCodeAt(0)<32&&$(a,"crtr.setup.cancel",n,(u,o)=>b(u,o)));if(G(),e){const n=new Error("Interrupted");throw n.name="AbortError",n}if(s===void 0)return"skipped";for(const[n,a]of s.pluginEnv)await S().setAppEnv(n,a);const t=await I(s);return process.stdout.write(w(t)),"completed"}p(re,"runSetup");export{B as SetupWizard,re as runSetup};
1
+ var P=Object.defineProperty;var p=(h,e)=>P(h,"name",{value:e,configurable:!0});import{matchesKey as b,truncateToWidth as o,visibleWidth as g}from"@earendil-works/pi-tui";import{formatGesture as v,formatMovePair as k,matchesPiTuiInput as $}from"../../core/keybindings/index.js";import{buildSetupInitialState as y,executeSetupSubmission as I,formatSetupExecutionSummary as w,packagePlanAction as A,reconcileInboxFrontDoor as x,renderSetupStaticInstructions as T,setupPluginEnvFields as C}from"./setup-core.js";import{runSetupSettingsProcess as W}from"./setup-settings-runner.js";import{DependenciesPanel as D}from"./panels/dependencies-panel.js";import{PAGE_CHROME_ROWS as F,pageFrame as L,theme as r}from"../../core/tui/panel.js";import{PluginsPanel as H}from"./panels/plugins-panel.js";import{ProviderPanel as O}from"./panels/provider-panel.js";import{PluginEnvPanel as _}from"./panels/plugin-env-panel.js";import{TerminalPanel as N}from"./panels/terminal-panel.js";import{describeEdit as R,planOptionAsAlt as z}from"./terminal-option.js";import{homedir as M}from"node:os";import{cliClient as S}from"../api-client.js";const E=["Providers","Plugins","Plugin env","Dependencies"],j="Option key";class B{static{p(this,"SetupWizard")}bindings;terminalRows;providers;plugins;pluginEnv;dependencies;terminal;steps;step=0;confirming=!1;cachedWidth;cachedHeight;cachedLines;_focused=!1;installedPackageIds;onSubmit;onCancel;constructor(e,i,t,n,s,c,a,l,f,m,d=null){this.bindings=l,this.terminalRows=f,this.installedPackageIds=i;const u=p(()=>this.invalidate(),"invalidate");this.providers=new O(n,s,c,a),this.providers.onChange=u,this.plugins=new H(e,i,u),this.pluginEnv=new _(m,u),this.dependencies=new D(t,u),this.terminal=d===null?void 0:new N(d,u),this.steps=this.terminal===void 0?E:[...E,j]}set focused(e){this._focused=e}get focused(){return this._focused}invalidate(){this.cachedWidth=void 0,this.cachedHeight=void 0,this.cachedLines=void 0}matches(e,i){return $(this.bindings,e,i,(t,n)=>b(t,n))}label(e){const i=this.bindings.gestures(e);return i.length===0?"disabled":v(i[0].split(" > ").pop())}fieldSafeLabel(e){const i=this.bindings.gestures(e).filter(t=>{if(t.includes(" > "))return!0;const n=t.split("+").pop();return!(n==="up"||n==="down"||n==="left"||n==="right")&&(n.length>1||t.includes("+"))});return i.length===0?"Disabled":i.map(v).join(" / ")}setStep(e){e===2&&this.step!==2&&this.pluginEnv.setFields(C(this.plugins.selected)),this.step=e,this.invalidate()}moveStep(e){this.setStep((this.step+e+this.steps.length)%this.steps.length)}advance(){this.step===this.steps.length-1?this.finalize():(this.step!==2||this.pluginEnv.complete)&&this.moveStep(1)}cancel(){if(this.confirming){this.confirming=!1,this.invalidate();return}this.onCancel?.()}dispose(){this.providers.dispose()}hasPendingInstalls(){return this.plugins.selected.some(e=>!this.installedPackageIds.has(e.id))||this.dependencies.selected.length>0||this.terminal?.selectedEdit!==void 0}buildSubmission(){return{packages:[...this.plugins.selected],installedPackageIds:new Set(this.installedPackageIds),systemDeps:[...this.dependencies.selected],pluginEnv:new Map(this.pluginEnv.values),...this.terminal?.selectedEdit===void 0?{}:{terminalEdit:this.terminal.selectedEdit}}}finalize(){if(this.confirming||!this.hasPendingInstalls()){this.onSubmit?.(this.buildSubmission());return}this.confirming=!0,this.invalidate()}currentPanel(){return this.step===0?this.providers:this.step===1?this.plugins:this.step===2?this.pluginEnv:this.step===3?this.dependencies:this.terminal}handleInput(e){const i=this.currentPanel(),t=p((s,c)=>this.matches(s,c),"match");if(this.step===0&&this.providers.isNestedFlowActive()){i.handleInput(e,t)&&this.invalidate();return}if(this.confirming){this.matches("crtr.setup.confirm.accept",e)?this.onSubmit?.(this.buildSubmission()):this.matches("crtr.setup.confirm.back",e)&&(this.confirming=!1,this.invalidate());return}if(this.step===2&&this.pluginEnv.handleInput(e)){this.invalidate();return}if(this.matches("crtr.setup.cancel",e)){this.cancel();return}if(this.matches("crtr.setup.tab-next",e)){if(this.step===2&&!this.pluginEnv.complete)return;this.moveStep(1);return}if(this.matches("crtr.setup.tab-previous",e)){this.moveStep(-1);return}if(i.handleInput(e,t)){this.invalidate();return}this.matches("crtr.setup.advance",e)&&this.advance()}renderTrail(e){const t=this.steps.map((n,s)=>{if(s===this.step)return r.bg("selectedBg",` ${s+1} ${n} `);const c=s<this.step?r.fg("success","\u2713"):`${s+1}`;return r.fg("dim",` ${c} ${n} `)}).join(r.fg("dim","\u203A"));return g(t)<=e?[o(t,e),""]:[o(`${r.fg("dim",`Step ${this.step+1} of ${this.steps.length}`)} ${r.fg("accent",r.bold(this.steps[this.step]))}`,e),""]}footer(e){const i=`${this.fieldSafeLabel("crtr.setup.tab-next")}/${this.fieldSafeLabel("crtr.setup.tab-previous")} step \xB7 ${this.label("crtr.setup.cancel")} cancel`,t=k(this.bindings,"crtr.setup.list-down","crtr.setup.list-up"),n=this.label("crtr.setup.advance");let s,c;if(this.confirming)s=`${this.label("crtr.setup.confirm.accept")} confirm \xB7 ${this.label("crtr.setup.confirm.back")} go back`;else if(this.step===0){const a=this.providers.isAddRowSelected()?`${n} add provider`:`${n} next`;s=this.providers.isNestedFlowActive()?"OAuth in progress \xB7 esc cancel":`${t} select \xB7 ${a} \xB7 a add \xB7 p prefer \xB7 r rename \xB7 l re-login \xB7 x remove`,this.providers.isNestedFlowActive()||(c=`${t} select \xB7 ${a} \xB7 a add \xB7 l re-login`)}else this.step===1?s=`${t} move \xB7 ${this.label("crtr.setup.toggle")} toggle \xB7 ${this.label("crtr.setup.details")} details \xB7 ${this.label("crtr.setup.advance")} next`:this.step===2?s=`type value \xB7 Enter save/skip \xB7 ${this.pluginEnv.complete?`${this.label("crtr.setup.advance")} next`:"complete keys to continue"}`:this.step===3?s=`${t} move \xB7 ${this.label("crtr.setup.toggle")} toggle \xB7 ${this.label("crtr.setup.advance")} ${this.steps.length>4?"next":"finish"}`:s=`${this.terminal?.canApply?`${this.label("crtr.setup.toggle")} apply for me \xB7 `:""}${this.label("crtr.setup.advance")} finish`;for(const a of c===void 0?[s]:[s,c]){const l=e-g(a)-g(i);if(l>=2)return`${r.fg("dim",a)}${" ".repeat(l)}${r.fg("dim",i)}`}return r.fg("dim",c??s)}renderConfirm(e){const i=this.buildSubmission(),t=[o(r.fg("warning",r.bold("Confirm installs")),e),""];if(i.packages.length===0&&i.systemDeps.length===0&&i.terminalEdit===void 0)return[...t,o(r.fg("success",`Nothing to install; ${this.label("crtr.setup.confirm.accept")} finish.`),e)];if(i.packages.length){t.push(o(r.fg("accent","Packages"),e));for(const n of i.packages)t.push(o(` \u2022 ${n.name} ${r.fg("dim","\u2192")} ${this.installedPackageIds.has(n.id)?r.fg("success","skip (already installed)"):r.fg("muted",A(n))}`,e))}if(i.systemDeps.length){t.push(o(r.fg("accent","System deps"),e));for(const n of i.systemDeps)t.push(o(` \u2022 ${n.tool} ${r.fg("dim","\u2192")} ${r.fg("muted",n.command??n.hint)}`,e))}if(i.terminalEdit!==void 0){t.push(o(r.fg("accent","Terminal config"),e));for(const n of R(i.terminalEdit))t.push(o(r.fg("muted",` ${n}`),e))}return t}render(e){const i=this.step===0,t=this.terminalRows();if(!i&&this.cachedLines&&this.cachedWidth===e&&this.cachedHeight===t)return this.cachedLines;const n=this.currentPanel(),s=Math.max(1,t-F),c=this.confirming||s<=2?[]:this.renderTrail(e),a=Math.max(1,s-c.length),l=L({width:e,height:t,title:"crouter setup",meta:this.confirming?"review":`step ${this.step+1} of ${this.steps.length}`,body:[...c,...this.confirming?this.renderConfirm(e):n.render(e,a)],footer:this.footer(e)});return i||(this.cachedWidth=e,this.cachedHeight=t,this.cachedLines=l),l}}function G(){process.stdout.write("\x1B[2J\x1B[H")}p(G,"clearWizardFrame");async function re(){const h=y();let e=!1;if(await x(),!process.stdout.isTTY)return process.stdout.write(T(h)),"skipped";const i=new Set((await S().listAppEnv()).names),t=await W(({tui:s,terminal:c,agentDir:a,runtime:l,registry:f,bindings:m},d)=>{const u=new B(h.manifest,h.installedPackageIds,h.systemPlans,s,a,l,f,m,()=>c.rows,i,z({env:process.env,platform:process.platform,home:M()}));return u.onCancel=d.cancel,u.onSubmit=d.submit,u},(s,c)=>s===""?(e=!0,!0):s.length>0&&s.charCodeAt(0)<32&&$(c,"crtr.setup.cancel",s,(a,l)=>b(a,l)));if(G(),e){const s=new Error("Interrupted");throw s.name="AbortError",s}if(t===void 0)return"skipped";for(const[s,c]of t.pluginEnv)await S().setAppEnv(s,c);const n=await I(t);return process.stdout.write(w(n)),"completed"}p(re,"runSetup");export{B as SetupWizard,re as runSetup};
@@ -0,0 +1,8 @@
1
+ ---
2
+ title: Quick setup
3
+ description: Register an app, sign a person in with Northlight, and start a run on their runtime.
4
+ ---
5
+
6
+ # Quick setup
7
+
8
+ This page is a placeholder. The quick setup path is written in a later change.
@@ -7,6 +7,18 @@ description: Behavior changes in @north-light/sdk that an app must act on, newes
7
7
 
8
8
  Changes to `@north-light/sdk` that can change what an existing app sees. Newest first.
9
9
 
10
+ ## 0.3.472
11
+
12
+ ### `npx @north-light/sdk init`, `skill` and `env --client-id` (additive, no app change)
13
+
14
+ The `crouter-sdk` bin gains three commands that need neither crtr nor a joined machine:
15
+
16
+ - `init [dir] [--agent claude|agents|all] [--global-skill]` scaffolds an app in an empty or new directory (`package.json` with `@north-light/sdk` pinned to the CLI's own version plus `tsx`, `server.ts`, `.gitignore`, `local/app.env`, a signing key in `local/app-key.json`) and installs the `northlight` Agent Skill into `.agents/skills` and `.claude/skills`. In a directory that already has a `package.json` it writes no app code: it runs `npm i --save-exact @north-light/sdk@<this version>`, makes a key if `local/app-key.json` is missing, and installs the skill. It never overwrites a file; it exits 1 and names the file it refused.
17
+ - `skill [--agent claude|agents|all] [--global] [--print]` writes the skill that ships in the package, replacing an older copy. The skill's `metadata.sdk-version` is the package version; run `skill` again after changing the pinned SDK version.
18
+ - `env --client-id <id> [--origin <url>] [--issuer <url>] [--out <path>]` writes `CROUTER_ISSUER`, `CROUTER_CLIENT_ID` and `APP_ORIGIN` into `local/app.env` and keeps every other line, with no network call. `env --app <id>` still reads them through crtr; passing both is a usage error.
19
+
20
+ `keygen` is unchanged. The package still has one bin, so `npx @north-light/sdk <command>` keeps working. A bare `npx @north-light/sdk`, `--help` and an unknown command print the command list (exit 1 for the unknown command).
21
+
10
22
  ## 0.3.462
11
23
 
12
24
  ### `ProfileDTO.memory_path` is removed (profile objects carry only `profile_path`)
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@north-light/cli",
3
- "version": "0.3.471",
3
+ "version": "0.3.472",
4
4
  "description": "crtr — agent runtime with memory, plugins, and marketplaces",
5
5
  "type": "module",
6
6
  "main": "dist/index.js",
@@ -93,7 +93,7 @@
93
93
  "activate:pull": "git pull && npm install && npm run activate",
94
94
  "build:api": "npm run build:identity && tsc -p packages/crouter-api/tsconfig.json",
95
95
  "build:env-docker": "tsc -p packages/crouter-env-docker/tsconfig.json",
96
- "build:sdk": "npm run build:api && npm run build:identity && tsc -p packages/crouter-sdk/tsconfig.json",
96
+ "build:sdk": "npm run build:api && npm run build:identity && npm run build --workspace packages/crouter-sdk",
97
97
  "build:plugin": "tsc -p packages/crouter-plugin/tsconfig.json",
98
98
  "typecheck:pi-packages": "npx tsc -p src/builtin-pi-packages/pi-crtr-extensions/tsconfig.json",
99
99
  "test:runtime-packaging": "node --test scripts/runtime-smoke.test.mjs scripts/pack-args.test.mjs scripts/ensure-native-linux.test.mjs scripts/release-version.test.mjs",
@@ -137,7 +137,7 @@
137
137
  },
138
138
  "license": "UNLICENSED",
139
139
  "dependencies": {
140
- "@north-light/identity": "0.3.471",
140
+ "@north-light/identity": "0.3.472",
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.471",
3
+ "version": "0.3.472",
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.471",
3
+ "version": "0.3.472",
4
4
  "lockfileVersion": 3,
5
5
  "requires": true,
6
6
  "packages": {
7
7
  "": {
8
8
  "name": "@north-light/cli",
9
- "version": "0.3.471",
9
+ "version": "0.3.472",
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.471",
21
+ "@north-light/identity": "0.3.472",
22
22
  "cron-parser": "^5.6.0",
23
23
  "esbuild": "^0.27.7",
24
24
  "jose": "^6.2.12",
@@ -50,6 +50,8 @@
50
50
  "name": "@north-light/docs",
51
51
  "version": "0.0.0",
52
52
  "dependencies": {
53
+ "@fontsource-variable/geist": "^5.3.0",
54
+ "@fontsource-variable/geist-mono": "^5.3.0",
53
55
  "@fontsource-variable/inter": "^5.3.0",
54
56
  "@tanstack/react-router": "^1.170.41",
55
57
  "@tanstack/react-start": "^1.168.60",
@@ -2469,6 +2471,24 @@
2469
2471
  "integrity": "sha512-HpCo8tmWzLVad5s2d19EhAz5zqrrQ6s69qd6moPMQvkOuSwDT1YgRfWSVuc4ennqrgv3OHppiOGMQ7oC13yIww==",
2470
2472
  "license": "MIT"
2471
2473
  },
2474
+ "node_modules/@fontsource-variable/geist": {
2475
+ "version": "5.3.0",
2476
+ "resolved": "https://registry.npmjs.org/@fontsource-variable/geist/-/geist-5.3.0.tgz",
2477
+ "integrity": "sha512-j0m+vLQuG5XAYoHtGCVu0spvlGreR3EzpECUVzkFmI1mTVnAO38l/NEPDCFgZ177JxzYJCLSmTQibIiYPilGrA==",
2478
+ "license": "OFL-1.1",
2479
+ "funding": {
2480
+ "url": "https://github.com/sponsors/ayuhito"
2481
+ }
2482
+ },
2483
+ "node_modules/@fontsource-variable/geist-mono": {
2484
+ "version": "5.3.0",
2485
+ "resolved": "https://registry.npmjs.org/@fontsource-variable/geist-mono/-/geist-mono-5.3.0.tgz",
2486
+ "integrity": "sha512-vBbuwDEo9AkrqADMXOrlAR3DFcJi4/JxeuU43FoiQERnNwsfXNnvxvReZG02cQKmyk4DZkZdBZX3oTDvy2zBAw==",
2487
+ "license": "OFL-1.1",
2488
+ "funding": {
2489
+ "url": "https://github.com/sponsors/ayuhito"
2490
+ }
2491
+ },
2472
2492
  "node_modules/@fontsource-variable/inter": {
2473
2493
  "version": "5.3.0",
2474
2494
  "resolved": "https://registry.npmjs.org/@fontsource-variable/inter/-/inter-5.3.0.tgz",
@@ -12095,17 +12115,17 @@
12095
12115
  },
12096
12116
  "packages/crouter-api": {
12097
12117
  "name": "@north-light/api",
12098
- "version": "0.3.471",
12118
+ "version": "0.3.472",
12099
12119
  "license": "UNLICENSED"
12100
12120
  },
12101
12121
  "packages/crouter-env-docker": {
12102
12122
  "name": "@north-light/env-docker",
12103
- "version": "0.3.471",
12123
+ "version": "0.3.472",
12104
12124
  "license": "UNLICENSED"
12105
12125
  },
12106
12126
  "packages/crouter-identity": {
12107
12127
  "name": "@north-light/identity",
12108
- "version": "0.3.471",
12128
+ "version": "0.3.472",
12109
12129
  "license": "UNLICENSED",
12110
12130
  "dependencies": {
12111
12131
  "jose": "^6.2.1"
@@ -12113,20 +12133,20 @@
12113
12133
  },
12114
12134
  "packages/crouter-plugin": {
12115
12135
  "name": "@north-light/plugin",
12116
- "version": "0.3.471",
12136
+ "version": "0.3.472",
12117
12137
  "license": "UNLICENSED",
12118
12138
  "dependencies": {
12119
- "@north-light/api": "0.3.471",
12120
- "@north-light/identity": "0.3.471"
12139
+ "@north-light/api": "0.3.472",
12140
+ "@north-light/identity": "0.3.472"
12121
12141
  }
12122
12142
  },
12123
12143
  "packages/crouter-sdk": {
12124
12144
  "name": "@north-light/sdk",
12125
- "version": "0.3.471",
12145
+ "version": "0.3.472",
12126
12146
  "license": "UNLICENSED",
12127
12147
  "dependencies": {
12128
- "@north-light/api": "0.3.471",
12129
- "@north-light/identity": "0.3.471",
12148
+ "@north-light/api": "0.3.472",
12149
+ "@north-light/identity": "0.3.472",
12130
12150
  "jose": "^6.2.1"
12131
12151
  },
12132
12152
  "bin": {