Skip to content

Commit 82c700a

Browse files
committed
feat: include agent instructions in skill matching system prompt
1 parent 4053676 commit 82c700a

2 files changed

Lines changed: 95 additions & 3 deletions

File tree

src/session.ts

Lines changed: 13 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -718,15 +718,15 @@ export class SessionManager {
718718
options?: { signal?: AbortSignal; sessionId?: string }
719719
): Promise<string[]> {
720720
this.throwIfAborted(options?.signal);
721-
let systemPrompt = `When users ask you to perform tasks, check if any of the available skills match. Skills provide specialized capabilities and domain knowledge.\n
721+
let systemPrompt = `When users ask you to perform tasks, check if any of the available skills match the goal and situation. Skills provide specialized capabilities and domain knowledge.\n
722722
Response in JSON format:
723723
\`\`\`
724724
{
725725
"skillNames": ["", ...]
726726
}
727727
\`\`\`\n
728728
If none of the available skills match, respond with an empty array, i.e. \`{"skillNames": []}\`.\n
729-
The candidate skills are as follows:\n\n`;
729+
`;
730730
const simpleSkills = skills
731731
.filter((x) => !x.isLoaded)
732732
.map((x) => {
@@ -735,13 +735,23 @@ The candidate skills are as follows:\n\n`;
735735
if (simpleSkills.length === 0) {
736736
return [];
737737
}
738-
systemPrompt += "```\n" + JSON.stringify(simpleSkills, null, 2) + "\n```";
739738

740739
const { client, model, baseURL, debugLogEnabled } = this.createOpenAIClient();
741740
if (!client) {
742741
return [];
743742
}
744743

744+
const agentInstructions = this.loadAgentInstructions();
745+
if (agentInstructions) {
746+
systemPrompt += `Use the current agent instructions as additional context when deciding which skills match:\n
747+
<agent-instructions>
748+
${agentInstructions}
749+
</agent-instructions>\n
750+
`;
751+
}
752+
systemPrompt += "The candidate skills are as follows:\n\n";
753+
systemPrompt += "```\n" + JSON.stringify(simpleSkills, null, 2) + "\n```";
754+
745755
try {
746756
const response = await this.createChatCompletionStream(
747757
client,

src/tests/session.test.ts

Lines changed: 82 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -893,6 +893,88 @@ test("createSession appends default system prompts in prefix-cache-friendly orde
893893
assert.equal(systemContents[3], "root project instructions");
894894
});
895895

896+
test("createSession includes agent instructions in the skill matching system prompt", async () => {
897+
const workspace = createTempDir("deepcode-skill-match-create-workspace-");
898+
const home = createTempDir("deepcode-skill-match-create-home-");
899+
setHomeDir(home);
900+
globalThis.fetch = (async () => ({ ok: true, text: async () => "" }) as Response) as typeof fetch;
901+
902+
fs.mkdirSync(path.join(workspace, ".deepcode"), { recursive: true });
903+
fs.writeFileSync(path.join(workspace, ".deepcode", "AGENTS.md"), "prefer project-specific skill matching", "utf8");
904+
const skillDir = path.join(workspace, ".deepcode", "skills", "project-aware");
905+
fs.mkdirSync(skillDir, { recursive: true });
906+
fs.writeFileSync(
907+
path.join(skillDir, "SKILL.md"),
908+
"---\nname: project-aware\ndescription: Match project-specific instructions\n---\n# Project Aware\n",
909+
"utf8"
910+
);
911+
912+
const requests: any[] = [];
913+
const client = {
914+
chat: {
915+
completions: {
916+
create: async (request: any) => {
917+
requests.push(request);
918+
return { choices: [{ message: { content: '{"skillNames":[]}' } }] };
919+
},
920+
},
921+
},
922+
};
923+
const manager = createMockedClientSessionManagerWithClient(workspace, client);
924+
(manager as any).activateSession = async () => {};
925+
926+
await manager.createSession({ text: "pick the right workflow" });
927+
928+
const messages = (requests[0]?.messages ?? []) as Array<{ role?: string; content?: string }>;
929+
assert.equal(messages[0]?.role, "system");
930+
assert.match(messages[0]?.content ?? "", /<agent-instructions>/);
931+
assert.match(messages[0]?.content ?? "", /prefer project-specific skill matching/);
932+
assert.match(messages[0]?.content ?? "", /<\/agent-instructions>/);
933+
assert.match(messages[0]?.content ?? "", /The candidate skills are as follows/);
934+
assert.equal(messages[1]?.role, "user");
935+
});
936+
937+
test("replySession includes current agent instructions in the skill matching system prompt", async () => {
938+
const workspace = createTempDir("deepcode-skill-match-reply-workspace-");
939+
const home = createTempDir("deepcode-skill-match-reply-home-");
940+
setHomeDir(home);
941+
globalThis.fetch = (async () => ({ ok: true, text: async () => "" }) as Response) as typeof fetch;
942+
943+
const requests: any[] = [];
944+
const client = {
945+
chat: {
946+
completions: {
947+
create: async (request: any) => {
948+
requests.push(request);
949+
return { choices: [{ message: { content: '{"skillNames":[]}' } }] };
950+
},
951+
},
952+
},
953+
};
954+
const manager = createMockedClientSessionManagerWithClient(workspace, client);
955+
(manager as any).activateSession = async () => {};
956+
957+
const sessionId = await manager.createSession({ text: "" });
958+
fs.writeFileSync(path.join(workspace, "AGENTS.md"), "use reply-time agent instructions", "utf8");
959+
const skillDir = path.join(workspace, ".agents", "skills", "reply-aware");
960+
fs.mkdirSync(skillDir, { recursive: true });
961+
fs.writeFileSync(
962+
path.join(skillDir, "SKILL.md"),
963+
"---\nname: reply-aware\ndescription: Match reply-time instructions\n---\n# Reply Aware\n",
964+
"utf8"
965+
);
966+
967+
await manager.replySession(sessionId, { text: "pick the reply workflow" });
968+
969+
const messages = (requests[0]?.messages ?? []) as Array<{ role?: string; content?: string }>;
970+
assert.equal(messages[0]?.role, "system");
971+
assert.match(messages[0]?.content ?? "", /<agent-instructions>/);
972+
assert.match(messages[0]?.content ?? "", /use reply-time agent instructions/);
973+
assert.match(messages[0]?.content ?? "", /<\/agent-instructions>/);
974+
assert.match(messages[0]?.content ?? "", /The candidate skills are as follows/);
975+
assert.equal(messages[1]?.role, "user");
976+
});
977+
896978
test("replySession stores /init and sends the active root project AGENTS path to the LLM", async () => {
897979
const workspace = createTempDir("deepcode-init-root-workspace-");
898980
const home = createTempDir("deepcode-init-root-home-");

0 commit comments

Comments
 (0)