https://github.com/dnuzi/niyox
NiyoX AI - Powered by DanuZz.
https://github.com/dnuzi/niyox
agentic ai ai-agent ai-agents cli danuzz dnuzi html js movanest niyox react reactjs terminal trending
Last synced: about 1 month ago
JSON representation
NiyoX AI - Powered by DanuZz.
- Host: GitHub
- URL: https://github.com/dnuzi/niyox
- Owner: dnuzi
- License: mit
- Created: 2026-05-27T10:16:43.000Z (about 2 months ago)
- Default Branch: main
- Last Pushed: 2026-06-08T12:07:50.000Z (about 1 month ago)
- Last Synced: 2026-06-08T13:26:04.669Z (about 1 month ago)
- Topics: agentic, ai, ai-agent, ai-agents, cli, danuzz, dnuzi, html, js, movanest, niyox, react, reactjs, terminal, trending
- Language: JavaScript
- Homepage: https://www.npmjs.com/package/niyox
- Size: 484 KB
- Stars: 2
- Watchers: 0
- Forks: 0
- Open Issues: 0
-
Metadata Files:
- Readme: README.md
- Changelog: CHANGELOG.md
- Contributing: CONTRIBUTING.md
- License: LICENSE
- Code of conduct: CODE_OF_CONDUCT.md
- Security: SECURITY.md
Awesome Lists containing this project
README


