@chamvi/chat

中文文档
0.8.0发布于 2026/11/09Apache-2.0TypeScriptES Module构建来源已验证近 30 天下载 1866

查查特务的SDK频道.

中文使用文档
文档目录11 节
  1. 安装
  2. 使用量
  3. 网络呼号
  4. 平台软件包
  5. 订阅和答复
  6. 内存
  7. 信托
  8. 限制
  9. 使用@ chamvi/ app
  10. API 密码
  11. 许可证

@chamvi/chat

@chamvi/聊天

Chamvi探员的聊天频道.
聊天SDK适配器开始运行,通过一个通道得到回复,
和平台软件包通过公共接缝插入.

npm version CI License


目录

安装

npm install @chamvi/chat @chamvi/core @chamvi/http chat --save

仅限无害环境管理,节点.js >=26.0.0。 。 。 . @chamvi/core, (中文(简体) ), @chamvi/http (网络浏览器)和 chat (Chat SDK,4.44或后在 4.x行)是同位相依性; smob 是唯一的运行时间依赖. @chamvi/app 是可选的对等点 @chamvi/chat/module。软件包没有导入 SDK:WhatsApp Web 的平台 @chamvi/chat-whatsapp。 。 。 .

条目持有
@chamvi/chatchatChannel(), (中文(简体) ), createChatIngressAdapter(), (中文(简体) ), chat.on()编号 :chat.to(),平台连接 IChatPlatform,限制和错误代码
@chamvi/chat/modulechatModule(),它为预建的信道提供了一个 @chamvi/app 应用

使用量

任意聊天 SDK Adapter 通过频道工作。 包起来 createChatIngressAdapter() 在登记之前 Chat,所以Chamvi的收录,而不是SDK的处理器和预处理器分解,接受它的信息;频道拥有 Chat 一个人 在引擎上注册频道, 订阅代理 channel.on() 并用工具回复 ctx.channels.findOneOrFail('chat').emit()数字 :

import type { LanguageModel } from 'ai';
import { z } from 'zod';
import { Chat } from 'chat';
import type { Adapter, StateAdapter } from 'chat';
import {
    Engine,
    createMemoryStore,
    defineModelAgent,
    defineTool,
} from '@chamvi/core';
import type { IClock, IEngine } from '@chamvi/core';
import { chatChannel, createChatIngressAdapter } from '@chamvi/chat';

export function createChatEngine(
    model: LanguageModel,
    // adapter: any Chat SDK adapter whose platform posts webhooks; state: a Chat SDK state adapter
    options: {
        adapter: Adapter;
        state: StateAdapter;
        clock?: IClock
    },
): IEngine {
    const { CHAT_USERS, APP_URL } = process.env;

    if (!CHAT_USERS || !APP_URL) {
        throw new Error('Set CHAT_USERS (platform user ids, comma separated) and APP_URL.');
    }

    const allowed = new Set(CHAT_USERS.split(','));

    // chamvi's intake, not the Chat SDK's handlers, accepts the adapter's messages
    const ingress = createChatIngressAdapter(options.adapter);
    const chat = new Chat({
        userName: 'chamvi',
        adapters: { [ingress.name]: ingress },
        state: options.state,
        logger: 'warn',
        concurrency: 'concurrent',
    });

    const channel = chatChannel({
        chat,
        adapters: [ingress],
        // the platform posts to POST /channels/chat/<adapter> (the http app's channel mount)
        webhooks: [ingress.name],
        // only these users start runs; everybody else is ignored
        allowMessage: ({ message }) => allowed.has(message.author.userId),
        resolveInvoker: ({ message }) => ({
            id: message.author.userId,
            kind: 'chat',
            permissions: [],
        }),
        // a link to the approval in the chamvi UI: ids only, answered there
        approvalUrl: ({ runId, approvalId }) => `${APP_URL}/ui/approvals?run=${encodeURIComponent(runId)}&approval=${encodeURIComponent(approvalId)}`,
    });

    const reply = defineTool({
        description: 'Reply in the chat the message came from.',
        inputSchema: z.object({ text: z.string() }),
        execute: async ({ text }, { context }) => {
            // the source chat: no address needed
            await context.channels.findOneOrFail('chat').emit({ body: text });

            return 'sent';
        },
    });

    const assistant = defineModelAgent({
        name: 'assistant',
        model,
        instructions: 'You are the team\'s assistant. Answer with the reply tool.',
        // one memory per direct chat and one per group
        conversation: true,
        // direct messages and mentions in a group
        channels: [channel.on()],
        tools: { reply },
    });

    return new Engine({
        // memory store: conversations included; use @chamvi/store-db in production
        store: createMemoryStore({ clock: options.clock }),
        agents: [assistant],
        channels: [channel],
        clock: options.clock,
        conversations: { authorize: ({ agent }) => agent === 'assistant' },
    });
}

