@agent-native/toolkit 0.204.0 → 0.204.1-nightly-20261008034100
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/dist/app/agent-page/AgentJobsTab.d.ts.map +1 -1
- package/dist/app/agent-page/AgentJobsTab.js +4 -2
- package/dist/app/agent-page/AgentJobsTab.js.map +1 -1
- package/dist/app/agent-page/AutomationDetailsDialog.d.ts +2 -1
- package/dist/app/agent-page/AutomationDetailsDialog.d.ts.map +1 -1
- package/dist/app/agent-page/AutomationDetailsDialog.js +8 -4
- package/dist/app/agent-page/AutomationDetailsDialog.js.map +1 -1
- package/dist/app/agent-page/ScheduledTriggerNotice.d.ts.map +1 -1
- package/dist/app/agent-page/ScheduledTriggerNotice.js +41 -19
- package/dist/app/agent-page/ScheduledTriggerNotice.js.map +1 -1
- package/dist/app/agent-page/use-jobs.d.ts +1 -1
- package/dist/app/agent-page/use-jobs.d.ts.map +1 -1
- package/dist/app/agentkit/react/components.d.ts.map +1 -1
- package/dist/app/agentkit/react/components.js +124 -45
- package/dist/app/agentkit/react/components.js.map +1 -1
- package/dist/app/agentkit/react/context.d.ts +22 -1
- package/dist/app/agentkit/react/context.d.ts.map +1 -1
- package/dist/app/agentkit/react/context.js +14 -1
- package/dist/app/agentkit/react/context.js.map +1 -1
- package/dist/app/agentkit/react/root.d.ts +3 -2
- package/dist/app/agentkit/react/root.d.ts.map +1 -1
- package/dist/app/agentkit/react/root.js +2 -2
- package/dist/app/agentkit/react/root.js.map +1 -1
- package/dist/app/agentkit/react/styles.css +32 -2
- package/dist/app/chat/AgentKitAssistantChat.d.ts.map +1 -1
- package/dist/app/chat/AgentKitAssistantChat.js +28 -3
- package/dist/app/chat/AgentKitAssistantChat.js.map +1 -1
- package/dist/app/chat/AgentPanel.js +1 -1
- package/dist/app/chat/AgentPanel.js.map +1 -1
- package/dist/app/chat/RunStuckBanner.d.ts +8 -1
- package/dist/app/chat/RunStuckBanner.d.ts.map +1 -1
- package/dist/app/chat/RunStuckBanner.js +68 -6
- package/dist/app/chat/RunStuckBanner.js.map +1 -1
- package/dist/app/chat/chat/run-recovery.d.ts +4 -2
- package/dist/app/chat/chat/run-recovery.d.ts.map +1 -1
- package/dist/app/chat/chat/run-recovery.js +3 -3
- package/dist/app/chat/chat/run-recovery.js.map +1 -1
- package/dist/app/chat/composer/use-mention-search.d.ts +1 -0
- package/dist/app/chat/composer/use-mention-search.d.ts.map +1 -1
- package/dist/app/chat/feedback-report.d.ts +12 -0
- package/dist/app/chat/feedback-report.d.ts.map +1 -0
- package/dist/app/chat/feedback-report.js +21 -0
- package/dist/app/chat/feedback-report.js.map +1 -0
- package/dist/app/chat/reconcile-settled-run.d.ts +15 -0
- package/dist/app/chat/reconcile-settled-run.d.ts.map +1 -0
- package/dist/app/chat/reconcile-settled-run.js +41 -0
- package/dist/app/chat/reconcile-settled-run.js.map +1 -0
- package/dist/app/i18n/catalogs/ar-SA.d.ts.map +1 -1
- package/dist/app/i18n/catalogs/ar-SA.js +9 -0
- 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 +9 -0
- package/dist/app/i18n/catalogs/de-DE.js.map +1 -1
- package/dist/app/i18n/catalogs/en-US.d.ts +9 -0
- package/dist/app/i18n/catalogs/en-US.d.ts.map +1 -1
- package/dist/app/i18n/catalogs/en-US.js +9 -0
- 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 +9 -0
- 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 +9 -0
- 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 +9 -0
- 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 +9 -0
- 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 +9 -0
- 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 +9 -0
- 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 +9 -0
- 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 +9 -0
- package/dist/app/i18n/catalogs/zh-TW.js.map +1 -1
- package/dist/app/settings/shell/pages/audit.d.ts.map +1 -1
- package/dist/app/settings/shell/pages/audit.js +11 -2
- package/dist/app/settings/shell/pages/audit.js.map +1 -1
- package/dist/composer/ComposerContextMenu.d.ts +14 -1
- package/dist/composer/ComposerContextMenu.d.ts.map +1 -1
- package/dist/composer/ComposerContextMenu.js +65 -19
- package/dist/composer/ComposerContextMenu.js.map +1 -1
- package/dist/composer/MentionPopover.d.ts.map +1 -1
- package/dist/composer/MentionPopover.js +3 -3
- package/dist/composer/MentionPopover.js.map +1 -1
- package/dist/composer/PromptComposer.d.ts +1 -1
- package/dist/composer/PromptComposer.d.ts.map +1 -1
- package/dist/composer/TiptapComposer.d.ts +2 -2
- package/dist/composer/TiptapComposer.d.ts.map +1 -1
- package/dist/composer/TiptapComposer.js +92 -36
- package/dist/composer/TiptapComposer.js.map +1 -1
- package/dist/composer/use-mention-search.d.ts +1 -0
- package/dist/composer/use-mention-search.d.ts.map +1 -1
- package/dist/composer/use-mention-search.js +8 -1
- package/dist/composer/use-mention-search.js.map +1 -1
- package/package.json +4 -4
- package/src/app/agent-page/AgentJobsTab.blocked.spec.tsx +43 -0
- package/src/app/agent-page/AgentJobsTab.tsx +14 -5
- package/src/app/agent-page/AutomationDetailsDialog.tsx +22 -8
- package/src/app/agent-page/ScheduledTriggerNotice.spec.tsx +45 -3
- package/src/app/agent-page/ScheduledTriggerNotice.tsx +52 -31
- package/src/app/agent-page/use-jobs.ts +1 -1
- package/src/app/agentkit/react/components.interaction.spec.tsx +311 -1
- package/src/app/agentkit/react/components.spec.tsx +106 -2
- package/src/app/agentkit/react/components.tsx +217 -80
- package/src/app/agentkit/react/context.tsx +36 -0
- package/src/app/agentkit/react/root.tsx +4 -0
- package/src/app/agentkit/react/styles.css +32 -2
- package/src/app/chat/AgentKitAssistantChat.tsx +35 -2
- package/src/app/chat/AgentPanel.header.spec.ts +43 -7
- package/src/app/chat/AgentPanel.tsx +1 -1
- package/src/app/chat/RunStuckBanner.spec.tsx +258 -17
- package/src/app/chat/RunStuckBanner.tsx +107 -5
- package/src/app/chat/chat/run-recovery.tsx +10 -2
- package/src/app/chat/feedback-report.spec.ts +45 -0
- package/src/app/chat/feedback-report.ts +27 -0
- package/src/app/chat/reconcile-settled-run.spec.ts +112 -0
- package/src/app/chat/reconcile-settled-run.ts +57 -0
- package/src/app/i18n/catalogs/ar-SA.ts +12 -0
- package/src/app/i18n/catalogs/de-DE.ts +12 -0
- package/src/app/i18n/catalogs/en-US.ts +12 -0
- package/src/app/i18n/catalogs/es-ES.ts +12 -0
- package/src/app/i18n/catalogs/fr-FR.ts +12 -0
- package/src/app/i18n/catalogs/hi-IN.ts +12 -0
- package/src/app/i18n/catalogs/ja-JP.ts +12 -0
- package/src/app/i18n/catalogs/ko-KR.ts +12 -0
- package/src/app/i18n/catalogs/pt-BR.ts +12 -0
- package/src/app/i18n/catalogs/zh-CN.ts +10 -0
- package/src/app/i18n/catalogs/zh-TW.ts +10 -0
- package/src/app/settings/shell/pages/audit.spec.tsx +30 -0
- package/src/app/settings/shell/pages/audit.tsx +12 -1
- package/src/composer/ComposerContextMenu.tsx +94 -22
- package/src/composer/ComposerPlusMenu.parity.spec.tsx +218 -233
- package/src/composer/MentionPopover.tsx +12 -3
- package/src/composer/PromptComposer.context.spec.tsx +526 -195
- package/src/composer/PromptComposer.tsx +1 -1
- package/src/composer/TiptapComposer.tsx +105 -37
- package/src/composer/use-mention-search.ts +8 -1
|
@@ -96,17 +96,16 @@ async function mount(props: Partial<PromptComposerProps> = {}) {
|
|
|
96
96
|
});
|
|
97
97
|
return { composerRef, onSubmit };
|
|
98
98
|
}
|
|
99
|
-
async function open(
|
|
100
|
-
const target =
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
: container.querySelector<HTMLElement>(".ProseMirror");
|
|
99
|
+
async function open(enterAddContext = false) {
|
|
100
|
+
const target = container.querySelector<HTMLElement>(
|
|
101
|
+
'button[aria-label="Add context"]',
|
|
102
|
+
);
|
|
104
103
|
expect(target).not.toBeNull();
|
|
105
104
|
await act(async () => {
|
|
106
105
|
target!.focus();
|
|
107
106
|
target!.dispatchEvent(
|
|
108
107
|
new KeyboardEvent("keydown", {
|
|
109
|
-
key:
|
|
108
|
+
key: "ArrowDown",
|
|
110
109
|
bubbles: true,
|
|
111
110
|
cancelable: true,
|
|
112
111
|
}),
|
|
@@ -193,250 +192,236 @@ describe("shared default action preservation", () => {
|
|
|
193
192
|
expect(merged[0]).toBe(provided[0]);
|
|
194
193
|
});
|
|
195
194
|
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
if (mode === "hidden") {
|
|
206
|
-
expect(
|
|
207
|
-
container.querySelector('button[aria-label="Add context"]'),
|
|
208
|
-
).toBeNull();
|
|
209
|
-
if (trigger === "@") {
|
|
210
|
-
await open(trigger);
|
|
211
|
-
expect(document.querySelector('[role="menu"]')).toBeNull();
|
|
212
|
-
}
|
|
213
|
-
} else {
|
|
214
|
-
await open(trigger, false);
|
|
215
|
-
const expected =
|
|
216
|
-
mode === "full"
|
|
217
|
-
? [
|
|
218
|
-
"Upload File",
|
|
219
|
-
"Schedule Task",
|
|
220
|
-
"Create Automation",
|
|
221
|
-
"Integrations",
|
|
222
|
-
"Create Skill",
|
|
223
|
-
]
|
|
224
|
-
: mode === "terminal"
|
|
225
|
-
? ["New terminal", "CLI terminal mode"]
|
|
226
|
-
: ["Upload File"];
|
|
227
|
-
expect(labels()).toEqual(expected);
|
|
228
|
-
}
|
|
229
|
-
if (mode === "full") {
|
|
230
|
-
expect(useOrg).toHaveBeenCalled();
|
|
231
|
-
expect(useCreateMcpServer).toHaveBeenCalled();
|
|
232
|
-
} else {
|
|
233
|
-
expect(useOrg).not.toHaveBeenCalled();
|
|
234
|
-
expect(useCreateMcpServer).not.toHaveBeenCalled();
|
|
235
|
-
expect(isMcpIntegrationAvailable).not.toHaveBeenCalled();
|
|
236
|
-
}
|
|
237
|
-
},
|
|
238
|
-
);
|
|
239
|
-
|
|
240
|
-
it.each([
|
|
241
|
-
["Schedule Task", "Create a recurring job: Draft", "manage-jobs"],
|
|
242
|
-
[
|
|
243
|
-
"Create Automation",
|
|
244
|
-
"Create an automation: Draft",
|
|
245
|
-
"manage-automations",
|
|
246
|
-
],
|
|
247
|
-
["Create Extension", "Create an extension: Draft", "create-extension"],
|
|
248
|
-
["Create new skill", "Create a skill: Draft", "resources"],
|
|
249
|
-
])(
|
|
250
|
-
`${trigger} submits %s instructions through the accepted host path`,
|
|
251
|
-
async (action, message, context) => {
|
|
252
|
-
const { composerRef, onSubmit } = await mount({
|
|
253
|
-
contextMenuItems: [
|
|
254
|
-
{ id: "host", label: "Host source", onSelect: vi.fn() },
|
|
255
|
-
],
|
|
256
|
-
extensionTools: true,
|
|
257
|
-
});
|
|
258
|
-
await open(trigger, false);
|
|
259
|
-
expect(labels()).not.toContain("Host source");
|
|
260
|
-
if (action === "Create new skill") await choose("Create Skill");
|
|
261
|
-
await choose(action);
|
|
262
|
-
expect(
|
|
263
|
-
container.querySelector('[data-agent-composer-slot="mode-row"]'),
|
|
264
|
-
).not.toBeNull();
|
|
265
|
-
await act(async () => {
|
|
266
|
-
expect(await composerRef.current!.submitWithText("Draft")).toBe(true);
|
|
267
|
-
});
|
|
268
|
-
expect(onSubmit).toHaveBeenCalledExactlyOnceWith(
|
|
269
|
-
message,
|
|
270
|
-
[],
|
|
271
|
-
[],
|
|
272
|
-
expect.objectContaining({
|
|
273
|
-
composerModeContext: expect.stringContaining(context),
|
|
274
|
-
intent: "immediate",
|
|
275
|
-
}),
|
|
276
|
-
);
|
|
277
|
-
expect(sendToAgentChat).not.toHaveBeenCalled();
|
|
195
|
+
it.each(["full", "upload-only", "terminal", "hidden"] as const)(
|
|
196
|
+
"+ respects %s action and resource gates",
|
|
197
|
+
async (mode) => {
|
|
198
|
+
const onChange = vi.fn();
|
|
199
|
+
await mount({
|
|
200
|
+
plusMenuMode: mode,
|
|
201
|
+
terminalModeControl: { enabled: false, onChange },
|
|
202
|
+
});
|
|
203
|
+
if (mode === "hidden") {
|
|
278
204
|
expect(
|
|
279
|
-
container.querySelector('[
|
|
205
|
+
container.querySelector('button[aria-label="Add context"]'),
|
|
280
206
|
).toBeNull();
|
|
281
|
-
}
|
|
282
|
-
|
|
207
|
+
} else {
|
|
208
|
+
await open();
|
|
209
|
+
const expected =
|
|
210
|
+
mode === "full"
|
|
211
|
+
? [
|
|
212
|
+
"Upload File",
|
|
213
|
+
"Schedule Task",
|
|
214
|
+
"Create Automation",
|
|
215
|
+
"Integrations",
|
|
216
|
+
"Create Skill",
|
|
217
|
+
]
|
|
218
|
+
: mode === "terminal"
|
|
219
|
+
? ["New terminal", "CLI terminal mode"]
|
|
220
|
+
: ["Upload File"];
|
|
221
|
+
expect(labels()).toEqual(expected);
|
|
222
|
+
}
|
|
223
|
+
if (mode === "full") {
|
|
224
|
+
expect(useOrg).toHaveBeenCalled();
|
|
225
|
+
expect(useCreateMcpServer).toHaveBeenCalled();
|
|
226
|
+
} else {
|
|
227
|
+
expect(useOrg).not.toHaveBeenCalled();
|
|
228
|
+
expect(useCreateMcpServer).not.toHaveBeenCalled();
|
|
229
|
+
expect(isMcpIntegrationAvailable).not.toHaveBeenCalled();
|
|
230
|
+
}
|
|
231
|
+
},
|
|
232
|
+
);
|
|
283
233
|
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
234
|
+
it.each([
|
|
235
|
+
["Schedule Task", "Create a recurring job: Draft", "manage-jobs"],
|
|
236
|
+
["Create Automation", "Create an automation: Draft", "manage-automations"],
|
|
237
|
+
["Create Extension", "Create an extension: Draft", "create-extension"],
|
|
238
|
+
["Create new skill", "Create a skill: Draft", "resources"],
|
|
239
|
+
])(
|
|
240
|
+
"+ submits %s instructions through the accepted host path",
|
|
241
|
+
async (action, message, context) => {
|
|
242
|
+
const { composerRef, onSubmit } = await mount({
|
|
243
|
+
contextMenuItems: [
|
|
244
|
+
{ id: "host", label: "Host source", onSelect: vi.fn() },
|
|
245
|
+
],
|
|
246
|
+
extensionTools: true,
|
|
295
247
|
});
|
|
248
|
+
await open();
|
|
249
|
+
expect(labels()).not.toContain("Host source");
|
|
250
|
+
if (action === "Create new skill") await choose("Create Skill");
|
|
251
|
+
await choose(action);
|
|
296
252
|
expect(
|
|
297
253
|
container.querySelector('[data-agent-composer-slot="mode-row"]'),
|
|
298
|
-
).toBeNull();
|
|
299
|
-
expect(container.querySelector(".ProseMirror")?.textContent).toContain(
|
|
300
|
-
"Draft",
|
|
301
|
-
);
|
|
302
|
-
expect(document.activeElement).toBe(
|
|
303
|
-
container.querySelector(".ProseMirror"),
|
|
304
|
-
);
|
|
254
|
+
).not.toBeNull();
|
|
305
255
|
await act(async () => {
|
|
306
256
|
expect(await composerRef.current!.submitWithText("Draft")).toBe(true);
|
|
307
257
|
});
|
|
308
|
-
expect(onSubmit
|
|
309
|
-
|
|
310
|
-
|
|
258
|
+
expect(onSubmit).toHaveBeenCalledExactlyOnceWith(
|
|
259
|
+
message,
|
|
260
|
+
[],
|
|
261
|
+
[],
|
|
262
|
+
expect.objectContaining({
|
|
263
|
+
composerModeContext: expect.stringContaining(context),
|
|
264
|
+
intent: "immediate",
|
|
265
|
+
}),
|
|
311
266
|
);
|
|
312
267
|
expect(sendToAgentChat).not.toHaveBeenCalled();
|
|
268
|
+
expect(
|
|
269
|
+
container.querySelector('[data-agent-composer-slot="mode-row"]'),
|
|
270
|
+
).toBeNull();
|
|
271
|
+
},
|
|
272
|
+
);
|
|
273
|
+
|
|
274
|
+
it("+ clears automation mode through its accessible Cancel button", async () => {
|
|
275
|
+
const { composerRef, onSubmit } = await mount();
|
|
276
|
+
await open();
|
|
277
|
+
await choose("Create Automation");
|
|
278
|
+
const cancel = container.querySelector<HTMLButtonElement>(
|
|
279
|
+
'[data-agent-composer-slot="mode-row"] button[aria-label="Cancel"]',
|
|
280
|
+
);
|
|
281
|
+
expect(cancel).not.toBeNull();
|
|
282
|
+
await act(async () => {
|
|
283
|
+
cancel!.focus();
|
|
284
|
+
cancel!.click();
|
|
285
|
+
});
|
|
286
|
+
expect(
|
|
287
|
+
container.querySelector('[data-agent-composer-slot="mode-row"]'),
|
|
288
|
+
).toBeNull();
|
|
289
|
+
expect(container.querySelector(".ProseMirror")?.textContent).toContain(
|
|
290
|
+
"Draft",
|
|
291
|
+
);
|
|
292
|
+
expect(document.activeElement).toBe(
|
|
293
|
+
container.querySelector(".ProseMirror"),
|
|
294
|
+
);
|
|
295
|
+
await act(async () => {
|
|
296
|
+
expect(await composerRef.current!.submitWithText("Draft")).toBe(true);
|
|
313
297
|
});
|
|
298
|
+
expect(onSubmit.mock.calls[0][0]).toBe("Draft");
|
|
299
|
+
expect(onSubmit.mock.calls[0][3]).not.toHaveProperty("composerModeContext");
|
|
300
|
+
expect(sendToAgentChat).not.toHaveBeenCalled();
|
|
301
|
+
});
|
|
314
302
|
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
});
|
|
328
|
-
await open(trigger, false);
|
|
329
|
-
expect(labels().filter((label) => label === "Integrations")).toHaveLength(
|
|
330
|
-
1,
|
|
331
|
-
);
|
|
332
|
-
await choose("Integrations");
|
|
333
|
-
await choose("Connect / Manage");
|
|
334
|
-
expect(configure).toHaveBeenCalledOnce();
|
|
335
|
-
expect(document.querySelector('[role="dialog"]')).toBeNull();
|
|
303
|
+
it("+ uses host Integrations, without abandoning its configuration action", async () => {
|
|
304
|
+
const configure = vi.fn();
|
|
305
|
+
await mount({
|
|
306
|
+
contextMenuItems: [
|
|
307
|
+
{
|
|
308
|
+
id: "integrations",
|
|
309
|
+
label: "Integrations",
|
|
310
|
+
children: [
|
|
311
|
+
{ id: "connect", label: "Connect / Manage", onSelect: configure },
|
|
312
|
+
],
|
|
313
|
+
},
|
|
314
|
+
],
|
|
336
315
|
});
|
|
316
|
+
await open();
|
|
317
|
+
expect(labels().filter((label) => label === "Integrations")).toHaveLength(
|
|
318
|
+
1,
|
|
319
|
+
);
|
|
320
|
+
await choose("Integrations");
|
|
321
|
+
await choose("Connect / Manage");
|
|
322
|
+
expect(configure).toHaveBeenCalledOnce();
|
|
323
|
+
expect(document.querySelector('[role="dialog"]')).toBeNull();
|
|
324
|
+
});
|
|
337
325
|
|
|
338
|
-
|
|
339
|
-
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
|
|
343
|
-
|
|
344
|
-
|
|
345
|
-
|
|
346
|
-
});
|
|
347
|
-
expect(onAttachmentRequest).toHaveBeenCalledOnce();
|
|
348
|
-
await mount({ attachmentsEnabled: false });
|
|
349
|
-
await open(trigger, false);
|
|
350
|
-
expect(labels()).not.toContain("Upload File");
|
|
351
|
-
await close();
|
|
352
|
-
await mount();
|
|
353
|
-
const input = container.querySelector<HTMLInputElement>(
|
|
354
|
-
'input[type="file"][multiple]',
|
|
355
|
-
)!;
|
|
356
|
-
const click = vi.spyOn(input, "click").mockImplementation(() => {});
|
|
357
|
-
await open(trigger, false);
|
|
358
|
-
await choose("Upload File");
|
|
359
|
-
expect(click).toHaveBeenCalledOnce();
|
|
326
|
+
it("+ preserves native upload and storage-setup handoff", async () => {
|
|
327
|
+
const onAttachmentRequest = vi.fn();
|
|
328
|
+
await mount({ attachmentsEnabled: false, onAttachmentRequest });
|
|
329
|
+
await open();
|
|
330
|
+
expect(onAttachmentRequest).not.toHaveBeenCalled();
|
|
331
|
+
await choose("Upload File");
|
|
332
|
+
await act(async () => {
|
|
333
|
+
await new Promise(requestAnimationFrame);
|
|
360
334
|
});
|
|
335
|
+
expect(onAttachmentRequest).toHaveBeenCalledOnce();
|
|
336
|
+
await mount({ attachmentsEnabled: false });
|
|
337
|
+
await open();
|
|
338
|
+
expect(labels()).not.toContain("Upload File");
|
|
339
|
+
await close();
|
|
340
|
+
await mount();
|
|
341
|
+
const input = container.querySelector<HTMLInputElement>(
|
|
342
|
+
'input[type="file"][multiple]',
|
|
343
|
+
)!;
|
|
344
|
+
const click = vi.spyOn(input, "click").mockImplementation(() => {});
|
|
345
|
+
await open();
|
|
346
|
+
await choose("Upload File");
|
|
347
|
+
expect(click).toHaveBeenCalledOnce();
|
|
348
|
+
});
|
|
361
349
|
|
|
362
|
-
|
|
363
|
-
|
|
364
|
-
|
|
365
|
-
|
|
366
|
-
|
|
367
|
-
|
|
368
|
-
});
|
|
369
|
-
await open(trigger, false);
|
|
370
|
-
await choose("New terminal");
|
|
371
|
-
expect(onChange).toHaveBeenCalledExactlyOnceWith(true);
|
|
372
|
-
expect(onNewTerminal).not.toHaveBeenCalled();
|
|
373
|
-
await mount({
|
|
374
|
-
plusMenuMode: "terminal",
|
|
375
|
-
terminalModeControl: { enabled: true, onChange, onNewTerminal },
|
|
376
|
-
});
|
|
377
|
-
await open(trigger, false);
|
|
378
|
-
expect(item("CLI terminal mode").getAttribute("aria-checked")).toBe(
|
|
379
|
-
"true",
|
|
380
|
-
);
|
|
381
|
-
await choose("New terminal");
|
|
382
|
-
expect(onNewTerminal).toHaveBeenCalledOnce();
|
|
383
|
-
await open(trigger, false);
|
|
384
|
-
await choose("CLI terminal mode");
|
|
385
|
-
expect(onChange).toHaveBeenLastCalledWith(false);
|
|
386
|
-
expect(useOrg).not.toHaveBeenCalled();
|
|
350
|
+
it("+ retains terminal creation and checked mode controls", async () => {
|
|
351
|
+
const onChange = vi.fn();
|
|
352
|
+
const onNewTerminal = vi.fn();
|
|
353
|
+
await mount({
|
|
354
|
+
plusMenuMode: "terminal",
|
|
355
|
+
terminalModeControl: { enabled: false, onChange, onNewTerminal },
|
|
387
356
|
});
|
|
357
|
+
await open();
|
|
358
|
+
await choose("New terminal");
|
|
359
|
+
expect(onChange).toHaveBeenCalledExactlyOnceWith(true);
|
|
360
|
+
expect(onNewTerminal).not.toHaveBeenCalled();
|
|
361
|
+
await mount({
|
|
362
|
+
plusMenuMode: "terminal",
|
|
363
|
+
terminalModeControl: { enabled: true, onChange, onNewTerminal },
|
|
364
|
+
});
|
|
365
|
+
await open();
|
|
366
|
+
expect(item("CLI terminal mode").getAttribute("aria-checked")).toBe("true");
|
|
367
|
+
await choose("New terminal");
|
|
368
|
+
expect(onNewTerminal).toHaveBeenCalledOnce();
|
|
369
|
+
await open();
|
|
370
|
+
await choose("CLI terminal mode");
|
|
371
|
+
expect(onChange).toHaveBeenLastCalledWith(false);
|
|
372
|
+
expect(useOrg).not.toHaveBeenCalled();
|
|
373
|
+
});
|
|
388
374
|
|
|
389
|
-
|
|
390
|
-
|
|
391
|
-
|
|
392
|
-
|
|
393
|
-
|
|
394
|
-
|
|
395
|
-
}),
|
|
396
|
-
);
|
|
397
|
-
vi.stubGlobal("fetch", fetch);
|
|
398
|
-
await mount();
|
|
399
|
-
await open(trigger, false);
|
|
400
|
-
const form = await uploadSkill();
|
|
401
|
-
expect(form).not.toBeNull();
|
|
402
|
-
expect(form.textContent).toContain(
|
|
403
|
-
"Review the content from Test Skill.md before saving.",
|
|
404
|
-
);
|
|
405
|
-
expect(form.textContent).toContain("skills/test-skill/SKILL.md");
|
|
406
|
-
expect(form.querySelector("textarea")?.value).toBe(
|
|
407
|
-
"# Test skill\nDo the test.",
|
|
408
|
-
);
|
|
409
|
-
await act(async () => {
|
|
410
|
-
form.dispatchEvent(
|
|
411
|
-
new Event("submit", { bubbles: true, cancelable: true }),
|
|
412
|
-
);
|
|
413
|
-
form.dispatchEvent(
|
|
414
|
-
new Event("submit", { bubbles: true, cancelable: true }),
|
|
415
|
-
);
|
|
416
|
-
await settle();
|
|
417
|
-
});
|
|
418
|
-
expect(fetch).toHaveBeenCalledExactlyOnceWith(
|
|
419
|
-
"/test-app/_agent-native/resources",
|
|
420
|
-
expect.objectContaining({
|
|
421
|
-
method: "POST",
|
|
422
|
-
signal: expect.any(AbortSignal),
|
|
423
|
-
body: JSON.stringify({
|
|
424
|
-
path: "skills/test-skill/SKILL.md",
|
|
425
|
-
content: "# Test skill\nDo the test.",
|
|
426
|
-
mimeType: "text/markdown",
|
|
427
|
-
shared: false,
|
|
428
|
-
}),
|
|
375
|
+
it("+ keeps the skill filename, review, save payload, and duplicate-save lock", async () => {
|
|
376
|
+
let resolve!: (response: Response) => void;
|
|
377
|
+
const fetch = vi.fn(
|
|
378
|
+
() =>
|
|
379
|
+
new Promise<Response>((done) => {
|
|
380
|
+
resolve = done;
|
|
429
381
|
}),
|
|
382
|
+
);
|
|
383
|
+
vi.stubGlobal("fetch", fetch);
|
|
384
|
+
await mount();
|
|
385
|
+
await open();
|
|
386
|
+
const form = await uploadSkill();
|
|
387
|
+
expect(form).not.toBeNull();
|
|
388
|
+
expect(form.textContent).toContain(
|
|
389
|
+
"Review the content from Test Skill.md before saving.",
|
|
390
|
+
);
|
|
391
|
+
expect(form.textContent).toContain("skills/test-skill/SKILL.md");
|
|
392
|
+
expect(form.querySelector("textarea")?.value).toBe(
|
|
393
|
+
"# Test skill\nDo the test.",
|
|
394
|
+
);
|
|
395
|
+
await act(async () => {
|
|
396
|
+
form.dispatchEvent(
|
|
397
|
+
new Event("submit", { bubbles: true, cancelable: true }),
|
|
430
398
|
);
|
|
431
|
-
|
|
432
|
-
|
|
433
|
-
await settle();
|
|
434
|
-
});
|
|
435
|
-
expect(form.querySelector('[role="status"]')?.textContent).toContain(
|
|
436
|
-
'Skill "Test Skill.md" added',
|
|
399
|
+
form.dispatchEvent(
|
|
400
|
+
new Event("submit", { bubbles: true, cancelable: true }),
|
|
437
401
|
);
|
|
402
|
+
await settle();
|
|
438
403
|
});
|
|
439
|
-
|
|
404
|
+
expect(fetch).toHaveBeenCalledExactlyOnceWith(
|
|
405
|
+
"/test-app/_agent-native/resources",
|
|
406
|
+
expect.objectContaining({
|
|
407
|
+
method: "POST",
|
|
408
|
+
signal: expect.any(AbortSignal),
|
|
409
|
+
body: JSON.stringify({
|
|
410
|
+
path: "skills/test-skill/SKILL.md",
|
|
411
|
+
content: "# Test skill\nDo the test.",
|
|
412
|
+
mimeType: "text/markdown",
|
|
413
|
+
shared: false,
|
|
414
|
+
}),
|
|
415
|
+
}),
|
|
416
|
+
);
|
|
417
|
+
await act(async () => {
|
|
418
|
+
resolve(new Response("{}"));
|
|
419
|
+
await settle();
|
|
420
|
+
});
|
|
421
|
+
expect(form.querySelector('[role="status"]')?.textContent).toContain(
|
|
422
|
+
'Skill "Test Skill.md" added',
|
|
423
|
+
);
|
|
424
|
+
});
|
|
440
425
|
|
|
441
426
|
it("keeps explicit hidden host menus lightweight and preserves the host action", async () => {
|
|
442
427
|
const onSelect = vi.fn();
|
|
@@ -444,7 +429,7 @@ describe("shared default action preservation", () => {
|
|
|
444
429
|
plusMenuMode: "hidden",
|
|
445
430
|
contextMenuItems: [{ id: "host", label: "Host source", onSelect }],
|
|
446
431
|
});
|
|
447
|
-
await open(
|
|
432
|
+
await open(true);
|
|
448
433
|
expect(labels()).toEqual(["Upload File", "Add context", "Host source"]);
|
|
449
434
|
await choose("Host source");
|
|
450
435
|
expect(onSelect).toHaveBeenCalledOnce();
|
|
@@ -476,7 +461,7 @@ describe("shared default action preservation", () => {
|
|
|
476
461
|
root.render(<RawHost />);
|
|
477
462
|
await settle();
|
|
478
463
|
});
|
|
479
|
-
await open(
|
|
464
|
+
await open();
|
|
480
465
|
await choose("Schedule Task");
|
|
481
466
|
await act(async () => {
|
|
482
467
|
expect(await composerRef.current!.submitWithText("Draft")).toBe(true);
|
|
@@ -572,9 +557,9 @@ describe("shared default action preservation", () => {
|
|
|
572
557
|
root.render(<Host />);
|
|
573
558
|
await settle();
|
|
574
559
|
});
|
|
575
|
-
await open(
|
|
560
|
+
await open(true);
|
|
576
561
|
await choose("Attach integration");
|
|
577
|
-
await open(
|
|
562
|
+
await open();
|
|
578
563
|
await choose("Schedule Task");
|
|
579
564
|
const file = new File(["test document"], "reference.pdf", {
|
|
580
565
|
type: "application/pdf",
|
|
@@ -640,7 +625,7 @@ describe("shared default action preservation", () => {
|
|
|
640
625
|
|
|
641
626
|
it("retains the fallback MCP dialog, role gates, and existing creation adapter", async () => {
|
|
642
627
|
await mount();
|
|
643
|
-
await open(
|
|
628
|
+
await open();
|
|
644
629
|
await choose("Integrations");
|
|
645
630
|
expect(dialogProps).toHaveBeenLastCalledWith(
|
|
646
631
|
expect.objectContaining({
|
|
@@ -676,7 +661,7 @@ describe("shared default action preservation", () => {
|
|
|
676
661
|
{ id: "host-source", label: "Host source", onSelect: vi.fn() },
|
|
677
662
|
],
|
|
678
663
|
});
|
|
679
|
-
await open(
|
|
664
|
+
await open();
|
|
680
665
|
expect(labels()).toContain("Schedule Task");
|
|
681
666
|
expect(labels()).toContain("Create Automation");
|
|
682
667
|
expect(labels()).toContain("Create Skill");
|
|
@@ -389,7 +389,10 @@ export const MentionPopover = forwardRef<
|
|
|
389
389
|
{item.label}
|
|
390
390
|
</span>
|
|
391
391
|
{item.description && (
|
|
392
|
-
<span
|
|
392
|
+
<span
|
|
393
|
+
data-mention-description
|
|
394
|
+
className="ms-auto max-w-[45%] shrink-0 truncate text-[14px] text-muted-foreground"
|
|
395
|
+
>
|
|
393
396
|
{item.description}
|
|
394
397
|
</span>
|
|
395
398
|
)}
|
|
@@ -431,7 +434,10 @@ export const MentionPopover = forwardRef<
|
|
|
431
434
|
/{cmd.name}
|
|
432
435
|
</span>
|
|
433
436
|
{cmd.description && (
|
|
434
|
-
<span
|
|
437
|
+
<span
|
|
438
|
+
data-mention-description
|
|
439
|
+
className="ms-auto max-w-[60%] shrink-0 truncate text-[13px] leading-4 text-muted-foreground"
|
|
440
|
+
>
|
|
435
441
|
{cmd.description}
|
|
436
442
|
</span>
|
|
437
443
|
)}
|
|
@@ -472,7 +478,10 @@ export const MentionPopover = forwardRef<
|
|
|
472
478
|
{skill.name}
|
|
473
479
|
</span>
|
|
474
480
|
{skill.description && (
|
|
475
|
-
<span
|
|
481
|
+
<span
|
|
482
|
+
data-mention-description
|
|
483
|
+
className="ms-auto max-w-[60%] shrink-0 truncate text-[13px] leading-4 text-muted-foreground"
|
|
484
|
+
>
|
|
476
485
|
{skill.description}
|
|
477
486
|
</span>
|
|
478
487
|
)}
|