To solve Eric's problem, we first need to translate the natural language description into a symbolic representation. Let's denote the number of Combo X as $x_1$ and the number of Combo Y as $x_2$. The objective is to maximize profit.

### Symbolic Representation:
- **Variables:** 
  - $x_1$: Number of Combo X
  - $x_2$: Number of Combo Y

- **Objective Function:**
  Maximize $12x_1 + 15x_2$

- **Constraints:**
  1. $2x_1 + x_2 \leq 25$ (Wireless keyboards constraint)
  2. $3x_2 \leq 13$ (Wired earbuds constraint)
  3. $2x_1 + x_2 \leq 19$ (USB hubs constraint)
  4. $x_1, x_2 \geq 0$ (Non-negativity constraints)

### JSON Representation:
```json
{
  'sym_variables': [('x1', 'Number of Combo X'), ('x2', 'Number of Combo Y')],
  'objective_function': '12*x1 + 15*x2',
  'constraints': ['2*x1 + x2 <= 25', '3*x2 <= 13', '2*x1 + x2 <= 19', 'x1 >= 0', 'x2 >= 0']
}
```

### Gurobi Code in Python:
```python
from gurobipy import *

# Create a new model
m = Model("Eric's Profit Maximization")

# Add variables
x1 = m.addVar(vtype=GRB.INTEGER, name="Combo_X")
x2 = m.addVar(vtype=GRB.INTEGER, name="Combo_Y")

# Set the objective function
m.setObjective(12*x1 + 15*x2, GRB.MAXIMIZE)

# Add constraints
m.addConstr(2*x1 + x2 <= 25, "Wireless_Keyboards")
m.addConstr(3*x2 <= 13, "Wired_Earbuds")
m.addConstr(2*x1 + x2 <= 19, "USB_Hubs")

# Optimize the model
m.optimize()

# Print the solution
if m.status == GRB.OPTIMAL:
    print("Optimal solution found.")
    print(f"Number of Combo X: {x1.x}")
    print(f"Number of Combo Y: {x2.x}")
    print(f"Maximum Profit: {m.objVal}")
else:
    print("No optimal solution found.")

```