@byok-sdk/client 0.1.1 → 0.3.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.
Files changed (34) hide show
  1. package/README.md +46 -6
  2. package/dist/adapters/claude/claude-adapter.d.ts +3 -0
  3. package/dist/adapters/claude/resolve-bin.d.ts +2 -2
  4. package/dist/adapters/codex/codex-adapter.d.ts +5 -3
  5. package/dist/adapters/index.d.ts +1 -1
  6. package/dist/adapters/index.js +293 -100
  7. package/dist/adapters/index.js.map +1 -1
  8. package/dist/adapters/pi/events.d.ts +10 -37
  9. package/dist/adapters/pi/permission-mapping.d.ts +4 -20
  10. package/dist/adapters/pi/pi-adapter.d.ts +22 -0
  11. package/dist/adapters/pi/resolve-bin.d.ts +18 -14
  12. package/dist/adapters/pi/rpc-client.d.ts +1 -4
  13. package/dist/adapters/provider-credential-environment.d.ts +18 -0
  14. package/dist/bin/byok-agent.js +1839 -838
  15. package/dist/bin/byok-agent.js.map +1 -1
  16. package/dist/bin/byok-approval-mcp.js +2 -2
  17. package/dist/bin/byok-approval-mcp.js.map +1 -1
  18. package/dist/daemon/assertion-client.d.ts +68 -0
  19. package/dist/daemon/capabilities-client.d.ts +48 -0
  20. package/dist/daemon/control-protocol.d.ts +81 -4
  21. package/dist/daemon/create-daemon.d.ts +169 -1
  22. package/dist/daemon/daemon-owner.d.ts +35 -0
  23. package/dist/daemon/device-assertion-signer.d.ts +41 -0
  24. package/dist/daemon/device-keys.d.ts +15 -13
  25. package/dist/daemon/observer.d.ts +68 -3
  26. package/dist/daemon/presence-publisher.d.ts +69 -0
  27. package/dist/daemon/skill-pack-installer.d.ts +116 -0
  28. package/dist/daemon/task-runner.d.ts +129 -3
  29. package/dist/index.d.ts +22 -3
  30. package/dist/index.js +1872 -284
  31. package/dist/index.js.map +1 -1
  32. package/dist/lifecycle/create-service-lifecycle.d.ts +2 -2
  33. package/dist/types.d.ts +29 -0
  34. package/package.json +6 -5
@@ -1,5 +1,5 @@
1
- import { type Envelope, type PermissionPolicy, type RuntimeId, type TaskOfferPayload } from '@byok-sdk/protocol';
2
- import { type RuntimeAdapter } from '../types';
1
+ import { type Envelope, type PermissionPolicy, type RuntimeId, type TaskOfferPayload, type TaskOfferWithToolsetsPayload } from '@byok-sdk/protocol';
2
+ import { type McpToolsetConfig, type RuntimeAdapter } from '../types';
3
3
  import { type ApprovalDecision, type ApprovalOrigin, type ApprovalRegistry } from './approvals';
4
4
  import type { BlobResolver } from './blob-client';
5
5
  import type { TaskQueueWatermark } from './control-protocol';
@@ -101,6 +101,56 @@ export declare const MAX_TRACKED_TASK_IDS = 2000;
101
101
  export declare const MAX_DURATION_EXCEEDED_REASON_PREFIX = "resource limit exceeded: maxDurationMs";
102
102
  /** M5 batch-3 (workstream 2): same contract as {@link MAX_DURATION_EXCEEDED_REASON_PREFIX}, for `DaemonConfig.maxTaskOutputBytes` — see `TaskRunner.pump`'s own per-event byte counting. */
103
103
  export declare const MAX_OUTPUT_BYTES_EXCEEDED_REASON_PREFIX = "resource limit exceeded: maxTaskOutputBytes";
104
+ /**
105
+ * additive-minor (`task.complete.document`): same stable-PREFIX contract as
106
+ * {@link MAX_DURATION_EXCEEDED_REASON_PREFIX} above, carried by every
107
+ * `task.fail` this daemon reports because a configured
108
+ * `DaemonConfig.resultDocument` extractor produced a document that could not
109
+ * be delivered — over the cap, not JSON-serializable, or destined for a
110
+ * server that never advertised the `result-document` capability. All three
111
+ * are `retryable: false`: none of them can come out differently on a retry
112
+ * against the same server with the same extractor. Everything after the
113
+ * prefix is human-readable detail (including the measured size), not part of
114
+ * the stable shape.
115
+ *
116
+ * There is deliberately no "send it anyway" or "send it truncated" path.
117
+ * A document is the task's PRIMARY structured result, so quietly dropping or
118
+ * mangling it would report success while destroying the thing the task
119
+ * existed to produce.
120
+ */
121
+ export declare const RESULT_DOCUMENT_UNDELIVERABLE_REASON_PREFIX = "result document undeliverable";
122
+ /**
123
+ * The task identity handed to a {@link ResultDocumentExtractor} alongside the
124
+ * final output text. Deliberately minimal — identity only, no session
125
+ * handle, no workspace path, no adapter: this seam exists to turn text the
126
+ * runtime already produced into the product's own JSON, not to become a
127
+ * general-purpose end-of-task callback with access to the daemon's innards.
128
+ */
129
+ export interface ResultDocumentTask {
130
+ readonly taskId: string;
131
+ readonly sessionRef: string;
132
+ }
133
+ /**
134
+ * Host-supplied glue that turns a finished task's final output into the
135
+ * product's structured terminal result (`task.complete.document`). Returning
136
+ * `undefined` means "this task has no structured result" and completes the
137
+ * task exactly as it would have without an extractor configured at all.
138
+ *
139
+ * SYNCHRONOUS by contract, like every other single-purpose callback on
140
+ * `TaskRunnerDeps`, and the runtime ENFORCES that rather than trusting it:
141
+ * the returned value is treated as data and JSON-encoded as-is, never
142
+ * awaited, so a returned promise would encode to an empty document (`{}`) —
143
+ * a well-formed, under-cap, and completely WRONG result. A thenable return
144
+ * is therefore rejected exactly like a throw (`task.fail`, `retryable:
145
+ * false`), because delivering a confidently wrong terminal result is worse
146
+ * than delivering none.
147
+ *
148
+ * Throwing is a real outcome, not a nuisance: it fails the task
149
+ * (`retryable: false`) rather than completing it without the result the
150
+ * extractor was supposed to produce — see {@link
151
+ * RESULT_DOCUMENT_UNDELIVERABLE_REASON_PREFIX}.
152
+ */
153
+ export type ResultDocumentExtractor = (finalOutput: string, task: ResultDocumentTask) => unknown;
104
154
  /**
105
155
  * M5 batch-3 (workstream 2): default cap (64 MiB) on accumulated
106
156
  * (approximate) agent-event output bytes this daemon tolerates for a single
@@ -130,6 +180,8 @@ export interface TaskRunnerDeps {
130
180
  runtimeEnvironment?: Record<string, {
131
181
  allow?: string[];
132
182
  }>;
183
+ /** Validated, device-local registry keyed by wire-level logical toolset id. */
184
+ mcpToolsets?: ReadonlyMap<string, McpToolsetConfig>;
133
185
  permissionDefaults?: PermissionPolicy;
134
186
  workspaceRoot: string;
135
187
  deviceId: string;
@@ -240,8 +292,22 @@ export interface TaskRunnerDeps {
240
292
  */
241
293
  admissionGuard?: (offer: {
242
294
  readonly taskId: string;
243
- readonly payload: TaskOfferPayload;
295
+ readonly payload: AcceptedOfferPayload;
244
296
  }) => AdmissionGuardDecision;
297
+ /**
298
+ * additive-minor (`task.complete.document`): the host's structured-result
299
+ * extractor, consulted once per task at the moment `task.complete` is
300
+ * built — see {@link ResultDocumentExtractor} and `DaemonConfig
301
+ * .resultDocument` (`create-daemon.ts`) for the full contract.
302
+ *
303
+ * Optional, and absent by default: with no extractor supplied, the
304
+ * completion path is byte-identical to what it was before this seam
305
+ * existed — no document is computed, no capability is consulted, and
306
+ * `task.complete` carries exactly the fields it always did.
307
+ */
308
+ resultDocument?: {
309
+ readonly extract: ResultDocumentExtractor;
310
+ };
245
311
  }
246
312
  /** See {@link TaskRunnerDeps.admissionGuard}. */
247
313
  export type AdmissionGuardDecision = {
@@ -251,6 +317,7 @@ export type AdmissionGuardDecision = {
251
317
  readonly reason: string;
252
318
  readonly retryable: boolean;
253
319
  };
320
+ type AcceptedOfferPayload = TaskOfferPayload | TaskOfferWithToolsetsPayload;
254
321
  /**
255
322
  * Per-connection task orchestration: offer -> (decline | claim -> adapter
256
323
  * session -> started) -> seq-ordered progress batches -> complete/fail/
@@ -508,6 +575,8 @@ export declare class TaskRunner {
508
575
  private handleOffer;
509
576
  /** Protocol §7: an instruction too large to inline arrives as a `blobRef` — resolve it via the blob client rather than failing closed. */
510
577
  private resolveInstruction;
578
+ /** Resolve every requested logical id locally and reject missing/colliding server authority before claim. */
579
+ private resolveMcpServers;
511
580
  private pump;
512
581
  /**
513
582
  * Protocol §7: an `artifact` `AgentEvent` only names a file the runtime
@@ -824,6 +893,62 @@ export declare class TaskRunner {
824
893
  /** Pre-claim, fail-closed rejection (protocol §3.2) — never claims first. */
825
894
  private decline;
826
895
  private fail;
896
+ /**
897
+ * additive-minor (`task.complete.document`): the whole daemon-side gate
898
+ * between a configured {@link ResultDocumentExtractor} and the wire —
899
+ * called once, from the `turn_end` completion path, immediately before
900
+ * `task.complete` is built.
901
+ *
902
+ * `{deliver: true}` means "go on and send `task.complete`", carrying the
903
+ * document when there is one. `{deliver: false}` means this method has
904
+ * ALREADY reported `task.fail` and finished the task; the caller must
905
+ * return without sending anything further.
906
+ *
907
+ * Four fail-closed branches, all `retryable: false` (see
908
+ * {@link RESULT_DOCUMENT_UNDELIVERABLE_REASON_PREFIX} for why none of them
909
+ * can succeed on a retry):
910
+ *
911
+ * 1. The extractor threw — its error is surfaced, never swallowed.
912
+ * 2. The extractor returned a thenable, violating the synchronous
913
+ * contract in the one way that would otherwise ship a wrong answer.
914
+ * 3. The document is over the cap, not JSON-serializable, or not plain
915
+ * JSON data, per `checkResultDocument` — the protocol's OWN check,
916
+ * imported rather than reimplemented, so this gate and the server's
917
+ * schema validation can never disagree about what is legal.
918
+ * 4. The connected server never advertised `result-document`. Its
919
+ * tolerant `z.object()` would silently strip the field on arrival
920
+ * (`version.ts`'s own flag doc comment), so "send anyway" is not a
921
+ * degraded-but-working path — it is the task's primary structured
922
+ * result being deleted in transit with nothing reported anywhere.
923
+ *
924
+ * The capability is checked LAST, deliberately: a document that is itself
925
+ * invalid is the host's own bug and is worth reporting as such even when
926
+ * the connected server could not have accepted any document at all. It is
927
+ * then re-checked once more by the caller after its own last await, since
928
+ * a reconnect can invalidate this answer in between (F3).
929
+ *
930
+ * **Residual window (bounded, deliberately not hacked around).** Even the
931
+ * caller's re-check happens before `ConnectionManager.send` hands the
932
+ * envelope to a transport, and a queued envelope can outlive the
933
+ * connection it was queued for: a reconnect between `send()` and the
934
+ * outbox actually draining could still deliver this `task.complete` to a
935
+ * rolled-back N-1 server that strips the document. Closing that would
936
+ * mean teaching the transport outbox to inspect payload semantics and
937
+ * mint a substitute `task.fail` for a task this runner already finished —
938
+ * a second authority over terminal outcomes living in the queue, which is
939
+ * worse than the window it closes. Documented instead, here and in
940
+ * docs/protocol.md §7.2.
941
+ */
942
+ private resolveResultDocument;
943
+ /**
944
+ * Whether the CURRENTLY connected server advertised `result-document` —
945
+ * read fresh on every call, never captured, because the answer changes
946
+ * across a reconnect (`ConnectionManager.getServerCapabilities` returns
947
+ * `[]` from the moment an acked connection closes until a fresh
948
+ * `conn.ack` repopulates it). An absent `getServerCapabilities` seam is
949
+ * "no capabilities", the fail-closed reading.
950
+ */
951
+ private hasResultDocumentCapability;
827
952
  private observeGit;
828
953
  private updateGitPhaseBestEffort;
829
954
  private finish;
@@ -860,3 +985,4 @@ export declare class TaskRunner {
860
985
  */
861
986
  private pickAdapter;
862
987
  }
988
+ export {};
package/dist/index.d.ts CHANGED
@@ -1,4 +1,4 @@
1
- export type { RuntimeAdapter, RuntimeCapabilities, RuntimeDetectResult, Session, TaskContext, GitWorkspaceConfig, } from './types';
1
+ export type { RuntimeAdapter, RuntimeCapabilities, RuntimeDetectResult, Session, TaskContext, GitWorkspaceConfig, McpStdioServerConfig, McpToolsetConfig, } from './types';
2
2
  export { PolicyUnsupportedError, SteerUnsupportedError } from './types';
3
3
  export type { RuntimeEnvironmentRequirements } from './daemon/environment';
4
4
  export { GitWorkspaceManager, GitWorkspaceError, isGitWorkspaceConfig, prependGitWorkspaceGuidance } from './daemon/git-workspace';
@@ -6,7 +6,17 @@ export type { GitWorkspaceObservation, GitWorkspaceLease, GitWorkspaceOptions, G
6
6
  export { GitWorkspaceStore } from './daemon/git-workspace-store';
7
7
  export type { GitWorkspaceLedger, GitWorkspaceLedgerRecord, GitWorkspacePhase } from './daemon/git-workspace-store';
8
8
  export { createDaemon, createDaemonWithAdapters } from './daemon/create-daemon';
9
- export type { Daemon, DaemonConfig, DaemonStatus, DaemonOverrides, DaemonBranding, HostedJournalConfig } from './daemon/create-daemon';
9
+ export type { Daemon, DaemonConfig, DaemonStatus, DaemonOverrides, DaemonBranding, HostedJournalConfig, DeviceAssertionConfig } from './daemon/create-daemon';
10
+ /**
11
+ * Plan `device-assertion-broker`: the ONLY control-socket capability this
12
+ * package exposes publicly. `connectControlClient`/`ControlClient` are
13
+ * deliberately NOT exported and must never be — they also carry `shutdown`,
14
+ * approval resolution and the raw task-event stream, and exporting the client
15
+ * would make all of it public API in one line. See `daemon/assertion-client.ts`
16
+ * and the constraint test that pins this.
17
+ */
18
+ export { requestDeviceAssertion } from './daemon/assertion-client';
19
+ export type { RequestDeviceAssertionOptions, RequestDeviceAssertionResult, RequestDeviceAssertionErrorCode, } from './daemon/assertion-client';
10
20
  export type { OperationalHealthSnapshot, OperationalHealthState } from './daemon/operational-health';
11
21
  export { journalHash, JournalUnavailableError, JournalCorruptError, JournalRecordTooLargeError, JournalUnknownTaskError, JournalClosedError, } from './daemon/journal/journal';
12
22
  export type { LocalTaskJournal, JournalIdentity, JournalReceipt, ReceivedEnvelopeRecord, AdmissionRecord, LocalTransitionRecord, LocalTerminalRecord, TerminalTruthState, RecoverableTask, RecoveryOutcome, RecoveryDisposition, LocalStorageUsage, StorageCategory, CategoryUsage, CleanableCategory, CleanupCandidate, CleanupResult, CompactOptions, CompactResult, } from './daemon/journal/journal';
@@ -18,6 +28,15 @@ export type { DeviceRecord } from './daemon/store';
18
28
  export { AuthManager, DeviceRevokedError } from './daemon/auth-manager';
19
29
  export { StoredDeviceProofSigner } from './daemon/device-proof-signer';
20
30
  export type { DeviceProofRequest, DeviceProofSigner, StoredDeviceProofSignerOptions, } from './daemon/device-proof-signer';
31
+ /**
32
+ * Plan `skill-pack-delivery-channel`: the device half of the `skills.pack`
33
+ * channel. The install pipeline and the two read APIs are public because the
34
+ * HOST, not this SDK, decides where a vendor CLI keeps its skills (K4) — a host
35
+ * lists what is installed and projects the pack it wants into the directory its
36
+ * own runtime reads. Nothing here ever writes to a vendor CLI's skill directory.
37
+ */
38
+ export { SKILL_PACKS_CAPABILITY, SKILL_PACKS_DIRNAME, SKILL_PACK_AUDIT_FILENAME, SKILL_PACK_INSTALL_ERROR_CODES, SKILL_PACK_LOCK_FILENAME, SKILL_PACK_LOCK_SCHEMA, SKILL_PACK_RESPONSE_MAX_BYTES, SkillPackInstallError, installSkillPacks, listInstalledSkillPacks, projectSkillPack, skillPacksRoot, } from './daemon/skill-pack-installer';
39
+ export type { InstallSkillPacksOptions, InstalledSkillPack, ProjectedSkillPack, SkillPackInstallErrorCode, SkillPackInstallResult, SkillPackLock, } from './daemon/skill-pack-installer';
21
40
  export { TruthMemoryClient, TruthMemoryClientError } from './daemon/truth-memory-client';
22
41
  export type { LocalMemoryFilter, MemorySelector, TruthManifestQueryInput, TruthManifestRecord, TruthMemoryClientErrorCode, TruthMemoryClientOptions, TruthMemoryMetric, TruthSnapshotCandidateInput, TruthSnapshotWriteInput, TruthTerminalWriteInput, TruthWriteBody, TruthWriteResult, VerifiedTruthRecord, } from './daemon/truth-memory-client';
23
42
  export type { ConnectionState } from './daemon/ws-transport';
@@ -35,7 +54,7 @@ export { generateWinswXml } from './lifecycle/winsw';
35
54
  export { ensureSecureDir, buildIcaclsArgs, SecureDirHardeningError } from './util/secure-dir';
36
55
  export type { EnsureSecureDirOptions } from './util/secure-dir';
37
56
  export { PiAdapter } from './adapters/pi/pi-adapter';
38
- export type { PiAdapterOptions } from './adapters/pi/pi-adapter';
57
+ export type { PiAdapterOptions, PiByokLauncherConfig } from './adapters/pi/pi-adapter';
39
58
  export { PI_PACKAGE_NAME } from './adapters/pi/resolve-bin';
40
59
  export { ClaudeAdapter } from './adapters/claude/claude-adapter';
41
60
  export type { ClaudeAdapterOptions } from './adapters/claude/claude-adapter';