npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

@ticket-assistant/core

v1.0.1

Published

Headless, AI-powered support ticket triage and assignment framework

Readme

@ticket-assistant/core (Ticket Assistant Core)

Headless, embeddable, AI-powered support ticket triage and routing framework.

npm version License: ISC

@ticket-assistant/core is an unopinionated backend engine that gives your application an enterprise-grade customer support triage loop with zero external queue dependencies.


📦 Installation

npm install @ticket-assistant/core

(Optional) If you plan to use the built-in Express router adapter:

npm install express cors

Quick Start

1. Direct Programmatic API (Next.js, Remix, Serverless)

Use Ticket Assistant directly within web-standard API route handlers without needing an Express server.

Step A: Configure next.config.ts

Add @ticket-assistant/core to serverExternalPackages so Next.js treats it as a backend server module:

// next.config.ts
const nextConfig = {
  serverExternalPackages: ['@ticket-assistant/core'],
};
export default nextConfig;

Step B: Create ticket.config.js

// ticket.config.js
import { defineConfig } from '@ticket-assistant/core';

export default defineConfig({
  storage: {
    provider: 'supabase', // or 'mongo'
    supabaseUrl: process.env.SUPABASE_URL || process.env.NEXT_PUBLIC_SUPABASE_URL,
    supabaseKey: process.env.SUPABASE_SERVICE_ROLE_KEY || process.env.SUPABASE_KEY
  },
  ai: {
    apiKey: process.env.GEMINI_API_KEY || process.env.GROQ_API_KEY,
    model: process.env.AI_MODEL || 'gemini-2.0-flash'
  },
  agents: [
    {
      name: 'Global Support Lead',
      email: '[email protected]',
      skills: ['Payments', 'Billing', 'Account', 'Technical']
    }
  ]
});

Step C: Create the Singleton Helper (src/lib/ticket-assistant.ts)

// src/lib/ticket-assistant.ts
import { TicketAssistant } from '@ticket-assistant/core';
import config from '../../ticket.config.js';

let assistantInstance: TicketAssistant | null = null;
let seeded = false;

export function getTicketAssistant(): TicketAssistant {
  if (!assistantInstance) {
    assistantInstance = new TicketAssistant(config);
  }
  return assistantInstance;
}

export async function ensureAgentsSeeded() {
  if (seeded) return;
  const assistant = getTicketAssistant();
  await assistant.seedAgents();
  seeded = true;
}

Step D: Route Handlers (src/app/api/support/tickets/route.ts)

import { NextResponse } from 'next/server';
import { getTicketAssistant, ensureAgentsSeeded } from '@/lib/ticket-assistant';

export async function GET() {
  await ensureAgentsSeeded();
  const assistant = getTicketAssistant();
  const tickets = await assistant.getTickets();
  return NextResponse.json(tickets);
}

export async function POST(req: Request) {
  await ensureAgentsSeeded();
  const assistant = getTicketAssistant();
  const { title, description } = await req.json();

  const ticket = await assistant.createTicket({
    title,
    description
  });

  return NextResponse.json(ticket, { status: 201 });
}

Step E: Agent Authentication (Next.js / NextAuth / Server Actions)

You can create agents with passwords (auto-hashed using zero-dependency built-in crypto) and verify credentials directly in Next.js Server Actions, Route Handlers, or NextAuth / Auth.js:

import { getTicketAssistant } from '@/lib/ticket-assistant';

const assistant = getTicketAssistant();

// 1. Register an agent with a password (auto-hashed with scrypt)
const agent = await assistant.createAgent({
  email: '[email protected]',
  name: 'Alex Johnson',
  password: 'SuperSecretPassword123!',
  skills: ['billing', 'technical']
});

// 2. Verify credentials in your login route or NextAuth authorize callback:
const verifiedAgent = await assistant.verifyAgentCredentials(
  '[email protected]',
  'SuperSecretPassword123!'
);

if (!verifiedAgent) {
  throw new Error('Invalid email or password');
}
// Returns safe agent object with id, email, name, skills (password hash stripped)

2. Express Server Integration

If you run an Express backend, Ticket Assistant includes a pre-configured lazy-loaded router:

import express from 'express';
import { TicketAssistant } from '@ticket-assistant/core';

const app = express();
app.use(express.json());

const assistant = new TicketAssistant({
  storage: 'mongo',
  mongoUri: process.env.MONGODB_URI,
  auth: {
    // Customer auth middleware: protects ticket submission & viewing
    middleware: (req, res, next) => {
      if (!req.headers.authorization) return res.status(401).json({ error: "Unauthorized" });
      next();
    },
    // Agent auth middleware: protects ticket assignment & status updates
    agentMiddleware: (req, res, next) => {
      // Custom role verification
      next();
    }
  }
});

