Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
45 changes: 45 additions & 0 deletions workspaces/boost/dynamic-plugins-filesystem-reference.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
# Example dynamic-plugins.yaml for local/development Boost deployment in RHDH
#
# This file shows how to configure Boost as a dynamic plugin in Red Hat
# Developer Hub using local filesystem paths. Use this for development
# and testing. For production OCI deployments, see
# dynamic-plugins-image-reference.yaml.
#
# Each plugin is loaded from a local path under dynamic-plugins/dist/.
# The package names follow the RHDH dynamic plugin naming convention:
# red-hat-developer-hub-backstage-plugin-<name>-dynamic
#
# For more information on RHDH dynamic plugins, see:
# https://docs.redhat.com/en/documentation/red_hat_developer_hub

plugins:
# -----------------------------------------------------------------------
# Core backend plugin — required
# -----------------------------------------------------------------------
- package: ./dynamic-plugins/dist/red-hat-developer-hub-backstage-plugin-boost-backend-dynamic
disabled: false
pluginConfig:
boost:
# Security mode: 'full' for production, 'development-only-no-auth' for local dev
security:
mode: full
model:
baseUrl: ${BOOST_MODEL_BASE_URL}
name: ${BOOST_MODEL_NAME}
# Skills marketplace (optional):
# features:
# skillsMarketplace: true
# skillsMarketplace:
# endpoint: http://skills-catalog.example.com

# -----------------------------------------------------------------------
# Provider modules — install at least one
# -----------------------------------------------------------------------

# Llama Stack provider: connects to a Llama Stack Responses API endpoint
- package: ./dynamic-plugins/dist/red-hat-developer-hub-backstage-plugin-boost-backend-module-llamastack-dynamic
disabled: false

# Kagenti provider: connects to a Kagenti multi-agent orchestrator
- package: ./dynamic-plugins/dist/red-hat-developer-hub-backstage-plugin-boost-backend-module-kagenti-dynamic
disabled: true
44 changes: 44 additions & 0 deletions workspaces/boost/dynamic-plugins-image-reference.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
# Example dynamic-plugins.yaml for production Boost deployment in RHDH
#
# This file shows how to configure Boost as a dynamic plugin in Red Hat
# Developer Hub using OCI container images. Use this for production
# deployments. For local development, see
# dynamic-plugins-filesystem-reference.yaml.
#
# Each plugin is loaded from an OCI artifact in a container registry.
# Replace <registry> and <tag> with your actual registry and version.
#
# For more information on RHDH dynamic plugins, see:
# https://docs.redhat.com/en/documentation/red_hat_developer_hub

plugins:
# -----------------------------------------------------------------------
# Core backend plugin — required
# -----------------------------------------------------------------------
- package: oci://<registry>/backstage-plugin-boost-backend:<tag>!red-hat-developer-hub-backstage-plugin-boost-backend-dynamic
disabled: false
pluginConfig:
boost:
# Security mode: 'full' for production, 'development-only-no-auth' for local dev
security:
mode: full
model:
baseUrl: ${BOOST_MODEL_BASE_URL}
name: ${BOOST_MODEL_NAME}
# Skills marketplace (optional):
# features:
# skillsMarketplace: true
# skillsMarketplace:
# endpoint: http://skills-catalog.example.com

# -----------------------------------------------------------------------
# Provider modules — install at least one
# -----------------------------------------------------------------------

# Llama Stack provider: connects to a Llama Stack Responses API endpoint
- package: oci://<registry>/backstage-plugin-boost-backend-module-llamastack:<tag>!red-hat-developer-hub-backstage-plugin-boost-backend-module-llamastack-dynamic
disabled: false

