@byok-sdk/client 0.2.0 → 0.4.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 (46) hide show
  1. package/README.md +58 -5
  2. package/dist/adapters/claude/claude-adapter.d.ts +6 -19
  3. package/dist/adapters/claude/events.d.ts +3 -0
  4. package/dist/adapters/claude/process-client.d.ts +9 -1
  5. package/dist/adapters/codex/codex-adapter.d.ts +4 -15
  6. package/dist/adapters/codex/process-runner.d.ts +4 -1
  7. package/dist/adapters/index.d.ts +4 -2
  8. package/dist/adapters/index.js +1081 -258
  9. package/dist/adapters/index.js.map +1 -1
  10. package/dist/adapters/pi/pi-adapter.d.ts +24 -15
  11. package/dist/adapters/pi/rpc-client.d.ts +9 -1
  12. package/dist/adapters/process-tree.d.ts +19 -0
  13. package/dist/adapters/provider-credential-environment.d.ts +18 -0
  14. package/dist/bin/audit-log.d.ts +12 -0
  15. package/dist/bin/byok-agent.js +2686 -912
  16. package/dist/bin/byok-agent.js.map +1 -1
  17. package/dist/bin/byok-approval-mcp.js +2 -2
  18. package/dist/bin/byok-approval-mcp.js.map +1 -1
  19. package/dist/bin/commands/workspaces.d.ts +11 -0
  20. package/dist/bin/format.d.ts +13 -0
  21. package/dist/bin/runtime-probe.d.ts +1 -1
  22. package/dist/bin/tasks-view.d.ts +13 -0
  23. package/dist/daemon/approvals.d.ts +2 -2
  24. package/dist/daemon/assertion-client.d.ts +68 -0
  25. package/dist/daemon/capabilities-client.d.ts +48 -0
  26. package/dist/daemon/connection-manager.d.ts +4 -2
  27. package/dist/daemon/control-protocol.d.ts +81 -4
  28. package/dist/daemon/control-server.d.ts +18 -1
  29. package/dist/daemon/create-daemon.d.ts +171 -3
  30. package/dist/daemon/daemon-owner.d.ts +37 -0
  31. package/dist/daemon/device-assertion-signer.d.ts +41 -0
  32. package/dist/daemon/device-keys.d.ts +15 -13
  33. package/dist/daemon/environment.d.ts +9 -9
  34. package/dist/daemon/git-workspace.d.ts +21 -0
  35. package/dist/daemon/observer.d.ts +81 -3
  36. package/dist/daemon/presence-publisher.d.ts +98 -0
  37. package/dist/daemon/runtime-capabilities.d.ts +1 -1
  38. package/dist/daemon/skill-pack-installer.d.ts +116 -0
  39. package/dist/daemon/task-runner.d.ts +156 -37
  40. package/dist/daemon/ws-transport.d.ts +3 -1
  41. package/dist/index.d.ts +25 -4
  42. package/dist/index.js +2972 -597
  43. package/dist/index.js.map +1 -1
  44. package/dist/runtime-failure.d.ts +64 -0
  45. package/dist/types.d.ts +114 -58
  46. package/package.json +4 -4
@@ -0,0 +1,64 @@
1
+ /** Closed lifecycle phases for failures after an offer has been admitted. */
2
+ export type RuntimeFailurePhase = 'start' | 'run';
3
+ /** Closed semantic axis. Retryability is explicit and is never inferred from this field. */
4
+ export type RuntimeFailureCategory = 'semantic' | 'infrastructure' | 'authority';
5
+ /** The adapter's explicit retry judgment consumed by TaskRunner. */
6
+ export type RuntimeRetryDisposition = 'retryable' | 'non-retryable';
7
+ /** Disposal is deliberately separate from start/run retryability authority. */
8
+ export type RuntimeDisposalStage = 'signal' | 'quiescence' | 'cleanup';
9
+ export interface RuntimeDisposalFailureInput {
10
+ stage: RuntimeDisposalStage;
11
+ /** Audit-safe operational reason. It must not contain task instructions or provider credentials. */
12
+ reason: string;
13
+ }
14
+ export interface RuntimeExecutionFailureInput {
15
+ phase: RuntimeFailurePhase;
16
+ category: RuntimeFailureCategory;
17
+ retry: RuntimeRetryDisposition;
18
+ /** Stable operator-facing reason. Provider diagnostics may be included, but are never parsed by TaskRunner. */
19
+ reason: string;
20
+ }
21
+ /**
22
+ * Expected failure of an owned runtime-resource disposal barrier. This never
23
+ * carries task retryability: semantic terminal authority may already have
24
+ * been published when disposal begins.
25
+ */
26
+ export declare class RuntimeDisposalFailure extends Error {
27
+ readonly stage: RuntimeDisposalStage;
28
+ constructor(input: RuntimeDisposalFailureInput, options?: ErrorOptions);
29
+ }
30
+ export declare function isRuntimeDisposalFailure(value: unknown): value is RuntimeDisposalFailure;
31
+ /**
32
+ * The only expected post-admission failure value accepted from a runtime
33
+ * adapter. Diagnostic AgentEvents remain observability; this value alone is
34
+ * terminal control authority.
35
+ */
36
+ export declare class RuntimeExecutionFailure extends Error {
37
+ readonly phase: RuntimeFailurePhase;
38
+ readonly category: RuntimeFailureCategory;
39
+ readonly retry: RuntimeRetryDisposition;
40
+ constructor(input: RuntimeExecutionFailureInput, options?: ErrorOptions);
41
+ }
42
+ export declare function isRuntimeExecutionFailure(value: unknown): value is RuntimeExecutionFailure;
43
+ export interface RuntimeFailureProjection {
44
+ reason: string;
45
+ retryable: boolean;
46
+ }
47
+ /**
48
+ * Exhaustive wire projection for a valid typed failure. A failure from the
49
+ * wrong phase is an invalid adapter state and must be handled as an untyped
50
+ * contract violation by the caller.
51
+ */
52
+ export declare function projectRuntimeExecutionFailure(failure: RuntimeExecutionFailure): RuntimeFailureProjection;
53
+ export declare const RUNTIME_ADAPTER_CONTRACT_VIOLATION_REASON: Readonly<{
54
+ start: string;
55
+ run: string;
56
+ }>;
57
+ /**
58
+ * Validate an adapter boundary. Unknown values and typed failures reported
59
+ * for the wrong phase fail closed; their source value is returned only as a
60
+ * local diagnostic cause and never influences wire semantics.
61
+ */
62
+ export declare function projectRuntimeBoundaryFailure(value: unknown, expectedPhase: RuntimeFailurePhase): RuntimeFailureProjection & {
63
+ contractViolation: boolean;
64
+ };
package/dist/types.d.ts CHANGED
@@ -17,8 +17,14 @@ export interface RuntimeDetectResult {
17
17
  }
18
18
  /** What a runtime adapter can do, advertised so the daemon can pick/validate adapters. */
19
19
  export interface RuntimeCapabilities {
20
- steer: boolean;
21
- resume: boolean;
20
+ readonly steer: boolean;
21
+ readonly resume: boolean;
22
+ /**
23
+ * Whether this adapter can project task-scoped, locally configured MCP
24
+ * servers into the runtime without accepting executable definitions from
25
+ * the remote task. Omission is fail-closed and means unsupported.
26
+ */
27
+ readonly mcpToolsets?: boolean;
22
28
  /**
23
29
  * Whether this adapter can genuinely pause a running session on
24
30
  * `needs_approval` and resume it from an out-of-band decision — i.e.
@@ -32,14 +38,23 @@ export interface RuntimeCapabilities {
32
38
  * declare it fails to compile rather than silently defaulting to a claim
33
39
  * it cannot back.
34
40
  */
35
- approvalInteractive: boolean;
41
+ readonly approvalInteractive: boolean;
36
42
  /** Subset of {@link PermissionPolicy}'s `mode` values this adapter can express without widening. */
37
- permissionModes: string[];
43
+ readonly permissionModes: readonly string[];
44
+ }
45
+ /** One local stdio MCP server definition. Remote task payloads can never supply this shape. */
46
+ export interface McpStdioServerConfig {
47
+ command: string;
48
+ args?: readonly string[];
49
+ }
50
+ /** A logical group of local MCP servers selectable by a wire-level toolset id. */
51
+ export interface McpToolsetConfig {
52
+ mcpServers: Readonly<Record<string, McpStdioServerConfig>>;
38
53
  }
