@agent-native/core 0.94.2 → 0.94.3
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/core/CHANGELOG.md +8 -0
- package/corpus/core/package.json +1 -1
- package/corpus/core/src/a2a/artifact-response.ts +154 -1
- package/corpus/core/src/integrations/a2a-continuation-processor.ts +118 -31
- package/corpus/core/src/integrations/a2a-continuations-store.ts +165 -7
- package/corpus/core/src/integrations/adapters/slack.ts +77 -7
- package/corpus/core/src/integrations/types.ts +30 -0
- package/corpus/core/src/integrations/webhook-handler.ts +54 -18
- package/corpus/core/src/scripts/call-agent.ts +1 -0
- package/corpus/core/src/server/request-context.ts +2 -0
- package/dist/a2a/artifact-response.d.ts.map +1 -1
- package/dist/a2a/artifact-response.js +127 -1
- package/dist/a2a/artifact-response.js.map +1 -1
- package/dist/integrations/a2a-continuation-processor.d.ts.map +1 -1
- package/dist/integrations/a2a-continuation-processor.js +76 -21
- package/dist/integrations/a2a-continuation-processor.js.map +1 -1
- package/dist/integrations/a2a-continuations-store.d.ts +4 -1
- package/dist/integrations/a2a-continuations-store.d.ts.map +1 -1
- package/dist/integrations/a2a-continuations-store.js +130 -6
- package/dist/integrations/a2a-continuations-store.js.map +1 -1
- package/dist/integrations/adapters/slack.d.ts.map +1 -1
- package/dist/integrations/adapters/slack.js +56 -7
- package/dist/integrations/adapters/slack.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 +54 -16
- package/dist/integrations/webhook-handler.js.map +1 -1
- package/dist/resources/handlers.d.ts +2 -2
- package/dist/scripts/call-agent.d.ts.map +1 -1
- package/dist/scripts/call-agent.js +1 -0
- package/dist/scripts/call-agent.js.map +1 -1
- package/dist/server/agent-engine-api-key-route.d.ts +1 -1
- package/dist/server/request-context.d.ts +2 -0
- package/dist/server/request-context.d.ts.map +1 -1
- package/dist/server/request-context.js.map +1 -1
- package/dist/server/transcribe-voice.d.ts +1 -1
- package/package.json +1 -1
package/corpus/core/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,13 @@
|
|
|
1
1
|
# @agent-native/core
|
|
2
2
|
|
|
3
|
+
## 0.94.3
|
|
4
|
+
|
|
5
|
+
### Patch Changes
|
|
6
|
+
|
|
7
|
+
- 48d8471: Keep Slack agent task cards active through deferred cross-agent work, show durable progress, and deliver the true final result instead of treating interim artifacts as complete.
|
|
8
|
+
- 48d8471: Keep completed realtime voice turns in their originating chat, restore that chat safely when voice ends, and expose live audio activity to the voice dock.
|
|
9
|
+
- 48d8471: Accept canonical Content document links returned by successful read-only actions as A2A artifact proof while continuing to reject mismatched or unproven URLs.
|
|
10
|
+
|
|
3
11
|
## 0.94.2
|
|
4
12
|
|
|
5
13
|
### Patch Changes
|
package/corpus/core/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@agent-native/core",
|
|
3
|
-
"version": "0.94.
|
|
3
|
+
"version": "0.94.3",
|
|
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": {
|
|
@@ -228,6 +228,132 @@ function contentDatabaseSubmissionArtifact(
|
|
|
228
228
|
};
|
|
229
229
|
}
|
|
230
230
|
|
|
231
|
+
function documentUrlForId(
|
|
232
|
+
parsed: Record<string, unknown>,
|
|
233
|
+
id: string,
|
|
234
|
+
additionalCandidates: Array<string | undefined> = [],
|
|
235
|
+
options: { requireContentOrigin?: boolean } = {},
|
|
236
|
+
): string | undefined {
|
|
237
|
+
const candidates = [
|
|
238
|
+
stringValue(parsed.url),
|
|
239
|
+
stringValue(parsed.urlPath),
|
|
240
|
+
stringValue(parsed.deepLink),
|
|
241
|
+
stringValue(parsed.pageUrl),
|
|
242
|
+
stringValue(parsed.documentUrl),
|
|
243
|
+
...additionalCandidates,
|
|
244
|
+
].filter((value): value is string => !!value);
|
|
245
|
+
|
|
246
|
+
return candidates.find((candidate) => {
|
|
247
|
+
if (!artifactUrlReferencesId(candidate, "document", id)) return false;
|
|
248
|
+
return !options.requireContentOrigin || isContentDocumentUrl(candidate);
|
|
249
|
+
});
|
|
250
|
+
}
|
|
251
|
+
|
|
252
|
+
function isContentDocumentUrl(rawUrl: string): boolean {
|
|
253
|
+
try {
|
|
254
|
+
return new URL(rawUrl).origin === "https://content.agent-native.com";
|
|
255
|
+
} catch {
|
|
256
|
+
return false;
|
|
257
|
+
}
|
|
258
|
+
}
|
|
259
|
+
|
|
260
|
+
function addDocumentReadArtifact(
|
|
261
|
+
documents: Map<string, CreatedDocumentArtifact>,
|
|
262
|
+
parsed: Record<string, unknown>,
|
|
263
|
+
options: {
|
|
264
|
+
allowWithoutUrl: boolean;
|
|
265
|
+
additionalUrlCandidates?: Array<string | undefined>;
|
|
266
|
+
requireContentOrigin?: boolean;
|
|
267
|
+
},
|
|
268
|
+
): void {
|
|
269
|
+
const id = stringValue(parsed.documentId) ?? stringValue(parsed.id);
|
|
270
|
+
if (!id) return;
|
|
271
|
+
|
|
272
|
+
const url = documentUrlForId(parsed, id, options.additionalUrlCandidates, {
|
|
273
|
+
requireContentOrigin: options.requireContentOrigin,
|
|
274
|
+
});
|
|
275
|
+
if (!url && !options.allowWithoutUrl) return;
|
|
276
|
+
|
|
277
|
+
documents.set(id, {
|
|
278
|
+
id,
|
|
279
|
+
title: stringValue(parsed.title) ?? stringValue(parsed.name),
|
|
280
|
+
url,
|
|
281
|
+
});
|
|
282
|
+
}
|
|
283
|
+
|
|
284
|
+
function addContentDatabaseReadArtifacts(
|
|
285
|
+
documents: Map<string, CreatedDocumentArtifact>,
|
|
286
|
+
parsed: Record<string, unknown>,
|
|
287
|
+
): void {
|
|
288
|
+
const resultUrls = [
|
|
289
|
+
stringValue(parsed.url),
|
|
290
|
+
stringValue(parsed.urlPath),
|
|
291
|
+
stringValue(parsed.deepLink),
|
|
292
|
+
];
|
|
293
|
+
const database = asRecord(parsed.database);
|
|
294
|
+
if (database) {
|
|
295
|
+
addDocumentReadArtifact(documents, database, {
|
|
296
|
+
allowWithoutUrl: true,
|
|
297
|
+
requireContentOrigin: true,
|
|
298
|
+
additionalUrlCandidates: resultUrls,
|
|
299
|
+
});
|
|
300
|
+
} else {
|
|
301
|
+
// Unavailable database reads still return a documentId, but they do not
|
|
302
|
+
// prove that the page exists and must not authorize an artifact URL.
|
|
303
|
+
if (parsed.available !== false) {
|
|
304
|
+
addDocumentReadArtifact(documents, parsed, {
|
|
305
|
+
allowWithoutUrl: true,
|
|
306
|
+
requireContentOrigin: true,
|
|
307
|
+
});
|
|
308
|
+
}
|
|
309
|
+
}
|
|
310
|
+
|
|
311
|
+
if (!Array.isArray(parsed.items)) return;
|
|
312
|
+
for (const item of parsed.items) {
|
|
313
|
+
const itemRecord = asRecord(item);
|
|
314
|
+
const document = asRecord(itemRecord?.document);
|
|
315
|
+
if (!document) continue;
|
|
316
|
+
addDocumentReadArtifact(documents, document, {
|
|
317
|
+
allowWithoutUrl: true,
|
|
318
|
+
requireContentOrigin: true,
|
|
319
|
+
additionalUrlCandidates: [
|
|
320
|
+
stringValue(itemRecord?.url),
|
|
321
|
+
stringValue(itemRecord?.urlPath),
|
|
322
|
+
stringValue(itemRecord?.deepLink),
|
|
323
|
+
],
|
|
324
|
+
});
|
|
325
|
+
}
|
|
326
|
+
}
|
|
327
|
+
|
|
328
|
+
function isGenericReadTool(tool: string): boolean {
|
|
329
|
+
return /^(?:find|get|list|query|read|search)-/i.test(tool);
|
|
330
|
+
}
|
|
331
|
+
|
|
332
|
+
function addGenericDocumentReadArtifact(
|
|
333
|
+
documents: Map<string, CreatedDocumentArtifact>,
|
|
334
|
+
parsed: Record<string, unknown>,
|
|
335
|
+
): void {
|
|
336
|
+
// Unknown read actions are accepted only when their result pairs a document
|
|
337
|
+
// ID with a canonical page URL containing that exact ID. An ID by itself is
|
|
338
|
+
// insufficient, preserving the fabrication guard for unrelated actions.
|
|
339
|
+
addDocumentReadArtifact(documents, parsed, {
|
|
340
|
+
allowWithoutUrl: false,
|
|
341
|
+
requireContentOrigin: true,
|
|
342
|
+
});
|
|
343
|
+
|
|
344
|
+
const document = asRecord(parsed.document);
|
|
345
|
+
if (!document) return;
|
|
346
|
+
addDocumentReadArtifact(documents, document, {
|
|
347
|
+
allowWithoutUrl: false,
|
|
348
|
+
requireContentOrigin: true,
|
|
349
|
+
additionalUrlCandidates: [
|
|
350
|
+
stringValue(parsed.url),
|
|
351
|
+
stringValue(parsed.urlPath),
|
|
352
|
+
stringValue(parsed.deepLink),
|
|
353
|
+
],
|
|
354
|
+
});
|
|
355
|
+
}
|
|
356
|
+
|
|
231
357
|
function addImageArtifact(
|
|
232
358
|
images: Map<string, CreatedImageArtifact>,
|
|
233
359
|
parsed: Record<string, unknown>,
|
|
@@ -387,7 +513,6 @@ function collectArtifacts(results: A2AToolResultSummary[]): {
|
|
|
387
513
|
|
|
388
514
|
if (
|
|
389
515
|
toolResult.tool === "create-document" ||
|
|
390
|
-
toolResult.tool === "get-document" ||
|
|
391
516
|
toolResult.tool === "update-document"
|
|
392
517
|
) {
|
|
393
518
|
const id = stringValue(parsed.id);
|
|
@@ -401,6 +526,34 @@ function collectArtifacts(results: A2AToolResultSummary[]): {
|
|
|
401
526
|
continue;
|
|
402
527
|
}
|
|
403
528
|
|
|
529
|
+
if (
|
|
530
|
+
toolResult.tool === "get-document" ||
|
|
531
|
+
toolResult.tool === "get-content-document"
|
|
532
|
+
) {
|
|
533
|
+
const document = asRecord(parsed.document);
|
|
534
|
+
addDocumentReadArtifact(documents, document ?? parsed, {
|
|
535
|
+
allowWithoutUrl: true,
|
|
536
|
+
requireContentOrigin: true,
|
|
537
|
+
additionalUrlCandidates: document
|
|
538
|
+
? [
|
|
539
|
+
stringValue(parsed.url),
|
|
540
|
+
stringValue(parsed.urlPath),
|
|
541
|
+
stringValue(parsed.deepLink),
|
|
542
|
+
]
|
|
543
|
+
: [],
|
|
544
|
+
});
|
|
545
|
+
continue;
|
|
546
|
+
}
|
|
547
|
+
|
|
548
|
+
if (toolResult.tool === "get-content-database") {
|
|
549
|
+
addContentDatabaseReadArtifacts(documents, parsed);
|
|
550
|
+
continue;
|
|
551
|
+
}
|
|
552
|
+
|
|
553
|
+
if (isGenericReadTool(toolResult.tool)) {
|
|
554
|
+
addGenericDocumentReadArtifact(documents, parsed);
|
|
555
|
+
}
|
|
556
|
+
|
|
404
557
|
if (
|
|
405
558
|
toolResult.tool === "create-deck" ||
|
|
406
559
|
toolResult.tool === "duplicate-deck"
|
|
@@ -18,7 +18,11 @@ import {
|
|
|
18
18
|
type A2AContinuation,
|
|
19
19
|
} from "./a2a-continuations-store.js";
|
|
20
20
|
import { signInternalToken } from "./internal-token.js";
|
|
21
|
-
import type {
|
|
21
|
+
import type {
|
|
22
|
+
OutgoingMessage,
|
|
23
|
+
PlatformAdapter,
|
|
24
|
+
PlatformRunProgress,
|
|
25
|
+
} from "./types.js";
|
|
22
26
|
|
|
23
27
|
const PROCESSOR_PATH = `${FRAMEWORK_ROUTE_PREFIX}/integrations/process-a2a-continuation`;
|
|
24
28
|
const TERMINAL_STATES = new Set(["completed", "failed", "canceled"]);
|
|
@@ -150,6 +154,8 @@ async function processClaimedContinuation(
|
|
|
150
154
|
return;
|
|
151
155
|
}
|
|
152
156
|
|
|
157
|
+
const progress = await resumeA2AContinuationProgress(continuation, adapter);
|
|
158
|
+
|
|
153
159
|
const auth = await signContinuationToken(continuation);
|
|
154
160
|
const client = new A2AClient(continuation.agentUrl, auth.apiKey, {
|
|
155
161
|
requestTimeoutMs: POLL_REQUEST_TIMEOUT_MS,
|
|
@@ -162,6 +168,7 @@ async function processClaimedContinuation(
|
|
|
162
168
|
while (Date.now() < deadline) {
|
|
163
169
|
task = await client.getTask(continuation.a2aTaskId);
|
|
164
170
|
if (TERMINAL_STATES.has(task.status.state)) break;
|
|
171
|
+
await reportA2AContinuationProgress(continuation, progress, task);
|
|
165
172
|
await new Promise((resolve) => setTimeout(resolve, POLL_INTERVAL_MS));
|
|
166
173
|
}
|
|
167
174
|
} catch (err) {
|
|
@@ -171,6 +178,7 @@ async function processClaimedContinuation(
|
|
|
171
178
|
continuation,
|
|
172
179
|
adapter,
|
|
173
180
|
remotePollFailureReason(continuation),
|
|
181
|
+
progress,
|
|
174
182
|
);
|
|
175
183
|
return;
|
|
176
184
|
}
|
|
@@ -182,6 +190,7 @@ async function processClaimedContinuation(
|
|
|
182
190
|
continuation,
|
|
183
191
|
adapter,
|
|
184
192
|
err instanceof Error ? err.message : String(err),
|
|
193
|
+
progress,
|
|
185
194
|
);
|
|
186
195
|
return;
|
|
187
196
|
}
|
|
@@ -190,24 +199,12 @@ async function processClaimedContinuation(
|
|
|
190
199
|
}
|
|
191
200
|
|
|
192
201
|
if (!task || !TERMINAL_STATES.has(task.status.state)) {
|
|
193
|
-
const recoverableArtifactText = extractRecoverableArtifactText(task);
|
|
194
|
-
if (recoverableArtifactText) {
|
|
195
|
-
await deliverAndCompleteA2AContinuation(
|
|
196
|
-
continuation,
|
|
197
|
-
adapter,
|
|
198
|
-
formatContinuationArtifactText(
|
|
199
|
-
recoverableArtifactText,
|
|
200
|
-
continuation.agentUrl,
|
|
201
|
-
),
|
|
202
|
-
);
|
|
203
|
-
return;
|
|
204
|
-
}
|
|
205
|
-
|
|
206
202
|
if (shouldStopPollingRemoteTask(continuation)) {
|
|
207
203
|
await notifyAndFailA2AContinuation(
|
|
208
204
|
continuation,
|
|
209
205
|
adapter,
|
|
210
206
|
remotePollFailureReason(continuation),
|
|
207
|
+
progress,
|
|
211
208
|
);
|
|
212
209
|
return;
|
|
213
210
|
}
|
|
@@ -219,7 +216,7 @@ async function processClaimedContinuation(
|
|
|
219
216
|
const reason =
|
|
220
217
|
extractTaskText(task) ||
|
|
221
218
|
`Remote A2A task ${continuation.a2aTaskId} ended with state ${task.status.state}`;
|
|
222
|
-
await notifyAndFailA2AContinuation(continuation, adapter, reason);
|
|
219
|
+
await notifyAndFailA2AContinuation(continuation, adapter, reason, progress);
|
|
223
220
|
return;
|
|
224
221
|
}
|
|
225
222
|
|
|
@@ -232,11 +229,64 @@ async function processClaimedContinuation(
|
|
|
232
229
|
continuation,
|
|
233
230
|
adapter,
|
|
234
231
|
`Remote A2A task ${continuation.a2aTaskId} completed without text`,
|
|
232
|
+
progress,
|
|
235
233
|
);
|
|
236
234
|
return;
|
|
237
235
|
}
|
|
238
236
|
|
|
239
|
-
await deliverAndCompleteA2AContinuation(
|
|
237
|
+
await deliverAndCompleteA2AContinuation(
|
|
238
|
+
continuation,
|
|
239
|
+
adapter,
|
|
240
|
+
text,
|
|
241
|
+
progress,
|
|
242
|
+
);
|
|
243
|
+
}
|
|
244
|
+
|
|
245
|
+
async function resumeA2AContinuationProgress(
|
|
246
|
+
continuation: A2AContinuation,
|
|
247
|
+
adapter: PlatformAdapter,
|
|
248
|
+
): Promise<PlatformRunProgress | null> {
|
|
249
|
+
if (!continuation.progressRef || !adapter.resumeRunProgress) return null;
|
|
250
|
+
try {
|
|
251
|
+
const progress = await adapter.resumeRunProgress(
|
|
252
|
+
continuation.incoming,
|
|
253
|
+
continuation.progressRef,
|
|
254
|
+
);
|
|
255
|
+
if (!progress) return null;
|
|
256
|
+
await progress.onEvent({
|
|
257
|
+
type: "agent_call_progress",
|
|
258
|
+
agent: continuation.agentName,
|
|
259
|
+
state: "working",
|
|
260
|
+
elapsedSeconds: Math.max(
|
|
261
|
+
0,
|
|
262
|
+
Math.round((Date.now() - continuation.createdAt) / 1_000),
|
|
263
|
+
),
|
|
264
|
+
detail: "Continuing in the background",
|
|
265
|
+
});
|
|
266
|
+
return progress;
|
|
267
|
+
} catch {
|
|
268
|
+
// A continuation still has a normal reply fallback. Do not log the
|
|
269
|
+
// opaque provider reference or the inbound message payload.
|
|
270
|
+
return null;
|
|
271
|
+
}
|
|
272
|
+
}
|
|
273
|
+
|
|
274
|
+
async function reportA2AContinuationProgress(
|
|
275
|
+
continuation: A2AContinuation,
|
|
276
|
+
progress: PlatformRunProgress | null,
|
|
277
|
+
task: Task,
|
|
278
|
+
): Promise<void> {
|
|
279
|
+
if (!progress) return;
|
|
280
|
+
await progress.onEvent({
|
|
281
|
+
type: "agent_call_progress",
|
|
282
|
+
agent: continuation.agentName,
|
|
283
|
+
state: task.status.state,
|
|
284
|
+
elapsedSeconds: Math.max(
|
|
285
|
+
0,
|
|
286
|
+
Math.round((Date.now() - continuation.createdAt) / 1_000),
|
|
287
|
+
),
|
|
288
|
+
detail: "Still working on the delegated request",
|
|
289
|
+
});
|
|
240
290
|
}
|
|
241
291
|
|
|
242
292
|
async function waitForContinuationDue(
|
|
@@ -262,6 +312,7 @@ async function notifyAndFailA2AContinuation(
|
|
|
262
312
|
continuation: A2AContinuation,
|
|
263
313
|
adapter: PlatformAdapter,
|
|
264
314
|
reason: string,
|
|
315
|
+
progress: PlatformRunProgress | null = null,
|
|
265
316
|
): Promise<void> {
|
|
266
317
|
const deliveryContinuation = await claimA2AContinuationDelivery(
|
|
267
318
|
continuation.id,
|
|
@@ -273,11 +324,14 @@ async function notifyAndFailA2AContinuation(
|
|
|
273
324
|
reason,
|
|
274
325
|
);
|
|
275
326
|
try {
|
|
327
|
+
const outgoing = adapter.formatAgentResponse(message);
|
|
276
328
|
await withTimeout(
|
|
277
|
-
|
|
278
|
-
adapter
|
|
279
|
-
deliveryContinuation
|
|
280
|
-
|
|
329
|
+
deliverA2AContinuationResponse(
|
|
330
|
+
adapter,
|
|
331
|
+
deliveryContinuation,
|
|
332
|
+
outgoing,
|
|
333
|
+
progress,
|
|
334
|
+
"error",
|
|
281
335
|
),
|
|
282
336
|
PLATFORM_SEND_TIMEOUT_MS,
|
|
283
337
|
`${deliveryContinuation.platform} failure notification timed out`,
|
|
@@ -296,6 +350,7 @@ async function deliverAndCompleteA2AContinuation(
|
|
|
296
350
|
continuation: A2AContinuation,
|
|
297
351
|
adapter: PlatformAdapter,
|
|
298
352
|
text: string,
|
|
353
|
+
progress: PlatformRunProgress | null = null,
|
|
299
354
|
): Promise<void> {
|
|
300
355
|
const deliveryContinuation = await claimA2AContinuationDelivery(
|
|
301
356
|
continuation.id,
|
|
@@ -303,11 +358,14 @@ async function deliverAndCompleteA2AContinuation(
|
|
|
303
358
|
if (!deliveryContinuation) return;
|
|
304
359
|
|
|
305
360
|
try {
|
|
361
|
+
const outgoing = adapter.formatAgentResponse(text);
|
|
306
362
|
await withTimeout(
|
|
307
|
-
|
|
308
|
-
adapter
|
|
309
|
-
deliveryContinuation
|
|
310
|
-
|
|
363
|
+
deliverA2AContinuationResponse(
|
|
364
|
+
adapter,
|
|
365
|
+
deliveryContinuation,
|
|
366
|
+
outgoing,
|
|
367
|
+
progress,
|
|
368
|
+
"done",
|
|
311
369
|
),
|
|
312
370
|
PLATFORM_SEND_TIMEOUT_MS,
|
|
313
371
|
`${deliveryContinuation.platform} response delivery timed out`,
|
|
@@ -327,6 +385,42 @@ async function deliverAndCompleteA2AContinuation(
|
|
|
327
385
|
await completeAfterSuccessfulDelivery(deliveryContinuation);
|
|
328
386
|
}
|
|
329
387
|
|
|
388
|
+
async function deliverA2AContinuationResponse(
|
|
389
|
+
adapter: PlatformAdapter,
|
|
390
|
+
continuation: A2AContinuation,
|
|
391
|
+
message: OutgoingMessage,
|
|
392
|
+
progress: PlatformRunProgress | null,
|
|
393
|
+
status: "done" | "error",
|
|
394
|
+
): Promise<void> {
|
|
395
|
+
if (progress) {
|
|
396
|
+
try {
|
|
397
|
+
await progress.onEvent({
|
|
398
|
+
type: "agent_call",
|
|
399
|
+
agent: continuation.agentName,
|
|
400
|
+
status,
|
|
401
|
+
});
|
|
402
|
+
await progress.complete(message);
|
|
403
|
+
return;
|
|
404
|
+
} catch {
|
|
405
|
+
// A resumed Slack stream can no longer be finalized (for example when
|
|
406
|
+
// chat.stopStream rejects). Preserve the final answer with the same
|
|
407
|
+
// thread reply fallback used by the initial webhook run. Also ask the
|
|
408
|
+
// adapter to terminate the native stream: otherwise Slack can keep the
|
|
409
|
+
// task card in its working state after the thread fallback succeeds.
|
|
410
|
+
try {
|
|
411
|
+
await progress.fail?.(
|
|
412
|
+
"I couldn't update the live response, but I posted the final result in this thread.",
|
|
413
|
+
);
|
|
414
|
+
} catch {
|
|
415
|
+
// The thread reply below is still the authoritative final answer.
|
|
416
|
+
}
|
|
417
|
+
}
|
|
418
|
+
}
|
|
419
|
+
await adapter.sendResponse(message, continuation.incoming, {
|
|
420
|
+
placeholderRef: continuation.placeholderRef ?? undefined,
|
|
421
|
+
});
|
|
422
|
+
}
|
|
423
|
+
|
|
330
424
|
async function rescheduleAndRedispatchA2AContinuation(
|
|
331
425
|
continuationId: string,
|
|
332
426
|
): Promise<void> {
|
|
@@ -524,13 +618,6 @@ function extractTaskText(task: Task): string {
|
|
|
524
618
|
.join("\n");
|
|
525
619
|
}
|
|
526
620
|
|
|
527
|
-
function extractRecoverableArtifactText(task: Task | null): string {
|
|
528
|
-
if (!task?.status.message?.metadata?.agentNativeRecoverableArtifacts) {
|
|
529
|
-
return "";
|
|
530
|
-
}
|
|
531
|
-
return extractTaskText(task);
|
|
532
|
-
}
|
|
533
|
-
|
|
534
621
|
function formatContinuationArtifactText(
|
|
535
622
|
text: string,
|
|
536
623
|
agentUrl: string,
|