Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
26 commits
Select commit Hold shift + click to select a range
8afa0dd
Update langchain to v1 alpha
davidkna-sap Oct 15, 2025
a1fa73c
feat: upgrade zod to v4
davidkna-sap Oct 16, 2025
e237d91
bump to langchain v1 release
davidkna-sap Oct 20, 2025
ca5efdc
fix: use `switch` instead of `instanceof` again
davidkna-sap Oct 21, 2025
c1c74ab
format
davidkna-sap Oct 21, 2025
826f87b
re-add deprecated`additional_kwargs.tool_calls`
davidkna-sap Oct 21, 2025
579e071
chore: bump langchain packages
davidkna-sap Oct 28, 2025
7281b0d
Merge branch 'main' into push-toqoormrvxpy
deekshas8 Oct 30, 2025
9b946a6
pnpm local
deekshas8 Oct 30, 2025
b3968bd
workaround for cjs compilation
deekshas8 Oct 30, 2025
adf70d5
check dep fix
deekshas8 Oct 30, 2025
baa15be
update pnpm lock file
deekshas8 Oct 30, 2025
67e9c44
chore: fix tests by bumping zod to v4
davidkna-sap Oct 30, 2025
da2abe1
Merge branch 'main' into push-toqoormrvxpy
deekshas8 Oct 30, 2025
f07f95b
Merge remote-tracking branch 'origin/main' into push-toqoormrvxpy
davidkna-sap Nov 6, 2025
22a5abb
chore: bump langchain
davidkna-sap Nov 6, 2025
1056808
fix: api updates
davidkna-sap Nov 6, 2025
f535bb1
chore: create changeset
davidkna-sap Nov 6, 2025
4230201
fix: revert sample-code to zod@3 for mcp-support
davidkna-sap Nov 6, 2025
9802b98
chore: add compatibility note for zod v4
davidkna-sap Nov 11, 2025
53913c0
Squashed commit of the following:
davidkna-sap Nov 21, 2025
0bedbc0
chore: re-bump mcp sdk
davidkna-sap Nov 21, 2025
7b59aec
Merge branch 'main' into push-toqoormrvxpy
davidkna-sap Nov 21, 2025
2a6ef39
chore: Migrate from `strict` to `strictObject`
davidkna-sap Nov 21, 2025
8dafc25
chore: allow major langchain updates to `main` again, but group futur…
davidkna-sap Nov 21, 2025
d7ace55
Merge branch 'main' into push-toqoormrvxpy
ZhongpinWang Nov 25, 2025
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 7 additions & 0 deletions .changeset/clean-dolls-tap.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
---
'@sap-ai-sdk/prompt-registry': minor
'@sap-ai-sdk/orchestration': minor
'@sap-ai-sdk/langchain': minor
---

[Compatibility Note] `zod` was upgraded to v4
5 changes: 5 additions & 0 deletions .changeset/crisp-animals-move.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
'@sap-ai-sdk/langchain': minor
---

[feat] Bump langchain to v1
7 changes: 2 additions & 5 deletions .github/dependabot.yml
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I added this to ensure there is a notification for future major updates, and added grouping because the packages are tightly coupled.

Original file line number Diff line number Diff line change
Expand Up @@ -12,14 +12,11 @@ updates:
# We only want to do major node updates on purpose, so don't create dependabot PRs for major versions
- dependency-name: '@types/node'
update-types: ['version-update:semver-major']
# Skip v1-release until compability is handled throughout the project
- dependency-name: 'langchain'
update-types: ['version-update:semver-major']
- dependency-name: '@langchain/*'
update-types: ['version-update:semver-major']
groups:
sap-cloud-sdk:
patterns: ['@sap-cloud-sdk/*']
langchain:
patterns: ['langchain', '@langchain/*']
- package-ecosystem: npm
directory: '/'
target-branch: 'v1-main'
Expand Down
8 changes: 4 additions & 4 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -33,15 +33,12 @@
"check:deps": "pnpm -r -F !./tests/smoke-tests -F !./sample-cap exec depcheck --ignores=\"nock,@jest/globals\" --quiet"
},
"devDependencies": {
"orval": "^7.17.0",
"zod": "^3.25.76",
"@changesets/cli": "^2.29.7",
"@jest/globals": "^30.2.0",
"@sap-ai-sdk/ai-api": "workspace:^",
"@sap-ai-sdk/core": "workspace:^",
"@sap-ai-sdk/foundation-models": "workspace:^",
"@sap-ai-sdk/orchestration": "workspace:^",
"tsx": "^4.20.6",
"@sap-cloud-sdk/connectivity": "^4.1.2",
"@sap-cloud-sdk/eslint-config": "^4.1.2",
"@sap-cloud-sdk/generator-common": "^4.1.2",
Expand All @@ -59,9 +56,12 @@
"jsonwebtoken": "^9.0.2",
"mock-fs": "^5.5.0",
"nock": "^14.0.10",
"orval": "^7.17.0",
"prettier": "^3.6.2",
"ts-jest": "^29.4.5",
"ts-node": "^10.9.2",
"typescript": "^5.9.3"
"tsx": "^4.20.6",
"typescript": "^5.9.3",
"zod": "^4.1.13"
}
}
6 changes: 3 additions & 3 deletions packages/langchain/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -25,19 +25,19 @@
],
"scripts": {
"compile": "tsc",
"compile:cjs": "tsc -p tsconfig.cjs.json",
"compile:cjs": "mv package.json package.json.bak && echo '{ \"type\": \"commonjs\" }' > package.json && tsc -p tsconfig.cjs.json && mv package.json.bak package.json",
"test": "NODE_OPTIONS=--experimental-vm-modules jest",
"lint": "eslint \"**/*.ts\" && prettier . --config ../../.prettierrc --ignore-path ../../.prettierignore -c",
"lint:fix": "eslint \"**/*.ts\" --fix && prettier . --config ../../.prettierrc --ignore-path ../../.prettierignore -w --log-level error"
},
"dependencies": {
"@langchain/core": "^1.0.6",
"@sap-ai-sdk/ai-api": "workspace:^",
"@sap-ai-sdk/core": "workspace:^",
"@sap-ai-sdk/foundation-models": "workspace:^",
"@sap-ai-sdk/orchestration": "workspace:^",
"@sap-cloud-sdk/connectivity": "^4.1.2",
"@sap-cloud-sdk/util": "^4.1.2",
"uuid": "^13.0.0",
"@langchain/core": "0.3.79"
"uuid": "^13.0.0"
}
}
4 changes: 4 additions & 0 deletions packages/langchain/src/openai/__snapshots__/chat.test.ts.snap
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,9 @@ exports[`Chat client streaming supports streaming responses 1`] = `
"tool_call_chunks": [],
"tool_calls": [],
"usage_metadata": {
"input_token_details": {},
"input_tokens": 14,
"output_token_details": {},
"output_tokens": 7,
"total_tokens": 21,
},
Expand Down Expand Up @@ -98,7 +100,9 @@ exports[`Chat client streaming supports streaming responses with tool calls 1`]
},
],
"usage_metadata": {
"input_token_details": {},
"input_tokens": 52,
"output_token_details": {},
"output_tokens": 18,
"total_tokens": 70,
},
Expand Down
5 changes: 5 additions & 0 deletions packages/langchain/src/openai/__snapshots__/util.test.ts.snap
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,11 @@ exports[`Mapping Functions should parse an OpenAI response to a (LangChain) chat
"invalid_tool_calls": [],
"response_metadata": {},
"tool_calls": [],
"usage_metadata": {
"input_tokens": 0,
"output_tokens": 0,
"total_tokens": 0,
},
},
"lc": 1,
"type": "constructor",
Expand Down
2 changes: 1 addition & 1 deletion packages/langchain/src/openai/chat.ts
Original file line number Diff line number Diff line change
Expand Up @@ -207,7 +207,7 @@ export class AzureOpenAiChatClient extends BaseChatModel<AzureOpenAiChatCallOpti
}
},
ls_structured_output_format: {
kwargs: { method: 'jsonSchema' },
kwargs: { method: 'functionCalling' },
schema: asJsonSchema
}
} as Partial<AzureOpenAiChatCallOptions>);
Expand Down
21 changes: 15 additions & 6 deletions packages/langchain/src/openai/util.ts
Original file line number Diff line number Diff line change
Expand Up @@ -127,6 +127,11 @@ export function mapOutputToChatResult(
tool_calls: mapAzureOpenAiToLangChainToolCall(
choice.message.tool_calls
),
usage_metadata: {
input_tokens: choice.message.usage?.prompt_tokens ?? 0,
output_tokens: choice.message.usage?.completion_tokens ?? 0,
total_tokens: choice.message.usage?.total_tokens ?? 0
},
additional_kwargs: {
function_call: choice.message.function_call,
tool_calls: choice.message.tool_calls
Expand Down Expand Up @@ -248,19 +253,23 @@ function mapSystemMessageToAzureOpenAiSystemMessage(
function mapBaseMessageToAzureOpenAiChatMessage(
message: BaseMessage
): AzureOpenAiChatCompletionRequestMessage {
switch (message.getType()) {
switch (message.type) {
case 'ai':
return mapAiMessageToAzureOpenAiAssistantMessage(message);
return mapAiMessageToAzureOpenAiAssistantMessage(message as AIMessage);
case 'human':
return mapHumanMessageToAzureOpenAiUserMessage(message);
return mapHumanMessageToAzureOpenAiUserMessage(message as HumanMessage);
case 'system':
return mapSystemMessageToAzureOpenAiSystemMessage(message);
return mapSystemMessageToAzureOpenAiSystemMessage(
message as SystemMessage
);
case 'function':
return mapFunctionMessageToAzureOpenAiFunctionMessage(message);
return mapFunctionMessageToAzureOpenAiFunctionMessage(
message as FunctionMessage
);
case 'tool':
return mapToolMessageToAzureOpenAiToolMessage(message as ToolMessage);
default:
throw new Error(`Unsupported message type: ${message.getType()}`);
throw new Error(`Unsupported message type: ${message.type}`);
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,11 @@ exports[`orchestration service client resilience returns successful response whe
"tool_calls": undefined,
},
"tool_calls": [],
"usage_metadata": {
"input_tokens": 9,
"output_tokens": 10,
"total_tokens": 19,
},
},
"lc": 1,
"type": "constructor",
Expand Down Expand Up @@ -62,6 +67,11 @@ exports[`orchestration service client resilience returns successful response whe
"tool_calls": undefined,
},
"tool_calls": [],
"usage_metadata": {
"input_tokens": 9,
"output_tokens": 10,
"total_tokens": 19,
},
},
"lc": 1,
"type": "constructor",
Expand Down Expand Up @@ -157,7 +167,9 @@ Overall, the SAP Cloud SDK is an essential tool for developers looking to build
"tool_call_chunks": [],
"tool_calls": [],
"usage_metadata": {
"input_token_details": {},
"input_tokens": 17,
"output_token_details": {},
"output_tokens": 271,
"total_tokens": 288,
},
Expand Down
2 changes: 1 addition & 1 deletion packages/langchain/src/orchestration/client.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -210,7 +210,7 @@ describe('orchestration service client', () => {
);
const client = new OrchestrationClient(config, { maxRetries: 0 });
await expect(client.stream('Hello!', { timeout: 1000 })).rejects.toThrow(
'AbortError'
'Aborted'
);
});
});
Expand Down
19 changes: 13 additions & 6 deletions packages/langchain/src/orchestration/util.ts
Original file line number Diff line number Diff line change
Expand Up @@ -108,17 +108,19 @@ export function isTemplateRef(
*/
// TODO: Add mapping of refusal property, once LangChain base class supports it natively.
function mapBaseMessageToChatMessage(message: BaseMessage): ChatMessage {
switch (message.getType()) {
switch (message.type) {
case 'ai':
return mapAiMessageToOrchestrationAssistantMessage(message);
return mapAiMessageToOrchestrationAssistantMessage(message as AIMessage);
case 'human':
return mapHumanMessageToChatMessage(message);
return mapHumanMessageToChatMessage(message as HumanMessage);
case 'system':
return mapSystemMessageToOrchestrationSystemMessage(message);
return mapSystemMessageToOrchestrationSystemMessage(
message as SystemMessage
);
case 'tool':
return mapToolMessageToOrchestrationToolMessage(message as ToolMessage);
default:
throw new Error(`Unsupported message type: ${message.getType()}`);
throw new Error(`Unsupported message type: ${message.type}`);
}
}

Expand Down Expand Up @@ -280,7 +282,12 @@ export function mapOutputToChatResult(
content: choice.message.content ?? '',
tool_calls: mapOrchestrationToLangChainToolCall(
choice.message.tool_calls
)
),
usage_metadata: {
input_tokens: usage?.prompt_tokens ?? 0,
output_tokens: usage?.completion_tokens ?? 0,
total_tokens: usage?.total_tokens ?? 0
}
}),
additional_kwargs: {
tool_calls: choice.message.tool_calls,
Expand Down
2 changes: 1 addition & 1 deletion packages/langchain/tsconfig.cjs.json
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
{
"extends": "./tsconfig.json",
"compilerOptions": {
"module": "CommonJS",
"module": "nodenext",
"outDir": "./dist-cjs"
}
}
5 changes: 2 additions & 3 deletions packages/orchestration/src/orchestration-client.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -597,13 +597,12 @@ describe('orchestration service client', () => {
).toThrowErrorMatchingInlineSnapshot(`
"Prompt Template YAML does not conform to the defined type. Validation errors: [
{
"code": "invalid_type",
"expected": "object",
"received": "undefined",
"code": "invalid_type",
"path": [
"spec"
],
"message": "Required"
"message": "Invalid input: expected object, received undefined"
}
]"
`);
Expand Down
2 changes: 1 addition & 1 deletion packages/prompt-registry/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,6 @@
},
"dependencies": {
"@sap-ai-sdk/core": "workspace:^",
"zod": "^3.25.76"
"zod": "^4.1.12"
}
}
22 changes: 11 additions & 11 deletions packages/prompt-registry/src/zod/prompt-registry.zod.ts
Original file line number Diff line number Diff line change
Expand Up @@ -190,7 +190,7 @@ export const registryControllerPromptControllerCreateUpdatePromptTemplateBody =
export const registryControllerPromptControllerCreateUpdatePromptTemplateResponse =
zod.object({
message: zod.string(),
id: zod.string().uuid(),
id: zod.uuid(),
scenario: zod.string(),
name: zod.string(),
version: zod.string()
Expand Down Expand Up @@ -234,7 +234,7 @@ export const registryControllerPromptControllerListPromptTemplatesResponse =
count: zod.number(),
resources: zod.array(
zod.object({
id: zod.string().uuid().optional(),
id: zod.uuid().optional(),
name: zod.string().optional(),
version: zod.string().optional(),
scenario: zod.string().optional(),
Expand Down Expand Up @@ -416,7 +416,7 @@ export const registryControllerPromptControllerListPromptTemplateHistoryResponse
count: zod.number(),
resources: zod.array(
zod.object({
id: zod.string().uuid().optional(),
id: zod.uuid().optional(),
name: zod.string().optional(),
version: zod.string().optional(),
scenario: zod.string().optional(),
Expand Down Expand Up @@ -575,7 +575,7 @@ export const registryControllerPromptControllerListPromptTemplateHistoryResponse
*/
export const registryControllerPromptControllerGetPromptTemplateByUuidParams =
zod.object({
promptTemplateId: zod.string().uuid()
promptTemplateId: zod.uuid()
});

export const registryControllerPromptControllerGetPromptTemplateByUuidResponseSpecTemplateItemContentItemImageUrlDetailDefault =
Expand All @@ -593,7 +593,7 @@ export const registryControllerPromptControllerGetPromptTemplateByUuidResponseSp

export const registryControllerPromptControllerGetPromptTemplateByUuidResponse =
zod.object({
id: zod.string().uuid().optional(),
id: zod.uuid().optional(),
name: zod.string().optional(),
version: zod.string().optional(),
scenario: zod.string().optional(),
Expand Down Expand Up @@ -748,7 +748,7 @@ export const registryControllerPromptControllerGetPromptTemplateByUuidResponse =
*/
export const registryControllerPromptControllerDeletePromptTemplateParams =
zod.object({
promptTemplateId: zod.string().uuid()
promptTemplateId: zod.uuid()
});

export const registryControllerPromptControllerDeletePromptTemplateResponse =
Expand All @@ -767,7 +767,7 @@ export const registryControllerPromptControllerImportPromptTemplateBody =
export const registryControllerPromptControllerImportPromptTemplateResponse =
zod.object({
message: zod.string(),
id: zod.string().uuid(),
id: zod.uuid(),
scenario: zod.string(),
name: zod.string(),
version: zod.string()
Expand All @@ -778,15 +778,15 @@ export const registryControllerPromptControllerImportPromptTemplateResponse =
*/
export const registryControllerPromptControllerExportPromptTemplateParams =
zod.object({
promptTemplateId: zod.string().uuid()
promptTemplateId: zod.uuid()
});

/**
* Parse prompt template by ID.
*/
export const registryControllerPromptControllerParsePromptTemplateByIdParams =
zod.object({
promptTemplateId: zod.string().uuid()
promptTemplateId: zod.uuid()
});

export const registryControllerPromptControllerParsePromptTemplateByIdQueryMetadataDefault = false;
Expand Down Expand Up @@ -852,7 +852,7 @@ export const registryControllerPromptControllerParsePromptTemplateByIdResponse =
.optional(),
resource: zod
.object({
id: zod.string().uuid().optional(),
id: zod.uuid().optional(),
name: zod.string().optional(),
version: zod.string().optional(),
scenario: zod.string().optional(),
Expand Down Expand Up @@ -1079,7 +1079,7 @@ export const registryControllerPromptControllerParsePromptTemplateByNameVersionR
.optional(),
resource: zod
.object({
id: zod.string().uuid().optional(),
id: zod.uuid().optional(),
name: zod.string().optional(),
version: zod.string().optional(),
scenario: zod.string().optional(),
Expand Down
Loading
Loading