From 15dc49fe6e238caa65fc9db9c0c94e29ac2eb8b7 Mon Sep 17 00:00:00 2001 From: Cursor Agent Date: Sun, 20 Sep 2026 11:09:10 +0000 Subject: [PATCH 1/2] chore: Node transition clarity and FreeOS release hygiene (P2) Keep uv/Docker/default packaging zero-Node (SHIP_OPENXYOS_RUNTIME=0). Desktop CI still ships the transitional iframe bridge explicitly. Skip managed Node when missing; include org trees in backup; retarget SECURITY, Issue templates, and GHCR/FnOS images to XYAIStudio/FreeOS. Co-authored-by: XYAI Labs --- .github/ISSUE_TEMPLATE/config.yml | 4 +- .github/workflows/docker-publish.yml | 37 +++++-- .github/workflows/fnos-build-fpk.yml | 2 +- .github/workflows/octop-desktop.yml | 11 ++- CHANGELOG.md | 7 ++ CONTRIBUTING.md | 6 +- README.md | 2 + README_CN.md | 10 +- SECURITY.md | 10 +- desktop/portable/package.sh | 14 +-- desktop/src/build/windows/Taskfile.yml | 10 +- desktop/src/build/windows/nsis/project.nsi | 16 +-- .../src/build/windows/nsis/wails_tools.nsh | 6 +- docker/README.md | 16 ++- docker/README_CN.md | 15 ++- docker/docker-compose.yml | 2 + docker/docker_build.sh | 12 +-- docs/architecture-integration.md | 11 ++- docs/node-runtime.md | 79 +++++++++++++++ docs/node-runtime.zh-CN.md | 72 ++++++++++++++ docs/org-capability-migration-map.md | 6 +- docs/org-capability-migration-map.zh-CN.md | 6 +- docs/product-contract.md | 2 +- docs/product-contract.zh-CN.md | 2 +- fnos/README.md | 14 +-- fnos/docker/Dockerfile | 2 +- fnos/docker/app/docker/docker-compose.yaml | 2 +- fnos/docker/manifest | 2 +- scripts/install-octop.sh | 2 +- scripts/install.sh | 2 +- src/octop/infra/backup/manifest.py | 4 + src/octop/infra/backup/store.py | 5 + src/octop/infra/backup/system_archive.py | 29 ++++++ src/octop/infra/utils/paths.py | 15 +++ src/octop/modules/org_os/managed_runtime.py | 48 +++++---- tests/unit/backup/test_store.py | 4 + tests/unit/backup/test_system_archive.py | 97 +++++++++++++++++++ tests/unit/desktop/test_nsis_uninstall.py | 6 +- tests/unit/desktop/test_phase5_defaults.py | 9 +- tests/unit/desktop/test_release_hygiene.py | 46 +++++++++ tests/unit/test_managed_runtime_skip.py | 37 +++++++ 41 files changed, 569 insertions(+), 113 deletions(-) create mode 100644 docs/node-runtime.md create mode 100644 docs/node-runtime.zh-CN.md create mode 100644 tests/unit/desktop/test_release_hygiene.py create mode 100644 tests/unit/test_managed_runtime_skip.py diff --git a/.github/ISSUE_TEMPLATE/config.yml b/.github/ISSUE_TEMPLATE/config.yml index 055368e7..0c8663f9 100644 --- a/.github/ISSUE_TEMPLATE/config.yml +++ b/.github/ISSUE_TEMPLATE/config.yml @@ -1,8 +1,8 @@ blank_issues_enabled: false contact_links: - name: Security advisory - url: https://github.com/TencentCloud/Octop/security/policy + url: https://github.com/XYAIStudio/FreeOS/security/policy about: Report security vulnerabilities privately (do not open a public issue) - name: Documentation - url: https://github.com/TencentCloud/Octop/tree/main/docs + url: https://github.com/XYAIStudio/FreeOS/tree/main/docs about: Read architecture, API, CLI, and configuration guides diff --git a/.github/workflows/docker-publish.yml b/.github/workflows/docker-publish.yml index 42537310..03e4ef5f 100644 --- a/.github/workflows/docker-publish.yml +++ b/.github/workflows/docker-publish.yml @@ -1,8 +1,9 @@ name: Docker Publish -# 仅在版本标签(v*)上构建并同步发布镜像到 Docker Hub 与 GHCR。 -# 文档与对外引用统一使用:ghcr.io/tencentcloud/octop -# (Hub 仍用 DOCKERHUB_* secrets 同步推送。) +# 仅在版本标签(v*)上构建并同步发布镜像。 +# 对外规范名:ghcr.io/xyaistudio/freeos +# Docker Hub 为可选镜像(需 DOCKERHUB_USERNAME / DOCKERHUB_TOKEN); +# 未配置 Hub secrets 时只推 GHCR,不让发版门禁因此变红。 # # 触发路径: # 1. 人工推送 v* tag → on.push.tags @@ -14,8 +15,8 @@ name: Docker Publish # FnOS FPK 由 Release 成功后自动 dispatch,并等待本工作流推送的 :{version} 就绪。 # # 拉取示例: -# docker pull ghcr.io/tencentcloud/octop:latest -# docker pull ghcr.io/tencentcloud/octop:0.0.1 +# docker pull ghcr.io/xyaistudio/freeos:latest +# docker pull ghcr.io/xyaistudio/freeos:0.0.3 on: push: tags: @@ -58,6 +59,7 @@ jobs: uses: docker/setup-buildx-action@v3 - name: Log in to Docker Hub + if: ${{ secrets.DOCKERHUB_USERNAME != '' && secrets.DOCKERHUB_TOKEN != '' }} uses: docker/login-action@v3 with: username: ${{ secrets.DOCKERHUB_USERNAME }} @@ -72,17 +74,32 @@ jobs: - name: Image names id: image + env: + HUB_USER: ${{ secrets.DOCKERHUB_USERNAME }} run: | - echo "ghcr=ghcr.io/$(echo '${{ github.repository }}' | tr '[:upper:]' '[:lower:]')" >> "$GITHUB_OUTPUT" - echo "hub=${{ secrets.DOCKERHUB_USERNAME }}/octop" >> "$GITHUB_OUTPUT" + set -euo pipefail + ghcr="ghcr.io/$(echo '${{ github.repository }}' | tr '[:upper:]' '[:lower:]')" + echo "ghcr=${ghcr}" >> "$GITHUB_OUTPUT" + images="${ghcr}" + if [ -n "${HUB_USER}" ]; then + hub="${HUB_USER}/freeos" + echo "hub=${hub}" >> "$GITHUB_OUTPUT" + images="${images}"$'\n'"${hub}" + else + echo "hub=" >> "$GITHUB_OUTPUT" + echo "::notice::DOCKERHUB_USERNAME unset; publishing GHCR only (${ghcr})" + fi + { + echo "images<> "$GITHUB_OUTPUT" - name: Docker metadata id: meta uses: docker/metadata-action@v5 with: - images: | - ${{ steps.image.outputs.hub }} - ${{ steps.image.outputs.ghcr }} + images: ${{ steps.image.outputs.images }} # 显式 raw tag:兼容 push.tags 与 Auto Tag 的 workflow_dispatch tags: | type=raw,value=${{ steps.ver.outputs.version }} diff --git a/.github/workflows/fnos-build-fpk.yml b/.github/workflows/fnos-build-fpk.yml index 677ad9e2..6786038e 100644 --- a/.github/workflows/fnos-build-fpk.yml +++ b/.github/workflows/fnos-build-fpk.yml @@ -8,7 +8,7 @@ name: Build Octop FPK # # 制品复用: # - Docker 镜像:不再重建,等待 docker-publish 推送的 -# ghcr.io/tencentcloud/octop:{version|latest} +# ghcr.io/xyaistudio/freeos:{version|latest} # - Native wheel:优先从同版本 GitHub Release(v*)下载; # 缺失时再回退到本仓源码构建 # - 产物挂到同一个 v* GitHub Release(与 wheel / 桌面包并列),不再单独打 fnos-* tag diff --git a/.github/workflows/octop-desktop.yml b/.github/workflows/octop-desktop.yml index cc28b9b5..3c0e7a04 100644 --- a/.github/workflows/octop-desktop.yml +++ b/.github/workflows/octop-desktop.yml @@ -1,8 +1,9 @@ name: FreeOS Desktop Package # Filename kept as octop-desktop.yml so auto-tag / existing dispatch keep working. -# Publishes FreeOS-desktop-* / FreeOS-portable-* (Windows NSIS .exe is the -# product installer: Octop shell + bundled openXYOS). +# Publishes FreeOS-desktop-* / FreeOS-portable-*. Default packaging is zero-Node; +# this workflow explicitly sets SHIP_OPENXYOS_RUNTIME=1 for the transitional +# managed-Node + iframe desktop bridge (not the destination architecture). # # 正式发版:Auto Tag 在打 v* 后与 Release / Docker Publish 一并 dispatch。 # 产物 upsert 到同一 GitHub Release。手工补包:workflow_dispatch + release_tag @@ -187,9 +188,10 @@ jobs: - name: Assemble green zip env: GREEN_HOST_PLAT: ${{ matrix.plat }} - # v0.0.3 ships the managed Organization runtime with the desktop - # package so the integrated Organization entry works offline. + # Transitional desktop flavor (0.0.3 iframe bridge). Default packaging + # is zero-Node; do not treat this flag as the permanent product. SKIP_ORG_SIDECAR: "0" + SHIP_OPENXYOS_RUNTIME: "1" run: | set -euo pipefail echo "GREEN_HOST_PLAT=${GREEN_HOST_PLAT} RUNNER_ARCH=${RUNNER_ARCH:-} uname=$(uname -ms)" @@ -263,6 +265,7 @@ jobs: - name: Package desktop app with bundled portable runtime working-directory: desktop/src env: + # Transitional desktop bridge only. Source / Docker stay zero-Node. SHIP_OPENXYOS_RUNTIME: "1" run: >- wails3 task package diff --git a/CHANGELOG.md b/CHANGELOG.md index 7b4cf4f3..e30ce0c4 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -9,9 +9,16 @@ ### 变更 - P1.4:本机模型与本机知识库作为默认路径。设置向导默认先选 Ollama(本机 OpenAI 兼容地址不必填云密钥);模型页默认打开「本地」标签;知识库空状态先引导本机文件夹,向量默认本机 ONNX。云厂商与 ima 仍是可选项。说明见 `docs/user-guide.md`、`docs/configuration.md`。 +- 默认绿色包 / NSIS `SHIP_OPENXYOS_RUNTIME` 回到 `0`(与 Phase 5 测试一致)。桌面 CI **显式** `SHIP_OPENXYOS_RUNTIME=1`,现有 Windows 用户仍可走 iframe 桥。 +- 缺少托管 Node 时 `ManagedOrganizationRuntime.start()` 只记警告并跳过,不再让 `uv run` / 测试因 `FREEOS_ORG_INTEGRATED=1` 整进程失败。 + +### 修复 + +- `freeos backup` 纳入宿主组织树:`{FREEOS_HOME}/org/*.sqlite`、`org-os/`、`org-skills/`、`tenants/`、`asset-packs/`、`openxyos-mirror/`、`governance/`。旧归档无 `includes_org` 时恢复不覆盖这些目录。 ### 文档 +- P2:Node 过渡说明与 FreeOS 发版卫生。[docs/node-runtime.md](docs/node-runtime.md) / [docs/node-runtime.zh-CN.md](docs/node-runtime.zh-CN.md) 写明 `uv run` / Docker **默认零 Node**;桌面 `SHIP_OPENXYOS_RUNTIME=1` 仅为过渡桥,不是永久产品。`SECURITY.md`、Issue 模板、Docker Publish / FnOS compose 不再指向 TencentCloud/Octop 安全公告或 `ghcr.io/tencentcloud/octop`;规范镜像为 `ghcr.io/xyaistudio/freeos`。Docker Hub 登录改为可选,避免未配置 secrets 时发版门禁变红。 - 冻结 FreeOS 产品契约(P0.1):[docs/product-contract.md](docs/product-contract.md) / [docs/product-contract.zh-CN.md](docs/product-contract.zh-CN.md)。核心愿景采用「创立初心」定稿(中文原文;英文 README 为忠实对应;使用方式段为工作室比喻:本机安顿起步,组织像另一间可独立布置的房间)。产品口号:**FreeOS:自由的 AI 工作室,想象空间由你来打开** / *Your FreeOS, free for you.* 托管 Node / 内嵌组织页仅为过渡桥,终态是把 openXYOS 迁入宿主并导出可商业化源码。取代先前「组织身份为唯一权威」与「永久 / 默认捆绑 Node 运行时」表述。冲突文档改为 Historical vs Current,不删工程历史。 - 官网 `website/` 文案对齐产品契约:中文口号作 Hero / 标题,英文 *Your FreeOS, free for you.* 作 EN 标题与 meta;工作室比喻贯穿介绍与 FAQ;下载入口只指向 GitHub Releases 列表(不写死版本号、不直链安装包);不再承诺永久零 Node,托管运行时写成迁向宿主原生界面的过渡。 diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 6687dcbd..6d1cd7ad 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -86,15 +86,15 @@ Branch from `main` → PR into `main` (tag if shipping a patch) → PR into `dev # 贡献指南 -感谢你对 Octop 的关注!Octop 是 [Octop Harness](https://github.com/TencentCloud) 生态中的可自托管 AI 助手平台,支持多用户与多 Agent。 +感谢你对 **FreeOS**([XYAIStudio/FreeOS](https://github.com/XYAIStudio/FreeOS))的关注。本仓库是 Octop + openXYOS 的独立下游;产品意图见 [docs/product-contract.md](docs/product-contract.md)。质量门禁仍是 Octop 宿主的 `make all`。 ## 环境搭建 **前置条件:** Python 3.12+、Node.js 18+、[uv](https://docs.astral.sh/uv/) ```bash -git clone https://github.com/TencentCloud/Octop.git octop -cd octop +git clone https://github.com/XYAIStudio/FreeOS.git +cd FreeOS make install make install-hooks # 每个 clone 执行一次:提交前跑 make all + 前端 build make all # format-all + 后端 lint / typecheck / test diff --git a/README.md b/README.md index 831650c7..e4167149 100644 --- a/README.md +++ b/README.md @@ -212,6 +212,8 @@ Optional Node sidecar (export/sync/advanced deploy only): FREEOS_ORG_SIDECAR=1 bash scripts/run-org-sidecar.sh ``` +Flag table and Node cut plan: [docs/node-runtime.md](docs/node-runtime.md). + Default origin if opted in: `http://127.0.0.1:3780`. Organization and `freeos org loop run` do **not** wait for `/api/health/livez`. diff --git a/README_CN.md b/README_CN.md index 9d866752..cee2d2d8 100644 --- a/README_CN.md +++ b/README_CN.md @@ -10,14 +10,14 @@

