universal-llm-client 4.2.0 → 4.5.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 (108) hide show
  1. package/CHANGELOG.md +142 -103
  2. package/LICENSE +21 -21
  3. package/README.md +640 -591
  4. package/dist/ai-model.d.ts +12 -1
  5. package/dist/ai-model.d.ts.map +1 -1
  6. package/dist/ai-model.js +36 -1
  7. package/dist/ai-model.js.map +1 -1
  8. package/dist/gemma-channel.d.ts +14 -0
  9. package/dist/gemma-channel.d.ts.map +1 -0
  10. package/dist/gemma-channel.js +38 -0
  11. package/dist/gemma-channel.js.map +1 -0
  12. package/dist/gemma-diffusion.d.ts +49 -0
  13. package/dist/gemma-diffusion.d.ts.map +1 -0
  14. package/dist/gemma-diffusion.js +147 -0
  15. package/dist/gemma-diffusion.js.map +1 -0
  16. package/dist/http.d.ts +4 -0
  17. package/dist/http.d.ts.map +1 -1
  18. package/dist/http.js +14 -1
  19. package/dist/http.js.map +1 -1
  20. package/dist/index.d.ts +2 -1
  21. package/dist/index.d.ts.map +1 -1
  22. package/dist/index.js +4 -0
  23. package/dist/index.js.map +1 -1
  24. package/dist/interfaces.d.ts +183 -7
  25. package/dist/interfaces.d.ts.map +1 -1
  26. package/dist/interfaces.js.map +1 -1
  27. package/dist/providers/anthropic.d.ts.map +1 -1
  28. package/dist/providers/anthropic.js +28 -3
  29. package/dist/providers/anthropic.js.map +1 -1
  30. package/dist/providers/google.d.ts +22 -1
  31. package/dist/providers/google.d.ts.map +1 -1
  32. package/dist/providers/google.js +225 -13
  33. package/dist/providers/google.js.map +1 -1
  34. package/dist/providers/ollama.d.ts +2 -0
  35. package/dist/providers/ollama.d.ts.map +1 -1
  36. package/dist/providers/ollama.js +59 -30
  37. package/dist/providers/ollama.js.map +1 -1
  38. package/dist/providers/openai.d.ts +14 -0
  39. package/dist/providers/openai.d.ts.map +1 -1
  40. package/dist/providers/openai.js +200 -22
  41. package/dist/providers/openai.js.map +1 -1
  42. package/dist/router.d.ts +2 -0
  43. package/dist/router.d.ts.map +1 -1
  44. package/dist/router.js +4 -0
  45. package/dist/router.js.map +1 -1
  46. package/dist/stream-decoder.d.ts +12 -0
  47. package/dist/stream-decoder.d.ts.map +1 -1
  48. package/dist/stream-decoder.js +182 -5
  49. package/dist/stream-decoder.js.map +1 -1
  50. package/dist/thinking.d.ts +36 -0
  51. package/dist/thinking.d.ts.map +1 -0
  52. package/dist/thinking.js +52 -0
  53. package/dist/thinking.js.map +1 -0
  54. package/package.json +118 -116
  55. package/src/ai-model.ts +400 -350
  56. package/src/auditor.ts +213 -213
  57. package/src/client.ts +402 -402
  58. package/src/debug/debug-google-streaming.ts +1 -1
  59. package/src/demos/basic/universal-llm-examples.ts +3 -3
  60. package/src/demos/diffusion-gemma/.env +29 -0
  61. package/src/demos/diffusion-gemma/.env.example +27 -0
  62. package/src/demos/diffusion-gemma/CLAUDE.md +95 -0
  63. package/src/demos/diffusion-gemma/README.md +59 -0
  64. package/src/demos/diffusion-gemma/canvas.ts +1606 -0
  65. package/src/demos/diffusion-gemma/docker-compose.yml +29 -0
  66. package/src/demos/diffusion-gemma/probe-stream.ts +51 -0
  67. package/src/demos/diffusion-gemma/probe-tools.ts +55 -0
  68. package/src/demos/diffusion-gemma/server.ts +1205 -0
  69. package/src/demos/diffusion-gemma/start-vllm.sh +98 -0
  70. package/src/gemma-channel.ts +47 -0
  71. package/src/gemma-diffusion.ts +167 -0
  72. package/src/http.ts +261 -247
  73. package/src/index.ts +180 -161
  74. package/src/interfaces.ts +843 -657
  75. package/src/mcp.ts +345 -345
  76. package/src/providers/anthropic.ts +796 -762
  77. package/src/providers/google.ts +840 -620
  78. package/src/providers/index.ts +8 -8
  79. package/src/providers/ollama.ts +503 -469
  80. package/src/providers/openai.ts +587 -392
  81. package/src/router.ts +785 -780
  82. package/src/stream-decoder.ts +535 -361
  83. package/src/structured-output.ts +759 -759
  84. package/src/test-scripts/test-google-deep-research.ts +33 -0
  85. package/src/test-scripts/test-google-streaming-enhanced.ts +147 -147
  86. package/src/test-scripts/test-google-streaming.ts +1 -1
  87. package/src/test-scripts/test-google-system-prompt-comprehensive.ts +189 -189
  88. package/src/test-scripts/test-google-thinking.ts +46 -0
  89. package/src/test-scripts/test-system-message-positions.ts +163 -163
  90. package/src/test-scripts/test-system-prompt-improvement-demo.ts +83 -83
  91. package/src/test-scripts/test-vllm-qwen36.ts +256 -0
  92. package/src/tests/ai-model.test.ts +1614 -1614
  93. package/src/tests/auditor.test.ts +224 -224
  94. package/src/tests/gemma-diffusion.test.ts +115 -0
  95. package/src/tests/http.test.ts +200 -200
  96. package/src/tests/interfaces.test.ts +117 -117
  97. package/src/tests/providers/anthropic.test.ts +118 -0
  98. package/src/tests/providers/google.test.ts +841 -660
  99. package/src/tests/providers/ollama.test.ts +1034 -954
  100. package/src/tests/providers/openai.test.ts +1511 -1122
  101. package/src/tests/router.test.ts +254 -254
  102. package/src/tests/stream-decoder.test.ts +263 -179
  103. package/src/tests/structured-output.test.ts +1450 -1450
  104. package/src/tests/thinking.test.ts +65 -0
  105. package/src/tests/tools.test.ts +175 -175
  106. package/src/thinking.ts +73 -0
  107. package/src/tools.ts +246 -246
  108. package/src/zod-adapter.ts +72 -72
@@ -1,189 +1,189 @@
1
- import { AIModelFactory } from "../factory";
2
-
3
- /**
4
- * Comprehensive test for Google models with proper system prompt handling
5
- * Tests both Gemini (systemInstruction) and Gemma (embedded in user prompt) approaches
6
- */
7
- async function testGoogleSystemPromptHandling() {
8
- console.log('🧪 Testing Google Models with Proper System Prompt Handling...\n');
9
-
10
- // Test models with different system instruction approaches
11
- const models = [
12
- {
13
- name: 'Gemini 2.5 Flash Lite',
14
- model: 'gemini-2.5-flash-lite',
15
- supportsSystemInstruction: true,
16
- approach: 'Uses Google systemInstruction parameter'
17
- },
18
- {
19
- name: 'Gemma 3 27B IT',
20
- model: 'gemma-3-27b-it',
21
- supportsSystemInstruction: false,
22
- approach: 'Embeds system prompt in user message'
23
- }
24
- ];
25
-
26
- let allTestsPassed = true;
27
-
28
- for (const modelInfo of models) {
29
- console.log(`\n🔬 Testing ${modelInfo.name} (${modelInfo.model})`);
30
- console.log(`System approach: ${modelInfo.approach}`);
31
- console.log(`System instruction parameter: ${modelInfo.supportsSystemInstruction ? '✅' : '❌'}`);
32
- console.log('='.repeat(70));
33
-
34
- const googleModel = AIModelFactory.createGoogleChatModel(
35
- modelInfo.model,
36
- 'AIzaSyBDbo7iVNEuCcRNTgDIgRrkGpFKisXXnm0'
37
- );
38
-
39
- const testResult = await testModelSystemPrompt(googleModel, modelInfo);
40
- if (!testResult) {
41
- allTestsPassed = false;
42
- }
43
- }
44
-
45
- return { success: allTestsPassed };
46
- }
47
-
48
- async function testModelSystemPrompt(googleModel: any, modelInfo: any) {
49
- const modelName = modelInfo.name;
50
- let testsPassed = true;
51
-
52
- // Test 1: Basic functionality without system prompt
53
- console.log(`\n--- Test 1: Basic Chat (${modelName}) ---`);
54
- try {
55
- console.log('Question: "What is 2+2?"');
56
-
57
- const basicResponse = await googleModel.chat([
58
- { role: 'user', content: 'What is 2+2?' }
59
- ]);
60
-
61
- console.log('Response:', basicResponse.message.content);
62
- console.log('✅ Basic chat works');
63
-
64
- } catch (error) {
65
- console.error(`❌ Basic chat failed for ${modelName}:`, error);
66
- testsPassed = false;
67
- }
68
-
69
- // Test 2: System prompt with math personality
70
- console.log(`\n--- Test 2: System Prompt - Math Teacher (${modelName}) ---`);
71
- try {
72
- console.log('System: "You are a math teacher. Always explain your answers step by step."');
73
- console.log('Question: "What is 2+2?"');
74
-
75
- const mathResponse = await googleModel.chat([
76
- { role: 'system', content: 'You are a math teacher. Always explain your answers step by step.' },
77
- { role: 'user', content: 'What is 2+2?' }
78
- ]);
79
-
80
- console.log('Response:', mathResponse.message.content);
81
-
82
- // Check if response is more detailed (indicating system prompt worked)
83
- const isDetailed = mathResponse.message.content.length > 10 &&
84
- (mathResponse.message.content.toLowerCase().includes('step') ||
85
- mathResponse.message.content.toLowerCase().includes('add') ||
86
- mathResponse.message.content.toLowerCase().includes('plus'));
87
-
88
- if (isDetailed) {
89
- console.log('✅ System prompt appears to be working - detailed explanation provided');
90
- } else {
91
- console.log('⚠️ System prompt effectiveness unclear - response:', mathResponse.message.content);
92
- }
93
-
94
- } catch (error) {
95
- console.error(`❌ Math teacher system prompt failed for ${modelName}:`, error);
96
- testsPassed = false;
97
- }
98
-
99
- // Test 3: System prompt with personality change - streaming
100
- console.log(`\n--- Test 3: System Prompt Streaming - Pirate (${modelName}) ---`);
101
- try {
102
- console.log('System: "You are a friendly pirate. Always use pirate language with Arrr!"');
103
- console.log('Question: "Count from 1 to 3"');
104
- console.log('Streaming response:');
105
- console.log('---');
106
-
107
- const pirateStream = googleModel.chatStream([
108
- { role: 'system', content: 'You are a friendly pirate. Always use pirate language with Arrr!' },
109
- { role: 'user', content: 'Count from 1 to 3' }
110
- ]);
111
-
112
- let streamResponse = '';
113
- for await (const chunk of pirateStream) {
114
- process.stdout.write(chunk);
115
- streamResponse += chunk;
116
- }
117
-
118
- console.log('\n---');
119
-
120
- // Check for pirate language
121
- const hasPirateLanguage = streamResponse.toLowerCase().includes('arr') ||
122
- streamResponse.toLowerCase().includes('matey') ||
123
- streamResponse.toLowerCase().includes('ahoy') ||
124
- streamResponse.toLowerCase().includes('pirate');
125
-
126
- if (hasPirateLanguage) {
127
- console.log('✅ System prompt streaming works - pirate language detected!');
128
- } else {
129
- console.log('⚠️ System prompt streaming effectiveness unclear');
130
- console.log('Response was:', streamResponse);
131
- }
132
-
133
- } catch (error) {
134
- console.error(`❌ Pirate system prompt streaming failed for ${modelName}:`, error);
135
- testsPassed = false;
136
- }
137
-
138
- // Test 4: Complex system prompt with multiple instructions
139
- console.log(`\n--- Test 4: Complex System Prompt (${modelName}) ---`);
140
- try {
141
- console.log('System: Complex instructions with format requirements');
142
- console.log('Question: "List 3 colors"');
143
-
144
- const complexResponse = await googleModel.chat([
145
- { role: 'system', content: 'You are a helpful assistant. Always format your lists with numbers. Always say "Here are" before your list. Keep responses very short.' },
146
- { role: 'user', content: 'List 3 colors' }
147
- ]);
148
-
149
- console.log('Response:', complexResponse.message.content);
150
-
151
- // Check if formatting instructions were followed
152
- const hasNumbering = /\d+\.|\d+\)/.test(complexResponse.message.content);
153
- const hasPrefix = complexResponse.message.content.toLowerCase().includes('here are');
154
-
155
- console.log(`Numbering detected: ${hasNumbering ? '✅' : '❌'}`);
156
- console.log(`Prefix detected: ${hasPrefix ? '✅' : '❌'}`);
157
-
158
- if (hasNumbering || hasPrefix) {
159
- console.log('✅ Complex system prompt partially effective');
160
- } else {
161
- console.log('⚠️ Complex system prompt effectiveness unclear');
162
- }
163
-
164
- } catch (error) {
165
- console.error(`❌ Complex system prompt failed for ${modelName}:`, error);
166
- testsPassed = false;
167
- }
168
-
169
- console.log(`\n📊 ${modelName} Tests Summary: ${testsPassed ? '✅ PASSED' : '❌ FAILED'}`);
170
- return testsPassed;
171
- }
172
-
173
- // Run the comprehensive test
174
- testGoogleSystemPromptHandling().then(result => {
175
- console.log('\n' + '='.repeat(70));
176
- if (result.success) {
177
- console.log('🎉 All tests completed successfully!');
178
- console.log('\n📋 Summary:');
179
- console.log('✅ Gemini models: Using systemInstruction parameter');
180
- console.log('✅ Gemma models: Embedding system prompts in user messages');
181
- console.log('✅ Both streaming and non-streaming work');
182
- console.log('✅ Complex system prompts handled correctly');
183
- } else {
184
- console.log('💥 Some tests failed - check output above');
185
- }
186
- console.log('\n💡 Implementation now follows Google\'s recommendations:');
187
- console.log(' • Gemini: Uses systemInstruction parameter');
188
- console.log(' • Gemma: Embeds system instructions in user prompts');
189
- });
1
+ import { AIModelFactory } from "../factory";
2
+
3
+ /**
4
+ * Comprehensive test for Google models with proper system prompt handling
5
+ * Tests both Gemini (systemInstruction) and Gemma (embedded in user prompt) approaches
6
+ */
7
+ async function testGoogleSystemPromptHandling() {
8
+ console.log('🧪 Testing Google Models with Proper System Prompt Handling...\n');
9
+
10
+ // Test models with different system instruction approaches
11
+ const models = [
12
+ {
13
+ name: 'Gemini 2.5 Flash Lite',
14
+ model: 'gemini-2.5-flash-lite',
15
+ supportsSystemInstruction: true,
16
+ approach: 'Uses Google systemInstruction parameter'
17
+ },
18
+ {
19
+ name: 'Gemma 3 27B IT',
20
+ model: 'gemma-3-27b-it',
21
+ supportsSystemInstruction: false,
22
+ approach: 'Embeds system prompt in user message'
23
+ }
24
+ ];
25
+
26
+ let allTestsPassed = true;
27
+
28
+ for (const modelInfo of models) {
29
+ console.log(`\n🔬 Testing ${modelInfo.name} (${modelInfo.model})`);
30
+ console.log(`System approach: ${modelInfo.approach}`);
31
+ console.log(`System instruction parameter: ${modelInfo.supportsSystemInstruction ? '✅' : '❌'}`);
32
+ console.log('='.repeat(70));
33
+
34
+ const googleModel = AIModelFactory.createGoogleChatModel(
35
+ modelInfo.model,
36
+ (process.env.GOOGLE_API_KEY ?? '')
37
+ );
38
+
39
+ const testResult = await testModelSystemPrompt(googleModel, modelInfo);
40
+ if (!testResult) {
41
+ allTestsPassed = false;
42
+ }
43
+ }
44
+
45
+ return { success: allTestsPassed };
46
+ }
47
+
48
+ async function testModelSystemPrompt(googleModel: any, modelInfo: any) {
49
+ const modelName = modelInfo.name;
50
+ let testsPassed = true;
51
+
52
+ // Test 1: Basic functionality without system prompt
53
+ console.log(`\n--- Test 1: Basic Chat (${modelName}) ---`);
54
+ try {
55
+ console.log('Question: "What is 2+2?"');
56
+
57
+ const basicResponse = await googleModel.chat([
58
+ { role: 'user', content: 'What is 2+2?' }
59
+ ]);
60
+
61
+ console.log('Response:', basicResponse.message.content);
62
+ console.log('✅ Basic chat works');
63
+
64
+ } catch (error) {
65
+ console.error(`❌ Basic chat failed for ${modelName}:`, error);
66
+ testsPassed = false;
67
+ }
68
+
69
+ // Test 2: System prompt with math personality
70
+ console.log(`\n--- Test 2: System Prompt - Math Teacher (${modelName}) ---`);
71
+ try {
72
+ console.log('System: "You are a math teacher. Always explain your answers step by step."');
73
+ console.log('Question: "What is 2+2?"');
74
+
75
+ const mathResponse = await googleModel.chat([
76
+ { role: 'system', content: 'You are a math teacher. Always explain your answers step by step.' },
77
+ { role: 'user', content: 'What is 2+2?' }
78
+ ]);
79
+
80
+ console.log('Response:', mathResponse.message.content);
81
+
82
+ // Check if response is more detailed (indicating system prompt worked)
83
+ const isDetailed = mathResponse.message.content.length > 10 &&
84
+ (mathResponse.message.content.toLowerCase().includes('step') ||
85
+ mathResponse.message.content.toLowerCase().includes('add') ||
86
+ mathResponse.message.content.toLowerCase().includes('plus'));
87
+
88
+ if (isDetailed) {
89
+ console.log('✅ System prompt appears to be working - detailed explanation provided');
90
+ } else {
91
+ console.log('⚠️ System prompt effectiveness unclear - response:', mathResponse.message.content);
92
+ }
93
+
94
+ } catch (error) {
95
+ console.error(`❌ Math teacher system prompt failed for ${modelName}:`, error);
96
+ testsPassed = false;
97
+ }
98
+
99
+ // Test 3: System prompt with personality change - streaming
100
+ console.log(`\n--- Test 3: System Prompt Streaming - Pirate (${modelName}) ---`);
101
+ try {
102
+ console.log('System: "You are a friendly pirate. Always use pirate language with Arrr!"');
103
+ console.log('Question: "Count from 1 to 3"');
104
+ console.log('Streaming response:');
105
+ console.log('---');
106
+
107
+ const pirateStream = googleModel.chatStream([
108
+ { role: 'system', content: 'You are a friendly pirate. Always use pirate language with Arrr!' },
109
+ { role: 'user', content: 'Count from 1 to 3' }
110
+ ]);
111
+
112
+ let streamResponse = '';
113
+ for await (const chunk of pirateStream) {
114
+ process.stdout.write(chunk);
115
+ streamResponse += chunk;
116
+ }
117
+
118
+ console.log('\n---');
119
+
120
+ // Check for pirate language
121
+ const hasPirateLanguage = streamResponse.toLowerCase().includes('arr') ||
122
+ streamResponse.toLowerCase().includes('matey') ||
123
+ streamResponse.toLowerCase().includes('ahoy') ||
124
+ streamResponse.toLowerCase().includes('pirate');
125
+
126
+ if (hasPirateLanguage) {
127
+ console.log('✅ System prompt streaming works - pirate language detected!');
128
+ } else {
129
+ console.log('⚠️ System prompt streaming effectiveness unclear');
130
+ console.log('Response was:', streamResponse);
131
+ }
132
+
133
+ } catch (error) {
134
+ console.error(`❌ Pirate system prompt streaming failed for ${modelName}:`, error);
135
+ testsPassed = false;
136
+ }
137
+
138
+ // Test 4: Complex system prompt with multiple instructions
139
+ console.log(`\n--- Test 4: Complex System Prompt (${modelName}) ---`);
140
+ try {
141
+ console.log('System: Complex instructions with format requirements');
142
+ console.log('Question: "List 3 colors"');
143
+
144
+ const complexResponse = await googleModel.chat([
145
+ { role: 'system', content: 'You are a helpful assistant. Always format your lists with numbers. Always say "Here are" before your list. Keep responses very short.' },
146
+ { role: 'user', content: 'List 3 colors' }
147
+ ]);
148
+
149
+ console.log('Response:', complexResponse.message.content);
150
+
151
+ // Check if formatting instructions were followed
152
+ const hasNumbering = /\d+\.|\d+\)/.test(complexResponse.message.content);
153
+ const hasPrefix = complexResponse.message.content.toLowerCase().includes('here are');
154
+
155
+ console.log(`Numbering detected: ${hasNumbering ? '✅' : '❌'}`);
156
+ console.log(`Prefix detected: ${hasPrefix ? '✅' : '❌'}`);
157
+
158
+ if (hasNumbering || hasPrefix) {
159
+ console.log('✅ Complex system prompt partially effective');
160
+ } else {
161
+ console.log('⚠️ Complex system prompt effectiveness unclear');
162
+ }
163
+
164
+ } catch (error) {
165
+ console.error(`❌ Complex system prompt failed for ${modelName}:`, error);
166
+ testsPassed = false;
167
+ }
168
+
169
+ console.log(`\n📊 ${modelName} Tests Summary: ${testsPassed ? '✅ PASSED' : '❌ FAILED'}`);
170
+ return testsPassed;
171
+ }
172
+
173
+ // Run the comprehensive test
174
+ testGoogleSystemPromptHandling().then(result => {
175
+ console.log('\n' + '='.repeat(70));
176
+ if (result.success) {
177
+ console.log('🎉 All tests completed successfully!');
178
+ console.log('\n📋 Summary:');
179
+ console.log('✅ Gemini models: Using systemInstruction parameter');
180
+ console.log('✅ Gemma models: Embedding system prompts in user messages');
181
+ console.log('✅ Both streaming and non-streaming work');
182
+ console.log('✅ Complex system prompts handled correctly');
183
+ } else {
184
+ console.log('💥 Some tests failed - check output above');
185
+ }
186
+ console.log('\n💡 Implementation now follows Google\'s recommendations:');
187
+ console.log(' • Gemini: Uses systemInstruction parameter');
188
+ console.log(' • Gemma: Embeds system instructions in user prompts');
189
+ });
@@ -0,0 +1,46 @@
1
+ /**
2
+ * Live check: unified `thinking` levels + reasoning-text surfacing against the
3
+ * real Gemini API. Reads GOOGLE_API_KEY from the environment (never hard-code).
4
+ *
5
+ * $env:GOOGLE_API_KEY="..."; bun run src/test-scripts/test-google-thinking.ts
6
+ */
7
+ import { AIModel } from '../index.js';
8
+ import type { ThinkingLevel } from '../index.js';
9
+
10
+ const KEY = process.env.GOOGLE_API_KEY;
11
+ const MODEL = process.env.GOOGLE_MODEL ?? 'gemini-3.5-flash';
12
+ if (!KEY) { console.error('Set GOOGLE_API_KEY'); process.exit(1); }
13
+
14
+ const PROMPT = 'A farmer has 17 sheep. All but 9 run away. Then he buys 5 more. How many sheep? Give the number.';
15
+
16
+ async function run(thinking: boolean | ThinkingLevel) {
17
+ const model = new AIModel({ model: MODEL, providers: [{ type: 'google', apiKey: KEY }] });
18
+ const r = await model.chat([{ role: 'user', content: PROMPT }], { thinking, maxTokens: 2048 });
19
+ return {
20
+ content: (r.message.content ?? '').replace(/\n/g, ' ').trim().slice(0, 55),
21
+ reasoningChars: (r.reasoning ?? '').length,
22
+ reasoningTokens: r.usage?.reasoningTokens ?? 0,
23
+ tps: r.usage?.tokensPerSecond,
24
+ };
25
+ }
26
+
27
+ (async () => {
28
+ console.log(`Live Gemini thinking-levels test — model=${MODEL}\n`);
29
+ const settings: Array<boolean | ThinkingLevel> = ['high', 'medium', 'low', 'minimal', false];
30
+ let anyText = false;
31
+ for (const t of settings) {
32
+ try {
33
+ const x = await run(t);
34
+ if (x.reasoningChars > 0) anyText = true;
35
+ console.log(
36
+ `thinking=${String(t).padEnd(8)} -> reasoning ${String(x.reasoningChars).padStart(5)} chars` +
37
+ `, reasoningTokens ${String(x.reasoningTokens).padStart(4)}, content: ${JSON.stringify(x.content)}`,
38
+ );
39
+ } catch (e) {
40
+ console.log(`thinking=${String(t).padEnd(8)} -> ERROR ${(e as Error)?.message ?? e}`);
41
+ }
42
+ }
43
+ console.log(anyText
44
+ ? '\n✅ Reasoning TEXT surfaced via response.reasoning (Part B) + levels mapped (Part A).'
45
+ : '\n🟡 No reasoning text surfaced — check includeThoughts/thinkingLevel mapping.');
46
+ })().catch(e => { console.error('FATAL', (e as Error)?.message ?? e); process.exit(1); });