Skip to content

feat(#3307): add boost-backend-module-kagenti provider module - #3573

Merged
gabemontero merged 5 commits into
mainfrom
agent/3307-kagenti-provider-module
Jun 25, 2026
Merged

feat(#3307): add boost-backend-module-kagenti provider module#3573
gabemontero merged 5 commits into
mainfrom
agent/3307-kagenti-provider-module

Conversation

@fullsend-ai-coder

Copy link
Copy Markdown
Contributor

Create the Kagenti provider module as an independent createBackendModule with pluginId 'boost' and moduleId 'kagenti'. The module registers KagentiProvider via the boostProviderExtensionPoint, enabling Kagenti as an AI backend using the A2A protocol.

Implementation includes:

  • KagentiProvider implementing AgenticProvider with A2A
    protocol integration for chat and streaming
  • KagentiProviderFactory reading connection config from
    boost.providers.kagenti and creating all caches
  • AgentCardCache using cacheService with 5m TTL (task 3.3)
  • KeycloakTokenCache with dynamic TTL per token (task 3.4)
  • SessionMap for A2A sessions with 24h TTL (task 3.7)
  • Kagenti-specific types (agent cards, A2A protocol,
    namespaces) defined in the module only (task 3b.1)
  • No cross-provider imports (task 2.5)

All caches use Backstage coreServices.cache per Decision 3. No raw Map<> caches. 25 tests passing with coverage.


Closes #3307

Post-script verification

  • Branch is not main/master (agent/3307-kagenti-provider-module)
  • Secret scan passed (gitleaks — 4bf51ccefa1eb56ee3201bc1bd094d29f66aff75..HEAD)
  • Pre-commit hooks passed (authoritative run on runner)
  • Tests ran inside sandbox

Create the Kagenti provider module as an independent
createBackendModule with pluginId 'boost' and moduleId
'kagenti'. The module registers KagentiProvider via the
boostProviderExtensionPoint, enabling Kagenti as an AI
backend using the A2A protocol.

Implementation includes:
- KagentiProvider implementing AgenticProvider with A2A
  protocol integration for chat and streaming
- KagentiProviderFactory reading connection config from
  boost.providers.kagenti and creating all caches
- AgentCardCache using cacheService with 5m TTL (task 3.3)
- KeycloakTokenCache with dynamic TTL per token (task 3.4)
- SessionMap for A2A sessions with 24h TTL (task 3.7)
- Kagenti-specific types (agent cards, A2A protocol,
  namespaces) defined in the module only (task 3b.1)
- No cross-provider imports (task 2.5)

All caches use Backstage coreServices.cache per Decision 3.
No raw Map<> caches. 25 tests passing with coverage.

Closes #3307
@rhdh-gh-app

rhdh-gh-app Bot commented Jun 24, 2026

Copy link
Copy Markdown

Missing Changesets

The following package(s) are changed by this PR but do not have a changeset:

  • @red-hat-developer-hub/backstage-plugin-boost-backend-module-kagenti

See CONTRIBUTING.md for more information about how to add changesets.

Changed Packages

Package Name Package Path Changeset Bump Current Version
@red-hat-developer-hub/backstage-plugin-boost-backend-module-kagenti workspaces/boost/plugins/boost-backend-module-kagenti none v0.1.0

@codecov

codecov Bot commented Jun 24, 2026

Copy link
Copy Markdown

Codecov Report

❌ Patch coverage is 79.35223% with 51 lines in your changes missing coverage. Please review.
✅ Project coverage is 50.84%. Comparing base (4bf51cc) to head (2546b2d).
✅ All tests successful. No failed tests found.

Additional details and impacted files
@@            Coverage Diff             @@
##             main    #3573      +/-   ##
==========================================
+ Coverage   50.76%   50.84%   +0.08%     
==========================================
  Files        2289     2295       +6     
  Lines       87353    87600     +247     
  Branches    24481    24525      +44     
==========================================
+ Hits        44341    44537     +196     
- Misses      41206    41291      +85     
+ Partials     1806     1772      -34     
Flag Coverage Δ *Carryforward flag
adoption-insights 83.70% <ø> (ø) Carriedforward from fc3f2a0
ai-integrations 67.95% <ø> (ø) Carriedforward from fc3f2a0
app-defaults 69.79% <ø> (ø) Carriedforward from fc3f2a0
augment 46.39% <ø> (ø) Carriedforward from fc3f2a0
boost 73.77% <79.35%> (+0.75%) ⬆️
bulk-import 72.46% <ø> (ø) Carriedforward from fc3f2a0
cost-management 14.10% <ø> (ø) Carriedforward from fc3f2a0
dcm 61.79% <ø> (ø) Carriedforward from fc3f2a0
extensions 61.53% <ø> (ø) Carriedforward from fc3f2a0
global-floating-action-button 71.18% <ø> (ø) Carriedforward from fc3f2a0
global-header 59.71% <ø> (ø) Carriedforward from fc3f2a0
homepage 49.92% <ø> (ø) Carriedforward from fc3f2a0
install-dynamic-plugins 56.77% <ø> (ø) Carriedforward from fc3f2a0
konflux 91.49% <ø> (ø) Carriedforward from fc3f2a0
lightspeed 68.57% <ø> (ø) Carriedforward from fc3f2a0
mcp-integrations 85.46% <ø> (ø) Carriedforward from fc3f2a0
orchestrator 38.30% <ø> (ø) Carriedforward from fc3f2a0
quickstart 63.76% <ø> (ø) Carriedforward from fc3f2a0
sandbox 79.56% <ø> (ø) Carriedforward from fc3f2a0
scorecard 83.96% <ø> (ø) Carriedforward from fc3f2a0
theme 61.26% <ø> (ø) Carriedforward from fc3f2a0
translations 7.25% <ø> (ø) Carriedforward from fc3f2a0
x2a 13.78% <ø> (ø) Carriedforward from fc3f2a0

*This pull request uses carry forward flags. Click here to find out more.


Continue to review full report in Codecov by Harness.

Legend - Click here to learn more
Δ = absolute <relative> (impact), ø = not affected, ? = missing data
Powered by Codecov. Last update 4bf51cc...2546b2d. Read the comment docs.

🚀 New features to boost your workflow:
  • 📦 JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

@fullsend-ai-review

fullsend-ai-review Bot commented Jun 24, 2026

Copy link
Copy Markdown

🤖 Finished Review · ✅ Success · Started 10:20 PM UTC · Completed 10:35 PM UTC
Commit: 4bf51cc · View workflow run →

@fullsend-ai-review

fullsend-ai-review Bot commented Jun 24, 2026

Copy link
Copy Markdown

Review

Findings

Medium

  • [fail-open] workspaces/boost/plugins/boost-backend-module-kagenti/src/provider/KagentiProviderFactory.ts:115 — When boost.providers.kagenti config is absent, the factory silently falls back to http://localhost:8080 and proceeds to register a fully functional provider. A misconfigured deployment will start up and route AI traffic to an arbitrary service on localhost:8080 instead of failing clearly.
    Remediation: Throw an error when the required boost.providers.kagenti config section is missing, or at minimum require baseUrl to be explicitly configured.

  • [error-handling-gap] workspaces/boost/plugins/boost-backend-module-kagenti/src/provider/KagentiProvider.ts:127 — The chat method calls response.json() without a try-catch. If the Kagenti endpoint returns a 200 OK with a malformed (non-JSON) body, this will throw an unhandled SyntaxError rather than a clear domain error.
    Remediation: Wrap the response.json() call in a try-catch and throw a domain-specific error.

Low

  • [uniqueness] workspaces/boost/plugins/boost-backend-module-kagenti/src/provider/KagentiProvider.ts:218 — Task IDs are generated with task-${Date.now()}. Date.now() has millisecond resolution, so two concurrent requests within the same millisecond will produce identical task IDs.

  • [test-inadequate] workspaces/boost/plugins/boost-backend-module-kagenti/src/provider/KagentiProvider.test.ts:142 — There is no test for the task.text.delta streaming event type. The normalizeStreamEvent method handles three event types but only task.status.update variants are tested.

  • [edge-case] workspaces/boost/plugins/boost-backend-module-kagenti/src/provider/KagentiProvider.ts:143 — The SSE parser does not account for multi-line data: fields per the SSE specification. If the A2A endpoint ever sends multi-line data fields, the parser will fail.

  • [data-exposure] workspaces/boost/plugins/boost-backend-module-kagenti/src/provider/KagentiProvider.ts:105 — Error response body from the upstream A2A endpoint is logged verbatim. If the upstream returns sensitive data in error responses, it will be written to the Backstage log.

  • [SSRF] workspaces/boost/plugins/boost-backend-module-kagenti/src/provider/KagentiProvider.ts:83 — The baseUrl from configuration is used directly in fetch() without URL validation. While the config is operator-controlled, adding a protocol check (http/https) would be good defense-in-depth.

Previous run

Review

Findings

High

  • [missing-auth] workspaces/boost/plugins/boost-backend-module-kagenti/src/provider/KagentiProvider.ts:84 — The KagentiProvider makes HTTP requests to the A2A endpoint with only a Content-Type header — no authentication token is attached. The KeycloakTokenCache is instantiated in KagentiProviderFactory but is never passed to or used by KagentiProvider. The types.ts defines a KagentiKeycloakConfig with clientId and clientSecret, but no code path fetches a Keycloak token and injects it as a Bearer token into outbound requests.
    Remediation: Wire KeycloakTokenCache into KagentiProvider so that outbound fetch calls include an `Authorization: Bearer *** header. If auth is intentionally deferred, document as a known limitation and ensure the A2A endpoint is not exposed without network-level access controls.

Medium

  • [error-handling-gap] workspaces/boost/plugins/boost-backend-module-kagenti/src/provider/KagentiProvider.ts:70 — The chat() method does not check the A2A task response status. If the server returns status.state of 'failed' or 'canceled', the method silently returns an empty string instead of throwing an error. The streaming path (chatStream) correctly handles these states by yielding error events, but the non-streaming path ignores them entirely. Callers of chat() cannot distinguish a failed task from a genuinely empty agent reply.
    Remediation: After parsing the A2ATaskResponse, check result.status.state before extracting text. If the state is 'failed' or 'canceled', throw an error with the status message.

  • [edge-case] workspaces/boost/plugins/boost-backend-module-kagenti/src/provider/KeycloakTokenCache.ts:79 — The set method accepts ttlSeconds with no lower-bound validation. If ttlSeconds is zero or negative (e.g., a token that has already expired), the cache will be called with ttl: 0 or a negative value. Behavior of CacheService.set with non-positive TTL is implementation-dependent — it may cache the token indefinitely or reject the call.
    Remediation: Validate ttlSeconds before caching: skip caching if <= 0, or clamp to a minimum value (e.g., 1 second).

Low

  • [ssrf] workspaces/boost/plugins/boost-backend-module-kagenti/src/provider/KagentiProvider.ts:77 — The baseUrl from config is concatenated into fetch URLs without validation. While app-config is operator-controlled (matching the sibling llamastack module pattern), validating the URL shape is a low-cost defense-in-depth measure.

  • [fail-open] workspaces/boost/plugins/boost-backend-module-kagenti/src/provider/KagentiProviderFactory.ts:96 — When boost.providers.kagenti config is absent, the factory falls back to http://localhost:8080. This matches the llamastack module pattern but means the provider is active and making unauthenticated requests if accidentally deployed without config.

  • [test-inadequate] workspaces/boost/plugins/boost-backend-module-kagenti/src/provider/KagentiProvider.test.ts:142 — No test for chat() receiving a failed or canceled task status. The chatStream tests also don't cover the 'failed' state (only 'canceled' and 'completed' are tested).

  • [logic-inconsistency] workspaces/boost/plugins/boost-backend-module-kagenti/src/provider/KagentiProvider.ts:193 — In normalizeStreamEvent, 'completed' yields done inline (immediate return), but 'failed' and 'canceled' do not — the stream continues processing until the connection closes. This asymmetry could cause the caller to hang if the server sends additional events after failure.

  • [edge-case] workspaces/boost/plugins/boost-backend-module-kagenti/src/provider/KagentiProvider.ts:139 — Task IDs use Date.now() which can produce identical IDs for concurrent calls within the same millisecond. Use crypto.randomUUID() or a timestamp+random suffix.

  • [data-exposure] workspaces/boost/plugins/boost-backend-module-kagenti/src/provider/KagentiProvider.ts:91 — Error responses from the A2A endpoint are logged with full response.text() content. If the endpoint returns sensitive info in error bodies, these will appear in Backstage logs.


Labels: PR adds a new AI provider module with A2A protocol integration and auth token caching

Previous run (2)

Review

Findings

Medium

  • [auth-bypass] workspaces/boost/plugins/boost-backend-module-kagenti/src/provider/KagentiProvider.ts:72chat() and chatStream() make outbound HTTP requests to the A2A endpoint with no authentication headers (only Content-Type: application/json). The module defines KagentiKeycloakConfig and builds a KeycloakTokenCache, but neither is wired into KagentiProvider. The sibling llamastack module follows the same scaffold-now/wire-later pattern, but all A2A requests are currently sent unauthenticated. When auth is wired in a future iteration, add a buildHeaders() method (matching the llamastack convention) that retrieves a valid token and attaches it as an Authorization header, and ensure the provider fails closed if authentication is configured but a token cannot be obtained.

  • [logic-error] workspaces/boost/plugins/boost-backend-module-kagenti/src/provider/KagentiProvider.ts:188 — The SSE stream parser in processStream() emits { type: 'done' } unconditionally when the readable stream ends, even if no terminal event (completed, failed, canceled, or [DONE]) was received. A truncated stream (e.g., server crash mid-response) is silently treated as successful completion. The llamastack provider has the same pattern, so this is a pre-existing architectural choice, but worth tracking: consider tracking whether a terminal event was received and yielding an error event for incomplete streams.

Low

  • [missing-test] workspaces/boost/plugins/boost-backend-module-kagenti/src/provider/KagentiProvider.test.ts — The task.text.delta event type (primary streaming text delivery path) and the failed status variant of task.status.update are handled in normalizeStreamEvent but have no test coverage.

  • [fail-open] workspaces/boost/plugins/boost-backend-module-kagenti/src/provider/KagentiProviderFactory.ts:107 — When no boost.providers.kagenti config is present, readConnectionConfig() falls back to http://localhost:8080. This matches the llamastack pattern and a warning is logged, but it is a fail-open default.

  • [dead-code] workspaces/boost/plugins/boost-backend-module-kagenti/src/module.ts:61 — The module creates agentCardCache, keycloakTokenCache, and sessionMap via the factory but immediately voids them. This matches the llamastack module pattern and is documented as intentional scaffolding.

  • [edge-case] workspaces/boost/plugins/boost-backend-module-kagenti/src/provider/KagentiProvider.ts:155 — Task IDs are generated via Date.now(), which can collide under concurrent requests. Consider crypto.randomUUID().

  • [scope-creep] workspaces/boost/plugins/boost-backend-module-kagenti/src/types.ts:63KagentiKeycloakConfig and KagentiNamespace types are defined but never imported or used anywhere in the module.

  • [naming-convention] workspaces/boost/plugins/boost-backend-module-kagenti/src/provider/KagentiProviderFactory.ts — Naming diverges from llamastack convention: llamastack uses protocol-based names (ResponsesApiProvider) while kagenti uses product-based names (KagentiProvider).

  • [error-handling-idiom] workspaces/boost/plugins/boost-backend-module-kagenti/src/provider/KagentiProvider.ts:89chat() wraps fetch in try/catch unlike llamastack which lets fetch errors propagate naturally. The kagenti approach provides better UX but diverges from the sibling module pattern.

  • [api-contract] workspaces/boost/plugins/boost-backend-module-kagenti/src/provider/KagentiProvider.ts:83chat() throws on empty text input while chatStream() yields an error event (same asymmetry as llamastack).

  • [edge-case] workspaces/boost/plugins/boost-backend-module-kagenti/src/provider/AgentCardCache.ts:66 — Pre-parsed array from cache cast as AgentCard[] without runtime validation.


Labels: PR adds a new feature module (Kagenti provider) in the boost workspace

Previous run (3)

Review

Reason: stale-head

The review agent reviewed commit c3ccd9d61939912516578b770b2c7c5606907ec9 but the PR HEAD is now 90364e3240d834e23e1934636b30b0d764608834. This review was discarded to avoid approving unreviewed code.

Previous run (4)

Review

Findings

Medium

  • [scope gap — missing spec requirement] src/module.ts — The provider-packaging spec requires the kagenti module to compose kagenti-entity-provider internally via catalogProcessingExtensionPoint. The module currently only registers the AI provider and does not integrate with the catalog. The sibling llamastack module has the identical omission, establishing this as an accepted incremental delivery pattern.
    Remediation: Either implement the catalogProcessingExtensionPoint integration or explicitly document that entity-provider composition is deferred to a separate issue.

  • [edge-case] src/provider/KagentiProvider.ts:253 — The normalizeStreamEvent method does not handle the 'canceled' task status state. When a task.status.update event arrives with state: 'canceled', no NormalizedStreamEvent is yielded (neither error nor done). The A2ATaskStatus type in types.ts explicitly defines 'canceled' as a valid state, but the consumer receives no indication the task was canceled.
    Remediation: Add a branch for event.status?.state === 'canceled' that yields { type: 'done' } or { type: 'error', message: 'A2A task canceled' } depending on the desired semantics.

  • [test-inadequate] src/provider/KagentiProvider.test.ts — The chatStream tests only cover error paths (empty input, fetch failure, non-ok response). There is no test for the successful streaming path — the SSE parsing logic in processStream and the event normalization in normalizeStreamEvent are untested for the happy path.

  • [Missing Authentication on Outbound Requests] src/provider/KagentiProvider.ts:98 — The provider makes outbound HTTP requests to the A2A endpoint with only Content-Type: application/json headers — no authentication. A KeycloakTokenCache is instantiated by the factory but never wired into the provider. The KagentiKeycloakConfig type is defined in types.ts but the factory never reads Keycloak config from app-config. See also: [scope gap — unused caches] finding.
    Remediation: Wire the KeycloakTokenCache into KagentiProvider and attach a Bearer token to outbound A2A requests, or document that auth is intentionally deferred.

  • [architectural coherence — Zod schema] src/provider/KagentiProviderFactory.ts:97 — AGENTS.md mandates config validation uses Zod schemas as single source of truth with TypeScript types generated from Zod. The readConnectionConfig method uses manual getString/getOptionalString calls without any Zod schema. The llamastack sibling has the same violation.
    Remediation: Define a Zod schema for KagentiConnectionConfig and derive the TypeScript type via z.infer<>().

Low

  • [Fail-Open on Missing Configuration] src/provider/KagentiProviderFactory.ts:96 — When boost.providers.kagenti config is absent, the factory silently falls back to http://localhost:8080. Matches the llamastack sibling pattern.

  • [scope gap — unused caches] src/module.ts:63 — The module instantiates AgentCardCache, KeycloakTokenCache, and SessionMap but immediately suppresses them with void. The caches are not wired into KagentiProvider. Same pattern as the llamastack sibling.

  • [naming convention inconsistency] src/provider/AgentCardCache.ts:68AgentCardCache uses cache.withOptions() for fixed TTL, while KeycloakTokenCache and SessionMap pass TTL per-call. The split is intentional (fixed vs dynamic TTL) and matches the llamastack sibling.

  • [error-handling] src/provider/KagentiProvider.ts:150 — In chat(), if fetch throws, the error propagates as an unhandled exception. In chatStream(), fetch failures are caught and yield a user-friendly error event.

  • [logic-error] src/provider/AgentCardCache.ts:66 — The get() method checks typeof cached === 'string' before parsing. If a cache backend returns an already-parsed object, the method returns undefined. Same pattern in SessionMap.get().

  • [SSRF via Admin-Controlled Config] src/provider/KagentiProvider.ts:92 — The baseUrl from config is concatenated directly into fetch URLs without URL validation. Risk is minimal since config is admin-controlled.

  • [test helper duplication] src/provider/AgentCardCache.test.tscreateMockLogger() and createMockCache() are copy-pasted across all five test files. Consistent with the llamastack sibling.


Labels: PR adds a new Kagenti AI provider module in the boost workspace.

@fullsend-ai-review fullsend-ai-review Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

See the review comment for full details.

Comment thread workspaces/boost/plugins/boost-backend-module-kagenti/src/module.ts
@fullsend-ai-review fullsend-ai-review Bot added requires-manual-review Review requires human judgment workspace/boost Boost workspace (Backstage AI plugin) ai-integrations labels Jun 24, 2026
…handling

- Handle 'canceled' task status in normalizeStreamEvent (yields error event)
- Wrap chat() fetch in try/catch for consistent error handling with chatStream()
- Handle pre-parsed objects from cache backends in AgentCardCache and SessionMap
- Add tests for all three fixes (31 tests passing)

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
@rhdh-qodo-merge

rhdh-qodo-merge Bot commented Jun 24, 2026

Copy link
Copy Markdown

CI Feedback 🧐

(Feedback updated until commit c3ccd9d)

A test triggered by this PR failed. Here is an AI-generated analysis of the failure:

Action: Workspace boost, CI step for node 24

Failed stage: type checking and declarations [❌]

Failed test name: ""

Failure summary:

The action failed during yarn tsc:full because TypeScript compilation errored with TS2352 invalid
type conversions in two files:
-
plugins/boost-backend-module-kagenti/src/provider/AgentCardCache.ts:68: attempted to cast cached
from JsonArray to AgentCard[] (return cached as AgentCard[];), but JsonValue[] doesn’t overlap with
AgentCard (missing id, name, url).
-
plugins/boost-backend-module-kagenti/src/provider/SessionMap.ts:82: attempted to cast cached from
JsonObject to SessionData (return cached as SessionData;), but JsonObject doesn’t overlap with
SessionData (missing sessionId, agentId, createdAt, lastActivity).

As a result, tsc reported “Found 2 errors in 2 files” and the step exited with code 2, failing the
GitHub Action.

Relevant error logs:
1:  ##[group]Runner Image Provisioner
2:  Hosted Compute Agent
...

255:  �[93m➤�[39m YN0002: │ �[38;5;166m@red-hat-developer-hub/�[39m�[38;5;173mbackstage-plugin-boost-backend�[39m�[38;5;111m@�[39m�[38;5;111mworkspace:plugins/boost-backend�[39m doesn't provide �[38;5;173mwebpack�[39m (�[38;5;111mp405fc5�[39m), requested by �[38;5;166m@backstage/�[39m�[38;5;173mcli�[39m.
256:  �[93m➤�[39m YN0002: │ �[38;5;166m@red-hat-developer-hub/�[39m�[38;5;173mbackstage-plugin-boost-common�[39m�[38;5;111m@�[39m�[38;5;111mworkspace:plugins/boost-common [c2cab]�[39m doesn't provide �[38;5;173mwebpack�[39m (�[38;5;111mp8e1e5a�[39m), requested by �[38;5;166m@backstage/�[39m�[38;5;173mcli�[39m.
257:  �[93m➤�[39m YN0002: │ �[38;5;166m@red-hat-developer-hub/�[39m�[38;5;173mbackstage-plugin-boost-common�[39m�[38;5;111m@�[39m�[38;5;111mworkspace:plugins/boost-common�[39m doesn't provide �[38;5;173mwebpack�[39m (�[38;5;111mpe50ee4�[39m), requested by �[38;5;166m@backstage/�[39m�[38;5;173mcli�[39m.
258:  �[93m➤�[39m YN0002: │ �[38;5;166m@red-hat-developer-hub/�[39m�[38;5;173mbackstage-plugin-boost-node�[39m�[38;5;111m@�[39m�[38;5;111mworkspace:plugins/boost-node�[39m doesn't provide �[38;5;173mwebpack�[39m (�[38;5;111mp456cbf�[39m), requested by �[38;5;166m@backstage/�[39m�[38;5;173mcli�[39m.
259:  �[93m➤�[39m YN0086: │ Some peer dependencies are incorrectly met by your project; run �[38;5;111myarn explain peer-requirements <hash>�[39m for details, where �[38;5;111m<hash>�[39m is the six-letter p-prefixed code.
260:  �[93m➤�[39m YN0086: │ Some peer dependencies are incorrectly met by dependencies; run �[38;5;111myarn explain peer-requirements�[39m for details.
261:  ##[endgroup]
262:  �[94m➤�[39m �[90mYN0000�[39m: └ Completed
263:  �[94m➤�[39m �[90mYN0000�[39m: ┌ Fetch step
264:  ##[group]Fetch step
265:  �[94m➤�[39m YN0013: │ �[38;5;220m1670�[39m packages were added to the project (�[38;5;160m+ 514.79 MiB�[39m).
266:  ##[endgroup]
267:  �[94m➤�[39m �[90mYN0000�[39m: └ Completed in 7s 510ms
268:  �[94m➤�[39m �[90mYN0000�[39m: ┌ Link step
269:  ##[group]Link step
270:  �[94m➤�[39m YN0007: │ �[38;5;166m@fission-ai/�[39m�[38;5;173mopenspec�[39m�[38;5;111m@�[39m�[38;5;111mnpm:1.4.1�[39m must be built because it never has been before or the last one failed
271:  �[94m➤�[39m YN0007: │ �[38;5;166m@swc/�[39m�[38;5;173mcore�[39m�[38;5;111m@�[39m�[38;5;111mnpm:1.15.40 [486b9]�[39m must be built because it never has been before or the last one failed
272:  �[94m➤�[39m YN0007: │ �[38;5;173mesbuild�[39m�[38;5;111m@�[39m�[38;5;111mnpm:0.25.12�[39m must be built because it never has been before or the last one failed
273:  �[94m➤�[39m YN0007: │ �[38;5;166m@nestjs/�[39m�[38;5;173mcore�[39m�[38;5;111m@�[39m�[38;5;111mnpm:11.1.21 [26b97]�[39m must be built because it never has been before or the last one failed
274:  �[94m➤�[39m YN0007: │ �[38;5;166m@openapitools/�[39m�[38;5;173mopenapi-generator-cli�[39m�[38;5;111m@�[39m�[38;5;111mnpm:2.34.0�[39m must be built because it never has been before or the last one failed
275:  �[94m➤�[39m YN0007: │ �[38;5;166m@internal/�[39m�[38;5;173mboost�[39m�[38;5;111m@�[39m�[38;5;111mworkspace:.�[39m must be built because it never has been before or the last one failed
276:  �[94m➤�[39m �[90mYN0000�[39m: │ �[38;5;166m@internal/�[39m�[38;5;173mboost�[39m�[38;5;111m@�[39m�[38;5;111mworkspace:.�[39m �[32mSTDOUT�[39m �[93m➤�[39m YN0000: Yarn detected that the current workflow is executed from a public pull request. For safety the hardened mode has been enabled.
...

284:  �[94m➤�[39m �[90mYN0000�[39m: │ �[38;5;166m@internal/�[39m�[38;5;173mboost�[39m�[38;5;111m@�[39m�[38;5;111mworkspace:.�[39m �[32mSTDOUT�[39m �[94m➤�[39m �[90mYN0000�[39m: ┌ Post-resolution validation
285:  �[94m➤�[39m �[90mYN0000�[39m: │ �[38;5;166m@internal/�[39m�[38;5;173mboost�[39m�[38;5;111m@�[39m�[38;5;111mworkspace:.�[39m �[32mSTDOUT�[39m ::group::Post-resolution validation
286:  �[94m➤�[39m �[90mYN0000�[39m: │ �[38;5;166m@internal/�[39m�[38;5;173mboost�[39m�[38;5;111m@�[39m�[38;5;111mworkspace:.�[39m �[32mSTDOUT�[39m �[93m➤�[39m YN0060: │ �[38;5;173mprettier�[39m is listed by your project with version �[38;5;111m3.7.4�[39m (�[38;5;111mpc2ecd8�[39m), which doesn't satisfy what �[38;5;166m@spotify/�[39m�[38;5;173mprettier-config�[39m and other dependencies request (�[38;5;37m^2.0.0�[39m).
287:  �[94m➤�[39m �[90mYN0000�[39m: │ �[38;5;166m@internal/�[39m�[38;5;173mboost�[39m�[38;5;111m@�[39m�[38;5;111mworkspace:.�[39m �[32mSTDOUT�[39m �[93m➤�[39m YN0002: │ �[38;5;166m@redhat-developer/�[39m�[38;5;173mrhdh-plugins�[39m�[38;5;111m@�[39m�[38;5;111mworkspace:.�[39m doesn't provide �[38;5;166m@typescript-eslint/�[39m�[38;5;173mparser�[39m (�[38;5;111mp8d7c5c�[39m), requested by �[38;5;166m@spotify/�[39m�[38;5;173meslint-plugin�[39m.
288:  �[94m➤�[39m �[90mYN0000�[39m: │ �[38;5;166m@internal/�[39m�[38;5;173mboost�[39m�[38;5;111m@�[39m�[38;5;111mworkspace:.�[39m �[32mSTDOUT�[39m �[93m➤�[39m YN0086: │ Some peer dependencies are incorrectly met by your project; run �[38;5;111myarn explain peer-requirements <hash>�[39m for details, where �[38;5;111m<hash>�[39m is the six-letter p-prefixed code.
289:  �[94m➤�[39m �[90mYN0000�[39m: │ �[38;5;166m@internal/�[39m�[38;5;173mboost�[39m�[38;5;111m@�[39m�[38;5;111mworkspace:.�[39m �[32mSTDOUT�[39m �[93m➤�[39m YN0086: │ Some peer dependencies are incorrectly met by dependencies; run �[38;5;111myarn explain peer-requirements�[39m for details.
290:  �[94m➤�[39m �[90mYN0000�[39m: │ �[38;5;166m@internal/�[39m�[38;5;173mboost�[39m�[38;5;111m@�[39m�[38;5;111mworkspace:.�[39m �[32mSTDOUT�[39m ::endgroup::
291:  �[94m➤�[39m �[90mYN0000�[39m: │ �[38;5;166m@internal/�[39m�[38;5;173mboost�[39m�[38;5;111m@�[39m�[38;5;111mworkspace:.�[39m �[32mSTDOUT�[39m �[94m➤�[39m �[90mYN0000�[39m: └ Completed
292:  �[94m➤�[39m �[90mYN0000�[39m: │ �[38;5;166m@internal/�[39m�[38;5;173mboost�[39m�[38;5;111m@�[39m�[38;5;111mworkspace:.�[39m �[32mSTDOUT�[39m �[94m➤�[39m �[90mYN0000�[39m: ┌ Fetch step
293:  �[94m➤�[39m �[90mYN0000�[39m: │ �[38;5;166m@internal/�[39m�[38;5;173mboost�[39m�[38;5;111m@�[39m�[38;5;111mworkspace:.�[39m �[32mSTDOUT�[39m ::group::Fetch step
294:  �[94m➤�[39m �[90mYN0000�[39m: │ �[38;5;166m@internal/�[39m�[38;5;173mboost�[39m�[38;5;111m@�[39m�[38;5;111mworkspace:.�[39m �[32mSTDOUT�[39m �[94m➤�[39m YN0013: │ �[38;5;220m690�[39m packages were added to the project (�[38;5;160m+ 288.05 MiB�[39m).
295:  �[94m➤�[39m �[90mYN0000�[39m: │ �[38;5;166m@internal/�[39m�[38;5;173mboost�[39m�[38;5;111m@�[39m�[38;5;111mworkspace:.�[39m �[32mSTDOUT�[39m ::endgroup::
296:  �[94m➤�[39m �[90mYN0000�[39m: │ �[38;5;166m@internal/�[39m�[38;5;173mboost�[39m�[38;5;111m@�[39m�[38;5;111mworkspace:.�[39m �[32mSTDOUT�[39m �[94m➤�[39m �[90mYN0000�[39m: └ Completed in 4s 449ms
297:  �[94m➤�[39m �[90mYN0000�[39m: │ �[38;5;166m@internal/�[39m�[38;5;173mboost�[39m�[38;5;111m@�[39m�[38;5;111mworkspace:.�[39m �[32mSTDOUT�[39m �[94m➤�[39m �[90mYN0000�[39m: ┌ Link step
298:  �[94m➤�[39m �[90mYN0000�[39m: │ �[38;5;166m@internal/�[39m�[38;5;173mboost�[39m�[38;5;111m@�[39m�[38;5;111mworkspace:.�[39m �[32mSTDOUT�[39m ::group::Link step
299:  �[94m➤�[39m �[90mYN0000�[39m: │ �[38;5;166m@internal/�[39m�[38;5;173mboost�[39m�[38;5;111m@�[39m�[38;5;111mworkspace:.�[39m �[32mSTDOUT�[39m �[94m➤�[39m YN0007: │ �[38;5;173mesbuild�[39m�[38;5;111m@�[39m�[38;5;111mnpm:0.21.5�[39m must be built because it never has been before or the last one failed
300:  �[94m➤�[39m �[90mYN0000�[39m: │ �[38;5;166m@internal/�[39m�[38;5;173mboost�[39m�[38;5;111m@�[39m�[38;5;111mworkspace:.�[39m �[32mSTDOUT�[39m �[94m➤�[39m YN0007: │ �[38;5;166m@swc/�[39m�[38;5;173mcore�[39m�[38;5;111m@�[39m�[38;5;111mnpm:1.4.13 [366d3]�[39m must be built because it never has been before or the last one failed
301:  �[94m➤�[39m �[90mYN0000�[39m: │ �[38;5;166m@internal/�[39m�[38;5;173mboost�[39m�[38;5;111m@�[39m�[38;5;111mworkspace:.�[39m �[32mSTDOUT�[39m �[94m➤�[39m YN0007: │ �[38;5;173mesbuild�[39m�[38;5;111m@�[39m�[38;5;111mnpm:0.23.1�[39m must be built because it never has been before or the last one failed
302:  �[94m➤�[39m �[90mYN0000�[39m: │ �[38;5;166m@internal/�[39m�[38;5;173mboost�[39m�[38;5;111m@�[39m�[38;5;111mworkspace:.�[39m �[32mSTDOUT�[39m �[94m➤�[39m YN0007: │ �[38;5;173mesbuild�[39m�[38;5;111m@�[39m�[38;5;111mnpm:0.20.2�[39m must be built because it never has been before or the last one failed
303:  �[94m➤�[39m �[90mYN0000�[39m: │ �[38;5;166m@internal/�[39m�[38;5;173mboost�[39m�[38;5;111m@�[39m�[38;5;111mworkspace:.�[39m �[32mSTDOUT�[39m �[94m➤�[39m YN0007: │ �[38;5;173mcore-js-pure�[39m�[38;5;111m@�[39m�[38;5;111mnpm:3.36.1�[39m must be built because it never has been before or the last one failed
304:  �[94m➤�[39m �[90mYN0000�[39m: │ �[38;5;166m@internal/�[39m�[38;5;173mboost�[39m�[38;5;111m@�[39m�[38;5;111mworkspace:.�[39m �[32mSTDOUT�[39m �[94m➤�[39m YN0007: │ �[38;5;166m@redhat-developer/�[39m�[38;5;173mrhdh-plugins�[39m�[38;5;111m@�[39m�[38;5;111mworkspace:.�[39m must be built because it never has been before or the last one failed
305:  �[94m➤�[39m �[90mYN0000�[39m: │ �[38;5;166m@internal/�[39m�[38;5;173mboost�[39m�[38;5;111m@�[39m�[38;5;111mworkspace:.�[39m �[32mSTDOUT�[39m ::endgroup::
...

314:  env:
315:  CI: true
316:  NODE_OPTIONS: --max-old-space-size=8192
317:  NPM_CONFIG_USERCONFIG: /home/runner/work/_temp/.npmrc
318:  NODE_AUTH_TOKEN: XXXXX-XXXXX-XXXXX-XXXXX
319:  ##[endgroup]
320:  ##[group]Run yarn tsc:full
321:  �[36;1myarn tsc:full�[0m
322:  shell: /usr/bin/bash -e {0}
323:  env:
324:  CI: true
325:  NODE_OPTIONS: --max-old-space-size=8192
326:  NPM_CONFIG_USERCONFIG: /home/runner/work/_temp/.npmrc
327:  NODE_AUTH_TOKEN: XXXXX-XXXXX-XXXXX-XXXXX
328:  ##[endgroup]
329:  �[96mplugins/boost-backend-module-kagenti/src/provider/AgentCardCache.ts�[0m:�[93m68�[0m:�[93m14�[0m - �[91merror�[0m�[90m TS2352: �[0mConversion of type 'JsonArray' to type 'AgentCard[]' may be a mistake because neither type sufficiently overlaps with the other. If this was intentional, convert the expression to 'unknown' first.
330:  Type 'JsonValue' is not comparable to type 'AgentCard'.
331:  Type 'JsonValue[]' is missing the following properties from type 'AgentCard': id, name, url
332:  �[7m68�[0m       return cached as AgentCard[];
333:  �[7m  �[0m �[91m             ~~~~~~~~~~~~~~~~~~~~~�[0m
334:  �[96mplugins/boost-backend-module-kagenti/src/provider/SessionMap.ts�[0m:�[93m82�[0m:�[93m14�[0m - �[91merror�[0m�[90m TS2352: �[0mConversion of type 'JsonObject' to type 'SessionData' may be a mistake because neither type sufficiently overlaps with the other. If this was intentional, convert the expression to 'unknown' first.
335:  Type 'JsonObject' is missing the following properties from type 'SessionData': sessionId, agentId, createdAt, lastActivity
336:  �[7m82�[0m       return cached as SessionData;
337:  �[7m  �[0m �[91m             ~~~~~~~~~~~~~~~~~~~~~�[0m
338:  Found 2 errors in 2 files.
339:  Errors  Files
340:  1  plugins/boost-backend-module-kagenti/src/provider/AgentCardCache.ts�[90m:68�[0m
341:  1  plugins/boost-backend-module-kagenti/src/provider/SessionMap.ts�[90m:82�[0m
342:  ##[error]Process completed with exit code 2.
343:  Node 20 is being deprecated. This workflow is running with Node 24 by default. If you need to temporarily use Node 20, you can set the ACTIONS_ALLOW_USE_UNSECURE_NODE_VERSION=true environment variable. For more information see: https://github.blog/changelog/2025-09-19-deprecation-of-node-20-on-github-actions-runners/

@fullsend-ai-review

fullsend-ai-review Bot commented Jun 24, 2026

Copy link
Copy Markdown

🤖 Finished Review · ✅ Success · Started 11:03 PM UTC · Completed 11:15 PM UTC
Commit: 4bf51cc · View workflow run →

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
@fullsend-ai-review

Copy link
Copy Markdown

/fs-review

@fullsend-ai-review

fullsend-ai-review Bot commented Jun 24, 2026

Copy link
Copy Markdown

🤖 Finished Review · ✅ Success · Started 11:18 PM UTC · Completed 11:32 PM UTC
Commit: 4bf51cc · View workflow run →

@fullsend-ai-review fullsend-ai-review Bot added requires-manual-review Review requires human judgment feature and removed requires-manual-review Review requires human judgment labels Jun 24, 2026
The provider-packaging spec referenced catalogProcessingExtensionPoint
entity provider composition in both module registration scenarios.
That work is tracked in the agent-creation-discovery change (issue #3308),
not in the provider module issues. Added cross-reference annotations.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
@fullsend-ai-review

fullsend-ai-review Bot commented Jun 25, 2026

Copy link
Copy Markdown

🤖 Finished Review · ✅ Success · Started 12:00 AM UTC · Completed 12:31 AM UTC
Commit: 4bf51cc · View workflow run →

@fullsend-ai-review fullsend-ai-review Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

See the review comment for full details.

@fullsend-ai-review fullsend-ai-review Bot removed the requires-manual-review Review requires human judgment label Jun 25, 2026
…idate TTL

- chat() now throws on failed/canceled A2A task status instead of
  returning empty string
- normalizeStreamEvent yields done after failed/canceled for symmetry
  with completed state (stream terminates immediately)
- KeycloakTokenCache.set() skips cache for non-positive TTL values
- Added tests: chat() failed/canceled, chatStream failed, TTL validation

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
@fullsend-ai-review

fullsend-ai-review Bot commented Jun 25, 2026

Copy link
Copy Markdown

🤖 Finished Review · ❌ Failure · Started 12:50 AM UTC · Completed 1:07 AM UTC
Commit: 4bf51cc · View workflow run →

@fullsend-ai-review

fullsend-ai-review Bot commented Jun 25, 2026

Copy link
Copy Markdown

🤖 Finished Review · ✅ Success · Started 1:15 AM UTC · Completed 1:26 AM UTC
Commit: 4bf51cc · View workflow run →

@fullsend-ai-review fullsend-ai-review Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

See the review comment for full details.

@fullsend-ai-review fullsend-ai-review Bot added the requires-manual-review Review requires human judgment label Jun 25, 2026
@gabemontero
gabemontero merged commit 8c01306 into main Jun 25, 2026
91 of 105 checks passed
@gabemontero
gabemontero deleted the agent/3307-kagenti-provider-module branch June 25, 2026 01:40
@sonarqubecloud

Copy link
Copy Markdown

Quality Gate Failed Quality Gate failed

Failed conditions
7.5% Duplication on New Code (required ≤ 3%)

See analysis details on SonarQube Cloud

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

Labels

ai-integrations feature requires-manual-review Review requires human judgment workspace/boost Boost workspace (Backstage AI plugin)

Projects

None yet

Development

Successfully merging this pull request may close these issues.

boost-backend-module-kagenti — Kagenti provider module (issue 11 of 15)

1 participant