Python 3.12+ - License: MIT + License: MIT Version 上游:Octop 组织模块:openXYOS PyPI Code Style: Ruff - GitHub stars - GitHub forks + GitHub stars + GitHub forks Discord

@@ -569,6 +569,6 @@ cd dashboard && npx tsc --noEmit 感谢所有贡献者: - - + + diff --git a/SECURITY.md b/SECURITY.md index 07e322bd..de44f56b 100644 --- a/SECURITY.md +++ b/SECURITY.md @@ -11,18 +11,20 @@ **Please do not open a public GitHub issue for security vulnerabilities.** -- **GitHub Security Advisory:** [Create advisory](https://github.com/TencentCloud/Octop/security/advisories/new) +- **GitHub Security Advisory:** [Create advisory](https://github.com/XYAIStudio/FreeOS/security/advisories/new) - **Email:** jubaoliang@gmail.com We aim to acknowledge reports within **3 business days** and provide a fix timeline within **7 business days** for confirmed issues. +Octop upstream advisories (MIT host this project is derived from) live at [TencentCloud/Octop](https://github.com/TencentCloud/Octop/security/advisories). Report **FreeOS** issues here, not there. + ## Scope -Octop is a self-hosted control plane. Operators are responsible for: +FreeOS is a self-hosted control plane. Operators are responsible for: -- Securing the host and network exposure of `octop run` +- Securing the host and network exposure of `freeos run` / `octop run` - Rotating JWT secrets and admin credentials -- Reviewing tool guard rules under `~/.octop/security/tool_guard/` +- Reviewing tool guard rules under `{FREEOS_HOME}/security/tool_guard/` (legacy `~/.octop/security/tool_guard/`) - Protecting LLM API keys and IM channel credentials See [docs/configuration.md](docs/configuration.md) for deployment hardening guidance. diff --git a/desktop/portable/package.sh b/desktop/portable/package.sh index b0ad895c..d1bb95e5 100755 --- a/desktop/portable/package.sh +++ b/desktop/portable/package.sh @@ -241,12 +241,14 @@ assemble_one() { cp "${TEMPLATES}/README.txt" "${staging}/README.txt" chmod +x "${staging}/start.sh" - # A production package always contains the organization runtime. Developers - # may opt out only with SHIP_OPENXYOS_RUNTIME=0 or SKIP_ORG_SIDECAR=1. - if [[ "${SHIP_OPENXYOS_RUNTIME:-1}" == "0" ]]; then - SKIP_ORG_SIDECAR=1 - elif [[ -z "${SKIP_ORG_SIDECAR:-}" ]]; then - SKIP_ORG_SIDECAR=0 + # Default is **zero-Node** (uv run / Docker / source / Phase-5 installer). + # Desktop CI sets SHIP_OPENXYOS_RUNTIME=1 for the transitional iframe bridge. + # Explicit SKIP_ORG_SIDECAR=0 still ships the sidecar even if the ship flag + # is unset. Do not treat SHIP_OPENXYOS_RUNTIME=1 as the permanent product. + if [[ "${SHIP_OPENXYOS_RUNTIME:-0}" == "0" ]]; then + SKIP_ORG_SIDECAR="${SKIP_ORG_SIDECAR:-1}" + else + SKIP_ORG_SIDECAR="${SKIP_ORG_SIDECAR:-0}" fi export SKIP_ORG_SIDECAR echo "[package] ${plat}: org sidecar (SKIP_ORG_SIDECAR=${SKIP_ORG_SIDECAR})" >&2 diff --git a/desktop/src/build/windows/Taskfile.yml b/desktop/src/build/windows/Taskfile.yml index 3c864893..9f7a33f6 100644 --- a/desktop/src/build/windows/Taskfile.yml +++ b/desktop/src/build/windows/Taskfile.yml @@ -55,7 +55,7 @@ tasks: PORTABLE_ZIP: '{{.PORTABLE_ZIP | default (printf "../portable/release/FreeOS-portable-windows-%s-%s.zip" (.ARCH | default ARCH) (.VERSION | default "dev"))}}' maybe-stage:openxyos-runtime: - summary: Stage openxyos-runtime.zip unless explicitly disabled for a development-only host build + summary: Stage openxyos-runtime.zip only when SHIP_OPENXYOS_RUNTIME=1 (transitional desktop bridge) status: - test "{{.SHIP_OPENXYOS_RUNTIME}}" != "1" cmds: @@ -65,10 +65,10 @@ tasks: PORTABLE_ZIP: "{{.PORTABLE_ZIP}}" VERSION: "{{.VERSION}}" vars: - SHIP_OPENXYOS_RUNTIME: '{{.SHIP_OPENXYOS_RUNTIME | default "1"}}' + SHIP_OPENXYOS_RUNTIME: '{{.SHIP_OPENXYOS_RUNTIME | default "0"}}' package: - summary: Packages the full NSIS installer with the managed organization runtime. + summary: Packages the NSIS installer. Node sidecar is opt-in (SHIP_OPENXYOS_RUNTIME=1, transitional). cmds: - task: stage:portable vars: @@ -99,7 +99,7 @@ tasks: vars: ARCH: "{{.ARCH | default ARCH}}" VERSION: '{{.VERSION | default "dev"}}' - SHIP_OPENXYOS_RUNTIME: '{{.SHIP_OPENXYOS_RUNTIME | default "1"}}' + SHIP_OPENXYOS_RUNTIME: '{{.SHIP_OPENXYOS_RUNTIME | default "0"}}' PORTABLE_ZIP: '{{.PORTABLE_ZIP | default (printf "../portable/release/FreeOS-portable-windows-%s-%s.zip" .ARCH .VERSION)}}' ARCHIVE: '{{.BIN_DIR}}/{{.APP_NAME}}-desktop-windows-{{.ARCH}}-{{.VERSION}}.exe' @@ -125,7 +125,7 @@ tasks: ARCH: '{{.ARCH | default ARCH}}' VERSION: '{{.VERSION | default "dev"}}' VERSION_NSIS_DEFINE: '{{if and .VERSION (ne .VERSION "dev")}}-DINFO_PRODUCTVERSION="{{.VERSION}}" {{end}}{{if eq .SHIP_OPENXYOS_RUNTIME "1"}}-DOPENXYOS_RUNTIME_ZIP_PRESENT {{end}}' - SHIP_OPENXYOS_RUNTIME: '{{.SHIP_OPENXYOS_RUNTIME | default "1"}}' + SHIP_OPENXYOS_RUNTIME: '{{.SHIP_OPENXYOS_RUNTIME | default "0"}}' ARG_FLAG: '{{if eq (.ARCH | default ARCH) "amd64"}}AMD64{{else}}ARM64{{end}}' ARCHIVE: '{{.BIN_DIR}}/{{.APP_NAME}}-desktop-windows-{{.ARCH}}-{{.VERSION}}.exe' diff --git a/desktop/src/build/windows/nsis/project.nsi b/desktop/src/build/windows/nsis/project.nsi index 68c8c932..bd981dac 100644 --- a/desktop/src/build/windows/nsis/project.nsi +++ b/desktop/src/build/windows/nsis/project.nsi @@ -52,14 +52,14 @@ ManifestDPIAware true LangString FINISH_RUN ${LANG_SIMPCHINESE} "运行 FreeOS" LangString FINISH_RUN ${LANG_ENGLISH} "Run FreeOS" -LangString OPENXYOS_WORKDIR ${LANG_SIMPCHINESE} "正在安装完整组织运行时(受管 Node、openXYOS 前端和业务后端)" -LangString OPENXYOS_WORKDIR ${LANG_ENGLISH} "Installing the full organization runtime (managed Node, openXYOS frontend, and business backend)" -LangString OPENXYOS_COPY_ZIP ${LANG_SIMPCHINESE} "正在复制完整 openXYOS 运行包" -LangString OPENXYOS_COPY_ZIP ${LANG_ENGLISH} "Copying the complete openXYOS runtime payload" -LangString OPENXYOS_OPTIONAL_SKIP ${LANG_SIMPCHINESE} "开发构建已明确关闭组织运行时;此构建不可作为完整产品发布。" -LangString OPENXYOS_OPTIONAL_SKIP ${LANG_ENGLISH} "The organization runtime was explicitly disabled for development; this build cannot be released as the full product." -LangString OPENXYOS_OPTIONAL_ABSENT ${LANG_SIMPCHINESE} "开发构建未包含组织运行包;此构建不可作为完整产品发布。" -LangString OPENXYOS_OPTIONAL_ABSENT ${LANG_ENGLISH} "The organization runtime is absent from this development build; it cannot be released as the full product." +LangString OPENXYOS_WORKDIR ${LANG_SIMPCHINESE} "正在复制过渡用组织运行时(受管 Node)。组织能力在 FreeOS 宿主内运行;此路径不是终态。" +LangString OPENXYOS_WORKDIR ${LANG_ENGLISH} "Copying the transitional organization runtime (managed Node). Organization runs in-host; this is not the destination. Setup continues." +LangString OPENXYOS_COPY_ZIP ${LANG_SIMPCHINESE} "正在复制过渡用 openXYOS 运行包" +LangString OPENXYOS_COPY_ZIP ${LANG_ENGLISH} "Copying the transitional openXYOS runtime payload" +LangString OPENXYOS_OPTIONAL_SKIP ${LANG_SIMPCHINESE} "组织能力在 FreeOS 宿主内运行(不捆绑 Node)。托管 Node + iframe 是过渡桥。安装继续。" +LangString OPENXYOS_OPTIONAL_SKIP ${LANG_ENGLISH} "Organization runs in-host (no bundled Node). Managed Node + iframe is a transition bridge. Setup continues." +LangString OPENXYOS_OPTIONAL_ABSENT ${LANG_SIMPCHINESE} "未包含 openXYOS 运行包。组织能力在 FreeOS 宿主内运行。安装继续。" +LangString OPENXYOS_OPTIONAL_ABSENT ${LANG_ENGLISH} "No openXYOS runtime zip in this installer. Organization runs in-host. Setup continues." LangString OPENXYOS_PROVISION ${LANG_SIMPCHINESE} "正在以子进程部署 openXYOS(解压、启动前后端、等待健康检查)" LangString OPENXYOS_PROVISION ${LANG_ENGLISH} "Running the openXYOS provisioner subprocess (extract, start FE/BE, wait for health)" LangString OPENXYOS_PROVISION_DETAIL ${LANG_SIMPCHINESE} "完整日志:%LOCALAPPDATA%\\FreeOS\\openxyos\\provision.log(UTF-8);此处只显示步骤结果" diff --git a/desktop/src/build/windows/nsis/wails_tools.nsh b/desktop/src/build/windows/nsis/wails_tools.nsh index 24a08a5c..ca6ec046 100644 --- a/desktop/src/build/windows/nsis/wails_tools.nsh +++ b/desktop/src/build/windows/nsis/wails_tools.nsh @@ -141,9 +141,8 @@ RequestExecutionLevel "${REQUEST_EXECUTION_LEVEL}" ${EndIf} !macroend -# Production Setup copies the complete openxyos-runtime.zip and runtime -# bootstrap scripts. It does not start Node in the installer; FreeOS owns that -# lifecycle after installation. Development-only builds may omit the runtime. +# Default Setup is zero-Node (in-host Organization). SHIP_OPENXYOS_RUNTIME=1 +# copies the transitional openxyos-runtime.zip; Setup does not start Node. # Do not FileWrite goto-label .cmd scripts here. Do not register logon autostart. !macro wails.provisionOpenXYOS !insertmacro wails.userLocalAppData @@ -163,6 +162,7 @@ RequestExecutionLevel "${REQUEST_EXECUTION_LEVEL}" !error "OPENXYOS_RUNTIME_ZIP_PRESENT is set but ${OPENXYOS_RUNTIME_ZIP} is missing" !endif !else + DetailPrint "$(OPENXYOS_OPTIONAL_SKIP)" DetailPrint "$(OPENXYOS_OPTIONAL_ABSENT)" !endif SetDetailsPrint listonly diff --git a/docker/README.md b/docker/README.md index 8537e6e1..e481c213 100644 --- a/docker/README.md +++ b/docker/README.md @@ -1,10 +1,18 @@ -# Octop Docker Deployment +# FreeOS Docker Deployment --- -This directory contains the Docker build and deployment assets for Octop / -FreeOS. Compose stays **one Python process**. There is no Node/openXYOS -sidecar service. Organization runs in-host (`/api/org-module/*`). +This directory contains the Docker build and deployment assets for FreeOS +(Octop-compatible identifiers remain). Compose stays **one Python process**. +There is no Node/openXYOS sidecar service. Organization runs in-host +(`/api/org-module/*`). Canonical published image: + +```bash +docker pull ghcr.io/xyaistudio/freeos:latest +``` + +Local Compose still tags `octop:latest` as a compatibility alias. See +[docs/node-runtime.md](../docs/node-runtime.md). **Home directory names:** the product name is `FREEOS_HOME`. Compose and this image still use `OCTOP_*` and `~/.octop` as compatibility aliases diff --git a/docker/README_CN.md b/docker/README_CN.md index 28da4428..023f2fae 100644 --- a/docker/README_CN.md +++ b/docker/README_CN.md @@ -1,10 +1,17 @@ -# Octop Docker 部署 +# FreeOS Docker 部署 --- -本目录包含 Octop / FreeOS 的 Docker 构建与部署相关文件。Compose **只有一个 -Python 进程**,没有 Node / openXYOS 边车。Organization 在宿主内运行 -(`/api/org-module/*`)。 +本目录包含 FreeOS 的 Docker 构建与部署相关文件(仍保留 Octop 兼容标识)。 +Compose **只有一个 Python 进程**,没有 Node / openXYOS 边车。Organization 在宿主内运行 +(`/api/org-module/*`)。对外规范镜像: + +```bash +docker pull ghcr.io/xyaistudio/freeos:latest +``` + +本地 Compose 仍用 `octop:latest` 作兼容标签。说明见 +[docs/node-runtime.zh-CN.md](../docs/node-runtime.zh-CN.md)。 **目录命名:** 产品名是 `FREEOS_HOME`。本镜像与 Compose 仍用 `OCTOP_*` 和 `~/.octop` 作为兼容别名(`HOME=/data` → `/data/.octop`)。需要显式路径时 diff --git a/docker/docker-compose.yml b/docker/docker-compose.yml index 82a4144e..a5001987 100644 --- a/docker/docker-compose.yml +++ b/docker/docker-compose.yml @@ -3,6 +3,8 @@ # # One service. No Node / openXYOS sidecar. Organization is in-host. # Product home name is FREEOS_HOME; OCTOP_* and ~/.octop remain aliases. +# Published image: ghcr.io/xyaistudio/freeos +# Local build tag remains octop:latest (compatibility). # # 用法(在仓库根目录执行): # docker compose -f docker/docker-compose.yml up -d diff --git a/docker/docker_build.sh b/docker/docker_build.sh index 2a0dc769..8e1316dd 100644 --- a/docker/docker_build.sh +++ b/docker/docker_build.sh @@ -1,15 +1,15 @@ #!/usr/bin/env bash # ============================================================================= -# 构建 Octop Docker 镜像 +# 构建 FreeOS Docker 镜像(本地默认标签 octop:latest,兼容别名) # # 用法: -# bash docker/docker_build.sh [镜像标签] [额外 docker build 参数...] -# -# 示例: # bash docker/docker_build.sh -# bash docker/docker_build.sh myreg/octop:v1 +# bash docker/docker_build.sh ghcr.io/xyaistudio/freeos:dev # bash docker/docker_build.sh octop:dev --no-cache # +# 对外规范名:ghcr.io/xyaistudio/freeos +# ============================================================================= +# # 国内加速(可选,需 BuildKit,本脚本默认已开启): # PIP_INDEX_URL=https://mirrors.cloud.tencent.com/pypi/simple \ # PIP_TRUSTED_HOST=mirrors.cloud.tencent.com \ @@ -46,7 +46,7 @@ if [ -n "${APT_MIRROR:-}" ]; then fi echo "╔══════════════════════════════════════════════════╗" -echo "║ 正在构建 Octop Docker 镜像 ║" +echo "║ 正在构建 FreeOS Docker 镜像 ║" echo "║ 标签: ${IMAGE_TAG}" echo "╚══════════════════════════════════════════════════╝" echo "" diff --git a/docs/architecture-integration.md b/docs/architecture-integration.md index 593e2ecd..38539dcb 100644 --- a/docs/architecture-integration.md +++ b/docs/architecture-integration.md @@ -26,7 +26,7 @@ FreeOS/Octop remains the execution runtime. - [ADR 001](adr/001-single-process-model.md) — single process, no external queue - [ADR 003](adr/003-org-ui-single-source-dual-delivery.md) — org-ui single source, dual delivery (Accepted; read the Current banner) - [org-merge-plan.md](org-merge-plan.md) — Phases 0–5 history; Phase-5 zero-Node is a transition default -- [org-export.md](org-export.md) — standalone commercial openXYOS source pack (`freeos org export-standalone`) +- [node-runtime.md](node-runtime.md) — zero-Node defaults, transitional desktop flags, cut plan - [asset-loop.md](asset-loop.md) — operator self-growth loop - [ADR index](adr/) @@ -339,8 +339,12 @@ Tenant hint: `FREEOS_ORG_TENANT_ID` or `modules.org_os.tenant_id`. | Org tenants, employees, matrix | sidecar DB — **not** the production SoT | | Brand assets | `dashboard/public/`, `docs/assets/` | -`freeos backup` does not include sidecar SQL.js files unless operators -copy the openXYOS working directory themselves. +`freeos backup` packs host organization trees under `{home}/org/` (SQLite +slices), `{home}/org-os/` (prefs / toggles / optional sidecar DB), plus +`org-skills/`, `tenants/`, `asset-packs/`, `openxyos-mirror/`, and +`governance/`. It does **not** pack the live openXYOS workdir +(`%LOCALAPPDATA%\FreeOS\openxyos` or `{home}/openxyos`). Older archives +without `includes_org` leave those live directories untouched on restore. ## Remaining `octop` identifiers (intentional) @@ -367,6 +371,7 @@ copy the openXYOS working directory themselves. | Role | Path | |---|---| | Architecture (this file) | `docs/architecture-integration.md` | +| Node flags + cut plan | `docs/node-runtime.md` | | Org-ui dual-delivery ADR | `docs/adr/003-org-ui-single-source-dual-delivery.md` | | Org merge plan (Phases 0–5) | `docs/org-merge-plan.md` | | BFF router | `src/octop/api/routers/org_module.py` | diff --git a/docs/node-runtime.md b/docs/node-runtime.md new file mode 100644 index 00000000..9ffc63b5 --- /dev/null +++ b/docs/node-runtime.md @@ -0,0 +1,79 @@ +# Node runtime: flags, defaults, cut plan + +**Status:** Canonical for Node packaging (P2). Product intent: +[product-contract.md](product-contract.md). Capability map: +[org-capability-migration-map.md](org-capability-migration-map.md) wave **E**. + +Managed Node + iframe is a **transition bridge** toward native host +organization UI. It is not the destination and must not be re-frozen as +`SHIP_OPENXYOS_RUNTIME=1` forever. + +[简体中文](node-runtime.zh-CN.md) + +## Defaults (zero-Node) + +These paths **do not** bundle, extract, or start Node: + +| Path | How | +|---|---| +| `uv run freeos run` / `octop run` | Host Python only. Organization is `/organization` + `/api/org-module/*`. | +| Docker Compose / `docker/Dockerfile` | One Python process. No sidecar service, no port 3780. | +| Default `desktop/portable/package.sh` | `SHIP_OPENXYOS_RUNTIME` defaults to `0` → `SKIP_ORG_SIDECAR=1`. | +| Default `wails3 task package` | `SHIP_OPENXYOS_RUNTIME` defaults to `0`; NSIS does not embed `openxyos-runtime.zip`. | + +Missing Node is **skip**, not host abort. `ManagedOrganizationRuntime.start()` +logs a warning and returns when no bundled/source runtime is present, so +`FREEOS_ORG_INTEGRATED=1` on a source checkout does not fail `uv run`. + +## Transitional desktop flavor (explicit opt-in) + +The GitHub workflow **FreeOS Desktop Package** (`.github/workflows/octop-desktop.yml`) +sets `SHIP_OPENXYOS_RUNTIME=1` and `SKIP_ORG_SIDECAR=0` so existing Windows +users keep the 0.0.3 iframe bridge. That flag is **labeled transitional** in +the workflow, NSIS strings, and this file. Do not copy it into Docker, `uv run`, +or the default installer. + +| Flag | Default | Meaning | +|---|---|---| +| `SHIP_OPENXYOS_RUNTIME` | `0` | Build-time: embed `org-sidecar` / `openxyos-runtime.zip`. Desktop CI sets `1`. | +| `SKIP_ORG_SIDECAR` | follows ship flag (`1` when ship is `0`) | Packager escape hatch. Explicit `0` still ships sidecar. | +| `FREEOS_ORG_SIDECAR` | unset | Runtime: start optional `:3780` sidecar (`ensure_sidecar`). | +| `FREEOS_ORG_INTEGRATED` | unset (desktop Go may set `1`) | Runtime: iframe `/organization` → `/organization-app` + managed Node. | +| `OPENXYOS_BASE_URL` / `FREEOS_ORG_SIDECAR_URL` | unset | Point asset loop / BFF at a live control plane. Does not start Node. | + +## Cut plan (tied to the migration map) + +Do **not** delete the managed runtime until native coverage exists. Sequence +from [org-capability-migration-map.md](org-capability-migration-map.md): + +1. **Keep** default installers / `uv run` / Docker zero-Node (this file). +2. **Keep** desktop `SHIP_OPENXYOS_RUNTIME=1` until wave E domains that still + live only in App.tsx (`managed_node_iframe`) have a native host route + operators can use. +3. **Then** stop setting `SHIP_OPENXYOS_RUNTIME=1` in desktop CI (same as + default packaging). Sidecar remains `FREEOS_ORG_SIDECAR=1` for export/sync. +4. **Last** remove `ManagedOrganizationRuntime` and the `/organization-app` + iframe home. + +Anti-goals: re-bundling Node into Docker or `uv run`; calling iframe “done”; +expanding `SHIP_OPENXYOS_RUNTIME=1` to new flavors. + +## Images and security (release hygiene) + +| What | Canonical FreeOS target | +|---|---| +| GHCR image | `ghcr.io/xyaistudio/freeos:{version\|latest}` | +| Local Compose tag | `octop:latest` (compatibility alias; one Python process) | +| Security advisories | [XYAIStudio/FreeOS](https://github.com/XYAIStudio/FreeOS/security/advisories/new) | +| PyPI package name | `octop` (intentional remaining identifier; CLI is `freeos`) | + +### Release / PyPI / Docker gates + +- **Docker Publish** pushes GHCR always. Docker Hub login is **optional** + (`DOCKERHUB_USERNAME` / `DOCKERHUB_TOKEN`). Missing Hub secrets must not + fail the workflow. +- **PyPI** still publishes the `octop` distribution (`PYPI_API_TOKEN` on the + `pypi` environment). That name is the Python package, not a pointer at + Tencent Cloud advisories. +- **FnOS Docker `.fpk`** compose must pull `ghcr.io/xyaistudio/freeos`, not + `ghcr.io/tencentcloud/octop`. diff --git a/docs/node-runtime.zh-CN.md b/docs/node-runtime.zh-CN.md new file mode 100644 index 00000000..83efb3ae --- /dev/null +++ b/docs/node-runtime.zh-CN.md @@ -0,0 +1,72 @@ +# Node 运行时:开关、默认值、拆除计划 + +**状态:** Node 打包的现行说明(P2)。产品意图见 +[product-contract.zh-CN.md](product-contract.zh-CN.md)。能力地图: +[org-capability-migration-map.zh-CN.md](org-capability-migration-map.zh-CN.md) 波次 **E**。 + +托管 Node + iframe 是通往宿主原生组织界面的 **过渡桥**,不是终点,也不得把 +`SHIP_OPENXYOS_RUNTIME=1` 再冻成永久产品。 + +[English](node-runtime.md) + +## 默认(零 Node) + +下列路径 **不** 捆绑、不解压、不自动拉起 Node: + +| 路径 | 行为 | +|---|---| +| `uv run freeos run` / `octop run` | 仅 Python 宿主。组织页是 `/organization` + `/api/org-module/*`。 | +| Docker Compose / `docker/Dockerfile` | 单进程。无边车、无 3780。 | +| 默认 `desktop/portable/package.sh` | `SHIP_OPENXYOS_RUNTIME` 默认 `0` → `SKIP_ORG_SIDECAR=1`。 | +| 默认 `wails3 task package` | `SHIP_OPENXYOS_RUNTIME` 默认 `0`;NSIS 不打入 `openxyos-runtime.zip`。 | + +缺少 Node 是 **跳过**,不是宿主崩溃。`ManagedOrganizationRuntime.start()` 在没有 +捆绑/源码运行时时报警告并返回,因此源码树上误设 `FREEOS_ORG_INTEGRATED=1` 也不会让 +`uv run` 失败。 + +## 过渡桌面口味(显式 opt-in) + +GitHub 工作流 **FreeOS Desktop Package**(`.github/workflows/octop-desktop.yml`) +会设 `SHIP_OPENXYOS_RUNTIME=1` 与 `SKIP_ORG_SIDECAR=0`,让现有 Windows 用户仍能用 +0.0.3 的 iframe 桥。该开关在工作流、NSIS 文案和本文里都标成 **过渡**。不要把它 +复制进 Docker、`uv run` 或默认安装器。 + +| 开关 | 默认 | 含义 | +|---|---|---| +| `SHIP_OPENXYOS_RUNTIME` | `0` | 构建期:打入 `org-sidecar` / `openxyos-runtime.zip`。桌面 CI 设 `1`。 | +| `SKIP_ORG_SIDECAR` | 随 ship 标志(ship 为 `0` 时为 `1`) | 打包逃逸舱。显式 `0` 仍打边车。 | +| `FREEOS_ORG_SIDECAR` | 未设 | 运行期:拉起可选 `:3780` 边车。 | +| `FREEOS_ORG_INTEGRATED` | 未设(桌面 Go 可能设 `1`) | 运行期:`/organization` iframe 到 `/organization-app` + 托管 Node。 | +| `OPENXYOS_BASE_URL` / `FREEOS_ORG_SIDECAR_URL` | 未设 | 资产循环 / BFF 指向已有控制面。不拉起 Node。 | + +## 拆除计划(对齐迁移图) + +原生覆盖完成前 **不要** 删除托管运行时。顺序来自迁移图: + +1. **保持** 默认安装器 / `uv run` / Docker 零 Node(本文)。 +2. **保持** 桌面 `SHIP_OPENXYOS_RUNTIME=1`,直到波次 E 里仍只活在 App.tsx 的域 + 有宿主原生路由可用。 +3. **然后** 桌面 CI 不再设 `SHIP_OPENXYOS_RUNTIME=1`(与默认打包一致)。边车仍可 + `FREEOS_ORG_SIDECAR=1` 做导出/同步。 +4. **最后** 去掉 `ManagedOrganizationRuntime` 和 `/organization-app` iframe 首页。 + +反目标:把 Node 重新打进 Docker 或 `uv run`;宣称 iframe「已完成」;把 +`SHIP_OPENXYOS_RUNTIME=1` 扩到新口味。 + +## 镜像与安全(发版卫生) + +| 项 | FreeOS 规范 | +|---|---| +| GHCR 镜像 | `ghcr.io/xyaistudio/freeos:{version\|latest}` | +| 本地 Compose 标签 | `octop:latest`(兼容别名;单 Python 进程) | +| 安全公告 | [XYAIStudio/FreeOS](https://github.com/XYAIStudio/FreeOS/security/advisories/new) | +| PyPI 包名 | `octop`(有意保留的标识;CLI 是 `freeos`) | + +### 发版 / PyPI / Docker 门禁 + +- **Docker Publish** 始终推 GHCR。Docker Hub 登录是 **可选** + (`DOCKERHUB_USERNAME` / `DOCKERHUB_TOKEN`)。没有 Hub secrets 不得让工作流变红。 +- **PyPI** 仍发布名为 `octop` 的发行版(`pypi` 环境的 `PYPI_API_TOKEN`)。这是 + Python 包名,不是腾讯云安全公告地址。 +- **飞牛 Docker `.fpk`** 的 compose 必须拉 `ghcr.io/xyaistudio/freeos`,不是 + `ghcr.io/tencentcloud/octop`。 diff --git a/docs/org-capability-migration-map.md b/docs/org-capability-migration-map.md index 35b62d70..665efc09 100644 --- a/docs/org-capability-migration-map.md +++ b/docs/org-capability-migration-map.md @@ -88,7 +88,7 @@ These shipping shapes still need a native port. They are bridges. 1. **Desktop integrated iframe** of the full App — `FREEOS_ORG_INTEGRATED=1` (`desktop/src/process.go`) makes `/organization` render `