Fix chat agent web search, greeting resume, and lead capture gaps
Seth+1: Claude Sonnet 5
b5da8dd
Competitor comparison tables defaulted straight to "Requires confirmation"
because the agentic prompt never told the model to actually use its
search_the_web tool for the comparison — only that the tool existed.
Now the model is instructed to search before falling back, and to label
web-sourced cells as unverified public info rather than a settled claim.
The widget's opening greeting silently disappeared on any repeat open
within the same browser (existing localStorage session skipped the
greeting fetch entirely, with no history shown either). Added a session-
resume endpoint so reopening replays prior messages, or shows the
greeting if nothing was exchanged yet.
Chat-agent-sourced leads were linked into Contacts the same way as
Smartlead reply-imports, which the enrichment "Fetch" gate explicitly
excludes — and no extraction logic existed at all for company name, only
visitor name. Chat-agent leads now get form-style (enrichable) contacts,
and company name is extracted from the conv…
LinkedIn connects/DMs are now throttled per connected account against
conservative daily/weekly caps (rolling windows, randomized jitter) enforced
by a new background scheduler so delivery keeps progressing without a
browser tab open. Email sending gets per-campaign timezone/business-hours/
interval controls set during campaign setup. Content generation can now be
stopped mid-run and resumed later without restarting.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Add dashboard activity/lead/deal stat boxes and backfill Contacts/Companies ownership scoping
Seth+1: Claude Sonnet 5
de29580
- Add Calls, Visits, New leads, Deals, and Closings stat boxes to the
Sales Dashboard, respecting the existing team/date-range filters.
- Add a tenant-wide GET /api/activities endpoint (previously only
available per-contact) and bump /api/leads' page-size cap to match
Deals, so the new dashboard counts aren't silently truncated.
- Give Contact and Company an owner_user_id column and apply the same
team-manager visibility scoping already used by Leads/Deals to their
list, detail, and patch routes — these had no ownership concept at
all before, so every tenant member could see everyone's contacts and
companies regardless of team.
- Add an Owner avatar + reassignment dropdown to Contacts.jsx and
Companies.jsx (factored into a shared OwnerCell component), matching
the admin-can-assign-anyone / member-can-only-self-claim rules the
backend now enforces.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Fix LinkedIn campaign generation reliability, quality, and persistence
Seth+1: Claude Sonnet 5
810c33d
- Stop silently swallowing generation errors as fake generic fallback
content; retry once on transient OpenAI failures, then surface a
typed failure instead of writing fabricated sequence rows.
- Fix step-order/message-numbering bugs so LinkedIn steps keep the
wizard's configured order and messages aren't mislabeled by list
position.
- Enforce the LinkedIn connection-note character cap server-side and
tighten the prompt to require concrete personalization and ban
generic filler openers.
- Give campaigns a real backend record (UploadedFile campaign_name/
status/updated_at + list/detail/meta-patch/delete routes) instead of
browser localStorage, which had a bug where a parse failure would
silently repopulate demo data over real campaigns.
- Reconcile the dashboard from the backend list, auto-save campaign
identity from the wizard on every step, and re-fetch the saved
sequence plan/prompts when reopening a campaign so content and
configuration survive closing and re…
Add sales teams: manager role, team assignment, and team-scoped data visibility
Seth+1: Claude Sonnet 5
67330bb
Managers head a team (Team.manager_user_id, TenantMembership.team_id) and see
their own plus their team's leads, deals, and Call/Visit activity; other
members see only their own. A shared _visible_owner_user_ids() helper gates
list_leads, list_deals, quarterly_recurring_metrics (which the Dashboard
reads from), and both activity-timeline endpoints. Leads gains an
owner_user_id column plus assignment UI (mirroring Deals, which already had
per-user ownership) since team-scoping needs something to scope by. Admins
manage teams and member-team assignment from a new Teams card in Settings.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Add Call/Visit activity logging and timeline for contacts and companies
Seth+1: Claude Sonnet 5
41c19e3
New ContactActivity table tracks calls/visits with notes and author,
surfaced via Call/Visit icon buttons (with an inline note textarea)
everywhere a contact appears — Contacts table rows, associated-contacts
lists on Companies/Leads/Deals, and the contact identity header in each
detail panel. Adds a per-contact activity timeline and a company-level
rollup that aggregates activity across every contact sharing that company.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Add Type field (Existing/New) to Contacts/Companies/Leads/Deals, synced like Category
Seth+1: Claude Sonnet 5
fe7e466
Company gets a new type column, wired through the existing generic
COMPANY_DETAIL_PATCH_FIELDS propagation so it syncs bidirectionally across
Company/Contact/Lead/Deal exactly like Category. Companies page also gets a
Type filter, table column, and inline-add-row selector matching Category's
existing footprint there.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Add contact number field to Contacts/Companies, show associated contacts on Leads/Deals
Seth+1: Claude Sonnet 5
c40de6e
Adds a personal phone column on Contact/CrmLead and a synced company-level
phone on Company (using the existing company_phone/company_name_for_emails
style patch-body disambiguation), surfaced in the shared identity/company
editors everywhere they're used. Leads and Deals detail panels now also show
an "Associated contacts" list for the linked company, matching the Companies
page, via a new shared AssociatedContactsList component and a
GET /api/contacts/by-company endpoint.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Add Companies page with Category field and contact sync
Seth+1: Claude Sonnet 5
c253255
- New Company entity (name, category A/B/C, industry, employees,
annual revenue, website, city/state/country) with routes to list,
create, patch, bulk-delete, and re-sync.
- Companies are associated with Contacts by case-insensitive name
match rather than a foreign key, so this is fully additive and
never touches the existing Contact/CrmLead/CrmDeal schema or
behavior. A Company row is auto-created for any distinct
Contact.company value that doesn't already have one, seeded from
the richest matching contact; manual edits are never overwritten
by later syncs.
- New Companies page (sidebar, between Contacts and Leads) built
from the same AppShell/MainTableWorkspace/SlideOverPanel
components as Leads, with a detail panel listing every associated
contact plus an inline "add a contact" form scoped to that company.
- Category dropdown (A/B/C) added to the shared CompanyDetailsEditor
used by Contacts, Leads, and Deals, so it's consistently available
wherever company …
Chat Agent: proactive website CTAs and per-conversation token usage tracking
Seth+1: Claude Sonnet 5
9889053
- Strengthen the Website Link Promotion skill section (and the code-level
CITATIONS instructions that produce the actual link) so the agent actively
surfaces a relevant indexed page as a call-to-action whenever one exists,
instead of only citing it as a passive afterthought.
- Track total LLM tokens spent on each reply (summed across every round of
the agentic tool-calling loop, or from Gemini's usage metadata on that
provider) and surface it in the admin Conversations tab: per message, per
conversation, and as an overall total across every chat for the tenant.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Chat Agent: render markdown tables properly, show web-search usage to admins, fix pricing leak
Seth+1: Claude Sonnet 5
f6dedbf
- Render GFM pipe tables as real <table> markup (with horizontal scroll) in the
Test Chat panel, Conversations transcript, and the embeddable widget, instead
of dumping raw "| a | b |" text into a narrow chat bubble.
- Track whether a reply actually used the search_the_web tool and surface a
"Used live web search" badge to admins (Test Chat + Conversations), so a
live-web-sourced answer is never mistaken for a knowledge-base answer.
- Fix a real pricing leak: a visitor comparison question ("are you cheaper than
X") caused the agent to recite actual EZOFIS pricing pulled from the tenant's
own indexed content, because the comparison-table instruction pushed the
model to fill every cell from retrieval, overriding the separate "never
disclose pricing" rule. Added a hard, code-level backstop that strips
dollar-amount/discount patterns out of retrieved chunk text before it ever
reaches a prompt, plus reinforced the comparison-table instruction itself.
- Make the Gemini fa…
Chat Agent: opt-in live web search (Gemini) with skill-editable guardrails + AI disclaimer
Seth+1: Claude Sonnet 5
9d44313
Generalizes the agent's web-lookup tool from competitor-only research into a
general search_the_web tool the agentic loop can reach for whenever the
knowledge base isn't enough, gated behind enable_web_search + a configured
Gemini key. Hard safety boundaries (never our own pricing/confidential info,
always framed as unverified) stay in code; "when it's worth searching"
guidance is now editable via the default skill's instructions. Also adds a
persistent "AI can make mistakes" disclaimer to both the embeddable widget
and the admin Test Chat panel.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Chat Agent: comprehensive EZOFIS default skill, ZIP export, Gemini fast indexing
Seth+1: Claude Sonnet 5
b5da702
- Replace the 3 small guardrail skills with one comprehensive default skill
authored from EZOFIS's real website-agent governance document: condensed
non-negotiable rules always injected via instructions, 10 topic references
searched on demand (keeps every live turn fast), 6 canned-response
templates, a real runnable compliance-checker script, and 8 eval cases
lifted from the document's own test scenarios. A migration auto-
consolidates any tenant whose skills are exactly the old 3 unmodified
defaults; tenants with custom skills are left untouched.
- Fix a real bug found while stress-testing the larger content: the eval
parser's regex was missing re.MULTILINE, so only the first eval of any
multi-eval skill ever parsed back on import.
- Elaborate each Skills section (References/Assets/Templates/Scripts/Evals)
in the Cards UI with its purpose and a worked example.
- Add a ZIP export (GET /api/chat-agent/skills/export-zip + Download ZIP
button) producing the exact ski…
Four upgrades to the Skills anatomy, aimed at making this a faithful demo of
Anthropic's Agent Skills format:
- Real YAML frontmatter (pyyaml) instead of a hand-rolled regex parser, which
broke on descriptions containing a colon/quote/comma — now round-trips
correctly via safe_dump/safe_load.
- New templates/ folder, a full sibling to assets/ throughout: schema,
migration, SKILL.md compile/parse, knowledge-base indexing/search, CRUD
routes, and a frontend section.
- A virtual file-browser view (Cards / File browser toggle in the Skills tab)
that renders the DB-backed skill anatomy as a real-looking
skills/<name>/{SKILL.md,references/,assets/,templates/,scripts/,evals/}
tree with a live preview pane, since there's no actual filesystem to browse
on this hosting.
- Admin-only sandboxed script execution: a real "Run" button that executes
Python in an isolated subprocess (secrets stripped from its environment,
timeout-bound, output capped). This is never reachable from …
Chat Agent: full Agent Skills library (SKILL.md anatomy)
Seth+1: Claude Sonnet 5
0bbe01f
Rebuilds the flat guardrail-string Skills feature into Anthropic's real
Agent Skills format: name + description + instructions (always injected
into the prompt), plus references/assets (indexed into the same
knowledge base the agentic search tool already searches), scripts
(stored/exported for documentation only — never executed, see
SKILLS-SECURITY.md), and evals (test cases graded by substring match or
an LLM judge). Skills export/import as real, portable SKILL.md files.
Also fixes a resilience gap found while testing live in the browser: an
indexing failure (e.g. the embeddings API being down) was crashing the
whole skill save with a 500 and losing the admin's text edits. The
skill's own fields now commit first, indexing runs in its own
try/except, and a failed index attempt rolls back cleanly so the next
save retries instead of getting stuck thinking it's already indexed.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Add Chat Agent module: RAG website widget with Drive/site knowledge base and CRM lead capture
Seth+1: Claude Sonnet 5
991c079
Adds an embeddable WordPress chat widget backed by a Google Drive folder and a
site crawl, with admin-editable skills/guardrails, streaming replies, and
automatic CrmLead creation (with live transcript) for every chat that shares
a name/email.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>