diff --git a/docs/chaos-testing/index.html b/docs/chaos-testing/index.html index cdbbbde7..3a51a323 100644 --- a/docs/chaos-testing/index.html +++ b/docs/chaos-testing/index.html @@ -217,7 +217,7 @@

CLI Flags

CLI chaos flags shell
-
$ npx @copilotkit/aimock --fixtures ./fixtures \
+              
$ npx -p @copilotkit/aimock llmock --fixtures ./fixtures \
   --chaos-drop 0.1 \
   --chaos-malformed 0.05 \
   --chaos-disconnect 0.02
@@ -254,7 +254,7 @@

Journal Tracking

"path": "/v1/chat/completions", "response": { "status": 500, - "fixture": { "..." }, + "fixture": { "...": "elided for brevity" }, "chaosAction": "drop" } }
diff --git a/docs/migrate-from-mock-llm/index.html b/docs/migrate-from-mock-llm/index.html index bac7c2d4..a83c210f 100644 --- a/docs/migrate-from-mock-llm/index.html +++ b/docs/migrate-from-mock-llm/index.html @@ -242,7 +242,7 @@

Zero dependencies

📦

Vector DB mocking

-

Mock Pinecone, Qdrant, Weaviate, and ChromaDB endpoints for RAG pipeline testing.

+

Mock Pinecone, Qdrant, and ChromaDB endpoints for RAG pipeline testing.

@@ -446,6 +446,20 @@

Kubernetes migration

mountPath: /app/fixtures existingClaim: "" # PVC for fixture files +livenessProbe: + httpGet: + path: /health + port: 4010 + initialDelaySeconds: 5 + periodSeconds: 10 + +readinessProbe: + httpGet: + path: /ready + port: 4010 + initialDelaySeconds: 2 + periodSeconds: 5 + resources: {} # limits: # cpu: 200m @@ -477,8 +491,8 @@

CLI / Docker quick start

Install & run sh
-
# Run the mock server
-npx @copilotkit/aimock -p 4010 -f ./fixtures
+              
# Run the mock server (flag-driven llmock bin)
+npx -p @copilotkit/aimock llmock -p 4010 -f ./fixtures
 
 # With a full config file
 npx @copilotkit/aimock --config aimock.json --port 4010
diff --git a/docs/migrate-from-mokksy/index.html b/docs/migrate-from-mokksy/index.html
index 3f044759..c22fd96b 100644
--- a/docs/migrate-from-mokksy/index.html
+++ b/docs/migrate-from-mokksy/index.html
@@ -153,16 +153,19 @@ 

The quick switch

"-p", "4010:4010", "-v", "./fixtures:/fixtures", "ghcr.io/copilotkit/aimock", "-f", "/fixtures", "-h", "0.0.0.0") .start().waitFor() - // Wait for server to be ready + // Wait for server to be ready — fail loudly if it never comes up + var lastError: Exception? = null repeat(30) { try { - java.net.URL("http://localhost:4010/__aimock/health") + java.net.URL("http://localhost:4010/health") .readText() return - } catch (_: Exception) { + } catch (e: Exception) { + lastError = e Thread.sleep(200) } } + throw IllegalStateException("aimock did not become healthy after 30 attempts", lastError) } @AfterAll @@ -403,7 +406,7 @@

CLI / Docker quick start

CLI sh
-
npx @copilotkit/aimock -p 4010 -f ./fixtures
+
npx -p @copilotkit/aimock llmock -p 4010 -f ./fixtures
diff --git a/docs/migrate-from-msw/index.html b/docs/migrate-from-msw/index.html index e04cf47e..886d2e54 100644 --- a/docs/migrate-from-msw/index.html +++ b/docs/migrate-from-msw/index.html @@ -250,14 +250,21 @@

Built-in SSE for 8 providers

🔌

WebSocket APIs

-

OpenAI Realtime, Responses WS, Gemini Live. MSW cannot intercept WebSocket.

+