39
54
  /**
40
55
  * M4 Phase 3: the out-of-band approval channel `TaskRunner` (`daemon/
41
- * task-runner.ts`) hands to an adapter's `start()` via `TaskContext
42
- * .approvalChannel`, for a runtime whose approval mechanism genuinely needs
56
+ * task-runner.ts`) hands to a prepared operation's `start()` via
57
+ * `RuntimeOperationStartInput.approvalChannel`, for a runtime whose approval mechanism genuinely needs
43
58
  * to reach back into the daemon from OUTSIDE the adapter's own process — the
44
59
  * claude adapter's concrete case: `claude`'s `--permission-prompt-tool`
45
60
  * resolves a pending permission entirely inside a SEPARATE MCP-server child
@@ -70,24 +85,6 @@ export interface ApprovalChannel {
70
85
  /** Resolve the single currently-pending out-of-band approval for this task. Rejects if none is pending right now. */
71
86
  resolve(approved: boolean, reason?: string): Promise<void>;
72
87
  }
73
- /**
74
- * Per-task execution context handed to {@link RuntimeAdapter.start}. `policy`
75
- * is the already fail-closed-checked *effective* policy (offer policy merged
76
- * against the daemon's configured ceiling) — the adapter must obey this, not
77
- * whatever the raw task offer's own `policy` field said.
78
- */
79
- export interface TaskContext {
80
- workspaceDir: string;
81
- policy: PermissionPolicy;
82
- env: NodeJS.ProcessEnv;
83
- /** Prepared local checkpoint repository metadata; absent for legacy plain workspaces. */
84
- gitWorkspace?: {
85
- workspaceId: string;
86
- baseline?: string;
87
- };
88
- /** M4 Phase 3 — see {@link ApprovalChannel}. Optional/adapter-agnostic: unset for every adapter that never requests an out-of-band approval. */
89
- approvalChannel?: ApprovalChannel;
90
- }
91
88
  /**
92
89
  * A running (or resumable) unit of work on a runtime. One `Session` maps to
93
90
  * one underlying runtime process/session for the lifetime of a task.
@@ -103,7 +100,12 @@ export interface Session {
103
100
  followUp(task: TaskOfferPayload): Promise<void>;
104
101
  /** Best-effort abort of the current turn (used for `task.cancel`). */
105
102
  interrupt(): Promise<void>;
106
- /** Tear down the underlying runtime process/session. Idempotent. */
103
+ /**
104
+ * Bounded, idempotent disposal receipt. Resolution proves every
105
+ * adapter-owned process and task-scoped resource is quiescent. Expected
106
+ * failure rejects with `RuntimeDisposalFailure` and never changes task
107
+ * semantics.
108
+ */
107
109
  close(): Promise<void>;
