Skip to content

Discord: reconcile native commands without restart churn#46597

Merged
huntharo merged 5 commits into
openclaw:mainfrom
huntharo:codex/discord-command-reconcile
Mar 20, 2026
Merged

Discord: reconcile native commands without restart churn#46597
huntharo merged 5 commits into
openclaw:mainfrom
huntharo:codex/discord-command-reconcile

Conversation

@huntharo

@huntharo huntharo commented Mar 14, 2026

Copy link
Copy Markdown
Member

Summary

Describe the problem and fix in 2–5 bullets:

  • Problem: this branch was carrying a local Discord command reconcile implementation because upstream Carbon did not have it yet.
  • Why it matters: now that Carbon beta has built-in global command reconciliation, keeping our own copy would be duplicate logic and duplicate tests around library behavior we no longer own.
  • What changed: I bumped @buape/carbon to the beta that adds built-in reconcile, removed the local OpenClaw reconcile implementation, and switched the Discord provider to configure Carbon with commandDeploymentMode: "reconcile".
  • What did NOT change (scope boundary): I did not try to recreate Carbon’s internal diff logic in OpenClaw tests. The remaining tests now cover our integration points only: that we configure Carbon correctly and pass it the right command set.

Change Type (select all)

  • Bug fix
  • Feature
  • Refactor
  • Docs
  • Security hardening
  • Chore/infra

Scope (select all touched areas)

  • Gateway / orchestration
  • Skills / tool execution
  • Auth / tokens
  • Memory / storage
  • Integrations
  • API / contracts
  • UI / DX
  • CI/CD / infra

Linked Issue/PR

User-visible / Behavior Changes

  • OpenClaw now uses Carbon’s built-in Discord native command reconcile behavior instead of a local OpenClaw implementation.
  • The Discord provider now configures Carbon with commandDeploymentMode: "reconcile".
  • The local native-command-state reconcile module and its tests are gone.
  • The provider-level behavior stays the same at a high level: Discord command deployment defaults to reconcile instead of blind overwrite.

Security Impact (required)

  • New permissions/capabilities? (Yes/No) No
  • Secrets/tokens handling changed? (Yes/No) No
  • New/changed network calls? (Yes/No) No
  • Command/tool execution surface changed? (Yes/No) No
  • Data access scope changed? (Yes/No) No
  • If any Yes, explain risk + mitigation:

Repro + Verification

Environment

  • OS: macOS
  • Runtime/container: local repo tests
  • Model/provider: N/A
  • Integration/channel (if any): Discord
  • Relevant config (redacted): none

Steps

  1. Install the upstream Carbon beta:
    • pnpm -w install @buape/carbon@beta
  2. Remove the local OpenClaw reconcile implementation and switch the provider to Carbon’s built-in reconcile mode.
  3. Run the focused Discord tests and repo checks.

Expected

  • OpenClaw should no longer own a duplicate reconcile implementation.
  • The Discord provider should configure Carbon reconcile by default.
  • Provider tests should validate OpenClaw’s integration points, not Carbon’s internal diff logic.

Actual

  • Carbon beta now contains its own reconcileGlobalCommands() implementation.
  • OpenClaw now sets commandDeploymentMode: "reconcile" on the Carbon client and uses the normal Carbon deploy path.
  • The local reconcile module/tests were removed, and the remaining tests now verify our provider wiring instead of mocking library internals and pretending to test reconcile behavior we no longer own.

Evidence

  • Failing test/log before + passing after
  • Trace/log snippets
  • Screenshot/recording
  • Perf numbers (if relevant)

Discord’s docs and maintainer guidance still justify why reconcile is the right deployment mode:

There is a global rate limit of 200 application command creates per day, per guild

Source: https://docs.discord.com/developers/interactions/application-commands#making-a-global-command

this should not be an issue unless you are doing something you shouldn't, such as constantly deleting and re-creating many commands.

Source: discord/discord-api-docs#4868 (comment)

