@orkg/scidquest 1.0.5 → 1.1.4

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 (62) hide show
  1. package/README.md +519 -28
  2. package/dist/assets/pdf.worker.min.mjs +28 -0
  3. package/dist/components/AI/AIConfigurationButton.d.ts +3 -0
  4. package/dist/components/AI/AIConfigurationDialog.d.ts +7 -0
  5. package/dist/components/TemplateQuestionaire/AIAssistantButton.d.ts +33 -0
  6. package/dist/components/TemplateQuestionaire/BufferedTextField.d.ts +19 -0
  7. package/dist/components/TemplateQuestionaire/FieldRow.d.ts +8 -0
  8. package/dist/components/TemplateQuestionaire/ImportDialog.d.ts +12 -0
  9. package/dist/components/TemplateQuestionaire/InfoTooltip.d.ts +7 -0
  10. package/dist/components/TemplateQuestionaire/InlineValidationFeedback.d.ts +8 -0
  11. package/dist/components/TemplateQuestionaire/NodeWrapper.d.ts +8 -0
  12. package/dist/components/TemplateQuestionaire/QuestionnaireAIHistoryDialog.d.ts +15 -0
  13. package/dist/components/TemplateQuestionaire/Questions/GroupQuestion.d.ts +30 -0
  14. package/dist/components/TemplateQuestionaire/Questions/MultiSelectQuestion.d.ts +31 -0
  15. package/dist/components/TemplateQuestionaire/Questions/QuestionRenderer.d.ts +32 -0
  16. package/dist/components/TemplateQuestionaire/Questions/RepeatGroupQuestion.d.ts +30 -0
  17. package/dist/components/TemplateQuestionaire/Questions/RepeatTextQuestion.d.ts +31 -0
  18. package/dist/components/TemplateQuestionaire/Questions/SelectQuestion.d.ts +31 -0
  19. package/dist/components/TemplateQuestionaire/Questions/TextQuestion.d.ts +32 -0
  20. package/dist/components/TemplateQuestionaire/SectionAccordion.d.ts +42 -0
  21. package/dist/components/TemplateQuestionaire/SuggestionBox.d.ts +30 -0
  22. package/dist/components/TemplateQuestionaire/TopSummaryBar.d.ts +43 -0
  23. package/dist/components/TemplateQuestionaire/ValidationStatusButton.d.ts +33 -0
  24. package/dist/context/QuestionnaireAIContext.d.ts +48 -0
  25. package/dist/hooks/useSuggestionGenerator.d.ts +30 -0
  26. package/dist/lib/adapter.d.ts +3 -0
  27. package/dist/lib/components/PDFUpload.d.ts +10 -0
  28. package/dist/lib/components/PdfViewer.d.ts +27 -0
  29. package/dist/lib/components/ResearchQuestionnaireApp.d.ts +32 -0
  30. package/dist/lib/components/ResearchQuestionnaireFieldAiWrapper.d.ts +25 -0
  31. package/dist/lib/components/TemplateQuestionnaire.d.ts +27 -0
  32. package/dist/lib/context.d.ts +14 -0
  33. package/dist/lib/hooks/useSuggestionGenerator.d.ts +26 -0
  34. package/dist/lib/index.d.ts +25 -0
  35. package/dist/lib/questionnaire-template-helpers.d.ts +10 -0
  36. package/dist/lib/research-questionnaire-workspace.d.ts +33 -0
  37. package/dist/lib/types.d.ts +121 -0
  38. package/dist/lib/utils/createLLMServiceFromAIService.d.ts +3 -0
  39. package/dist/scidquest.es.js +6679 -64083
  40. package/dist/semanticChunker-CNi7GgV8.js +84 -0
  41. package/dist/services/aiService.d.ts +39 -0
  42. package/dist/services/backendAIService.d.ts +191 -0
  43. package/dist/store/hooks.d.ts +4 -0
  44. package/dist/store/slices/aiSlice.d.ts +21 -0
  45. package/dist/store/store.d.ts +9 -0
  46. package/dist/types/context.d.ts +39 -0
  47. package/dist/utils/contextGatherer.d.ts +39 -0
  48. package/dist/utils/fuzzyPdfMatcher.d.ts +15 -0
  49. package/dist/utils/pdf.d.ts +25 -0
  50. package/dist/utils/pdfWorker.d.ts +10 -0
  51. package/dist/utils/robustPdfMatcher.d.ts +22 -0
  52. package/dist/utils/semanticChunker.d.ts +27 -0
  53. package/dist/utils/simplePdfMatcher.d.ts +13 -0
  54. package/dist/utils/structuredPdfExtractor.d.ts +34 -0
  55. package/dist/utils/suggestions.d.ts +88 -0
  56. package/dist/utils/theme.d.ts +6 -0
  57. package/dist/utils/tokenEstimator.d.ts +32 -0
  58. package/dist/utils/tokenPdfMatcher.d.ts +14 -0
  59. package/dist/utils/unicodeNormalizer.d.ts +13 -0
  60. package/dist/utils/validationRules.d.ts +51 -0
  61. package/package.json +30 -8
  62. package/dist/semanticChunker-CEckDeUn.js +0 -102
