milwright commited on
Commit
6e0c330
·
1 Parent(s): 9dafab7

refactor: reduce technical debt by removing unused methods and tool definitions

Browse files

- Remove unused questionTools from aiService constructor
- Remove unused getEnhancedFallback and getContextualHint methods
- Remove unused getContextualization method (duplicate)
- Remove unused helper methods from conversationManager
- Clean up unused word processing and variation methods
- Maintain only essential, actively used code paths

Files changed (2) hide show
  1. src/aiService.js +0 -153
  2. src/conversationManager.js +0 -57
src/aiService.js CHANGED
@@ -3,54 +3,6 @@ class OpenRouterService {
3
  this.apiUrl = 'https://openrouter.ai/api/v1/chat/completions';
4
  this.apiKey = this.getApiKey();
5
  this.model = 'google/gemma-3-27b-it:free';
6
-
7
- // Focused tool definitions for specific, non-overlapping question types
8
- this.questionTools = {
9
- part_of_speech: {
10
- name: 'identify_part_of_speech',
11
- description: 'Identify the grammatical category directly and clearly',
12
- parameters: {
13
- type: 'object',
14
- properties: {
15
- hint: { type: 'string', description: 'Direct answer: "This is a [noun/verb/adjective/adverb]" then add a simple, concrete clue about what type (e.g., "a thing", "an action", "describes something")' }
16
- },
17
- required: ['hint']
18
- }
19
- },
20
- sentence_role: {
21
- name: 'explain_sentence_role',
22
- description: 'Explain the structural function using context clues',
23
- parameters: {
24
- type: 'object',
25
- properties: {
26
- hint: { type: 'string', description: 'Point to specific words around the blank. Example: "Look at \'the whole ___ consisting of\' - what could contain something?" Focus on the immediate context.' }
27
- },
28
- required: ['hint']
29
- }
30
- },
31
- word_category: {
32
- name: 'categorize_word',
33
- description: 'State clearly if abstract or concrete',
34
- parameters: {
35
- type: 'object',
36
- properties: {
37
- hint: { type: 'string', description: 'Start simple: "This is abstract/concrete." Then give a relatable example or size clue: "Think about something very big/small" or "Like feelings/objects"' }
38
- },
39
- required: ['hint']
40
- }
41
- },
42
- synonym: {
43
- name: 'provide_synonym',
44
- description: 'Give clear synonym or similar word',
45
- parameters: {
46
- type: 'object',
47
- properties: {
48
- hint: { type: 'string', description: 'Direct synonyms or word families: "Try a word similar to [related word]" or "Think of another word for [meaning]"' }
49
- },
50
- required: ['hint']
51
- }
52
- }
53
- };
54
  }
55
 
56
  getApiKey() {
@@ -114,57 +66,6 @@ class OpenRouterService {
114
  }
115
  }
116
 
117
- getEnhancedFallback(questionType, word, sentence, bookTitle) {
118
- const fallbacks = {
119
- part_of_speech: `Consider what "${word}" is doing in the sentence. Is it a person, place, thing (noun), an action (verb), or describing something (adjective)?`,
120
- sentence_role: `Look at how "${word}" connects to other words around it. What is its job in making the sentence complete?`,
121
- word_category: `Think about whether "${word}" is something you can touch or see (concrete) or an idea/feeling (abstract).`,
122
- synonym: `What other word could replace "${word}" and keep the same meaning in this sentence?`
123
- };
124
-
125
- return fallbacks[questionType] || `Think about what "${word}" means in this classic literature context.`;
126
- }
127
-
128
- async getContextualHint(passage, wordToReplace, context) {
129
- if (!this.apiKey) {
130
- return 'API key required for contextual hints';
131
- }
132
-
133
- try {
134
- const response = await fetch(this.apiUrl, {
135
- method: 'POST',
136
- headers: {
137
- 'Content-Type': 'application/json',
138
- 'Authorization': `Bearer ${this.apiKey}`,
139
- 'HTTP-Referer': window.location.origin,
140
- 'X-Title': 'Cloze Reader'
141
- },
142
- body: JSON.stringify({
143
- model: this.model,
144
- messages: [{
145
- role: 'user',
146
- content: `In this passage: "${passage}"
147
-
148
- The word "${wordToReplace}" has been replaced with a blank. Give me a helpful hint about what word fits here, considering the context: "${context}".
149
-
150
- Provide a brief, educational hint that helps understand the word without giving it away directly.`
151
- }],
152
- max_tokens: 150,
153
- temperature: 0.7
154
- })
155
- });
156
-
157
- if (!response.ok) {
158
- throw new Error(`API request failed: ${response.status}`);
159
- }
160
-
161
- const data = await response.json();
162
- return data.choices[0].message.content.trim();
163
- } catch (error) {
164
- console.error('Error getting contextual hint:', error);
165
- return 'Unable to generate hint at this time';
166
- }
167
- }
168
 
