@retrivora-ai/rag-engine 1.2.0 → 1.2.2

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 (49) hide show
  1. package/dist/DocumentChunker-BXOUMKoP.d.ts +93 -0
  2. package/dist/DocumentChunker-D1dg5iCi.d.mts +93 -0
  3. package/dist/{chunk-OCDCJUNE.mjs → chunk-GCPPRD2G.mjs} +70 -1
  4. package/dist/handlers/index.d.mts +2 -2
  5. package/dist/handlers/index.d.ts +2 -2
  6. package/dist/handlers/index.js +70 -0
  7. package/dist/handlers/index.mjs +3 -1
  8. package/dist/{index-CYgr00ot.d.ts → index-B67KQ9NN.d.ts} +14 -2
  9. package/dist/{RagConfig-FyMB_UG6.d.mts → index-Cti1u0y1.d.mts} +87 -86
  10. package/dist/{RagConfig-FyMB_UG6.d.ts → index-Cti1u0y1.d.ts} +87 -86
  11. package/dist/{index-D-lfcqlL.d.mts → index-kUXnRvuI.d.mts} +14 -2
  12. package/dist/index.d.mts +53 -89
  13. package/dist/index.d.ts +53 -89
  14. package/dist/index.js +139 -27
  15. package/dist/index.mjs +143 -27
  16. package/dist/server.d.mts +9 -4
  17. package/dist/server.d.ts +9 -4
  18. package/dist/server.js +51 -0
  19. package/dist/server.mjs +1 -1
  20. package/package.json +1 -1
  21. package/src/app/api/suggestions/route.ts +4 -0
  22. package/src/components/ChatWidget.tsx +1 -7
  23. package/src/components/ChatWindow.tsx +180 -25
  24. package/src/components/ConfigProvider.tsx +7 -33
  25. package/src/components/DocumentUpload.tsx +1 -8
  26. package/src/components/MessageBubble.tsx +1 -12
  27. package/src/components/ProductCard.tsx +1 -15
  28. package/src/components/ProductCarousel.tsx +2 -7
  29. package/src/components/SourceCard.tsx +1 -6
  30. package/src/config/RagConfig.ts +2 -0
  31. package/src/config/uiConstants.ts +23 -0
  32. package/src/core/Pipeline.ts +57 -1
  33. package/src/core/VectorPlugin.ts +8 -1
  34. package/src/handlers/index.ts +31 -1
  35. package/src/hooks/useRagChat.ts +1 -45
  36. package/src/hooks/useStoredMessages.ts +1 -1
  37. package/src/index.ts +20 -5
  38. package/src/llm/ILLMProvider.ts +1 -13
  39. package/src/llm/providers/AnthropicProvider.ts +2 -1
  40. package/src/llm/providers/GeminiProvider.ts +2 -1
  41. package/src/llm/providers/OllamaProvider.ts +2 -1
  42. package/src/llm/providers/OpenAIProvider.ts +2 -1
  43. package/src/llm/providers/UniversalLLMAdapter.ts +2 -1
  44. package/src/server.ts +2 -2
  45. package/src/types/chat.ts +53 -0
  46. package/src/types/index.ts +17 -0
  47. package/src/types/props.ts +79 -0
  48. package/dist/DocumentChunker-Dh9TvmGG.d.mts +0 -45
  49. package/dist/DocumentChunker-Dh9TvmGG.d.ts +0 -45
