@salesforce/sfdx-agent-chat-generations 0.0.1

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.
@@ -0,0 +1,78 @@
1
+ /*
2
+ * Copyright 2026, Salesforce, Inc. All rights reserved.
3
+ * See LICENSE.txt for license terms.
4
+ */
5
+ /**
6
+ * Provider hint for the GovCloud `chat/generations` wire shape. Used to dispatch
7
+ * to the injected builder in the Mastra harness factory.
8
+ */
9
+ export const CHAT_GENERATIONS_PROVIDER_HINT = 'salesforce-chat-generations';
10
+ /**
11
+ * Decorator over a consumer's real `AgentConnectivityResolver` that flips an existing
12
+ * connectivity bag onto the GovCloud `chat/generations` path. Reuses the delegate's
13
+ * `getHeaders()` verbatim (JWT rotation + tenant/feature headers for free), merging
14
+ * any GovCloud-required extras on top.
15
+ *
16
+ * **Why a decorator, not a subclass:** `DefaultAgentConnectivityResolver` and
17
+ * `buildSalesforceGatewayHeaders` are not on the SDK's public surface — subclassing
18
+ * would force new public exports. This decorator wraps the consumer's existing
19
+ * resolver (e.g., AFV's `VibesAgentConnectivityResolver`) and reuses its `getHeaders()`
20
+ * without needing SDK-internal header helpers.
21
+ *
22
+ * **Gating is explicit, not auto-detected.** Do not sniff `instanceUrl` for `.gov` —
23
+ * domain research showed that's unreliable (org instanceUrl differs from gateway host,
24
+ * and civilian gov is `*.salesforce.com`, indistinguishable from commercial). The
25
+ * consumer knows they're deploying to GovCloud; they wire this decorator at construction.
26
+ *
27
+ * **Consumer must set a GPT `modelId`.** The SDK default (Claude Sonnet 4.6) will not
28
+ * resolve in GovCloud. AFV must bind `AgentConfig.modelId` to a GovCloud-provisioned
29
+ * `sfdc_ai__DefaultGPT*` model id.
30
+ *
31
+ * @example
32
+ * ```ts
33
+ * const resolver = new ChatGenerationsResolver({
34
+ * delegate: myExistingResolver,
35
+ * baseUrl: 'https://dev.api.gov.salesforce.com/ai/gpt/v1',
36
+ * extraHeaders: { 'x-salesforce-region': 'us-gov-east-1' },
37
+ * });
38
+ * const manager = await createAgentManager(storageRoot, factory, { connectivityResolver: resolver });
39
+ * ```
40
+ */
41
+ export class ChatGenerationsResolver {
42
+ opts;
43
+ constructor(opts) {
44
+ this.opts = opts;
45
+ }
46
+ async resolve(projectRoot, config) {
47
+ // Delegate to the wrapped resolver to get the base connectivity bag
48
+ const inner = await this.opts.delegate.resolve(projectRoot, config);
49
+ // Kill-switch: when disabled, pass through the delegate's result unchanged
50
+ const enabled = this.opts.enabled ?? process.env['SF_GOVCLOUD_LEGACY_FALLBACK'] === '1';
51
+ if (!enabled) {
52
+ return inner;
53
+ }
54
+ const innerInfo = inner.modelConnectivityInfo;
55
+ // Rewrite the connectivity bag: flip `baseUrl` and `providerHint` onto the
56
+ // GovCloud `chat/generations` path, but leave `model` and `nativeModelId`
57
+ // untouched (the delegate already resolved the consumer's GPT `modelId` to
58
+ // the `sfdc_ai__DefaultGPT*` wire id the builder will send in the body).
59
+ return {
60
+ ...inner,
61
+ modelConnectivityInfo: {
62
+ ...innerInfo,
63
+ baseUrl: this.opts.baseUrl,
64
+ providerHint: CHAT_GENERATIONS_PROVIDER_HINT,
65
+ // Reuse the delegate's getHeaders VERBATIM. This closure re-invokes
66
+ // `innerInfo.getHeaders()` on every call (per-call freshness contract),
67
+ // then merges GovCloud-required extras on top (extras win on conflict).
68
+ // Do NOT snapshot the header map at resolve time — JWT rotation and
69
+ // feature-id swaps require re-evaluation per request.
70
+ getHeaders: async () => {
71
+ const delegateHeaders = await innerInfo.getHeaders();
72
+ return { ...delegateHeaders, ...(this.opts.extraHeaders ?? {}) };
73
+ },
74
+ },
75
+ };
76
+ }
77
+ }
78
+ //# sourceMappingURL=chat-generations-resolver.js.map
@@ -0,0 +1,117 @@
1
+ export type ChatRequest = {
2
+ messages: ChatMessageIn[];
3
+ generation_settings: GenerationSettings;
4
+ reasoning_settings?: ReasoningSettings;
5
+ tools?: ChatCompletionFunctionTool[];
6
+ tool_config?: ToolConfig;
7
+ };
8
+ type ReasoningSettings = {
9
+ /**
10
+ * Indicates whether to include thinking/reasoning content in the response. Defaults to `false`.
11
+ */
12
+ return_reasoning?: boolean;
13
+ /**
14
+ * Parameter that guides the model on the budget to use for reasoning tokens to generate before creating a response to the prompt.
15
+ *
16
+ * Only supported in OpenAI and Gemini models.
17
+ * See: https://git.soma.salesforce.com/pages/tech-enablement/einstein/docs/gateway/reasoning/
18
+ */
19
+ reasoning_budget?: ReasoningBudget;
20
+ };
21
+ type ReasoningBudget = {
22
+ effort: 'minimal' | 'low' | 'medium' | 'high';
23
+ } | {
24
+ tokens: number;
25
+ };
26
+ export type ChatMessageIn = {
27
+ role: 'user' | 'assistant' | 'system' | 'tool';
28
+ content: string;
29
+ files?: ChatMessageFile[];
30
+ tool_call_id?: string;
31
+ tool_call_name?: string;
32
+ tool_invocations?: ToolInvocationIn[];
33
+ };
34
+ /**
35
+ * MIME types accepted on the multimodal path.
36
+ * Any other value triggers a `LLMGClientError('MODEL_DOES_NOT_SUPPORT_FORMAT')` error.
37
+ */
38
+ export declare const MimeType: {
39
+ readonly Png: "image/png";
40
+ readonly Jpeg: "image/jpeg";
41
+ readonly Pdf: "application/pdf";
42
+ };
43
+ export type MimeType = (typeof MimeType)[keyof typeof MimeType];
44
+ /**
45
+ * One image or PDF attached to a `ChatMessageIn`.
46
+ * v1 only supports `dataType: 'base64'`
47
+ * Allowed `mimeType` values are PNG, JPEG, and PDF — see {@link MimeType}.
48
+ */
49
+ export type ChatMessageFile = {
50
+ /** Caller-supplied unique identifier (UUID recommended). */
51
+ fileId: string;
52
+ /** MIME type. Only PNG, JPEG, and PDF are accepted by the SDK in v1. */
53
+ mimeType: MimeType;
54
+ /** Transport. Only `'base64'` is supported in v1. */
55
+ dataType: 'base64';
56
+ /** Base64-encoded file bytes (no `data:` URI prefix). */
57
+ data: string;
58
+ /** Optional human-readable filename. Surfaces to providers that display it (e.g. Data Cloud). */
59
+ fileName?: string;
60
+ };
61
+ export type ToolInvocationIn = {
62
+ id: string;
63
+ function: {
64
+ name: string;
65
+ arguments: string;
66
+ };
67
+ };
68
+ export type GenerationSettings = {
69
+ max_tokens?: number;
70
+ temperature?: number;
71
+ /**
72
+ * An array of stop sequences to be used. The generated text is cut at the end of the earliest occurrence of a stop sequence.
73
+ */
74
+ stop_sequences?: string[];
75
+ /**
76
+ * The frequency penalty to be used. Min value is 0.0; max value is 1.0. Can reduce the repetitiveness of generated tokens. The higher the value, the stronger a penalty is applied to previously present tokens, proportional to how many times they have already appeared in the prompt or prior generation.
77
+ */
78
+ frequency_penalty?: number;
79
+ /**
80
+ * The presence penalty to be used. Min value is 0.0; max value is 1.0. Can reduce the repetitiveness of generated tokens. Behaves similarly to frequency_penalty, except that this penalty is applied equally to all tokens that have already appeared, regardless of their exact frequencies.
81
+ */
82
+ presence_penalty?: number;
83
+ /**
84
+ * Dictionary of any other parameters that are required by the specified provider. Values are passed as is to the provider so that the request can include parameters that are unique to a provider.
85
+ */
86
+ parameters?: object;
87
+ };
88
+ export type ChatCompletionFunctionTool = {
89
+ type?: 'function';
90
+ function: {
91
+ name: string;
92
+ description?: string;
93
+ parameters?: {
94
+ type: 'object';
95
+ properties?: Record<string, LlmgPropertyDefinition>;
96
+ required?: string[];
97
+ };
98
+ strict?: boolean;
99
+ };
100
+ };
101
+ export type LlmgPropertyDefinition = ToolPropertyDefinition & {
102
+ enum?: string[];
103
+ items?: LlmgPropertyDefinition;
104
+ };
105
+ type ToolPropertyDefinition = {
106
+ type: string;
107
+ description?: string;
108
+ properties?: Record<string, ToolPropertyDefinition>;
109
+ };
110
+ export type ToolConfig = {
111
+ mode: 'auto' | 'none' | 'tool' | 'any';
112
+ allowed_tools?: {
113
+ type: 'function';
114
+ name: string;
115
+ }[];
116
+ };
117
+ export {};
@@ -0,0 +1,14 @@
1
+ /*
2
+ * Copyright 2026, Salesforce, Inc. All rights reserved.
3
+ * See LICENSE.txt for license terms.
4
+ */
5
+ /**
6
+ * MIME types accepted on the multimodal path.
7
+ * Any other value triggers a `LLMGClientError('MODEL_DOES_NOT_SUPPORT_FORMAT')` error.
8
+ */
9
+ export const MimeType = {
10
+ Png: 'image/png',
11
+ Jpeg: 'image/jpeg',
12
+ Pdf: 'application/pdf',
13
+ };
14
+ //# sourceMappingURL=chat-request.js.map
@@ -0,0 +1,119 @@
1
+ type Response<T> = {
2
+ status: number;
3
+ data: T;
4
+ };
5
+ export type ChatResponse = Response<ChatResponseData>;
6
+ /**
7
+ * Union of all known finish reasons across supported models.
8
+ * GPT-5 uses: 'stop', 'length', 'tool_calls'
9
+ */
10
+ export type FinishReason = 'stop' | 'length' | 'tool_calls';
11
+ export type ChatResponseData = {
12
+ generatedText?: string;
13
+ finishReason?: FinishReason;
14
+ error?: LLMGError;
15
+ toolInvocations?: ToolInvocation[];
16
+ usage?: TokenUsage;
17
+ };
18
+ export type ChatStreamResponse = Response<AsyncGenerator<ChatStreamChunk>>;
19
+ export type TokenUsage = {
20
+ inputTokens: number;
21
+ outputTokens: number;
22
+ totalTokens: number;
23
+ reasoningTokens?: number;
24
+ cacheReadTokens?: number;
25
+ cacheWriteTokens?: number;
26
+ };
27
+ export type ChatStreamChunk = {
28
+ generatedText: string;
29
+ done: boolean;
30
+ finishReason?: FinishReason;
31
+ error?: LLMGError;
32
+ toolInvocations?: ToolInvocation[];
33
+ usage?: TokenUsage;
34
+ };
35
+ export type ToolInvocation = {
36
+ id: string;
37
+ function: {
38
+ name: string;
39
+ arguments: string;
40
+ };
41
+ };
42
+ export type RawToolInvocation = {
43
+ id: string;
44
+ function: {
45
+ name: string;
46
+ arguments: string;
47
+ };
48
+ thought_signature?: string | null;
49
+ };
50
+ export type LLMGErrorParameter = {
51
+ name: string;
52
+ value: unknown;
53
+ };
54
+ export type LLMGExtendedErrorDetails = {
55
+ providerStatusCode?: number;
56
+ [key: string]: unknown;
57
+ };
58
+ export type LLMGError = {
59
+ /**
60
+ * See: https://git.soma.salesforce.com/pages/tech-enablement/einstein/docs/gateway/error-codes/
61
+ */
62
+ messageCode: string;
63
+ errorCode: string;
64
+ message: string;
65
+ extendedErrorDetails?: LLMGExtendedErrorDetails[];
66
+ parameters?: LLMGErrorParameter[];
67
+ };
68
+ type GPT5TokenUsageDetails = {
69
+ prompt_tokens: number;
70
+ completion_tokens: number;
71
+ total_tokens: number;
72
+ completion_tokens_details?: {
73
+ reasoning_tokens?: number;
74
+ };
75
+ };
76
+ type GPT5Generation = {
77
+ id?: string;
78
+ role: 'user' | 'assistant' | 'system' | 'tool';
79
+ content: string;
80
+ thought_signature?: string | null;
81
+ contents?: Array<{
82
+ type: 'thinking_summary' | 'redacted_thinking' | 'text';
83
+ content: string;
84
+ }> | null;
85
+ timestamp?: number;
86
+ parameters?: {
87
+ finish_reason?: 'stop' | 'length' | 'tool_calls' | null;
88
+ refusal?: string | null;
89
+ index?: number;
90
+ };
91
+ tool_invocations?: RawToolInvocation[] | null;
92
+ };
93
+ type GPT5GenerationParameters = {
94
+ provider: 'openai';
95
+ created?: number;
96
+ model?: string;
97
+ usage?: GPT5TokenUsageDetails;
98
+ };
99
+ type GPT5RawChatChunk = {
100
+ id: string;
101
+ generation_details: {
102
+ generations: GPT5Generation[];
103
+ parameters: GPT5GenerationParameters;
104
+ };
105
+ other_details?: unknown | null;
106
+ };
107
+ export type LLMGErrorEvent = {
108
+ error: LLMGError;
109
+ };
110
+ export type RawChatChunk = GPT5RawChatChunk | LLMGErrorEvent;
111
+ /**
112
+ * Type guard to check if a raw chunk is an error event.
113
+ */
114
+ export declare function isLLMGErrorEvent(chunk: RawChatChunk): chunk is LLMGErrorEvent;
115
+ /**
116
+ * Type guard to check if a raw response is from GPT-5.
117
+ */
118
+ export declare function isGPT5Response(response: RawChatChunk): response is GPT5RawChatChunk;
119
+ export {};
@@ -0,0 +1,21 @@
1
+ /*
2
+ * Copyright 2026, Salesforce, Inc. All rights reserved.
3
+ * See LICENSE.txt for license terms.
4
+ */
5
+ // =====================================================================================================================
6
+ // ==== TYPE GUARDS
7
+ // =====================================================================================================================
8
+ /**
9
+ * Type guard to check if a raw chunk is an error event.
10
+ */
11
+ export function isLLMGErrorEvent(chunk) {
12
+ return 'error' in chunk && typeof chunk.error === 'object' && 'errorCode' in chunk.error;
13
+ }
14
+ /**
15
+ * Type guard to check if a raw response is from GPT-5.
16
+ */
17
+ export function isGPT5Response(response) {
18
+ const params = 'generation_details' in response ? response.generation_details?.parameters : undefined;
19
+ return params !== undefined && 'provider' in params && params.provider === 'openai';
20
+ }
21
+ //# sourceMappingURL=chat-response.js.map
@@ -0,0 +1,7 @@
1
+ export declare class LLMGClientError extends Error {
2
+ code: string;
3
+ httpStatus?: number;
4
+ constructor(message: string, code: string, options?: ErrorOptions & {
5
+ httpStatus?: number;
6
+ });
7
+ }
package/dist/errors.js ADDED
@@ -0,0 +1,18 @@
1
+ /*
2
+ * Copyright 2026, Salesforce, Inc. All rights reserved.
3
+ * See LICENSE.txt for license terms.
4
+ */
5
+ // Ported from 3f694898^:packages/llm-gateway-sdk/src/errors.ts (W-23560954).
6
+ // Minimal subset: the LLMGError shape lives in chat-response.ts; this file is currently
7
+ // a placeholder for future error-handling needs.
8
+ export class LLMGClientError extends Error {
9
+ code;
10
+ httpStatus;
11
+ constructor(message, code, options) {
12
+ super(message, options);
13
+ this.name = 'LLMGatewayClientError';
14
+ this.code = code;
15
+ this.httpStatus = options?.httpStatus;
16
+ }
17
+ }
18
+ //# sourceMappingURL=errors.js.map
@@ -0,0 +1,6 @@
1
+ import type { ChatResponseData, ChatStreamChunk, RawChatChunk } from './chat-response.js';
2
+ import type { ResponseProcessor } from './response-processor.js';
3
+ export declare class GPT5ResponseProcessor implements ResponseProcessor {
4
+ processRawChatStream(rawStream: AsyncGenerator<RawChatChunk>): AsyncGenerator<ChatStreamChunk>;
5
+ processRawChatResponse(raw: RawChatChunk): ChatResponseData;
6
+ }
@@ -0,0 +1,189 @@
1
+ /*
2
+ * Copyright 2026, Salesforce, Inc. All rights reserved.
3
+ * See LICENSE.txt for license terms.
4
+ */
5
+ import { isLLMGErrorEvent, isGPT5Response } from './chat-response.js';
6
+ import { normalizeToolArguments } from './tool-arg-normalize.js';
7
+ // Detect if this is the start of a new tool call (has id and name)
8
+ function isToolCallStart(inv) {
9
+ return !!(inv.id && inv.function?.name);
10
+ }
11
+ // Convert accumulated tool call to normalized ToolInvocation
12
+ function toToolInvocation(pending) {
13
+ return {
14
+ id: pending.id,
15
+ function: {
16
+ name: pending.name,
17
+ arguments: normalizeToolArguments(pending.argumentsBuffer),
18
+ },
19
+ };
20
+ }
21
+ export class GPT5ResponseProcessor {
22
+ async *processRawChatStream(rawStream) {
23
+ let pendingToolCall = null;
24
+ let capturedUsage;
25
+ let bufferedFinalChunk = null;
26
+ for await (const raw of rawStream) {
27
+ // Check for error events first
28
+ if (isLLMGErrorEvent(raw)) {
29
+ yield {
30
+ generatedText: '',
31
+ done: true,
32
+ error: raw.error,
33
+ };
34
+ return; // Error events are terminal - stop processing
35
+ }
36
+ // Type guard ensures we have GPT5RawChatChunk from here on
37
+ if (!isGPT5Response(raw)) {
38
+ // This should never happen in practice, but we need to handle it for type safety
39
+ continue;
40
+ }
41
+ const generation = raw.generation_details?.generations?.[0];
42
+ // Check for usage chunk (empty generations with usage in parameters)
43
+ // Usage info comes in the final chunk.
44
+ //
45
+ // See: https://platform.openai.com/docs/api-reference/completions/object#completions-object-usage
46
+ if (!generation) {
47
+ const usage = raw.generation_details?.parameters.usage;
48
+ if (usage) {
49
+ const inputTokens = usage.prompt_tokens ?? 0;
50
+ const outputTokens = usage.completion_tokens ?? 0;
51
+ const reasoningTokens = usage.completion_tokens_details?.reasoning_tokens;
52
+ capturedUsage = {
53
+ inputTokens,
54
+ outputTokens,
55
+ totalTokens: usage.total_tokens,
56
+ ...(reasoningTokens ? { reasoningTokens } : {}),
57
+ };
58
+ }
59
+ continue;
60
+ }
61
+ const finishReason = generation.parameters?.finish_reason;
62
+ const isDone = !!finishReason;
63
+ const content = generation.content || '';
64
+ const toolInvocation = generation.tool_invocations?.[0];
65
+ // NOTE (cristian):
66
+ // I haven't found any LLMG/OpenAI doc about this being a possible case,
67
+ // we are handling it just to be safe.
68
+ //
69
+ // If chunk has BOTH content and tool invocations, yield text first
70
+ if (content && toolInvocation) {
71
+ yield {
72
+ generatedText: content,
73
+ done: false,
74
+ };
75
+ // Continue to process tool invocation below
76
+ }
77
+ // Check for tool invocations
78
+ if (toolInvocation) {
79
+ if (isToolCallStart(toolInvocation)) {
80
+ // Flush any pending tool call first
81
+ if (pendingToolCall) {
82
+ yield {
83
+ generatedText: '',
84
+ done: false,
85
+ toolInvocations: [toToolInvocation(pendingToolCall)],
86
+ };
87
+ }
88
+ // Start accumulating new tool call
89
+ pendingToolCall = {
90
+ id: toolInvocation.id,
91
+ name: toolInvocation.function.name,
92
+ argumentsBuffer: toolInvocation.function.arguments || '',
93
+ };
94
+ }
95
+ else if (pendingToolCall) {
96
+ // Continuation - append arguments
97
+ pendingToolCall.argumentsBuffer += toolInvocation.function.arguments || '';
98
+ }
99
+ continue;
100
+ }
101
+ // Handle done signal - may come in a separate chunk without tool_invocations
102
+ // (e.g., finish_reason: "tool_calls" arrives after all tool fragments)
103
+ if (isDone && pendingToolCall) {
104
+ bufferedFinalChunk = {
105
+ generatedText: '',
106
+ done: true,
107
+ finishReason: finishReason ?? undefined,
108
+ toolInvocations: [toToolInvocation(pendingToolCall)],
109
+ };
110
+ pendingToolCall = null;
111
+ continue;
112
+ }
113
+ // Text content - yield immediately for low latency
114
+ // Note: If text content + toolInvocation was present, we already continued above,
115
+ // so this only handles text-only chunks or done signals without tools.
116
+ if (content || isDone) {
117
+ // For text content with done signal, buffer to capture usage later
118
+ if (isDone) {
119
+ bufferedFinalChunk = {
120
+ generatedText: content,
121
+ done: true,
122
+ finishReason: finishReason ?? undefined,
123
+ };
124
+ }
125
+ else if (content) {
126
+ yield {
127
+ generatedText: content,
128
+ done: false,
129
+ };
130
+ }
131
+ }
132
+ }
133
+ // Stream ended - yield buffered final chunk WITHOUT usage, then usage chunk separately
134
+ if (bufferedFinalChunk) {
135
+ // Yield the content chunk first with done=false
136
+ yield {
137
+ ...bufferedFinalChunk,
138
+ done: false, // NOT the final chunk - usage chunk comes next
139
+ };
140
+ }
141
+ else if (pendingToolCall) {
142
+ // Stream ended with pending tool call (no finish_reason received)
143
+ yield {
144
+ generatedText: '',
145
+ done: false,
146
+ toolInvocations: [toToolInvocation(pendingToolCall)],
147
+ };
148
+ }
149
+ // ALWAYS yield a final usage chunk with done=true (even if usage is undefined)
150
+ // This ensures there's always exactly ONE chunk with done=true at the end
151
+ yield {
152
+ generatedText: '',
153
+ done: true, // This is the FINAL chunk
154
+ finishReason: bufferedFinalChunk?.finishReason,
155
+ usage: capturedUsage, // May be undefined if API didn't send usage
156
+ };
157
+ }
158
+ processRawChatResponse(raw) {
159
+ if (isLLMGErrorEvent(raw)) {
160
+ throw new Error(raw.error.message);
161
+ }
162
+ if (!isGPT5Response(raw)) {
163
+ throw new Error('Invalid response type for GPT-5 processor');
164
+ }
165
+ const generation = raw.generation_details?.generations?.[0];
166
+ const generatedText = generation?.content ?? '';
167
+ const finishReason = generation?.parameters?.finish_reason ?? undefined;
168
+ const toolInvocations = (generation?.tool_invocations ?? []).map((inv) => ({
169
+ id: inv.id,
170
+ function: {
171
+ name: inv.function.name,
172
+ arguments: normalizeToolArguments(inv.function.arguments),
173
+ },
174
+ }));
175
+ let usage;
176
+ const rawUsage = raw.generation_details?.parameters.usage;
177
+ if (rawUsage) {
178
+ const reasoningTokens = rawUsage.completion_tokens_details?.reasoning_tokens;
179
+ usage = {
180
+ inputTokens: rawUsage.prompt_tokens ?? 0,
181
+ outputTokens: rawUsage.completion_tokens ?? 0,
182
+ totalTokens: rawUsage.total_tokens,
183
+ ...(reasoningTokens ? { reasoningTokens } : {}),
184
+ };
185
+ }
186
+ return { generatedText, finishReason, toolInvocations, usage };
187
+ }
188
+ }
189
+ //# sourceMappingURL=gpt5-response-processor.js.map
@@ -0,0 +1,91 @@
1
+ export { buildChatGenerationsLanguageModel } from './chat-generations-language-model.js';
2
+ export { ChatGenerationsResolver, CHAT_GENERATIONS_PROVIDER_HINT } from './chat-generations-resolver.js';
3
+ export type { ChatGenerationsResolverOptions } from './chat-generations-resolver.js';
4
+ import type { MastraLanguageModelBuilder } from '@salesforce/sfdx-agent-harness-mastra';
5
+ import { ChatGenerationsResolver, CHAT_GENERATIONS_PROVIDER_HINT, type ChatGenerationsResolverOptions } from './chat-generations-resolver.js';
6
+ /**
7
+ * The return value of {@link createChatGenerationsFallback}, carrying a connectivity
8
+ * resolver decorator and a language-model builder ready to spread into
9
+ * `createAgentManager` and `MastraHarnessFactory`.
10
+ *
11
+ * @remarks
12
+ * Consumers wire the fallback at construction time, either explicitly (construct
13
+ * `ChatGenerationsResolver` and pass `languageModelBuilders` separately) or via the
14
+ * convenience factory (destructure its return and spread both fields). Both forms produce
15
+ * identical runtime wiring.
16
+ *
17
+ * @example Explicit construction
18
+ * ```ts
19
+ * const factory = new MastraHarnessFactory({
20
+ * languageModelBuilders: {
21
+ * [CHAT_GENERATIONS_PROVIDER_HINT]: buildChatGenerationsLanguageModel,
22
+ * },
23
+ * });
24
+ * const resolver = new ChatGenerationsResolver({
25
+ * delegate: myExistingResolver,
26
+ * baseUrl: 'https://dev.api.gov.salesforce.com/ai/gpt/v1',
27
+ * extraHeaders: { 'x-salesforce-region': 'us-gov-east-1' },
28
+ * });
29
+ * const manager = await createAgentManager(storageRoot, factory, { connectivityResolver: resolver });
30
+ * ```
31
+ *
32
+ * @example Convenience factory (preferred)
33
+ * ```ts
34
+ * const { connectivityResolver, languageModelBuilders } = createChatGenerationsFallback({
35
+ * delegate: myExistingResolver,
36
+ * baseUrl: 'https://dev.api.gov.salesforce.com/ai/gpt/v1',
37
+ * extraHeaders: { 'x-salesforce-region': 'us-gov-east-1' },
38
+ * });
39
+ * const factory = new MastraHarnessFactory({ languageModelBuilders });
40
+ * const manager = await createAgentManager(storageRoot, factory, { connectivityResolver });
41
+ * ```
42
+ */
43
+ export type ChatGenerationsFallback = {
44
+ /**
45
+ * The connectivity resolver decorator wrapping the consumer's delegate. Passes to
46
+ * `createAgentManager`'s `options.connectivityResolver` parameter.
47
+ */
48
+ connectivityResolver: ChatGenerationsResolver;
49
+ /**
50
+ * Language-model builder map keyed by `CHAT_GENERATIONS_PROVIDER_HINT`, ready to spread
51
+ * into `MastraHarnessFactory`'s `languageModelBuilders` constructor option. The value is
52
+ * typed explicitly as `MastraLanguageModelBuilder` so TS assignability checks succeed
53
+ * without widening.
54
+ */
55
+ languageModelBuilders: Record<typeof CHAT_GENERATIONS_PROVIDER_HINT, MastraLanguageModelBuilder>;
56
+ };
57
+ /**
58
+ * Convenience factory for constructing the GovCloud `chat/generations` fallback wiring.
59
+ * Returns a `{ connectivityResolver, languageModelBuilders }` object ready to spread into
60
+ * `createAgentManager` and `MastraHarnessFactory` constructors (W-23560954).
61
+ *
62
+ * @remarks
63
+ * This fallback routes all model traffic through the legacy GovCloud `chat/generations`
64
+ * wire shape. The consumer MUST set `AgentConfig.modelId` to a GovCloud-provisioned GPT
65
+ * model (e.g., `sfdc_ai__DefaultGPT4_8`) — the SDK default (Claude Sonnet 4.6) will not
66
+ * resolve in GovCloud. The resolver decorator flips the delegate's `baseUrl` and
67
+ * `providerHint` onto the GovCloud path, and the injected language-model builder speaks
68
+ * the Salesforce-proprietary `chat/generations` wire contract.
69
+ *
70
+ * **This package is temporary** and will be deleted once the Responses API is onboarded
71
+ * in GovCloud (expected within a few weeks).
72
+ *
73
+ * @param options - Configuration for the resolver decorator (delegate + GovCloud base URL +
74
+ * optional extra headers + optional enabled gate).
75
+ * @returns A `ChatGenerationsFallback` bag carrying both the resolver and builder map,
76
+ * typed for direct assignability to the manager + factory.
77
+ *
78
+ * @example
79
+ * ```ts
80
+ * const { connectivityResolver, languageModelBuilders } = createChatGenerationsFallback({
81
+ * delegate: myExistingResolver,
82
+ * baseUrl: 'https://dev.api.gov.salesforce.com/ai/gpt/v1',
83
+ * extraHeaders: { 'x-salesforce-region': 'us-gov-east-1' }, // VERIFY: region header requirement
84
+ * });
85
+ * const factory = new MastraHarnessFactory({ languageModelBuilders });
86
+ * const manager = await createAgentManager(storageRoot, factory, { connectivityResolver });
87
+ * // Agent MUST bind a GovCloud-provisioned GPT model:
88
+ * const agent = await manager.createAgent(projectRoot, { modelId: 'sfdc_ai__DefaultGPT4_8', ... });
89
+ * ```
90
+ */
91
+ export declare function createChatGenerationsFallback(options: ChatGenerationsResolverOptions): ChatGenerationsFallback;