diff --git a/packages/docs/src/pages/index.module.css b/packages/docs/src/pages/index.module.css
index 195b5cb2660..24e85238087 100644
--- a/packages/docs/src/pages/index.module.css
+++ b/packages/docs/src/pages/index.module.css
@@ -1169,9 +1169,11 @@
font-size: 0.8rem;
color: rgba(0, 255, 255, 0.8);
margin-bottom: 0.75rem;
- display: inline-flex;
+ /* display: inline-flex; */
align-items: center;
gap: 0.35rem;
+ text-align: center;
+ justify-content: center;
}
.sectionHeading {
diff --git a/packages/docs/src/pages/jlinc-partnership.tsx b/packages/docs/src/pages/jlinc-partnership.tsx
index c6f3ca1f253..084cb27f157 100644
--- a/packages/docs/src/pages/jlinc-partnership.tsx
+++ b/packages/docs/src/pages/jlinc-partnership.tsx
@@ -14,7 +14,6 @@ function PartnershipHero() {
-
Strategic Partnership Announcement
Cryptographically-Verifiable AI Collaboration
Answer Agents × JLINC brings immutable data provenance to AI agent workflows—finally enabling trustworthy AI adoption in
@@ -1287,7 +1286,6 @@ export default function JLINCPartnership(): JSX.Element {
}}
/>
-
@@ -1295,13 +1293,13 @@ export default function JLINCPartnership(): JSX.Element {
-
+ {/* */}
-
-
+ {/* */}
+ {/* */}
-
+ {/* */}
diff --git a/packages/docs/src/theme/Layout/styles.module.css b/packages/docs/src/theme/Layout/styles.module.css
index e416fe32993..b8597cec48e 100644
--- a/packages/docs/src/theme/Layout/styles.module.css
+++ b/packages/docs/src/theme/Layout/styles.module.css
@@ -80,8 +80,8 @@
}
/* Push everything down to account for the fixed banner */
-:global(body) {
- padding-top: 54px !important;
+:global(.navbar) {
+ top: 54px !important;
}
/* Remove padding for webinar pages and hide navbar */
diff --git a/packages/server/src/database/migrations/postgres/1753000000001-AddUniqueConstraintDefaultChatflows.ts b/packages/server/src/database/migrations/postgres/1753000000001-AddUniqueConstraintDefaultChatflows.ts
index b124b8a1d25..a48a2b231e5 100644
--- a/packages/server/src/database/migrations/postgres/1753000000001-AddUniqueConstraintDefaultChatflows.ts
+++ b/packages/server/src/database/migrations/postgres/1753000000001-AddUniqueConstraintDefaultChatflows.ts
@@ -4,20 +4,15 @@ export class AddUniqueConstraintDefaultChatflows1753000000001 implements Migrati
name = 'AddUniqueConstraintDefaultChatflows1753000000001'
public async up(queryRunner: QueryRunner): Promise {
- // NOTE: Before running this migration, you should manually clean up duplicate chatflows
- // using the SQL scripts provided:
- // 1. Run 1-analyze-duplicate-chatflows.sql to see duplicates
- // 2. Run 2-generate-cleanup-statements.sql to get DELETE statements
- // 3. Manually execute the DELETE statements after reviewing them
- // 4. Then run this migration to add the unique constraint
-
- // Check if there are any remaining duplicates before adding the constraint
+ // Automatically clean up duplicate chatflows, keeping the most recently updated one
+
+ // First, check if there are any duplicates
const duplicateCheck = await queryRunner.query(`
SELECT COUNT(*) as duplicate_count
FROM (
SELECT "userId", "parentChatflowId"
FROM "chat_flow"
- WHERE "parentChatflowId" IS NOT NULL
+ WHERE "parentChatflowId" IS NOT NULL
AND "deletedDate" IS NULL
GROUP BY "userId", "parentChatflowId"
HAVING COUNT(*) > 1
@@ -27,21 +22,40 @@ export class AddUniqueConstraintDefaultChatflows1753000000001 implements Migrati
const duplicateCount = parseInt(duplicateCheck[0]?.duplicate_count || '0')
if (duplicateCount > 0) {
- throw new Error(
- `Cannot add unique constraint: ${duplicateCount} duplicate chatflow groups still exist. ` +
- `Please run the manual cleanup scripts first:\n` +
- `1. 1-analyze-duplicate-chatflows.sql\n` +
- `2. 2-generate-cleanup-statements.sql\n` +
- `3. Manually execute the DELETE statements\n` +
- `4. Then re-run this migration`
- )
+ console.log(`Found ${duplicateCount} duplicate chatflow groups. Cleaning up automatically...`)
+
+ // Delete duplicate chatflows, keeping only the most recently updated one for each group
+ const deleteResult = await queryRunner.query(`
+ DELETE FROM "chat_flow"
+ WHERE id IN (
+ SELECT cf.id
+ FROM "chat_flow" cf
+ INNER JOIN (
+ SELECT
+ "userId",
+ "parentChatflowId",
+ MAX("updatedDate") as max_updated_date
+ FROM "chat_flow"
+ WHERE "parentChatflowId" IS NOT NULL
+ AND "deletedDate" IS NULL
+ GROUP BY "userId", "parentChatflowId"
+ HAVING COUNT(*) > 1
+ ) duplicates
+ ON cf."userId" = duplicates."userId"
+ AND cf."parentChatflowId" = duplicates."parentChatflowId"
+ WHERE cf."deletedDate" IS NULL
+ AND cf."updatedDate" < duplicates.max_updated_date
+ )
+ `)
+
+ console.log(`Deleted ${deleteResult[1]} duplicate chatflow records`)
}
// Add the unique constraint
// This prevents multiple default chatflows from the same template for the same user
await queryRunner.query(`
- CREATE UNIQUE INDEX "idx_unique_user_parent_chatflow"
- ON "chat_flow" ("userId", "parentChatflowId")
+ CREATE UNIQUE INDEX "idx_unique_user_parent_chatflow"
+ ON "chat_flow" ("userId", "parentChatflowId")
WHERE "parentChatflowId" IS NOT NULL AND "deletedDate" IS NULL
`)
}