github-router 0.3.151 → 0.3.153

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.
@@ -1,6 +1,6 @@
1
- import { t as PATHS } from "./paths-D0tJ_tms.js";
2
- import { d as runCommandCapture, l as parseBoolEnv, n as isPidAlive, o as trackChild, p as runManagedExeCapture, r as registerColbertExitHandlers, t as getColbertInstanceUuid, u as resolveExecutable } from "./lifecycle-DyEXZu2z.js";
3
- import { i as registerExitHandlers, n as getInstanceUuid, r as recordWorkerRepo, t as WorktreeRegistry } from "./lifecycle-DGvk4z63.js";
1
+ import { t as PATHS } from "./paths-Bt7sqiVr.js";
2
+ import { d as runCommandCapture, l as parseBoolEnv, n as isPidAlive, o as trackChild, p as runManagedExeCapture, r as registerColbertExitHandlers, t as getColbertInstanceUuid, u as resolveExecutable } from "./lifecycle-VTQI28wT.js";
3
+ import { i as registerExitHandlers, n as getInstanceUuid, r as recordWorkerRepo, t as WorktreeRegistry } from "./lifecycle-C4k0pEvn.js";
4
4
  import { createRequire } from "node:module";
5
5
  import consola from "consola";
6
6
  import { createHash, randomBytes, randomUUID, timingSafeEqual } from "node:crypto";
@@ -1176,35 +1176,172 @@ var ArtifactError = class extends Error {
1176
1176
  this.detail = args.detail;
1177
1177
  }
1178
1178
  };
