Skip to content

Commit 12f080c

Browse files
redxzetaAgent
andauthored
feat: add upstream amnesia toggle (#37)
* chore: replace remaining Synara branding with Forkara (#12) * feat: add upstream amnesia repository label toggle --------- Co-authored-by: Agent <agent@debian.local>
1 parent d608f95 commit 12f080c

6 files changed

Lines changed: 108 additions & 6 deletions

File tree

apps/web/src/appSettings.test.ts

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -262,6 +262,20 @@ describe("environment panel defaults", () => {
262262
});
263263
});
264264

265+
describe("upstream amnesia preference", () => {
266+
it("defaults upstream hiding to off and persists the toggle as a local-only setting", () => {
267+
const defaults = AppSettingsSchema.makeUnsafe({});
268+
expect(defaults.hideUpstreamRepositoryInfo).toBe(false);
269+
270+
const decode = Schema.decodeSync(Schema.fromJsonString(AppSettingsSchema));
271+
const decoded = decode(JSON.stringify({ hideUpstreamRepositoryInfo: true }));
272+
273+
expect(normalizeStoredAppSettings(decoded)).toMatchObject({
274+
hideUpstreamRepositoryInfo: true,
275+
});
276+
});
277+
});
278+
265279
describe("resolveAppModelSelection", () => {
266280
it("preserves saved custom model slugs instead of falling back to the default", () => {
267281
expect(

apps/web/src/appSettings.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -224,6 +224,7 @@ export const AppSettingsSchema = Schema.Struct({
224224
environmentPanelDefaultOpen: Schema.Boolean.pipe(withDefaults(() => false)),
225225
showEnvironmentUsage: Schema.Boolean.pipe(withDefaults(() => true)),
226226
showEnvironmentRepository: Schema.Boolean.pipe(withDefaults(() => true)),
227+
hideUpstreamRepositoryInfo: Schema.Boolean.pipe(withDefaults(() => false)),
227228
showEnvironmentPullRequest: Schema.Boolean.pipe(withDefaults(() => true)),
228229
showEnvironmentEditor: Schema.Boolean.pipe(withDefaults(() => true)),
229230
showEnvironmentRecap: Schema.Boolean.pipe(withDefaults(() => true)),

apps/web/src/components/chat/environment/EnvironmentPanel.logic.test.ts

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,7 @@
1+
import { renderToStaticMarkup } from "react-dom/server";
12
import { describe, expect, it } from "vitest";
23

4+
import { getRepositoryLabel, UPSTREAM_AMNESIA_HINT, UPSTREAM_AMNESIA_LABEL } from "./EnvironmentPanel";
35
import { shouldShowStudioFolderRow } from "./EnvironmentPanel.logic";
46

57
describe("shouldShowStudioFolderRow", () => {
@@ -37,3 +39,30 @@ describe("shouldShowStudioFolderRow", () => {
3739
).toBe(false);
3840
});
3941
});
42+
43+
describe("getRepositoryLabel", () => {
44+
it("shows the upstream repository when amnesia is disabled", () => {
45+
const markup = renderToStaticMarkup(
46+
getRepositoryLabel({
47+
githubRepository: { nameWithOwner: "openai/codex", url: "https://github.com/openai/codex" },
48+
hideUpstreamRepositoryInfo: false,
49+
}),
50+
);
51+
52+
expect(markup).toContain("openai/codex");
53+
expect(markup).not.toContain(UPSTREAM_AMNESIA_LABEL);
54+
});
55+
56+
it("hides upstream identity with amnesia messaging when enabled", () => {
57+
const markup = renderToStaticMarkup(
58+
getRepositoryLabel({
59+
githubRepository: { nameWithOwner: "openai/codex", url: "https://github.com/openai/codex" },
60+
hideUpstreamRepositoryInfo: true,
61+
}),
62+
);
63+
64+
expect(markup).toContain(UPSTREAM_AMNESIA_LABEL);
65+
expect(markup).toContain(UPSTREAM_AMNESIA_HINT);
66+
expect(markup).not.toContain("openai/codex");
67+
});
68+
});

apps/web/src/components/chat/environment/EnvironmentPanel.tsx

Lines changed: 46 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@ import type {
2121
ThreadMarkerId,
2222
} from "@synara/contracts";
2323
import { useNavigate } from "@tanstack/react-router";
24+
import { type ReactNode } from "react";
2425

2526
import { useAppSettings } from "~/appSettings";
2627
import { SETTINGS_TARGETS } from "~/settingsNavigation";
@@ -73,6 +74,31 @@ export const ENVIRONMENT_DOCKED_CONTENT_INSET_PX = 312;
7374

7475
const ENVIRONMENT_PANEL_OVERLAY_WRAPPER_CLASS_NAME =
7576
"pointer-events-none absolute inset-y-0 right-0 z-20 flex flex-col p-3";
77+
export const UPSTREAM_AMNESIA_LABEL = "Upstream information hidden";
78+
export const UPSTREAM_AMNESIA_HINT = "Upstream successfully forgotten. Git remembers.";
79+
80+
export function getRepositoryLabel(input: {
81+
githubRepository: {
82+
readonly nameWithOwner: string;
83+
readonly url: string;
84+
} | null;
85+
hideUpstreamRepositoryInfo: boolean;
86+
}): ReactNode {
87+
if (!input.hideUpstreamRepositoryInfo) {
88+
return (
89+
<span className="truncate">{input.githubRepository?.nameWithOwner ?? "Unknown repository"}</span>
90+
);
91+
}
92+
93+
return (
94+
<span className="flex min-w-0 flex-col gap-0.5">
95+
<span className="truncate text-muted-foreground">{UPSTREAM_AMNESIA_LABEL}</span>
96+
<span className="truncate text-[length:var(--app-font-size-ui-xs,10px)] text-muted-foreground/80">
97+
{UPSTREAM_AMNESIA_HINT}
98+
</span>
99+
</span>
100+
);
101+
}
76102

77103
export interface EnvironmentPanelProps {
78104
/** Drives the slide-in/out transition; the panel stays mounted so CSS can interpolate. */
@@ -387,12 +413,26 @@ export function EnvironmentPanel({
387413
<EnvironmentLabeledSection label="Repository">
388414
<EnvironmentRow
389415
icon={<GitHubIcon className={ENVIRONMENT_ROW_ICON_CLASS_NAME} aria-hidden />}
390-
label={<span className="truncate">{githubRepository.nameWithOwner}</span>}
391-
trailing={<ArrowUpRightIcon className={ENVIRONMENT_ROW_ICON_CLASS_NAME} aria-hidden />}
392-
onClick={() => {
393-
onOpenGithubRepository(githubRepository.url);
394-
onClose();
395-
}}
416+
label={getRepositoryLabel({
417+
githubRepository,
418+
hideUpstreamRepositoryInfo: settings.hideUpstreamRepositoryInfo,
419+
})}
420+
trailing={
421+
!settings.hideUpstreamRepositoryInfo ? (
422+
<ArrowUpRightIcon className={ENVIRONMENT_ROW_ICON_CLASS_NAME} aria-hidden />
423+
) : null
424+
}
425+
{...(!settings.hideUpstreamRepositoryInfo
426+
? {
427+
onClick: () => {
428+
onOpenGithubRepository(githubRepository.url);
429+
onClose();
430+
},
431+
}
432+
: {
433+
"aria-label": "Upstream repository identity is hidden",
434+
title: "Upstream repository identity is hidden",
435+
})}
396436
/>
397437
</EnvironmentLabeledSection>
398438
) : null}

apps/web/src/routes/_chat.settings.tsx

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -250,6 +250,9 @@ function SettingsRouteView() {
250250
...(settings.enableProviderUpdateChecks !== defaults.enableProviderUpdateChecks
251251
? ["Provider update checks"]
252252
: []),
253+
...(settings.hideUpstreamRepositoryInfo !== defaults.hideUpstreamRepositoryInfo
254+
? ["Upstream information visibility"]
255+
: []),
253256
...(settings.diffWordWrap !== defaults.diffWordWrap ? ["Diff line wrapping"] : []),
254257
...(settings.showPullRequestDiffColors !== defaults.showPullRequestDiffColors
255258
? ["Pull request diff colors"]
@@ -544,6 +547,15 @@ function SettingsRouteView() {
544547
ariaLabel: "Show the Repository section in the Environment panel",
545548
})}
546549

550+
{renderBooleanSettingRow({
551+
settingKey: "hideUpstreamRepositoryInfo",
552+
title: "Hide upstream information",
553+
description:
554+
"Hide upstream repository identity in the chat Environment panel while keeping Git behavior unchanged.",
555+
resetLabel: "upstream information visibility",
556+
ariaLabel: "Hide upstream repository information in the Environment panel",
557+
})}
558+
547559
{renderBooleanSettingRow({
548560
settingKey: "showEnvironmentPullRequest",
549561
title: "Pull request",

apps/web/src/settingsSearchIndex.ts

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -91,6 +91,12 @@ export const SETTINGS_SEARCH_ENTRIES: readonly SettingsSearchEntry[] = [
9191
title: "Repository",
9292
keywords: "Show the GitHub repository link in the chat Environment panel. git changes worktree",
9393
},
94+
{
95+
id: "general:environment-hide-upstream",
96+
section: "general",
97+
title: "Hide upstream information",
98+
keywords: "Hide upstream repository identity in the Environment panel. Forkara parody",
99+
},
94100
{
95101
id: "general:environment-pull-request",
96102
section: "general",

0 commit comments

Comments
 (0)