g1t/apps/web/app/routes/repo/memory.tsx

126 lines5,312 bytesCodeBlame

Pick any line to see why it is the way it is: the commit, the pull request and issue it came from, and what the agent was thinking.

Agents and memory, checks and conflicts, profiles, slug renames, custom domains1import { Brain } from "lucide-react";
Invite-only launch: sign in with GitHub, repository access and lifecycle, many emails, a new look2import { Link } from "react-router";
Agents and memory, checks and conflicts, profiles, slug renames, custom domains3
4import type { Route } from "./+types/memory";
5import { page } from "../../lib/meta";
6import { AddMemory, MemoryList, memoryAction } from "../../components/memory";
Agents get guardrails, run credentials, an audit log, a context hub, repository instructions and mentions; security upkeep; snake_case API7import { ReviewQueue, reviewAction } from "../../components/context";
8import { agents, memoryReview } from "../../lib/services.server";
Invite-only launch: sign in with GitHub, repository access and lifecycle, many emails, a new look9import { assertSameOrigin, requireUser, roleIn, unwrap } from "../../lib/session.server";
10import { requireRepo } from "../../lib/access.server";
Agents and memory, checks and conflicts, profiles, slug renames, custom domains11
12export function meta({ params, ...args }: Route.MetaArgs) {
13 return page(args, { title: `Memory · ${params.owner}/${params.repo} · g1t` });
14}
15
16export async function loader({ params, context }: Route.LoaderArgs) {
Invite-only launch: sign in with GitHub, repository access and lifecycle, many emails, a new look17 // The project's memory is for anyone who can read the repository; the
18 // workspace's (and what waits for review) for its members only.
19 const { viewer, access } = await requireRepo(context, params, "read");
20 const member = !!roleIn(viewer, params.owner);
Agents get guardrails, run credentials, an audit log, a context hub, repository instructions and mentions; security upkeep; snake_case API21 const path = { namespace: params.owner, name: params.repo };
22 const [memories, candidates] = await Promise.all([
23 agents.listMemories(viewer, params.owner, path),
24 // Candidates waiting for review (the context hub); none if the service is not there yet.
Invite-only launch: sign in with GitHub, repository access and lifecycle, many emails, a new look25 member ? memoryReview.listCandidates(viewer, params.owner, path).catch(() => null) : null,
Agents get guardrails, run credentials, an audit log, a context hub, repository instructions and mentions; security upkeep; snake_case API26 ]);
Invite-only launch: sign in with GitHub, repository access and lifecycle, many emails, a new look27 return {
28 ...unwrap(memories),
29 candidates: candidates?.ok ? candidates.value : [],
30 member,
31 // Adding to, editing and forgetting the project's memory: Write and up.
32 editable: access.can.push,
33 };
Agents and memory, checks and conflicts, profiles, slug renames, custom domains34}
35
36export async function action({ params, context, request }: Route.ActionArgs) {
37 assertSameOrigin(request);
38 const user = requireUser(context, request);
Agents get guardrails, run credentials, an audit log, a context hub, repository instructions and mentions; security upkeep; snake_case API39 const form = await request.formData();
40 return (
41 (await reviewAction(memoryReview, user, params.owner, form)) ??
42 memoryAction(agents, user, params.owner, { namespace: params.owner, name: params.repo }, form)
43 );
Agents and memory, checks and conflicts, profiles, slug renames, custom domains44}
45
46export default function ProjectMemory({ loaderData, params }: Route.ComponentProps) {
Invite-only launch: sign in with GitHub, repository access and lifecycle, many emails, a new look47 const { project, workspace, candidates, member, editable } = loaderData;
Agents and memory, checks and conflicts, profiles, slug renames, custom domains48 const action = `/${params.owner}/${params.repo}/memory`;
49 return (
50 <div className="max-w-4xl">
51 <h2 className="flex items-center gap-2 text-xl font-semibold tracking-tight">
52 <Brain size={19} className="text-merged" />
53 Memory
54 </h2>
55 <p className="mt-1.5 max-w-2xl text-sm text-muted">
56 What agents and people have learned about this project that the next agent should know: how
g1t is one name: its agent's work, commits and comments show as @g1t, and nobody can claim g1t or g1t-agent57 to build and test it, its conventions, decisions and why, and its traps. Every run of g1t
Invite-only launch: sign in with GitHub, repository access and lifecycle, many emails, a new look58 here is given it, pinned first{member ? ", together with the workspace's memory" : ""}. Agents add to it with
59 the remember tool as they work{editable ? "; keep it true by editing or forgetting what no longer holds" : ""}.
Agents and memory, checks and conflicts, profiles, slug renames, custom domains60 </p>
Invite-only launch: sign in with GitHub, repository access and lifecycle, many emails, a new look61 {!editable && (
62 <p className="mt-2 text-xs text-muted">
63 You can read this project's memory. Adding to it and changing it needs the Write role.
64 </p>
65 )}
Agents and memory, checks and conflicts, profiles, slug renames, custom domains66
Invite-only launch: sign in with GitHub, repository access and lifecycle, many emails, a new look67 {editable && (
68 <div className="mt-6">
69 <AddMemory scope="project" action={action} placeholder="The tests need TZ=UTC or the date tests fail." />
70 </div>
71 )}
Agents and memory, checks and conflicts, profiles, slug renames, custom domains72
Agents get guardrails, run credentials, an audit log, a context hub, repository instructions and mentions; security upkeep; snake_case API73 {candidates.length > 0 && (
74 <section className="mt-8">
75 <div className="flex items-baseline justify-between">
76 <h3 className="text-sm font-medium">Review</h3>
77 <span className="text-xs text-muted">{candidates.length} waiting</span>
78 </div>
79 <p className="mt-1 text-xs text-muted">
80 Learned by agents, from reviews and merges, and from this project's docs. No agent is given one until it is kept.
81 </p>
82 <div className="mt-3">
83 <ReviewQueue candidates={candidates} action={action} empty="" />
84 </div>
85 </section>
86 )}
87
Agents and memory, checks and conflicts, profiles, slug renames, custom domains88 <section className="mt-8">
89 <div className="flex items-baseline justify-between">
90 <h3 className="text-sm font-medium">This project</h3>
91 <span className="text-xs text-muted">{project.length} kept</span>
92 </div>
93 <div className="mt-3">
94 <MemoryList
95 memories={project}
96 action={action}
Invite-only launch: sign in with GitHub, repository access and lifecycle, many emails, a new look97 editable={editable}
98 empty={editable ? "Nothing yet. Agents add what they learn here as they work, and so can you." : "Nothing yet."}
Agents and memory, checks and conflicts, profiles, slug renames, custom domains99 />
100 </div>
101 </section>
102
Invite-only launch: sign in with GitHub, repository access and lifecycle, many emails, a new look103 {member && (
104 <section className="mt-10">
105 <div className="flex items-baseline justify-between">
106 <h3 className="text-sm font-medium">From the workspace</h3>
107 <Link to={`/${params.owner}/-/memory`} className="text-xs text-muted hover:text-fg">
108 Manage workspace memory
109 </Link>
110 </div>
111 <p className="mt-1 text-xs text-muted">
112 True across all of {params.owner}'s projects, and given to agents here too.
113 </p>
114 <div className="mt-3">
115 <MemoryList
116 memories={workspace}
117 action={`/${params.owner}/-/memory`}
118 editable={false}
119 empty="The workspace remembers nothing yet."
120 />
121 </div>
122 </section>
123 )}
Agents and memory, checks and conflicts, profiles, slug renames, custom domains124 </div>
125 );
126}