@exellix/narrix-adapter-chat
v2.0.0
Published
Chat thread to CNI v1.1 adapter (byMessage / byLength)
Readme
@exellix/narrix-adapter-chat
Convert chat threads to CNI v1.1 deterministically. Adapter is translator-only: facts: [], signals: [].
- Default: one content item per message (
byMessage) - Optional: merge then chunk (
byLength) with configurable separator (default\n---\n) - Truncation: drop whole messages from the end when
maxTotalCharsis exceeded - Subject ID: from
threadIdwhen present, otherwisesha256(stableStringify(fingerprint))
Install
From GitHub (private):
npm install git+https://github.com/exellix/narrix-adapters-chat.gitOr with GitHub Packages (after publish):
npm install @exellix/narrix-adapter-chatUsage
import { toCni } from "@exellix/narrix-adapter-chat";
import type { ChatThread, ChatAdapterOptions } from "@exellix/narrix-adapter-chat";
const thread: ChatThread = {
threadId: "conv-1",
title: "Support",
messages: [
{ role: "user", text: "Hello", ts: Date.now() },
{ role: "assistant", text: "Hi there!", ts: Date.now() },
],
};
const options: Partial<ChatAdapterOptions> = {
chat: { strategy: "byMessage" },
};
const { cni, diagnostics } = toCni(thread, options);Options
chat.strategy:"byMessage"(default) or"byLength"chat.maxTotalChars: truncate by dropping whole messages from the endchat.separator: separator between messages in byLength (default"\n---\n")chat.maxChunkChars/chat.overlapChars: chunking when using byLength
Build & test
npm install
npm run build
npm testGolden tests (C1–C6) use fixture files under test/fixtures/:
case-CN.input.json— input threadcase-CN.options.json— optional adapter optionscase-CN.expected.json— full expected result (cni+diagnostics)
Each test runs toCni(input, options) and asserts deepStrictEqual against the expected JSON. All IDs/hashes are precomputed in the expected files.
| Case | Description |
|------|-------------|
| C1 | Simple 2-message thread (CVE text); CHAT_NO_TIMESTAMPS when no ts |
| C2 | Message ids and timestamps; entities (IP, hostname); contentId from subjectId\|msgId |
| C3 | No threadId; subject.id = sha256(stableStringify fingerprint); CHAT_NO_THREAD_ID, CHAT_NO_TIMESTAMPS |
| C4 | Empty messages; content [], CHAT_EMPTY_MESSAGES |
| C5 | byLength merge chunking (6×800 chars); ~3 chunks, kind chunk, path merged |
| C6 | Truncation (maxTotalChars 100); 1 message kept, CHAT_TRUNCATED |
To regenerate expected files after intentional adapter changes: node test/generate-expected.js
Publish (private GitHub Packages)
.npmrc is not in the repo (gitignored). Create it locally with:
@exellix:registry=https://npm.pkg.github.com
//npm.pkg.github.com/:_authToken=YOUR_TOKENThen:
npm run build
npm publishLicense
UNLICENSED (private)
