Always consider the computational complexity of your algorithms and leverage efficient built-in methods when available. Look for opportunities to reduce time complexity and avoid unnecessary operations like redundant loops or object creation.

Common inefficiencies to watch for:

Examples of improvements:

Before (O(n^2) deduplication):

promptParams.forEach((promptParam) => {
  if (!allParams.some((param) => param.key === promptParam.key)) {
    allParams.push(promptParam);
  }
});

After (O(n) with Map):

const paramMap = new Map(allParams.map(p => [p.key, p]));
promptParams.forEach(p => paramMap.set(p.key, p));
const allParams = Array.from(paramMap.values());

Before (unnecessary string creation):

const beforeCursor = text.slice(0, cursorPosition);
const lastAtIndex = beforeCursor.lastIndexOf('@');

After (direct method usage):

const lastAtIndex = text.lastIndexOf('@', cursorPosition - 1);