@agent-native/core 0.133.1 → 0.133.2
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/corpus/README.md +1 -1
- package/corpus/core/CHANGELOG.md +6 -0
- package/corpus/core/package.json +1 -1
- package/corpus/core/src/a2a/client.ts +22 -5
- package/corpus/core/src/integrations/webhook-handler.ts +7 -0
- package/corpus/core/src/scripts/call-agent.ts +29 -2
- package/corpus/templates/content/app/components/editor/database/sidebar.tsx +1 -34
- package/corpus/templates/content/app/components/sidebar/DocumentSidebar.tsx +77 -3
- package/corpus/templates/content/app/components/sidebar/DocumentTreeItem.tsx +4 -211
- package/corpus/templates/content/changelog/2026-07-30-deleting-a-page-no-longer-leaves-the-content-sidebar-unrespo.md +6 -0
- package/corpus/templates/content/e2e/playwright.config.ts +2 -1
- package/dist/a2a/client.d.ts +9 -1
- package/dist/a2a/client.d.ts.map +1 -1
- package/dist/a2a/client.js +12 -4
- package/dist/a2a/client.js.map +1 -1
- package/dist/collab/routes.d.ts +1 -1
- package/dist/integrations/webhook-handler.d.ts.map +1 -1
- package/dist/integrations/webhook-handler.js +3 -0
- package/dist/integrations/webhook-handler.js.map +1 -1
- package/dist/notifications/routes.d.ts +1 -1
- package/dist/resources/handlers.d.ts +1 -1
- package/dist/scripts/call-agent.d.ts.map +1 -1
- package/dist/scripts/call-agent.js +24 -2
- package/dist/scripts/call-agent.js.map +1 -1
- package/dist/server/agent-engine-api-key-route.d.ts +1 -1
- package/package.json +1 -1
- package/src/a2a/client.ts +22 -5
- package/src/integrations/webhook-handler.ts +7 -0
- package/src/scripts/call-agent.ts +29 -2
package/corpus/README.md
CHANGED
package/corpus/core/CHANGELOG.md
CHANGED
package/corpus/core/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@agent-native/core",
|
|
3
|
-
"version": "0.133.
|
|
3
|
+
"version": "0.133.2",
|
|
4
4
|
"description": "Framework for agent-native application development — where AI agents and UI share SQL state, actions, and context",
|
|
5
5
|
"homepage": "https://github.com/BuilderIO/agent-native#readme",
|
|
6
6
|
"bugs": {
|
|
@@ -536,8 +536,14 @@ export class A2AClient {
|
|
|
536
536
|
metadata?: Record<string, unknown>;
|
|
537
537
|
idempotencyKey?: string;
|
|
538
538
|
approvedActions?: A2AApprovedAction[];
|
|
539
|
-
/**
|
|
539
|
+
/** Time to wait after submission for completion. Default 5 min. */
|
|
540
540
|
timeoutMs?: number;
|
|
541
|
+
/**
|
|
542
|
+
* Optional separate budget for agent-card discovery and the initial
|
|
543
|
+
* async message submission. When omitted, timeoutMs remains the shared
|
|
544
|
+
* end-to-end deadline for backwards compatibility.
|
|
545
|
+
*/
|
|
546
|
+
submissionTimeoutMs?: number;
|
|
541
547
|
/** Poll interval. Default 2s. */
|
|
542
548
|
pollIntervalMs?: number;
|
|
543
549
|
/** Called with each polled task — useful for surfacing progress. */
|
|
@@ -545,7 +551,8 @@ export class A2AClient {
|
|
|
545
551
|
},
|
|
546
552
|
): Promise<Task> {
|
|
547
553
|
const timeoutMs = opts?.timeoutMs ?? 5 * 60_000;
|
|
548
|
-
const
|
|
554
|
+
const submissionDeadlineMs =
|
|
555
|
+
Date.now() + (opts?.submissionTimeoutMs ?? timeoutMs);
|
|
549
556
|
const submitted = await this.send(message, {
|
|
550
557
|
contextId: opts?.contextId,
|
|
551
558
|
metadata: opts?.metadata,
|
|
@@ -556,12 +563,19 @@ export class A2AClient {
|
|
|
556
563
|
async: true,
|
|
557
564
|
requestTimeoutMs: Math.min(
|
|
558
565
|
this.requestTimeoutMs ?? DEFAULT_A2A_POLL_REQUEST_TIMEOUT_MS,
|
|
559
|
-
Math.max(1,
|
|
566
|
+
Math.max(1, submissionDeadlineMs - Date.now()),
|
|
560
567
|
),
|
|
561
|
-
deadlineMs,
|
|
568
|
+
deadlineMs: submissionDeadlineMs,
|
|
562
569
|
});
|
|
563
570
|
|
|
564
|
-
|
|
571
|
+
const pollingDeadlineMs = opts?.submissionTimeoutMs
|
|
572
|
+
? Date.now() + timeoutMs
|
|
573
|
+
: submissionDeadlineMs;
|
|
574
|
+
return this.pollTask(submitted, {
|
|
575
|
+
...opts,
|
|
576
|
+
timeoutMs,
|
|
577
|
+
deadlineMs: pollingDeadlineMs,
|
|
578
|
+
});
|
|
565
579
|
}
|
|
566
580
|
|
|
567
581
|
/**
|
|
@@ -1017,6 +1031,8 @@ export async function callAgent(
|
|
|
1017
1031
|
async?: boolean;
|
|
1018
1032
|
/** Total time to wait for the polled task (default 5 min). */
|
|
1019
1033
|
timeoutMs?: number;
|
|
1034
|
+
/** Separate budget for discovery and initial async submission. */
|
|
1035
|
+
submissionTimeoutMs?: number;
|
|
1020
1036
|
/**
|
|
1021
1037
|
* Existing async task to keep polling. When set, no new message is sent.
|
|
1022
1038
|
* This prevents a caller-side timeout from duplicating downstream work.
|
|
@@ -1092,6 +1108,7 @@ export async function callAgent(
|
|
|
1092
1108
|
? { approvedActions: opts.approvedActions }
|
|
1093
1109
|
: {}),
|
|
1094
1110
|
timeoutMs: opts?.timeoutMs,
|
|
1111
|
+
submissionTimeoutMs: opts?.submissionTimeoutMs,
|
|
1095
1112
|
pollIntervalMs: opts?.pollIntervalMs,
|
|
1096
1113
|
onUpdate: opts?.onUpdate,
|
|
1097
1114
|
});
|
|
@@ -2274,6 +2274,13 @@ function isQueuedA2AContinuationDeferral(text: string): boolean {
|
|
|
2274
2274
|
if (!normalized) return true;
|
|
2275
2275
|
if (hasSubstantiveA2APartialAnswer(text)) return false;
|
|
2276
2276
|
if (normalized.includes(A2A_CONTINUATION_QUEUED_MARKER)) return true;
|
|
2277
|
+
if (
|
|
2278
|
+
/\bwill\b[^.!?]{0,160}\bpost\b[^.!?]{0,160}\b(?:thread|result|link|content id)\b/i.test(
|
|
2279
|
+
normalized,
|
|
2280
|
+
)
|
|
2281
|
+
) {
|
|
2282
|
+
return true;
|
|
2283
|
+
}
|
|
2277
2284
|
return /\b(?:still (?:working|processing)|is working on|taking longer than expected|will (?:post|update|surface|show up)|(?:it'?ll|it will|the result will|the final result will) (?:post|be posted|update|be updated|surface|show up)|will be (?:posted|updated|sent|shared)|final result when it finishes|while you wait|as soon as (?:it|it'?s|it is|the result|the artifact) (?:comes back|is ready|ready)|hang tight|relay from the .* agent)\b/i.test(
|
|
2278
2285
|
normalized,
|
|
2279
2286
|
);
|
|
@@ -38,6 +38,7 @@ import { track } from "../tracking/registry.js";
|
|
|
38
38
|
|
|
39
39
|
const DEFAULT_SERVERLESS_INTEGRATION_A2A_TIMEOUT_MS = 18_000;
|
|
40
40
|
const NETLIFY_INTEGRATION_A2A_TIMEOUT_MS = 2_000;
|
|
41
|
+
const NETLIFY_INTEGRATION_A2A_SUBMISSION_TIMEOUT_MS = 15_000;
|
|
41
42
|
const INTEGRATION_A2A_TOKEN_TTL = "30m";
|
|
42
43
|
const A2A_INVOCATION_EVENT = "$a2a_invocation";
|
|
43
44
|
|
|
@@ -167,13 +168,32 @@ function parseTimeoutMs(value: string | undefined): number | undefined {
|
|
|
167
168
|
return Math.floor(parsed);
|
|
168
169
|
}
|
|
169
170
|
|
|
171
|
+
function hasExplicitNonHostedNetlifyOverride(): boolean {
|
|
172
|
+
return (
|
|
173
|
+
process.env.NETLIFY_LOCAL === "true" || process.env.NETLIFY === "false"
|
|
174
|
+
);
|
|
175
|
+
}
|
|
176
|
+
|
|
177
|
+
function isNetlifyHostedRuntimeForIntegrationCall(): boolean {
|
|
178
|
+
if (hasExplicitNonHostedNetlifyOverride()) return false;
|
|
179
|
+
if (process.env.NETLIFY && process.env.NETLIFY !== "false") return true;
|
|
180
|
+
|
|
181
|
+
// NETLIFY is a build-time marker, while deployed Netlify Functions expose
|
|
182
|
+
// SITE_ID at runtime. Recognize the same runtime-only marker used by the
|
|
183
|
+
// durable background and run-manager gates so the integration caller hands
|
|
184
|
+
// slow A2A work to durable delivery before its foreground budget expires.
|
|
185
|
+
return Boolean(process.env.SITE_ID); // guard:allow-env-credential -- Netlify's read-only public site identifier is a runtime host marker, not a user credential.
|
|
186
|
+
}
|
|
187
|
+
|
|
170
188
|
function isServerlessHost(): boolean {
|
|
189
|
+
if (hasExplicitNonHostedNetlifyOverride()) return false;
|
|
190
|
+
|
|
171
191
|
// Detection mirrors db/migrations.ts:297-301. On Cloudflare Workers/Pages,
|
|
172
192
|
// `process.env` is shimmed and CF_PAGES isn't reliably populated at runtime —
|
|
173
193
|
// the canonical signal is the `__cf_env`/`__env__` global injected by the
|
|
174
194
|
// Cloudflare runtime adapter.
|
|
175
195
|
return (
|
|
176
|
-
|
|
196
|
+
isNetlifyHostedRuntimeForIntegrationCall() ||
|
|
177
197
|
!!process.env.AWS_LAMBDA_FUNCTION_NAME ||
|
|
178
198
|
!!process.env.VERCEL ||
|
|
179
199
|
"__cf_env" in globalThis ||
|
|
@@ -193,7 +213,9 @@ function getIntegrationCallTimeoutMs(): number | undefined {
|
|
|
193
213
|
// calls very short so multi-agent integration requests queue downstream
|
|
194
214
|
// continuations quickly instead of spending the parent Slack/email processor
|
|
195
215
|
// budget waiting on separately deployed apps one-by-one.
|
|
196
|
-
if (
|
|
216
|
+
if (isNetlifyHostedRuntimeForIntegrationCall()) {
|
|
217
|
+
return NETLIFY_INTEGRATION_A2A_TIMEOUT_MS;
|
|
218
|
+
}
|
|
197
219
|
|
|
198
220
|
return DEFAULT_SERVERLESS_INTEGRATION_A2A_TIMEOUT_MS;
|
|
199
221
|
}
|
|
@@ -676,6 +698,10 @@ export async function run(
|
|
|
676
698
|
// Docker can wait for slow-but-valid answers; integration processors
|
|
677
699
|
// still need to finish before their current function execution dies.
|
|
678
700
|
const callTimeoutMs = getIntegrationCallTimeoutMs();
|
|
701
|
+
const submissionTimeoutMs =
|
|
702
|
+
callTimeoutMs && isNetlifyHostedRuntimeForIntegrationCall()
|
|
703
|
+
? NETLIFY_INTEGRATION_A2A_SUBMISSION_TIMEOUT_MS
|
|
704
|
+
: undefined;
|
|
679
705
|
responseText = await callAgent(agent.url, messageWithHint, {
|
|
680
706
|
apiKey,
|
|
681
707
|
userEmail: callerEmail,
|
|
@@ -692,6 +718,7 @@ export async function run(
|
|
|
692
718
|
...(callTimeoutMs
|
|
693
719
|
? {
|
|
694
720
|
timeoutMs: callTimeoutMs,
|
|
721
|
+
...(submissionTimeoutMs ? { submissionTimeoutMs } : {}),
|
|
695
722
|
}
|
|
696
723
|
: {}),
|
|
697
724
|
});
|
|
@@ -21,16 +21,6 @@ import {
|
|
|
21
21
|
import { useEffect, useState, type MouseEvent, type ReactNode } from "react";
|
|
22
22
|
import { Link } from "react-router";
|
|
23
23
|
|
|
24
|
-
import {
|
|
25
|
-
AlertDialog,
|
|
26
|
-
AlertDialogAction,
|
|
27
|
-
AlertDialogCancel,
|
|
28
|
-
AlertDialogContent,
|
|
29
|
-
AlertDialogDescription,
|
|
30
|
-
AlertDialogFooter,
|
|
31
|
-
AlertDialogHeader,
|
|
32
|
-
AlertDialogTitle,
|
|
33
|
-
} from "@/components/ui/alert-dialog";
|
|
34
24
|
import { Button } from "@/components/ui/button";
|
|
35
25
|
import {
|
|
36
26
|
Collapsible,
|
|
@@ -727,7 +717,6 @@ function DatabaseSidebarRow({
|
|
|
727
717
|
};
|
|
728
718
|
}) {
|
|
729
719
|
const t = useT();
|
|
730
|
-
const [deleteDialogOpen, setDeleteDialogOpen] = useState(false);
|
|
731
720
|
const canEdit = item.document.canEdit !== false;
|
|
732
721
|
const canManage =
|
|
733
722
|
item.document.canManage === true ||
|
|
@@ -858,7 +847,7 @@ function DatabaseSidebarRow({
|
|
|
858
847
|
{canManage && onDeleteItem ? (
|
|
859
848
|
<DropdownMenuItem
|
|
860
849
|
className="text-destructive focus:text-destructive"
|
|
861
|
-
onSelect={() =>
|
|
850
|
+
onSelect={() => onDeleteItem(item)}
|
|
862
851
|
>
|
|
863
852
|
<IconTrash className="me-2 size-4" />
|
|
864
853
|
{t("database.delete")}
|
|
@@ -903,28 +892,6 @@ function DatabaseSidebarRow({
|
|
|
903
892
|
</div>
|
|
904
893
|
)}
|
|
905
894
|
</div>
|
|
906
|
-
|
|
907
|
-
<AlertDialog open={deleteDialogOpen} onOpenChange={setDeleteDialogOpen}>
|
|
908
|
-
<AlertDialogContent>
|
|
909
|
-
<AlertDialogHeader>
|
|
910
|
-
<AlertDialogTitle>
|
|
911
|
-
{t("sidebar.deletePageQuestion")}
|
|
912
|
-
</AlertDialogTitle>
|
|
913
|
-
<AlertDialogDescription>
|
|
914
|
-
{t("sidebar.deletePageDescription", { title })}
|
|
915
|
-
</AlertDialogDescription>
|
|
916
|
-
</AlertDialogHeader>
|
|
917
|
-
<AlertDialogFooter>
|
|
918
|
-
<AlertDialogCancel>{t("comments.cancel")}</AlertDialogCancel>
|
|
919
|
-
<AlertDialogAction
|
|
920
|
-
className="bg-destructive text-destructive-foreground hover:bg-destructive/90"
|
|
921
|
-
onClick={() => onDeleteItem?.(item)}
|
|
922
|
-
>
|
|
923
|
-
{t("database.delete")}
|
|
924
|
-
</AlertDialogAction>
|
|
925
|
-
</AlertDialogFooter>
|
|
926
|
-
</AlertDialogContent>
|
|
927
|
-
</AlertDialog>
|
|
928
895
|
</>
|
|
929
896
|
);
|
|
930
897
|
}
|
|
@@ -222,6 +222,18 @@ const SIDEBAR_SECTION_COLLAPSE_STORAGE_KEY =
|
|
|
222
222
|
const TRASH_COLLAPSED_DEFAULT_MIGRATION_KEY =
|
|
223
223
|
"content-sidebar-trash-collapsed-default-v2";
|
|
224
224
|
const CONTENT_SIDEBAR_STATE_VERSION = 1 as const;
|
|
225
|
+
|
|
226
|
+
function afterBodyPointerUnlock(callback: () => void) {
|
|
227
|
+
const run = () => {
|
|
228
|
+
if (document.body.style.pointerEvents === "none") {
|
|
229
|
+
window.requestAnimationFrame(run);
|
|
230
|
+
return;
|
|
231
|
+
}
|
|
232
|
+
callback();
|
|
233
|
+
};
|
|
234
|
+
window.requestAnimationFrame(run);
|
|
235
|
+
}
|
|
236
|
+
|
|
225
237
|
interface ContentSidebarStateSnapshot {
|
|
226
238
|
version: typeof CONTENT_SIDEBAR_STATE_VERSION;
|
|
227
239
|
expandedWorkspaceIds: string[];
|
|
@@ -906,6 +918,11 @@ export function DocumentSidebar({
|
|
|
906
918
|
}, [setStoredCollapsedSections]);
|
|
907
919
|
const [removeLocalFilesDialogOpen, setRemoveLocalFilesDialogOpen] =
|
|
908
920
|
useState(false);
|
|
921
|
+
const [pendingDelete, setPendingDelete] = useState<{
|
|
922
|
+
id: string;
|
|
923
|
+
title: string;
|
|
924
|
+
} | null>(null);
|
|
925
|
+
const confirmedDeleteIdRef = useRef<string | null>(null);
|
|
909
926
|
const settingsActive = location.pathname.startsWith("/settings");
|
|
910
927
|
const sensors = useSensors(
|
|
911
928
|
useSensor(PointerSensor, {
|
|
@@ -1258,6 +1275,12 @@ export function DocumentSidebar({
|
|
|
1258
1275
|
],
|
|
1259
1276
|
);
|
|
1260
1277
|
|
|
1278
|
+
const requestDelete = useCallback((id: string, title: string) => {
|
|
1279
|
+
afterBodyPointerUnlock(() => {
|
|
1280
|
+
setPendingDelete({ id, title });
|
|
1281
|
+
});
|
|
1282
|
+
}, []);
|
|
1283
|
+
|
|
1261
1284
|
const handleReorderPage = useCallback(
|
|
1262
1285
|
async (id: string, overId: string) => {
|
|
1263
1286
|
if (id === overId) return;
|
|
@@ -1520,7 +1543,7 @@ export function DocumentSidebar({
|
|
|
1520
1543
|
}}
|
|
1521
1544
|
onCreateChildPage={(parentId) => handleCreatePage(parentId)}
|
|
1522
1545
|
onCreateChildDatabase={(parentId) => handleCreateDatabase(parentId)}
|
|
1523
|
-
onDelete={
|
|
1546
|
+
onDelete={requestDelete}
|
|
1524
1547
|
onToggleFavorite={handleToggleFavorite}
|
|
1525
1548
|
/>
|
|
1526
1549
|
))}
|
|
@@ -1832,7 +1855,12 @@ export function DocumentSidebar({
|
|
|
1832
1855
|
onCreateChildDatabase={(nextSpace, item) =>
|
|
1833
1856
|
void handleCreateDatabase(item.document.id, nextSpace.id)
|
|
1834
1857
|
}
|
|
1835
|
-
onDeleteItem={(item) =>
|
|
1858
|
+
onDeleteItem={(item) =>
|
|
1859
|
+
requestDelete(
|
|
1860
|
+
item.document.id,
|
|
1861
|
+
item.document.title || t("sidebar.untitled"),
|
|
1862
|
+
)
|
|
1863
|
+
}
|
|
1836
1864
|
onToggleFavorite={(item) =>
|
|
1837
1865
|
handleToggleFavorite(item.document.id, !item.document.isFavorite)
|
|
1838
1866
|
}
|
|
@@ -2348,7 +2376,10 @@ export function DocumentSidebar({
|
|
|
2348
2376
|
void handleCreateDatabase(item.document.id)
|
|
2349
2377
|
}
|
|
2350
2378
|
onDeleteItem={(item) =>
|
|
2351
|
-
|
|
2379
|
+
requestDelete(
|
|
2380
|
+
item.document.id,
|
|
2381
|
+
item.document.title || t("sidebar.untitled"),
|
|
2382
|
+
)
|
|
2352
2383
|
}
|
|
2353
2384
|
onToggleFavorite={(item) =>
|
|
2354
2385
|
handleToggleFavorite(item.document.id, false)
|
|
@@ -2416,6 +2447,49 @@ export function DocumentSidebar({
|
|
|
2416
2447
|
onMouseDown={handleMouseDown}
|
|
2417
2448
|
/>
|
|
2418
2449
|
)}
|
|
2450
|
+
<AlertDialog
|
|
2451
|
+
open={pendingDelete !== null}
|
|
2452
|
+
onOpenChange={(open) => {
|
|
2453
|
+
if (open) return;
|
|
2454
|
+
setPendingDelete(null);
|
|
2455
|
+
const confirmedDeleteId = confirmedDeleteIdRef.current;
|
|
2456
|
+
confirmedDeleteIdRef.current = null;
|
|
2457
|
+
if (confirmedDeleteId) {
|
|
2458
|
+
afterBodyPointerUnlock(() => {
|
|
2459
|
+
void handleDelete(confirmedDeleteId);
|
|
2460
|
+
});
|
|
2461
|
+
}
|
|
2462
|
+
}}
|
|
2463
|
+
>
|
|
2464
|
+
<AlertDialogContent>
|
|
2465
|
+
<AlertDialogHeader>
|
|
2466
|
+
<AlertDialogTitle>
|
|
2467
|
+
{t("sidebar.deletePageQuestion")}
|
|
2468
|
+
</AlertDialogTitle>
|
|
2469
|
+
<AlertDialogDescription>
|
|
2470
|
+
{pendingDelete
|
|
2471
|
+
? t("sidebar.deletePageDescription", {
|
|
2472
|
+
title: pendingDelete.title,
|
|
2473
|
+
})
|
|
2474
|
+
: null}
|
|
2475
|
+
</AlertDialogDescription>
|
|
2476
|
+
</AlertDialogHeader>
|
|
2477
|
+
<AlertDialogFooter>
|
|
2478
|
+
<AlertDialogCancel>{t("comments.cancel")}</AlertDialogCancel>
|
|
2479
|
+
<AlertDialogAction
|
|
2480
|
+
className="bg-destructive text-destructive-foreground hover:bg-destructive/90"
|
|
2481
|
+
disabled={
|
|
2482
|
+
deleteDocument.isPending || deleteContentDatabase.isPending
|
|
2483
|
+
}
|
|
2484
|
+
onClick={() => {
|
|
2485
|
+
confirmedDeleteIdRef.current = pendingDelete?.id ?? null;
|
|
2486
|
+
}}
|
|
2487
|
+
>
|
|
2488
|
+
{t("database.delete")}
|
|
2489
|
+
</AlertDialogAction>
|
|
2490
|
+
</AlertDialogFooter>
|
|
2491
|
+
</AlertDialogContent>
|
|
2492
|
+
</AlertDialog>
|
|
2419
2493
|
<AlertDialog
|
|
2420
2494
|
open={removeLocalFilesDialogOpen}
|
|
2421
2495
|
onOpenChange={setRemoveLocalFilesDialogOpen}
|
|
@@ -6,7 +6,7 @@ import {
|
|
|
6
6
|
verticalListSortingStrategy,
|
|
7
7
|
} from "@dnd-kit/sortable";
|
|
8
8
|
import { CSS } from "@dnd-kit/utilities";
|
|
9
|
-
import type {
|
|
9
|
+
import type { DocumentTreeNode } from "@shared/api";
|
|
10
10
|
import {
|
|
11
11
|
IconChevronRight,
|
|
12
12
|
IconDatabase,
|
|
@@ -19,16 +19,6 @@ import {
|
|
|
19
19
|
} from "@tabler/icons-react";
|
|
20
20
|
import { useState } from "react";
|
|
21
21
|
|
|
22
|
-
import {
|
|
23
|
-
AlertDialog,
|
|
24
|
-
AlertDialogAction,
|
|
25
|
-
AlertDialogCancel,
|
|
26
|
-
AlertDialogContent,
|
|
27
|
-
AlertDialogDescription,
|
|
28
|
-
AlertDialogFooter,
|
|
29
|
-
AlertDialogHeader,
|
|
30
|
-
AlertDialogTitle,
|
|
31
|
-
} from "@/components/ui/alert-dialog";
|
|
32
22
|
import {
|
|
33
23
|
DropdownMenu,
|
|
34
24
|
DropdownMenuContent,
|
|
@@ -53,7 +43,7 @@ interface DocumentTreeItemProps {
|
|
|
53
43
|
onSelect: (id: string) => void;
|
|
54
44
|
onCreateChildPage: (parentId: string) => void;
|
|
55
45
|
onCreateChildDatabase: (parentId: string) => void;
|
|
56
|
-
onDelete: (id: string) => void;
|
|
46
|
+
onDelete: (id: string, title: string) => void;
|
|
57
47
|
onToggleFavorite: (id: string, isFavorite: boolean) => void;
|
|
58
48
|
}
|
|
59
49
|
|
|
@@ -88,178 +78,6 @@ export function DocumentSidebarIcon({
|
|
|
88
78
|
return <IconFileText size={14} className="text-muted-foreground" />;
|
|
89
79
|
}
|
|
90
80
|
|
|
91
|
-
export function FavoriteDocumentItem({
|
|
92
|
-
document,
|
|
93
|
-
active,
|
|
94
|
-
sidebarWidth,
|
|
95
|
-
onSelect,
|
|
96
|
-
onCreateChildPage,
|
|
97
|
-
onCreateChildDatabase,
|
|
98
|
-
onRemoveFavorite,
|
|
99
|
-
onDelete,
|
|
100
|
-
}: {
|
|
101
|
-
document: Document;
|
|
102
|
-
active: boolean;
|
|
103
|
-
sidebarWidth?: number;
|
|
104
|
-
onSelect: () => void;
|
|
105
|
-
onCreateChildPage: () => void;
|
|
106
|
-
onCreateChildDatabase: () => void;
|
|
107
|
-
onRemoveFavorite: () => void;
|
|
108
|
-
onDelete: () => void;
|
|
109
|
-
}) {
|
|
110
|
-
const t = useT();
|
|
111
|
-
const [deleteDialogOpen, setDeleteDialogOpen] = useState(false);
|
|
112
|
-
const canEdit = document.canEdit !== false;
|
|
113
|
-
const canManage =
|
|
114
|
-
document.canManage === true ||
|
|
115
|
-
document.accessRole === "owner" ||
|
|
116
|
-
document.accessRole === "admin";
|
|
117
|
-
const canCreateChild = canEdit && document.source?.mode !== "local-files";
|
|
118
|
-
const title = document.title || t("sidebar.untitled");
|
|
119
|
-
|
|
120
|
-
return (
|
|
121
|
-
<div
|
|
122
|
-
className={cn(
|
|
123
|
-
"group relative flex min-w-0 cursor-pointer items-center gap-1.5 rounded-md py-[5px] pe-2 text-sm",
|
|
124
|
-
active
|
|
125
|
-
? "font-semibold text-foreground"
|
|
126
|
-
: "text-muted-foreground hover:bg-accent hover:text-foreground",
|
|
127
|
-
)}
|
|
128
|
-
style={{
|
|
129
|
-
paddingInlineStart: "26px",
|
|
130
|
-
width:
|
|
131
|
-
sidebarWidth === undefined
|
|
132
|
-
? undefined
|
|
133
|
-
: `${Math.max(0, sidebarWidth)}px`,
|
|
134
|
-
}}
|
|
135
|
-
aria-label={title}
|
|
136
|
-
>
|
|
137
|
-
<button
|
|
138
|
-
type="button"
|
|
139
|
-
className="absolute inset-0 rounded-md focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring"
|
|
140
|
-
aria-label={`Open ${title}`}
|
|
141
|
-
onClick={onSelect}
|
|
142
|
-
/>
|
|
143
|
-
<span className="pointer-events-none relative flex h-5 w-5 shrink-0 items-center justify-center text-center">
|
|
144
|
-
<DocumentSidebarIcon document={document} />
|
|
145
|
-
</span>
|
|
146
|
-
<span className="pointer-events-none relative min-w-0 flex-1 truncate pe-12">
|
|
147
|
-
{title}
|
|
148
|
-
</span>
|
|
149
|
-
<div
|
|
150
|
-
className={cn(
|
|
151
|
-
"pointer-events-none absolute right-1 top-1/2 z-10 flex -translate-y-1/2 items-center gap-0.5 rounded-md bg-accent px-0.5 opacity-0 group-hover:pointer-events-auto group-hover:opacity-100 group-focus-within:pointer-events-auto group-focus-within:opacity-100",
|
|
152
|
-
active && "text-accent-foreground",
|
|
153
|
-
)}
|
|
154
|
-
onPointerDown={(event) => event.stopPropagation()}
|
|
155
|
-
onClick={(event) => event.stopPropagation()}
|
|
156
|
-
>
|
|
157
|
-
{(canEdit || canManage) && (
|
|
158
|
-
<DropdownMenu>
|
|
159
|
-
<DropdownMenuTrigger asChild>
|
|
160
|
-
<button
|
|
161
|
-
type="button"
|
|
162
|
-
className="flex h-6 w-6 items-center justify-center rounded hover:bg-background focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring"
|
|
163
|
-
aria-label={`More actions for ${title}`}
|
|
164
|
-
onClick={(event) => event.stopPropagation()}
|
|
165
|
-
>
|
|
166
|
-
<IconDots size={14} />
|
|
167
|
-
</button>
|
|
168
|
-
</DropdownMenuTrigger>
|
|
169
|
-
<DropdownMenuContent align="start" className="w-48">
|
|
170
|
-
{canEdit && (
|
|
171
|
-
<DropdownMenuItem
|
|
172
|
-
onClick={(event) => {
|
|
173
|
-
event.stopPropagation();
|
|
174
|
-
onRemoveFavorite();
|
|
175
|
-
}}
|
|
176
|
-
>
|
|
177
|
-
<IconStar size={14} className="me-2 fill-current" />
|
|
178
|
-
{t("sidebar.unpinFromSidebar")}
|
|
179
|
-
</DropdownMenuItem>
|
|
180
|
-
)}
|
|
181
|
-
{canEdit && canManage && <DropdownMenuSeparator />}
|
|
182
|
-
{canManage && (
|
|
183
|
-
<DropdownMenuItem
|
|
184
|
-
className="text-destructive"
|
|
185
|
-
onClick={(event) => {
|
|
186
|
-
event.stopPropagation();
|
|
187
|
-
setDeleteDialogOpen(true);
|
|
188
|
-
}}
|
|
189
|
-
>
|
|
190
|
-
<IconTrash size={14} className="me-2" />
|
|
191
|
-
{t("database.delete")}
|
|
192
|
-
</DropdownMenuItem>
|
|
193
|
-
)}
|
|
194
|
-
</DropdownMenuContent>
|
|
195
|
-
</DropdownMenu>
|
|
196
|
-
)}
|
|
197
|
-
{canCreateChild && (
|
|
198
|
-
<DropdownMenu>
|
|
199
|
-
<Tooltip>
|
|
200
|
-
<TooltipTrigger asChild>
|
|
201
|
-
<DropdownMenuTrigger asChild>
|
|
202
|
-
<button
|
|
203
|
-
type="button"
|
|
204
|
-
className="flex h-7 w-7 items-center justify-center rounded hover:bg-background focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring"
|
|
205
|
-
aria-label={t("sidebar.addChildTo", { title })}
|
|
206
|
-
onClick={(event) => event.stopPropagation()}
|
|
207
|
-
>
|
|
208
|
-
<IconPlus size={14} />
|
|
209
|
-
</button>
|
|
210
|
-
</DropdownMenuTrigger>
|
|
211
|
-
</TooltipTrigger>
|
|
212
|
-
<TooltipContent>{t("sidebar.addChild")}</TooltipContent>
|
|
213
|
-
</Tooltip>
|
|
214
|
-
<DropdownMenuContent align="start" className="w-44">
|
|
215
|
-
<DropdownMenuItem
|
|
216
|
-
onClick={(event) => {
|
|
217
|
-
event.stopPropagation();
|
|
218
|
-
onCreateChildPage();
|
|
219
|
-
}}
|
|
220
|
-
>
|
|
221
|
-
<IconFileText className="me-2 size-4" />
|
|
222
|
-
{t("sidebar.page")}
|
|
223
|
-
</DropdownMenuItem>
|
|
224
|
-
<DropdownMenuItem
|
|
225
|
-
onClick={(event) => {
|
|
226
|
-
event.stopPropagation();
|
|
227
|
-
onCreateChildDatabase();
|
|
228
|
-
}}
|
|
229
|
-
>
|
|
230
|
-
<IconDatabase className="me-2 size-4" />
|
|
231
|
-
{t("sidebar.database")}
|
|
232
|
-
</DropdownMenuItem>
|
|
233
|
-
</DropdownMenuContent>
|
|
234
|
-
</DropdownMenu>
|
|
235
|
-
)}
|
|
236
|
-
</div>
|
|
237
|
-
|
|
238
|
-
<AlertDialog open={deleteDialogOpen} onOpenChange={setDeleteDialogOpen}>
|
|
239
|
-
<AlertDialogContent>
|
|
240
|
-
<AlertDialogHeader>
|
|
241
|
-
<AlertDialogTitle>
|
|
242
|
-
{t("sidebar.deletePageQuestion")}
|
|
243
|
-
</AlertDialogTitle>
|
|
244
|
-
<AlertDialogDescription>
|
|
245
|
-
{t("sidebar.deletePageDescription", { title })}
|
|
246
|
-
</AlertDialogDescription>
|
|
247
|
-
</AlertDialogHeader>
|
|
248
|
-
<AlertDialogFooter>
|
|
249
|
-
<AlertDialogCancel>{t("comments.cancel")}</AlertDialogCancel>
|
|
250
|
-
<AlertDialogAction
|
|
251
|
-
className="bg-destructive text-destructive-foreground hover:bg-destructive/90"
|
|
252
|
-
onClick={onDelete}
|
|
253
|
-
>
|
|
254
|
-
{t("database.delete")}
|
|
255
|
-
</AlertDialogAction>
|
|
256
|
-
</AlertDialogFooter>
|
|
257
|
-
</AlertDialogContent>
|
|
258
|
-
</AlertDialog>
|
|
259
|
-
</div>
|
|
260
|
-
);
|
|
261
|
-
}
|
|
262
|
-
|
|
263
81
|
export function DocumentTreeItem({
|
|
264
82
|
node,
|
|
265
83
|
depth,
|
|
@@ -286,7 +104,6 @@ export function DocumentTreeItem({
|
|
|
286
104
|
node.accessRole === "admin";
|
|
287
105
|
const hasMenuActions = canEdit || canManage;
|
|
288
106
|
const canCreateChild = canEdit && !isLocalFileNode;
|
|
289
|
-
const [deleteDialogOpen, setDeleteDialogOpen] = useState(false);
|
|
290
107
|
const [contextSheetOpen, setContextSheetOpen] = useState(false);
|
|
291
108
|
const indent = depth * 12 + 12;
|
|
292
109
|
const rowWidth =
|
|
@@ -439,9 +256,9 @@ export function DocumentTreeItem({
|
|
|
439
256
|
{canManage && (
|
|
440
257
|
<DropdownMenuItem
|
|
441
258
|
className="text-destructive"
|
|
442
|
-
|
|
259
|
+
onSelect={(e) => {
|
|
443
260
|
e.stopPropagation();
|
|
444
|
-
|
|
261
|
+
onDelete(node.id, node.title || t("sidebar.untitled"));
|
|
445
262
|
}}
|
|
446
263
|
>
|
|
447
264
|
<IconTrash size={14} className="me-2" />
|
|
@@ -534,30 +351,6 @@ export function DocumentTreeItem({
|
|
|
534
351
|
))}
|
|
535
352
|
</SortableContext>
|
|
536
353
|
)}
|
|
537
|
-
|
|
538
|
-
<AlertDialog open={deleteDialogOpen} onOpenChange={setDeleteDialogOpen}>
|
|
539
|
-
<AlertDialogContent>
|
|
540
|
-
<AlertDialogHeader>
|
|
541
|
-
<AlertDialogTitle>
|
|
542
|
-
{t("sidebar.deletePageQuestion")}
|
|
543
|
-
</AlertDialogTitle>
|
|
544
|
-
<AlertDialogDescription>
|
|
545
|
-
{t("sidebar.deletePageDescription", {
|
|
546
|
-
title: node.title || t("sidebar.untitled"),
|
|
547
|
-
})}
|
|
548
|
-
</AlertDialogDescription>
|
|
549
|
-
</AlertDialogHeader>
|
|
550
|
-
<AlertDialogFooter>
|
|
551
|
-
<AlertDialogCancel>{t("comments.cancel")}</AlertDialogCancel>
|
|
552
|
-
<AlertDialogAction
|
|
553
|
-
className="bg-destructive text-destructive-foreground hover:bg-destructive/90"
|
|
554
|
-
onClick={() => onDelete(node.id)}
|
|
555
|
-
>
|
|
556
|
-
{t("database.delete")}
|
|
557
|
-
</AlertDialogAction>
|
|
558
|
-
</AlertDialogFooter>
|
|
559
|
-
</AlertDialogContent>
|
|
560
|
-
</AlertDialog>
|
|
561
354
|
</div>
|
|
562
355
|
);
|
|
563
356
|
}
|
|
@@ -14,7 +14,8 @@ import { defineConfig, devices } from "@playwright/test";
|
|
|
14
14
|
*/
|
|
15
15
|
export default defineConfig({
|
|
16
16
|
testDir: ".",
|
|
17
|
-
testMatch:
|
|
17
|
+
testMatch:
|
|
18
|
+
/(registry-blocks|local-files|database-preview-menu|sidebar-delete)\.spec\.ts/,
|
|
18
19
|
fullyParallel: true,
|
|
19
20
|
workers: process.env.CI ? 2 : 3,
|
|
20
21
|
retries: 2,
|
package/dist/a2a/client.d.ts
CHANGED
|
@@ -123,8 +123,14 @@ export declare class A2AClient {
|
|
|
123
123
|
metadata?: Record<string, unknown>;
|
|
124
124
|
idempotencyKey?: string;
|
|
125
125
|
approvedActions?: A2AApprovedAction[];
|
|
126
|
-
/**
|
|
126
|
+
/** Time to wait after submission for completion. Default 5 min. */
|
|
127
127
|
timeoutMs?: number;
|
|
128
|
+
/**
|
|
129
|
+
* Optional separate budget for agent-card discovery and the initial
|
|
130
|
+
* async message submission. When omitted, timeoutMs remains the shared
|
|
131
|
+
* end-to-end deadline for backwards compatibility.
|
|
132
|
+
*/
|
|
133
|
+
submissionTimeoutMs?: number;
|
|
128
134
|
/** Poll interval. Default 2s. */
|
|
129
135
|
pollIntervalMs?: number;
|
|
130
136
|
/** Called with each polled task — useful for surfacing progress. */
|
|
@@ -186,6 +192,8 @@ export declare function callAgent(url: string, text: string, opts?: {
|
|
|
186
192
|
async?: boolean;
|
|
187
193
|
/** Total time to wait for the polled task (default 5 min). */
|
|
188
194
|
timeoutMs?: number;
|
|
195
|
+
/** Separate budget for discovery and initial async submission. */
|
|
196
|
+
submissionTimeoutMs?: number;
|
|
189
197
|
/**
|
|
190
198
|
* Existing async task to keep polling. When set, no new message is sent.
|
|
191
199
|
* This prevents a caller-side timeout from duplicating downstream work.
|