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
4 changes: 3 additions & 1 deletion CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,8 @@

### 新增

- Organization Phase 4(独立站导出起步):`freeos org export-standalone --out <dir>` 从 `dashboard/src/org-ui` 生成可运行的 Vite 包(OpenApp 风格路由、本地 JWT IdentityBridge `openxyos.standalone.jwt`、登录页、Docker / docker-compose、`server/proxy.mjs` 把 `/api` 反代到 FreeOS `FREEOS_UPSTREAM`)。Chat 不导出。默认安装器与 sidecar 不变(Phase 5)。说明见 `docs/org-export.md`。
- Organization Phase 5(默认安装器瘦身):Windows/macOS/Linux 默认包装与 Docker Compose 保持 **单进程 FreeOS + 宿主内 Organization**,不捆绑、不解压、不自动拉起 openXYOS Node。`FREEOS_ORG_SIDECAR=1` 与 `SHIP_OPENXYOS_RUNTIME=1` 仍是可选高级路径。文档对齐 #55 / ADR 001 / ADR 003 / `docs/org-export.md`。`modules/openxyos` 保留给导出与开发,不是默认运行时。
- Organization Phase 4(独立站导出起步):`freeos org export-standalone --out <dir>` 从 `dashboard/src/org-ui` 生成可运行的 Vite 包(OpenApp 风格路由、本地 JWT IdentityBridge `openxyos.standalone.jwt`、登录页、Docker / docker-compose、`server/proxy.mjs` 把 `/api` 反代到 FreeOS `FREEOS_UPSTREAM`)。Chat 不导出。默认安装器零 Node(Phase 5)。说明见 `docs/org-export.md`。
- Organization Phase 3(工作台总览切片,Open-12 收口):宿主内薄 Workspace / OpenDashboard。Dashboard `/organization/workspace` 使用共享 `dashboard/src/org-ui` 的 `WorkspacePage`。数据复用已有 `GET /api/org-module/overview`,链到已迁的公告 / 架构 / 员工 / 技能 / 智能体 / 任务 / 知识 / 反思 / 治理 / 设置。**不是**第二套控制面(assemble / pack / loop 仍在 `/organization`)。**Chat 永久不迁。** `freeos org export-standalone` 同时列出 Workspace。Phase 3 Open-12 宿主 UI 完成,下一步 Phase 4 导出。
- Organization Phase 3(智能体切片):宿主内 Agent Studio / 智能体定制。Dashboard `/organization/agents` 使用共享 `dashboard/src/org-ui` 的 `AgentsPage`。列表走 `GET /api/org-module/agents`;编译 / 生命周期 / 注册复用已有 `POST /api/org-module/blueprints/compile`、`/employees/transition`、`/employees/spawn`(`{FREEOS_HOME}/tenants/<id>/employees/`)。**不是** FreeOS 个性化智能体编辑器,也不是 Chat,也不依赖未挂载的 sidecar `/api/agent-studio/*`。注册后的同事出现在 Experts。`freeos org export-standalone` 同时列出 Agents。未迁:Chat、资料上传、人才市场。
- Organization Phase 3(设置切片):宿主内 Organization Settings。Dashboard `/organization/settings` 使用共享 `dashboard/src/org-ui` 的 `SettingsPage`。本页只编辑 `org_os` 目录模块开关(复用 `GET/PUT /api/org-module/modules`)与组织本地偏好(`GET /api/org-module/settings` · `PUT /api/org-module/prefs`,`{FREEOS_HOME}/org-os/prefs.json`)。**不是** FreeOS 系统设置:大模型密钥、用户、时区仍链到 `/system-settings`。没有边车,也不复制 sidecar 的 AI/用户/数据库页。`freeos org export-standalone` 同时列出 Settings。未迁:Chat、边车系统设置。
Expand All @@ -22,6 +23,7 @@

### 修复

