@deepseek-ai/dsh-llm-mock-server 0.1.6-alpha.2 → 0.1.7-alpha.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.i18n.yaml CHANGED
@@ -2,5 +2,5 @@
2
2
  # side as of the last confirmed-consistent state. Both languages carry equal authority;
3
3
  # after editing either side, bring the other along and re-record with:
4
4
  # pnpm run verify-translation-pairing --write packages/test-support/llm-mock-server/README.md
5
- README.md: be311d9c83bcd35ad5bd0c003f6e95861b6d6976
6
- README.zh.md: 7a022131d9ef09d9ef89c91cae418f093f77aca1
5
+ README.md: 2f83cf66c02728820a4f8aa6f14b1a091d092626
6
+ README.zh.md: ad85853fb4a20c3ccdb444508da8032c18d7538a
package/README.md CHANGED
@@ -1,5 +1,5 @@
1
1
  ---
2
- description: "Scriptable OpenAI-compatible fault server for testing LLM adapters and recovery policy without a provider key, for test authors and demos."
2
+ description: "Scriptable Messages-compatible fault server for testing LLM adapters and recovery policy without a provider key, for test authors and demos."
3
3
  kind: "package-library"
4
4
  ---
5
5
 
@@ -9,7 +9,7 @@ English | [中文](README.zh.md)
9
9
 
10
10
  ## Summary
11
11
 
12
- This package gives tests and demos a scriptable OpenAI-compatible HTTP/SSE endpoint, so they can exercise model-provider failures and successes without a provider key. Each accepted `/chat/completions` request consumes the next scripted behavior, including resets, stalls, malformed chunks, rate limits, server errors, completions, and tool calls. Test authors can run it with `pnpm run mock:llm` or call `startMockLlmServer`, which returns captured requests for assertions. Seeded `random` behavior supports reproducible mixed-failure stress runs.
12
+ This package gives tests and demos a scriptable Messages-compatible HTTP/SSE endpoint, so they can exercise model-provider failures and successes without a provider key. Each accepted `/v1/messages` request consumes the next scripted behavior, including resets, stalls, malformed chunks, rate limits, server errors, completions, and tool calls. Test authors can run it with `pnpm run mock:llm` or call `startMockLlmServer`, which returns captured requests for assertions. Seeded `random` behavior supports reproducible mixed-failure stress runs.
13
13
 
14
14
  ## Table of Contents
15
15
 
@@ -39,7 +39,7 @@ pnpm run mock:llm \
39
39
  --partial-text "discard this half"
40
40
  ```
41
41
 
42
- Point the shipping DeepSeek adapter at the server; it appends `/chat/completions` to the configured base:
42
+ Point the shipping DeepSeek adapter at the server; it sends requests to `/messages` beneath the server's `/v1` root:
43
43
 
44
44
  ```sh
45
45
  DEEPSEEK_BASE_URL=http://127.0.0.1:8000/v1 \
