forked from EduCraft/curriculum-project-hub
feat(hub): RoleEntry 完整 bundle + per-run tool 白名单 + per-role 触发权限
RoleEntry 扩成 (model, systemPrompt, tools) bundle,id 兼任 slash command 名。 ToolRegistry.subset() 支持按白名单构造 per-run 视图,模型永远看不到 role 外的工具。 trigger 解析 /<role> 命令,查 RoleEntry 组装 systemPrompt + 子集 registry 传给 runner。 新增 RoleTriggerGrant 表 + canTriggerRole gate,与 ADR-0004 canTriggerAgent 串联: 先问'能不能触发 agent',再问'能触发哪个 role'。未配置 role 放行(back-compat)。 - models.ts: RoleEntry 加 systemPrompt + tools 字段 - tools.ts: ToolRegistry.subset(names) 返回共享 handler 的子集视图 - trigger.ts: extractRole 解析 slash; 传 systemPrompt + runTools; catch 链容错 P2025 - runner.ts: RunRequest.systemPrompt 改 string | undefined (exactOptionalPropertyTypes) - schema.prisma + migration: RoleTriggerGrant(projectId, roleId, principal, revokedAt) - permission.ts: canTriggerRole gate (有 grant 记录即白名单模式,含 revoked) - server.ts: draft/review 两个 role 加 systemPrompt + tools 白名单 - 测试: role-permission.test.ts (5) + trigger.test.ts (+3), 53 全绿
This commit is contained in:
+23
-5
@@ -9,11 +9,17 @@
|
||||
*/
|
||||
|
||||
/**
|
||||
* A named role preset that maps to a default model. Roles are **data**, not a
|
||||
* code enum: admin/teachers define them (ADR-0017: role-based routing is
|
||||
* product config, not a spec invariant). `roleId` is an opaque string here —
|
||||
* the registry holds the role set, so new roles are added by configuration,
|
||||
* not by editing this file.
|
||||
* A named role preset — the full per-run agent bundle. Roles are **data**, not
|
||||
* a code enum: admin/teachers define them (ADR-0017: role-based routing is
|
||||
* product config, not a spec invariant). `roleId` is an opaque string and
|
||||
* doubles as the slash-command name (`/draft ...`) — the registry holds the
|
||||
* role set, so new roles are added by configuration, not by editing code.
|
||||
*
|
||||
* A role bundles everything that distinguishes one agent persona from another:
|
||||
* model, system prompt, and the tool surface (files / cph / feishu / skills /
|
||||
* mcps). Per-run tool whitelisting is enforced by {@link ToolRegistry.subset};
|
||||
* the model never sees tools outside its role's whitelist, even if it tries to
|
||||
* call them — security does not rely on the system prompt.
|
||||
*/
|
||||
export interface RoleEntry {
|
||||
readonly id: string;
|
||||
@@ -21,6 +27,18 @@ export interface RoleEntry {
|
||||
readonly label: string;
|
||||
/** Default model id for runs under this role, if a routing rule is set. */
|
||||
readonly defaultModel: string | undefined;
|
||||
/**
|
||||
* System prompt seeding the agent's persona/instructions. Prepended to the
|
||||
* run's messages only at session start (resume reads it from the transcript,
|
||||
* see runner.ts). `undefined` ⇒ no system prompt (bare run).
|
||||
*/
|
||||
readonly systemPrompt: string | undefined;
|
||||
/**
|
||||
* Tool names this role may use (whitelist). `undefined` ⇒ the full registered
|
||||
* set (back-compat / unrestricted roles). An empty array ⇒ no tools at all.
|
||||
* Names not present in the registry are silently dropped at run setup.
|
||||
*/
|
||||
readonly tools: readonly string[] | undefined;
|
||||
}
|
||||
|
||||
/** A model the admin has enabled for use by the Hub. */
|
||||
|
||||
Reference in New Issue
Block a user