@providerprotocol/ai 0.0.9 → 0.0.11
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/dist/index.d.ts +7 -1
- package/dist/index.js +34 -6
- package/dist/index.js.map +1 -1
- package/dist/openai/index.d.ts +24 -4
- package/dist/openai/index.js.map +1 -1
- package/package.json +1 -1
- package/src/core/llm.ts +34 -8
- package/src/openai/index.ts +1 -0
- package/src/providers/openai/index.ts +1 -0
- package/src/providers/openai/types.ts +24 -3
- package/src/types/stream.ts +42 -0
package/src/core/llm.ts
CHANGED
|
@@ -23,7 +23,11 @@ import {
|
|
|
23
23
|
isAssistantMessage,
|
|
24
24
|
} from '../types/messages.ts';
|
|
25
25
|
import { createTurn, aggregateUsage, emptyUsage } from '../types/turn.ts';
|
|
26
|
-
import {
|
|
26
|
+
import {
|
|
27
|
+
createStreamResult,
|
|
28
|
+
toolExecutionStart,
|
|
29
|
+
toolExecutionEnd,
|
|
30
|
+
} from '../types/stream.ts';
|
|
27
31
|
import { generateShortId } from '../utils/id.ts';
|
|
28
32
|
|
|
29
33
|
/**
|
|
@@ -413,14 +417,21 @@ function executeStream<TParams>(
|
|
|
413
417
|
);
|
|
414
418
|
}
|
|
415
419
|
|
|
416
|
-
// Execute tools
|
|
420
|
+
// Execute tools with event emission
|
|
421
|
+
const toolEvents: StreamEvent[] = [];
|
|
417
422
|
const results = await executeTools(
|
|
418
423
|
response.message,
|
|
419
424
|
tools,
|
|
420
425
|
toolStrategy,
|
|
421
|
-
toolExecutions
|
|
426
|
+
toolExecutions,
|
|
427
|
+
(event) => toolEvents.push(event)
|
|
422
428
|
);
|
|
423
429
|
|
|
430
|
+
// Yield tool execution events
|
|
431
|
+
for (const event of toolEvents) {
|
|
432
|
+
yield event;
|
|
433
|
+
}
|
|
434
|
+
|
|
424
435
|
// Add tool results
|
|
425
436
|
allMessages.push(new ToolResultMessage(results));
|
|
426
437
|
|
|
@@ -467,7 +478,8 @@ async function executeTools(
|
|
|
467
478
|
message: AssistantMessage,
|
|
468
479
|
tools: Tool[],
|
|
469
480
|
toolStrategy: LLMOptions<unknown>['toolStrategy'],
|
|
470
|
-
executions: ToolExecution[]
|
|
481
|
+
executions: ToolExecution[],
|
|
482
|
+
onEvent?: (event: StreamEvent) => void
|
|
471
483
|
): Promise<ToolResult[]> {
|
|
472
484
|
const toolCalls = message.toolCalls ?? [];
|
|
473
485
|
const results: ToolResult[] = [];
|
|
@@ -476,7 +488,7 @@ async function executeTools(
|
|
|
476
488
|
const toolMap = new Map(tools.map((t) => [t.name, t]));
|
|
477
489
|
|
|
478
490
|
// Execute tools (in parallel)
|
|
479
|
-
const promises = toolCalls.map(async (call) => {
|
|
491
|
+
const promises = toolCalls.map(async (call, index) => {
|
|
480
492
|
const tool = toolMap.get(call.toolName);
|
|
481
493
|
if (!tool) {
|
|
482
494
|
return {
|
|
@@ -488,6 +500,9 @@ async function executeTools(
|
|
|
488
500
|
|
|
489
501
|
const startTime = Date.now();
|
|
490
502
|
|
|
503
|
+
// Emit start event
|
|
504
|
+
onEvent?.(toolExecutionStart(call.toolCallId, tool.name, startTime, index));
|
|
505
|
+
|
|
491
506
|
// Notify strategy
|
|
492
507
|
await toolStrategy?.onToolCall?.(tool, call.arguments);
|
|
493
508
|
|
|
@@ -495,6 +510,8 @@ async function executeTools(
|
|
|
495
510
|
if (toolStrategy?.onBeforeCall) {
|
|
496
511
|
const shouldRun = await toolStrategy.onBeforeCall(tool, call.arguments);
|
|
497
512
|
if (!shouldRun) {
|
|
513
|
+
const endTime = Date.now();
|
|
514
|
+
onEvent?.(toolExecutionEnd(call.toolCallId, tool.name, 'Tool execution skipped', true, endTime, index));
|
|
498
515
|
return {
|
|
499
516
|
toolCallId: call.toolCallId,
|
|
500
517
|
result: 'Tool execution skipped',
|
|
@@ -515,17 +532,20 @@ async function executeTools(
|
|
|
515
532
|
}
|
|
516
533
|
|
|
517
534
|
if (!approved) {
|
|
535
|
+
const endTime = Date.now();
|
|
518
536
|
const execution: ToolExecution = {
|
|
519
537
|
toolName: tool.name,
|
|
520
538
|
toolCallId: call.toolCallId,
|
|
521
539
|
arguments: call.arguments,
|
|
522
540
|
result: 'Tool execution denied',
|
|
523
541
|
isError: true,
|
|
524
|
-
duration:
|
|
542
|
+
duration: endTime - startTime,
|
|
525
543
|
approved: false,
|
|
526
544
|
};
|
|
527
545
|
executions.push(execution);
|
|
528
546
|
|
|
547
|
+
onEvent?.(toolExecutionEnd(call.toolCallId, tool.name, 'Tool execution denied by approval handler', true, endTime, index));
|
|
548
|
+
|
|
529
549
|
return {
|
|
530
550
|
toolCallId: call.toolCallId,
|
|
531
551
|
result: 'Tool execution denied by approval handler',
|
|
@@ -536,6 +556,7 @@ async function executeTools(
|
|
|
536
556
|
// Execute tool
|
|
537
557
|
try {
|
|
538
558
|
const result = await tool.run(call.arguments);
|
|
559
|
+
const endTime = Date.now();
|
|
539
560
|
|
|
540
561
|
await toolStrategy?.onAfterCall?.(tool, call.arguments, result);
|
|
541
562
|
|
|
@@ -545,17 +566,20 @@ async function executeTools(
|
|
|
545
566
|
arguments: call.arguments,
|
|
546
567
|
result,
|
|
547
568
|
isError: false,
|
|
548
|
-
duration:
|
|
569
|
+
duration: endTime - startTime,
|
|
549
570
|
approved,
|
|
550
571
|
};
|
|
551
572
|
executions.push(execution);
|
|
552
573
|
|
|
574
|
+
onEvent?.(toolExecutionEnd(call.toolCallId, tool.name, result, false, endTime, index));
|
|
575
|
+
|
|
553
576
|
return {
|
|
554
577
|
toolCallId: call.toolCallId,
|
|
555
578
|
result,
|
|
556
579
|
isError: false,
|
|
557
580
|
};
|
|
558
581
|
} catch (error) {
|
|
582
|
+
const endTime = Date.now();
|
|
559
583
|
await toolStrategy?.onError?.(tool, call.arguments, error as Error);
|
|
560
584
|
|
|
561
585
|
const errorMessage = error instanceof Error ? error.message : String(error);
|
|
@@ -566,11 +590,13 @@ async function executeTools(
|
|
|
566
590
|
arguments: call.arguments,
|
|
567
591
|
result: errorMessage,
|
|
568
592
|
isError: true,
|
|
569
|
-
duration:
|
|
593
|
+
duration: endTime - startTime,
|
|
570
594
|
approved,
|
|
571
595
|
};
|
|
572
596
|
executions.push(execution);
|
|
573
597
|
|
|
598
|
+
onEvent?.(toolExecutionEnd(call.toolCallId, tool.name, errorMessage, true, endTime, index));
|
|
599
|
+
|
|
574
600
|
return {
|
|
575
601
|
toolCallId: call.toolCallId,
|
|
576
602
|
result: errorMessage,
|
package/src/openai/index.ts
CHANGED
|
@@ -27,8 +27,8 @@ export interface OpenAIAudioConfig {
|
|
|
27
27
|
// ============================================
|
|
28
28
|
|
|
29
29
|
/**
|
|
30
|
-
* User location for web search context
|
|
31
|
-
*
|
|
30
|
+
* User location for web search context (Responses API format)
|
|
31
|
+
* Fields are at the same level as type
|
|
32
32
|
*/
|
|
33
33
|
export interface OpenAIWebSearchUserLocation {
|
|
34
34
|
/** Location type - must be 'approximate' */
|
|
@@ -43,8 +43,29 @@ export interface OpenAIWebSearchUserLocation {
|
|
|
43
43
|
timezone?: string;
|
|
44
44
|
}
|
|
45
45
|
|
|
46
|
+
/**
|
|
47
|
+
* User location for web search context (Chat Completions API format)
|
|
48
|
+
* Fields are nested under 'approximate' object
|
|
49
|
+
*/
|
|
50
|
+
export interface OpenAICompletionsWebSearchUserLocation {
|
|
51
|
+
/** Location type - must be 'approximate' */
|
|
52
|
+
type: 'approximate';
|
|
53
|
+
/** Approximate location details */
|
|
54
|
+
approximate: {
|
|
55
|
+
/** City name */
|
|
56
|
+
city?: string;
|
|
57
|
+
/** ISO 3166-1 country code (e.g., "US") */
|
|
58
|
+
country?: string;
|
|
59
|
+
/** Region/state name */
|
|
60
|
+
region?: string;
|
|
61
|
+
/** IANA timezone (e.g., "America/New_York") */
|
|
62
|
+
timezone?: string;
|
|
63
|
+
};
|
|
64
|
+
}
|
|
65
|
+
|
|
46
66
|
/**
|
|
47
67
|
* Web search options for Chat Completions API
|
|
68
|
+
* Use with gpt-5-search-api-* models
|
|
48
69
|
*/
|
|
49
70
|
export interface OpenAIWebSearchOptions {
|
|
50
71
|
/**
|
|
@@ -53,7 +74,7 @@ export interface OpenAIWebSearchOptions {
|
|
|
53
74
|
*/
|
|
54
75
|
search_context_size?: 'low' | 'medium' | 'high';
|
|
55
76
|
/** User location for localizing search results */
|
|
56
|
-
user_location?:
|
|
77
|
+
user_location?: OpenAICompletionsWebSearchUserLocation | null;
|
|
57
78
|
}
|
|
58
79
|
|
|
59
80
|
/**
|
package/src/types/stream.ts
CHANGED
|
@@ -10,6 +10,8 @@ export type StreamEventType =
|
|
|
10
10
|
| 'audio_delta'
|
|
11
11
|
| 'video_delta'
|
|
12
12
|
| 'tool_call_delta'
|
|
13
|
+
| 'tool_execution_start'
|
|
14
|
+
| 'tool_execution_end'
|
|
13
15
|
| 'message_start'
|
|
14
16
|
| 'message_stop'
|
|
15
17
|
| 'content_block_start'
|
|
@@ -24,6 +26,12 @@ export interface EventDelta {
|
|
|
24
26
|
toolCallId?: string;
|
|
25
27
|
toolName?: string;
|
|
26
28
|
argumentsJson?: string;
|
|
29
|
+
/** Tool execution result (for tool_execution_end) */
|
|
30
|
+
result?: unknown;
|
|
31
|
+
/** Whether tool execution errored (for tool_execution_end) */
|
|
32
|
+
isError?: boolean;
|
|
33
|
+
/** Timestamp in ms (for tool_execution_start/end) */
|
|
34
|
+
timestamp?: number;
|
|
27
35
|
}
|
|
28
36
|
|
|
29
37
|
/**
|
|
@@ -144,3 +152,37 @@ export function contentBlockStop(index: number): StreamEvent {
|
|
|
144
152
|
delta: {},
|
|
145
153
|
};
|
|
146
154
|
}
|
|
155
|
+
|
|
156
|
+
/**
|
|
157
|
+
* Create a tool execution start event
|
|
158
|
+
*/
|
|
159
|
+
export function toolExecutionStart(
|
|
160
|
+
toolCallId: string,
|
|
161
|
+
toolName: string,
|
|
162
|
+
timestamp: number,
|
|
163
|
+
index = 0
|
|
164
|
+
): StreamEvent {
|
|
165
|
+
return {
|
|
166
|
+
type: 'tool_execution_start',
|
|
167
|
+
index,
|
|
168
|
+
delta: { toolCallId, toolName, timestamp },
|
|
169
|
+
};
|
|
170
|
+
}
|
|
171
|
+
|
|
172
|
+
/**
|
|
173
|
+
* Create a tool execution end event
|
|
174
|
+
*/
|
|
175
|
+
export function toolExecutionEnd(
|
|
176
|
+
toolCallId: string,
|
|
177
|
+
toolName: string,
|
|
178
|
+
result: unknown,
|
|
179
|
+
isError: boolean,
|
|
180
|
+
timestamp: number,
|
|
181
|
+
index = 0
|
|
182
|
+
): StreamEvent {
|
|
183
|
+
return {
|
|
184
|
+
type: 'tool_execution_end',
|
|
185
|
+
index,
|
|
186
|
+
delta: { toolCallId, toolName, result, isError, timestamp },
|
|
187
|
+
};
|
|
188
|
+
}
|