Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -67,6 +67,8 @@ Each agent has a `soul.md` (personality), `memory.md` (long-term memory), and a
- 2-core CPU / 4 GB RAM / 30 GB disk (minimum)
- Network access to LLM API endpoints

> **Ubuntu/Debian note:** If you use the system Python 3.12 package, also install `python3.12-venv`; otherwise `bash setup.sh` will fail when creating the backend virtual environment.

> **Note:** Clawith does not run any AI models locally — all LLM inference is handled by external API providers (OpenAI, Anthropic, etc.). The local deployment is a standard web application with Docker orchestration.

#### Recommended Configurations
Expand Down
2 changes: 2 additions & 0 deletions README_zh-CN.md
Original file line number Diff line number Diff line change
Expand Up @@ -67,6 +67,8 @@ Agent 可以在运行时**发现并安装新工具**([Smithery](https://smithe
- 2 核 CPU / 4 GB 内存 / 30 GB 磁盘(最低配置)
- 可访问 LLM API

> **Ubuntu/Debian 额外说明:** 如果使用系统 Python 3.12,请同时安装 `python3.12-venv`,否则 `bash setup.sh` 在创建后端虚拟环境时会失败。

> **说明:** Clawith 不在本地运行任何 AI 模型——所有 LLM 推理均由外部 API 提供商处理(OpenAI、Anthropic 等)。本地部署本质上是一个标准 Web 应用 + Docker 编排。

#### 各场景推荐配置
Expand Down
14 changes: 11 additions & 3 deletions backend/app/api/wecom.py
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@
from app.models.identity import IdentityProvider, SSOScanSession
from app.models.user import User
from app.services.activity_logger import log_activity
from app.services.auth_provider import auth_provider_registry
from app.services.auth_registry import auth_provider_registry
from app.services.channel_session import find_or_create_channel_session
from app.services.channel_user_service import channel_user_service
from app.services.platform_service import platform_service
Expand Down Expand Up @@ -686,7 +686,13 @@ async def wecom_callback(

# 2. Extract user info and login/register via RegistrationService
try:
auth_provider = auth_provider_registry.get_provider(provider)
auth_provider = await auth_provider_registry.get_provider(
db,
"wecom",
str(tenant_id) if tenant_id else None,
)
if not auth_provider:
raise HTTPException(status_code=404, detail="WeCom provider not available")
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Preserve 404 when WeCom provider is unavailable

Raising HTTPException(404) here is ineffective because the surrounding try in wecom_callback catches all exceptions and always returns HTMLResponse(...) with HTTP 200. This means when auth_provider_registry.get_provider(...) returns None (for example, if the tenant’s WeCom provider exists but is inactive), clients receive a success status with an error string instead of a real 404, which breaks status-based error handling and monitoring.

Useful? React with 👍 / 👎.

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Good catch — fixed in beb2311. Added except HTTPException: raise before the broad except Exception so the 404 (and any future HTTPException) propagates instead of being converted into HTMLResponse 200.


token_data = await auth_provider.exchange_code_for_token(code)
access_token_str = token_data.get("access_token")
Expand All @@ -698,9 +704,11 @@ async def wecom_callback(
return HTMLResponse("Auth failed: No UserId returned")

# Find or Create User (handles Identity and OrgMember linking)
user = await auth_provider.find_or_create_user(
user, _ = await auth_provider.find_or_create_user(
db, user_info, tenant_id=tenant_id or provider.tenant_id
)
except HTTPException:
raise
except Exception as e:
logger.exception(f"WeCom login/register error: {e}")
return HTMLResponse(f"Auth failed: {str(e)}")
Expand Down
2 changes: 1 addition & 1 deletion backend/pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
name = "clawith-backend"
version = "0.1.0"
description = "Clawith - Enterprise Digital Employee Platform Backend"
requires-python = ">=3.11"
requires-python = ">=3.12"
dependencies = [
"fastapi[standard]>=0.115.0",
"uvicorn[standard]>=0.30.0",
Expand Down
42 changes: 25 additions & 17 deletions setup.sh
Original file line number Diff line number Diff line change
Expand Up @@ -131,7 +131,8 @@ if PG_BIN_DIR=$(find_psql 2>/dev/null); then

# Try to create role and database
ROLE_EXISTS=false
if psql -h localhost -p $PG_PORT -U "$USER" -d postgres -tAc "SELECT 1 FROM pg_roles WHERE rolname='clawith'" 2>/dev/null | grep -q 1; then
# Use --no-password so existing PostgreSQL setups don't hang on an interactive prompt.
if psql -w -h localhost -p $PG_PORT -U "$USER" -d postgres -tAc "SELECT 1 FROM pg_roles WHERE rolname='clawith'" 2>/dev/null | grep -q 1; then
ROLE_EXISTS=true
echo -e " ${GREEN}✓${NC} Role 'clawith' already exists"
elif sudo -u postgres psql -tAc "SELECT 1 FROM pg_roles WHERE rolname='clawith'" 2>/dev/null | grep -q 1; then
Expand All @@ -141,8 +142,8 @@ if PG_BIN_DIR=$(find_psql 2>/dev/null); then

if [ "$ROLE_EXISTS" = false ]; then
# Try 1: as current user
if createuser -h localhost -p $PG_PORT clawith 2>/dev/null; then
psql -h localhost -p $PG_PORT -U "$USER" -d postgres -c "ALTER ROLE clawith WITH LOGIN PASSWORD 'clawith';" &>/dev/null
if createuser -w -h localhost -p $PG_PORT clawith 2>/dev/null; then
psql -w -h localhost -p $PG_PORT -U "$USER" -d postgres -c "ALTER ROLE clawith WITH LOGIN PASSWORD 'clawith';" &>/dev/null
echo -e " ${GREEN}✓${NC} Created PostgreSQL role: clawith"
# Try 2: via sudo -u postgres (standard Linux setup)
elif sudo -u postgres createuser clawith 2>/dev/null && \
Expand All @@ -156,7 +157,7 @@ if PG_BIN_DIR=$(find_psql 2>/dev/null); then

if [ -n "$PG_BIN_DIR" ] || command -v psql &>/dev/null; then
DB_EXISTS=false
if psql -h localhost -p $PG_PORT -U "$USER" -lqt 2>/dev/null | cut -d\| -f1 | grep -qw clawith; then
if psql -w -h localhost -p $PG_PORT -U "$USER" -lqt 2>/dev/null | cut -d\| -f1 | grep -qw clawith; then
DB_EXISTS=true
elif sudo -u postgres psql -lqt 2>/dev/null | cut -d\| -f1 | grep -qw clawith; then
DB_EXISTS=true
Expand All @@ -165,7 +166,7 @@ if PG_BIN_DIR=$(find_psql 2>/dev/null); then
if [ "$DB_EXISTS" = true ]; then
echo -e " ${GREEN}✓${NC} Database 'clawith' already exists"
else
if createdb -h localhost -p $PG_PORT -O clawith clawith 2>/dev/null || \
if createdb -w -h localhost -p $PG_PORT -O clawith clawith 2>/dev/null || \
sudo -u postgres createdb -O clawith clawith 2>/dev/null; then
echo -e " ${GREEN}✓${NC} Created database: clawith"
fi
Expand Down Expand Up @@ -246,14 +247,14 @@ if [ -z "$PG_BIN_DIR" ] && ! (PGPASSWORD=clawith psql -h localhost -p 5432 -U cl
done
# Create role and database
if command -v psql &>/dev/null; then
if ! psql -h localhost -p $PG_PORT -U postgres -tAc "SELECT 1 FROM pg_roles WHERE rolname='clawith'" 2>/dev/null | grep -q 1; then
sudo -u postgres createuser clawith 2>/dev/null || createuser -h localhost -p $PG_PORT clawith 2>/dev/null || true
if ! psql -w -h localhost -p $PG_PORT -U postgres -tAc "SELECT 1 FROM pg_roles WHERE rolname='clawith'" 2>/dev/null | grep -q 1; then
sudo -u postgres createuser clawith 2>/dev/null || createuser -w -h localhost -p $PG_PORT clawith 2>/dev/null || true
sudo -u postgres psql -c "ALTER ROLE clawith WITH LOGIN PASSWORD 'clawith';" 2>/dev/null || \
psql -h localhost -p $PG_PORT -U postgres -c "ALTER ROLE clawith WITH LOGIN PASSWORD 'clawith';" 2>/dev/null || true
psql -w -h localhost -p $PG_PORT -U postgres -c "ALTER ROLE clawith WITH LOGIN PASSWORD 'clawith';" 2>/dev/null || true
echo -e " ${GREEN}✓${NC} Created role: clawith"
fi
if ! psql -h localhost -p $PG_PORT -U postgres -lqt 2>/dev/null | cut -d\| -f1 | grep -qw clawith; then
sudo -u postgres createdb -O clawith clawith 2>/dev/null || createdb -h localhost -p $PG_PORT -O clawith clawith 2>/dev/null || true
if ! psql -w -h localhost -p $PG_PORT -U postgres -lqt 2>/dev/null | cut -d\| -f1 | grep -qw clawith; then
sudo -u postgres createdb -O clawith clawith 2>/dev/null || createdb -w -h localhost -p $PG_PORT -O clawith clawith 2>/dev/null || true
echo -e " ${GREEN}✓${NC} Created database: clawith"
fi
PG_MANAGED_BY_US=false # System manages PG now
Expand Down Expand Up @@ -320,13 +321,13 @@ if [ -z "$PG_BIN_DIR" ] && ! (PGPASSWORD=clawith psql -h localhost -p 5432 -U cl
fi

# Create role and database
if ! psql -h localhost -p "$PG_PORT" -U postgres -tAc "SELECT 1 FROM pg_roles WHERE rolname='clawith'" 2>/dev/null | grep -q 1; then
createuser -h localhost -p "$PG_PORT" -U postgres clawith 2>/dev/null || true
psql -h localhost -p "$PG_PORT" -U postgres -c "ALTER ROLE clawith WITH LOGIN PASSWORD 'clawith';" &>/dev/null
if ! psql -w -h localhost -p "$PG_PORT" -U postgres -tAc "SELECT 1 FROM pg_roles WHERE rolname='clawith'" 2>/dev/null | grep -q 1; then
createuser -w -h localhost -p "$PG_PORT" -U postgres clawith 2>/dev/null || true
psql -w -h localhost -p "$PG_PORT" -U postgres -c "ALTER ROLE clawith WITH LOGIN PASSWORD 'clawith';" &>/dev/null
echo -e " ${GREEN}✓${NC} Created role: clawith"
fi
if ! psql -h localhost -p "$PG_PORT" -U postgres -lqt 2>/dev/null | cut -d\| -f1 | grep -qw clawith; then
createdb -h localhost -p "$PG_PORT" -U postgres -O clawith clawith 2>/dev/null
if ! psql -w -h localhost -p "$PG_PORT" -U postgres -lqt 2>/dev/null | cut -d\| -f1 | grep -qw clawith; then
createdb -w -h localhost -p "$PG_PORT" -U postgres -O clawith clawith 2>/dev/null
echo -e " ${GREEN}✓${NC} Created database: clawith"
fi
else
Expand Down Expand Up @@ -366,8 +367,15 @@ cd "$ROOT/backend"

if [ ! -d ".venv" ]; then
echo " Creating Python virtual environment..."
$PYTHON_BIN -m venv .venv
echo -e " ${GREEN}✓${NC} Virtual environment created"
if $PYTHON_BIN -m venv .venv; then
echo -e " ${GREEN}✓${NC} Virtual environment created"
else
echo -e " ${RED}✗${NC} Failed to create Python virtual environment."
echo " On Ubuntu/Debian, install the venv package first:"
echo " sudo apt install python3.12-venv"
echo " Then re-run: bash setup.sh"
exit 1
fi
fi

if [ "$INSTALL_DEV" = true ]; then
Expand Down