@oneciel-ai/claude-any 0.1.82 → 0.1.83
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/claude_any.py +55 -9
- package/package.json +1 -1
package/claude_any.py
CHANGED
|
@@ -104,7 +104,7 @@ OFFICIAL_CHANNEL_PLUGINS = {
|
|
|
104
104
|
"fakechat": "plugin:fakechat@claude-plugins-official",
|
|
105
105
|
}
|
|
106
106
|
APP_NAME = "Claude Any"
|
|
107
|
-
VERSION = "0.1.
|
|
107
|
+
VERSION = "0.1.83"
|
|
108
108
|
CREDITS = "Credits: One Ciel LLC"
|
|
109
109
|
|
|
110
110
|
LOG_LEVELS = {"SILENT": 0, "ERROR": 1, "WARN": 2, "INFO": 3, "DEBUG": 4, "TRACE": 5}
|
|
@@ -13749,14 +13749,52 @@ def _write_fd_all(fd: int, data: bytes) -> None:
|
|
|
13749
13749
|
view = view[written:]
|
|
13750
13750
|
|
|
13751
13751
|
|
|
13752
|
-
def
|
|
13752
|
+
def _channel_wake_enter_bytes(value: str | bytes | None = None) -> bytes:
|
|
13753
|
+
raw: str | bytes | None = value
|
|
13754
|
+
if raw is None:
|
|
13755
|
+
raw = os.environ.get("CLAUDE_ANY_CHANNEL_WAKE_ENTER")
|
|
13756
|
+
if isinstance(raw, bytes):
|
|
13757
|
+
return raw if raw in (b"\n", b"\r", b"\r\n") else b"\n"
|
|
13758
|
+
normalized = str(raw or "").strip().lower()
|
|
13759
|
+
if normalized in {"", "lf", "nl", "newline", "linefeed", "\\n"}:
|
|
13760
|
+
return b"\n"
|
|
13761
|
+
if normalized in {"cr", "return", "carriage-return", "carriage_return", "\\r"}:
|
|
13762
|
+
return b"\r"
|
|
13763
|
+
if normalized in {"crlf", "cr-lf", "return-newline", "\\r\\n"}:
|
|
13764
|
+
return b"\r\n"
|
|
13765
|
+
return b"\n"
|
|
13766
|
+
|
|
13767
|
+
|
|
13768
|
+
def _channel_enter_bytes_from_user_input(data: bytes) -> bytes | None:
|
|
13769
|
+
if not data:
|
|
13770
|
+
return None
|
|
13771
|
+
if data in (b"\n", b"\r", b"\r\n"):
|
|
13772
|
+
return data
|
|
13773
|
+
last_lf = data.rfind(b"\n")
|
|
13774
|
+
last_cr = data.rfind(b"\r")
|
|
13775
|
+
if last_lf < 0 and last_cr < 0:
|
|
13776
|
+
return None
|
|
13777
|
+
if last_lf > last_cr:
|
|
13778
|
+
return b"\r\n" if last_lf > 0 and data[last_lf - 1 : last_lf] == b"\r" else b"\n"
|
|
13779
|
+
return b"\r\n" if last_cr + 1 < len(data) and data[last_cr + 1 : last_cr + 2] == b"\n" else b"\r"
|
|
13780
|
+
|
|
13781
|
+
|
|
13782
|
+
def _channel_enter_label(enter_bytes: bytes) -> str:
|
|
13783
|
+
if enter_bytes == b"\r":
|
|
13784
|
+
return "cr"
|
|
13785
|
+
if enter_bytes == b"\r\n":
|
|
13786
|
+
return "crlf"
|
|
13787
|
+
return "lf"
|
|
13788
|
+
|
|
13789
|
+
|
|
13790
|
+
def _channel_wake_input_bytes(prompt: str, enter_bytes: bytes | None = None) -> bytes:
|
|
13753
13791
|
# Ctrl-U clears any stale line editor text before submitting the synthetic prompt.
|
|
13754
|
-
# Claude Code's interactive input is terminal-driven
|
|
13755
|
-
#
|
|
13756
|
-
return b"\x15" + prompt.encode("utf-8", errors="replace") +
|
|
13792
|
+
# Claude Code's interactive input is terminal-driven; the submit byte can
|
|
13793
|
+
# differ by PTY/input stack, so callers pass the observed Enter sequence.
|
|
13794
|
+
return b"\x15" + prompt.encode("utf-8", errors="replace") + _channel_wake_enter_bytes(enter_bytes)
|
|
13757
13795
|
|
|
13758
13796
|
|
|
13759
|
-
def _inject_pending_channel_messages(master_fd: int, last_id: int) -> int:
|
|
13797
|
+
def _inject_pending_channel_messages(master_fd: int, last_id: int, enter_bytes: bytes | None = None) -> int:
|
|
13760
13798
|
pending: list[dict[str, Any]] = []
|
|
13761
13799
|
for message in read_chat_messages(last_id, None, None, 100):
|
|
13762
13800
|
try:
|
|
@@ -13773,10 +13811,14 @@ def _inject_pending_channel_messages(master_fd: int, last_id: int) -> int:
|
|
|
13773
13811
|
pending.append(message)
|
|
13774
13812
|
if pending:
|
|
13775
13813
|
prompt = format_channel_wake_batch_prompt(pending)
|
|
13776
|
-
|
|
13814
|
+
submit_bytes = _channel_wake_enter_bytes(enter_bytes)
|
|
13815
|
+
_write_fd_all(master_fd, _channel_wake_input_bytes(prompt, submit_bytes))
|
|
13777
13816
|
ids = ",".join(str(message.get("id") or "") for message in pending)
|
|
13778
13817
|
channels = ",".join(sorted({str(message.get("channel") or "default") for message in pending}))
|
|
13779
|
-
router_log(
|
|
13818
|
+
router_log(
|
|
13819
|
+
"INFO",
|
|
13820
|
+
f"channel_stdin_proxy_injected count={len(pending)} message_ids={ids} channels={channels} enter={_channel_enter_label(submit_bytes)}",
|
|
13821
|
+
)
|
|
13780
13822
|
return last_id
|
|
13781
13823
|
|
|
13782
13824
|
|
|
@@ -13806,6 +13848,7 @@ def subprocess_call_with_channel_wake_proxy(cmd: list[str], env: dict[str, str])
|
|
|
13806
13848
|
stdout_fd = sys.stdout.fileno()
|
|
13807
13849
|
old_attrs = termios.tcgetattr(stdin_fd)
|
|
13808
13850
|
last_channel_poll = 0.0
|
|
13851
|
+
channel_enter_bytes = _channel_wake_enter_bytes()
|
|
13809
13852
|
try:
|
|
13810
13853
|
tty.setraw(stdin_fd)
|
|
13811
13854
|
while proc.poll() is None:
|
|
@@ -13816,6 +13859,9 @@ def subprocess_call_with_channel_wake_proxy(cmd: list[str], env: dict[str, str])
|
|
|
13816
13859
|
if stdin_fd in readable:
|
|
13817
13860
|
data = os.read(stdin_fd, 4096)
|
|
13818
13861
|
if data:
|
|
13862
|
+
observed_enter = _channel_enter_bytes_from_user_input(data)
|
|
13863
|
+
if observed_enter:
|
|
13864
|
+
channel_enter_bytes = observed_enter
|
|
13819
13865
|
_write_fd_all(master_fd, data)
|
|
13820
13866
|
if master_fd in readable:
|
|
13821
13867
|
try:
|
|
@@ -13830,7 +13876,7 @@ def subprocess_call_with_channel_wake_proxy(cmd: list[str], env: dict[str, str])
|
|
|
13830
13876
|
marker = _chat_messages_file_marker()
|
|
13831
13877
|
if marker != last_channel_marker:
|
|
13832
13878
|
last_channel_marker = marker
|
|
13833
|
-
last_id = _inject_pending_channel_messages(master_fd, last_id)
|
|
13879
|
+
last_id = _inject_pending_channel_messages(master_fd, last_id, channel_enter_bytes)
|
|
13834
13880
|
while True:
|
|
13835
13881
|
try:
|
|
13836
13882
|
readable, _, _ = select.select([master_fd], [], [], 0)
|
package/package.json
CHANGED