import { renderPrompt, ACTION_GROUPS } from './actions.js'; import { normalizeLanguage } from './settings.js'; import { serializePrompt, MAX_URL_CHARS } from './build-url.js'; const IDS = new Set([...Object.values(ACTION_GROUPS).flat(), 'translate']); const error = message => ({ kind: 'error', message }); export function prepareAction(request) { if (!IDS.has(request.actionId)) return error('This action is no longer available. Please try again.'); const source = String(request.source ?? '').trim(); if (!source && request.actionId !== 'ask') return error('There is no text or URL to send. Please select it again.'); const isUrl = request.actionId.includes('-'); if (isUrl) { try { const parsed = new URL(source); if (!['http:', 'https:'].includes(parsed.protocol) || parsed.username || parsed.password) throw new Error(); } catch { return error('This action supports only HTTP or HTTPS links without embedded login credentials.'); } } let language = normalizeLanguage(request.language); if (request.actionId === 'translate') { if (!language && request.settings.translationMode === 'preferred') language = normalizeLanguage(request.settings.translationLanguage); if (!language) return { kind: 'language' }; } const resolved = { ...request, language }; const serialize = text => serializePrompt(request.settings, renderPrompt(resolved, text)); const url = serialize(source); if (url.length <= MAX_URL_CHARS) return { kind: 'ready', url }; if (isUrl) return error('This URL is too long to send intact. No part of it has been sent.'); const marker = '\n[Selected text shortened]'; if (serialize(marker).length >= MAX_URL_CHARS) return error('The prompt instructions are too long. Shorten your prompt template and try again.'); const points = Array.from(source); let low = 0, high = points.length; while (low < high) { const mid = Math.ceil((low + high) / 2); if (serialize(points.slice(0, mid).join('') + marker).length <= MAX_URL_CHARS) low = mid; else high = mid - 1; } let kept = points.slice(0, low).join(''); const boundary = kept.search(/\s+\S*$/u); if (boundary > kept.length * 0.9) kept = kept.slice(0, boundary); if (!kept.trim()) return error('The prompt leaves no room for the selected text. Shorten the prompt template and try again.'); return { kind: 'shortened', url: serialize(kept + marker) }; }