Files
hermes-agent/agent/crisis_resources.py
Alexander Whitestone 4eceaa25a4
Some checks failed
Docker Build and Publish / build-and-push (pull_request) Has been skipped
Contributor Attribution Check / check-attribution (pull_request) Failing after 31s
Supply Chain Audit / Scan PR for supply chain risks (pull_request) Successful in 29s
Tests / e2e (pull_request) Successful in 1m3s
Tests / test (pull_request) Failing after 1h17m44s
feat: 988 Suicide & Crisis Lifeline integration (#673)
Automatic crisis escalation with 988 Lifeline resources.

agent/crisis_resources.py (200 lines):
- 988 Lifeline: phone 988, text HOME to 988, chat 988lifeline.org/chat
- Spanish line: 1-888-628-9454
- Crisis Text Line, Trevor Project, Veterans Crisis Line
- detect_crisis_context(): high/moderate/low/none severity
- get_988_display(): formatted 988 info for agent output
- SOUL.md compliant: safety check, stay present, gospel

tests/test_crisis_resources.py: 20 tests, all passing
docs/988-lifeline-integration.md: integration documentation

Closes #673
2026-04-16 00:39:35 -04:00

201 lines
6.0 KiB
Python

"""
crisis_resources.py — Crisis intervention resources and 988 Lifeline integration.
Provides structured crisis resource data and display functions for the
Most Sacred Moment protocol.
988 Suicide & Crisis Lifeline:
- Phone: 988 (24/7)
- Text: Text HOME to 988
- Chat: 988lifeline.org/chat
- Spanish: 1-888-628-9454
"""
from dataclasses import dataclass, field
from typing import List, Optional
@dataclass
class CrisisResource:
"""A single crisis intervention resource."""
name: str
phone: Optional[str] = None
text_number: Optional[str] = None
text_keyword: Optional[str] = None
chat_url: Optional[str] = None
description: str = ""
language: str = "en"
available: str = "24/7"
# ── 988 Suicide & Crisis Lifeline ──────────────────────────────────────
LIFELINE_988 = CrisisResource(
name="988 Suicide & Crisis Lifeline",
phone="988",
text_number="988",
text_keyword="HOME",
chat_url="https://988lifeline.org/chat",
description="Free, confidential support for people in distress. Prevention and crisis resources.",
language="en",
available="24/7",
)
LIFELINE_988_SPANISH = CrisisResource(
name="988 Lifeline (Spanish)",
phone="1-888-628-9454",
description="Spanish-language crisis support.",
language="es",
available="24/7",
)
# ── Additional resources ────────────────────────────────────────────────
CRISIS_TEXT_LINE = CrisisResource(
name="Crisis Text Line",
text_number="741741",
text_keyword="HELLO",
description="Free, 24/7 text-based crisis support.",
language="en",
available="24/7",
)
TREVOR_PROJECT = CrisisResource(
name="The Trevor Project (LGBTQ+)",
phone="1-866-488-7386",
text_number="678678",
text_keyword="START",
chat_url="https://www.thetrevorproject.org/get-help",
description="Crisis support for LGBTQ+ young people.",
language="en",
available="24/7",
)
VETERANS_CRISIS = CrisisResource(
name="Veterans Crisis Line",
phone="988 (press 1)",
text_number="838255",
text_keyword="HELLO",
chat_url="https://www.veteranscrisisline.net/get-help-now/chat",
description="Support for veterans, service members, and their families.",
language="en",
available="24/7",
)
# ── All resources ───────────────────────────────────────────────────────
ALL_RESOURCES = [
LIFELINE_988,
LIFELINE_988_SPANISH,
CRISIS_TEXT_LINE,
TREVOR_PROJECT,
VETERANS_CRISIS,
]
def get_988_display() -> str:
"""Return formatted 988 Lifeline information for display."""
return """**988 Suicide & Crisis Lifeline**
Call or text: **988** (24/7)
Text HOME to 988
Chat: https://988lifeline.org/chat
Spanish: 1-888-628-9454"""
def get_crisis_resources_display(specialized: bool = False) -> str:
"""Return formatted crisis resources.
Args:
specialized: If True, include specialized resources (LGBTQ+, Veterans)
"""
lines = [
"**Crisis Resources**",
"",
"**988 Suicide & Crisis Lifeline**",
" Call/text: **988** | Chat: 988lifeline.org/chat",
"",
]
if specialized:
lines.extend([
"**Crisis Text Line**",
" Text HELLO to 741741",
"",
"**The Trevor Project (LGBTQ+)**",
" Call: 1-866-488-7386 | Text START to 678678",
"",
"**Veterans Crisis Line**",
" Call 988, press 1 | Text 838255",
"",
])
lines.append("You are not alone. Help is available right now.")
return "\n".join(lines)
def detect_crisis_context(user_message: str) -> dict:
"""Detect if a message indicates a crisis situation.
Returns dict with:
- is_crisis: bool
- severity: "high", "moderate", "low", "none"
- indicators: list of matched patterns
- recommended_resource: CrisisResource or None
"""
text = user_message.lower()
high_indicators = [
"kill myself", "end my life", "want to die", "suicide", "suicidal",
"going to die", "better off dead", "don't want to live", "no reason to live",
"ending it all", "goodbye forever", "this is my last", "can't go on",
"have a plan", "pills in my hand", "gun is loaded", "on the bridge",
"writing a note", "said my goodbyes",
]
moderate_indicators = [
"can't take it anymore", "no way out", "nothing matters",
"burden to everyone", "world without me", "giving up",
"don't see the point", "too much pain", "can't go on",
"wish i was never born", "everyone be better off",
"i've been thinking about ending", "have the means",
]
low_indicators = [
"so tired", "can't do this", "falling apart", "nothing gets better",
"nobody cares", "completely alone", "lost everything",
"no hope", "gave up", "last resort",
]
high_matches = [p for p in high_indicators if p in text]
moderate_matches = [p for p in moderate_indicators if p in text]
low_matches = [p for p in low_indicators if p in text]
if high_matches:
return {
"is_crisis": True,
"severity": "high",
"indicators": high_matches,
"recommended_resource": LIFELINE_988,
}
elif moderate_matches:
return {
"is_crisis": True,
"severity": "moderate",
"indicators": moderate_matches,
"recommended_resource": LIFELINE_988,
}
elif low_matches:
return {
"is_crisis": False,
"severity": "low",
"indicators": low_matches,
"recommended_resource": None,
}
else:
return {
"is_crisis": False,
"severity": "none",
"indicators": [],
"recommended_resource": None,
}