merge(release): reconcile frozen remote tip 92f58603 (#8875)

# Conflicts:
#	open-sse/executors/github.ts
This commit is contained in:
diegosouzapw
2026-08-23 20:15:45 -03:00
18 changed files with 306 additions and 15 deletions

View File

@@ -0,0 +1 @@
- **feat(dashboard):** lead Traffic Inspector with a purpose-first header that separates "what happened" from "how it happened", so beginners can read request outcomes without drowning in protocol detail ([#11283](https://github.com/diegosouzapw/OmniRoute/pull/11283))

View File

@@ -0,0 +1 @@
- **feat(dashboard):** add an Essentials sidebar preset that shows only the beginner core path (Home → Endpoints → API Keys → Providers → Health → Settings) while keeping Advanced tools reachable via Command Palette search ([#11286](https://github.com/diegosouzapw/OmniRoute/pull/11286))

View File

@@ -0,0 +1 @@
- fix(oauth): stop treating the Kiro profile ARN as an account identity in `findKiroConnectionByIdentity()`, so a second Google/GitHub social login creates a new connection instead of overwriting the first — distinct Builder ID accounts share the same CodeWhisperer profile ARN, and the social token is not a JWT, so no e-mail was available to disambiguate them (#10815)

View File

@@ -1,3 +1,5 @@
import { randomBytes } from "node:crypto";
import {
BaseExecutor,
ExecuteInput,
@@ -13,6 +15,11 @@ import {
import { sanitizeResponsesInputItems } from "../services/responsesInputSanitizer.ts";
import { stripUnsupportedParams } from "../translator/paramSupport.ts";
/** Correlation-id fallback for runtimes without crypto.randomUUID — still CSPRNG-backed. */
function randomIdFallback(): string {
return `${Date.now()}-${randomBytes(9).toString("hex")}`;
}
/**
* What a Copilot credential refresh resolves to.
*
@@ -329,7 +336,7 @@ export class GithubExecutor extends BaseExecutor {
...getGitHubCopilotChatHeaders(stream ? "text/event-stream" : "application/json", initiator),
Authorization: `Bearer ${token}`,
"x-request-id":
crypto.randomUUID?.() || `${Date.now()}-${Math.random().toString(36).slice(2)}`,
crypto.randomUUID?.() || randomIdFallback(),
};
// Per-call / per-conversation / per-turn correlation ids the @github/copilot
@@ -337,8 +344,7 @@ export class GithubExecutor extends BaseExecutor {
// id (getGitHubCopilotMachineId) is stable per-install; these three are
// fresh uuids. A Copilot-aware client may pin the session/task ids across a
// conversation via its own headers — honor those when present, else mint.
const genId = () =>
crypto.randomUUID?.() || `${Date.now()}-${Math.random().toString(36).slice(2)}`;
const genId = () => crypto.randomUUID?.() || randomIdFallback();
headers["x-interaction-id"] =
this.readClientHeader(clientHeaders, "x-interaction-id") || genId();
headers["x-client-session-id"] =

View File

@@ -521,6 +521,7 @@ export default function SidebarTab() {
const presetLabels: Record<SidebarPresetId, string> = {
all: getSettingsLabel("presetAll", "All"),
essentials: getSettingsLabel("presetEssentials", "Essentials"),
minimal: getSettingsLabel("presetMinimal", "Minimal"),
developer: getSettingsLabel("presetDeveloper", "Developer"),
admin: getSettingsLabel("presetAdmin", "Admin"),
@@ -528,6 +529,10 @@ export default function SidebarTab() {
const presetDescriptions: Record<SidebarPresetId, string> = {
all: getSettingsLabel("presetAllDesc", "Show everything"),
essentials: getSettingsLabel(
"presetEssentialsDesc",
"Beginner path — Advanced tools stay searchable"
),
minimal: getSettingsLabel("presetMinimalDesc", "Core pages only"),
developer: getSettingsLabel("presetDeveloperDesc", "Dev & proxy tools"),
admin: getSettingsLabel("presetAdminDesc", "Monitoring & audit"),

View File

@@ -15,7 +15,15 @@ import { HistoricSessionBanner } from "./components/session/HistoricSessionBanne
const BUFFER_MAX = 1000;
export function TrafficInspectorPageClient() {
export function TrafficInspectorPageClient({
title,
subtitle,
purpose,
}: {
title?: string;
subtitle?: string;
purpose?: string;
} = {}) {
const [containerHeight, setContainerHeight] = useState(600);
const listContainerRef = useRef<HTMLDivElement | null>(null);
const [selectedRequest, setSelectedRequest] = useState<InterceptedRequest | null>(null);
@@ -91,6 +99,18 @@ export function TrafficInspectorPageClient() {
return (
<div className="flex flex-col h-full overflow-hidden">
{title && (
<div className="shrink-0 px-4 pt-4 pb-2">
<h1 className="text-2xl font-bold text-text-main">{title}</h1>
{subtitle && (
<p className="text-sm text-text-muted mt-1 max-w-2xl">{subtitle}</p>
)}
{purpose && (
<p className="text-xs text-text-muted mt-2 max-w-2xl italic">{purpose}</p>
)}
</div>
)}
{/* Capture modes toolbar */}
<div className="shrink-0 px-4 pt-4 pb-2">
<CaptureModesToolbar customHostCount={0} />

View File

@@ -9,6 +9,7 @@ export async function generateMetadata() {
};
}
export default function TrafficInspectorPage() {
return <TrafficInspectorPageClient />;
export default async function TrafficInspectorPage() {
const t = await getTranslations("sidebar");
return <TrafficInspectorPageClient title={t("trafficInspector")} subtitle={t("trafficInspectorSubtitle")} purpose={t("trafficInspectorPurpose")} />;
}

View File

@@ -1272,7 +1272,8 @@
"agentBridge": "Agent Bridge",
"agentBridgeSubtitle": "Intercept IDE agent traffic",
"trafficInspector": "Traffic Inspector",
"trafficInspectorSubtitle": "Monitor LLM calls + debug any HTTPS traffic",
"trafficInspectorSubtitle": "Inspect request and response traffic from your apps",
"trafficInspectorPurpose": "See exactly what your application sends to and receives from AI providers. Works with any OpenAI-compatible client.",
"cliCode": "CLI Code",
"cliCodeSubtitle": "Code tools pointing to OmniRoute",
"cliAgents": "CLI Agents",
@@ -6707,6 +6708,18 @@
"sidebarVisibility": "Hide sidebar items",
"sidebarVisibilityDesc": "Hide any sidebar navigation entry to reduce visual clutter without disabling any features",
"sidebarVisibilityHint": "Any sidebar section is hidden automatically when all of its entries are hidden",
"presetAll": "All",
"presetAllDesc": "Show everything",
"presetEssentials": "Essentials",
"presetEssentialsDesc": "Beginner path - Advanced tools stay searchable",
"presetMinimal": "Minimal",
"presetMinimalDesc": "Core pages only",
"presetDeveloper": "Developer",
"presetDeveloperDesc": "Dev & proxy tools",
"presetAdmin": "Admin",
"presetAdminDesc": "Monitoring & audit",
"settingsSidebarTitle": "Sidebar Customization",
"settingsSidebarDesc": "Choose which sidebar items to show. Essentials keeps Advanced tools searchable.",
"hideHealthLogs": "Hide Health Check Logs",
"hideHealthLogsDesc": "When ON, suppress [HealthCheck] messages in server console",
"themeAccent": "Theme color",

View File

@@ -30,6 +30,27 @@ function providerData(connection: KiroConnectionLike): Record<string, unknown> {
: {};
}
/** True when the identity carries something that identifies the ACCOUNT (not the profile). */
function hasAccountIdentifier(identity: KiroConnectionIdentity): boolean {
return Boolean(folded(identity.email) || trimmed(identity.clientId));
}
/** True when a shared field is present on both sides and disagrees — different accounts. */
function contradictsAccount(
connection: KiroConnectionLike,
identity: KiroConnectionIdentity
): boolean {
const email = folded(identity.email);
const existingEmail = folded(connection.email);
if (email && existingEmail && email !== existingEmail) return true;
const clientId = trimmed(identity.clientId);
const existingClientId = trimmed(providerData(connection).clientId);
if (clientId && existingClientId && clientId !== existingClientId) return true;
return false;
}
/** Find an existing Kiro account without comparing OAuth tokens or API keys. */
export function findKiroConnectionByIdentity(
connections: KiroConnectionLike[],
@@ -45,7 +66,14 @@ export function findKiroConnectionByIdentity(
const match = candidates.find(
(connection) => trimmed(providerData(connection).profileArn) === profileArn
);
if (match) return match;
// A profile ARN identifies the CodeWhisperer PROFILE, not the account: distinct
// Builder ID accounts (Google/GitHub social login) share the same ARN. Accepting it
// as identity made a second social login overwrite the first connection (#10815).
// Only trust the ARN when the incoming identity carries an account-level identifier
// that does not contradict the stored one.
if (match && hasAccountIdentifier(identity) && !contradictsAccount(match, identity)) {
return match;
}
}
const clientId = trimmed(identity.clientId);

View File

@@ -6,8 +6,11 @@ import { useTranslations } from "next-intl";
import {
SIDEBAR_SECTIONS,
HIDDEN_SIDEBAR_ITEMS_SETTING_KEY,
SIDEBAR_PRESET_KEY,
ESSENTIALS_ADVANCED_TOOL_IDS,
normalizeHiddenSidebarItems,
resolveRuntimeSidebarSections,
type HideableSidebarItemId,
type SidebarItemDefinition,
type SidebarSectionChild,
} from "@/shared/constants/sidebarVisibility";
@@ -61,6 +64,7 @@ function CommandPaletteDialog({ onClose }: { onClose: () => void }) {
const [query, setQuery] = useState("");
const [selectedIndex, setSelectedIndex] = useState(0);
const [hiddenItems, setHiddenItems] = useState<Set<string>>(new Set());
const [activePreset, setActivePreset] = useState<string | null>(null);
const [radarAdminUrl, setRadarAdminUrl] = useState<unknown>(null);
useEffect(() => {
@@ -71,6 +75,9 @@ function CommandPaletteDialog({ onClose }: { onClose: () => void }) {
setHiddenItems(
new Set(normalizeHiddenSidebarItems(data?.[HIDDEN_SIDEBAR_ITEMS_SETTING_KEY]))
);
setActivePreset(
typeof data?.[SIDEBAR_PRESET_KEY] === "string" ? data[SIDEBAR_PRESET_KEY] : null
);
setRadarAdminUrl(data?.radarAdminUrl ?? null);
})
.catch(() => {
@@ -104,7 +111,13 @@ function CommandPaletteDialog({ onClose }: { onClose: () => void }) {
if (isSidebarGroup(child)) {
const subgroupLabel = safeTranslate(child.titleKey, child.titleFallback);
return child.items
.filter((item) => !hiddenItems.has(item.id))
.filter((item) => {
if (!hiddenItems.has(item.id)) return true;
return (
activePreset === "essentials" &&
ESSENTIALS_ADVANCED_TOOL_IDS.has(item.id as HideableSidebarItemId)
);
})
.map<PaletteItem>((item) => ({
id: item.id,
href: item.href,
@@ -121,7 +134,12 @@ function CommandPaletteDialog({ onClose }: { onClose: () => void }) {
}));
}
const item = child as SidebarItemDefinition;
if (hiddenItems.has(item.id)) return [];
if (hiddenItems.has(item.id)) {
const keepForEssentials =
activePreset === "essentials" &&
ESSENTIALS_ADVANCED_TOOL_IDS.has(item.id as HideableSidebarItemId);
if (!keepForEssentials) return [];
}
return [
{
id: item.id,

View File

@@ -202,6 +202,36 @@ export const SIDEBAR_ITEM_ORDER_KEY = "sidebarItemOrder";
export const SIDEBAR_PRESET_KEY = "sidebarActivePreset";
export const SIDEBAR_SETTINGS_UPDATED_EVENT = "omniroute:settings-updated";
/** Beginner Essentials: core path only. Advanced tools stay reachable via search. */
const ESSENTIALS_SHOWN: ReadonlySet<HideableSidebarItemId> = new Set([
"home",
"endpoints",
"api-manager",
"providers",
"health",
"settings-general",
"settings-sidebar",
]);
/** Hidden in Essentials sidebar but kept searchable in Command Palette. */
export const ESSENTIALS_ADVANCED_TOOL_IDS: ReadonlySet<HideableSidebarItemId> = new Set([
"playground",
"logs",
"batch",
"translator",
"combos",
"quota",
"analytics",
"costs",
"cache",
"runtime",
"resilience-connections",
"mcp",
"a2a",
"memory",
"skills",
]);
const MINIMAL_SHOWN: ReadonlySet<HideableSidebarItemId> = new Set([
"home",
"endpoints",
@@ -297,6 +327,7 @@ function buildHiddenList(shown: ReadonlySet<HideableSidebarItemId>): HideableSid
export const SIDEBAR_PRESETS: readonly SidebarPresetDefinition[] = [
{ id: "all", icon: "select_all", hiddenItems: [] },
{ id: "essentials", icon: "star", hiddenItems: buildHiddenList(ESSENTIALS_SHOWN) },
{ id: "minimal", icon: "minimize", hiddenItems: buildHiddenList(MINIMAL_SHOWN) },
{ id: "developer", icon: "code", hiddenItems: buildHiddenList(DEVELOPER_SHOWN) },
{ id: "admin", icon: "admin_panel_settings", hiddenItems: buildHiddenList(ADMIN_SHOWN) },

View File

@@ -174,7 +174,7 @@ export interface SidebarSectionDefinition {
defaultPinned?: boolean;
}
export type SidebarPresetId = "all" | "minimal" | "developer" | "admin";
export type SidebarPresetId = "all" | "essentials" | "minimal" | "developer" | "admin";
export interface SidebarPresetDefinition {
id: SidebarPresetId;

View File

@@ -199,7 +199,10 @@ export const updateSettingsSchema = z.object({
.array(z.enum(SIDEBAR_SECTIONS.map((s) => s.id) as [string, ...string[]]))
.optional(),
sidebarItemOrder: z.record(z.string(), z.array(z.string().max(100))).optional(),
sidebarActivePreset: z.enum(["all", "minimal", "developer", "admin"]).nullable().optional(),
sidebarActivePreset: z
.enum(["all", "essentials", "minimal", "developer", "admin"])
.nullable()
.optional(),
comboConfigMode: z.enum(COMBO_CONFIG_MODES).optional(),
codexServiceTier: z
.object({

View File

@@ -23,8 +23,11 @@ export function unescapeWindowsShellArg(arg) {
s = s.replace(/\^(.)/g, "$1").replace(/\^(.)/g, "$1");
// 2. drop the wrapping quotes added by the CRT argv layer
if (s.length >= 2 && s.startsWith('"') && s.endsWith('"')) s = s.slice(1, -1);
// 3. undo the doubled backslashes and the escaped embedded quotes
s = s.replace(/\\\\/g, "\\").replace(/\\"/g, '"');
// 3. undo the doubled backslashes and the escaped embedded quotes in a single
// left-to-right pass — two sequential global replaces would let the first
// pass's output feed the second (e.g. an escaped-backslash-then-quote
// sequence could be misread), which is exactly what js/double-escaping flags.
s = s.replace(/\\\\|\\"/g, (m) => (m === "\\\\" ? "\\" : '"'));
return s;
}

View File

@@ -79,3 +79,49 @@ test("findKiroConnectionByIdentity never overwrites a different authentication t
null
);
});
// #10815 — a profile ARN identifies the CodeWhisperer profile, not the account: two
// distinct social (Google/GitHub) Builder ID accounts share the same ARN, so matching
// on it alone made the second login overwrite the first connection.
const SHARED_PROFILE_ARN = "arn:aws:codewhisperer:us-east-1:1:profile/SHARED";
const firstSocialAccount = {
id: "social-account-1",
authType: "oauth",
name: null,
email: null,
providerSpecificData: {
profileArn: SHARED_PROFILE_ARN,
authMethod: "imported",
provider: "Github",
},
};
test("findKiroConnectionByIdentity does not match a shared profile ARN without an account identifier", () => {
const match = findKiroConnectionByIdentity([firstSocialAccount], {
authType: "oauth",
profileArn: SHARED_PROFILE_ARN,
email: null,
});
assert.equal(match, null);
});
test("findKiroConnectionByIdentity treats diverging emails on a shared profile ARN as distinct accounts", () => {
const stored = { ...firstSocialAccount, id: "social-a", email: "a@example.com" };
const match = findKiroConnectionByIdentity([stored], {
authType: "oauth",
profileArn: SHARED_PROFILE_ARN,
email: "b@example.com",
});
assert.equal(match, null);
});
test("findKiroConnectionByIdentity still matches the same account on a shared profile ARN", () => {
const stored = { ...firstSocialAccount, id: "social-a", email: "a@example.com" };
const match = findKiroConnectionByIdentity([stored], {
authType: "oauth",
profileArn: SHARED_PROFILE_ARN,
email: "a@example.com",
});
assert.equal(match?.id, "social-a");
});

View File

@@ -89,9 +89,10 @@ test("applyItemOrder ignores unknown IDs in order list", () => {
// ─── SIDEBAR_PRESETS ──────────────────────────────────────────────────────────
test("SIDEBAR_PRESETS contains all four preset IDs", () => {
test("SIDEBAR_PRESETS contains all five preset IDs", () => {
const ids = SIDEBAR_PRESETS.map((p) => p.id);
assert.ok(ids.includes("all"), "expected 'all' preset");
assert.ok(ids.includes("essentials"), "expected 'essentials' preset");
assert.ok(ids.includes("minimal"), "expected 'minimal' preset");
assert.ok(ids.includes("developer"), "expected 'developer' preset");
assert.ok(ids.includes("admin"), "expected 'admin' preset");
@@ -112,6 +113,30 @@ test("SIDEBAR_PRESETS 'all' preset has no hidden items", () => {
assert.deepEqual(allPreset.hiddenItems, []);
});
test("SIDEBAR_PRESETS includes essentials as the beginner path", () => {
assert.equal(SIDEBAR_PRESETS.length, 5);
assert.deepEqual(
SIDEBAR_PRESETS.map((p) => p.id),
["all", "essentials", "minimal", "developer", "admin"]
);
const essentials = SIDEBAR_PRESETS.find((p) => p.id === "essentials");
assert.ok(essentials, "expected 'essentials' preset to exist");
const hidden = new Set(essentials.hiddenItems);
for (const id of [
"home",
"endpoints",
"api-manager",
"providers",
"health",
"settings-general",
"settings-sidebar",
]) {
assert.equal(hidden.has(id as never), false, `${id} should stay visible in essentials`);
}
assert.equal(hidden.has("playground"), true);
assert.equal(hidden.has("logs"), true);
});
test("SIDEBAR_PRESETS non-all presets have at least one hidden item", () => {
for (const preset of SIDEBAR_PRESETS.filter((p) => p.id !== "all")) {
assert.ok(preset.hiddenItems.length > 0, `Preset '${preset.id}' should hide at least one item`);

View File

@@ -0,0 +1,45 @@
import test from "node:test";
import assert from "node:assert/strict";
import fs from "node:fs";
import path from "node:path";
import { fileURLToPath } from "node:url";
const repoRoot = path.resolve(path.dirname(fileURLToPath(import.meta.url)), "../..");
test("essentials preset is registered in sidebar visibility types and presets", () => {
const types = fs.readFileSync(
path.join(repoRoot, "src/shared/constants/sidebarVisibility/types.ts"),
"utf8"
);
const visibility = fs.readFileSync(
path.join(repoRoot, "src/shared/constants/sidebarVisibility.ts"),
"utf8"
);
const schema = fs.readFileSync(
path.join(repoRoot, "src/shared/validation/settingsSchemas.ts"),
"utf8"
);
assert.match(types, /"essentials"/);
assert.match(visibility, /id:\s*"essentials"/);
assert.match(visibility, /ESSENTIALS_ADVANCED_TOOL_IDS/);
assert.match(schema, /"essentials"/);
});
test("command palette keeps essentials advanced tools searchable", () => {
const source = fs.readFileSync(
path.join(repoRoot, "src/shared/components/CommandPalette.tsx"),
"utf8"
);
assert.match(source, /ESSENTIALS_ADVANCED_TOOL_IDS/);
assert.match(source, /activePreset === "essentials"/);
});
test("essentials i18n keys exist in en.json", () => {
const en = JSON.parse(
fs.readFileSync(path.join(repoRoot, "src/i18n/messages/en.json"), "utf8")
) as { settings: Record<string, string> };
assert.equal(en.settings.presetEssentials, "Essentials");
assert.match(en.settings.presetEssentialsDesc, /Beginner path/i);
assert.match(en.settings.presetEssentialsDesc, /searchable/i);
});

View File

@@ -0,0 +1,44 @@
import test from "node:test";
import assert from "node:assert/strict";
import fs from "node:fs";
import path from "node:path";
import { fileURLToPath } from "node:url";
const repoRoot = path.resolve(path.dirname(fileURLToPath(import.meta.url)), "../..");
const pagePath = path.join(
repoRoot,
"src/app/(dashboard)/dashboard/tools/traffic-inspector/page.tsx"
);
const clientPath = path.join(
repoRoot,
"src/app/(dashboard)/dashboard/tools/traffic-inspector/TrafficInspectorPageClient.tsx"
);
const enPath = path.join(repoRoot, "src/i18n/messages/en.json");
test("Traffic Inspector page passes translated title, subtitle, and purpose", () => {
const pageSource = fs.readFileSync(pagePath, "utf8");
assert.match(pageSource, /title=\{t\("trafficInspector"\)\}/);
assert.match(pageSource, /subtitle=\{t\("trafficInspectorSubtitle"\)\}/);
assert.match(pageSource, /purpose=\{t\("trafficInspectorPurpose"\)\}/);
});
test("Traffic Inspector client renders purpose-first header when props are provided", () => {
const clientSource = fs.readFileSync(clientPath, "utf8");
assert.match(clientSource, /title\s*&&/);
assert.match(clientSource, /subtitle\s*&&/);
assert.match(clientSource, /purpose\s*&&/);
});
test("Traffic Inspector beginner i18n keys exist in en.json", () => {
const en = JSON.parse(fs.readFileSync(enPath, "utf8"));
assert.equal(en.sidebar.trafficInspector, "Traffic Inspector");
assert.equal(
en.sidebar.trafficInspectorSubtitle,
"Inspect request and response traffic from your apps"
);
assert.equal(
typeof en.sidebar.trafficInspectorPurpose,
"string"
);
assert.ok(en.sidebar.trafficInspectorPurpose.length > 20);
});