The important change in this revision is ownership, not the end behavior:

  • before: OpenClaw implemented its own reconcile logic in extensions/discord/src/monitor/native-command-state.ts
  • after: Carbon beta owns that logic, and OpenClaw only configures and calls into it

Human Verification (required)

What you personally verified (not just CI), and how:

  • Verified scenarios:
    • I installed @buape/carbon@beta.
    • I verified the installed Carbon beta now contains Client.reconcileGlobalCommands() and commandDeploymentMode: "reconcile" in its built output.
    • I removed the local OpenClaw reconcile module and switched the Discord provider to rely on Carbon’s deployment mode.
    • I verified the provider tests now cover our integration layer instead of a mocked copy of reconcile internals.
  • Edge cases checked:
    • the provider still handles Discord create-quota errors at startup
    • plugin commands are still included in the constructed Discord command list
    • the managed /vc command is still included in the constructed Discord command list
  • What you did not verify:
    • I did not claim that OpenClaw’s remaining tests prove Carbon’s internal reconcile diff algorithm. That logic now lives in the dependency, so our local suite should not pretend to cover it.

Review Conversations

  • I replied to or resolved every bot review conversation I addressed in this PR.
  • I left unresolved only the conversations that still need reviewer or maintainer judgment.

If a bot review conversation is addressed by this PR, resolve that conversation yourself. Do not leave bot review conversation cleanup for maintainers.

Compatibility / Migration

  • Backward compatible? (Yes/No) Yes
  • Config/env changes? (Yes/No) No
  • Migration needed? (Yes/No) No
  • If yes, exact upgrade steps:
    • pnpm install

Failure Recovery (if this breaks)

  • How to disable/revert this change quickly:
    • revert this PR, which restores the previous local implementation and prior Carbon version
  • Files/config to restore:
    • package.json
    • pnpm-lock.yaml
    • extensions/discord/src/monitor/provider.ts
  • Known bad symptoms reviewers should watch for:
    • Discord command deploy behavior regressing after the Carbon beta bump
    • provider tests passing while real Discord startup behavior diverges from what Carbon now owns

Risks and Mitigations

  • Risk: Carbon’s reconcile internals are now a dependency concern rather than local OpenClaw code.
    • Mitigation: this PR removes the local duplicate implementation and keeps only provider-level coverage that we actually own.
  • Risk: the beta dependency could have unrelated behavior changes outside command reconcile.
    • Mitigation: I limited the local test focus to Discord provider wiring and kept the change surface narrow around the provider and dependency bump.

@openclaw-barnacle openclaw-barnacle Bot added channel: discord Channel integration: discord size: XL maintainer Maintainer-authored PR labels Mar 14, 2026
@greptile-apps

greptile-apps Bot commented Mar 14, 2026

Copy link
Copy Markdown
Contributor

Greptile Summary

This PR adds an opt-in Discord native command reconcile mode (channels.discord.commands.reconcileOnStartup) that replaces the full bulk-overwrite deploy with a targeted diff: it fetches live commands, compares them against the desired set by a SHA-256 hash of the normalised command body, then issues only the individual deletes, patches, and creates needed to converge. The default bulk-deploy path is unchanged. The feature is well-tested and the hash normalisation carefully strips Discord response-only fields and Carbon serialisation quirks to avoid false drift.

  • leftAlone in DiscordNativeCommandReconcileSummary is initialised to 0 and never incremented; it appears in both summary log lines but carries no signal, and should either be removed or documented.
  • savedCount in DiscordNativeCommandReconcileResult is always hardcoded to 0 on both return paths; it looks like a field carried over from the bulk-deploy result shape that is not meaningful in reconcile mode.
  • The reconcileDiscordNativeCommandsMock in provider.test.ts omits the validated field (required by DiscordNativeCommandReconcileSummary) in both mock initialisations, creating a type inconsistency that would silently return undefined if that field is ever asserted on.

Confidence Score: 4/5

  • Safe to merge; the feature is opt-in behind a config flag and the existing bulk-deploy path is untouched
  • The reconcile logic is sound, well-tested, and correctly falls back to the legacy path for guild-scoped commands. The only issues are minor: a dead leftAlone counter, a vestigial savedCount: 0, and a missing validated field in test mocks. None affect runtime behaviour of the default path or the new reconcile path.
  • No files require special attention; all issues are non-critical style/test quality improvements.
