@oneciel-ai/claude-any 0.1.37 → 0.1.39

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/README.md CHANGED
@@ -48,7 +48,7 @@ arguments through unchanged.
48
48
 
49
49
  Credits: One Ciel LLC
50
50
 
51
- Current version: `0.1.37`
51
+ Current version: `0.1.39`
52
52
 
53
53
  ## Why This Exists
54
54
 
@@ -381,6 +381,23 @@ steps under that larger model's supervision.
381
381
 
382
382
  ## Changelog
383
383
 
384
+ ### 0.1.39
385
+
386
+ - **Menu input fixes**: restores terminal line/echo mode before text or number
387
+ prompts, so typed numeric values are visible in the prelaunch UI.
388
+ - **Safer numeric validation**: invalid numeric option input now shows an
389
+ inline message instead of crashing the menu.
390
+ - **Preset visibility**: applied presets report the effective context, reserve,
391
+ output, and timeout values.
392
+
393
+ ### 0.1.38
394
+
395
+ - **User-selected context windows**: removes the NVIDIA hosted 32K safety cap.
396
+ The router now uses the context window selected in LLM options or headless
397
+ configuration, with model-aware fallback only when no value is configured.
398
+ - **NVIDIA presets updated**: NVIDIA hosted presets now start at 65K and scale
399
+ up to 256K for large-output/reasoning workflows.
400
+
384
401
  ### 0.1.37
385
402
 
386
403
  - **Pseudo tool-call recovery**: the NVIDIA/OpenAI-compatible stream path now
package/claude_any.py CHANGED
@@ -85,7 +85,7 @@ PROVIDER_LABELS = {
85
85
  "self-hosted-nim": "Self Hosted NIM",
86
86
  }
87
87
  APP_NAME = "Claude Any"
88
- VERSION = "0.1.37"
88
+ VERSION = "0.1.39"
89
89
  CREDITS = "Credits: One Ciel LLC"
90
90
 
91
91
  LOG_LEVELS = {"SILENT": 0, "ERROR": 1, "WARN": 2, "INFO": 3, "DEBUG": 4, "TRACE": 5}
@@ -144,7 +144,7 @@ LANGUAGES = {
144
144
  "zh": "中文",
145
145
  }
146
146
 
