Skip to content

Commit 61401d8

Browse files
authored
Merge branch 'main' into posthog-code/autoresearch-task-switch-latency
2 parents 9849254 + d0002a5 commit 61401d8

59 files changed

Lines changed: 1476 additions & 526 deletions

Some content is hidden

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

.github/workflows/build.yml

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -77,6 +77,9 @@ jobs:
7777
- name: Build enricher
7878
run: pnpm --filter @posthog/enricher build
7979

80+
- name: Build harness
81+
run: pnpm --filter @posthog/harness build
82+
8083
- name: Build agent
8184
run: pnpm --filter agent build
8285

.github/workflows/code-build-test.yml

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -88,6 +88,7 @@ jobs:
8888
pnpm --filter @posthog/shared run build
8989
pnpm --filter @posthog/git run build
9090
pnpm --filter @posthog/enricher run build
91+
pnpm --filter @posthog/harness run build
9192
pnpm --filter @posthog/agent run build
9293
9394
# build/Assets.car is gitignored; regenerate it so the packaged app ships
@@ -205,6 +206,7 @@ jobs:
205206
pnpm --filter @posthog/shared run build
206207
pnpm --filter @posthog/git run build
207208
pnpm --filter @posthog/enricher run build
209+
pnpm --filter @posthog/harness run build
208210
pnpm --filter @posthog/agent run build
209211
210212
- name: Build app
@@ -275,6 +277,7 @@ jobs:
275277
pnpm --filter @posthog/shared run build
276278
pnpm --filter @posthog/git run build
277279
pnpm --filter @posthog/enricher run build
280+
pnpm --filter @posthog/harness run build
278281
pnpm --filter @posthog/agent run build
279282
280283
- name: Build app

.github/workflows/code-release.yml

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -140,6 +140,9 @@ jobs:
140140
- name: Build enricher package
141141
run: pnpm --filter @posthog/enricher run build
142142

143+
- name: Build harness package
144+
run: pnpm --filter @posthog/harness run build
145+
143146
- name: Build agent package
144147
run: pnpm --filter @posthog/agent run build
145148

@@ -331,6 +334,9 @@ jobs:
331334
- name: Build enricher package
332335
run: pnpm --filter @posthog/enricher run build
333336

337+
- name: Build harness package
338+
run: pnpm --filter @posthog/harness run build
339+
334340
- name: Build agent package
335341
run: pnpm --filter @posthog/agent run build
336342

@@ -457,6 +463,9 @@ jobs:
457463
- name: Build enricher package
458464
run: pnpm --filter @posthog/enricher run build
459465

466+
- name: Build harness package
467+
run: pnpm --filter @posthog/harness run build
468+
460469
- name: Build agent package
461470
run: pnpm --filter @posthog/agent run build
462471

.github/workflows/code-storybook.yml

Lines changed: 10 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -149,16 +149,20 @@ jobs:
149149
pid2=$!
150150
wait_all "$pid1" "$pid2"
151151
152-
# @posthog/agent imports @posthog/git's dist, so git must finish
153-
# before the last group starts.
154-
pnpm --filter @posthog/git build
155-
156-
pnpm --filter @posthog/enricher build &
152+
# @posthog/agent imports the dist of @posthog/git and
153+
# @posthog/harness, so both must finish before the last group starts.
154+
pnpm --filter @posthog/git build &
157155
pid3=$!
158-
pnpm --filter @posthog/agent build &
156+
pnpm --filter @posthog/harness build &
159157
pid4=$!
160158
wait_all "$pid3" "$pid4"
161159
160+
pnpm --filter @posthog/enricher build &
161+
pid5=$!
162+
pnpm --filter @posthog/agent build &
163+
pid6=$!
164+
wait_all "$pid5" "$pid6"
165+
162166
- name: Build Storybook
163167
working-directory: apps/code
164168
run: pnpm build-storybook

.github/workflows/code-update-e2e.yml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -106,6 +106,7 @@ jobs:
106106
pnpm --filter @posthog/shared run build
107107
pnpm --filter @posthog/git run build
108108
pnpm --filter @posthog/enricher run build
109+
pnpm --filter @posthog/harness run build
109110
pnpm --filter @posthog/agent run build
110111
111112
- name: Build old + new update pair

.github/workflows/pr-build-installer.yml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -93,6 +93,7 @@ jobs:
9393
pnpm --filter @posthog/shared run build
9494
pnpm --filter @posthog/git run build
9595
pnpm --filter @posthog/enricher run build
96+
pnpm --filter @posthog/harness run build
9697
pnpm --filter @posthog/agent run build
9798
9899
# build/Assets.car is gitignored; regenerate it so the packaged app ships