169
  async selectSignificantWords(passage, count) {
170
  console.log('selectSignificantWords called with count:', count);
@@ -290,60 +191,6 @@ Passage: "${passage}"`
290
  }
291
  }
292
 
293
- async getContextualization(title, author, passage) {
294
- console.log('getContextualization called for:', title, 'by', author);
295
-
296
- // Check for API key at runtime
297
- const currentKey = this.getApiKey();
298
- if (currentKey && !this.apiKey) {
299
- this.apiKey = currentKey;
300
- }
301
-
302
- console.log('API key available for contextualization:', !!this.apiKey);
303
-
304
- if (!this.apiKey) {
305
- console.log('No API key, returning fallback contextualization');
306
- return `📚 Practice with classic literature from ${author}'s "${title}"`;
307
- }
308
-
309
- try {
310
- const response = await fetch(this.apiUrl, {
311
- method: 'POST',
312
- headers: {
313
- 'Content-Type': 'application/json',
314
- 'Authorization': `Bearer ${this.apiKey}`,
315
- 'HTTP-Referer': window.location.origin,
316
- 'X-Title': 'Cloze Reader'
317
- },
318
- body: JSON.stringify({
319
- model: this.model,
320
- messages: [{
321
- role: 'system',
322
- content: 'You are a literary expert providing brief educational context about classic literature. Always respond with exactly 2 sentences, no more. Avoid exaggerative adverbs. Be factual and restrained.'
323
- }, {
324
- role: 'user',
325
- content: `Provide educational context for this passage from "${title}" by ${author}: "${passage}"`
326
- }],
327
- max_tokens: 100,
328
- temperature: 0.3
329
- })
330
- });
331
-
332
- if (!response.ok) {
333
- const errorText = await response.text();
334
- console.error('Contextualization API error:', response.status, errorText);
335
- throw new Error(`API request failed: ${response.status}`);
336
- }
337
-
338
- const data = await response.json();
339
- const content = data.choices[0].message.content.trim();
340
- console.log('Contextualization received:', content);
341
- return content;
342
- } catch (error) {
343
- console.error('Error getting contextualization:', error);
344
- return `📚 Practice with classic literature from ${author}'s "${title}"`;
345
- }
346
- }
347
  }
348
 
349
  export { OpenRouterService as AIService };
 
3
  this.apiUrl = 'https://openrouter.ai/api/v1/chat/completions';
4
  this.apiKey = this.getApiKey();
5
  this.model = 'google/gemma-3-27b-it:free';
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
6
  }
7
 
8
  getApiKey() {
 
66
  }
67
  }
68
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
69
 
70
  async selectSignificantWords(passage, count) {
71
  console.log('selectSignificantWords called with count:', count);
 
191
  }
192
  }
193
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
194
  }
195
 
196
  export { OpenRouterService as AIService };
src/conversationManager.js CHANGED
@@ -129,63 +129,6 @@ class ChatService {
129
  };
130
  }
131
 
132
- // Helper method to get words before the target word
133
- getWordsBefore(sentence, targetWord, count = 3) {
134
- const words = sentence.split(/\s+/);
135
- const targetIndex = words.findIndex(word =>
136
- word.toLowerCase().replace(/[^\w]/g, '') === targetWord.toLowerCase()
137
- );
138
-
139
- if (targetIndex === -1) return "";
140
-
141
- const startIndex = Math.max(0, targetIndex - count);
142
- return words.slice(startIndex, targetIndex).join(' ');
143
- }
144
-
145
- // Helper method to get words after the target word
146
- getWordsAfter(sentence, targetWord, count = 3) {
147
- const words = sentence.split(/\s+/);
148
- const targetIndex = words.findIndex(word =>
149
- word.toLowerCase().replace(/[^\w]/g, '') === targetWord.toLowerCase()
150
- );
151
-
152
- if (targetIndex === -1) return "";
153
-
154
- const endIndex = Math.min(words.length, targetIndex + count + 1);
155
- return words.slice(targetIndex + 1, endIndex).join(' ');
156
- }
157
-
158
- // Process AI response to ensure quality and safety
159
- processAIResponse(rawResponse, targetWord) {
160
- let processed = rawResponse.trim();
161
-
162
- // Remove any accidental word reveals
163
- const variations = this.generateWordVariations(targetWord);
164
- variations.forEach(variation => {
165
- const regex = new RegExp(`\\b${variation}\\b`, 'gi');
166
- processed = processed.replace(regex, '[the word]');
167
- });
168
-
169
- return processed;
170
- }
171
-
172
- // Generate word variations to avoid accidental reveals
173
- generateWordVariations(word) {
174
- const variations = [word.toLowerCase()];
175
-
176
- // Add common variations
177
- if (word.endsWith('ing')) {
178
- variations.push(word.slice(0, -3));
179
- }
180
- if (word.endsWith('ed')) {
181
- variations.push(word.slice(0, -2));
182
- }
183
- if (word.endsWith('s')) {
184
- variations.push(word.slice(0, -1));
185
- }
186
-
187
- return variations;
188
- }
189
 
190
  // Clear conversations and reset tracking
191
  clearConversations() {
 
129
  };
130
  }
131
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
132
 
133
  // Clear conversations and reset tracking
134
  clearConversations() {