Skip to content
Merged
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
367 changes: 367 additions & 0 deletions .github/workflows/fnos-build-fpk.yml

Large diffs are not rendered by default.

6 changes: 6 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -135,6 +135,12 @@ Here are our mid-to-long term plans:

This roadmap may shift as the community grows; treat it as indicative only.


## 🖥️ FnOS (飞牛 NAS) Installation

Octop can be installed on FnOS (飞牛 NAS) devices via the App Center as a `.fpk` package, either as a Docker-backed app or as a native (non-Docker) app. See [`fnos/README.md`](fnos/README.md) for the full packaging guide, the FPK build helper (`scripts/build-fpk.sh`), and the CI pipeline template (`.github/workflows/fnos-build-fpk.yml`).

Initial admin credentials: `admin` / `Octop123` (change after first login). For non-root FnOS installs, the WeCom/Feishu connector CLIs require the fix in [PR #406](https://github.com/TencentCloud/Octop/pull/406) (user-level npm fallback).
## 🚀 Quick Start

### Prerequisites
Expand Down
Binary file added fnos-native/ICON.PNG
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added fnos-native/ICON_256.PNG
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
21 changes: 21 additions & 0 deletions fnos-native/LICENSE
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
MIT License

Copyright (c) 2026 Octop

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
80 changes: 80 additions & 0 deletions fnos-native/app/bin/octop
Original file line number Diff line number Diff line change
@@ -0,0 +1,80 @@
#!/bin/bash
#
# Octop 本地版 — 启动器
# 运行在飞牛主机上,依赖飞牛应用商店提供的 Python 3.12(不内置 Python 运行时)。
# 包内仅含 Octop 核心 whl + 核心依赖 site-packages;浏览器/专家/技能由用户按需安装。
# 首次启动用向导配置的 .env 初始化管理员账号,然后启动服务。
#
set -euo pipefail

# 共享函数库(find_python312 / fix_ownership_and_perms / free_octop_ports)
# 打包时由 scripts/build-fpk.sh 注入;仓库内运行无此文件时跳过(函数缺失时再报错)。
_OCTOP_COMMON=""$(dirname "$0")/../cmd/common.sh""
[ -f "$_OCTOP_COMMON" ] && source "$_OCTOP_COMMON"

APPDEST="${TRIM_APPDEST:-/var/apps/octop-native}"
PKGVAR="${TRIM_PKGVAR:-/var/apps/octop-native/var}"

# 数据落在 FnOS 的 data-share 共享目录,升级时保留。
if [ -n "${TRIM_DATA_SHARE_PATHS:-}" ]; then
DATA_DIR="${TRIM_DATA_SHARE_PATHS%%:*}"
else
DATA_DIR="${APPDEST}/shares/octop-native/data"
fi

mkdir -p "$DATA_DIR" "$PKGVAR"

# 加载向导配置(install_callback / config_callback 写入)
if [ -f "$PKGVAR/.env" ]; then
set -a
. "$PKGVAR/.env"
set +a
fi

export HOME="$DATA_DIR"
export OCTOP_HOME="${DATA_DIR}/.octop"
export OCTOP_DATA_DIR="$DATA_DIR"

# 查找飞牛系统上的 Python 3.12(优先应用商店安装路径,再 PATH)


PY="$(find_python312)" || {
echo "[octop-native] 错误:未找到 Python 3.12。" >&2
echo "请先前往飞牛应用中心安装「Python 3.12」开发工具,再重新安装本应用。" >&2
exit 1
}

SITE_PACKAGES="$APPDEST/site-packages"
export PYTHONPATH="${SITE_PACKAGES}${PYTHONPATH:+:${PYTHONPATH}}"

# 兜底:若包内 site-packages 中未检测到 octop(升级异常 / 损坏等),
# 用内置核心 whl 就地离线安装,避免用户联网下载。
if ! "$PY" -c "import octop" >/dev/null 2>&1; then
echo "[octop-native] 未检测到已安装的 Octop,正在用内置核心 whl 离线安装 ..."
"$PY" -m pip install --no-cache --no-index --find-links "$SITE_PACKAGES" "$SITE_PACKAGES/octop.whl" >/dev/null 2>&1 || {
echo "[octop-native] 离线安装失败,请检查网络或手动执行:$PY -m pip install $SITE_PACKAGES/octop.whl" >&2
exit 1
}
fi

OCTOP_PORT="${OCTOP_PORT:-8089}"
OCTOP_LOG_LEVEL="${OCTOP_LOG_LEVEL:-info}"
OCTOP_BIND_HOST="${OCTOP_BIND_HOST:-0.0.0.0}"

mkdir -p "$OCTOP_HOME"

octop_cmd() {
"$PY" -m octop.cli.main "$@"
}

# 首次初始化管理员账号(仅当数据库尚未建立)
if [ ! -f "$OCTOP_HOME/octop.db" ]; then
echo "[octop-native] 首次启动,正在初始化管理员账号 ..."
octop_cmd init --yes \
--admin-username "${OCTOP_ADMIN_USERNAME:-admin}" \
--admin-password "${OCTOP_DEFAULT_PASSWORD:-Octop123}" \
${OCTOP_ADMIN_DISPLAY_NAME:+--admin-display-name "$OCTOP_ADMIN_DISPLAY_NAME"}
fi

echo "[octop-native] 正在启动 Octop,$OCTOP_BIND_HOST:$OCTOP_PORT ..."
exec "$PY" -m octop.cli.main run --host "$OCTOP_BIND_HOST" --port "$OCTOP_PORT" --log-level "${OCTOP_LOG_LEVEL}"
78 changes: 78 additions & 0 deletions fnos-native/app/bin/octop-cli
Original file line number Diff line number Diff line change
@@ -0,0 +1,78 @@
#!/bin/bash
#
# octop — 飞牛本地版「官方 CLI」包装
#
# 复刻 octop 运行环境后调用 `python -m octop.cli.main`,因此可使用全部官方子命令:
# octop --help
# octop version
# octop provider list
# octop agent list
# octop user list
# ...(还包括 init / run / config / backup / skills / update / clean 等)
#
# 注意:本机 Web 服务由飞牛应用中心托管(cmd/main 拉起 bin/octop),
# 请勿手动执行 `octop run`(会与飞牛管理的实例抢 8089 端口)。
#
# 本包装以 octop-native 身份运行,避免产生 root 所有的数据文件
# (Web 服务本身也以 octop-native 运行,混用 root 会导致后续权限问题)。
# root 调用 sudo 免密;其他用户调用需输入自身 sudo 密码。
#
set -euo pipefail

# 共享函数库(find_python312 / fix_ownership_and_perms / free_octop_ports)
# 打包时由 scripts/build-fpk.sh 注入;仓库内运行无此文件时跳过(函数缺失时再报错)。
_OCTOP_COMMON=""$(dirname "$0")/../cmd/common.sh""
[ -f "$_OCTOP_COMMON" ] && source "$_OCTOP_COMMON"

APPDEST="${TRIM_APPDEST:-/var/apps/octop-native}"
PKGVAR="${TRIM_PKGVAR:-/var/apps/octop-native/var}"

# 数据目录:优先飞牛 data-share 共享目录,否则回退包内目录
if [ -n "${TRIM_DATA_SHARE_PATHS:-}" ]; then
DATA_DIR="${TRIM_DATA_SHARE_PATHS%%:*}"
else
DATA_DIR="$APPDEST/shares/octop-native/data"
fi

mkdir -p "$DATA_DIR" "$PKGVAR"

# 加载安装向导写入的配置(OCTOP_PORT / 管理员账号 等)
if [ -f "$PKGVAR/.env" ]; then
set -a; . "$PKGVAR/.env"; set +a
fi

# 查找飞牛应用商店提供的 Python 3.12


PY="$(find_python312)" || {
echo "错误:未找到 Python 3.12,请先在飞牛应用中心安装「Python 3.12」开发工具。" >&2
exit 1
}

# 关键环境变量:让 octop 找到包本体(site-packages)与你的数据目录
SITE_PACKAGES="$APPDEST/site-packages"
export PYTHONPATH="${SITE_PACKAGES}${PYTHONPATH:+:$PYTHONPATH}"
export HOME="$DATA_DIR"
export OCTOP_HOME="$DATA_DIR/.octop"
export OCTOP_DATA_DIR="$DATA_DIR"

# 兜底:若包内 octop 未就绪,用内置核心 whl 离线安装(避免联网)
if ! "$PY" -c "import octop" >/dev/null 2>&1; then
echo "[octop] 未检测到已安装的 Octop,正在用内置核心 whl 离线安装 ..."
"$PY" -m pip install --no-cache --no-index --find-links "$SITE_PACKAGES" "$SITE_PACKAGES/octop.whl" >/dev/null 2>&1 || {
echo "[octop] 离线安装失败,请检查网络或手动执行:$PY -m pip install $SITE_PACKAGES/octop.whl" >&2
exit 1
}
fi

# 以 octop-native 身份运行,避免产生 root 所有的数据文件
if id octop-native >/dev/null 2>&1 && command -v sudo >/dev/null 2>&1; then
exec sudo -u octop-native \
PYTHONPATH="$PYTHONPATH" \
HOME="$HOME" \
OCTOP_HOME="$OCTOP_HOME" \
OCTOP_DATA_DIR="$OCTOP_DATA_DIR" \
"$PY" -m octop.cli.main "$@"
else
exec "$PY" -m octop.cli.main "$@"
fi
16 changes: 16 additions & 0 deletions fnos-native/app/ui/config
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
{
".url": {
"octop-native.Application": {
"title": "OCTOP",
"icon": "images/icon_{0}.png",
"type": "iframe",
"protocol": "http",
"port": "8089",
"url": "/",
"allUsers": true,
"control": {
"accessPerm": "readonly"
}
}
}
}
Binary file added fnos-native/app/ui/images/icon_256.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added fnos-native/app/ui/images/icon_64.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
58 changes: 58 additions & 0 deletions fnos-native/cmd/config_callback
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
#!/bin/bash
#
# Octop 本地版 — 重新配置回调
# 与安装回调逻辑一致:将向导配置写回 PKGVAR/.env。
# 注意:管理员账号/密码仅对尚未初始化的数据库生效;
# 密钥与日志级别在应用重启后生效。
#
set -euo pipefail

# 共享函数库(find_python312 / fix_ownership_and_perms / free_octop_ports)
# 打包时由 scripts/build-fpk.sh 注入;仓库内运行无此文件时跳过(函数缺失时再报错)。
_OCTOP_COMMON=""$(dirname "$0")/common.sh""
[ -f "$_OCTOP_COMMON" ] && source "$_OCTOP_COMMON"

# ---------------------------------------------------------------------------
# 修正数据目录与 .env 属主/权限(与 install_callback 同一坑):
# 重新配置回调以 root 身份写 .env,必须 chown 给 octop-native,否则服务
# 以 octop-native 启动读 .env 时 Permission denied。含 setfacl -b 防 ACL 把
# mask 压成 ---。路径用 TRIM_* 变量,兼容 /vol3 等其它卷。
# ---------------------------------------------------------------------------


PKGVAR="${TRIM_PKGVAR:-/var/apps/octop-native/var}"
mkdir -p "$PKGVAR"
ENV_FILE="$PKGVAR/.env"

ADMIN_USER="${wizard_admin_username:-admin}"
ADMIN_PASS="${wizard_admin_password:-octop}"
LOG_LEVEL="${wizard_log_level:-info}"
OPENAI="${wizard_openai_api_key:-}"
DASHSCOPE="${wizard_dashscope_api_key:-}"

sanitize() { printf '%s' "$1" | tr -d '\n\r"'"'"''; }

ADMIN_USER=$(sanitize "$ADMIN_USER")
ADMIN_PASS=$(sanitize "$ADMIN_PASS")
LOG_LEVEL=$(sanitize "$LOG_LEVEL")
OPENAI=$(sanitize "$OPENAI")
DASHSCOPE=$(sanitize "$DASHSCOPE")

{
echo "OCTOP_PORT=8089"
echo "OCTOP_BIND_HOST=0.0.0.0"
echo "OCTOP_LOG_LEVEL=${LOG_LEVEL}"
echo "OCTOP_ADMIN_USERNAME=${ADMIN_USER}"
echo "OCTOP_DEFAULT_PASSWORD=${ADMIN_PASS}"
echo "OCTOP_ADMIN_DISPLAY_NAME=Admin"
echo "OPENAI_API_KEY=${OPENAI}"
echo "DASHSCOPE_API_KEY=${DASHSCOPE}"
} > "$ENV_FILE"

chmod 600 "$ENV_FILE"
echo "[octop-native] 已更新配置: $ENV_FILE" > "${TRIM_TEMP_LOGFILE:-/dev/null}" 2>/dev/null || true

# 修正属主/权限:.env 与 appdata 改回 octop-native(root 写 root 属主会让
# 以 octop-native 启动的服务读取 .env 时 Permission denied)。
fix_ownership_and_perms "$PKGVAR" "$ENV_FILE"
exit 0
2 changes: 2 additions & 0 deletions fnos-native/cmd/config_init
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
#!/bin/bash
exit 0
Loading