@agent-native/toolkit 0.207.0-nightly-20261011124220 → 0.207.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/agent-native.eject.json +1 -0
- package/dist/app/auth/AuthPage.d.ts.map +1 -1
- package/dist/app/auth/AuthPage.js +24 -55
- package/dist/app/auth/AuthPage.js.map +1 -1
- package/dist/app/chat/chat/run-recovery.d.ts.map +1 -1
- package/dist/app/chat/chat/run-recovery.js +21 -5
- package/dist/app/chat/chat/run-recovery.js.map +1 -1
- package/dist/app/chat/chat-first/ChatFirstAgentActivityPanel.d.ts.map +1 -1
- package/dist/app/chat/chat-first/ChatFirstAgentActivityPanel.js +3 -2
- package/dist/app/chat/chat-first/ChatFirstAgentActivityPanel.js.map +1 -1
- package/dist/app/i18n/catalogs/ar-SA.d.ts.map +1 -1
- package/dist/app/i18n/catalogs/ar-SA.js +11 -3
- package/dist/app/i18n/catalogs/ar-SA.js.map +1 -1
- package/dist/app/i18n/catalogs/de-DE.d.ts.map +1 -1
- package/dist/app/i18n/catalogs/de-DE.js +11 -3
- package/dist/app/i18n/catalogs/de-DE.js.map +1 -1
- package/dist/app/i18n/catalogs/en-US.d.ts +11 -3
- package/dist/app/i18n/catalogs/en-US.d.ts.map +1 -1
- package/dist/app/i18n/catalogs/en-US.js +11 -3
- package/dist/app/i18n/catalogs/en-US.js.map +1 -1
- package/dist/app/i18n/catalogs/es-ES.d.ts.map +1 -1
- package/dist/app/i18n/catalogs/es-ES.js +11 -3
- package/dist/app/i18n/catalogs/es-ES.js.map +1 -1
- package/dist/app/i18n/catalogs/fr-FR.d.ts.map +1 -1
- package/dist/app/i18n/catalogs/fr-FR.js +11 -3
- package/dist/app/i18n/catalogs/fr-FR.js.map +1 -1
- package/dist/app/i18n/catalogs/hi-IN.d.ts.map +1 -1
- package/dist/app/i18n/catalogs/hi-IN.js +11 -3
- package/dist/app/i18n/catalogs/hi-IN.js.map +1 -1
- package/dist/app/i18n/catalogs/ja-JP.d.ts.map +1 -1
- package/dist/app/i18n/catalogs/ja-JP.js +11 -3
- package/dist/app/i18n/catalogs/ja-JP.js.map +1 -1
- package/dist/app/i18n/catalogs/ko-KR.d.ts.map +1 -1
- package/dist/app/i18n/catalogs/ko-KR.js +11 -3
- package/dist/app/i18n/catalogs/ko-KR.js.map +1 -1
- package/dist/app/i18n/catalogs/pt-BR.d.ts.map +1 -1
- package/dist/app/i18n/catalogs/pt-BR.js +11 -3
- package/dist/app/i18n/catalogs/pt-BR.js.map +1 -1
- package/dist/app/i18n/catalogs/zh-CN.d.ts.map +1 -1
- package/dist/app/i18n/catalogs/zh-CN.js +11 -3
- package/dist/app/i18n/catalogs/zh-CN.js.map +1 -1
- package/dist/app/i18n/catalogs/zh-TW.d.ts.map +1 -1
- package/dist/app/i18n/catalogs/zh-TW.js +11 -3
- package/dist/app/i18n/catalogs/zh-TW.js.map +1 -1
- package/dist/app/onboarding/FirstRunOnboarding.d.ts +2 -3
- package/dist/app/onboarding/FirstRunOnboarding.d.ts.map +1 -1
- package/dist/app/onboarding/FirstRunOnboarding.js +3 -4
- package/dist/app/onboarding/FirstRunOnboarding.js.map +1 -1
- package/dist/app/onboarding/OnboardingBanner.d.ts.map +1 -1
- package/dist/app/onboarding/OnboardingBanner.js +37 -3
- package/dist/app/onboarding/OnboardingBanner.js.map +1 -1
- package/dist/app/onboarding/OnboardingPanel.d.ts.map +1 -1
- package/dist/app/onboarding/OnboardingPanel.js +49 -11
- package/dist/app/onboarding/OnboardingPanel.js.map +1 -1
- package/dist/app/progress/RunsTray.d.ts.map +1 -1
- package/dist/app/progress/RunsTray.js +136 -17
- package/dist/app/progress/RunsTray.js.map +1 -1
- package/dist/app/settings/BuilderConnectPopover.d.ts +1 -0
- package/dist/app/settings/BuilderConnectPopover.d.ts.map +1 -1
- package/dist/app/settings/BuilderConnectPopover.js +21 -5
- package/dist/app/settings/BuilderConnectPopover.js.map +1 -1
- package/dist/app/settings/shell/pages/audit.d.ts.map +1 -1
- package/dist/app/settings/shell/pages/audit.js +3 -3
- package/dist/app/settings/shell/pages/audit.js.map +1 -1
- package/dist/app/settings/useBuilderStatus.d.ts +1 -0
- package/dist/app/settings/useBuilderStatus.d.ts.map +1 -1
- package/dist/app/settings/useBuilderStatus.js +1 -0
- package/dist/app/settings/useBuilderStatus.js.map +1 -1
- package/dist/app/shared/AgentMark.d.ts +6 -0
- package/dist/app/shared/AgentMark.d.ts.map +1 -0
- package/dist/app/shared/AgentMark.js +5 -0
- package/dist/app/shared/AgentMark.js.map +1 -0
- package/dist/app/shared/index.d.ts +1 -0
- package/dist/app/shared/index.d.ts.map +1 -1
- package/dist/app/shared/index.js +1 -0
- package/dist/app/shared/index.js.map +1 -1
- package/dist/app/sharing/ShareButton.d.ts +1 -0
- package/dist/app/sharing/ShareButton.d.ts.map +1 -1
- package/dist/app/sharing/ShareButton.js +2 -2
- package/dist/app/sharing/ShareButton.js.map +1 -1
- package/dist/app/styles/agent-native.css +1 -0
- package/dist/app-shell/sidebar.d.ts.map +1 -1
- package/dist/app-shell/sidebar.js +3 -3
- package/dist/app-shell/sidebar.js.map +1 -1
- package/dist/sharing/ShareControls.d.ts +1 -0
- package/dist/sharing/ShareControls.d.ts.map +1 -1
- package/dist/sharing/ShareControls.js +5 -2
- package/dist/sharing/ShareControls.js.map +1 -1
- package/package.json +4 -4
- package/src/app/auth/AuthPage.attribution.spec.tsx +268 -0
- package/src/app/auth/AuthPage.tsx +27 -54
- package/src/app/chat/chat/run-recovery.spec.tsx +76 -0
- package/src/app/chat/chat/run-recovery.tsx +101 -23
- package/src/app/chat/chat-first/ChatFirstAgentActivityPanel.tsx +11 -5
- package/src/app/i18n/catalogs/ar-SA.ts +18 -3
- package/src/app/i18n/catalogs/de-DE.ts +19 -3
- package/src/app/i18n/catalogs/en-US.ts +18 -3
- package/src/app/i18n/catalogs/es-ES.ts +18 -3
- package/src/app/i18n/catalogs/fr-FR.ts +19 -3
- package/src/app/i18n/catalogs/hi-IN.ts +18 -3
- package/src/app/i18n/catalogs/ja-JP.ts +18 -3
- package/src/app/i18n/catalogs/ko-KR.ts +18 -3
- package/src/app/i18n/catalogs/pt-BR.ts +18 -3
- package/src/app/i18n/catalogs/zh-CN.ts +17 -3
- package/src/app/i18n/catalogs/zh-TW.ts +17 -3
- package/src/app/onboarding/FirstRunOnboarding.spec.tsx +49 -1
- package/src/app/onboarding/FirstRunOnboarding.tsx +4 -13
- package/src/app/onboarding/OnboardingBanner.tsx +70 -5
- package/src/app/onboarding/OnboardingPanel.save-scope.spec.tsx +143 -2
- package/src/app/onboarding/OnboardingPanel.tsx +72 -5
- package/src/app/progress/RunsTray.spec.tsx +577 -0
- package/src/app/progress/RunsTray.tsx +253 -51
- package/src/app/settings/BuilderConnectPopover.spec.tsx +39 -1
- package/src/app/settings/BuilderConnectPopover.tsx +27 -4
- package/src/app/settings/shell/pages/audit.tsx +7 -3
- package/src/app/settings/useBuilderStatus.spec.tsx +21 -1
- package/src/app/settings/useBuilderStatus.ts +2 -0
- package/src/app/shared/AgentMark.tsx +34 -0
- package/src/app/shared/index.ts +1 -0
- package/src/app/sharing/ShareButton.tsx +3 -0
- package/src/app/styles/agent-native.css +1 -0
- package/src/app-shell/sidebar.tsx +29 -21
- package/src/sharing/ShareControls.spec.tsx +36 -0
- package/src/sharing/ShareControls.tsx +17 -2
|
@@ -70,6 +70,402 @@ describe("RunsTrayMenuItem", () => {
|
|
|
70
70
|
|
|
71
71
|
expect(document.body.textContent).toContain("No recent runs");
|
|
72
72
|
});
|
|
73
|
+
|
|
74
|
+
it("makes run titles keyboard-navigable menu items", async () => {
|
|
75
|
+
const now = new Date().toISOString();
|
|
76
|
+
const fetchMock = vi.fn(async (input: RequestInfo | URL) => {
|
|
77
|
+
if (String(input).includes("/agent-chat/runs/list")) {
|
|
78
|
+
return Response.json({
|
|
79
|
+
status: "ok",
|
|
80
|
+
runs: [
|
|
81
|
+
{
|
|
82
|
+
id: "menu-run-1",
|
|
83
|
+
kind: "harness",
|
|
84
|
+
source: "agent-harness",
|
|
85
|
+
title: "Review slides",
|
|
86
|
+
status: "completed",
|
|
87
|
+
goalId: "agent-harness",
|
|
88
|
+
needsInput: false,
|
|
89
|
+
needsApproval: false,
|
|
90
|
+
createdAt: now,
|
|
91
|
+
updatedAt: now,
|
|
92
|
+
sourceRecord: { threadId: "thread-menu" },
|
|
93
|
+
},
|
|
94
|
+
],
|
|
95
|
+
});
|
|
96
|
+
}
|
|
97
|
+
return Response.json([]);
|
|
98
|
+
});
|
|
99
|
+
vi.stubGlobal("fetch", fetchMock);
|
|
100
|
+
|
|
101
|
+
await act(async () => {
|
|
102
|
+
root.render(
|
|
103
|
+
<DropdownMenu open>
|
|
104
|
+
<DropdownMenuContent forceMount>
|
|
105
|
+
<RunsTrayMenuItem pollMs={0} />
|
|
106
|
+
</DropdownMenuContent>
|
|
107
|
+
</DropdownMenu>,
|
|
108
|
+
);
|
|
109
|
+
});
|
|
110
|
+
await act(async () => {
|
|
111
|
+
await vi.waitFor(() =>
|
|
112
|
+
expect(document.body.textContent).toContain("Agent runs"),
|
|
113
|
+
);
|
|
114
|
+
});
|
|
115
|
+
|
|
116
|
+
const trigger = document.querySelector(
|
|
117
|
+
'[aria-label^="Agent runs"]',
|
|
118
|
+
) as HTMLButtonElement | null;
|
|
119
|
+
await act(async () => {
|
|
120
|
+
trigger?.dispatchEvent(
|
|
121
|
+
new MouseEvent("click", { bubbles: true, cancelable: true }),
|
|
122
|
+
);
|
|
123
|
+
});
|
|
124
|
+
|
|
125
|
+
const openedThreads: unknown[] = [];
|
|
126
|
+
const onOpen = (event: Event) =>
|
|
127
|
+
openedThreads.push((event as CustomEvent).detail);
|
|
128
|
+
window.addEventListener("agent-chat:open-thread", onOpen);
|
|
129
|
+
try {
|
|
130
|
+
const titleItem = await vi.waitFor(() => {
|
|
131
|
+
const item = Array.from(
|
|
132
|
+
document.querySelectorAll<HTMLButtonElement>(
|
|
133
|
+
'button[role="menuitem"]',
|
|
134
|
+
),
|
|
135
|
+
).find((button) => button.textContent?.includes("Review slides"));
|
|
136
|
+
expect(item).toBeTruthy();
|
|
137
|
+
return item!;
|
|
138
|
+
});
|
|
139
|
+
|
|
140
|
+
expect(titleItem.hasAttribute("data-radix-collection-item")).toBe(true);
|
|
141
|
+
await act(async () => {
|
|
142
|
+
titleItem.dispatchEvent(
|
|
143
|
+
new KeyboardEvent("keydown", {
|
|
144
|
+
key: "Enter",
|
|
145
|
+
bubbles: true,
|
|
146
|
+
cancelable: true,
|
|
147
|
+
}),
|
|
148
|
+
);
|
|
149
|
+
await vi.waitFor(() => expect(openedThreads).toHaveLength(1));
|
|
150
|
+
});
|
|
151
|
+
expect(openedThreads[0]).toMatchObject({ threadId: "thread-menu" });
|
|
152
|
+
} finally {
|
|
153
|
+
window.removeEventListener("agent-chat:open-thread", onOpen);
|
|
154
|
+
}
|
|
155
|
+
});
|
|
156
|
+
|
|
157
|
+
it("keeps the runs submenu open after stopping and hiding runs", async () => {
|
|
158
|
+
const now = new Date().toISOString();
|
|
159
|
+
const fetchMock = vi.fn(async (input: RequestInfo | URL) => {
|
|
160
|
+
if (String(input).includes("/agent-chat/runs/list")) {
|
|
161
|
+
return Response.json({
|
|
162
|
+
status: "ok",
|
|
163
|
+
runs: [
|
|
164
|
+
{
|
|
165
|
+
id: "menu-run-2",
|
|
166
|
+
kind: "agent-team",
|
|
167
|
+
source: "agent-teams",
|
|
168
|
+
title: "Manage the active run",
|
|
169
|
+
status: "running",
|
|
170
|
+
goalId: "agent-teams",
|
|
171
|
+
needsInput: false,
|
|
172
|
+
needsApproval: false,
|
|
173
|
+
createdAt: now,
|
|
174
|
+
updatedAt: now,
|
|
175
|
+
sourceRecord: { threadId: "thread-menu-2" },
|
|
176
|
+
metadata: { parentThreadId: "thread-parent-2" },
|
|
177
|
+
},
|
|
178
|
+
],
|
|
179
|
+
});
|
|
180
|
+
}
|
|
181
|
+
return Response.json([]);
|
|
182
|
+
});
|
|
183
|
+
vi.stubGlobal("fetch", fetchMock);
|
|
184
|
+
|
|
185
|
+
await act(async () => {
|
|
186
|
+
root.render(
|
|
187
|
+
<DropdownMenu open>
|
|
188
|
+
<DropdownMenuContent forceMount>
|
|
189
|
+
<RunsTrayMenuItem pollMs={0} />
|
|
190
|
+
</DropdownMenuContent>
|
|
191
|
+
</DropdownMenu>,
|
|
192
|
+
);
|
|
193
|
+
});
|
|
194
|
+
const runsTrigger = document.querySelector(
|
|
195
|
+
'[aria-label^="Agent runs"]',
|
|
196
|
+
) as HTMLButtonElement | null;
|
|
197
|
+
await act(async () => {
|
|
198
|
+
runsTrigger?.dispatchEvent(
|
|
199
|
+
new MouseEvent("click", { bubbles: true, cancelable: true }),
|
|
200
|
+
);
|
|
201
|
+
await vi.waitFor(() =>
|
|
202
|
+
expect(document.body.textContent).toContain("Manage the active run"),
|
|
203
|
+
);
|
|
204
|
+
});
|
|
205
|
+
|
|
206
|
+
const stopButton = document.querySelector(
|
|
207
|
+
'[aria-label="Stop Manage the active run"]',
|
|
208
|
+
) as HTMLButtonElement | null;
|
|
209
|
+
expect(stopButton).toBeTruthy();
|
|
210
|
+
await act(async () => {
|
|
211
|
+
stopButton?.dispatchEvent(
|
|
212
|
+
new MouseEvent("click", { bubbles: true, cancelable: true }),
|
|
213
|
+
);
|
|
214
|
+
await vi.waitFor(() =>
|
|
215
|
+
expect(
|
|
216
|
+
document.querySelector('[aria-label="Hide Manage the active run"]'),
|
|
217
|
+
).toBeTruthy(),
|
|
218
|
+
);
|
|
219
|
+
});
|
|
220
|
+
expect(runsTrigger?.getAttribute("aria-expanded")).toBe("true");
|
|
221
|
+
expect(document.activeElement).toBe(runsTrigger);
|
|
222
|
+
|
|
223
|
+
const hideButton = document.querySelector(
|
|
224
|
+
'[aria-label="Hide Manage the active run"]',
|
|
225
|
+
) as HTMLButtonElement | null;
|
|
226
|
+
await act(async () => {
|
|
227
|
+
hideButton?.dispatchEvent(
|
|
228
|
+
new MouseEvent("click", { bubbles: true, cancelable: true }),
|
|
229
|
+
);
|
|
230
|
+
await vi.waitFor(() =>
|
|
231
|
+
expect(document.body.textContent).toContain("No recent runs"),
|
|
232
|
+
);
|
|
233
|
+
});
|
|
234
|
+
expect(runsTrigger?.getAttribute("aria-expanded")).toBe("true");
|
|
235
|
+
expect(document.activeElement).toBe(runsTrigger);
|
|
236
|
+
});
|
|
237
|
+
|
|
238
|
+
it("does not stop a run when a pointer gesture starts on another run", async () => {
|
|
239
|
+
const now = new Date().toISOString();
|
|
240
|
+
const fetchMock = vi.fn(async (input: RequestInfo | URL) => {
|
|
241
|
+
if (String(input).includes("/agent-chat/runs/list")) {
|
|
242
|
+
return Response.json({
|
|
243
|
+
status: "ok",
|
|
244
|
+
runs: [
|
|
245
|
+
{
|
|
246
|
+
id: "menu-run-3",
|
|
247
|
+
kind: "agent-team",
|
|
248
|
+
source: "agent-teams",
|
|
249
|
+
title: "Manage the active run",
|
|
250
|
+
status: "running",
|
|
251
|
+
goalId: "agent-teams",
|
|
252
|
+
needsInput: false,
|
|
253
|
+
needsApproval: false,
|
|
254
|
+
createdAt: now,
|
|
255
|
+
updatedAt: now,
|
|
256
|
+
sourceRecord: { threadId: "thread-menu-3" },
|
|
257
|
+
metadata: { parentThreadId: "thread-parent-3" },
|
|
258
|
+
},
|
|
259
|
+
{
|
|
260
|
+
id: "menu-run-4",
|
|
261
|
+
kind: "agent-team",
|
|
262
|
+
source: "agent-teams",
|
|
263
|
+
title: "Another active run",
|
|
264
|
+
status: "running",
|
|
265
|
+
goalId: "agent-teams",
|
|
266
|
+
needsInput: false,
|
|
267
|
+
needsApproval: false,
|
|
268
|
+
createdAt: now,
|
|
269
|
+
updatedAt: now,
|
|
270
|
+
sourceRecord: { threadId: "thread-menu-4" },
|
|
271
|
+
metadata: { parentThreadId: "thread-parent-4" },
|
|
272
|
+
},
|
|
273
|
+
],
|
|
274
|
+
});
|
|
275
|
+
}
|
|
276
|
+
return Response.json([]);
|
|
277
|
+
});
|
|
278
|
+
vi.stubGlobal("fetch", fetchMock);
|
|
279
|
+
|
|
280
|
+
await act(async () => {
|
|
281
|
+
root.render(
|
|
282
|
+
<DropdownMenu open>
|
|
283
|
+
<DropdownMenuContent forceMount>
|
|
284
|
+
<RunsTrayMenuItem pollMs={0} />
|
|
285
|
+
</DropdownMenuContent>
|
|
286
|
+
</DropdownMenu>,
|
|
287
|
+
);
|
|
288
|
+
});
|
|
289
|
+
const runsTrigger = document.querySelector(
|
|
290
|
+
'[aria-label^="Agent runs"]',
|
|
291
|
+
) as HTMLButtonElement | null;
|
|
292
|
+
await act(async () => {
|
|
293
|
+
runsTrigger?.dispatchEvent(
|
|
294
|
+
new MouseEvent("click", { bubbles: true, cancelable: true }),
|
|
295
|
+
);
|
|
296
|
+
await vi.waitFor(() =>
|
|
297
|
+
expect(document.body.textContent).toContain("Another active run"),
|
|
298
|
+
);
|
|
299
|
+
});
|
|
300
|
+
|
|
301
|
+
const otherRunTitle = Array.from(
|
|
302
|
+
document.querySelectorAll('button[role="menuitem"]'),
|
|
303
|
+
).find((button) => button.textContent?.includes("Another active run"));
|
|
304
|
+
const stopButton = document.querySelector(
|
|
305
|
+
'[aria-label="Stop Manage the active run"]',
|
|
306
|
+
) as HTMLButtonElement | null;
|
|
307
|
+
expect(otherRunTitle).toBeTruthy();
|
|
308
|
+
expect(stopButton).toBeTruthy();
|
|
309
|
+
|
|
310
|
+
await act(async () => {
|
|
311
|
+
otherRunTitle?.dispatchEvent(new Event("pointerdown", { bubbles: true }));
|
|
312
|
+
stopButton?.dispatchEvent(new Event("pointerup", { bubbles: true }));
|
|
313
|
+
stopButton?.dispatchEvent(
|
|
314
|
+
new MouseEvent("click", {
|
|
315
|
+
bubbles: true,
|
|
316
|
+
cancelable: true,
|
|
317
|
+
detail: 1,
|
|
318
|
+
}),
|
|
319
|
+
);
|
|
320
|
+
});
|
|
321
|
+
|
|
322
|
+
expect(
|
|
323
|
+
fetchMock.mock.calls.filter(([input]) =>
|
|
324
|
+
String(input).includes("/agent-chat/runs/menu-run-3/stop"),
|
|
325
|
+
),
|
|
326
|
+
).toHaveLength(0);
|
|
327
|
+
expect(
|
|
328
|
+
document.querySelector('[aria-label="Stop Manage the active run"]'),
|
|
329
|
+
).toBeTruthy();
|
|
330
|
+
});
|
|
331
|
+
|
|
332
|
+
it("does not open another run when a pointer gesture starts on an action", async () => {
|
|
333
|
+
const now = new Date().toISOString();
|
|
334
|
+
const fetchMock = vi.fn(async (input: RequestInfo | URL) => {
|
|
335
|
+
if (String(input).includes("/agent-chat/runs/list")) {
|
|
336
|
+
return Response.json({
|
|
337
|
+
status: "ok",
|
|
338
|
+
runs: [
|
|
339
|
+
{
|
|
340
|
+
id: "menu-run-5",
|
|
341
|
+
kind: "agent-team",
|
|
342
|
+
source: "agent-teams",
|
|
343
|
+
title: "Manage the active run",
|
|
344
|
+
status: "running",
|
|
345
|
+
goalId: "agent-teams",
|
|
346
|
+
needsInput: false,
|
|
347
|
+
needsApproval: false,
|
|
348
|
+
createdAt: now,
|
|
349
|
+
updatedAt: now,
|
|
350
|
+
sourceRecord: { threadId: "thread-menu-5" },
|
|
351
|
+
metadata: { parentThreadId: "thread-parent-5" },
|
|
352
|
+
},
|
|
353
|
+
{
|
|
354
|
+
id: "menu-run-6",
|
|
355
|
+
kind: "harness",
|
|
356
|
+
source: "agent-harness",
|
|
357
|
+
title: "Another active run",
|
|
358
|
+
status: "running",
|
|
359
|
+
goalId: "agent-harness",
|
|
360
|
+
needsInput: false,
|
|
361
|
+
needsApproval: false,
|
|
362
|
+
createdAt: now,
|
|
363
|
+
updatedAt: now,
|
|
364
|
+
sourceRecord: { threadId: "thread-menu-6" },
|
|
365
|
+
},
|
|
366
|
+
],
|
|
367
|
+
});
|
|
368
|
+
}
|
|
369
|
+
return Response.json([]);
|
|
370
|
+
});
|
|
371
|
+
vi.stubGlobal("fetch", fetchMock);
|
|
372
|
+
const onOpenChange = vi.fn();
|
|
373
|
+
|
|
374
|
+
await act(async () => {
|
|
375
|
+
root.render(
|
|
376
|
+
<DropdownMenu open onOpenChange={onOpenChange}>
|
|
377
|
+
<DropdownMenuContent forceMount>
|
|
378
|
+
<RunsTrayMenuItem pollMs={0} />
|
|
379
|
+
</DropdownMenuContent>
|
|
380
|
+
</DropdownMenu>,
|
|
381
|
+
);
|
|
382
|
+
});
|
|
383
|
+
const runsTrigger = document.querySelector(
|
|
384
|
+
'[aria-label^="Agent runs"]',
|
|
385
|
+
) as HTMLButtonElement | null;
|
|
386
|
+
await act(async () => {
|
|
387
|
+
runsTrigger?.dispatchEvent(
|
|
388
|
+
new MouseEvent("click", { bubbles: true, cancelable: true }),
|
|
389
|
+
);
|
|
390
|
+
await vi.waitFor(() =>
|
|
391
|
+
expect(document.body.textContent).toContain("Another active run"),
|
|
392
|
+
);
|
|
393
|
+
});
|
|
394
|
+
|
|
395
|
+
const openedThreads: unknown[] = [];
|
|
396
|
+
const onOpen = (event: Event) =>
|
|
397
|
+
openedThreads.push((event as CustomEvent).detail);
|
|
398
|
+
window.addEventListener("agent-chat:open-thread", onOpen);
|
|
399
|
+
try {
|
|
400
|
+
const stopButton = document.querySelector(
|
|
401
|
+
'[aria-label="Stop Manage the active run"]',
|
|
402
|
+
) as HTMLButtonElement | null;
|
|
403
|
+
const otherRunTitle = Array.from(
|
|
404
|
+
document.querySelectorAll<HTMLButtonElement>('button[role="menuitem"]'),
|
|
405
|
+
).find((button) => button.textContent?.includes("Another active run"));
|
|
406
|
+
expect(stopButton).toBeTruthy();
|
|
407
|
+
expect(otherRunTitle).toBeTruthy();
|
|
408
|
+
|
|
409
|
+
await act(async () => {
|
|
410
|
+
stopButton?.dispatchEvent(new Event("pointerdown", { bubbles: true }));
|
|
411
|
+
otherRunTitle?.dispatchEvent(new Event("pointerup", { bubbles: true }));
|
|
412
|
+
otherRunTitle?.dispatchEvent(
|
|
413
|
+
new MouseEvent("click", {
|
|
414
|
+
bubbles: true,
|
|
415
|
+
cancelable: true,
|
|
416
|
+
detail: 0,
|
|
417
|
+
}),
|
|
418
|
+
);
|
|
419
|
+
});
|
|
420
|
+
|
|
421
|
+
expect(openedThreads).toHaveLength(0);
|
|
422
|
+
expect(onOpenChange).not.toHaveBeenCalledWith(false);
|
|
423
|
+
|
|
424
|
+
const firstRunTitle = Array.from(
|
|
425
|
+
document.querySelectorAll<HTMLButtonElement>('button[role="menuitem"]'),
|
|
426
|
+
).find((button) => button.textContent?.includes("Manage the active run"));
|
|
427
|
+
expect(firstRunTitle).toBeTruthy();
|
|
428
|
+
|
|
429
|
+
await act(async () => {
|
|
430
|
+
firstRunTitle?.dispatchEvent(
|
|
431
|
+
new Event("pointerdown", { bubbles: true }),
|
|
432
|
+
);
|
|
433
|
+
otherRunTitle?.dispatchEvent(new Event("pointerup", { bubbles: true }));
|
|
434
|
+
otherRunTitle?.dispatchEvent(
|
|
435
|
+
new MouseEvent("click", {
|
|
436
|
+
bubbles: true,
|
|
437
|
+
cancelable: true,
|
|
438
|
+
detail: 0,
|
|
439
|
+
}),
|
|
440
|
+
);
|
|
441
|
+
});
|
|
442
|
+
|
|
443
|
+
expect(openedThreads).toHaveLength(0);
|
|
444
|
+
expect(onOpenChange).not.toHaveBeenCalledWith(false);
|
|
445
|
+
|
|
446
|
+
const menuContent = document.querySelector(
|
|
447
|
+
'[role="menu"]',
|
|
448
|
+
) as HTMLElement | null;
|
|
449
|
+
expect(menuContent).toBeTruthy();
|
|
450
|
+
|
|
451
|
+
await act(async () => {
|
|
452
|
+
menuContent?.dispatchEvent(new Event("pointerdown", { bubbles: true }));
|
|
453
|
+
otherRunTitle?.dispatchEvent(new Event("pointerup", { bubbles: true }));
|
|
454
|
+
otherRunTitle?.dispatchEvent(
|
|
455
|
+
new MouseEvent("click", {
|
|
456
|
+
bubbles: true,
|
|
457
|
+
cancelable: true,
|
|
458
|
+
detail: 0,
|
|
459
|
+
}),
|
|
460
|
+
);
|
|
461
|
+
});
|
|
462
|
+
|
|
463
|
+
expect(openedThreads).toHaveLength(0);
|
|
464
|
+
expect(onOpenChange).not.toHaveBeenCalledWith(false);
|
|
465
|
+
} finally {
|
|
466
|
+
window.removeEventListener("agent-chat:open-thread", onOpen);
|
|
467
|
+
}
|
|
468
|
+
});
|
|
73
469
|
});
|
|
74
470
|
|
|
75
471
|
describe("RunsTray polling", () => {
|
|
@@ -198,4 +594,185 @@ describe("RunsTray polling", () => {
|
|
|
198
594
|
document.querySelector('[aria-label="Stop Codex harness"]'),
|
|
199
595
|
).toBeTruthy();
|
|
200
596
|
});
|
|
597
|
+
|
|
598
|
+
it("opens standard and unparented Agent Teams runs from their titles", async () => {
|
|
599
|
+
const now = new Date().toISOString();
|
|
600
|
+
const fetchMock = vi.fn(async (input: RequestInfo | URL) => {
|
|
601
|
+
if (String(input).includes("/agent-chat/runs/list")) {
|
|
602
|
+
return Response.json({
|
|
603
|
+
status: "ok",
|
|
604
|
+
runs: [
|
|
605
|
+
{
|
|
606
|
+
id: "harness-run-2",
|
|
607
|
+
kind: "harness",
|
|
608
|
+
source: "agent-harness",
|
|
609
|
+
title: "Slides import",
|
|
610
|
+
status: "running",
|
|
611
|
+
goalId: "agent-harness",
|
|
612
|
+
needsInput: false,
|
|
613
|
+
needsApproval: false,
|
|
614
|
+
createdAt: now,
|
|
615
|
+
updatedAt: now,
|
|
616
|
+
sourceRecord: { threadId: "thread-slides-import" },
|
|
617
|
+
},
|
|
618
|
+
{
|
|
619
|
+
id: "team-run-2",
|
|
620
|
+
kind: "agent-team",
|
|
621
|
+
source: "agent-teams",
|
|
622
|
+
title: "Slides outline task",
|
|
623
|
+
status: "running",
|
|
624
|
+
goalId: "agent-teams",
|
|
625
|
+
needsInput: false,
|
|
626
|
+
needsApproval: false,
|
|
627
|
+
createdAt: now,
|
|
628
|
+
updatedAt: now,
|
|
629
|
+
sourceRecord: { threadId: "team-chat-thread" },
|
|
630
|
+
},
|
|
631
|
+
],
|
|
632
|
+
});
|
|
633
|
+
}
|
|
634
|
+
return Response.json([]);
|
|
635
|
+
});
|
|
636
|
+
vi.stubGlobal("fetch", fetchMock);
|
|
637
|
+
|
|
638
|
+
await act(async () => {
|
|
639
|
+
root.render(<RunsTray pollMs={0} hideWhenIdle={false} showRecent />);
|
|
640
|
+
});
|
|
641
|
+
await act(async () => {
|
|
642
|
+
await vi.waitFor(() =>
|
|
643
|
+
expect(
|
|
644
|
+
document.querySelector('[aria-label="2 active runs"]'),
|
|
645
|
+
).toBeTruthy(),
|
|
646
|
+
);
|
|
647
|
+
});
|
|
648
|
+
|
|
649
|
+
const trigger = document.querySelector(
|
|
650
|
+
'[aria-label="2 active runs"]',
|
|
651
|
+
) as HTMLButtonElement | null;
|
|
652
|
+
await act(async () => {
|
|
653
|
+
trigger?.dispatchEvent(
|
|
654
|
+
new MouseEvent("click", { bubbles: true, cancelable: true }),
|
|
655
|
+
);
|
|
656
|
+
});
|
|
657
|
+
|
|
658
|
+
const openedThreads: unknown[] = [];
|
|
659
|
+
const onOpen = (event: Event) =>
|
|
660
|
+
openedThreads.push((event as CustomEvent).detail);
|
|
661
|
+
window.addEventListener("agent-chat:open-thread", onOpen);
|
|
662
|
+
try {
|
|
663
|
+
const titleButton = Array.from(document.querySelectorAll("button")).find(
|
|
664
|
+
(button) => button.textContent?.includes("Slides import"),
|
|
665
|
+
);
|
|
666
|
+
expect(titleButton).toBeTruthy();
|
|
667
|
+
|
|
668
|
+
await act(async () => {
|
|
669
|
+
titleButton?.dispatchEvent(
|
|
670
|
+
new MouseEvent("click", { bubbles: true, cancelable: true }),
|
|
671
|
+
);
|
|
672
|
+
await vi.waitFor(() => expect(openedThreads).toHaveLength(1));
|
|
673
|
+
});
|
|
674
|
+
|
|
675
|
+
expect(openedThreads[0]).toMatchObject({
|
|
676
|
+
threadId: "thread-slides-import",
|
|
677
|
+
});
|
|
678
|
+
|
|
679
|
+
const teamTitleButton = Array.from(
|
|
680
|
+
document.querySelectorAll("button"),
|
|
681
|
+
).find((button) => button.textContent?.includes("Slides outline task"));
|
|
682
|
+
expect(teamTitleButton).toBeTruthy();
|
|
683
|
+
|
|
684
|
+
await act(async () => {
|
|
685
|
+
teamTitleButton?.dispatchEvent(
|
|
686
|
+
new MouseEvent("click", { bubbles: true, cancelable: true }),
|
|
687
|
+
);
|
|
688
|
+
await vi.waitFor(() => expect(openedThreads).toHaveLength(2));
|
|
689
|
+
});
|
|
690
|
+
|
|
691
|
+
expect(openedThreads[1]).toMatchObject({
|
|
692
|
+
threadId: "team-chat-thread",
|
|
693
|
+
});
|
|
694
|
+
} finally {
|
|
695
|
+
window.removeEventListener("agent-chat:open-thread", onOpen);
|
|
696
|
+
}
|
|
697
|
+
});
|
|
698
|
+
|
|
699
|
+
it("opens an agent-team run with its parent task context", async () => {
|
|
700
|
+
const now = new Date().toISOString();
|
|
701
|
+
const fetchMock = vi.fn(async (input: RequestInfo | URL) => {
|
|
702
|
+
if (String(input).includes("/agent-chat/runs/list")) {
|
|
703
|
+
return Response.json({
|
|
704
|
+
status: "ok",
|
|
705
|
+
runs: [
|
|
706
|
+
{
|
|
707
|
+
id: "team-run-1",
|
|
708
|
+
kind: "agent-team",
|
|
709
|
+
source: "agent-teams",
|
|
710
|
+
title: "Review Slides task",
|
|
711
|
+
status: "running",
|
|
712
|
+
goalId: "agent-teams",
|
|
713
|
+
needsInput: false,
|
|
714
|
+
needsApproval: false,
|
|
715
|
+
createdAt: now,
|
|
716
|
+
updatedAt: now,
|
|
717
|
+
sourceRecord: { threadId: "child-thread" },
|
|
718
|
+
metadata: {
|
|
719
|
+
parentThreadId: "parent-thread",
|
|
720
|
+
description: "Review the Slides task",
|
|
721
|
+
name: "Slides review",
|
|
722
|
+
},
|
|
723
|
+
},
|
|
724
|
+
],
|
|
725
|
+
});
|
|
726
|
+
}
|
|
727
|
+
return Response.json([]);
|
|
728
|
+
});
|
|
729
|
+
vi.stubGlobal("fetch", fetchMock);
|
|
730
|
+
|
|
731
|
+
await act(async () => {
|
|
732
|
+
root.render(<RunsTray pollMs={0} hideWhenIdle={false} showRecent />);
|
|
733
|
+
});
|
|
734
|
+
await act(async () => {
|
|
735
|
+
await vi.waitFor(() =>
|
|
736
|
+
expect(
|
|
737
|
+
document.querySelector('[aria-label="1 active run"]'),
|
|
738
|
+
).toBeTruthy(),
|
|
739
|
+
);
|
|
740
|
+
});
|
|
741
|
+
|
|
742
|
+
const trigger = document.querySelector(
|
|
743
|
+
'[aria-label="1 active run"]',
|
|
744
|
+
) as HTMLButtonElement | null;
|
|
745
|
+
await act(async () => {
|
|
746
|
+
trigger?.dispatchEvent(
|
|
747
|
+
new MouseEvent("click", { bubbles: true, cancelable: true }),
|
|
748
|
+
);
|
|
749
|
+
});
|
|
750
|
+
|
|
751
|
+
const openedTasks: unknown[] = [];
|
|
752
|
+
const onOpen = (event: Event) =>
|
|
753
|
+
openedTasks.push((event as CustomEvent).detail);
|
|
754
|
+
window.addEventListener("agent-task-open", onOpen);
|
|
755
|
+
try {
|
|
756
|
+
const titleButton = Array.from(document.querySelectorAll("button")).find(
|
|
757
|
+
(button) => button.textContent?.includes("Review Slides task"),
|
|
758
|
+
);
|
|
759
|
+
expect(titleButton).toBeTruthy();
|
|
760
|
+
|
|
761
|
+
await act(async () => {
|
|
762
|
+
titleButton?.dispatchEvent(
|
|
763
|
+
new MouseEvent("click", { bubbles: true, cancelable: true }),
|
|
764
|
+
);
|
|
765
|
+
await vi.waitFor(() => expect(openedTasks).toHaveLength(1));
|
|
766
|
+
});
|
|
767
|
+
|
|
768
|
+
expect(openedTasks[0]).toMatchObject({
|
|
769
|
+
threadId: "child-thread",
|
|
770
|
+
parentThreadId: "parent-thread",
|
|
771
|
+
description: "Review the Slides task",
|
|
772
|
+
name: "Slides review",
|
|
773
|
+
});
|
|
774
|
+
} finally {
|
|
775
|
+
window.removeEventListener("agent-task-open", onOpen);
|
|
776
|
+
}
|
|
777
|
+
});
|
|
201
778
|
});
|