@@ -0,0 +1,93 @@
1
+ import { C as ChatMessage, c as ChatOptions } from './index-Cti1u0y1.js';
2
+
3
+ /**
4
+ * Generic LLM Provider interface.
5
+ * Covers both chat completion and embedding generation so a single
6
+ * provider can handle both responsibilities when appropriate.
7
+ */
8
+
9
+ interface EmbedOptions {
10
+ /** Override model for this specific embed call */
11
+ model?: string;
12
+ /** Specify the task type for models that require prefixes (e.g. nomic-embed-text) */
13
+ taskType?: 'query' | 'document';
14
+ }
15
+ interface ILLMProvider {
16
+ /**
17
+ * Send a chat completion request.
18
+ * @param messages – the full conversation history
19
+ * @param context – retrieved RAG context to inject
20
+ * @param options – optional per-call overrides
21
+ * @returns – the assistant's reply text
22
+ */
23
+ chat(messages: ChatMessage[], context: string, options?: ChatOptions): Promise<string>;
24
+ /**
25
+ * Send a streaming chat completion request.
26
+ * @returns – an async iterable of text chunks
27
+ */
28
+ chatStream?(messages: ChatMessage[], context: string, options?: ChatOptions): AsyncIterable<string>;
29
+ /**
30
+ * Generate an embedding vector for the given text.
31
+ * @param text – text to embed
32
+ * @param options – optional overrides
33
+ * @returns – float array (the embedding)
34
+ */
35
+ embed(text: string, options?: EmbedOptions): Promise<number[]>;
36
+ /**
37
+ * Generate embedding vectors for multiple texts in a single batch.
38
+ * @param texts – array of texts to embed
39
+ * @param options – optional overrides
40
+ * @returns – array of float arrays
41
+ */
42
+ batchEmbed(texts: string[], options?: EmbedOptions): Promise<number[][]>;
43
+ /**
44
+ * Check if the provider endpoint is reachable.
45
+ */
46
+ ping(): Promise<boolean>;
47
+ }
48
+
49
+ /**
50
+ * DocumentChunker — splits long text into overlapping chunks
51
+ * suitable for vector embedding and retrieval.
52
+ *
53
+ * Strategy: sentence-aware sliding window
54
+ * 1. Split on sentence boundaries
55
+ * 2. Accumulate sentences into chunks up to `chunkSize` characters
56
+ * 3. Carry over `chunkOverlap` characters from the previous chunk
57
+ */
58
+ interface Chunk {
59
+ id: string;
60
+ content: string;
61
+ metadata?: Record<string, unknown>;
62
+ }
63
+ interface ChunkOptions {
64
+ /** Target chunk size in characters (default 1000) */
65
+ chunkSize?: number;
66
+ /** Overlap between consecutive chunks in characters (default 200) */
67
+ chunkOverlap?: number;
68
+ /** Source document identifier used as ID prefix */
69
+ docId?: string | number;
70
+ /** Extra metadata to attach to every chunk */
71
+ metadata?: Record<string, unknown>;
72
+ /** Characters used to split text, in order of priority */
73
+ separators?: string[];
74
+ }
75
+ declare class DocumentChunker {
76
+ private readonly chunkSize;
77
+ private readonly chunkOverlap;
78
+ private readonly separators;
79
+ constructor(chunkSize?: number, chunkOverlap?: number, separators?: string[]);
80
+ /**
81
+ * Split a single text string into overlapping chunks using a recursive strategy.
82
+ * Preserves structural boundaries (Markdown headers) where possible.
83
+ */
84
+ chunk(text: string, options?: ChunkOptions): Chunk[];
85
+ private recursiveSplit;
86
+ chunkMany(documents: Array<{
87
+ content: string;
88
+ docId?: string | number;
89
+ metadata?: Record<string, unknown>;
90
+ }>): Chunk[];
91
+ }
92
+
93
+ export { type Chunk as C, DocumentChunker as D, type EmbedOptions as E, type ILLMProvider as I, type ChunkOptions as a };
@@ -0,0 +1,93 @@
1
+ import { C as ChatMessage, c as ChatOptions } from './index-Cti1u0y1.mjs';
2
+
3
+ /**
4
+ * Generic LLM Provider interface.
5
+ * Covers both chat completion and embedding generation so a single
6
+ * provider can handle both responsibilities when appropriate.
7
+ */
8
+
9
+ interface EmbedOptions {
10
+ /** Override model for this specific embed call */
11
+ model?: string;
12
+ /** Specify the task type for models that require prefixes (e.g. nomic-embed-text) */
13
+ taskType?: 'query' | 'document';
14
+ }
15
+ interface ILLMProvider {
16
+ /**
17
+ * Send a chat completion request.
18
+ * @param messages – the full conversation history
19
+ * @param context – retrieved RAG context to inject
20
+ * @param options – optional per-call overrides
21
+ * @returns – the assistant's reply text
22
+ */
23
+ chat(messages: ChatMessage[], context: string, options?: ChatOptions): Promise<string>;
24
+ /**
25
+ * Send a streaming chat completion request.
26
+ * @returns – an async iterable of text chunks
27
+ */
28
+ chatStream?(messages: ChatMessage[], context: string, options?: ChatOptions): AsyncIterable<string>;
29
+ /**
30
+ * Generate an embedding vector for the given text.
31
+ * @param text – text to embed
32
+ * @param options – optional overrides
33
+ * @returns – float array (the embedding)
34
+ */
35
+ embed(text: string, options?: EmbedOptions): Promise<number[]>;
36
+ /**
37
+ * Generate embedding vectors for multiple texts in a single batch.
38
+ * @param texts – array of texts to embed
39
+ * @param options – optional overrides
40
+ * @returns – array of float arrays
41
+ */
42
+ batchEmbed(texts: string[], options?: EmbedOptions): Promise<number[][]>;
43
+ /**
44
+ * Check if the provider endpoint is reachable.
45
+ */
46
+ ping(): Promise<boolean>;
47
+ }
48
+
49
+ /**
50
+ * DocumentChunker — splits long text into overlapping chunks
51
+ * suitable for vector embedding and retrieval.
52
+ *
53
+ * Strategy: sentence-aware sliding window
54
+ * 1. Split on sentence boundaries
55
+ * 2. Accumulate sentences into chunks up to `chunkSize` characters
56
+ * 3. Carry over `chunkOverlap` characters from the previous chunk
57
+ */
58
+ interface Chunk {
59
+ id: string;
60
+ content: string;
61
+ metadata?: Record<string, unknown>;
62
+ }
63
+ interface ChunkOptions {
64
+ /** Target chunk size in characters (default 1000) */
65
+ chunkSize?: number;
66
+ /** Overlap between consecutive chunks in characters (default 200) */
67
+ chunkOverlap?: number;
68
+ /** Source document identifier used as ID prefix */
69
+ docId?: string | number;
70
+ /** Extra metadata to attach to every chunk */
71
+ metadata?: Record<string, unknown>;
72
+ /** Characters used to split text, in order of priority */
73
+ separators?: string[];
74
+ }
75
+ declare class DocumentChunker {
76
+ private readonly chunkSize;
77
+ private readonly chunkOverlap;
78
+ private readonly separators;
79
+ constructor(chunkSize?: number, chunkOverlap?: number, separators?: string[]);
80
+ /**
81
+ * Split a single text string into overlapping chunks using a recursive strategy.
82
+ * Preserves structural boundaries (Markdown headers) where possible.
83
+ */
84
+ chunk(text: string, options?: ChunkOptions): Chunk[];
85
+ private recursiveSplit;
86
+ chunkMany(documents: Array<{
87
+ content: string;
88
+ docId?: string | number;
89
+ metadata?: Record<string, unknown>;
90
+ }>): Chunk[];
91
+ }
92
+
93
+ export { type Chunk as C, DocumentChunker as D, type EmbedOptions as E, type ILLMProvider as I, type ChunkOptions as a };
@@ -2523,6 +2523,50 @@ Optimized Search Query:`;
2523
2523
  );
2524
2524
  return rewrite.trim() || question;
2525
2525
  }
2526
+ /**
2527
+ * Generate 3-5 short, relevant questions based on the vector database content.
2528
+ */
2529
+ async getSuggestions(query, namespace) {
2530
+ if (!query || query.trim().length < 3) {
2531
+ return [];
2532
+ }
2533
+ await this.initialize();
2534
+ const ns = namespace != null ? namespace : this.config.projectId;
2535
+ try {
2536
+ const { sources } = await this.retrieve(query, { namespace: ns, topK: 3 });
2537
+ if (sources.length === 0) {
2538
+ return [];
2539
+ }
2540
+ const context = sources.map((s) => s.content).join("\n\n---\n\n");
2541
+ const prompt = `
2542
+ Based on the following snippets from a document, what are 3 short, relevant questions a user might ask?
2543
+ Focus on questions that can be answered by the context.
2544
+ Keep each question under 10 words and make them very specific to the content.
2545
+ Return ONLY a JSON array of strings like ["Question 1", "Question 2", "Question 3"].
2546
+
2547
+ Context:
2548
+ ${context}
2549
+
2550
+ Suggestions:`;
2551
+ const response = await this.llmProvider.chat(
2552
+ [
2553
+ { role: "system", content: "You are a helpful assistant that generates search suggestions." },
2554
+ { role: "user", content: prompt }
2555
+ ],
2556
+ ""
2557
+ );
2558
+ const match = response.match(/\[[\s\S]*\]/);
2559
+ if (match) {
2560
+ const suggestions = JSON.parse(match[0]);
2561
+ if (Array.isArray(suggestions)) {
2562
+ return suggestions.map((s) => String(s)).slice(0, 3);
2563
+ }
2564
+ }
2565
+ } catch (error) {
2566
+ console.error("[Pipeline] Failed to generate suggestions:", error);
2567
+ }
2568
+ return [];
2569
+ }
2526
2570
  };
2527
2571
 
2528
2572
  // src/core/ProviderHealthCheck.ts
@@ -2677,6 +2721,13 @@ var VectorPlugin = class {
2677
2721
  await this.validationPromise;
2678
2722
  return this.pipeline.ingest(documents, namespace);
2679
2723
  }
2724
+ /**
2725
+ * Get auto-suggestions based on a query prefix.
2726
+ */
2727
+ async getSuggestions(query, namespace) {
2728
+ await this.validationPromise;
2729
+ return this.pipeline.getSuggestions(query, namespace);
2730
+ }
2680
2731
  };
2681
2732
 
2682
2733
  // src/utils/DocumentParser.ts
@@ -2906,6 +2957,23 @@ function createUploadHandler(configOrPlugin) {
2906
2957
  }
2907
2958
  };
2908
2959
  }
2960
+ function createSuggestionsHandler(configOrPlugin) {
2961
+ const plugin = configOrPlugin instanceof VectorPlugin ? configOrPlugin : new VectorPlugin(configOrPlugin);
2962
+ return async function POST(req) {
2963
+ try {
2964
+ const body = await req.json();
2965
+ const { query, namespace } = body;
2966
+ if (typeof query !== "string") {
2967
+ return NextResponse.json({ error: "query is required" }, { status: 400 });
2968
+ }
2969
+ const suggestions = await plugin.getSuggestions(query, namespace);
2970
+ return NextResponse.json({ suggestions });
2971
+ } catch (err) {
2972
+ const message = err instanceof Error ? err.message : "Internal server error";
2973
+ return NextResponse.json({ error: message }, { status: 500 });
2974
+ }
2975
+ };
2976
+ }
2909
2977
 
2910
2978
  export {
2911
2979
  getRagConfig,
@@ -2935,5 +3003,6 @@ export {
2935
3003
  createStreamHandler,
2936
3004
  createIngestHandler,
2937
3005
  createHealthHandler,
2938
- createUploadHandler
3006
+ createUploadHandler,
3007
+ createSuggestionsHandler
2939
3008
  };
@@ -1,3 +1,3 @@
1
- import '../RagConfig-FyMB_UG6.mjs';
2
- export { c as createChatHandler, d as createHealthHandler, e as createIngestHandler, f as createStreamHandler, g as createUploadHandler, s as sseErrorFrame, h as sseFrame, i as sseMetaFrame, j as sseTextFrame } from '../index-D-lfcqlL.mjs';
1
+ import '../index-Cti1u0y1.mjs';
2
+ export { c as createChatHandler, d as createHealthHandler, e as createIngestHandler, f as createStreamHandler, k as createSuggestionsHandler, g as createUploadHandler, s as sseErrorFrame, h as sseFrame, i as sseMetaFrame, j as sseTextFrame } from '../index-kUXnRvuI.mjs';
3
3
  import 'next/server';
@@ -1,3 +1,3 @@
1
- import '../RagConfig-FyMB_UG6.js';
2
- export { c as createChatHandler, d as createHealthHandler, e as createIngestHandler, f as createStreamHandler, g as createUploadHandler, s as sseErrorFrame, h as sseFrame, i as sseMetaFrame, j as sseTextFrame } from '../index-CYgr00ot.js';
1
+ import '../index-Cti1u0y1.js';
2
+ export { c as createChatHandler, d as createHealthHandler, e as createIngestHandler, f as createStreamHandler, k as createSuggestionsHandler, g as createUploadHandler, s as sseErrorFrame, h as sseFrame, i as sseMetaFrame, j as sseTextFrame } from '../index-B67KQ9NN.js';
3
3
  import 'next/server';
@@ -1612,6 +1612,7 @@ __export(handlers_exports, {
1612
1612
  createHealthHandler: () => createHealthHandler,
1613
1613
  createIngestHandler: () => createIngestHandler,
1614
1614
  createStreamHandler: () => createStreamHandler,
1615
+ createSuggestionsHandler: () => createSuggestionsHandler,
1615
1616
  createUploadHandler: () => createUploadHandler,
1616
1617
  sseErrorFrame: () => sseErrorFrame,
1617
1618
  sseFrame: () => sseFrame,
@@ -4085,6 +4086,50 @@ Optimized Search Query:`;
4085
4086
  );
