Files
devos/apps/api/src/v2/adapters/v2.controller.ts
T
phptits b1f17cf637 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)
2026-09-10 21:09:44 +00:00

78 lines
2.5 KiB
TypeScript
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
/**
* # 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,
});
}
}