|
1 | | -import { SelectorType } from "@/const" |
2 | 1 | import { HUB_URL } from "@/const" |
3 | 2 | import { Storage, LOCAL_STORAGE_KEY } from "@/services/storage" |
4 | | -import type { Caches } from "@/types" |
| 3 | +import type { Caches, AiService } from "@/types" |
| 4 | +import { |
| 5 | + normalizeServices, |
| 6 | + AI_SERVICES_FALLBACK, |
| 7 | + getAiServicesFallback, |
| 8 | +} from "@/services/aiPromptFallback" |
5 | 9 |
|
6 | | -/** |
7 | | - * Defines selectors and configuration for a supported AI service. |
8 | | - */ |
9 | | -export type AiService = { |
10 | | - id: string |
11 | | - name: string |
12 | | - url: string |
13 | | - faviconUrl: string |
14 | | - inputSelectors: string[] |
15 | | - submitSelectors: string[] |
16 | | - selectorType: SelectorType |
17 | | -} |
| 10 | +export { getAiServicesFallback } |
18 | 11 |
|
19 | 12 | /** External endpoint URL for AI service config data. */ |
20 | 13 | const AI_SERVICES_URL = `${HUB_URL}/data/ai-services.json` |
21 | 14 |
|
22 | 15 | /** Today's date string "YYYY-MM-DD" used as cache TTL key. */ |
23 | 16 | const todayStr = (): string => new Date().toISOString().slice(0, 10) |
24 | 17 |
|
25 | | -/** |
26 | | - * Normalize raw JSON data fetched from the external endpoint into AiService[]. |
27 | | - * - Items that are missing required fields (id, url, inputSelectors, submitSelectors) are silently skipped. |
28 | | - * - The external JSON may omit `selectorType`, defaulting to `CSS`. |
29 | | - */ |
30 | | -const normalizeServices = (raw: unknown[]): AiService[] => { |
31 | | - const results: AiService[] = [] |
32 | | - for (const item of raw) { |
33 | | - const s = item as Partial<AiService> |
34 | | - if ( |
35 | | - !s.id || |
36 | | - !s.url || |
37 | | - !Array.isArray(s.inputSelectors) || |
38 | | - !Array.isArray(s.submitSelectors) || |
39 | | - s.inputSelectors.length === 0 || |
40 | | - s.submitSelectors.length === 0 |
41 | | - ) { |
42 | | - console.warn("Skipping invalid AI service entry:", s) |
43 | | - continue |
44 | | - } |
45 | | - results.push({ |
46 | | - id: s.id, |
47 | | - name: s.name ?? s.id, |
48 | | - url: s.url, |
49 | | - faviconUrl: s.faviconUrl ?? "", |
50 | | - inputSelectors: s.inputSelectors, |
51 | | - submitSelectors: s.submitSelectors, |
52 | | - selectorType: s.selectorType ?? SelectorType.css, |
53 | | - }) |
54 | | - } |
55 | | - return results |
56 | | -} |
57 | | - |
58 | | -/** |
59 | | - * List of supported AI services with their DOM selectors. |
60 | | - * Built from the hub's ai-services.json at compile time. |
61 | | - * Used as fallback when the external fetch fails and no cache is available. |
62 | | - * Selector arrays are tried in order, using the first one that matches. |
63 | | - */ |
64 | | -const AI_SERVICES_FALLBACK: AiService[] = |
65 | | - normalizeServices(__AI_SERVICES_JSON__) |
66 | | - |
67 | 18 | /** |
68 | 19 | * Retrieve AI service definitions. |
69 | 20 | * Strategy: |
@@ -126,9 +77,3 @@ export const findAiService = async ( |
126 | 77 | const services = await getAiServices() |
127 | 78 | return services.find((s) => s.id === id) |
128 | 79 | } |
129 | | - |
130 | | -/** |
131 | | - * Return the list of AI services synchronously using only the hardcoded fallback. |
132 | | - * Used in UI contexts where async is not available (e.g. option section rendering). |
133 | | - */ |
134 | | -export const getAiServicesFallback = (): AiService[] => AI_SERVICES_FALLBACK |
0 commit comments