@band-ai/sdk 0.2.1 → 0.3.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/dist/{ClaudeSDKAdapter-Cna5P1dR.d.ts → ClaudeSDKAdapter-CXud2DBE.d.ts} +2 -1
- package/dist/{ClaudeSDKAdapter-BY4zEbCl.d.cts → ClaudeSDKAdapter-Cx6zhSaG.d.cts} +2 -1
- package/dist/adapters.cjs +208 -115
- package/dist/adapters.d.cts +8 -4
- package/dist/adapters.d.ts +8 -4
- package/dist/adapters.js +105 -43
- package/dist/chunk-F63TPOI3.js +29 -0
- package/dist/{chunk-3BKAC4OZ.js → chunk-JADCAMZY.js} +8 -0
- package/dist/{chunk-N2QTUMGO.js → chunk-JJF44XWA.js} +365 -249
- package/dist/{chunk-TLBCKDQO.js → chunk-K5KAEYPF.js} +2 -2
- package/dist/{chunk-ZZJRRBPQ.js → chunk-KXJ74J73.js} +1 -1
- package/dist/{chunk-NMZLX7TP.js → chunk-MQBBWYRP.js} +52 -45
- package/dist/{chunk-RV76SKFT.js → chunk-MQY74R7D.js} +2 -20
- package/dist/{chunk-LBWKISBS.js → chunk-OH6VVVKT.js} +21 -0
- package/dist/{chunk-EAI2M3WM.js → chunk-W5IAI6Z4.js} +1 -1
- package/dist/{chunk-4IAXZBXX.js → chunk-WA7CHXUS.js} +2 -2
- package/dist/{chunk-NT7TBFX2.js → chunk-XWHWJP4I.js} +2 -2
- package/dist/{chunk-WLCM2OXG.js → chunk-YJ42AZO4.js} +1 -1
- package/dist/converters.js +6 -5
- package/dist/index.cjs +405 -277
- package/dist/index.d.cts +5 -5
- package/dist/index.d.ts +5 -5
- package/dist/index.js +12 -11
- package/dist/mcp-claude.js +4 -3
- package/dist/mcp.js +5 -4
- package/dist/rest.js +3 -3
- package/dist/runtime.cjs +387 -362
- package/dist/runtime.d.cts +10 -39
- package/dist/runtime.d.ts +10 -39
- package/dist/runtime.js +20 -142
- package/dist/{schemas-BotL3ZLH.d.cts → schemas-BgJhlqqO.d.cts} +57 -13
- package/dist/{schemas-DBsC4J1g.d.ts → schemas-C4mK1WSs.d.ts} +57 -13
- package/dist/testing.cjs +11 -0
- package/dist/testing.js +8 -1
- package/dist/{types-D958TC71.d.cts → types-BNNtOXu3.d.cts} +1 -1
- package/dist/{types-BTN_ZETM.d.ts → types-DFUtpxah.d.ts} +1 -1
- package/package.json +2 -2
package/dist/adapters.js
CHANGED
|
@@ -23,14 +23,15 @@ import {
|
|
|
23
23
|
ToolCallingAdapter,
|
|
24
24
|
VercelAISDKAdapter,
|
|
25
25
|
VercelAISDKToolCallingModel,
|
|
26
|
-
runSingleToolRound
|
|
27
|
-
|
|
26
|
+
runSingleToolRound,
|
|
27
|
+
systemUpdateParts
|
|
28
|
+
} from "./chunk-MQBBWYRP.js";
|
|
28
29
|
import {
|
|
29
30
|
BandMcpServer,
|
|
30
31
|
BandMcpSseServer,
|
|
31
32
|
generateAuthToken
|
|
32
|
-
} from "./chunk-
|
|
33
|
-
import "./chunk-
|
|
33
|
+
} from "./chunk-WA7CHXUS.js";
|
|
34
|
+
import "./chunk-XWHWJP4I.js";
|
|
34
35
|
import {
|
|
35
36
|
ACPClientHistoryConverter,
|
|
36
37
|
ACPServerHistoryConverter
|
|
@@ -48,21 +49,26 @@ import {
|
|
|
48
49
|
createGatewayServer,
|
|
49
50
|
parseToolCall,
|
|
50
51
|
parseToolResult
|
|
51
|
-
} from "./chunk-
|
|
52
|
+
} from "./chunk-K5KAEYPF.js";
|
|
52
53
|
import {
|
|
53
54
|
SimpleAdapter
|
|
54
55
|
} from "./chunk-AVVDPXP4.js";
|
|
55
56
|
import {
|
|
56
|
-
ensureHandlePrefix
|
|
57
|
-
|
|
57
|
+
ensureHandlePrefix,
|
|
58
|
+
mentionSubjectsFromMetadata,
|
|
59
|
+
replaceUuidMentions
|
|
60
|
+
} from "./chunk-OH6VVVKT.js";
|
|
58
61
|
import {
|
|
59
62
|
renderSystemPrompt
|
|
60
|
-
} from "./chunk-
|
|
63
|
+
} from "./chunk-YJ42AZO4.js";
|
|
61
64
|
import {
|
|
62
65
|
MCP_SERVER_NAME
|
|
63
|
-
} from "./chunk-
|
|
64
|
-
import
|
|
65
|
-
|
|
66
|
+
} from "./chunk-MQY74R7D.js";
|
|
67
|
+
import {
|
|
68
|
+
isBlankEventContent
|
|
69
|
+
} from "./chunk-F63TPOI3.js";
|
|
70
|
+
import "./chunk-KXJ74J73.js";
|
|
71
|
+
import "./chunk-JADCAMZY.js";
|
|
66
72
|
import {
|
|
67
73
|
NoopLogger
|
|
68
74
|
} from "./chunk-OD2G5LFQ.js";
|
|
@@ -75,6 +81,21 @@ import {
|
|
|
75
81
|
import { spawn } from "child_process";
|
|
76
82
|
import { Readable, Writable } from "stream";
|
|
77
83
|
|
|
84
|
+
// src/adapters/shared/withTimeout.ts
|
|
85
|
+
async function withTimeout(promise, timeoutMs, message) {
|
|
86
|
+
let timer;
|
|
87
|
+
try {
|
|
88
|
+
return await Promise.race([
|
|
89
|
+
promise,
|
|
90
|
+
new Promise((_, reject) => {
|
|
91
|
+
timer = setTimeout(() => reject(new Error(message)), timeoutMs);
|
|
92
|
+
})
|
|
93
|
+
]);
|
|
94
|
+
} finally {
|
|
95
|
+
clearTimeout(timer);
|
|
96
|
+
}
|
|
97
|
+
}
|
|
98
|
+
|
|
78
99
|
// src/adapters/acp/types.ts
|
|
79
100
|
var DEFAULT_ACP_SERVER_MODES = [
|
|
80
101
|
{
|
|
@@ -348,6 +369,7 @@ var acpModule = new LazyAsyncValue({
|
|
|
348
369
|
|
|
349
370
|
// src/adapters/acp/ACPClientAdapter.ts
|
|
350
371
|
var DEFAULT_PERMISSION_TIMEOUT_MS = 5 * 6e4;
|
|
372
|
+
var SET_SESSION_MODE_TIMEOUT_MS = 1e4;
|
|
351
373
|
var ACPClientAdapter = class extends SimpleAdapter {
|
|
352
374
|
command;
|
|
353
375
|
cwd;
|
|
@@ -366,6 +388,7 @@ var ACPClientAdapter = class extends SimpleAdapter {
|
|
|
366
388
|
pendingPermissions = /* @__PURE__ */ new Map();
|
|
367
389
|
resolvePermission;
|
|
368
390
|
permissionTimeoutMs;
|
|
391
|
+
requestedPermissionMode;
|
|
369
392
|
logger;
|
|
370
393
|
backend = null;
|
|
371
394
|
backendPromise = null;
|
|
@@ -396,6 +419,10 @@ var ACPClientAdapter = class extends SimpleAdapter {
|
|
|
396
419
|
this.resolvePermission = options.resolvePermission;
|
|
397
420
|
this.logger = options.logger ?? new NoopLogger();
|
|
398
421
|
this.permissionTimeoutMs = options.permissionTimeoutMs ?? DEFAULT_PERMISSION_TIMEOUT_MS;
|
|
422
|
+
this.requestedPermissionMode = options.requestedPermissionMode;
|
|
423
|
+
if (this.requestedPermissionMode !== void 0 && this.requestedPermissionMode.length === 0) {
|
|
424
|
+
throw new ValidationError("requestedPermissionMode must be a non-empty mode id, got an empty string");
|
|
425
|
+
}
|
|
399
426
|
if (this.resolvePermission && (!Number.isFinite(this.permissionTimeoutMs) || this.permissionTimeoutMs <= 0)) {
|
|
400
427
|
throw new ValidationError(`permissionTimeoutMs must be a positive finite number, got ${options.permissionTimeoutMs}`);
|
|
401
428
|
}
|
|
@@ -410,7 +437,7 @@ var ACPClientAdapter = class extends SimpleAdapter {
|
|
|
410
437
|
});
|
|
411
438
|
await this.ensureConnection();
|
|
412
439
|
}
|
|
413
|
-
async onMessage(message, tools, history,
|
|
440
|
+
async onMessage(message, tools, history, participantsMessage, contactsMessage, context) {
|
|
414
441
|
if (context.isSessionBootstrap) {
|
|
415
442
|
this.rehydrate(history);
|
|
416
443
|
}
|
|
@@ -426,9 +453,11 @@ var ACPClientAdapter = class extends SimpleAdapter {
|
|
|
426
453
|
sessionId,
|
|
427
454
|
(params) => this.handlePermissionRequest(tools, context.roomId, params)
|
|
428
455
|
);
|
|
429
|
-
const
|
|
456
|
+
const content = replaceUuidMentions(message.content, mentionSubjectsFromMetadata(message.metadata));
|
|
457
|
+
const messageWithContext = [...systemUpdateParts(participantsMessage, contactsMessage), content].join("\n\n");
|
|
458
|
+
const promptText = this.bootstrappedSessions.has(sessionId) ? messageWithContext : `${this.buildSystemContext(context.roomId, message)}
|
|
430
459
|
|
|
431
|
-
${
|
|
460
|
+
${messageWithContext}`;
|
|
432
461
|
this.bootstrappedSessions.add(sessionId);
|
|
433
462
|
try {
|
|
434
463
|
await connection.prompt({
|
|
@@ -555,9 +584,10 @@ ${message.content}`;
|
|
|
555
584
|
const mcpServers = await this.buildSessionMcpServers();
|
|
556
585
|
if (existingSessionId) {
|
|
557
586
|
const restored = await this.tryRestoreSession(connection, existingSessionId, mcpServers);
|
|
558
|
-
if (restored) {
|
|
587
|
+
if (restored.ok) {
|
|
559
588
|
this.activeSessions.add(existingSessionId);
|
|
560
589
|
this.bootstrappedSessions.add(existingSessionId);
|
|
590
|
+
await this.applyRequestedPermissionMode(connection, existingSessionId, restored.modes);
|
|
561
591
|
return existingSessionId;
|
|
562
592
|
}
|
|
563
593
|
}
|
|
@@ -567,30 +597,52 @@ ${message.content}`;
|
|
|
567
597
|
});
|
|
568
598
|
this.roomToSession.set(roomId, created.sessionId);
|
|
569
599
|
this.activeSessions.add(created.sessionId);
|
|
600
|
+
await this.applyRequestedPermissionMode(connection, created.sessionId, created.modes);
|
|
570
601
|
return created.sessionId;
|
|
571
602
|
}
|
|
572
603
|
async tryRestoreSession(connection, sessionId, mcpServers) {
|
|
604
|
+
const capabilities = this.connectionState?.agentCapabilities;
|
|
605
|
+
const params = { cwd: this.cwd, mcpServers, sessionId };
|
|
606
|
+
const restore = capabilities?.loadSession ? () => connection.loadSession(params) : capabilities?.sessionCapabilities?.resume ? () => connection.unstable_resumeSession(params) : null;
|
|
607
|
+
if (!restore) {
|
|
608
|
+
return { ok: false };
|
|
609
|
+
}
|
|
573
610
|
try {
|
|
574
|
-
|
|
575
|
-
|
|
576
|
-
cwd: this.cwd,
|
|
577
|
-
mcpServers,
|
|
578
|
-
sessionId
|
|
579
|
-
});
|
|
580
|
-
return true;
|
|
581
|
-
}
|
|
582
|
-
if (this.connectionState?.agentCapabilities?.sessionCapabilities?.resume) {
|
|
583
|
-
await connection.unstable_resumeSession({
|
|
584
|
-
cwd: this.cwd,
|
|
585
|
-
mcpServers,
|
|
586
|
-
sessionId
|
|
587
|
-
});
|
|
588
|
-
return true;
|
|
589
|
-
}
|
|
611
|
+
const restored = await restore();
|
|
612
|
+
return { ok: true, modes: restored?.modes };
|
|
590
613
|
} catch {
|
|
591
|
-
return false;
|
|
614
|
+
return { ok: false };
|
|
615
|
+
}
|
|
616
|
+
}
|
|
617
|
+
// Best-effort: never throws, so a mode switch going wrong can't take a
|
|
618
|
+
// session establishment down with it.
|
|
619
|
+
async applyRequestedPermissionMode(connection, sessionId, modes) {
|
|
620
|
+
const requestedModeId = this.requestedPermissionMode;
|
|
621
|
+
if (!requestedModeId || !modes || modes.currentModeId === requestedModeId) {
|
|
622
|
+
return;
|
|
623
|
+
}
|
|
624
|
+
const availableModes = Array.isArray(modes.availableModes) ? modes.availableModes : [];
|
|
625
|
+
if (!availableModes.some((mode) => mode?.id === requestedModeId)) {
|
|
626
|
+
this.safeWarn("requested permission mode is not advertised by this session", {
|
|
627
|
+
sessionId,
|
|
628
|
+
requestedModeId,
|
|
629
|
+
availableModeIds: availableModes.map((mode) => mode?.id)
|
|
630
|
+
});
|
|
631
|
+
return;
|
|
632
|
+
}
|
|
633
|
+
try {
|
|
634
|
+
await withTimeout(
|
|
635
|
+
connection.setSessionMode({ sessionId, modeId: requestedModeId }),
|
|
636
|
+
SET_SESSION_MODE_TIMEOUT_MS,
|
|
637
|
+
`setSessionMode did not respond within ${SET_SESSION_MODE_TIMEOUT_MS}ms`
|
|
638
|
+
);
|
|
639
|
+
} catch (error) {
|
|
640
|
+
this.safeWarn("failed to switch session into the requested permission mode", {
|
|
641
|
+
sessionId,
|
|
642
|
+
requestedModeId,
|
|
643
|
+
error: String(error)
|
|
644
|
+
});
|
|
592
645
|
}
|
|
593
|
-
return false;
|
|
594
646
|
}
|
|
595
647
|
async buildSessionMcpServers() {
|
|
596
648
|
const mcpServers = [...this.mcpServers];
|
|
@@ -729,6 +781,18 @@ ${message.content}`;
|
|
|
729
781
|
const matched = chosenId !== void 0 && options.some((option) => option.optionId === chosenId);
|
|
730
782
|
return matched ? { outcome: { outcome: "selected", optionId: chosenId } } : { outcome: { outcome: "cancelled" } };
|
|
731
783
|
}
|
|
784
|
+
// A caller-supplied `Logger` isn't guaranteed to be synchronous or
|
|
785
|
+
// non-throwing. Every best-effort warning in this file routes through here
|
|
786
|
+
// so one failing sink — a synchronous throw, or an `async` implementation
|
|
787
|
+
// rejecting (the `Logger` interface's `void` return type permits either;
|
|
788
|
+
// a bare try/catch only ever catches the former) — can't turn a warning
|
|
789
|
+
// into an unhandled rejection in its place.
|
|
790
|
+
safeWarn(message, context) {
|
|
791
|
+
try {
|
|
792
|
+
Promise.resolve(this.logger.warn(message, context)).catch(() => void 0);
|
|
793
|
+
} catch {
|
|
794
|
+
}
|
|
795
|
+
}
|
|
732
796
|
// Races the caller-supplied resolver against a timeout and against
|
|
733
797
|
// `controller`'s own abort signal — aborted externally by
|
|
734
798
|
// `cancelPendingPermissions`/`cancelAllPendingPermissions` (fired from
|
|
@@ -752,10 +816,7 @@ ${message.content}`;
|
|
|
752
816
|
// rejected promise, so both land in the `.catch` below rather than
|
|
753
817
|
// escaping this race uncaught.
|
|
754
818
|
Promise.resolve().then(() => this.resolvePermission(params, controller.signal)).catch((error) => {
|
|
755
|
-
|
|
756
|
-
this.logger.warn("resolvePermission threw; treating as no answer", { error: String(error) });
|
|
757
|
-
} catch {
|
|
758
|
-
}
|
|
819
|
+
this.safeWarn("resolvePermission threw; treating as no answer", { error: String(error) });
|
|
759
820
|
return void 0;
|
|
760
821
|
}),
|
|
761
822
|
timeout,
|
|
@@ -795,13 +856,14 @@ ${message.content}`;
|
|
|
795
856
|
return;
|
|
796
857
|
}
|
|
797
858
|
for (const chunk of client.getCollectedChunks(input.sessionId)) {
|
|
859
|
+
if (isBlankEventContent(chunk.content)) {
|
|
860
|
+
continue;
|
|
861
|
+
}
|
|
798
862
|
if (chunk.chunkType === "text") {
|
|
799
|
-
|
|
800
|
-
|
|
801
|
-
|
|
802
|
-
|
|
803
|
-
}]);
|
|
804
|
-
}
|
|
863
|
+
await input.tools.sendMessage(chunk.content, [{
|
|
864
|
+
id: input.senderId,
|
|
865
|
+
handle: input.senderHandle
|
|
866
|
+
}]);
|
|
805
867
|
continue;
|
|
806
868
|
}
|
|
807
869
|
const messageType = chunk.chunkType === "plan" ? "task" : chunk.chunkType;
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
import {
|
|
2
|
+
ValidationError
|
|
3
|
+
} from "./chunk-JY75VSQK.js";
|
|
4
|
+
|
|
5
|
+
// src/contracts/chatEvents.ts
|
|
6
|
+
var CHAT_EVENT_TYPES = ["tool_call", "tool_result", "thought", "error", "task"];
|
|
7
|
+
var CHAT_MESSAGE_TYPES = ["text", ...CHAT_EVENT_TYPES];
|
|
8
|
+
function isChatEventType(value) {
|
|
9
|
+
return CHAT_EVENT_TYPES.includes(value);
|
|
10
|
+
}
|
|
11
|
+
function assertChatEventType(value) {
|
|
12
|
+
if (!isChatEventType(value)) {
|
|
13
|
+
throw new ValidationError(
|
|
14
|
+
`Invalid event message_type '${value}'. Expected one of: ${CHAT_EVENT_TYPES.join(", ")}`
|
|
15
|
+
);
|
|
16
|
+
}
|
|
17
|
+
}
|
|
18
|
+
var VISIBLE_CONTENT_PATTERN = /[\p{L}\p{N}\p{P}\p{S}]/u;
|
|
19
|
+
function isBlankEventContent(content) {
|
|
20
|
+
return !VISIBLE_CONTENT_PATTERN.test(content);
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
export {
|
|
24
|
+
CHAT_EVENT_TYPES,
|
|
25
|
+
CHAT_MESSAGE_TYPES,
|
|
26
|
+
isChatEventType,
|
|
27
|
+
assertChatEventType,
|
|
28
|
+
isBlankEventContent
|
|
29
|
+
};
|
|
@@ -21,6 +21,13 @@ function isToolExecutorError(value) {
|
|
|
21
21
|
const candidate = value;
|
|
22
22
|
return candidate.ok === false && typeof candidate.errorType === "string" && TOOL_EXECUTOR_ERROR_TYPES.includes(candidate.errorType) && typeof candidate.toolName === "string" && typeof candidate.message === "string" && typeof candidate.legacyMessage === "string";
|
|
23
23
|
}
|
|
24
|
+
function isStructuredToolFailure(value) {
|
|
25
|
+
if (!value || typeof value !== "object") {
|
|
26
|
+
return false;
|
|
27
|
+
}
|
|
28
|
+
const payload = value;
|
|
29
|
+
return payload.ok === false && typeof payload.message === "string";
|
|
30
|
+
}
|
|
24
31
|
function toLegacyToolExecutorErrorMessage(value) {
|
|
25
32
|
if (typeof value === "string") {
|
|
26
33
|
return value;
|
|
@@ -39,6 +46,7 @@ var DEFAULT_AGENT_TOOLS_CAPABILITIES = {
|
|
|
39
46
|
export {
|
|
40
47
|
createToolExecutorError,
|
|
41
48
|
isToolExecutorError,
|
|
49
|
+
isStructuredToolFailure,
|
|
42
50
|
toLegacyToolExecutorErrorMessage,
|
|
43
51
|
DEFAULT_AGENT_TOOLS_CAPABILITIES
|
|
44
52
|
};
|