openclaw - ✅(Solved) Fix /skill command not transformed when no model aliases are configured [1 pull requests, 1 participants]

Official PRs (…)
ON THIS PAGE

Recommended Tools

×6

Utilities matched from this issue’s tags and category — try them while you read without losing context.

GitHub issue graph ai analysis

Paste a GitHub issue URL. We fetch that issue, discover linked issues from bodies/comments/timeline, collect linked pull requests, and produce a structured English report.

The report is written in English Markdown for sharing and archival.

Helpful · Quick feedback

Loading…
GitHub stats
openclaw/openclaw#56188Fetched 2026-04-08 01:43:53
View on GitHub
Comments
0
Participants
1
Timeline
2
Reactions
0
Participants
Timeline (top)
cross-referenced ×1referenced ×1

Root Cause

Two issues in pi-embedded-BaSvmUpW.js:

Issue 1 — In resolveReplyDirectives, skill commands are only loaded when model aliases exist:

```javascript const rawAliases = Object.values(cfg.agents?.defaults?.models ?? {}) .map(entry => entry.alias?.trim()).filter(Boolean)...;

const skillCommands = allowTextCommands && commandTextHasSlash && rawAliases.length > 0 // ← gate ? (await loadSkillCommands()).listSkillCommandsForWorkspace({...}) : []; // returns [] when no aliases configured ```

Issue 2 — In handleInlineActions, the fallback fresh-load is never reached because [] (empty array) is truthy in JavaScript:

```javascript const skillCommands = shouldLoadSkillCommands && params.skillCommands // [] is truthy! ? params.skillCommands // ← returns [], skips fresh load : shouldLoadSkillCommands ? freshLoad // ← never reached when params.skillCommands = [] : []; ```

Fix Action

Fixed

PR fix notes

PR #56196: fix(skills): load skill commands regardless of model alias configuration

Description (problem / solution / changelog)

Summary

Fixes #56188

/skill <name> <input> was silently skipped (passed as raw text to the agent) when no model aliases were configured in cfg.agents.defaults.models.*.alias.

Root Cause

Two issues in the skill command resolution pipeline:

  1. resolveReplyDirectives (src/auto-reply/reply/get-reply-directives.ts): Skill commands were only loaded when rawAliases.length > 0, meaning they were never loaded (and never passed downstream) when no model aliases existed.

  2. handleInlineActions (src/auto-reply/reply/get-reply-inline-actions.ts): The fallback fresh-load of skill commands was unreachable because params.skillCommands (an empty [] from issue 1) is truthy in JavaScript, so the ternary always took the first branch returning [] instead of falling through to the fresh-load path.

Fix

  1. Remove the rawAliases.length > 0 gate from skill command loading in resolveReplyDirectives — skill commands should be loaded whenever the message contains a slash and text commands are allowed, regardless of model alias configuration.

  2. Change the truthy check params.skillCommands to params.skillCommands.length > 0 in handleInlineActions so that an empty upstream array correctly falls through to the fresh-load path.

Test

Added a test case verifying that when skillCommands is passed as an empty array (simulating the no-model-aliases scenario), handleInlineActions falls back to loading skill commands fresh and correctly rewrites the /skill command body.

Verification

  • pnpm test -- src/auto-reply/reply/get-reply-inline-actions.skip-when-config-empty.test.ts — 6/6 pass
  • pnpm check — only pre-existing type errors in unrelated files (channels.status.test.ts, typing-lease.test-support.ts)

Changed files

  • src/auto-reply/reply/get-reply-directives.ts (modified, +6/-3)
  • src/auto-reply/reply/get-reply-inline-actions.skip-when-config-empty.test.ts (modified, +54/-0)
  • src/auto-reply/reply/get-reply-inline-actions.ts (modified, +1/-1)

Code Example

Use the "<name>" skill for this request.

User input:
<input>
RAW_BUFFERClick to expand / collapse

Describe the bug

When a user sends /skill <name> <input>, the message body should be transformed into the skill-injection format before being passed to the agent:

Use the "<name>" skill for this request.

User input:
<input>

However, this transformation is silently skipped when no model aliases are configured in cfg.agents.defaults.models.*.alias. The raw /skill <name> <input> text is passed to the agent as-is.

Root cause

Two issues in pi-embedded-BaSvmUpW.js:

Issue 1 — In resolveReplyDirectives, skill commands are only loaded when model aliases exist:

```javascript const rawAliases = Object.values(cfg.agents?.defaults?.models ?? {}) .map(entry => entry.alias?.trim()).filter(Boolean)...;

const skillCommands = allowTextCommands && commandTextHasSlash && rawAliases.length > 0 // ← gate ? (await loadSkillCommands()).listSkillCommandsForWorkspace({...}) : []; // returns [] when no aliases configured ```

Issue 2 — In handleInlineActions, the fallback fresh-load is never reached because [] (empty array) is truthy in JavaScript:

```javascript const skillCommands = shouldLoadSkillCommands && params.skillCommands // [] is truthy! ? params.skillCommands // ← returns [], skips fresh load : shouldLoadSkillCommands ? freshLoad // ← never reached when params.skillCommands = [] : []; ```

Expected behavior

/skill <name> <input> should be transformed into the skill-injection format regardless of whether model aliases are configured.

Suggested fix

```javascript // Change: shouldLoadSkillCommands && params.skillCommands ? // To: shouldLoadSkillCommands && params.skillCommands?.length > 0 ? ```

This allows handleInlineActions to fall back to loading skill commands fresh when the upstream resolveReplyDirectives returned an empty array due to missing model aliases.

Additional context

Observed via session file inspection: the same /skill command produced two different message bodies depending on whether model aliases were configured in the agent — one with the raw command text, one correctly transformed.

extent analysis

Fix Plan

To fix the issue, we need to modify the handleInlineActions function to correctly handle the case when params.skillCommands is an empty array. We can do this by changing the condition to check for the length of params.skillCommands.

  • Modify the handleInlineActions function as follows:
const skillCommands = shouldLoadSkillCommands && params.skillCommands?.length > 0
  ? params.skillCommands
  : shouldLoadSkillCommands
    ? freshLoad
    : [];

Additionally, we should also modify the resolveReplyDirectives function to load skill commands even when no model aliases are configured:

const skillCommands = allowTextCommands && commandTextHasSlash
  ? (await loadSkillCommands()).listSkillCommandsForWorkspace({...})
  : [];

Remove the condition rawAliases.length > 0 to ensure that skill commands are loaded regardless of whether model aliases are configured.

Verification

To verify that the fix worked, you can test the /skill <name> <input> command with and without model aliases configured. The message body should be transformed into the skill-injection format in both cases.

Extra Tips

  • Make sure to test the fix thoroughly to ensure that it does not introduce any new issues.
  • Consider adding additional logging or debugging statements to help identify any future issues related to skill commands or model aliases.

Vote matrix · Quick signals

Works
Did the solution work? Tap to confirm.
Easy Fix
Was it a quick fix?
Time Saver
Did it save you time?
Blocking
Was it severely blocking?
Common Issue
Are others likely hitting this too?
Flaky / Intermittent
Is it intermittent?
Verified / Reproducible
Can you reproduce it reliably?
Loading…

FAQ

Expected behavior

/skill <name> <input> should be transformed into the skill-injection format regardless of whether model aliases are configured.

Still need to ship something?

×6

Another batch ranked right after the header list — different links, same matching logic.

Back to top recommendations

TRENDING