Skip to content

claude-code-chat-browser: Decompose sessions.js tool rendering into dispatch registry #59

@clean6378-max-it

Description

@clean6378-max-it

Planned Effort

8 story points — sprint item #1 (High): Frontend sessions.js dispatch registry decomposition

Depends on: Monday PR merged (or branch based on Monday) — no hard code dependency, but finish policy docs first if review is parallel.

Problem

static/js/sessions.js is a ~427-line monolith. Tool invocations (renderToolUse) and tool results (renderToolResult) are implemented as long if / else if chains keyed by tool name / result_type. Every new Claude tool type requires editing this file — high regression risk and unlike the backend, which already uses an ordered dispatch table in utils/tool_dispatch.py (PR #56).

Goal

Mirror the backend pattern on the frontend:

  • Registry maps tool type → render function.
  • One module per renderer (or small grouped modules).
  • sessions.js retains only workspace/session orchestration (target: < 100 lines of rendering logic; imports + loop + renderUser / renderAssistant / renderSystem may remain in file or move per taste).
  • Zero visual/behavior change for existing sessions.
  • Vitest tests prove registry wiring + sample renderers.

Scope

Target layout (suggested)

static/js/
  sessions.js                    # orchestration: loadSession, message loop
  render/
    registry.js                  # TOOL_USE_RENDERERS, TOOL_RESULT_RENDERERS, dispatch helpers
    tool_use/
      bash.js
      read.js
      write.js
      edit.js
      glob.js
      grep.js
      task.js
      todo_write.js
      ask_user_question.js
      fallback.js                # JSON.stringify fallback (current else branch)
    tool_result/
      bash.js
      file_read.js
      file_edit.js
      ...
      plan.js
      fallback.js

Names are flexible; keep ES module import/export consistent with static/js/app.js.

Tool use renderers to preserve (from current sessions.js)

Tool name Notes
Bash Command + optional description
Read, Write, Edit File paths + content snippets
Glob, Grep Pattern + path
Task subagent_type, description, prompt
TodoWrite todo list icons
AskUserQuestion questions
default Truncated JSON (truncate(s, 500)) — tools like WebFetch / WebSearch may use this path today

Also preserve getToolSummary(name, inp) — move next to registry or into registry.js.

Tool result renderers to preserve (result_type)

result_type Notes
bash stdout/stderr, exit status
file_read, file_edit, file_write
glob, grep, web_search, web_fetch
task status, duration, retrieval, description branches
todo_write, user_input, plan
default Tool result (${rt}) summary-only when no body

Security (non-negotiable)

  • Use esc() from shared/utils.js for string interpolation into HTML.
  • Route markdown through renderMarkdown() in shared/markdown.js (DOMPurify) — never marked.parse()innerHTML directly for untrusted session text.
  • Do not weaken static/js/shared/markdown.test.js expectations.

Tests (Vitest)

New file(s) e.g. static/js/render/registry.test.js:

  • Registry contains keys for all tool names / result types listed above (or explicit subset + fallback documented).
  • At least two renderers return HTML containing expected escaped content (e.g. Bash command text, Read file path).
  • getToolSummary('Bash', { command: 'ls' }) matches pre-refactor output (snapshot or string assert).

Run: npm test

Docs

  • Update docs/architecture.md frontend section: mention render/registry.js pattern and parity with utils/tool_dispatch.py.

Acceptance Criteria

  • Dispatch registry: map of tool types → render functions (use + result)
  • Each tool type renderer in its own module/function
  • sessions.js reduced to orchestration-focused size (< 100 lines for tool rendering chains removed)
  • New tool types addable by registering one function
  • All existing rendering behavior preserved (manual smoke: open session with Bash, Read, Task, todos)
  • Vitest tests covering registry + ≥2 renderers
  • npm test and pytest -q green in CI

Metadata

Metadata

Labels

No labels
No labels

Type

No type
No fields configured for issues without a type.

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions