@band-ai/sdk 0.3.3 → 0.4.0
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/README.md +54 -1
- package/dist/{ClaudeSDKAdapter-CXud2DBE.d.ts → CopilotACPAdapter-BCpbHFB0.d.ts} +240 -19
- package/dist/{ClaudeSDKAdapter-Cx6zhSaG.d.cts → CopilotACPAdapter-D4VWg8lJ.d.cts} +240 -19
- package/dist/{opencode-2YdscIc1.d.cts → acp-client-D-I_5lK-.d.cts} +23 -4
- package/dist/{opencode-Bld62x5t.d.ts → acp-client-DUXyczlF.d.ts} +23 -4
- package/dist/acp-server-BlcYMxKt.d.ts +17 -0
- package/dist/acp-server-CJhclo6P.d.cts +17 -0
- package/dist/adapters.cjs +2217 -973
- package/dist/adapters.d.cts +21 -132
- package/dist/adapters.d.ts +21 -132
- package/dist/adapters.js +26 -1914
- package/dist/{backends-D-dBdDm-.d.ts → backends-CgsPQa9B.d.ts} +2 -2
- package/dist/{backends-ZLxmQrTZ.d.cts → backends-Dh2WXcHQ.d.cts} +2 -2
- package/dist/{chunk-JY75VSQK.js → chunk-4OVNFDD7.js} +14 -1
- package/dist/chunk-6BE2EG5P.js +128 -0
- package/dist/{chunk-U6AFCLYZ.js → chunk-6TGXV5TE.js} +1824 -514
- package/dist/{chunk-OH6VVVKT.js → chunk-CBCHTTUY.js} +10 -0
- package/dist/{chunk-K5KAEYPF.js → chunk-HNWZZXAE.js} +288 -120
- package/dist/chunk-I34SXMTJ.js +6 -0
- package/dist/{chunk-XWHWJP4I.js → chunk-JDW5WSGF.js} +2 -2
- package/dist/{chunk-KXJ74J73.js → chunk-JIZE4EC6.js} +4 -10
- package/dist/chunk-OGOXY43L.js +119 -0
- package/dist/{chunk-W5IAI6Z4.js → chunk-OVXVZUPO.js} +5 -5
- package/dist/{chunk-YJ42AZO4.js → chunk-RJNJUISR.js} +5 -2
- package/dist/{chunk-MQY74R7D.js → chunk-SHZBLLDQ.js} +21 -9
- package/dist/{chunk-JADCAMZY.js → chunk-TGDDFBYS.js} +45 -0
- package/dist/{chunk-US226AS4.js → chunk-UENIC5FJ.js} +14 -11
- package/dist/{chunk-WA7CHXUS.js → chunk-UL3Y5C4J.js} +2 -2
- package/dist/{chunk-WL2HNJZ6.js → chunk-VOMJRQOM.js} +3 -3
- package/dist/{chunk-MQBBWYRP.js → chunk-YF7K4UB3.js} +3352 -572
- package/dist/{chunk-OD2G5LFQ.js → chunk-ZYOXI4JL.js} +41 -2
- package/dist/config.cjs +2 -12
- package/dist/config.js +2 -2
- package/dist/converters.cjs +36 -11
- package/dist/converters.d.cts +7 -5
- package/dist/converters.d.ts +7 -5
- package/dist/converters.js +11 -13
- package/dist/core.cjs +239 -5
- package/dist/core.d.cts +71 -6
- package/dist/core.d.ts +71 -6
- package/dist/core.js +31 -6
- package/dist/{customTools-BzF0IISO.d.cts → customTools-Bfecd0mJ.d.cts} +1 -1
- package/dist/{customTools-BzF0IISO.d.ts → customTools-Bfecd0mJ.d.ts} +1 -1
- package/dist/{disconnectReason-IuADl6TH.d.ts → disconnectReason-Cctmg1SN.d.cts} +1 -1
- package/dist/{disconnectReason-IuADl6TH.d.cts → disconnectReason-Cctmg1SN.d.ts} +1 -1
- package/dist/{dtos-B8KU_q4d.d.ts → dtos-CjQsN1_h.d.cts} +5 -12
- package/dist/{dtos-B8KU_q4d.d.cts → dtos-CjQsN1_h.d.ts} +5 -12
- package/dist/index.cjs +5237 -1474
- package/dist/index.d.cts +61 -22
- package/dist/index.d.ts +61 -22
- package/dist/index.js +151 -43
- package/dist/linear.cjs +45 -7
- package/dist/linear.d.cts +4 -3
- package/dist/linear.d.ts +4 -3
- package/dist/linear.js +10 -10
- package/dist/mcp-claude.cjs +11 -6
- package/dist/mcp-claude.d.cts +4 -3
- package/dist/mcp-claude.d.ts +4 -3
- package/dist/mcp-claude.js +4 -5
- package/dist/mcp.cjs +13 -7
- package/dist/mcp.d.cts +6 -5
- package/dist/mcp.d.ts +6 -5
- package/dist/mcp.js +5 -6
- package/dist/{pagination-DqdkQArT.d.cts → pagination-BZDhB_nO.d.cts} +2 -2
- package/dist/{pagination-BgEx-HeL.d.ts → pagination-CPz0J_vQ.d.ts} +2 -2
- package/dist/{protocols-Bz1rxcUg.d.cts → protocols-CabgO52c.d.cts} +38 -3
- package/dist/{protocols-Bwwcql0h.d.ts → protocols-Dpci6uae.d.ts} +38 -3
- package/dist/rest.cjs +43 -1
- package/dist/rest.d.cts +6 -5
- package/dist/rest.d.ts +6 -5
- package/dist/rest.js +6 -5
- package/dist/runtime.cjs +2113 -597
- package/dist/runtime.d.cts +44 -25
- package/dist/runtime.d.ts +44 -25
- package/dist/runtime.js +11 -11
- package/dist/{schemas-BgJhlqqO.d.cts → schemas-BKnh4fKR.d.cts} +209 -24
- package/dist/{schemas-C4mK1WSs.d.ts → schemas-CDa3V_I5.d.ts} +209 -24
- package/dist/{sdk-BTciSLRQ.d.cts → sdk-CXNqzoY1.d.cts} +1 -1
- package/dist/{sdk-qKJtMma_.d.ts → sdk-Cin80BTC.d.ts} +1 -1
- package/dist/{simpleAdapter-BpT4XbZC.d.cts → simpleAdapter-D75rcz9n.d.cts} +3 -1
- package/dist/{simpleAdapter--wznuoOw.d.ts → simpleAdapter-eLvsAQNo.d.ts} +3 -1
- package/dist/testing.cjs +25 -7
- package/dist/testing.d.cts +5 -3
- package/dist/testing.d.ts +5 -3
- package/dist/testing.js +9 -6
- package/dist/{types-BivGO7I9.d.ts → types-42-HWeX8.d.cts} +10 -4
- package/dist/types-CKU1N0SK.d.ts +137 -0
- package/dist/{types-BgYFd_Yw.d.cts → types-CjxZekMH.d.ts} +10 -4
- package/dist/types-DtcOLALn.d.cts +137 -0
- package/package.json +25 -26
- package/dist/acp-server-CiUqN3G3.d.ts +0 -24
- package/dist/acp-server-Dlj7D563.d.cts +0 -24
- package/dist/chunk-AVVDPXP4.js +0 -39
- package/dist/chunk-F63TPOI3.js +0 -29
- package/dist/chunk-V5TSWS7P.js +0 -62
- package/dist/types-BNNtOXu3.d.cts +0 -446
- package/dist/types-DFUtpxah.d.ts +0 -446
|
@@ -113,7 +113,17 @@ function buildParticipantsMessage(participants) {
|
|
|
113
113
|
return lines.join("\n");
|
|
114
114
|
}
|
|
115
115
|
|
|
116
|
+
// src/core/deferred.ts
|
|
117
|
+
function createDeferred() {
|
|
118
|
+
let resolve;
|
|
119
|
+
const promise = new Promise((innerResolve) => {
|
|
120
|
+
resolve = innerResolve;
|
|
121
|
+
});
|
|
122
|
+
return { promise, resolve };
|
|
123
|
+
}
|
|
124
|
+
|
|
116
125
|
export {
|
|
126
|
+
createDeferred,
|
|
117
127
|
HistoryProvider,
|
|
118
128
|
SYNTHETIC_SENDER_TYPE,
|
|
119
129
|
SYNTHETIC_CONTACT_EVENTS_SENDER_ID,
|
|
@@ -1,21 +1,34 @@
|
|
|
1
1
|
import {
|
|
2
|
-
|
|
3
|
-
|
|
2
|
+
FAILURE_CODE_TIMEOUT,
|
|
3
|
+
SimpleAdapter,
|
|
4
|
+
agentFailure,
|
|
5
|
+
deliverReply,
|
|
6
|
+
reportProviderTurnFailure,
|
|
7
|
+
reportTurnFailure
|
|
8
|
+
} from "./chunk-OGOXY43L.js";
|
|
4
9
|
import {
|
|
5
10
|
renderSystemPrompt
|
|
6
|
-
} from "./chunk-
|
|
11
|
+
} from "./chunk-RJNJUISR.js";
|
|
7
12
|
import {
|
|
8
|
-
asErrorMessage,
|
|
9
13
|
asNonEmptyString,
|
|
10
|
-
asOptionalRecord
|
|
11
|
-
|
|
14
|
+
asOptionalRecord,
|
|
15
|
+
asString
|
|
16
|
+
} from "./chunk-JIZE4EC6.js";
|
|
12
17
|
import {
|
|
13
|
-
|
|
14
|
-
} from "./chunk-
|
|
18
|
+
asErrorMessage
|
|
19
|
+
} from "./chunk-6BE2EG5P.js";
|
|
20
|
+
import {
|
|
21
|
+
FAILURE_METADATA_KEY
|
|
22
|
+
} from "./chunk-TGDDFBYS.js";
|
|
23
|
+
import {
|
|
24
|
+
GATEWAY_FREE_TEXT_SENSITIVE_KEY_TERMS,
|
|
25
|
+
resolveLogger
|
|
26
|
+
} from "./chunk-ZYOXI4JL.js";
|
|
15
27
|
import {
|
|
16
28
|
UnsupportedFeatureError,
|
|
17
|
-
ValidationError
|
|
18
|
-
|
|
29
|
+
ValidationError,
|
|
30
|
+
rethrowIfRecoverableTurnFailure
|
|
31
|
+
} from "./chunk-4OVNFDD7.js";
|
|
19
32
|
|
|
20
33
|
// src/adapters/shared/history.ts
|
|
21
34
|
function findLatestTaskMetadata(raw, predicate) {
|
|
@@ -32,6 +45,76 @@ function findLatestTaskMetadata(raw, predicate) {
|
|
|
32
45
|
}
|
|
33
46
|
return null;
|
|
34
47
|
}
|
|
48
|
+
var UNKNOWN_SENDER = "Unknown";
|
|
49
|
+
function mergeConsecutiveSameRole(turns) {
|
|
50
|
+
const merged = [];
|
|
51
|
+
let attributedTo = "";
|
|
52
|
+
for (const turn of turns) {
|
|
53
|
+
if (!turn.content) {
|
|
54
|
+
continue;
|
|
55
|
+
}
|
|
56
|
+
const previous = merged[merged.length - 1];
|
|
57
|
+
if (!previous || previous.role !== turn.role) {
|
|
58
|
+
merged.push({ ...turn });
|
|
59
|
+
attributedTo = turn.sender ?? "";
|
|
60
|
+
continue;
|
|
61
|
+
}
|
|
62
|
+
const speaker = turn.sender ?? "";
|
|
63
|
+
previous.content += speaker === attributedTo ? `
|
|
64
|
+
${turn.content}` : `
|
|
65
|
+
${nameContribution(turn.content, speaker)}`;
|
|
66
|
+
attributedTo = speaker;
|
|
67
|
+
}
|
|
68
|
+
return merged;
|
|
69
|
+
}
|
|
70
|
+
function nameContribution(content, speaker) {
|
|
71
|
+
if (speaker !== "" && content.startsWith(`[${speaker}]: `)) {
|
|
72
|
+
return content;
|
|
73
|
+
}
|
|
74
|
+
return `[${speaker || UNKNOWN_SENDER}]: ${content}`;
|
|
75
|
+
}
|
|
76
|
+
function pairUserAssistantTurns(turns) {
|
|
77
|
+
const paired = [];
|
|
78
|
+
let index = 0;
|
|
79
|
+
while (index < turns.length) {
|
|
80
|
+
const current = turns[index];
|
|
81
|
+
if (current.role !== "user" || !current.content) {
|
|
82
|
+
index += 1;
|
|
83
|
+
continue;
|
|
84
|
+
}
|
|
85
|
+
const next = turns[index + 1];
|
|
86
|
+
if (next && next.role === "assistant" && next.content) {
|
|
87
|
+
paired.push(current, next);
|
|
88
|
+
index += 2;
|
|
89
|
+
continue;
|
|
90
|
+
}
|
|
91
|
+
if (index === turns.length - 1) {
|
|
92
|
+
paired.push(current);
|
|
93
|
+
}
|
|
94
|
+
index += 1;
|
|
95
|
+
}
|
|
96
|
+
return paired;
|
|
97
|
+
}
|
|
98
|
+
function takeRecentTurns(turns, limit) {
|
|
99
|
+
const cap = Number.isNaN(limit) ? 0 : Math.floor(limit);
|
|
100
|
+
if (cap <= 0) {
|
|
101
|
+
return [];
|
|
102
|
+
}
|
|
103
|
+
if (turns.length <= cap) {
|
|
104
|
+
return [...turns];
|
|
105
|
+
}
|
|
106
|
+
const truncated = turns.slice(-cap);
|
|
107
|
+
if (truncated[0]?.role === "assistant") {
|
|
108
|
+
truncated.shift();
|
|
109
|
+
}
|
|
110
|
+
return truncated;
|
|
111
|
+
}
|
|
112
|
+
function selectCompleteExchanges(history, limit) {
|
|
113
|
+
return takeRecentTurns(
|
|
114
|
+
pairUserAssistantTurns(mergeConsecutiveSameRole(history)),
|
|
115
|
+
limit
|
|
116
|
+
);
|
|
117
|
+
}
|
|
35
118
|
|
|
36
119
|
// src/converters/shared.ts
|
|
37
120
|
function asOptionalString(value) {
|
|
@@ -280,6 +363,7 @@ import { randomUUID } from "crypto";
|
|
|
280
363
|
var TERMINAL_STATES = /* @__PURE__ */ new Set(["completed", "failed", "canceled", "rejected", "auth-required"]);
|
|
281
364
|
var DEFAULT_MAX_STREAM_EVENTS = 1e4;
|
|
282
365
|
var A2AAdapter = class extends SimpleAdapter {
|
|
366
|
+
provider = "a2a";
|
|
283
367
|
remoteUrl;
|
|
284
368
|
authHeaders;
|
|
285
369
|
streaming;
|
|
@@ -299,20 +383,20 @@ var A2AAdapter = class extends SimpleAdapter {
|
|
|
299
383
|
this.streaming = options.streaming ?? true;
|
|
300
384
|
this.clientFactory = options.clientFactory;
|
|
301
385
|
this.maxStreamEvents = normalizeMaxStreamEvents(options.maxStreamEvents);
|
|
302
|
-
this.logger = options.logger
|
|
386
|
+
this.logger = resolveLogger(options.logger);
|
|
303
387
|
}
|
|
304
388
|
async onStarted(agentName, agentDescription) {
|
|
305
389
|
await super.onStarted(agentName, agentDescription);
|
|
306
390
|
this.client = await this.createClient();
|
|
307
391
|
}
|
|
308
392
|
async onMessage(message, tools, history, _participantsMessage, _contactsMessage, context) {
|
|
309
|
-
const client = this.client ?? await this.createClient();
|
|
310
|
-
this.client = client;
|
|
311
|
-
if (context.isSessionBootstrap) {
|
|
312
|
-
await this.rehydrateFromHistory(context.roomId, history, client);
|
|
313
|
-
}
|
|
314
|
-
const request = this.toSendParams(message, context.roomId);
|
|
315
393
|
try {
|
|
394
|
+
const client = this.client ?? await this.createClient();
|
|
395
|
+
this.client = client;
|
|
396
|
+
if (context.isSessionBootstrap) {
|
|
397
|
+
await this.rehydrateFromHistory(context.roomId, history, client);
|
|
398
|
+
}
|
|
399
|
+
const request = this.toSendParams(message, context.roomId);
|
|
316
400
|
if (this.streaming) {
|
|
317
401
|
let streamEventCount = 0;
|
|
318
402
|
for await (const event of client.sendMessageStream(request)) {
|
|
@@ -323,6 +407,7 @@ var A2AAdapter = class extends SimpleAdapter {
|
|
|
323
407
|
try {
|
|
324
408
|
await this.handleEvent(event, tools, context.roomId, message.senderId);
|
|
325
409
|
} catch (handleError) {
|
|
410
|
+
rethrowIfRecoverableTurnFailure(handleError);
|
|
326
411
|
this.logger.error("A2A stream event handling failed; continuing stream", {
|
|
327
412
|
roomId: context.roomId,
|
|
328
413
|
remoteUrl: this.remoteUrl,
|
|
@@ -336,24 +421,11 @@ var A2AAdapter = class extends SimpleAdapter {
|
|
|
336
421
|
const response = await client.sendMessage(request);
|
|
337
422
|
await this.handleEvent(response, tools, context.roomId, message.senderId);
|
|
338
423
|
} catch (error) {
|
|
339
|
-
|
|
340
|
-
this.logger.
|
|
424
|
+
rethrowIfRecoverableTurnFailure(error);
|
|
425
|
+
await reportProviderTurnFailure(tools, this.logger, this.provider, "A2A adapter request failed", error, {
|
|
341
426
|
roomId: context.roomId,
|
|
342
|
-
remoteUrl: this.remoteUrl
|
|
343
|
-
error
|
|
427
|
+
remoteUrl: this.remoteUrl
|
|
344
428
|
});
|
|
345
|
-
try {
|
|
346
|
-
await tools.sendEvent(`A2A agent error: ${errorMessage}`, "error", {
|
|
347
|
-
a2a_error: errorMessage
|
|
348
|
-
});
|
|
349
|
-
} catch (eventError) {
|
|
350
|
-
this.logger.warn("A2A adapter failed to emit error event", {
|
|
351
|
-
roomId: context.roomId,
|
|
352
|
-
remoteUrl: this.remoteUrl,
|
|
353
|
-
error: eventError
|
|
354
|
-
});
|
|
355
|
-
}
|
|
356
|
-
throw error instanceof Error ? error : new Error(errorMessage);
|
|
357
429
|
}
|
|
358
430
|
}
|
|
359
431
|
async onCleanup(roomId) {
|
|
@@ -373,7 +445,7 @@ var A2AAdapter = class extends SimpleAdapter {
|
|
|
373
445
|
if (isMessageEvent(event)) {
|
|
374
446
|
const text = extractMessageText(event);
|
|
375
447
|
if (text) {
|
|
376
|
-
await tools
|
|
448
|
+
await deliverReply(tools, text, [{ id: senderId }]);
|
|
377
449
|
}
|
|
378
450
|
return;
|
|
379
451
|
}
|
|
@@ -388,7 +460,7 @@ var A2AAdapter = class extends SimpleAdapter {
|
|
|
388
460
|
if (isArtifactUpdateEvent(event)) {
|
|
389
461
|
const text = extractArtifactText(event.artifact);
|
|
390
462
|
if (text) {
|
|
391
|
-
await tools
|
|
463
|
+
await deliverReply(tools, text, [{ id: senderId }]);
|
|
392
464
|
}
|
|
393
465
|
}
|
|
394
466
|
}
|
|
@@ -459,23 +531,29 @@ var A2AAdapter = class extends SimpleAdapter {
|
|
|
459
531
|
}
|
|
460
532
|
if (input.state === "input-required") {
|
|
461
533
|
const text = extractMessageText(input.statusMessage) ?? "Please provide more information.";
|
|
462
|
-
await input.tools
|
|
534
|
+
await deliverReply(input.tools, text, [input.sender]);
|
|
463
535
|
await this.emitTaskEvent(input.tools, input.contextId, input.taskId, input.state);
|
|
464
536
|
return;
|
|
465
537
|
}
|
|
466
538
|
if (input.state === "completed") {
|
|
467
|
-
|
|
468
|
-
|
|
539
|
+
try {
|
|
540
|
+
if (input.completedMessage) {
|
|
541
|
+
await deliverReply(input.tools, input.completedMessage, [input.sender]);
|
|
542
|
+
}
|
|
543
|
+
await this.emitTaskEvent(input.tools, input.contextId, input.taskId, input.state);
|
|
544
|
+
} finally {
|
|
545
|
+
this.clearTaskTracking(input.key, input.roomId);
|
|
469
546
|
}
|
|
470
|
-
await this.emitTaskEvent(input.tools, input.contextId, input.taskId, input.state);
|
|
471
|
-
this.clearTaskTracking(input.key, input.roomId);
|
|
472
547
|
return;
|
|
473
548
|
}
|
|
474
549
|
if (TERMINAL_STATES.has(input.state)) {
|
|
475
550
|
const text = extractMessageText(input.statusMessage) ?? `A2A task ${input.state}`;
|
|
476
|
-
|
|
477
|
-
|
|
478
|
-
|
|
551
|
+
try {
|
|
552
|
+
await this.emitTaskEvent(input.tools, input.contextId, input.taskId, input.state);
|
|
553
|
+
} finally {
|
|
554
|
+
this.clearTaskTracking(input.key, input.roomId);
|
|
555
|
+
}
|
|
556
|
+
await reportTurnFailure(input.tools, agentFailure(this.provider, text, input.state), this.logger, { roomId: input.roomId });
|
|
479
557
|
}
|
|
480
558
|
}
|
|
481
559
|
async emitTaskEvent(tools, contextId, taskId, state) {
|
|
@@ -851,15 +929,57 @@ function buildStatusEvent(input) {
|
|
|
851
929
|
};
|
|
852
930
|
}
|
|
853
931
|
|
|
932
|
+
// src/adapters/a2a-gateway/failure.ts
|
|
933
|
+
import { AgentFailure } from "@band-ai/band-sdk-core";
|
|
934
|
+
var PROVIDER = "a2a-gateway";
|
|
935
|
+
var SENSITIVE_VALUE_PATTERN = new RegExp(
|
|
936
|
+
`(${GATEWAY_FREE_TEXT_SENSITIVE_KEY_TERMS})"?\\s*(?:[A-Za-z]+\\s*)?[:=]\\s*"?(?:[A-Za-z][\\w-]*\\s+)?[^\\s,;"]+`,
|
|
937
|
+
"gi"
|
|
938
|
+
);
|
|
939
|
+
function buildGatewayFailureMetadata(error, code, message = sanitizeGatewayErrorMessage(error)) {
|
|
940
|
+
return {
|
|
941
|
+
[FAILURE_METADATA_KEY]: new AgentFailure(
|
|
942
|
+
PROVIDER,
|
|
943
|
+
message,
|
|
944
|
+
code ?? (error instanceof Error ? error.name : "UnknownError")
|
|
945
|
+
).toObject()
|
|
946
|
+
};
|
|
947
|
+
}
|
|
948
|
+
function sanitizeGatewayErrorMessage(error) {
|
|
949
|
+
const rawMessage = error instanceof Error ? error.message : String(error);
|
|
950
|
+
const trimmed = rawMessage.trim();
|
|
951
|
+
if (!trimmed) {
|
|
952
|
+
return "Unknown error";
|
|
953
|
+
}
|
|
954
|
+
const withBearerRedaction = trimmed.replace(/Bearer\s+[^\s,;]+/gi, "Bearer [REDACTED]").replace(SENSITIVE_VALUE_PATTERN, "$1=[REDACTED]");
|
|
955
|
+
const maxLength = 240;
|
|
956
|
+
if (withBearerRedaction.length <= maxLength) {
|
|
957
|
+
return withBearerRedaction;
|
|
958
|
+
}
|
|
959
|
+
return `${withBearerRedaction.slice(0, maxLength - 3)}...`;
|
|
960
|
+
}
|
|
961
|
+
function sanitizeForwardedFailure(value) {
|
|
962
|
+
const record = asOptionalRecord(value);
|
|
963
|
+
if (!record) {
|
|
964
|
+
return void 0;
|
|
965
|
+
}
|
|
966
|
+
const provider = asString(record.provider) ?? "unknown";
|
|
967
|
+
const code = asString(record.code) ?? void 0;
|
|
968
|
+
const message = sanitizeGatewayErrorMessage(asString(record.message) ?? "Unknown error");
|
|
969
|
+
return new AgentFailure(provider, message, code).toObject();
|
|
970
|
+
}
|
|
971
|
+
|
|
854
972
|
// src/adapters/a2a-gateway/server.ts
|
|
855
973
|
var GatewayPeerExecutor = class {
|
|
856
974
|
peer;
|
|
857
975
|
onRequest;
|
|
858
976
|
onCancel;
|
|
977
|
+
logger;
|
|
859
978
|
constructor(options) {
|
|
860
979
|
this.peer = options.peer;
|
|
861
980
|
this.onRequest = options.onRequest;
|
|
862
981
|
this.onCancel = options.onCancel;
|
|
982
|
+
this.logger = options.logger;
|
|
863
983
|
}
|
|
864
984
|
async execute(requestContext, eventBus) {
|
|
865
985
|
const taskId = asNonEmptyString(requestContext.taskId) ?? randomUUID3();
|
|
@@ -879,6 +999,12 @@ var GatewayPeerExecutor = class {
|
|
|
879
999
|
}
|
|
880
1000
|
}
|
|
881
1001
|
} catch (error) {
|
|
1002
|
+
this.logger.warn("a2a_gateway.peer_request_failed", {
|
|
1003
|
+
peerId: this.peer.id,
|
|
1004
|
+
taskId,
|
|
1005
|
+
contextId,
|
|
1006
|
+
error
|
|
1007
|
+
});
|
|
882
1008
|
eventBus.publish(
|
|
883
1009
|
buildStatusEvent({
|
|
884
1010
|
taskId,
|
|
@@ -886,7 +1012,7 @@ var GatewayPeerExecutor = class {
|
|
|
886
1012
|
state: "failed",
|
|
887
1013
|
final: true,
|
|
888
1014
|
text: "Peer request failed.",
|
|
889
|
-
metadata:
|
|
1015
|
+
metadata: buildGatewayFailureMetadata(error)
|
|
890
1016
|
})
|
|
891
1017
|
);
|
|
892
1018
|
} finally {
|
|
@@ -914,10 +1040,12 @@ var GatewayPeerExecutor = class {
|
|
|
914
1040
|
};
|
|
915
1041
|
var GatewayServer = class {
|
|
916
1042
|
options;
|
|
1043
|
+
logger;
|
|
917
1044
|
server = null;
|
|
918
1045
|
started = false;
|
|
919
1046
|
constructor(options) {
|
|
920
1047
|
this.options = options;
|
|
1048
|
+
this.logger = resolveLogger(options.logger);
|
|
921
1049
|
}
|
|
922
1050
|
async start() {
|
|
923
1051
|
if (this.started) {
|
|
@@ -987,7 +1115,8 @@ var GatewayServer = class {
|
|
|
987
1115
|
new GatewayPeerExecutor({
|
|
988
1116
|
peer,
|
|
989
1117
|
onRequest: this.options.onRequest,
|
|
990
|
-
onCancel: this.options.onCancel
|
|
1118
|
+
onCancel: this.options.onCancel,
|
|
1119
|
+
logger: this.logger
|
|
991
1120
|
})
|
|
992
1121
|
);
|
|
993
1122
|
const userBuilder = createUserBuilder(
|
|
@@ -1244,25 +1373,6 @@ function verifyBearerAuthorization(headers, authToken) {
|
|
|
1244
1373
|
}
|
|
1245
1374
|
return safeHeaderEquals(authorization, `Bearer ${authToken}`);
|
|
1246
1375
|
}
|
|
1247
|
-
function buildGatewayExecutionFailureMetadata(error) {
|
|
1248
|
-
return {
|
|
1249
|
-
error_type: error instanceof Error ? error.name : "UnknownError",
|
|
1250
|
-
error_message: sanitizeGatewayErrorMessage(error)
|
|
1251
|
-
};
|
|
1252
|
-
}
|
|
1253
|
-
function sanitizeGatewayErrorMessage(error) {
|
|
1254
|
-
const rawMessage = error instanceof Error ? error.message : String(error);
|
|
1255
|
-
const trimmed = rawMessage.trim();
|
|
1256
|
-
if (!trimmed) {
|
|
1257
|
-
return "Unknown error";
|
|
1258
|
-
}
|
|
1259
|
-
const withBearerRedaction = trimmed.replace(/Bearer\s+[^\s,;]+/gi, "Bearer [REDACTED]").replace(/(token|authorization|api[_-]?key)\s*[:=]\s*[^\s,;]+/gi, "$1=[REDACTED]");
|
|
1260
|
-
const maxLength = 240;
|
|
1261
|
-
if (withBearerRedaction.length <= maxLength) {
|
|
1262
|
-
return withBearerRedaction;
|
|
1263
|
-
}
|
|
1264
|
-
return `${withBearerRedaction.slice(0, maxLength - 3)}...`;
|
|
1265
|
-
}
|
|
1266
1376
|
function safeHeaderEquals(left, right) {
|
|
1267
1377
|
const leftBuffer = Buffer.from(left);
|
|
1268
1378
|
const rightBuffer = Buffer.from(right);
|
|
@@ -1281,6 +1391,7 @@ var DEFAULT_RESPONSE_TIMEOUT_MS = 12e4;
|
|
|
1281
1391
|
var DEFAULT_PEER_PAGE_SIZE = 100;
|
|
1282
1392
|
var DEFAULT_MAX_PEER_PAGES = 25;
|
|
1283
1393
|
var A2AGatewayAdapter = class extends SimpleAdapter {
|
|
1394
|
+
provider = PROVIDER;
|
|
1284
1395
|
bandRest;
|
|
1285
1396
|
gatewayUrl;
|
|
1286
1397
|
host;
|
|
@@ -1291,6 +1402,7 @@ var A2AGatewayAdapter = class extends SimpleAdapter {
|
|
|
1291
1402
|
peerPageSize;
|
|
1292
1403
|
maxPeerPages;
|
|
1293
1404
|
serverFactory;
|
|
1405
|
+
logger;
|
|
1294
1406
|
peersBySlug = /* @__PURE__ */ new Map();
|
|
1295
1407
|
peersById = /* @__PURE__ */ new Map();
|
|
1296
1408
|
contextToRoom = /* @__PURE__ */ new Map();
|
|
@@ -1312,6 +1424,7 @@ var A2AGatewayAdapter = class extends SimpleAdapter {
|
|
|
1312
1424
|
this.peerPageSize = options.peerPageSize ?? DEFAULT_PEER_PAGE_SIZE;
|
|
1313
1425
|
this.maxPeerPages = options.maxPeerPages ?? DEFAULT_MAX_PEER_PAGES;
|
|
1314
1426
|
this.serverFactory = options.serverFactory ?? createGatewayServer;
|
|
1427
|
+
this.logger = resolveLogger(options.logger);
|
|
1315
1428
|
if (this.allowUnauthenticatedLoopback && !isLoopbackHost2(this.host)) {
|
|
1316
1429
|
throw new ValidationError(
|
|
1317
1430
|
"A2AGatewayAdapter `allowUnauthenticatedLoopback` may only be enabled for loopback hosts."
|
|
@@ -1333,7 +1446,8 @@ var A2AGatewayAdapter = class extends SimpleAdapter {
|
|
|
1333
1446
|
onCancel: async (request) => {
|
|
1334
1447
|
const canonicalPeerId = this.resolveCanonicalPeerId(request);
|
|
1335
1448
|
this.cancelPendingTask(request.taskId, canonicalPeerId ?? request.peerId);
|
|
1336
|
-
}
|
|
1449
|
+
},
|
|
1450
|
+
logger: this.logger
|
|
1337
1451
|
});
|
|
1338
1452
|
await this.server.start();
|
|
1339
1453
|
}
|
|
@@ -1415,12 +1529,15 @@ var A2AGatewayAdapter = class extends SimpleAdapter {
|
|
|
1415
1529
|
async *handleGatewayRequest(request) {
|
|
1416
1530
|
const peer = this.resolveGatewayPeer(request);
|
|
1417
1531
|
if (!peer) {
|
|
1532
|
+
const text = `Peer not found: ${request.peerId}`;
|
|
1533
|
+
this.logger.warn("a2a_gateway.peer_not_found", { peerId: request.peerId, taskId: request.taskId });
|
|
1418
1534
|
yield buildStatusEvent({
|
|
1419
1535
|
taskId: request.taskId,
|
|
1420
1536
|
contextId: request.contextId,
|
|
1421
1537
|
state: "failed",
|
|
1422
1538
|
final: true,
|
|
1423
|
-
text
|
|
1539
|
+
text,
|
|
1540
|
+
metadata: buildGatewayFailureMetadata(text, "peer_not_found")
|
|
1424
1541
|
});
|
|
1425
1542
|
return;
|
|
1426
1543
|
}
|
|
@@ -1471,12 +1588,20 @@ var A2AGatewayAdapter = class extends SimpleAdapter {
|
|
|
1471
1588
|
});
|
|
1472
1589
|
} catch (error) {
|
|
1473
1590
|
this.removePending(pending);
|
|
1591
|
+
const text = sanitizeGatewayErrorMessage(error);
|
|
1592
|
+
this.logger.warn("a2a_gateway.relay_failed", {
|
|
1593
|
+
roomId,
|
|
1594
|
+
peerId: peer.id,
|
|
1595
|
+
taskId: pending.taskId,
|
|
1596
|
+
error
|
|
1597
|
+
});
|
|
1474
1598
|
yield buildStatusEvent({
|
|
1475
1599
|
taskId: pending.taskId,
|
|
1476
1600
|
contextId: pending.contextId,
|
|
1477
1601
|
state: "failed",
|
|
1478
1602
|
final: true,
|
|
1479
|
-
text
|
|
1603
|
+
text,
|
|
1604
|
+
metadata: buildGatewayFailureMetadata(error, void 0, text)
|
|
1480
1605
|
});
|
|
1481
1606
|
return;
|
|
1482
1607
|
}
|
|
@@ -1484,12 +1609,20 @@ var A2AGatewayAdapter = class extends SimpleAdapter {
|
|
|
1484
1609
|
const next = await pending.queue.dequeue(this.responseTimeoutMs);
|
|
1485
1610
|
if (!next) {
|
|
1486
1611
|
this.removePending(pending);
|
|
1612
|
+
const text = "Timed out waiting for a Band peer response.";
|
|
1613
|
+
this.logger.warn("a2a_gateway.peer_response_timeout", {
|
|
1614
|
+
roomId,
|
|
1615
|
+
peerId: peer.id,
|
|
1616
|
+
taskId: pending.taskId,
|
|
1617
|
+
responseTimeoutMs: this.responseTimeoutMs
|
|
1618
|
+
});
|
|
1487
1619
|
yield buildStatusEvent({
|
|
1488
1620
|
taskId: pending.taskId,
|
|
1489
1621
|
contextId: pending.contextId,
|
|
1490
1622
|
state: "failed",
|
|
1491
1623
|
final: true,
|
|
1492
|
-
text
|
|
1624
|
+
text,
|
|
1625
|
+
metadata: buildGatewayFailureMetadata(text, FAILURE_CODE_TIMEOUT)
|
|
1493
1626
|
});
|
|
1494
1627
|
return;
|
|
1495
1628
|
}
|
|
@@ -1770,17 +1903,22 @@ function toStatusUpdateEvent(message, taskId, contextId) {
|
|
|
1770
1903
|
} else {
|
|
1771
1904
|
state = "working";
|
|
1772
1905
|
}
|
|
1906
|
+
const failure = sanitizeForwardedFailure(message.metadata?.[FAILURE_METADATA_KEY]);
|
|
1773
1907
|
return buildStatusEvent({
|
|
1774
1908
|
taskId,
|
|
1775
1909
|
contextId,
|
|
1776
1910
|
state,
|
|
1777
1911
|
final,
|
|
1778
|
-
|
|
1912
|
+
// A room's own "error" event reaches an external A2A client verbatim
|
|
1913
|
+
// otherwise — sanitize it the same way a gateway-originated failure is,
|
|
1914
|
+
// since neither is guaranteed to be pre-redacted upstream.
|
|
1915
|
+
text: normalizedType === "error" ? sanitizeGatewayErrorMessage(message.content) : message.content,
|
|
1779
1916
|
metadata: {
|
|
1780
1917
|
band_message_id: message.id,
|
|
1781
1918
|
band_message_type: message.messageType,
|
|
1782
1919
|
band_sender_id: message.senderId,
|
|
1783
|
-
band_room_id: message.roomId
|
|
1920
|
+
band_room_id: message.roomId,
|
|
1921
|
+
...failure !== void 0 ? { [FAILURE_METADATA_KEY]: failure } : {}
|
|
1784
1922
|
}
|
|
1785
1923
|
});
|
|
1786
1924
|
}
|
|
@@ -1914,6 +2052,7 @@ var LazyAsyncValue = class {
|
|
|
1914
2052
|
var DEFAULT_RESPONSE_TIMEOUT_SECONDS = 120;
|
|
1915
2053
|
var DEFAULT_MAX_HISTORY_MESSAGES = 100;
|
|
1916
2054
|
var ParlantAdapter = class extends SimpleAdapter {
|
|
2055
|
+
provider = "parlant";
|
|
1917
2056
|
environment;
|
|
1918
2057
|
baseUrl;
|
|
1919
2058
|
agentId;
|
|
@@ -1949,7 +2088,7 @@ var ParlantAdapter = class extends SimpleAdapter {
|
|
|
1949
2088
|
this.responseTimeoutSeconds = options.responseTimeoutSeconds ?? DEFAULT_RESPONSE_TIMEOUT_SECONDS;
|
|
1950
2089
|
this.maxHistoryMessages = options.maxHistoryMessages ?? DEFAULT_MAX_HISTORY_MESSAGES;
|
|
1951
2090
|
this.clientFactory = options.clientFactory;
|
|
1952
|
-
this.logger = options.logger
|
|
2091
|
+
this.logger = resolveLogger(options.logger);
|
|
1953
2092
|
this.clientLoader = new LazyAsyncValue({
|
|
1954
2093
|
load: async () => this.createClient(),
|
|
1955
2094
|
onRejected: (error) => {
|
|
@@ -2006,40 +2145,27 @@ var ParlantAdapter = class extends SimpleAdapter {
|
|
|
2006
2145
|
createdEvent.offset
|
|
2007
2146
|
);
|
|
2008
2147
|
if (!reply) {
|
|
2009
|
-
|
|
2010
|
-
|
|
2011
|
-
"
|
|
2012
|
-
|
|
2013
|
-
|
|
2014
|
-
parlant_timeout_seconds: this.responseTimeoutSeconds
|
|
2015
|
-
}
|
|
2148
|
+
return reportTurnFailure(
|
|
2149
|
+
tools,
|
|
2150
|
+
agentFailure(this.provider, "Parlant did not return a response before timeout.", FAILURE_CODE_TIMEOUT),
|
|
2151
|
+
this.logger,
|
|
2152
|
+
{ roomId: context.roomId, agentId: this.agentId }
|
|
2016
2153
|
);
|
|
2017
|
-
return;
|
|
2018
2154
|
}
|
|
2019
|
-
await tools
|
|
2155
|
+
await deliverReply(tools, reply, [{ id: message.senderId }]);
|
|
2020
2156
|
} catch (error) {
|
|
2021
|
-
|
|
2157
|
+
rethrowIfRecoverableTurnFailure(error);
|
|
2022
2158
|
this.logger.error("Parlant adapter request failed", {
|
|
2023
2159
|
roomId: context.roomId,
|
|
2024
2160
|
agentId: this.agentId,
|
|
2025
2161
|
error
|
|
2026
2162
|
});
|
|
2027
|
-
|
|
2028
|
-
|
|
2029
|
-
|
|
2030
|
-
|
|
2031
|
-
|
|
2032
|
-
|
|
2033
|
-
}
|
|
2034
|
-
);
|
|
2035
|
-
} catch (eventError) {
|
|
2036
|
-
this.logger.warn("Parlant adapter failed to emit error event", {
|
|
2037
|
-
roomId: context.roomId,
|
|
2038
|
-
agentId: this.agentId,
|
|
2039
|
-
error: eventError
|
|
2040
|
-
});
|
|
2041
|
-
}
|
|
2042
|
-
throw error instanceof Error ? error : new Error(errorMessage);
|
|
2163
|
+
await reportTurnFailure(
|
|
2164
|
+
tools,
|
|
2165
|
+
agentFailure(this.provider, asErrorMessage(error)),
|
|
2166
|
+
this.logger,
|
|
2167
|
+
{ roomId: context.roomId, agentId: this.agentId }
|
|
2168
|
+
);
|
|
2043
2169
|
}
|
|
2044
2170
|
}
|
|
2045
2171
|
async onCleanup(roomId) {
|
|
@@ -2151,8 +2277,9 @@ var ParlantAdapter = class extends SimpleAdapter {
|
|
|
2151
2277
|
if (history.length === 0) {
|
|
2152
2278
|
return;
|
|
2153
2279
|
}
|
|
2154
|
-
const completeHistory = selectCompleteExchanges(
|
|
2155
|
-
|
|
2280
|
+
const completeHistory = selectCompleteExchanges(
|
|
2281
|
+
history,
|
|
2282
|
+
this.maxHistoryMessages
|
|
2156
2283
|
);
|
|
2157
2284
|
let failedEvents = 0;
|
|
2158
2285
|
for (const item of completeHistory) {
|
|
@@ -2283,26 +2410,6 @@ var ParlantAdapter = class extends SimpleAdapter {
|
|
|
2283
2410
|
return factory();
|
|
2284
2411
|
}
|
|
2285
2412
|
};
|
|
2286
|
-
function selectCompleteExchanges(history) {
|
|
2287
|
-
const complete = [];
|
|
2288
|
-
let index = 0;
|
|
2289
|
-
while (index < history.length) {
|
|
2290
|
-
const current = history[index];
|
|
2291
|
-
if (current.role === "user" && current.content) {
|
|
2292
|
-
const next = history[index + 1];
|
|
2293
|
-
if (next && next.role === "assistant" && next.content) {
|
|
2294
|
-
complete.push(current);
|
|
2295
|
-
complete.push(next);
|
|
2296
|
-
index += 2;
|
|
2297
|
-
continue;
|
|
2298
|
-
}
|
|
2299
|
-
index += 1;
|
|
2300
|
-
continue;
|
|
2301
|
-
}
|
|
2302
|
-
index += 1;
|
|
2303
|
-
}
|
|
2304
|
-
return complete;
|
|
2305
|
-
}
|
|
2306
2413
|
function buildUserMessage(input) {
|
|
2307
2414
|
const updates = [];
|
|
2308
2415
|
if (input.participantsMessage) {
|
|
@@ -2480,8 +2587,67 @@ function buildClaudeSdkText(raw, agentName) {
|
|
|
2480
2587
|
return lines.join("\n");
|
|
2481
2588
|
}
|
|
2482
2589
|
|
|
2590
|
+
// src/converters/acp-client.ts
|
|
2591
|
+
var ACPClientHistoryConverter = class {
|
|
2592
|
+
convert(raw) {
|
|
2593
|
+
const roomToSession = {};
|
|
2594
|
+
for (const entry of raw) {
|
|
2595
|
+
if (entry.message_type !== "task") {
|
|
2596
|
+
continue;
|
|
2597
|
+
}
|
|
2598
|
+
const metadataRaw = entry.metadata;
|
|
2599
|
+
if (!metadataRaw || typeof metadataRaw !== "object" || Array.isArray(metadataRaw)) {
|
|
2600
|
+
continue;
|
|
2601
|
+
}
|
|
2602
|
+
const metadata = metadataRaw;
|
|
2603
|
+
const sessionId = metadata.acp_client_session_id;
|
|
2604
|
+
const roomId = metadata.acp_client_room_id;
|
|
2605
|
+
if (typeof sessionId === "string" && typeof roomId === "string" && sessionId && roomId && roomId === entry.room_id) {
|
|
2606
|
+
roomToSession[roomId] = sessionId;
|
|
2607
|
+
}
|
|
2608
|
+
}
|
|
2609
|
+
return { roomToSession };
|
|
2610
|
+
}
|
|
2611
|
+
};
|
|
2612
|
+
|
|
2613
|
+
// src/converters/acp-server.ts
|
|
2614
|
+
var ACPServerHistoryConverter = class {
|
|
2615
|
+
convert(raw) {
|
|
2616
|
+
const sessionToRoom = {};
|
|
2617
|
+
const sessionCwd = {};
|
|
2618
|
+
const sessionMcpServers = {};
|
|
2619
|
+
for (const entry of raw) {
|
|
2620
|
+
const metadataRaw = entry.metadata;
|
|
2621
|
+
if (!metadataRaw || typeof metadataRaw !== "object" || Array.isArray(metadataRaw)) {
|
|
2622
|
+
continue;
|
|
2623
|
+
}
|
|
2624
|
+
const metadata = metadataRaw;
|
|
2625
|
+
const sessionId = metadata.acp_session_id;
|
|
2626
|
+
if (typeof sessionId !== "string" || sessionId.length === 0) {
|
|
2627
|
+
continue;
|
|
2628
|
+
}
|
|
2629
|
+
const roomId = typeof metadata.acp_room_id === "string" ? metadata.acp_room_id : typeof entry.room_id === "string" ? entry.room_id : null;
|
|
2630
|
+
if (roomId) {
|
|
2631
|
+
sessionToRoom[sessionId] = roomId;
|
|
2632
|
+
}
|
|
2633
|
+
if (typeof metadata.acp_cwd === "string" && metadata.acp_cwd.length > 0) {
|
|
2634
|
+
sessionCwd[sessionId] = metadata.acp_cwd;
|
|
2635
|
+
}
|
|
2636
|
+
if (Array.isArray(metadata.acp_mcp_servers)) {
|
|
2637
|
+
sessionMcpServers[sessionId] = metadata.acp_mcp_servers.filter((server) => !!server && typeof server === "object" && !Array.isArray(server));
|
|
2638
|
+
}
|
|
2639
|
+
}
|
|
2640
|
+
return {
|
|
2641
|
+
sessionToRoom,
|
|
2642
|
+
sessionCwd,
|
|
2643
|
+
sessionMcpServers
|
|
2644
|
+
};
|
|
2645
|
+
}
|
|
2646
|
+
};
|
|
2647
|
+
|
|
2483
2648
|
export {
|
|
2484
2649
|
findLatestTaskMetadata,
|
|
2650
|
+
selectCompleteExchanges,
|
|
2485
2651
|
LazyAsyncValue,
|
|
2486
2652
|
asOptionalString,
|
|
2487
2653
|
parseDate,
|
|
@@ -2501,5 +2667,7 @@ export {
|
|
|
2501
2667
|
OpencodeHistoryConverter,
|
|
2502
2668
|
extractOpencodeSessionId,
|
|
2503
2669
|
ClaudeSDKHistoryConverter,
|
|
2504
|
-
extractClaudeSessionId
|
|
2670
|
+
extractClaudeSessionId,
|
|
2671
|
+
ACPClientHistoryConverter,
|
|
2672
|
+
ACPServerHistoryConverter
|
|
2505
2673
|
};
|