@@ -88,13 +88,13 @@ Omitting `--seed` generates one and prints it in the `ready` record. `--random-w
88
88
 
89
89
  ### Timing and content controls
90
90
 
91
- The CLI exposes `--success-text`, `--partial-text`, `--reasoning-text`, `--chunk-size`, `--chunk-delay-ms`, `--disconnect-delay-ms`, `--retry-after-ms`, `--request-id`, `--tool-name`, and `--tool-arguments`. Millisecond delays are bounded integers within Node's timer range; `retryAfterMs` must also be positive. The library accepts the same camel-case options. An optional exact `apiKey` validates `Authorization: Bearer <token>`; omission accepts any token.
91
+ The CLI exposes `--success-text`, `--partial-text`, `--reasoning-text`, `--chunk-size`, `--chunk-delay-ms`, `--disconnect-delay-ms`, `--retry-after-ms`, `--request-id`, `--tool-name`, and `--tool-arguments`. Millisecond delays are bounded integers within Node's timer range; `retryAfterMs` must also be positive. The library accepts the same camel-case options. An optional exact `apiKey` validates `x-api-key: <token>`; omission accepts any token.
92
92
 
93
93
  ### What can go wrong
94
94
 
95
95
  - **The script runs out** — exhaustion returns a structured HTTP 500; set `--repeat-last` or lengthen the sequence when a run needs more requests.
96
96
  - **Random weights without a positive concrete behavior are rejected** — every entry must name an existing behavior and at least one must carry positive weight.
97
- - **Invalid requests do not consume the script** — wrong methods, paths, bearer tokens, and malformed JSON get ordinary 4xx responses, so a misconfigured client can burn retries without advancing the sequence.
97
+ - **Invalid requests do not consume the script** — wrong methods, paths, API keys, and malformed JSON get ordinary 4xx responses, so a misconfigured client can burn retries without advancing the sequence.
98
98
 
99
99
  -----
100
100
 
@@ -108,7 +108,7 @@ This section explains the design of the server; the observable behavior is fully
108
108
 
109
109
  ### Design
110
110
 
111
- The server is built on one rule: each accepted chat-completions request consumes exactly one behavior from an arrival-ordered FIFO cursor, and the server never retries or interprets harness policy. Validation happens before the cursor advances — only a `POST` whose path ends in `/chat/completions`, with a valid bearer token when one is configured and a parseable JSON body, consumes the script; everything else receives an ordinary 4xx. `random` entries resolve at request time through a seeded PRNG over the configured weights, so a run is reproducible from its printed seed.
111
+ The server is built on one rule: each accepted Messages request consumes exactly one behavior from an arrival-ordered FIFO cursor, and the server never retries or interprets harness policy. Validation happens before the cursor advances — only a `POST` whose path ends in `/v1/messages`, with a valid API key when one is configured and a parseable JSON body, consumes the script; everything else receives an ordinary 4xx. `random` entries resolve at request time through a seeded PRNG over the configured weights, so a run is reproducible from its printed seed.
112
112
 
113
113
  ### Source map
114
114
 
package/README.zh.md CHANGED
@@ -1,5 +1,5 @@
1
1
  ---
2
- description: "用于在无提供方密钥的情况下测试 LLM(大语言模型)适配器与恢复策略的可通过脚本控制的 OpenAI 兼容故障服务器,面向测试作者与演示。"
2
+ description: "用于在无提供方密钥的情况下测试 LLM(大语言模型)适配器与恢复策略的可通过脚本控制的 Messages 兼容故障服务器,面向测试作者与演示。"
3
3
  kind: "package-library"
4
4
  ---
5
5
 
@@ -9,7 +9,7 @@ kind: "package-library"
9
9
 
10
10
  ## 概述
11
11
 
12
- 本包为测试与演示提供可编脚本的 OpenAI 兼容 HTTP/SSE(Server-Sent Events)端点,使其无需提供方密钥即可检验模型提供方的失败与成功。每个已接受的 `/chat/completions` 请求依次消费下一个脚本行为,包括重置、停滞、畸形分片、限流、服务器错误、补全与工具调用。测试作者可以通过 `pnpm run mock:llm` 运行服务器,也可以调用 `startMockLlmServer`,后者会返回捕获的请求供断言使用。带种子的 `random` 行为支持可复现的混合故障压力运行。
12
+ 本包为测试与演示提供可编脚本的 Messages 兼容 HTTP/SSE(Server-Sent Events)端点,使其无需提供方密钥即可检验模型提供方的失败与成功。每个已接受的 `/v1/messages` 请求依次消费下一个脚本行为,包括重置、停滞、畸形分片、限流、服务器错误、补全与工具调用。测试作者可以通过 `pnpm run mock:llm` 运行服务器,也可以调用 `startMockLlmServer`,后者会返回捕获的请求供断言使用。带种子的 `random` 行为支持可复现的混合故障压力运行。
13
13
 
14
14
  ## 目录
15
15
 
@@ -39,7 +39,7 @@ pnpm run mock:llm \
39
39
  --partial-text "discard this half"
40
40
  ```
