Обновить модели DeepSeek, добавить CLAUDE.md и тесты сигналов
- claude_setup.sh: обновлён эндпоинт DeepSeek API (/v1/models вместо /anthropic/v1/models), исправлена аутентификация (Authorization: Bearer вместо x-api-key), обновлены модели (deepseek-v4-pro, deepseek-v4-flash), убрано предложение сделать , добавлен авто-перезапуск shell после выполнения скрипта - CLAUDE.md: правила для агентов (запрет самостоятельных коммитов) - test_interactive.py: тест обработки SIGINT в интерактивном bash (PTY) - test_sigint.sh: тест сигналов для фоновых процессов Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
5
CLAUDE.md
Normal file
5
CLAUDE.md
Normal file
@@ -0,0 +1,5 @@
|
|||||||
|
# Правила для агентов (Agent Instructions)
|
||||||
|
|
||||||
|
Данные правила применяются ко всем агентам (Claude, Gemini, DeepSeek и др.), работающим в этом проекте.
|
||||||
|
|
||||||
|
1. **Никаких самостоятельных коммитов (No unauthorized commits):** ЗАПРЕЩЕНО выполнять команду `git commit`, если пользователь прямо и недвусмысленно не попросил об этом. Вы можете изменять файлы, выполнять `git add` (если это часть подготовки), но финальный коммит делает пользователь или вы — строго по его команде.
|
||||||
@@ -226,9 +226,9 @@ claude_deepseek() {
|
|||||||
|
|
||||||
echo "Проверяю ключ..."
|
echo "Проверяю ключ..."
|
||||||
local http_code
|
local http_code
|
||||||
http_code=$(curl -sf -o /dev/null -w "%{http_code}" \
|
http_code=$(curl -s -o /dev/null -w "%{http_code}" \
|
||||||
https://api.deepseek.com/anthropic/v1/models \
|
https://api.deepseek.com/v1/models \
|
||||||
-H "x-api-key: $api_key" 2>/dev/null || echo "000")
|
-H "Authorization: Bearer $api_key" 2>/dev/null || echo "000")
|
||||||
|
|
||||||
if [ "$http_code" = "200" ]; then
|
if [ "$http_code" = "200" ]; then
|
||||||
mkdir -p "$(dirname "$key_file")"
|
mkdir -p "$(dirname "$key_file")"
|
||||||
@@ -248,11 +248,11 @@ claude_deepseek() {
|
|||||||
|
|
||||||
ANTHROPIC_BASE_URL=https://api.deepseek.com/anthropic \
|
ANTHROPIC_BASE_URL=https://api.deepseek.com/anthropic \
|
||||||
ANTHROPIC_AUTH_TOKEN="$api_key" \
|
ANTHROPIC_AUTH_TOKEN="$api_key" \
|
||||||
ANTHROPIC_MODEL=deepseek-chat \
|
ANTHROPIC_MODEL=deepseek-v4-pro \
|
||||||
ANTHROPIC_DEFAULT_OPUS_MODEL=deepseek-chat \
|
ANTHROPIC_DEFAULT_OPUS_MODEL=deepseek-v4-pro \
|
||||||
ANTHROPIC_DEFAULT_SONNET_MODEL=deepseek-chat \
|
ANTHROPIC_DEFAULT_SONNET_MODEL=deepseek-v4-pro \
|
||||||
ANTHROPIC_DEFAULT_HAIKU_MODEL=deepseek-chat \
|
ANTHROPIC_DEFAULT_HAIKU_MODEL=deepseek-v4-flash \
|
||||||
CLAUDE_CODE_SUBAGENT_MODEL=deepseek-chat \
|
CLAUDE_CODE_SUBAGENT_MODEL=deepseek-v4-flash \
|
||||||
CLAUDE_CODE_DISABLE_NONESSENTIAL_TRAFFIC=1 \
|
CLAUDE_CODE_DISABLE_NONESSENTIAL_TRAFFIC=1 \
|
||||||
claude "$@"
|
claude "$@"
|
||||||
}
|
}
|
||||||
@@ -338,10 +338,6 @@ echo -e "${GREEN}═════════════════════
|
|||||||
echo -e "${GREEN} Установка завершена!${NC}"
|
echo -e "${GREEN} Установка завершена!${NC}"
|
||||||
echo -e "${GREEN}════════════════════════════════════════════════════${NC}"
|
echo -e "${GREEN}════════════════════════════════════════════════════${NC}"
|
||||||
echo ""
|
echo ""
|
||||||
echo "Примените изменения:"
|
|
||||||
echo ""
|
|
||||||
echo -e " ${CYAN}source ~/.bashrc${NC}"
|
|
||||||
echo ""
|
|
||||||
echo "Доступные команды:"
|
echo "Доступные команды:"
|
||||||
echo -e " ${CYAN}claude_anthropic${NC} — оригинальный Claude (Anthropic API)"
|
echo -e " ${CYAN}claude_anthropic${NC} — оригинальный Claude (Anthropic API)"
|
||||||
echo -e " ${CYAN}claude_gpt${NC} — GPT-5.5 (ChatGPT Plus/Pro, браузерная авторизация)"
|
echo -e " ${CYAN}claude_gpt${NC} — GPT-5.5 (ChatGPT Plus/Pro, браузерная авторизация)"
|
||||||
@@ -359,3 +355,11 @@ echo -e " GPT статус: ${CYAN}claude-code-proxy codex auth status${NC}
|
|||||||
echo -e " GPT выйти: ${CYAN}claude-code-proxy codex auth logout${NC}"
|
echo -e " GPT выйти: ${CYAN}claude-code-proxy codex auth logout${NC}"
|
||||||
echo -e " Gemini WebUI: ${CYAN}http://localhost:8080${NC} (когда прокси запущен)"
|
echo -e " Gemini WebUI: ${CYAN}http://localhost:8080${NC} (когда прокси запущен)"
|
||||||
echo ""
|
echo ""
|
||||||
|
|
||||||
|
if [ "$0" != "${BASH_SOURCE[0]}" ]; then
|
||||||
|
return 0 2>/dev/null || exit 0
|
||||||
|
fi
|
||||||
|
|
||||||
|
echo -e "${CYAN}Перезапускаю shell для применения функций...${NC}"
|
||||||
|
exec bash
|
||||||
|
echo ""
|
||||||
|
|||||||
135
test_interactive.py
Normal file
135
test_interactive.py
Normal file
@@ -0,0 +1,135 @@
|
|||||||
|
import os
|
||||||
|
import pty
|
||||||
|
import time
|
||||||
|
import subprocess
|
||||||
|
import signal
|
||||||
|
|
||||||
|
def run_test():
|
||||||
|
# Create pseudo-terminal
|
||||||
|
master, slave = pty.openpty()
|
||||||
|
|
||||||
|
# Start bash in interactive mode
|
||||||
|
p = subprocess.Popen(
|
||||||
|
['bash', '-i'],
|
||||||
|
stdin=slave,
|
||||||
|
stdout=slave,
|
||||||
|
stderr=slave,
|
||||||
|
close_fds=True,
|
||||||
|
preexec_fn=os.setsid # Create a new session/process group
|
||||||
|
)
|
||||||
|
|
||||||
|
# Close slave end in parent
|
||||||
|
os.close(slave)
|
||||||
|
|
||||||
|
# Set master to non-blocking
|
||||||
|
os.set_blocking(master, False)
|
||||||
|
|
||||||
|
# Helper to write to bash
|
||||||
|
def write_to_bash(cmd):
|
||||||
|
os.write(master, cmd.encode())
|
||||||
|
time.sleep(0.5)
|
||||||
|
|
||||||
|
# Define function in the interactive shell
|
||||||
|
func_def = """
|
||||||
|
my_func() {
|
||||||
|
sleep 100 &
|
||||||
|
local bg_pid=$!
|
||||||
|
echo "ACTUAL_BG_PID:$bg_pid"
|
||||||
|
sleep 10
|
||||||
|
echo "RUNNING CLEANUP"
|
||||||
|
kill $bg_pid 2>/dev/null
|
||||||
|
wait $bg_pid 2>/dev/null
|
||||||
|
echo "CLEANUP DONE"
|
||||||
|
}
|
||||||
|
"""
|
||||||
|
write_to_bash(func_def + "\n")
|
||||||
|
|
||||||
|
# Run the function
|
||||||
|
write_to_bash("my_func\n")
|
||||||
|
|
||||||
|
# Read output to wait for "ACTUAL_BG_PID:"
|
||||||
|
output = b""
|
||||||
|
start_time = time.time()
|
||||||
|
bg_pid = None
|
||||||
|
while time.time() - start_time < 5:
|
||||||
|
try:
|
||||||
|
r = os.read(master, 1024)
|
||||||
|
if r:
|
||||||
|
output += r
|
||||||
|
except BlockingIOError:
|
||||||
|
pass
|
||||||
|
|
||||||
|
if b"ACTUAL_BG_PID:" in output:
|
||||||
|
parts = output.split(b"ACTUAL_BG_PID:")
|
||||||
|
if len(parts) > 1:
|
||||||
|
# Get the part after ACTUAL_BG_PID:
|
||||||
|
rest = parts[-1].strip()
|
||||||
|
# Split by newline or carriage return or spaces
|
||||||
|
potential_pid = rest.split(b"\r")[0].split(b"\n")[0].split(b" ")[0].decode().strip()
|
||||||
|
if potential_pid.isdigit():
|
||||||
|
bg_pid = int(potential_pid)
|
||||||
|
break
|
||||||
|
time.sleep(0.1)
|
||||||
|
|
||||||
|
print("Found BG PID:", bg_pid)
|
||||||
|
print("Output so far:", output.decode('utf-8', errors='ignore'))
|
||||||
|
|
||||||
|
if bg_pid is None:
|
||||||
|
print("Error: Could not find BG PID.")
|
||||||
|
p.terminate()
|
||||||
|
return
|
||||||
|
|
||||||
|
# Wait a bit to ensure it is sleeping
|
||||||
|
time.sleep(1)
|
||||||
|
|
||||||
|
# In a terminal, Ctrl+C sends SIGINT to the foreground process group.
|
||||||
|
# The shell sets the foreground process group of the terminal to the active job.
|
||||||
|
# Let's get the foreground process group of the master terminal.
|
||||||
|
# We can use os.tcgetpgrp(master) to get the process group currently in the foreground!
|
||||||
|
try:
|
||||||
|
fore_pgid = os.tcgetpgrp(master)
|
||||||
|
print(f"Foreground process group of tty: {fore_pgid}")
|
||||||
|
# Send SIGINT to the foreground process group
|
||||||
|
os.killpg(fore_pgid, signal.SIGINT)
|
||||||
|
except Exception as e:
|
||||||
|
print("Failed to get foreground pgid via tcgetpgrp or killpg:", e)
|
||||||
|
# Fallback: kill the bash process group
|
||||||
|
pgid = os.getpgid(p.pid)
|
||||||
|
print(f"Fallback: sending SIGINT to bash process group {pgid}")
|
||||||
|
os.killpg(pgid, signal.SIGINT)
|
||||||
|
|
||||||
|
# Give it some time to process
|
||||||
|
time.sleep(2)
|
||||||
|
|
||||||
|
# Let's read the remaining output to see if "RUNNING CLEANUP" was printed
|
||||||
|
try:
|
||||||
|
time.sleep(1)
|
||||||
|
remaining = b""
|
||||||
|
start_time = time.time()
|
||||||
|
while time.time() - start_time < 2:
|
||||||
|
try:
|
||||||
|
r = os.read(master, 4096)
|
||||||
|
if r:
|
||||||
|
remaining += r
|
||||||
|
except BlockingIOError:
|
||||||
|
pass
|
||||||
|
time.sleep(0.1)
|
||||||
|
print("Remaining output:", remaining.decode('utf-8', errors='ignore'))
|
||||||
|
except Exception as e:
|
||||||
|
print("Read error or no more output:", e)
|
||||||
|
|
||||||
|
# Check if bg_pid is still running
|
||||||
|
try:
|
||||||
|
os.kill(bg_pid, 0)
|
||||||
|
print(f"VERDICT: Process {bg_pid} is STILL RUNNING! It was orphaned!")
|
||||||
|
# Clean it up
|
||||||
|
os.kill(bg_pid, signal.SIGKILL)
|
||||||
|
except OSError:
|
||||||
|
print(f"VERDICT: Process {bg_pid} is NOT running. Cleanup worked!")
|
||||||
|
|
||||||
|
# Clean up bash
|
||||||
|
p.terminate()
|
||||||
|
p.wait()
|
||||||
|
|
||||||
|
if __name__ == '__main__':
|
||||||
|
run_test()
|
||||||
18
test_sigint.sh
Normal file
18
test_sigint.sh
Normal file
@@ -0,0 +1,18 @@
|
|||||||
|
#!/usr/bin/env bash
|
||||||
|
|
||||||
|
test_func() {
|
||||||
|
echo "Starting background process..."
|
||||||
|
sleep 100 &
|
||||||
|
local pid=$!
|
||||||
|
echo "Background PID: $pid"
|
||||||
|
|
||||||
|
echo "Starting foreground sleep (simulate claude)..."
|
||||||
|
sleep 10
|
||||||
|
|
||||||
|
echo "Foreground sleep finished. Cleaning up background process $pid..."
|
||||||
|
kill "$pid"
|
||||||
|
wait "$pid" 2>/dev/null
|
||||||
|
echo "Cleanup done."
|
||||||
|
}
|
||||||
|
|
||||||
|
test_func
|
||||||
Reference in New Issue
Block a user