Skip to content
Closed
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
Original file line number Diff line number Diff line change
Expand Up @@ -177,6 +177,10 @@ export function registerAgentRoutes(
version: cfg?.version ?? 0,
promotedAt: cfg?.promotedAt,
promotedBy: cfg?.promotedBy,
createdBy: cfg?.createdBy,
rejectionReason: cfg?.rejectionReason,
rejectedBy: cfg?.rejectedBy,
rejectedAt: cfg?.rejectedAt,
};
}

Expand Down Expand Up @@ -311,6 +315,11 @@ export function registerAgentRoutes(
existing.version = (existing.version ?? 0) + 1;
existing.promotedAt = now;
existing.promotedBy = userRef;
if (isSubmitForReview) {
existing.rejectionReason = undefined;
existing.rejectedBy = undefined;
existing.rejectedAt = undefined;
}
} else {
configs.push({
agentId,
Expand Down Expand Up @@ -363,7 +372,10 @@ export function registerAgentRoutes(
'Failed to demote agent',
async (req, res) => {
const agentId = decodeURIComponent(req.params.agentId);
const { targetStage } = req.body as { targetStage?: string };
const { targetStage, reason } = req.body as {
targetStage?: string;
reason?: string;
};
const resolved = targetStage
? normalizeLifecycleStage(targetStage)
: undefined;
Expand Down Expand Up @@ -393,6 +405,7 @@ export function registerAgentRoutes(

const now = new Date().toISOString();
const isProd = isProductionStage(nextStage);
const isRejection = currentStage === 'review' && nextStage === 'draft';

if (existing) {
existing.lifecycleStage = nextStage;
Expand All @@ -403,6 +416,11 @@ export function registerAgentRoutes(
}
existing.promotedAt = now;
existing.promotedBy = userRef;
if (isRejection) {
existing.rejectionReason = reason || undefined;
existing.rejectedBy = userRef;
existing.rejectedAt = now;
}
} else {
configs.push({
agentId,
Expand All @@ -422,7 +440,12 @@ export function registerAgentRoutes(
target: agentId,
outcome: 'success',
sourceIp: AuditLogger.extractIp(req),
meta: { from: currentStage, to: nextStage, direction: 'demote' },
meta: {
from: currentStage,
to: nextStage,
direction: 'demote',
...(isRejection && reason ? { rejectionReason: reason } : {}),
},
});
logger.info(`Agent "${agentId}" demoted to ${nextStage} by ${userRef}`);
res.json({ success: true, agentId, lifecycleStage: nextStage });
Expand Down
8 changes: 8 additions & 0 deletions workspaces/augment/plugins/augment-common/report.api.md
Original file line number Diff line number Diff line change
Expand Up @@ -257,6 +257,7 @@ export interface ChatAgent {
agentRole?: AgentRole;
avatarUrl?: string;
createdAt?: string;
createdBy?: string;
description?: string;
framework?: string;
id: string;
Expand All @@ -269,6 +270,9 @@ export interface ChatAgent {
protocols?: string[];
providerType: string;
published?: boolean;
rejectedAt?: string;
rejectedBy?: string;
rejectionReason?: string;
source?: string;
starters?: string[];
status: string;
Expand All @@ -281,6 +285,7 @@ export interface ChatAgentConfig {
agentId: string;
avatarUrl?: string;
conversationStarters?: string[];
createdBy?: string;
description?: string;
displayName?: string;
featured: boolean;
Expand All @@ -290,6 +295,9 @@ export interface ChatAgentConfig {
promotedAt?: string;
promotedBy?: string;
published: boolean;
rejectedAt?: string;
rejectedBy?: string;
rejectionReason?: string;
version?: number;
visible: boolean;
}
Expand Down
16 changes: 16 additions & 0 deletions workspaces/augment/plugins/augment-common/src/types/shared.ts
Original file line number Diff line number Diff line change
Expand Up @@ -404,6 +404,14 @@ export interface ChatAgentConfig {
greeting?: string;
/** Suggested prompts shown on the agent card and below the input */
conversationStarters?: string[];
/** User ref of who originally created this agent config entry */
createdBy?: string;
/** Reason provided by admin when rejecting (demoting review→draft) */
rejectionReason?: string;
/** User ref of who rejected this agent */
rejectedBy?: string;
/** ISO timestamp of when the rejection occurred */
rejectedAt?: string;
}

/**
Expand Down Expand Up @@ -614,6 +622,14 @@ export interface ChatAgent {
promotedBy?: string;
/** Role of this agent in the orchestration topology */
agentRole?: AgentRole;
/** User ref of who originally created this agent */
createdBy?: string;
/** Reason provided by admin when rejecting (demoting review→draft) */
rejectionReason?: string;
/** User ref of who rejected this agent */
rejectedBy?: string;
/** ISO timestamp of when the rejection occurred */
rejectedAt?: string;
}

/**
Expand Down
1 change: 1 addition & 0 deletions workspaces/augment/plugins/augment/report.api.md
Original file line number Diff line number Diff line change
Expand Up @@ -181,6 +181,7 @@ export interface AugmentApi {
demoteAgent(
agentId: string,
targetStage?: AgentLifecycleStage,
reason?: string,
): Promise<{
lifecycleStage: string;
}>;
Expand Down
5 changes: 4 additions & 1 deletion workspaces/augment/plugins/augment/src/api/AugmentApi.ts
Original file line number Diff line number Diff line change
Expand Up @@ -93,10 +93,12 @@ export interface AugmentApi {

/**
* Demote an agent to a previous lifecycle stage (deployed → registered → draft).
* @param reason - optional rejection reason (used when demoting review→draft)
*/
demoteAgent(
agentId: string,
targetStage?: import('@red-hat-developer-hub/backstage-plugin-augment-common').AgentLifecycleStage,
reason?: string,
): Promise<{ lifecycleStage: string }>;

/**
Expand Down Expand Up @@ -775,11 +777,12 @@ export class AugmentApiClient implements AugmentApi {
async demoteAgent(
agentId: string,
targetStage?: import('@red-hat-developer-hub/backstage-plugin-augment-common').AgentLifecycleStage,
reason?: string,
): Promise<{ lifecycleStage: string }> {
return this.fetchJson(`/agents/${encodeURIComponent(agentId)}/demote`, {
method: 'PUT',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ targetStage }),
body: JSON.stringify({ targetStage, reason }),
});
}

Expand Down
Loading