@agentproto/runtime 5.14.0 → 5.15.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.mjs CHANGED
@@ -8940,7 +8940,7 @@ function boundaryMeta(b) {
8940
8940
  return { [APP_BOUNDARY_META_KEY]: encodeAppBoundary(b) };
8941
8941
  }
8942
8942
  function inAny(canon, zones) {
8943
- return zones.some((z61) => isPathWithin(canon, canonicalizePath(z61)));
8943
+ return zones.some((z62) => isPathWithin(canon, canonicalizePath(z62)));
8944
8944
  }
8945
8945
  function resolveBoundaryPath(b, input, mode) {
8946
8946
  if (typeof input !== "string" || input.length === 0) {
@@ -26328,6 +26328,163 @@ async function processTreeRss(rootPids, exec = defaultPsExecutor) {
26328
26328
  }
26329
26329
  return result;
26330
26330
  }
26331
+ var SessionListFilterError = class extends Error {
26332
+ constructor(message) {
26333
+ super(message);
26334
+ this.name = "SessionListFilterError";
26335
+ }
26336
+ };
26337
+ var SESSION_LIST_FILTER_KEYS = [
26338
+ "q",
26339
+ "excludeLabelPrefix",
26340
+ "excludeLabels",
26341
+ "excludeKinds",
26342
+ "rootOnly",
26343
+ "parentSessionId",
26344
+ "updatedSince",
26345
+ "startedSince",
26346
+ "excludeNoise"
26347
+ ];
26348
+ function pickSessionListFilters(input) {
26349
+ const out = {};
26350
+ for (const key of SESSION_LIST_FILTER_KEYS) {
26351
+ if (input[key] !== void 0) out[key] = input[key];
26352
+ }
26353
+ return out;
26354
+ }
26355
+ var TIME_UNIT_MS = {
26356
+ s: 1e3,
26357
+ m: 6e4,
26358
+ h: 36e5,
26359
+ d: 864e5,
26360
+ w: 6048e5
26361
+ };
26362
+ var RELATIVE_RE = /^(\d+(?:\.\d+)?)\s*([smhdw])$/i;
26363
+ function parseTimeBound(raw, field, now = Date.now()) {
26364
+ const text13 = raw.trim();
26365
+ const rel = RELATIVE_RE.exec(text13);
26366
+ if (rel) {
26367
+ const n = Number(rel[1]);
26368
+ const unit = TIME_UNIT_MS[rel[2].toLowerCase()];
26369
+ return now - n * unit;
26370
+ }
26371
+ const abs = text13 === "" ? Number.NaN : Date.parse(text13);
26372
+ if (Number.isNaN(abs)) {
26373
+ throw new SessionListFilterError(
26374
+ `${field} must be an ISO-8601 time or a relative age like "30m", "24h", "7d", "2w"; got ${JSON.stringify(raw)}.`
26375
+ );
26376
+ }
26377
+ return abs;
26378
+ }
26379
+ function toList(v) {
26380
+ if (v === void 0) return [];
26381
+ const parts = typeof v === "string" ? [v] : [...v];
26382
+ return parts.flatMap((p) => p.split(",")).map((s) => s.trim()).filter((s) => s.length > 0);
26383
+ }
26384
+ var REVIEW_LABEL_PREFIX = "review:";
26385
+ var WORKFLOW_LABEL_PREFIX = "wf:";
26386
+ var NOISE_ORIGINS = /* @__PURE__ */ new Set(["review", "workflow"]);
26387
+ function isNoiseSession(s) {
26388
+ const label = s.label ?? "";
26389
+ if (label.startsWith(REVIEW_LABEL_PREFIX) || label.startsWith(WORKFLOW_LABEL_PREFIX)) return true;
26390
+ if (s.origin !== void 0 && NOISE_ORIGINS.has(s.origin)) return true;
26391
+ const ended = s.status === "exited" || s.status === "killed";
26392
+ if (ended && (s.kind === "command" || s.kind === "terminal" && !s.adapterSlug)) return true;
26393
+ return false;
26394
+ }
26395
+ function sessionActivityMs(s) {
26396
+ const ms = Date.parse(s.lastActivityAt ?? s.startedAt);
26397
+ return Number.isNaN(ms) ? 0 : ms;
26398
+ }
26399
+ function sortNewestActivityFirst(rows) {
26400
+ return [...rows].sort((a, b) => sessionActivityMs(b) - sessionActivityMs(a) || a.id.localeCompare(b.id));
26401
+ }
26402
+ function hasSessionListFilters(input) {
26403
+ return input.q !== void 0 && input.q.trim() !== "" || toList(input.excludeLabelPrefix).length > 0 || toList(input.excludeLabels).length > 0 || toList(input.excludeKinds).length > 0 || input.rootOnly === true || input.parentSessionId !== void 0 && input.parentSessionId !== "" || input.updatedSince !== void 0 && input.updatedSince.trim() !== "" || input.startedSince !== void 0 && input.startedSince.trim() !== "" || input.excludeNoise === true;
26404
+ }
26405
+ function compileSessionListFilters(input, now = Date.now()) {
26406
+ const q = input.q?.trim().toLowerCase() ?? "";
26407
+ const prefixes = toList(input.excludeLabelPrefix);
26408
+ const labels = new Set(toList(input.excludeLabels));
26409
+ const kinds = new Set(toList(input.excludeKinds));
26410
+ const parentId = input.parentSessionId && input.parentSessionId !== "" ? input.parentSessionId : void 0;
26411
+ const updatedSince = input.updatedSince && input.updatedSince.trim() !== "" ? parseTimeBound(input.updatedSince, "updatedSince", now) : void 0;
26412
+ const startedSince = input.startedSince && input.startedSince.trim() !== "" ? parseTimeBound(input.startedSince, "startedSince", now) : void 0;
26413
+ return (s) => {
26414
+ if (q) {
26415
+ const hit = [s.id, s.name, s.label, s.title, s.cwd].some((f) => f !== void 0 && f.toLowerCase().includes(q));
26416
+ if (!hit) return false;
26417
+ }
26418
+ if (kinds.has(s.kind)) return false;
26419
+ const label = s.label;
26420
+ if (label !== void 0) {
26421
+ if (labels.has(label)) return false;
26422
+ if (prefixes.some((p) => label.startsWith(p))) return false;
26423
+ }
26424
+ if (input.rootOnly === true && s.parentSessionId) return false;
26425
+ if (parentId !== void 0 && s.parentSessionId !== parentId) return false;
26426
+ if (updatedSince !== void 0 && sessionActivityMs(s) < updatedSince) return false;
26427
+ if (startedSince !== void 0) {
26428
+ const started = Date.parse(s.startedAt);
26429
+ if (Number.isNaN(started) || started < startedSince) return false;
26430
+ }
26431
+ if (input.excludeNoise === true && isNoiseSession(s)) return false;
26432
+ return true;
26433
+ };
26434
+ }
26435
+ function applySessionListFilters(rows, input, now = Date.now()) {
26436
+ if (!hasSessionListFilters(input)) return [...rows];
26437
+ return rows.filter(compileSessionListFilters(input, now));
26438
+ }
26439
+ function parseSessionListFilterParams(params) {
26440
+ const flag = (k) => {
26441
+ const v = params.get(k);
26442
+ return v === null ? void 0 : v === "true" || v === "1";
26443
+ };
26444
+ const list = (k) => {
26445
+ const all = params.getAll(k);
26446
+ return all.length > 0 ? toList(all) : void 0;
26447
+ };
26448
+ const str3 = (k) => {
26449
+ const v = params.get(k);
26450
+ return v === null || v === "" ? void 0 : v;
26451
+ };
26452
+ const out = {};
26453
+ const q = str3("q");
26454
+ if (q !== void 0) out.q = q;
26455
+ const prefix = list("excludeLabelPrefix");
26456
+ if (prefix) out.excludeLabelPrefix = prefix;
26457
+ const labels = list("excludeLabels");
26458
+ if (labels) out.excludeLabels = labels;
26459
+ const kinds = list("excludeKinds");
26460
+ if (kinds) out.excludeKinds = kinds;
26461
+ const rootOnly = flag("rootOnly");
26462
+ if (rootOnly !== void 0) out.rootOnly = rootOnly;
26463
+ const parent = str3("parentSessionId");
26464
+ if (parent !== void 0) out.parentSessionId = parent;
26465
+ const updatedSince = str3("updatedSince");
26466
+ if (updatedSince !== void 0) out.updatedSince = updatedSince;
26467
+ const startedSince = str3("startedSince");
26468
+ if (startedSince !== void 0) out.startedSince = startedSince;
26469
+ const noise = flag("excludeNoise");
26470
+ if (noise !== void 0) out.excludeNoise = noise;
26471
+ return out;
26472
+ }
26473
+ var mcpBool2 = z.preprocess((v) => v === "true" ? true : v === "false" ? false : v, z.boolean());
26474
+ var stringOrList = z.union([z.string(), z.array(z.string())]);
26475
+ var sessionListFilterShape = {
26476
+ q: z.string().optional().describe("Case-insensitive substring over id, name, label, title, cwd."),
26477
+ excludeLabelPrefix: stringOrList.optional().describe("Drop labels starting with any of these, e.g. ['review:','wf:']."),
26478
+ excludeLabels: stringOrList.optional().describe("Drop labels exactly equal to any of these (as session_follow exclude.labels)."),
26479
+ excludeKinds: stringOrList.optional().describe("Drop kinds: terminal | agent-cli | command."),
26480
+ rootOnly: mcpBool2.optional().describe("Only sessions with no parent."),
26481
+ parentSessionId: z.string().optional().describe("Only direct children of this session (id or name)."),
26482
+ updatedSince: z.string().optional().describe("Activity at/after: ISO time or age like '30m','24h','7d'."),
26483
+ startedSince: z.string().optional().describe("Started at/after: ISO time or age like '30m','24h','7d'."),
26484
+ excludeNoise: mcpBool2.optional().describe(
26485
+ 'Drop review:*/wf:* sessions and ended command/plain-terminal runs. Details: tool_help {name:"session_list", topic:"excludeNoise"}'
26486
+ )
26487
+ };
26331
26488
 
26332
26489
  // src/session-tools.ts
26333
26490
  init_transcript_writer();
@@ -28332,7 +28489,7 @@ function buildSessionTree(sessions) {
28332
28489
  });
28333
28490
  return sessions.filter((s) => !s.parentSessionId || !idSet.has(s.parentSessionId)).sort((a, b) => a.startedAt.localeCompare(b.startedAt)).map(toNode);
28334
28491
  }
28335
- var mcpBool2 = z.preprocess(
28492
+ var mcpBool3 = z.preprocess(
28336
28493
  (v) => v === "true" ? true : v === "false" ? false : v,
28337
28494
  z.boolean()
28338
28495
  );
@@ -28568,28 +28725,21 @@ function registerSessionTools(rawServer, opts) {
28568
28725
  };
28569
28726
  registerAgentTools(server, opts);
28570
28727
  const sessionListSchema = z.object({
28571
- kind: z.enum(["terminal", "agent-cli", "command", "all"]).optional().describe(
28572
- "Filter by session kind. `all` (default) returns every live-able kind (terminal + agent-cli) but excludes `command` unless `includeCommands` is set. Use `terminal` to list only PTY sessions, `agent-cli` for structured ACP agents, or `command` to list only raw shell-command runs."
28573
- ),
28574
- includeCommands: z.boolean().optional().describe(
28575
- "When true and `kind` is unset/`all`, also include `kind:'command'` rows in the result (they're excluded by default \u2014 see `kind`). No effect when `kind` is set explicitly. Default false."
28576
- ),
28728
+ kind: z.enum(["terminal", "agent-cli", "command", "all"]).optional().describe("Filter by kind. `all` (default) = terminal + agent-cli, without `command` unless `includeCommands`."),
28729
+ includeCommands: z.boolean().optional().describe("With kind unset/`all`, also include `kind:'command'` rows. Default false."),
28577
28730
  onlyAlive: z.boolean().optional().describe("When true, only running/starting sessions. Default false."),
28578
28731
  status: z.enum(["starting", "running", "exited", "killed", "error"]).optional().describe("Filter by exact status (overrides onlyAlive)."),
28579
- includeArchived: z.boolean().optional().describe(
28580
- "When true, also include archived sessions (hidden from every other view by `session_archive`). Default false."
28581
- ),
28582
- withMemory: z.boolean().optional().describe(
28583
- "When true, add `rssBytes` (summed RSS in bytes of the process tree, via `ps`) to every live session that has a pid. Default false \u2014 a distinct opt-in from `full`/`compact` since it costs one `ps` spawn per call; omitted otherwise, so a plain listing never pays for it."
28584
- ),
28732
+ includeArchived: z.boolean().optional().describe("Also include archived sessions. Default false."),
28733
+ withMemory: z.boolean().optional().describe("Add `rssBytes` (process-tree RSS) to live sessions with a pid; one `ps` per call. Default false."),
28585
28734
  stats: statsParamSchema.describe(
28586
- 'Resource stats per live session - process-tree RSS, %CPU, process count and the top commands by RSS (normalized: `pnpm install`, `vitest`, `tsc`, `git`, \u2026), under each row\'s `stats`. `true` = summary; `"full"` = also every process (pid, ppid, command, RSS, CPU, elapsed). Sampled on demand and cached ~3s; rows with no live process carry no `stats`. Use `session_stats` for the host-level view (daemon / provisioning / orphan buckets, load, free memory).'
28735
+ 'Per-live-session RSS, %CPU, process count and top commands under `stats`; `true` = summary, `"full"` = every process. Cached ~3s. Host-level view: `session_stats`.'
28587
28736
  ),
28737
+ ...sessionListFilterShape,
28588
28738
  ...pageParamsShape
28589
28739
  });
28590
28740
  registerBuiltinTool(server, {
28591
28741
  id: "session_list",
28592
- description: "List sessions tracked by the daemon \u2014 agent-CLI sessions (claude-code, hermes, \u2026) and terminal/PTY sessions (claude TUI, bash, \u2026). Each entry includes `kind`, `pty` (true for real PTYs), `name` (when set at spawn), `status`, `command`, age + exit code. Use this when you need to know what's already running before spawning anything new, or to discover a session id by name. COMPACT BY DEFAULT: each entry is a slim projection (id/kind/name/label/status/command/cwd/model/busy/awaitingInput/blockedOn/lastActivityAt/depth/parentSessionId/continuedFrom/lastTurnErroredAt/interrupted); `interrupted: true` marks a session a daemon restart cut off mid-turn (see `session_continue_interrupted`); pass `full: true` (or `compact: false`) for the complete, unprojected per-session record. Raw shell-command runs (`kind:'command'`) are a log, not a resumable session, so they're excluded from the default view \u2014 pass `kind:'command'` or `includeCommands:true` to see them, or use `command_list`.",
28742
+ description: "List sessions tracked by the daemon (agent-CLI and terminal/PTY). Use it to see what's already running before spawning, or to find a session id by name. NARROW BEFORE YOU READ: hundreds of sessions are mostly noise and without `limit` all come back. Filter (`q`, `excludeNoise`, `rootOnly`, `updatedSince`, \u2026) and/or pass `limit`; rows are newest-activity first, `total` is the filtered count. E.g. `{q:'X', excludeNoise:true, limit:10}`. Rows are COMPACT by default (`fields:[\u2026]` picks keys, `full:true` returns everything). Detail: tool_help {name:\"session_list\"}; ranked text search: `session_search`.",
28593
28743
  inputSchema: sessionListSchema,
28594
28744
  handler: async (input) => {
28595
28745
  let rows = registry.list({ includeArchived: true });
@@ -28612,6 +28762,12 @@ function registerSessionTools(rawServer, opts) {
28612
28762
  (s) => s.status === "running" || s.status === "starting"
28613
28763
  );
28614
28764
  }
28765
+ const { parentSessionId, ...filterRest } = pickSessionListFilters(input);
28766
+ rows = applySessionListFilters(rows, {
28767
+ ...filterRest,
28768
+ ...parentSessionId ? { parentSessionId: registry.findByIdOrName(parentSessionId)?.id ?? parentSessionId } : {}
28769
+ });
28770
+ rows = sortNewestActivityFirst(rows);
28615
28771
  if (input.withMemory) {
28616
28772
  const live = rows.filter(
28617
28773
  (s) => typeof s.pid === "number" && (s.status === "running" || s.status === "starting")
@@ -28636,11 +28792,13 @@ function registerSessionTools(rawServer, opts) {
28636
28792
  return rows.map(publicSessionDescriptor);
28637
28793
  },
28638
28794
  transformers: [
28795
+ catchErrors(),
28639
28796
  paginated({
28640
28797
  project: compactSessionItem,
28641
28798
  keyOf: (s) => s.id,
28642
28799
  maxLimit: 200,
28643
- itemKey: "sessions"
28800
+ itemKey: "sessions",
28801
+ includeTotal: true
28644
28802
  })
28645
28803
  ]
28646
28804
  });
@@ -28710,7 +28868,7 @@ function registerSessionTools(rawServer, opts) {
28710
28868
  description: 'Resource usage per session, sampled from the OS process table: RSS bytes, %CPU, process count and top commands by RSS for every live session, sorted by RSS (each row labelled with the session\'s `label`/`name`), plus `daemon` (the daemon process + its own children), `provisioning` (worktree setup work such as `pnpm install` not yet attached to a session, with `inFlight` provisions), `orphans` (processes that look agentproto-owned but belong to no live session - reported only, never killed), `totals`, and `host` (load average, free/total memory). `detail:"full"` adds every process (pid, command, RSS, CPU, elapsed) per row. Cached ~3s; `fresh:true` forces a new sample. A subtree-scoped caller sees only its own sessions (no daemon/provisioning/orphan buckets).',
28711
28869
  inputSchema: z.object({
28712
28870
  detail: z.enum(["summary", "full"]).optional().describe('Default "summary".'),
28713
- fresh: mcpBool2.optional().describe("Bypass the ~3s cache and sample now.")
28871
+ fresh: mcpBool3.optional().describe("Bypass the ~3s cache and sample now.")
28714
28872
  }),
28715
28873
  handler: async (input) => {
28716
28874
  const all = registry.list({ includeArchived: true });
@@ -28730,7 +28888,7 @@ function registerSessionTools(rawServer, opts) {
28730
28888
  description: 'Host-level load report: load average vs core count, CPU user/sys/idle, RAM (used/wired/compressor/free) and swap, per-disk transfers/s + MB/s, the top 10 processes by CPU and by memory footprint (compressed pages included on macOS) each tagged with its owning session (`session`/`daemon`/`provisioning`/`orphan`/`system`/`other`), and `warnings` (swap > 50%, orphaned processes older than 30 min that are busy or serving, deleted-cwd processes, filesystem-wide `find`/`bfs`/`du` scans, several servers on one port, load > 4x cores). `detail:"full"` adds a per-session rollup and every process. Bounded to ~2s: a probe that is slow or unavailable is named in `partial` and the rest still ships (raise `budgetMs` to give the macOS `top` footprint probe longer on a saturated host). Cached ~2s; `fresh:true` resamples. Never needs sudo. A subtree-scoped caller sees host metrics plus only its own sessions\' processes.',
28731
28889
  inputSchema: z.object({
28732
28890
  detail: z.enum(["summary", "full"]).optional().describe('Default "summary".'),
28733
- fresh: mcpBool2.optional().describe("Bypass the ~2s cache and sample now."),
28891
+ fresh: mcpBool3.optional().describe("Bypass the ~2s cache and sample now."),
28734
28892
  budgetMs: z.coerce.number().int().min(300).max(6e4).optional().describe("Time budget for the sample in ms (default 1900).")
28735
28893
  }),
28736
28894
  handler: async (input) => {
@@ -28749,7 +28907,7 @@ function registerSessionTools(rawServer, opts) {
28749
28907
  "session_continue_interrupted",
28750
28908
  "List the sessions the LAST daemon restart cut off mid-turn (`interrupted: true`) and \u2014 with `dryRun: false` \u2014 send each a one-shot \"continue\" prompt (the interrupted prompt itself is never re-run). Goes through the normal prompt path, so a dead-but-resumable session resumes in place first. Skips sessions that aren't interrupted, were interrupted by an older restart, aren't resumable, hit the resume attempt cap, are already busy, or whose cwd no longer exists. Returns a per-session outcome (`eligible` on a dry run, else `sent`/`skipped` with a reason/`failed`).",
28751
28909
  {
28752
- dryRun: mcpBool2.optional().describe("Default true: only report what would be sent. Pass false to send."),
28910
+ dryRun: mcpBool3.optional().describe("Default true: only report what would be sent. Pass false to send."),
28753
28911
  ids: z.array(z.string().min(1)).optional().describe(
28754
28912
  "Restrict to these sessions (id or name). Omitted \u21D2 every session interrupted by the last restart."
28755
28913
  ),
@@ -30067,7 +30225,7 @@ function registerSessionTools(rawServer, opts) {
30067
30225
  workspaceSlug: z.string().optional().describe(
30068
30226
  "Workspace slug from `agentproto workspace list`. Resolves the repo root via the active workspace when omitted."
30069
30227
  ),
30070
- openOnly: mcpBool2.optional().describe(
30228
+ openOnly: mcpBool3.optional().describe(
30071
30229
  "When true, only return worktrees whose `pr.state` is `open`. Default false."
30072
30230
  ),
30073
30231
  sessionId: z.string().optional().describe(
@@ -30118,19 +30276,19 @@ function registerSessionTools(rawServer, opts) {
30118
30276
  workspaceSlug: z.string().optional().describe(
30119
30277
  "Workspace slug from `agentproto workspace list`. Resolves the repo root via the active workspace when omitted."
30120
30278
  ),
30121
- apply: mcpBool2.optional().describe(
30279
+ apply: mcpBool3.optional().describe(
30122
30280
  "When true, EXECUTE the plan (reclaim/salvage). Default false \u2014 a dry run that returns the plan and mutates nothing."
30123
30281
  ),
30124
- salvageDirty: mcpBool2.optional().describe(
30282
+ salvageDirty: mcpBool3.optional().describe(
30125
30283
  "When true, archive (snapshot-then-remove) every `salvage`-class worktree during `apply`. Default false \u2014 salvage entries are left untouched. Ignored on a dry run."
30126
30284
  ),
30127
- includeDetached: mcpBool2.optional().describe(
30285
+ includeDetached: mcpBool3.optional().describe(
30128
30286
  "When true, a clean, idle detached worktree is reclaimed instead of held. Default false. This is the only flag that can promote an entry toward reclaim; no flag ever weakens a hold otherwise."
30129
30287
  ),
30130
30288
  noisePaths: z.array(z.string()).optional().describe(
30131
30289
  "Worktree-relative paths whose dirt is known noise (a worktree dirty ONLY on these counts as clean). Default `.opencode/package-lock.json`; pass [] to disable."
30132
30290
  ),
30133
- wait: mcpBool2.optional().describe(
30291
+ wait: mcpBool3.optional().describe(
30134
30292
  "false \u21D2 return a jobId immediately; poll `worktree_gc_status`. true \u21D2 block until the gc finishes (no background fallback). Default: wait up to `waitMs`, then fall back to background."
30135
30293
  ),
30136
30294
  waitMs: mcpNumber.optional().describe(
@@ -30224,12 +30382,12 @@ function registerSessionTools(rawServer, opts) {
30224
30382
  base: z.string().optional().describe("Base ref the work must be in. Default `origin/main`."),
30225
30383
  scopes: z.array(branchGcKind).optional().describe("Ref kinds to consider: local, remote, orphan. Default all three for a plan; REQUIRED for apply."),
30226
30384
  minAgeDays: mcpNumber.optional().describe("Unmerged refs younger than this many days are held. Default 3."),
30227
- includeReviewed: mcpBool2.optional().describe(
30385
+ includeReviewed: mcpBool3.optional().describe(
30228
30386
  "When true, a `review` ref whose stored verdict (branch_gc_verdict) has gate.agree=true for the SAME tip sha becomes `reclaim` (`reviewed`). Default false."
30229
30387
  ),
30230
30388
  anchor: z.string().optional().describe("Explicit anchor commit for a re-rooted base. Auto-detected when omitted."),
30231
- apply: mcpBool2.optional().describe("When true, EXECUTE the plan for `scopes`. Default false \u2014 a dry run."),
30232
- wait: mcpBool2.optional().describe("Block until the gc finishes (default true \u2014 today's behaviour). false \u21D2 return a jobId immediately; poll `branch_gc_status`."),
30389
+ apply: mcpBool3.optional().describe("When true, EXECUTE the plan for `scopes`. Default false \u2014 a dry run."),
30390
+ wait: mcpBool3.optional().describe("Block until the gc finishes (default true \u2014 today's behaviour). false \u21D2 return a jobId immediately; poll `branch_gc_status`."),
30233
30391
  waitMs: mcpNumber.optional().describe('Block at most this many milliseconds, then fall back to background: returns `{ jobId, status: "running" }` to poll with `branch_gc_status`. Only meaningful with the default `wait: true`.')
30234
30392
  },
30235
30393
  async (input) => {
@@ -30289,7 +30447,7 @@ function registerSessionTools(rawServer, opts) {
30289
30447
  'Poll a branch_gc run started with `wait: false` (or one that fell back to the background via `waitMs`). While running: status + elapsed time. When done: the plan\'s own summary (plus, for an apply, `applySummary` \u2014 deleted/skipped/failed per scope and the restore log path) and the path of the full result saved on disk (`resultPath`). The full result is too big to return whole, so `full: true` (or any of `section`, `classes`, `scopes`, `results`, `limit`, `cursor`) returns ONE filtered page of it: `result` (summary + plan metadata + the selected list) and `page { section, total, returned, nextCursor }` \u2014 default 100 rows, pass `nextCursor` back as `cursor` for the next page. Use `classes: ["reclaim"]` to see only what an apply would delete. While running the view carries `followUp.pollAfterMs` (poll every 30 s). When failed: the error.',
30290
30448
  {
30291
30449
  jobId: z.string().describe("Job id returned by `branch_gc` (`bgc_\u2026`)."),
30292
- full: mcpBool2.optional().describe("Include a filtered/paged slice of the full result (see description). Implied by any other slice param. Default false."),
30450
+ full: mcpBool3.optional().describe("Include a filtered/paged slice of the full result (see description). Implied by any other slice param. Default false."),
30293
30451
  section: z.enum(["entries", "outcomes"]).optional().describe("Which list to return: plan `entries` or apply `outcomes`. Default `entries` for a plan, `outcomes` for an apply."),
30294
30452
  classes: z.array(z.enum(["reclaim", "review", "hold"])).optional().describe('Entries only: keep these classes (e.g. ["reclaim"]).'),
30295
30453
  scopes: z.array(branchGcKind).optional().describe("Keep these ref kinds (local, remote, orphan)."),
@@ -30354,7 +30512,7 @@ function registerSessionTools(rawServer, opts) {
30354
30512
  salvage: z.string().optional().describe("What is worth keeping, if anything.")
30355
30513
  }),
30356
30514
  gate: z.object({
30357
- agree: mcpBool2.describe("true only if deleting the branch loses nothing of value"),
30515
+ agree: mcpBool3.describe("true only if deleting the branch loses nothing of value"),
30358
30516
  verdict: branchVerdictEnum,
30359
30517
  reason: z.string(),
30360
30518
  evidence: z.array(z.string()).describe("Concrete shas/paths. Required non-empty when agree is true.")
@@ -30967,10 +31125,10 @@ function registerSessionTools(rawServer, opts) {
30967
31125
  "DRY RUN, mutates nothing \u2014 classify every idle agent-cli session for the session steward: `close` (safe to auto-close: idle past `idleMinutes` AND the session's worktree merged or its parent already ended, with no tool call pending, and not `keepAlive`), `stuck` (stuck in `status:'starting'` with no pid for 10+ minutes \u2014 closing it is free, it never ran), `judge` (idle-enough but ambiguous \u2014 no merge/parent-ended signal, a pending tool call, or a `keepAlive` session that would otherwise close, since `keepAlive` can only ever reach `judge`, never `close`), or `keep` (not idle long enough yet, or busy/awaitingInput/awaitingPermission/archived/pinned/has busy children/has a live parent/is the caller's own session \u2014 NEVER eligible for `session_wrapup_apply`; omitted here unless `includeKeep` is set). Also reports `rssBytes` (process-tree RSS) per entry and summed per class in `totals`. Feed `close`/`stuck` ids straight to `session_wrapup_apply`; `judge` ids need a judge's verdict first (FIX-9B). Computing worktree merge status can take minutes: this call waits up to 25 s (`waitMs`), then returns `{ jobId, status: \"running\", followUp }` \u2014 poll `session_wrapup_status` with that jobId.",
30968
31126
  {
30969
31127
  idleMinutes: z.number().int().positive().optional().describe("Idle threshold in minutes a `close` candidate must clear. Default 20."),
30970
- includeKeep: mcpBool2.optional().describe(
31128
+ includeKeep: mcpBool3.optional().describe(
30971
31129
  "Include `keep`-class entries too. Default false \u2014 `keep` rows are never acted on, so they're omitted to keep the plan focused on what the steward might actually do."
30972
31130
  ),
30973
- wait: mcpBool2.optional().describe(
31131
+ wait: mcpBool3.optional().describe(
30974
31132
  "false \u21D2 return a jobId immediately; poll `session_wrapup_status`. true \u21D2 block until the plan is computed. Default: wait up to `waitMs`, then fall back to background."
30975
31133
  ),
30976
31134
  waitMs: mcpNumber.optional().describe("Block at most this many milliseconds, then fall back to background. Default 25000.")
@@ -31036,7 +31194,7 @@ function registerSessionTools(rawServer, opts) {
31036
31194
  judgedBy: z.string().optional().describe(
31037
31195
  "A judge session id. When set, the outcome's `source` is `'judged'` and a `judge`-class session also becomes eligible (not just `close`/`stuck`). Omitted \u21D2 `source:'declared'`, `judgedBy:'steward-rules'`, and only `close`/`stuck` are eligible."
31038
31196
  ),
31039
- wait: mcpBool2.optional().describe(
31197
+ wait: mcpBool3.optional().describe(
31040
31198
  "false \u21D2 return a jobId immediately; poll `session_wrapup_status`. true \u21D2 block until done. Default: wait up to `waitMs`, then fall back to background (the apply keeps running)."
31041
31199
  ),
31042
31200
  waitMs: mcpNumber.optional().describe("Block at most this many milliseconds, then fall back to background. Default 25000.")
@@ -31487,7 +31645,7 @@ function registerSessionTools(rawServer, opts) {
31487
31645
  "Set or clear a session's idle-reaper exemption. When `keepAlive` is true, the idle-reaper (`isReapable`) never auto-retires this session no matter how long it sits idle \u2014 for a supervisor that legitimately parks waiting on a child or a scheduled wake, which otherwise looks identical to a finished session. Set false to clear the exemption. Persists across daemon restarts. Does NOT touch the running agent.",
31488
31646
  {
31489
31647
  idOrName: z.string().min(1).describe("Session id or name to update \u2014 from `session_list`."),
31490
- keepAlive: mcpBool2.describe(
31648
+ keepAlive: mcpBool3.describe(
31491
31649
  "true to exempt this session from the idle-reaper, false to clear the exemption."
31492
31650
  )
31493
31651
  },
@@ -31549,7 +31707,7 @@ function registerSessionTools(rawServer, opts) {
31549
31707
  "Set or clear a session's list-visibility pin. When `pinned` is true, the session sorts to the top of `agentproto sessions` and the VS Code sessions webview's dedicated Pinned group. Set false to clear it. Persists across daemon restarts. Purely a sort/display flag \u2014 does NOT touch the idle-reaper, keepAlive, or emit any notification, and does NOT touch the running agent.",
31550
31708
  {
31551
31709
  idOrName: z.string().min(1).describe("Session id or name to update \u2014 from `session_list`."),
31552
- pinned: mcpBool2.describe(
31710
+ pinned: mcpBool3.describe(
31553
31711
  "true to pin this session to the top of the list, false to unpin it."
31554
31712
  )
31555
31713
  },
@@ -31834,7 +31992,7 @@ function registerSessionTools(rawServer, opts) {
31834
31992
  {
31835
31993
  idOrName: z.string().min(1).describe("Session id or name \u2014 from `session_list`."),
31836
31994
  key: z.string().min(1).describe("Artifact key, from `session_artifact_list`."),
31837
- pinned: mcpBool2.describe("true to pin, false to unpin.")
31995
+ pinned: mcpBool3.describe("true to pin, false to unpin.")
31838
31996
  },
31839
31997
  async (input) => {
31840
31998
  const prev = registry.findByIdOrName(input.idOrName);
@@ -32055,7 +32213,7 @@ function registerSessionTools(rawServer, opts) {
32055
32213
  lastBytes: z.number().int().min(1).max(64 * 1024).optional().describe(
32056
32214
  "Max bytes from the tail. Default 4096; the full ~64 KiB ring remains reachable by passing `lastBytes: 65536` explicitly."
32057
32215
  ),
32058
- clean: mcpBool2.optional().describe(
32216
+ clean: mcpBool3.optional().describe(
32059
32217
  "Strip ANSI codes, returning human-readable text (as `text` instead of `b64`). Default false = raw base64."
32060
32218
  )
32061
32219
  },
@@ -32147,7 +32305,7 @@ function registerSessionTools(rawServer, opts) {
32147
32305
 
32148
32306
  // src/index.ts
32149
32307
  init_agent_tools();
32150
- var mcpBool3 = z.preprocess(
32308
+ var mcpBool4 = z.preprocess(
32151
32309
  (v) => v === "true" ? true : v === "false" ? false : v,
32152
32310
  z.boolean()
32153
32311
  );
@@ -32232,10 +32390,10 @@ function registerBrainTools(server, opts) {
32232
32390
  {
32233
32391
  workspace: z.string().optional().describe("Workspace slug. Omit to use the calling session's workspace."),
32234
32392
  sessionId: z.string().optional().describe("Ingest one specific session (sess_xxx) instead of the backlog."),
32235
- reindex: mcpBool3.optional().describe(
32393
+ reindex: mcpBool4.optional().describe(
32236
32394
  'When `sessionId` is set and it was already ingested, force a re-ingest from the current transcript. Default false. Pass `true` or the string "true" to enable.'
32237
32395
  ),
32238
- reindexStale: mcpBool3.optional().describe(
32396
+ reindexStale: mcpBool4.optional().describe(
32239
32397
  'When `sessionId` is NOT set (backlog mode), also force-reingest every already-indexed session whose pipeline version is older than the code running now. Default false. Pass `true` or the string "true" to enable.'
32240
32398
  )
32241
32399
  },
@@ -38944,6 +39102,9 @@ function sentinelView(s) {
38944
39102
  ...s.lastError ? { lastError: s.lastError } : {}
38945
39103
  };
38946
39104
  }
39105
+ function sentinelViewWithDelivery(s, deliveryStatus) {
39106
+ return deliveryStatus ? { ...sentinelView(s), deliveryStatus } : sentinelView(s);
39107
+ }
38947
39108
  var ok2 = (body) => ({
38948
39109
  content: [{ type: "text", text: JSON.stringify({ ok: true, ...body }) }]
38949
39110
  });
@@ -38977,9 +39138,9 @@ function registerSentinelTools(server, opts) {
38977
39138
  );
38978
39139
  server.tool(
38979
39140
  "sentinel_list",
38980
- "List every sentinel this daemon is tracking, with status, match clauses, target, and event counters. Credentials are never returned.",
39141
+ "List every sentinel this daemon is tracking, with status, match clauses, target, and event counters (webhook targets also report `deliveryStatus`). Credentials are never returned.",
38981
39142
  {},
38982
- async () => ok2({ sentinels: store.list().map(sentinelView) })
39143
+ async () => ok2({ sentinels: store.list().map((s) => sentinelViewWithDelivery(s, opts.deliveryStatus?.(s.id))) })
38983
39144
  );
38984
39145
  server.tool(
38985
39146
  "sentinel_unwatch",
@@ -40931,7 +41092,7 @@ var TRANSPORT_CLOSED_RE = /\bACP connection closed\b/i;
40931
41092
  function withReviewWorktreeZones(boundary, cwd) {
40932
41093
  const zones = reviewWorktreeReadZones(cwd);
40933
41094
  if (!zones) return boundary;
40934
- const extra = [zones.worktree, zones.gitCommonDir].filter((z61) => !boundary.readOnly.includes(z61));
41095
+ const extra = [zones.worktree, zones.gitCommonDir].filter((z62) => !boundary.readOnly.includes(z62));
40935
41096
  return extra.length === 0 ? boundary : { ...boundary, readOnly: [...boundary.readOnly, ...extra] };
40936
41097
  }
40937
41098
  function agentStepMcpServers(input) {
@@ -45273,9 +45434,17 @@ function policyToActivities(policy) {
45273
45434
  return records;
45274
45435
  }
45275
45436
  var STALE_TURN_AFTER_MS = 10 * 6e4;
45437
+ var TURN_NAME_MAX = 60;
45438
+ function sessionDisplayName(session) {
45439
+ const name = session.title?.trim() || session.label?.trim();
45440
+ if (!name) return session.id;
45441
+ const clipped = name.length > TURN_NAME_MAX ? `${name.slice(0, TURN_NAME_MAX - 1).trimEnd()}\u2026` : name;
45442
+ return `"${clipped}"`;
45443
+ }
45276
45444
  function turnToActivities(session, opts = {}) {
45277
45445
  if (session.kind !== "agent-cli") return [];
45278
45446
  const completed = session.turnsCompleted ?? 0;
45447
+ const name = sessionDisplayName(session);
45279
45448
  const base = (turn, title) => ({
45280
45449
  id: `turn:${session.id}:${turn}`,
45281
45450
  kind: "turn",
@@ -45289,20 +45458,20 @@ function turnToActivities(session, opts = {}) {
45289
45458
  if (terminal) {
45290
45459
  if (session.killedMidTurn === true) {
45291
45460
  const rec = record(
45292
- base(completed + 1, `Turn ${completed + 1} interrupted on ${session.id}`),
45461
+ base(completed + 1, `Turn ${completed + 1} interrupted on ${name}`),
45293
45462
  session.status === "error" ? "failed" : "cancelled"
45294
45463
  );
45295
45464
  return [{ ...rec, ...session.lastActivityAt ? { endedAt: session.lastActivityAt } : {} }];
45296
45465
  }
45297
45466
  if (completed > 0) {
45298
- const rec = record(base(completed, `Turn ${completed} completed on ${session.id}`), "done");
45467
+ const rec = record(base(completed, `Turn ${completed} completed on ${name}`), "done");
45299
45468
  return [{ ...rec, ...session.lastActivityAt ? { endedAt: session.lastActivityAt } : {} }];
45300
45469
  }
45301
45470
  return [];
45302
45471
  }
45303
45472
  if (session.awaitingPermission === true) {
45304
45473
  return [
45305
- pendingRecord(base(completed + 1, `Turn ${completed + 1} on ${session.id} held on a permission`), {
45474
+ pendingRecord(base(completed + 1, `Turn ${completed + 1} on ${name} held on a permission`), {
45306
45475
  kind: "human-ack",
45307
45476
  refs: [session.id],
45308
45477
  detail: "permission request parked for permissions_respond"
@@ -45310,7 +45479,7 @@ function turnToActivities(session, opts = {}) {
45310
45479
  ];
45311
45480
  }
45312
45481
  if (session.busy === true) {
45313
- const rec = record(base(completed + 1, `Turn ${completed + 1} running on ${session.id}`), "active");
45482
+ const rec = record(base(completed + 1, `Turn ${completed + 1} running on ${name}`), "active");
45314
45483
  if (opts.now && session.lastActivityAt) {
45315
45484
  const nowMs = Date.parse(opts.now);
45316
45485
  const lastMs = Date.parse(session.lastActivityAt);
@@ -45322,7 +45491,7 @@ function turnToActivities(session, opts = {}) {
45322
45491
  }
45323
45492
  if (session.awaitingInput === true) {
45324
45493
  return [
45325
- pendingRecord(base(completed + 1, `Awaiting human input on ${session.id}`), {
45494
+ pendingRecord(base(completed + 1, `Awaiting human input on ${name}`), {
45326
45495
  kind: "human-ack",
45327
45496
  refs: [session.id],
45328
45497
  detail: "session asked a question; next turn needs a human prompt"
@@ -45330,7 +45499,7 @@ function turnToActivities(session, opts = {}) {
45330
45499
  ];
45331
45500
  }
45332
45501
  if (completed > 0) {
45333
- const rec = record(base(completed, `Turn ${completed} completed on ${session.id}`), "done");
45502
+ const rec = record(base(completed, `Turn ${completed} completed on ${name}`), "done");
45334
45503
  return [{ ...rec, ...session.lastActivityAt ? { endedAt: session.lastActivityAt } : {} }];
45335
45504
  }
45336
45505
  return [];
@@ -47574,16 +47743,34 @@ var FIRST_PARTY_CATALOG_ENTRIES = [
47574
47743
  "description": "View and continue any agentproto daemon session's conversation in the Agentik chat UI (assistant-ui based). Pick a session from the live/recent list or deep-link with ?session=<id>; the page replays the session's full transcript, then follows it live over SSE, and lets you send follow-up prompts into the same session. Built on @agstudio/react-agentproto (SSE transcript projection, permission approval, thread list) and @agstudio/chat-starter's assistant-ui shell, reused almost as-is.",
47575
47744
  "source": {
47576
47745
  "kind": "agentapp",
47577
- "url": "https://github.com/agentproto/apps/releases/download/session-chat%400.1.0/session-chat-0.1.0.agentapp",
47578
- "sha256": "12216f65fa3cff9bfb9fcd49c46c9166eb68a790d278d466e07e0a95df5f4eef",
47579
- "version": "0.1.0",
47580
- "size": 518621
47746
+ "url": "https://github.com/agentproto/apps/releases/download/session-chat%400.1.1/session-chat-0.1.1.agentapp",
47747
+ "sha256": "e8084a125e335cbc408b0e8dd3371711191f6aa0019dad4907f26b19ec9f344b",
47748
+ "version": "0.1.1",
47749
+ "size": 516437
47581
47750
  },
47582
- "version": "0.1.0",
47751
+ "icon": "https://raw.githubusercontent.com/agentproto/apps/main/media/@agentik/session-chat/0.1.1/icon.svg",
47752
+ "version": "0.1.1",
47583
47753
  "tier": "bundle",
47754
+ "publisher": "Agentik",
47584
47755
  "license": {
47585
47756
  "kind": "free"
47586
- }
47757
+ },
47758
+ "tagline": "Read and continue any agentproto session as a chat thread.",
47759
+ "longDescription": "Session Chat turns any agentproto session into a chat thread you can read and continue.\n\nPick a running or recent session, or open one directly with `?session=<id>`. The page replays the full transcript, then follows the session live as the agent works, and lets you send follow-up prompts into the same session.\n\n## What you get\n\n- **Transcript replay and live follow**: the whole conversation, then new turns as they stream in.\n- **Tool activity at a glance**: file reads, commands and edits grouped under each reply, with the files an agent changed.\n- **Reply into the session**: send a follow-up, interrupt a running turn, queue prompts while the agent works.\n- **Approvals**: answer the agent's permission requests from the thread.\n- **Session list**: running and recent sessions, grouped by workspace, with search and pins.\n- **Start a session**: pick a harness and model and start a new chat from the same page.\n\n## Requirements\n\nSession Chat talks to your local agentproto daemon. Its bundled agent runs on the `mastra-agent` adapter: install it first with `agentproto install mastra-agent`.",
47760
+ "screenshots": [
47761
+ {
47762
+ "url": "https://raw.githubusercontent.com/agentproto/apps/main/media/@agentik/session-chat/0.1.1/conversation.png",
47763
+ "alt": "A finished session replayed as a chat thread, with a markdown table in the agent's reply and the composer below",
47764
+ "width": 1280,
47765
+ "height": 800
47766
+ }
47767
+ ],
47768
+ "categories": [
47769
+ "chat",
47770
+ "sessions",
47771
+ "developer-tools"
47772
+ ],
47773
+ "homepage": "https://agentproto.sh/apps/session-chat"
47587
47774
  }
47588
47775
  ];
47589
47776
 
@@ -53526,8 +53713,45 @@ async function handleSessions(req, res, path, registry, resolveAgentAdapter, pty
53526
53713
  if (kindParam && kindParam !== "all") return s.kind === kindParam;
53527
53714
  return includeCommands || s.kind !== "command";
53528
53715
  };
53716
+ const listFilters = parseSessionListFilterParams(params);
53717
+ if (listFilters.parentSessionId) {
53718
+ listFilters.parentSessionId = registry.findByIdOrName(listFilters.parentSessionId)?.id ?? listFilters.parentSessionId;
53719
+ }
53720
+ const statusParam = params.get("status");
53721
+ const onlyAlive = params.get("onlyAlive") === "true";
53722
+ const limitParam = params.get("limit");
53723
+ const limit = limitParam === null ? void 0 : Number.parseInt(limitParam, 10);
53724
+ if (limit !== void 0 && (!Number.isInteger(limit) || limit < 1)) {
53725
+ json3(400, {
53726
+ error: "invalid_limit",
53727
+ message: `?limit must be a positive integer, got ${JSON.stringify(limitParam)}.`
53728
+ });
53729
+ return true;
53730
+ }
53731
+ const narrowed = hasSessionListFilters(listFilters) || statusParam !== null || onlyAlive || limit !== void 0;
53732
+ let narrow;
53733
+ try {
53734
+ const keep = compileSessionListFilters(listFilters);
53735
+ narrow = (list) => list.filter((s) => {
53736
+ if (statusParam) {
53737
+ if (s.status !== statusParam) return false;
53738
+ } else if (onlyAlive && s.status !== "running" && s.status !== "starting") {
53739
+ return false;
53740
+ }
53741
+ return keep(s);
53742
+ });
53743
+ } catch (err) {
53744
+ if (err instanceof SessionListFilterError) {
53745
+ json3(400, { error: "invalid_filter", message: err.message });
53746
+ return true;
53747
+ }
53748
+ throw err;
53749
+ }
53529
53750
  let rows = registry.list({ includeArchived });
53530
- rows = rows.filter(matchesFilter);
53751
+ rows = narrow(rows.filter(matchesFilter));
53752
+ if (narrowed) rows = sortNewestActivityFirst(rows);
53753
+ const total = rows.length;
53754
+ if (limit !== void 0 && sinceParam === null) rows = rows.slice(0, limit);
53531
53755
  let body;
53532
53756
  if (sinceParam !== null) {
53533
53757
  const sinceMs = Date.parse(sinceParam);
@@ -53543,11 +53767,14 @@ async function handleSessions(req, res, path, registry, resolveAgentAdapter, pty
53543
53767
  return Number.isNaN(ts) || ts >= sinceMs;
53544
53768
  });
53545
53769
  const removed = includeArchived ? [] : registry.list({ includeArchived: true }).filter(
53546
- (s) => s.archived && matchesFilter(s) && (s.archivedAt === void 0 || Date.parse(s.archivedAt) >= sinceMs)
53770
+ (s) => s.archived && matchesFilter(s) && narrow([s]).length > 0 && (s.archivedAt === void 0 || Date.parse(s.archivedAt) >= sinceMs)
53547
53771
  ).map((s) => s.id);
53548
53772
  body = { sessions: changed.map((s) => projectSessionForHttp(s, fields)), removed };
53549
53773
  } else {
53550
- body = { sessions: rows.map((s) => projectSessionForHttp(s, fields)) };
53774
+ body = {
53775
+ sessions: rows.map((s) => projectSessionForHttp(s, fields)),
53776
+ ...narrowed ? { total } : {}
53777
+ };
53551
53778
  }
53552
53779
  const serialized = JSON.stringify(body);
53553
53780
  const etag = strongEtag(serialized);
@@ -55230,7 +55457,7 @@ async function handleSentinels(req, res, path, deps2) {
55230
55457
  res.end(JSON.stringify(body));
55231
55458
  };
55232
55459
  if (path === "/sentinels" && req.method === "GET") {
55233
- json3(200, { sentinels: deps2.store.list().map(sentinelView) });
55460
+ json3(200, { sentinels: deps2.store.list().map((s) => sentinelViewWithDelivery(s, deps2.deliveryStatus?.(s.id))) });
55234
55461
  return true;
55235
55462
  }
55236
55463
  if (path === "/sentinels" && req.method === "POST") {
@@ -58410,6 +58637,23 @@ function rawPost(args) {
58410
58637
  }
58411
58638
 
58412
58639
  // src/webhook-egress/delivery.ts
58640
+ function callbackHost(url) {
58641
+ try {
58642
+ return new URL(url).host;
58643
+ } catch {
58644
+ return "invalid-url";
58645
+ }
58646
+ }
58647
+ function redactUrls(text13) {
58648
+ return text13.replace(/https?:\/\/[^\s'"<>)]+/gi, (m) => {
58649
+ try {
58650
+ const u = new URL(m);
58651
+ return `${u.protocol}//${u.host}`;
58652
+ } catch {
58653
+ return "<url>";
58654
+ }
58655
+ });
58656
+ }
58413
58657
  var CLAMP_LIMIT_BYTES = 262144;
58414
58658
  var MAX_ATTEMPTS = 5;
58415
58659
  var BACKOFF_BASE_MS = 250;
@@ -58441,6 +58685,12 @@ async function deliverEventEnvelope(replay, event, deps2 = {}) {
58441
58685
  const sleep3 = deps2.sleep ?? ((ms) => new Promise((r) => setTimeout(r, ms)));
58442
58686
  const fetcher = deps2.fetch ?? ((url, init) => ssrfFetch(url, init));
58443
58687
  const { bytes: payloadBytes } = envelopeClampedBytes(event);
58688
+ const note = (info) => {
58689
+ try {
58690
+ deps2.onAttempt?.(info);
58691
+ } catch {
58692
+ }
58693
+ };
58444
58694
  const delivery = { attempts: 0 };
58445
58695
  for (let attempt = 0; attempt < MAX_ATTEMPTS; attempt++) {
58446
58696
  if (attempt > 0) await sleep3(deliveryBackoffDelay(attempt));
@@ -58452,6 +58702,7 @@ async function deliverEventEnvelope(replay, event, deps2 = {}) {
58452
58702
  signed = signWebhook({ msgId: event.eventId, timestamp, payload: payloadBytes, secrets: replay.secrets });
58453
58703
  } catch (err) {
58454
58704
  delivery.lastError = `signing failed: ${err.message}`;
58705
+ note({ attempt: delivery.attempts, error: "invalid_secret", outcome: "dead" });
58455
58706
  return { ok: false, reason: "invalid_secret", delivery };
58456
58707
  }
58457
58708
  let response;
@@ -58464,18 +58715,27 @@ async function deliverEventEnvelope(replay, event, deps2 = {}) {
58464
58715
  // delivery default (challenge uses 10_000)
58465
58716
  });
58466
58717
  } catch (err) {
58467
- delivery.lastError = err instanceof Error ? err.message : String(err);
58468
- if (attempt < MAX_ATTEMPTS - 1) continue;
58718
+ delivery.lastError = redactUrls(err instanceof Error ? err.message : String(err));
58719
+ const last = attempt >= MAX_ATTEMPTS - 1;
58720
+ note({ attempt: delivery.attempts, error: delivery.lastError, outcome: last ? "dead" : "retry" });
58721
+ if (!last) continue;
58469
58722
  return { ok: false, reason: "network", delivery };
58470
58723
  }
58471
58724
  if (response.status >= 200 && response.status <= 299) {
58725
+ note({ attempt: delivery.attempts, status: response.status, outcome: "delivered" });
58472
58726
  return { ok: true, delivery };
58473
58727
  }
58474
58728
  if (TERMINAL_NO_RETRY_STATUSES.has(response.status)) {
58475
58729
  delivery.lastError = `terminal status ${response.status}`;
58730
+ note({ attempt: delivery.attempts, status: response.status, outcome: "dead" });
58476
58731
  return { ok: false, reason: `http_${response.status}`, delivery };
58477
58732
  }
58478
58733
  delivery.lastError = `retryable status ${response.status}`;
58734
+ note({
58735
+ attempt: delivery.attempts,
58736
+ status: response.status,
58737
+ outcome: attempt >= MAX_ATTEMPTS - 1 ? "dead" : "retry"
58738
+ });
58479
58739
  }
58480
58740
  return { ok: false, reason: "retries_exhausted", delivery };
58481
58741
  }
@@ -59093,7 +59353,20 @@ function createSentinelWebhookOutbox(opts) {
59093
59353
  const debounceMs = opts.debounceMs ?? PERSIST_DEBOUNCE_MS8;
59094
59354
  const log = opts.log ?? ((line) => console.warn(line));
59095
59355
  const persist = opts.persist ?? opts.filePath !== void 0;
59096
- const deliverEvent = opts.deliverEvent ?? (async (input) => deliverEventEnvelope(input.replay, input.row.envelope));
59356
+ const deliveryLog = (row, host, detail) => {
59357
+ log(`[sentinel-webhook-outbox] sentinel=${row.sentinelId} event=${row.eventId} host=${host} ${detail}`);
59358
+ };
59359
+ const deliverEvent = opts.deliverEvent ?? (async (input) => {
59360
+ const host = callbackHost(input.replay.callbackUrl);
59361
+ return deliverEventEnvelope(input.replay, input.row.envelope, {
59362
+ ...opts.deliverDeps,
59363
+ onAttempt: (a) => deliveryLog(
59364
+ input.row,
59365
+ host,
59366
+ `attempt=${a.attempt} ${a.status !== void 0 ? `http=${a.status}` : `error="${a.error ?? "unknown"}"`} ${a.outcome}`
59367
+ )
59368
+ });
59369
+ });
59097
59370
  const rowKey = (sentinelId, eventId) => `${sentinelId}::${eventId}`;
59098
59371
  const load2 = () => {
59099
59372
  const out = /* @__PURE__ */ new Map();
@@ -59204,14 +59477,19 @@ function createSentinelWebhookOutbox(opts) {
59204
59477
  row.failReason = outcome.reason;
59205
59478
  }
59206
59479
  row.terminalAt = nowMs();
59480
+ deliveryLog(
59481
+ row,
59482
+ callbackHost(replay.callbackUrl),
59483
+ `final=${row.status} attempts=${outcome.delivery.attempts}` + (outcome.ok ? "" : ` reason=${outcome.reason}`)
59484
+ );
59207
59485
  } catch (err) {
59208
59486
  row.deliveryState = {
59209
59487
  ...row.deliveryState ?? { attempts: 0 },
59210
- lastError: err instanceof Error ? err.message : String(err),
59488
+ lastError: redactUrls(err instanceof Error ? err.message : String(err)),
59211
59489
  lastAt: new Date(nowMs()).toISOString()
59212
59490
  };
59213
59491
  row.status = "pending";
59214
- log(`[sentinel-webhook-outbox] dispatch failed, row left pending: ${row.sentinelId} ${row.eventId}`);
59492
+ deliveryLog(row, callbackHost(replay.callbackUrl), "dispatch failed, row left pending");
59215
59493
  }
59216
59494
  schedulePersist();
59217
59495
  if (row.status === "delivered" || row.status === "dead") {
@@ -59306,6 +59584,27 @@ function createSentinelWebhookOutbox(opts) {
59306
59584
  rows() {
59307
59585
  return Array.from(rows.values());
59308
59586
  },
59587
+ deliveryStatus(sentinelId) {
59588
+ let latest;
59589
+ let active = false;
59590
+ let dead = 0;
59591
+ for (const row of rows.values()) {
59592
+ if (row.sentinelId !== sentinelId) continue;
59593
+ if (row.status === "pending") active = true;
59594
+ if (row.status === "dead") dead++;
59595
+ if (!latest || (row.terminalAt ?? row.createdAt) >= (latest.terminalAt ?? latest.createdAt)) latest = row;
59596
+ }
59597
+ if (!latest) return void 0;
59598
+ const lastError = latest.deliveryState.lastError ?? latest.failReason ?? latest.deadReason;
59599
+ return {
59600
+ active,
59601
+ ...latest.deliveryState.lastAt ? { lastDeliveryAt: latest.deliveryState.lastAt } : {},
59602
+ lastStatus: latest.status,
59603
+ ...lastError && latest.status !== "delivered" ? { lastError: redactUrls(lastError) } : {},
59604
+ attempts: latest.deliveryState.attempts,
59605
+ dead
59606
+ };
59607
+ },
59309
59608
  flushSync
59310
59609
  };
59311
59610
  }
@@ -70404,6 +70703,7 @@ async function createGateway(opts) {
70404
70703
  store: sentinelStore,
70405
70704
  runtime: sentinelRuntime,
70406
70705
  tombstones: sentinelRuntime.cancelTombstones,
70706
+ deliveryStatus: (id) => sentinelRuntime.webhookOutbox.deliveryStatus(id),
70407
70707
  resolveProvider: resolveSentinelProviderResolved,
70408
70708
  isSessionAlive,
70409
70709
  ...callerSessionId ? { callerSessionId } : {}
@@ -70555,7 +70855,8 @@ async function createGateway(opts) {
70555
70855
  resolveProvider: resolveSentinelProviderResolved,
70556
70856
  isSessionAlive,
70557
70857
  runtime: sentinelRuntime,
70558
- tombstones: sentinelRuntime.cancelTombstones
70858
+ tombstones: sentinelRuntime.cancelTombstones,
70859
+ deliveryStatus: (id) => sentinelRuntime.webhookOutbox.deliveryStatus(id)
70559
70860
  },
70560
70861
  follows: {
70561
70862
  store: sessionFollowStore,
@@ -70904,6 +71205,6 @@ var export_readPairingsSnapshot = pairing_registry_exports.readPairingsSnapshot;
70904
71205
  var export_removeProviderKey = providers_store_exports.removeProviderKey;
70905
71206
  var export_setProviderKey = providers_store_exports.setProviderKey;
70906
71207
 
70907
- export { AnthropicRemainingQuotaReader, AuthResolutionError, BUCKETS_ROOT, CLAMP_LIMIT_BYTES, CLAUDE_CODE_OAUTH_SOURCE, CONTINUE_PROMPT_SOURCE, DEAD_SESSION_STATUSES, DEFAULT_ALWAYS_ON_TOOLS, DEFAULT_BUCKET, DEFAULT_CONTINUE_PROMPT, DEFAULT_HOST_LOAD_BUDGET_MS, DEFAULT_HOST_LOAD_THRESHOLDS, DEFAULT_MODEL_ROLES, DEFAULT_ORCHESTRATOR_TOOLS, DEFAULT_TTL_MS, DEFAULT_WORKTREE_ISOLATION, DEFAULT_WORKTREE_PROVISION_CONCURRENCY, DEVICE_PROMPT_PATH_PREFIX, EVENT_REGISTRY, FOLLOW_EVENTS, GC_REAPABLE_STATES, GITHUB_SCHEME, HOSTS_VERSION, HOST_HANDSHAKE_REMEDIATION_HINT, HOST_SCOPE_HEADER, HarnessPresetValidationError, INBOUND_PROVIDERS, INDEX_DEFAULT_LIMIT, INDEX_MAX_OUTPUT, INDEX_MAX_PROMPT, INDEX_TAIL_BYTES, JOIN_TOKENS_VERSION, LEGACY_SESSIONS_FILE, MAX_ATTEMPTS, MAX_AUTO_CONTINUE_ATTEMPTS, MAX_MESSAGE_DATA_BYTES, MAX_TTL_MS, MCP_APP_BRIDGE_SCRIPT, MESSAGE_KINDS, MESSAGE_PREAMBLE, MESSAGE_TAG, MESSAGE_URGENCIES, MIN_TTL_MS, MODEL_ROLE_REF_PREFIX, McpEventsError, NO_OUTPUT_STALL_TURN_ERROR, export_PAIRINGS_VERSION as PAIRINGS_VERSION, POSTURE_NATIVE_ALIASES, POSTURE_PREAMBLES, export_PROVIDER_ENV_VARS as PROVIDER_ENV_VARS, PrLookupError, ResumeDisabledError, SESSION_END_REASONS, SESSION_ID_ENV, SIGN_NAMESPACE, SentinelBackingExpiredError, SessionRetiredError, SsrfFetchError, SubscriptionSourceError, TASK_STATUSES, WORKSPACE_SLUG_ENV, WORKTREE_ISOLATION_ENV, WORKTREE_PROVISION_CONCURRENCY_ENV, activityCounts, addHarnessPreset, allowedSignersLine, appendConversationRecord, attachSandbox, backfillSessionIndexes, bucketDir, bucketSessionsFile, bucketTranscriptDir, buildCatalogModels, buildCatalogProviderModels, buildHostLoadReport, buildMcpConfigSnippet, buildRouteAwareLaunchConfig, buildSessionRecap, canonicalForModeId, canonicalizeJcs, challengeCacheSize, challengeReasonForSsrf, claudeProjectSlug, collectGcCandidates, collectHostSample, compactOutcome, composeMode, composeSessionObservers, composedFromRangeSha, computeHostWarnings, computeRefreshBefore, continueInterruptedSessions, continueSkipReason, conversationIndexPath, createActivityProjector, createDaemonReviewerHost, createDefaultHostProbes, createDeviceRegistry, createFileStepCache, createGateway, createHostLoadService, createHostRegistry, createInboundEndpointStore, createJoinTokenRegistry, createOrchestratorInjector, createOrchestratorMcpServerFactory, export_createPairingRegistry as createPairingRegistry, createPrProvenanceReconciler, createProcessStatsService, createReviewLaneExecutor, createReviewLedger, createReviewPackLoader, createReviewRunner, createScopeTokenRegistry, createSentinelWebhookOutbox, createSessionFollowStore, createSessionMessage, createSupervisorTaskGateRunner, createTaskLedger, createWorkspaceBrainSubscriber, createWorkspaceBrains, createWorkspaceFs, credentialFingerprint, daemonBearerPrincipal, daemonRegistryDir, decideWorktreeIsolation, declaredPresetToProviderPreset, decodeWhsecSecret, decomposeMode, defaultBrowserAdapterIds, defaultBrowserAdapterResolution, defaultReviewKeysDir, defaultReviewLedgerRoot, defaultReviewPackCacheDir, defaultTranscriptBaseDir, defineBraveSearchHttpDriver, defineSerperHttpDriver, deleteUserPreset, deliverEventEnvelope, deliveryBackoffDelay, deriveIndexFromTranscript, deriveSessionOutcome, deriveSessionUsage, describeOwner, encodeWhsecSecret, enrichRollupWithProviderQuota, enrichWithRemainingQuota, ensureReviewSigningKey, envelopeClampedBytes, escapeHumanPrompt, escapeMessageBody, evaluateCostBudget, eventsList, eventsSubscribe, eventsUnsubscribe, execGh, extractHelpSection, fetchHostTurns, fetchPrStatus, fileConversationStore, fileExists3 as fileExists, filterActivities, findComposeCandidate, findConversationRecord, findEventDefinition, findNativeMode, findPrForCommit, formatToolCall, formatToolResult, getDefaultHarnessPreset, getHarnessPreset, getHostLoadService, getMcpCredentialDeps, getProcessStatsService, export_getProviderKey as getProviderKey, getToolHelp, getUserPreset, githubRepoOf, harnessPresetsPath, hostPlaceholders, hostRecordToMirrorRecord, indexEntryFromDescriptor, injectMcpAppBridge, export_injectProviderKeysIntoEnv as injectProviderKeysIntoEnv, isAgentCliAuthConfigured, isAutomatedPromptSource, isClosedTaskStatus, isKnownSessionEndReason, isMessageAllowed, isNoSessionPromptFailure, isProviderLimitError, isPubliclyRoutable, isRetired, isSafeBucketSlug, isTerminalActivityState, listBuckets, listHarnessPresets, listModelRoles, listPresets, listToolHelpTopics, listUserPresets, loadHarnessPresets, export_loadProviders as loadProviders, loadQuotaStore, loadUserPresets, loadWorkspaceModelRoles, loadWorktreeIsolation, locateConversationByNativePath, locateConversationBySessionId, makeBrowserAdapterLister, makeRestartForRouting, makeSandboxCredsStore, makeSandboxResolver, matchesMessageFilter, matchesSessionQuery, measureTool, measureToolList, messageFrom, migrateLegacySessionsFile, migrationMarkerPath, mintMessageId, mirrorCursorForSession, monitorPolicyWait, monitorSessionWait, narrowOrchestratorTools, normalizeCallbackUrl, normalizeCommand, normalizeInbound, normalizeModeId, normalizeRemote, normalizeSkillsOption, normalizeWorktreeField, parseAnthropicRateLimitHeaders, parseDuration, parseModelRoleRef, parsePrUrl, parseTaskStatus, parseWindow, parseWorktreeIsolationMode, pickUsageDetail, policyToActivities, policyWatchesSession, prHeadSha, prToActivities, projectBrowserTools, projectSessionUsage, promptDeviceSession, promptHostSession, export_providerEnvVar as providerEnvVar, export_providersPath as providersPath, readAllSessionIndexes, readConversationIndex, readDaemonRegistry, readHostsSnapshot, export_readPairingsSnapshot as readPairingsSnapshot, readProfileQuota, readRegisteredSlugs, readRuntimeMeta, readSandboxLedger, readSessionForBrain, readSessionIndex, readTranscriptTail, readUsageSnapshots, reapGcEntry, reapOrphanedDescendants, reconcileSandboxLedger, recordProfileQuota, recordSandboxBoot, recordSandboxLiveness, recordSandboxOrigin, recordSandboxState, registerBrainTools, registerBuiltinRoutes, registerDeviceTools, registerPairingTools, registerReviewTools, registerSandboxAttachTool, registerWebSearchTools, removeHarnessPreset, export_removeProviderKey as removeProviderKey, removeSandboxLedgerEntry, renderInboxDigest, renderSessionMessage, renderSessionMessages, repoSlug, resetChallengeCacheForTests, resolveAuthSpec, resolveBucketSlug, resolveDeferredToolsGatewayOption, resolveDevicePromptMapping, resolveEffectiveLlmEndpointFlag, resolveModelRole, resolveNativeLink, resolvePosture, resolvePrincipal, resolveRelation, resolveReuseFromLedger, resolveReviewerPreset, resolveSpawnDefaults, resolveSubscriptionCredential, resolveSuccessor, rollupSessionSubtree, rollupUsage, runContinueOnBootPass, runCrashDetectPass, runEagerResumePass, runIdleReapPass, runShellLane, runStallWatchdogPass, sandboxLedgerPath, sanitizeLabel, saveUserPreset, searchSessionIndexes, seedWalkForTranscript, serializeEnvelope, sessionEventsPath, sessionIndexPath, sessionPrincipal, sessionTranscriptDir, setDefaultPreset, setDefaultSessionsBaseDir, setEgressDispatcherForTests, setMcpCredentialDeps, export_setProviderKey as setProviderKey, signAttestation, signWebhook, ssrfFetch, subscriptionId, summarizeBranchGcApply, sweepStaleDaemonRegistry, sweepStaleRuntimeMetas, syncDeviceMirror, tenantScope, toMcpEvent, toWebhookEnvelope, toWorktreeStatusView, trackWorktreeProvision, turnToActivities, unlinkDaemonRegistryEntry, unlinkRuntimeMeta, untilForTtl, updateHarnessPreset, upsertSandboxLedger, userPresetsPath, validateAgainstInputSchema, verifyCallback, verifyInboundSignature, verifySignedAttestation, webSearchTool, webhookRequestId, wireSessionFollow, withBranchGcApplySummary, withPr, withPrStatus, workflowToActivities, writeDaemonRegistryEntry, writeSessionIndex };
71208
+ export { AnthropicRemainingQuotaReader, AuthResolutionError, BUCKETS_ROOT, CLAMP_LIMIT_BYTES, CLAUDE_CODE_OAUTH_SOURCE, CONTINUE_PROMPT_SOURCE, DEAD_SESSION_STATUSES, DEFAULT_ALWAYS_ON_TOOLS, DEFAULT_BUCKET, DEFAULT_CONTINUE_PROMPT, DEFAULT_HOST_LOAD_BUDGET_MS, DEFAULT_HOST_LOAD_THRESHOLDS, DEFAULT_MODEL_ROLES, DEFAULT_ORCHESTRATOR_TOOLS, DEFAULT_TTL_MS, DEFAULT_WORKTREE_ISOLATION, DEFAULT_WORKTREE_PROVISION_CONCURRENCY, DEVICE_PROMPT_PATH_PREFIX, EVENT_REGISTRY, FOLLOW_EVENTS, GC_REAPABLE_STATES, GITHUB_SCHEME, HOSTS_VERSION, HOST_HANDSHAKE_REMEDIATION_HINT, HOST_SCOPE_HEADER, HarnessPresetValidationError, INBOUND_PROVIDERS, INDEX_DEFAULT_LIMIT, INDEX_MAX_OUTPUT, INDEX_MAX_PROMPT, INDEX_TAIL_BYTES, JOIN_TOKENS_VERSION, LEGACY_SESSIONS_FILE, MAX_ATTEMPTS, MAX_AUTO_CONTINUE_ATTEMPTS, MAX_MESSAGE_DATA_BYTES, MAX_TTL_MS, MCP_APP_BRIDGE_SCRIPT, MESSAGE_KINDS, MESSAGE_PREAMBLE, MESSAGE_TAG, MESSAGE_URGENCIES, MIN_TTL_MS, MODEL_ROLE_REF_PREFIX, McpEventsError, NO_OUTPUT_STALL_TURN_ERROR, export_PAIRINGS_VERSION as PAIRINGS_VERSION, POSTURE_NATIVE_ALIASES, POSTURE_PREAMBLES, export_PROVIDER_ENV_VARS as PROVIDER_ENV_VARS, PrLookupError, ResumeDisabledError, SESSION_END_REASONS, SESSION_ID_ENV, SESSION_LIST_FILTER_KEYS, SIGN_NAMESPACE, SentinelBackingExpiredError, SessionListFilterError, SessionRetiredError, SsrfFetchError, SubscriptionSourceError, TASK_STATUSES, WORKSPACE_SLUG_ENV, WORKTREE_ISOLATION_ENV, WORKTREE_PROVISION_CONCURRENCY_ENV, activityCounts, addHarnessPreset, allowedSignersLine, appendConversationRecord, applySessionListFilters, attachSandbox, backfillSessionIndexes, bucketDir, bucketSessionsFile, bucketTranscriptDir, buildCatalogModels, buildCatalogProviderModels, buildHostLoadReport, buildMcpConfigSnippet, buildRouteAwareLaunchConfig, buildSessionRecap, canonicalForModeId, canonicalizeJcs, challengeCacheSize, challengeReasonForSsrf, claudeProjectSlug, collectGcCandidates, collectHostSample, compactOutcome, compileSessionListFilters, composeMode, composeSessionObservers, composedFromRangeSha, computeHostWarnings, computeRefreshBefore, continueInterruptedSessions, continueSkipReason, conversationIndexPath, createActivityProjector, createDaemonReviewerHost, createDefaultHostProbes, createDeviceRegistry, createFileStepCache, createGateway, createHostLoadService, createHostRegistry, createInboundEndpointStore, createJoinTokenRegistry, createOrchestratorInjector, createOrchestratorMcpServerFactory, export_createPairingRegistry as createPairingRegistry, createPrProvenanceReconciler, createProcessStatsService, createReviewLaneExecutor, createReviewLedger, createReviewPackLoader, createReviewRunner, createScopeTokenRegistry, createSentinelWebhookOutbox, createSessionFollowStore, createSessionMessage, createSupervisorTaskGateRunner, createTaskLedger, createWorkspaceBrainSubscriber, createWorkspaceBrains, createWorkspaceFs, credentialFingerprint, daemonBearerPrincipal, daemonRegistryDir, decideWorktreeIsolation, declaredPresetToProviderPreset, decodeWhsecSecret, decomposeMode, defaultBrowserAdapterIds, defaultBrowserAdapterResolution, defaultReviewKeysDir, defaultReviewLedgerRoot, defaultReviewPackCacheDir, defaultTranscriptBaseDir, defineBraveSearchHttpDriver, defineSerperHttpDriver, deleteUserPreset, deliverEventEnvelope, deliveryBackoffDelay, deriveIndexFromTranscript, deriveSessionOutcome, deriveSessionUsage, describeOwner, encodeWhsecSecret, enrichRollupWithProviderQuota, enrichWithRemainingQuota, ensureReviewSigningKey, envelopeClampedBytes, escapeHumanPrompt, escapeMessageBody, evaluateCostBudget, eventsList, eventsSubscribe, eventsUnsubscribe, execGh, extractHelpSection, fetchHostTurns, fetchPrStatus, fileConversationStore, fileExists3 as fileExists, filterActivities, findComposeCandidate, findConversationRecord, findEventDefinition, findNativeMode, findPrForCommit, formatToolCall, formatToolResult, getDefaultHarnessPreset, getHarnessPreset, getHostLoadService, getMcpCredentialDeps, getProcessStatsService, export_getProviderKey as getProviderKey, getToolHelp, getUserPreset, githubRepoOf, harnessPresetsPath, hasSessionListFilters, hostPlaceholders, hostRecordToMirrorRecord, indexEntryFromDescriptor, injectMcpAppBridge, export_injectProviderKeysIntoEnv as injectProviderKeysIntoEnv, isAgentCliAuthConfigured, isAutomatedPromptSource, isClosedTaskStatus, isKnownSessionEndReason, isMessageAllowed, isNoSessionPromptFailure, isNoiseSession, isProviderLimitError, isPubliclyRoutable, isRetired, isSafeBucketSlug, isTerminalActivityState, listBuckets, listHarnessPresets, listModelRoles, listPresets, listToolHelpTopics, listUserPresets, loadHarnessPresets, export_loadProviders as loadProviders, loadQuotaStore, loadUserPresets, loadWorkspaceModelRoles, loadWorktreeIsolation, locateConversationByNativePath, locateConversationBySessionId, makeBrowserAdapterLister, makeRestartForRouting, makeSandboxCredsStore, makeSandboxResolver, matchesMessageFilter, matchesSessionQuery, measureTool, measureToolList, messageFrom, migrateLegacySessionsFile, migrationMarkerPath, mintMessageId, mirrorCursorForSession, monitorPolicyWait, monitorSessionWait, narrowOrchestratorTools, normalizeCallbackUrl, normalizeCommand, normalizeInbound, normalizeModeId, normalizeRemote, normalizeSkillsOption, normalizeWorktreeField, parseAnthropicRateLimitHeaders, parseDuration, parseModelRoleRef, parsePrUrl, parseSessionListFilterParams, parseTaskStatus, parseTimeBound, parseWindow, parseWorktreeIsolationMode, pickSessionListFilters, pickUsageDetail, policyToActivities, policyWatchesSession, prHeadSha, prToActivities, projectBrowserTools, projectSessionUsage, promptDeviceSession, promptHostSession, export_providerEnvVar as providerEnvVar, export_providersPath as providersPath, readAllSessionIndexes, readConversationIndex, readDaemonRegistry, readHostsSnapshot, export_readPairingsSnapshot as readPairingsSnapshot, readProfileQuota, readRegisteredSlugs, readRuntimeMeta, readSandboxLedger, readSessionForBrain, readSessionIndex, readTranscriptTail, readUsageSnapshots, reapGcEntry, reapOrphanedDescendants, reconcileSandboxLedger, recordProfileQuota, recordSandboxBoot, recordSandboxLiveness, recordSandboxOrigin, recordSandboxState, registerBrainTools, registerBuiltinRoutes, registerDeviceTools, registerPairingTools, registerReviewTools, registerSandboxAttachTool, registerWebSearchTools, removeHarnessPreset, export_removeProviderKey as removeProviderKey, removeSandboxLedgerEntry, renderInboxDigest, renderSessionMessage, renderSessionMessages, repoSlug, resetChallengeCacheForTests, resolveAuthSpec, resolveBucketSlug, resolveDeferredToolsGatewayOption, resolveDevicePromptMapping, resolveEffectiveLlmEndpointFlag, resolveModelRole, resolveNativeLink, resolvePosture, resolvePrincipal, resolveRelation, resolveReuseFromLedger, resolveReviewerPreset, resolveSpawnDefaults, resolveSubscriptionCredential, resolveSuccessor, rollupSessionSubtree, rollupUsage, runContinueOnBootPass, runCrashDetectPass, runEagerResumePass, runIdleReapPass, runShellLane, runStallWatchdogPass, sandboxLedgerPath, sanitizeLabel, saveUserPreset, searchSessionIndexes, seedWalkForTranscript, serializeEnvelope, sessionActivityMs, sessionEventsPath, sessionIndexPath, sessionListFilterShape, sessionPrincipal, sessionTranscriptDir, setDefaultPreset, setDefaultSessionsBaseDir, setEgressDispatcherForTests, setMcpCredentialDeps, export_setProviderKey as setProviderKey, signAttestation, signWebhook, sortNewestActivityFirst, ssrfFetch, subscriptionId, summarizeBranchGcApply, sweepStaleDaemonRegistry, sweepStaleRuntimeMetas, syncDeviceMirror, tenantScope, toMcpEvent, toWebhookEnvelope, toWorktreeStatusView, trackWorktreeProvision, turnToActivities, unlinkDaemonRegistryEntry, unlinkRuntimeMeta, untilForTtl, updateHarnessPreset, upsertSandboxLedger, userPresetsPath, validateAgainstInputSchema, verifyCallback, verifyInboundSignature, verifySignedAttestation, webSearchTool, webhookRequestId, wireSessionFollow, withBranchGcApplySummary, withPr, withPrStatus, workflowToActivities, writeDaemonRegistryEntry, writeSessionIndex };
70908
71209
  //# sourceMappingURL=index.mjs.map
70909
71210
  //# sourceMappingURL=index.mjs.map