Skip to content

g1t/apps/web/app/components/agent-instructions.tsx

94 lines4,540 bytesCodeBlame
1import { FileText, ScrollText, ShieldCheck } from "lucide-react";
2import { Link } from "react-router";
3
4import type { RepoInstructions } from "@g1t/contracts";
5
6import { Idle } from "./agents";
7import { TimeAgo } from "./ui";
8import { Hint } from "./ui/hint";
9
10const ROLE: Record<RepoInstructions["files"][number]["role"], string> = {
11 root: "Every run",
12 directory: "Runs that touch this directory",
13 review: "Reviews",
14};
15
16/**
17 * The files every run of g1t in a project reads as the repository's
18 * instructions, as they are on its default branch: which, what they say,
19 * when they last changed, and where to change them.
20 */
21export function AgentInstructions({ instructions, base }: { instructions: RepoInstructions; base: string }) {
22 const { branch, files, limits } = instructions;
23 return (
24 <section id="instructions" className="mt-10 scroll-mt-20">
25 <div className="flex items-baseline justify-between">
26 <h3 className="flex items-center gap-2 text-sm font-medium">
27 <ScrollText size={15} className="text-muted" />
28 Instructions
29 </h3>
30 <span className="text-xs text-muted">
31 {files.length === 0 ? "None yet" : `${files.length} ${files.length === 1 ? "file" : "files"} on ${branch}`}
32 </span>
33 </div>
34 <p className="mt-1.5 max-w-2xl text-sm text-muted">
35 Every agent run here reads the repository's <code className="font-mono text-xs">AGENTS.md</code> and{" "}
36 <code className="font-mono text-xs">CLAUDE.md</code> from {branch}: the ones at the root, and the nearest
37 ones above the files its task touches. Reviews also read{" "}
38 <code className="font-mono text-xs">.g1t/review.md</code>. Each file is cut at{" "}
39 {limits.fileChars.toLocaleString()} characters, and all of them at {limits.totalChars.toLocaleString()}.
40 </p>
41 <p className="mt-2 flex max-w-2xl items-start gap-2 text-xs text-faint">
42 <ShieldCheck size={13} className="mt-px shrink-0" />
43 Only {branch} and the repository's own branches are followed. A pull request from a fork that changes these
44 files is reviewed as a change, never followed as instructions.
45 </p>
46 {files.length === 0 ? (
47 <div className="mt-3">
48 <Idle>
49 No instructions yet. Commit an AGENTS.md to {branch} with how to build, test and work in this repository,
50 and every agent run reads it.
51 </Idle>
52 </div>
53 ) : (
54 <ul className="mt-3 space-y-3">
55 {files.map((file) => (
56 <li key={file.path} className="rounded-xl border border-line bg-surface">
57 <details>
58 <summary className="flex cursor-pointer flex-wrap items-center gap-x-3 gap-y-1 px-4 py-3 text-sm">
59 <FileText size={14} className="text-muted" />
60 <span className="font-mono font-medium">{file.path}</span>
61 <span className="rounded-full bg-raised px-2 py-px text-xs text-muted">{ROLE[file.role]}</span>
62 {file.truncated && <span className="text-xs text-warn">Longer than agents are given</span>}
63 <span className="ml-auto flex items-center gap-2 text-xs text-faint">
64 {file.lastChanged && (
65 <>
66 <Hint label={file.lastChanged.message}>
67 <Link to={`${base}/commit/${file.lastChanged.commit}`} className="font-mono hover:text-fg">
68 {file.lastChanged.commit.slice(0, 7)}
69 </Link>
70 </Hint>
71 <span>by {file.lastChanged.author}</span>
72 <TimeAgo at={file.lastChanged.at} />
73 </>
74 )}
75 <Link to={`${base}/blob/${encodeURIComponent(branch)}/${file.path}`} className="text-muted hover:text-fg">
76 Open in code
77 </Link>
78 </span>
79 </summary>
80 <pre className="max-h-96 overflow-auto border-t border-line px-4 py-3 font-mono text-xs whitespace-pre-wrap text-muted">
81 {file.text || "(empty)"}
82 </pre>
83 </details>
84 </li>
85 ))}
86 </ul>
87 )}
88 <p className="mt-3 text-xs text-faint">
89 To change them, edit the files in the repository and merge the change into {branch}. Agents read the new version
90 from their next run.
91 </p>
92 </section>
93 );
94}