v2 platform foundation (docs 01/02/03): Action Runtime + Registry + unified API
- v2 foundation: ActionResult/DevError/ActorContext/ResourceRef/Execution types - ActionRegistry + ResourceRegistry (namespaced types, FAIL FAST on duplicates) - ActionRuntime pipeline: validate -> authorize -> middleware -> handler -> output validation -> audit -> event -> execution persisted (devos_action_executions) - Legacy bridge: v1 services registered as devops.*/core.* resources & actions (47 actions, 9 resources) - Unified Action API: POST /api/v2/actions/:actionId, GET discovery (actions/resources) - 10 v2 unit tests (registry fail-fast, validation, authz, failure audit, events)
This commit is contained in:
@@ -0,0 +1,77 @@
|
||||
/**
|
||||
* # v2 统一 Action API(docs 03 §48/§90/§91)
|
||||
* - GET /api/v2/actions Action Discovery
|
||||
* - GET /api/v2/actions/:id 单个 Action 契约
|
||||
* - POST /api/v2/actions/:actionId 执行(六入口之一的 REST 形态)
|
||||
* - GET /api/v2/resources Resource Discovery
|
||||
*/
|
||||
import { Body, Controller, Get, Param, Post, Query } from "@nestjs/common";
|
||||
import { z } from "zod";
|
||||
import { ActionRuntime } from "../runtime/action-runtime";
|
||||
import { actionRegistry } from "../registry/action-registry";
|
||||
import { resourceRegistry } from "../registry/resource-registry";
|
||||
import { ZodValidationPipe } from "../../common/pipes/zod-validation.pipe";
|
||||
import { CurrentUser, CurrentWorkspace, Roles } from "../../common/decorators";
|
||||
import type { RequestUser, RequestWorkspace } from "../../common/decorators";
|
||||
import type { ActorContext } from "../foundation/types";
|
||||
|
||||
const ExecuteSchema = z.object({
|
||||
input: z.record(z.unknown()).default({}),
|
||||
});
|
||||
|
||||
@Controller("v2")
|
||||
export class V2Controller {
|
||||
constructor(private readonly runtime: ActionRuntime) {}
|
||||
|
||||
/** # Action Discovery */
|
||||
@Get("actions")
|
||||
listActions(@Query("source") source?: string) {
|
||||
return this.runtime.discover((source as "agent" | "mcp" | undefined) ?? undefined);
|
||||
}
|
||||
|
||||
/** # 单个 Action 契约 */
|
||||
@Get("actions/:id")
|
||||
getAction(@Param("id") id: string) {
|
||||
const action = actionRegistry.get(id);
|
||||
if (!action) return { found: false };
|
||||
return {
|
||||
found: true,
|
||||
id: action.id,
|
||||
resource: action.resource,
|
||||
name: action.name,
|
||||
description: action.description,
|
||||
mode: action.mode,
|
||||
permission: action.permission,
|
||||
dangerous: action.dangerous ?? false,
|
||||
inputSchema: action.inputSchema ?? undefined,
|
||||
outputSchema: action.outputSchema ?? undefined,
|
||||
};
|
||||
}
|
||||
|
||||
/** # Resource Discovery */
|
||||
@Get("resources")
|
||||
listResources() {
|
||||
return this.runtime.discoverResources();
|
||||
}
|
||||
|
||||
/** # 执行 Action —— REST 入口(与 UI/MCP/Agent/CLI 同一 Runtime) */
|
||||
@Roles("MEMBER")
|
||||
@Post("actions/:actionId")
|
||||
async execute(
|
||||
@Param("actionId") actionId: string,
|
||||
@CurrentWorkspace() ws: RequestWorkspace,
|
||||
@CurrentUser() user: RequestUser,
|
||||
@Body(new ZodValidationPipe(ExecuteSchema)) body: { input: Record<string, unknown> },
|
||||
) {
|
||||
const actor: ActorContext = {
|
||||
type: "user",
|
||||
id: user.id,
|
||||
displayName: user.email,
|
||||
organizationId: ws.id,
|
||||
};
|
||||
return this.runtime.execute(actionId, body.input, actor, {
|
||||
source: "user",
|
||||
organizationId: ws.id,
|
||||
});
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user