diff --git a/templates/vsc/js/basic-custom-engine-agent/infra/azure.bicep.tpl b/templates/vsc/js/basic-custom-engine-agent/infra/azure.bicep.tpl index 6adb2e7b4a4..41aad4d240f 100644 --- a/templates/vsc/js/basic-custom-engine-agent/infra/azure.bicep.tpl +++ b/templates/vsc/js/basic-custom-engine-agent/infra/azure.bicep.tpl @@ -60,7 +60,7 @@ resource webApp 'Microsoft.Web/sites@2021-02-01' = { } { name: 'WEBSITE_NODE_DEFAULT_VERSION' - value: '~18' // Set NodeJS version to 18.x for your site + value: '~22' // Set NodeJS version to 22.x for your site } { name: 'RUNNING_ON_AZURE' diff --git a/templates/vsc/js/basic-custom-engine-agent/package.json.tpl b/templates/vsc/js/basic-custom-engine-agent/package.json.tpl index fee24ca6133..5d5deecf890 100644 --- a/templates/vsc/js/basic-custom-engine-agent/package.json.tpl +++ b/templates/vsc/js/basic-custom-engine-agent/package.json.tpl @@ -5,9 +5,6 @@ "teamsAppId": null }, "description": "Basic Custome Engine Agent with Microsoft 365 Agents SDK", - "engines": { - "node": "18 || 20 || 22" - }, "author": "Microsoft", "license": "MIT", "main": "./src/index.js", @@ -27,13 +24,12 @@ "dependencies": { "@azure/identity": "^4.8.0", "@azure/openai": "^2.0.0", - "@microsoft/agents-hosting": "^0.2.14", - "express": "^5.0.1", + "@microsoft/agents-hosting-express": "^1.0.0", "openai": "^4.94.0" }, "devDependencies": { "env-cmd": "^10.1.0", - "nodemon": "^3.1.7", + "nodemon": "^3.1.10", "shx": "^0.3.3" } } \ No newline at end of file diff --git a/templates/vsc/js/basic-custom-engine-agent/src/adapter.js b/templates/vsc/js/basic-custom-engine-agent/src/adapter.js deleted file mode 100644 index 9780383b53d..00000000000 --- a/templates/vsc/js/basic-custom-engine-agent/src/adapter.js +++ /dev/null @@ -1,35 +0,0 @@ -const { CloudAdapter, loadAuthConfigFromEnv } = require("@microsoft/agents-hosting"); - -// Create authentication configuration -const authConfig = loadAuthConfigFromEnv(); - -// Create adapter -const adapter = new CloudAdapter(authConfig); - -// Catch-all for errors. -const onTurnErrorHandler = async (context, error) => { - // This check writes out errors to console log .vs. app insights. - // NOTE: In production environment, you should consider logging this to Azure - // application insights. - console.error(`\n [onTurnError] unhandled error: ${error}`); - - // Only send error message for user messages, not for other message types so the agent doesn't spam a channel or chat. - if (context.activity.type === "message") { - // Send a trace activity, which will be displayed in Bot Framework Emulator - await context.sendTraceActivity( - "OnTurnError Trace", - `${error}`, - "https://www.botframework.com/schemas/error", - "TurnError" - ); - - // Send a message to the user - await context.sendActivity("The agent encountered an error or bug."); - await context.sendActivity("To continue to run this agent, please fix the agent source code."); - } -}; - -// Set the onTurnError for the singleton TeamsAdapter. -adapter.onTurnError = onTurnErrorHandler; - -module.exports = adapter; diff --git a/templates/vsc/js/basic-custom-engine-agent/src/agent.js.tpl b/templates/vsc/js/basic-custom-engine-agent/src/agent.js.tpl index 9ddfb8b59a2..2896c0fcd91 100644 --- a/templates/vsc/js/basic-custom-engine-agent/src/agent.js.tpl +++ b/templates/vsc/js/basic-custom-engine-agent/src/agent.js.tpl @@ -25,12 +25,12 @@ const agentApp = new AgentApplication({ storage, }); -agentApp.conversationUpdate("membersAdded", async (context) => { +agentApp.onConversationUpdate("membersAdded", async (context) => { await context.sendActivity(`Hi there! I'm an agent to chat with you.`); }); // Listen for ANY message to be received. MUST BE AFTER ANY OTHER MESSAGE HANDLERS -agentApp.activity(ActivityTypes.Message, async (context) => { +agentApp.onActivity(ActivityTypes.Message, async (context) => { // Echo back users request const result = await client.chat.completions.create({ messages: [ diff --git a/templates/vsc/js/basic-custom-engine-agent/src/index.js b/templates/vsc/js/basic-custom-engine-agent/src/index.js index d65761ec827..ae654c4d5c9 100644 --- a/templates/vsc/js/basic-custom-engine-agent/src/index.js +++ b/templates/vsc/js/basic-custom-engine-agent/src/index.js @@ -1,28 +1,3 @@ -// Import required packages -const { authorizeJWT, loadAuthConfigFromEnv } = require("@microsoft/agents-hosting"); -const express = require("express"); - -// This bot's adapter -const adapter = require("./adapter"); - -// This bot's main dialog. +const { startServer } = require("@microsoft/agents-hosting-express"); const { agentApp } = require("./agent"); - -// Create authentication configuration -const authConfig = loadAuthConfigFromEnv(); - -// Create express application. -const expressApp = express(); -expressApp.use(express.json()); -expressApp.use(authorizeJWT(authConfig)); - -const server = expressApp.listen(process.env.port || process.env.PORT || 3978, () => { - console.log(`\nAgent started, ${expressApp.name} listening to`, server.address()); -}); - -// Listen for incoming requests. -expressApp.post("/api/messages", async (req, res) => { - await adapter.process(req, res, async (context) => { - await agentApp.run(context); - }); -}); +startServer(agentApp); diff --git a/templates/vsc/js/default-bot/teamsBot.js b/templates/vsc/js/default-bot/agent.js similarity index 75% rename from templates/vsc/js/default-bot/teamsBot.js rename to templates/vsc/js/default-bot/agent.js index f8579d65b6f..ff513895a40 100644 --- a/templates/vsc/js/default-bot/teamsBot.js +++ b/templates/vsc/js/default-bot/agent.js @@ -10,33 +10,33 @@ const downloader = new AttachmentDownloader(); // Define storage and application const storage = new MemoryStorage(); -const teamsBot = new AgentApplication({ +const agentApp = new AgentApplication({ storage, fileDownloaders: [downloader], }); // Listen for user to say '/reset' and then delete conversation state -teamsBot.message("/reset", async (context, state) => { +agentApp.onMessage("/reset", async (context, state) => { state.deleteConversationState(); await context.sendActivity("Ok I've deleted the current conversation state."); }); -teamsBot.message("/count", async (context, state) => { +agentApp.onMessage("/count", async (context, state) => { const count = state.conversation.count ?? 0; await context.sendActivity(`The count is ${count}`); }); -teamsBot.message("/diag", async (context, state) => { +agentApp.onMessage("/diag", async (context, state) => { await state.load(context, storage); await context.sendActivity(JSON.stringify(context.activity)); }); -teamsBot.message("/state", async (context, state) => { +agentApp.onMessage("/state", async (context, state) => { await state.load(context, storage); await context.sendActivity(JSON.stringify(state)); }); -teamsBot.message("/runtime", async (context, state) => { +agentApp.onMessage("/runtime", async (context, state) => { const runtime = { nodeversion: process.version, sdkversion: version, @@ -44,14 +44,14 @@ teamsBot.message("/runtime", async (context, state) => { await context.sendActivity(JSON.stringify(runtime)); }); -teamsBot.conversationUpdate("membersAdded", async (context, state) => { +agentApp.onConversationUpdate("membersAdded", async (context, state) => { await context.sendActivity( `Hi there! I'm an echo bot running on Agents SDK version ${version} that will echo what you said to me.` ); }); // Listen for ANY message to be received. MUST BE AFTER ANY OTHER MESSAGE HANDLERS -teamsBot.activity(ActivityTypes.Message, async (context, state) => { +agentApp.onActivity(ActivityTypes.Message, async (context, state) => { // Increment count state let count = state.conversation.count ?? 0; state.conversation.count = ++count; @@ -60,15 +60,15 @@ teamsBot.activity(ActivityTypes.Message, async (context, state) => { await context.sendActivity(`[${count}] you said: ${context.activity.text}`); }); -teamsBot.activity(/^message/, async (context, state) => { +agentApp.onActivity(/^message/, async (context, state) => { await context.sendActivity(`Matched with regex: ${context.activity.type}`); }); -teamsBot.activity( +agentApp.onActivity( async (context) => Promise.resolve(context.activity.type === "message"), async (context, state) => { await context.sendActivity(`Matched function: ${context.activity.type}`); } ); -module.exports.teamsBot = teamsBot; +module.exports.agentApp = agentApp; diff --git a/templates/vsc/js/default-bot/index.js b/templates/vsc/js/default-bot/index.js index a19e873a856..ae654c4d5c9 100644 --- a/templates/vsc/js/default-bot/index.js +++ b/templates/vsc/js/default-bot/index.js @@ -1,56 +1,3 @@ -// index.js is used to setup and configure your bot - -// Import required packages -const express = require("express"); - -// Import required bot services. -// See https://aka.ms/bot-services to learn more about the different parts of a bot. -const { authorizeJWT, CloudAdapter, loadAuthConfigFromEnv } = require("@microsoft/agents-hosting"); -const { teamsBot } = require("./teamsBot"); - -// Create authentication configuration -const authConfig = loadAuthConfigFromEnv(); - -// Create adapter -const adapter = new CloudAdapter(authConfig); - -adapter.onTurnError = async (context, error) => { - // This check writes out errors to console log .vs. app insights. - // NOTE: In production environment, you should consider logging this to Azure - // application insights. See https://aka.ms/bottelemetry for telemetry - // configuration instructions. - console.error(`\n [onTurnError] unhandled error: ${error}`); - - // Only send error message for user messages, not for other message types so the bot doesn't spam a channel or chat. - if (context.activity.type === "message") { - // Send a message to the user - await context.sendActivity(`The bot encountered an unhandled error:\n ${error.message}`); - await context.sendActivity("To continue to run this bot, please fix the bot source code."); - } -}; - -// Create express application. -const expressApp = express(); -expressApp.use(express.json()); -expressApp.use(authorizeJWT(authConfig)); - -const port = process.env.port || process.env.PORT || 3978; -const server = expressApp.listen(port, () => { - console.log( - `Bot Started, listening to port ${port} for appId ${authConfig.clientId} debug ${process.env.DEBUG}` - ); -}); - -// Listen for incoming requests. -expressApp.post("/api/messages", async (req, res) => { - await adapter.process(req, res, async (context) => { - await teamsBot.run(context); - }); -}); - -// Gracefully shutdown HTTP server -["exit", "uncaughtException", "SIGINT", "SIGTERM", "SIGUSR1", "SIGUSR2"].forEach((event) => { - process.on(event, () => { - server.close(); - }); -}); +const { startServer } = require("@microsoft/agents-hosting-express"); +const { agentApp } = require("./agent"); +startServer(agentApp); diff --git a/templates/vsc/js/default-bot/infra/azure.bicep b/templates/vsc/js/default-bot/infra/azure.bicep index 3999e8c3a86..d883f5ce16f 100644 --- a/templates/vsc/js/default-bot/infra/azure.bicep +++ b/templates/vsc/js/default-bot/infra/azure.bicep @@ -45,7 +45,7 @@ resource webApp 'Microsoft.Web/sites@2021-02-01' = { } { name: 'WEBSITE_NODE_DEFAULT_VERSION' - value: '~18' // Set NodeJS version to 18.x for your site + value: '~22' // Set NodeJS version to 22.x for your site } { name: 'RUNNING_ON_AZURE' diff --git a/templates/vsc/js/default-bot/package.json.tpl b/templates/vsc/js/default-bot/package.json.tpl index 6355873d6b3..fa7bb843351 100644 --- a/templates/vsc/js/default-bot/package.json.tpl +++ b/templates/vsc/js/default-bot/package.json.tpl @@ -5,9 +5,6 @@ "teamsAppId": null }, "description": "Microsoft 365 Agents Toolkit echo bot sample", - "engines": { - "node": "18 || 20 || 22" - }, "author": "Microsoft", "license": "MIT", "main": "index.js", @@ -21,11 +18,10 @@ "test": "echo \"Error: no test specified\" && exit 1" }, "dependencies": { - "@microsoft/agents-hosting": "^0.2.14", - "express": "^5.0.1" + "@microsoft/agents-hosting-express": "^1.0.0" }, "devDependencies": { "env-cmd": "^10.1.0", - "nodemon": "^3.1.7" + "nodemon": "^3.1.10" } } diff --git a/templates/vsc/js/weather-agent/infra/azure.bicep.tpl b/templates/vsc/js/weather-agent/infra/azure.bicep.tpl index 6adb2e7b4a4..41aad4d240f 100644 --- a/templates/vsc/js/weather-agent/infra/azure.bicep.tpl +++ b/templates/vsc/js/weather-agent/infra/azure.bicep.tpl @@ -60,7 +60,7 @@ resource webApp 'Microsoft.Web/sites@2021-02-01' = { } { name: 'WEBSITE_NODE_DEFAULT_VERSION' - value: '~18' // Set NodeJS version to 18.x for your site + value: '~22' // Set NodeJS version to 22.x for your site } { name: 'RUNNING_ON_AZURE' diff --git a/templates/vsc/js/weather-agent/package.json.tpl b/templates/vsc/js/weather-agent/package.json.tpl index f22f749bb48..e977f6706a4 100644 --- a/templates/vsc/js/weather-agent/package.json.tpl +++ b/templates/vsc/js/weather-agent/package.json.tpl @@ -5,9 +5,6 @@ "teamsAppId": null }, "description": "Weather Agent with Microsoft 365 Agents SDK and LangChain", - "engines": { - "node": "18 || 20 || 22" - }, "author": "Microsoft", "license": "MIT", "main": "./src/index.js", @@ -28,13 +25,11 @@ "@azure/openai": "^2.0.0", "@langchain/langgraph": "^0.2.66", "@langchain/openai": "^0.5.6", - "@microsoft/agents-hosting": "^0.2.14", - "express": "^5.0.1", - "zod": "3.25.67" + "@microsoft/agents-hosting-express": "^1.0.0" }, "devDependencies": { "env-cmd": "^10.1.0", - "nodemon": "^3.1.7", + "nodemon": "^3.1.10", "shx": "^0.3.3" }, "overrides": { diff --git a/templates/vsc/js/weather-agent/src/agent.js.tpl b/templates/vsc/js/weather-agent/src/agent.js.tpl index 7d98ae322a9..83488fbb986 100644 --- a/templates/vsc/js/weather-agent/src/agent.js.tpl +++ b/templates/vsc/js/weather-agent/src/agent.js.tpl @@ -9,7 +9,7 @@ const { getWeatherTool } = require("./tools/getWeatherTool"); const weatherAgent = new AgentApplicationBuilder().build(); -weatherAgent.conversationUpdate( +weatherAgent.onConversationUpdate( "membersAdded", async (context) => { await context.sendActivity( @@ -55,7 +55,7 @@ Respond in JSON format with the following JSON schema, and do not use markdown i "content": "{The content of the response, may be plain text, or JSON based adaptive card}" }`); -weatherAgent.activity(ActivityTypes.Message, async (context, state) => { +weatherAgent.onActivity(ActivityTypes.Message, async (context, state) => { const llmResponse = await agent.invoke( { messages: [sysMessage, new HumanMessage(context.activity.text)], diff --git a/templates/vsc/js/weather-agent/src/index.js b/templates/vsc/js/weather-agent/src/index.js index 7516fc31c03..ae654c4d5c9 100644 --- a/templates/vsc/js/weather-agent/src/index.js +++ b/templates/vsc/js/weather-agent/src/index.js @@ -1,29 +1,3 @@ -// Import required packages -const { authorizeJWT, CloudAdapter, loadAuthConfigFromEnv } = require("@microsoft/agents-hosting"); -const express = require("express"); - -// This bot's main dialog. -const { weatherAgent } = require("./agent"); - -// Create authentication configuration -const authConfig = loadAuthConfigFromEnv(); -const adapter = new CloudAdapter(authConfig); - -// Create express application. -const server = express(); -server.use(express.json()); -server.use(authorizeJWT(authConfig)); - -// Listen for incoming requests. -server.post("/api/messages", async (req, res) => { - await adapter.process(req, res, async (context) => { - await weatherAgent.run(context); - }); -}); - -const port = process.env.port || process.env.PORT || 3978; -server.listen(port, () => { - console.log( - `\nServer listening to port ${port} for appId ${authConfig.clientId} debug ${process.env.DEBUG}` - ); -}); +const { startServer } = require("@microsoft/agents-hosting-express"); +const { agentApp } = require("./agent"); +startServer(agentApp); diff --git a/templates/vsc/ts/basic-custom-engine-agent/infra/azure.bicep.tpl b/templates/vsc/ts/basic-custom-engine-agent/infra/azure.bicep.tpl index 6adb2e7b4a4..41aad4d240f 100644 --- a/templates/vsc/ts/basic-custom-engine-agent/infra/azure.bicep.tpl +++ b/templates/vsc/ts/basic-custom-engine-agent/infra/azure.bicep.tpl @@ -60,7 +60,7 @@ resource webApp 'Microsoft.Web/sites@2021-02-01' = { } { name: 'WEBSITE_NODE_DEFAULT_VERSION' - value: '~18' // Set NodeJS version to 18.x for your site + value: '~22' // Set NodeJS version to 22.x for your site } { name: 'RUNNING_ON_AZURE' diff --git a/templates/vsc/ts/basic-custom-engine-agent/package.json.tpl b/templates/vsc/ts/basic-custom-engine-agent/package.json.tpl index c12fa9533c1..27cf0f12ebd 100644 --- a/templates/vsc/ts/basic-custom-engine-agent/package.json.tpl +++ b/templates/vsc/ts/basic-custom-engine-agent/package.json.tpl @@ -5,9 +5,6 @@ "teamsAppId": null }, "description": "Basic Custome Engine Agent with Microsoft 365 Agents SDK", - "engines": { - "node": "18 || 20 || 22" - }, "author": "Microsoft", "license": "MIT", "main": "./lib/src/index.js", @@ -28,17 +25,16 @@ "dependencies": { "@azure/identity": "^4.8.0", "@azure/openai": "^2.0.0", - "@microsoft/agents-hosting": "^0.2.14", - "express": "^5.0.1", + "@microsoft/agents-hosting-express": "^1.0.0", "openai": "^4.94.0" }, "devDependencies": { "@types/express": "^5.0.0", - "@types/node": "^18.0.0", + "@types/node": "^22.0.0", "env-cmd": "^10.1.0", - "nodemon": "^3.1.7", + "nodemon": "^3.1.10", "shx": "^0.3.3", - "ts-node": "^10.4.0", - "typescript": "^5.5.4" + "ts-node": "^10.9.2", + "typescript": "^5.8.3" } } \ No newline at end of file diff --git a/templates/vsc/ts/basic-custom-engine-agent/src/adapter.ts b/templates/vsc/ts/basic-custom-engine-agent/src/adapter.ts deleted file mode 100644 index 5ac047072c8..00000000000 --- a/templates/vsc/ts/basic-custom-engine-agent/src/adapter.ts +++ /dev/null @@ -1,35 +0,0 @@ -import { AuthConfiguration, CloudAdapter, loadAuthConfigFromEnv } from "@microsoft/agents-hosting"; - -// Create authentication configuration -const authConfig: AuthConfiguration = loadAuthConfigFromEnv(); - -// Create adapter -const adapter = new CloudAdapter(authConfig); - -// Catch-all for errors. -const onTurnErrorHandler = async (context, error) => { - // This check writes out errors to console log .vs. app insights. - // NOTE: In production environment, you should consider logging this to Azure - // application insights. - console.error(`\n [onTurnError] unhandled error: ${error}`); - - // Only send error message for user messages, not for other message types so the agent doesn't spam a channel or chat. - if (context.activity.type === "message") { - // Send a trace activity, which will be displayed in Bot Framework Emulator - await context.sendTraceActivity( - "OnTurnError Trace", - `${error}`, - "https://www.botframework.com/schemas/error", - "TurnError" - ); - - // Send a message to the user - await context.sendActivity("The agent encountered an error or bug."); - await context.sendActivity("To continue to run this agent, please fix the agent source code."); - } -}; - -// Set the onTurnError for the singleton TeamsAdapter. -adapter.onTurnError = onTurnErrorHandler; - -export default adapter; diff --git a/templates/vsc/ts/basic-custom-engine-agent/src/agent.ts.tpl b/templates/vsc/ts/basic-custom-engine-agent/src/agent.ts.tpl index ad156c02a34..8082e531702 100644 --- a/templates/vsc/ts/basic-custom-engine-agent/src/agent.ts.tpl +++ b/templates/vsc/ts/basic-custom-engine-agent/src/agent.ts.tpl @@ -24,12 +24,12 @@ export const agentApp = new AgentApplication({ storage, }); -agentApp.conversationUpdate("membersAdded", async (context: TurnContext) => { +agentApp.onConversationUpdate("membersAdded", async (context: TurnContext) => { await context.sendActivity(`Hi there! I'm an agent to chat with you.`); }); // Listen for ANY message to be received. MUST BE AFTER ANY OTHER MESSAGE HANDLERS -agentApp.activity(ActivityTypes.Message, async (context: TurnContext) => { +agentApp.onActivity(ActivityTypes.Message, async (context: TurnContext) => { // Echo back users request const result = await client.chat.completions.create({ messages: [ diff --git a/templates/vsc/ts/basic-custom-engine-agent/src/index.ts b/templates/vsc/ts/basic-custom-engine-agent/src/index.ts index b4f56d57485..25f892be4c0 100644 --- a/templates/vsc/ts/basic-custom-engine-agent/src/index.ts +++ b/templates/vsc/ts/basic-custom-engine-agent/src/index.ts @@ -1,33 +1,3 @@ -// Import required packages -import { - AuthConfiguration, - authorizeJWT, - loadAuthConfigFromEnv, - Request, -} from "@microsoft/agents-hosting"; -import express, { Response } from "express"; - -// This bot's adapter -import adapter from "./adapter"; - -// This bot's main dialog. +import { startServer } from "@microsoft/agents-hosting-express"; import { agentApp } from "./agent"; - -// Create authentication configuration -const authConfig: AuthConfiguration = loadAuthConfigFromEnv(); - -// Create express application. -const expressApp = express(); -expressApp.use(express.json()); -expressApp.use(authorizeJWT(authConfig)); - -const server = expressApp.listen(process.env.port || process.env.PORT || 3978, () => { - console.log(`\nAgent started, ${expressApp.name} listening to`, server.address()); -}); - -// Listen for incoming requests. -expressApp.post("/api/messages", async (req: Request, res: Response) => { - await adapter.process(req, res, async (context) => { - await agentApp.run(context); - }); -}); +startServer(agentApp); diff --git a/templates/vsc/ts/basic-custom-engine-agent/tsconfig.json b/templates/vsc/ts/basic-custom-engine-agent/tsconfig.json index a68afb21f72..4a2330fdc68 100644 --- a/templates/vsc/ts/basic-custom-engine-agent/tsconfig.json +++ b/templates/vsc/ts/basic-custom-engine-agent/tsconfig.json @@ -1,8 +1,9 @@ { "compilerOptions": { "declaration": true, - "target": "es2017", + "target": "es2019", "module": "commonjs", + "moduleResolution": "node", "outDir": "./lib", "rootDir": "./", "sourceMap": true, diff --git a/templates/vsc/ts/default-bot/teamsBot.ts b/templates/vsc/ts/default-bot/agent.ts similarity index 71% rename from templates/vsc/ts/default-bot/teamsBot.ts rename to templates/vsc/ts/default-bot/agent.ts index 63a14fd1bf5..15cb160848d 100644 --- a/templates/vsc/ts/default-bot/teamsBot.ts +++ b/templates/vsc/ts/default-bot/agent.ts @@ -6,7 +6,7 @@ import { TurnContext, TurnState, } from "@microsoft/agents-hosting"; -import { version } from "@microsoft/agents-hosting/package.json"; +import pkg from "@microsoft/agents-hosting/package.json"; interface ConversationState { count: number; @@ -17,51 +17,51 @@ const downloader = new AttachmentDownloader(); // Define storage and application const storage = new MemoryStorage(); -export const teamsBot = new AgentApplication({ +export const agentApp = new AgentApplication({ storage, fileDownloaders: [downloader], }); // Listen for user to say '/reset' and then delete conversation state -teamsBot.message("/reset", async (context: TurnContext, state: ApplicationTurnState) => { +agentApp.onMessage("/reset", async (context: TurnContext, state: ApplicationTurnState) => { state.deleteConversationState(); await context.sendActivity("Ok I've deleted the current conversation state."); }); -teamsBot.message("/count", async (context: TurnContext, state: ApplicationTurnState) => { +agentApp.onMessage("/count", async (context: TurnContext, state: ApplicationTurnState) => { const count = state.conversation.count ?? 0; await context.sendActivity(`The count is ${count}`); }); -teamsBot.message("/diag", async (context: TurnContext, state: ApplicationTurnState) => { +agentApp.onMessage("/diag", async (context: TurnContext, state: ApplicationTurnState) => { await state.load(context, storage); await context.sendActivity(JSON.stringify(context.activity)); }); -teamsBot.message("/state", async (context: TurnContext, state: ApplicationTurnState) => { +agentApp.onMessage("/state", async (context: TurnContext, state: ApplicationTurnState) => { await state.load(context, storage); await context.sendActivity(JSON.stringify(state)); }); -teamsBot.message("/runtime", async (context: TurnContext, state: ApplicationTurnState) => { +agentApp.onMessage("/runtime", async (context: TurnContext) => { const runtime = { nodeversion: process.version, - sdkversion: version, + sdkversion: pkg.version, }; await context.sendActivity(JSON.stringify(runtime)); }); -teamsBot.conversationUpdate( +agentApp.onConversationUpdate( "membersAdded", async (context: TurnContext, state: ApplicationTurnState) => { await context.sendActivity( - `Hi there! I'm an echo bot running on Agents SDK version ${version} that will echo what you said to me.` + `Hi there! I'm an echo bot running on Agents SDK version ${pkg.version} that will echo what you said to me.` ); } ); // Listen for ANY message to be received. MUST BE AFTER ANY OTHER MESSAGE HANDLERS -teamsBot.activity( +agentApp.onActivity( ActivityTypes.Message, async (context: TurnContext, state: ApplicationTurnState) => { // Increment count state @@ -73,11 +73,11 @@ teamsBot.activity( } ); -teamsBot.activity(/^message/, async (context: TurnContext, state: ApplicationTurnState) => { +agentApp.onActivity(/^message/, async (context: TurnContext, state: ApplicationTurnState) => { await context.sendActivity(`Matched with regex: ${context.activity.type}`); }); -teamsBot.activity( +agentApp.onActivity( async (context: TurnContext) => Promise.resolve(context.activity.type === "message"), async (context, state) => { await context.sendActivity(`Matched function: ${context.activity.type}`); diff --git a/templates/vsc/ts/default-bot/index.ts b/templates/vsc/ts/default-bot/index.ts index c1427a9e0c7..25f892be4c0 100644 --- a/templates/vsc/ts/default-bot/index.ts +++ b/templates/vsc/ts/default-bot/index.ts @@ -1,68 +1,3 @@ -import { - AuthConfiguration, - authorizeJWT, - CloudAdapter, - loadAuthConfigFromEnv, - Request, - TurnContext, -} from "@microsoft/agents-hosting"; -import express, { Response } from "express"; - -import { teamsBot } from "./teamsBot"; - -// Create authentication configuration -const authConfig: AuthConfiguration = loadAuthConfigFromEnv(); - -// Create adapter -const adapter = new CloudAdapter(authConfig); - -// Catch-all for errors. -const onTurnErrorHandler = async (context: TurnContext, error: Error) => { - // This check writes out errors to console log .vs. app insights. - // NOTE: In production environment, you should consider logging this to Azure - // application insights. - console.error(`\n [onTurnError] unhandled error: ${error}`); - - // Only send error message for user messages, not for other message types so the bot doesn't spam a channel or chat. - if (context.activity.type === "message") { - // Send a trace activity - await context.sendTraceActivity( - "OnTurnError Trace", - `${error}`, - "https://www.botframework.com/schemas/error", - "TurnError" - ); - - // Send a message to the user - await context.sendActivity(`The bot encountered unhandled error:\n ${error.message}`); - await context.sendActivity("To continue to run this bot, please fix the bot source code."); - } -}; - -// Set the onTurnError for the singleton CloudAdapter. -adapter.onTurnError = onTurnErrorHandler; - -// Create express application -const server = express(); -server.use(express.json()); -server.use(authorizeJWT(authConfig)); - -// Listen for incoming requests. -server.post("/api/messages", async (req: Request, res: Response) => { - await adapter.process(req, res, async (context) => { - await teamsBot.run(context); - }); -}); - -// Start the server -const port = process.env.PORT || 3978; -server - .listen(port, () => { - console.log( - `Bot Started, listening to port ${port} for appId ${authConfig.clientId} debug ${process.env.DEBUG}` - ); - }) - .on("error", (err) => { - console.error(err); - process.exit(1); - }); +import { startServer } from "@microsoft/agents-hosting-express"; +import { agentApp } from "./agent"; +startServer(agentApp); diff --git a/templates/vsc/ts/default-bot/infra/azure.bicep b/templates/vsc/ts/default-bot/infra/azure.bicep index 3999e8c3a86..d883f5ce16f 100644 --- a/templates/vsc/ts/default-bot/infra/azure.bicep +++ b/templates/vsc/ts/default-bot/infra/azure.bicep @@ -45,7 +45,7 @@ resource webApp 'Microsoft.Web/sites@2021-02-01' = { } { name: 'WEBSITE_NODE_DEFAULT_VERSION' - value: '~18' // Set NodeJS version to 18.x for your site + value: '~22' // Set NodeJS version to 22.x for your site } { name: 'RUNNING_ON_AZURE' diff --git a/templates/vsc/ts/default-bot/package.json.tpl b/templates/vsc/ts/default-bot/package.json.tpl index 05a14501a6c..9d557b48479 100644 --- a/templates/vsc/ts/default-bot/package.json.tpl +++ b/templates/vsc/ts/default-bot/package.json.tpl @@ -2,9 +2,6 @@ "name": "{{SafeProjectNameLowerCase}}", "version": "1.0.0", "description": "Microsoft 365 Agents Toolkit echo bot sample", - "engines": { - "node": "18 || 20 || 22" - }, "author": "Microsoft", "license": "MIT", "main": "./lib/index.js", @@ -23,16 +20,15 @@ "url": "https://github.com" }, "dependencies": { - "@microsoft/agents-hosting": "^0.2.14", - "express": "^5.0.1" + "@microsoft/agents-hosting-express": "^1.0.0" }, - "devDependencies": { + "devvDependencies": { "@types/express": "^5.0.0", - "@types/node": "^18.0.0", + "@types/node": "^22.0.0", "env-cmd": "^10.1.0", - "nodemon": "^3.1.7", + "nodemon": "^3.1.10", "shx": "^0.3.3", - "ts-node": "^10.4.0", - "typescript": "^4.4.4" + "ts-node": "^10.9.2", + "typescript": "^5.8.3" } } diff --git a/templates/vsc/ts/default-bot/tsconfig.json b/templates/vsc/ts/default-bot/tsconfig.json index 385a05ba674..852f5750086 100644 --- a/templates/vsc/ts/default-bot/tsconfig.json +++ b/templates/vsc/ts/default-bot/tsconfig.json @@ -1,11 +1,11 @@ { "compilerOptions": { "declaration": true, - "target": "es2017", + "target": "es2019", "module": "commonjs", + "moduleResolution": "node", "outDir": "./lib", "rootDir": "./", - "moduleResolution": "nodenext", "sourceMap": true, "incremental": true, "tsBuildInfoFile": "./lib/.tsbuildinfo", diff --git a/templates/vsc/ts/weather-agent/infra/azure.bicep.tpl b/templates/vsc/ts/weather-agent/infra/azure.bicep.tpl index 6adb2e7b4a4..41aad4d240f 100644 --- a/templates/vsc/ts/weather-agent/infra/azure.bicep.tpl +++ b/templates/vsc/ts/weather-agent/infra/azure.bicep.tpl @@ -60,7 +60,7 @@ resource webApp 'Microsoft.Web/sites@2021-02-01' = { } { name: 'WEBSITE_NODE_DEFAULT_VERSION' - value: '~18' // Set NodeJS version to 18.x for your site + value: '~22' // Set NodeJS version to 22.x for your site } { name: 'RUNNING_ON_AZURE' diff --git a/templates/vsc/ts/weather-agent/package.json.tpl b/templates/vsc/ts/weather-agent/package.json.tpl index d2fd9f2b9a6..796f395869e 100644 --- a/templates/vsc/ts/weather-agent/package.json.tpl +++ b/templates/vsc/ts/weather-agent/package.json.tpl @@ -5,9 +5,6 @@ "teamsAppId": null }, "description": "Weather Agent with Microsoft 365 Agents SDK and LangChain", - "engines": { - "node": "18 || 20 || 22" - }, "author": "Microsoft", "license": "MIT", "main": "./lib/src/index.js", @@ -29,21 +26,22 @@ "@azure/openai": "^2.0.0", "@langchain/langgraph": "^0.2.66", "@langchain/openai": "^0.5.6", - "@microsoft/agents-hosting": "^0.2.14", - "express": "^5.0.1", - "zod": "3.25.67" + "@microsoft/agents-hosting-express": "^1.0.0" }, "devDependencies": { "@types/express": "^5.0.0", - "@types/node": "^18.0.0", + "@types/node": "^22.0.0", "env-cmd": "^10.1.0", - "nodemon": "^3.1.7", + "nodemon": "^3.1.10", "shx": "^0.3.3", - "ts-node": "^10.4.0", - "typescript": "^5.5.4" + "ts-node": "^10.9.2", + "typescript": "^5.8.3" }, "overrides": { - "**": { + "@microsoft/agents-activity": { + "zod": "3.25.67" + }, + "@langchain/core": { "zod": "3.25.67" } } diff --git a/templates/vsc/ts/weather-agent/src/agent.ts.tpl b/templates/vsc/ts/weather-agent/src/agent.ts.tpl index fe01280c35d..d6fadc8ffaf 100644 --- a/templates/vsc/ts/weather-agent/src/agent.ts.tpl +++ b/templates/vsc/ts/weather-agent/src/agent.ts.tpl @@ -13,7 +13,7 @@ import { getWeatherTool } from "./tools/getWeatherTool"; export const weatherAgent = new AgentApplicationBuilder().build(); -weatherAgent.conversationUpdate( +weatherAgent.onConversationUpdate( "membersAdded", async (context: TurnContext) => { await context.sendActivity( @@ -64,7 +64,7 @@ Respond in JSON format with the following JSON schema, and do not use markdown i "content": "{The content of the response, may be plain text, or JSON based adaptive card}" }`); -weatherAgent.activity(ActivityTypes.Message, async (context, state) => { +weatherAgent.onActivity(ActivityTypes.Message, async (context, state) => { const llmResponse = await agent.invoke( { messages: [sysMessage, new HumanMessage(context.activity.text!)], diff --git a/templates/vsc/ts/weather-agent/src/index.ts b/templates/vsc/ts/weather-agent/src/index.ts index 876aa2ece49..8e57b88f43b 100644 --- a/templates/vsc/ts/weather-agent/src/index.ts +++ b/templates/vsc/ts/weather-agent/src/index.ts @@ -1,35 +1,3 @@ -// Import required packages -import { - AuthConfiguration, - authorizeJWT, - CloudAdapter, - loadAuthConfigFromEnv, - Request, -} from "@microsoft/agents-hosting"; -import express, { Response } from "express"; - -// This bot's main dialog. +import { startServer } from "@microsoft/agents-hosting-express"; import { weatherAgent } from "./agent"; - -// Create authentication configuration -const authConfig: AuthConfiguration = loadAuthConfigFromEnv(); -const adapter = new CloudAdapter(authConfig); - -// Create express application. -const server = express(); -server.use(express.json()); -server.use(authorizeJWT(authConfig)); - -// Listen for incoming requests. -server.post("/api/messages", async (req: Request, res: Response) => { - await adapter.process(req, res, async (context) => { - await weatherAgent.run(context); - }); -}); - -const port = process.env.port || process.env.PORT || 3978; -server.listen(port, () => { - console.log( - `\nServer listening to port ${port} for appId ${authConfig.clientId} debug ${process.env.DEBUG}` - ); -}); +startServer(weatherAgent); diff --git a/templates/vsc/ts/weather-agent/tsconfig.json b/templates/vsc/ts/weather-agent/tsconfig.json index a68afb21f72..4a2330fdc68 100644 --- a/templates/vsc/ts/weather-agent/tsconfig.json +++ b/templates/vsc/ts/weather-agent/tsconfig.json @@ -1,8 +1,9 @@ { "compilerOptions": { "declaration": true, - "target": "es2017", + "target": "es2019", "module": "commonjs", + "moduleResolution": "node", "outDir": "./lib", "rootDir": "./", "sourceMap": true,