@echoes-io/mcp-server 2.2.0 → 4.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.
- package/README.md +2 -2
- package/package.json +23 -12
- package/cli/index.d.ts +0 -2
- package/cli/index.js +0 -6
- package/lib/prompts/handlers.d.ts +0 -21
- package/lib/prompts/handlers.js +0 -107
- package/lib/prompts/index.d.ts +0 -2
- package/lib/prompts/index.js +0 -2
- package/lib/prompts/substitution.d.ts +0 -2
- package/lib/prompts/substitution.js +0 -45
- package/lib/prompts/validation.d.ts +0 -8
- package/lib/prompts/validation.js +0 -20
- package/lib/server.d.ts +0 -55
- package/lib/server.js +0 -305
- package/lib/tools/book-generate.d.ts +0 -20
- package/lib/tools/book-generate.js +0 -36
- package/lib/tools/chapter-delete.d.ts +0 -15
- package/lib/tools/chapter-delete.js +0 -48
- package/lib/tools/chapter-info.d.ts +0 -14
- package/lib/tools/chapter-info.js +0 -47
- package/lib/tools/chapter-insert.d.ts +0 -21
- package/lib/tools/chapter-insert.js +0 -104
- package/lib/tools/chapter-refresh.d.ts +0 -12
- package/lib/tools/chapter-refresh.js +0 -78
- package/lib/tools/episode-info.d.ts +0 -13
- package/lib/tools/episode-info.js +0 -45
- package/lib/tools/episode-update.d.ts +0 -16
- package/lib/tools/episode-update.js +0 -42
- package/lib/tools/index.d.ts +0 -14
- package/lib/tools/index.js +0 -14
- package/lib/tools/rag-characters.d.ts +0 -12
- package/lib/tools/rag-characters.js +0 -26
- package/lib/tools/rag-context.d.ts +0 -16
- package/lib/tools/rag-context.js +0 -54
- package/lib/tools/rag-index.d.ts +0 -18
- package/lib/tools/rag-index.js +0 -89
- package/lib/tools/rag-search.d.ts +0 -17
- package/lib/tools/rag-search.js +0 -58
- package/lib/tools/stats.d.ts +0 -14
- package/lib/tools/stats.js +0 -132
- package/lib/tools/timeline-sync.d.ts +0 -15
- package/lib/tools/timeline-sync.js +0 -217
- package/lib/tools/words-count.d.ts +0 -10
- package/lib/tools/words-count.js +0 -30
- package/lib/utils.d.ts +0 -1
- package/lib/utils.js +0 -2
|
@@ -1,78 +0,0 @@
|
|
|
1
|
-
import { readFileSync } from 'node:fs';
|
|
2
|
-
import { getTextStats, parseMarkdown } from '@echoes-io/utils';
|
|
3
|
-
import { z } from 'zod';
|
|
4
|
-
export const chapterRefreshSchema = z.object({
|
|
5
|
-
timeline: z.string().describe('Timeline name'),
|
|
6
|
-
file: z.string().describe('Path to chapter markdown file'),
|
|
7
|
-
});
|
|
8
|
-
export async function chapterRefresh(args, tracker) {
|
|
9
|
-
try {
|
|
10
|
-
const content = readFileSync(args.file, 'utf-8');
|
|
11
|
-
const { metadata, content: markdownContent } = parseMarkdown(content);
|
|
12
|
-
const stats = getTextStats(markdownContent);
|
|
13
|
-
const arc = metadata.arc;
|
|
14
|
-
const episode = metadata.episode;
|
|
15
|
-
const chapter = metadata.chapter;
|
|
16
|
-
if (!arc || !episode || !chapter) {
|
|
17
|
-
throw new Error('Missing required metadata: arc, episode, or chapter');
|
|
18
|
-
}
|
|
19
|
-
const existing = await tracker.getChapter(args.timeline, arc, episode, chapter);
|
|
20
|
-
if (!existing) {
|
|
21
|
-
throw new Error(`Chapter not found in database: ${args.timeline}/${arc}/ep${episode}/ch${chapter}`);
|
|
22
|
-
}
|
|
23
|
-
const chapterData = {
|
|
24
|
-
timelineName: args.timeline,
|
|
25
|
-
arcName: arc,
|
|
26
|
-
episodeNumber: episode,
|
|
27
|
-
partNumber: metadata.part || 1,
|
|
28
|
-
number: chapter,
|
|
29
|
-
pov: metadata.pov || 'Unknown',
|
|
30
|
-
title: metadata.title || 'Untitled',
|
|
31
|
-
date: new Date(metadata.date || Date.now()).toISOString(),
|
|
32
|
-
summary: metadata.summary || '',
|
|
33
|
-
location: metadata.location || '',
|
|
34
|
-
outfit: metadata.outfit || '',
|
|
35
|
-
kink: metadata.kink || '',
|
|
36
|
-
words: stats.words,
|
|
37
|
-
characters: stats.characters,
|
|
38
|
-
charactersNoSpaces: stats.charactersNoSpaces,
|
|
39
|
-
paragraphs: stats.paragraphs,
|
|
40
|
-
sentences: stats.sentences,
|
|
41
|
-
readingTimeMinutes: Math.ceil(stats.words / 200),
|
|
42
|
-
};
|
|
43
|
-
await tracker.updateChapter(args.timeline, arc, episode, chapter, chapterData);
|
|
44
|
-
return {
|
|
45
|
-
content: [
|
|
46
|
-
{
|
|
47
|
-
type: 'text',
|
|
48
|
-
text: JSON.stringify({
|
|
49
|
-
file: args.file,
|
|
50
|
-
timeline: args.timeline,
|
|
51
|
-
arc,
|
|
52
|
-
episode,
|
|
53
|
-
chapter,
|
|
54
|
-
updated: {
|
|
55
|
-
metadata: {
|
|
56
|
-
pov: chapterData.pov,
|
|
57
|
-
title: chapterData.title,
|
|
58
|
-
date: chapterData.date,
|
|
59
|
-
summary: chapterData.summary,
|
|
60
|
-
location: chapterData.location,
|
|
61
|
-
},
|
|
62
|
-
stats: {
|
|
63
|
-
words: stats.words,
|
|
64
|
-
characters: stats.characters,
|
|
65
|
-
paragraphs: stats.paragraphs,
|
|
66
|
-
sentences: stats.sentences,
|
|
67
|
-
readingTimeMinutes: chapterData.readingTimeMinutes,
|
|
68
|
-
},
|
|
69
|
-
},
|
|
70
|
-
}, null, 2),
|
|
71
|
-
},
|
|
72
|
-
],
|
|
73
|
-
};
|
|
74
|
-
}
|
|
75
|
-
catch (error) {
|
|
76
|
-
throw new Error(`Failed to refresh chapter: ${error instanceof Error ? error.message : 'Unknown error'}`);
|
|
77
|
-
}
|
|
78
|
-
}
|
|
@@ -1,13 +0,0 @@
|
|
|
1
|
-
import type { Tracker } from '@echoes-io/tracker';
|
|
2
|
-
import { z } from 'zod';
|
|
3
|
-
export declare const episodeInfoSchema: z.ZodObject<{
|
|
4
|
-
timeline: z.ZodString;
|
|
5
|
-
arc: z.ZodString;
|
|
6
|
-
episode: z.ZodNumber;
|
|
7
|
-
}, z.core.$strip>;
|
|
8
|
-
export declare function episodeInfo(args: z.infer<typeof episodeInfoSchema>, tracker: Tracker): Promise<{
|
|
9
|
-
content: {
|
|
10
|
-
type: "text";
|
|
11
|
-
text: string;
|
|
12
|
-
}[];
|
|
13
|
-
}>;
|
|
@@ -1,45 +0,0 @@
|
|
|
1
|
-
import { z } from 'zod';
|
|
2
|
-
export const episodeInfoSchema = z.object({
|
|
3
|
-
timeline: z.string().describe('Timeline name'),
|
|
4
|
-
arc: z.string().describe('Arc name'),
|
|
5
|
-
episode: z.number().describe('Episode number'),
|
|
6
|
-
});
|
|
7
|
-
export async function episodeInfo(args, tracker) {
|
|
8
|
-
try {
|
|
9
|
-
const episode = await tracker.getEpisode(args.timeline, args.arc, args.episode);
|
|
10
|
-
if (!episode) {
|
|
11
|
-
throw new Error(`Episode not found: ${args.timeline}/${args.arc}/ep${args.episode}`);
|
|
12
|
-
}
|
|
13
|
-
const chapters = await tracker.getChapters(args.timeline, args.arc, args.episode);
|
|
14
|
-
return {
|
|
15
|
-
content: [
|
|
16
|
-
{
|
|
17
|
-
type: 'text',
|
|
18
|
-
text: JSON.stringify({
|
|
19
|
-
timeline: args.timeline,
|
|
20
|
-
arc: args.arc,
|
|
21
|
-
episodeInfo: {
|
|
22
|
-
number: episode.number,
|
|
23
|
-
title: episode.title,
|
|
24
|
-
slug: episode.slug,
|
|
25
|
-
description: episode.description,
|
|
26
|
-
},
|
|
27
|
-
chapters: chapters.map((ch) => ({
|
|
28
|
-
number: ch.number,
|
|
29
|
-
pov: ch.pov,
|
|
30
|
-
title: ch.title,
|
|
31
|
-
words: ch.words,
|
|
32
|
-
})),
|
|
33
|
-
stats: {
|
|
34
|
-
totalChapters: chapters.length,
|
|
35
|
-
totalWords: chapters.reduce((sum, ch) => sum + ch.words, 0),
|
|
36
|
-
},
|
|
37
|
-
}, null, 2),
|
|
38
|
-
},
|
|
39
|
-
],
|
|
40
|
-
};
|
|
41
|
-
}
|
|
42
|
-
catch (error) {
|
|
43
|
-
throw new Error(`Failed to get episode info: ${error instanceof Error ? error.message : 'Unknown error'}`);
|
|
44
|
-
}
|
|
45
|
-
}
|
|
@@ -1,16 +0,0 @@
|
|
|
1
|
-
import type { Tracker } from '@echoes-io/tracker';
|
|
2
|
-
import { z } from 'zod';
|
|
3
|
-
export declare const episodeUpdateSchema: z.ZodObject<{
|
|
4
|
-
timeline: z.ZodString;
|
|
5
|
-
arc: z.ZodString;
|
|
6
|
-
episode: z.ZodNumber;
|
|
7
|
-
description: z.ZodOptional<z.ZodString>;
|
|
8
|
-
title: z.ZodOptional<z.ZodString>;
|
|
9
|
-
slug: z.ZodOptional<z.ZodString>;
|
|
10
|
-
}, z.core.$strip>;
|
|
11
|
-
export declare function episodeUpdate(args: z.infer<typeof episodeUpdateSchema>, tracker: Tracker): Promise<{
|
|
12
|
-
content: {
|
|
13
|
-
type: "text";
|
|
14
|
-
text: string;
|
|
15
|
-
}[];
|
|
16
|
-
}>;
|
|
@@ -1,42 +0,0 @@
|
|
|
1
|
-
import { z } from 'zod';
|
|
2
|
-
export const episodeUpdateSchema = z.object({
|
|
3
|
-
timeline: z.string().describe('Timeline name'),
|
|
4
|
-
arc: z.string().describe('Arc name'),
|
|
5
|
-
episode: z.number().describe('Episode number'),
|
|
6
|
-
description: z.string().optional().describe('Episode description'),
|
|
7
|
-
title: z.string().optional().describe('Episode title'),
|
|
8
|
-
slug: z.string().optional().describe('Episode slug'),
|
|
9
|
-
});
|
|
10
|
-
export async function episodeUpdate(args, tracker) {
|
|
11
|
-
try {
|
|
12
|
-
const existing = await tracker.getEpisode(args.timeline, args.arc, args.episode);
|
|
13
|
-
if (!existing) {
|
|
14
|
-
throw new Error(`Episode not found: ${args.timeline}/${args.arc}/ep${args.episode}`);
|
|
15
|
-
}
|
|
16
|
-
const updateData = {};
|
|
17
|
-
if (args.description !== undefined)
|
|
18
|
-
updateData.description = args.description;
|
|
19
|
-
if (args.title !== undefined)
|
|
20
|
-
updateData.title = args.title;
|
|
21
|
-
if (args.slug !== undefined)
|
|
22
|
-
updateData.slug = args.slug;
|
|
23
|
-
await tracker.updateEpisode(args.timeline, args.arc, args.episode, updateData);
|
|
24
|
-
return {
|
|
25
|
-
content: [
|
|
26
|
-
{
|
|
27
|
-
type: 'text',
|
|
28
|
-
text: JSON.stringify({
|
|
29
|
-
timeline: args.timeline,
|
|
30
|
-
arc: args.arc,
|
|
31
|
-
episode: args.episode,
|
|
32
|
-
updated: updateData,
|
|
33
|
-
message: 'Episode successfully updated',
|
|
34
|
-
}, null, 2),
|
|
35
|
-
},
|
|
36
|
-
],
|
|
37
|
-
};
|
|
38
|
-
}
|
|
39
|
-
catch (error) {
|
|
40
|
-
throw new Error(`Failed to update episode: ${error instanceof Error ? error.message : 'Unknown error'}`);
|
|
41
|
-
}
|
|
42
|
-
}
|
package/lib/tools/index.d.ts
DELETED
|
@@ -1,14 +0,0 @@
|
|
|
1
|
-
export { bookGenerate, bookGenerateSchema } from './book-generate.js';
|
|
2
|
-
export { chapterDelete, chapterDeleteSchema } from './chapter-delete.js';
|
|
3
|
-
export { chapterInfo, chapterInfoSchema } from './chapter-info.js';
|
|
4
|
-
export { chapterInsert, chapterInsertSchema } from './chapter-insert.js';
|
|
5
|
-
export { chapterRefresh, chapterRefreshSchema } from './chapter-refresh.js';
|
|
6
|
-
export { episodeInfo, episodeInfoSchema } from './episode-info.js';
|
|
7
|
-
export { episodeUpdate, episodeUpdateSchema } from './episode-update.js';
|
|
8
|
-
export { ragCharacters, ragCharactersSchema } from './rag-characters.js';
|
|
9
|
-
export { ragContext, ragContextSchema } from './rag-context.js';
|
|
10
|
-
export { ragIndex, ragIndexSchema } from './rag-index.js';
|
|
11
|
-
export { ragSearch, ragSearchSchema } from './rag-search.js';
|
|
12
|
-
export { stats, statsSchema } from './stats.js';
|
|
13
|
-
export { timelineSync, timelineSyncSchema } from './timeline-sync.js';
|
|
14
|
-
export { wordsCount, wordsCountSchema } from './words-count.js';
|
package/lib/tools/index.js
DELETED
|
@@ -1,14 +0,0 @@
|
|
|
1
|
-
export { bookGenerate, bookGenerateSchema } from './book-generate.js';
|
|
2
|
-
export { chapterDelete, chapterDeleteSchema } from './chapter-delete.js';
|
|
3
|
-
export { chapterInfo, chapterInfoSchema } from './chapter-info.js';
|
|
4
|
-
export { chapterInsert, chapterInsertSchema } from './chapter-insert.js';
|
|
5
|
-
export { chapterRefresh, chapterRefreshSchema } from './chapter-refresh.js';
|
|
6
|
-
export { episodeInfo, episodeInfoSchema } from './episode-info.js';
|
|
7
|
-
export { episodeUpdate, episodeUpdateSchema } from './episode-update.js';
|
|
8
|
-
export { ragCharacters, ragCharactersSchema } from './rag-characters.js';
|
|
9
|
-
export { ragContext, ragContextSchema } from './rag-context.js';
|
|
10
|
-
export { ragIndex, ragIndexSchema } from './rag-index.js';
|
|
11
|
-
export { ragSearch, ragSearchSchema } from './rag-search.js';
|
|
12
|
-
export { stats, statsSchema } from './stats.js';
|
|
13
|
-
export { timelineSync, timelineSyncSchema } from './timeline-sync.js';
|
|
14
|
-
export { wordsCount, wordsCountSchema } from './words-count.js';
|
|
@@ -1,12 +0,0 @@
|
|
|
1
|
-
import type { RAGSystem } from '@echoes-io/rag';
|
|
2
|
-
import { z } from 'zod';
|
|
3
|
-
export declare const ragCharactersSchema: z.ZodObject<{
|
|
4
|
-
timeline: z.ZodString;
|
|
5
|
-
character: z.ZodString;
|
|
6
|
-
}, z.core.$strip>;
|
|
7
|
-
export declare function ragCharacters(args: z.infer<typeof ragCharactersSchema>, rag: RAGSystem): Promise<{
|
|
8
|
-
content: {
|
|
9
|
-
type: "text";
|
|
10
|
-
text: string;
|
|
11
|
-
}[];
|
|
12
|
-
}>;
|
|
@@ -1,26 +0,0 @@
|
|
|
1
|
-
import { z } from 'zod';
|
|
2
|
-
export const ragCharactersSchema = z.object({
|
|
3
|
-
timeline: z.string().describe('Timeline name'),
|
|
4
|
-
character: z.string().describe('Character name to find co-occurrences for'),
|
|
5
|
-
});
|
|
6
|
-
export async function ragCharacters(args, rag) {
|
|
7
|
-
try {
|
|
8
|
-
const characters = await rag.getCharacterMentions(args.character);
|
|
9
|
-
return {
|
|
10
|
-
content: [
|
|
11
|
-
{
|
|
12
|
-
type: 'text',
|
|
13
|
-
text: JSON.stringify({
|
|
14
|
-
character: args.character,
|
|
15
|
-
timeline: args.timeline,
|
|
16
|
-
coOccurringCharacters: characters.filter((c) => c !== args.character).sort(),
|
|
17
|
-
total: characters.length - 1,
|
|
18
|
-
}, null, 2),
|
|
19
|
-
},
|
|
20
|
-
],
|
|
21
|
-
};
|
|
22
|
-
}
|
|
23
|
-
catch (error) {
|
|
24
|
-
throw new Error(`Failed to get character mentions: ${error instanceof Error ? error.message : 'Unknown error'}`);
|
|
25
|
-
}
|
|
26
|
-
}
|
|
@@ -1,16 +0,0 @@
|
|
|
1
|
-
import type { RAGSystem } from '@echoes-io/rag';
|
|
2
|
-
import { z } from 'zod';
|
|
3
|
-
export declare const ragContextSchema: z.ZodObject<{
|
|
4
|
-
timeline: z.ZodString;
|
|
5
|
-
query: z.ZodString;
|
|
6
|
-
arc: z.ZodOptional<z.ZodString>;
|
|
7
|
-
pov: z.ZodOptional<z.ZodString>;
|
|
8
|
-
maxChapters: z.ZodOptional<z.ZodNumber>;
|
|
9
|
-
characters: z.ZodOptional<z.ZodArray<z.ZodString>>;
|
|
10
|
-
}, z.core.$strip>;
|
|
11
|
-
export declare function ragContext(args: z.infer<typeof ragContextSchema>, rag: RAGSystem): Promise<{
|
|
12
|
-
content: {
|
|
13
|
-
type: "text";
|
|
14
|
-
text: string;
|
|
15
|
-
}[];
|
|
16
|
-
}>;
|
package/lib/tools/rag-context.js
DELETED
|
@@ -1,54 +0,0 @@
|
|
|
1
|
-
import { z } from 'zod';
|
|
2
|
-
export const ragContextSchema = z.object({
|
|
3
|
-
timeline: z.string().describe('Timeline name'),
|
|
4
|
-
query: z.string().describe('Context query'),
|
|
5
|
-
arc: z.string().optional().describe('Filter by arc name'),
|
|
6
|
-
pov: z.string().optional().describe('Filter by POV character'),
|
|
7
|
-
maxChapters: z.number().optional().describe('Maximum number of chapters (default: 5)'),
|
|
8
|
-
characters: z
|
|
9
|
-
.array(z.string())
|
|
10
|
-
.optional()
|
|
11
|
-
.describe('Filter by character names present in chapter'),
|
|
12
|
-
});
|
|
13
|
-
export async function ragContext(args, rag) {
|
|
14
|
-
try {
|
|
15
|
-
const results = await rag.getContext({
|
|
16
|
-
query: args.query,
|
|
17
|
-
timeline: args.timeline,
|
|
18
|
-
arc: args.arc,
|
|
19
|
-
pov: args.pov,
|
|
20
|
-
maxChapters: args.maxChapters,
|
|
21
|
-
characters: args.characters,
|
|
22
|
-
});
|
|
23
|
-
return {
|
|
24
|
-
content: [
|
|
25
|
-
{
|
|
26
|
-
type: 'text',
|
|
27
|
-
text: JSON.stringify({
|
|
28
|
-
query: args.query,
|
|
29
|
-
timeline: args.timeline,
|
|
30
|
-
filters: {
|
|
31
|
-
arc: args.arc || null,
|
|
32
|
-
pov: args.pov || null,
|
|
33
|
-
},
|
|
34
|
-
context: results.map((r) => ({
|
|
35
|
-
chapter: {
|
|
36
|
-
arc: r.metadata.arcName,
|
|
37
|
-
episode: r.metadata.episodeNumber,
|
|
38
|
-
chapter: r.metadata.number,
|
|
39
|
-
pov: r.metadata.pov,
|
|
40
|
-
title: r.metadata.title,
|
|
41
|
-
characters: r.metadata.characterNames || [],
|
|
42
|
-
},
|
|
43
|
-
similarity: r.similarity,
|
|
44
|
-
content: r.content,
|
|
45
|
-
})),
|
|
46
|
-
}, null, 2),
|
|
47
|
-
},
|
|
48
|
-
],
|
|
49
|
-
};
|
|
50
|
-
}
|
|
51
|
-
catch (error) {
|
|
52
|
-
throw new Error(`Failed to get context: ${error instanceof Error ? error.message : 'Unknown error'}`);
|
|
53
|
-
}
|
|
54
|
-
}
|
package/lib/tools/rag-index.d.ts
DELETED
|
@@ -1,18 +0,0 @@
|
|
|
1
|
-
import type { RAGSystem } from '@echoes-io/rag';
|
|
2
|
-
import type { Tracker } from '@echoes-io/tracker';
|
|
3
|
-
import { z } from 'zod';
|
|
4
|
-
export declare const ragIndexSchema: z.ZodObject<{
|
|
5
|
-
timeline: z.ZodString;
|
|
6
|
-
arc: z.ZodOptional<z.ZodString>;
|
|
7
|
-
episode: z.ZodOptional<z.ZodNumber>;
|
|
8
|
-
}, z.core.$strip>;
|
|
9
|
-
type RagIndexArgs = z.infer<typeof ragIndexSchema> & {
|
|
10
|
-
contentPath: string;
|
|
11
|
-
};
|
|
12
|
-
export declare function ragIndex(args: RagIndexArgs, tracker: Tracker, rag: RAGSystem): Promise<{
|
|
13
|
-
content: {
|
|
14
|
-
type: "text";
|
|
15
|
-
text: string;
|
|
16
|
-
}[];
|
|
17
|
-
}>;
|
|
18
|
-
export {};
|
package/lib/tools/rag-index.js
DELETED
|
@@ -1,89 +0,0 @@
|
|
|
1
|
-
import { readdirSync, readFileSync } from 'node:fs';
|
|
2
|
-
import { join } from 'node:path';
|
|
3
|
-
import { parseMarkdown } from '@echoes-io/utils';
|
|
4
|
-
import { z } from 'zod';
|
|
5
|
-
export const ragIndexSchema = z.object({
|
|
6
|
-
timeline: z.string().describe('Timeline name'),
|
|
7
|
-
arc: z.string().optional().describe('Index specific arc only'),
|
|
8
|
-
episode: z.number().optional().describe('Index specific episode only (requires arc)'),
|
|
9
|
-
});
|
|
10
|
-
export async function ragIndex(args, tracker, rag) {
|
|
11
|
-
try {
|
|
12
|
-
let chapters = [];
|
|
13
|
-
// Get chapters based on filters
|
|
14
|
-
if (args.arc && args.episode) {
|
|
15
|
-
chapters = await tracker.getChapters(args.timeline, args.arc, args.episode);
|
|
16
|
-
}
|
|
17
|
-
else if (args.arc) {
|
|
18
|
-
const episodes = await tracker.getEpisodes(args.timeline, args.arc);
|
|
19
|
-
for (const ep of episodes) {
|
|
20
|
-
const epChapters = await tracker.getChapters(args.timeline, args.arc, ep.number);
|
|
21
|
-
chapters.push(...epChapters);
|
|
22
|
-
}
|
|
23
|
-
}
|
|
24
|
-
else {
|
|
25
|
-
const arcs = await tracker.getArcs(args.timeline);
|
|
26
|
-
for (const arc of arcs) {
|
|
27
|
-
const episodes = await tracker.getEpisodes(args.timeline, arc.name);
|
|
28
|
-
for (const ep of episodes) {
|
|
29
|
-
const epChapters = await tracker.getChapters(args.timeline, arc.name, ep.number);
|
|
30
|
-
chapters.push(...epChapters);
|
|
31
|
-
}
|
|
32
|
-
}
|
|
33
|
-
}
|
|
34
|
-
// Convert to embedding format and add to RAG
|
|
35
|
-
const embeddingChapters = chapters
|
|
36
|
-
.map((ch) => {
|
|
37
|
-
// Read actual file content
|
|
38
|
-
try {
|
|
39
|
-
// Find episode directory
|
|
40
|
-
const episodeDir = `ep${String(ch.episodeNumber).padStart(2, '0')}`;
|
|
41
|
-
const arcPath = join(args.contentPath, ch.arcName);
|
|
42
|
-
const episodePath = readdirSync(arcPath, { withFileTypes: true })
|
|
43
|
-
.filter((e) => e.isDirectory() && e.name.startsWith(episodeDir))
|
|
44
|
-
.map((e) => join(arcPath, e.name))[0];
|
|
45
|
-
if (!episodePath) {
|
|
46
|
-
console.error(`Episode directory not found for ${ch.arcName}/ep${ch.episodeNumber}`);
|
|
47
|
-
return null;
|
|
48
|
-
}
|
|
49
|
-
// Find chapter file by episode and chapter number (filename-agnostic for title/pov)
|
|
50
|
-
const chapterPattern = `ep${String(ch.episodeNumber).padStart(2, '0')}-ch${String(ch.number).padStart(3, '0')}-`;
|
|
51
|
-
const chapterFiles = readdirSync(episodePath).filter((f) => f.startsWith(chapterPattern) && f.endsWith('.md'));
|
|
52
|
-
if (chapterFiles.length === 0) {
|
|
53
|
-
console.error(`Chapter file not found for ${ch.arcName}/ep${ch.episodeNumber}/ch${ch.number}`);
|
|
54
|
-
return null;
|
|
55
|
-
}
|
|
56
|
-
const filePath = join(episodePath, chapterFiles[0]);
|
|
57
|
-
const fileContent = readFileSync(filePath, 'utf-8');
|
|
58
|
-
const { content } = parseMarkdown(fileContent);
|
|
59
|
-
return {
|
|
60
|
-
id: `${ch.timelineName}-${ch.arcName}-${ch.episodeNumber}-${ch.number}`,
|
|
61
|
-
metadata: ch,
|
|
62
|
-
content,
|
|
63
|
-
};
|
|
64
|
-
}
|
|
65
|
-
catch (error) {
|
|
66
|
-
console.error(`Error reading chapter ${ch.arcName}/ep${ch.episodeNumber}/ch${ch.number}:`, error);
|
|
67
|
-
return null;
|
|
68
|
-
}
|
|
69
|
-
})
|
|
70
|
-
.filter((ch) => ch !== null);
|
|
71
|
-
await rag.addChapters(embeddingChapters);
|
|
72
|
-
return {
|
|
73
|
-
content: [
|
|
74
|
-
{
|
|
75
|
-
type: 'text',
|
|
76
|
-
text: JSON.stringify({
|
|
77
|
-
indexed: embeddingChapters.length,
|
|
78
|
-
timeline: args.timeline,
|
|
79
|
-
arc: args.arc || 'all',
|
|
80
|
-
episode: args.episode || 'all',
|
|
81
|
-
}, null, 2),
|
|
82
|
-
},
|
|
83
|
-
],
|
|
84
|
-
};
|
|
85
|
-
}
|
|
86
|
-
catch (error) {
|
|
87
|
-
throw new Error(`Failed to index chapters: ${error instanceof Error ? error.message : 'Unknown error'}`);
|
|
88
|
-
}
|
|
89
|
-
}
|
|
@@ -1,17 +0,0 @@
|
|
|
1
|
-
import type { RAGSystem } from '@echoes-io/rag';
|
|
2
|
-
import { z } from 'zod';
|
|
3
|
-
export declare const ragSearchSchema: z.ZodObject<{
|
|
4
|
-
timeline: z.ZodString;
|
|
5
|
-
query: z.ZodString;
|
|
6
|
-
arc: z.ZodOptional<z.ZodString>;
|
|
7
|
-
pov: z.ZodOptional<z.ZodString>;
|
|
8
|
-
maxResults: z.ZodOptional<z.ZodNumber>;
|
|
9
|
-
characters: z.ZodOptional<z.ZodArray<z.ZodString>>;
|
|
10
|
-
allCharacters: z.ZodOptional<z.ZodBoolean>;
|
|
11
|
-
}, z.core.$strip>;
|
|
12
|
-
export declare function ragSearch(args: z.infer<typeof ragSearchSchema>, rag: RAGSystem): Promise<{
|
|
13
|
-
content: {
|
|
14
|
-
type: "text";
|
|
15
|
-
text: string;
|
|
16
|
-
}[];
|
|
17
|
-
}>;
|
package/lib/tools/rag-search.js
DELETED
|
@@ -1,58 +0,0 @@
|
|
|
1
|
-
import { z } from 'zod';
|
|
2
|
-
export const ragSearchSchema = z.object({
|
|
3
|
-
timeline: z.string().describe('Timeline name'),
|
|
4
|
-
query: z.string().describe('Search query'),
|
|
5
|
-
arc: z.string().optional().describe('Filter by arc name'),
|
|
6
|
-
pov: z.string().optional().describe('Filter by POV character'),
|
|
7
|
-
maxResults: z.number().optional().describe('Maximum number of results (default: 10)'),
|
|
8
|
-
characters: z
|
|
9
|
-
.array(z.string())
|
|
10
|
-
.optional()
|
|
11
|
-
.describe('Filter by character names present in chapter'),
|
|
12
|
-
allCharacters: z
|
|
13
|
-
.boolean()
|
|
14
|
-
.optional()
|
|
15
|
-
.describe('If true, all characters must be present (AND). If false, at least one (OR). Default: false'),
|
|
16
|
-
});
|
|
17
|
-
export async function ragSearch(args, rag) {
|
|
18
|
-
try {
|
|
19
|
-
const results = await rag.search(args.query, {
|
|
20
|
-
timeline: args.timeline,
|
|
21
|
-
arc: args.arc,
|
|
22
|
-
pov: args.pov,
|
|
23
|
-
maxResults: args.maxResults,
|
|
24
|
-
characters: args.characters,
|
|
25
|
-
allCharacters: args.allCharacters,
|
|
26
|
-
});
|
|
27
|
-
return {
|
|
28
|
-
content: [
|
|
29
|
-
{
|
|
30
|
-
type: 'text',
|
|
31
|
-
text: JSON.stringify({
|
|
32
|
-
query: args.query,
|
|
33
|
-
timeline: args.timeline,
|
|
34
|
-
filters: {
|
|
35
|
-
arc: args.arc || null,
|
|
36
|
-
pov: args.pov || null,
|
|
37
|
-
},
|
|
38
|
-
results: results.map((r) => ({
|
|
39
|
-
chapter: {
|
|
40
|
-
arc: r.metadata.arcName,
|
|
41
|
-
episode: r.metadata.episodeNumber,
|
|
42
|
-
chapter: r.metadata.number,
|
|
43
|
-
pov: r.metadata.pov,
|
|
44
|
-
title: r.metadata.title,
|
|
45
|
-
characters: r.metadata.characterNames || [],
|
|
46
|
-
},
|
|
47
|
-
similarity: r.similarity,
|
|
48
|
-
preview: `${r.content.substring(0, 200)}...`,
|
|
49
|
-
})),
|
|
50
|
-
}, null, 2),
|
|
51
|
-
},
|
|
52
|
-
],
|
|
53
|
-
};
|
|
54
|
-
}
|
|
55
|
-
catch (error) {
|
|
56
|
-
throw new Error(`Failed to search: ${error instanceof Error ? error.message : 'Unknown error'}`);
|
|
57
|
-
}
|
|
58
|
-
}
|
package/lib/tools/stats.d.ts
DELETED
|
@@ -1,14 +0,0 @@
|
|
|
1
|
-
import type { Tracker } from '@echoes-io/tracker';
|
|
2
|
-
import { z } from 'zod';
|
|
3
|
-
export declare const statsSchema: z.ZodObject<{
|
|
4
|
-
timeline: z.ZodString;
|
|
5
|
-
arc: z.ZodOptional<z.ZodString>;
|
|
6
|
-
episode: z.ZodOptional<z.ZodNumber>;
|
|
7
|
-
pov: z.ZodOptional<z.ZodString>;
|
|
8
|
-
}, z.core.$strip>;
|
|
9
|
-
export declare function stats(args: z.infer<typeof statsSchema>, tracker: Tracker): Promise<{
|
|
10
|
-
content: {
|
|
11
|
-
type: "text";
|
|
12
|
-
text: string;
|
|
13
|
-
}[];
|
|
14
|
-
}>;
|