mirror of
https://github.com/pewdiepie-archdaemon/odysseus.git
synced 2026-09-13 19:52:20 +02:00
167 lines
6.9 KiB
Python
167 lines
6.9 KiB
Python
from pathlib import Path
|
|
import re
|
|
|
|
|
|
ROOT = Path(__file__).resolve().parents[1]
|
|
|
|
|
|
def test_skill_deeplink_clears_filters_and_retries_scroll():
|
|
src = (ROOT / "static/js/skills.js").read_text()
|
|
|
|
assert "function _resetSkillDeepLinkFilters()" in src
|
|
assert "skills-search" in src
|
|
assert "_showDraftsOnly = false;" in src
|
|
assert "_showPublishedOnly = false;" in src
|
|
assert "_confMax = null;" in src
|
|
assert "_skillsQuickFilter = null;" in src
|
|
assert "attempt < 12" in src
|
|
assert "setTimeout(() => _focusSkillRow(targetName, attempt + 1), 120)" in src
|
|
assert "scrollIntoView({ behavior: 'smooth', block: 'center', inline: 'nearest' })" in src
|
|
assert "if (!card.classList.contains('doclib-card-expanded')) await _expandSkillCard" in src
|
|
assert "decodeURIComponent(String(name || '').replace" in src
|
|
|
|
|
|
def test_ui_control_open_panel_supports_theme_and_settings_module_open():
|
|
stream_src = (ROOT / "static/js/chatStream.js").read_text()
|
|
ai_src = (ROOT / "src/ai_interaction.py").read_text()
|
|
schema_src = (ROOT / "src/tool_schemas.py").read_text()
|
|
index_src = (ROOT / "src/tool_index.py").read_text()
|
|
|
|
assert "panel === 'theme' || panel === 'themes'" in stream_src
|
|
assert "mod.togglePopup" in stream_src
|
|
assert "mod.open || (mod.default && mod.default.open)" in stream_src
|
|
assert '"theme": "theme"' in ai_src
|
|
assert '"themes": "theme"' in ai_src
|
|
assert "settings, theme, cookbook" in schema_src
|
|
assert "settings, theme, cookbook" in index_src
|
|
|
|
|
|
def test_skill_list_summary_persists_clickable_skill_anchors():
|
|
from src.agent_loop import _skills_list_summary_from_tool_output
|
|
|
|
summary = _skills_list_summary_from_tool_output(
|
|
"\n".join(
|
|
[
|
|
"## Published",
|
|
"- **open-a-youtube-creator-s-latest-video** (general): Open a YouTube creator's latest video",
|
|
"## Drafts",
|
|
"- **audit-fixture-20260828-skills-search** [draft]: domain audit fixture",
|
|
]
|
|
)
|
|
)
|
|
|
|
assert "[open-a-youtube-creator-s-latest-video](#skill-open-a-youtube-creator-s-latest-video)" in summary
|
|
assert "[audit-fixture-20260828-skills-search](#skill-audit-fixture-20260828-skills-search)" in summary
|
|
assert "**open-a-youtube-creator-s-latest-video**" not in summary
|
|
|
|
|
|
def test_memory_list_summary_persists_clickable_memory_anchors():
|
|
from src.agent_loop import _memory_list_summary_from_tool_output
|
|
|
|
summary = _memory_list_summary_from_tool_output(
|
|
"\n".join(
|
|
[
|
|
"Found 2 memory entries:",
|
|
"",
|
|
"- [preference] `abc12345` — Use short replies.",
|
|
"- [project] `def67890` — Working on Odysseus SFT traces.",
|
|
]
|
|
)
|
|
)
|
|
|
|
assert "[preference abc12345](#memory-abc12345)" in summary
|
|
assert "[project def67890](#memory-def67890)" in summary
|
|
assert "`abc12345`" not in summary
|
|
|
|
|
|
def test_saved_chat_renderer_routes_memory_and_skill_anchors():
|
|
renderer_src = (ROOT / "static/js/chatRenderer.js").read_text()
|
|
|
|
assert "decodeURIComponent(String(rawId || '').replace" in renderer_src
|
|
assert "kind === 'memory'" in renderer_src
|
|
assert "mod.openMemory" in renderer_src
|
|
assert "import('./memory.js')" in renderer_src
|
|
assert "kind === 'skill'" in renderer_src
|
|
assert "mod.openSkill" in renderer_src
|
|
assert re.search(r"import\('\./skills\.js\?v=[A-Za-z0-9_-]+'\)", renderer_src)
|
|
|
|
|
|
def test_markdown_keeps_encoded_deeplink_hashes_clickable():
|
|
markdown_src = (ROOT / "static/js/markdown.js").read_text()
|
|
|
|
assert r"^#[A-Za-z0-9_.~%:@-]*$" in markdown_src
|
|
|
|
|
|
def test_markdown_flattens_legacy_notes_more_details():
|
|
markdown_src = (ROOT / "static/js/markdown.js").read_text()
|
|
|
|
assert "function flattenLegacyNoteMoreDetails" in markdown_src
|
|
assert "more\\s+notes?" in markdown_src
|
|
assert "let s = extractMoreListPayloads(flattenLegacyNoteMoreDetails(src ?? ''));" in markdown_src
|
|
|
|
|
|
def test_markdown_expands_note_and_skill_more_links_without_details():
|
|
markdown_src = (ROOT / "static/js/markdown.js").read_text()
|
|
style_src = (ROOT / "static/style.css").read_text()
|
|
|
|
assert "function extractMoreListPayloads" in markdown_src
|
|
assert "ody-more-(notes|skills|memories|events|sessions)" in markdown_src
|
|
assert "a.chat-link[href^=\"#notes-more-\"]" in style_src
|
|
assert "a.chat-link[href^=\"#skills-more-\"]" in style_src
|
|
assert "a.chat-link[href^=\"#memories-more-\"]" in style_src
|
|
assert "a.chat-link[href^=\"#events-more-\"]" in style_src
|
|
assert "a.chat-link[href^=\"#sessions-more-\"]" in style_src
|
|
assert "more-list-expanded" in markdown_src
|
|
assert "more-list-expanded" in style_src
|
|
assert "insertionPoint.insertAdjacentElement('beforebegin', expanded)" in markdown_src
|
|
assert "parent.insertAdjacentElement('afterend', expanded)" not in markdown_src
|
|
|
|
|
|
def test_terminal_skill_listing_uses_clickable_bounded_formatter():
|
|
agent_src = (ROOT / "src/agent_loop.py").read_text()
|
|
style_src = (ROOT / "static/style.css").read_text()
|
|
|
|
assert "_qwen_skills_terminal_summary = _skills_list_summary_from_tool_output(" in agent_src
|
|
assert '.msg-ai .body a[href^="#skill-"]' in style_src
|
|
assert '.msg-ai .body a[href^="#memory-"]' in style_src
|
|
|
|
|
|
def test_list_links_share_compact_typography():
|
|
style_src = (ROOT / "static/style.css").read_text()
|
|
|
|
assert 'a.chat-link[href^="#events-more-"]' in style_src
|
|
assert "font-size: 11px;" in style_src
|
|
assert '.msg-ai .body a[href^="#note-"]' in style_src
|
|
assert '.msg-ai .body a[href^="#session-"]:hover' in style_src
|
|
assert 'p:has(> .emoji:first-child):has(> a.chat-link[href^="#note-"])' in style_src
|
|
|
|
|
|
def test_open_skills_also_persists_skill_list():
|
|
agent_src = (ROOT / "src/agent_loop.py").read_text()
|
|
|
|
assert 're.search(r"\\bopen_panel\\s+skills\\b"' in agent_src
|
|
assert 'tool_blocks.append(ToolBlock("manage_skills", json.dumps({"action": "list"})))' in agent_src
|
|
|
|
|
|
def test_memory_deeplink_scrolls_and_flashes_even_when_filtered():
|
|
memory_src = (ROOT / "static/js/memory.js").read_text()
|
|
style_src = (ROOT / "static/style.css").read_text()
|
|
|
|
assert "function _resetMemoryDeepLinkFilters()" in memory_src
|
|
assert "activeCategory = 'all';" in memory_src
|
|
assert "memory-search" in memory_src
|
|
assert "attempt < 12" in memory_src
|
|
assert "setTimeout(() => openMemory(wanted, attempt + 1), 120)" in memory_src
|
|
assert "scrollIntoView({ behavior: 'smooth', block: 'center', inline: 'nearest' })" in memory_src
|
|
assert "memory-item-focus" in style_src
|
|
assert "animation: anchor-item-flash 2.2s ease-out" in style_src
|
|
|
|
|
|
def test_skill_and_memory_links_use_polished_chat_link_style():
|
|
style_src = (ROOT / "static/style.css").read_text()
|
|
|
|
assert '.msg-ai .body a[href^="#skill-"]' in style_src
|
|
assert '.msg-ai .body a[href^="#memory-"]' in style_src
|
|
assert '.msg-ai .body a[href^="#skill-"]:hover' in style_src
|
|
assert '.msg-ai .body a[href^="#memory-"]:hover' in style_src
|