@byok-sdk/client 0.3.0 → 0.4.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 (41) hide show
  1. package/README.md +14 -1
  2. package/dist/adapters/claude/claude-adapter.d.ts +4 -20
  3. package/dist/adapters/claude/events.d.ts +3 -0
  4. package/dist/adapters/claude/process-client.d.ts +15 -1
  5. package/dist/adapters/codex/codex-adapter.d.ts +4 -16
  6. package/dist/adapters/codex/process-runner.d.ts +9 -1
  7. package/dist/adapters/index.d.ts +3 -1
  8. package/dist/adapters/index.js +1057 -261
  9. package/dist/adapters/index.js.map +1 -1
  10. package/dist/adapters/pi/pi-adapter.d.ts +3 -16
  11. package/dist/adapters/pi/resolve-bin.d.ts +1 -1
  12. package/dist/adapters/pi/rpc-client.d.ts +15 -1
  13. package/dist/adapters/process-tree.d.ts +60 -0
  14. package/dist/adapters/taskkill-pid-set.d.ts +34 -0
  15. package/dist/bin/audit-log.d.ts +12 -0
  16. package/dist/bin/byok-agent.js +1452 -507
  17. package/dist/bin/byok-agent.js.map +1 -1
  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/connection-manager.d.ts +15 -17
  25. package/dist/daemon/control-server.d.ts +18 -1
  26. package/dist/daemon/create-daemon.d.ts +2 -2
  27. package/dist/daemon/daemon-owner.d.ts +4 -2
  28. package/dist/daemon/environment.d.ts +9 -9
  29. package/dist/daemon/git-workspace.d.ts +21 -0
  30. package/dist/daemon/long-poll-transport.d.ts +6 -0
  31. package/dist/daemon/observer.d.ts +13 -0
  32. package/dist/daemon/presence-publisher.d.ts +29 -0
  33. package/dist/daemon/runtime-capabilities.d.ts +1 -1
  34. package/dist/daemon/task-runner.d.ts +34 -40
  35. package/dist/daemon/ws-transport.d.ts +3 -1
  36. package/dist/index.d.ts +4 -2
  37. package/dist/index.js +1413 -455
  38. package/dist/index.js.map +1 -1
  39. package/dist/runtime-failure.d.ts +64 -0
  40. package/dist/types.d.ts +100 -73
  41. package/package.json +14 -14
@@ -1,5 +1,4 @@
1
- import type { TaskOfferPayload } from '@byok-sdk/protocol';
2
- import { type RuntimeAdapter, type RuntimeCapabilities, type RuntimeDetectResult, type RuntimeEnvironmentRequirements, type Session, type TaskContext } from '../../types';
1
+ import { type RuntimeAdapter, type RuntimeDetectResult, type RuntimeAdapterPrepareInput, type RuntimeAdapterPrepareResult } from '../../types';
3
2
  import { type ResolvedBin } from './resolve-bin';
4
3
  import { type SpawnFn } from './rpc-client';
5
4
  /**
@@ -31,21 +30,9 @@ export interface PiByokLauncherConfig {
31
30
  }
32
31
  export declare class PiAdapter implements RuntimeAdapter {
33
32
  private readonly options;
34
- readonly id = "pi";
35
- readonly supportsDispatchSelection = true;
33
+ readonly descriptor: import("..").RuntimeAdapterDescriptor;
36
34
  constructor(options?: PiAdapterOptions);
37
35
  detect(): Promise<RuntimeDetectResult>;
38
- capabilities(): RuntimeCapabilities;
39
- /**
40
- * M5: pi authenticates to its ~30 supported providers via env-var API
41
- * keys — `detect()`'s own `authPresent` probe above checks this identical
42
- * list — so these MUST keep flowing into pi's spawned process or pi auth
43
- * breaks entirely. `KNOWN_PROVIDER_ENV_VARS` above is the single source
44
- * of truth, reused here rather than duplicated. No `baseNames`: nothing
45
- * in this adapter or `rpc-client.ts` reads a pi-specific config-discovery
46
- * variable beyond the platform baseline (`daemon/environment.ts`).
47
- */
48
- environmentRequirements(): RuntimeEnvironmentRequirements;
49
- start(task: TaskOfferPayload, ctx: TaskContext): Promise<Session>;
36
+ prepare(input: RuntimeAdapterPrepareInput): Promise<RuntimeAdapterPrepareResult>;
50
37
  private resolveBin;
51
38
  }
@@ -25,7 +25,7 @@ export interface ResolvedBin {
25
25
  * only ever constructs `new PiAdapter()` with no options (see `createDaemon`),
26
26
  * so an out-of-process substitution (e.g. examples/basic's e2e run swapping
27
27
  * in the fake-pi fixture, or a single-file product injecting its required
28
- * Node 22.19+ pi sidecar) has no other seam to use.
28
+ * Node 22.22+ pi sidecar) has no other seam to use.
29
29
  *
