zenn-rag 0.1.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.
Files changed (79) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +221 -0
  3. package/dist/cli.d.ts +3 -0
  4. package/dist/cli.d.ts.map +1 -0
  5. package/dist/cli.js +68 -0
  6. package/dist/cli.js.map +1 -0
  7. package/dist/commands/index.d.ts +6 -0
  8. package/dist/commands/index.d.ts.map +1 -0
  9. package/dist/commands/index.js +11 -0
  10. package/dist/commands/index.js.map +1 -0
  11. package/dist/commands/mcp.d.ts +2 -0
  12. package/dist/commands/mcp.d.ts.map +1 -0
  13. package/dist/commands/mcp.js +245 -0
  14. package/dist/commands/mcp.js.map +1 -0
  15. package/dist/commands/search.d.ts +10 -0
  16. package/dist/commands/search.d.ts.map +1 -0
  17. package/dist/commands/search.js +37 -0
  18. package/dist/commands/search.js.map +1 -0
  19. package/dist/commands/status.d.ts +2 -0
  20. package/dist/commands/status.d.ts.map +1 -0
  21. package/dist/commands/status.js +111 -0
  22. package/dist/commands/status.js.map +1 -0
  23. package/dist/config.d.ts +28 -0
  24. package/dist/config.d.ts.map +1 -0
  25. package/dist/config.js +88 -0
  26. package/dist/config.js.map +1 -0
  27. package/dist/embedder.d.ts +17 -0
  28. package/dist/embedder.d.ts.map +1 -0
  29. package/dist/embedder.js +31 -0
  30. package/dist/embedder.js.map +1 -0
  31. package/dist/index.d.ts +12 -0
  32. package/dist/index.d.ts.map +1 -0
  33. package/dist/index.js +12 -0
  34. package/dist/index.js.map +1 -0
  35. package/dist/logger.d.ts +31 -0
  36. package/dist/logger.d.ts.map +1 -0
  37. package/dist/logger.js +56 -0
  38. package/dist/logger.js.map +1 -0
  39. package/dist/parser.d.ts +56 -0
  40. package/dist/parser.d.ts.map +1 -0
  41. package/dist/parser.js +214 -0
  42. package/dist/parser.js.map +1 -0
  43. package/dist/providers/base.d.ts +2 -0
  44. package/dist/providers/base.d.ts.map +1 -0
  45. package/dist/providers/base.js +4 -0
  46. package/dist/providers/base.js.map +1 -0
  47. package/dist/providers/factory.d.ts +4 -0
  48. package/dist/providers/factory.d.ts.map +1 -0
  49. package/dist/providers/factory.js +27 -0
  50. package/dist/providers/factory.js.map +1 -0
  51. package/dist/providers/gemini.d.ts +20 -0
  52. package/dist/providers/gemini.d.ts.map +1 -0
  53. package/dist/providers/gemini.js +79 -0
  54. package/dist/providers/gemini.js.map +1 -0
  55. package/dist/providers/ollama.d.ts +14 -0
  56. package/dist/providers/ollama.d.ts.map +1 -0
  57. package/dist/providers/ollama.js +38 -0
  58. package/dist/providers/ollama.js.map +1 -0
  59. package/dist/providers/openai.d.ts +18 -0
  60. package/dist/providers/openai.d.ts.map +1 -0
  61. package/dist/providers/openai.js +65 -0
  62. package/dist/providers/openai.js.map +1 -0
  63. package/dist/providers/types.d.ts +7 -0
  64. package/dist/providers/types.d.ts.map +1 -0
  65. package/dist/providers/types.js +2 -0
  66. package/dist/providers/types.js.map +1 -0
  67. package/dist/services/sync-service.d.ts +28 -0
  68. package/dist/services/sync-service.d.ts.map +1 -0
  69. package/dist/services/sync-service.js +310 -0
  70. package/dist/services/sync-service.js.map +1 -0
  71. package/dist/store.d.ts +35 -0
  72. package/dist/store.d.ts.map +1 -0
  73. package/dist/store.js +180 -0
  74. package/dist/store.js.map +1 -0
  75. package/dist/types.d.ts +49 -0
  76. package/dist/types.d.ts.map +1 -0
  77. package/dist/types.js +2 -0
  78. package/dist/types.js.map +1 -0
  79. package/package.json +61 -0
