mirror of
https://github.com/TencentCloud/Octop.git
synced 2026-10-01 23:26:13 +08:00
* docs: refresh README roadmap, anchors, and product sync (#1211) Align EN/CN README with shipped features and current install/channel docs; fix GitHub heading anchors and drop obsolete extras examples. Co-authored-by: jubaoliang <jubaoliang@tencent.com> Co-authored-by: Cursor <cursoragent@cursor.com> * fix(dashboard): define missing --fn-bg-container theme variable (#1216) Dark-theme surfaces that use var(--fn-bg-container, #fff) — most visibly the knowledge-base Markdown preview body, toolbar and outline panel — resolved to a white background while text stayed light, leaving preview content invisible. Define the variable as #ffffff (light) and #141414 (dark), and point the Admin/Users badge tints that borrowed the name for a translucent fill at --fn-bg-tertiary so their look is unchanged. Fixes #1215 * feat(dashboard): let each account customize the sidebar (#1218) Store group order, item placement, and hidden entries on the user so navigation can be rearranged without showing items the account cannot access. Co-authored-by: jubaoliang <jubaoliang@tencent.com> Co-authored-by: Cursor <cursoragent@cursor.com> * style(dashboard): apply Prettier to files that drifted from the formatter (#1222) Co-authored-by: jubaoliang <jubaoliang@tencent.com> Co-authored-by: Cursor <cursoragent@cursor.com> * feat: store role-template id on users.role and harden mobile composer (#1220) Collapse the dual user_role_id / role model so users.role and invites.role hold the template public id, block deleting roles still in use, and keep the chat composer visible under mobile browser visualViewport. Co-authored-by: jubaoliang <jubaoliang@tencent.com> Co-authored-by: Cursor <cursoragent@cursor.com> * docs: use product names for sibling project links in the README (#1225) Link labels now match the product names while the repository URLs stay unchanged. Co-authored-by: jubaoliang <jubaoliang@tencent.com> Co-authored-by: Cursor <cursoragent@cursor.com> * docs(publish): bump version badges in all localized READMEs (#1229) Co-authored-by: jubaoliang <jubaoliang@tencent.com> Co-authored-by: Cursor <cursoragent@cursor.com> * fix: load plugins that still import harness_agent (#1260) Marketplace plugins written before the octop_harness rename fail to install and enable with ModuleNotFoundError. Alias that import onto the installed package. Co-authored-by: jubaoliang <jubaoliang@tencent.com> Co-authored-by: Cursor <cursoragent@cursor.com> * fix(backup): skip the Octop-owned _builtin_skills prefix on zip import (#1255) POST /workspace/archive writes archive entries straight into the workspace; _safe_zip_name only blocks traversal, so a zip could plant files under _builtin_skills/ and .octop/_builtin_skills/. That prefix is owned by Octop: DELETE and POST /workspace/move refuse it via _assert_workspace_mutable and sync_octop_builtin_skills only prunes its own retired names, so planted skills both load as kind=builtin and stay irremovable through the API. This restores the #1105 guard (filter plus warnings reporting) together with its regression test, which a later "restore prior behaviors" commit had removed along with the filter. Fixes #1254 Co-authored-by: jubaoliang <jubaoliang@tencent.com> * fix(dashboard): define the missing --fn-* design tokens (#1240) About 30 --fn-* custom properties were referenced across dashboard styles but never defined in theme-vars.css. References without a fallback resolved to invalid-at-computed-value-time (transparent surfaces, e.g. the Connectors page sunken wells), and fallbacks were often light-only literals that broke the dark theme. Define the missing tokens for both themes, aligned with their nearest existing design-system values, and fix the misspelled --text-secondary / --border-color references that could never resolve. Fixes #1239 * feat(ollama): allow configuring local model download directory (#1279) * feat(ollama): allow configuring local model download directory Users who move Ollama models off the default path could list custom models but Octop treated them as not downloaded. Persist an OLLAMA_MODELS directory, scan manifests for downloaded names, and pass the path when starting serve. Co-authored-by: Cursor <cursoragent@cursor.com> * fix(ollama): keep service running when saving models dir Saving the download directory no longer sends enabled=false, so a running Ollama daemon is not stopped. Disk-scanned models report size 0 so the UI does not show the manifest file size as the model size. Co-authored-by: Cursor <cursoragent@cursor.com> --------- Co-authored-by: Cursor <cursoragent@cursor.com> * feat(skills): let octop-assistant answer product and help questions (#1311) Give the bundled assistant a product overview plus links to octop.cloud and the docs, and keep CLI setup for changes on the running instance. Co-authored-by: jubaoliang <jubaoliang@tencent.com> Co-authored-by: Cursor <cursoragent@cursor.com> * fix(ollama): list local models even when Octop service is off (#1316) * fix(ollama): list local models even when Octop service is off Windows users often run Ollama themselves. Octop only queried the daemon when its managed-service toggle was on, so already-pulled models showed as not downloaded. List from a reachable daemon without starting serve, and mark IDs from fetch-models as downloaded. * docs: note Ollama downloaded-model detection when the service toggle is off * fix(mobile): stop the JPEG stream after a run of failed captures (#1309) `_stream_frames` (the mobile JPEG fallback) retried forever: on `TimeoutError` it logged and `continue`d, and on `captured is None` it just `continue`d. A phone unplugged mid-stream, or a dead adb bridge, makes every capture fail at once, so the loop spun at the frame interval indefinitely — a warning per iteration, a log flood, and a canvas frozen on the last frame with nothing ever sent to explain it. The desktop sibling `desktop/stream.py::_stream_loop` already counts consecutive misses, warns once, and after 30 sends an error frame and breaks. This mirrors that: timeouts and `None` both count as misses, the first one is logged once, and at `_CAPTURE_MISS_LIMIT` (30) the stream sends the `{"type": "error", "message": ...}` frame the rest of this router already uses and returns. A successful frame resets the streak, so an occasional dropped frame still does not tear the stream down. Folding the timeout branch into the shared counter also removes the per-iteration warning flood. * fix(cli): read and write cli_state.json through the shared JSON helpers (#1307) `octop.cli.support.state` keeps a private reader/writer for `~/.octop/cli_state.json` and both halves are looser than the rest of the tree. `load()` parses with a bare `json.loads(path.read_text(...))`, so an unparseable file raises a `json.JSONDecodeError` traceback. This file is read by nearly every CLI command (`config`, `agent`, `db`, `acting`, `ctx`, the REPL), so one damaged file aborts all of them at once. `save()` writes with `path.write_text(...)` — truncate, then write. A crash or a full disk mid-write leaves exactly the truncated file that `load()` then refuses, with no warning and no `ensure_root()` in between. `infra/utils/json_file.py` exists for this; its docstring is explicit that a torn write "creates the same precondition" as a hand-edit slip and that callers "must not fall back to an empty dict". Four call sites already route through it (`cli/commands/run.py`, `agents/plugins/manager.py`, `agents/plugins/seed.py`, `setup/service.py`). `load()` now reads via `read_json_object` and translates `JsonFileCorruptError` into `corrupt_config_error(...)` (`CONFIG_FILE_CORRUPT`) — the same policy as every other `OCTOP_HOME` JSON reader. `save()` writes via `write_json_atomic` (mkstemp + `os.replace`) so a reader never observes a partial file. A non-object payload such as `[1, 2]` also raises the typed error now, instead of a stray `dict.update` `TypeError`. * fix(gateway): preserve IM attachment metadata in history (#1276) * fix(docker): ship the langfuse env var the client actually reads (#1258) OCTOP_LANGFUSE_ENABLED is set by .env.example and forwarded by docker-compose.yml, but nothing reads it: Octop keeps the switch in the settings table (observability_langfuse_enabled) and the langfuse client honours LANGFUSE_TRACING_ENABLED. Add a test that fails while a shipped Langfuse variable has no reader. * fix(api): sandbox media preview responses (#1243) media/preview streams user-controlled bytes (chat attachments, tool outputs) inline on the dashboard origin. image/svg+xml is previewable, so a navigated preview URL executed as a live document on the app origin and could run attacker script — the endpoint also accepts the access_token query parameter for media loads. Serve previews with Content-Security-Policy: sandbox and X-Content-Type-Options: nosniff; image/video previews keep working. Fixes #1242 Co-authored-by: jubaoliang <jubaoliang@gmail.com> * feat: add Octop↔Octop cloud collab for remote experts (#1281) * feat: add Octop↔Octop Bridge for remote agent access Enable admin-managed peer connections with WS tunnel, path allowlist, hello_ack handshake, SSRF guards, and Chat shadow-agent hydrate so operators can probe and use remote agents from the local dashboard. Co-authored-by: Cursor <cursoragent@cursor.com> * fix: serialize bridge turn chunks and flag remote experts LangChain HumanMessage objects in peer turn.chunk frames crashed json.dumps; add a bridge JSON default. Show a 远端/Remote badge on shadow experts in the picker and sidebar lists. Co-authored-by: Cursor <cursoragent@cursor.com> * fix: bridge avatars, named remote badges, and auto-reconnect Keep bundled / CDN icon URLs for shadow experts and only proxy uploaded avatars. Show the bridge display name on remote badges. Add a default-on auto-reconnect switch that backs off on disconnect and disables itself after repeated failures, recording the reason in last_error. Co-authored-by: Cursor <cursoragent@cursor.com> * feat: add card/table views for bridge connections Match the storage page card layout and add a Segmented toggle so admins can switch between a card grid and a table of remote links. Co-authored-by: Cursor <cursoragent@cursor.com> * fix: render bridge expert icons correctly on the chat page Encode bridge agent ids in avatar URLs the same way as chat WS paths, fall back to Lucide when the image fails, size portraits to fill the sidebar avatar, and refresh AgentContext when icon_url changes. Co-authored-by: Cursor <cursoragent@cursor.com> * feat: tunnel peer models and knowledge bases for bridge chat Allow read-only GET of peer providers/resolved, active-model, and knowledge-bases (plus capability) through the Bridge tunnel, expose local bridge connection routes, and point the chat composer at those sources when talking to a shadow expert. Hide local connectors for remote sessions. Also allow agent subagents paths on the tunnel. Co-authored-by: Cursor <cursoragent@cursor.com> * fix: scope bridge chat expert picker to peer agents When the active expert is a Bridge shadow, the composer expert picker and @-mentions only list peers on that connection (not local experts). Encode bridge agent ids for skills and subagents list/install paths. Co-authored-by: Cursor <cursoragent@cursor.com> * fix: hint remote chat pickers to manage settings on the peer In Bridge sessions, replace local “manage …” footers for models, skills, knowledge bases, experts, and subagents with a muted “edit on remote” tip and a toast instead of navigating to local admin. Co-authored-by: Cursor <cursoragent@cursor.com> * feat: polish bridge remote UX and tunnel agent status Allowlist GET …/status so hubs can read real peer harness state (peers need this build). Keep history-migration hub-local, skip noisy bridge polls in the UI, move Bridge under Settings, and mark remote experts with cable + name. Co-authored-by: Cursor <cursoragent@cursor.com> * feat: tunnel remote expert catalogs and polish bridge connection UX Hub can edit peer subagents, memory, channels, tools, plugins, and MBTI through the tunnel; surfaces that cannot hop show an in-drawer hint. Peer must run this build so the new allowlist takes effect. Co-authored-by: Cursor <cursoragent@cursor.com> * feat: group cloud-collab experts and unify header-tunneled composer APIs Keep the selected remote expert on disconnect, gate peer-only surfaces in the UI, and stop forking composer/task requests through dedicated bridge endpoints. Co-authored-by: Cursor <cursoragent@cursor.com> * feat: add search to the Experts toolbar Filter my experts, teams, and the library from the existing button row so long catalogs stay scannable. Co-authored-by: Cursor <cursoragent@cursor.com> * fix: keep inbound cloud-collab cards peer-owned Inbound links can only edit name/icon/notes; disconnect, delete, and auto-reconnect stay disabled. Peer offline shows as 离线, peer delete removes the card, and the default inbound name is the short connection id. Co-authored-by: Cursor <cursoragent@cursor.com> * fix: polish inbound cloud-collab UX and unify 对端 copy Peer-initiated links can only edit display info and cannot redial; offline cards may be deleted. Local-only pages hint when a peer expert is selected. Co-authored-by: Cursor <cursoragent@cursor.com> * fix: map peer team speakers onto Bridge shadows Peer team chats stamped local member ids, so the hub fell back to the host avatar. Rewrite roster and stream speakers onto bridge:{cid}:{id} shadows, and keep the local team picker from mixing in peer experts. Co-authored-by: Cursor <cursoragent@cursor.com> * fix: stop rewriting team thread ids in the Bridge tunnel Member job threads are {room}~{agent}. A blanket JSON replace of the peer agent id turned those into hub shadows, so history 404ed on the peer. Co-authored-by: Cursor <cursoragent@cursor.com> * fix: rewrite peer media URLs and keep bridge turn composer fields Live send_file_to_user frames still pointed at peer-local /api/agents/{id}. Map every teammate id in tunneled JSON, and copy the full dashboard turn body so knowledge bases and HITL policy are not dropped on the peer. Co-authored-by: Cursor <cursoragent@cursor.com> * fix: rename bridge probe tests to avoid pytest module clash tests/unit/bridge/test_probe.py collided with tests/unit/mobile/test_probe.py during collection (same basename). Co-authored-by: Cursor <cursoragent@cursor.com> * feat: collapse extra experts on Bridge cards and fill avatars Show at most four experts on a connection card, with the rest behind expand. Portraits fill the 40px ring without a tinted background. Co-authored-by: Cursor <cursoragent@cursor.com> --------- Co-authored-by: jubaoliang <jubaoliang@tencent.com> Co-authored-by: lulinzhi37-alt <lulinzhi37@gmail.com> * chore: release 1.0.2b5 Co-authored-by: Cursor <cursoragent@cursor.com> * chore: bump uv.lock to 1.0.2b5 Co-authored-by: Cursor <cursoragent@cursor.com> * fix(ollama): sanitize models dir through host path policy Co-authored-by: Cursor <cursoragent@cursor.com> --------- Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com> Co-authored-by: jubaoliang <jubaoliang@tencent.com> Co-authored-by: Cursor <cursoragent@cursor.com> Co-authored-by: Dang Zitou <dengzitao888@163.com> Co-authored-by: Frank Zhang <77115469+Master-Frank@users.noreply.github.com> Co-authored-by: XiaoChen <1326713348@qq.com> Co-authored-by: locip123 <116343912+locip123@users.noreply.github.com> Co-authored-by: lihongyuan99 <64824864+lihongyuan99@users.noreply.github.com> Co-authored-by: lulinzhi37-alt <lulinzhi37@gmail.com>