Skip to content

fix(dictionary): normalize untrimmed agent names in agentNameDictionaryChanges #1441

Description

@hsusul

Component

Dictionary helper (src/helpers/agentNameDictionary.js)

Description & Actual Behavior

When agentNameDictionaryChanges(dictionary, newName, oldName) processes agent name updates, it trims newName for insertion but checks oldName without trimming against newName and dictionary.

This leads to two correctness defects:

  1. Accidental Deletion of Agent Name: When oldName is "MyAgent" and newName is " MyAgent " (or vice versa), newName.trim() equals "MyAgent". Because words.includes("MyAgent") is true, add becomes []. However, oldName !== newName ("MyAgent" !== " MyAgent ") evaluates to true and words.includes(oldName) evaluates to true, causing remove to return ["MyAgent"]. The function returns { add: [], remove: ["MyAgent"] }, wiping the agent's name from the custom dictionary simply because surrounding whitespace was introduced in the name field.
  2. Orphaned Dictionary Entries on Rename: When oldName has surrounding whitespace (e.g. " MyAgent ") and the user renames the agent to "NewAgent", oldName !== newName is true but words.includes(" MyAgent ") fails (since dictionary words are stored trimmed as "MyAgent"). As a result, remove returns [] and { add: ["NewAgent"], remove: [] }, leaving the old agent name orphaned in SQLite.

Expected Behavior

agentNameDictionaryChanges should normalize both newName and oldName by trimming whitespace before checking equality and dictionary presence.

  • Renaming "OpenWhispr" to " OpenWhispr " should yield { add: [], remove: [] }.
  • Renaming " OpenWhispr " to "Jarvis" when dictionary has ["OpenWhispr"] should yield { add: ["Jarvis"], remove: ["OpenWhispr"] }.

Reproduction

const { agentNameDictionaryChanges } = await import("./src/helpers/agentNameDictionary.js");

// Case 1: Agent name wiped on whitespace update
const r1 = agentNameDictionaryChanges(["MyAgent"], " MyAgent ", "MyAgent");
console.log(r1); // Actual: { add: [], remove: ['MyAgent'] } | Expected: { add: [], remove: [] }

// Case 2: Old agent name orphaned on rename with untrimmed oldName
const r2 = agentNameDictionaryChanges(["MyAgent"], "Jarvis", " MyAgent ");
console.log(r2); // Actual: { add: ['Jarvis'], remove: [] } | Expected: { add: ['Jarvis'], remove: ['MyAgent'] }

Environment

  • OpenWhispr main branch
  • Node.js 24+

User Impact

Updating or editing agent names in settings can silently wipe the agent's name from the custom dictionary or leave stale/orphaned names in the dictionary table.

Root-Cause Hypothesis

agentNameDictionaryChanges compares raw oldName against raw newName and checks words.includes(oldName) without trimming oldName first or comparing their trimmed forms.

Proposed Scope

Normalize newName and oldName using trim() before checking string equality and dictionary membership in agentNameDictionaryChanges. Add regression tests covering untrimmed inputs and whitespace-only name updates.

I intend to work on this issue and submit a pull request.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions