Skip to content

Feat/desktop goal status bar conversation mode - #48285

Closed
HaisamAbbas wants to merge 5 commits into
NousResearch:mainfrom
HaisamAbbas:feat/desktop-goal-status-bar-conversation-mode
Closed

Feat/desktop goal status bar conversation mode#48285
HaisamAbbas wants to merge 5 commits into
NousResearch:mainfrom
HaisamAbbas:feat/desktop-goal-status-bar-conversation-mode

Conversation

@HaisamAbbas

Copy link
Copy Markdown

What does this PR do?

Related Issue

Fixes #

Type of Change

  • 🐛 Bug fix (non-breaking change that fixes an issue)
  • ✨ New feature (non-breaking change that adds functionality)
  • 🔒 Security fix
  • 📝 Documentation update
  • ✅ Tests (adding or improving test coverage)
  • ♻️ Refactor (no behavior change)
  • 🎯 New skill (bundled or hub)

Changes Made

How to Test

Checklist

Code

  • I've read the Contributing Guide
  • My commit messages follow Conventional Commits (fix(scope):, feat(scope):, etc.)
  • I searched for existing PRs to make sure this isn't a duplicate
  • My PR contains only changes related to this fix/feature (no unrelated commits)
  • I've run pytest tests/ -q and all tests pass
  • I've added tests for my changes (required for bug fixes, strongly encouraged for features)
  • I've tested on my platform:

Documentation & Housekeeping

  • I've updated relevant documentation (README, docs/, docstrings) — or N/A
  • I've updated cli-config.yaml.example if I added/changed config keys — or N/A
  • I've updated CONTRIBUTING.md or AGENTS.md if I changed architecture or workflows — or N/A
  • I've considered cross-platform impact (Windows, macOS) per the compatibility guide — or N/A
  • I've updated tool descriptions/schemas if I changed tool behavior — or N/A

For New Skills

  • This skill is broadly useful to most users (if bundled) — see Contributing Guide
  • SKILL.md follows the standard format (frontmatter, trigger conditions, steps, pitfalls)
  • No external dependencies that aren't already available (prefer stdlib, curl, existing Hermes tools)
  • I've tested the skill end-to-end: hermes --toolsets skills -q "Use the X skill to do Y"

Screenshots / Logs

Haisam added 5 commits June 17, 2026 13:51
When the sidebar is in All-profiles mode, each session row now shows a
compact, color-coded profile badge (first letter of the profile name)
between the status dot and the session title.  The badge uses the same
deterministic color from profileColor() that the sidebar rail squares
already use, so the same profile always reads the same color.

Hovering the badge shows a tooltip: Profile: <name>.  The default
profile produces no badge (consistent with its neutral rail treatment).

In single-profile or scoped-to-one-profile mode the badge is completely
absent, so existing users see zero visual change.

The active-status dot (SidebarRowDot) already covered the 'running',
'needs input', and 'idle' states; no changes to that component.

Files changed:
- session-row.tsx: ProfileBadge component + showProfileBadge prop
- index.tsx: prop wired through SidebarSessionsSectionProps; passed to
  search-results and pinned sections when showAllProfiles is true
- virtual-session-list.tsx: prop threaded to virtual and sortable rows
- i18n/en.ts: sidebar.row.profileBadge key

Closes #feat/sidebar-profile-badge-active-status
Adds a new subcommand to hermes curator that exposes the telemetry
already collected by tools/skill_usage.py (use_count, view_count,
patch_count, last_activity_at, provenance) in a human-readable table.

Unlike hermes curator status (which shows only curator-managed /
agent-created skills), hermes curator usage surfaces ALL skills on
disk — bundled built-ins and hub-installed included — so users can
answer 'which skills do I actually use?' without reading .usage.json
directly.

Usage:
  hermes curator usage [--sort use_count|view_count|activity_count|last_activity_at]
                        [--provenance agent|bundled|hub]
                        [--limit N]

Example output:
  NAME                                     USE   VIEW  PATCH  ACTIVITY  LAST_SEEN         PROVENANCE
  -----------------------------------------------------------------------
  spare-parts-pipeline-v8-17               120    120    123       363  2h ago            agent
  plan                                      12     88      0       100  1h ago            bundled
  shop                                       0      3      0         3  2d ago            hub

Implementation notes:
- _cmd_usage() is a thin wrapper around skill_usage.usage_report();
  no new data is collected — this just renders what was already there.
- Reuses _fmt_ts() already in curator.py for human-friendly timestamps.
- Registered as a subcommand of hermes curator (Footprint Ladder rung 1:
  extend existing code) rather than a new top-level command.
- 16 tests covering: table structure, all four sort keys, provenance
  filtering, limit, empty-set, invalid-sort (exit 2), and cli_main E2E.
…elivery

Bot API 10.1's math renderer silently drops LaTeX commands outside its
supported subset.  Two common cases reported:

  * \\boxed{E = mc^2}   -- box wrapper dropped, inner math disappears
  * \\ce{H2O}           -- mhchem entirely unsupported, formula disappears

Root cause: _rich_message_payload() passed raw markdown to sendRichMessage
unchanged; Telegram's parser discards unknown commands without error.

Fix: add _normalize_rich_latex() called from _rich_message_payload() that
pre-processes content INSIDE \$\$...\$\$ math blocks only (prose is untouched):

  * \\boxed{X}  -> X           strip the wrapper; inner math renders correctly
  * \\ce{X}     -> \\text{X}   mhchem -> labeled text entity so formula is visible

\\boxed uses a balanced-brace depth scanner (_extract_brace_arg + _strip_boxed)
so \\boxed{\\frac{a}{b}} and deeply nested forms are handled correctly.
\\ce uses a simple [^{}]* pattern (chemistry formulas have no nested braces).

New entries can be added via _CE_LATEX_RE or _strip_boxed as further gaps
in Bot API's LaTeX support are discovered.

Tests: 17 new cases covering fast-path (no \$\$), simple and nested \\boxed,
double-nested \\boxed, \\ce, prose-between-blocks guard, multiple \$\$ blocks
in one message, and _rich_message_payload integration.
Add store/goal.ts: per-session goal atom, parseGoalResponse, refreshSessionGoal, sendGoalCommand.
Add store/conversation-mode.ts: guidance/queue mode atom with localStorage persistence.
Add composer/goal-status-bar.tsx: compact strip above status stack showing goal state (active/paused/waiting/completed/failed).
Add composer/conversation-mode-toggle.tsx: toolbar pill to switch between Guidance and Queue modes.
Modify composer/controls.tsx: add sessionId prop, render ConversationModeToggle.
Modify composer/index.tsx: wire GoalStatusBar + mode toggle, queue-mode submit branch.
Modify use-message-stream.ts: refreshSessionGoal after message.complete; read goal from session.info.
Modify i18n/types.ts + en.ts: add goalBar and conversationMode string tables.
Tests: 34 unit tests for all store helpers.

Closes NousResearch#48236
@alt-glitch alt-glitch added type/feature New feature or request comp/tui Terminal UI (ui-tui/ + tui_gateway/) comp/gateway Gateway runner, session dispatch, delivery P3 Low — cosmetic, nice to have labels Jun 18, 2026
@alt-glitch alt-glitch added comp/desktop Electron desktop app (apps/desktop/*) comp/agent Core agent runtime: loop, agent_init, prompt builder, context-compression, responses endpoint comp/cli CLI entry point, hermes_cli/, setup wizard and removed comp/tui Terminal UI (ui-tui/ + tui_gateway/) labels Jun 26, 2026

@teknium1 teknium1 left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for the Desktop goal-status concept. Current main supports /goal, but this branch needs contract and scope work before the Desktop feature can be salvaged.

Problems

  • apps/desktop/src/store/goal.ts:166 reads text/response, while current /goal status returns {type: "exec", output: ...} at tui_gateway/server.py:12129-12130; the bar receives no status.
  • apps/desktop/src/store/goal.ts:186 sends /goal end; current main only clears on clear, stop, or done (tui_gateway/server.py:12149-12158). end instead reaches GoalManager.set() (tui_gateway/server.py:12160-12162).
  • The PR also bundles unrelated prompt-builder, Telegram, curator, and sidebar work across five commits.

Suggested changes

  • Rebuild the goal state around a typed/versioned backend payload, or consume the current output contract and cover active/paused/cleared states end to end.
  • Send /goal clear for the End action and add a regression test.
  • Split the unrelated commits, then salvage the focused Desktop change onto current main's TypeScript architecture.

Automated hermes-sweeper review.

{ command: '/goal status', session_id: sid }
)

const raw = result?.text ?? result?.response ?? ''

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Blocking: current slash.exec routes /goal status to command.dispatch, which returns {type: "exec", output: mgr.status_line()} (tui_gateway/server.py:12129-12130). This discards output, so raw is always empty and the goal bar cannot populate. Consume the actual response contract or add a typed goal-status RPC.


try {
await gateway.request('slash.exec', {
command: `/goal ${subcommand}`,

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Blocking: /goal end is not a supported clearing command. Current main accepts clear, stop, and done; any other text is treated as a new goal (tui_gateway/server.py:12149-12162). The End button therefore replaces the goal with end. Send /goal clear and cover that behavior.

@teknium1 teknium1 added sweeper:risk-session-state Sweeper risk: may lose/corrupt/mis-associate session or context state sweeper:risk-message-delivery Sweeper risk: may drop, duplicate, misroute, or suppress messages sweeper:risk-compatibility Sweeper risk: may break existing users, config, migrations, defaults, or upgrades sweeper:blast-broad Sweeper blast radius: broad — a core path most sessions hit labels Jul 14, 2026
@teknium1

Copy link
Copy Markdown
Contributor

The desktop goal status bar work was unified into #72244 (now merged) with credit. Thanks!

@teknium1 teknium1 closed this Jul 27, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

comp/agent Core agent runtime: loop, agent_init, prompt builder, context-compression, responses endpoint comp/cli CLI entry point, hermes_cli/, setup wizard comp/desktop Electron desktop app (apps/desktop/*) comp/gateway Gateway runner, session dispatch, delivery P3 Low — cosmetic, nice to have sweeper:blast-broad Sweeper blast radius: broad — a core path most sessions hit sweeper:risk-compatibility Sweeper risk: may break existing users, config, migrations, defaults, or upgrades sweeper:risk-message-delivery Sweeper risk: may drop, duplicate, misroute, or suppress messages sweeper:risk-session-state Sweeper risk: may lose/corrupt/mis-associate session or context state type/feature New feature or request

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants