Skip to content

feat: add Agrifine browser extension scaffold (Phase 1)#3216

Open
leanmachine1209-ui wants to merge 27 commits into
vinta:masterfrom
leanmachine1209-ui:claude/farm-data-dashboard-extension-y7lp8i
Open

feat: add Agrifine browser extension scaffold (Phase 1)#3216
leanmachine1209-ui wants to merge 27 commits into
vinta:masterfrom
leanmachine1209-ui:claude/farm-data-dashboard-extension-y7lp8i

Conversation

@leanmachine1209-ui

Copy link
Copy Markdown

Manifest V3 Chrome extension with a persistent side-panel dashboard for farm data management. Includes:

  • Background service worker that proxies all Anthropic API calls (API key stored in chrome.storage.session, never in content scripts)
  • Content script that extracts page text for reading-list summarisation
  • Sidebar UI with bottom tab bar and settings panel (API key entry)
  • Five module stubs wired to live storage:
    1. ReadingList — save pages with AI summary + topic tagging
    2. DataIngest — drag-and-drop CSV/Excel/PDF → AI-structured JSON
    3. FieldProfile — per-field cards with CLU, acres, soil, coordinates
    4. Dashboard — unified filterable view + natural-language AI query bar
    5. CarbonEstimator — Phase 7 stub with feature preview
  • Shared storage schema (chrome.storage.local) with context-bundle builder for passing reading-list + field data as AI system context
  • Tailwind CSS + Webpack 5 build pipeline; builds successfully

Claude-Session: https://claude.ai/code/session_01KBD2dN2KEjzz3UQFa9hEpu

Project

Project Name

Checklist

  • One project per PR
  • PR title format: Add project-name
  • Entry format: - [project-name](url) - Description ending with period.
  • Description is concise and short

Why This Project Is Awesome

Which criterion does it meet? (pick one)

  • Industry Standard - The go-to tool for a specific use case
  • Rising Star - 5000+ stars in < 2 years, significant adoption
  • Hidden Gem - Exceptional quality, solves niche problems elegantly

Explain:

How It Differs

If similar entries exist, what makes this one unique?

claude added 19 commits June 27, 2026 03:15
Manifest V3 Chrome extension with a persistent side-panel dashboard
for farm data management. Includes:

- Background service worker that proxies all Anthropic API calls
  (API key stored in chrome.storage.session, never in content scripts)
- Content script that extracts page text for reading-list summarisation
- Sidebar UI with bottom tab bar and settings panel (API key entry)
- Five module stubs wired to live storage:
    1. ReadingList — save pages with AI summary + topic tagging
    2. DataIngest — drag-and-drop CSV/Excel/PDF → AI-structured JSON
    3. FieldProfile — per-field cards with CLU, acres, soil, coordinates
    4. Dashboard — unified filterable view + natural-language AI query bar
    5. CarbonEstimator — Phase 7 stub with feature preview
- Shared storage schema (chrome.storage.local) with context-bundle
  builder for passing reading-list + field data as AI system context
- Tailwind CSS + Webpack 5 build pipeline; builds successfully

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01KBD2dN2KEjzz3UQFa9hEpu
Multi-step AI agent in src/ag-refine/:
- agent.js: Claude tool-use loop (up to 10 iterations), streams events
  to UI as it thinks and calls tools
- tools.js: 6 live tools — get_reading_list, get_field_profiles,
  get_ingested_files, get_weather (Open-Meteo), lookup_usda_soil
  (USDA SDA API), calculate_gdd
- index.js: chat UI with streaming tool-call display, suggested
  prompts, clear conversation
- Wired as new Agent tab in sidebar (6th tab)
- Also fixes manifest.json paths (dist/ prefix removed)

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01KBD2dN2KEjzz3UQFa9hEpu
Driver (.claude/skills/run-agrifine-extension/driver.mjs):
- Launches Chrome with unpacked extension via Playwright persistent context
- Stubs chrome.* APIs so sidebar renders headlessly without real extension context
- REPL commands: ss, tab, click, type, eval, quit
- Screenshots land in screenshots/
- Verified: all 6 tabs render correctly (Reading, Ingest, Fields, Dashboard, Carbon, Agent)

SKILL.md documents agent path first, gotchas, and troubleshooting from
actual execution in this container.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01KBD2dN2KEjzz3UQFa9hEpu
- agent.js: add anthropic-dangerous-direct-browser-access header to _callAPI
  (root cause of 401 CORS errors in AgriAgent tab)
