feat(hub): 抽出运行时配置

This commit is contained in:
2026-07-08 15:25:49 +08:00
parent a766d99573
commit 3f486232a8
9 changed files with 297 additions and 66 deletions
+11 -6
View File
@@ -12,8 +12,8 @@ import type { Prisma, PrismaClient } from "@prisma/client";
import { z } from "zod";
import type { FastifyBaseLogger } from "fastify";
import { sendText, sendTextMessage, patchTextMessage, reactToMessage, downloadMessageFile, type FeishuRuntime, type MessageReceiveEvent } from "./client.js";
import type { ModelRegistry } from "../agent/models.js";
import { runAgent as defaultRunAgent, type ProjectContext, type RunRequest, type RunResult } from "../agent/runner.js";
import type { RuntimeSettings } from "../settings/runtime.js";
import { acquireLock, currentLockRunId, releaseLock } from "../lock.js";
import { canTriggerAgent, canTriggerRole } from "../permission.js";
import { writeAudit } from "../audit.js";
@@ -22,7 +22,7 @@ import { createFileDeliveryMcpServer } from "./fileDeliveryTool.js";
interface TriggerDeps {
readonly prisma: PrismaClient;
readonly models: ModelRegistry;
readonly settings: RuntimeSettings;
readonly logger: FastifyBaseLogger;
readonly runAgent?: (req: RunRequest) => Promise<RunResult>;
}
@@ -183,7 +183,8 @@ export function makeTriggerHandler(deps: TriggerDeps) {
// ADR-0017: role-as-data. Parse a leading `/<role>` command; unknown
// slashes are left as literal text (extractRole returns null). Falls back
// to "draft" when no role is named — the registry degrades gracefully.
const { roleId: parsedRole, prompt: agentPrompt } = extractRole(cleanPrompt, deps.models);
const models = await deps.settings.modelRegistry({ projectId });
const { roleId: parsedRole, prompt: agentPrompt } = extractRole(cleanPrompt, models);
const roleId = parsedRole ?? "draft";
// Per-role trigger gate (ADR-0017). Orthogonal to ADR-0004's
// canTriggerAgent above: that checked "can trigger an agent at all";
@@ -195,9 +196,11 @@ export function makeTriggerHandler(deps: TriggerDeps) {
await sendText(rt, chatId, `无权限使用角色 ${roleId}`);
return;
}
const role = deps.models.role(roleId);
const model = deps.models.resolve(undefined, roleId);
const providerId = "openrouter";
const role = models.role(roleId);
const model = models.resolve(undefined, roleId);
const provider = await deps.settings.provider("openrouter", { projectId });
const runPolicy = await deps.settings.runPolicy({ projectId, roleId });
const providerId = provider.id;
// Per-role bundle (ADR-0017): systemPrompt seeds persona; tools whitelist
// is enforced inside runAgent when it builds the SDK tools record. `tools:
// undefined` means the full registered set (unrestricted role).
@@ -289,8 +292,10 @@ export function makeTriggerHandler(deps: TriggerDeps) {
model,
project: projectCtx,
systemPrompt,
providerEnv: provider.sdkEnv,
resumeSessionId: sessionMetadata.claudeSessionId,
mcpServers: { cph_hub: fileDeliveryMcpServer },
maxTurns: runPolicy.maxTurns,
runId: run.id,
sessionId: session.id,
prisma: deps.prisma,