41
41
 
42
- 将发布的 DeepSeek 适配器指向服务器;它会将 `/chat/completions` 追加到已配置 base:
42
+ 将发布的 DeepSeek 适配器指向服务器;它会向服务器 `/v1` 根路径下的 `/messages` 发送请求:
43
43
 
44
44
  ```sh
45
45
  DEEPSEEK_BASE_URL=http://127.0.0.1:8000/v1 \
@@ -88,13 +88,13 @@ pnpm run mock:llm \
88
88
 
89
89
  ### 时序与内容控制
90
90
 
91
- CLI 公开 `--success-text`、`--partial-text`、`--reasoning-text`、`--chunk-size`、`--chunk-delay-ms`、`--disconnect-delay-ms`、`--retry-after-ms`、`--request-id`、`--tool-name` 与 `--tool-arguments`。毫秒延迟是 Node 定时器范围内的有界整数;`retryAfterMs` 还必须为正数。库接受相同的 camel-case 选项。可选的 `apiKey` 会精确验证 `Authorization: Bearer <token>`;省略时接受任何 token。
91
+ CLI 公开 `--success-text`、`--partial-text`、`--reasoning-text`、`--chunk-size`、`--chunk-delay-ms`、`--disconnect-delay-ms`、`--retry-after-ms`、`--request-id`、`--tool-name` 与 `--tool-arguments`。毫秒延迟是 Node 定时器范围内的有界整数;`retryAfterMs` 还必须为正数。库接受相同的 camel-case 选项。可选的 `apiKey` 会精确验证 `x-api-key: <token>`;省略时接受任何 token。
92
92
 
93
93
  ### 可能出什么问题
94
94
 
95
95
  - **脚本耗尽**——耗尽时返回结构化 HTTP 500;当一次运行需要更多请求时设置 `--repeat-last` 或加长序列。
96
96
  - **没有正权重具体行为的随机权重会被拒绝**——每个条目都必须命名现有行为,且至少一个条目带正权重。
97
- - **无效请求不消费脚本**——错误方法、路径、Bearer token 与畸形 JSON 会收到普通 4xx 响应,因此配置错误的客户端可能耗尽重试却不推进序列。
97
+ - **无效请求不消费脚本**——错误方法、路径、API key 与畸形 JSON 会收到普通 4xx 响应,因此配置错误的客户端可能耗尽重试却不推进序列。
98
98
 
99
99
  -----
100
100
 
@@ -108,7 +108,7 @@ CLI 公开 `--success-text`、`--partial-text`、`--reasoning-text`、`--chunk-s
108
108
 
109
109
  ### 设计
110
110
 
111
- 服务器建立在一个规则之上:每个已接受的 chat-completions 请求从按到达顺序排列的 FIFO 游标消费恰好一个行为,服务器从不重试或解读 harness 策略。校验先于游标推进——只有 `POST` 且路径以 `/chat/completions` 结尾、配置密钥时携带有效 Bearer token、且 JSON 正文可解析的请求才消费脚本;其余请求都收到普通 4xx。`random` 条目在请求时通过带种子的 PRNG 按配置权重解析,因此一次运行可由其打印出的种子复现。
111
+ 服务器建立在一个规则之上:每个已接受的 Messages 请求从按到达顺序排列的 FIFO 游标消费恰好一个行为,服务器从不重试或解读 harness 策略。校验先于游标推进——只有 `POST` 且路径以 `/v1/messages` 结尾、配置密钥时携带有效 API key、且 JSON 正文可解析的请求才消费脚本;其余请求都收到普通 4xx。`random` 条目在请求时通过带种子的 PRNG 按配置权重解析,因此一次运行可由其打印出的种子复现。
112
112
 
113
113
  ### 源码地图
114
114
 
package/lib/index.js CHANGED
@@ -4,8 +4,8 @@ import { isIP } from "node:net";
4
4
  import { setTimeout } from "node:timers/promises";