Prompt To Fix All With AI
This is a comment left during a code review.
Path: extensions/discord/src/monitor/native-command-state.ts
Line: 228-251

Comment:
**`leftAlone` counter is never incremented**

The `leftAlone` field is declared in `DiscordNativeCommandReconcileSummary` and is printed in both summary log lines, but it is initialized to `0` and never incremented anywhere in the function. In the current design every live command is either validated (matched by name) or scheduled for deletion — there are no commands that get "left alone" — so the counter will always be `0`. This makes the field appear in logs (`leftAlone=0`) without carrying any signal, which could confuse future readers.

Consider either removing `leftAlone` from the type and the two log strings, or adding a comment that clearly explains its intended purpose (e.g., for a future mode where commands from other applications are deliberately preserved).

How can I resolve this? If you propose a fix, please make it concise.

---

This is a comment left during a code review.
Path: extensions/discord/src/monitor/provider.test.ts
Line: 84-95

Comment:
**Mock is missing the `validated` field from `DiscordNativeCommandReconcileSummary`**

The `summary` object in the initial mock return (and again in the `mockResolvedValue` call around line 457) omits the `validated: number` field that is required by `DiscordNativeCommandReconcileSummary`. If TypeScript's strict return-type inference tightens, or if any downstream assertion ever checks `summary.validated`, the mock will silently return `undefined` instead of a number.

The same omission appears a second time in the `mockResolvedValue` call:

`extensions/discord/src/monitor/provider.test.ts:457`

```suggestion
    reconcileDiscordNativeCommandsMock: vi.fn(async () => ({
      mode: "reconcile",
      liveCount: 0,
      savedCount: 0,
      summary: {
        validated: 0,
        unchanged: 0,
        created: 0,
        updated: 0,
        deleted: 0,
        leftAlone: 0,
      },
    })),
```

How can I resolve this? If you propose a fix, please make it concise.

---

This is a comment left during a code review.
Path: extensions/discord/src/monitor/native-command-state.ts
Line: 37-42

Comment:
**`savedCount` is always hardcoded to `0`**

Both return sites in `reconcileDiscordNativeCommands` set `savedCount: 0`. The field is present in `DiscordNativeCommandReconcileResult` and is referenced in the test mock, but it is never meaningfully populated — unlike the `summary` object, which carries the actual counts. If `savedCount` is genuinely unused in reconcile mode (e.g., it was carried over from the bulk deploy result shape), removing it from this return type would prevent confusion about what it is supposed to represent.

How can I resolve this? If you propose a fix, please make it concise.

Last reviewed commit: 979f499

Comment on lines +228 to +251
const summary: DiscordNativeCommandReconcileSummary = {
validated: 0,
unchanged: 0,
created: 0,
updated: 0,
deleted: 0,
leftAlone: 0,
};

for (const desired of desiredCommands) {
const live = liveByName.get(desired.name);
if (live) {
if (live.signatureHash === desired.signatureHash) {
summary.validated += 1;
summary.unchanged += 1;
continue;
}
summary.validated += 1;
summary.updated += 1;
continue;
}

summary.created += 1;
}

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

leftAlone counter is never incremented

The leftAlone field is declared in DiscordNativeCommandReconcileSummary and is printed in both summary log lines, but it is initialized to 0 and never incremented anywhere in the function. In the current design every live command is either validated (matched by name) or scheduled for deletion — there are no commands that get "left alone" — so the counter will always be 0. This makes the field appear in logs (leftAlone=0) without carrying any signal, which could confuse future readers.

Consider either removing leftAlone from the type and the two log strings, or adding a comment that clearly explains its intended purpose (e.g., for a future mode where commands from other applications are deliberately preserved).

Prompt To Fix With AI
This is a comment left during a code review.
Path: extensions/discord/src/monitor/native-command-state.ts
Line: 228-251

