mirror of
https://github.com/openswarm-ai/openswarm.git
synced 2026-09-24 02:24:52 +02:00
[eric] onboarding: sharpen the scan-driven reveal (surface telling apps, insight-led greeting)
This commit is contained in:
@@ -21,6 +21,18 @@ SCAN_FOLDERS = ("Downloads", "Desktop", "Documents")
|
||||
REPO_PARENT_CANDIDATES = ("dev", "code", "projects", "src", "repos", "Documents/GitHub")
|
||||
SCREENSHOT_PREFIXES = ("screenshot", "screen shot", "screen recording")
|
||||
|
||||
# The high-signal tools that actually tell prep who this person is (an IDE, a design app, a DAW) so the greeting can lead with a confident read instead of drowning in Calculator + System Settings. Matched by exact name or "name " prefix so "Arc" never trips on "Search".
|
||||
NOTABLE_APP_KEYWORDS = (
|
||||
"xcode", "visual studio code", "cursor", "zed", "sublime text", "intellij idea",
|
||||
"pycharm", "webstorm", "android studio", "docker", "orbstack", "postman", "iterm",
|
||||
"warp", "ghostty", "tableplus", "github desktop", "figma", "sketch",
|
||||
"adobe photoshop", "adobe illustrator", "adobe xd", "affinity", "framer", "blender",
|
||||
"cinema 4d", "final cut pro", "davinci resolve", "adobe premiere pro",
|
||||
"adobe after effects", "screenflow", "capcut", "obs", "logic pro", "ableton live",
|
||||
"fl studio", "garageband", "unity", "unreal engine", "godot", "notion", "obsidian",
|
||||
"ulysses", "scrivener", "craft", "linear", "tableau", "rstudio", "ollama", "lm studio", "arc",
|
||||
)
|
||||
|
||||
|
||||
@typechecked
|
||||
def p_list_apps() -> List[str]:
|
||||
@@ -66,6 +78,16 @@ def p_summarize_folder(folder: Path) -> FolderSummary:
|
||||
return summary
|
||||
|
||||
|
||||
@typechecked
|
||||
def detect_signal_apps(apps: List[str]) -> List[str]:
|
||||
out: List[str] = []
|
||||
for name in apps:
|
||||
low = name.lower()
|
||||
if any(low == kw or low.startswith(kw + " ") for kw in NOTABLE_APP_KEYWORDS):
|
||||
out.append(name)
|
||||
return out[:20]
|
||||
|
||||
|
||||
@typechecked
|
||||
def p_count_git_repos(home: Path) -> int:
|
||||
count = 0
|
||||
@@ -90,8 +112,10 @@ def p_count_git_repos(home: Path) -> int:
|
||||
@typechecked
|
||||
def run_local_scan(home: Path) -> ScanResult:
|
||||
folders = [p_summarize_folder(home / name) for name in SCAN_FOLDERS]
|
||||
apps = p_list_apps()
|
||||
return ScanResult(
|
||||
apps=p_list_apps(),
|
||||
apps=apps,
|
||||
signal_apps=detect_signal_apps(apps),
|
||||
folders=folders,
|
||||
git_repo_count=p_count_git_repos(home),
|
||||
has_gitconfig=(home / ".gitconfig").is_file(),
|
||||
|
||||
@@ -35,6 +35,8 @@ class ScanResult(BaseModel):
|
||||
model_config = ConfigDict(validate_assignment=True)
|
||||
|
||||
apps: List[str] = Field(default_factory=list)
|
||||
# The high-signal subset of apps (IDEs, design/creative tools); the profile leans on these.
|
||||
signal_apps: List[str] = Field(default_factory=list)
|
||||
folders: List[FolderSummary] = Field(default_factory=list)
|
||||
git_repo_count: int = 0
|
||||
has_gitconfig: bool = False
|
||||
|
||||
@@ -28,9 +28,11 @@ P_SYSTEM = (
|
||||
"organize local files, browse the web in a real browser, build small apps, and run agents in parallel. "
|
||||
"Given facts about the user's machine and the apps they picked, respond with STRICT JSON only: "
|
||||
'{"greeting": string, "starters": [{"title": string, "prompt": string, "reason": string}], "app_title": string, "app_prompt": string, "app_reason": string, "automations": [{"title": string, "prompt": string, "cadence": "daily"|"weekday"|"weekly"}]}. '
|
||||
"First, silently infer a short profile of this user. If usage_summary is present it is the STRONGEST signal (it is "
|
||||
"what they actually ask their AI about and facts their AI remembers about them); weight it above everything else, "
|
||||
"then apps, folders, plan tier, email domain. Tune every task and the personal app to that profile; do not output the profile. "
|
||||
"First, silently infer a short, confident profile of this user: who they are and what they are working on. "
|
||||
"If usage_summary is present it is the STRONGEST signal (it is what they actually ask their AI about and facts "
|
||||
"their AI remembers about them); weight it above everything else, then signal_apps (the high-signal tools they "
|
||||
"have installed, like an IDE, a design app, or a DAW: these reveal their craft), then folders, plan tier, email "
|
||||
"domain. Tune every task and the personal app to that profile; do not output the profile. "
|
||||
"Exactly 4 starters. Each title is 2-5 words. Each prompt is a concrete, safe, immediately runnable task "
|
||||
"referencing the user's real folders, file counts, or picked apps when possible; never invent facts, never "
|
||||
"propose deleting anything without review. The FIRST starter must be an audit sized for parallel sub-work "
|
||||
@@ -49,8 +51,10 @@ P_SYSTEM = (
|
||||
"profile and habits (for example a daily morning brief, a weekly folder cleanup, a weekday summary of their "
|
||||
"connected apps). Each automation title is 2-4 words, prompt is one runnable instruction, cadence is exactly "
|
||||
"'daily', 'weekday', or 'weekly'. Automations must be safe to run unattended (never delete without review). "
|
||||
"The greeting is one warm sentence that names 2-3 specific things "
|
||||
"found on the machine. Never use em-dashes or en-dashes anywhere. No markdown, no commentary, JSON only."
|
||||
"The greeting is one or two warm sentences: first say out loud, specifically and confidently, what this person is "
|
||||
"into or working on (grounded in usage_summary, signal_apps, and folders, for example 'Looks like you live in "
|
||||
"Xcode and ship iOS apps'), then name 2-3 concrete things you actually saw. Be specific, never generic, and never "
|
||||
"name boring system apps. Never use em-dashes or en-dashes anywhere. No markdown, no commentary, JSON only."
|
||||
)
|
||||
|
||||
|
||||
|
||||
Reference in New Issue
Block a user