5
5
  //#region lib/types/index.js
6
6
  /**
7
- * Scriptable OpenAI-compatible HTTP/SSE server for transport, protocol, and
8
- * semantic-empty LLM recovery tests. Each accepted chat-completions request
7
+ * Scriptable Messages HTTP/SSE server for transport, protocol, and
8
+ * semantic-empty LLM recovery tests. Each accepted Messages request
9
9
  * consumes one behavior; the server never retries or interprets harness policy.
10
10
  *
11
11
  * @module @deepseek-ai/dsh-llm-mock-server
@@ -153,7 +153,7 @@ function writeSse(record, response, payload) {
153
153
  record.chunksSent += 1;
154
154
  }
155
155
  function writeDone(record, response) {
156
- writeSse(record, response, "[DONE]");
156
+ writeSse(record, response, { type: "message_stop" });
157
157
  }
158
158
  function finishRecord(options, record, outcome) {
159
159
  if (record.outcome !== void 0) return;
@@ -179,17 +179,40 @@ function httpError(options, record, response, status, message, code, type = "moc
179
179
  } }));
180
180
  finishRecord(options, record, "completed");
181
181
  }
182
+ function startMessage(record, response) {
183
+ writeSse(record, response, {
184
+ type: "message_start",
185
+ message: {
186
+ id: "mock-message",
187
+ type: "message",
188
+ role: "assistant",
189
+ model: "mock-model",
190
+ content: [],
191
+ usage: {
192
+ input_tokens: 3,
193
+ output_tokens: 0
194
+ }
195
+ }
196
+ });
197
+ }
198
+ function startText(record, response, index) {
199
+ writeSse(record, response, {
200
+ type: "content_block_start",
201
+ index,
202
+ content_block: {
203
+ type: "text",
204
+ text: ""
205
+ }
206
+ });
207
+ }
182
208
  function terminalChunk(reason, outputTokens) {
183
209
  return {
184
- choices: [{
185
- index: 0,
186
- delta: { content: "" },
187
- finish_reason: reason
188
- }],
189
- usage: {
190
- prompt_tokens: 3,
191
- completion_tokens: outputTokens
192
- }
210
+ type: "message_delta",
211
+ delta: {
212
+ stop_reason: reason,
213
+ stop_sequence: null
214
+ },
215
+ usage: { output_tokens: outputTokens }
193
216
  };
194
217
  }
195
218
  async function pause(milliseconds, response) {
@@ -208,22 +231,30 @@ async function pause(milliseconds, response) {
208
231
  response.off("close", stop);
209
232
  }
210
233
  }
211
- async function streamText(options, record, response, text, delayMs) {
234
+ async function streamText(options, record, response, text, delayMs, index = 0) {
212
235
  for (const chunk of splitText(text, options.chunkSize)) {
213
- writeSse(record, response, { choices: [{
214
- index: 0,
215
- delta: { content: chunk },
216
- finish_reason: null
217
- }] });
236
+ writeSse(record, response, {
237
+ type: "content_block_delta",
238
+ index,
239
+ delta: {
240
+ type: "text_delta",
241
+ text: chunk
242
+ }
243
+ });
218
244
  if (!await pause(delayMs, response)) return false;
219
245
  }
220
246
  return true;
221
247
  }
222
- async function completeText(options, record, response, reason, delayMs) {
223
- if (!await streamText(options, record, response, options.successText, delayMs)) {
248
+ async function completeText(options, record, response, reason, delayMs, index = 0) {
249
+ startText(record, response, index);
250
+ if (!await streamText(options, record, response, options.successText, delayMs, index)) {
224
251
  finishRecord(options, record, "client_closed");
225
252
  return;
226
253
  }
254
+ writeSse(record, response, {
255
+ type: "content_block_stop",
256
+ index
257
+ });
227
258
  writeSse(record, response, terminalChunk(reason, Array.from(options.successText).length));
228
259
  writeDone(record, response);
229
260
  response.end();
@@ -239,26 +270,30 @@ async function disconnect(options, record, response) {
239
270
  }
240
271
  function toolCallChunks(options) {
241
272
  const midpoint = Math.max(1, Math.floor(options.toolArguments.length / 2));
242
- return [{ choices: [{
243
- index: 0,
244
- delta: { tool_calls: [{
273
+ return [
274
+ {
275
+ type: "content_block_start",
245
276
  index: 0,
246
- id: "mock-call-1",
247
- type: "function",
248
- function: {
277
+ content_block: {
278
+ type: "tool_use",
279
+ id: "mock-call-1",
249
280
  name: options.toolName,
250
- arguments: options.toolArguments.slice(0, midpoint)
281
+ input: {}
251
282
  }
252
- }] },
253
- finish_reason: null
254
- }] }, { choices: [{
255
- index: 0,
256
- delta: { tool_calls: [{
283
+ },
284
+ ...[options.toolArguments.slice(0, midpoint), options.toolArguments.slice(midpoint)].map((partial) => ({
285
+ type: "content_block_delta",
257
286
  index: 0,
258
- function: { arguments: options.toolArguments.slice(midpoint) }
259
- }] },
260
- finish_reason: null
261
- }] }];
287
+ delta: {
288
+ type: "input_json_delta",
289
+ partial_json: partial
290
+ }
291
+ })),
292
+ {
293
+ type: "content_block_stop",
294
+ index: 0
295
+ }
296
+ ];
262
297
  }
263
298
  async function runBehavior(options, record, request, response) {
264
299
  switch (record.behavior) {
@@ -275,7 +310,8 @@ async function runBehavior(options, record, request, response) {
275
310
  return;
276
311
  case "empty":
277
312
  openSse(response);
278
- writeSse(record, response, terminalChunk("stop", 0));
313
+ startMessage(record, response);
314
+ writeSse(record, response, terminalChunk("end_turn", 0));
279
315
  writeDone(record, response);
280
316
  response.end();
281
317
  finishRecord(options, record, "completed");
@@ -287,22 +323,22 @@ async function runBehavior(options, record, request, response) {
287
323
  return;
288
324
  case "stream_eof":
289
325
  openSse(response);
290
- writeSse(record, response, { choices: [{
291
- index: 0,
292
- delta: { role: "assistant" },
293
- finish_reason: null
294
- }] });
326
+ startMessage(record, response);
295
327
  response.end();
296
328
  finishRecord(options, record, "completed");
297
329
  return;
298
330
  case "partial_eof":
299
331
  openSse(response);
332
+ startMessage(record, response);
333
+ startText(record, response, 0);
300
334
  await streamText(options, record, response, options.partialText, 0);
301
335
  response.end();
302
336
  finishRecord(options, record, "completed");
303
337
  return;
304
338
  case "partial_disconnect":
305
339
  openSse(response);
340
+ startMessage(record, response);
341
+ startText(record, response, 0);
306
342
  if (!await streamText(options, record, response, options.partialText, options.chunkDelayMs)) return;
307
343
  await disconnect(options, record, response);
308
344
  return;
@@ -319,14 +355,19 @@ async function runBehavior(options, record, request, response) {
319
355
  return;
320
356
  case "malformed_event":
321
357
  openSse(response);
322
- writeSse(record, response, { choices: [null] });
358
+ writeSse(record, response, {
359
+ type: "content_block_start",
360
+ index: 0,
361
+ content_block: null
362
+ });
323
363
  writeDone(record, response);
324
364
  response.end();
325
365
  finishRecord(options, record, "completed");
326
366
  return;
327
367
  case "wrong_content_type":
328
368
  openSse(response, "application/json");
329
- await completeText(options, record, response, "stop", 0);
369
+ startMessage(record, response);
370
+ await completeText(options, record, response, "end_turn", 0);
330
371
  return;
331
372
  case "rate_limit":
332
373
  httpError(options, record, response, 429, "mock rate limit", "rate_limit");
@@ -351,32 +392,52 @@ async function runBehavior(options, record, request, response) {
351
392
  return;
352
393
  case "success":
353
394
  openSse(response);
354
- await completeText(options, record, response, "stop", 0);
395
+ startMessage(record, response);
396
+ await completeText(options, record, response, "end_turn", 0);
355
397
  return;
356
398
  case "reasoning_success":
357
399
  openSse(response);
358
- for (const chunk of splitText(options.reasoningText, options.chunkSize)) writeSse(record, response, { choices: [{
400
+ startMessage(record, response);
401
+ writeSse(record, response, {
402
+ type: "content_block_start",
403
+ index: 0,
404
+ content_block: {
405
+ type: "thinking",
406
+ thinking: ""
407
+ }
408
+ });
409
+ for (const chunk of splitText(options.reasoningText, options.chunkSize)) writeSse(record, response, {
410
+ type: "content_block_delta",
359
411
  index: 0,
360
- delta: { reasoning_content: chunk },
361
- finish_reason: null
362
- }] });
363
- await completeText(options, record, response, "stop", 0);
412
+ delta: {
413
+ type: "thinking_delta",
414
+ thinking: chunk
415
+ }
416
+ });
417
+ writeSse(record, response, {
418
+ type: "content_block_stop",
419
+ index: 0
420
+ });
421
+ await completeText(options, record, response, "end_turn", 0, 1);
364
422
  return;
365
423
  case "tool_call_success":
366
424
  openSse(response);
425
+ startMessage(record, response);
367
426
  for (const chunk of toolCallChunks(options)) writeSse(record, response, chunk);
368
- writeSse(record, response, terminalChunk("tool_calls", 2));
427
+ writeSse(record, response, terminalChunk("tool_use", 2));
369
428
  writeDone(record, response);
370
429
  response.end();
371
430
  finishRecord(options, record, "completed");
372
431
  return;
373
432
  case "max_tokens":
374
433
  openSse(response);
375
- await completeText(options, record, response, "length", 0);
434
+ startMessage(record, response);
435
+ await completeText(options, record, response, "max_tokens", 0);
376
436
  return;
377
437
  case "slow_success":
378
438
  openSse(response);
379
- await completeText(options, record, response, "stop", options.chunkDelayMs);
439
+ startMessage(record, response);
440
+ await completeText(options, record, response, "end_turn", options.chunkDelayMs);
380
441
  return;
381
442
  }
382
443
  }
@@ -401,9 +462,9 @@ function chooseRandomBehavior(weights, random) {
401
462
  return weights.at(-1)[0];
402
463
  }
403
464
  /**
404
- * Start a local chat-completions server that consumes one configured behavior
405
- * per accepted request. Only a `POST` path ending in `/chat/completions` consumes the script;
406
- * invalid routes, methods, authorization, and JSON receive ordinary 4xx
465
+ * Start a local Messages server that consumes one configured behavior
466
+ * per accepted request. Only a `POST` path ending in `/v1/messages` consumes the script;
467
+ * invalid routes, methods, API keys, and JSON receive ordinary 4xx
407
468
  * responses. Closing the handle terminates stalled connections.
408
469
  *
409
470
  * @param options - listener, script, response content, timing, and telemetry options.
@@ -430,14 +491,14 @@ async function startMockLlmServer(options) {
430
491
  response.writeHead(405, { allow: "POST" }).end();
431
492
  return;
432
493
  }
433
- if (!path.endsWith("/chat/completions")) {
494
+ if (!path.endsWith("/v1/messages")) {
434
495
  response.writeHead(404).end();
435
496
  return;
436
497
  }
437
- if (resolved.apiKey !== void 0 && request.headers.authorization !== `Bearer ${resolved.apiKey}`) {
498
+ if (resolved.apiKey !== void 0 && request.headers["x-api-key"] !== resolved.apiKey) {
438
499
  response.writeHead(401, { "content-type": "application/json" });
439
500
  response.end(JSON.stringify({ error: {
440
- message: "invalid mock bearer token",
501
+ message: "invalid mock API key",
441
502
  code: "invalid_api_key"
442
503
  } }));
443
504
  return;
@@ -1,6 +1,6 @@
1
1
  /**
2
- * Scriptable OpenAI-compatible HTTP/SSE server for transport, protocol, and
3
- * semantic-empty LLM recovery tests. Each accepted chat-completions request
2
+ * Scriptable Messages HTTP/SSE server for transport, protocol, and
3
+ * semantic-empty LLM recovery tests. Each accepted Messages request
4
4
  * consumes one behavior; the server never retries or interprets harness policy.
5
5
  *
6
6
  * @module @deepseek-ai/dsh-llm-mock-server
@@ -40,7 +40,7 @@ export type MockLlmServerEvent = {
40
40
  };
41
41
  /** Captured wire request and its final server-side outcome. */
