diff --git a/app/Home.py b/app/Home.py
index d06c405..7b23d94 100644
--- a/app/Home.py
+++ b/app/Home.py
@@ -69,7 +69,7 @@ _SETUP_BANNERS = [
{"key": "upload_corpus", "text": "Upload your cover letter corpus for voice fine-tuning",
"link_label": "Settings ā Fine-Tune"},
{"key": "configure_linkedin", "text": "Configure LinkedIn Easy Apply automation",
- "link_label": "Settings ā AIHawk"},
+ "link_label": "Settings ā Integrations"},
{"key": "setup_searxng", "text": "Set up company research with SearXNG",
"link_label": "Settings ā Services"},
{"key": "target_companies", "text": "Build a target company list for focused outreach",
diff --git a/app/app.py b/app/app.py
index d6f17a3..b1bf71a 100644
--- a/app/app.py
+++ b/app/app.py
@@ -22,11 +22,11 @@ IS_DEMO = os.environ.get("DEMO_MODE", "").lower() in ("1", "true", "yes")
import streamlit as st
from scripts.db import DEFAULT_DB, init_db, get_active_tasks
from app.feedback import inject_feedback_button
-from app.cloud_session import resolve_session, get_db_path
+from app.cloud_session import resolve_session, get_db_path, get_config_dir
import sqlite3
st.set_page_config(
- page_title="Job Seeker",
+ page_title="Peregrine",
page_icon="š¼",
layout="wide",
)
@@ -80,7 +80,7 @@ except Exception:
# āā First-run wizard gate āāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāā
from scripts.user_profile import UserProfile as _UserProfile
-_USER_YAML = Path(__file__).parent.parent / "config" / "user.yaml"
+_USER_YAML = get_config_dir() / "user.yaml"
_show_wizard = not IS_DEMO and (
not _UserProfile.exists(_USER_YAML)
diff --git a/app/cloud_session.py b/app/cloud_session.py
index a88631e..9db96cd 100644
--- a/app/cloud_session.py
+++ b/app/cloud_session.py
@@ -112,13 +112,19 @@ def resolve_session(app: str = "peregrine") -> None:
cookie_header = st.context.headers.get("x-cf-session", "")
session_jwt = _extract_session_token(cookie_header)
if not session_jwt:
- st.error("Session token missing. Please log in at circuitforge.tech.")
+ st.components.v1.html(
+ '',
+ height=0,
+ )
st.stop()
try:
user_id = validate_session_jwt(session_jwt)
- except Exception as exc:
- st.error(f"Invalid session ā please log in again. ({exc})")
+ except Exception:
+ st.components.v1.html(
+ '',
+ height=0,
+ )
st.stop()
user_path = _user_data_path(user_id, app)
@@ -141,6 +147,19 @@ def get_db_path() -> Path:
return st.session_state.get("db_path", DEFAULT_DB)
+def get_config_dir() -> Path:
+ """
+ Return the config directory for this session.
+ Cloud: per-user path (//peregrine/config/) so each
+ user's YAML files (user.yaml, plain_text_resume.yaml, etc.) are
+ isolated and never shared across tenants.
+ Local: repo-level config/ directory.
+ """
+ if CLOUD_MODE and st.session_state.get("db_path"):
+ return Path(st.session_state["db_path"]).parent / "config"
+ return Path(__file__).parent.parent.parent / "config"
+
+
def get_cloud_tier() -> str:
"""
Return the current user's cloud tier.
diff --git a/app/pages/4_Apply.py b/app/pages/4_Apply.py
index dd3c5b5..1e9a3d1 100644
--- a/app/pages/4_Apply.py
+++ b/app/pages/4_Apply.py
@@ -389,7 +389,7 @@ with col_tools:
st.markdown("---")
else:
- st.warning("Resume YAML not found ā check that AIHawk is cloned.")
+ st.warning("Resume profile not found ā complete setup or upload a resume in Settings ā Resume Profile.")
# āā Application Q&A āāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāā
with st.expander("š¬ Answer Application Questions"):
diff --git a/scripts/migrate.py b/scripts/migrate.py
index 67cfad8..edf97cf 100644
--- a/scripts/migrate.py
+++ b/scripts/migrate.py
@@ -83,10 +83,10 @@ def _extract_career_summary(source: Path) -> str:
def _extract_personal_info(source: Path) -> dict:
- """Extract personal info from aihawk resume yaml."""
+ """Extract personal info from resume yaml."""
resume = source / "config" / "plain_text_resume.yaml"
if not resume.exists():
- resume = source / "aihawk" / "data_folder" / "plain_text_resume.yaml"
+ resume = source / "aihawk" / "data_folder" / "plain_text_resume.yaml" # legacy path
if not resume.exists():
return {}
data = _load_yaml(resume)
@@ -196,7 +196,7 @@ def _copy_configs(source: Path, dest: Path, apply: bool) -> None:
def _copy_aihawk_resume(source: Path, dest: Path, apply: bool) -> None:
- print("\nāā Copying AIHawk resume profile")
+ print("\nāā Copying resume profile")
src = source / "config" / "plain_text_resume.yaml"
if not src.exists():
src = source / "aihawk" / "data_folder" / "plain_text_resume.yaml"