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

@dbx-tools/genie-shared

v0.1.36

Published

Pure types and sync helpers for `@dbx-tools/genie`. Wire-format zod schemas (extending the generated `@dbx-tools/sdk-shared` Genie shapes), the high-level `GenieChatEvent` discriminated union the `genieEventChat` driver emits, and the per-event detectors

Readme

@dbx-tools/genie-shared

Pure types and sync helpers for @dbx-tools/genie. Wire-format zod schemas (extending the generated @dbx-tools/sdk-shared Genie shapes), the high-level GenieChatEvent discriminated union the genieEventChat driver emits, and the per-event detectors that derive those events from a GenieMessage snapshot diff.

No node:*, no WorkspaceClient, no I/O. Safe to import from any runtime, including browser bundles.

import {
  // Wire schemas (extended over @dbx-tools/sdk-shared)
  GenieMessageSchema,
  GenieAttachmentSchema,
  GenieQueryAttachmentSchema,
  GenieThoughtSchema,
  // High-level event union
  GenieChatEventSchema,
  type GenieChatEvent,
  type GenieChatLocation,
  // Status helpers
  TERMINAL_STATUSES,
  isTerminalStatus,
  humanizeStatus,
  // Attachment discriminator
  detectAttachmentType,
  tagAttachment,
  // Pure event detectors + orchestrator
  eventsFromMessage,
  detectStatus,
  detectThinking,
  detectText,
  detectQuery,
  detectStatement,
  detectRows,
  detectSuggestedQuestions,
  detectAttachmentAdded,
} from "@dbx-tools/genie-shared";

Server-side chat driving (genieChat, genieEventChat) lives in @dbx-tools/genie and pulls these types in. Frontends only need this package.

Widened wire schemas

The SDK shapes from @dbx-tools/sdk-shared are re-exported with a few fields Genie ships on the wire that the upstream .d.ts doesn't currently type:

| Schema | Extension | | ---------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | | GenieMessageSchema | Adds auto_regenerate_count: number and re-types attachments to the local GenieAttachmentSchema. | | GenieAttachmentSchema | Re-types query to the thoughts-aware GenieQueryAttachmentSchema, adds attachment_type discriminator literal so consumers can switch (att.attachment_type) instead of probing which sub-object is populated. | | GenieQueryAttachmentSchema | Adds thoughts: GenieThought[] (the streamed reasoning payload). | | GenieThoughtSchema | New: { thought_type, content }. See GenieThoughtType for the known kinds. |

Thought types

Open at the type level (| (string & {})) so a new server-side thought type doesn't break compilation; the four known types still narrow correctly under switch:

| thought_type | Content | | ------------------------------- | -------------------------------------------------------------------------------------- | | THOUGHT_TYPE_DESCRIPTION | One-paragraph restatement of what the user asked. | | THOUGHT_TYPE_DATA_SOURCING | Markdown bullets of the fully-qualified catalog.schema.table sources Genie chose. | | THOUGHT_TYPE_STEPS | High-level plan Genie wrote before running SQL (one bullet per step). | | THOUGHT_TYPE_UNDERSTANDING | Ambiguity / interpretation notes ("'revenue' could be gross, net, or recognized..."). |

Attachment discriminator

Genie populates only one of query / text / suggested_questions per attachment slot. tagAttachment(att) stamps the matching discriminator literal onto att.attachment_type; detectAttachmentType(att) just returns it without copying.

import { tagAttachment, detectAttachmentType } from "@dbx-tools/genie-shared";

const tagged = tagAttachment(att);
switch (tagged.attachment_type) {
  case "query":               // tagged.query is non-null
  case "text":                // tagged.text is non-null
  case "suggested_questions": // tagged.suggested_questions is non-null
}

Terminal-status helpers

import { TERMINAL_STATUSES, isTerminalStatus, humanizeStatus } from "@dbx-tools/genie-shared";

