@byok-sdk/client 0.10.2 → 0.12.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 +86 -6
- package/dist/adapters/claude/claude-adapter.d.ts +3 -2
- package/dist/adapters/claude/permission-mapping.d.ts +48 -1
- package/dist/adapters/claude/resolve-approval-mcp-bin.d.ts +3 -2
- package/dist/adapters/codex/permission-mapping.d.ts +16 -0
- package/dist/adapters/index.js +292 -23
- package/dist/adapters/index.js.map +1 -1
- package/dist/adapters/mcp-tool-grants.d.ts +36 -0
- package/dist/adapters/pi/resolve-extensions.d.ts +4 -1
- package/dist/adapters/pi/subagents-policy-config.d.ts +7 -0
- package/dist/adapters/pi/subagents-policy-extension.js +137 -0
- package/dist/adapters/pi/subagents-policy-extension.js.map +1 -0
- package/dist/agent-home.d.ts +33 -0
- package/dist/agent-memory/index.d.ts +1 -1
- package/dist/agent-memory/index.js +12 -9
- package/dist/agent-memory/index.js.map +1 -1
- package/dist/bin/agent-memory-mcp-server.d.ts +2 -2
- package/dist/bin/agent-message-mcp-server.d.ts +0 -1
- package/dist/bin/byok-agent-memory-mcp.js +340 -7
- package/dist/bin/byok-agent-memory-mcp.js.map +1 -1
- package/dist/bin/byok-agent-message-mcp.js +331 -7
- package/dist/bin/byok-agent-message-mcp.js.map +1 -1
- package/dist/bin/byok-agent-team-mcp.d.ts +2 -0
- package/dist/bin/byok-agent-team-mcp.js +765 -0
- package/dist/bin/byok-agent-team-mcp.js.map +1 -0
- package/dist/bin/byok-agent.js +16413 -14479
- package/dist/bin/byok-agent.js.map +1 -1
- package/dist/bin/byok-approval-mcp.js +312 -45
- package/dist/bin/byok-approval-mcp.js.map +1 -1
- package/dist/bin/commands/team.d.ts +15 -0
- package/dist/bin/sdk-reserved-helper-runners.d.ts +2 -0
- package/dist/bin/team-mcp-server.d.ts +27 -0
- package/dist/bin/team-tmux-view.d.ts +19 -0
- package/dist/daemon/agent-egress-controller.d.ts +4 -0
- package/dist/daemon/agent-message-mcp-preflight.d.ts +17 -0
- package/dist/daemon/auth-manager.d.ts +20 -0
- package/dist/daemon/blob-client.d.ts +24 -6
- package/dist/daemon/connection-manager.d.ts +7 -0
- package/dist/daemon/control-protocol.d.ts +38 -0
- package/dist/daemon/create-daemon.d.ts +9 -0
- package/dist/daemon/device-credential-store.d.ts +16 -0
- package/dist/daemon/long-poll-transport.d.ts +3 -0
- package/dist/daemon/mcp-tools-probe.d.ts +105 -0
- package/dist/daemon/replay-cursor.d.ts +9 -0
- package/dist/daemon/resolve-agent-memory-mcp-bin.d.ts +2 -1
- package/dist/daemon/resolve-agent-message-mcp-bin.d.ts +2 -1
- package/dist/daemon/task-runner.d.ts +22 -1
- package/dist/daemon/team-workspace.d.ts +202 -0
- package/dist/daemon/toolset-registry.d.ts +0 -2
- package/dist/daemon/url.d.ts +7 -1
- package/dist/index.d.ts +8 -3
- package/dist/index.js +3611 -1364
- package/dist/index.js.map +1 -1
- package/dist/sdk-reserved-helper-host.d.ts +25 -0
- package/dist/sdk-reserved-mcp.d.ts +23 -0
- package/dist/types.d.ts +36 -0
- package/package.json +10 -5
|
@@ -0,0 +1,765 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
import { promises, constants } from 'fs';
|
|
3
|
+
import net from 'net';
|
|
4
|
+
import { randomBytes, createHash, timingSafeEqual, createHmac } from 'crypto';
|
|
5
|
+
import path from 'path';
|
|
6
|
+
import { createInterface } from 'readline';
|
|
7
|
+
|
|
8
|
+
var CONTROL_PROTOCOL_VERSION = 1;
|
|
9
|
+
var HANDSHAKE_TIMEOUT_MS = 3e3;
|
|
10
|
+
var UNIX_SOCKET_PATH_SOFT_LIMIT = 100;
|
|
11
|
+
var CONTROL_SOCKET_FALLBACK_ROOT = "/tmp";
|
|
12
|
+
function shortHash(input) {
|
|
13
|
+
return createHash("sha256").update(input, "utf8").digest("hex").slice(0, 16);
|
|
14
|
+
}
|
|
15
|
+
function controlSocketPath(storeDir) {
|
|
16
|
+
const candidate = path.join(storeDir, "control.sock");
|
|
17
|
+
if (Buffer.byteLength(candidate, "utf8") <= UNIX_SOCKET_PATH_SOFT_LIMIT) return candidate;
|
|
18
|
+
return path.join(CONTROL_SOCKET_FALLBACK_ROOT, `byok-${shortHash(storeDir)}`, "sock");
|
|
19
|
+
}
|
|
20
|
+
function controlPipeName(productId, storeDir) {
|
|
21
|
+
const id = shortHash(`${productId}|${path.resolve(storeDir)}`);
|
|
22
|
+
return `\\\\.\\pipe\\byok-${id}`;
|
|
23
|
+
}
|
|
24
|
+
function controlEndpointPath(productId, storeDir, platform = process.platform) {
|
|
25
|
+
return platform === "win32" ? controlPipeName(productId, storeDir) : controlSocketPath(storeDir);
|
|
26
|
+
}
|
|
27
|
+
function controlTokenPath(storeDir) {
|
|
28
|
+
return path.join(storeDir, "control.token");
|
|
29
|
+
}
|
|
30
|
+
var SERVER_PROOF_LABEL = "byok-control-server|";
|
|
31
|
+
var CLIENT_AUTH_LABEL = "byok-control-client|";
|
|
32
|
+
function randomNonceHex() {
|
|
33
|
+
return randomBytes(32).toString("hex");
|
|
34
|
+
}
|
|
35
|
+
function hmacHex(token, message) {
|
|
36
|
+
return createHmac("sha256", token).update(message, "utf8").digest("hex");
|
|
37
|
+
}
|
|
38
|
+
function computeServerProof(token, clientNonce) {
|
|
39
|
+
return hmacHex(token, SERVER_PROOF_LABEL + clientNonce);
|
|
40
|
+
}
|
|
41
|
+
function computeClientAuth(token, serverNonce) {
|
|
42
|
+
return hmacHex(token, CLIENT_AUTH_LABEL + serverNonce);
|
|
43
|
+
}
|
|
44
|
+
function timingSafeEqualHex(a, b) {
|
|
45
|
+
const bufA = Buffer.from(a, "hex");
|
|
46
|
+
const bufB = Buffer.from(b, "hex");
|
|
47
|
+
if (bufA.length !== bufB.length) return false;
|
|
48
|
+
return timingSafeEqual(bufA, bufB);
|
|
49
|
+
}
|
|
50
|
+
function isRecord(value) {
|
|
51
|
+
return typeof value === "object" && value !== null;
|
|
52
|
+
}
|
|
53
|
+
function parseServerHello(value) {
|
|
54
|
+
if (!isRecord(value)) return void 0;
|
|
55
|
+
if (value.v !== CONTROL_PROTOCOL_VERSION || value.hello !== "server" || typeof value.proof !== "string" || typeof value.nonce !== "string") {
|
|
56
|
+
return void 0;
|
|
57
|
+
}
|
|
58
|
+
return { v: CONTROL_PROTOCOL_VERSION, hello: "server", proof: value.proof, nonce: value.nonce };
|
|
59
|
+
}
|
|
60
|
+
function parseServerReady(value) {
|
|
61
|
+
if (!isRecord(value)) return void 0;
|
|
62
|
+
if (value.v !== CONTROL_PROTOCOL_VERSION || value.ready !== true) return void 0;
|
|
63
|
+
return { v: CONTROL_PROTOCOL_VERSION, ready: true };
|
|
64
|
+
}
|
|
65
|
+
function encodeFrame(frame) {
|
|
66
|
+
return `${JSON.stringify(frame)}
|
|
67
|
+
`;
|
|
68
|
+
}
|
|
69
|
+
var ControlError = class extends Error {
|
|
70
|
+
constructor(code, message) {
|
|
71
|
+
super(message);
|
|
72
|
+
this.code = code;
|
|
73
|
+
this.name = "ControlError";
|
|
74
|
+
}
|
|
75
|
+
code;
|
|
76
|
+
};
|
|
77
|
+
var MAX_LINE_BYTES = 64 * 1024;
|
|
78
|
+
var NdjsonLineReader = class {
|
|
79
|
+
pending = Buffer.alloc(0);
|
|
80
|
+
/** @throws if the still-unterminated remainder exceeds {@link MAX_LINE_BYTES} — see that constant's own doc comment. */
|
|
81
|
+
push(chunk) {
|
|
82
|
+
this.pending = this.pending.length > 0 ? Buffer.concat([this.pending, chunk]) : chunk;
|
|
83
|
+
const lines = [];
|
|
84
|
+
let newlineIndex;
|
|
85
|
+
while ((newlineIndex = this.pending.indexOf(10)) !== -1) {
|
|
86
|
+
const line = this.pending.subarray(0, newlineIndex).toString("utf8");
|
|
87
|
+
this.pending = this.pending.subarray(newlineIndex + 1);
|
|
88
|
+
if (line.length > 0) lines.push(line);
|
|
89
|
+
}
|
|
90
|
+
if (this.pending.length > MAX_LINE_BYTES) {
|
|
91
|
+
throw new Error(`NDJSON line exceeded ${MAX_LINE_BYTES} bytes without a terminating newline`);
|
|
92
|
+
}
|
|
93
|
+
return lines;
|
|
94
|
+
}
|
|
95
|
+
};
|
|
96
|
+
|
|
97
|
+
// src/bin/control-client.ts
|
|
98
|
+
var MAX_CONTROL_TOKEN_BYTES = 256;
|
|
99
|
+
function errorMessage(err) {
|
|
100
|
+
return err instanceof Error ? err.message : String(err);
|
|
101
|
+
}
|
|
102
|
+
function sameFileState(left, right) {
|
|
103
|
+
return left.dev === right.dev && left.ino === right.ino && left.size === right.size && left.mtimeNs === right.mtimeNs && left.ctimeNs === right.ctimeNs;
|
|
104
|
+
}
|
|
105
|
+
async function readControlToken(tokenPath) {
|
|
106
|
+
let namedBefore;
|
|
107
|
+
try {
|
|
108
|
+
namedBefore = await promises.lstat(tokenPath, { bigint: true });
|
|
109
|
+
} catch (err) {
|
|
110
|
+
if (err.code === "ENOENT") return void 0;
|
|
111
|
+
throw err;
|
|
112
|
+
}
|
|
113
|
+
if (!namedBefore.isFile() || namedBefore.isSymbolicLink()) {
|
|
114
|
+
throw new Error("control token is not a real regular file");
|
|
115
|
+
}
|
|
116
|
+
const handle = await promises.open(
|
|
117
|
+
tokenPath,
|
|
118
|
+
constants.O_RDONLY | (constants.O_NONBLOCK ?? 0) | (constants.O_NOFOLLOW ?? 0)
|
|
119
|
+
);
|
|
120
|
+
try {
|
|
121
|
+
const opened = await handle.stat({ bigint: true });
|
|
122
|
+
const namedAfterOpen = await promises.lstat(tokenPath, { bigint: true });
|
|
123
|
+
if (!opened.isFile() || !namedAfterOpen.isFile() || namedAfterOpen.isSymbolicLink() || !sameFileState(namedBefore, opened) || !sameFileState(opened, namedAfterOpen)) {
|
|
124
|
+
throw new Error("control token pathname changed before safe open");
|
|
125
|
+
}
|
|
126
|
+
if (opened.size < 0 || opened.size > BigInt(MAX_CONTROL_TOKEN_BYTES)) {
|
|
127
|
+
throw new Error("control token exceeds the bounded read limit");
|
|
128
|
+
}
|
|
129
|
+
const size = Number(opened.size);
|
|
130
|
+
const bytes = Buffer.alloc(size);
|
|
131
|
+
const { bytesRead } = await handle.read(bytes, 0, size, 0);
|
|
132
|
+
const afterRead = await handle.stat({ bigint: true });
|
|
133
|
+
const namedAfterRead = await promises.lstat(tokenPath, { bigint: true });
|
|
134
|
+
if (bytesRead !== size || namedAfterRead.isSymbolicLink() || !sameFileState(opened, afterRead) || !sameFileState(afterRead, namedAfterRead)) {
|
|
135
|
+
throw new Error("control token changed during bounded read");
|
|
136
|
+
}
|
|
137
|
+
return bytes.toString("utf8").trim();
|
|
138
|
+
} finally {
|
|
139
|
+
await handle.close();
|
|
140
|
+
}
|
|
141
|
+
}
|
|
142
|
+
async function connectControlClient(opts) {
|
|
143
|
+
const tokenPath = controlTokenPath(opts.storeDir);
|
|
144
|
+
let token;
|
|
145
|
+
try {
|
|
146
|
+
const read = await readControlToken(tokenPath);
|
|
147
|
+
if (read === void 0) {
|
|
148
|
+
return { ok: false, reason: "daemon is not running (no control.token found)" };
|
|
149
|
+
}
|
|
150
|
+
token = read;
|
|
151
|
+
} catch (err) {
|
|
152
|
+
return { ok: false, reason: `could not read the control token: ${errorMessage(err)}` };
|
|
153
|
+
}
|
|
154
|
+
if (!token) {
|
|
155
|
+
return { ok: false, reason: "control token file is empty" };
|
|
156
|
+
}
|
|
157
|
+
const endpoint = controlEndpointPath(opts.productId, opts.storeDir);
|
|
158
|
+
try {
|
|
159
|
+
const client = await connectAndHandshake(endpoint, token, opts);
|
|
160
|
+
return { ok: true, client };
|
|
161
|
+
} catch (err) {
|
|
162
|
+
return { ok: false, reason: `daemon control socket not reachable: ${errorMessage(err)}` };
|
|
163
|
+
}
|
|
164
|
+
}
|
|
165
|
+
function connectAndHandshake(endpoint, token, opts) {
|
|
166
|
+
return new Promise((resolve, reject) => {
|
|
167
|
+
const socket = net.createConnection(endpoint);
|
|
168
|
+
const reader = new NdjsonLineReader();
|
|
169
|
+
let phase = "server-hello";
|
|
170
|
+
let settled = false;
|
|
171
|
+
const clientNonce = randomNonceHex();
|
|
172
|
+
const timer = setTimeout(() => {
|
|
173
|
+
fail(new Error("handshake timed out"));
|
|
174
|
+
}, opts.handshakeTimeoutMs ?? HANDSHAKE_TIMEOUT_MS);
|
|
175
|
+
timer.unref?.();
|
|
176
|
+
function fail(err) {
|
|
177
|
+
if (settled) return;
|
|
178
|
+
settled = true;
|
|
179
|
+
clearTimeout(timer);
|
|
180
|
+
socket.removeAllListeners();
|
|
181
|
+
socket.destroy();
|
|
182
|
+
reject(err instanceof Error ? err : new Error(String(err)));
|
|
183
|
+
}
|
|
184
|
+
function succeed() {
|
|
185
|
+
settled = true;
|
|
186
|
+
clearTimeout(timer);
|
|
187
|
+
socket.removeListener("error", onError);
|
|
188
|
+
socket.removeListener("data", onData);
|
|
189
|
+
resolve(createControlClient(socket, reader, opts));
|
|
190
|
+
}
|
|
191
|
+
function onData(chunk) {
|
|
192
|
+
let lines;
|
|
193
|
+
try {
|
|
194
|
+
lines = reader.push(chunk);
|
|
195
|
+
} catch (err) {
|
|
196
|
+
fail(err);
|
|
197
|
+
return;
|
|
198
|
+
}
|
|
199
|
+
for (const line of lines) {
|
|
200
|
+
let parsed;
|
|
201
|
+
try {
|
|
202
|
+
parsed = JSON.parse(line);
|
|
203
|
+
} catch {
|
|
204
|
+
fail(new Error("malformed handshake frame"));
|
|
205
|
+
return;
|
|
206
|
+
}
|
|
207
|
+
if (phase === "server-hello") {
|
|
208
|
+
const hello = parseServerHello(parsed);
|
|
209
|
+
if (!hello) {
|
|
210
|
+
fail(new Error("malformed or unexpected server hello"));
|
|
211
|
+
return;
|
|
212
|
+
}
|
|
213
|
+
if (!timingSafeEqualHex(hello.proof, computeServerProof(token, clientNonce))) {
|
|
214
|
+
fail(new Error("server failed to prove it holds the control token"));
|
|
215
|
+
return;
|
|
216
|
+
}
|
|
217
|
+
socket.write(encodeFrame({ v: CONTROL_PROTOCOL_VERSION, auth: computeClientAuth(token, hello.nonce) }));
|
|
218
|
+
phase = "ready";
|
|
219
|
+
continue;
|
|
220
|
+
}
|
|
221
|
+
if (!parseServerReady(parsed)) {
|
|
222
|
+
fail(new Error("server did not confirm readiness"));
|
|
223
|
+
return;
|
|
224
|
+
}
|
|
225
|
+
succeed();
|
|
226
|
+
return;
|
|
227
|
+
}
|
|
228
|
+
}
|
|
229
|
+
function onError(err) {
|
|
230
|
+
fail(err);
|
|
231
|
+
}
|
|
232
|
+
socket.once("error", onError);
|
|
233
|
+
socket.once("connect", () => {
|
|
234
|
+
socket.write(encodeFrame({ v: CONTROL_PROTOCOL_VERSION, hello: "client", nonce: clientNonce }));
|
|
235
|
+
socket.on("data", onData);
|
|
236
|
+
});
|
|
237
|
+
});
|
|
238
|
+
}
|
|
239
|
+
function withTimeout(promise, ms, message) {
|
|
240
|
+
return new Promise((resolve, reject) => {
|
|
241
|
+
const timer = setTimeout(() => reject(new Error(message)), ms);
|
|
242
|
+
timer.unref?.();
|
|
243
|
+
promise.then(
|
|
244
|
+
(value) => {
|
|
245
|
+
clearTimeout(timer);
|
|
246
|
+
resolve(value);
|
|
247
|
+
},
|
|
248
|
+
(err) => {
|
|
249
|
+
clearTimeout(timer);
|
|
250
|
+
reject(err);
|
|
251
|
+
}
|
|
252
|
+
);
|
|
253
|
+
});
|
|
254
|
+
}
|
|
255
|
+
function createControlClient(socket, reader, opts) {
|
|
256
|
+
const pending = /* @__PURE__ */ new Map();
|
|
257
|
+
let idSeq = 0;
|
|
258
|
+
let closed = false;
|
|
259
|
+
function handleFrame(parsed) {
|
|
260
|
+
if (!isRecord(parsed) || typeof parsed.id !== "string") return;
|
|
261
|
+
const entry = pending.get(parsed.id);
|
|
262
|
+
if (!entry) return;
|
|
263
|
+
if ("event" in parsed) {
|
|
264
|
+
entry.onEvent?.(parsed.event);
|
|
265
|
+
return;
|
|
266
|
+
}
|
|
267
|
+
if (parsed.ok === true) {
|
|
268
|
+
pending.delete(parsed.id);
|
|
269
|
+
entry.resolve(parsed.done === true ? void 0 : parsed.result);
|
|
270
|
+
return;
|
|
271
|
+
}
|
|
272
|
+
pending.delete(parsed.id);
|
|
273
|
+
const shape = parsed.error;
|
|
274
|
+
entry.reject(
|
|
275
|
+
new ControlError(
|
|
276
|
+
typeof shape?.code === "string" ? shape.code : "internal_error",
|
|
277
|
+
typeof shape?.message === "string" ? shape.message : "unknown control error"
|
|
278
|
+
)
|
|
279
|
+
);
|
|
280
|
+
}
|
|
281
|
+
socket.on("data", (chunk) => {
|
|
282
|
+
let lines;
|
|
283
|
+
try {
|
|
284
|
+
lines = reader.push(chunk);
|
|
285
|
+
} catch {
|
|
286
|
+
socket.destroy();
|
|
287
|
+
return;
|
|
288
|
+
}
|
|
289
|
+
for (const line of lines) {
|
|
290
|
+
let parsed;
|
|
291
|
+
try {
|
|
292
|
+
parsed = JSON.parse(line);
|
|
293
|
+
} catch {
|
|
294
|
+
continue;
|
|
295
|
+
}
|
|
296
|
+
handleFrame(parsed);
|
|
297
|
+
}
|
|
298
|
+
});
|
|
299
|
+
socket.on("close", () => {
|
|
300
|
+
closed = true;
|
|
301
|
+
for (const entry of pending.values()) entry.reject(new Error("control connection closed"));
|
|
302
|
+
pending.clear();
|
|
303
|
+
});
|
|
304
|
+
socket.on("error", () => {
|
|
305
|
+
});
|
|
306
|
+
function send(method, params, onEvent) {
|
|
307
|
+
const id = `c${++idSeq}`;
|
|
308
|
+
const promise = new Promise((resolve, reject) => {
|
|
309
|
+
pending.set(id, { resolve, reject, onEvent });
|
|
310
|
+
});
|
|
311
|
+
socket.write(encodeFrame({ v: CONTROL_PROTOCOL_VERSION, id, method, params }));
|
|
312
|
+
return { id, promise };
|
|
313
|
+
}
|
|
314
|
+
return {
|
|
315
|
+
async request(method, params) {
|
|
316
|
+
if (closed) throw new Error("control connection is closed");
|
|
317
|
+
const { promise } = send(method, params);
|
|
318
|
+
const result = await withTimeout(promise, opts.requestTimeoutMs ?? 1e4, `control request "${method}" timed out`);
|
|
319
|
+
return result;
|
|
320
|
+
},
|
|
321
|
+
subscribe(method, params, onEvent) {
|
|
322
|
+
const { id, promise } = send(method, params, onEvent);
|
|
323
|
+
promise.catch(() => {
|
|
324
|
+
});
|
|
325
|
+
return {
|
|
326
|
+
close: () => {
|
|
327
|
+
pending.delete(id);
|
|
328
|
+
socket.destroy();
|
|
329
|
+
}
|
|
330
|
+
};
|
|
331
|
+
},
|
|
332
|
+
close() {
|
|
333
|
+
socket.destroy();
|
|
334
|
+
}
|
|
335
|
+
};
|
|
336
|
+
}
|
|
337
|
+
var AGENT_MESSAGE_TOOL_NAME = "send_agent_message";
|
|
338
|
+
|
|
339
|
+
// src/bin/agent-message-mcp-server.ts
|
|
340
|
+
async function handleAgentMessageMcpRequest(request, deps) {
|
|
341
|
+
const id = request.id;
|
|
342
|
+
if (request.method === "initialize") {
|
|
343
|
+
const params = request.params ?? {};
|
|
344
|
+
return {
|
|
345
|
+
jsonrpc: "2.0",
|
|
346
|
+
id,
|
|
347
|
+
result: {
|
|
348
|
+
protocolVersion: typeof params.protocolVersion === "string" ? params.protocolVersion : "2024-11-05",
|
|
349
|
+
capabilities: { tools: {} },
|
|
350
|
+
serverInfo: { name: "byok-agent-message-mcp", version: "0.0.1" }
|
|
351
|
+
}
|
|
352
|
+
};
|
|
353
|
+
}
|
|
354
|
+
if (request.method === "notifications/initialized") return void 0;
|
|
355
|
+
if (request.method === "tools/list") {
|
|
356
|
+
return {
|
|
357
|
+
jsonrpc: "2.0",
|
|
358
|
+
id,
|
|
359
|
+
result: { tools: [{
|
|
360
|
+
name: AGENT_MESSAGE_TOOL_NAME,
|
|
361
|
+
description: "Send the single user-visible Agent reply for this exact task. Routing identity is supplied by the authenticated task context.",
|
|
362
|
+
inputSchema: {
|
|
363
|
+
type: "object",
|
|
364
|
+
additionalProperties: false,
|
|
365
|
+
required: ["body"],
|
|
366
|
+
properties: {
|
|
367
|
+
body: { type: "string", minLength: 1 },
|
|
368
|
+
contentType: { type: "string", enum: ["text/plain", "text/markdown"] }
|
|
369
|
+
}
|
|
370
|
+
}
|
|
371
|
+
}] }
|
|
372
|
+
};
|
|
373
|
+
}
|
|
374
|
+
if (request.method === "tools/call") {
|
|
375
|
+
const params = request.params ?? {};
|
|
376
|
+
if (params.name !== AGENT_MESSAGE_TOOL_NAME) return { jsonrpc: "2.0", id, error: { code: -32602, message: "unknown Agent message tool" } };
|
|
377
|
+
const args = params.arguments;
|
|
378
|
+
if (args === null || typeof args !== "object" || Array.isArray(args)) return { jsonrpc: "2.0", id, error: { code: -32602, message: "message input must be an object" } };
|
|
379
|
+
const record3 = args;
|
|
380
|
+
if (Object.keys(record3).some((key) => key !== "body" && key !== "contentType") || typeof record3.body !== "string" || record3.body.length === 0) {
|
|
381
|
+
return { jsonrpc: "2.0", id, error: { code: -32602, message: "message input accepts only non-empty body and optional contentType" } };
|
|
382
|
+
}
|
|
383
|
+
const contentType = record3.contentType ?? "text/markdown";
|
|
384
|
+
if (contentType !== "text/plain" && contentType !== "text/markdown") return { jsonrpc: "2.0", id, error: { code: -32602, message: "unsupported contentType" } };
|
|
385
|
+
try {
|
|
386
|
+
const receipt = await deps.publish({ contentType, body: record3.body });
|
|
387
|
+
return { jsonrpc: "2.0", id, result: { content: [{ type: "text", text: JSON.stringify(receipt) }] } };
|
|
388
|
+
} catch (error) {
|
|
389
|
+
return { jsonrpc: "2.0", id, error: { code: -32e3, message: error instanceof Error ? error.message : String(error) } };
|
|
390
|
+
}
|
|
391
|
+
}
|
|
392
|
+
return id === void 0 ? void 0 : { jsonrpc: "2.0", id, error: { code: -32601, message: `unknown method: ${String(request.method)}` } };
|
|
393
|
+
}
|
|
394
|
+
function serveAgentMessageMcpOverStdio(input) {
|
|
395
|
+
const reader = createInterface({ input: input.stdin ?? process.stdin, terminal: false });
|
|
396
|
+
const output = input.stdout ?? process.stdout;
|
|
397
|
+
reader.on("line", (line) => {
|
|
398
|
+
const trimmed = line.trim();
|
|
399
|
+
if (trimmed.length === 0) return;
|
|
400
|
+
void (async () => {
|
|
401
|
+
let request;
|
|
402
|
+
try {
|
|
403
|
+
request = JSON.parse(trimmed);
|
|
404
|
+
} catch {
|
|
405
|
+
return;
|
|
406
|
+
}
|
|
407
|
+
const response = await handleAgentMessageMcpRequest(request, input.deps);
|
|
408
|
+
if (response !== void 0) output.write(`${JSON.stringify(response)}
|
|
409
|
+
`);
|
|
410
|
+
})();
|
|
411
|
+
});
|
|
412
|
+
}
|
|
413
|
+
var AGENT_MEMORY_RECALL_TOOL_NAME = "memory_recall";
|
|
414
|
+
var AGENT_MEMORY_SAVE_TOOL_NAME = "memory_save";
|
|
415
|
+
function record(value) {
|
|
416
|
+
return value !== null && typeof value === "object" && !Array.isArray(value) ? value : void 0;
|
|
417
|
+
}
|
|
418
|
+
function invalid(id, message) {
|
|
419
|
+
return { jsonrpc: "2.0", id, error: { code: -32602, message } };
|
|
420
|
+
}
|
|
421
|
+
function success(id, value) {
|
|
422
|
+
return { jsonrpc: "2.0", id, result: { content: [{ type: "text", text: JSON.stringify(value) }] } };
|
|
423
|
+
}
|
|
424
|
+
async function handleAgentMemoryMcpRequest(request, deps) {
|
|
425
|
+
const id = request.id;
|
|
426
|
+
if (request.method === "initialize") {
|
|
427
|
+
const params2 = record(request.params) ?? {};
|
|
428
|
+
return { jsonrpc: "2.0", id, result: { protocolVersion: typeof params2.protocolVersion === "string" ? params2.protocolVersion : "2024-11-05", capabilities: { tools: {} }, serverInfo: { name: "byok-agent-memory-mcp", version: "0.0.1" } } };
|
|
429
|
+
}
|
|
430
|
+
if (request.method === "notifications/initialized") return void 0;
|
|
431
|
+
if (request.method === "tools/list") return {
|
|
432
|
+
jsonrpc: "2.0",
|
|
433
|
+
id,
|
|
434
|
+
result: { tools: [
|
|
435
|
+
{ name: AGENT_MEMORY_RECALL_TOOL_NAME, description: "Recall one SDK-owned memory file for this exact active Agent task. Identity and memory root are never model parameters.", inputSchema: { type: "object", additionalProperties: false, required: ["path"], properties: { path: { type: "string" }, ifRevision: { type: "string", pattern: "^sha256:[a-f0-9]{64}$" } } } },
|
|
436
|
+
{ name: AGENT_MEMORY_SAVE_TOOL_NAME, description: "Atomically replace or delete one SDK-owned memory file with exact sha256 compare-and-swap.", inputSchema: { type: "object", additionalProperties: false, required: ["op", "path", "expectedRevision"], properties: { op: { type: "string", enum: ["replace", "delete"] }, path: { type: "string" }, expectedRevision: { type: "string", pattern: "^sha256:[a-f0-9]{64}$" }, content: { type: "string" } } } }
|
|
437
|
+
] }
|
|
438
|
+
};
|
|
439
|
+
if (request.method !== "tools/call") return id === void 0 ? void 0 : { jsonrpc: "2.0", id, error: { code: -32601, message: `unknown method: ${String(request.method)}` } };
|
|
440
|
+
const params = record(request.params);
|
|
441
|
+
const args = record(params?.arguments);
|
|
442
|
+
if (!params || !args || typeof params.name !== "string") return invalid(id, "memory tool input must be an object");
|
|
443
|
+
try {
|
|
444
|
+
if (params.name === AGENT_MEMORY_RECALL_TOOL_NAME) {
|
|
445
|
+
if (Object.keys(args).some((key) => key !== "path" && key !== "ifRevision") || typeof args.path !== "string" || args.ifRevision !== void 0 && typeof args.ifRevision !== "string") return invalid(id, "memory_recall accepts only path and optional ifRevision");
|
|
446
|
+
return success(id, await deps.recall({ path: args.path, ...args.ifRevision === void 0 ? {} : { ifRevision: args.ifRevision } }));
|
|
447
|
+
}
|
|
448
|
+
if (params.name === AGENT_MEMORY_SAVE_TOOL_NAME) {
|
|
449
|
+
if (Object.keys(args).some((key) => key !== "op" && key !== "path" && key !== "expectedRevision" && key !== "content") || args.op !== "replace" && args.op !== "delete" || typeof args.path !== "string" || typeof args.expectedRevision !== "string" || args.op === "replace" && typeof args.content !== "string" || args.op === "delete" && args.content !== void 0) return invalid(id, "memory_save requires replace|delete, path, expectedRevision, and content only for replace");
|
|
450
|
+
const content = args.content;
|
|
451
|
+
return success(id, await deps.save({ op: args.op, path: args.path, expectedRevision: args.expectedRevision, ...typeof content === "string" ? { content } : {} }));
|
|
452
|
+
}
|
|
453
|
+
return invalid(id, "unknown Agent memory tool");
|
|
454
|
+
} catch (error) {
|
|
455
|
+
return { jsonrpc: "2.0", id, error: { code: -32e3, message: error instanceof Error ? error.message : String(error) } };
|
|
456
|
+
}
|
|
457
|
+
}
|
|
458
|
+
function serveAgentMemoryMcpOverStdio(input) {
|
|
459
|
+
const reader = createInterface({ input: input.stdin ?? process.stdin, terminal: false });
|
|
460
|
+
const output = input.stdout ?? process.stdout;
|
|
461
|
+
reader.on("line", (line) => {
|
|
462
|
+
const trimmed = line.trim();
|
|
463
|
+
if (!trimmed) return;
|
|
464
|
+
void (async () => {
|
|
465
|
+
let request;
|
|
466
|
+
try {
|
|
467
|
+
request = JSON.parse(trimmed);
|
|
468
|
+
} catch {
|
|
469
|
+
return;
|
|
470
|
+
}
|
|
471
|
+
const response = await handleAgentMemoryMcpRequest(request, input.deps);
|
|
472
|
+
if (response !== void 0) output.write(`${JSON.stringify(response)}
|
|
473
|
+
`);
|
|
474
|
+
})();
|
|
475
|
+
});
|
|
476
|
+
}
|
|
477
|
+
var TEAM_POST_TOOL_NAME = "post_team_message";
|
|
478
|
+
var TEAM_READ_TOOL_NAME = "read_team_messages";
|
|
479
|
+
var TEAM_ACK_TOOL_NAME = "ack_team_messages";
|
|
480
|
+
var record2 = (value) => value !== null && typeof value === "object" && !Array.isArray(value) ? value : void 0;
|
|
481
|
+
var invalid2 = (id, message) => ({ jsonrpc: "2.0", id, error: { code: -32602, message } });
|
|
482
|
+
var success2 = (id, value) => ({ jsonrpc: "2.0", id, result: { content: [{ type: "text", text: JSON.stringify(value) }] } });
|
|
483
|
+
async function handleTeamMcpRequest(request, deps) {
|
|
484
|
+
const { id } = request;
|
|
485
|
+
if (request.method === "initialize") {
|
|
486
|
+
const params2 = record2(request.params) ?? {};
|
|
487
|
+
return { jsonrpc: "2.0", id, result: { protocolVersion: typeof params2.protocolVersion === "string" ? params2.protocolVersion : "2024-11-05", capabilities: { tools: {} }, serverInfo: { name: "byok-agent-team-mcp", version: "0.0.1" } } };
|
|
488
|
+
}
|
|
489
|
+
if (request.method === "notifications/initialized") return void 0;
|
|
490
|
+
if (request.method === "tools/list") return { jsonrpc: "2.0", id, result: { tools: [
|
|
491
|
+
{ name: TEAM_POST_TOOL_NAME, description: "Post one broadcast message as this exact leased team member. Sender and workspace are daemon-owned.", inputSchema: { type: "object", additionalProperties: false, required: ["body"], properties: { body: { type: "string" }, contentType: { type: "string" } } } },
|
|
492
|
+
{ name: TEAM_READ_TOOL_NAME, description: "Read ordered team messages visible to this exact leased member.", inputSchema: { type: "object", additionalProperties: false, properties: { afterSeq: { type: "integer", minimum: 0 } } } },
|
|
493
|
+
{ name: TEAM_ACK_TOOL_NAME, description: "Durably acknowledge messages through an already delivered sequence for this exact leased member.", inputSchema: { type: "object", additionalProperties: false, required: ["throughSeq"], properties: { throughSeq: { type: "integer", minimum: 0 } } } }
|
|
494
|
+
] } };
|
|
495
|
+
if (request.method !== "tools/call") return id === void 0 ? void 0 : { jsonrpc: "2.0", id, error: { code: -32601, message: `unknown method: ${String(request.method)}` } };
|
|
496
|
+
const params = record2(request.params);
|
|
497
|
+
const args = record2(params?.arguments);
|
|
498
|
+
if (!params || !args || typeof params.name !== "string") return invalid2(id, "team tool input must be an object");
|
|
499
|
+
try {
|
|
500
|
+
if (params.name === TEAM_POST_TOOL_NAME) {
|
|
501
|
+
if (Object.keys(args).some((key) => key !== "body" && key !== "contentType") || typeof args.body !== "string" || args.contentType !== void 0 && typeof args.contentType !== "string") return invalid2(id, "post_team_message accepts body and optional contentType only");
|
|
502
|
+
return success2(id, await deps.post({ body: args.body, ...typeof args.contentType === "string" ? { contentType: args.contentType } : {} }));
|
|
503
|
+
}
|
|
504
|
+
if (params.name === TEAM_READ_TOOL_NAME) {
|
|
505
|
+
if (Object.keys(args).some((key) => key !== "afterSeq") || args.afterSeq !== void 0 && (!Number.isSafeInteger(args.afterSeq) || Number(args.afterSeq) < 0)) return invalid2(id, "read_team_messages accepts optional non-negative integer afterSeq only");
|
|
506
|
+
return success2(id, await deps.read(args.afterSeq === void 0 ? {} : { afterSeq: Number(args.afterSeq) }));
|
|
507
|
+
}
|
|
508
|
+
if (params.name === TEAM_ACK_TOOL_NAME) {
|
|
509
|
+
if (Object.keys(args).some((key) => key !== "throughSeq") || !Number.isSafeInteger(args.throughSeq) || Number(args.throughSeq) < 0) return invalid2(id, "ack_team_messages requires non-negative integer throughSeq only");
|
|
510
|
+
return success2(id, await deps.ack({ throughSeq: Number(args.throughSeq) }));
|
|
511
|
+
}
|
|
512
|
+
return invalid2(id, "unknown team tool");
|
|
513
|
+
} catch (error) {
|
|
514
|
+
return { jsonrpc: "2.0", id, error: { code: -32e3, message: error instanceof Error ? error.message : String(error) } };
|
|
515
|
+
}
|
|
516
|
+
}
|
|
517
|
+
function serveTeamMcpOverStdio(input) {
|
|
518
|
+
const reader = createInterface({ input: input.stdin ?? process.stdin, terminal: false });
|
|
519
|
+
const output = input.stdout ?? process.stdout;
|
|
520
|
+
reader.on("line", (line) => {
|
|
521
|
+
const trimmed = line.trim();
|
|
522
|
+
if (!trimmed) return;
|
|
523
|
+
void (async () => {
|
|
524
|
+
let request;
|
|
525
|
+
try {
|
|
526
|
+
request = JSON.parse(trimmed);
|
|
527
|
+
} catch {
|
|
528
|
+
return;
|
|
529
|
+
}
|
|
530
|
+
const response = await handleTeamMcpRequest(request, input.deps);
|
|
531
|
+
if (response !== void 0) output.write(`${JSON.stringify(response)}
|
|
532
|
+
`);
|
|
533
|
+
})();
|
|
534
|
+
});
|
|
535
|
+
}
|
|
536
|
+
var APPROVAL_TOOL_NAME = "approval_prompt";
|
|
537
|
+
var APPROVAL_SUMMARY_MAX_CHARS = 500;
|
|
538
|
+
function errorMessage2(err) {
|
|
539
|
+
return err instanceof Error ? err.message : String(err);
|
|
540
|
+
}
|
|
541
|
+
function summarizeToolCall(toolName, input) {
|
|
542
|
+
let inputStr;
|
|
543
|
+
try {
|
|
544
|
+
inputStr = JSON.stringify(input);
|
|
545
|
+
} catch (err) {
|
|
546
|
+
inputStr = `<unserializable input: ${errorMessage2(err)}>`;
|
|
547
|
+
}
|
|
548
|
+
const bounded = inputStr.length > APPROVAL_SUMMARY_MAX_CHARS ? `${inputStr.slice(0, APPROVAL_SUMMARY_MAX_CHARS)}\u2026 [truncated]` : inputStr;
|
|
549
|
+
return `${toolName}: ${bounded}`;
|
|
550
|
+
}
|
|
551
|
+
async function handleMcpRequest(req, deps, taskId) {
|
|
552
|
+
const id = req.id;
|
|
553
|
+
if (req.method === "initialize") {
|
|
554
|
+
const params = req.params ?? {};
|
|
555
|
+
return {
|
|
556
|
+
jsonrpc: "2.0",
|
|
557
|
+
id,
|
|
558
|
+
result: {
|
|
559
|
+
protocolVersion: typeof params.protocolVersion === "string" ? params.protocolVersion : "2024-11-05",
|
|
560
|
+
capabilities: { tools: {} },
|
|
561
|
+
serverInfo: { name: "byok-approval-mcp", version: "0.0.1" }
|
|
562
|
+
}
|
|
563
|
+
};
|
|
564
|
+
}
|
|
565
|
+
if (req.method === "notifications/initialized") {
|
|
566
|
+
return void 0;
|
|
567
|
+
}
|
|
568
|
+
if (req.method === "tools/list") {
|
|
569
|
+
return {
|
|
570
|
+
jsonrpc: "2.0",
|
|
571
|
+
id,
|
|
572
|
+
result: {
|
|
573
|
+
tools: [
|
|
574
|
+
{
|
|
575
|
+
name: APPROVAL_TOOL_NAME,
|
|
576
|
+
description: "Requests operator approval for a pending tool call. Blocks until a human (or this device's daemon) decides, or the configured timeout elapses (fail-closed deny on timeout).",
|
|
577
|
+
inputSchema: {
|
|
578
|
+
type: "object",
|
|
579
|
+
properties: {
|
|
580
|
+
tool_name: { type: "string" },
|
|
581
|
+
input: { type: "object" }
|
|
582
|
+
}
|
|
583
|
+
}
|
|
584
|
+
}
|
|
585
|
+
]
|
|
586
|
+
}
|
|
587
|
+
};
|
|
588
|
+
}
|
|
589
|
+
if (req.method === "tools/call") {
|
|
590
|
+
const params = req.params ?? {};
|
|
591
|
+
if (params.name !== APPROVAL_TOOL_NAME) {
|
|
592
|
+
return { jsonrpc: "2.0", id, error: { code: -32602, message: `unknown tool "${String(params.name)}"` } };
|
|
593
|
+
}
|
|
594
|
+
const args = params.arguments ?? {};
|
|
595
|
+
const toolName = typeof args.tool_name === "string" ? args.tool_name : "unknown tool";
|
|
596
|
+
const input = args.input ?? {};
|
|
597
|
+
const summary = summarizeToolCall(toolName, input);
|
|
598
|
+
let outcome;
|
|
599
|
+
try {
|
|
600
|
+
outcome = await deps.requestApproval(taskId, summary);
|
|
601
|
+
} catch (err) {
|
|
602
|
+
outcome = { approved: false, reason: `could not reach the approving device: ${errorMessage2(err)}` };
|
|
603
|
+
}
|
|
604
|
+
const payload = outcome.approved ? { behavior: "allow", updatedInput: input } : { behavior: "deny", message: outcome.reason ?? "denied" };
|
|
605
|
+
return { jsonrpc: "2.0", id, result: { content: [{ type: "text", text: JSON.stringify(payload) }] } };
|
|
606
|
+
}
|
|
607
|
+
if (id !== void 0) {
|
|
608
|
+
return { jsonrpc: "2.0", id, error: { code: -32601, message: `unknown method: ${String(req.method)}` } };
|
|
609
|
+
}
|
|
610
|
+
return void 0;
|
|
611
|
+
}
|
|
612
|
+
function serveApprovalMcpOverStdio(opts) {
|
|
613
|
+
const input = opts.input ?? process.stdin;
|
|
614
|
+
const output = opts.output ?? process.stdout;
|
|
615
|
+
const rl = createInterface({ input, terminal: false });
|
|
616
|
+
rl.on("line", (line) => {
|
|
617
|
+
const trimmed = line.trim();
|
|
618
|
+
if (!trimmed) return;
|
|
619
|
+
let parsed;
|
|
620
|
+
try {
|
|
621
|
+
parsed = JSON.parse(trimmed);
|
|
622
|
+
} catch {
|
|
623
|
+
return;
|
|
624
|
+
}
|
|
625
|
+
void handleMcpRequest(parsed, opts.deps, opts.taskId).then((response) => {
|
|
626
|
+
if (response !== void 0) output.write(`${JSON.stringify(response)}
|
|
627
|
+
`);
|
|
628
|
+
});
|
|
629
|
+
});
|
|
630
|
+
}
|
|
631
|
+
|
|
632
|
+
// src/bin/sdk-reserved-helper-runners.ts
|
|
633
|
+
var APPROVAL_REQUEST_TIMEOUT_SLOP_MS = 5e3;
|
|
634
|
+
function required(name) {
|
|
635
|
+
const value = process.env[name];
|
|
636
|
+
if (!value) throw new Error(`missing required environment variable ${name}`);
|
|
637
|
+
return value;
|
|
638
|
+
}
|
|
639
|
+
function waitForInputClose(input = process.stdin) {
|
|
640
|
+
if (input.readableEnded || input.destroyed) return Promise.resolve();
|
|
641
|
+
return new Promise((resolve) => {
|
|
642
|
+
const done = () => {
|
|
643
|
+
input.off("end", done);
|
|
644
|
+
input.off("close", done);
|
|
645
|
+
resolve();
|
|
646
|
+
};
|
|
647
|
+
input.once("end", done);
|
|
648
|
+
input.once("close", done);
|
|
649
|
+
});
|
|
650
|
+
}
|
|
651
|
+
async function runAgentMessageMcp() {
|
|
652
|
+
const storeDir = required("BYOK_STORE_DIR");
|
|
653
|
+
const productId = required("BYOK_PRODUCT_ID");
|
|
654
|
+
const contextToken = required("BYOK_AGENT_MESSAGE_CONTEXT");
|
|
655
|
+
let clientPromise;
|
|
656
|
+
const client = async () => {
|
|
657
|
+
if (!clientPromise) clientPromise = connectControlClient({ storeDir, productId }).then((result) => {
|
|
658
|
+
if (!result.ok) throw new Error(result.reason);
|
|
659
|
+
return result.client;
|
|
660
|
+
});
|
|
661
|
+
return clientPromise;
|
|
662
|
+
};
|
|
663
|
+
const deps = {
|
|
664
|
+
publish: async (input) => (await client()).request("agent_messages.publish", { contextToken, ...input })
|
|
665
|
+
};
|
|
666
|
+
serveAgentMessageMcpOverStdio({ deps });
|
|
667
|
+
await waitForInputClose();
|
|
668
|
+
}
|
|
669
|
+
async function runAgentMemoryMcp() {
|
|
670
|
+
const storeDir = required("BYOK_STORE_DIR");
|
|
671
|
+
const productId = required("BYOK_PRODUCT_ID");
|
|
672
|
+
const contextToken = required("BYOK_AGENT_MEMORY_CONTEXT");
|
|
673
|
+
let clientPromise;
|
|
674
|
+
const client = async () => {
|
|
675
|
+
if (!clientPromise) clientPromise = connectControlClient({ storeDir, productId }).then((result) => {
|
|
676
|
+
if (!result.ok) throw new Error(result.reason);
|
|
677
|
+
return result.client;
|
|
678
|
+
});
|
|
679
|
+
return clientPromise;
|
|
680
|
+
};
|
|
681
|
+
const deps = {
|
|
682
|
+
recall: async (input) => (await client()).request("agent_memory.recall", { contextToken, ...input }),
|
|
683
|
+
save: async (input) => (await client()).request("agent_memory.save", { contextToken, ...input })
|
|
684
|
+
};
|
|
685
|
+
serveAgentMemoryMcpOverStdio({ deps });
|
|
686
|
+
await waitForInputClose();
|
|
687
|
+
}
|
|
688
|
+
async function runApprovalMcp() {
|
|
689
|
+
const storeDir = required("BYOK_STORE_DIR");
|
|
690
|
+
const productId = required("BYOK_PRODUCT_ID");
|
|
691
|
+
const taskId = required("BYOK_TASK_ID");
|
|
692
|
+
const timeoutMs = Number(process.env.BYOK_APPROVAL_TIMEOUT_MS ?? "600000");
|
|
693
|
+
if (!Number.isFinite(timeoutMs) || timeoutMs <= 0) {
|
|
694
|
+
throw new Error("invalid BYOK_APPROVAL_TIMEOUT_MS environment variable");
|
|
695
|
+
}
|
|
696
|
+
let clientPromise;
|
|
697
|
+
const client = async () => {
|
|
698
|
+
if (!clientPromise) clientPromise = connectControlClient({
|
|
699
|
+
storeDir,
|
|
700
|
+
productId,
|
|
701
|
+
requestTimeoutMs: timeoutMs + APPROVAL_REQUEST_TIMEOUT_SLOP_MS
|
|
702
|
+
}).then((result) => {
|
|
703
|
+
if (!result.ok) throw new Error(result.reason);
|
|
704
|
+
return result.client;
|
|
705
|
+
});
|
|
706
|
+
return clientPromise;
|
|
707
|
+
};
|
|
708
|
+
const deps = {
|
|
709
|
+
requestApproval: async (requestedTaskId, summary) => {
|
|
710
|
+
try {
|
|
711
|
+
return await (await client()).request("approvals.request", { taskId: requestedTaskId, summary });
|
|
712
|
+
} catch (error) {
|
|
713
|
+
clientPromise = void 0;
|
|
714
|
+
throw error;
|
|
715
|
+
}
|
|
716
|
+
}
|
|
717
|
+
};
|
|
718
|
+
serveApprovalMcpOverStdio({ taskId, deps });
|
|
719
|
+
await waitForInputClose();
|
|
720
|
+
}
|
|
721
|
+
async function runAgentTeamMcp() {
|
|
722
|
+
const storeDir = required("BYOK_STORE_DIR");
|
|
723
|
+
const productId = required("BYOK_PRODUCT_ID");
|
|
724
|
+
const lease = required("BYOK_TEAM_MEMBER_CONTEXT");
|
|
725
|
+
let clientPromise;
|
|
726
|
+
const client = async () => {
|
|
727
|
+
if (!clientPromise) clientPromise = connectControlClient({ storeDir, productId }).then((result) => {
|
|
728
|
+
if (!result.ok) throw new Error(result.reason);
|
|
729
|
+
return result.client;
|
|
730
|
+
});
|
|
731
|
+
return clientPromise;
|
|
732
|
+
};
|
|
733
|
+
const deps = {
|
|
734
|
+
post: async (input) => (await client()).request("team_messages.post", { context: lease, ...input }),
|
|
735
|
+
read: async (input) => (await client()).request("team_messages.read", { context: lease, ...input }),
|
|
736
|
+
ack: async (input) => (await client()).request("team_messages.ack", { context: lease, ...input })
|
|
737
|
+
};
|
|
738
|
+
serveTeamMcpOverStdio({ deps });
|
|
739
|
+
await waitForInputClose();
|
|
740
|
+
}
|
|
741
|
+
async function runSdkReservedHelper(kind) {
|
|
742
|
+
switch (kind) {
|
|
743
|
+
case "agent-message-mcp":
|
|
744
|
+
await runAgentMessageMcp();
|
|
745
|
+
return;
|
|
746
|
+
case "agent-memory-mcp":
|
|
747
|
+
await runAgentMemoryMcp();
|
|
748
|
+
return;
|
|
749
|
+
case "approval-mcp":
|
|
750
|
+
await runApprovalMcp();
|
|
751
|
+
return;
|
|
752
|
+
case "agent-team-mcp":
|
|
753
|
+
await runAgentTeamMcp();
|
|
754
|
+
return;
|
|
755
|
+
}
|
|
756
|
+
}
|
|
757
|
+
|
|
758
|
+
// src/bin/byok-agent-team-mcp.ts
|
|
759
|
+
runSdkReservedHelper("agent-team-mcp").catch((error) => {
|
|
760
|
+
process.stderr.write(`byok-agent-team-mcp: ${error instanceof Error ? error.message : String(error)}
|
|
761
|
+
`);
|
|
762
|
+
process.exit(1);
|
|
763
|
+
});
|
|
764
|
+
//# sourceMappingURL=byok-agent-team-mcp.js.map
|
|
765
|
+
//# sourceMappingURL=byok-agent-team-mcp.js.map
|