Files
hermes-agent/tui_gateway/onboarding_personalization.py
Siddharth Balyan cbe9e5b294 chore(desktop): literal comments across the onboarding flow (#108438)
* chore(desktop): literal comments in the guide script and runbooks

Comment-only change to onboarding-script.ts and setup-profile.ts. The module
headers now state the purpose and the constraints that shaped each file. The
notes beside the runbook strings keep one fact per sentence, or are deleted
when the string beside them says the same thing. The runbook text, the
persona, the option pills and the SOUL text are unchanged.

Both versions transpile to identical output with comments removed.

* chore(desktop): literal comments in the guide chat cards and stores

Comment-only change to the guided chat's cards, directive dispatcher, option
catalog, assembly module and chip. Metaphor and personification are replaced
by the name of the atom, effect or CSS property they stood for. Comments that
restate the code are deleted. Two stale facts are corrected in place: the
mini layout trees point at app/contrib/layout-presets.ts, and the skip button
sets the onboarding phase to skipped rather than done.

One comment line in cards/frame.tsx from bb/connector-ui-e2e-v2 loses a
metaphor and an em dash; its fact is unchanged.

* chore(desktop): literal comments in the handoff and first build

Comment-only change to the handoff wiring, the kickoff, the receipt store,
the first-build check-ins, the handoff tour, the connector rows and the
machine profile store. Every kept comment names the caller, the constraint or
the defect it prevents. The claim that the tour never throws is removed: the
function can reject and its caller does not catch.

Five comment blocks in connector-tool.tsx written on bb/connector-ui-e2e-v2
lose personification, dramatic capitals and em dashes. Every fact in them
stays, and no block moves.

* chore(desktop): literal comments in the intro reveal

Comment-only change to the intro reveal's clock, timeline, cube renderer,
sound, scenes, store and README. Animation comments now name the actual
ramp, easing or offset with its number. Four comments that contradicted the
code are corrected: the first texture slot opens at 3700 ms, the tear settles
from 1 to 0 over 460 ms, the typing weight delays the character it sits on,
and INTRO_EXIT_MS is wall time in index.tsx but score time in the overlay.

* chore(desktop): literal comments in the Electron onboarding windows

Comment-only change to the window growth geometry and the two onboarding
windows. The 768 px floor keeps its one fact: the floor uses Math.ceil where
the deltas round, because rounding 906.24 DIP down leaves the media query
false. The comment that placed the CSS-pixel to DIP conversion at getBounds
now points at growWindowBounds, where it happens.

* chore(gateway): literal docstrings in the onboarding RPCs and the tour tool

Docstring and comment-only change. The module summaries state what each
module does and where authorization comes from, without contrast pairs. The
tool descriptions the model reads are unchanged. Two words in the tour tool's
module docstring lose personification; the rest of that docstring is as it
was.

ast.dump of both versions, with docstrings stripped, is identical for all
three files.

* chore(desktop): literal punctuation in the relaunch and film-end notes

Comment-only change to four lines that bb/connector-ui-e2e-v2 added to the
boot gate, the gate store and the intro gate. Each em dash becomes a colon, a
full stop or a pair of parentheses; one emphasis capital is lowercased. The
facts in the notes are unchanged.
2026-09-12 10:00:08 +05:30

45 lines
2.4 KiB
Python

"""Writes the setup facts agreed during onboarding into the default profile's user memory."""
import json
from hermes_constants import reset_hermes_home_override, set_hermes_home_override
from hermes_cli.profiles import get_profile_dir
from tools.memory_tool import load_on_disk_store, memory_tool
def remember_onboarding(answers: dict) -> dict:
if not isinstance(answers, dict):
raise ValueError('Onboarding answers must be an object')
facts = []
for key, label in (('name', 'User prefers to be called'), ('context', 'Working on'),
('theme', 'Desktop theme'), ('accent', 'Desktop accent'), ('layout', 'Desktop layout')):
value = answers.get(key)
if value is not None and not isinstance(value, str):
raise ValueError(f'{key} must be text')
if value and value.strip():
facts.append(f'{label}: {value.strip()}')
for key, label in (('focus', 'Focus areas'), ('connectors', 'Tools the user uses (not connection status)')):
values = answers.get(key, [])
if not isinstance(values, list) or not all(isinstance(value, str) for value in values):
raise ValueError(f'{key} must be a list of text')
if values := list(dict.fromkeys(value.strip() for value in values if value.strip())):
facts.append(f'{label}: {", ".join(values)}')
if not facts:
return {'saved': True, 'profile': 'default', 'target': 'user'}
content = 'Agreed during onboarding:\n' + '\n'.join(facts)
if len(content) > 2000:
raise ValueError('Onboarding facts are too long to remember')
# The entry must land in the 'default' profile directory even when this RPC arrives on the guide's
# backend or under a custom Hermes home.
token = set_hermes_home_override(get_profile_dir('default'))
try:
result = json.loads(memory_tool(action='add', target='user', content=content, store=load_on_disk_store()))
if not result.get('success') or result.get('staged'):
raise ValueError(result.get('error') or result.get('message') or 'Memory was not saved')
# memory_tool can report success without the entry reaching disk, so read it back from a fresh store.
if content not in load_on_disk_store().user_entries:
raise ValueError('Could not verify saved onboarding facts')
return {'saved': True, 'profile': 'default', 'target': 'user'}
finally:
reset_hermes_home_override(token)