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

@nexwage/ai-tool

v0.2.4

Published

Nexwage AI tool package with TypeScript builders, parsers, validators, and handlers for LLM resource tools.

Readme

AI Packages: Builders, Parsers, Handlers, and Remote Host Contract

Package npm: @nexwage/ai-tool

Install:

npm install @nexwage/ai-tool

Import dari root package:

import { buildGetResourceTool, createGetResourceHandler, createGetResourceRemoteHandler } from '@nexwage/ai-tool';

Import yang direkomendasikan untuk bundle lebih kecil:

import { buildGetResourceTool, createGetResourceHandler, createGetResourceRemoteHandler } from '@nexwage/ai-tool/get_resource';

Catatan:

  • Gunakan subpath import jika hanya butuh satu tool/module.
  • Root import @nexwage/ai-tool tetap didukung, tetapi bisa membuat bundler menarik lebih banyak code.
  • Subpath yang tersedia: get_resource, list_resource, create_resource, update_resource, delete_resource, search_resources, count_resources, track_resource, update_resource_status, remote_host.

Tujuan package ini:

  • builder.ts: membangun JSON tool definition (untuk dikirim ke LLM).
  • parser.ts: parse + validasi argumen dari function call LLM.
  • handler.ts: wrapper eksekusi nyata (DB/API/host lain) via executor.
  • remote_host: kontrak envelope untuk POST /tools/execute agar integrator remote host dapat parse payload tanpa menulis schema manual.

1) Cara isi builder (contoh real)

get_resource

import { buildGetResourceTool } from '@nexwage/ai-tool/get_resource';

const tool = buildGetResourceTool({
  description: 'Get one active product/service by id, code, or exact name.',
  parameters: {
    type: 'object',
    properties: {
      resource: { type: 'string', description: 'Resource name. Example: products' },
      value: { type: 'string', description: 'Selector value (id/code/name)' },
      issuer: { type: 'string', description: 'Caller identity for audit logs' },
    },
    required: ['resource', 'value'],
  },
});

list_resource

import { buildListResourceTool } from '@nexwage/ai-tool/list_resource';

const tool = buildListResourceTool({
  description: 'List resources with optional filter expression and paging.',
  parameters: {
    type: 'object',
    properties: {
      resource: { type: 'string', description: 'Resource name. Example: products' },
      filters: { type: 'string', description: 'Filter expression, example: status=active' },
      fieldsCsv: { type: 'string', description: 'Selected fields CSV, example: id,code,name,price' },
      page: { type: 'number', description: 'Page number' },
      limit: { type: 'number', description: 'Page size' },
      sortBy: { type: 'string', description: 'Sort field' },
      sortOrder: { type: 'string', description: 'asc|desc', enum: ['asc', 'desc'] },
      issuer: { type: 'string', description: 'Caller identity for audit logs' },
    },
    required: ['resource'],
  },
});

create_resource

import { buildCreateResourceTool } from '@nexwage/ai-tool/create_resource';

const tool = buildCreateResourceTool({
  description: 'Create one record in requested resource.',
  parameters: {
    type: 'object',
    properties: {
      resource: { type: 'string', description: 'Resource name. Example: products' },
      payload: {
        type: 'object',
        description:
          'Record payload/body. Example: {"code":"PRD-001","name":"Oli Mesin Full Synthetic","price":95000,"stock":45,"isActive":true}',
      },
      issuer: { type: 'string', description: 'Caller identity for audit logs' },
    },
    required: ['resource', 'payload'],
  },
});

Tool lain sama pola-nya:

  • buildUpdateResourceTool dari @nexwage/ai-tool/update_resource
  • buildDeleteResourceTool dari @nexwage/ai-tool/delete_resource
  • buildSearchResourcesTool dari @nexwage/ai-tool/search_resources
  • buildCountResourcesTool dari @nexwage/ai-tool/count_resources
  • buildTrackResourceTool dari @nexwage/ai-tool/track_resource
  • buildUpdateResourceStatusTool dari @nexwage/ai-tool/update_resource_status

Ringkasan tujuan setiap tool

| Tool | Tujuan/Fungsi | | --- | --- | | get_resource | Ambil satu record berdasarkan selector unik seperti id, code, atau name. | | list_resource | Ambil daftar record dengan opsi filter, pagination, dan sorting. | | create_resource | Buat satu record baru berdasarkan payload. | | update_resource | Update satu record berdasarkan selector unik dan payload perubahan. | | delete_resource | Hapus satu record berdasarkan selector unik (soft/hard delete sesuai implementasi executor). | | search_resources | Cari record berdasarkan kata kunci (query) dengan filter opsional. | | count_resources | Hitung jumlah record sesuai filter opsional. | | track_resource | Lacak status/tahap lifecycle suatu record berdasarkan selector unik. | | update_resource_status | Ubah nilai status dari satu record target secara spesifik. |

2) Cara pakai handler (contoh real)

Contoh get_resource dengan executor nyata (DB/API).

import { createGetResourceHandler } from '@nexwage/ai-tool/get_resource';

const handler = createGetResourceHandler(async (args) => {
  // Contoh nyata: ganti ke repository/API call
  // return await productRepository.findByCodeOrName(args.resource, args.value);
  return {
    id: 'p-1',
    code: 'OLI-001',
    name: 'Oli Mesin Full Synthetic',
    resource: args.resource,
  };
});

const result = await handler({
  resource: 'products',
  value: 'OLI-001',
  issuer: 'crm-worker',
});

// result = { ok, message, data }

Pattern handler lain sama:

  • parse + validate input dari LLM
  • panggil executor (sumber data real)
  • kembalikan { ok, message, data }

Semua module juga menyediakan remote-ready wrapper:

  • createGetResourceRemoteHandler
  • createListResourceRemoteHandler
  • createCreateResourceRemoteHandler
  • createUpdateResourceRemoteHandler
  • createDeleteResourceRemoteHandler
  • createSearchResourcesRemoteHandler
  • createCountResourcesRemoteHandler
  • createTrackResourceRemoteHandler
  • createUpdateResourceStatusRemoteHandler

3) Remote Tool Host Contract (POST /tools/execute)

Jika kamu membuat server remote tool host (misalnya dengan Express), envelope request/response sebaiknya mengikuti kontrak yang konsisten.

Package ini menyediakan kontrak envelope di module remote_host:

import {
  parseRemoteToolRequest,
  REMOTE_TOOL_VERSION,
} from '@nexwage/ai-tool/remote_host';

Contoh dispatcher sederhana (pakai remote handler):

import express from 'express';
import { createGetResourceRemoteHandler } from '@nexwage/ai-tool/get_resource';
import {
  parseRemoteToolRequest,
  REMOTE_TOOL_VERSION,
} from '@nexwage/ai-tool/remote_host';

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

const getResource = createGetResourceRemoteHandler(
  async (args) => {
  return { id: 'p1', code: String(args.value), name: 'Example' };
  },
  { errorCode: 'resource_not_found', retriable: false },
);

app.post('/tools/execute', async (req, res) => {
  let input;
  try {
    input = parseRemoteToolRequest(req.body);
  } catch {
    return res.status(422).json({
      ok: false,
      message: 'Invalid remote tool request payload.',
      error: { code: 'invalid_request', retriable: false },
    });
  }

  if (input.version !== REMOTE_TOOL_VERSION.V1) {
    return res.status(422).json({
      ok: false,
      message: 'Unsupported contract version.',
      error: { code: 'unsupported_contract_version', retriable: false },
    });
  }

  if (input.toolName === 'get_resource') {
    return res.status(200).json(await getResource(input.args));
  }

  return res.status(422).json({
    ok: false,
    message: `Unsupported tool: ${input.toolName}`,
    error: { code: 'unsupported_tool', retriable: false },
  });
});

Catatan:

  • parseRemoteToolRequest(...) hanya memvalidasi envelope { version, requestId, toolName, scope, args }.
  • Validasi isi args dilakukan oleh masing-masing createXHandler(...).
  • createXRemoteHandler(...) mengembalikan response yang sudah di-map ke RemoteToolResponse.
  • data di response sukses dapat berupa object atau array, sesuai output handler.

4) Catatan LLM-friendly

  • Hindari nested object pada argumen tool, kecuali payload di create_resource/update_resource.
  • Untuk filter kompleks, kirim sebagai string expression di field filters.
  • Selalu isi description tool spesifik domain tenant agar routing LLM lebih akurat.

5) Tips saat data kosong (agar AI klarifikasi)

Jika data tidak ditemukan/kosong, kembalikan response handler dengan deskripsi yang memberi konteks tabel/data agar AI bisa bertanya klarifikasi yang tepat ke user.

Contoh:

{
  "ok": false,
  "message": "Resource not found.",
  "data": {
    "resource": "products",
    "description": "Table products berisi katalog produk aktif. Kolom umum: id, code, name, price, stock, isActive.",
    "hint": "Minta user sebutkan kode produk atau nama produk yang lebih spesifik."
  }
}

Dengan pola ini, AI bisa lanjut klarifikasi seperti:

  • meminta kode/id produk
  • meminta nama produk yang lebih spesifik
  • menawarkan daftar produk relevan jika user setuju