@band-ai/sdk 0.1.10 → 0.2.1
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 -54
- package/dist/{ClaudeSDKAdapter-DfjaI5ke.d.cts → ClaudeSDKAdapter-BY4zEbCl.d.cts} +12 -10
- package/dist/{ClaudeSDKAdapter-DonPGJ43.d.ts → ClaudeSDKAdapter-Cna5P1dR.d.ts} +12 -10
- package/dist/{acp-server-NZAeg-WO.d.ts → acp-server-CiUqN3G3.d.ts} +2 -2
- package/dist/{acp-server-CUBXIiG6.d.cts → acp-server-Dlj7D563.d.cts} +2 -2
- package/dist/adapters.cjs +387 -238
- package/dist/adapters.d.cts +36 -21
- package/dist/adapters.d.ts +36 -21
- package/dist/adapters.js +168 -65
- package/dist/backends-D-dBdDm-.d.ts +27 -0
- package/dist/backends-ZLxmQrTZ.d.cts +27 -0
- package/dist/{chunk-2BHHR6YW.js → chunk-4IAXZBXX.js} +62 -23
- package/dist/{chunk-SG4WLD2H.js → chunk-EAI2M3WM.js} +38 -94
- package/dist/{chunk-YR3BOQNW.js → chunk-JY75VSQK.js} +7 -7
- package/dist/{chunk-RDM4TE4B.js → chunk-LBWKISBS.js} +19 -1
- package/dist/{chunk-FP237EAG.js → chunk-N2QTUMGO.js} +112 -195
- package/dist/{chunk-J3M3PFFY.js → chunk-NMZLX7TP.js} +35 -31
- package/dist/{chunk-6RXWL6TC.js → chunk-NT7TBFX2.js} +1 -1
- package/dist/{chunk-MLROFDKR.js → chunk-RV76SKFT.js} +39 -33
- package/dist/{chunk-XA4N2JPH.js → chunk-TLBCKDQO.js} +23 -23
- package/dist/{chunk-IZPV6QS6.js → chunk-WL2HNJZ6.js} +38 -11
- package/dist/{chunk-DNPVCR3S.js → chunk-WLCM2OXG.js} +31 -31
- package/dist/config.cjs +40 -13
- package/dist/config.d.cts +7 -1
- package/dist/config.d.ts +7 -1
- package/dist/config.js +2 -2
- package/dist/converters.cjs +61 -61
- package/dist/converters.d.cts +5 -5
- package/dist/converters.d.ts +5 -5
- package/dist/converters.js +4 -4
- package/dist/core.cjs +8 -8
- package/dist/core.d.cts +9 -9
- package/dist/core.d.ts +9 -9
- package/dist/core.js +3 -3
- package/dist/{dtos-Dd_fTfLn.d.cts → dtos-B8KU_q4d.d.cts} +2 -2
- package/dist/{dtos-Dd_fTfLn.d.ts → dtos-B8KU_q4d.d.ts} +2 -2
- package/dist/index.cjs +459 -504
- package/dist/index.d.cts +16 -15
- package/dist/index.d.ts +16 -15
- package/dist/index.js +15 -13
- package/dist/linear.cjs +74 -74
- package/dist/linear.d.cts +14 -14
- package/dist/linear.d.ts +14 -14
- package/dist/linear.js +72 -72
- package/dist/mcp-claude.cjs +37 -36
- package/dist/mcp-claude.d.cts +3 -3
- package/dist/mcp-claude.d.ts +3 -3
- package/dist/mcp-claude.js +7 -6
- package/dist/mcp.cjs +103 -62
- package/dist/mcp.d.cts +29 -16
- package/dist/mcp.d.ts +29 -16
- package/dist/mcp.js +14 -14
- package/dist/{opencode--iA5-KYk.d.cts → opencode-2YdscIc1.d.cts} +5 -5
- package/dist/{opencode-YNacv-eJ.d.ts → opencode-Bld62x5t.d.ts} +5 -5
- package/dist/{pagination-BBLsYLhT.d.ts → pagination-BgEx-HeL.d.ts} +2 -2
- package/dist/{pagination-CqidD-L_.d.cts → pagination-DqdkQArT.d.cts} +2 -2
- package/dist/{protocols-BF6jamIl.d.ts → protocols-Bwwcql0h.d.ts} +1 -1
- package/dist/{protocols-D2bTrQ_t.d.cts → protocols-Bz1rxcUg.d.cts} +1 -1
- package/dist/rest.cjs +41 -97
- package/dist/rest.d.cts +7 -7
- package/dist/rest.d.ts +7 -7
- package/dist/rest.js +2 -2
- package/dist/runtime.cjs +293 -464
- package/dist/runtime.d.cts +16 -28
- package/dist/runtime.d.ts +16 -28
- package/dist/runtime.js +12 -63
- package/dist/{schemas-CI0qgcp_.d.cts → schemas-BotL3ZLH.d.cts} +40 -54
- package/dist/{schemas-B1Fd3oUM.d.ts → schemas-DBsC4J1g.d.ts} +40 -54
- package/dist/{sdk-D2rTDU_o.d.cts → sdk-BTciSLRQ.d.cts} +5 -5
- package/dist/{sdk-CyqN1W5g.d.ts → sdk-qKJtMma_.d.ts} +5 -5
- package/dist/{simpleAdapter-qQt-tSz4.d.ts → simpleAdapter--wznuoOw.d.ts} +1 -1
- package/dist/{simpleAdapter-C_f-01Cu.d.cts → simpleAdapter-BpT4XbZC.d.cts} +1 -1
- package/dist/testing.d.cts +3 -3
- package/dist/testing.d.ts +3 -3
- package/dist/{types-DNySTI_8.d.ts → types-BTN_ZETM.d.ts} +2 -2
- package/dist/{types-D3AsUnd0.d.ts → types-BgYFd_Yw.d.cts} +5 -5
- package/dist/{types-DtMms5Fi.d.cts → types-BivGO7I9.d.ts} +5 -5
- package/dist/{types-CKqrhGB1.d.cts → types-D958TC71.d.cts} +2 -2
- package/package.json +6 -5
- package/dist/backends-DYtEhCZG.d.cts +0 -25
- package/dist/backends-oYAb7EU-.d.ts +0 -25
package/dist/adapters.js
CHANGED
|
@@ -24,12 +24,13 @@ import {
|
|
|
24
24
|
VercelAISDKAdapter,
|
|
25
25
|
VercelAISDKToolCallingModel,
|
|
26
26
|
runSingleToolRound
|
|
27
|
-
} from "./chunk-
|
|
27
|
+
} from "./chunk-NMZLX7TP.js";
|
|
28
28
|
import {
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
29
|
+
BandMcpServer,
|
|
30
|
+
BandMcpSseServer,
|
|
31
|
+
generateAuthToken
|
|
32
|
+
} from "./chunk-4IAXZBXX.js";
|
|
33
|
+
import "./chunk-NT7TBFX2.js";
|
|
33
34
|
import {
|
|
34
35
|
ACPClientHistoryConverter,
|
|
35
36
|
ACPServerHistoryConverter
|
|
@@ -47,23 +48,28 @@ import {
|
|
|
47
48
|
createGatewayServer,
|
|
48
49
|
parseToolCall,
|
|
49
50
|
parseToolResult
|
|
50
|
-
} from "./chunk-
|
|
51
|
+
} from "./chunk-TLBCKDQO.js";
|
|
51
52
|
import {
|
|
52
53
|
SimpleAdapter
|
|
53
54
|
} from "./chunk-AVVDPXP4.js";
|
|
54
55
|
import {
|
|
55
56
|
ensureHandlePrefix
|
|
56
|
-
} from "./chunk-
|
|
57
|
+
} from "./chunk-LBWKISBS.js";
|
|
57
58
|
import {
|
|
58
59
|
renderSystemPrompt
|
|
59
|
-
} from "./chunk-
|
|
60
|
-
import
|
|
60
|
+
} from "./chunk-WLCM2OXG.js";
|
|
61
|
+
import {
|
|
62
|
+
MCP_SERVER_NAME
|
|
63
|
+
} from "./chunk-RV76SKFT.js";
|
|
61
64
|
import "./chunk-ZZJRRBPQ.js";
|
|
62
65
|
import "./chunk-3BKAC4OZ.js";
|
|
63
|
-
import "./chunk-OD2G5LFQ.js";
|
|
64
66
|
import {
|
|
65
|
-
|
|
66
|
-
} from "./chunk-
|
|
67
|
+
NoopLogger
|
|
68
|
+
} from "./chunk-OD2G5LFQ.js";
|
|
69
|
+
import {
|
|
70
|
+
UnsupportedFeatureError,
|
|
71
|
+
ValidationError
|
|
72
|
+
} from "./chunk-JY75VSQK.js";
|
|
67
73
|
|
|
68
74
|
// src/adapters/acp/ACPClientAdapter.ts
|
|
69
75
|
import { spawn } from "child_process";
|
|
@@ -129,7 +135,7 @@ function normalizeMcpServers(mcpServers) {
|
|
|
129
135
|
}
|
|
130
136
|
|
|
131
137
|
// src/adapters/acp/client.ts
|
|
132
|
-
var
|
|
138
|
+
var BandACPClient = class {
|
|
133
139
|
sessionChunks = /* @__PURE__ */ new Map();
|
|
134
140
|
permissionHandlers = /* @__PURE__ */ new Map();
|
|
135
141
|
async sessionUpdate(params) {
|
|
@@ -341,6 +347,7 @@ var acpModule = new LazyAsyncValue({
|
|
|
341
347
|
});
|
|
342
348
|
|
|
343
349
|
// src/adapters/acp/ACPClientAdapter.ts
|
|
350
|
+
var DEFAULT_PERMISSION_TIMEOUT_MS = 5 * 6e4;
|
|
344
351
|
var ACPClientAdapter = class extends SimpleAdapter {
|
|
345
352
|
command;
|
|
346
353
|
cwd;
|
|
@@ -356,7 +363,12 @@ var ACPClientAdapter = class extends SimpleAdapter {
|
|
|
356
363
|
roomTools = /* @__PURE__ */ new Map();
|
|
357
364
|
activeSessions = /* @__PURE__ */ new Set();
|
|
358
365
|
bootstrappedSessions = /* @__PURE__ */ new Set();
|
|
366
|
+
pendingPermissions = /* @__PURE__ */ new Map();
|
|
367
|
+
resolvePermission;
|
|
368
|
+
permissionTimeoutMs;
|
|
369
|
+
logger;
|
|
359
370
|
backend = null;
|
|
371
|
+
backendPromise = null;
|
|
360
372
|
client = null;
|
|
361
373
|
connectionHandle = null;
|
|
362
374
|
connection = null;
|
|
@@ -381,6 +393,12 @@ var ACPClientAdapter = class extends SimpleAdapter {
|
|
|
381
393
|
this.additionalMcpTools = [...options.additionalMcpTools ?? []];
|
|
382
394
|
this.clientCapabilities = options.clientCapabilities;
|
|
383
395
|
this.connectionFactory = options.connectionFactory ?? createSubprocessConnection;
|
|
396
|
+
this.resolvePermission = options.resolvePermission;
|
|
397
|
+
this.logger = options.logger ?? new NoopLogger();
|
|
398
|
+
this.permissionTimeoutMs = options.permissionTimeoutMs ?? DEFAULT_PERMISSION_TIMEOUT_MS;
|
|
399
|
+
if (this.resolvePermission && (!Number.isFinite(this.permissionTimeoutMs) || this.permissionTimeoutMs <= 0)) {
|
|
400
|
+
throw new ValidationError(`permissionTimeoutMs must be a positive finite number, got ${options.permissionTimeoutMs}`);
|
|
401
|
+
}
|
|
384
402
|
}
|
|
385
403
|
async onStarted(agentName, agentDescription) {
|
|
386
404
|
await super.onStarted(agentName, agentDescription);
|
|
@@ -446,6 +464,7 @@ ${message.content}`;
|
|
|
446
464
|
this.activeSessions.delete(sessionId);
|
|
447
465
|
this.bootstrappedSessions.delete(sessionId);
|
|
448
466
|
this.client?.setPermissionHandler(sessionId, void 0);
|
|
467
|
+
this.cancelPendingPermissions(sessionId);
|
|
449
468
|
}
|
|
450
469
|
}
|
|
451
470
|
async onRuntimeStop() {
|
|
@@ -458,6 +477,7 @@ ${message.content}`;
|
|
|
458
477
|
this.bootstrappedSessions.clear();
|
|
459
478
|
this.roomToSession.clear();
|
|
460
479
|
this.roomTools.clear();
|
|
480
|
+
this.cancelAllPendingPermissions();
|
|
461
481
|
this.client = null;
|
|
462
482
|
this.connection = null;
|
|
463
483
|
if (this.backend) {
|
|
@@ -497,7 +517,7 @@ ${message.content}`;
|
|
|
497
517
|
}
|
|
498
518
|
async spawnConnection() {
|
|
499
519
|
const acp = await acpModule.get();
|
|
500
|
-
const client = new
|
|
520
|
+
const client = new BandACPClient();
|
|
501
521
|
const handle = await this.connectionFactory(client, {
|
|
502
522
|
command: this.command,
|
|
503
523
|
cwd: this.cwd,
|
|
@@ -529,11 +549,11 @@ ${message.content}`;
|
|
|
529
549
|
}
|
|
530
550
|
async getOrCreateSession(roomId, connection) {
|
|
531
551
|
const existingSessionId = this.roomToSession.get(roomId);
|
|
552
|
+
if (existingSessionId && this.activeSessions.has(existingSessionId)) {
|
|
553
|
+
return existingSessionId;
|
|
554
|
+
}
|
|
532
555
|
const mcpServers = await this.buildSessionMcpServers();
|
|
533
556
|
if (existingSessionId) {
|
|
534
|
-
if (this.activeSessions.has(existingSessionId)) {
|
|
535
|
-
return existingSessionId;
|
|
536
|
-
}
|
|
537
557
|
const restored = await this.tryRestoreSession(connection, existingSessionId, mcpServers);
|
|
538
558
|
if (restored) {
|
|
539
559
|
this.activeSessions.add(existingSessionId);
|
|
@@ -581,26 +601,26 @@ ${message.content}`;
|
|
|
581
601
|
if (backend.kind === "http") {
|
|
582
602
|
const url = backend.server.url;
|
|
583
603
|
if (!url) {
|
|
584
|
-
throw new Error("
|
|
604
|
+
throw new Error("Band MCP HTTP backend did not expose a URL");
|
|
585
605
|
}
|
|
586
606
|
mcpServers.push({
|
|
587
607
|
type: "http",
|
|
588
|
-
name:
|
|
608
|
+
name: MCP_SERVER_NAME,
|
|
589
609
|
url,
|
|
590
|
-
headers: []
|
|
610
|
+
headers: [{ name: "Authorization", value: `Bearer ${backend.authToken}` }]
|
|
591
611
|
});
|
|
592
612
|
return mcpServers;
|
|
593
613
|
}
|
|
594
614
|
if (backend.kind === "sse") {
|
|
595
615
|
const url = backend.server.sseUrl;
|
|
596
616
|
if (!url) {
|
|
597
|
-
throw new Error("
|
|
617
|
+
throw new Error("Band MCP SSE backend did not expose a URL");
|
|
598
618
|
}
|
|
599
619
|
mcpServers.push({
|
|
600
620
|
type: "sse",
|
|
601
|
-
name:
|
|
621
|
+
name: MCP_SERVER_NAME,
|
|
602
622
|
url,
|
|
603
|
-
headers: []
|
|
623
|
+
headers: [{ name: "Authorization", value: `Bearer ${backend.authToken}` }]
|
|
604
624
|
});
|
|
605
625
|
return mcpServers;
|
|
606
626
|
}
|
|
@@ -610,34 +630,51 @@ ${message.content}`;
|
|
|
610
630
|
if (this.backend) {
|
|
611
631
|
return this.backend;
|
|
612
632
|
}
|
|
613
|
-
|
|
633
|
+
this.backendPromise ??= this.createBackend().finally(() => {
|
|
634
|
+
this.backendPromise = null;
|
|
635
|
+
});
|
|
636
|
+
return this.backendPromise;
|
|
637
|
+
}
|
|
638
|
+
async createBackend() {
|
|
639
|
+
const mcpCapabilities = this.connectionState?.agentCapabilities?.mcpCapabilities;
|
|
640
|
+
const transport = mcpCapabilities?.http ? "http" : mcpCapabilities?.sse ? "sse" : null;
|
|
641
|
+
if (transport === null) {
|
|
642
|
+
throw new Error(
|
|
643
|
+
"ACP agent does not advertise MCP transport support: its initialize response has mcpCapabilities.http and .sse both false or missing, so Band tools cannot be exposed to it over MCP."
|
|
644
|
+
);
|
|
645
|
+
}
|
|
646
|
+
const authToken = generateAuthToken();
|
|
614
647
|
if (transport === "sse") {
|
|
615
|
-
const server2 = new
|
|
648
|
+
const server2 = new BandMcpSseServer({
|
|
616
649
|
tools: (roomId) => this.roomTools.get(roomId),
|
|
617
650
|
enableMemoryTools: this.enableMemoryTools,
|
|
618
651
|
enableContactTools: true,
|
|
619
|
-
additionalTools: this.additionalMcpTools
|
|
652
|
+
additionalTools: this.additionalMcpTools,
|
|
653
|
+
authToken
|
|
620
654
|
});
|
|
621
655
|
await server2.start();
|
|
622
656
|
this.backend = {
|
|
623
657
|
kind: "sse",
|
|
624
658
|
server: server2,
|
|
659
|
+
authToken,
|
|
625
660
|
stop: async () => {
|
|
626
661
|
await server2.stop();
|
|
627
662
|
}
|
|
628
663
|
};
|
|
629
664
|
return this.backend;
|
|
630
665
|
}
|
|
631
|
-
const server = new
|
|
666
|
+
const server = new BandMcpServer({
|
|
632
667
|
tools: (roomId) => this.roomTools.get(roomId),
|
|
633
668
|
enableMemoryTools: this.enableMemoryTools,
|
|
634
669
|
enableContactTools: true,
|
|
635
|
-
additionalTools: this.additionalMcpTools
|
|
670
|
+
additionalTools: this.additionalMcpTools,
|
|
671
|
+
authToken
|
|
636
672
|
});
|
|
637
673
|
await server.start();
|
|
638
674
|
this.backend = {
|
|
639
675
|
kind: "http",
|
|
640
676
|
server,
|
|
677
|
+
authToken,
|
|
641
678
|
stop: async () => {
|
|
642
679
|
await server.stop();
|
|
643
680
|
}
|
|
@@ -652,39 +689,105 @@ ${message.content}`;
|
|
|
652
689
|
this.systemPrompt,
|
|
653
690
|
"",
|
|
654
691
|
"## Room Context",
|
|
655
|
-
"You are connected to
|
|
656
|
-
"Use the
|
|
692
|
+
"You are connected to Band using Band MCP tools.",
|
|
693
|
+
"Use the Band tools for any visible room action. Plain text output is not posted back to the room.",
|
|
657
694
|
"",
|
|
658
695
|
`Current room_id: ${roomId}`,
|
|
659
696
|
`Current requester name: ${requesterName}`,
|
|
660
697
|
`Current requester id: ${requesterId}`,
|
|
661
698
|
"",
|
|
662
|
-
"All
|
|
699
|
+
"All Band MCP tool calls must include room_id."
|
|
663
700
|
].join("\n");
|
|
664
701
|
}
|
|
665
702
|
async handlePermissionRequest(tools, roomId, params) {
|
|
666
|
-
const selected = choosePermissionOption(params.options);
|
|
667
703
|
const toolName = params.toolCall.title ?? "unknown";
|
|
668
|
-
|
|
669
|
-
|
|
670
|
-
|
|
671
|
-
|
|
672
|
-
|
|
673
|
-
|
|
704
|
+
const autoSelection = this.resolvePermission ? void 0 : choosePermissionOption(params.options);
|
|
705
|
+
const controller = this.resolvePermission ? new AbortController() : void 0;
|
|
706
|
+
if (controller) {
|
|
707
|
+
this.trackPending(params.sessionId, controller);
|
|
708
|
+
}
|
|
709
|
+
const [, chosenId] = await Promise.all([
|
|
710
|
+
// This is the room's only "a permission request is pending" signal,
|
|
711
|
+
// and the only one other room participants ever see — started
|
|
712
|
+
// immediately rather than serialized in front of a manual wait that
|
|
713
|
+
// can take up to `permissionTimeoutMs`.
|
|
714
|
+
tools.sendEvent(`Permission requested: ${toolName}`, "tool_call", {
|
|
715
|
+
permission_request: true,
|
|
716
|
+
tool_name: toolName,
|
|
717
|
+
tool_call_id: params.toolCall.toolCallId,
|
|
718
|
+
acp_session_id: params.sessionId,
|
|
719
|
+
auto_allowed: autoSelection !== void 0 && autoSelection !== null
|
|
720
|
+
}),
|
|
721
|
+
controller ? this.resolveManually(params.sessionId, params, controller) : Promise.resolve(autoSelection?.optionId)
|
|
722
|
+
]);
|
|
723
|
+
return this.toResponse(chosenId, params.options);
|
|
724
|
+
}
|
|
725
|
+
// `undefined`, or an id absent from this request's own `options` (a buggy
|
|
726
|
+
// or stale caller), both map to `cancelled` — never silently treated as a
|
|
727
|
+
// deny. A real match, reject-kind options included, maps to `selected`.
|
|
728
|
+
toResponse(chosenId, options) {
|
|
729
|
+
const matched = chosenId !== void 0 && options.some((option) => option.optionId === chosenId);
|
|
730
|
+
return matched ? { outcome: { outcome: "selected", optionId: chosenId } } : { outcome: { outcome: "cancelled" } };
|
|
731
|
+
}
|
|
732
|
+
// Races the caller-supplied resolver against a timeout and against
|
|
733
|
+
// `controller`'s own abort signal — aborted externally by
|
|
734
|
+
// `cancelPendingPermissions`/`cancelAllPendingPermissions` (fired from
|
|
735
|
+
// `onCleanup`/`stop()` below) when a room or the whole adapter tears down
|
|
736
|
+
// while this is still pending. `controller` is the same object tracked in
|
|
737
|
+
// `pendingPermissions` by the caller, so there is exactly one cancellation
|
|
738
|
+
// channel here, not a second hand-rolled one alongside it.
|
|
739
|
+
async resolveManually(sessionId, params, controller) {
|
|
740
|
+
let timer;
|
|
741
|
+
const cancelled = new Promise((resolve) => {
|
|
742
|
+
controller.signal.addEventListener("abort", () => resolve(void 0));
|
|
674
743
|
});
|
|
675
|
-
|
|
676
|
-
|
|
677
|
-
|
|
678
|
-
|
|
679
|
-
|
|
680
|
-
|
|
744
|
+
try {
|
|
745
|
+
const timeout = new Promise((resolve) => {
|
|
746
|
+
timer = setTimeout(() => resolve(void 0), this.permissionTimeoutMs);
|
|
747
|
+
});
|
|
748
|
+
return await Promise.race([
|
|
749
|
+
// `resolvePermission` is caller-supplied; nothing guarantees it's
|
|
750
|
+
// `async` or otherwise well-behaved. `Promise.resolve().then(...)`
|
|
751
|
+
// normalizes a synchronous throw the same way it normalizes a
|
|
752
|
+
// rejected promise, so both land in the `.catch` below rather than
|
|
753
|
+
// escaping this race uncaught.
|
|
754
|
+
Promise.resolve().then(() => this.resolvePermission(params, controller.signal)).catch((error) => {
|
|
755
|
+
try {
|
|
756
|
+
this.logger.warn("resolvePermission threw; treating as no answer", { error: String(error) });
|
|
757
|
+
} catch {
|
|
758
|
+
}
|
|
759
|
+
return void 0;
|
|
760
|
+
}),
|
|
761
|
+
timeout,
|
|
762
|
+
cancelled
|
|
763
|
+
]);
|
|
764
|
+
} finally {
|
|
765
|
+
clearTimeout(timer);
|
|
766
|
+
this.untrackPending(sessionId, controller);
|
|
767
|
+
controller.abort();
|
|
768
|
+
}
|
|
769
|
+
}
|
|
770
|
+
trackPending(sessionId, controller) {
|
|
771
|
+
const pending = this.pendingPermissions.get(sessionId) ?? /* @__PURE__ */ new Set();
|
|
772
|
+
pending.add(controller);
|
|
773
|
+
this.pendingPermissions.set(sessionId, pending);
|
|
774
|
+
}
|
|
775
|
+
untrackPending(sessionId, controller) {
|
|
776
|
+
const pending = this.pendingPermissions.get(sessionId);
|
|
777
|
+
pending?.delete(controller);
|
|
778
|
+
if (pending?.size === 0) {
|
|
779
|
+
this.pendingPermissions.delete(sessionId);
|
|
780
|
+
}
|
|
781
|
+
}
|
|
782
|
+
cancelPendingPermissions(sessionId) {
|
|
783
|
+
for (const controller of this.pendingPermissions.get(sessionId) ?? []) {
|
|
784
|
+
controller.abort();
|
|
785
|
+
}
|
|
786
|
+
}
|
|
787
|
+
cancelAllPendingPermissions() {
|
|
788
|
+
for (const sessionId of this.pendingPermissions.keys()) {
|
|
789
|
+
this.cancelPendingPermissions(sessionId);
|
|
681
790
|
}
|
|
682
|
-
return {
|
|
683
|
-
outcome: {
|
|
684
|
-
outcome: "selected",
|
|
685
|
-
optionId: selected.optionId
|
|
686
|
-
}
|
|
687
|
-
};
|
|
688
791
|
}
|
|
689
792
|
async flushChunks(input) {
|
|
690
793
|
const client = this.client;
|
|
@@ -768,7 +871,7 @@ function toErrorMessage(error) {
|
|
|
768
871
|
// src/adapters/acp/ACPServer.ts
|
|
769
872
|
import { Readable as Readable2, Writable as Writable2 } from "stream";
|
|
770
873
|
|
|
771
|
-
// src/adapters/acp/
|
|
874
|
+
// src/adapters/acp/BandACPServerAdapter.ts
|
|
772
875
|
import { randomUUID } from "crypto";
|
|
773
876
|
|
|
774
877
|
// src/adapters/acp/eventConverter.ts
|
|
@@ -922,12 +1025,12 @@ var AgentRouter = class {
|
|
|
922
1025
|
}
|
|
923
1026
|
};
|
|
924
1027
|
|
|
925
|
-
// src/adapters/acp/
|
|
1028
|
+
// src/adapters/acp/BandACPServerAdapter.ts
|
|
926
1029
|
var DEFAULT_MAX_SESSIONS = 100;
|
|
927
1030
|
var DEFAULT_PROMPT_TIMEOUT_MS = 3e5;
|
|
928
1031
|
var DEFAULT_PROMPT_COMPLETION_GRACE_MS = 250;
|
|
929
|
-
var
|
|
930
|
-
|
|
1032
|
+
var BandACPServerAdapter = class extends SimpleAdapter {
|
|
1033
|
+
bandRest;
|
|
931
1034
|
maxSessions;
|
|
932
1035
|
responseTimeoutMs;
|
|
933
1036
|
promptCompletionGraceMs;
|
|
@@ -948,7 +1051,7 @@ var ThenvoiACPServerAdapter = class extends SimpleAdapter {
|
|
|
948
1051
|
super({
|
|
949
1052
|
historyConverter: new ACPServerHistoryConverter()
|
|
950
1053
|
});
|
|
951
|
-
this.
|
|
1054
|
+
this.bandRest = options.bandRest;
|
|
952
1055
|
this.maxSessions = options.maxSessions ?? DEFAULT_MAX_SESSIONS;
|
|
953
1056
|
this.responseTimeoutMs = options.responseTimeoutMs ?? DEFAULT_PROMPT_TIMEOUT_MS;
|
|
954
1057
|
this.promptCompletionGraceMs = options.promptCompletionGraceMs ?? DEFAULT_PROMPT_COMPLETION_GRACE_MS;
|
|
@@ -1010,7 +1113,7 @@ var ThenvoiACPServerAdapter = class extends SimpleAdapter {
|
|
|
1010
1113
|
}
|
|
1011
1114
|
async verifyCredentials() {
|
|
1012
1115
|
try {
|
|
1013
|
-
await this.
|
|
1116
|
+
await this.bandRest.getAgentMe();
|
|
1014
1117
|
return true;
|
|
1015
1118
|
} catch {
|
|
1016
1119
|
return false;
|
|
@@ -1019,7 +1122,7 @@ var ThenvoiACPServerAdapter = class extends SimpleAdapter {
|
|
|
1019
1122
|
async onStarted(agentName, agentDescription) {
|
|
1020
1123
|
await super.onStarted(agentName, agentDescription);
|
|
1021
1124
|
try {
|
|
1022
|
-
const identity = await this.
|
|
1125
|
+
const identity = await this.bandRest.getAgentMe();
|
|
1023
1126
|
this.agentId = identity.id;
|
|
1024
1127
|
} catch {
|
|
1025
1128
|
this.agentId = null;
|
|
@@ -1033,7 +1136,7 @@ var ThenvoiACPServerAdapter = class extends SimpleAdapter {
|
|
|
1033
1136
|
throw new Error(`Maximum ACP sessions (${this.maxSessions}) reached`);
|
|
1034
1137
|
}
|
|
1035
1138
|
try {
|
|
1036
|
-
const room = await this.
|
|
1139
|
+
const room = await this.bandRest.createChat();
|
|
1037
1140
|
const sessionId = randomUUID();
|
|
1038
1141
|
const normalizedMcpServers = normalizeMcpServers(input.mcpServers);
|
|
1039
1142
|
this.sessionToRoom.set(sessionId, room.id);
|
|
@@ -1043,7 +1146,7 @@ var ThenvoiACPServerAdapter = class extends SimpleAdapter {
|
|
|
1043
1146
|
this.sessionMcpServers.set(sessionId, normalizedMcpServers);
|
|
1044
1147
|
}
|
|
1045
1148
|
try {
|
|
1046
|
-
await this.
|
|
1149
|
+
await this.bandRest.createChatEvent(room.id, {
|
|
1047
1150
|
content: "ACP session context",
|
|
1048
1151
|
messageType: "task",
|
|
1049
1152
|
metadata: {
|
|
@@ -1076,10 +1179,10 @@ var ThenvoiACPServerAdapter = class extends SimpleAdapter {
|
|
|
1076
1179
|
this.pendingPrompts.set(roomId, pending);
|
|
1077
1180
|
const resolved = this.router.resolve(text, this.sessionModeIds.get(sessionId));
|
|
1078
1181
|
const promptText = this.prependSessionContext(sessionId, resolved.text);
|
|
1079
|
-
const participants = await this.
|
|
1182
|
+
const participants = await this.bandRest.listChatParticipants(roomId);
|
|
1080
1183
|
const mentions = this.resolveMentions(participants, resolved.targetPeer);
|
|
1081
1184
|
try {
|
|
1082
|
-
await this.
|
|
1185
|
+
await this.bandRest.createChatMessage(roomId, {
|
|
1083
1186
|
content: promptText,
|
|
1084
1187
|
mentions
|
|
1085
1188
|
});
|
|
@@ -1332,7 +1435,7 @@ var ACPServer = class {
|
|
|
1332
1435
|
this.authMethods = options?.authMethods ?? [{
|
|
1333
1436
|
id: "api_key",
|
|
1334
1437
|
name: "API Key",
|
|
1335
|
-
description: "Authenticate with THENVOI_API_KEY."
|
|
1438
|
+
description: "Authenticate with BAND_API_KEY (legacy THENVOI_API_KEY)."
|
|
1336
1439
|
}];
|
|
1337
1440
|
this.agentInfo = options?.agentInfo ?? {};
|
|
1338
1441
|
this.extensionHandler = options?.extensionHandler ?? new CursorExtensionHandler();
|
|
@@ -1385,8 +1488,8 @@ var ACPServer = class {
|
|
|
1385
1488
|
}
|
|
1386
1489
|
},
|
|
1387
1490
|
agentInfo: {
|
|
1388
|
-
name: this.agentInfo.name ?? "
|
|
1389
|
-
title: this.agentInfo.title ?? this.adapter.displayName ?? "
|
|
1491
|
+
name: this.agentInfo.name ?? "band-agent",
|
|
1492
|
+
title: this.agentInfo.title ?? this.adapter.displayName ?? "Band Agent",
|
|
1390
1493
|
version: this.agentInfo.version ?? "0.1.0"
|
|
1391
1494
|
},
|
|
1392
1495
|
authMethods: this.authMethods
|
|
@@ -1558,6 +1661,7 @@ export {
|
|
|
1558
1661
|
ACPServer,
|
|
1559
1662
|
AnthropicAdapter,
|
|
1560
1663
|
AnthropicToolCallingModel,
|
|
1664
|
+
BandACPServerAdapter,
|
|
1561
1665
|
CODEX_REASONING_EFFORTS,
|
|
1562
1666
|
CODEX_REASONING_SUMMARIES,
|
|
1563
1667
|
CODEX_WEB_SEARCH_MODES,
|
|
@@ -1581,7 +1685,6 @@ export {
|
|
|
1581
1685
|
OpencodeAdapter,
|
|
1582
1686
|
ParlantAdapter,
|
|
1583
1687
|
ParlantHistoryConverter,
|
|
1584
|
-
ThenvoiACPServerAdapter,
|
|
1585
1688
|
ToolCallingAdapter,
|
|
1586
1689
|
VercelAISDKAdapter,
|
|
1587
1690
|
VercelAISDKToolCallingModel,
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
import { A as AdapterToolsProtocol } from './protocols-Bwwcql0h.js';
|
|
2
|
+
import { M as McpToolRegistration, B as BandSdkMcpServer } from './sdk-qKJtMma_.js';
|
|
3
|
+
|
|
4
|
+
type BandMcpBackendKind = "sdk" | "http" | "sse" | "stdio";
|
|
5
|
+
interface BandMcpBackend {
|
|
6
|
+
kind: BandMcpBackendKind;
|
|
7
|
+
server: unknown;
|
|
8
|
+
allowedTools: string[];
|
|
9
|
+
/** Bearer token callers must present to reach `server`. Set for "http"/"sse", which listen on a loopback network port. */
|
|
10
|
+
authToken?: string;
|
|
11
|
+
stop(): Promise<void>;
|
|
12
|
+
}
|
|
13
|
+
interface CreateBandMcpBackendOptions {
|
|
14
|
+
kind: BandMcpBackendKind;
|
|
15
|
+
enableMemoryTools: boolean;
|
|
16
|
+
/**
|
|
17
|
+
* Returns the tools for a given room. In single-room mode (`multiRoom: false`),
|
|
18
|
+
* called once during init with `""` — must return the tools instance regardless of the argument.
|
|
19
|
+
*/
|
|
20
|
+
getToolsForRoom: (roomId: string) => AdapterToolsProtocol | undefined;
|
|
21
|
+
additionalTools?: McpToolRegistration[];
|
|
22
|
+
multiRoom?: boolean;
|
|
23
|
+
}
|
|
24
|
+
declare function createBandMcpBackend(options: CreateBandMcpBackendOptions): Promise<BandMcpBackend>;
|
|
25
|
+
declare function getBandSdkMcpServerConfig(backend: BandMcpBackend): BandSdkMcpServer["serverConfig"];
|
|
26
|
+
|
|
27
|
+
export { type BandMcpBackend as B, type CreateBandMcpBackendOptions as C, type BandMcpBackendKind as a, createBandMcpBackend as c, getBandSdkMcpServerConfig as g };
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
import { A as AdapterToolsProtocol } from './protocols-Bz1rxcUg.cjs';
|
|
2
|
+
import { M as McpToolRegistration, B as BandSdkMcpServer } from './sdk-BTciSLRQ.cjs';
|
|
3
|
+
|
|
4
|
+
type BandMcpBackendKind = "sdk" | "http" | "sse" | "stdio";
|
|
5
|
+
interface BandMcpBackend {
|
|
6
|
+
kind: BandMcpBackendKind;
|
|
7
|
+
server: unknown;
|
|
8
|
+
allowedTools: string[];
|
|
9
|
+
/** Bearer token callers must present to reach `server`. Set for "http"/"sse", which listen on a loopback network port. */
|
|
10
|
+
authToken?: string;
|
|
11
|
+
stop(): Promise<void>;
|
|
12
|
+
}
|
|
13
|
+
interface CreateBandMcpBackendOptions {
|
|
14
|
+
kind: BandMcpBackendKind;
|
|
15
|
+
enableMemoryTools: boolean;
|
|
16
|
+
/**
|
|
17
|
+
* Returns the tools for a given room. In single-room mode (`multiRoom: false`),
|
|
18
|
+
* called once during init with `""` — must return the tools instance regardless of the argument.
|
|
19
|
+
*/
|
|
20
|
+
getToolsForRoom: (roomId: string) => AdapterToolsProtocol | undefined;
|
|
21
|
+
additionalTools?: McpToolRegistration[];
|
|
22
|
+
multiRoom?: boolean;
|
|
23
|
+
}
|
|
24
|
+
declare function createBandMcpBackend(options: CreateBandMcpBackendOptions): Promise<BandMcpBackend>;
|
|
25
|
+
declare function getBandSdkMcpServerConfig(backend: BandMcpBackend): BandSdkMcpServer["serverConfig"];
|
|
26
|
+
|
|
27
|
+
export { type BandMcpBackend as B, type CreateBandMcpBackendOptions as C, type BandMcpBackendKind as a, createBandMcpBackend as c, getBandSdkMcpServerConfig as g };
|