108
110
  /**
109
111
  * Resolve a session paused on `needs_approval` (protocol §5). The
@@ -121,50 +123,104 @@ export interface Session {
121
123
  resolveApproval(approved: boolean, reason?: string): Promise<void>;
122
124
  }
123
125
  /**
124
- * Uniform seam every concrete runtime (pi now; claude/codex in M2) implements.
126
+ * Immutable runtime facts shared by discovery and one prepared operation.
125
127
  *
126
- * Credential-isolation rule: an adapter spawns only the runtime's official
127
- * binary. It never reads, proxies, or forwards that runtime's own credential
128
- * storage (OAuth tokens, API keys on disk, `~/.claude`, `~/.codex`, `~/.pi`
129
- * auth state, etc). Presence checks are limited to environment variable
130
- * *names* (see {@link RuntimeDetectResult.authPresent}).
131
- *
132
- * M5: separately, {@link RuntimeAdapter.environmentRequirements} below
133
- * declares which environment variable NAMES (never values inspected here
134
- * either) this adapter's runtime needs forwarded into its own spawned
135
- * process — see that method's own doc comment and `daemon/environment.ts`.
128
+ * The SDK snapshots this value before each offer and never consults adapter
129
+ * capability authority again during admission, claim, environment projection,
130
+ * or start. Credential declarations are names only, never values.
131
+ */
132
+ export interface RuntimeAdapterDescriptor {
133
+ readonly id: string;
134
+ readonly capabilities: RuntimeCapabilities;
135
+ readonly environmentRequirements: RuntimeEnvironmentRequirements;
136
+ /** Explicit opt-in to authoritative `task.offer.dispatchSelection` semantics. */
137
+ readonly supportsDispatchSelection: boolean;
138
+ }
139
+ /** The pure input to one adapter admission decision. It contains no credential values or workspace resources. */
140
+ export interface RuntimeAdapterPrepareInput {
141
+ offer: TaskOfferPayload;
142
+ policy: PermissionPolicy;
143
+ descriptor: RuntimeAdapterDescriptor;
144
+ requiredToolsetIds: readonly string[];
145
+ /** Locally resolved MCP authority; available for pure admission validation only. */
146
+ mcpServers?: Readonly<Record<string, McpStdioServerConfig>>;
147
+ }
148
+ /** A permanent or currently-unavailable pre-claim admission rejection. */
149
+ export interface RuntimeAdapterRejectedOperation {
150
+ kind: 'reject';
151
+ reason: string;
152
+ retryable: boolean;
153
+ }
154
+ /** The side-effect-free adapter decision made before TaskRunner claims an offer. */
155
+ export interface RuntimeAdapterPreparedOperation {
156
+ kind: 'prepared';
157
+ operation: PreparedRuntimeOperation;
158
+ }
159
+ export type RuntimeAdapterPrepareResult = RuntimeAdapterRejectedOperation | RuntimeAdapterPreparedOperation;
160
+ /**
161
+ * Credential-free immutable identity for one admitted runtime operation.
162
+ * It can be emitted, compared, and passed to a prepared operation, but never
163
+ * serializes environment values or credential material.
164
+ */
165
+ export interface RuntimeOperationManifest {
166
+ readonly taskId: string;
167
+ /** Selected runtime id; lane/provider/model, when present, live only in `dispatchSelection`. */
168
+ readonly runtimeId: string;
169
+ readonly descriptor: RuntimeAdapterDescriptor;
170
+ readonly policy: PermissionPolicy;
171
+ readonly requiredToolsetIds: readonly string[];
172
+ /** The credential-free runtime/lane/provider/model authority for this operation. */
173
+ readonly dispatchSelection?: TaskOfferPayload['dispatchSelection'];
174
+ readonly sessionRef?: string;
175
+ readonly workspace: {
176
+ readonly workspaceDir: string;
177
+ readonly workspaceId?: string;
178
+ readonly baseline?: string;
179
+ };
180
+ /** Names are audit-safe; credential values intentionally never enter the manifest. */
181
+ readonly forwardedEnvironmentNames: readonly string[];
182
+ }
183
+ /** Runtime resources only available after TaskRunner has sealed the manifest and claimed the task. */
184
+ export interface RuntimeOperationStartInput {
185
+ readonly manifest: RuntimeOperationManifest;
186
+ readonly instruction: string;
187
+ readonly env: NodeJS.ProcessEnv;
188
+ /** Local MCP authority resolved from logical wire ids. */
189
+ readonly mcpServers?: Readonly<Record<string, McpStdioServerConfig>>;
190
+ /** Optional, adapter-agnostic out-of-band approval channel. */
191
+ readonly approvalChannel?: ApprovalChannel;
192
+ }
193
+ /** A pinned provider/runtime decision. `start()` receives resources only, never a raw offer. */
194
+ export interface PreparedRuntimeOperation {
195
+ start(input: RuntimeOperationStartInput): Promise<Session>;
196
+ }
197
+ /**
198
+ * Uniform public adapter seam. `prepare()` is required and must not spawn,
199
+ * create temp files, mutate a workspace, allocate a session id, or read a
200
+ * credential value. There is intentionally no direct `RuntimeAdapter.start`.
136
201
  */
