@nexwage/ai-tool
v0.2.4
Published
Nexwage AI tool package with TypeScript builders, parsers, validators, and handlers for LLM resource tools.
Maintainers
Readme
AI Packages: Builders, Parsers, Handlers, and Remote Host Contract
Package npm: @nexwage/ai-tool
Install:
npm install @nexwage/ai-toolImport 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-tooltetap 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) viaexecutor.remote_host: kontrak envelope untukPOST /tools/executeagar 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:
buildUpdateResourceTooldari@nexwage/ai-tool/update_resourcebuildDeleteResourceTooldari@nexwage/ai-tool/delete_resourcebuildSearchResourcesTooldari@nexwage/ai-tool/search_resourcesbuildCountResourcesTooldari@nexwage/ai-tool/count_resourcesbuildTrackResourceTooldari@nexwage/ai-tool/track_resourcebuildUpdateResourceStatusTooldari@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:
createGetResourceRemoteHandlercreateListResourceRemoteHandlercreateCreateResourceRemoteHandlercreateUpdateResourceRemoteHandlercreateDeleteResourceRemoteHandlercreateSearchResourcesRemoteHandlercreateCountResourcesRemoteHandlercreateTrackResourceRemoteHandlercreateUpdateResourceStatusRemoteHandler
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
argsdilakukan oleh masing-masingcreateXHandler(...). createXRemoteHandler(...)mengembalikan response yang sudah di-map keRemoteToolResponse.datadi response sukses dapat berupa object atau array, sesuai output handler.
4) Catatan LLM-friendly
- Hindari nested object pada argumen tool, kecuali
payloaddicreate_resource/update_resource. - Untuk filter kompleks, kirim sebagai string expression di field
filters. - Selalu isi
descriptiontool 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
