@agentproto/runtime 5.5.0 → 5.7.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.d.ts CHANGED
@@ -3,8 +3,8 @@ import { h as WorktreeIsolationMode, i as SpawnAttachMode, j as SpawnDedupeMode,
3
3
  export { k as DEFAULT_MODEL_ROLES, M as MODEL_ROLE_REF_PREFIX, l as ModelRoleContext, m as ModelRoleEntry, n as ModelRoleSource, o as ModelRoleValue, p as ModelRolesConfig, q as listModelRoles, r as parseModelRoleRef, s as resolveModelRole } from './config-Gz7q9yfJ.js';
4
4
  import { B as BuildHeartbeatAgent } from './heartbeat-BJtxbDb9.js';
5
5
  export { H as HeartbeatAgent, a as HeartbeatRunner, R as RuntimeEvent, b as RuntimeEvents, p as parseDuration } from './heartbeat-BJtxbDb9.js';
6
- import { M as MessageUrgency, S as SessionEvent, a as SessionEventType, b as SessionEventBus, c as SessionsRegistry, C as CompletionPolicySupervisor, T as TaskLedger, d as SessionDescriptor, e as SessionEndReason, A as ActivityPolicySlice, f as ActivityListFilter, g as ActivityRecord, h as ActivityTurnSession, i as ActivityPrSession, j as ActivityWorkflowRunSlice, P as PrResolvedState, k as ActivityTaskSlice, W as WorktreeProvisioner, l as AgentsMdResolution, U as UserPreset, R as RestartPolicy, m as SandboxAppServeSpec, n as WorktreeField, o as AgentSessionLike, p as UsageReadContext, q as UsageReadResult, r as MessageKind, s as SessionMessage, t as AgentStreamEvent, u as SessionUsage, v as ToolCallRecord, w as StatsSessionDescriptor, x as ProcRow, y as ProvisionInFlight, z as ProvisionTracker, B as UsageRollup, D as RemainingQuotaReader, Q as QuotaReadableProfile, E as UsageSnapshotRecord, F as SessionAwaitingQuestion, G as PolicyRunState, H as PtyFactory, I as WorktreeAutoReclaimer } from './sessions-DMzCgTVy.js';
7
- export { J as ActivityKind, K as ActivitySource, L as ActivityState, N as ActivityWaitingOn, O as AnthropicReaderConfig, V as AnthropicRemainingQuotaReader, X as AttachPolicyInput, Y as CommandGroupStats, Z as CommitSpec, _ as DEFAULT_WORKTREE_ISOLATION, $ as DEFAULT_WORKTREE_PROVISION_CONCURRENCY, a0 as EagerResumeFailReason, a1 as EagerResumeOutcome, a2 as EagerResumeSkipReason, a3 as GateSpec, a4 as HostInfo, a5 as JudgeGateSpec, a6 as LabeledProcessStatsReport, a7 as LabeledSessionStats, a8 as MAX_MESSAGE_DATA_BYTES, a9 as MESSAGE_KINDS, aa as MESSAGE_PREAMBLE, ab as MESSAGE_TAG, ac as MESSAGE_URGENCIES, ad as MessageDeliveryVia, ae as MessageFilter, af as MessageRelation, ag as MessageTreeNode, ah as OnFailSpec, ai as OrphanGroup, aj as PendingPermission, ak as PermissionRespondInput, al as PermissionRespondResult, am as PolicyRunStatus, an as PricingResolver, ao as ProcessDetail, ap as ProcessStatsReport, aq as ProcessStatsService, ar as QuotaStoreFile, as as QuotaStoreOptions, at as RegisterBrowserInput, au as RegisterSessionInput, av as RemainingQuota, aw as ResourceStats, ax as ResumeDisabledError, ay as SESSION_END_REASONS, az as SESSION_ID_ENV, aA as SessionCurrentPhase, aB as SessionKind, aC as SessionMessageFrom, aD as SessionOutcome, aE as SessionOutcomeArtifact, aF as SessionOutcomeCompact, aG as SessionOutcomeLink, aH as SessionResourceStats, aI as SessionSnapshots, aJ as SessionStatus, aK as ShellGateSpec, aL as SpawnAgentInput, aM as SpawnSessionInput, aN as StatsDetail, aO as StoredProfileQuota, aP as TASK_STATUSES, aQ as TaskCaller, aR as TaskChangedEvent, aS as TaskClaimInput, aT as TaskCreateInput, aU as TaskGateOutcome, aV as TaskGateRunner, aW as TaskLedgerRegistry, aX as TaskLedgerSessionSlice, aY as TaskListFilter, aZ as TaskRecord, a_ as TaskStatus, a$ as TaskUpdateInput, b0 as TaskVerification, b1 as TaskVerifySupervisor, b2 as TaskWriteResult, b3 as TokenPricing, b4 as UsageBucket, b5 as UsageComputeInput, b6 as UsageDetail, b7 as UsageSource, b8 as UserPresetsFile, b9 as WORKSPACE_SLUG_ENV, ba as WORKTREE_ISOLATION_ENV, bb as WORKTREE_PROVISION_CONCURRENCY_ENV, bc as WorktreeDecision, bd as WorktreeProvisionOutcome, be as WorktreeProvisionPhase, bf as WorktreeProvisionProgress, bg as WorktreeProvisionRequest, bh as WorktreeRequest, bi as activityCounts, bj as compactOutcome, bk as createProcessStatsService, bl as createSessionMessage, bm as createSupervisorTaskGateRunner, bn as createTaskLedger, bo as decideWorktreeIsolation, bp as deleteUserPreset, bq as deriveSessionOutcome, br as deriveSessionUsage, bs as escapeHumanPrompt, bt as escapeMessageBody, bu as filterActivities, bv as getProcessStatsService, bw as getUserPreset, bx as isClosedTaskStatus, by as isKnownSessionEndReason, bz as isMessageAllowed, bA as isProviderLimitError, bB as isTerminalActivityState, bC as listUserPresets, bD as loadQuotaStore, bE as loadUserPresets, bF as loadWorktreeIsolation, bG as matchesMessageFilter, bH as messageFrom, bI as mintMessageId, bJ as normalizeCommand, bK as normalizeWorktreeField, bL as parseAnthropicRateLimitHeaders, bM as parseTaskStatus, bN as parseWindow, bO as parseWorktreeIsolationMode, bP as pickUsageDetail, bQ as policyToActivities, bR as policyWatchesSession, bS as prToActivities, bT as projectSessionUsage, bU as readProfileQuota, bV as recordProfileQuota, bW as renderInboxDigest, bX as renderSessionMessage, bY as renderSessionMessages, bZ as resolveRelation, b_ as rollupUsage, b$ as sanitizeLabel, c0 as saveUserPreset, c1 as trackWorktreeProvision, c2 as turnToActivities, c3 as userPresetsPath, c4 as workflowToActivities } from './sessions-DMzCgTVy.js';
6
+ import { M as MessageUrgency, S as SessionEvent, a as SessionEventType, b as SessionEventBus, c as SessionsRegistry, C as CompletionPolicySupervisor, T as TaskLedger, d as SessionDescriptor, e as SessionEndReason, A as ActivityPolicySlice, f as ActivityListFilter, g as ActivityRecord, h as ActivityTurnSession, i as ActivityPrSession, j as ActivityWorkflowRunSlice, P as PrResolvedState, k as ActivityTaskSlice, W as WorktreeProvisioner, l as AgentsMdResolution, U as UserPreset, R as RestartPolicy, m as SandboxAppServeSpec, n as WorktreeField, o as AgentSessionLike, p as UsageReadContext, q as UsageReadResult, r as MessageKind, s as SessionMessage, t as AgentStreamEvent, u as SessionUsage, v as ToolCallRecord, w as StatsSessionDescriptor, x as ProcRow, y as ProvisionInFlight, z as ProvisionTracker, B as UsageRollup, D as RemainingQuotaReader, Q as QuotaReadableProfile, E as UsageSnapshotRecord, F as SessionAwaitingQuestion, G as PolicyRunState, H as PtyFactory, I as WorktreeAutoReclaimer } from './sessions-DHSLsPHA.js';
7
+ export { J as ActivityKind, K as ActivitySource, L as ActivityState, N as ActivityWaitingOn, O as AnthropicReaderConfig, V as AnthropicRemainingQuotaReader, X as AttachPolicyInput, Y as CommandGroupStats, Z as CommitSpec, _ as DEFAULT_WORKTREE_ISOLATION, $ as DEFAULT_WORKTREE_PROVISION_CONCURRENCY, a0 as EagerResumeFailReason, a1 as EagerResumeOutcome, a2 as EagerResumeSkipReason, a3 as GateSpec, a4 as HostInfo, a5 as JudgeGateSpec, a6 as LabeledProcessStatsReport, a7 as LabeledSessionStats, a8 as MAX_MESSAGE_DATA_BYTES, a9 as MESSAGE_KINDS, aa as MESSAGE_PREAMBLE, ab as MESSAGE_TAG, ac as MESSAGE_URGENCIES, ad as MessageDeliveryVia, ae as MessageFilter, af as MessageRelation, ag as MessageTreeNode, ah as OnFailSpec, ai as OrphanGroup, aj as PendingPermission, ak as PermissionRespondInput, al as PermissionRespondResult, am as PolicyRunStatus, an as PricingResolver, ao as ProcessDetail, ap as ProcessStatsReport, aq as ProcessStatsService, ar as QuotaStoreFile, as as QuotaStoreOptions, at as RegisterBrowserInput, au as RegisterSessionInput, av as RemainingQuota, aw as ResourceStats, ax as ResumeDisabledError, ay as SESSION_END_REASONS, az as SESSION_ID_ENV, aA as SessionCurrentPhase, aB as SessionKind, aC as SessionMessageFrom, aD as SessionOutcome, aE as SessionOutcomeArtifact, aF as SessionOutcomeCompact, aG as SessionOutcomeLink, aH as SessionResourceStats, aI as SessionSnapshots, aJ as SessionStatus, aK as ShellGateSpec, aL as SpawnAgentInput, aM as SpawnSessionInput, aN as StatsDetail, aO as StoredProfileQuota, aP as TASK_STATUSES, aQ as TaskCaller, aR as TaskChangedEvent, aS as TaskClaimInput, aT as TaskCreateInput, aU as TaskGateOutcome, aV as TaskGateRunner, aW as TaskLedgerRegistry, aX as TaskLedgerSessionSlice, aY as TaskListFilter, aZ as TaskRecord, a_ as TaskStatus, a$ as TaskUpdateInput, b0 as TaskVerification, b1 as TaskVerifySupervisor, b2 as TaskWriteResult, b3 as TokenPricing, b4 as UsageBucket, b5 as UsageComputeInput, b6 as UsageDetail, b7 as UsageSource, b8 as UserPresetsFile, b9 as WORKSPACE_SLUG_ENV, ba as WORKTREE_ISOLATION_ENV, bb as WORKTREE_PROVISION_CONCURRENCY_ENV, bc as WorktreeDecision, bd as WorktreeProvisionOutcome, be as WorktreeProvisionPhase, bf as WorktreeProvisionProgress, bg as WorktreeProvisionRequest, bh as WorktreeRequest, bi as activityCounts, bj as compactOutcome, bk as createProcessStatsService, bl as createSessionMessage, bm as createSupervisorTaskGateRunner, bn as createTaskLedger, bo as decideWorktreeIsolation, bp as deleteUserPreset, bq as deriveSessionOutcome, br as deriveSessionUsage, bs as escapeHumanPrompt, bt as escapeMessageBody, bu as filterActivities, bv as getProcessStatsService, bw as getUserPreset, bx as isClosedTaskStatus, by as isKnownSessionEndReason, bz as isMessageAllowed, bA as isProviderLimitError, bB as isTerminalActivityState, bC as listUserPresets, bD as loadQuotaStore, bE as loadUserPresets, bF as loadWorktreeIsolation, bG as matchesMessageFilter, bH as messageFrom, bI as mintMessageId, bJ as normalizeCommand, bK as normalizeWorktreeField, bL as parseAnthropicRateLimitHeaders, bM as parseTaskStatus, bN as parseWindow, bO as parseWorktreeIsolationMode, bP as pickUsageDetail, bQ as policyToActivities, bR as policyWatchesSession, bS as prToActivities, bT as projectSessionUsage, bU as readProfileQuota, bV as recordProfileQuota, bW as renderInboxDigest, bX as renderSessionMessage, bY as renderSessionMessages, bZ as resolveRelation, b_ as rollupUsage, b$ as sanitizeLabel, c0 as saveUserPreset, c1 as trackWorktreeProvision, c2 as turnToActivities, c3 as userPresetsPath, c4 as workflowToActivities } from './sessions-DHSLsPHA.js';
8
8
  import { R as RouteSpec, P as Posture, C as ContextProfile, a as CanonicalPosture } from './session-config-DxIIuJFY.js';
9
9
  export { A as AuthMethod, D as DeclaredAdapterMode, E as EffortLevel, S as SessionConfig, c as composeMode, d as decomposeMode } from './session-config-DxIIuJFY.js';
10
10
  import { AcpMcpServer } from '@agentproto/acp';
@@ -328,6 +328,46 @@ declare class TunnelRegistry {
328
328
  * here rather than the other way around.
329
329
  */
330
330
 
331
+ /**
332
+ * One normalized immutable fact, emitted by a provider and landed into a
333
+ * session's inbox. CloudEvents 1.0 structured JSON plus agentproto extension
334
+ * attributes (`summary`, `subjects`, `terminal`, `consumerref`, `seq`).
335
+ *
336
+ * `type` grammar: `<scheme>.<object>.<action>` (e.g.
337
+ * `github.pull_request.closed`). `subject` grammar: `<scheme>:<path>` (e.g.
338
+ * `github:agentproto/ts#1428`). `subjects` is the full hierarchy, most
339
+ * specific first — a sentinel `subject` ending in `*` prefix-matches it.
340
+ */
341
+ interface SentinelEvent {
342
+ readonly specversion: "1.0";
343
+ /** Stable across retries/redeliveries. Idempotency key is `(sentinelId,
344
+ * event.id)` — unaffected by `SentinelSpec.match` fan-out: an event that
345
+ * happens to satisfy more than one match clause on the same sentinel is
346
+ * still landed at most once. */
347
+ readonly id: string;
348
+ /** URI naming the provider instance that emitted this event. */
349
+ readonly source: string;
350
+ readonly type: string;
351
+ /** Primary (most specific) subject this event is filed under. */
352
+ readonly subject: string;
353
+ /** ISO-8601. */
354
+ readonly time: string;
355
+ readonly datacontenttype: "application/json";
356
+ /** Normalized projection, <= 32 KiB. Raw provider payloads never appear
357
+ * here. */
358
+ readonly data: Record<string, unknown>;
359
+ /** One line, used verbatim as inbox text (after a `[<scheme>]` prefix). */
360
+ readonly summary: string;
361
+ /** Full subject hierarchy, most specific first. */
362
+ readonly subjects: readonly string[];
363
+ /** Ends the subject's lifecycle when `spec.until.kind === "subject_terminal"`. */
364
+ readonly terminal: boolean;
365
+ /** Opaque consumer reference the provider was asked to stamp (agentpush's
366
+ * `consumerRef`), when applicable. */
367
+ readonly consumerref?: string;
368
+ /** Monotonic sequence, when the provider assigns one. */
369
+ readonly seq?: number;
370
+ }
331
371
  /** When a sentinel stops watching. */
332
372
  type SentinelUntil = {
333
373
  kind: "subject_terminal";
@@ -415,6 +455,14 @@ interface SentinelSpec {
415
455
  * Writes are atomic (write to a per-process tmp file, then rename), same
416
456
  * idiom as `sandbox-ledger.ts` — a crash mid-write must never leave a
417
457
  * corrupt `sentinels.json` behind.
458
+ *
459
+ * Secret-at-rest (W-B): a `webhook` target's signing secret never lives
460
+ * inside the `Sentinel` record (whose `spec` is echoed verbatim by views) —
461
+ * it is kept in a sidecar row keyed by an opaque `secretRef` handle,
462
+ * persisted to `sentinels-secrets.json` next to `sentinels.json` with the
463
+ * SAME 0600 plaintext-at-rest tradeoff every other credential store in this
464
+ * runtime commits to (`handle.state`, `makeCredsStore` family files). Keys
465
+ * are never logged; the delivery path is the only consumer of the sidecar.
418
466
  */
419
467
 
420
468
  type SentinelStatus = "active" | "paused" | "expired" | "orphaned" | "error";
@@ -2274,6 +2322,21 @@ interface SpawnAgentSessionInput {
2274
2322
  harness?: string;
2275
2323
  cwd?: string;
2276
2324
  workspaceSlug?: string;
2325
+ /** CONTROLLER-side marker (issue #1647): set ONLY by the device-sandbox
2326
+ * proxy path when the controller dials the TARGET daemon's own
2327
+ * `agent_start` through the `/device-spawn` bridge (the bridge carries
2328
+ * no ambient marker paths — the controller-side spawn already knows
2329
+ * which spawns cross a device). On the TARGET daemon this marks the
2330
+ * spawn as arriving "through the bridge", so an unresolvable
2331
+ * `workspaceSlug` there fails loudly with the slug + the target's known
2332
+ * slugs instead of silently falling through to the active workspace.
2333
+ * NEVER set (never expose) on a local spawn — local fallback semantics
2334
+ * are deliberately unchanged. Stripped by the controller before the
2335
+ * inner `agent_start` call (the target's own schema has no such field;
2336
+ * an unknown extra key there would 400 an otherwise-fine spawn). Controller
2337
+ * input arriving with this field is consumed immediately (read + delete,
2338
+ * never an error) so it can't leak into spawn defaults or the registry. */
2339
+ deviceBridge?: boolean;
2277
2340
  /** Trusted-loopback parent-lineage hint (WP-R1). Attributes this spawn to a
2278
2341
  * logical parent session so it nests under that node in the sessions tree,
2279
2342
  * filling the gap that otherwise leaves an anonymous `agent_start` (an
@@ -6404,15 +6467,28 @@ declare function readUsageSnapshots(sessionId: string, baseDir?: string): Promis
6404
6467
  * method, since sentinel creation also needs the provider handle.
6405
6468
  */
6406
6469
 
6470
+ /** The wire view of a target: for a `webhook` target this is the REDACTED
6471
+ * shape — `url` yes, plus `hasSecret:true`/`secretRedacted:true`. The
6472
+ * secret material (or even its `secretRef` handle) NEVER crosses a
6473
+ * listing/get view (plan §4 W-B task 4 — code-verified leak closed here). */
6474
+ type SentinelTargetView = Exclude<SentinelTarget, {
6475
+ kind: "webhook";
6476
+ }> | {
6477
+ kind: "webhook";
6478
+ url: string;
6479
+ hasSecret: true;
6480
+ secretRedacted: true;
6481
+ };
6407
6482
  /** Compact wire view of a sentinel for tool/HTTP results — the internal-only
6408
- * fields (`handle`, `seen`, `terminalSubjects`) never leave the daemon. */
6483
+ * fields (`handle`, `seen`, `terminalSubjects`) and any secret material
6484
+ * never leave the daemon. */
6409
6485
  interface SentinelView {
6410
6486
  id: string;
6411
6487
  provider: string;
6412
6488
  status: SentinelStatus;
6413
6489
  match: SentinelMatchClause[];
6414
6490
  until: SentinelUntil;
6415
- target: SentinelTarget;
6491
+ target: SentinelTargetView;
6416
6492
  group?: string;
6417
6493
  label?: string;
6418
6494
  createdTs: number;
@@ -6421,6 +6497,390 @@ interface SentinelView {
6421
6497
  lastError?: string;
6422
6498
  }
6423
6499
 
6500
+ /**
6501
+ * Standard Webhooks `whsec_` signing for webhook egress (W-A of
6502
+ * `.plans/sentinel-mcp-events/PLAN.md`).
6503
+ *
6504
+ * Contract (frozen §3):
6505
+ * - HMAC-SHA256 over `msgId.timestamp.body` (raw bytes; `.update` chained so
6506
+ * the body is never re-encoded — payload arrives as `Uint8Array`, I2).
6507
+ * - Signature print = standard base64 (NOT base64url): `v1,<b64>`.
6508
+ * - HMAC key = the base64 payload DECODED after the `whsec_` prefix.
6509
+ * - Multi-secret: space-separated `v1,<sig>` segments (rotation window).
6510
+ * - Returns ONLY headers — the caller owns the bytes and signs them again
6511
+ * with a fresh timestamp on retry; signing never re-serializes.
6512
+ */
6513
+ interface WebhookSignInput {
6514
+ /** Stable event id (`evt_…` / verification `msg_verification_…`) — same across retries. */
6515
+ msgId: string;
6516
+ /** Seconds, Unix epoch (Standard Webhooks wire format). */
6517
+ timestamp: number;
6518
+ /** Exact bytes — signed once (I2). Caller passes the serialization; signing never re-serializes. */
6519
+ payload: Uint8Array;
6520
+ /** One or, during a rotation window, two secrets (`whsec_…`). */
6521
+ secrets: readonly string[];
6522
+ }
6523
+ type WebhookSignatureHeaders = {
6524
+ "webhook-id": string;
6525
+ "webhook-timestamp": string;
6526
+ "webhook-signature": string;
6527
+ };
6528
+ /**
6529
+ * Encode raw secret bytes into the `whsec_<base64>` wire format.
6530
+ * Inverse of {@link decodeWhsecSecret}.
6531
+ */
6532
+ declare function encodeWhsecSecret(raw: Uint8Array): string;
6533
+ /**
6534
+ * Decode a `whsec_…` secret to its raw HMAC key: standard-base64 payload
6535
+ * after the prefix, which must decode to 24..64 bytes. Returns `null` on any
6536
+ * violation (bad prefix, not base64, length out of range). The canonical
6537
+ * validator for W-C: a submit failing this is `-32602` upstream; egress
6538
+ * surfaces it as a categorized challenge failure.
6539
+ */
6540
+ declare function decodeWhsecSecret(secret: string): Buffer | null;
6541
+ /**
6542
+ * Sign exactly the bytes given. Throws `Error` when any secret fails
6543
+ * {@link decodeWhsecSecret} (callers must have validated upstream; a bad
6544
+ * secret at this point is a programmer error, never silently signed).
6545
+ */
6546
+ declare function signWebhook(input: WebhookSignInput): WebhookSignatureHeaders;
6547
+
6548
+ /**
6549
+ * SSRF-guarded outbound HTTPS POST for webhook egress (W-A of
6550
+ * `.plans/sentinel-mcp-events/PLAN.md`).
6551
+ *
6552
+ * Frozen failure-mode reasons: `non_https | private_target | redirect |
6553
+ * timeout | connect` — mapped by challenge to the §3 ChallengeFailureReason
6554
+ * table; the SAME function guards BOTH the challenge and delivery path (I3).
6555
+ * No HTTP client library addition: node http/https only.
6556
+ *
6557
+ * Safety model (one predicate, fail closed):
6558
+ * 1. scheme must be https → `non_https`
6559
+ * 2. ALL DNS-resolved addresses (A + AAAA, plus literal-IP hosts) must pass
6560
+ * {@link isPubliclyRoutable}, else `private_target` — one rejected
6561
+ * address fails; unparseable/odd literals fail closed
6562
+ * 3. connect pins the VALIDATED IP (no second resolution → the
6563
+ * DNS-rebinding TOCTOU is closed) while `servername` keeps the ORIGINAL
6564
+ * hostname for TLS SNI + certificate verification
6565
+ * 4. redirects are never followed: a 3xx comes back as a plain
6566
+ * `{status: 3xx}` result (challenge → "non_2xx", delivery → retryable);
6567
+ * a non-https redirect target additionally throws `redirect`
6568
+ * 5. hard `timeoutMs` budget; request body clamped to 256 KiB here too
6569
+ * (defense-in-depth — delivery clamps before signing)
6570
+ */
6571
+ type SsrfFetchReason = "non_https" | "private_target" | "redirect" | "timeout" | "connect";
6572
+ declare class SsrfFetchError extends Error {
6573
+ readonly reason: SsrfFetchReason;
6574
+ constructor(reason: SsrfFetchReason, message: string);
6575
+ }
6576
+ interface SsrfFetchInit {
6577
+ method?: "POST";
6578
+ headers?: Record<string, string>;
6579
+ /** ≤ 262 144; enforced also on response read (only status + body read). */
6580
+ body?: Uint8Array;
6581
+ timeoutMs: number;
6582
+ }
6583
+ interface SsrfFetchResult {
6584
+ status: number;
6585
+ body: string;
6586
+ }
6587
+ /**
6588
+ * The one predicate for every address this module may connect to. Fails
6589
+ * closed — anything unparseable, IPv4-mapped with an invalid embedded v4, or
6590
+ * inside a non-globally-routable block is NOT public.
6591
+ *
6592
+ * Plan §4 W-A.2 ranges:
6593
+ * IPv4 — 0/8, 10/8, 127/8, 169.254/16, 172.16/12, 192.0.0.0/24,
6594
+ * 192.0.2.0/24, 198.18/15, 198.51.100.0/24, 203.0.113.0/24,
6595
+ * 100.64/10 (CGNAT), 224/4 (multicast), 240/4 (reserved)
6596
+ * IPv6 — ::, ::1, fc00::/7 (ULA), fe80::/10 (link-local),
6597
+ * ff00::/8 (multicast), 2001:db8::/32 (doc range), and ::ffff:
6598
+ * mapped-v4 whose EMBEDDED v4 re-runs this very predicate
6599
+ */
6600
+ declare function isPubliclyRoutable(ipRaw: string): boolean;
6601
+ type SsrfResolvers = {
6602
+ /** Replaces both A and AAAA resolution. Returns every address, any family. */
6603
+ lookup?: (host: string) => Promise<Array<{
6604
+ address: string;
6605
+ family: 4 | 6;
6606
+ }>>;
6607
+ };
6608
+ type EgressDispatcher = (req: {
6609
+ url: string;
6610
+ headers: Record<string, string>;
6611
+ body?: Uint8Array;
6612
+ timeoutMs: number;
6613
+ }) => Promise<SsrfFetchResult>;
6614
+ /** vitest-only: set a recording dispatcher; pass `null` to restore. */
6615
+ declare function setEgressDispatcherForTests(dispatcher: EgressDispatcher | null): void;
6616
+ declare function ssrfFetch(url: string, init: SsrfFetchInit, io?: {
6617
+ resolvers?: SsrfResolvers;
6618
+ }): Promise<SsrfFetchResult>;
6619
+
6620
+ /**
6621
+ * Callback challenge verification (W-A of `.plans/sentinel-mcp-events/PLAN.md`,
6622
+ * §3 frozen): POST `{"type":"verification","challenge":"<fresh 64-hex>"}` to
6623
+ * the candidate callback URL, signed with the CANDIDATE secret, carrying
6624
+ * `X-MCP-Subscription-Id`; require 2xx and a constant-time-equal
6625
+ * `{"challenge":"<same>"}` echo in the response body.
6626
+ *
6627
+ * Success cache: keyed (principal, normalized callback URL, sha256(secret)),
6628
+ * bounded TTL 10 min. A NEW secret during rotation NEVER resolves a cache
6629
+ * hit — the sha256(secret) key component structurally forces
6630
+ * re-verification (the cache can never bless an unverified secret).
6631
+ *
6632
+ * The outbound POST runs through the SAME `ssrfFetch` gate as delivery (I3) —
6633
+ * injectable here only for tests; production passes nothing.
6634
+ */
6635
+
6636
+ type ChallengeOutcome = {
6637
+ ok: true;
6638
+ verificationBytes: Uint8Array;
6639
+ } | {
6640
+ ok: false;
6641
+ reason: ChallengeFailureReason;
6642
+ detail: string;
6643
+ };
6644
+ type ChallengeFailureReason = "challenge_failed" | "timeout" | "non_https" | "ssrf_blocked" | "non_2xx";
6645
+ interface VerifyCallbackInput {
6646
+ principal: string;
6647
+ url: string;
6648
+ subscriptionId: string;
6649
+ secret: string;
6650
+ }
6651
+ interface VerifyCallbackDeps {
6652
+ /** Replaces the POST boundary. Default: the shared `ssrfFetch` gate. */
6653
+ fetch?: (url: string, init: SsrfFetchArgs$1) => Promise<SsrfFetchView>;
6654
+ /** Clock for the bounded TTL. Default: real wall clock. */
6655
+ now?: () => number;
6656
+ }
6657
+ interface SsrfFetchArgs$1 {
6658
+ method?: "POST";
6659
+ headers?: Record<string, string>;
6660
+ body?: Uint8Array;
6661
+ timeoutMs: number;
6662
+ }
6663
+ interface SsrfFetchView {
6664
+ status: number;
6665
+ body: string;
6666
+ }
6667
+ /** §4 W-A task 4: the challenge reason table (single mapped, none unmapped). */
6668
+ declare function challengeReasonForSsrf(reason: SsrfFetchReason): ChallengeFailureReason;
6669
+ declare function challengeCacheSize(): number;
6670
+ /** vitest-only: clear the success cache between suites. */
6671
+ declare function resetChallengeCacheForTests(): void;
6672
+ /** Cache-key URL normalization (never reused for anything else). */
6673
+ declare function normalizeCallbackUrl(url: string): string | null;
6674
+ declare function verifyCallback(input: VerifyCallbackInput, deps?: VerifyCallbackDeps): Promise<ChallengeOutcome>;
6675
+
6676
+ /**
6677
+ * Signed event delivery with bounded retry (W-A of
6678
+ * `.plans/sentinel-mcp-events/PLAN.md`, §3 frozen).
6679
+ *
6680
+ * I2 — the body is serialized ONCE: the clamp (when needed) happens first,
6681
+ * then the exact bytes are signed per attempt with a FRESH timestamp. An
6682
+ * observer sees a different `webhook-signature` header per attempt while the
6683
+ * body bytes stay bitwise identical — `signWebhook` returns ONLY headers and
6684
+ * never re-serializes.
6685
+ *
6686
+ * ≤ 256 KiB — when the serialized body exceeds 262 144 bytes, `data` is
6687
+ * replaced with `{summary, subject}` and the envelope gains `truncated: true`
6688
+ * (no read tool — plan §5), and the CLAMPED bytes (not the original) are what
6689
+ * every attempt signs.
6690
+ *
6691
+ * Retry — exponential backoff bounded to 5 attempts; 3xx / other 4xx / 5xx /
6692
+ * network errors retry; 410/413 are terminal with NO further attempt;
6693
+ * 2xx = delivered. The returned `DeliveryState` is what the caller persists
6694
+ * into the store for post-restart resume (W-B's job to wire).
6695
+ */
6696
+ type McpEventEnvelope = {
6697
+ /** OpenAI doc wire shape VERBATIM (developers.openai.com/plugins/build/mcp-events):
6698
+ * `eventId` (NOT `id` — the `webhook-id` header carries eventId), `name`,
6699
+ * `timestamp`, `data`, `cursor`. A top-level `type` field = protocol
6700
+ * control notification only — never sent by us (no control events). */
6701
+ eventId: string;
6702
+ name: string;
6703
+ timestamp: string;
6704
+ data: Record<string, unknown>;
6705
+ cursor: string | null;
6706
+ truncated?: boolean;
6707
+ };
6708
+ interface DeliveryState {
6709
+ attempts: number;
6710
+ lastError?: string;
6711
+ lastAt?: string;
6712
+ }
6713
+ interface DeliveryReplay {
6714
+ subId: string;
6715
+ callbackUrl: string;
6716
+ secrets: readonly string[];
6717
+ }
6718
+ /** One event → one POST. Frozen §3 outcome. */
6719
+ type DeliveryOutcome = {
6720
+ ok: true;
6721
+ delivery: DeliveryState;
6722
+ } | {
6723
+ ok: false;
6724
+ reason: string;
6725
+ delivery: DeliveryState;
6726
+ };
6727
+ interface SsrfFetchArgs {
6728
+ method?: "POST";
6729
+ headers?: Record<string, string>;
6730
+ body?: Uint8Array;
6731
+ timeoutMs: number;
6732
+ }
6733
+ interface DeliverEventDeps {
6734
+ /** Replaces the POST boundary (tests only). Default: the shared `ssrfFetch` gate. */
6735
+ fetch?: (url: string, init: SsrfFetchArgs) => Promise<{
6736
+ status: number;
6737
+ body: string;
6738
+ }>;
6739
+ /** Backoff sleep (tests only). Default: real `setTimeout`. */
6740
+ sleep?: (ms: number) => Promise<void>;
6741
+ /** Clock (tests only). Default: real wall clock. */
6742
+ now?: () => number;
6743
+ }
6744
+ declare const CLAMP_LIMIT_BYTES = 262144;
6745
+ declare const MAX_ATTEMPTS = 5;
6746
+ /** Bounded exponential backoff: 250, 500, 1000, 2000, capped at 4000 (attempt ≥ 4). */
6747
+ declare function deliveryBackoffDelay(attempt: number): number;
6748
+ declare function serializeEnvelope(envelope: McpEventEnvelope): Uint8Array;
6749
+ /** Serialize once; over-size → `{summary, subject}` + `truncated:true` (§3). */
6750
+ declare function envelopeClampedBytes(event: McpEventEnvelope): {
6751
+ bytes: Uint8Array;
6752
+ clamped: boolean;
6753
+ };
6754
+ declare function deliverEventEnvelope(replay: DeliveryReplay, event: McpEventEnvelope, deps?: DeliverEventDeps): Promise<DeliveryOutcome>;
6755
+
6756
+ /**
6757
+ * SentinelWebhookOutbox — the PERSISTED outbox for `webhook`-target sentinel
6758
+ * events (W-B of `.plans/sentinel-mcp-events/PLAN.md`, §4 task 3).
6759
+ *
6760
+ * Why an outbox: the runtime's `processEvents` marks an event `seen` the
6761
+ * moment in-process handling resolves, but a webhook POST is an EXTERNAL
6762
+ * delivery — a crash between ack and delivery loses the event forever (I4).
6763
+ * So the webhook fire path appends a DURABLE row first:
6764
+ *
6765
+ * `{sentinelId, requestId, eventId, bodyBytes, cursor:null,
6766
+ * deliveryState, status: pending|delivered|dead}`
6767
+ *
6768
+ * with `bodyBytes` = the EXACT canonical body bytes that will be sent (I2 —
6769
+ * the envelope is serialized once here via `serializeEnvelope`; the dispatch
6770
+ * re-signs those same bytes, and `deliverEventEnvelope`'s internal
6771
+ * serialization is deterministic over the stored envelope — asserted by
6772
+ * tests). The underlying sentinel event is marked seen/acked ONLY when the
6773
+ * row reaches terminal status (`delivered`, or `dead` per the retry cap /
6774
+ * age-out); a dispatch that THREW (crash-shaped) leaves the row `pending`,
6775
+ * the event UN-acked, and a restart re-dispatches it by exact bytes.
6776
+ *
6777
+ * Ordering across events of one subscription is never assumed (I5). Rows
6778
+ * reaped once `delivered` for 24 h; pending rows age out after 7 d (plan
6779
+ * risk table); the file is capped. Feedback-loop guard is data, not policy:
6780
+ * the `ssrfFetch` gate inside `deliverEventEnvelope` inherently blocks
6781
+ * loopback/private delivery targets, so nothing here can ring back into our
6782
+ * own inbound routes — self-delivery cannot even connect.
6783
+ */
6784
+
6785
+ type SentinelWebhookOutboxStatus = "pending" | "delivered" | "dead";
6786
+ interface SentinelWebhookOutboxRow {
6787
+ sentinelId: string;
6788
+ /** Deterministic sub id over `(sentinelId, eventId)` — stable across
6789
+ * restarts (I1: a redelivery is a consumer no-op; the wire `webhook-id`
6790
+ * header stays the EVENT id). */
6791
+ requestId: string;
6792
+ eventId: string;
6793
+ /** The EXACT body bytes, as sent — utf-8 base64 of `serializeEnvelope`
6794
+ * (I2: bytes stored exactly as sent; resume dispatches the stored bytes). */
6795
+ bodyBytes: string;
6796
+ /** v1 events are non-replayable (plan §2) — always null. */
6797
+ cursor: null;
6798
+ /** Persisted W-A delivery state so a post-restart dispatch makes sense. */
6799
+ deliveryState: {
6800
+ attempts: number;
6801
+ lastError?: string;
6802
+ lastAt?: string;
6803
+ };
6804
+ status: SentinelWebhookOutboxStatus;
6805
+ /** The bounded-retry loop's final `ok:false` reason. */
6806
+ failReason?: string;
6807
+ /** Why the outbox itself went a row `dead` (`sentinel_expired`,
6808
+ * `sentinel_removed`, `age_out`). */
6809
+ deadReason?: string;
6810
+ createdAt: number;
6811
+ /** Wall-clock ms the row reached terminal status (drives reaping). */
6812
+ terminalAt?: number;
6813
+ }
6814
+ /** The full row is JSON-persisted; the envelope rides along so a resumed
6815
+ * dispatch re-delivers byte-identically without re-deriving the projection,
6816
+ * and the original event rides along for ack-time lifetime bookkeeping
6817
+ * (terminal flag / subject tracking). */
6818
+ type PersistedOutboxRow = SentinelWebhookOutboxRow & {
6819
+ envelope?: McpEventEnvelope;
6820
+ event?: SentinelEvent;
6821
+ };
6822
+ interface SentinelWebhookOutbox {
6823
+ /** Append a row for a matched webhook-delivery event. Idempotent per
6824
+ * `(sentinelId, eventId)`: an existing row (pending OR terminal) is never
6825
+ * duplicated — returns `undefined`, and for a terminal existing row
6826
+ * re-fires `onTerminal` so a lost ack (crash between the terminal
6827
+ * transition and the store write) still lands. Kicks dispatch off
6828
+ * asynchronously. */
6829
+ enqueue(input: {
6830
+ sentinelId: string;
6831
+ event: SentinelEvent;
6832
+ }): Promise<SentinelWebhookOutboxRow | undefined>;
6833
+ /** Dispatch every `pending` row (serialized, one POST in flight). Consults
6834
+ * `isExpired` per row AND the secrets sidecar BEFORE dispatch — an
6835
+ * expired or unwound sentinel never delivers another byte. */
6836
+ dispatch(): Promise<void>;
6837
+ /** Startup re-enqueue: re-dispatch every `pending` row by exact stored
6838
+ * bytes (no payload re-serialization on the resume path). */
6839
+ resumeDeliveries(): Promise<void>;
6840
+ /** Re-`delivered` rows after 24 h are reaped; pending rows age out after
6841
+ * 7 d (plan risk table). Cheap; called on the runtime's periodic tick. */
6842
+ sweep(): void;
6843
+ rows(): PersistedOutboxRow[];
6844
+ /** Synchronous flush for shutdown paths. */
6845
+ flushSync(): void;
6846
+ }
6847
+ interface SentinelWebhookOutboxOptions {
6848
+ /** Override persist path. Default `~/.agentproto/sentinel-webhook-outbox.json`. */
6849
+ filePath?: string;
6850
+ /** Injectable clock. */
6851
+ nowMs?: () => number;
6852
+ /** Debounce interval for disk persistence. Default 1500 ms. */
6853
+ debounceMs?: number;
6854
+ /** Disable disk persistence (unit tests). Default false unless filePath. */
6855
+ persist?: boolean;
6856
+ /** DI boundary (not module fakes): replaces W-A's `deliverEventEnvelope`
6857
+ * as the POST boundary. Throws = dispatch did not complete (row stays
6858
+ * pending, event stays un-acked). Default: the real deliverer. */
6859
+ deliverEvent?: (input: {
6860
+ replay: DeliveryReplay;
6861
+ row: PersistedOutboxRow;
6862
+ }) => Promise<DeliveryOutcome>;
6863
+ /** Signing secrets for a sentinel — `{subId, callbackUrl, secrets[]}`, or
6864
+ * null when the sentinel/secret sidecar is gone (row goes dead, never
6865
+ * silently lost). */
6866
+ secretsFor: (sentinelId: string) => DeliveryReplay | null;
6867
+ /** Expiry gate, consulted BEFORE every dispatch (plan §4 W-B task 2b).
6868
+ * true = the sentinel is past its `until` and must not deliver. */
6869
+ isExpired: (sentinelId: string) => boolean;
6870
+ /** The ack — mark the underlying event seen, after terminal status only. */
6871
+ onTerminal: (sentinelId: string, row: SentinelWebhookOutboxRow) => void;
6872
+ log?: (line: string) => void;
6873
+ }
6874
+ /** `sub_<hex32>` — deterministic over (sentinelId, eventId). */
6875
+ declare function webhookRequestId(sentinelId: string, eventId: string): `sub_${string}`;
6876
+ /** The CloudEvents → MCP-Events-envelope fusion this WP owns (W-C's adapter
6877
+ * becomes the canonical owner of the same mapping; this shape is the frozen
6878
+ * §3 wire envelope — insertion order stable, so its serialization is
6879
+ * byte-stable across restarts). `data` gains `subject`/`summary` so the
6880
+ * 256 KiB clamp's `{summary, subject}` replacement never goes blind. */
6881
+ declare function toWebhookEnvelope(event: SentinelEvent): McpEventEnvelope;
6882
+ declare function createSentinelWebhookOutbox(opts: SentinelWebhookOutboxOptions): SentinelWebhookOutbox;
6883
+
6424
6884
  /**
6425
6885
  * Smart default for `features.llmEndpoint` (daemon-managed-gateway): an
6426
6886
  * operator who already configured a named endpoint, an upstream credential
@@ -6559,6 +7019,110 @@ interface DeviceRegistry {
6559
7019
  forwardHttp(idOrName: string, req: ForwardHttpRequest): Promise<ForwardHttpResponse>;
6560
7020
  }
6561
7021
  declare function createDeviceRegistry(pairing: PairingRegistry, hosts?: HostRegistry): DeviceRegistry;
7022
+ /** The host-side route `promptHostSession` forwards to — served by the HOST
7023
+ * daemon's `/device-prompt/:sessionId` (http-server.ts), gated by the same
7024
+ * host-scoped-pairing + `deviceSpawnAllow` two-gate as `/device-spawn/*`. */
7025
+ declare const DEVICE_PROMPT_PATH_PREFIX = "/device-prompt";
7026
+ interface PromptHostSessionInput {
7027
+ /**
7028
+ * The turn to deliver — same shapes local `agent_prompt` accepts: a
7029
+ * non-empty string, a content block object, or a non-empty array of
7030
+ * content blocks. Validated here (never forwarded ill-formed).
7031
+ */
7032
+ prompt: unknown;
7033
+ /** When the host session is mid-turn, redirect instead of queueing
7034
+ * (mirrors local `agent_prompt`'s `interrupt`). Default false. */
7035
+ interrupt?: boolean;
7036
+ /** With a mid-turn session, jump the FRONT of the FIFO instead of the
7037
+ * back (mirrors local `agent_prompt`'s `force`). Default false. */
7038
+ force?: boolean;
7039
+ /** Block until the prompted turn drains (the session goes idle with an
7040
+ * empty queue) instead of fire-and-forget. Default false. */
7041
+ wait?: boolean;
7042
+ /** Poll cadence while `wait`ing, ms — clamped to [10, 10_000], default
7043
+ * 1_000. Each poll is a fresh E2E dial to the host, so don't set this
7044
+ * low in production; the clamp floor exists for tests. */
7045
+ pollMs?: number;
7046
+ /** Give up `wait`ing after this long (ms). 0 (default) = wait forever. */
7047
+ maxWaitMs?: number;
7048
+ /** Injectable delay for tests. Default a real setTimeout sleep. */
7049
+ sleep?: (ms: number) => Promise<void>;
7050
+ }
7051
+ interface PromptHostSessionResult {
7052
+ ok: boolean;
7053
+ /** The enqueue landed in the host session's FIFO (it was mid-turn) —
7054
+ * present on the fire-and-forget arm only. */
7055
+ pending?: boolean;
7056
+ queueId?: string;
7057
+ queuePosition?: number;
7058
+ /** Present on the `wait` arm: how long the turn took to drain. */
7059
+ waitedMs?: number;
7060
+ /** The host's HTTP status, when the enqueue itself failed. */
7061
+ status?: number;
7062
+ message?: string;
7063
+ }
7064
+ /**
7065
+ * Prompt a HOST device's session — the write counterpart of `device_sessions`
7066
+ * (BOOTSTRAP P4 item 1). Forwards `POST /device-prompt/:sessionId` over the
7067
+ * host's E2E channel (`HostRegistry.forwardHttp`, the same dial the read
7068
+ * verbs use); the host daemon, if it has opted in (`deviceSpawnAllow`) and
7069
+ * the pairing is host-scoped, calls its own `POST
7070
+ * /sessions/:id/prompt` — queueing rules identical to a local prompt.
7071
+ *
7072
+ * Fire-and-forget by default (the enqueue's 202 comes straight back);
7073
+ * `wait: true` then polls the host's `GET /sessions/:id` until the session
7074
+ * is idle with an empty queue (or dies, or `maxWaitMs` elapses). Never
7075
+ * silently serves stale data — a failed forward throws, there is no
7076
+ * snapshot fallback for a write.
7077
+ */
7078
+ declare function promptHostSession(hosts: HostRegistry | undefined, target: string, sessionId: string, input: PromptHostSessionInput): Promise<PromptHostSessionResult>;
7079
+ /** A narrow slice of the sessions registry `promptDeviceSession` needs —
7080
+ * kept minimal so tests stub one function. */
7081
+ interface DevicePromptSessionsLike {
7082
+ findByIdOrName(idOrName: string): {
7083
+ id: string;
7084
+ hostSessionId?: string;
7085
+ hostFingerprint?: string;
7086
+ } | undefined;
7087
+ }
7088
+ /** Is this failure the "the given session id doesn't exist on the host"
7089
+ * shape — the only case P7a's controller-id resolution may rescue? A
7090
+ * `no session "<id>"` envelope (the host's `enqueuePrompt` 404, the shape
7091
+ * behind the field finding's `{"ok":false,"status":404,…}`) is the match;
7092
+ * ANY other failure (pairing gate, wait arm, prompt validation) must pass
7093
+ * through untouched rather than get masked by a mapping retry. */
7094
+ declare function isNoSessionPromptFailure(result: PromptHostSessionResult): boolean;
7095
+ /** The controller→host mapping for one id, resolved against the LOCAL
7096
+ * registry — dial-free. Answers `kind: "controller"` only when a local
7097
+ * descriptor with that controller id carries BOTH `hostSessionId` AND a
7098
+ * device identity whose fingerprint-or-name belongs to the SAME target
7099
+ * device (exact-string when no `hosts` registry is wired — the raw
7100
+ * `device:<…>` target round-tripped; fingerprint-vs-name reversed against
7101
+ * the host records otherwise). Resolution order at the call site stays
7102
+ * (a) exact host-id first (promoted by the direct-attempt 404),
7103
+ * (b) this mapping second. */
7104
+ declare function resolveDevicePromptMapping(sessions: DevicePromptSessionsLike | undefined, hosts: HostRegistry | undefined, sessionId: string, target: string): Promise<{
7105
+ kind: "controller";
7106
+ hostSessionId: string;
7107
+ } | {
7108
+ kind: "none";
7109
+ }>;
7110
+ /**
7111
+ * `device_prompt` with P7a id resolution (#1637). Resolution order:
7112
+ *
7113
+ * (a) exact host session id match — the current behavior, tried FIRST,
7114
+ * exactly as `promptHostSession` always has;
7115
+ * (b) controller-id → host-id via the local registry: when (a) fails
7116
+ * with a no-session failure AND a local device descriptor maps the
7117
+ * given id (`hostSessionId` stamped at device spawn), retry once
7118
+ * against the mapped host id.
7119
+ *
7120
+ * Any other failure passes through untouched — the mapping must never mask
7121
+ * a pairing gate, a prompt-validation rejection, or a wait-arm error. When
7122
+ * both fail, the error names the host and the mapping so the operator
7123
+ * knows both halves were checked.
7124
+ */
7125
+ declare function promptDeviceSession(hosts: HostRegistry | undefined, sessions: DevicePromptSessionsLike | undefined, target: string, sessionId: string, input: PromptHostSessionInput): Promise<PromptHostSessionResult>;
6562
7126
 
6563
7127
  /**
6564
7128
  * MCP tools over the device registry (DEVICES-PLAN PR-A/PR-C) — `device_list`
@@ -6580,12 +7144,161 @@ declare function createDeviceRegistry(pairing: PairingRegistry, hosts?: HostRegi
6580
7144
 
6581
7145
  interface RegisterDeviceToolsOptions {
6582
7146
  registry: DeviceRegistry;
7147
+ /** Optional — the underlying host registry (`device_add`'s), when wired.
7148
+ * `device_prompt` needs it directly: its wait-loop dials the host more
7149
+ * than once, which `DeviceRegistry.forwardHttp`'s snapshot fallback
7150
+ * would happily answer from cache. When absent, `device_prompt` is not
7151
+ * registered. */
7152
+ hosts?: HostRegistry;
7153
+ /** Optional (BOOTSTRAP P7a) — the session registry, for `device_prompt`
7154
+ * to resolve a CONTROLLER session id onto its mapped HOST session id
7155
+ * (the issue #1637 id split). Absent ⇒ no controller-id resolution and
7156
+ * the tool keeps behaving exactly as before. */
7157
+ sessions?: DevicePromptSessionsLike;
6583
7158
  /** Optional (SANDBOX-VISIBILITY-JOIN) — when wired, registers
6584
7159
  * `join_token_create`/`join_token_list`/`join_token_revoke`. */
6585
7160
  joinTokens?: JoinTokenRegistry;
6586
7161
  }
6587
7162
  declare function registerDeviceTools(server: McpServer, opts: RegisterDeviceToolsOptions): void;
6588
7163
 
7164
+ /**
7165
+ * BOOTSTRAP P7b — read-time mirror of a HOST device's turns into the
7166
+ * CONTROLLER's own session reads (issue #1637).
7167
+ *
7168
+ * A `session spawned with sandbox: "device:<fp|name>"` lives on TWO
7169
+ * daemons: the controller keeps a thin proxy-backed descriptor (its `id`,
7170
+ * e.g. `sess_305be17c`) while the real conversation accumulates on the
7171
+ * host' under a DIFFERENT id (`sess_cf318f00`, on the descriptor's
7172
+ * `hostSessionId`). #1640 gave the controller WRITE access across the gap
7173
+ * (`device_prompt`); this module closes the READ half: nothing runs in
7174
+ * the background — every controller READ (`GET /sessions/:id`, the
7175
+ * `/output` tail, `/events`, `/export`, the `agent_output` tool) calls
7176
+ * {@link syncDeviceMirror} first, which:
7177
+ *
7178
+ * 1. derives the dedup cursor from the session's OWN events.jsonl (max
7179
+ * `hostSeq` across records tagged `origin: "device"` — so the cursor
7180
+ * survives a daemon restart by construction, P7b-3), seeding it the
7181
+ * first time from what the controller already knows locally (below),
7182
+ * 2. dials the host ONCE over the existing E2E channel
7183
+ * (`HostRegistry.forwardHttp`, the same path `device_sessions` uses)
7184
+ * and pages `GET /sessions/:hostSessionId/events?since=<cursor>` —
7185
+ * an EXISTING host route; no host-side changes are consumed for this
7186
+ * (P7b uses today's 1.7.x-compatible endpoints only),
7187
+ * 3. appends the new host records to the controller transcript,
7188
+ * byte-faithful, tagged `origin: "device"` + `hostSeq` +
7189
+ * `sourceRef: "device:<fp>"` (idempotent by the hostSeq cursor —
7190
+ * re-reading never duplicates), and
7191
+ * 4. cheaply refreshes the controller descriptor's live projection
7192
+ * fields from the host snapshot (`lastActivityAt`, `busy`, usage),
7193
+ * without touching controller-local fields (label, agentsMdMode…).
7194
+ *
7195
+ * Backward compatibility (P7b constraint): only EXISTING host endpoints
7196
+ * are consumed. An older host, or one whose daemon lacks the events route,
7197
+ * surfaces as `mirrorError` on the descriptor — never a crash, never a
7198
+ * silent stale overwrite.
7199
+ */
7200
+
7201
+ /** One raw record off the host's own transcript (the exact on-disk shape —
7202
+ * `{seq, ts, kind, ...}` — so the mirror is byte-faithful to the host). */
7203
+ type HostEventRecord = Record<string, unknown>;
7204
+ /**
7205
+ * Dial the host and read its session's transcript from `sinceSeq`
7206
+ * (exclusive), paginating until the host reports the tail complete.
7207
+ *
7208
+ * Same failure semantics as `device_sessions`' tail mode, but WITHOUT its
7209
+ * stale-snapshot fallback: the host's unreachability must surface as
7210
+ * `{ ok: false, error }` so readers can show "host unreachable" rather
7211
+ * than silently rendering the last snapshot (P7b-1). `404 no_transcript`
7212
+ * (a host session with nothing written — most usefully a just-spawned one)
7213
+ * is a NORMAL empty result, not an error.
7214
+ */
7215
+ type FetchHostTurnsResult = {
7216
+ ok: true;
7217
+ /** Records strictly AFTER `sinceSeq`, ascending. */
7218
+ events: HostEventRecord[];
7219
+ /** Host-reported tip: the seq the next call should use as `sinceSeq`. */
7220
+ nextSeq: number;
7221
+ } | {
7222
+ ok: false;
7223
+ error: string;
7224
+ staleAt?: string;
7225
+ };
7226
+ declare function fetchHostTurns(hosts: HostRegistry, hostFingerprint: string, hostSessionId: string, sinceSeq: number): Promise<FetchHostTurnsResult>;
7227
+ /** The highest `hostSeq` already mirrored into the session's transcript —
7228
+ * the next sync reads only what is STRICTLY newer, so a daemon restart or
7229
+ * a re-read can never duplicate or skip turns (P7b-3, the correctness
7230
+ * core). Scans for `origin === "device"` records; every other line is
7231
+ * controller-local and owns no `hostSeq`. Standalone fs reader (tests +
7232
+ * tooling): the LIVE sync path uses the registry's own
7233
+ * `scanDeviceMirrorState` so custom transcript base dirs can't drift. */
7234
+ declare function mirrorCursorForSession(sessionId: string, baseDir?: string): Promise<number>;
7235
+ /**
7236
+ * Seed the cursor so a FIRST mirror read (before anything was ever
7237
+ * mirrored) skips the turns the controller already recorded on its own.
7238
+ *
7239
+ * Walks the host transcript in order; a host `user-prompt` whose text
7240
+ * matches the NEXT unmatched known local prompt is a turn the controller
7241
+ * already has (it captured that turn live through the sandbox proxy) —
7242
+ * consume it and keep walking. The first host turn that does NOT match is
7243
+ * where local knowledge ends: the cursor is the last turn-end BEFORE it,
7244
+ * so everything from that turn onward gets mirrored exactly once.
7245
+ *
7246
+ * Ordered (not set-membership) on purpose: re-issued prompts later in a
7247
+ * conversation legitimately reappear in the host transcript and a
7248
+ * set-membership match would wrongly skip them.
7249
+ *
7250
+ * Exit states: every host turn matched → full tip is known, cursor is the
7251
+ * last turn-end; no local prompts (or the first host prompt already
7252
+ * unknown) → 0, mirror everything. A transcript longer than one page
7253
+ * leaves the seed `undefined` — the caller merges from 0 (a possible
7254
+ * duplicate beats any lost content) rather than trusting a partial walk.
7255
+ */
7256
+ declare function seedWalkForTranscript(localTexts: readonly string[], hostRecords: readonly HostEventRecord[]): number | undefined;
7257
+ /** Turn a raw host record into the controller-transcript record the mirror
7258
+ * appends — same `kind` (so every existing transcript renderer renders it
7259
+ * unchanged) plus the three mirror tags, and the HOST's own `ts` preserved
7260
+ * inside the record. `undefined` for kinds that carry conversations the
7261
+ * controller doesn't derive value from duplicating (`system-prompt`,
7262
+ * `usage_update`, derived `tool-call-record`, …). */
7263
+ declare function hostRecordToMirrorRecord(rec: HostEventRecord, hostFingerprint: string): Record<string, unknown> | undefined;
7264
+ /** The slice of `SessionsRegistry` (and the descriptor) the sync needs —
7265
+ * kept narrow so tests can stub the registry. */
7266
+ interface DeviceMirrorTarget {
7267
+ findByIdOrName(idOrName: string): SessionDescriptor | undefined;
7268
+ appendDeviceMirrorRecords(id: string, records: readonly Record<string, unknown>[]): number;
7269
+ /** Preferred cursor/prompt source — the registry's own scan (correct
7270
+ * transcript base dir). Falls back to this module's default-dir fs read
7271
+ * when absent (older registry shapes / direct unit calls). */
7272
+ scanDeviceMirrorState?(id: string): {
7273
+ cursor: number;
7274
+ localPromptTexts: readonly string[];
7275
+ };
7276
+ }
7277
+ type DeviceMirrorSyncResult = {
7278
+ ok: true;
7279
+ /** New records merged from the host this call. */
7280
+ merged: number;
7281
+ /** The advanced mirror cursor after the merge. */
7282
+ cursor: number;
7283
+ } | {
7284
+ ok: false;
7285
+ reason: "no-session" | "not-device" | "no-host-registry";
7286
+ error?: string;
7287
+ } | {
7288
+ ok: false;
7289
+ reason: "mirror-error";
7290
+ error: string;
7291
+ };
7292
+ /**
7293
+ * One read-time sync for a controller id/name. Fast no-op path: no local
7294
+ * descriptor, or not a device-mirrored session (both fields absent) —
7295
+ * local spawns pay ZERO extra reads/calls (P7b test invariant). Reads the
7296
+ * cursor, dials the host, appends new records, refreshes the descriptor's
7297
+ * live projection fields, and stamps/clears `mirrorError` on the
7298
+ * descriptor for unreachable-host surfacing.
7299
+ */
7300
+ declare function syncDeviceMirror(sessions: DeviceMirrorTarget, hosts: HostRegistry | undefined, idOrName: string): Promise<DeviceMirrorSyncResult>;
7301
+
6589
7302
  /**
6590
7303
  * Provider-preset family on top of `@agentproto/provider-kit` — the *thin,
6591
7304
  * honest* lister (Option B). Unlike tunnels/sandboxes/eval-reporters, presets
@@ -7942,4 +8655,4 @@ interface GatewayHandle {
7942
8655
  */
7943
8656
  declare function createGateway(opts: CreateGatewayOptions): Promise<GatewayHandle>;
7944
8657
 
7945
- export { ActivityListFilter, type ActivityPolicyLister, type ActivityProjector, type ActivityProjectorRegistry, type ActivityProjectorSession, ActivityRecord, type ActivityWorkflowLister, AdapterAuthDescriptor, type AdapterCapabilitiesLister, type AdapterInstallResult, type AdapterListEntry, type AgentAdapterInstaller, type AgentAdapterLister, type AgentAdapterResolver, AgentSessionLike, AgentStreamEvent, type AttachSandboxOpts, type AttachSandboxResult, BUCKETS_ROOT, type BranchGcClass, type BranchGcCoverageView, type BranchGcHoldReason, type BranchGcKind, type BranchGcOutcomeView, type BranchGcPlanEntryView, type BranchGcPlanView, type BranchGcReclaimReason, type BranchGcResult, type BranchGcRunInput, type BranchGcRunner, type BranchGcStatus, type BranchGcSummaryView, type BranchGcTriageVerdict, type BranchGcVerdictInput, type BranchGcVerdictLookupInput, type BranchGcVerdictReader, type BranchGcVerdictRecordView, type BranchGcVerdictRecorder, type BrowserAdapterHandle, type BrowserAdapterInfo, type BrowserAdapterLister, type BrowserAdapterResolver, BuildHeartbeatAgent, CONTINUE_PROMPT_SOURCE, CanonicalPosture, type CapabilitiesInventory, type CapabilitiesInventoryMcp, type CapabilitiesInventorySkills, type CatalogModelsLister, CatalogModelsQuery, CatalogModelsResponse, type CatalogProviderModel, type CatalogProviderModelsQuery, type CatalogProviderModelsResponse, type CatalogProviderPricing, type ClaudeNativeRef, CompletionPolicySupervisor, type ComposeCandidate, ContextProfile, type ContinueInterruptedMode, type ContinueInterruptedOutcome, type ContinueInterruptedResult, type ContinueInterruptedSkipReason, type ContinueOnBootSummary, type ConversationIndexRecord, type ConversationNativeRef, type CostBudgetDecision, type CrashDetectSummary, type CrashReaperRegistry, type CreateGatewayOptions, type CreateJoinTokenInput, type CreateReviewRunnerOptions, type CreatedJoinToken, DEAD_SESSION_STATUSES, DEFAULT_ALWAYS_ON_TOOLS, DEFAULT_BUCKET, DEFAULT_CONTINUE_PROMPT, DEFAULT_HOST_LOAD_BUDGET_MS, DEFAULT_HOST_LOAD_THRESHOLDS, DEFAULT_ORCHESTRATOR_TOOLS, type DaemonReviewerHostDeps, DeclaredAdapterOption, type DeclaredAdapterPreset, DefaultsAdapterAuthConfig, type Device, type DeviceKind, type DeviceRegistry, type DeviceRole, type DiskLoad, type EagerResumeSummary, type EnableInput, type EnableResult, type FindComposeCandidateInput, type ForwardHttpRequest, type ForwardHttpResponse, GC_REAPABLE_STATES, type GatewayHandle, type GhRunner, HOSTS_VERSION, HOST_HANDSHAKE_REMEDIATION_HINT, HOST_SCOPE_HEADER, type HarnessPreset, type HarnessPresetValidationDeps, HarnessPresetValidationError, type HarnessPresetsFile, type HermesNativeRef, type HostJoinMeta, type HostLoadCpu, type HostLoadDetail, type HostLoadMemory, type HostLoadReport, type HostLoadService, type HostLoadSwap, type HostLoadThresholds, type HostProbes, type HostProcess, type HostProcessOwner, type HostRecord, type HostRegistry, type HostRegistryDeps, type HostSessionRollup, type HostWarning, type HostWarningKind, INBOUND_PROVIDERS, type IdleReapSummary, type IdleReaperRegistry, type InboundEndpoint, type InboundEndpointStore, type InboundEndpointStoreOptions, type InboundEnqueuePrompt, type InboundIsSessionAlive, type InboundMessage, type InboundProvider, type InboundRestartSession, type InboundRouteMode, type InboundRouterDeps, type InboundRouterLog, type InboundSpawnForContact, type InboundWatcher, JOIN_TOKENS_VERSION, type JoinTokenRecord, type JoinTokenRegistry, type JoinTokenRegistryDeps, LEGACY_SESSIONS_FILE, type LedgerAnnotations, type LedgerEntry, type LedgerHostMeta, type LlmEndpointDescriptor, type LlmEndpointStatus, type LlmEndpointStatusReport, type LocatedConversation, type LocatedConversationByPath, MAX_AUTO_CONTINUE_ATTEMPTS, MCP_APP_BRIDGE_SCRIPT, type McpCredentialDeps, type MeasurableTool, type MeasuredToolEntry, MessageKind, MessageUrgency, type MigrationMarker, type ModelRolesInput, type ModelRolesOutput, type NormalizeInboundResult, type OpenPrResolver, type OrchestratorGatewayDeps, type OrchestratorInjection, type OrchestratorInjector, type OrchestratorInjectorDeps, type OrchestratorMcpServerFactory, type OrchestratorScope, type OrphanReaperRegistry, POSTURE_NATIVE_ALIASES, POSTURE_PREAMBLES, PolicyRunState, Posture, type PostureResolution, PrLookupError, type PrLookupErrorCode, PrResolvedState, type PrStateResolver, type PrStatusSnapshot, type PresetInfo, type ProjectBrowserToolsOptions, type ProjectedBrowserTool, type ProjectedBrowserTools, type ProjectedProvider, type ProjectedToolResult, ProvisionInFlight, QuotaReadableProfile, type RegisterBrainToolsOptions, type RegisterDeviceToolsOptions, type RegisterPairingToolsOptions, type RegisterReviewToolsOptions, type RegisterWebSearchToolsOptions, RemainingQuotaReader, type RemoteStatus, type ResolveNativeLinkInput, ResolvedAuthSpec, ResolvedModelRole, type ReuseResolution, type ReviewComposeContext, type ReviewLedger, type ReviewLedgerFilter, type ReviewRun, type ReviewRunInput, type ReviewRunStatus, type ReviewRunner, type ReviewSignature, type ReviewSigningKey, type ReviewerRunResult, type ReviewerSessionHost, type RouteAwareLaunchConfig, type RouteAwareLaunchConfigInput, RouteSpec, type RuntimeMeta, SIGN_NAMESPACE, type SandboxAdapterInfo, type SandboxConnectionDescriptor, type SandboxGcCandidate, type SandboxGcProviderHandle, type SandboxGcReapDeps, type SandboxGcReapResult, type SandboxLedgerEntry, type SandboxLedgerState, type SandboxProviderCapabilities, type SandboxProviderHandle, type SandboxProviderLister, type SandboxProviderResolver, type SandboxReconcileDeps, type SandboxReconcileProviderHandle, type SandboxReconcileResult, type SandboxReconcileRow, type SandboxReconcileVerdict, type ScopeTokenRegistry, type SentinelMatchClause, type SentinelSpec, type SentinelStatus, type SentinelTarget, type SentinelUntil, type SentinelView, SessionDescriptor, SessionEndReason, SessionMessage, type SessionMessageSentRecord, type SessionObserver, SessionUsage, type SessionUsageWithSubtree, type SessionWaitEvent, type SessionWaitResult, SessionsRegistry, type SkillPackInventoryEntry, type SkillsByHarnessEntry, SpawnDefaultsConfig, type StallWatchdogRegistry, type StallWatchdogSummary, type SubtreeChildUsage, type SubtreeUsageTotals, TaskLedger, type ToolListMeasurement, type TransmitterBinding, type TransmitterBindingStore, type TunnelDescriptor, type TunnelProvider, type TunnelStatus, UsageReadContext, UsageReadResult, UsageRollup, UsageSnapshotRecord, UserPreset, type VerifySignedAttestationResult, type WatcherDescriptor, type WatcherStartInput, type WebSearchInput, type WebSearchOutput, type WebSearchResult, type WorkspaceBrainSubscriber, type WorkspaceBrainSubscriberOptions, type WorkspaceBrains, WorkspaceFs, WorktreeAutoReclaimer, WorktreeField, type WorktreeGcClass, type WorktreeGcOutcomeView, type WorktreeGcPlanEntryView, type WorktreeGcReclaimReason, type WorktreeGcResult, type WorktreeGcRunInput, type WorktreeGcRunner, WorktreeIsolationMode, WorktreeProvisioner, type WorktreeStatusLister, type WorktreeStatusView, addHarnessPreset, allowedSignersLine, appendConversationRecord, attachSandbox, bucketDir, bucketSessionsFile, bucketTranscriptDir, buildCatalogProviderModels, buildHostLoadReport, buildMcpConfigSnippet, buildRouteAwareLaunchConfig, canonicalForModeId, claudeProjectSlug, collectGcCandidates, collectHostSample, composeSessionObservers, composedFromRangeSha, computeHostWarnings, continueInterruptedSessions, continueSkipReason, conversationIndexPath, createActivityProjector, createDaemonReviewerHost, createDefaultHostProbes, createDeviceRegistry, createFileStepCache, createGateway, createHostLoadService, createHostRegistry, createInboundEndpointStore, createJoinTokenRegistry, createOrchestratorInjector, createOrchestratorMcpServerFactory, createPrProvenanceReconciler, createReviewLaneExecutor, createReviewLedger, createReviewPackLoader, createReviewRunner, createScopeTokenRegistry, createWorkspaceBrainSubscriber, createWorkspaceBrains, daemonRegistryDir, declaredPresetToProviderPreset, defaultBrowserAdapterIds, defaultBrowserAdapterResolution, defaultReviewKeysDir, defaultReviewLedgerRoot, defaultReviewPackCacheDir, defineBraveSearchHttpDriver, defineSerperHttpDriver, describeOwner, enrichRollupWithProviderQuota, enrichWithRemainingQuota, ensureReviewSigningKey, evaluateCostBudget, execGh, extractHelpSection, fetchPrStatus, fileExists, findComposeCandidate, findConversationRecord, findNativeMode, findPrForCommit, formatToolCall, formatToolResult, getDefaultHarnessPreset, getHarnessPreset, getHostLoadService, getMcpCredentialDeps, getToolHelp, githubRepoOf, harnessPresetsPath, hostPlaceholders, injectMcpAppBridge, isAgentCliAuthConfigured, isSafeBucketSlug, listBuckets, listHarnessPresets, listPresets, listToolHelpTopics, loadHarnessPresets, loadWorkspaceModelRoles, locateConversationByNativePath, locateConversationBySessionId, makeBrowserAdapterLister, makeSandboxCredsStore, makeSandboxResolver, measureTool, measureToolList, migrateLegacySessionsFile, migrationMarkerPath, monitorPolicyWait, monitorSessionWait, narrowOrchestratorTools, normalizeInbound, normalizeModeId, normalizeRemote, parsePrUrl, prHeadSha, projectBrowserTools, readConversationIndex, readDaemonRegistry, readHostsSnapshot, readRegisteredSlugs, readRuntimeMeta, readSandboxLedger, readSessionForBrain, readUsageSnapshots, reapGcEntry, reapOrphanedDescendants, reconcileSandboxLedger, recordSandboxBoot, recordSandboxLiveness, recordSandboxOrigin, recordSandboxState, registerBrainTools, registerBuiltinRoutes, registerDeviceTools, registerPairingTools, registerReviewTools, registerSandboxAttachTool, registerWebSearchTools, removeHarnessPreset, removeSandboxLedgerEntry, repoSlug, resolveBucketSlug, resolveEffectiveLlmEndpointFlag, resolveNativeLink, resolvePosture, resolvePrincipal, resolveReuseFromLedger, resolveReviewerPreset, rollupSessionSubtree, runContinueOnBootPass, runCrashDetectPass, runEagerResumePass, runIdleReapPass, runShellLane, runStallWatchdogPass, sandboxLedgerPath, setDefaultPreset, setMcpCredentialDeps, signAttestation, sweepStaleDaemonRegistry, sweepStaleRuntimeMetas, toWorktreeStatusView, unlinkDaemonRegistryEntry, unlinkRuntimeMeta, updateHarnessPreset, upsertSandboxLedger, verifyInboundSignature, verifySignedAttestation, webSearchTool, withPr, withPrStatus, writeDaemonRegistryEntry };
8658
+ export { ActivityListFilter, type ActivityPolicyLister, type ActivityProjector, type ActivityProjectorRegistry, type ActivityProjectorSession, ActivityRecord, type ActivityWorkflowLister, AdapterAuthDescriptor, type AdapterCapabilitiesLister, type AdapterInstallResult, type AdapterListEntry, type AgentAdapterInstaller, type AgentAdapterLister, type AgentAdapterResolver, AgentSessionLike, AgentStreamEvent, type AttachSandboxOpts, type AttachSandboxResult, BUCKETS_ROOT, type BranchGcClass, type BranchGcCoverageView, type BranchGcHoldReason, type BranchGcKind, type BranchGcOutcomeView, type BranchGcPlanEntryView, type BranchGcPlanView, type BranchGcReclaimReason, type BranchGcResult, type BranchGcRunInput, type BranchGcRunner, type BranchGcStatus, type BranchGcSummaryView, type BranchGcTriageVerdict, type BranchGcVerdictInput, type BranchGcVerdictLookupInput, type BranchGcVerdictReader, type BranchGcVerdictRecordView, type BranchGcVerdictRecorder, type BrowserAdapterHandle, type BrowserAdapterInfo, type BrowserAdapterLister, type BrowserAdapterResolver, BuildHeartbeatAgent, CLAMP_LIMIT_BYTES, CONTINUE_PROMPT_SOURCE, CanonicalPosture, type CapabilitiesInventory, type CapabilitiesInventoryMcp, type CapabilitiesInventorySkills, type CatalogModelsLister, CatalogModelsQuery, CatalogModelsResponse, type CatalogProviderModel, type CatalogProviderModelsQuery, type CatalogProviderModelsResponse, type CatalogProviderPricing, type ChallengeFailureReason, type ChallengeOutcome, type ClaudeNativeRef, CompletionPolicySupervisor, type ComposeCandidate, ContextProfile, type ContinueInterruptedMode, type ContinueInterruptedOutcome, type ContinueInterruptedResult, type ContinueInterruptedSkipReason, type ContinueOnBootSummary, type ConversationIndexRecord, type ConversationNativeRef, type CostBudgetDecision, type CrashDetectSummary, type CrashReaperRegistry, type CreateGatewayOptions, type CreateJoinTokenInput, type CreateReviewRunnerOptions, type CreatedJoinToken, DEAD_SESSION_STATUSES, DEFAULT_ALWAYS_ON_TOOLS, DEFAULT_BUCKET, DEFAULT_CONTINUE_PROMPT, DEFAULT_HOST_LOAD_BUDGET_MS, DEFAULT_HOST_LOAD_THRESHOLDS, DEFAULT_ORCHESTRATOR_TOOLS, DEVICE_PROMPT_PATH_PREFIX, type DaemonReviewerHostDeps, DeclaredAdapterOption, type DeclaredAdapterPreset, DefaultsAdapterAuthConfig, type DeliveryOutcome, type DeliveryReplay, type DeliveryState, type Device, type DeviceKind, type DeviceMirrorSyncResult, type DeviceMirrorTarget, type DevicePromptSessionsLike, type DeviceRegistry, type DeviceRole, type DiskLoad, type EagerResumeSummary, type EgressDispatcher, type EnableInput, type EnableResult, type FetchHostTurnsResult, type FindComposeCandidateInput, type ForwardHttpRequest, type ForwardHttpResponse, GC_REAPABLE_STATES, type GatewayHandle, type GhRunner, HOSTS_VERSION, HOST_HANDSHAKE_REMEDIATION_HINT, HOST_SCOPE_HEADER, type HarnessPreset, type HarnessPresetValidationDeps, HarnessPresetValidationError, type HarnessPresetsFile, type HermesNativeRef, type HostEventRecord, type HostJoinMeta, type HostLoadCpu, type HostLoadDetail, type HostLoadMemory, type HostLoadReport, type HostLoadService, type HostLoadSwap, type HostLoadThresholds, type HostProbes, type HostProcess, type HostProcessOwner, type HostRecord, type HostRegistry, type HostRegistryDeps, type HostSessionRollup, type HostWarning, type HostWarningKind, INBOUND_PROVIDERS, type IdleReapSummary, type IdleReaperRegistry, type InboundEndpoint, type InboundEndpointStore, type InboundEndpointStoreOptions, type InboundEnqueuePrompt, type InboundIsSessionAlive, type InboundMessage, type InboundProvider, type InboundRestartSession, type InboundRouteMode, type InboundRouterDeps, type InboundRouterLog, type InboundSpawnForContact, type InboundWatcher, JOIN_TOKENS_VERSION, type JoinTokenRecord, type JoinTokenRegistry, type JoinTokenRegistryDeps, LEGACY_SESSIONS_FILE, type LedgerAnnotations, type LedgerEntry, type LedgerHostMeta, type LlmEndpointDescriptor, type LlmEndpointStatus, type LlmEndpointStatusReport, type LocatedConversation, type LocatedConversationByPath, MAX_ATTEMPTS, MAX_AUTO_CONTINUE_ATTEMPTS, MCP_APP_BRIDGE_SCRIPT, type McpCredentialDeps, type McpEventEnvelope, type MeasurableTool, type MeasuredToolEntry, MessageKind, MessageUrgency, type MigrationMarker, type ModelRolesInput, type ModelRolesOutput, type NormalizeInboundResult, type OpenPrResolver, type OrchestratorGatewayDeps, type OrchestratorInjection, type OrchestratorInjector, type OrchestratorInjectorDeps, type OrchestratorMcpServerFactory, type OrchestratorScope, type OrphanReaperRegistry, POSTURE_NATIVE_ALIASES, POSTURE_PREAMBLES, type PersistedOutboxRow, PolicyRunState, Posture, type PostureResolution, PrLookupError, type PrLookupErrorCode, PrResolvedState, type PrStateResolver, type PrStatusSnapshot, type PresetInfo, type ProjectBrowserToolsOptions, type ProjectedBrowserTool, type ProjectedBrowserTools, type ProjectedProvider, type ProjectedToolResult, type PromptHostSessionInput, type PromptHostSessionResult, ProvisionInFlight, QuotaReadableProfile, type RegisterBrainToolsOptions, type RegisterDeviceToolsOptions, type RegisterPairingToolsOptions, type RegisterReviewToolsOptions, type RegisterWebSearchToolsOptions, RemainingQuotaReader, type RemoteStatus, type ResolveNativeLinkInput, ResolvedAuthSpec, ResolvedModelRole, type ReuseResolution, type ReviewComposeContext, type ReviewLedger, type ReviewLedgerFilter, type ReviewRun, type ReviewRunInput, type ReviewRunStatus, type ReviewRunner, type ReviewSignature, type ReviewSigningKey, type ReviewerRunResult, type ReviewerSessionHost, type RouteAwareLaunchConfig, type RouteAwareLaunchConfigInput, RouteSpec, type RuntimeMeta, SIGN_NAMESPACE, type SandboxAdapterInfo, type SandboxConnectionDescriptor, type SandboxGcCandidate, type SandboxGcProviderHandle, type SandboxGcReapDeps, type SandboxGcReapResult, type SandboxLedgerEntry, type SandboxLedgerState, type SandboxProviderCapabilities, type SandboxProviderHandle, type SandboxProviderLister, type SandboxProviderResolver, type SandboxReconcileDeps, type SandboxReconcileProviderHandle, type SandboxReconcileResult, type SandboxReconcileRow, type SandboxReconcileVerdict, type ScopeTokenRegistry, type SentinelMatchClause, type SentinelSpec, type SentinelStatus, type SentinelTarget, type SentinelUntil, type SentinelView, type SentinelWebhookOutbox, type SentinelWebhookOutboxOptions, type SentinelWebhookOutboxRow, type SentinelWebhookOutboxStatus, SessionDescriptor, SessionEndReason, SessionMessage, type SessionMessageSentRecord, type SessionObserver, SessionUsage, type SessionUsageWithSubtree, type SessionWaitEvent, type SessionWaitResult, SessionsRegistry, type SkillPackInventoryEntry, type SkillsByHarnessEntry, SpawnDefaultsConfig, SsrfFetchError, type SsrfFetchInit, type SsrfFetchReason, type SsrfFetchResult, type StallWatchdogRegistry, type StallWatchdogSummary, type SubtreeChildUsage, type SubtreeUsageTotals, TaskLedger, type ToolListMeasurement, type TransmitterBinding, type TransmitterBindingStore, type TunnelDescriptor, type TunnelProvider, type TunnelStatus, UsageReadContext, UsageReadResult, UsageRollup, UsageSnapshotRecord, UserPreset, type VerifyCallbackInput, type VerifySignedAttestationResult, type WatcherDescriptor, type WatcherStartInput, type WebSearchInput, type WebSearchOutput, type WebSearchResult, type WebhookSignInput, type WebhookSignatureHeaders, type WorkspaceBrainSubscriber, type WorkspaceBrainSubscriberOptions, type WorkspaceBrains, WorkspaceFs, WorktreeAutoReclaimer, WorktreeField, type WorktreeGcClass, type WorktreeGcOutcomeView, type WorktreeGcPlanEntryView, type WorktreeGcReclaimReason, type WorktreeGcResult, type WorktreeGcRunInput, type WorktreeGcRunner, WorktreeIsolationMode, WorktreeProvisioner, type WorktreeStatusLister, type WorktreeStatusView, addHarnessPreset, allowedSignersLine, appendConversationRecord, attachSandbox, bucketDir, bucketSessionsFile, bucketTranscriptDir, buildCatalogProviderModels, buildHostLoadReport, buildMcpConfigSnippet, buildRouteAwareLaunchConfig, canonicalForModeId, challengeCacheSize, challengeReasonForSsrf, claudeProjectSlug, collectGcCandidates, collectHostSample, composeSessionObservers, composedFromRangeSha, computeHostWarnings, continueInterruptedSessions, continueSkipReason, conversationIndexPath, createActivityProjector, createDaemonReviewerHost, createDefaultHostProbes, createDeviceRegistry, createFileStepCache, createGateway, createHostLoadService, createHostRegistry, createInboundEndpointStore, createJoinTokenRegistry, createOrchestratorInjector, createOrchestratorMcpServerFactory, createPrProvenanceReconciler, createReviewLaneExecutor, createReviewLedger, createReviewPackLoader, createReviewRunner, createScopeTokenRegistry, createSentinelWebhookOutbox, createWorkspaceBrainSubscriber, createWorkspaceBrains, daemonRegistryDir, declaredPresetToProviderPreset, decodeWhsecSecret, defaultBrowserAdapterIds, defaultBrowserAdapterResolution, defaultReviewKeysDir, defaultReviewLedgerRoot, defaultReviewPackCacheDir, defineBraveSearchHttpDriver, defineSerperHttpDriver, deliverEventEnvelope, deliveryBackoffDelay, describeOwner, encodeWhsecSecret, enrichRollupWithProviderQuota, enrichWithRemainingQuota, ensureReviewSigningKey, envelopeClampedBytes, evaluateCostBudget, execGh, extractHelpSection, fetchHostTurns, fetchPrStatus, fileExists, findComposeCandidate, findConversationRecord, findNativeMode, findPrForCommit, formatToolCall, formatToolResult, getDefaultHarnessPreset, getHarnessPreset, getHostLoadService, getMcpCredentialDeps, getToolHelp, githubRepoOf, harnessPresetsPath, hostPlaceholders, hostRecordToMirrorRecord, injectMcpAppBridge, isAgentCliAuthConfigured, isNoSessionPromptFailure, isPubliclyRoutable, isSafeBucketSlug, listBuckets, listHarnessPresets, listPresets, listToolHelpTopics, loadHarnessPresets, loadWorkspaceModelRoles, locateConversationByNativePath, locateConversationBySessionId, makeBrowserAdapterLister, makeSandboxCredsStore, makeSandboxResolver, measureTool, measureToolList, migrateLegacySessionsFile, migrationMarkerPath, mirrorCursorForSession, monitorPolicyWait, monitorSessionWait, narrowOrchestratorTools, normalizeCallbackUrl, normalizeInbound, normalizeModeId, normalizeRemote, parsePrUrl, prHeadSha, projectBrowserTools, promptDeviceSession, promptHostSession, readConversationIndex, readDaemonRegistry, readHostsSnapshot, readRegisteredSlugs, readRuntimeMeta, readSandboxLedger, readSessionForBrain, readUsageSnapshots, reapGcEntry, reapOrphanedDescendants, reconcileSandboxLedger, recordSandboxBoot, recordSandboxLiveness, recordSandboxOrigin, recordSandboxState, registerBrainTools, registerBuiltinRoutes, registerDeviceTools, registerPairingTools, registerReviewTools, registerSandboxAttachTool, registerWebSearchTools, removeHarnessPreset, removeSandboxLedgerEntry, repoSlug, resetChallengeCacheForTests, resolveBucketSlug, resolveDevicePromptMapping, resolveEffectiveLlmEndpointFlag, resolveNativeLink, resolvePosture, resolvePrincipal, resolveReuseFromLedger, resolveReviewerPreset, rollupSessionSubtree, runContinueOnBootPass, runCrashDetectPass, runEagerResumePass, runIdleReapPass, runShellLane, runStallWatchdogPass, sandboxLedgerPath, seedWalkForTranscript, serializeEnvelope, setDefaultPreset, setEgressDispatcherForTests, setMcpCredentialDeps, signAttestation, signWebhook, ssrfFetch, sweepStaleDaemonRegistry, sweepStaleRuntimeMetas, syncDeviceMirror, toWebhookEnvelope, toWorktreeStatusView, unlinkDaemonRegistryEntry, unlinkRuntimeMeta, updateHarnessPreset, upsertSandboxLedger, verifyCallback, verifyInboundSignature, verifySignedAttestation, webSearchTool, webhookRequestId, withPr, withPrStatus, writeDaemonRegistryEntry };