await assistant.connect();

// Mounts:
// GET    /api/tickets       - List tickets (with ?status, ?assignedTo filters)
// POST   /api/tickets       - Create ticket & trigger background AI triage
// GET    /api/tickets/:id   - Fetch single ticket details & AI notes
// PATCH  /api/tickets/:id   - Update status or reassign ticket
// GET    /api/agents        - List support agents
// POST   /api/agents        - Register a new support agent
// PATCH  /api/agents/:id    - Update agent skills or details
// DELETE /api/agents/:id    - Delete agent
app.use('/api', await assistant.getRouter());

app.listen(3000, () => console.log('Support API running on port 3000'));

🗄️ Storage Proxies

Ticket Assistant isolates all data using namespaced tables (ticketai_*), ensuring zero interference with your app's existing schema.

Supabase (PostgreSQL)

const assistant = new TicketAssistant({
  storage: 'supabase',
  supabaseUrl: 'https://xyz.supabase.co',
  supabaseKey: 'service-role-key'
});

Create the tables once in Supabase SQL editor:

CREATE TABLE IF NOT EXISTS ticketai_agents (
  id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
  name TEXT NOT NULL,
  email TEXT UNIQUE NOT NULL,
  skills TEXT[] DEFAULT '{}',
  password_hash TEXT,
  auth_provider_id TEXT,
  metadata JSONB DEFAULT '{}'::jsonb,
  created_at TIMESTAMPTZ DEFAULT NOW(),
  updated_at TIMESTAMPTZ DEFAULT NOW()
);

CREATE TABLE IF NOT EXISTS ticketai_tickets (
  id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
  title TEXT NOT NULL,
  description TEXT NOT NULL,
  status TEXT DEFAULT 'TODO' CHECK (status IN ('TODO', 'IN_PROGRESS', 'DONE')),
  priority TEXT CHECK (priority IN ('low', 'medium', 'high')),
  summary TEXT,
  helpful_notes TEXT,
  related_skills TEXT[] DEFAULT '{}',
  assigned_to UUID REFERENCES ticketai_agents(id) ON DELETE SET NULL,
  created_by TEXT,
  created_at TIMESTAMPTZ DEFAULT NOW(),
  updated_at TIMESTAMPTZ DEFAULT NOW()
);

MongoDB (Mongoose)

const assistant = new TicketAssistant({
  storage: 'mongo',
  mongoUri: 'mongodb+srv://user:[email protected]/dbname'
});

Mongoose automatically manages ticketai_tickets and ticketai_agents schemas.


🤖 AI Providers & Model Configuration

Ticket Assistant supports any OpenAI-compatible completions API using native zero-dependency HTTP fetch. The provider endpoint is automatically resolved from your environment variables:

// Example 1: Google Gemini (automatic endpoint resolution)
const assistant = new TicketAssistant({
  ai: {
    apiKey: process.env.GEMINI_API_KEY,
    model: 'gemini-2.0-flash' // or 'gemini-1.5-flash', 'gemini-1.5-pro'
  }
});

// Example 2: Groq (high-speed inference)
const assistant = new TicketAssistant({
  ai: {
    apiKey: process.env.GROQ_API_KEY,
    model: 'openai/gpt-oss-20b' // or 'qwen/qwen3.8-27b'
  }
});

// Example 3: OpenAI
const assistant = new TicketAssistant({
  ai: {
    apiKey: process.env.OPENAI_API_KEY,
    model: 'gpt-4o-mini' // or 'gpt-4o'
  }
});

// Example 4: Local Ollama / Custom vLLM
const assistant = new TicketAssistant({
  ai: {
    baseUrl: 'http://localhost:11434/v1',
    model: 'llama3'
  }
});

Note: Ticket Assistant never hardcodes default AI models. You can use any model supported by your provider by supplying model in your configuration or AI_MODEL in your environment.


📚 Programmatic API Reference

Tickets

  • assistant.createTicket({ title, description, createdBy }): Creates ticket and launches async triage loop.
  • assistant.getTickets(filter): Returns array of tickets matching optional { status, assignedTo, createdBy }.
  • assistant.getTicket(id): Returns ticket by ID.
  • assistant.updateTicket(id, updates): Updates status, priority, or assigned agent.

Agents

  • assistant.createAgent({ name, email, skills }): Adds a support agent for AI routing.
  • assistant.getAgents(): Returns all registered agents and their skill keywords.
  • assistant.getAgentByEmail(email): Finds agent by email.
  • assistant.updateAgent(id, updates): Updates agent skills or name.
  • assistant.deleteAgent(id): Deletes an agent.

📄 License

ISC License © 2026 Ticket Assistant Contributors.