频道建成时没有初始化:频道的 start (引擎)绑定适配器,初始化 Chat,然后打电话 connect。 。 。 . allowMessage 要求每个适配器(可启动运行); resolveInvoker 命名运行的引用者( 无默认) ; connect编号 :disconnect 将套接字式的适配器接入频道的起动和停止. 消息只在 allowMessage 允许它; 拒绝的消息被悄悄地删除: 没有运行, 没有回复, 没有下载。 通用的webhook适配器仅被假适配器的测试所覆盖: chamvi除了WhatsApp Web之外没有验证过任何平台.

网络呼号

一个网点适配器的平台帖子 POST /channels/<channel>/<adapter> ( http app 的频道挂载; 仅列出在 webhooks,任何其它404个。 身体被读取到 CHAT_BODY_LIMIT_BYTES (一米B,上面有413个) 交给适配器自己 handleWebhook以核实请求。 答案将等到适配器移交的每个消息都作为运行存储(最多) CHAT_WEBHOOK_TIMEOUT_MS, 30 s)),并且是一个503,当一个人不能因为某种原因重新交付可能会被修复(存储失败,频道没有启动或停止,超时),所以平台被重新删除. 一个消息只被拒绝(媒体,没有文本,无效的ID,拒绝的谈话,扔出过滤器)一次被报告,并得到了适配器自己的答案,因为重新发送会被再次拒绝. 获取挑战流量没有服务。 只有适配器在请求的同声上下文中交接的信息才会被跟踪:一个将信息传递给在它之外开始的消费者的适配器(一个队列,一个请求前的收听器)不会被等待,它自己的2xx站. 除非 channelRateLimits 命名频道.

平台软件包

平台软件包( 如 @chamvi/chat-whatsapp建立其 Chat,其包裹适配器和一个 chatChannel() 喜欢任何应用,通过 只有运输知道 platform (单位:千美元)IChatPlatform,每个钩子可选并呼叫平台对象:

钩子运行答复
online()每发件, 之后 prepare,仅在频道启动时虚假拒绝发送( f)chat_request; 默认为真实
prepare({ adapter, threadId, text, key })每发件,在地址解码和发送信件之后,在 online投出时拒绝目标(其错误如是);否则 (signal) => Promise 频道通话一次,以 timeoutMs 和发送信号(失败 a) chat_request页:1 signal 以先来者为准中止,所以平台可以取消其请求; key 是消息密钥,所以传输可以获得稳定的消息ID. 默认适配器 postMessage(threadId, { raw: text })
conversationTarget(incoming, payload)每个代理人 conversation之后 allowMessage,文本检查和 resolveInvoker对话身份; 未定义拒绝该代理( q)chat_intake_failed),一个投出失败的消息。 从有效载荷默认

频道在施工时检查平台(InvalidAgentDefinitionError 对于一个非对象,一个没有功能的钩子,或者一个没有钩子的普通对象. 它的套接字寿命周期与 connect编号 :disconnect,其信息政策与 allowMessage编号 :resolveInvoker。 。 。 .

订阅和答复

channel.on({ adapter?, events?, id?, filter?, concurrencyMaxRuns? }) 订阅代理; events 为: direct (直接聊天), mention (一组中提及的机器人)和 message (任何其他组消息),默认 ['direct', 'mention']。 。 。 . chat.on() 对命名的频道进行同样的修改 chat运行的有效载荷是很小的 ChatPayload (单位:千美元)adapter, (中文(简体) ), event, (中文(简体) ), threadId, (中文(简体) ), channelId, (中文(简体) ), message: { id, text, author, sentAt? }),从来不是平台的原始对象;其地址是聊天,所以工具的 emit() 没有地址回复. channel.to({ adapter, threadId }) 构建另一个聊天地址 .

一旦每个代理商(偶当键的散列通道、适配器、线程、发送器和消息ID)接受消息,就不再进行第二次发送;瞬态商店故障将重复两次(1 s, 2 s),然后报告为 chat_intake_failed。 。 。 .

核准ctx.channels.findOneOrFail('chat').approve()发送带有标题、正文(切合)、选项和 approvalUrl 链接( c)Approve or deny: <link>选项 Choose and approve or deny: <link>; 车主在chamvi UI中回答. 链接只携带ID;没有本地按钮,聊天中的回覆不回答批准.

内存

一个特工与 conversation: true 每个聊天通过核心获得一个内存 对话记忆:信道通过引擎的可信赖的谈话收录,从不通过有效载荷场来绑定每个消息. 它需要一个商店 conversations (单位:千美元)createMemoryStore() 或者说 @chamvi/store-db和发动机的 conversations: { authorize } (单位:千美元)createApp({ conversations })) (中文(简体) ). 身份是频道 account 别名、聊天和观众: direct:<sender> 直接聊天, group:<channel id> 对于一个集团,所以一个集团在其成员之间共享一个记忆. 被接受的消息文本和向源聊天发送的答复被记住; history: 0 是唯一的设置( 没有获取平台历史) 。 一个平台软件包可以命名自己的身份(IChatPlatform.conversationTarget) (中文(简体) ).

信托

每次运行聊天频道启动都会被污染(untrusted: true 默认; false 仅用于完全信任的私人部署),所以工具分类 guardWhenTainted 要求批准(或被拒绝)。 消息源聊天的回覆可以免去出入口;发送到另一个聊天的回覆通过. 一个配置 defaultAddress 也可以免责:它是一个被污染的跑道的通水槽,所以没有一条是默认的.

限制

  • 只有文本:拒绝发送带有附件或没有文本的信息(报告,不运行)。 无媒体下载.
  • 无历史history: 0),没有消息分割:上面的信息 maxTextChars (默认) CHAT_TEXT_MAX_CHARS, 4096 UTF-16 代码单位)被拒绝;批准只削减其通用语.
  • ChannelMessage.slot 被忽略 : 每个消息都是新的聊天消息 .
  • 发送至少一次:发送方为 timeoutMs (默认) CHAT_TIMEOUT_MS, 30 s); 发送时段仍可发送, 重试时可能再次发送。 频道停止或耗尽时发送失败 .

使用@ chamvi/ app

import { createApp } from '@chamvi/app';
import { chatChannel } from '@chamvi/chat';
import { chatModule } from '@chamvi/chat/module';

const channel = chatChannel({ ... });

export default createApp({
    agents: [assistant],
    modules: [chatModule({ channel })],
    conversations: { authorize: ({ agent }) => agent === 'assistant' },
});

chatModule() 将频道输入 AppToken.CHANNELS (单元名称) chamvi:channel:<name>); 引擎开始并停止它, 和 http 模块挂载它 in 当它服务于网络用户。 它没有增加嵌入变量 并且构造什么,所以 chamvi start --check 没有初始化 Chat 也没有连接.

API 密码

导出条目
chatChannel(options), (中文(简体) ), createChatIngressAdapter(adapter), (中文(简体) ), chat, (中文(简体) ), chatAddress(), (中文(简体) ), createChatSubscription()@chamvi/chat
类型 ChatChannelOptions, (中文(简体) ), ChatChannel, (中文(简体) ), ChatPayload, (中文(简体) ), ChatEvent, (中文(简体) ), ChatIncoming, (中文(简体) ), ChatIngress, (中文(简体) ), ChatApprovalRef, (中文(简体) ), IChatPlatform, (中文(简体) ), ChatPlatformSend, (中文(简体) ), ChatPlatformPost@chamvi/chat
CHAT_CHANNEL_NAME 'chat', (中文(简体) ), CHAT_TEXT_MAX_CHARS 4096号, CHAT_TIMEOUT_MS 3万块, CHAT_BODY_LIMIT_BYTES 1个小贝, CHAT_WEBHOOK_TIMEOUT_MS 3万块, CHAT_STOP_TIMEOUT_MS 3万块, CHAT_EVENTS, (中文(简体) ), DEFAULT_CHAT_EVENTS, (中文(简体) ), CHAT_ADDRESS_PREFIX@chamvi/chat
错误代码 chat_request, (中文(简体) ), chat_intake_failed, (中文(简体) ), chat_stop_timeout (单位:千美元)CHAT_*_ERROR_CODE(中文(简体) )@chamvi/chat
chatModule(options), (中文(简体) ), ChatModule@chamvi/chat/module

整个选项参考是 聊天参考。 。 。 .

许可证

由 所制

原载 Apache 许可证 2.0。 。 。 .

版本与发布记录

@chamvi/chat 共发布 10 个版本,首次发布于 2026/11/02;过去 12 个月发布了 10 个版本。最新版本附带 npm provenance 构建来源证明,可追溯到公开的 CI 构建记录。

版本发布日期距今
0.8.0latest2026/11/09今天
0.7.32026/11/064 天前
0.7.22026/11/054 天前
0.7.12026/11/055 天前
0.7.02026/11/045 天前
0.6.12026/11/045 天前

关于 @chamvi/chat 的常见问题

@chamvi/chat 是什么?

查查特务的SDK频道.

如何安装 @chamvi/chat?

在项目目录运行 npm install @chamvi/chat,或使用 pnpm add / yarn add / bun add。它还需要宿主项目提供 peer 依赖:chat(^4.44.0)、@chamvi/core(^0.8.0)、@chamvi/http(^0.8.0)。npm 7 及以上与 pnpm 8 及以上默认会自动安装必需的 peer 依赖,Yarn 需要手动安装。

@chamvi/chat 支持 TypeScript 吗?

支持。包内自带 TypeScript 类型声明(package.json 声明了 types 入口),安装后即可获得类型提示,无需再安装 @types 包。

@chamvi/chat 支持 ESM 还是 CommonJS?

以 ES Module 形式发布,推荐使用 import 引入。在 CommonJS 项目中,Node.js 20.19+ / 22.12+ 可以直接 require() 不含顶层 await 的 ES Module,更早的版本需要改用动态 import()。

@chamvi/chat 需要什么版本的 Node.js?

package.json 的 engines 字段要求 Node.js >=26.0.0。版本不符时 npm 默认只给出警告,开启 engine-strict 后会拒绝安装。

@chamvi/chat 可以商用吗?

@chamvi/chat 使用 Apache-2.0 许可。宽松许可:允许商业使用、修改和再分发,并附带明确的专利授权;分发时需保留许可与 NOTICE 文件,修改过的文件要注明改动。以上为概括,不构成法律意见,请以许可原文为准。

@chamvi/chat 的下载量有多少?

根据 npm 官方下载统计,@chamvi/chat 在 2026/10/10 – 2026/11/08 这 30 天内被下载 1,866 次,日均约 62 次。下载量会把 CI 构建、镜像同步和作为其他包依赖的安装一并计入,适合横向比较热度,不能直接等同于使用人数。

@chamvi/chat 还在维护吗?

最新版本 0.8.0 发布于 2026/11/09(今天);至今共发布 10 个版本,其中过去 12 个月发布了 10 个;首次发布于 2026/11/02。发布频率只是参考信号:功能稳定的工具可能很少需要更新,建议结合源码仓库的 issue 和提交记录判断。