> 下面若干「启动即拉起本机 openXYOS」条目记录的是 0.0.1 边车时代问题。默认路径已被 [0.0.2] 与本文件 Unreleased 的 Phase 5 取代:安装与首屏不再捆绑或自动拉起 Node。

- Windows 安装预配不再把 Node 工作目录选到残留的嵌套 `openxyos\\openxyos`:顶层已有 `backend-dist/server.js` 与 `dist/index.html` 时必须用 live 根。嵌套 cwd 会让 `node backend-dist/server.js` 立刻退出且 stdout/stderr 为空,安装空等 90s 后以退出码 12 失败。`start-sidecar.ps1` / 预配 / 桌面 Go / Python 启动路径统一按此选择 cwd;每次启动截断 `start.log`;Shell.Application 若未刷新日志则改走 explorer / Start-Process,Node fail-fast 不再伪装成 livez 超时。
- Windows 安装详情不再把 openXYOS 预配的 UTF-8 Node/PowerShell 控制台(`[Error] POST /api/auth`、`[seed]`、中文 Server/WebSocket 状态)按系统 ANSI/GBK 打成乱码。NSIS 只用 `nsExec::Exec` 等退出码,详情页只显示本地化步骤结果;完整日志写入 `%LOCALAPPDATA%\\FreeOS\\openxyos\\provision.log` / `start.log`(UTF-8)。解压前停止并等待旧的 FreeOS openXYOS Node 退出;livez 通过即成功,不把启动期 auth 日志当失败。
Expand Down
1 change: 1 addition & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -122,6 +122,7 @@ The TypeScript sidecar under `modules/openxyos/` is optional.
| CLI | `uv run freeos org enable` · `uv run freeos org status` · `uv run freeos org loop run` |
| Plugin | Admin → Plugins → **Organization OS** (`org-os`) |
| API | `PATCH /api/org-module` with `{ "enabled": true }` |
| Standalone commercial site | `uv run freeos org export-standalone --out dist/openxyos-web` — see [docs/org-export.md](docs/org-export.md) |

Optional Node sidecar (export/sync/advanced deploy only):

Expand Down
4 changes: 2 additions & 2 deletions README_CN.md
Original file line number Diff line number Diff line change
Expand Up @@ -208,12 +208,12 @@ curl -fsSL https://finnie-1258344699.cos.ap-guangzhou.myqcloud.com/octop/install

| 平台 | 制品 |
|------|------|
| Windows | `FreeOS-desktop-windows-amd64-<version>.exe`(64 位)/ `FreeOS-desktop-windows-arm64-<version>.exe`(ARM64)— NSIS 安装程序,内置 openXYOS,打开即可聊天+组织 |
| Windows | `FreeOS-desktop-windows-amd64-<version>.exe`(64 位)/ `FreeOS-desktop-windows-arm64-<version>.exe`(ARM64)— NSIS 安装程序,单进程 FreeOS + 宿主内 Organization;不捆绑也不自动拉起 openXYOS Node |
| macOS | `FreeOS-desktop-darwin-arm64-<version>.dmg`(Apple 芯片)/ `FreeOS-desktop-darwin-amd64-<version>.dmg`(Intel) |
| Linux | `FreeOS-desktop-linux-amd64-<version>.tar.gz` / `FreeOS-desktop-linux-arm64-<version>.tar.gz` |
| 飞牛 NAS(FnOS) | `Octop-fnos-docker-<version>.fpk`(依赖 Docker)/ `Octop-fnos-native-<version>.fpk`(无需 Docker)— 通过应用中心安装 |

桌面客户端说明见 [desktop/README.md](desktop/README.md),飞牛打包指南见 [fnos/README.md](fnos/README.md)。
桌面客户端说明见 [desktop/README.md](desktop/README.md),飞牛打包指南见 [fnos/README.md](fnos/README.md)。独立商业组织站见 [docs/org-export.md](docs/org-export.md)(`freeos org export-standalone`),不是默认安装器里的第二套 Node。

