github-router 0.3.121 → 0.3.122

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.
@@ -40,6 +40,7 @@ const state = {
40
40
  showToken: false,
41
41
  extendedBetas: false,
42
42
  browseEnabled: false,
43
+ fleetEnabled: false,
43
44
  powerBrowseEnabled: false,
44
45
  humanlikeForce: "auto",
45
46
  sessionId: randomUUID(),
@@ -1045,6 +1046,1273 @@ function collapsePathKeys(env) {
1045
1046
  return env;
1046
1047
  }
1047
1048
 
1049
+ //#endregion
1050
+ //#region src/lib/artifact/client.ts
1051
+ var ArtifactError = class extends Error {
1052
+ code;
1053
+ retryable;
1054
+ status;
1055
+ detail;
1056
+ constructor(args) {
1057
+ super(args.message);
1058
+ this.name = "ArtifactError";
1059
+ this.code = args.code;
1060
+ this.retryable = args.retryable;
1061
+ this.status = args.status;
1062
+ this.detail = args.detail;
1063
+ }
1064
+ };
1065
+ var ArtifactClient = class {
1066
+ baseUrl;
1067
+ token;
1068
+ sessionId;
1069
+ fetchFn;
1070
+ constructor(options) {
1071
+ this.baseUrl = options.baseUrl.replace(/\/+$/, "");
1072
+ this.token = options.token;
1073
+ this.sessionId = options.sessionId;
1074
+ this.fetchFn = options.fetchFn ?? globalThis.fetch.bind(globalThis);
1075
+ }
1076
+ open(file, signal) {
1077
+ return this.request("POST", `/api/artifact/${encodeURIComponent(this.sessionId)}/open`, { file }, signal);
1078
+ }
1079
+ poll(timeoutMsHint, signal) {
1080
+ return this.request("GET", `/api/artifact/${encodeURIComponent(this.sessionId)}/poll`, void 0, signal, timeoutMsHint);
1081
+ }
1082
+ agentReply(text, signal) {
1083
+ return this.request("POST", `/api/artifact/${encodeURIComponent(this.sessionId)}/agent-reply`, { text }, signal, void 0, true);
1084
+ }
1085
+ async request(method, pathname, body, signal, timeoutMsHint, allowEmptyJson = false) {
1086
+ let url;
1087
+ try {
1088
+ url = new URL(pathname, `${this.baseUrl}/`);
1089
+ } catch (err) {
1090
+ throw new ArtifactError({
1091
+ code: "UNREACHABLE",
1092
+ message: "artifact API base URL is invalid",
1093
+ retryable: false,
1094
+ detail: err
1095
+ });
1096
+ }
1097
+ const timeout = combineSignalAndTimeout(signal, timeoutMsHint);
1098
+ let response;
1099
+ try {
1100
+ response = await this.fetchFn(url.toString(), {
1101
+ method,
1102
+ headers: {
1103
+ Authorization: `Bearer ${this.token}`,
1104
+ ...body === void 0 ? {} : { "Content-Type": "application/json" }
1105
+ },
1106
+ body: body === void 0 ? void 0 : JSON.stringify(body),
1107
+ redirect: "error",
1108
+ signal: timeout.signal
1109
+ });
1110
+ } catch (err) {
1111
+ throw mapNetworkError$1(err);
1112
+ } finally {
1113
+ timeout.cleanup();
1114
+ }
1115
+ if (!response.ok) throw await mapHttpError$1(response);
1116
+ const text = await response.text().catch((err) => {
1117
+ throw new ArtifactError({
1118
+ code: "INVALID_RESPONSE",
1119
+ message: "artifact API response body could not be read",
1120
+ retryable: false,
1121
+ detail: err
1122
+ });
1123
+ });
1124
+ if (!text && allowEmptyJson) return {};
1125
+ try {
1126
+ return JSON.parse(text);
1127
+ } catch (err) {
1128
+ throw new ArtifactError({
1129
+ code: "INVALID_RESPONSE",
1130
+ message: "artifact API returned a non-JSON response",
1131
+ retryable: false,
1132
+ detail: err
1133
+ });
1134
+ }
1135
+ }
1136
+ };
1137
+ function combineSignalAndTimeout(signal, timeoutMsHint) {
1138
+ const timeoutMs = typeof timeoutMsHint === "number" && Number.isFinite(timeoutMsHint) && timeoutMsHint > 0 ? timeoutMsHint : void 0;
1139
+ if (timeoutMs === void 0) return {
1140
+ signal,
1141
+ cleanup: () => {}
1142
+ };
1143
+ const controller = new AbortController();
1144
+ const abortFromCaller = () => {
1145
+ try {
1146
+ controller.abort(signal?.reason);
1147
+ } catch {
1148
+ controller.abort();
1149
+ }
1150
+ };
1151
+ if (signal?.aborted) abortFromCaller();
1152
+ signal?.addEventListener("abort", abortFromCaller, { once: true });
1153
+ const timer = setTimeout(() => {
1154
+ try {
1155
+ controller.abort(new DOMException("artifact API request timed out", "TimeoutError"));
1156
+ } catch {
1157
+ controller.abort();
1158
+ }
1159
+ }, timeoutMs);
1160
+ return {
1161
+ signal: controller.signal,
1162
+ cleanup: () => {
1163
+ clearTimeout(timer);
1164
+ signal?.removeEventListener("abort", abortFromCaller);
1165
+ }
1166
+ };
1167
+ }
1168
+ async function mapHttpError$1(response) {
1169
+ const detail = await readErrorDetail$1(response);
1170
+ const upstreamMessage = detailToMessage$1(detail);
1171
+ const suffix = upstreamMessage ? `: ${upstreamMessage}` : "";
1172
+ if (response.status === 401 || response.status === 403) return new ArtifactError({
1173
+ code: "AUTH_FAILED",
1174
+ message: `artifact API authentication failed (${response.status})${suffix}`,
1175
+ retryable: false,
1176
+ status: response.status,
1177
+ detail
1178
+ });
1179
+ if (response.status === 404) return new ArtifactError({
1180
+ code: "NOT_FOUND",
1181
+ message: `artifact session or resource not found (404)${suffix}`,
1182
+ retryable: false,
1183
+ status: response.status,
1184
+ detail
1185
+ });
1186
+ if (response.status === 408 || response.status === 504) return new ArtifactError({
1187
+ code: "TIMEOUT",
1188
+ message: `artifact API request timed out (${response.status})${suffix}`,
1189
+ retryable: true,
1190
+ status: response.status,
1191
+ detail
1192
+ });
1193
+ return new ArtifactError({
1194
+ code: "UPSTREAM_ERROR",
1195
+ message: `artifact API returned HTTP ${response.status}${suffix}`,
1196
+ retryable: response.status === 429 || response.status >= 500,
1197
+ status: response.status,
1198
+ detail
1199
+ });
1200
+ }
1201
+ function mapNetworkError$1(err) {
1202
+ if (isAbortLike$1(err)) return new ArtifactError({
1203
+ code: "TIMEOUT",
1204
+ message: "artifact API request timed out or was aborted",
1205
+ retryable: true,
1206
+ detail: err
1207
+ });
1208
+ return new ArtifactError({
1209
+ code: "UNREACHABLE",
1210
+ message: `artifact API unreachable: ${err instanceof Error ? err.message : String(err)}`,
1211
+ retryable: true,
1212
+ detail: err
1213
+ });
1214
+ }
1215
+ async function readErrorDetail$1(response) {
1216
+ const text = await response.text().catch(() => "");
1217
+ if (!text) return void 0;
1218
+ try {
1219
+ return JSON.parse(text);
1220
+ } catch {
1221
+ return text;
1222
+ }
1223
+ }
1224
+ function detailToMessage$1(detail) {
1225
+ if (typeof detail === "string") return detail;
1226
+ if (typeof detail !== "object" || detail === null) return void 0;
1227
+ const record = detail;
1228
+ const error = record.error;
1229
+ if (typeof error === "string") return error;
1230
+ if (typeof error === "object" && error !== null) {
1231
+ const errorRecord = error;
1232
+ if (typeof errorRecord.message === "string") return errorRecord.message;
1233
+ if (typeof errorRecord.code === "string") return errorRecord.code;
1234
+ }
1235
+ if (typeof record.message === "string") return record.message;
1236
+ }
1237
+ function isAbortLike$1(err) {
1238
+ return err instanceof Error && (err.name === "AbortError" || err.name === "TimeoutError");
1239
+ }
1240
+
1241
+ //#endregion
1242
+ //#region src/lib/artifact/tools.ts
1243
+ const ARTIFACT_GROUP = "peers";
1244
+ const ARTIFACT_POLL_TOOL_BUDGET_MS = 5e4;
1245
+ const ARTIFACT_SINGLE_POLL_TIMEOUT_MS = 25e3;
1246
+ const ARTIFACT_POLL_RETURN_MARGIN_MS = 1e3;
1247
+ const ARTIFACT_MAX_POLLS_PER_TOOL_CALL = 2;
1248
+ function tool(toolNameHttp, description, inputSchema, handler) {
1249
+ return {
1250
+ toolNameHttp,
1251
+ group: ARTIFACT_GROUP,
1252
+ capability: "artifact",
1253
+ description,
1254
+ inputSchema,
1255
+ async handler(args, signal) {
1256
+ try {
1257
+ return await handler(args, signal);
1258
+ } catch (err) {
1259
+ return errorResult$1(err);
1260
+ }
1261
+ }
1262
+ };
1263
+ }
1264
+ const ARTIFACT_TOOLS = Object.freeze([
1265
+ tool("artifact_open", "Open a workspace file in ai-or-die's Artifact review panel for human review. Only works inside an ai-or-die tab-backed Claude session.", objectSchema$1({ file: stringProp$1("Workspace-relative or absolute file path to show in the Artifact panel.") }, ["file"]), async (args, signal) => {
1266
+ const env = readArtifactEnv();
1267
+ if (!env) return missingEnvResult();
1268
+ const file = requiredString$1(args, "file");
1269
+ return ok$1({
1270
+ viewUrl: (await clientFromEnv(env).open(file, signal)).viewUrl,
1271
+ next_step: "Tell the user to review at the Artifact panel, then call artifact_poll."
1272
+ });
1273
+ }),
1274
+ tool("artifact_poll", "Wait for human Artifact review feedback from ai-or-die and return the prompts/layout warnings/DOM snapshot for the agent to act on. Only works inside an ai-or-die tab-backed Claude session.", objectSchema$1({}, []), async (_args, signal) => {
1275
+ const env = readArtifactEnv();
1276
+ if (!env) return missingEnvResult();
1277
+ return ok$1(formatPollResponse(await pollUntilReady(clientFromEnv(env), signal)));
1278
+ }),
1279
+ tool("artifact_reply", "Send the agent's reply back to the ai-or-die Artifact review panel after applying or responding to human feedback. Only works inside an ai-or-die tab-backed Claude session.", objectSchema$1({ text: stringProp$1("Agent reply text to deliver to the human Artifact review panel.") }, ["text"]), async (args, signal) => {
1280
+ const env = readArtifactEnv();
1281
+ if (!env) return missingEnvResult();
1282
+ const text = requiredString$1(args, "text");
1283
+ return ok$1({
1284
+ ok: true,
1285
+ ...await clientFromEnv(env).agentReply(text, signal),
1286
+ next_step: "Wait for further human review, or continue if the review loop is complete."
1287
+ });
1288
+ })
1289
+ ]);
1290
+ function readArtifactEnv() {
1291
+ const baseUrl = process.env.AIORDIE_BASE_URL;
1292
+ const token = process.env.AIORDIE_TOKEN;
1293
+ const sessionId = process.env.AIORDIE_SESSION_ID;
1294
+ if (!baseUrl || !token || !sessionId) return void 0;
1295
+ return {
1296
+ baseUrl,
1297
+ token,
1298
+ sessionId
1299
+ };
1300
+ }
1301
+ function clientFromEnv(env) {
1302
+ return new ArtifactClient(env);
1303
+ }
1304
+ async function pollUntilReady(client, signal) {
1305
+ const deadline = Date.now() + ARTIFACT_POLL_TOOL_BUDGET_MS;
1306
+ let last;
1307
+ let attempts = 0;
1308
+ while (!signal?.aborted && attempts < ARTIFACT_MAX_POLLS_PER_TOOL_CALL) {
1309
+ attempts += 1;
1310
+ const remaining = deadline - Date.now();
1311
+ if (remaining <= ARTIFACT_POLL_RETURN_MARGIN_MS) break;
1312
+ const timeoutMsHint = Math.min(ARTIFACT_SINGLE_POLL_TIMEOUT_MS, Math.max(1, remaining - ARTIFACT_POLL_RETURN_MARGIN_MS));
1313
+ last = await client.poll(timeoutMsHint, signal);
1314
+ if (!isWaitingPoll(last)) return last;
1315
+ if (deadline - Date.now() <= ARTIFACT_POLL_RETURN_MARGIN_MS) break;
1316
+ }
1317
+ return {
1318
+ ...last ?? { status: "waiting" },
1319
+ status: "waiting",
1320
+ next_step: "No human feedback is ready yet. Call artifact_poll again."
1321
+ };
1322
+ }
1323
+ function isWaitingPoll(response) {
1324
+ if (hasFeedback(response.prompts)) return false;
1325
+ const status = response.status.toLowerCase();
1326
+ return status === "waiting" || status === "pending" || status === "open" || status === "idle" || status === "timeout" || status === "no_feedback";
1327
+ }
1328
+ function hasFeedback(prompts) {
1329
+ if (Array.isArray(prompts)) return prompts.length > 0;
1330
+ if (typeof prompts === "string") return prompts.trim() !== "";
1331
+ if (typeof prompts === "object" && prompts !== null) return Object.keys(prompts).length > 0;
1332
+ return prompts !== void 0 && prompts !== null;
1333
+ }
1334
+ function formatPollResponse(response) {
1335
+ return definedObject$1({
1336
+ status: response.status,
1337
+ prompts: response.prompts,
1338
+ layout_warnings: response.layout_warnings,
1339
+ dom_snapshot: response.dom_snapshot,
1340
+ next_step: response.next_step ?? defaultPollNextStep(response.status)
1341
+ });
1342
+ }
1343
+ function defaultPollNextStep(status) {
1344
+ return isWaitingStatus(status) ? "No human feedback is ready yet. Call artifact_poll again." : "Apply the human Artifact review feedback, then call artifact_reply with a concise summary.";
1345
+ }
1346
+ function isWaitingStatus(status) {
1347
+ const normalized = status.toLowerCase();
1348
+ return normalized === "waiting" || normalized === "pending" || normalized === "open" || normalized === "idle" || normalized === "timeout" || normalized === "no_feedback";
1349
+ }
1350
+ function requiredString$1(args, key) {
1351
+ const value = args[key];
1352
+ if (typeof value !== "string" || value.trim() === "") throw new ArtifactToolInputError("INVALID_ARGUMENT", `arguments.${key} is required and must be a non-empty string`);
1353
+ return value;
1354
+ }
1355
+ var ArtifactToolInputError = class extends Error {
1356
+ code;
1357
+ constructor(code, message) {
1358
+ super(message);
1359
+ this.name = "ArtifactToolInputError";
1360
+ this.code = code;
1361
+ }
1362
+ };
1363
+ function missingEnvResult() {
1364
+ return jsonResult$1({ error: {
1365
+ code: "NOT_IN_AIORDIE_TAB",
1366
+ message: "artifact tools only work inside an ai-or-die tab-backed Claude session. Missing AIORDIE_BASE_URL, AIORDIE_TOKEN, or AIORDIE_SESSION_ID."
1367
+ } }, true);
1368
+ }
1369
+ function ok$1(value) {
1370
+ return jsonResult$1(value, false);
1371
+ }
1372
+ function jsonResult$1(value, isError) {
1373
+ return {
1374
+ content: [{
1375
+ type: "text",
1376
+ text: JSON.stringify(value)
1377
+ }],
1378
+ ...isError ? { isError: true } : {}
1379
+ };
1380
+ }
1381
+ function errorResult$1(err) {
1382
+ if (err instanceof ArtifactError) return jsonResult$1({ error: definedObject$1({
1383
+ code: err.code,
1384
+ message: err.message,
1385
+ retryable: err.retryable,
1386
+ status: err.status
1387
+ }) }, true);
1388
+ return jsonResult$1({ error: {
1389
+ code: errorCode$1(err),
1390
+ message: err instanceof Error ? err.message : String(err)
1391
+ } }, true);
1392
+ }
1393
+ function errorCode$1(err) {
1394
+ if (typeof err === "object" && err !== null && "code" in err) {
1395
+ const code = err.code;
1396
+ if (typeof code === "string") return code;
1397
+ }
1398
+ return "ARTIFACT_ERROR";
1399
+ }
1400
+ function definedObject$1(input) {
1401
+ const result = {};
1402
+ for (const [key, value] of Object.entries(input)) if (value !== void 0) result[key] = value;
1403
+ return result;
1404
+ }
1405
+ function objectSchema$1(properties, required) {
1406
+ return {
1407
+ type: "object",
1408
+ required,
1409
+ additionalProperties: false,
1410
+ properties
1411
+ };
1412
+ }
1413
+ function stringProp$1(description) {
1414
+ return {
1415
+ type: "string",
1416
+ description
1417
+ };
1418
+ }
1419
+
1420
+ //#endregion
1421
+ //#region src/lib/fleet/client.ts
1422
+ var FleetError = class extends Error {
1423
+ code;
1424
+ retryable;
1425
+ status;
1426
+ detail;
1427
+ constructor(args) {
1428
+ super(args.message);
1429
+ this.name = "FleetError";
1430
+ this.code = args.code;
1431
+ this.retryable = args.retryable;
1432
+ this.status = args.status;
1433
+ this.detail = args.detail;
1434
+ }
1435
+ };
1436
+ function encodeSessionId(instanceId, localId) {
1437
+ return `${instanceId}:${localId}`;
1438
+ }
1439
+ function decodeSessionId(globalId) {
1440
+ const idx = globalId.indexOf(":");
1441
+ if (idx <= 0 || idx === globalId.length - 1) throw new FleetError({
1442
+ code: "SESSION_NOT_FOUND",
1443
+ message: `invalid fleet sessionId ${JSON.stringify(globalId)}; expected "instanceId:localSessionId"`,
1444
+ retryable: false
1445
+ });
1446
+ return {
1447
+ instanceId: globalId.slice(0, idx),
1448
+ localId: globalId.slice(idx + 1)
1449
+ };
1450
+ }
1451
+ var FleetClient = class {
1452
+ baseUrl;
1453
+ token;
1454
+ fetchFn;
1455
+ constructor(options) {
1456
+ this.baseUrl = options.url.replace(/\/+$/, "");
1457
+ this.token = options.token;
1458
+ this.fetchFn = options.fetchFn ?? globalThis.fetch.bind(globalThis);
1459
+ }
1460
+ listSessions(signal) {
1461
+ return this.request("GET", "/api/control/sessions", void 0, void 0, signal);
1462
+ }
1463
+ status(sessionId, signal) {
1464
+ return this.request("GET", `/api/control/sessions/${encodeURIComponent(sessionId)}/status`, void 0, void 0, signal);
1465
+ }
1466
+ readSession(sessionId, lines, signal) {
1467
+ return this.request("GET", `/api/control/sessions/${encodeURIComponent(sessionId)}/read`, lines === void 0 ? void 0 : { lines: String(lines) }, void 0, signal);
1468
+ }
1469
+ createSession(input, signal) {
1470
+ return this.request("POST", "/api/control/sessions/create", void 0, input, signal);
1471
+ }
1472
+ stopSession(sessionId, modeOrInput, idempotencyKeyOrSignal, signal) {
1473
+ const body = {};
1474
+ let requestSignal;
1475
+ if (typeof modeOrInput === "object" && modeOrInput !== null) {
1476
+ if (modeOrInput.mode !== void 0) body.mode = modeOrInput.mode;
1477
+ if (modeOrInput.idempotencyKey !== void 0) body.idempotencyKey = modeOrInput.idempotencyKey;
1478
+ requestSignal = typeof idempotencyKeyOrSignal === "string" ? signal : idempotencyKeyOrSignal;
1479
+ } else {
1480
+ if (modeOrInput !== void 0) body.mode = modeOrInput;
1481
+ if (typeof idempotencyKeyOrSignal === "string") {
1482
+ body.idempotencyKey = idempotencyKeyOrSignal;
1483
+ requestSignal = signal;
1484
+ } else requestSignal = idempotencyKeyOrSignal;
1485
+ }
1486
+ return this.request("POST", `/api/control/sessions/${encodeURIComponent(sessionId)}/stop`, void 0, body, requestSignal);
1487
+ }
1488
+ sendMessage(sessionId, input, signal) {
1489
+ return this.request("POST", `/api/control/sessions/${encodeURIComponent(sessionId)}/message`, void 0, input, signal);
1490
+ }
1491
+ sendKeys(sessionId, input, signal) {
1492
+ return this.request("POST", `/api/control/sessions/${encodeURIComponent(sessionId)}/keys`, void 0, input, signal);
1493
+ }
1494
+ respond(sessionId, input, signal) {
1495
+ return this.request("POST", `/api/control/sessions/${encodeURIComponent(sessionId)}/respond`, void 0, input, signal);
1496
+ }
1497
+ waitEvents(input, signal) {
1498
+ const query = {};
1499
+ if (input.cursor !== void 0) query.cursor = input.cursor;
1500
+ if (input.timeoutMs !== void 0) query.timeoutMs = String(input.timeoutMs);
1501
+ if (input.sessionIds !== void 0) query.sessionIds = input.sessionIds.join(",");
1502
+ if (input.kinds !== void 0) query.kinds = input.kinds.join(",");
1503
+ return this.request("GET", "/api/control/events", query, void 0, signal);
1504
+ }
1505
+ readFile(pathValue, signal) {
1506
+ return this.request("GET", "/api/files/content", { path: pathValue }, void 0, signal);
1507
+ }
1508
+ listDir(pathValue, signal) {
1509
+ return this.request("GET", "/api/files", { path: pathValue }, void 0, signal);
1510
+ }
1511
+ search(queryValue, pathValue, signal) {
1512
+ const query = { q: queryValue };
1513
+ if (pathValue !== void 0) query.path = pathValue;
1514
+ return this.request("GET", "/api/search", query, void 0, signal);
1515
+ }
1516
+ gitShow(input, signal) {
1517
+ const query = {};
1518
+ for (const [key, value] of Object.entries(input)) {
1519
+ if (value === void 0 || value === null) continue;
1520
+ if (key === "instance") continue;
1521
+ query[key] = String(value);
1522
+ }
1523
+ return this.request("GET", "/api/files/git-show", query, void 0, signal);
1524
+ }
1525
+ async request(method, pathname, query, body, signal) {
1526
+ const url = new URL(pathname, `${this.baseUrl}/`);
1527
+ for (const [key, value] of Object.entries(query ?? {})) url.searchParams.set(key, value);
1528
+ let response;
1529
+ try {
1530
+ response = await this.fetchFn(url.toString(), {
1531
+ method,
1532
+ headers: {
1533
+ Authorization: `Bearer ${this.token}`,
1534
+ ...body === void 0 ? {} : { "Content-Type": "application/json" }
1535
+ },
1536
+ body: body === void 0 ? void 0 : JSON.stringify(body),
1537
+ redirect: "error",
1538
+ signal
1539
+ });
1540
+ } catch (err) {
1541
+ throw mapNetworkError(err);
1542
+ }
1543
+ if (!response.ok) throw await mapHttpError(response);
1544
+ return await response.json();
1545
+ }
1546
+ };
1547
+ async function mapHttpError(response) {
1548
+ const detail = await readErrorDetail(response);
1549
+ const upstreamMessage = detailToMessage(detail);
1550
+ const suffix = upstreamMessage ? `: ${upstreamMessage}` : "";
1551
+ if (response.status === 401 || response.status === 403) return new FleetError({
1552
+ code: "AUTH_FAILED",
1553
+ message: `fleet instance authentication failed (${response.status})${suffix}`,
1554
+ retryable: false,
1555
+ status: response.status,
1556
+ detail
1557
+ });
1558
+ if (response.status === 404) return new FleetError({
1559
+ code: "SESSION_NOT_FOUND",
1560
+ message: `fleet session or resource not found (404)${suffix}`,
1561
+ retryable: false,
1562
+ status: response.status,
1563
+ detail
1564
+ });
1565
+ if (response.status === 409 || response.status === 412) return new FleetError({
1566
+ code: "PRECONDITION_FAILED",
1567
+ message: `fleet instance precondition failed (${response.status})${suffix}`,
1568
+ retryable: false,
1569
+ status: response.status,
1570
+ detail
1571
+ });
1572
+ if (response.status === 408 || response.status === 504) return new FleetError({
1573
+ code: "TIMEOUT",
1574
+ message: `fleet instance request timed out (${response.status})${suffix}`,
1575
+ retryable: true,
1576
+ status: response.status,
1577
+ detail
1578
+ });
1579
+ return new FleetError({
1580
+ code: "UPSTREAM_ERROR",
1581
+ message: `fleet instance returned HTTP ${response.status}${suffix}`,
1582
+ retryable: response.status === 429 || response.status >= 500,
1583
+ status: response.status,
1584
+ detail
1585
+ });
1586
+ }
1587
+ function mapNetworkError(err) {
1588
+ if (isAbortLike(err)) return new FleetError({
1589
+ code: "TIMEOUT",
1590
+ message: "fleet instance request timed out or was aborted",
1591
+ retryable: true,
1592
+ detail: err
1593
+ });
1594
+ return new FleetError({
1595
+ code: "UNREACHABLE",
1596
+ message: `fleet instance unreachable: ${err instanceof Error ? err.message : String(err)}`,
1597
+ retryable: true,
1598
+ detail: err
1599
+ });
1600
+ }
1601
+ async function readErrorDetail(response) {
1602
+ const text = await response.text().catch(() => "");
1603
+ if (!text) return void 0;
1604
+ try {
1605
+ return JSON.parse(text);
1606
+ } catch {
1607
+ return text;
1608
+ }
1609
+ }
1610
+ function detailToMessage(detail) {
1611
+ if (typeof detail === "string") return detail;
1612
+ if (typeof detail !== "object" || detail === null) return void 0;
1613
+ const record = detail;
1614
+ const error = record.error;
1615
+ if (typeof error === "string") return error;
1616
+ if (typeof error === "object" && error !== null) {
1617
+ const errorRecord = error;
1618
+ if (typeof errorRecord.message === "string") return errorRecord.message;
1619
+ if (typeof errorRecord.code === "string") return errorRecord.code;
1620
+ }
1621
+ if (typeof record.message === "string") return record.message;
1622
+ }
1623
+ function isAbortLike(err) {
1624
+ return err instanceof Error && (err.name === "AbortError" || err.name === "TimeoutError");
1625
+ }
1626
+
1627
+ //#endregion
1628
+ //#region src/lib/fleet/registry.ts
1629
+ var FleetRegistryError = class extends Error {
1630
+ code;
1631
+ constructor(code, message) {
1632
+ super(message);
1633
+ this.name = "FleetRegistryError";
1634
+ this.code = code;
1635
+ }
1636
+ };
1637
+ function defaultFleetConfigPath() {
1638
+ return process.env.GH_ROUTER_FLEET_CONFIG || nodePath.join(os.homedir(), ".local", "share", "github-router", "fleet.json");
1639
+ }
1640
+ async function loadFleetRegistryConfig(configPath = defaultFleetConfigPath()) {
1641
+ let stat$1;
1642
+ try {
1643
+ stat$1 = await fs.stat(configPath);
1644
+ } catch (err) {
1645
+ if (isNodeErrorCode(err, "ENOENT")) return { instances: [] };
1646
+ throw err;
1647
+ }
1648
+ if (process.platform !== "win32" && (stat$1.mode & 63) !== 0) console.warn(`[fleet] Registry file ${configPath} is group/other-readable; it contains bearer tokens. Consider chmod 600.`);
1649
+ const raw = await fs.readFile(configPath, "utf8");
1650
+ if (raw.trim() === "") return { instances: [] };
1651
+ const parsed = JSON.parse(raw);
1652
+ if (!isObject(parsed)) throw new FleetRegistryError("INVALID_CONFIG", "fleet registry must be a JSON object");
1653
+ const instances = parsed.instances;
1654
+ if (instances === void 0) return { instances: [] };
1655
+ if (!Array.isArray(instances)) throw new FleetRegistryError("INVALID_CONFIG", "fleet registry instances must be an array");
1656
+ return { instances: instances.map(parseInstance) };
1657
+ }
1658
+ var FleetRegistry = class {
1659
+ loader;
1660
+ loaded;
1661
+ constructor(options = {}) {
1662
+ if (options.config !== void 0) {
1663
+ const config = options.config;
1664
+ this.loader = () => config;
1665
+ } else if (options.loadConfig !== void 0) this.loader = options.loadConfig;
1666
+ else {
1667
+ const configPath = options.configPath;
1668
+ this.loader = () => loadFleetRegistryConfig(configPath);
1669
+ }
1670
+ }
1671
+ async resolveInstance(arg) {
1672
+ const instances = await this.instancesWithTokens();
1673
+ const wanted = typeof arg === "string" ? arg.trim() : "";
1674
+ if (wanted) {
1675
+ const byId = instances.find((instance) => instance.id === wanted);
1676
+ if (byId) return resolvedInstance(byId);
1677
+ const labelMatches = instances.filter((instance) => instance.label.toLocaleLowerCase() === wanted.toLocaleLowerCase());
1678
+ if (labelMatches.length > 1) throw new FleetRegistryError("AMBIGUOUS_LABEL", `fleet instance label ${JSON.stringify(wanted)} matches ${labelMatches.length} instances; use an id`);
1679
+ if (labelMatches.length === 1) return resolvedInstance(labelMatches[0]);
1680
+ throw new FleetRegistryError("INSTANCE_NOT_FOUND", `fleet instance ${JSON.stringify(wanted)} was not found`);
1681
+ }
1682
+ const defaultInstance = instances.find((instance) => instance.default === true);
1683
+ if (defaultInstance) return resolvedInstance(defaultInstance);
1684
+ if (instances.length === 1) return resolvedInstance(instances[0]);
1685
+ throw new FleetRegistryError("INSTANCE_REQUIRED", instances.length === 0 ? "fleet instance is required; registry is empty" : "fleet instance is required; specify an instance id or label");
1686
+ }
1687
+ async listInstances() {
1688
+ return (await this.instancesWithTokens()).map((instance) => ({
1689
+ id: instance.id,
1690
+ label: instance.label,
1691
+ url: instance.url,
1692
+ default: instance.default,
1693
+ allowExec: instance.allowExec
1694
+ }));
1695
+ }
1696
+ instancesWithTokens() {
1697
+ if (!this.loaded) this.loaded = Promise.resolve(this.loader()).then((config) => normalizeConfig(config));
1698
+ return this.loaded;
1699
+ }
1700
+ };
1701
+ function normalizeConfig(config) {
1702
+ if (!isObject(config)) throw new FleetRegistryError("INVALID_CONFIG", "fleet registry config must be an object");
1703
+ const instances = config.instances ?? [];
1704
+ if (!Array.isArray(instances)) throw new FleetRegistryError("INVALID_CONFIG", "fleet registry instances must be an array");
1705
+ return instances.map(parseInstance);
1706
+ }
1707
+ function parseInstance(raw) {
1708
+ if (!isObject(raw)) throw new FleetRegistryError("INVALID_CONFIG", "fleet registry instance must be an object");
1709
+ const instance = raw;
1710
+ const id = instance.id;
1711
+ const label = instance.label;
1712
+ const url = instance.url;
1713
+ const token = instance.token;
1714
+ if (typeof id !== "string" || id.trim() === "") throw new FleetRegistryError("INVALID_CONFIG", "fleet registry instance id must be a non-empty string");
1715
+ if (typeof label !== "string" || label.trim() === "") throw new FleetRegistryError("INVALID_CONFIG", `fleet registry instance ${id} label must be a non-empty string`);
1716
+ if (typeof url !== "string" || url.trim() === "") throw new FleetRegistryError("INVALID_CONFIG", `fleet registry instance ${id} url must be a non-empty string`);
1717
+ const trimmedUrl = url.trim();
1718
+ let parsedUrl;
1719
+ try {
1720
+ parsedUrl = new URL(trimmedUrl);
1721
+ } catch {
1722
+ throw invalidInstanceUrlError(id);
1723
+ }
1724
+ if (!isAllowedInstanceUrl(parsedUrl)) throw invalidInstanceUrlError(id);
1725
+ if (typeof token !== "string" || token === "") throw new FleetRegistryError("INVALID_CONFIG", `fleet registry instance ${id} token must be a non-empty string`);
1726
+ return {
1727
+ id: id.trim(),
1728
+ label: label.trim(),
1729
+ url: trimmedUrl,
1730
+ token,
1731
+ default: instance.default === true ? true : void 0,
1732
+ allowExec: instance.allowExec === true ? true : void 0
1733
+ };
1734
+ }
1735
+ function invalidInstanceUrlError(id) {
1736
+ return new FleetRegistryError("INVALID_CONFIG", `${id.trim()} url must be https (or http://localhost for local testing)`);
1737
+ }
1738
+ function isAllowedInstanceUrl(url) {
1739
+ if (url.protocol === "https:") return true;
1740
+ if (url.protocol !== "http:") return false;
1741
+ return url.hostname === "localhost" || url.hostname === "127.0.0.1" || url.hostname === "[::1]";
1742
+ }
1743
+ function resolvedInstance(instance) {
1744
+ return {
1745
+ id: instance.id,
1746
+ label: instance.label,
1747
+ url: instance.url,
1748
+ token: instance.token,
1749
+ allowExec: instance.allowExec
1750
+ };
1751
+ }
1752
+ function isObject(value) {
1753
+ return typeof value === "object" && value !== null && !Array.isArray(value);
1754
+ }
1755
+ function isNodeErrorCode(err, code) {
1756
+ return isObject(err) && err.code === code;
1757
+ }
1758
+
1759
+ //#endregion
1760
+ //#region src/lib/fleet/tools.ts
1761
+ const FLEET_GROUP = "fleet";
1762
+ const INSTANCE_PROBE_TIMEOUT_MS = 2e3;
1763
+ const INSTANCE_PROBE_CACHE_TTL_MS = 5e3;
1764
+ var FleetToolInputError = class extends Error {
1765
+ code;
1766
+ constructor(code, message) {
1767
+ super(message);
1768
+ this.name = "FleetToolInputError";
1769
+ this.code = code;
1770
+ }
1771
+ };
1772
+ let defaultRegistry;
1773
+ const awaitTurnCursors = /* @__PURE__ */ new Map();
1774
+ const instanceProbeCache = /* @__PURE__ */ new Map();
1775
+ function createFleetTools(options = {}) {
1776
+ const registry = options.registry;
1777
+ const clients = /* @__PURE__ */ new Map();
1778
+ function getRegistry() {
1779
+ if (registry) return registry;
1780
+ defaultRegistry ??= new FleetRegistry();
1781
+ return defaultRegistry;
1782
+ }
1783
+ function clientFor(instance) {
1784
+ const key = `${instance.id}\0${instance.url}\0${instance.token}`;
1785
+ const existing = clients.get(key);
1786
+ if (existing) return existing;
1787
+ const created = options.createClient ? options.createClient(instance) : new FleetClient({
1788
+ url: instance.url,
1789
+ token: instance.token,
1790
+ fetchFn: options.fetchFn
1791
+ });
1792
+ clients.set(key, created);
1793
+ return created;
1794
+ }
1795
+ async function resolve(arg) {
1796
+ return getRegistry().resolveInstance(arg);
1797
+ }
1798
+ async function resolveSession(args) {
1799
+ const globalId = requiredString(args, "sessionId");
1800
+ const decoded = decodeSessionId(globalId);
1801
+ const instance = await resolve(decoded.instanceId);
1802
+ const explicitInstance = optionalString(args, "instance");
1803
+ if (explicitInstance !== void 0) {
1804
+ const explicit = await resolve(explicitInstance);
1805
+ if (explicit.id !== decoded.instanceId) throw new FleetToolInputError("INSTANCE_MISMATCH", `sessionId is for instance ${JSON.stringify(decoded.instanceId)} but arguments.instance resolved to ${JSON.stringify(explicit.id)}`);
1806
+ }
1807
+ return {
1808
+ instance,
1809
+ localId: decoded.localId,
1810
+ globalId
1811
+ };
1812
+ }
1813
+ async function probeInstance(info) {
1814
+ const cacheKey = `${info.id}\0${info.url}`;
1815
+ const now = Date.now();
1816
+ const cached$1 = instanceProbeCache.get(cacheKey);
1817
+ if (cached$1 && now - cached$1.at < INSTANCE_PROBE_CACHE_TTL_MS) return cached$1.result;
1818
+ const timeout = createProbeTimeout();
1819
+ try {
1820
+ const response = await clientFor(await resolve(info.id)).listSessions(timeout.signal);
1821
+ const lastSeen = Date.now();
1822
+ const result = {
1823
+ id: info.id,
1824
+ label: info.label,
1825
+ reachable: true,
1826
+ sessionCount: response.sessions.length,
1827
+ lastSeen
1828
+ };
1829
+ instanceProbeCache.set(cacheKey, {
1830
+ result,
1831
+ at: lastSeen
1832
+ });
1833
+ return result;
1834
+ } catch (err) {
1835
+ const result = {
1836
+ id: info.id,
1837
+ label: info.label,
1838
+ reachable: false,
1839
+ error: fleetProbeErrorCode(err)
1840
+ };
1841
+ instanceProbeCache.set(cacheKey, {
1842
+ result,
1843
+ at: Date.now()
1844
+ });
1845
+ return result;
1846
+ } finally {
1847
+ timeout.cleanup();
1848
+ }
1849
+ }
1850
+ function tool$1(toolNameHttp, description, inputSchema, handler) {
1851
+ return {
1852
+ toolNameHttp,
1853
+ group: FLEET_GROUP,
1854
+ description,
1855
+ inputSchema,
1856
+ capability: "fleet",
1857
+ async handler(args, signal) {
1858
+ try {
1859
+ return await handler(args, signal);
1860
+ } catch (err) {
1861
+ return errorResult(err);
1862
+ }
1863
+ }
1864
+ };
1865
+ }
1866
+ return Object.freeze([
1867
+ tool$1("list_instances", "List registered remote ai-or-die instances in the fleet registry. Tokens are never returned.", objectSchema({}, []), async () => {
1868
+ const instances = await getRegistry().listInstances();
1869
+ return ok({ instances: await Promise.all(instances.map((instance) => probeInstance(instance))) });
1870
+ }),
1871
+ tool$1("list_sessions", "List sessions on one fleet instance, returning globally-addressable session ids.", objectSchema({ instance: stringProp("Instance id or label. Defaults to the registry default, or the sole instance.") }, []), async (args, signal) => {
1872
+ const instance = await resolve(optionalString(args, "instance"));
1873
+ const response = await clientFor(instance).listSessions(signal);
1874
+ return ok({
1875
+ resolvedInstance: publicInstance(instance),
1876
+ sessions: response.sessions.map((session) => globalizeSession(instance.id, session))
1877
+ });
1878
+ }),
1879
+ tool$1("read_session", "Read recent text output from an addressed fleet session.", objectSchema({
1880
+ sessionId: stringProp("Global session id in the form instanceId:localSessionId."),
1881
+ instance: stringProp("Optional instance id/label; when supplied it must agree with sessionId."),
1882
+ lines: numberProp("Number of recent lines to read."),
1883
+ format: stringProp("Reserved for future formatting; results are JSON text today.")
1884
+ }, ["sessionId"]), async (args, signal) => {
1885
+ const { instance, localId, globalId } = await resolveSession(args);
1886
+ const lines = optionalNumber(args, "lines");
1887
+ const response = await clientFor(instance).readSession(localId, lines, signal);
1888
+ return ok({
1889
+ resolvedInstance: publicInstance(instance),
1890
+ ...response,
1891
+ sessionId: globalId
1892
+ });
1893
+ }),
1894
+ tool$1("session_status", "Fetch lifecycle and interaction status for an addressed fleet session.", objectSchema({
1895
+ sessionId: stringProp("Global session id in the form instanceId:localSessionId."),
1896
+ instance: stringProp("Optional instance id/label; when supplied it must agree with sessionId.")
1897
+ }, ["sessionId"]), async (args, signal) => {
1898
+ const { instance, localId, globalId } = await resolveSession(args);
1899
+ const response = await clientFor(instance).status(localId, signal);
1900
+ return ok({
1901
+ resolvedInstance: publicInstance(instance),
1902
+ ...response,
1903
+ sessionId: globalId
1904
+ });
1905
+ }),
1906
+ tool$1("send_message", "Send a message to a fleet session. Returns isError if delivery failed or an awaited confirmation did not arrive.", objectSchema({
1907
+ sessionId: stringProp("Global session id in the form instanceId:localSessionId."),
1908
+ instance: stringProp("Optional instance id/label; when supplied it must agree with sessionId."),
1909
+ message: stringProp("Message text to deliver to the session."),
1910
+ idempotencyKey: stringProp("Caller-generated idempotency key."),
1911
+ awaitMs: numberProp("Optional confirmation wait time in milliseconds.")
1912
+ }, [
1913
+ "sessionId",
1914
+ "message",
1915
+ "idempotencyKey"
1916
+ ]), async (args, signal) => {
1917
+ const { instance, localId, globalId } = await resolveSession(args);
1918
+ const awaitMs = optionalNumber(args, "awaitMs");
1919
+ const response = await clientFor(instance).sendMessage(localId, {
1920
+ message: requiredString(args, "message"),
1921
+ idempotencyKey: requiredString(args, "idempotencyKey"),
1922
+ ...awaitMs === void 0 ? {} : { awaitMs }
1923
+ }, signal);
1924
+ const delivered = response.delivered !== false;
1925
+ const confirmed = response.confirmed !== false;
1926
+ const isError = !delivered || awaitMs !== void 0 && awaitMs > 0 && !confirmed;
1927
+ return jsonResult({
1928
+ resolvedInstance: publicInstance(instance),
1929
+ sessionId: globalId,
1930
+ ...response,
1931
+ ...isError ? { message: !delivered ? "message was not delivered by the upstream instance" : `message delivery was not confirmed within awaitMs=${awaitMs}` } : {}
1932
+ }, isError);
1933
+ }),
1934
+ tool$1("send_keys", "Send key input to a fleet session.", objectSchema({
1935
+ sessionId: stringProp("Global session id in the form instanceId:localSessionId."),
1936
+ instance: stringProp("Optional instance id/label; when supplied it must agree with sessionId."),
1937
+ keys: stringProp("Key sequence to send."),
1938
+ idempotencyKey: stringProp("Caller-generated idempotency key."),
1939
+ raw: booleanProp("Pass keys through as raw input when the instance supports it.")
1940
+ }, [
1941
+ "sessionId",
1942
+ "keys",
1943
+ "idempotencyKey"
1944
+ ]), async (args, signal) => {
1945
+ const { instance, localId, globalId } = await resolveSession(args);
1946
+ const raw = optionalBoolean(args, "raw");
1947
+ const response = await clientFor(instance).sendKeys(localId, {
1948
+ keys: requiredString(args, "keys"),
1949
+ idempotencyKey: requiredString(args, "idempotencyKey"),
1950
+ ...raw === void 0 ? {} : { raw }
1951
+ }, signal);
1952
+ return ok({
1953
+ resolvedInstance: publicInstance(instance),
1954
+ sessionId: globalId,
1955
+ ...response
1956
+ });
1957
+ }),
1958
+ tool$1("respond", "Answer an awaited prompt in a fleet session by choice, option value, or explicit key override.", objectSchema({
1959
+ sessionId: stringProp("Global session id in the form instanceId:localSessionId."),
1960
+ instance: stringProp("Optional instance id/label; when supplied it must agree with sessionId."),
1961
+ choice: stringProp("Named or numbered choice to select."),
1962
+ optionValue: stringProp("Exact option value to select."),
1963
+ keys: stringProp("Explicit key override to send instead of a mapped choice."),
1964
+ idempotencyKey: stringProp("Caller-generated idempotency key.")
1965
+ }, ["sessionId", "idempotencyKey"]), async (args, signal) => {
1966
+ const { instance, localId, globalId } = await resolveSession(args);
1967
+ const input = definedObject({
1968
+ choice: optionalString(args, "choice"),
1969
+ optionValue: optionalString(args, "optionValue"),
1970
+ keys: optionalString(args, "keys"),
1971
+ idempotencyKey: requiredString(args, "idempotencyKey")
1972
+ });
1973
+ const response = await clientFor(instance).respond(localId, input, signal);
1974
+ return ok({
1975
+ resolvedInstance: publicInstance(instance),
1976
+ sessionId: globalId,
1977
+ ...response
1978
+ });
1979
+ }),
1980
+ tool$1("create_session", "Create a new session on a specific fleet instance. The instance argument is required; no default is used.", objectSchema({
1981
+ instance: stringProp("Required instance id or label. Create never uses the registry default."),
1982
+ agent: stringProp("Agent/runtime to create on the instance."),
1983
+ name: stringProp("Optional display name for the session."),
1984
+ workingDir: stringProp("Optional working directory on the remote instance."),
1985
+ idempotencyKey: stringProp("Caller-generated idempotency key."),
1986
+ start: booleanProp("Whether the remote instance should start the session immediately.")
1987
+ }, [
1988
+ "instance",
1989
+ "agent",
1990
+ "idempotencyKey"
1991
+ ]), async (args, signal) => {
1992
+ const instance = await resolve(requiredString(args, "instance"));
1993
+ const idempotencyKey = requiredString(args, "idempotencyKey");
1994
+ const response = await clientFor(instance).createSession(definedObject({
1995
+ agent: requiredString(args, "agent"),
1996
+ name: optionalString(args, "name"),
1997
+ workingDir: optionalString(args, "workingDir"),
1998
+ start: optionalBoolean(args, "start"),
1999
+ idempotencyKey
2000
+ }), signal);
2001
+ const localSessionId = typeof response.sessionId === "string" ? response.sessionId : "";
2002
+ return ok({
2003
+ resolvedInstance: publicInstance(instance),
2004
+ ...response,
2005
+ sessionId: localSessionId ? encodeSessionId(instance.id, localSessionId) : response.sessionId
2006
+ });
2007
+ }),
2008
+ tool$1("stop_session", "Stop a fleet session.", objectSchema({
2009
+ sessionId: stringProp("Global session id in the form instanceId:localSessionId."),
2010
+ instance: stringProp("Optional instance id/label; when supplied it must agree with sessionId."),
2011
+ idempotencyKey: stringProp("Caller-generated idempotency key."),
2012
+ mode: stringProp("Optional stop mode understood by the remote instance.")
2013
+ }, ["sessionId", "idempotencyKey"]), async (args, signal) => {
2014
+ const { instance, localId, globalId } = await resolveSession(args);
2015
+ const idempotencyKey = requiredString(args, "idempotencyKey");
2016
+ const response = await clientFor(instance).stopSession(localId, definedObject({
2017
+ mode: optionalString(args, "mode"),
2018
+ idempotencyKey
2019
+ }), signal);
2020
+ return ok({
2021
+ resolvedInstance: publicInstance(instance),
2022
+ sessionId: globalId,
2023
+ ...response
2024
+ });
2025
+ }),
2026
+ tool$1("await_turn", "Long-poll session events across fleet instances. The server owns per-target cursors, so callers do not pass cursor tokens.", objectSchema({
2027
+ instances: arrayProp("Instance ids or labels to poll. Omit with sessionIds to target those session instances; omit both to poll every registered instance."),
2028
+ sessionIds: arrayProp("Global session ids to filter to."),
2029
+ timeoutMs: numberProp("Long-poll timeout per instance in milliseconds."),
2030
+ kinds: arrayProp("Optional event kinds to filter to.")
2031
+ }, []), async (args, signal) => {
2032
+ const target = await resolveAwaitTarget(args, getRegistry());
2033
+ const clientKey = target.instances.map((instance) => instance.id).sort().join(",");
2034
+ const cursorByInstance = awaitTurnCursors.get(clientKey) ?? /* @__PURE__ */ new Map();
2035
+ awaitTurnCursors.set(clientKey, cursorByInstance);
2036
+ const timeoutMs = optionalNumber(args, "timeoutMs");
2037
+ const kinds = optionalStringArray(args, "kinds");
2038
+ const responses = await Promise.all(target.instances.map(async (instance) => {
2039
+ const response = await clientFor(instance).waitEvents(definedObject({
2040
+ cursor: cursorByInstance.get(instance.id),
2041
+ timeoutMs,
2042
+ sessionIds: target.localSessionIdsByInstance.get(instance.id),
2043
+ kinds
2044
+ }), signal);
2045
+ cursorByInstance.set(instance.id, response.cursor);
2046
+ return {
2047
+ instance,
2048
+ response
2049
+ };
2050
+ }));
2051
+ const events$1 = responses.flatMap(({ instance, response }) => response.events.map((event) => stampEvent(instance, event))).sort(compareStampedEvents);
2052
+ const gaps = responses.flatMap(({ instance, response }) => response.gaps.map((gap) => ({
2053
+ instance: publicInstance(instance),
2054
+ ...gap
2055
+ })));
2056
+ return ok({
2057
+ resolvedInstances: target.instances.map(publicInstance),
2058
+ events: events$1,
2059
+ gaps,
2060
+ cursors: responses.map(({ instance, response }) => ({
2061
+ instance: publicInstance(instance),
2062
+ ...parseCursor(response.cursor)
2063
+ })),
2064
+ more: responses.some(({ response }) => response.more)
2065
+ });
2066
+ }),
2067
+ tool$1("read_file", "Read a file from one fleet instance via its existing /api/files/content endpoint.", objectSchema({
2068
+ instance: stringProp("Instance id or label. Defaults to the registry default, or the sole instance."),
2069
+ path: stringProp("Remote file path to read.")
2070
+ }, ["path"]), async (args, signal) => {
2071
+ const instance = await resolve(optionalString(args, "instance"));
2072
+ const response = await clientFor(instance).readFile(requiredString(args, "path"), signal);
2073
+ return ok({
2074
+ resolvedInstance: publicInstance(instance),
2075
+ ...response
2076
+ });
2077
+ }),
2078
+ tool$1("list_dir", "List a directory on one fleet instance via its existing /api/files endpoint.", objectSchema({
2079
+ instance: stringProp("Instance id or label. Defaults to the registry default, or the sole instance."),
2080
+ path: stringProp("Remote directory path to list.")
2081
+ }, ["path"]), async (args, signal) => {
2082
+ const instance = await resolve(optionalString(args, "instance"));
2083
+ const response = await clientFor(instance).listDir(requiredString(args, "path"), signal);
2084
+ return ok({
2085
+ resolvedInstance: publicInstance(instance),
2086
+ ...response
2087
+ });
2088
+ }),
2089
+ tool$1("search", "Search files on one fleet instance via its existing /api/search endpoint.", objectSchema({
2090
+ instance: stringProp("Instance id or label. Defaults to the registry default, or the sole instance."),
2091
+ query: stringProp("Search query."),
2092
+ path: stringProp("Optional path scope.")
2093
+ }, ["query"]), async (args, signal) => {
2094
+ const instance = await resolve(optionalString(args, "instance"));
2095
+ const response = await clientFor(instance).search(requiredString(args, "query"), optionalString(args, "path"), signal);
2096
+ return ok({
2097
+ resolvedInstance: publicInstance(instance),
2098
+ ...response
2099
+ });
2100
+ }),
2101
+ tool$1("git_show", "Read a file/revision through one fleet instance's existing /api/files/git-show endpoint.", objectSchema({
2102
+ instance: stringProp("Instance id or label. Defaults to the registry default, or the sole instance."),
2103
+ path: stringProp("Remote repository path or file path for git-show."),
2104
+ ref: stringProp("Optional git ref/revision."),
2105
+ rev: stringProp("Optional git revision alias."),
2106
+ commit: stringProp("Optional commit id.")
2107
+ }, ["path"]), async (args, signal) => {
2108
+ const instance = await resolve(optionalString(args, "instance"));
2109
+ const response = await clientFor(instance).gitShow({
2110
+ ...args,
2111
+ instance: void 0
2112
+ }, signal);
2113
+ return ok({
2114
+ resolvedInstance: publicInstance(instance),
2115
+ ...response
2116
+ });
2117
+ })
2118
+ ]);
2119
+ }
2120
+ const FLEET_TOOLS = createFleetTools();
2121
+ function createProbeTimeout() {
2122
+ const timeout = AbortSignal.timeout;
2123
+ if (typeof timeout === "function") return {
2124
+ signal: timeout(INSTANCE_PROBE_TIMEOUT_MS),
2125
+ cleanup: () => {}
2126
+ };
2127
+ const controller = new AbortController();
2128
+ const timer = setTimeout(() => controller.abort(), INSTANCE_PROBE_TIMEOUT_MS);
2129
+ return {
2130
+ signal: controller.signal,
2131
+ cleanup: () => clearTimeout(timer)
2132
+ };
2133
+ }
2134
+ function fleetProbeErrorCode(err) {
2135
+ if (typeof err === "object" && err !== null && "code" in err) {
2136
+ const code = err.code;
2137
+ if (typeof code === "string" && isFleetErrorCode(code)) return code;
2138
+ }
2139
+ return "UNREACHABLE";
2140
+ }
2141
+ function isFleetErrorCode(code) {
2142
+ switch (code) {
2143
+ case "UNREACHABLE":
2144
+ case "AUTH_FAILED":
2145
+ case "SESSION_NOT_FOUND":
2146
+ case "PRECONDITION_FAILED":
2147
+ case "TIMEOUT":
2148
+ case "UPSTREAM_ERROR": return true;
2149
+ default: return false;
2150
+ }
2151
+ }
2152
+ async function resolveAwaitTarget(args, registry) {
2153
+ const instanceArgs = optionalStringArray(args, "instances");
2154
+ const sessionIdArgs = optionalStringArray(args, "sessionIds");
2155
+ const localSessionIdsByInstance = /* @__PURE__ */ new Map();
2156
+ for (const sessionId of sessionIdArgs ?? []) {
2157
+ const decoded = decodeSessionId(sessionId);
2158
+ const existing = localSessionIdsByInstance.get(decoded.instanceId) ?? [];
2159
+ existing.push(decoded.localId);
2160
+ localSessionIdsByInstance.set(decoded.instanceId, existing);
2161
+ }
2162
+ let instances;
2163
+ if (instanceArgs !== void 0 && instanceArgs.length > 0) {
2164
+ instances = uniqueInstances(await Promise.all(instanceArgs.map((arg) => registry.resolveInstance(arg))));
2165
+ const ids = new Set(instances.map((instance) => instance.id));
2166
+ for (const instanceId of localSessionIdsByInstance.keys()) if (!ids.has(instanceId)) throw new FleetToolInputError("INSTANCE_MISMATCH", `sessionIds include instance ${JSON.stringify(instanceId)} which is not in arguments.instances`);
2167
+ } else if (localSessionIdsByInstance.size > 0) instances = uniqueInstances(await Promise.all([...localSessionIdsByInstance.keys()].map((instanceId) => registry.resolveInstance(instanceId))));
2168
+ else {
2169
+ const infos = await registry.listInstances();
2170
+ if (infos.length === 0) throw new FleetRegistryError("INSTANCE_REQUIRED", "await_turn requires at least one registered fleet instance");
2171
+ instances = uniqueInstances(await Promise.all(infos.map((info) => registry.resolveInstance(info.id))));
2172
+ }
2173
+ return {
2174
+ instances,
2175
+ localSessionIdsByInstance
2176
+ };
2177
+ }
2178
+ function globalizeSession(instanceId, session) {
2179
+ return {
2180
+ ...session,
2181
+ sessionId: encodeSessionId(instanceId, session.sessionId)
2182
+ };
2183
+ }
2184
+ function stampEvent(instance, event) {
2185
+ return {
2186
+ ...event,
2187
+ instance: publicInstance(instance),
2188
+ ...typeof event.sessionId === "string" ? { sessionId: encodeSessionId(instance.id, event.sessionId) } : {}
2189
+ };
2190
+ }
2191
+ function compareStampedEvents(a, b) {
2192
+ const atA = typeof a.at === "string" ? a.at : "";
2193
+ const atB = typeof b.at === "string" ? b.at : "";
2194
+ if (atA !== atB) return atA < atB ? -1 : 1;
2195
+ return (typeof a.seq === "number" ? a.seq : 0) - (typeof b.seq === "number" ? b.seq : 0);
2196
+ }
2197
+ function parseCursor(cursor) {
2198
+ const idx = cursor.indexOf(":");
2199
+ if (idx < 0) return { cursor };
2200
+ const seq = Number(cursor.slice(idx + 1));
2201
+ return {
2202
+ cursor,
2203
+ epoch: cursor.slice(0, idx),
2204
+ ...Number.isFinite(seq) ? { seq } : {}
2205
+ };
2206
+ }
2207
+ function uniqueInstances(instances) {
2208
+ const seen = /* @__PURE__ */ new Set();
2209
+ const result = [];
2210
+ for (const instance of instances) {
2211
+ if (seen.has(instance.id)) continue;
2212
+ seen.add(instance.id);
2213
+ result.push(instance);
2214
+ }
2215
+ return result;
2216
+ }
2217
+ function publicInstance(instance) {
2218
+ return {
2219
+ id: instance.id,
2220
+ label: instance.label
2221
+ };
2222
+ }
2223
+ function ok(value) {
2224
+ return jsonResult(value, false);
2225
+ }
2226
+ function jsonResult(value, isError) {
2227
+ return {
2228
+ content: [{
2229
+ type: "text",
2230
+ text: JSON.stringify(value)
2231
+ }],
2232
+ ...isError ? { isError: true } : {}
2233
+ };
2234
+ }
2235
+ function errorResult(err) {
2236
+ return jsonResult({ error: {
2237
+ code: errorCode(err),
2238
+ message: err instanceof Error ? err.message : String(err)
2239
+ } }, true);
2240
+ }
2241
+ function errorCode(err) {
2242
+ if (typeof err === "object" && err !== null && "code" in err) {
2243
+ const code = err.code;
2244
+ if (typeof code === "string") return code;
2245
+ }
2246
+ return "FLEET_ERROR";
2247
+ }
2248
+ function definedObject(input) {
2249
+ const result = {};
2250
+ for (const [key, value] of Object.entries(input)) if (value !== void 0) result[key] = value;
2251
+ return result;
2252
+ }
2253
+ function requiredString(args, key) {
2254
+ const value = args[key];
2255
+ if (typeof value !== "string" || value.trim() === "") throw new FleetToolInputError("INVALID_ARGUMENT", `arguments.${key} is required and must be a non-empty string`);
2256
+ return value;
2257
+ }
2258
+ function optionalString(args, key) {
2259
+ const value = args[key];
2260
+ if (value === void 0) return void 0;
2261
+ if (typeof value !== "string") throw new FleetToolInputError("INVALID_ARGUMENT", `arguments.${key} must be a string`);
2262
+ return value.trim() === "" ? void 0 : value;
2263
+ }
2264
+ function optionalNumber(args, key) {
2265
+ const value = args[key];
2266
+ if (value === void 0) return void 0;
2267
+ if (typeof value !== "number" || !Number.isFinite(value)) throw new FleetToolInputError("INVALID_ARGUMENT", `arguments.${key} must be a finite number`);
2268
+ return value;
2269
+ }
2270
+ function optionalBoolean(args, key) {
2271
+ const value = args[key];
2272
+ if (value === void 0) return void 0;
2273
+ if (typeof value !== "boolean") throw new FleetToolInputError("INVALID_ARGUMENT", `arguments.${key} must be a boolean`);
2274
+ return value;
2275
+ }
2276
+ function optionalStringArray(args, key) {
2277
+ const value = args[key];
2278
+ if (value === void 0) return void 0;
2279
+ if (!Array.isArray(value) || value.some((item) => typeof item !== "string" || item.trim() === "")) throw new FleetToolInputError("INVALID_ARGUMENT", `arguments.${key} must be an array of non-empty strings`);
2280
+ return value;
2281
+ }
2282
+ function objectSchema(properties, required) {
2283
+ return {
2284
+ type: "object",
2285
+ required,
2286
+ additionalProperties: false,
2287
+ properties
2288
+ };
2289
+ }
2290
+ function stringProp(description) {
2291
+ return {
2292
+ type: "string",
2293
+ description
2294
+ };
2295
+ }
2296
+ function numberProp(description) {
2297
+ return {
2298
+ type: "number",
2299
+ description
2300
+ };
2301
+ }
2302
+ function booleanProp(description) {
2303
+ return {
2304
+ type: "boolean",
2305
+ description
2306
+ };
2307
+ }
2308
+ function arrayProp(description) {
2309
+ return {
2310
+ type: "array",
2311
+ items: { type: "string" },
2312
+ description
2313
+ };
2314
+ }
2315
+
1048
2316
  //#endregion
1049
2317
  //#region src/lib/tree-sitter-grammars.ts
1050
2318
  /**
@@ -5046,7 +6314,7 @@ async function runInit(workspace) {
5046
6314
  ];
5047
6315
  const onInactivityCheck = makeIndexProgressProbe(workspace);
5048
6316
  const startMs = Date.now();
5049
- let ok = false;
6317
+ let ok$2 = false;
5050
6318
  let failureClass;
5051
6319
  try {
5052
6320
  const res = await runManagedExeCapture(binary, args, {
@@ -5063,10 +6331,10 @@ async function runInit(workspace) {
5063
6331
  }).catch(() => {});
5064
6332
  }
5065
6333
  });
5066
- ok = !res.stalled && !res.timedOut && res.code === 0;
5067
- if (!ok) failureClass = res.stalled || res.timedOut ? "stuck" : "error";
6334
+ ok$2 = !res.stalled && !res.timedOut && res.code === 0;
6335
+ if (!ok$2) failureClass = res.stalled || res.timedOut ? "stuck" : "error";
5068
6336
  } catch {
5069
- ok = false;
6337
+ ok$2 = false;
5070
6338
  failureClass = "launch";
5071
6339
  } finally {
5072
6340
  releaseInit(workspace);
@@ -5083,9 +6351,9 @@ async function runInit(workspace) {
5083
6351
  finalMeta.lastIndexedDirty = g.dirty;
5084
6352
  }
5085
6353
  } catch {}
5086
- finalMeta.status = ok ? "ready" : "failed";
6354
+ finalMeta.status = ok$2 ? "ready" : "failed";
5087
6355
  finalMeta.lastIndexedAt = (/* @__PURE__ */ new Date()).toISOString();