- agent.js: handle stop_reason=max_tokens alongside end_turn
- ag-refine/index.js: reset isRunning in a try/catch around agent.run()
- tools.js: check res.ok before parsing JSON in toolLookupUSDAsoil
- tools.js: guard p.name?.toLowerCase() against null field names
- field-profile/index.js: guard both lat and lon before toFixed()
- reading-list/index.js: escapeHtml + safeHref to prevent XSS from page titles/urls
- dashboard/index.js: escapeHtml AI answer and all dynamic list content
- data-ingest/index.js: add .xlsx/.xls extension fallbacks for missing MIME type
- storage.js: check chrome.runtime.lastError in all four storage helpers

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01KBD2dN2KEjzz3UQFa9hEpu
screenshot_active_tab — captures current browser tab as JPEG; agent.js
  formats the result as an Anthropic vision image block so Claude can
  actually see the page (not just its text)

get_page_content — reads text of the active tab via content script, or
  falls back to the reading-list cache when a URL is supplied

export_farm_data — generates a CSV or JSON file and triggers a browser
  download for reading_list, field_profiles, ingested_files, or all data

open_tab — opens any https:// URL in a new browser tab and waits for it
  to finish loading; returns tab_id for chained tool calls

read_tab_content — extracts and parses page text from any tab by tab_id
  (or active tab) using chrome.scripting.executeScript; more reliable
  than the content-script sendMessage path

Background worker gains CAPTURE_SCREENSHOT, GET_ACTIVE_TAB_CONTENT,
OPEN_TAB, and READ_TAB_CONTENT message handlers; agent.js detects
_type:'image' results and formats them as vision content blocks.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01KBD2dN2KEjzz3UQFa9hEpu
Farm memory (agrifine_farm_memory in chrome.storage.local):
- New FarmMemory schema: aiGeneratedSummary, farm_name, total_acres,
  primary_crops, soil_overview, key_insights, action_items, risk_flags,
  opportunities, lastUpdated
- getFarmMemory() / saveFarmMemory() in storage.js

buildContextBundle() now loads all four data sources in parallel:
  1. Farm memory snapshot (AI synthesis from prior sessions) — at top
  2. Field profiles with crop history, harvest records, and coordinates
  3. Ingested data files with structured-data previews
  4. Reading list articles with summaries and tags

Two new AgriAgent tools:
- get_farm_memory: retrieve the stored knowledge snapshot
- update_farm_memory: agent saves a comprehensive farm synthesis so future
  sessions start with full context (the key to persistent memory)

System prompt rewrite in agent.js:
- Agent now understands its role as the farm's persistent advisor
- Memory protocol: reference farm memory first, update it when new
  insights are discovered
- Explicit reasoning steps: Ground → Gaps → Connect → Cite → Remember
- Full tool selection guide with when-to-use guidance for all 11 tools

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01KBD2dN2KEjzz3UQFa9hEpu
Replace all light-mode Tailwind classes across every module with the
AG-Refine dark design system: #0f1621 body, #131c2b header/nav,
#1a2438 cards, #1e2d40 borders, agri-green (22c55e/16a34a) accents.

- tailwind.config.js: add `night` dark palette (950–300)
- sidebar.css: full dark rewrite (cards, tags, inputs, scrollbar)
- sidebar.html: AG/REFINE/FIELD INTELLIGENCE logo, dark tab bar with
  INTEL/INGEST/FIELDS/DATA/CARBON/AGENT labels and dot indicators
- sidebar/index.js: manage inactive tab color via inline style
- reading-list: card links → agri-400, summary/date → gray-400/500
- data-ingest: drop zone → night borders, file cards → dark theme
- field-profile: form → night-700 bg, inputs use .ag-input, cards dark
- dashboard: AI query bar and category pills → dark, answer box dark
- carbon-estimator: feature list and notify banner → dark palette
- ag-refine: suggestions → night-700, chat bubbles dark, tool call
  cards use night-700/border-night-600, errors use red-900/20 tint

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01KBD2dN2KEjzz3UQFa9hEpu
Chrome loads files from dist/ directly, so the built output needs to be
in the repo. Removed dist/ from .gitignore and committed the current
build which includes the AG-Refine dark theme redesign.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01KBD2dN2KEjzz3UQFa9hEpu
Document parsing fixes:
- Copy pdf.worker.min.mjs to dist/pdf.worker.js via webpack CopyPlugin
  (was missing, causing all PDF parsing to silently fail)
- Set webpack output.publicPath '/' so dynamic import chunks resolve
  correctly from Chrome extension chrome-extension:// URLs