**备选 — PyPI**(若你已自行管理 Python 环境):

Expand Down
5 changes: 5 additions & 0 deletions dashboard/src/pages/Organization/OrgMiniBrowser.tsx
Original file line number Diff line number Diff line change
@@ -1,3 +1,8 @@
/**
* Leftover iframe chrome for the optional Node sidecar (`FREEOS_ORG_SIDECAR=1`).
* The default Organization workbench (`index.tsx`) does not mount this.
* Core org pages live in `dashboard/src/org-ui` and talk to `/api/org-module/*`.
*/
import { useMemo, type MutableRefObject } from "react";
import { Button, Input, Tooltip } from "antd";
import { ArrowLeft, ArrowRight, RotateCcw } from "lucide-react";
Expand Down
21 changes: 12 additions & 9 deletions desktop/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,8 @@ Windows end-user product: **download the NSIS `.exe` → install → open FreeOS

| Path | Role |
|------|------|
| [`portable/`](portable/) | Green zip packaging (CPython + host wheel + Node/openXYOS sidecar) |
| [`src/`](src/) | Wails v3 shell: extract zip, start host + sidecar, tray/settings |
| [`portable/`](portable/) | Green zip packaging (CPython + host wheel; Node/openXYOS sidecar opt-in) |
| [`src/`](src/) | Wails v3 shell: extract zip, start host (sidecar only if `FREEOS_ORG_SIDECAR=1`), tray/settings |
| [`package-release.sh`](package-release.sh) | Native end-to-end portable + Wails release build |

## Data directory
Expand Down Expand Up @@ -109,21 +109,23 @@ On first open the shell:

## Build green zip

From repo root (needs Node 20+ so openXYOS can be built into the zip):
From repo root (Node 20+ is only required to rebuild the dashboard or to
opt into `SHIP_OPENXYOS_RUNTIME=1`):

```bash
make -f desktop/portable/Makefile green
```

The Node sidecar is optional. Package it with the green zip when you want
advanced export/sync; skip it with `SKIP_ORG_SIDECAR=1`. Desktop/runtime
never requires it for Organization.
The Node sidecar is optional. Default green zips skip it (`SKIP_ORG_SIDECAR=1`).
Package it only with `SHIP_OPENXYOS_RUNTIME=1` (or `SKIP_ORG_SIDECAR=0`) when
you want advanced export/sync. Desktop/runtime never requires it for
Organization.

CI: `.github/workflows/octop-desktop.yml` (**name:** FreeOS Desktop Package)
builds native platform/arch variants. `v*` tags and `workflow_dispatch`
(platforms=`all`) run all six; pull requests that touch `desktop/` or
`modules/openxyos/` build `darwin-*` and `windows-*` (amd64 + arm64). Each job
creates the green zip (including the sidecar) and packages the Wails app.
creates the slim green zip (Python host only) and packages the Wails app.

This cloud/Linux VM cannot emit a Windows `.exe`. The job that does is
**FreeOS Desktop Package** → matrix `windows-amd64` / `windows-arm64`
Expand All @@ -132,8 +134,9 @@ This cloud/Linux VM cannot emit a Windows `.exe`. The job that does is
## Build a complete desktop release

Run the end-to-end script on the matching native host. It builds the Dashboard,
creates and verifies the portable runtime (with openXYOS), embeds it into Wails,
and produces the final native package:
creates and verifies the portable Python host (Node/openXYOS only if
`SHIP_OPENXYOS_RUNTIME=1`), embeds it into Wails, and produces the final
native package:

```bash
desktop/package-release.sh
Expand Down
6 changes: 4 additions & 2 deletions desktop/src/build/stage_openxyos_runtime.py
Original file line number Diff line number Diff line change
@@ -1,8 +1,10 @@
#!/usr/bin/env python3
"""Build openxyos-runtime.zip from a green portable zip or staging tree.

The Windows NSIS installer copies this zip into $INSTDIR and expands it to
$INSTDIR\\openxyos so the finish log shows FE+BE, not only FreeOS.exe.
Opt-in only. Default Windows/macOS/Linux packages do not call this script
and do not ship the zip. Pass SHIP_OPENXYOS_RUNTIME=1 to stage it; NSIS
then copies the zip into $INSTDIR but still does not extract or start Node
unless FREEOS_ORG_SIDECAR=1 later.
"""

from __future__ import annotations
Expand Down
9 changes: 5 additions & 4 deletions desktop/src/build/windows/nsis/wails_tools.nsh
Original file line number Diff line number Diff line change
Expand Up @@ -142,15 +142,15 @@ RequestExecutionLevel "${REQUEST_EXECUTION_LEVEL}"
${EndIf}
!macroend

# Organization is in-host. Default Setup copies no openxyos-runtime.zip.
# Opt-in builds (-DOPENXYOS_RUNTIME_ZIP_PRESENT) copy the zip + scripts
# but still never extract, start Node, wait for livez, or Abort.
# Organization is in-host. Default Setup copies no openxyos-runtime.zip
# and does not create $INSTDIR\openxyos. Opt-in builds
# (-DOPENXYOS_RUNTIME_ZIP_PRESENT) copy the zip + scripts but still
# never extract, start Node, wait for livez, or Abort.
# Do not FileWrite goto-label .cmd scripts here. Do not register logon autostart.
!macro wails.provisionOpenXYOS
!insertmacro wails.userLocalAppData
SetDetailsPrint both
DetailPrint "$(OPENXYOS_WORKDIR)"
CreateDirectory "$INSTDIR\openxyos"
!ifdef OPENXYOS_RUNTIME_ZIP_PRESENT
!if /FileExists "${OPENXYOS_RUNTIME_ZIP}"
DetailPrint "$(OPENXYOS_COPY_ZIP)"
Expand All @@ -159,6 +159,7 @@ RequestExecutionLevel "${REQUEST_EXECUTION_LEVEL}"
File "provision-openxyos.cmd"
File "start-sidecar.ps1"
File "start-sidecar.cmd"
CreateDirectory "$INSTDIR\openxyos"
DetailPrint "$(OPENXYOS_OPTIONAL_SKIP)"
!else
!error "OPENXYOS_RUNTIME_ZIP_PRESENT is set but ${OPENXYOS_RUNTIME_ZIP} is missing"
Expand Down
11 changes: 10 additions & 1 deletion docker/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,14 @@

---

This directory contains the Docker build and deployment assets for Octop.
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/*`).

**Home directory names:** the product name is `FREEOS_HOME`. Compose and
this image still use `OCTOP_*` and `~/.octop` as compatibility aliases
(`HOME=/data` → `/data/.octop`). Set `FREEOS_HOME` (or `OCTOP_HOME`) if
you want an explicit path; the app honors `FREEOS_HOME` first.

### Files

Expand Down Expand Up @@ -57,6 +64,8 @@ bash docker/docker_build.sh
| Variable | Default | Description |
|----------|---------|-------------|
| `HOME` | `/data` | Must be `/data` so `~/.octop` maps to the data volume |
| `FREEOS_HOME` | _(unset)_ | Product home. When set, wins over `OCTOP_HOME` / `~/.octop` |
| `OCTOP_HOME` | _(unset)_ | Legacy alias for the same home directory |
| `OCTOP_PORT` | `8088` | HTTP listen port |
| `OCTOP_DEFAULT_PASSWORD` | _(unset)_ | First-run admin password (≥8 chars, letters + digits). When unset, a random password is generated and written to `credential.txt` |
| `OCTOP_ADMIN_USERNAME` | `admin` | Initial admin username |
Expand Down
10 changes: 9 additions & 1 deletion docker/README_CN.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,13 @@

---

本目录包含 Octop 的 Docker 构建与部署相关文件。
本目录包含 Octop / FreeOS 的 Docker 构建与部署相关文件。Compose **只有一个
Python 进程**,没有 Node / openXYOS 边车。Organization 在宿主内运行
(`/api/org-module/*`)。

**目录命名:** 产品名是 `FREEOS_HOME`。本镜像与 Compose 仍用 `OCTOP_*` 和
`~/.octop` 作为兼容别名(`HOME=/data` → `/data/.octop`)。需要显式路径时
设置 `FREEOS_HOME`(或遗留的 `OCTOP_HOME`);应用优先读 `FREEOS_HOME`。

### 文件说明

Expand Down Expand Up @@ -57,6 +63,8 @@ bash docker/docker_build.sh
| 变量 | 默认值 | 说明 |
|------|--------|------|
| `HOME` | `/data` | 必须为 `/data`,数据目录映射到 `~/.octop` |
| `FREEOS_HOME` | _(未设置)_ | 产品家目录。设置后优先于 `OCTOP_HOME` / `~/.octop` |
| `OCTOP_HOME` | _(未设置)_ | 同一家目录的遗留别名 |
| `OCTOP_PORT` | `8088` | HTTP 服务端口 |
| `OCTOP_DEFAULT_PASSWORD` | _(未设置)_ | 首次管理员密码(≥8 位,字母+数字)。未设置时自动生成随机密码并写入 `credential.txt` |
| `OCTOP_ADMIN_USERNAME` | `admin` | 首次管理员用户名 |
Expand Down
5 changes: 4 additions & 1 deletion docker/docker-compose.yml
Original file line number Diff line number Diff line change
@@ -1,5 +1,8 @@
# =============================================================================
# Octop — Docker Compose
# FreeOS / Octop — Docker Compose (single Python process)
#
# One service. No Node / openXYOS sidecar. Organization is in-host.
# Product home name is FREEOS_HOME; OCTOP_* and ~/.octop remain aliases.
#
# 用法(在仓库根目录执行):
# docker compose -f docker/docker-compose.yml up -d
Expand Down
2 changes: 2 additions & 0 deletions docker/docker-entrypoint.sh
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,8 @@
#
# 环境变量:
# HOME — 必须为 /data,使 ~/.octop 映射到数据卷
# FREEOS_HOME — 产品家目录(可选;应用优先于 OCTOP_HOME)
# OCTOP_HOME — 遗留别名。入口脚本仍用 ~/.octop 做首次 init
# OCTOP_DEFAULT_PASSWORD — 首次管理员密码(须 ≥8 位且含字母和数字;
# 不设置则自动生成随机密码,凭据写入
# /data/.octop/credential.txt)
Expand Down
8 changes: 8 additions & 0 deletions docs/adr/001-single-process-model.md
Original file line number Diff line number Diff line change
Expand Up @@ -33,3 +33,11 @@ Everything runs in a single Python process served by uvicorn. There is no extern
- All async; blocking calls must use `run_in_executor`.
- `SharedServices` (DI container) is process-global — safe because the process owns all state.
- Future scale-out would require extracting the worker into a separate process and adding a queue; that seam is already partially visible in `infra/gateway/processor.py`.

## Later confirmation (FreeOS Organization, 2026-09)

