Skip to content

Commit 0bf1574

Browse files
authored
Merge branch 'main' into posthog-code/inbox-priority-filter
2 parents cdd1651 + 5acc1e1 commit 0bf1574

113 files changed

Lines changed: 3943 additions & 1778 deletions

File tree

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

.gitignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ out/
1111
storybook-static
1212
bin/
1313

14+
1415
# Environment
1516
.env
1617
.env.local

apps/code/.gitattributes

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
src/renderer/routeTree.gen.ts linguist-generated=true

apps/code/package.json

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@
2323
"build-icons": "bash scripts/generate-icns.sh",
2424
"typecheck": "tsc -p tsconfig.node.json --noEmit && tsc -p tsconfig.web.json --noEmit",
2525
"generate-client": "tsx scripts/update-openapi-client.ts",
26+
"generate-routes": "node scripts/generate-routes.mjs",
2627
"test": "vitest run",
2728
"test:e2e": "playwright test --config=tests/e2e/playwright.config.ts",
2829
"test:e2e:headed": "playwright test --config=tests/e2e/playwright.config.ts --headed",
@@ -51,10 +52,10 @@
5152
"@electron-forge/plugin-vite": "^7.11.1",
5253
"@electron-forge/publisher-github": "^7.11.1",
5354
"@electron-forge/shared-types": "^7.11.1",
54-
"@reforged/maker-appimage": "^5.2.0",
5555
"@electron/rebuild": "^4.0.3",
5656
"@playwright/test": "^1.42.0",
5757
"@posthog/rollup-plugin": "^1.4.0",
58+
"@reforged/maker-appimage": "^5.2.0",
5859
"@storybook/addon-a11y": "10.2.0",
5960
"@storybook/addon-docs": "10.2.0",
6061
"@storybook/react-vite": "10.2.0",
@@ -67,6 +68,7 @@
6768
"@types/react": "^19.1.0",
6869
"@types/react-dom": "^19.1.0",
6970
"@types/semver": "^7.7.1",
71+
"@types/turndown": "^5.0.6",
7072
"@vitejs/plugin-react": "^4.2.1",
7173
"@vitest/ui": "^4.0.10",
7274
"adm-zip": "^0.5.16",
@@ -118,6 +120,7 @@
118120
"@codemirror/view": "^6.39.17",
119121
"@dnd-kit/react": "^0.1.21",
120122
"@fontsource-variable/inter": "^5.2.8",
123+
"@joplin/turndown-plugin-gfm": "^1.0.67",
121124
"@lezer/common": "^1.5.1",
122125
"@lezer/highlight": "^1.2.3",
123126
"@modelcontextprotocol/ext-apps": "^1.1.2",
@@ -143,7 +146,10 @@
143146
"@radix-ui/themes": "^3.2.1",
144147
"@tailwindcss/vite": "^4.2.2",
145148
"@tanstack/react-query": "^5.90.2",
149+
"@tanstack/react-router": "^1.95.0",
150+
"@tanstack/react-router-devtools": "^1.95.0",
146151
"@tanstack/react-virtual": "^3.13.26",
152+
"@tanstack/router-plugin": "^1.95.0",
147153
"@tiptap/core": "^3.13.0",
148154
"@tiptap/extension-mention": "^3.13.0",
149155
"@tiptap/extension-placeholder": "^3.13.0",
@@ -203,6 +209,7 @@
203209
"tailwind-merge": "^3.5.0",
204210
"tailwindcss-scroll-mask": "^0.0.3",
205211
"tippy.js": "^6.3.7",
212+
"turndown": "^7.2.4",
206213
"tw-animate-css": "^1.4.0",
207214
"vaul": "^1.1.2",
208215
"vscode-icons-js": "^11.6.1",
Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
import path from "node:path";
2+
import { fileURLToPath } from "node:url";
3+
import { Generator, getConfig } from "@tanstack/router-generator";
4+
5+
const __dirname = path.dirname(fileURLToPath(import.meta.url));
6+
const root = path.resolve(__dirname, "..");
7+
8+
const config = getConfig(
9+
{
10+
target: "react",
11+
autoCodeSplitting: true,
12+
routesDirectory: path.resolve(root, "src/renderer/routes"),
13+
generatedRouteTree: path.resolve(root, "src/renderer/routeTree.gen.ts"),
14+
},
15+
root,
16+
);
17+
18+
const generator = new Generator({ config, root });
19+
await generator.run();
20+
console.log("Generated routeTree.gen.ts");

apps/code/src/main/services/agent/auth-adapter.test.ts

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -105,6 +105,18 @@ describe("AgentAuthAdapter", () => {
105105
);
106106
});
107107

108+
it("identifies as the PostHog Code consumer so the MCP server emits UI-app metadata", async () => {
109+
const { servers } = await adapter.buildMcpServers(baseCredentials);
110+
111+
const posthogServer = servers.find((s) => s.name === "posthog");
112+
expect(posthogServer).toBeDefined();
113+
expect(posthogServer?.headers).toEqual(
114+
expect.arrayContaining([
115+
{ name: "x-posthog-mcp-consumer", value: "posthog-code" },
116+
]),
117+
);
118+
});
119+
108120
it("routes authenticated installed MCP servers through the proxy URL", async () => {
109121
mockFetch.mockResolvedValue({
110122
ok: true,

apps/code/src/main/services/agent/auth-adapter.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -99,6 +99,8 @@ export class AgentAuthAdapter {
9999
value: String(credentials.projectId),
100100
},
101101
{ name: "x-posthog-mcp-version", value: "2" },
102+
// Identify as the PostHog Code UI-apps host.
103+
{ name: "x-posthog-mcp-consumer", value: "posthog-code" },
102104
],
103105
});
104106

Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,45 @@
1+
import { beforeEach, describe, expect, it, vi } from "vitest";
2+
3+
vi.mock("../../utils/logger", () => ({
4+
logger: {
5+
scope: () => ({
6+
info: vi.fn(),
7+
debug: vi.fn(),
8+
warn: vi.fn(),
9+
error: vi.fn(),
10+
}),
11+
},
12+
}));
13+
14+
import { McpAppsService } from "./service";
15+
16+
function makeService(): McpAppsService {
17+
const urlLauncher = { launch: vi.fn() };
18+
return new McpAppsService(urlLauncher as never);
19+
}
20+
21+
describe("McpAppsService.getUiResourceByUri", () => {
22+
let service: McpAppsService;
23+
24+
beforeEach(() => {
25+
service = makeService();
26+
});
27+
28+
it("rejects non-ui:// URIs without attempting a fetch", async () => {
29+
await expect(
30+
service.getUiResourceByUri("posthog", "https://evil.example/app.html"),
31+
).resolves.toBeNull();
32+
await expect(
33+
service.getUiResourceByUri("posthog", "file:///etc/passwd"),
34+
).resolves.toBeNull();
35+
});
36+
37+
it("rejects when the server has no connection config", async () => {
38+
// ui:// passes the guard, but with no configured server the lazy connection
39+
// fails. The fetch rethrows rather than caching a permanent null, so the
40+
// caller's query can surface the error and retry once boot populates configs.
41+
await expect(
42+
service.getUiResourceByUri("posthog", "ui://posthog/survey-list.html"),
43+
).rejects.toThrow("No server config for: posthog");
44+
});
45+
});

0 commit comments

Comments
 (0)