Skip to content

feat: enhance plugin provider handling and add tests for decorator providers#320

Merged
frontegg-david merged 4 commits intorelease/1.0.xfrom
fix-inline-provider-in-plugins
Mar 29, 2026
Merged

feat: enhance plugin provider handling and add tests for decorator providers#320
frontegg-david merged 4 commits intorelease/1.0.xfrom
fix-inline-provider-in-plugins

Conversation

@frontegg-david
Copy link
Copy Markdown
Contributor

@frontegg-david frontegg-david commented Mar 29, 2026

Summary by CodeRabbit

  • Bug Fixes

    • Prevented inline/dynamic provider entries from overriding decorator-declared providers during plugin normalization/registration.
  • New Features

    • Project scaffolding now generates a versioned, comment-delimited "Skills and Tools" section in CLAUDE.md populated from the local/packaged skills catalog.
  • Documentation

    • Added skills/tools guidance and updated skill guides to rely on framework error handling (avoid wrapping execute() in try/catch).
  • Tests

    • Added tests for decorator-based provider handling, normalization merging, and CLAUDE.md skills generation.
  • Style

    • Cleaned up inline ESLint suppression comments across multiple modules.

@coderabbitai
Copy link
Copy Markdown
Contributor

coderabbitai bot commented Mar 29, 2026

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: 28e98c8d-f84c-4442-becc-9ff783d64a94

📥 Commits

Reviewing files that changed from the base of the PR and between 3976fad and cdc9039.

📒 Files selected for processing (2)
  • libs/cli/src/commands/skills/__tests__/install.spec.ts
  • libs/cli/src/commands/skills/install.ts
🚧 Files skipped from review as they are similar to previous changes (2)
  • libs/cli/src/commands/skills/tests/install.spec.ts
  • libs/cli/src/commands/skills/install.ts

📝 Walkthrough

Walkthrough

Normalize plugin metadata to prevent inline providers from overriding decorator-declared providers; add/extend tests for provider-merge and registry behavior; integrate manifest-driven, versioned "Skills and Tools" blocks into CLAUDE.md generation with CLI scaffolding and tests; remove several inline ESLint disable comments; update skill docs to stop catching infrastructure errors.

Changes