+ OpenAI Realtime, Responses WS, Gemini Live — all built in. MSW v2 added + WebSocket interception via ws.link(), but you still handwrite every + frame; aimock ships the full provider handshakes. +

Record & Replay

Proxy real APIs, save as fixtures, replay forever. - npx @copilotkit/aimock --record --provider-openai https://api.openai.com + npx -p @copilotkit/aimock llmock --record --provider-openai + https://api.openai.com

@@ -311,9 +318,9 @@

What you keep (or lose)

WebSocket - ✗ - ✓ - 3 protocols + Manual (ws.link, v2+) + Built-in + 3 AI protocols Record & replay @@ -347,6 +354,7 @@

Using aimock alongside MSW

test-setup.ts ts
// test setup
 import { setupServer } from 'msw/node'
+import { http, HttpResponse } from 'msw'
 import { LLMock } from '@copilotkit/aimock'
 
 // MSW for REST APIs
@@ -372,7 +380,7 @@ 

CLI / Docker quick start

CLI sh
-
npx @copilotkit/aimock -p 4010 -f ./fixtures
+
npx -p @copilotkit/aimock llmock -p 4010 -f ./fixtures
diff --git a/docs/migrate-from-openai-responses/index.html b/docs/migrate-from-openai-responses/index.html index 1e54d1b8..c9abebe5 100644 --- a/docs/migrate-from-openai-responses/index.html +++ b/docs/migrate-from-openai-responses/index.html @@ -183,7 +183,7 @@

Before / After

from openai import OpenAI
 
 def test_chat(aimock):
-    aimock.on_message("hi", content="Hello!")
+    aimock.on_message("hi", {"content": "Hello!"})
     client = OpenAI(base_url=aimock.url + "/v1", api_key="test")
     result = client.chat.completions.create(
         model="gpt-4o", messages=[{"role": "user", "content": "hi"}]
@@ -266,7 +266,7 @@ 

Feature mapping

openai_mock.chat.completions.create.response = {...} - aimock.on_message("pattern", content="...") + aimock.on_message("pattern", {"content": "..."}) Partial envelope (choices required, other fields auto-filled) diff --git a/docs/migrate-from-piyook/index.html b/docs/migrate-from-piyook/index.html index 00fc6aea..67e31b1c 100644 --- a/docs/migrate-from-piyook/index.html +++ b/docs/migrate-from-piyook/index.html @@ -191,14 +191,14 @@

Fixture format comparison

{
   "match": { "userMessage": "hello" },
   "response": { "content": "Hello there" }
-}
-
-// aimock auto-generates:
-//   - id, object, created, model
-//   - choices[].index, finish_reason
-//   - usage (prompt_tokens, completion_tokens)
-//   - SSE streaming chunks (when stream: true)
+}
+

+ aimock auto-generates id, object, created, + model, choices[].index, finish_reason, + usage (prompt / completion tokens), and SSE streaming chunks when + stream: true. +

@@ -391,8 +391,8 @@

CLI / Docker quick start

Install & run sh
-
# Run the mock server
-npx @copilotkit/aimock -p 4010 -f ./fixtures
+              
# Run the mock server (flag-driven llmock bin)
+npx -p @copilotkit/aimock llmock -p 4010 -f ./fixtures
 
 # With a full config file
 npx @copilotkit/aimock --config aimock.json --port 4010
diff --git a/docs/migrate-from-python-mocks/index.html b/docs/migrate-from-python-mocks/index.html
index 3ee71a42..42b68b57 100644
--- a/docs/migrate-from-python-mocks/index.html
+++ b/docs/migrate-from-python-mocks/index.html
@@ -255,21 +255,41 @@ 

aimock (after)

"ghcr.io/copilotkit/aimock:latest", "-f", "/fixtures", "-h", "0.0.0.0" ]) - # Wait for health endpoint + # Wait for health endpoint — fail loudly if aimock never comes up import requests for _ in range(30): + if proc.poll() is not None: + raise RuntimeError(f"aimock exited early with code {proc.returncode}") try: - if requests.get("http://localhost:4010/__aimock/health").ok: + if requests.get("http://localhost:4010/health").ok: break except requests.ConnectionError: - time.sleep(0.2) - + pass + time.sleep(0.2) + else: + raise RuntimeError("aimock did not become healthy after 30 attempts") + + # Save originals so we don't clobber real credentials in the test process + prev_base = os.environ.get("OPENAI_BASE_URL") + prev_key = os.environ.get("OPENAI_API_KEY") os.environ["OPENAI_BASE_URL"] = "http://localhost:4010/v1" os.environ["OPENAI_API_KEY"] = "mock-key" - yield "http://localhost:4010" - proc.terminate() - proc.wait()
+ try: + yield "http://localhost:4010" + finally: + proc.terminate() + try: + proc.wait(timeout=10) + except subprocess.TimeoutExpired: + proc.kill() + proc.wait(timeout=5) + # Restore originals (or remove if there were none) + for name, val in (("OPENAI_BASE_URL", prev_base), ("OPENAI_API_KEY", prev_key)): + if val is None: + os.environ.pop(name, None) + else: + os.environ[name] = val
@@ -435,8 +455,8 @@

CLI / Docker quick start

Install & run sh
-
# Run the mock server (requires Node.js)
-npx @copilotkit/aimock -p 4010 -f ./fixtures
+              
# Run the mock server (requires Node.js, flag-driven llmock bin)
+npx -p @copilotkit/aimock llmock -p 4010 -f ./fixtures
 
 # Point your Python app at the mock
 export OPENAI_BASE_URL=http://localhost:4010/v1
@@ -490,24 +510,44 @@ 

Alternative: npx fixture (no Docker)

@pytest.fixture(scope="session") def aimock_server(): proc = subprocess.Popen( - ["npx", "aimock", "-p", "4010", "-f", "./fixtures"], - stdout=subprocess.PIPE, stderr=subprocess.STDOUT + ["npx", "-p", "@copilotkit/aimock", "llmock", "-p", "4010", "-f", "./fixtures"], + stdout=subprocess.DEVNULL, stderr=subprocess.DEVNULL ) - # Wait for health endpoint + # Wait for health endpoint — fail loudly if aimock never comes up import requests for _ in range(30): + if proc.poll() is not None: + raise RuntimeError(f"aimock exited early with code {proc.returncode}") try: - if requests.get("http://localhost:4010/__aimock/health").ok: + if requests.get("http://localhost:4010/health").ok: break except requests.ConnectionError: - time.sleep(0.2) - + pass + time.sleep(0.2) + else: + raise RuntimeError("aimock did not become healthy after 30 attempts") + + # Save originals so we don't clobber real credentials in the test process + prev_base = os.environ.get("OPENAI_BASE_URL") + prev_key = os.environ.get("OPENAI_API_KEY") os.environ["OPENAI_BASE_URL"] = "http://localhost:4010/v1" os.environ["OPENAI_API_KEY"] = "mock-key" - yield "http://localhost:4010" - proc.terminate() - proc.wait()
+ try: + yield "http://localhost:4010" + finally: + proc.terminate() + try: + proc.wait(timeout=10) + except subprocess.TimeoutExpired: + proc.kill() + proc.wait(timeout=5) + # Restore originals (or remove if there were none) + for name, val in (("OPENAI_BASE_URL", prev_base), ("OPENAI_API_KEY", prev_key)): + if val is None: + os.environ.pop(name, None) + else: + os.environ[name] = val
diff --git a/docs/migrate-from-vidaimock/index.html b/docs/migrate-from-vidaimock/index.html index 1ea3debb..acdd2a2f 100644 --- a/docs/migrate-from-vidaimock/index.html +++ b/docs/migrate-from-vidaimock/index.html @@ -78,7 +78,7 @@

The quick switch

aimock (equivalent) shell
-
npx @copilotkit/aimock -p 4010 -f ./fixtures
+
npx -p @copilotkit/aimock llmock -p 4010 -f ./fixtures
@@ -286,8 +286,8 @@

CLI / Docker quick start

Install & run shell
-
# Run the mock server
-npx @copilotkit/aimock -p 4010 -f ./fixtures
+              
# Run the mock server (flag-driven llmock bin)
+npx -p @copilotkit/aimock llmock -p 4010 -f ./fixtures
 
 # Point your app at it
 export OPENAI_BASE_URL=http://localhost:4010/v1
diff --git a/docs/record-replay/index.html b/docs/record-replay/index.html
index 4d4a21ce..a3166d29 100644
--- a/docs/record-replay/index.html
+++ b/docs/record-replay/index.html
@@ -89,7 +89,7 @@ 

Proxy-Only Mode

Proxy-only mode shell
-
$ npx @copilotkit/aimock -f ./fixtures \
+              
$ npx -p @copilotkit/aimock llmock -f ./fixtures \
   --proxy-only \
   --provider-openai https://api.openai.com
@@ -140,7 +140,7 @@

Quick Start

CLI usage shell
-
$ npx @copilotkit/aimock -f ./fixtures \
+              
$ npx -p @copilotkit/aimock llmock -f ./fixtures \
   --record \
   --provider-openai https://api.openai.com \
   --provider-anthropic https://api.anthropic.com
@@ -302,20 +302,25 @@

Programmatic API

const mock = new LLMock(); await mock.start(); -// Enable recording — unmatched requests are proxied AND saved as fixtures -mock.enableRecording({ - providers: { - openai: "https://api.openai.com", - anthropic: "https://api.anthropic.com", - }, - fixturePath: "./fixtures/recorded", -}); - -// Make requests — unmatched ones are proxied and recorded -// ... - -// Disable recording — recorded fixtures persist on disk -mock.disableRecording();
+try { + // Enable recording — unmatched requests are proxied AND saved as fixtures + mock.enableRecording({ + providers: { + openai: "https://api.openai.com", + anthropic: "https://api.anthropic.com", + }, + fixturePath: "./fixtures/recorded", + }); + + // Make requests — unmatched ones are proxied and recorded + // ... + + // Disable recording — recorded fixtures persist on disk + mock.disableRecording(); +} finally { + // Always release the port, even if a test above threw + await mock.stop(); +}

@@ -478,10 +483,10 @@

Local Development Workflow

Record then replay shell
# First run: record real API responses
-$ npx @copilotkit/aimock --record --provider-openai https://api.openai.com -f ./fixtures
+$ npx -p @copilotkit/aimock llmock --record --provider-openai https://api.openai.com -f ./fixtures
 
 # Subsequent runs: replay from recorded fixtures
-$ npx @copilotkit/aimock -f ./fixtures
+$ npx -p @copilotkit/aimock llmock -f ./fixtures
@@ -516,7 +521,7 @@

CI Pipeline Workflow

- name: Start aimock
   run: |
-    docker run -d --name aimock \
+    docker run -d --rm --name aimock \
       -v ./fixtures:/fixtures \
       -p 4010:4010 \
       ghcr.io/copilotkit/aimock \
@@ -528,7 +533,8 @@ 

CI Pipeline Workflow

run: pnpm test - name: Stop aimock - run: docker stop aimock
+ if: always() + run: docker rm -f aimock

Request Transform

@@ -686,11 +692,16 @@

Cross-Language Testing

import openai client = openai.OpenAI(base_url="http://localhost:4010/v1", api_key="mock") -# Go -client := openai.NewClient(option.WithBaseURL("http://localhost:4010/v1")) +# Go — github.com/sashabaranov/go-openai +config := openai.DefaultConfig("mock") +config.BaseURL = "http://localhost:4010/v1" +client := openai.NewClientWithConfig(config) -# Rust -let client = Client::new().with_base_url("http://localhost:4010/v1");
+# Rust — async-openai +let config = OpenAIConfig::new() + .with_api_base("http://localhost:4010/v1") + .with_api_key("mock"); +let client = Client::with_config(config);