# @cogitator-ai/test-utils 中文文档

规范地址：https://npmcn.com/package/%40cogitator-ai/test-utils/

版本：0\.15\.0
npm 元数据更新时间：2026-11-03T18:10:22.522Z
中文译文更新时间：2026-11-10T10:11:35.620Z
软件包许可：MIT

本文由上游 README 翻译，可能存在偏差，请结合原文核对 API、命令与配置。版权与许可归原作者所有。

原始 npm 页面：https://www.npmjs.com/package/%40cogitator-ai/test-utils
原文对照：https://npmcn.com/package/%40cogitator-ai/test-utils/?lang=original
源码仓库：https://github.com/cogitator-ai/Cogitator-AI

## 关键信息（来自 npm 元数据）

- 包体积（解压后）：235 kB，81 个文件
- 模块格式：ES Module
- TypeScript 类型：包内自带
- Node.js 要求：\>=22\.12\.0
- 运行依赖：2 个
- 首次发布：2026-01-26T17:00:32.381Z
- 最新版本发布：2026-11-03T18:10:22.237Z
- 近 30 天下载量：9585（2026-10-11 至 2026-11-09，npm 官方下载统计）
- 已发布版本数：79（近 12 个月 79 个）

## 中文简介

共享 Cogitator 包的测试工具

## 安装

```sh
npm install @cogitator-ai/test-utils
```

也可以使用：`pnpm add @cogitator-ai/test-utils`、`yarn add @cogitator-ai/test-utils`、`bun add @cogitator-ai/test-utils`

## README

# @cogitator-ai/ test-utils (英语)

测试 Cogitator 的公用设备, 以测试自己的代理、 工具、 工作流程和后端, 而无需调用真正的 LLM 或数据库 .

## 安装

```bash
pnpm add -D @cogitator-ai/test-utils
```

`@cogitator-ai/test-utils` 给您定型的站台和助手测试您的代理和应用程序,而不使用网络呼叫、付费的API密钥或外部数据库。 见 [测试工具](https://cogitator.app/docs/testing/test-utils) 在网站上.

## 特征

-   **锁定 LLM 后端** - 脚本 `MockLLMBackend` 确定性 `chat()` 答复和答复 `chatStream()` 附有请求记录和检查的块
-   **模拟记忆适应器** - 进行中 `MockMemoryAdapter` 记录方法调用线索和条目
-   **模拟嵌入服务** - 决定主义 `MockEmbeddingService`: 平稳的单位向量,来自一袋散列的单词,每个文本可标注,记录每个呼叫
-   **测试固定器** - 预配置代理、信息、工具呼叫、工具结果、JSON Schema工具以及运行结果
-   **串流帮助** - 排水和收集溪流内容、块和工具调用,或创建模拟字节流
-   **同步公用事业** - 投票(`waitFor`, (中文(简体) ), `eventually`延迟,和约期援助者
-   **后端合规套件** - 测试针对电线协议的自定义后端(OpenAI、Anthropic、双子座、Ollama、Bedrock) `startFakeProvider`
-   **内存符合要求** - 持有内存适配器、内存项目存储器、内存文件存储器和内存存储器

* * *

## 快速启动

### 用 MockLLMBackend 进行测试

使用短而有效的 Vitest 示例 `MockLLMBackend`数字 :

```typescript
import { describe, it, expect } from 'vitest';
import { MockLLMBackend, createToolCall } from '@cogitator-ai/test-utils';

describe('MockLLMBackend', () => {
  it('returns scripted responses and inspects requests', async () => {
    const backend = new MockLLMBackend();
    backend.setResponses([
      { toolCalls: [createToolCall('get_weather', { city: 'Tokyo' })] },
      { content: 'The weather in Tokyo is sunny and 22°C.' },
    ]);

    const first = await backend.chat({
      model: 'test-model',
      messages: [{ role: 'user', content: 'What is the weather in Tokyo?' }],
    });

    expect(first.finishReason).toBe('tool_calls');
    expect(first.toolCalls?.[0].name).toBe('get_weather');

    const second = await backend.chat({
      model: 'test-model',
      messages: [
        { role: 'user', content: 'What is the weather in Tokyo?' },
        { role: 'assistant', content: 'Checking weather...' },
        {
          role: 'tool',
          content: '{"temperature": 22}',
          toolCallId: first.toolCalls![0].id,
          name: 'get_weather',
        },
      ],
    });

    expect(second.content).toBe('The weather in Tokyo is sunny and 22°C.');
    expect(second.finishReason).toBe('stop');

    expect(backend.getCallCount()).toBe(2);
    expect(backend.wasCalledWith((req) => req.model === 'test-model')).toBe(true);
    expect(backend.getLastCall()?.messages).toHaveLength(3);
  });
});
```

### 使用MockMemoryAdapter进行测试

使用短而有效的 Vitest 示例 `MockMemoryAdapter`数字 :

```typescript
import { describe, it, expect } from 'vitest';
import { MockMemoryAdapter, createUserMessage } from '@cogitator-ai/test-utils';

describe('MockMemoryAdapter', () => {
  it('stores conversation history and records calls', async () => {
    const memory = new MockMemoryAdapter();
    await memory.connect();
    expect(memory.isConnected()).toBe(true);

    const threadResult = await memory.createThread('agent-1', { topic: 'testing' }, 'thread-123');
    expect(threadResult.success).toBe(true);

    const addResult = await memory.addEntry({
      threadId: 'thread-123',
      message: createUserMessage('Remember this note'),
      tokenCount: 4,
    });
    expect(addResult.success).toBe(true);

    const entriesResult = await memory.getEntries({ threadId: 'thread-123' });
    expect(entriesResult.success).toBe(true);
    if (entriesResult.success) {
      expect(entriesResult.data).toHaveLength(1);
      expect(entriesResult.data[0].message.content).toBe('Remember this note');
    }

    expect(memory.getCallsFor('createThread')).toHaveLength(1);
    expect(memory.getCallsFor('addEntry')).toHaveLength(1);

    await memory.disconnect();
    expect(memory.isConnected()).toBe(false);
  });
});
```

* * *

## 鸡鸡

### MockLLMBackend 移动端

`MockLLMBackend` 执行 `LLMBackend` (单位:千美元)`provider: 'openai'`)和以脚本响应或流块响应呼叫,同时记录所有收到的请求.

#### 脚本聊天响应

```typescript
import { MockLLMBackend, createMockLLMBackend, createToolCall } from '@cogitator-ai/test-utils';

const backend = createMockLLMBackend();

// Set a single response for all chat() calls
backend.setResponse({ content: 'Hello, world!' });

// Set multiple responses returned in sequence (the last response repeats)
backend.setResponses([{ content: 'First response' }, { content: 'Second response' }]);

// Shortcut for scripted tool call responses
backend.setToolCallResponse([createToolCall('calculator', { expression: '2 + 2' })]);

// Set default delay (in ms) before answering
backend.setDefaultDelay(50);
```

#### 流线

```typescript
import { MockLLMBackend, collectStreamContent } from '@cogitator-ai/test-utils';

const backend = new MockLLMBackend();

// Script a stream for chatStream()
backend.setStreamChunks([{ content: 'Hello' }, { content: ' world' }, { content: '!' }]);

// Or script multiple distinct streams in sequence
backend.setMultipleStreamChunks([[{ content: 'First stream' }], [{ content: 'Second stream' }]]);

const stream = backend.chatStream({
  model: 'test-model',
  messages: [{ role: 'user', content: 'Hi' }],
});

const text = await collectStreamContent(stream);
```

#### 请检查

```typescript
// Inspect recorded requests
const count = backend.getCallCount();
const allCalls = backend.getCalls();
const lastCall = backend.getLastCall();

// Predicate match
const wasCalled = backend.wasCalledWith((req) => req.model === 'test-model');

// Reset calls, responses, and stream chunks
backend.reset();
```

### 模拟地图

`MockMemoryAdapter` 执行 `MemoryAdapter` (单位:千美元)`provider: 'memory'`),在记忆中使用了本土地图并记录了每次引用.