Organization control-plane UI and BFF stay in this same Python process
(`/api/org-module/*`, Dashboard `/organization`). A Node openXYOS sidecar
is **not** part of the default installer (Phase 5). Opt in only with
`FREEOS_ORG_SIDECAR=1` / `SHIP_OPENXYOS_RUNTIME=1`. This does not change
the original decision: one process, one port, no required extra runtime.
2 changes: 1 addition & 1 deletion docs/adr/003-org-ui-single-source-dual-delivery.md
Original file line number Diff line number Diff line change
Expand Up @@ -94,4 +94,4 @@ Phase 2 proves the contract on **Announcements** (see [org-merge-plan.md](../org

## Follow-through

Implementation sequencing, overlap matrix, package layout, API ownership, and Phase 2 acceptance criteria live in [org-merge-plan.md](../org-merge-plan.md). This ADR does not move pages or change the installer.
Implementation sequencing, overlap matrix, package layout, API ownership, and Phase 2–5 status live in [org-merge-plan.md](../org-merge-plan.md). Phase 5 default installer is **zero-Node**; standalone commercial deploy is [org-export.md](../org-export.md), not a second always-on runtime.
3 changes: 2 additions & 1 deletion docs/architecture-integration.md
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,8 @@ 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)
- [org-merge-plan.md](org-merge-plan.md) — Phases 0–5; Phase 3 in progress (org chart / employees / skills / governance / knowledge / tasks / reflections / settings / agents)
- [org-merge-plan.md](org-merge-plan.md) — Phases 0–5; Phase 5 default installer is zero-Node (sidecar opt-in)
- [org-export.md](org-export.md) — standalone commercial Organization site (`freeos org export-standalone`)
- [asset-loop.md](asset-loop.md) — operator self-growth loop
- [ADR index](adr/)

Expand Down
12 changes: 6 additions & 6 deletions docs/org-export.md
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
# 独立组织站导出(Phase 4)
# 独立组织站导出(Phase 4 包 + Phase 5 默认安装器

`freeos org export-standalone --out <dir>` 从 **同一套** `dashboard/src/org-ui` 生成可部署的 openXYOS 风格独立站。这是商业加售的交付物,不是第二份手维护前端。

默认 FreeOS 安装器 **不** 因此改成捆绑 Node。Sidecar 仍是可选兼容(`FREEOS_ORG_SIDECAR` / `SHIP_OPENXYOS_RUNTIME`)。安装器瘦身是 **Phase 5**。
默认 FreeOS 安装器 **不** 捆绑 Node,也 **不** 自动拉起 openXYOS。Sidecar 仅作可选兼容(`FREEOS_ORG_SIDECAR=1` / `SHIP_OPENXYOS_RUNTIME=1`)。这是 **Phase 5** 已落地的默认拓扑:一个 Python 进程 + 宿主内 Organization

## 生成

Expand Down Expand Up @@ -51,7 +51,7 @@ FREEOS_UPSTREAM=http://127.0.0.1:8088 docker compose up --build
| UI | 本包 SPA(org-ui) | 同一套 org-ui |
| API | 反向代理到 FreeOS `/api/org-module/*` | 本包自包含服务实现同一合同 |
| 身份 | 本地 JWT,登录打 FreeOS `/api/auth/login` | 客户自己的账号体系发本地 JWT |
| 安装器 | 不变;sidecar 仍可选 | Phase 5:默认安装器零 Node |
| 安装器 | **已落地(Phase 5)**:默认零 Node,sidecar 仅 opt-in | 保持单进程;不把独立站 Node 打进默认安装包 |

`VITE_API_BASE` 默认 `/api`(同源)。不要在浏览器里直连另一个源的 FreeOS,除非那个宿主已配好 CORS。推荐始终走代理。

Expand All @@ -63,9 +63,9 @@ FREEOS_UPSTREAM=http://127.0.0.1:8088 docker compose up --build
| `FREEOS_UPSTREAM` | 运行 | 拥有 `/api/org-module` 与 `/api/auth` 的 FreeOS 源 |
| `PORT` | `npm start` / Vite | 监听端口,默认 `3780` |

## 非目标(本波)
## 非目标 / 残留

- 从默认安装器里摘掉 sidecar(Phase 5)
- 重写整套 Express → 独立 Node API
- 重写整套 Express → 独立 Node API(导出仍代理到宿主 `/api/org-module`)
- 迁 openXYOS Chat
- 抽出 `packages/org-ui` monorepo(仅当 Dashboard Vite 图必须脱离时再做)
- 把独立站 Node 打进默认 Windows/macOS/Linux 安装器(明确不做)
Loading
Loading