@openclaw/msteams 2026.5.30-beta.1 → 2026.5.31-beta.1
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/dist/api.js +2 -2
- package/dist/{channel-I5mMZ1Ju.js → channel-CqRTzeBc.js} +5 -5
- package/dist/channel-plugin-api.js +1 -1
- package/dist/{channel.runtime-Cg8XWuDW.js → channel.runtime-C38epVZr.js} +4 -4
- package/dist/doctor-contract-api.js +171 -0
- package/dist/{errors-HUt6we-U.js → errors-Dpn8B05h.js} +1 -1
- package/dist/{probe-MGBfnHCR.js → probe-DMNefdBZ.js} +195 -55
- package/dist/setup-plugin-api.js +2 -2
- package/dist/{setup-surface-BLAlJzog.js → setup-surface-B7a1pD-K.js} +1 -1
- package/dist/{src-hH0j_Pt1.js → src-B6CFMcvV.js} +79 -69
- package/node_modules/es-object-atoms/CHANGELOG.md +21 -14
- package/node_modules/es-object-atoms/isObject.d.ts +1 -1
- package/node_modules/es-object-atoms/package.json +6 -7
- package/node_modules/es-object-atoms/tsconfig.json +1 -0
- package/node_modules/hasown/CHANGELOG.md +7 -0
- package/node_modules/hasown/index.d.ts +0 -1
- package/node_modules/hasown/package.json +4 -5
- package/node_modules/typebox/build/type/script/mapping.d.mts +5 -2
- package/node_modules/typebox/build/type/script/mapping.mjs +15 -8
- package/node_modules/typebox/build/type/script/parser.d.mts +3 -1
- package/node_modules/typebox/build/type/script/parser.mjs +2 -1
- package/node_modules/typebox/package.json +29 -29
- package/npm-shrinkwrap.json +13 -13
- package/package.json +5 -5
package/dist/api.js
CHANGED
|
@@ -1,3 +1,3 @@
|
|
|
1
|
-
import { i as msteamsSetupAdapter, n as openDelegatedOAuthUrl, r as createMSTeamsSetupWizardBase, t as msteamsSetupWizard } from "./setup-surface-
|
|
2
|
-
import { t as msteamsPlugin } from "./channel-
|
|
1
|
+
import { i as msteamsSetupAdapter, n as openDelegatedOAuthUrl, r as createMSTeamsSetupWizardBase, t as msteamsSetupWizard } from "./setup-surface-B7a1pD-K.js";
|
|
2
|
+
import { t as msteamsPlugin } from "./channel-CqRTzeBc.js";
|
|
3
3
|
export { createMSTeamsSetupWizardBase, msteamsPlugin, msteamsSetupAdapter, msteamsSetupWizard, openDelegatedOAuthUrl };
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { O as resolveNestedAllowlistDecision, S as normalizeChannelSlug, T as resolveChannelEntryMatchWithFallback, _ as isDangerousNameMatchingEnabled, i as buildChannelKeyCandidates, k as resolveToolsBySender, o as buildProbeChannelStatusSummary, r as PAIRING_APPROVED_MESSAGE, s as chunkTextForOutbound, t as DEFAULT_ACCOUNT_ID, u as createDefaultChannelRuntimeState, w as resolveAllowlistMatchSimple } from "./runtime-api-BlvMnDKz.js";
|
|
2
|
-
import { y as resolveMSTeamsCredentials } from "./errors-
|
|
3
|
-
import { a as looksLikeMSTeamsTargetId, c as parseMSTeamsConversationId, d as resolveMSTeamsUserAllowlist, i as msteamsSetupAdapter, l as parseMSTeamsTeamChannelInput, o as normalizeMSTeamsMessagingTarget, s as normalizeMSTeamsUserInput, t as msteamsSetupWizard, u as resolveMSTeamsChannelAllowlist } from "./setup-surface-
|
|
2
|
+
import { y as resolveMSTeamsCredentials } from "./errors-Dpn8B05h.js";
|
|
3
|
+
import { a as looksLikeMSTeamsTargetId, c as parseMSTeamsConversationId, d as resolveMSTeamsUserAllowlist, i as msteamsSetupAdapter, l as parseMSTeamsTeamChannelInput, o as normalizeMSTeamsMessagingTarget, s as normalizeMSTeamsUserInput, t as msteamsSetupWizard, u as resolveMSTeamsChannelAllowlist } from "./setup-surface-B7a1pD-K.js";
|
|
4
4
|
import { t as MSTeamsChannelConfigSchema } from "./config-schema-BL4qQZiA.js";
|
|
5
5
|
import { describeAccountSnapshot } from "openclaw/plugin-sdk/account-helpers";
|
|
6
6
|
import { formatAllowFromLowercase } from "openclaw/plugin-sdk/allow-from";
|
|
@@ -283,7 +283,7 @@ function buildMSTeamsPresentationCard(params) {
|
|
|
283
283
|
//#endregion
|
|
284
284
|
//#region extensions/msteams/src/session-route.ts
|
|
285
285
|
function resolveMSTeamsOutboundSessionRoute(params) {
|
|
286
|
-
|
|
286
|
+
const trimmed = stripChannelTargetPrefix(params.target, "msteams", "teams");
|
|
287
287
|
if (!trimmed) return null;
|
|
288
288
|
const isUser = normalizeLowercaseStringOrEmpty(trimmed).startsWith("user:");
|
|
289
289
|
const rawId = stripTargetKindPrefix(trimmed);
|
|
@@ -330,7 +330,7 @@ const collectMSTeamsSecurityWarnings = createAllowlistProviderGroupPolicyWarning
|
|
|
330
330
|
resolveGroupPolicy: ({ cfg }) => cfg.channels?.msteams?.groupPolicy,
|
|
331
331
|
collect: ({ groupPolicy }) => groupPolicy === "open" ? ["- MS Teams groups: groupPolicy=\"open\" allows any member to trigger (mention-gated). Set channels.msteams.groupPolicy=\"allowlist\" + channels.msteams.groupAllowFrom to restrict senders."] : []
|
|
332
332
|
});
|
|
333
|
-
const loadMSTeamsChannelRuntime = createLazyRuntimeNamedExport(() => import("./channel.runtime-
|
|
333
|
+
const loadMSTeamsChannelRuntime = createLazyRuntimeNamedExport(() => import("./channel.runtime-C38epVZr.js"), "msTeamsChannelRuntime");
|
|
334
334
|
const resolveMSTeamsChannelConfig = (cfg) => ({
|
|
335
335
|
allowFrom: cfg.channels?.msteams?.allowFrom,
|
|
336
336
|
defaultTo: cfg.channels?.msteams?.defaultTo
|
|
@@ -1116,7 +1116,7 @@ const msteamsPlugin = createChatChannelPlugin({
|
|
|
1116
1116
|
})
|
|
1117
1117
|
}),
|
|
1118
1118
|
gateway: { startAccount: async (ctx) => {
|
|
1119
|
-
const { monitorMSTeamsProvider } = await import("./src-
|
|
1119
|
+
const { monitorMSTeamsProvider } = await import("./src-B6CFMcvV.js");
|
|
1120
1120
|
const port = ctx.cfg.channels?.msteams?.webhook?.port ?? 3978;
|
|
1121
1121
|
ctx.setStatus({
|
|
1122
1122
|
accountId: ctx.accountId,
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import { t as msteamsPlugin } from "./channel-
|
|
1
|
+
import { t as msteamsPlugin } from "./channel-CqRTzeBc.js";
|
|
2
2
|
export { msteamsPlugin };
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { C as normalizeStringEntries$1, s as chunkTextForOutbound } from "./runtime-api-BlvMnDKz.js";
|
|
2
|
-
import { a as searchGraphUsers, c as fetchGraphAbsoluteUrl, d as listTeamsByName, f as normalizeQuery, g as resolveGraphToken, h as postGraphJson, l as fetchGraphJson, m as postGraphBetaJson, o as deleteGraphRequest, p as patchGraphJson, s as escapeOData, u as listChannelsForTeam } from "./errors-
|
|
3
|
-
import { n as MSTEAMS_PRESENTATION_CAPABILITIES, r as buildMSTeamsPresentationCard } from "./channel-
|
|
4
|
-
import { S as createMSTeamsConversationStoreState, a as sendMessageMSTeams, b as createMSTeamsPollStoreState, i as sendAdaptiveCardMSTeams, n as deleteMessageMSTeams, o as sendPollMSTeams, r as editMessageMSTeams, t as probeMSTeams } from "./probe-
|
|
2
|
+
import { a as searchGraphUsers, c as fetchGraphAbsoluteUrl, d as listTeamsByName, f as normalizeQuery, g as resolveGraphToken, h as postGraphJson, l as fetchGraphJson, m as postGraphBetaJson, o as deleteGraphRequest, p as patchGraphJson, s as escapeOData, u as listChannelsForTeam } from "./errors-Dpn8B05h.js";
|
|
3
|
+
import { n as MSTEAMS_PRESENTATION_CAPABILITIES, r as buildMSTeamsPresentationCard } from "./channel-CqRTzeBc.js";
|
|
4
|
+
import { S as createMSTeamsConversationStoreState, a as sendMessageMSTeams, b as createMSTeamsPollStoreState, i as sendAdaptiveCardMSTeams, n as deleteMessageMSTeams, o as sendPollMSTeams, r as editMessageMSTeams, t as probeMSTeams } from "./probe-DMNefdBZ.js";
|
|
5
5
|
import { resolveOutboundSendDep } from "openclaw/plugin-sdk/channel-outbound";
|
|
6
6
|
import { normalizeLowercaseStringOrEmpty, normalizeStringEntries } from "openclaw/plugin-sdk/string-coerce-runtime";
|
|
7
7
|
import { resolvePayloadMediaUrls, resolveTextChunksWithFallback, sendPayloadMediaSequence } from "openclaw/plugin-sdk/reply-payload";
|
|
@@ -473,7 +473,7 @@ async function listChannelsMSTeams(params) {
|
|
|
473
473
|
description: ch.description,
|
|
474
474
|
membershipType: ch.membershipType
|
|
475
475
|
})),
|
|
476
|
-
truncated:
|
|
476
|
+
truncated: Boolean(nextPath)
|
|
477
477
|
};
|
|
478
478
|
}
|
|
479
479
|
/**
|
|
@@ -0,0 +1,171 @@
|
|
|
1
|
+
import path from "node:path";
|
|
2
|
+
import crypto from "node:crypto";
|
|
3
|
+
import fs from "node:fs/promises";
|
|
4
|
+
import { resolveStorePath } from "openclaw/plugin-sdk/session-store-runtime";
|
|
5
|
+
//#region extensions/msteams/doctor-contract-api.ts
|
|
6
|
+
const LEARNINGS_NAMESPACE = "feedback-learnings";
|
|
7
|
+
const MAX_LEARNING_ENTRIES = 1e4;
|
|
8
|
+
function encodeSessionKey(sessionKey) {
|
|
9
|
+
return Buffer.from(sessionKey, "utf8").toString("base64url");
|
|
10
|
+
}
|
|
11
|
+
function learningStoreKey(storePath, sessionKey) {
|
|
12
|
+
return crypto.createHash("sha256").update(`${storePath}\0${sessionKey}`, "utf8").digest("hex");
|
|
13
|
+
}
|
|
14
|
+
function decodeSessionKey(fileStem) {
|
|
15
|
+
try {
|
|
16
|
+
const decoded = Buffer.from(fileStem, "base64url").toString("utf8");
|
|
17
|
+
return encodeSessionKey(decoded) === fileStem && decoded.trim() ? decoded : null;
|
|
18
|
+
} catch {
|
|
19
|
+
return null;
|
|
20
|
+
}
|
|
21
|
+
}
|
|
22
|
+
function resolveLearningSessionKey(fileStem) {
|
|
23
|
+
return decodeSessionKey(fileStem);
|
|
24
|
+
}
|
|
25
|
+
function legacySanitizeSessionKey(sessionKey) {
|
|
26
|
+
return sessionKey.replace(/[^a-zA-Z0-9_-]/g, "_");
|
|
27
|
+
}
|
|
28
|
+
async function listKnownSessionKeys(storePath) {
|
|
29
|
+
const candidates = [storePath, path.join(storePath, "sessions.json")];
|
|
30
|
+
for (const candidate of candidates) try {
|
|
31
|
+
const parsed = JSON.parse(await fs.readFile(candidate, "utf8"));
|
|
32
|
+
if (!parsed || typeof parsed !== "object" || Array.isArray(parsed)) continue;
|
|
33
|
+
const sessions = parsed.sessions && typeof parsed.sessions === "object" && !Array.isArray(parsed.sessions) ? parsed.sessions : parsed;
|
|
34
|
+
return Object.keys(sessions).filter((key) => key.trim());
|
|
35
|
+
} catch {}
|
|
36
|
+
return [];
|
|
37
|
+
}
|
|
38
|
+
function resolveLegacySanitizedSessionKey(fileStem, knownSessionKeys) {
|
|
39
|
+
const matches = knownSessionKeys.filter((sessionKey) => legacySanitizeSessionKey(sessionKey) === fileStem);
|
|
40
|
+
return matches.length === 1 ? matches[0] : null;
|
|
41
|
+
}
|
|
42
|
+
function listAgentIds(config) {
|
|
43
|
+
const ids = new Set(["main"]);
|
|
44
|
+
for (const agent of config.agents?.list ?? []) if (typeof agent.id === "string" && agent.id.trim()) ids.add(agent.id.trim());
|
|
45
|
+
return [...ids];
|
|
46
|
+
}
|
|
47
|
+
function listCandidateStorePaths(params) {
|
|
48
|
+
const paths = /* @__PURE__ */ new Set();
|
|
49
|
+
paths.add(resolveStorePath(params.config.session?.store, { env: params.env }));
|
|
50
|
+
for (const agentId of listAgentIds(params.config)) paths.add(resolveStorePath(params.config.session?.store, {
|
|
51
|
+
agentId,
|
|
52
|
+
env: params.env
|
|
53
|
+
}));
|
|
54
|
+
return [...paths];
|
|
55
|
+
}
|
|
56
|
+
async function fileExists(filePath) {
|
|
57
|
+
try {
|
|
58
|
+
return (await fs.stat(filePath)).isFile();
|
|
59
|
+
} catch {
|
|
60
|
+
return false;
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
async function listLegacyLearningFiles(storePath) {
|
|
64
|
+
let entries = [];
|
|
65
|
+
try {
|
|
66
|
+
entries = await fs.readdir(storePath, { withFileTypes: true });
|
|
67
|
+
} catch {
|
|
68
|
+
return [];
|
|
69
|
+
}
|
|
70
|
+
const suffix = ".learnings.json";
|
|
71
|
+
const knownSessionKeys = await listKnownSessionKeys(storePath);
|
|
72
|
+
const files = [];
|
|
73
|
+
for (const entry of entries) {
|
|
74
|
+
if (!entry.isFile() || !entry.name.endsWith(suffix)) continue;
|
|
75
|
+
const fileStem = entry.name.slice(0, -15);
|
|
76
|
+
const sessionKey = resolveLearningSessionKey(fileStem) ?? resolveLegacySanitizedSessionKey(fileStem, knownSessionKeys);
|
|
77
|
+
const filePath = path.join(storePath, entry.name);
|
|
78
|
+
try {
|
|
79
|
+
const parsed = JSON.parse(await fs.readFile(filePath, "utf8"));
|
|
80
|
+
if (Array.isArray(parsed)) {
|
|
81
|
+
const learnings = parsed.filter((item) => typeof item === "string");
|
|
82
|
+
if (learnings.length > 0) files.push({
|
|
83
|
+
storePath,
|
|
84
|
+
sessionKey,
|
|
85
|
+
filePath,
|
|
86
|
+
learnings: learnings.slice(-10)
|
|
87
|
+
});
|
|
88
|
+
}
|
|
89
|
+
} catch {}
|
|
90
|
+
}
|
|
91
|
+
return files;
|
|
92
|
+
}
|
|
93
|
+
async function archiveLegacySource(params) {
|
|
94
|
+
const archivedPath = `${params.filePath}.migrated`;
|
|
95
|
+
if (await fileExists(archivedPath)) {
|
|
96
|
+
params.warnings.push(`Left migrated Microsoft Teams feedback-learning source in place because ${archivedPath} already exists`);
|
|
97
|
+
return;
|
|
98
|
+
}
|
|
99
|
+
try {
|
|
100
|
+
await fs.rename(params.filePath, archivedPath);
|
|
101
|
+
params.changes.push(`Archived Microsoft Teams feedback-learning legacy source -> ${archivedPath}`);
|
|
102
|
+
} catch (err) {
|
|
103
|
+
params.warnings.push(`Failed archiving Microsoft Teams feedback-learning legacy source: ${String(err)}`);
|
|
104
|
+
}
|
|
105
|
+
}
|
|
106
|
+
function mergeLearnings(legacy, existing) {
|
|
107
|
+
const seen = /* @__PURE__ */ new Set();
|
|
108
|
+
const merged = [];
|
|
109
|
+
for (const learning of [...legacy, ...existing?.learnings ?? []]) {
|
|
110
|
+
if (seen.has(learning)) continue;
|
|
111
|
+
seen.add(learning);
|
|
112
|
+
merged.push(learning);
|
|
113
|
+
}
|
|
114
|
+
return merged.slice(-10);
|
|
115
|
+
}
|
|
116
|
+
const stateMigrations = [{
|
|
117
|
+
id: "msteams-feedback-learnings-json-to-plugin-state",
|
|
118
|
+
label: "Microsoft Teams feedback learnings",
|
|
119
|
+
async detectLegacyState(params) {
|
|
120
|
+
const files = (await Promise.all(listCandidateStorePaths(params).map((storePath) => listLegacyLearningFiles(storePath)))).flat();
|
|
121
|
+
if (files.length === 0) return null;
|
|
122
|
+
return { preview: [`- Microsoft Teams feedback learnings: ${files.length} ${files.length === 1 ? "file" : "files"} -> plugin state (${LEARNINGS_NAMESPACE})`] };
|
|
123
|
+
},
|
|
124
|
+
async migrateLegacyState(params) {
|
|
125
|
+
const changes = [];
|
|
126
|
+
const warnings = [];
|
|
127
|
+
const files = (await Promise.all(listCandidateStorePaths(params).map((storePath) => listLegacyLearningFiles(storePath)))).flat();
|
|
128
|
+
const store = params.context.openPluginStateKeyedStore({
|
|
129
|
+
namespace: LEARNINGS_NAMESPACE,
|
|
130
|
+
maxEntries: MAX_LEARNING_ENTRIES
|
|
131
|
+
});
|
|
132
|
+
const existingEntries = await store.entries();
|
|
133
|
+
const existingKeys = new Set(existingEntries.map((entry) => entry.key));
|
|
134
|
+
const importableFiles = files.filter((file) => file.sessionKey);
|
|
135
|
+
const missingKeys = new Set(importableFiles.map((file) => learningStoreKey(file.storePath, file.sessionKey ?? "")).filter((key) => !existingKeys.has(key)));
|
|
136
|
+
if (missingKeys.size > MAX_LEARNING_ENTRIES - existingKeys.size) {
|
|
137
|
+
warnings.push(`Skipped Microsoft Teams feedback-learning migration because plugin state has room for ${MAX_LEARNING_ENTRIES - existingKeys.size} of ${missingKeys.size} missing entries; left legacy sources in place`);
|
|
138
|
+
return {
|
|
139
|
+
changes,
|
|
140
|
+
warnings
|
|
141
|
+
};
|
|
142
|
+
}
|
|
143
|
+
let imported = 0;
|
|
144
|
+
for (const file of files) {
|
|
145
|
+
if (!file.sessionKey) {
|
|
146
|
+
warnings.push(`Left Microsoft Teams feedback-learning source in place because its legacy filename cannot be mapped to a session key: ${file.filePath}`);
|
|
147
|
+
continue;
|
|
148
|
+
}
|
|
149
|
+
const key = learningStoreKey(file.storePath, file.sessionKey);
|
|
150
|
+
const existing = await store.lookup(key);
|
|
151
|
+
await store.register(key, {
|
|
152
|
+
sessionKey: existing?.sessionKey ?? file.sessionKey,
|
|
153
|
+
learnings: mergeLearnings(file.learnings, existing),
|
|
154
|
+
updatedAt: Date.now()
|
|
155
|
+
});
|
|
156
|
+
imported++;
|
|
157
|
+
await archiveLegacySource({
|
|
158
|
+
filePath: file.filePath,
|
|
159
|
+
changes,
|
|
160
|
+
warnings
|
|
161
|
+
});
|
|
162
|
+
}
|
|
163
|
+
if (imported > 0) changes.unshift(`Migrated ${imported} Microsoft Teams feedback-learning ${imported === 1 ? "entry" : "entries"} -> plugin state`);
|
|
164
|
+
return {
|
|
165
|
+
changes,
|
|
166
|
+
warnings
|
|
167
|
+
};
|
|
168
|
+
}
|
|
169
|
+
}];
|
|
170
|
+
//#endregion
|
|
171
|
+
export { stateMigrations };
|
|
@@ -296,7 +296,7 @@ function resolveAuthAllowedHosts(input) {
|
|
|
296
296
|
}
|
|
297
297
|
function isMockFetchFn(fetchFn) {
|
|
298
298
|
const candidate = fetchFn;
|
|
299
|
-
return Boolean(candidate.mock || Object.
|
|
299
|
+
return Boolean(candidate.mock || Object.hasOwn(candidate, "_isMockFunction"));
|
|
300
300
|
}
|
|
301
301
|
function resolveGuardedFetchImpl(params) {
|
|
302
302
|
if (!params.fetchFn) return;
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { C as normalizeStringEntries$1, E as resolveChannelMediaMaxBytes, M as getMSTeamsRuntime, d as detectMime, g as getFileExtension, m as extractOriginalFilename, p as extensionForMime, y as loadOutboundMediaFromUrl } from "./runtime-api-BlvMnDKz.js";
|
|
2
|
-
import { A as isAllowedBotFrameworkServiceUrl, C as readAccessToken, D as buildUserAgent, E as loadMSTeamsSdkWithAuth, N as resolveMSTeamsSdkCloudOptions, P as validateMSTeamsProactiveServiceUrlBoundary, T as createMSTeamsTokenProvider, i as isRevokedProxyError, j as normalizeBotFrameworkServiceUrl, k as describeBotFrameworkServiceUrlHost, n as formatMSTeamsSendErrorHint, r as formatUnknownError, t as classifyMSTeamsSendError, v as loadDelegatedTokens, x as resolveMSTeamsStorePath, y as resolveMSTeamsCredentials } from "./errors-
|
|
2
|
+
import { A as isAllowedBotFrameworkServiceUrl, C as readAccessToken, D as buildUserAgent, E as loadMSTeamsSdkWithAuth, N as resolveMSTeamsSdkCloudOptions, P as validateMSTeamsProactiveServiceUrlBoundary, T as createMSTeamsTokenProvider, i as isRevokedProxyError, j as normalizeBotFrameworkServiceUrl, k as describeBotFrameworkServiceUrlHost, n as formatMSTeamsSendErrorHint, r as formatUnknownError, t as classifyMSTeamsSendError, v as loadDelegatedTokens, x as resolveMSTeamsStorePath, y as resolveMSTeamsCredentials } from "./errors-Dpn8B05h.js";
|
|
3
3
|
import { c as createMSTeamsHttpError } from "./oauth.token-BKzEFepQ.js";
|
|
4
|
-
import { a as resolveMSTeamsReplyPolicy, o as resolveMSTeamsRouteConfig } from "./channel-
|
|
4
|
+
import { a as resolveMSTeamsReplyPolicy, o as resolveMSTeamsRouteConfig } from "./channel-CqRTzeBc.js";
|
|
5
5
|
import { createMessageReceiptFromOutboundResults } from "openclaw/plugin-sdk/channel-outbound";
|
|
6
6
|
import { isRecord, normalizeLowercaseStringOrEmpty, normalizeOptionalLowercaseString, normalizeOptionalString, normalizeStringEntries, uniqueStrings } from "openclaw/plugin-sdk/string-coerce-runtime";
|
|
7
7
|
import { withFileLock } from "openclaw/plugin-sdk/file-lock";
|
|
@@ -12,7 +12,7 @@ import { isPrivateIpAddress } from "openclaw/plugin-sdk/ssrf-policy";
|
|
|
12
12
|
import path from "node:path";
|
|
13
13
|
import { isFutureDateTimestampMs, parseStrictNonNegativeInteger } from "openclaw/plugin-sdk/number-runtime";
|
|
14
14
|
import { pathExists } from "openclaw/plugin-sdk/security-runtime";
|
|
15
|
-
import crypto from "node:crypto";
|
|
15
|
+
import crypto, { createHash } from "node:crypto";
|
|
16
16
|
import fs from "node:fs/promises";
|
|
17
17
|
import { readJsonFileWithFallback, writeJsonFileAtomically } from "openclaw/plugin-sdk/json-store";
|
|
18
18
|
import { resolveMarkdownTableMode } from "openclaw/plugin-sdk/markdown-table-runtime";
|
|
@@ -106,7 +106,8 @@ function resolveMSTeamsSqliteStateEnv(options) {
|
|
|
106
106
|
};
|
|
107
107
|
}
|
|
108
108
|
function toPluginJsonValue(value) {
|
|
109
|
-
|
|
109
|
+
const serialized = JSON.stringify(value);
|
|
110
|
+
return JSON.parse(serialized);
|
|
110
111
|
}
|
|
111
112
|
function resolveMSTeamsSqliteStateDir(options) {
|
|
112
113
|
return resolveStateDirOverride(options) ?? getMSTeamsRuntime().state.resolveStateDir(options?.env ?? process.env, options?.homedir);
|
|
@@ -786,31 +787,24 @@ async function uploadToConsentUrl(params) {
|
|
|
786
787
|
}
|
|
787
788
|
//#endregion
|
|
788
789
|
//#region extensions/msteams/src/pending-uploads-fs.ts
|
|
789
|
-
/**
|
|
790
|
-
* Filesystem-backed pending upload store for the FileConsentCard flow.
|
|
791
|
-
*
|
|
792
|
-
* The CLI `message send --media` path runs in a different process from the
|
|
793
|
-
* gateway's bot monitor that receives the `fileConsent/invoke` callback.
|
|
794
|
-
* An in-memory `pending-uploads.ts` store cannot bridge those processes, so
|
|
795
|
-
* when the user clicks "Allow" the monitor handler's lookup misses and the
|
|
796
|
-
* user sees "card action not supported".
|
|
797
|
-
*
|
|
798
|
-
* This FS store persists pending uploads to a JSON file (with the file buffer
|
|
799
|
-
* base64-encoded) so any process that shares the OpenClaw state dir can read
|
|
800
|
-
* them back. The in-memory store in `pending-uploads.ts` is still the fast
|
|
801
|
-
* path for same-process flows (for example the messenger reply path); this FS
|
|
802
|
-
* store is a cross-process fallback.
|
|
803
|
-
*/
|
|
804
790
|
/** TTL for persisted pending uploads (matches in-memory store). */
|
|
805
791
|
const PENDING_UPLOAD_TTL_MS$1 = 300 * 1e3;
|
|
806
792
|
/** Cap to avoid unbounded growth if a process crashes mid-flow. */
|
|
807
793
|
const MAX_PENDING_UPLOADS = 100;
|
|
794
|
+
const MAX_CHUNKS_PER_UPLOAD = 3072;
|
|
795
|
+
const MAX_PENDING_UPLOAD_CHUNK_ROWS = 45e3;
|
|
796
|
+
const RAW_CHUNK_BYTES = 36 * 1024;
|
|
797
|
+
const PENDING_UPLOAD_META_MAX_ENTRIES = 200;
|
|
808
798
|
const STORE_FILENAME = "msteams-pending-uploads.json";
|
|
799
|
+
const PENDING_UPLOAD_META_NAMESPACE = "pending-uploads";
|
|
800
|
+
const PENDING_UPLOAD_CHUNKS_NAMESPACE = "pending-upload-chunks";
|
|
801
|
+
const PENDING_UPLOAD_MIGRATIONS_NAMESPACE = "pending-upload-migrations";
|
|
802
|
+
const PENDING_UPLOAD_LOCK_FILENAME = "msteams-pending-uploads.sqlite.lock";
|
|
809
803
|
const empty = {
|
|
810
804
|
version: 1,
|
|
811
805
|
uploads: {}
|
|
812
806
|
};
|
|
813
|
-
function
|
|
807
|
+
function resolveLegacyFilePath(options) {
|
|
814
808
|
return resolveMSTeamsStorePath({
|
|
815
809
|
filename: STORE_FILENAME,
|
|
816
810
|
env: options?.env,
|
|
@@ -819,6 +813,42 @@ function resolveFilePath(options) {
|
|
|
819
813
|
storePath: options?.storePath
|
|
820
814
|
});
|
|
821
815
|
}
|
|
816
|
+
function createMetaStore(options) {
|
|
817
|
+
return getMSTeamsRuntime().state.openKeyedStore({
|
|
818
|
+
namespace: PENDING_UPLOAD_META_NAMESPACE,
|
|
819
|
+
maxEntries: PENDING_UPLOAD_META_MAX_ENTRIES,
|
|
820
|
+
env: resolveMSTeamsSqliteStateEnv(options)
|
|
821
|
+
});
|
|
822
|
+
}
|
|
823
|
+
function createChunkStore(options) {
|
|
824
|
+
return getMSTeamsRuntime().state.openKeyedStore({
|
|
825
|
+
namespace: PENDING_UPLOAD_CHUNKS_NAMESPACE,
|
|
826
|
+
maxEntries: MAX_PENDING_UPLOAD_CHUNK_ROWS,
|
|
827
|
+
env: resolveMSTeamsSqliteStateEnv(options)
|
|
828
|
+
});
|
|
829
|
+
}
|
|
830
|
+
function createMigrationStore(options) {
|
|
831
|
+
return getMSTeamsRuntime().state.openKeyedStore({
|
|
832
|
+
namespace: PENDING_UPLOAD_MIGRATIONS_NAMESPACE,
|
|
833
|
+
maxEntries: 100,
|
|
834
|
+
env: resolveMSTeamsSqliteStateEnv(options)
|
|
835
|
+
});
|
|
836
|
+
}
|
|
837
|
+
function buildUploadKey(id) {
|
|
838
|
+
return `upload:${createHash("sha256").update(id).digest("hex")}`;
|
|
839
|
+
}
|
|
840
|
+
function buildMetaKey(id) {
|
|
841
|
+
return `${buildUploadKey(id)}:meta`;
|
|
842
|
+
}
|
|
843
|
+
function buildChunkKey(id, index) {
|
|
844
|
+
return `${buildUploadKey(id)}:chunk:${String(index).padStart(4, "0")}`;
|
|
845
|
+
}
|
|
846
|
+
function buildMigrationKey(filePath) {
|
|
847
|
+
return `legacy-json:${createHash("sha256").update(filePath).digest("hex")}`;
|
|
848
|
+
}
|
|
849
|
+
function buildMigrationContentKey(filePath, value) {
|
|
850
|
+
return `legacy-json-content:${createHash("sha256").update(filePath).update("\0").update(JSON.stringify(value) ?? "undefined").digest("hex")}`;
|
|
851
|
+
}
|
|
822
852
|
function pruneExpired(uploads, nowMs, ttlMs) {
|
|
823
853
|
const kept = {};
|
|
824
854
|
for (const [id, record] of Object.entries(uploads)) if (nowMs - record.createdAt <= ttlMs) kept[id] = record;
|
|
@@ -831,10 +861,10 @@ function pruneToLimit(uploads) {
|
|
|
831
861
|
const keep = entries.slice(entries.length - MAX_PENDING_UPLOADS);
|
|
832
862
|
return Object.fromEntries(keep);
|
|
833
863
|
}
|
|
834
|
-
function recordToUpload(record) {
|
|
864
|
+
function recordToUpload(record, buffer) {
|
|
835
865
|
return {
|
|
836
866
|
id: record.id,
|
|
837
|
-
buffer
|
|
867
|
+
buffer,
|
|
838
868
|
filename: record.filename,
|
|
839
869
|
contentType: record.contentType,
|
|
840
870
|
conversationId: record.conversationId,
|
|
@@ -847,17 +877,119 @@ function isValidStore(value) {
|
|
|
847
877
|
const candidate = value;
|
|
848
878
|
return candidate.version === 1 && typeof candidate.uploads === "object" && candidate.uploads !== null && !Array.isArray(candidate.uploads);
|
|
849
879
|
}
|
|
850
|
-
|
|
851
|
-
|
|
852
|
-
|
|
853
|
-
|
|
854
|
-
uploads: {}
|
|
855
|
-
};
|
|
880
|
+
function normalizeLegacyUploadRecord(value) {
|
|
881
|
+
if (!value || typeof value !== "object") return null;
|
|
882
|
+
const record = value;
|
|
883
|
+
if (typeof record.id !== "string" || !record.id || typeof record.bufferBase64 !== "string" || typeof record.filename !== "string" || !record.filename || typeof record.conversationId !== "string" || !record.conversationId || typeof record.createdAt !== "number" || !Number.isFinite(record.createdAt)) return null;
|
|
856
884
|
return {
|
|
857
|
-
|
|
858
|
-
|
|
885
|
+
id: record.id,
|
|
886
|
+
bufferBase64: record.bufferBase64,
|
|
887
|
+
filename: record.filename,
|
|
888
|
+
contentType: typeof record.contentType === "string" ? record.contentType : void 0,
|
|
889
|
+
conversationId: record.conversationId,
|
|
890
|
+
consentCardActivityId: typeof record.consentCardActivityId === "string" ? record.consentCardActivityId : void 0,
|
|
891
|
+
createdAt: record.createdAt
|
|
859
892
|
};
|
|
860
893
|
}
|
|
894
|
+
function normalizeLegacyUploads(value) {
|
|
895
|
+
if (!isValidStore(value)) return {};
|
|
896
|
+
const uploads = {};
|
|
897
|
+
for (const record of Object.values(value.uploads)) {
|
|
898
|
+
const normalized = normalizeLegacyUploadRecord(record);
|
|
899
|
+
if (normalized) uploads[normalized.id] = normalized;
|
|
900
|
+
}
|
|
901
|
+
return uploads;
|
|
902
|
+
}
|
|
903
|
+
async function deleteUploadRows(id, metaStore, chunkStore) {
|
|
904
|
+
const existing = await metaStore.lookup(buildMetaKey(id));
|
|
905
|
+
await metaStore.delete(buildMetaKey(id));
|
|
906
|
+
if (!existing) return;
|
|
907
|
+
const chunkCount = existing.chunkCount;
|
|
908
|
+
for (let index = 0; index < chunkCount; index += 1) await chunkStore.delete(buildChunkKey(id, index));
|
|
909
|
+
}
|
|
910
|
+
async function registerUploadRows(record, metaStore, chunkStore, ttlMs, overwrite) {
|
|
911
|
+
const buffer = Buffer.from(record.bufferBase64, "base64");
|
|
912
|
+
const chunkCount = Math.max(1, Math.ceil(buffer.byteLength / RAW_CHUNK_BYTES));
|
|
913
|
+
if (chunkCount > MAX_CHUNKS_PER_UPLOAD) throw new Error(`Microsoft Teams pending upload ${record.id} exceeds SQLite chunk limit (${chunkCount}/${MAX_CHUNKS_PER_UPLOAD})`);
|
|
914
|
+
if (overwrite) await deleteUploadRows(record.id, metaStore, chunkStore);
|
|
915
|
+
else if (await metaStore.lookup(buildMetaKey(record.id))) return;
|
|
916
|
+
await pruneUploadStore(metaStore, chunkStore, ttlMs, chunkCount);
|
|
917
|
+
for (let index = 0; index < chunkCount; index += 1) {
|
|
918
|
+
const chunk = buffer.subarray(index * RAW_CHUNK_BYTES, (index + 1) * RAW_CHUNK_BYTES);
|
|
919
|
+
await chunkStore.register(buildChunkKey(record.id, index), toPluginJsonValue({
|
|
920
|
+
id: record.id,
|
|
921
|
+
index,
|
|
922
|
+
dataBase64: chunk.toString("base64")
|
|
923
|
+
}));
|
|
924
|
+
}
|
|
925
|
+
await metaStore.register(buildMetaKey(record.id), toPluginJsonValue({
|
|
926
|
+
id: record.id,
|
|
927
|
+
filename: record.filename,
|
|
928
|
+
contentType: record.contentType,
|
|
929
|
+
conversationId: record.conversationId,
|
|
930
|
+
consentCardActivityId: record.consentCardActivityId,
|
|
931
|
+
createdAt: record.createdAt,
|
|
932
|
+
chunkCount,
|
|
933
|
+
byteLength: buffer.byteLength
|
|
934
|
+
}));
|
|
935
|
+
}
|
|
936
|
+
async function importLegacyStore(options, metaStore, chunkStore, ttlMs) {
|
|
937
|
+
const legacyFilePath = resolveLegacyFilePath(options);
|
|
938
|
+
const migrationStore = createMigrationStore(options);
|
|
939
|
+
const migrationKey = buildMigrationKey(legacyFilePath);
|
|
940
|
+
const imported = await migrationStore.lookup(migrationKey) !== void 0;
|
|
941
|
+
const { value, exists } = await readJsonFile(legacyFilePath, empty);
|
|
942
|
+
if (!exists) {
|
|
943
|
+
if (!imported) await migrationStore.register(migrationKey, { importedAt: (/* @__PURE__ */ new Date()).toISOString() });
|
|
944
|
+
return;
|
|
945
|
+
}
|
|
946
|
+
const contentKey = buildMigrationContentKey(legacyFilePath, value);
|
|
947
|
+
if (await migrationStore.lookup(contentKey)) return;
|
|
948
|
+
const legacy = pruneToLimit(pruneExpired(normalizeLegacyUploads(value), Date.now(), ttlMs));
|
|
949
|
+
for (const record of Object.values(legacy)) await registerUploadRows(record, metaStore, chunkStore, ttlMs, false);
|
|
950
|
+
await migrationStore.register(contentKey, { importedAt: (/* @__PURE__ */ new Date()).toISOString() });
|
|
951
|
+
if (!imported) await migrationStore.register(migrationKey, { importedAt: (/* @__PURE__ */ new Date()).toISOString() });
|
|
952
|
+
await fs.rm(legacyFilePath, { force: true }).catch(() => {});
|
|
953
|
+
}
|
|
954
|
+
async function withPendingUploadLock(options, run) {
|
|
955
|
+
return await withMSTeamsSqliteMutationLock(options, PENDING_UPLOAD_LOCK_FILENAME, run);
|
|
956
|
+
}
|
|
957
|
+
async function ensureLegacyImported(options, metaStore, chunkStore, ttlMs) {
|
|
958
|
+
await withPendingUploadLock(options, () => importLegacyStore(options, metaStore, chunkStore, ttlMs));
|
|
959
|
+
}
|
|
960
|
+
async function readUploadRows(id, metaStore, chunkStore) {
|
|
961
|
+
const meta = await metaStore.lookup(buildMetaKey(id));
|
|
962
|
+
if (!meta) return;
|
|
963
|
+
const chunks = [];
|
|
964
|
+
for (let index = 0; index < meta.chunkCount; index += 1) {
|
|
965
|
+
const chunk = await chunkStore.lookup(buildChunkKey(id, index));
|
|
966
|
+
if (!chunk || chunk.id !== id || chunk.index !== index) return;
|
|
967
|
+
chunks.push(Buffer.from(chunk.dataBase64, "base64"));
|
|
968
|
+
}
|
|
969
|
+
return recordToUpload(meta, Buffer.concat(chunks, meta.byteLength));
|
|
970
|
+
}
|
|
971
|
+
async function pruneUploadStore(metaStore, chunkStore, ttlMs, extraChunkRows = 0) {
|
|
972
|
+
const rows = await metaStore.entries();
|
|
973
|
+
const liveRows = [];
|
|
974
|
+
const now = Date.now();
|
|
975
|
+
let liveChunkRows = 0;
|
|
976
|
+
for (const row of rows) {
|
|
977
|
+
if (now - row.value.createdAt > ttlMs) {
|
|
978
|
+
await deleteUploadRows(row.value.id, metaStore, chunkStore);
|
|
979
|
+
continue;
|
|
980
|
+
}
|
|
981
|
+
liveChunkRows += row.value.chunkCount;
|
|
982
|
+
liveRows.push(row);
|
|
983
|
+
}
|
|
984
|
+
if (liveRows.length <= MAX_PENDING_UPLOADS && liveChunkRows + extraChunkRows <= MAX_PENDING_UPLOAD_CHUNK_ROWS) return;
|
|
985
|
+
const sorted = liveRows.toSorted((a, b) => a.value.createdAt - b.value.createdAt || a.value.id.localeCompare(b.value.id));
|
|
986
|
+
for (const row of sorted) {
|
|
987
|
+
if (liveRows.length <= MAX_PENDING_UPLOADS && liveChunkRows + extraChunkRows <= MAX_PENDING_UPLOAD_CHUNK_ROWS) break;
|
|
988
|
+
await deleteUploadRows(row.value.id, metaStore, chunkStore);
|
|
989
|
+
liveChunkRows -= row.value.chunkCount;
|
|
990
|
+
liveRows.pop();
|
|
991
|
+
}
|
|
992
|
+
}
|
|
861
993
|
/**
|
|
862
994
|
* Persist a pending upload record so another process can read it back.
|
|
863
995
|
* Pass in the pre-generated id (same as the one placed in the consent card
|
|
@@ -865,10 +997,11 @@ async function readStore(filePath, ttlMs) {
|
|
|
865
997
|
*/
|
|
866
998
|
async function storePendingUploadFs(upload, options) {
|
|
867
999
|
const ttlMs = options?.ttlMs ?? PENDING_UPLOAD_TTL_MS$1;
|
|
868
|
-
const
|
|
869
|
-
|
|
870
|
-
|
|
871
|
-
|
|
1000
|
+
const metaStore = createMetaStore(options);
|
|
1001
|
+
const chunkStore = createChunkStore(options);
|
|
1002
|
+
await withPendingUploadLock(options, async () => {
|
|
1003
|
+
await importLegacyStore(options, metaStore, chunkStore, ttlMs);
|
|
1004
|
+
await registerUploadRows({
|
|
872
1005
|
id: upload.id,
|
|
873
1006
|
bufferBase64: upload.buffer.toString("base64"),
|
|
874
1007
|
filename: upload.filename,
|
|
@@ -876,9 +1009,8 @@ async function storePendingUploadFs(upload, options) {
|
|
|
876
1009
|
conversationId: upload.conversationId,
|
|
877
1010
|
consentCardActivityId: upload.consentCardActivityId,
|
|
878
1011
|
createdAt: Date.now()
|
|
879
|
-
};
|
|
880
|
-
|
|
881
|
-
await writeJsonFile(filePath, store);
|
|
1012
|
+
}, metaStore, chunkStore, ttlMs, true);
|
|
1013
|
+
await pruneUploadStore(metaStore, chunkStore, ttlMs);
|
|
882
1014
|
});
|
|
883
1015
|
}
|
|
884
1016
|
/**
|
|
@@ -887,10 +1019,16 @@ async function storePendingUploadFs(upload, options) {
|
|
|
887
1019
|
async function getPendingUploadFs(id, options) {
|
|
888
1020
|
if (!id) return;
|
|
889
1021
|
const ttlMs = options?.ttlMs ?? PENDING_UPLOAD_TTL_MS$1;
|
|
890
|
-
const
|
|
891
|
-
|
|
892
|
-
|
|
893
|
-
|
|
1022
|
+
const metaStore = createMetaStore(options);
|
|
1023
|
+
const chunkStore = createChunkStore(options);
|
|
1024
|
+
await ensureLegacyImported(options, metaStore, chunkStore, ttlMs);
|
|
1025
|
+
const upload = await readUploadRows(id, metaStore, chunkStore);
|
|
1026
|
+
if (!upload) return;
|
|
1027
|
+
if (Date.now() - upload.createdAt > ttlMs) {
|
|
1028
|
+
await removePendingUploadFs(id, options);
|
|
1029
|
+
return;
|
|
1030
|
+
}
|
|
1031
|
+
return upload;
|
|
894
1032
|
}
|
|
895
1033
|
/**
|
|
896
1034
|
* Remove a persisted pending upload (after successful upload or decline).
|
|
@@ -899,12 +1037,11 @@ async function getPendingUploadFs(id, options) {
|
|
|
899
1037
|
async function removePendingUploadFs(id, options) {
|
|
900
1038
|
if (!id) return;
|
|
901
1039
|
const ttlMs = options?.ttlMs ?? PENDING_UPLOAD_TTL_MS$1;
|
|
902
|
-
const
|
|
903
|
-
|
|
904
|
-
|
|
905
|
-
|
|
906
|
-
|
|
907
|
-
await writeJsonFile(filePath, store);
|
|
1040
|
+
const metaStore = createMetaStore(options);
|
|
1041
|
+
const chunkStore = createChunkStore(options);
|
|
1042
|
+
await withPendingUploadLock(options, async () => {
|
|
1043
|
+
await importLegacyStore(options, metaStore, chunkStore, ttlMs);
|
|
1044
|
+
await deleteUploadRows(id, metaStore, chunkStore);
|
|
908
1045
|
});
|
|
909
1046
|
}
|
|
910
1047
|
/**
|
|
@@ -913,13 +1050,16 @@ async function removePendingUploadFs(id, options) {
|
|
|
913
1050
|
*/
|
|
914
1051
|
async function setPendingUploadActivityIdFs(id, activityId, options) {
|
|
915
1052
|
const ttlMs = options?.ttlMs ?? PENDING_UPLOAD_TTL_MS$1;
|
|
916
|
-
const
|
|
917
|
-
|
|
918
|
-
|
|
919
|
-
|
|
920
|
-
|
|
921
|
-
record.
|
|
922
|
-
await
|
|
1053
|
+
const metaStore = createMetaStore(options);
|
|
1054
|
+
const chunkStore = createChunkStore(options);
|
|
1055
|
+
await withPendingUploadLock(options, async () => {
|
|
1056
|
+
await importLegacyStore(options, metaStore, chunkStore, ttlMs);
|
|
1057
|
+
const record = await metaStore.lookup(buildMetaKey(id));
|
|
1058
|
+
if (!record || Date.now() - record.createdAt > ttlMs) return;
|
|
1059
|
+
await metaStore.register(buildMetaKey(id), toPluginJsonValue({
|
|
1060
|
+
...record,
|
|
1061
|
+
consentCardActivityId: activityId
|
|
1062
|
+
}));
|
|
923
1063
|
});
|
|
924
1064
|
}
|
|
925
1065
|
//#endregion
|
|
@@ -2567,4 +2707,4 @@ async function probeMSTeams(cfg) {
|
|
|
2567
2707
|
}
|
|
2568
2708
|
}
|
|
2569
2709
|
//#endregion
|
|
2570
|
-
export {
|
|
2710
|
+
export { resolveMSTeamsSqliteStateEnv as C, readJsonFile as E, createMSTeamsConversationStoreState as S, withMSTeamsSqliteMutationLock as T, buildFileInfoCard as _, sendMessageMSTeams as a, createMSTeamsPollStoreState as b, renderReplyPayloadsToMessages as c, withRevokedProxyFallback as d, resolveGraphChatId as f, removePendingUploadFs as g, getPendingUploadFs as h, sendAdaptiveCardMSTeams as i, sendMSTeamsMessages as l, removePendingUpload as m, deleteMessageMSTeams as n, sendPollMSTeams as o, getPendingUpload as p, editMessageMSTeams as r, buildConversationReference as s, probeMSTeams as t, sendMSTeamsActivityWithReference as u, parseFileConsentInvoke as v, toPluginJsonValue as w, extractMSTeamsPollVote as x, uploadToConsentUrl as y };
|
package/dist/setup-plugin-api.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { y as resolveMSTeamsCredentials } from "./errors-
|
|
2
|
-
import { i as msteamsSetupAdapter, t as msteamsSetupWizard } from "./setup-surface-
|
|
1
|
+
import { y as resolveMSTeamsCredentials } from "./errors-Dpn8B05h.js";
|
|
2
|
+
import { i as msteamsSetupAdapter, t as msteamsSetupWizard } from "./setup-surface-B7a1pD-K.js";
|
|
3
3
|
import { t as MSTeamsChannelConfigSchema } from "./config-schema-BL4qQZiA.js";
|
|
4
4
|
import { describeAccountSnapshot } from "openclaw/plugin-sdk/account-helpers";
|
|
5
5
|
import { formatAllowFromLowercase } from "openclaw/plugin-sdk/allow-from";
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { S as normalizeSecretInputString, _ as hasConfiguredMSTeamsCredentials, a as searchGraphUsers, b as saveDelegatedTokens, d as listTeamsByName, f as normalizeQuery, g as resolveGraphToken, r as formatUnknownError, u as listChannelsForTeam, y as resolveMSTeamsCredentials } from "./errors-
|
|
1
|
+
import { S as normalizeSecretInputString, _ as hasConfiguredMSTeamsCredentials, a as searchGraphUsers, b as saveDelegatedTokens, d as listTeamsByName, f as normalizeQuery, g as resolveGraphToken, r as formatUnknownError, u as listChannelsForTeam, y as resolveMSTeamsCredentials } from "./errors-Dpn8B05h.js";
|
|
2
2
|
import { mapAllowlistResolutionInputs } from "openclaw/plugin-sdk/allow-from";
|
|
3
3
|
import { normalizeLowercaseStringOrEmpty, normalizeOptionalLowercaseString } from "openclaw/plugin-sdk/string-coerce-runtime";
|
|
4
4
|
import { DEFAULT_ACCOUNT_ID, createSetupTranslator, createStandardChannelSetupStatus, createTopLevelChannelAllowFromSetter, createTopLevelChannelDmPolicy, createTopLevelChannelGroupPolicySetter, mergeAllowFromEntries, splitSetupEntries } from "openclaw/plugin-sdk/setup";
|