@@ -0,0 +1,84 @@
1
+ var u = Object.defineProperty;
2
+ var p = (a, t, n) => t in a ? u(a, t, { enumerable: !0, configurable: !0, writable: !0, value: n }) : a[t] = n;
3
+ var h = (a, t, n) => p(a, typeof t != "symbol" ? t + "" : t, n);
4
+ import { pipeline as g } from "@huggingface/transformers";
5
+ class f {
6
+ constructor() {
7
+ h(this, "model", null);
8
+ h(this, "modelLoading", null);
9
+ }
10
+ async initialize() {
11
+ if (!this.model) {
12
+ if (this.modelLoading) return this.modelLoading;
13
+ this.modelLoading = (async () => {
14
+ try {
15
+ this.model = await g(
16
+ "feature-extraction",
17
+ "Xenova/all-MiniLM-L6-v2",
18
+ { dtype: "q8" }
19
+ );
20
+ } catch (t) {
21
+ throw console.error("[FrontendSemanticChunker] Model initialization failed:", t), this.modelLoading = null, t;
22
+ }
23
+ })(), await this.modelLoading;
24
+ }
25
+ }
26
+ splitIntoChunks(t) {
27
+ const n = [];
28
+ for (const r of t) {
29
+ if (!r.text || r.text.trim().length === 0) continue;
30
+ const o = r.text.split(new RegExp("(?<=[.!?])(?=\\s)"));
31
+ let e = "", s = 0;
32
+ for (const d of o) {
33
+ const i = d.trim();
34
+ i && (e && e.length + i.length + 1 > 2e3 ? (n.push({
35
+ text: e.trim(),
36
+ pageNumber: r.pageNumber,
37
+ startIndex: s,
38
+ endIndex: s + e.length,
39
+ tokenEstimate: Math.ceil(e.length / 4)
40
+ }), e = e.trim().split(/\s+/).slice(-Math.ceil(400 / 5)).join(" ") + " " + i, s += e.length - 400) : e += (e ? " " : "") + i);
41
+ }
42
+ e.trim() && (n.push({
43
+ text: e.trim(),
44
+ pageNumber: r.pageNumber,
45
+ startIndex: s,
46
+ endIndex: s + e.length,
47
+ tokenEstimate: Math.ceil(e.length / 4)
48
+ }), e = "", s = 0);
49
+ }
50
+ return n;
51
+ }
52
+ async embed(t) {
53
+ const n = await this.model(t, { pooling: "mean", normalize: !0 });
54
+ return Array.from(n.data);
55
+ }
56
+ cosineSimilarity(t, n) {
57
+ let c = 0, l = 0, r = 0;
58
+ for (let o = 0; o < t.length; o++)
59
+ c += t[o] * n[o], l += t[o] * t[o], r += n[o] * n[o];
60
+ return c / (Math.sqrt(l) * Math.sqrt(r));
61
+ }
62
+ async findRelevantChunks(t, n, c = 4e3) {
63
+ await this.initialize();
64
+ const l = this.splitIntoChunks(n), r = await Promise.all(
65
+ l.map((i) => this.embed(i.text))
66
+ ), o = await this.embed(t), e = l.map((i, m) => ({
67
+ ...i,
68
+ similarity: this.cosineSimilarity(o, r[m])
69
+ }));
70
+ e.sort((i, m) => m.similarity - i.similarity);
71
+ const s = [];
72
+ let d = 0;
73
+ for (const i of e)
74
+ d + i.tokenEstimate <= c && (s.push(i), d += i.tokenEstimate);
75
+ return s.sort((i, m) => i.pageNumber - m.pageNumber), s;
76
+ }
77
+ isInitialized() {
78
+ return this.model !== null;
79
+ }
80
+ }
81
+ const S = new f();
82
+ export {
83
+ S as frontendSemanticChunker
84
+ };
@@ -0,0 +1,39 @@
1
+ import type { AIProvider, OpenAIModel, GroqModel, MistralModel } from '../store/slices/aiSlice';
2
+ export interface AIConfig {
3
+ provider: AIProvider;
4
+ openaiModel: OpenAIModel;
5
+ groqModel: GroqModel;
6
+ mistralModel: MistralModel;
7
+ openaiApiKey: string;
8
+ groqApiKey: string;
9
+ mistralApiKey: string;
10
+ useEnvironmentKeys: boolean;
11
+ }
12
+ export declare class AIService {
13
+ private config;
14
+ constructor(config: AIConfig);
15
+ private getApiKey;
16
+ private createProvider;
17
+ private getModel;
18
+ getEnhancedModel(provider?: AIProvider, modelName?: string): any;
19
+ generateText(prompt: string, options?: {
20
+ temperature?: number;
21
+ maxTokens?: number;
22
+ provider?: AIProvider;
23
+ model?: string;
24
+ systemContext?: string;
25
+ }): Promise<{
26
+ text: string;
27
+ reasoning?: string;
28
+ usage?: any;
29
+ }>;
30
+ isConfigured(): boolean;
31
+ getCurrentConfig(): {
32
+ provider: AIProvider;
33
+ model: string;
34
+ apiKeyConfigured: boolean;
35
+ };
36
+ generateSuggestions(request: any): Promise<any>;
37
+ }
38
+ export declare const useAIService: () => AIService;
39
+ export declare const createDefaultAIService: () => AIService;
@@ -0,0 +1,191 @@
1
+ import type { AIProvider, OpenAIModel, GroqModel, MistralModel } from '../store/slices/aiSlice';
2
+ import { type GenerateSuggestionsRequest, type GenerateSuggestionsResponse } from '../utils/suggestions';
3
+ export interface BackendAIConfig {
4
+ provider: AIProvider;
5
+ openaiModel: OpenAIModel;
6
+ groqModel: GroqModel;
7
+ mistralModel: MistralModel;
8
+ useEnvironmentKeys: boolean;
9
+ }
10
+ export interface GenerateTextRequest {
11
+ prompt: string;
12
+ provider?: AIProvider;
13
+ model?: string;
14
+ temperature?: number;
15
+ maxTokens?: number;
16
+ systemContext?: string;
17
+ }
18
+ export interface GenerateTextResponse {
19
+ text: string;
20
+ reasoning?: string;
21
+ usage?: {
22
+ promptTokens: number;
23
+ completionTokens: number;
24
+ totalTokens: number;
25
+ };
26
+ }
27
+ export interface AIConfigResponse {
28
+ provider: AIProvider;
29
+ model: string;
30
+ apiKeyConfigured: boolean;
31
+ }
32
+ export interface VerificationEvidence {
33
+ pageNumber: number;
34
+ excerpt: string;
35
+ supportsAnswer: boolean;
36
+ }
37
+ export interface AIVerificationResult {
38
+ questionId: string;
39
+ status: 'verified' | 'needs_improvement' | 'error';
40
+ feedback?: string;
41
+ suggestions?: string[];
42
+ confidence: number;
43
+ qualityScore?: number;
44
+ evidence?: VerificationEvidence[];
45
+ /** Optional model chain-of-thought / rationale from the host `LLMService`. */
46
+ reasoning?: string;
47
+ }
48
+ export interface VerifyAnswerRequest {
49
+ questionId: string;
50
+ questionText: string;
51
+ currentAnswer: string;
52
+ questionType?: string;
53
+ /** Allowed labels for select / multi_select style questions (optional). */
54
+ questionOptions?: string[];
55
+ context?: string;
56
+ pdfContent?: string;
57
+ }
58
+ export interface VerifyAnswerResponse {
59
+ result: AIVerificationResult;
60
+ }
61
+ export interface BatchVerifyRequest {
62
+ verifications: VerifyAnswerRequest[];
63
+ }
64
+ export interface BatchVerifyResponse {
65
+ results: AIVerificationResult[];
66
+ }
67
+ export declare class BackendAIService {
68
+ private baseUrl;
69
+ private config;
70
+ constructor(config: BackendAIConfig);
71
+ private makeRequest;
72
+ generateText(prompt: string, options?: {
73
+ temperature?: number;
74
+ maxTokens?: number;
75
+ provider?: AIProvider;
76
+ model?: string;
77
+ systemContext?: string;
78
+ }): Promise<{
79
+ text: string;
80
+ reasoning?: string;
81
+ }>;
82
+ getConfiguration(): Promise<AIConfigResponse>;
83
+ checkHealth(): Promise<{
84
+ status: string;
85
+ timestamp: string;
86
+ aiConfigured: boolean;
87
+ }>;
88
+ /**
89
+ * Verify a single answer for quality and completeness
90
+ */
91
+ verifyAnswer(request: VerifyAnswerRequest): Promise<AIVerificationResult>;
92
+ /**
93
+ * Verify multiple answers in batch
94
+ */
95
+ verifyAnswersBatch(requests: VerifyAnswerRequest[]): Promise<AIVerificationResult[]>;
96
+ /**
97
+ * Get relevant PDF chunks using transformer-based semantic chunking (in-browser)
98
+ * Uses Xenova/all-MiniLM-L6-v2 for embedding + cosine similarity
99
+ */
100
+ getSemanticChunks(question: string, pages: Array<{
101
+ pageNumber: number;
102
+ text: string;
103
+ wordCount: number;
104
+ }>, maxTokens?: number): Promise<{
105
+ chunks: Array<{
106
+ text: string;
107
+ pageNumber: number;
108
+ similarity: number;
109
+ tokenEstimate: number;
110
+ }>;
111
+ totalTokens: number;
112
+ totalChunks: number;
113
+ }>;
114
+ generateSuggestions(request: GenerateSuggestionsRequest): Promise<GenerateSuggestionsResponse>;
115
+ isConfigured(): boolean;
116
+ getCurrentConfig(): {
117
+ provider: AIProvider;
118
+ model: string;
119
+ apiKeyConfigured: boolean;
120
+ };
121
+ }
122
+ /**
123
+ * Unified AI Service that automatically chooses between frontend and backend
124
+ * - Uses frontend service when user provides their own API keys (privacy-first)
125
+ * - Uses backend service when using shared/environment keys
126
+ */
127
+ export declare class UnifiedAIService {
128
+ private frontendService;
129
+ private backendService;
130
+ private config;
131
+ constructor(config: {
132
+ provider: AIProvider;
133
+ openaiModel: OpenAIModel;
134
+ groqModel: GroqModel;
135
+ mistralModel: MistralModel;
136
+ openaiApiKey: string;
137
+ groqApiKey: string;
138
+ mistralApiKey: string;
139
+ useEnvironmentKeys: boolean;
140
+ });
141
+ /**
142
+ * Determines if we should use frontend service (user's own API keys)
143
+ * Returns true if user has provided their own API keys and is not using environment keys
144
+ */
145
+ private shouldUseFrontend;
146
+ private getFrontendService;
147
+ private getBackendService;
148
+ generateText(prompt: string, options?: {
149
+ temperature?: number;
150
+ maxTokens?: number;
151
+ provider?: AIProvider;
152
+ model?: string;
153
+ systemContext?: string;
154
+ }): Promise<{
155
+ text: string;
156
+ reasoning?: string;
157
+ }>;
158
+ generateSuggestions(request: GenerateSuggestionsRequest): Promise<GenerateSuggestionsResponse>;
159
+ getSemanticChunks(question: string, pages: Array<{
160
+ pageNumber: number;
161
+ text: string;
162
+ wordCount: number;
163
+ }>, maxTokens?: number): Promise<{
164
+ chunks: Array<{
165
+ text: string;
166
+ pageNumber: number;
167
+ similarity: number;
168
+ tokenEstimate: number;
169
+ }>;
170
+ totalTokens: number;
171
+ totalChunks: number;
172
+ }>;
173
+ getConfiguration(): Promise<AIConfigResponse>;
174
+ checkHealth(): Promise<{
175
+ status: string;
176
+ timestamp: string;
177
+ aiConfigured: boolean;
178
+ }>;
179
+ isConfigured(): boolean;
180
+ getCurrentConfig(): {
181
+ provider: AIProvider;
182
+ model: string;
183
+ apiKeyConfigured: boolean;
184
+ };
185
+ verifyAnswer(request: VerifyAnswerRequest): Promise<AIVerificationResult>;
186
+ verifyAnswersBatch(requests: VerifyAnswerRequest[]): Promise<AIVerificationResult[]>;
187
+ }
188
+ export declare const useBackendAIService: () => BackendAIService;
189
+ export declare const useAIService: () => UnifiedAIService;
190
+ export declare const createDefaultBackendAIService: () => BackendAIService;
191
+ export declare const createDefaultAIService: () => UnifiedAIService;
@@ -0,0 +1,4 @@
1
+ import { TypedUseSelectorHook } from 'react-redux';
2
+ import type { RootState, AppDispatch } from './store';
3
+ export declare const useAppDispatch: () => AppDispatch;
4
+ export declare const useAppSelector: TypedUseSelectorHook<RootState>;
@@ -0,0 +1,21 @@
1
+ export declare const OPENAI_MODELS: readonly ["gpt-4o", "gpt-4o-mini", "gpt-4-turbo", "gpt-4", "gpt-3.5-turbo"];
2
+ export declare const GROQ_MODELS: readonly ["llama-3.1-8b-instant", "llama-3.1-70b-versatile", "llama-3.1-405b-reasoning", "mixtral-8x7b-32768", "gemma-7b-it", "deepseek-r1-distill-llama-70b"];
3
+ export declare const MISTRAL_MODELS: readonly ["mistral-large-latest", "mistral-medium-latest", "mistral-small-latest", "pixtral-large-latest", "open-mistral-nemo"];
4
+ export type OpenAIModel = (typeof OPENAI_MODELS)[number];
5
+ export type GroqModel = (typeof GROQ_MODELS)[number];
6
+ export type MistralModel = (typeof MISTRAL_MODELS)[number];
7
+ export type AIProvider = 'openai' | 'groq' | 'mistral';
8
+ export interface InitialState {
9
+ provider: AIProvider;
10
+ openaiModel: OpenAIModel;
11
+ groqModel: GroqModel;
12
+ mistralModel: MistralModel;
13
+ openaiApiKey: string;
14
+ groqApiKey: string;
15
+ mistralApiKey: string;
16
+ isConfigured: boolean;
17
+ useEnvironmentKeys: boolean;
18
+ }
19
+ export declare const setProvider: import("@reduxjs/toolkit").ActionCreatorWithPayload<AIProvider, "ai/setProvider">, setOpenAIModel: import("@reduxjs/toolkit").ActionCreatorWithPayload<"gpt-4o" | "gpt-4o-mini" | "gpt-4-turbo" | "gpt-4" | "gpt-3.5-turbo", "ai/setOpenAIModel">, setGroqModel: import("@reduxjs/toolkit").ActionCreatorWithPayload<"llama-3.1-8b-instant" | "llama-3.1-70b-versatile" | "llama-3.1-405b-reasoning" | "mixtral-8x7b-32768" | "gemma-7b-it" | "deepseek-r1-distill-llama-70b", "ai/setGroqModel">, setMistralModel: import("@reduxjs/toolkit").ActionCreatorWithPayload<"mistral-large-latest" | "mistral-medium-latest" | "mistral-small-latest" | "pixtral-large-latest" | "open-mistral-nemo", "ai/setMistralModel">, setOpenAIApiKey: import("@reduxjs/toolkit").ActionCreatorWithPayload<string, "ai/setOpenAIApiKey">, setGroqApiKey: import("@reduxjs/toolkit").ActionCreatorWithPayload<string, "ai/setGroqApiKey">, setMistralApiKey: import("@reduxjs/toolkit").ActionCreatorWithPayload<string, "ai/setMistralApiKey">, setIsConfigured: import("@reduxjs/toolkit").ActionCreatorWithPayload<boolean, "ai/setIsConfigured">, setUseEnvironmentKeys: import("@reduxjs/toolkit").ActionCreatorWithPayload<boolean, "ai/setUseEnvironmentKeys">, resetConfiguration: import("@reduxjs/toolkit").ActionCreatorWithoutPayload<"ai/resetConfiguration">, clearStoredConfiguration: import("@reduxjs/toolkit").ActionCreatorWithoutPayload<"ai/clearStoredConfiguration">;
20
+ declare const _default: import("redux").Reducer<InitialState>;
21
+ export default _default;
@@ -0,0 +1,9 @@
1
+ export declare const store: import("@reduxjs/toolkit").EnhancedStore<{
2
+ ai: import("./slices/aiSlice").InitialState;
3
+ }, import("redux").UnknownAction, import("@reduxjs/toolkit").Tuple<[import("redux").StoreEnhancer<{
4
+ dispatch: import("redux-thunk").ThunkDispatch<{
5
+ ai: import("./slices/aiSlice").InitialState;
6
+ }, undefined, import("redux").UnknownAction>;
7
+ }>, import("redux").StoreEnhancer]>>;
8
+ export type RootState = ReturnType<typeof store.getState>;
9
+ export type AppDispatch = typeof store.dispatch;
@@ -0,0 +1,39 @@
1
+ export interface ParentContext {
2
+ questionText: string;
3
+ answer: string | object;
4
+ questionId: string;
5
+ questionType?: string;
6
+ parentChain?: ParentContext[];
7
+ }
8
+ export interface SiblingContext {
9
+ questionText: string;
10
+ answer: string | object;
11
+ questionId: string;
12
+ answeredAt: number;
13
+ }
14
+ export interface PreviousEntryContext {
15
+ entryNumber: number;
16
+ questions: Array<{
17
+ questionText: string;
18
+ answer: string | object;
19
+ questionId: string;
20
+ }>;
21
+ }
22
+ export interface ContextGatheringConfig {
23
+ includeParent: boolean;
24
+ includeSiblings: boolean;
25
+ maxSiblings: number;
26
+ includePreviousEntries: boolean;
27
+ maxPreviousEntries: number;
28
+ maxAnswerLength: number;
29
+ tokenLimits?: Partial<TokenLimits>;
30
+ }
31
+ export interface TokenLimits {
32
+ parentContext: number;
33
+ siblingContext: number;
34
+ previousEntryContext: number;
35
+ perSibling: number;
36
+ perPreviousEntry: number;
37
+ }
38
+ export declare const DEFAULT_TOKEN_LIMITS: TokenLimits;
39
+ export declare const DEFAULT_CONTEXT_CONFIG: ContextGatheringConfig;
@@ -0,0 +1,39 @@
1
+ import type { SiblingContext, PreviousEntryContext, ContextGatheringConfig, ParentContext, TokenLimits } from '../types/context';
2
+ import { TokenEstimator } from './tokenEstimator';
3
+ interface QuestionDefinition {
4
+ id: string;
5
+ label?: string;
6
+ [key: string]: any;
7
+ }
8
+ export declare class ContextGatherer {
9
+ private config;
10
+ private tokenEstimator;
11
+ private visitedQuestions;
12
+ constructor(config?: Partial<ContextGatheringConfig>, tokenLimits?: Partial<TokenLimits>);
13
+ gatherSiblingContext(currentQuestionId: string, siblingQuestionIds: string[], allAnswers: Record<string, any>, questionDefinitions: Record<string, QuestionDefinition>): SiblingContext[];
14
+ gatherPreviousEntryContext(currentEntryIndex: number, allEntries: any[], questionDefinitions: QuestionDefinition[]): PreviousEntryContext[];
15
+ private formatAnswer;
16
+ private isAnswerValid;
17
+ private getAnswerTimestamp;
18
+ updateConfig(config: Partial<ContextGatheringConfig>): void;
19
+ getConfig(): ContextGatheringConfig;
20
+ truncateSiblingContext(siblingContext: SiblingContext[], maxTokens: number): SiblingContext[];
21
+ truncatePreviousEntryContext(previousEntryContext: PreviousEntryContext[], maxTokens: number): PreviousEntryContext[];
22
+ private truncateEntryQuestions;
23
+ applyTokenLimits(contexts: {
24
+ parentContext?: ParentContext;
25
+ siblingContext?: SiblingContext[];
26
+ previousEntryContext?: PreviousEntryContext[];
27
+ }): {
28
+ truncated: boolean;
29
+ parentContext?: ParentContext;
30
+ siblingContext?: SiblingContext[];
31
+ previousEntryContext?: PreviousEntryContext[];
32
+ };
33
+ getTokenEstimator(): TokenEstimator;
34
+ private resetVisitedQuestions;
35
+ private hasVisitedQuestion;
36
+ private markQuestionVisited;
37
+ }
38
+ export declare const contextGatherer: ContextGatherer;
39
+ export {};
@@ -0,0 +1,15 @@
1
+ export interface FuzzyMatchResult {
2
+ found: boolean;
3
+ startIndex: number;
4
+ endIndex: number;
5
+ similarity: number;
6
+ matchedText: string;
7
+ }
8
+ export declare function normalizeForMatching(text: string): string;
9
+ export declare function aggressiveNormalize(text: string): string;
10
+ export declare function findFuzzyMatch(pdfText: string, searchText: string, options?: {
11
+ similarityThreshold?: number;
12
+ useAggressiveNormalization?: boolean;
13
+ windowSizeMultiplier?: number;
14
+ }): FuzzyMatchResult;
15
+ export declare function findAllFuzzyMatches(pdfText: string, searchText: string, options?: Parameters<typeof findFuzzyMatch>[2]): FuzzyMatchResult[];
@@ -0,0 +1,25 @@
1
+ import type { PDFDocumentProxy } from 'pdfjs-dist/types/src/display/api';
2
+ import type { Evidence, EvidenceHighlight, HighlightRect } from './suggestions';
3
+ export declare class PDFTextExtractor {
4
+ private fullTextCache;
5
+ private pageTextCache;
6
+ private documentCache;
7
+ extractFullText(pdfUrl: string): Promise<string>;
8
+ extractPageText(pdfUrl: string, pageNumber: number): Promise<string>;
9
+ extractPageRange(pdfUrl: string, startPage: number, endPage: number): Promise<string>;
10
+ clearCache(): void;
11
+ clearDocumentCache(pdfUrl: string): void;
12
+ private loadDocument;
13
+ private extractPageTextInternal;
14
+ getDocumentInfo(pdfUrl: string): Promise<{
15
+ numPages: number;
16
+ filename: string;
17
+ }>;
18
+ }
19
+ export declare const pdfTextExtractor: PDFTextExtractor;
20
+ export declare function loadPDFDocument(pdfUrl: string): Promise<PDFDocumentProxy>;
21
+ export declare function getCachedDocument(pdfUrl: string): PDFDocumentProxy | null;
22
+ export declare function generateEvidenceHighlight(pdfDoc: PDFDocumentProxy, pageWidth: number, evidence: Evidence, suggestionId: string): Promise<EvidenceHighlight | null>;
23
+ export declare function generateEvidenceHighlights(pdfDoc: PDFDocumentProxy, pageWidth: number, evidenceList: Evidence[], suggestionId: string): Promise<EvidenceHighlight[]>;
24
+ export declare function evidenceHighlightsToPageMap(highlights: EvidenceHighlight[]): Record<number, HighlightRect[]>;
25
+ export declare function generateSingleEvidenceHighlightMap(pdfDoc: PDFDocumentProxy, pageWidth: number, evidence: Evidence, suggestionId: string): Promise<Record<number, HighlightRect[]>>;
@@ -0,0 +1,10 @@
1
+ export declare function defaultPdfWorkerSrc(): string;
2
+ type PdfJsWorkerHost = {
3
+ GlobalWorkerOptions: {
4
+ workerSrc: string;
5
+ };
6
+ };
7
+ export declare function configurePdfWorker(workerSrc?: string): void;
8
+ /** Configure worker on react-pdf's pdfjs instance (must run after `react-pdf` import). */
9
+ export declare function configureReactPdfWorker(reactPdfJs: PdfJsWorkerHost, workerSrc?: string): void;
10
+ export {};
@@ -0,0 +1,22 @@
1
+ export interface RobustMatchResult {
2
+ found: boolean;
3
+ startIndex: number;
4
+ endIndex: number;
5
+ confidence: number;
6
+ matchedText: string;
7
+ strategy: 'exact' | 'normalized' | 'aggressive' | 'fuzzy' | 'token' | 'partial';
8
+ metadata?: {
9
+ skippedReferences?: string[];
10
+ similarity?: number;
11
+ };
12
+ }
13
+ export interface RobustMatchOptions {
14
+ similarityThreshold?: number;
15
+ allowSkipReferences?: boolean;
16
+ minTokenMatch?: number;
17
+ tryAllStrategies?: boolean;
18
+ enablePartialMatch?: boolean;
19
+ }
20
+ export declare function findRobustMatch(pdfText: string, searchText: string, options?: RobustMatchOptions): RobustMatchResult;
21
+ export declare function preprocessSearchText(text: string): string;
22
+ export declare function findAllRobustMatches(pdfText: string, searchTexts: string[], options?: RobustMatchOptions): RobustMatchResult[];
@@ -0,0 +1,27 @@
1
+ interface PageContent {
2
+ pageNumber: number;
3
+ text: string;
4
+ wordCount: number;
5
+ }
6
+ interface SemanticChunk {
7
+ text: string;
8
+ pageNumber: number;
9
+ startIndex: number;
10
+ endIndex: number;
11
+ tokenEstimate: number;
12
+ }
13
+ interface SemanticChunkWithScore extends SemanticChunk {
14
+ similarity: number;
15
+ }
16
+ declare class FrontendSemanticChunker {
17
+ private model;
18
+ private modelLoading;
19
+ initialize(): Promise<void>;
20
+ private splitIntoChunks;
21
+ private embed;
22
+ private cosineSimilarity;
23
+ findRelevantChunks(question: string, pages: PageContent[], maxTokens?: number): Promise<SemanticChunkWithScore[]>;
24
+ isInitialized(): boolean;
25
+ }
26
+ export declare const frontendSemanticChunker: FrontendSemanticChunker;
27
+ export {};
@@ -0,0 +1,13 @@
1
+ export interface SimpleMatchResult {
2
+ found: boolean;
3
+ startIndex: number;
4
+ endIndex: number;
5
+ confidence: number;
6
+ strategy: 'exact' | 'normalized' | 'none';
7
+ matchedText: string;
8
+ }
9
+ export declare function normalizeText(text: string): string;
10
+ export declare function findSimpleMatch(pdfText: string, searchText: string, options?: {
11
+ maxSearchTime?: number;
12
+ }): SimpleMatchResult;
13
+ export declare function preprocessSearchText(text: string): string;
@@ -0,0 +1,34 @@
1
+ export interface PageContent {
2
+ pageNumber: number;
3
+ text: string;
4
+ wordCount: number;
5
+ }
6
+ export interface DocumentMetadata {
7
+ filename: string;
8
+ totalPages: number;
9
+ totalWords: number;
10
+ extractedAt: number;
11
+ }
12
+ export interface StructuredDocument {
13
+ metadata: DocumentMetadata;
14
+ pages: PageContent[];
15
+ fullText: string;
16
+ }
17
+ export interface RetrievalResult {
18
+ content: string;
19
+ pages: number[];
20
+ tokenEstimate: number;
21
+ }
22
+ export declare class StructuredPDFExtractor {
23
+ private documentCache;
24
+ private pdfDocCache;
25
+ private loadDocument;
26
+ private extractPageText;
27
+ extractStructuredDocument(pdfUrl: string, filename?: string): Promise<StructuredDocument>;
28
+ getPageContent(document: StructuredDocument, pageNumbers: number[]): RetrievalResult;
29
+ getFullContent(document: StructuredDocument): RetrievalResult;
30
+ formatFullDocumentWithPageMarkers(document: StructuredDocument): string;
31
+ clearCache(pdfUrl: string): void;
32
+ clearAllCaches(): void;
33
+ }
34
+ export declare const structuredPdfExtractor: StructuredPDFExtractor;
@@ -0,0 +1,88 @@
1
+ export interface AppError extends Error {
2
+ status?: number;
3
+ requiresAuth?: boolean;
4
+ resetIn?: number;
5
+ resetAt?: string;
6
+ }
7
+ export interface Evidence {
8
+ pageNumber: number;
9
+ excerpt: string;
10
+ context?: string;
11
+ startIndex?: number;
12
+ endIndex?: number;
13
+ }
14
+ export interface HighlightRect {
15
+ left: number;
16
+ top: number;
17
+ width: number;
18
+ height: number;
19
+ }
20
+ export interface EvidenceHighlight {
21
+ evidence: Evidence;
22
+ suggestionId: string;
23
+ rects: HighlightRect[];
24
+ }
25
+ export interface Suggestion {
26
+ id: string;
27
+ rank: number;
28
+ text: string | string[];
29
+ confidence: number;
30
+ evidence: Evidence[];
31
+ createdAt: number;
32
+ }
33
+ export declare function suggestionTextToString(text: string | string[] | any): string;
34
+ export interface FeedbackData {
35
+ suggestionId: string;
36
+ questionId: string;
37
+ rating: 'positive' | 'negative';
38
+ comment?: string;
39
+ timestamp: number;
40
+ userId?: string;
41
+ suggestionText?: string;
42
+ suggestionRank?: number;
43
+ }
44
+ export interface GenerateSuggestionsRequest {
45
+ questionText: string;
46
+ questionType: string;
47
+ questionOptions?: string[];
48
+ pdfContent: string;
49
+ pdfMetadata?: {
50
+ filename: string;
51
+ totalPages: number;
52
+ };
53
+ provider?: string;
54
+ model?: string;
55
+ previousFeedback?: FeedbackData[];
56
+ contextHistory?: Array<{
57
+ id: string;
58
+ type: string;
59
+ content: string;
60
+ timestamp: number;
61
+ metadata?: any;
62
+ }>;
63
+ parentContext?: import('../types/context').ParentContext;
64
+ siblingContext?: import('../types/context').SiblingContext[];
65
+ previousEntryContext?: import('../types/context').PreviousEntryContext[];
66
+ }
67
+ export interface GenerateSuggestionsResponse {
68
+ suggestions: Suggestion[];
69
+ reasoning?: string;
70
+ usage?: {
71
+ promptTokens: number;
72
+ completionTokens: number;
73
+ totalTokens: number;
74
+ };
75
+ }
76
+ export declare const isAuthError: (error: unknown) => boolean;
77
+ export declare const isRateLimitError: (error: unknown) => boolean;
78
+ export declare const isConfigError: (error: unknown) => boolean;
79
+ export declare const formatErrorMessage: (error: unknown, context?: string) => string;
80
+ export declare class FeedbackService {
81
+ static saveFeedback(feedback: FeedbackData): void;
82
+ static getAllFeedback(): FeedbackData[];
83
+ static getFeedbackForQuestion(questionId: string): FeedbackData[];
84
+ static clearFeedbackForQuestion(questionId: string): void;
85
+ static deleteFeedbackBySuggestionId(suggestionId: string): void;
86
+ static deleteFeedbackBySuggestionIds(suggestionIds: string[]): void;
87
+ static clearAllFeedback(): void;
88
+ }