TERMINAL_STATUSES; // ["COMPLETED", "FAILED", "CANCELLED"] as const

if (isTerminalStatus(msg.status)) {
  // msg.status is now TerminalStatus
}

humanizeStatus("EXECUTING_QUERY"); // "Running SQL query"
humanizeStatus("FUTURE_NEW_STATE"); // "Future new state" (falls back to tokenizer)

humanizeStatus is the single source of truth for status pill labels. Both the server (via @dbx-tools/genie) and any UI that subscribes to status events call it so labels stay in lock-step across the wire.

GenieChatEvent union

genieEventChat (in @dbx-tools/genie) drives a turn and yields a stream of these. Each variant is a flat { type, ...fields } object with type as the discriminator and snake_case payload fields hoisted to the top level - no payload wrapper.

| type | Source | Notable fields | | --------------------- | ------------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------- | | question | Lifecycle. Fires once per turn, on the first message yield. | content, message_id, conversation_id, space_id | | message | Lifecycle. Fires once per poll yield. | message: GenieMessage | | status | Top-level message.status transitioned. | status, previous_status | | attachment | A new attachment slot appeared in message.attachments[]. | index, attachment_type | | thinking | A new (thought_type, content) tuple on a query attachment (value-based dedupe). | text, thought_type | | text | Text-attachment content appeared or changed. | text | | query | SQL was finalized on a query attachment (transitioned undefined -> string or rewrote). | sql, title?, description? | | statement | SQL submitted to a warehouse and a statement_id was assigned. | statement_id | | rows | Row count on a query attachment changed (fires for undefined -> 0 and 0 -> N). | row_count, previous_row_count, statement_id | | suggested_questions | Follow-up suggested-questions array appeared or rewrote. | questions: string[] | | result | Lifecycle. Fires once on the terminal snapshot. | status: TerminalStatus, message: GenieMessage |

Every variant carries a GenieChatLocation mixin (space_id, conversation_id?, message_id?, attachment_id?) so subscribers can route, log, or correlate without re-walking the message.

import { type GenieChatEvent } from "@dbx-tools/genie-shared";

function handleEvent(event: GenieChatEvent) {
  switch (event.type) {
    case "question":
      console.log(`[Q]`, event.content);
      break;
    case "thinking":
      console.log(`[think:${event.thought_type}]`, event.text);
      break;
    case "query":
      console.log(`[sql]`, event.title, "\n", event.sql);
      break;
    case "rows":
      console.log(`[rows]`, event.previous_row_count, "->", event.row_count);
      break;
    case "result":
      console.log(`[done]`, event.status);
      break;
  }
}

Stream order per turn

  1. question (deferred to the first message yield so the assigned message_id is present).
  2. message for every poll yield (carries the raw snapshot on event.message).
  3. Any derived events the snapshot diff produced (status, attachment, thinking, text, query, statement, rows, suggested_questions) in that fixed order.
  4. On the terminal snapshot, a final result event.

Errors propagate via the generator throwing - there is no error variant on the union. Wrap the for await in try / catch if you need to handle failures.

Detectors + eventsFromMessage

If you want to derive events from GenieMessage snapshots on the client (e.g. replaying persisted history, or driving your own loop that bypasses genieEventChat), use the pure detectors directly:

import {
  eventsFromMessage,
  detectStatus,
  detectText,
} from "@dbx-tools/genie-shared";

// All detectors, in stable wire order:
for (const event of eventsFromMessage(current, previous, spaceId)) {
  handleEvent(event);
}

// Or one detector at a time:
const statusEvent = detectStatus.detect(current, previous, spaceId);
const textEvent   = detectText.detect(currAttachment, prevAttachment, location, idx);

Each detector is built with eventDetector(name, detect) so the event name ("status") is a string literal that TS uses to look up the diff signature (message vs attachment) and the allowed return-fields shape (DetectorResult<T>). Mis-typing the event name or returning the wrong fields fails to compile.

License

Apache-2.0