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

tuul-sdk-ts

v0.2.6

Published

TypeScript SDK for Tuul agent runtime, SSE streaming, triggers, and embed helpers.

Readme

Tuul SDK TS

TypeScript-first SDK for Tuul agent runtimes, streaming responses, local tool orchestration, widget configuration, and React integration.

Install

npm install tuul-sdk-ts
# or
pnpm add tuul-sdk-ts
# or
yarn add tuul-sdk-ts

For React apps, react 18+ must also be installed.

Package entry points

  • Core SDK: tuul-sdk-ts
  • React support: tuul-sdk-ts/react

Quick start

import { TuulClient } from "tuul-sdk-ts";

const client = new TuulClient({
  agentId: "your-agent-id",
  apiKey: "your-sdk-api-key",
  defaultSessionId: "browser-session-1",
});

const response = await client.generate({
  input: "Summarize the latest customer support queue in three bullets.",
});

console.log(response.text);

Core usage

Create a client

const client = new TuulClient({
  agentId: "your-agent-id",
  apiKey: "your-sdk-api-key",
  widgetKey: "your-widget-key", // optional
  defaultSessionId: "browser-session-1",
});

Generate text

const response = await client.generate({
  input: "Write a short product update for our engineering team.",
  stream: false,
});

console.log(response.text);

Stream responses

for await (const event of client.stream({
  input: "Write a launch announcement and think step by step.",
  localTools: [
    {
      name: "local_weather_lookup",
      description: "Looks up locally cached weather data on the client.",
      inputSchema: {
        type: "object",
        properties: { city: { type: "string" } },
        required: ["city"],
      },
      async execute(input) {
        const args = input as { city: string };
        return { city: args.city, forecast: "Sunny" };
      },
    },
  ],
})) {
  if (event.type === "delta" && event.text) {
    process.stdout.write(event.text);
  }

  if (event.type === "tool-call") {
    console.log("Tool call requested:", event.toolName, event.input);
  }

  if (event.type === "tool-result") {
    console.log("Tool result received:", event.toolName, event.output);
  }

  if (event.type === "finish") {
    console.log("Finish reason:", event.finishReason);
  }
}

When localTools are provided, the SDK executes the matching local tool and sends the result back to the runtime automatically. The stream will continue once the local result is delivered.

Prompt helper

Use prompt() to automatically select streaming or non-streaming behavior.

const result = await client.prompt({
  input: "Create a short summary.",
  stream: false,
});

Local tools

Local tools let your application execute client-side logic when the model requests it. The SDK now supports seamless local-tool streaming: the runtime emits a tool-call, the client executes the local tool, and the SDK submits the result back to the runtime automatically.

const response = await client.generate({
  input: "Use the local weather lookup tool for Lagos and tell me what to wear.",
  stream: false,
  localTools: [
    {
      name: "local_weather_lookup",
      description: "Looks up locally cached weather data on the client.",
      inputSchema: {
        type: "object",
        properties: {
          city: { type: "string" },
        },
        required: ["city"],
      },
      async execute(input) {
        const args = input as { city: string };
        return {
          city: args.city,
          forecast: "Humid with scattered clouds",
          temperatureC: 30,
        };
      },
    },
  ],
});

console.log(response.text);

When the model emits a recognized tool call, the SDK executes the tool and continues the request automatically.

Orchestrated local tools example

const response = await client.generate({
  input: "Check the ticket queue, get customer health, and draft a priority summary.",
  stream: false,
  localTools: [
    {
      name: "queue_snapshot",
      description: "Returns the latest support queue grouped by severity.",
      inputSchema: { type: "object", properties: {} },
      async execute() {
        return { open: 14, urgent: 3 };
      },
    },
    {
      name: "customer_health_lookup",
      description: "Looks up CRM health signals for a customer id.",
      inputSchema: {
        type: "object",
        properties: {
          customerId: { type: "string" },
        },
        required: ["customerId"],
      },
      async execute(input) {
        const args = input as { customerId: string };
        return { customerId: args.customerId, plan: "enterprise", renewalRisk: "medium" };
      },
    },
  ],
});

console.log(response.text);

Direct tool calls

The SDK also supports explicit tool execution with callTool().

const result = await client.callTool("weather.lookup", {
  params: {
    city: "Lagos",
    units: "metric",
  },
});

console.log(result.toolName, result.result);

Widget support

The same client can fetch public widget information.

const widgetConfig = await client.getWidgetConfig();
const widgetTheme = await client.getWidgetTheme();
const widgetEmbed = await client.getWidgetEmbed();

console.log(widgetConfig.launcherLabel);
console.log(widgetTheme.primaryAccentToken);
console.log(widgetEmbed.snippet);

React integration

import { TuulAgentProvider, useTuulChat, TuulAgentFab, TuulAgentWidget } from "tuul-sdk-ts/react";

function App() {
  return (
    <TuulAgentProvider
      config={{
        agentId: "your-agent-id",
        apiKey: "your-sdk-api-key",
        defaultSessionId: "browser-session-1",
      }}
    >
      <ConversationPanel />
    </TuulAgentProvider>
  );
}

useTuulChat() example

import { useTuulChat } from "tuul-sdk-ts/react";

function ConversationPanel() {
  const { messages, conversations, send, loadConversations, renameConversation, deleteConversation } = useTuulChat({
    sessionId: "browser-session-1",
    autoLoadConversations: true,
  });

  return (
    <div>
      <button onClick={() => void loadConversations()}>Refresh conversations</button>
      <button onClick={() => void send("Hello from React")}>Send greeting</button>
      <pre>{JSON.stringify(messages, null, 2)}</pre>
    </div>
  );
}

JavaScript / CommonJS usage

This package publishes both ESM and CommonJS builds.

const { TuulClient } = require("tuul-sdk-ts");

const client = new TuulClient({
  agentId: "your-agent-id",
  apiKey: "your-sdk-api-key",
  defaultSessionId: "browser-session-1",
});

Additional helpers

The SDK exports low-level streaming helpers:

  • collectRuntimeStream
  • collectStreamText
  • parseSseStream

Use these when you need manual SSE handling or a custom streaming pipeline.

Error handling

import { TuulSdkError } from "tuul-sdk-ts";

Handle API errors consistently using the SDK error type.

Included examples

The repository contains example files in examples/:

  • 01-basic-generate.ts
  • 02-stream-runtime.ts
  • 03-local-tools.ts
  • 04-widget-and-security.ts
  • 05-conversations-and-react.tsx
  • 06-tool-call-basic.ts
  • 07-tool-call-session.ts

Notes

  • Use defaultSessionId to keep requests in the same session.
  • widgetKey is required for widget endpoint access.
  • Local tools run only when the model emits a matching tool call.
  • This SDK is built for both TypeScript and JavaScript consumers.