@byok-sdk/client 0.13.0 → 0.15.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (69) hide show
  1. package/README.md +95 -0
  2. package/dist/adapters/claude/process-client.d.ts +24 -0
  3. package/dist/adapters/codex/codex-adapter.d.ts +2 -0
  4. package/dist/adapters/codex/process-runner.d.ts +62 -18
  5. package/dist/adapters/detect-outcome.d.ts +18 -0
  6. package/dist/adapters/index.d.ts +1 -1
  7. package/dist/adapters/index.js +546 -76
  8. package/dist/adapters/index.js.map +1 -1
  9. package/dist/adapters/pi/events.d.ts +1 -1
  10. package/dist/adapters/pi/rpc-client.d.ts +47 -1
  11. package/dist/adapters/pi/subagents-policy-extension.js +1 -1
  12. package/dist/adapters/pi/subagents-policy-extension.js.map +1 -1
  13. package/dist/adapters/pi/team-interaction-extension.d.ts +24 -0
  14. package/dist/adapters/pi/team-interaction-extension.js +81 -0
  15. package/dist/adapters/pi/team-interaction-extension.js.map +1 -0
  16. package/dist/adapters/process-tree.d.ts +74 -4
  17. package/dist/adapters/provider-credential-environment.d.ts +1 -1
  18. package/dist/adapters/win32-job-object.d.ts +101 -0
  19. package/dist/bin/byok-agent-memory-mcp.js +29 -0
  20. package/dist/bin/byok-agent-memory-mcp.js.map +1 -1
  21. package/dist/bin/byok-agent-message-mcp.js +29 -0
  22. package/dist/bin/byok-agent-message-mcp.js.map +1 -1
  23. package/dist/bin/byok-agent-team-mcp.js +29 -0
  24. package/dist/bin/byok-agent-team-mcp.js.map +1 -1
  25. package/dist/bin/byok-agent.js +20274 -18057
  26. package/dist/bin/byok-agent.js.map +1 -1
  27. package/dist/bin/byok-approval-mcp.js +29 -0
  28. package/dist/bin/byok-approval-mcp.js.map +1 -1
  29. package/dist/bin/byok-mcp-env.d.ts +2 -0
  30. package/dist/bin/byok-mcp-env.js +36 -0
  31. package/dist/bin/byok-mcp-env.js.map +1 -0
  32. package/dist/bin/commands/doctor.d.ts +3 -0
  33. package/dist/bin/commands/team-pi-relay.d.ts +24 -0
  34. package/dist/bin/commands/team-relay.d.ts +11 -0
  35. package/dist/bin/mcp-env-launcher.d.ts +5 -0
  36. package/dist/bin/runtime-probe.d.ts +6 -7
  37. package/dist/bin/team-codex-relay.d.ts +32 -0
  38. package/dist/bin/team-notification-relay.d.ts +40 -0
  39. package/dist/bin/team-pi-session.d.ts +59 -0
  40. package/dist/daemon/admission-wait.d.ts +2 -0
  41. package/dist/daemon/agent-egress-policy.d.ts +8 -0
  42. package/dist/daemon/agent-egress-spool.d.ts +1 -0
  43. package/dist/daemon/agent-message-outbox.d.ts +15 -3
  44. package/dist/daemon/artifact-read.d.ts +7 -0
  45. package/dist/daemon/connection-manager.d.ts +23 -176
  46. package/dist/daemon/control-protocol.d.ts +2 -0
  47. package/dist/daemon/create-daemon.d.ts +43 -1
  48. package/dist/daemon/event-spill.d.ts +90 -0
  49. package/dist/daemon/journal/journal.d.ts +15 -3
  50. package/dist/daemon/journal/sqlite-journal.d.ts +7 -2
  51. package/dist/daemon/long-poll-transport.d.ts +2 -50
  52. package/dist/daemon/runtime-start.d.ts +3 -0
  53. package/dist/daemon/store.d.ts +2 -0
  54. package/dist/daemon/task-runner.d.ts +36 -0
  55. package/dist/daemon/team-workspace.d.ts +9 -0
  56. package/dist/daemon/terminal-commit-queue.d.ts +21 -0
  57. package/dist/daemon/terminal-identity.d.ts +6 -0
  58. package/dist/diagnostics/device-doctor.d.ts +46 -0
  59. package/dist/diagnostics/diagnostics.d.ts +3 -80
  60. package/dist/diagnostics/types.d.ts +82 -0
  61. package/dist/index.d.ts +3 -1
  62. package/dist/index.js +2824 -649
  63. package/dist/index.js.map +1 -1
  64. package/dist/runtime-detection.d.ts +3 -0
  65. package/dist/runtime-failure.d.ts +6 -0
  66. package/dist/sdk-reserved-helper-host.d.ts +1 -1
  67. package/dist/types.d.ts +20 -10
  68. package/dist/util/durable-jsonl.d.ts +12 -0
  69. package/package.json +8 -5
package/README.md CHANGED
@@ -1,5 +1,20 @@
1
1
  # @byok-sdk/client
2
2
 
3
+ ## Diagnostics and recovery integration
4
+
5
+ Use the SDK-maintained [downstream guide](https://github.com/Ancienttwo/byok-sdk/blob/main/docs/agent-diagnostics-integration.md)
6
+ to build diagnostic UI and local repair flows. `byok-agent doctor --json` is
7
+ the current read-only CLI entrypoint; `--fix --yes` only quarantines confirmed-corrupt
8
+ operational health state with the daemon stopped. It does not repair an Agent
9
+ or rebuild its journal. The guide includes integration limits and acceptance
10
+ scenarios; qualify them against the exact SDK artifact shipped by your product.
11
+
12
+ The public `diagnoseDevice` API accepts the host's actual adapters.
13
+ `repairDeviceEnrollmentMetadata` (or the named CLI `--repair restore-enrollment-metadata`
14
+ action) restores missing/valid-stale non-secret enrollment metadata from its
15
+ existing OS authority, with confirmation, exact expected tenant/device and
16
+ exclusive store ownership. It does not renew credentials or prove Agent readiness.
17
+
3
18
  ## Exact provider-profile admission
4
19
 
5
20
  When `DaemonConfig.piByokLauncher` is configured, the daemon advertises the
@@ -354,4 +369,84 @@ plain watcher. Native Windows returns `unsupported_platform` for the tmux view.
354
369
  The launcher never uses `send-keys` or `capture-pane`; tmux displays the
355
370
  daemon-owned stream but is never message transport or protocol authority.
356
371
 
372
+ ### Automatic notification for two existing Codex sessions
373
+
374
+ Configure two operator-owned Codex app-server sessions with their respective
375
+ `team join` MCP grants. Record each exact native thread UUID and local endpoint.
376
+ The relay does not create sessions or verify your member-to-session mapping.
377
+ Write an absolute-path JSON file with mode `0600` (its contexts are bearer secrets):
378
+
379
+ ```json
380
+ {"version":1,"bindings":[
381
+ {"context":"<member-a-context>","threadId":"<native-thread-a-uuid>","endpoint":"ws://127.0.0.1:9101","afterSeq":0},
382
+ {"context":"<member-b-context>","threadId":"<native-thread-b-uuid>","endpoint":"ws://127.0.0.1:9102","afterSeq":0}
383
+ ]}
384
+ ```
385
+
386
+ ```bash
387
+ byok-agent team relay dev --bindings /absolute/private-bindings.json --codex-bin /absolute/codex --max-notifications 2 --config /absolute/agent.json
388
+ ```
389
+
390
+ POSIX only; the executable must report `codex-cli 0.153.4`, the qualified native
391
+ queue version. Endpoints must be explicit loopback `ws://127.0.0.1:<port>` /
392
+ `ws://[::1]:<port>` or `unix:///absolute/socket`. No remote server discovery. Loopback app-server queue endpoints trust local
393
+ processes; the relay does not add authentication to the native Codex endpoint.
394
+ Keep the foreground command open and enter `pause`, `resume`, `status`, or `stop`;
395
+ SIGINT/SIGTERM also stop. Output includes queue attempts/receipts and redacted
396
+ state. A successful queue receipt means accepted notification, not completed work.
397
+ The model reads, replies and acknowledges with the existing Team MCP tools.
398
+
399
+ The required budget counts every attempt, capped at 100. Unknown delivery,
400
+ revoked/expired grant or control failure stops without retry. An operator stop
401
+ during enqueue can report `stopped` with `queue_delivery_unknown`: aborting the
402
+ local queue process cannot prove the native server rejected the notification. Pause does not undo
403
+ queued work. A room lock rejects concurrent relays; inspect the recorded owner
404
+ before manually removing a stale `<storeDir>/team-relay-locks/<room>.lock`.
405
+ Watermarks are process-local. On restart choose `afterSeq` explicitly from prior
406
+ status and actual room receipts; do not assume automatic crash replay, exactly-once
407
+ or guaranteed at-least-once delivery. Renewing grants requires explicitly updating
408
+ both the session MCP grant and binding file. tmux remains an optional view.
409
+
410
+ ### Codex + Pi through a GUI host
411
+
412
+ `team pi-relay` owns a fresh Pi **0.85.1** RPC child alongside your existing Codex
413
+ session. Prepare a private `0600` absolute-path binding document:
414
+
415
+ ```json
416
+ {"version":1,"codex":{"context":"<codex-grant>","threadId":"<uuid>","endpoint":"ws://127.0.0.1:9101","afterSeq":0},"pi":{"context":"<pi-grant>","afterSeq":0,"cwd":"/absolute/workspace","sessionDir":"/absolute/new-session-dir","provider":"<provider>","model":"<model>","systemPrompt":"<explicit instructions>","extensionPaths":[]}}
417
+ ```
418
+
419
+ The session directory must not exist; its parent must exist. The SDK supplies the
420
+ Pi Team MCP tools and guard extension. Additional absolute extension paths are
421
+ operator-trusted code, loaded after the guard. Ambient extension loading is off.
422
+
423
+ ```bash
424
+ byok-agent team pi-relay dev --bindings /absolute/private.json --codex-bin /absolute/codex --max-notifications 2 --config /absolute/agent.json
425
+ ```
426
+
427
+ Connect a GUI backend to stdin/stdout JSONL. This command provides the interface;
428
+ it does not include a GUI app. Keep stdin open while the session runs.
429
+
430
+ ```json
431
+ {"command":"status"}
432
+ {"command":"pause"}
433
+ {"command":"resume"}
434
+ {"command":"input","sessionId":"<pi_ready sessionId>","message":"<operator input>"}
435
+ {"command":"respond","sessionId":"<ui_request sessionId>","requestId":"<request.id>","response":{"cancelled":true}}
436
+ {"command":"stop"}
437
+ ```
438
+
439
+ For confirm, use `{"confirmed":true}` or `false`; for select/input/editor, use
440
+ `{"value":"..."}`. Exactly one response field is accepted. Wrong session, stale ID,
441
+ duplicate answer or mismatched shape is rejected. `ui_response_sent` confirms pipe
442
+ write only: Pi may have expired that ID. Expiry leaves the GUI item pending until
443
+ you explicitly dismiss it. Render `ui_request.request` as untrusted display data.
444
+
445
+ The first-loaded native guard holds input/provider admission during Pi UI spans.
446
+ `pi_gate` reports that state; `pi_settled` reports completed native work. Busy Pi
447
+ waits for readiness. A 30-second unresolved RPC stops the owned process, without
448
+ retry. Budget exhaustion drains accepted Pi work for up to 120 seconds; explicit
449
+ stop or stdin EOF terminates it. Neither pause nor a new dialog recalls already
450
+ admitted work. Runtime/grants remain separate from the native Codex session.
451
+
357
452
  MIT licensed. Node.js 22.22.0 or newer.
@@ -7,6 +7,17 @@ export interface ClaudeProcessClientOptions {
7
7
  cwd: string;
8
8
  env: NodeJS.ProcessEnv;
9
9
  spawnFn?: SpawnFn;
10
+ /**
11
+ * DI seam scoped to ADOPTION only (`../process-tree.ts`'s
12
+ * `adoptOwnedProcessTree`), so the win32 job-object branch is exercisable
13
+ * from POSIX. Disposal keeps `process.platform` as its own authority — this
14
+ * must never silently reroute the taskkill sweep on a real host.
15
+ */
16
+ platform?: NodeJS.Platform;
17
+ /** DI seam for the win32 job-object backstop; see `../win32-job-object.ts`. */
18
+ jobObject?: {
19
+ assign(pid: number): Promise<void>;
20
+ };
10
21
  }
11
22
  /**
12
23
  * NDJSON process transport for `claude -p --input-format stream-json
@@ -55,6 +66,10 @@ export declare class ClaudeProcessClient {
55
66
  private readonly closedPromise;
56
67
  private resolveClosed;
57
68
  private disposalAttempt;
69
+ /** Resolves once this tree is backstopped (see `adoptOwnedProcessTree`); rejects with the adoption failure, having already terminated the tree. */
70
+ private readonly adopted;
71
+ /** Set before the fail-closed termination starts, so it — not the exit code of the kill we ourselves requested — becomes this client's exit error. */
72
+ private adoptionFailure;
58
73
  private readonly stderrRing;
59
74
  private readonly unmappedFrameCounts;
60
75
  private sessionId;
@@ -108,6 +123,15 @@ export declare class ClaudeProcessClient {
108
123
  waitClosed(): Promise<void>;
109
124
  dispose(): Promise<void>;
110
125
  private processTreeOptions;
126
+ /**
127
+ * Backstop this tree, or tear it down. Adoption failure is a start-time
128
+ * precondition, not a degraded mode: the child is terminated through the one
129
+ * disposal authority and the failure is re-thrown, which is what makes
130
+ * `waitForInit()` — and therefore `ClaudeAdapter.start()` — fail before any
131
+ * session is published. Both cleanup attempts are best-effort because the
132
+ * adoption failure, not a terminator's own complaint, is the reason to report.
133
+ */
134
+ private adoptOwnedTree;
111
135
  private onData;
112
136
  private onLine;
113
137
  private onStderr;
@@ -1,7 +1,9 @@
1
+ import { type SdkHelperHostConfig } from '../../sdk-reserved-helper-host';
1
2
  import { type RuntimeAdapter, type RuntimeDetectResult, type RuntimeAdapterPrepareInput, type RuntimeAdapterPrepareResult } from '../../types';
2
3
  import { type ResolvedBin } from './resolve-bin';
3
4
  import { type SpawnFn } from './process-runner';
4
5
  export interface CodexAdapterOptions {
6
+ sdkHelperHost?: SdkHelperHostConfig;
5
7
  /** Override bin resolution — tests substitute the fake-codex fixture script. */
6
8
  resolveBin?: () => ResolvedBin;
7
9
  /** Override process spawning — tests substitute a fake spawn. */
@@ -1,3 +1,4 @@
1
+ import { RuntimeExecutionFailure } from '../../runtime-failure';
1
2
  import { spawn } from 'node:child_process';
2
3
  export type SpawnFn = typeof spawn;
3
4
  /**
@@ -14,12 +15,28 @@ export interface CodexRawEvent {
14
15
  export interface CodexProcessOptions {
15
16
  command: string;
16
17
  args: string[];
18
+ instruction?: string;
17
19
  cwd: string;
18
20
  env: NodeJS.ProcessEnv;
19
21
  spawnFn?: SpawnFn;
20
22
  /** Called once per parsed JSONL line, in arrival order. */
21
23
  onEvent: (evt: CodexRawEvent) => void;
24
+ onFailure?: (error: RuntimeExecutionFailure) => void;
25
+ /**
26
+ * DI seam scoped to ADOPTION only (`../process-tree.ts`'s
27
+ * `adoptOwnedProcessTree`), so the win32 job-object branch is exercisable
28
+ * from POSIX. Disposal keeps `process.platform` as its own authority — this
29
+ * must never silently reroute the taskkill sweep on a real host.
30
+ */
31
+ platform?: NodeJS.Platform;
32
+ /** DI seam for the win32 job-object backstop; see `../win32-job-object.ts`. */
33
+ jobObject?: {
34
+ assign(pid: number): Promise<void>;
35
+ };
22
36
  }
37
+ export declare const CODEX_MAX_FRAME_BYTES: number;
38
+ export declare const CODEX_MAX_DEFERRED_BYTES: number;
39
+ export declare const CODEX_MAX_STDERR_BYTES: number;
23
40
  /**
24
41
  * Spawns and streams ONE `codex exec` / `codex exec resume` invocation — i.e.
25
42
  * exactly one turn.
@@ -27,32 +44,24 @@ export interface CodexProcessOptions {
27
44
  * Unlike pi (a single long-lived RPC server process for a whole session's
28
45
  * lifetime — see `../pi/rpc-client.ts`), `codex exec` is a one-shot batch
29
46
  * process per turn with no persistent request/response channel: it takes its
30
- * prompt as an argv positional, streams JSONL to stdout for the one turn
47
+ * prompt from stdin with the documented `-` positional, streams JSONL to stdout for the one turn
31
48
  * it's running, and exits. `../codex-adapter.ts`'s `CodexSession` constructs
32
49
  * a fresh `CodexProcessRunner` for every turn (the initial `start()` and
33
50
  * every later `followUp()`), forwarding each one's lines into the same
34
51
  * long-lived event queue.
35
52
  *
36
- * stdin is deliberately never piped to the child (`stdio: ['ignore', 'pipe',
37
- * 'pipe']`): `codex exec --help` documents that a piped, non-TTY stdin is
38
- * read and appended to the prompt as a `<stdin>` block even when a prompt was
39
- * ALSO given as an argv positional, and empirically every single real
40
- * invocation made while building this adapter logged "Reading additional
41
- * input from stdin..." on stderr regardless of whether a prompt argument was
42
- * given. Leaving `stdio: ['pipe', ...]` open for stdin and never closing it
43
- * risks codex blocking on that read forever — exactly the hang class this
44
- * task was built to avoid (the pi adapter's own `agent_end`/`agent_settled`
45
- * mismatch left a task stuck `Running` forever in the M0/M1 GLM run).
46
- * `'ignore'` presents immediate EOF instead, which was verified live with a
47
- * dedicated Node `child_process` probe before this was written: no hang,
48
- * clean completion at normal model latency. This adapter never needs to
49
- * SEND codex anything over stdin — there is no in-band steer/approval
50
- * protocol (see `../codex-adapter.ts`'s `steer`/`resolveApproval`).
53
+ * Prompt stdin is closed with EOF immediately after writing. This is a one-shot
54
+ * input channel; steer and approvals are not multiplexed over it.
51
55
  */
52
56
  export declare class CodexProcessRunner {
53
57
  private readonly child;
54
58
  private readonly onEvent;
55
- private buffer;
59
+ private readonly frameChunks;
60
+ private frameBytes;
61
+ private deferredBytes;
62
+ private stderrBytes;
63
+ private transportFailure;
64
+ private readonly onFailure;
56
65
  private readonly stderrRing;
57
66
  private closed;
58
67
  private exitCode;
@@ -60,6 +69,19 @@ export declare class CodexProcessRunner {
60
69
  private readonly closedPromise;
61
70
  private resolveClosed;
62
71
  private disposalAttempt;
72
+ /** Resolves once this tree is backstopped (see `adoptOwnedProcessTree`); rejects with the adoption failure, having already terminated the tree. */
73
+ private readonly adopted;
74
+ /** Set before the fail-closed termination starts; `buildExitError` reports it instead of the exit status of the kill we ourselves requested. */
75
+ private adoptionFailure;
76
+ private adoption;
77
+ /**
78
+ * Lines parsed before adoption settled. Unlike pi and claude, this runner has
79
+ * no first awaited operation of its own to gate on — its caller reads the
80
+ * FIRST event as the authoritative thread id. Holding events until the tree
81
+ * is backstopped is what keeps that caller from publishing a session for a
82
+ * tree the job object never took.
83
+ */
84
+ private readonly deferredEvents;
63
85
  constructor(options: CodexProcessOptions);
64
86
  private finishClosing;
65
87
  /** Resolves once the child process has fully exited (both exit and stdio-flush guaranteed — see the `close` listener above). Never rejects. */
@@ -86,8 +108,30 @@ export declare class CodexProcessRunner {
86
108
  kill(): void;
87
109
  dispose(): Promise<void>;
88
110
  private processTreeOptions;
89
- /** Builds a descriptive error folding in the exit code/signal and the stderr tail — mirrors `PiRpcClient.buildExitError`'s reasoning: a post-mortem on a failed start/resume should never need separately re-running codex by hand with a raw JSONL logger to learn why. */
111
+ /**
112
+ * Backstop this tree, or tear it down. Adoption failure is a start-time
113
+ * precondition, not a degraded mode: the child is terminated through the one
114
+ * disposal authority, every parsed line is dropped instead of delivered, and
115
+ * the resulting close makes the caller's own `waitClosed()` race reject with
116
+ * the adoption failure (`buildExitError`) before a thread id is published.
117
+ * Both cleanup attempts are best-effort because the adoption failure, not a
118
+ * terminator's own complaint, is the reason to report.
119
+ */
120
+ private adoptOwnedTree;
121
+ /** Arrival-order delivery, held back until the tree is backstopped (see `deferredEvents`). */
122
+ private deliver;
123
+ /**
124
+ * Builds a descriptive error folding in the exit code/signal and the stderr
125
+ * tail — mirrors `PiRpcClient.buildExitError`'s reasoning: a post-mortem on a
126
+ * failed start/resume should never need separately re-running codex by hand
127
+ * with a raw JSONL logger to learn why.
128
+ *
129
+ * A tree this runner could not backstop is the one exception: that process
130
+ * exited because THIS runner killed it, so `exit code=null, signal=SIGKILL`
131
+ * plus an empty stderr tail would bury the only reason anyone can act on.
132
+ */
90
133
  buildExitError(context: string): Error;
134
+ private failTransport;
91
135
  private onData;
92
136
  private parseLine;
93
137
  private onStderr;
@@ -0,0 +1,18 @@
1
+ import type { RuntimeDetectResult } from '../types';
2
+ type ProbeFailure = Exclude<RuntimeDetectResult, {
3
+ kind: 'available';
4
+ }>;
5
+ type VersionProbeResult = ProbeFailure | {
6
+ kind: 'available';
7
+ stdout: string;
8
+ stderr: string;
9
+ };
10
+ /** OS/process codes only. Arbitrary messages, streams and resolver paths never escape. */
11
+ export declare function classifyDetectError(error: unknown): ProbeFailure;
12
+ /**
13
+ * This probe owns both the deadline and the version child. A killed child is
14
+ * not by itself timeout evidence (execFile also kills on output overflow).
15
+ * Resolve only at execFile completion; SIGKILL bounds a TERM-ignoring probe.
16
+ */
17
+ export declare function probeRuntimeVersion(command: string, timeoutMs: number): Promise<VersionProbeResult>;
18
+ export {};
@@ -1,6 +1,6 @@
1
1
  export type { RuntimeAdapter, RuntimeAdapterDescriptor, RuntimeAdapterPrepareInput, RuntimeAdapterPrepareResult, RuntimeAdapterRejectedOperation, RuntimeAdapterPreparedOperation, PreparedRuntimeOperation, RuntimeOperationManifest, RuntimeOperationStartInput, RuntimeCapabilities, RuntimeDetectResult, } from '../types';
2
2
  export type { RuntimeEnvironmentRequirements } from '../daemon/environment';
3
- export { RuntimeDisposalFailure, RuntimeExecutionFailure } from '../runtime-failure';
3
+ export { RuntimeDisposalFailure, RuntimeExecutionFailure, RuntimeStartupDisposalFailure } from '../runtime-failure';
4
4
  export type { RuntimeDisposalFailureInput, RuntimeDisposalStage, RuntimeExecutionFailureInput, RuntimeFailureCategory, RuntimeFailurePhase, RuntimeRetryDisposition, } from '../runtime-failure';
5
5
  export { PiAdapter } from './pi/pi-adapter';
6
6
  export type { PiAdapterOptions, PiByokLauncherConfig } from './pi/pi-adapter';