1179
+ const AWAIT_DEFAULT_TIMEOUT_MS = 25e3;
1180
+ const AWAIT_ABORT_MARGIN_MS = 5e3;
1181
+ const DEFAULT_RETRY_BASE_MS = 250;
1182
+ const TRANSIENT_RETRIES = 2;
1183
+ const DEFAULT_RETRYABLE_CODES = new Set(["UNREACHABLE", "TIMEOUT"]);
1184
+ const AWAIT_RETRYABLE_CODES = new Set(["UNREACHABLE"]);
1179
1185
  var ArtifactClient = class {
1180
1186
  baseUrl;
1181
1187
  token;
1182
1188
  sessionId;
1183
1189
  fetchFn;
1184
1190
  insecureTLS;
1191
+ retryBaseMs;
1185
1192
  constructor(options) {
1186
1193
  this.baseUrl = options.baseUrl.replace(/\/+$/, "");
1187
1194
  this.token = options.token;
1188
1195
  this.sessionId = options.sessionId;
1189
1196
  this.fetchFn = options.fetchFn ?? globalThis.fetch.bind(globalThis);
1190
1197
  this.insecureTLS = options.insecureTLS ?? false;
1198
+ this.retryBaseMs = options.retryBaseMs ?? DEFAULT_RETRY_BASE_MS;
1191
1199
  }
1192
- open(file, signal) {
1193
- return this.request("POST", `/api/artifact/${encodeURIComponent(this.sessionId)}/open`, { file }, signal);
1200
+ /**
1201
+ * Open (or replace) the review for this session. `mode` is advisory metadata
1202
+ * forwarded to the server (forward-compat: ignored if unknown); the actual
1203
+ * interactivity comes from the served HTML's `data-aod-*` markup. Retried on a
1204
+ * transient failure with a STABLE idempotency key so a retry-after-success does
1205
+ * not double-open.
1206
+ */
1207
+ open(file, opts = {}) {
1208
+ const idempotencyKey = opts.idempotencyKey ?? randomUUID();
1209
+ const body = { file };
1210
+ if (opts.mode) body.mode = opts.mode;
1211
+ return this.withRetry(() => this.requestOnce({
1212
+ method: "POST",
1213
+ pathname: this.path("/open"),
1214
+ body,
1215
+ signal: opts.signal,
1216
+ idempotencyKey
1217
+ }), TRANSIENT_RETRIES, opts.signal);
1194
1218
  }
1195
- poll(timeoutMsHint, signal) {
1196
- return this.request("GET", `/api/artifact/${encodeURIComponent(this.sessionId)}/poll`, void 0, signal, timeoutMsHint);
1219
+ /**
1220
+ * Replace the current review's content. Exactly one of `file` | `html` (the
1221
+ * caller-facing tool enforces that). `html` is written by the SERVER to the
1222
+ * review's existing sandboxed file, so `html` with no existing review is an
1223
+ * INVALID_REQUEST from the server. Retried with a stable idempotency key.
1224
+ */
1225
+ update(opts) {
1226
+ const idempotencyKey = opts.idempotencyKey ?? randomUUID();
1227
+ const body = {};
1228
+ if (opts.file !== void 0) body.file = opts.file;
1229
+ if (opts.html !== void 0) body.html = opts.html;
1230
+ return this.withRetry(() => this.requestOnce({
1231
+ method: "POST",
1232
+ pathname: this.path("/update"),
1233
+ body,
1234
+ signal: opts.signal,
1235
+ idempotencyKey,
1236
+ allowEmptyJson: true
1237
+ }), TRANSIENT_RETRIES, opts.signal);
1197
1238
  }
1239
+ /** Force a reload from disk (no content change). Single-shot (idempotent, cheap). */
1240
+ refresh(signal) {
1241
+ return this.requestOnce({
1242
+ method: "POST",
1243
+ pathname: this.path("/refresh"),
1244
+ signal,
1245
+ allowEmptyJson: true
1246
+ });
1247
+ }
1248
+ /** Hide the panel UI while keeping the review alive. Single-shot; server idempotent. */
1249
+ dismiss(signal) {
1250
+ return this.requestOnce({
1251
+ method: "POST",
1252
+ pathname: this.path("/dismiss"),
1253
+ signal,
1254
+ allowEmptyJson: true
1255
+ });
1256
+ }
1257
+ /**
1258
+ * Typed drain (contract v2.2 §1/§2). Long-holds up to the server cap, returns
1259
+ * events with `id > cursor` plus the new high-water `cursor`. Idempotent by
1260
+ * (cursor, event.id): re-calling with the same cursor replays the same window
1261
+ * from the server's bounded buffer, so a lost cursor (compaction) is
1262
+ * recoverable. Retried on a transient network failure (the cursor makes retry
1263
+ * safe — no double-consumption).
1264
+ */
1265
+ awaitEvents(opts = {}) {
1266
+ const serverTimeoutMs = typeof opts.timeoutMs === "number" && Number.isFinite(opts.timeoutMs) && opts.timeoutMs > 0 ? opts.timeoutMs : AWAIT_DEFAULT_TIMEOUT_MS;
1267
+ const clientTimeoutMs = serverTimeoutMs + AWAIT_ABORT_MARGIN_MS;
1268
+ return this.withRetry(() => this.requestOnce({
1269
+ method: "GET",
1270
+ pathname: this.path("/await"),
1271
+ query: {
1272
+ cursor: opts.cursor,
1273
+ timeoutMs: String(serverTimeoutMs)
1274
+ },
1275
+ signal: opts.signal,
1276
+ timeoutMsHint: clientTimeoutMs
1277
+ }), TRANSIENT_RETRIES, opts.signal, AWAIT_RETRYABLE_CODES);
1278
+ }
1279
+ /** Free-text agent->human reply. SINGLE-SHOT (not retried): a retry-after-success
1280
+ * would render a duplicate chat bubble server-side. */
1198
1281
  agentReply(text, signal) {
1199
- return this.request("POST", `/api/artifact/${encodeURIComponent(this.sessionId)}/agent-reply`, { text }, signal, void 0, true);
1282
+ return this.requestOnce({
1283
+ method: "POST",
1284
+ pathname: this.path("/agent-reply"),
1285
+ body: { text },
1286
+ signal,
1287
+ allowEmptyJson: true
1288
+ });
1200
1289
  }
1201
- end(signal) {
1202
- return this.request("POST", `/api/artifact/${encodeURIComponent(this.sessionId)}/end`, void 0, signal, void 0, true);
1290
+ /**
1291
+ * End the review. Retried with a stable idempotency key; a NOT_FOUND (the
1292
+ * review is already ended — whether by a prior call or by a retry landing after
1293
+ * the first attempt succeeded) is mapped to a successful `{ ok, status:"ended" }`
1294
+ * rather than surfaced as a 404 (contract v2.2 §1.1).
1295
+ */
1296
+ async end(signal) {
1297
+ const idempotencyKey = randomUUID();
1298
+ try {
1299
+ return await this.withRetry(() => this.requestOnce({
1300
+ method: "POST",
1301
+ pathname: this.path("/end"),
1302
+ signal,
1303
+ idempotencyKey,
1304
+ allowEmptyJson: true
1305
+ }), TRANSIENT_RETRIES, signal);
1306
+ } catch (err) {
1307
+ if (err instanceof ArtifactError && err.code === "NOT_FOUND") return {
1308
+ ok: true,
1309
+ status: "ended"
1310
+ };
1311
+ throw err;
1312
+ }
1203
1313
  }
1204
- async request(method, pathname, body, signal, timeoutMsHint, allowEmptyJson = false) {
1314
+ /**
1315
+ * FROZEN legacy long-poll (contract v2.2 §1). Old payload shape,
1316
+ * comment-equivalent only. New agents use `awaitEvents`. Single request per
1317
+ * call (the caller-facing tool owns the bounded re-poll budget).
1318
+ */
1319
+ poll(timeoutMsHint, signal) {
1320
+ return this.requestOnce({
1321
+ method: "GET",
1322
+ pathname: this.path("/poll"),
1323
+ signal,
1324
+ timeoutMsHint
1325
+ });
1326
+ }
1327
+ path(suffix) {
1328
+ return `/api/artifact/${encodeURIComponent(this.sessionId)}${suffix}`;
1329
+ }
1330
+ async withRetry(fn, retries, signal, retryableCodes = DEFAULT_RETRYABLE_CODES) {
1331
+ let attempt = 0;
1332
+ for (;;) try {
1333
+ return await fn();
1334
+ } catch (err) {
1335
+ attempt += 1;
1336
+ if (!(err instanceof ArtifactError && err.retryable && retryableCodes.has(err.code)) || attempt > retries || signal?.aborted) throw err;
1337
+ const base = this.retryBaseMs;
1338
+ await sleep$1(base <= 0 ? 0 : Math.round(base * 2 ** (attempt - 1) * (.5 + Math.random() * .5)), signal);
1339
+ }
1340
+ }
1341
+ async requestOnce(o) {
1205
1342
  let url;
1206
1343
  try {
1207
- url = new URL(pathname, `${this.baseUrl}/`);
1344
+ url = new URL(o.pathname, `${this.baseUrl}/`);
1208
1345
  } catch (err) {
1209
1346
  throw new ArtifactError({
1210
1347
  code: "UNREACHABLE",
@@ -1213,48 +1350,73 @@ var ArtifactClient = class {
1213
1350
  detail: err
1214
1351
  });
1215
1352
  }
1216
- const timeout = combineSignalAndTimeout(signal, timeoutMsHint);
1217
- let response;
1353
+ if (o.query) {
1354
+ for (const [key, value] of Object.entries(o.query)) if (value !== void 0) url.searchParams.set(key, value);
1355
+ }
1356
+ const timeout = combineSignalAndTimeout(o.signal, o.timeoutMsHint);
1218
1357
  try {
1358
+ const headers = { Authorization: `Bearer ${this.token}` };
1359
+ if (o.body !== void 0) headers["Content-Type"] = "application/json";
1360
+ if (o.idempotencyKey) headers["Idempotency-Key"] = o.idempotencyKey;
1219
1361
  const init = {
1220
- method,
1221
- headers: {
1222
- Authorization: `Bearer ${this.token}`,
1223
- ...body === void 0 ? {} : { "Content-Type": "application/json" }
1224
- },
1225
- body: body === void 0 ? void 0 : JSON.stringify(body),
1362
+ method: o.method,
1363
+ headers,
1364
+ body: o.body === void 0 ? void 0 : JSON.stringify(o.body),
1226
1365
  redirect: "error",
1227
1366
  signal: timeout.signal
1228
1367
  };
1229
1368
  if (this.insecureTLS) applyInsecureTls(init);
1230
- response = await this.fetchFn(url.toString(), init);
1369
+ const response = await this.fetchFn(url.toString(), init);
1370
+ if (!response.ok) throw await mapHttpError$1(response);
1371
+ let text;
1372
+ try {
1373
+ text = await response.text();
1374
+ } catch (err) {
1375
+ if (isAbortLike$2(err)) throw mapNetworkError$1(err);
1376
+ throw new ArtifactError({
1377
+ code: "INVALID_RESPONSE",
1378
+ message: "artifact API response body could not be read",
1379
+ retryable: false,
1380
+ detail: err
1381
+ });
1382
+ }
1383
+ if (!text && o.allowEmptyJson) return {};
1384
+ try {
1385
+ return JSON.parse(text);
1386
+ } catch (err) {
1387
+ throw new ArtifactError({
1388
+ code: "INVALID_RESPONSE",
1389
+ message: "artifact API returned a non-JSON response",
1390
+ retryable: false,
1391
+ detail: err
1392
+ });
1393
+ }
1231
1394
  } catch (err) {
1395
+ if (err instanceof ArtifactError) throw err;
1232
1396
  throw mapNetworkError$1(err);
1233
1397
  } finally {
1234
1398
  timeout.cleanup();
1235
1399
  }
1236
- if (!response.ok) throw await mapHttpError$1(response);
1237
- const text = await response.text().catch((err) => {
1238
- throw new ArtifactError({
1239
- code: "INVALID_RESPONSE",
1240
- message: "artifact API response body could not be read",
1241
- retryable: false,
1242
- detail: err
1243
- });
1244
- });
1245
- if (!text && allowEmptyJson) return {};
1246
- try {
1247
- return JSON.parse(text);
1248
- } catch (err) {
1249
- throw new ArtifactError({
1250
- code: "INVALID_RESPONSE",
1251
- message: "artifact API returned a non-JSON response",
1252
- retryable: false,
1253
- detail: err
1254
- });
1255
- }
1256
1400
  }
1257
1401
  };
1402
+ function sleep$1(ms, signal) {
1403
+ if (ms <= 0) return Promise.resolve();
1404
+ return new Promise((resolve, reject) => {
1405
+ const onAbort = () => {
1406
+ clearTimeout(timer);
1407
+ reject(new DOMException("retry backoff aborted", "AbortError"));
1408
+ };
1409
+ const timer = setTimeout(() => {
1410
+ signal?.removeEventListener("abort", onAbort);
1411
+ resolve();
1412
+ }, ms);
1413
+ if (signal?.aborted) {
1414
+ onAbort();
1415
+ return;
1416
+ }
1417
+ signal?.addEventListener("abort", onAbort, { once: true });
1418
+ });
1419
+ }
1258
1420
  function combineSignalAndTimeout(signal, timeoutMsHint) {
1259
1421
  const timeoutMs = typeof timeoutMsHint === "number" && Number.isFinite(timeoutMsHint) && timeoutMsHint > 0 ? timeoutMsHint : void 0;
1260
1422
  if (timeoutMs === void 0) return {
@@ -1311,6 +1473,13 @@ async function mapHttpError$1(response) {
1311
1473
  status: response.status,
1312
1474
  detail
1313
1475
  });
1476
+ if (response.status === 400 && detailToCode(detail)?.toUpperCase() === "INVALID_REQUEST") return new ArtifactError({
1477
+ code: "INVALID_REQUEST",
1478
+ message: `artifact API rejected the request (400)${suffix}`,
1479
+ retryable: false,
1480
+ status: response.status,
1481
+ detail
1482
+ });
1314
1483
  return new ArtifactError({
1315
1484
  code: "UPSTREAM_ERROR",
1316
1485
  message: `artifact API returned HTTP ${response.status}${suffix}`,
@@ -1355,6 +1524,18 @@ function detailToMessage$1(detail) {
1355
1524
  }
1356
1525
  if (typeof record.message === "string") return record.message;
1357
1526
  }
1527
+ /** Extract a machine `code` from an upstream error body (`{error:{code}}` or
1528
+ * `{code}`) so a tagged 400 can be classified (INVALID_REQUEST). */
1529
+ function detailToCode(detail) {
1530
+ if (typeof detail !== "object" || detail === null) return void 0;
1531
+ const record = detail;
1532
+ const error = record.error;
1533
+ if (typeof error === "object" && error !== null) {
1534
+ const code = error.code;
1535
+ if (typeof code === "string") return code;
1536
+ }
1537
+ if (typeof record.code === "string") return record.code;
1538
+ }
1358
1539
  function isAbortLike$2(err) {
1359
1540
  return err instanceof Error && (err.name === "AbortError" || err.name === "TimeoutError");
1360
1541
  }
@@ -1383,27 +1564,86 @@ function tool(toolNameHttp, description, inputSchema, handler) {
1383
1564
  };
1384
1565
  }
1385
1566
  const ARTIFACT_TOOLS = Object.freeze([
1386
- 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$2({ file: stringProp$2("Workspace-relative or absolute file path to show in the Artifact panel.") }, ["file"]), async (args, signal) => {
1567
+ tool("artifact_open", "Open a workspace file in ai-or-die's Artifact review panel for human review. Pass mode:\"interactive\" when the HTML carries data-aod-* action controls. Only works inside an ai-or-die tab-backed Claude session.", objectSchema$2({
1568
+ file: stringProp$2("Workspace-relative or absolute file path to show in the Artifact panel."),
1569
+ mode: enumProp(["static", "interactive"], "Advisory. \"interactive\" signals the HTML contains data-aod-* action controls the panel should wire; \"static\" (default) is a read-and-annotate artifact.")
1570
+ }, ["file"]), async (args, signal) => {
1387
1571
  const env = readArtifactEnv();
1388
1572
  if (!env) return missingEnvResult();
1389
1573
  const file = requiredString$2(args, "file");
1574
+ const mode = optionalEnum(args, "mode", ["static", "interactive"]);
1575
+ const response = await clientFromEnv(env).open(file, {
1576
+ mode,
1577
+ signal
1578
+ });
1390
1579
  return ok$2({
1391
- viewUrl: (await clientFromEnv(env).open(file, signal)).viewUrl,
1392
- next_step: "Tell the user to review at the Artifact panel, then call artifact_poll."
1580
+ viewUrl: response.viewUrl,
1581
+ sessionId: response.sessionId,
1582
+ key: response.key,
1583
+ next_step: "Tell the user to review at the Artifact panel, then call artifact_await to receive their feedback."
1393
1584
  });
1394
1585
  }),
1395
- 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$2({}, []), async (_args, signal) => {
1586
+ tool("artifact_update", "Replace the current Artifact review's content in place. Provide EXACTLY ONE of file (a workspace file path) or html (raw HTML the server writes to the review's sandboxed file). html requires an already-open review. Only works inside an ai-or-die tab-backed Claude session.", objectSchema$2({
1587
+ file: stringProp$2("Workspace-relative or absolute file path to become the review's new content."),
1588
+ html: stringProp$2("Raw HTML to write into the review's existing sandboxed file, then reload."),
1589
+ idempotencyKey: stringProp$2("Optional stable key so a retried update is de-duplicated by the server.")
1590
+ }, []), async (args, signal) => {
1396
1591
  const env = readArtifactEnv();
1397
1592
  if (!env) return missingEnvResult();
1398
- return ok$2(formatPollResponse(await pollUntilReady(clientFromEnv(env), signal)));
1593
+ const file = optionalString$2(args, "file");
1594
+ const html = optionalString$2(args, "html");
1595
+ if (file === void 0 === (html === void 0)) throw new ArtifactToolInputError("INVALID_ARGUMENT", "artifact_update requires EXACTLY ONE of arguments.file or arguments.html");
1596
+ const idempotencyKey = optionalString$2(args, "idempotencyKey");
1597
+ return ok$2({
1598
+ ...await clientFromEnv(env).update({
1599
+ file,
1600
+ html,
1601
+ idempotencyKey,
1602
+ signal
1603
+ }),
1604
+ ok: true,
1605
+ next_step: "The panel now shows the updated content. Call artifact_await for further feedback."
1606
+ });
1607
+ }),
1608
+ tool("artifact_refresh", "Force the ai-or-die Artifact panel to reload the current artifact from disk (no content change). Only works inside an ai-or-die tab-backed Claude session.", objectSchema$2({}, []), async (_args, signal) => {
1609
+ const env = readArtifactEnv();
1610
+ if (!env) return missingEnvResult();
1611
+ return ok$2({
1612
+ ...await clientFromEnv(env).refresh(signal),
1613
+ ok: true,
1614
+ next_step: "The panel reloaded the artifact. Call artifact_await for feedback."
1615
+ });
1616
+ }),
1617
+ tool("artifact_await", "Wait for the human's next Artifact review events (typed drain: comments AND structured action-button/checkbox events) and return them with a cursor. Pass the returned cursor on the next call to receive only newer events. Supersedes artifact_poll. Only works inside an ai-or-die tab-backed Claude session.", objectSchema$2({
1618
+ cursor: stringProp$2("High-water cursor from the previous artifact_await response. Omit on the first call."),
1619
+ timeoutMs: numberProp$2("Optional server long-hold budget in ms (default ~25000).")
1620
+ }, []), async (args, signal) => {
1621
+ const env = readArtifactEnv();
1622
+ if (!env) return missingEnvResult();
1623
+ const cursor = optionalString$2(args, "cursor");
1624
+ const timeoutMs = optionalNumber$2(args, "timeoutMs");
1625
+ return ok$2(formatAwaitResponse(await clientFromEnv(env).awaitEvents({
1626
+ cursor,
1627
+ timeoutMs,
1628
+ signal
1629
+ })));
1630
+ }),
1631
+ tool("artifact_dismiss", "Hide the ai-or-die Artifact panel UI while keeping the review alive (queued feedback preserved, channel open, re-openable). Only works inside an ai-or-die tab-backed Claude session.", objectSchema$2({}, []), async (_args, signal) => {
1632
+ const env = readArtifactEnv();
1633
+ if (!env) return missingEnvResult();
1634
+ return ok$2({
1635
+ ...await clientFromEnv(env).dismiss(signal),
1636
+ ok: true,
1637
+ next_step: "The panel is hidden but the review is still live. Re-open the artifact or call artifact_await when ready."
1638
+ });
1399
1639
  }),
1400
1640
  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$2({ text: stringProp$2("Agent reply text to deliver to the human Artifact review panel.") }, ["text"]), async (args, signal) => {
1401
1641
  const env = readArtifactEnv();
1402
1642
  if (!env) return missingEnvResult();
1403
1643
  const text = requiredString$2(args, "text");
1404
1644
  return ok$2({
1405
- ok: true,
1406
1645
  ...await clientFromEnv(env).agentReply(text, signal),
1646
+ ok: true,
1407
1647
  next_step: "Wait for further human review, or continue if the review loop is complete."
1408
1648
  });
1409
1649
  }),
@@ -1411,10 +1651,15 @@ const ARTIFACT_TOOLS = Object.freeze([
1411
1651
  const env = readArtifactEnv();
1412
1652
  if (!env) return missingEnvResult();
1413
1653
  return ok$2({
1414
- ok: true,
1415
1654
  ...await clientFromEnv(env).end(signal),
1655
+ ok: true,
1416
1656
  next_step: "Artifact review loop ended."
1417
1657
  });
1658
+ }),
1659
+ tool("artifact_poll", "FROZEN legacy alias for artifact_await (old payload, human comments only, no structured actions). New agents should call artifact_await instead. Only works inside an ai-or-die tab-backed Claude session.", objectSchema$2({ timeoutMs: numberProp$2("Optional per-call budget hint in ms (advisory).") }, []), async (_args, signal) => {
1660
+ const env = readArtifactEnv();
1661
+ if (!env) return missingEnvResult();
1662
+ return ok$2(formatPollResponse(await pollUntilReady(clientFromEnv(env), signal)));
1418
1663
  })
1419
1664
  ]);
1420
1665
  function readArtifactEnv() {
@@ -1489,6 +1734,30 @@ function formatPollResponse(response) {
1489
1734
  next_step: response.next_step ?? defaultPollNextStep(response.status)
1490
1735
  });
1491
1736
  }
1737
+ /**
1738
+ * Shape the typed drain for the model: pass events through verbatim (unknown
1739
+ * `kind`s preserved — the model ignores what it does not understand), echo the
1740
+ * cursor to thread into the next call, and pick a next_step from the events.
1741
+ */
1742
+ function formatAwaitResponse(response) {
1743
+ const events$1 = Array.isArray(response.events) ? response.events : [];
1744
+ const status = typeof response.status === "string" ? response.status : void 0;
1745
+ return definedObject$1({
1746
+ events: events$1,
1747
+ status,
1748
+ cursor: response.cursor,
1749
+ next_step: awaitNextStep(status ?? "", events$1)
1750
+ });
1751
+ }
1752
+ function awaitNextStep(status, events$1) {
1753
+ if ((status ?? "").toLowerCase() === "ended") return "The review has ended. No further feedback will arrive.";
1754
+ if (events$1.length === 0) return "No feedback yet. Call artifact_await again, passing the returned cursor.";
1755
+ const hasAction = events$1.some((e) => e.kind === "action");
1756
+ const hasComment = events$1.some((e) => e.kind === "comment");
1757
+ if (hasAction && hasComment) return "Act on the action events (buttons/checkboxes) and the comments, reply with artifact_reply, then call artifact_await with the returned cursor.";
1758
+ if (hasAction) return "The human triggered action controls. Act on them, optionally artifact_reply, then call artifact_await with the returned cursor.";
1759
+ return "Apply the human comments, call artifact_reply with a concise summary, then artifact_await with the returned cursor.";
1760
+ }
1492
1761
  function defaultPollNextStep(status) {
1493
1762
  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.";
1494
1763
  }
@@ -1501,6 +1770,24 @@ function requiredString$2(args, key) {
1501
1770
  if (typeof value !== "string" || value.trim() === "") throw new ArtifactToolInputError("INVALID_ARGUMENT", `arguments.${key} is required and must be a non-empty string`);
1502
1771
  return value;
1503
1772
  }
1773
+ function optionalString$2(args, key) {
1774
+ const value = args[key];
1775
+ if (value === void 0 || value === null) return void 0;
1776
+ if (typeof value !== "string" || value.trim() === "") throw new ArtifactToolInputError("INVALID_ARGUMENT", `arguments.${key} must be a non-empty string when provided`);
1777
+ return value;
1778
+ }
1779
+ function optionalNumber$2(args, key) {
1780
+ const value = args[key];
1781
+ if (value === void 0 || value === null) return void 0;
1782
+ if (typeof value !== "number" || !Number.isFinite(value) || value <= 0) throw new ArtifactToolInputError("INVALID_ARGUMENT", `arguments.${key} must be a positive number when provided`);
1783
+ return value;
1784
+ }
1785
+ function optionalEnum(args, key, allowed) {
1786
+ const value = optionalString$2(args, key);
1787
+ if (value === void 0) return void 0;
1788
+ if (!allowed.includes(value)) throw new ArtifactToolInputError("INVALID_ARGUMENT", `arguments.${key} must be one of ${allowed.join(", ")}`);
1789
+ return value;
1790
+ }
1504
1791
  var ArtifactToolInputError = class extends Error {
1505
1792
  code;
1506
1793
  constructor(code, message) {
@@ -1565,6 +1852,19 @@ function stringProp$2(description) {
1565
1852
  description
1566
1853
  };
1567
1854
  }
1855
+ function numberProp$2(description) {
1856
+ return {
1857
+ type: "number",
1858
+ description
1859
+ };
1860
+ }
1861
+ function enumProp(values, description) {
1862
+ return {
1863
+ type: "string",
1864
+ enum: [...values],
1865
+ description
1866
+ };
1867
+ }
1568
1868
 
1569
1869
  //#endregion
1570
1870
  //#region src/lib/fleet/mesh-egress-agent.ts
@@ -2769,7 +3069,7 @@ function isHardNotReady(reason) {
2769
3069
  */
2770
3070
  async function waitForMessageReady(client, localId, options = {}) {
2771
3071
  const now = options.now ?? Date.now;
2772
- const sleep$1 = options.sleep ?? realSleep;
3072
+ const sleep$2 = options.sleep ?? realSleep;
2773
3073
  const waitMs = Math.max(0, options.waitMs ?? 0);
2774
3074
  const pollMs = Math.max(1, options.pollMs ?? DEFAULT_READY_POLL_MS);
2775
3075
  const deadline = now() + waitMs;
@@ -2801,7 +3101,7 @@ async function waitForMessageReady(client, localId, options = {}) {
2801
3101
  ready: false,
2802
3102
  readiness: last
2803
3103
  };
2804
- await sleep$1(Math.min(pollMs, remaining));
3104
+ await sleep$2(Math.min(pollMs, remaining));
2805
3105
  }
2806
3106
  }
2807
3107
  /**
@@ -2879,7 +3179,7 @@ async function primeTurnCursor(client, localId, timeoutMs, signal) {
2879
3179
  */
2880
3180
  async function waitForTurnSettled(client, localId, options) {
2881
3181
  const now = options.now ?? Date.now;
2882
- const sleep$1 = options.sleep ?? realSleep;
3182
+ const sleep$2 = options.sleep ?? realSleep;
2883
3183
  const pollTimeoutMs = Math.max(1, options.pollTimeoutMs ?? DEFAULT_TURN_POLL_MS);
2884
3184
  const budget = Number.isFinite(options.timeoutMs) ? Math.max(0, options.timeoutMs) : 0;
2885
3185
  const deadline = now() + budget;
@@ -2911,7 +3211,7 @@ async function waitForTurnSettled(client, localId, options) {
2911
3211
  reason: "timeout",
2912
3212
  cursor
2913
3213
  };
2914
- await sleep$1(Math.min(TURN_POLL_ERROR_BACKOFF_MS, Math.max(0, deadline - now())));
3214
+ await sleep$2(Math.min(TURN_POLL_ERROR_BACKOFF_MS, Math.max(0, deadline - now())));
2915
3215
  continue;
2916
3216
  }
2917
3217
  cursor = response.cursor;
@@ -3028,13 +3328,13 @@ async function readTail(client, localId, lines, signal) {
3028
3328
  async function driveTask(deps) {
3029
3329
  const { client, localId, prompt, timeoutMs, expectReport, idempotencyKey, interruptKey, reportId, signal } = deps;
3030
3330
  const now = deps.now ?? Date.now;
3031
- const sleep$1 = deps.sleep ?? realSleep;
3331
+ const sleep$2 = deps.sleep ?? realSleep;
3032
3332
  const tailLines = deps.tailLines ?? DEFAULT_TAIL_LINES;
3033
3333
  const pollTimeoutMs = deps.pollTimeoutMs;
3034
3334
  const readyResult = await waitForMessageReady(client, localId, {
3035
3335
  waitMs: deps.idleWaitMs ?? DEFAULT_IDLE_WAIT_MS,
3036
3336
  now,
3037
- sleep: sleep$1,
3337
+ sleep: sleep$2,
3038
3338
  signal
3039
3339
  });
3040
3340
  if (!readyResult.ready && isHardNotReady(readyResult.readiness.reason)) return {
@@ -3077,7 +3377,7 @@ async function driveTask(deps) {
3077
3377
  pollTimeoutMs,
3078
3378
  cursor,
3079
3379
  now,
3080
- sleep: sleep$1,
3380
+ sleep: sleep$2,
3081
3381
  signal
3082
3382
  });
3083
3383
  cursor = settle.cursor;
@@ -3099,7 +3399,7 @@ async function driveTask(deps) {
3099
3399
  pollTimeoutMs,
3100
3400
  cursor,
3101
3401
  now,
3102
- sleep: sleep$1,
3402
+ sleep: sleep$2,
3103
3403
  signal
3104
3404
  });
3105
3405
  recovered = recovery.settled;
@@ -12558,7 +12858,7 @@ function logAudit$1(record) {
12558
12858
  try {
12559
12859
  const fs$2 = await import("node:fs/promises");
12560
12860
  const path$1 = await import("node:path");
12561
- const { PATHS: PATHS$1 } = await import("./paths-DhLJ9bLG.js");
12861
+ const { PATHS: PATHS$1 } = await import("./paths-C9Nkr_NK.js");
12562
12862
  const dir = path$1.join(PATHS$1.APP_DIR, "browser-mcp");
12563
12863
  await fs$2.mkdir(dir, { recursive: true });
12564
12864
  const line = JSON.stringify({
@@ -25782,17 +26082,28 @@ function buildAgentPrompt(persona, opts) {
25782
26082
  * anchors disguised as description ("cheapest first move", "saves them
25783
26083
  * the discovery step", "waste wall-clock"). Pure capability inventory.
25784
26084
  *
26085
+ * Wording budget (minimal sufficient guidance, NOT sentence-count parity):
26086
+ * each tool/group gets only the wording needed for correct, safe, high-value
26087
+ * use; extra wording must earn its attention cost. "Importance" shows up via
26088
+ * cost-of-misuse / ambiguity / invocation complexity, not proportional length
26089
+ * (a critical-but-simple tool can be one clause). When editing this snippet or
26090
+ * any injected guidance, re-check the whole surface for balance rather than
26091
+ * only expanding whatever was last touched.
26092
+ *
25785
26093
  * Surface contract (regression-pinned in tests/peer-mcp-personas.test.ts):
25786
26094
  * - Always lists codex_critic, codex_reviewer, opus_critic, advisor,
25787
26095
  * peer-review-coordinator, and the subagent-inheritance fact (the
25788
26096
  * load-bearing UX claim: spawned subagents inherit the peer-MCP
25789
26097
  * toolset via the mirrored `.claude.json`).
25790
26098
  * - Conditionally lists gemini_critic only when `geminiAvailable`.
25791
- * - Conditionally lists worker_explore / worker_implement /
25792
- * "Workers themselves have code_search" only when
25793
- * `workerToolsAvailable` (mirrors `workerToolsEnabled()` in
25794
- * src/routes/mcp/handler.ts so the snippet never names a tool gated
25795
- * out of the live catalog).
26099
+ * - Conditionally lists the `worker-*` background dispatcher subagents
26100
+ * (worker-explore / worker-review / worker-plan / worker-implement /
26101
+ * worker-test), the non-blocking-guard fact, and "Workers themselves
26102
+ * have code_search" only when `workerToolsAvailable` (mirrors
26103
+ * `workerToolsEnabled()` so the snippet never names a surface gated out
26104
+ * of the live catalog). The raw `mcp__<workers>__*` tools are named only
26105
+ * as the guarded plumbing the dispatchers call, never as a main-agent
26106
+ * interface.
25796
26107
  * - Conditionally lists stand_in only when `standInAvailable`
25797
26108
  * (mirrors `standInToolEnabled()`).
25798
26109
  * - Conditionally lists gh-first-mate only when `agentToolsAvailable`
@@ -25820,7 +26131,7 @@ function buildPeerAwarenessSnippet(opts) {
25820
26131
  criticList.push("`opus_critic` (Opus 4.7)");
25821
26132
  const codexCliClause = opts.codexCli ? " `mcp__codex-cli__codex` dispatches to `codex-implementer` (gpt-5.3-codex with workspace-write) for end-to-end coding tasks." : "";
25822
26133
  const para2Parts = [`\`mcp__${searchKey}__code\` is the one-stop code search (no extra model call). Its DEFAULT mode (or \`mode:"semantic"\`) ranks by MEANING via ColBERT over a per-workspace index, the first thing to reach for on intent/concept questions ("where is retry/backoff handled", "how does auth work"); when that index isn't ready it transparently falls back to lexical (the response \`source\` says which engine ran). Forced modes cover the rest: \`lexical\` (BM25F-ranked + tree-sitter, best for exact symbols), \`exact\`, \`regex\`, \`complete\` (exhaustive set), \`ast_pattern\`+\`ast_lang\` for multi-line AST shapes, \`scan\` for a whole-workspace symbol outline, \`multiline\` for cross-line regex. Multiple queries can run in a single turn. The index covers code-shaped files; for unstructured files (logs, \`.csv\`, \`.env*\`, config-only wiring), \`grep\`/\`glob\` still apply.`];
25823
- if (opts.workerToolsAvailable) para2Parts.push(`\`mcp__${workersKey}__explore\` runs a Gemini-backed read-only worker that returns a summary, using its own context rather than yours; concurrent launches share the \`MAX_INFLIGHT_TOOLS_CALL\` cap (default 128) with operator traffic.`, `\`mcp__${workersKey}__review\` is the same worker framed as a code reviewer that reads the code itself to verify a change or claim, reporting findings with severity, so it checks context the \`peers\` critics (stateless calls on the pasted artifact) cannot.`, `\`mcp__${workersKey}__plan\` is the same read-only worker framed as a planner: from a task + acceptance criteria it returns an ordered implementation plan.`, `\`mcp__${workersKey}__implement\` is the same worker with edit/write/bash; \`worktree: true\` runs it in an isolated git worktree and returns the diff.`, `\`mcp__${workersKey}__test\` is a write-capable worker framed as an independent test author: it authors tests that try to break the implementation and reports pass/fail, never editing the implementation to make them pass.`, "Workers themselves have `code_search` in their toolset.");
26134
+ if (opts.workerToolsAvailable) para2Parts.push(`\`worker-*\` are background Agent subagents (subagent_type) that run the matching worker in its own context and deliver the result as a completion notification, so a long run never blocks the turn: \`worker-explore\` (read-only research), \`worker-review\` (reads the code to verify a change or claim), \`worker-plan\` (ordered implementation plan), \`worker-implement\` (edit/write/bash; \`worktree: true\` isolates in a git worktree and returns the diff), \`worker-test\` (independent test author). The raw \`mcp__${workersKey}__*\` tools they call are guarded (a direct main-thread call is redirected to the matching agent); Workers themselves have \`code_search\`.`);
25824
26135
  if (opts.workerToolsAvailable) para2Parts.push(`\`mcp__${orchestrateKey}__decompose\` composes an open-ended ask into a typed, VERIFIED workflow IR (a strong driver decorrelated by a cross-lab critic, so the decompose step isn't a single point of failure), and \`mcp__${orchestrateKey}__run_workflow\` executes that IR through a frozen kernel delivering max(orchestrated, baseline) over a sealed executable gate, so it never ships worse than a plain single-model run. \`mcp__${orchestrateKey}__verify_workflow\` checks an IR's floor invariants before you run it, and \`mcp__${orchestrateKey}__attest_step\` audits that a finished run's producers were each checked by a different lab. They suit non-trivial, role-separated asks; a trivial ask does not need them.`);
25825
26136
  else para2Parts.push(`\`mcp__${orchestrateKey}__verify_workflow\` statically checks a workflow IR's floor invariants and \`mcp__${orchestrateKey}__attest_step\` audits a run's cross-lab lineage (the \`decompose\`/\`run_workflow\` composer + kernel need the worker backend, unavailable here).`);
25826
26137
  if (opts.workerToolsAvailable) {
@@ -26058,7 +26369,7 @@ const NON_PERSONA_MCP_TOOLS = Object.freeze([
26058
26369
  toolNameHttp: "explore",
26059
26370
  group: "workers",
26060
26371
  capability: "worker",
26061
- description: "Read-only investigation by an autonomous worker (Pi runtime; default model `gpt-5.4-mini` at xhigh reasoning, override via the `model` arg with any Copilot-catalog model that advertises `tool_calls`). Tools: read, glob, grep, code_search (semantic-first), web_search, fetch_url, advisor (consult a stronger cross-lab model), update_plan (planning checklist), and toolbelt (run a read-only analysis CLI: rg/fd/jq/yq/sg/gron/tokei/difft/git). The worker's system prompt sandboxes it and gives one-line descriptions of each tool, so brief it on the investigation, not on tool semantics. Offloads bounded research that would otherwise eat your context window — the worker plans its own tool calls and returns a single text answer. Examples: \"find files matching X then summarize\", \"how does library Y handle Z\", \"survey this codebase for usages of deprecated API\".",
26372
+ description: "Runs as the background `worker-explore` agent. Dispatch via the Agent tool (subagent_type: worker-explore) so your turn is never blocked; the result arrives as a completion notification. Read-only investigation by an autonomous worker (Pi runtime; default model `gpt-5.4-mini` at xhigh reasoning, override via the `model` arg with any Copilot-catalog model that advertises `tool_calls`). Tools: read, glob, grep, code_search (semantic-first), web_search, fetch_url, advisor (consult a stronger cross-lab model), update_plan (planning checklist), and toolbelt (run a read-only analysis CLI: rg/fd/jq/yq/sg/gron/tokei/difft/git). The worker's system prompt sandboxes it and gives one-line descriptions of each tool, so brief it on the investigation, not on tool semantics. Offloads bounded research that would otherwise eat your context window — the worker plans its own tool calls and returns a single text answer. Examples: \"find files matching X then summarize\", \"how does library Y handle Z\", \"survey this codebase for usages of deprecated API\".",
26062
26373
  inputSchema: {
26063
26374
  type: "object",
26064
26375
  required: ["prompt"],
@@ -26102,7 +26413,7 @@ const NON_PERSONA_MCP_TOOLS = Object.freeze([
26102
26413
  toolNameHttp: "implement",
26103
26414
  group: "workers",
26104
26415
  capability: "worker",
26105
- description: "Delegates a scoped coding task to an autonomous worker (Pi runtime; default model `gpt-5.5` at xhigh reasoning, override via the `model` arg with any Copilot-catalog model that advertises `tool_calls`). Tools: the explore read-only set (read, glob, grep, code_search, web_search, fetch_url, advisor, update_plan, toolbelt) plus edit, write, bash, and codex_review (code review by codex-reviewer / gpt-5.3-codex). The worker's system prompt sandboxes it and gives one-line descriptions of each tool, so brief it on the task, not on tool semantics. With `worktree: false` (default) edits in place — concurrent worker_implement calls and Claude's own edits to the same files will race. With `worktree: true` runs in an isolated git worktree and returns the diff for review. HARD ERROR if true and the workspace is not a git repository.",
26416
+ description: "Runs as the background `worker-implement` agent. Dispatch via the Agent tool (subagent_type: worker-implement) so your turn is never blocked; the result arrives as a completion notification. Delegates a scoped coding task to an autonomous worker (Pi runtime; default model `gpt-5.5` at xhigh reasoning, override via the `model` arg with any Copilot-catalog model that advertises `tool_calls`). Tools: the explore read-only set (read, glob, grep, code_search, web_search, fetch_url, advisor, update_plan, toolbelt) plus edit, write, bash, and codex_review (code review by codex-reviewer / gpt-5.3-codex). The worker's system prompt sandboxes it and gives one-line descriptions of each tool, so brief it on the task, not on tool semantics. With `worktree: false` (default) edits in place — concurrent worker_implement calls and Claude's own edits to the same files will race. With `worktree: true` runs in an isolated git worktree and returns the diff for review. HARD ERROR if true and the workspace is not a git repository.",
26106
26417
  inputSchema: {
26107
26418
  type: "object",
26108
26419
  required: ["prompt"],
@@ -26150,7 +26461,7 @@ const NON_PERSONA_MCP_TOOLS = Object.freeze([
26150
26461
  toolNameHttp: "review",
26151
26462
  group: "workers",
26152
26463
  capability: "worker",
26153
- description: "Read-only code review by an autonomous worker (Pi runtime; default model `gpt-5.5` at xhigh reasoning, override via `model` with any Copilot-catalog model that advertises `tool_calls`). Same read-only toolset as `explore` (read, glob, grep, code_search, web_search, fetch_url, advisor, update_plan, toolbelt) — it CANNOT edit — but the worker is framed as a reviewer: it verifies correctness against the actual code itself rather than trusting a claim, and reports findings (bugs, edge cases, security / concurrency / resource risks, missing handling) with a severity and `file:line`. Brief it with the change / diff / claim to verify (paste it, or name the files) — it reads the code to confirm, so you get a self-verifying second opinion that doesn't depend on you having pre-extracted the relevant code. Unlike the `peers` critics (single stateless model calls on the artifact you paste), this worker can navigate the repo to check surrounding context for itself.",
26464
+ description: "Runs as the background `worker-review` agent. Dispatch via the Agent tool (subagent_type: worker-review) so your turn is never blocked; the result arrives as a completion notification. Read-only code review by an autonomous worker (Pi runtime; default model `gpt-5.5` at xhigh reasoning, override via `model` with any Copilot-catalog model that advertises `tool_calls`). Same read-only toolset as `explore` (read, glob, grep, code_search, web_search, fetch_url, advisor, update_plan, toolbelt) — it CANNOT edit — but the worker is framed as a reviewer: it verifies correctness against the actual code itself rather than trusting a claim, and reports findings (bugs, edge cases, security / concurrency / resource risks, missing handling) with a severity and `file:line`. Brief it with the change / diff / claim to verify (paste it, or name the files) — it reads the code to confirm, so you get a self-verifying second opinion that doesn't depend on you having pre-extracted the relevant code. Unlike the `peers` critics (single stateless model calls on the artifact you paste), this worker can navigate the repo to check surrounding context for itself.",
26154
26465
  inputSchema: {
26155
26466
  type: "object",
26156
26467
  required: ["prompt"],
@@ -26194,7 +26505,7 @@ const NON_PERSONA_MCP_TOOLS = Object.freeze([
26194
26505
  toolNameHttp: "plan",
26195
26506
  group: "workers",
26196
26507
  capability: "worker",
26197
- description: "Read-only implementation planning by an autonomous worker (Pi runtime; default model `claude-opus-4.8`, override via `model` with any Copilot-catalog model that advertises `tool_calls`). Same read-only toolset as `explore` (read, glob, grep, code_search, web_search, fetch_url, advisor, update_plan, toolbelt) — it CANNOT edit — but the worker is framed as a planner: from the task and acceptance criteria it produces a concrete, ordered implementation plan (the files to change, the approach, the key risks, and how each acceptance criterion will be verified), grounded by reading the actual code. Brief it with the task and any acceptance criteria; it returns a single plan, not code.",
26508
+ description: "Runs as the background `worker-plan` agent. Dispatch via the Agent tool (subagent_type: worker-plan) so your turn is never blocked; the result arrives as a completion notification. Read-only implementation planning by an autonomous worker (Pi runtime; default model `claude-opus-4.8`, override via `model` with any Copilot-catalog model that advertises `tool_calls`). Same read-only toolset as `explore` (read, glob, grep, code_search, web_search, fetch_url, advisor, update_plan, toolbelt) — it CANNOT edit — but the worker is framed as a planner: from the task and acceptance criteria it produces a concrete, ordered implementation plan (the files to change, the approach, the key risks, and how each acceptance criterion will be verified), grounded by reading the actual code. Brief it with the task and any acceptance criteria; it returns a single plan, not code.",
26198
26509
  inputSchema: {
26199
26510
  type: "object",
26200
26511
  required: ["prompt"],
@@ -26238,7 +26549,7 @@ const NON_PERSONA_MCP_TOOLS = Object.freeze([
26238
26549
  toolNameHttp: "test",
26239
26550
  group: "workers",
26240
26551
  capability: "worker",
26241
- description: "Independent adversarial test authoring by an autonomous worker (Pi runtime; default model `gpt-5.5` at xhigh reasoning, override via `model` with any Copilot-catalog model that advertises `tool_calls`). Same read+write toolset as `implement` (the explore set plus edit, write, bash, codex_review). The worker is framed as an INDEPENDENT test author that did NOT write the code under test: from the task and acceptance criteria it writes tests that try to BREAK the implementation (edge cases, error paths, the acceptance criteria as executable checks), runs them, and reports which pass and fail — it does NOT modify the implementation to make tests pass. With `worktree: true` runs in an isolated git worktree and returns the diff; HARD ERROR if true and the workspace is not a git repository.",
26552
+ description: "Runs as the background `worker-test` agent. Dispatch via the Agent tool (subagent_type: worker-test) so your turn is never blocked; the result arrives as a completion notification. Independent adversarial test authoring by an autonomous worker (Pi runtime; default model `gpt-5.5` at xhigh reasoning, override via `model` with any Copilot-catalog model that advertises `tool_calls`). Same read+write toolset as `implement` (the explore set plus edit, write, bash, codex_review). The worker is framed as an INDEPENDENT test author that did NOT write the code under test: from the task and acceptance criteria it writes tests that try to BREAK the implementation (edge cases, error paths, the acceptance criteria as executable checks), runs them, and reports which pass and fail — it does NOT modify the implementation to make tests pass. With `worktree: true` runs in an isolated git worktree and returns the diff; HARD ERROR if true and the workspace is not a git repository.",
26242
26553
  inputSchema: {
26243
26554
  type: "object",
26244
26555
  required: ["prompt"],
@@ -26485,7 +26796,7 @@ const NON_PERSONA_MCP_TOOLS = Object.freeze([
26485
26796
  toolNameHttp: "browse",
26486
26797
  group: "workers",
26487
26798
  capability: "browse_agent",
26488
- description: "A Pi-driven autonomous browser agent (gpt-5.4-mini) that drives a real browser to accomplish `task` and returns the result. Runs in its own context to preserve the lead's window (raw DOM / page snapshots stay inside the agent). Pass `sessionId` to continue a prior session (its id is returned appended to the result as `[browse session: <id>]`); omit it for a fresh isolated session. Multiple concurrent calls run as parallel sessions on the one shared browser. Examples: \"find the cheapest flight LHR-JFK next Tuesday\", \"log into the dashboard and read the current MRR\", \"summarize the top 3 HN front-page stories\".",
26799
+ description: "Runs as the background `worker-browse` agent. Dispatch via the Agent tool (subagent_type: worker-browse) so your turn is never blocked; the result arrives as a completion notification. A Pi-driven autonomous browser agent (gpt-5.4-mini) that drives a real browser to accomplish `task` and returns the result. Runs in its own context to preserve the lead's window (raw DOM / page snapshots stay inside the agent). Pass `sessionId` to continue a prior session (its id is returned appended to the result as `[browse session: <id>]`); omit it for a fresh isolated session. Multiple concurrent calls run as parallel sessions on the one shared browser. Examples: \"find the cheapest flight LHR-JFK next Tuesday\", \"log into the dashboard and read the current MRR\", \"summarize the top 3 HN front-page stories\".",
26489
26800
  inputSchema: {
26490
26801
  type: "object",
26491
26802
  required: ["task"],
@@ -26889,5 +27200,5 @@ async function runStandInToolCall(args, signal) {
26889
27200
  }
26890
27201
 
26891
27202
  //#endregion
26892
- export { logStreamError as $, copilotBaseUrl as $t, BROWSE_DEFAULT_MODEL as A, UPSTREAM_FETCH_TIMEOUT_MS as At, toolbeltEnabled as B, cacheCopilotVersion as Bt, repoFingerprint as C, ArtifactClient as Ct, trustRepo as D, DEFAULT_CODEX_MODEL as Dt, stopReviewStateDir as E, DEFAULT_CLAUDE_MODEL_FALLBACKS as Et, appendPlanReminder as F, withInstallLock as Ft, searchWeb as G, resolveCodexModel as Gt, vscodeRipgrepPath as H, cacheVSCodeVersion as Ht, runWorkerAgent as I, setupCopilotToken as It, buildAdvisorStream as J, getModels as Jt, ADVISOR_INTERNAL_TOOL_NAME as K, resolveModel as Kt, withNoOutputRetry as L, setupGitHubAgentToken as Lt, IMPLEMENT_DEFAULT_MODEL as M, generateRandomPort as Mt, PLAN_DEFAULT_MODEL as N, pickClaudeDefault as Nt, resolveSealedGate as O, DEFAULT_CODEX_MODEL_FALLBACKS as Ot, REVIEW_DEFAULT_MODEL as P, getPackageVersion as Pt, isControllerClosedError as Q, GITHUB_API_BASE_URL as Qt, availableToolCommands as R, setupGitHubToken as Rt, isSubagentContext as S, shouldUseInsecureTls as St, stopGateEnabledForRepo as T, toolbeltPathOverride as Tt, TOOLBELT_TOOLS$1 as U, filterBetaHeader as Ut, toolbeltSkipSet as V, cacheModels as Vt, assetFor as W, isNullish as Wt, isAdvisorRequested as X, HTTPError as Xt, injectAdvisorTool as Y, fetchWithTransientRetry as Yt, buildOpenAIErrorEvent as Z, forwardError as Zt, stopReviewEnabled as _, provisionBrowserAssets as _t, buildPeerAwarenessSnippet as a, browserToolsEnabled as at, fileLastPromptStore as b, extractTarGzMember as bt, buildSessionBindHookCommand as c, workerToolsEnabled as ct, decideStopHook as d, getTokenCount as dt, copilotHeaders as en, readIteratorWithTimeout as et, fileBlockBudget as f, createResponses as ft, stopGateId as g, parseJsonOrDiagnose as gt, stopGateDisabled as h, readResponseBodyCapped as ht, buildAgentPrompt as i, agentToolsEnabled as it, DEFAULT_MODEL as j, UPSTREAM_INACTIVITY_TIMEOUT_MS as jt, liveExec as k, DEFAULT_PORT as kt, buildStopHookCommand as l, countTokens as lt, launchBaselineKey as m, MAX_RESPONSE_BODY_BYTES as mt, MCP_GROUPS as n, state as nn, handleMcpDelete as nt, personasFor as o, fleetToolsEnabled as ot, injectStopHookIntoSettingsFile as p, createChatCompletions as pt, ADVISOR_TOOL_INSTRUCTIONS as q, sleep as qt, assertMcpToolSurfaceConsistent as r, handleMcpPost as rt, buildArtifactOpenHookCommand as s, standInToolEnabled as st, GROUP_META as t, githubHeaders as tn, relayAnthropicStream as tt, captureLaunchBaseline as u, createMessages as ut, fileBaselineStore as v, hasSupportedBrowserInstalled as vt, repoRoot as w, collapsePathKeys as wt, fileReviewDebounce as x, extractZipMember as xt, fileFindingsStore as y, provisionAndIndexColbert as yt, buildToolbeltAwareness as z, tryRefreshAndRetry as zt };
26893
- //# sourceMappingURL=peer-mcp-personas-Dm3UCpXz.js.map
27203
+ export { logStreamError as $, GITHUB_API_BASE_URL as $t, BROWSE_DEFAULT_MODEL as A, DEFAULT_PORT as At, toolbeltEnabled as B, tryRefreshAndRetry as Bt, repoFingerprint as C, shouldUseInsecureTls as Ct, trustRepo as D, DEFAULT_CLAUDE_MODEL_FALLBACKS as Dt, stopReviewStateDir as E, toolbeltPathOverride as Et, appendPlanReminder as F, getPackageVersion as Ft, searchWeb as G, isNullish as Gt, vscodeRipgrepPath as H, cacheModels as Ht, runWorkerAgent as I, withInstallLock as It, buildAdvisorStream as J, sleep as Jt, ADVISOR_INTERNAL_TOOL_NAME as K, resolveCodexModel as Kt, withNoOutputRetry as L, setupCopilotToken as Lt, IMPLEMENT_DEFAULT_MODEL as M, UPSTREAM_INACTIVITY_TIMEOUT_MS as Mt, PLAN_DEFAULT_MODEL as N, generateRandomPort as Nt, resolveSealedGate as O, DEFAULT_CODEX_MODEL as Ot, REVIEW_DEFAULT_MODEL as P, pickClaudeDefault as Pt, isControllerClosedError as Q, forwardError as Qt, availableToolCommands as R, setupGitHubAgentToken as Rt, isSubagentContext as S, extractZipMember as St, stopGateEnabledForRepo as T, collapsePathKeys as Tt, TOOLBELT_TOOLS$1 as U, cacheVSCodeVersion as Ut, toolbeltSkipSet as V, cacheCopilotVersion as Vt, assetFor as W, filterBetaHeader as Wt, isAdvisorRequested as X, fetchWithTransientRetry as Xt, injectAdvisorTool as Y, getModels as Yt, buildOpenAIErrorEvent as Z, HTTPError as Zt, stopReviewEnabled as _, parseJsonOrDiagnose as _t, buildPeerAwarenessSnippet as a, browseAgentEnabled as at, fileLastPromptStore as b, provisionAndIndexColbert as bt, buildSessionBindHookCommand as c, standInToolEnabled as ct, decideStopHook as d, createMessages as dt, copilotBaseUrl as en, readIteratorWithTimeout as et, fileBlockBudget as f, getTokenCount as ft, stopGateId as g, readResponseBodyCapped as gt, stopGateDisabled as h, MAX_RESPONSE_BODY_BYTES as ht, buildAgentPrompt as i, agentToolsEnabled as it, DEFAULT_MODEL as j, UPSTREAM_FETCH_TIMEOUT_MS as jt, liveExec as k, DEFAULT_CODEX_MODEL_FALLBACKS as kt, buildStopHookCommand as l, workerToolsEnabled as lt, launchBaselineKey as m, createChatCompletions as mt, MCP_GROUPS as n, githubHeaders as nn, handleMcpDelete as nt, personasFor as o, browserToolsEnabled as ot, injectStopHookIntoSettingsFile as p, createResponses as pt, ADVISOR_TOOL_INSTRUCTIONS as q, resolveModel as qt, assertMcpToolSurfaceConsistent as r, state as rn, handleMcpPost as rt, buildArtifactOpenHookCommand as s, fleetToolsEnabled as st, GROUP_META as t, copilotHeaders as tn, relayAnthropicStream as tt, captureLaunchBaseline as u, countTokens as ut, fileBaselineStore as v, provisionBrowserAssets as vt, repoRoot as w, ArtifactClient as wt, fileReviewDebounce as x, extractTarGzMember as xt, fileFindingsStore as y, hasSupportedBrowserInstalled as yt, buildToolbeltAwareness as z, setupGitHubToken as zt };
27204
+ //# sourceMappingURL=peer-mcp-personas-DMM1akDa.js.map