@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.
Files changed (80) hide show
  1. package/corpus/README.md +1 -1
  2. package/corpus/core/CHANGELOG.md +6 -0
  3. package/corpus/core/docs/content/external-agents.mdx +15 -11
  4. package/corpus/core/docs/content/locales/ar-SA/external-agents.mdx +3 -1
  5. package/corpus/core/docs/content/locales/de-DE/external-agents.mdx +3 -1
  6. package/corpus/core/docs/content/locales/es-ES/external-agents.mdx +3 -1
  7. package/corpus/core/docs/content/locales/fr-FR/external-agents.mdx +3 -1
  8. package/corpus/core/docs/content/locales/hi-IN/external-agents.mdx +3 -1
  9. package/corpus/core/docs/content/locales/ja-JP/external-agents.mdx +3 -1
  10. package/corpus/core/docs/content/locales/ko-KR/external-agents.mdx +3 -1
  11. package/corpus/core/docs/content/locales/pt-BR/external-agents.mdx +3 -1
  12. package/corpus/core/docs/content/locales/zh-CN/external-agents.mdx +3 -1
  13. package/corpus/core/docs/content/locales/zh-TW/external-agents.mdx +3 -1
  14. package/corpus/core/package.json +1 -1
  15. package/corpus/core/src/a2a/handlers.ts +6 -5
  16. package/corpus/core/src/a2a/task-store.ts +63 -0
  17. package/corpus/core/src/client/session-replay.ts +67 -5
  18. package/corpus/core/src/integrations/adapters/slack.ts +99 -19
  19. package/corpus/core/src/integrations/identity.ts +103 -39
  20. package/corpus/core/src/integrations/plugin.ts +81 -9
  21. package/corpus/core/src/integrations/types.ts +30 -0
  22. package/corpus/core/src/integrations/webhook-handler.ts +1 -0
  23. package/corpus/core/src/mcp/builtin-tools.ts +5 -2
  24. package/corpus/templates/analytics/.agents/skills/session-replay/SKILL.md +4 -1
  25. package/corpus/templates/analytics/AGENTS.md +9 -9
  26. package/corpus/templates/analytics/changelog/2026-07-12-analytics-uses-the-full-in-app-agent-for-multi-step-incident.md +6 -0
  27. package/corpus/templates/analytics/server/handlers/session-replay.ts +15 -9
  28. package/corpus/templates/analytics/server/lib/session-replay-agent-context.ts +23 -5
  29. package/corpus/templates/analytics/server/lib/session-replay.ts +26 -5
  30. package/corpus/templates/analytics/server/plugins/agent-chat.ts +4 -1
  31. package/corpus/templates/analytics/server/routes/api/session-replay/agent-diagnostics.json.get.ts +8 -5
  32. package/corpus/templates/analytics/server/routes/api/session-replay/agent-events.json.get.ts +8 -3
  33. package/corpus/templates/calendar/app/components/calendar/DeleteEventDialog.tsx +12 -2
  34. package/dist/a2a/handlers.d.ts.map +1 -1
  35. package/dist/a2a/handlers.js +6 -6
  36. package/dist/a2a/handlers.js.map +1 -1
  37. package/dist/a2a/task-store.d.ts +12 -0
  38. package/dist/a2a/task-store.d.ts.map +1 -1
  39. package/dist/a2a/task-store.js +54 -0
  40. package/dist/a2a/task-store.js.map +1 -1
  41. package/dist/client/session-replay.d.ts.map +1 -1
  42. package/dist/client/session-replay.js +53 -8
  43. package/dist/client/session-replay.js.map +1 -1
  44. package/dist/collab/routes.d.ts +1 -1
  45. package/dist/collab/struct-routes.d.ts +1 -1
  46. package/dist/file-upload/actions/upload-image.d.ts +1 -1
  47. package/dist/integrations/adapters/slack.d.ts.map +1 -1
  48. package/dist/integrations/adapters/slack.js +85 -11
  49. package/dist/integrations/adapters/slack.js.map +1 -1
  50. package/dist/integrations/identity.d.ts +19 -2
  51. package/dist/integrations/identity.d.ts.map +1 -1
  52. package/dist/integrations/identity.js +76 -34
  53. package/dist/integrations/identity.js.map +1 -1
  54. package/dist/integrations/plugin.d.ts.map +1 -1
  55. package/dist/integrations/plugin.js +56 -6
  56. package/dist/integrations/plugin.js.map +1 -1
  57. package/dist/integrations/types.d.ts +25 -0
  58. package/dist/integrations/types.d.ts.map +1 -1
  59. package/dist/integrations/types.js.map +1 -1
  60. package/dist/integrations/webhook-handler.js +1 -0
  61. package/dist/integrations/webhook-handler.js.map +1 -1
  62. package/dist/mcp/builtin-tools.d.ts.map +1 -1
  63. package/dist/mcp/builtin-tools.js +5 -2
  64. package/dist/mcp/builtin-tools.js.map +1 -1
  65. package/dist/progress/routes.d.ts +1 -1
  66. package/dist/resources/handlers.d.ts +3 -3
  67. package/dist/server/agent-engine-api-key-route.d.ts +1 -1
  68. package/dist/server/transcribe-voice.d.ts +1 -1
  69. package/docs/content/external-agents.mdx +15 -11
  70. package/docs/content/locales/ar-SA/external-agents.mdx +3 -1
  71. package/docs/content/locales/de-DE/external-agents.mdx +3 -1
  72. package/docs/content/locales/es-ES/external-agents.mdx +3 -1
  73. package/docs/content/locales/fr-FR/external-agents.mdx +3 -1
  74. package/docs/content/locales/hi-IN/external-agents.mdx +3 -1
  75. package/docs/content/locales/ja-JP/external-agents.mdx +3 -1
  76. package/docs/content/locales/ko-KR/external-agents.mdx +3 -1
  77. package/docs/content/locales/pt-BR/external-agents.mdx +3 -1
  78. package/docs/content/locales/zh-CN/external-agents.mdx +3 -1
  79. package/docs/content/locales/zh-TW/external-agents.mdx +3 -1
  80. 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
- if (verifySessionReplayAgentAccess(recordingId, token)) return token;
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(recordingId);
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 verifyScopedAgentAccessToken(token, {
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
- }).ok;
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
- if (!verifySessionReplayAgentAccess(recordingId, token)) {
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(recordingId);
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, { limit: 10000 })
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
- const demoMode = await isSessionDemoModeEnabled(getRequestUserEmail());
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(recordingId);
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(recordingId);
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(recordingId);
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(recordingId);
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
- authenticatedReads: "auto",
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) => {
@@ -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
- if (!verifySessionReplayAgentAccess(id, token)) {
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(id, {
112
- limit: replayEventReadLimit,
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> =>
@@ -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
- if (!verifySessionReplayAgentAccess(id, token)) {
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(id, options);
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
- confirmButtonRef.current?.focus();
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 variant="outline" onClick={() => handleConfirm("none")}>
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":"AA4BA,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"}
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"}
@@ -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 updateTask(taskId, {
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 updateTask(taskId, {
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 updateTask(taskId, {
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 updateTask(taskId, {
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 updateTask(taskId, {
296
+ await settleProcessingA2ATask(taskId, {
297
297
  state: "failed",
298
298
  message: {
299
299
  role: "agent",