@byok-sdk/client 0.4.0 → 0.4.2
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.
- package/README.md +1 -1
- package/dist/adapters/claude/process-client.d.ts +7 -1
- package/dist/adapters/codex/process-runner.d.ts +5 -0
- package/dist/adapters/index.js +258 -60
- package/dist/adapters/index.js.map +1 -1
- package/dist/adapters/pi/resolve-bin.d.ts +1 -1
- package/dist/adapters/pi/rpc-client.d.ts +7 -1
- package/dist/adapters/process-tree.d.ts +45 -4
- package/dist/adapters/taskkill-pid-set.d.ts +34 -0
- package/dist/bin/byok-agent.js +283 -80
- package/dist/bin/byok-agent.js.map +1 -1
- package/dist/daemon/connection-manager.d.ts +11 -15
- package/dist/daemon/long-poll-transport.d.ts +6 -0
- package/dist/daemon/task-runner.d.ts +7 -6
- package/dist/index.js +283 -80
- package/dist/index.js.map +1 -1
- package/package.json +14 -14
|
@@ -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.
|
|
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
|
|
@@ -66,7 +66,13 @@ export declare class PiRpcClient {
|
|
|
66
66
|
* a post-mortem on a failed/hung task has it without separate log scraping.
|
|
67
67
|
*/
|
|
68
68
|
recordUnmappedFrame(type: string): void;
|
|
69
|
-
/**
|
|
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
|
+
*/
|
|
70
76
|
kill(): void;
|
|
71
77
|
waitClosed(): Promise<void>;
|
|
72
78
|
dispose(): Promise<void>;
|
|
@@ -1,4 +1,5 @@
|
|
|
1
|
-
import { type ChildProcess, type SpawnOptions } from 'node:child_process';
|
|
1
|
+
import { spawn, type ChildProcess, type SpawnOptions } from 'node:child_process';
|
|
2
|
+
type KillFn = (pid: number, signal: NodeJS.Signals | number) => void;
|
|
2
3
|
export interface OwnedProcessTreeOptions {
|
|
3
4
|
child: ChildProcess;
|
|
4
5
|
waitClosed: () => Promise<void>;
|
|
@@ -6,6 +7,12 @@ export interface OwnedProcessTreeOptions {
|
|
|
6
7
|
label: string;
|
|
7
8
|
termGraceMs?: number;
|
|
8
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;
|
|
9
16
|
}
|
|
10
17
|
/**
|
|
11
18
|
* Every bundled runtime root is an owned process-group leader on POSIX. Pipes
|
|
@@ -13,7 +20,41 @@ export interface OwnedProcessTreeOptions {
|
|
|
13
20
|
* the runtime outlive the daemon. Windows uses taskkill's `/T` tree authority.
|
|
14
21
|
*/
|
|
15
22
|
export declare function withOwnedProcessTree<T extends SpawnOptions>(options: T): T;
|
|
16
|
-
/**
|
|
17
|
-
|
|
18
|
-
|
|
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
|
+
*/
|
|
19
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>;
|