@pedrofariasx/qwenproxy 1.1.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.
Files changed (59) hide show
  1. package/LICENSE +13 -0
  2. package/README.md +292 -0
  3. package/bin/qwenproxy.mjs +11 -0
  4. package/package.json +56 -0
  5. package/src/api/models.ts +183 -0
  6. package/src/api/server.ts +126 -0
  7. package/src/cache/memory-cache.ts +186 -0
  8. package/src/core/account-manager.ts +132 -0
  9. package/src/core/accounts.ts +78 -0
  10. package/src/core/config.ts +91 -0
  11. package/src/core/database.ts +92 -0
  12. package/src/core/logger.ts +96 -0
  13. package/src/core/metrics.ts +169 -0
  14. package/src/core/model-registry.ts +30 -0
  15. package/src/core/stream-registry.ts +40 -0
  16. package/src/core/watchdog.ts +130 -0
  17. package/src/index.ts +7 -0
  18. package/src/linter/extraction-engine.ts +165 -0
  19. package/src/linter/index.ts +258 -0
  20. package/src/linter/repair-normalize.ts +245 -0
  21. package/src/linter/safety-gate.ts +219 -0
  22. package/src/linter/streaming-state-machine.ts +252 -0
  23. package/src/linter/structural-parser.ts +352 -0
  24. package/src/linter/types.ts +74 -0
  25. package/src/login.ts +228 -0
  26. package/src/routes/chat.ts +801 -0
  27. package/src/routes/upload.ts +700 -0
  28. package/src/services/playwright.ts +778 -0
  29. package/src/services/qwen.ts +500 -0
  30. package/src/tests/advanced.test.ts +227 -0
  31. package/src/tests/agenticStress.test.ts +360 -0
  32. package/src/tests/concurrency.test.ts +103 -0
  33. package/src/tests/concurrentChat.test.ts +71 -0
  34. package/src/tests/delta.test.ts +63 -0
  35. package/src/tests/index.test.ts +356 -0
  36. package/src/tests/jsonFix.test.ts +98 -0
  37. package/src/tests/linter.test.ts +151 -0
  38. package/src/tests/parallel.test.ts +42 -0
  39. package/src/tests/parser.test.ts +89 -0
  40. package/src/tests/rotation.test.ts +45 -0
  41. package/src/tests/streamingOptimizations.test.ts +328 -0
  42. package/src/tests/structureVerification.test.ts +176 -0
  43. package/src/tools/ast.ts +15 -0
  44. package/src/tools/coercion.ts +67 -0
  45. package/src/tools/confidence.ts +48 -0
  46. package/src/tools/detector.ts +40 -0
  47. package/src/tools/executor.ts +236 -0
  48. package/src/tools/parser.ts +446 -0
  49. package/src/tools/pipeline.ts +122 -0
  50. package/src/tools/registry-runtime.ts +34 -0
  51. package/src/tools/registry.ts +142 -0
  52. package/src/tools/repair.ts +42 -0
  53. package/src/tools/schema.ts +285 -0
  54. package/src/tools/types.ts +104 -0
  55. package/src/tools/validator.ts +33 -0
  56. package/src/utils/context-truncation.ts +61 -0
  57. package/src/utils/json.ts +114 -0
  58. package/src/utils/qwen-stream-parser.ts +286 -0
  59. package/src/utils/types.ts +101 -0
@@ -0,0 +1,151 @@
1
+ /*
2
+ * UltraToolCallLinter v1.0 - Edge Case Stress Tests
3
+ * Tests required by spec
4
+ */
5
+
6
+ import { describe, it, beforeEach, afterEach } from 'node:test'
7
+ import assert from 'node:assert'
8
+
9
+ import { UltraToolCallLinter } from '../linter/index.js'
10
+ import type { ParseResult, RawToolCandidate } from '../linter/types.js'
11
+
12
+ // Helper functions to match the old bar.ts API using direct instantiation
13
+ let globalLinter: UltraToolCallLinter | null = null
14
+
15
+ function getGlobalLinter(): UltraToolCallLinter {
16
+ if (!globalLinter) globalLinter = new UltraToolCallLinter()
17
+ return globalLinter
18
+ }
19
+
20
+ function configure(config: { registry?: any; strictMode?: boolean; enableSecurityGate?: boolean; maxRecoveryAttempts?: number; minConfidenceThreshold?: number }): void {
21
+ globalLinter = new UltraToolCallLinter(config)
22
+ }
23
+
24
+ function parseText(input: string): ParseResult {
25
+ return getGlobalLinter().parseText(input)
26
+ }
27
+
28
+ function extract(input: string): RawToolCandidate[] {
29
+ return getGlobalLinter().extract(input)
30
+ }
31
+
32
+ function repair(input: string): string {
33
+ return getGlobalLinter().repair(input)
34
+ }
35
+
36
+ describe('UltraToolCallLinter Edge Cases', () => {
37
+ it('parses truncated JSON in the middle', () => {
38
+ configure({ minConfidenceThreshold: 0.1 })
39
+ const input = 'Here is the query: {"search": {"query": "test"}}'
40
+ const result = parseText(input)
41
+ assert.ok(result.toolCalls.length >= 1)
42
+ assert.equal(result.toolCalls[0].tool, 'search')
43
+ })
44
+
45
+ it('parses concatenated multiple JSONs', () => {
46
+ const input = '{"name":"search","arguments":{"query":"foo"}}{"name":"browser_open","arguments":{"url":"http://x"}}'
47
+ const candidates = extract(input)
48
+ assert.ok(candidates.length >= 1, 'Expected at least one candidate')
49
+ })
50
+
51
+ it('parses markdown-wrapped JSON', () => {
52
+ const input = '```json\n{"tool":"search","input":{"query":"beer"}}\n```'
53
+ const result = parseText(input)
54
+ assert.ok(result.toolCalls.length >= 1)
55
+ assert.equal(result.toolCalls[0].tool, 'search')
56
+ })
57
+
58
+ it('parses human text mixed with a tool call (ReAct)', () => {
59
+ const input =
60
+ 'Sure, let me search that for you.\nAction: search\nAction Input: {"query": "breaking news"}'
61
+ const result = parseText(input)
62
+ assert.ok(result.toolCalls.length >= 1, 'Expected ReAct extraction')
63
+ })
64
+
65
+ it('recovers from broken escape sequences', () => {
66
+ const input = '{"tool":"search","input":{"query":"test\\\\n\\\\t\\\\"}}'
67
+ const result = parseText(input)
68
+ assert.ok(result.toolCalls.length >= 1)
69
+ })
70
+
71
+ it('recovers from unicode corruption', () => {
72
+ const input = '{"tool":"search","input":{"query":"caf\u0000\u001Fé"}}'
73
+ const result = parseText(input)
74
+ assert.ok(result.toolCalls.length >= 1)
75
+ })
76
+
77
+ it('handles streaming with repeated chunks', () => {
78
+ const linter = new UltraToolCallLinter({ minConfidenceThreshold: 0.1 })
79
+ const chunks = [
80
+ 'S',
81
+ 'Su',
82
+ 'Sur',
83
+ 'Sure! ',
84
+ 'Here i',
85
+ 'Here is ',
86
+ 'Here is the ',
87
+ 'Here is the result: ',
88
+ 'Here is the result: {"tool":"search","input":{"query":"async"}}',
89
+ ]
90
+ for (const c of chunks) linter.push(c)
91
+ const result = linter.parse()
92
+ assert.ok(result.toolCalls.length >= 1)
93
+ })
94
+
95
+ it('extracts tool call inside a textual array', () => {
96
+ const input =
97
+ 'Options:\n- `{"tool":"search","input":{"query":"foo"}}`\n- `{"tool":"search","input":{"query":"bar"}}`'
98
+ const candidates = extract(input)
99
+ assert.ok(candidates.length >= 1, 'Expected extraction from array-text format')
100
+ })
101
+
102
+ it('handles duplicate model output', () => {
103
+ const input =
104
+ '{"tool":"search","input":{"query":"dup"}}\n\n{"tool":"search","input":{"query":"dup"}}'
105
+ const result = parseText(input)
106
+ assert.ok(Array.isArray(result.toolCalls))
107
+ })
108
+
109
+ it('repair: single quotes to double quotes', () => {
110
+ const input = "{'tool': 'search', 'input': {'query': 'test'}}"
111
+ const repaired = repair(input)
112
+ assert.ok(repaired.includes('search'))
113
+ })
114
+
115
+ it('repair: trailing comma', () => {
116
+ const input = '{"tool": "search", "input": {"query": "test"},}'
117
+ const repaired = repair(input)
118
+ assert.ok(repaired.includes('search'))
119
+ })
120
+
121
+ it('repair: key without quotes', () => {
122
+ const input = '{tool: "search", input: {query: "test"}}'
123
+ const repaired = repair(input)
124
+ assert.ok(repaired.includes('search'))
125
+ })
126
+
127
+ it('security gate blocks destructive shell injection', () => {
128
+ configure({ minConfidenceThreshold: 0.0 })
129
+ const input = '{"tool":"search","input":{"query":"\'; rm -rf /; echo \'"}}'
130
+ const result = parseText(input)
131
+ const passed = result.toolCalls.some((call: any) => {
132
+ const val = (call.input.query ?? '') as string
133
+ return typeof val === 'string' && val.includes('rm -rf /')
134
+ })
135
+ assert.strictEqual(passed, false, 'Should not pass through destructive payload')
136
+ })
137
+
138
+ it('rejects empty string values per spec', () => {
139
+ configure({ minConfidenceThreshold: 0.0 })
140
+ const input = '{"tool":"search","input":{"query":""}}'
141
+ const result = parseText(input)
142
+ assert.ok(Array.isArray(result.toolCalls))
143
+ })
144
+
145
+ it('parseText returns canonical tool calls', () => {
146
+ configure({ minConfidenceThreshold: 0.1 })
147
+ const input = '{"tool":"search","input":{"query":"x"}}'
148
+ const result = parseText(input)
149
+ assert.ok(Array.isArray(result.toolCalls))
150
+ })
151
+ })
@@ -0,0 +1,42 @@
1
+ import { test } from 'node:test';
2
+ import assert from 'node:assert';
3
+ import { executeToolCalls } from '../tools/executor.ts';
4
+ import { registry } from '../tools/registry.ts';
5
+ import type { ToolContext } from '../tools/types.ts';
6
+
7
+ test('executeToolCalls: parallel execution', async () => {
8
+ let activeCount = 0;
9
+ let maxParallel = 0;
10
+
11
+ registry.register(
12
+ 'parallel_tool',
13
+ 'A tool that waits to test parallelism',
14
+ { type: 'object', properties: {} },
15
+ async () => {
16
+ activeCount++;
17
+ maxParallel = Math.max(maxParallel, activeCount);
18
+ await new Promise(r => setTimeout(r, 100));
19
+ activeCount--;
20
+ return 'done';
21
+ }
22
+ );
23
+
24
+ const toolCalls = [
25
+ { id: '1', name: 'parallel_tool', arguments: {} },
26
+ { id: '2', name: 'parallel_tool', arguments: {} },
27
+ { id: '3', name: 'parallel_tool', arguments: {} },
28
+ ];
29
+
30
+ const context: ToolContext = {
31
+ messages: [],
32
+ turn: 0,
33
+ model: 'test'
34
+ };
35
+
36
+ const results = await executeToolCalls(toolCalls, context);
37
+
38
+ assert.strictEqual(results.length, 3);
39
+ assert.ok(maxParallel > 1, `Max parallel should be > 1, got ${maxParallel}`);
40
+
41
+ registry.unregister('parallel_tool');
42
+ });
@@ -0,0 +1,89 @@
1
+ import { test } from 'node:test';
2
+ import assert from 'node:assert';
3
+ import { StreamingToolParser } from '../tools/parser.ts';
4
+
5
+ test('StreamingToolParser: basic tool call', () => {
6
+ const parser = new StreamingToolParser();
7
+
8
+ const result = parser.feed('Hello! <tool_call>{"name": "t1", "arguments": {"a": 1}}</tool_call>');
9
+ assert.strictEqual(result.text, 'Hello! ');
10
+ assert.strictEqual(result.toolCalls.length, 1);
11
+ assert.strictEqual(result.toolCalls[0].name, 't1');
12
+ });
13
+
14
+ test('StreamingToolParser: multiple tool calls', () => {
15
+ const parser = new StreamingToolParser();
16
+
17
+ const result = parser.feed('<tool_call>{"name": "t2", "arguments": {}}</tool_call><tool_call>{"name": "t3", "arguments": {}}</tool_call>');
18
+ assert.strictEqual(result.text, '');
19
+ assert.strictEqual(result.toolCalls.length, 2);
20
+ assert.strictEqual(result.toolCalls[0].name, 't2');
21
+ assert.strictEqual(result.toolCalls[1].name, 't3');
22
+ });
23
+
24
+ test('StreamingToolParser: fragmented tool call', () => {
25
+ const parser = new StreamingToolParser();
26
+
27
+ assert.strictEqual(parser.feed('Text <tool_').text, 'Text ');
28
+ assert.strictEqual(parser.feed('call>{"name": ').text, '');
29
+ const final = parser.feed('"frag", "arguments": {}}</tool_call> trailing');
30
+
31
+ assert.strictEqual(final.toolCalls.length, 1);
32
+ assert.strictEqual(final.toolCalls[0].name, 'frag');
33
+ assert.strictEqual(final.text, ' trailing');
34
+ });
35
+
36
+ test('StreamingToolParser: flush partial content', () => {
37
+ const parser = new StreamingToolParser();
38
+
39
+ parser.feed('Unfinished tag <tool_');
40
+ assert.strictEqual(parser.flush().text, '<tool_');
41
+
42
+ const parser2 = new StreamingToolParser();
43
+ parser2.feed('Broken tool <tool_call>{"name": "healable"');
44
+ const flushed = parser2.flush();
45
+ assert.strictEqual(flushed.toolCalls.length, 1);
46
+ assert.strictEqual(flushed.toolCalls[0].name, 'healable');
47
+
48
+ const parser3 = new StreamingToolParser();
49
+ parser3.feed('Invalid <tool_call>NOT_JSON');
50
+ const flushed2 = parser3.flush();
51
+ assert.strictEqual(flushed2.text, '<tool_call>NOT_JSON</tool_call>');
52
+ });
53
+
54
+ test('StreamingToolParser: robust parsing of malformed JSON', () => {
55
+ const parser = new StreamingToolParser();
56
+
57
+ const res = parser.feed('<tool_call>{"name": "broken", "arguments": {"a": 1</tool_call>');
58
+ assert.strictEqual(res.toolCalls.length, 1);
59
+ assert.strictEqual(res.toolCalls[0].name, 'broken');
60
+ assert.deepStrictEqual(res.toolCalls[0].arguments, { a: 1 });
61
+ });
62
+
63
+ test('StreamingToolParser: preserves tags in non-tool text', () => {
64
+ const parser = new StreamingToolParser();
65
+
66
+ const res1 = parser.feed('Fake: <tool_call> { "only_args": 1 } </tool_call> ');
67
+ assert.ok(res1.text.includes('<tool_call>'), 'Should contain start tag');
68
+ assert.ok(res1.text.includes('</tool_call>'), 'Should contain end tag');
69
+ assert.strictEqual(res1.toolCalls.length, 0);
70
+
71
+ const res2 = parser.feed('Real: <tool_call>{"name":"r"}</tool_call>');
72
+ assert.strictEqual(res2.toolCalls.length, 1);
73
+ assert.strictEqual(res2.toolCalls[0].name, 'r');
74
+ });
75
+
76
+ test('StreamingToolParser: handles multiple tool calls in array format', () => {
77
+ const parser = new StreamingToolParser();
78
+
79
+ const chunk = `<tool_call>[
80
+ {"name": "bash", "arguments": {"command": "ls", "description": "List files"}},
81
+ {"name": "read", "arguments": {"path": "test.txt"}}
82
+ ]</tool_call>`;
83
+
84
+ const result = parser.feed(chunk);
85
+ assert.strictEqual(result.toolCalls.length, 2, 'Should extract both tool calls');
86
+ assert.strictEqual(result.toolCalls[0].name, 'bash');
87
+ assert.strictEqual(result.toolCalls[1].name, 'read');
88
+ assert.strictEqual(result.toolCalls[0].arguments.command, 'ls');
89
+ });
@@ -0,0 +1,45 @@
1
+ import { test } from 'node:test';
2
+ import assert from 'node:assert';
3
+ import { getNextAccount, invalidateAccountsCache } from '../core/account-manager.ts';
4
+ import { addAccount, removeAccount, loadAccounts } from '../core/accounts.ts';
5
+
6
+ test('Account Rotation: Round-Robin rotation cycle', async () => {
7
+ const originalAccounts = loadAccounts();
8
+ const originalIds = originalAccounts.map(a => a.id);
9
+
10
+ const mockAccounts = [
11
+ { email: 'account1@test.com', password: 'password1' },
12
+ { email: 'account2@test.com', password: 'password2' },
13
+ { email: 'account3@test.com', password: 'password3' },
14
+ ];
15
+
16
+ try {
17
+ for (const acc of mockAccounts) {
18
+ addAccount(acc.email, acc.password);
19
+ }
20
+ invalidateAccountsCache();
21
+
22
+ const first = getNextAccount(true);
23
+ const second = getNextAccount();
24
+ const third = getNextAccount();
25
+ const fourth = getNextAccount();
26
+
27
+ assert.ok(first);
28
+ assert.ok(second);
29
+ assert.ok(third);
30
+ assert.ok(fourth);
31
+
32
+ assert.strictEqual(first.email, 'account1@test.com');
33
+ assert.strictEqual(second.email, 'account2@test.com');
34
+ assert.strictEqual(third.email, 'account3@test.com');
35
+ assert.strictEqual(fourth.email, 'account1@test.com');
36
+ } finally {
37
+ const current = loadAccounts();
38
+ for (const acc of current) {
39
+ if (!originalIds.includes(acc.id)) {
40
+ removeAccount(acc.id);
41
+ }
42
+ }
43
+ invalidateAccountsCache();
44
+ }
45
+ });
@@ -0,0 +1,328 @@
1
+ /*
2
+ * File: streamingOptimizations.test.ts
3
+ * Project: qwenproxy
4
+ * Author: Pedro Farias
5
+ * Created: 2026-06-02
6
+ *
7
+ * Last Modified: Tue Jun 02 2026
8
+ * Modified By: Pedro Farias
9
+ */
10
+
11
+ import { describe, it, beforeEach } from 'node:test';
12
+ import assert from 'node:assert';
13
+ import { getIncrementalDelta, DeltaResult } from '../routes/chat.js';
14
+
15
+ describe('Streaming Optimizations Tests', () => {
16
+ describe('getIncrementalDelta', () => {
17
+ it('should return full string as delta when oldStr is empty', () => {
18
+ const result = getIncrementalDelta('', 'Hello World');
19
+ assert.strictEqual(result.delta, 'Hello World');
20
+ assert.strictEqual(result.matchedContent, 'Hello World');
21
+ });
22
+
23
+ it('should return empty delta when strings are identical', () => {
24
+ const result = getIncrementalDelta('Hello World', 'Hello World');
25
+ assert.strictEqual(result.delta, '');
26
+ assert.strictEqual(result.matchedContent, 'Hello World');
27
+ });
28
+
29
+ it('should detect cumulative content and return incremental delta', () => {
30
+ const result = getIncrementalDelta('Hello ', 'Hello World');
31
+ assert.strictEqual(result.delta, 'World');
32
+ assert.strictEqual(result.matchedContent, 'Hello World');
33
+ });
34
+
35
+ it('should handle long string prefix matching efficiently', () => {
36
+ const longPrefix = 'a'.repeat(1000);
37
+ const oldStr = longPrefix + 'X';
38
+ const newStr = longPrefix + 'Y';
39
+
40
+ const result = getIncrementalDelta(oldStr, newStr);
41
+ assert.strictEqual(result.delta, 'Y');
42
+ assert.strictEqual(result.matchedContent, newStr);
43
+ });
44
+
45
+ it('should handle prefix mismatch by treating as incremental', () => {
46
+ const result = getIncrementalDelta('abc', 'xyz');
47
+ // Since no common prefix of length >= 4, treated as incremental
48
+ assert.strictEqual(result.delta, 'xyz');
49
+ assert.strictEqual(result.matchedContent, 'abcxyz');
50
+ });
51
+
52
+ it('should handle short prefix matches (below threshold)', () => {
53
+ const result = getIncrementalDelta('ab', 'abc');
54
+ // Prefix match of length 2 is below threshold of 4
55
+ assert.strictEqual(result.delta, 'abc');
56
+ assert.strictEqual(result.matchedContent, 'ababc');
57
+ });
58
+
59
+ it('should handle threshold boundary correctly', () => {
60
+ const result = getIncrementalDelta('abcd', 'abcde');
61
+ // Prefix match of length 4 meets threshold
62
+ assert.strictEqual(result.delta, 'e');
63
+ assert.strictEqual(result.matchedContent, 'abcde');
64
+ });
65
+
66
+ it('should handle very long strings with segment-based matching', () => {
67
+ const base = 'x'.repeat(5000);
68
+ const oldStr = base;
69
+ const newStr = base + 'suffix';
70
+
71
+ const result = getIncrementalDelta(oldStr, newStr);
72
+ assert.strictEqual(result.delta, 'suffix');
73
+ assert.strictEqual(result.matchedContent, newStr);
74
+ });
75
+
76
+ it('should handle empty new string correctly', () => {
77
+ const result = getIncrementalDelta('Hello', '');
78
+ assert.strictEqual(result.delta, '');
79
+ assert.strictEqual(result.matchedContent, 'Hello');
80
+ });
81
+
82
+ it('should handle unicode characters correctly', () => {
83
+ const result = getIncrementalDelta('Hello 🌍', 'Hello 🌍🌎');
84
+ assert.strictEqual(result.delta, '🌎');
85
+ assert.strictEqual(result.matchedContent, 'Hello 🌍🌎');
86
+ });
87
+ });
88
+
89
+ describe('Batch Flush Logic', () => {
90
+ it('should accumulate events until byte threshold', () => {
91
+ // Simulate batch accumulation logic
92
+ const MAX_BATCH_BYTES = 4096;
93
+ const MAX_BATCH_COUNT = 8;
94
+
95
+ let batchBytes = 0;
96
+ let batchCount = 0;
97
+ let sseBatch = '';
98
+ const events: string[] = [];
99
+
100
+ // Add small events
101
+ for (let i = 0; i < 5; i++) {
102
+ const evt = `data: {"id":"test","content":"chunk${i}"}\n\n`;
103
+ sseBatch += evt;
104
+ batchBytes += evt.length;
105
+ batchCount++;
106
+
107
+ // Should not flush yet
108
+ if (batchBytes >= MAX_BATCH_BYTES || batchCount >= MAX_BATCH_COUNT) {
109
+ events.push(sseBatch);
110
+ sseBatch = '';
111
+ batchBytes = 0;
112
+ batchCount = 0;
113
+ }
114
+ }
115
+
116
+ // Should not have flushed yet (5 events < 8 count threshold)
117
+ assert.strictEqual(batchCount, 5);
118
+ assert.strictEqual(events.length, 0);
119
+ });
120
+
121
+ it('should flush when count threshold is reached', () => {
122
+ const MAX_BATCH_BYTES = 4096;
123
+ const MAX_BATCH_COUNT = 8;
124
+
125
+ let batchBytes = 0;
126
+ let batchCount = 0;
127
+ let sseBatch = '';
128
+ const events: string[] = [];
129
+
130
+ for (let i = 0; i < 10; i++) {
131
+ const evt = `data: {"id":"test","content":"chunk${i}"}\n\n`;
132
+ sseBatch += evt;
133
+ batchBytes += evt.length;
134
+ batchCount++;
135
+
136
+ if (batchBytes >= MAX_BATCH_BYTES || batchCount >= MAX_BATCH_COUNT) {
137
+ events.push(sseBatch);
138
+ sseBatch = '';
139
+ batchBytes = 0;
140
+ batchCount = 0;
141
+ }
142
+ }
143
+
144
+ // Should have flushed once at 8 events, then accumulated 2 more
145
+ assert.strictEqual(events.length, 1);
146
+ assert.strictEqual(batchCount, 2);
147
+ });
148
+
149
+ it('should flush when byte threshold is reached', () => {
150
+ const MAX_BATCH_BYTES = 100;
151
+ const MAX_BATCH_COUNT = 8;
152
+
153
+ let batchBytes = 0;
154
+ let batchCount = 0;
155
+ let sseBatch = '';
156
+ const events: string[] = [];
157
+
158
+ // Add large events that will exceed byte threshold
159
+ for (let i = 0; i < 5; i++) {
160
+ const content = 'x'.repeat(30); // Each event ~42 bytes
161
+ const evt = `data: {"id":"test","content":"${content}"}\n\n`;
162
+ sseBatch += evt;
163
+ batchBytes += evt.length;
164
+ batchCount++;
165
+
166
+ if (batchBytes >= MAX_BATCH_BYTES || batchCount >= MAX_BATCH_COUNT) {
167
+ events.push(sseBatch);
168
+ sseBatch = '';
169
+ batchBytes = 0;
170
+ batchCount = 0;
171
+ }
172
+ }
173
+
174
+ // Should have flushed at least once due to byte threshold
175
+ assert.ok(events.length >= 1);
176
+ });
177
+ });
178
+
179
+ describe('Buffer Parsing Optimization', () => {
180
+ it('should parse SSE lines using index-based scanning', () => {
181
+ const buffer = 'data: chunk1\n\ndata: chunk2\n\ndata: chunk3\n\nremainder';
182
+
183
+ const lines: string[] = [];
184
+ let startIdx = 0;
185
+ let newlineIdx: number;
186
+
187
+ while ((newlineIdx = buffer.indexOf('\n', startIdx)) !== -1) {
188
+ const line = buffer.slice(startIdx, newlineIdx);
189
+ startIdx = newlineIdx + 1;
190
+ lines.push(line);
191
+ }
192
+
193
+ const remainder = buffer.slice(startIdx);
194
+
195
+ assert.deepStrictEqual(lines, ['data: chunk1\n', 'data: chunk2\n', 'data: chunk3\n']);
196
+ assert.strictEqual(remainder, 'remainder');
197
+ });
198
+
199
+ it('should handle buffer with no newlines correctly', () => {
200
+ const buffer = 'partial data line';
201
+
202
+ const lines: string[] = [];
203
+ let startIdx = 0;
204
+ let newlineIdx: number;
205
+
206
+ while ((newlineIdx = buffer.indexOf('\n', startIdx)) !== -1) {
207
+ const line = buffer.slice(startIdx, newlineIdx);
208
+ startIdx = newlineIdx + 1;
209
+ lines.push(line);
210
+ }
211
+
212
+ const remainder = buffer.slice(startIdx);
213
+
214
+ assert.deepStrictEqual(lines, []);
215
+ assert.strictEqual(remainder, 'partial data line');
216
+ });
217
+
218
+ it('should handle empty buffer correctly', () => {
219
+ const buffer = '';
220
+
221
+ const lines: string[] = [];
222
+ let startIdx = 0;
223
+ let newlineIdx: number;
224
+
225
+ while ((newlineIdx = buffer.indexOf('\n', startIdx)) !== -1) {
226
+ const line = buffer.slice(startIdx, newlineIdx);
227
+ startIdx = newlineIdx + 1;
228
+ lines.push(line);
229
+ }
230
+
231
+ const remainder = buffer.slice(startIdx);
232
+
233
+ assert.deepStrictEqual(lines, []);
234
+ assert.strictEqual(remainder, '');
235
+ });
236
+ });
237
+
238
+ describe('Target Response ID Optimization', () => {
239
+ it('should use boolean flag for targetResponseId check', () => {
240
+ // Simulate the optimized check pattern
241
+ let targetResponseId: string | null = null;
242
+ let targetResponseIdSet = false;
243
+
244
+ // Before target is set
245
+ const chunk1ResponseId = 'resp-123';
246
+ const shouldProcess1 = !targetResponseIdSet || chunk1ResponseId === targetResponseId;
247
+ assert.strictEqual(shouldProcess1, true);
248
+
249
+ // Set target
250
+ targetResponseId = chunk1ResponseId;
251
+ targetResponseIdSet = true;
252
+
253
+ // After target is set, matching response_id
254
+ const chunk2ResponseId = 'resp-123';
255
+ const shouldProcess2 = !targetResponseIdSet || chunk2ResponseId === targetResponseId;
256
+ assert.strictEqual(shouldProcess2, true);
257
+
258
+ // Non-matching response_id
259
+ const chunk3ResponseId = 'resp-456';
260
+ const shouldProcess3 = !targetResponseIdSet || chunk3ResponseId === targetResponseId;
261
+ assert.strictEqual(shouldProcess3, false);
262
+ });
263
+ });
264
+
265
+ describe('Timestamp Pre-computation', () => {
266
+ it('should use pre-computed timestamp consistently', () => {
267
+ const createdTimestamp = Math.floor(Date.now() / 1000);
268
+
269
+ // Simulate multiple events using the same timestamp
270
+ const events = [];
271
+ for (let i = 0; i < 5; i++) {
272
+ events.push({
273
+ id: 'test',
274
+ object: 'chat.completion.chunk',
275
+ created: createdTimestamp,
276
+ model: 'test-model',
277
+ choices: [{ index: 0, delta: { content: `chunk${i}` } }]
278
+ });
279
+ }
280
+
281
+ // All events should have the same timestamp
282
+ const timestamps = events.map(e => e.created);
283
+ assert.ok(timestamps.every(t => t === createdTimestamp));
284
+ });
285
+ });
286
+
287
+ describe('WriteEvent Optimization', () => {
288
+ it('should use fire-and-forget pattern', () => {
289
+ // Simulate the writeEvent function
290
+ const writes: string[] = [];
291
+ const streamWriter = {
292
+ write: (data: string) => {
293
+ writes.push(data);
294
+ return Promise.resolve();
295
+ }
296
+ };
297
+
298
+ const writeEvent = (data: any) => {
299
+ streamWriter.write(`data: ${JSON.stringify(data)}\n\n`);
300
+ };
301
+
302
+ writeEvent({ id: 'test', content: 'hello' });
303
+ writeEvent({ id: 'test', content: 'world' });
304
+
305
+ assert.strictEqual(writes.length, 2);
306
+ assert.ok(writes[0].includes('hello'));
307
+ assert.ok(writes[1].includes('world'));
308
+ });
309
+ });
310
+
311
+ describe('SetImmediate Yielding', () => {
312
+ it('should yield every 100 chunks to prevent event loop starvation', async () => {
313
+ const yields: number[] = [];
314
+ let chunkCount = 0;
315
+
316
+ // Simulate processing 250 chunks
317
+ for (let i = 0; i < 250; i++) {
318
+ chunkCount++;
319
+ if (chunkCount % 100 === 0) {
320
+ yields.push(chunkCount);
321
+ await new Promise(r => setImmediate(r));
322
+ }
323
+ }
324
+
325
+ assert.deepStrictEqual(yields, [100, 200]);
326
+ });
327
+ });
328
+ });