```typescript
import { MockMemoryAdapter, createMockMemoryAdapter } from '@cogitator-ai/test-utils';

const memory = createMockMemoryAdapter();

// Lifecycle
await memory.connect();
const connected = memory.isConnected(); // true

// Threads
const thread = await memory.createThread('agent-id', { tag: 'session' }, 'custom-id');
const fetchedThread = await memory.getThread('custom-id');
await memory.updateThread('custom-id', { tag: 'updated' });

// Entries
await memory.addEntry({
  threadId: 'custom-id',
  message: { role: 'user', content: 'Hello' },
  tokenCount: 1,
});
const entries = await memory.getEntries({ threadId: 'custom-id', limit: 10 });
const singleEntry = await memory.getEntry(
  entries.success && entries.data[0] ? entries.data[0].id : ''
);
await memory.deleteEntry('entry-id');
await memory.clearThread('custom-id');
await memory.deleteThread('custom-id');

// Inspection
const calls = memory.getCalls(); // Array<{ method: string; args: unknown[] }>
const threadCalls = memory.getCallsFor('createThread');

// Reset all internal state and calls
memory.reset();
await memory.disconnect();
```

* * *

## 固定设备

### 探员

生成具有测试默认值的测试代理配置或代理形状对象 :

```typescript
import { createTestAgentConfig, createTestAgent } from '@cogitator-ai/test-utils';

// AgentConfig with default name 'test-agent' and model 'mock/test-model'
const config = createTestAgentConfig({
  name: 'custom-agent',
  instructions: 'Custom instructions',
});

// Agent-shaped object implementing the Agent interface
const agent = createTestAgent({
  name: 'test-agent',
});
```

### 信件和工具调用

构造强烈的对口消息、工具呼叫和工具结果 :

```typescript
import {
  createUserMessage,
  createAssistantMessage,
  createSystemMessage,
  createToolMessage,
  createMultimodalMessage,
  createImageUrlMessage,
  createToolCall,
  createToolResult,
  createConversation,
} from '@cogitator-ai/test-utils';

const userMsg = createUserMessage('Hello');
const assistantMsg = createAssistantMessage('Hi there');
const systemMsg = createSystemMessage('You are a test assistant');
const toolMsg = createToolMessage('call_1', '{"result": 42}', 'calculator');

const multimodalMsg = createMultimodalMessage([
  { type: 'text', text: 'Describe this' },
  { type: 'image_url', image_url: { url: 'https://example.com/image.png' } },
]);
const imgMsg = createImageUrlMessage('Look at this', 'https://example.com/image.png');

const call = createToolCall('calculator', { expression: '2 + 2' });
const result = createToolResult(call, { result: 4 });

const turns = createConversation(
  { role: 'user', content: 'Hello' },
  { role: 'assistant', content: 'Hi' }
);
```

### 工具

用于测试工具执行和计划通过的预定义的 JSON Schema 工具固定装置 :

```typescript
import {
  createTestTool,
  createCalculatorTool,
  createWeatherTool,
  createFailingTool,
  createSlowTool,
  createToolSchema,
} from '@cogitator-ai/test-utils';

// Customizable SimpleTool
const customTool = createTestTool({
  name: 'custom_tool',
  description: 'A custom tool',
  execute: async (args) => ({ echo: args }),
});

// Built-in tools
const calc = createCalculatorTool(); // evaluates arithmetic expressions ('2 + 2')
const weather = createWeatherTool(); // returns 22°C sunny weather for city
const failing = createFailingTool('Custom error'); // always throws
const slow = createSlowTool(50); // delays for specified ms before returning

// ToolSchema fixture
const schema = createToolSchema('my_tool', 'Tool description');
```

### 运行结果

雾 `RunResult` 密码消耗代理执行结果的结构:

```typescript
import {
  createMockRunResult,
  createRunResultWithToolCalls,
  createRunResultWithMessages,
} from '@cogitator-ai/test-utils';

const baseResult = createMockRunResult('Final answer');
const withTools = createRunResultWithToolCalls('Output', [call]);
const withHistory = createRunResultWithMessages('Output', [userMsg, assistantMsg]);
```

* * *

## 帮助者

### 串流帮助

帮助消耗和测试同步发电机流(`AsyncGenerator<ChatStreamChunk>`:

```typescript
import {
  collectStreamContent,
  collectStreamChunks,
  collectStreamToolCalls,
  createMockReadableStream,
} from '@cogitator-ai/test-utils';

// Drains stream and returns concatenated text
const content = await collectStreamContent(stream);

// Drains stream and returns all chunks as an array
const chunks = await collectStreamChunks(stream);

// Drains stream and returns parsed tool calls
const toolCalls = await collectStreamToolCalls(stream);

// Creates a ReadableStream<Uint8Array> from string chunks (e.g. for SSE testing)
const byteStream = createMockReadableStream(['data: {"text":"hello"}\n\n']);
```

### 同步帮助器

处理同步计时、投票和超时的公用事业:

```typescript
import { waitFor, eventually, delay, withTimeout } from '@cogitator-ai/test-utils';

// Sleep for ms
await delay(100);

// Poll condition until truthy or timeout (defaults: timeout 5000ms, interval 50ms)
const ready = await waitFor(() => checkReady(), { timeout: 2000, interval: 20 });

// Retry assertion until it passes or timeout
await eventually(() => expect(isDone()).toBe(true), { timeout: 3000, interval: 50 });

// Wrap promise with timeout
const value = await withTimeout(fetchData(), 1000);
```

* * *

## 遵约

用于验证该自定义或第三方的完整工具包 `LLMBackend` 执行中正确遵守提供者协议、错误处理、取消和流转惯例.

### 后端合规套件

运行全套符合性测试案例,针对 `LLMBackend`数字 :

```typescript
import { describe, it } from 'vitest';
import {
  backendConformanceCases,
  openAIChatWire,
  type BackendConformanceTarget,
} from '@cogitator-ai/test-utils';

const target: BackendConformanceTarget = {
  name: 'MyCustomBackend',
  model: 'gpt-4o',
  wire: openAIChatWire,
  createBackend: (url) => new MyCustomBackend({ baseUrl: url }),
};

describe('MyCustomBackend conformance', () => {
  for (const c of backendConformanceCases(target)) {
    (c.skip ? it.skip : it)(c.name, () => c.run());
  }
});
```

### 假的提供服务器

运行一个轻量级的 HTTP 服务器模拟提供者 API :

```typescript
import { startFakeProvider, sse } from '@cogitator-ai/test-utils';

const server = await startFakeProvider();

server.reply((req) => {
  if (req.path === '/v1/chat/completions') {
    return {
      type: 'stream',
      contentType: 'text/event-stream',
      chunks: [sse({ choices: [{ delta: { content: 'Hi' } }] })],
    };
  }
  return { type: 'json', status: 404, body: { error: 'Not found' } };
});

console.log(`Fake provider listening at: ${server.url}`);

await server.close();
```

### 电线协议和编码

流行LLM提供者协议的电线规格和格式化帮助器:

-   **电线**数字 : `openAIChatWire`, (中文(简体) ), `openAIResponsesWire`, (中文(简体) ), `anthropicWire`, (中文(简体) ), `geminiWire`, (中文(简体) ), `ollamaWire`, (中文(简体) ), `bedrockConverseWire`
-   **编码**数字 : `sse(data, event?)`, (中文(简体) ), `ndjson(data)`, (中文(简体) ), `awsEventStreamMessage(headers, payload)`
-   **固定线**数字 : `conformanceRequest`, (中文(简体) ), `CONFORMANCE_FIXTURE`

### 内存适配器和嵌入存储器

`memoryAdapterConformanceCases(target)`, (中文(简体) ), `memoryItemAdapterConformanceCases(target)`, (中文(简体) ), `memoryFileAdapterConformanceCases(target)` 财务报告和审定财务报表 `embeddingAdapterConformanceCases(target)` 检查a `MemoryAdapter`页:1 `MemoryItemAdapter`页:1 `MemoryFileAdapter` 或一个 `EmbeddingAdapter` 与合同相对 内在的内在 保存: 缺失与 `null`原子 `updateThread`,带有等分时间戳、限制、级联、副本的入场命令, `listThreads` 过滤和呼号,最近的第一搜索,阈值,过滤和删除.

```typescript
for (const c of memoryAdapterConformanceCases({
  create: async () => {
    const adapter = new MyAdapter();
    await adapter.connect();
    return adapter;
  },
  release: (adapter) => adapter.disconnect().then(() => undefined),
})) {
  (c.skip ? it.skip : it)(c.name, () => c.run());
}
```

每个案件都使用线程,代理或自嵌入,所以一个数据库可以服务于他们所有人. 嵌入套件也要使用 `dimensions`。在内存文件套件中 `file-find-heads` 检查 `findFileHeads`:每个范围和路径的最新版本,包括删除内容,将一个版本从被忽略的分支中移出,最古老的第一,没有它就没有任何适配器 `file-withdraw` 检查 `withdrawFileVersions`:被撤回的版本保持其序列,从不是头. 在内存适配套件中 `redacts-an-entry-in-place` 检查 `redactEntry`:一个已编辑的条目保留其位置、作用和工具调用标识,不保留其文本、工具参数或工具结果、记录中的任何内容 `metadata.redacted`,给出 `null` 丢失时,一次报告为 `entry-redacted`,并且,在有分支的适配器上,它保留其母(也当母被删除时),并且拒绝一个事件条目(不检查任何适配器 `redactEntry` 或者说 `onChange`) (中文(简体) ). 内存项套件检查项目和实体对字段的回读(日期: `Date`s, 一个缺失的字段, 永远不会 `null`页:1, `findItems` 滤镜、瞄准镜滤镜(`visibleTo`, (中文(简体) ), `scope`)和顺序(最先记录的),项目被放出,除非 `includeExpired` 尽管后来仍然发现有人放过,但用任何普通名称发现的实体,删除和复制。 内存文件套件检查一个版本的内存文件为字段读回字段(删除的) `null` 在另一个地方的版本(范围、路径和 `sequence`) 被拒绝 `MEMORY_FILE_CONFLICT`,当作家竞逐一个地方时, 被拒绝的批次没有保存任何版本, 过滤器( )`ids`, (中文(简体) ), `paths`, (中文(简体) ), `prefix`, (中文(简体) ), `visibleTo`, (中文(简体) ), `scope`和他们的顺序(由 `createdAt`,则 `sequence`编辑(内容和内容) `sha256` 替换,无其他改动),删除和复制.

* * *

## 公共出口

公共出口分类如下: `src/index.ts` 作为:

| 组 | 模块 | 说明 |
| --- | --- | --- |
| **鸡鸡** | `@cogitator-ai/test-utils` (单位:千美元)`./mocks`(中文(简体) ) | `MockLLMBackend`, (中文(简体) ), `createMockLLMBackend`, (中文(简体) ), `MockMemoryAdapter`, (中文(简体) ), `createMockMemoryAdapter`, (中文(简体) ), `MockChatResponse`, (中文(简体) ), `MockStreamChunk` |
| **固定设备** | `@cogitator-ai/test-utils` (单位:千美元)`./fixtures`(中文(简体) ) | `createTestAgent`, (中文(简体) ), `createTestAgentConfig`, (中文(简体) ), `TestAgentConfig`, (中文(简体) ), `createUserMessage`, (中文(简体) ), `createAssistantMessage`, (中文(简体) ), `createSystemMessage`, (中文(简体) ), `createToolMessage`, (中文(简体) ), `createMultimodalMessage`, (中文(简体) ), `createImageUrlMessage`, (中文(简体) ), `createToolCall`, (中文(简体) ), `createToolResult`, (中文(简体) ), `createConversation`, (中文(简体) ), `createTestTool`, (中文(简体) ), `createCalculatorTool`, (中文(简体) ), `createWeatherTool`, (中文(简体) ), `createFailingTool`, (中文(简体) ), `createSlowTool`, (中文(简体) ), `createToolSchema`, (中文(简体) ), `TestToolOptions`, (中文(简体) ), `SimpleTool`, (中文(简体) ), `createMockRunResult`, (中文(简体) ), `createRunResultWithToolCalls`, (中文(简体) ), `createRunResultWithMessages`, (中文(简体) ), `TestRunResultOptions` |
| **帮助者** | `@cogitator-ai/test-utils` (单位:千美元)`./helpers`(中文(简体) ) | `collectStreamContent`, (中文(简体) ), `collectStreamChunks`, (中文(简体) ), `collectStreamToolCalls`, (中文(简体) ), `createMockReadableStream`, (中文(简体) ), `waitFor`, (中文(简体) ), `eventually`, (中文(简体) ), `delay`, (中文(简体) ), `withTimeout` |
| **遵约** | `@cogitator-ai/test-utils` (单位:千美元)`./conformance`(中文(简体) ) | `startFakeProvider`, (中文(简体) ), `FakeProvider`, (中文(简体) ), `FakeProviderHandler`, (中文(简体) ), `FakeProviderOptions`, (中文(简体) ), `FakeProviderReply`, (中文(简体) ), `FakeProviderRequest`, (中文(简体) ), `backendConformanceCases`, (中文(简体) ), `conformanceRequest`, (中文(简体) ), `CONFORMANCE_FIXTURE`, (中文(简体) ), `BackendConformanceCase`, (中文(简体) ), `BackendConformanceTarget`, (中文(简体) ), `ConformanceMode`, (中文(简体) ), `ConformanceScenario`, (中文(简体) ), `ProviderWire`, (中文(简体) ), `openAIChatWire`, (中文(简体) ), `openAIResponsesWire`, (中文(简体) ), `anthropicWire`, (中文(简体) ), `geminiWire`, (中文(简体) ), `ollamaWire`, (中文(简体) ), `bedrockConverseWire`, (中文(简体) ), `sse`, (中文(简体) ), `ndjson`, (中文(简体) ), `awsEventStreamMessage`, (中文(简体) ), `memoryAdapterConformanceCases`, (中文(简体) ), `memoryItemAdapterConformanceCases`, (中文(简体) ), `memoryFileAdapterConformanceCases`, (中文(简体) ), `embeddingAdapterConformanceCases` 联合国 `*ConformanceCase`, (中文(简体) ), `*ConformanceTarget` 财务报告和审定财务报表 `*Scenario` 类型 |

* * *

## 许可证

麻省理工学院

## 常见问题

### @cogitator-ai/test-utils 是什么？

共享 Cogitator 包的测试工具

### 如何安装 @cogitator-ai/test-utils？

在项目目录运行 npm install @cogitator-ai/test-utils，或使用 pnpm add / yarn add / bun add。

### @cogitator-ai/test-utils 支持 TypeScript 吗？

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

### @cogitator-ai/test-utils 支持 ESM 还是 CommonJS？

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

### @cogitator-ai/test-utils 需要什么版本的 Node\.js？

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

### @cogitator-ai/test-utils 可以商用吗？

@cogitator-ai/test-utils 使用 MIT 许可。宽松许可：允许商业使用、修改和再分发，通常只需在分发时保留原版权与许可声明。以上为概括，不构成法律意见，请以许可原文为准。

### @cogitator-ai/test-utils 的下载量有多少？

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

### @cogitator-ai/test-utils 还在维护吗？

最新版本 0\.15\.0 发布于 2026/11/04（6 天前）；至今共发布 79 个版本，其中过去 12 个月发布了 79 个；首次发布于 2026/01/27。发布频率只是参考信号：功能稳定的工具可能很少需要更新，建议结合源码仓库的 issue 和提交记录判断。

