@changw98ic/dashboard 1.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,141 @@
1
+ import { StateManager, IndexManager, RAGAdapter } from '@changw98ic/data';
2
+ export const statsRoutes = async (fastify, options) => {
3
+ const { projectRoot } = options;
4
+ // 获取项目概览统计
5
+ fastify.get('/overview', async (_request, reply) => {
6
+ const stateManager = new StateManager({ projectRoot });
7
+ const indexManager = new IndexManager({ projectRoot });
8
+ if (!stateManager.exists()) {
9
+ return reply.code(404).send({ error: 'Project not initialized' });
10
+ }
11
+ const state = await stateManager.loadState();
12
+ const entityStats = indexManager.getStats();
13
+ return {
14
+ project: {
15
+ title: state.project_info.title,
16
+ genre: state.project_info.genre,
17
+ target_words: state.project_info.target_words,
18
+ target_chapters: state.project_info.target_chapters,
19
+ },
20
+ progress: {
21
+ current_chapter: state.progress.current_chapter,
22
+ total_words: state.progress.total_words,
23
+ completed_chapters: state.progress.completed_chapters || 0,
24
+ progress_percent: state.project_info.target_chapters
25
+ ? Math.round((state.progress.current_chapter / state.project_info.target_chapters) * 100)
26
+ : 0,
27
+ },
28
+ entities: {
29
+ total: entityStats.totalEntities,
30
+ by_type: entityStats.byType,
31
+ by_tier: entityStats.byTier,
32
+ },
33
+ plot_threads: {
34
+ foreshadowing: state.plot_threads?.foreshadowing?.length || 0,
35
+ active_foreshadowing: state.plot_threads?.foreshadowing?.filter((f) => f.status === 'active').length || 0,
36
+ active_conflicts: state.plot_threads?.active_conflicts?.length || 0,
37
+ unresolved_questions: state.plot_threads?.unresolved_questions?.length || 0,
38
+ },
39
+ strand_tracker: {
40
+ quest_consecutive: state.strand_tracker?.quest_consecutive || 0,
41
+ fire_gap: state.strand_tracker?.fire_gap || 0,
42
+ constellation_gap: state.strand_tracker?.constellation_gap || 0,
43
+ },
44
+ };
45
+ });
46
+ // 获取实体统计
47
+ fastify.get('/entities', async (_request, _reply) => {
48
+ const indexManager = new IndexManager({ projectRoot });
49
+ const stats = indexManager.getStats();
50
+ return {
51
+ total: stats.totalEntities,
52
+ by_type: stats.byType,
53
+ by_tier: stats.byTier,
54
+ };
55
+ });
56
+ // 获取 RAG 索引统计
57
+ fastify.get('/rag', async (_request, _reply) => {
58
+ try {
59
+ const ragAdapter = new RAGAdapter({ projectRoot });
60
+ const indexManager = new IndexManager({ projectRoot });
61
+ const stats = ragAdapter.getStats();
62
+ const queryMetrics = indexManager.getRagQuerySummary(5);
63
+ ragAdapter.close();
64
+ indexManager.close();
65
+ return {
66
+ indexed: true,
67
+ ...stats,
68
+ query_metrics: queryMetrics,
69
+ };
70
+ }
71
+ catch (error) {
72
+ return {
73
+ indexed: false,
74
+ error: error instanceof Error ? error.message : 'Unknown error',
75
+ };
76
+ }
77
+ });
78
+ // 获取章节统计
79
+ fastify.get('/chapters', async (_request, reply) => {
80
+ const stateManager = new StateManager({ projectRoot });
81
+ if (!stateManager.exists()) {
82
+ return reply.code(404).send({ error: 'Project not initialized' });
83
+ }
84
+ const state = await stateManager.loadState();
85
+ const chapterMetas = Object.entries(state.chapter_meta || {});
86
+ const stats = {
87
+ total: chapterMetas.length,
88
+ total_words: 0,
89
+ avg_words: 0,
90
+ by_location: {},
91
+ };
92
+ for (const [, meta] of chapterMetas) {
93
+ const m = meta;
94
+ stats.total_words += m.word_count || 0;
95
+ if (m.location) {
96
+ const loc = m.location.split('/')[0];
97
+ stats.by_location[loc] = (stats.by_location[loc] || 0) + 1;
98
+ }
99
+ }
100
+ stats.avg_words = stats.total > 0 ? Math.round(stats.total_words / stats.total) : 0;
101
+ return stats;
102
+ });
103
+ // 获取审查指标
104
+ fastify.get('/review', async (_request, reply) => {
105
+ const stateManager = new StateManager({ projectRoot });
106
+ if (!stateManager.exists()) {
107
+ return reply.code(404).send({ error: 'Project not initialized' });
108
+ }
109
+ const state = await stateManager.loadState();
110
+ // 汇总所有章节的审查指标
111
+ const metrics = {
112
+ high_point_avg: 0,
113
+ consistency_score: 0,
114
+ pacing_score: 0,
115
+ reader_pull_avg: 0,
116
+ chapters_reviewed: 0,
117
+ };
118
+ const chapterMetas = Object.values(state.chapter_meta || {});
119
+ let totalHighPoint = 0;
120
+ let totalPacing = 0;
121
+ let totalReaderPull = 0;
122
+ let reviewedCount = 0;
123
+ for (const meta of chapterMetas) {
124
+ const m = meta;
125
+ if (m.review_metrics) {
126
+ reviewedCount++;
127
+ totalHighPoint += m.review_metrics.high_point || 0;
128
+ totalPacing += m.review_metrics.pacing || 0;
129
+ totalReaderPull += m.review_metrics.reader_pull || 0;
130
+ }
131
+ }
132
+ if (reviewedCount > 0) {
133
+ metrics.high_point_avg = Math.round((totalHighPoint / reviewedCount) * 10) / 10;
134
+ metrics.pacing_score = Math.round((totalPacing / reviewedCount) * 10) / 10;
135
+ metrics.reader_pull_avg = Math.round((totalReaderPull / reviewedCount) * 10) / 10;
136
+ metrics.chapters_reviewed = reviewedCount;
137
+ }
138
+ return metrics;
139
+ });
140
+ };
141
+ //# sourceMappingURL=stats.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"stats.js","sourceRoot":"","sources":["../../src/routes/stats.ts"],"names":[],"mappings":"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"}
package/package.json ADDED
@@ -0,0 +1,60 @@
1
+ {
2
+ "name": "@changw98ic/dashboard",
3
+ "version": "1.0.0",
4
+ "description": "可视化面板 - Fastify 后端",
5
+ "type": "module",
6
+ "main": "dist/index.js",
7
+ "types": "dist/index.d.ts",
8
+ "exports": {
9
+ ".": {
10
+ "import": "./dist/index.js",
11
+ "types": "./dist/index.d.ts"
12
+ }
13
+ },
14
+ "files": [
15
+ "dist",
16
+ "README.md",
17
+ "LICENSE"
18
+ ],
19
+ "keywords": [
20
+ "webnovel",
21
+ "writing",
22
+ "ai",
23
+ "dashboard",
24
+ "fastify",
25
+ "visualization"
26
+ ],
27
+ "author": "",
28
+ "license": "GPL-3.0-or-later",
29
+ "repository": {
30
+ "type": "git",
31
+ "url": "git+https://github.com/changw98ic/webnovel-writer-skill.git",
32
+ "directory": "packages/dashboard"
33
+ },
34
+ "bugs": {
35
+ "url": "https://github.com/changw98ic/webnovel-writer-skill/issues"
36
+ },
37
+ "homepage": "https://github.com/changw98ic/webnovel-writer-skill#readme",
38
+ "publishConfig": {
39
+ "access": "public"
40
+ },
41
+ "dependencies": {
42
+ "@fastify/cors": "^9.0.1",
43
+ "@fastify/static": "^7.0.4",
44
+ "fastify": "^4.29.1",
45
+ "@changw98ic/core": "1.0.0",
46
+ "@changw98ic/data": "1.0.0"
47
+ },
48
+ "devDependencies": {
49
+ "@types/node": "^20.19.37",
50
+ "typescript": "^5.4.0",
51
+ "vitest": "^1.6.0"
52
+ },
53
+ "scripts": {
54
+ "build": "tsc -p tsconfig.build.json",
55
+ "dev": "tsc -p tsconfig.build.json --watch",
56
+ "start": "node dist/index.js",
57
+ "clean": "rm -rf dist",
58
+ "test": "vitest run packages/dashboard"
59
+ }
60
+ }