Skip to content

Commit f00064e

Browse files
committed
fix: normalize cursor source to cursor-sync to prevent duplicate dropdown entries
1 parent 2b8cf0c commit f00064e

48 files changed

Lines changed: 62 additions & 11266 deletions

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

.gitignore

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,4 +26,7 @@ dist/
2626
# Logs
2727
*.log
2828

29+
# Documentation (internal)
30+
docs/
31+
2932

changelog.md

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,17 @@ Format based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/).
66

77
## [Unreleased]
88

9+
### Fixed
10+
11+
- Fixed duplicate "cursor" and "Cursor" entries in source filter dropdown
12+
- Normalized source values: "cursor" is now converted to "cursor-sync" on sync
13+
- Updated sessions.upsert and batchUpsert to normalize source on insert/update
14+
- Updated messages.upsert and batchUpsert to normalize source for auto-created sessions
15+
- Updated users.me query to normalize enabledAgents (converts "cursor" to "cursor-sync", deduplicates)
16+
- Updated users.updateEnabledAgents to normalize input before saving
17+
- Added "cursor" as alias in source.ts getSourceLabel and getSourceColorClass
18+
- Added "cursor" mapping in Dashboard AI_AGENTS_MAP for legacy data display
19+
920
### Added
1021

1122
- Sessions pagination: loads 40 sessions initially with "Load more" button for 20 at a time

convex/messages.ts

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -60,6 +60,9 @@ export const upsert = internalMutation({
6060

6161
// Auto-create session if it doesn't exist (handles out-of-order sync)
6262
if (!session) {
63+
// Normalize source: "cursor" -> "cursor-sync" for consistency
64+
const rawSource = args.source || "opencode";
65+
const normalizedSource = rawSource === "cursor" ? "cursor-sync" : rawSource;
6366
sessionId = await ctx.db.insert("sessions", {
6467
userId: args.userId,
6568
externalId: args.sessionExternalId,
@@ -68,7 +71,7 @@ export const upsert = internalMutation({
6871
projectName: undefined,
6972
model: args.model,
7073
provider: undefined,
71-
source: args.source || "opencode",
74+
source: normalizedSource,
7275
promptTokens: 0,
7376
completionTokens: 0,
7477
totalTokens: 0,
@@ -258,6 +261,9 @@ export const batchUpsert = internalMutation({
258261
if (!session) {
259262
// Create session for out-of-order messages
260263
const firstMsg = messages[0];
264+
// Normalize source: "cursor" -> "cursor-sync" for consistency
265+
const rawSource = firstMsg.source || "opencode";
266+
const normalizedSource = rawSource === "cursor" ? "cursor-sync" : rawSource;
261267
sessionId = await ctx.db.insert("sessions", {
262268
userId: args.userId,
263269
externalId: sessionExternalId,
@@ -266,7 +272,7 @@ export const batchUpsert = internalMutation({
266272
projectName: undefined,
267273
model: firstMsg.model,
268274
provider: undefined,
269-
source: firstMsg.source || "opencode",
275+
source: normalizedSource,
270276
promptTokens: 0,
271277
completionTokens: 0,
272278
totalTokens: 0,

convex/sessions.ts

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -322,7 +322,9 @@ export const upsert = internalMutation({
322322

323323
const promptTokens = args.promptTokens ?? 0;
324324
const completionTokens = args.completionTokens ?? 0;
325-
const source = args.source || "opencode";
325+
// Normalize source: "cursor" -> "cursor-sync" for consistency
326+
const rawSource = args.source || "opencode";
327+
const source = rawSource === "cursor" ? "cursor-sync" : rawSource;
326328

327329
if (existing) {
328330
// Idempotency check: skip if recently updated with same key values
@@ -593,7 +595,9 @@ export const batchUpsert = internalMutation({
593595

594596
const promptTokens = session.promptTokens ?? 0;
595597
const completionTokens = session.completionTokens ?? 0;
596-
const source = session.source || "opencode";
598+
// Normalize source: "cursor" -> "cursor-sync" for consistency
599+
const rawSource = session.source || "opencode";
600+
const source = rawSource === "cursor" ? "cursor-sync" : rawSource;
597601

598602
if (existing) {
599603
// Idempotency check

convex/users.ts

Lines changed: 14 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -29,13 +29,20 @@ export const me = query({
2929

3030
if (!user) return null;
3131

32+
// Normalize enabledAgents: convert "cursor" -> "cursor-sync" and deduplicate
33+
let normalizedAgents = user.enabledAgents;
34+
if (normalizedAgents) {
35+
normalizedAgents = normalizedAgents.map((a) => (a === "cursor" ? "cursor-sync" : a));
36+
normalizedAgents = [...new Set(normalizedAgents)];
37+
}
38+
3239
return {
3340
_id: user._id,
3441
email: user.email,
3542
name: user.name,
3643
avatarUrl: user.avatarUrl,
3744
hasApiKey: !!user.apiKey,
38-
enabledAgents: user.enabledAgents,
45+
enabledAgents: normalizedAgents,
3946
createdAt: user.createdAt,
4047
};
4148
},
@@ -146,9 +153,14 @@ export const updateEnabledAgents = mutation({
146153

147154
if (!user) throw new Error("User not found");
148155

156+
// Normalize: convert "cursor" -> "cursor-sync" and deduplicate
157+
const normalizedAgents = [...new Set(
158+
enabledAgents.map((a) => (a === "cursor" ? "cursor-sync" : a))
159+
)];
160+
149161
// Patch directly for idempotency
150162
await ctx.db.patch(user._id, {
151-
enabledAgents,
163+
enabledAgents: normalizedAgents,
152164
updatedAt: Date.now(),
153165
});
154166

0 commit comments

Comments
 (0)