42
42
  export interface MockLlmRequestRecord {
43
- /** One-based accepted chat-completions request number. */
43
+ /** One-based accepted Messages request number. */
44
44
  readonly attempt: number;
45
45
  /** Script entry consumed for this request before random resolution. */
46
46
  readonly scriptBehavior: MockLlmBehavior | 'script_exhausted';
@@ -63,7 +63,7 @@ export interface MockLlmServerOptions {
63
63
  readonly host?: string;
64
64
  /** TCP port; zero requests an OS-assigned port. */
65
65
  readonly port?: number;
66
- /** Optional exact bearer token; omission accepts any authorization header. */
66
+ /** Optional exact API key; omission accepts any x-api-key header. */
67
67
  readonly apiKey?: string;
68
68
  /** Ordered request behaviors; exhaustion fails loud unless `repeatLast` is true. */
69
69
  readonly sequence: readonly MockLlmBehavior[];
@@ -98,7 +98,7 @@ export interface MockLlmServerOptions {
98
98
  }
99
99
  /** Running mock server and captured request state. */
100
100
  export interface MockLlmServer {
101
- /** Base URL without `/v1`; both root and `/v1` chat-completions paths are accepted. */
101
+ /** Base URL without `/v1`; the endpoint is `/v1/messages`. */
102
102
  readonly baseURL: string;
103
103
  /** Actual bound port, including an OS-assigned value. */
104
104
  readonly port: number;
@@ -110,9 +110,9 @@ export interface MockLlmServer {
110
110
  close(): Promise<void>;
111
111
  }
112
112
  /**
113
- * Start a local chat-completions server that consumes one configured behavior
114
- * per accepted request. Only a `POST` path ending in `/chat/completions` consumes the script;
115
- * invalid routes, methods, authorization, and JSON receive ordinary 4xx
113
+ * Start a local Messages server that consumes one configured behavior
114
+ * per accepted request. Only a `POST` path ending in `/v1/messages` consumes the script;
115
+ * invalid routes, methods, API keys, and JSON receive ordinary 4xx
116
116
  * responses. Closing the handle terminates stalled connections.
117
117
  *
118
118
  * @param options - listener, script, response content, timing, and telemetry options.
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@deepseek-ai/dsh-llm-mock-server",
3
- "description": "Scriptable OpenAI-compatible HTTP/SSE fault server for LLM recovery tests",
4
- "version": "0.1.6-alpha.2",
3
+ "description": "Scriptable Messages HTTP/SSE fault server for LLM recovery tests",
4
+ "version": "0.1.7-alpha.1",
5
5
  "publishConfig": {
6
6
  "access": "public"
7
7
  },
@@ -27,9 +27,9 @@
27
27
  ],
28
28
  "license": "MIT",
29
29
  "peerDependencies": {
30
- "@deepseek-ai/cordis": "^4.0.2"
30
+ "@deepseek-ai/cordis": "^4.0.3"
31
31
  },
32
32
  "devDependencies": {
33
- "@deepseek-ai/cordis": "^4.0.2"
33
+ "@deepseek-ai/cordis": "^4.0.3"
34
34
  }
35
35
  }