Skip to content

Commit 5842f3b

Browse files
Copilotbenfoxall
andcommitted
Use global Summarizer constructor and add testSummarizer function
Co-authored-by: benfoxall <51385+benfoxall@users.noreply.github.com>
1 parent dcb7b15 commit 5842f3b

1 file changed

Lines changed: 112 additions & 31 deletions

File tree

assets/prompt-api-summaries.js

Lines changed: 112 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@
55
* for each hack day entry on the Previous Hacks page.
66
*
77
* Summarizer API docs: https://developer.chrome.com/docs/ai/summarizer-api
8-
* MDN: https://developer.mozilla.org/en-US/docs/Web/API/Summarizer
8+
* MDN: https://developer.mozilla.org/en-US/docs/Web/API/Summarizer_API/Using
99
*
1010
* Summaries are cached in IndexedDB using a hash of content + context
1111
* to avoid regenerating unchanged content.
@@ -25,7 +25,7 @@
2525
// Store parsed feed items for reuse
2626
let feedItems = null;
2727
// Store the summarizer instance
28-
let summarizer = null;
28+
let summarizerInstance = null;
2929
// Store the IndexedDB instance
3030
let db = null;
3131

@@ -133,18 +133,19 @@
133133
* @returns {Promise<boolean>}
134134
*/
135135
async function isSummarizerAvailable() {
136-
if (!('ai' in self) || !('summarizer' in self.ai)) {
137-
console.info('[Summarizer] Not available: ai.summarizer not found in window');
136+
// Check for global Summarizer constructor (new API)
137+
if (typeof Summarizer === 'undefined') {
138+
console.info('[Summarizer] Not available: Summarizer constructor not found');
138139
return false;
139140
}
140141

141142
try {
142-
const capabilities = await self.ai.summarizer.capabilities();
143-
if (capabilities.available === 'no') {
144-
console.info('[Summarizer] Not available: capabilities.available is "no"');
143+
const availability = await Summarizer.availability();
144+
if (availability === 'unavailable') {
145+
console.info('[Summarizer] Not available: availability is "unavailable"');
145146
return false;
146147
}
147-
console.info('[Summarizer] Available with capabilities:', capabilities);
148+
console.info('[Summarizer] Available with availability:', availability);
148149
return true;
149150
} catch (error) {
150151
console.info('[Summarizer] Not available due to error:', error.message);
@@ -158,18 +159,18 @@
158159
* @returns {Promise<Object|null>}
159160
*/
160161
async function getSummarizer(sharedContext) {
161-
if (summarizer) {
162-
return summarizer;
162+
if (summarizerInstance) {
163+
return summarizerInstance;
163164
}
164165

165166
try {
166-
summarizer = await self.ai.summarizer.create({
167+
summarizerInstance = await Summarizer.create({
167168
sharedContext: sharedContext,
168169
type: 'tl;dr',
169170
length: 'short',
170171
format: 'plain-text'
171172
});
172-
return summarizer;
173+
return summarizerInstance;
173174
} catch (error) {
174175
console.error('[Summarizer] Failed to create summarizer:', error.message);
175176
return null;
@@ -264,47 +265,66 @@
264265
}
265266

266267
/**
267-
* Generate a summary for a hack day using the Summarizer API
268-
* @param {Object} item - Feed item with title, url, description
268+
* Generate a summary for content using the Summarizer API
269+
* @param {string} content - Content to summarize
269270
* @param {string} context - Context for summarization
271+
* @param {boolean} useCache - Whether to use caching (default: true)
270272
* @returns {Promise<string>}
271273
*/
272-
async function generateSummary(item, context) {
274+
async function generateSummaryForContent(content, context, useCache = true) {
273275
// Skip if there's no real content
274-
if (!item.description || item.description.length < 20) {
276+
if (!content || content.length < 20) {
275277
return '';
276278
}
277279

278280
// Create cache key from content + context
279-
const cacheKey = await hashString(item.description + context);
281+
const cacheKey = await hashString(content + context);
280282

281-
// Check cache first
282-
const cached = await getCachedSummary(cacheKey);
283-
if (cached) {
284-
console.info('[Summarizer] Using cached summary for', item.title);
285-
return cached;
283+
// Check cache first (if enabled)
284+
if (useCache) {
285+
const cached = await getCachedSummary(cacheKey);
286+
if (cached) {
287+
console.info('[Summarizer] Using cached summary');
288+
return cached;
289+
}
286290
}
287291

288-
const summarizerInstance = await getSummarizer(context);
289-
if (!summarizerInstance) {
292+
const summarizer = await getSummarizer(context);
293+
if (!summarizer) {
290294
return '';
291295
}
292296

293297
try {
294-
const content = `Hack day: ${item.title}\n\n${item.description}`;
295-
const result = await summarizerInstance.summarize(content);
298+
const result = await summarizer.summarize(content);
296299
const summary = result.trim();
297300

298301
// Cache the result
299-
await cacheSummary(cacheKey, summary);
302+
if (useCache) {
303+
await cacheSummary(cacheKey, summary);
304+
}
300305

301306
return summary;
302307
} catch (error) {
303-
console.warn('[Summarizer] Failed to generate summary for', item.title, ':', error.message);
308+
console.warn('[Summarizer] Failed to generate summary:', error.message);
304309
return '';
305310
}
306311
}
307312

313+
/**
314+
* Generate a summary for a hack day using the Summarizer API
315+
* @param {Object} item - Feed item with title, url, description
316+
* @param {string} context - Context for summarization
317+
* @returns {Promise<string>}
318+
*/
319+
async function generateSummary(item, context) {
320+
const content = `Hack day: ${item.title}\n\n${item.description}`;
321+
const summary = await generateSummaryForContent(content, context);
322+
if (summary) {
323+
console.info('[Summarizer] Generated summary for', item.title);
324+
}
325+
return summary;
326+
}
327+
308328
/**
309329
* Update all taglines on the page with generated summaries
310330
* @param {string} context - The context to use for summarization
@@ -393,13 +413,13 @@
393413
});
394414

395415
// Destroy existing summarizer to get fresh results with new context
396-
if (summarizer) {
416+
if (summarizerInstance) {
397417
try {
398-
summarizer.destroy();
418+
summarizerInstance.destroy();
399419
} catch (e) {
400420
// Ignore errors on destroy
401421
}
402-
summarizer = null;
422+
summarizerInstance = null;
403423
}
404424

405425
await updateTaglines(context);
@@ -415,6 +435,67 @@
415435
*/
416436
window.clearHackSummaryCache = clearCache;
417437

438+
/**
439+
* Test function to generate summaries without DOM changes
440+
* Useful for testing the Summarizer API in Chrome DevTools
441+
*
442+
* @param {number} count - Number of summaries to generate (default: 3)
443+
* @param {string} context - Custom context for summarization
444+
* @example
445+
* // From browser console:
446+
* testSummarizer()
447+
* testSummarizer(5)
448+
* testSummarizer(2, "What projects did people work on?")
449+
*/
450+
window.testSummarizer = async function(count = 3, context = DEFAULT_CONTEXT) {
451+
console.info('[Summarizer] Testing Summarizer API...');
452+
453+
// Check availability
454+
const available = await isSummarizerAvailable();
455+
if (!available) {
456+
console.error('[Summarizer] API not available - cannot run test');
457+
return;
458+
}
459+
460+
// Load feed
461+
const items = await loadFeed();
462+
if (items.length === 0) {
463+
console.error('[Summarizer] No feed items available for testing');
464+
return;
465+
}
466+
467+
// Filter items with content
468+
const itemsWithContent = items.filter(item => item.description && item.description.length >= 20);
469+
const testItems = itemsWithContent.slice(0, count);
470+
471+
console.info(`[Summarizer] Generating ${testItems.length} test summaries with context: "${context}"`);
472+
console.info('---');
473+
474+
for (const item of testItems) {
475+
console.info(`Processing: ${item.title}`);
476+
const startTime = performance.now();
477+
478+
// Generate summary without caching for testing
479+
const summary = await generateSummaryForContent(
480+
`Hack day: ${item.title}\n\n${item.description}`,
481+
context,
482+
false // Skip cache for testing
483+
);
484+
485+
const elapsed = Math.round(performance.now() - startTime);
486+
487+
if (summary) {
488+
console.info(`✓ ${item.title} (${elapsed}ms):`);
489+
console.info(` "${summary}"`);
490+
} else {
491+
console.warn(`✗ ${item.title}: Failed to generate summary`);
492+
}
493+
console.info('---');
494+
}
495+
496+
console.info('[Summarizer] Test complete');
497+
};
498+
418499
// Run on page load
419500
if (document.readyState === 'loading') {
420501
document.addEventListener('DOMContentLoaded', () => updateTaglines());

0 commit comments

Comments
 (0)