@poolzin/pool-bot 2026.3.25 → 2026.3.26
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/agents/model-fallback.js +5 -4
- package/dist/agents/tools/common.js +16 -201
- package/dist/auto-reply/auto-reply/reply/agent-runner-execution.js +502 -0
- package/dist/auto-reply/auto-reply/reply/agent-runner-helpers.js +65 -0
- package/dist/auto-reply/auto-reply/reply/agent-runner-memory.js +160 -0
- package/dist/auto-reply/auto-reply/reply/agent-runner-payloads.js +85 -0
- package/dist/auto-reply/auto-reply/reply/agent-runner-utils.js +101 -0
- package/dist/auto-reply/auto-reply/reply/bash-command.js +338 -0
- package/dist/auto-reply/auto-reply/reply/block-streaming.js +91 -0
- package/dist/auto-reply/auto-reply/reply/commands-approve.js +88 -0
- package/dist/auto-reply/auto-reply/reply/commands-bash.js +26 -0
- package/dist/auto-reply/auto-reply/reply/commands-compact.js +107 -0
- package/dist/auto-reply/auto-reply/reply/commands-config.js +241 -0
- package/dist/auto-reply/auto-reply/reply/commands-context-report.js +295 -0
- package/dist/auto-reply/auto-reply/reply/commands-context.js +30 -0
- package/dist/auto-reply/auto-reply/reply/commands-core.js +151 -0
- package/dist/auto-reply/auto-reply/reply/commands-export-session.js +163 -0
- package/dist/auto-reply/auto-reply/reply/commands-info.js +184 -0
- package/dist/auto-reply/auto-reply/reply/commands-models.js +299 -0
- package/dist/auto-reply/auto-reply/reply/commands-plugin.js +35 -0
- package/dist/auto-reply/auto-reply/reply/commands-ptt.js +171 -0
- package/dist/auto-reply/auto-reply/reply/commands-setunset-standard.js +13 -0
- package/dist/auto-reply/auto-reply/reply/commands-setunset.js +73 -0
- package/dist/auto-reply/auto-reply/reply/commands-slash-parse.js +31 -0
- package/dist/auto-reply/auto-reply/reply/commands-status.js +178 -0
- package/dist/auto-reply/auto-reply/reply/commands-subagents.js +73 -0
- package/dist/auto-reply/auto-reply/reply/commands-system-prompt.js +117 -0
- package/dist/auto-reply/auto-reply/reply/commands-tts.js +231 -0
- package/dist/auto-reply/auto-reply/reply/directive-handling.impl.js +380 -0
- package/dist/auto-reply/auto-reply/reply/followup-runner.js +227 -0
- package/dist/auto-reply/auto-reply/reply/get-reply-directives-apply.js +201 -0
- package/dist/auto-reply/auto-reply/reply/get-reply-directives-utils.js +54 -0
- package/dist/auto-reply/auto-reply/reply/get-reply-directives.js +332 -0
- package/dist/auto-reply/auto-reply/reply/get-reply-inline-actions.js +258 -0
- package/dist/auto-reply/auto-reply/reply/get-reply-run.js +297 -0
- package/dist/auto-reply/auto-reply/reply/groups.js +102 -0
- package/dist/auto-reply/auto-reply/reply/mentions.js +129 -0
- package/dist/auto-reply/auto-reply/reply/reply-delivery.js +92 -0
- package/dist/auto-reply/auto-reply/reply/reply-directives.js +30 -0
- package/dist/auto-reply/auto-reply/reply/reply-dispatcher.js +152 -0
- package/dist/auto-reply/auto-reply/reply/reply-elevated.js +166 -0
- package/dist/auto-reply/auto-reply/reply/reply-inline.js +28 -0
- package/dist/auto-reply/auto-reply/reply/reply-payloads.js +114 -0
- package/dist/auto-reply/auto-reply/reply/reply-reference.js +36 -0
- package/dist/auto-reply/auto-reply/reply/reply-tags.js +13 -0
- package/dist/auto-reply/auto-reply/reply/reply-threading.js +41 -0
- package/dist/auto-reply/auto-reply/reply/session-updates.js +233 -0
- package/dist/auto-reply/auto-reply/reply/stage-sandbox-media.js +146 -0
- package/dist/build-info.json +3 -3
- package/dist/canvas-host/a2ui/.bundle.hash +1 -1
- package/dist/canvas-host/a2ui/a2ui.bundle.js +2 -17772
- package/dist/canvas-host/a2ui/index.html +1 -307
- package/dist/channels/channels/directory-config.js +185 -0
- package/dist/channels/channels/discord/handle-action.guild-admin.js +332 -0
- package/dist/channels/channels/discord/handle-action.js +165 -0
- package/dist/channels/channels/discord.js +413 -0
- package/dist/channels/channels/dock.js +436 -0
- package/dist/channels/channels/index.js +51 -0
- package/dist/channels/channels/plugins/outbound/discord.js +101 -0
- package/dist/channels/channels/whatsapp.js +17 -0
- package/dist/channels/plugins/types.js +1 -1
- package/dist/channels/run-state-machine.js +7 -0
- package/dist/commands/models/auth.js +47 -1
- package/dist/commands-subagents/action-agents.js +44 -0
- package/dist/commands-subagents/action-focus.js +64 -0
- package/dist/commands-subagents/action-help.js +4 -0
- package/dist/commands-subagents/action-info.js +45 -0
- package/dist/commands-subagents/action-kill.js +60 -0
- package/dist/commands-subagents/action-list.js +44 -0
- package/dist/commands-subagents/action-log.js +29 -0
- package/dist/commands-subagents/action-send.js +119 -0
- package/dist/commands-subagents/action-spawn.js +52 -0
- package/dist/commands-subagents/action-unfocus.js +30 -0
- package/dist/commands-subagents/shared.js +303 -0
- package/dist/config/config.js +1 -8
- package/dist/config/types.secrets.js +61 -0
- package/dist/control-ui/assets/{index-D7shnQwQ.js → index-umCsvrWy.js} +884 -741
- package/dist/control-ui/assets/index-umCsvrWy.js.map +1 -0
- package/dist/control-ui/assets/pt-BR-DedEVAvY.js +2 -0
- package/dist/control-ui/assets/pt-BR-DedEVAvY.js.map +1 -0
- package/dist/control-ui/assets/zh-CN-CDzeklK-.js +2 -0
- package/dist/control-ui/assets/zh-CN-CDzeklK-.js.map +1 -0
- package/dist/control-ui/assets/zh-TW-BJCRYNWH.js +2 -0
- package/dist/control-ui/assets/zh-TW-BJCRYNWH.js.map +1 -0
- package/dist/control-ui/index.html +1 -1
- package/dist/gateway/method-scopes.js +9 -1
- package/dist/gateway/node-pending-work.js +142 -0
- package/dist/gateway/protocol/index.js +5 -1
- package/dist/gateway/protocol/schema/nodes.js +18 -0
- package/dist/gateway/server-methods/nodes-pending.js +96 -0
- package/dist/gateway/server-methods-list.js +4 -0
- package/dist/gateway/server-methods.js +2 -0
- package/dist/imessage/channel.js +253 -0
- package/dist/imessage/monitor/echo-cache.js +70 -0
- package/dist/imessage/monitor/loop-rate-limiter.js +51 -0
- package/dist/imessage/monitor/reflection-guard.js +50 -0
- package/dist/imessage/monitor/sanitize-outbound.js +25 -0
- package/dist/imessage/monitor/self-chat-cache.js +75 -0
- package/dist/imessage/runtime.js +3 -0
- package/dist/infra/exec-approval-reply.js +7 -0
- package/dist/infra/tmp-openclaw-dir.js +84 -0
- package/dist/pairing/pairing-challenge.js +15 -0
- package/dist/plugin-sdk/account-id.d.ts +1 -0
- package/dist/plugin-sdk/agent-media-payload.d.ts +12 -0
- package/dist/plugin-sdk/allow-from.d.ts +27 -0
- package/dist/plugin-sdk/command-auth.d.ts +25 -0
- package/dist/plugin-sdk/command-auth.js +3 -1
- package/dist/plugin-sdk/config-paths.d.ts +6 -0
- package/dist/plugin-sdk/file-lock.d.ts +16 -0
- package/dist/plugin-sdk/index.d.ts +428 -0
- package/dist/plugin-sdk/index.js +237 -103
- package/dist/plugin-sdk/json-store.d.ts +5 -0
- package/dist/plugin-sdk/keyed-async-queue.d.ts +12 -0
- package/dist/plugin-sdk/onboarding.d.ts +11 -0
- package/dist/plugin-sdk/provider-auth-result.d.ts +14 -0
- package/dist/plugin-sdk/slack-message-actions.d.ts +11 -0
- package/dist/plugin-sdk/status-helpers.d.ts +25 -0
- package/dist/plugin-sdk/temp-path.d.ts +12 -0
- package/dist/plugin-sdk/text-chunking.d.ts +1 -0
- package/dist/plugin-sdk/tool-send.d.ts +4 -0
- package/dist/plugin-sdk/webhook-path.d.ts +6 -0
- package/dist/plugin-sdk/webhook-targets.d.ts +23 -0
- package/dist/plugin-sdk/windows-spawn.d.ts +39 -0
- package/dist/plugin-sdk-internal/accounts.js +6 -0
- package/dist/plugin-sdk-internal/discord.js +23 -0
- package/dist/plugin-sdk-internal/imessage.js +13 -0
- package/dist/plugin-sdk-internal/setup.js +9 -0
- package/dist/plugin-sdk-internal/signal.js +13 -0
- package/dist/plugin-sdk-internal/slack.js +22 -0
- package/dist/plugin-sdk-internal/telegram.js +32 -0
- package/dist/plugin-sdk-internal/whatsapp.js +29 -0
- package/dist/routing/session-key.js +4 -185
- package/dist/shared/pid-alive.js +2 -61
- package/dist/shared/process-scoped-map.js +5 -7
- package/dist/signal/channel.js +264 -0
- package/dist/signal/monitor/access-policy.js +60 -0
- package/dist/signal/runtime.js +3 -0
- package/dist/slack/account-inspect.js +135 -0
- package/dist/slack/blocks-input.js +7 -38
- package/dist/slack/channel.js +394 -0
- package/dist/slack/interactive-replies.js +28 -0
- package/dist/slack/monitor/channel-type.js +31 -0
- package/dist/slack/monitor/dm-auth.js +49 -0
- package/dist/slack/monitor/events/interactions.modal.js +137 -0
- package/dist/slack/monitor/events/message-subtype-handlers.js +68 -0
- package/dist/slack/monitor/events/system-event-context.js +29 -0
- package/dist/slack/monitor/events/system-event-test-harness.js +41 -0
- package/dist/slack/monitor/external-arg-menu-store.js +46 -0
- package/dist/slack/monitor/message-handler/prepare-content.js +69 -0
- package/dist/slack/monitor/message-handler/prepare-thread-context.js +91 -0
- package/dist/slack/monitor/message-handler/prepare.test-helpers.js +55 -0
- package/dist/slack/monitor/reconnect-policy.js +78 -0
- package/dist/slack/monitor/slash-commands.runtime.js +1 -0
- package/dist/slack/monitor/slash-dispatch.runtime.js +9 -0
- package/dist/slack/monitor/slash-skill-commands.runtime.js +1 -0
- package/dist/slack/resolve-allowlist-common.js +36 -0
- package/dist/slack/runtime.js +3 -0
- package/dist/slack/sent-thread-cache.js +61 -0
- package/dist/slack/truncate.js +10 -0
- package/dist/telegram/account-inspect.js +175 -0
- package/dist/telegram/allow-from.js +10 -0
- package/dist/telegram/api-fetch.js +18 -0
- package/dist/telegram/approval-buttons.js +30 -0
- package/dist/telegram/audit-membership-runtime.js +61 -0
- package/dist/telegram/bot/delivery.replies.js +508 -0
- package/dist/telegram/bot/delivery.resolve-media.js +227 -0
- package/dist/telegram/bot/delivery.send.js +132 -0
- package/dist/telegram/bot/reply-threading.js +46 -0
- package/dist/telegram/bot-message-context.body.js +186 -0
- package/dist/telegram/bot-message-context.session.js +207 -0
- package/dist/telegram/bot-message-context.types.js +1 -0
- package/dist/telegram/bot-native-commands.test-helpers.js +117 -0
- package/dist/telegram/bot.media.e2e-harness.js +81 -0
- package/dist/telegram/bot.media.test-utils.js +81 -0
- package/dist/telegram/channel-actions.js +225 -0
- package/dist/telegram/channel.js +515 -0
- package/dist/telegram/conversation-route.js +107 -0
- package/dist/telegram/delivery.js +2 -0
- package/dist/telegram/delivery.replies.js +508 -0
- package/dist/telegram/dm-access.js +86 -0
- package/dist/telegram/draft-stream.test-helpers.js +62 -0
- package/dist/telegram/exec-approvals-handler.js +281 -0
- package/dist/telegram/exec-approvals.js +62 -0
- package/dist/telegram/forum-service-message.js +22 -0
- package/dist/telegram/group-config-helpers.js +10 -0
- package/dist/telegram/lane-delivery-state.js +19 -0
- package/dist/telegram/lane-delivery-text-deliverer.js +357 -0
- package/dist/telegram/lane-delivery.js +2 -0
- package/dist/telegram/normalize.js +37 -0
- package/dist/telegram/onboarding.js +192 -0
- package/dist/telegram/outbound-adapter.js +100 -0
- package/dist/telegram/polling-session.js +275 -0
- package/dist/telegram/runtime.js +3 -0
- package/dist/telegram/sendchataction-401-backoff.js +71 -0
- package/dist/telegram/sequential-key.js +46 -0
- package/dist/telegram/status-issues.js +105 -0
- package/dist/telegram/target-writeback.js +165 -0
- package/dist/telegram/thread-bindings.js +560 -0
- package/dist/utils.js +10 -276
- package/dist/wizard/prompts.js +5 -5
- package/extensions/feishu/src/policy.ts +1 -1
- package/extensions/firecrawl/index.test.ts +82 -0
- package/extensions/firecrawl/index.ts +20 -0
- package/extensions/firecrawl/openclaw.plugin.json +8 -0
- package/extensions/firecrawl/package.json +12 -0
- package/extensions/firecrawl/src/config.ts +159 -0
- package/extensions/firecrawl/src/firecrawl-client.ts +446 -0
- package/extensions/firecrawl/src/firecrawl-scrape-tool.ts +89 -0
- package/extensions/firecrawl/src/firecrawl-search-provider.ts +63 -0
- package/extensions/firecrawl/src/firecrawl-search-tool.ts +76 -0
- package/package.json +1 -1
- package/dist/.buildstamp +0 -1
- package/dist/acp/bindings-store.js +0 -209
- package/dist/acp/control-plane/runtime-cache.js +0 -54
- package/dist/acp/control-plane/runtime-options.js +0 -215
- package/dist/acp/control-plane/session-actor-queue.js +0 -36
- package/dist/acp/index.js +0 -2
- package/dist/acp/runtime/errors.js +0 -47
- package/dist/acp/runtime/registry.js +0 -86
- package/dist/acp/secret-file.js +0 -22
- package/dist/agents/auth-profiles.resolve-auth-profile-order.fixtures.js +0 -23
- package/dist/agents/bash-process-registry.test-helpers.js +0 -29
- package/dist/agents/bash-tools.exec-approval-request.js +0 -20
- package/dist/agents/bash-tools.exec-host-gateway.js +0 -240
- package/dist/agents/bash-tools.exec-host-node.js +0 -235
- package/dist/agents/checkpoint-manager.js +0 -290
- package/dist/agents/claude-cli-runner.js +0 -3
- package/dist/agents/error-classifier.js +0 -251
- package/dist/agents/live-model-filter.js +0 -84
- package/dist/agents/nvidia-models.js +0 -228
- package/dist/agents/pi-embedded-runner/run.overflow-compaction.fixture.js +0 -34
- package/dist/agents/pi-embedded-runner/run.overflow-compaction.mocks.shared.js +0 -156
- package/dist/agents/pi-embedded-subscribe.handlers.tools.media.test-helpers.js +0 -30
- package/dist/agents/provider/config-loader.js +0 -76
- package/dist/agents/provider/index.js +0 -15
- package/dist/agents/provider/models-dev.js +0 -129
- package/dist/agents/provider/session-binding.js +0 -376
- package/dist/agents/queued-file-writer.js +0 -22
- package/dist/agents/skills/bundled-context.js +0 -23
- package/dist/agents/skills/security.js +0 -211
- package/dist/agents/skills/tools-dir.js +0 -9
- package/dist/agents/skills-install-download.js +0 -290
- package/dist/agents/skills-install-output.js +0 -30
- package/dist/agents/skills-install.download-test-utils.js +0 -36
- package/dist/agents/skills.test-helpers.js +0 -13
- package/dist/agents/subagent-announce-reliability.js +0 -160
- package/dist/agents/subagent-registry.mocks.shared.js +0 -12
- package/dist/agents/test-helpers/assistant-message-fixtures.js +0 -29
- package/dist/agents/test-helpers/fast-coding-tools.js +0 -1
- package/dist/agents/test-helpers/fast-core-tools.js +0 -8
- package/dist/agents/test-helpers/fast-tool-stubs.js +0 -18
- package/dist/agents/test-helpers/host-sandbox-fs-bridge.js +0 -74
- package/dist/agents/test-helpers/pi-tools-sandbox-context.js +0 -27
- package/dist/agents/tool-display-common.js +0 -915
- package/dist/agents/tool-policy-shared.js +0 -108
- package/dist/agents/tool-policy.conformance.js +0 -14
- package/dist/agents/tool-result-truncation.js +0 -299
- package/dist/agents/tools/cron-tool.test-helpers.js +0 -12
- package/dist/agents/tools/discord-actions-moderation-shared.js +0 -27
- package/dist/agents/tools/discord-actions-presence.js +0 -78
- package/dist/control-ui/assets/index-D7shnQwQ.js.map +0 -1
- package/dist/discord/discord-improvements.js +0 -167
- package/dist/discord/index.js +0 -2
- package/dist/hooks/bundled/boot-md/HOOK.md +0 -19
- package/dist/hooks/bundled/command-logger/HOOK.md +0 -122
- package/dist/hooks/bundled/session-memory/HOOK.md +0 -86
- package/dist/hooks/bundled/soul-evil/HOOK.md +0 -71
- package/dist/whatsapp/normalize.js +0 -66
- package/dist/whatsapp/resolve-outbound-target.js +0 -42
- /package/dist/{acp/runtime/types.js → auto-reply/auto-reply/reply/commands-types.js} +0 -0
- /package/dist/{agents/pi-embedded-payloads.js → slack/account-surface-fields.js} +0 -0
|
@@ -0,0 +1,78 @@
|
|
|
1
|
+
const SLACK_AUTH_ERROR_RE = /account_inactive|invalid_auth|token_revoked|token_expired|not_authed|org_login_required|team_access_not_granted|missing_scope|cannot_find_service|invalid_token/i;
|
|
2
|
+
export const SLACK_SOCKET_RECONNECT_POLICY = {
|
|
3
|
+
initialMs: 2_000,
|
|
4
|
+
maxMs: 30_000,
|
|
5
|
+
factor: 1.8,
|
|
6
|
+
jitter: 0.25,
|
|
7
|
+
maxAttempts: 12,
|
|
8
|
+
};
|
|
9
|
+
export function getSocketEmitter(app) {
|
|
10
|
+
const receiver = app.receiver;
|
|
11
|
+
const client = receiver && typeof receiver === "object"
|
|
12
|
+
? receiver.client
|
|
13
|
+
: undefined;
|
|
14
|
+
if (!client || typeof client !== "object") {
|
|
15
|
+
return null;
|
|
16
|
+
}
|
|
17
|
+
const on = client.on;
|
|
18
|
+
const off = client.off;
|
|
19
|
+
if (typeof on !== "function" || typeof off !== "function") {
|
|
20
|
+
return null;
|
|
21
|
+
}
|
|
22
|
+
return {
|
|
23
|
+
on: (event, listener) => on.call(client, event, listener),
|
|
24
|
+
off: (event, listener) => off.call(client, event, listener),
|
|
25
|
+
};
|
|
26
|
+
}
|
|
27
|
+
export function waitForSlackSocketDisconnect(app, abortSignal) {
|
|
28
|
+
return new Promise((resolve) => {
|
|
29
|
+
const emitter = getSocketEmitter(app);
|
|
30
|
+
if (!emitter) {
|
|
31
|
+
abortSignal?.addEventListener("abort", () => resolve({ event: "disconnect" }), {
|
|
32
|
+
once: true,
|
|
33
|
+
});
|
|
34
|
+
return;
|
|
35
|
+
}
|
|
36
|
+
const disconnectListener = () => resolveOnce({ event: "disconnect" });
|
|
37
|
+
const startFailListener = (error) => resolveOnce({ event: "unable_to_socket_mode_start", error });
|
|
38
|
+
const errorListener = (error) => resolveOnce({ event: "error", error });
|
|
39
|
+
const abortListener = () => resolveOnce({ event: "disconnect" });
|
|
40
|
+
const cleanup = () => {
|
|
41
|
+
emitter.off("disconnected", disconnectListener);
|
|
42
|
+
emitter.off("unable_to_socket_mode_start", startFailListener);
|
|
43
|
+
emitter.off("error", errorListener);
|
|
44
|
+
abortSignal?.removeEventListener("abort", abortListener);
|
|
45
|
+
};
|
|
46
|
+
const resolveOnce = (value) => {
|
|
47
|
+
cleanup();
|
|
48
|
+
resolve(value);
|
|
49
|
+
};
|
|
50
|
+
emitter.on("disconnected", disconnectListener);
|
|
51
|
+
emitter.on("unable_to_socket_mode_start", startFailListener);
|
|
52
|
+
emitter.on("error", errorListener);
|
|
53
|
+
abortSignal?.addEventListener("abort", abortListener, { once: true });
|
|
54
|
+
});
|
|
55
|
+
}
|
|
56
|
+
/**
|
|
57
|
+
* Detect non-recoverable Slack API / auth errors that should NOT be retried.
|
|
58
|
+
* These indicate permanent credential problems (revoked bot, deactivated account, etc.)
|
|
59
|
+
* and retrying will never succeed — continuing to retry blocks the entire gateway.
|
|
60
|
+
*/
|
|
61
|
+
export function isNonRecoverableSlackAuthError(error) {
|
|
62
|
+
const msg = error instanceof Error ? error.message : typeof error === "string" ? error : "";
|
|
63
|
+
return SLACK_AUTH_ERROR_RE.test(msg);
|
|
64
|
+
}
|
|
65
|
+
export function formatUnknownError(error) {
|
|
66
|
+
if (error instanceof Error) {
|
|
67
|
+
return error.message;
|
|
68
|
+
}
|
|
69
|
+
if (typeof error === "string") {
|
|
70
|
+
return error;
|
|
71
|
+
}
|
|
72
|
+
try {
|
|
73
|
+
return JSON.stringify(error);
|
|
74
|
+
}
|
|
75
|
+
catch {
|
|
76
|
+
return "unknown error";
|
|
77
|
+
}
|
|
78
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export { buildCommandTextFromArgs, findCommandByNativeName, listNativeCommandSpecsForConfig, parseCommandArgs, resolveCommandArgMenu, } from "../../../../src/auto-reply/commands-registry.js";
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
export { resolveChunkMode } from "../../../../src/auto-reply/chunk.js";
|
|
2
|
+
export { finalizeInboundContext } from "../../../../src/auto-reply/reply/inbound-context.js";
|
|
3
|
+
export { dispatchReplyWithDispatcher } from "../../../../src/auto-reply/reply/provider-dispatcher.js";
|
|
4
|
+
export { resolveConversationLabel } from "../../../../src/channels/conversation-label.js";
|
|
5
|
+
export { createReplyPrefixOptions } from "../../../../src/channels/reply-prefix.js";
|
|
6
|
+
export { recordInboundSessionMetaSafe } from "../../../../src/channels/session-meta.js";
|
|
7
|
+
export { resolveMarkdownTableMode } from "../../../../src/config/markdown-tables.js";
|
|
8
|
+
export { resolveAgentRoute } from "../../../../src/routing/resolve-route.js";
|
|
9
|
+
export { deliverSlackSlashReplies } from "./replies.js";
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export { listSkillCommandsForAgents } from "../../../../src/auto-reply/skill-commands.js";
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
function readSlackNextCursor(response) {
|
|
2
|
+
const next = response.response_metadata?.next_cursor?.trim();
|
|
3
|
+
return next ? next : undefined;
|
|
4
|
+
}
|
|
5
|
+
export async function collectSlackCursorItems(params) {
|
|
6
|
+
const items = [];
|
|
7
|
+
let cursor;
|
|
8
|
+
do {
|
|
9
|
+
const response = await params.fetchPage(cursor);
|
|
10
|
+
items.push(...params.collectPageItems(response));
|
|
11
|
+
cursor = readSlackNextCursor(response);
|
|
12
|
+
} while (cursor);
|
|
13
|
+
return items;
|
|
14
|
+
}
|
|
15
|
+
export function resolveSlackAllowlistEntries(params) {
|
|
16
|
+
const results = [];
|
|
17
|
+
for (const input of params.entries) {
|
|
18
|
+
const parsed = params.parseInput(input);
|
|
19
|
+
if (parsed.id) {
|
|
20
|
+
const match = params.findById(params.lookup, parsed.id);
|
|
21
|
+
results.push(params.buildIdResolved({ input, parsed, match }));
|
|
22
|
+
continue;
|
|
23
|
+
}
|
|
24
|
+
const resolved = params.resolveNonId({
|
|
25
|
+
input,
|
|
26
|
+
parsed,
|
|
27
|
+
lookup: params.lookup,
|
|
28
|
+
});
|
|
29
|
+
if (resolved) {
|
|
30
|
+
results.push(resolved);
|
|
31
|
+
continue;
|
|
32
|
+
}
|
|
33
|
+
results.push(params.buildUnresolved(input));
|
|
34
|
+
}
|
|
35
|
+
return results;
|
|
36
|
+
}
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
import { resolveGlobalMap } from "../../../src/shared/global-singleton.js";
|
|
2
|
+
/**
|
|
3
|
+
* In-memory cache of Slack threads the bot has participated in.
|
|
4
|
+
* Used to auto-respond in threads without requiring @mention after the first reply.
|
|
5
|
+
* Follows a similar TTL pattern to the MS Teams and Telegram sent-message caches.
|
|
6
|
+
*/
|
|
7
|
+
const TTL_MS = 24 * 60 * 60 * 1000; // 24 hours
|
|
8
|
+
const MAX_ENTRIES = 5000;
|
|
9
|
+
/**
|
|
10
|
+
* Keep Slack thread participation shared across bundled chunks so thread
|
|
11
|
+
* auto-reply gating does not diverge between prepare/dispatch call paths.
|
|
12
|
+
*/
|
|
13
|
+
const SLACK_THREAD_PARTICIPATION_KEY = Symbol.for("openclaw.slackThreadParticipation");
|
|
14
|
+
const threadParticipation = resolveGlobalMap(SLACK_THREAD_PARTICIPATION_KEY);
|
|
15
|
+
function makeKey(accountId, channelId, threadTs) {
|
|
16
|
+
return `${accountId}:${channelId}:${threadTs}`;
|
|
17
|
+
}
|
|
18
|
+
function evictExpired() {
|
|
19
|
+
const now = Date.now();
|
|
20
|
+
for (const [key, timestamp] of threadParticipation) {
|
|
21
|
+
if (now - timestamp > TTL_MS) {
|
|
22
|
+
threadParticipation.delete(key);
|
|
23
|
+
}
|
|
24
|
+
}
|
|
25
|
+
}
|
|
26
|
+
function evictOldest() {
|
|
27
|
+
const oldest = threadParticipation.keys().next().value;
|
|
28
|
+
if (oldest) {
|
|
29
|
+
threadParticipation.delete(oldest);
|
|
30
|
+
}
|
|
31
|
+
}
|
|
32
|
+
export function recordSlackThreadParticipation(accountId, channelId, threadTs) {
|
|
33
|
+
if (!accountId || !channelId || !threadTs) {
|
|
34
|
+
return;
|
|
35
|
+
}
|
|
36
|
+
if (threadParticipation.size >= MAX_ENTRIES) {
|
|
37
|
+
evictExpired();
|
|
38
|
+
}
|
|
39
|
+
if (threadParticipation.size >= MAX_ENTRIES) {
|
|
40
|
+
evictOldest();
|
|
41
|
+
}
|
|
42
|
+
threadParticipation.set(makeKey(accountId, channelId, threadTs), Date.now());
|
|
43
|
+
}
|
|
44
|
+
export function hasSlackThreadParticipation(accountId, channelId, threadTs) {
|
|
45
|
+
if (!accountId || !channelId || !threadTs) {
|
|
46
|
+
return false;
|
|
47
|
+
}
|
|
48
|
+
const key = makeKey(accountId, channelId, threadTs);
|
|
49
|
+
const timestamp = threadParticipation.get(key);
|
|
50
|
+
if (timestamp == null) {
|
|
51
|
+
return false;
|
|
52
|
+
}
|
|
53
|
+
if (Date.now() - timestamp > TTL_MS) {
|
|
54
|
+
threadParticipation.delete(key);
|
|
55
|
+
return false;
|
|
56
|
+
}
|
|
57
|
+
return true;
|
|
58
|
+
}
|
|
59
|
+
export function clearSlackThreadParticipationCache() {
|
|
60
|
+
threadParticipation.clear();
|
|
61
|
+
}
|
|
@@ -0,0 +1,175 @@
|
|
|
1
|
+
import { coerceSecretRef, hasConfiguredSecretInput, normalizeSecretInputString, } from "../../../src/config/types.secrets.js";
|
|
2
|
+
import { tryReadSecretFileSync } from "../../../src/infra/secret-file.js";
|
|
3
|
+
import { resolveAccountWithDefaultFallback } from "../../../src/plugin-sdk/account-resolution.js";
|
|
4
|
+
import { DEFAULT_ACCOUNT_ID, normalizeAccountId } from "../../../src/routing/session-key.js";
|
|
5
|
+
import { resolveDefaultSecretProviderAlias } from "../../../src/secrets/ref-contract.js";
|
|
6
|
+
import { mergeTelegramAccountConfig, resolveDefaultTelegramAccountId, resolveTelegramAccountConfig, } from "./accounts.js";
|
|
7
|
+
function inspectTokenFile(pathValue) {
|
|
8
|
+
const tokenFile = typeof pathValue === "string" ? pathValue.trim() : "";
|
|
9
|
+
if (!tokenFile) {
|
|
10
|
+
return null;
|
|
11
|
+
}
|
|
12
|
+
const token = tryReadSecretFileSync(tokenFile, "Telegram bot token", {
|
|
13
|
+
rejectSymlink: true,
|
|
14
|
+
});
|
|
15
|
+
return {
|
|
16
|
+
token: token ?? "",
|
|
17
|
+
tokenSource: "tokenFile",
|
|
18
|
+
tokenStatus: token ? "available" : "configured_unavailable",
|
|
19
|
+
};
|
|
20
|
+
}
|
|
21
|
+
function canResolveEnvSecretRefInReadOnlyPath(params) {
|
|
22
|
+
const providerConfig = params.cfg.secrets?.providers?.[params.provider];
|
|
23
|
+
if (!providerConfig) {
|
|
24
|
+
return params.provider === resolveDefaultSecretProviderAlias(params.cfg, "env");
|
|
25
|
+
}
|
|
26
|
+
if (providerConfig.source !== "env") {
|
|
27
|
+
return false;
|
|
28
|
+
}
|
|
29
|
+
const allowlist = providerConfig.allowlist;
|
|
30
|
+
return !allowlist || allowlist.includes(params.id);
|
|
31
|
+
}
|
|
32
|
+
function inspectTokenValue(params) {
|
|
33
|
+
// Try to resolve env-based SecretRefs from process.env for read-only inspection
|
|
34
|
+
const ref = coerceSecretRef(params.value, params.cfg.secrets?.defaults);
|
|
35
|
+
if (ref?.source === "env") {
|
|
36
|
+
if (!canResolveEnvSecretRefInReadOnlyPath({
|
|
37
|
+
cfg: params.cfg,
|
|
38
|
+
provider: ref.provider,
|
|
39
|
+
id: ref.id,
|
|
40
|
+
})) {
|
|
41
|
+
return {
|
|
42
|
+
token: "",
|
|
43
|
+
tokenSource: "env",
|
|
44
|
+
tokenStatus: "configured_unavailable",
|
|
45
|
+
};
|
|
46
|
+
}
|
|
47
|
+
const envValue = process.env[ref.id];
|
|
48
|
+
if (envValue && envValue.trim()) {
|
|
49
|
+
return {
|
|
50
|
+
token: envValue.trim(),
|
|
51
|
+
tokenSource: "env",
|
|
52
|
+
tokenStatus: "available",
|
|
53
|
+
};
|
|
54
|
+
}
|
|
55
|
+
return {
|
|
56
|
+
token: "",
|
|
57
|
+
tokenSource: "env",
|
|
58
|
+
tokenStatus: "configured_unavailable",
|
|
59
|
+
};
|
|
60
|
+
}
|
|
61
|
+
const token = normalizeSecretInputString(params.value);
|
|
62
|
+
if (token) {
|
|
63
|
+
return {
|
|
64
|
+
token,
|
|
65
|
+
tokenSource: "config",
|
|
66
|
+
tokenStatus: "available",
|
|
67
|
+
};
|
|
68
|
+
}
|
|
69
|
+
if (hasConfiguredSecretInput(params.value, params.cfg.secrets?.defaults)) {
|
|
70
|
+
return {
|
|
71
|
+
token: "",
|
|
72
|
+
tokenSource: "config",
|
|
73
|
+
tokenStatus: "configured_unavailable",
|
|
74
|
+
};
|
|
75
|
+
}
|
|
76
|
+
return null;
|
|
77
|
+
}
|
|
78
|
+
function inspectTelegramAccountPrimary(params) {
|
|
79
|
+
const accountId = normalizeAccountId(params.accountId);
|
|
80
|
+
const merged = mergeTelegramAccountConfig(params.cfg, accountId);
|
|
81
|
+
const enabled = params.cfg.channels?.telegram?.enabled !== false && merged.enabled !== false;
|
|
82
|
+
const accountConfig = resolveTelegramAccountConfig(params.cfg, accountId);
|
|
83
|
+
const accountTokenFile = inspectTokenFile(accountConfig?.tokenFile);
|
|
84
|
+
if (accountTokenFile) {
|
|
85
|
+
return {
|
|
86
|
+
accountId,
|
|
87
|
+
enabled,
|
|
88
|
+
name: merged.name?.trim() || undefined,
|
|
89
|
+
token: accountTokenFile.token,
|
|
90
|
+
tokenSource: accountTokenFile.tokenSource,
|
|
91
|
+
tokenStatus: accountTokenFile.tokenStatus,
|
|
92
|
+
configured: accountTokenFile.tokenStatus !== "missing",
|
|
93
|
+
config: merged,
|
|
94
|
+
};
|
|
95
|
+
}
|
|
96
|
+
const accountToken = inspectTokenValue({ cfg: params.cfg, value: accountConfig?.botToken });
|
|
97
|
+
if (accountToken) {
|
|
98
|
+
return {
|
|
99
|
+
accountId,
|
|
100
|
+
enabled,
|
|
101
|
+
name: merged.name?.trim() || undefined,
|
|
102
|
+
token: accountToken.token,
|
|
103
|
+
tokenSource: accountToken.tokenSource,
|
|
104
|
+
tokenStatus: accountToken.tokenStatus,
|
|
105
|
+
configured: accountToken.tokenStatus !== "missing",
|
|
106
|
+
config: merged,
|
|
107
|
+
};
|
|
108
|
+
}
|
|
109
|
+
const channelTokenFile = inspectTokenFile(params.cfg.channels?.telegram?.tokenFile);
|
|
110
|
+
if (channelTokenFile) {
|
|
111
|
+
return {
|
|
112
|
+
accountId,
|
|
113
|
+
enabled,
|
|
114
|
+
name: merged.name?.trim() || undefined,
|
|
115
|
+
token: channelTokenFile.token,
|
|
116
|
+
tokenSource: channelTokenFile.tokenSource,
|
|
117
|
+
tokenStatus: channelTokenFile.tokenStatus,
|
|
118
|
+
configured: channelTokenFile.tokenStatus !== "missing",
|
|
119
|
+
config: merged,
|
|
120
|
+
};
|
|
121
|
+
}
|
|
122
|
+
const channelToken = inspectTokenValue({
|
|
123
|
+
cfg: params.cfg,
|
|
124
|
+
value: params.cfg.channels?.telegram?.botToken,
|
|
125
|
+
});
|
|
126
|
+
if (channelToken) {
|
|
127
|
+
return {
|
|
128
|
+
accountId,
|
|
129
|
+
enabled,
|
|
130
|
+
name: merged.name?.trim() || undefined,
|
|
131
|
+
token: channelToken.token,
|
|
132
|
+
tokenSource: channelToken.tokenSource,
|
|
133
|
+
tokenStatus: channelToken.tokenStatus,
|
|
134
|
+
configured: channelToken.tokenStatus !== "missing",
|
|
135
|
+
config: merged,
|
|
136
|
+
};
|
|
137
|
+
}
|
|
138
|
+
const allowEnv = accountId === DEFAULT_ACCOUNT_ID;
|
|
139
|
+
const envToken = allowEnv ? (params.envToken ?? process.env.TELEGRAM_BOT_TOKEN)?.trim() : "";
|
|
140
|
+
if (envToken) {
|
|
141
|
+
return {
|
|
142
|
+
accountId,
|
|
143
|
+
enabled,
|
|
144
|
+
name: merged.name?.trim() || undefined,
|
|
145
|
+
token: envToken,
|
|
146
|
+
tokenSource: "env",
|
|
147
|
+
tokenStatus: "available",
|
|
148
|
+
configured: true,
|
|
149
|
+
config: merged,
|
|
150
|
+
};
|
|
151
|
+
}
|
|
152
|
+
return {
|
|
153
|
+
accountId,
|
|
154
|
+
enabled,
|
|
155
|
+
name: merged.name?.trim() || undefined,
|
|
156
|
+
token: "",
|
|
157
|
+
tokenSource: "none",
|
|
158
|
+
tokenStatus: "missing",
|
|
159
|
+
configured: false,
|
|
160
|
+
config: merged,
|
|
161
|
+
};
|
|
162
|
+
}
|
|
163
|
+
export function inspectTelegramAccount(params) {
|
|
164
|
+
return resolveAccountWithDefaultFallback({
|
|
165
|
+
accountId: params.accountId,
|
|
166
|
+
normalizeAccountId,
|
|
167
|
+
resolvePrimary: (accountId) => inspectTelegramAccountPrimary({
|
|
168
|
+
cfg: params.cfg,
|
|
169
|
+
accountId,
|
|
170
|
+
envToken: params.envToken,
|
|
171
|
+
}),
|
|
172
|
+
hasCredential: (account) => account.tokenSource !== "none",
|
|
173
|
+
resolveDefaultAccountId: () => resolveDefaultTelegramAccountId(params.cfg),
|
|
174
|
+
});
|
|
175
|
+
}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
export function normalizeTelegramAllowFromEntry(raw) {
|
|
2
|
+
const base = typeof raw === "string" ? raw : typeof raw === "number" ? String(raw) : "";
|
|
3
|
+
return base
|
|
4
|
+
.trim()
|
|
5
|
+
.replace(/^(telegram|tg):/i, "")
|
|
6
|
+
.trim();
|
|
7
|
+
}
|
|
8
|
+
export function isNumericTelegramUserId(raw) {
|
|
9
|
+
return /^-?\d+$/.test(raw);
|
|
10
|
+
}
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
export async function fetchTelegramChatId(params) {
|
|
2
|
+
const url = `https://api.telegram.org/bot${params.token}/getChat?chat_id=${encodeURIComponent(params.chatId)}`;
|
|
3
|
+
try {
|
|
4
|
+
const res = await fetch(url, params.signal ? { signal: params.signal } : undefined);
|
|
5
|
+
if (!res.ok) {
|
|
6
|
+
return null;
|
|
7
|
+
}
|
|
8
|
+
const data = (await res.json().catch(() => null));
|
|
9
|
+
const id = data?.ok ? data?.result?.id : undefined;
|
|
10
|
+
if (typeof id === "number" || typeof id === "string") {
|
|
11
|
+
return String(id);
|
|
12
|
+
}
|
|
13
|
+
return null;
|
|
14
|
+
}
|
|
15
|
+
catch {
|
|
16
|
+
return null;
|
|
17
|
+
}
|
|
18
|
+
}
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
const MAX_CALLBACK_DATA_BYTES = 64;
|
|
2
|
+
function fitsCallbackData(value) {
|
|
3
|
+
return Buffer.byteLength(value, "utf8") <= MAX_CALLBACK_DATA_BYTES;
|
|
4
|
+
}
|
|
5
|
+
export function buildTelegramExecApprovalButtons(approvalId) {
|
|
6
|
+
return buildTelegramExecApprovalButtonsForDecisions(approvalId, [
|
|
7
|
+
"allow-once",
|
|
8
|
+
"allow-always",
|
|
9
|
+
"deny",
|
|
10
|
+
]);
|
|
11
|
+
}
|
|
12
|
+
function buildTelegramExecApprovalButtonsForDecisions(approvalId, allowedDecisions) {
|
|
13
|
+
const allowOnce = `/approve ${approvalId} allow-once`;
|
|
14
|
+
if (!allowedDecisions.includes("allow-once") || !fitsCallbackData(allowOnce)) {
|
|
15
|
+
return undefined;
|
|
16
|
+
}
|
|
17
|
+
const primaryRow = [
|
|
18
|
+
{ text: "Allow Once", callback_data: allowOnce },
|
|
19
|
+
];
|
|
20
|
+
const allowAlways = `/approve ${approvalId} allow-always`;
|
|
21
|
+
if (allowedDecisions.includes("allow-always") && fitsCallbackData(allowAlways)) {
|
|
22
|
+
primaryRow.push({ text: "Allow Always", callback_data: allowAlways });
|
|
23
|
+
}
|
|
24
|
+
const rows = [primaryRow];
|
|
25
|
+
const deny = `/approve ${approvalId} deny`;
|
|
26
|
+
if (allowedDecisions.includes("deny") && fitsCallbackData(deny)) {
|
|
27
|
+
rows.push([{ text: "Deny", callback_data: deny }]);
|
|
28
|
+
}
|
|
29
|
+
return rows;
|
|
30
|
+
}
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
import { isRecord } from "../../../src/utils.js";
|
|
2
|
+
import { fetchWithTimeout } from "../../../src/utils/fetch-timeout.js";
|
|
3
|
+
import { resolveTelegramFetch } from "./fetch.js";
|
|
4
|
+
import { makeProxyFetch } from "./proxy.js";
|
|
5
|
+
const TELEGRAM_API_BASE = "https://api.telegram.org";
|
|
6
|
+
export async function auditTelegramGroupMembershipImpl(params) {
|
|
7
|
+
const proxyFetch = params.proxyUrl ? makeProxyFetch(params.proxyUrl) : undefined;
|
|
8
|
+
const fetcher = resolveTelegramFetch(proxyFetch, { network: params.network });
|
|
9
|
+
const base = `${TELEGRAM_API_BASE}/bot${params.token}`;
|
|
10
|
+
const groups = [];
|
|
11
|
+
for (const chatId of params.groupIds) {
|
|
12
|
+
try {
|
|
13
|
+
const url = `${base}/getChatMember?chat_id=${encodeURIComponent(chatId)}&user_id=${encodeURIComponent(String(params.botId))}`;
|
|
14
|
+
const res = await fetchWithTimeout(url, {}, params.timeoutMs, fetcher);
|
|
15
|
+
const json = (await res.json());
|
|
16
|
+
if (!res.ok || !isRecord(json) || !json.ok) {
|
|
17
|
+
const desc = isRecord(json) && !json.ok && typeof json.description === "string"
|
|
18
|
+
? json.description
|
|
19
|
+
: `getChatMember failed (${res.status})`;
|
|
20
|
+
groups.push({
|
|
21
|
+
chatId,
|
|
22
|
+
ok: false,
|
|
23
|
+
status: null,
|
|
24
|
+
error: desc,
|
|
25
|
+
matchKey: chatId,
|
|
26
|
+
matchSource: "id",
|
|
27
|
+
});
|
|
28
|
+
continue;
|
|
29
|
+
}
|
|
30
|
+
const status = isRecord(json.result)
|
|
31
|
+
? (json.result.status ?? null)
|
|
32
|
+
: null;
|
|
33
|
+
const ok = status === "creator" || status === "administrator" || status === "member";
|
|
34
|
+
groups.push({
|
|
35
|
+
chatId,
|
|
36
|
+
ok,
|
|
37
|
+
status,
|
|
38
|
+
error: ok ? null : "bot not in group",
|
|
39
|
+
matchKey: chatId,
|
|
40
|
+
matchSource: "id",
|
|
41
|
+
});
|
|
42
|
+
}
|
|
43
|
+
catch (err) {
|
|
44
|
+
groups.push({
|
|
45
|
+
chatId,
|
|
46
|
+
ok: false,
|
|
47
|
+
status: null,
|
|
48
|
+
error: err instanceof Error ? err.message : String(err),
|
|
49
|
+
matchKey: chatId,
|
|
50
|
+
matchSource: "id",
|
|
51
|
+
});
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
return {
|
|
55
|
+
ok: groups.every((g) => g.ok),
|
|
56
|
+
checkedGroups: groups.length,
|
|
57
|
+
unresolvedGroups: 0,
|
|
58
|
+
hasWildcardUnmentionedGroups: false,
|
|
59
|
+
groups,
|
|
60
|
+
};
|
|
61
|
+
}
|