# Kagenti provider: connects to a Kagenti multi-agent orchestrator
- package: oci://<registry>/backstage-plugin-boost-backend-module-kagenti:<tag>!red-hat-developer-hub-backstage-plugin-boost-backend-module-kagenti-dynamic
disabled: true
Original file line number Diff line number Diff line change
Expand Up @@ -100,7 +100,6 @@ The following new features MUST have runtime configuration fields as specified b
| Field | Scope | Description |
|---|---|---|
| `boost.skillsMarketplace.endpoint` | yaml-only | Skills catalog backend URL |
| `boost.skillsMarketplace.enabled` | db-overridable | Enable/disable skills marketplace |

#### Scenario: Token exchange configuration

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -61,3 +61,48 @@
- [ ] 7.2 Verify hot-swap works with modular provider packages
- [ ] 7.3 Verify cache behavior in both in-memory and Redis-backed modes
- [ ] 7.4 Verify no provider ID string checks in frontend — all capability-based

## 8. Skills Marketplace Integration (P1)

### Design decisions (from grill-me review):

- Runtimes are **local app-config**, not proxied from the external catalog.
`boost.skillsMarketplace.runtimes[]` defines which agent execution frameworks
this RHDH instance supports (e.g. DocsClaw, ZeroClaw). Each entry has `id`,
`name`, `description`, `image`, `language`, `footprint`, `features[]`, `status`.
- Deploy endpoint accepts `runtimeId` in the request body; the backend resolves
the container image from config server-side. Frontend never sees registry URLs.
- Manifest generation is extracted into `src/skills/manifestBuilder.ts` for
independent testability and future extension (Service, ConfigMap, Secret).
- Reference implementation: augment workspace `agent-creation-discovery` section 5
and UC-23 flow diagram. Boost is a clean room re-implementation — endpoint paths
and internal structure may diverge from augment.

### 8a. Skills catalog proxy routes

- [x] 8a.1 Implement `GET /skills` proxy to external skills catalog backend
- [x] 8a.2 Implement `GET /skills/domains` proxy to external skills catalog backend
- [ ] 8a.3 Add proxy tests for `GET /skills` and `GET /skills/domains` (mock fetch, verify URL construction, query param forwarding, feature gate, permission checks, non-JSON handling)

### 8b. Skills runtimes from config

- [ ] 8b.1 Add `boost.skillsMarketplace.runtimes[]` Zod schema to `schemas.ts` (`yaml-only` scope) with fields: `id`, `name`, `description`, `image`, `language`, `footprint`, `features[]`, `status`
- [ ] 8b.2 Refactor `GET /skills/runtimes` to read from local app-config instead of proxying to external catalog
- [ ] 8b.3 Add tests for `GET /skills/runtimes` (reads config, returns runtime list, feature gate)

### 8c. Deployment with runtime resolution

- [ ] 8c.1 Change `POST /skills/deploy` request body to accept `runtimeId` instead of `ociImage`; resolve container image from `boost.skillsMarketplace.runtimes[]` config
- [ ] 8c.2 Extract manifest generation into `src/skills/manifestBuilder.ts`
- [ ] 8c.3 Update deploy tests for `runtimeId` resolution and `manifestBuilder` unit tests

### 8d. Skills browse UI

- [ ] 8d.1 Implement skills browse UI with runtime and domain filters (consuming proxied data)
- [ ] 8d.2 Add skill badge to gallery for framework agents
- [ ] 8d.3 Route chat to skill agents via `chatEndpoint` field

### 8e. Deployment progress

