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
24 changes: 11 additions & 13 deletions .github/workflows/octop-desktop.yml
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ on:
default: true
type: boolean
release_tag:
description: "GitHub Release tag to attach to (e.g. v0.0.1). Used when not running on a v* ref."
description: "GitHub Release tag to attach to (e.g. v0.0.2). Used when not running on a v* ref."
required: false
default: ""
type: string
Expand Down Expand Up @@ -187,6 +187,9 @@ jobs:
- name: Assemble green zip
env:
GREEN_HOST_PLAT: ${{ matrix.plat }}
# Default v0.0.2: Python host only. Set SHIP_OPENXYOS_RUNTIME=1 to
# embed Node/openXYOS (~500MB) in the portable zip + NSIS payload.
SKIP_ORG_SIDECAR: "1"
run: |
set -euo pipefail
echo "GREEN_HOST_PLAT=${GREEN_HOST_PLAT} RUNNER_ARCH=${RUNNER_ARCH:-} uname=$(uname -ms)"
Expand Down Expand Up @@ -220,20 +223,11 @@ jobs:
PYTHONNOUSERSITE=1 \
"$py" desktop/portable/verify_imports.py \
"${verify_args[@]}"
if [[ ! -f "${staging}/org-sidecar/openxyos/backend/server.ts" ]]; then
echo "org-sidecar missing under ${staging}" >&2
exit 1
fi
if [[ ! -f "${staging}/org-sidecar/openxyos/dist/index.html" ]]; then
echo "openXYOS frontend missing under ${staging}/org-sidecar/openxyos/dist" >&2
exit 1
fi
if [[ -f "${staging}/org-sidecar/node/node.exe" || -x "${staging}/org-sidecar/node/bin/node" ]]; then
echo "org-sidecar Node runtime present"
else
echo "bundled Node missing under ${staging}/org-sidecar/node" >&2
if [[ -d "${staging}/org-sidecar" ]]; then
echo "default v0.0.2 portable zip must not embed org-sidecar (set SHIP_OPENXYOS_RUNTIME=1 for opt-in builds)" >&2
exit 1
fi
echo "slim portable zip: org-sidecar absent (in-host Organization)"
# macOS: fail if any native extension linked Homebrew/MacPorts paths.
if [[ "${{ matrix.plat }}" == darwin-* ]]; then
REPO_ROOT="$PWD" # shellcheck source=desktop/portable/_common.sh
Expand Down Expand Up @@ -268,11 +262,15 @@ jobs:

- name: Package desktop app with bundled portable runtime
working-directory: desktop/src
env:
# Slim NSIS: do not pass SHIP_OPENXYOS_RUNTIME=1 (no openxyos-runtime.zip).
SHIP_OPENXYOS_RUNTIME: "0"
run: >-
wails3 task package
ARCH=${{ matrix.arch }}
VERSION=${{ env.OCTOP_VERSION }}
PORTABLE_ZIP=../portable/release/FreeOS-portable-${{ matrix.plat }}-${{ env.OCTOP_VERSION }}.zip
SHIP_OPENXYOS_RUNTIME=0

# archive: false — upload the prebuilt zip as-is. Default archive=true would
# wrap it again, so Actions UI / "Download artifact" becomes zip-in-zip.
Expand Down
2 changes: 1 addition & 1 deletion .github/workflows/sync-main-to-develop.yml
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ on:
workflow_dispatch:
inputs:
version:
description: "Release tag being synced, e.g. v0.0.1. Blank = read main's pyproject.toml."
description: "Release tag being synced, e.g. v0.0.2. Blank = read main's pyproject.toml."
required: false
type: string

Expand Down
19 changes: 17 additions & 2 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@

### 修复


- 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 日志当失败。
- 组织页互生长通道两端都落到可选用状态:推送到 openXYOS 时员工/人才写成列表页能看到的 `active` / `internal` / `available`;从 openXYOS 回流时即使没有技能字段也会登记为同事,技能/插件/MCP 写入 `org-skills` / `org-plugins` / `org-mcps`,并把聊天专家挂到当前用户(修复 `user_id=NULL` 导致「专家」页看不见)。导入后跳到「专家」页,推送/循环后关闭管理抽屉并刷新预览。
Expand Down Expand Up @@ -97,11 +98,25 @@
- First launch on desktop / loopback opens a local guest session — no login wall. Register or sign in only when saving, exporting, or publishing to an account.
- Login, splash, favicons, and desktop icons use the circular XYAI mark. Product version remains 0.0.1.