30
30
  * Deliberately does NOT use `createRequire(...).resolve()`: this package is
31
31
  * pure ESM with no `require` export condition (`exports["."]` only offers
@@ -39,6 +39,9 @@ export declare class PiRpcClient {
39
39
  private readonly eventQueue;
40
40
  private closed;
41
41
  private exitError;
42
+ private readonly closedPromise;
43
+ private resolveClosed;
44
+ private disposalAttempt;
42
45
  /** Bounded tail of recent stderr lines — pi discarded this entirely before (nothing ever read `child.stderr`), which is exactly why finding #1 (`Error: Unknown option: --session-id`, exit 1) had to be root-caused by hand instead of reading it off a thrown error. See `buildExitError`. */
43
46
  private readonly stderrRing;
44
47
  /** Count of pi RPC message types `PiSession` (pi-adapter.ts) has told us have no `AgentEvent` mapping and aren't routine bookkeeping — see `recordUnmappedFrame`. */
@@ -51,6 +54,8 @@ export declare class PiRpcClient {
51
54
  }): Promise<PiRpcMessage>;
52
55
  /** Every non-response, non-`extension_ui_request` line — the latter is answered directly by this client (see `respondToExtensionUiRequest`) and never enqueued. */
53
56
  get events(): AsyncIterable<PiRpcMessage>;
57
+ /** Local transport diagnostic retained when the process closes; consumers must classify it explicitly. */
58
+ get terminalError(): Error | undefined;
54
59
  /**
55
60
  * Record a pi RPC message `type` that `PiSession` (pi-adapter.ts) decided
56
61
  * has no `AgentEvent` mapping and isn't routine bookkeeping (see
@@ -61,8 +66,17 @@ export declare class PiRpcClient {
61
66
  * a post-mortem on a failed/hung task has it without separate log scraping.
62
67
  */
63
68
  recordUnmappedFrame(type: string): void;
64
- /** Best-effort teardown. SIGTERM on POSIX; `taskkill /T /F` on Windows to also reap child processes pi itself spawned (e.g. bash). */
69
+ /**
70
+ * Immediate process-tree termination request. `dispose()` is the settlement
71
+ * receipt, so this stays fire-and-forget: an interrupt must not block on a
72
+ * terminator. A request that could not be spawned is left unrecorded, so
73
+ * `dispose()` re-issues it and raises the typed `stage:'signal'` failure —
74
+ * swallowing it here loses nothing.
75
+ */
65
76
  kill(): void;
77
+ waitClosed(): Promise<void>;
78
+ dispose(): Promise<void>;
79
+ private processTreeOptions;
66
80
  private onData;
67
81
  private onLine;
68
82
  /**
@@ -0,0 +1,60 @@
1
+ import { spawn, type ChildProcess, type SpawnOptions } from 'node:child_process';
2
+ type KillFn = (pid: number, signal: NodeJS.Signals | number) => void;
3
+ export interface OwnedProcessTreeOptions {
4
+ child: ChildProcess;
5
+ waitClosed: () => Promise<void>;
6
+ isClosed: () => boolean;
7
+ label: string;
8
+ termGraceMs?: number;
9
+ killGraceMs?: number;
10
+ /** DI seam — defaults to `process.platform`. Lets the win32 branch be exercised from POSIX CI, mirroring `util/secure-dir.ts`'s identical convention. */
11
+ platform?: NodeJS.Platform;
12
+ /** DI seam for the win32 `taskkill` sweep — defaults to `node:child_process`'s `spawn`. */
13
+ spawnFn?: typeof spawn;
14
+ /** DI seam for liveness probing — defaults to `process.kill`. */
15
+ killFn?: KillFn;
16
+ }
17
+ /**
18
+ * Every bundled runtime root is an owned process-group leader on POSIX. Pipes
19
+ * remain referenced, so `detached` changes ownership topology without making
20
+ * the runtime outlive the daemon. Windows uses taskkill's `/T` tree authority.
21
+ */
22
+ export declare function withOwnedProcessTree<T extends SpawnOptions>(options: T): T;
23
+ /**
24
+ * Immediate termination request used by interrupt paths; close remains the
25
+ * receipt. On win32 the request also RECORDS the pid set taskkill walked,
26
+ * which is what {@link disposeOwnedProcessTree} later measures — so an
27
+ * interrupt that is fired and forgotten still leaves disposal a measurable
28
+ * tree. A request that could not be spawned records nothing, which makes
29
+ * disposal re-issue it and surface `stage:'signal'` itself.
30
+ */
31
+ export declare function requestOwnedProcessTreeTermination(options: OwnedProcessTreeOptions): Promise<void>;
32
+ /**
33
+ * Resolve only after the adapter-owned root and descendants are quiescent.
34
+ *
35
+ * POSIX measures the owned process GROUP; win32 measures the pid set taskkill
36
+ * reported walking (`stage:'quiescence'` names how many of those were still
37
+ * alive at the deadline). Neither platform reads a terminator's exit status:
38
+ * on win32 `stage:'signal'` now means only that taskkill could not be spawned.
39
+ * `close` stays the final receipt on both — it is the stdio-flush guarantee,
40
+ * not the liveness proof.
41
+ *
42
+ * Grace budget: each phase carries its own full grace on both platforms. On
43
+ * win32 the quiescence poll gets `killGraceMs` and the close wait that follows
44
+ * gets a fresh `killGraceMs`; POSIX likewise gives the SIGTERM wait
45
+ * `termGraceMs`, the SIGKILL wait `killGraceMs`, and the close wait another
46
+ * `killGraceMs`. Worst-case disposal is therefore bounded by the sum, never by
47
+ * one shared deadline that could starve the close wait after a slow drain.
48
+ *
49
+ * Residual boundary, stated honestly. Three cases this mechanism cannot cover:
50
+ * a descendant whose intermediate parent died before any sweep observed it is
51
+ * unreachable, because Windows does not re-parent orphans — nothing in the
52
+ * surviving tree links back to it and `taskkill /T` cannot find it. The same
53
+ * window means a recycled pid could read as alive. And if taskkill's output is
54
+ * empty or unparseable, the walked set collapses to `{root}`: disposal then
55
+ * measures the root alone and reports quiescence on that basis, which is a
56
+ * narrower claim than the tree, not a false one. Preventing orphans left behind
57
+ * by a DAEMON crash is a separate job-object concern, explicitly out of scope.
58
+ */
59
+ export declare function disposeOwnedProcessTree(options: OwnedProcessTreeOptions): Promise<void>;
60
+ export {};
@@ -0,0 +1,34 @@
1
+ /**
2
+ * Windows-only: recovers the process-tree PID set that `taskkill /T /F`
3
+ * reports it walked, so `process-tree.ts` can MEASURE quiescence instead of
4
+ * trusting taskkill's exit status.
5
+ *
6
+ * Two constraints shape this parser:
7
+ *
8
+ * - taskkill's messages are LOCALIZED (the same run prints
9
+ * `SUCCESS: The process with PID ...` on en-US and a translated sentence on
10
+ * de-DE/zh-CN/ja-JP), so no word, prefix, or field label may be matched.
11
+ * Only the integers and their CO-OCCURRENCE on one line are stable: every
12
+ * line taskkill emits for a walked process names that process and its
13
+ * parent together. Seeding with the root pid and closing over co-occurrence
14
+ * therefore reaches exactly the walked tree, in any locale.
15
+ * - the text arrives in the console OEM codepage, not UTF-8. It is decoded as
16
+ * latin1 (byte-preserving) rather than guessed: every OEM codepage taskkill
17
+ * can use encodes ASCII digits as single bytes 0x30-0x39, and no DBCS trail
18
+ * byte (CP932/CP936/CP949/CP950 all start their trail range at 0x40) can
19
+ * land in that range. Undecodable non-ASCII bytes become mojibake, which is
20
+ * irrelevant: they can never manufacture a digit.
21
+ *
22
+ * Line ORDER is deliberately not relied on (taskkill emits children before
23
+ * parents today); the walk iterates to a fixpoint instead.
24
+ */
25
+ /**
26
+ * Returns the PID set reachable from `rootPid` by co-occurrence over `text`.
27
+ *
28
+ * `excludedPids` removes integers that must never enter the set even when
29
+ * they share a line with an accepted pid — taskkill names the ROOT's own
30
+ * parent (this daemon process) on the root's line, and accepting it would
31
+ * make quiescence unreachable by construction. `rootPid` is always seeded and
32
+ * is never subject to exclusion.
33
+ */
34
+ export declare function walkTaskkillPidSet(text: string, rootPid: number, excludedPids?: Iterable<number>): Set<number>;
@@ -118,6 +118,18 @@ export declare const AUDIT_LOG_TRIM_TARGET_LINES = 5000;
118
118
  * tail) rather than the file growing without bound.
119
119
  */
120
120
  export declare const MAX_LIVE_TASK_ANCHORS = 500;
121
+ /**
122
+ * Git failures are serialized only as this closed, stable category set —
123
+ * never raw Git errors or command output. Projected from
124
+ * `daemon/git-workspace.ts`'s `GIT_ERROR_CATEGORIES` (the single source of
125
+ * truth for the `GitErrorCategory` union) rather than carrying a literal
126
+ * copy that could drift from it; the runtime half of that guarantee is
127
+ * `__tests__/git-category-drift.test.ts`.
128
+ *
129
+ * @internal Exported for the drift-guard test only (never re-exported from
130
+ * `index.ts`).
131
+ */
132
+ export declare const STABLE_GIT_ERROR_CATEGORIES: Set<string>;
121
133
  /**
122
134
  * Appends one `DaemonEvent` as a single redacted JSON line (finding P1 #3 —
123
135
  * see this file's module doc comment) at 0600, and rotates the file if it's