Add provider skill discovery - #1905

Merged
juliusmarminge merged 12 commits into
mainfrom
t3code/server-provider-skills
Apr 11, 2026
Merged

Add provider skill discovery#1905
juliusmarminge merged 12 commits into
mainfrom
t3code/server-provider-skills

Conversation

@juliusmarminge

@juliusmarmingejuliusmarminge commented Apr 10, 2026

Copy link
Copy Markdown
Member

Summary

  • Adds provider skill presentation and slash-command discovery so composer UI can surface provider capabilities more directly.
  • Updates server/provider orchestration and Codex app-server plumbing to carry the new skill metadata through session and turn flows.
  • Refactors several effect service tags and ID constructors to the newer ServiceMap/makeUnsafe patterns for consistency.
  • Adjusts CLI publish/package metadata and related tests to match the new build outputs and config behavior.

Testing

  • Not run
  • Existing unit and integration tests were updated alongside the feature changes
  • Full project checks still need to pass: bun fmt, bun lint, bun typecheck, and bun run test

Note

Medium Risk
Extends the ServerProvider contract and provider health/probing flows to carry new capability metadata, and updates chat composer parsing/rendering and menu ranking logic; regressions could affect provider snapshots or composer input behavior across clients.

Overview
Provider snapshots now include capability metadata: ServerProvider gains slashCommands and skills arrays (with decoding defaults for backward compatibility), and buildServerProvider populates them.

Server-side probing is extended to fill these fields: Claude’s SDK init probe now collects and dedupes slash commands (and caches the combined probe), while Codex switches from account-only probing to probeCodexDiscovery via the app-server JSON-RPC to return both account info and per-CWD skills.

The web composer UI now surfaces provider capabilities: it adds $skill token detection/rendering (Lexical ComposerSkillNode chips with tooltip descriptions), expands slash-command completion to include provider commands, adds skill search/completion, and refactors menu highlighting + ranking using a new shared searchRanking utility (also reused for workspace entry ranking). Tests and fixtures are updated accordingly.

Reviewed by Cursor Bugbot for commit 016dbfd. Bugbot is set up for automated code reviews on this repo. Configure here.

Note

Add provider skill discovery and skill/slash-command support in the composer

  • Adds ServerProviderSkill and ServerProviderSlashCommand schemas to the contracts layer; both default to empty arrays when decoding legacy snapshots.
  • Probes the Codex provider via a new probeCodexDiscovery API to return discovered skills alongside account info, and parses Claude Agent SDK initialization commands into normalized slash commands.
  • Introduces a ComposerSkillNode Lexical node that renders inline skill chips with tooltips, and extends splitPromptTextIntoComposerSegments to parse $<name> tokens as skill segments.
  • Extends the composer command menu to show ranked, grouped results for both provider slash commands and skills, with correct /<command> and $<skill> insertion on selection.
  • Extracts a shared searchRanking package (scoreQueryMatch, insertRankedSearchResult, etc.) used by workspace entry search, skill search, and slash command search.
  • Risk: ComposerPromptEditor now requires a skills prop; any caller that does not pass it will get a type error.

Macroscope summarized 016dbfd.

- Probe Codex skills and Claude slash commands during provider checks
- Surface discovered items in server snapshots and composer UI
@coderabbitai

coderabbitaiBot commented Apr 10, 2026

Copy link
Copy Markdown

Important

Review skipped

Auto reviews are disabled on this repository. Please check the settings in the CodeRabbit UI or the .coderabbit.yaml file in this repository. To trigger a single review, invoke the @coderabbitai review command.

⚙️ Run configuration

Configuration used: Repository UI

Review profile: CHILL

Plan: Pro

Run ID: 1385ec2d-bc74-4b7b-b23e-c104f25cb89c

You can disable this status message by setting the reviews.review_status to false in the CodeRabbit configuration file.

Use the checkbox below for a quick retry:

  • 🔍 Trigger review
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch t3code/server-provider-skills

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

@github-actionsgithub-actionsBot added size:XL 500-999 changed lines (additions + deletions). vouch:trusted PR author is trusted by repo permissions or the VOUCHED list. labels Apr 10, 2026

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

Cursor Bugbot has reviewed your changes and found 2 potential issues.

Autofix Details

Bugbot Autofix prepared fixes for both issues found in the latest run.

  • ✅ Fixed: Ref assignments moved to useEffect cause stale reads
    • Moved the three ref assignments (composerMenuOpenRef, composerMenuItemsRef, activeComposerMenuItemRef) back to synchronous render phase by removing the useEffect wrapper, ensuring event handlers always read current values.
  • ✅ Fixed: Exported probeCodexAccount function is now unused
    • Removed the dead probeCodexAccount function from codexAppServer.ts since it has no remaining imports anywhere in the codebase.

Create PR

Or push these changes by commenting:

@cursor push 2d23dae3cc
Preview (2d23dae3cc)
diff --git a/apps/server/src/provider/codexAppServer.ts b/apps/server/src/provider/codexAppServer.ts--- a/apps/server/src/provider/codexAppServer.ts+++ b/apps/server/src/provider/codexAppServer.ts@@ -244,16 +244,3 @@
});
});
}
--export async function probeCodexAccount(input: {- readonly binaryPath: string;- readonly homePath?: string;- readonly signal?: AbortSignal;-}): Promise<CodexAccountSnapshot> {- return (- await probeCodexDiscovery({- ...input,- cwd: process.cwd(),- })- ).account;-}diff --git a/apps/web/src/components/chat/ChatComposer.tsx b/apps/web/src/components/chat/ChatComposer.tsx--- a/apps/web/src/components/chat/ChatComposer.tsx+++ b/apps/web/src/components/chat/ChatComposer.tsx@@ -820,11 +820,9 @@
[composerHighlightedItemId, composerMenuItems],
);
- useEffect(() => {- composerMenuOpenRef.current = composerMenuOpen;- composerMenuItemsRef.current = composerMenuItems;- activeComposerMenuItemRef.current = activeComposerMenuItem;- }, [activeComposerMenuItem, composerMenuItems, composerMenuOpen]);+ composerMenuOpenRef.current = composerMenuOpen;+ composerMenuItemsRef.current = composerMenuItems;+ activeComposerMenuItemRef.current = activeComposerMenuItem;
const nonPersistedComposerImageIdSet = useMemo(
() => new Set(nonPersistedComposerImageIds),

You can send follow-ups to the cloud agent here.

Comment threadapps/web/src/components/chat/ChatComposer.tsx Outdated
Comment threadapps/server/src/provider/codexAppServer.ts Outdated
Comment threadapps/web/src/components/ComposerPromptEditor.tsx Outdated
Comment threadapps/web/src/components/ComposerPromptEditor.tsx
@macroscopeapp

macroscopeappBot commented Apr 10, 2026

Copy link
Copy Markdown
Contributor

Approvability

Verdict: Needs human review

This PR introduces a significant new feature: provider skill and slash command discovery. It adds new user-facing capabilities including skill autocomplete via $ syntax, skill pills in the composer, provider slash commands in the command menu, and supporting search/ranking infrastructure. New features of this scope warrant human review to validate the design and integration.

You can customize Macroscope's approvability policy. Learn more.

- Map provider slash command hints into the shared contract
- Surface provider command metadata in the chat composer

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

Cursor Bugbot has reviewed your changes and found 1 potential issue.

There are 3 total unresolved issues (including 2 from previous reviews).

Autofix Details

Bugbot Autofix prepared a fix for the issue found in the latest run.

  • ✅ Fixed: skills/list failure rejects entire account probe
    • Changed the skills/list error handler to gracefully fall back to an empty skills array instead of calling fail(), so account probing remains resilient when skills/list is unsupported or errors.

Create PR

Or push these changes by commenting:

@cursor push 26dfbbe0ac
Preview (26dfbbe0ac)
diff --git a/apps/server/src/provider/codexAppServer.ts b/apps/server/src/provider/codexAppServer.ts--- a/apps/server/src/provider/codexAppServer.ts+++ b/apps/server/src/provider/codexAppServer.ts@@ -205,12 +205,7 @@
if (response.id === 2) {
const errorMessage = readErrorMessage(response);
- if (errorMessage) {- fail(new Error(`skills/list failed: ${errorMessage}`));- return;- }-- skills = parseCodexSkillsResult(response.result, input.cwd);+ skills = errorMessage ? [] : parseCodexSkillsResult(response.result, input.cwd);
maybeResolve();
return;
}

You can send follow-ups to the cloud agent here.

Comment threadapps/server/src/provider/codexAppServer.ts
cursoragentand others added 3 commits April 10, 2026 22:56
…tire probe
When skills/list returns an error (e.g. on older Codex CLI versions that
don't support it), fall back to an empty skills array instead of calling
fail() which would reject the entire discovery promise and break account
probing.
Co-authored-by: codex <codex@users.noreply.github.com>
- Restore serialized composer skill node state
- Sync skill labels before paint to avoid stale UI
- Keep composer menu refs current during render
@juliusmarminge

Copy link
Copy Markdown
MemberAuthor

@cursor push 26dfbbe

…tire probe
When skills/list returns an error (e.g. on older Codex CLI versions that
don't support it), fall back to an empty skills array instead of calling
fail() which would reject the entire discovery promise and break account
probing.
Applied via @cursor push command
@juliusmarmingejuliusmarminge changed the title Add provider skill discovery to Codex sessionsAdd provider skill discovery Apr 10, 2026

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

Cursor Bugbot has reviewed your changes and found 1 potential issue.

Autofix Details

Bugbot Autofix prepared a fix for the issue found in the latest run.

  • ✅ Fixed: Inconsistent field lookup for displayName vs shortDescription
    • Updated displayName lookup to check skill?.displayName first, falling back to display?.displayName, matching the same pattern used for shortDescription.

Create PR

Or push these changes by commenting:

@cursor push 6b028d659a
Preview (6b028d659a)
diff --git a/apps/server/src/provider/codexAppServer.ts b/apps/server/src/provider/codexAppServer.ts--- a/apps/server/src/provider/codexAppServer.ts+++ b/apps/server/src/provider/codexAppServer.ts@@ -64,8 +64,11 @@
? { description: nonEmptyTrimmed(skill?.description) }
: {}),
...(nonEmptyTrimmed(skill?.scope) ? { scope: nonEmptyTrimmed(skill?.scope) } : {}),
- ...(nonEmptyTrimmed(display?.displayName)- ? { displayName: nonEmptyTrimmed(display?.displayName) }+ ...(nonEmptyTrimmed(skill?.displayName) || nonEmptyTrimmed(display?.displayName)+ ? {+ displayName:+ nonEmptyTrimmed(skill?.displayName) ?? nonEmptyTrimmed(display?.displayName),+ }
: {}),
...(nonEmptyTrimmed(skill?.shortDescription) || nonEmptyTrimmed(display?.shortDescription)
? {

You can send follow-ups to the cloud agent here.

Comment threadapps/server/src/provider/codexAppServer.ts
- Introduced a new scoring mechanism for workspace entries that prioritizes exact basename matches over broader path matches.
- Updated the search logic to utilize shared ranking functions for improved performance and maintainability.
- Added a test case to validate the new ranking behavior for exact matches in workspace entries.
- Removed deprecated functions related to scoring and ranking to streamline the codebase.
@github-actionsgithub-actionsBot added size:XXL 1,000+ changed lines (additions + deletions). and removed size:XL 500-999 changed lines (additions + deletions). labels Apr 10, 2026

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

Cursor Bugbot has reviewed your changes and found 1 potential issue.

Autofix Details

Bugbot Autofix prepared a fix for the issue found in the latest run.

  • ✅ Fixed: Callback recreated on every keystroke causing unnecessary re-renders
    • Replaced the prompt state variable with promptRef.current in the setPromptFromTraits callback and removed prompt from the dependency array, restoring the stable ref-based pattern that prevents callback recreation on every keystroke.

Create PR

Or push these changes by commenting:

@cursor push aadef2980e
Preview (aadef2980e)
diff --git a/apps/web/src/components/chat/ChatComposer.tsx b/apps/web/src/components/chat/ChatComposer.tsx--- a/apps/web/src/components/chat/ChatComposer.tsx+++ b/apps/web/src/components/chat/ChatComposer.tsx@@ -868,7 +868,8 @@
// ------------------------------------------------------------------
const setPromptFromTraits = useCallback(
(nextPrompt: string) => {
- if (nextPrompt === prompt) {+ const currentPrompt = promptRef.current;+ if (nextPrompt === currentPrompt) {
scheduleComposerFocus();
return;
}
@@ -879,7 +880,7 @@
setComposerTrigger(detectComposerTrigger(nextPrompt, nextPrompt.length));
scheduleComposerFocus();
},
- [composerDraftTarget, prompt, promptRef, scheduleComposerFocus, setComposerDraftPrompt],+ [composerDraftTarget, promptRef, scheduleComposerFocus, setComposerDraftPrompt],
);
const providerTraitsMenuContent = renderProviderTraitsMenuContent({

You can send follow-ups to the cloud agent here.

Comment threadapps/web/src/components/chat/ChatComposer.tsx Outdated
Co-authored-by: codex <codex@users.noreply.github.com>

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

Cursor Bugbot has reviewed your changes and found 1 potential issue.

Fix All in Cursor

Bugbot Autofix prepared a fix for the issue found in the latest run.

  • ✅ Fixed: Double-lowercasing in shared scoring utility is redundant
    • Removed the redundant .trim().toLowerCase() calls inside scoreQueryMatch since all callers already pass pre-normalized inputs, replacing them with a direct destructure and a JSDoc contract documenting the pre-normalization requirement.

Create PR

Or push these changes by commenting:

@cursor push 20f5a4b15c
Preview (20f5a4b15c)
diff --git a/packages/shared/src/searchRanking.ts b/packages/shared/src/searchRanking.ts--- a/packages/shared/src/searchRanking.ts+++ b/packages/shared/src/searchRanking.ts@@ -77,6 +77,12 @@
return bestIndex;
}
+/**+ * Scores how well `value` matches `query` using tiered match strategies.+ *+ * **Expects pre-normalized inputs**: both `value` and `query` must already be+ * trimmed and lowercased (e.g. via {@link normalizeSearchQuery}).+ */
export function scoreQueryMatch(input: {
value: string;
query: string;
@@ -87,8 +93,7 @@
fuzzyBase?: number;
boundaryMarkers?: readonly string[];
}): number | null {
- const value = input.value.trim().toLowerCase();- const query = input.query.trim().toLowerCase();+ const { value, query } = input;
if (!value || !query) {
return null;

You can send follow-ups to the cloud agent here.

Reviewed by Cursor Bugbot for commit b0488e2. Configure here.

Comment threadpackages/shared/src/searchRanking.ts Outdated
cursoragentand others added 2 commits April 10, 2026 23:54
All callers already pass pre-normalized (trimmed and lowercased) inputs,
so the internal .trim().toLowerCase() calls were redundant O(n) string
operations allocating unnecessary copies on every candidate per keystroke.
Replace with a destructured read and a JSDoc contract stating that inputs
must be pre-normalized.
Co-authored-by: codex <codex@users.noreply.github.com>
@juliusmarmingejuliusmarminge changed the title Add provider skill discovery Add provider skill discoveryApr 11, 2026
@juliusmarminge

Copy link
Copy Markdown
MemberAuthor

@cursor push 20f5a4b

All callers already pass pre-normalized (trimmed and lowercased) inputs,
so the internal .trim().toLowerCase() calls were redundant O(n) string
operations allocating unnecessary copies on every candidate per keystroke.
Replace with a destructured read and a JSDoc contract stating that inputs
must be pre-normalized.
Applied via @cursor push command
@juliusmarminge
juliusmarminge merged commit 58e5f71 into mainApr 11, 2026
12 checks passed
@juliusmarminge
juliusmarminge deleted the t3code/server-provider-skills branch April 11, 2026 00:19
@juliusmarmingejuliusmarminge mentioned this pull request Apr 11, 2026
4 tasks
juliusmarminge added a commit that referenced this pull request Apr 13, 2026
Co-authored-by: Cursor Agent <cursoragent@cursor.com>
Co-authored-by: codex <codex@users.noreply.github.com>
Co-authored-by: cursor[bot] <206951365+cursor[bot]@users.noreply.github.com>
youpele52 referenced this pull request in youpele52/bigbud Jun 17, 2026
Co-authored-by: codex <codex@users.noreply.github.com>
Co-authored-by: cursor[bot] <206951365+cursor[bot]@users.noreply.github.com>
NeilTheFisher pushed a commit to NeilTheFisher/t3code that referenced this pull request Aug 18, 2026
Co-authored-by: Cursor Agent <cursoragent@cursor.com>
Co-authored-by: codex <codex@users.noreply.github.com>
Co-authored-by: cursor[bot] <206951365+cursor[bot]@users.noreply.github.com>
Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

size:XXL1,000+ changed lines (additions + deletions).vouch:trustedPR author is trusted by repo permissions or the VOUCHED list.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants

@juliusmarminge@cursoragent
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Add copy buttons to all
 blocks\n(function() {\n function addCopyButtons() {\n document.querySelectorAll('pre code').forEach(function(codeBlock) {\n if (codeBlock.parentElement.hasAttribute('data-copy-added')) return;\n codeBlock.parentElement.setAttribute('data-copy-added', 'true');\n \n var btn = document.createElement('button');\n btn.textContent = 'Copy';\n btn.style.cssText = 'position:absolute;top:4px;right:4px;padding:2px 8px;font-size:11px;background:#4ecdc4;border:none;border-radius:4px;color:#1a1a2e;cursor:pointer;opacity:0.7;transition:opacity 0.2s;';\n btn.onmouseover = function() { this.style.opacity = '1'; };\n btn.onmouseout = function() { this.style.opacity = '0.7'; };\n btn.onclick = function() {\n navigator.clipboard.writeText(codeBlock.textContent).then(function() {\n btn.textContent = 'Copied!';\n setTimeout(function() { btn.textContent = 'Copy'; }, 1500);\n });\n };\n codeBlock.parentElement.style.position = 'relative';\n codeBlock.parentElement.appendChild(btn);\n });\n }\n \n addCopyButtons();\n \n // Re-run on dynamic content\n var observer = new MutationObserver(addCopyButtons);\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "Add Copy Buttons to Code Blocks");
}
} catch(__e) { console.warn('[Userscript:Add Copy Buttons to Code Blocks]', __e); }
})();
(function(){
try {
var __m = "github.com";
var __re = new RegExp('^' + "github\\.com" + '
Skip to content

Add provider skill discovery - #1905

Merged
juliusmarminge merged 12 commits into
mainfrom
t3code/server-provider-skills
Apr 11, 2026
Merged

Add provider skill discovery#1905
juliusmarminge merged 12 commits into
mainfrom
t3code/server-provider-skills

Conversation

@juliusmarminge

@juliusmarmingejuliusmarminge commented Apr 10, 2026

Copy link
Copy Markdown
Member

Summary

  • Adds provider skill presentation and slash-command discovery so composer UI can surface provider capabilities more directly.
  • Updates server/provider orchestration and Codex app-server plumbing to carry the new skill metadata through session and turn flows.
  • Refactors several effect service tags and ID constructors to the newer ServiceMap/makeUnsafe patterns for consistency.
  • Adjusts CLI publish/package metadata and related tests to match the new build outputs and config behavior.

Testing

  • Not run
  • Existing unit and integration tests were updated alongside the feature changes
  • Full project checks still need to pass: bun fmt, bun lint, bun typecheck, and bun run test

Note

Medium Risk
Extends the ServerProvider contract and provider health/probing flows to carry new capability metadata, and updates chat composer parsing/rendering and menu ranking logic; regressions could affect provider snapshots or composer input behavior across clients.

Overview
Provider snapshots now include capability metadata: ServerProvider gains slashCommands and skills arrays (with decoding defaults for backward compatibility), and buildServerProvider populates them.

Server-side probing is extended to fill these fields: Claude’s SDK init probe now collects and dedupes slash commands (and caches the combined probe), while Codex switches from account-only probing to probeCodexDiscovery via the app-server JSON-RPC to return both account info and per-CWD skills.

The web composer UI now surfaces provider capabilities: it adds $skill token detection/rendering (Lexical ComposerSkillNode chips with tooltip descriptions), expands slash-command completion to include provider commands, adds skill search/completion, and refactors menu highlighting + ranking using a new shared searchRanking utility (also reused for workspace entry ranking). Tests and fixtures are updated accordingly.

Reviewed by Cursor Bugbot for commit 016dbfd. Bugbot is set up for automated code reviews on this repo. Configure here.

Note

Add provider skill discovery and skill/slash-command support in the composer

  • Adds ServerProviderSkill and ServerProviderSlashCommand schemas to the contracts layer; both default to empty arrays when decoding legacy snapshots.
  • Probes the Codex provider via a new probeCodexDiscovery API to return discovered skills alongside account info, and parses Claude Agent SDK initialization commands into normalized slash commands.
  • Introduces a ComposerSkillNode Lexical node that renders inline skill chips with tooltips, and extends splitPromptTextIntoComposerSegments to parse $<name> tokens as skill segments.
  • Extends the composer command menu to show ranked, grouped results for both provider slash commands and skills, with correct /<command> and $<skill> insertion on selection.
  • Extracts a shared searchRanking package (scoreQueryMatch, insertRankedSearchResult, etc.) used by workspace entry search, skill search, and slash command search.
  • Risk: ComposerPromptEditor now requires a skills prop; any caller that does not pass it will get a type error.

Macroscope summarized 016dbfd.

- Probe Codex skills and Claude slash commands during provider checks
- Surface discovered items in server snapshots and composer UI
@coderabbitai

coderabbitaiBot commented Apr 10, 2026

Copy link
Copy Markdown

Important

Review skipped

Auto reviews are disabled on this repository. Please check the settings in the CodeRabbit UI or the .coderabbit.yaml file in this repository. To trigger a single review, invoke the @coderabbitai review command.

⚙️ Run configuration

Configuration used: Repository UI

Review profile: CHILL

Plan: Pro

Run ID: 1385ec2d-bc74-4b7b-b23e-c104f25cb89c

You can disable this status message by setting the reviews.review_status to false in the CodeRabbit configuration file.

Use the checkbox below for a quick retry:

  • 🔍 Trigger review
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch t3code/server-provider-skills

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

@github-actionsgithub-actionsBot added size:XL 500-999 changed lines (additions + deletions). vouch:trusted PR author is trusted by repo permissions or the VOUCHED list. labels Apr 10, 2026

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

Cursor Bugbot has reviewed your changes and found 2 potential issues.

Autofix Details

Bugbot Autofix prepared fixes for both issues found in the latest run.

  • ✅ Fixed: Ref assignments moved to useEffect cause stale reads
    • Moved the three ref assignments (composerMenuOpenRef, composerMenuItemsRef, activeComposerMenuItemRef) back to synchronous render phase by removing the useEffect wrapper, ensuring event handlers always read current values.
  • ✅ Fixed: Exported probeCodexAccount function is now unused
    • Removed the dead probeCodexAccount function from codexAppServer.ts since it has no remaining imports anywhere in the codebase.

Create PR

Or push these changes by commenting:

@cursor push 2d23dae3cc
Preview (2d23dae3cc)
diff --git a/apps/server/src/provider/codexAppServer.ts b/apps/server/src/provider/codexAppServer.ts--- a/apps/server/src/provider/codexAppServer.ts+++ b/apps/server/src/provider/codexAppServer.ts@@ -244,16 +244,3 @@
});
});
}
--export async function probeCodexAccount(input: {- readonly binaryPath: string;- readonly homePath?: string;- readonly signal?: AbortSignal;-}): Promise<CodexAccountSnapshot> {- return (- await probeCodexDiscovery({- ...input,- cwd: process.cwd(),- })- ).account;-}diff --git a/apps/web/src/components/chat/ChatComposer.tsx b/apps/web/src/components/chat/ChatComposer.tsx--- a/apps/web/src/components/chat/ChatComposer.tsx+++ b/apps/web/src/components/chat/ChatComposer.tsx@@ -820,11 +820,9 @@
[composerHighlightedItemId, composerMenuItems],
);
- useEffect(() => {- composerMenuOpenRef.current = composerMenuOpen;- composerMenuItemsRef.current = composerMenuItems;- activeComposerMenuItemRef.current = activeComposerMenuItem;- }, [activeComposerMenuItem, composerMenuItems, composerMenuOpen]);+ composerMenuOpenRef.current = composerMenuOpen;+ composerMenuItemsRef.current = composerMenuItems;+ activeComposerMenuItemRef.current = activeComposerMenuItem;
const nonPersistedComposerImageIdSet = useMemo(
() => new Set(nonPersistedComposerImageIds),

You can send follow-ups to the cloud agent here.

Comment threadapps/web/src/components/chat/ChatComposer.tsx Outdated
Comment threadapps/server/src/provider/codexAppServer.ts Outdated
Comment threadapps/web/src/components/ComposerPromptEditor.tsx Outdated
Comment threadapps/web/src/components/ComposerPromptEditor.tsx
@macroscopeapp

macroscopeappBot commented Apr 10, 2026

Copy link
Copy Markdown
Contributor

Approvability

Verdict: Needs human review

This PR introduces a significant new feature: provider skill and slash command discovery. It adds new user-facing capabilities including skill autocomplete via $ syntax, skill pills in the composer, provider slash commands in the command menu, and supporting search/ranking infrastructure. New features of this scope warrant human review to validate the design and integration.

You can customize Macroscope's approvability policy. Learn more.

- Map provider slash command hints into the shared contract
- Surface provider command metadata in the chat composer

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

Cursor Bugbot has reviewed your changes and found 1 potential issue.

There are 3 total unresolved issues (including 2 from previous reviews).

Autofix Details

Bugbot Autofix prepared a fix for the issue found in the latest run.

  • ✅ Fixed: skills/list failure rejects entire account probe
    • Changed the skills/list error handler to gracefully fall back to an empty skills array instead of calling fail(), so account probing remains resilient when skills/list is unsupported or errors.

Create PR

Or push these changes by commenting:

@cursor push 26dfbbe0ac
Preview (26dfbbe0ac)
diff --git a/apps/server/src/provider/codexAppServer.ts b/apps/server/src/provider/codexAppServer.ts--- a/apps/server/src/provider/codexAppServer.ts+++ b/apps/server/src/provider/codexAppServer.ts@@ -205,12 +205,7 @@
if (response.id === 2) {
const errorMessage = readErrorMessage(response);
- if (errorMessage) {- fail(new Error(`skills/list failed: ${errorMessage}`));- return;- }-- skills = parseCodexSkillsResult(response.result, input.cwd);+ skills = errorMessage ? [] : parseCodexSkillsResult(response.result, input.cwd);
maybeResolve();
return;
}

You can send follow-ups to the cloud agent here.

Comment threadapps/server/src/provider/codexAppServer.ts
cursoragentand others added 3 commits April 10, 2026 22:56
…tire probe
When skills/list returns an error (e.g. on older Codex CLI versions that
don't support it), fall back to an empty skills array instead of calling
fail() which would reject the entire discovery promise and break account
probing.
Co-authored-by: codex <codex@users.noreply.github.com>
- Restore serialized composer skill node state
- Sync skill labels before paint to avoid stale UI
- Keep composer menu refs current during render
@juliusmarminge

Copy link
Copy Markdown
MemberAuthor

@cursor push 26dfbbe

…tire probe
When skills/list returns an error (e.g. on older Codex CLI versions that
don't support it), fall back to an empty skills array instead of calling
fail() which would reject the entire discovery promise and break account
probing.
Applied via @cursor push command
@juliusmarmingejuliusmarminge changed the title Add provider skill discovery to Codex sessionsAdd provider skill discovery Apr 10, 2026

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

Cursor Bugbot has reviewed your changes and found 1 potential issue.

Autofix Details

Bugbot Autofix prepared a fix for the issue found in the latest run.

  • ✅ Fixed: Inconsistent field lookup for displayName vs shortDescription
    • Updated displayName lookup to check skill?.displayName first, falling back to display?.displayName, matching the same pattern used for shortDescription.

Create PR

Or push these changes by commenting:

@cursor push 6b028d659a
Preview (6b028d659a)
diff --git a/apps/server/src/provider/codexAppServer.ts b/apps/server/src/provider/codexAppServer.ts--- a/apps/server/src/provider/codexAppServer.ts+++ b/apps/server/src/provider/codexAppServer.ts@@ -64,8 +64,11 @@
? { description: nonEmptyTrimmed(skill?.description) }
: {}),
...(nonEmptyTrimmed(skill?.scope) ? { scope: nonEmptyTrimmed(skill?.scope) } : {}),
- ...(nonEmptyTrimmed(display?.displayName)- ? { displayName: nonEmptyTrimmed(display?.displayName) }+ ...(nonEmptyTrimmed(skill?.displayName) || nonEmptyTrimmed(display?.displayName)+ ? {+ displayName:+ nonEmptyTrimmed(skill?.displayName) ?? nonEmptyTrimmed(display?.displayName),+ }
: {}),
...(nonEmptyTrimmed(skill?.shortDescription) || nonEmptyTrimmed(display?.shortDescription)
? {

You can send follow-ups to the cloud agent here.

Comment threadapps/server/src/provider/codexAppServer.ts
- Introduced a new scoring mechanism for workspace entries that prioritizes exact basename matches over broader path matches.
- Updated the search logic to utilize shared ranking functions for improved performance and maintainability.
- Added a test case to validate the new ranking behavior for exact matches in workspace entries.
- Removed deprecated functions related to scoring and ranking to streamline the codebase.
@github-actionsgithub-actionsBot added size:XXL 1,000+ changed lines (additions + deletions). and removed size:XL 500-999 changed lines (additions + deletions). labels Apr 10, 2026

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

Cursor Bugbot has reviewed your changes and found 1 potential issue.

Autofix Details

Bugbot Autofix prepared a fix for the issue found in the latest run.

  • ✅ Fixed: Callback recreated on every keystroke causing unnecessary re-renders
    • Replaced the prompt state variable with promptRef.current in the setPromptFromTraits callback and removed prompt from the dependency array, restoring the stable ref-based pattern that prevents callback recreation on every keystroke.

Create PR

Or push these changes by commenting:

@cursor push aadef2980e
Preview (aadef2980e)
diff --git a/apps/web/src/components/chat/ChatComposer.tsx b/apps/web/src/components/chat/ChatComposer.tsx--- a/apps/web/src/components/chat/ChatComposer.tsx+++ b/apps/web/src/components/chat/ChatComposer.tsx@@ -868,7 +868,8 @@
// ------------------------------------------------------------------
const setPromptFromTraits = useCallback(
(nextPrompt: string) => {
- if (nextPrompt === prompt) {+ const currentPrompt = promptRef.current;+ if (nextPrompt === currentPrompt) {
scheduleComposerFocus();
return;
}
@@ -879,7 +880,7 @@
setComposerTrigger(detectComposerTrigger(nextPrompt, nextPrompt.length));
scheduleComposerFocus();
},
- [composerDraftTarget, prompt, promptRef, scheduleComposerFocus, setComposerDraftPrompt],+ [composerDraftTarget, promptRef, scheduleComposerFocus, setComposerDraftPrompt],
);
const providerTraitsMenuContent = renderProviderTraitsMenuContent({

You can send follow-ups to the cloud agent here.

Comment threadapps/web/src/components/chat/ChatComposer.tsx Outdated
Co-authored-by: codex <codex@users.noreply.github.com>

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

Cursor Bugbot has reviewed your changes and found 1 potential issue.

Fix All in Cursor

Bugbot Autofix prepared a fix for the issue found in the latest run.

  • ✅ Fixed: Double-lowercasing in shared scoring utility is redundant
    • Removed the redundant .trim().toLowerCase() calls inside scoreQueryMatch since all callers already pass pre-normalized inputs, replacing them with a direct destructure and a JSDoc contract documenting the pre-normalization requirement.

Create PR

Or push these changes by commenting:

@cursor push 20f5a4b15c
Preview (20f5a4b15c)
diff --git a/packages/shared/src/searchRanking.ts b/packages/shared/src/searchRanking.ts--- a/packages/shared/src/searchRanking.ts+++ b/packages/shared/src/searchRanking.ts@@ -77,6 +77,12 @@
return bestIndex;
}
+/**+ * Scores how well `value` matches `query` using tiered match strategies.+ *+ * **Expects pre-normalized inputs**: both `value` and `query` must already be+ * trimmed and lowercased (e.g. via {@link normalizeSearchQuery}).+ */
export function scoreQueryMatch(input: {
value: string;
query: string;
@@ -87,8 +93,7 @@
fuzzyBase?: number;
boundaryMarkers?: readonly string[];
}): number | null {
- const value = input.value.trim().toLowerCase();- const query = input.query.trim().toLowerCase();+ const { value, query } = input;
if (!value || !query) {
return null;

You can send follow-ups to the cloud agent here.

Reviewed by Cursor Bugbot for commit b0488e2. Configure here.

Comment threadpackages/shared/src/searchRanking.ts Outdated
cursoragentand others added 2 commits April 10, 2026 23:54
All callers already pass pre-normalized (trimmed and lowercased) inputs,
so the internal .trim().toLowerCase() calls were redundant O(n) string
operations allocating unnecessary copies on every candidate per keystroke.
Replace with a destructured read and a JSDoc contract stating that inputs
must be pre-normalized.
Co-authored-by: codex <codex@users.noreply.github.com>
@juliusmarmingejuliusmarminge changed the title Add provider skill discovery Add provider skill discoveryApr 11, 2026
@juliusmarminge

Copy link
Copy Markdown
MemberAuthor

@cursor push 20f5a4b

All callers already pass pre-normalized (trimmed and lowercased) inputs,
so the internal .trim().toLowerCase() calls were redundant O(n) string
operations allocating unnecessary copies on every candidate per keystroke.
Replace with a destructured read and a JSDoc contract stating that inputs
must be pre-normalized.
Applied via @cursor push command
@juliusmarminge
juliusmarminge merged commit 58e5f71 into mainApr 11, 2026
12 checks passed
@juliusmarminge
juliusmarminge deleted the t3code/server-provider-skills branch April 11, 2026 00:19
@juliusmarmingejuliusmarminge mentioned this pull request Apr 11, 2026
4 tasks
juliusmarminge added a commit that referenced this pull request Apr 13, 2026
Co-authored-by: Cursor Agent <cursoragent@cursor.com>
Co-authored-by: codex <codex@users.noreply.github.com>
Co-authored-by: cursor[bot] <206951365+cursor[bot]@users.noreply.github.com>
youpele52 referenced this pull request in youpele52/bigbud Jun 17, 2026
Co-authored-by: codex <codex@users.noreply.github.com>
Co-authored-by: cursor[bot] <206951365+cursor[bot]@users.noreply.github.com>
NeilTheFisher pushed a commit to NeilTheFisher/t3code that referenced this pull request Aug 18, 2026
Co-authored-by: Cursor Agent <cursoragent@cursor.com>
Co-authored-by: codex <codex@users.noreply.github.com>
Co-authored-by: cursor[bot] <206951365+cursor[bot]@users.noreply.github.com>
Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

size:XXL1,000+ changed lines (additions + deletions).vouch:trustedPR author is trusted by repo permissions or the VOUCHED list.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants

@juliusmarminge@cursoragent
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Force GitHub README to respect dark mode\n(function() {\n var style = document.createElement('style');\n style.textContent = '\n .markdown-body {\n color-scheme: dark light;\n }\n .markdown-body pre { background: #161b22 !important; }\n .markdown-body code { background: rgba(110, 118, 129, 0.4) !important; }\n .markdown-body table th, .markdown-body table td { border-color: #30363d !important; }\n .markdown-body img { background: #0d1117; }\n .markdown-body blockquote { border-left-color: #8b949e; }\n .markdown-body hr { border-color: #30363d; }\n ';\n document.head.appendChild(style);\n})();", "GitHub Dark Mode README Fix"); } } catch(__e) { console.warn('[Userscript:GitHub Dark Mode README Fix]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content

Add provider skill discovery - #1905

Merged
juliusmarminge merged 12 commits into
mainfrom
t3code/server-provider-skills
Apr 11, 2026
Merged

Add provider skill discovery#1905
juliusmarminge merged 12 commits into
mainfrom
t3code/server-provider-skills

Conversation

@juliusmarminge

@juliusmarmingejuliusmarminge commented Apr 10, 2026

Copy link
Copy Markdown
Member

Summary

  • Adds provider skill presentation and slash-command discovery so composer UI can surface provider capabilities more directly.
  • Updates server/provider orchestration and Codex app-server plumbing to carry the new skill metadata through session and turn flows.
  • Refactors several effect service tags and ID constructors to the newer ServiceMap/makeUnsafe patterns for consistency.
  • Adjusts CLI publish/package metadata and related tests to match the new build outputs and config behavior.

Testing

  • Not run
  • Existing unit and integration tests were updated alongside the feature changes
  • Full project checks still need to pass: bun fmt, bun lint, bun typecheck, and bun run test

Note

Medium Risk
Extends the ServerProvider contract and provider health/probing flows to carry new capability metadata, and updates chat composer parsing/rendering and menu ranking logic; regressions could affect provider snapshots or composer input behavior across clients.

Overview
Provider snapshots now include capability metadata: ServerProvider gains slashCommands and skills arrays (with decoding defaults for backward compatibility), and buildServerProvider populates them.

Server-side probing is extended to fill these fields: Claude’s SDK init probe now collects and dedupes slash commands (and caches the combined probe), while Codex switches from account-only probing to probeCodexDiscovery via the app-server JSON-RPC to return both account info and per-CWD skills.

The web composer UI now surfaces provider capabilities: it adds $skill token detection/rendering (Lexical ComposerSkillNode chips with tooltip descriptions), expands slash-command completion to include provider commands, adds skill search/completion, and refactors menu highlighting + ranking using a new shared searchRanking utility (also reused for workspace entry ranking). Tests and fixtures are updated accordingly.

Reviewed by Cursor Bugbot for commit 016dbfd. Bugbot is set up for automated code reviews on this repo. Configure here.

Note

Add provider skill discovery and skill/slash-command support in the composer

  • Adds ServerProviderSkill and ServerProviderSlashCommand schemas to the contracts layer; both default to empty arrays when decoding legacy snapshots.
  • Probes the Codex provider via a new probeCodexDiscovery API to return discovered skills alongside account info, and parses Claude Agent SDK initialization commands into normalized slash commands.
  • Introduces a ComposerSkillNode Lexical node that renders inline skill chips with tooltips, and extends splitPromptTextIntoComposerSegments to parse $<name> tokens as skill segments.
  • Extends the composer command menu to show ranked, grouped results for both provider slash commands and skills, with correct /<command> and $<skill> insertion on selection.
  • Extracts a shared searchRanking package (scoreQueryMatch, insertRankedSearchResult, etc.) used by workspace entry search, skill search, and slash command search.
  • Risk: ComposerPromptEditor now requires a skills prop; any caller that does not pass it will get a type error.

Macroscope summarized 016dbfd.

- Probe Codex skills and Claude slash commands during provider checks
- Surface discovered items in server snapshots and composer UI
@coderabbitai

coderabbitaiBot commented Apr 10, 2026

Copy link
Copy Markdown

Important

Review skipped

Auto reviews are disabled on this repository. Please check the settings in the CodeRabbit UI or the .coderabbit.yaml file in this repository. To trigger a single review, invoke the @coderabbitai review command.

⚙️ Run configuration

Configuration used: Repository UI

Review profile: CHILL

Plan: Pro

Run ID: 1385ec2d-bc74-4b7b-b23e-c104f25cb89c

You can disable this status message by setting the reviews.review_status to false in the CodeRabbit configuration file.

Use the checkbox below for a quick retry:

  • 🔍 Trigger review
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch t3code/server-provider-skills

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

@github-actionsgithub-actionsBot added size:XL 500-999 changed lines (additions + deletions). vouch:trusted PR author is trusted by repo permissions or the VOUCHED list. labels Apr 10, 2026

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

Cursor Bugbot has reviewed your changes and found 2 potential issues.

Autofix Details

Bugbot Autofix prepared fixes for both issues found in the latest run.

  • ✅ Fixed: Ref assignments moved to useEffect cause stale reads
    • Moved the three ref assignments (composerMenuOpenRef, composerMenuItemsRef, activeComposerMenuItemRef) back to synchronous render phase by removing the useEffect wrapper, ensuring event handlers always read current values.
  • ✅ Fixed: Exported probeCodexAccount function is now unused
    • Removed the dead probeCodexAccount function from codexAppServer.ts since it has no remaining imports anywhere in the codebase.

Create PR

Or push these changes by commenting:

@cursor push 2d23dae3cc
Preview (2d23dae3cc)
diff --git a/apps/server/src/provider/codexAppServer.ts b/apps/server/src/provider/codexAppServer.ts--- a/apps/server/src/provider/codexAppServer.ts+++ b/apps/server/src/provider/codexAppServer.ts@@ -244,16 +244,3 @@
});
});
}
--export async function probeCodexAccount(input: {- readonly binaryPath: string;- readonly homePath?: string;- readonly signal?: AbortSignal;-}): Promise<CodexAccountSnapshot> {- return (- await probeCodexDiscovery({- ...input,- cwd: process.cwd(),- })- ).account;-}diff --git a/apps/web/src/components/chat/ChatComposer.tsx b/apps/web/src/components/chat/ChatComposer.tsx--- a/apps/web/src/components/chat/ChatComposer.tsx+++ b/apps/web/src/components/chat/ChatComposer.tsx@@ -820,11 +820,9 @@
[composerHighlightedItemId, composerMenuItems],
);
- useEffect(() => {- composerMenuOpenRef.current = composerMenuOpen;- composerMenuItemsRef.current = composerMenuItems;- activeComposerMenuItemRef.current = activeComposerMenuItem;- }, [activeComposerMenuItem, composerMenuItems, composerMenuOpen]);+ composerMenuOpenRef.current = composerMenuOpen;+ composerMenuItemsRef.current = composerMenuItems;+ activeComposerMenuItemRef.current = activeComposerMenuItem;
const nonPersistedComposerImageIdSet = useMemo(
() => new Set(nonPersistedComposerImageIds),

You can send follow-ups to the cloud agent here.

Comment threadapps/web/src/components/chat/ChatComposer.tsx Outdated
Comment threadapps/server/src/provider/codexAppServer.ts Outdated
Comment threadapps/web/src/components/ComposerPromptEditor.tsx Outdated
Comment threadapps/web/src/components/ComposerPromptEditor.tsx
@macroscopeapp

macroscopeappBot commented Apr 10, 2026

Copy link
Copy Markdown
Contributor

Approvability

Verdict: Needs human review

This PR introduces a significant new feature: provider skill and slash command discovery. It adds new user-facing capabilities including skill autocomplete via $ syntax, skill pills in the composer, provider slash commands in the command menu, and supporting search/ranking infrastructure. New features of this scope warrant human review to validate the design and integration.

You can customize Macroscope's approvability policy. Learn more.

- Map provider slash command hints into the shared contract
- Surface provider command metadata in the chat composer

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

Cursor Bugbot has reviewed your changes and found 1 potential issue.

There are 3 total unresolved issues (including 2 from previous reviews).

Autofix Details

Bugbot Autofix prepared a fix for the issue found in the latest run.

  • ✅ Fixed: skills/list failure rejects entire account probe
    • Changed the skills/list error handler to gracefully fall back to an empty skills array instead of calling fail(), so account probing remains resilient when skills/list is unsupported or errors.

Create PR

Or push these changes by commenting:

@cursor push 26dfbbe0ac
Preview (26dfbbe0ac)
diff --git a/apps/server/src/provider/codexAppServer.ts b/apps/server/src/provider/codexAppServer.ts--- a/apps/server/src/provider/codexAppServer.ts+++ b/apps/server/src/provider/codexAppServer.ts@@ -205,12 +205,7 @@
if (response.id === 2) {
const errorMessage = readErrorMessage(response);
- if (errorMessage) {- fail(new Error(`skills/list failed: ${errorMessage}`));- return;- }-- skills = parseCodexSkillsResult(response.result, input.cwd);+ skills = errorMessage ? [] : parseCodexSkillsResult(response.result, input.cwd);
maybeResolve();
return;
}

You can send follow-ups to the cloud agent here.

Comment threadapps/server/src/provider/codexAppServer.ts
cursoragentand others added 3 commits April 10, 2026 22:56
…tire probe
When skills/list returns an error (e.g. on older Codex CLI versions that
don't support it), fall back to an empty skills array instead of calling
fail() which would reject the entire discovery promise and break account
probing.
Co-authored-by: codex <codex@users.noreply.github.com>
- Restore serialized composer skill node state
- Sync skill labels before paint to avoid stale UI
- Keep composer menu refs current during render
@juliusmarminge

Copy link
Copy Markdown
MemberAuthor

@cursor push 26dfbbe

…tire probe
When skills/list returns an error (e.g. on older Codex CLI versions that
don't support it), fall back to an empty skills array instead of calling
fail() which would reject the entire discovery promise and break account
probing.
Applied via @cursor push command
@juliusmarmingejuliusmarminge changed the title Add provider skill discovery to Codex sessionsAdd provider skill discovery Apr 10, 2026

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

Cursor Bugbot has reviewed your changes and found 1 potential issue.

Autofix Details

Bugbot Autofix prepared a fix for the issue found in the latest run.

  • ✅ Fixed: Inconsistent field lookup for displayName vs shortDescription
    • Updated displayName lookup to check skill?.displayName first, falling back to display?.displayName, matching the same pattern used for shortDescription.

Create PR

Or push these changes by commenting:

@cursor push 6b028d659a
Preview (6b028d659a)
diff --git a/apps/server/src/provider/codexAppServer.ts b/apps/server/src/provider/codexAppServer.ts--- a/apps/server/src/provider/codexAppServer.ts+++ b/apps/server/src/provider/codexAppServer.ts@@ -64,8 +64,11 @@
? { description: nonEmptyTrimmed(skill?.description) }
: {}),
...(nonEmptyTrimmed(skill?.scope) ? { scope: nonEmptyTrimmed(skill?.scope) } : {}),
- ...(nonEmptyTrimmed(display?.displayName)- ? { displayName: nonEmptyTrimmed(display?.displayName) }+ ...(nonEmptyTrimmed(skill?.displayName) || nonEmptyTrimmed(display?.displayName)+ ? {+ displayName:+ nonEmptyTrimmed(skill?.displayName) ?? nonEmptyTrimmed(display?.displayName),+ }
: {}),
...(nonEmptyTrimmed(skill?.shortDescription) || nonEmptyTrimmed(display?.shortDescription)
? {

You can send follow-ups to the cloud agent here.

Comment threadapps/server/src/provider/codexAppServer.ts
- Introduced a new scoring mechanism for workspace entries that prioritizes exact basename matches over broader path matches.
- Updated the search logic to utilize shared ranking functions for improved performance and maintainability.
- Added a test case to validate the new ranking behavior for exact matches in workspace entries.
- Removed deprecated functions related to scoring and ranking to streamline the codebase.
@github-actionsgithub-actionsBot added size:XXL 1,000+ changed lines (additions + deletions). and removed size:XL 500-999 changed lines (additions + deletions). labels Apr 10, 2026

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

Cursor Bugbot has reviewed your changes and found 1 potential issue.

Autofix Details

Bugbot Autofix prepared a fix for the issue found in the latest run.

  • ✅ Fixed: Callback recreated on every keystroke causing unnecessary re-renders
    • Replaced the prompt state variable with promptRef.current in the setPromptFromTraits callback and removed prompt from the dependency array, restoring the stable ref-based pattern that prevents callback recreation on every keystroke.

Create PR

Or push these changes by commenting:

@cursor push aadef2980e
Preview (aadef2980e)
diff --git a/apps/web/src/components/chat/ChatComposer.tsx b/apps/web/src/components/chat/ChatComposer.tsx--- a/apps/web/src/components/chat/ChatComposer.tsx+++ b/apps/web/src/components/chat/ChatComposer.tsx@@ -868,7 +868,8 @@
// ------------------------------------------------------------------
const setPromptFromTraits = useCallback(
(nextPrompt: string) => {
- if (nextPrompt === prompt) {+ const currentPrompt = promptRef.current;+ if (nextPrompt === currentPrompt) {
scheduleComposerFocus();
return;
}
@@ -879,7 +880,7 @@
setComposerTrigger(detectComposerTrigger(nextPrompt, nextPrompt.length));
scheduleComposerFocus();
},
- [composerDraftTarget, prompt, promptRef, scheduleComposerFocus, setComposerDraftPrompt],+ [composerDraftTarget, promptRef, scheduleComposerFocus, setComposerDraftPrompt],
);
const providerTraitsMenuContent = renderProviderTraitsMenuContent({

You can send follow-ups to the cloud agent here.

Comment threadapps/web/src/components/chat/ChatComposer.tsx Outdated
Co-authored-by: codex <codex@users.noreply.github.com>

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

Cursor Bugbot has reviewed your changes and found 1 potential issue.

Fix All in Cursor

Bugbot Autofix prepared a fix for the issue found in the latest run.

  • ✅ Fixed: Double-lowercasing in shared scoring utility is redundant
    • Removed the redundant .trim().toLowerCase() calls inside scoreQueryMatch since all callers already pass pre-normalized inputs, replacing them with a direct destructure and a JSDoc contract documenting the pre-normalization requirement.

Create PR

Or push these changes by commenting:

@cursor push 20f5a4b15c
Preview (20f5a4b15c)
diff --git a/packages/shared/src/searchRanking.ts b/packages/shared/src/searchRanking.ts--- a/packages/shared/src/searchRanking.ts+++ b/packages/shared/src/searchRanking.ts@@ -77,6 +77,12 @@
return bestIndex;
}
+/**+ * Scores how well `value` matches `query` using tiered match strategies.+ *+ * **Expects pre-normalized inputs**: both `value` and `query` must already be+ * trimmed and lowercased (e.g. via {@link normalizeSearchQuery}).+ */
export function scoreQueryMatch(input: {
value: string;
query: string;
@@ -87,8 +93,7 @@
fuzzyBase?: number;
boundaryMarkers?: readonly string[];
}): number | null {
- const value = input.value.trim().toLowerCase();- const query = input.query.trim().toLowerCase();+ const { value, query } = input;
if (!value || !query) {
return null;

You can send follow-ups to the cloud agent here.

Reviewed by Cursor Bugbot for commit b0488e2. Configure here.

Comment threadpackages/shared/src/searchRanking.ts Outdated
cursoragentand others added 2 commits April 10, 2026 23:54
All callers already pass pre-normalized (trimmed and lowercased) inputs,
so the internal .trim().toLowerCase() calls were redundant O(n) string
operations allocating unnecessary copies on every candidate per keystroke.
Replace with a destructured read and a JSDoc contract stating that inputs
must be pre-normalized.
Co-authored-by: codex <codex@users.noreply.github.com>
@juliusmarmingejuliusmarminge changed the title Add provider skill discovery Add provider skill discoveryApr 11, 2026
@juliusmarminge

Copy link
Copy Markdown
MemberAuthor

@cursor push 20f5a4b

All callers already pass pre-normalized (trimmed and lowercased) inputs,
so the internal .trim().toLowerCase() calls were redundant O(n) string
operations allocating unnecessary copies on every candidate per keystroke.
Replace with a destructured read and a JSDoc contract stating that inputs
must be pre-normalized.
Applied via @cursor push command
@juliusmarminge
juliusmarminge merged commit 58e5f71 into mainApr 11, 2026
12 checks passed
@juliusmarminge
juliusmarminge deleted the t3code/server-provider-skills branch April 11, 2026 00:19
@juliusmarmingejuliusmarminge mentioned this pull request Apr 11, 2026
4 tasks
juliusmarminge added a commit that referenced this pull request Apr 13, 2026
Co-authored-by: Cursor Agent <cursoragent@cursor.com>
Co-authored-by: codex <codex@users.noreply.github.com>
Co-authored-by: cursor[bot] <206951365+cursor[bot]@users.noreply.github.com>
youpele52 referenced this pull request in youpele52/bigbud Jun 17, 2026
Co-authored-by: codex <codex@users.noreply.github.com>
Co-authored-by: cursor[bot] <206951365+cursor[bot]@users.noreply.github.com>
NeilTheFisher pushed a commit to NeilTheFisher/t3code that referenced this pull request Aug 18, 2026
Co-authored-by: Cursor Agent <cursoragent@cursor.com>
Co-authored-by: codex <codex@users.noreply.github.com>
Co-authored-by: cursor[bot] <206951365+cursor[bot]@users.noreply.github.com>
Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

size:XXL1,000+ changed lines (additions + deletions).vouch:trustedPR author is trusted by repo permissions or the VOUCHED list.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants

@juliusmarminge@cursoragent
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Highlight search terms from Google/DuckDuckGo/Bing referrer\n(function() {\n var ref = document.referrer;\n var terms = [];\n \n if (ref.includes('google.com') || ref.includes('duckduckgo.com') || ref.includes('bing.com')) {\n var url = new URL(ref);\n var q = url.searchParams.get('q') || url.searchParams.get('p');\n if (q) {\n terms = q.split(/\\s+/).filter(function(t) { return t.length > 2; });\n }\n }\n \n if (terms.length === 0) return;\n \n var style = document.createElement('style');\n style.textContent = '.userscript-highlight { background: #fbbf24; color: #1a1a2e; padding: 1px 3px; border-radius: 2px; }';\n document.head.appendChild(style);\n \n function highlight(node) {\n if (node.nodeType === 3) { // text node\n var text = node.textContent;\n var found = false;\n terms.forEach(function(term) {\n var regex = new RegExp('(' + term.replace(/[.*+?^${}()|[\\]\\\\]/g, '\\\\') + ')', 'gi');\n if (regex.test(text)) {\n found = true;\n var frag = document.createDocumentFragment();\n var parts = text.split(regex);\n parts.forEach(function(part, i) {\n if (i % 2 === 0) {\n frag.appendChild(document.createTextNode(part));\n } else {\n var span = document.createElement('span');\n span.className = 'userscript-highlight';\n span.textContent = part;\n frag.appendChild(span);\n }\n });\n node.parentNode.replaceChild(frag, node);\n }\n });\n } else if (node.nodeType === 1 && node.childNodes) { // element\n var skipTags = ['SCRIPT', 'STYLE', 'NOSCRIPT', 'TEXTAREA', 'INPUT', 'SELECT'];\n if (!skipTags.includes(node.tagName)) {\n Array.from(node.childNodes).forEach(highlight);\n }\n }\n }\n \n highlight(document.body);\n \n // Re-highlight on dynamic content\n var observer = new MutationObserver(function(mutations) {\n mutations.forEach(function(m) {\n m.addedNodes.forEach(function(node) {\n if (node.nodeType === 1 || node.nodeType === 3) highlight(node);\n });\n });\n });\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "Highlight Search Terms"); } } catch(__e) { console.warn('[Userscript:Highlight Search Terms]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content

Add provider skill discovery - #1905

Merged
juliusmarminge merged 12 commits into
mainfrom
t3code/server-provider-skills
Apr 11, 2026
Merged

Add provider skill discovery#1905
juliusmarminge merged 12 commits into
mainfrom
t3code/server-provider-skills

Conversation

@juliusmarminge

@juliusmarmingejuliusmarminge commented Apr 10, 2026

Copy link
Copy Markdown
Member

Summary

  • Adds provider skill presentation and slash-command discovery so composer UI can surface provider capabilities more directly.
  • Updates server/provider orchestration and Codex app-server plumbing to carry the new skill metadata through session and turn flows.
  • Refactors several effect service tags and ID constructors to the newer ServiceMap/makeUnsafe patterns for consistency.
  • Adjusts CLI publish/package metadata and related tests to match the new build outputs and config behavior.

Testing

  • Not run
  • Existing unit and integration tests were updated alongside the feature changes
  • Full project checks still need to pass: bun fmt, bun lint, bun typecheck, and bun run test

Note

Medium Risk
Extends the ServerProvider contract and provider health/probing flows to carry new capability metadata, and updates chat composer parsing/rendering and menu ranking logic; regressions could affect provider snapshots or composer input behavior across clients.

Overview
Provider snapshots now include capability metadata: ServerProvider gains slashCommands and skills arrays (with decoding defaults for backward compatibility), and buildServerProvider populates them.

Server-side probing is extended to fill these fields: Claude’s SDK init probe now collects and dedupes slash commands (and caches the combined probe), while Codex switches from account-only probing to probeCodexDiscovery via the app-server JSON-RPC to return both account info and per-CWD skills.

The web composer UI now surfaces provider capabilities: it adds $skill token detection/rendering (Lexical ComposerSkillNode chips with tooltip descriptions), expands slash-command completion to include provider commands, adds skill search/completion, and refactors menu highlighting + ranking using a new shared searchRanking utility (also reused for workspace entry ranking). Tests and fixtures are updated accordingly.

Reviewed by Cursor Bugbot for commit 016dbfd. Bugbot is set up for automated code reviews on this repo. Configure here.

Note

Add provider skill discovery and skill/slash-command support in the composer

  • Adds ServerProviderSkill and ServerProviderSlashCommand schemas to the contracts layer; both default to empty arrays when decoding legacy snapshots.
  • Probes the Codex provider via a new probeCodexDiscovery API to return discovered skills alongside account info, and parses Claude Agent SDK initialization commands into normalized slash commands.
  • Introduces a ComposerSkillNode Lexical node that renders inline skill chips with tooltips, and extends splitPromptTextIntoComposerSegments to parse $<name> tokens as skill segments.
  • Extends the composer command menu to show ranked, grouped results for both provider slash commands and skills, with correct /<command> and $<skill> insertion on selection.
  • Extracts a shared searchRanking package (scoreQueryMatch, insertRankedSearchResult, etc.) used by workspace entry search, skill search, and slash command search.
  • Risk: ComposerPromptEditor now requires a skills prop; any caller that does not pass it will get a type error.

Macroscope summarized 016dbfd.

- Probe Codex skills and Claude slash commands during provider checks
- Surface discovered items in server snapshots and composer UI
@coderabbitai

coderabbitaiBot commented Apr 10, 2026

Copy link
Copy Markdown

Important

Review skipped

Auto reviews are disabled on this repository. Please check the settings in the CodeRabbit UI or the .coderabbit.yaml file in this repository. To trigger a single review, invoke the @coderabbitai review command.

⚙️ Run configuration

Configuration used: Repository UI

Review profile: CHILL

Plan: Pro

Run ID: 1385ec2d-bc74-4b7b-b23e-c104f25cb89c

You can disable this status message by setting the reviews.review_status to false in the CodeRabbit configuration file.

Use the checkbox below for a quick retry:

  • 🔍 Trigger review
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch t3code/server-provider-skills

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

@github-actionsgithub-actionsBot added size:XL 500-999 changed lines (additions + deletions). vouch:trusted PR author is trusted by repo permissions or the VOUCHED list. labels Apr 10, 2026

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

Cursor Bugbot has reviewed your changes and found 2 potential issues.

Autofix Details

Bugbot Autofix prepared fixes for both issues found in the latest run.

  • ✅ Fixed: Ref assignments moved to useEffect cause stale reads
    • Moved the three ref assignments (composerMenuOpenRef, composerMenuItemsRef, activeComposerMenuItemRef) back to synchronous render phase by removing the useEffect wrapper, ensuring event handlers always read current values.
  • ✅ Fixed: Exported probeCodexAccount function is now unused
    • Removed the dead probeCodexAccount function from codexAppServer.ts since it has no remaining imports anywhere in the codebase.

Create PR

Or push these changes by commenting:

@cursor push 2d23dae3cc
Preview (2d23dae3cc)
diff --git a/apps/server/src/provider/codexAppServer.ts b/apps/server/src/provider/codexAppServer.ts--- a/apps/server/src/provider/codexAppServer.ts+++ b/apps/server/src/provider/codexAppServer.ts@@ -244,16 +244,3 @@
});
});
}
--export async function probeCodexAccount(input: {- readonly binaryPath: string;- readonly homePath?: string;- readonly signal?: AbortSignal;-}): Promise<CodexAccountSnapshot> {- return (- await probeCodexDiscovery({- ...input,- cwd: process.cwd(),- })- ).account;-}diff --git a/apps/web/src/components/chat/ChatComposer.tsx b/apps/web/src/components/chat/ChatComposer.tsx--- a/apps/web/src/components/chat/ChatComposer.tsx+++ b/apps/web/src/components/chat/ChatComposer.tsx@@ -820,11 +820,9 @@
[composerHighlightedItemId, composerMenuItems],
);
- useEffect(() => {- composerMenuOpenRef.current = composerMenuOpen;- composerMenuItemsRef.current = composerMenuItems;- activeComposerMenuItemRef.current = activeComposerMenuItem;- }, [activeComposerMenuItem, composerMenuItems, composerMenuOpen]);+ composerMenuOpenRef.current = composerMenuOpen;+ composerMenuItemsRef.current = composerMenuItems;+ activeComposerMenuItemRef.current = activeComposerMenuItem;
const nonPersistedComposerImageIdSet = useMemo(
() => new Set(nonPersistedComposerImageIds),

You can send follow-ups to the cloud agent here.

Comment threadapps/web/src/components/chat/ChatComposer.tsx Outdated
Comment threadapps/server/src/provider/codexAppServer.ts Outdated
Comment threadapps/web/src/components/ComposerPromptEditor.tsx Outdated
Comment threadapps/web/src/components/ComposerPromptEditor.tsx
@macroscopeapp

macroscopeappBot commented Apr 10, 2026

Copy link
Copy Markdown
Contributor

Approvability

Verdict: Needs human review

This PR introduces a significant new feature: provider skill and slash command discovery. It adds new user-facing capabilities including skill autocomplete via $ syntax, skill pills in the composer, provider slash commands in the command menu, and supporting search/ranking infrastructure. New features of this scope warrant human review to validate the design and integration.

You can customize Macroscope's approvability policy. Learn more.

- Map provider slash command hints into the shared contract
- Surface provider command metadata in the chat composer

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

Cursor Bugbot has reviewed your changes and found 1 potential issue.

There are 3 total unresolved issues (including 2 from previous reviews).

Autofix Details

Bugbot Autofix prepared a fix for the issue found in the latest run.

  • ✅ Fixed: skills/list failure rejects entire account probe
    • Changed the skills/list error handler to gracefully fall back to an empty skills array instead of calling fail(), so account probing remains resilient when skills/list is unsupported or errors.

Create PR

Or push these changes by commenting:

@cursor push 26dfbbe0ac
Preview (26dfbbe0ac)
diff --git a/apps/server/src/provider/codexAppServer.ts b/apps/server/src/provider/codexAppServer.ts--- a/apps/server/src/provider/codexAppServer.ts+++ b/apps/server/src/provider/codexAppServer.ts@@ -205,12 +205,7 @@
if (response.id === 2) {
const errorMessage = readErrorMessage(response);
- if (errorMessage) {- fail(new Error(`skills/list failed: ${errorMessage}`));- return;- }-- skills = parseCodexSkillsResult(response.result, input.cwd);+ skills = errorMessage ? [] : parseCodexSkillsResult(response.result, input.cwd);
maybeResolve();
return;
}

You can send follow-ups to the cloud agent here.

Comment threadapps/server/src/provider/codexAppServer.ts
cursoragentand others added 3 commits April 10, 2026 22:56
…tire probe
When skills/list returns an error (e.g. on older Codex CLI versions that
don't support it), fall back to an empty skills array instead of calling
fail() which would reject the entire discovery promise and break account
probing.
Co-authored-by: codex <codex@users.noreply.github.com>
- Restore serialized composer skill node state
- Sync skill labels before paint to avoid stale UI
- Keep composer menu refs current during render
@juliusmarminge

Copy link
Copy Markdown
MemberAuthor

@cursor push 26dfbbe

…tire probe
When skills/list returns an error (e.g. on older Codex CLI versions that
don't support it), fall back to an empty skills array instead of calling
fail() which would reject the entire discovery promise and break account
probing.
Applied via @cursor push command
@juliusmarmingejuliusmarminge changed the title Add provider skill discovery to Codex sessionsAdd provider skill discovery Apr 10, 2026

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

Cursor Bugbot has reviewed your changes and found 1 potential issue.

Autofix Details

Bugbot Autofix prepared a fix for the issue found in the latest run.

  • ✅ Fixed: Inconsistent field lookup for displayName vs shortDescription
    • Updated displayName lookup to check skill?.displayName first, falling back to display?.displayName, matching the same pattern used for shortDescription.

Create PR

Or push these changes by commenting:

@cursor push 6b028d659a
Preview (6b028d659a)
diff --git a/apps/server/src/provider/codexAppServer.ts b/apps/server/src/provider/codexAppServer.ts--- a/apps/server/src/provider/codexAppServer.ts+++ b/apps/server/src/provider/codexAppServer.ts@@ -64,8 +64,11 @@
? { description: nonEmptyTrimmed(skill?.description) }
: {}),
...(nonEmptyTrimmed(skill?.scope) ? { scope: nonEmptyTrimmed(skill?.scope) } : {}),
- ...(nonEmptyTrimmed(display?.displayName)- ? { displayName: nonEmptyTrimmed(display?.displayName) }+ ...(nonEmptyTrimmed(skill?.displayName) || nonEmptyTrimmed(display?.displayName)+ ? {+ displayName:+ nonEmptyTrimmed(skill?.displayName) ?? nonEmptyTrimmed(display?.displayName),+ }
: {}),
...(nonEmptyTrimmed(skill?.shortDescription) || nonEmptyTrimmed(display?.shortDescription)
? {

You can send follow-ups to the cloud agent here.

Comment threadapps/server/src/provider/codexAppServer.ts
- Introduced a new scoring mechanism for workspace entries that prioritizes exact basename matches over broader path matches.
- Updated the search logic to utilize shared ranking functions for improved performance and maintainability.
- Added a test case to validate the new ranking behavior for exact matches in workspace entries.
- Removed deprecated functions related to scoring and ranking to streamline the codebase.
@github-actionsgithub-actionsBot added size:XXL 1,000+ changed lines (additions + deletions). and removed size:XL 500-999 changed lines (additions + deletions). labels Apr 10, 2026

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

Cursor Bugbot has reviewed your changes and found 1 potential issue.

Autofix Details

Bugbot Autofix prepared a fix for the issue found in the latest run.

  • ✅ Fixed: Callback recreated on every keystroke causing unnecessary re-renders
    • Replaced the prompt state variable with promptRef.current in the setPromptFromTraits callback and removed prompt from the dependency array, restoring the stable ref-based pattern that prevents callback recreation on every keystroke.

Create PR

Or push these changes by commenting:

@cursor push aadef2980e
Preview (aadef2980e)
diff --git a/apps/web/src/components/chat/ChatComposer.tsx b/apps/web/src/components/chat/ChatComposer.tsx--- a/apps/web/src/components/chat/ChatComposer.tsx+++ b/apps/web/src/components/chat/ChatComposer.tsx@@ -868,7 +868,8 @@
// ------------------------------------------------------------------
const setPromptFromTraits = useCallback(
(nextPrompt: string) => {
- if (nextPrompt === prompt) {+ const currentPrompt = promptRef.current;+ if (nextPrompt === currentPrompt) {
scheduleComposerFocus();
return;
}
@@ -879,7 +880,7 @@
setComposerTrigger(detectComposerTrigger(nextPrompt, nextPrompt.length));
scheduleComposerFocus();
},
- [composerDraftTarget, prompt, promptRef, scheduleComposerFocus, setComposerDraftPrompt],+ [composerDraftTarget, promptRef, scheduleComposerFocus, setComposerDraftPrompt],
);
const providerTraitsMenuContent = renderProviderTraitsMenuContent({

You can send follow-ups to the cloud agent here.

Comment threadapps/web/src/components/chat/ChatComposer.tsx Outdated
Co-authored-by: codex <codex@users.noreply.github.com>

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

Cursor Bugbot has reviewed your changes and found 1 potential issue.

Fix All in Cursor

Bugbot Autofix prepared a fix for the issue found in the latest run.

  • ✅ Fixed: Double-lowercasing in shared scoring utility is redundant
    • Removed the redundant .trim().toLowerCase() calls inside scoreQueryMatch since all callers already pass pre-normalized inputs, replacing them with a direct destructure and a JSDoc contract documenting the pre-normalization requirement.

Create PR

Or push these changes by commenting:

@cursor push 20f5a4b15c
Preview (20f5a4b15c)
diff --git a/packages/shared/src/searchRanking.ts b/packages/shared/src/searchRanking.ts--- a/packages/shared/src/searchRanking.ts+++ b/packages/shared/src/searchRanking.ts@@ -77,6 +77,12 @@
return bestIndex;
}
+/**+ * Scores how well `value` matches `query` using tiered match strategies.+ *+ * **Expects pre-normalized inputs**: both `value` and `query` must already be+ * trimmed and lowercased (e.g. via {@link normalizeSearchQuery}).+ */
export function scoreQueryMatch(input: {
value: string;
query: string;
@@ -87,8 +93,7 @@
fuzzyBase?: number;
boundaryMarkers?: readonly string[];
}): number | null {
- const value = input.value.trim().toLowerCase();- const query = input.query.trim().toLowerCase();+ const { value, query } = input;
if (!value || !query) {
return null;

You can send follow-ups to the cloud agent here.

Reviewed by Cursor Bugbot for commit b0488e2. Configure here.

Comment threadpackages/shared/src/searchRanking.ts Outdated
cursoragentand others added 2 commits April 10, 2026 23:54
All callers already pass pre-normalized (trimmed and lowercased) inputs,
so the internal .trim().toLowerCase() calls were redundant O(n) string
operations allocating unnecessary copies on every candidate per keystroke.
Replace with a destructured read and a JSDoc contract stating that inputs
must be pre-normalized.
Co-authored-by: codex <codex@users.noreply.github.com>
@juliusmarmingejuliusmarminge changed the title Add provider skill discovery Add provider skill discoveryApr 11, 2026
@juliusmarminge

Copy link
Copy Markdown
MemberAuthor

@cursor push 20f5a4b

All callers already pass pre-normalized (trimmed and lowercased) inputs,
so the internal .trim().toLowerCase() calls were redundant O(n) string
operations allocating unnecessary copies on every candidate per keystroke.
Replace with a destructured read and a JSDoc contract stating that inputs
must be pre-normalized.
Applied via @cursor push command
@juliusmarminge
juliusmarminge merged commit 58e5f71 into mainApr 11, 2026
12 checks passed
@juliusmarminge
juliusmarminge deleted the t3code/server-provider-skills branch April 11, 2026 00:19
@juliusmarmingejuliusmarminge mentioned this pull request Apr 11, 2026
4 tasks
juliusmarminge added a commit that referenced this pull request Apr 13, 2026
Co-authored-by: Cursor Agent <cursoragent@cursor.com>
Co-authored-by: codex <codex@users.noreply.github.com>
Co-authored-by: cursor[bot] <206951365+cursor[bot]@users.noreply.github.com>
youpele52 referenced this pull request in youpele52/bigbud Jun 17, 2026
Co-authored-by: codex <codex@users.noreply.github.com>
Co-authored-by: cursor[bot] <206951365+cursor[bot]@users.noreply.github.com>
NeilTheFisher pushed a commit to NeilTheFisher/t3code that referenced this pull request Aug 18, 2026
Co-authored-by: Cursor Agent <cursoragent@cursor.com>
Co-authored-by: codex <codex@users.noreply.github.com>
Co-authored-by: cursor[bot] <206951365+cursor[bot]@users.noreply.github.com>
Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

size:XXL1,000+ changed lines (additions + deletions).vouch:trustedPR author is trusted by repo permissions or the VOUCHED list.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants

@juliusmarminge@cursoragent
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Strip utm_, fbclid, gclid, etc. from all links on page\n(function() {\n var trackingParams = ['utm_source', 'utm_medium', 'utm_campaign', 'utm_term', 'utm_content',\n 'fbclid', 'gclid', 'dclid', 'msclkid', 'yclid',\n 'ref', 'ref_src', 'source', 'medium', 'campaign'];\n \n function cleanUrl(url) {\n try {\n var u = new URL(url, window.location.origin);\n var changed = false;\n trackingParams.forEach(function(p) {\n if (u.searchParams.has(p)) {\n u.searchParams.delete(p);\n changed = true;\n }\n });\n return changed ? u.toString() : url;\n } catch (e) {\n return url;\n }\n }\n \n function cleanLinks() {\n document.querySelectorAll('a[href]').forEach(function(a) {\n var clean = cleanUrl(a.href);\n if (clean !== a.href) a.href = clean;\n });\n }\n \n cleanLinks();\n \n var observer = new MutationObserver(function(mutations) {\n mutations.forEach(function(m) {\n m.addedNodes.forEach(function(node) {\n if (node.nodeType === 1) {\n if (node.tagName === 'A') cleanLinks();\n node.querySelectorAll('a[href]').forEach(function(a) {\n var clean = cleanUrl(a.href);\n if (clean !== a.href) a.href = clean;\n });\n }\n });\n });\n });\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "Remove Tracking Parameters from Links"); } } catch(__e) { console.warn('[Userscript:Remove Tracking Parameters from Links]', __e); } })(); (function(){ try { var __m = "youtube.com"; var __re = new RegExp('^' + "youtube\\.com" + '
Skip to content

Add provider skill discovery - #1905

Merged
juliusmarminge merged 12 commits into
mainfrom
t3code/server-provider-skills
Apr 11, 2026
Merged

Add provider skill discovery#1905
juliusmarminge merged 12 commits into
mainfrom
t3code/server-provider-skills

Conversation

@juliusmarminge

@juliusmarmingejuliusmarminge commented Apr 10, 2026

Copy link
Copy Markdown
Member

Summary

  • Adds provider skill presentation and slash-command discovery so composer UI can surface provider capabilities more directly.
  • Updates server/provider orchestration and Codex app-server plumbing to carry the new skill metadata through session and turn flows.
  • Refactors several effect service tags and ID constructors to the newer ServiceMap/makeUnsafe patterns for consistency.
  • Adjusts CLI publish/package metadata and related tests to match the new build outputs and config behavior.

Testing

  • Not run
  • Existing unit and integration tests were updated alongside the feature changes
  • Full project checks still need to pass: bun fmt, bun lint, bun typecheck, and bun run test

Note

Medium Risk
Extends the ServerProvider contract and provider health/probing flows to carry new capability metadata, and updates chat composer parsing/rendering and menu ranking logic; regressions could affect provider snapshots or composer input behavior across clients.

Overview
Provider snapshots now include capability metadata: ServerProvider gains slashCommands and skills arrays (with decoding defaults for backward compatibility), and buildServerProvider populates them.

Server-side probing is extended to fill these fields: Claude’s SDK init probe now collects and dedupes slash commands (and caches the combined probe), while Codex switches from account-only probing to probeCodexDiscovery via the app-server JSON-RPC to return both account info and per-CWD skills.

The web composer UI now surfaces provider capabilities: it adds $skill token detection/rendering (Lexical ComposerSkillNode chips with tooltip descriptions), expands slash-command completion to include provider commands, adds skill search/completion, and refactors menu highlighting + ranking using a new shared searchRanking utility (also reused for workspace entry ranking). Tests and fixtures are updated accordingly.

Reviewed by Cursor Bugbot for commit 016dbfd. Bugbot is set up for automated code reviews on this repo. Configure here.

Note

Add provider skill discovery and skill/slash-command support in the composer

  • Adds ServerProviderSkill and ServerProviderSlashCommand schemas to the contracts layer; both default to empty arrays when decoding legacy snapshots.
  • Probes the Codex provider via a new probeCodexDiscovery API to return discovered skills alongside account info, and parses Claude Agent SDK initialization commands into normalized slash commands.
  • Introduces a ComposerSkillNode Lexical node that renders inline skill chips with tooltips, and extends splitPromptTextIntoComposerSegments to parse $<name> tokens as skill segments.
  • Extends the composer command menu to show ranked, grouped results for both provider slash commands and skills, with correct /<command> and $<skill> insertion on selection.
  • Extracts a shared searchRanking package (scoreQueryMatch, insertRankedSearchResult, etc.) used by workspace entry search, skill search, and slash command search.
  • Risk: ComposerPromptEditor now requires a skills prop; any caller that does not pass it will get a type error.

Macroscope summarized 016dbfd.

- Probe Codex skills and Claude slash commands during provider checks
- Surface discovered items in server snapshots and composer UI
@coderabbitai

coderabbitaiBot commented Apr 10, 2026

Copy link
Copy Markdown

Important

Review skipped

Auto reviews are disabled on this repository. Please check the settings in the CodeRabbit UI or the .coderabbit.yaml file in this repository. To trigger a single review, invoke the @coderabbitai review command.

⚙️ Run configuration

Configuration used: Repository UI

Review profile: CHILL

Plan: Pro

Run ID: 1385ec2d-bc74-4b7b-b23e-c104f25cb89c

You can disable this status message by setting the reviews.review_status to false in the CodeRabbit configuration file.

Use the checkbox below for a quick retry:

  • 🔍 Trigger review
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch t3code/server-provider-skills

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

@github-actionsgithub-actionsBot added size:XL 500-999 changed lines (additions + deletions). vouch:trusted PR author is trusted by repo permissions or the VOUCHED list. labels Apr 10, 2026

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

Cursor Bugbot has reviewed your changes and found 2 potential issues.

Autofix Details

Bugbot Autofix prepared fixes for both issues found in the latest run.

  • ✅ Fixed: Ref assignments moved to useEffect cause stale reads
    • Moved the three ref assignments (composerMenuOpenRef, composerMenuItemsRef, activeComposerMenuItemRef) back to synchronous render phase by removing the useEffect wrapper, ensuring event handlers always read current values.
  • ✅ Fixed: Exported probeCodexAccount function is now unused
    • Removed the dead probeCodexAccount function from codexAppServer.ts since it has no remaining imports anywhere in the codebase.

Create PR

Or push these changes by commenting:

@cursor push 2d23dae3cc
Preview (2d23dae3cc)
diff --git a/apps/server/src/provider/codexAppServer.ts b/apps/server/src/provider/codexAppServer.ts--- a/apps/server/src/provider/codexAppServer.ts+++ b/apps/server/src/provider/codexAppServer.ts@@ -244,16 +244,3 @@
});
});
}
--export async function probeCodexAccount(input: {- readonly binaryPath: string;- readonly homePath?: string;- readonly signal?: AbortSignal;-}): Promise<CodexAccountSnapshot> {- return (- await probeCodexDiscovery({- ...input,- cwd: process.cwd(),- })- ).account;-}diff --git a/apps/web/src/components/chat/ChatComposer.tsx b/apps/web/src/components/chat/ChatComposer.tsx--- a/apps/web/src/components/chat/ChatComposer.tsx+++ b/apps/web/src/components/chat/ChatComposer.tsx@@ -820,11 +820,9 @@
[composerHighlightedItemId, composerMenuItems],
);
- useEffect(() => {- composerMenuOpenRef.current = composerMenuOpen;- composerMenuItemsRef.current = composerMenuItems;- activeComposerMenuItemRef.current = activeComposerMenuItem;- }, [activeComposerMenuItem, composerMenuItems, composerMenuOpen]);+ composerMenuOpenRef.current = composerMenuOpen;+ composerMenuItemsRef.current = composerMenuItems;+ activeComposerMenuItemRef.current = activeComposerMenuItem;
const nonPersistedComposerImageIdSet = useMemo(
() => new Set(nonPersistedComposerImageIds),

You can send follow-ups to the cloud agent here.

Comment threadapps/web/src/components/chat/ChatComposer.tsx Outdated
Comment threadapps/server/src/provider/codexAppServer.ts Outdated
Comment threadapps/web/src/components/ComposerPromptEditor.tsx Outdated
Comment threadapps/web/src/components/ComposerPromptEditor.tsx
@macroscopeapp

macroscopeappBot commented Apr 10, 2026

Copy link
Copy Markdown
Contributor

Approvability

Verdict: Needs human review

This PR introduces a significant new feature: provider skill and slash command discovery. It adds new user-facing capabilities including skill autocomplete via $ syntax, skill pills in the composer, provider slash commands in the command menu, and supporting search/ranking infrastructure. New features of this scope warrant human review to validate the design and integration.

You can customize Macroscope's approvability policy. Learn more.

- Map provider slash command hints into the shared contract
- Surface provider command metadata in the chat composer

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

Cursor Bugbot has reviewed your changes and found 1 potential issue.

There are 3 total unresolved issues (including 2 from previous reviews).

Autofix Details

Bugbot Autofix prepared a fix for the issue found in the latest run.

  • ✅ Fixed: skills/list failure rejects entire account probe
    • Changed the skills/list error handler to gracefully fall back to an empty skills array instead of calling fail(), so account probing remains resilient when skills/list is unsupported or errors.

Create PR

Or push these changes by commenting:

@cursor push 26dfbbe0ac
Preview (26dfbbe0ac)
diff --git a/apps/server/src/provider/codexAppServer.ts b/apps/server/src/provider/codexAppServer.ts--- a/apps/server/src/provider/codexAppServer.ts+++ b/apps/server/src/provider/codexAppServer.ts@@ -205,12 +205,7 @@
if (response.id === 2) {
const errorMessage = readErrorMessage(response);
- if (errorMessage) {- fail(new Error(`skills/list failed: ${errorMessage}`));- return;- }-- skills = parseCodexSkillsResult(response.result, input.cwd);+ skills = errorMessage ? [] : parseCodexSkillsResult(response.result, input.cwd);
maybeResolve();
return;
}

You can send follow-ups to the cloud agent here.

Comment threadapps/server/src/provider/codexAppServer.ts
cursoragentand others added 3 commits April 10, 2026 22:56
…tire probe
When skills/list returns an error (e.g. on older Codex CLI versions that
don't support it), fall back to an empty skills array instead of calling
fail() which would reject the entire discovery promise and break account
probing.
Co-authored-by: codex <codex@users.noreply.github.com>
- Restore serialized composer skill node state
- Sync skill labels before paint to avoid stale UI
- Keep composer menu refs current during render
@juliusmarminge

Copy link
Copy Markdown
MemberAuthor

@cursor push 26dfbbe

…tire probe
When skills/list returns an error (e.g. on older Codex CLI versions that
don't support it), fall back to an empty skills array instead of calling
fail() which would reject the entire discovery promise and break account
probing.
Applied via @cursor push command
@juliusmarmingejuliusmarminge changed the title Add provider skill discovery to Codex sessionsAdd provider skill discovery Apr 10, 2026

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

Cursor Bugbot has reviewed your changes and found 1 potential issue.

Autofix Details

Bugbot Autofix prepared a fix for the issue found in the latest run.

  • ✅ Fixed: Inconsistent field lookup for displayName vs shortDescription
    • Updated displayName lookup to check skill?.displayName first, falling back to display?.displayName, matching the same pattern used for shortDescription.

Create PR

Or push these changes by commenting:

@cursor push 6b028d659a
Preview (6b028d659a)
diff --git a/apps/server/src/provider/codexAppServer.ts b/apps/server/src/provider/codexAppServer.ts--- a/apps/server/src/provider/codexAppServer.ts+++ b/apps/server/src/provider/codexAppServer.ts@@ -64,8 +64,11 @@
? { description: nonEmptyTrimmed(skill?.description) }
: {}),
...(nonEmptyTrimmed(skill?.scope) ? { scope: nonEmptyTrimmed(skill?.scope) } : {}),
- ...(nonEmptyTrimmed(display?.displayName)- ? { displayName: nonEmptyTrimmed(display?.displayName) }+ ...(nonEmptyTrimmed(skill?.displayName) || nonEmptyTrimmed(display?.displayName)+ ? {+ displayName:+ nonEmptyTrimmed(skill?.displayName) ?? nonEmptyTrimmed(display?.displayName),+ }
: {}),
...(nonEmptyTrimmed(skill?.shortDescription) || nonEmptyTrimmed(display?.shortDescription)
? {

You can send follow-ups to the cloud agent here.

Comment threadapps/server/src/provider/codexAppServer.ts
- Introduced a new scoring mechanism for workspace entries that prioritizes exact basename matches over broader path matches.
- Updated the search logic to utilize shared ranking functions for improved performance and maintainability.
- Added a test case to validate the new ranking behavior for exact matches in workspace entries.
- Removed deprecated functions related to scoring and ranking to streamline the codebase.
@github-actionsgithub-actionsBot added size:XXL 1,000+ changed lines (additions + deletions). and removed size:XL 500-999 changed lines (additions + deletions). labels Apr 10, 2026

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

Cursor Bugbot has reviewed your changes and found 1 potential issue.

Autofix Details

Bugbot Autofix prepared a fix for the issue found in the latest run.

  • ✅ Fixed: Callback recreated on every keystroke causing unnecessary re-renders
    • Replaced the prompt state variable with promptRef.current in the setPromptFromTraits callback and removed prompt from the dependency array, restoring the stable ref-based pattern that prevents callback recreation on every keystroke.

Create PR

Or push these changes by commenting:

@cursor push aadef2980e
Preview (aadef2980e)
diff --git a/apps/web/src/components/chat/ChatComposer.tsx b/apps/web/src/components/chat/ChatComposer.tsx--- a/apps/web/src/components/chat/ChatComposer.tsx+++ b/apps/web/src/components/chat/ChatComposer.tsx@@ -868,7 +868,8 @@
// ------------------------------------------------------------------
const setPromptFromTraits = useCallback(
(nextPrompt: string) => {
- if (nextPrompt === prompt) {+ const currentPrompt = promptRef.current;+ if (nextPrompt === currentPrompt) {
scheduleComposerFocus();
return;
}
@@ -879,7 +880,7 @@
setComposerTrigger(detectComposerTrigger(nextPrompt, nextPrompt.length));
scheduleComposerFocus();
},
- [composerDraftTarget, prompt, promptRef, scheduleComposerFocus, setComposerDraftPrompt],+ [composerDraftTarget, promptRef, scheduleComposerFocus, setComposerDraftPrompt],
);
const providerTraitsMenuContent = renderProviderTraitsMenuContent({

You can send follow-ups to the cloud agent here.

Comment threadapps/web/src/components/chat/ChatComposer.tsx Outdated
Co-authored-by: codex <codex@users.noreply.github.com>

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

Cursor Bugbot has reviewed your changes and found 1 potential issue.

Fix All in Cursor

Bugbot Autofix prepared a fix for the issue found in the latest run.

  • ✅ Fixed: Double-lowercasing in shared scoring utility is redundant
    • Removed the redundant .trim().toLowerCase() calls inside scoreQueryMatch since all callers already pass pre-normalized inputs, replacing them with a direct destructure and a JSDoc contract documenting the pre-normalization requirement.

Create PR

Or push these changes by commenting:

@cursor push 20f5a4b15c
Preview (20f5a4b15c)
diff --git a/packages/shared/src/searchRanking.ts b/packages/shared/src/searchRanking.ts--- a/packages/shared/src/searchRanking.ts+++ b/packages/shared/src/searchRanking.ts@@ -77,6 +77,12 @@
return bestIndex;
}
+/**+ * Scores how well `value` matches `query` using tiered match strategies.+ *+ * **Expects pre-normalized inputs**: both `value` and `query` must already be+ * trimmed and lowercased (e.g. via {@link normalizeSearchQuery}).+ */
export function scoreQueryMatch(input: {
value: string;
query: string;
@@ -87,8 +93,7 @@
fuzzyBase?: number;
boundaryMarkers?: readonly string[];
}): number | null {
- const value = input.value.trim().toLowerCase();- const query = input.query.trim().toLowerCase();+ const { value, query } = input;
if (!value || !query) {
return null;

You can send follow-ups to the cloud agent here.

Reviewed by Cursor Bugbot for commit b0488e2. Configure here.

Comment threadpackages/shared/src/searchRanking.ts Outdated
cursoragentand others added 2 commits April 10, 2026 23:54
All callers already pass pre-normalized (trimmed and lowercased) inputs,
so the internal .trim().toLowerCase() calls were redundant O(n) string
operations allocating unnecessary copies on every candidate per keystroke.
Replace with a destructured read and a JSDoc contract stating that inputs
must be pre-normalized.
Co-authored-by: codex <codex@users.noreply.github.com>
@juliusmarmingejuliusmarminge changed the title Add provider skill discovery Add provider skill discoveryApr 11, 2026
@juliusmarminge

Copy link
Copy Markdown
MemberAuthor

@cursor push 20f5a4b

All callers already pass pre-normalized (trimmed and lowercased) inputs,
so the internal .trim().toLowerCase() calls were redundant O(n) string
operations allocating unnecessary copies on every candidate per keystroke.
Replace with a destructured read and a JSDoc contract stating that inputs
must be pre-normalized.
Applied via @cursor push command
@juliusmarminge
juliusmarminge merged commit 58e5f71 into mainApr 11, 2026
12 checks passed
@juliusmarminge
juliusmarminge deleted the t3code/server-provider-skills branch April 11, 2026 00:19
@juliusmarmingejuliusmarminge mentioned this pull request Apr 11, 2026
4 tasks
juliusmarminge added a commit that referenced this pull request Apr 13, 2026
Co-authored-by: Cursor Agent <cursoragent@cursor.com>
Co-authored-by: codex <codex@users.noreply.github.com>
Co-authored-by: cursor[bot] <206951365+cursor[bot]@users.noreply.github.com>
youpele52 referenced this pull request in youpele52/bigbud Jun 17, 2026
Co-authored-by: codex <codex@users.noreply.github.com>
Co-authored-by: cursor[bot] <206951365+cursor[bot]@users.noreply.github.com>
NeilTheFisher pushed a commit to NeilTheFisher/t3code that referenced this pull request Aug 18, 2026
Co-authored-by: Cursor Agent <cursoragent@cursor.com>
Co-authored-by: codex <codex@users.noreply.github.com>
Co-authored-by: cursor[bot] <206951365+cursor[bot]@users.noreply.github.com>
Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

size:XXL1,000+ changed lines (additions + deletions).vouch:trustedPR author is trusted by repo permissions or the VOUCHED list.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants

@juliusmarminge@cursoragent
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Auto-enable theater mode on YouTube\n(function() {\n function tryTheater() {\n var btn = document.querySelector('button[aria-label=\"Theater mode\"], ytd-player #player button[title=\"Theater mode\"]');\n if (btn && !btn.classList.contains('activated')) {\n btn.click();\n }\n }\n \n // Try immediately\n tryTheater();\n \n // Try after navigation (SPA)\n var lastUrl = location.href;\n setInterval(function() {\n if (location.href !== lastUrl) {\n lastUrl = location.href;\n setTimeout(tryTheater, 500);\n }\n }, 1000);\n \n // Also try on player load\n var observer = new MutationObserver(tryTheater);\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "YouTube Theater Mode Default"); } } catch(__e) { console.warn('[Userscript:YouTube Theater Mode Default]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content

Add provider skill discovery - #1905

Merged
juliusmarminge merged 12 commits into
mainfrom
t3code/server-provider-skills
Apr 11, 2026
Merged

Add provider skill discovery#1905
juliusmarminge merged 12 commits into
mainfrom
t3code/server-provider-skills

Conversation

@juliusmarminge

@juliusmarmingejuliusmarminge commented Apr 10, 2026

Copy link
Copy Markdown
Member

Summary

  • Adds provider skill presentation and slash-command discovery so composer UI can surface provider capabilities more directly.
  • Updates server/provider orchestration and Codex app-server plumbing to carry the new skill metadata through session and turn flows.
  • Refactors several effect service tags and ID constructors to the newer ServiceMap/makeUnsafe patterns for consistency.
  • Adjusts CLI publish/package metadata and related tests to match the new build outputs and config behavior.

Testing

  • Not run
  • Existing unit and integration tests were updated alongside the feature changes
  • Full project checks still need to pass: bun fmt, bun lint, bun typecheck, and bun run test

Note

Medium Risk
Extends the ServerProvider contract and provider health/probing flows to carry new capability metadata, and updates chat composer parsing/rendering and menu ranking logic; regressions could affect provider snapshots or composer input behavior across clients.

Overview
Provider snapshots now include capability metadata: ServerProvider gains slashCommands and skills arrays (with decoding defaults for backward compatibility), and buildServerProvider populates them.

Server-side probing is extended to fill these fields: Claude’s SDK init probe now collects and dedupes slash commands (and caches the combined probe), while Codex switches from account-only probing to probeCodexDiscovery via the app-server JSON-RPC to return both account info and per-CWD skills.

The web composer UI now surfaces provider capabilities: it adds $skill token detection/rendering (Lexical ComposerSkillNode chips with tooltip descriptions), expands slash-command completion to include provider commands, adds skill search/completion, and refactors menu highlighting + ranking using a new shared searchRanking utility (also reused for workspace entry ranking). Tests and fixtures are updated accordingly.

Reviewed by Cursor Bugbot for commit 016dbfd. Bugbot is set up for automated code reviews on this repo. Configure here.

Note

Add provider skill discovery and skill/slash-command support in the composer

  • Adds ServerProviderSkill and ServerProviderSlashCommand schemas to the contracts layer; both default to empty arrays when decoding legacy snapshots.
  • Probes the Codex provider via a new probeCodexDiscovery API to return discovered skills alongside account info, and parses Claude Agent SDK initialization commands into normalized slash commands.
  • Introduces a ComposerSkillNode Lexical node that renders inline skill chips with tooltips, and extends splitPromptTextIntoComposerSegments to parse $<name> tokens as skill segments.
  • Extends the composer command menu to show ranked, grouped results for both provider slash commands and skills, with correct /<command> and $<skill> insertion on selection.
  • Extracts a shared searchRanking package (scoreQueryMatch, insertRankedSearchResult, etc.) used by workspace entry search, skill search, and slash command search.
  • Risk: ComposerPromptEditor now requires a skills prop; any caller that does not pass it will get a type error.

Macroscope summarized 016dbfd.

- Probe Codex skills and Claude slash commands during provider checks
- Surface discovered items in server snapshots and composer UI
@coderabbitai

coderabbitaiBot commented Apr 10, 2026

Copy link
Copy Markdown

Important

Review skipped

Auto reviews are disabled on this repository. Please check the settings in the CodeRabbit UI or the .coderabbit.yaml file in this repository. To trigger a single review, invoke the @coderabbitai review command.

⚙️ Run configuration

Configuration used: Repository UI

Review profile: CHILL

Plan: Pro

Run ID: 1385ec2d-bc74-4b7b-b23e-c104f25cb89c

You can disable this status message by setting the reviews.review_status to false in the CodeRabbit configuration file.

Use the checkbox below for a quick retry:

  • 🔍 Trigger review
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch t3code/server-provider-skills

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

@github-actionsgithub-actionsBot added size:XL 500-999 changed lines (additions + deletions). vouch:trusted PR author is trusted by repo permissions or the VOUCHED list. labels Apr 10, 2026

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

Cursor Bugbot has reviewed your changes and found 2 potential issues.

Autofix Details

Bugbot Autofix prepared fixes for both issues found in the latest run.

  • ✅ Fixed: Ref assignments moved to useEffect cause stale reads
    • Moved the three ref assignments (composerMenuOpenRef, composerMenuItemsRef, activeComposerMenuItemRef) back to synchronous render phase by removing the useEffect wrapper, ensuring event handlers always read current values.
  • ✅ Fixed: Exported probeCodexAccount function is now unused
    • Removed the dead probeCodexAccount function from codexAppServer.ts since it has no remaining imports anywhere in the codebase.

Create PR

Or push these changes by commenting:

@cursor push 2d23dae3cc
Preview (2d23dae3cc)
diff --git a/apps/server/src/provider/codexAppServer.ts b/apps/server/src/provider/codexAppServer.ts--- a/apps/server/src/provider/codexAppServer.ts+++ b/apps/server/src/provider/codexAppServer.ts@@ -244,16 +244,3 @@
});
});
}
--export async function probeCodexAccount(input: {- readonly binaryPath: string;- readonly homePath?: string;- readonly signal?: AbortSignal;-}): Promise<CodexAccountSnapshot> {- return (- await probeCodexDiscovery({- ...input,- cwd: process.cwd(),- })- ).account;-}diff --git a/apps/web/src/components/chat/ChatComposer.tsx b/apps/web/src/components/chat/ChatComposer.tsx--- a/apps/web/src/components/chat/ChatComposer.tsx+++ b/apps/web/src/components/chat/ChatComposer.tsx@@ -820,11 +820,9 @@
[composerHighlightedItemId, composerMenuItems],
);
- useEffect(() => {- composerMenuOpenRef.current = composerMenuOpen;- composerMenuItemsRef.current = composerMenuItems;- activeComposerMenuItemRef.current = activeComposerMenuItem;- }, [activeComposerMenuItem, composerMenuItems, composerMenuOpen]);+ composerMenuOpenRef.current = composerMenuOpen;+ composerMenuItemsRef.current = composerMenuItems;+ activeComposerMenuItemRef.current = activeComposerMenuItem;
const nonPersistedComposerImageIdSet = useMemo(
() => new Set(nonPersistedComposerImageIds),

You can send follow-ups to the cloud agent here.

Comment threadapps/web/src/components/chat/ChatComposer.tsx Outdated
Comment threadapps/server/src/provider/codexAppServer.ts Outdated
Comment threadapps/web/src/components/ComposerPromptEditor.tsx Outdated
Comment threadapps/web/src/components/ComposerPromptEditor.tsx
@macroscopeapp

macroscopeappBot commented Apr 10, 2026

Copy link
Copy Markdown
Contributor

Approvability

Verdict: Needs human review

This PR introduces a significant new feature: provider skill and slash command discovery. It adds new user-facing capabilities including skill autocomplete via $ syntax, skill pills in the composer, provider slash commands in the command menu, and supporting search/ranking infrastructure. New features of this scope warrant human review to validate the design and integration.

You can customize Macroscope's approvability policy. Learn more.

- Map provider slash command hints into the shared contract
- Surface provider command metadata in the chat composer

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

Cursor Bugbot has reviewed your changes and found 1 potential issue.

There are 3 total unresolved issues (including 2 from previous reviews).

Autofix Details

Bugbot Autofix prepared a fix for the issue found in the latest run.

  • ✅ Fixed: skills/list failure rejects entire account probe
    • Changed the skills/list error handler to gracefully fall back to an empty skills array instead of calling fail(), so account probing remains resilient when skills/list is unsupported or errors.

Create PR

Or push these changes by commenting:

@cursor push 26dfbbe0ac
Preview (26dfbbe0ac)
diff --git a/apps/server/src/provider/codexAppServer.ts b/apps/server/src/provider/codexAppServer.ts--- a/apps/server/src/provider/codexAppServer.ts+++ b/apps/server/src/provider/codexAppServer.ts@@ -205,12 +205,7 @@
if (response.id === 2) {
const errorMessage = readErrorMessage(response);
- if (errorMessage) {- fail(new Error(`skills/list failed: ${errorMessage}`));- return;- }-- skills = parseCodexSkillsResult(response.result, input.cwd);+ skills = errorMessage ? [] : parseCodexSkillsResult(response.result, input.cwd);
maybeResolve();
return;
}

You can send follow-ups to the cloud agent here.

Comment threadapps/server/src/provider/codexAppServer.ts
cursoragentand others added 3 commits April 10, 2026 22:56
…tire probe
When skills/list returns an error (e.g. on older Codex CLI versions that
don't support it), fall back to an empty skills array instead of calling
fail() which would reject the entire discovery promise and break account
probing.
Co-authored-by: codex <codex@users.noreply.github.com>
- Restore serialized composer skill node state
- Sync skill labels before paint to avoid stale UI
- Keep composer menu refs current during render
@juliusmarminge

Copy link
Copy Markdown
MemberAuthor

@cursor push 26dfbbe

…tire probe
When skills/list returns an error (e.g. on older Codex CLI versions that
don't support it), fall back to an empty skills array instead of calling
fail() which would reject the entire discovery promise and break account
probing.
Applied via @cursor push command
@juliusmarmingejuliusmarminge changed the title Add provider skill discovery to Codex sessionsAdd provider skill discovery Apr 10, 2026

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

Cursor Bugbot has reviewed your changes and found 1 potential issue.

Autofix Details

Bugbot Autofix prepared a fix for the issue found in the latest run.

  • ✅ Fixed: Inconsistent field lookup for displayName vs shortDescription
    • Updated displayName lookup to check skill?.displayName first, falling back to display?.displayName, matching the same pattern used for shortDescription.

Create PR

Or push these changes by commenting:

@cursor push 6b028d659a
Preview (6b028d659a)
diff --git a/apps/server/src/provider/codexAppServer.ts b/apps/server/src/provider/codexAppServer.ts--- a/apps/server/src/provider/codexAppServer.ts+++ b/apps/server/src/provider/codexAppServer.ts@@ -64,8 +64,11 @@
? { description: nonEmptyTrimmed(skill?.description) }
: {}),
...(nonEmptyTrimmed(skill?.scope) ? { scope: nonEmptyTrimmed(skill?.scope) } : {}),
- ...(nonEmptyTrimmed(display?.displayName)- ? { displayName: nonEmptyTrimmed(display?.displayName) }+ ...(nonEmptyTrimmed(skill?.displayName) || nonEmptyTrimmed(display?.displayName)+ ? {+ displayName:+ nonEmptyTrimmed(skill?.displayName) ?? nonEmptyTrimmed(display?.displayName),+ }
: {}),
...(nonEmptyTrimmed(skill?.shortDescription) || nonEmptyTrimmed(display?.shortDescription)
? {

You can send follow-ups to the cloud agent here.

Comment threadapps/server/src/provider/codexAppServer.ts
- Introduced a new scoring mechanism for workspace entries that prioritizes exact basename matches over broader path matches.
- Updated the search logic to utilize shared ranking functions for improved performance and maintainability.
- Added a test case to validate the new ranking behavior for exact matches in workspace entries.
- Removed deprecated functions related to scoring and ranking to streamline the codebase.
@github-actionsgithub-actionsBot added size:XXL 1,000+ changed lines (additions + deletions). and removed size:XL 500-999 changed lines (additions + deletions). labels Apr 10, 2026

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

Cursor Bugbot has reviewed your changes and found 1 potential issue.

Autofix Details

Bugbot Autofix prepared a fix for the issue found in the latest run.

  • ✅ Fixed: Callback recreated on every keystroke causing unnecessary re-renders
    • Replaced the prompt state variable with promptRef.current in the setPromptFromTraits callback and removed prompt from the dependency array, restoring the stable ref-based pattern that prevents callback recreation on every keystroke.

Create PR

Or push these changes by commenting:

@cursor push aadef2980e
Preview (aadef2980e)
diff --git a/apps/web/src/components/chat/ChatComposer.tsx b/apps/web/src/components/chat/ChatComposer.tsx--- a/apps/web/src/components/chat/ChatComposer.tsx+++ b/apps/web/src/components/chat/ChatComposer.tsx@@ -868,7 +868,8 @@
// ------------------------------------------------------------------
const setPromptFromTraits = useCallback(
(nextPrompt: string) => {
- if (nextPrompt === prompt) {+ const currentPrompt = promptRef.current;+ if (nextPrompt === currentPrompt) {
scheduleComposerFocus();
return;
}
@@ -879,7 +880,7 @@
setComposerTrigger(detectComposerTrigger(nextPrompt, nextPrompt.length));
scheduleComposerFocus();
},
- [composerDraftTarget, prompt, promptRef, scheduleComposerFocus, setComposerDraftPrompt],+ [composerDraftTarget, promptRef, scheduleComposerFocus, setComposerDraftPrompt],
);
const providerTraitsMenuContent = renderProviderTraitsMenuContent({

You can send follow-ups to the cloud agent here.

Comment threadapps/web/src/components/chat/ChatComposer.tsx Outdated
Co-authored-by: codex <codex@users.noreply.github.com>

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

Cursor Bugbot has reviewed your changes and found 1 potential issue.

Fix All in Cursor

Bugbot Autofix prepared a fix for the issue found in the latest run.

  • ✅ Fixed: Double-lowercasing in shared scoring utility is redundant
    • Removed the redundant .trim().toLowerCase() calls inside scoreQueryMatch since all callers already pass pre-normalized inputs, replacing them with a direct destructure and a JSDoc contract documenting the pre-normalization requirement.

Create PR

Or push these changes by commenting:

@cursor push 20f5a4b15c
Preview (20f5a4b15c)
diff --git a/packages/shared/src/searchRanking.ts b/packages/shared/src/searchRanking.ts--- a/packages/shared/src/searchRanking.ts+++ b/packages/shared/src/searchRanking.ts@@ -77,6 +77,12 @@
return bestIndex;
}
+/**+ * Scores how well `value` matches `query` using tiered match strategies.+ *+ * **Expects pre-normalized inputs**: both `value` and `query` must already be+ * trimmed and lowercased (e.g. via {@link normalizeSearchQuery}).+ */
export function scoreQueryMatch(input: {
value: string;
query: string;
@@ -87,8 +93,7 @@
fuzzyBase?: number;
boundaryMarkers?: readonly string[];
}): number | null {
- const value = input.value.trim().toLowerCase();- const query = input.query.trim().toLowerCase();+ const { value, query } = input;
if (!value || !query) {
return null;

You can send follow-ups to the cloud agent here.

Reviewed by Cursor Bugbot for commit b0488e2. Configure here.

Comment threadpackages/shared/src/searchRanking.ts Outdated
cursoragentand others added 2 commits April 10, 2026 23:54
All callers already pass pre-normalized (trimmed and lowercased) inputs,
so the internal .trim().toLowerCase() calls were redundant O(n) string
operations allocating unnecessary copies on every candidate per keystroke.
Replace with a destructured read and a JSDoc contract stating that inputs
must be pre-normalized.
Co-authored-by: codex <codex@users.noreply.github.com>
@juliusmarmingejuliusmarminge changed the title Add provider skill discovery Add provider skill discoveryApr 11, 2026
@juliusmarminge

Copy link
Copy Markdown
MemberAuthor

@cursor push 20f5a4b

All callers already pass pre-normalized (trimmed and lowercased) inputs,
so the internal .trim().toLowerCase() calls were redundant O(n) string
operations allocating unnecessary copies on every candidate per keystroke.
Replace with a destructured read and a JSDoc contract stating that inputs
must be pre-normalized.
Applied via @cursor push command
@juliusmarminge
juliusmarminge merged commit 58e5f71 into mainApr 11, 2026
12 checks passed
@juliusmarminge
juliusmarminge deleted the t3code/server-provider-skills branch April 11, 2026 00:19
@juliusmarmingejuliusmarminge mentioned this pull request Apr 11, 2026
4 tasks
juliusmarminge added a commit that referenced this pull request Apr 13, 2026
Co-authored-by: Cursor Agent <cursoragent@cursor.com>
Co-authored-by: codex <codex@users.noreply.github.com>
Co-authored-by: cursor[bot] <206951365+cursor[bot]@users.noreply.github.com>
youpele52 referenced this pull request in youpele52/bigbud Jun 17, 2026
Co-authored-by: codex <codex@users.noreply.github.com>
Co-authored-by: cursor[bot] <206951365+cursor[bot]@users.noreply.github.com>
NeilTheFisher pushed a commit to NeilTheFisher/t3code that referenced this pull request Aug 18, 2026
Co-authored-by: Cursor Agent <cursoragent@cursor.com>
Co-authored-by: codex <codex@users.noreply.github.com>
Co-authored-by: cursor[bot] <206951365+cursor[bot]@users.noreply.github.com>
Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

size:XXL1,000+ changed lines (additions + deletions).vouch:trustedPR author is trusted by repo permissions or the VOUCHED list.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants

@juliusmarminge@cursoragent
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Remove or un-stick sticky/fixed headers that block content\n(function() {\n function unstick() {\n document.querySelectorAll('header, nav, [role=\"banner\"], .header, .navbar, .sticky, .fixed-top, [style*=\"position: fixed\"], [style*=\"position:sticky\"]').forEach(function(el) {\n if (el.style.position === 'fixed' || el.style.position === 'sticky' || \n getComputedStyle(el).position === 'fixed' || getComputedStyle(el).position === 'sticky') {\n el.style.position = 'static';\n el.style.top = 'auto';\n el.style.zIndex = 'auto';\n }\n });\n }\n \n unstick();\n \n var observer = new MutationObserver(unstick);\n observer.observe(document.body, { childList: true, subtree: true, attributes: true, attributeFilter: ['style', 'class'] });\n})();", "Kill Sticky Headers"); } } catch(__e) { console.warn('[Userscript:Kill Sticky Headers]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content

Add provider skill discovery - #1905

Merged
juliusmarminge merged 12 commits into
mainfrom
t3code/server-provider-skills
Apr 11, 2026
Merged

Add provider skill discovery#1905
juliusmarminge merged 12 commits into
mainfrom
t3code/server-provider-skills

Conversation

@juliusmarminge

@juliusmarmingejuliusmarminge commented Apr 10, 2026

Copy link
Copy Markdown
Member

Summary

  • Adds provider skill presentation and slash-command discovery so composer UI can surface provider capabilities more directly.
  • Updates server/provider orchestration and Codex app-server plumbing to carry the new skill metadata through session and turn flows.
  • Refactors several effect service tags and ID constructors to the newer ServiceMap/makeUnsafe patterns for consistency.
  • Adjusts CLI publish/package metadata and related tests to match the new build outputs and config behavior.

Testing

  • Not run
  • Existing unit and integration tests were updated alongside the feature changes
  • Full project checks still need to pass: bun fmt, bun lint, bun typecheck, and bun run test

Note

Medium Risk
Extends the ServerProvider contract and provider health/probing flows to carry new capability metadata, and updates chat composer parsing/rendering and menu ranking logic; regressions could affect provider snapshots or composer input behavior across clients.

Overview
Provider snapshots now include capability metadata: ServerProvider gains slashCommands and skills arrays (with decoding defaults for backward compatibility), and buildServerProvider populates them.

Server-side probing is extended to fill these fields: Claude’s SDK init probe now collects and dedupes slash commands (and caches the combined probe), while Codex switches from account-only probing to probeCodexDiscovery via the app-server JSON-RPC to return both account info and per-CWD skills.

The web composer UI now surfaces provider capabilities: it adds $skill token detection/rendering (Lexical ComposerSkillNode chips with tooltip descriptions), expands slash-command completion to include provider commands, adds skill search/completion, and refactors menu highlighting + ranking using a new shared searchRanking utility (also reused for workspace entry ranking). Tests and fixtures are updated accordingly.

Reviewed by Cursor Bugbot for commit 016dbfd. Bugbot is set up for automated code reviews on this repo. Configure here.

Note

Add provider skill discovery and skill/slash-command support in the composer

  • Adds ServerProviderSkill and ServerProviderSlashCommand schemas to the contracts layer; both default to empty arrays when decoding legacy snapshots.
  • Probes the Codex provider via a new probeCodexDiscovery API to return discovered skills alongside account info, and parses Claude Agent SDK initialization commands into normalized slash commands.
  • Introduces a ComposerSkillNode Lexical node that renders inline skill chips with tooltips, and extends splitPromptTextIntoComposerSegments to parse $<name> tokens as skill segments.
  • Extends the composer command menu to show ranked, grouped results for both provider slash commands and skills, with correct /<command> and $<skill> insertion on selection.
  • Extracts a shared searchRanking package (scoreQueryMatch, insertRankedSearchResult, etc.) used by workspace entry search, skill search, and slash command search.
  • Risk: ComposerPromptEditor now requires a skills prop; any caller that does not pass it will get a type error.

Macroscope summarized 016dbfd.

- Probe Codex skills and Claude slash commands during provider checks
- Surface discovered items in server snapshots and composer UI
@coderabbitai

coderabbitaiBot commented Apr 10, 2026

Copy link
Copy Markdown

Important

Review skipped

Auto reviews are disabled on this repository. Please check the settings in the CodeRabbit UI or the .coderabbit.yaml file in this repository. To trigger a single review, invoke the @coderabbitai review command.

⚙️ Run configuration

Configuration used: Repository UI

Review profile: CHILL

Plan: Pro

Run ID: 1385ec2d-bc74-4b7b-b23e-c104f25cb89c

You can disable this status message by setting the reviews.review_status to false in the CodeRabbit configuration file.

Use the checkbox below for a quick retry:

  • 🔍 Trigger review
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch t3code/server-provider-skills

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

@github-actionsgithub-actionsBot added size:XL 500-999 changed lines (additions + deletions). vouch:trusted PR author is trusted by repo permissions or the VOUCHED list. labels Apr 10, 2026

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

Cursor Bugbot has reviewed your changes and found 2 potential issues.

Autofix Details

Bugbot Autofix prepared fixes for both issues found in the latest run.

  • ✅ Fixed: Ref assignments moved to useEffect cause stale reads
    • Moved the three ref assignments (composerMenuOpenRef, composerMenuItemsRef, activeComposerMenuItemRef) back to synchronous render phase by removing the useEffect wrapper, ensuring event handlers always read current values.
  • ✅ Fixed: Exported probeCodexAccount function is now unused
    • Removed the dead probeCodexAccount function from codexAppServer.ts since it has no remaining imports anywhere in the codebase.

Create PR

Or push these changes by commenting:

@cursor push 2d23dae3cc
Preview (2d23dae3cc)
diff --git a/apps/server/src/provider/codexAppServer.ts b/apps/server/src/provider/codexAppServer.ts--- a/apps/server/src/provider/codexAppServer.ts+++ b/apps/server/src/provider/codexAppServer.ts@@ -244,16 +244,3 @@
});
});
}
--export async function probeCodexAccount(input: {- readonly binaryPath: string;- readonly homePath?: string;- readonly signal?: AbortSignal;-}): Promise<CodexAccountSnapshot> {- return (- await probeCodexDiscovery({- ...input,- cwd: process.cwd(),- })- ).account;-}diff --git a/apps/web/src/components/chat/ChatComposer.tsx b/apps/web/src/components/chat/ChatComposer.tsx--- a/apps/web/src/components/chat/ChatComposer.tsx+++ b/apps/web/src/components/chat/ChatComposer.tsx@@ -820,11 +820,9 @@
[composerHighlightedItemId, composerMenuItems],
);
- useEffect(() => {- composerMenuOpenRef.current = composerMenuOpen;- composerMenuItemsRef.current = composerMenuItems;- activeComposerMenuItemRef.current = activeComposerMenuItem;- }, [activeComposerMenuItem, composerMenuItems, composerMenuOpen]);+ composerMenuOpenRef.current = composerMenuOpen;+ composerMenuItemsRef.current = composerMenuItems;+ activeComposerMenuItemRef.current = activeComposerMenuItem;
const nonPersistedComposerImageIdSet = useMemo(
() => new Set(nonPersistedComposerImageIds),

You can send follow-ups to the cloud agent here.

Comment threadapps/web/src/components/chat/ChatComposer.tsx Outdated
Comment threadapps/server/src/provider/codexAppServer.ts Outdated
Comment threadapps/web/src/components/ComposerPromptEditor.tsx Outdated
Comment threadapps/web/src/components/ComposerPromptEditor.tsx
@macroscopeapp

macroscopeappBot commented Apr 10, 2026

Copy link
Copy Markdown
Contributor

Approvability

Verdict: Needs human review

This PR introduces a significant new feature: provider skill and slash command discovery. It adds new user-facing capabilities including skill autocomplete via $ syntax, skill pills in the composer, provider slash commands in the command menu, and supporting search/ranking infrastructure. New features of this scope warrant human review to validate the design and integration.

You can customize Macroscope's approvability policy. Learn more.

- Map provider slash command hints into the shared contract
- Surface provider command metadata in the chat composer

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

Cursor Bugbot has reviewed your changes and found 1 potential issue.

There are 3 total unresolved issues (including 2 from previous reviews).

Autofix Details

Bugbot Autofix prepared a fix for the issue found in the latest run.

  • ✅ Fixed: skills/list failure rejects entire account probe
    • Changed the skills/list error handler to gracefully fall back to an empty skills array instead of calling fail(), so account probing remains resilient when skills/list is unsupported or errors.

Create PR

Or push these changes by commenting:

@cursor push 26dfbbe0ac
Preview (26dfbbe0ac)
diff --git a/apps/server/src/provider/codexAppServer.ts b/apps/server/src/provider/codexAppServer.ts--- a/apps/server/src/provider/codexAppServer.ts+++ b/apps/server/src/provider/codexAppServer.ts@@ -205,12 +205,7 @@
if (response.id === 2) {
const errorMessage = readErrorMessage(response);
- if (errorMessage) {- fail(new Error(`skills/list failed: ${errorMessage}`));- return;- }-- skills = parseCodexSkillsResult(response.result, input.cwd);+ skills = errorMessage ? [] : parseCodexSkillsResult(response.result, input.cwd);
maybeResolve();
return;
}

You can send follow-ups to the cloud agent here.

Comment threadapps/server/src/provider/codexAppServer.ts
cursoragentand others added 3 commits April 10, 2026 22:56
…tire probe
When skills/list returns an error (e.g. on older Codex CLI versions that
don't support it), fall back to an empty skills array instead of calling
fail() which would reject the entire discovery promise and break account
probing.
Co-authored-by: codex <codex@users.noreply.github.com>
- Restore serialized composer skill node state
- Sync skill labels before paint to avoid stale UI
- Keep composer menu refs current during render
@juliusmarminge

Copy link
Copy Markdown
MemberAuthor

@cursor push 26dfbbe

…tire probe
When skills/list returns an error (e.g. on older Codex CLI versions that
don't support it), fall back to an empty skills array instead of calling
fail() which would reject the entire discovery promise and break account
probing.
Applied via @cursor push command
@juliusmarmingejuliusmarminge changed the title Add provider skill discovery to Codex sessionsAdd provider skill discovery Apr 10, 2026

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

Cursor Bugbot has reviewed your changes and found 1 potential issue.

Autofix Details

Bugbot Autofix prepared a fix for the issue found in the latest run.

  • ✅ Fixed: Inconsistent field lookup for displayName vs shortDescription
    • Updated displayName lookup to check skill?.displayName first, falling back to display?.displayName, matching the same pattern used for shortDescription.

Create PR

Or push these changes by commenting:

@cursor push 6b028d659a
Preview (6b028d659a)
diff --git a/apps/server/src/provider/codexAppServer.ts b/apps/server/src/provider/codexAppServer.ts--- a/apps/server/src/provider/codexAppServer.ts+++ b/apps/server/src/provider/codexAppServer.ts@@ -64,8 +64,11 @@
? { description: nonEmptyTrimmed(skill?.description) }
: {}),
...(nonEmptyTrimmed(skill?.scope) ? { scope: nonEmptyTrimmed(skill?.scope) } : {}),
- ...(nonEmptyTrimmed(display?.displayName)- ? { displayName: nonEmptyTrimmed(display?.displayName) }+ ...(nonEmptyTrimmed(skill?.displayName) || nonEmptyTrimmed(display?.displayName)+ ? {+ displayName:+ nonEmptyTrimmed(skill?.displayName) ?? nonEmptyTrimmed(display?.displayName),+ }
: {}),
...(nonEmptyTrimmed(skill?.shortDescription) || nonEmptyTrimmed(display?.shortDescription)
? {

You can send follow-ups to the cloud agent here.

Comment threadapps/server/src/provider/codexAppServer.ts
- Introduced a new scoring mechanism for workspace entries that prioritizes exact basename matches over broader path matches.
- Updated the search logic to utilize shared ranking functions for improved performance and maintainability.
- Added a test case to validate the new ranking behavior for exact matches in workspace entries.
- Removed deprecated functions related to scoring and ranking to streamline the codebase.
@github-actionsgithub-actionsBot added size:XXL 1,000+ changed lines (additions + deletions). and removed size:XL 500-999 changed lines (additions + deletions). labels Apr 10, 2026

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

Cursor Bugbot has reviewed your changes and found 1 potential issue.

Autofix Details

Bugbot Autofix prepared a fix for the issue found in the latest run.

  • ✅ Fixed: Callback recreated on every keystroke causing unnecessary re-renders
    • Replaced the prompt state variable with promptRef.current in the setPromptFromTraits callback and removed prompt from the dependency array, restoring the stable ref-based pattern that prevents callback recreation on every keystroke.

Create PR

Or push these changes by commenting:

@cursor push aadef2980e
Preview (aadef2980e)
diff --git a/apps/web/src/components/chat/ChatComposer.tsx b/apps/web/src/components/chat/ChatComposer.tsx--- a/apps/web/src/components/chat/ChatComposer.tsx+++ b/apps/web/src/components/chat/ChatComposer.tsx@@ -868,7 +868,8 @@
// ------------------------------------------------------------------
const setPromptFromTraits = useCallback(
(nextPrompt: string) => {
- if (nextPrompt === prompt) {+ const currentPrompt = promptRef.current;+ if (nextPrompt === currentPrompt) {
scheduleComposerFocus();
return;
}
@@ -879,7 +880,7 @@
setComposerTrigger(detectComposerTrigger(nextPrompt, nextPrompt.length));
scheduleComposerFocus();
},
- [composerDraftTarget, prompt, promptRef, scheduleComposerFocus, setComposerDraftPrompt],+ [composerDraftTarget, promptRef, scheduleComposerFocus, setComposerDraftPrompt],
);
const providerTraitsMenuContent = renderProviderTraitsMenuContent({

You can send follow-ups to the cloud agent here.

Comment threadapps/web/src/components/chat/ChatComposer.tsx Outdated
Co-authored-by: codex <codex@users.noreply.github.com>

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

Cursor Bugbot has reviewed your changes and found 1 potential issue.

Fix All in Cursor

Bugbot Autofix prepared a fix for the issue found in the latest run.

  • ✅ Fixed: Double-lowercasing in shared scoring utility is redundant
    • Removed the redundant .trim().toLowerCase() calls inside scoreQueryMatch since all callers already pass pre-normalized inputs, replacing them with a direct destructure and a JSDoc contract documenting the pre-normalization requirement.

Create PR

Or push these changes by commenting:

@cursor push 20f5a4b15c
Preview (20f5a4b15c)
diff --git a/packages/shared/src/searchRanking.ts b/packages/shared/src/searchRanking.ts--- a/packages/shared/src/searchRanking.ts+++ b/packages/shared/src/searchRanking.ts@@ -77,6 +77,12 @@
return bestIndex;
}
+/**+ * Scores how well `value` matches `query` using tiered match strategies.+ *+ * **Expects pre-normalized inputs**: both `value` and `query` must already be+ * trimmed and lowercased (e.g. via {@link normalizeSearchQuery}).+ */
export function scoreQueryMatch(input: {
value: string;
query: string;
@@ -87,8 +93,7 @@
fuzzyBase?: number;
boundaryMarkers?: readonly string[];
}): number | null {
- const value = input.value.trim().toLowerCase();- const query = input.query.trim().toLowerCase();+ const { value, query } = input;
if (!value || !query) {
return null;

You can send follow-ups to the cloud agent here.

Reviewed by Cursor Bugbot for commit b0488e2. Configure here.

Comment threadpackages/shared/src/searchRanking.ts Outdated
cursoragentand others added 2 commits April 10, 2026 23:54
All callers already pass pre-normalized (trimmed and lowercased) inputs,
so the internal .trim().toLowerCase() calls were redundant O(n) string
operations allocating unnecessary copies on every candidate per keystroke.
Replace with a destructured read and a JSDoc contract stating that inputs
must be pre-normalized.
Co-authored-by: codex <codex@users.noreply.github.com>
@juliusmarmingejuliusmarminge changed the title Add provider skill discovery Add provider skill discoveryApr 11, 2026
@juliusmarminge

Copy link
Copy Markdown
MemberAuthor

@cursor push 20f5a4b

All callers already pass pre-normalized (trimmed and lowercased) inputs,
so the internal .trim().toLowerCase() calls were redundant O(n) string
operations allocating unnecessary copies on every candidate per keystroke.
Replace with a destructured read and a JSDoc contract stating that inputs
must be pre-normalized.
Applied via @cursor push command
@juliusmarminge
juliusmarminge merged commit 58e5f71 into mainApr 11, 2026
12 checks passed
@juliusmarminge
juliusmarminge deleted the t3code/server-provider-skills branch April 11, 2026 00:19
@juliusmarmingejuliusmarminge mentioned this pull request Apr 11, 2026
4 tasks
juliusmarminge added a commit that referenced this pull request Apr 13, 2026
Co-authored-by: Cursor Agent <cursoragent@cursor.com>
Co-authored-by: codex <codex@users.noreply.github.com>
Co-authored-by: cursor[bot] <206951365+cursor[bot]@users.noreply.github.com>
youpele52 referenced this pull request in youpele52/bigbud Jun 17, 2026
Co-authored-by: codex <codex@users.noreply.github.com>
Co-authored-by: cursor[bot] <206951365+cursor[bot]@users.noreply.github.com>
NeilTheFisher pushed a commit to NeilTheFisher/t3code that referenced this pull request Aug 18, 2026
Co-authored-by: Cursor Agent <cursoragent@cursor.com>
Co-authored-by: codex <codex@users.noreply.github.com>
Co-authored-by: cursor[bot] <206951365+cursor[bot]@users.noreply.github.com>
Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

size:XXL1,000+ changed lines (additions + deletions).vouch:trustedPR author is trusted by repo permissions or the VOUCHED list.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants

@juliusmarminge@cursoragent
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Universal Dark Mode - works on any site\n(function() {\n var enabled = true;\n \n function applyDarkMode() {\n if (!enabled) return;\n \n // Create style element if it doesn't exist\n var style = document.getElementById('universal-dark-mode-style');\n if (!style) {\n style = document.createElement('style');\n style.id = 'universal-dark-mode-style';\n document.head.appendChild(style);\n }\n \n // Dark mode CSS - inverts colors but preserves images/video\n style.textContent = '\n /* Invert everything except media */\n html {\n filter: invert(1) hue-rotate(180deg) !important;\n background: #1a1a2e !important;\n }\n \n /* Restore images, videos, iframes, canvas */\n img, video, iframe, canvas, svg, picture, [style*=\"background-image\"] {\n filter: invert(1) hue-rotate(180deg) !important;\n }\n \n /* Preserve specific elements that should not be inverted */\n .no-dark-mode, .no-dark-mode *,\n [data-theme=\"light\"], [data-theme=\"light\"],\n .ace_editor, .ace_editor *,\n .CodeMirror, .CodeMirror *,\n .monaco-editor, .monaco-editor *,\n .markdown-body pre, .markdown-body pre *,\n .highlight, .highlight *,\n pre code, pre code * {\n filter: none !important;\n }\n \n /* Fix common UI elements */\n .modal, .popup, .dropdown-menu, .tooltip, .popover {\n filter: invert(1) hue-rotate(180deg) !important;\n background: #2d2d44 !important;\n border-color: #444 !important;\n }\n \n /* Scrollbars */\n ::-webkit-scrollbar { background: #1a1a2e !important; }\n ::-webkit-scrollbar-thumb { background: #444 !important; }\n ::-webkit-scrollbar-thumb:hover { background: #555 !important; }\n \n /* Selection */\n ::selection { background: #4ecdc4 !important; color: #1a1a2e !important; }\n ::-moz-selection { background: #4ecdc4 !important; color: #1a1a2e !important; }\n ';\n }\n \n function removeDarkMode() {\n var style = document.getElementById('universal-dark-mode-style');\n if (style) style.remove();\n }\n \n // Toggle with Alt+Shift+D\n document.addEventListener('keydown', function(e) {\n if (e.altKey && e.shiftKey && e.key === 'D') {\n e.preventDefault();\n enabled = !enabled;\n if (enabled) {\n applyDarkMode();\n console.log('[Universal Dark Mode] Enabled');\n } else {\n removeDarkMode();\n console.log('[Universal Dark Mode] Disabled');\n }\n }\n });\n \n // Apply on load\n applyDarkMode();\n \n // Re-apply on dynamic content\n var observer = new MutationObserver(function(mutations) {\n if (enabled && !document.getElementById('universal-dark-mode-style')) {\n applyDarkMode();\n }\n });\n observer.observe(document.head, { childList: true });\n \n console.log('[Universal Dark Mode] Loaded - Press Alt+Shift+D to toggle');\n})();", "Universal Dark Mode"); } } catch(__e) { console.warn('[Userscript:Universal Dark Mode]', __e); } })(); })();
Skip to content

Add provider skill discovery - #1905

Merged
juliusmarminge merged 12 commits into
mainfrom
t3code/server-provider-skills
Apr 11, 2026
Merged

Add provider skill discovery#1905
juliusmarminge merged 12 commits into
mainfrom
t3code/server-provider-skills

Conversation

@juliusmarminge

@juliusmarmingejuliusmarminge commented Apr 10, 2026

Copy link
Copy Markdown
Member

Summary

  • Adds provider skill presentation and slash-command discovery so composer UI can surface provider capabilities more directly.
  • Updates server/provider orchestration and Codex app-server plumbing to carry the new skill metadata through session and turn flows.
  • Refactors several effect service tags and ID constructors to the newer ServiceMap/makeUnsafe patterns for consistency.
  • Adjusts CLI publish/package metadata and related tests to match the new build outputs and config behavior.

Testing

  • Not run
  • Existing unit and integration tests were updated alongside the feature changes
  • Full project checks still need to pass: bun fmt, bun lint, bun typecheck, and bun run test

Note

Medium Risk
Extends the ServerProvider contract and provider health/probing flows to carry new capability metadata, and updates chat composer parsing/rendering and menu ranking logic; regressions could affect provider snapshots or composer input behavior across clients.

Overview
Provider snapshots now include capability metadata: ServerProvider gains slashCommands and skills arrays (with decoding defaults for backward compatibility), and buildServerProvider populates them.

Server-side probing is extended to fill these fields: Claude’s SDK init probe now collects and dedupes slash commands (and caches the combined probe), while Codex switches from account-only probing to probeCodexDiscovery via the app-server JSON-RPC to return both account info and per-CWD skills.

The web composer UI now surfaces provider capabilities: it adds $skill token detection/rendering (Lexical ComposerSkillNode chips with tooltip descriptions), expands slash-command completion to include provider commands, adds skill search/completion, and refactors menu highlighting + ranking using a new shared searchRanking utility (also reused for workspace entry ranking). Tests and fixtures are updated accordingly.

Reviewed by Cursor Bugbot for commit 016dbfd. Bugbot is set up for automated code reviews on this repo. Configure here.

Note

Add provider skill discovery and skill/slash-command support in the composer

  • Adds ServerProviderSkill and ServerProviderSlashCommand schemas to the contracts layer; both default to empty arrays when decoding legacy snapshots.
  • Probes the Codex provider via a new probeCodexDiscovery API to return discovered skills alongside account info, and parses Claude Agent SDK initialization commands into normalized slash commands.
  • Introduces a ComposerSkillNode Lexical node that renders inline skill chips with tooltips, and extends splitPromptTextIntoComposerSegments to parse $<name> tokens as skill segments.
  • Extends the composer command menu to show ranked, grouped results for both provider slash commands and skills, with correct /<command> and $<skill> insertion on selection.
  • Extracts a shared searchRanking package (scoreQueryMatch, insertRankedSearchResult, etc.) used by workspace entry search, skill search, and slash command search.
  • Risk: ComposerPromptEditor now requires a skills prop; any caller that does not pass it will get a type error.

Macroscope summarized 016dbfd.

- Probe Codex skills and Claude slash commands during provider checks
- Surface discovered items in server snapshots and composer UI
@coderabbitai

coderabbitaiBot commented Apr 10, 2026

Copy link
Copy Markdown

Important

Review skipped

Auto reviews are disabled on this repository. Please check the settings in the CodeRabbit UI or the .coderabbit.yaml file in this repository. To trigger a single review, invoke the @coderabbitai review command.

⚙️ Run configuration

Configuration used: Repository UI

Review profile: CHILL

Plan: Pro

Run ID: 1385ec2d-bc74-4b7b-b23e-c104f25cb89c

You can disable this status message by setting the reviews.review_status to false in the CodeRabbit configuration file.

Use the checkbox below for a quick retry:

  • 🔍 Trigger review
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch t3code/server-provider-skills

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

@github-actionsgithub-actionsBot added size:XL 500-999 changed lines (additions + deletions). vouch:trusted PR author is trusted by repo permissions or the VOUCHED list. labels Apr 10, 2026

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

Cursor Bugbot has reviewed your changes and found 2 potential issues.

Autofix Details

Bugbot Autofix prepared fixes for both issues found in the latest run.

  • ✅ Fixed: Ref assignments moved to useEffect cause stale reads
    • Moved the three ref assignments (composerMenuOpenRef, composerMenuItemsRef, activeComposerMenuItemRef) back to synchronous render phase by removing the useEffect wrapper, ensuring event handlers always read current values.
  • ✅ Fixed: Exported probeCodexAccount function is now unused
    • Removed the dead probeCodexAccount function from codexAppServer.ts since it has no remaining imports anywhere in the codebase.

Create PR

Or push these changes by commenting:

@cursor push 2d23dae3cc
Preview (2d23dae3cc)
diff --git a/apps/server/src/provider/codexAppServer.ts b/apps/server/src/provider/codexAppServer.ts--- a/apps/server/src/provider/codexAppServer.ts+++ b/apps/server/src/provider/codexAppServer.ts@@ -244,16 +244,3 @@
});
});
}
--export async function probeCodexAccount(input: {- readonly binaryPath: string;- readonly homePath?: string;- readonly signal?: AbortSignal;-}): Promise<CodexAccountSnapshot> {- return (- await probeCodexDiscovery({- ...input,- cwd: process.cwd(),- })- ).account;-}diff --git a/apps/web/src/components/chat/ChatComposer.tsx b/apps/web/src/components/chat/ChatComposer.tsx--- a/apps/web/src/components/chat/ChatComposer.tsx+++ b/apps/web/src/components/chat/ChatComposer.tsx@@ -820,11 +820,9 @@
[composerHighlightedItemId, composerMenuItems],
);
- useEffect(() => {- composerMenuOpenRef.current = composerMenuOpen;- composerMenuItemsRef.current = composerMenuItems;- activeComposerMenuItemRef.current = activeComposerMenuItem;- }, [activeComposerMenuItem, composerMenuItems, composerMenuOpen]);+ composerMenuOpenRef.current = composerMenuOpen;+ composerMenuItemsRef.current = composerMenuItems;+ activeComposerMenuItemRef.current = activeComposerMenuItem;
const nonPersistedComposerImageIdSet = useMemo(
() => new Set(nonPersistedComposerImageIds),

You can send follow-ups to the cloud agent here.

Comment threadapps/web/src/components/chat/ChatComposer.tsx Outdated
Comment threadapps/server/src/provider/codexAppServer.ts Outdated
Comment threadapps/web/src/components/ComposerPromptEditor.tsx Outdated
Comment threadapps/web/src/components/ComposerPromptEditor.tsx
@macroscopeapp

macroscopeappBot commented Apr 10, 2026

Copy link
Copy Markdown
Contributor

Approvability

Verdict: Needs human review

This PR introduces a significant new feature: provider skill and slash command discovery. It adds new user-facing capabilities including skill autocomplete via $ syntax, skill pills in the composer, provider slash commands in the command menu, and supporting search/ranking infrastructure. New features of this scope warrant human review to validate the design and integration.

You can customize Macroscope's approvability policy. Learn more.

- Map provider slash command hints into the shared contract
- Surface provider command metadata in the chat composer

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

Cursor Bugbot has reviewed your changes and found 1 potential issue.

There are 3 total unresolved issues (including 2 from previous reviews).

Autofix Details

Bugbot Autofix prepared a fix for the issue found in the latest run.

  • ✅ Fixed: skills/list failure rejects entire account probe
    • Changed the skills/list error handler to gracefully fall back to an empty skills array instead of calling fail(), so account probing remains resilient when skills/list is unsupported or errors.

Create PR

Or push these changes by commenting:

@cursor push 26dfbbe0ac
Preview (26dfbbe0ac)
diff --git a/apps/server/src/provider/codexAppServer.ts b/apps/server/src/provider/codexAppServer.ts--- a/apps/server/src/provider/codexAppServer.ts+++ b/apps/server/src/provider/codexAppServer.ts@@ -205,12 +205,7 @@
if (response.id === 2) {
const errorMessage = readErrorMessage(response);
- if (errorMessage) {- fail(new Error(`skills/list failed: ${errorMessage}`));- return;- }-- skills = parseCodexSkillsResult(response.result, input.cwd);+ skills = errorMessage ? [] : parseCodexSkillsResult(response.result, input.cwd);
maybeResolve();
return;
}

You can send follow-ups to the cloud agent here.

Comment threadapps/server/src/provider/codexAppServer.ts
cursoragentand others added 3 commits April 10, 2026 22:56
…tire probe
When skills/list returns an error (e.g. on older Codex CLI versions that
don't support it), fall back to an empty skills array instead of calling
fail() which would reject the entire discovery promise and break account
probing.
Co-authored-by: codex <codex@users.noreply.github.com>
- Restore serialized composer skill node state
- Sync skill labels before paint to avoid stale UI
- Keep composer menu refs current during render
@juliusmarminge

Copy link
Copy Markdown
MemberAuthor

@cursor push 26dfbbe

…tire probe
When skills/list returns an error (e.g. on older Codex CLI versions that
don't support it), fall back to an empty skills array instead of calling
fail() which would reject the entire discovery promise and break account
probing.
Applied via @cursor push command
@juliusmarmingejuliusmarminge changed the title Add provider skill discovery to Codex sessionsAdd provider skill discovery Apr 10, 2026

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

Cursor Bugbot has reviewed your changes and found 1 potential issue.

Autofix Details

Bugbot Autofix prepared a fix for the issue found in the latest run.

  • ✅ Fixed: Inconsistent field lookup for displayName vs shortDescription
    • Updated displayName lookup to check skill?.displayName first, falling back to display?.displayName, matching the same pattern used for shortDescription.

Create PR

Or push these changes by commenting:

@cursor push 6b028d659a
Preview (6b028d659a)
diff --git a/apps/server/src/provider/codexAppServer.ts b/apps/server/src/provider/codexAppServer.ts--- a/apps/server/src/provider/codexAppServer.ts+++ b/apps/server/src/provider/codexAppServer.ts@@ -64,8 +64,11 @@
? { description: nonEmptyTrimmed(skill?.description) }
: {}),
...(nonEmptyTrimmed(skill?.scope) ? { scope: nonEmptyTrimmed(skill?.scope) } : {}),
- ...(nonEmptyTrimmed(display?.displayName)- ? { displayName: nonEmptyTrimmed(display?.displayName) }+ ...(nonEmptyTrimmed(skill?.displayName) || nonEmptyTrimmed(display?.displayName)+ ? {+ displayName:+ nonEmptyTrimmed(skill?.displayName) ?? nonEmptyTrimmed(display?.displayName),+ }
: {}),
...(nonEmptyTrimmed(skill?.shortDescription) || nonEmptyTrimmed(display?.shortDescription)
? {

You can send follow-ups to the cloud agent here.

Comment threadapps/server/src/provider/codexAppServer.ts
- Introduced a new scoring mechanism for workspace entries that prioritizes exact basename matches over broader path matches.
- Updated the search logic to utilize shared ranking functions for improved performance and maintainability.
- Added a test case to validate the new ranking behavior for exact matches in workspace entries.
- Removed deprecated functions related to scoring and ranking to streamline the codebase.
@github-actionsgithub-actionsBot added size:XXL 1,000+ changed lines (additions + deletions). and removed size:XL 500-999 changed lines (additions + deletions). labels Apr 10, 2026

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

Cursor Bugbot has reviewed your changes and found 1 potential issue.

Autofix Details

Bugbot Autofix prepared a fix for the issue found in the latest run.

  • ✅ Fixed: Callback recreated on every keystroke causing unnecessary re-renders
    • Replaced the prompt state variable with promptRef.current in the setPromptFromTraits callback and removed prompt from the dependency array, restoring the stable ref-based pattern that prevents callback recreation on every keystroke.

Create PR

Or push these changes by commenting:

@cursor push aadef2980e
Preview (aadef2980e)
diff --git a/apps/web/src/components/chat/ChatComposer.tsx b/apps/web/src/components/chat/ChatComposer.tsx--- a/apps/web/src/components/chat/ChatComposer.tsx+++ b/apps/web/src/components/chat/ChatComposer.tsx@@ -868,7 +868,8 @@
// ------------------------------------------------------------------
const setPromptFromTraits = useCallback(
(nextPrompt: string) => {
- if (nextPrompt === prompt) {+ const currentPrompt = promptRef.current;+ if (nextPrompt === currentPrompt) {
scheduleComposerFocus();
return;
}
@@ -879,7 +880,7 @@
setComposerTrigger(detectComposerTrigger(nextPrompt, nextPrompt.length));
scheduleComposerFocus();
},
- [composerDraftTarget, prompt, promptRef, scheduleComposerFocus, setComposerDraftPrompt],+ [composerDraftTarget, promptRef, scheduleComposerFocus, setComposerDraftPrompt],
);
const providerTraitsMenuContent = renderProviderTraitsMenuContent({

You can send follow-ups to the cloud agent here.

Comment threadapps/web/src/components/chat/ChatComposer.tsx Outdated
Co-authored-by: codex <codex@users.noreply.github.com>

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

Cursor Bugbot has reviewed your changes and found 1 potential issue.

Fix All in Cursor

Bugbot Autofix prepared a fix for the issue found in the latest run.

  • ✅ Fixed: Double-lowercasing in shared scoring utility is redundant
    • Removed the redundant .trim().toLowerCase() calls inside scoreQueryMatch since all callers already pass pre-normalized inputs, replacing them with a direct destructure and a JSDoc contract documenting the pre-normalization requirement.

Create PR

Or push these changes by commenting:

@cursor push 20f5a4b15c
Preview (20f5a4b15c)
diff --git a/packages/shared/src/searchRanking.ts b/packages/shared/src/searchRanking.ts--- a/packages/shared/src/searchRanking.ts+++ b/packages/shared/src/searchRanking.ts@@ -77,6 +77,12 @@
return bestIndex;
}
+/**+ * Scores how well `value` matches `query` using tiered match strategies.+ *+ * **Expects pre-normalized inputs**: both `value` and `query` must already be+ * trimmed and lowercased (e.g. via {@link normalizeSearchQuery}).+ */
export function scoreQueryMatch(input: {
value: string;
query: string;
@@ -87,8 +93,7 @@
fuzzyBase?: number;
boundaryMarkers?: readonly string[];
}): number | null {
- const value = input.value.trim().toLowerCase();- const query = input.query.trim().toLowerCase();+ const { value, query } = input;
if (!value || !query) {
return null;

You can send follow-ups to the cloud agent here.

Reviewed by Cursor Bugbot for commit b0488e2. Configure here.

Comment threadpackages/shared/src/searchRanking.ts Outdated
cursoragentand others added 2 commits April 10, 2026 23:54
All callers already pass pre-normalized (trimmed and lowercased) inputs,
so the internal .trim().toLowerCase() calls were redundant O(n) string
operations allocating unnecessary copies on every candidate per keystroke.
Replace with a destructured read and a JSDoc contract stating that inputs
must be pre-normalized.
Co-authored-by: codex <codex@users.noreply.github.com>
@juliusmarmingejuliusmarminge changed the title Add provider skill discovery Add provider skill discoveryApr 11, 2026
@juliusmarminge

Copy link
Copy Markdown
MemberAuthor

@cursor push 20f5a4b

All callers already pass pre-normalized (trimmed and lowercased) inputs,
so the internal .trim().toLowerCase() calls were redundant O(n) string
operations allocating unnecessary copies on every candidate per keystroke.
Replace with a destructured read and a JSDoc contract stating that inputs
must be pre-normalized.
Applied via @cursor push command
@juliusmarminge
juliusmarminge merged commit 58e5f71 into mainApr 11, 2026
12 checks passed
@juliusmarminge
juliusmarminge deleted the t3code/server-provider-skills branch April 11, 2026 00:19
@juliusmarmingejuliusmarminge mentioned this pull request Apr 11, 2026
4 tasks
juliusmarminge added a commit that referenced this pull request Apr 13, 2026
Co-authored-by: Cursor Agent <cursoragent@cursor.com>
Co-authored-by: codex <codex@users.noreply.github.com>
Co-authored-by: cursor[bot] <206951365+cursor[bot]@users.noreply.github.com>
youpele52 referenced this pull request in youpele52/bigbud Jun 17, 2026
Co-authored-by: codex <codex@users.noreply.github.com>
Co-authored-by: cursor[bot] <206951365+cursor[bot]@users.noreply.github.com>
NeilTheFisher pushed a commit to NeilTheFisher/t3code that referenced this pull request Aug 18, 2026
Co-authored-by: Cursor Agent <cursoragent@cursor.com>
Co-authored-by: codex <codex@users.noreply.github.com>
Co-authored-by: cursor[bot] <206951365+cursor[bot]@users.noreply.github.com>
Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

size:XXL1,000+ changed lines (additions + deletions).vouch:trustedPR author is trusted by repo permissions or the VOUCHED list.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants

@juliusmarminge@cursoragent