- pdfjs: pass Uint8Array and set useWorkerFetch/isEvalSupported for
  extension CSP compatibility
- Add Python doc server (tools/doc_server.py) using flask + pandas +
  PyPDF2 at localhost:7432; extension tries it first then falls back
  to browser-side parsing for more robust CSV/Excel/PDF extraction

AG-Refine sister-app integration:
- New utils/agrefine-bridge.js: detects open AG-Refine tab by URL
  pattern, executes script to dump its localStorage, maps field/load
  data to Agrifine field profile schema, merges without overwriting
  user edits, logs sync history
- Background handler AGREFINE_SYNC calls syncFromAgRefine()
- Field Profiles module: "AG-Refine" sync button, status feedback,
  synced-field badge, "Open in AG-Refine ↗" link in expanded detail
- Settings panel: AG-Refine URL field so sync pins to a specific origin
- sidebar/index.js: loads and saves AG-Refine URL on settings open/save

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01KBD2dN2KEjzz3UQFa9hEpu
Previously the Anthropic API key was session-only and lost on Chrome
restart. Now:

- KEYS.API_KEY_SAVED added to storage schema (chrome.storage.local)
- Background service worker restores saved key into session on startup,
  so the key is available immediately without re-entering it
- SET_API_KEY handler accepts a `remember` flag: if true, writes to
  both session and local; if false, clears the local copy
- Settings panel: "Remember across sessions" checkbox next to Save,
  "Forget saved key" button appears when a key is persisted
- Status text distinguishes "Key saved across sessions" vs
  "Key active this session only"

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01KBD2dN2KEjzz3UQFa9hEpu
- Data Ingest: after AI extraction, detect field names in structured data
  and offer one-click import of harvest records + crop history into matching
  field profiles; "Re-import" link persists on each ingested file card

- Field Profiles: expanded card now renders full Crop History table (year,
  crop, yield) and Harvest Records (date, yield, moisture) pulled from
  stored data; previously these were stored but never displayed

- Field Profiles: added separate Pull (sync from AG-Refine) and Push (write
  to AG-Refine localStorage) buttons making the integration bidirectional;
  synced fields fire a CustomEvent so a listening AG-Refine app can react

- Field Profiles: sync log panel shows last 5 syncs with timestamp, field
  counts, and source URL; card summary line shows "X yr history" count
  and source badge (manual / AG-Refine / AG-Refine + manual)

- Background: added AGREFINE_PUSH message handler that serializes all
  field profiles and calls pushToAgRefine

- Added seeder test (tests/seed_and_screenshot.mjs) with realistic
  Hendricks Family Farms data and screenshots of all 6 tabs

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01KBD2dN2KEjzz3UQFa9hEpu
Adds a dual-mode AGENT / BOARDROOM toggle to the AgriAgent tab:

AGENT mode (unchanged): single AgriAgent chat with full tool loop,
farm memory, and agentic reasoning.

BOARDROOM mode: four named committee members hold a structured meeting
over the farm's live data context.

Committee roster:
  💹 Kount Kuekkens  — CFO / Financials (spiraling economist, Dairy Moneyball math)
  🌾 Rolf Forage     — Agronomist / Crops (opinionated, field-first)
  🐄 Dr. Vera Hest   — Chief Veterinarian / Herd Health (precise, biological thresholds)
  📋 Marla Shift     — Operations Manager / Personnel (reality-check, labor constraints)

