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

@mmteam/jsllm

v0.1.14

Published

MM Team LLM library (providers + chat/session runner)

Downloads

664

Readme

@mmteam/jsllm

独立的 LLM 能力库:封装多供应商差异(OpenAI 兼容、Gemini)与会话执行(含工具循环/落盘)。

发布形态:

  • 单文件运行时代码:dist/index.cjs(CommonJS,已 bundle 所有运行时依赖)
  • 单文件类型声明:dist/types.d.ts
  • 发布包零 dependencies(下游安装后无需额外安装 OpenAI/Gemini SDK 等依赖)

功能概览

  • 统一供应商:OpenAI 兼容 / Gemini
  • 统一会话:会话目录管理、消息落盘、历史恢复、usage 累计
  • 流式输出:stdout 输出回答;stderr 输出诊断与 think/reasoning(若模型提供)
  • 工具循环:内置 shell 工具(模型触发时在工作区执行命令,并回填输出)

安装

npm i @mmteam/jsllm

环境要求

  • Node.js >= 20

快速开始

CommonJS(推荐)

const path = require("node:path");
const { chatInSession } = require("@mmteam/jsllm");

async function main() {
  await chatInSession({
    init: {
      providerName: "openai",
      apiType: "openai",
      apiKey: process.env.OPENAI_API_KEY,
      model: "gpt-4o-mini",
      temperature: 0.7,
    },
    workspaceRoot: process.cwd(),
    sessionRootDir: path.join(process.cwd(), ".magicai/chat-sessions"),
    messageArg: "hello",
  });
}

main().catch((err) => {
  console.error(err);
  process.exitCode = 1;
});

输入规则:

  • 若提供 messageArg,使用其作为用户输入
  • 否则当 stdin 非 TTY 时读取 stdin;两者都没有则报错

ESM 项目中使用(可选)

本包对外导出为 CommonJS(require)。在纯 ESM 项目中可用 createRequire 引用:

import { createRequire } from "node:module";
const require = createRequire(import.meta.url);
const { chatDirectText } = require("@mmteam/jsllm");

API

对外仅导出 2 个函数(以及必要类型):

详细参数、类型与中文说明:请参考 node_modules/@mmteam/jsllm/dist/types.d.ts(本仓库构建产物对应 projects/jsllm/codex-zf/dist/types.d.ts)。

如何选择?

| 能力 | chatDirectText | chatInSession | |---|---|---| | 目标 | 单轮生成(返回文本) | 会话引擎(落盘 + 工具循环 + 流式输出) | | 输入 | 调用方提供 messages | messageArg 或 stdin;并自动加载会话历史 | | 输出 | Promise<string> | stdout 流式输出;会话文件落盘;stderr 输出诊断/think | | 工具 | 不启用、不执行 | 内置 shell(模型触发时执行并回填) | | 适用场景 | 摘要/改写/分类等一次性生成;你自管存储 | CLI/交互式场景;需要可追溯、可续写会话 |

chatDirectText(init, messages): Promise<string>

  • 用途:不落盘、不启用工具的“单轮文本生成”,返回最终聚合文本
  • 示例:
const { chatDirectText } = require("@mmteam/jsllm");
const text = await chatDirectText(
  {
    providerName: "gemini",
    apiType: "gemini",
    apiKey: process.env.GEMINI_API_KEY,
    model: "gemini-1.5-pro",
  },
  [
    { role: "user", content: "Summarize: ..." },
  ],
);
console.log(text);

chatInSession(options): Promise<void>

  • 用途:执行一次“CLI 式会话主循环”(会话落盘 + 流式输出 + 工具循环)
  • 重要参数:
    • workspaceRoot:工作区根目录(用于解析 public/agents,以及工具执行 cwd)
    • sessionRootDir:会话根目录(会在其下创建会话目录与 latest 软链)
    • systemPrompt:支持内联文本或 @ 引用文件/agent 名称(见下方说明)
    • consoleOutput:是否写入 stdout/stderr(默认 true
    • onEvent:实时输出回调(区分正常回复 text 与 think,并携带与落盘一致的文件名/路径)

供应商与配置

OpenAI 兼容(apiType: "openai"

init: {
  providerName: "openai", // 或 dashscope / 自建网关等;qwen* 见下
  apiType: "openai",
  apiKey: "...",
  baseUrl: "https://your-gateway.example.com", // 可选
  model: "gpt-4o-mini",
  temperature: 0.7,
}

Gemini(apiType: "gemini"

init: {
  providerName: "gemini",
  apiType: "gemini",
  apiKey: "...",
  baseUrl: "https://generativelanguage.googleapis.com", // 可选;仅代理/国内环境需要
  apiVersion: "v1beta", // 建议显式配置;预览模型推荐 v1beta
  model: "gemini-1.5-pro",
}
  • baseUrl:非必须;未配置时使用 SDK 默认地址
  • apiVersion:建议显式配置;预览模型常用 v1beta

qwen*(OpenAI 兼容扩展)

判断规则:providerNameqwen 前缀(不区分大小写)即视为 qwen 模式(如 qwen1qwen-local)。

thinking 参数:

  • 公共字段:thinking.enabledthinking.budgetTokens
  • qwen 私有字段:qwen.enable_thinkingqwen.thinking_budget(优先级高于公共字段)

示例:

init: {
  providerName: "qwen-local",
  apiType: "openai",
  apiKey: "...",
  baseUrl: "http://localhost:8000/v1",
  model: "qwen2.5",
  thinking: { enabled: true, budgetTokens: 2048 },
  qwen: { enable_thinking: true, thinking_budget: 2048 },
}

会话落盘说明(chatInSession

  • 会话根目录:由 sessionRootDir 指定
  • 会话目录:YYYYMMDD_HHMMSS/
  • latest:会话根目录下的软链,指向最近一次有效会话目录
  • usage.json:会话累计用量(当供应商返回 usage 时会自动累加)
  • 消息文件:按序号落盘,支持恢复历史继续会话
  • .think:当模型输出 reasoning/think 时,会额外落盘同名 .think 文件

实时回调(chatInSession.onEvent

你可以通过 onEvent 在应用侧接收流式输出,并区分正常回复与 think(事件中携带与落盘一致的文件名):

await chatInSession({
  /* ... */,
  consoleOutput: false,
  onEvent(e) {
    if (e.type === "assistant_text") {
      // e.textSoFar:当前轮累计的“正常回复”
    }
    if (e.type === "assistant_think") {
      // e.thinkSoFar:当前轮累计的 think/reasoning
    }
  },
});

多轮会话(chatInSession

chatInSession 的多轮能力通过“会话目录落盘 + 下次加载历史”实现:每次调用会读取目标会话目录的历史消息并继续追加写入。

  • 默认续写上一会话(推荐):多次调用时保持相同的 sessionRootDir,且不传 sessionArg,库会自动复用 latest 指向的会话目录。
  • 固定到指定会话:传入 sessionArg: "my-session"(相对 sessionRootDir 的相对子目录),每次调用都使用同一个值,即可稳定续写同一会话。
  • systemPrompt 建议:同一会话通常只在“第一轮”设置 systemPrompt;后续轮次不再传(或改用 sessionArg 固定会话),避免触发创建新会话导致上下文断裂。

systemPrompt / globalAgent(chatInSession

  • systemPrompt 支持两种形式:
    • 内联文本:直接传字符串
    • 引用文件/agent:以 @ 开头,例如 @公共智能体@./path/to/prompt.txt
  • 当引用的是名称(非绝对路径且不以 ./ 开头)时,会在 ${workspaceRoot}/public/agents/ 下查找,并允许省略 .agent.md 扩展名

环境变量

  • MCHAT_REQUEST_TIMEOUT_MS:OpenAI 兼容请求超时(毫秒)
  • MCHAT_DEBUG:Gemini provider debug 输出(true/1 开启)

安全说明(工具)

chatInSession 内置 shell 工具:当模型触发工具调用时,会在 workspaceRoot 下通过 bash -lc 执行命令并回填输出。请仅在可信环境中使用,并确保运行账号权限可控。

开发

下述为仓库开发者使用;下游项目不需要执行 build。

npm run build