4086
4087
  return rewrite.trim() || question;
4087
4088
  }
4089
+ /**
4090
+ * Generate 3-5 short, relevant questions based on the vector database content.
4091
+ */
4092
+ async getSuggestions(query, namespace) {
4093
+ if (!query || query.trim().length < 3) {
4094
+ return [];
4095
+ }
4096
+ await this.initialize();
4097
+ const ns = namespace != null ? namespace : this.config.projectId;
4098
+ try {
4099
+ const { sources } = await this.retrieve(query, { namespace: ns, topK: 3 });
4100
+ if (sources.length === 0) {
4101
+ return [];
4102
+ }
4103
+ const context = sources.map((s) => s.content).join("\n\n---\n\n");
4104
+ const prompt = `
4105
+ Based on the following snippets from a document, what are 3 short, relevant questions a user might ask?
4106
+ Focus on questions that can be answered by the context.
4107
+ Keep each question under 10 words and make them very specific to the content.
4108
+ Return ONLY a JSON array of strings like ["Question 1", "Question 2", "Question 3"].
4109
+
4110
+ Context:
4111
+ ${context}
4112
+
4113
+ Suggestions:`;
4114
+ const response = await this.llmProvider.chat(
4115
+ [
4116
+ { role: "system", content: "You are a helpful assistant that generates search suggestions." },
4117
+ { role: "user", content: prompt }
4118
+ ],
4119
+ ""
4120
+ );
4121
+ const match = response.match(/\[[\s\S]*\]/);
4122
+ if (match) {
4123
+ const suggestions = JSON.parse(match[0]);
4124
+ if (Array.isArray(suggestions)) {
4125
+ return suggestions.map((s) => String(s)).slice(0, 3);
4126
+ }
4127
+ }
4128
+ } catch (error) {
4129
+ console.error("[Pipeline] Failed to generate suggestions:", error);
4130
+ }
4131
+ return [];
4132
+ }
4088
4133
  };