Comment:
**`leftAlone` counter is never incremented**

The `leftAlone` field is declared in `DiscordNativeCommandReconcileSummary` and is printed in both summary log lines, but it is initialized to `0` and never incremented anywhere in the function. In the current design every live command is either validated (matched by name) or scheduled for deletion — there are no commands that get "left alone" — so the counter will always be `0`. This makes the field appear in logs (`leftAlone=0`) without carrying any signal, which could confuse future readers.

Consider either removing `leftAlone` from the type and the two log strings, or adding a comment that clearly explains its intended purpose (e.g., for a future mode where commands from other applications are deliberately preserved).

How can I resolve this? If you propose a fix, please make it concise.

Comment on lines +84 to +95
reconcileDiscordNativeCommandsMock: vi.fn(async () => ({
mode: "reconcile",
liveCount: 0,
savedCount: 0,
summary: {
unchanged: 0,
created: 0,
updated: 0,
deleted: 0,
leftAlone: 0,
},
})),

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Mock is missing the validated field from DiscordNativeCommandReconcileSummary

The summary object in the initial mock return (and again in the mockResolvedValue call around line 457) omits the validated: number field that is required by DiscordNativeCommandReconcileSummary. If TypeScript's strict return-type inference tightens, or if any downstream assertion ever checks summary.validated, the mock will silently return undefined instead of a number.

The same omission appears a second time in the mockResolvedValue call:

extensions/discord/src/monitor/provider.test.ts:457

Suggested change
reconcileDiscordNativeCommandsMock: vi.fn(async () => ({
mode: "reconcile",
liveCount: 0,
savedCount: 0,
summary: {
unchanged: 0,
created: 0,
updated: 0,
deleted: 0,
leftAlone: 0,
},
})),
reconcileDiscordNativeCommandsMock: vi.fn(async () => ({
mode: "reconcile",
liveCount: 0,
savedCount: 0,
summary: {
validated: 0,
unchanged: 0,
created: 0,
updated: 0,
deleted: 0,
leftAlone: 0,
},
})),
Prompt To Fix With AI
This is a comment left during a code review.
Path: extensions/discord/src/monitor/provider.test.ts
Line: 84-95

Comment:
**Mock is missing the `validated` field from `DiscordNativeCommandReconcileSummary`**

The `summary` object in the initial mock return (and again in the `mockResolvedValue` call around line 457) omits the `validated: number` field that is required by `DiscordNativeCommandReconcileSummary`. If TypeScript's strict return-type inference tightens, or if any downstream assertion ever checks `summary.validated`, the mock will silently return `undefined` instead of a number.

The same omission appears a second time in the `mockResolvedValue` call:

`extensions/discord/src/monitor/provider.test.ts:457`

```suggestion
    reconcileDiscordNativeCommandsMock: vi.fn(async () => ({
      mode: "reconcile",
      liveCount: 0,
      savedCount: 0,
      summary: {
        validated: 0,
        unchanged: 0,
        created: 0,
        updated: 0,
        deleted: 0,
        leftAlone: 0,
      },
    })),
```

How can I resolve this? If you propose a fix, please make it concise.

Comment on lines +37 to +42
export type DiscordNativeCommandReconcileResult = {
mode: "reconcile";
liveCount: number;
savedCount: number;
summary: DiscordNativeCommandReconcileSummary;
};

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

savedCount is always hardcoded to 0

Both return sites in reconcileDiscordNativeCommands set savedCount: 0. The field is present in DiscordNativeCommandReconcileResult and is referenced in the test mock, but it is never meaningfully populated — unlike the summary object, which carries the actual counts. If savedCount is genuinely unused in reconcile mode (e.g., it was carried over from the bulk deploy result shape), removing it from this return type would prevent confusion about what it is supposed to represent.

Prompt To Fix With AI
This is a comment left during a code review.
Path: extensions/discord/src/monitor/native-command-state.ts
Line: 37-42

Comment:
**`savedCount` is always hardcoded to `0`**