137
202
  export interface RuntimeAdapter {
138
- id: string;
203
+ readonly descriptor: RuntimeAdapterDescriptor;
139
204
  detect(): Promise<RuntimeDetectResult>;
140
- capabilities(): RuntimeCapabilities;
141
- start(task: TaskOfferPayload, ctx: TaskContext): Promise<Session>;
142
- /**
143
- * M5: declares which environment variable names (exact, or `*`-suffixed
144
- * prefix) this runtime's own CLI needs beyond the always-included
145
- * platform baseline (`daemon/environment.ts`'s `buildRuntimeEnv`) —
146
- * `task-runner.ts` builds each task's `TaskContext.env` from this instead
147
- * of ever handing a spawned agent the daemon's raw `process.env` again.
148
- * Optional and fail-closed by omission: an adapter that doesn't implement
149
- * this gets the platform baseline ONLY, never an implicit "everything."
150
- */
151
- environmentRequirements?(): RuntimeEnvironmentRequirements;
205
+ prepare(input: RuntimeAdapterPrepareInput): Promise<RuntimeAdapterPrepareResult>;
152
206
  }
207
+ /** Copy then deeply freeze descriptor authority so callers cannot retain a mutable source reference. */
208
+ export declare function freezeRuntimeAdapterDescriptor(descriptor: RuntimeAdapterDescriptor): RuntimeAdapterDescriptor;
209
+ /** Copy then freeze the complete safe operation authority just before claim. */
210
+ export declare function sealRuntimeOperationManifest(manifest: RuntimeOperationManifest): RuntimeOperationManifest;
153
211
  /**
154
- * Thrown by `RuntimeAdapter.start` when the task can never succeed on this
155
- * adapter as offered an unsupported `PermissionPolicy` (fail-closed) or an
156
- * instruction shape the adapter can't handle (e.g. a blob-ref in M0) as
157
- * opposed to a transient/environmental failure (spawn error, missing
158
- * credentials) that might succeed on a later retry. The daemon uses this
159
- * distinction to set `task.fail`'s `retryable` flag correctly instead of
160
- * treating every `start()` failure the same way.
212
+ * Thrown by a prepared operation's `start()` when an already admitted task
213
+ * cannot continue because an internal invariant was violated. Permanent
214
+ * offer semantics are rejected by `RuntimeAdapter.prepare()` before claim;
215
+ * this class remains for post-claim operational/session failures whose
216
+ * retryability is already part of the frozen task behavior.
161
217
  */
162
218
  export declare class PolicyUnsupportedError extends Error {
163
219
  constructor(message: string);
164
220
  }
165
221
  /**
166
222
  * Thrown by {@link Session.steer} on an adapter whose runtime has no
167
- * mid-turn steering channel at all (`capabilities().steer === false`) — a
223
+ * mid-turn steering channel at all (`descriptor.capabilities.steer === false`) — a
168
224
  * permanent property of the runtime, never a transient failure. Typed
169
225
  * rather than a bare `Error` so the daemon can classify an inbound
170
226
  * `task.steer` for such a runtime as non-retryable (record + ack, cursor
@@ -172,7 +228,7 @@ export declare class PolicyUnsupportedError extends Error {
172
228
  * on message strings.
173
229
  */
174
230
  export declare class SteerUnsupportedError extends Error {
175
- /** The `RuntimeAdapter.id` that cannot steer (e.g. `claude`, `codex`). */
231
+ /** The `RuntimeAdapter.descriptor.id` that cannot steer (e.g. `claude`, `codex`). */
176
232
  readonly runtimeId: string;
177
233
  constructor(runtimeId: string, message: string);
178
234
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@byok-sdk/client",
3
- "version": "0.2.0",
3
+ "version": "0.4.0",
4
4
  "description": "BYOK SDK client daemon: runs on the end user's machine, pairs with a SaaS server, and drives a local coding-agent runtime",
5
5
  "type": "module",
6
6
  "license": "MIT",
@@ -46,13 +46,13 @@
46
46
  "dependencies": {
47
47
  "@earendil-works/pi-coding-agent": "0.84.1",
48
48
  "ws": "^8.21.1",
49
- "@byok-sdk/core": "0.2.0",
50
- "@byok-sdk/protocol": "0.2.0"
49
+ "@byok-sdk/core": "0.4.0",
50
+ "@byok-sdk/protocol": "0.4.0"
51
51
  },
52
52
  "devDependencies": {
53
53
  "@types/ws": "^8.18.1",
54
54
  "@hono/node-server": "^2.0.10",
55
- "@byok-sdk/server": "0.2.0"
55
+ "@byok-sdk/server": "0.4.0"
56
56
  },
57
57
  "scripts": {
58
58
  "build": "tsup && tsc -p tsconfig.build.json && node scripts/check-adapters-entry.mjs",