claude-code-rust 0.11.1 → 0.11.2

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.
@@ -36,7 +36,7 @@ export function shouldEmitStartupAuthRequiredForAccount(account) {
36
36
  return !nonEmptyString(account.email) && !nonEmptyString(account.apiKeySource);
37
37
  }
38
38
  const DEFAULT_SETTING_SOURCES = ["user", "project", "local"];
39
- const DEFAULT_MODEL_NAME = "default";
39
+ const OPUS_MODEL_ALIAS = "opus";
40
40
  const DEFAULT_PERMISSION_MODE = "default";
41
41
  function isSdkElicitationContentValue(value) {
42
42
  return (typeof value === "string" ||
@@ -546,7 +546,7 @@ function permissionModeFromSettingsValue(rawMode) {
546
546
  function initialSessionModel(launchSettings) {
547
547
  const settings = settingsObjectFromLaunchSettings(launchSettings);
548
548
  const model = typeof settings?.model === "string" ? settings.model.trim() : "";
549
- return model || DEFAULT_MODEL_NAME;
549
+ return model || OPUS_MODEL_ALIAS;
550
550
  }
551
551
  function startupModelOption(launchSettings) {
552
552
  const settings = settingsObjectFromLaunchSettings(launchSettings);
@@ -958,10 +958,12 @@ export function handleElicitationResponse(command) {
958
958
  } : {}),
959
959
  });
960
960
  }