.github/workflows/test.yml

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -140,8 +140,9 @@ jobs:
140140
pnpm --filter @posthog/shared build
141141
pnpm --filter @posthog/git build
142142
pnpm --filter @posthog/enricher build
143-
pnpm --filter agent build &
144143
wait
144+
pnpm --filter @posthog/harness build
145+
pnpm --filter agent build
145146
146147
- name: Package Electron app
147148
run: pnpm --filter code run package

apps/code/scripts/download-binaries.mjs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@ const DEST_DIR = join(__dirname, "..", "resources", "codex-acp");
2222
const BINARIES = [
2323
{
2424
name: "codex",
25-
version: "0.140.0",
25+
version: "0.144.0",
2626
getUrl: (version, target) => {
2727
if (target.includes("windows")) {
2828
return `https://github.com/openai/codex/releases/download/rust-v${version}/codex-${target}.exe.zip`;

apps/code/snapshots.yml

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -7,11 +7,11 @@ snapshots:
77
archive-archivedtasksview--branch-not-found-dialog--dark:
88
hash: v1.k4693efd2.e96cff68c4f34d389b8cd11870015bf99acdca2dbb39ace8cc51d0e7551e891a.Y_j6ePigJuWFQiciNqn504CKtDXvcZTe6GeEnnP9EmY
99
archive-archivedtasksview--branch-not-found-dialog--light:
10-
hash: v1.k4693efd2.6e61b2982936aa51f9d5f89f6a8a3eac752921fe45e231a0edad8549f1ca8637.YpLKs7304DnWvEUZ569muavj94whl7YemMlP2Z1V9qM
10+
hash: v1.k4693efd2.b3d998e459d8bf39a694a16a8d3861cfbf5700585c5090ca84010e64a65f026e.ZFVmtMdXKtHv7CHr4gNwGIT3LsDE_K65e8jG2PU7fLw
1111
archive-archivedtasksview--default--dark:
12-
hash: v1.k4693efd2.ba91152c666e7d5e5a4ed7cdcc1020a28374ff7a2a04367eacfe9b42002e270c.zmnuTOfMpSscj2lBlnKO8w7t1cKkRqGttPjxcL1IjQU
12+
hash: v1.k4693efd2.ae6a6e4693a50291fb8c10110fe58e23df652de293844300c33ed0dd2a61c201.5nG9TkDCF5Ihx3z3XKeH6vQRs6a3Envq177RVeSAMc8
1313
archive-archivedtasksview--default--light:
14-
hash: v1.k4693efd2.cef5977a704ad5e8d50439462fe32511d8b6bd9821094f23a178091c6935db1b.WNWMI8O_gYh2isGEIX7A0TKEAgq7F9o01PV4MnwRgQE
14+
hash: v1.k4693efd2.22b4a09a47507ddb5a0c84dc8be4bf01816210d9eff2dea3baa4b14c586d8887.S8xaODdd0sbzD5C7QTPki8z3VIRO9aSqrDjLcZgwWlc
1515
archive-archivedtasksview--empty--dark:
1616
hash: v1.k4693efd2.c6acdfd1ef1a2a6144191a701c06f6f16d7b9a5ff90287849ad0b11a26db8007.SKmKu6vwd5POmVLH8CELsPptzbijE9W2wzOoi1OfBlI
1717
archive-archivedtasksview--empty--light:
@@ -25,9 +25,9 @@ snapshots:
2525
archive-archivedtasksview--long-labels--light:
2626
hash: v1.k4693efd2.29752b30fe1095a9ea51f85718d80238de8fa3405259aba25ec0b6a9c1719621.cKYkJ_3BAJK067PBn_YtsSpN9eKWD_RWD2WzIECzWyE
2727
archive-archivedtasksview--many-tasks--dark:
28-
hash: v1.k4693efd2.40d24f07a24c6400c32ae68b39fd908a056beb5dc6df8bcb237ec2ab2b494f4a.l2vjfSQDalCPRtDNV7pbfTKGlMsQoI81jI-UdJfLHWE
28+
hash: v1.k4693efd2.bb3dce57a417523ba1f46ba80ffbd6c5ead80f00724018efab3b476cc8908b91.TFhFNMNfTDTpTEyhGd0tfUgD2kWnU9pXgzW085Q0eg0
2929
archive-archivedtasksview--many-tasks--light:
30-
hash: v1.k4693efd2.52ec9963bfe6f248ffcdaa4c26945d2b7e303115825b65d978aa5aefd4af1007.ZLtOfTZUrznhYeB-N2SIHzQWRzF6TDSaipNkfd8uzjM
30+
hash: v1.k4693efd2.d3064a6a013d9fc98ea521e158267b7ac4b0a0690caa043d5def414844bbd100.eC9B8Hu-hmDxgA2BTY6B5f-rc-g1Va37FjnOWJyqnUA
3131
archive-archivedtasksview--mixed-modes--dark:
3232
hash: v1.k4693efd2.d94039b8cc17a4ad1b720364f41fee58a4843aa9a901443997ba62602f698794.441LWZhT-2WQZJHni4LoOgQsOSr2O103NZOk1pF8ME4
3333
archive-archivedtasksview--mixed-modes--light:
@@ -37,9 +37,9 @@ snapshots:
3737
archive-archivedtasksview--single-task--light:
3838
hash: v1.k4693efd2.e8c79272f21754cd4db934a8677c7f7b480eda4dfc5b4771fc19649932b475c0.WlV7Y7KjBQMAdXfJVBiSVGp-ylrlCmr2Ov9ABnB0WmY
3939
archive-archivedtasksview--with-missing-task--dark:
40-
hash: v1.k4693efd2.74d9ba343428a3f253685597bad5e07f842a2c0c24ee9f53112eb8bddda8fe49._WsfzSXfmvpyxETWVK6bivVMZ7GZ9y_otB9IVO7VQoo
40+
hash: v1.k4693efd2.58144cdaf083f0ff98b136a5bae61686a2a856a0fce7835d5d11647e106b0b4f.-G4zNrpohMozh41d_NvfZ-pD1DUHkANR7XkHBaV6CCQ
4141
archive-archivedtasksview--with-missing-task--light:
42-
hash: v1.k4693efd2.648f64ae048e0915a1d0e7907c22fcc8b553630b4e1d538c5537ceb6aa5bbf25.0gmoZwbpniXv2OXkuSD12wLt34aaHBW-8aEmvrT-PqI
42+
hash: v1.k4693efd2.2aad97fbf529d8e0c0896105051e140af8322d9c699653b0c60d6375dd2ea4c3.mc318EfElvU4a7rtpUNV9VJbFkYNpei4y4vhOcf3GRI
4343
autoresearch-configurable-full-dashboard--before-baseline--dark:
4444
hash: v1.k4693efd2.34b322085d4a0cc5723c4cc8b984fd81cf89809714f11de742605666e6979db2.D9JzgYGAuE95x0QkPVy4uBUYgUIkwrCCA08KMKXkKcg
4545
autoresearch-configurable-full-dashboard--before-baseline--light:

apps/code/src/main/zoom.test.ts

Lines changed: 145 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -20,13 +20,20 @@ vi.mock("./utils/store", () => ({
2020
import { adjustWindowZoom, restoreWindowZoom, setupWindowZoom } from "./zoom";
2121

2222
class FakeWebContents extends EventEmitter {
23+
public destroyed = false;
24+
public readonly setZoomLevelCalls: number[] = [];
2325
public zoomLevel = 0;
2426

27+
public isDestroyed(): boolean {
28+
return this.destroyed;
29+
}
30+
2531
public getZoomLevel(): number {
2632
return this.zoomLevel;
2733
}
2834

2935
public setZoomLevel(level: number): void {
36+
this.setZoomLevelCalls.push(level);
3037
this.zoomLevel = level;
3138
}
3239
}
@@ -89,50 +96,174 @@ describe("window zoom", () => {
8996
expect(window.webContents.zoomLevel).toBe(0.5);
9097
});
9198

92-
it("persists wheel zoom after Chromium updates its level", () => {
99+
it("restores the current level after an external window resize", () => {
93100
const window = createWindow();
94101
setupWindowZoom(window);
95102

96-
window.webContents.emit("zoom-changed");
97-
window.webContents.zoomLevel = 1.5;
103+
window.webContents.emit("zoom-changed", { preventDefault: vi.fn() }, "in");
104+
vi.runAllTimers();
105+
window.webContents.zoomLevel = 0;
106+
107+
window.emit("resize");
98108
vi.runAllTimers();
109+
const restoredZoomLevel = window.webContents.zoomLevel;
110+
adjustWindowZoom(window, 0.5);
99111

100-
expect(store.save).toHaveBeenCalledWith(1.5);
112+
expect({
113+
restoredZoomLevel,
114+
zoomLevel: window.webContents.zoomLevel,
115+
saved: store.save.mock.calls,
116+
}).toEqual({
117+
restoredZoomLevel: 1,
118+
zoomLevel: 1.5,
119+
saved: [[1], [1.5]],
120+
});
101121
});
102122

103-
it("waits for native zoom before applying a menu adjustment", () => {
123+
it.each([
124+
["in", 1],
125+
["out", 0],
126+
] as const)(
127+
"applies wheel zoom %s from the persisted level",
128+
(direction, expected) => {
129+
const window = createWindow();
130+
setupWindowZoom(window);
131+
const event = { preventDefault: vi.fn() };
132+
133+
window.webContents.emit("zoom-changed", event, direction);
134+
vi.runAllTimers();
135+
136+
expect({
137+
prevented: event.preventDefault.mock.calls.length,
138+
zoomLevel: window.webContents.zoomLevel,
139+
saved: store.save.mock.calls,
140+
}).toEqual({
141+
prevented: 1,
142+
zoomLevel: expected,
143+
saved: [[expected]],
144+
});
145+
},
146+
);
147+
148+
it.each(["resize", "resized"] as const)(
149+
"keeps wheel zoom after %s",
150+
(resizeEvent) => {
151+
const window = createWindow();
152+
setupWindowZoom(window);
153+
154+
window.webContents.emit(
155+
"zoom-changed",
156+
{ preventDefault: vi.fn() },
157+
"in",
158+
);
159+
window.emit(resizeEvent);
160+
vi.runAllTimers();
161+
162+
expect({
163+
zoomLevel: window.webContents.zoomLevel,
164+
saved: store.save.mock.calls,
165+
}).toEqual({
166+
zoomLevel: 1,
167+
saved: [[1]],
168+
});
169+
},
170+
);
171+
172+
it("skips redundant restoration during a resize storm", () => {
104173
const window = createWindow();
105174
setupWindowZoom(window);
175+
window.webContents.zoomLevel = 0.5;
176+
177+
window.emit("resize");
178+
vi.runAllTimers();
179+
vi.advanceTimersByTime(16);
180+
window.emit("resize");
181+
vi.runAllTimers();
182+
const callsBeforeReset = [...window.webContents.setZoomLevelCalls];
183+
184+
window.webContents.zoomLevel = 0;
185+
window.emit("resize");
186+
vi.runAllTimers();
106187

107-
window.webContents.emit("zoom-changed");
108-
window.webContents.zoomLevel = 1.5;
188+
expect({
189+
callsBeforeReset,
190+
callsAfterReset: window.webContents.setZoomLevelCalls,
191+
}).toEqual({
192+
callsBeforeReset: [],
193+
callsAfterReset: [0.5],
194+
});
195+
});
196+
197+
it("ignores queued zoom work after the window is destroyed", () => {
198+
const window = createWindow();
199+
setupWindowZoom(window);
200+
201+
window.webContents.emit("zoom-changed", { preventDefault: vi.fn() }, "in");
202+
window.emit("resize");
203+
window.webContents.destroyed = true;
204+
vi.runAllTimers();
205+
206+
expect({
207+
zoomLevelCalls: window.webContents.setZoomLevelCalls,
208+
saved: store.save.mock.calls,
209+
}).toEqual({
210+
zoomLevelCalls: [],
211+
saved: [],
212+
});
213+
});
214+
215+
it("keeps wheel zoom after a renderer reload", () => {
216+
const window = createWindow();
217+
setupWindowZoom(window);
218+
219+
window.webContents.emit("zoom-changed", { preventDefault: vi.fn() }, "in");
220+
window.webContents.emit("did-finish-load");
221+
vi.runAllTimers();
222+
223+
expect({
224+
zoomLevel: window.webContents.zoomLevel,
225+
saved: store.save.mock.calls,
226+
}).toEqual({
227+
zoomLevel: 1,
228+
saved: [[1]],
229+
});
230+
});
231+
232+
it("serializes wheel and menu zoom changes", () => {
233+
const window = createWindow();
234+
setupWindowZoom(window);
235+
236+
window.webContents.emit("zoom-changed", { preventDefault: vi.fn() }, "in");
109237
adjustWindowZoom(window, 0.5);
110238
vi.runAllTimers();
111239

112240
expect({
113241
zoomLevel: window.webContents.zoomLevel,
114242
saved: store.save.mock.calls,
115243
}).toEqual({
116-
zoomLevel: 2,
117-
saved: [[1.5], [2]],
244+
zoomLevel: 1.5,
245+
saved: [[1], [1.5]],
118246
});
119247
});
120248

121-
it("waits for native zoom before restoring after a reload", () => {
249+
it("uses the in-memory zoom level when persistence fails", () => {
122250
const window = createWindow();
123251
setupWindowZoom(window);
252+
store.save.mockImplementation(() => {});
124253

125-
window.webContents.emit("zoom-changed");
126-
window.webContents.zoomLevel = 1.5;
127-
window.webContents.emit("did-finish-load");
254+
window.webContents.emit("zoom-changed", { preventDefault: vi.fn() }, "in");
255+
vi.runAllTimers();
256+
window.webContents.emit("zoom-changed", { preventDefault: vi.fn() }, "in");
128257
vi.runAllTimers();
129258

130259
expect({
260+
persistedZoomLevel: store.state.zoomLevel,
131261
zoomLevel: window.webContents.zoomLevel,
132262
saved: store.save.mock.calls,
133263
}).toEqual({
264+
persistedZoomLevel: 0.5,
134265
zoomLevel: 1.5,
135-
saved: [[1.5]],
266+
saved: [[1], [1.5]],
136267
});
137268
});
138269

0 commit comments

Comments
 (0)