Panduan migrasi Azure Bot Framework SDK ke Agen SDK Microsoft 365 untuk Node.js

Artikel ini menjelaskan perubahan yang diperlukan untuk bermigrasi dari Bot Framework SDK untuk Node.js.

Prasyarat

  • Node.js versi 20 atau lebih tinggi
  • Proyek Bot Framework SDK yang ada
  • Azure Bot Service resource (tidak berubah selama migrasi)

Perubahan Kode SDK NodeJS

Perubahan di bagian ini disebabkan oleh perbedaan antara Azure Bot Framework SDK dan Agen SDK Microsoft 365 JavaScript .

Sumber daya Azure

Sumber daya Azure Anda tetap tidak berubah. Anda perlu mereferensikan properti appsettings Anda untuk MicrosoftAppType, MicrosoftAppId, MicrosoftAppPassword, dan MicrosoftAppTenantId. Namun nama pengaturan tersebut tidak lagi digunakan dan dapat dihapus nanti. Pelajari selengkapnya tentang konfigurasi lingkungan

Langkah pertama

Terapkan perubahan berikut terlebih dahulu untuk mengatasi sebagian besar perbedaan. Anda masih perlu men-debug dan memeriksa perbedaan lain setelah menerapkan perubahan ini.

Memperbarui dependensi paket

Perubahan ini tidak menyelesaikan semua namespace yang diperlukan, tetapi mencakup sebagian besarnya.

Skenario SDK Bot Framework Agen SDK
Hosting utama botbuilder @microsoft/agents-hosting
Skema aktivitas botframework-schema @microsoft/agents-activity
Dialogs botbuilder-dialogs @microsoft/agents-hosting-dialogs
Azure Cosmos DB botbuilder-azure @microsoft/agents-hosting-storage-cosmos
Azure Blob Storage botbuilder-azure-blobs @microsoft/agents-hosting-storage-blob
Utilitas server ekspres Penyiapan manual @microsoft/agents-hosting-express

Bot menggunakan Teams

Jika bot Anda menggunakan Teams, tambahkan dependensi paket untuk @microsoft/agents-hosting-extensions-teams

Memperbarui impor/persyaratan

Gunakan temukan dan ganti untuk membuat perubahan berikut:

Kerangka Kerja Bot Agen SDK
require('botframework-schema'); require('@microsoft/agents-activity')
require('botbuilder'); require('@microsoft/agents-hosting')
require('botbuilder-dialogs'); require('@microsoft/agents-hosting-dialogs')

Kelas Aktivitas Agen SDK

Paket @microsoft/agents-activity ini mencakup Kelas aktivitas untuk melakukan penguraian berdasarkan zod. Anda dapat mengurai dan memvalidasi aktivitas kustom Anda dari JSON dengan Activity.fromJson() atau dari objek JavaScript harfiah dengan Activity.fromObject().

Selain itu, kelas Activity memusatkan semua operasi yang terkait dengan payload aktivitas, seperti getConversationReference. Metode dalam tabel berikut berpindah dari TurnContext dan sekarang beroperasi melalui instans aktivitas saat ini:

Metode statis Kerangka Kerja Bot Metode instans Agen SDK
TurnContext.applyConversationReference activity.applyConversationReference
TurnContext.getConversationReference activity.getConversationReference
TurnContext.getReplyConversationReference activity.getReplyConversationReference
TurnContext.removeRecipientMention activity.removeRecipientMention
TurnContext.getMentions activity.getMentions
TurnContext.removeMentionText activity.removeMentionText

Pemulaian dan Konfigurasi

Sistem konfigurasi SDK Agen mengganti kelas ConfigurationBotFrameworkAuthentication dengan AuthConfiguration antarmuka.

Untuk memuat konfigurasi dari file default .env , gunakan loadAuthConfigFromEnv.

Important

Variabel konfigurasi dijelaskan dalam Mengonfigurasi autentikasi di JavaScript.

Konfigurasi Lingkungan

Buat .env file dengan variabel berikut:

# Required for Azure Bot Service
clientId=your-app-id
clientSecret=your-app-secret  
tenantId=your-tenant-id

# Optional - for local debugging
PORT=3978
DEBUG=true

Catatan Migrasi: Perbarui nama variabel lingkungan Anda seperti yang diperlihatkan dalam tabel berikut:

SDK Bot Framework Agen SDK
MicrosoftAppId clientId
MicrosoftAppPassword clientSecret
MicrosoftAppTenantId tenantId

Otentikasi dan Keamanan

