Skip to content

fix: add Trae command adapter for slash commands support#1193

Open
studyzy wants to merge 1 commit into
Fission-AI:mainfrom
studyzy:fix/trae_commands
Open

fix: add Trae command adapter for slash commands support#1193
studyzy wants to merge 1 commit into
Fission-AI:mainfrom
studyzy:fix/trae_commands

Conversation

@studyzy

@studyzy studyzy commented Jun 10, 2026

Copy link
Copy Markdown

Summary

Fixes a bug where openspec init --tools trae did not generate any commands because the Trae adapter was never registered in CommandAdapterRegistry.init().

Changes

  • src/core/command-generation/adapters/trae.ts (new): Trae command adapter. Writes to .trae/commands/opsx/<id>.md with bare command ID as the name field (per Trae convention).
  • src/core/command-generation/adapters/index.ts: Export traeAdapter.
  • src/core/command-generation/registry.ts: Register traeAdapter in CommandAdapterRegistry.init().

Root Cause

The adapter file and export were missing entirely — CommandAdapterRegistry.init() had no entry for Trae, so the tool was silently skipped during init.

Testing

All existing tests pass (npm test). The test/core/command-generation/adapters.test.ts suite (92 tests) covers adapter formatting and confirms the fix works correctly.

Summary by CodeRabbit

  • New Features
    • Added support for Trae command generation with structured markdown formatting, including metadata and command documentation in YAML frontmatter.

Adds a command adapter for Trae so that 'openspec init --tools trae'
generates commands in .trae/commands/opsx/ directory.

Per Trae's convention, the command name uses the bare ID (e.g., 'apply')
instead of the prefixed format used by Claude (e.g., 'OPSX: Apply').

Fixes missing Trae adapter registration in CommandAdapterRegistry.init().
@studyzy studyzy requested a review from TabishB as a code owner June 10, 2026 02:19
@coderabbitai

coderabbitai Bot commented Jun 10, 2026

Copy link
Copy Markdown
Contributor

Review Change Stack

📝 Walkthrough

Walkthrough

A new TypeScript adapter module for Trae command generation is introduced and integrated into the command adapter registry. The implementation defines file paths under .trae/commands/opsx/ and formats commands with YAML frontmatter containing name and description fields.

Changes

Trae Adapter Integration

Layer / File(s) Summary
Trae adapter implementation and registration
src/core/command-generation/adapters/trae.ts, src/core/command-generation/adapters/index.ts, src/core/command-generation/registry.ts
traeAdapter implements ToolCommandAdapter with tool ID 'trae', generates .trae/commands/opsx/<commandId>.md file paths, and formats markdown with YAML frontmatter (name from content.id and description from content.description) followed by content.body. The adapter is exported and registered in the CommandAdapterRegistry at startup.

Estimated code review effort

🎯 1 (Trivial) | ⏱️ ~3 minutes

Suggested reviewers

  • TabishB
  • alfred-openspec

Poem

A new Trae adapter hops into place,
With YAML frontmatter and markdown grace,
Filed beneath .opsx in neat array,
The registry welcomes it right away,
One command tool closer to hooray! 🐰✨

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title directly and accurately describes the main change: adding a Trae command adapter to enable slash commands support, which fixes the root cause identified in the PR objectives.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

@coderabbitai coderabbitai 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.

Actionable comments posted: 1

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@src/core/command-generation/adapters/trae.ts`:
- Around line 23-31: formatFile in adapters/trae.ts injects content.id and
content.description directly into YAML frontmatter causing invalid YAML when
values contain special characters; update formatFile to use the same
escapeYamlValue utility used by sibling adapters (e.g., claude.ts, cursor.ts) to
sanitize both the name and description before interpolation. Locate the
formatFile method and replace direct interpolation of content.id and
content.description with escaped values (call escapeYamlValue(content.id) and
escapeYamlValue(content.description)), ensuring description remains quoted in
the frontmatter as in other adapters.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: 994aa242-f91e-4b26-80ad-06f65cd96244

📥 Commits

Reviewing files that changed from the base of the PR and between 1b06fdd and 8453821.

📒 Files selected for processing (3)
  • src/core/command-generation/adapters/index.ts
  • src/core/command-generation/adapters/trae.ts
  • src/core/command-generation/registry.ts

Comment on lines +23 to +31
formatFile(content: CommandContent): string {
return `---
name: ${content.id}
description: "${content.description}"
---

