@north-light/cli 0.3.541 → 0.3.542

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,5 +1,5 @@
1
1
  /** The contract level this build serves and requires. Written by `scripts/contract.mjs release`; never edit by hand. */
2
- export declare const CONTRACT_LEVEL = "1.28";
2
+ export declare const CONTRACT_LEVEL = "1.29";
3
3
  /** Request header naming the one contract level the caller needs, e.g. `1.3`. Optional: absent means no check. */
4
4
  export declare const REQUIRED_CONTRACT_HEADER = "Crouter-Required-Contract";
5
5
  /** Response header listing the contract levels the server serves, comma-separated, one per major, e.g. `1.3`. */
@@ -1 +1 @@
1
- var c=Object.defineProperty;var e=(r,t)=>c(r,"name",{value:t,configurable:!0});const f="1.28",i="Crouter-Required-Contract",p="Crouter-Contract";function l(r){const t=/^(\d+)\.(\d+)$/.exec(r.trim());return t===null?null:{major:Number(t[1]),minor:Number(t[2])}}e(l,"parseContractLevel");function a(r){return r==null?[]:r.split(",").map(t=>l(t)).filter(t=>t!==null)}e(a,"parseServedContracts");function s(r,t){const n=l(r);return n===null?!1:(typeof t=="string"||t===null||t===void 0?a(t):t).some(u=>u.major===n.major&&u.minor>=n.minor)}e(s,"contractSatisfies");function C(r,t,n={}){if(r===void 0)return null;if(l(r)===null)return{status:400,code:"invalid_request",param:i,message:`${i} must be a contract level like 1.0.`};if(s(r,t))return null;const o=r.trim();return{status:426,code:"runtime_version_unsupported",message:t===null||a(t).length===0?`The runtime did not name its contract level; the caller requires contract ${o} or later. Roll the runtime forward.`:`The runtime serves contract ${t}; the caller requires contract ${o} or later within the same major. Roll the runtime forward, or pin an SDK whose crouterContract the runtime serves.`,details:{sdk_version:(n.legacyMinimum??"").trim(),runtime_version:n.runtimeVersion??null,required_contract:o,runtime_contract:t}}}e(C,"contractRefusal");export{p as CONTRACT_HEADER,f as CONTRACT_LEVEL,i as REQUIRED_CONTRACT_HEADER,C as contractRefusal,s as contractSatisfies,l as parseContractLevel,a as parseServedContracts};
1
+ var c=Object.defineProperty;var e=(r,t)=>c(r,"name",{value:t,configurable:!0});const f="1.29",i="Crouter-Required-Contract",p="Crouter-Contract";function l(r){const t=/^(\d+)\.(\d+)$/.exec(r.trim());return t===null?null:{major:Number(t[1]),minor:Number(t[2])}}e(l,"parseContractLevel");function a(r){return r==null?[]:r.split(",").map(t=>l(t)).filter(t=>t!==null)}e(a,"parseServedContracts");function s(r,t){const n=l(r);return n===null?!1:(typeof t=="string"||t===null||t===void 0?a(t):t).some(u=>u.major===n.major&&u.minor>=n.minor)}e(s,"contractSatisfies");function C(r,t,n={}){if(r===void 0)return null;if(l(r)===null)return{status:400,code:"invalid_request",param:i,message:`${i} must be a contract level like 1.0.`};if(s(r,t))return null;const o=r.trim();return{status:426,code:"runtime_version_unsupported",message:t===null||a(t).length===0?`The runtime did not name its contract level; the caller requires contract ${o} or later. Roll the runtime forward.`:`The runtime serves contract ${t}; the caller requires contract ${o} or later within the same major. Roll the runtime forward, or pin an SDK whose crouterContract the runtime serves.`,details:{sdk_version:(n.legacyMinimum??"").trim(),runtime_version:n.runtimeVersion??null,required_contract:o,runtime_contract:t}}}e(C,"contractRefusal");export{p as CONTRACT_HEADER,f as CONTRACT_LEVEL,i as REQUIRED_CONTRACT_HEADER,C as contractRefusal,s as contractSatisfies,l as parseContractLevel,a as parseServedContracts};
@@ -9,6 +9,14 @@ 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.542
13
+
14
+ The directory's account page reads and removes individual AI subscription accounts. Additive: no app-facing request or response changes.
15
+
16
+ - `runtime.vendor-status` (directory token) carries an optional `accounts` field: per vendor, each signed-in account's `id`, `label`, `state` (`connected`, `needs_reconnecting`, `rate_limited`) and, when rate limited, `cooling_until`.
17
+ - New `runtime.vendor-account-remove` (`POST /v1/runtime/vendor-account-remove`, directory token with purpose `vendor_account_remove`, body `{ vendor, account_id }`).
18
+ - A refresh token the vendor rejects (`invalid_grant`) on the daemon's model route now flags the account as needing reconnecting, as it already did on a node's own turns.
19
+
12
20
  ## 0.3.539
13
21
 