Both return sites in `reconcileDiscordNativeCommands` set `savedCount: 0`. The field is present in `DiscordNativeCommandReconcileResult` and is referenced in the test mock, but it is never meaningfully populated — unlike the `summary` object, which carries the actual counts. If `savedCount` is genuinely unused in reconcile mode (e.g., it was carried over from the bulk deploy result shape), removing it from this return type would prevent confusion about what it is supposed to represent.

How can I resolve this? If you propose a fix, please make it concise.

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 979f499917

ℹ️ About Codex in GitHub

Your team has set up Codex to 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 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment on lines +294 to +296
for (const live of deletedLiveCommands) {
await params.client.rest.delete(Routes.applicationCommand(params.applicationId, live.id));
}

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1 Badge Create missing commands before deleting live commands

reconcileDiscordNativeCommands deletes stale commands first (extensions/discord/src/monitor/native-command-state.ts:294-296) and only creates missing commands later, so a Discord 30034 create-limit error during the create loop can leave the app with commands removed but not replaced. Because runDiscordNativeCommandSyncOperation treats that error as a skipped sync (extensions/discord/src/monitor/provider.ts:310-317) rather than rolling back, this can silently degrade command availability for the rest of the quota window whenever reconcile needs at least one create.

Useful? React with 👍 / 👎.

Comment on lines +217 to +218
const liveByName = new Map(liveCommands.map((command) => [command.name, command]));
const deletedLiveCommands = liveCommands.filter((command) => !desiredByName.has(command.name));

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Match live commands by type as well as name

The reconcile diff keys live/desired commands by lowercase name only (liveByName / deletedLiveCommands), but Routes.applicationCommands returns all command types for the application. In environments that also register non-chat-input commands (user/message context commands), this logic will classify them as extras and delete them, or match the wrong command when names collide across types. Filter to chat-input commands (or include type in the identity key) before diffing.

Useful? React with 👍 / 👎.

@huntharo huntharo self-assigned this Mar 14, 2026
@openclaw-barnacle openclaw-barnacle Bot added docs Improvements or additions to documentation gateway Gateway runtime labels Mar 14, 2026
@huntharo
huntharo force-pushed the codex/discord-command-reconcile branch from 31995c9 to 02d50ae Compare March 14, 2026 22:26
@openclaw-barnacle openclaw-barnacle Bot removed docs Improvements or additions to documentation gateway Gateway runtime labels Mar 14, 2026
@huntharo
huntharo force-pushed the codex/discord-command-reconcile branch from 02d50ae to 62d7184 Compare March 15, 2026 00:18
@huntharo

Copy link
Copy Markdown
Member Author

Talked to @steipete - He suggested to ship this without the config option - just make the default. Hopefully we can get this into Carbon soon and then remove our detailed functionality. @thewilloftheshadow - thoughts?

@thewilloftheshadow

Copy link
Copy Markdown
Member

Sounds good to me

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 36226959a2

ℹ️ About Codex in GitHub

