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

tally-ai

v0.1.1

Published

Natural language to query and AI columns for Tally.

Readme

tally-ai

Natural language to query and AI columns for Tally. Works with any model the AI SDK can call: Anthropic, OpenAI, Google, Mistral, Ollama, a gateway model id or your own provider.

Not published yet.

Install

npm install tally-ai ai @ai-sdk/anthropic

Ask

ask turns a question into a validated Tally query. The model answers in Tally query text, the text is parsed against your schema, and parse errors go back to the model for one repair round. Only a query that parses is returned, so the model never applies free text to a view.

import { anthropic } from '@ai-sdk/anthropic'
import { createSchema } from 'tally-core'
import { ask } from 'tally-ai'

const schema = createSchema({
  columns: [
    { id: 'account', label: 'Account' },
    { id: 'plan', type: 'enum', options: [{ value: 'pro' }, { value: 'team' }] },
    { id: 'mrr', label: 'MRR', type: 'currency' },
    { id: 'renewal', type: 'date' },
  ],
})

const result = await ask('team plans renewing this quarter, biggest first', {
  model: anthropic('claude-sonnet-5-5'),
  schema,
})

result.text
// 'plan is team and renewal this quarter, sort by mrr desc'
result.query
// { filter: { type: 'and', filters: [...] }, sort: [{ column: 'mrr', direction: 'desc' }] }
result.explanation
// 'Team accounts whose renewal falls in this quarter, largest MRR first'

Options:

| Option | Default | Purpose | | ---------- | -------------- | ---------------------------------------------- | | model | | Any AI SDK LanguageModel | | schema | | The grid schema the query is validated against | | examples | [] | Example queries shown to the model | | context | en-US, UTC | Format context; the time zone resolves today | | now | new Date() | Clock for relative dates | | repairs | 1 | Repair rounds after a parse error | | signal | | Abort signal passed to the model call |

When the model cannot produce a parseable query, ask throws an AskError carrying every attempt and its parse errors.

With tally-react

createAskHandler returns the ask handler for the ai prop of Tally. The schema comes from the grid. Text typed into the filter bar that does not parse as a query, or reads like a sentence, goes to the handler and the answer lands as filter chips.

import { createAskHandler } from 'tally-ai'

const ai = { ask: createAskHandler({ model: anthropic('claude-sonnet-5-5') }) }

<Tally grid={grid} ai={ai} />

Model calls need an API key. In a browser app point the provider at a same-origin proxy that adds the key, as the playground does in examples/playground/server/anthropic.ts, so ask, designColumn and withAiColumns all run on the client.

AI columns

withAiColumns wraps any data source. Rows come back immediately, the model fills the AI columns in batches, and the values arrive as live patches, so the grid updates the cells as they resolve. Values are cached per row and recomputed when their input columns change.

import { createArraySource, createSchema } from 'tally-core'
import { withAiColumns } from 'tally-ai'

const schema = createSchema({
  columns: [
    { id: 'account' },
    { id: 'notes' },
    {
      id: 'mood',
      type: 'enum',
      options: [{ value: 'happy' }, { value: 'neutral' }, { value: 'unhappy' }],
      filterable: false,
      sortable: false,
      groupable: false,
    },
  ],
})

const source = withAiColumns(createArraySource(rows, schema), schema, [
  {
    column: 'mood',
    model: anthropic('claude-haiku-5-5'),
    instruction: 'Judge the customer mood from the notes.',
    inputs: ['notes'],
  },
])

AI columns are computed on the client, so they must be declared with filterable, sortable and groupable set to false. Mark them ai: true and tally-react renders the header with a sparkle, shows a shimmer while a value is pending and reveals it when it arrives. The returned source exposes pending(column?) with the keys still being computed and idle(), a promise that resolves when every batch has finished.

Designing a column from a prompt

designColumn(prompt, { model, schema }) asks the model for a column definition and the instruction to fill it, ready for withAiColumns. The column comes back as ai: true, non filterable, non sortable and non groupable, with a unique id and, for enums, tinted options.

import { designColumn, withAiColumns } from 'tally-ai'

const { column, instruction } = await designColumn('Churn risk, low, medium or high', {
  model: anthropic('claude-sonnet-5-5'),
  schema,
})
const extended = schema.extend([column], 1)
const source = withAiColumns(base, extended, [{ column: column.id, model, instruction }])

tally-react wires this up through the addColumn handler of the ai prop: the AI button opens a prompt, the handler returns the new column id, and the grid animates the column in. The playground keeps the added columns in state and rebuilds the schema and source, which useGrid picks up while keeping the current view.

| Option | Default | Purpose | | ------------- | ------------------- | ---------------------------------------------- | | column | | Id of the column to fill | | model | | Any AI SDK LanguageModel | | instruction | | What to compute | | inputs | every non-AI column | Columns sent to the model for each row | | batchSize | 20 | Rows per model call | | concurrency | 2 | Model calls in flight per column | | cache | in-memory Map | Anything with get(key) and set(key, value) |

Prompts

describeSchema(schema, options) returns the system prompt ask uses: the query grammar, every visible column with its type, operators, enum values, aliases and limits, optional examples and today's date. Use it when you drive your own agent loop.