mirror of
https://bitbucket.org/siakitem/my-pi.git
synced 2026-10-26 10:45:22 +00:00
feat(pi-subagents): 重新启用子 Agent 并使用独立的子 Agent 提示词
- 根包恢复 file:./pi-subagents 依赖与 extensions/subagents.ts 加载 (排在 permission-system 之后、Tool Search 之前),并刷新根锁文件; Agent / get_subagent_result / steer_subagent 权限设为 allow, 子 Agent 内的实际操作仍逐个经权限系统并转发主会话。 - 新增 config/prompt/subagent/:执行者角色 preamble 与组合包自带的 general-purpose / Explore / Plan 定义(替换上游内置,去掉 bash find 冲突规则与写死的 Haiku 模型)。 - pi-subagents 新增 basePrompt / bundledAgentsDir / excludedExtensionPaths 选项:子 Agent 不再嵌入父会话提示词,身份标记置于开头;子会话排除 pi-ask-user。未传选项时保持上游行为。 - system-prompt.ts:customPrompt 自带开场白时不再覆盖(修复子 Agent 角色 与 <active_agent> 身份被抹掉);仅凭 customPrompt 上的 <active_agent> 识别子会话,routing 规则支持 scope,sections 支持 subagentExclude (子会话去掉 memory_policy 与 chrome_profile_bridge)。 - pi-hermes-memory:子会话只读,记忆/skill 写入工具返回错误,后台整理、 纠错检测、会话 flush 与索引写入全部跳过。 Generated with [Devin](https://devin.ai) Co-Authored-By: Devin <158243242+devin-ai-integration[bot]@users.noreply.github.com>
This commit is contained in:
co-authored by
Devin <158243242+devin-ai-integration[bot]@users.noreply.github.com>
parent
b817d66a11
commit
360d8cffc8
@@ -433,4 +433,116 @@ describe("buildAgentPrompt", () => {
|
||||
expect(prompt.indexOf("<worktree_isolation>")).toBeGreaterThan(prompt.indexOf("<sub_agent_context>"));
|
||||
});
|
||||
});
|
||||
|
||||
describe("host-owned base prompt", () => {
|
||||
const BASE = "You are a subagent operating inside pi. The human user does not see your messages.";
|
||||
|
||||
function baseConfig(promptMode: "append" | "replace", systemPrompt = "Custom instructions."): AgentConfig {
|
||||
return {
|
||||
name: "bundled-agent",
|
||||
description: "Bundled",
|
||||
builtinToolNames: [],
|
||||
extensions: true,
|
||||
skills: true,
|
||||
systemPrompt,
|
||||
promptMode,
|
||||
inheritContext: false,
|
||||
runInBackground: false,
|
||||
isolated: false,
|
||||
};
|
||||
}
|
||||
|
||||
it("append mode: replaces parent prompt and drops the bridge, keeps env/instructions/tag", () => {
|
||||
const prompt = buildAgentPrompt(
|
||||
baseConfig("append"),
|
||||
"/workspace",
|
||||
env,
|
||||
"SECRET parent prompt content",
|
||||
undefined,
|
||||
BASE,
|
||||
);
|
||||
// No inherited parent prefix to keep cacheable, so the tag leads the
|
||||
// prompt — same position as replace mode — and lets early session hooks
|
||||
// identify the child before before_agent_start.
|
||||
expect(prompt.startsWith('<active_agent name="bundled-agent"/>')).toBe(true);
|
||||
expect(prompt).not.toContain("SECRET parent prompt content");
|
||||
expect(prompt).not.toContain("<sub_agent_context>");
|
||||
expect(prompt).not.toContain("You are a pi coding agent sub-agent");
|
||||
expect(prompt).toContain("Working directory: /workspace");
|
||||
expect(prompt).toContain("<agent_instructions>");
|
||||
expect(prompt).toContain("Custom instructions.");
|
||||
expect(prompt.match(/<active_agent name="bundled-agent"\/>/g)).toHaveLength(1);
|
||||
const order = [
|
||||
'<active_agent name="bundled-agent"/>',
|
||||
BASE,
|
||||
"# Environment",
|
||||
"<agent_instructions>",
|
||||
].map((s) => prompt.indexOf(s));
|
||||
expect(order.every((i) => i >= 0)).toBe(true);
|
||||
expect(order).toEqual([...order].sort((a, b) => a - b));
|
||||
});
|
||||
|
||||
it("replace mode: drops the sub-agent header, keeps env + config prompt + tag", () => {
|
||||
const prompt = buildAgentPrompt(
|
||||
baseConfig("replace", "You are a read-only search agent."),
|
||||
"/workspace",
|
||||
env,
|
||||
"SECRET parent prompt content",
|
||||
undefined,
|
||||
BASE,
|
||||
);
|
||||
expect(prompt).not.toContain("You are a pi coding agent sub-agent");
|
||||
expect(prompt).not.toContain("SECRET parent prompt content");
|
||||
expect(prompt).not.toContain("<sub_agent_context>");
|
||||
expect(prompt).toContain("Working directory: /workspace");
|
||||
expect(prompt).toContain("You are a read-only search agent.");
|
||||
expect(prompt.match(/<active_agent name="bundled-agent"\/>/g)).toHaveLength(1);
|
||||
// The tag leads, then base, then env, then the config's system prompt.
|
||||
const order = [
|
||||
'<active_agent name="bundled-agent"/>',
|
||||
BASE,
|
||||
"# Environment",
|
||||
"You are a read-only search agent.",
|
||||
].map((s) => prompt.indexOf(s));
|
||||
expect(order.every((i) => i >= 0)).toBe(true);
|
||||
expect(order).toEqual([...order].sort((a, b) => a - b));
|
||||
});
|
||||
|
||||
it("keeps worktree and extras blocks", () => {
|
||||
const prompt = buildAgentPrompt(
|
||||
baseConfig("append"),
|
||||
"/wt/copy",
|
||||
env,
|
||||
undefined,
|
||||
{ worktreeBase: "/repo", memoryBlock: "# Agent Memory\nRemember this." },
|
||||
BASE,
|
||||
);
|
||||
expect(prompt).toContain("isolated git worktree copy of /repo");
|
||||
expect(prompt).toContain("# Agent Memory");
|
||||
expect(prompt).not.toContain("<sub_agent_context>");
|
||||
});
|
||||
|
||||
it("empty agent systemPrompt yields no agent_instructions in append mode", () => {
|
||||
const prompt = buildAgentPrompt(
|
||||
baseConfig("append", ""),
|
||||
"/workspace",
|
||||
env,
|
||||
"Parent.",
|
||||
undefined,
|
||||
BASE,
|
||||
);
|
||||
expect(prompt).not.toContain("<agent_instructions>");
|
||||
});
|
||||
|
||||
it("blank base keeps upstream composition byte-for-byte", () => {
|
||||
for (const promptMode of ["append", "replace"] as const) {
|
||||
const config = baseConfig(promptMode);
|
||||
for (const blank of [undefined, "", " \n "]) {
|
||||
expect(buildAgentPrompt(config, "/workspace", env, "Parent.", undefined, blank)).toBe(
|
||||
buildAgentPrompt(config, "/workspace", env, "Parent."),
|
||||
);
|
||||
}
|
||||
}
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user