[](https://www.npmjs.com/package/niyox)
```
███╗ ██╗██╗██╗ ██╗ ██████╗ ██╗ ██╗
████╗ ██║██║╚██╗ ██╔╝██╔═══██╗╚██╗██╔╝
██╔██╗ ██║██║ ╚████╔╝ ██║ ██║ ╚███╔╝
██║╚██╗██║██║ ╚██╔╝ ██║ ██║ ██╔██╗
██║ ╚████║██║ ██║ ╚██████╔╝██╔╝ ██╗
╚═╝ ╚═══╝╚═╝ ╚═╝ ╚═════╝ ╚═╝ ╚═╝
```

[](https://ai.dnuz.top)
[](https://github.com/dnuzi/niyox)
[](https://npmjs.com/package/niyox)
---

## What is NiyoX AI?
**NiyoX** is a full-featured AI SDK and CLI that wraps the [NiyoX AI REST API](https://ai.dnuz.top/api/ai). Chat with AI from your terminal, Node.js server, React/Next.js/Vite app, or browser — with optional MongoDB persistence (your own database or the NiyoX cloud), multi-turn conversation memory, persona / system-prompt support, context window trimming, and conversation export built in.
The package ships four layers you can use independently:
- **`NiyoXClient`** — thin HTTP wrapper, in-memory history, persona, export
- **`NiyoXStorage`** — optional MongoDB layer (plug in your own URI)
- **`NiyoXAI`** — high-level class combining both
- **`useNiyoX` / `NiyoXChat`** — React hook + ready-made component
---

## What's new in 0.0.4
| # | Change |
|---|---|
| 🎭 | **Persona / System Prompt** — set an AI personality once; injected into every message automatically. Auto-saved to MongoDB when storage is enabled. |
| ✂️ | **Context window trimming** — `maxHistory` option + `setMaxHistory()` prune oldest turns so conversations never silently overflow. |
| 📤 | **Conversation export** — `exportConversation(id, format)` dumps any conversation as **JSON**, **plain text**, or **Markdown**. Works in-memory (no DB needed) or from MongoDB. |
| ⚛️ | **React hook updated** — `useNiyoX()` now returns `persona`, `setPersona`, `maxHistory`, `setMaxHistory`, and `exportConversation`. |
| 🖥️ | **`` widget updated** — new 🎭 Persona editor and ⬇ Export button in the header. |
| 🧪 | **68 tests** — all new features covered (up from 38). |
---

## Features
| Feature | Status |
|---|:---:|
| 🖥️ Interactive REPL CLI | ✅ |
| ⚡ One-shot CLI queries | ✅ |
| 🔄 Multi-turn conversation memory | ✅ |
| 🗄️ Custom MongoDB URI (bring your own DB) | ✅ |
| ⚛️ React hook + component | ✅ |
| 🔷 Next.js App Router support | ✅ |
| ⚡ Vite + vanilla JS example | ✅ |
| 🌐 Browser / CDN support | ✅ |
| 📦 CommonJS + ESM dual package | ✅ |
| 🎨 Rich CLI output | ✅ |
| 🎭 Persona / System Prompt | ✅ **new** |
| ✂️ Context window trimming | ✅ **new** |
| 📤 Conversation export (JSON / text / MD) | ✅ **new** |
---

## Contents
[Install](#-install) · [CLI](#-cli) · [Node.js](#-nodejs) · [Persona](#-persona--system-prompt-new) · [Context Trimming](#-context-window-trimming-new) · [Export](#-conversation-export-new) · [React / Vite](#-react--vite) · [Next.js](#-nextjs) · [Custom MongoDB](#-custom-mongodb) · [Browser](#-browser) · [API Reference](#-api-reference) · [Development](#-development)
---

## Install
```bash
# Global — gives you the niyox command everywhere
npm install -g niyox
# Local — use in your project
npm install niyox
```
> Requires **Node.js ≥ 18**. On older Node, install `node-fetch` and it will be picked up automatically.
---

## CLI
**Launch the interactive REPL:**
```bash
niyox
```
**One-shot question:**
```bash
niyox "what is the speed of light?"
niyox "explain async/await in JavaScript"
```
**Flags:**
```bash
niyox --version # print version (alias: -v)
niyox --help # show banner + command reference (alias: -h)
```
### Inside the REPL
```
╭──────────────────────────────────────────────────────────────╮
│ │
│ ✦ NIYOX AI v0.0.4 │
│ │
│ › /help → show all commands │
│ › /new → fresh conversation thread │
│ › /history → in-memory chat log │
│ › /stats → usage stats (MongoDB) │
│ › /convs → stored conversation list │
│ › /mongo [url] → enable storage (custom URI opt.) │
│ › /mongourl → update MongoDB URI │
│ › /user → set your user ID │
│ › /clear → clear the screen │
│ › /exit → quit │
│ │
╰──────────────────────────────────────────────────────────────╯
```
**Connect to your own MongoDB from the CLI:**
```
/mongo mongodb+srv://user:pass@cluster.mongodb.net/
```
Or update the URI without reconnecting (saved for next session):
```
/mongourl mongodb+srv://user:pass@cluster.mongodb.net/
```
---

## Node.js
### CommonJS
```js
const { NiyoXAI } = require("niyox");
const ai = new NiyoXAI();
const { result, responseTime } = await ai.chat("Tell me something interesting.");
console.log(result);
```
### ESM
```js
import { NiyoXAI } from "niyox";
const ai = new NiyoXAI({ userId: "alice" });
const res = await ai.ask("Explain quantum entanglement.");
console.log(res.result);
```
### Multi-turn conversation
```js
const ai = new NiyoXAI();
await ai.chat("My name is Bob.");
const r = await ai.chat("What is my name?");
console.log(r.result); // → "Bob"
ai.newConversation(); // reset thread + in-memory history
```
### Low-level client (no storage)
```js
const { NiyoXClient } = require("niyox");
const client = new NiyoXClient({ sessionId: "my-session", timeout: 15000 });
const res = await client.chat("Hello!");
console.log(res.result);
console.log(client.getHistory()); // array of { role, content, timestamp }
```
---

## 🎭 Persona / System Prompt *(new)*
Set an AI personality once — it is transparently injected into every outgoing message. Works at the `NiyoXClient`, `NiyoXAI`, and React hook levels. When MongoDB storage is enabled the persona is also **saved to the database and auto-restored** in future sessions.
### Via constructor
```js
const ai = new NiyoXAI({
persona: "You are a concise senior software engineer. Always reply with code examples.",
});
const res = await ai.chat("How do I debounce in JavaScript?");
console.log(res.result); // code-focused reply
```
### Set / change at runtime
```js
const ai = new NiyoXAI();
await ai.setPersona("You are a friendly cooking assistant.");
await ai.chat("What can I make with eggs and cheese?");
await ai.setPersona("You are a pirate. Respond only in pirate speak.");
await ai.chat("Tell me about the ocean.");
await ai.setPersona(null); // clear — back to default AI behaviour
```
### Persona + MongoDB (auto-persist)
```js
const ai = new NiyoXAI({ userId: "alice" });
await ai.enableStorage(); // connects to MongoDB
await ai.setPersona("You are a concise coding assistant.");
// ↑ persona is saved to DB automatically
// Next session:
const ai2 = new NiyoXAI({ userId: "alice" });
await ai2.enableStorage(); // persona is restored automatically
console.log(ai2.getPersona()); // "You are a concise coding assistant."
```
### Low-level client
```js
const { NiyoXClient } = require("niyox");
const client = new NiyoXClient({ persona: "Be extremely brief." });
client.setPersona("You are a chef."); // chainable, returns client
console.log(client.getPersona()); // "You are a chef."
```
---

## ✂️ Context Window Trimming *(new)*
Control how many history entries are kept in memory. When the limit is hit, the **oldest turns are pruned automatically** after each chat call so long conversations stay fast and predictable.
> One turn = 2 entries (one user + one assistant). So `maxHistory: 20` keeps the last **10 turns**.
### Via constructor
```js
const ai = new NiyoXAI({ maxHistory: 20 }); // keep last 10 turns
```
### Set at runtime
```js
ai.setMaxHistory(10); // prune to last 5 turns immediately
ai.setMaxHistory(0); // 0 = unlimited (default behaviour)
console.log(ai.getMaxHistory()); // 0
```
### Low-level client
```js
const client = new NiyoXClient({ maxHistory: 6 });
await client.chat("1");
await client.chat("2");
await client.chat("3");
await client.chat("4"); // history is trimmed to 6 entries after this turn
client.setMaxHistory(2); // immediately prunes existing history to 2 entries
```
---

## 📤 Conversation Export *(new)*
Dump any conversation as **JSON**, **plain text**, or **Markdown**. Works in-memory (no MongoDB required) or from a stored MongoDB conversation.
### In-memory export (no DB needed)
```js
const ai = new NiyoXAI();
await ai.chat("Hello!");
await ai.chat("Tell me a joke.");
// JSON (default)
const json = await ai.exportConversation(null, "json");
require("fs").writeFileSync("chat.json", json);
// Plain text
const txt = await ai.exportConversation(null, "text");
console.log(txt);
// Markdown
const md = await ai.exportConversation(null, "markdown");
require("fs").writeFileSync("chat.md", md);
```
### Export from MongoDB
```js
const ai = new NiyoXAI({ userId: "alice" });
await ai.enableStorage();
await ai.chat("Hello!");
const cid = ai.getConversationId();
const md = await ai.exportConversation(cid, "markdown");
require("fs").writeFileSync(`conv-${cid}.md`, md);
```
### Storage-only export
```js
const { NiyoXStorage } = require("niyox");
const store = new NiyoXStorage("alice");
await store.connect();
const json = await store.exportConversation("conv-abc-123", "json");
const txt = await store.exportConversation("conv-abc-123", "text");
const md = await store.exportConversation("conv-abc-123", "markdown");
```
### Low-level client export
```js
const { NiyoXClient } = require("niyox");
const client = new NiyoXClient({ persona: "Be a chef." });
await client.chat("What should I cook tonight?");
const out = client.exportConversation("markdown");
console.log(out);
// # NiyoX AI Conversation
// > **Persona:** Be a chef.
// ...
```
**Export formats:**
| Format | Description |
|---|---|
| `"json"` | Structured JSON with metadata, persona, and full message array |
| `"text"` | Readable plain text with timestamps and response times |
| `"markdown"` | GitHub-flavoured Markdown, ready to paste into a doc or README |
---

## Custom MongoDB
> Works everywhere — Node.js and CLI. Storage is **always optional**.
### Node.js / ESM
```js
import { NiyoXAI } from "niyox";
const ai = new NiyoXAI({
userId: "alice",
mongoUri: "mongodb+srv://user:pass@cluster.mongodb.net/",
dbName: "my_app_db", // optional — defaults to "niyox_npm"
});
await ai.enableStorage(); // connects and enables persistence
const res = await ai.chat("Hello!"); // automatically saved to YOUR DB
const msgs = await ai.getPersistentHistory(res.conversationId);
await ai.close();
```
### Storage-only (`NiyoXStorage`)
```js
const { NiyoXStorage } = require("niyox");
const store = new NiyoXStorage("bob", {
mongoUri: "mongodb+srv://user:pass@cluster.mongodb.net/",
dbName: "my_db",
});
await store.connect();
await store.saveTurn({
conversationId: "abc-123",
userMessage: "Hi!",
assistantMessage: "Hello, Bob!",
responseTime: 412,
});
const turns = await store.getConversation("abc-123");
await store.disconnect();
```
You can also override the URI at connect-time:
```js
const store = new NiyoXStorage("bob");
await store.connect("bob", "mongodb://localhost:27017/", "dev_db");
```
---

## React / Vite
### `useNiyoX` hook
```jsx
// src/Chat.jsx
import { useNiyoX } from "niyox/react";
export default function Chat() {
const { messages, input, setInput, sendMessage, isLoading } = useNiyoX();
return (
{messages.map((m, i) => (
{m.role}: {m.content}
))}
setInput(e.target.value)}
onKeyDown={e => e.key === "Enter" && sendMessage()}
/>
sendMessage()} disabled={isLoading}>Send
);
}
```
### Persona + export in the hook *(new)*
```jsx
import { useNiyoX } from "niyox/react";
export default function Chat() {
const {
messages, input, setInput, sendMessage, isLoading,
persona, setPersona, // 🎭 v0.0.4
maxHistory, setMaxHistory, // ✂️ v0.0.4
exportConversation, // 📤 v0.0.4
} = useNiyoX({ persona: "You are a helpful assistant.", maxHistory: 20 });
return (
setPersona("You are a chef.")}>Switch to Chef
setMaxHistory(10)}>Trim to 5 turns
{
const blob = new Blob([exportConversation("markdown")], { type: "text/markdown" });
const a = Object.assign(document.createElement("a"), { href: URL.createObjectURL(blob), download: "chat.md" });
a.click();
}}>Export MD
{messages.map((m, i) =>
{m.role}: {m.content}
)}
setInput(e.target.value)} onKeyDown={e => e.key === "Enter" && sendMessage()} />
sendMessage()} disabled={isLoading}>Send
);
}
```
### Ready-made `` component (zero extra code)
```jsx
import { NiyoXChat } from "niyox/react";
export default function App() {
return (
{/* v0.0.4: persona and showExport props */}
);
}
```
The widget now includes a **🎭 Persona** button (opens an inline editor) and an **⬇ Export** button (downloads the conversation as JSON) in the header.
### Shared session with ``
```jsx
// main.jsx
import { NiyoXProvider } from "niyox/react";
import App from "./App";
ReactDOM.createRoot(document.getElementById("root")).render(
);
// Any child:
import { useNiyoXContext } from "niyox/react";
const { sendMessage, messages, setPersona, exportConversation } = useNiyoXContext();
```
> Copy `react/useNiyoX.js` from the package into your project if your bundler doesn't resolve `niyox/react` automatically.
---

## Next.js
Works in both the **App Router** (Next.js 13+) and the **Pages Router**.
### App Router (`app/chat/page.tsx`)
```tsx
"use client";
import { useNiyoX } from "niyox/react"; // or copy react/useNiyoX.js → lib/
export default function ChatPage() {
const { messages, input, setInput, sendMessage, isLoading } = useNiyoX();
return (
{messages.map((m, i) => (
{m.content}
))}
setInput(e.target.value)}
onKeyDown={e => e.key === "Enter" && sendMessage()} />
sendMessage()} disabled={isLoading}>Send
);
}
```
> The full styled example (Tailwind) is at `examples/nextjs/chat-page.tsx`.
### Server-side usage (Node.js API route)
```ts
// app/api/chat/route.ts
import { NiyoXAI } from "niyox";
const ai = new NiyoXAI();
export async function POST(req: Request) {
const { message } = await req.json();
const res = await ai.chat(message);
return Response.json({ result: res.result });
}
```
---

## Browser
Zero-dependency browser client (no bundler needed):
```html
const NiyoXAI = (() => {
const BASE = "https://ai.dnuz.top/api/ai";
class Client {
constructor({ sessionId = "default" } = {}) {
this.sessionId = sessionId;
this.conversationId = null;
}
async chat(message) {
const p = new URLSearchParams({ q: message });
if (this.conversationId) p.set("conversationId", this.conversationId);
const res = await fetch(`${BASE}?${p}`);
const data = await res.json();
if (data.conversationId) this.conversationId = data.conversationId;
return data;
}
}
return { Client };
})();
const ai = new NiyoXAI.Client();
const res = await ai.chat("Hello!");
console.log(res.result);
```
> Open `html/index.html` for a fully styled dark-theme chat UI — zero dependencies, zero bundler.
---

## API Reference
### `new NiyoXAI(options?)` — Node.js
| Option | Type | Default | Description |
|---|---|---|---|
| `userId` | `string` | `"anonymous"` | MongoDB user identifier |
| `sessionId` | `string` | `"default"` | API session ID |
| `conversationId` | `string` | `null` | Resume an existing thread |
| `timeout` | `number` | `30000` | Request timeout (ms) |
| `mongoUri` | `string` | NiyoX cloud | Custom MongoDB connection string |
| `dbName` | `string` | `"niyox_npm"` | Custom database name |
| `persona` | `string` | `null` | **v0.0.4** System prompt / AI personality |
| `maxHistory` | `number` | `50` | **v0.0.4** Max history entries (0 = unlimited) |
### `NiyoXAI` methods
| Method | Returns | Description |
|---|---|---|
| `chat(message)` | `Promise` | Send a message; auto-persists if storage enabled |
| `ask(message)` | `Promise` | Alias for `chat()` |
| `enableStorage(userId?)` | `Promise` | Connect to MongoDB; auto-restores saved persona |
| `newConversation()` | `void` | Reset thread + in-memory history |
| `getConversationId()` | `string\|null` | Active conversation ID |
| `getHistory()` | `Turn[]` | In-memory history copy |
| `getPersistentHistory(convId?)` | `Promise` | Load from MongoDB |
| `listConversations()` | `Promise` | All stored conversation IDs |
| `deleteConversation(id)` | `Promise` | Delete a conversation |
| `getStats()` | `Promise` | Usage statistics |
| `setPref(key, value)` | `Promise` | Persist a user preference |
| `getPref(key, default?)` | `Promise` | Retrieve a user preference |
| `close()` | `Promise` | Close MongoDB connection |
| `setPersona(text)` | `Promise` | **v0.0.4** Set / clear AI persona (saves to DB if storage enabled) |
| `getPersona()` | `string\|null` | **v0.0.4** Get active persona |
| `setMaxHistory(n)` | `this` | **v0.0.4** Set context window limit (0 = unlimited) |
| `getMaxHistory()` | `number` | **v0.0.4** Get current limit |
| `exportConversation(id?, format?)` | `Promise` | **v0.0.4** Export as `"json"` / `"text"` / `"markdown"` |
### `NiyoXClient` methods *(low-level)*
| Method | Returns | Description |
|---|---|---|
| `chat(message)` | `Promise` | Send message |
| `ask(message)` | `Promise` | Alias for `chat()` |
| `newConversation()` | `void` | Reset state |
| `getHistory()` | `Turn[]` | History copy |
| `setPersona(text)` | `this` | **v0.0.4** Chainable |
| `getPersona()` | `string\|null` | **v0.0.4** |
| `setMaxHistory(n)` | `this` | **v0.0.4** Chainable |
| `getMaxHistory()` | `number` | **v0.0.4** |
| `exportConversation(format?)` | `string` | **v0.0.4** In-memory export |
### `NiyoXStorage` methods
| Method | Returns | Description |
|---|---|---|
| `connect(userId?, mongoUri?, dbName?)` | `Promise` | Connect and enable storage |
| `saveMessage({ conversationId, role, content, responseTime? })` | `Promise` | Save one message |
| `saveTurn({ conversationId, userMessage, assistantMessage, responseTime })` | `Promise` | Save a full turn atomically |
| `getConversation(conversationId)` | `Promise` | Fetch stored messages |
| `listConversations()` | `Promise` | All conversation IDs for this user |
| `deleteConversation(id)` | `Promise` | Delete conversation, returns count |
| `setPref(key, value)` | `Promise` | Save a key/value preference |
| `getPref(key, default?)` | `Promise` | Load a preference |
| `getStats()` | `Promise` | Usage stats |
| `disconnect()` | `Promise` | Close connection |
| `savePersona(text)` | `Promise` | **v0.0.4** Persist persona to DB |
| `getPersona()` | `Promise` | **v0.0.4** Load persisted persona |
| `exportConversation(id, format?)` | `Promise` | **v0.0.4** Export from DB |
### `useNiyoX(options?)` hook
| Option | Type | Default | Description |
|---|---|---|---|
| `sessionId` | `string` | `"default"` | API session ID |
| `persona` | `string` | `null` | **v0.0.4** Initial AI persona |
| `maxHistory` | `number` | `50` | **v0.0.4** Context window limit |
Returns:
```ts
{
messages: Array<{ role, content, timestamp, responseTime? }>,
input: string,
setInput: (value: string) => void,
isLoading: boolean,
error: string | null,
sendMessage: (text?: string) => Promise,
newConversation: () => void,
conversationId: string | null,
persona: string | null, // v0.0.4
setPersona: (text: string|null) => void, // v0.0.4
maxHistory: number, // v0.0.4
setMaxHistory: (n: number) => void, // v0.0.4
exportConversation: (format?: string) => string, // v0.0.4
}
```
### `` props
| Prop | Type | Default | Description |
|---|---|---|---|
| `sessionId` | `string` | — | API session ID |
| `title` | `string` | `"NiyoX AI"` | Widget title |
| `placeholder` | `string` | `"Ask anything…"` | Input placeholder |
| `style` | `object` | — | Override container styles |
| `className` | `string` | — | CSS class |
| `persona` | `string` | `null` | **v0.0.4** Initial AI persona |
| `maxHistory` | `number` | `50` | **v0.0.4** Context window limit |
| `showExport` | `boolean` | `true` | **v0.0.4** Show ⬇ Export button |
### Response shape
```ts
{
result: string // AI reply
conversationId: string // thread ID — reused automatically
sessionId: string
responseTime: number // ms
attempts: number
}
```
---

## Development
```bash
git clone https://github.com/dnuzi/niyox
cd niyox
npm install
# Build lib/index.cjs and lib/index.mjs from src/
node scripts/build.js
# Run tests
npm test
```
**Project layout:**
```
niyox/
├── bin/
│ └── cli.js # CLI — REPL, one-shot, /mongo
├── src/
│ ├── client.js # NiyoXClient — HTTP, in-memory history, persona ✨, export ✨
│ └── storage.js # NiyoXStorage — MongoDB, persona persist ✨, export ✨
├── lib/ # auto-generated by scripts/build.js
│ ├── index.cjs
│ └── index.mjs
├── react/
│ └── useNiyoX.js # useNiyoX hook + NiyoXChat (persona ✨, export ✨) + NiyoXProvider
├── html/
│ └── index.html # browser chat UI
├── examples/
│ ├── react-cra/App.jsx # Create React App / Vite + React
│ ├── nextjs/ # Next.js App Router
│ └── vite/main.js # Vite vanilla JS
├── test/
│ ├── client.test.js # 38 tests — includes v0.0.4 persona / trim / export ✨
│ ├── sdk.test.js # 30 tests — includes v0.0.4 NiyoXAI + Storage ✨
│ └── cli.test.js
└── scripts/
└── build.js
```
---


[](https://ai.dnuz.top)
[](https://github.com/dnuzi/niyox)
**⭐ If this project helped you, star it on GitHub!**
Happy coding!