@copilotkit/aimock 1.7.0
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/.claude-plugin/marketplace.json +17 -0
- package/.claude-plugin/plugin.json +12 -0
- package/LICENSE +21 -0
- package/README.md +82 -0
- package/dist/_virtual/_rolldown/runtime.cjs +29 -0
- package/dist/a2a-handler.cjs +203 -0
- package/dist/a2a-handler.cjs.map +1 -0
- package/dist/a2a-handler.js +199 -0
- package/dist/a2a-handler.js.map +1 -0
- package/dist/a2a-mock.cjs +292 -0
- package/dist/a2a-mock.cjs.map +1 -0
- package/dist/a2a-mock.d.cts +41 -0
- package/dist/a2a-mock.d.cts.map +1 -0
- package/dist/a2a-mock.d.ts +41 -0
- package/dist/a2a-mock.d.ts.map +1 -0
- package/dist/a2a-mock.js +290 -0
- package/dist/a2a-mock.js.map +1 -0
- package/dist/a2a-stub.cjs +4 -0
- package/dist/a2a-stub.d.cts +3 -0
- package/dist/a2a-stub.d.ts +3 -0
- package/dist/a2a-stub.js +3 -0
- package/dist/a2a-types.d.cts +68 -0
- package/dist/a2a-types.d.cts.map +1 -0
- package/dist/a2a-types.d.ts +68 -0
- package/dist/a2a-types.d.ts.map +1 -0
- package/dist/aimock-cli.cjs +112 -0
- package/dist/aimock-cli.cjs.map +1 -0
- package/dist/aimock-cli.d.cts +19 -0
- package/dist/aimock-cli.d.cts.map +1 -0
- package/dist/aimock-cli.d.ts +19 -0
- package/dist/aimock-cli.d.ts.map +1 -0
- package/dist/aimock-cli.js +110 -0
- package/dist/aimock-cli.js.map +1 -0
- package/dist/aws-event-stream.cjs +117 -0
- package/dist/aws-event-stream.cjs.map +1 -0
- package/dist/aws-event-stream.d.cts +38 -0
- package/dist/aws-event-stream.d.cts.map +1 -0
- package/dist/aws-event-stream.d.ts +38 -0
- package/dist/aws-event-stream.d.ts.map +1 -0
- package/dist/aws-event-stream.js +114 -0
- package/dist/aws-event-stream.js.map +1 -0
- package/dist/bedrock-converse.cjs +445 -0
- package/dist/bedrock-converse.cjs.map +1 -0
- package/dist/bedrock-converse.d.cts +50 -0
- package/dist/bedrock-converse.d.cts.map +1 -0
- package/dist/bedrock-converse.d.ts +50 -0
- package/dist/bedrock-converse.d.ts.map +1 -0
- package/dist/bedrock-converse.js +443 -0
- package/dist/bedrock-converse.js.map +1 -0
- package/dist/bedrock.cjs +557 -0
- package/dist/bedrock.cjs.map +1 -0
- package/dist/bedrock.d.cts +41 -0
- package/dist/bedrock.d.cts.map +1 -0
- package/dist/bedrock.d.ts +41 -0
- package/dist/bedrock.d.ts.map +1 -0
- package/dist/bedrock.js +553 -0
- package/dist/bedrock.js.map +1 -0
- package/dist/chaos.cjs +114 -0
- package/dist/chaos.cjs.map +1 -0
- package/dist/chaos.d.cts +27 -0
- package/dist/chaos.d.cts.map +1 -0
- package/dist/chaos.d.ts +27 -0
- package/dist/chaos.d.ts.map +1 -0
- package/dist/chaos.js +113 -0
- package/dist/chaos.js.map +1 -0
- package/dist/cli.cjs +268 -0
- package/dist/cli.cjs.map +1 -0
- package/dist/cli.d.cts +1 -0
- package/dist/cli.d.ts +1 -0
- package/dist/cli.js +268 -0
- package/dist/cli.js.map +1 -0
- package/dist/cohere.cjs +434 -0
- package/dist/cohere.cjs.map +1 -0
- package/dist/cohere.d.cts +34 -0
- package/dist/cohere.d.cts.map +1 -0
- package/dist/cohere.d.ts +34 -0
- package/dist/cohere.d.ts.map +1 -0
- package/dist/cohere.js +433 -0
- package/dist/cohere.js.map +1 -0
- package/dist/config-loader.cjs +111 -0
- package/dist/config-loader.cjs.map +1 -0
- package/dist/config-loader.d.cts +100 -0
- package/dist/config-loader.d.cts.map +1 -0
- package/dist/config-loader.d.ts +100 -0
- package/dist/config-loader.d.ts.map +1 -0
- package/dist/config-loader.js +107 -0
- package/dist/config-loader.js.map +1 -0
- package/dist/embeddings.cjs +150 -0
- package/dist/embeddings.cjs.map +1 -0
- package/dist/embeddings.d.cts +12 -0
- package/dist/embeddings.d.cts.map +1 -0
- package/dist/embeddings.d.ts +12 -0
- package/dist/embeddings.d.ts.map +1 -0
- package/dist/embeddings.js +150 -0
- package/dist/embeddings.js.map +1 -0
- package/dist/fixture-loader.cjs +269 -0
- package/dist/fixture-loader.cjs.map +1 -0
- package/dist/fixture-loader.d.cts +17 -0
- package/dist/fixture-loader.d.cts.map +1 -0
- package/dist/fixture-loader.d.ts +17 -0
- package/dist/fixture-loader.d.ts.map +1 -0
- package/dist/fixture-loader.js +265 -0
- package/dist/fixture-loader.js.map +1 -0
- package/dist/gemini.cjs +403 -0
- package/dist/gemini.cjs.map +1 -0
- package/dist/gemini.d.cts +10 -0
- package/dist/gemini.d.cts.map +1 -0
- package/dist/gemini.d.ts +10 -0
- package/dist/gemini.d.ts.map +1 -0
- package/dist/gemini.js +403 -0
- package/dist/gemini.js.map +1 -0
- package/dist/helpers.cjs +276 -0
- package/dist/helpers.cjs.map +1 -0
- package/dist/helpers.d.cts +39 -0
- package/dist/helpers.d.cts.map +1 -0
- package/dist/helpers.d.ts +39 -0
- package/dist/helpers.d.ts.map +1 -0
- package/dist/helpers.js +259 -0
- package/dist/helpers.js.map +1 -0
- package/dist/index.cjs +113 -0
- package/dist/index.d.cts +42 -0
- package/dist/index.d.ts +42 -0
- package/dist/index.js +39 -0
- package/dist/interruption.cjs +40 -0
- package/dist/interruption.cjs.map +1 -0
- package/dist/interruption.d.cts +15 -0
- package/dist/interruption.d.cts.map +1 -0
- package/dist/interruption.d.ts +15 -0
- package/dist/interruption.d.ts.map +1 -0
- package/dist/interruption.js +39 -0
- package/dist/interruption.js.map +1 -0
- package/dist/journal.cjs +65 -0
- package/dist/journal.cjs.map +1 -0
- package/dist/journal.d.cts +23 -0
- package/dist/journal.d.cts.map +1 -0
- package/dist/journal.d.ts +23 -0
- package/dist/journal.d.ts.map +1 -0
- package/dist/journal.js +65 -0
- package/dist/journal.js.map +1 -0
- package/dist/jsonrpc.cjs +91 -0
- package/dist/jsonrpc.cjs.map +1 -0
- package/dist/jsonrpc.d.cts +24 -0
- package/dist/jsonrpc.d.cts.map +1 -0
- package/dist/jsonrpc.d.ts +24 -0
- package/dist/jsonrpc.d.ts.map +1 -0
- package/dist/jsonrpc.js +90 -0
- package/dist/jsonrpc.js.map +1 -0
- package/dist/llmock.cjs +223 -0
- package/dist/llmock.cjs.map +1 -0
- package/dist/llmock.d.cts +70 -0
- package/dist/llmock.d.cts.map +1 -0
- package/dist/llmock.d.ts +70 -0
- package/dist/llmock.d.ts.map +1 -0
- package/dist/llmock.js +223 -0
- package/dist/llmock.js.map +1 -0
- package/dist/logger.cjs +29 -0
- package/dist/logger.cjs.map +1 -0
- package/dist/logger.d.cts +14 -0
- package/dist/logger.d.cts.map +1 -0
- package/dist/logger.d.ts +14 -0
- package/dist/logger.d.ts.map +1 -0
- package/dist/logger.js +28 -0
- package/dist/logger.js.map +1 -0
- package/dist/mcp-handler.cjs +189 -0
- package/dist/mcp-handler.cjs.map +1 -0
- package/dist/mcp-handler.js +188 -0
- package/dist/mcp-handler.js.map +1 -0
- package/dist/mcp-mock.cjs +169 -0
- package/dist/mcp-mock.cjs.map +1 -0
- package/dist/mcp-mock.d.cts +40 -0
- package/dist/mcp-mock.d.cts.map +1 -0
- package/dist/mcp-mock.d.ts +40 -0
- package/dist/mcp-mock.d.ts.map +1 -0
- package/dist/mcp-mock.js +167 -0
- package/dist/mcp-mock.js.map +1 -0
- package/dist/mcp-stub.cjs +4 -0
- package/dist/mcp-stub.d.cts +3 -0
- package/dist/mcp-stub.d.ts +3 -0
- package/dist/mcp-stub.js +3 -0
- package/dist/mcp-types.d.cts +65 -0
- package/dist/mcp-types.d.cts.map +1 -0
- package/dist/mcp-types.d.ts +65 -0
- package/dist/mcp-types.d.ts.map +1 -0
- package/dist/messages.cjs +489 -0
- package/dist/messages.cjs.map +1 -0
- package/dist/messages.d.cts +10 -0
- package/dist/messages.d.cts.map +1 -0
- package/dist/messages.d.ts +10 -0
- package/dist/messages.d.ts.map +1 -0
- package/dist/messages.js +489 -0
- package/dist/messages.js.map +1 -0
- package/dist/metrics.cjs +160 -0
- package/dist/metrics.cjs.map +1 -0
- package/dist/metrics.d.cts +24 -0
- package/dist/metrics.d.cts.map +1 -0
- package/dist/metrics.d.ts +24 -0
- package/dist/metrics.d.ts.map +1 -0
- package/dist/metrics.js +158 -0
- package/dist/metrics.js.map +1 -0
- package/dist/moderation.cjs +91 -0
- package/dist/moderation.cjs.map +1 -0
- package/dist/moderation.d.cts +23 -0
- package/dist/moderation.d.cts.map +1 -0
- package/dist/moderation.d.ts +23 -0
- package/dist/moderation.d.ts.map +1 -0
- package/dist/moderation.js +91 -0
- package/dist/moderation.js.map +1 -0
- package/dist/ndjson-writer.cjs +31 -0
- package/dist/ndjson-writer.cjs.map +1 -0
- package/dist/ndjson-writer.d.cts +17 -0
- package/dist/ndjson-writer.d.cts.map +1 -0
- package/dist/ndjson-writer.d.ts +17 -0
- package/dist/ndjson-writer.d.ts.map +1 -0
- package/dist/ndjson-writer.js +31 -0
- package/dist/ndjson-writer.js.map +1 -0
- package/dist/ollama.cjs +519 -0
- package/dist/ollama.cjs.map +1 -0
- package/dist/ollama.d.cts +34 -0
- package/dist/ollama.d.cts.map +1 -0
- package/dist/ollama.d.ts +34 -0
- package/dist/ollama.d.ts.map +1 -0
- package/dist/ollama.js +517 -0
- package/dist/ollama.js.map +1 -0
- package/dist/recorder.cjs +311 -0
- package/dist/recorder.cjs.map +1 -0
- package/dist/recorder.d.cts +23 -0
- package/dist/recorder.d.cts.map +1 -0
- package/dist/recorder.d.ts +23 -0
- package/dist/recorder.d.ts.map +1 -0
- package/dist/recorder.js +305 -0
- package/dist/recorder.js.map +1 -0
- package/dist/rerank.cjs +71 -0
- package/dist/rerank.cjs.map +1 -0
- package/dist/rerank.d.cts +22 -0
- package/dist/rerank.d.cts.map +1 -0
- package/dist/rerank.d.ts +22 -0
- package/dist/rerank.d.ts.map +1 -0
- package/dist/rerank.js +71 -0
- package/dist/rerank.js.map +1 -0
- package/dist/responses.cjs +637 -0
- package/dist/responses.cjs.map +1 -0
- package/dist/responses.d.cts +16 -0
- package/dist/responses.d.cts.map +1 -0
- package/dist/responses.d.ts +16 -0
- package/dist/responses.d.ts.map +1 -0
- package/dist/responses.js +634 -0
- package/dist/responses.js.map +1 -0
- package/dist/router.cjs +68 -0
- package/dist/router.cjs.map +1 -0
- package/dist/router.d.cts +16 -0
- package/dist/router.d.cts.map +1 -0
- package/dist/router.d.ts +16 -0
- package/dist/router.d.ts.map +1 -0
- package/dist/router.js +65 -0
- package/dist/router.js.map +1 -0
- package/dist/search.cjs +59 -0
- package/dist/search.cjs.map +1 -0
- package/dist/search.d.cts +23 -0
- package/dist/search.d.cts.map +1 -0
- package/dist/search.d.ts +23 -0
- package/dist/search.d.ts.map +1 -0
- package/dist/search.js +59 -0
- package/dist/search.js.map +1 -0
- package/dist/server.cjs +935 -0
- package/dist/server.cjs.map +1 -0
- package/dist/server.d.cts +28 -0
- package/dist/server.d.cts.map +1 -0
- package/dist/server.d.ts +28 -0
- package/dist/server.d.ts.map +1 -0
- package/dist/server.js +933 -0
- package/dist/server.js.map +1 -0
- package/dist/sse-writer.cjs +59 -0
- package/dist/sse-writer.cjs.map +1 -0
- package/dist/sse-writer.d.cts +19 -0
- package/dist/sse-writer.d.cts.map +1 -0
- package/dist/sse-writer.d.ts +19 -0
- package/dist/sse-writer.d.ts.map +1 -0
- package/dist/sse-writer.js +55 -0
- package/dist/sse-writer.js.map +1 -0
- package/dist/stream-collapse.cjs +496 -0
- package/dist/stream-collapse.cjs.map +1 -0
- package/dist/stream-collapse.d.cts +70 -0
- package/dist/stream-collapse.d.cts.map +1 -0
- package/dist/stream-collapse.d.ts +70 -0
- package/dist/stream-collapse.d.ts.map +1 -0
- package/dist/stream-collapse.js +489 -0
- package/dist/stream-collapse.js.map +1 -0
- package/dist/suite.cjs +46 -0
- package/dist/suite.cjs.map +1 -0
- package/dist/suite.d.cts +31 -0
- package/dist/suite.d.cts.map +1 -0
- package/dist/suite.d.ts +31 -0
- package/dist/suite.d.ts.map +1 -0
- package/dist/suite.js +46 -0
- package/dist/suite.js.map +1 -0
- package/dist/types.d.cts +243 -0
- package/dist/types.d.cts.map +1 -0
- package/dist/types.d.ts +243 -0
- package/dist/types.d.ts.map +1 -0
- package/dist/url.cjs +21 -0
- package/dist/url.cjs.map +1 -0
- package/dist/url.d.cts +16 -0
- package/dist/url.d.cts.map +1 -0
- package/dist/url.d.ts +16 -0
- package/dist/url.d.ts.map +1 -0
- package/dist/url.js +20 -0
- package/dist/url.js.map +1 -0
- package/dist/vector-handler.cjs +239 -0
- package/dist/vector-handler.cjs.map +1 -0
- package/dist/vector-handler.js +238 -0
- package/dist/vector-handler.js.map +1 -0
- package/dist/vector-mock.cjs +229 -0
- package/dist/vector-mock.cjs.map +1 -0
- package/dist/vector-mock.d.cts +39 -0
- package/dist/vector-mock.d.cts.map +1 -0
- package/dist/vector-mock.d.ts +39 -0
- package/dist/vector-mock.d.ts.map +1 -0
- package/dist/vector-mock.js +227 -0
- package/dist/vector-mock.js.map +1 -0
- package/dist/vector-stub.cjs +4 -0
- package/dist/vector-stub.d.cts +3 -0
- package/dist/vector-stub.d.ts +3 -0
- package/dist/vector-stub.js +3 -0
- package/dist/vector-types.d.cts +32 -0
- package/dist/vector-types.d.cts.map +1 -0
- package/dist/vector-types.d.ts +32 -0
- package/dist/vector-types.d.ts.map +1 -0
- package/dist/watcher.cjs +59 -0
- package/dist/watcher.cjs.map +1 -0
- package/dist/watcher.js +58 -0
- package/dist/watcher.js.map +1 -0
- package/dist/ws-framing.cjs +187 -0
- package/dist/ws-framing.cjs.map +1 -0
- package/dist/ws-framing.d.cts +26 -0
- package/dist/ws-framing.d.cts.map +1 -0
- package/dist/ws-framing.d.ts +26 -0
- package/dist/ws-framing.d.ts.map +1 -0
- package/dist/ws-framing.js +184 -0
- package/dist/ws-framing.js.map +1 -0
- package/dist/ws-gemini-live.cjs +364 -0
- package/dist/ws-gemini-live.cjs.map +1 -0
- package/dist/ws-gemini-live.d.cts +18 -0
- package/dist/ws-gemini-live.d.cts.map +1 -0
- package/dist/ws-gemini-live.d.ts +18 -0
- package/dist/ws-gemini-live.d.ts.map +1 -0
- package/dist/ws-gemini-live.js +364 -0
- package/dist/ws-gemini-live.js.map +1 -0
- package/dist/ws-realtime.cjs +435 -0
- package/dist/ws-realtime.cjs.map +1 -0
- package/dist/ws-realtime.d.cts +17 -0
- package/dist/ws-realtime.d.cts.map +1 -0
- package/dist/ws-realtime.d.ts +17 -0
- package/dist/ws-realtime.d.ts.map +1 -0
- package/dist/ws-realtime.js +435 -0
- package/dist/ws-realtime.js.map +1 -0
- package/dist/ws-responses.cjs +164 -0
- package/dist/ws-responses.cjs.map +1 -0
- package/dist/ws-responses.d.cts +18 -0
- package/dist/ws-responses.d.cts.map +1 -0
- package/dist/ws-responses.d.ts +18 -0
- package/dist/ws-responses.d.ts.map +1 -0
- package/dist/ws-responses.js +164 -0
- package/dist/ws-responses.js.map +1 -0
- package/fixtures/example-greeting.json +12 -0
- package/fixtures/example-multi-turn.json +14 -0
- package/fixtures/example-tool-call.json +15 -0
- package/package.json +118 -0
- package/skills/write-fixtures/SKILL.md +625 -0
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"llmock.d.ts","names":[],"sources":["../src/llmock.ts"],"sourcesContent":[],"mappings":";;;;;;;cAwBa,MAAA;;EAAA,QAAA,cAAM;EAAA,QAAA,cAAA;UASK,kBAAA;UAMF,MAAA;UAKE,cAAA;UAKE,OAAA;aAKA,CAAA,OAAA,CAAA,EArBF,iBAqBE;YAkBY,CAAA,OAAA,EAjChB,OAiCgB,CAAA,EAAA,IAAA;aAqB1B,CAAA,QAAA,EAjDY,OAiDZ,EAAA,CAAA,EAAA,IAAA;gBAAwB,CAAA,OAAA,EA5CV,OA4CU,CAAA,EAAA,IAAA;aAAwB,CAAA,CAAA,EAAA,SAvClC,OAuCkC,EAAA;iBAQ9B,CAAA,QAAA,EAAA,MAAA,CAAA,EAAA,IAAA;gBAAkB,CAAA,OAAA,EAAA,MAAA,CAAA,EAAA,IAAA;;;;;qBAYf,CAAA,KAAA,EAAA,MAAA,GAzCK,gBAyCL,EAAA,CAAA,EAAA,IAAA;eAA6C,CAAA,CAAA,EAAA,IAAA;KAKzC,KAAA,EAzBzB,YAyByB,EAAA,QAAA,EAzBD,eAyBC,EAAA,IAAA,CAAA,EAzBuB,WAyBvB,CAAA,EAAA,IAAA;WAAwB,CAAA,OAAA,EAAA,MAAA,GAjB/B,MAiB+B,EAAA,QAAA,EAjBb,eAiBa,EAAA,IAAA,CAAA,EAjBW,WAiBX,CAAA,EAAA,IAAA;aAIxB,CAAA,OAAA,EAAA,MAAA,GAhBf,MAgBe,EAAA,QAAA,EAfvB,eAeuB,EAAA,IAAA,CAAA,EAd1B,oBAc0B,CAAA,EAAA,IAAA;cAAwB,CAAA,OAAA,EAAA,MAAA,GAT5B,MAS4B,EAAA,WAAA,EAAA,MAAA,GAAA,MAAA,EAAA,IAAA,CAAA,EATiB,WASjB,CAAA,EAAA,IAAA;YAMhC,CAAA,IAAA,EAAA,MAAA,EAAA,QAAA,EAVQ,eAUR,EAAA,IAAA,CAAA,EAVgC,WAUhC,CAAA,EAAA,IAAA;cAAiB,CAAA,EAAA,EAAA,MAAA,EAAA,QAAA,EANT,eAMS,EAAA,IAAA,CAAA,EANe,WAMf,CAAA,EAAA,IAAA;UAKjB,CAAA,OAAA,EAAA,MAAA,GALA,MAKA,EAAA,OAAA,EALiB,YAKjB,EAAA,CAAA,EAAA,IAAA;UAAiB,CAAA,OAAA,EAAA,MAAA,GAAjB,MAAiB,EAAA,OAAA,EAAA,YAAA,EAAA,CAAA,EAAA,IAAA;YAKf,CAAA,OAAA,EAAA,MAAA,GAAA,MAAA,EAAA,MAAA,EAAgB,gBAAhB,CAAA,EAAA,IAAA;;;;;;;kBA0Hd,CAAA,MAAA,EAAA,MAAA,EAAA,UAAA,EAAA;IAYD,OAAA,CAAA,EAAA,MAAA;IAaC,IAAA,CAAA,EAAA,MAAA;IA4Be,IAAA,CAAA,EAAA,MAAA;MAA4B,IAAA;OAAR,CAAA,IAAA,EAAA,MAAA,EAAA,OAAA,EAhIrB,SAgIqB,CAAA,EAAA,IAAA;EAAO,WAAA,CAAA,CAAA,EAhInB,YAAA,EAgImB;oBA/GT,YAAA;;;mBAqB/B;;0BAYO;;;WAyBT;UAYD;iBAaC;;;;0BA4Be,oBAAoB,QAAQ"}
|
package/dist/llmock.js
ADDED
|
@@ -0,0 +1,223 @@
|
|
|
1
|
+
import { entryToFixture, loadFixtureFile, loadFixturesFromDir, validateFixtures } from "./fixture-loader.js";
|
|
2
|
+
import { createServer } from "./server.js";
|
|
3
|
+
|
|
4
|
+
//#region src/llmock.ts
|
|
5
|
+
var LLMock = class LLMock {
|
|
6
|
+
fixtures = [];
|
|
7
|
+
searchFixtures = [];
|
|
8
|
+
rerankFixtures = [];
|
|
9
|
+
moderationFixtures = [];
|
|
10
|
+
mounts = [];
|
|
11
|
+
serverInstance = null;
|
|
12
|
+
options;
|
|
13
|
+
constructor(options) {
|
|
14
|
+
this.options = options ?? {};
|
|
15
|
+
}
|
|
16
|
+
addFixture(fixture) {
|
|
17
|
+
this.fixtures.push(fixture);
|
|
18
|
+
return this;
|
|
19
|
+
}
|
|
20
|
+
addFixtures(fixtures) {
|
|
21
|
+
this.fixtures.push(...fixtures);
|
|
22
|
+
return this;
|
|
23
|
+
}
|
|
24
|
+
prependFixture(fixture) {
|
|
25
|
+
this.fixtures.unshift(fixture);
|
|
26
|
+
return this;
|
|
27
|
+
}
|
|
28
|
+
getFixtures() {
|
|
29
|
+
return this.fixtures;
|
|
30
|
+
}
|
|
31
|
+
loadFixtureFile(filePath) {
|
|
32
|
+
this.fixtures.push(...loadFixtureFile(filePath));
|
|
33
|
+
return this;
|
|
34
|
+
}
|
|
35
|
+
loadFixtureDir(dirPath) {
|
|
36
|
+
this.fixtures.push(...loadFixturesFromDir(dirPath));
|
|
37
|
+
return this;
|
|
38
|
+
}
|
|
39
|
+
/**
|
|
40
|
+
* Add fixtures from a JSON string or pre-parsed array of fixture entries.
|
|
41
|
+
* Validates all fixtures and throws if any have severity "error".
|
|
42
|
+
*/
|
|
43
|
+
addFixturesFromJSON(input) {
|
|
44
|
+
const converted = (typeof input === "string" ? JSON.parse(input) : input).map(entryToFixture);
|
|
45
|
+
const errors = validateFixtures(converted).filter((i) => i.severity === "error");
|
|
46
|
+
if (errors.length > 0) throw new Error(`Fixture validation failed: ${JSON.stringify(errors)}`);
|
|
47
|
+
this.fixtures.push(...converted);
|
|
48
|
+
return this;
|
|
49
|
+
}
|
|
50
|
+
clearFixtures() {
|
|
51
|
+
this.fixtures.length = 0;
|
|
52
|
+
return this;
|
|
53
|
+
}
|
|
54
|
+
on(match, response, opts) {
|
|
55
|
+
return this.addFixture({
|
|
56
|
+
match,
|
|
57
|
+
response,
|
|
58
|
+
...opts
|
|
59
|
+
});
|
|
60
|
+
}
|
|
61
|
+
onMessage(pattern, response, opts) {
|
|
62
|
+
return this.on({ userMessage: pattern }, response, opts);
|
|
63
|
+
}
|
|
64
|
+
onEmbedding(pattern, response, opts) {
|
|
65
|
+
return this.on({ inputText: pattern }, response, opts);
|
|
66
|
+
}
|
|
67
|
+
onJsonOutput(pattern, jsonContent, opts) {
|
|
68
|
+
const content = typeof jsonContent === "string" ? jsonContent : JSON.stringify(jsonContent);
|
|
69
|
+
return this.on({
|
|
70
|
+
userMessage: pattern,
|
|
71
|
+
responseFormat: "json_object"
|
|
72
|
+
}, { content }, opts);
|
|
73
|
+
}
|
|
74
|
+
onToolCall(name, response, opts) {
|
|
75
|
+
return this.on({ toolName: name }, response, opts);
|
|
76
|
+
}
|
|
77
|
+
onToolResult(id, response, opts) {
|
|
78
|
+
return this.on({ toolCallId: id }, response, opts);
|
|
79
|
+
}
|
|
80
|
+
onSearch(pattern, results) {
|
|
81
|
+
this.searchFixtures.push({
|
|
82
|
+
match: pattern,
|
|
83
|
+
results
|
|
84
|
+
});
|
|
85
|
+
return this;
|
|
86
|
+
}
|
|
87
|
+
onRerank(pattern, results) {
|
|
88
|
+
this.rerankFixtures.push({
|
|
89
|
+
match: pattern,
|
|
90
|
+
results
|
|
91
|
+
});
|
|
92
|
+
return this;
|
|
93
|
+
}
|
|
94
|
+
onModerate(pattern, result) {
|
|
95
|
+
this.moderationFixtures.push({
|
|
96
|
+
match: pattern,
|
|
97
|
+
result
|
|
98
|
+
});
|
|
99
|
+
return this;
|
|
100
|
+
}
|
|
101
|
+
/**
|
|
102
|
+
* Queue a one-shot error that will be returned for the next matching
|
|
103
|
+
* request, then automatically removed. Implemented as an internal fixture
|
|
104
|
+
* with a `predicate` that always matches (so it fires first) and spliced
|
|
105
|
+
* at the front of the fixture list.
|
|
106
|
+
*/
|
|
107
|
+
nextRequestError(status, errorBody) {
|
|
108
|
+
const fixture = {
|
|
109
|
+
match: { predicate: () => true },
|
|
110
|
+
response: {
|
|
111
|
+
error: {
|
|
112
|
+
message: errorBody?.message ?? "Injected error",
|
|
113
|
+
type: errorBody?.type ?? "server_error",
|
|
114
|
+
code: errorBody?.code
|
|
115
|
+
},
|
|
116
|
+
status
|
|
117
|
+
}
|
|
118
|
+
};
|
|
119
|
+
this.fixtures.unshift(fixture);
|
|
120
|
+
const original = fixture.match.predicate;
|
|
121
|
+
fixture.match.predicate = (req) => {
|
|
122
|
+
const result = original(req);
|
|
123
|
+
if (result) queueMicrotask(() => {
|
|
124
|
+
const idx = this.fixtures.indexOf(fixture);
|
|
125
|
+
if (idx !== -1) this.fixtures.splice(idx, 1);
|
|
126
|
+
});
|
|
127
|
+
return result;
|
|
128
|
+
};
|
|
129
|
+
return this;
|
|
130
|
+
}
|
|
131
|
+
mount(path, handler) {
|
|
132
|
+
this.mounts.push({
|
|
133
|
+
path,
|
|
134
|
+
handler
|
|
135
|
+
});
|
|
136
|
+
if (this.serverInstance) {
|
|
137
|
+
if (handler.setJournal) handler.setJournal(this.serverInstance.journal);
|
|
138
|
+
if (handler.setBaseUrl) handler.setBaseUrl(this.serverInstance.url + path);
|
|
139
|
+
const registry = this.serverInstance.defaults.registry;
|
|
140
|
+
if (registry && handler.setRegistry) handler.setRegistry(registry);
|
|
141
|
+
}
|
|
142
|
+
return this;
|
|
143
|
+
}
|
|
144
|
+
getRequests() {
|
|
145
|
+
return this.journal.getAll();
|
|
146
|
+
}
|
|
147
|
+
getLastRequest() {
|
|
148
|
+
return this.journal.getLast();
|
|
149
|
+
}
|
|
150
|
+
clearRequests() {
|
|
151
|
+
this.journal.clear();
|
|
152
|
+
}
|
|
153
|
+
resetMatchCounts() {
|
|
154
|
+
if (this.serverInstance) this.serverInstance.journal.clearMatchCounts();
|
|
155
|
+
return this;
|
|
156
|
+
}
|
|
157
|
+
setChaos(config) {
|
|
158
|
+
this.options.chaos = config;
|
|
159
|
+
return this;
|
|
160
|
+
}
|
|
161
|
+
clearChaos() {
|
|
162
|
+
delete this.options.chaos;
|
|
163
|
+
return this;
|
|
164
|
+
}
|
|
165
|
+
enableRecording(config) {
|
|
166
|
+
this.options.record = config;
|
|
167
|
+
return this;
|
|
168
|
+
}
|
|
169
|
+
disableRecording() {
|
|
170
|
+
delete this.options.record;
|
|
171
|
+
return this;
|
|
172
|
+
}
|
|
173
|
+
reset() {
|
|
174
|
+
this.clearFixtures();
|
|
175
|
+
this.searchFixtures.length = 0;
|
|
176
|
+
this.rerankFixtures.length = 0;
|
|
177
|
+
this.moderationFixtures.length = 0;
|
|
178
|
+
if (this.serverInstance) this.serverInstance.journal.clear();
|
|
179
|
+
return this;
|
|
180
|
+
}
|
|
181
|
+
async start() {
|
|
182
|
+
if (this.serverInstance) throw new Error("Server already started");
|
|
183
|
+
this.serverInstance = await createServer(this.fixtures, this.options, this.mounts, {
|
|
184
|
+
search: this.searchFixtures,
|
|
185
|
+
rerank: this.rerankFixtures,
|
|
186
|
+
moderation: this.moderationFixtures
|
|
187
|
+
});
|
|
188
|
+
return this.serverInstance.url;
|
|
189
|
+
}
|
|
190
|
+
async stop() {
|
|
191
|
+
if (!this.serverInstance) throw new Error("Server not started");
|
|
192
|
+
const { server } = this.serverInstance;
|
|
193
|
+
await new Promise((resolve, reject) => {
|
|
194
|
+
server.close((err) => err ? reject(err) : resolve());
|
|
195
|
+
});
|
|
196
|
+
this.serverInstance = null;
|
|
197
|
+
}
|
|
198
|
+
get journal() {
|
|
199
|
+
if (!this.serverInstance) throw new Error("Server not started");
|
|
200
|
+
return this.serverInstance.journal;
|
|
201
|
+
}
|
|
202
|
+
get url() {
|
|
203
|
+
if (!this.serverInstance) throw new Error("Server not started");
|
|
204
|
+
return this.serverInstance.url;
|
|
205
|
+
}
|
|
206
|
+
get baseUrl() {
|
|
207
|
+
return this.url;
|
|
208
|
+
}
|
|
209
|
+
get port() {
|
|
210
|
+
const parsed = new URL(this.url);
|
|
211
|
+
if (!parsed.port) throw new Error(`Server URL has no explicit port: ${this.url}`);
|
|
212
|
+
return parseInt(parsed.port, 10);
|
|
213
|
+
}
|
|
214
|
+
static async create(options) {
|
|
215
|
+
const instance = new LLMock(options);
|
|
216
|
+
await instance.start();
|
|
217
|
+
return instance;
|
|
218
|
+
}
|
|
219
|
+
};
|
|
220
|
+
|
|
221
|
+
//#endregion
|
|
222
|
+
export { LLMock };
|
|
223
|
+
//# sourceMappingURL=llmock.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"llmock.js","names":[],"sources":["../src/llmock.ts"],"sourcesContent":["import type {\n ChaosConfig,\n EmbeddingFixtureOpts,\n Fixture,\n FixtureFileEntry,\n FixtureMatch,\n FixtureOpts,\n FixtureResponse,\n MockServerOptions,\n Mountable,\n RecordConfig,\n} from \"./types.js\";\nimport { createServer, type ServerInstance } from \"./server.js\";\nimport {\n loadFixtureFile,\n loadFixturesFromDir,\n entryToFixture,\n validateFixtures,\n} from \"./fixture-loader.js\";\nimport { Journal } from \"./journal.js\";\nimport type { SearchFixture, SearchResult } from \"./search.js\";\nimport type { RerankFixture, RerankResult } from \"./rerank.js\";\nimport type { ModerationFixture, ModerationResult } from \"./moderation.js\";\n\nexport class LLMock {\n private fixtures: Fixture[] = [];\n private searchFixtures: SearchFixture[] = [];\n private rerankFixtures: RerankFixture[] = [];\n private moderationFixtures: ModerationFixture[] = [];\n private mounts: Array<{ path: string; handler: Mountable }> = [];\n private serverInstance: ServerInstance | null = null;\n private options: MockServerOptions;\n\n constructor(options?: MockServerOptions) {\n this.options = options ?? {};\n }\n\n // ---- Fixture management ----\n\n addFixture(fixture: Fixture): this {\n this.fixtures.push(fixture);\n return this;\n }\n\n addFixtures(fixtures: Fixture[]): this {\n this.fixtures.push(...fixtures);\n return this;\n }\n\n prependFixture(fixture: Fixture): this {\n this.fixtures.unshift(fixture);\n return this;\n }\n\n getFixtures(): readonly Fixture[] {\n return this.fixtures;\n }\n\n loadFixtureFile(filePath: string): this {\n this.fixtures.push(...loadFixtureFile(filePath));\n return this;\n }\n\n loadFixtureDir(dirPath: string): this {\n this.fixtures.push(...loadFixturesFromDir(dirPath));\n return this;\n }\n\n /**\n * Add fixtures from a JSON string or pre-parsed array of fixture entries.\n * Validates all fixtures and throws if any have severity \"error\".\n */\n addFixturesFromJSON(input: string | FixtureFileEntry[]): this {\n const entries: FixtureFileEntry[] = typeof input === \"string\" ? JSON.parse(input) : input;\n const converted = entries.map(entryToFixture);\n const issues = validateFixtures(converted);\n const errors = issues.filter((i) => i.severity === \"error\");\n if (errors.length > 0) {\n throw new Error(`Fixture validation failed: ${JSON.stringify(errors)}`);\n }\n this.fixtures.push(...converted);\n return this;\n }\n\n // Uses length = 0 to preserve array reference identity — the running\n // server reads this same array on every request.\n clearFixtures(): this {\n this.fixtures.length = 0;\n return this;\n }\n\n // ---- Convenience ----\n\n on(match: FixtureMatch, response: FixtureResponse, opts?: FixtureOpts): this {\n return this.addFixture({\n match,\n response,\n ...opts,\n });\n }\n\n onMessage(pattern: string | RegExp, response: FixtureResponse, opts?: FixtureOpts): this {\n return this.on({ userMessage: pattern }, response, opts);\n }\n\n onEmbedding(\n pattern: string | RegExp,\n response: FixtureResponse,\n opts?: EmbeddingFixtureOpts,\n ): this {\n return this.on({ inputText: pattern }, response, opts);\n }\n\n onJsonOutput(pattern: string | RegExp, jsonContent: object | string, opts?: FixtureOpts): this {\n const content = typeof jsonContent === \"string\" ? jsonContent : JSON.stringify(jsonContent);\n return this.on({ userMessage: pattern, responseFormat: \"json_object\" }, { content }, opts);\n }\n\n onToolCall(name: string, response: FixtureResponse, opts?: FixtureOpts): this {\n return this.on({ toolName: name }, response, opts);\n }\n\n onToolResult(id: string, response: FixtureResponse, opts?: FixtureOpts): this {\n return this.on({ toolCallId: id }, response, opts);\n }\n\n // ---- Service mock convenience methods ----\n\n onSearch(pattern: string | RegExp, results: SearchResult[]): this {\n this.searchFixtures.push({ match: pattern, results });\n return this;\n }\n\n onRerank(pattern: string | RegExp, results: RerankResult[]): this {\n this.rerankFixtures.push({ match: pattern, results });\n return this;\n }\n\n onModerate(pattern: string | RegExp, result: ModerationResult): this {\n this.moderationFixtures.push({ match: pattern, result });\n return this;\n }\n\n /**\n * Queue a one-shot error that will be returned for the next matching\n * request, then automatically removed. Implemented as an internal fixture\n * with a `predicate` that always matches (so it fires first) and spliced\n * at the front of the fixture list.\n */\n nextRequestError(\n status: number,\n errorBody?: { message?: string; type?: string; code?: string },\n ): this {\n const errorResponse: FixtureResponse = {\n error: {\n message: errorBody?.message ?? \"Injected error\",\n type: errorBody?.type ?? \"server_error\",\n code: errorBody?.code,\n },\n status,\n };\n const fixture: Fixture = {\n match: { predicate: () => true },\n response: errorResponse,\n };\n // Insert at front so it matches before everything else\n this.fixtures.unshift(fixture);\n // Remove after first match — the journal records it so tests can assert\n const original = fixture.match.predicate!;\n fixture.match.predicate = (req) => {\n const result = original(req);\n if (result) {\n // Defer splice so it doesn't mutate the array while matchFixture iterates it\n queueMicrotask(() => {\n const idx = this.fixtures.indexOf(fixture);\n if (idx !== -1) this.fixtures.splice(idx, 1);\n });\n }\n return result;\n };\n return this;\n }\n\n // ---- Mounts ----\n\n mount(path: string, handler: Mountable): this {\n this.mounts.push({ path, handler });\n\n // If server is already running, wire up journal, registry, and baseUrl immediately\n // so late mounts behave identically to pre-start mounts.\n if (this.serverInstance) {\n if (handler.setJournal) handler.setJournal(this.serverInstance.journal);\n if (handler.setBaseUrl) handler.setBaseUrl(this.serverInstance.url + path);\n const registry = this.serverInstance.defaults.registry;\n if (registry && handler.setRegistry) handler.setRegistry(registry);\n }\n\n return this;\n }\n\n // ---- Journal proxies ----\n\n getRequests(): import(\"./types.js\").JournalEntry[] {\n return this.journal.getAll();\n }\n\n getLastRequest(): import(\"./types.js\").JournalEntry | null {\n return this.journal.getLast();\n }\n\n clearRequests(): void {\n this.journal.clear();\n }\n\n resetMatchCounts(): this {\n if (this.serverInstance) {\n this.serverInstance.journal.clearMatchCounts();\n }\n return this;\n }\n\n // ---- Chaos ----\n\n setChaos(config: ChaosConfig): this {\n this.options.chaos = config;\n return this;\n }\n\n clearChaos(): this {\n delete this.options.chaos;\n return this;\n }\n\n // ---- Recording ----\n\n enableRecording(config: RecordConfig): this {\n this.options.record = config;\n return this;\n }\n\n disableRecording(): this {\n delete this.options.record;\n return this;\n }\n\n // ---- Reset ----\n\n reset(): this {\n this.clearFixtures();\n this.searchFixtures.length = 0;\n this.rerankFixtures.length = 0;\n this.moderationFixtures.length = 0;\n if (this.serverInstance) {\n this.serverInstance.journal.clear();\n }\n return this;\n }\n\n // ---- Server lifecycle ----\n\n async start(): Promise<string> {\n if (this.serverInstance) {\n throw new Error(\"Server already started\");\n }\n this.serverInstance = await createServer(this.fixtures, this.options, this.mounts, {\n search: this.searchFixtures,\n rerank: this.rerankFixtures,\n moderation: this.moderationFixtures,\n });\n return this.serverInstance.url;\n }\n\n async stop(): Promise<void> {\n if (!this.serverInstance) {\n throw new Error(\"Server not started\");\n }\n const { server } = this.serverInstance;\n await new Promise<void>((resolve, reject) => {\n server.close((err: Error | undefined) => (err ? reject(err) : resolve()));\n });\n this.serverInstance = null;\n }\n\n // ---- Accessors ----\n\n get journal(): Journal {\n if (!this.serverInstance) {\n throw new Error(\"Server not started\");\n }\n return this.serverInstance.journal;\n }\n\n get url(): string {\n if (!this.serverInstance) {\n throw new Error(\"Server not started\");\n }\n return this.serverInstance.url;\n }\n\n get baseUrl(): string {\n return this.url;\n }\n\n get port(): number {\n const parsed = new URL(this.url); // this.url throws if not started\n if (!parsed.port) {\n throw new Error(`Server URL has no explicit port: ${this.url}`);\n }\n return parseInt(parsed.port, 10);\n }\n\n // ---- Static factory ----\n\n static async create(options?: MockServerOptions): Promise<LLMock> {\n const instance = new LLMock(options);\n await instance.start();\n return instance;\n }\n}\n"],"mappings":"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"}
|
package/dist/logger.cjs
ADDED
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
|
|
2
|
+
//#region src/logger.ts
|
|
3
|
+
const LEVELS = {
|
|
4
|
+
silent: 0,
|
|
5
|
+
info: 1,
|
|
6
|
+
debug: 2
|
|
7
|
+
};
|
|
8
|
+
var Logger = class {
|
|
9
|
+
level;
|
|
10
|
+
constructor(level = "silent") {
|
|
11
|
+
this.level = LEVELS[level];
|
|
12
|
+
}
|
|
13
|
+
info(...args) {
|
|
14
|
+
if (this.level >= LEVELS.info) console.log("[aimock]", ...args);
|
|
15
|
+
}
|
|
16
|
+
debug(...args) {
|
|
17
|
+
if (this.level >= LEVELS.debug) console.log("[aimock]", ...args);
|
|
18
|
+
}
|
|
19
|
+
warn(...args) {
|
|
20
|
+
console.warn("[aimock]", ...args);
|
|
21
|
+
}
|
|
22
|
+
error(...args) {
|
|
23
|
+
console.error("[aimock]", ...args);
|
|
24
|
+
}
|
|
25
|
+
};
|
|
26
|
+
|
|
27
|
+
//#endregion
|
|
28
|
+
exports.Logger = Logger;
|
|
29
|
+
//# sourceMappingURL=logger.cjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"logger.cjs","names":[],"sources":["../src/logger.ts"],"sourcesContent":["export type LogLevel = \"silent\" | \"info\" | \"debug\";\n\nconst LEVELS: Record<LogLevel, number> = {\n silent: 0,\n info: 1,\n debug: 2,\n};\n\nexport class Logger {\n private level: number;\n\n constructor(level: LogLevel = \"silent\") {\n this.level = LEVELS[level];\n }\n\n info(...args: unknown[]): void {\n if (this.level >= LEVELS.info) {\n console.log(\"[aimock]\", ...args);\n }\n }\n\n debug(...args: unknown[]): void {\n if (this.level >= LEVELS.debug) {\n console.log(\"[aimock]\", ...args);\n }\n }\n\n warn(...args: unknown[]): void {\n console.warn(\"[aimock]\", ...args);\n }\n\n error(...args: unknown[]): void {\n console.error(\"[aimock]\", ...args);\n }\n}\n"],"mappings":";;AAEA,MAAM,SAAmC;CACvC,QAAQ;CACR,MAAM;CACN,OAAO;CACR;AAED,IAAa,SAAb,MAAoB;CAClB,AAAQ;CAER,YAAY,QAAkB,UAAU;AACtC,OAAK,QAAQ,OAAO;;CAGtB,KAAK,GAAG,MAAuB;AAC7B,MAAI,KAAK,SAAS,OAAO,KACvB,SAAQ,IAAI,YAAY,GAAG,KAAK;;CAIpC,MAAM,GAAG,MAAuB;AAC9B,MAAI,KAAK,SAAS,OAAO,MACvB,SAAQ,IAAI,YAAY,GAAG,KAAK;;CAIpC,KAAK,GAAG,MAAuB;AAC7B,UAAQ,KAAK,YAAY,GAAG,KAAK;;CAGnC,MAAM,GAAG,MAAuB;AAC9B,UAAQ,MAAM,YAAY,GAAG,KAAK"}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
//#region src/logger.d.ts
|
|
2
|
+
type LogLevel = "silent" | "info" | "debug";
|
|
3
|
+
declare class Logger {
|
|
4
|
+
private level;
|
|
5
|
+
constructor(level?: LogLevel);
|
|
6
|
+
info(...args: unknown[]): void;
|
|
7
|
+
debug(...args: unknown[]): void;
|
|
8
|
+
warn(...args: unknown[]): void;
|
|
9
|
+
error(...args: unknown[]): void;
|
|
10
|
+
}
|
|
11
|
+
//# sourceMappingURL=logger.d.ts.map
|
|
12
|
+
//#endregion
|
|
13
|
+
export { LogLevel, Logger };
|
|
14
|
+
//# sourceMappingURL=logger.d.cts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"logger.d.cts","names":[],"sources":["../src/logger.ts"],"sourcesContent":[],"mappings":";KAAY,QAAA;AAAA,cAQC,MAAA,CARO;EAQP,QAAA,KAAM;sBAGE"}
|
package/dist/logger.d.ts
ADDED
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
//#region src/logger.d.ts
|
|
2
|
+
type LogLevel = "silent" | "info" | "debug";
|
|
3
|
+
declare class Logger {
|
|
4
|
+
private level;
|
|
5
|
+
constructor(level?: LogLevel);
|
|
6
|
+
info(...args: unknown[]): void;
|
|
7
|
+
debug(...args: unknown[]): void;
|
|
8
|
+
warn(...args: unknown[]): void;
|
|
9
|
+
error(...args: unknown[]): void;
|
|
10
|
+
}
|
|
11
|
+
//# sourceMappingURL=logger.d.ts.map
|
|
12
|
+
//#endregion
|
|
13
|
+
export { LogLevel, Logger };
|
|
14
|
+
//# sourceMappingURL=logger.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"logger.d.ts","names":[],"sources":["../src/logger.ts"],"sourcesContent":[],"mappings":";KAAY,QAAA;AAAA,cAQC,MAAA,CARO;EAQP,QAAA,KAAM;sBAGE"}
|
package/dist/logger.js
ADDED
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
//#region src/logger.ts
|
|
2
|
+
const LEVELS = {
|
|
3
|
+
silent: 0,
|
|
4
|
+
info: 1,
|
|
5
|
+
debug: 2
|
|
6
|
+
};
|
|
7
|
+
var Logger = class {
|
|
8
|
+
level;
|
|
9
|
+
constructor(level = "silent") {
|
|
10
|
+
this.level = LEVELS[level];
|
|
11
|
+
}
|
|
12
|
+
info(...args) {
|
|
13
|
+
if (this.level >= LEVELS.info) console.log("[aimock]", ...args);
|
|
14
|
+
}
|
|
15
|
+
debug(...args) {
|
|
16
|
+
if (this.level >= LEVELS.debug) console.log("[aimock]", ...args);
|
|
17
|
+
}
|
|
18
|
+
warn(...args) {
|
|
19
|
+
console.warn("[aimock]", ...args);
|
|
20
|
+
}
|
|
21
|
+
error(...args) {
|
|
22
|
+
console.error("[aimock]", ...args);
|
|
23
|
+
}
|
|
24
|
+
};
|
|
25
|
+
|
|
26
|
+
//#endregion
|
|
27
|
+
export { Logger };
|
|
28
|
+
//# sourceMappingURL=logger.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"logger.js","names":[],"sources":["../src/logger.ts"],"sourcesContent":["export type LogLevel = \"silent\" | \"info\" | \"debug\";\n\nconst LEVELS: Record<LogLevel, number> = {\n silent: 0,\n info: 1,\n debug: 2,\n};\n\nexport class Logger {\n private level: number;\n\n constructor(level: LogLevel = \"silent\") {\n this.level = LEVELS[level];\n }\n\n info(...args: unknown[]): void {\n if (this.level >= LEVELS.info) {\n console.log(\"[aimock]\", ...args);\n }\n }\n\n debug(...args: unknown[]): void {\n if (this.level >= LEVELS.debug) {\n console.log(\"[aimock]\", ...args);\n }\n }\n\n warn(...args: unknown[]): void {\n console.warn(\"[aimock]\", ...args);\n }\n\n error(...args: unknown[]): void {\n console.error(\"[aimock]\", ...args);\n }\n}\n"],"mappings":";AAEA,MAAM,SAAmC;CACvC,QAAQ;CACR,MAAM;CACN,OAAO;CACR;AAED,IAAa,SAAb,MAAoB;CAClB,AAAQ;CAER,YAAY,QAAkB,UAAU;AACtC,OAAK,QAAQ,OAAO;;CAGtB,KAAK,GAAG,MAAuB;AAC7B,MAAI,KAAK,SAAS,OAAO,KACvB,SAAQ,IAAI,YAAY,GAAG,KAAK;;CAIpC,MAAM,GAAG,MAAuB;AAC9B,MAAI,KAAK,SAAS,OAAO,MACvB,SAAQ,IAAI,YAAY,GAAG,KAAK;;CAIpC,KAAK,GAAG,MAAuB;AAC7B,UAAQ,KAAK,YAAY,GAAG,KAAK;;CAGnC,MAAM,GAAG,MAAuB;AAC9B,UAAQ,MAAM,YAAY,GAAG,KAAK"}
|
|
@@ -0,0 +1,189 @@
|
|
|
1
|
+
const require_runtime = require('./_virtual/_rolldown/runtime.cjs');
|
|
2
|
+
const require_jsonrpc = require('./jsonrpc.cjs');
|
|
3
|
+
let node_crypto = require("node:crypto");
|
|
4
|
+
|
|
5
|
+
//#region src/mcp-handler.ts
|
|
6
|
+
function jsonRpcResult(id, result) {
|
|
7
|
+
return {
|
|
8
|
+
jsonrpc: "2.0",
|
|
9
|
+
id,
|
|
10
|
+
result
|
|
11
|
+
};
|
|
12
|
+
}
|
|
13
|
+
function jsonRpcError(id, code, message) {
|
|
14
|
+
return {
|
|
15
|
+
jsonrpc: "2.0",
|
|
16
|
+
id,
|
|
17
|
+
error: {
|
|
18
|
+
code,
|
|
19
|
+
message
|
|
20
|
+
}
|
|
21
|
+
};
|
|
22
|
+
}
|
|
23
|
+
function createMCPRequestHandler(state) {
|
|
24
|
+
const dispatcher = require_jsonrpc.createJsonRpcDispatcher({ methods: {
|
|
25
|
+
initialize: async (_params, id) => {
|
|
26
|
+
return jsonRpcResult(id, {
|
|
27
|
+
protocolVersion: "2025-03-26",
|
|
28
|
+
capabilities: {
|
|
29
|
+
tools: {},
|
|
30
|
+
resources: {},
|
|
31
|
+
prompts: {}
|
|
32
|
+
},
|
|
33
|
+
serverInfo: state.serverInfo
|
|
34
|
+
});
|
|
35
|
+
},
|
|
36
|
+
"notifications/initialized": async (_params, _id, req) => {
|
|
37
|
+
const sessionId = req.headers["mcp-session-id"];
|
|
38
|
+
const session = state.sessions.get(sessionId);
|
|
39
|
+
if (session) session.initialized = true;
|
|
40
|
+
return null;
|
|
41
|
+
},
|
|
42
|
+
ping: async (_params, id) => {
|
|
43
|
+
return jsonRpcResult(id, {});
|
|
44
|
+
},
|
|
45
|
+
"tools/list": async (_params, id) => {
|
|
46
|
+
const tools = [];
|
|
47
|
+
for (const { def } of state.tools.values()) tools.push(def);
|
|
48
|
+
return jsonRpcResult(id, { tools });
|
|
49
|
+
},
|
|
50
|
+
"tools/call": async (params, id) => {
|
|
51
|
+
const { name, arguments: args } = params ?? {};
|
|
52
|
+
if (!name) return jsonRpcError(id, -32602, "Missing tool name");
|
|
53
|
+
const entry = state.tools.get(name);
|
|
54
|
+
if (!entry) return jsonRpcError(id, -32602, `Unknown tool: ${name}`);
|
|
55
|
+
if (entry.handler) try {
|
|
56
|
+
const result = await entry.handler(args);
|
|
57
|
+
return jsonRpcResult(id, {
|
|
58
|
+
content: Array.isArray(result) ? result : [{
|
|
59
|
+
type: "text",
|
|
60
|
+
text: String(result)
|
|
61
|
+
}],
|
|
62
|
+
isError: false
|
|
63
|
+
});
|
|
64
|
+
} catch (err) {
|
|
65
|
+
return jsonRpcResult(id, {
|
|
66
|
+
content: [{
|
|
67
|
+
type: "text",
|
|
68
|
+
text: err instanceof Error ? err.message : String(err)
|
|
69
|
+
}],
|
|
70
|
+
isError: true
|
|
71
|
+
});
|
|
72
|
+
}
|
|
73
|
+
return jsonRpcResult(id, {
|
|
74
|
+
content: [],
|
|
75
|
+
isError: false
|
|
76
|
+
});
|
|
77
|
+
},
|
|
78
|
+
"resources/list": async (_params, id) => {
|
|
79
|
+
const resources = [];
|
|
80
|
+
for (const { def } of state.resources.values()) resources.push(def);
|
|
81
|
+
return jsonRpcResult(id, { resources });
|
|
82
|
+
},
|
|
83
|
+
"resources/read": async (params, id) => {
|
|
84
|
+
const { uri } = params ?? {};
|
|
85
|
+
if (!uri) return jsonRpcError(id, -32602, "Missing resource URI");
|
|
86
|
+
const entry = state.resources.get(uri);
|
|
87
|
+
if (!entry) return jsonRpcError(id, -32602, `Unknown resource: ${uri}`);
|
|
88
|
+
return jsonRpcResult(id, { contents: [{
|
|
89
|
+
uri,
|
|
90
|
+
...entry.content?.text !== void 0 && { text: entry.content.text },
|
|
91
|
+
...entry.content?.blob !== void 0 && { blob: entry.content.blob },
|
|
92
|
+
...entry.content?.mimeType !== void 0 && { mimeType: entry.content.mimeType }
|
|
93
|
+
}] });
|
|
94
|
+
},
|
|
95
|
+
"prompts/list": async (_params, id) => {
|
|
96
|
+
const prompts = [];
|
|
97
|
+
for (const { def } of state.prompts.values()) prompts.push(def);
|
|
98
|
+
return jsonRpcResult(id, { prompts });
|
|
99
|
+
},
|
|
100
|
+
"prompts/get": async (params, id) => {
|
|
101
|
+
const { name, arguments: args } = params ?? {};
|
|
102
|
+
if (!name) return jsonRpcError(id, -32602, "Missing prompt name");
|
|
103
|
+
const entry = state.prompts.get(name);
|
|
104
|
+
if (!entry) return jsonRpcError(id, -32602, `Unknown prompt: ${name}`);
|
|
105
|
+
if (entry.handler) try {
|
|
106
|
+
return jsonRpcResult(id, await entry.handler(args));
|
|
107
|
+
} catch (err) {
|
|
108
|
+
return jsonRpcError(id, -32603, `Prompt handler error: ${err instanceof Error ? err.message : String(err)}`);
|
|
109
|
+
}
|
|
110
|
+
return jsonRpcResult(id, { messages: [] });
|
|
111
|
+
}
|
|
112
|
+
} });
|
|
113
|
+
return async (req, res, body) => {
|
|
114
|
+
if (req.method === "DELETE") {
|
|
115
|
+
const sessionId = req.headers["mcp-session-id"];
|
|
116
|
+
if (!sessionId) {
|
|
117
|
+
res.writeHead(400, { "Content-Type": "application/json" });
|
|
118
|
+
res.end(JSON.stringify({ error: "Missing mcp-session-id header" }));
|
|
119
|
+
return;
|
|
120
|
+
}
|
|
121
|
+
if (!state.sessions.has(sessionId)) {
|
|
122
|
+
res.writeHead(404, { "Content-Type": "application/json" });
|
|
123
|
+
res.end(JSON.stringify({ error: "Session not found" }));
|
|
124
|
+
return;
|
|
125
|
+
}
|
|
126
|
+
state.sessions.delete(sessionId);
|
|
127
|
+
res.writeHead(200, { "Content-Type": "application/json" });
|
|
128
|
+
res.end(JSON.stringify({ ok: true }));
|
|
129
|
+
return;
|
|
130
|
+
}
|
|
131
|
+
let parsed;
|
|
132
|
+
try {
|
|
133
|
+
parsed = JSON.parse(body);
|
|
134
|
+
} catch {
|
|
135
|
+
await dispatcher(req, res, body);
|
|
136
|
+
return;
|
|
137
|
+
}
|
|
138
|
+
const method = typeof parsed === "object" && parsed !== null && "method" in parsed ? parsed.method : void 0;
|
|
139
|
+
if (method === "initialize") {
|
|
140
|
+
const id = typeof parsed === "object" && parsed !== null && "id" in parsed ? parsed.id : null;
|
|
141
|
+
const sessionId = (0, node_crypto.randomUUID)();
|
|
142
|
+
state.sessions.set(sessionId, {
|
|
143
|
+
id: sessionId,
|
|
144
|
+
initialized: false,
|
|
145
|
+
createdAt: Date.now()
|
|
146
|
+
});
|
|
147
|
+
const response = {
|
|
148
|
+
jsonrpc: "2.0",
|
|
149
|
+
id,
|
|
150
|
+
result: {
|
|
151
|
+
protocolVersion: "2025-03-26",
|
|
152
|
+
capabilities: {
|
|
153
|
+
tools: {},
|
|
154
|
+
resources: {},
|
|
155
|
+
prompts: {}
|
|
156
|
+
},
|
|
157
|
+
serverInfo: state.serverInfo
|
|
158
|
+
}
|
|
159
|
+
};
|
|
160
|
+
res.writeHead(200, {
|
|
161
|
+
"Content-Type": "application/json",
|
|
162
|
+
"Mcp-Session-Id": sessionId
|
|
163
|
+
});
|
|
164
|
+
res.end(JSON.stringify(response));
|
|
165
|
+
return;
|
|
166
|
+
}
|
|
167
|
+
const sessionId = req.headers["mcp-session-id"];
|
|
168
|
+
if (!sessionId) {
|
|
169
|
+
res.writeHead(400, { "Content-Type": "application/json" });
|
|
170
|
+
res.end(JSON.stringify({ error: "Missing mcp-session-id header" }));
|
|
171
|
+
return;
|
|
172
|
+
}
|
|
173
|
+
if (!state.sessions.has(sessionId)) {
|
|
174
|
+
res.writeHead(404, { "Content-Type": "application/json" });
|
|
175
|
+
res.end(JSON.stringify({ error: "Session not found" }));
|
|
176
|
+
return;
|
|
177
|
+
}
|
|
178
|
+
if (!state.sessions.get(sessionId).initialized && method !== "notifications/initialized") {
|
|
179
|
+
res.writeHead(400, { "Content-Type": "application/json" });
|
|
180
|
+
res.end(JSON.stringify(jsonRpcError(typeof parsed === "object" && parsed !== null && "id" in parsed ? parsed.id : null, -32002, "Session not initialized")));
|
|
181
|
+
return;
|
|
182
|
+
}
|
|
183
|
+
await dispatcher(req, res, body);
|
|
184
|
+
};
|
|
185
|
+
}
|
|
186
|
+
|
|
187
|
+
//#endregion
|
|
188
|
+
exports.createMCPRequestHandler = createMCPRequestHandler;
|
|
189
|
+
//# sourceMappingURL=mcp-handler.cjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"mcp-handler.cjs","names":["createJsonRpcDispatcher"],"sources":["../src/mcp-handler.ts"],"sourcesContent":["import type * as http from \"node:http\";\nimport { randomUUID } from \"node:crypto\";\nimport { createJsonRpcDispatcher } from \"./jsonrpc.js\";\nimport type {\n MCPToolDefinition,\n MCPResourceDefinition,\n MCPResourceContent,\n MCPPromptDefinition,\n MCPPromptResult,\n MCPContent,\n MCPSession,\n} from \"./mcp-types.js\";\n\nexport interface MCPState {\n serverInfo: { name: string; version: string };\n tools: Map<string, { def: MCPToolDefinition; handler?: (...args: unknown[]) => unknown }>;\n resources: Map<string, { def: MCPResourceDefinition; content?: MCPResourceContent }>;\n prompts: Map<\n string,\n {\n def: MCPPromptDefinition;\n handler?: (...args: unknown[]) => MCPPromptResult | Promise<MCPPromptResult>;\n }\n >;\n sessions: Map<string, MCPSession>;\n}\n\nfunction jsonRpcResult(id: string | number, result: unknown) {\n return { jsonrpc: \"2.0\" as const, id, result };\n}\n\nfunction jsonRpcError(id: string | number | null, code: number, message: string) {\n return { jsonrpc: \"2.0\" as const, id, error: { code, message } };\n}\n\nexport function createMCPRequestHandler(state: MCPState) {\n const dispatcher = createJsonRpcDispatcher({\n methods: {\n // initialize is handled directly in the outer function — this entry is\n // only here so the dispatcher doesn't return \"Method not found\" if the\n // request somehow reaches it.\n initialize: async (_params, id) => {\n return jsonRpcResult(id, {\n protocolVersion: \"2025-03-26\",\n capabilities: { tools: {}, resources: {}, prompts: {} },\n serverInfo: state.serverInfo,\n });\n },\n\n \"notifications/initialized\": async (_params, _id, req) => {\n const sessionId = req.headers[\"mcp-session-id\"] as string;\n const session = state.sessions.get(sessionId);\n if (session) {\n session.initialized = true;\n }\n return null;\n },\n\n ping: async (_params, id) => {\n return jsonRpcResult(id, {});\n },\n\n \"tools/list\": async (_params, id) => {\n const tools: MCPToolDefinition[] = [];\n for (const { def } of state.tools.values()) {\n tools.push(def);\n }\n return jsonRpcResult(id, { tools });\n },\n\n \"tools/call\": async (params, id) => {\n const { name, arguments: args } = (params ?? {}) as { name?: string; arguments?: unknown };\n if (!name) {\n return jsonRpcError(id, -32602, \"Missing tool name\");\n }\n const entry = state.tools.get(name);\n if (!entry) {\n return jsonRpcError(id, -32602, `Unknown tool: ${name}`);\n }\n if (entry.handler) {\n try {\n const result = await entry.handler(args);\n const content: MCPContent[] = Array.isArray(result)\n ? result\n : [{ type: \"text\", text: String(result) }];\n return jsonRpcResult(id, { content, isError: false });\n } catch (err: unknown) {\n const message = err instanceof Error ? err.message : String(err);\n return jsonRpcResult(id, {\n content: [{ type: \"text\", text: message }],\n isError: true,\n });\n }\n }\n // No handler — return empty content\n return jsonRpcResult(id, { content: [], isError: false });\n },\n\n \"resources/list\": async (_params, id) => {\n const resources: MCPResourceDefinition[] = [];\n for (const { def } of state.resources.values()) {\n resources.push(def);\n }\n return jsonRpcResult(id, { resources });\n },\n\n \"resources/read\": async (params, id) => {\n const { uri } = (params ?? {}) as { uri?: string };\n if (!uri) {\n return jsonRpcError(id, -32602, \"Missing resource URI\");\n }\n const entry = state.resources.get(uri);\n if (!entry) {\n return jsonRpcError(id, -32602, `Unknown resource: ${uri}`);\n }\n return jsonRpcResult(id, {\n contents: [\n {\n uri,\n ...(entry.content?.text !== undefined && { text: entry.content.text }),\n ...(entry.content?.blob !== undefined && { blob: entry.content.blob }),\n ...(entry.content?.mimeType !== undefined && { mimeType: entry.content.mimeType }),\n },\n ],\n });\n },\n\n \"prompts/list\": async (_params, id) => {\n const prompts: MCPPromptDefinition[] = [];\n for (const { def } of state.prompts.values()) {\n prompts.push(def);\n }\n return jsonRpcResult(id, { prompts });\n },\n\n \"prompts/get\": async (params, id) => {\n const { name, arguments: args } = (params ?? {}) as { name?: string; arguments?: unknown };\n if (!name) {\n return jsonRpcError(id, -32602, \"Missing prompt name\");\n }\n const entry = state.prompts.get(name);\n if (!entry) {\n return jsonRpcError(id, -32602, `Unknown prompt: ${name}`);\n }\n if (entry.handler) {\n try {\n const result = await entry.handler(args);\n return jsonRpcResult(id, result);\n } catch (err: unknown) {\n const message = err instanceof Error ? err.message : String(err);\n return jsonRpcError(id, -32603, `Prompt handler error: ${message}`);\n }\n }\n // No handler — return empty messages\n return jsonRpcResult(id, { messages: [] });\n },\n },\n });\n\n return async (\n req: http.IncomingMessage,\n res: http.ServerResponse,\n body: string,\n ): Promise<void> => {\n // DELETE handler: session teardown\n if (req.method === \"DELETE\") {\n const sessionId = req.headers[\"mcp-session-id\"] as string | undefined;\n if (!sessionId) {\n res.writeHead(400, { \"Content-Type\": \"application/json\" });\n res.end(JSON.stringify({ error: \"Missing mcp-session-id header\" }));\n return;\n }\n if (!state.sessions.has(sessionId)) {\n res.writeHead(404, { \"Content-Type\": \"application/json\" });\n res.end(JSON.stringify({ error: \"Session not found\" }));\n return;\n }\n state.sessions.delete(sessionId);\n res.writeHead(200, { \"Content-Type\": \"application/json\" });\n res.end(JSON.stringify({ ok: true }));\n return;\n }\n\n // Parse the body to determine method for session validation\n let parsed: unknown;\n try {\n parsed = JSON.parse(body);\n } catch {\n // Let the dispatcher handle parse errors\n await dispatcher(req, res, body);\n return;\n }\n\n const method =\n typeof parsed === \"object\" && parsed !== null && \"method\" in parsed\n ? (parsed as { method: unknown }).method\n : undefined;\n\n // Handle initialize directly to control response headers\n if (method === \"initialize\") {\n const id =\n typeof parsed === \"object\" && parsed !== null && \"id\" in parsed\n ? (parsed as { id: unknown }).id\n : null;\n\n const sessionId = randomUUID();\n state.sessions.set(sessionId, {\n id: sessionId,\n initialized: false,\n createdAt: Date.now(),\n });\n\n const response = {\n jsonrpc: \"2.0\",\n id,\n result: {\n protocolVersion: \"2025-03-26\",\n capabilities: { tools: {}, resources: {}, prompts: {} },\n serverInfo: state.serverInfo,\n },\n };\n\n res.writeHead(200, {\n \"Content-Type\": \"application/json\",\n \"Mcp-Session-Id\": sessionId,\n });\n res.end(JSON.stringify(response));\n return;\n }\n\n // Session validation for all other methods\n const sessionId = req.headers[\"mcp-session-id\"] as string | undefined;\n if (!sessionId) {\n res.writeHead(400, { \"Content-Type\": \"application/json\" });\n res.end(JSON.stringify({ error: \"Missing mcp-session-id header\" }));\n return;\n }\n if (!state.sessions.has(sessionId)) {\n res.writeHead(404, { \"Content-Type\": \"application/json\" });\n res.end(JSON.stringify({ error: \"Session not found\" }));\n return;\n }\n\n // Enforce initialization: only allow notifications/initialized through\n // before the session is fully initialized\n const session = state.sessions.get(sessionId)!;\n if (!session.initialized && method !== \"notifications/initialized\") {\n res.writeHead(400, { \"Content-Type\": \"application/json\" });\n res.end(\n JSON.stringify(\n jsonRpcError(\n typeof parsed === \"object\" && parsed !== null && \"id\" in parsed\n ? ((parsed as { id: unknown }).id as string | number)\n : null,\n -32002,\n \"Session not initialized\",\n ),\n ),\n );\n return;\n }\n\n // Delegate to the JSON-RPC dispatcher for all other methods\n await dispatcher(req, res, body);\n };\n}\n"],"mappings":"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"}
|