Your team has set up Codex to 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 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment on lines +221 to +223
const liveByName = new Map(liveCommands.map((command) => [command.name, command]));
const deletedLiveCommands = liveCommands.filter((command) => !desiredByName.has(command.name));
const updatedCommands = desiredCommands.flatMap((desired) => {

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Include command type in reconcile identity key

The reconcile diff currently keys both live and desired commands only by lowercase name, so any non-chat-input application command returned by Routes.applicationCommands(...) can be treated as an extra and deleted, or incorrectly matched when names collide across command types. This affects bots that also register user/message context commands (or other non-chat command types) under the same application, because the map/indexing logic at this point does not preserve type as part of identity.

Useful? React with 👍 / 👎.

Comment on lines +298 to +300
for (const live of deletedLiveCommands) {
await params.client.rest.delete(Routes.applicationCommand(params.applicationId, live.id));
}

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1 Badge Create replacements before deleting live commands

Reconcile deletes stale commands before it attempts any creates, so if a later create hits Discord's daily create limit (30034) or another create-time failure, command availability is reduced and not restored in that run. Fresh evidence in this commit is that the delete loop executes first here, while runDiscordNativeCommandSyncOperation in extensions/discord/src/monitor/provider.ts treats 30034 as a skipped sync instead of rolling back, which can leave previously working commands removed for the remainder of the quota window.

Useful? React with 👍 / 👎.

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 028eb10e9c

ℹ️ About Codex in GitHub

Your team has set up Codex to 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 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread package.json Outdated
@@ -615,7 +615,7 @@
"dependencies": {
"@agentclientprotocol/sdk": "0.16.1",
"@aws-sdk/client-bedrock": "^3.1009.0",
"@buape/carbon": "0.0.0-beta-20260216184201",
"@buape/carbon": "0.0.0-beta-20260317045421",

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1 Badge Revert unapproved Carbon dependency bump

This change upgrades @buape/carbon, but the repository guideline in AGENTS.md explicitly states "Never update the Carbon dependency." Because this project treats Carbon changes as a restricted surface, updating it here introduces externally owned Discord behavior changes without the required explicit approval path and should be reverted (or moved to an approved, owner-driven update).

Useful? React with 👍 / 👎.

@huntharo
huntharo force-pushed the codex/discord-command-reconcile branch from 028eb10 to 10cf07e Compare March 20, 2026 00:34
@huntharo
huntharo merged commit f1ce679 into openclaw:main Mar 20, 2026
38 of 42 checks passed
@huntharo

Copy link
Copy Markdown
Member Author

Merged via squash.

Thanks @huntharo!

veryoung pushed a commit to veryoung/openclaw that referenced this pull request Mar 20, 2026
)

Merged via squash.

Prepared head SHA: 37090da
Co-authored-by: huntharo <[email protected]>
Reviewed-by: @huntharo
yinuotxie pushed a commit to yinuotxie/openclaw that referenced this pull request Mar 20, 2026
)

Merged via squash.

Prepared head SHA: 37090da
Co-authored-by: huntharo <[email protected]>
Reviewed-by: @huntharo
fuller-stack-dev pushed a commit to fuller-stack-dev/openclaw that referenced this pull request Mar 20, 2026
)

Merged via squash.

Prepared head SHA: 37090da
Co-authored-by: huntharo <[email protected]>
Reviewed-by: @huntharo
fuller-stack-dev pushed a commit to fuller-stack-dev/openclaw that referenced this pull request Mar 20, 2026
)

Merged via squash.

Prepared head SHA: 37090da
Co-authored-by: huntharo <[email protected]>
Reviewed-by: @huntharo
frankekn pushed a commit to artwalker/openclaw that referenced this pull request Mar 23, 2026
)

Merged via squash.

Prepared head SHA: 37090da
Co-authored-by: huntharo <[email protected]>
Reviewed-by: @huntharo
lovewanwan pushed a commit to lovewanwan/openclaw that referenced this pull request Apr 28, 2026
)

Merged via squash.

Prepared head SHA: 37090da
Co-authored-by: huntharo <[email protected]>
Reviewed-by: @huntharo
ogt-redknie pushed a commit to ogt-redknie/OPENX that referenced this pull request May 2, 2026
)

Merged via squash.

Prepared head SHA: 37090da
Co-authored-by: huntharo <[email protected]>
Reviewed-by: @huntharo
github-actions Bot pushed a commit to Desicool/openclaw that referenced this pull request May 9, 2026
)

Merged via squash.

Prepared head SHA: 37090da
Co-authored-by: huntharo <[email protected]>
Reviewed-by: @huntharo
github-actions Bot pushed a commit to Desicool/openclaw that referenced this pull request May 24, 2026
)

Merged via squash.

Prepared head SHA: 37090da
Co-authored-by: huntharo <[email protected]>
Reviewed-by: @huntharo
Nachx639 pushed a commit to Nachx639/clawdbot that referenced this pull request Jun 17, 2026
)

Merged via squash.

Prepared head SHA: 37090da
Co-authored-by: huntharo <[email protected]>
Reviewed-by: @huntharo
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

channel: discord Channel integration: discord maintainer Maintainer-authored PR size: XS

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants