@oneciel-ai/claude-any 0.1.92 → 0.1.94

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.
Files changed (2) hide show
  1. package/claude_any.py +56 -6
  2. package/package.json +1 -1
package/claude_any.py CHANGED
@@ -105,7 +105,7 @@ OFFICIAL_CHANNEL_PLUGINS = {
105
105
  "fakechat": "plugin:fakechat@claude-plugins-official",
106
106
  }
107
107
  APP_NAME = "Claude Any"
108
- VERSION = "0.1.92"
108
+ VERSION = "0.1.94"
109
109
  CREDITS = "Credits: One Ciel LLC"
110
110
 
111
111
  LOG_LEVELS = {"SILENT": 0, "ERROR": 1, "WARN": 2, "INFO": 3, "DEBUG": 4, "TRACE": 5}
@@ -5083,6 +5083,45 @@ def _channel_mcp_update_cursor(last_id: int) -> None:
5083
5083
  router_log("WARN", f"channel_mcp_cursor_write_failed error={type(exc).__name__}: {exc}")
5084
5084
 
5085
5085
 
5086
+ def _channel_mcp_parse_event_id(value: Any) -> int | None:
5087
+ text = str(value or "").strip()
5088
+ if not text:
5089
+ return None
5090
+ try:
5091
+ return max(0, int(text))
5092
+ except Exception:
5093
+ return None
5094
+
5095
+
5096
+ def _channel_mcp_client_last_event_id(handler: BaseHTTPRequestHandler) -> int | None:
5097
+ try:
5098
+ event_id = _channel_mcp_parse_event_id(handler.headers.get("Last-Event-ID"))
5099
+ if event_id is not None:
5100
+ return event_id
5101
+ except Exception:
5102
+ pass
5103
+ try:
5104
+ params = _query_params(handler)
5105
+ for key in ("lastEventId", "last_event_id", "last_id"):
5106
+ event_id = _channel_mcp_parse_event_id(_first_param(params, key))
5107
+ if event_id is not None:
5108
+ return event_id
5109
+ except Exception:
5110
+ pass
5111
+ return None
5112
+
5113
+
5114
+ def _channel_mcp_session_start_last_id(handler: BaseHTTPRequestHandler) -> int:
5115
+ cursor_last_id = _channel_mcp_ensure_cursor_initialized()
5116
+ client_last_id = _channel_mcp_client_last_event_id(handler)
5117
+ if client_last_id is None:
5118
+ return cursor_last_id
5119
+ if client_last_id > cursor_last_id:
5120
+ _channel_mcp_update_cursor(client_last_id)
5121
+ router_log("INFO", f"channel_mcp_resume client_last_id={client_last_id} cursor_last_id={cursor_last_id}")
5122
+ return client_last_id
5123
+
5124
+
5086
5125
  def _channel_mcp_notifications_for_messages(
5087
5126
  messages: list[dict[str, Any]],
5088
5127
  session: str = "",
@@ -5102,7 +5141,7 @@ def _channel_mcp_notifications_for_messages(
5102
5141
  events.append((last_id, _channel_mcp_notification(message)))
5103
5142
  router_log(
5104
5143
  "INFO",
5105
- f"channel_mcp_notification_sent session={session or '-'} message_id={message.get('id')} channel={message.get('channel')}",
5144
+ f"channel_mcp_notification_prepared session={session or '-'} message_id={message.get('id')} channel={message.get('channel')}",
5106
5145
  )
5107
5146
  return last_id, events
5108
5147
 
@@ -5114,7 +5153,7 @@ def handle_channel_mcp_get(handler: BaseHTTPRequestHandler, path: str) -> bool:
5114
5153
  if path != "/ca/mcp/sse":
5115
5154
  return False
5116
5155
  session = _channel_mcp_session_id()
5117
- last_id = _channel_mcp_ensure_cursor_initialized()
5156
+ last_id = _channel_mcp_session_start_last_id(handler)
5118
5157
  with _CHANNEL_MCP_LOCK:
5119
5158
  _CHANNEL_MCP_SESSIONS[session] = {"created_at": time.time(), "last_id": last_id, "initialized": False, "outbox": []}
5120
5159
  router_log("INFO", f"channel_mcp_session_started session={session} last_id={last_id}")
@@ -5149,7 +5188,9 @@ def handle_channel_mcp_get(handler: BaseHTTPRequestHandler, path: str) -> bool:
5149
5188
  last_id = max(last_id, delivered_last_id)
5150
5189
  for event_id, notification in events:
5151
5190
  _write_sse_event(handler, "message", notification, event_id)
5152
- _channel_mcp_update_cursor(last_id)
5191
+ router_log("INFO", f"channel_mcp_notification_written session={session} message_id={event_id}")
5192
+ if not events:
5193
+ _channel_mcp_update_cursor(last_id)
5153
5194
  with _CHANNEL_MCP_LOCK:
5154
5195
  state = _CHANNEL_MCP_SESSIONS.get(session)
5155
5196
  if state:
@@ -14137,6 +14178,15 @@ def _channel_enter_bytes_from_user_input(data: bytes) -> bytes | None:
14137
14178
  return b"\r\n" if last_cr + 1 < len(data) and data[last_cr + 1 : last_cr + 2] == b"\n" else b"\r"
14138
14179
 
14139
14180
 
14181
+ def _channel_synthetic_enter_bytes_from_user_input(data: bytes) -> bytes | None:
14182
+ observed = _channel_enter_bytes_from_user_input(data)
14183
+ if observed == b"\r":
14184
+ # Bare CR is common from raw POSIX terminals, but synthetic CR-only
14185
+ # writes can sit in Claude Code's line editor on some PTY stacks.
14186
+ return b"\r\n"
14187
+ return observed
14188
+
14189
+
14140
14190
  def _channel_enter_label(enter_bytes: bytes) -> str:
14141
14191
  if enter_bytes == b"\r":
14142
14192
  return "cr"
@@ -14217,8 +14267,8 @@ def subprocess_call_with_channel_wake_proxy(cmd: list[str], env: dict[str, str])
14217
14267
  if stdin_fd in readable:
14218
14268
  data = os.read(stdin_fd, 4096)
14219
14269
  if data:
14220
- observed_enter = _channel_enter_bytes_from_user_input(data)
14221
- if observed_enter:
14270
+ observed_enter = _channel_synthetic_enter_bytes_from_user_input(data)
14271
+ if observed_enter and not os.environ.get("CLAUDE_ANY_CHANNEL_WAKE_ENTER"):
14222
14272
  channel_enter_bytes = observed_enter
14223
14273
  _write_fd_all(master_fd, data)
14224
14274
  if master_fd in readable:
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@oneciel-ai/claude-any",
3
- "version": "0.1.92",
3
+ "version": "0.1.94",
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",