Ketika Bot Framework SDK mengotorisasi permintaan masuk, ia menyertakan token otorisasi JSON Web Token (JWT) di dalam stack. Agen SDK tidak demikian. Saat menggunakan runtime server web seperti Express, Anda harus mengonfigurasi middleware JWT untuk mengotorisasi permintaan masuk berdasarkan token JWT Bearer, Agent SDK menyediakan metode authorizeJWT(AuthConfiguration).

Middleware JWT (Diperlukan untuk produksi):

import { authorizeJWT, loadAuthConfigFromEnv } from '@microsoft/agents-hosting'

const authConfig = loadAuthConfigFromEnv()
server.use(authorizeJWT(authConfig))

Pengembangan Lokal:

Untuk penelusuran kesalahan lokal, validasi JWT dapat dinonaktifkan:

// Only for local development - NEVER in production
if (process.env.NODE_ENV === 'development') {
    // JWT validation disabled for local testing
} else {
    server.use(authorizeJWT(authConfig))
}

Opsi Penyetelan Server

SDK Agen menyediakan dua pendekatan untuk menyiapkan server Anda.

Menggunakan metode startServer

Gunakan pendekatan yang disederhanakan ini untuk proyek baru saat Anda menginginkan penyiapan minimal dan tidak memerlukan middleware kustom.

Perbarui kode inisialisasi Anda dari botbuilder:

const { EchoBot } = require('./bot');
const {
    CloudAdapter,
    ConfigurationBotFrameworkAuthentication
} = require('botbuilder');
const botFrameworkAuthentication = new ConfigurationBotFrameworkAuthentication(process.env);
const adapter = new CloudAdapter(botFrameworkAuthentication);
const myBot = new EchoBot();
const server = express();
server.use(express.json());
server.post('/api/messages', async (req, res) => 
    await adapter.process(req, res, (context) => 
      myBot.run(context));
);

Untuk hosting agen dengan startServer():

const { EchoBot } = require('./bot');
const { startServer } = require('@microsoft/agents-hosting-express')
startServer(new EchoBot());

Penyiapan Ekspres Manual

Gunakan pendekatan ini saat memigrasikan bot yang ada, memerlukan middleware kustom, ingin kontrol penuh atas konfigurasi Ekspres

const { EchoBot } = require('./bot');
const {
    CloudAdapter,
    loadAuthConfigFromEnv, // Update
    authorizeJWT // Update
} = require('@microsoft/agents-hosting'); // Update
const authConfig = loadAuthConfigFromEnv(); // Update
const adapter = new CloudAdapter(authConfig); // Update
const myBot = new EchoBot();
const server = express();
server.use(express.json());
server.use(authorizeJWT(authConfig)); // Update
server.post('/api/messages', async (req, res) => 
    await adapter.process(req, res, (context) => 
      myBot.run(context));
);

const port = process.env.PORT || 3978;
server.listen(port, () => {
    console.log(`Server listening on port ${port}`);
}).on('error', (err) => {
    console.error('Server failed to start:', err);
    process.exit(1);
});

Dukungan ActivityHandler

Sebagian besar bot yang dibuat dengan Bot Framework SDK didasarkan pada botbuilder-core.ActivityHandler kelas dasar.

Agen SDK menyediakan agents-hosting.ActivityHandler yang kompatibel dan mempertahankan antarmuka API yang sama untuk memudahkan migrasi.

Perbedaan utama

Beberapa perbedaan utama antara Bot Framework SDK dan Agen SDK meliputi:

Parameter Penanganan:

SDK Jenis Handler
SDK Bot Framework BotHandler
Agen SDK AgentHandler

Metode Tambahan dalam Agen SDK:

Metode Description
onMessageDelete Menangani aktivitas penghapusan pesan
onMessageUpdate Menangani aktivitas pembaruan pesan
onSignInInvoke Menangani aktivitas pemanggilan masuk

Metode yang Hilang dalam Agent SDK:

Metode Reason
onCommand Aktivitas perintah tidak didukung
onCommandResult Aktivitas hasil perintah tidak didukung
onEvent Penanganan peristiwa generik (jenis peristiwa tertentu seperti onTokenResponseEvent masih didukung)
onTokenResponseEvent Peristiwa respons token OAuth

Perubahan Tanda Tangan Metode:

Semua metode handler mengembalikan ActivityHandler alih-alih this untuk perangkaian metode. Fungsi handler menggunakan AgentHandler jenis , yang memiliki tanda tangan yang sama dengan BotHandler

Contoh Migrasi:

SDK Kerangka Kerja Bot:

const { ActivityHandler } = require('botbuilder');

class MyBot extends ActivityHandler {
    constructor() {
        super();
        this.onMessage(async (context, next) => {
            await context.sendActivity('Hello!');
            await next();
        });
    }
}

