mirror of
https://github.com/pewdiepie-archdaemon/odysseus.git
synced 2026-06-16 01:35:36 -04:00
4f7061fd61
Two months of iteration on the Settings panel, integration forms, and small visual nudges across the app. Highlights: Settings restructure - Add Models: split into separate Local + API cards (no more in-card tabs); each fuses Type/Provider with the URL input. - Added Models: new dedicated sidebar tab, with Probe + Clear-offline pulled into its header; Local/API sub-section icons accent-tinted. - Search: Web Search and a new Deep Research card (Model + tuning), with a cross-link to AI Defaults. Provider hints use real clickable anchors; Web Search Test button shows a whirlpool spinner. - AI Defaults: Image Generation card returns; Research Model card carries only Endpoint+Model with a cross-link to Search; Vision / Default / Utility fallbacks unified under one numbered-row design matching Search's chain. - API Permissions (was 'API Tokens'): per-row rename, inline Permissions toggle that expands the scope-edit panel, in-field copy icons (icon→check on success). Empty state accent-tinted. - Integrations: + Add Integration drops a type-picker menu directly under the button (drop-up on tight viewports); each integration form (API, CalDAV, CardDAV, Email, Codex/Claude, Vault, MCP) uses the same accent-outlined Save/Test/Cancel buttons right-aligned. - Danger Zone: Wipe→Delete with trash icons; new 'Delete everything' row at the bottom that loops every category. AI Synthesis (Reminders) - Persona dropdown sourced from PROMPT_TEMPLATES + custom preset. - src/reminder_personas.py mirrors the five built-ins for the server-side synthesis path. - dispatch_reminder() reads reminder_llm_persona and uses the persona's system prompt; empty/unknown falls back to warm-neutral. Esc handling - Kebab menus and the provider picker intercept Esc in capture phase so dismissing a popup no longer closes the whole Settings modal. Accent tinting - Scoped CSS rule across data-settings-panel=ai/services/added-models/ search/integrations/reminders for card h2 icons + the Added Models sub-section icons. Codex/Claude integration form - No more auto-creation on form open — explicit Create token button. - New tokens start with every scope granted; existing tokens move out of the integration form into the API Permissions card. - Setup reveal: copy buttons inline inside the token + setup code blocks; shorter subtitle wording. Misc visual polish - Save/Test/Cancel uniformly accent-outlined and right-aligned on every integration form. - Provider logos render inline next to the search fallback selects and the Deep Research Search dropdown. - Trash icons in fallback rows bumped to 20x20 so they fill the 32px button. - Image generation default flipped to off.
74 lines
2.1 KiB
Python
74 lines
2.1 KiB
Python
"""Auto-create a Document row from an Office attachment.
|
|
|
|
When a .docx (and friends) lands in chat, the full extracted text is stored
|
|
as a Document so the agent can page through it with `manage_documents
|
|
action=read offset=…` even after the inline chat payload was capped. Mirrors
|
|
the PDF auto-doc pattern in `src.pdf_form_doc`.
|
|
"""
|
|
|
|
import logging
|
|
import uuid
|
|
from typing import Optional
|
|
|
|
logger = logging.getLogger(__name__)
|
|
|
|
|
|
def create_office_document(
|
|
session_id: str,
|
|
upload_id: str,
|
|
title: str,
|
|
body_text: Optional[str] = None,
|
|
) -> Optional[str]:
|
|
"""Create a markdown Document for an Office attachment and set it active.
|
|
|
|
Returns the new doc_id, or None on failure / empty body. The full
|
|
extracted body lives in `current_content`, so the agent can fetch
|
|
arbitrary windows via `manage_documents action=read` even when the
|
|
inline chat copy was truncated.
|
|
"""
|
|
from src.database import (
|
|
SessionLocal,
|
|
Document,
|
|
DocumentVersion,
|
|
Session as DbSession,
|
|
)
|
|
from src.tool_implementations import set_active_document
|
|
|
|
if not body_text or not body_text.strip():
|
|
return None
|
|
|
|
db = SessionLocal()
|
|
try:
|
|
doc_id = str(uuid.uuid4())
|
|
ver_id = str(uuid.uuid4())
|
|
sess = db.query(DbSession).filter(DbSession.id == session_id).first()
|
|
doc = Document(
|
|
id=doc_id,
|
|
session_id=session_id,
|
|
title=title,
|
|
language="markdown",
|
|
current_content=body_text,
|
|
version_count=1,
|
|
is_active=True,
|
|
owner=sess.owner if sess else None,
|
|
)
|
|
ver = DocumentVersion(
|
|
id=ver_id,
|
|
document_id=doc_id,
|
|
version_number=1,
|
|
content=body_text,
|
|
summary="Imported from Office attachment",
|
|
source="upload",
|
|
)
|
|
db.add(doc)
|
|
db.add(ver)
|
|
db.commit()
|
|
set_active_document(doc_id)
|
|
return doc_id
|
|
except Exception as e:
|
|
db.rollback()
|
|
logger.error("Failed to create office document: %s", e)
|
|
return None
|
|
finally:
|
|
db.close()
|