cclawd 1.0.4 → 1.0.5

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.
Files changed (67) hide show
  1. package/dist/build-info.json +2 -2
  2. package/dist/plugin-sdk/imessage.js +2 -2
  3. package/dist/plugin-sdk/index.js +35 -35
  4. package/dist/plugin-sdk/signal.js +2 -2
  5. package/extensions/mfa-auth/src/notification-service.ts +68 -24
  6. package/package.json +1 -1
  7. package/dist/plugin-sdk/active-listener-CN-tMEvN.js +0 -35
  8. package/dist/plugin-sdk/api-key-rotation-CimGYMBc.js +0 -176
  9. package/dist/plugin-sdk/audio-preflight-C-xXBoE2.js +0 -51
  10. package/dist/plugin-sdk/audio-transcription-runner-CTIHpebA.js +0 -2173
  11. package/dist/plugin-sdk/audit-membership-runtime-BFatB2LJ.js +0 -58
  12. package/dist/plugin-sdk/channel-activity-DO0FEzyj.js +0 -95
  13. package/dist/plugin-sdk/channel-web-Da-__nUF.js +0 -2238
  14. package/dist/plugin-sdk/commands-registry-6no2NNrY.js +0 -1118
  15. package/dist/plugin-sdk/compact.runtime-CCoclu5e.js +0 -35
  16. package/dist/plugin-sdk/config-B9ODwgpz.js +0 -37426
  17. package/dist/plugin-sdk/deliver-B1fFpKjV.js +0 -1757
  18. package/dist/plugin-sdk/deliver-runtime-DB-VRMe1.js +0 -15
  19. package/dist/plugin-sdk/deps-send-discord.runtime-DklqycYG.js +0 -15
  20. package/dist/plugin-sdk/deps-send-imessage.runtime-Chs8zeon.js +0 -14
  21. package/dist/plugin-sdk/deps-send-signal.runtime-clW9aSJP.js +0 -13
  22. package/dist/plugin-sdk/deps-send-slack.runtime-BUx0LYY1.js +0 -13
  23. package/dist/plugin-sdk/deps-send-telegram.runtime-LECSHgMG.js +0 -16
  24. package/dist/plugin-sdk/deps-send-whatsapp.runtime-D2d65fw0.js +0 -40
  25. package/dist/plugin-sdk/diagnostic-CxIvS-C2.js +0 -315
  26. package/dist/plugin-sdk/dispatch-BqlR4dPx.js +0 -105863
  27. package/dist/plugin-sdk/env-b9k1PHMI.js +0 -34
  28. package/dist/plugin-sdk/fetch-PoxzAANT.js +0 -326
  29. package/dist/plugin-sdk/fetch-guard-4UVSZ0uS.js +0 -164
  30. package/dist/plugin-sdk/image-Ch6M4tnJ.js +0 -2420
  31. package/dist/plugin-sdk/image-runtime-CSh2o5wY.js +0 -8
  32. package/dist/plugin-sdk/ir-CugsqGH8.js +0 -1312
  33. package/dist/plugin-sdk/local-roots-adnEg9zb.js +0 -217
  34. package/dist/plugin-sdk/logger-D6zRubj0.js +0 -1164
  35. package/dist/plugin-sdk/login-CYvkQ0At.js +0 -54
  36. package/dist/plugin-sdk/login-qr-ll4NtaT5.js +0 -316
  37. package/dist/plugin-sdk/manager-CHy8IclH.js +0 -3959
  38. package/dist/plugin-sdk/manager-runtime-C70EkEr7.js +0 -11
  39. package/dist/plugin-sdk/outbound-Wzs2iN7X.js +0 -216
  40. package/dist/plugin-sdk/outbound-attachment-khXJwucX.js +0 -17
  41. package/dist/plugin-sdk/paths-BtVqCdw4.js +0 -3063
  42. package/dist/plugin-sdk/pi-model-discovery-Dh4ziodY.js +0 -131
  43. package/dist/plugin-sdk/pi-model-discovery-runtime-b83Xe-HT.js +0 -8
  44. package/dist/plugin-sdk/pi-tools.before-tool-call.runtime-C1z5CDBF.js +0 -349
  45. package/dist/plugin-sdk/proxy-fetch-CJEmoBxi.js +0 -54
  46. package/dist/plugin-sdk/pw-ai-Dj3Cvlzl.js +0 -1990
  47. package/dist/plugin-sdk/qmd-manager-egHUAseQ.js +0 -1581
  48. package/dist/plugin-sdk/resolve-outbound-target-BiICvIKs.js +0 -38
  49. package/dist/plugin-sdk/runtime-whatsapp-login.runtime-DNApufzW.js +0 -9
  50. package/dist/plugin-sdk/runtime-whatsapp-outbound.runtime-CBmtfIQ8.js +0 -13
  51. package/dist/plugin-sdk/send-CScblaI4.js +0 -532
  52. package/dist/plugin-sdk/send-CeHhnld6.js +0 -407
  53. package/dist/plugin-sdk/send-DP_c8JfR.js +0 -3277
  54. package/dist/plugin-sdk/send-Dc5fI6e8.js +0 -495
  55. package/dist/plugin-sdk/send-l-77_s1_.js +0 -2507
  56. package/dist/plugin-sdk/session-CkOKZaqa.js +0 -166
  57. package/dist/plugin-sdk/skill-commands-BohYCgkq.js +0 -336
  58. package/dist/plugin-sdk/slash-commands.runtime-DpLfVTM6.js +0 -8
  59. package/dist/plugin-sdk/slash-dispatch.runtime-CASMHwpm.js +0 -35
  60. package/dist/plugin-sdk/slash-skill-commands.runtime-D7rrJEci.js +0 -9
  61. package/dist/plugin-sdk/sqlite-CJE3X7Mv.js +0 -1005
  62. package/dist/plugin-sdk/subagent-registry-runtime-B1oo5bih.js +0 -35
  63. package/dist/plugin-sdk/tables-D5VgpTmm.js +0 -53
  64. package/dist/plugin-sdk/target-errors-C6zZ_OpA.js +0 -191
  65. package/dist/plugin-sdk/tokens-DUnJnpMS.js +0 -50
  66. package/dist/plugin-sdk/web-TfUM1nSi.js +0 -39
  67. package/dist/plugin-sdk/whatsapp-actions-DuWJ0j1r.js +0 -71
@@ -1,5 +1,5 @@
1
1
  {
2
- "version": "1.0.4",
2
+ "version": "1.0.5",
3
3
  "commit": "dcee9f245a22ea09abb0f25d03d6e980669df08f",
4
- "builtAt": "2026-03-18T07:00:07.749Z"
4
+ "builtAt": "2026-03-18T07:07:26.467Z"
5
5
  }
@@ -5,7 +5,7 @@ import chalk, { Chalk } from "chalk";
5
5
  import fs, { constants } from "node:fs";
6
6
  import { Logger } from "tslog";
7
7
  import os from "node:os";
8
- import JSON5 from "json5";
8
+ import json5 from "json5";
9
9
  import { promisify } from "node:util";
10
10
  import fs$1 from "node:fs/promises";
11
11
  import "@clack/prompts";
@@ -747,7 +747,7 @@ function readLoggingConfig() {
747
747
  try {
748
748
  if (!fs.existsSync(configPath)) return;
749
749
  const raw = fs.readFileSync(configPath, "utf-8");
750
- const logging = JSON5.parse(raw)?.logging;
750
+ const logging = json5.parse(raw)?.logging;
751
751
  if (!logging || typeof logging !== "object" || Array.isArray(logging)) return;
752
752
  return logging;
753
753
  } catch {
@@ -1,43 +1,43 @@
1
- import { E as redactSensitiveText, Ft as DEFAULT_ACCOUNT_ID, It as normalizeAccountId, Mt as resolveThreadSessionKeys, _ as openFileWithinRoot, c as applyWindowsSpawnProgramPolicy, ct as sameFileIdentity, d as resolveWindowsSpawnProgram, dt as isPathInside, f as resolveWindowsSpawnProgramCandidate, kt as normalizeAgentId, l as materializeWindowsSpawnProgram, nt as runCommandWithTimeout, p as SafeOpenError, u as resolveWindowsExecutablePath, ut as isNotFoundPathError, v as openWritableFileWithinRoot } from "./paths-BtVqCdw4.js";
2
- import { $i as resolveWhatsAppGroupToolPolicy, $l as normalizeResolvedSecretInputString, $t as requireApiKey, A as DmConfigSchema, Aa as formatTrimmedAllowFromEntries, Ao as resolveToolsBySender, B as TtsProviderSchema, Ba as resolveDefaultWhatsAppAccountId, Bi as resolveBlueBubblesGroupRequireMention, Ci as listTelegramDirectoryGroupsFromConfig, Co as resolveDefaultDiscordAccountId, Da as resolveSignalAccount, Di as looksLikeSlackTargetId, Ds as getFileExtension, Ea as resolveDefaultSignalAccountId, Ei as listWhatsAppDirectoryPeersFromConfig, Es as extensionForMime, F as ReplyRuntimeConfigSchemaShape, Fa as resolveOptionalConfigString, Gi as resolveGoogleChatGroupToolPolicy, H as requireOpenAllowFrom, Ha as resolveWhatsAppAuthDir, Hi as resolveDiscordGroupRequireMention, Hl as withFileLock, Hs as formatErrorMessage, I as SecretInputSchema, Ia as resolveWhatsAppConfigAllowFrom, Ii as resolveWhatsAppGroupIntroHint, Jc as getChatChannelMeta, Ji as resolveSlackGroupRequireMention, Jl as assertSecretInputResolved, Ki as resolveIMessageGroupRequireMention, L as TtsAutoSchema, La as resolveWhatsAppConfigDefaultTo, Li as resolveWhatsAppMentionStripPatterns, M as GroupPolicySchema, Ma as mapAllowFromEntries, Ml as resolveDefaultSecretProviderAlias, N as MarkdownConfigSchema, Na as resolveIMessageConfigAllowFrom, O as ToolPolicySchema, Oa as createScopedAccountConfigAccessors, Oi as normalizeSlackMessagingTarget, Oo as resolveChannelGroupRequireMention, P as MarkdownTableModeSchema, Pa as resolveIMessageConfigDefaultTo, Pl as encodeJsonPointerToken, Qi as resolveWhatsAppGroupRequireMention, Ql as isValidEnvSecretRefId, R as TtsConfigSchema, Ri as looksLikeSignalTargetId, Si as listSlackDirectoryPeersFromConfig, Ss as extractOriginalFilename, Ta as listSignalAccountIds, Ti as listWhatsAppDirectoryGroupsFromConfig, Ts as detectMime, Ui as resolveDiscordGroupToolPolicy, Ul as formatCliCommand, V as normalizeAllowFrom, Va as resolveWhatsAppAccount, Vi as resolveBlueBubblesGroupToolPolicy, Vl as acquireFileLock, Wi as resolveGoogleChatGroupRequireMention, Xi as resolveTelegramGroupRequireMention, Xl as hasConfiguredSecretInput, Yi as resolveSlackGroupToolPolicy, Zi as resolveTelegramGroupToolPolicy, Zl as isSecretRef, Zs as SsrFBlockedError, _ as TelegramConfigSchema, _a as listEnabledSlackAccounts, _o as isAllowedParsedChatSender, aa as listTelegramAccountIds, ao as looksLikeWhatsAppTargetId, ba as resolveSlackAccount, bi as listDiscordDirectoryPeersFromConfig, bs as rawDataToString, co as looksLikeHandleOrPhoneTarget, d as DiscordConfigSchema, do as normalizeWhatsAppTarget, du as createAccountListHelpers, ec as isBlockedHostname, eu as normalizeSecretInputString, f as GoogleChatConfigSchema, fo as clearAccountEntryFields, g as SlackConfigSchema, ga as inspectSlackAccount, go as formatNormalizedAllowFromEntries, h as SignalConfigSchema, ha as buildSlackThreadingToolContext, ho as formatAllowFromLowercase, io as resolveIMessageAccount, j as DmPolicySchema, ja as formatWhatsAppConfigAllowFromEntries, jl as isValidFileSecretRefId, k as BlockStreamingCoalesceSchema, ka as createScopedChannelConfigBase, lo as trimMessagingTarget, m as MSTeamsConfigSchema, ma as resolveAccountWithDefaultFallback, ml as registerContextEngine, mo as setAccountEnabledInConfigSection, na as inspectTelegramAccount, nc as isPrivateIpAddress, no as listIMessageAccountIds, oa as resolveDefaultTelegramAccountId, ol as normalizePluginHttpPath, oo as normalizeWhatsAppAllowFromEntries, p as IMessageConfigSchema, pa as listConfiguredAccountIds, po as deleteAccountFromConfigSection, qi as resolveIMessageGroupToolPolicy, ro as resolveDefaultIMessageAccountId, sa as resolveTelegramAccount, so as normalizeWhatsAppMessagingTarget, tc as isBlockedHostnameOrIp, u as WhatsAppConfigSchema, uo as isWhatsAppGroupJid, va as listSlackAccountIds, vo as isNormalizedSenderAllowed, wi as listTelegramDirectoryPeersFromConfig, wl as resolveSecretRefString, wo as resolveDiscordAccount, xa as resolveSlackReplyToMode, xi as listSlackDirectoryGroupsFromConfig, xo as listDiscordAccountIds, ya as resolveDefaultSlackAccountId, yi as listDiscordDirectoryGroupsFromConfig, yo as inspectDiscordAccount, z as TtsModeSchema, za as listWhatsAppAccountIds, zi as normalizeSignalMessagingTarget } from "./config-B9ODwgpz.js";
3
- import { $t as installRequestBodyLimitGuard, A as createReplyPrefixContext, At as createReceiptCard, B as evictOldHistoryKeys, Bt as DM_GROUP_ACCESS_REASON, C as resolveDiscordChannelAllowlist, Cn as CHANNEL_MESSAGE_ACTION_NAMES, D as resolveMentionGating, Dt as hasMarkdownToConvert, F as DEFAULT_GROUP_HISTORY_LIMIT, G as recordInboundSession, Gt as resolveDmGroupAccessWithLists, H as recordPendingHistoryEntryIfEnabled, Ht as resolveDmAllowState, It as formatInboundFromLabel, J as shouldAckReactionForWhatsApp, Jt as resolveControlCommandGate, K as removeAckReactionAfterReply, Kt as resolveEffectiveAllowFromLists, L as buildPendingHistoryContextFromMap, Lt as formatUtcTimestamp, M as logAckFailure, Mt as extractToolSend, N as logInboundDrop, Nt as issuePairingChallenge, O as resolveMentionGatingWithBypass, Ot as processLineMessage, P as logTypingFailure, Pt as resolveInboundSessionEnvelopeContext, Qt as RequestBodyLimitError, R as clearHistoryEntries, Rt as formatZonedTimestamp, S as resolveDiscordUserAllowlist, Sn as BLUEBUBBLES_GROUP_ACTIONS, T as summarizeMapping, U as buildMediaPayload, Ut as resolveDmGroupAccessDecision, V as recordPendingHistoryEntry, Vt as readStoreAllowFromForDmPolicy, W as collectDiscordAuditChannelIds, Wt as resolveDmGroupAccessWithCommandGate, Xt as DEFAULT_WEBHOOK_BODY_TIMEOUT_MS, Yt as pruneMapToMaxSize, Zt as DEFAULT_WEBHOOK_MAX_BODY_BYTES, _ as listLineAccountIds, _n as formatAllowlistMatchMeta, an as enqueueKeyedTask, b as resolveLineAccount, bn as BLUEBUBBLES_ACTIONS, bt as listDevicePairing, cn as getAcpRuntimeBackend, dn as unregisterAcpRuntimeBackend, dt as readBooleanParam, en as isRequestBodyLimitError, f as formatDocsLink, fn as ACP_ERROR_CODES, ft as optionalStringEnum, g as resolveSlackChannelAllowlist, gn as unbindThreadBindingsBySessionKey, gt as resolveAckReaction, h as resolveSlackUserAllowlist, hn as listThreadBindingsBySessionKey, in as KeyedAsyncQueue, j as createReplyPrefixOptions, jt as attachFooterText, k as createTypingCallbacks, kt as stripMarkdown, ln as registerAcpRuntimeBackend, lt as parseTelegramReplyToMessageId, mn as autoBindSpawnedDiscordSubagent, n as dispatchReplyFromConfig, nn as readRequestBodyWithLimit, on as isDangerousNameMatchingEnabled, ot as createDedupeCache, pn as AcpRuntimeError, pt as stringEnum, q as shouldAckReaction, rn as requestBodyErrorToText, sn as registerPluginHttpRoute, t as withReplyDispatcher, tn as readJsonBodyWithLimit, un as requireAcpRuntimeBackend, ut as parseTelegramThreadId, v as normalizeAccountId$1, vn as resolveAllowlistMatchByCandidates, w as mergeAllowlist, x as detectBinary, xn as BLUEBUBBLES_ACTION_NAMES, xt as rejectDevicePairing, y as resolveDefaultLineAccountId, yn as resolveAllowlistMatchSimple, yt as approveDevicePairing, z as clearHistoryEntriesIfEnabled, zt as resolveTimezone } from "./dispatch-BqlR4dPx.js";
1
+ import { E as redactSensitiveText, Ft as DEFAULT_ACCOUNT_ID, It as normalizeAccountId, Mt as resolveThreadSessionKeys, _ as openFileWithinRoot, c as applyWindowsSpawnProgramPolicy, ct as sameFileIdentity, d as resolveWindowsSpawnProgram, dt as isPathInside, f as resolveWindowsSpawnProgramCandidate, kt as normalizeAgentId, l as materializeWindowsSpawnProgram, nt as runCommandWithTimeout, p as SafeOpenError, u as resolveWindowsExecutablePath, ut as isNotFoundPathError, v as openWritableFileWithinRoot } from "./paths-BMopnplU.js";
2
+ import { $i as resolveWhatsAppGroupToolPolicy, $l as normalizeResolvedSecretInputString, $t as requireApiKey, A as DmConfigSchema, Aa as formatTrimmedAllowFromEntries, Ao as resolveToolsBySender, B as TtsProviderSchema, Ba as resolveDefaultWhatsAppAccountId, Bi as resolveBlueBubblesGroupRequireMention, Ci as listTelegramDirectoryGroupsFromConfig, Co as resolveDefaultDiscordAccountId, Da as resolveSignalAccount, Di as looksLikeSlackTargetId, Ds as getFileExtension, Ea as resolveDefaultSignalAccountId, Ei as listWhatsAppDirectoryPeersFromConfig, Es as extensionForMime, F as ReplyRuntimeConfigSchemaShape, Fa as resolveOptionalConfigString, Gi as resolveGoogleChatGroupToolPolicy, H as requireOpenAllowFrom, Ha as resolveWhatsAppAuthDir, Hi as resolveDiscordGroupRequireMention, Hl as withFileLock, Hs as formatErrorMessage, I as SecretInputSchema, Ia as resolveWhatsAppConfigAllowFrom, Ii as resolveWhatsAppGroupIntroHint, Jc as getChatChannelMeta, Ji as resolveSlackGroupRequireMention, Jl as assertSecretInputResolved, Ki as resolveIMessageGroupRequireMention, L as TtsAutoSchema, La as resolveWhatsAppConfigDefaultTo, Li as resolveWhatsAppMentionStripPatterns, M as GroupPolicySchema, Ma as mapAllowFromEntries, Ml as resolveDefaultSecretProviderAlias, N as MarkdownConfigSchema, Na as resolveIMessageConfigAllowFrom, O as ToolPolicySchema, Oa as createScopedAccountConfigAccessors, Oi as normalizeSlackMessagingTarget, Oo as resolveChannelGroupRequireMention, P as MarkdownTableModeSchema, Pa as resolveIMessageConfigDefaultTo, Pl as encodeJsonPointerToken, Qi as resolveWhatsAppGroupRequireMention, Ql as isValidEnvSecretRefId, R as TtsConfigSchema, Ri as looksLikeSignalTargetId, Si as listSlackDirectoryPeersFromConfig, Ss as extractOriginalFilename, Ta as listSignalAccountIds, Ti as listWhatsAppDirectoryGroupsFromConfig, Ts as detectMime, Ui as resolveDiscordGroupToolPolicy, Ul as formatCliCommand, V as normalizeAllowFrom, Va as resolveWhatsAppAccount, Vi as resolveBlueBubblesGroupToolPolicy, Vl as acquireFileLock, Wi as resolveGoogleChatGroupRequireMention, Xi as resolveTelegramGroupRequireMention, Xl as hasConfiguredSecretInput, Yi as resolveSlackGroupToolPolicy, Zi as resolveTelegramGroupToolPolicy, Zl as isSecretRef, Zs as SsrFBlockedError, _ as TelegramConfigSchema, _a as listEnabledSlackAccounts, _o as isAllowedParsedChatSender, aa as listTelegramAccountIds, ao as looksLikeWhatsAppTargetId, ba as resolveSlackAccount, bi as listDiscordDirectoryPeersFromConfig, bs as rawDataToString, co as looksLikeHandleOrPhoneTarget, d as DiscordConfigSchema, do as normalizeWhatsAppTarget, du as createAccountListHelpers, ec as isBlockedHostname, eu as normalizeSecretInputString, f as GoogleChatConfigSchema, fo as clearAccountEntryFields, g as SlackConfigSchema, ga as inspectSlackAccount, go as formatNormalizedAllowFromEntries, h as SignalConfigSchema, ha as buildSlackThreadingToolContext, ho as formatAllowFromLowercase, io as resolveIMessageAccount, j as DmPolicySchema, ja as formatWhatsAppConfigAllowFromEntries, jl as isValidFileSecretRefId, k as BlockStreamingCoalesceSchema, ka as createScopedChannelConfigBase, lo as trimMessagingTarget, m as MSTeamsConfigSchema, ma as resolveAccountWithDefaultFallback, ml as registerContextEngine, mo as setAccountEnabledInConfigSection, na as inspectTelegramAccount, nc as isPrivateIpAddress, no as listIMessageAccountIds, oa as resolveDefaultTelegramAccountId, ol as normalizePluginHttpPath, oo as normalizeWhatsAppAllowFromEntries, p as IMessageConfigSchema, pa as listConfiguredAccountIds, po as deleteAccountFromConfigSection, qi as resolveIMessageGroupToolPolicy, ro as resolveDefaultIMessageAccountId, sa as resolveTelegramAccount, so as normalizeWhatsAppMessagingTarget, tc as isBlockedHostnameOrIp, u as WhatsAppConfigSchema, uo as isWhatsAppGroupJid, va as listSlackAccountIds, vo as isNormalizedSenderAllowed, wi as listTelegramDirectoryPeersFromConfig, wl as resolveSecretRefString, wo as resolveDiscordAccount, xa as resolveSlackReplyToMode, xi as listSlackDirectoryGroupsFromConfig, xo as listDiscordAccountIds, ya as resolveDefaultSlackAccountId, yi as listDiscordDirectoryGroupsFromConfig, yo as inspectDiscordAccount, z as TtsModeSchema, za as listWhatsAppAccountIds, zi as normalizeSignalMessagingTarget } from "./config-B6fwS1Kz.js";
3
+ import { $t as installRequestBodyLimitGuard, A as createReplyPrefixContext, At as createReceiptCard, B as evictOldHistoryKeys, Bt as DM_GROUP_ACCESS_REASON, C as resolveDiscordChannelAllowlist, Cn as CHANNEL_MESSAGE_ACTION_NAMES, D as resolveMentionGating, Dt as hasMarkdownToConvert, F as DEFAULT_GROUP_HISTORY_LIMIT, G as recordInboundSession, Gt as resolveDmGroupAccessWithLists, H as recordPendingHistoryEntryIfEnabled, Ht as resolveDmAllowState, It as formatInboundFromLabel, J as shouldAckReactionForWhatsApp, Jt as resolveControlCommandGate, K as removeAckReactionAfterReply, Kt as resolveEffectiveAllowFromLists, L as buildPendingHistoryContextFromMap, Lt as formatUtcTimestamp, M as logAckFailure, Mt as extractToolSend, N as logInboundDrop, Nt as issuePairingChallenge, O as resolveMentionGatingWithBypass, Ot as processLineMessage, P as logTypingFailure, Pt as resolveInboundSessionEnvelopeContext, Qt as RequestBodyLimitError, R as clearHistoryEntries, Rt as formatZonedTimestamp, S as resolveDiscordUserAllowlist, Sn as BLUEBUBBLES_GROUP_ACTIONS, T as summarizeMapping, U as buildMediaPayload, Ut as resolveDmGroupAccessDecision, V as recordPendingHistoryEntry, Vt as readStoreAllowFromForDmPolicy, W as collectDiscordAuditChannelIds, Wt as resolveDmGroupAccessWithCommandGate, Xt as DEFAULT_WEBHOOK_BODY_TIMEOUT_MS, Yt as pruneMapToMaxSize, Zt as DEFAULT_WEBHOOK_MAX_BODY_BYTES, _ as listLineAccountIds, _n as formatAllowlistMatchMeta, an as enqueueKeyedTask, b as resolveLineAccount, bn as BLUEBUBBLES_ACTIONS, bt as listDevicePairing, cn as getAcpRuntimeBackend, dn as unregisterAcpRuntimeBackend, dt as readBooleanParam, en as isRequestBodyLimitError, f as formatDocsLink, fn as ACP_ERROR_CODES, ft as optionalStringEnum, g as resolveSlackChannelAllowlist, gn as unbindThreadBindingsBySessionKey, gt as resolveAckReaction, h as resolveSlackUserAllowlist, hn as listThreadBindingsBySessionKey, in as KeyedAsyncQueue, j as createReplyPrefixOptions, jt as attachFooterText, k as createTypingCallbacks, kt as stripMarkdown, ln as registerAcpRuntimeBackend, lt as parseTelegramReplyToMessageId, mn as autoBindSpawnedDiscordSubagent, n as dispatchReplyFromConfig, nn as readRequestBodyWithLimit, on as isDangerousNameMatchingEnabled, ot as createDedupeCache, pn as AcpRuntimeError, pt as stringEnum, q as shouldAckReaction, rn as requestBodyErrorToText, sn as registerPluginHttpRoute, t as withReplyDispatcher, tn as readJsonBodyWithLimit, un as requireAcpRuntimeBackend, ut as parseTelegramThreadId, v as normalizeAccountId$1, vn as resolveAllowlistMatchByCandidates, w as mergeAllowlist, x as detectBinary, xn as BLUEBUBBLES_ACTION_NAMES, xt as rejectDevicePairing, y as resolveDefaultLineAccountId, yn as resolveAllowlistMatchSimple, yt as approveDevicePairing, z as clearHistoryEntriesIfEnabled, zt as resolveTimezone } from "./dispatch-DHll-mp1.js";
4
4
  import "./paths-eFexkPEh.js";
5
5
  import "./github-copilot-token-Cxf8QYZb.js";
6
- import { C as normalizeE164, O as safeParseJson, Q as resolvePreferredOpenClawTmpDir, b as isRecord, j as sleep, m as clamp, p as CONFIG_DIR, q as registerLogTransport, s as stripAnsi, v as escapeRegExp, w as pathExists } from "./logger-D6zRubj0.js";
7
- import { t as isTruthyEnvValue } from "./env-b9k1PHMI.js";
8
- import { At as GROUP_POLICY_BLOCKED_LABEL, Bt as buildChannelKeyCandidates, Dt as evaluateSenderGroupAccess, Et as evaluateMatchedGroupAccessForPolicy, Ft as resolveRuntimeGroupPolicy, Ht as resolveChannelEntryMatch, It as warnMissingProviderGroupPolicyFallbackOnce, Mt as resolveAllowlistProviderRuntimeGroupPolicy, Nt as resolveDefaultGroupPolicy, Ot as evaluateSenderGroupAccessForPolicy, Pt as resolveOpenProviderRuntimeGroupPolicy, Tt as evaluateGroupRouteAccessForPolicy, Ut as resolveChannelEntryMatchWithFallback, Vt as normalizeChannelSlug, Wt as resolveNestedAllowlistDecision, at as parseDiscordTarget, dt as normalizeDiscordSlug, jt as resetMissingProviderGroupPolicyFallbackWarningsForTesting, kt as resolveSenderScopedGroupPolicy } from "./send-DP_c8JfR.js";
6
+ import { C as normalizeE164, O as safeParseJson, Q as resolvePreferredOpenClawTmpDir, b as isRecord, j as sleep, m as clamp, p as CONFIG_DIR, q as registerLogTransport, s as stripAnsi, v as escapeRegExp, w as pathExists } from "./logger-4h9G_BiT.js";
7
+ import { t as isTruthyEnvValue } from "./env-16_axnas.js";
8
+ import { At as GROUP_POLICY_BLOCKED_LABEL, Bt as buildChannelKeyCandidates, Dt as evaluateSenderGroupAccess, Et as evaluateMatchedGroupAccessForPolicy, Ft as resolveRuntimeGroupPolicy, Ht as resolveChannelEntryMatch, It as warnMissingProviderGroupPolicyFallbackOnce, Mt as resolveAllowlistProviderRuntimeGroupPolicy, Nt as resolveDefaultGroupPolicy, Ot as evaluateSenderGroupAccessForPolicy, Pt as resolveOpenProviderRuntimeGroupPolicy, Tt as evaluateGroupRouteAccessForPolicy, Ut as resolveChannelEntryMatchWithFallback, Vt as normalizeChannelSlug, Wt as resolveNestedAllowlistDecision, at as parseDiscordTarget, dt as normalizeDiscordSlug, jt as resetMissingProviderGroupPolicyFallbackWarningsForTesting, kt as resolveSenderScopedGroupPolicy } from "./send-CrviNQqd.js";
9
9
  import "./fetch-BSKpf2dM.js";
10
- import "./channel-activity-DO0FEzyj.js";
11
- import { t as fetchWithSsrFGuard } from "./fetch-guard-4UVSZ0uS.js";
12
- import "./local-roots-adnEg9zb.js";
13
- import { p as chunkTextByBreakResolver, v as loadWebMedia } from "./ir-CugsqGH8.js";
10
+ import "./channel-activity-D1ewxjRA.js";
11
+ import { t as fetchWithSsrFGuard } from "./fetch-guard-D5xZ4NgD.js";
12
+ import "./local-roots-BmJJ0DW6.js";
13
+ import { p as chunkTextByBreakResolver, v as loadWebMedia } from "./ir-sjcp8bOx.js";
14
14
  import "./render-CKf6NJ1M.js";
15
- import "./tables-D5VgpTmm.js";
16
- import { J as formatLocationText, Y as toLocationContext, nt as readJsonFileWithFallback, rt as writeJsonFileAtomically } from "./send-l-77_s1_.js";
17
- import { d as readNumberParam, f as readReactionParams, h as readStringParam, l as jsonResult, n as missingTargetError, o as createActionGate } from "./target-errors-C6zZ_OpA.js";
18
- import { s as parseSlackBlocksInput } from "./send-CeHhnld6.js";
19
- import { h as resolveChannelMediaMaxBytes } from "./deliver-B1fFpKjV.js";
20
- import { g as onDiagnosticEvent, h as isDiagnosticsEnabled, m as emitDiagnosticEvent } from "./diagnostic-CxIvS-C2.js";
21
- import "./pi-model-discovery-Dh4ziodY.js";
22
- import { d as buildRandomTempFilePath, f as withTempDownloadPath } from "./audio-transcription-runner-CTIHpebA.js";
23
- import "./image-Ch6M4tnJ.js";
24
- import "./api-key-rotation-CimGYMBc.js";
25
- import "./proxy-fetch-CJEmoBxi.js";
26
- import { i as isSilentReplyText, n as SILENT_REPLY_TOKEN } from "./tokens-DUnJnpMS.js";
27
- import "./commands-registry-6no2NNrY.js";
15
+ import "./tables-BDIh5Jdg.js";
16
+ import { J as formatLocationText, Y as toLocationContext, nt as readJsonFileWithFallback, rt as writeJsonFileAtomically } from "./send-z35HNVtD.js";
17
+ import { d as readNumberParam, f as readReactionParams, h as readStringParam, l as jsonResult, n as missingTargetError, o as createActionGate } from "./target-errors-B3_uM5qQ.js";
18
+ import { s as parseSlackBlocksInput } from "./send-DoQSSC-e.js";
19
+ import { h as resolveChannelMediaMaxBytes } from "./deliver-sDS_neu8.js";
20
+ import { g as onDiagnosticEvent, h as isDiagnosticsEnabled, m as emitDiagnosticEvent } from "./diagnostic-BShsSCRy.js";
21
+ import "./pi-model-discovery-DDQEBQc9.js";
22
+ import { d as buildRandomTempFilePath, f as withTempDownloadPath } from "./audio-transcription-runner-BUqRvf08.js";
23
+ import "./image-DQ8fBtXx.js";
24
+ import "./api-key-rotation-DPjUBVuJ.js";
25
+ import "./proxy-fetch-DN1cfotw.js";
26
+ import { i as isSilentReplyText, n as SILENT_REPLY_TOKEN } from "./tokens-BQbFuzFW.js";
27
+ import "./commands-registry-CIaR-qRn.js";
28
28
  import { n as normalizeTelegramLookupTarget, r as parseTelegramTarget } from "./targets-s9KeyATC.js";
29
- import { n as listSkillCommandsForAgents } from "./skill-commands-BohYCgkq.js";
30
- import "./send-CScblaI4.js";
31
- import "./outbound-attachment-khXJwucX.js";
32
- import { c as createAllowedChatSenderMatcher, d as resolveServicePrefixedAllowTarget, f as resolveServicePrefixedChatTarget, l as parseChatAllowTargetPrefixes, m as resolveServicePrefixedTarget, o as normalizeIMessageHandle, p as resolveServicePrefixedOrChatAllowTarget, u as parseChatTargetPrefixesOrThrow } from "./send-Dc5fI6e8.js";
33
- import "./sqlite-CJE3X7Mv.js";
34
- import { i as isWSLSync, n as isWSL2Sync, r as isWSLEnv } from "./fetch-PoxzAANT.js";
35
- import "./manager-CHy8IclH.js";
36
- import { t as resolveWhatsAppOutboundTarget } from "./resolve-outbound-target-BiICvIKs.js";
37
- import { r as resolveWhatsAppHeartbeatRecipients } from "./channel-web-Da-__nUF.js";
38
- import "./outbound-Wzs2iN7X.js";
39
- import "./session-CkOKZaqa.js";
40
- import { t as loginWeb } from "./login-CYvkQ0At.js";
29
+ import { n as listSkillCommandsForAgents } from "./skill-commands-DuKOrryr.js";
30
+ import "./send-2kliIusR.js";
31
+ import "./outbound-attachment-B1n9VVI8.js";
32
+ import { c as createAllowedChatSenderMatcher, d as resolveServicePrefixedAllowTarget, f as resolveServicePrefixedChatTarget, l as parseChatAllowTargetPrefixes, m as resolveServicePrefixedTarget, o as normalizeIMessageHandle, p as resolveServicePrefixedOrChatAllowTarget, u as parseChatTargetPrefixesOrThrow } from "./send-BhMWDqI9.js";
33
+ import "./sqlite-BPMcn30D.js";
34
+ import { i as isWSLSync, n as isWSL2Sync, r as isWSLEnv } from "./fetch-BYCV2n_Y.js";
35
+ import "./manager-tIwC8DEO.js";
36
+ import { t as resolveWhatsAppOutboundTarget } from "./resolve-outbound-target-DfAPWL26.js";
37
+ import { r as resolveWhatsAppHeartbeatRecipients } from "./channel-web-DRnh0GDK.js";
38
+ import "./outbound-DutV0sq6.js";
39
+ import "./session-C5WI4lUa.js";
40
+ import { t as loginWeb } from "./login-A9QduCfA.js";
41
41
  import fs, { constants, createWriteStream } from "node:fs";
42
42
  import path from "node:path";
43
43
  import os from "node:os";
@@ -5,7 +5,7 @@ import chalk, { Chalk } from "chalk";
5
5
  import fs, { constants, createWriteStream } from "node:fs";
6
6
  import { Logger } from "tslog";
7
7
  import os from "node:os";
8
- import json5 from "json5";
8
+ import JSON5 from "json5";
9
9
  import { promisify } from "node:util";
10
10
  import { randomUUID } from "node:crypto";
11
11
  import fs$1 from "node:fs/promises";
@@ -752,7 +752,7 @@ function readLoggingConfig() {
752
752
  try {
753
753
  if (!fs.existsSync(configPath)) return;
754
754
  const raw = fs.readFileSync(configPath, "utf-8");
755
- const logging = json5.parse(raw)?.logging;
755
+ const logging = JSON5.parse(raw)?.logging;
756
756
  if (!logging || typeof logging !== "object" || Array.isArray(logging)) return;
757
757
  return logging;
758
758
  } catch {
@@ -22,34 +22,47 @@ class NotificationService {
22
22
  }
23
23
 
24
24
  async sendAuthNotification(session: AuthSession, message: string): Promise<void> {
25
- const { channel, accountId, to } = session.originalContext;
25
+ const { channel } = session.originalContext;
26
26
 
27
27
  if (!this.cfg) {
28
28
  console.warn("[mfa-auth] Config not set, skipping notification");
29
29
  return;
30
30
  }
31
31
 
32
- if (channel === "webchat" || channel === "web" || channel === "main" || channel === "desktop") {
33
- console.log(`[mfa-auth] ${channel} channel: sending notification via WebSocket`);
34
- await this.sendToWebChat(session, message);
35
- return;
36
- }
32
+ const normalizedChannel = String(channel || "")
33
+ .trim()
34
+ .toLowerCase();
37
35
 
38
- if (channel === "feishu") {
39
- await this.sendToFeishu(session, message);
36
+ if (normalizedChannel === "feishu") {
37
+ try {
38
+ await this.sendToFeishu(session, message);
39
+ } catch (error) {
40
+ // Fallback to gateway injection to avoid silent message loss when channel API
41
+ // permissions are temporarily missing.
42
+ console.warn(
43
+ `[mfa-auth] Feishu direct send failed, falling back to gateway inject: ${String(error)}`,
44
+ );
45
+ await this.sendViaGatewayInject(session, message, normalizedChannel);
46
+ }
40
47
  return;
41
48
  }
42
49
 
43
- console.warn(`[mfa-auth] Unsupported channel: ${channel}`);
50
+ await this.sendViaGatewayInject(session, message, normalizedChannel);
44
51
  }
45
52
 
46
- private async sendToWebChat(session: AuthSession, message: string): Promise<void> {
47
- const { sessionKey } = session.originalContext;
53
+ private async sendViaGatewayInject(
54
+ session: AuthSession,
55
+ message: string,
56
+ channelHint?: string,
57
+ ): Promise<void> {
58
+ const { sessionKey, accountId } = session.originalContext;
48
59
  const port = this.cfg?.gateway?.port || 18789;
49
60
  const token = this.cfg?.gateway?.auth?.token;
50
61
  const host = config.gatewayHost || "127.0.0.1";
51
62
 
52
- console.log(`[mfa-auth] sendToWebChat: sessionKey=${sessionKey}, host=${host}, port=${port}`);
63
+ console.log(
64
+ `[mfa-auth] sendViaGatewayInject: channel=${channelHint || "unknown"}, sessionKey=${sessionKey}, host=${host}, port=${port}`,
65
+ );
53
66
 
54
67
  // eslint-disable-next-line @typescript-eslint/no-explicit-any
55
68
  const wsModule = await import("ws");
@@ -133,7 +146,9 @@ class NotificationService {
133
146
  reject(new Error(`sessions.list failed: ${JSON.stringify(response.error)}`));
134
147
  return;
135
148
  }
136
- candidateSessionKeys = this.resolveWebchatSessionCandidates({
149
+ candidateSessionKeys = this.resolveSessionCandidates({
150
+ channelHint,
151
+ accountId,
137
152
  requestedSessionKey: sessionKey,
138
153
  userId: session.userId,
139
154
  targetTo: session.originalContext.to,
@@ -141,11 +156,11 @@ class NotificationService {
141
156
  });
142
157
  if (candidateSessionKeys.length === 0) {
143
158
  ws.close();
144
- reject(new Error("No candidate webchat sessions found"));
159
+ reject(new Error("No candidate sessions found for gateway inject"));
145
160
  return;
146
161
  }
147
162
  console.log(
148
- `[mfa-auth] candidate webchat sessions: ${candidateSessionKeys.join(", ")}`,
163
+ `[mfa-auth] candidate sessions (${channelHint || "any"}): ${candidateSessionKeys.join(", ")}`,
149
164
  );
150
165
  injectIndex = 0;
151
166
  sendInject(candidateSessionKeys[injectIndex]);
@@ -193,12 +208,20 @@ class NotificationService {
193
208
  });
194
209
  }
195
210
 
196
- private resolveWebchatSessionCandidates(params: {
211
+ private resolveSessionCandidates(params: {
212
+ channelHint?: string;
213
+ accountId?: string;
197
214
  requestedSessionKey?: string;
198
215
  userId: string;
199
216
  targetTo?: string;
200
217
  sessionsListResult: unknown;
201
218
  }): string[] {
219
+ const normalizedChannelHint = String(params.channelHint || "")
220
+ .trim()
221
+ .toLowerCase();
222
+ const normalizedAccountId = String(params.accountId || "")
223
+ .trim()
224
+ .toLowerCase();
202
225
  const normalizedTarget = String(params.targetTo || params.userId || "")
203
226
  .trim()
204
227
  .toLowerCase();
@@ -207,7 +230,7 @@ class NotificationService {
207
230
  ? (params.sessionsListResult as Record<string, unknown>)
208
231
  : undefined;
209
232
  const sessionsRaw = Array.isArray(resultObject?.sessions) ? resultObject.sessions : [];
210
- const webchatRows = sessionsRaw
233
+ const matchingRows = sessionsRaw
211
234
  .map((row) => (row && typeof row === "object" ? (row as Record<string, unknown>) : undefined))
212
235
  .filter((row): row is Record<string, unknown> => Boolean(row))
213
236
  .filter((row) => {
@@ -218,20 +241,40 @@ class NotificationService {
218
241
  const dcChannel = String(dc?.channel ?? "")
219
242
  .trim()
220
243
  .toLowerCase();
221
- return ch === "webchat" || ch === "web" || dcChannel === "webchat" || dcChannel === "web";
244
+
245
+ if (!normalizedChannelHint) {
246
+ return true;
247
+ }
248
+
249
+ if (normalizedChannelHint === "web" || normalizedChannelHint === "webchat") {
250
+ return ch === "webchat" || ch === "web" || dcChannel === "webchat" || dcChannel === "web";
251
+ }
252
+
253
+ return ch === normalizedChannelHint || dcChannel === normalizedChannelHint;
254
+ })
255
+ .filter((row) => {
256
+ if (!normalizedAccountId) return true;
257
+ const dc = row.deliveryContext as Record<string, unknown> | undefined;
258
+ const rowAccount = String(row.accountId ?? "")
259
+ .trim()
260
+ .toLowerCase();
261
+ const dcAccount = String(dc?.accountId ?? "")
262
+ .trim()
263
+ .toLowerCase();
264
+ return rowAccount === normalizedAccountId || dcAccount === normalizedAccountId;
222
265
  });
223
266
 
224
- const exactRows = webchatRows.filter((row) => {
267
+ const exactRows = matchingRows.filter((row) => {
225
268
  const dc = row.deliveryContext as Record<string, unknown> | undefined;
226
269
  const peer = String(dc?.to ?? row.lastTo ?? "")
227
270
  .trim()
228
271
  .toLowerCase();
229
272
  return peer.length > 0 && peer === normalizedTarget;
230
273
  });
231
- const fallbackRows = webchatRows.filter((row) => !exactRows.includes(row));
274
+ const fallbackRows = matchingRows.filter((row) => !exactRows.includes(row));
232
275
 
233
- // Fuzzy match: include any webchat session that contains the userId in its key
234
- const fuzzyRows = webchatRows.filter((row) => {
276
+ // Fuzzy match: include any session whose key contains the target id.
277
+ const fuzzyRows = matchingRows.filter((row) => {
235
278
  const key = String(row.key ?? "").toLowerCase();
236
279
  // Ensure we don't duplicate rows already found
237
280
  return (
@@ -253,9 +296,10 @@ class NotificationService {
253
296
  ...exactRows.map((row) => String(row.key ?? "").trim()),
254
297
  ...fallbackRows.map((row) => String(row.key ?? "").trim()),
255
298
  ...fuzzyRows.map((row) => String(row.key ?? "").trim()),
256
- // Add standard webchat patterns
299
+ // Common fallback patterns.
257
300
  `agent:main:${normalizedTarget}`,
258
- `webchat:${normalizedTarget}`,
301
+ `${normalizedChannelHint}:${normalizedTarget}`,
302
+ normalizedAccountId ? `${normalizedChannelHint}:${normalizedAccountId}:${normalizedTarget}` : "",
259
303
  normalizedTarget,
260
304
  "main",
261
305
  ];
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "cclawd",
3
- "version": "1.0.4",
3
+ "version": "1.0.5",
4
4
  "description": "Multi-channel AI gateway with extensible messaging integrations",
5
5
  "keywords": [],
6
6
  "homepage": "https://github.com/openclaw/openclaw#readme",
@@ -1,35 +0,0 @@
1
- import { Ft as DEFAULT_ACCOUNT_ID } from "./paths-BtVqCdw4.js";
2
- import { Ul as formatCliCommand } from "./config-B9ODwgpz.js";
3
- //#region src/web/active-listener.ts
4
- const listeners = /* @__PURE__ */ new Map();
5
- function resolveWebAccountId(accountId) {
6
- return (accountId ?? "").trim() || "default";
7
- }
8
- function requireActiveWebListener(accountId) {
9
- const id = resolveWebAccountId(accountId);
10
- const listener = listeners.get(id) ?? null;
11
- if (!listener) throw new Error(`No active WhatsApp Web listener (account: ${id}). Start the gateway, then link WhatsApp with: ${formatCliCommand(`openclaw channels login --channel whatsapp --account ${id}`)}.`);
12
- return {
13
- accountId: id,
14
- listener
15
- };
16
- }
17
- function setActiveWebListener(accountIdOrListener, maybeListener) {
18
- const { accountId, listener } = typeof accountIdOrListener === "string" ? {
19
- accountId: accountIdOrListener,
20
- listener: maybeListener ?? null
21
- } : {
22
- accountId: DEFAULT_ACCOUNT_ID,
23
- listener: accountIdOrListener ?? null
24
- };
25
- const id = resolveWebAccountId(accountId);
26
- if (!listener) listeners.delete(id);
27
- else listeners.set(id, listener);
28
- if (id === "default") {}
29
- }
30
- function getActiveWebListener(accountId) {
31
- const id = resolveWebAccountId(accountId);
32
- return listeners.get(id) ?? null;
33
- }
34
- //#endregion
35
- export { requireActiveWebListener as n, setActiveWebListener as r, getActiveWebListener as t };
@@ -1,176 +0,0 @@
1
- import { Hs as formatErrorMessage, Vt as normalizeProviderId } from "./config-B9ODwgpz.js";
2
- //#region src/infra/gemini-auth.ts
3
- /**
4
- * Shared Gemini authentication utilities.
5
- *
6
- * Supports both traditional API keys and OAuth JSON format.
7
- */
8
- /**
9
- * Parse Gemini API key and return appropriate auth headers.
10
- *
11
- * OAuth format: `{"token": "...", "projectId": "..."}`
12
- *
13
- * @param apiKey - Either a traditional API key string or OAuth JSON
14
- * @returns Headers object with appropriate authentication
15
- */
16
- function parseGeminiAuth(apiKey) {
17
- if (apiKey.startsWith("{")) try {
18
- const parsed = JSON.parse(apiKey);
19
- if (typeof parsed.token === "string" && parsed.token) return { headers: {
20
- Authorization: `Bearer ${parsed.token}`,
21
- "Content-Type": "application/json"
22
- } };
23
- } catch {}
24
- return { headers: {
25
- "x-goog-api-key": apiKey,
26
- "Content-Type": "application/json"
27
- } };
28
- }
29
- //#endregion
30
- //#region src/agents/live-auth-keys.ts
31
- const KEY_SPLIT_RE = /[\s,;]+/g;
32
- const GOOGLE_LIVE_SINGLE_KEY = "OPENCLAW_LIVE_GEMINI_KEY";
33
- const PROVIDER_PREFIX_OVERRIDES = {
34
- google: "GEMINI",
35
- "google-vertex": "GEMINI"
36
- };
37
- const PROVIDER_API_KEY_CONFIG = {
38
- anthropic: {
39
- liveSingle: "OPENCLAW_LIVE_ANTHROPIC_KEY",
40
- listVar: "OPENCLAW_LIVE_ANTHROPIC_KEYS",
41
- primaryVar: "ANTHROPIC_API_KEY",
42
- prefixedVar: "ANTHROPIC_API_KEY_"
43
- },
44
- google: {
45
- liveSingle: GOOGLE_LIVE_SINGLE_KEY,
46
- listVar: "GEMINI_API_KEYS",
47
- primaryVar: "GEMINI_API_KEY",
48
- prefixedVar: "GEMINI_API_KEY_"
49
- },
50
- "google-vertex": {
51
- liveSingle: GOOGLE_LIVE_SINGLE_KEY,
52
- listVar: "GEMINI_API_KEYS",
53
- primaryVar: "GEMINI_API_KEY",
54
- prefixedVar: "GEMINI_API_KEY_"
55
- },
56
- openai: {
57
- liveSingle: "OPENCLAW_LIVE_OPENAI_KEY",
58
- listVar: "OPENAI_API_KEYS",
59
- primaryVar: "OPENAI_API_KEY",
60
- prefixedVar: "OPENAI_API_KEY_"
61
- }
62
- };
63
- function parseKeyList(raw) {
64
- if (!raw) return [];
65
- return raw.split(KEY_SPLIT_RE).map((value) => value.trim()).filter(Boolean);
66
- }
67
- function collectEnvPrefixedKeys(prefix) {
68
- const keys = [];
69
- for (const [name, value] of Object.entries(process.env)) {
70
- if (!name.startsWith(prefix)) continue;
71
- const trimmed = value?.trim();
72
- if (!trimmed) continue;
73
- keys.push(trimmed);
74
- }
75
- return keys;
76
- }
77
- function resolveProviderApiKeyConfig(provider) {
78
- const normalized = normalizeProviderId(provider);
79
- const custom = PROVIDER_API_KEY_CONFIG[normalized];
80
- const base = PROVIDER_PREFIX_OVERRIDES[normalized] ?? normalized.toUpperCase().replace(/-/g, "_");
81
- const liveSingle = custom?.liveSingle ?? `OPENCLAW_LIVE_${base}_KEY`;
82
- const listVar = custom?.listVar ?? `${base}_API_KEYS`;
83
- const primaryVar = custom?.primaryVar ?? `${base}_API_KEY`;
84
- const prefixedVar = custom?.prefixedVar ?? `${base}_API_KEY_`;
85
- if (normalized === "google" || normalized === "google-vertex") return {
86
- liveSingle,
87
- listVar,
88
- primaryVar,
89
- prefixedVar,
90
- fallbackVars: ["GOOGLE_API_KEY"]
91
- };
92
- return {
93
- liveSingle,
94
- listVar,
95
- primaryVar,
96
- prefixedVar,
97
- fallbackVars: []
98
- };
99
- }
100
- function collectProviderApiKeys(provider) {
101
- const config = resolveProviderApiKeyConfig(provider);
102
- const forcedSingle = config.liveSingle ? process.env[config.liveSingle]?.trim() : void 0;
103
- if (forcedSingle) return [forcedSingle];
104
- const fromList = parseKeyList(config.listVar ? process.env[config.listVar] : void 0);
105
- const primary = config.primaryVar ? process.env[config.primaryVar]?.trim() : void 0;
106
- const fromPrefixed = config.prefixedVar ? collectEnvPrefixedKeys(config.prefixedVar) : [];
107
- const fallback = config.fallbackVars.map((envVar) => process.env[envVar]?.trim()).filter(Boolean);
108
- const seen = /* @__PURE__ */ new Set();
109
- const add = (value) => {
110
- if (!value) return;
111
- if (seen.has(value)) return;
112
- seen.add(value);
113
- };
114
- for (const value of fromList) add(value);
115
- add(primary);
116
- for (const value of fromPrefixed) add(value);
117
- for (const value of fallback) add(value);
118
- return Array.from(seen);
119
- }
120
- function isApiKeyRateLimitError(message) {
121
- const lower = message.toLowerCase();
122
- if (lower.includes("rate_limit")) return true;
123
- if (lower.includes("rate limit")) return true;
124
- if (lower.includes("429")) return true;
125
- if (lower.includes("quota exceeded") || lower.includes("quota_exceeded")) return true;
126
- if (lower.includes("resource exhausted") || lower.includes("resource_exhausted")) return true;
127
- if (lower.includes("too many requests")) return true;
128
- return false;
129
- }
130
- //#endregion
131
- //#region src/agents/api-key-rotation.ts
132
- function dedupeApiKeys(raw) {
133
- const seen = /* @__PURE__ */ new Set();
134
- const keys = [];
135
- for (const value of raw) {
136
- const apiKey = value.trim();
137
- if (!apiKey || seen.has(apiKey)) continue;
138
- seen.add(apiKey);
139
- keys.push(apiKey);
140
- }
141
- return keys;
142
- }
143
- function collectProviderApiKeysForExecution(params) {
144
- const { primaryApiKey, provider } = params;
145
- return dedupeApiKeys([primaryApiKey?.trim() ?? "", ...collectProviderApiKeys(provider)]);
146
- }
147
- async function executeWithApiKeyRotation(params) {
148
- const keys = dedupeApiKeys(params.apiKeys);
149
- if (keys.length === 0) throw new Error(`No API keys configured for provider "${params.provider}".`);
150
- let lastError;
151
- for (let attempt = 0; attempt < keys.length; attempt += 1) {
152
- const apiKey = keys[attempt];
153
- try {
154
- return await params.execute(apiKey);
155
- } catch (error) {
156
- lastError = error;
157
- const message = formatErrorMessage(error);
158
- if (!(params.shouldRetry ? params.shouldRetry({
159
- apiKey,
160
- error,
161
- attempt,
162
- message
163
- }) : isApiKeyRateLimitError(message)) || attempt + 1 >= keys.length) break;
164
- params.onRetry?.({
165
- apiKey,
166
- error,
167
- attempt,
168
- message
169
- });
170
- }
171
- }
172
- if (lastError === void 0) throw new Error(`Failed to run API request for ${params.provider}.`);
173
- throw lastError;
174
- }
175
- //#endregion
176
- export { executeWithApiKeyRotation as n, parseGeminiAuth as r, collectProviderApiKeysForExecution as t };
@@ -1,51 +0,0 @@
1
- import "./paths-BtVqCdw4.js";
2
- import "./config-B9ODwgpz.js";
3
- import "./paths-eFexkPEh.js";
4
- import "./github-copilot-token-Cxf8QYZb.js";
5
- import { B as shouldLogVerbose, R as logVerbose } from "./logger-D6zRubj0.js";
6
- import "./env-b9k1PHMI.js";
7
- import "./fetch-guard-4UVSZ0uS.js";
8
- import "./local-roots-adnEg9zb.js";
9
- import { i as normalizeMediaAttachments, m as isAudioAttachment, o as resolveMediaAttachmentLocalRoots, t as runAudioTranscription } from "./audio-transcription-runner-CTIHpebA.js";
10
- import "./image-Ch6M4tnJ.js";
11
- import "./api-key-rotation-CimGYMBc.js";
12
- import "./proxy-fetch-CJEmoBxi.js";
13
- //#region src/media-understanding/audio-preflight.ts
14
- /**
15
- * Transcribes the first audio attachment BEFORE mention checking.
16
- * This allows voice notes to be processed in group chats with requireMention: true.
17
- * Returns the transcript or undefined if transcription fails or no audio is found.
18
- */
19
- async function transcribeFirstAudio(params) {
20
- const { ctx, cfg } = params;
21
- const audioConfig = cfg.tools?.media?.audio;
22
- if (!audioConfig || audioConfig.enabled === false) return;
23
- const attachments = normalizeMediaAttachments(ctx);
24
- if (!attachments || attachments.length === 0) return;
25
- const firstAudio = attachments.find((att) => att && isAudioAttachment(att) && !att.alreadyTranscribed);
26
- if (!firstAudio) return;
27
- if (shouldLogVerbose()) logVerbose(`audio-preflight: transcribing attachment ${firstAudio.index} for mention check`);
28
- try {
29
- const { transcript } = await runAudioTranscription({
30
- ctx,
31
- cfg,
32
- attachments,
33
- agentDir: params.agentDir,
34
- providers: params.providers,
35
- activeModel: params.activeModel,
36
- localPathRoots: resolveMediaAttachmentLocalRoots({
37
- cfg,
38
- ctx
39
- })
40
- });
41
- if (!transcript) return;
42
- firstAudio.alreadyTranscribed = true;
43
- if (shouldLogVerbose()) logVerbose(`audio-preflight: transcribed ${transcript.length} chars from attachment ${firstAudio.index}`);
44
- return transcript;
45
- } catch (err) {
46
- if (shouldLogVerbose()) logVerbose(`audio-preflight: transcription failed: ${String(err)}`);
47
- return;
48
- }
49
- }
50
- //#endregion
51
- export { transcribeFirstAudio };