4089
4134
 
4090
4135
  // src/core/ProviderHealthCheck.ts
@@ -4239,6 +4284,13 @@ var VectorPlugin = class {
4239
4284
  await this.validationPromise;
4240
4285
  return this.pipeline.ingest(documents, namespace);
4241
4286
  }
4287
+ /**
4288
+ * Get auto-suggestions based on a query prefix.
4289
+ */
4290
+ async getSuggestions(query, namespace) {
4291
+ await this.validationPromise;
4292
+ return this.pipeline.getSuggestions(query, namespace);
4293
+ }
4242
4294
  };
4243
4295
 
4244
4296
  // src/utils/DocumentParser.ts
@@ -4468,12 +4520,30 @@ function createUploadHandler(configOrPlugin) {
4468
4520
  }
4469
4521
  };
4470
4522
  }
4523
+ function createSuggestionsHandler(configOrPlugin) {
4524
+ const plugin = configOrPlugin instanceof VectorPlugin ? configOrPlugin : new VectorPlugin(configOrPlugin);
4525
+ return async function POST(req) {
4526
+ try {
4527
+ const body = await req.json();
4528
+ const { query, namespace } = body;
4529
+ if (typeof query !== "string") {
4530
+ return import_server.NextResponse.json({ error: "query is required" }, { status: 400 });
4531
+ }
4532
+ const suggestions = await plugin.getSuggestions(query, namespace);
4533
+ return import_server.NextResponse.json({ suggestions });
4534
+ } catch (err) {
4535
+ const message = err instanceof Error ? err.message : "Internal server error";
4536
+ return import_server.NextResponse.json({ error: message }, { status: 500 });
4537
+ }
4538
+ };
4539
+ }
4471
4540
  // Annotate the CommonJS export names for ESM import in node:
4472
4541
  0 && (module.exports = {
4473
4542
  createChatHandler,
4474
4543
  createHealthHandler,
4475
4544
  createIngestHandler,
4476
4545
  createStreamHandler,
4546
+ createSuggestionsHandler,
4477
4547
  createUploadHandler,
4478
4548
  sseErrorFrame,
4479
4549
  sseFrame,
@@ -3,12 +3,13 @@ import {
3
3
  createHealthHandler,
4
4
  createIngestHandler,
5
5
  createStreamHandler,
6
+ createSuggestionsHandler,
6
7
  createUploadHandler,
7
8
  sseErrorFrame,
8
9
  sseFrame,
9
10
  sseMetaFrame,
10
11
  sseTextFrame
11
- } from "../chunk-OCDCJUNE.mjs";
12
+ } from "../chunk-GCPPRD2G.mjs";
12
13
  import "../chunk-YLTMFW4M.mjs";
13
14
  import "../chunk-X4TOT24V.mjs";
14
15
  export {
@@ -16,6 +17,7 @@ export {
16
17
  createHealthHandler,
17
18
  createIngestHandler,
18
19
  createStreamHandler,
20
+ createSuggestionsHandler,
19
21
  createUploadHandler,
20
22
  sseErrorFrame,
21
23
  sseFrame,
@@ -1,4 +1,4 @@
1
- import { g as RagConfig, C as ChatMessage, b as ChatResponse, e as IngestDocument } from './RagConfig-FyMB_UG6.js';
1
+ import { h as RagConfig, C as ChatMessage, d as ChatResponse, I as IngestDocument } from './index-Cti1u0y1.js';
2
2
  import { NextRequest, NextResponse } from 'next/server';
3
3
 
4
4
  interface ValidationError {
@@ -112,6 +112,10 @@ declare class VectorPlugin {
112
112
  docId: string | number;
113
113
  chunksIngested: number;
114
114
  }>>;
115
+ /**
116
+ * Get auto-suggestions based on a query prefix.
117
+ */
118
+ getSuggestions(query: string, namespace?: string): Promise<string[]>;
115
119
  }
116
120
 
117
121
  /**
@@ -202,5 +206,13 @@ declare function createUploadHandler(configOrPlugin?: Partial<RagConfig> | Vecto
202
206
  chunksIngested: number;
203
207
  }[];
204
208
  }>>;
209
+ /**
210
+ * createSuggestionsHandler — factory for the auto-suggestions endpoint.
211
+ */
212
+ declare function createSuggestionsHandler(configOrPlugin?: Partial<RagConfig> | VectorPlugin): (req: NextRequest) => Promise<NextResponse<{
213
+ error: string;
214
+ }> | NextResponse<{
215
+ suggestions: string[];
216
+ }>>;
205
217
 
206
- export { ConfigValidator as C, type HealthCheckResult as H, type IProviderValidator as I, type ValidationError as V, type IProviderHealthChecker as a, VectorPlugin as b, createChatHandler as c, createHealthHandler as d, createIngestHandler as e, createStreamHandler as f, createUploadHandler as g, sseFrame as h, sseMetaFrame as i, sseTextFrame as j, sseErrorFrame as s };
218
+ export { ConfigValidator as C, type HealthCheckResult as H, type IProviderValidator as I, type ValidationError as V, type IProviderHealthChecker as a, VectorPlugin as b, createChatHandler as c, createHealthHandler as d, createIngestHandler as e, createStreamHandler as f, createUploadHandler as g, sseFrame as h, sseMetaFrame as i, sseTextFrame as j, createSuggestionsHandler as k, sseErrorFrame as s };
@@ -1,12 +1,13 @@
1
- /**
2
- * Generic LLM Provider interface.
3
- * Covers both chat completion and embedding generation so a single
4
- * provider can handle both responsibilities when appropriate.
5
- */
1
+ type MessageRole = 'user' | 'assistant' | 'system';
6
2
  interface ChatMessage {
7
- role: 'user' | 'assistant' | 'system';
3
+ role: MessageRole;
8
4
  content: string;
9
5
  }
6
+ interface RagMessage extends ChatMessage {
7
+ id: string;
8
+ sources?: VectorMatch[];
9
+ createdAt: string;
10
+ }
10
11
  interface ChatOptions {
11
12
  /** Override max tokens for this specific call */
12
13
  maxTokens?: number;
@@ -15,86 +16,33 @@ interface ChatOptions {
15
16
  /** Stop sequences */
16
17
  stop?: string[];
17
18
  }
18
- interface EmbedOptions {
19
- /** Override model for this specific embed call */
20
- model?: string;
21
- /** Specify the task type for models that require prefixes (e.g. nomic-embed-text) */
22
- taskType?: 'query' | 'document';
23
- }
24
- interface ILLMProvider {
25
- /**
26
- * Send a chat completion request.
27
- * @param messages the full conversation history
28
- * @param context – retrieved RAG context to inject
29
- * @param options – optional per-call overrides
30
- * @returns – the assistant's reply text
31
- */
32
- chat(messages: ChatMessage[], context: string, options?: ChatOptions): Promise<string>;
33
- /**
34
- * Send a streaming chat completion request.
35
- * @returns – an async iterable of text chunks
36
- */
37
- chatStream?(messages: ChatMessage[], context: string, options?: ChatOptions): AsyncIterable<string>;
38
- /**
39
- * Generate an embedding vector for the given text.
40
- * @param text – text to embed
41
- * @param options – optional overrides
42
- * @returns – float array (the embedding)
43
- */
44
- embed(text: string, options?: EmbedOptions): Promise<number[]>;
45
- /**
46
- * Generate embedding vectors for multiple texts in a single batch.
47
- * @param texts – array of texts to embed
48
- * @param options – optional overrides
49
- * @returns – array of float arrays
50
- */
51
- batchEmbed(texts: string[], options?: EmbedOptions): Promise<number[][]>;
52
- /**
53
- * Check if the provider endpoint is reachable.
54
- */
55
- ping(): Promise<boolean>;
56
- }
57
-
58
- interface VectorMatch {
59
- id: string | number;
60
- score: number;
61
- content: string;
62
- metadata?: Record<string, unknown>;
63
- }
64
- interface UpsertDocument {
65
- id: string | number;
66
- vector: number[];
67
- content: string;
68
- metadata?: Record<string, unknown>;
69
- }
70
- interface IngestDocument {
71
- docId: string | number;
72
- content: string;
73
- metadata?: Record<string, unknown>;
74
- }
75
- interface ChatResponse {
76
- reply: string;
77
- sources: VectorMatch[];
78
- graphData?: GraphSearchResult;
79
- }
80
- interface GraphNode {
81
- id: string;
82
- label: string;
83
- properties?: Record<string, unknown>;
84
- }
85
- interface Edge {
86
- source: string;
87
- target: string;
88
- type: string;
89
- properties?: Record<string, unknown>;
90
- }
91
- interface GraphSearchResult {
92
- nodes: GraphNode[];
93
- edges: Edge[];
19
+ interface UseRagChatOptions {
20
+ /** Override the chat API endpoint (default: /api/chat) */
21
+ apiUrl?: string;
22
+ /** Override project namespace */
23
+ namespace?: string;
24
+ /** Persist chat history to localStorage (default: true) */
25
+ persist?: boolean;
26
+ /** Called after each successful assistant reply */
27
+ onReply?: (message: RagMessage) => void;
28
+ /** Called on error */
29
+ onError?: (error: string) => void;
94
30
  }
95
- interface RetrievalResult {
96
- sources: VectorMatch[];
97
- graphData?: GraphSearchResult;
31
+ interface UseRagChatReturn {
32
+ /** All messages in the current conversation */
33
+ messages: RagMessage[];
34
+ /** Whether a response is in flight */
35
+ isLoading: boolean;
36
+ /** Current error message, or null */
37
+ error: string | null;
38
+ /** Send a user message */
39
+ send: (text: string) => Promise<void>;
40
+ /** Clear the conversation (and localStorage if persist=true) */
41
+ clear: () => void;
42
+ /** Retry the last failed send */
43
+ retry: () => Promise<void>;
44
+ /** Programmatically set the conversation (e.g. to restore from a DB) */
45
+ setMessages: React.Dispatch<React.SetStateAction<RagMessage[]>>;
98
46
  }
99
47
 
100
48
  /**
@@ -224,6 +172,8 @@ interface UIConfig {
224
172
  allowUpload?: boolean;
225
173
  /** Whether to allow manual resizing of the chat window. Defaults to true. */
226
174
  allowResize?: boolean;
175
+ /** Whether to enable voice search input. Defaults to true. */
176
+ enableVoiceInput?: boolean;
227
177
  }
228
178
  interface RAGConfig {
229
179
  /** Number of top-K chunks retrieved per query */
@@ -271,4 +221,55 @@ interface RagConfig {
271
221
  graphDb?: GraphDBConfig;
272
222
  }
273
223
 
274
- export type { ChatMessage as C, EmbedOptions as E, GraphDBConfig as G, ILLMProvider as I, LLMConfig as L, RAGConfig as R, UIConfig as U, VectorMatch as V, ChatOptions as a, ChatResponse as b, EmbeddingConfig as c, EmbeddingProvider as d, IngestDocument as e, LLMProvider as f, RagConfig as g, UpsertDocument as h, VectorDBConfig as i, VectorDBProvider as j, RetrievalResult as k, GraphNode as l, Edge as m, GraphSearchResult as n };
224
+ interface VectorMatch {
225
+ id: string | number;
226
+ score: number;
227
+ content: string;
228
+ metadata?: Record<string, unknown>;
229
+ }
230
+ interface UpsertDocument {
231
+ id: string | number;
232
+ vector: number[];
233
+ content: string;
234
+ metadata?: Record<string, unknown>;
235
+ }
236
+ interface IngestDocument {
237
+ docId: string | number;
238
+ content: string;
239
+ metadata?: Record<string, unknown>;
240
+ }
241
+ interface ChatResponse {
242
+ reply: string;
243
+ sources: VectorMatch[];
244
+ graphData?: GraphSearchResult;
245
+ }
246
+ interface GraphNode {
247
+ id: string;
248
+ label: string;
249
+ properties?: Record<string, unknown>;
250
+ }
251
+ interface Edge {
252
+ source: string;
253
+ target: string;
254
+ type: string;
255
+ properties?: Record<string, unknown>;
256
+ }
257
+ interface GraphSearchResult {
258
+ nodes: GraphNode[];
259
+ edges: Edge[];
260
+ }
261
+ interface RetrievalResult {
262
+ sources: VectorMatch[];
263
+ graphData?: GraphSearchResult;
264
+ }
265
+ interface Product {
266
+ id: string | number;
267
+ name: string;
268
+ brand?: string;
269
+ price?: string | number;
270
+ image?: string;
271
+ link?: string;
272
+ description?: string;
273
+ }
274
+
275
+ export type { ChatMessage as C, EmbeddingConfig as E, GraphDBConfig as G, IngestDocument as I, LLMConfig as L, Product as P, RagMessage as R, UIConfig as U, VectorMatch as V, UseRagChatOptions as a, UseRagChatReturn as b, ChatOptions as c, ChatResponse as d, EmbeddingProvider as e, LLMProvider as f, RAGConfig as g, RagConfig as h, UpsertDocument as i, VectorDBConfig as j, VectorDBProvider as k, RetrievalResult as l, GraphNode as m, Edge as n, GraphSearchResult as o };