gx402 1.3.5
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 +15 -0
- package/index.ts +1 -0
- package/package.json +18 -0
- package/patch +290 -0
- package/test/basic.test.ts +73 -0
- package/test/edge.test.ts +237 -0
- package/test/streaming.test.ts +78 -0
- package/tsconfig.json +28 -0
- package/uai.ts +835 -0
|
@@ -0,0 +1,78 @@
|
|
|
1
|
+
import { test, expect, it, describe } from 'bun:test';
|
|
2
|
+
import { z } from 'zod';
|
|
3
|
+
import { Agent, LLM, ProgressUpdate, StreamingUpdate } from '../uai';
|
|
4
|
+
|
|
5
|
+
describe('UAI Streaming Tests', () => {
|
|
6
|
+
it('should emit streaming progress updates token-by-token', async () => {
|
|
7
|
+
const streamingAgent = new Agent({
|
|
8
|
+
llm: 'o4-mini-2025-04-16',
|
|
9
|
+
inputFormat: z.object({
|
|
10
|
+
question: z.string(),
|
|
11
|
+
}),
|
|
12
|
+
outputFormat: z.object({
|
|
13
|
+
analysis: z.object({
|
|
14
|
+
step1: z.string(), // nested fieild should be named like analysis_step1
|
|
15
|
+
step2: z.string(),
|
|
16
|
+
step3: z.string(),
|
|
17
|
+
}).describe("Step-by-step analysis of the question"),
|
|
18
|
+
answer: z.string().describe("The final short concise answer to the question"),
|
|
19
|
+
status: z.string().describe("just literal word OK"), // to ensure streaming single-word responses
|
|
20
|
+
}),
|
|
21
|
+
temperature: 0.7,
|
|
22
|
+
});
|
|
23
|
+
|
|
24
|
+
const input = {
|
|
25
|
+
question: 'What are the benefits of renewable energy?',
|
|
26
|
+
};
|
|
27
|
+
|
|
28
|
+
const streamingUpdates: StreamingUpdate[] = [];
|
|
29
|
+
const progressUpdates: ProgressUpdate[] = [];
|
|
30
|
+
|
|
31
|
+
try {
|
|
32
|
+
const result = await streamingAgent.run(input, (update) => {
|
|
33
|
+
if (update.stage === 'streaming') {
|
|
34
|
+
streamingUpdates.push(update as StreamingUpdate);
|
|
35
|
+
console.log(`Field: ${update.field}, Value: ${update.value}`);
|
|
36
|
+
} else {
|
|
37
|
+
progressUpdates.push(update);
|
|
38
|
+
}
|
|
39
|
+
});
|
|
40
|
+
|
|
41
|
+
console.log('\n--- Final Result ---');
|
|
42
|
+
console.log('Analysis:', result.analysis);
|
|
43
|
+
console.log('Answer:', result.answer);
|
|
44
|
+
|
|
45
|
+
// Verify we received streaming updates
|
|
46
|
+
expect(streamingUpdates.length).toBeGreaterThan(0);
|
|
47
|
+
|
|
48
|
+
// Verify we have updates for both fields
|
|
49
|
+
const fieldsUpdated = new Set(streamingUpdates.map(u => u.field));
|
|
50
|
+
expect(fieldsUpdated.has('analysis')).toBe(true);
|
|
51
|
+
expect(fieldsUpdated.has('answer')).toBe(true);
|
|
52
|
+
|
|
53
|
+
// Verify the streaming updates show progressive content building
|
|
54
|
+
const analysisUpdates = streamingUpdates.filter(u => u.field === 'analysis');
|
|
55
|
+
const answerUpdates = streamingUpdates.filter(u => u.field === 'answer');
|
|
56
|
+
|
|
57
|
+
expect(analysisUpdates.length).toBeGreaterThan(1);
|
|
58
|
+
expect(answerUpdates.length).toBeGreaterThan(1);
|
|
59
|
+
|
|
60
|
+
// Verify content is progressively building (each update should contain more text)
|
|
61
|
+
for (let i = 1; i < analysisUpdates.length; i++) {
|
|
62
|
+
expect(analysisUpdates[i].value.length).toBeGreaterThanOrEqual(analysisUpdates[i - 1].value.length);
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
// Verify final result matches last streaming update values
|
|
66
|
+
const lastAnalysisUpdate = analysisUpdates[analysisUpdates.length - 1];
|
|
67
|
+
const lastAnswerUpdate = answerUpdates[answerUpdates.length - 1];
|
|
68
|
+
|
|
69
|
+
expect(result.analysis.trim()).toBe(lastAnalysisUpdate.value.trim());
|
|
70
|
+
expect(result.answer.trim()).toBe(lastAnswerUpdate.value.trim());
|
|
71
|
+
|
|
72
|
+
console.log(`\n✅ Received ${streamingUpdates.length} streaming updates across ${fieldsUpdated.size} fields`);
|
|
73
|
+
|
|
74
|
+
} catch (error) {
|
|
75
|
+
console.warn('\n⚠️ Streaming test skipped (this is expected if API keys are not configured):', error.message);
|
|
76
|
+
}
|
|
77
|
+
}, { timeout: 60000 });
|
|
78
|
+
});
|
package/tsconfig.json
ADDED
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
{
|
|
2
|
+
"compilerOptions": {
|
|
3
|
+
// Environment setup & latest features
|
|
4
|
+
"lib": ["ESNext"],
|
|
5
|
+
"target": "ESNext",
|
|
6
|
+
"module": "ESNext",
|
|
7
|
+
"moduleDetection": "force",
|
|
8
|
+
"jsx": "react-jsx",
|
|
9
|
+
"allowJs": true,
|
|
10
|
+
|
|
11
|
+
// Bundler mode
|
|
12
|
+
"moduleResolution": "bundler",
|
|
13
|
+
"allowImportingTsExtensions": true,
|
|
14
|
+
"verbatimModuleSyntax": true,
|
|
15
|
+
"noEmit": true,
|
|
16
|
+
|
|
17
|
+
// Best practices
|
|
18
|
+
"strict": true,
|
|
19
|
+
"skipLibCheck": true,
|
|
20
|
+
"noFallthroughCasesInSwitch": true,
|
|
21
|
+
"noUncheckedIndexedAccess": true,
|
|
22
|
+
|
|
23
|
+
// Some stricter flags (disabled by default)
|
|
24
|
+
"noUnusedLocals": false,
|
|
25
|
+
"noUnusedParameters": false,
|
|
26
|
+
"noPropertyAccessFromIndexSignature": false
|
|
27
|
+
}
|
|
28
|
+
}
|