@wingman-ai/gateway 0.4.2 → 0.4.3
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/README.md +14 -0
- package/dist/agent/config/mcpClientManager.cjs +104 -1
- package/dist/agent/config/mcpClientManager.d.ts +30 -0
- package/dist/agent/config/mcpClientManager.js +104 -1
- package/dist/agent/config/modelFactory.cjs +10 -0
- package/dist/agent/config/modelFactory.js +10 -0
- package/dist/agent/config/xaiImageModel.cjs +242 -0
- package/dist/agent/config/xaiImageModel.d.ts +33 -0
- package/dist/agent/config/xaiImageModel.js +202 -0
- package/dist/agent/tests/mcpClientManager.test.cjs +116 -0
- package/dist/agent/tests/mcpClientManager.test.js +117 -1
- package/dist/agent/tests/mcpResourceTools.test.cjs +101 -0
- package/dist/agent/tests/mcpResourceTools.test.d.ts +1 -0
- package/dist/agent/tests/mcpResourceTools.test.js +95 -0
- package/dist/agent/tests/modelFactory.test.cjs +16 -2
- package/dist/agent/tests/modelFactory.test.js +16 -2
- package/dist/agent/tests/xaiImageModel.test.cjs +194 -0
- package/dist/agent/tests/xaiImageModel.test.d.ts +1 -0
- package/dist/agent/tests/xaiImageModel.test.js +188 -0
- package/dist/agent/tools/mcp_resources.cjs +111 -0
- package/dist/agent/tools/mcp_resources.d.ts +3 -0
- package/dist/agent/tools/mcp_resources.js +77 -0
- package/dist/bench/adapters/commandAdapter.cjs +93 -0
- package/dist/bench/adapters/commandAdapter.d.ts +6 -0
- package/dist/bench/adapters/commandAdapter.js +59 -0
- package/dist/bench/adapters/helpers.cjs +170 -0
- package/dist/bench/adapters/helpers.d.ts +7 -0
- package/dist/bench/adapters/helpers.js +133 -0
- package/dist/bench/adapters/index.cjs +41 -0
- package/dist/bench/adapters/index.d.ts +2 -0
- package/dist/bench/adapters/index.js +7 -0
- package/dist/bench/adapters/wingmanCliAdapter.cjs +100 -0
- package/dist/bench/adapters/wingmanCliAdapter.d.ts +6 -0
- package/dist/bench/adapters/wingmanCliAdapter.js +66 -0
- package/dist/bench/cleanup.cjs +122 -0
- package/dist/bench/cleanup.d.ts +9 -0
- package/dist/bench/cleanup.js +85 -0
- package/dist/bench/config.cjs +190 -0
- package/dist/bench/config.d.ts +2 -0
- package/dist/bench/config.js +156 -0
- package/dist/bench/index.cjs +43 -0
- package/dist/bench/index.d.ts +3 -0
- package/dist/bench/index.js +3 -0
- package/dist/bench/official.cjs +616 -0
- package/dist/bench/official.d.ts +80 -0
- package/dist/bench/official.js +546 -0
- package/dist/bench/officialCli.cjs +204 -0
- package/dist/bench/officialCli.d.ts +5 -0
- package/dist/bench/officialCli.js +170 -0
- package/dist/bench/process.cjs +78 -0
- package/dist/bench/process.d.ts +14 -0
- package/dist/bench/process.js +44 -0
- package/dist/bench/runner.cjs +237 -0
- package/dist/bench/runner.d.ts +7 -0
- package/dist/bench/runner.js +197 -0
- package/dist/bench/scoring.cjs +171 -0
- package/dist/bench/scoring.d.ts +9 -0
- package/dist/bench/scoring.js +137 -0
- package/dist/bench/types.cjs +18 -0
- package/dist/bench/types.d.ts +200 -0
- package/dist/bench/types.js +0 -0
- package/dist/bench/validator.cjs +92 -0
- package/dist/bench/validator.d.ts +2 -0
- package/dist/bench/validator.js +58 -0
- package/dist/cli/config/schema.cjs +36 -1
- package/dist/cli/config/schema.d.ts +46 -0
- package/dist/cli/config/schema.js +36 -1
- package/dist/cli/config/warnings.cjs +119 -51
- package/dist/cli/config/warnings.js +119 -51
- package/dist/cli/core/agentInvoker.cjs +9 -2
- package/dist/cli/core/agentInvoker.d.ts +1 -0
- package/dist/cli/core/agentInvoker.js +9 -2
- package/dist/cli/core/imagePersistence.cjs +17 -1
- package/dist/cli/core/imagePersistence.d.ts +2 -0
- package/dist/cli/core/imagePersistence.js +13 -3
- package/dist/cli/core/sessionManager.cjs +2 -0
- package/dist/cli/core/sessionManager.js +3 -1
- package/dist/cli/types.d.ts +18 -0
- package/dist/gateway/adapters/teams.cjs +419 -0
- package/dist/gateway/adapters/teams.d.ts +47 -0
- package/dist/gateway/adapters/teams.js +361 -0
- package/dist/gateway/http/sms.cjs +286 -0
- package/dist/gateway/http/sms.d.ts +4 -0
- package/dist/gateway/http/sms.js +249 -0
- package/dist/gateway/server.cjs +54 -3
- package/dist/gateway/server.d.ts +2 -0
- package/dist/gateway/server.js +54 -3
- package/dist/gateway/sms/commands.cjs +116 -0
- package/dist/gateway/sms/commands.d.ts +15 -0
- package/dist/gateway/sms/commands.js +79 -0
- package/dist/gateway/sms/control.cjs +118 -0
- package/dist/gateway/sms/control.d.ts +18 -0
- package/dist/gateway/sms/control.js +84 -0
- package/dist/gateway/sms/policyStore.cjs +198 -0
- package/dist/gateway/sms/policyStore.d.ts +37 -0
- package/dist/gateway/sms/policyStore.js +161 -0
- package/dist/providers/registry.cjs +1 -0
- package/dist/providers/registry.js +1 -0
- package/dist/tests/cli-config-warnings.test.cjs +41 -0
- package/dist/tests/cli-config-warnings.test.js +41 -0
- package/dist/tests/cli-init.test.cjs +32 -26
- package/dist/tests/cli-init.test.js +32 -26
- package/dist/tests/gateway-http-security.test.cjs +21 -0
- package/dist/tests/gateway-http-security.test.js +21 -0
- package/dist/tests/gateway-origin-policy.test.cjs +22 -0
- package/dist/tests/gateway-origin-policy.test.js +22 -0
- package/dist/tests/gateway.test.cjs +57 -0
- package/dist/tests/gateway.test.js +57 -0
- package/dist/tests/imagePersistence.test.cjs +26 -0
- package/dist/tests/imagePersistence.test.js +27 -1
- package/dist/tests/run-terminal-bench-official-script.test.cjs +61 -0
- package/dist/tests/run-terminal-bench-official-script.test.d.ts +1 -0
- package/dist/tests/run-terminal-bench-official-script.test.js +55 -0
- package/dist/tests/sessions-api.test.cjs +69 -1
- package/dist/tests/sessions-api.test.js +70 -2
- package/dist/tests/sms-api.test.cjs +183 -0
- package/dist/tests/sms-api.test.d.ts +1 -0
- package/dist/tests/sms-api.test.js +177 -0
- package/dist/tests/sms-commands.test.cjs +90 -0
- package/dist/tests/sms-commands.test.d.ts +1 -0
- package/dist/tests/sms-commands.test.js +84 -0
- package/dist/tests/sms-policy-store.test.cjs +69 -0
- package/dist/tests/sms-policy-store.test.d.ts +1 -0
- package/dist/tests/sms-policy-store.test.js +63 -0
- package/dist/tests/teams-adapter.test.cjs +58 -0
- package/dist/tests/teams-adapter.test.d.ts +1 -0
- package/dist/tests/teams-adapter.test.js +52 -0
- package/dist/tests/terminal-bench-adapters-helpers.test.cjs +64 -0
- package/dist/tests/terminal-bench-adapters-helpers.test.d.ts +1 -0
- package/dist/tests/terminal-bench-adapters-helpers.test.js +58 -0
- package/dist/tests/terminal-bench-cleanup.test.cjs +93 -0
- package/dist/tests/terminal-bench-cleanup.test.d.ts +1 -0
- package/dist/tests/terminal-bench-cleanup.test.js +87 -0
- package/dist/tests/terminal-bench-config.test.cjs +62 -0
- package/dist/tests/terminal-bench-config.test.d.ts +1 -0
- package/dist/tests/terminal-bench-config.test.js +56 -0
- package/dist/tests/terminal-bench-official.test.cjs +194 -0
- package/dist/tests/terminal-bench-official.test.d.ts +1 -0
- package/dist/tests/terminal-bench-official.test.js +188 -0
- package/dist/tests/terminal-bench-runner.test.cjs +82 -0
- package/dist/tests/terminal-bench-runner.test.d.ts +1 -0
- package/dist/tests/terminal-bench-runner.test.js +76 -0
- package/dist/tests/terminal-bench-scoring.test.cjs +128 -0
- package/dist/tests/terminal-bench-scoring.test.d.ts +1 -0
- package/dist/tests/terminal-bench-scoring.test.js +122 -0
- package/dist/tools/mcp-fal-ai.cjs +1 -1
- package/dist/tools/mcp-fal-ai.js +1 -1
- package/dist/webui/assets/index-Cyg_Hs57.css +11 -0
- package/dist/webui/assets/{index-BMekSELC.js → index-DZXLLjaA.js} +109 -109
- package/dist/webui/index.html +2 -2
- package/package.json +11 -2
- package/templates/agents/game-dev/agent.md +122 -63
- package/templates/agents/game-dev/art-director.md +106 -0
- package/templates/agents/game-dev/game-designer.md +87 -0
- package/templates/agents/game-dev/scene-engineer.md +474 -0
- package/dist/webui/assets/index-Cwkg4DKj.css +0 -11
- package/templates/agents/game-dev/art-generation.md +0 -38
- package/templates/agents/game-dev/asset-refinement.md +0 -17
- package/templates/agents/game-dev/planning-idea.md +0 -17
- package/templates/agents/game-dev/ui-specialist.md +0 -17
|
@@ -0,0 +1,361 @@
|
|
|
1
|
+
import { CloudAdapter, ConfigurationBotFrameworkAuthentication } from "botbuilder";
|
|
2
|
+
import { parseStreamChunk } from "../../cli/core/streamParser.js";
|
|
3
|
+
import { createLogger } from "../../logger.js";
|
|
4
|
+
import { GatewayRpcClient } from "../rpcClient.js";
|
|
5
|
+
import { extractSessionOverride, extractUiMeta, parseAgentIdFromSessionKey } from "./discord.js";
|
|
6
|
+
function _define_property(obj, key, value) {
|
|
7
|
+
if (key in obj) Object.defineProperty(obj, key, {
|
|
8
|
+
value: value,
|
|
9
|
+
enumerable: true,
|
|
10
|
+
configurable: true,
|
|
11
|
+
writable: true
|
|
12
|
+
});
|
|
13
|
+
else obj[key] = value;
|
|
14
|
+
return obj;
|
|
15
|
+
}
|
|
16
|
+
const DEFAULT_TEAMS_ENDPOINT_PATH = "/api/adapters/teams/messages";
|
|
17
|
+
const DEFAULT_TEAMS_RESPONSE_CHUNK = 3500;
|
|
18
|
+
function normalizeTeamsEndpointPath(path) {
|
|
19
|
+
const fallback = DEFAULT_TEAMS_ENDPOINT_PATH;
|
|
20
|
+
if (!path || "string" != typeof path) return fallback;
|
|
21
|
+
const trimmed = path.trim();
|
|
22
|
+
if (!trimmed) return fallback;
|
|
23
|
+
return trimmed.startsWith("/") ? trimmed : `/${trimmed}`;
|
|
24
|
+
}
|
|
25
|
+
function splitTeamsMessage(text, maxLength = DEFAULT_TEAMS_RESPONSE_CHUNK) {
|
|
26
|
+
const normalized = text.trim();
|
|
27
|
+
if (!normalized) return [];
|
|
28
|
+
const chunks = [];
|
|
29
|
+
let current = "";
|
|
30
|
+
for (const char of normalized){
|
|
31
|
+
if (current.length + 1 > maxLength) {
|
|
32
|
+
chunks.push(current);
|
|
33
|
+
current = "";
|
|
34
|
+
}
|
|
35
|
+
current += char;
|
|
36
|
+
}
|
|
37
|
+
if (current) chunks.push(current);
|
|
38
|
+
return chunks;
|
|
39
|
+
}
|
|
40
|
+
function escapeRegex(value) {
|
|
41
|
+
return value.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
|
|
42
|
+
}
|
|
43
|
+
function getEntities(activity) {
|
|
44
|
+
if (!Array.isArray(activity.entities)) return [];
|
|
45
|
+
return activity.entities;
|
|
46
|
+
}
|
|
47
|
+
function extractTeamsMentionTexts(activity, botAccountId) {
|
|
48
|
+
const recipientName = activity.recipient?.name?.trim().toLowerCase();
|
|
49
|
+
const texts = new Set();
|
|
50
|
+
for (const entity of getEntities(activity)){
|
|
51
|
+
if ("mention" !== entity.type || "string" != typeof entity.text) continue;
|
|
52
|
+
const mentionedId = entity.mentioned?.id?.trim();
|
|
53
|
+
const mentionedName = entity.mentioned?.name?.trim().toLowerCase();
|
|
54
|
+
if (botAccountId && mentionedId === botAccountId || recipientName && mentionedName === recipientName) texts.add(entity.text);
|
|
55
|
+
}
|
|
56
|
+
return Array.from(texts);
|
|
57
|
+
}
|
|
58
|
+
function stripTeamsBotMention(content, mentionTexts = []) {
|
|
59
|
+
if (!content) return content;
|
|
60
|
+
let next = content;
|
|
61
|
+
for (const text of mentionTexts)next = next.replace(new RegExp(escapeRegex(text), "gi"), " ");
|
|
62
|
+
return next.replace(/<at>.*?<\/at>/gi, " ").replace(/\s+/g, " ").trim();
|
|
63
|
+
}
|
|
64
|
+
function isTeamsBotMentioned(activity, botAccountId) {
|
|
65
|
+
if (extractTeamsMentionTexts(activity, botAccountId).length > 0) return true;
|
|
66
|
+
const text = activity.text || "";
|
|
67
|
+
const recipientName = activity.recipient?.name?.trim();
|
|
68
|
+
if (recipientName) {
|
|
69
|
+
const regex = new RegExp(`<at>\\s*${escapeRegex(recipientName)}\\s*</at>`, "i");
|
|
70
|
+
return regex.test(text);
|
|
71
|
+
}
|
|
72
|
+
return false;
|
|
73
|
+
}
|
|
74
|
+
function resolveTeamsChannelSessionKey(channelId, channelSessions) {
|
|
75
|
+
if (!channelSessions) return;
|
|
76
|
+
return channelSessions[channelId];
|
|
77
|
+
}
|
|
78
|
+
function toHeaderRecord(headers) {
|
|
79
|
+
const result = {};
|
|
80
|
+
for (const [key, value] of headers.entries())result[key] = value;
|
|
81
|
+
if (!result.Authorization && result.authorization) result.Authorization = result.authorization;
|
|
82
|
+
return result;
|
|
83
|
+
}
|
|
84
|
+
function buildBotBuilderResponse(resolve) {
|
|
85
|
+
let statusCode = 200;
|
|
86
|
+
const headers = new Headers();
|
|
87
|
+
let body;
|
|
88
|
+
const finalize = (payload)=>{
|
|
89
|
+
if (void 0 !== payload) if ("string" == typeof payload) body = payload;
|
|
90
|
+
else {
|
|
91
|
+
body = JSON.stringify(payload);
|
|
92
|
+
if (!headers.get("Content-Type")) headers.set("Content-Type", "application/json");
|
|
93
|
+
}
|
|
94
|
+
resolve(new Response(body, {
|
|
95
|
+
status: statusCode,
|
|
96
|
+
headers
|
|
97
|
+
}));
|
|
98
|
+
};
|
|
99
|
+
return {
|
|
100
|
+
status (code) {
|
|
101
|
+
statusCode = code;
|
|
102
|
+
return this;
|
|
103
|
+
},
|
|
104
|
+
header (name, value) {
|
|
105
|
+
headers.set(name, value);
|
|
106
|
+
return this;
|
|
107
|
+
},
|
|
108
|
+
send (payload) {
|
|
109
|
+
finalize(payload);
|
|
110
|
+
},
|
|
111
|
+
end (payload) {
|
|
112
|
+
finalize(payload);
|
|
113
|
+
},
|
|
114
|
+
socket: {}
|
|
115
|
+
};
|
|
116
|
+
}
|
|
117
|
+
function extractTeamId(activity) {
|
|
118
|
+
const raw = activity.channelData?.team?.id;
|
|
119
|
+
if ("string" == typeof raw && raw.trim()) return raw;
|
|
120
|
+
}
|
|
121
|
+
function extractChannelId(activity) {
|
|
122
|
+
const channelId = activity.channelData?.channel?.id;
|
|
123
|
+
if ("string" == typeof channelId && channelId.trim()) return channelId;
|
|
124
|
+
const conversationId = activity.conversation?.id;
|
|
125
|
+
if ("string" == typeof conversationId && conversationId.trim()) return conversationId;
|
|
126
|
+
}
|
|
127
|
+
function extractThreadId(activity) {
|
|
128
|
+
if (activity.replyToId && activity.replyToId.trim()) return activity.replyToId;
|
|
129
|
+
const conversationId = activity.conversation?.id;
|
|
130
|
+
if (!conversationId) return;
|
|
131
|
+
const match = conversationId.match(/;messageid=([^;]+)/i);
|
|
132
|
+
if (!match?.[1]) return;
|
|
133
|
+
try {
|
|
134
|
+
return decodeURIComponent(match[1]);
|
|
135
|
+
} catch {
|
|
136
|
+
return match[1];
|
|
137
|
+
}
|
|
138
|
+
}
|
|
139
|
+
function isDirectMessage(activity) {
|
|
140
|
+
return activity.conversation?.conversationType === "personal";
|
|
141
|
+
}
|
|
142
|
+
function buildRoutingInfo(activity, botAccountId) {
|
|
143
|
+
const routing = {
|
|
144
|
+
channel: "teams",
|
|
145
|
+
accountId: botAccountId
|
|
146
|
+
};
|
|
147
|
+
const teamId = extractTeamId(activity);
|
|
148
|
+
if (teamId) routing.teamId = teamId;
|
|
149
|
+
const conversationType = activity.conversation?.conversationType;
|
|
150
|
+
if ("personal" === conversationType) {
|
|
151
|
+
const dmId = activity.from?.aadObjectId || activity.from?.id;
|
|
152
|
+
if (dmId) routing.peer = {
|
|
153
|
+
kind: "dm",
|
|
154
|
+
id: dmId
|
|
155
|
+
};
|
|
156
|
+
} else if ("groupChat" === conversationType) {
|
|
157
|
+
if (activity.conversation?.id) routing.peer = {
|
|
158
|
+
kind: "group",
|
|
159
|
+
id: activity.conversation.id
|
|
160
|
+
};
|
|
161
|
+
} else {
|
|
162
|
+
const channelId = extractChannelId(activity);
|
|
163
|
+
if (channelId) routing.peer = {
|
|
164
|
+
kind: "channel",
|
|
165
|
+
id: channelId
|
|
166
|
+
};
|
|
167
|
+
}
|
|
168
|
+
const threadId = extractThreadId(activity);
|
|
169
|
+
if (threadId) routing.threadId = threadId;
|
|
170
|
+
return routing;
|
|
171
|
+
}
|
|
172
|
+
function isBotMessage(activity) {
|
|
173
|
+
return activity.from?.role === "bot";
|
|
174
|
+
}
|
|
175
|
+
class TeamsGatewayAdapter {
|
|
176
|
+
get endpointPath() {
|
|
177
|
+
return normalizeTeamsEndpointPath(this.config.endpointPath);
|
|
178
|
+
}
|
|
179
|
+
async start() {
|
|
180
|
+
if (this.started) return;
|
|
181
|
+
if (!this.config.enabled) return;
|
|
182
|
+
if (!this.config.appId || !this.config.appPassword) return void this.logger.warn("Teams adapter enabled but Microsoft app credentials are incomplete.");
|
|
183
|
+
this.gatewayClient = new GatewayRpcClient(this.gateway.url, {
|
|
184
|
+
token: this.gateway.token,
|
|
185
|
+
password: this.gateway.password,
|
|
186
|
+
clientType: "teams"
|
|
187
|
+
});
|
|
188
|
+
await this.gatewayClient.connect();
|
|
189
|
+
const authConfig = {
|
|
190
|
+
MicrosoftAppId: this.config.appId,
|
|
191
|
+
MicrosoftAppPassword: this.config.appPassword,
|
|
192
|
+
MicrosoftAppType: this.config.appType
|
|
193
|
+
};
|
|
194
|
+
if (this.config.tenantId) authConfig.MicrosoftAppTenantId = this.config.tenantId;
|
|
195
|
+
const authentication = new ConfigurationBotFrameworkAuthentication(authConfig);
|
|
196
|
+
this.adapter = new CloudAdapter(authentication);
|
|
197
|
+
this.adapter.onTurnError = async (context, error)=>{
|
|
198
|
+
this.logger.error("Teams adapter turn error", error);
|
|
199
|
+
try {
|
|
200
|
+
await context.sendActivity("Sorry, I hit an error running that request.");
|
|
201
|
+
} catch {}
|
|
202
|
+
};
|
|
203
|
+
this.started = true;
|
|
204
|
+
}
|
|
205
|
+
async stop() {
|
|
206
|
+
if (!this.started) return;
|
|
207
|
+
this.started = false;
|
|
208
|
+
this.adapter = null;
|
|
209
|
+
if (this.gatewayClient) {
|
|
210
|
+
this.gatewayClient.disconnect();
|
|
211
|
+
this.gatewayClient = null;
|
|
212
|
+
}
|
|
213
|
+
}
|
|
214
|
+
async handleHttpRequest(req, url) {
|
|
215
|
+
if (url.pathname !== this.endpointPath) return null;
|
|
216
|
+
if ("POST" !== req.method) return new Response("Method Not Allowed", {
|
|
217
|
+
status: 405,
|
|
218
|
+
headers: {
|
|
219
|
+
Allow: "POST"
|
|
220
|
+
}
|
|
221
|
+
});
|
|
222
|
+
if (!this.started || !this.adapter || !this.gatewayClient) return new Response("Teams adapter not started", {
|
|
223
|
+
status: 503
|
|
224
|
+
});
|
|
225
|
+
const adapter = this.adapter;
|
|
226
|
+
let body;
|
|
227
|
+
try {
|
|
228
|
+
body = await req.json();
|
|
229
|
+
} catch {
|
|
230
|
+
return new Response("Invalid JSON payload", {
|
|
231
|
+
status: 400
|
|
232
|
+
});
|
|
233
|
+
}
|
|
234
|
+
const activity = body;
|
|
235
|
+
return new Promise((resolve)=>{
|
|
236
|
+
const response = buildBotBuilderResponse(resolve);
|
|
237
|
+
adapter.process({
|
|
238
|
+
method: req.method,
|
|
239
|
+
headers: toHeaderRecord(req.headers),
|
|
240
|
+
body: activity
|
|
241
|
+
}, response, async (context)=>this.handleMessage(context)).catch((error)=>{
|
|
242
|
+
this.logger.error("Teams adapter failed to process request", error);
|
|
243
|
+
resolve(new Response("Failed to process Teams request", {
|
|
244
|
+
status: 500
|
|
245
|
+
}));
|
|
246
|
+
});
|
|
247
|
+
});
|
|
248
|
+
}
|
|
249
|
+
async handleMessage(context) {
|
|
250
|
+
if (!this.gatewayClient) return;
|
|
251
|
+
const activity = context.activity;
|
|
252
|
+
if ("message" !== activity.type) return;
|
|
253
|
+
if (!activity.text && !activity.attachments?.length) return;
|
|
254
|
+
if (isBotMessage(activity)) {
|
|
255
|
+
if (!this.config.allowBots) return;
|
|
256
|
+
if (activity.from?.id && activity.from.id === activity.recipient?.id) return;
|
|
257
|
+
}
|
|
258
|
+
const teamId = extractTeamId(activity);
|
|
259
|
+
if (this.config.allowedTeamIds.length > 0 && teamId) {
|
|
260
|
+
if (!this.config.allowedTeamIds.includes(teamId)) return;
|
|
261
|
+
}
|
|
262
|
+
const channelId = extractChannelId(activity);
|
|
263
|
+
if (this.config.allowedChannelIds.length > 0) {
|
|
264
|
+
if (!channelId || !this.config.allowedChannelIds.includes(channelId)) return;
|
|
265
|
+
}
|
|
266
|
+
const botAccountId = activity.recipient?.id || this.config.appId;
|
|
267
|
+
if (this.config.mentionOnly && !isDirectMessage(activity) && !isTeamsBotMentioned(activity, botAccountId)) return;
|
|
268
|
+
const mentionTexts = extractTeamsMentionTexts(activity, botAccountId);
|
|
269
|
+
const cleaned = stripTeamsBotMention(activity.text || "", mentionTexts);
|
|
270
|
+
const attachments = (activity.attachments || []).map((attachment)=>attachment.contentUrl).filter((url)=>Boolean(url));
|
|
271
|
+
const attachmentText = attachments.length > 0 ? `\n\nAttachments:\n${attachments.map((url)=>`- ${url}`).join("\n")}` : "";
|
|
272
|
+
let content = `${cleaned}${attachmentText}`.trim();
|
|
273
|
+
const { sessionKey, content: nextContent, matched } = extractSessionOverride(content, this.config.sessionCommand);
|
|
274
|
+
let resolvedSessionKey = sessionKey;
|
|
275
|
+
let usedChannelMapping = false;
|
|
276
|
+
if (matched) {
|
|
277
|
+
content = nextContent.trim();
|
|
278
|
+
if (!sessionKey) return void await context.sendActivity(`Provide a session key after \`${this.config.sessionCommand}\`.`);
|
|
279
|
+
}
|
|
280
|
+
if (!matched && channelId) {
|
|
281
|
+
resolvedSessionKey = resolveTeamsChannelSessionKey(channelId, this.config.channelSessions);
|
|
282
|
+
usedChannelMapping = Boolean(resolvedSessionKey);
|
|
283
|
+
}
|
|
284
|
+
const inferredAgentId = parseAgentIdFromSessionKey(resolvedSessionKey);
|
|
285
|
+
if (usedChannelMapping && !inferredAgentId) this.logger.warn(`Teams channel session mapping for channel ${channelId} does not include an agent prefix. Use "agent:<id>:..." to auto-select an agent.`, {
|
|
286
|
+
sessionKey: resolvedSessionKey
|
|
287
|
+
});
|
|
288
|
+
if (!content) return;
|
|
289
|
+
const payload = {
|
|
290
|
+
agentId: inferredAgentId,
|
|
291
|
+
content,
|
|
292
|
+
routing: buildRoutingInfo(activity, botAccountId),
|
|
293
|
+
sessionKey: resolvedSessionKey
|
|
294
|
+
};
|
|
295
|
+
try {
|
|
296
|
+
await context.sendActivity({
|
|
297
|
+
type: "typing"
|
|
298
|
+
});
|
|
299
|
+
let fallbackText = "";
|
|
300
|
+
let uiFallbackText = "";
|
|
301
|
+
let uiOnlyDetected = false;
|
|
302
|
+
const textByMessageId = new Map();
|
|
303
|
+
const messageOrder = [];
|
|
304
|
+
await this.gatewayClient.requestAgent(payload, (event)=>{
|
|
305
|
+
if (!event || "object" != typeof event) return;
|
|
306
|
+
if ("agent-error" === event.type) {
|
|
307
|
+
fallbackText += `\n${event.error || "Agent error"}`;
|
|
308
|
+
return;
|
|
309
|
+
}
|
|
310
|
+
if ("agent-stream" !== event.type) return;
|
|
311
|
+
const parsedChunks = parseStreamChunk(event.chunk);
|
|
312
|
+
for (const chunk of parsedChunks){
|
|
313
|
+
if ("tool-result" === chunk.type && chunk.toolResult?.output) {
|
|
314
|
+
const meta = extractUiMeta(chunk.toolResult.output);
|
|
315
|
+
if (true === meta.uiOnly) uiOnlyDetected = true;
|
|
316
|
+
if (meta.textFallback) uiFallbackText = meta.textFallback;
|
|
317
|
+
}
|
|
318
|
+
if ("text" === chunk.type && chunk.text) {
|
|
319
|
+
if (chunk.messageId) {
|
|
320
|
+
if (!textByMessageId.has(chunk.messageId)) {
|
|
321
|
+
messageOrder.push(chunk.messageId);
|
|
322
|
+
textByMessageId.set(chunk.messageId, chunk.text);
|
|
323
|
+
continue;
|
|
324
|
+
}
|
|
325
|
+
const current = textByMessageId.get(chunk.messageId) || "";
|
|
326
|
+
textByMessageId.set(chunk.messageId, chunk.isDelta ? current + chunk.text : chunk.text);
|
|
327
|
+
continue;
|
|
328
|
+
}
|
|
329
|
+
fallbackText += chunk.text;
|
|
330
|
+
}
|
|
331
|
+
}
|
|
332
|
+
});
|
|
333
|
+
const orderedText = messageOrder.map((id)=>textByMessageId.get(id)).filter((value)=>Boolean(value)).join("\n\n");
|
|
334
|
+
let responseText = `${fallbackText}${fallbackText && orderedText ? "\n\n" : ""}${orderedText}`.trim();
|
|
335
|
+
if (uiFallbackText && (uiOnlyDetected || !responseText)) responseText = uiFallbackText.trim();
|
|
336
|
+
if (!responseText) return;
|
|
337
|
+
const chunks = splitTeamsMessage(responseText, this.config.responseChunkSize);
|
|
338
|
+
for (const chunk of chunks)await context.sendActivity(chunk);
|
|
339
|
+
} catch (error) {
|
|
340
|
+
this.logger.error("Teams adapter failed to handle message", error);
|
|
341
|
+
try {
|
|
342
|
+
await context.sendActivity("Sorry, I hit an error running that request.");
|
|
343
|
+
} catch {}
|
|
344
|
+
}
|
|
345
|
+
}
|
|
346
|
+
constructor(config, gateway, logger){
|
|
347
|
+
_define_property(this, "config", void 0);
|
|
348
|
+
_define_property(this, "gateway", void 0);
|
|
349
|
+
_define_property(this, "adapter", void 0);
|
|
350
|
+
_define_property(this, "gatewayClient", void 0);
|
|
351
|
+
_define_property(this, "logger", void 0);
|
|
352
|
+
_define_property(this, "started", void 0);
|
|
353
|
+
this.config = config;
|
|
354
|
+
this.gateway = gateway;
|
|
355
|
+
this.adapter = null;
|
|
356
|
+
this.gatewayClient = null;
|
|
357
|
+
this.started = false;
|
|
358
|
+
this.logger = logger || createLogger();
|
|
359
|
+
}
|
|
360
|
+
}
|
|
361
|
+
export { DEFAULT_TEAMS_ENDPOINT_PATH, DEFAULT_TEAMS_RESPONSE_CHUNK, TeamsGatewayAdapter, extractTeamsMentionTexts, isTeamsBotMentioned, normalizeTeamsEndpointPath, resolveTeamsChannelSessionKey, splitTeamsMessage, stripTeamsBotMention };
|
|
@@ -0,0 +1,286 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __webpack_require__ = {};
|
|
3
|
+
(()=>{
|
|
4
|
+
__webpack_require__.d = (exports1, definition)=>{
|
|
5
|
+
for(var key in definition)if (__webpack_require__.o(definition, key) && !__webpack_require__.o(exports1, key)) Object.defineProperty(exports1, key, {
|
|
6
|
+
enumerable: true,
|
|
7
|
+
get: definition[key]
|
|
8
|
+
});
|
|
9
|
+
};
|
|
10
|
+
})();
|
|
11
|
+
(()=>{
|
|
12
|
+
__webpack_require__.o = (obj, prop)=>Object.prototype.hasOwnProperty.call(obj, prop);
|
|
13
|
+
})();
|
|
14
|
+
(()=>{
|
|
15
|
+
__webpack_require__.r = (exports1)=>{
|
|
16
|
+
if ("u" > typeof Symbol && Symbol.toStringTag) Object.defineProperty(exports1, Symbol.toStringTag, {
|
|
17
|
+
value: 'Module'
|
|
18
|
+
});
|
|
19
|
+
Object.defineProperty(exports1, '__esModule', {
|
|
20
|
+
value: true
|
|
21
|
+
});
|
|
22
|
+
};
|
|
23
|
+
})();
|
|
24
|
+
var __webpack_exports__ = {};
|
|
25
|
+
__webpack_require__.r(__webpack_exports__);
|
|
26
|
+
__webpack_require__.d(__webpack_exports__, {
|
|
27
|
+
handleSmsApi: ()=>handleSmsApi,
|
|
28
|
+
createSmsPolicyStateStore: ()=>createSmsPolicyStateStore
|
|
29
|
+
});
|
|
30
|
+
const control_cjs_namespaceObject = require("../sms/control.cjs");
|
|
31
|
+
const policyStore_cjs_namespaceObject = require("../sms/policyStore.cjs");
|
|
32
|
+
const MAX_PAUSE_FOR_MS = 2592000000;
|
|
33
|
+
const createSmsPolicyStateStore = (resolveConfigDirPath)=>(0, policyStore_cjs_namespaceObject.createSmsPolicyStore)(resolveConfigDirPath);
|
|
34
|
+
function decodeTarget(raw) {
|
|
35
|
+
let decoded = "";
|
|
36
|
+
try {
|
|
37
|
+
decoded = decodeURIComponent(raw);
|
|
38
|
+
} catch {
|
|
39
|
+
return null;
|
|
40
|
+
}
|
|
41
|
+
return (0, policyStore_cjs_namespaceObject.normalizeSmsPolicyTarget)(decoded);
|
|
42
|
+
}
|
|
43
|
+
function parsePauseForMs(raw) {
|
|
44
|
+
if ("number" != typeof raw || !Number.isFinite(raw)) return null;
|
|
45
|
+
const value = Math.trunc(raw);
|
|
46
|
+
if (value <= 0 || value > MAX_PAUSE_FOR_MS) return null;
|
|
47
|
+
return value;
|
|
48
|
+
}
|
|
49
|
+
function toResponsePayload(resolution, nowMs) {
|
|
50
|
+
return {
|
|
51
|
+
...resolution,
|
|
52
|
+
policy: {
|
|
53
|
+
...resolution.policy,
|
|
54
|
+
pauseExpiresInMs: resolution.policy.paused && resolution.policy.pausedUntil ? Math.max(resolution.policy.pausedUntil - nowMs, 0) : null
|
|
55
|
+
}
|
|
56
|
+
};
|
|
57
|
+
}
|
|
58
|
+
function parseRoutingTarget(rawTarget) {
|
|
59
|
+
const trimmed = rawTarget.trim();
|
|
60
|
+
if (!trimmed) return null;
|
|
61
|
+
const normalized = (0, policyStore_cjs_namespaceObject.normalizeSmsPolicyTarget)(trimmed);
|
|
62
|
+
if (!normalized) return null;
|
|
63
|
+
const separatorIndex = normalized.indexOf(":");
|
|
64
|
+
let channel = "sms-macos";
|
|
65
|
+
let peerId = normalized;
|
|
66
|
+
if (separatorIndex > 0 && separatorIndex < normalized.length - 1) {
|
|
67
|
+
const candidateChannel = normalized.slice(0, separatorIndex).trim();
|
|
68
|
+
const candidatePeer = normalized.slice(separatorIndex + 1).trim();
|
|
69
|
+
if (candidateChannel && candidatePeer) {
|
|
70
|
+
channel = candidateChannel;
|
|
71
|
+
peerId = candidatePeer;
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
return {
|
|
75
|
+
normalizedTarget: normalized,
|
|
76
|
+
routing: {
|
|
77
|
+
channel,
|
|
78
|
+
peer: {
|
|
79
|
+
kind: "dm",
|
|
80
|
+
id: peerId
|
|
81
|
+
}
|
|
82
|
+
}
|
|
83
|
+
};
|
|
84
|
+
}
|
|
85
|
+
const handleSmsApi = async (ctx, store, req, url)=>{
|
|
86
|
+
if ("/api/sms/messages" === url.pathname) {
|
|
87
|
+
if ("POST" !== req.method) return new Response("Method Not Allowed", {
|
|
88
|
+
status: 405
|
|
89
|
+
});
|
|
90
|
+
let body;
|
|
91
|
+
try {
|
|
92
|
+
body = await req.json();
|
|
93
|
+
} catch {
|
|
94
|
+
return new Response("Invalid JSON body", {
|
|
95
|
+
status: 400
|
|
96
|
+
});
|
|
97
|
+
}
|
|
98
|
+
const parsed = parseRoutingTarget("string" == typeof body.target ? body.target : "");
|
|
99
|
+
if (!parsed) return new Response("valid target required", {
|
|
100
|
+
status: 400
|
|
101
|
+
});
|
|
102
|
+
const nowMs = Date.now();
|
|
103
|
+
const text = "string" == typeof body.text ? body.text : "";
|
|
104
|
+
const control = (0, control_cjs_namespaceObject.applySmsControlCommand)({
|
|
105
|
+
store,
|
|
106
|
+
target: parsed.normalizedTarget,
|
|
107
|
+
text,
|
|
108
|
+
nowMs
|
|
109
|
+
});
|
|
110
|
+
if (control.handled) return new Response(JSON.stringify({
|
|
111
|
+
kind: "command",
|
|
112
|
+
...toResponsePayload(control, nowMs)
|
|
113
|
+
}, null, 2), {
|
|
114
|
+
headers: {
|
|
115
|
+
"Content-Type": "application/json"
|
|
116
|
+
}
|
|
117
|
+
});
|
|
118
|
+
if (!control.passThroughText.trim()) return new Response("text required", {
|
|
119
|
+
status: 400
|
|
120
|
+
});
|
|
121
|
+
if (control.policy.stopEnabled) return new Response(JSON.stringify({
|
|
122
|
+
kind: "stopped",
|
|
123
|
+
responseText: "SMS chat is stopped for this sender. Re-enable in Wingman settings/API.",
|
|
124
|
+
policy: control.policy
|
|
125
|
+
}, null, 2), {
|
|
126
|
+
headers: {
|
|
127
|
+
"Content-Type": "application/json"
|
|
128
|
+
}
|
|
129
|
+
});
|
|
130
|
+
const routing = {
|
|
131
|
+
...parsed.routing
|
|
132
|
+
};
|
|
133
|
+
if ("string" == typeof body.accountId && body.accountId.trim()) routing.accountId = body.accountId.trim();
|
|
134
|
+
if ("string" == typeof body.threadId && body.threadId.trim()) routing.threadId = body.threadId.trim();
|
|
135
|
+
const selectedAgentId = ctx.router.selectAgent("string" == typeof body.agentId ? body.agentId.trim() : void 0, routing);
|
|
136
|
+
if (!selectedAgentId) return new Response("Unable to resolve agent", {
|
|
137
|
+
status: 400
|
|
138
|
+
});
|
|
139
|
+
const explicitSessionKey = "string" == typeof body.sessionKey ? body.sessionKey.trim() : "";
|
|
140
|
+
const sessionKey = explicitSessionKey || ctx.router.buildSessionKey(selectedAgentId, routing);
|
|
141
|
+
const request = {
|
|
142
|
+
agentId: selectedAgentId,
|
|
143
|
+
content: control.passThroughText,
|
|
144
|
+
routing,
|
|
145
|
+
sessionKey
|
|
146
|
+
};
|
|
147
|
+
if ("boolean" == typeof body.queueIfBusy) request.queueIfBusy = body.queueIfBusy;
|
|
148
|
+
return new Response(JSON.stringify({
|
|
149
|
+
kind: "agent",
|
|
150
|
+
target: parsed.normalizedTarget,
|
|
151
|
+
policy: control.policy,
|
|
152
|
+
request
|
|
153
|
+
}, null, 2), {
|
|
154
|
+
headers: {
|
|
155
|
+
"Content-Type": "application/json"
|
|
156
|
+
}
|
|
157
|
+
});
|
|
158
|
+
}
|
|
159
|
+
if ("/api/sms/policies" === url.pathname && "GET" === req.method) {
|
|
160
|
+
const targetRaw = url.searchParams.get("target");
|
|
161
|
+
if (targetRaw) {
|
|
162
|
+
const target = (0, policyStore_cjs_namespaceObject.normalizeSmsPolicyTarget)(targetRaw);
|
|
163
|
+
if (!target) return new Response("valid target query required", {
|
|
164
|
+
status: 400
|
|
165
|
+
});
|
|
166
|
+
const record = store.resolve(target);
|
|
167
|
+
return new Response(JSON.stringify(record, null, 2), {
|
|
168
|
+
headers: {
|
|
169
|
+
"Content-Type": "application/json"
|
|
170
|
+
}
|
|
171
|
+
});
|
|
172
|
+
}
|
|
173
|
+
const policies = store.list();
|
|
174
|
+
return new Response(JSON.stringify({
|
|
175
|
+
policies
|
|
176
|
+
}, null, 2), {
|
|
177
|
+
headers: {
|
|
178
|
+
"Content-Type": "application/json"
|
|
179
|
+
}
|
|
180
|
+
});
|
|
181
|
+
}
|
|
182
|
+
const commandMatch = url.pathname.match(/^\/api\/sms\/policies\/([^/]+)\/command$/);
|
|
183
|
+
if (commandMatch) {
|
|
184
|
+
if ("POST" !== req.method) return new Response("Method Not Allowed", {
|
|
185
|
+
status: 405
|
|
186
|
+
});
|
|
187
|
+
const target = decodeTarget(commandMatch[1]);
|
|
188
|
+
if (!target) return new Response("valid target required", {
|
|
189
|
+
status: 400
|
|
190
|
+
});
|
|
191
|
+
let body;
|
|
192
|
+
try {
|
|
193
|
+
body = await req.json();
|
|
194
|
+
} catch {
|
|
195
|
+
return new Response("Invalid JSON body", {
|
|
196
|
+
status: 400
|
|
197
|
+
});
|
|
198
|
+
}
|
|
199
|
+
const text = "string" == typeof body.text ? body.text : "";
|
|
200
|
+
const nowMs = "number" == typeof body.nowMs && Number.isFinite(body.nowMs) ? Math.trunc(body.nowMs) : Date.now();
|
|
201
|
+
const result = (0, control_cjs_namespaceObject.applySmsControlCommand)({
|
|
202
|
+
store,
|
|
203
|
+
target,
|
|
204
|
+
text,
|
|
205
|
+
nowMs
|
|
206
|
+
});
|
|
207
|
+
return new Response(JSON.stringify(toResponsePayload(result, nowMs), null, 2), {
|
|
208
|
+
headers: {
|
|
209
|
+
"Content-Type": "application/json"
|
|
210
|
+
}
|
|
211
|
+
});
|
|
212
|
+
}
|
|
213
|
+
const targetMatch = url.pathname.match(/^\/api\/sms\/policies\/([^/]+)$/);
|
|
214
|
+
if (!targetMatch) return null;
|
|
215
|
+
const target = decodeTarget(targetMatch[1]);
|
|
216
|
+
if (!target) return new Response("valid target required", {
|
|
217
|
+
status: 400
|
|
218
|
+
});
|
|
219
|
+
if ("GET" === req.method) return new Response(JSON.stringify(store.resolve(target), null, 2), {
|
|
220
|
+
headers: {
|
|
221
|
+
"Content-Type": "application/json"
|
|
222
|
+
}
|
|
223
|
+
});
|
|
224
|
+
if ("DELETE" === req.method) {
|
|
225
|
+
store.reset(target);
|
|
226
|
+
return new Response(JSON.stringify(store.resolve(target), null, 2), {
|
|
227
|
+
headers: {
|
|
228
|
+
"Content-Type": "application/json"
|
|
229
|
+
}
|
|
230
|
+
});
|
|
231
|
+
}
|
|
232
|
+
if ("PUT" !== req.method) return new Response("Method Not Allowed", {
|
|
233
|
+
status: 405
|
|
234
|
+
});
|
|
235
|
+
let body;
|
|
236
|
+
try {
|
|
237
|
+
body = await req.json();
|
|
238
|
+
} catch {
|
|
239
|
+
return new Response("Invalid JSON body", {
|
|
240
|
+
status: 400
|
|
241
|
+
});
|
|
242
|
+
}
|
|
243
|
+
const patch = {};
|
|
244
|
+
const hasPauseForMs = Object.hasOwn(body ?? {}, "pauseForMs");
|
|
245
|
+
if (hasPauseForMs) {
|
|
246
|
+
const duration = parsePauseForMs(body.pauseForMs);
|
|
247
|
+
if (null === duration) return new Response("pauseForMs must be a positive duration", {
|
|
248
|
+
status: 400
|
|
249
|
+
});
|
|
250
|
+
const nowMs = Date.now();
|
|
251
|
+
patch.paused = true;
|
|
252
|
+
patch.pausedUntil = nowMs + duration;
|
|
253
|
+
}
|
|
254
|
+
if ("boolean" == typeof body.paused) patch.paused = body.paused;
|
|
255
|
+
if (Object.hasOwn(body ?? {}, "pausedUntil")) {
|
|
256
|
+
const value = body.pausedUntil;
|
|
257
|
+
if (null === value) {
|
|
258
|
+
patch.paused = false;
|
|
259
|
+
patch.pausedUntil = null;
|
|
260
|
+
} else {
|
|
261
|
+
if (!("number" == typeof value && Number.isFinite(value))) return new Response("pausedUntil must be a number or null", {
|
|
262
|
+
status: 400
|
|
263
|
+
});
|
|
264
|
+
patch.paused = true;
|
|
265
|
+
patch.pausedUntil = Math.trunc(value);
|
|
266
|
+
}
|
|
267
|
+
}
|
|
268
|
+
if ("boolean" == typeof body.stopEnabled) patch.stopEnabled = body.stopEnabled;
|
|
269
|
+
if ("off" === body.alertMode || "important-only" === body.alertMode || "all" === body.alertMode) patch.alertMode = body.alertMode;
|
|
270
|
+
if (Object.hasOwn(body ?? {}, "quietHours")) patch.quietHours = body.quietHours ?? null;
|
|
271
|
+
const updated = store.upsert(target, patch);
|
|
272
|
+
return new Response(JSON.stringify(updated, null, 2), {
|
|
273
|
+
headers: {
|
|
274
|
+
"Content-Type": "application/json"
|
|
275
|
+
}
|
|
276
|
+
});
|
|
277
|
+
};
|
|
278
|
+
exports.createSmsPolicyStateStore = __webpack_exports__.createSmsPolicyStateStore;
|
|
279
|
+
exports.handleSmsApi = __webpack_exports__.handleSmsApi;
|
|
280
|
+
for(var __rspack_i in __webpack_exports__)if (-1 === [
|
|
281
|
+
"createSmsPolicyStateStore",
|
|
282
|
+
"handleSmsApi"
|
|
283
|
+
].indexOf(__rspack_i)) exports[__rspack_i] = __webpack_exports__[__rspack_i];
|
|
284
|
+
Object.defineProperty(exports, '__esModule', {
|
|
285
|
+
value: true
|
|
286
|
+
});
|
|
@@ -0,0 +1,4 @@
|
|
|
1
|
+
import { type SmsPolicyStore } from "../sms/policyStore.js";
|
|
2
|
+
import type { GatewayHttpContext } from "./types.js";
|
|
3
|
+
export declare const createSmsPolicyStateStore: (resolveConfigDirPath: () => string) => SmsPolicyStore;
|
|
4
|
+
export declare const handleSmsApi: (ctx: GatewayHttpContext, store: SmsPolicyStore, req: Request, url: URL) => Promise<Response | null>;
|