@@ -53,19 +53,89 @@ export async function loadMSTeamsSdk(): Promise<MSTeamsTeamsSdk> {
5353 } ;
5454}
5555
56+ /**
57+ * Create a lightweight no-op HTTP plugin stub that satisfies the Teams SDK's
58+ * plugin discovery by name ("http") but does NOT spin up an Express server.
59+ *
60+ * The default HttpPlugin in @microsoft/teams.apps registers an Express
61+ * middleware with the pattern `/api*`. When the host application (OpenClaw)
62+ * uses Express 5 — which depends on path-to-regexp v8 — that pattern is
63+ * invalid and throws:
64+ *
65+ * Missing parameter name at index 5: /api*
66+ *
67+ * OpenClaw manages its own Express server for the Teams webhook endpoint, so
68+ * the SDK's built-in HTTP server is unnecessary. Passing this stub prevents
69+ * the SDK from creating the default HttpPlugin and avoids the crash.
70+ *
71+ * See: https://github.com/openclaw/openclaw/issues/55161
72+ */
73+ async function createNoOpHttpPlugin ( ) : Promise < unknown > {
74+ // Lazy-import reflect-metadata (required by the Teams SDK decorator system)
75+ // and the decorator key constants so we can tag the stub class correctly.
76+ //
77+ // FRAGILE: these are internal SDK paths (not public API). If
78+ // @microsoft /teams.apps changes its dist layout, these imports will break.
79+ // Pin the SDK version and re-verify after any upgrade.
80+ await import ( "reflect-metadata" ) ;
81+ const { PLUGIN_METADATA_KEY } =
82+ await import ( "@microsoft/teams.apps/dist/types/plugin/decorators/plugin.js" ) ;
83+ const { PLUGIN_DEPENDENCIES_METADATA_KEY } =
84+ await import ( "@microsoft/teams.apps/dist/types/plugin/decorators/dependency.js" ) ;
85+ const { PLUGIN_EVENTS_METADATA_KEY } =
86+ await import ( "@microsoft/teams.apps/dist/types/plugin/decorators/event.js" ) ;
87+
88+ class NoOpHttpPlugin {
89+ onInit ( ) { }
90+ async onStart ( ) { }
91+ onStop ( ) { }
92+ asServer ( ) {
93+ return {
94+ onRequest : undefined as unknown ,
95+ initialize : async ( ) => { } ,
96+ start : async ( ) => { } ,
97+ stop : async ( ) => { } ,
98+ } as {
99+ onRequest : unknown ;
100+ initialize : ( opts ?: unknown ) => Promise < void > ;
101+ start : ( port ?: number | string ) => Promise < void > ;
102+ stop : ( ) => Promise < void > ;
103+ } ;
104+ }
105+ }
106+
107+ Reflect . defineMetadata (
108+ PLUGIN_METADATA_KEY ,
109+ { name : "http" , version : "0.0.0" , description : "no-op stub (express 5 compat)" } ,
110+ NoOpHttpPlugin ,
111+ ) ;
112+ Reflect . defineMetadata ( PLUGIN_DEPENDENCIES_METADATA_KEY , [ ] , NoOpHttpPlugin ) ;
113+ Reflect . defineMetadata ( PLUGIN_EVENTS_METADATA_KEY , [ ] , NoOpHttpPlugin ) ;
114+
115+ return new NoOpHttpPlugin ( ) ;
116+ }
117+
56118/**
57119 * Create a Teams SDK App instance from credentials. The App manages token
58120 * acquisition, JWT validation, and the HTTP server lifecycle.
59121 *
60122 * This replaces the previous CloudAdapter + MsalTokenProvider + authorizeJWT
61123 * from @microsoft/agents-hosting.
62124 */
63- export function createMSTeamsApp ( creds : MSTeamsCredentials , sdk : MSTeamsTeamsSdk ) : MSTeamsApp {
125+ export async function createMSTeamsApp (
126+ creds : MSTeamsCredentials ,
127+ sdk : MSTeamsTeamsSdk ,
128+ ) : Promise < MSTeamsApp > {
129+ const noOpHttp = await createNoOpHttpPlugin ( ) ;
130+ // Use type assertion: the SDK's AppOptions generic narrows `plugins` to
131+ // Array<TPlugin>, but our no-op stub satisfies the runtime contract without
132+ // matching the decorator-heavy IPlugin type at compile time.
64133 return new sdk . App ( {
65134 clientId : creds . appId ,
66135 clientSecret : creds . appPassword ,
67136 tenantId : creds . tenantId ,
68- } ) ;
137+ plugins : [ noOpHttp ] ,
138+ } as ConstructorParameters < MSTeamsTeamsSdk [ "App" ] > [ 0 ] ) ;
69139}
70140
71141/**
@@ -396,7 +466,7 @@ export function createMSTeamsAdapter(app: MSTeamsApp, sdk: MSTeamsTeamsSdk): MST
396466
397467export async function loadMSTeamsSdkWithAuth ( creds : MSTeamsCredentials ) {
398468 const sdk = await loadMSTeamsSdk ( ) ;
399- const app = createMSTeamsApp ( creds , sdk ) ;
469+ const app = await createMSTeamsApp ( creds , sdk ) ;
400470 return { sdk, app } ;
401471}
402472
0 commit comments