graphlit-client 1.0.20260406002 ā 1.0.20260408001
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/client.d.ts +4 -0
- package/dist/client.js +106 -17
- package/dist/generated/graphql-documents.js +7 -0
- package/dist/generated/graphql-types.d.ts +23 -1
- package/dist/generated/graphql-types.js +8 -0
- package/dist/model-mapping.d.ts +6 -0
- package/dist/model-mapping.js +36 -0
- package/dist/streaming/llm-formatters.d.ts +45 -0
- package/dist/streaming/llm-formatters.js +124 -0
- package/dist/streaming/openai-responses.d.ts +10 -0
- package/dist/streaming/openai-responses.js +221 -0
- package/dist/types/agent.d.ts +4 -0
- package/package.json +2 -2
package/dist/client.d.ts
CHANGED
|
@@ -3057,6 +3057,10 @@ declare class Graphlit {
|
|
|
3057
3057
|
* Fallback to non-streaming when streaming is not available
|
|
3058
3058
|
*/
|
|
3059
3059
|
private fallbackToNonStreaming;
|
|
3060
|
+
/**
|
|
3061
|
+
* Stream with OpenAI client
|
|
3062
|
+
*/
|
|
3063
|
+
private streamWithOpenAIResponses;
|
|
3060
3064
|
/**
|
|
3061
3065
|
* Stream with OpenAI client
|
|
3062
3066
|
*/
|
package/dist/client.js
CHANGED
|
@@ -6,13 +6,14 @@ import { RetryLink } from "@apollo/client/link/retry/index.js";
|
|
|
6
6
|
import { attachPartialErrors } from "./partial-errors.js";
|
|
7
7
|
import * as Types from "./generated/graphql-types.js";
|
|
8
8
|
import * as Documents from "./generated/graphql-documents.js";
|
|
9
|
-
import { getServiceType, getModelName, getModelEnum } from "./model-mapping.js";
|
|
9
|
+
import { getServiceType, getModelName, getModelEnum, isOpenAIResponsesEligibleModel, } from "./model-mapping.js";
|
|
10
10
|
import { StuckDetector } from "./helpers/stuck-detector.js";
|
|
11
11
|
import { TurnEvaluator } from "./helpers/turn-evaluator.js";
|
|
12
12
|
import { TokenBudgetTracker, truncateToolResult, windowToolRounds, estimateTokens, DEFAULT_CONTEXT_STRATEGY, } from "./helpers/context-management.js";
|
|
13
13
|
import { ProviderError } from "./types/internal.js";
|
|
14
14
|
import { UIEventAdapter } from "./streaming/ui-event-adapter.js";
|
|
15
|
-
import { formatMessagesForOpenAI, formatMessagesForAnthropic, formatMessagesForGoogle, formatMessagesForMistral, formatMessagesForBedrock, } from "./streaming/llm-formatters.js";
|
|
15
|
+
import { formatMessagesForOpenAI, formatMessagesForOpenAIResponsesInitialRound, extractInstructionsForOpenAIResponses, buildResponsesFunctionCallOutputItems, formatToolsForOpenAIResponses, formatMessagesForAnthropic, formatMessagesForGoogle, formatMessagesForMistral, formatMessagesForBedrock, } from "./streaming/llm-formatters.js";
|
|
16
|
+
import { streamWithOpenAIResponses, } from "./streaming/openai-responses.js";
|
|
16
17
|
import { streamWithOpenAI, streamWithAnthropic, streamWithGoogle, streamWithGroq, streamWithCerebras, streamWithCohere, streamWithMistral, streamWithBedrock, streamWithDeepseek, streamWithXai, } from "./streaming/providers.js";
|
|
17
18
|
// Optional imports for streaming LLM clients
|
|
18
19
|
// These are peer dependencies and may not be installed
|
|
@@ -50,6 +51,9 @@ function normalizeToolCallForExecution(toolCall) {
|
|
|
50
51
|
firstStatusAt: toolCall.firstStatusAt ?? undefined,
|
|
51
52
|
};
|
|
52
53
|
}
|
|
54
|
+
// Temporary rollout guard: keep default OpenAI Responses routing off until we
|
|
55
|
+
// intentionally flip the switch. Explicit `useResponsesApi: true` still forces it.
|
|
56
|
+
const OPENAI_RESPONSES_AUTO_ROUTING_ENABLED = false;
|
|
53
57
|
function buildConversationToolCallFromResult(toolResult) {
|
|
54
58
|
return {
|
|
55
59
|
__typename: "ConversationToolCall",
|
|
@@ -5650,7 +5654,7 @@ class Graphlit {
|
|
|
5650
5654
|
});
|
|
5651
5655
|
// Start the streaming conversation
|
|
5652
5656
|
// fullSpec is guaranteed non-null here ā the !fullSpec check above returns early
|
|
5653
|
-
await this.executeStreamingAgent(prompt, actualConversationId, fullSpec, tools, toolHandlers, uiAdapter, maxRounds, abortSignal, mimeType, data, correlationId, persona, options?.contextStrategy, options?.instructions, options?.scratchpad, options?.skills);
|
|
5657
|
+
await this.executeStreamingAgent(prompt, actualConversationId, fullSpec, tools, toolHandlers, uiAdapter, maxRounds, abortSignal, mimeType, data, correlationId, persona, options?.contextStrategy, options?.useResponsesApi, options?.instructions, options?.scratchpad, options?.skills);
|
|
5654
5658
|
}, abortSignal);
|
|
5655
5659
|
}
|
|
5656
5660
|
catch (error) {
|
|
@@ -5696,7 +5700,7 @@ class Graphlit {
|
|
|
5696
5700
|
/**
|
|
5697
5701
|
* Execute the streaming agent workflow with tool calling loop
|
|
5698
5702
|
*/
|
|
5699
|
-
async executeStreamingAgent(prompt, conversationId, specification, tools, toolHandlers, uiAdapter, maxRounds, abortSignal, mimeType, data, correlationId, persona, contextStrategy, instructions, scratchpad, skills) {
|
|
5703
|
+
async executeStreamingAgent(prompt, conversationId, specification, tools, toolHandlers, uiAdapter, maxRounds, abortSignal, mimeType, data, correlationId, persona, contextStrategy, useResponsesApi, instructions, scratchpad, skills) {
|
|
5700
5704
|
// Collects artifact content IDs from tool handlers (e.g. code_execution).
|
|
5701
5705
|
// Handlers register async ingestion promises; we await all of them before
|
|
5702
5706
|
// completeConversation so the IDs are available without blocking the LLM.
|
|
@@ -5868,6 +5872,7 @@ class Graphlit {
|
|
|
5868
5872
|
contextStrategy: mergedStrategy,
|
|
5869
5873
|
maxRounds,
|
|
5870
5874
|
abortSignal,
|
|
5875
|
+
useResponsesApi,
|
|
5871
5876
|
correlationId,
|
|
5872
5877
|
persona,
|
|
5873
5878
|
mimeType,
|
|
@@ -5928,7 +5933,7 @@ class Graphlit {
|
|
|
5928
5933
|
* Shared between streamAgent (single turn) and runAgent (multi-turn harness).
|
|
5929
5934
|
*/
|
|
5930
5935
|
async executeStreamingLoop(config) {
|
|
5931
|
-
const { conversationId, specification, tools, toolHandlers, uiAdapter, budgetTracker, contextStrategy: { toolResultTokenLimit, toolRoundLimit, rebudgetThreshold }, maxRounds, abortSignal, mimeType, data, correlationId, persona, } = config;
|
|
5936
|
+
const { conversationId, specification, tools, toolHandlers, uiAdapter, budgetTracker, contextStrategy: { toolResultTokenLimit, toolRoundLimit, rebudgetThreshold }, maxRounds, abortSignal, useResponsesApi, mimeType, data, correlationId, persona, } = config;
|
|
5932
5937
|
let messages = config.messages;
|
|
5933
5938
|
let currentRound = 0;
|
|
5934
5939
|
let fullMessage = "";
|
|
@@ -5951,8 +5956,14 @@ class Graphlit {
|
|
|
5951
5956
|
},
|
|
5952
5957
|
};
|
|
5953
5958
|
const serviceType = getServiceType(specification);
|
|
5959
|
+
const useOpenAIResponses = (useResponsesApi === true ||
|
|
5960
|
+
(OPENAI_RESPONSES_AUTO_ROUTING_ENABLED && useResponsesApi !== false)) &&
|
|
5961
|
+
serviceType === Types.ModelServiceTypes.OpenAi &&
|
|
5962
|
+
isOpenAIResponsesEligibleModel(specification);
|
|
5954
5963
|
const toolMessagesStartIndex = messages.length;
|
|
5955
5964
|
let lastRoundReasoning;
|
|
5965
|
+
let openAIResponsesState;
|
|
5966
|
+
let openAIResponsesPendingToolMessages = [];
|
|
5956
5967
|
if (process.env.DEBUG_GRAPHLIT_SDK_STREAMING && budgetTracker) {
|
|
5957
5968
|
console.log(`š [Context Management] Initialized budget tracker: ${budgetTracker.usagePercent}% used, ` +
|
|
5958
5969
|
`${budgetTracker.remaining.toLocaleString()} tokens remaining. ` +
|
|
@@ -5970,6 +5981,10 @@ class Graphlit {
|
|
|
5970
5981
|
const beforeCount = messages.length;
|
|
5971
5982
|
messages = windowToolRounds(messages, toolRoundLimit);
|
|
5972
5983
|
budgetTracker.resetFromMessages(messages);
|
|
5984
|
+
if (useOpenAIResponses) {
|
|
5985
|
+
openAIResponsesState = undefined;
|
|
5986
|
+
openAIResponsesPendingToolMessages = [];
|
|
5987
|
+
}
|
|
5973
5988
|
const afterUsage = budgetTracker.usagePercent;
|
|
5974
5989
|
const droppedRounds = Math.max(0, Math.floor((beforeCount - messages.length) / 2));
|
|
5975
5990
|
if (droppedRounds > 0) {
|
|
@@ -6018,22 +6033,44 @@ class Graphlit {
|
|
|
6018
6033
|
if (serviceType === Types.ModelServiceTypes.OpenAi &&
|
|
6019
6034
|
(OpenAI || this.openaiClient)) {
|
|
6020
6035
|
if (process.env.DEBUG_GRAPHLIT_SDK_STREAMING) {
|
|
6021
|
-
console.log(`\nā
[Streaming] Using OpenAI native streaming (Round ${currentRound})`);
|
|
6036
|
+
console.log(`\nā
[Streaming] Using OpenAI ${useOpenAIResponses ? "Responses" : "native"} streaming (Round ${currentRound})`);
|
|
6022
6037
|
}
|
|
6023
|
-
|
|
6024
|
-
|
|
6025
|
-
|
|
6038
|
+
if (useOpenAIResponses) {
|
|
6039
|
+
if (!openAIResponsesState) {
|
|
6040
|
+
openAIResponsesState = {
|
|
6041
|
+
instructions: extractInstructionsForOpenAIResponses(messages),
|
|
6042
|
+
initialInput: formatMessagesForOpenAIResponsesInitialRound(messages),
|
|
6043
|
+
continuationItems: [],
|
|
6044
|
+
};
|
|
6045
|
+
}
|
|
6046
|
+
if (process.env.DEBUG_GRAPHLIT_SDK_STREAMING_MESSAGES) {
|
|
6047
|
+
console.log(`š [OpenAI Responses] Sending ${openAIResponsesState.initialInput.length} initial items and ${openAIResponsesState.continuationItems.length} continuation items`);
|
|
6048
|
+
}
|
|
6049
|
+
const responsesResult = await this.streamWithOpenAIResponses(specification, messages, openAIResponsesPendingToolMessages, tools, uiAdapter, abortSignal, openAIResponsesState);
|
|
6050
|
+
roundMessage = responsesResult.message;
|
|
6051
|
+
toolCalls = responsesResult.toolCalls;
|
|
6052
|
+
openAIResponsesState = responsesResult.state;
|
|
6053
|
+
if (responsesResult.usage) {
|
|
6054
|
+
uiAdapter.setUsageData(responsesResult.usage);
|
|
6055
|
+
}
|
|
6056
|
+
openAIResponsesPendingToolMessages = [];
|
|
6026
6057
|
}
|
|
6027
|
-
|
|
6028
|
-
|
|
6029
|
-
|
|
6030
|
-
|
|
6031
|
-
if (usage) {
|
|
6032
|
-
uiAdapter.setUsageData(usage);
|
|
6058
|
+
else {
|
|
6059
|
+
const openaiMessages = formatMessagesForOpenAI(messages);
|
|
6060
|
+
if (process.env.DEBUG_GRAPHLIT_SDK_STREAMING_MESSAGES) {
|
|
6061
|
+
console.log(`š [OpenAI] Sending ${openaiMessages.length} messages to LLM: ${JSON.stringify(openaiMessages)}`);
|
|
6033
6062
|
}
|
|
6034
|
-
|
|
6063
|
+
await this.streamWithOpenAI(specification, openaiMessages, tools, uiAdapter, (message, calls, usage, reasoning) => {
|
|
6064
|
+
roundMessage = message;
|
|
6065
|
+
toolCalls = calls;
|
|
6066
|
+
roundReasoning = reasoning;
|
|
6067
|
+
if (usage) {
|
|
6068
|
+
uiAdapter.setUsageData(usage);
|
|
6069
|
+
}
|
|
6070
|
+
}, abortSignal);
|
|
6071
|
+
}
|
|
6035
6072
|
if (process.env.DEBUG_GRAPHLIT_SDK_STREAMING) {
|
|
6036
|
-
console.log(`\nš [Streaming] OpenAI native streaming completed (Round ${currentRound})`);
|
|
6073
|
+
console.log(`\nš [Streaming] OpenAI ${useOpenAIResponses ? "Responses" : "native"} streaming completed (Round ${currentRound})`);
|
|
6037
6074
|
}
|
|
6038
6075
|
}
|
|
6039
6076
|
else if (serviceType === Types.ModelServiceTypes.Anthropic &&
|
|
@@ -6620,6 +6657,11 @@ class Graphlit {
|
|
|
6620
6657
|
budgetTracker.addMessage(executionResult.budgetText);
|
|
6621
6658
|
}
|
|
6622
6659
|
}
|
|
6660
|
+
if (useOpenAIResponses) {
|
|
6661
|
+
openAIResponsesPendingToolMessages = toolExecutionResults
|
|
6662
|
+
.map((executionResult) => executionResult?.toolMessage)
|
|
6663
|
+
.filter((message) => message != null);
|
|
6664
|
+
}
|
|
6623
6665
|
}
|
|
6624
6666
|
// Emit context window usage after each tool round
|
|
6625
6667
|
if (budgetTracker) {
|
|
@@ -7074,6 +7116,7 @@ class Graphlit {
|
|
|
7074
7116
|
contextStrategy: mergedStrategy,
|
|
7075
7117
|
maxRounds: DEFAULT_MAX_TOOL_ROUNDS,
|
|
7076
7118
|
abortSignal,
|
|
7119
|
+
useResponsesApi: options?.useResponsesApi,
|
|
7077
7120
|
correlationId: options?.correlationId,
|
|
7078
7121
|
persona: options?.persona,
|
|
7079
7122
|
});
|
|
@@ -7558,6 +7601,52 @@ class Graphlit {
|
|
|
7558
7601
|
}
|
|
7559
7602
|
}
|
|
7560
7603
|
}
|
|
7604
|
+
/**
|
|
7605
|
+
* Stream with OpenAI client
|
|
7606
|
+
*/
|
|
7607
|
+
async streamWithOpenAIResponses(specification, messages, toolMessages, tools, uiAdapter, abortSignal, state) {
|
|
7608
|
+
if (!OpenAI && !this.openaiClient) {
|
|
7609
|
+
throw new Error("OpenAI client not available");
|
|
7610
|
+
}
|
|
7611
|
+
const openaiClient = this.openaiClient ||
|
|
7612
|
+
(OpenAI
|
|
7613
|
+
? new OpenAI({
|
|
7614
|
+
apiKey: process.env.OPENAI_API_KEY || "",
|
|
7615
|
+
maxRetries: 3,
|
|
7616
|
+
timeout: 60000,
|
|
7617
|
+
})
|
|
7618
|
+
: (() => {
|
|
7619
|
+
throw new Error("OpenAI module not available");
|
|
7620
|
+
})());
|
|
7621
|
+
const reasoningEffort = specification.openAI?.reasoningEffort || undefined;
|
|
7622
|
+
const toolDefinitions = formatToolsForOpenAIResponses(tools);
|
|
7623
|
+
const baseState = state || {
|
|
7624
|
+
instructions: extractInstructionsForOpenAIResponses(messages),
|
|
7625
|
+
initialInput: formatMessagesForOpenAIResponsesInitialRound(messages),
|
|
7626
|
+
continuationItems: [],
|
|
7627
|
+
};
|
|
7628
|
+
const functionCallOutputs = buildResponsesFunctionCallOutputItems(toolMessages);
|
|
7629
|
+
const input = [
|
|
7630
|
+
...baseState.initialInput,
|
|
7631
|
+
...baseState.continuationItems,
|
|
7632
|
+
...functionCallOutputs,
|
|
7633
|
+
];
|
|
7634
|
+
const response = await streamWithOpenAIResponses(specification, baseState.instructions, input, toolDefinitions, openaiClient, (event) => uiAdapter.handleEvent(event), abortSignal, reasoningEffort);
|
|
7635
|
+
return {
|
|
7636
|
+
message: response.message,
|
|
7637
|
+
toolCalls: response.toolCalls,
|
|
7638
|
+
usage: response.usage,
|
|
7639
|
+
state: {
|
|
7640
|
+
instructions: baseState.instructions,
|
|
7641
|
+
initialInput: baseState.initialInput,
|
|
7642
|
+
continuationItems: [
|
|
7643
|
+
...baseState.continuationItems,
|
|
7644
|
+
...functionCallOutputs,
|
|
7645
|
+
...response.outputItems,
|
|
7646
|
+
],
|
|
7647
|
+
},
|
|
7648
|
+
};
|
|
7649
|
+
}
|
|
7561
7650
|
/**
|
|
7562
7651
|
* Stream with OpenAI client
|
|
7563
7652
|
*/
|
|
@@ -16597,6 +16597,7 @@ export const CreatePersona = gql `
|
|
|
16597
16597
|
id
|
|
16598
16598
|
name
|
|
16599
16599
|
state
|
|
16600
|
+
type
|
|
16600
16601
|
identifier
|
|
16601
16602
|
platform
|
|
16602
16603
|
displayName
|
|
@@ -16644,6 +16645,7 @@ export const GetPersona = gql `
|
|
|
16644
16645
|
id
|
|
16645
16646
|
}
|
|
16646
16647
|
state
|
|
16648
|
+
type
|
|
16647
16649
|
user {
|
|
16648
16650
|
id
|
|
16649
16651
|
}
|
|
@@ -16673,6 +16675,7 @@ export const QueryPersonas = gql `
|
|
|
16673
16675
|
id
|
|
16674
16676
|
}
|
|
16675
16677
|
state
|
|
16678
|
+
type
|
|
16676
16679
|
identifier
|
|
16677
16680
|
platform
|
|
16678
16681
|
displayName
|
|
@@ -16693,6 +16696,7 @@ export const UpdatePersona = gql `
|
|
|
16693
16696
|
id
|
|
16694
16697
|
name
|
|
16695
16698
|
state
|
|
16699
|
+
type
|
|
16696
16700
|
identifier
|
|
16697
16701
|
platform
|
|
16698
16702
|
displayName
|
|
@@ -18989,6 +18993,7 @@ export const GetUser = gql `
|
|
|
18989
18993
|
id
|
|
18990
18994
|
name
|
|
18991
18995
|
state
|
|
18996
|
+
type
|
|
18992
18997
|
identifier
|
|
18993
18998
|
platform
|
|
18994
18999
|
displayName
|
|
@@ -19117,6 +19122,7 @@ export const GetUserByIdentifier = gql `
|
|
|
19117
19122
|
id
|
|
19118
19123
|
name
|
|
19119
19124
|
state
|
|
19125
|
+
type
|
|
19120
19126
|
identifier
|
|
19121
19127
|
platform
|
|
19122
19128
|
displayName
|
|
@@ -19246,6 +19252,7 @@ export const QueryUsers = gql `
|
|
|
19246
19252
|
id
|
|
19247
19253
|
name
|
|
19248
19254
|
state
|
|
19255
|
+
type
|
|
19249
19256
|
identifier
|
|
19250
19257
|
platform
|
|
19251
19258
|
displayName
|
|
@@ -19156,7 +19156,7 @@ export type PersonUpdateInput = {
|
|
|
19156
19156
|
/** The person URI. */
|
|
19157
19157
|
uri?: InputMaybe<Scalars['URL']['input']>;
|
|
19158
19158
|
};
|
|
19159
|
-
/** Represents a
|
|
19159
|
+
/** Represents a persona for user or agent personalization. */
|
|
19160
19160
|
export type Persona = {
|
|
19161
19161
|
__typename?: 'Persona';
|
|
19162
19162
|
/** The creation date of the persona. */
|
|
@@ -19187,6 +19187,8 @@ export type Persona = {
|
|
|
19187
19187
|
state: EntityState;
|
|
19188
19188
|
/** The IANA timezone of the persona. */
|
|
19189
19189
|
timezone?: Maybe<Scalars['String']['output']>;
|
|
19190
|
+
/** The type of the persona. */
|
|
19191
|
+
type?: Maybe<PersonaTypes>;
|
|
19190
19192
|
/** The user that created the entity. */
|
|
19191
19193
|
user?: Maybe<EntityReference>;
|
|
19192
19194
|
};
|
|
@@ -19220,6 +19222,8 @@ export type PersonaFilter = {
|
|
|
19220
19222
|
search?: InputMaybe<Scalars['String']['input']>;
|
|
19221
19223
|
/** Filter persona(s) by their states. */
|
|
19222
19224
|
states?: InputMaybe<Array<EntityState>>;
|
|
19225
|
+
/** Filter by persona type. */
|
|
19226
|
+
types?: InputMaybe<Array<PersonaTypes>>;
|
|
19223
19227
|
};
|
|
19224
19228
|
/** Represents a persona. */
|
|
19225
19229
|
export type PersonaInput = {
|
|
@@ -19237,6 +19241,8 @@ export type PersonaInput = {
|
|
|
19237
19241
|
role?: InputMaybe<Scalars['String']['input']>;
|
|
19238
19242
|
/** The IANA timezone of the persona. */
|
|
19239
19243
|
timezone?: InputMaybe<Scalars['String']['input']>;
|
|
19244
|
+
/** The type of the persona. Defaults to User. */
|
|
19245
|
+
type?: InputMaybe<PersonaTypes>;
|
|
19240
19246
|
};
|
|
19241
19247
|
/** Represents persona query results. */
|
|
19242
19248
|
export type PersonaResults = {
|
|
@@ -19244,6 +19250,13 @@ export type PersonaResults = {
|
|
|
19244
19250
|
/** The list of persona query results. */
|
|
19245
19251
|
results?: Maybe<Array<Persona>>;
|
|
19246
19252
|
};
|
|
19253
|
+
/** Persona type */
|
|
19254
|
+
export declare enum PersonaTypes {
|
|
19255
|
+
/** Agent persona */
|
|
19256
|
+
Agent = "AGENT",
|
|
19257
|
+
/** User persona */
|
|
19258
|
+
User = "USER"
|
|
19259
|
+
}
|
|
19247
19260
|
/** Represents a persona. */
|
|
19248
19261
|
export type PersonaUpdateInput = {
|
|
19249
19262
|
/** The display name of the persona. */
|
|
@@ -19262,6 +19275,8 @@ export type PersonaUpdateInput = {
|
|
|
19262
19275
|
role?: InputMaybe<Scalars['String']['input']>;
|
|
19263
19276
|
/** The IANA timezone of the persona. */
|
|
19264
19277
|
timezone?: InputMaybe<Scalars['String']['input']>;
|
|
19278
|
+
/** The type of the persona. */
|
|
19279
|
+
type?: InputMaybe<PersonaTypes>;
|
|
19265
19280
|
};
|
|
19266
19281
|
/** Represents a place. */
|
|
19267
19282
|
export type Place = {
|
|
@@ -44898,6 +44913,7 @@ export type CreatePersonaMutation = {
|
|
|
44898
44913
|
id: string;
|
|
44899
44914
|
name: string;
|
|
44900
44915
|
state: EntityState;
|
|
44916
|
+
type?: PersonaTypes | null;
|
|
44901
44917
|
identifier?: string | null;
|
|
44902
44918
|
platform?: string | null;
|
|
44903
44919
|
displayName?: string | null;
|
|
@@ -44954,6 +44970,7 @@ export type GetPersonaQuery = {
|
|
|
44954
44970
|
creationDate: any;
|
|
44955
44971
|
modifiedDate?: any | null;
|
|
44956
44972
|
state: EntityState;
|
|
44973
|
+
type?: PersonaTypes | null;
|
|
44957
44974
|
identifier?: string | null;
|
|
44958
44975
|
platform?: string | null;
|
|
44959
44976
|
displayName?: string | null;
|
|
@@ -44991,6 +45008,7 @@ export type QueryPersonasQuery = {
|
|
|
44991
45008
|
modifiedDate?: any | null;
|
|
44992
45009
|
relevance?: number | null;
|
|
44993
45010
|
state: EntityState;
|
|
45011
|
+
type?: PersonaTypes | null;
|
|
44994
45012
|
identifier?: string | null;
|
|
44995
45013
|
platform?: string | null;
|
|
44996
45014
|
displayName?: string | null;
|
|
@@ -45019,6 +45037,7 @@ export type UpdatePersonaMutation = {
|
|
|
45019
45037
|
id: string;
|
|
45020
45038
|
name: string;
|
|
45021
45039
|
state: EntityState;
|
|
45040
|
+
type?: PersonaTypes | null;
|
|
45022
45041
|
identifier?: string | null;
|
|
45023
45042
|
platform?: string | null;
|
|
45024
45043
|
displayName?: string | null;
|
|
@@ -47762,6 +47781,7 @@ export type GetUserQuery = {
|
|
|
47762
47781
|
id: string;
|
|
47763
47782
|
name: string;
|
|
47764
47783
|
state: EntityState;
|
|
47784
|
+
type?: PersonaTypes | null;
|
|
47765
47785
|
identifier?: string | null;
|
|
47766
47786
|
platform?: string | null;
|
|
47767
47787
|
displayName?: string | null;
|
|
@@ -47915,6 +47935,7 @@ export type GetUserByIdentifierQuery = {
|
|
|
47915
47935
|
id: string;
|
|
47916
47936
|
name: string;
|
|
47917
47937
|
state: EntityState;
|
|
47938
|
+
type?: PersonaTypes | null;
|
|
47918
47939
|
identifier?: string | null;
|
|
47919
47940
|
platform?: string | null;
|
|
47920
47941
|
displayName?: string | null;
|
|
@@ -48071,6 +48092,7 @@ export type QueryUsersQuery = {
|
|
|
48071
48092
|
id: string;
|
|
48072
48093
|
name: string;
|
|
48073
48094
|
state: EntityState;
|
|
48095
|
+
type?: PersonaTypes | null;
|
|
48074
48096
|
identifier?: string | null;
|
|
48075
48097
|
platform?: string | null;
|
|
48076
48098
|
displayName?: string | null;
|
|
@@ -2858,6 +2858,14 @@ export var PersonFacetTypes;
|
|
|
2858
2858
|
/** Creation Date */
|
|
2859
2859
|
PersonFacetTypes["CreationDate"] = "CREATION_DATE";
|
|
2860
2860
|
})(PersonFacetTypes || (PersonFacetTypes = {}));
|
|
2861
|
+
/** Persona type */
|
|
2862
|
+
export var PersonaTypes;
|
|
2863
|
+
(function (PersonaTypes) {
|
|
2864
|
+
/** Agent persona */
|
|
2865
|
+
PersonaTypes["Agent"] = "AGENT";
|
|
2866
|
+
/** User persona */
|
|
2867
|
+
PersonaTypes["User"] = "USER";
|
|
2868
|
+
})(PersonaTypes || (PersonaTypes = {}));
|
|
2861
2869
|
/** Place facet types */
|
|
2862
2870
|
export var PlaceFacetTypes;
|
|
2863
2871
|
(function (PlaceFacetTypes) {
|
package/dist/model-mapping.d.ts
CHANGED
|
@@ -22,3 +22,9 @@ export declare function getServiceType(specification: any): string | undefined;
|
|
|
22
22
|
* @returns The model enum value
|
|
23
23
|
*/
|
|
24
24
|
export declare function getModelEnum(specification: any): string | undefined;
|
|
25
|
+
/**
|
|
26
|
+
* Check whether an OpenAI specification should use the Responses API path.
|
|
27
|
+
* Eligible models are GPT-5.4 and newer.
|
|
28
|
+
*/
|
|
29
|
+
export declare function isOpenAIResponsesEligibleModel(specification: any): boolean;
|
|
30
|
+
export declare const shouldUseOpenAIResponsesModel: typeof isOpenAIResponsesEligibleModel;
|
package/dist/model-mapping.js
CHANGED
|
@@ -66,6 +66,14 @@ const OPENAI_MODEL_MAP = {
|
|
|
66
66
|
[Types.OpenAiModels.O4Mini_200K]: "o4-mini",
|
|
67
67
|
[Types.OpenAiModels.O4Mini_200K_20250416]: "o4-mini-2025-04-16",
|
|
68
68
|
};
|
|
69
|
+
const OPENAI_RESPONSES_MODEL_ENUMS = new Set([
|
|
70
|
+
Types.OpenAiModels.Gpt54_1024K,
|
|
71
|
+
Types.OpenAiModels.Gpt54_1024K_20260305,
|
|
72
|
+
Types.OpenAiModels.Gpt54Mini_400K,
|
|
73
|
+
Types.OpenAiModels.Gpt54Mini_400K_20260317,
|
|
74
|
+
Types.OpenAiModels.Gpt54Nano_400K,
|
|
75
|
+
Types.OpenAiModels.Gpt54Nano_400K_20260317,
|
|
76
|
+
]);
|
|
69
77
|
// Anthropic model mappings
|
|
70
78
|
const ANTHROPIC_MODEL_MAP = {
|
|
71
79
|
// Claude 3 models
|
|
@@ -342,3 +350,31 @@ export function getModelEnum(specification) {
|
|
|
342
350
|
return undefined;
|
|
343
351
|
}
|
|
344
352
|
}
|
|
353
|
+
/**
|
|
354
|
+
* Check whether an OpenAI specification should use the Responses API path.
|
|
355
|
+
* Eligible models are GPT-5.4 and newer.
|
|
356
|
+
*/
|
|
357
|
+
export function isOpenAIResponsesEligibleModel(specification) {
|
|
358
|
+
if (specification?.serviceType !== Types.ModelServiceTypes.OpenAi) {
|
|
359
|
+
return false;
|
|
360
|
+
}
|
|
361
|
+
const modelEnum = getModelEnum(specification);
|
|
362
|
+
if (modelEnum && OPENAI_RESPONSES_MODEL_ENUMS.has(modelEnum)) {
|
|
363
|
+
return true;
|
|
364
|
+
}
|
|
365
|
+
const modelName = getModelName(specification);
|
|
366
|
+
if (!modelName) {
|
|
367
|
+
return false;
|
|
368
|
+
}
|
|
369
|
+
const match = modelName.match(/^gpt-(\d+)(?:\.(\d+))?(?:-[a-z0-9]+)?(?:-\d{4}-\d{2}-\d{2})?$/);
|
|
370
|
+
if (!match) {
|
|
371
|
+
return false;
|
|
372
|
+
}
|
|
373
|
+
const major = Number(match[1]);
|
|
374
|
+
const minor = match[2] ? Number(match[2]) : 0;
|
|
375
|
+
if (!Number.isFinite(major) || !Number.isFinite(minor)) {
|
|
376
|
+
return false;
|
|
377
|
+
}
|
|
378
|
+
return major > 5 || (major === 5 && minor >= 4);
|
|
379
|
+
}
|
|
380
|
+
export const shouldUseOpenAIResponsesModel = isOpenAIResponsesEligibleModel;
|
|
@@ -21,6 +21,42 @@ export interface OpenAIMessage {
|
|
|
21
21
|
}>;
|
|
22
22
|
tool_call_id?: string;
|
|
23
23
|
}
|
|
24
|
+
export interface OpenAIResponsesTextContentPart {
|
|
25
|
+
type: "input_text";
|
|
26
|
+
text: string;
|
|
27
|
+
}
|
|
28
|
+
export interface OpenAIResponsesImageContentPart {
|
|
29
|
+
type: "input_image";
|
|
30
|
+
image_url: string;
|
|
31
|
+
detail: "low" | "high" | "auto";
|
|
32
|
+
}
|
|
33
|
+
export type OpenAIResponsesContentPart = OpenAIResponsesTextContentPart | OpenAIResponsesImageContentPart;
|
|
34
|
+
export interface OpenAIResponsesMessageItem {
|
|
35
|
+
type: "message";
|
|
36
|
+
role: "user" | "assistant";
|
|
37
|
+
content: string | OpenAIResponsesContentPart[];
|
|
38
|
+
}
|
|
39
|
+
export interface OpenAIResponsesFunctionCallItem {
|
|
40
|
+
type: "function_call";
|
|
41
|
+
call_id: string;
|
|
42
|
+
name: string;
|
|
43
|
+
arguments: string;
|
|
44
|
+
id?: string;
|
|
45
|
+
}
|
|
46
|
+
export interface OpenAIResponsesFunctionCallOutputItem {
|
|
47
|
+
type: "function_call_output";
|
|
48
|
+
call_id: string;
|
|
49
|
+
output: string;
|
|
50
|
+
id?: string;
|
|
51
|
+
}
|
|
52
|
+
export type OpenAIResponsesInputItem = OpenAIResponsesMessageItem | OpenAIResponsesFunctionCallItem | OpenAIResponsesFunctionCallOutputItem | Record<string, unknown>;
|
|
53
|
+
export interface OpenAIResponsesToolDefinition {
|
|
54
|
+
type: "function";
|
|
55
|
+
name: string;
|
|
56
|
+
description?: string;
|
|
57
|
+
parameters: Record<string, unknown>;
|
|
58
|
+
strict: false;
|
|
59
|
+
}
|
|
24
60
|
/**
|
|
25
61
|
* Anthropic message format
|
|
26
62
|
*/
|
|
@@ -74,6 +110,15 @@ export interface GoogleMessage {
|
|
|
74
110
|
* Format GraphQL conversation messages for OpenAI SDK
|
|
75
111
|
*/
|
|
76
112
|
export declare function formatMessagesForOpenAI(messages: ConversationMessage[]): OpenAIMessage[];
|
|
113
|
+
export declare function extractInstructionsForOpenAIResponses(messages: ConversationMessage[]): string | undefined;
|
|
114
|
+
export declare function formatMessagesForOpenAIResponsesInitialRound(messages: ConversationMessage[]): OpenAIResponsesInputItem[];
|
|
115
|
+
export declare function buildResponsesFunctionCallOutputItems(toolMessages: ConversationMessage[]): OpenAIResponsesFunctionCallOutputItem[];
|
|
116
|
+
export declare const buildOpenAIResponsesFunctionCallOutputItems: typeof buildResponsesFunctionCallOutputItems;
|
|
117
|
+
export declare function formatToolsForOpenAIResponses(tools: Array<{
|
|
118
|
+
name: string;
|
|
119
|
+
description?: string | null;
|
|
120
|
+
schema?: string | null;
|
|
121
|
+
}> | undefined): OpenAIResponsesToolDefinition[] | undefined;
|
|
77
122
|
/**
|
|
78
123
|
* Format GraphQL conversation messages for Anthropic SDK
|
|
79
124
|
*/
|
|
@@ -190,6 +190,130 @@ export function formatMessagesForOpenAI(messages) {
|
|
|
190
190
|
}
|
|
191
191
|
return formattedMessages;
|
|
192
192
|
}
|
|
193
|
+
export function extractInstructionsForOpenAIResponses(messages) {
|
|
194
|
+
const systemMessages = messages
|
|
195
|
+
.filter((message) => message.role === ConversationRoleTypes.System)
|
|
196
|
+
.map((message) => message.message?.trim() || "")
|
|
197
|
+
.filter((message) => message.length > 0);
|
|
198
|
+
return systemMessages.length > 0
|
|
199
|
+
? systemMessages.join("\n\n")
|
|
200
|
+
: undefined;
|
|
201
|
+
}
|
|
202
|
+
export function formatMessagesForOpenAIResponsesInitialRound(messages) {
|
|
203
|
+
const formattedMessages = [];
|
|
204
|
+
for (const message of messages) {
|
|
205
|
+
if (!message.role || message.role === ConversationRoleTypes.System) {
|
|
206
|
+
continue;
|
|
207
|
+
}
|
|
208
|
+
const trimmedMessage = message.message?.trim() || "";
|
|
209
|
+
const hasToolCalls = !!message.toolCalls?.length;
|
|
210
|
+
if (!trimmedMessage && !hasToolCalls) {
|
|
211
|
+
continue;
|
|
212
|
+
}
|
|
213
|
+
switch (message.role) {
|
|
214
|
+
case ConversationRoleTypes.Assistant: {
|
|
215
|
+
if (trimmedMessage) {
|
|
216
|
+
formattedMessages.push({
|
|
217
|
+
type: "message",
|
|
218
|
+
role: "assistant",
|
|
219
|
+
content: trimmedMessage,
|
|
220
|
+
});
|
|
221
|
+
}
|
|
222
|
+
if (message.toolCalls?.length) {
|
|
223
|
+
for (const toolCall of message.toolCalls) {
|
|
224
|
+
if (!toolCall) {
|
|
225
|
+
continue;
|
|
226
|
+
}
|
|
227
|
+
formattedMessages.push({
|
|
228
|
+
type: "function_call",
|
|
229
|
+
id: toolCall.id,
|
|
230
|
+
call_id: toolCall.id,
|
|
231
|
+
name: toolCall.name,
|
|
232
|
+
arguments: toolCall.arguments,
|
|
233
|
+
});
|
|
234
|
+
}
|
|
235
|
+
}
|
|
236
|
+
break;
|
|
237
|
+
}
|
|
238
|
+
case ConversationRoleTypes.Tool: {
|
|
239
|
+
if (!message.toolCallId) {
|
|
240
|
+
continue;
|
|
241
|
+
}
|
|
242
|
+
formattedMessages.push({
|
|
243
|
+
type: "function_call_output",
|
|
244
|
+
call_id: message.toolCallId,
|
|
245
|
+
output: stripImagesToText(trimmedMessage),
|
|
246
|
+
});
|
|
247
|
+
break;
|
|
248
|
+
}
|
|
249
|
+
default: {
|
|
250
|
+
if (message.mimeType && message.data) {
|
|
251
|
+
const contentParts = [];
|
|
252
|
+
if (trimmedMessage) {
|
|
253
|
+
contentParts.push({
|
|
254
|
+
type: "input_text",
|
|
255
|
+
text: trimmedMessage,
|
|
256
|
+
});
|
|
257
|
+
}
|
|
258
|
+
contentParts.push({
|
|
259
|
+
type: "input_image",
|
|
260
|
+
image_url: `data:${message.mimeType};base64,${message.data}`,
|
|
261
|
+
detail: "auto",
|
|
262
|
+
});
|
|
263
|
+
formattedMessages.push({
|
|
264
|
+
type: "message",
|
|
265
|
+
role: "user",
|
|
266
|
+
content: contentParts,
|
|
267
|
+
});
|
|
268
|
+
}
|
|
269
|
+
else {
|
|
270
|
+
formattedMessages.push({
|
|
271
|
+
type: "message",
|
|
272
|
+
role: "user",
|
|
273
|
+
content: trimmedMessage,
|
|
274
|
+
});
|
|
275
|
+
}
|
|
276
|
+
break;
|
|
277
|
+
}
|
|
278
|
+
}
|
|
279
|
+
}
|
|
280
|
+
return formattedMessages;
|
|
281
|
+
}
|
|
282
|
+
export function buildResponsesFunctionCallOutputItems(toolMessages) {
|
|
283
|
+
return toolMessages
|
|
284
|
+
.filter((message) => message.role === ConversationRoleTypes.Tool &&
|
|
285
|
+
typeof message.toolCallId === "string" &&
|
|
286
|
+
message.toolCallId.length > 0)
|
|
287
|
+
.map((message) => ({
|
|
288
|
+
type: "function_call_output",
|
|
289
|
+
call_id: message.toolCallId,
|
|
290
|
+
output: stripImagesToText(message.message?.trim() || ""),
|
|
291
|
+
}));
|
|
292
|
+
}
|
|
293
|
+
export const buildOpenAIResponsesFunctionCallOutputItems = buildResponsesFunctionCallOutputItems;
|
|
294
|
+
export function formatToolsForOpenAIResponses(tools) {
|
|
295
|
+
if (!tools?.length) {
|
|
296
|
+
return undefined;
|
|
297
|
+
}
|
|
298
|
+
return tools.map((tool) => {
|
|
299
|
+
let parameters = {};
|
|
300
|
+
if (tool.schema) {
|
|
301
|
+
try {
|
|
302
|
+
parameters = JSON.parse(tool.schema);
|
|
303
|
+
}
|
|
304
|
+
catch {
|
|
305
|
+
parameters = {};
|
|
306
|
+
}
|
|
307
|
+
}
|
|
308
|
+
return {
|
|
309
|
+
type: "function",
|
|
310
|
+
name: tool.name,
|
|
311
|
+
description: tool.description || undefined,
|
|
312
|
+
parameters,
|
|
313
|
+
strict: false,
|
|
314
|
+
};
|
|
315
|
+
});
|
|
316
|
+
}
|
|
193
317
|
/**
|
|
194
318
|
* Format GraphQL conversation messages for Anthropic SDK
|
|
195
319
|
*/
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import { ConversationToolCall, Specification } from "../generated/graphql-types.js";
|
|
2
|
+
import { StreamEvent } from "../types/internal.js";
|
|
3
|
+
import type { OpenAIResponsesInputItem, OpenAIResponsesToolDefinition } from "./llm-formatters.js";
|
|
4
|
+
export interface OpenAIResponsesRoundResult {
|
|
5
|
+
message: string;
|
|
6
|
+
toolCalls: ConversationToolCall[];
|
|
7
|
+
usage?: unknown;
|
|
8
|
+
outputItems: OpenAIResponsesInputItem[];
|
|
9
|
+
}
|
|
10
|
+
export declare function streamWithOpenAIResponses(specification: Specification, instructions: string | undefined, input: OpenAIResponsesInputItem[], tools: OpenAIResponsesToolDefinition[] | undefined, openaiClient: any, onEvent: (event: StreamEvent) => void, abortSignal?: AbortSignal, reasoningEffort?: string): Promise<OpenAIResponsesRoundResult>;
|
|
@@ -0,0 +1,221 @@
|
|
|
1
|
+
import { getModelName } from "../model-mapping.js";
|
|
2
|
+
import { ProviderError, extractRequestId, isNetworkError, isRateLimitError, isRetryableServerError, } from "../types/internal.js";
|
|
3
|
+
function toToolCallId(item, outputIndex) {
|
|
4
|
+
return item.call_id || item.id || `tool_${Date.now()}_${outputIndex}`;
|
|
5
|
+
}
|
|
6
|
+
export async function streamWithOpenAIResponses(specification, instructions, input, tools, openaiClient, onEvent, abortSignal, reasoningEffort) {
|
|
7
|
+
let fullMessage = "";
|
|
8
|
+
let tokenCount = 0;
|
|
9
|
+
let usageData;
|
|
10
|
+
let outputItems = [];
|
|
11
|
+
const toolCallsByIndex = new Map();
|
|
12
|
+
const toolCallIdsByItemId = new Map();
|
|
13
|
+
const startedToolCallIds = new Set();
|
|
14
|
+
const parsedToolCallIds = new Set();
|
|
15
|
+
const getOrCreateToolCall = (outputIndex, item) => {
|
|
16
|
+
const existing = toolCallsByIndex.get(outputIndex);
|
|
17
|
+
if (existing) {
|
|
18
|
+
if (item?.name) {
|
|
19
|
+
existing.name = item.name;
|
|
20
|
+
}
|
|
21
|
+
if (typeof item?.arguments === "string" && !existing.arguments) {
|
|
22
|
+
existing.arguments = item.arguments;
|
|
23
|
+
}
|
|
24
|
+
return existing;
|
|
25
|
+
}
|
|
26
|
+
const toolCall = {
|
|
27
|
+
__typename: "ConversationToolCall",
|
|
28
|
+
id: toToolCallId(item || {}, outputIndex),
|
|
29
|
+
name: item?.name || "",
|
|
30
|
+
arguments: item?.arguments || "",
|
|
31
|
+
};
|
|
32
|
+
toolCallsByIndex.set(outputIndex, toolCall);
|
|
33
|
+
if (item?.id) {
|
|
34
|
+
toolCallIdsByItemId.set(item.id, toolCall.id);
|
|
35
|
+
}
|
|
36
|
+
return toolCall;
|
|
37
|
+
};
|
|
38
|
+
const emitToolCallStartIfNeeded = (toolCall) => {
|
|
39
|
+
if (startedToolCallIds.has(toolCall.id)) {
|
|
40
|
+
return;
|
|
41
|
+
}
|
|
42
|
+
startedToolCallIds.add(toolCall.id);
|
|
43
|
+
onEvent({
|
|
44
|
+
type: "tool_call_start",
|
|
45
|
+
toolCall: {
|
|
46
|
+
id: toolCall.id,
|
|
47
|
+
name: toolCall.name,
|
|
48
|
+
},
|
|
49
|
+
});
|
|
50
|
+
};
|
|
51
|
+
const emitToolCallParsedIfNeeded = (toolCall) => {
|
|
52
|
+
if (!toolCall.arguments || parsedToolCallIds.has(toolCall.id)) {
|
|
53
|
+
return;
|
|
54
|
+
}
|
|
55
|
+
parsedToolCallIds.add(toolCall.id);
|
|
56
|
+
onEvent({
|
|
57
|
+
type: "tool_call_parsed",
|
|
58
|
+
toolCall: {
|
|
59
|
+
id: toolCall.id,
|
|
60
|
+
name: toolCall.name,
|
|
61
|
+
arguments: toolCall.arguments,
|
|
62
|
+
},
|
|
63
|
+
});
|
|
64
|
+
};
|
|
65
|
+
try {
|
|
66
|
+
const modelName = getModelName(specification);
|
|
67
|
+
if (!modelName) {
|
|
68
|
+
throw new Error(`No model name found for specification: ${specification.name} (service: ${specification.serviceType})`);
|
|
69
|
+
}
|
|
70
|
+
const request = {
|
|
71
|
+
model: modelName,
|
|
72
|
+
input,
|
|
73
|
+
stream: true,
|
|
74
|
+
store: false,
|
|
75
|
+
include: ["reasoning.encrypted_content"],
|
|
76
|
+
};
|
|
77
|
+
if (instructions?.trim()) {
|
|
78
|
+
request.instructions = instructions.trim();
|
|
79
|
+
}
|
|
80
|
+
if (specification.openAI?.temperature !== undefined) {
|
|
81
|
+
request.temperature = specification.openAI.temperature;
|
|
82
|
+
}
|
|
83
|
+
if (specification.openAI?.completionTokenLimit) {
|
|
84
|
+
request.max_output_tokens = specification.openAI.completionTokenLimit;
|
|
85
|
+
}
|
|
86
|
+
if (tools?.length) {
|
|
87
|
+
request.tools = tools;
|
|
88
|
+
}
|
|
89
|
+
if (reasoningEffort) {
|
|
90
|
+
request.reasoning = { effort: reasoningEffort.toLowerCase() };
|
|
91
|
+
}
|
|
92
|
+
const stream = await openaiClient.responses.create(request, {
|
|
93
|
+
signal: abortSignal,
|
|
94
|
+
});
|
|
95
|
+
for await (const event of stream) {
|
|
96
|
+
switch (event.type) {
|
|
97
|
+
case "response.output_text.delta":
|
|
98
|
+
if (event.delta) {
|
|
99
|
+
fullMessage += event.delta;
|
|
100
|
+
tokenCount++;
|
|
101
|
+
onEvent({ type: "token", token: event.delta });
|
|
102
|
+
}
|
|
103
|
+
break;
|
|
104
|
+
case "response.output_item.added": {
|
|
105
|
+
const item = event.item;
|
|
106
|
+
if (item?.type !== "function_call") {
|
|
107
|
+
break;
|
|
108
|
+
}
|
|
109
|
+
const toolCall = getOrCreateToolCall(event.output_index, item);
|
|
110
|
+
emitToolCallStartIfNeeded(toolCall);
|
|
111
|
+
break;
|
|
112
|
+
}
|
|
113
|
+
case "response.function_call_arguments.delta": {
|
|
114
|
+
const toolCallId = toolCallIdsByItemId.get(event.item_id) ||
|
|
115
|
+
toolCallsByIndex.get(event.output_index)?.id;
|
|
116
|
+
const toolCall = toolCallsByIndex.get(event.output_index);
|
|
117
|
+
if (!toolCall || !toolCallId) {
|
|
118
|
+
break;
|
|
119
|
+
}
|
|
120
|
+
toolCall.arguments += event.delta;
|
|
121
|
+
onEvent({
|
|
122
|
+
type: "tool_call_delta",
|
|
123
|
+
toolCallId,
|
|
124
|
+
argumentDelta: event.delta,
|
|
125
|
+
});
|
|
126
|
+
break;
|
|
127
|
+
}
|
|
128
|
+
case "response.function_call_arguments.done": {
|
|
129
|
+
const toolCall = toolCallsByIndex.get(event.output_index);
|
|
130
|
+
if (!toolCall) {
|
|
131
|
+
break;
|
|
132
|
+
}
|
|
133
|
+
toolCall.arguments = event.arguments;
|
|
134
|
+
emitToolCallParsedIfNeeded(toolCall);
|
|
135
|
+
break;
|
|
136
|
+
}
|
|
137
|
+
case "response.output_item.done": {
|
|
138
|
+
const item = event.item;
|
|
139
|
+
if (item?.type !== "function_call") {
|
|
140
|
+
break;
|
|
141
|
+
}
|
|
142
|
+
const toolCall = getOrCreateToolCall(event.output_index, item);
|
|
143
|
+
if (item.id) {
|
|
144
|
+
toolCallIdsByItemId.set(item.id, toolCall.id);
|
|
145
|
+
}
|
|
146
|
+
emitToolCallStartIfNeeded(toolCall);
|
|
147
|
+
if (typeof item.arguments === "string") {
|
|
148
|
+
toolCall.arguments = item.arguments;
|
|
149
|
+
emitToolCallParsedIfNeeded(toolCall);
|
|
150
|
+
}
|
|
151
|
+
break;
|
|
152
|
+
}
|
|
153
|
+
case "response.completed":
|
|
154
|
+
usageData = event.response?.usage;
|
|
155
|
+
outputItems = (event.response?.output || []);
|
|
156
|
+
if (!fullMessage && typeof event.response?.output_text === "string") {
|
|
157
|
+
fullMessage = event.response.output_text;
|
|
158
|
+
}
|
|
159
|
+
break;
|
|
160
|
+
case "error":
|
|
161
|
+
case "response.error":
|
|
162
|
+
throw new Error(event.error?.message || "OpenAI Responses streaming error");
|
|
163
|
+
case "response.failed":
|
|
164
|
+
throw new Error(event.response?.error?.message || "OpenAI Responses request failed");
|
|
165
|
+
}
|
|
166
|
+
}
|
|
167
|
+
const orderedToolCalls = Array.from(toolCallsByIndex.entries())
|
|
168
|
+
.sort(([left], [right]) => left - right)
|
|
169
|
+
.map(([, toolCall]) => toolCall);
|
|
170
|
+
for (const toolCall of orderedToolCalls) {
|
|
171
|
+
emitToolCallParsedIfNeeded(toolCall);
|
|
172
|
+
}
|
|
173
|
+
onEvent({
|
|
174
|
+
type: "complete",
|
|
175
|
+
tokens: tokenCount,
|
|
176
|
+
});
|
|
177
|
+
return {
|
|
178
|
+
message: fullMessage,
|
|
179
|
+
toolCalls: orderedToolCalls,
|
|
180
|
+
usage: usageData,
|
|
181
|
+
outputItems,
|
|
182
|
+
};
|
|
183
|
+
}
|
|
184
|
+
catch (error) {
|
|
185
|
+
const errorMessage = error.message || error.toString();
|
|
186
|
+
if (isRateLimitError(error)) {
|
|
187
|
+
throw new ProviderError(`OpenAI rate limit exceeded: ${errorMessage}`, {
|
|
188
|
+
provider: "openai",
|
|
189
|
+
statusCode: 429,
|
|
190
|
+
retryable: true,
|
|
191
|
+
requestId: extractRequestId(error),
|
|
192
|
+
cause: error,
|
|
193
|
+
});
|
|
194
|
+
}
|
|
195
|
+
if (isNetworkError(error)) {
|
|
196
|
+
throw new ProviderError(`OpenAI network error: ${errorMessage}`, {
|
|
197
|
+
provider: "openai",
|
|
198
|
+
statusCode: error.status ?? 0,
|
|
199
|
+
retryable: true,
|
|
200
|
+
requestId: extractRequestId(error),
|
|
201
|
+
cause: error,
|
|
202
|
+
});
|
|
203
|
+
}
|
|
204
|
+
if (isRetryableServerError(error)) {
|
|
205
|
+
throw new ProviderError(`OpenAI server error: ${errorMessage}`, {
|
|
206
|
+
provider: "openai",
|
|
207
|
+
statusCode: error.status ?? error.statusCode ?? 500,
|
|
208
|
+
retryable: true,
|
|
209
|
+
requestId: extractRequestId(error),
|
|
210
|
+
cause: error,
|
|
211
|
+
});
|
|
212
|
+
}
|
|
213
|
+
throw new ProviderError(`OpenAI error: ${errorMessage}`, {
|
|
214
|
+
provider: "openai",
|
|
215
|
+
statusCode: error.status ?? error.statusCode ?? 400,
|
|
216
|
+
retryable: false,
|
|
217
|
+
requestId: extractRequestId(error),
|
|
218
|
+
cause: error,
|
|
219
|
+
});
|
|
220
|
+
}
|
|
221
|
+
}
|
package/dist/types/agent.d.ts
CHANGED
|
@@ -66,6 +66,8 @@ export interface StreamAgentOptions {
|
|
|
66
66
|
chunkingStrategy?: "character" | "word" | "sentence";
|
|
67
67
|
smoothingDelay?: number;
|
|
68
68
|
contextStrategy?: ContextStrategy;
|
|
69
|
+
/** Explicitly route eligible OpenAI GPT-5.4+ models through Responses; false forces legacy Chat Completions. */
|
|
70
|
+
useResponsesApi?: boolean;
|
|
69
71
|
/** Harness-injected instructions appended to the formatted conversation (e.g. wind-down, stuck intervention). */
|
|
70
72
|
instructions?: string;
|
|
71
73
|
/** Harness-injected scratchpad text, merged with conversation scratchpad. Placed right before user-prompt. */
|
|
@@ -157,6 +159,7 @@ export interface RunAgentOptions {
|
|
|
157
159
|
smoothingEnabled?: boolean;
|
|
158
160
|
chunkingStrategy?: "character" | "word" | "sentence";
|
|
159
161
|
smoothingDelay?: number;
|
|
162
|
+
useResponsesApi?: boolean;
|
|
160
163
|
/** Skill references to inject into the agent's context window. Retrieved via querySkills, passed by reference. */
|
|
161
164
|
skills?: EntityReferenceInput[];
|
|
162
165
|
}
|
|
@@ -205,6 +208,7 @@ export interface StreamingLoopConfig {
|
|
|
205
208
|
};
|
|
206
209
|
maxRounds: number;
|
|
207
210
|
abortSignal: AbortSignal | undefined;
|
|
211
|
+
useResponsesApi?: boolean;
|
|
208
212
|
correlationId?: string;
|
|
209
213
|
persona?: EntityReferenceInput;
|
|
210
214
|
mimeType?: string;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "graphlit-client",
|
|
3
|
-
"version": "1.0.
|
|
3
|
+
"version": "1.0.20260408001",
|
|
4
4
|
"description": "Graphlit API Client for TypeScript",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "./dist/client.js",
|
|
@@ -85,7 +85,7 @@
|
|
|
85
85
|
"cohere-ai": "^7.20.0",
|
|
86
86
|
"groq-sdk": "^0.25.0",
|
|
87
87
|
"js-tiktoken": "^1.0.16",
|
|
88
|
-
"openai": "^5.
|
|
88
|
+
"openai": "^5.23.2"
|
|
89
89
|
},
|
|
90
90
|
"devDependencies": {
|
|
91
91
|
"@graphql-codegen/typescript-document-nodes": "^5.0.7",
|