sprag-cli 3.78.0 → 3.79.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "sprag-cli",
3
- "version": "3.78.0",
3
+ "version": "3.79.0",
4
4
  "description": "Model-delegation router for Claude Code and Codex: lookups, checks and test runs go to cheaper models, documents go in as compact Markdown, and a live statusline shows spend and savings.",
5
5
  "type": "module",
6
6
  "bin": {
@@ -15,7 +15,7 @@ import { pendingPrompts } from '../team-prompts.js';
15
15
  import { memberId } from '../member-id.js';
16
16
  import {
17
17
  loadTeamState, deviceInfo, isJoined, joinTeam, leaveTeam, syncTeam, autoJoin, aggregateDaily, rpc,
18
- teamRulesCachePath, teamSyncDisabled, requestSignInCode, verifySignInCode, createTeam, isSeatLimitError,
18
+ teamRulesCachePath, teamSyncDisabled, requestSignInCode, verifySignInCode, createTeam, isSeatLimitError, isOrgExpiredError,
19
19
  } from '../team-sync.js';
20
20
 
21
21
  const T = {
@@ -40,6 +40,7 @@ const T = {
40
40
  aborted: 'Not joined.',
41
41
  joined: (n) => `Joined team "${n}". Check it with: sprag team status`,
42
42
  seatLimit: 'This organization has no free seat. Ask your organization owner or admin to add seats, then join again.',
43
+ orgExpired: "This organization's paid term has ended, so the server no longer accepts uploads or joins. Ask your organization owner to renew it (sales@sprag.io).",
43
44
  org: 'Organization',
44
45
  seats: (u, l) => `${u}/${l} seats used`,
45
46
  orgCreated: (n, u, l) => `Organization: ${n}${u != null && l != null ? ` (${u}/${l} seats used)` : ''}`,
@@ -105,6 +106,7 @@ const T = {
105
106
  aborted: '참여하지 않았습니다.',
106
107
  joined: (n) => `팀 "${n}" 에 참여했습니다. 확인: sprag team status`,
107
108
  seatLimit: '이 조직에 남은 좌석이 없습니다. 조직 오너나 어드민에게 좌석 추가를 요청한 뒤 다시 참여하세요',
109
+ orgExpired: '조직의 이용 기간이 끝나 서버가 업로드와 참여를 받지 않습니다. 조직 오너에게 연장을 요청하세요(sales@sprag.io)',
108
110
  org: '조직',
109
111
  seats: (u, l) => `좌석 ${u}/${l} 사용 중`,
110
112
  orgCreated: (n, u, l) => `조직: ${n}${u != null && l != null ? ` (좌석 ${u}/${l} 사용 중)` : ''}`,
@@ -284,7 +286,7 @@ export async function run({ args, hasFlag, getArg, version, fetch, interactive,
284
286
  }
285
287
  out(`${m.name}: ${st.displayName}`);
286
288
  out(st.lastSyncAt ? m.lastSync(new Date(st.lastSyncAt).toLocaleString(), st.lastSyncRows || 0) : m.neverSynced);
287
- if (st.lastError) out(`${m.lastError}: ${st.lastError}`);
289
+ if (st.lastError) out(isOrgExpiredError(st.lastError) ? m.orgExpired : `${m.lastError}: ${st.lastError}`);
288
290
  if (hasFlag('--show-payload')) {
289
291
  out(`device: ${JSON.stringify(st.deviceInfo || deviceInfo())}`);
290
292
  out(JSON.stringify(await aggregateDaily(), null, 2));
@@ -336,7 +338,7 @@ export async function run({ args, hasFlag, getArg, version, fetch, interactive,
336
338
  return verb && verb !== 'help' ? process.exit(2) : undefined;
337
339
  }
338
340
  } catch (e) {
339
- console.error(isSeatLimitError(e) ? m.seatLimit : e.message);
341
+ console.error(isSeatLimitError(e) ? m.seatLimit : isOrgExpiredError(e) ? m.orgExpired : e.message);
340
342
  return process.exit(1);
341
343
  }
342
344
  }
package/src/team-sync.js CHANGED
@@ -247,6 +247,9 @@ export class SeatLimitError extends Error {
247
247
 
248
248
  export const isSeatLimitError = (e) => !!e && (e.code === 'SEAT_LIMIT' || /seat limit reached/i.test(String(e.message || '')));
249
249
 
250
+ /** The server refuses uploads and joins 14 days after an organization's paid term ends ('org_expired: ...'). */
251
+ export const isOrgExpiredError = (e) => /\borg_expired\b/.test(String((e && e.message) || e || ''));
252
+
250
253
  /** Local calendar day, same key as stats.js. */
251
254
  function dayKey(ms) {
252
255
  const d = new Date(ms);