AI-powered desktop app for EventHive that monitors Teams channels and automatically proposes updates to your EventHive tools.
Version: 0.2.0 — Sprint 01 (Teams Polish) Tech: Electron + Svelte 5 + Playwright (Chromium)
- Monitors Teams channels using an embedded Electron browser window (no Teams API, no admin consent)
- Classifies incoming messages using Claude (Anthropic) to identify actionable supplier responses
- Proposes actions (create/update/patch tool data records) for your approval
- Submits approved actions to EventHive via the Agent API
All credentials are encrypted with your OS keychain (macOS Keychain via safeStorage).
# 1. Install dependencies
npm install
# 2. Start in development mode (Electron + HMR)
npm startOn first launch, the setup wizard will guide you through:
- EventHive URL + Agent API key (generate in EventHive → Settings → Agent Access)
- Anthropic API key (for Claude message classification — optional, enables AI mode)
- Download
Hive-Agent.dmgfrom Releases - Open the DMG and drag Hive Agent to Applications
- First launch: Right-click the app → "Open" → "Open" again (macOS blocks unsigned apps by default — this is a one-time bypass)
- The setup wizard will guide you through connecting to EventHive
Apple Developer ID: If a paid Apple Developer certificate is available, add
osxSignandosxNotarizetoforge.config.tsto remove the Gatekeeper warning entirely.
# Build for current machine's architecture
npm run make:mac
# Explicit architectures
npm run make:mac:arm # Apple Silicon
npm run make:mac:intel # Intel Mac
# Output: out/make/Hive Agent.dmgsrc/
├── main/ # Electron main process (Node.js)
│ ├── index.ts # App lifecycle, tray, IPC handlers
│ ├── preload.ts # contextBridge IPC bridge → renderer
│ ├── browser/
│ │ ├── camoufox.ts # Browser session manager
│ │ ├── session-manager.ts # Platform session state
│ │ ├── monitor-manager.ts # Orchestrates all monitors
│ │ └── monitors/
│ │ ├── teams-monitor.ts # Teams MutationObserver scraper
│ │ ├── teams-selectors.ts # DOM selectors (tiered resilience)
│ │ └── selector-resolver.ts # Fallback selector health checker
│ ├── intelligence/
│ │ ├── llm-processor.ts # Anthropic API — action classification
│ │ ├── message-buffer.ts # Rolling conversation context buffer
│ │ └── action-executor.ts # POSTs approved actions to EventHive
│ └── store/
│ ├── credentials.ts # safeStorage + config.json
│ └── rules.ts # Auto-approve rules persistence
└── renderer/ # Svelte 5 UI
├── App.svelte # Root — setup gate or dashboard
├── env.d.ts # window.agent ambient types
└── pages/
├── Setup.svelte # First-run wizard
├── Dashboard.svelte # Shell + sidebar navigation
├── Platforms.svelte # Platform connections + channel selection
├── ActivityFeed.svelte # Message feed with search/filters
├── Approvals.svelte # Pending action review
├── Rules.svelte # Auto-approve rules editor
└── Settings.svelte # API keys, monitoring config, data
assets/
├── icon.icns # macOS app icon
├── icon.png # 1024px PNG (tray/dock)
└── erleah-mark.svg # Source SVG
The renderer never touches Node.js or Electron APIs directly. All cross-process calls go through contextBridge in preload.ts:
window.agent.cred.save('key', 'value') // encrypt & store
window.agent.platform.getChannels('teams') // list Teams channels
window.agent.monitor.getHealth() // selector health check
window.agent.settings.testAnthropic() // connection test
window.agent.actions.approve(action) // submit to EventHiveSecrets (agent_api_key, anthropic_api_key) are encrypted with safeStorage.encryptString() stored as hex files in ~/.hive-agent/secrets/. Non-secret config (EventHive URL, setup timestamp) is plain JSON at ~/.hive-agent/config.json.
A hidden BrowserWindow loads teams.microsoft.com with persist:teams session. A MutationObserver is injected via executeJavaScript to detect new messages. Messages are polled every 2 seconds and channelled through the LLM pipeline.
Selectors use a three-tier resilience system (primary → secondary → tertiary → failed). Health is visible as a colour dot in the sidebar.
TeamsMonitor → messageBuffer.add()
→ LLMProcessor.process(msg + context)
→ rulesStore.findMatch(proposal)
→ auto-approve OR pending:new-action
Context: last 10 messages from the same channel (capped at 2000 chars) are sent alongside each new message so Claude understands replies like "Yes, confirmed".
| Version | Sprint | What shipped |
|---|---|---|
| 0.1.0 | Sprint 29 | Electron scaffold, tray, IPC, setup wizard, Teams monitor scaffold |
| 0.2.0 | Sprint 01 | Channel selection, Settings page, Activity Feed, selector resilience, message context window, DMG packaging |
- Teams only (Slack, Gmail, Outlook monitors are stubs)
- No code signing — Gatekeeper bypass required on first launch
- Camoufox binary is not bundled — first install requires internet access
- Channel discovery requires Teams to be loaded in the browser window