Releases: crmkit/crmkit
Releases · crmkit/crmkit
Release list
v0.9.1
Changed
- MCP
tools/listnow annotates the genericrequesttool with atitleand the full standard hint set —readOnlyHint,destructiveHint, andopenWorldHint— all present and explicit. A single tool spans every HTTP method, so it is annotated for its worst case: not read-only and destructive (it canPATCH/DELETE);openWorldHintisfalsebecause crmkit only ever touches the caller's own workspace, never public/internet state. This satisfies app-directory scanners (e.g. the OpenAI apps store) that require every tool to set all three hints. Purpose-split, per-method-annotated connectors remain the recommended surface for directory submissions.
v0.9.0
Features
- On-behalf-of attribution. Activities can record who an agent acted on behalf of: an optional
on_behalf_ofon activity creation (POST /{contacts,companies,tickets}/{id}/activities) names the principal an interaction was performed for — an email by convention (likeowner/assignee), client-supplied, so it can name a teammate who has no crmkit account. It is a distinct attribution axis fromcreated_by/by=, which stays the actor that actually wrote the row (the agent's own token):by=is who logged it,on_behalf_of=is who it was done for. It shows on every activity line and is filterable on the feed —GET /activities?on_behalf_of=alice@acme.com(case-insensitive). - That per-activity principal rolls up to the records the activity belongs to. Each contact, company, deal, and ticket surfaces
on_behalf_of=<the set of people who have worked it>on its line and detail — derived from its activities, so when several people work the same deal they all appear (it is a set, never a single overwritten value). Every such list is filterable by principal:GET /deals?on_behalf_of=alice@acme.com,GET /contacts?on_behalf_of=alice@acme.com, etc. The roll-up is computed on read (never stored), so it can't drift from the activity log it derives from. Tasks and campaigns have no activities and carry noon_behalf_of. - Deals get their own activity endpoints,
GET/POST /deals/{id}/activities, matching contacts/companies/tickets — so you log work straight onto a deal instead of cross-linking it from another record's activity. (The cross-link route still works and now resolves handles; see Fixed.) - Adds migration v19 (a nullable
on_behalf_ofcolumn and its index onactivities— the only place it is stored; the record roll-ups need no schema). Existing activities are unaffected. Back up, then runcrmkitd migrate --executeafter upgrading.
Fixed
- Logging an activity that cross-links another record by handle in the body (e.g.
POST /contacts/{id}/activities {"deal_id":"deal_x7k2", …}) now resolves that handle to the internal id before storing, instead of saving the handle verbatim. Previously such an activity was invisible to anything keyed on the id — the linked deal's/company's/ticket's activity count,last_activity, the?deal=/?company=/?ticket=activity feed filter, and the newon_behalf_ofroll-up all missed it. The path record was always resolved; this extends the same resolution to the body's cross-link ids.
v0.8.0
Features
- Outreach signal on contacts and companies. Every list line now also carries
outreach=Nandlast_outreach— the activity subset of the kinds that mean "we reached out" (call/email/meeting), distinct from the all-kindsactivities/last_activityalready shown (a loggednoteortaskdoes not count). The same signal is filterable, so segmenting who you have or haven't contacted no longer needs a tag:?last_outreach=is:null(never contacted),?last_outreach=lt:2026-05-01T00:00:00Z(reached before, now cold),?outreach_count=gte:1(reached at least once) — on both/contactsand/companies. It is derived from the activity log on read (never persisted), so it can never drift from the activities it summarises, and the displayed figure and the filtered figure share one source of truth. The agent manual now spells out the convention this enables: record outreach as an activity (not a tag), keep funnel position instage, and reserve tags for durable labels.
v0.7.0
Features
- List endpoints (
/contacts,/companies,/deals,/tickets) now carry an at-a-glance activity signal on every line:activities=N(how many activities reference the record) andlast_activity(when the most recent was logged) — the same summary a single-recordGETalready shows, but for a whole page in one batched query. Quiet records add nothing (a zero count and empty timestamp are omitted), so a caller can tell which records are active without a fetch per record. The fields are computed on read only (never persisted). GET /activitiesfilters (contact,deal,company,ticket) now accept several comma-separated handles, not just one — e.g.?company=company_a,company_bmatches the activity for any of them. This pulls the activity text for a whole list of records in a single call (group the results by thecompany=/contact=handle each line carries) instead of one request per record. A single handle still works exactly as before.
v0.6.0
Features
- List endpoints (
/contacts,/companies,/deals,/tickets,/tasks,/campaigns) now report the total number of records matching the query across all pages, not just the current page. Keyset pagination still drives navigation; the total is an extra hint so a caller (or agent) can tell how much is there and decide whether to keep paging or narrow its filters. It honours the same filters andsearchas the list and is exposed as atotalfield in JSON responses and a# total: Ntrailer in the grepable text format, alongside the existing# next:cursor.
v0.5.1
Fixed
- Plan limits: a configured plan that omitted a resource cap (e.g.
max_tasks) silently capped it at 0, rejecting every create withplan_limit_reached. Each cap is now optional and distinct from an explicit0: an omitted limit inherits the built-in default, an explicit0means "none allowed", and-1stays unlimited.
v0.5.0
Features
- Tasks: a first-class, completable unit of follow-up work with a title, optional due date, done flag, assignee, and explicit links to any of a contact/company/deal/ticket. Full CRUD at
/tasks; complete withPATCH /tasks/{id} {"done":true}.
Changed
- Breaking:
GET /remindersnow surfaces due, open tasks (withaboutandassignee) instead of per-record follow-ups. Follow-up tracking moves from a single slot per record to tasks, which allow several open items per record and can be checked off.
Removed
- Breaking: the
follow_up_at/follow_up_notefields on contacts, deals, and tickets. Existing follow-ups are migrated to linked tasks automatically (migration v18); the columns are then dropped.
v0.4.1
Features
- Ticket management: full CRUD, ticket activities with conversation summaries, and follow-ups
- Extend cross-entity search to include tickets
- Stricter email validation on contact and auth flows
v0.4.0
Features
- Ticket management: full CRUD, ticket activities with conversation summaries, and follow-ups
- Extend cross-entity search to include tickets
- Stricter email validation on contact and auth flows
v0.3.1
Features
- Ticket management: full CRUD, ticket activities with conversation summaries, and follow-ups
- Extend cross-entity search to include tickets
- Stricter email validation on contact and auth flows