shortcutxl 0.3.62 → 0.3.63

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/CHANGELOG.md CHANGED
@@ -1,9 +1,9 @@
1
1
  # Changelog
2
2
 
3
- ## [0.3.62]
3
+ ## [0.3.63]
4
4
 
5
5
  - **Windows runtime security** - Updated the embedded Windows SQLite DLL used by ShortcutXL's bundled Python runtime.
6
- - **Default model update** - Updated the default model to Fable.
6
+ - **Default model update** - Updated the default model to Fable for individual users, while team accounts continue to use Opus 4.8.
7
7
 
8
8
  ## [0.3.61]
9
9
 
@@ -50,13 +50,13 @@
50
50
  "builtBy": "third-party",
51
51
  "verification": "Downloaded from python.org CPython release artifacts; verify upstream SHA/signature before vendoring."
52
52
  },
53
- {
54
- "pattern": "xll/python/sqlite3.dll",
55
- "source": "SQLite official precompiled Windows x64 DLL",
56
- "version": "3.53.2",
57
- "builtBy": "third-party",
58
- "verification": "Downloaded from sqlite.org sqlite-dll-win-x64-3530200.zip; upstream SHA3-256 is b898ced2e0627999d7d0b9d554ea53086a9b165e52ae743277d115dcd39e6868, and vendor-python.ps1 verifies extracted sqlite3.dll SHA256 73b045c910fc19a069bae2e2c7ebb5ea66fe6c85f166535a6e07e09155cd9e6d before copying."
59
- },
53
+ {
54
+ "pattern": "xll/python/sqlite3.dll",
55
+ "source": "SQLite official precompiled Windows x64 DLL",
56
+ "version": "3.53.2",
57
+ "builtBy": "third-party",
58
+ "verification": "Downloaded from sqlite.org sqlite-dll-win-x64-3530200.zip; upstream SHA3-256 is b898ced2e0627999d7d0b9d554ea53086a9b165e52ae743277d115dcd39e6868, and vendor-python.ps1 verifies extracted sqlite3.dll SHA256 73b045c910fc19a069bae2e2c7ebb5ea66fe6c85f166535a6e07e09155cd9e6d before copying."
59
+ },
60
60
  {
61
61
  "pattern": "xll/python/vcruntime*.dll",
62
62
  "source": "Microsoft Visual C++ runtime library bundled with CPython Windows embeddable runtime",
@@ -14,6 +14,7 @@ export declare class ModelRegistry {
14
14
  private customProviderApiKeys;
15
15
  private registeredProviders;
16
16
  private registeredOAuthProviderIds;
17
+ private modelAvailabilityFilter;
17
18
  private loadError;
18
19
  constructor(authStorage: AuthStorage, modelsJsonPath?: string | undefined);
19
20
  /**
@@ -24,6 +25,8 @@ export declare class ModelRegistry {
24
25
  * Get any error from loading models.json (undefined if no error).
25
26
  */
26
27
  getError(): string | undefined;
28
+ setModelAvailabilityFilter(filter?: (model: Model<Api>) => boolean): void;
29
+ private getPolicyAllowedModels;
27
30
  private loadModels;
28
31
  /** Load built-in models and apply provider/model overrides */
29
32
  private loadBuiltInModels;
@@ -169,6 +169,7 @@ export class ModelRegistry {
169
169
  customProviderApiKeys = new Map();
170
170
  registeredProviders = new Map();
171
171
  registeredOAuthProviderIds = new Set();
172
+ modelAvailabilityFilter = () => true;
172
173
  loadError = undefined;
173
174
  constructor(authStorage, modelsJsonPath = join(getAgentDir(), 'models.json')) {
174
175
  this.authStorage = authStorage;
@@ -207,6 +208,12 @@ export class ModelRegistry {
207
208
  getError() {
208
209
  return this.loadError;
209
210
  }
211
+ setModelAvailabilityFilter(filter) {
212
+ this.modelAvailabilityFilter = filter ?? (() => true);
213
+ }
214
+ getPolicyAllowedModels() {
215
+ return this.models.filter((model) => this.modelAvailabilityFilter(model));
216
+ }
210
217
  loadModels() {
211
218
  // Load custom models and overrides from models.json
212
219
  const { models: customModels, overrides, modelOverrides, error } = this.modelsJsonPath
@@ -403,25 +410,28 @@ export class ModelRegistry {
403
410
  * If models.json had errors, returns only built-in models.
404
411
  */
405
412
  getAll() {
406
- return this.models;
413
+ return this.getPolicyAllowedModels();
407
414
  }
408
415
  /**
409
416
  * Get only models that have auth configured.
410
417
  * This is a fast check that doesn't refresh OAuth tokens.
411
418
  */
412
419
  getAvailable() {
413
- return this.models.filter((m) => this.authStorage.hasAuth(m.provider));
420
+ return this.getPolicyAllowedModels().filter((m) => this.authStorage.hasAuth(m.provider));
414
421
  }
415
422
  /**
416
423
  * Find a model by provider and ID.
417
424
  */
418
425
  find(provider, modelId) {
419
- return this.models.find((m) => m.provider === provider && m.id === modelId);
426
+ return this.getPolicyAllowedModels().find((m) => m.provider === provider && m.id === modelId);
420
427
  }
421
428
  /**
422
429
  * Get API key for a model.
423
430
  */
424
431
  async getApiKey(model) {
432
+ if (!this.modelAvailabilityFilter(model)) {
433
+ return undefined;
434
+ }
425
435
  return this.authStorage.getApiKey(model.provider);
426
436
  }
427
437
  /**
@@ -54,6 +54,12 @@ export const defaultModelPerProvider = {
54
54
  opencode: SHORTCUT_MODEL_ID.ClaudeOpus48,
55
55
  'kimi-coding': 'kimi-k2-thinking'
56
56
  };
57
+ function getDefaultModelCandidatesForProvider(provider) {
58
+ if (provider === SHORTCUT_PROVIDER_ID) {
59
+ return [SHORTCUT_MODEL_ID.ClaudeFable5, SHORTCUT_MODEL_ID.ClaudeOpus48];
60
+ }
61
+ return [defaultModelPerProvider[provider]].filter((modelId) => !!modelId);
62
+ }
57
63
  /**
58
64
  * Helper to check if a model ID looks like an alias (no date suffix)
59
65
  * Dates are typically in format: -20241022 or -20250929
@@ -320,10 +326,15 @@ export async function findInitialModel(options) {
320
326
  if (availableModels.length > 0) {
321
327
  // Try to find a default model from known providers
322
328
  for (const provider of Object.keys(defaultModelPerProvider)) {
323
- const defaultId = defaultModelPerProvider[provider];
324
- const match = availableModels.find((m) => m.provider === provider && m.id === defaultId);
325
- if (match) {
326
- return { model: match, thinkingLevel: DEFAULT_THINKING_LEVEL, fallbackMessage: undefined };
329
+ for (const defaultId of getDefaultModelCandidatesForProvider(provider)) {
330
+ const match = availableModels.find((m) => m.provider === provider && m.id === defaultId);
331
+ if (match) {
332
+ return {
333
+ model: match,
334
+ thinkingLevel: DEFAULT_THINKING_LEVEL,
335
+ fallbackMessage: undefined
336
+ };
337
+ }
327
338
  }
328
339
  }
329
340
  // If no default found, use first available
package/dist/cli.js CHANGED
@@ -39508,6 +39508,12 @@ var init_policy = __esm({
39508
39508
  });
39509
39509
 
39510
39510
  // src/model-ids.ts
39511
+ function isShortcutTeamRestrictedModel(model) {
39512
+ return model?.provider === SHORTCUT_PROVIDER_ID && model.id === SHORTCUT_MODEL_ID.ClaudeFable5;
39513
+ }
39514
+ function isShortcutModelAllowedForTeamAccount(model, teamAccount) {
39515
+ return !teamAccount || !isShortcutTeamRestrictedModel(model);
39516
+ }
39511
39517
  function isShortcutFastModeModel(model) {
39512
39518
  return model?.id === SHORTCUT_MODEL_ID.ClaudeOpus48 || model?.id === SHORTCUT_MODEL_ID.Gpt55;
39513
39519
  }
@@ -152736,6 +152742,7 @@ var init_model_registry = __esm({
152736
152742
  customProviderApiKeys = /* @__PURE__ */ new Map();
152737
152743
  registeredProviders = /* @__PURE__ */ new Map();
152738
152744
  registeredOAuthProviderIds = /* @__PURE__ */ new Set();
152745
+ modelAvailabilityFilter = () => true;
152739
152746
  loadError = void 0;
152740
152747
  /**
152741
152748
  * Reload models from disk (built-in + custom from models.json).
@@ -152759,6 +152766,12 @@ var init_model_registry = __esm({
152759
152766
  getError() {
152760
152767
  return this.loadError;
152761
152768
  }
152769
+ setModelAvailabilityFilter(filter2) {
152770
+ this.modelAvailabilityFilter = filter2 ?? (() => true);
152771
+ }
152772
+ getPolicyAllowedModels() {
152773
+ return this.models.filter((model) => this.modelAvailabilityFilter(model));
152774
+ }
152762
152775
  loadModels() {
152763
152776
  const {
152764
152777
  models: customModels,
@@ -152958,25 +152971,28 @@ File: ${modelsJsonPath}`
152958
152971
  * If models.json had errors, returns only built-in models.
152959
152972
  */
152960
152973
  getAll() {
152961
- return this.models;
152974
+ return this.getPolicyAllowedModels();
152962
152975
  }
152963
152976
  /**
152964
152977
  * Get only models that have auth configured.
152965
152978
  * This is a fast check that doesn't refresh OAuth tokens.
152966
152979
  */
152967
152980
  getAvailable() {
152968
- return this.models.filter((m3) => this.authStorage.hasAuth(m3.provider));
152981
+ return this.getPolicyAllowedModels().filter((m3) => this.authStorage.hasAuth(m3.provider));
152969
152982
  }
152970
152983
  /**
152971
152984
  * Find a model by provider and ID.
152972
152985
  */
152973
152986
  find(provider, modelId) {
152974
- return this.models.find((m3) => m3.provider === provider && m3.id === modelId);
152987
+ return this.getPolicyAllowedModels().find((m3) => m3.provider === provider && m3.id === modelId);
152975
152988
  }
152976
152989
  /**
152977
152990
  * Get API key for a model.
152978
152991
  */
152979
152992
  async getApiKey(model) {
152993
+ if (!this.modelAvailabilityFilter(model)) {
152994
+ return void 0;
152995
+ }
152980
152996
  return this.authStorage.getApiKey(model.provider);
152981
152997
  }
152982
152998
  /**
@@ -153143,6 +153159,12 @@ function resolveExactModelRef(availableModels, requested) {
153143
153159
  error: `Ambiguous model "${requested}". Use one of: ${matches.map(formatModelRef).join(", ")}.`
153144
153160
  };
153145
153161
  }
153162
+ function getDefaultModelCandidatesForProvider(provider) {
153163
+ if (provider === SHORTCUT_PROVIDER_ID) {
153164
+ return [SHORTCUT_MODEL_ID.ClaudeFable5, SHORTCUT_MODEL_ID.ClaudeOpus48];
153165
+ }
153166
+ return [defaultModelPerProvider[provider]].filter((modelId) => !!modelId);
153167
+ }
153146
153168
  function isAlias(id) {
153147
153169
  if (id.endsWith("-latest")) return true;
153148
153170
  const datePattern = /-\d{8}$/;
@@ -153339,10 +153361,15 @@ async function findInitialModel(options2) {
153339
153361
  const availableModels = await modelRegistry2.getAvailable();
153340
153362
  if (availableModels.length > 0) {
153341
153363
  for (const provider of Object.keys(defaultModelPerProvider)) {
153342
- const defaultId = defaultModelPerProvider[provider];
153343
- const match2 = availableModels.find((m3) => m3.provider === provider && m3.id === defaultId);
153344
- if (match2) {
153345
- return { model: match2, thinkingLevel: DEFAULT_THINKING_LEVEL, fallbackMessage: void 0 };
153364
+ for (const defaultId of getDefaultModelCandidatesForProvider(provider)) {
153365
+ const match2 = availableModels.find((m3) => m3.provider === provider && m3.id === defaultId);
153366
+ if (match2) {
153367
+ return {
153368
+ model: match2,
153369
+ thinkingLevel: DEFAULT_THINKING_LEVEL,
153370
+ fallbackMessage: void 0
153371
+ };
153372
+ }
153346
153373
  }
153347
153374
  }
153348
153375
  return {
@@ -484102,6 +484129,24 @@ function getFastModeDisabledReasonForUser(userInfo) {
484102
484129
  function resolvePromptEngine(userInfo) {
484103
484130
  return isMogRuntimeEnabledForUser(userInfo) && isMogSdkAvailable() ? "mog" : "com";
484104
484131
  }
484132
+ function applyShortcutModelPolicyForUser(modelRegistry2, userInfo) {
484133
+ const teamAccount = Boolean(userInfo?.teamId);
484134
+ modelRegistry2.setModelAvailabilityFilter(
484135
+ (model) => isShortcutModelAllowedForTeamAccount(model, teamAccount)
484136
+ );
484137
+ }
484138
+ async function moveSessionOffPolicyDeniedModel(session, modelRegistry2) {
484139
+ const currentModel = session?.model;
484140
+ if (!session || !currentModel) return;
484141
+ if (modelRegistry2.find(currentModel.provider, currentModel.id)) return;
484142
+ const availableModels = await modelRegistry2.getAvailable();
484143
+ const fallback = availableModels.find(
484144
+ (model) => model.provider === SHORTCUT_PROVIDER_ID && model.id === SHORTCUT_MODEL_ID.ClaudeOpus48
484145
+ ) ?? availableModels.find((model) => model.provider === SHORTCUT_PROVIDER_ID) ?? availableModels[0];
484146
+ if (fallback) {
484147
+ await session.setModel(fallback);
484148
+ }
484149
+ }
484105
484150
  async function refreshSessionForMogPolicyChange(session) {
484106
484151
  if (!session) return;
484107
484152
  await session.reload();
@@ -484179,6 +484224,7 @@ async function main(args) {
484179
484224
  }
484180
484225
  });
484181
484226
  let shortcutUserInfo = await refreshShortcutUserInfoLoggerContext(authStorage, clientLogger);
484227
+ applyShortcutModelPolicyForUser(modelRegistry2, shortcutUserInfo);
484182
484228
  const mogConfigured = isNewSheetEnabled();
484183
484229
  const mogRuntimeEnabled = isMogRuntimeEnabledForUser(shortcutUserInfo);
484184
484230
  const mogSdkAvailable = mogRuntimeEnabled && isMogSdkAvailable();
@@ -484451,6 +484497,15 @@ async function main(args) {
484451
484497
  });
484452
484498
  if (refreshedShortcutUserInfo !== void 0) {
484453
484499
  shortcutUserInfo = refreshedShortcutUserInfo;
484500
+ applyShortcutModelPolicyForUser(modelRegistry2, shortcutUserInfo);
484501
+ if (parsed.model && sessionOptions.model && !modelRegistry2.find(sessionOptions.model.provider, sessionOptions.model.id)) {
484502
+ console.error(
484503
+ source_default.red(
484504
+ `Model ${sessionOptions.model.provider}/${sessionOptions.model.id} is not available for team accounts.`
484505
+ )
484506
+ );
484507
+ process.exit(1);
484508
+ }
484454
484509
  }
484455
484510
  }
484456
484511
  sessionOptions.fastModeAllowed = isFastModeAllowedForUser(shortcutUserInfo);
@@ -484667,6 +484722,7 @@ async function main(args) {
484667
484722
  const previousMogRuntimeEnabled = isMogRuntimeEnabledForUser(shortcutUserInfo);
484668
484723
  const userInfo = await resolveShortcutUserInfo(authStorage);
484669
484724
  shortcutUserInfo = userInfo;
484725
+ applyShortcutModelPolicyForUser(modelRegistry2, shortcutUserInfo);
484670
484726
  setDefaultEnginePrompts(resolvePromptEngine(shortcutUserInfo));
484671
484727
  const resolvedUserId = userInfo?.userId ?? userId;
484672
484728
  if (userInfo) {
@@ -484689,6 +484745,7 @@ async function main(args) {
484689
484745
  isFastModeAllowedForUser(userInfo),
484690
484746
  getFastModeDisabledReasonForUser(userInfo) ?? "team"
484691
484747
  );
484748
+ await moveSessionOffPolicyDeniedModel(sessionRef, modelRegistry2);
484692
484749
  setRemoteControlTeamAccount(Boolean(userInfo?.teamId));
484693
484750
  if (isMogRuntimeEnabledForUser(shortcutUserInfo) !== previousMogRuntimeEnabled) {
484694
484751
  await refreshSessionForMogPolicyChange(sessionRef);
@@ -484722,6 +484779,7 @@ async function main(args) {
484722
484779
  });
484723
484780
  const previousMogRuntimeEnabled = isMogRuntimeEnabledForUser(shortcutUserInfo);
484724
484781
  shortcutUserInfo = null;
484782
+ applyShortcutModelPolicyForUser(modelRegistry2, shortcutUserInfo);
484725
484783
  setDefaultEnginePrompts(resolvePromptEngine(shortcutUserInfo));
484726
484784
  sessionRef?.setFastModeAllowed(false, "login");
484727
484785
  setRemoteControlTeamAccount(false);
@@ -28,6 +28,7 @@ export interface CreateShortcutXLAgentModelOptions {
28
28
  readonly baseUrl?: string;
29
29
  readonly availableModelIds?: readonly string[];
30
30
  readonly gatewayModelIds?: readonly string[];
31
+ readonly teamAccount?: boolean;
31
32
  }
32
33
  export interface CreateShortcutXLAgentModelRegistryOptions extends CreateShortcutXLAgentModelOptions {
33
34
  getAccessToken?: () => Promise<string | undefined>;
@@ -1,4 +1,4 @@
1
- import { SHORTCUT_MODEL_ID } from '../model-ids.js';
1
+ import { isShortcutModelAllowedForTeamAccount, SHORTCUT_MODEL_ID } from '../model-ids.js';
2
2
  import { createShortcutPublicModelDefinitions, DEFAULT_SHORTCUT_MODEL_ID } from '../shortcut-model-catalog.js';
3
3
  /** Provider tag the registry uses to gate auth and model lookup. */
4
4
  export const ShortcutXLAgentProviderId = {
@@ -27,6 +27,34 @@ function formatGatewayModelName(modelId) {
27
27
  .join(' ');
28
28
  }
29
29
  function createGatewayModel(modelId, baseUrl) {
30
+ if (modelId === 'qwen/qwen3.7-max') {
31
+ return {
32
+ id: modelId,
33
+ name: 'Qwen 3.7 Max',
34
+ api: 'shortcut-llm',
35
+ provider: ShortcutXLAgentProviderId.Shortcut,
36
+ baseUrl,
37
+ reasoning: true,
38
+ input: ['text'],
39
+ cost: { input: 0, output: 0, cacheRead: 0, cacheWrite: 0 },
40
+ contextWindow: 1_000_000,
41
+ maxTokens: 128000
42
+ };
43
+ }
44
+ if (modelId === 'qwen/qwen3.7-plus') {
45
+ return {
46
+ id: modelId,
47
+ name: 'Qwen 3.7 Plus',
48
+ api: 'shortcut-llm',
49
+ provider: ShortcutXLAgentProviderId.Shortcut,
50
+ baseUrl,
51
+ reasoning: true,
52
+ input: ['text', 'image'],
53
+ cost: { input: 0, output: 0, cacheRead: 0, cacheWrite: 0 },
54
+ contextWindow: 1_000_000,
55
+ maxTokens: 128000
56
+ };
57
+ }
30
58
  return {
31
59
  id: modelId,
32
60
  name: formatGatewayModelName(modelId),
@@ -90,8 +118,10 @@ function resolveShortcutXLAgentModel(modelId, options = {}) {
90
118
  : undefined;
91
119
  }
92
120
  const selectableModels = getSelectableModels(models, options);
93
- return (selectableModels.find((model) => model.id === DEFAULT_SHORTCUTXL_AGENT_MODEL_ID) ??
94
- selectableModels[0]);
121
+ const defaultModelId = options.teamAccount
122
+ ? ShortcutXLAgentModelId.ClaudeOpus48
123
+ : DEFAULT_SHORTCUTXL_AGENT_MODEL_ID;
124
+ return selectableModels.find((model) => model.id === defaultModelId) ?? selectableModels[0];
95
125
  }
96
126
  /** Predicate: is this an internal-only model that should never appear in UI selectors? */
97
127
  function isInternalModel(modelId) {
@@ -101,7 +131,9 @@ function getSelectableModels(models, options = {}) {
101
131
  const availableModelIds = options.availableModelIds === undefined
102
132
  ? undefined
103
133
  : new Set(options.availableModelIds.map((modelId) => modelId.trim()).filter(Boolean));
104
- return models.filter((model) => !isInternalModel(model.id) && (!availableModelIds || availableModelIds.has(model.id)));
134
+ return models.filter((model) => !isInternalModel(model.id) &&
135
+ isShortcutModelAllowedForTeamAccount(model, options.teamAccount === true) &&
136
+ (!availableModelIds || availableModelIds.has(model.id)));
105
137
  }
106
138
  /** Build a `AgentModelRegistry` over the ShortcutXL model catalog. */
107
139
  export function createShortcutXLAgentModelRegistry(options = {}) {
package/dist/main.js CHANGED
@@ -60,7 +60,7 @@ import { SHORTCUT_API_HEADERS } from './endpoints.js';
60
60
  import { createLocalAgentSession } from './local/index.js';
61
61
  import { handleConfigCommand, handleShortcutAuthCommand, handleXllStartupStatus, isTruthyEnvFlag, prepareInitialMessage, readPipedStdin, runInteractiveShell, validateAgentMode } from './main-helpers.js';
62
62
  import { getCurrentMode, MODE, setCurrentMode } from './mode-names.js';
63
- import { SHORTCUT_PROVIDER_ID } from './model-ids.js';
63
+ import { isShortcutModelAllowedForTeamAccount, SHORTCUT_MODEL_ID, SHORTCUT_PROVIDER_ID } from './model-ids.js';
64
64
  import { attachSessionUpload, BashApprovalComponent, createApprovalGate, createBatchingApprovalGate, createInteractiveSessionClient, createNetworkPrompt, createPrintModeSessionClient, createSandboxBashTool, createShortySlashCommand, ensureWslSandbox, ExcelApprovalComponent, exportFromFile, FileAccessApprovalComponent, getTraceHooks, hasCustomExtensionUI, initTheme, InteractiveMode, isDistroInstalled, isWsl2Available, KeybindingsManager, runPrintMode, SANDBOX_DISTRO, startCronStatusPolling, startDurableMemoryStatusUpdater, startLoopStatusPolling, startSkillProposalStatusUpdater, stopThemeWatcher, SwitchModeApprovalComponent, TaskSpawnApprovalComponent } from './shell/index.js';
65
65
  import { resolveStartupXll } from './startup/startup-xll.js';
66
66
  import { printTimings, time } from './startup/timings.js';
@@ -354,6 +354,24 @@ function getFastModeDisabledReasonForUser(userInfo) {
354
354
  function resolvePromptEngine(userInfo) {
355
355
  return isMogRuntimeEnabledForUser(userInfo) && isMogSdkAvailable() ? 'mog' : 'com';
356
356
  }
357
+ function applyShortcutModelPolicyForUser(modelRegistry, userInfo) {
358
+ const teamAccount = Boolean(userInfo?.teamId);
359
+ modelRegistry.setModelAvailabilityFilter((model) => isShortcutModelAllowedForTeamAccount(model, teamAccount));
360
+ }
361
+ async function moveSessionOffPolicyDeniedModel(session, modelRegistry) {
362
+ const currentModel = session?.model;
363
+ if (!session || !currentModel)
364
+ return;
365
+ if (modelRegistry.find(currentModel.provider, currentModel.id))
366
+ return;
367
+ const availableModels = await modelRegistry.getAvailable();
368
+ const fallback = availableModels.find((model) => model.provider === SHORTCUT_PROVIDER_ID && model.id === SHORTCUT_MODEL_ID.ClaudeOpus48) ??
369
+ availableModels.find((model) => model.provider === SHORTCUT_PROVIDER_ID) ??
370
+ availableModels[0];
371
+ if (fallback) {
372
+ await session.setModel(fallback);
373
+ }
374
+ }
357
375
  async function refreshSessionForMogPolicyChange(session) {
358
376
  if (!session)
359
377
  return;
@@ -441,6 +459,7 @@ export async function main(args) {
441
459
  }
442
460
  });
443
461
  let shortcutUserInfo = await refreshShortcutUserInfoLoggerContext(authStorage, clientLogger);
462
+ applyShortcutModelPolicyForUser(modelRegistry, shortcutUserInfo);
444
463
  const mogConfigured = isNewSheetEnabled();
445
464
  const mogRuntimeEnabled = isMogRuntimeEnabledForUser(shortcutUserInfo);
446
465
  const mogSdkAvailable = mogRuntimeEnabled && isMogSdkAvailable();
@@ -725,6 +744,13 @@ export async function main(args) {
725
744
  });
726
745
  if (refreshedShortcutUserInfo !== undefined) {
727
746
  shortcutUserInfo = refreshedShortcutUserInfo;
747
+ applyShortcutModelPolicyForUser(modelRegistry, shortcutUserInfo);
748
+ if (parsed.model &&
749
+ sessionOptions.model &&
750
+ !modelRegistry.find(sessionOptions.model.provider, sessionOptions.model.id)) {
751
+ console.error(chalk.red(`Model ${sessionOptions.model.provider}/${sessionOptions.model.id} is not available for team accounts.`));
752
+ process.exit(1);
753
+ }
728
754
  }
729
755
  }
730
756
  sessionOptions.fastModeAllowed = isFastModeAllowedForUser(shortcutUserInfo);
@@ -955,6 +981,7 @@ export async function main(args) {
955
981
  const previousMogRuntimeEnabled = isMogRuntimeEnabledForUser(shortcutUserInfo);
956
982
  const userInfo = await resolveShortcutUserInfo(authStorage);
957
983
  shortcutUserInfo = userInfo;
984
+ applyShortcutModelPolicyForUser(modelRegistry, shortcutUserInfo);
958
985
  setDefaultEnginePrompts(resolvePromptEngine(shortcutUserInfo));
959
986
  const resolvedUserId = userInfo?.userId ?? userId;
960
987
  if (userInfo) {
@@ -976,6 +1003,7 @@ export async function main(args) {
976
1003
  }
977
1004
  });
978
1005
  sessionRef?.setFastModeAllowed(isFastModeAllowedForUser(userInfo), getFastModeDisabledReasonForUser(userInfo) ?? 'team');
1006
+ await moveSessionOffPolicyDeniedModel(sessionRef, modelRegistry);
979
1007
  setRemoteControlTeamAccount(Boolean(userInfo?.teamId));
980
1008
  if (isMogRuntimeEnabledForUser(shortcutUserInfo) !== previousMogRuntimeEnabled) {
981
1009
  await refreshSessionForMogPolicyChange(sessionRef);
@@ -1010,6 +1038,7 @@ export async function main(args) {
1010
1038
  });
1011
1039
  const previousMogRuntimeEnabled = isMogRuntimeEnabledForUser(shortcutUserInfo);
1012
1040
  shortcutUserInfo = null;
1041
+ applyShortcutModelPolicyForUser(modelRegistry, shortcutUserInfo);
1013
1042
  setDefaultEnginePrompts(resolvePromptEngine(shortcutUserInfo));
1014
1043
  sessionRef?.setFastModeAllowed(false, 'login');
1015
1044
  setRemoteControlTeamAccount(false);
@@ -15,6 +15,14 @@ export declare const SHORTCUT_MODEL_REF: {
15
15
  readonly Gpt55: "shortcut/gpt-5.5-2026-04-23";
16
16
  readonly FreeModel: "shortcut/free-model";
17
17
  };
18
+ export declare function isShortcutTeamRestrictedModel(model: {
19
+ readonly provider?: string;
20
+ readonly id?: string;
21
+ } | undefined): boolean;
22
+ export declare function isShortcutModelAllowedForTeamAccount(model: {
23
+ readonly provider?: string;
24
+ readonly id?: string;
25
+ } | undefined, teamAccount: boolean): boolean;
18
26
  export declare function isShortcutFastModeModel(model: {
19
27
  readonly provider?: string;
20
28
  readonly id?: string;
package/dist/model-ids.js CHANGED
@@ -15,6 +15,12 @@ export const SHORTCUT_MODEL_REF = {
15
15
  Gpt55: `${SHORTCUT_PROVIDER_ID}/${SHORTCUT_MODEL_ID.Gpt55}`,
16
16
  FreeModel: `${SHORTCUT_PROVIDER_ID}/${SHORTCUT_MODEL_ID.FreeModel}`
17
17
  };
18
+ export function isShortcutTeamRestrictedModel(model) {
19
+ return model?.provider === SHORTCUT_PROVIDER_ID && model.id === SHORTCUT_MODEL_ID.ClaudeFable5;
20
+ }
21
+ export function isShortcutModelAllowedForTeamAccount(model, teamAccount) {
22
+ return !teamAccount || !isShortcutTeamRestrictedModel(model);
23
+ }
18
24
  export function isShortcutFastModeModel(model) {
19
25
  return model?.id === SHORTCUT_MODEL_ID.ClaudeOpus48 || model?.id === SHORTCUT_MODEL_ID.Gpt55;
20
26
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "shortcutxl",
3
- "version": "0.3.62",
3
+ "version": "0.3.63",
4
4
  "license": "MIT",
5
5
  "type": "module",
6
6
  "types": "./dist/index.d.ts",
Binary file