Each agent makes an independent streaming API call with a persona-specific
system prompt. Agents run sequentially so later speakers receive a full
transcript of what earlier colleagues said, enabling authentic cross-domain
commentary (e.g. Vera referencing Rolf's harvest quality point).

After the initial round, a target bar appears for cross-examination: the
chair can direct follow-ups to All, or to a specific advisor by name.

Five boardroom-specific suggested topics replace the standard agent prompts
in this mode (weekly audit, data integrity, heat stress, risk per dept,
biggest cross-dept contention).

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01KBD2dN2KEjzz3UQFa9hEpu
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01KBD2dN2KEjzz3UQFa9hEpu
…mittee personas

Replace localStorage-scraping approach with proper REST API calls. The bridge
now injects async fetch functions into the AG-Refine tab's page context so
session cookies work without any CORS configuration on the server.

syncFromAgRefine() now calls /api/fields/, /api/scales/tickets/all,
/api/intelligence/lab-samples, and /api/harvest/plans simultaneously.
WeighTicket records (DM%, protein, commodity, harvest label) are mapped to
per-field harvest records; NIR/lab samples are mapped to per-field labSamples
arrays and surfaced in the field profile expanded card.

pushToAgRefine() creates new fields via POST /api/fields/ and back-fills
_agRefineId on success so subsequent pulls correctly merge rather than duplicate.

buildContextBundle in storage.js now includes latest lab sample quality metrics
(DM%, NDF%, RFV, NEL) in the AI context for each field.

Committee agent personas enriched with AG-Refine-specific domain knowledge:
Kount reads ticket DM% and integrity scores for cost-per-ton math; Rolf reads
lab NDF/ADF/RFV against thresholds and harvest calendar cut timing; Dr. Vera
connects forage DM% on tickets to intake prediction and ketosis risk; Marla
reads operation cycle times and driver assignment logs for throughput analysis.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01KBD2dN2KEjzz3UQFa9hEpu
… + re-extract

When callAnthropic throws due to a missing API key, the error state is now
'no_api_key' instead of the generic 'AI extraction unavailable'. Each file
card shows an amber banner with gear icon — "Add API key in Settings to
extract" — and an "Extract now" / "Retry" button.

raw_text (6000 chars) is preserved in the structuredData so the user can
re-run AI extraction after configuring their key without re-uploading the
file. _reExtractFile() handles this flow, updating the stored record and
triggering the field-import offer on success.

buildContextBundle and the preview strip now filter raw_text alongside
raw_preview so the large cached text doesn't leak into AI prompts.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01KBD2dN2KEjzz3UQFa9hEpu
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01KBD2dN2KEjzz3UQFa9hEpu
Node.js service for the farm server that replaces the Chrome extension concept.
Pulls from AG-Refine REST API and Dropbox (DairyComp/FeedLync logs), synthesises
with Claude Haiku on a cron schedule, pushes summaries back to Dropbox and WhatsApp.

- Hourly pulse, daily digest (Haiku), weekly summary (Sonnet)
- TomTom geofence webhook receiver — entry/exit events → WhatsApp + Dropbox log
- WhatsApp Business API send (gracefully disabled if no credentials)
- Express HTTP server with /health, /status, manual /run/* trigger endpoints
- Windows start.bat for farm server deployment
- .env.example documents all credentials (none committed)

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01KBD2dN2KEjzz3UQFa9hEpu
@kghzjk4hdj-arch

Copy link
Copy Markdown

Daddy is that u

claude added 8 commits June 28, 2026 04:11
One-time CLI script to exchange App Key + App Secret for a long-lived
refresh token without needing a web server redirect flow.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01KBD2dN2KEjzz3UQFa9hEpu
- render.yaml for one-click Render web service deploy
- Fix PORT env var (Render sets $PORT, not $WEBHOOK_PORT)
- Add farm-aggregator/.gitignore so .env stays local but .env.example commits
- Commit .env.example so it's available after clone

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01KBD2dN2KEjzz3UQFa9hEpu
Replaces the persistent web service with 3 separate Render Cron Job
services — pulse (hourly), daily digest (06:00), weekly summary (Mon 06:00).
Each job runs and exits, no $7/mo web service needed.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01KBD2dN2KEjzz3UQFa9hEpu
Recursively lists /Farm folder contents so you can see what data
is available to route into DairyComp / FeedLync subfolders.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01KBD2dN2KEjzz3UQFa9hEpu
- System prompt now includes FeedLync CSV column definitions and error thresholds
- Flags load error >5% (note), >10% (flag), >20% (urgent)
- Daily prompt leads with FeedLync TMR loads as primary data source
- References Drumgoon Dairy specifically

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01KBD2dN2KEjzz3UQFa9hEpu
Checks auth, lists root folder, and attempts a test upload to diagnose
400 errors (usually App Folder vs Full Dropbox access mismatch).

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01KBD2dN2KEjzz3UQFa9hEpu
…n rotation

Combines Dropbox OAuth flow with automatic Render API env var update.
Run once to rotate the refresh token across all 3 cron job services
without touching the Render dashboard manually.

Requires RENDER_API_KEY and RENDER_SERVICE_IDS in env.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01KBD2dN2KEjzz3UQFa9hEpu
…→Claude→WhatsApp bridge

Strips out AG-Refine API, TomTom, Express server, and node-cron scheduling.
Single bridge.js (~100 lines) reads FeedLync/DairyComp files from Dropbox,
generates a Haiku digest, sends to WhatsApp, and saves back to /Farm/Summaries.
One daily Render free cron job instead of three.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01KBD2dN2KEjzz3UQFa9hEpu
@kghzjk4hdj-arch

Copy link
Copy Markdown

Hhaaahahha

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants