Skip to content

feat(server): characters#882

Merged
luoling8192 merged 7 commits intomainfrom
dev/new-character-server
Jan 7, 2026
Merged

feat(server): characters#882
luoling8192 merged 7 commits intomainfrom
dev/new-character-server

Conversation

@luoling8192
Copy link
Member

No description provided.

@gemini-code-assist
Copy link
Contributor

Summary of Changes

Hello @luoling8192, I'm Gemini Code Assist1! I'm currently reviewing this pull request and will post my feedback shortly. In the meantime, here's a summary to help you and other reviewers quickly get up to speed!

This pull request significantly expands the application's backend capabilities by introducing a comprehensive system for managing character metadata and AI provider configurations. It includes crucial database schema updates, new API endpoints for character interactions (liking, bookmarking) and full CRUD operations for provider settings, and integrates these new functionalities into the frontend. The changes aim to provide a more dynamic and interactive user experience while laying the groundwork for flexible AI service integration.

Highlights

  • Database Schema Enhancements: Introduced new tables for character_bookmarks and character_likes, and expanded the characters table with fields like avatar_url, price_credit, and various count metrics (likes, bookmarks, interactions, forks). The character_i18n table now includes a tagline.
  • AI Provider Configuration Management: Added a new provider_configs table and corresponding API endpoints for creating, reading, updating, and deleting AI provider configurations, allowing for dynamic management of external AI services.
  • Character Interaction Features: Implemented new API endpoints for users to 'like' and 'bookmark' characters, with associated counters (likes_count, bookmarks_count) automatically updated in the database.
  • Frontend Integration for New Features: The frontend now dynamically fetches character data, including new fields and interaction counts, and provides interactive buttons for liking and bookmarking characters. The provider settings page has been refactored to use the new backend API for managing provider configurations.
  • Improved Testing Infrastructure: A new mockDB utility using @electric-sql/pglite has been added to facilitate robust in-memory database testing for services and API routes, ensuring reliability of new and existing features.
Using Gemini Code Assist

The full guide for Gemini Code Assist can be found on our documentation page, here are some quick tips.

Invoking Gemini

You can request assistance from Gemini at any point by creating a comment using either /gemini <command> or @gemini-code-assist <command>. Below is a summary of the supported commands on the current page.

Feature Command Description
Code Review /gemini review Performs a code review for the current pull request in its current state.
Pull Request Summary /gemini summary Provides a summary of the current pull request in its current state.
Comment @gemini-code-assist Responds in comments when explicitly tagged, both in pull request comments and review comments.
Help /gemini help Displays a list of available commands.

Customization

To customize Gemini Code Assist for GitHub experience, repository maintainers can create a configuration file and/or provide a custom code review style guide (such as PEP-8 for Python) by creating and adding files to a .gemini/ folder in the base of the repository. Detailed instructions can be found here.

Limitations & Feedback

Gemini Code Assist may make mistakes. Please leave feedback on any instances where its feedback is incorrect or counter productive. You can react with 👍 and 👎 on @gemini-code-assist comments. If you're interested in giving your feedback about your experience with Gemini Code Assist for Github and other Google products, sign up here.

You can also get AI-powered code generation, chat, as well as code reviews directly in the IDE at no cost with the Gemini Code Assist IDE Extension.

Footnotes

  1. Review the Privacy Notices, Generative AI Prohibited Use Policy, Terms of Service, and learn how to configure Gemini Code Assist in GitHub here. Gemini can make mistakes, so double check it and use code with caution.

- Created new tables for character bookmarks and likes.
- Updated the characters table to include additional fields: avatar_url, character_avatar_url, cover_background_url, creator_role, price_credit, likes_count, bookmarks_count, interactions_count, and forks_count.
- Enhanced character schema and service to support liking and bookmarking characters.
- Updated API routes to handle like and bookmark actions.
- Modified character store to manage likes and bookmarks in the frontend.
…onality

- Added @electric-sql/pglite as a dependency for in-memory database testing.
- Implemented mock database creation in mock-db.ts to facilitate testing.
- Updated character service and routes tests to utilize the new mock database.
- Removed outdated character tests and replaced them with updated tests using the mock database.
- Enhanced character creation and retrieval tests to validate new schema fields.
- Added a new table for provider configurations in the database.
- Created API routes for managing provider configurations, including CRUD operations.
- Developed a provider service to handle business logic related to provider configurations.
- Implemented validation schemas for provider configuration requests.
- Added tests for provider service and routes to ensure functionality and reliability.
- Updated application structure to integrate provider management into the existing server architecture.
- Added a watcher to reset the provider configuration edit state when the provider configuration changes and is not empty.
Copy link
Contributor

@gemini-code-assist gemini-code-assist bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Code Review

This pull request introduces significant new features, including a provider configuration system and expanded character details like likes and bookmarks. The implementation is robust, featuring new database migrations, services, API routes, and comprehensive tests using an in-memory database, which is a great practice. I've identified a critical data modeling issue where numeric counters are stored as text, leading to inefficient queries. I've also noted a high-severity issue with a validation schema being too restrictive. Addressing these points will improve data integrity, performance, and code quality.

Comment on lines +17 to +21
ALTER TABLE "characters" ADD COLUMN "price_credit" text DEFAULT '0' NOT NULL;--> statement-breakpoint
ALTER TABLE "characters" ADD COLUMN "likes_count" text DEFAULT '0' NOT NULL;--> statement-breakpoint
ALTER TABLE "characters" ADD COLUMN "bookmarks_count" text DEFAULT '0' NOT NULL;--> statement-breakpoint
ALTER TABLE "characters" ADD COLUMN "interactions_count" text DEFAULT '0' NOT NULL;--> statement-breakpoint
ALTER TABLE "characters" ADD COLUMN "forks_count" text DEFAULT '0' NOT NULL;--> statement-breakpoint
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

critical

The columns price_credit, likes_count, bookmarks_count, interactions_count, and forks_count are defined as text. These columns store numeric data and should use a numeric data type like INTEGER. Using text for numbers is inefficient, requires constant casting in queries (as seen in characterService), and is prone to data integrity issues. Please change these to an appropriate numeric type, for example, INTEGER DEFAULT 0 NOT NULL. This change will also need to be propagated to the Drizzle schema and will simplify the logic in characterService.

ALTER TABLE "characters" ADD COLUMN "price_credit" integer DEFAULT 0 NOT NULL;--> statement-breakpoint
ALTER TABLE "characters" ADD COLUMN "likes_count" integer DEFAULT 0 NOT NULL;--> statement-breakpoint
ALTER TABLE "characters" ADD COLUMN "bookmarks_count" integer DEFAULT 0 NOT NULL;--> statement-breakpoint
ALTER TABLE "characters" ADD COLUMN "interactions_count" integer DEFAULT 0 NOT NULL;--> statement-breakpoint
ALTER TABLE "characters" ADD COLUMN "forks_count" integer DEFAULT 0 NOT NULL;--> statement-breakpoint

Comment on lines +9 to +22
export const CreateProviderConfigSchema = object({
definitionId: string(),
name: string(),
config: optional(record(string(), string())),
validated: optional(boolean()),
validationBypassed: optional(boolean()),
})

export const UpdateProviderConfigSchema = object({
name: optional(string()),
config: optional(record(string(), string())),
validated: optional(boolean()),
validationBypassed: optional(boolean()),
})
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

high

The config field in CreateProviderConfigSchema and UpdateProviderConfigSchema is defined as optional(record(string(), string())). This is too restrictive for a jsonb database column, as it only allows string values in the configuration object. This would prevent storing numbers or booleans, which are common in configurations. To allow for any valid JSON structure, you should use unknown() for the record values. You will also need to add unknown to your valibot import: import { ..., unknown } from 'valibot.

Suggested change
export const CreateProviderConfigSchema = object({
definitionId: string(),
name: string(),
config: optional(record(string(), string())),
validated: optional(boolean()),
validationBypassed: optional(boolean()),
})
export const UpdateProviderConfigSchema = object({
name: optional(string()),
config: optional(record(string(), string())),
validated: optional(boolean()),
validationBypassed: optional(boolean()),
})
export const CreateProviderConfigSchema = object({
definitionId: string(),
name: string(),
config: optional(record(string(), unknown())),
validated: optional(boolean()),
validationBypassed: optional(boolean()),
})
export const UpdateProviderConfigSchema = object({
name: optional(string()),
config: optional(record(string(), unknown())),
validated: optional(boolean()),
validationBypassed: optional(boolean()),
})


await tx.update(schema.character)
.set({
likesCount: sql`CAST(CAST(${schema.character.likesCount} AS INTEGER) - 1 AS TEXT)`,
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

Using raw SQL with string interpolation for arithmetic operations on text columns is inefficient and less safe than using numeric types. If you change the likesCount column to INTEGER as suggested in the SQL migration file, you can simplify this to likesCount: sql${schema.character.likesCount} - 1``. This avoids manual casting and is more idiomatic for Drizzle.


await tx.update(schema.character)
.set({
likesCount: sql`CAST(CAST(${schema.character.likesCount} AS INTEGER) + 1 AS TEXT)`,
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

Similar to the decrement operation, this increment operation on a text column is inefficient. By changing the column type to INTEGER, this can be simplified to likesCount: sql${schema.character.likesCount} + 1``, which is cleaner and more performant.


await tx.update(schema.character)
.set({
bookmarksCount: sql`CAST(CAST(${schema.character.bookmarksCount} AS INTEGER) - 1 AS TEXT)`,
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

The same issue with performing arithmetic on text columns applies here for bookmarksCount. Changing the column to INTEGER would allow for a much simpler and more efficient update: bookmarksCount: sql${schema.character.bookmarksCount} - 1``.


await tx.update(schema.character)
.set({
bookmarksCount: sql`CAST(CAST(${schema.character.bookmarksCount} AS INTEGER) + 1 AS TEXT)`,
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

This increment operation on bookmarksCount should also be simplified by changing the column's data type to INTEGER. The update would then become bookmarksCount: sql${schema.character.bookmarksCount} + 1``.

@luoling8192 luoling8192 force-pushed the dev/new-character-server branch from 710d323 to cdbf07f Compare January 5, 2026 19:52
@github-actions
Copy link
Contributor

github-actions bot commented Jan 5, 2026

⏳ Approval required for deploying to Cloudflare Workers (Preview) for stage-web.

Name Link
🔭 Waiting for approval For maintainers, approve here

Hey, @nekomeowww, @sumimakito, @luoling8192, @LemonNekoGH, kindly take some time to review and approve this deployment when you are available. Thank you! 🙏

@nekomeowww nekomeowww changed the title Dev/new-character-server [DO NOT MERGE] feat(server): characters Jan 6, 2026
…ations

- Introduced new tables for character bookmarks and likes, including necessary foreign key constraints.
- Updated the characters table to include new fields: avatar_url, character_avatar_url, cover_background_url, creator_role, price_credit, likes_count, bookmarks_count, interactions_count, and forks_count.
- Adjusted character schema to reflect changes in data types for likes and bookmarks counts.
- Enhanced character service methods to correctly handle integer values for likes and bookmarks.
- Updated tests to validate the new functionality and ensure correct data handling.
@nekomeowww nekomeowww changed the title [DO NOT MERGE] feat(server): characters feat(server): characters Jan 7, 2026
import { user } from './accounts'

export const providerConfigs = pgTable(
'provider_configs',
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

user_settings_provider_configs

@luoling8192 luoling8192 marked this pull request as ready for review January 7, 2026 13:37
@luoling8192 luoling8192 merged commit 9346708 into main Jan 7, 2026
8 of 9 checks passed
@luoling8192 luoling8192 deleted the dev/new-character-server branch January 7, 2026 13:37
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants