@agent-native/core 0.98.6 → 0.98.7
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/docs/content/external-agents.mdx +15 -11
- package/corpus/core/docs/content/locales/ar-SA/external-agents.mdx +3 -1
- package/corpus/core/docs/content/locales/de-DE/external-agents.mdx +3 -1
- package/corpus/core/docs/content/locales/es-ES/external-agents.mdx +3 -1
- package/corpus/core/docs/content/locales/fr-FR/external-agents.mdx +3 -1
- package/corpus/core/docs/content/locales/hi-IN/external-agents.mdx +3 -1
- package/corpus/core/docs/content/locales/ja-JP/external-agents.mdx +3 -1
- package/corpus/core/docs/content/locales/ko-KR/external-agents.mdx +3 -1
- package/corpus/core/docs/content/locales/pt-BR/external-agents.mdx +3 -1
- package/corpus/core/docs/content/locales/zh-CN/external-agents.mdx +3 -1
- package/corpus/core/docs/content/locales/zh-TW/external-agents.mdx +3 -1
- package/corpus/core/package.json +1 -1
- package/corpus/core/src/a2a/handlers.ts +6 -5
- package/corpus/core/src/a2a/task-store.ts +63 -0
- package/corpus/core/src/client/session-replay.ts +67 -5
- package/corpus/core/src/integrations/adapters/slack.ts +99 -19
- package/corpus/core/src/integrations/identity.ts +103 -39
- package/corpus/core/src/integrations/plugin.ts +81 -9
- package/corpus/core/src/integrations/types.ts +30 -0
- package/corpus/core/src/integrations/webhook-handler.ts +1 -0
- package/corpus/core/src/mcp/builtin-tools.ts +5 -2
- package/corpus/templates/analytics/.agents/skills/session-replay/SKILL.md +4 -1
- package/corpus/templates/analytics/AGENTS.md +9 -9
- package/corpus/templates/analytics/changelog/2026-07-12-analytics-uses-the-full-in-app-agent-for-multi-step-incident.md +6 -0
- package/corpus/templates/analytics/server/handlers/session-replay.ts +15 -9
- package/corpus/templates/analytics/server/lib/session-replay-agent-context.ts +23 -5
- package/corpus/templates/analytics/server/lib/session-replay.ts +26 -5
- package/corpus/templates/analytics/server/plugins/agent-chat.ts +4 -1
- package/corpus/templates/analytics/server/routes/api/session-replay/agent-diagnostics.json.get.ts +8 -5
- package/corpus/templates/analytics/server/routes/api/session-replay/agent-events.json.get.ts +8 -3
- package/corpus/templates/calendar/app/components/calendar/DeleteEventDialog.tsx +12 -2
- package/dist/a2a/handlers.d.ts.map +1 -1
- package/dist/a2a/handlers.js +6 -6
- package/dist/a2a/handlers.js.map +1 -1
- package/dist/a2a/task-store.d.ts +12 -0
- package/dist/a2a/task-store.d.ts.map +1 -1
- package/dist/a2a/task-store.js +54 -0
- package/dist/a2a/task-store.js.map +1 -1
- package/dist/client/session-replay.d.ts.map +1 -1
- package/dist/client/session-replay.js +53 -8
- package/dist/client/session-replay.js.map +1 -1
- package/dist/collab/routes.d.ts +1 -1
- package/dist/collab/struct-routes.d.ts +1 -1
- package/dist/file-upload/actions/upload-image.d.ts +1 -1
- package/dist/integrations/adapters/slack.d.ts.map +1 -1
- package/dist/integrations/adapters/slack.js +85 -11
- package/dist/integrations/adapters/slack.js.map +1 -1
- package/dist/integrations/identity.d.ts +19 -2
- package/dist/integrations/identity.d.ts.map +1 -1
- package/dist/integrations/identity.js +76 -34
- package/dist/integrations/identity.js.map +1 -1
- package/dist/integrations/plugin.d.ts.map +1 -1
- package/dist/integrations/plugin.js +56 -6
- package/dist/integrations/plugin.js.map +1 -1
- package/dist/integrations/types.d.ts +25 -0
- package/dist/integrations/types.d.ts.map +1 -1
- package/dist/integrations/types.js.map +1 -1
- package/dist/integrations/webhook-handler.js +1 -0
- package/dist/integrations/webhook-handler.js.map +1 -1
- package/dist/mcp/builtin-tools.d.ts.map +1 -1
- package/dist/mcp/builtin-tools.js +5 -2
- package/dist/mcp/builtin-tools.js.map +1 -1
- package/dist/progress/routes.d.ts +1 -1
- package/dist/resources/handlers.d.ts +3 -3
- package/dist/server/agent-engine-api-key-route.d.ts +1 -1
- package/dist/server/transcribe-voice.d.ts +1 -1
- package/docs/content/external-agents.mdx +15 -11
- package/docs/content/locales/ar-SA/external-agents.mdx +3 -1
- package/docs/content/locales/de-DE/external-agents.mdx +3 -1
- package/docs/content/locales/es-ES/external-agents.mdx +3 -1
- package/docs/content/locales/fr-FR/external-agents.mdx +3 -1
- package/docs/content/locales/hi-IN/external-agents.mdx +3 -1
- package/docs/content/locales/ja-JP/external-agents.mdx +3 -1
- package/docs/content/locales/ko-KR/external-agents.mdx +3 -1
- package/docs/content/locales/pt-BR/external-agents.mdx +3 -1
- package/docs/content/locales/zh-CN/external-agents.mdx +3 -1
- package/docs/content/locales/zh-TW/external-agents.mdx +3 -1
- package/package.json +1 -1
|
@@ -12,8 +12,8 @@ import {
|
|
|
12
12
|
|
|
13
13
|
import { runApiHandlerWithContext } from "../lib/credentials";
|
|
14
14
|
import {
|
|
15
|
+
resolveSessionReplayAgentAccess,
|
|
15
16
|
SESSION_REPLAY_AGENT_ACCESS_PARAM,
|
|
16
|
-
verifySessionReplayAgentAccess,
|
|
17
17
|
} from "../lib/session-replay-agent-context.js";
|
|
18
18
|
import {
|
|
19
19
|
getSessionReplayManifest,
|
|
@@ -236,12 +236,13 @@ function replayChunkSeqsFromQuery(query: Record<string, unknown>): number[] {
|
|
|
236
236
|
function verifyAgentReplayAccessToken(
|
|
237
237
|
event: any,
|
|
238
238
|
recordingId: string,
|
|
239
|
-
): string | null {
|
|
239
|
+
): { token: string; viewerEmail: string } | null | false {
|
|
240
240
|
const token = readAgentReplayAccessToken(event);
|
|
241
241
|
if (!token) return null;
|
|
242
|
-
|
|
242
|
+
const access = resolveSessionReplayAgentAccess(recordingId, token);
|
|
243
|
+
if (access) return { token, viewerEmail: access.viewerEmail };
|
|
243
244
|
setResponseStatus(event, 401);
|
|
244
|
-
return
|
|
245
|
+
return false;
|
|
245
246
|
}
|
|
246
247
|
|
|
247
248
|
function listFiltersFromQuery(
|
|
@@ -371,13 +372,16 @@ export const handleSessionReplayManifest = defineEventHandler(async (event) => {
|
|
|
371
372
|
}
|
|
372
373
|
|
|
373
374
|
const agentAccessToken = verifyAgentReplayAccessToken(event, recordingId);
|
|
374
|
-
if (agentAccessToken ===
|
|
375
|
+
if (agentAccessToken === false) {
|
|
375
376
|
return { error: "Invalid or expired agent access" };
|
|
376
377
|
}
|
|
377
378
|
if (agentAccessToken) {
|
|
378
379
|
try {
|
|
379
380
|
applyAgentReplayReadHeaders(event);
|
|
380
|
-
const manifest = await getSessionReplayTokenizedManifest(
|
|
381
|
+
const manifest = await getSessionReplayTokenizedManifest(
|
|
382
|
+
recordingId,
|
|
383
|
+
agentAccessToken.viewerEmail,
|
|
384
|
+
);
|
|
381
385
|
return {
|
|
382
386
|
...manifest,
|
|
383
387
|
chunks: manifest.chunks.map((chunk) => ({
|
|
@@ -385,7 +389,7 @@ export const handleSessionReplayManifest = defineEventHandler(async (event) => {
|
|
|
385
389
|
bytesPath: appendQueryParam(
|
|
386
390
|
chunk.bytesPath,
|
|
387
391
|
SESSION_REPLAY_AGENT_ACCESS_PARAM,
|
|
388
|
-
agentAccessToken,
|
|
392
|
+
agentAccessToken.token,
|
|
389
393
|
),
|
|
390
394
|
})),
|
|
391
395
|
};
|
|
@@ -419,7 +423,7 @@ export const handleSessionReplayChunkBytes = defineEventHandler(
|
|
|
419
423
|
}
|
|
420
424
|
|
|
421
425
|
const agentAccessToken = verifyAgentReplayAccessToken(event, recordingId);
|
|
422
|
-
if (agentAccessToken ===
|
|
426
|
+
if (agentAccessToken === false) {
|
|
423
427
|
return { error: "Invalid or expired agent access" };
|
|
424
428
|
}
|
|
425
429
|
if (agentAccessToken) {
|
|
@@ -427,6 +431,7 @@ export const handleSessionReplayChunkBytes = defineEventHandler(
|
|
|
427
431
|
const result = await readSessionReplayTokenizedChunkBytes(
|
|
428
432
|
recordingId,
|
|
429
433
|
seq,
|
|
434
|
+
agentAccessToken.viewerEmail,
|
|
430
435
|
);
|
|
431
436
|
applyAgentReplayReadHeaders(event);
|
|
432
437
|
setResponseHeader(event, "Content-Type", "application/json");
|
|
@@ -472,7 +477,7 @@ export const handleSessionReplayChunkBatch = defineEventHandler(
|
|
|
472
477
|
const seqs = replayChunkSeqsFromQuery(getQuery(event));
|
|
473
478
|
|
|
474
479
|
const agentAccessToken = verifyAgentReplayAccessToken(event, recordingId);
|
|
475
|
-
if (agentAccessToken ===
|
|
480
|
+
if (agentAccessToken === false) {
|
|
476
481
|
return { error: "Invalid or expired agent access" };
|
|
477
482
|
}
|
|
478
483
|
if (agentAccessToken) {
|
|
@@ -480,6 +485,7 @@ export const handleSessionReplayChunkBatch = defineEventHandler(
|
|
|
480
485
|
const result = await readSessionReplayTokenizedChunkBatch(
|
|
481
486
|
recordingId,
|
|
482
487
|
seqs,
|
|
488
|
+
agentAccessToken.viewerEmail,
|
|
483
489
|
);
|
|
484
490
|
applyAgentReplayReadHeaders(event);
|
|
485
491
|
setResponseHeader(event, "Content-Type", "application/json");
|
|
@@ -651,10 +651,22 @@ export function verifySessionReplayAgentAccess(
|
|
|
651
651
|
recordingId: string,
|
|
652
652
|
token: string,
|
|
653
653
|
): boolean {
|
|
654
|
-
return
|
|
654
|
+
return resolveSessionReplayAgentAccess(recordingId, token) !== null;
|
|
655
|
+
}
|
|
656
|
+
|
|
657
|
+
export function resolveSessionReplayAgentAccess(
|
|
658
|
+
recordingId: string,
|
|
659
|
+
token: string,
|
|
660
|
+
): { viewerEmail: string } | null {
|
|
661
|
+
const result = verifyScopedAgentAccessToken(token, {
|
|
655
662
|
resourceKind: SESSION_REPLAY_AGENT_ACCESS_TOKEN_PREFIX,
|
|
656
663
|
resourceId: recordingId,
|
|
657
|
-
})
|
|
664
|
+
});
|
|
665
|
+
// Replay grants are always minted by an authenticated viewer. Fail closed
|
|
666
|
+
// for grants without that signed identity: demo-mode policy is viewer-scoped,
|
|
667
|
+
// so guessing from the ambient request could expose identities to agents.
|
|
668
|
+
if (!result.ok || !result.viewerEmail) return null;
|
|
669
|
+
return { viewerEmail: result.viewerEmail };
|
|
658
670
|
}
|
|
659
671
|
|
|
660
672
|
export async function createSessionReplayAgentLink({
|
|
@@ -707,14 +719,18 @@ export async function buildSessionReplayAgentContext({
|
|
|
707
719
|
origin?: string;
|
|
708
720
|
includeTimeline?: boolean;
|
|
709
721
|
}) {
|
|
710
|
-
|
|
722
|
+
const access = resolveSessionReplayAgentAccess(recordingId, token);
|
|
723
|
+
if (!access) {
|
|
711
724
|
const error = Object.assign(new Error("Invalid or expired agent access"), {
|
|
712
725
|
statusCode: 401,
|
|
713
726
|
});
|
|
714
727
|
throw error;
|
|
715
728
|
}
|
|
716
729
|
|
|
717
|
-
const recording = await getSessionReplayTokenizedSummary(
|
|
730
|
+
const recording = await getSessionReplayTokenizedSummary(
|
|
731
|
+
recordingId,
|
|
732
|
+
access.viewerEmail,
|
|
733
|
+
);
|
|
718
734
|
const resolvedOrigin = appOrigin(origin);
|
|
719
735
|
const basePath = appBasePath();
|
|
720
736
|
const contextUrl = buildAgentAccessApiUrl({
|
|
@@ -747,7 +763,9 @@ export async function buildSessionReplayAgentContext({
|
|
|
747
763
|
});
|
|
748
764
|
|
|
749
765
|
const eventsResponse = includeTimeline
|
|
750
|
-
? await getSessionReplayTokenizedEvents(recording.id, {
|
|
766
|
+
? await getSessionReplayTokenizedEvents(recording.id, access.viewerEmail, {
|
|
767
|
+
limit: 10000,
|
|
768
|
+
})
|
|
751
769
|
: null;
|
|
752
770
|
const events =
|
|
753
771
|
eventsResponse?.chunks.flatMap((chunk) =>
|
|
@@ -1786,8 +1786,13 @@ export async function getSessionReplaySummary(
|
|
|
1786
1786
|
|
|
1787
1787
|
export async function getSessionReplayTokenizedSummary(
|
|
1788
1788
|
recordingId: string,
|
|
1789
|
+
viewerEmail: string,
|
|
1789
1790
|
): Promise<SessionRecordingSummary> {
|
|
1790
|
-
|
|
1791
|
+
// Tokenized reads often run without an authenticated request session. Use
|
|
1792
|
+
// the viewer identity embedded in the signed, recording-scoped grant so a
|
|
1793
|
+
// link minted while demo mode is enabled cannot reveal real identities when
|
|
1794
|
+
// it is opened in a signed-out browser or by an external agent.
|
|
1795
|
+
const demoMode = await isSessionDemoModeEnabled(viewerEmail);
|
|
1791
1796
|
const db = getDb() as any;
|
|
1792
1797
|
// guard:allow-unscoped -- called only after verifySessionReplayAgentAccess(recordingId, token) verifies a signed, recording-scoped agent_access token.
|
|
1793
1798
|
const [row] = await db
|
|
@@ -1847,6 +1852,7 @@ export async function getSessionReplayManifest(
|
|
|
1847
1852
|
|
|
1848
1853
|
export async function getSessionReplayTokenizedManifest(
|
|
1849
1854
|
recordingId: string,
|
|
1855
|
+
viewerEmail: string,
|
|
1850
1856
|
): Promise<{
|
|
1851
1857
|
recording: AgentSessionRecordingSummary;
|
|
1852
1858
|
chunks: Array<{
|
|
@@ -1859,7 +1865,10 @@ export async function getSessionReplayTokenizedManifest(
|
|
|
1859
1865
|
bytesPath: string;
|
|
1860
1866
|
}>;
|
|
1861
1867
|
}> {
|
|
1862
|
-
const recording = await getSessionReplayTokenizedSummary(
|
|
1868
|
+
const recording = await getSessionReplayTokenizedSummary(
|
|
1869
|
+
recordingId,
|
|
1870
|
+
viewerEmail,
|
|
1871
|
+
);
|
|
1863
1872
|
const manifest = await getSessionReplayManifestForRecording(recording);
|
|
1864
1873
|
return {
|
|
1865
1874
|
...manifest,
|
|
@@ -1923,6 +1932,7 @@ export async function readSessionReplayChunkBytes(
|
|
|
1923
1932
|
export async function readSessionReplayTokenizedChunkBytes(
|
|
1924
1933
|
recordingId: string,
|
|
1925
1934
|
seq: number,
|
|
1935
|
+
viewerEmail: string,
|
|
1926
1936
|
): Promise<{
|
|
1927
1937
|
recording: AgentSessionRecordingSummary;
|
|
1928
1938
|
seq: number;
|
|
@@ -1930,7 +1940,10 @@ export async function readSessionReplayTokenizedChunkBytes(
|
|
|
1930
1940
|
/** Decompressed replay-chunk JSON text (a serialized rrweb events array). */
|
|
1931
1941
|
json: string;
|
|
1932
1942
|
}> {
|
|
1933
|
-
const recording = await getSessionReplayTokenizedSummary(
|
|
1943
|
+
const recording = await getSessionReplayTokenizedSummary(
|
|
1944
|
+
recordingId,
|
|
1945
|
+
viewerEmail,
|
|
1946
|
+
);
|
|
1934
1947
|
const chunk = await readSessionReplayChunkBytesForRecording(recording, seq);
|
|
1935
1948
|
return {
|
|
1936
1949
|
...chunk,
|
|
@@ -2175,8 +2188,12 @@ export async function readSessionReplayChunkBatch(
|
|
|
2175
2188
|
export async function readSessionReplayTokenizedChunkBatch(
|
|
2176
2189
|
recordingId: string,
|
|
2177
2190
|
seqs: number[],
|
|
2191
|
+
viewerEmail: string,
|
|
2178
2192
|
): Promise<SessionReplayChunkBatchResult> {
|
|
2179
|
-
const recording = await getSessionReplayTokenizedSummary(
|
|
2193
|
+
const recording = await getSessionReplayTokenizedSummary(
|
|
2194
|
+
recordingId,
|
|
2195
|
+
viewerEmail,
|
|
2196
|
+
);
|
|
2180
2197
|
return readSessionReplayChunkBatchForRecording(recording, seqs);
|
|
2181
2198
|
}
|
|
2182
2199
|
|
|
@@ -2204,6 +2221,7 @@ export async function getSessionReplayEvents(
|
|
|
2204
2221
|
|
|
2205
2222
|
export async function getSessionReplayTokenizedEvents(
|
|
2206
2223
|
recordingId: string,
|
|
2224
|
+
viewerEmail: string,
|
|
2207
2225
|
options: SessionReplayEventReadOptions = {},
|
|
2208
2226
|
): Promise<{
|
|
2209
2227
|
recording: AgentSessionRecordingSummary;
|
|
@@ -2219,7 +2237,10 @@ export async function getSessionReplayTokenizedEvents(
|
|
|
2219
2237
|
truncated: boolean;
|
|
2220
2238
|
unavailableChunks: number;
|
|
2221
2239
|
}> {
|
|
2222
|
-
const recording = await getSessionReplayTokenizedSummary(
|
|
2240
|
+
const recording = await getSessionReplayTokenizedSummary(
|
|
2241
|
+
recordingId,
|
|
2242
|
+
viewerEmail,
|
|
2243
|
+
);
|
|
2223
2244
|
const result = await getSessionReplayEventsForRecording(recording, options);
|
|
2224
2245
|
return {
|
|
2225
2246
|
...result,
|
|
@@ -259,7 +259,10 @@ export default createAgentChatPlugin({
|
|
|
259
259
|
codeExecution: { production: "sandboxed" },
|
|
260
260
|
connectorCatalog: [...ANALYTICS_CONNECTOR_CATALOG],
|
|
261
261
|
externalAgents: {
|
|
262
|
-
|
|
262
|
+
// Keep the direct MCP surface deliberately curated. External agents
|
|
263
|
+
// should use ask_app for multi-step investigation; these six actions are
|
|
264
|
+
// bounded fallback reads for callers that already know what they need.
|
|
265
|
+
authenticatedReads: "off",
|
|
263
266
|
writes: "ask_app_only",
|
|
264
267
|
},
|
|
265
268
|
resolveOrgId: async (event) => {
|
package/corpus/templates/analytics/server/routes/api/session-replay/agent-diagnostics.json.get.ts
CHANGED
|
@@ -8,8 +8,8 @@ import {
|
|
|
8
8
|
import { type SessionReplayConsoleLevel } from "../../../../shared/session-replay-diagnostics.js";
|
|
9
9
|
import {
|
|
10
10
|
buildSessionReplayDiagnostics,
|
|
11
|
+
resolveSessionReplayAgentAccess,
|
|
11
12
|
SESSION_REPLAY_AGENT_ACCESS_PARAM,
|
|
12
|
-
verifySessionReplayAgentAccess,
|
|
13
13
|
} from "../../../lib/session-replay-agent-context.js";
|
|
14
14
|
import { getSessionReplayTokenizedEvents } from "../../../lib/session-replay.js";
|
|
15
15
|
|
|
@@ -48,7 +48,8 @@ export default defineEventHandler(async (event) => {
|
|
|
48
48
|
setResponseStatus(event, 400);
|
|
49
49
|
return { error: "id and agent access token are required" };
|
|
50
50
|
}
|
|
51
|
-
|
|
51
|
+
const access = resolveSessionReplayAgentAccess(id, token);
|
|
52
|
+
if (!access) {
|
|
52
53
|
setResponseStatus(event, 401);
|
|
53
54
|
return { error: "Invalid or expired agent access" };
|
|
54
55
|
}
|
|
@@ -108,9 +109,11 @@ export default defineEventHandler(async (event) => {
|
|
|
108
109
|
: (rawOffset ? offset : 0) + limit,
|
|
109
110
|
),
|
|
110
111
|
);
|
|
111
|
-
const eventsResponse = await getSessionReplayTokenizedEvents(
|
|
112
|
-
|
|
113
|
-
|
|
112
|
+
const eventsResponse = await getSessionReplayTokenizedEvents(
|
|
113
|
+
id,
|
|
114
|
+
access.viewerEmail,
|
|
115
|
+
{ limit: replayEventReadLimit },
|
|
116
|
+
);
|
|
114
117
|
const events = eventsResponse.chunks.flatMap((chunk) =>
|
|
115
118
|
chunk.events.filter(
|
|
116
119
|
(item): item is Record<string, any> =>
|
package/corpus/templates/analytics/server/routes/api/session-replay/agent-events.json.get.ts
CHANGED
|
@@ -6,8 +6,8 @@ import {
|
|
|
6
6
|
} from "h3";
|
|
7
7
|
|
|
8
8
|
import {
|
|
9
|
+
resolveSessionReplayAgentAccess,
|
|
9
10
|
SESSION_REPLAY_AGENT_ACCESS_PARAM,
|
|
10
|
-
verifySessionReplayAgentAccess,
|
|
11
11
|
} from "../../../lib/session-replay-agent-context.js";
|
|
12
12
|
import {
|
|
13
13
|
getSessionReplayTokenizedEvents,
|
|
@@ -43,7 +43,8 @@ export default defineEventHandler(async (event) => {
|
|
|
43
43
|
setResponseStatus(event, 400);
|
|
44
44
|
return { error: "id and agent access token are required" };
|
|
45
45
|
}
|
|
46
|
-
|
|
46
|
+
const access = resolveSessionReplayAgentAccess(id, token);
|
|
47
|
+
if (!access) {
|
|
47
48
|
setResponseStatus(event, 401);
|
|
48
49
|
return { error: "Invalid or expired agent access" };
|
|
49
50
|
}
|
|
@@ -55,7 +56,11 @@ export default defineEventHandler(async (event) => {
|
|
|
55
56
|
};
|
|
56
57
|
|
|
57
58
|
try {
|
|
58
|
-
return await getSessionReplayTokenizedEvents(
|
|
59
|
+
return await getSessionReplayTokenizedEvents(
|
|
60
|
+
id,
|
|
61
|
+
access.viewerEmail,
|
|
62
|
+
options,
|
|
63
|
+
);
|
|
59
64
|
} catch (error: any) {
|
|
60
65
|
setResponseStatus(event, error?.statusCode ?? 400);
|
|
61
66
|
return { error: error?.message || String(error) };
|
|
@@ -37,6 +37,7 @@ export function DeleteEventDialog({
|
|
|
37
37
|
}: DeleteEventDialogProps) {
|
|
38
38
|
const t = useT();
|
|
39
39
|
const confirmButtonRef = useRef<HTMLButtonElement>(null);
|
|
40
|
+
const dontNotifyButtonRef = useRef<HTMLButtonElement>(null);
|
|
40
41
|
const [scope, setScope] = useState<DeleteEventScope>("single");
|
|
41
42
|
const [message, setMessage] = useState("");
|
|
42
43
|
|
|
@@ -114,7 +115,12 @@ export function DeleteEventDialog({
|
|
|
114
115
|
onKeyDown={handleKeyDown}
|
|
115
116
|
onOpenAutoFocus={(event) => {
|
|
116
117
|
event.preventDefault();
|
|
117
|
-
|
|
118
|
+
// For events with guests, Enter should default to the reversible,
|
|
119
|
+
// no-email path instead of immediately sending a cancellation.
|
|
120
|
+
(canNotifyGuests
|
|
121
|
+
? dontNotifyButtonRef.current
|
|
122
|
+
: confirmButtonRef.current
|
|
123
|
+
)?.focus();
|
|
118
124
|
}}
|
|
119
125
|
>
|
|
120
126
|
<AlertDialogHeader>
|
|
@@ -177,7 +183,11 @@ export function DeleteEventDialog({
|
|
|
177
183
|
{t("deleteEvent.cancel")}
|
|
178
184
|
</AlertDialogCancel>
|
|
179
185
|
{canNotifyGuests && (
|
|
180
|
-
<Button
|
|
186
|
+
<Button
|
|
187
|
+
ref={dontNotifyButtonRef}
|
|
188
|
+
variant="outline"
|
|
189
|
+
onClick={() => handleConfirm("none")}
|
|
190
|
+
>
|
|
181
191
|
{t("deleteEvent.dontNotify")}
|
|
182
192
|
</Button>
|
|
183
193
|
)}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"handlers.d.ts","sourceRoot":"","sources":["../../src/a2a/handlers.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"handlers.d.ts","sourceRoot":"","sources":["../../src/a2a/handlers.ts"],"names":[],"mappings":"AA6BA,OAAO,KAAK,EACV,SAAS,EAIT,eAAe,EAGhB,MAAM,YAAY,CAAC;AA4EpB;;;;;;;;GAQG;AACH,wBAAsB,uBAAuB,CAC3C,MAAM,EAAE,MAAM,EACd,MAAM,EAAE,SAAS,EACjB,KAAK,CAAC,EAAE,GAAG,GACV,OAAO,CAAC,IAAI,CAAC,CAwEf;AAsqBD;;;GAGG;AACH,wBAAsB,eAAe,CACnC,IAAI,EAAE,GAAG,EACT,KAAK,EAAE,GAAG,EACV,MAAM,EAAE,SAAS,GAChB,OAAO,CAAC,eAAe,CAAC,CAyC1B"}
|
package/dist/a2a/handlers.js
CHANGED
|
@@ -4,7 +4,7 @@ import { withConfiguredAppBasePath } from "../server/app-base-path.js";
|
|
|
4
4
|
import { fireInternalDispatch } from "../server/self-dispatch.js";
|
|
5
5
|
import { agentChat } from "../shared/agent-chat.js";
|
|
6
6
|
import { hasConfiguredA2ASecret, isA2AProductionRuntime, } from "./auth-policy.js";
|
|
7
|
-
import { createTask, getTask, getTaskOwner, updateTask, claimA2ATaskForProcessing, getA2ATaskDispatchState, failStuckA2ATask, failStuckQueuedA2ATask, touchQueuedA2ATaskDispatch, touchProcessingA2ATask, } from "./task-store.js";
|
|
7
|
+
import { createTask, getTask, getTaskOwner, updateTask, claimA2ATaskForProcessing, getA2ATaskDispatchState, failStuckA2ATask, failStuckQueuedA2ATask, settleProcessingA2ATask, touchQueuedA2ATaskDispatch, touchProcessingA2ATask, } from "./task-store.js";
|
|
8
8
|
// Inlined to avoid pulling the entire core-routes-plugin (and its h3
|
|
9
9
|
// transitive deps) into the a2a/handlers test boundary. Must stay in sync
|
|
10
10
|
// with FRAMEWORK_ROUTE_PREFIX in `server/core-routes-plugin.ts`.
|
|
@@ -87,7 +87,7 @@ export async function processA2ATaskFromQueue(taskId, config, event) {
|
|
|
87
87
|
}
|
|
88
88
|
const message = claimed.history?.[0];
|
|
89
89
|
if (!message) {
|
|
90
|
-
await
|
|
90
|
+
await settleProcessingA2ATask(taskId, {
|
|
91
91
|
state: "failed",
|
|
92
92
|
message: {
|
|
93
93
|
role: "agent",
|
|
@@ -113,7 +113,7 @@ export async function processA2ATaskFromQueue(taskId, config, event) {
|
|
|
113
113
|
}
|
|
114
114
|
catch (err) {
|
|
115
115
|
try {
|
|
116
|
-
await
|
|
116
|
+
await settleProcessingA2ATask(taskId, {
|
|
117
117
|
state: "failed",
|
|
118
118
|
message: {
|
|
119
119
|
role: "agent",
|
|
@@ -277,7 +277,7 @@ async function runHandlerAndPersist(taskId, message, config, contextId, metadata
|
|
|
277
277
|
for await (const msg of result) {
|
|
278
278
|
lastMessage = msg;
|
|
279
279
|
}
|
|
280
|
-
await
|
|
280
|
+
await settleProcessingA2ATask(taskId, {
|
|
281
281
|
state: "completed",
|
|
282
282
|
message: lastMessage,
|
|
283
283
|
artifacts: artifacts.length > 0 ? artifacts : undefined,
|
|
@@ -286,14 +286,14 @@ async function runHandlerAndPersist(taskId, message, config, contextId, metadata
|
|
|
286
286
|
}
|
|
287
287
|
const handlerResult = await result;
|
|
288
288
|
const allArtifacts = [...artifacts, ...(handlerResult.artifacts ?? [])];
|
|
289
|
-
await
|
|
289
|
+
await settleProcessingA2ATask(taskId, {
|
|
290
290
|
state: "completed",
|
|
291
291
|
message: handlerResult.message,
|
|
292
292
|
artifacts: allArtifacts.length > 0 ? allArtifacts : undefined,
|
|
293
293
|
});
|
|
294
294
|
}
|
|
295
295
|
catch (err) {
|
|
296
|
-
await
|
|
296
|
+
await settleProcessingA2ATask(taskId, {
|
|
297
297
|
state: "failed",
|
|
298
298
|
message: {
|
|
299
299
|
role: "agent",
|