awddwasd commited on
Commit
7ddf331
·
verified ·
1 Parent(s): 9b3471a

Upload 3 files

Browse files
Files changed (3) hide show
  1. Dockerfile +37 -0
  2. README.md +28 -7
  3. entrypoint.sh +123 -0
Dockerfile ADDED
@@ -0,0 +1,37 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ FROM node:18-slim
2
+
3
+ # 安装系统工具和 HF CLI
4
+ RUN apt-get update && apt-get install -y \
5
+ curl \
6
+ bash \
7
+ git \
8
+ python3 \
9
+ python3-pip \
10
+ python3.11-venv \
11
+ procps \
12
+ iputils-ping \
13
+ nano \
14
+ vim \
15
+ telnet \
16
+ net-tools \
17
+ wget \
18
+ rsync \
19
+ && curl -LsSf https://hf.co/cli/install.sh | bash \
20
+ && rm -rf /var/lib/apt/lists/*
21
+
22
+ # 安装 OpenCode
23
+ RUN curl -fsSL https://opencode.ai/install | bash
24
+
25
+ # 创建目录
26
+ RUN mkdir -p /home && chmod 777 /home
27
+
28
+ # 复制入口脚本
29
+ COPY entrypoint.sh /entrypoint.sh
30
+ RUN chmod +x /entrypoint.sh
31
+
32
+ # 环境设置
33
+ ENV PATH="/root/.local/bin:/home/node/.local/bin:/home/.local/bin:$PATH"
34
+ ENV NODE_OPTIONS="--max-old-space-size=14336"
35
+
36
+ EXPOSE 7860
37
+ CMD ["/entrypoint.sh"]
README.md CHANGED
@@ -1,12 +1,33 @@
1
  ---
2
- title: Opencodeai
3
- emoji: 📊
4
- colorFrom: blue
5
- colorTo: pink
6
  sdk: docker
7
  pinned: false
8
- license: mit
9
- short_description: opencodeai
10
  ---
11
 
12
- Check out the configuration reference at https://huggingface.co/docs/hub/spaces-config-reference
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
  ---
2
+ title: opencode-ai
3
+ emoji: 🐢
4
+ colorFrom: pink
5
+ colorTo: gray
6
  sdk: docker
7
  pinned: false
 
 
8
  ---
9
 
10
+ ## 环境变量
11
+
12
+ 在 Space Settings → Secrets and variables 中设置:
13
+
14
+ | 变量 | 必填 | 说明 |
15
+ |------|------|------|
16
+ | `OPENCODE_SERVER_USERNAME` | 是 | OpenCode web UI 登录用户名 |
17
+ | `OPENCODE_SERVER_PASSWORD` | 是 | OpenCode web UI 登录密码 |
18
+ | `LOG_LEVEL` | 否 | 日志级别:`debug`/`info`/`warning`(默认:warning) |
19
+
20
+ ## 持久化存储
21
+
22
+ **重要**:需要将 HuggingFace bucket 挂载到 `/root` 目录作为持久化存储。
23
+
24
+ 在 Space Settings → Repo 中:
25
+ - 将 Persistent Storage 路径设置为 `/root`
26
+
27
+ 这样所有数据(用户文件、日志等)都会直接持久化到 bucket,无需额外备份。
28
+
29
+ ## 功能特性
30
+
31
+ - 运行在 HuggingFace Spaces 上的 OpenCode AI 助手
32
+ - 数据持久化到 bucket(/root 目录)
33
+ - RAM 监控,内存超限时自动重启(14GB 限制)
entrypoint.sh ADDED
@@ -0,0 +1,123 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ #!/bin/bash
2
+
3
+ # 设置 DNS(在容器启动后执行)
4
+ echo "nameserver 8.8.8.8" > /tmp/resolv.conf
5
+ echo "nameserver 8.8.4.4" >> /tmp/resolv.conf
6
+ cp /tmp/resolv.conf /etc/resolv.conf 2>/dev/null || true
7
+
8
+ export PATH="/root/.local/bin:$PATH"
9
+
10
+ # 日志级别配置(默认 warning,可选 debug/info/warning)
11
+ LOG_LEVEL="${LOG_LEVEL:-warning}"
12
+
13
+ # 创建日志目录(/root/.opencode/logs 由 bucket 挂载)
14
+ mkdir -p /root/.opencode/logs
15
+ LOG_DIR='/root/.opencode/logs'
16
+ LOG_MAX_SIZE=104857600 # 100MB
17
+
18
+ log() {
19
+ local level="$1"
20
+ shift
21
+ local message="$@"
22
+
23
+ # 检查日志文件大小,超过 100MB 则重命名
24
+ if [ -f "$LOG_DIR/entrypoint.log" ]; then
25
+ LOG_SIZE=$(wc -c < "$LOG_DIR/entrypoint.log" 2>/dev/null | awk '{print $1}')
26
+ if [ -n "$LOG_SIZE" ] && [ "$LOG_SIZE" -gt "$LOG_MAX_SIZE" ]; then
27
+ mv "$LOG_DIR/entrypoint.log" "$LOG_DIR/entrypoint-$(date +%Y-%m-%d).log"
28
+ fi
29
+ fi
30
+
31
+ # 根据 LOG_LEVEL 过滤日志
32
+ case "$LOG_LEVEL" in
33
+ debug)
34
+ # debug: 显示所有日志
35
+ ;;
36
+ info)
37
+ # info: 只显示 info/warning/error
38
+ [ "$level" = "debug" ] && return
39
+ ;;
40
+ warning)
41
+ # warning: 只显示 warning/error
42
+ [ "$level" = "debug" ] && return
43
+ [ "$level" = "info" ] && return
44
+ ;;
45
+ esac
46
+
47
+ # 额外过滤:只显示重要日志到控制台
48
+ local is_important=false
49
+ [ "$level" = "error" ] && is_important=true
50
+ [ "$level" = "warning" ] && is_important=true
51
+
52
+ TIMESTAMP=$(date '+%Y-%m-%d %H:%M:%S')
53
+ if [ "$is_important" = true ]; then
54
+ echo "[$TIMESTAMP] [$level] $message" | tee -a "$LOG_DIR/entrypoint.log"
55
+ else
56
+ echo "[$TIMESTAMP] $message" >> "$LOG_DIR/entrypoint.log"
57
+ fi
58
+ }
59
+
60
+ OPENCODE_LOG_FILE="${LOG_DIR}/opencode.log"
61
+
62
+ # 设置 OpenCode 路径
63
+ OP_PATH=$(find / -name opencode -type f -printf '%h' -quit 2>/dev/null)
64
+ if [ -n "$OP_PATH" ]; then
65
+ export PATH="$OP_PATH:$PATH"
66
+ fi
67
+
68
+ # ============================================
69
+ # 启动 OpenCode(带 RAM 监控)
70
+ # ============================================
71
+ RAM_LIMIT_KB=$((14 * 1024 * 1024))
72
+ RAM_CHECK_INTERVAL=30
73
+
74
+ start_opencode() {
75
+ log info "=== 启动 OpenCode ==="
76
+ export OPENCODE_SERVER_USERNAME=${OPENCODE_SERVER_USERNAME}
77
+ export OPENCODE_SERVER_PASSWORD=${OPENCODE_SERVER_PASSWORD}
78
+ opencode serve --port 7860 --hostname 0.0.0.0 > "$OPENCODE_LOG_FILE" 2>&1 &
79
+ OPENCODE_PID=$!
80
+ log info "=== OpenCode 已启动(PID: $OPENCODE_PID)==="
81
+ }
82
+
83
+ ram_watchdog() {
84
+ while true; do
85
+ if [ -n "$OPENCODE_PID" ] && kill -0 "$OPENCODE_PID" 2>/dev/null; then
86
+ USED_KB=$(ps --no-headers -o rss --ppid "$OPENCODE_PID" 2>/dev/null | awk '{sum+=$1} END {print sum+0}')
87
+ SELF_KB=$(ps --no-headers -o rss -p "$OPENCODE_PID" 2>/dev/null | awk '{print $1+0}')
88
+ TOTAL_KB=$((USED_KB + SELF_KB))
89
+
90
+ # debug 模式显示详细 RAM 信息
91
+ if [ "$LOG_LEVEL" = "debug" ]; then
92
+ USED_MB=$((USED_KB / 1024))
93
+ SELF_MB=$((SELF_KB / 1024))
94
+ TOTAL_MB=$((TOTAL_KB / 1024))
95
+ RAM_PERCENT=$((TOTAL_KB * 100 / RAM_LIMIT_KB))
96
+ log debug "RAM: ${TOTAL_MB}MB / 14336MB (${RAM_PERCENT}%)"
97
+ fi
98
+
99
+ if [ "$TOTAL_KB" -ge "$RAM_LIMIT_KB" ]; then
100
+ log warning "=== [RAM] 内存超限!杀死 OpenCode(${TOTAL_KB}KB >= ${RAM_LIMIT_KB}KB)==="
101
+ kill -9 "$OPENCODE_PID" 2>/dev/null
102
+ sleep 3
103
+ log warning '=== [RAM] 重启 OpenCode... ==='
104
+ start_opencode
105
+ fi
106
+ else
107
+ log warning '=== [RAM] OpenCode 未运行!重启... ==='
108
+ start_opencode
109
+ fi
110
+ sleep "$RAM_CHECK_INTERVAL"
111
+ done
112
+ }
113
+
114
+ start_opencode
115
+ ram_watchdog &
116
+
117
+ log info "=== OpenCode 运行中 ==="
118
+
119
+ # 无限循环:检查 OpenCode 是否运行
120
+ while true; do
121
+ pgrep -f 'opencode' > /dev/null || { log error '严重错误:OpenCode 进程已退出!容器退出...'; exit 1; }
122
+ sleep "$RAM_CHECK_INTERVAL"
123
+ done