14
22
  `exchangeIdentity` now returns the verified identity when the directory's token answer also carries a runtime connection. It used to throw `oauth_exchange_mismatch`, so no member could sign in to an app held by a team with a runtime grant (the directory gives that app a connection on every sign-in). The SDK revokes the unneeded refresh token best-effort; revocation removes only that token, never the grant. `exchangeCode` still refuses a sign-in-only answer.
@@ -1,7 +1,7 @@
1
1
  import { spawn } from 'node:child_process';
2
2
  import { createAssistantMessageEventStream, } from '@earendil-works/pi-ai';
3
3
  import { anthropicMessagesApi, openAICodexResponsesApi, openAIResponsesApi } from '@earendil-works/pi-ai/compat';
4
- import { ANTHROPIC_PROVIDER_ID, OPENAI_CHATGPT_PROVIDER_ID, OPENAI_CODEX_PROVIDER_ID, INVALID_REFRESH_TOKEN_BACKOFF_MS, openAIDeviceId, MAX_RATE_LIMIT_COOLDOWN_MS, coolingUntilFor, formatCooldowns, formatStatusLine, getProviderLabel, isManagedProvider, isInvalidRefreshTokenError, addSubscription, enrichManagedLoginIdentity, markSubscriptionAuthenticationFailed, markSubscriptionRateLimited, markSubscriptionSuccess, retryAfterMsFromHeaders, retryAfterMsFromError, promoteSubscription, readRotationConfig, readSubscriptionPool, refreshSubscriptionCredential, removeManagedAccount, resolveProviderCandidates, upsertSubscriptionWithUniqueAccount, subscriptionNeedsSuccessWrite, } from '../../../core/subscription-state.js';
4
+ import { ANTHROPIC_PROVIDER_ID, OPENAI_CHATGPT_PROVIDER_ID, OPENAI_CODEX_PROVIDER_ID, openAIDeviceId, MAX_RATE_LIMIT_COOLDOWN_MS, coolingUntilFor, formatCooldowns, formatStatusLine, getProviderLabel, isManagedProvider, isInvalidRefreshTokenError, addSubscription, enrichManagedLoginIdentity, markSubscriptionRateLimited, markSubscriptionSuccess, retryAfterMsFromHeaders, retryAfterMsFromError, promoteSubscription, readRotationConfig, readSubscriptionPool, refreshSubscriptionCredential, removeManagedAccount, resolveProviderCandidates, upsertSubscriptionWithUniqueAccount, subscriptionNeedsSuccessWrite, } from '../../../core/subscription-state.js';
5
5
  import { classifyRateLimit, describeRateLimitScope, rateLimitHeaders } from '../../../core/rate-limit-scope.js';
6
6
  import { readMergedLaunchConfig } from '../../../core/config.js';
7
7
  import { expandModelCandidates, modelRequestFromConfig, probeRouteAvailability } from '../../../core/model-routes.js';
@@ -732,8 +732,6 @@ async function runManagedProvider(state, model, context, options, stream) {
732
732
  state.runtimeContext?.ui.notify(`${getProviderLabel(providerId)} re-authentication failed: ${loginError instanceof Error ? loginError.message : String(loginError)}`, 'error');
733
733
  }
734
734
  if (!reauthenticated) {
735
- const attemptAt = Date.now();
736
- await recordSubscriptionMutation(`recording ${getProviderLabel(providerId)} authentication failure`, () => markSubscriptionAuthenticationFailed(providerId, credential.label, credential, INVALID_REFRESH_TOKEN_BACKOFF_MS, attemptAt));
737
735
  authFailures.add(`${providerId}/${credential.label}`);
738
736
  continue;
739
737
  }
@@ -17,7 +17,6 @@ import {
17
17
  ANTHROPIC_PROVIDER_ID,
18
18
  OPENAI_CHATGPT_PROVIDER_ID,
19
19
  OPENAI_CODEX_PROVIDER_ID,
20
- INVALID_REFRESH_TOKEN_BACKOFF_MS,
21
20
  openAIDeviceId,
22
21
  MAX_RATE_LIMIT_COOLDOWN_MS,
23
22
  coolingUntilFor,
@@ -28,7 +27,6 @@ import {
28
27
  isInvalidRefreshTokenError,
29
28
  addSubscription,
30
29
  enrichManagedLoginIdentity,
31
- markSubscriptionAuthenticationFailed,
32
30
  markSubscriptionRateLimited,
33
31
  markSubscriptionSuccess,
34
32
  retryAfterMsFromHeaders,
@@ -940,8 +938,6 @@ async function runManagedProvider(
940
938
  state.runtimeContext?.ui.notify(`${getProviderLabel(providerId)} re-authentication failed: ${loginError instanceof Error ? loginError.message : String(loginError)}`, 'error');
941
939
  }
942
940
  if (!reauthenticated) {
943
- const attemptAt = Date.now();
944
- await recordSubscriptionMutation(`recording ${getProviderLabel(providerId)} authentication failure`, () => markSubscriptionAuthenticationFailed(providerId, credential.label, credential, INVALID_REFRESH_TOKEN_BACKOFF_MS, attemptAt));
945
941
  authFailures.add(`${providerId}/${credential.label}`);
946
942
  continue;
947
943
  }