- [ ] 8e.1 Implement deployment status persistence (replace current stub)
- [ ] 8e.2 Add deployment progress polling and status display in UI
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,8 @@
"@red-hat-developer-hub/backstage-plugin-boost-node": "workspace:^"
},
"devDependencies": {
"@backstage/cli": "^0.34.5"
"@backstage/cli": "^0.34.5",
"@red-hat-developer-hub/cli": "^1.11.1"
},
"sideEffects": false,
"scripts": {
Expand All @@ -49,10 +50,13 @@
"tsc": "tsc",
"start": "backstage-cli package start",
"prepack": "backstage-cli package prepack",
"postpack": "backstage-cli package postpack"
"postpack": "backstage-cli package postpack",
"export-dynamic": "rhdh-cli plugin export"
},
"files": [
"dist"
"dist",
"dist-dynamic/*.*",
"dist-dynamic/dist/**"
],
"repository": {
"type": "git",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,8 @@
"@red-hat-developer-hub/backstage-plugin-boost-responses-api-toolkit": "workspace:^"
},
"devDependencies": {
"@backstage/cli": "^0.34.5"
"@backstage/cli": "^0.34.5",
"@red-hat-developer-hub/cli": "^1.11.1"
},
"sideEffects": false,
"scripts": {
Expand All @@ -50,10 +51,13 @@
"tsc": "tsc",
"start": "backstage-cli package start",
"prepack": "backstage-cli package prepack",
"postpack": "backstage-cli package postpack"
"postpack": "backstage-cli package postpack",
"export-dynamic": "rhdh-cli plugin export"
},
"files": [
"dist"
"dist",
"dist-dynamic/*.*",
"dist-dynamic/dist/**"
],
"repository": {
"type": "git",
Expand Down
6 changes: 0 additions & 6 deletions workspaces/boost/plugins/boost-backend/config.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -93,12 +93,6 @@ export interface Config {
* @configScope yaml-only
*/
endpoint?: string;
/**
* Enable or disable skills marketplace.
* @visibility frontend
* @configScope db-overridable
*/
enabled?: boolean;
};

/** Kagenti provider configuration. */
Expand Down
8 changes: 6 additions & 2 deletions workspaces/boost/plugins/boost-backend/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,7 @@
},
"devDependencies": {
"@backstage/cli": "^0.34.5",
"@red-hat-developer-hub/cli": "^1.11.1",
"@types/express": "4.17.25"
},
"sideEffects": false,
Expand All @@ -57,10 +58,13 @@
"tsc": "tsc",
"start": "backstage-cli package start",
"prepack": "backstage-cli package prepack",
"postpack": "backstage-cli package postpack"
"postpack": "backstage-cli package postpack",
"export-dynamic": "rhdh-cli plugin export"
},
"files": [
"dist"
"dist",
"dist-dynamic/*.*",
"dist-dynamic/dist/**"
],
"repository": {
"type": "git",
Expand Down
48 changes: 30 additions & 18 deletions workspaces/boost/plugins/boost-backend/report.api.md
Original file line number Diff line number Diff line change
Expand Up @@ -126,74 +126,75 @@ export const boostConfigFields: {
readonly 'boost.model.baseUrl': {
readonly schema: z.ZodString;
readonly configScope: ConfigScope;
readonly description: 'Base URL for the AI model endpoint';
readonly description: string;
};
readonly 'boost.model.name': {
readonly schema: z.ZodString;
readonly configScope: ConfigScope;
readonly description: 'Name of the AI model to use';
readonly description: string;
};
readonly 'boost.systemPrompt': {
readonly schema: z.ZodOptional<z.ZodString>;
readonly configScope: ConfigScope;
readonly description: 'System prompt for AI conversations';
readonly description: string;
};
readonly 'boost.security.mode': {
readonly schema: z.ZodEnum<
['development-only-no-auth', 'plugin-only', 'full']
>;
readonly configScope: ConfigScope;
readonly description: 'Security mode for the boost plugin';
readonly description: string;
};
readonly 'boost.features.agentCreation': {
readonly schema: z.ZodOptional<z.ZodBoolean>;
readonly configScope: ConfigScope;
readonly description: 'Enable agent creation feature';
readonly description: string;
};
readonly 'boost.features.skillsMarketplace': {
readonly schema: z.ZodOptional<z.ZodBoolean>;
readonly configScope: ConfigScope;
readonly description: 'Enable skills marketplace feature';
readonly description: string;
};
readonly 'boost.agentApproval.mode': {
readonly schema: z.ZodOptional<z.ZodEnum<['built-in', 'sonataflow']>>;
readonly configScope: ConfigScope;
readonly description: 'Agent approval mode: built-in or SonataFlow-managed';
readonly description: string;
};
readonly 'boost.agentApproval.sonataflow.endpoint': {
readonly schema: z.ZodOptional<z.ZodString>;
readonly configScope: ConfigScope;
readonly description: 'SonataFlow workflow endpoint for agent approval';
readonly description: string;
};
readonly 'boost.skillsMarketplace.endpoint': {
readonly schema: z.ZodOptional<z.ZodString>;
readonly configScope: ConfigScope;
readonly description: 'Skills catalog backend URL';
};
readonly 'boost.skillsMarketplace.enabled': {
readonly schema: z.ZodOptional<z.ZodBoolean>;
readonly configScope: ConfigScope;
readonly description: 'Enable or disable skills marketplace';
readonly description: string;
};
readonly 'boost.kagenti.auth.tokenExchange.enabled': {
readonly schema: z.ZodOptional<z.ZodBoolean>;
readonly configScope: ConfigScope;
readonly description: 'Enable RFC 8693 token exchange for Kagenti';
readonly description: string;
};
readonly 'boost.kagenti.auth.tokenExchange.audience': {
readonly schema: z.ZodOptional<z.ZodString>;
readonly configScope: ConfigScope;
readonly description: 'Target audience for exchanged token';
readonly description: string;
};
readonly 'boost.kagenti.auth.tokenExchange.userTokenHeader': {
readonly schema: z.ZodOptional<z.ZodString>;
readonly configScope: ConfigScope;
readonly description: 'Header containing user OIDC token';
readonly description: string;
};
readonly 'boost.encryptionSecret': {
readonly schema: z.ZodOptional<z.ZodString>;
readonly configScope: ConfigScope;
readonly description: string;
readonly sensitive: true;
};
readonly 'boost.devSpaces.credentials': {
readonly schema: z.ZodOptional<z.ZodString>;
readonly configScope: ConfigScope;
readonly description: 'DevSpaces integration credentials';
readonly description: string;
readonly sensitive: true;
};
};
Expand Down Expand Up @@ -328,6 +329,9 @@ export function createKagentiAdminRoutes(
// @public
export function createMcpServerRoutes(options: McpServerRoutesOptions): Router;

// @public
export function createSkillsRoutes(options: SkillsRoutesOptions): Router;

// @public
export function createToolResourceLoader(): ResourceLoader;

Expand Down Expand Up @@ -473,6 +477,14 @@ export interface RuntimeConfigResolverOptions {
// @public
export type SecurityMode = 'development-only-no-auth' | 'plugin-only' | 'full';

// @public
export interface SkillsRoutesOptions {
config: RootConfigService;
httpAuth: HttpAuthService;
logger: LoggerService;
permissions: PermissionsService;
}

// @public
export class ToolLifecycleStore {
constructor(options: ToolLifecycleStoreOptions);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -36,8 +36,8 @@ describe('boostConfigFields', () => {
expect(keys).toContain('boost.security.mode');
expect(keys).toContain('boost.features.agentCreation');
expect(keys).toContain('boost.agentApproval.mode');
expect(keys).toContain('boost.skillsMarketplace.enabled');
expect(keys).toContain('boost.kagenti.auth.tokenExchange.enabled');
expect(keys).toContain('boost.encryptionSecret');
expect(keys).toContain('boost.devSpaces.credentials');
});

Expand Down Expand Up @@ -121,11 +121,13 @@ describe('isDbWritable', () => {
expect(isDbWritable('boost.kagenti.auth.tokenExchange.enabled')).toBe(
false,
);
expect(isDbWritable('boost.encryptionSecret')).toBe(false);
});
});

describe('isSensitiveField', () => {
it('returns true for sensitive fields', () => {
expect(isSensitiveField('boost.encryptionSecret')).toBe(true);
expect(isSensitiveField('boost.devSpaces.credentials')).toBe(true);
});

Expand Down
Loading
Loading