@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.
package/dist/index.js ADDED
@@ -0,0 +1,52 @@
1
+ /*
2
+ * Copyright 2026, Salesforce, Inc. All rights reserved.
3
+ * See LICENSE.txt for license terms.
4
+ */
5
+ // W-23560954: GovCloud `chat/generations` fallback exports.
6
+ export { buildChatGenerationsLanguageModel } from './chat-generations-language-model.js';
7
+ export { ChatGenerationsResolver, CHAT_GENERATIONS_PROVIDER_HINT } from './chat-generations-resolver.js';
8
+ import { buildChatGenerationsLanguageModel } from './chat-generations-language-model.js';
9
+ import { ChatGenerationsResolver, CHAT_GENERATIONS_PROVIDER_HINT, } from './chat-generations-resolver.js';
10
+ /**
11
+ * Convenience factory for constructing the GovCloud `chat/generations` fallback wiring.
12
+ * Returns a `{ connectivityResolver, languageModelBuilders }` object ready to spread into
13
+ * `createAgentManager` and `MastraHarnessFactory` constructors (W-23560954).
14
+ *
15
+ * @remarks
16
+ * This fallback routes all model traffic through the legacy GovCloud `chat/generations`
17
+ * wire shape. The consumer MUST set `AgentConfig.modelId` to a GovCloud-provisioned GPT
18
+ * model (e.g., `sfdc_ai__DefaultGPT4_8`) — the SDK default (Claude Sonnet 4.6) will not
19
+ * resolve in GovCloud. The resolver decorator flips the delegate's `baseUrl` and
20
+ * `providerHint` onto the GovCloud path, and the injected language-model builder speaks
21
+ * the Salesforce-proprietary `chat/generations` wire contract.
22
+ *
23
+ * **This package is temporary** and will be deleted once the Responses API is onboarded
24
+ * in GovCloud (expected within a few weeks).
25
+ *
26
+ * @param options - Configuration for the resolver decorator (delegate + GovCloud base URL +
27
+ * optional extra headers + optional enabled gate).
28
+ * @returns A `ChatGenerationsFallback` bag carrying both the resolver and builder map,
29
+ * typed for direct assignability to the manager + factory.
30
+ *
31
+ * @example
32
+ * ```ts
33
+ * const { connectivityResolver, languageModelBuilders } = createChatGenerationsFallback({
34
+ * delegate: myExistingResolver,
35
+ * baseUrl: 'https://dev.api.gov.salesforce.com/ai/gpt/v1',
36
+ * extraHeaders: { 'x-salesforce-region': 'us-gov-east-1' }, // VERIFY: region header requirement
37
+ * });
38
+ * const factory = new MastraHarnessFactory({ languageModelBuilders });
39
+ * const manager = await createAgentManager(storageRoot, factory, { connectivityResolver });
40
+ * // Agent MUST bind a GovCloud-provisioned GPT model:
41
+ * const agent = await manager.createAgent(projectRoot, { modelId: 'sfdc_ai__DefaultGPT4_8', ... });
42
+ * ```
43
+ */
44
+ export function createChatGenerationsFallback(options) {
45
+ return {
46
+ connectivityResolver: new ChatGenerationsResolver(options),
47
+ languageModelBuilders: {
48
+ [CHAT_GENERATIONS_PROVIDER_HINT]: buildChatGenerationsLanguageModel,
49
+ },
50
+ };
51
+ }
52
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1,5 @@
1
+ import type { ChatResponseData, ChatStreamChunk, RawChatChunk } from './chat-response.js';
2
+ export interface ResponseProcessor {
3
+ processRawChatStream(rawStream: AsyncGenerator<RawChatChunk>): AsyncGenerator<ChatStreamChunk>;
4
+ processRawChatResponse(raw: RawChatChunk): ChatResponseData;
5
+ }
@@ -0,0 +1,6 @@
1
+ /*
2
+ * Copyright 2026, Salesforce, Inc. All rights reserved.
3
+ * See LICENSE.txt for license terms.
4
+ */
5
+ export {};
6
+ //# sourceMappingURL=response-processor.js.map
@@ -0,0 +1,53 @@
1
+ /**
2
+ * Filter all events that aren't generations or errors
3
+ *
4
+ * See: https://git.soma.salesforce.com/pages/tech-enablement/einstein/docs/gateway/streaming/#how-it-works
5
+ */
6
+ export declare function shouldSkipEvent(event: string): boolean;
7
+ /**
8
+ * Check if this is an error event from the gateway.
9
+ *
10
+ * See: https://git.soma.salesforce.com/pages/tech-enablement/einstein/docs/gateway/streaming/#error-chunks
11
+ */
12
+ export declare function isErrorEvent(event: string | undefined): boolean;
13
+ /**
14
+ * Creates an SSE event handler for parsing LLMG API responses.
15
+ * This handler is shared between the streaming client and test utilities.
16
+ *
17
+ * @param queue - Array to push parsed chunks into
18
+ * @param onDone - Optional callback when [DONE] sentinel is received
19
+ * @param onParseError - Optional callback invoked when a chunk fails to parse. The callback
20
+ * receives the (truncated) raw chunk and a short reason string so consumers can surface a
21
+ * log or metric without the parser depending on a logging bus.
22
+ * @returns Event handler function for eventsource-parser
23
+ */
24
+ export declare function createSSEEventHandler<T>(queue: T[], onDone?: () => void, onParseError?: (ctx: {
25
+ chunk: string;
26
+ reason: string;
27
+ }) => void): (event: {
28
+ event?: string;
29
+ data?: string;
30
+ }) => void;
31
+ /**
32
+ * Parses raw SSE event strings into array of parsed objects.
33
+ * Used for testing - synchronous version that processes complete SSE string.
34
+ *
35
+ * This function uses the same parsing logic as RealLLMGatewayClient.requestStream()
36
+ * to ensure tests validate the production parser behavior.
37
+ *
38
+ * @param sseString - Raw SSE events (e.g., "event: generation\ndata: {...}\n\n")
39
+ * @returns Array of parsed objects (RawChatChunk or error objects)
40
+ *
41
+ * @example
42
+ * ```typescript
43
+ * const chunks = parseSSEString<RawChatChunk>(`
44
+ * event: generation
45
+ * data: {"id":"test","generation_details":{"generations":[{"role":"assistant","content":"Hello"}],"parameters":{"provider":"openai"}}}
46
+ *
47
+ * event: generation
48
+ * data: [DONE]
49
+ *
50
+ * `);
51
+ * ```
52
+ */
53
+ export declare function parseSSEString<T>(sseString: string): T[];
@@ -0,0 +1,116 @@
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/sse-parser.ts (W-23560954).
6
+ import { createParser } from 'eventsource-parser';
7
+ /**
8
+ * Filter all events that aren't generations or errors
9
+ *
10
+ * See: https://git.soma.salesforce.com/pages/tech-enablement/einstein/docs/gateway/streaming/#how-it-works
11
+ */
12
+ export function shouldSkipEvent(event) {
13
+ return !['generation', 'error'].includes(event);
14
+ }
15
+ /**
16
+ * Check if this is an error event from the gateway.
17
+ *
18
+ * See: https://git.soma.salesforce.com/pages/tech-enablement/einstein/docs/gateway/streaming/#error-chunks
19
+ */
20
+ export function isErrorEvent(event) {
21
+ return event === 'error';
22
+ }
23
+ /**
24
+ * Creates an SSE event handler for parsing LLMG API responses.
25
+ * This handler is shared between the streaming client and test utilities.
26
+ *
27
+ * @param queue - Array to push parsed chunks into
28
+ * @param onDone - Optional callback when [DONE] sentinel is received
29
+ * @param onParseError - Optional callback invoked when a chunk fails to parse. The callback
30
+ * receives the (truncated) raw chunk and a short reason string so consumers can surface a
31
+ * log or metric without the parser depending on a logging bus.
32
+ * @returns Event handler function for eventsource-parser
33
+ */
34
+ export function createSSEEventHandler(queue, onDone, onParseError) {
35
+ let done = false;
36
+ return ({ event, data }) => {
37
+ // Stop processing events after DONE sentinel
38
+ if (done)
39
+ return;
40
+ if (!data || !event)
41
+ return;
42
+ if (shouldSkipEvent(event))
43
+ return;
44
+ // Handle error events from the gateway - add to queue wrapped in error object
45
+ if (isErrorEvent(event)) {
46
+ try {
47
+ const errorData = JSON.parse(data);
48
+ queue.push({
49
+ error: errorData,
50
+ });
51
+ }
52
+ catch {
53
+ // Malformed error data - create a parse error event
54
+ queue.push({
55
+ error: {
56
+ messageCode: 'E99999',
57
+ errorCode: 'PARSE_ERROR',
58
+ message: `Failed to parse error event: ${data}`,
59
+ },
60
+ });
61
+ onParseError?.({ chunk: truncateChunk(data), reason: 'malformed error event JSON' });
62
+ }
63
+ return;
64
+ }
65
+ const trimmed = data.trim();
66
+ // Stop parsing when DONE sentinel is received
67
+ if (trimmed === '[DONE]' || trimmed === 'DONE') {
68
+ done = true;
69
+ onDone?.();
70
+ return;
71
+ }
72
+ try {
73
+ const parsed = JSON.parse(data);
74
+ queue.push(parsed);
75
+ }
76
+ catch {
77
+ onParseError?.({ chunk: truncateChunk(data), reason: 'unparseable generation chunk' });
78
+ }
79
+ };
80
+ }
81
+ function truncateChunk(chunk, max = 200) {
82
+ return chunk.length > max ? `${chunk.slice(0, max)}…` : chunk;
83
+ }
84
+ /**
85
+ * Parses raw SSE event strings into array of parsed objects.
86
+ * Used for testing - synchronous version that processes complete SSE string.
87
+ *
88
+ * This function uses the same parsing logic as RealLLMGatewayClient.requestStream()
89
+ * to ensure tests validate the production parser behavior.
90
+ *
91
+ * @param sseString - Raw SSE events (e.g., "event: generation\ndata: {...}\n\n")
92
+ * @returns Array of parsed objects (RawChatChunk or error objects)
93
+ *
94
+ * @example
95
+ * ```typescript
96
+ * const chunks = parseSSEString<RawChatChunk>(`
97
+ * event: generation
98
+ * data: {"id":"test","generation_details":{"generations":[{"role":"assistant","content":"Hello"}],"parameters":{"provider":"openai"}}}
99
+ *
100
+ * event: generation
101
+ * data: [DONE]
102
+ *
103
+ * `);
104
+ * ```
105
+ */
106
+ export function parseSSEString(sseString) {
107
+ const queue = [];
108
+ // Create the parser using the shared event handler
109
+ const parser = createParser({
110
+ onEvent: createSSEEventHandler(queue),
111
+ });
112
+ // Feed the entire SSE string to the parser
113
+ parser.feed(sseString);
114
+ return queue;
115
+ }
116
+ //# sourceMappingURL=sse-parser.js.map
@@ -0,0 +1 @@
1
+ export declare function normalizeToolArguments(args: string | null | undefined): string;
@@ -0,0 +1,10 @@
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/models/tool-arg-normalize.ts (W-23560954).
6
+ // Normalize empty/null/undefined tool-call args to "{}" so consumers can JSON.parse.
7
+ export function normalizeToolArguments(args) {
8
+ return args ? args : '{}';
9
+ }
10
+ //# sourceMappingURL=tool-arg-normalize.js.map
package/package.json ADDED
@@ -0,0 +1,67 @@
1
+ {
2
+ "name": "@salesforce/sfdx-agent-chat-generations",
3
+ "version": "0.0.1",
4
+ "description": "Temporary GovCloud chat/generations fallback for @salesforce/sfdx-agent-harness-mastra",
5
+ "type": "module",
6
+ "main": "dist/index.js",
7
+ "types": "dist/index.d.ts",
8
+ "exports": {
9
+ ".": "./dist/index.js"
10
+ },
11
+ "scripts": {
12
+ "build": "tsc --build",
13
+ "clean": "tsc --build --clean",
14
+ "clean:all": "npm run clean && rimraf node_modules",
15
+ "postclean": "rimraf coverage && rimraf dist",
16
+ "format": "prettier --write .",
17
+ "lint": "eslint .",
18
+ "lint:fix": "eslint . --fix",
19
+ "showcoverage": "open ./coverage/lcov-report/index.html",
20
+ "test": "tsc --build ./test/tsconfig.json && vitest run --coverage"
21
+ },
22
+ "license": "SEE LICENSE IN LICENSE.txt",
23
+ "files": [
24
+ "dist",
25
+ "!dist/**/*.map",
26
+ "!dist/test",
27
+ "CHANGELOG.md",
28
+ "LICENSE.txt"
29
+ ],
30
+ "dependencies": {
31
+ "@ai-sdk/provider": "^3.0.10",
32
+ "eventsource-parser": "^3.0.0"
33
+ },
34
+ "peerDependencies": {
35
+ "@salesforce/sfdx-agent-sdk": "0.37.0",
36
+ "@salesforce/sfdx-agent-harness-mastra": "0.36.0"
37
+ },
38
+ "devDependencies": {
39
+ "@eslint/js": "^10.0.1",
40
+ "@salesforce/sfdx-agent-sdk": "0.37.0",
41
+ "@salesforce/sfdx-agent-harness-mastra": "0.36.0",
42
+ "@types/node": "^22.20.0",
43
+ "@vitest/coverage-istanbul": "^4.1.10",
44
+ "@vitest/eslint-plugin": "^1.6.22",
45
+ "eslint": "^10.7.0",
46
+ "eslint-config-prettier": "^10.1.8",
47
+ "eslint-import-resolver-typescript": "^4.4.5",
48
+ "eslint-plugin-import": "^2.32.0",
49
+ "eslint-plugin-n": "^18.2.1",
50
+ "globals": "^17.6.0",
51
+ "lint-staged": "^17.0.7",
52
+ "prettier": "^3.9.4",
53
+ "rimraf": "^6.1.3",
54
+ "tsx": "^4.23.0",
55
+ "typescript": "^6.0.3",
56
+ "typescript-eslint": "^8.63.0",
57
+ "vitest": "^4.1.8"
58
+ },
59
+ "engines": {
60
+ "node": ">=22.22.0"
61
+ },
62
+ "lint-staged": {
63
+ "*.{js,jsx,ts,tsx,json,md}": [
64
+ "prettier --write"
65
+ ]
66
+ }
67
+ }