Settings overhaul + UI polish pass
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.
2026-06-10 15:15:13 +09:00
|
|
|
"""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,
|
|
|
|
|
)
|
2026-06-15 21:20:15 +09:00
|
|
|
from src.agent_tools.document_tools import set_active_document
|
Settings overhaul + UI polish pass
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.
2026-06-10 15:15:13 +09:00
|
|
|
|
|
|
|
|
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()
|