147
- MODEL_PRESETS: dict[str, dict[str, Any]] = {
147
+ MODEL_PRESETS: dict[str, dict[str, Any]] = {
148
148
  "glm-4.7": {"compat_max_tokens": 64, "thinking": True, "num_ctx_min": 32768, "num_ctx_max": 131072},
149
149
  "glm-5.1": {"compat_max_tokens": 64, "thinking": True, "num_ctx_min": 32768, "num_ctx_max": 131072},
150
150
  "glm-4.7:cloud": {"compat_max_tokens": 64, "thinking": True, "num_ctx_min": 32768, "num_ctx_max": 131072},
@@ -154,10 +154,21 @@ MODEL_PRESETS: dict[str, dict[str, Any]] = {
154
154
  "qwen3.6:27b": {"compat_max_tokens": 16, "thinking": False, "num_ctx_min": 32768, "num_ctx_max": 65536},
155
155
  "deepseek-r1": {"compat_max_tokens": 64, "thinking": True, "num_ctx_min": 32768, "num_ctx_max": 131072},
156
156
  "llama3.3:70b": {"compat_max_tokens": 16, "thinking": False, "num_ctx_min": 32768, "num_ctx_max": 131072},
157
- }
158
-
159
-
160
- def model_preset(model_id: str) -> dict[str, Any]:
157
+ }
158
+
159
+
160
+ def nvidia_hosted_context_default(model_id: str) -> int:
161
+ model = model_id.lower()
162
+ if "kimi-k2.6" in model or "kimi_k2.6" in model:
163
+ return 262144
164
+ if "deepseek" in model:
165
+ return 131072
166
+ if "glm" in model or "qwen" in model:
167
+ return 65536
168
+ return 65536
169
+
170
+
171
+ def model_preset(model_id: str) -> dict[str, Any]:
161
172
  """Return preset dict for a model ID, checking exact match then prefix match."""
162
173
  if model_id in MODEL_PRESETS:
163
174
  return MODEL_PRESETS[model_id]
@@ -722,7 +733,7 @@ DEFAULT_CONFIG: dict[str, Any] = {
722
733
  "native_compat": False,
723
734
  "rate_limit_rpm": 40,
724
735
  "rate_limit_status": True,
725
- "context_window": 32768,
736
+ "context_window": 65536,
726
737
  "max_output_tokens": 4096,
727
738
  "temperature": 0.7,
728
739
  "top_p": 0.8,
@@ -788,7 +799,14 @@ def apply_config_migrations(cfg: dict[str, Any]) -> None:
788
799
  if not migrations.get(marker):
789
800
  pcfg = cfg.get("providers", {}).get("nvidia-hosted", {})
790
801
  if isinstance(pcfg, dict) and not positive_int(pcfg.get("context_window")):
791
- pcfg["context_window"] = 32768
802
+ pcfg["context_window"] = nvidia_hosted_context_default(str(pcfg.get("current_model") or ""))
803
+ migrations[marker] = True
804
+
805
+ marker = "nvidia_context_window_unforce_32k_20260513"
806
+ if not migrations.get(marker):
807
+ pcfg = cfg.get("providers", {}).get("nvidia-hosted", {})
808
+ if isinstance(pcfg, dict) and positive_int(pcfg.get("context_window")) == 32768:
809
+ pcfg["context_window"] = nvidia_hosted_context_default(str(pcfg.get("current_model") or ""))
792
810
  migrations[marker] = True
793
811
 
794
812
  marker = "stream_enabled_default_true_20260513"
@@ -3620,7 +3638,7 @@ def openai_context_limit_for_budget(provider: str, pcfg: dict[str, Any]) -> int:
3620
3638
  if configured:
3621
3639
  return configured
3622
3640
  if provider == "nvidia-hosted":
3623
- return 32768
3641
+ return nvidia_hosted_context_default(str(pcfg.get("current_model") or ""))
3624
3642
  return 65536
3625
3643
 
3626
3644
 
@@ -6124,14 +6142,72 @@ def apply_llm_preset_to_provider(provider: str, pcfg: dict[str, Any], preset_id:
6124
6142
  }
6125
6143
  for token in tokens_by_preset[preset_id]:
6126
6144
  apply_provider_option(provider, pcfg, token)
6127
- else:
6128
- native_default = "false" if provider == "nvidia-hosted" else "true"
6129
- server_limit = upstream_model_context_limit(provider, pcfg) if provider in ("vllm", "self-hosted-nim") else None
6130
- tokens_by_preset = {
6131
- "balanced": [
6132
- "context_window=32768",
6133
- "reserve=2048",
6134
- "max_output_tokens=4096",
6145
+ else:
6146
+ native_default = "false" if provider == "nvidia-hosted" else "true"
6147
+ server_limit = upstream_model_context_limit(provider, pcfg) if provider in ("vllm", "self-hosted-nim") else None
6148
+ if provider == "nvidia-hosted":
6149
+ tokens_by_preset = {
6150
+ "balanced": [
6151
+ "context_window=65536",
6152
+ "reserve=4096",
6153
+ "max_output_tokens=4096",
6154
+ "timeout=300000",
6155
+ "temperature=0.3",
6156
+ "unset:top_p",
6157
+ "unset:top_k",
6158
+ ],
6159
+ "coding": [
6160
+ "context_window=65536",
6161
+ "reserve=4096",
6162
+ "max_output_tokens=4096",
6163
+ "timeout=300000",
6164
+ "temperature=0.2",
6165
+ "unset:top_p",
6166
+ "unset:top_k",
6167
+ ],
6168
+ "fast": [
6169
+ "context_window=65536",
6170
+ "reserve=2048",
6171
+ "max_output_tokens=2048",
6172
+ "timeout=300000",
6173
+ "temperature=0.2",
6174
+ "unset:top_p",
6175
+ "unset:top_k",
6176
+ ],
6177
+ "long-context-65k": [
6178
+ "context_window=131072",
6179
+ "reserve=8192",
6180
+ "max_output_tokens=4096",
6181
+ "timeout=900000",
6182
+ "temperature=0.3",
6183
+ "unset:top_p",
6184
+ "unset:top_k",
6185
+ ],
6186
+ "large-output": [
6187
+ "context_window=262144",
6188
+ "reserve=8192",
6189
+ "max_output_tokens=8192",
6190
+ "timeout=1200000",
6191
+ "temperature=0.3",
6192
+ "unset:top_p",
6193
+ "unset:top_k",
6194
+ ],
6195
+ "reasoning": [
6196
+ "context_window=262144",
6197
+ "reserve=8192",
6198
+ "max_output_tokens=4096",
6199
+ "timeout=1800000",
6200
+ "temperature=0.6",
6201
+ "unset:top_p",
6202
+ "unset:top_k",
6203
+ ],
6204
+ }
6205
+ else:
6206
+ tokens_by_preset = {
6207
+ "balanced": [
6208
+ "context_window=32768",
6209
+ "reserve=2048",
6210
+ "max_output_tokens=4096",
6135
6211
  "timeout=300000",
6136
6212
  "temperature=0.3",
6137
6213
  "unset:top_p",
@@ -6185,10 +6261,10 @@ def apply_llm_preset_to_provider(provider: str, pcfg: dict[str, Any], preset_id:
6185
6261
  "timeout=1800000",
6186
6262
  "temperature=0.6",
6187
6263
  "unset:top_p",
6188
- "unset:top_k",
6189
- f"native={native_default}",
6190
- ],
6191
- }
6264
+ "unset:top_k",
6265
+ f"native={native_default}",
6266
+ ],
6267
+ }
6192
6268
  for token in tokens_by_preset[preset_id]:
6193
6269
  if provider == "nvidia-hosted" and token.startswith("native="):
6194
6270
  continue
@@ -6206,16 +6282,38 @@ def apply_llm_preset_to_provider(provider: str, pcfg: dict[str, Any], preset_id:
6206
6282
  f"{ui_text('apply_preset', lang)}: {label}",
6207
6283
  f"Provider: {provider}; {ui_text('model_family', lang)}: {model_family_text(family, lang)}",
6208
6284
  ]
6209
- if provider in ("vllm", "self-hosted-nim"):
6210
- server_limit = upstream_model_context_limit(provider, pcfg)
6211
- if server_limit:
6212
- lines.append(f"Server max_model_len: {server_limit}")
6213
- if preset_id in ("long-context-65k", "large-output") and server_limit < 65536:
6214
- lines.append("Long-context preset requires restarting the server with --max-model-len 65536 or higher.")
6215
- lines.append("Client settings were capped to the server-reported context length.")
6216
- elif preset_id in ("long-context-65k", "large-output"):
6217
- lines.append("Could not verify server max_model_len; vLLM/NIM must be started with a matching context limit.")
6218
- return lines
6285
+ if provider in ("vllm", "nvidia-hosted", "self-hosted-nim"):
6286
+ server_limit = upstream_model_context_limit(provider, pcfg)
6287
+ if server_limit:
6288
+ lines.append(f"Server max_model_len: {server_limit}")
6289
+ if preset_id in ("long-context-65k", "large-output") and server_limit < 65536:
6290
+ lines.append("Long-context preset requires restarting the server with --max-model-len 65536 or higher.")
6291
+ lines.append("Client settings were capped to the server-reported context length.")
6292
+ elif preset_id in ("long-context-65k", "large-output"):
6293
+ lines.append("Could not verify server max_model_len; vLLM/NIM must be started with a matching context limit.")
6294
+ if provider in ("vllm", "nvidia-hosted", "self-hosted-nim"):
6295
+ lines.append(
6296
+ "Applied options: "
6297
+ f"context_window={pcfg.get('context_window', 'default')}, "
6298
+ f"reserve={pcfg.get('context_reserve_tokens', 'default')}, "
6299
+ f"max_output_tokens={pcfg.get('max_output_tokens', 'default')}, "
6300
+ f"timeout={pcfg.get('request_timeout_ms', 'default')}ms"
6301
+ )
6302
+ elif provider in ("ollama", "ollama-cloud"):
6303
+ opts = ollama_extra_options(pcfg)
6304
+ lines.append(
6305
+ "Applied options: "
6306
+ f"num_ctx={ollama_num_ctx_status(pcfg)}, "
6307
+ f"num_predict={opts.get('num_predict', 'default')}, "
6308
+ f"timeout={pcfg.get('request_timeout_ms', 'default')}ms"
6309
+ )
6310
+ elif provider == "anthropic":
6311
+ lines.append(
6312
+ "Applied options: "
6313
+ f"max_output_tokens={pcfg.get('max_output_tokens', 'default')}, "
6314
+ f"timeout={pcfg.get('request_timeout_ms', 'default')}ms"
6315
+ )
6316
+ return lines
6219
6317
 
6220
6318
 
6221
6319
  def apply_llm_preset_config(provider: str, preset_id: str) -> list[str]:
@@ -6413,9 +6511,9 @@ def llm_option_panel_rows(provider: str, pcfg: dict[str, Any], lang: str | None
6413
6511
  add("Rate limit RPM", "rate_limit_rpm", pcfg.get("rate_limit_rpm", 40))
6414
6512
  add("Rate limit status", "rate_limit_status", "on" if bool(pcfg.get("rate_limit_status", True)) else "off")
6415
6513
  else:
6416
- if provider in ("vllm", "self-hosted-nim"):
6417
- add("Context window", "context_window", pcfg.get("context_window", "default"))
6418
- add("Context reserve", "context_reserve_tokens", pcfg.get("context_reserve_tokens", "default"))
6514
+ if provider in ("vllm", "nvidia-hosted", "self-hosted-nim"):
6515
+ add("Context window", "context_window", pcfg.get("context_window", "default"))
6516
+ add("Context reserve", "context_reserve_tokens", pcfg.get("context_reserve_tokens", "default"))
6419
6517
  add("Max output tokens", "max_output_tokens", pcfg.get("max_output_tokens", "default"))
6420
6518
  if provider in ("vllm", "nvidia-hosted", "self-hosted-nim"):
6421
6519
  add("Timeout ms", "request_timeout_ms", pcfg.get("request_timeout_ms", "default"))
@@ -6456,13 +6554,38 @@ def llm_option_prompt_default(provider: str, pcfg: dict[str, Any], key: str) ->
6456
6554
  return "" if value is None else str(value)
6457
6555
 
6458
6556
 
6459
- def set_llm_option_config(provider: str, key: str, raw_value: str) -> list[str]:
6557
+ def set_llm_option_config(provider: str, key: str, raw_value: str) -> list[str]:
6460
6558
  cfg = load_config()
6461
6559
  pcfg = cfg["providers"][provider]
6462
- value = raw_value.strip()
6463
- if not value:
6464
- return ["Option unchanged."]
6465
- clear_words = ("default", "unset", "none", "null")
6560
+ value = raw_value.strip()
6561
+ if not value:
6562
+ return ["Option unchanged."]
6563
+ numeric_keys = {
6564
+ "context_window",
6565
+ "context",
6566
+ "max_model_len",
6567
+ "context_reserve_tokens",
6568
+ "reserve",
6569
+ "max_output_tokens",
6570
+ "max_tokens",
6571
+ "maxtoken",
6572
+ "max_token",
6573
+ "num_ctx_min",
6574
+ "num_ctx_max",
6575
+ "num_predict",
6576
+ "timeout",
6577
+ "timeout_ms",
6578
+ "request_timeout",
6579
+ "request_timeout_ms",
6580
+ "rate_limit",
6581
+ "rate_limit_rpm",
6582
+ "rpm",
6583
+ "top_k",
6584
+ }
6585
+ if key in numeric_keys and value.lower() not in ("default", "unset", "none", "null", "0"):
6586
+ if not re.fullmatch(r"\d+", value):
6587
+ return [f"{key}: enter digits only, or use default/unset to clear."]
6588
+ clear_words = ("default", "unset", "none", "null")
6466
6589
  token = f"unset:{key}" if value.lower() in clear_words else f"{key}={value}"
6467
6590
  if provider in ("ollama", "ollama-cloud"):
6468
6591
  apply_ollama_option(pcfg, token)
@@ -8040,14 +8163,16 @@ def render_prelaunch_screen(
8040
8163
  return False
8041
8164
 
8042
8165
 
8043
- def prompt_menu_value(prompt: str, default: str = "", secret: bool = False) -> str:
8044
- label = f"{prompt}"
8045
- if default:
8046
- label += f" [{default}]"
8047
- label += ": "
8048
- if sys.stdout.isatty():
8049
- sys.stdout.write("\033[?25h")
8050
- sys.stdout.flush()
8166
+ def prompt_menu_value(prompt: str, default: str = "", secret: bool = False, restore_tty: Callable[[], None] | None = None, raw_tty: Callable[[], None] | None = None) -> str:
8167
+ label = f"{prompt}"
8168
+ if default:
8169
+ label += f" [{default}]"
8170
+ label += ": "
8171
+ if restore_tty:
8172
+ restore_tty()
8173
+ if sys.stdout.isatty():
8174
+ sys.stdout.write("\033[?25h")
8175
+ sys.stdout.flush()
8051
8176
  sys.stdout.write("\n" + ansi(label, "1;38;5;208"))
8052
8177
  sys.stdout.flush()
8053
8178
  try:
@@ -8055,12 +8180,14 @@ def prompt_menu_value(prompt: str, default: str = "", secret: bool = False) -> s
8055
8180
  value = getpass.getpass("")
8056
8181
  else:
8057
8182
  value = input()
8058
- finally:
8059
- if sys.stdout.isatty():
8060
- sys.stdout.write("\033[?25l")
8061
- sys.stdout.flush()
8062
- value = value.strip()
8063
- return value or default
8183
+ finally:
8184
+ if sys.stdout.isatty():
8185
+ sys.stdout.write("\033[?25l")
8186
+ sys.stdout.flush()
8187
+ if raw_tty:
8188
+ raw_tty()
8189
+ value = value.strip()
8190
+ return value or default
8064
8191
 
8065
8192
 
8066
8193
  def portable_provider_menu() -> int:
@@ -8092,22 +8219,23 @@ def portable_prelaunch_menu() -> int:
8092
8219
  enable_ansi()
8093
8220
  main_idx = 7 if settings_ready_except_api_key() else 0
8094
8221
  panel: str | None = None
8095
- panel_idx = 0
8096
- panel_rows: list[str] = []
8097
- panel_values: list[str] = []
8222
+ panel_idx = 0
8223
+ panel_rows: list[str] = []
8224
+ panel_values: list[str] = []
8225
+ panel_last_idx: dict[str, int] = {}
8098
8226
  checks = preflight_lines()
8099
8227
  messages: list[str] = []
8100
8228
  first_render = True
8101
8229
 
8102
- def open_panel(name: str) -> None:
8103
- nonlocal panel, panel_idx, panel_rows, panel_values, messages, first_render
8104
- cfg = load_config()
8105
- provider, pcfg = get_current_provider(cfg)
8106
- panel = name
8107
- panel_idx = 0
8108
- if name == "language":
8109
- panel_rows, panel_values = language_panel_rows(cfg)
8110
- panel_idx = panel_values.index(cfg.get("language", "en"))
8230
+ def open_panel(name: str) -> None:
8231
+ nonlocal panel, panel_idx, panel_rows, panel_values, messages, first_render
8232
+ cfg = load_config()
8233
+ provider, pcfg = get_current_provider(cfg)
8234
+ panel = name
8235
+ panel_idx = panel_last_idx.get(name, 0)
8236
+ if name == "language":
8237
+ panel_rows, panel_values = language_panel_rows(cfg)
8238
+ panel_idx = panel_values.index(cfg.get("language", "en"))
8111
8239
  elif name == "provider":
8112
8240
  panel_rows, panel_values = provider_panel_rows(cfg)
8113
8241
  panel_idx = panel_values.index(provider)
@@ -8129,15 +8257,19 @@ def portable_prelaunch_menu() -> int:
8129
8257
  panel_rows, panel_values = [f"Advisor model list failed: {type(exc).__name__}: {exc}", "+ Custom advisor model id..."], []
8130
8258
  elif name == "test":
8131
8259
  panel_rows, panel_values = ["Run compatibility test", "Back"], ["run", "back"]
8132
- elif name == "options":
8133
- panel_rows, panel_values = llm_option_panel_rows(provider, pcfg, cfg.get("language", "en"))
8134
- elif name == "preset":
8135
- panel_rows, panel_values = llm_preset_panel_rows(provider, pcfg, cfg.get("language", "en"))
8136
-
8137
- def close_panel(next_idx: int | None = None) -> None:
8138
- nonlocal panel, panel_idx, panel_rows, panel_values, main_idx
8139
- panel = None
8140
- panel_idx = 0
8260
+ elif name == "options":
8261
+ panel_rows, panel_values = llm_option_panel_rows(provider, pcfg, cfg.get("language", "en"))
8262
+ elif name == "preset":
8263
+ panel_rows, panel_values = llm_preset_panel_rows(provider, pcfg, cfg.get("language", "en"))
8264
+ if panel_rows:
8265
+ panel_idx = max(0, min(panel_idx, len(panel_rows) - 1))
8266
+
8267
+ def close_panel(next_idx: int | None = None) -> None:
8268
+ nonlocal panel, panel_idx, panel_rows, panel_values, main_idx
8269
+ if panel:
8270
+ panel_last_idx[panel] = panel_idx
8271
+ panel = None
8272
+ panel_idx = 0
8141
8273
  panel_rows = []
8142
8274
  panel_values = []
8143
8275
  if next_idx is not None:
@@ -8160,20 +8292,43 @@ def portable_prelaunch_menu() -> int:
8160
8292
  termios.tcsetattr(fd, termios.TCSANOW, new)
8161
8293
  except Exception:
8162
8294
  fd = -1
8163
- if sys.stdout.isatty():
8164
- sys.stdout.write("\033[?25l")
8165
- sys.stdout.flush()
8166
- try:
8295
+ if sys.stdout.isatty():
8296
+ sys.stdout.write("\033[?25l")
8297
+ sys.stdout.flush()
8298
+ def restore_line_mode() -> None:
8299
+ if old_settings is not None and fd >= 0:
8300
+ try:
8301
+ import termios
8302
+ termios.tcsetattr(fd, termios.TCSANOW, old_settings)
8303
+ except Exception:
8304
+ pass
8305
+
8306
+ def restore_raw_mode() -> None:
8307
+ if old_settings is not None and fd >= 0:
8308
+ try:
8309
+ import termios
8310
+ new = termios.tcgetattr(fd)
8311
+ new[3] = new[3] & ~(termios.ECHO | termios.ICANON)
8312
+ new[6][termios.VMIN] = 1
8313
+ new[6][termios.VTIME] = 0
8314
+ termios.tcsetattr(fd, termios.TCSANOW, new)
8315
+ except Exception:
8316
+ pass
8317
+
8318
+ try:
8167
8319
  while True:
8168
8320
  first_render = render_prelaunch_screen(main_idx, panel, panel_idx, panel_rows, checks, messages, first_render)
8169
8321
  key = read_menu_key(fd) if fd >= 0 else read_menu_key()
8170
- if panel:
8171
- if key in ("up", "k"):
8172
- panel_idx = (panel_idx - 1) % max(1, len(panel_rows))
8173
- continue
8174
- if key in ("down", "j"):
8175
- panel_idx = (panel_idx + 1) % max(1, len(panel_rows))
8176
- continue
8322
+ if panel:
8323
+ panel_name = panel
8324
+ if key in ("up", "k"):
8325
+ panel_idx = (panel_idx - 1) % max(1, len(panel_rows))
8326
+ panel_last_idx[panel_name] = panel_idx
8327
+ continue
8328
+ if key in ("down", "j"):
8329
+ panel_idx = (panel_idx + 1) % max(1, len(panel_rows))
8330
+ panel_last_idx[panel_name] = panel_idx
8331
+ continue
8177
8332
  if key in ("esc", "left", "q"):
8178
8333
  close_panel()
8179
8334
  continue
@@ -8198,7 +8353,7 @@ def portable_prelaunch_menu() -> int:
8198
8353
  close_panel()
8199
8354
  continue
8200
8355
  if value == "__custom__" or panel_idx >= len(panel_values):
8201
- model_value = prompt_menu_value("Model id or alias")
8356
+ model_value = prompt_menu_value("Model id or alias", restore_tty=restore_line_mode, raw_tty=restore_raw_mode)
8202
8357
  else:
8203
8358
  model_value = value
8204
8359
  if model_value:
@@ -8210,7 +8365,7 @@ def portable_prelaunch_menu() -> int:
8210
8365
  close_panel()
8211
8366
  continue
8212
8367
  if value == "__custom__" or panel_idx >= len(panel_values):
8213
- advisor_value = prompt_menu_value("Advisor model id", "deepseek-v4-pro")
8368
+ advisor_value = prompt_menu_value("Advisor model id", "deepseek-v4-pro", restore_tty=restore_line_mode, raw_tty=restore_raw_mode)
8214
8369
  else:
8215
8370
  advisor_value = value
8216
8371
  messages = set_advisor_model_config(advisor_value)
@@ -8220,7 +8375,7 @@ def portable_prelaunch_menu() -> int:
8220
8375
  if value == "back":
8221
8376
  close_panel()
8222
8377
  elif value == "input":
8223
- key_value = prompt_menu_value(f"API key for {provider}", secret=True)
8378
+ key_value = prompt_menu_value(f"API key for {provider}", secret=True, restore_tty=restore_line_mode, raw_tty=restore_raw_mode)
8224
8379
  if key_value:
8225
8380
  messages = store_api_key_config(provider, key_value)
8226
8381
  refresh_checks()
@@ -8231,7 +8386,7 @@ def portable_prelaunch_menu() -> int:
8231
8386
  "nvidia-hosted": "NVIDIA_API_KEY",
8232
8387
  "ollama-cloud": "OLLAMA_API_KEY",
8233
8388
  }.get(provider, "API_KEY")
8234
- env_name = prompt_menu_value("Environment variable name", default_env)
8389
+ env_name = prompt_menu_value("Environment variable name", default_env, restore_tty=restore_line_mode, raw_tty=restore_raw_mode)
8235
8390
  key_value = os.environ.get(env_name, "").strip()
8236
8391
  if key_value:
8237
8392
  messages = store_api_key_config(provider, key_value)
@@ -8244,7 +8399,7 @@ def portable_prelaunch_menu() -> int:
8244
8399
  if not key_value:
8245
8400
  messages = ["Clipboard did not contain readable text."]
8246
8401
  else:
8247
- confirm = prompt_menu_value(f"Clipboard contains {mask_secret(key_value)}. Store it? y/N")
8402
+ confirm = prompt_menu_value(f"Clipboard contains {mask_secret(key_value)}. Store it? y/N", restore_tty=restore_line_mode, raw_tty=restore_raw_mode)
8248
8403
  if confirm.lower().startswith("y"):
8249
8404
  messages = store_api_key_config(provider, key_value)
8250
8405
  else:
@@ -8260,7 +8415,7 @@ def portable_prelaunch_menu() -> int:
8260
8415
  close_panel(4)
8261
8416
  elif value == "edit":
8262
8417
  default = pcfg.get("base_url") or default_base_url(provider)
8263
- url = prompt_menu_value(f"Base URL for {provider}", default)
8418
+ url = prompt_menu_value(f"Base URL for {provider}", default, restore_tty=restore_line_mode, raw_tty=restore_raw_mode)
8264
8419
  if url:
8265
8420
  messages = set_base_url_config(provider, url)
8266
8421
  refresh_checks()
@@ -8289,21 +8444,27 @@ def portable_prelaunch_menu() -> int:
8289
8444
  messages = set_llm_option_config(provider, value, "false" if current else "true")
8290
8445
  except Exception as exc:
8291
8446
  messages = [f"Option update failed: {type(exc).__name__}: {exc}"]
8292
- refresh_checks()
8293
- cfg = load_config()
8294
- provider, pcfg = get_current_provider(cfg)
8295
- panel_rows, panel_values = llm_option_panel_rows(provider, pcfg, cfg.get("language", "en"))
8296
- else:
8297
- default = llm_option_prompt_default(provider, pcfg, value)
8298
- entered = prompt_menu_value(f"{value} for {provider} (default/unset clears)", default)
8447
+ refresh_checks()
8448
+ cfg = load_config()
8449
+ provider, pcfg = get_current_provider(cfg)
8450
+ old_idx = panel_idx
8451
+ panel_rows, panel_values = llm_option_panel_rows(provider, pcfg, cfg.get("language", "en"))
8452
+ panel_idx = max(0, min(old_idx, len(panel_rows) - 1))
8453
+ panel_last_idx["options"] = panel_idx
8454
+ else:
8455
+ default = llm_option_prompt_default(provider, pcfg, value)
8456
+ entered = prompt_menu_value(f"{value} for {provider} (default/unset clears)", default, restore_tty=restore_line_mode, raw_tty=restore_raw_mode)
8299
8457
  try:
8300
8458
  messages = set_llm_option_config(provider, value, entered)
8301
8459
  except Exception as exc:
8302
8460
  messages = [f"Option update failed: {type(exc).__name__}: {exc}"]
8303
- refresh_checks()
8304
- cfg = load_config()
8305
- provider, pcfg = get_current_provider(cfg)
8306
- panel_rows, panel_values = llm_option_panel_rows(provider, pcfg, cfg.get("language", "en"))
8461
+ refresh_checks()
8462
+ cfg = load_config()
8463
+ provider, pcfg = get_current_provider(cfg)
8464
+ old_idx = panel_idx
8465
+ panel_rows, panel_values = llm_option_panel_rows(provider, pcfg, cfg.get("language", "en"))
8466
+ panel_idx = max(0, min(old_idx, len(panel_rows) - 1))
8467
+ panel_last_idx["options"] = panel_idx
8307
8468
  elif panel == "preset":
8308
8469
  if value == "back":
8309
8470
  open_panel("options")
@@ -8315,12 +8476,14 @@ def portable_prelaunch_menu() -> int:
8315
8476
  except Exception as exc:
8316
8477
  messages = [f"Preset failed: {type(exc).__name__}: {exc}"]
8317
8478
  refresh_checks()
8318
- cfg = load_config()
8319
- provider, pcfg = get_current_provider(cfg)
8320
- panel = "options"
8321
- panel_idx = 0
8322
- panel_rows, panel_values = llm_option_panel_rows(provider, pcfg, cfg.get("language", "en"))
8323
- continue
8479
+ cfg = load_config()
8480
+ provider, pcfg = get_current_provider(cfg)
8481
+ panel = "options"
8482
+ panel_idx = panel_last_idx.get("options", 0)
8483
+ panel_rows, panel_values = llm_option_panel_rows(provider, pcfg, cfg.get("language", "en"))
8484
+ panel_idx = max(0, min(panel_idx, len(panel_rows) - 1))
8485
+ panel_last_idx["options"] = panel_idx
8486
+ continue
8324
8487
 
8325
8488
  if key in ("up", "k"):
8326
8489
  main_idx = (main_idx - 1) % 10
package/docs/README.ja.md CHANGED
@@ -47,7 +47,7 @@ vLLM、NVIDIA hosted、self-hosted NIM を選択し、通常の Claude Code 引
47
47
 
48
48
  Credits: One Ciel LLC
49
49
 
50
- 現在のバージョン: `0.1.37`
50
+ 現在のバージョン: `0.1.39`
51
51
 
52
52
  ## 作られた理由
53
53
 
@@ -351,6 +351,23 @@ Windows/Linux 管理、クリーンアップスクリプト、定期的なセキ
351
351
 
352
352
  ## 変更履歴
353
353
 
354
+ ### 0.1.39
355
+
356
+ - **メニュー入力修正**: テキスト/数字プロンプトの前に terminal line/echo mode を
357
+ 復元し、prelaunch UI で入力した数字が見えるようにしました。
358
+ - **数字検証の安定化**: 数字オプションへ不正な文字を入れてもメニューが
359
+ クラッシュせず、案内メッセージを表示します。
360
+ - **プリセット表示改善**: preset 適用後に実際の context、reserve、output、
361
+ timeout 値をメッセージに表示します。
362
+
363
+ ### 0.1.38
364
+
365
+ - **ユーザー選択の context window を優先**: NVIDIA hosted の 32K safety cap を
366
+ 削除しました。router は LLM options または headless 設定で選ばれた
367
+ context window を使い、未設定の場合のみモデル別 fallback を使います。
368
+ - **NVIDIA preset 更新**: NVIDIA hosted preset は 65K から開始し、
369
+ large-output/reasoning workflow では 256K まで使います。
370
+
354
371
  ### 0.1.37
355
372
 
356
373
  - **Pseudo tool-call recovery**: NVIDIA/OpenAI-compatible stream 経路で
package/docs/README.ko.md CHANGED
@@ -47,7 +47,7 @@ NVIDIA hosted, self-hosted NIM을 선택하고, Claude Code의 일반 인자는
47
47
 
48
48
  Credits: One Ciel LLC
49
49
 
50
- 현재 버전: `0.1.37`
50
+ 현재 버전: `0.1.39`
51
51
 
52
52
  ## 왜 만들었나
53
53
 
@@ -351,6 +351,23 @@ Windows 이벤트 로그 리뷰, 바이러스/랜섬웨어 침입 시도 정리,
351
351
 
352
352
  ## 변경 이력
353
353
 
354
+ ### 0.1.39
355
+
356
+ - **메뉴 입력 수정**: 텍스트/숫자 프롬프트 전에 터미널 line/echo 모드를 복구하여
357
+ prelaunch UI에서 입력한 숫자가 보이게 했습니다.
358
+ - **숫자 검증 안정화**: 숫자 옵션에 잘못된 문자를 넣어도 메뉴가 크래시되지 않고
359
+ 안내 메시지를 표시합니다.
360
+ - **프리셋 표시 개선**: preset 적용 후 실제 context, reserve, output, timeout 값을
361
+ 메시지에 표시합니다.
362
+
363
+ ### 0.1.38
364
+
365
+ - **사용자 선택 context window 우선**: NVIDIA hosted 32K safety cap을 제거했습니다.
366
+ router는 LLM 옵션 또는 headless 설정에서 선택한 context window를 사용하고,
367
+ 값이 없을 때만 모델별 fallback을 사용합니다.
368
+ - **NVIDIA preset 업데이트**: NVIDIA hosted preset은 65K부터 시작하고,
369
+ large-output/reasoning 워크플로에서는 256K까지 사용합니다.
370
+
354
371
  ### 0.1.37
355
372
 
356
373
  - **Pseudo tool-call recovery**: NVIDIA/OpenAI-compatible stream 경로에서
package/docs/README.zh.md CHANGED
@@ -47,7 +47,7 @@ NIM,并把普通 Claude Code 参数原样传递。
47
47
 
48
48
  Credits: One Ciel LLC
49
49
 
50
- 当前版本: `0.1.37`
50
+ 当前版本: `0.1.39`
51
51
 
52
52
  ## 为什么存在
53
53
 
@@ -337,6 +337,22 @@ Hermes 格式模型或部分较旧的 Qwen tool template。
337
337
 
338
338
  ## 更新日志
339
339
 
340
+ ### 0.1.39
341
+
342
+ - **菜单输入修复**:在文本/数字提示前恢复 terminal line/echo mode,
343
+ prelaunch UI 中输入的数字现在可见。
344
+ - **数字校验更稳**:数字选项输入非法字符时不再让菜单崩溃,而是显示提示消息。
345
+ - **Preset 可见性**:应用 preset 后会显示实际 context、reserve、output、
346
+ timeout 值。
347
+
348
+ ### 0.1.38
349
+
350
+ - **优先使用用户选择的 context window**:移除 NVIDIA hosted 的 32K safety cap。
351
+ router 会使用 LLM options 或 headless 配置中选择的 context window,
352
+ 只有未配置时才使用按模型推断的 fallback。
353
+ - **NVIDIA preset 更新**:NVIDIA hosted preset 从 65K 起步,
354
+ large-output/reasoning 工作流最高使用 256K。
355
+
340
356
  ### 0.1.37
341
357
 
342
358
  - **Pseudo tool-call recovery**:NVIDIA/OpenAI-compatible stream 路径现在会
package/docs/manual.md CHANGED
@@ -10,7 +10,7 @@ Code starts, while passing normal Claude Code arguments through unchanged.
10
10
 
11
11
  Credits: One Ciel LLC
12
12
 
13
- Current version: `0.1.37`
13
+ Current version: `0.1.39`
14
14
 
15
15
  ## Install
16
16
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@oneciel-ai/claude-any",
3
- "version": "0.1.37",
3
+ "version": "0.1.39",
4
4
  "description": "Claude Code provider selector for Anthropic, Ollama, Ollama Cloud, vLLM, NVIDIA hosted, and self-hosted NIM.",
5
5
  "license": "MIT",
6
6
  "author": "One Ciel LLC",