Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion trailblazers/dist/js/ai/ai-classifier.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import { updateDraftData } from '../drafts/draft-manager.js';
import { customAlert } from '../utils/dialog-utils.js';
import { getMonitor, runAIAction } from './ai-features.js';
import { isNativeAIFeature } from './ai-ui-utils.js';
import { refreshAIVisibility } from './ai-toggle.js';
import {
renderClassifierResults,
Expand Down Expand Up @@ -70,7 +71,7 @@ export async function initAIClassifier(ui, updateCallback) {
}

const input = `Title: ${title}\n\nContent: ${content}`;
const isNative = ClassifierClass.toString().includes('[native code]');
const isNative = isNativeAIFeature(ClassifierClass);

await runAIAction(
ui,
Expand Down
4 changes: 2 additions & 2 deletions trailblazers/dist/js/ai/ai-features.js
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import { detectLanguage } from './ai-language-detection.js';
import { customAlert } from '../utils/dialog-utils.js';
import { refreshAIVisibility } from './ai-toggle.js';
import { getMonitor, runAIAction } from './ai-ui-utils.js';
import { getMonitor, runAIAction, isNativeAIFeature } from './ai-ui-utils.js';

export { getMonitor, runAIAction };

Expand Down Expand Up @@ -36,7 +36,7 @@ async function runSummarizer(ui, type, input, targetInput, updateCallback) {
const btn =
type === 'headline' ? ui.aiSuggestTitleBtn : ui.aiSuggestDescriptionBtn;

const isNative = Summarizer.toString().includes('[native code]');
const isNative = isNativeAIFeature(Summarizer);

await runAIAction(
ui,
Expand Down
3 changes: 2 additions & 1 deletion trailblazers/dist/js/ai/ai-multimodal.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import { detectLanguage } from './ai-language-detection.js';
import { checkAIKeys } from './ai-config.js';
import { isNativeAIFeature } from './ai-ui-utils.js';

/** @type {Object} */
export const imageMetadataSchema = {
Expand Down Expand Up @@ -38,7 +39,7 @@ export async function generateImageMetadata(imageSource, ui) {
return null;
}

const isNative = LanguageModel.toString().includes('[native code]');
const isNative = isNativeAIFeature(LanguageModel);
if (!isNative && !checkAIKeys(ui)) {
return null;
}
Expand Down
3 changes: 2 additions & 1 deletion trailblazers/dist/js/ai/ai-rewriter.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import { detectLanguage } from './ai-language-detection.js';
import { customAlert, customConfirm } from '../utils/dialog-utils.js';
import { getMonitor, runAIAction } from './ai-features.js';
import { isNativeAIFeature } from './ai-ui-utils.js';
import { refreshAIVisibility } from './ai-toggle.js';

/**
Expand Down Expand Up @@ -89,7 +90,7 @@ export async function initAIRewriter(ui, updateCallback) {
return customAlert(ui, 'Please write some content first.');
}

const isNative = Rewriter.toString().includes('[native code]');
const isNative = isNativeAIFeature(Rewriter);

await runAIAction(
ui,
Expand Down
3 changes: 2 additions & 1 deletion trailblazers/dist/js/ai/ai-tag-suggestions.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import { detectLanguage } from './ai-language-detection.js';
import { customAlert } from '../utils/dialog-utils.js';
import { runAIAction } from './ai-features.js';
import { isNativeAIFeature } from './ai-ui-utils.js';
import { refreshAIVisibility } from './ai-toggle.js';
import { runTagGeneration } from './ai-tag-generator.js';

Expand Down Expand Up @@ -60,7 +61,7 @@ export async function initTagSuggestions(ui, updateCallback) {
return customAlert(ui, 'Please write some content first.');
}

const isNative = LanguageModel.toString().includes('[native code]');
const isNative = isNativeAIFeature(LanguageModel);

await runAIAction(
ui,
Expand Down
3 changes: 2 additions & 1 deletion trailblazers/dist/js/ai/ai-translator-core.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import { detectLanguage } from './ai-language-detection.js';
import { customAlert, customConfirm } from '../utils/dialog-utils.js';
import { runAIAction } from './ai-features.js';
import { isNativeAIFeature } from './ai-ui-utils.js';
import { updatePreview } from './ai-translator-preview.js';
import { drafts, currentDraftId } from '../drafts/draft-manager.js';
import { generateMarkdown } from '../utils/markdown-utils.js';
Expand Down Expand Up @@ -50,7 +51,7 @@ export async function runTranslation(
const preview = details.querySelector('.translation-preview');
const btn = details.querySelector('.translate-btn');

const isNative = Translator.toString().includes('[native code]');
const isNative = isNativeAIFeature(Translator);

await runAIAction(
ui,
Expand Down
19 changes: 19 additions & 0 deletions trailblazers/dist/js/ai/ai-ui-utils.js
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,25 @@ export const getMonitor = (ui, lang, modelName) => ({
},
});

/**
* Determines whether an on-device AI API (Writer, Rewriter, Summarizer, etc.)
* can run without a cloud AI API key. A `Function.toString()` "[native code]"
* check misses the case where `built-in-ai-task-apis-polyfills` installs a
* plain-class fallback that itself runs on the browser's native, on-device
* Prompt API (`LanguageModel`) — that path needs no key either.
* @param {Function} apiClass - The task API class (e.g. `Writer`, `Rewriter`).
* @return {boolean} True if the feature can run without a cloud AI API key.
*/
export function isNativeAIFeature(apiClass) {
if (typeof apiClass !== 'function') {
return false;
}
if (!apiClass.__isPolyfill) {
return true;
}
return typeof LanguageModel !== 'undefined' && !LanguageModel.__isPolyfill;
}

/**
* Executes an AI action with UI feedback (loading state).
* @param {Object} ui - The UI elements.
Expand Down
3 changes: 2 additions & 1 deletion trailblazers/dist/js/ai/ai-writer.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import { detectLanguage } from './ai-language-detection.js';
import { customAlert, customConfirm } from '../utils/dialog-utils.js';
import { getMonitor, runAIAction } from './ai-features.js';
import { isNativeAIFeature } from './ai-ui-utils.js';
import { refreshAIVisibility } from './ai-toggle.js';

/**
Expand Down Expand Up @@ -79,7 +80,7 @@ export async function initAIWriter(ui, updateCallback) {
}
}

const isNative = Writer.toString().includes('[native code]');
const isNative = isNativeAIFeature(Writer);

await runAIAction(
ui,
Expand Down
3 changes: 2 additions & 1 deletion trailblazers/public/js/ai/ai-classifier.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import { updateDraftData } from '../drafts/draft-manager.js';
import { customAlert } from '../utils/dialog-utils.js';
import { getMonitor, runAIAction } from './ai-features.js';
import { isNativeAIFeature } from './ai-ui-utils.js';
import { refreshAIVisibility } from './ai-toggle.js';
import {
renderClassifierResults,
Expand Down Expand Up @@ -70,7 +71,7 @@ export async function initAIClassifier(ui, updateCallback) {
}

const input = `Title: ${title}\n\nContent: ${content}`;
const isNative = ClassifierClass.toString().includes('[native code]');
const isNative = isNativeAIFeature(ClassifierClass);

await runAIAction(
ui,
Expand Down
4 changes: 2 additions & 2 deletions trailblazers/public/js/ai/ai-features.js
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import { detectLanguage } from './ai-language-detection.js';
import { customAlert } from '../utils/dialog-utils.js';
import { refreshAIVisibility } from './ai-toggle.js';
import { getMonitor, runAIAction } from './ai-ui-utils.js';
import { getMonitor, runAIAction, isNativeAIFeature } from './ai-ui-utils.js';

export { getMonitor, runAIAction };

Expand Down Expand Up @@ -36,7 +36,7 @@ async function runSummarizer(ui, type, input, targetInput, updateCallback) {
const btn =
type === 'headline' ? ui.aiSuggestTitleBtn : ui.aiSuggestDescriptionBtn;

const isNative = Summarizer.toString().includes('[native code]');
const isNative = isNativeAIFeature(Summarizer);

await runAIAction(
ui,
Expand Down
3 changes: 2 additions & 1 deletion trailblazers/public/js/ai/ai-multimodal.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import { detectLanguage } from './ai-language-detection.js';
import { checkAIKeys } from './ai-config.js';
import { isNativeAIFeature } from './ai-ui-utils.js';

/** @type {Object} */
export const imageMetadataSchema = {
Expand Down Expand Up @@ -38,7 +39,7 @@ export async function generateImageMetadata(imageSource, ui) {
return null;
}

const isNative = LanguageModel.toString().includes('[native code]');
const isNative = isNativeAIFeature(LanguageModel);
if (!isNative && !checkAIKeys(ui)) {
return null;
}
Expand Down
3 changes: 2 additions & 1 deletion trailblazers/public/js/ai/ai-rewriter.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import { detectLanguage } from './ai-language-detection.js';
import { customAlert, customConfirm } from '../utils/dialog-utils.js';
import { getMonitor, runAIAction } from './ai-features.js';
import { isNativeAIFeature } from './ai-ui-utils.js';
import { refreshAIVisibility } from './ai-toggle.js';

/**
Expand Down Expand Up @@ -89,7 +90,7 @@ export async function initAIRewriter(ui, updateCallback) {
return customAlert(ui, 'Please write some content first.');
}

const isNative = Rewriter.toString().includes('[native code]');
const isNative = isNativeAIFeature(Rewriter);

await runAIAction(
ui,
Expand Down
3 changes: 2 additions & 1 deletion trailblazers/public/js/ai/ai-tag-suggestions.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import { detectLanguage } from './ai-language-detection.js';
import { customAlert } from '../utils/dialog-utils.js';
import { runAIAction } from './ai-features.js';
import { isNativeAIFeature } from './ai-ui-utils.js';
import { refreshAIVisibility } from './ai-toggle.js';
import { runTagGeneration } from './ai-tag-generator.js';

Expand Down Expand Up @@ -60,7 +61,7 @@ export async function initTagSuggestions(ui, updateCallback) {
return customAlert(ui, 'Please write some content first.');
}

const isNative = LanguageModel.toString().includes('[native code]');
const isNative = isNativeAIFeature(LanguageModel);

await runAIAction(
ui,
Expand Down
3 changes: 2 additions & 1 deletion trailblazers/public/js/ai/ai-translator-core.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import { detectLanguage } from './ai-language-detection.js';
import { customAlert, customConfirm } from '../utils/dialog-utils.js';
import { runAIAction } from './ai-features.js';
import { isNativeAIFeature } from './ai-ui-utils.js';
import { updatePreview } from './ai-translator-preview.js';
import { drafts, currentDraftId } from '../drafts/draft-manager.js';
import { generateMarkdown } from '../utils/markdown-utils.js';
Expand Down Expand Up @@ -50,7 +51,7 @@ export async function runTranslation(
const preview = details.querySelector('.translation-preview');
const btn = details.querySelector('.translate-btn');

const isNative = Translator.toString().includes('[native code]');
const isNative = isNativeAIFeature(Translator);

await runAIAction(
ui,
Expand Down
19 changes: 19 additions & 0 deletions trailblazers/public/js/ai/ai-ui-utils.js
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,25 @@ export const getMonitor = (ui, lang, modelName) => ({
},
});

/**
* Determines whether an on-device AI API (Writer, Rewriter, Summarizer, etc.)
* can run without a cloud AI API key. A `Function.toString()` "[native code]"
* check misses the case where `built-in-ai-task-apis-polyfills` installs a
* plain-class fallback that itself runs on the browser's native, on-device
* Prompt API (`LanguageModel`) — that path needs no key either.
* @param {Function} apiClass - The task API class (e.g. `Writer`, `Rewriter`).
* @return {boolean} True if the feature can run without a cloud AI API key.
*/
export function isNativeAIFeature(apiClass) {
if (typeof apiClass !== 'function') {
return false;
}
if (!apiClass.__isPolyfill) {
return true;
}
return typeof LanguageModel !== 'undefined' && !LanguageModel.__isPolyfill;
}

/**
* Executes an AI action with UI feedback (loading state).
* @param {Object} ui - The UI elements.
Expand Down
3 changes: 2 additions & 1 deletion trailblazers/public/js/ai/ai-writer.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import { detectLanguage } from './ai-language-detection.js';
import { customAlert, customConfirm } from '../utils/dialog-utils.js';
import { getMonitor, runAIAction } from './ai-features.js';
import { isNativeAIFeature } from './ai-ui-utils.js';
import { refreshAIVisibility } from './ai-toggle.js';

/**
Expand Down Expand Up @@ -79,7 +80,7 @@ export async function initAIWriter(ui, updateCallback) {
}
}

const isNative = Writer.toString().includes('[native code]');
const isNative = isNativeAIFeature(Writer);

await runAIAction(
ui,
Expand Down