Repository navigation
Main - #24
Open
Keninjavelas wants to merge 3156 commits into
Open
Main#24Keninjavelas wants to merge 3156 commits into
Keninjavelas wants to merge 3156 commits into
Conversation
…tion - Vendor KaTeX fonts and Mermaid library to static/lib for offline math rendering - Add comprehensive troubleshooting guide and setup documentation updates - Implement CDN asset vendoring script (scripts/vendor_cdn_assets.py) - Expand test suite with 60+ new test cases covering tool tiering, diagnostics, and first-boot scenarios - Add smoke tests framework and core tour extraction tests - Enhance security documentation and update roadmap checkpoints - Refactor middleware and agent loop for improved context budget handling - Add tour core module for guided user onboarding experiences - Update CI workflow configuration and security settings - Add desktop configuration file and branded documentation assets - Improve cookbook, email, STT, and TTS route implementations - Update tool execution, indexing, and provider configurations for better reliability
…pace is set (#6722) * fix(agent): give file tools the agent workspace as root when no workspace is set (#6679) With no workspace bound, bash/python run in data/agent_workspace, but RequestAuthority sealed no filesystem root, so every native file tool failed with "requires a sealed resource root", and an approved write_file failed with "no sealed resource identity". Seal the agent workspace instead, and resolve relative paths in _resolve_tool_path against it rather than the server's cwd. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * test: re-seal resource roots when a test swaps the authority owner (#6679) A no-workspace authority now seals the agent workspace for its owner, so replace(authority, owner="bob") copied alice's root and was rejected before the approval-binding check the tests are about. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * fix(agent): only seal a vetted agent workspace as the file-tool root (#6679) Apply the agent_cwd() check before sealing data/agent_workspace: it must be a real directory in the readable data subdirs, otherwise no root is sealed. A symlinked workspace no longer redirects the file tools or the bash/python launch scope. Tighten the dispatch test assertions to the exact 'outside the sealed roots' message. * refactor(agent): vet the no-workspace file root with default_agent_workspace (#6679) --------- Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
…6353) * fix(security): block read-only cookbook tools for non-admin owners list_cached_models, list_served_models, tail_serve_output, list_downloads, search_hf_models, list_serve_presets and list_cookbook_servers were in the plan-mode read-only allowlist but in neither NON_ADMIN_BLOCKED_TOOLS nor the dispatcher's _ADMIN_TOOLS. Each implementation calls a require_admin route over the internal loopback with the process-wide INTERNAL_TOOL_TOKEN and never checks the owner, so a non-admin user's agent inherited admin reach through them. list_cached_models is the worst case: a caller-chosen `host` is forwarded to /api/model/cached, which SSHes to that host with the app user's keys and walks caller-chosen model_dirs. THREAT_MODEL.md lists model serving as admin-only, so gate the read side the same way as serve/download. Adding the names to NON_ADMIN_BLOCKED_TOOLS also hides them from non-admin tool schemas and caps bearer-token agent runs; _ADMIN_TOOLS blocks them at dispatch. Regression test covers both lists, schema hiding, and that the loopback is never reached for a non-admin owner. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01TwcwfY2uQMxNRsK3y6xBAp * fix(cookbook): bind request authority in admin gate regressions Keep all seven read-only Cookbook tools in the admin prompt inventory. Grant request authority in dispatch tests so the admin gate itself is exercised, and verify administrators still reach each handler. Validation: 359 focused authorization, tool-policy and schema tests passed. Against the running app with real auth accounts, all seven tools reject a non-admin and an admin reaches the authenticated Cookbook HTTP API. --------- Co-authored-by: Claude Fable 5.1 <noreply@anthropic.com> Co-authored-by: Afonso Junior <chatgpt@yack.com.br>
* fix(email): guard user-supplied IMAP/SMTP hosts against SSRF POST /api/email/accounts/test opened raw imaplib/smtplib connections to whatever host:port the request body named, and POST/PUT /api/email/accounts and PUT /api/email/config persisted arbitrary hosts for the background pollers to contact. All of these sit behind require_user/require_owner with no admin gate, so any authenticated user could make the server connect to loopback, LAN and cloud-metadata targets (169.254.169.254) and read the first 200 characters of the remote banner back out of the friendly error. THREAT_MODEL.md lists email as admin-only; the tool layer honours that but the HTTP routes did not. Add check_outbound_host() to src/url_safety.py, a bare-host companion to check_outbound_url() with the same classification (link-local, multicast, reserved and unspecified always rejected; private/loopback only with block_private) plus localhost-name handling and an explicit policy for names that do not resolve. Wire it into the four email routes via _check_mail_host(): non-admin owners (and everyone when EMAIL_BLOCK_PRIVATE_IPS=true) also lose private/loopback targets, admins keep the local-first LAN/Dovecot setups. Unresolvable names pass through because the connect that follows fails with the same DNS error. Regression tests cover the helper's policy table and each route: the test route rejects before any socket opens, save routes reject before touching the DB, admins keep loopback unless locked down, and an update that fails validation leaves the stored row untouched. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01TwcwfY2uQMxNRsK3y6xBAp * fix(email): harden IMAP/SMTP SSRF protection against rebinding, TOCTOU, and unvetted hosts - P0: Implement safe_create_connection() in src/url_safety.py to resolve hostnames once, validate every returned address against SSRF policy, and connect directly to the pinned IP. This eliminates DNS rebinding and TOCTOU while preserving TLS SNI and certificate hostname verification across IMAP, IMAPS, STARTTLS, SMTP, and SMTP_SSL. - P1: Ensure unresolvable or deferred hostnames cannot become an unrestricted future connection capability by enforcing runtime SSRF validation fail-closed on every connection, while maintaining compatibility with offline configurations. - P2: Extend SSRF enforcement to the core connection layer (_open_imap_connection, _send_smtp_message, _imap_connect) using ContextVar owner scoping, protecting pre-existing DB rows, restored configs, background pollers, and scheduled operations. - P3: Allow admin and single-user access to IPv6 loopback (::1, [::1]) for local mail servers (e.g. Dovecot) by checking loopback before is_reserved, while keeping link-local, cloud metadata (169.254.169.254, 100.100.100.200), and non-admin restrictions strictly enforced. - Add comprehensive regression and adversarial test coverage in tests/test_email_account_host_ssrf.py. * fix(email): reject unresolved saved hosts without stdlib monkeypatches Use the existing explicit policy IMAP/SMTP classes and canonical connect_outbound_tcp helper. Remove process-wide stdlib assignments, context-variable plumbing, redundant aliases and resolver-signature retries. Reject unsafe or unresolved hosts before account/config persistence, keep DNS work off the event loop, return fixed client errors, identify Alibaba metadata accurately and reject invalid TCP ports. Validation: 654 relevant email, URL-safety and CodeQL regression tests passed, 3 skipped. Three unrelated browser checks were excluded after environment failures (missing Playwright browser and Chromium timeout). Running-app checks verified rejected create/update/config requests leave stored data unchanged, administrator LAN configuration still works, and metadata/non-admin loopback are blocked. --------- Co-authored-by: Claude Fable 5.1 <noreply@anthropic.com> Co-authored-by: PR #6029 Reviewer <reviewer@odysseus-review.local> Co-authored-by: Afonso Junior <chatgpt@yack.com.br>
* fix(ui): let confirm-dialog buttons grow to fit wrapped labels
The global `button { height:32px }` rule also applies to styledConfirm's
buttons. A label that wraps to two lines, such as "Delete chat and images",
"Launch anyway (CPU)" or a three-button dialog's alternate action, keeps
one line's height, so its second line renders below the button. On narrow
windows the dialog makes the buttons equal width, so this hits most
multi-word labels; it also happens on desktop, where the dialog box is
narrow too.
Give .styled-confirm-box .confirm-btn height:auto with min-height:32px.
Single-line buttons keep their current 32px.
Bumps the shared stylesheet/app cache token and the service worker cache
name, since a stylesheet changed.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
* chore(static): leave admin.js's cache tag unchanged
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
* fix(cache): keep upstream's service worker cache name format
dev's editor tests require CACHE_NAME to match
odysseus-v<N>-pr40-editor-precache, so keep the version bump and use
that suffix.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
---------
Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
* fix(skills): restore the source editor from test results * fix(skills): align the chat link module version * test: isolate photo routing from external MCP registry state
* fix(modals): keep restored settings and theme windows open * fix(theme): cancel closing on a rapid toggle reopen * test: isolate photo routing from external MCP registry state * fix(cache): preserve the upstream editor worker key format
…(#6782) * fix(ui): keep the confirm dialog's OK button in line with the others #styled-confirm-ok was moved down 2px (position: relative; top: 2px), so the OK button sat 2px below Cancel and the alternate button in every styledConfirm dialog. Its label, and the alternate button's, now sit in a span nudged the same way as the Cancel label, so the text keeps its place and no button moves. Stylesheets and app.js get a new cache-bust token. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * refactor(ui): build confirm labels inline and share the Cancel nudge rule Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * fix(cache): keep upstream's service worker cache name format dev's editor tests require CACHE_NAME to match odysseus-v<N>-pr40-editor-precache, so keep the version bump and use that suffix. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> --------- Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
…on message route (#6826) (#6827)
…n (#6725) (#6726) The recipe Run button sent repo_id "<backend> setup"; the space fails the pip package-spec check, so every Run returned "Invalid pip package name". It now sends "<backend>-setup". The vLLM/SGLang recipes start with `uv pip install ... --torch-backend auto`, but uv was not in the serve command allowlist. Allow uv only for the `pip install` subcommand. Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
…s (#6829) (#6830)
…64 characters (#6820) (#6821)
…columns MultiModelThread/MultiModelMessage map the new multi-model conversation feature (created via create_all). PlanStep gains doc_id/doc_action so the document-aware step code can read them; an idempotent ALTER-on-startup migration backfills those two columns for existing databases (create_all only covers fresh ones).
Run one prompt across several models/endpoint URLs concurrently, with a thread lifecycle manager (core/multi_model_manager.py), an async fan-out executor (src/multi_model_executor.py), authenticated routes registered in app.py, and a browser pane-sync UI under static/js/multiModel/. Sessions list and stylesheet gain the multi-model thread affordances.
Plan steps can now target a document with a create/update/edit/suggest/read verb. Adds the /steps/document endpoint and doc context in _step_dict (plan_routes.py), a _execute_document_step branch in PlanExecutor, and the docStepBuilder UI wired into the plans panel and progress tracker. Relies on the PlanStep doc_id/doc_action columns from the schema commit.
Adds GET /morning (returns today's digest, generating it in the background via morning_digest_service if absent) plus GET/PUT /config for the per-user schedule, backed by new morning_digest_enabled/time/delivery settings (delivery method opt-in, defaults to in-session).
Documents the Photoshop-class editor gaps, the documentary compiler reworked as an episode Plan (shot = step) on Odysseus's existing substrate, and the NLE as an editable timeline-of-data, under the zero-cost local-rendering policy. Framed as subsections of Odysseus, not a standalone project.
Extends the existing keep-agent-memory-out policy (165ced3) to the .agents/ design/task scratch so it can never be staged.
multiModel/* had zero inbound references, so its code never loaded. Import it into app.js and expose it on window (mirroring compare/researchPanel) so the module graph boots, and precache multiModel/index.js with a CACHE_NAME bump (v348 -> v349). docStepBuilder needs no precache since its importer plans-panel isn't precached. The tour-core cache test now asserts a minimum version (>= 348) instead of pinning v348, so a legitimate future bump passes. Note: this makes the modules loadable; a user-facing launch trigger (compare-style mode + opening is_multi_model sessions) is still pending.
|
The following required sections are missing or incomplete. Please update the PR description to address them:
This comment is deleted automatically once all sections are complete. |
Codex/public feature merge
onemorethan0
pushed a commit
to onemorethan0/odysseus
that referenced
this pull request
Nov 9, 2026
…ules refactor(settings): move the shell out of settings.js into settings/
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.
Summary
Target branch
dev, notmain. All PRs land indev;mainis curated by the maintainer at each release. If your PR is onmainby accident, click "Edit" on this PR and change the base.Linked Issue
Fixes #
Type of Change
Checklist
devdocker compose uporuvicorn app:app) and verified the change works end-to-end. Type-checks and unit tests are not enough.How to Test
Visual / UI changes — REQUIRED if you touched anything that renders
Anything that changes what the UI looks like — buttons, icons, padding, colors, fonts, spacing, layout, CSS, HTML, SVG, or any
static/js/module that draws to the DOM — needs all of the following. PRs that change rendering without these WILL be closed.--red,--fg,--bg,--card,--border, etc.) — do not introduce new color values, font sizes, or spacing units.static/index.html) or plain text.Fira Code) for primary UI text. Don't override.Screenshots / clips