mirror of
https://github.com/openswarm-ai/openswarm.git
synced 2026-08-17 18:25:42 +02:00
188 lines
6.8 KiB
Python
188 lines
6.8 KiB
Python
"""Assembles what the in-app help chat knows: shipped product facts plus live facts about THIS
|
|
install (version, platform, the user's actual shortcuts, whether a model is even connected).
|
|
|
|
Shipped facts can't drift from the build. Live facts are the part a shipped file can never get
|
|
right, and they are exactly where a hardcoded help prompt goes stale first.
|
|
|
|
The result is handed to the chat as its system prompt, which lands in the provider's cached
|
|
prefix (see RunOptions), so the knowledge is paid for once per session rather than per turn.
|
|
"""
|
|
|
|
import platform
|
|
from typing import List, Optional
|
|
|
|
from pydantic import BaseModel, ConfigDict
|
|
from typeguard import typechecked
|
|
|
|
from backend.apps.help.help_topics import HELP_TOPICS, HelpTopic
|
|
from backend.apps.help.known_issues import KNOWN_ISSUES, HelpKnownIssue
|
|
from backend.apps.help.prompt_rules import GROUNDING_RULES, ROLE
|
|
|
|
IS_MAC = platform.system() == "Darwin"
|
|
|
|
# Off mac these handlers fire on Ctrl (the code reads metaKey||ctrlKey), so "Meta" must READ as Ctrl.
|
|
P_MAC_GLYPH = {"meta": "⌘", "ctrl": "⌃", "alt": "⌥", "shift": "⇧"}
|
|
P_OTHER_NAME = {"meta": "Ctrl", "ctrl": "Ctrl", "alt": "Alt", "shift": "Shift"}
|
|
|
|
# Same "Meta+l" parts format the settings fields use, so one renderer covers stock and configured alike.
|
|
P_FIXED_SHORTCUTS: List[tuple] = [
|
|
("Meta+k", "Search everything, across all dashboards"),
|
|
("Meta+f", "Find cards on this canvas; inside a browser card it finds text on the page"),
|
|
("Meta+Shift+t", "Reopen the card you just closed"),
|
|
("Meta+a", "Select every card"),
|
|
("Meta+c", "Copy the selected cards"),
|
|
("Meta+v", "Paste the copied cards"),
|
|
("Delete", "Delete the selected cards"),
|
|
("Enter", "Expand or collapse the selected chat"),
|
|
("Meta+Alt+Left", "Previous dashboard"),
|
|
("Meta+Alt+Right", "Next dashboard"),
|
|
("Meta+=", "Zoom in; inside a browser card it zooms the page"),
|
|
("Meta+-", "Zoom out; inside a browser card it zooms the page"),
|
|
("Meta+0", "Reset zoom"),
|
|
("Ctrl+Tab", "Next tab in the focused browser card"),
|
|
("Space", "Hold and drag to pan the canvas"),
|
|
("Arrows", "Move between cards"),
|
|
("Escape", "Close the open panel or menu"),
|
|
]
|
|
|
|
|
|
class HelpShortcut(BaseModel):
|
|
model_config = ConfigDict(validate_assignment=True)
|
|
|
|
keys: str
|
|
action: str
|
|
|
|
|
|
class HelpKnowledgeResponse(BaseModel):
|
|
model_config = ConfigDict(validate_assignment=True)
|
|
|
|
system_prompt: str
|
|
topics: List[HelpTopic]
|
|
known_issues: List[HelpKnownIssue]
|
|
shortcuts: List[HelpShortcut]
|
|
app_version: str
|
|
|
|
|
|
@typechecked
|
|
def render_combo(combo: str) -> str:
|
|
"""'Meta+Shift+d' -> '⇧⌘D' on mac, 'Ctrl+Shift+D' elsewhere."""
|
|
parts = [p for p in combo.split("+") if p]
|
|
out: List[str] = []
|
|
for part in parts:
|
|
low = part.lower()
|
|
if IS_MAC:
|
|
out.append(P_MAC_GLYPH.get(low, part.upper() if len(part) == 1 else part))
|
|
else:
|
|
out.append(P_OTHER_NAME.get(low, part.upper() if len(part) == 1 else part))
|
|
return ("" if IS_MAC else "+").join(out)
|
|
|
|
|
|
@typechecked
|
|
def dictation_default_combo() -> str:
|
|
return "Meta+Shift+d" if IS_MAC else "Ctrl+Shift+d"
|
|
|
|
|
|
@typechecked
|
|
def build_shortcuts(new_agent_combo: str, dictation_combo: Optional[str]) -> List[HelpShortcut]:
|
|
live = [
|
|
HelpShortcut(keys=render_combo(new_agent_combo or "Meta+l"), action="Open the new-chat composer"),
|
|
HelpShortcut(keys=render_combo(dictation_combo or dictation_default_combo()), action="Start or stop voice dictation"),
|
|
]
|
|
return live + [HelpShortcut(keys=render_combo(c), action=a) for c, a in P_FIXED_SHORTCUTS]
|
|
|
|
|
|
@typechecked
|
|
def p_provider_state() -> str:
|
|
"""One honest line about whether this install can actually run a model."""
|
|
from backend.apps.settings.store import load_settings
|
|
|
|
s = load_settings()
|
|
mode = getattr(s, "connection_mode", "own_key")
|
|
if mode == "free-trial":
|
|
return "on the free trial (a shared capacity pool)"
|
|
if mode == "openswarm-pro":
|
|
return "on an OpenSwarm paid plan"
|
|
keyed = any(
|
|
getattr(s, f, None)
|
|
for f in ("anthropic_api_key", "openai_api_key", "google_api_key", "openrouter_api_key")
|
|
)
|
|
subbed = any(
|
|
getattr(s, f, None)
|
|
for f in ("claude_subscription_token", "openai_subscription_token", "gemini_subscription_token")
|
|
)
|
|
if subbed:
|
|
return "on a connected provider subscription"
|
|
if keyed:
|
|
return "on their own API key"
|
|
return "with NO model connected yet, so most agent work will fail until they connect one in Settings > Models"
|
|
|
|
|
|
@typechecked
|
|
def p_topics_block() -> str:
|
|
lines: List[str] = []
|
|
for t in HELP_TOPICS:
|
|
where = f" WHERE: {t.where}" if t.where else ""
|
|
lines.append(f"- [{t.id}] {t.title}.{where} {t.body}")
|
|
return "\n".join(lines)
|
|
|
|
|
|
@typechecked
|
|
def p_issues_block() -> str:
|
|
lines: List[str] = []
|
|
for i in KNOWN_ISSUES:
|
|
fix = f" Workaround: {i.workaround}" if i.workaround else ""
|
|
lines.append(f"- [{i.id}] ({i.status}) {i.title}. {i.detail}{fix}")
|
|
return "\n".join(lines)
|
|
|
|
|
|
@typechecked
|
|
def build_system_prompt(shortcuts: List[HelpShortcut], app_version: str) -> str:
|
|
shortcut_lines = "\n".join(f"- {s.keys}: {s.action}" for s in shortcuts)
|
|
os_name = "macOS" if IS_MAC else platform.system()
|
|
return "\n".join(
|
|
[
|
|
ROLE,
|
|
"",
|
|
"<this_install>",
|
|
f"OpenSwarm version {app_version} on {os_name}. This user is {p_provider_state()}.",
|
|
"These are live facts about the machine you are talking to; trust them over anything you recall.",
|
|
"</this_install>",
|
|
"",
|
|
"<surfaces>",
|
|
"Verified against this exact build. This is your ground truth for where things are.",
|
|
p_topics_block(),
|
|
"</surfaces>",
|
|
"",
|
|
"<shortcuts>",
|
|
"This user's real shortcuts, already written for their platform. Quote them exactly.",
|
|
shortcut_lines,
|
|
"</shortcuts>",
|
|
"",
|
|
"<known_issues>",
|
|
"The complete list of issues shipped with this build. You cannot see live bug reports.",
|
|
p_issues_block(),
|
|
"</known_issues>",
|
|
"",
|
|
GROUNDING_RULES,
|
|
]
|
|
)
|
|
|
|
|
|
@typechecked
|
|
def build_knowledge_response() -> HelpKnowledgeResponse:
|
|
from backend.apps.service.version import APP_VERSION
|
|
from backend.apps.settings.store import load_settings
|
|
|
|
s = load_settings()
|
|
shortcuts = build_shortcuts(
|
|
getattr(s, "new_agent_shortcut", "Meta+l") or "Meta+l",
|
|
getattr(s, "dictation_shortcut", None),
|
|
)
|
|
return HelpKnowledgeResponse(
|
|
system_prompt=build_system_prompt(shortcuts, APP_VERSION),
|
|
topics=HELP_TOPICS,
|
|
known_issues=KNOWN_ISSUES,
|
|
shortcuts=shortcuts,
|
|
app_version=APP_VERSION,
|
|
)
|