diff --git a/agrifine-extension/src/ag-refine/agent.js b/agrifine-extension/src/ag-refine/agent.js index 75af4ba..fc2f0a0 100644 --- a/agrifine-extension/src/ag-refine/agent.js +++ b/agrifine-extension/src/ag-refine/agent.js @@ -61,8 +61,7 @@ export class AgrifineAgent { // Append assistant turn messages.push({ role: 'assistant', content: response.content }); - if (response.stop_reason === 'end_turn') { - // Extract final text + if (response.stop_reason === 'end_turn' || response.stop_reason === 'max_tokens') { const text = response.content .filter((b) => b.type === 'text') .map((b) => b.text) @@ -113,6 +112,7 @@ export class AgrifineAgent { 'Content-Type': 'application/json', 'x-api-key': apiKey, 'anthropic-version': '2023-06-01', + 'anthropic-dangerous-direct-browser-access': 'true', }, body: JSON.stringify(body), }); diff --git a/agrifine-extension/src/ag-refine/index.js b/agrifine-extension/src/ag-refine/index.js index d870629..a509734 100644 --- a/agrifine-extension/src/ag-refine/index.js +++ b/agrifine-extension/src/ag-refine/index.js @@ -153,7 +153,15 @@ export function AgRefineModule() { }, }); - await agent.run(userText); + try { + await agent.run(userText); + } catch (err) { + const idx = messages.findIndex((m) => m.id === thinkingId); + if (idx >= 0) messages.splice(idx, 1); + messages.push({ role: 'error', text: err.message }); + isRunning = false; + this._renderMessages(container); + } }, _renderMessages(container) { diff --git a/agrifine-extension/src/ag-refine/tools.js b/agrifine-extension/src/ag-refine/tools.js index 6d693cd..f47cf3a 100644 --- a/agrifine-extension/src/ag-refine/tools.js +++ b/agrifine-extension/src/ag-refine/tools.js @@ -151,7 +151,7 @@ async function toolGetReadingList({ tag } = {}) { async function toolGetFieldProfiles({ field_name } = {}) { const profiles = await getFieldProfiles(); const filtered = field_name - ? profiles.filter((p) => p.name.toLowerCase().includes(field_name.toLowerCase())) + ? profiles.filter((p) => p.name?.toLowerCase().includes(field_name.toLowerCase())) : profiles; return { count: filtered.length, @@ -260,6 +260,7 @@ async function toolLookupUSDAsoil({ latitude, longitude }) { headers: { 'Content-Type': 'application/x-www-form-urlencoded' }, body: `request=query&query=${encodeURIComponent(query)}&format=JSON`, }); + if (!res.ok) throw new Error(`USDA SDA API ${res.status}`); const data = await res.json(); const rows = data.Table ?? []; return { diff --git a/agrifine-extension/src/modules/dashboard/index.js b/agrifine-extension/src/modules/dashboard/index.js index 390d7db..bff6de4 100644 --- a/agrifine-extension/src/modules/dashboard/index.js +++ b/agrifine-extension/src/modules/dashboard/index.js @@ -3,6 +3,12 @@ import { } from '../../utils/storage.js'; import { callAnthropic } from '../../utils/api.js'; +function escapeHtml(str) { + return String(str ?? '') + .replace(/&/g, '&').replace(//g, '>').replace(/"/g, '"'); +} + const CATEGORIES = ['all', 'land', 'equipment', 'harvest', 'finance', 'carbon', 'weather']; function tagCategory(item) { @@ -118,7 +124,7 @@ export function DashboardModule() { maxTokens: 512, }); - answerEl.innerHTML = `
Answer
${answer}`; + answerEl.innerHTML = `Answer
${escapeHtml(answer)}`; } catch (err) { answerEl.textContent = `Error: ${err.message}`; } finally { @@ -167,11 +173,11 @@ export function DashboardModule() {${title}
- ${sub ? `${sub}
` : ''} +${escapeHtml(title)}
+ ${sub ? `${escapeHtml(sub)}
` : ''}