## [0.0.2] - 2026-09-18

当前 FreeOS 产品版本,与 0.0.1 边车时代 Windows 安装包区分。`1.0.0` 对本阶段过早;后续按 [semver](https://semver.org/spec/v2.0.0.html) 随产品成熟度递增。规范来源是 `pyproject.toml`(同步 `octop.__version__`、桌面 / NSIS / FnOS 回退值,以及 CI 产物名)。发布工作流需要标签时使用 `v0.0.2`;不重写已推送的历史 tag。

命令核对:`uv run freeos --version` 与 `uv run python -c "import octop; print(octop.__version__)"` 均应输出 `0.0.2`。

### 变更

- 桌面单一运行时:组织控制面能力在 FreeOS/Octop Python 宿主内运行(`org_os` / `/api/org-module/*` / 组织页原生工作台)。完整 openXYOS Node(3780)改为可选导出/同步,不再是安装或首屏的硬依赖。
- 组织页默认不再嵌入 `127.0.0.1:3780`,也不再以 livez /「重启边车」挡住登录或首屏。互生长(导入 / 推送 / 循环)走宿主内镜像与同事/专家列表。
- Windows 安装不再解压或启动 `openxyos-runtime`,也不再因 livez 失败中止安装。桌面启动默认不设置 `OPENXYOS_BASE_URL`,不拉起 Node;需要时设 `FREEOS_ORG_SIDECAR=1`。
- `freeos org loop run` 不再 `ensure_sidecar` 或空等 3780。未配置边车时只写 `{FREEOS_HOME}/openxyos-mirror/` 与生命周期登记。
- 产品版本从 `0.0.1` 升到 `0.0.2`,安装包 / NSIS DisplayVersion / `octop.__version__` 同步,便于与边车时代构建区分。后续 GitHub Release 标签为 `v0.0.2`。
- 默认 Windows NSIS / 绿色便携包不再打入 `openxyos-runtime.zip` 或 `org-sidecar`(约 500MB Node 运行包)。`OPENXYOS_RUNTIME_ZIP_PRESENT` 默认关闭;仅 `SHIP_OPENXYOS_RUNTIME=1` 的构建才带边车。

## [0.0.1] - 2026-09-15

当前 FreeOS 产品版本。`1.0.0` 对本阶段过早;后续按 [semver](https://semver.org/spec/v2.0.0.html) 随产品成熟度递增。规范来源是 `pyproject.toml`(同步 `octop.__version__`、桌面 / NSIS / FnOS 回退值,以及 CI 产物名)。发布工作流需要标签时使用 `v0.0.1`;不重写已推送的历史 tag。
首个 FreeOS 产品版本(桌面默认拉起本机 openXYOS Node 边车)。后续版本见 [0.0.2]。规范来源是 `pyproject.toml`。历史发布标签为 `v0.0.1`;不重写已推送的历史 tag。

命令核对:`uv run freeos --version` 与 `uv run python -c "import octop; print(octop.__version__)"` 均应输出 `0.0.1`。

### 新增

Expand Down
21 changes: 12 additions & 9 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@

<p align="center">
<a href="https://www.python.org/downloads/"><img alt="Python 3.12+" src="https://img.shields.io/badge/python-3.12%2B-blue?logo=python&logoColor=white" /></a>
<a href="https://github.com/XYAIStudio/FreeOS/releases"><img alt="Version" src="https://img.shields.io/badge/version-0.0.1-orange" /></a>
<a href="https://github.com/XYAIStudio/FreeOS/releases"><img alt="Version" src="https://img.shields.io/badge/version-0.0.2-orange" /></a>
<a href="LICENSE"><img alt="License: MIT + Apache-2.0" src="https://img.shields.io/badge/license-MIT%20%2B%20Apache--2.0-green" /></a>
</p>

Expand Down Expand Up @@ -62,7 +62,7 @@ Operator detail: [docs/asset-loop.md](docs/asset-loop.md).
`FreeOS-desktop-windows-arm64-<version>.exe`(ARM 电脑)。
2. 双击安装包。安装程序会放到「程序文件」并创建开始菜单和桌面快捷方式。
3. 打开 **FreeOS**。第一次启动会解压内置运行环境(可能要一两分钟),然后直接进入可用会话,无需先登录。
4. 保存、导出或发布到账号时再注册或登录。组织控制台(openXYOS)已随安装包内置,无需再装 Node;侧栏 **Organization** 默认打开。
4. 保存、导出或发布到账号时再注册或登录。侧栏 **Organization** 使用宿主内组织能力,不必再装 Node,也不依赖本机 `127.0.0.1:3780`。完整 openXYOS Node 栈是可选项(导出/同步/高级部署)。

数据目录默认是 `%USERPROFILE%\.freeos`(可用环境变量 `FREEOS_HOME` 改)。旧版 Octop 的 `~/.octop` 仍会被识别。卸载安装包会清空安装目录(默认为 `Program Files\FreeOS`)并删除快捷方式,但**不会**删除该用户数据目录;详见 [desktop/README.md](desktop/README.md#windows-uninstall)。

Expand All @@ -71,7 +71,7 @@ Operator detail: [docs/asset-loop.md](docs/asset-loop.md).
### Prerequisites

- Python 3.12+ (the project uses [uv](https://docs.astral.sh/uv/))
- Node.js 20.19+ only if you start the organization sidecar from source, or rebuild the dashboard. The Windows installer already bundles Node + openXYOS.
- Node.js 20.19+ only if you opt into the organization sidecar (`FREEOS_ORG_SIDECAR=1`) from source, or rebuild the dashboard. A fresh FreeOS install does not need Node.

### From this repository

Expand Down Expand Up @@ -112,22 +112,25 @@ Full host suite: `uv run pytest` / `make test-fast` (needs the usual extra servi

## Enable the organization module

The host stays Python. openXYOS stays a TypeScript sidecar under `modules/openxyos/`. Toggle it from any of:
The host stays Python. Organization first paint is the native dashboard page
plus `/api/org-module/*` (catalog, ingest/import, growth loop, employees).
The TypeScript sidecar under `modules/openxyos/` is optional.

| Surface | Action |
|---|---|
| Dashboard | Sidebar → **Organization** → enable switch |
| CLI | `uv run freeos org enable` · `uv run freeos org status` |
| Dashboard | Sidebar → **Organization** (in-host workbench) |
| 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 }` |

Then start the sidecar (Node 20+):
Optional Node sidecar (export/sync/advanced deploy only):

```bash
bash scripts/run-org-sidecar.sh
FREEOS_ORG_SIDECAR=1 bash scripts/run-org-sidecar.sh
```

Default origin: `http://127.0.0.1:3780` (`FREEOS_ORG_SIDECAR_URL` / `OPENXYOS_BASE_URL` / `FREEOS_ORG_SIDECAR_PORT` to override). When `/api/health/livez` succeeds, `/organization` embeds the org console and `/api/org-module/sidecar/*` proxies to it.
Default origin if opted in: `http://127.0.0.1:3780`. Organization and
`freeos org loop run` do **not** wait for `/api/health/livez`.

**Auth:** FreeOS JWT users and openXYOS tenants are separate. The proxy forwards `X-FreeOS-User*` and `X-FreeOS-Tenant-Id`. One tenant = one workspace/sandbox — not prompt isolation.

Expand Down
2 changes: 1 addition & 1 deletion README_CN.md
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@
<p align="center">
<a href="https://www.python.org/downloads/"><img alt="Python 3.12+" src="https://img.shields.io/badge/python-3.12%2B-blue?logo=python&logoColor=white" /></a>
<a href="https://github.com/TencentCloud/Octop/blob/main/LICENSE"><img alt="License: MIT" src="https://img.shields.io/badge/license-MIT-green" /></a>
<a href="https://github.com/XYAIStudio/FreeOS/releases"><img alt="Version" src="https://img.shields.io/badge/version-0.0.1-orange" /></a>
<a href="https://github.com/XYAIStudio/FreeOS/releases"><img alt="Version" src="https://img.shields.io/badge/version-0.0.2-orange" /></a>
<a href="https://pypi.org/project/octop/"><img src="https://img.shields.io/pypi/v/octop" alt="PyPI" /></a>
<a href="https://github.com/astral-sh/ruff"><img alt="Code Style: Ruff" src="https://img.shields.io/badge/code%20style-ruff-000000?logo=ruff&logoColor=white" /></a>
<a href="https://github.com/TencentCloud/Octop"><img alt="GitHub stars" src="https://img.shields.io/github/stars/TencentCloud/Octop?style=social" /></a>
Expand Down
24 changes: 24 additions & 0 deletions dashboard/src/api/modules/orgModule.ts
Original file line number Diff line number Diff line change
Expand Up @@ -49,8 +49,24 @@ export interface OrgControlPlane {
approvals: number;
}

export interface OrgColleague {
slug: string;
name: string;
lifecycle: string;
agent_id: string;
spawned: boolean;
}

export interface OrgExpert {
agent_id: string;
slug: string;
name: string;
}

export interface OrgOverview {
enabled: boolean;
runtime?: "in_host" | string;
sidecar_optional?: boolean;
sidecar_reachable: boolean;
sidecar_embed_ok?: boolean;
sidecar_url: string;
Expand All @@ -61,6 +77,14 @@ export interface OrgOverview {
last_sync: string | null;
freeos: OrgPlaneCounts;
openxyos: OrgControlPlane;
colleagues?: OrgColleague[];
experts?: OrgExpert[];
org_surfaces?: {
employees: number;
talent: number;
skills: number;
plugins: number;
};
last_loop: Record<string, unknown> | null;
notes: string[];
catalog: OrgCapability[];
Expand Down
25 changes: 20 additions & 5 deletions dashboard/src/locales/en.json
Original file line number Diff line number Diff line change
Expand Up @@ -19,10 +19,25 @@
"statusBarTitle": "Organization",
"on": "Enabled",
"off": "Disabled",
"sidecarUp": "Local openXYOS connected",
"sidecarEmbedFailed": "Preview failed to load",
"sidecarDown": "Opening local openXYOS",
"sidecarOpening": "Opening local openXYOS",
"sidecarUp": "Optional openXYOS connected",
"sidecarEmbedFailed": "Optional preview failed to load",
"sidecarDown": "In-host organization",
"sidecarOpening": "In-host organization",
"inHostReady": "In-host organization ready",
"sidecarOptionalChip": "Node sidecar optional",
"advancedConsole": "Advanced: optional openXYOS",
"colleaguesTitle": "Colleagues and experts",
"colleaguesEmpty": "No colleagues yet. Import, produce, or run the growth loop.",
"orgSurfacesTitle": "Organization assets (in-host)",
"runtimeInHost": "FreeOS host",
"sidecarAdvancedHint": "The Node console on port 3780 is optional export/sync. Organization and the growth loop work without it.",
"packLocalDone": "Wrote the local organization mirror. Assets are selectable below and on Experts.",
"expertsHint": "Spawned colleagues are also listed on Experts.",
"surfaceEmployees": "Employees",
"surfaceTalent": "Talent",
"surfacePlugins": "Plugins",
"openExperts": "Open Experts",
"colleagueLifecycle": "Lifecycle",
"lastSync": "Last sync",
"restartSidecar": "Restart openXYOS frontend and backend",
"restartSidecarCta": "Restart frontend and backend",
Expand Down Expand Up @@ -104,7 +119,7 @@
"timelineRemote": "Pushed to control plane",
"timelineGovernance": "High-risk tool blocked by governance",
"emptyTitle": "First look at Organization",
"emptyBody": "FreeOS on the left owns colleagues, experts / assistants not yet in a department, skills, MCP, and tasks. openXYOS on the right owns department employees, blueprints, modules, and approvals. After Setup the local console opens on its own; you can also run the loop once to see a real cycle.",
"emptyBody": "FreeOS on the left owns colleagues, experts / assistants not yet in a department, skills, MCP, and tasks. Organization on the right owns department employees, blueprints, modules, and approvals — all in this host. Run the loop once to see a real cycle. The Node sidecar is optional.",
"startSidecarTitle": "Opening local openXYOS",
"startSidecarBody": "Organization opens the local test URL http://127.0.0.1:3780 directly.",
"startSidecarAction": "Open local openXYOS",
Expand Down
25 changes: 20 additions & 5 deletions dashboard/src/locales/zh.json
Original file line number Diff line number Diff line change
Expand Up @@ -19,10 +19,25 @@
"statusBarTitle": "组织",
"on": "已启用",
"off": "已关闭",
"sidecarUp": "本机 openXYOS 已连接",
"sidecarEmbedFailed": "预览页未能加载",
"sidecarDown": "正在打开本机 openXYOS",
"sidecarOpening": "正在打开本机 openXYOS",
"sidecarUp": "可选 openXYOS 已连接",
"sidecarEmbedFailed": "可选预览未能加载",
"sidecarDown": "宿主内组织已就绪",
"sidecarOpening": "宿主内组织已就绪",
"inHostReady": "宿主内组织已就绪",
"sidecarOptionalChip": "Node 边车可选",
"advancedConsole": "高级:可选 openXYOS",
"colleaguesTitle": "同事与专家",
"colleaguesEmpty": "还没有同事。请导入、从语料生产,或运行自增长循环。",
"orgSurfacesTitle": "组织资产(宿主内)",
"runtimeInHost": "FreeOS 宿主",
"sidecarAdvancedHint": "3780 上的 Node 控制台只用于导出/同步/高级部署。组织页和自增长循环不依赖它。",
"packLocalDone": "已写入本地组织镜像。资产可在下方和「专家」页选用。",
"expertsHint": "登记后的同事也会出现在「专家」页。",
"surfaceEmployees": "员工",
"surfaceTalent": "人才",
"surfacePlugins": "插件",
"openExperts": "打开专家页",
"colleagueLifecycle": "生命周期",
"lastSync": "最近同步",
"restartSidecar": "重启 openXYOS 前后端服务",
"restartSidecarCta": "重启前后端服务",
Expand Down Expand Up @@ -104,7 +119,7 @@
"timelineRemote": "已推送到控制面",
"timelineGovernance": "高风险工具被治理拦截",
"emptyTitle": "第一次打开组织",
"emptyBody": "左侧 FreeOS 负责同事、尚未入部门的专家 / 智能助手、技能、MCP 与任务;右侧 openXYOS 负责部门员工、蓝图、模块与审批。安装完成后会自动打开本机 openXYOS;也可直接运行组织循环看一次真实闭环。",
"emptyBody": "左侧 FreeOS 负责同事、尚未入部门的专家 / 智能助手、技能、MCP 与任务;右侧组织能力负责部门员工、蓝图、模块与审批——都在本宿主内。直接运行组织循环即可看到真实闭环。Node 边车是可选项。",
"startSidecarTitle": "正在打开本机 openXYOS",
"startSidecarBody": "组织界面直接访问本机测试网址 http://127.0.0.1:3780。",
"startSidecarAction": "打开本机 openXYOS",
Expand Down
51 changes: 44 additions & 7 deletions dashboard/src/pages/Organization/Organization.module.less
Original file line number Diff line number Diff line change
@@ -1,13 +1,9 @@
/*
* Organization page layout
* ------------------------
* The main view is a slim blue status bar + a full-area iframe. The iframe
* box is height-constrained to the remaining window (not stretched to match
* leftover chrome). That matters for openXYOS dialogs: `position:fixed`
* inside the iframe is relative to the iframe element's box. A tall iframe
* (old two-column layout) centered modals far below the visible FreeOS
* viewport. Keeping the iframe == the visible pane centers overlays both
* vertically and horizontally.
* The main view is a slim blue status bar + the in-host Organization
* workbench (catalog, colleagues, growth loop). The optional Node console
* is not required for first paint.
*/
.page {
position: relative;
Expand All @@ -19,6 +15,47 @@
gap: 0;
}

.workbench {
flex: 1;
min-height: 0;
overflow: auto;
padding: 20px 24px 32px;
display: flex;
flex-direction: column;
gap: 20px;
}

.colleagueList {
display: flex;
flex-direction: column;
gap: 8px;
margin: 0;
padding: 0;
list-style: none;
}

.colleagueRow {
display: flex;
align-items: center;
justify-content: space-between;
gap: 12px;
border-radius: 12px;
padding: 10px 14px;
background: var(--fn-bg-secondary);
}

.colleagueName {
margin: 0;
font-size: 14px;
font-weight: 650;
}

.colleagueMeta {
margin: 2px 0 0;
font-size: 12px;
color: var(--fn-text-secondary);
}

.statusBar {
display: flex;
align-items: flex-end;
Expand Down
Loading
Loading