@astralibx/call-log-engine
v0.3.3
Published
Call log engine with pipelines, timeline-based notes, contact adapters, analytics, and shared agent support
Downloads
104
Maintainers
Readme
@astralibx/call-log-engine
Call log engine with pipelines, timeline-based notes, contact adapters, follow-up worker, analytics, export, and shared agent support.
Install
npm install @astralibx/call-log-enginePeer Dependencies
| Package | Required |
|---------|----------|
| express | Yes |
| mongoose | Yes |
npm install express mongooseRequirements
MongoDB is mandatory for call-log-engine. It stores pipelines, call logs (with embedded timelines), and settings.
There is no Redis dependency -- the follow-up worker polls MongoDB directly.
Quick Start
import { createCallLogEngine } from '@astralibx/call-log-engine';
import mongoose from 'mongoose';
import express from 'express';
const app = express();
app.use(express.json());
const connection = mongoose.createConnection('mongodb://localhost:27017/myapp');
const engine = createCallLogEngine({
db: { connection, collectionPrefix: '' },
adapters: {
lookupContact: async (query) => {
// Look up contact by phone/email/externalId
return null;
},
authenticateAgent: async (token) => {
// Verify JWT/session token, return { adminUserId, displayName } or null
return null;
},
},
});
// Mount REST routes
app.use('/api/call-log', engine.routes);
app.listen(3000);
// Graceful shutdown -- stops the follow-up worker
process.on('SIGTERM', async () => {
await engine.destroy();
});Full Setup with Agent Sharing
When running alongside @astralibx/chat-engine, both engines share the same agent collection by default (chatagents). See Agent Sharing.
const engine = createCallLogEngine({
db: { connection },
agents: {
collectionName: 'chatagents', // default -- same collection chat-engine uses
resolveAgent: async (agentId) => {
const agent = await AgentModel.findById(agentId);
return agent ? { agentId: agent._id.toString(), displayName: agent.name } : null;
},
},
adapters: {
lookupContact: async (query) => {
const contact = await ContactModel.findOne(query);
return contact
? { externalId: contact._id.toString(), displayName: contact.name, phone: contact.phone }
: null;
},
addContact: async (data) => {
const contact = await ContactModel.create(data);
return { externalId: contact._id.toString(), displayName: contact.displayName };
},
authenticateAgent: async (token) => {
const user = await verifyJWT(token);
return user ? { adminUserId: user.id, displayName: user.name } : null;
},
},
hooks: {
onCallCreated: (callLog) => console.log('New call:', callLog.callLogId),
onStageChanged: (callLog, from, to) => console.log(`Stage: ${from} -> ${to}`),
onCallClosed: (callLog) => console.log('Call closed:', callLog.callLogId),
onFollowUpDue: async (callLog) => notifyAgent(callLog),
onMetric: (metric) => prometheus.observe(metric.name, metric.value, metric.labels),
},
options: {
maxTimelineEntries: 200, // default
followUpCheckIntervalMs: 60_000, // default: 1 minute
},
});Features
- Pipeline management -- CRUD pipelines with configurable stages, default/terminal flags, and stage reordering. Details
- Call log lifecycle -- Create, update, change stage, assign, close, reopen, soft delete calls with automatic timeline tracking. Details
- Call channels -- Track communication channel per call (phone, whatsapp, telegram, etc.). Admin-configurable
availableChannelsin settings. Filterable in list queries. Channel distribution in analytics. - Call outcomes -- Track result of each call separate from pipeline stage (interested, not_interested, no_answer, etc.). Admin-configurable
availableOutcomesin settings. Filterable, with outcome distribution in analytics. - Follow-up flag --
isFollowUpboolean distinguishes follow-up calls from fresh calls. Filterable in list queries. Follow-up ratio computed in analytics. - Soft delete --
DELETE /:idsoft-deletes withisDeletedflag anddeletedAttimestamp. Excluded from all queries and analytics by default.includeDeleted=truequery param for audit access. - Agent-scoped filtering -- When
enableAgentScopingis true (default), non-owner staff see only their own calls in list and analytics. Owners see everything. Based onrolefield fromauthenticateAgentadapter. - Timeline -- Append-only audit trail per call with notes, stage changes, assignments, follow-up events. Details
- Contact timeline -- Merged cross-call timeline for a contact. Details
- Follow-up worker -- Background worker polls for due follow-ups and fires
onFollowUpDuehook. Starts automatically, stops viaengine.destroy(). Details - Analytics -- Dashboard stats, agent stats, leaderboard, pipeline stats/funnel, team stats, daily/weekly/overall reports, channel/outcome distributions, follow-up ratio. Deleted calls excluded from all analytics. Details
- Export -- Bulk call export, single call export, pipeline report export in JSON or CSV. Details
- Settings -- Runtime-mutable tags, categories, priority levels, follow-up defaults, available channels, available outcomes. Settings updates use partial merge (
$set) -- only fields you provide are updated. Callingsettings.update({ availableChannels: [...] })will NOT overwrite other settings likeavailableOutcomesordefaultFollowUpDays. Details - Bulk operations -- Bulk stage change for multiple call logs at once. Details
- Contact adapters -- Pluggable contact lookup and creation. Details
- Agent sharing -- Reuse chat-engine's agent collection. Details
- Lifecycle hooks -- 6 hooks for call events, follow-ups, and metrics. Details
- Error classes -- Typed errors with codes for every failure scenario.
Phase 2 Routes
New routes
| Method | Route | Description |
|--------|-------|-------------|
| DELETE | /calls/:id | Soft-delete a call log (sets isDeleted + deletedAt) |
| GET | /analytics/channel-distribution | Channel breakdown — query: from?, to? |
| GET | /analytics/outcome-distribution | Outcome breakdown — query: from?, to? |
| GET | /analytics/follow-up-stats | Follow-up ratio — query: from?, to? |
New query params on GET /calls
| Param | Type | Description |
|-------|------|-------------|
| channel | string | Filter by communication channel |
| outcome | string | Filter by call outcome |
| isFollowUp | boolean | Filter follow-up calls (true or false) |
| includeDeleted | boolean | Include soft-deleted calls in results (true or false, default false) |
Architecture
The library exposes an Express router from a single factory call:
| Export | Purpose | Access |
|--------|---------|--------|
| engine.routes | REST API -- pipelines, calls, contacts, analytics, settings, export | Protected (via authenticateAgent adapter) |
| engine.destroy() | Stops follow-up worker, cleans up resources | Call on shutdown |
All services are also available programmatically via the returned engine object: pipelines, callLogs, lifecycle, timeline, analytics, pipelineAnalytics, settings, export, models.
Seeding Data
Schema factory functions are exported so you can seed data or run scripts without creating a full engine instance:
import { createPipelineModel, createCallLogSettingsModel } from '@astralibx/call-log-engine';
const Pipeline = createPipelineModel(connection);
const Settings = createCallLogSettingsModel(connection);
await Pipeline.create({ ... });Getting Started Guide
- Configuration -- Set up database, agents, adapters, and options
- Adapters -- Implement contact lookup, authentication, and agent resolution
- Hooks -- Wire up notifications, analytics, and monitoring
Guides: Agent Sharing
Reference: API Routes
Links
License
MIT
