@byok-sdk/client 0.6.0 → 0.6.1

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.
Files changed (38) hide show
  1. package/README.md +91 -1
  2. package/dist/adapters/index.js +183 -34
  3. package/dist/adapters/index.js.map +1 -1
  4. package/dist/adapters/pi/events.d.ts +1 -1
  5. package/dist/adapters/pi/mcp-config.d.ts +1 -0
  6. package/dist/adapters/pi/mcp-extension.js +25 -0
  7. package/dist/adapters/pi/mcp-extension.js.map +1 -0
  8. package/dist/adapters/pi/permission-mapping.d.ts +1 -1
  9. package/dist/adapters/pi/pi-adapter.d.ts +5 -0
  10. package/dist/adapters/pi/resolve-extensions.d.ts +11 -0
  11. package/dist/agent-home.d.ts +106 -0
  12. package/dist/bin/byok-agent.js +12892 -9473
  13. package/dist/bin/byok-agent.js.map +1 -1
  14. package/dist/bin/byok-approval-mcp.js.map +1 -1
  15. package/dist/bin/commands/toolsets.d.ts +8 -0
  16. package/dist/bin/format.d.ts +3 -0
  17. package/dist/daemon/agent-content-audit-store.d.ts +35 -0
  18. package/dist/daemon/agent-content-read.d.ts +169 -0
  19. package/dist/daemon/agent-egress-controller.d.ts +76 -0
  20. package/dist/daemon/agent-egress-policy.d.ts +36 -0
  21. package/dist/daemon/agent-egress-sanitizer.d.ts +38 -0
  22. package/dist/daemon/agent-egress-spool.d.ts +116 -0
  23. package/dist/daemon/agent-session-handoff-store.d.ts +82 -0
  24. package/dist/daemon/blob-client.d.ts +6 -2
  25. package/dist/daemon/connection-manager.d.ts +2 -2
  26. package/dist/daemon/control-protocol.d.ts +9 -0
  27. package/dist/daemon/create-daemon.d.ts +78 -3
  28. package/dist/daemon/long-poll-transport.d.ts +60 -0
  29. package/dist/daemon/presence-publisher.d.ts +2 -2
  30. package/dist/daemon/task-runner.d.ts +53 -4
  31. package/dist/daemon/toolset-registry.d.ts +30 -0
  32. package/dist/daemon/url.d.ts +21 -0
  33. package/dist/daemon/ws-transport.d.ts +30 -5
  34. package/dist/index.d.ts +12 -2
  35. package/dist/index.js +8646 -5272
  36. package/dist/index.js.map +1 -1
  37. package/dist/types.d.ts +44 -0
  38. package/package.json +7 -5
@@ -1,5 +1,7 @@
1
- import { type Envelope, type PermissionPolicy, type RuntimeId, type TaskOfferPayload, type TaskOfferWithToolsetsPayload } from '@byok-sdk/protocol';
1
+ import { type AgentEgressPolicy, type Envelope, type PermissionPolicy, type RuntimeId, type TaskOfferPayload, type TaskOfferForAgentPayload, type TaskOfferForAgentWithEgressPayload, type TaskOfferWithToolsetsPayload } from '@byok-sdk/protocol';
2
2
  import { type McpToolsetConfig, type RuntimeAdapter } from '../types';
3
+ import { AgentHomeManager, type AgentRef } from '../agent-home';
4
+ import { AgentSessionHandoffStore, type AgentTerminalCause } from './agent-session-handoff-store';
3
5
  import { type RuntimeDisposalStage } from '../runtime-failure';
4
6
  import { type ApprovalDecision, type ApprovalOrigin, type ApprovalRegistry } from './approvals';
5
7
  import type { BlobResolver } from './blob-client';
@@ -9,6 +11,7 @@ import { type ProgressBatcherOptions } from './progress-batcher';
9
11
  import type { SessionWorkspaceStore } from './session-workspace-store';
10
12
  import type { GitWorkspaceManager, GitWorkspaceObservation } from './git-workspace';
11
13
  import type { GitWorkspaceStore, GitWorkspacePhase } from './git-workspace-store';
14
+ import type { AgentEgressController } from './agent-egress-controller';
12
15
  /**
13
16
  * M4 Phase 3: default wait for `requestApproval` (see its own doc comment)
14
17
  * before force-resolving an unanswered out-of-band approval as a fail-closed
@@ -41,6 +44,8 @@ export declare const DEFAULT_APPROVAL_TIMEOUT_MS: number;
41
44
  * `DaemonOverrides.shutdown.taskInterruptTimeoutMs` — see `create-daemon.ts`).
42
45
  */
43
46
  export declare const DEFAULT_SHUTDOWN_INTERRUPT_TIMEOUT_MS = 5000;
47
+ /** Bounded retry before terminal publication degrades observably. */
48
+ export declare const AGENT_TERMINAL_EVIDENCE_MAX_ATTEMPTS = 3;
44
49
  /**
45
50
  * M4 Phase 4 (fold-in from the P3 gate): bound on how many `requestApproval`
46
51
  * calls may sit QUEUED (not yet dispatched — see that method's own doc
@@ -184,10 +189,18 @@ export interface TaskRunnerDeps {
184
189
  runtimeEnvironment?: Record<string, {
185
190
  allow?: string[];
186
191
  }>;
187
- /** Validated, device-local registry keyed by wire-level logical toolset id. */
188
- mcpToolsets?: ReadonlyMap<string, McpToolsetConfig>;
192
+ /** Reads the daemon's current validated device-local registry once per offer. */
193
+ getMcpToolsets?: () => ReadonlyMap<string, McpToolsetConfig>;
189
194
  permissionDefaults?: PermissionPolicy;
190
195
  workspaceRoot: string;
196
+ /** Strict Agent offer authority. Absent means legacy offers never resolve an Agent home. */
197
+ agentHome?: AgentHomeManager;
198
+ /** Exact host-selected policy accepted by `task.offer_for_agent_with_egress`. */
199
+ agentEgressPolicy?: Readonly<AgentEgressPolicy>;
200
+ /** Always-present projection/sanitizer consumer; it defaults to metadata-only. */
201
+ agentEgress?: AgentEgressController;
202
+ /** Durable exact-match Agent session handoff authority. */
203
+ agentSessionHandoffs?: AgentSessionHandoffStore;
191
204
  deviceId: string;
192
205
  send: (envelope: Envelope) => void;
193
206
  blobClient: BlobResolver;
@@ -216,6 +229,22 @@ export interface TaskRunnerDeps {
216
229
  stage: RuntimeDisposalStage;
217
230
  reason: string;
218
231
  }) => void;
232
+ /**
233
+ * Local audit signal emitted only after bounded Agent-home terminal
234
+ * evidence retries are exhausted. The wire terminal still proceeds so a
235
+ * cloud task cannot remain Claimed/Running forever behind auxiliary local
236
+ * storage failure.
237
+ */
238
+ onAgentTerminalEvidenceFailure?: (event: {
239
+ taskId: string;
240
+ agentRef: AgentRef;
241
+ runtimeId: string;
242
+ cwd: string;
243
+ cause: AgentTerminalCause;
244
+ reason?: string;
245
+ attempts: number;
246
+ error: string;
247
+ }) => void;
219
248
  /**
220
249
  * M4 Phase 3: this daemon's control-socket identity + the shared registry
221
250
  * backing the control socket's own `approvals.list`/`approvals.resolve`
@@ -337,7 +366,7 @@ export type AdmissionGuardDecision = {
337
366
  readonly reason: string;
338
367
  readonly retryable: boolean;
339
368
  };
340
- type AcceptedOfferPayload = TaskOfferPayload | TaskOfferWithToolsetsPayload;
369
+ type AcceptedOfferPayload = TaskOfferPayload | TaskOfferWithToolsetsPayload | TaskOfferForAgentPayload | TaskOfferForAgentWithEgressPayload;
341
370
  /**
342
371
  * Per-connection task orchestration: offer -> (decline | prepare -> seal ->
343
372
  * claim -> prepared operation -> started) -> seq-ordered progress batches -> complete/fail/
@@ -462,6 +491,12 @@ export declare class TaskRunner {
462
491
  private stoppingOffers;
463
492
  constructor(deps: TaskRunnerDeps);
464
493
  get activeTaskCount(): number;
494
+ /**
495
+ * Transport-boundary classification for the currently active task. Legacy
496
+ * tasks and plain Agent-home offers are deliberately false: the additive
497
+ * egress contract must never reclassify their existing wire semantics.
498
+ */
499
+ usesAgentEgress(taskId: string): boolean;
465
500
  /** M5 batch-3 (workstream 2): effective `maxTaskOutputBytes` cap for this daemon — see {@link DEFAULT_MAX_TASK_OUTPUT_BYTES}'s own doc comment. */
466
501
  private get maxTaskOutputBytes();
467
502
  /**
@@ -897,6 +932,14 @@ export declare class TaskRunner {
897
932
  /** Pre-claim, fail-closed rejection (protocol §3.2) — never claims first. */
898
933
  private decline;
899
934
  private fail;
935
+ /**
936
+ * Claimed Agent failures before ActiveTask registration still carry the
937
+ * exact AgentRef and normally have Agent-local, fsynced terminal evidence
938
+ * first. A bounded storage failure degrades observably but cannot strand
939
+ * the already-claimed cloud task forever; the exact terminal still goes on
940
+ * the wire and handleOffer's finally block releases the lease.
941
+ */
942
+ private failClaimedAgent;
900
943
  /**
901
944
  * Build the optional terminal observation from facts this running daemon
902
945
  * actually has. No offered `dispatchSelection` is echoed here: it is a
@@ -908,6 +951,8 @@ export declare class TaskRunner {
908
951
  * independently known runtime, elapsed duration, or Local Agent version.
909
952
  */
910
953
  private terminalInferenceUsagePayload;
954
+ /** Exact Agent identity projection for claim/terminal wire payloads. */
955
+ private agentTerminalPayload;
911
956
  /**
912
957
  * additive-minor (`task.complete.document`): the whole daemon-side gate
913
958
  * between a configured {@link ResultDocumentExtractor} and the wire —
@@ -966,6 +1011,10 @@ export declare class TaskRunner {
966
1011
  private hasResultDocumentCapability;
967
1012
  private observeGit;
968
1013
  private updateGitPhaseBestEffort;
1014
+ /** Persist Agent terminal truth before wire when local storage is available. */
1015
+ private persistAgentTerminalEvidence;
1016
+ private retryAgentTerminalEvidence;
1017
+ private reportAgentTerminalEvidenceFailure;
969
1018
  private finish;
970
1019
  private reserveSemanticTerminal;
971
1020
  /** M3-B: bounded insert for `finishedTaskIds` — see its class-level doc comment and `MAX_TRACKED_TASK_IDS`. Evicts the oldest (first-inserted) entry once over cap, same idiom as `ConnectionHub.checkAndRecordDuplicate` (packages/server/src/hub.ts). */
@@ -0,0 +1,30 @@
1
+ import { type ToolsetId } from '@byok-sdk/protocol';
2
+ import type { McpToolsetConfig, McpToolsetObservation, McpToolsetRegistryStatus, McpToolsetReloadReceipt } from '../types';
3
+ export type McpToolsetConfigInput = Record<string, McpToolsetConfig> | undefined;
4
+ export interface McpToolsetRegistrySnapshot {
5
+ revision: string;
6
+ toolsets: ReadonlyMap<string, McpToolsetConfig>;
7
+ configuredToolsets: readonly ToolsetId[];
8
+ }
9
+ export declare class McpToolsetRevisionConflictError extends Error {
10
+ readonly expectedRevision: string;
11
+ readonly actualRevision: string;
12
+ constructor(expectedRevision: string, actualRevision: string);
13
+ }
14
+ export declare class McpToolsetDefinitionRevisionConflictError extends Error {
15
+ readonly toolsetId: string;
16
+ readonly expectedRevision: string;
17
+ readonly actualRevision: string;
18
+ constructor(toolsetId: string, expectedRevision: string, actualRevision: string);
19
+ }
20
+ /** Single mutable owner of immutable-at-a-time device-local toolset snapshots. */
21
+ export declare class McpToolsetRegistry {
22
+ private state;
23
+ private observations;
24
+ constructor(configured?: McpToolsetConfigInput);
25
+ snapshot(): McpToolsetRegistrySnapshot;
26
+ status(): McpToolsetRegistryStatus;
27
+ reload(configured: McpToolsetConfigInput, expectedRevision: string): McpToolsetReloadReceipt;
28
+ report(toolsetId: string, expectedDefinitionRevision: string, observation: McpToolsetObservation): void;
29
+ private statusRows;
30
+ }
@@ -2,6 +2,27 @@
2
2
  export declare function toHttpBase(serverUrl: string): string;
3
3
  /** Derive the `/byok/ws` WebSocket URL from a configured `serverUrl`. */
4
4
  export declare function toWsUrl(serverUrl: string): string;
5
+ /**
6
+ * Which route a transport diagnostic is about, in the only two fields that
7
+ * are safe to keep: the host (with port) and the path.
8
+ *
9
+ * Both are read off a parsed `URL` in {@link describeEndpoint}, so the
10
+ * redaction is STRUCTURAL rather than a scrub pass — userinfo, query and
11
+ * fragment are the only places a bearer token or a presigned signature ever
12
+ * travels in this SDK, and none of the three survive the projection onto
13
+ * these two fields. There is exactly one construction site, so a future
14
+ * diagnostic cannot accidentally reintroduce a credential-bearing component
15
+ * by formatting a raw URL of its own.
16
+ */
17
+ export interface TransportEndpoint {
18
+ readonly transport: 'ws' | 'long-poll';
19
+ /** `URL.host` — hostname plus port when non-default. Never userinfo. */
20
+ readonly host: string;
21
+ /** `URL.pathname` — no query, no fragment. */
22
+ readonly path: string;
23
+ }
24
+ /** The single construction site for {@link TransportEndpoint} — see that interface's own doc comment for why it is the only one. */
25
+ export declare function describeEndpoint(transport: TransportEndpoint['transport'], url: string | URL): TransportEndpoint;
5
26
  /**
6
27
  * M5: thrown by {@link assertServerUrlAllowed} — see that function's own doc
7
28
  * comment for the full allow/deny rule this names. Deliberately ONE error
@@ -1,9 +1,22 @@
1
1
  import { type CapabilityFlag, type Envelope, type RuntimeInfo, type ToolsetId } from '@byok-sdk/protocol';
2
+ import { type TransportEndpoint } from './url';
2
3
  export type ConnectionState = 'connecting' | 'open' | 'closed' | 'degraded' | 'revoked';
3
- /** The WS upgrade itself was rejected with a non-101 HTTP status (e.g. 401 for an expired/invalid bearer token). Surfaced via `onConnectOutcome` so `ConnectionManager` can force a reactive token renewal before the next attempt (protocol §6.2, "reactively on 401"). */
4
+ /**
5
+ * The WS upgrade itself was rejected with a non-101 HTTP status (e.g. 401 for
6
+ * an expired/invalid bearer token). Surfaced via `onConnectOutcome` so
7
+ * `ConnectionManager` can force a reactive token renewal before the next
8
+ * attempt (protocol §6.2, "reactively on 401").
9
+ *
10
+ * Carries the {@link TransportEndpoint} the rejected upgrade was aimed at, so
11
+ * a 401 in a log names WHICH server and path refused it instead of leaving
12
+ * the reader to guess between a stale `serverUrl` and a genuinely expired
13
+ * token. The endpoint's own construction is what keeps the bearer token out
14
+ * of this message — see {@link describeEndpoint}.
15
+ */
4
16
  export declare class WsUnexpectedStatusError extends Error {
5
17
  readonly status: number;
6
- constructor(status: number);
18
+ readonly endpoint: TransportEndpoint;
19
+ constructor(status: number, endpoint: TransportEndpoint);
7
20
  }
8
21
  export interface BackoffOptions {
9
22
  baseMs?: number;
@@ -27,8 +40,8 @@ export interface WsTransportOptions {
27
40
  clientVersion?: string;
28
41
  /** Detected runtimes, sent on every `conn.hello` (protocol §10 gap #4/#11). */
29
42
  runtimes?: RuntimeInfo[];
30
- /** Sorted logical IDs configured locally; no MCP executable definition crosses the wire. */
31
- configuredToolsets?: readonly ToolsetId[];
43
+ /** Reads current sorted logical IDs for every hello; no executable definition crosses the wire. */
44
+ getConfiguredToolsets?: () => readonly ToolsetId[];
32
45
  /** The redelivery cursor to send as `conn.hello.cursor` (protocol §9) — read fresh on every connect so a value learned mid-connection is used on the next reconnect. */
33
46
  getCursor?: () => number | undefined;
34
47
  onEnvelope: (envelope: Envelope) => void;
@@ -51,13 +64,25 @@ export interface WsTransportOptions {
51
64
  * and the causing error when the attempt failed before a socket even
52
65
  * opened (e.g. `getToken()` rejecting). Used by `ConnectionManager` to
53
66
  * count consecutive failures for the long-poll fallback (protocol §8).
67
+ *
68
+ * `endpoint` names the route this attempt was aimed at (computed once per
69
+ * `openSocket()`, so every outcome site reports the same one) — a
70
+ * consecutive-failure count in a log is only actionable once it says WHICH
71
+ * server kept refusing.
54
72
  */
55
- onConnectOutcome?: (acked: boolean, err?: unknown) => void;
73
+ onConnectOutcome?: (acked: boolean, err: unknown, endpoint: TransportEndpoint) => void;
56
74
  backoff?: BackoffOptions;
57
75
  liveness?: LivenessOptions;
58
76
  /** Deterministic automatic reconnect delay. Manual `connect({auto:false})` never reaches this scheduler. */
59
77
  reconnectDelayMs?: (attempt: number, baseDelayMs: number) => number;
60
78
  }
79
+ /**
80
+ * One canonical authenticated capability snapshot for both transports.
81
+ * Long-poll sends this envelope through `POST /byok/messages`; WS sends the
82
+ * same shape as its opening frame. Keeping construction here prevents one
83
+ * transport from silently omitting a newly added daemon capability.
84
+ */
85
+ export declare function createConnectionHelloEnvelope(opts: Pick<WsTransportOptions, 'deviceId' | 'productId' | 'capabilities' | 'clientVersion' | 'runtimes' | 'getConfiguredToolsets' | 'getCursor'>): Envelope;
61
86
  /**
62
87
  * The daemon's outbound-only WS connection: opens, sends `conn.hello`, waits
63
88
  * for `conn.ack`, and reconnects with capped exponential backoff + jitter on
package/dist/index.d.ts CHANGED
@@ -1,4 +1,9 @@
1
- export type { RuntimeAdapter, RuntimeAdapterDescriptor, RuntimeAdapterPrepareInput, RuntimeAdapterPrepareResult, RuntimeAdapterRejectedOperation, RuntimeAdapterPreparedOperation, PreparedRuntimeOperation, RuntimeOperationManifest, RuntimeOperationStartInput, RuntimeCapabilities, RuntimeDetectResult, Session, GitWorkspaceConfig, McpStdioServerConfig, McpToolsetConfig, } from './types';
1
+ export type { RuntimeAdapter, RuntimeAdapterDescriptor, RuntimeAdapterPrepareInput, RuntimeAdapterPrepareResult, RuntimeAdapterRejectedOperation, RuntimeAdapterPreparedOperation, PreparedRuntimeOperation, RuntimeOperationManifest, RuntimeOperationStartInput, RuntimeCapabilities, RuntimeDetectResult, Session, GitWorkspaceConfig, McpStdioServerConfig, McpToolsetConfig, McpToolsetLifecycleState, McpToolsetObservation, McpToolsetStatus, McpToolsetRegistryStatus, McpToolsetReloadReceipt, AgentEgressPolicy, } from './types';
2
+ export type { AgentRef } from './agent-home';
3
+ export { AgentHomeError, AgentRefValidationError, AgentHomeResolutionError, AgentHomeCollisionError, AgentHomeBusyError, AgentHomeLeaseCorruptError, AgentHomeLayout, AgentHomeLeaseManager, AgentHomeManager, createAgentHomeProjection, stableAgentHomeOwnerId, validateAgentRef, } from './agent-home';
4
+ export { AgentSessionHandoffStore, AgentSessionHandoffStoreError, AgentSessionHandoffCorruptError, AgentSessionHandoffMismatchError, } from './daemon/agent-session-handoff-store';
5
+ export type { AgentSessionHandoff, AgentSessionHandoffMatch, AgentTaskTerminalEvidence, AgentTaskTerminalMatch, AgentTerminalCause, } from './daemon/agent-session-handoff-store';
6
+ export type { AgentHomeResolution, AgentHomeProjection, AgentHomeProjectionInput, AgentHomeProjectionFunction, AgentHomeLease, AgentHomeBinding, } from './agent-home';
2
7
  export { PolicyUnsupportedError, SteerUnsupportedError, freezeRuntimeAdapterDescriptor, sealRuntimeOperationManifest } from './types';
3
8
  export type { RuntimeEnvironmentRequirements } from './daemon/environment';
4
9
  export { resolveLocalAgentReleaseIdentity } from './release-identity';
@@ -10,7 +15,12 @@ export type { GitWorkspaceObservation, GitWorkspaceLease, GitWorkspaceOptions, G
10
15
  export { GitWorkspaceStore } from './daemon/git-workspace-store';
11
16
  export type { GitWorkspaceLedger, GitWorkspaceLedgerRecord, GitWorkspacePhase } from './daemon/git-workspace-store';
12
17
  export { createDaemon, createDaemonWithAdapters } from './daemon/create-daemon';
13
- export type { Daemon, DaemonConfig, DaemonStatus, DaemonOverrides, DaemonBranding, HostedJournalConfig, DeviceAssertionConfig } from './daemon/create-daemon';
18
+ export type { Daemon, DaemonConfig, DaemonStatus, DaemonOverrides, DaemonBranding, HostedJournalConfig, DeviceAssertionConfig, AgentEgressConfig, AgentContentReadConfig, AgentContentReadSurfaceConfig, AgentReliableEgressInput, } from './daemon/create-daemon';
19
+ export type { AgentEgressDropReceipt, AgentEgressLaneStatus, AgentEgressStatus, } from './daemon/agent-egress-policy';
20
+ export type { AgentEgressSanitizer, AgentEgressSanitizerContext } from './daemon/agent-egress-sanitizer';
21
+ export { AGENT_CONTENT_READ_CAPABILITIES, AGENT_CONTENT_READ_CAPABILITY_WORKSPACE, AGENT_CONTENT_READ_CAPABILITY_TRANSCRIPT, AGENT_CONTENT_READ_CAPABILITY_ARTIFACT, } from './daemon/agent-content-read';
22
+ export type { AgentContentReadSurface, AgentContentReadDecision, AgentContentReadReason, AgentContentReadRoot, AgentContentReadPolicy, AgentContentReadPolicySelection, AgentContentReadRequest, AgentContentReadResult, AgentContentReadAllowed, AgentContentReadDenied, AgentContentSessionIdentity, AgentContentAuditReceipt, } from './daemon/agent-content-read';
23
+ export { McpToolsetRevisionConflictError, McpToolsetDefinitionRevisionConflictError, } from './daemon/toolset-registry';
14
24
  export type { ProgressBatcherOptions } from './daemon/progress-batcher';
15
25
  /**
16
26
  * Plan `device-assertion-broker`: the ONLY control-socket capability this