Migrasi sebagian besar mudah, dengan perubahan utama adalah pernyataan impor dan jenis handler. Sebagian besar bot berbasis ActivityHandler yang sudah ada dapat berfungsi dengan modifikasi minimal.

Important

ActivityHandler tidak digunakan lagi demi kelas baru AgentApplication

Migrasi dari ActivityHandler ke AgentApplication

Meskipun ActivityHandler didukung untuk kompatibilitas mundur, pendekatan yang direkomendasikan adalah menggunakan AgentApplication:

Menggunakan ActivityHandler:

import { ActivityHandler } from '@microsoft/agents-hosting'

class MyBot extends ActivityHandler {
    constructor() {
        super()
        this.onMessage(async (context, next) => {
            await context.sendActivity('Hello!')
            await next()
        })
        
        this.onMembersAdded(async (context, next) => {
            await context.sendActivity('Welcome!')
            await next()
        })
    }
}

Perbedaan Utama

Tabel berikut ini menjelaskan perbedaan fitur utama antara ActivityHandler dan AgentApplication:

Fitur ActivityHandler AgentApplication
Manajemen Negara Diperlukan manajemen status manual Manajemen status bawaan disediakan
Penanganan Peristiwa Penanganan aktivitas generik (misalnya, onMembersAdded) Penangan kejadian yang lebih spesifik (misalnya, membersAdded)
Fungsi Berikutnya Penanganan memerlukan panggilan next() Handler tidak memerlukan panggilan next()
Penyimpanan Konfigurasi penyimpanan manual Dukungan penyimpanan bawaan dengan persistensi status otomatis

Pola Migrasi Umum

Beberapa pola migrasi umum adalah:

Bot Echo Sederhana

Kerangka Kerja Bot

const { ActivityHandler } = require('botbuilder')

class EchoBot extends ActivityHandler {
    constructor() {
        super()
        this.onMessage(async (context, next) => {
            await context.sendActivity(`You said: ${context.activity.text}`)
            await next()
        })
    }
}

Manajemen Negara

Menggunakan AgentApplication:

import { AgentApplication, MemoryStorage } from '@microsoft/agents-hosting'

const agent = new AgentApplication({
    storage: new MemoryStorage()
})

agent.onMessage('/count', async (context, state) => {
    const count = state.conversation.count ?? 0
    state.conversation.count = count + 1
    await context.sendActivity(`Count: ${state.conversation.count}`)
})

Mewarisi dari "AgentApplication"

Untuk skenario yang lebih kompleks, Anda dapat membuat kelas yang mewarisi dari AgentApplication:

import { AgentApplication, MemoryStorage, MessageFactory } from '@microsoft/agents-hosting'

class MyAgent extends AgentApplication {
    constructor() {
        super({
            storage: new MemoryStorage()
        })
        this.setupRoutes()
    }
    
    setupRoutes() {
        this.onMessage('/help', this.handleHelp)
        this.onMessage('/status', this.handleStatus)
        this.onMessage('/reset', this.handleReset)
        
        this.onActivity('message', this.handleDefault)
        this.onConversationUpdate('membersAdded', this.handleWelcome)
    }
    
    handleHelp = async (context, state) => {
        const helpText = `
                Available commands:
                - /help - Show this help message
                - /status - Show current status
                - /reset - Reset conversation state
        `
        await context.sendActivity(MessageFactory.text(helpText))
    }
    
    handleStatus = async (context, state) => {
        const messageCount = state.conversation.messageCount ?? 0
        await context.sendActivity(`Messages processed: ${messageCount}`)
    }
    
    handleReset = async (context, state) => {
        state.deleteConversationState()
        await context.sendActivity('Conversation state has been reset.')
    }
    
    handleWelcome = async (context, state) => {
        const welcomeText = 'Welcome! Type /help to see available commands.'
        await context.sendActivity(MessageFactory.text(welcomeText))
    }
    
    handleDefault = async (context, state) => {
        // Increment message counter
        const messageCount = (state.conversation.messageCount ?? 0) + 1
        state.conversation.messageCount = messageCount
        
        const replyText = `Echo: ${context.activity.text} (Message #${messageCount})`
        await context.sendActivity(MessageFactory.text(replyText))
    }
}

export default new MyAgent()

Manfaat pola ini

Manfaat Description
Organisasi yang lebih baik Metode terpisah untuk pengendali yang beragam
Dapat Digunakan Kembali Dapat dengan mudah diperpanjang atau diwariskan lebih lanjut
Kemampuan uji Metode individual dapat diuji dengan unit
Maintainability Struktur kode yang lebih bersih untuk bot kompleks
Fungsi panah Mengikat this konteks secara otomatis tanpa memerlukan .bind()