${content.body}
`;
},

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.

⚠️ Potential issue | 🟠 Major

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
# Description: Check sibling adapters for escapeYamlValue pattern

# Search for escapeYamlValue function definitions in adapter files
rg -n 'function escapeYamlValue|const escapeYamlValue' src/core/command-generation/adapters/ --type ts

# Show a sample adapter (claude.ts) to compare structure
echo "--- Sample: claude.ts formatFile implementation ---"
rg -A 20 'formatFile\(content: CommandContent\)' src/core/command-generation/adapters/claude.ts

Repository: Fission-AI/OpenSpec

Length of output: 884


🏁 Script executed:

#!/bin/bash
set -euo pipefail

# Show trae.ts around formatFile for direct evidence
echo "=== trae.ts: formatFile section ==="
sed -n '1,120p' src/core/command-generation/adapters/trae.ts | nl -ba | sed -n '1,120p'

# Compare one sibling escapeYamlValue implementation with what we'd want for trae.ts
echo
echo "=== claude.ts: escapeYamlValue implementation ==="
sed -n '1,120p' src/core/command-generation/adapters/claude.ts | nl -ba | sed -n '1,120p'

echo
echo "=== cursor.ts: escapeYamlValue implementation ==="
sed -n '1,120p' src/core/command-generation/adapters/cursor.ts | nl -ba | sed -n '1,120p'

Repository: Fission-AI/OpenSpec

Length of output: 160


🏁 Script executed:

#!/bin/bash
set -euo pipefail

echo "=== trae.ts: formatFile section ==="
# Print with line numbers using cat -n (should be available)
cat -n src/core/command-generation/adapters/trae.ts | sed -n '1,140p' | sed -n '15,120p'

echo
echo "=== claude.ts: escapeYamlValue implementation + formatFile usage ==="
cat -n src/core/command-generation/adapters/claude.ts | sed -n '1,120p'

echo
echo "=== cursor.ts: escapeYamlValue implementation (for comparison) ==="
cat -n src/core/command-generation/adapters/cursor.ts | sed -n '1,120p'

Repository: Fission-AI/OpenSpec

Length of output: 4533


🏁 Script executed:

#!/bin/bash
set -euo pipefail

echo "=== trae.ts: top of file (imports + structure) ==="
cat -n src/core/command-generation/adapters/trae.ts | sed -n '1,80p'

Repository: Fission-AI/OpenSpec

Length of output: 1071


Fix Trae YAML frontmatter escaping for name/description

src/core/command-generation/adapters/trae.ts injects content.id and content.description directly into YAML frontmatter (name: ${content.id}, description: "${content.description}") without using the existing escapeYamlValue pattern used by sibling adapters (e.g., claude.ts, cursor.ts). Special characters like :, ", backslashes, or newlines can make the generated frontmatter invalid.

🛡️ Add escapeYamlValue helper and use it in formatFile
 import path from 'path';
 import type { CommandContent, ToolCommandAdapter } from '../types.js';
 
+/**
+ * Escapes a string value for safe inclusion in YAML.
+ * Adds quotes if the value contains special characters.
+ */
+function escapeYamlValue(value: string): string {
+  // Check if value needs quoting
+  const needsQuoting = /[:\n\r{}[\]&*#?|<>=!%@`"']/.test(value);
+  
+  if (!needsQuoting) {
+    return value;
+  }
+  
+  // Escape special characters and wrap in double quotes
+  const escaped = value
+    .replace(/\\/g, '\\\\')
+    .replace(/"/g, '\\"')
+    .replace(/\n/g, '\\n')
+    .replace(/\t/g, '\\t');
+  
+  return `"${escaped}"`;
+}
+
 /**
  * Trae adapter for command generation.
  * File path: .trae/commands/opsx/<id>.md
  * Frontmatter: name (bare id), description
  */
 export const traeAdapter: ToolCommandAdapter = {
   toolId: 'trae',
 
   getFilePath(commandId: string): string {
     return path.join('.trae', 'commands', 'opsx', `${commandId}.md`);
   },
 
   formatFile(content: CommandContent): string {
     return `---
-name: ${content.id}
-description: "${content.description}"
+name: ${escapeYamlValue(content.id)}
+description: ${escapeYamlValue(content.description)}
 ---
 
 ${content.body}
 `;
   },
 };
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/core/command-generation/adapters/trae.ts` around lines 23 - 31,
formatFile in adapters/trae.ts injects content.id and content.description
directly into YAML frontmatter causing invalid YAML when values contain special
characters; update formatFile to use the same escapeYamlValue utility used by
sibling adapters (e.g., claude.ts, cursor.ts) to sanitize both the name and
description before interpolation. Locate the formatFile method and replace
direct interpolation of content.id and content.description with escaped values
(call escapeYamlValue(content.id) and escapeYamlValue(content.description)),
ensuring description remains quoted in the frontmatter as in other adapters.

Source: Learnings

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant