Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
24 changes: 24 additions & 0 deletions packages/cli/src/tests/agent-instructions.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
import { test } from "node:test";
import assert from "node:assert/strict";
import { buildAgentInstructionsReport } from "../ui/core/agent-instructions";

test("buildAgentInstructionsReport highlights the loaded file (#262)", () => {
const report = buildAgentInstructionsReport([
{ displayPath: "./.deepcode/AGENTS.md", absolutePath: "/p/.deepcode/AGENTS.md", exists: true, loaded: true },
{ displayPath: "./AGENTS.md", absolutePath: "/p/AGENTS.md", exists: true, loaded: false },
{ displayPath: "~/.deepcode/AGENTS.md", absolutePath: "/home/u/.deepcode/AGENTS.md", exists: false, loaded: false },
]);
assert.match(report, /Agent instructions loaded from \.\/\.deepcode\/AGENTS\.md/);
assert.match(report, /\.\/\.deepcode\/AGENTS\.md — loaded/);
assert.match(report, /\.\/AGENTS\.md — present/);
assert.match(report, /~\/\.deepcode\/AGENTS\.md — not found/);
});

test("buildAgentInstructionsReport handles the no-instructions case (#262)", () => {
const report = buildAgentInstructionsReport([
{ displayPath: "./.deepcode/AGENTS.md", absolutePath: "/p/.deepcode/AGENTS.md", exists: false, loaded: false },
{ displayPath: "./AGENTS.md", absolutePath: "/p/AGENTS.md", exists: false, loaded: false },
{ displayPath: "~/.deepcode/AGENTS.md", absolutePath: "/home/u/.deepcode/AGENTS.md", exists: false, loaded: false },
]);
assert.match(report, /No AGENTS\.md instruction file found/);
});
1 change: 1 addition & 0 deletions packages/cli/src/tests/slash-commands.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@ test("buildSlashCommands prefixes skills before built-ins", () => {
"undo",
"mcp",
"raw",
"agents",
"exit",
]);
});
Expand Down
19 changes: 19 additions & 0 deletions packages/cli/src/ui/core/agent-instructions.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
export type AgentInstructionSource = {
displayPath: string;
absolutePath: string;
exists: boolean;
loaded: boolean;
};

/** Render a human-readable report of which AGENTS.md files exist and which one is loaded. (#262) */
export function buildAgentInstructionsReport(sources: AgentInstructionSource[]): string {
const lines = sources.map((source) => {
const status = source.exists ? (source.loaded ? "loaded" : "present") : "not found";
return `${source.displayPath} — ${status}`;
});
const loaded = sources.find((source) => source.loaded);
const header = loaded
? `Agent instructions loaded from ${loaded.displayPath}`
: "No AGENTS.md instruction file found (default system prompt only)";
return `${header}\n${lines.join("\n")}`;
}
7 changes: 7 additions & 0 deletions packages/cli/src/ui/core/slash-commands.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ export type SlashCommandKind =
| "undo"
| "mcp"
| "raw"
| "agents"
| "exit";

export type SlashCommandItem = {
Expand Down Expand Up @@ -92,6 +93,12 @@ export const BUILTIN_SLASH_COMMANDS: SlashCommandItem[] = [
args: ["lite", "normal", "raw-scrollback"],
description: "Toggle display mode for viewing or collapsing reasoning content",
},
{
kind: "agents",
name: "agents",
label: "/agents",
description: "Show which AGENTS.md instruction files are loaded",
},
{
kind: "exit",
name: "exit",
Expand Down
6 changes: 6 additions & 0 deletions packages/cli/src/ui/views/App.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ import { MessageView, RawModeExitPrompt } from "../components";
import { SessionList } from "./SessionList";
import { type UndoRestoreMode, UndoSelector } from "./UndoSelector";
import { buildLoadingText } from "../core/loading-text";
import { buildAgentInstructionsReport } from "../core/agent-instructions";
import { findExpandedThinkingId } from "../core/thinking-state";
import { WelcomeScreen } from "./WelcomeScreen";
import { AskUserQuestionPrompt } from "./AskUserQuestionPrompt";
Expand Down Expand Up @@ -392,6 +393,11 @@ function App({ projectRoot, initialPrompt, resumeSessionId, forkSessionId, onRes
navigateToSubView("mcp-status");
return;
}
if (submission.command === "agents") {
const report = buildAgentInstructionsReport(sessionManager.getAgentInstructionSources());
setMessages((prev) => [...prev, buildSyntheticUserMessage(report, 0)]);
return;
}

const prompt: UserPromptContent = {
text: submission.text,
Expand Down
7 changes: 6 additions & 1 deletion packages/cli/src/ui/views/PromptInput.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -73,7 +73,7 @@ export type PromptSubmission = {
permissions?: UserToolPermission[];
alwaysAllows?: PermissionScope[];
planMode?: boolean;
command?: "new" | "resume" | "fork" | "continue" | "undo" | "mcp" | "exit";
command?: "new" | "resume" | "fork" | "continue" | "undo" | "mcp" | "agents" | "exit";
};

export type PromptDraft = {
Expand Down Expand Up @@ -734,6 +734,11 @@ export const PromptInput = React.memo(function PromptInput({
resetPromptInput();
return;
}
if (item.kind === "agents") {
onSubmit({ text: "/agents", imageUrls: [], command: "agents" });
resetPromptInput();
return;
}
if (item.kind === "exit") {
onSubmit({ text: "/exit", imageUrls: [], command: "exit" });
setBuffer(EMPTY_BUFFER);
Expand Down
27 changes: 27 additions & 0 deletions packages/core/src/session.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2403,6 +2403,33 @@ ${agentInstructions}
return this.readNonEmptyFile(path.join(os.homedir(), ".deepcode", "AGENTS.md"));
}

/** Report which AGENTS.md instruction files exist and which one is loaded. (#262) */
getAgentInstructionSources(): Array<{ displayPath: string; absolutePath: string; exists: boolean; loaded: boolean }> {
const candidates = [
{
absolutePath: path.join(this.projectRoot, ".deepcode", "AGENTS.md"),
displayPath: "./.deepcode/AGENTS.md",
},
{
absolutePath: path.join(this.projectRoot, "AGENTS.md"),
displayPath: "./AGENTS.md",
},
{
absolutePath: path.join(os.homedir(), ".deepcode", "AGENTS.md"),
displayPath: "~/.deepcode/AGENTS.md",
},
];
const project = this.loadProjectAgentInstructions();
const userContent = this.readNonEmptyFile(path.join(os.homedir(), ".deepcode", "AGENTS.md"));
const effectiveDisplayPath = project?.displayPath ?? (userContent ? candidates[2]!.displayPath : null);
return candidates.map((candidate) => ({
displayPath: candidate.displayPath,
absolutePath: candidate.absolutePath,
exists: fs.existsSync(candidate.absolutePath),
loaded: candidate.displayPath === effectiveDisplayPath,
}));
}

private buildSystemMessage(
sessionId: string,
content: string,
Expand Down