package/dist/parser.js ADDED
@@ -0,0 +1,214 @@
1
+ import crypto from "node:crypto";
2
+ import fs from "node:fs/promises";
3
+ import path from "node:path";
4
+ import matter from "gray-matter";
5
+ import { getArticleUrl, getBookChapterUrl } from "./config.js";
6
+ export function computeHash(content) {
7
+ return crypto.createHash("md5").update(content, "utf8").digest("hex");
8
+ }
9
+ /**
10
+ * Markdownを見出し単位でセクションに分割する
11
+ */
12
+ export function splitMarkdownIntoSections(markdown) {
13
+ const lines = markdown.split(/\r?\n/);
14
+ const sections = [];
15
+ const headingStack = [];
16
+ let currentLines = [];
17
+ let currentHeading = "イントロダクション";
18
+ function saveCurrentSection() {
19
+ const text = currentLines.join("\n").trim();
20
+ if (text.length > 0) {
21
+ sections.push({
22
+ heading: currentHeading,
23
+ text,
24
+ });
25
+ }
26
+ currentLines = [];
27
+ }
28
+ for (const line of lines) {
29
+ const headingMatch = line.match(/^(#{1,4})\s+(.+)$/);
30
+ if (headingMatch) {
31
+ saveCurrentSection();
32
+ const level = headingMatch[1].length;
33
+ const title = headingMatch[2].trim();
34
+ while (headingStack.length > 0 &&
35
+ headingStack[headingStack.length - 1].level >= level) {
36
+ headingStack.pop();
37
+ }
38
+ headingStack.push({ level, text: title });
39
+ currentHeading = headingStack.map((h) => h.text).join(" > ");
40
+ }
41
+ else {
42
+ currentLines.push(line);
43
+ }
44
+ }
45
+ saveCurrentSection();
46
+ return sections;
47
+ }
48
+ /**
49
+ * コードブロック(``` または ~~~)を保護しながら段落に分割する
50
+ */
51
+ export function extractParagraphs(text) {
52
+ const lines = text.split(/\r?\n/);
53
+ const paragraphs = [];
54
+ let currentParagraphLines = [];
55
+ let inCodeFence = false;
56
+ let codeFenceMarker = "";
57
+ for (const line of lines) {
58
+ const trimmed = line.trim();
59
+ const fenceMatch = trimmed.match(/^(`{3,}|~{3,})/);
60
+ if (fenceMatch) {
61
+ const marker = fenceMatch[1][0]; // '`' or '~'
62
+ if (!inCodeFence) {
63
+ inCodeFence = true;
64
+ codeFenceMarker = marker;
65
+ }
66
+ else if (marker === codeFenceMarker) {
67
+ inCodeFence = false;
68
+ codeFenceMarker = "";
69
+ }
70
+ }
71
+ if (!inCodeFence && trimmed === "") {
72
+ if (currentParagraphLines.length > 0) {
73
+ paragraphs.push(currentParagraphLines.join("\n"));
74
+ currentParagraphLines = [];
75
+ }
76
+ }
77
+ else {
78
+ currentParagraphLines.push(line);
79
+ }
80
+ }
81
+ if (currentParagraphLines.length > 0) {
82
+ paragraphs.push(currentParagraphLines.join("\n"));
83
+ }
84
+ return paragraphs;
85
+ }
86
+ export function splitSectionIfLong(text, maxChars = 2000) {
87
+ if (text.length <= maxChars) {
88
+ return [text];
89
+ }
90
+ const paragraphs = extractParagraphs(text);
91
+ const chunks = [];
92
+ let current = "";
93
+ for (const p of paragraphs) {
94
+ if ((current + "\n\n" + p).length > maxChars && current.length > 0) {
95
+ chunks.push(current.trim());
96
+ current = p;
97
+ }
98
+ else {
99
+ current = current.length > 0 ? `${current}\n\n${p}` : p;
100
+ }
101
+ }
102
+ if (current.trim().length > 0) {
103
+ chunks.push(current.trim());
104
+ }
105
+ return chunks;
106
+ }
107
+ /**
108
+ * Markdown文字列をパースしてArticleChunk配列に変換する純粋関数
109
+ */
110
+ export function parseArticle(rawContent, slug, options) {
111
+ const fileHash = computeHash(rawContent);
112
+ const parsed = matter(rawContent);
113
+ const frontmatter = parsed.data;
114
+ const title = frontmatter.title || slug;
115
+ const topics = Array.isArray(frontmatter.topics) ? frontmatter.topics : [];
116
+ const articleUrl = options?.articleUrl ?? getArticleUrl(slug);
117
+ const sections = splitMarkdownIntoSections(parsed.content);
118
+ const chunks = [];
119
+ let chunkIndex = 0;
120
+ for (const section of sections) {
121
+ const subTexts = splitSectionIfLong(section.text);
122
+ for (let i = 0; i < subTexts.length; i++) {
123
+ const text = subTexts[i];
124
+ const partSuffix = subTexts.length > 1 ? ` (Part ${i + 1})` : "";
125
+ const headingWithPart = `${section.heading}${partSuffix}`;
126
+ const vectorText = [
127
+ `記事タイトル: ${title}`,
128
+ topics.length > 0 ? `トピック: ${topics.join(", ")}` : null,
129
+ `見出し: ${headingWithPart}`,
130
+ "",
131
+ text,
132
+ ]
133
+ .filter(Boolean)
134
+ .join("\n");
135
+ chunks.push({
136
+ id: `${slug}#chunk_${chunkIndex++}`,
137
+ slug,
138
+ title,
139
+ topics,
140
+ heading: headingWithPart,
141
+ text,
142
+ vectorText,
143
+ url: articleUrl,
144
+ contentHash: computeHash(text),
145
+ itemType: "article",
146
+ });
147
+ }
148
+ }
149
+ return { slug, frontmatter, chunks, fileHash };
150
+ }
151
+ /**
152
+ * 1つの記事Markdownファイルを読み込んでパースし、複数のArticleChunkに変換する
153
+ */
154
+ export async function parseArticleFile(filePath, options) {
155
+ const rawContent = await fs.readFile(filePath, "utf-8");
156
+ const slug = path.basename(filePath, path.extname(filePath));
157
+ return parseArticle(rawContent, slug, options);
158
+ }
159
+ /**
160
+ * Zennの本(Books)の1チャプターをパースしてArticleChunk配列に変換する純粋関数
161
+ */
162
+ export function parseBookChapter(rawContent, bookSlug, chapterSlug, options) {
163
+ const fileHash = computeHash(rawContent);
164
+ const parsed = matter(rawContent);
165
+ const frontmatter = parsed.data;
166
+ const title = frontmatter.title || chapterSlug;
167
+ const topics = Array.isArray(frontmatter.topics) ? frontmatter.topics : [];
168
+ const fullSlug = `${bookSlug}/${chapterSlug}`;
169
+ const chapterUrl = options?.articleUrl ?? getBookChapterUrl(bookSlug, chapterSlug);
170
+ const sections = splitMarkdownIntoSections(parsed.content);
171
+ const chunks = [];
172
+ let chunkIndex = 0;
173
+ for (const section of sections) {
174
+ const subTexts = splitSectionIfLong(section.text);
175
+ for (let i = 0; i < subTexts.length; i++) {
176
+ const text = subTexts[i];
177
+ const partSuffix = subTexts.length > 1 ? ` (Part ${i + 1})` : "";
178
+ const headingWithPart = `${section.heading}${partSuffix}`;
179
+ const vectorText = [
180
+ `本: ${bookSlug}`,
181
+ `チャプター: ${title}`,
182
+ topics.length > 0 ? `トピック: ${topics.join(", ")}` : null,
183
+ `見出し: ${headingWithPart}`,
184
+ "",
185
+ text,
186
+ ]
187
+ .filter(Boolean)
188
+ .join("\n");
189
+ chunks.push({
190
+ id: `${fullSlug}#chunk_${chunkIndex++}`,
191
+ slug: fullSlug,
192
+ title: `${bookSlug}: ${title}`,
193
+ topics,
194
+ heading: headingWithPart,
195
+ text,
196
+ vectorText,
197
+ url: chapterUrl,
198
+ contentHash: computeHash(text),
199
+ itemType: "book",
200
+ bookSlug,
201
+ });
202
+ }
203
+ }
204
+ return { slug: fullSlug, frontmatter, chunks, fileHash, bookSlug };
205
+ }
206
+ /**
207
+ * 本のチャプターファイルを読み込んでパースする
208
+ */
209
+ export async function parseBookChapterFile(filePath, bookSlug, options) {
210
+ const rawContent = await fs.readFile(filePath, "utf-8");
211
+ const chapterSlug = path.basename(filePath, path.extname(filePath));
212
+ return parseBookChapter(rawContent, bookSlug, chapterSlug, options);
213
+ }
214
+ //# sourceMappingURL=parser.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"parser.js","sourceRoot":"","sources":["../src/parser.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,2 @@
1
+ export declare function sleep(ms: number): Promise<void>;
2
+ //# sourceMappingURL=base.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"base.d.ts","sourceRoot":"","sources":["../../src/providers/base.ts"],"names":[],"mappings":"AAAA,wBAAgB,KAAK,CAAC,EAAE,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAE/C"}
@@ -0,0 +1,4 @@
1
+ export function sleep(ms) {
2
+ return new Promise((resolve) => setTimeout(resolve, ms));
3
+ }
4
+ //# sourceMappingURL=base.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"base.js","sourceRoot":"","sources":["../../src/providers/base.ts"],"names":[],"mappings":"AAAA,MAAM,UAAU,KAAK,CAAC,EAAU;IAC9B,OAAO,IAAI,OAAO,CAAC,CAAC,OAAO,EAAE,EAAE,CAAC,UAAU,CAAC,OAAO,EAAE,EAAE,CAAC,CAAC,CAAC;AAC3D,CAAC"}
@@ -0,0 +1,4 @@
1
+ import { type RagContext } from "../config.js";
2
+ import type { IEmbeddingProvider } from "./types.js";
3
+ export declare function createEmbeddingProvider(customCtx?: RagContext): IEmbeddingProvider;
4
+ //# sourceMappingURL=factory.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"factory.d.ts","sourceRoot":"","sources":["../../src/providers/factory.ts"],"names":[],"mappings":"AAAA,OAAO,EAAc,KAAK,UAAU,EAAE,MAAM,cAAc,CAAC;AAI3D,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,YAAY,CAAC;AAErD,wBAAgB,uBAAuB,CACrC,SAAS,CAAC,EAAE,UAAU,GACrB,kBAAkB,CAwBpB"}
@@ -0,0 +1,27 @@
1
+ import { getContext } from "../config.js";
2
+ import { GeminiEmbeddingProvider } from "./gemini.js";
3
+ import { OllamaEmbeddingProvider } from "./ollama.js";
4
+ import { OpenAIEmbeddingProvider } from "./openai.js";
5
+ export function createEmbeddingProvider(customCtx) {
6
+ const ctx = customCtx ?? getContext();
7
+ switch (ctx.provider) {
8
+ case "openai":
9
+ return new OpenAIEmbeddingProvider({
10
+ apiKey: ctx.openaiApiKey,
11
+ model: ctx.openaiModel,
12
+ baseUrl: ctx.openaiBaseUrl,
13
+ });
14
+ case "ollama":
15
+ return new OllamaEmbeddingProvider({
16
+ baseUrl: ctx.ollamaBaseUrl,
17
+ model: ctx.ollamaModel,
18
+ });
19
+ case "gemini":
20
+ default:
21
+ return new GeminiEmbeddingProvider({
22
+ apiKey: ctx.geminiApiKey,
23
+ model: ctx.geminiModel,
24
+ });
25
+ }
26
+ }
27
+ //# sourceMappingURL=factory.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"factory.js","sourceRoot":"","sources":["../../src/providers/factory.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAmB,MAAM,cAAc,CAAC;AAC3D,OAAO,EAAE,uBAAuB,EAAE,MAAM,aAAa,CAAC;AACtD,OAAO,EAAE,uBAAuB,EAAE,MAAM,aAAa,CAAC;AACtD,OAAO,EAAE,uBAAuB,EAAE,MAAM,aAAa,CAAC;AAGtD,MAAM,UAAU,uBAAuB,CACrC,SAAsB;IAEtB,MAAM,GAAG,GAAG,SAAS,IAAI,UAAU,EAAE,CAAC;IAEtC,QAAQ,GAAG,CAAC,QAAQ,EAAE,CAAC;QACrB,KAAK,QAAQ;YACX,OAAO,IAAI,uBAAuB,CAAC;gBACjC,MAAM,EAAE,GAAG,CAAC,YAAY;gBACxB,KAAK,EAAE,GAAG,CAAC,WAAW;gBACtB,OAAO,EAAE,GAAG,CAAC,aAAa;aAC3B,CAAC,CAAC;QAEL,KAAK,QAAQ;YACX,OAAO,IAAI,uBAAuB,CAAC;gBACjC,OAAO,EAAE,GAAG,CAAC,aAAa;gBAC1B,KAAK,EAAE,GAAG,CAAC,WAAW;aACvB,CAAC,CAAC;QAEL,KAAK,QAAQ,CAAC;QACd;YACE,OAAO,IAAI,uBAAuB,CAAC;gBACjC,MAAM,EAAE,GAAG,CAAC,YAAY;gBACxB,KAAK,EAAE,GAAG,CAAC,WAAW;aACvB,CAAC,CAAC;IACP,CAAC;AACH,CAAC"}
@@ -0,0 +1,20 @@
1
+ import type { IEmbeddingProvider } from "./types.js";
2
+ export interface GeminiProviderOptions {
3
+ apiKey: string;
4
+ model: string;
5
+ maxRetries?: number;
6
+ delayBetweenRequestsMs?: number;
7
+ }
8
+ export declare class GeminiEmbeddingProvider implements IEmbeddingProvider {
9
+ readonly name = "gemini";
10
+ readonly model: string;
11
+ private readonly apiKey;
12
+ private readonly maxRetries;
13
+ private readonly delayBetweenRequestsMs;
14
+ private client;
15
+ constructor(options: GeminiProviderOptions);
16
+ private getClient;
17
+ getEmbedding(text: string): Promise<number[]>;
18
+ getEmbeddings(texts: string[], onProgress?: (completed: number, total: number) => void): Promise<number[][]>;
19
+ }
20
+ //# sourceMappingURL=gemini.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"gemini.d.ts","sourceRoot":"","sources":["../../src/providers/gemini.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,YAAY,CAAC;AAErD,MAAM,WAAW,qBAAqB;IACpC,MAAM,EAAE,MAAM,CAAC;IACf,KAAK,EAAE,MAAM,CAAC;IACd,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,sBAAsB,CAAC,EAAE,MAAM,CAAC;CACjC;AAED,qBAAa,uBAAwB,YAAW,kBAAkB;IAChE,QAAQ,CAAC,IAAI,YAAY;IACzB,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;IACvB,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAS;IAChC,OAAO,CAAC,QAAQ,CAAC,UAAU,CAAS;IACpC,OAAO,CAAC,QAAQ,CAAC,sBAAsB,CAAS;IAChD,OAAO,CAAC,MAAM,CAA4B;IAE1C,YAAY,OAAO,EAAE,qBAAqB,EAYzC;IAED,OAAO,CAAC,SAAS;IAOX,YAAY,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,EAAE,CAAC,CAqDlD;IAEK,aAAa,CACjB,KAAK,EAAE,MAAM,EAAE,EACf,UAAU,CAAC,EAAE,CAAC,SAAS,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,KAAK,IAAI,GACtD,OAAO,CAAC,MAAM,EAAE,EAAE,CAAC,CAgBrB;CACF"}
@@ -0,0 +1,79 @@
1
+ import { GoogleGenAI } from "@google/genai";
2
+ import { sleep } from "./base.js";
3
+ export class GeminiEmbeddingProvider {
4
+ name = "gemini";
5
+ model;
6
+ apiKey;
7
+ maxRetries;
8
+ delayBetweenRequestsMs;
9
+ client = null;
10
+ constructor(options) {
11
+ if (!options.apiKey) {
12
+ throw new Error("GEMINI_API_KEY が設定されていません。\n" +
13
+ ".env に GEMINI_API_KEY=<your-key> を設定するか、\n" +
14
+ "または EMBEDDING_PROVIDER=openai を指定して OPENAI_API_KEY を設定してください。");
15
+ }
16
+ this.apiKey = options.apiKey;
17
+ this.model = options.model;
18
+ this.maxRetries = options.maxRetries ?? 5;
19
+ this.delayBetweenRequestsMs = options.delayBetweenRequestsMs ?? 650;
20
+ }
21
+ getClient() {
22
+ if (!this.client) {
23
+ this.client = new GoogleGenAI({ apiKey: this.apiKey });
24
+ }
25
+ return this.client;
26
+ }
27
+ async getEmbedding(text) {
28
+ const ai = this.getClient();
29
+ for (let attempt = 1; attempt <= this.maxRetries; attempt++) {
30
+ try {
31
+ const response = await ai.models.embedContent({
32
+ model: this.model,
33
+ contents: text,
34
+ });
35
+ const embedding = response.embeddings?.[0]?.values ||
36
+ response
37
+ .embedding?.values;
38
+ if (!embedding || embedding.length === 0) {
39
+ throw new Error("Gemini Embeddingの生成に失敗しました: 空のベクトルが返されました");
40
+ }
41
+ return embedding;
42
+ }
43
+ catch (err) {
44
+ const errorMsg = err instanceof Error ? err.message : String(err);
45
+ const isRateLimit = errorMsg.includes("429") ||
46
+ errorMsg.includes("RESOURCE_EXHAUSTED") ||
47
+ errorMsg.includes("quota");
48
+ if (isRateLimit && attempt <= this.maxRetries) {
49
+ const match = errorMsg.match(/retry in ([0-9.]+)s/i) ||
50
+ errorMsg.match(/retryDelay["':\s]+([0-9.]+)s/i);
51
+ let waitMs = 3000 * Math.pow(1.5, attempt);
52
+ if (match && match[1]) {
53
+ waitMs = Math.ceil(parseFloat(match[1])) * 1000 + 1000;
54
+ }
55
+ console.warn(`\n[Gemini レートリミット待機] Quota制限のため ${Math.round(waitMs / 1000)} 秒待機して再試行します (${attempt}/${this.maxRetries})...`);
56
+ await sleep(waitMs);
57
+ continue;
58
+ }
59
+ throw err;
60
+ }
61
+ }
62
+ throw new Error(`Gemini Embedding生成が ${this.maxRetries} 回の再試行後に失敗しました`);
63
+ }
64
+ async getEmbeddings(texts, onProgress) {
65
+ const results = [];
66
+ for (let i = 0; i < texts.length; i++) {
67
+ const vector = await this.getEmbedding(texts[i]);
68
+ results.push(vector);
69
+ if (onProgress) {
70
+ onProgress(i + 1, texts.length);
71
+ }
72
+ if (i + 1 < texts.length) {
73
+ await sleep(this.delayBetweenRequestsMs);
74
+ }
75
+ }
76
+ return results;
77
+ }
78
+ }
79
+ //# sourceMappingURL=gemini.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"gemini.js","sourceRoot":"","sources":["../../src/providers/gemini.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,14 @@
1
+ import type { IEmbeddingProvider } from "./types.js";
2
+ export interface OllamaProviderOptions {
3
+ baseUrl?: string;
4
+ model: string;
5
+ }
6
+ export declare class OllamaEmbeddingProvider implements IEmbeddingProvider {
7
+ readonly name = "ollama";
8
+ readonly model: string;
9
+ private readonly baseUrl;
10
+ constructor(options: OllamaProviderOptions);
11
+ getEmbedding(text: string): Promise<number[]>;
12
+ getEmbeddings(texts: string[], onProgress?: (completed: number, total: number) => void): Promise<number[][]>;
13
+ }
14
+ //# sourceMappingURL=ollama.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ollama.d.ts","sourceRoot":"","sources":["../../src/providers/ollama.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,YAAY,CAAC;AAErD,MAAM,WAAW,qBAAqB;IACpC,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,KAAK,EAAE,MAAM,CAAC;CACf;AAED,qBAAa,uBAAwB,YAAW,kBAAkB;IAChE,QAAQ,CAAC,IAAI,YAAY;IACzB,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;IACvB,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAS;IAEjC,YAAY,OAAO,EAAE,qBAAqB,EAMzC;IAEK,YAAY,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,EAAE,CAAC,CAkBlD;IAEK,aAAa,CACjB,KAAK,EAAE,MAAM,EAAE,EACf,UAAU,CAAC,EAAE,CAAC,SAAS,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,KAAK,IAAI,GACtD,OAAO,CAAC,MAAM,EAAE,EAAE,CAAC,CAUrB;CACF"}
@@ -0,0 +1,38 @@
1
+ export class OllamaEmbeddingProvider {
2
+ name = "ollama";
3
+ model;
4
+ baseUrl;
5
+ constructor(options) {
6
+ this.model = options.model;
7
+ this.baseUrl = (options.baseUrl || "http://localhost:11434").replace(/\/+$/, "");
8
+ }
9
+ async getEmbedding(text) {
10
+ const url = `${this.baseUrl}/api/embeddings`;
11
+ const res = await fetch(url, {
12
+ method: "POST",
13
+ headers: { "Content-Type": "application/json" },
14
+ body: JSON.stringify({
15
+ model: this.model,
16
+ prompt: text,
17
+ }),
18
+ });
19
+ if (!res.ok) {
20
+ const errorText = await res.text();
21
+ throw new Error(`Ollama Embeddingエラー (${res.status}): ${errorText}`);
22
+ }
23
+ const json = (await res.json());
24
+ return json.embedding;
25
+ }
26
+ async getEmbeddings(texts, onProgress) {
27
+ const results = [];
28
+ for (let i = 0; i < texts.length; i++) {
29
+ const vector = await this.getEmbedding(texts[i]);
30
+ results.push(vector);
31
+ if (onProgress) {
32
+ onProgress(i + 1, texts.length);
33
+ }
34
+ }
35
+ return results;
36
+ }
37
+ }
38
+ //# sourceMappingURL=ollama.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ollama.js","sourceRoot":"","sources":["../../src/providers/ollama.ts"],"names":[],"mappings":"AAOA,MAAM,OAAO,uBAAuB;IACzB,IAAI,GAAG,QAAQ,CAAC;IAChB,KAAK,CAAS;IACN,OAAO,CAAS;IAEjC,YAAY,OAA8B;QACxC,IAAI,CAAC,KAAK,GAAG,OAAO,CAAC,KAAK,CAAC;QAC3B,IAAI,CAAC,OAAO,GAAG,CAAC,OAAO,CAAC,OAAO,IAAI,wBAAwB,CAAC,CAAC,OAAO,CAClE,MAAM,EACN,EAAE,CACH,CAAC;IACJ,CAAC;IAED,KAAK,CAAC,YAAY,CAAC,IAAY;QAC7B,MAAM,GAAG,GAAG,GAAG,IAAI,CAAC,OAAO,iBAAiB,CAAC;QAC7C,MAAM,GAAG,GAAG,MAAM,KAAK,CAAC,GAAG,EAAE;YAC3B,MAAM,EAAE,MAAM;YACd,OAAO,EAAE,EAAE,cAAc,EAAE,kBAAkB,EAAE;YAC/C,IAAI,EAAE,IAAI,CAAC,SAAS,CAAC;gBACnB,KAAK,EAAE,IAAI,CAAC,KAAK;gBACjB,MAAM,EAAE,IAAI;aACb,CAAC;SACH,CAAC,CAAC;QAEH,IAAI,CAAC,GAAG,CAAC,EAAE,EAAE,CAAC;YACZ,MAAM,SAAS,GAAG,MAAM,GAAG,CAAC,IAAI,EAAE,CAAC;YACnC,MAAM,IAAI,KAAK,CAAC,wBAAwB,GAAG,CAAC,MAAM,MAAM,SAAS,EAAE,CAAC,CAAC;QACvE,CAAC;QAED,MAAM,IAAI,GAAG,CAAC,MAAM,GAAG,CAAC,IAAI,EAAE,CAA4B,CAAC;QAC3D,OAAO,IAAI,CAAC,SAAS,CAAC;IACxB,CAAC;IAED,KAAK,CAAC,aAAa,CACjB,KAAe,EACf,UAAuD;QAEvD,MAAM,OAAO,GAAe,EAAE,CAAC;QAC/B,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,KAAK,CAAC,MAAM,EAAE,CAAC,EAAE,EAAE,CAAC;YACtC,MAAM,MAAM,GAAG,MAAM,IAAI,CAAC,YAAY,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC;YACjD,OAAO,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC;YACrB,IAAI,UAAU,EAAE,CAAC;gBACf,UAAU,CAAC,CAAC,GAAG,CAAC,EAAE,KAAK,CAAC,MAAM,CAAC,CAAC;YAClC,CAAC;QACH,CAAC;QACD,OAAO,OAAO,CAAC;IACjB,CAAC;CACF"}
@@ -0,0 +1,18 @@
1
+ import type { IEmbeddingProvider } from "./types.js";
2
+ export interface OpenAIProviderOptions {
3
+ apiKey?: string;
4
+ model: string;
5
+ baseUrl?: string;
6
+ batchSize?: number;
7
+ }
8
+ export declare class OpenAIEmbeddingProvider implements IEmbeddingProvider {
9
+ readonly name = "openai";
10
+ readonly model: string;
11
+ private readonly apiKey;
12
+ private readonly baseUrl;
13
+ private readonly batchSize;
14
+ constructor(options: OpenAIProviderOptions);
15
+ getEmbedding(text: string): Promise<number[]>;
16
+ getEmbeddings(texts: string[], onProgress?: (completed: number, total: number) => void): Promise<number[][]>;
17
+ }
18
+ //# sourceMappingURL=openai.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"openai.d.ts","sourceRoot":"","sources":["../../src/providers/openai.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,YAAY,CAAC;AAErD,MAAM,WAAW,qBAAqB;IACpC,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,KAAK,EAAE,MAAM,CAAC;IACd,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB;AAED,qBAAa,uBAAwB,YAAW,kBAAkB;IAChE,QAAQ,CAAC,IAAI,YAAY;IACzB,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;IACvB,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAS;IAChC,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAS;IACjC,OAAO,CAAC,QAAQ,CAAC,SAAS,CAAS;IAEnC,YAAY,OAAO,EAAE,qBAAqB,EAQzC;IAEK,YAAY,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,EAAE,CAAC,CAqBlD;IAEK,aAAa,CACjB,KAAK,EAAE,MAAM,EAAE,EACf,UAAU,CAAC,EAAE,CAAC,SAAS,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,KAAK,IAAI,GACtD,OAAO,CAAC,MAAM,EAAE,EAAE,CAAC,CAqCrB;CACF"}
@@ -0,0 +1,65 @@
1
+ export class OpenAIEmbeddingProvider {
2
+ name = "openai";
3
+ model;
4
+ apiKey;
5
+ baseUrl;
6
+ batchSize;
7
+ constructor(options) {
8
+ this.model = options.model;
9
+ this.apiKey = options.apiKey || (options.baseUrl ? "lm-studio" : "");
10
+ this.baseUrl = (options.baseUrl || "https://api.openai.com/v1").replace(/\/+$/, "");
11
+ this.batchSize = options.batchSize ?? 25;
12
+ }
13
+ async getEmbedding(text) {
14
+ const url = `${this.baseUrl}/embeddings`;
15
+ const res = await fetch(url, {
16
+ method: "POST",
17
+ headers: {
18
+ "Content-Type": "application/json",
19
+ Authorization: `Bearer ${this.apiKey || "lm-studio"}`,
20
+ },
21
+ body: JSON.stringify({
22
+ model: this.model,
23
+ input: text,
24
+ }),
25
+ });
26
+ if (!res.ok) {
27
+ const errorText = await res.text();
28
+ throw new Error(`Embedding APIエラー (${res.status}): ${errorText}`);
29
+ }
30
+ const json = (await res.json());
31
+ return json.data[0].embedding;
32
+ }
33
+ async getEmbeddings(texts, onProgress) {
34
+ const url = `${this.baseUrl}/embeddings`;
35
+ const results = [];
36
+ for (let i = 0; i < texts.length; i += this.batchSize) {
37
+ const batch = texts.slice(i, i + this.batchSize);
38
+ const res = await fetch(url, {
39
+ method: "POST",
40
+ headers: {
41
+ "Content-Type": "application/json",
42
+ Authorization: `Bearer ${this.apiKey || "lm-studio"}`,
43
+ },
44
+ body: JSON.stringify({
45
+ model: this.model,
46
+ input: batch,
47
+ }),
48
+ });
49
+ if (!res.ok) {
50
+ const errorText = await res.text();
51
+ throw new Error(`Embedding APIエラー (${res.status}): ${errorText}`);
52
+ }
53
+ const json = (await res.json());
54
+ const sorted = [...json.data].sort((a, b) => a.index - b.index);
55
+ for (const item of sorted) {
56
+ results.push(item.embedding);
57
+ }
58
+ if (onProgress) {
59
+ onProgress(results.length, texts.length);
60
+ }
61
+ }
62
+ return results;
63
+ }
64
+ }
65
+ //# sourceMappingURL=openai.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"openai.js","sourceRoot":"","sources":["../../src/providers/openai.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,7 @@
1
+ export interface IEmbeddingProvider {
2
+ readonly name: string;
3
+ readonly model: string;
4
+ getEmbedding(text: string): Promise<number[]>;
5
+ getEmbeddings(texts: string[], onProgress?: (completed: number, total: number) => void): Promise<number[][]>;
6
+ }
7
+ //# sourceMappingURL=types.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../src/providers/types.ts"],"names":[],"mappings":"AAAA,MAAM,WAAW,kBAAkB;IACjC,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;IAEvB,YAAY,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,EAAE,CAAC,CAAC;IAE9C,aAAa,CACX,KAAK,EAAE,MAAM,EAAE,EACf,UAAU,CAAC,EAAE,CAAC,SAAS,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,KAAK,IAAI,GACtD,OAAO,CAAC,MAAM,EAAE,EAAE,CAAC,CAAC;CACxB"}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=types.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.js","sourceRoot":"","sources":["../../src/providers/types.ts"],"names":[],"mappings":""}
@@ -0,0 +1,28 @@
1
+ import type { SyncManifest } from "../types.js";
2
+ import { type Logger } from "../logger.js";
3
+ export interface SyncOptions {
4
+ force?: boolean;
5
+ logger?: Logger;
6
+ }
7
+ export interface SyncResult {
8
+ totalFiles: number;
9
+ processedArticles: number;
10
+ totalChunks: number;
11
+ isReset: boolean;
12
+ }
13
+ export declare class SyncService {
14
+ private logger;
15
+ constructor(logger?: Logger);
16
+ loadManifest(manifestPath: string): Promise<SyncManifest>;
17
+ saveManifest(manifestPath: string, manifest: SyncManifest): Promise<void>;
18
+ /**
19
+ * articles/ および books/ から対象 Markdown ファイルを走査
20
+ */
21
+ private scanContentTargets;
22
+ sync(options?: SyncOptions): Promise<SyncResult>;
23
+ /**
24
+ * ファイル保存を監視して自動同期するウォッチモード
25
+ */
26
+ watch(options?: SyncOptions): Promise<void>;
27
+ }
28
+ //# sourceMappingURL=sync-service.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"sync-service.d.ts","sourceRoot":"","sources":["../../src/services/sync-service.ts"],"names":[],"mappings":"AAWA,OAAO,KAAK,EAA0B,YAAY,EAAE,MAAM,aAAa,CAAC;AACxE,OAAO,EAAa,KAAK,MAAM,EAAE,MAAM,cAAc,CAAC;AAEtD,MAAM,WAAW,WAAW;IAC1B,KAAK,CAAC,EAAE,OAAO,CAAC;IAChB,MAAM,CAAC,EAAE,MAAM,CAAC;CACjB;AAED,MAAM,WAAW,UAAU;IACzB,UAAU,EAAE,MAAM,CAAC;IACnB,iBAAiB,EAAE,MAAM,CAAC;IAC1B,WAAW,EAAE,MAAM,CAAC;IACpB,OAAO,EAAE,OAAO,CAAC;CAClB;AASD,qBAAa,WAAW;IACtB,OAAO,CAAC,MAAM,CAAS;IAEvB,YAAY,MAAM,CAAC,EAAE,MAAM,EAE1B;IAEK,YAAY,CAAC,YAAY,EAAE,MAAM,GAAG,OAAO,CAAC,YAAY,CAAC,CAO9D;IAEK,YAAY,CAChB,YAAY,EAAE,MAAM,EACpB,QAAQ,EAAE,YAAY,GACrB,OAAO,CAAC,IAAI,CAAC,CAGf;IAED;;OAEG;YACW,kBAAkB;IAgE1B,IAAI,CAAC,OAAO,GAAE,WAAgB,GAAG,OAAO,CAAC,UAAU,CAAC,CA2MzD;IAED;;OAEG;IACG,KAAK,CAAC,OAAO,GAAE,WAAgB,GAAG,OAAO,CAAC,IAAI,CAAC,CA+DpD;CACF"}