Cohort / File(s) Summary
Plugin Normalization & Tests
libs/sdk/src/plugin/plugin.utils.ts, libs/sdk/src/plugin/__tests__/plugin.utils.spec.ts, libs/sdk/src/plugin/__tests__/plugin.registry.spec.ts
Strip providers from inline metadata when merging with decorator-derived metadata; add tests for decorator vs inline/dynamic provider merging and registry behavior ensuring decorator-provided services persist.
CLI: CLAUDE.md Skills Integration
libs/cli/src/commands/scaffold/create.ts, libs/cli/src/commands/skills/install.ts, libs/cli/src/commands/skills/__tests__/install.spec.ts
Add loadSkillEntriesForClaudeMd() to read/filter skills manifest (local or package), build a versioned, comment-delimited skills block via buildSkillsSection, wire it into scaffolding, and export ensureClaudeMdSkillsInstructions; include comprehensive tests for insertion, migration, idempotence, and formatting.
Scaffold Helper
libs/cli/src/commands/scaffold/create.ts
New helper resolves skills-manifest.json, filters by deployment target and bundle, returns {name,description}[] or empty on failure.
Documentation / Skills Catalog
CLAUDE.md, libs/skills/catalog/.../*
Add "Skills and Tools" guidance to CLAUDE.md and update skill docs to discourage try/catch around execute() so framework handles infra errors.
ESLint Directive Cleanup
libs/cli/src/core/__tests__/help.spec.ts, libs/auth/src/machine-id/machine-id.ts, libs/nx-plugin/src/generators/workspace/workspace.spec.ts, libs/ui/src/renderer/common/lazy-import.ts, libs/ui/src/renderer/react/index.ts, libs/uipack/src/component/transpiler.ts, libs/utils/src/crypto/index.ts, libs/utils/src/crypto/secret-persistence/persistence.ts, libs/utils/src/event-emitter/browser-event-emitter.ts
Removed inline ESLint suppression comments adjacent to lazy require/dynamic new Function(...) patterns and tests; no runtime behavior changes.
ESLint Config
eslint.config.mjs
Expanded top-level ignores to exclude common test/spec patterns and test/support folders.

Sequence Diagram(s)

sequenceDiagram
  participant CLI as CLI scaffold/create
  participant FS as Local filesystem (skills/catalog)
  participant PKG as `@frontmcp/skills` package
  participant Generator as generateClaudeMd / buildSkillsSection
  CLI->>FS: try read skills-manifest.json
  FS-->>CLI: manifest (or not found)
  alt manifest found locally
    CLI->>Generator: filter by target/bundle, map to entries
  else not found
    CLI->>PKG: resolve package manifest
    PKG-->>CLI: manifest (or fail)
    CLI->>Generator: filter/map (or empty)
  end
  CLI->>Generator: buildSkillsSection(version, entries)
  Generator-->>CLI: skills block
  CLI->>FS: read/write CLAUDE.md (insert/replace/prepend block)
  FS-->>CLI: file written
Loading

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~25 minutes

Possibly related PRs

Poem

🐰 I nibbled metadata, neat and bright,

Providers stayed put — no sneaky overwrite.
CLAUDE now lists skills with versioned cheer,
Tests thump their paws, docs steer clear —
A rabbit's wink for changes here.

🚥 Pre-merge checks | ✅ 3
✅ Passed checks (3 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title accurately reflects the main changes: enhanced plugin provider handling logic and comprehensive test coverage for decorator-based providers across multiple test files.
Docstring Coverage ✅ Passed Docstring coverage is 68.75% which is sufficient. The required threshold is 65.00%.

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

✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch fix-inline-provider-in-plugins

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

Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 1

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
libs/sdk/src/plugin/plugin.utils.ts (1)

53-65: ⚠️ Potential issue | 🟠 Major

Strip inline providers from metadata in both useFactory and useClass branches.

The useValue branch correctly excludes inline providers from metadata (line 76) and returns them separately (line 83). However, both useFactory (line 63) and useClass (line 49) pass metadata without stripping providers, which breaks the intended separation. If a factory or class plugin is registered with inline providers, they remain in metadata.providers instead of being extracted to rec.providers for registration at line 277 in plugin.registry.ts.

Apply the same pattern as useValue:

  • Extract providers from metadata: const { providers: _dynamicProviders, ...inlineMetadata } = metadata
  • Return providers: (item.providers ?? []) in the record
  • Use inlineMetadata (without providers) for metadata merging
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@libs/sdk/src/plugin/plugin.utils.ts` around lines 53 - 65, In the useFactory
and useClass branches of the plugin builder (the blocks that return records with
kind PluginKind.FACTORY and PluginKind.CLASS), strip inline providers from
metadata the same way useValue does: destructure metadata to extract providers
(e.g. const { providers: _dynamicProviders, ...inlineMetadata } = metadata),
return a providers field set to (item.providers ?? []) on the record, and use
inlineMetadata (without providers) for the metadata property; ensure the
InvalidUseFactoryError/type checks remain unchanged and that tokenName(provide)
usage is preserved.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@libs/cli/src/core/__tests__/help.spec.ts`:
- Around line 58-59: Restore the ESLint suppression for the control character in
the regex used by the stripAnsi function: add the comment "//
eslint-disable-next-line no-control-regex" immediately above the stripAnsi
declaration (the line defining const stripAnsi = (s: string) =>
s.replace(/\x1b\[[0-9;]*m/g, '');) so the no-control-regex rule is ignored for
this required ANSI-stripping regular expression.

---

Outside diff comments:
In `@libs/sdk/src/plugin/plugin.utils.ts`:
- Around line 53-65: In the useFactory and useClass branches of the plugin
builder (the blocks that return records with kind PluginKind.FACTORY and
PluginKind.CLASS), strip inline providers from metadata the same way useValue
does: destructure metadata to extract providers (e.g. const { providers:
_dynamicProviders, ...inlineMetadata } = metadata), return a providers field set
to (item.providers ?? []) on the record, and use inlineMetadata (without
providers) for the metadata property; ensure the InvalidUseFactoryError/type
checks remain unchanged and that tokenName(provide) usage is preserved.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

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

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: 58e34534-6aae-428e-981d-24515d3776d0

📥 Commits

Reviewing files that changed from the base of the PR and between 85eaa23 and 3dca221.

📒 Files selected for processing (4)
  • libs/cli/src/core/__tests__/help.spec.ts
  • libs/sdk/src/plugin/__tests__/plugin.registry.spec.ts
  • libs/sdk/src/plugin/__tests__/plugin.utils.spec.ts
  • libs/sdk/src/plugin/plugin.utils.ts

@github-actions
Copy link
Copy Markdown
Contributor

github-actions bot commented Mar 29, 2026

Performance Test Results

Status: ✅ All tests passed

Summary

Project Tests Passed Warnings Failed Leaks
✅ demo-e2e-agents 4 4 0 0 0
✅ demo-e2e-cache 11 11 0 0 0
✅ demo-e2e-codecall 4 4 0 0 0
✅ demo-e2e-config 4 4 0 0 0
✅ demo-e2e-direct 3 3 0 0 0
✅ demo-e2e-elicitation 1 1 0 0 0
✅ demo-e2e-errors 4 4 0 0 0
✅ demo-e2e-hooks 3 3 0 0 0
✅ demo-e2e-multiapp 4 4 0 0 0
✅ demo-e2e-notifications 3 3 0 0 0
✅ demo-e2e-openapi 2 2 0 0 0
✅ demo-e2e-providers 4 4 0 0 0
✅ demo-e2e-public 4 4 0 0 0
✅ demo-e2e-redis 15 15 0 0 0
✅ demo-e2e-remember 4 4 0 0 0
✅ demo-e2e-remote 5 5 0 0 0
✅ demo-e2e-serverless 2 2 0 0 0
✅ demo-e2e-skills 15 15 0 0 0
✅ demo-e2e-standalone 2 2 0 0 0
✅ demo-e2e-transport-recreation 3 3 0 0 0
✅ demo-e2e-ui 4 4 0 0 0

Total: 101 tests across 21 projects

📊 View full report in workflow run


Generated at: 2026-03-29T06:33:53.897Z
Commit: a4877c2b

Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 3

🧹 Nitpick comments (1)
libs/cli/src/commands/skills/__tests__/install.spec.ts (1)

125-142: Add migration coverage for legacy blocks followed by ## headings.

Current migration tests only validate a next # heading. Add a case with ## (common in real CLAUDE.md) to prevent accidental truncation regressions.

🧪 Suggested additional test
+  it('should migrate legacy section and preserve content under subheadings', async () => {
+    mockFiles['/test/project/CLAUDE.md'] = [
+      '# Skills and Tools',
+      'Legacy content',
+      '',
+      '## Commands',
+      'Run yarn dev.',
+    ].join('\n');
+
+    await ensureClaudeMdSkillsInstructions('/test/project');
+
+    const content = mockFiles['/test/project/CLAUDE.md'];
+    expect(content).toContain('<!-- frontmcp:skills-start v1.0.0-test -->');
+    expect(content).toContain('## Commands');
+    expect(content).toContain('Run yarn dev.');
+  });
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@libs/cli/src/commands/skills/__tests__/install.spec.ts` around lines 125 -
142, Add a new test in install.spec.ts that verifies migration of legacy "#
Skills and Tools" when the next heading is a "##" level (not just "#"); update
or add a case using mockFiles['/test/project/CLAUDE.md'] where after the legacy
block you have '## Other Heading' and content, then call
ensureClaudeMdSkillsInstructions('/test/project') and assert the file contains
the marker comments ('<!-- frontmcp:skills-start v1.0.0-test -->' and '<!--
frontmcp:skills-end -->'), does not contain the old hardcoded content, and still
contains the '## Other Heading' and its following content; reference the
existing test name and function ensureClaudeMdSkillsInstructions to locate where
to add this case.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@libs/cli/src/commands/scaffold/create.ts`:
- Around line 312-325: The CLAUDE.md generator (generateClaudeMd) is using the
full manifest's skillEntries which can include skills not actually scaffolded;
update generateClaudeMd (and the callers that pass skillEntries) to filter
skillEntries the same way the scaffolding/install logic does (by target and
bundle) before calling buildSkillsSection so the skills block only lists
installed skills (reuse the same filter function or inline the target/bundle
check used in the scaffold flow). Ensure you reference the same filtering
criteria used in the scaffold/install code paths so all places that call
generateClaudeMd (and related ranges around buildSkillsSection) stay consistent.

In `@libs/cli/src/commands/skills/install.ts`:
- Around line 111-113: The current heading-detection only matches "\n" followed
by a single "#" (const nextHeadingMatch = afterLegacy.match(/\n(?=# )/)), which
causes content after "##" or "###" headings to be dropped; update the regex to
detect any Markdown heading level (for example use /\n(?=#+\s)/ or
/\n(?=#{1,6}\s)/) when computing nextHeadingMatch, leaving the subsequent slice
logic (after = nextHeadingMatch ? afterLegacy.slice(nextHeadingMatch.index!) :
'') unchanged so all following headings (##, ###, etc.) are preserved.
- Around line 94-99: The end-marker search should begin at the start-marker
index to ensure we match the correct block: change the lookup of
SKILLS_BLOCK_END to search from startIdx (use indexOf with the start position)
so endIdx = content.indexOf(SKILLS_BLOCK_END, startIdx) (then keep the existing
slicing into before = content.slice(0, startIdx) and after =
content.slice(endIdx + SKILLS_BLOCK_END.length) logic); this prevents picking an
earlier unrelated end marker and ensures proper replacement boundaries for
SKILLS_BLOCK_START/SKILLS_BLOCK_END handling.

---

Nitpick comments:
In `@libs/cli/src/commands/skills/__tests__/install.spec.ts`:
- Around line 125-142: Add a new test in install.spec.ts that verifies migration
of legacy "# Skills and Tools" when the next heading is a "##" level (not just
"#"); update or add a case using mockFiles['/test/project/CLAUDE.md'] where
after the legacy block you have '## Other Heading' and content, then call
ensureClaudeMdSkillsInstructions('/test/project') and assert the file contains
the marker comments ('<!-- frontmcp:skills-start v1.0.0-test -->' and '<!--
frontmcp:skills-end -->'), does not contain the old hardcoded content, and still
contains the '## Other Heading' and its following content; reference the
existing test name and function ensureClaudeMdSkillsInstructions to locate where
to add this case.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

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

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: 6ced55b2-b35d-490c-927d-5258606c62c5

📥 Commits

Reviewing files that changed from the base of the PR and between 3dca221 and 7b79f16.

📒 Files selected for processing (8)
  • CLAUDE.md
  • libs/cli/src/commands/scaffold/create.ts
  • libs/cli/src/commands/skills/__tests__/install.spec.ts
  • libs/cli/src/commands/skills/install.ts
  • libs/skills/catalog/frontmcp-development/references/create-tool.md
  • libs/skills/catalog/frontmcp-guides/references/example-task-manager.md
  • libs/skills/catalog/frontmcp-guides/references/example-weather-api.md
  • libs/skills/catalog/frontmcp-testing/references/setup-testing.md
✅ Files skipped from review due to trivial changes (3)
  • libs/skills/catalog/frontmcp-testing/references/setup-testing.md
  • CLAUDE.md
  • libs/skills/catalog/frontmcp-development/references/create-tool.md

Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 2

🧹 Nitpick comments (1)
libs/cli/src/commands/scaffold/create.ts (1)

1404-1434: Unify skill-manifest loading/filtering to avoid future drift.

Line 1404 duplicates manifest resolution + target/bundle filtering logic already present in scaffoldSkills. This is the same class of logic that previously drifted and caused CLAUDE.md mismatch behavior. Centralizing into one helper will reduce regression risk.

♻️ Suggested refactor sketch
+async function loadSkillManifest(): Promise<SkillManifest | null> {
+  try {
+    const catalogDir = path.resolve(__dirname, '..', '..', '..', '..', 'skills', 'catalog');
+    const manifestPath = path.join(catalogDir, 'skills-manifest.json');
+    if (await fileExists(manifestPath)) {
+      return JSON.parse(await readFile(manifestPath)) as SkillManifest;
+    }
+    const require_ = createRequire(__filename);
+    const pkgManifest = require_.resolve('@frontmcp/skills/catalog/skills-manifest.json');
+    return JSON.parse(await readFile(pkgManifest)) as SkillManifest;
+  } catch {
+    return null;
+  }
+}
+
+function filterSkillsByTargetAndBundle(
+  skills: SkillCatalogEntry[],
+  options: Pick<CreateOptions, 'deploymentTarget' | 'skillsBundle'>,
+): SkillCatalogEntry[] {
+  const bundle = options.skillsBundle ?? 'recommended';
+  if (bundle === 'none') return [];
+  return skills.filter((s) => {
+    const targetMatch = s.targets.includes('all') || s.targets.includes(options.deploymentTarget);
+    const bundleMatch = s.bundle?.includes(bundle) === true;
+    return targetMatch && bundleMatch;
+  });
+}
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@libs/cli/src/commands/scaffold/create.ts` around lines 1404 - 1434, The
function loadSkillEntriesForClaudeMd duplicates manifest resolution and
target/bundle filtering logic found in scaffoldSkills; extract a single helper
(e.g., loadSkillManifest and filterSkillsByTargetAndBundle) that performs
manifest path resolution (including fallback to require_.resolve),
reading/parsing into SkillManifest, and the filter (targets includes 'all' or
deploymentTarget and bundle includes skillsBundle), then update
loadSkillEntriesForClaudeMd and scaffoldSkills to call that helper and return
the {name, description} mapping; keep error handling behavior (return [] on
failure) and reuse unique symbols loadSkillEntriesForClaudeMd and scaffoldSkills
to locate call sites.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@eslint.config.mjs`:
- Around line 8-23: The global "ignores" array currently contains test-file glob
patterns (e.g., **/*.spec.ts, **/*.test.tsx, **/__tests__/**) which cause ESLint
to skip those files before any overrides run; remove those test-related globs
from the "ignores" array so the override block that relaxes rules for test files
(the existing override block for test patterns) can actually apply, leaving only
build/artifact globs (like **/dist, **/*.d.ts, apps/e2e/**) in "ignores" and
relying on the overrides section to target test files.

In `@libs/cli/src/commands/skills/install.ts`:
- Around line 84-87: The CLAUDE.md generation currently passes manifest.skills
to buildSkillsSection which includes catalog entries not actually installed;
change this to derive the skills list from the installed skill directories under
the project (use cwd to locate the provider/installed skills folder), collect
only the installed skill names/metadata, and pass that installed-skills array
into buildSkillsSection(version, installedSkills) instead of manifest.skills so
the generated CLAUDE.md reflects what is actually installed.

---

Nitpick comments:
In `@libs/cli/src/commands/scaffold/create.ts`:
- Around line 1404-1434: The function loadSkillEntriesForClaudeMd duplicates
manifest resolution and target/bundle filtering logic found in scaffoldSkills;
extract a single helper (e.g., loadSkillManifest and
filterSkillsByTargetAndBundle) that performs manifest path resolution (including
fallback to require_.resolve), reading/parsing into SkillManifest, and the
filter (targets includes 'all' or deploymentTarget and bundle includes
skillsBundle), then update loadSkillEntriesForClaudeMd and scaffoldSkills to
call that helper and return the {name, description} mapping; keep error handling
behavior (return [] on failure) and reuse unique symbols
loadSkillEntriesForClaudeMd and scaffoldSkills to locate call sites.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

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

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: 8754a4cb-280f-4cda-bc04-94716250365e

📥 Commits

Reviewing files that changed from the base of the PR and between 7b79f16 and 3976fad.

⛔ Files ignored due to path filters (1)
  • libs/cli/src/commands/build/exec/cli-runtime/daemon-client.ts is excluded by !**/build/**
📒 Files selected for processing (12)
  • eslint.config.mjs
  • libs/auth/src/machine-id/machine-id.ts
  • libs/cli/src/commands/scaffold/create.ts
  • libs/cli/src/commands/skills/__tests__/install.spec.ts
  • libs/cli/src/commands/skills/install.ts
  • libs/nx-plugin/src/generators/workspace/workspace.spec.ts
  • libs/ui/src/renderer/common/lazy-import.ts
  • libs/ui/src/renderer/react/index.ts
  • libs/uipack/src/component/transpiler.ts
  • libs/utils/src/crypto/index.ts
  • libs/utils/src/crypto/secret-persistence/persistence.ts
  • libs/utils/src/event-emitter/browser-event-emitter.ts
💤 Files with no reviewable changes (4)
  • libs/utils/src/event-emitter/browser-event-emitter.ts
  • libs/ui/src/renderer/common/lazy-import.ts
  • libs/nx-plugin/src/generators/workspace/workspace.spec.ts
  • libs/ui/src/renderer/react/index.ts
✅ Files skipped from review due to trivial changes (5)
  • libs/uipack/src/component/transpiler.ts
  • libs/auth/src/machine-id/machine-id.ts
  • libs/utils/src/crypto/secret-persistence/persistence.ts
  • libs/utils/src/crypto/index.ts
  • libs/cli/src/commands/skills/tests/install.spec.ts

@frontegg-david frontegg-david merged commit 4e06ff2 into release/1.0.x Mar 29, 2026
67 checks passed
@frontegg-david frontegg-david deleted the fix-inline-provider-in-plugins branch March 29, 2026 06:36
github-actions bot pushed a commit that referenced this pull request Mar 29, 2026
… decorator providers

Cherry-picked from #320 (merged to release/1.0.x)
Original commit: 4e06ff2

Co-Authored-By: frontegg-david <69419539+frontegg-david@users.noreply.github.com>
@github-actions
Copy link
Copy Markdown
Contributor

Cherry-pick Created

A cherry-pick PR to main has been automatically created.

Please review and merge if this change should also be in main.

If the cherry-pick is not needed, close the PR.

frontegg-david added a commit that referenced this pull request Mar 29, 2026
… decorator providers (#321)

Cherry-picked from #320 (merged to release/1.0.x)
Original commit: 4e06ff2

Co-authored-by: agentfront[bot] <agentfront[bot]@users.noreply.github.com>
Co-authored-by: frontegg-david <69419539+frontegg-david@users.noreply.github.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant