mirror of
https://github.com/CherryHQ/cherry-studio.git
synced 2025-12-26 03:31:24 +08:00
feat(database): message.stats and related message type definitions
- Changed migration command from `yarn run migrations:generate` to `yarn run db:migrations:generate` for consistency across the project. - Updated related documentation in `CLAUDE.md`, `migrations/README.md`, and `src/main/data/README.md` to reflect the new command. - Added a notice in `migrations/README.md` regarding potential database structure changes before the alpha release.
This commit is contained in:
parent
6633082335
commit
8292958c0d
@ -120,7 +120,7 @@ UI Library: `@packages/ui`
|
||||
- **JSON Fields**: For JSON support, add `{ mode: 'json' }`, refer to `preference.ts` table definition
|
||||
- **JSON Serialization**: For JSON fields, no need to manually serialize/deserialize when reading/writing to database, Drizzle handles this automatically
|
||||
- **Timestamps**: Use existing `crudTimestamps` utility
|
||||
- **Migrations**: Generate via `yarn run migrations:generate`
|
||||
- **Migrations**: Generate via `yarn run db:migrations:generate`
|
||||
|
||||
## Data Access Patterns
|
||||
|
||||
|
||||
@ -1,6 +1,10 @@
|
||||
**THIS DIRECTORY IS NOT FOR RUNTIME USE**
|
||||
|
||||
**v2 Data Refactoring Notice**
|
||||
Before the official release of the alpha version, the database structure may change at any time. To maintain simplicity, the database migration files will be periodically reinitialized, which may cause the application to fail. If this occurs, please delete the `cherrystudio.sqlite` file located in the user data directory.
|
||||
|
||||
- Using `libsql` as the `sqlite3` driver, and `drizzle` as the ORM and database migration tool
|
||||
- Table schemas are defined in `src\main\data\db\schemas`
|
||||
- `migrations/sqlite-drizzle` contains auto-generated migration data. Please **DO NOT** modify it.
|
||||
- If table structure changes, we should run migrations.
|
||||
- To generate migrations, use the command `yarn run migrations:generate`
|
||||
- To generate migrations, use the command `yarn run db:migrations:generate`
|
||||
|
||||
3
migrations/sqlite-drizzle/0001_faulty_ogun.sql
Normal file
3
migrations/sqlite-drizzle/0001_faulty_ogun.sql
Normal file
@ -0,0 +1,3 @@
|
||||
ALTER TABLE `message` ADD `stats` text;--> statement-breakpoint
|
||||
ALTER TABLE `message` DROP COLUMN `usage`;--> statement-breakpoint
|
||||
ALTER TABLE `message` DROP COLUMN `metrics`;
|
||||
655
migrations/sqlite-drizzle/meta/0001_snapshot.json
Normal file
655
migrations/sqlite-drizzle/meta/0001_snapshot.json
Normal file
@ -0,0 +1,655 @@
|
||||
{
|
||||
"version": "6",
|
||||
"dialect": "sqlite",
|
||||
"id": "ae53858a-1786-4059-9ff7-9e87267911b6",
|
||||
"prevId": "62a198e0-bfc2-4db1-af58-7e479fedd7b9",
|
||||
"tables": {
|
||||
"app_state": {
|
||||
"name": "app_state",
|
||||
"columns": {
|
||||
"key": {
|
||||
"name": "key",
|
||||
"type": "text",
|
||||
"primaryKey": true,
|
||||
"notNull": true,
|
||||
"autoincrement": false
|
||||
},
|
||||
"value": {
|
||||
"name": "value",
|
||||
"type": "text",
|
||||
"primaryKey": false,
|
||||
"notNull": true,
|
||||
"autoincrement": false
|
||||
},
|
||||
"description": {
|
||||
"name": "description",
|
||||
"type": "text",
|
||||
"primaryKey": false,
|
||||
"notNull": false,
|
||||
"autoincrement": false
|
||||
},
|
||||
"created_at": {
|
||||
"name": "created_at",
|
||||
"type": "integer",
|
||||
"primaryKey": false,
|
||||
"notNull": false,
|
||||
"autoincrement": false
|
||||
},
|
||||
"updated_at": {
|
||||
"name": "updated_at",
|
||||
"type": "integer",
|
||||
"primaryKey": false,
|
||||
"notNull": false,
|
||||
"autoincrement": false
|
||||
}
|
||||
},
|
||||
"indexes": {},
|
||||
"foreignKeys": {},
|
||||
"compositePrimaryKeys": {},
|
||||
"uniqueConstraints": {},
|
||||
"checkConstraints": {}
|
||||
},
|
||||
"entity_tag": {
|
||||
"name": "entity_tag",
|
||||
"columns": {
|
||||
"entity_type": {
|
||||
"name": "entity_type",
|
||||
"type": "text",
|
||||
"primaryKey": false,
|
||||
"notNull": true,
|
||||
"autoincrement": false
|
||||
},
|
||||
"entity_id": {
|
||||
"name": "entity_id",
|
||||
"type": "text",
|
||||
"primaryKey": false,
|
||||
"notNull": true,
|
||||
"autoincrement": false
|
||||
},
|
||||
"tag_id": {
|
||||
"name": "tag_id",
|
||||
"type": "text",
|
||||
"primaryKey": false,
|
||||
"notNull": true,
|
||||
"autoincrement": false
|
||||
},
|
||||
"created_at": {
|
||||
"name": "created_at",
|
||||
"type": "integer",
|
||||
"primaryKey": false,
|
||||
"notNull": false,
|
||||
"autoincrement": false
|
||||
},
|
||||
"updated_at": {
|
||||
"name": "updated_at",
|
||||
"type": "integer",
|
||||
"primaryKey": false,
|
||||
"notNull": false,
|
||||
"autoincrement": false
|
||||
}
|
||||
},
|
||||
"indexes": {
|
||||
"entity_tag_tag_id_idx": {
|
||||
"name": "entity_tag_tag_id_idx",
|
||||
"columns": [
|
||||
"tag_id"
|
||||
],
|
||||
"isUnique": false
|
||||
}
|
||||
},
|
||||
"foreignKeys": {
|
||||
"entity_tag_tag_id_tag_id_fk": {
|
||||
"name": "entity_tag_tag_id_tag_id_fk",
|
||||
"tableFrom": "entity_tag",
|
||||
"tableTo": "tag",
|
||||
"columnsFrom": [
|
||||
"tag_id"
|
||||
],
|
||||
"columnsTo": [
|
||||
"id"
|
||||
],
|
||||
"onDelete": "cascade",
|
||||
"onUpdate": "no action"
|
||||
}
|
||||
},
|
||||
"compositePrimaryKeys": {
|
||||
"entity_tag_entity_type_entity_id_tag_id_pk": {
|
||||
"columns": [
|
||||
"entity_type",
|
||||
"entity_id",
|
||||
"tag_id"
|
||||
],
|
||||
"name": "entity_tag_entity_type_entity_id_tag_id_pk"
|
||||
}
|
||||
},
|
||||
"uniqueConstraints": {},
|
||||
"checkConstraints": {}
|
||||
},
|
||||
"group": {
|
||||
"name": "group",
|
||||
"columns": {
|
||||
"id": {
|
||||
"name": "id",
|
||||
"type": "text",
|
||||
"primaryKey": true,
|
||||
"notNull": true,
|
||||
"autoincrement": false
|
||||
},
|
||||
"entity_type": {
|
||||
"name": "entity_type",
|
||||
"type": "text",
|
||||
"primaryKey": false,
|
||||
"notNull": true,
|
||||
"autoincrement": false
|
||||
},
|
||||
"name": {
|
||||
"name": "name",
|
||||
"type": "text",
|
||||
"primaryKey": false,
|
||||
"notNull": true,
|
||||
"autoincrement": false
|
||||
},
|
||||
"sort_order": {
|
||||
"name": "sort_order",
|
||||
"type": "integer",
|
||||
"primaryKey": false,
|
||||
"notNull": false,
|
||||
"autoincrement": false,
|
||||
"default": 0
|
||||
},
|
||||
"created_at": {
|
||||
"name": "created_at",
|
||||
"type": "integer",
|
||||
"primaryKey": false,
|
||||
"notNull": false,
|
||||
"autoincrement": false
|
||||
},
|
||||
"updated_at": {
|
||||
"name": "updated_at",
|
||||
"type": "integer",
|
||||
"primaryKey": false,
|
||||
"notNull": false,
|
||||
"autoincrement": false
|
||||
}
|
||||
},
|
||||
"indexes": {
|
||||
"group_entity_sort_idx": {
|
||||
"name": "group_entity_sort_idx",
|
||||
"columns": [
|
||||
"entity_type",
|
||||
"sort_order"
|
||||
],
|
||||
"isUnique": false
|
||||
}
|
||||
},
|
||||
"foreignKeys": {},
|
||||
"compositePrimaryKeys": {},
|
||||
"uniqueConstraints": {},
|
||||
"checkConstraints": {}
|
||||
},
|
||||
"message": {
|
||||
"name": "message",
|
||||
"columns": {
|
||||
"id": {
|
||||
"name": "id",
|
||||
"type": "text",
|
||||
"primaryKey": true,
|
||||
"notNull": true,
|
||||
"autoincrement": false
|
||||
},
|
||||
"topic_id": {
|
||||
"name": "topic_id",
|
||||
"type": "text",
|
||||
"primaryKey": false,
|
||||
"notNull": true,
|
||||
"autoincrement": false
|
||||
},
|
||||
"parent_id": {
|
||||
"name": "parent_id",
|
||||
"type": "text",
|
||||
"primaryKey": false,
|
||||
"notNull": false,
|
||||
"autoincrement": false
|
||||
},
|
||||
"response_group_id": {
|
||||
"name": "response_group_id",
|
||||
"type": "integer",
|
||||
"primaryKey": false,
|
||||
"notNull": false,
|
||||
"autoincrement": false,
|
||||
"default": 0
|
||||
},
|
||||
"role": {
|
||||
"name": "role",
|
||||
"type": "text",
|
||||
"primaryKey": false,
|
||||
"notNull": true,
|
||||
"autoincrement": false
|
||||
},
|
||||
"status": {
|
||||
"name": "status",
|
||||
"type": "text",
|
||||
"primaryKey": false,
|
||||
"notNull": true,
|
||||
"autoincrement": false
|
||||
},
|
||||
"assistant_id": {
|
||||
"name": "assistant_id",
|
||||
"type": "text",
|
||||
"primaryKey": false,
|
||||
"notNull": false,
|
||||
"autoincrement": false
|
||||
},
|
||||
"assistant_meta": {
|
||||
"name": "assistant_meta",
|
||||
"type": "text",
|
||||
"primaryKey": false,
|
||||
"notNull": false,
|
||||
"autoincrement": false
|
||||
},
|
||||
"model_id": {
|
||||
"name": "model_id",
|
||||
"type": "text",
|
||||
"primaryKey": false,
|
||||
"notNull": false,
|
||||
"autoincrement": false
|
||||
},
|
||||
"model_meta": {
|
||||
"name": "model_meta",
|
||||
"type": "text",
|
||||
"primaryKey": false,
|
||||
"notNull": false,
|
||||
"autoincrement": false
|
||||
},
|
||||
"data": {
|
||||
"name": "data",
|
||||
"type": "text",
|
||||
"primaryKey": false,
|
||||
"notNull": true,
|
||||
"autoincrement": false
|
||||
},
|
||||
"stats": {
|
||||
"name": "stats",
|
||||
"type": "text",
|
||||
"primaryKey": false,
|
||||
"notNull": false,
|
||||
"autoincrement": false
|
||||
},
|
||||
"trace_id": {
|
||||
"name": "trace_id",
|
||||
"type": "text",
|
||||
"primaryKey": false,
|
||||
"notNull": false,
|
||||
"autoincrement": false
|
||||
},
|
||||
"searchable_text": {
|
||||
"name": "searchable_text",
|
||||
"type": "text",
|
||||
"primaryKey": false,
|
||||
"notNull": false,
|
||||
"autoincrement": false
|
||||
},
|
||||
"created_at": {
|
||||
"name": "created_at",
|
||||
"type": "integer",
|
||||
"primaryKey": false,
|
||||
"notNull": false,
|
||||
"autoincrement": false
|
||||
},
|
||||
"updated_at": {
|
||||
"name": "updated_at",
|
||||
"type": "integer",
|
||||
"primaryKey": false,
|
||||
"notNull": false,
|
||||
"autoincrement": false
|
||||
},
|
||||
"deleted_at": {
|
||||
"name": "deleted_at",
|
||||
"type": "integer",
|
||||
"primaryKey": false,
|
||||
"notNull": false,
|
||||
"autoincrement": false
|
||||
}
|
||||
},
|
||||
"indexes": {
|
||||
"message_parent_id_idx": {
|
||||
"name": "message_parent_id_idx",
|
||||
"columns": [
|
||||
"parent_id"
|
||||
],
|
||||
"isUnique": false
|
||||
},
|
||||
"message_topic_created_idx": {
|
||||
"name": "message_topic_created_idx",
|
||||
"columns": [
|
||||
"topic_id",
|
||||
"created_at"
|
||||
],
|
||||
"isUnique": false
|
||||
},
|
||||
"message_trace_id_idx": {
|
||||
"name": "message_trace_id_idx",
|
||||
"columns": [
|
||||
"trace_id"
|
||||
],
|
||||
"isUnique": false
|
||||
}
|
||||
},
|
||||
"foreignKeys": {
|
||||
"message_topic_id_topic_id_fk": {
|
||||
"name": "message_topic_id_topic_id_fk",
|
||||
"tableFrom": "message",
|
||||
"tableTo": "topic",
|
||||
"columnsFrom": [
|
||||
"topic_id"
|
||||
],
|
||||
"columnsTo": [
|
||||
"id"
|
||||
],
|
||||
"onDelete": "cascade",
|
||||
"onUpdate": "no action"
|
||||
},
|
||||
"message_parent_id_message_id_fk": {
|
||||
"name": "message_parent_id_message_id_fk",
|
||||
"tableFrom": "message",
|
||||
"tableTo": "message",
|
||||
"columnsFrom": [
|
||||
"parent_id"
|
||||
],
|
||||
"columnsTo": [
|
||||
"id"
|
||||
],
|
||||
"onDelete": "set null",
|
||||
"onUpdate": "no action"
|
||||
}
|
||||
},
|
||||
"compositePrimaryKeys": {},
|
||||
"uniqueConstraints": {},
|
||||
"checkConstraints": {
|
||||
"message_role_check": {
|
||||
"name": "message_role_check",
|
||||
"value": "\"message\".\"role\" IN ('user', 'assistant', 'system')"
|
||||
},
|
||||
"message_status_check": {
|
||||
"name": "message_status_check",
|
||||
"value": "\"message\".\"status\" IN ('success', 'error', 'paused')"
|
||||
}
|
||||
}
|
||||
},
|
||||
"preference": {
|
||||
"name": "preference",
|
||||
"columns": {
|
||||
"scope": {
|
||||
"name": "scope",
|
||||
"type": "text",
|
||||
"primaryKey": false,
|
||||
"notNull": true,
|
||||
"autoincrement": false,
|
||||
"default": "'default'"
|
||||
},
|
||||
"key": {
|
||||
"name": "key",
|
||||
"type": "text",
|
||||
"primaryKey": false,
|
||||
"notNull": true,
|
||||
"autoincrement": false
|
||||
},
|
||||
"value": {
|
||||
"name": "value",
|
||||
"type": "text",
|
||||
"primaryKey": false,
|
||||
"notNull": false,
|
||||
"autoincrement": false
|
||||
},
|
||||
"created_at": {
|
||||
"name": "created_at",
|
||||
"type": "integer",
|
||||
"primaryKey": false,
|
||||
"notNull": false,
|
||||
"autoincrement": false
|
||||
},
|
||||
"updated_at": {
|
||||
"name": "updated_at",
|
||||
"type": "integer",
|
||||
"primaryKey": false,
|
||||
"notNull": false,
|
||||
"autoincrement": false
|
||||
}
|
||||
},
|
||||
"indexes": {},
|
||||
"foreignKeys": {},
|
||||
"compositePrimaryKeys": {
|
||||
"preference_scope_key_pk": {
|
||||
"columns": [
|
||||
"scope",
|
||||
"key"
|
||||
],
|
||||
"name": "preference_scope_key_pk"
|
||||
}
|
||||
},
|
||||
"uniqueConstraints": {},
|
||||
"checkConstraints": {}
|
||||
},
|
||||
"tag": {
|
||||
"name": "tag",
|
||||
"columns": {
|
||||
"id": {
|
||||
"name": "id",
|
||||
"type": "text",
|
||||
"primaryKey": true,
|
||||
"notNull": true,
|
||||
"autoincrement": false
|
||||
},
|
||||
"name": {
|
||||
"name": "name",
|
||||
"type": "text",
|
||||
"primaryKey": false,
|
||||
"notNull": true,
|
||||
"autoincrement": false
|
||||
},
|
||||
"color": {
|
||||
"name": "color",
|
||||
"type": "text",
|
||||
"primaryKey": false,
|
||||
"notNull": false,
|
||||
"autoincrement": false
|
||||
},
|
||||
"created_at": {
|
||||
"name": "created_at",
|
||||
"type": "integer",
|
||||
"primaryKey": false,
|
||||
"notNull": false,
|
||||
"autoincrement": false
|
||||
},
|
||||
"updated_at": {
|
||||
"name": "updated_at",
|
||||
"type": "integer",
|
||||
"primaryKey": false,
|
||||
"notNull": false,
|
||||
"autoincrement": false
|
||||
}
|
||||
},
|
||||
"indexes": {
|
||||
"tag_name_unique": {
|
||||
"name": "tag_name_unique",
|
||||
"columns": [
|
||||
"name"
|
||||
],
|
||||
"isUnique": true
|
||||
}
|
||||
},
|
||||
"foreignKeys": {},
|
||||
"compositePrimaryKeys": {},
|
||||
"uniqueConstraints": {},
|
||||
"checkConstraints": {}
|
||||
},
|
||||
"topic": {
|
||||
"name": "topic",
|
||||
"columns": {
|
||||
"id": {
|
||||
"name": "id",
|
||||
"type": "text",
|
||||
"primaryKey": true,
|
||||
"notNull": true,
|
||||
"autoincrement": false
|
||||
},
|
||||
"name": {
|
||||
"name": "name",
|
||||
"type": "text",
|
||||
"primaryKey": false,
|
||||
"notNull": false,
|
||||
"autoincrement": false
|
||||
},
|
||||
"assistant_id": {
|
||||
"name": "assistant_id",
|
||||
"type": "text",
|
||||
"primaryKey": false,
|
||||
"notNull": false,
|
||||
"autoincrement": false
|
||||
},
|
||||
"assistant_meta": {
|
||||
"name": "assistant_meta",
|
||||
"type": "text",
|
||||
"primaryKey": false,
|
||||
"notNull": false,
|
||||
"autoincrement": false
|
||||
},
|
||||
"prompt": {
|
||||
"name": "prompt",
|
||||
"type": "text",
|
||||
"primaryKey": false,
|
||||
"notNull": false,
|
||||
"autoincrement": false
|
||||
},
|
||||
"group_id": {
|
||||
"name": "group_id",
|
||||
"type": "text",
|
||||
"primaryKey": false,
|
||||
"notNull": false,
|
||||
"autoincrement": false
|
||||
},
|
||||
"is_pinned": {
|
||||
"name": "is_pinned",
|
||||
"type": "integer",
|
||||
"primaryKey": false,
|
||||
"notNull": false,
|
||||
"autoincrement": false,
|
||||
"default": false
|
||||
},
|
||||
"pinned_order": {
|
||||
"name": "pinned_order",
|
||||
"type": "integer",
|
||||
"primaryKey": false,
|
||||
"notNull": false,
|
||||
"autoincrement": false,
|
||||
"default": 0
|
||||
},
|
||||
"sort_order": {
|
||||
"name": "sort_order",
|
||||
"type": "integer",
|
||||
"primaryKey": false,
|
||||
"notNull": false,
|
||||
"autoincrement": false,
|
||||
"default": 0
|
||||
},
|
||||
"is_name_manually_edited": {
|
||||
"name": "is_name_manually_edited",
|
||||
"type": "integer",
|
||||
"primaryKey": false,
|
||||
"notNull": false,
|
||||
"autoincrement": false,
|
||||
"default": false
|
||||
},
|
||||
"created_at": {
|
||||
"name": "created_at",
|
||||
"type": "integer",
|
||||
"primaryKey": false,
|
||||
"notNull": false,
|
||||
"autoincrement": false
|
||||
},
|
||||
"updated_at": {
|
||||
"name": "updated_at",
|
||||
"type": "integer",
|
||||
"primaryKey": false,
|
||||
"notNull": false,
|
||||
"autoincrement": false
|
||||
},
|
||||
"deleted_at": {
|
||||
"name": "deleted_at",
|
||||
"type": "integer",
|
||||
"primaryKey": false,
|
||||
"notNull": false,
|
||||
"autoincrement": false
|
||||
}
|
||||
},
|
||||
"indexes": {
|
||||
"topic_group_updated_idx": {
|
||||
"name": "topic_group_updated_idx",
|
||||
"columns": [
|
||||
"group_id",
|
||||
"updated_at"
|
||||
],
|
||||
"isUnique": false
|
||||
},
|
||||
"topic_group_sort_idx": {
|
||||
"name": "topic_group_sort_idx",
|
||||
"columns": [
|
||||
"group_id",
|
||||
"sort_order"
|
||||
],
|
||||
"isUnique": false
|
||||
},
|
||||
"topic_updated_at_idx": {
|
||||
"name": "topic_updated_at_idx",
|
||||
"columns": [
|
||||
"updated_at"
|
||||
],
|
||||
"isUnique": false
|
||||
},
|
||||
"topic_is_pinned_idx": {
|
||||
"name": "topic_is_pinned_idx",
|
||||
"columns": [
|
||||
"is_pinned",
|
||||
"pinned_order"
|
||||
],
|
||||
"isUnique": false
|
||||
},
|
||||
"topic_assistant_id_idx": {
|
||||
"name": "topic_assistant_id_idx",
|
||||
"columns": [
|
||||
"assistant_id"
|
||||
],
|
||||
"isUnique": false
|
||||
}
|
||||
},
|
||||
"foreignKeys": {
|
||||
"topic_group_id_group_id_fk": {
|
||||
"name": "topic_group_id_group_id_fk",
|
||||
"tableFrom": "topic",
|
||||
"tableTo": "group",
|
||||
"columnsFrom": [
|
||||
"group_id"
|
||||
],
|
||||
"columnsTo": [
|
||||
"id"
|
||||
],
|
||||
"onDelete": "set null",
|
||||
"onUpdate": "no action"
|
||||
}
|
||||
},
|
||||
"compositePrimaryKeys": {},
|
||||
"uniqueConstraints": {},
|
||||
"checkConstraints": {}
|
||||
}
|
||||
},
|
||||
"views": {},
|
||||
"enums": {},
|
||||
"_meta": {
|
||||
"schemas": {},
|
||||
"tables": {},
|
||||
"columns": {}
|
||||
},
|
||||
"internal": {
|
||||
"indexes": {}
|
||||
}
|
||||
}
|
||||
@ -8,6 +8,13 @@
|
||||
"when": 1766588456958,
|
||||
"tag": "0000_init",
|
||||
"breakpoints": true
|
||||
},
|
||||
{
|
||||
"idx": 1,
|
||||
"version": "6",
|
||||
"when": 1766670360754,
|
||||
"tag": "0001_faulty_ogun",
|
||||
"breakpoints": true
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
@ -75,7 +75,7 @@
|
||||
"format:check": "biome format && biome lint",
|
||||
"prepare": "git config blame.ignoreRevsFile .git-blame-ignore-revs && husky",
|
||||
"claude": "dotenv -e .env -- claude",
|
||||
"migrations:generate": "drizzle-kit generate --config ./migrations/sqlite-drizzle.config.ts",
|
||||
"db:migrations:generate": "drizzle-kit generate --config ./migrations/sqlite-drizzle.config.ts",
|
||||
"release:aicore:alpha": "yarn workspace @cherrystudio/ai-core version prerelease --preid alpha --immediate && yarn workspace @cherrystudio/ai-core build && yarn workspace @cherrystudio/ai-core npm publish --tag alpha --access public",
|
||||
"release:aicore:beta": "yarn workspace @cherrystudio/ai-core version prerelease --preid beta --immediate && yarn workspace @cherrystudio/ai-core build && yarn workspace @cherrystudio/ai-core npm publish --tag beta --access public",
|
||||
"release:aicore": "yarn workspace @cherrystudio/ai-core version patch --immediate && yarn workspace @cherrystudio/ai-core build && yarn workspace @cherrystudio/ai-core npm publish --access public",
|
||||
|
||||
@ -7,25 +7,31 @@ This directory contains shared type definitions and schemas for the Cherry Studi
|
||||
```
|
||||
packages/shared/data/
|
||||
├── api/ # Data API type system
|
||||
│ ├── index.ts # Barrel exports for clean imports
|
||||
│ ├── apiSchemas.ts # API endpoint definitions and mappings
|
||||
│ ├── apiTypes.ts # Core request/response infrastructure types
|
||||
│ ├── apiModels.ts # Business entity types and DTOs
|
||||
│ ├── apiPaths.ts # API path definitions and utilities
|
||||
│ └── errorCodes.ts # Standardized error handling
|
||||
│ ├── index.ts # Barrel exports for clean imports
|
||||
│ ├── apiSchemas.ts # API endpoint definitions and mappings
|
||||
│ ├── apiTypes.ts # Core request/response infrastructure types
|
||||
│ ├── apiModels.ts # Business entity types and DTOs
|
||||
│ ├── apiPaths.ts # API path definitions and utilities
|
||||
│ └── errorCodes.ts # Standardized error handling
|
||||
├── cache/ # Cache system type definitions
|
||||
│ ├── cacheTypes.ts # Core cache infrastructure types
|
||||
│ ├── cacheSchemas.ts # Cache key schemas and type mappings
|
||||
│ └── cacheValueTypes.ts # Cache value type definitions
|
||||
│ ├── cacheTypes.ts # Core cache infrastructure types
|
||||
│ ├── cacheSchemas.ts # Cache key schemas and type mappings
|
||||
│ └── cacheValueTypes.ts # Cache value type definitions
|
||||
├── preference/ # Preference system type definitions
|
||||
│ ├── preferenceTypes.ts # Core preference system types
|
||||
│ ├── preferenceTypes.ts # Core preference system types
|
||||
│ └── preferenceSchemas.ts # Preference schemas and default values
|
||||
└── README.md # This file
|
||||
├── types/ # Shared data types for Main/Renderer
|
||||
└── README.md # This file
|
||||
```
|
||||
|
||||
## 🏗️ System Overview
|
||||
|
||||
This directory provides type definitions for three main data management systems:
|
||||
This directory provides type definitions for four main data management systems:
|
||||
|
||||
### Types System (`types/`)
|
||||
- **Purpose**: Shared data types for cross-process (Main/Renderer) communication and database schemas
|
||||
- **Features**: Database table field types, business entity definitions
|
||||
- **Usage**: Used in Drizzle ORM schemas via `.$type<T>()` and runtime type checking
|
||||
|
||||
### API System (`api/`)
|
||||
- **Purpose**: Type-safe IPC communication between Main and Renderer processes
|
||||
@ -72,6 +78,11 @@ import type { PreferenceKeyType, PreferenceDefaultScopeType } from '@shared/data
|
||||
|
||||
## 🔧 Development Guidelines
|
||||
|
||||
### Adding Shared Types
|
||||
1. Create or update type file in `types/` directory
|
||||
2. Use camelCase for field names
|
||||
3. Reference types in Drizzle schemas using `.$type<T>()`
|
||||
|
||||
### Adding Cache Types
|
||||
1. Add cache key to `cache/cacheSchemas.ts`
|
||||
2. Define value type in `cache/cacheValueTypes.ts`
|
||||
|
||||
171
packages/shared/data/types/message.ts
Normal file
171
packages/shared/data/types/message.ts
Normal file
@ -0,0 +1,171 @@
|
||||
/**
|
||||
* Message Statistics - combines token usage and performance metrics
|
||||
* Replaces the separate `usage` and `metrics` fields
|
||||
*/
|
||||
export interface MessageStats {
|
||||
// Token consumption (from API response)
|
||||
promptTokens?: number
|
||||
completionTokens?: number
|
||||
totalTokens?: number
|
||||
thoughtsTokens?: number
|
||||
|
||||
// Cost (calculated at message completion time)
|
||||
cost?: number
|
||||
|
||||
// Performance metrics (measured locally)
|
||||
timeFirstTokenMs?: number
|
||||
timeCompletionMs?: number
|
||||
timeThinkingMs?: number
|
||||
}
|
||||
|
||||
// ============================================================================
|
||||
// Message Data
|
||||
// ============================================================================
|
||||
|
||||
/**
|
||||
* Message data field structure
|
||||
* This is the type for the `data` column in the message table
|
||||
*/
|
||||
export interface MessageData {
|
||||
blocks: MessageDataBlock[]
|
||||
}
|
||||
|
||||
//FIXME [v2] 注意,以下类型只是占位,接口未稳定,随时会变
|
||||
|
||||
// ============================================================================
|
||||
// Message Block
|
||||
// ============================================================================
|
||||
|
||||
export enum BlockType {
|
||||
UNKNOWN = 'unknown',
|
||||
MAIN_TEXT = 'main_text',
|
||||
THINKING = 'thinking',
|
||||
TRANSLATION = 'translation',
|
||||
IMAGE = 'image',
|
||||
CODE = 'code',
|
||||
TOOL = 'tool',
|
||||
FILE = 'file',
|
||||
ERROR = 'error',
|
||||
CITATION = 'citation',
|
||||
VIDEO = 'video',
|
||||
COMPACT = 'compact'
|
||||
}
|
||||
|
||||
/**
|
||||
* Base message block data structure
|
||||
*/
|
||||
export interface BaseBlock {
|
||||
type: BlockType
|
||||
createdAt: number // timestamp
|
||||
updatedAt?: number
|
||||
modelId?: string
|
||||
metadata?: Record<string, unknown>
|
||||
error?: SerializedErrorData
|
||||
}
|
||||
|
||||
/**
|
||||
* Serialized error for storage
|
||||
*/
|
||||
export interface SerializedErrorData {
|
||||
name?: string
|
||||
message: string
|
||||
code?: string
|
||||
stack?: string
|
||||
cause?: unknown
|
||||
}
|
||||
|
||||
// Block type specific interfaces
|
||||
|
||||
export interface UnknownBlock extends BaseBlock {
|
||||
type: BlockType.UNKNOWN
|
||||
content?: string
|
||||
}
|
||||
|
||||
export interface MainTextBlock extends BaseBlock {
|
||||
type: BlockType.MAIN_TEXT
|
||||
content: string
|
||||
knowledgeBaseIds?: string[]
|
||||
citationReferences?: {
|
||||
citationBlockId?: string
|
||||
citationBlockSource?: string
|
||||
}[]
|
||||
}
|
||||
|
||||
export interface ThinkingBlock extends BaseBlock {
|
||||
type: BlockType.THINKING
|
||||
content: string
|
||||
thinkingMs: number
|
||||
}
|
||||
|
||||
export interface TranslationBlock extends BaseBlock {
|
||||
type: BlockType.TRANSLATION
|
||||
content: string
|
||||
sourceBlockId?: string
|
||||
sourceLanguage?: string
|
||||
targetLanguage: string
|
||||
}
|
||||
|
||||
export interface CodeBlock extends BaseBlock {
|
||||
type: BlockType.CODE
|
||||
content: string
|
||||
language: string
|
||||
}
|
||||
|
||||
export interface ImageBlock extends BaseBlock {
|
||||
type: BlockType.IMAGE
|
||||
url?: string
|
||||
fileId?: string
|
||||
}
|
||||
|
||||
export interface ToolBlock extends BaseBlock {
|
||||
type: BlockType.TOOL
|
||||
toolId: string
|
||||
toolName?: string
|
||||
arguments?: Record<string, unknown>
|
||||
content?: string | object
|
||||
}
|
||||
|
||||
export interface CitationBlock extends BaseBlock {
|
||||
type: BlockType.CITATION
|
||||
responseData?: unknown
|
||||
knowledgeData?: unknown
|
||||
memoriesData?: unknown
|
||||
}
|
||||
|
||||
export interface FileBlock extends BaseBlock {
|
||||
type: BlockType.FILE
|
||||
fileId: string
|
||||
}
|
||||
|
||||
export interface VideoBlock extends BaseBlock {
|
||||
type: BlockType.VIDEO
|
||||
url?: string
|
||||
filePath?: string
|
||||
}
|
||||
|
||||
export interface ErrorBlock extends BaseBlock {
|
||||
type: BlockType.ERROR
|
||||
}
|
||||
|
||||
export interface CompactBlock extends BaseBlock {
|
||||
type: BlockType.COMPACT
|
||||
content: string
|
||||
compactedContent: string
|
||||
}
|
||||
|
||||
/**
|
||||
* Union type of all message block data types
|
||||
*/
|
||||
export type MessageDataBlock =
|
||||
| UnknownBlock
|
||||
| MainTextBlock
|
||||
| ThinkingBlock
|
||||
| TranslationBlock
|
||||
| CodeBlock
|
||||
| ImageBlock
|
||||
| ToolBlock
|
||||
| CitationBlock
|
||||
| FileBlock
|
||||
| VideoBlock
|
||||
| ErrorBlock
|
||||
| CompactBlock
|
||||
@ -239,7 +239,7 @@ import { dataApiService } from '@/data/DataApiService'
|
||||
|
||||
### Adding Database Tables
|
||||
1. Create schema in `db/schemas/{tableName}.ts`
|
||||
2. Generate migration: `yarn run migrations:generate`
|
||||
2. Generate migration: `yarn run db:migrations:generate`
|
||||
3. Add seeding data in `db/seeding/` if needed
|
||||
4. Decide: Repository pattern or direct Drizzle?
|
||||
- Complex domain → Create repository in `repositories/`
|
||||
|
||||
@ -1,3 +1,4 @@
|
||||
import type { MessageData, MessageStats } from '@shared/data/types/message'
|
||||
import { sql } from 'drizzle-orm'
|
||||
import { check, index, integer, sqliteTable, text } from 'drizzle-orm/sqlite-core'
|
||||
|
||||
@ -37,11 +38,9 @@ export const messageTable = sqliteTable(
|
||||
// Preserved model info (provider, name)
|
||||
modelMeta: text({ mode: 'json' }),
|
||||
// Main content - contains blocks[], mentions, etc.
|
||||
data: text({ mode: 'json' }).notNull(),
|
||||
// Token usage statistics
|
||||
usage: text({ mode: 'json' }),
|
||||
// Performance metrics
|
||||
metrics: text({ mode: 'json' }),
|
||||
data: text({ mode: 'json' }).$type<MessageData>().notNull(),
|
||||
// Statistics: token usage, performance metrics, etc.
|
||||
stats: text({ mode: 'json' }).$type<MessageStats>(),
|
||||
// Trace ID for tracking
|
||||
traceId: text(),
|
||||
// Searchable text extracted from data.blocks (populated by trigger, used for FTS5)
|
||||
|
||||
@ -1,3 +1,5 @@
|
||||
//TODO [v2] 类型将转移至 packages/shared/data/types/message.ts。 转移后此文件将废弃(deprecated)
|
||||
|
||||
import type { CompletionUsage } from '@cherrystudio/openai/resources'
|
||||
import type { ProviderMetadata } from 'ai'
|
||||
|
||||
|
||||
Loading…
Reference in New Issue
Block a user