vite-plugin-ai-mock 0.1.0 → 0.1.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -2,6 +2,12 @@
2
2
 
3
3
  > English | [中文](./README.zh-CN.md)
4
4
 
5
+ [![npm version](https://img.shields.io/npm/v/vite-plugin-ai-mock?color=4fc08d)](https://www.npmjs.com/package/vite-plugin-ai-mock)
6
+ [![node version](https://img.shields.io/node/v/vite-plugin-ai-mock?color=4fc08d)](https://nodejs.org)
7
+ [![vite peer](https://img.shields.io/badge/vite-%3E%3D5.0.0-646cff)](https://vitejs.dev)
8
+ [![CI](https://img.shields.io/github/actions/workflow/status/quanzhiyuan/vite-plugin-ai-mock/ci.yml?label=CI)](https://github.com/quanzhiyuan/vite-plugin-ai-mock/actions)
9
+ [![license](https://img.shields.io/npm/l/vite-plugin-ai-mock)](./LICENSE)
10
+
5
11
  A standalone Vite plugin for AI scene mocking. Returns streaming data in JSON format, simulating various AI scenarios.
6
12
 
7
13
  - Reads mock files from `mock/ai/*.json`
@@ -63,6 +69,17 @@ Append parameters directly to the request URL, useful for debugging a single end
63
69
  /api/ai/mock/default?firstChunkDelayMs=1000&errorAt=3
64
70
  ```
65
71
 
72
+ ```ts
73
+ const response = await fetch("/api/ai/mock/default?firstChunkDelayMs=4800", {
74
+ method: "POST",
75
+ headers: {
76
+ "Content-Type": "application/json",
77
+ Accept: "text/event-stream",
78
+ },
79
+ body: JSON.stringify({}),
80
+ });
81
+ ```
82
+
66
83
  **2. Plugin option `defaultScenario` (global)**
67
84
 
68
85
  Configure in `vite.config.ts` to apply to all mock requests. URL parameters take precedence and override this:
@@ -70,7 +87,7 @@ Configure in `vite.config.ts` to apply to all mock requests. URL parameters take
70
87
  ```ts
71
88
  aiMockPlugin({
72
89
  defaultScenario: {
73
- scenario: "jitter", // Use a preset scenario name
90
+ scenario: "jitter", // Use a preset scenario name
74
91
  // Individual options override the preset's corresponding values:
75
92
  firstChunkDelayMs: 500,
76
93
  minIntervalMs: 100,
@@ -108,7 +125,18 @@ Each file is a JSON object with a `chunks` array. Every chunk maps to one SSE ev
108
125
 
109
126
  ### Real-world format examples
110
127
 
111
- The `data` field can mirror any real API response. Built-in examples are available in `mock/ai/`:
128
+ The `data` field can mirror any real API response. The package ships with ready-to-use examples in `mock/ai/` — copy them into your project as a starting point:
129
+
130
+ | File | Provider |
131
+ | --- | --- |
132
+ | `mock/ai/openai.json` | OpenAI / compatible |
133
+ | `mock/ai/claude.json` | Anthropic Claude |
134
+ | `mock/ai/gemini.json` | Google Gemini |
135
+ | `mock/ai/deepseek.json` | DeepSeek |
136
+ | `mock/ai/deepseek-reasoner.json` | DeepSeek Reasoner |
137
+ | `mock/ai/qwen.json` | Qwen (Alibaba) |
138
+ | `mock/ai/qwen-thinking.json` | Qwen Thinking |
139
+ | `mock/ai/doubao.json` | Doubao (ByteDance) |
112
140
 
113
141
  **OpenAI / compatible** (`openai.json`) — `data` ends with `"[DONE]"` string:
114
142
 
package/README.zh-CN.md CHANGED
@@ -63,6 +63,17 @@ export default defineConfig({
63
63
  /api/ai/mock/default?firstChunkDelayMs=1000&errorAt=3
64
64
  ```
65
65
 
66
+ ```ts
67
+ const response = await fetch("/api/ai/mock/default?firstChunkDelayMs=4800", {
68
+ method: "POST",
69
+ headers: {
70
+ "Content-Type": "application/json",
71
+ Accept: "text/event-stream",
72
+ },
73
+ body: JSON.stringify({}),
74
+ });
75
+ ```
76
+
66
77
  **2. 插件选项 `defaultScenario`(全局生效)**
67
78
 
68
79
  在 `vite.config.ts` 中配置,对所有 mock 请求生效,可被 URL 参数覆盖:
@@ -108,7 +119,18 @@ aiMockPlugin({
108
119
 
109
120
  ### 主流格式示例
110
121
 
111
- `data` 字段可以完整模拟真实 API 的响应结构,内置示例文件位于 `mock/ai/`:
122
+ `data` 字段可以完整模拟真实 API 的响应结构。npm 包内置了以下示例文件(位于 `mock/ai/`),可直接复制到项目中使用:
123
+
124
+ | 文件 | 提供商 |
125
+ | --- | --- |
126
+ | `mock/ai/openai.json` | OpenAI / 兼容格式 |
127
+ | `mock/ai/claude.json` | Anthropic Claude |
128
+ | `mock/ai/gemini.json` | Google Gemini |
129
+ | `mock/ai/deepseek.json` | DeepSeek |
130
+ | `mock/ai/deepseek-reasoner.json` | DeepSeek Reasoner |
131
+ | `mock/ai/qwen.json` | 通义千问(阿里) |
132
+ | `mock/ai/qwen-thinking.json` | 通义千问 Thinking |
133
+ | `mock/ai/doubao.json` | 豆包(字节跳动) |
112
134
 
113
135
  **OpenAI / 兼容格式**(`openai.json`)——最后一条 `data` 为字符串 `"[DONE]"`:
114
136
 
@@ -0,0 +1,116 @@
1
+ {
2
+ "chunks": [
3
+ {
4
+ "id": "1",
5
+ "event": "message_start",
6
+ "data": {
7
+ "type": "message_start",
8
+ "message": {
9
+ "id": "msg_001",
10
+ "type": "message",
11
+ "role": "assistant",
12
+ "model": "claude-opus-4-5",
13
+ "content": [],
14
+ "stop_reason": null,
15
+ "usage": { "input_tokens": 25, "output_tokens": 0 }
16
+ }
17
+ }
18
+ },
19
+ {
20
+ "id": "2",
21
+ "event": "content_block_start",
22
+ "data": {
23
+ "type": "content_block_start",
24
+ "index": 0,
25
+ "content_block": { "type": "thinking", "thinking": "" }
26
+ }
27
+ },
28
+ {
29
+ "id": "3",
30
+ "event": "content_block_delta",
31
+ "data": {
32
+ "type": "content_block_delta",
33
+ "index": 0,
34
+ "delta": { "type": "thinking_delta", "thinking": "The user is asking about React hooks. I should explain useState and useEffect with clear code examples and markdown formatting." }
35
+ }
36
+ },
37
+ {
38
+ "id": "4",
39
+ "event": "content_block_stop",
40
+ "data": { "type": "content_block_stop", "index": 0 }
41
+ },
42
+ {
43
+ "id": "5",
44
+ "event": "content_block_start",
45
+ "data": {
46
+ "type": "content_block_start",
47
+ "index": 1,
48
+ "content_block": { "type": "text", "text": "" }
49
+ }
50
+ },
51
+ {
52
+ "id": "6",
53
+ "event": "content_block_delta",
54
+ "data": {
55
+ "type": "content_block_delta",
56
+ "index": 1,
57
+ "delta": { "type": "text_delta", "text": "## React Hooks Guide\n\n" }
58
+ }
59
+ },
60
+ {
61
+ "id": "7",
62
+ "event": "content_block_delta",
63
+ "data": {
64
+ "type": "content_block_delta",
65
+ "index": 1,
66
+ "delta": { "type": "text_delta", "text": "Hooks let function components have state and side effects without writing classes.\n\n### `useState`\n\n" }
67
+ }
68
+ },
69
+ {
70
+ "id": "8",
71
+ "event": "content_block_delta",
72
+ "data": {
73
+ "type": "content_block_delta",
74
+ "index": 1,
75
+ "delta": { "type": "text_delta", "text": "```tsx\nconst [count, setCount] = useState(0);\n// Read: count\n// Update: setCount(count + 1)\n```\n\n" }
76
+ }
77
+ },
78
+ {
79
+ "id": "9",
80
+ "event": "content_block_delta",
81
+ "data": {
82
+ "type": "content_block_delta",
83
+ "index": 1,
84
+ "delta": { "type": "text_delta", "text": "### `useEffect`\n\n```tsx\nuseEffect(() => {\n document.title = `Count: ${count}`;\n return () => { /* cleanup */ };\n}, [count]); // Dependency array\n```\n\n" }
85
+ }
86
+ },
87
+ {
88
+ "id": "10",
89
+ "event": "content_block_delta",
90
+ "data": {
91
+ "type": "content_block_delta",
92
+ "index": 1,
93
+ "delta": { "type": "text_delta", "text": "| Hook | Purpose |\n|------|---------|\n| `useState` | Local state |\n| `useEffect` | Side effects (fetch, subscriptions) |\n| `useRef` | DOM references / values across renders |\n| `useMemo` | Cache computed results |" }
94
+ }
95
+ },
96
+ {
97
+ "id": "11",
98
+ "event": "content_block_stop",
99
+ "data": { "type": "content_block_stop", "index": 1 }
100
+ },
101
+ {
102
+ "id": "12",
103
+ "event": "message_delta",
104
+ "data": {
105
+ "type": "message_delta",
106
+ "delta": { "stop_reason": "end_turn", "stop_sequence": null },
107
+ "usage": { "output_tokens": 120 }
108
+ }
109
+ },
110
+ {
111
+ "id": "13",
112
+ "event": "message_stop",
113
+ "data": { "type": "message_stop" }
114
+ }
115
+ ]
116
+ }
@@ -0,0 +1,79 @@
1
+ {
2
+ "chunks": [
3
+ {
4
+ "id": "1",
5
+ "event": "message",
6
+ "data": {
7
+ "id": "chatcmpl-dsr-001",
8
+ "object": "chat.completion.chunk",
9
+ "model": "deepseek-reasoner",
10
+ "choices": [{ "index": 0, "delta": { "role": "assistant", "content": "", "reasoning_content": null }, "finish_reason": null }]
11
+ }
12
+ },
13
+ {
14
+ "id": "2",
15
+ "event": "message",
16
+ "data": {
17
+ "id": "chatcmpl-dsr-001",
18
+ "object": "chat.completion.chunk",
19
+ "model": "deepseek-reasoner",
20
+ "choices": [{ "index": 0, "delta": { "reasoning_content": "The user wants to know the time complexity of bubble sort. Let me think through this carefully." }, "finish_reason": null }]
21
+ }
22
+ },
23
+ {
24
+ "id": "3",
25
+ "event": "message",
26
+ "data": {
27
+ "id": "chatcmpl-dsr-001",
28
+ "object": "chat.completion.chunk",
29
+ "model": "deepseek-reasoner",
30
+ "choices": [{ "index": 0, "delta": { "reasoning_content": " Bubble sort has two nested loops, each running up to n iterations, giving O(n²) in the worst case. Best case with early termination is O(n)." }, "finish_reason": null }]
31
+ }
32
+ },
33
+ {
34
+ "id": "4",
35
+ "event": "message",
36
+ "data": {
37
+ "id": "chatcmpl-dsr-001",
38
+ "object": "chat.completion.chunk",
39
+ "model": "deepseek-reasoner",
40
+ "choices": [{ "index": 0, "delta": { "content": "## Bubble Sort Complexity\n\n" }, "finish_reason": null }]
41
+ }
42
+ },
43
+ {
44
+ "id": "5",
45
+ "event": "message",
46
+ "data": {
47
+ "id": "chatcmpl-dsr-001",
48
+ "object": "chat.completion.chunk",
49
+ "model": "deepseek-reasoner",
50
+ "choices": [{ "index": 0, "delta": { "content": "Bubble sort repeatedly swaps adjacent elements that are in the wrong order.\n\n" }, "finish_reason": null }]
51
+ }
52
+ },
53
+ {
54
+ "id": "6",
55
+ "event": "message",
56
+ "data": {
57
+ "id": "chatcmpl-dsr-001",
58
+ "object": "chat.completion.chunk",
59
+ "model": "deepseek-reasoner",
60
+ "choices": [{ "index": 0, "delta": { "content": "| Case | Time | Space |\n|------|------|-------|\n| Best | O(n) | O(1) |\n| Average | O(n²) | O(1) |\n| Worst | O(n²) | O(1) |\n\n> **Note:** Best case requires an early-exit flag to detect an already-sorted array." }, "finish_reason": null }]
61
+ }
62
+ },
63
+ {
64
+ "id": "7",
65
+ "event": "message",
66
+ "data": {
67
+ "id": "chatcmpl-dsr-001",
68
+ "object": "chat.completion.chunk",
69
+ "model": "deepseek-reasoner",
70
+ "choices": [{ "index": 0, "delta": {}, "finish_reason": "stop" }]
71
+ }
72
+ },
73
+ {
74
+ "id": "8",
75
+ "event": "message",
76
+ "data": "[DONE]"
77
+ }
78
+ ]
79
+ }
@@ -0,0 +1,69 @@
1
+ {
2
+ "chunks": [
3
+ {
4
+ "id": "1",
5
+ "event": "message",
6
+ "data": {
7
+ "id": "chatcmpl-ds-001",
8
+ "object": "chat.completion.chunk",
9
+ "model": "deepseek-chat",
10
+ "choices": [{ "index": 0, "delta": { "role": "assistant", "content": "" }, "finish_reason": null }]
11
+ }
12
+ },
13
+ {
14
+ "id": "2",
15
+ "event": "message",
16
+ "data": {
17
+ "id": "chatcmpl-ds-001",
18
+ "object": "chat.completion.chunk",
19
+ "model": "deepseek-chat",
20
+ "choices": [{ "index": 0, "delta": { "content": "## Quick Sort\n\n" }, "finish_reason": null }]
21
+ }
22
+ },
23
+ {
24
+ "id": "3",
25
+ "event": "message",
26
+ "data": {
27
+ "id": "chatcmpl-ds-001",
28
+ "object": "chat.completion.chunk",
29
+ "model": "deepseek-chat",
30
+ "choices": [{ "index": 0, "delta": { "content": "Quick sort works by selecting a **pivot** element and partitioning the array:\n\n" }, "finish_reason": null }]
31
+ }
32
+ },
33
+ {
34
+ "id": "4",
35
+ "event": "message",
36
+ "data": {
37
+ "id": "chatcmpl-ds-001",
38
+ "object": "chat.completion.chunk",
39
+ "model": "deepseek-chat",
40
+ "choices": [{ "index": 0, "delta": { "content": "```python\ndef quick_sort(arr):\n if len(arr) <= 1:\n return arr\n pivot = arr[len(arr) // 2]\n left = [x for x in arr if x < pivot]\n mid = [x for x in arr if x == pivot]\n right= [x for x in arr if x > pivot]\n return quick_sort(left) + mid + quick_sort(right)\n```\n\n" }, "finish_reason": null }]
41
+ }
42
+ },
43
+ {
44
+ "id": "5",
45
+ "event": "message",
46
+ "data": {
47
+ "id": "chatcmpl-ds-001",
48
+ "object": "chat.completion.chunk",
49
+ "model": "deepseek-chat",
50
+ "choices": [{ "index": 0, "delta": { "content": "| Case | Time Complexity |\n|------|-----------------|\n| Best | O(n log n) |\n| Average | O(n log n) |\n| Worst | O(n²) |" }, "finish_reason": null }]
51
+ }
52
+ },
53
+ {
54
+ "id": "6",
55
+ "event": "message",
56
+ "data": {
57
+ "id": "chatcmpl-ds-001",
58
+ "object": "chat.completion.chunk",
59
+ "model": "deepseek-chat",
60
+ "choices": [{ "index": 0, "delta": {}, "finish_reason": "stop" }]
61
+ }
62
+ },
63
+ {
64
+ "id": "7",
65
+ "event": "message",
66
+ "data": "[DONE]"
67
+ }
68
+ ]
69
+ }
@@ -0,0 +1,7 @@
1
+ {
2
+ "chunks": [
3
+ { "id": "1", "event": "message", "data": { "delta": "Hello" } },
4
+ { "id": "2", "event": "message", "data": { "delta": ", " } },
5
+ { "id": "3", "event": "message", "data": { "delta": "world!" } }
6
+ ]
7
+ }
@@ -0,0 +1,69 @@
1
+ {
2
+ "chunks": [
3
+ {
4
+ "id": "1",
5
+ "event": "message",
6
+ "data": {
7
+ "id": "chatcmpl-db-001",
8
+ "object": "chat.completion.chunk",
9
+ "model": "doubao-pro-32k",
10
+ "choices": [{ "index": 0, "delta": { "role": "assistant", "content": "" }, "finish_reason": null }]
11
+ }
12
+ },
13
+ {
14
+ "id": "2",
15
+ "event": "message",
16
+ "data": {
17
+ "id": "chatcmpl-db-001",
18
+ "object": "chat.completion.chunk",
19
+ "model": "doubao-pro-32k",
20
+ "choices": [{ "index": 0, "delta": { "content": "## CSS Grid Layout Guide\n\n" }, "finish_reason": null }]
21
+ }
22
+ },
23
+ {
24
+ "id": "3",
25
+ "event": "message",
26
+ "data": {
27
+ "id": "chatcmpl-db-001",
28
+ "object": "chat.completion.chunk",
29
+ "model": "doubao-pro-32k",
30
+ "choices": [{ "index": 0, "delta": { "content": "CSS Grid is a two-dimensional layout system that controls both **rows** and **columns**, ideal for complex page structures.\n\n" }, "finish_reason": null }]
31
+ }
32
+ },
33
+ {
34
+ "id": "4",
35
+ "event": "message",
36
+ "data": {
37
+ "id": "chatcmpl-db-001",
38
+ "object": "chat.completion.chunk",
39
+ "model": "doubao-pro-32k",
40
+ "choices": [{ "index": 0, "delta": { "content": "### Basic Usage\n\n```css\n.container {\n display: grid;\n grid-template-columns: repeat(3, 1fr);\n grid-template-rows: auto;\n gap: 16px;\n}\n```\n\n" }, "finish_reason": null }]
41
+ }
42
+ },
43
+ {
44
+ "id": "5",
45
+ "event": "message",
46
+ "data": {
47
+ "id": "chatcmpl-db-001",
48
+ "object": "chat.completion.chunk",
49
+ "model": "doubao-pro-32k",
50
+ "choices": [{ "index": 0, "delta": { "content": "### Common Properties\n\n| Property | Function |\n|----------|----------|\n| `grid-template-columns` | Define columns count and width |\n| `grid-template-rows` | Define rows count and height |\n| `gap` | Row and column spacing |\n| `grid-area` | Child element area placement |\n\n> Tip: Works best with Flexbox: Grid for overall layout, Flex for local alignment." }, "finish_reason": null }]
51
+ }
52
+ },
53
+ {
54
+ "id": "6",
55
+ "event": "message",
56
+ "data": {
57
+ "id": "chatcmpl-db-001",
58
+ "object": "chat.completion.chunk",
59
+ "model": "doubao-pro-32k",
60
+ "choices": [{ "index": 0, "delta": {}, "finish_reason": "stop" }]
61
+ }
62
+ },
63
+ {
64
+ "id": "7",
65
+ "event": "message",
66
+ "data": "[DONE]"
67
+ }
68
+ ]
69
+ }
@@ -0,0 +1,61 @@
1
+ {
2
+ "chunks": [
3
+ {
4
+ "id": "1",
5
+ "event": "message",
6
+ "data": {
7
+ "candidates": [
8
+ {
9
+ "content": { "parts": [{ "text": "## Async/Await in JavaScript\n\n" }], "role": "model" },
10
+ "finishReason": null,
11
+ "index": 0
12
+ }
13
+ ],
14
+ "modelVersion": "gemini-2.0-flash"
15
+ }
16
+ },
17
+ {
18
+ "id": "2",
19
+ "event": "message",
20
+ "data": {
21
+ "candidates": [
22
+ {
23
+ "content": { "parts": [{ "text": "`async/await` is syntactic sugar over Promises, making asynchronous code read like synchronous code.\n\n" }], "role": "model" },
24
+ "finishReason": null,
25
+ "index": 0
26
+ }
27
+ ],
28
+ "modelVersion": "gemini-2.0-flash"
29
+ }
30
+ },
31
+ {
32
+ "id": "3",
33
+ "event": "message",
34
+ "data": {
35
+ "candidates": [
36
+ {
37
+ "content": { "parts": [{ "text": "```js\nasync function fetchUser(id) {\n try {\n const res = await fetch(`/api/users/${id}`);\n if (!res.ok) throw new Error(`HTTP ${res.status}`);\n return await res.json();\n } catch (err) {\n console.error('Failed:', err);\n }\n}\n```\n\n" }], "role": "model" },
38
+ "finishReason": null,
39
+ "index": 0
40
+ }
41
+ ],
42
+ "modelVersion": "gemini-2.0-flash"
43
+ }
44
+ },
45
+ {
46
+ "id": "4",
47
+ "event": "message",
48
+ "data": {
49
+ "candidates": [
50
+ {
51
+ "content": { "parts": [{ "text": "### Key Rules\n\n- `await` can only be used inside an `async` function\n- `await` pauses execution **within the function only**\n- Errors propagate via `try/catch` or `.catch()` on the returned Promise\n\n| Pattern | Use when |\n|---------|----------|\n| `await` sequentially | Each call depends on the previous |\n| `Promise.all([...])` | Independent parallel calls |" }], "role": "model" },
52
+ "finishReason": "STOP",
53
+ "index": 0
54
+ }
55
+ ],
56
+ "usageMetadata": { "promptTokenCount": 18, "candidatesTokenCount": 110, "totalTokenCount": 128 },
57
+ "modelVersion": "gemini-2.0-flash"
58
+ }
59
+ }
60
+ ]
61
+ }
@@ -0,0 +1,69 @@
1
+ {
2
+ "chunks": [
3
+ {
4
+ "id": "1",
5
+ "event": "message",
6
+ "data": {
7
+ "id": "chatcmpl-001",
8
+ "object": "chat.completion.chunk",
9
+ "model": "gpt-4o",
10
+ "choices": [{ "index": 0, "delta": { "role": "assistant", "content": "" }, "finish_reason": null }]
11
+ }
12
+ },
13
+ {
14
+ "id": "2",
15
+ "event": "message",
16
+ "data": {
17
+ "id": "chatcmpl-001",
18
+ "object": "chat.completion.chunk",
19
+ "model": "gpt-4o",
20
+ "choices": [{ "index": 0, "delta": { "content": "## TypeScript Generics\n\n" }, "finish_reason": null }]
21
+ }
22
+ },
23
+ {
24
+ "id": "3",
25
+ "event": "message",
26
+ "data": {
27
+ "id": "chatcmpl-001",
28
+ "object": "chat.completion.chunk",
29
+ "model": "gpt-4o",
30
+ "choices": [{ "index": 0, "delta": { "content": "Generics allow you to write **reusable, type-safe** functions and classes.\n\n" }, "finish_reason": null }]
31
+ }
32
+ },
33
+ {
34
+ "id": "4",
35
+ "event": "message",
36
+ "data": {
37
+ "id": "chatcmpl-001",
38
+ "object": "chat.completion.chunk",
39
+ "model": "gpt-4o",
40
+ "choices": [{ "index": 0, "delta": { "content": "```ts\nfunction identity<T>(value: T): T {\n return value;\n}\n\n// Usage\nconst num = identity<number>(42); // T = number\nconst str = identity(\"hello\"); // T inferred as string\n```\n\n" }, "finish_reason": null }]
41
+ }
42
+ },
43
+ {
44
+ "id": "5",
45
+ "event": "message",
46
+ "data": {
47
+ "id": "chatcmpl-001",
48
+ "object": "chat.completion.chunk",
49
+ "model": "gpt-4o",
50
+ "choices": [{ "index": 0, "delta": { "content": "### Constraints\n\n```ts\nfunction getLength<T extends { length: number }>(arg: T): number {\n return arg.length;\n}\n```\n\n> Use `extends` to restrict `T` to types that have specific properties." }, "finish_reason": null }]
51
+ }
52
+ },
53
+ {
54
+ "id": "6",
55
+ "event": "message",
56
+ "data": {
57
+ "id": "chatcmpl-001",
58
+ "object": "chat.completion.chunk",
59
+ "model": "gpt-4o",
60
+ "choices": [{ "index": 0, "delta": {}, "finish_reason": "stop" }]
61
+ }
62
+ },
63
+ {
64
+ "id": "7",
65
+ "event": "message",
66
+ "data": "[DONE]"
67
+ }
68
+ ]
69
+ }
@@ -0,0 +1,79 @@
1
+ {
2
+ "chunks": [
3
+ {
4
+ "id": "1",
5
+ "event": "message",
6
+ "data": {
7
+ "id": "chatcmpl-qwt-001",
8
+ "object": "chat.completion.chunk",
9
+ "model": "qwq-plus",
10
+ "choices": [{ "index": 0, "delta": { "role": "assistant", "content": "", "reasoning_content": null }, "finish_reason": null }]
11
+ }
12
+ },
13
+ {
14
+ "id": "2",
15
+ "event": "message",
16
+ "data": {
17
+ "id": "chatcmpl-qwt-001",
18
+ "object": "chat.completion.chunk",
19
+ "model": "qwq-plus",
20
+ "choices": [{ "index": 0, "delta": { "reasoning_content": "The user is asking about the Fibonacci recurrence formula. This is a basic math problem." }, "finish_reason": null }]
21
+ }
22
+ },
23
+ {
24
+ "id": "3",
25
+ "event": "message",
26
+ "data": {
27
+ "id": "chatcmpl-qwt-001",
28
+ "object": "chat.completion.chunk",
29
+ "model": "qwq-plus",
30
+ "choices": [{ "index": 0, "delta": { "reasoning_content": " F(n) = F(n-1) + F(n-2), with base cases F(0)=0, F(1)=1. I should provide the definition, formula, and a short code example." }, "finish_reason": null }]
31
+ }
32
+ },
33
+ {
34
+ "id": "4",
35
+ "event": "message",
36
+ "data": {
37
+ "id": "chatcmpl-qwt-001",
38
+ "object": "chat.completion.chunk",
39
+ "model": "qwq-plus",
40
+ "choices": [{ "index": 0, "delta": { "content": "## Fibonacci Sequence\n\n" }, "finish_reason": null }]
41
+ }
42
+ },
43
+ {
44
+ "id": "5",
45
+ "event": "message",
46
+ "data": {
47
+ "id": "chatcmpl-qwt-001",
48
+ "object": "chat.completion.chunk",
49
+ "model": "qwq-plus",
50
+ "choices": [{ "index": 0, "delta": { "content": "**Recurrence Formula:**\n\n$$F(n) = F(n-1) + F(n-2), \\quad F(0)=0,\\ F(1)=1$$\n\n" }, "finish_reason": null }]
51
+ }
52
+ },
53
+ {
54
+ "id": "6",
55
+ "event": "message",
56
+ "data": {
57
+ "id": "chatcmpl-qwt-001",
58
+ "object": "chat.completion.chunk",
59
+ "model": "qwq-plus",
60
+ "choices": [{ "index": 0, "delta": { "content": "First 10 terms: `0, 1, 1, 2, 3, 5, 8, 13, 21, 34`\n\n```python\ndef fib(n):\n a, b = 0, 1\n for _ in range(n):\n a, b = b, a + b\n return a\n```" }, "finish_reason": null }]
61
+ }
62
+ },
63
+ {
64
+ "id": "7",
65
+ "event": "message",
66
+ "data": {
67
+ "id": "chatcmpl-qwt-001",
68
+ "object": "chat.completion.chunk",
69
+ "model": "qwq-plus",
70
+ "choices": [{ "index": 0, "delta": {}, "finish_reason": "stop" }]
71
+ }
72
+ },
73
+ {
74
+ "id": "8",
75
+ "event": "message",
76
+ "data": "[DONE]"
77
+ }
78
+ ]
79
+ }
@@ -0,0 +1,69 @@
1
+ {
2
+ "chunks": [
3
+ {
4
+ "id": "1",
5
+ "event": "message",
6
+ "data": {
7
+ "id": "chatcmpl-qw-001",
8
+ "object": "chat.completion.chunk",
9
+ "model": "qwen-plus",
10
+ "choices": [{ "index": 0, "delta": { "role": "assistant", "content": "" }, "finish_reason": null }]
11
+ }
12
+ },
13
+ {
14
+ "id": "2",
15
+ "event": "message",
16
+ "data": {
17
+ "id": "chatcmpl-qw-001",
18
+ "object": "chat.completion.chunk",
19
+ "model": "qwen-plus",
20
+ "choices": [{ "index": 0, "delta": { "content": "## What is Transformer?\n\n" }, "finish_reason": null }]
21
+ }
22
+ },
23
+ {
24
+ "id": "3",
25
+ "event": "message",
26
+ "data": {
27
+ "id": "chatcmpl-qw-001",
28
+ "object": "chat.completion.chunk",
29
+ "model": "qwen-plus",
30
+ "choices": [{ "index": 0, "delta": { "content": "Transformer is a neural network architecture based on the **Self-Attention** mechanism, proposed by Google in the 2017 paper *Attention Is All You Need*.\n\n" }, "finish_reason": null }]
31
+ }
32
+ },
33
+ {
34
+ "id": "4",
35
+ "event": "message",
36
+ "data": {
37
+ "id": "chatcmpl-qw-001",
38
+ "object": "chat.completion.chunk",
39
+ "model": "qwen-plus",
40
+ "choices": [{ "index": 0, "delta": { "content": "### Core Components\n\n1. **Multi-Head Attention** — Captures dependencies across different subspaces in parallel\n2. **Feed-Forward Network** — Applies non-linear transformations independently at each position\n3. **Positional Encoding** — Injects position information into the sequence\n\n" }, "finish_reason": null }]
41
+ }
42
+ },
43
+ {
44
+ "id": "5",
45
+ "event": "message",
46
+ "data": {
47
+ "id": "chatcmpl-qw-001",
48
+ "object": "chat.completion.chunk",
49
+ "model": "qwen-plus",
50
+ "choices": [{ "index": 0, "delta": { "content": "```\nInput → Embedding + Positional Encoding\n → N × (Multi-Head Attention → Add&Norm → FFN → Add&Norm)\n → Output\n```" }, "finish_reason": null }]
51
+ }
52
+ },
53
+ {
54
+ "id": "6",
55
+ "event": "message",
56
+ "data": {
57
+ "id": "chatcmpl-qw-001",
58
+ "object": "chat.completion.chunk",
59
+ "model": "qwen-plus",
60
+ "choices": [{ "index": 0, "delta": {}, "finish_reason": "stop" }]
61
+ }
62
+ },
63
+ {
64
+ "id": "7",
65
+ "event": "message",
66
+ "data": "[DONE]"
67
+ }
68
+ ]
69
+ }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "vite-plugin-ai-mock",
3
- "version": "0.1.0",
3
+ "version": "0.1.1",
4
4
  "description": "A Vite plugin for AI streaming mock (SSE/JSON) with configurable scenarios.",
5
5
  "license": "MIT",
6
6
  "type": "module",
@@ -16,6 +16,7 @@
16
16
  },
17
17
  "files": [
18
18
  "dist",
19
+ "mock",
19
20
  "README.md",
20
21
  "README.zh-CN.md",
21
22
  "LICENSE"
@@ -27,6 +28,14 @@
27
28
  "sse",
28
29
  "ai"
29
30
  ],
31
+ "repository": {
32
+ "type": "git",
33
+ "url": "https://github.com/quanzhiyuan/vite-plugin-ai-mock"
34
+ },
35
+ "homepage": "https://github.com/quanzhiyuan/vite-plugin-ai-mock#readme",
36
+ "bugs": {
37
+ "url": "https://github.com/quanzhiyuan/vite-plugin-ai-mock/issues"
38
+ },
30
39
  "engines": {
31
40
  "node": ">=18"
32
41
  },