Repository navigation
Prepare FreeOS 0.1.0 runtime and distribution fixes - #107
Draft
XYAIStudio wants to merge 39 commits into
Draft
XYAIStudio wants to merge 39 commits into
XYAIStudio wants to merge 39 commits into
Conversation
* fix(update): checkpoint SQLite WAL before desktop process restart In desktop/portable mode, POST /api/update/restart replaced the process image with os.execv without flushing the SQLite WAL. Because SqlitePool uses WAL mode with a large autocheckpoint window, all writes since the last checkpoint were lost on restart (#800). Change _restart_desktop_process to accept the OctopServer, and before execv run PRAGMA wal_checkpoint(TRUNCATE) and close the pool when the database is SQLite. The restart endpoint now injects the server via Depends(get_server). Fixes #800. * style(tests): format desktop restart regression cases
… (#738)
* fix(config): never rewrite an unparseable config.json as empty (#730)
Four call sites read config.json, treated a parse failure as an empty dict and
wrote that back, destroying every other key. One trailing comma plus one
`octop run --port 8088` wiped 17 of 18 keys including the whole `database`
section; the next boot silently came up as a greenfield SQLite instance (fresh
setup-wizard password, zero warnings) while the PostgreSQL data sat unreachable.
Losing `bind_host` the same way is what makes #730's reporter unable to reach
the server from the LAN.
A torn write creates the same precondition with no user error: three of the four
sites wrote config.json with a bare write_text, so a crash / OOM / full disk
mid-write left invalid JSON that the next plugin toggle then wiped.
One shared policy in a new leaf helper, infra/utils/json_file.py:
absent file -> {} and write (first run, unchanged)
valid JSON object -> merge and write (unchanged)
unparseable/non-object -> raise CONFIG_FILE_CORRUPT, write nothing
The error names the file and the parser line/column but never the contents,
which hold database credentials. Writes now go through write_json_atomic (temp +
os.replace, fd closed on every path, temp removed on failure) so no reader can
observe a torn file.
Sites: cli/commands/run.py (_save_configfile_overrides, plus
_load_configfile_overrides which used to fall back to launch defaults),
infra/agents/plugins/manager.py (_write_global_plugin_enabled = the dashboard
toggle), infra/setup/service.py (persist_bind_options),
infra/agents/plugins/seed.py. `octop run` / `octop service start` report the
error and exit 1 via fail_octop (now NoReturn) instead of a traceback.
Supersedes the pinned "treat a malformed file as empty so the next run rewrites
it cleanly" contract: its fixture (`{not valid json`) had nothing to lose, so
the test could not observe the destruction. Rewritten as
test_run_reports_corrupt_config_cleanly and
test_run_does_not_overwrite_corrupt_config.
Verified end-to-end against a real OctopServer + real PostgreSQL. Before: one
`octop run --port` flipped driver postgresql -> sqlite, the instance reverted to
the first-run wizard, and users=1/agents=1 were orphaned in PG with no warning.
After: exit 1, config.json byte-identical, boot fails loudly instead of
switching backends. Mutation check: restoring the lenient policy in the helper
reddens 9 tests spanning all four sites.
make all green (3299 passed, 16 skipped); mypy --strict clean; dashboard
`npx tsc --noEmit` clean.
* fix(config): name the file when config.json is corrupt (#730)
`load_config` let a bare `json.JSONDecodeError` escape: it reports a line and
column but never says *which* file failed, and this entry point is reached from
boot, backup and several CLI commands — not only `octop run`. Raise a ValueError
naming the path and the parser position, refuse a non-object document, and never
echo file contents (config.json holds database credentials).
Same policy as infra/utils/json_file.py, duplicated here because octop.config
must stay free of infra imports (AGENTS.md §5).
`octop run` already exits cleanly on a corrupt config through resolve_bind; this
covers the remaining entry points.
make all green (3301 passed, 16 skipped); mypy --strict clean.
* fix(config): preserve config.json permissions in atomic writes
Self-review against CONTRIBUTING.md / AGENTS.md §7 caught a regression in the
atomic writer added earlier in this branch: tempfile.mkstemp creates the temp
file 0600, so replacing config.json silently tightened an existing 0644 file to
0600. Under `octop service start --scope system` that runs as root and writes
into the service user's home, a root-owned 0600 config.json is unreadable by the
service user and the unit cannot start; the bare write_text it replaced produced
the umask default.
write_json_atomic now chmods the temp file to the mode of the file being
replaced, or to `0o666 & ~umask` for a new file — matching the two pre-existing
config.json writers (infra/db/rebind.py, infra/backup/auto.py; both
write_text + replace) rather than mkstemp's 0600. POSIX-guarded, so Windows
behaviour is unchanged and no test asserts mode bits off POSIX (AGENTS.md §7).
Also adds the missing CHANGELOG line for the load_config error-message change.
Verified: new file -> 0644, existing 0644 -> 0644, existing 0600 -> 0600.
make all green (3303 passed, 16 skipped); make typecheck-frontend green;
eslint 0 errors (67 pre-existing react-hooks warnings).
Note: `make check-all` is red on develop itself — prettier --check fails on
dashboard/src/pages/Agent/Skills/components/SkillsTabs.tsx exactly as committed
by 83378876. Left untouched here; confirmed pre-existing by checking develop's
version of that file in isolation.
Refresh the openXYOS lock so npm ci resolves on Node 24 and require Node >=22.12. Wait for the SearchConfig source label before asserting it; that was the Node 24 dashboard failure while the spinner was still mounted. Bind the organization sidecar to 127.0.0.1 from the server default and every desktop launcher. Seed local accounts only under FREEOS_ORG_LOCAL_TEST, with a random password stored beside the database and a forced change on first sign-in. The UI no longer shows a shared demo password. Mark rc/a/b/dev tags as GitHub prereleases in the release, desktop attach, and FNOS attach workflows. Collapse the changelog to a single 0.1.0 section and stop README_CN from directing installs at PyPI octop. Order desktop version compare so a final release sorts above its rc. Co-authored-by: haoboy007-sudo <haoboy007-sudo@users.noreply.github.com>
Name new FnOS artifacts FreeOS-fnos-*.fpk in the workflow, build script, release links, and user docs. Older Release assets may still be named Octop-fnos-*. Remove the expired WeCom QR from the user guide and README_CN. Readers go to GitHub Discussions or the existing Discord link. Bump vite to 6.4.5, vitest to 4.1.12, and follow-redirects to 1.16.1 so Desktop Package npm audit exits 0. Co-authored-by: haoboy007-sudo <haoboy007-sudo@users.noreply.github.com>
Set the distribution name to freeos so the wheel and sdist are freeos-0.1.0*. The import package and the octop CLI alias stay. FnOS, portable packaging, and release notes use the new filenames and say not to pip install octop. User-facing paths in the docs this change touches name ~/.octop as the data directory. FREEOS_HOME applies only when it is already set; this release does not migrate that directory to ~/.freeos. Co-authored-by: haoboy007-sudo <haoboy007-sudo@users.noreply.github.com>
README and the user guide no longer recommend the Tencent COS octop/install URLs. Those scripts install PyPI octop. Desktop packages on GitHub Releases are the primary install path; CLI installs use this repo's develop scripts. New installs use ~/.freeos. install.sh, install.ps1, and install.bat follow PathLayout: FREEOS_HOME, OCTOP_HOME, an existing ~/.freeos, an existing ~/.octop when ~/.freeos is absent, otherwise ~/.freeos. The desktop app still does not adopt a leftover ~/.octop. Co-authored-by: haoboy007-sudo <haoboy007-sudo@users.noreply.github.com>
Point the package version at 0.1.0rc1 so tag v0.1.0rc1 matches pyproject and stays a GitHub prerelease. Attach SHA256SUMS for desktop installers, portable zips, wheels, and sdists. Align the employee password hint and backup home help with the code. Co-authored-by: haoboy007-sudo <haoboy007-sudo@users.noreply.github.com>
npm audit fix updates DOMPurify, fast-uri, and serialize-javascript in the dashboard lock, and those plus body-parser, ip-address, multer, and undici in the organization module. All stay on the current major. Co-authored-by: haoboy007-sudo <haoboy007-sudo@users.noreply.github.com>
Hash FreeOS-fnos-*.fpk with the other release artifacts, and refresh SHA256SUMS after the FnOS workflow attaches those packages. Co-authored-by: haoboy007-sudo <haoboy007-sudo@users.noreply.github.com>
NSIS VIProductVersion and go-winres file_version reject 0.1.0rc1. Keep the display string, and write 0.1.0.0 for the numeric fields. Co-authored-by: haoboy007-sudo <haoboy007-sudo@users.noreply.github.com>
Windows pathlib orders paths case-insensitively, so freeos-* sorted ahead of FreeOS-*. Compare the filename string instead. Co-authored-by: haoboy007-sudo <haoboy007-sudo@users.noreply.github.com>
Operators still saw [octop] and "Installing Octop" while installing FreeOS. Log prefixes, success lines, and install prompts now say FreeOS. Paths, the octop CLI, and notes about upstream PyPI Octop stay unchanged. Co-authored-by: haoboy007-sudo <haoboy007-sudo@users.noreply.github.com>
Default agent root_dir followed Path.home(), so setup/finish seeded main at ~/.octop/workspaces and overwrote an existing profile when --home pointed elsewhere. Workspaces, the wizard password file, and llama.cpp logs now stay under the product home. A pre-existing directory outside that home is refused, and default-agent seed will not replace files that are already there. Co-authored-by: haoboy007-sudo <haoboy007-sudo@users.noreply.github.com>
The built-in runtime warning stays red only when no provider answers a connectivity check. Ollama or another reachable base URL turns it into a grey note, and an Ollama model can still be selected for chat. Co-authored-by: haoboy007-sudo <haoboy007-sudo@users.noreply.github.com>
Install snippets no longer fetch the develop script. Node is described as absent from the default single-process install, and Docker is no longer called the production recommendation. Data-directory examples use ~/.freeos / FREEOS_HOME. Co-authored-by: haoboy007-sudo <haoboy007-sudo@users.noreply.github.com>
FREEOS_ORG_LOCAL_TEST is set only when FREEOS_ORG_DEV_BOOTSTRAP or FREEOS_ORG_LOCAL_TEST is already explicitly on. Release launches leave it unset. FREEOS_ORG_INTEGRATED stays, because real installs use it for distinct organization tenants and host identity, not for demo accounts. Co-authored-by: haoboy007-sudo <haoboy007-sudo@users.noreply.github.com>
ensureLocalBootstrap runs only when FREEOS_ORG_DEV_BOOTSTRAP or FREEOS_ORG_LOCAL_TEST is explicit, and only when the database has no users and no one-time marker. It no longer reactivates tenants, recreates deleted accounts, or rotates passwords. Release starts do not create demo@demo.com or user@demo.com. Co-authored-by: haoboy007-sudo <haoboy007-sudo@users.noreply.github.com>
Startup no longer writes the internal deployment-rules reflections into tenant 1. Deleting those rows stays deleted across later starts. Co-authored-by: haoboy007-sudo <haoboy007-sudo@users.noreply.github.com>
Startup no longer inserts AI合同智能解析 for every tenant. Uninstalling it stays uninstalled. The catalog entry for an explicit install remains. Co-authored-by: haoboy007-sudo <haoboy007-sudo@users.noreply.github.com>
New archives store workspace_dir relative to the product home. Restore remaps old absolute paths onto the home given to --home and refuses a target outside that directory, so a live workspace is not overwritten. Co-authored-by: haoboy007-sudo <haoboy007-sudo@users.noreply.github.com>
install.sh, install.ps1, and the desktop in-app upgrade now run octop backup create --include-chats before replacing the runtime. The archive sha256 is recorded beside it, and a failed backup aborts the upgrade. Co-authored-by: haoboy007-sudo <haoboy007-sudo@users.noreply.github.com>
…installed contract plugin once After the pre-upgrade backup, one marker-gated pass replaces seeded demo and bootstrap-admin passwords, disables accounts that own no data, deletes exact P16 reflections, and disables the v0.0.x contract plugin row without removing it. Co-authored-by: haoboy007-sudo <haoboy007-sudo@users.noreply.github.com>
Demo inserts live in backend/dev, which the sidecar bundle excludes. The release seed entry refuses to load them unless FREEOS_DEV_BUILD is set, and a scan of the shipped tree rejects the demo account strings. Co-authored-by: haoboy007-sudo <haoboy007-sudo@users.noreply.github.com>
…mation Uninstall now sets the plugin status to disabled so the contract parser gate turns off, and a paid install stays disabled until the client confirms the exact price. Both actions write an audit row. The catalog row is kept. Co-authored-by: haoboy007-sudo <haoboy007-sudo@users.noreply.github.com>
CI run 40838520982 failed npm audit, not the compile. qs 6.16.0 is inside GHSA-6pq8-jhm2-2vcw, and vite-plugin-pwa pulls deepmerge >=4.2.0 (GHSA-gcqx-w48m-w2h4) which has no patched 4.2 release. Overrides move both trees onto versions outside those ranges. Co-authored-by: haoboy007-sudo <haoboy007-sudo@users.noreply.github.com>
…e without one install.sh can run the real pre-upgrade backup against a fake existing home and abort when that backup fails. The Windows NSIS overwrite path now runs the same full backup before copying files and aborts Setup when it fails. makensis itself is not executed here. Co-authored-by: haoboy007-sudo <haoboy007-sudo@users.noreply.github.com>
A release process with inherited local-test flags creates no demo accounts on an empty database, and three later starts leave an existing password hash and tenant status alone. Co-authored-by: haoboy007-sudo <haoboy007-sudo@users.noreply.github.com>
FREEOS_ORG_LOCAL_TEST and FREEOS_ORG_DEV_BOOTSTRAP are dropped unless FREEOS_DEV_BUILD is explicitly set. Parent environments can no longer turn demo seeding on for a release sidecar. Co-authored-by: haoboy007-sudo <haoboy007-sudo@users.noreply.github.com>
Inherited HOST is ignored. LAN or NAS exposure requires FREEOS_ORG_BIND_HOST or OCTOP_BIND_HOST. Compose keeps a container-internal 0.0.0.0 only where the published port defaults to 127.0.0.1; host-network mobile stays on loopback. Co-authored-by: haoboy007-sudo <haoboy007-sudo@users.noreply.github.com>
resolveUiTenantId follows the logged-in non-seed user. A later demo login and the openxyos-local slug no longer win over that user's own tenant. Co-authored-by: haoboy007-sudo <haoboy007-sudo@users.noreply.github.com>
The catalog list no longer returns a price, and the plugin center shows an amount only after the install API asks for confirmation. A migrated contract plugin stays out of the active list; uninstall goes through the HTTP route and leaves the row disabled. Co-authored-by: haoboy007-sudo <haoboy007-sudo@users.noreply.github.com>
…ceholder The vulnerability contact line is now 「漏洞接收邮箱:待董事长指定」 and does not name an inbox. Co-authored-by: haoboy007-sudo <haoboy007-sudo@users.noreply.github.com>
Ruff format --check failed CI on these two files. Co-authored-by: haoboy007-sudo <haoboy007-sudo@users.noreply.github.com>
create() now resolves the workspace through agent_workspace before ensure_agent_workspace. The unit fake only stubbed the old method, so CI make test failed with AttributeError. Co-authored-by: haoboy007-sudo <haoboy007-sudo@users.noreply.github.com>
Portable upgrade tests embed a fake python. After the full backup became mandatory, those tests executed it and failed with exec format error. The default stub writes an archive; the backup-specific tests still replace it. Co-authored-by: haoboy007-sudo <haoboy007-sudo@users.noreply.github.com>
install.sh exits immediately when uname is not Linux or Darwin. The Windows CI runner was executing that path through Git bash and failing before the backup hook. Co-authored-by: haoboy007-sudo <haoboy007-sudo@users.noreply.github.com>
This branch has not been deployed
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Prepare FreeOS 0.1.0 with safer SQLite restart, user-controlled Ollama discovery, malformed-config preservation and cleanup of stale system messages before model calls. Align Python/runtime version metadata and route FreeOS distribution through GitHub Releases without publishing the Octop-compatible package name to PyPI.
Validation so far: backend 3,611 passed / 117 skipped; frontend 1,075 passed; Ruff, mypy, frontend lint/typecheck/format checks and production build passed. The 0.1.0 wheel and sdist have been built and the embedded dashboard/version metadata verified.
This is the development integration PR. Packaged runtime, native desktop and security acceptance are in progress; do not publish a stable release until those checks are complete. v0.0.10 remains available until the replacement release and its assets are verified.
Prepare FreeOS 0.1.0 with safer SQLite restart, user-controlled Ollama discovery, malformed-config preservation and cleanup of stale system messages before model calls. Align Python/runtime version metadata and route FreeOS distribution through GitHub Releases without publishing the Octop-compatible package name to PyPI.
Validation so far: backend 3,611 passed / 117 skipped; frontend 1,075 passed.
Follow-up on this branch (still draft, not merged, not tagged): one-time v0.0.x residue cleanup, demo seed excluded from the release tree, paid-plugin install confirmation, pre-upgrade backup behaviour, release builds ignore inherited demo-seed flags, loopback bind by default, UI tenant no longer prefers demo tenants, and the security contact line is a placeholder. Head
df18457ccf1f970e5ca1889da44b921ab5228086. CI https://github.com/XYAIStudio/FreeOS/actions/runs/40849963899 and desktop https://github.com/XYAIStudio/FreeOS/actions/runs/40849963814 are green.