bluebubbles: forward per-group systemPrompt into GroupSystemPrompt#69198
Conversation
Greptile SummaryThis PR adds an optional Confidence Score: 5/5Safe to merge — additive optional config field with no breaking changes and good test coverage. All changes are additive, the implementation faithfully mirrors the Feishu/LINE pattern, four test cases cover the exact-match, wildcard-fallback, priority, and DM-exclusion paths, and the pnpm check suite is reported clean. No files require special attention. Reviews (2): Last reviewed commit: "bluebubbles: honor "*" wildcard fallback..." | Re-trigger Greptile |
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 9ba05e280c
ℹ️ About Codex in GitHub
Codex has been enabled to automatically review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
When you sign up for Codex through ChatGPT, Codex can also answer questions or update the PR, like "@codex address that feedback".
| GroupSystemPrompt: isGroup | ||
| ? normalizeOptionalString(account.config.groups?.[peerId]?.systemPrompt) | ||
| : undefined, |
There was a problem hiding this comment.
Honor '*' fallback for GroupSystemPrompt
GroupSystemPrompt is currently resolved only from account.config.groups?.[peerId], so a default config like channels.bluebubbles.groups["*"].systemPrompt is silently ignored for all group chats. In this same flow, other per-group settings (e.g. requireMention/tools) go through group-policy resolvers that support wildcard fallback, so this introduces inconsistent behavior where operators cannot set one global group prompt and must duplicate the value per group ID.
Useful? React with 👍 / 👎.
|
@greptile review — added '*' wildcard fallback per Codex consistency nit, plus CI allowlist line-number bump. |
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: ef0ba1ebab
ℹ️ About Codex in GitHub
Codex has been enabled to automatically review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
When you sign up for Codex through ChatGPT, Codex can also answer questions or update the PR, like "@codex address that feedback".
| historyLimit: z.number().int().min(0).optional(), | ||
| dmHistoryLimit: z.number().int().min(0).optional(), | ||
| textChunkLimit: z.number().int().positive().optional(), | ||
| sendTimeoutMs: z.number().int().positive().optional(), |
There was a problem hiding this comment.
Remove no-op
sendTimeoutMs config key
Adding sendTimeoutMs to the BlueBubbles schema exposes a user-facing setting that the runtime never consumes, so operators can set channels.bluebubbles(...).sendTimeoutMs and still get the existing hard-coded/per-call timeouts in send/probe paths. This creates a misleading config contract (it validates and appears in generated metadata/docs but has no behavior), which is likely to cause confusing timeout-debugging in production.
Useful? React with 👍 / 👎.
ef0ba1e to
29aae94
Compare
🔒 Aisle Security AnalysisWe found 1 potential security issue(s) in this PR:
1. 🟡 Webhook payload can spoof group identity to select unintended per-group systemPrompt
Description
If an attacker can submit webhook requests with a valid webhook token (e.g., token leakage, proxy/log exposure, or an internal threat), they can craft Key points:
Vulnerable code (new behavior): const peerId = isGroup
? (chatGuid ?? chatIdentifier ?? (chatId ? String(chatId) : "group"))
: message.senderId;
...
GroupSystemPrompt: isGroup
? normalizeOptionalString(
account.config.groups?.[peerId]?.systemPrompt ??
account.config.groups?.["*"]?.systemPrompt,
)
: undefined,RecommendationTreat webhook payload fields ( Recommended mitigations (defense in depth):
Example pattern: import { createHmac, timingSafeEqual } from "node:crypto";
function verifyHmac(rawBody: string, signatureHeader: string, secret: string): boolean {
const expected = createHmac("sha256", secret).update(rawBody).digest("hex");
const got = signatureHeader.replace(/^sha256=/, "");
return expected.length === got.length && timingSafeEqual(Buffer.from(expected), Buffer.from(got));
}
Analyzed PR: #69198 at commit Last updated on: 2026-04-21T02:17:31Z |
…penclaw#69198) Forward per-group systemPrompt config into inbound context GroupSystemPrompt so configured group-specific behavioral instructions (for example threaded-reply and tapback conventions) are injected on every turn. Supports "*" wildcard fallback matching the existing requireMention pattern. Closes openclaw#60665. Co-authored-by: Omar Shahine <omarshahine@users.noreply.github.com>
…penclaw#69198) Forward per-group systemPrompt config into inbound context GroupSystemPrompt so configured group-specific behavioral instructions (for example threaded-reply and tapback conventions) are injected on every turn. Supports "*" wildcard fallback matching the existing requireMention pattern. Closes openclaw#60665. Co-authored-by: Omar Shahine <omarshahine@users.noreply.github.com>
…penclaw#69198) Forward per-group systemPrompt config into inbound context GroupSystemPrompt so configured group-specific behavioral instructions (for example threaded-reply and tapback conventions) are injected on every turn. Supports "*" wildcard fallback matching the existing requireMention pattern. Closes openclaw#60665. Co-authored-by: Omar Shahine <omarshahine@users.noreply.github.com>
…penclaw#69198) Forward per-group systemPrompt config into inbound context GroupSystemPrompt so configured group-specific behavioral instructions (for example threaded-reply and tapback conventions) are injected on every turn. Supports "*" wildcard fallback matching the existing requireMention pattern. Closes openclaw#60665. Co-authored-by: Omar Shahine <omarshahine@users.noreply.github.com>
…penclaw#69198) Forward per-group systemPrompt config into inbound context GroupSystemPrompt so configured group-specific behavioral instructions (for example threaded-reply and tapback conventions) are injected on every turn. Supports "*" wildcard fallback matching the existing requireMention pattern. Closes openclaw#60665. Co-authored-by: Omar Shahine <omarshahine@users.noreply.github.com>
…penclaw#69198) Forward per-group systemPrompt config into inbound context GroupSystemPrompt so configured group-specific behavioral instructions (for example threaded-reply and tapback conventions) are injected on every turn. Supports "*" wildcard fallback matching the existing requireMention pattern. Closes openclaw#60665. Co-authored-by: Omar Shahine <omarshahine@users.noreply.github.com>
…penclaw#69198) Forward per-group systemPrompt config into inbound context GroupSystemPrompt so configured group-specific behavioral instructions (for example threaded-reply and tapback conventions) are injected on every turn. Supports "*" wildcard fallback matching the existing requireMention pattern. Closes openclaw#60665. Co-authored-by: Omar Shahine <omarshahine@users.noreply.github.com>
…penclaw#69198) Forward per-group systemPrompt config into inbound context GroupSystemPrompt so configured group-specific behavioral instructions (for example threaded-reply and tapback conventions) are injected on every turn. Supports "*" wildcard fallback matching the existing requireMention pattern. Closes openclaw#60665. Co-authored-by: Omar Shahine <omarshahine@users.noreply.github.com>
Summary
Add optional
systemPromptto the BlueBubbles per-group config and forward it into inbound context asGroupSystemPrompt, so configured per-group behavioral directives are injected into the agent's system prompt on every turn.BlueBubbles was the only major channel missing this pattern — Discord, Feishu, Google Chat, IRC, LINE, Matrix, Nextcloud-Talk, Slack, and Telegram already wire
GroupSystemPromptintosessionCtxvia the core resolver atsrc/auto-reply/reply/get-reply-run.ts:289. This PR is a scoped BB-only implementation that matches the existing Feishu shape (extensions/feishu/src/bot.ts:1023).Why this matters
Operators can now set per-group rules via config alone, without agent-side workarounds. A motivating use case documented in the new docs section: with BlueBubbles Private API enabled, inbound messages carry
[[reply_to:N]]short IDs and the agent hasaction=replyandaction=reacttools available. A per-groupsystemPromptis the reliable way to keep the agent consistently using threaded replies and tapback reactions instead of dropping plain-text new messages.Change shape
extensions/bluebubbles/src/config-schema.tssystemPrompt: z.string().optional()onbluebubblesGroupConfigSchemaextensions/bluebubbles/src/types.tsBlueBubblesGroupConfigextensions/bluebubbles/src/monitor-processing.tsGroupSystemPrompt: isGroup ? normalizeOptionalString(account.config.groups?.[peerId]?.systemPrompt) : undefinedonfinalizeInboundContextextensions/bluebubbles/src/monitor.test.tsdocs/channels/bluebubbles.mddocs/.generated/config-baseline.sha256pnpm config:docs:genNo plugin-sdk surface change; no other channel touched. Core extension-agnostic boundary preserved.
Change Type
Scope
Linked Issue
User-visible / Behavior Changes
channels.bluebubbles.accounts.<name>.groups.<peerId>.systemPrompt: string.Security Impact
None. The value is injected only into the agent's own system prompt (trusted config surface), not into any model-facing untrusted context. No new network, filesystem, or auth surface.
Rollback
Revert this commit. No config migration; the new field is additive and optional.
Test plan
pnpm test extensions/bluebubbles/src/monitor.test.ts— 72/72 pass, including two new assertionspnpm check— tsgo (core + core:test + extensions + extensions:test), oxlint, webhook/auth/scope checks, import-cycle + madge all greenpnpm config:docs:check— schema baseline hash stable after regenChangelog entry intentionally omitted here; will be added during
/landpr.