mirror of
https://github.com/openclaw/openclaw.git
synced 2026-05-06 06:40:44 +00:00
fix: polish Slack thread starter context (#68594)
This commit is contained in:
@@ -69,6 +69,7 @@ Docs: https://docs.openclaw.ai
|
||||
- Gateway/restart: keep stale-gateway cleanup from terminating the current process's parent or ancestors, so plugin sidecars like WeChat no longer kill the active gateway and trigger an infinite supervisor restart loop. Fixes #68451. (#68517) Thanks @openperf.
|
||||
- Gateway/auth: reject gateway auth credentials that match published example placeholders at startup and secret reload, and keep cloud install snippets from publishing copy-paste gateway/keyring secrets. (#68404) Thanks @coygeek.
|
||||
- CLI/update: preserve macOS restart helper launchctl failures in the update restart log without letting log setup block the restart path. (#68492) Thanks @hclsys.
|
||||
- Slack/threads: keep file-only root messages as starter context so first thread replies can still hydrate starter media. (#68594) Thanks @martingarramon.
|
||||
|
||||
## 2026.4.15
|
||||
|
||||
|
||||
@@ -6,6 +6,7 @@ import type {
|
||||
} from "openclaw/plugin-sdk/config-runtime";
|
||||
import type { SessionScope } from "openclaw/plugin-sdk/config-runtime";
|
||||
import type { DmPolicy, GroupPolicy } from "openclaw/plugin-sdk/config-runtime";
|
||||
import { formatErrorMessage } from "openclaw/plugin-sdk/error-runtime";
|
||||
import { createDedupeCache } from "openclaw/plugin-sdk/infra-runtime";
|
||||
import type { HistoryEntry } from "openclaw/plugin-sdk/reply-history";
|
||||
import { resolveAgentRoute } from "openclaw/plugin-sdk/routing";
|
||||
@@ -282,7 +283,9 @@ export function createSlackMonitorContext(params: {
|
||||
status: p.status,
|
||||
});
|
||||
} catch (err) {
|
||||
logVerbose(`slack status update failed for channel ${p.channelId}: ${String(err)}`);
|
||||
logVerbose(
|
||||
`slack status update failed for channel ${p.channelId}: ${formatErrorMessage(err)}`,
|
||||
);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
import { formatAllowlistMatchMeta } from "openclaw/plugin-sdk/allow-from";
|
||||
import { createChannelPairingChallengeIssuer } from "openclaw/plugin-sdk/channel-pairing";
|
||||
import { formatErrorMessage } from "openclaw/plugin-sdk/error-runtime";
|
||||
import { resolveSlackAllowListMatch } from "./allow-list.js";
|
||||
import type { SlackMonitorContext } from "./context.js";
|
||||
import { upsertChannelPairingRequest } from "./conversation.runtime.js";
|
||||
@@ -57,7 +58,7 @@ export async function authorizeSlackDirectMessage(params: {
|
||||
);
|
||||
},
|
||||
onReplyError: (err) => {
|
||||
params.log(`slack pairing reply failed for ${params.senderId}: ${String(err)}`);
|
||||
params.log(`slack pairing reply failed for ${params.senderId}: ${formatErrorMessage(err)}`);
|
||||
},
|
||||
});
|
||||
return false;
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
import type { SlackEventMiddlewareArgs } from "@slack/bolt";
|
||||
import { resolveChannelConfigWrites } from "openclaw/plugin-sdk/channel-config-writes";
|
||||
import { loadConfig, writeConfigFile } from "openclaw/plugin-sdk/config-runtime";
|
||||
import { formatErrorMessage } from "openclaw/plugin-sdk/error-runtime";
|
||||
import { enqueueSystemEvent } from "openclaw/plugin-sdk/infra-runtime";
|
||||
import { danger, warn } from "openclaw/plugin-sdk/runtime-env";
|
||||
import { migrateSlackChannelConfig } from "../../channel-migration.js";
|
||||
@@ -61,7 +62,9 @@ export function registerSlackChannelEvents(params: {
|
||||
const channelName = payload.channel?.name;
|
||||
enqueueChannelSystemEvent({ kind: "created", channelId, channelName });
|
||||
} catch (err) {
|
||||
ctx.runtime.error?.(danger(`slack channel created handler failed: ${String(err)}`));
|
||||
ctx.runtime.error?.(
|
||||
danger(`slack channel created handler failed: ${formatErrorMessage(err)}`),
|
||||
);
|
||||
}
|
||||
},
|
||||
);
|
||||
@@ -80,7 +83,9 @@ export function registerSlackChannelEvents(params: {
|
||||
const channelName = payload.channel?.name_normalized ?? payload.channel?.name;
|
||||
enqueueChannelSystemEvent({ kind: "renamed", channelId, channelName });
|
||||
} catch (err) {
|
||||
ctx.runtime.error?.(danger(`slack channel rename handler failed: ${String(err)}`));
|
||||
ctx.runtime.error?.(
|
||||
danger(`slack channel rename handler failed: ${formatErrorMessage(err)}`),
|
||||
);
|
||||
}
|
||||
},
|
||||
);
|
||||
@@ -155,7 +160,9 @@ export function registerSlackChannelEvents(params: {
|
||||
);
|
||||
}
|
||||
} catch (err) {
|
||||
ctx.runtime.error?.(danger(`slack channel_id_changed handler failed: ${String(err)}`));
|
||||
ctx.runtime.error?.(
|
||||
danger(`slack channel_id_changed handler failed: ${formatErrorMessage(err)}`),
|
||||
);
|
||||
}
|
||||
},
|
||||
);
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
import type { SlackEventMiddlewareArgs } from "@slack/bolt";
|
||||
import { formatErrorMessage } from "openclaw/plugin-sdk/error-runtime";
|
||||
import { enqueueSystemEvent } from "openclaw/plugin-sdk/infra-runtime";
|
||||
import { danger } from "openclaw/plugin-sdk/runtime-env";
|
||||
import type { SlackMonitorContext } from "../context.js";
|
||||
@@ -42,7 +43,9 @@ export function registerSlackMemberEvents(params: {
|
||||
contextKey: `slack:member:${params.verb}:${channelId ?? "unknown"}:${payload.user ?? "unknown"}`,
|
||||
});
|
||||
} catch (err) {
|
||||
ctx.runtime.error?.(danger(`slack ${params.verb} handler failed: ${String(err)}`));
|
||||
ctx.runtime.error?.(
|
||||
danger(`slack ${params.verb} handler failed: ${formatErrorMessage(err)}`),
|
||||
);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
import type { SlackEventMiddlewareArgs } from "@slack/bolt";
|
||||
import { formatErrorMessage } from "openclaw/plugin-sdk/error-runtime";
|
||||
import { enqueueSystemEvent } from "openclaw/plugin-sdk/infra-runtime";
|
||||
import { danger } from "openclaw/plugin-sdk/runtime-env";
|
||||
import type { SlackAppMentionEvent, SlackMessageEvent } from "../../types.js";
|
||||
@@ -43,7 +44,7 @@ export function registerSlackMessageEvents(params: {
|
||||
|
||||
await handleSlackMessage(message, { source: "message" });
|
||||
} catch (err) {
|
||||
ctx.runtime.error?.(danger(`slack handler failed: ${String(err)}`));
|
||||
ctx.runtime.error?.(danger(`slack handler failed: ${formatErrorMessage(err)}`));
|
||||
}
|
||||
};
|
||||
|
||||
@@ -77,7 +78,7 @@ export function registerSlackMessageEvents(params: {
|
||||
wasMentioned: true,
|
||||
});
|
||||
} catch (err) {
|
||||
ctx.runtime.error?.(danger(`slack mention handler failed: ${String(err)}`));
|
||||
ctx.runtime.error?.(danger(`slack mention handler failed: ${formatErrorMessage(err)}`));
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
import type { SlackEventMiddlewareArgs } from "@slack/bolt";
|
||||
import { formatErrorMessage } from "openclaw/plugin-sdk/error-runtime";
|
||||
import { enqueueSystemEvent } from "openclaw/plugin-sdk/infra-runtime";
|
||||
import { danger } from "openclaw/plugin-sdk/runtime-env";
|
||||
import type { SlackMonitorContext } from "../context.js";
|
||||
@@ -45,7 +46,7 @@ async function handleSlackPinEvent(params: {
|
||||
},
|
||||
);
|
||||
} catch (err) {
|
||||
ctx.runtime.error?.(danger(`slack ${errorLabel} handler failed: ${String(err)}`));
|
||||
ctx.runtime.error?.(danger(`slack ${errorLabel} handler failed: ${formatErrorMessage(err)}`));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
import type { SlackEventMiddlewareArgs } from "@slack/bolt";
|
||||
import { formatErrorMessage } from "openclaw/plugin-sdk/error-runtime";
|
||||
import { enqueueSystemEvent } from "openclaw/plugin-sdk/infra-runtime";
|
||||
import { danger } from "openclaw/plugin-sdk/runtime-env";
|
||||
import type { SlackMonitorContext } from "../context.js";
|
||||
@@ -46,7 +47,7 @@ export function registerSlackReactionEvents(params: {
|
||||
contextKey: `slack:reaction:${action}:${item.channel}:${item.ts}:${event.user}:${emojiLabel}`,
|
||||
});
|
||||
} catch (err) {
|
||||
ctx.runtime.error?.(danger(`slack reaction handler failed: ${String(err)}`));
|
||||
ctx.runtime.error?.(danger(`slack reaction handler failed: ${formatErrorMessage(err)}`));
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
@@ -905,7 +905,7 @@ describe("resolveSlackThreadStarter", () => {
|
||||
expect(vi.mocked(logVerbose)).not.toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it("returns null when the starter message has no text and no files", async () => {
|
||||
it("returns null when the starter message has no text or files", async () => {
|
||||
const replies = vi.fn().mockResolvedValueOnce({ messages: [{ text: " ", user: "U1" }] });
|
||||
const client = {
|
||||
conversations: { replies },
|
||||
@@ -921,6 +921,37 @@ describe("resolveSlackThreadStarter", () => {
|
||||
expect(vi.mocked(logVerbose)).not.toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it("returns a placeholder starter when the root message only has files", async () => {
|
||||
const replies = vi.fn().mockResolvedValueOnce({
|
||||
messages: [
|
||||
{
|
||||
text: " ",
|
||||
user: "U1",
|
||||
ts: "1.000",
|
||||
files: [{ name: "root.png", mimetype: "image/png" }],
|
||||
},
|
||||
],
|
||||
});
|
||||
const client = {
|
||||
conversations: { replies },
|
||||
} as unknown as Parameters<typeof resolveSlackThreadStarter>[0]["client"];
|
||||
|
||||
const result = await resolveSlackThreadStarter({
|
||||
channelId: "C1",
|
||||
threadTs: "1.000",
|
||||
client,
|
||||
});
|
||||
|
||||
expect(result).toEqual({
|
||||
text: "[attached: root.png]",
|
||||
userId: "U1",
|
||||
botId: undefined,
|
||||
ts: "1.000",
|
||||
files: [{ name: "root.png", mimetype: "image/png" }],
|
||||
});
|
||||
expect(vi.mocked(logVerbose)).not.toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it("returns null and surfaces the error via logVerbose when Slack API throws", async () => {
|
||||
const replies = vi.fn().mockRejectedValueOnce(new Error("not_in_channel"));
|
||||
const client = {
|
||||
@@ -942,7 +973,7 @@ describe("resolveSlackThreadStarter", () => {
|
||||
expect(vi.mocked(logVerbose)).toHaveBeenCalledWith(expect.stringContaining("ts=9.999"));
|
||||
});
|
||||
|
||||
it("surfaces non-Error thrown values as String(err) via logVerbose", async () => {
|
||||
it("surfaces non-Error thrown values via logVerbose", async () => {
|
||||
const replies = vi.fn().mockRejectedValueOnce("rate_limited");
|
||||
const client = {
|
||||
conversations: { replies },
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
import type { WebClient as SlackWebClient } from "@slack/web-api";
|
||||
import { pruneMapToMaxSize } from "openclaw/plugin-sdk/collection-runtime";
|
||||
import { formatErrorMessage } from "openclaw/plugin-sdk/error-runtime";
|
||||
import { normalizeHostname } from "openclaw/plugin-sdk/host-runtime";
|
||||
import { fetchWithRuntimeDispatcher } from "openclaw/plugin-sdk/infra-runtime";
|
||||
@@ -385,18 +386,11 @@ function evictThreadStarterCache(): void {
|
||||
THREAD_STARTER_CACHE.delete(cacheKey);
|
||||
}
|
||||
}
|
||||
if (THREAD_STARTER_CACHE.size <= THREAD_STARTER_CACHE_MAX) {
|
||||
return;
|
||||
}
|
||||
const excess = THREAD_STARTER_CACHE.size - THREAD_STARTER_CACHE_MAX;
|
||||
let removed = 0;
|
||||
for (const cacheKey of THREAD_STARTER_CACHE.keys()) {
|
||||
THREAD_STARTER_CACHE.delete(cacheKey);
|
||||
removed += 1;
|
||||
if (removed >= excess) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
pruneMapToMaxSize(THREAD_STARTER_CACHE, THREAD_STARTER_CACHE_MAX);
|
||||
}
|
||||
|
||||
function formatSlackFilePlaceholder(files: SlackFile[] | undefined): string {
|
||||
return `[attached: ${files?.map((file) => file.name ?? "file").join(", ") ?? "file"}]`;
|
||||
}
|
||||
|
||||
export async function resolveSlackThreadStarter(params: {
|
||||
@@ -430,15 +424,16 @@ export async function resolveSlackThreadStarter(params: {
|
||||
};
|
||||
const message = response?.messages?.[0];
|
||||
const text = (message?.text ?? "").trim();
|
||||
if (!message || !text) {
|
||||
const files = message?.files?.length ? message.files : undefined;
|
||||
if (!message || (!text && !files)) {
|
||||
return null;
|
||||
}
|
||||
const starter: SlackThreadStarter = {
|
||||
text,
|
||||
text: text || formatSlackFilePlaceholder(files),
|
||||
userId: message.user,
|
||||
botId: message.bot_id,
|
||||
ts: message.ts,
|
||||
files: message.files,
|
||||
files,
|
||||
};
|
||||
if (THREAD_STARTER_CACHE.has(cacheKey)) {
|
||||
THREAD_STARTER_CACHE.delete(cacheKey);
|
||||
@@ -536,9 +531,7 @@ export async function resolveSlackThreadHistory(params: {
|
||||
|
||||
return retained.map((msg) => ({
|
||||
// For file-only messages, create a placeholder showing attached filenames
|
||||
text: msg.text?.trim()
|
||||
? msg.text
|
||||
: `[attached: ${msg.files?.map((f) => f.name ?? "file").join(", ")}]`,
|
||||
text: msg.text?.trim() ? msg.text : formatSlackFilePlaceholder(msg.files),
|
||||
userId: msg.user,
|
||||
botId: msg.bot_id,
|
||||
ts: msg.ts,
|
||||
|
||||
@@ -2,6 +2,7 @@ import {
|
||||
createChannelInboundDebouncer,
|
||||
shouldDebounceTextInbound,
|
||||
} from "openclaw/plugin-sdk/channel-inbound";
|
||||
import { formatErrorMessage } from "openclaw/plugin-sdk/error-runtime";
|
||||
import type { ResolvedSlackAccount } from "../accounts.js";
|
||||
import type { SlackMessageEvent } from "../types.js";
|
||||
import { stripSlackMentionsForCommandDetection } from "./commands.js";
|
||||
@@ -189,7 +190,7 @@ export function createSlackMessageHandler(params: {
|
||||
}
|
||||
},
|
||||
onError: (err) => {
|
||||
ctx.runtime.error?.(`slack inbound debounce flush failed: ${String(err)}`);
|
||||
ctx.runtime.error?.(`slack inbound debounce flush failed: ${formatErrorMessage(err)}`);
|
||||
},
|
||||
});
|
||||
const threadTsResolver = createSlackThreadTsResolver({ client: ctx.app.client });
|
||||
|
||||
@@ -12,6 +12,7 @@ import {
|
||||
resolveChannelStreamingBlockEnabled,
|
||||
resolveChannelStreamingNativeTransport,
|
||||
} from "openclaw/plugin-sdk/channel-streaming";
|
||||
import { formatErrorMessage } from "openclaw/plugin-sdk/error-runtime";
|
||||
import { resolveAgentOutboundIdentity } from "openclaw/plugin-sdk/outbound-runtime";
|
||||
import { clearHistoryEntriesIfEnabled } from "openclaw/plugin-sdk/reply-history";
|
||||
import { resolveSendableOutboundReplyParts } from "openclaw/plugin-sdk/reply-payload";
|
||||
@@ -199,7 +200,7 @@ export async function resolveSlackStreamRecipientTeamId(params: {
|
||||
return teamId;
|
||||
}
|
||||
} catch (err) {
|
||||
logVerbose(`slack-stream: users.info team lookup failed (${String(err)})`);
|
||||
logVerbose(`slack-stream: users.info team lookup failed (${formatErrorMessage(err)})`);
|
||||
}
|
||||
}
|
||||
return params.fallbackTeamId;
|
||||
@@ -273,7 +274,7 @@ export async function dispatchPreparedSlackMessage(prepared: PreparedSlackMessag
|
||||
token: ctx.botToken,
|
||||
client: ctx.app.client,
|
||||
}).catch((err) => {
|
||||
if (String(err).includes("already_reacted")) {
|
||||
if (formatErrorMessage(err).includes("already_reacted")) {
|
||||
return;
|
||||
}
|
||||
throw err;
|
||||
@@ -284,7 +285,7 @@ export async function dispatchPreparedSlackMessage(prepared: PreparedSlackMessag
|
||||
token: ctx.botToken,
|
||||
client: ctx.app.client,
|
||||
}).catch((err) => {
|
||||
if (String(err).includes("no_reaction")) {
|
||||
if (formatErrorMessage(err).includes("no_reaction")) {
|
||||
return;
|
||||
}
|
||||
throw err;
|
||||
@@ -556,7 +557,7 @@ export async function dispatchPreparedSlackMessage(prepared: PreparedSlackMessag
|
||||
});
|
||||
} catch (err) {
|
||||
runtime.error?.(
|
||||
danger(`slack-stream: streaming API call failed: ${String(err)}, falling back`),
|
||||
danger(`slack-stream: streaming API call failed: ${formatErrorMessage(err)}, falling back`),
|
||||
);
|
||||
streamFailed = true;
|
||||
await deliverNormally({
|
||||
@@ -613,7 +614,7 @@ export async function dispatchPreparedSlackMessage(prepared: PreparedSlackMessag
|
||||
return;
|
||||
} catch (err) {
|
||||
logVerbose(
|
||||
`slack: preview final edit failed; falling back to standard send (${String(err)})`,
|
||||
`slack: preview final edit failed; falling back to standard send (${formatErrorMessage(err)})`,
|
||||
);
|
||||
}
|
||||
} else if (previewStreamingEnabled && streamMode === "status_final" && hasStreamedMessage) {
|
||||
@@ -629,7 +630,7 @@ export async function dispatchPreparedSlackMessage(prepared: PreparedSlackMessag
|
||||
});
|
||||
}
|
||||
} catch (err) {
|
||||
logVerbose(`slack: status_final completion update failed (${String(err)})`);
|
||||
logVerbose(`slack: status_final completion update failed (${formatErrorMessage(err)})`);
|
||||
}
|
||||
} else if (reply.hasMedia) {
|
||||
await draftStream?.clear();
|
||||
@@ -639,7 +640,7 @@ export async function dispatchPreparedSlackMessage(prepared: PreparedSlackMessag
|
||||
await deliverNormally({ payload, kind: info.kind });
|
||||
},
|
||||
onError: (err, info) => {
|
||||
runtime.error?.(danger(`slack ${info.kind} reply failed: ${String(err)}`));
|
||||
runtime.error?.(danger(`slack ${info.kind} reply failed: ${formatErrorMessage(err)}`));
|
||||
replyPipeline.typingCallbacks?.onIdle?.();
|
||||
},
|
||||
});
|
||||
@@ -771,7 +772,7 @@ export async function dispatchPreparedSlackMessage(prepared: PreparedSlackMessag
|
||||
try {
|
||||
await stopSlackStream({ session: finalStream });
|
||||
} catch (err) {
|
||||
runtime.error?.(danger(`slack-stream: failed to stop stream: ${String(err)}`));
|
||||
runtime.error?.(danger(`slack-stream: failed to stop stream: ${formatErrorMessage(err)}`));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -15,6 +15,7 @@ import {
|
||||
import { resolveControlCommandGate } from "openclaw/plugin-sdk/command-auth";
|
||||
import { hasControlCommand } from "openclaw/plugin-sdk/command-auth";
|
||||
import { shouldHandleTextCommands } from "openclaw/plugin-sdk/command-auth";
|
||||
import { formatErrorMessage } from "openclaw/plugin-sdk/error-runtime";
|
||||
import { enqueueSystemEvent } from "openclaw/plugin-sdk/infra-runtime";
|
||||
import {
|
||||
buildPendingHistoryContextFromMap,
|
||||
@@ -596,7 +597,9 @@ export async function prepareSlackMessage(params: {
|
||||
}).then(
|
||||
() => true,
|
||||
(err) => {
|
||||
logVerbose(`slack react failed for channel ${message.channel}: ${String(err)}`);
|
||||
logVerbose(
|
||||
`slack react failed for channel ${message.channel}: ${formatErrorMessage(err)}`,
|
||||
);
|
||||
return false;
|
||||
},
|
||||
)
|
||||
@@ -804,7 +807,7 @@ export async function prepareSlackMessage(params: {
|
||||
onRecordError: (err) => {
|
||||
ctx.logger.warn(
|
||||
{
|
||||
error: String(err),
|
||||
error: formatErrorMessage(err),
|
||||
storePath,
|
||||
sessionKey,
|
||||
},
|
||||
|
||||
@@ -512,7 +512,9 @@ export async function monitorSlackProvider(opts: MonitorSlackOpts = {}) {
|
||||
summarizeMapping("slack channels", mapping, unresolved, runtime);
|
||||
}
|
||||
} catch (err) {
|
||||
runtime.log?.(`slack channel resolve failed; using config entries. ${String(err)}`);
|
||||
runtime.log?.(
|
||||
`slack channel resolve failed; using config entries. ${formatUnknownError(err)}`,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -533,7 +535,9 @@ export async function monitorSlackProvider(opts: MonitorSlackOpts = {}) {
|
||||
ctx.allowFrom = normalizeAllowList(allowFrom);
|
||||
summarizeMapping("slack users", mapping, unresolved, runtime);
|
||||
} catch (err) {
|
||||
runtime.log?.(`slack user resolve failed; using config entries. ${String(err)}`);
|
||||
runtime.log?.(
|
||||
`slack user resolve failed; using config entries. ${formatUnknownError(err)}`,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -565,7 +569,7 @@ export async function monitorSlackProvider(opts: MonitorSlackOpts = {}) {
|
||||
summarizeMapping("slack channel users", mapping, unresolved, runtime);
|
||||
} catch (err) {
|
||||
runtime.log?.(
|
||||
`slack channel user resolve failed; using config entries. ${String(err)}`,
|
||||
`slack channel user resolve failed; using config entries. ${formatUnknownError(err)}`,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -10,6 +10,7 @@ import {
|
||||
resolveNativeCommandsEnabled,
|
||||
resolveNativeSkillsEnabled,
|
||||
} from "openclaw/plugin-sdk/config-runtime";
|
||||
import { formatErrorMessage } from "openclaw/plugin-sdk/error-runtime";
|
||||
import type { ReplyPayload } from "openclaw/plugin-sdk/reply-runtime";
|
||||
import { danger, logVerbose } from "openclaw/plugin-sdk/runtime-env";
|
||||
import { chunkItems, normalizeLowercaseStringOrEmpty } from "openclaw/plugin-sdk/text-runtime";
|
||||
@@ -600,7 +601,9 @@ export async function registerSlackMonitorSlashCommands(params: {
|
||||
sessionKey: ctxPayload.SessionKey ?? route.sessionKey,
|
||||
ctx: ctxPayload,
|
||||
onError: (err) =>
|
||||
runtime.error?.(danger(`slack slash: failed updating session meta: ${String(err)}`)),
|
||||
runtime.error?.(
|
||||
danger(`slack slash: failed updating session meta: ${formatErrorMessage(err)}`),
|
||||
),
|
||||
});
|
||||
|
||||
const { onModelSelected, ...replyPipeline } = createChannelReplyPipeline({
|
||||
@@ -632,7 +635,9 @@ export async function registerSlackMonitorSlashCommands(params: {
|
||||
...replyPipeline,
|
||||
deliver: async (payload) => deliverSlashPayloads([payload]),
|
||||
onError: (err, info) => {
|
||||
runtime.error?.(danger(`slack slash ${info.kind} reply failed: ${String(err)}`));
|
||||
runtime.error?.(
|
||||
danger(`slack slash ${info.kind} reply failed: ${formatErrorMessage(err)}`),
|
||||
);
|
||||
},
|
||||
},
|
||||
replyOptions: {
|
||||
@@ -644,7 +649,7 @@ export async function registerSlackMonitorSlashCommands(params: {
|
||||
await deliverSlashPayloads([]);
|
||||
}
|
||||
} catch (err) {
|
||||
runtime.error?.(danger(`slack slash handler failed: ${String(err)}`));
|
||||
runtime.error?.(danger(`slack slash handler failed: ${formatErrorMessage(err)}`));
|
||||
await respond({
|
||||
text: "Sorry, something went wrong handling that command.",
|
||||
response_type: "ephemeral",
|
||||
@@ -803,7 +808,7 @@ export async function registerSlackMonitorSlashCommands(params: {
|
||||
} catch (err) {
|
||||
supportsExternalArgMenus = false;
|
||||
logVerbose(
|
||||
`slack: external arg-menu registration failed, falling back to static menus: ${String(err)}`,
|
||||
`slack: external arg-menu registration failed, falling back to static menus: ${formatErrorMessage(err)}`,
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
import type { WebClient as SlackWebClient } from "@slack/web-api";
|
||||
import { pruneMapToMaxSize } from "openclaw/plugin-sdk/collection-runtime";
|
||||
import { formatErrorMessage } from "openclaw/plugin-sdk/error-runtime";
|
||||
import { logVerbose, shouldLogVerbose } from "openclaw/plugin-sdk/runtime-env";
|
||||
import type { SlackMessageEvent } from "../types.js";
|
||||
|
||||
@@ -35,7 +36,7 @@ async function resolveThreadTsFromHistory(params: {
|
||||
} catch (err) {
|
||||
if (shouldLogVerbose()) {
|
||||
logVerbose(
|
||||
`slack inbound: failed to resolve thread_ts via conversations.history for channel=${params.channelId} ts=${params.messageTs}: ${String(err)}`,
|
||||
`slack inbound: failed to resolve thread_ts via conversations.history for channel=${params.channelId} ts=${params.messageTs}: ${formatErrorMessage(err)}`,
|
||||
);
|
||||
}
|
||||
return undefined;
|
||||
|
||||
@@ -60,9 +60,9 @@ const allowedRawFetchCallsites = new Set([
|
||||
bundledPluginCallsite("qqbot", "src/tools/channel.ts", 180),
|
||||
bundledPluginCallsite("qqbot", "src/utils/audio-convert.ts", 377),
|
||||
bundledPluginCallsite("signal", "src/install-signal-cli.ts", 224),
|
||||
bundledPluginCallsite("slack", "src/monitor/media.ts", 98),
|
||||
bundledPluginCallsite("slack", "src/monitor/media.ts", 117),
|
||||
bundledPluginCallsite("slack", "src/monitor/media.ts", 122),
|
||||
bundledPluginCallsite("slack", "src/monitor/media.ts", 99),
|
||||
bundledPluginCallsite("slack", "src/monitor/media.ts", 118),
|
||||
bundledPluginCallsite("slack", "src/monitor/media.ts", 123),
|
||||
bundledPluginCallsite("tlon", "src/tlon-api.ts", 185),
|
||||
bundledPluginCallsite("tlon", "src/tlon-api.ts", 235),
|
||||
bundledPluginCallsite("tlon", "src/tlon-api.ts", 289),
|
||||
|
||||
Reference in New Issue
Block a user