llm-mock-server 1.0.5 → 1.0.7
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.md +1 -1
- package/dist/cli/cli.d.ts +3 -0
- package/dist/cli/cli.d.ts.map +1 -0
- package/dist/cli/cli.js +103 -0
- package/dist/cli/cli.js.map +1 -0
- package/dist/cli/validators.d.ts +7 -0
- package/dist/cli/validators.d.ts.map +1 -0
- package/dist/cli/validators.js +53 -0
- package/dist/cli/validators.js.map +1 -0
- package/dist/formats/anthropic/index.d.ts +1 -1
- package/dist/formats/anthropic/index.d.ts.map +1 -1
- package/dist/formats/anthropic/index.js +1 -1
- package/dist/formats/anthropic/index.js.map +1 -1
- package/dist/formats/anthropic/parse.d.ts +2 -2
- package/dist/formats/anthropic/parse.d.ts.map +1 -1
- package/dist/formats/anthropic/parse.js +4 -2
- package/dist/formats/anthropic/parse.js.map +1 -1
- package/dist/formats/anthropic/schema.d.ts +1 -1
- package/dist/formats/anthropic/schema.d.ts.map +1 -1
- package/dist/formats/anthropic/schema.js +9 -4
- package/dist/formats/anthropic/schema.js.map +1 -1
- package/dist/formats/anthropic/serialize.d.ts +2 -2
- package/dist/formats/anthropic/serialize.d.ts.map +1 -1
- package/dist/formats/anthropic/serialize.js +76 -19
- package/dist/formats/anthropic/serialize.js.map +1 -1
- package/dist/formats/openai/chat-completions/index.d.ts +3 -0
- package/dist/formats/openai/chat-completions/index.d.ts.map +1 -0
- package/dist/formats/openai/chat-completions/index.js +13 -0
- package/dist/formats/openai/chat-completions/index.js.map +1 -0
- package/dist/formats/openai/chat-completions/parse.d.ts +4 -0
- package/dist/formats/openai/chat-completions/parse.d.ts.map +1 -0
- package/dist/formats/openai/chat-completions/parse.js +33 -0
- package/dist/formats/openai/chat-completions/parse.js.map +1 -0
- package/dist/formats/openai/chat-completions/schema.d.ts +93 -0
- package/dist/formats/openai/chat-completions/schema.d.ts.map +1 -0
- package/dist/formats/openai/chat-completions/schema.js +74 -0
- package/dist/formats/openai/chat-completions/schema.js.map +1 -0
- package/dist/formats/openai/chat-completions/serialize.d.ts +10 -0
- package/dist/formats/openai/chat-completions/serialize.d.ts.map +1 -0
- package/dist/formats/openai/chat-completions/serialize.js +99 -0
- package/dist/formats/openai/chat-completions/serialize.js.map +1 -0
- package/dist/formats/openai/responses/index.d.ts +3 -0
- package/dist/formats/openai/responses/index.d.ts.map +1 -0
- package/dist/formats/openai/responses/index.js +13 -0
- package/dist/formats/openai/responses/index.js.map +1 -0
- package/dist/formats/openai/responses/parse.d.ts +4 -0
- package/dist/formats/openai/responses/parse.d.ts.map +1 -0
- package/dist/formats/openai/responses/parse.js +51 -0
- package/dist/formats/openai/responses/parse.js.map +1 -0
- package/dist/formats/openai/responses/schema.d.ts +103 -0
- package/dist/formats/openai/responses/schema.d.ts.map +1 -0
- package/dist/formats/openai/responses/schema.js +71 -0
- package/dist/formats/openai/responses/schema.js.map +1 -0
- package/dist/formats/openai/responses/serialize.d.ts +10 -0
- package/dist/formats/openai/responses/serialize.d.ts.map +1 -0
- package/dist/formats/openai/responses/serialize.js +273 -0
- package/dist/formats/openai/responses/serialize.js.map +1 -0
- package/dist/formats/request-helpers.d.ts +1 -1
- package/dist/formats/request-helpers.d.ts.map +1 -1
- package/dist/formats/request-helpers.js.map +1 -1
- package/dist/formats/serialize-helpers.d.ts +1 -1
- package/dist/formats/serialize-helpers.d.ts.map +1 -1
- package/dist/formats/serialize-helpers.js +6 -3
- package/dist/formats/serialize-helpers.js.map +1 -1
- package/dist/formats/types.d.ts +2 -1
- package/dist/formats/types.d.ts.map +1 -1
- package/dist/history.d.ts +6 -2
- package/dist/history.d.ts.map +1 -1
- package/dist/history.js +2 -0
- package/dist/history.js.map +1 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js.map +1 -1
- package/dist/loader.d.ts +1 -1
- package/dist/loader.d.ts.map +1 -1
- package/dist/loader.js +26 -9
- package/dist/loader.js.map +1 -1
- package/dist/logger.d.ts.map +1 -1
- package/dist/logger.js +12 -4
- package/dist/logger.js.map +1 -1
- package/dist/mock-server.d.ts +44 -48
- package/dist/mock-server.d.ts.map +1 -1
- package/dist/mock-server.js +37 -85
- package/dist/mock-server.js.map +1 -1
- package/dist/route-handler.d.ts +1 -1
- package/dist/route-handler.d.ts.map +1 -1
- package/dist/route-handler.js +19 -7
- package/dist/route-handler.js.map +1 -1
- package/dist/rule-builder.d.ts +21 -0
- package/dist/rule-builder.d.ts.map +1 -0
- package/dist/rule-builder.js +58 -0
- package/dist/rule-builder.js.map +1 -0
- package/dist/rule-engine.d.ts +3 -1
- package/dist/rule-engine.d.ts.map +1 -1
- package/dist/rule-engine.js +7 -2
- package/dist/rule-engine.js.map +1 -1
- package/dist/sse-writer.d.ts +1 -1
- package/dist/sse-writer.d.ts.map +1 -1
- package/dist/types/reply.d.ts +51 -8
- package/dist/types/reply.d.ts.map +1 -1
- package/dist/types/request.d.ts +21 -6
- package/dist/types/request.d.ts.map +1 -1
- package/dist/types/rule.d.ts +65 -7
- package/dist/types/rule.d.ts.map +1 -1
- package/dist/types.d.ts +3 -3
- package/dist/types.d.ts.map +1 -1
- package/package.json +20 -11
- package/.claude/skills/desloppify/SKILL.md +0 -308
- package/.desloppify/external_review_sessions/ext_20260315_000339_a6cdc3e6/canonical_import_20260315_000801.json +0 -242
- package/.desloppify/external_review_sessions/ext_20260315_000339_a6cdc3e6/canonical_import_20260315_000905.json +0 -248
- package/.desloppify/external_review_sessions/ext_20260315_000339_a6cdc3e6/canonical_import_20260315_000917.json +0 -248
- package/.desloppify/external_review_sessions/ext_20260315_000339_a6cdc3e6/canonical_import_20260315_000950.json +0 -311
- package/.desloppify/external_review_sessions/ext_20260315_000339_a6cdc3e6/claude_launch_prompt.md +0 -17
- package/.desloppify/external_review_sessions/ext_20260315_000339_a6cdc3e6/review_result.json +0 -255
- package/.desloppify/external_review_sessions/ext_20260315_000339_a6cdc3e6/review_result.template.json +0 -22
- package/.desloppify/external_review_sessions/ext_20260315_000339_a6cdc3e6/reviewer_instructions.md +0 -20
- package/.desloppify/external_review_sessions/ext_20260315_000339_a6cdc3e6/session.json +0 -20
- package/.desloppify/external_review_sessions/ext_20260315_045546_0587ea3b/canonical_import_20260315_050000.json +0 -286
- package/.desloppify/external_review_sessions/ext_20260315_045546_0587ea3b/canonical_import_20260315_050028.json +0 -303
- package/.desloppify/external_review_sessions/ext_20260315_045546_0587ea3b/claude_launch_prompt.md +0 -17
- package/.desloppify/external_review_sessions/ext_20260315_045546_0587ea3b/review_result.json +0 -297
- package/.desloppify/external_review_sessions/ext_20260315_045546_0587ea3b/review_result.template.json +0 -22
- package/.desloppify/external_review_sessions/ext_20260315_045546_0587ea3b/reviewer_instructions.md +0 -20
- package/.desloppify/external_review_sessions/ext_20260315_045546_0587ea3b/session.json +0 -20
- package/.desloppify/query.json +0 -1312
- package/.desloppify/review_packet_blind.json +0 -1249
- package/.desloppify/review_packets/holistic_packet_20260315_000339.json +0 -1471
- package/.desloppify/review_packets/holistic_packet_20260315_045546.json +0 -1480
- package/.desloppify/review_packets/holistic_packet_20260315_185401.json +0 -1407
- package/.desloppify/review_packets/holistic_packet_20260315_185613.json +0 -1407
- package/.desloppify/state-typescript.json +0 -8438
- package/.desloppify/state-typescript.json.bak +0 -8432
- package/.desloppify/subagents/runs/20260315_185401/logs/batch-1.log +0 -384
- package/.desloppify/subagents/runs/20260315_185401/logs/batch-10.log +0 -484
- package/.desloppify/subagents/runs/20260315_185401/logs/batch-2.log +0 -408
- package/.desloppify/subagents/runs/20260315_185401/logs/batch-3.log +0 -416
- package/.desloppify/subagents/runs/20260315_185401/logs/batch-4.log +0 -360
- package/.desloppify/subagents/runs/20260315_185401/logs/batch-5.log +0 -360
- package/.desloppify/subagents/runs/20260315_185401/logs/batch-6.log +0 -364
- package/.desloppify/subagents/runs/20260315_185401/logs/batch-7.log +0 -428
- package/.desloppify/subagents/runs/20260315_185401/logs/batch-8.log +0 -388
- package/.desloppify/subagents/runs/20260315_185401/logs/batch-9.log +0 -500
- package/.desloppify/subagents/runs/20260315_185401/prompts/batch-1.md +0 -83
- package/.desloppify/subagents/runs/20260315_185401/prompts/batch-10.md +0 -108
- package/.desloppify/subagents/runs/20260315_185401/prompts/batch-2.md +0 -89
- package/.desloppify/subagents/runs/20260315_185401/prompts/batch-3.md +0 -91
- package/.desloppify/subagents/runs/20260315_185401/prompts/batch-4.md +0 -77
- package/.desloppify/subagents/runs/20260315_185401/prompts/batch-5.md +0 -77
- package/.desloppify/subagents/runs/20260315_185401/prompts/batch-6.md +0 -78
- package/.desloppify/subagents/runs/20260315_185401/prompts/batch-7.md +0 -94
- package/.desloppify/subagents/runs/20260315_185401/prompts/batch-8.md +0 -84
- package/.desloppify/subagents/runs/20260315_185401/prompts/batch-9.md +0 -112
- package/.desloppify/subagents/runs/20260315_185401/results/batch-1.raw.txt +0 -0
- package/.desloppify/subagents/runs/20260315_185401/results/batch-10.raw.txt +0 -0
- package/.desloppify/subagents/runs/20260315_185401/results/batch-2.raw.txt +0 -0
- package/.desloppify/subagents/runs/20260315_185401/results/batch-3.raw.txt +0 -0
- package/.desloppify/subagents/runs/20260315_185401/results/batch-4.raw.txt +0 -0
- package/.desloppify/subagents/runs/20260315_185401/results/batch-5.raw.txt +0 -0
- package/.desloppify/subagents/runs/20260315_185401/results/batch-6.raw.txt +0 -0
- package/.desloppify/subagents/runs/20260315_185401/results/batch-7.raw.txt +0 -0
- package/.desloppify/subagents/runs/20260315_185401/results/batch-8.raw.txt +0 -0
- package/.desloppify/subagents/runs/20260315_185401/results/batch-9.raw.txt +0 -0
- package/.desloppify/subagents/runs/20260315_185401/run.log +0 -36
- package/.desloppify/subagents/runs/20260315_185401/run_summary.json +0 -156
- package/.desloppify/subagents/runs/20260315_185613/holistic_findings_merged.json +0 -741
- package/.desloppify/subagents/runs/20260315_185613/logs/batch-1.log +0 -579
- package/.desloppify/subagents/runs/20260315_185613/logs/batch-10.log +0 -1537
- package/.desloppify/subagents/runs/20260315_185613/logs/batch-2.log +0 -829
- package/.desloppify/subagents/runs/20260315_185613/logs/batch-3.log +0 -927
- package/.desloppify/subagents/runs/20260315_185613/logs/batch-4.log +0 -429
- package/.desloppify/subagents/runs/20260315_185613/logs/batch-5.log +0 -276
- package/.desloppify/subagents/runs/20260315_185613/logs/batch-6.log +0 -450
- package/.desloppify/subagents/runs/20260315_185613/logs/batch-7.log +0 -730
- package/.desloppify/subagents/runs/20260315_185613/logs/batch-8.log +0 -698
- package/.desloppify/subagents/runs/20260315_185613/logs/batch-9.log +0 -938
- package/.desloppify/subagents/runs/20260315_185613/prompts/batch-1.md +0 -83
- package/.desloppify/subagents/runs/20260315_185613/prompts/batch-10.md +0 -108
- package/.desloppify/subagents/runs/20260315_185613/prompts/batch-2.md +0 -89
- package/.desloppify/subagents/runs/20260315_185613/prompts/batch-3.md +0 -91
- package/.desloppify/subagents/runs/20260315_185613/prompts/batch-4.md +0 -77
- package/.desloppify/subagents/runs/20260315_185613/prompts/batch-5.md +0 -77
- package/.desloppify/subagents/runs/20260315_185613/prompts/batch-6.md +0 -78
- package/.desloppify/subagents/runs/20260315_185613/prompts/batch-7.md +0 -94
- package/.desloppify/subagents/runs/20260315_185613/prompts/batch-8.md +0 -84
- package/.desloppify/subagents/runs/20260315_185613/prompts/batch-9.md +0 -112
- package/.desloppify/subagents/runs/20260315_185613/results/batch-1.raw.txt +0 -78
- package/.desloppify/subagents/runs/20260315_185613/results/batch-10.raw.txt +0 -242
- package/.desloppify/subagents/runs/20260315_185613/results/batch-2.raw.txt +0 -102
- package/.desloppify/subagents/runs/20260315_185613/results/batch-3.raw.txt +0 -94
- package/.desloppify/subagents/runs/20260315_185613/results/batch-4.raw.txt +0 -86
- package/.desloppify/subagents/runs/20260315_185613/results/batch-5.raw.txt +0 -1
- package/.desloppify/subagents/runs/20260315_185613/results/batch-6.raw.txt +0 -87
- package/.desloppify/subagents/runs/20260315_185613/results/batch-7.raw.txt +0 -1
- package/.desloppify/subagents/runs/20260315_185613/results/batch-8.raw.txt +0 -107
- package/.desloppify/subagents/runs/20260315_185613/results/batch-9.raw.txt +0 -67
- package/.desloppify/subagents/runs/20260315_185613/run.log +0 -96
- package/.desloppify/subagents/runs/20260315_185613/run_summary.json +0 -156
- package/.editorconfig +0 -12
- package/.github/dependabot.yml +0 -11
- package/.github/workflows/docs.yml +0 -46
- package/.github/workflows/test.yml +0 -40
- package/.markdownlint.jsonc +0 -11
- package/.node-version +0 -1
- package/.oxfmtrc.json +0 -9
- package/.oxlintrc.json +0 -35
- package/docs/ARCHITECTURE.md +0 -125
- package/scorecard.png +0 -0
- package/src/cli/cli.ts +0 -141
- package/src/cli/validators.ts +0 -68
- package/src/formats/anthropic/index.ts +0 -14
- package/src/formats/anthropic/parse.ts +0 -67
- package/src/formats/anthropic/schema.ts +0 -74
- package/src/formats/anthropic/serialize.ts +0 -179
- package/src/formats/openai/chat-completions/index.ts +0 -14
- package/src/formats/openai/chat-completions/parse.ts +0 -44
- package/src/formats/openai/chat-completions/schema.ts +0 -92
- package/src/formats/openai/chat-completions/serialize.ts +0 -146
- package/src/formats/openai/responses/index.ts +0 -14
- package/src/formats/openai/responses/parse.ts +0 -70
- package/src/formats/openai/responses/schema.ts +0 -86
- package/src/formats/openai/responses/serialize.ts +0 -332
- package/src/formats/request-helpers.ts +0 -56
- package/src/formats/serialize-helpers.ts +0 -43
- package/src/formats/types.ts +0 -26
- package/src/history.ts +0 -70
- package/src/index.ts +0 -46
- package/src/loader.ts +0 -246
- package/src/logger.ts +0 -70
- package/src/mock-server.ts +0 -203
- package/src/route-handler.ts +0 -144
- package/src/rule-builder.ts +0 -73
- package/src/rule-engine.ts +0 -165
- package/src/sse-writer.ts +0 -35
- package/src/types/reply.ts +0 -92
- package/src/types/request.ts +0 -56
- package/src/types/rule.ts +0 -125
- package/src/types.ts +0 -24
- package/test/cli-validators.test.ts +0 -151
- package/test/formats/anthropic.test.ts +0 -336
- package/test/formats/openai.test.ts +0 -316
- package/test/formats/parse-helpers.test.ts +0 -315
- package/test/formats/responses.test.ts +0 -380
- package/test/helpers/make-req.ts +0 -18
- package/test/history.test.ts +0 -361
- package/test/loader.test.ts +0 -333
- package/test/logger.test.ts +0 -344
- package/test/mock-server.test.ts +0 -619
- package/test/rule-engine.test.ts +0 -229
- package/tsconfig.json +0 -26
- package/tsconfig.test.json +0 -11
- package/typedoc.json +0 -9
- package/vitest.config.ts +0 -18
package/dist/mock-server.d.ts
CHANGED
|
@@ -1,19 +1,39 @@
|
|
|
1
|
-
import type {
|
|
1
|
+
import type { Reply } from "./types/reply.js";
|
|
2
|
+
import type { RuleSummary } from "./types/rule.js";
|
|
3
|
+
import { RuleBuilder } from "./rule-builder.js";
|
|
2
4
|
import { RequestHistory } from "./history.js";
|
|
3
5
|
import type { LogLevel } from "./logger.js";
|
|
6
|
+
/** Options for constructing a `MockServer` or calling `createMock()`. */
|
|
4
7
|
export interface MockServerOptions {
|
|
8
|
+
/**
|
|
9
|
+
* Port to listen on. Pass `0` for a random port (useful in tests).
|
|
10
|
+
* @defaultValue `0`
|
|
11
|
+
*/
|
|
5
12
|
readonly port?: number;
|
|
6
|
-
/**
|
|
13
|
+
/**
|
|
14
|
+
* Host to bind to. Set to `"0.0.0.0"` to listen on all interfaces.
|
|
15
|
+
* @defaultValue `"127.0.0.1"`
|
|
16
|
+
*/
|
|
7
17
|
readonly host?: string;
|
|
8
|
-
/**
|
|
18
|
+
/**
|
|
19
|
+
* Log verbosity.
|
|
20
|
+
* @defaultValue `"none"`
|
|
21
|
+
*/
|
|
9
22
|
readonly logLevel?: LogLevel;
|
|
10
|
-
/**
|
|
23
|
+
/**
|
|
24
|
+
* Default ms delay between SSE chunks. Individual rules can override this.
|
|
25
|
+
* @defaultValue `0`
|
|
26
|
+
*/
|
|
11
27
|
readonly defaultLatency?: number;
|
|
12
|
-
/**
|
|
28
|
+
/**
|
|
29
|
+
* Default characters per SSE text chunk. Individual rules can override this.
|
|
30
|
+
* @defaultValue `0`
|
|
31
|
+
*/
|
|
13
32
|
readonly defaultChunkSize?: number;
|
|
14
33
|
}
|
|
34
|
+
type RuleAPI = Pick<RuleBuilder, "when" | "whenTool" | "whenToolResult" | "nextError">;
|
|
15
35
|
/**
|
|
16
|
-
* Mock LLM server that handles OpenAI, Anthropic, and Responses API formats.
|
|
36
|
+
* Mock LLM server that handles OpenAI Chat Completions, Anthropic Messages, and OpenAI Responses API formats.
|
|
17
37
|
* Register rules with `when()`, point your SDK at `url`, and go.
|
|
18
38
|
*
|
|
19
39
|
* Supports `await using` for automatic cleanup.
|
|
@@ -27,59 +47,29 @@ export interface MockServerOptions {
|
|
|
27
47
|
* await server.stop();
|
|
28
48
|
* ```
|
|
29
49
|
*/
|
|
30
|
-
export declare class MockServer {
|
|
50
|
+
export declare class MockServer implements RuleAPI {
|
|
31
51
|
private readonly app;
|
|
32
52
|
private readonly engine;
|
|
53
|
+
private readonly rules_;
|
|
33
54
|
private readonly history_;
|
|
34
55
|
private readonly logger;
|
|
35
56
|
private readonly host;
|
|
36
57
|
private readonly defaultOptions;
|
|
37
58
|
private fallbackReply;
|
|
38
59
|
private listening;
|
|
60
|
+
/** Register a matching rule. Call `.reply()` on the result to set the response. */
|
|
61
|
+
when: (match: import("./types/rule.js").Match) => import("./types/rule.js").PendingRule;
|
|
62
|
+
/** Shorthand for `when({ toolName })`. */
|
|
63
|
+
whenTool: (toolName: string) => import("./types/rule.js").PendingRule;
|
|
64
|
+
/** Shorthand for `when({ toolCallId })`. */
|
|
65
|
+
whenToolResult: (toolCallId: string) => import("./types/rule.js").PendingRule;
|
|
66
|
+
/** Queue a one-shot error for the very next request. Fires once then removes itself. */
|
|
67
|
+
nextError: (status: number, message: string, type?: string) => import("./types/rule.js").RuleHandle;
|
|
39
68
|
constructor(options?: MockServerOptions);
|
|
40
69
|
/**
|
|
41
|
-
*
|
|
42
|
-
*
|
|
43
|
-
* @example
|
|
44
|
-
* ```ts
|
|
45
|
-
* server.when("hello").reply("Hi!");
|
|
46
|
-
* server.when(/explain (\w+)/i).reply((req) => `Let me explain ${req.lastMessage}`);
|
|
47
|
-
* server.when({ model: /claude/ }).reply("I'm Claude.");
|
|
48
|
-
* ```
|
|
49
|
-
*/
|
|
50
|
-
when(match: Match): PendingRule;
|
|
51
|
-
/**
|
|
52
|
-
* Register a rule that matches when the request includes a tool with this name.
|
|
53
|
-
*
|
|
54
|
-
* @example
|
|
55
|
-
* ```ts
|
|
56
|
-
* server.whenTool("get_weather").reply({
|
|
57
|
-
* tools: [{ name: "get_weather", args: { location: "London" } }],
|
|
58
|
-
* });
|
|
59
|
-
* ```
|
|
60
|
-
*/
|
|
61
|
-
whenTool(toolName: string): PendingRule;
|
|
62
|
-
/**
|
|
63
|
-
* Register a rule that matches when the last message is a tool result with this call ID.
|
|
64
|
-
*
|
|
65
|
-
* @example
|
|
66
|
-
* ```ts
|
|
67
|
-
* server.whenToolResult("call_abc").reply("Got your result, cheers!");
|
|
68
|
-
* ```
|
|
69
|
-
*/
|
|
70
|
-
whenToolResult(toolCallId: string): PendingRule;
|
|
71
|
-
/**
|
|
72
|
-
* Queue a one-shot error for the very next request, regardless of content.
|
|
73
|
-
* Fires once then removes itself.
|
|
74
|
-
*
|
|
75
|
-
* @example
|
|
76
|
-
* ```ts
|
|
77
|
-
* server.nextError(429, "Rate limited");
|
|
78
|
-
* // next request gets a 429, after that normal matching resumes
|
|
79
|
-
* ```
|
|
70
|
+
* Set the reply used when no rule matches.
|
|
71
|
+
* @defaultValue `"Mock server: no matching rule."`
|
|
80
72
|
*/
|
|
81
|
-
nextError(status: number, message: string, type?: string): RuleHandle;
|
|
82
|
-
/** Set the reply used when no rule matches. Defaults to a generic message. */
|
|
83
73
|
fallback(reply: Reply): void;
|
|
84
74
|
/** Load rules from a `.json5` file, a `.ts`/`.js` handler file, or a directory containing them. */
|
|
85
75
|
load(pathOrDir: string): Promise<void>;
|
|
@@ -91,12 +81,18 @@ export declare class MockServer {
|
|
|
91
81
|
reset(): void;
|
|
92
82
|
/** The base URL the server is listening on, e.g. `http://127.0.0.1:12345`. Throws if the server hasn't started. */
|
|
93
83
|
get url(): string;
|
|
84
|
+
/** The API routes registered on this server, e.g. `["/v1/chat/completions", ...]`. */
|
|
85
|
+
get routes(): readonly string[];
|
|
86
|
+
/** Number of currently registered rules. */
|
|
94
87
|
get ruleCount(): number;
|
|
95
88
|
/** A snapshot of all registered rules with their descriptions and remaining match counts. */
|
|
96
89
|
get rules(): readonly RuleSummary[];
|
|
97
90
|
/** Start listening. Pass `0` (the default) for a random port. */
|
|
98
91
|
start(port?: number): Promise<void>;
|
|
92
|
+
/** Stop the server. Safe to call multiple times. */
|
|
99
93
|
stop(): Promise<void>;
|
|
94
|
+
/** Calls `stop()`. Enables `await using server = ...` for automatic cleanup. */
|
|
100
95
|
[Symbol.asyncDispose](): Promise<void>;
|
|
101
96
|
}
|
|
97
|
+
export {};
|
|
102
98
|
//# sourceMappingURL=mock-server.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"mock-server.d.ts","sourceRoot":"","sources":["../src/mock-server.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,
|
|
1
|
+
{"version":3,"file":"mock-server.d.ts","sourceRoot":"","sources":["../src/mock-server.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,KAAK,EAAgB,MAAM,kBAAkB,CAAC;AAC5D,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,iBAAiB,CAAC;AAEnD,OAAO,EAAE,WAAW,EAAE,MAAM,mBAAmB,CAAC;AAChD,OAAO,EAAE,cAAc,EAAE,MAAM,cAAc,CAAC;AAM9C,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,aAAa,CAAC;AAS5C,yEAAyE;AACzE,MAAM,WAAW,iBAAiB;IAChC;;;OAGG;IACH,QAAQ,CAAC,IAAI,CAAC,EAAE,MAAM,CAAC;IACvB;;;OAGG;IACH,QAAQ,CAAC,IAAI,CAAC,EAAE,MAAM,CAAC;IACvB;;;OAGG;IACH,QAAQ,CAAC,QAAQ,CAAC,EAAE,QAAQ,CAAC;IAC7B;;;OAGG;IACH,QAAQ,CAAC,cAAc,CAAC,EAAE,MAAM,CAAC;IACjC;;;OAGG;IACH,QAAQ,CAAC,gBAAgB,CAAC,EAAE,MAAM,CAAC;CACpC;AAED,KAAK,OAAO,GAAG,IAAI,CACjB,WAAW,EACX,MAAM,GAAG,UAAU,GAAG,gBAAgB,GAAG,WAAW,CACrD,CAAC;AAEF;;;;;;;;;;;;;;GAcG;AACH,qBAAa,UAAW,YAAW,OAAO;IACxC,OAAO,CAAC,QAAQ,CAAC,GAAG,CAAkB;IACtC,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAoB;IAC3C,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAgC;IACvD,OAAO,CAAC,QAAQ,CAAC,QAAQ,CAAwB;IACjD,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAS;IAChC,OAAO,CAAC,QAAQ,CAAC,IAAI,CAAS;IAC9B,OAAO,CAAC,QAAQ,CAAC,cAAc,CAAe;IAC9C,OAAO,CAAC,aAAa,CAA2C;IAChE,OAAO,CAAC,SAAS,CAAS;IAE1B,mFAAmF;IACnF,IAAI,oFAAsC;IAC1C,0CAA0C;IAC1C,QAAQ,8DAA0C;IAClD,4CAA4C;IAC5C,cAAc,gEAAgD;IAC9D,wFAAwF;IACxF,SAAS,2FAA2C;gBAExC,OAAO,GAAE,iBAAsB;IA0B3C;;;OAGG;IACH,QAAQ,CAAC,KAAK,EAAE,KAAK,GAAG,IAAI;IAI5B,mGAAmG;IAC7F,IAAI,CAAC,SAAS,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAe5C,4CAA4C;IAC5C,IAAI,OAAO,IAAI,cAAc,CAE5B;IAED,gFAAgF;IAChF,MAAM,IAAI,OAAO;IAIjB,+EAA+E;IAC/E,KAAK,IAAI,IAAI;IAOb,mHAAmH;IACnH,IAAI,GAAG,IAAI,MAAM,CAMhB;IAED,sFAAsF;IACtF,IAAI,MAAM,IAAI,SAAS,MAAM,EAAE,CAE9B;IAED,4CAA4C;IAC5C,IAAI,SAAS,IAAI,MAAM,CAEtB;IAED,6FAA6F;IAC7F,IAAI,KAAK,IAAI,SAAS,WAAW,EAAE,CAElC;IAED,iEAAiE;IAC3D,KAAK,CAAC,IAAI,SAAI,GAAG,OAAO,CAAC,IAAI,CAAC;IAOpC,oDAAoD;IAC9C,IAAI,IAAI,OAAO,CAAC,IAAI,CAAC;IAO3B,gFAAgF;IAC1E,CAAC,MAAM,CAAC,YAAY,CAAC,IAAI,OAAO,CAAC,IAAI,CAAC;CAG7C"}
|
package/dist/mock-server.js
CHANGED
|
@@ -1,14 +1,19 @@
|
|
|
1
1
|
import Fastify from "fastify";
|
|
2
|
-
import { RuleEngine
|
|
2
|
+
import { RuleEngine } from "./rule-engine.js";
|
|
3
|
+
import { RuleBuilder } from "./rule-builder.js";
|
|
3
4
|
import { RequestHistory } from "./history.js";
|
|
4
|
-
import {
|
|
5
|
+
import { chatCompletionsFormat } from "./formats/openai/chat-completions/index.js";
|
|
5
6
|
import { anthropicFormat } from "./formats/anthropic/index.js";
|
|
6
|
-
import { responsesFormat } from "./formats/responses/index.js";
|
|
7
|
+
import { responsesFormat } from "./formats/openai/responses/index.js";
|
|
7
8
|
import { Logger } from "./logger.js";
|
|
8
9
|
import { createRouteHandler } from "./route-handler.js";
|
|
9
|
-
const formats = [
|
|
10
|
+
const formats = [
|
|
11
|
+
chatCompletionsFormat,
|
|
12
|
+
anthropicFormat,
|
|
13
|
+
responsesFormat,
|
|
14
|
+
];
|
|
10
15
|
/**
|
|
11
|
-
* Mock LLM server that handles OpenAI, Anthropic, and Responses API formats.
|
|
16
|
+
* Mock LLM server that handles OpenAI Chat Completions, Anthropic Messages, and OpenAI Responses API formats.
|
|
12
17
|
* Register rules with `when()`, point your SDK at `url`, and go.
|
|
13
18
|
*
|
|
14
19
|
* Supports `await using` for automatic cleanup.
|
|
@@ -25,18 +30,31 @@ const formats = [openaiFormat, anthropicFormat, responsesFormat];
|
|
|
25
30
|
export class MockServer {
|
|
26
31
|
app;
|
|
27
32
|
engine = new RuleEngine();
|
|
33
|
+
rules_ = new RuleBuilder(this.engine);
|
|
28
34
|
history_ = new RequestHistory();
|
|
29
35
|
logger;
|
|
30
36
|
host;
|
|
31
37
|
defaultOptions;
|
|
32
38
|
fallbackReply = "Mock server: no matching rule.";
|
|
33
39
|
listening = false;
|
|
40
|
+
/** Register a matching rule. Call `.reply()` on the result to set the response. */
|
|
41
|
+
when = this.rules_.when.bind(this.rules_);
|
|
42
|
+
/** Shorthand for `when({ toolName })`. */
|
|
43
|
+
whenTool = this.rules_.whenTool.bind(this.rules_);
|
|
44
|
+
/** Shorthand for `when({ toolCallId })`. */
|
|
45
|
+
whenToolResult = this.rules_.whenToolResult.bind(this.rules_);
|
|
46
|
+
/** Queue a one-shot error for the very next request. Fires once then removes itself. */
|
|
47
|
+
nextError = this.rules_.nextError.bind(this.rules_);
|
|
34
48
|
constructor(options = {}) {
|
|
35
49
|
this.host = options.host ?? "127.0.0.1";
|
|
36
50
|
this.logger = new Logger(options.logLevel ?? "none");
|
|
37
51
|
this.defaultOptions = {
|
|
38
|
-
...(options.defaultLatency !== undefined && {
|
|
39
|
-
|
|
52
|
+
...(options.defaultLatency !== undefined && {
|
|
53
|
+
latency: options.defaultLatency,
|
|
54
|
+
}),
|
|
55
|
+
...(options.defaultChunkSize !== undefined && {
|
|
56
|
+
chunkSize: options.defaultChunkSize,
|
|
57
|
+
}),
|
|
40
58
|
};
|
|
41
59
|
this.app = Fastify({ logger: false });
|
|
42
60
|
const deps = {
|
|
@@ -51,84 +69,9 @@ export class MockServer {
|
|
|
51
69
|
}
|
|
52
70
|
}
|
|
53
71
|
/**
|
|
54
|
-
*
|
|
55
|
-
*
|
|
56
|
-
* @example
|
|
57
|
-
* ```ts
|
|
58
|
-
* server.when("hello").reply("Hi!");
|
|
59
|
-
* server.when(/explain (\w+)/i).reply((req) => `Let me explain ${req.lastMessage}`);
|
|
60
|
-
* server.when({ model: /claude/ }).reply("I'm Claude.");
|
|
61
|
-
* ```
|
|
72
|
+
* Set the reply used when no rule matches.
|
|
73
|
+
* @defaultValue `"Mock server: no matching rule."`
|
|
62
74
|
*/
|
|
63
|
-
when(match) {
|
|
64
|
-
const engine = this.engine;
|
|
65
|
-
const makeHandle = (rule) => ({
|
|
66
|
-
times(n) {
|
|
67
|
-
rule.remaining = n;
|
|
68
|
-
return this;
|
|
69
|
-
},
|
|
70
|
-
first() {
|
|
71
|
-
engine.moveToFront(rule);
|
|
72
|
-
return this;
|
|
73
|
-
},
|
|
74
|
-
});
|
|
75
|
-
return {
|
|
76
|
-
reply(response, options) {
|
|
77
|
-
return makeHandle(engine.add(match, response, options));
|
|
78
|
-
},
|
|
79
|
-
replySequence(entries) {
|
|
80
|
-
const steps = entries.map((entry) => typeof entry === "string" || !("reply" in entry)
|
|
81
|
-
? { reply: entry }
|
|
82
|
-
: { reply: entry.reply, options: entry.options });
|
|
83
|
-
const rule = engine.add(match, "");
|
|
84
|
-
const { resolver, entryCount } = createSequenceResolver(steps, rule);
|
|
85
|
-
rule.resolve = resolver;
|
|
86
|
-
rule.remaining = entryCount;
|
|
87
|
-
return makeHandle(rule);
|
|
88
|
-
},
|
|
89
|
-
};
|
|
90
|
-
}
|
|
91
|
-
/**
|
|
92
|
-
* Register a rule that matches when the request includes a tool with this name.
|
|
93
|
-
*
|
|
94
|
-
* @example
|
|
95
|
-
* ```ts
|
|
96
|
-
* server.whenTool("get_weather").reply({
|
|
97
|
-
* tools: [{ name: "get_weather", args: { location: "London" } }],
|
|
98
|
-
* });
|
|
99
|
-
* ```
|
|
100
|
-
*/
|
|
101
|
-
whenTool(toolName) {
|
|
102
|
-
return this.when({ toolName });
|
|
103
|
-
}
|
|
104
|
-
/**
|
|
105
|
-
* Register a rule that matches when the last message is a tool result with this call ID.
|
|
106
|
-
*
|
|
107
|
-
* @example
|
|
108
|
-
* ```ts
|
|
109
|
-
* server.whenToolResult("call_abc").reply("Got your result, cheers!");
|
|
110
|
-
* ```
|
|
111
|
-
*/
|
|
112
|
-
whenToolResult(toolCallId) {
|
|
113
|
-
return this.when({ toolCallId });
|
|
114
|
-
}
|
|
115
|
-
/**
|
|
116
|
-
* Queue a one-shot error for the very next request, regardless of content.
|
|
117
|
-
* Fires once then removes itself.
|
|
118
|
-
*
|
|
119
|
-
* @example
|
|
120
|
-
* ```ts
|
|
121
|
-
* server.nextError(429, "Rate limited");
|
|
122
|
-
* // next request gets a 429, after that normal matching resumes
|
|
123
|
-
* ```
|
|
124
|
-
*/
|
|
125
|
-
nextError(status, message, type) {
|
|
126
|
-
return this.when(() => true)
|
|
127
|
-
.reply({ error: { status, message, type } })
|
|
128
|
-
.times(1)
|
|
129
|
-
.first();
|
|
130
|
-
}
|
|
131
|
-
/** Set the reply used when no rule matches. Defaults to a generic message. */
|
|
132
75
|
fallback(reply) {
|
|
133
76
|
this.fallbackReply = reply;
|
|
134
77
|
}
|
|
@@ -138,7 +81,9 @@ export class MockServer {
|
|
|
138
81
|
const { loadRulesFromPath } = await import("./loader.js");
|
|
139
82
|
await loadRulesFromPath(pathOrDir, {
|
|
140
83
|
engine: this.engine,
|
|
141
|
-
setFallback: (reply) => {
|
|
84
|
+
setFallback: (reply) => {
|
|
85
|
+
this.fallbackReply = reply;
|
|
86
|
+
},
|
|
142
87
|
});
|
|
143
88
|
const loaded = this.engine.ruleCount - before;
|
|
144
89
|
this.logger.info(`Loaded ${loaded} rule${loaded !== 1 ? "s" : ""} from ${pathOrDir}`);
|
|
@@ -166,6 +111,11 @@ export class MockServer {
|
|
|
166
111
|
const port = addr !== null && typeof addr === "object" ? addr.port : 0;
|
|
167
112
|
return `http://${this.host}:${port}`;
|
|
168
113
|
}
|
|
114
|
+
/** The API routes registered on this server, e.g. `["/v1/chat/completions", ...]`. */
|
|
115
|
+
get routes() {
|
|
116
|
+
return formats.map((f) => f.route);
|
|
117
|
+
}
|
|
118
|
+
/** Number of currently registered rules. */
|
|
169
119
|
get ruleCount() {
|
|
170
120
|
return this.engine.ruleCount;
|
|
171
121
|
}
|
|
@@ -181,6 +131,7 @@ export class MockServer {
|
|
|
181
131
|
this.listening = true;
|
|
182
132
|
this.logger.info(`Listening on ${this.url}`);
|
|
183
133
|
}
|
|
134
|
+
/** Stop the server. Safe to call multiple times. */
|
|
184
135
|
async stop() {
|
|
185
136
|
if (!this.listening)
|
|
186
137
|
return;
|
|
@@ -188,6 +139,7 @@ export class MockServer {
|
|
|
188
139
|
this.listening = false;
|
|
189
140
|
this.logger.info("Server stopped");
|
|
190
141
|
}
|
|
142
|
+
/** Calls `stop()`. Enables `await using server = ...` for automatic cleanup. */
|
|
191
143
|
async [Symbol.asyncDispose]() {
|
|
192
144
|
await this.stop();
|
|
193
145
|
}
|
package/dist/mock-server.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"mock-server.js","sourceRoot":"","sources":["../src/mock-server.ts"],"names":[],"mappings":"AAAA,OAAO,OAAO,MAAM,SAAS,CAAC;
|
|
1
|
+
{"version":3,"file":"mock-server.js","sourceRoot":"","sources":["../src/mock-server.ts"],"names":[],"mappings":"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"}
|
package/dist/route-handler.d.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import type { FastifyReply, FastifyRequest } from "fastify";
|
|
2
|
-
import type { Reply, ReplyOptions } from "./types.js";
|
|
2
|
+
import type { Reply, ReplyOptions } from "./types/reply.js";
|
|
3
3
|
import type { Format } from "./formats/types.js";
|
|
4
4
|
import type { RuleEngine } from "./rule-engine.js";
|
|
5
5
|
import type { RequestHistory } from "./history.js";
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"route-handler.d.ts","sourceRoot":"","sources":["../src/route-handler.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,YAAY,EAAE,cAAc,EAAE,MAAM,SAAS,CAAC;
|
|
1
|
+
{"version":3,"file":"route-handler.d.ts","sourceRoot":"","sources":["../src/route-handler.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,YAAY,EAAE,cAAc,EAAE,MAAM,SAAS,CAAC;AAG5D,OAAO,KAAK,EAAE,KAAK,EAAe,YAAY,EAAE,MAAM,kBAAkB,CAAC;AAEzE,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,oBAAoB,CAAC;AACjD,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,kBAAkB,CAAC;AACnD,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,cAAc,CAAC;AACnD,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,aAAa,CAAC;AAoC1C,UAAU,gBAAgB;IACxB,MAAM,EAAE,UAAU,CAAC;IACnB,OAAO,EAAE,cAAc,CAAC;IACxB,MAAM,EAAE,MAAM,CAAC;IACf,cAAc,EAAE,YAAY,CAAC;IAC7B,WAAW,EAAE,MAAM,KAAK,CAAC;CAC1B;AAED,wBAAgB,kBAAkB,CAChC,MAAM,EAAE,MAAM,EACd,IAAI,EAAE,gBAAgB,GACrB,CAAC,OAAO,EAAE,cAAc,EAAE,KAAK,EAAE,YAAY,KAAK,OAAO,CAAC,IAAI,CAAC,CAwFjE"}
|
package/dist/route-handler.js
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { ZodError } from "zod";
|
|
2
2
|
import { writeSSE } from "./sse-writer.js";
|
|
3
3
|
const HTTP_BAD_REQUEST = 400;
|
|
4
|
-
function
|
|
4
|
+
function normaliseReply(reply) {
|
|
5
5
|
if (typeof reply === "string")
|
|
6
6
|
return { text: reply };
|
|
7
7
|
return reply;
|
|
@@ -9,18 +9,18 @@ function normalizeReply(reply) {
|
|
|
9
9
|
async function resolveReply(matched, mockReq, fallback, logger) {
|
|
10
10
|
if (!matched) {
|
|
11
11
|
logger.warn(`No matching rule for "${mockReq.lastMessage}", using fallback`);
|
|
12
|
-
return { reply:
|
|
12
|
+
return { reply: normaliseReply(fallback), ruleDesc: undefined };
|
|
13
13
|
}
|
|
14
14
|
try {
|
|
15
15
|
const raw = typeof matched.resolve === "function"
|
|
16
16
|
? await matched.resolve(mockReq)
|
|
17
17
|
: matched.resolve;
|
|
18
18
|
logger.debug(`Matched rule ${matched.description}`);
|
|
19
|
-
return { reply:
|
|
19
|
+
return { reply: normaliseReply(raw), ruleDesc: matched.description };
|
|
20
20
|
}
|
|
21
21
|
catch (err) {
|
|
22
22
|
logger.error(`Resolver threw for rule ${matched.description}`, err);
|
|
23
|
-
return { reply:
|
|
23
|
+
return { reply: normaliseReply(fallback), ruleDesc: matched.description };
|
|
24
24
|
}
|
|
25
25
|
}
|
|
26
26
|
export function createRouteHandler(format, deps) {
|
|
@@ -39,7 +39,14 @@ export function createRouteHandler(format, deps) {
|
|
|
39
39
|
catch (err) {
|
|
40
40
|
if (err instanceof ZodError) {
|
|
41
41
|
logger.warn(`Invalid ${format.name} request: ${err.issues.map((i) => i.message).join(", ")}`);
|
|
42
|
-
return reply
|
|
42
|
+
return reply
|
|
43
|
+
.status(HTTP_BAD_REQUEST)
|
|
44
|
+
.type("application/json")
|
|
45
|
+
.send(format.serializeError({
|
|
46
|
+
status: HTTP_BAD_REQUEST,
|
|
47
|
+
message: "Invalid request body",
|
|
48
|
+
type: "invalid_request_error",
|
|
49
|
+
}));
|
|
43
50
|
}
|
|
44
51
|
throw err;
|
|
45
52
|
}
|
|
@@ -51,7 +58,10 @@ export function createRouteHandler(format, deps) {
|
|
|
51
58
|
const { error } = resolvedReply;
|
|
52
59
|
logger.info(`Error reply: ${String(error.status)} ${error.message}`);
|
|
53
60
|
history.record(mockReq, ruleDesc);
|
|
54
|
-
return reply
|
|
61
|
+
return reply
|
|
62
|
+
.status(error.status)
|
|
63
|
+
.type("application/json")
|
|
64
|
+
.send(format.serializeError(error));
|
|
55
65
|
}
|
|
56
66
|
history.record(mockReq, ruleDesc);
|
|
57
67
|
const isStreaming = format.isStreaming(body);
|
|
@@ -66,7 +76,9 @@ export function createRouteHandler(format, deps) {
|
|
|
66
76
|
logger.debug(`Reply tool calls: ${resolvedReply.tools.map((t) => t.name).join(", ")}`);
|
|
67
77
|
}
|
|
68
78
|
if (!isStreaming) {
|
|
69
|
-
return reply
|
|
79
|
+
return reply
|
|
80
|
+
.type("application/json")
|
|
81
|
+
.send(format.serializeComplete(resolvedReply, mockReq.model));
|
|
70
82
|
}
|
|
71
83
|
const chunks = format.serialize(resolvedReply, mockReq.model, effectiveOptions);
|
|
72
84
|
await writeSSE(reply, chunks, effectiveOptions);
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"route-handler.js","sourceRoot":"","sources":["../src/route-handler.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,QAAQ,EAAE,MAAM,KAAK,CAAC;
|
|
1
|
+
{"version":3,"file":"route-handler.js","sourceRoot":"","sources":["../src/route-handler.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import type { Reply, ReplyOptions, SequenceEntry } from "./types/reply.js";
|
|
2
|
+
import type { Match, PendingRule, RuleHandle } from "./types/rule.js";
|
|
3
|
+
import type { RuleEngine } from "./rule-engine.js";
|
|
4
|
+
/** Builds matching rules against the rule engine. Proxied onto `MockServer`. */
|
|
5
|
+
export declare class RuleBuilder {
|
|
6
|
+
private readonly engine;
|
|
7
|
+
constructor(engine: RuleEngine);
|
|
8
|
+
/** Register a matching rule. Call `.reply()` on the result to set the response. */
|
|
9
|
+
when(match: Match): PendingRule;
|
|
10
|
+
/** Shorthand for `when({ toolName })`. */
|
|
11
|
+
whenTool(toolName: string): PendingRule;
|
|
12
|
+
/** Shorthand for `when({ toolCallId })`. */
|
|
13
|
+
whenToolResult(toolCallId: string): PendingRule;
|
|
14
|
+
/** Queue a one-shot error for the very next request. Fires once then removes itself. */
|
|
15
|
+
nextError(status: number, message: string, type?: string): RuleHandle;
|
|
16
|
+
}
|
|
17
|
+
export declare function normaliseSequenceEntries(entries: readonly SequenceEntry[]): {
|
|
18
|
+
reply: Reply;
|
|
19
|
+
options?: ReplyOptions | undefined;
|
|
20
|
+
}[];
|
|
21
|
+
//# sourceMappingURL=rule-builder.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"rule-builder.d.ts","sourceRoot":"","sources":["../src/rule-builder.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EACV,KAAK,EACL,YAAY,EAEZ,aAAa,EACd,MAAM,kBAAkB,CAAC;AAC1B,OAAO,KAAK,EAAE,KAAK,EAAE,WAAW,EAAQ,UAAU,EAAE,MAAM,iBAAiB,CAAC;AAC5E,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,kBAAkB,CAAC;AAgBnD,gFAAgF;AAChF,qBAAa,WAAW;IACV,OAAO,CAAC,QAAQ,CAAC,MAAM;gBAAN,MAAM,EAAE,UAAU;IAE/C,mFAAmF;IACnF,IAAI,CAAC,KAAK,EAAE,KAAK,GAAG,WAAW;IAiB/B,0CAA0C;IAC1C,QAAQ,CAAC,QAAQ,EAAE,MAAM,GAAG,WAAW;IAIvC,4CAA4C;IAC5C,cAAc,CAAC,UAAU,EAAE,MAAM,GAAG,WAAW;IAI/C,wFAAwF;IACxF,SAAS,CAAC,MAAM,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,EAAE,IAAI,CAAC,EAAE,MAAM,GAAG,UAAU;CAMtE;AAED,wBAAgB,wBAAwB,CACtC,OAAO,EAAE,SAAS,aAAa,EAAE,GAChC;IAAE,KAAK,EAAE,KAAK,CAAC;IAAC,OAAO,CAAC,EAAE,YAAY,GAAG,SAAS,CAAA;CAAE,EAAE,CAMxD"}
|
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
import { createSequenceResolver } from "./rule-engine.js";
|
|
2
|
+
function makeHandle(engine, rule) {
|
|
3
|
+
return {
|
|
4
|
+
times(n) {
|
|
5
|
+
rule.remaining = n;
|
|
6
|
+
return this;
|
|
7
|
+
},
|
|
8
|
+
first() {
|
|
9
|
+
engine.moveToFront(rule);
|
|
10
|
+
return this;
|
|
11
|
+
},
|
|
12
|
+
};
|
|
13
|
+
}
|
|
14
|
+
/** Builds matching rules against the rule engine. Proxied onto `MockServer`. */
|
|
15
|
+
export class RuleBuilder {
|
|
16
|
+
engine;
|
|
17
|
+
constructor(engine) {
|
|
18
|
+
this.engine = engine;
|
|
19
|
+
}
|
|
20
|
+
/** Register a matching rule. Call `.reply()` on the result to set the response. */
|
|
21
|
+
when(match) {
|
|
22
|
+
const engine = this.engine;
|
|
23
|
+
return {
|
|
24
|
+
reply(response, options) {
|
|
25
|
+
return makeHandle(engine, engine.add(match, response, options));
|
|
26
|
+
},
|
|
27
|
+
replySequence(entries) {
|
|
28
|
+
const steps = normaliseSequenceEntries(entries);
|
|
29
|
+
const rule = engine.add(match, "");
|
|
30
|
+
const { resolver, entryCount } = createSequenceResolver(steps, rule);
|
|
31
|
+
rule.resolve = resolver;
|
|
32
|
+
rule.remaining = entryCount;
|
|
33
|
+
return makeHandle(engine, rule);
|
|
34
|
+
},
|
|
35
|
+
};
|
|
36
|
+
}
|
|
37
|
+
/** Shorthand for `when({ toolName })`. */
|
|
38
|
+
whenTool(toolName) {
|
|
39
|
+
return this.when({ toolName });
|
|
40
|
+
}
|
|
41
|
+
/** Shorthand for `when({ toolCallId })`. */
|
|
42
|
+
whenToolResult(toolCallId) {
|
|
43
|
+
return this.when({ toolCallId });
|
|
44
|
+
}
|
|
45
|
+
/** Queue a one-shot error for the very next request. Fires once then removes itself. */
|
|
46
|
+
nextError(status, message, type) {
|
|
47
|
+
return this.when(() => true)
|
|
48
|
+
.reply({ error: { status, message, type } })
|
|
49
|
+
.times(1)
|
|
50
|
+
.first();
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
export function normaliseSequenceEntries(entries) {
|
|
54
|
+
return entries.map((entry) => typeof entry === "string" || !("reply" in entry)
|
|
55
|
+
? { reply: entry }
|
|
56
|
+
: { reply: entry.reply, options: entry.options });
|
|
57
|
+
}
|
|
58
|
+
//# sourceMappingURL=rule-builder.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"rule-builder.js","sourceRoot":"","sources":["../src/rule-builder.ts"],"names":[],"mappings":"AAQA,OAAO,EAAE,sBAAsB,EAAE,MAAM,kBAAkB,CAAC;AAE1D,SAAS,UAAU,CAAC,MAAkB,EAAE,IAAU;IAChD,OAAO;QACL,KAAK,CAAC,CAAS;YACb,IAAI,CAAC,SAAS,GAAG,CAAC,CAAC;YACnB,OAAO,IAAI,CAAC;QACd,CAAC;QACD,KAAK;YACH,MAAM,CAAC,WAAW,CAAC,IAAI,CAAC,CAAC;YACzB,OAAO,IAAI,CAAC;QACd,CAAC;KACF,CAAC;AACJ,CAAC;AAED,gFAAgF;AAChF,MAAM,OAAO,WAAW;IACO;IAA7B,YAA6B,MAAkB;QAAlB,WAAM,GAAN,MAAM,CAAY;IAAG,CAAC;IAEnD,mFAAmF;IACnF,IAAI,CAAC,KAAY;QACf,MAAM,MAAM,GAAG,IAAI,CAAC,MAAM,CAAC;QAC3B,OAAO;YACL,KAAK,CAAC,QAAkB,EAAE,OAAsB;gBAC9C,OAAO,UAAU,CAAC,MAAM,EAAE,MAAM,CAAC,GAAG,CAAC,KAAK,EAAE,QAAQ,EAAE,OAAO,CAAC,CAAC,CAAC;YAClE,CAAC;YACD,aAAa,CAAC,OAAiC;gBAC7C,MAAM,KAAK,GAAG,wBAAwB,CAAC,OAAO,CAAC,CAAC;gBAChD,MAAM,IAAI,GAAG,MAAM,CAAC,GAAG,CAAC,KAAK,EAAE,EAAE,CAAC,CAAC;gBACnC,MAAM,EAAE,QAAQ,EAAE,UAAU,EAAE,GAAG,sBAAsB,CAAC,KAAK,EAAE,IAAI,CAAC,CAAC;gBACrE,IAAI,CAAC,OAAO,GAAG,QAAQ,CAAC;gBACxB,IAAI,CAAC,SAAS,GAAG,UAAU,CAAC;gBAC5B,OAAO,UAAU,CAAC,MAAM,EAAE,IAAI,CAAC,CAAC;YAClC,CAAC;SACF,CAAC;IACJ,CAAC;IAED,0CAA0C;IAC1C,QAAQ,CAAC,QAAgB;QACvB,OAAO,IAAI,CAAC,IAAI,CAAC,EAAE,QAAQ,EAAE,CAAC,CAAC;IACjC,CAAC;IAED,4CAA4C;IAC5C,cAAc,CAAC,UAAkB;QAC/B,OAAO,IAAI,CAAC,IAAI,CAAC,EAAE,UAAU,EAAE,CAAC,CAAC;IACnC,CAAC;IAED,wFAAwF;IACxF,SAAS,CAAC,MAAc,EAAE,OAAe,EAAE,IAAa;QACtD,OAAO,IAAI,CAAC,IAAI,CAAC,GAAG,EAAE,CAAC,IAAI,CAAC;aACzB,KAAK,CAAC,EAAE,KAAK,EAAE,EAAE,MAAM,EAAE,OAAO,EAAE,IAAI,EAAE,EAAE,CAAC;aAC3C,KAAK,CAAC,CAAC,CAAC;aACR,KAAK,EAAE,CAAC;IACb,CAAC;CACF;AAED,MAAM,UAAU,wBAAwB,CACtC,OAAiC;IAEjC,OAAO,OAAO,CAAC,GAAG,CAAC,CAAC,KAAK,EAAE,EAAE,CAC3B,OAAO,KAAK,KAAK,QAAQ,IAAI,CAAC,CAAC,OAAO,IAAI,KAAK,CAAC;QAC9C,CAAC,CAAC,EAAE,KAAK,EAAE,KAAc,EAAE;QAC3B,CAAC,CAAC,EAAE,KAAK,EAAE,KAAK,CAAC,KAAK,EAAE,OAAO,EAAE,KAAK,CAAC,OAAO,EAAE,CACnD,CAAC;AACJ,CAAC"}
|
package/dist/rule-engine.d.ts
CHANGED
|
@@ -1,4 +1,6 @@
|
|
|
1
|
-
import type {
|
|
1
|
+
import type { MockRequest } from "./types/request.js";
|
|
2
|
+
import type { Reply, ReplyOptions, Resolver } from "./types/reply.js";
|
|
3
|
+
import type { Match, Rule, RuleSummary } from "./types/rule.js";
|
|
2
4
|
interface SequenceStep {
|
|
3
5
|
readonly reply: Reply;
|
|
4
6
|
readonly options?: ReplyOptions | undefined;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"rule-engine.d.ts","sourceRoot":"","sources":["../src/rule-engine.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,KAAK,
|
|
1
|
+
{"version":3,"file":"rule-engine.d.ts","sourceRoot":"","sources":["../src/rule-engine.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,oBAAoB,CAAC;AACtD,OAAO,KAAK,EAAE,KAAK,EAAE,YAAY,EAAE,QAAQ,EAAE,MAAM,kBAAkB,CAAC;AACtE,OAAO,KAAK,EAAE,KAAK,EAAe,IAAI,EAAE,WAAW,EAAE,MAAM,iBAAiB,CAAC;AA4E7E,UAAU,YAAY;IACpB,QAAQ,CAAC,KAAK,EAAE,KAAK,CAAC;IACtB,QAAQ,CAAC,OAAO,CAAC,EAAE,YAAY,GAAG,SAAS,CAAC;CAC7C;AAED,wBAAgB,sBAAsB,CACpC,KAAK,EAAE,SAAS,YAAY,EAAE,EAC9B,IAAI,EAAE;IAAE,OAAO,EAAE,YAAY,CAAA;CAAE,GAC9B;IAAE,QAAQ,EAAE,MAAM,KAAK,CAAC;IAAC,UAAU,EAAE,MAAM,CAAA;CAAE,CAa/C;AAED,qBAAa,UAAU;IACrB,OAAO,CAAC,QAAQ,CAAC,KAAK,CAAc;IAEpC,GAAG,CAAC,KAAK,EAAE,KAAK,EAAE,OAAO,EAAE,QAAQ,EAAE,OAAO,GAAE,YAAiB,GAAG,IAAI;IAMtE,WAAW,CAAC,IAAI,EAAE,IAAI,GAAG,IAAI;IAQ7B,UAAU,CACR,OAAO,EAAE,CAAC,GAAG,EAAE,WAAW,KAAK,OAAO,EACtC,OAAO,EAAE,QAAQ,EACjB,WAAW,SAAc,GACxB,IAAI;IAMP,KAAK,CAAC,GAAG,EAAE,WAAW,GAAG,IAAI,GAAG,SAAS;IAgBzC,MAAM,IAAI,OAAO;IAMjB,IAAI,SAAS,IAAI,MAAM,CAEtB;IAED,QAAQ,IAAI,SAAS,WAAW,EAAE;IAOlC,KAAK,IAAI,IAAI;CAGd"}
|
package/dist/rule-engine.js
CHANGED
|
@@ -1,5 +1,7 @@
|
|
|
1
1
|
function safeRegex(re) {
|
|
2
|
-
return
|
|
2
|
+
return re.global || re.sticky
|
|
3
|
+
? new RegExp(re.source, re.flags.replace(/[gy]/g, ""))
|
|
4
|
+
: re;
|
|
3
5
|
}
|
|
4
6
|
function compilePattern(pattern) {
|
|
5
7
|
if (typeof pattern === "string") {
|
|
@@ -120,7 +122,10 @@ export class RuleEngine {
|
|
|
120
122
|
return this.rules.length;
|
|
121
123
|
}
|
|
122
124
|
describe() {
|
|
123
|
-
return this.rules.map((r) => ({
|
|
125
|
+
return this.rules.map((r) => ({
|
|
126
|
+
description: r.description,
|
|
127
|
+
remaining: r.remaining,
|
|
128
|
+
}));
|
|
124
129
|
}
|
|
125
130
|
clear() {
|
|
126
131
|
this.rules.length = 0;
|
package/dist/rule-engine.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"rule-engine.js","sourceRoot":"","sources":["../src/rule-engine.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"rule-engine.js","sourceRoot":"","sources":["../src/rule-engine.ts"],"names":[],"mappings":"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"}
|
package/dist/sse-writer.d.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import type { FastifyReply } from "fastify";
|
|
2
2
|
import type { SSEChunk } from "./formats/types.js";
|
|
3
|
-
import type { ReplyOptions } from "./types.js";
|
|
3
|
+
import type { ReplyOptions } from "./types/reply.js";
|
|
4
4
|
export declare function writeSSE(reply: FastifyReply, chunks: readonly SSEChunk[], options?: ReplyOptions): Promise<void>;
|
|
5
5
|
//# sourceMappingURL=sse-writer.d.ts.map
|