961
+ const MAX_MODEL_VERSION_PARTS = 2;
962
+ const RELEASE_BUILD_TOKEN = /^20\d{6}$/;
961
963
  function normalizeModelKey(id) {
962
964
  const original = id.trim();
963
- if (!original || original === DEFAULT_MODEL_NAME) {
964
- return { original, family: "default", versionParts: [], variantParts: [] };
965
+ if (!original) {
966
+ return { original, family: "unknown", versionParts: [], variantParts: [], buildParts: [] };
965
967
  }
966
968
  const lower = original.toLowerCase();
967
969
  const contextMatch = lower.match(/\[([^\]]+)\]$/);
@@ -975,32 +977,39 @@ function normalizeModelKey(id) {
975
977
  const family = familyPart === "opus" || familyPart === "sonnet" || familyPart === "haiku"
976
978
  ? familyPart
977
979
  : "unknown";
978
- const versionParts = family === "unknown"
979
- ? []
980
- : parts
981
- .slice(1)
982
- .filter((part) => /^\d+$/.test(part))
983
- .map((part) => Number.parseInt(part, 10))
984
- .filter((part) => Number.isFinite(part));
985
- const variantParts = family === "unknown"
986
- ? []
987
- : parts
988
- .slice(1)
989
- .filter((part) => !/^\d+$/.test(part));
980
+ const versionParts = [];
981
+ const variantParts = [];
982
+ const buildParts = [];
983
+ if (family !== "unknown") {
984
+ for (const part of parts.slice(1)) {
985
+ if (/^\d+$/.test(part)) {
986
+ if (versionParts.length < MAX_MODEL_VERSION_PARTS) {
987
+ const parsed = Number.parseInt(part, 10);
988
+ if (Number.isFinite(parsed)) {
989
+ versionParts.push(parsed);
990
+ }
991
+ continue;
992
+ }
993
+ if (RELEASE_BUILD_TOKEN.test(part)) {
994
+ buildParts.push(part);
995
+ continue;
996
+ }
997
+ }
998
+ variantParts.push(part);
999
+ }
1000
+ }
990
1001
  return {
991
1002
  original,
992
1003
  family,
993
1004
  versionParts,
994
1005
  variantParts,
1006
+ buildParts,
995
1007
  ...(contextSuffix ? { contextSuffix } : {}),
996
1008
  };
997
1009
  }
998
1010
  function modelKeysAreCompatible(leftId, rightId) {
999
1011
  const left = normalizeModelKey(leftId);
1000
1012
  const right = normalizeModelKey(rightId);
1001
- if (left.family === "default" || right.family === "default") {
1002
- return false;
1003
- }
1004
1013
  if (left.family === "unknown" || right.family === "unknown") {
1005
1014
  return left.original.toLowerCase() === right.original.toLowerCase();
1006
1015
  }
@@ -1023,9 +1032,6 @@ function sameContextSuffix(leftId, rightId) {
1023
1032
  function sameFamilyAndVersion(leftId, rightId) {
1024
1033
  const left = normalizeModelKey(leftId);
1025
1034
  const right = normalizeModelKey(rightId);
1026
- if (left.family === "default" || right.family === "default") {
1027
- return false;
1028
- }
1029
1035
  if (left.family === "unknown" || right.family === "unknown") {
1030
1036
  return left.original.toLowerCase() === right.original.toLowerCase();
1031
1037
  }
@@ -1058,9 +1064,6 @@ function hasVariantSiblingConflict(availableModels, candidateId, resolvedId) {
1058
1064
  }
1059
1065
  function humanizeModelId(id) {
1060
1066
  const normalized = normalizeModelKey(id);
1061
- if (normalized.family === "default") {
1062
- return "Default";
1063
- }
1064
1067
  if (normalized.family === "unknown") {
1065
1068
  return id;
1066
1069
  }
@@ -1079,9 +1082,6 @@ function humanizeModelId(id) {
1079
1082
  }
1080
1083
  function shortDisplayNameForModelId(id) {
1081
1084
  const normalized = normalizeModelKey(id);
1082
- if (normalized.family === "default") {
1083
- return "Default";
1084
- }
1085
1085
  if (normalized.family === "unknown") {
1086
1086
  return id;
1087
1087
  }
@@ -1090,17 +1090,18 @@ function shortDisplayNameForModelId(id) {
1090
1090
  : normalized.family === "sonnet"
1091
1091
  ? "Sonnet"
1092
1092
  : "Haiku";
1093
+ const versionLabel = normalized.versionParts.length > 0 ? ` ${normalized.versionParts.join(".")}` : "";
1093
1094
  const contextLabel = normalized.contextSuffix?.toLowerCase() === "1m"
1094
1095
  ? " [1M]"
1095
1096
  : normalized.contextSuffix
1096
1097
  ? ` [${normalized.contextSuffix}]`
1097
1098
  : "";
1098
- return `${familyLabel}${contextLabel}`;
1099
+ return `${familyLabel}${versionLabel}${contextLabel}`;
1099
1100
  }
1100
1101
  function currentModelIsAuthoritative(resolvedId, requestedId) {
1101
1102
  const resolved = resolvedId.trim();
1102
- if (!resolved || resolved === DEFAULT_MODEL_NAME || resolved === "Connecting...") {
1103
- return Boolean(requestedId?.trim() && requestedId.trim() !== DEFAULT_MODEL_NAME);
1103
+ if (!resolved || resolved === "Connecting...") {
1104
+ return Boolean(requestedId?.trim());
1104
1105
  }
1105
1106
  return true;
1106
1107
  }
@@ -1126,9 +1127,9 @@ export function resolveCurrentModel(session) {
1126
1127
  const resolvedId = session.resolvedRuntimeModelId?.trim() ||
1127
1128
  session.model.trim() ||
1128
1129
  requestedId ||
1129
- DEFAULT_MODEL_NAME;
1130
+ OPUS_MODEL_ALIAS;
1130
1131
  const catalogModel = resolveCatalogModel(session.availableModels, resolvedId, requestedId);
1131
- const runtimeDisplayId = resolvedId || requestedId || DEFAULT_MODEL_NAME;
1132
+ const runtimeDisplayId = resolvedId || requestedId || OPUS_MODEL_ALIAS;
1132
1133
  const displayNameShort = shortDisplayNameForModelId(runtimeDisplayId);
1133
1134
  const displayNameLong = humanizeModelId(runtimeDisplayId);
1134
1135
  const currentModel = {
@@ -43,7 +43,7 @@ export async function generatePersistedSessionTitle(query, description) {
43
43
  }
44
44
  return title;
45
45
  }
46
- const EXPECTED_AGENT_SDK_VERSION = "0.2.104";
46
+ const EXPECTED_AGENT_SDK_VERSION = "0.2.112";
47
47
  const require = createRequire(import.meta.url);
48
48
  export function resolveInstalledAgentSdkVersion() {
49
49
  try {
@@ -67,9 +67,9 @@ test("refreshSupportedModesForSession uses resolved current model for auto-mode
67
67
  },
68
68
  ];
69
69
  session.currentModel = {
70
- resolved_id: "claude-sonnet-4-6[1m]",
71
- display_name_short: "Sonnet [1M]",
72
- display_name_long: "Sonnet 4.6 [1M]",
70
+ resolved_id: "claude-sonnet-4-7[1m]",
71
+ display_name_short: "Sonnet 4.7 [1M]",
72
+ display_name_long: "Sonnet 4.7 [1M]",
73
73
  supports_effort: true,
74
74
  supported_effort_levels: ["low", "medium", "high"],
75
75
  supports_auto_mode: false,
@@ -484,7 +484,7 @@ test("buildQueryOptions trims startup model before passing sdk option", () => {
484
484
  cwd: "C:/work",
485
485
  launchSettings: {
486
486
  settings: {
487
- model: " claude-opus-4-6 ",
487
+ model: " claude-opus-4-7 ",
488
488
  permissions: { defaultMode: "plan" },
489
489
  },
490
490
  },
@@ -495,7 +495,7 @@ test("buildQueryOptions trims startup model before passing sdk option", () => {
495
495
  enableSpawnDebug: false,
496
496
  sessionIdForLogs: () => "session-model",
497
497
  });
498
- assert.equal(options.model, "claude-opus-4-6");
498
+ assert.equal(options.model, "claude-opus-4-7");
499
499
  assert.equal(options.permissionMode, "plan");
500
500
  });
501
501
  test("buildQueryOptions maps auto startup permission mode", () => {
@@ -1673,7 +1673,7 @@ test("looksLikeAuthRequired detects login hints", () => {
1673
1673
  assert.equal(looksLikeAuthRequired("normal tool output"), false);
1674
1674
  });
1675
1675
  test("agent sdk version compatibility check matches pinned version", () => {
1676
- assert.equal(resolveInstalledAgentSdkVersion(), "0.2.104");
1676
+ assert.equal(resolveInstalledAgentSdkVersion(), "0.2.112");
1677
1677
  assert.equal(agentSdkVersionCompatibilityError(), undefined);
1678
1678
  });
1679
1679
  test("mapSessionMessagesToUpdates maps message content blocks", () => {
@@ -1994,46 +1994,46 @@ test("mapAvailableModels preserves optional fast and auto mode metadata", () =>
1994
1994
  });
1995
1995
  test("resolveCurrentModel keeps 1M context suffix in short and long display names", () => {
1996
1996
  const session = makeSessionState();
1997
- session.resolvedRuntimeModelId = "claude-opus-4-6[1m]";
1997
+ session.resolvedRuntimeModelId = "claude-opus-4-7[1m]";
1998
1998
  const currentModel = resolveCurrentModel(session);
1999
- assert.equal(currentModel.display_name_short, "Opus [1M]");
2000
- assert.equal(currentModel.display_name_long, "Opus 4.6 [1M]");
1999
+ assert.equal(currentModel.display_name_short, "Opus 4.7 [1M]");
2000
+ assert.equal(currentModel.display_name_long, "Opus 4.7 [1M]");
2001
2001
  });
2002
2002
  test("resolveCurrentModel does not inherit standard Opus capabilities for 1M when sibling variants exist", () => {
2003
2003
  const session = makeSessionState();
2004
- session.requestedModelId = "claude-opus-4-6";
2005
- session.resolvedRuntimeModelId = "claude-opus-4-6[1m]";
2004
+ session.requestedModelId = "claude-opus-4-7";
2005
+ session.resolvedRuntimeModelId = "claude-opus-4-7[1m]";
2006
2006
  session.availableModels = [
2007
2007
  {
2008
- id: "claude-opus-4-6",
2008
+ id: "claude-opus-4-7",
2009
2009
  display_name: "Claude Opus",
2010
2010
  supports_effort: true,
2011
2011
  supported_effort_levels: ["low", "medium", "high"],
2012
2012
  },
2013
2013
  {
2014
- id: "claude-opus-4-6[1m]",
2014
+ id: "claude-opus-4-7[1m]",
2015
2015
  display_name: "Claude Opus 1M",
2016
2016
  supports_effort: false,
2017
2017
  supported_effort_levels: [],
2018
2018
  },
2019
2019
  ];
2020
2020
  const currentModel = resolveCurrentModel(session);
2021
- assert.equal(currentModel.catalog_id, "claude-opus-4-6[1m]");
2021
+ assert.equal(currentModel.catalog_id, "claude-opus-4-7[1m]");
2022
2022
  assert.equal(currentModel.supports_effort, false);
2023
2023
  });
2024
2024
  test("resolveCurrentModel avoids suffix-insensitive fallback when sibling variants make it ambiguous", () => {
2025
2025
  const session = makeSessionState();
2026
- session.requestedModelId = "claude-opus-4-6";
2027
- session.resolvedRuntimeModelId = "claude-opus-4-6[1m]";
2026
+ session.requestedModelId = "claude-opus-4-7";
2027
+ session.resolvedRuntimeModelId = "claude-opus-4-7[1m]";
2028
2028
  session.availableModels = [
2029
2029
  {
2030
- id: "claude-opus-4-6",
2030
+ id: "claude-opus-4-7",
2031
2031
  display_name: "Claude Opus",
2032
2032
  supports_effort: true,
2033
2033
  supported_effort_levels: ["low", "medium", "high"],
2034
2034
  },
2035
2035
  {
2036
- id: "claude-opus-4-6-alt[1m]",
2036
+ id: "claude-opus-4-7-alt[1m]",
2037
2037
  display_name: "Claude Opus Alt 1M",
2038
2038
  supports_effort: false,
2039
2039
  supported_effort_levels: [],
@@ -2045,9 +2045,9 @@ test("resolveCurrentModel avoids suffix-insensitive fallback when sibling varian
2045
2045
  });
2046
2046
  test("emitCurrentModelUpdate can acknowledge a successful no-op set_model", () => {
2047
2047
  const session = makeSessionState();
2048
- session.model = "default";
2049
- session.requestedModelId = "default";
2050
- session.resolvedRuntimeModelId = "claude-opus-4-6[1m]";
2048
+ session.model = "opus";
2049
+ session.requestedModelId = "opus";
2050
+ session.resolvedRuntimeModelId = "claude-opus-4-7[1m]";
2051
2051
  refreshCurrentModel(session);
2052
2052
  const events = captureBridgeEvents(() => {
2053
2053
  const changed = refreshCurrentModel(session, true);
@@ -2061,10 +2061,10 @@ test("emitCurrentModelUpdate can acknowledge a successful no-op set_model", () =
2061
2061
  assert.deepEqual(lastEvent.update, {
2062
2062
  type: "current_model_update",
2063
2063
  current_model: {
2064
- requested_id: "default",
2065
- resolved_id: "claude-opus-4-6[1m]",
2066
- display_name_short: "Opus [1M]",
2067
- display_name_long: "Opus 4.6 [1M]",
2064
+ requested_id: "opus",
2065
+ resolved_id: "claude-opus-4-7[1m]",
2066
+ display_name_short: "Opus 4.7 [1M]",
2067
+ display_name_long: "Opus 4.7 [1M]",
2068
2068
  supports_effort: false,
2069
2069
  supported_effort_levels: [],
2070
2070
  is_authoritative: true,
@@ -2107,9 +2107,18 @@ test("emitCurrentModelUpdate can publish catalog-enriched current model metadata
2107
2107
  });
2108
2108
  });
2109
2109
  test("shouldInvalidateResolvedRuntimeModel invalidates stale runtime identity only when the request changes", () => {
2110
- assert.equal(shouldInvalidateResolvedRuntimeModel("default", "default", "sonnet"), true);
2110
+ assert.equal(shouldInvalidateResolvedRuntimeModel("opus", "opus", "sonnet"), true);
2111
2111
  assert.equal(shouldInvalidateResolvedRuntimeModel("sonnet", "sonnet", "haiku"), true);
2112
- assert.equal(shouldInvalidateResolvedRuntimeModel("default", "default", "default"), false);
2112
+ assert.equal(shouldInvalidateResolvedRuntimeModel("opus", "opus", "opus"), false);
2113
+ });
2114
+ test("resolveCurrentModel strips release date suffix from dated model ids", () => {
2115
+ const session = makeSessionState();
2116
+ session.model = "claude-opus-4-5-20251101";
2117
+ session.requestedModelId = "claude-opus-4-5-20251101";
2118
+ session.resolvedRuntimeModelId = "claude-opus-4-5-20251101";
2119
+ const currentModel = resolveCurrentModel(session);
2120
+ assert.equal(currentModel.display_name_short, "Opus 4.5");
2121
+ assert.equal(currentModel.display_name_long, "Opus 4.5");
2113
2122
  });
2114
2123
  test("resolveCurrentModel falls back to the requested model immediately after stale runtime identity is cleared", () => {
2115
2124
  const session = makeSessionState();
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "claude-code-rust",
3
- "version": "0.11.1",
3
+ "version": "0.11.2",
4
4
  "description": "Claude Code Rust - native Rust terminal interface for Claude Code",
5
5
  "keywords": [
6
6
  "cli",
@@ -29,7 +29,7 @@
29
29
  "README.md"
30
30
  ],
31
31
  "dependencies": {
32
- "@anthropic-ai/claude-agent-sdk": "0.2.104"
32
+ "@anthropic-ai/claude-agent-sdk": "0.2.112"
33
33
  },
34
34
  "scripts": {
35
35
  "postinstall": "node ./scripts/postinstall.js",