5088
- if (ok) {
6356
+ if (ok$2) {
5089
6357
  finalMeta.failedAttempts = 0;
5090
6358
  finalMeta.failureClass = void 0;
5091
6359
  } else {
@@ -6164,8 +7432,8 @@ async function isHumanlikeAutoOn(tabId, signal) {
6164
7432
  } catch {}
6165
7433
  return humanlikeAutoCache.tabs.has(tabId);
6166
7434
  }
6167
- async function maybeInjectHumanlikeDelay(tool, signal, tabId) {
6168
- if (!PACED_TOOLS.has(tool)) return;
7435
+ async function maybeInjectHumanlikeDelay(tool$1, signal, tabId) {
7436
+ if (!PACED_TOOLS.has(tool$1)) return;
6169
7437
  let on = state.humanlikeForce === "on";
6170
7438
  if (!on && state.humanlikeForce === "auto") on = await isHumanlikeAutoOn(tabId, signal);
6171
7439
  if (!on) return;
@@ -6270,8 +7538,8 @@ const PER_TOOL_TIMEOUTS = {
6270
7538
  maxMs: 1e4
6271
7539
  }
6272
7540
  };
6273
- function pickTimeout(tool) {
6274
- if (tool in PER_TOOL_TIMEOUTS) return PER_TOOL_TIMEOUTS[tool];
7541
+ function pickTimeout(tool$1) {
7542
+ if (tool$1 in PER_TOOL_TIMEOUTS) return PER_TOOL_TIMEOUTS[tool$1];
6275
7543
  return {
6276
7544
  defaultMs: 1e4,
6277
7545
  maxMs: 3e4
@@ -6284,7 +7552,7 @@ function pickTimeout(tool) {
6284
7552
  * client sends notifications/cancelled, the WS is force-closed and
6285
7553
  * the promise rejects so the slot releases cleanly.
6286
7554
  */
6287
- async function bridgeCall(endpoint, tool, args, timeoutMs, signal) {
7555
+ async function bridgeCall(endpoint, tool$1, args, timeoutMs, signal) {
6288
7556
  return new Promise((resolve, reject) => {
6289
7557
  const id = randomUUID();
6290
7558
  const ws = new WebSocket(`ws://127.0.0.1:${endpoint.port}`, { headers: { authorization: `Bearer ${endpoint.token}` } });
@@ -6318,7 +7586,7 @@ async function bridgeCall(endpoint, tool, args, timeoutMs, signal) {
6318
7586
  }
6319
7587
  ws.send(JSON.stringify({
6320
7588
  id,
6321
- tool,
7589
+ tool: tool$1,
6322
7590
  args
6323
7591
  }));
6324
7592
  });
@@ -6377,8 +7645,8 @@ function blockedUrlEnvelope(reason) {
6377
7645
  * happy-path `ensureBridgeReady()` (and its NMH install) is the accepted
6378
7646
  * cost of keeping the credentials fresh.
6379
7647
  */
6380
- async function browserPreflight(tool, args) {
6381
- const policy = preflightUrlPolicy(tool.startsWith("browser_") ? tool : `browser_${tool}`, args);
7648
+ async function browserPreflight(tool$1, args) {
7649
+ const policy = preflightUrlPolicy(tool$1.startsWith("browser_") ? tool$1 : `browser_${tool$1}`, args);
6382
7650
  if (policy.blocked) return { envelope: blockedUrlEnvelope(policy.reason) };
6383
7651
  const ready = await ensureBridgeReady();
6384
7652
  if (ready.install_required) return { envelope: installRequiredToolResult(ready) };
@@ -6389,23 +7657,23 @@ async function browserPreflight(tool, args) {
6389
7657
  * src/lib/browser-mcp/index.ts. Returns the standard MCP tool-result
6390
7658
  * envelope.
6391
7659
  */
6392
- async function dispatchBrowserTool(tool, args, signal, opts = {}) {
6393
- const policy = preflightUrlPolicy(tool, args);
7660
+ async function dispatchBrowserTool(tool$1, args, signal, opts = {}) {
7661
+ const policy = preflightUrlPolicy(tool$1, args);
6394
7662
  if (policy.blocked) return blockedUrlEnvelope(policy.reason);
6395
7663
  const ready = await ensureBridgeReady();
6396
7664
  if (ready.install_required) return installRequiredToolResult(ready);
6397
- await maybeInjectHumanlikeDelay(tool, signal, typeof args.tabId === "number" ? args.tabId : void 0);
6398
- const { defaultMs, maxMs } = pickTimeout(tool);
7665
+ await maybeInjectHumanlikeDelay(tool$1, signal, typeof args.tabId === "number" ? args.tabId : void 0);
7666
+ const { defaultMs, maxMs } = pickTimeout(tool$1);
6399
7667
  const callerTimeout = typeof opts.timeoutMs === "number" && opts.timeoutMs > 0 ? Math.min(opts.timeoutMs, maxMs) : defaultMs;
6400
7668
  try {
6401
7669
  const resp = await bridgeCall({
6402
7670
  port: ready.port,
6403
7671
  token: ready.token
6404
- }, tool, args, callerTimeout, signal);
7672
+ }, tool$1, args, callerTimeout, signal);
6405
7673
  if (resp.ok) {
6406
7674
  const text = typeof resp.data === "string" ? resp.data : JSON.stringify(resp.data, null, 2);
6407
7675
  logAudit$1({
6408
- tool,
7676
+ tool: tool$1,
6409
7677
  argsBytes: argsByteSize(args),
6410
7678
  durationMs: 0,
6411
7679
  profile: typeof args.profile === "string" ? args.profile : "isolated",
@@ -6417,7 +7685,7 @@ async function dispatchBrowserTool(tool, args, signal, opts = {}) {
6417
7685
  }] };
6418
7686
  }
6419
7687
  logAudit$1({
6420
- tool,
7688
+ tool: tool$1,
6421
7689
  argsBytes: argsByteSize(args),
6422
7690
  durationMs: 0,
6423
7691
  profile: typeof args.profile === "string" ? args.profile : "isolated",
@@ -6427,14 +7695,14 @@ async function dispatchBrowserTool(tool, args, signal, opts = {}) {
6427
7695
  return {
6428
7696
  content: [{
6429
7697
  type: "text",
6430
- text: `${tool} failed: ${resp.error}${resp.code ? ` (${resp.code})` : ""}`
7698
+ text: `${tool$1} failed: ${resp.error}${resp.code ? ` (${resp.code})` : ""}`
6431
7699
  }],
6432
7700
  isError: true
6433
7701
  };
6434
7702
  } catch (err) {
6435
7703
  const message = err instanceof Error ? err.message : String(err);
6436
7704
  logAudit$1({
6437
- tool,
7705
+ tool: tool$1,
6438
7706
  argsBytes: argsByteSize(args),
6439
7707
  durationMs: 0,
6440
7708
  profile: typeof args.profile === "string" ? args.profile : "isolated",
@@ -6444,7 +7712,7 @@ async function dispatchBrowserTool(tool, args, signal, opts = {}) {
6444
7712
  return {
6445
7713
  content: [{
6446
7714
  type: "text",
6447
- text: `${tool} failed: ${message}`
7715
+ text: `${tool$1} failed: ${message}`
6448
7716
  }],
6449
7717
  isError: true
6450
7718
  };
@@ -7405,20 +8673,20 @@ function compressorAvailable() {
7405
8673
  * free-form `message.content` and strip a leading / trailing ```` ``` ````
7406
8674
  * code fence before parsing.
7407
8675
  */
7408
- async function callCompressor(systemPrompt, userMessage, tool, signal) {
8676
+ async function callCompressor(systemPrompt, userMessage, tool$1, signal) {
7409
8677
  const backend = pickBackend();
7410
8678
  if (!backend) throw new Error(`browser-mcp compressor: no backend available in catalog. Checked: ${COMPRESSOR_FALLBACK_CHAIN.join(", ")}`);
7411
8679
  const release = acquireInFlightSlot();
7412
8680
  if (!release) throw new Error("browser-mcp compressor: inflight slot saturated (cap 8); try again shortly");
7413
8681
  try {
7414
- return backend.endpoint === "responses" ? await callViaResponses(backend.id, systemPrompt, userMessage, tool, signal) : await callViaChat(backend.id, systemPrompt, userMessage, tool, signal);
8682
+ return backend.endpoint === "responses" ? await callViaResponses(backend.id, systemPrompt, userMessage, tool$1, signal) : await callViaChat(backend.id, systemPrompt, userMessage, tool$1, signal);
7415
8683
  } finally {
7416
8684
  release();
7417
8685
  }
7418
8686
  }
7419
8687
  /** Forced-tool-call over `/chat/completions`. Parses the function-call
7420
8688
  * arguments, falling back to fenced free-form content. */
7421
- async function callViaChat(model, systemPrompt, userMessage, tool, signal) {
8689
+ async function callViaChat(model, systemPrompt, userMessage, tool$1, signal) {
7422
8690
  const msg = (await createChatCompletions({
7423
8691
  model,
7424
8692
  stream: false,
@@ -7432,14 +8700,14 @@ async function callViaChat(model, systemPrompt, userMessage, tool, signal) {
7432
8700
  tools: [{
7433
8701
  type: "function",
7434
8702
  function: {
7435
- name: tool.name,
7436
- description: tool.description,
7437
- parameters: tool.parameters
8703
+ name: tool$1.name,
8704
+ description: tool$1.description,
8705
+ parameters: tool$1.parameters
7438
8706
  }
7439
8707
  }],
7440
8708
  tool_choice: {
7441
8709
  type: "function",
7442
- function: { name: tool.name }
8710
+ function: { name: tool$1.name }
7443
8711
  }
7444
8712
  }, void 0, signal)).choices?.[0]?.message;
7445
8713
  const toolArgs = msg?.tool_calls?.[0]?.function?.arguments;
@@ -7453,7 +8721,7 @@ async function callViaChat(model, systemPrompt, userMessage, tool, signal) {
7453
8721
  * items of `type: "function_call"` carrying the `arguments` JSON string.
7454
8722
  * Image parts use `input_image` (vs chat's `image_url`) — see
7455
8723
  * `toResponsesContent`. */
7456
- async function callViaResponses(model, systemPrompt, userMessage, tool, signal) {
8724
+ async function callViaResponses(model, systemPrompt, userMessage, tool$1, signal) {
7457
8725
  const resp = await createResponses({
7458
8726
  model,
7459
8727
  stream: false,
@@ -7466,13 +8734,13 @@ async function callViaResponses(model, systemPrompt, userMessage, tool, signal)
7466
8734
  }],
7467
8735
  tools: [{
7468
8736
  type: "function",
7469
- name: tool.name,
7470
- description: tool.description,
7471
- parameters: tool.parameters
8737
+ name: tool$1.name,
8738
+ description: tool$1.description,
8739
+ parameters: tool$1.parameters
7472
8740
  }],
7473
8741
  tool_choice: {
7474
8742
  type: "function",
7475
- name: tool.name
8743
+ name: tool$1.name
7476
8744
  }
7477
8745
  }, void 0, signal);
7478
8746
  const output = Array.isArray(resp.output) ? resp.output : [];
@@ -7528,8 +8796,8 @@ function extractResponsesText$1(output) {
7528
8796
  * directly so the underlying function can change signature without
7529
8797
  * breaking the public surface.
7530
8798
  */
7531
- async function callCompressorPublic(systemPrompt, userMessage, tool, signal) {
7532
- return callCompressor(systemPrompt, userMessage, tool, signal);
8799
+ async function callCompressorPublic(systemPrompt, userMessage, tool$1, signal) {
8800
+ return callCompressor(systemPrompt, userMessage, tool$1, signal);
7533
8801
  }
7534
8802
  /**
7535
8803
  * Strip a single leading / trailing ``` (or ```json) code fence from a
@@ -8643,12 +9911,12 @@ const BROWSER_TOOLS = Object.freeze([
8643
9911
  capability: "browser_power",
8644
9912
  async handler(args, signal) {
8645
9913
  const kind = args.kind === "network" ? "network" : "console";
8646
- const tool = kind === "network" ? "browser_network_log" : "browser_console_logs";
9914
+ const tool$1 = kind === "network" ? "browser_network_log" : "browser_console_logs";
8647
9915
  const tabId = typeof args.tabId === "number" ? args.tabId : void 0;
8648
9916
  const level = typeof args.level === "string" ? args.level : "all";
8649
9917
  const regexStr = typeof args.regex === "string" ? args.regex : void 0;
8650
9918
  const limit = typeof args.limit === "number" ? Math.min(1e3, Math.max(1, args.limit)) : 100;
8651
- const env = await dispatchBrowserTool(tool, {
9919
+ const env = await dispatchBrowserTool(tool$1, {
8652
9920
  tabId,
8653
9921
  level
8654
9922
  }, signal);
@@ -9536,12 +10804,12 @@ function formatValidationPath(error) {
9536
10804
  * @returns The validated (and potentially coerced) arguments
9537
10805
  * @throws Error with formatted message if validation fails
9538
10806
  */
9539
- function validateToolArguments(tool, toolCall) {
10807
+ function validateToolArguments(tool$1, toolCall) {
9540
10808
  const args = structuredClone(toolCall.arguments);
9541
- Value.Convert(tool.parameters, args);
9542
- const validator = getValidator(tool.parameters);
9543
- if (!hasTypeBoxMetadata(tool.parameters) && isJsonSchemaObject(tool.parameters)) {
9544
- const coerced = coerceWithJsonSchema(args, tool.parameters);
10809
+ Value.Convert(tool$1.parameters, args);
10810
+ const validator = getValidator(tool$1.parameters);
10811
+ if (!hasTypeBoxMetadata(tool$1.parameters) && isJsonSchemaObject(tool$1.parameters)) {
10812
+ const coerced = coerceWithJsonSchema(args, tool$1.parameters);
9545
10813
  if (coerced !== args) if (isRecord(args) && isRecord(coerced)) {
9546
10814
  for (const key of Object.keys(args)) delete args[key];
9547
10815
  Object.assign(args, coerced);
@@ -9850,9 +11118,9 @@ async function executeToolCallsParallel(currentContext, assistantMessage, toolCa
9850
11118
  function shouldTerminateToolBatch(finalizedCalls) {
9851
11119
  return finalizedCalls.length > 0 && finalizedCalls.every((finalized) => finalized.result.terminate === true);
9852
11120
  }
9853
- function prepareToolCallArguments(tool, toolCall) {
9854
- if (!tool.prepareArguments) return toolCall;
9855
- const preparedArguments = tool.prepareArguments(toolCall.arguments);
11121
+ function prepareToolCallArguments(tool$1, toolCall) {
11122
+ if (!tool$1.prepareArguments) return toolCall;
11123
+ const preparedArguments = tool$1.prepareArguments(toolCall.arguments);
9856
11124
  if (preparedArguments === toolCall.arguments) return toolCall;
9857
11125
  return {
9858
11126
  ...toolCall,
@@ -9860,14 +11128,14 @@ function prepareToolCallArguments(tool, toolCall) {
9860
11128
  };
9861
11129
  }
9862
11130
  async function prepareToolCall(currentContext, assistantMessage, toolCall, config, signal) {
9863
- const tool = currentContext.tools?.find((t) => t.name === toolCall.name);
9864
- if (!tool) return {
11131
+ const tool$1 = currentContext.tools?.find((t) => t.name === toolCall.name);
11132
+ if (!tool$1) return {
9865
11133
  kind: "immediate",
9866
11134
  result: createErrorToolResult(`Tool ${toolCall.name} not found`),
9867
11135
  isError: true
9868
11136
  };
9869
11137
  try {
9870
- const validatedArgs = validateToolArguments(tool, prepareToolCallArguments(tool, toolCall));
11138
+ const validatedArgs = validateToolArguments(tool$1, prepareToolCallArguments(tool$1, toolCall));
9871
11139
  if (config.beforeToolCall) {
9872
11140
  const beforeResult = await config.beforeToolCall({
9873
11141
  assistantMessage,
@@ -9894,7 +11162,7 @@ async function prepareToolCall(currentContext, assistantMessage, toolCall, confi
9894
11162
  return {
9895
11163
  kind: "prepared",
9896
11164
  toolCall,
9897
- tool,
11165
+ tool: tool$1,
9898
11166
  args: validatedArgs
9899
11167
  };
9900
11168
  } catch (error) {
@@ -12192,7 +13460,7 @@ const REPORT_INSUFFICIENT_DESCRIPTION = "Finish by declaring the requested value
12192
13460
  function makeBrowserTool(meta, parameters, dispatch, sessionId) {
12193
13461
  const wireName = `browser_${meta.name}`;
12194
13462
  const policy = tabPolicyFor(meta.name);
12195
- const tool = {
13463
+ const tool$1 = {
12196
13464
  name: meta.name,
12197
13465
  label: meta.label,
12198
13466
  description: meta.description,
@@ -12217,8 +13485,8 @@ function makeBrowserTool(meta, parameters, dispatch, sessionId) {
12217
13485
  return textResult$1(text);
12218
13486
  }
12219
13487
  };
12220
- if (meta.executionMode) tool.executionMode = meta.executionMode;
12221
- return tool;
13488
+ if (meta.executionMode) tool$1.executionMode = meta.executionMode;
13489
+ return tool$1;
12222
13490
  }
12223
13491
  /**
12224
13492
  * Build a synthetic terminal tool. `execute` never touches the browser — it
@@ -12699,9 +13967,9 @@ const calculateParametersTokens = (parameters, encoder, constants) => {
12699
13967
  /**
12700
13968
  * Calculate tokens for a single tool
12701
13969
  */
12702
- const calculateToolTokens = (tool, encoder, constants) => {
13970
+ const calculateToolTokens = (tool$1, encoder, constants) => {
12703
13971
  let tokens = constants.funcInit;
12704
- const func = tool.function;
13972
+ const func = tool$1.function;
12705
13973
  const fName = func.name;
12706
13974
  let fDesc = func.description || "";
12707
13975
  if (fDesc.endsWith(".")) fDesc = fDesc.slice(0, -1);
@@ -12715,7 +13983,7 @@ const calculateToolTokens = (tool, encoder, constants) => {
12715
13983
  */
12716
13984
  const numTokensForTools = (tools, encoder, constants) => {
12717
13985
  let funcTokenCount = 0;
12718
- for (const tool of tools) funcTokenCount += calculateToolTokens(tool, encoder, constants);
13986
+ for (const tool$1 of tools) funcTokenCount += calculateToolTokens(tool$1, encoder, constants);
12719
13987
  funcTokenCount += constants.funcEnd;
12720
13988
  return funcTokenCount;
12721
13989
  };
@@ -13001,6 +14269,28 @@ function browserToolsEnabled() {
13001
14269
  return hasSupportedBrowserInstalled();
13002
14270
  }
13003
14271
  /**
14272
+ * Gate for the fleet session-control MCP tools (`mcp__fleet__*`).
14273
+ *
14274
+ * Returns true iff the operator opted in (`state.fleetEnabled`, set by
14275
+ * `--fleet`, OR `GH_ROUTER_ENABLE_FLEET=1` read directly so non-
14276
+ * `setupAndServe` startup paths — tests, embedded use — can still flip
14277
+ * the gate). Fleet needs no local installed dependency check.
14278
+ */
14279
+ function fleetToolsEnabled() {
14280
+ return state.fleetEnabled || process.env.GH_ROUTER_ENABLE_FLEET === "1";
14281
+ }
14282
+ /**
14283
+ * Gate for ai-or-die Artifact review tools.
14284
+ *
14285
+ * Returns true iff this github-router process was launched inside an
14286
+ * ai-or-die tab and received the tab-scoped API trio. The tools are
14287
+ * otherwise invisible at `tools/list` and rejected at `tools/call`; direct
14288
+ * handler calls still return a friendly isError envelope.
14289
+ */
14290
+ function artifactToolsEnabled() {
14291
+ return !!(process.env.AIORDIE_BASE_URL && process.env.AIORDIE_TOKEN && process.env.AIORDIE_SESSION_ID);
14292
+ }
14293
+ /**
13004
14294
  * Gate for the `browse` worker tool (the Pi-driven autonomous browser
13005
14295
  * agent that delegates a browsing task to its own context).
13006
14296
  *
@@ -13196,6 +14486,8 @@ function toolEntries(scope) {
13196
14486
  if (t.capability === "browse_agent") return browseAgentEnabled();
13197
14487
  if (t.capability === "stand_in") return standInToolEnabled();
13198
14488
  if (t.capability === "browser") return browserToolsEnabled();
14489
+ if (t.capability === "fleet") return fleetToolsEnabled();
14490
+ if (t.capability === "artifact") return artifactToolsEnabled();
13199
14491
  if (t.capability === "browser_compound") return browserToolsEnabled() && browserCompoundToolsEnabled();
13200
14492
  if (t.capability === "browser_power") return browserToolsEnabled() && browserPowerToolsEnabled();
13201
14493
  return true;
@@ -13522,6 +14814,8 @@ async function handleToolsCall(body, scope) {
13522
14814
  if (nonPersonaTool && nonPersonaTool.capability === "browse_agent" && !browseAgentEnabled()) return rpcError(body.id, RPC_METHOD_NOT_FOUND, `tools/call: unknown tool "${name}"`);
13523
14815
  if (nonPersonaTool && nonPersonaTool.capability === "stand_in" && !standInToolEnabled()) return rpcError(body.id, RPC_METHOD_NOT_FOUND, `tools/call: unknown tool "${name}"`);
13524
14816
  if (nonPersonaTool && nonPersonaTool.capability === "browser" && !browserToolsEnabled()) return rpcError(body.id, RPC_METHOD_NOT_FOUND, `tools/call: unknown tool "${name}"`);
14817
+ if (nonPersonaTool && nonPersonaTool.capability === "fleet" && !fleetToolsEnabled()) return rpcError(body.id, RPC_METHOD_NOT_FOUND, `tools/call: unknown tool "${name}"`);
14818
+ if (nonPersonaTool && nonPersonaTool.capability === "artifact" && !artifactToolsEnabled()) return rpcError(body.id, RPC_METHOD_NOT_FOUND, `tools/call: unknown tool "${name}"`);
13525
14819
  if (nonPersonaTool && nonPersonaTool.capability === "browser_compound" && !(browserToolsEnabled() && browserCompoundToolsEnabled())) return rpcError(body.id, RPC_METHOD_NOT_FOUND, `tools/call: unknown tool "${name}"`);
13526
14820
  if (nonPersonaTool && nonPersonaTool.capability === "browser_power" && !(browserToolsEnabled() && browserPowerToolsEnabled())) return rpcError(body.id, RPC_METHOD_NOT_FOUND, `tools/call: unknown tool "${name}"`);
13527
14821
  let personaPrompt;
@@ -16197,32 +17491,32 @@ function toolbeltTool(workspace) {
16197
17491
  description: "Run a read-only code-analysis CLI in the workspace with NO shell (args are literal — no pipes / redirects / chaining / globbing). Tools: rg, fd, sg (ast-grep), jq, yq, gron, scc, tokei, difft (difftastic), and git (read-only subcommands). Write/exec flags (fd -x, rg --pre, ast-grep --rewrite, yq -i) and mutating git subcommands are rejected. Returns combined stdout (stderr appended on non-zero exit).",
16198
17492
  parameters: TOOLBELT_PARAMS,
16199
17493
  async execute(_toolCallId, params, signal) {
16200
- const tool = params.tool;
17494
+ const tool$1 = params.tool;
16201
17495
  const args = Array.isArray(params.args) ? params.args.map(String) : [];
16202
- if (!TOOLBELT_TOOL_SET.has(tool)) throw new Error(`toolbelt: unknown tool '${tool}'`);
16203
- if (tool === "git") {
17496
+ if (!TOOLBELT_TOOL_SET.has(tool$1)) throw new Error(`toolbelt: unknown tool '${tool$1}'`);
17497
+ if (tool$1 === "git") {
16204
17498
  const sub = args[0];
16205
17499
  if (!sub || !GIT_READONLY_SUBCOMMANDS.has(sub)) throw new Error(`git: only read-only subcommands are allowed and the subcommand must be args[0] (no leading -C/-c). Allowed: ${[...GIT_READONLY_SUBCOMMANDS].join(", ")}. Got: ${sub ? `'${sub}'` : "<none>"}`);
16206
17500
  for (const arg of args) if (gitArgDenied(arg)) throw new Error(`git: flag '${arg}' is not allowed (toolbelt is read-only)`);
16207
17501
  } else {
16208
- if (tool === "sg" && args[0] && SG_DENIED_SUBCOMMANDS.has(args[0])) throw new Error(`sg: subcommand '${args[0]}' is not allowed (toolbelt is read-only)`);
16209
- const denied = TOOLBELT_DENIED_FLAGS[tool];
17502
+ if (tool$1 === "sg" && args[0] && SG_DENIED_SUBCOMMANDS.has(args[0])) throw new Error(`sg: subcommand '${args[0]}' is not allowed (toolbelt is read-only)`);
17503
+ const denied = TOOLBELT_DENIED_FLAGS[tool$1];
16210
17504
  if (denied) {
16211
- for (const arg of args) if (argViolatesDenylist(denied, arg)) throw new Error(`${tool}: arg '${arg}' carries a write/exec flag (toolbelt is read-only)`);
17505
+ for (const arg of args) if (argViolatesDenylist(denied, arg)) throw new Error(`${tool$1}: arg '${arg}' carries a write/exec flag (toolbelt is read-only)`);
16212
17506
  }
16213
17507
  }
16214
17508
  const env = buildEnv();
16215
- if (tool === "git") {
17509
+ if (tool$1 === "git") {
16216
17510
  env.GIT_PAGER = "cat";
16217
17511
  env.PAGER = "cat";
16218
17512
  env.GIT_TERMINAL_PROMPT = "0";
16219
17513
  env.GIT_OPTIONAL_LOCKS = "0";
16220
17514
  }
16221
- const binPath = resolveExecutable(tool, { env });
16222
- if (!binPath) return textResult(`${tool}: not available on this host (not on PATH / toolbelt). rg/fd/jq/yq/sg/gron/scc/difft ship with the toolbelt; git and tokei may require a system install.`);
17515
+ const binPath = resolveExecutable(tool$1, { env });
17516
+ if (!binPath) return textResult(`${tool$1}: not available on this host (not on PATH / toolbelt). rg/fd/jq/yq/sg/gron/scc/difft ship with the toolbelt; git and tokei may require a system install.`);
16223
17517
  const TOOLBELT_TIMEOUT_MS = 6e4;
16224
17518
  const TOOLBELT_STDOUT_CAP = 1024 * 1024;
16225
- const res = await runManagedExeCapture(binPath, tool === "git" ? buildGitExecArgs(args) : args, {
17519
+ const res = await runManagedExeCapture(binPath, tool$1 === "git" ? buildGitExecArgs(args) : args, {
16226
17520
  cwd: workspace,
16227
17521
  env,
16228
17522
  timeoutMs: TOOLBELT_TIMEOUT_MS,
@@ -16232,13 +17526,13 @@ function toolbeltTool(workspace) {
16232
17526
  else signal?.addEventListener("abort", () => killChildTree(child), { once: true });
16233
17527
  }
16234
17528
  });
16235
- if (signal?.aborted) throw new Error(`${tool} aborted`);
16236
- if (res.timedOut) throw new Error(`${tool} timed out after ${TOOLBELT_TIMEOUT_MS}ms`);
17529
+ if (signal?.aborted) throw new Error(`${tool$1} aborted`);
17530
+ if (res.timedOut) throw new Error(`${tool$1} timed out after ${TOOLBELT_TIMEOUT_MS}ms`);
16237
17531
  const parts = [];
16238
17532
  if (res.stdout) parts.push(res.stdout);
16239
17533
  if ((res.code !== 0 || !res.stdout) && res.stderr.trim()) parts.push(`[stderr] ${res.stderr.trim()}`);
16240
17534
  if (res.stdoutTruncated) parts.push(`[truncated at ${TOOLBELT_STDOUT_CAP} bytes — narrow the query]`);
16241
- if (parts.length === 0) parts.push(`(${tool} exited ${res.code} with no output)`);
17535
+ if (parts.length === 0) parts.push(`(${tool$1} exited ${res.code} with no output)`);
16242
17536
  return textResult(parts.join("\n"));
16243
17537
  }
16244
17538
  };
@@ -19233,7 +20527,8 @@ const MCP_GROUPS = Object.freeze([
19233
20527
  "workers",
19234
20528
  "orchestrate",
19235
20529
  "browser",
19236
- "decide"
20530
+ "decide",
20531
+ "fleet"
19237
20532
  ]);
19238
20533
  const GROUP_META = Object.freeze({
19239
20534
  peers: {
@@ -19265,6 +20560,11 @@ const GROUP_META = Object.freeze({
19265
20560
  preferredKey: "decide",
19266
20561
  urlSuffix: "decide",
19267
20562
  serverInfoName: "github-router-decide"
20563
+ },
20564
+ fleet: {
20565
+ preferredKey: "fleet",
20566
+ urlSuffix: "fleet",
20567
+ serverInfoName: "github-router-fleet"
19268
20568
  }
19269
20569
  });
19270
20570
  /** True iff `s` is a registered group name (route `:group` param validation). */
@@ -20376,6 +21676,8 @@ const NON_PERSONA_MCP_TOOLS = Object.freeze([
20376
21676
  return runStandInToolCall(args, signal);
20377
21677
  }
20378
21678
  },
21679
+ ...ARTIFACT_TOOLS,
21680
+ ...FLEET_TOOLS,
20379
21681
  ...BROWSER_TOOLS.map((t) => ({
20380
21682
  ...t,
20381
21683
  group: "browser",
@@ -20704,5 +22006,5 @@ async function runStandInToolCall(args, signal) {
20704
22006
  }
20705
22007
 
20706
22008
  //#endregion
20707
- export { handleMcpDelete as $, IMPLEMENT_DEFAULT_MODEL as A, setupGitHubToken as At, TOOLBELT_TOOLS$1 as B, getModels as Bt, stopGateEnabledForRepo as C, UPSTREAM_FETCH_TIMEOUT_MS as Ct, liveExec as D, getPackageVersion as Dt, resolveSealedGate as E, pickClaudeDefault as Et, availableToolCommands as F, filterBetaHeader as Ft, buildAdvisorStream as G, copilotBaseUrl as Gt, searchWeb as H, HTTPError as Ht, buildToolbeltAwareness as I, isNullish as It, buildOpenAIErrorEvent as J, state as Jt, injectAdvisorTool as K, copilotHeaders as Kt, toolbeltEnabled as L, resolveCodexModel as Lt, appendPlanReminder as M, cacheCopilotVersion as Mt, runWorkerAgent as N, cacheModels as Nt, BROWSE_DEFAULT_MODEL as O, withInstallLock as Ot, withNoOutputRetry as P, cacheVSCodeVersion as Pt, relayAnthropicStream as Q, toolbeltSkipSet as R, resolveModel as Rt, repoRoot as S, DEFAULT_PORT as St, trustRepo as T, generateRandomPort as Tt, ADVISOR_INTERNAL_TOOL_NAME as U, forwardError as Ut, assetFor as V, fetchWithTransientRetry as Vt, ADVISOR_TOOL_INSTRUCTIONS as W, GITHUB_API_BASE_URL as Wt, logStreamError as X, isControllerClosedError as Y, readIteratorWithTimeout as Z, fileFindingsStore as _, collapsePathKeys as _t, buildPeerAwarenessSnippet as a, createMessages as at, isSubagentContext as b, DEFAULT_CODEX_MODEL as bt, buildStopHookCommand as c, createChatCompletions as ct, fileBlockBudget as d, parseJsonOrDiagnose as dt, handleMcpPost as et, injectStopHookIntoSettingsFile as f, provisionBrowserAssets as ft, fileBaselineStore as g, extractZipMember as gt, stopReviewEnabled as h, extractTarGzMember as ht, buildAgentPrompt as i, countTokens as it, PLAN_DEFAULT_MODEL as j, tryRefreshAndRetry as jt, DEFAULT_MODEL as k, setupCopilotToken as kt, captureLaunchBaseline as l, MAX_RESPONSE_BODY_BYTES as lt, stopGateId as m, provisionAndIndexColbert as mt, MCP_GROUPS as n, standInToolEnabled as nt, personasFor as o, getTokenCount as ot, launchBaselineKey as p, hasSupportedBrowserInstalled as pt, isAdvisorRequested as q, githubHeaders as qt, assertMcpToolSurfaceConsistent as r, workerToolsEnabled as rt, buildSessionBindHookCommand as s, createResponses as st, GROUP_META as t, browserToolsEnabled as tt, decideStopHook as u, readResponseBodyCapped as ut, fileLastPromptStore as v, toolbeltPathOverride as vt, stopReviewStateDir as w, UPSTREAM_INACTIVITY_TIMEOUT_MS as wt, repoFingerprint as x, DEFAULT_CODEX_MODEL_FALLBACKS as xt, fileReviewDebounce as y, DEFAULT_CLAUDE_MODEL_FALLBACKS as yt, vscodeRipgrepPath as z, sleep as zt };
20708
- //# sourceMappingURL=peer-mcp-personas-CoeEliOe.js.map
22009
+ export { handleMcpDelete as $, IMPLEMENT_DEFAULT_MODEL as A, setupCopilotToken as At, TOOLBELT_TOOLS$1 as B, sleep as Bt, stopGateEnabledForRepo as C, DEFAULT_PORT as Ct, liveExec as D, pickClaudeDefault as Dt, resolveSealedGate as E, generateRandomPort as Et, availableToolCommands as F, cacheVSCodeVersion as Ft, buildAdvisorStream as G, GITHUB_API_BASE_URL as Gt, searchWeb as H, fetchWithTransientRetry as Ht, buildToolbeltAwareness as I, filterBetaHeader as It, buildOpenAIErrorEvent as J, githubHeaders as Jt, injectAdvisorTool as K, copilotBaseUrl as Kt, toolbeltEnabled as L, isNullish as Lt, appendPlanReminder as M, tryRefreshAndRetry as Mt, runWorkerAgent as N, cacheCopilotVersion as Nt, BROWSE_DEFAULT_MODEL as O, getPackageVersion as Ot, withNoOutputRetry as P, cacheModels as Pt, relayAnthropicStream as Q, toolbeltSkipSet as R, resolveCodexModel as Rt, repoRoot as S, DEFAULT_CODEX_MODEL_FALLBACKS as St, trustRepo as T, UPSTREAM_INACTIVITY_TIMEOUT_MS as Tt, ADVISOR_INTERNAL_TOOL_NAME as U, HTTPError as Ut, assetFor as V, getModels as Vt, ADVISOR_TOOL_INSTRUCTIONS as W, forwardError as Wt, logStreamError as X, isControllerClosedError as Y, state as Yt, readIteratorWithTimeout as Z, fileFindingsStore as _, extractZipMember as _t, buildPeerAwarenessSnippet as a, countTokens as at, isSubagentContext as b, DEFAULT_CLAUDE_MODEL_FALLBACKS as bt, buildStopHookCommand as c, createResponses as ct, fileBlockBudget as d, readResponseBodyCapped as dt, handleMcpPost as et, injectStopHookIntoSettingsFile as f, parseJsonOrDiagnose as ft, fileBaselineStore as g, extractTarGzMember as gt, stopReviewEnabled as h, provisionAndIndexColbert as ht, buildAgentPrompt as i, workerToolsEnabled as it, PLAN_DEFAULT_MODEL as j, setupGitHubToken as jt, DEFAULT_MODEL as k, withInstallLock as kt, captureLaunchBaseline as l, createChatCompletions as lt, stopGateId as m, hasSupportedBrowserInstalled as mt, MCP_GROUPS as n, fleetToolsEnabled as nt, personasFor as o, createMessages as ot, launchBaselineKey as p, provisionBrowserAssets as pt, isAdvisorRequested as q, copilotHeaders as qt, assertMcpToolSurfaceConsistent as r, standInToolEnabled as rt, buildSessionBindHookCommand as s, getTokenCount as st, GROUP_META as t, browserToolsEnabled as tt, decideStopHook as u, MAX_RESPONSE_BODY_BYTES as ut, fileLastPromptStore as v, collapsePathKeys as vt, stopReviewStateDir as w, UPSTREAM_FETCH_TIMEOUT_MS as wt, repoFingerprint as x, DEFAULT_CODEX_MODEL as xt, fileReviewDebounce as y, toolbeltPathOverride as yt, vscodeRipgrepPath as z, resolveModel as zt };
22010
+ //# sourceMappingURL=peer-mcp-personas-B6z15bmc.js.map