- agent_run gains depth / spawn_reason (0029); agent_run_event types
subagent_spawned / subagent_event / subagent_completed
- agent.spawn (propose, medium, replay never): allowlist ⊆ parent, mode not
above parent, budget carved from parent's remainder, idempotent per run+input;
settings.pi.subagents {enabled, maxConcurrent, maxDepth} (subagentsEnabled kept as alias)
- child runs claim a concurrency slot under an advisory lock (waitForFact while
queued); agent.await polls business tables without calling the model
- parent abort cascades to all descendants; parent runtime budget counts
descendant usage; child events mirrored into the parent stream by parent seq
- authorize caps every child call by all ancestors' allowlists/kinds
- session page shows parent link, inherited info and the subagent tree
- e2e E11; runbook section on subagents
Co-Authored-By: Claude Opus 5.5 <[email protected]>
65 lines
2.6 KiB
TypeScript
65 lines
2.6 KiB
TypeScript
import { z } from "zod";
|
|
|
|
export const THINKING_LEVELS = ["off", "minimal", "low", "medium", "high", "xhigh", "max"] as const;
|
|
export type AgentThinkingLevel = (typeof THINKING_LEVELS)[number];
|
|
|
|
/**
|
|
* 设置页 → Agent 运行参数。apiKey 为调用方从 secret store 解密后的明文,
|
|
* 只在请求时经 provider auth.resolve 交给 SDK,不进入事件、日志、错误信息。
|
|
*/
|
|
export const AgentSettingsSchema = z.object({
|
|
/**
|
|
* pi provider id。按上游运行(PiAgentRuntimeOptions.upstream)时只作记录;
|
|
* 没有上游时只支持旧的 anthropic / openai-compatible(apiKey 必填)
|
|
*/
|
|
provider: z.string().min(1),
|
|
/** Anthropic 写不带 /v1 的根地址;OpenAI 兼容写带 /v1 的地址 */
|
|
baseUrl: z.string().url().optional(),
|
|
/** 旧的单上游密钥;按上游运行时由凭据存储提供,这里留空 */
|
|
apiKey: z.string().min(1).optional(),
|
|
model: z.string().min(1),
|
|
thinkingLevel: z.enum(THINKING_LEVELS).default("off"),
|
|
/** 上下文预算 = 模型 contextWindow(可以比上游真实窗口小) */
|
|
contextBudgetTokens: z.number().int().min(1024).default(128_000),
|
|
/** 单次回复最大输出 token */
|
|
maxOutputTokens: z.number().int().min(256).default(8192),
|
|
compaction: z
|
|
.object({
|
|
mode: z.enum(["threshold", "manual"]),
|
|
/** 上下文占用达到预算的该比例时自动压缩(0.5~0.95) */
|
|
threshold: z.number().min(0.5).max(0.95).default(0.8),
|
|
})
|
|
.default({ mode: "threshold", threshold: 0.8 }),
|
|
/** 子代理开关(仅记录);派生由服务端 agent.spawn 能力实现,开关与并发/深度上限在服务端校验 */
|
|
subagentsEnabled: z.boolean().default(false),
|
|
maxToolCalls: z.number().int().min(1).default(40),
|
|
maxDurationMs: z
|
|
.number()
|
|
.int()
|
|
.min(1000)
|
|
.default(15 * 60_000),
|
|
costBudget: z
|
|
.object({
|
|
maxTotalTokens: z.number().int().positive().optional(),
|
|
maxCostUsd: z.number().positive().optional(),
|
|
})
|
|
.optional(),
|
|
/** 单次请求超时 */
|
|
requestTimeoutMs: z.number().int().positive().default(120_000),
|
|
maxRetries: z.number().int().min(0).max(10).default(2),
|
|
});
|
|
export type AgentSettings = z.input<typeof AgentSettingsSchema>;
|
|
export type ResolvedAgentSettings = z.output<typeof AgentSettingsSchema>;
|
|
|
|
export function resolveAgentSettings(settings: AgentSettings): ResolvedAgentSettings {
|
|
return AgentSettingsSchema.parse(settings);
|
|
}
|
|
|
|
/** 用于日志/展示:去掉 apiKey */
|
|
export function describeSettings(settings: ResolvedAgentSettings): Omit<ResolvedAgentSettings, "apiKey"> & {
|
|
apiKey: "[REDACTED]";
|
|
} {
|
|
// apiKey 可能为空(按上游运行),展示时一律打码
|
|
return { ...settings, apiKey: "[REDACTED]" };
|
|
}
|