@openclaw/msteams 2026.9.1 → 2026.9.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/dist/api.cjs +2 -2
- package/dist/{approval-card-ClrTjCsL.cjs → approval-card-CPNH_q3P.cjs} +7 -85
- package/dist/{approval-handler.runtime-9rMFhyLp.cjs → approval-handler.runtime-CoTQG4FS.cjs} +6 -6
- package/dist/{channel-CqRcu6kk.cjs → channel-Cdm6-HsU.cjs} +4 -4
- package/dist/channel-config-api.cjs +1 -1
- package/dist/channel-plugin-api.cjs +1 -1
- package/dist/{channel.runtime-BAy59d1L.cjs → channel.runtime-__5ZQlfG.cjs} +5 -5
- package/dist/{channel.setup-D2YO3F4O.cjs → channel.setup-ChwkwdLk.cjs} +5 -2
- package/dist/{config-schema-MyN2lamA.cjs → config-schema-D22Lr1Qk.cjs} +4 -13
- package/dist/doctor-contract-api.cjs +7 -7
- package/dist/{messenger-BvR2flEt.cjs → messenger-DbWgzI01.cjs} +50 -55
- package/dist/{polls-P86qBpeV.cjs → polls-BBdZPx_R.cjs} +9 -15
- package/dist/{reaction-types-DcJBoyFP.cjs → reaction-types-zP91Ncwk.cjs} +16 -15
- package/dist/{send-CAKTR80N.cjs → send-Bw4W8RO7.cjs} +10 -9
- package/dist/setup-plugin-api.cjs +1 -1
- package/dist/{src-CyNCea9B.cjs → src-B--Qc6lj.cjs} +152 -172
- package/dist/{sso-token-store-CNbRhz-A.cjs → sso-token-store-DTeYxubp.cjs} +1 -1
- package/openclaw.plugin.json +18 -2
- package/package.json +5 -5
|
@@ -2,14 +2,14 @@ const require_rolldown_runtime = require("./rolldown-runtime-VH7oDXx4.cjs");
|
|
|
2
2
|
const require_runtime = require("./runtime-gZTAuFux.cjs");
|
|
3
3
|
require("./runtime-api.cjs");
|
|
4
4
|
const require_resolve_allowlist = require("./resolve-allowlist-CoKmLXYe.cjs");
|
|
5
|
-
const require_channel = require("./channel-
|
|
5
|
+
const require_channel = require("./channel-Cdm6-HsU.cjs");
|
|
6
6
|
const require_thread_session = require("./thread-session-p8FNgohv.cjs");
|
|
7
|
-
const require_channel_setup = require("./channel.setup-
|
|
8
|
-
const require_polls = require("./polls-
|
|
9
|
-
const require_sso_token_store = require("./sso-token-store-
|
|
10
|
-
const require_approval_card = require("./approval-card-
|
|
11
|
-
const require_messenger = require("./messenger-
|
|
12
|
-
const require_reaction_types = require("./reaction-types-
|
|
7
|
+
const require_channel_setup = require("./channel.setup-ChwkwdLk.cjs");
|
|
8
|
+
const require_polls = require("./polls-BBdZPx_R.cjs");
|
|
9
|
+
const require_sso_token_store = require("./sso-token-store-DTeYxubp.cjs");
|
|
10
|
+
const require_approval_card = require("./approval-card-CPNH_q3P.cjs");
|
|
11
|
+
const require_messenger = require("./messenger-DbWgzI01.cjs");
|
|
12
|
+
const require_reaction_types = require("./reaction-types-zP91Ncwk.cjs");
|
|
13
13
|
let openclaw_plugin_sdk_channel_outbound = require("openclaw/plugin-sdk/channel-outbound");
|
|
14
14
|
let openclaw_plugin_sdk_string_coerce_runtime = require("openclaw/plugin-sdk/string-coerce-runtime");
|
|
15
15
|
let openclaw_plugin_sdk_allow_from = require("openclaw/plugin-sdk/allow-from");
|
|
@@ -22,18 +22,19 @@ let openclaw_plugin_sdk_text_utility_runtime = require("openclaw/plugin-sdk/text
|
|
|
22
22
|
let openclaw_plugin_sdk_routing = require("openclaw/plugin-sdk/routing");
|
|
23
23
|
let node_crypto = require("node:crypto");
|
|
24
24
|
node_crypto = require_rolldown_runtime.__toESM(node_crypto, 1);
|
|
25
|
-
let openclaw_plugin_sdk_collection_runtime = require("openclaw/plugin-sdk/collection-runtime");
|
|
26
25
|
let openclaw_plugin_sdk_error_runtime = require("openclaw/plugin-sdk/error-runtime");
|
|
27
26
|
let openclaw_plugin_sdk_channel_inbound = require("openclaw/plugin-sdk/channel-inbound");
|
|
28
27
|
let openclaw_plugin_sdk_approval_gateway_runtime = require("openclaw/plugin-sdk/approval-gateway-runtime");
|
|
29
28
|
let openclaw_plugin_sdk_channel_ingress_runtime = require("openclaw/plugin-sdk/channel-ingress-runtime");
|
|
30
29
|
let openclaw_plugin_sdk_context_visibility_runtime = require("openclaw/plugin-sdk/context-visibility-runtime");
|
|
31
30
|
let openclaw_plugin_sdk_reply_history = require("openclaw/plugin-sdk/reply-history");
|
|
31
|
+
let openclaw_plugin_sdk_runtime_config_snapshot = require("openclaw/plugin-sdk/runtime-config-snapshot");
|
|
32
32
|
let openclaw_plugin_sdk_agent_runtime = require("openclaw/plugin-sdk/agent-runtime");
|
|
33
33
|
let openclaw_plugin_sdk_extension_shared = require("openclaw/plugin-sdk/extension-shared");
|
|
34
34
|
let openclaw_plugin_sdk_plugin_runtime = require("openclaw/plugin-sdk/plugin-runtime");
|
|
35
35
|
let openclaw_plugin_sdk_dedupe_runtime = require("openclaw/plugin-sdk/dedupe-runtime");
|
|
36
36
|
let openclaw_plugin_sdk_plugin_state_runtime = require("openclaw/plugin-sdk/plugin-state-runtime");
|
|
37
|
+
let openclaw_plugin_sdk_collection_runtime = require("openclaw/plugin-sdk/collection-runtime");
|
|
37
38
|
let openclaw_plugin_sdk_gateway_runtime = require("openclaw/plugin-sdk/gateway-runtime");
|
|
38
39
|
let openclaw_plugin_sdk_channel_pairing = require("openclaw/plugin-sdk/channel-pairing");
|
|
39
40
|
let openclaw_plugin_sdk_runtime_group_policy = require("openclaw/plugin-sdk/runtime-group-policy");
|
|
@@ -187,7 +188,7 @@ async function maybeHandleMSTeamsApprovalCardSubmit(params) {
|
|
|
187
188
|
ignored("missing card token");
|
|
188
189
|
return true;
|
|
189
190
|
}
|
|
190
|
-
const binding = require_approval_card.
|
|
191
|
+
const binding = require_approval_card.msTeamsApprovalControls.get(token);
|
|
191
192
|
if (!binding) {
|
|
192
193
|
ignored("unknown or expired card token");
|
|
193
194
|
return true;
|
|
@@ -219,15 +220,8 @@ async function maybeHandleMSTeamsApprovalCardSubmit(params) {
|
|
|
219
220
|
ignored(`unauthorized actor ${senderId || "unknown"}`);
|
|
220
221
|
return true;
|
|
221
222
|
}
|
|
222
|
-
const
|
|
223
|
-
|
|
224
|
-
ignored(claim.kind === "in-flight" ? "card token resolve already in flight" : "card token already consumed");
|
|
225
|
-
return true;
|
|
226
|
-
}
|
|
227
|
-
const consumed = claim.binding;
|
|
228
|
-
let result;
|
|
229
|
-
try {
|
|
230
|
-
result = await (0, openclaw_plugin_sdk_approval_gateway_runtime.resolveApprovalOverGateway)({
|
|
223
|
+
const outcome = await require_approval_card.msTeamsApprovalControls.settle(token, async (consumed) => {
|
|
224
|
+
const result = await (0, openclaw_plugin_sdk_approval_gateway_runtime.resolveApprovalOverGateway)({
|
|
231
225
|
cfg: deps.cfg,
|
|
232
226
|
approvalId: consumed.approvalId,
|
|
233
227
|
approvalKind: consumed.approvalKind,
|
|
@@ -244,16 +238,13 @@ async function maybeHandleMSTeamsApprovalCardSubmit(params) {
|
|
|
244
238
|
content: require_approval_card.buildMSTeamsCanonicalApprovalTerminalCard(result)
|
|
245
239
|
}]
|
|
246
240
|
});
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
}
|
|
253
|
-
require_approval_card.releaseMSTeamsApprovalCardBinding(token);
|
|
254
|
-
throw error;
|
|
241
|
+
return result;
|
|
242
|
+
});
|
|
243
|
+
if (outcome.kind !== "settled") {
|
|
244
|
+
ignored(outcome.kind === "missing" ? "card token already consumed" : outcome.kind === "in-flight" ? "card token resolve already in flight" : `approval expired or no longer exists id=${outcome.binding.approvalId}`);
|
|
245
|
+
return true;
|
|
255
246
|
}
|
|
256
|
-
|
|
247
|
+
const { binding: consumed, result } = outcome;
|
|
257
248
|
deps.log.info("msteams approval resolved", {
|
|
258
249
|
approvalId: consumed.approvalId,
|
|
259
250
|
approvalKind: consumed.approvalKind,
|
|
@@ -1747,7 +1738,7 @@ function isStreamCancelledError(err) {
|
|
|
1747
1738
|
* Streaming is enabled for personal (DM) conversations only; group/channel
|
|
1748
1739
|
* messages fall through to block delivery.
|
|
1749
1740
|
*
|
|
1750
|
-
* Streaming modes (resolved from `cfg.channels.msteams.streaming.
|
|
1741
|
+
* Streaming modes (resolved from `cfg.channels.msteams.streaming.mode`):
|
|
1751
1742
|
* - "partial" (default): per-token streaming via `stream.emit(text)`. Each
|
|
1752
1743
|
* chunk goes onto the live preview card in Teams.
|
|
1753
1744
|
* - "progress": no per-token streaming; the preview card carries an
|
|
@@ -1760,39 +1751,35 @@ function isStreamCancelledError(err) {
|
|
|
1760
1751
|
function createTeamsReplyStreamController(params) {
|
|
1761
1752
|
const isPersonal = (0, openclaw_plugin_sdk_string_coerce_runtime.normalizeOptionalLowercaseString)(params.conversationType) === "personal";
|
|
1762
1753
|
const streamMode = (0, openclaw_plugin_sdk_channel_outbound.resolveChannelPreviewStreamMode)(params.msteamsConfig, "partial");
|
|
1763
|
-
const
|
|
1764
|
-
const shouldStreamPreviewToolProgress = streamMode === "progress" && (0, openclaw_plugin_sdk_channel_outbound.resolveChannelStreamingPreviewToolProgress)(params.msteamsConfig, true, streamMode);
|
|
1765
|
-
const stream = shouldUseNativeStream ? params.context.stream : void 0;
|
|
1754
|
+
const stream = params.allowProviderPreview && isPersonal && (streamMode === "partial" || streamMode === "progress") ? params.context.stream : void 0;
|
|
1766
1755
|
let tokensEmitted = false;
|
|
1767
1756
|
let nativeDispatchStarted = false;
|
|
1768
1757
|
let nativeDeliveryClaimed = false;
|
|
1769
1758
|
let streamFinalizationPending = false;
|
|
1770
1759
|
let canceledLocally = false;
|
|
1771
1760
|
let streamFailed = false;
|
|
1772
|
-
let lastInformativeText = "";
|
|
1773
|
-
let progressLines = [];
|
|
1774
|
-
let latestPlan;
|
|
1775
|
-
let latestPlanExplanation;
|
|
1776
1761
|
let pendingFinalPayload;
|
|
1777
1762
|
let emittedText = "";
|
|
1778
1763
|
let acknowledgedText = "";
|
|
1764
|
+
let acknowledgedLogicalText = "";
|
|
1779
1765
|
let acknowledgedStreamId;
|
|
1780
1766
|
let replacementFinalPending = false;
|
|
1781
1767
|
let replacementEmitFailed = false;
|
|
1782
1768
|
let replacementSettlementPending = false;
|
|
1783
1769
|
let replacementTextAwaitingAcknowledgement;
|
|
1784
1770
|
let deferredReplacementEntries = [];
|
|
1785
|
-
let
|
|
1771
|
+
let queuedFinalActivity;
|
|
1786
1772
|
let failedSegmentFallbackPrepared = false;
|
|
1787
1773
|
const streamEvents = stream?.events;
|
|
1788
1774
|
let streamChunkSubscription;
|
|
1789
1775
|
if (typeof streamEvents?.on === "function" && typeof streamEvents.off === "function") streamChunkSubscription = streamEvents.on("chunk", (activity) => {
|
|
1790
1776
|
const replacementAcknowledgementPending = replacementTextAwaitingAcknowledgement !== void 0;
|
|
1791
|
-
const replacementAcknowledgement = typeof activity.text === "string" && replacementAcknowledgementPending && activity.text === replacementTextAwaitingAcknowledgement;
|
|
1792
|
-
if (activity.type !== "typing" || activity.channelData?.streamType !== "streaming" || !activity.id || !activity.text || acknowledgedStreamId !== void 0 && activity.id !== acknowledgedStreamId || (replacementAcknowledgementPending ? !replacementAcknowledgement : !activity.text.startsWith(acknowledgedText)) || !emittedText.startsWith(activity.text)) return;
|
|
1777
|
+
const replacementAcknowledgement = typeof activity.text === "string" && replacementAcknowledgementPending && activity.text === replacementTextAwaitingAcknowledgement?.text;
|
|
1778
|
+
if (activity.type !== "typing" || activity.channelData?.streamType !== "streaming" || !activity.id || !activity.text || acknowledgedStreamId !== void 0 && activity.id !== acknowledgedStreamId || (replacementAcknowledgementPending ? !replacementAcknowledgement : !activity.text.startsWith(acknowledgedText)) || !replacementAcknowledgement && !emittedText.startsWith(activity.text)) return;
|
|
1793
1779
|
acknowledgedStreamId = activity.id;
|
|
1794
1780
|
acknowledgedText = activity.text;
|
|
1795
|
-
|
|
1781
|
+
acknowledgedLogicalText = replacementAcknowledgement ? replacementTextAwaitingAcknowledgement.logicalText : activity.text;
|
|
1782
|
+
if (replacementAcknowledgement) replacementTextAwaitingAcknowledgement = void 0;
|
|
1796
1783
|
});
|
|
1797
1784
|
const wasCanceled = () => canceledLocally || Boolean(stream?.canceled);
|
|
1798
1785
|
const releaseStreamChunkSubscription = () => {
|
|
@@ -1809,8 +1796,8 @@ function createTeamsReplyStreamController(params) {
|
|
|
1809
1796
|
};
|
|
1810
1797
|
};
|
|
1811
1798
|
const fallbackPayloadAfterAcknowledgedText = (payload) => {
|
|
1812
|
-
if (!
|
|
1813
|
-
const remainingText = payload.text.slice(
|
|
1799
|
+
if (!acknowledgedLogicalText || typeof payload.text !== "string" || !payload.text.startsWith(acknowledgedLogicalText)) return payload;
|
|
1800
|
+
const remainingText = payload.text.slice(acknowledgedLogicalText.length);
|
|
1814
1801
|
const hasMedia = Boolean(payload.mediaUrl || payload.mediaUrls?.length);
|
|
1815
1802
|
if (!remainingText && !hasMedia) return;
|
|
1816
1803
|
return {
|
|
@@ -1826,15 +1813,7 @@ function createTeamsReplyStreamController(params) {
|
|
|
1826
1813
|
} : payload;
|
|
1827
1814
|
};
|
|
1828
1815
|
const finalStreamActivity = (text) => ({
|
|
1829
|
-
|
|
1830
|
-
...text ? { text } : {},
|
|
1831
|
-
entities: [{
|
|
1832
|
-
type: "https://schema.org/Message",
|
|
1833
|
-
"@type": "Message",
|
|
1834
|
-
"@context": "https://schema.org",
|
|
1835
|
-
"@id": "",
|
|
1836
|
-
additionalType: ["AIGeneratedContent"]
|
|
1837
|
-
}],
|
|
1816
|
+
...require_messenger.buildMSTeamsMessageActivity(text === void 0 ? void 0 : require_messenger.formatMSTeamsMarkdown(text, params.tableMode ?? "code")),
|
|
1838
1817
|
channelData: params.feedbackLoopEnabled ? { feedbackLoopEnabled: true } : {}
|
|
1839
1818
|
});
|
|
1840
1819
|
const deferredReplacementLogicalContent = () => {
|
|
@@ -1854,34 +1833,23 @@ function createTeamsReplyStreamController(params) {
|
|
|
1854
1833
|
deferredReplacementEntries = [];
|
|
1855
1834
|
return payloads;
|
|
1856
1835
|
};
|
|
1857
|
-
|
|
1858
|
-
|
|
1859
|
-
|
|
1860
|
-
|
|
1861
|
-
|
|
1862
|
-
|
|
1863
|
-
|
|
1864
|
-
|
|
1865
|
-
|
|
1866
|
-
|
|
1867
|
-
|
|
1868
|
-
|
|
1869
|
-
|
|
1870
|
-
|
|
1871
|
-
});
|
|
1872
|
-
if (!informativeText || informativeText === lastInformativeText) return;
|
|
1873
|
-
lastInformativeText = informativeText;
|
|
1874
|
-
try {
|
|
1875
|
-
stream.update(informativeText);
|
|
1876
|
-
} catch (err) {
|
|
1877
|
-
if (isStreamCancelledError(err)) {
|
|
1878
|
-
canceledLocally = true;
|
|
1879
|
-
return;
|
|
1836
|
+
const progressDraft = (0, openclaw_plugin_sdk_channel_outbound.createChannelProgressDraftCompositor)({
|
|
1837
|
+
entry: params.msteamsConfig,
|
|
1838
|
+
mode: streamMode,
|
|
1839
|
+
active: Boolean(stream) && streamMode === "progress",
|
|
1840
|
+
seed: params.progressSeed ?? "msteams",
|
|
1841
|
+
update: (text) => {
|
|
1842
|
+
if (!stream || wasCanceled() || streamFinalizationPending) return false;
|
|
1843
|
+
try {
|
|
1844
|
+
stream.update(text.replace(/^• /gmu, "- "));
|
|
1845
|
+
return true;
|
|
1846
|
+
} catch (err) {
|
|
1847
|
+
if (isStreamCancelledError(err)) canceledLocally = true;
|
|
1848
|
+
else params.log?.debug?.(`stream informative update failed: ${(0, openclaw_plugin_sdk_error_runtime.coerceErrorMessage)(err)}`);
|
|
1849
|
+
return false;
|
|
1880
1850
|
}
|
|
1881
|
-
params.log?.debug?.(`stream informative update failed: ${(0, openclaw_plugin_sdk_error_runtime.coerceErrorMessage)(err)}`);
|
|
1882
1851
|
}
|
|
1883
|
-
};
|
|
1884
|
-
const progressDraftGate = (0, openclaw_plugin_sdk_channel_outbound.createChannelProgressDraftGate)({ onStart: renderInformativeUpdate });
|
|
1852
|
+
});
|
|
1885
1853
|
return {
|
|
1886
1854
|
async onReplyStart() {},
|
|
1887
1855
|
onPartialReply(payload) {
|
|
@@ -1890,7 +1858,7 @@ function createTeamsReplyStreamController(params) {
|
|
|
1890
1858
|
pendingFinalPayload = { text: payload.text };
|
|
1891
1859
|
return;
|
|
1892
1860
|
}
|
|
1893
|
-
if (streamFinalizationPending) return;
|
|
1861
|
+
if (streamFinalizationPending || nativeDeliveryClaimed) return;
|
|
1894
1862
|
const fullText = payload.text;
|
|
1895
1863
|
let prefixLength = 0;
|
|
1896
1864
|
while (prefixLength < emittedText.length && prefixLength < fullText.length && emittedText[prefixLength] === fullText[prefixLength]) prefixLength += 1;
|
|
@@ -1923,45 +1891,27 @@ function createTeamsReplyStreamController(params) {
|
|
|
1923
1891
|
params.log?.warn?.(`msteams stream emit failed, falling back to block delivery: ${(0, openclaw_plugin_sdk_error_runtime.coerceErrorMessage)(err)}`);
|
|
1924
1892
|
}
|
|
1925
1893
|
},
|
|
1926
|
-
/**
|
|
1927
|
-
* Note that the agent is working — bumps the progress-draft gate so the
|
|
1928
|
-
* informative status starts (or refreshes) on the next render. Called
|
|
1929
|
-
* from the reply-dispatcher's typing callbacks.
|
|
1930
|
-
*/
|
|
1931
1894
|
async noteProgressWork(options) {
|
|
1932
|
-
if (!stream || streamMode !== "progress") return;
|
|
1933
1895
|
if (options?.toolName !== void 0 && !(0, openclaw_plugin_sdk_channel_outbound.isChannelProgressDraftWorkToolName)(options.toolName)) return;
|
|
1934
|
-
|
|
1935
|
-
const progressActive = await progressDraftGate.noteWork();
|
|
1936
|
-
if ((hadStarted || progressActive) && progressDraftGate.hasStarted) renderInformativeUpdate();
|
|
1896
|
+
await progressDraft.noteActivity();
|
|
1937
1897
|
},
|
|
1938
|
-
/**
|
|
1939
|
-
* Append a tool-progress line (e.g. a tool name being invoked) into the
|
|
1940
|
-
* preview card's informative status. Only takes effect in "progress" mode
|
|
1941
|
-
* with `streaming.previewToolProgress` enabled in config.
|
|
1942
|
-
*/
|
|
1943
1898
|
async pushProgressLine(line, options) {
|
|
1944
|
-
|
|
1945
|
-
|
|
1946
|
-
|
|
1947
|
-
|
|
1948
|
-
|
|
1949
|
-
|
|
1950
|
-
|
|
1951
|
-
|
|
1952
|
-
if ((hadStarted || progressActive) && progressDraftGate.hasStarted) renderInformativeUpdate();
|
|
1899
|
+
await progressDraft.pushToolProgress(line, options);
|
|
1900
|
+
},
|
|
1901
|
+
async pushReasoningProgress(text, options) {
|
|
1902
|
+
await progressDraft.pushReasoningProgress(text, options);
|
|
1903
|
+
},
|
|
1904
|
+
resetReasoningProgress: () => progressDraft.resetReasoningProgress(),
|
|
1905
|
+
async pushApprovalEvent(payload) {
|
|
1906
|
+
await progressDraft.pushApprovalEvent(payload);
|
|
1953
1907
|
},
|
|
1954
1908
|
async pushPlanProgress(steps, options) {
|
|
1955
|
-
|
|
1956
|
-
latestPlan = steps?.length ? steps.map((entry) => ({ ...entry })) : void 0;
|
|
1957
|
-
latestPlanExplanation = options?.explanation?.replace(/\s+/g, " ").trim() || void 0;
|
|
1958
|
-
const hadStarted = progressDraftGate.hasStarted;
|
|
1959
|
-
await progressDraftGate.startNow();
|
|
1960
|
-
if (hadStarted && progressDraftGate.hasStarted) renderInformativeUpdate();
|
|
1909
|
+
await progressDraft.pushPlanProgress(steps, options);
|
|
1961
1910
|
},
|
|
1962
1911
|
preparePayload(payload) {
|
|
1963
1912
|
if (!stream) return payload;
|
|
1964
1913
|
if (wasCanceled()) return;
|
|
1914
|
+
if (payload.text) progressDraft.markFinalReplyStarted();
|
|
1965
1915
|
if (replacementSettlementPending) {
|
|
1966
1916
|
if (!replacementFinalPending) {
|
|
1967
1917
|
deferredReplacementEntries.push({
|
|
@@ -1984,9 +1934,13 @@ function createTeamsReplyStreamController(params) {
|
|
|
1984
1934
|
});
|
|
1985
1935
|
pendingFinalPayload = fallbackPayloadForSuppressedFinal(payload);
|
|
1986
1936
|
try {
|
|
1987
|
-
|
|
1988
|
-
|
|
1989
|
-
|
|
1937
|
+
const activity = finalStreamActivity(payload.text);
|
|
1938
|
+
replacementTextAwaitingAcknowledgement = {
|
|
1939
|
+
text: activity.text,
|
|
1940
|
+
logicalText: payload.text
|
|
1941
|
+
};
|
|
1942
|
+
stream.emit(activity);
|
|
1943
|
+
queuedFinalActivity = activity;
|
|
1990
1944
|
emittedText = payload.text;
|
|
1991
1945
|
tokensEmitted = false;
|
|
1992
1946
|
return;
|
|
@@ -2005,31 +1959,17 @@ function createTeamsReplyStreamController(params) {
|
|
|
2005
1959
|
return;
|
|
2006
1960
|
}
|
|
2007
1961
|
}
|
|
2008
|
-
if (tokensEmitted && !streamFailed) {
|
|
2009
|
-
const hasMedia = Boolean(payload.mediaUrl || payload.mediaUrls?.length);
|
|
2010
|
-
pendingFinalPayload = fallbackPayloadForSuppressedFinal(payload);
|
|
2011
|
-
streamFinalizationPending = true;
|
|
2012
|
-
tokensEmitted = false;
|
|
2013
|
-
return hasMedia ? {
|
|
2014
|
-
...payload,
|
|
2015
|
-
text: void 0
|
|
2016
|
-
} : void 0;
|
|
2017
|
-
}
|
|
2018
1962
|
if (streamFailed) {
|
|
2019
1963
|
const fallback = failedSegmentFallbackPrepared ? payload : fallbackPayloadAfterAcknowledgedText(payload);
|
|
2020
1964
|
failedSegmentFallbackPrepared = true;
|
|
2021
1965
|
pendingFinalPayload = void 0;
|
|
2022
1966
|
return fallback;
|
|
2023
1967
|
}
|
|
2024
|
-
if (streamMode === "progress" && payload.text) try {
|
|
1968
|
+
if (streamMode === "progress" && payload.text && !nativeDispatchStarted) try {
|
|
2025
1969
|
stream.emit(payload.text);
|
|
1970
|
+
emittedText = payload.text;
|
|
2026
1971
|
nativeDispatchStarted = true;
|
|
2027
|
-
|
|
2028
|
-
streamFinalizationPending = true;
|
|
2029
|
-
return Boolean(payload.mediaUrl || payload.mediaUrls?.length) ? {
|
|
2030
|
-
...payload,
|
|
2031
|
-
text: void 0
|
|
2032
|
-
} : void 0;
|
|
1972
|
+
tokensEmitted = true;
|
|
2033
1973
|
} catch (err) {
|
|
2034
1974
|
if (isStreamCancelledError(err)) {
|
|
2035
1975
|
canceledLocally = true;
|
|
@@ -2037,6 +1977,16 @@ function createTeamsReplyStreamController(params) {
|
|
|
2037
1977
|
}
|
|
2038
1978
|
params.log?.debug?.(`progress-mode finalize failed: ${(0, openclaw_plugin_sdk_error_runtime.coerceErrorMessage)(err)}`);
|
|
2039
1979
|
}
|
|
1980
|
+
if (tokensEmitted) {
|
|
1981
|
+
const hasMedia = Boolean(payload.mediaUrl || payload.mediaUrls?.length);
|
|
1982
|
+
pendingFinalPayload = fallbackPayloadForSuppressedFinal(payload);
|
|
1983
|
+
streamFinalizationPending = true;
|
|
1984
|
+
tokensEmitted = false;
|
|
1985
|
+
return hasMedia ? {
|
|
1986
|
+
...payload,
|
|
1987
|
+
text: void 0
|
|
1988
|
+
} : void 0;
|
|
1989
|
+
}
|
|
2040
1990
|
return payload;
|
|
2041
1991
|
},
|
|
2042
1992
|
claimNativeDelivery() {
|
|
@@ -2045,7 +1995,7 @@ function createTeamsReplyStreamController(params) {
|
|
|
2045
1995
|
return true;
|
|
2046
1996
|
},
|
|
2047
1997
|
async finalize() {
|
|
2048
|
-
|
|
1998
|
+
progressDraft.markFinalReplyStarted();
|
|
2049
1999
|
if (!stream || !nativeDispatchStarted) {
|
|
2050
2000
|
releaseStreamChunkSubscription();
|
|
2051
2001
|
return { visibleReplySent: false };
|
|
@@ -2065,15 +2015,34 @@ function createTeamsReplyStreamController(params) {
|
|
|
2065
2015
|
kind: "replacement",
|
|
2066
2016
|
payload: pendingFinalPayload
|
|
2067
2017
|
});
|
|
2068
|
-
|
|
2018
|
+
const activity = finalStreamActivity(pendingFinalPayload.text);
|
|
2019
|
+
replacementTextAwaitingAcknowledgement = {
|
|
2020
|
+
text: activity.text,
|
|
2021
|
+
logicalText: pendingFinalPayload.text
|
|
2022
|
+
};
|
|
2069
2023
|
logicalContent = deferredReplacementLogicalContent();
|
|
2070
|
-
stream.emit(
|
|
2071
|
-
|
|
2024
|
+
stream.emit(activity);
|
|
2025
|
+
queuedFinalActivity = activity;
|
|
2072
2026
|
emittedText = pendingFinalPayload.text;
|
|
2073
2027
|
}
|
|
2074
2028
|
logicalContent ??= replacementSettlementPending ? deferredReplacementLogicalContent() : void 0;
|
|
2075
|
-
const
|
|
2076
|
-
|
|
2029
|
+
const logicalText = pendingFinalPayload?.text ?? (emittedText || void 0);
|
|
2030
|
+
const finalActivity = queuedFinalActivity ?? finalStreamActivity(logicalText);
|
|
2031
|
+
const content = finalActivity.text;
|
|
2032
|
+
logicalContent ??= content !== logicalText ? logicalText : void 0;
|
|
2033
|
+
if (!queuedFinalActivity) {
|
|
2034
|
+
if (content !== void 0 && content !== emittedText) {
|
|
2035
|
+
stream.clearText();
|
|
2036
|
+
replacementTextAwaitingAcknowledgement = {
|
|
2037
|
+
text: content,
|
|
2038
|
+
logicalText
|
|
2039
|
+
};
|
|
2040
|
+
stream.emit(finalActivity);
|
|
2041
|
+
} else stream.emit({
|
|
2042
|
+
...finalActivity,
|
|
2043
|
+
text: void 0
|
|
2044
|
+
});
|
|
2045
|
+
}
|
|
2077
2046
|
const result = await stream.close();
|
|
2078
2047
|
streamFinalizationPending = false;
|
|
2079
2048
|
if (!result) {
|
|
@@ -2126,7 +2095,8 @@ function createTeamsReplyStreamController(params) {
|
|
|
2126
2095
|
...postNativePayloads.length > 0 ? { postNativePayloads } : {}
|
|
2127
2096
|
};
|
|
2128
2097
|
} finally {
|
|
2129
|
-
|
|
2098
|
+
failedSegmentFallbackPrepared = true;
|
|
2099
|
+
queuedFinalActivity = void 0;
|
|
2130
2100
|
replacementEmitFailed = false;
|
|
2131
2101
|
replacementFinalPending = false;
|
|
2132
2102
|
replacementSettlementPending = false;
|
|
@@ -2219,6 +2189,7 @@ function createMSTeamsReplyDispatcher(params) {
|
|
|
2219
2189
|
const feedbackLoopEnabled = params.cfg.channels?.msteams?.feedbackEnabled !== false;
|
|
2220
2190
|
const hookRunner = (0, openclaw_plugin_sdk_plugin_runtime.getGlobalHookRunner)();
|
|
2221
2191
|
const streamController = createTeamsReplyStreamController({
|
|
2192
|
+
tableMode,
|
|
2222
2193
|
allowProviderPreview: !((hookRunner?.hasHooks("reply_payload_sending") ?? false) || (hookRunner?.hasHooks("message_sending") ?? false)),
|
|
2223
2194
|
conversationType,
|
|
2224
2195
|
context: params.context,
|
|
@@ -2234,6 +2205,8 @@ function createMSTeamsReplyDispatcher(params) {
|
|
|
2234
2205
|
const blockStreamingEnabled = blockStreamingResolved ?? false;
|
|
2235
2206
|
const typingIndicatorEnabled = typeof msteamsCfg?.typingIndicator === "boolean" ? msteamsCfg.typingIndicator : true;
|
|
2236
2207
|
const pendingDeliveries = [];
|
|
2208
|
+
let pendingSettlement;
|
|
2209
|
+
const findPendingNativeDelivery = () => pendingDeliveries.find((candidate) => candidate.native && !candidate.nativeSettled);
|
|
2237
2210
|
const joinAcceptedContents = (contents) => contents.filter((content) => Boolean(content)).join("\n");
|
|
2238
2211
|
const sendMessages = async (messages) => {
|
|
2239
2212
|
return require_messenger.sendMSTeamsMessages({
|
|
@@ -2376,9 +2349,11 @@ function createMSTeamsReplyDispatcher(params) {
|
|
|
2376
2349
|
const delivery = {
|
|
2377
2350
|
observeMessageSent: true,
|
|
2378
2351
|
deliver: async (payload) => {
|
|
2352
|
+
if (pendingSettlement) await pendingSettlement;
|
|
2379
2353
|
const preparedPayload = streamController.preparePayload(payload);
|
|
2380
2354
|
const native = streamController.claimNativeDelivery();
|
|
2381
|
-
|
|
2355
|
+
if (preparedPayload && !native && findPendingNativeDelivery()) await settleDelivery();
|
|
2356
|
+
const messages = preparedPayload && !streamController.wasCanceled() ? renderReplyPayload(preparedPayload) : [];
|
|
2382
2357
|
if (!native && messages.length === 0) return {
|
|
2383
2358
|
visibleReplySent: false,
|
|
2384
2359
|
suppression: { reason: "no_visible_result" }
|
|
@@ -2404,9 +2379,9 @@ function createMSTeamsReplyDispatcher(params) {
|
|
|
2404
2379
|
});
|
|
2405
2380
|
}
|
|
2406
2381
|
};
|
|
2407
|
-
const settleDelivery = async () => {
|
|
2382
|
+
const settleDelivery = () => pendingSettlement ??= Promise.resolve().then(async () => {
|
|
2408
2383
|
await flushPendingMessages();
|
|
2409
|
-
const nativeDelivery =
|
|
2384
|
+
const nativeDelivery = findPendingNativeDelivery();
|
|
2410
2385
|
if (!nativeDelivery) {
|
|
2411
2386
|
await streamController.finalize();
|
|
2412
2387
|
return;
|
|
@@ -2440,25 +2415,18 @@ function createMSTeamsReplyDispatcher(params) {
|
|
|
2440
2415
|
} catch (error) {
|
|
2441
2416
|
params.log.warn?.("failed to record sent Teams message id", { error: require_channel_setup.formatUnknownError(error) });
|
|
2442
2417
|
}
|
|
2443
|
-
}
|
|
2444
|
-
|
|
2445
|
-
|
|
2446
|
-
const shouldSuppressDefaultToolProgressMessages = streamController.hasStream() && teamsStreamMode === "progress"
|
|
2418
|
+
}).finally(() => {
|
|
2419
|
+
pendingSettlement = void 0;
|
|
2420
|
+
});
|
|
2421
|
+
const shouldSuppressDefaultToolProgressMessages = streamController.hasStream() && teamsStreamMode === "progress";
|
|
2447
2422
|
const progressCallbacks = streamController.hasStream() ? {
|
|
2448
2423
|
onReasoningStream: async (payload) => {
|
|
2449
2424
|
const text = typeof payload?.text === "string" ? payload.text : void 0;
|
|
2450
|
-
|
|
2451
|
-
|
|
2452
|
-
|
|
2453
|
-
|
|
2454
|
-
|
|
2455
|
-
await streamController.pushProgressLine((0, openclaw_plugin_sdk_channel_outbound.buildChannelProgressDraftLine)({
|
|
2456
|
-
event: "item",
|
|
2457
|
-
itemId: "reasoning",
|
|
2458
|
-
itemKind: "analysis",
|
|
2459
|
-
title: "Reasoning",
|
|
2460
|
-
progressText: text
|
|
2461
|
-
}));
|
|
2425
|
+
await streamController.pushReasoningProgress(text, { snapshot: payload?.isReasoningSnapshot === true });
|
|
2426
|
+
return false;
|
|
2427
|
+
},
|
|
2428
|
+
onReasoningEnd: () => {
|
|
2429
|
+
streamController.resetReasoningProgress();
|
|
2462
2430
|
return false;
|
|
2463
2431
|
},
|
|
2464
2432
|
onToolStart: async (payload) => {
|
|
@@ -2496,15 +2464,14 @@ function createMSTeamsReplyDispatcher(params) {
|
|
|
2496
2464
|
return false;
|
|
2497
2465
|
},
|
|
2498
2466
|
onApprovalEvent: async (payload) => {
|
|
2499
|
-
|
|
2500
|
-
|
|
2501
|
-
|
|
2502
|
-
phase: payload.phase,
|
|
2467
|
+
await streamController.pushApprovalEvent({
|
|
2468
|
+
...typeof payload?.phase === "string" ? { phase: payload.phase } : {},
|
|
2469
|
+
...typeof payload?.approvalId === "string" ? { approvalId: payload.approvalId } : {},
|
|
2503
2470
|
...typeof payload?.title === "string" ? { title: payload.title } : {},
|
|
2504
2471
|
...typeof payload?.command === "string" ? { command: payload.command } : {},
|
|
2505
2472
|
...typeof payload?.reason === "string" ? { reason: payload.reason } : {},
|
|
2506
2473
|
...typeof payload?.message === "string" ? { message: payload.message } : {}
|
|
2507
|
-
})
|
|
2474
|
+
});
|
|
2508
2475
|
return false;
|
|
2509
2476
|
},
|
|
2510
2477
|
onCommandOutput: async (payload) => {
|
|
@@ -2636,7 +2603,6 @@ async function dispatchMSTeamsInboundTurn(params) {
|
|
|
2636
2603
|
allowNameMatching
|
|
2637
2604
|
}).allowed
|
|
2638
2605
|
}) : true;
|
|
2639
|
-
const bodyForAgent = threadContext ? `[Thread history]\n${threadContext}\n[/Thread history]\n\n${agentBody}` : agentBody;
|
|
2640
2606
|
const nativeChannelId = isChannel && teamAadGroupId ? `${teamAadGroupId}/${graphChannelId}` : void 0;
|
|
2641
2607
|
const boundIngress = await resolveMSTeamsSenderAccess({
|
|
2642
2608
|
cfg,
|
|
@@ -2655,13 +2621,25 @@ async function dispatchMSTeamsInboundTurn(params) {
|
|
|
2655
2621
|
channelIngress: boundIngress.channelIngress,
|
|
2656
2622
|
channel: "msteams",
|
|
2657
2623
|
contextVisibility: contextVisibilityMode,
|
|
2658
|
-
supplemental: {
|
|
2659
|
-
|
|
2660
|
-
|
|
2661
|
-
|
|
2662
|
-
|
|
2663
|
-
|
|
2664
|
-
|
|
2624
|
+
supplemental: {
|
|
2625
|
+
channelStructuredContext: threadContext.length ? [{
|
|
2626
|
+
label: "Thread history",
|
|
2627
|
+
source: "msteams",
|
|
2628
|
+
type: "chat_window",
|
|
2629
|
+
sessionTranscriptMode: "preserve",
|
|
2630
|
+
payload: {
|
|
2631
|
+
order: "chronological",
|
|
2632
|
+
messages: threadContext
|
|
2633
|
+
}
|
|
2634
|
+
}] : void 0,
|
|
2635
|
+
quote: quoteInfo ? {
|
|
2636
|
+
id: quoteInfo.id ?? activity.replyToId ?? void 0,
|
|
2637
|
+
body: quoteBodyFull ?? quoteInfo.body,
|
|
2638
|
+
sender: quoteInfo.sender,
|
|
2639
|
+
senderAllowed: quoteSenderAllowed,
|
|
2640
|
+
isQuote: true
|
|
2641
|
+
} : void 0
|
|
2642
|
+
},
|
|
2665
2643
|
media: await (0, openclaw_plugin_sdk_channel_inbound.toInboundMediaFactsWithMetadata)(inboundMedia),
|
|
2666
2644
|
messageId: activity.id,
|
|
2667
2645
|
timestamp: timestamp?.getTime() ?? Date.now(),
|
|
@@ -2692,7 +2670,7 @@ async function dispatchMSTeamsInboundTurn(params) {
|
|
|
2692
2670
|
},
|
|
2693
2671
|
message: {
|
|
2694
2672
|
body: combinedBody,
|
|
2695
|
-
bodyForAgent,
|
|
2673
|
+
bodyForAgent: agentBody,
|
|
2696
2674
|
inboundHistory,
|
|
2697
2675
|
rawBody,
|
|
2698
2676
|
commandBody
|
|
@@ -2753,7 +2731,7 @@ async function dispatchMSTeamsInboundTurn(params) {
|
|
|
2753
2731
|
id: activity.id ?? `${teamsFrom}:${Date.now()}`,
|
|
2754
2732
|
timestamp: timestamp?.getTime(),
|
|
2755
2733
|
rawText: rawBody,
|
|
2756
|
-
textForAgent:
|
|
2734
|
+
textForAgent: agentBody,
|
|
2757
2735
|
textForCommands: commandBody,
|
|
2758
2736
|
raw: activity
|
|
2759
2737
|
}),
|
|
@@ -3096,7 +3074,7 @@ async function resolveMSTeamsThreadContext(params) {
|
|
|
3096
3074
|
} catch (err) {
|
|
3097
3075
|
params.log.debug?.("failed to fetch full quoted message text", { error: require_channel_setup.formatUnknownError(err) });
|
|
3098
3076
|
}
|
|
3099
|
-
let threadContext;
|
|
3077
|
+
let threadContext = [];
|
|
3100
3078
|
const threadParentId = params.routing.threadRootId;
|
|
3101
3079
|
if (threadParentId && threadParentId !== activity.id && params.isChannel && teamAadGroupId) try {
|
|
3102
3080
|
const graphToken = await require_resolve_allowlist.withMSTeamsRequestDeadline({
|
|
@@ -3147,7 +3125,7 @@ async function resolveMSTeamsThreadContext(params) {
|
|
|
3147
3125
|
kind: "thread",
|
|
3148
3126
|
isSenderAllowed: isThreadSenderAllowed
|
|
3149
3127
|
});
|
|
3150
|
-
threadContext = require_reaction_types.
|
|
3128
|
+
threadContext = require_reaction_types.buildThreadContext(threadMessages, activity.id);
|
|
3151
3129
|
} catch (err) {
|
|
3152
3130
|
params.log.debug?.("failed to fetch thread history", { error: require_channel_setup.formatUnknownError(err) });
|
|
3153
3131
|
}
|
|
@@ -3175,8 +3153,9 @@ function createMSTeamsMessageHandler(deps) {
|
|
|
3175
3153
|
});
|
|
3176
3154
|
const historyLimit = Math.max(0, msteamsCfg?.historyLimit ?? cfg.messages?.groupChat?.historyLimit ?? openclaw_plugin_sdk_reply_history.DEFAULT_GROUP_HISTORY_LIMIT);
|
|
3177
3155
|
const conversationHistories = /* @__PURE__ */ new Map();
|
|
3178
|
-
const
|
|
3179
|
-
|
|
3156
|
+
const readConfig = (0, openclaw_plugin_sdk_runtime_config_snapshot.createRuntimeConfigReader)(cfg);
|
|
3157
|
+
const resolveDebounceMs = () => core.channel.debounce.resolveInboundDebounceMs({
|
|
3158
|
+
cfg: readConfig(),
|
|
3180
3159
|
channel: "msteams"
|
|
3181
3160
|
});
|
|
3182
3161
|
const handleTeamsMessageNow = async (params) => {
|
|
@@ -3355,7 +3334,8 @@ function createMSTeamsMessageHandler(deps) {
|
|
|
3355
3334
|
});
|
|
3356
3335
|
};
|
|
3357
3336
|
const inboundDebouncer = core.channel.debounce.createInboundDebouncer({
|
|
3358
|
-
debounceMs:
|
|
3337
|
+
debounceMs: resolveDebounceMs(),
|
|
3338
|
+
resolveDebounceMs,
|
|
3359
3339
|
buildKey: (entry) => {
|
|
3360
3340
|
const conversationId = require_resolve_allowlist.normalizeMSTeamsConversationId(entry.context.activity.conversation?.id ?? "");
|
|
3361
3341
|
const senderId = entry.context.activity.from?.aadObjectId ?? entry.context.activity.from?.id ?? "";
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
const require_runtime = require("./runtime-gZTAuFux.cjs");
|
|
2
|
-
const require_polls = require("./polls-
|
|
2
|
+
const require_polls = require("./polls-BBdZPx_R.cjs");
|
|
3
3
|
let node_crypto = require("node:crypto");
|
|
4
4
|
//#region extensions/msteams/src/sso-token-store.ts
|
|
5
5
|
/**
|
package/openclaw.plugin.json
CHANGED
|
@@ -2,7 +2,23 @@
|
|
|
2
2
|
"id": "msteams",
|
|
3
3
|
"doctorContract": {
|
|
4
4
|
"configRepair": true,
|
|
5
|
-
"stateMigrations":
|
|
5
|
+
"stateMigrations": [
|
|
6
|
+
{
|
|
7
|
+
"id": "msteams-conversations-json-to-plugin-state"
|
|
8
|
+
},
|
|
9
|
+
{
|
|
10
|
+
"id": "msteams-polls-json-to-plugin-state"
|
|
11
|
+
},
|
|
12
|
+
{
|
|
13
|
+
"id": "msteams-sso-tokens-json-to-plugin-state"
|
|
14
|
+
},
|
|
15
|
+
{
|
|
16
|
+
"id": "msteams-delegated-token-json-to-plugin-state"
|
|
17
|
+
},
|
|
18
|
+
{
|
|
19
|
+
"id": "msteams-feedback-learnings-json-to-plugin-state"
|
|
20
|
+
}
|
|
21
|
+
]
|
|
6
22
|
},
|
|
7
23
|
"name": "Microsoft Teams",
|
|
8
24
|
"description": "OpenClaw Microsoft Teams channel plugin for bot conversations.",
|
|
@@ -751,7 +767,7 @@
|
|
|
751
767
|
},
|
|
752
768
|
"streaming.progress.toolProgress": {
|
|
753
769
|
"label": "MS Teams Progress Tool Lines",
|
|
754
|
-
"help": "Show
|
|
770
|
+
"help": "Show individual tool activity in progress drafts (default: false). Quiet drafts retain plans, approval requests, failures, and authored progress text."
|
|
755
771
|
},
|
|
756
772
|
"streaming.progress.commandText": {
|
|
757
773
|
"label": "MS Teams Progress Command Text",
|