@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.
- package/README.md +14 -1
- package/dist/adapters/claude/claude-adapter.d.ts +4 -20
- package/dist/adapters/claude/events.d.ts +3 -0
- package/dist/adapters/claude/process-client.d.ts +15 -1
- package/dist/adapters/codex/codex-adapter.d.ts +4 -16
- package/dist/adapters/codex/process-runner.d.ts +9 -1
- package/dist/adapters/index.d.ts +3 -1
- package/dist/adapters/index.js +1057 -261
- package/dist/adapters/index.js.map +1 -1
- package/dist/adapters/pi/pi-adapter.d.ts +3 -16
- package/dist/adapters/pi/resolve-bin.d.ts +1 -1
- package/dist/adapters/pi/rpc-client.d.ts +15 -1
- package/dist/adapters/process-tree.d.ts +60 -0
- package/dist/adapters/taskkill-pid-set.d.ts +34 -0
- package/dist/bin/audit-log.d.ts +12 -0
- package/dist/bin/byok-agent.js +1452 -507
- package/dist/bin/byok-agent.js.map +1 -1
- package/dist/bin/byok-approval-mcp.js.map +1 -1
- package/dist/bin/commands/workspaces.d.ts +11 -0
- package/dist/bin/format.d.ts +13 -0
- package/dist/bin/runtime-probe.d.ts +1 -1
- package/dist/bin/tasks-view.d.ts +13 -0
- package/dist/daemon/approvals.d.ts +2 -2
- package/dist/daemon/connection-manager.d.ts +15 -17
- package/dist/daemon/control-server.d.ts +18 -1
- package/dist/daemon/create-daemon.d.ts +2 -2
- package/dist/daemon/daemon-owner.d.ts +4 -2
- package/dist/daemon/environment.d.ts +9 -9
- package/dist/daemon/git-workspace.d.ts +21 -0
- package/dist/daemon/long-poll-transport.d.ts +6 -0
- package/dist/daemon/observer.d.ts +13 -0
- package/dist/daemon/presence-publisher.d.ts +29 -0
- package/dist/daemon/runtime-capabilities.d.ts +1 -1
- package/dist/daemon/task-runner.d.ts +34 -40
- package/dist/daemon/ws-transport.d.ts +3 -1
- package/dist/index.d.ts +4 -2
- package/dist/index.js +1413 -455
- package/dist/index.js.map +1 -1
- package/dist/runtime-failure.d.ts +64 -0
- package/dist/types.d.ts +100 -73
- package/package.json +14 -14
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
* M5: per-runtime environment allowlist for spawned agent child processes.
|
|
3
3
|
*
|
|
4
4
|
* Before this module existed, `task-runner.ts` built every task's
|
|
5
|
-
* `
|
|
5
|
+
* `RuntimeOperationStartInput.env` as `process.env` verbatim — the daemon's OWN full
|
|
6
6
|
* environment, unfiltered, handed to whichever runtime CLI (`pi`/`claude`/
|
|
7
7
|
* `codex`) `pickAdapter` selected. Any credential-shaped variable sitting in
|
|
8
8
|
* the daemon's own environment for a completely unrelated reason (an
|
|
@@ -20,10 +20,9 @@
|
|
|
20
20
|
* behave sanely in a non-interactive shell.
|
|
21
21
|
* 2. Whatever ADDITIONAL names the *specific* runtime adapter about to be
|
|
22
22
|
* spawned declares it actually needs
|
|
23
|
-
* (`RuntimeAdapter.environmentRequirements
|
|
24
|
-
*
|
|
25
|
-
*
|
|
26
|
-
* not by an extra check here.
|
|
23
|
+
* (`RuntimeAdapter.descriptor.environmentRequirements` — see
|
|
24
|
+
* `../types.ts`). A descriptor that declares no names gets the platform
|
|
25
|
+
* baseline only; descriptors are required and frozen before claim.
|
|
27
26
|
* 3. A per-device, per-runtime operator override (`DaemonConfig
|
|
28
27
|
* .runtimeEnvironment` — see `create-daemon.ts`) — a local escape hatch
|
|
29
28
|
* for a product/operator that knows it needs one more variable forwarded
|
|
@@ -39,8 +38,8 @@
|
|
|
39
38
|
*/
|
|
40
39
|
/**
|
|
41
40
|
* What one runtime adapter declares it needs beyond the always-included
|
|
42
|
-
* platform baseline.
|
|
43
|
-
* `RuntimeAdapter.environmentRequirements
|
|
41
|
+
* platform baseline. Declared in the required frozen
|
|
42
|
+
* `RuntimeAdapter.descriptor.environmentRequirements` (`../types.ts`).
|
|
44
43
|
*/
|
|
45
44
|
export interface RuntimeEnvironmentRequirements {
|
|
46
45
|
/**
|
|
@@ -69,8 +68,9 @@ export interface BuildRuntimeEnvOptions {
|
|
|
69
68
|
ambient: NodeJS.ProcessEnv;
|
|
70
69
|
/**
|
|
71
70
|
* The selected runtime adapter's own declared requirements —
|
|
72
|
-
* `undefined`
|
|
73
|
-
*
|
|
71
|
+
* `undefined` means "platform baseline only" for this helper. The public
|
|
72
|
+
* RuntimeAdapter descriptor always supplies this object before TaskRunner
|
|
73
|
+
* invokes the helper.
|
|
74
74
|
*/
|
|
75
75
|
requirements?: RuntimeEnvironmentRequirements;
|
|
76
76
|
/**
|
|
@@ -2,6 +2,27 @@ export interface GitWorkspaceConfig {
|
|
|
2
2
|
mode: 'local-checkpoints';
|
|
3
3
|
}
|
|
4
4
|
export type GitErrorCategory = 'git-unavailable' | 'git-timeout' | 'git-output-limit' | 'git-command-failed' | 'workspace-root-invalid' | 'workspace-root-conflict' | 'workspace-not-owned' | 'repository-root-mismatch' | 'repository-invalid' | 'lease-busy' | 'ledger-invalid';
|
|
5
|
+
/**
|
|
6
|
+
* Runtime projection of {@link GitErrorCategory}: every union member, once,
|
|
7
|
+
* in union order — the single source of truth the CLI's stable-output
|
|
8
|
+
* validators (`bin/format.ts`, `bin/audit-log.ts`, `bin/tasks-view.ts`,
|
|
9
|
+
* `bin/commands/workspaces.ts`) project from when deciding which category
|
|
10
|
+
* strings from ledger records are stable enough to render, so those filters
|
|
11
|
+
* can never drift from the union. The `satisfies` half rejects a string
|
|
12
|
+
* that isn't a union member; the `AssertExhaustive` proof below rejects a
|
|
13
|
+
* union member missing from this list — extending either side alone is a
|
|
14
|
+
* compile error. The runtime half (no duplicates, every consumer projects
|
|
15
|
+
* exactly this list) is `__tests__/git-category-drift.test.ts`.
|
|
16
|
+
*/
|
|
17
|
+
export declare const GIT_ERROR_CATEGORIES: readonly ["git-unavailable", "git-timeout", "git-output-limit", "git-command-failed", "workspace-root-invalid", "workspace-root-conflict", "workspace-not-owned", "repository-root-mismatch", "repository-invalid", "lease-busy", "ledger-invalid"];
|
|
18
|
+
/**
|
|
19
|
+
* Runtime projection of `GitWorkspacePhase` (the type itself lives in
|
|
20
|
+
* `git-workspace-store.ts`; the projection lives here beside
|
|
21
|
+
* {@link GIT_ERROR_CATEGORIES} so both category/phase single sources ship
|
|
22
|
+
* from one module) — same exhaustiveness contract, consumed by
|
|
23
|
+
* `bin/tasks-view.ts`'s phase filter.
|
|
24
|
+
*/
|
|
25
|
+
export declare const GIT_WORKSPACE_PHASES: readonly ["preparing", "active", "completed", "failed", "cancelled", "interrupted", "salvage"];
|
|
5
26
|
export declare class GitWorkspaceError extends Error {
|
|
6
27
|
readonly category: GitErrorCategory;
|
|
7
28
|
constructor(category: GitErrorCategory, message?: string);
|
|
@@ -5,6 +5,12 @@ export interface LongPollClientOptions {
|
|
|
5
5
|
auth: AuthManager;
|
|
6
6
|
getCursor: () => number | undefined;
|
|
7
7
|
onEnvelope: (envelope: Envelope) => void;
|
|
8
|
+
/**
|
|
9
|
+
* Capabilities advertised by the server that produced the current poll
|
|
10
|
+
* response. Called before any envelopes from that response are delivered.
|
|
11
|
+
* An older responder omitting the additive field is reported as `[]`.
|
|
12
|
+
*/
|
|
13
|
+
onServerCapabilities?: (capabilities: string[]) => void;
|
|
8
14
|
/** Called once the device is found to be revoked (401 surfaced through {@link AuthManager}) — the loop stops itself rather than retrying. */
|
|
9
15
|
onRevoked?: () => void;
|
|
10
16
|
/**
|
|
@@ -188,6 +188,13 @@ export type DaemonEvent = {
|
|
|
188
188
|
conflicted: number;
|
|
189
189
|
};
|
|
190
190
|
errorCategory?: string;
|
|
191
|
+
} | {
|
|
192
|
+
kind: 'runtime-disposal-failed';
|
|
193
|
+
ts: string;
|
|
194
|
+
taskId: string;
|
|
195
|
+
runtimeId: string;
|
|
196
|
+
stage: 'signal' | 'quiescence' | 'cleanup';
|
|
197
|
+
reason: string;
|
|
191
198
|
}
|
|
192
199
|
/**
|
|
193
200
|
* Plan `device-assertion-broker`: one `assertion.issue` control call
|
|
@@ -350,6 +357,12 @@ export declare class DaemonObserver {
|
|
|
350
357
|
};
|
|
351
358
|
errorCategory?: string;
|
|
352
359
|
}): void;
|
|
360
|
+
noteRuntimeDisposalFailure(event: {
|
|
361
|
+
taskId: string;
|
|
362
|
+
runtimeId: string;
|
|
363
|
+
stage: 'signal' | 'quiescence' | 'cleanup';
|
|
364
|
+
reason: string;
|
|
365
|
+
}): void;
|
|
353
366
|
/**
|
|
354
367
|
* Finding F4: wired from `TaskRunnerDeps.onApprovalDispatched`, called
|
|
355
368
|
* synchronously by `TaskRunner.dispatchApproval` BEFORE its own
|
|
@@ -1,3 +1,30 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Presence producer (§12.3): a periodic `{ level: 'online' }` heartbeat to
|
|
3
|
+
* `PUT /byok/presence`, started only when the deployment's capability
|
|
4
|
+
* declaration contains `presence.hints` (ADR-010 — see `capabilities-client.ts`).
|
|
5
|
+
*
|
|
6
|
+
* Three properties this module deliberately holds:
|
|
7
|
+
*
|
|
8
|
+
* - **Only `online`.** The five levels exist in core, but nothing downstream
|
|
9
|
+
* consumes a `thinking`/`working`/`error` mapping yet, so none is invented
|
|
10
|
+
* here. That also keeps the rule below trivially true.
|
|
11
|
+
* - **It never reads or writes task state.** Presence is a lossy, unsigned,
|
|
12
|
+
* TTL-bounded hint that must never become coordination or execution state
|
|
13
|
+
* (`@byok-sdk/core`'s `presence.ts` module doc). This publisher's only input
|
|
14
|
+
* is a clock.
|
|
15
|
+
* - **Stopping IS the offline signal.** No explicit `offline` publish on
|
|
16
|
+
* shutdown: the hosted hint carries a TTL and expiry means *absence*, so a
|
|
17
|
+
* daemon that stops beating disappears on its own. Publishing `offline` too
|
|
18
|
+
* would express the same fact through a second channel that a crashed daemon
|
|
19
|
+
* could never use anyway.
|
|
20
|
+
*
|
|
21
|
+
* Auth reuses the daemon's one device-token lifecycle: {@link authedFetch}
|
|
22
|
+
* attaches the current bearer and, on a 401, renews once through `AuthManager`
|
|
23
|
+
* and retries exactly once. A revoked device (`DeviceRevokedError`) stops this
|
|
24
|
+
* publisher permanently — there is no recourse but a fresh `pair()`, so
|
|
25
|
+
* retrying would be a pure spin.
|
|
26
|
+
*/
|
|
27
|
+
import { type ToolsetId } from '@byok-sdk/protocol';
|
|
1
28
|
import type { AuthManager } from './auth-manager';
|
|
2
29
|
/**
|
|
3
30
|
* Client-side defaults, chosen against the hosted defaults
|
|
@@ -30,6 +57,8 @@ export declare function assertPresenceHeartbeatCadence(cadence: {
|
|
|
30
57
|
export interface PresencePublisherOptions {
|
|
31
58
|
serverUrl: string;
|
|
32
59
|
auth: AuthManager;
|
|
60
|
+
/** Sorted logical IDs only. Executable MCP definitions and credentials remain device-local. */
|
|
61
|
+
configuredToolsets?: readonly ToolsetId[];
|
|
33
62
|
/** Heartbeat cadence. Must sit strictly between {@link PresencePublisherOptions.minimumIntervalMs} and {@link PresencePublisherOptions.ttlMs}. */
|
|
34
63
|
intervalMs?: number;
|
|
35
64
|
/** The deployment's presence hint TTL, as this daemon understands it. Only used to validate the cadence. */
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import type { RuntimeCapabilities as ProtocolRuntimeCapabilities } from '@byok-sdk/protocol';
|
|
2
2
|
import type { RuntimeCapabilities } from '../types';
|
|
3
3
|
/**
|
|
4
|
-
* Maps a `
|
|
4
|
+
* Maps a frozen `RuntimeAdapterDescriptor`'s internal `capabilities` value
|
|
5
5
|
* (`../types.ts`'s `RuntimeCapabilities` — `{steer, resume,
|
|
6
6
|
* approvalInteractive, permissionModes}`, always-required fields) onto the
|
|
7
7
|
* wire's `RuntimeCapabilities` shape (`@byok-sdk/protocol` — the same field names,
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { type Envelope, type PermissionPolicy, type RuntimeId, type TaskOfferPayload, type TaskOfferWithToolsetsPayload } from '@byok-sdk/protocol';
|
|
2
2
|
import { type McpToolsetConfig, type RuntimeAdapter } from '../types';
|
|
3
|
+
import { type RuntimeDisposalStage } from '../runtime-failure';
|
|
3
4
|
import { type ApprovalDecision, type ApprovalOrigin, type ApprovalRegistry } from './approvals';
|
|
4
5
|
import type { BlobResolver } from './blob-client';
|
|
5
6
|
import type { TaskQueueWatermark } from './control-protocol';
|
|
@@ -205,13 +206,20 @@ export interface TaskRunnerDeps {
|
|
|
205
206
|
observation?: GitWorkspaceObservation;
|
|
206
207
|
errorCategory?: string;
|
|
207
208
|
}) => void;
|
|
209
|
+
/** Local-only evidence that a semantic terminal outcome could not yet release its runtime ownership. */
|
|
210
|
+
onRuntimeDisposalFailure?: (event: {
|
|
211
|
+
taskId: string;
|
|
212
|
+
runtimeId: string;
|
|
213
|
+
stage: RuntimeDisposalStage;
|
|
214
|
+
reason: string;
|
|
215
|
+
}) => void;
|
|
208
216
|
/**
|
|
209
217
|
* M4 Phase 3: this daemon's control-socket identity + the shared registry
|
|
210
218
|
* backing the control socket's own `approvals.list`/`approvals.resolve`
|
|
211
219
|
* methods (`create-daemon.ts` constructs ONE `ApprovalRegistry` and passes
|
|
212
220
|
* the SAME instance here) — see `requestApproval`'s own doc comment for
|
|
213
221
|
* why `TaskRunner` needs a handle on all three. `storeDir`/`productId` are
|
|
214
|
-
* copied verbatim into every
|
|
222
|
+
* copied verbatim into every prepared operation's approval channel.
|
|
215
223
|
*/
|
|
216
224
|
approvalRegistry: ApprovalRegistry;
|
|
217
225
|
storeDir: string;
|
|
@@ -244,7 +252,7 @@ export interface TaskRunnerDeps {
|
|
|
244
252
|
* to supply one — mirrors `onStaleApprovalDecision`'s own contract.
|
|
245
253
|
*/
|
|
246
254
|
onApprovalDispatched?: (taskId: string, approvalId: string) => void;
|
|
247
|
-
/**
|
|
255
|
+
/** Overrides the bounded soft-interrupt window before authoritative `Session.close()` disposal begins. */
|
|
248
256
|
shutdownInterruptTimeoutMs?: number;
|
|
249
257
|
/**
|
|
250
258
|
* M5 batch-3 (workstream 2): overrides {@link DEFAULT_MAX_TASK_OUTPUT_BYTES}
|
|
@@ -256,9 +264,10 @@ export interface TaskRunnerDeps {
|
|
|
256
264
|
*/
|
|
257
265
|
maxTaskOutputBytes?: number;
|
|
258
266
|
/**
|
|
259
|
-
* M4 (additive-minor, `task.approval_resolved`): the
|
|
260
|
-
* `conn.ack
|
|
261
|
-
*
|
|
267
|
+
* M4 (additive-minor, `task.approval_resolved`): the capabilities advertised
|
|
268
|
+
* by the CURRENT transport's server (`conn.ack` on WS, the latest successful
|
|
269
|
+
* events response on long-poll) — read fresh at call time (mirrors
|
|
270
|
+
* `getCursor`/`getToken`'s own
|
|
262
271
|
* "read fresh, not captured once" convention elsewhere in this codebase),
|
|
263
272
|
* since the capability is learned asynchronously, after this `TaskRunner`
|
|
264
273
|
* is already constructed (`create-daemon.ts`'s `start()` builds `deps`
|
|
@@ -319,8 +328,8 @@ export type AdmissionGuardDecision = {
|
|
|
319
328
|
};
|
|
320
329
|
type AcceptedOfferPayload = TaskOfferPayload | TaskOfferWithToolsetsPayload;
|
|
321
330
|
/**
|
|
322
|
-
* Per-connection task orchestration: offer -> (decline |
|
|
323
|
-
*
|
|
331
|
+
* Per-connection task orchestration: offer -> (decline | prepare -> seal ->
|
|
332
|
+
* claim -> prepared operation -> started) -> seq-ordered progress batches -> complete/fail/
|
|
324
333
|
* cancelled, plus approve/reject/cancel/steer handling.
|
|
325
334
|
*
|
|
326
335
|
* M1 rework (docs/protocol.md §3, §5, §10 — `packages/protocol` is frozen,
|
|
@@ -340,13 +349,13 @@ export declare class TaskRunner {
|
|
|
340
349
|
* Finding F4 (cancel lost during the offer-processing window): a
|
|
341
350
|
* `task.cancel` for a taskId that hasn't finished `handleOffer` yet (still
|
|
342
351
|
* awaiting adapter detection / instruction resolution / workspace setup /
|
|
343
|
-
* `
|
|
352
|
+
* prepared operation `start()`) has no `this.tasks` entry to land on — it used to be
|
|
344
353
|
* silently dropped, and the runtime session `handleOffer` was about to
|
|
345
354
|
* register would then run an unsupervised ("zombie") turn nobody asked
|
|
346
355
|
* for anymore. Recording the taskId here lets `handleOffer` consult it at
|
|
347
356
|
* the two points where it can still safely react (see its body): before
|
|
348
357
|
* claiming at all (decline instead of ever starting a session), and right
|
|
349
|
-
* after
|
|
358
|
+
* after the prepared operation resolves but before this task is registered as
|
|
350
359
|
* active (tear the just-started session down immediately, before its
|
|
351
360
|
* event loop ever pumps a single event). Consumed (deleted) at whichever
|
|
352
361
|
* checkpoint handles it; a cancel for a taskId that's already active,
|
|
@@ -372,12 +381,12 @@ export declare class TaskRunner {
|
|
|
372
381
|
* checkpoint-2 cancel-teardown, or successful registration into
|
|
373
382
|
* `this.tasks`). Bounded eviction on `pendingCancelled` (below) must never
|
|
374
383
|
* remove an entry for a taskId in this set: doing so is exactly the bug —
|
|
375
|
-
* block task A in `
|
|
384
|
+
* block task A in prepared-operation `start()`, deliver A's own `task.cancel` (so
|
|
376
385
|
* `pendingCancelled` gets an entry for A while A is still in-flight),
|
|
377
386
|
* then deliver `MAX_TRACKED_TASK_IDS` more cancels for unrelated taskIds
|
|
378
387
|
* nobody ever offered — under naive oldest-wins eviction, A's entry (the
|
|
379
388
|
* single oldest) gets evicted purely because of unrelated churn, so when
|
|
380
|
-
*
|
|
389
|
+
* the prepared operation finally resolves, checkpoint 2 finds no cancel marker
|
|
381
390
|
* and the already-cancelled task starts a real session. See
|
|
382
391
|
* `evictPendingCancelled` below for the fix, and
|
|
383
392
|
* `task-runner-bounded-collections.test.ts` for a test mirroring this
|
|
@@ -397,7 +406,7 @@ export declare class TaskRunner {
|
|
|
397
406
|
* explicitly relies on redelivered handlers being idempotent for exactly
|
|
398
407
|
* this reason). `handleOffer` must treat a redelivered offer for a taskId
|
|
399
408
|
* that's already active (`this.tasks`) or already finished (this set) as
|
|
400
|
-
* a no-op — never a second `
|
|
409
|
+
* a no-op — never a second prepared-operation `start()` call, which would orphan the
|
|
401
410
|
* first session.
|
|
402
411
|
*
|
|
403
412
|
* M3-B: unbounded otherwise — a long-lived daemon that's finished many
|
|
@@ -455,10 +464,9 @@ export declare class TaskRunner {
|
|
|
455
464
|
/** M4 Phase 2: stop claiming any FUTURE `task.offer` — see `stoppingOffers`'s own doc comment. Idempotent. */
|
|
456
465
|
stopAcceptingOffers(): void;
|
|
457
466
|
/**
|
|
458
|
-
*
|
|
459
|
-
*
|
|
460
|
-
*
|
|
461
|
-
* terminal message is sent either way) but reports `task.fail` rather than
|
|
467
|
+
* Shutdown of every currently ACTIVE task for the control socket's
|
|
468
|
+
* `shutdown` RPC. Soft interrupt remains bounded, but each task's
|
|
469
|
+
* authoritative close receipt must settle successfully. Reports `task.fail` rather than
|
|
462
470
|
* `task.cancelled` — these tasks aren't ending because the SERVER
|
|
463
471
|
* cancelled them, they're ending because this device is shutting down.
|
|
464
472
|
* `retryable: true` throughout: nothing about the task/policy itself was
|
|
@@ -509,28 +517,13 @@ export declare class TaskRunner {
|
|
|
509
517
|
* unconditionally, so a hung `interrupt()` (a misbehaving adapter) can
|
|
510
518
|
* never block `task.fail` from being sent at all.
|
|
511
519
|
*
|
|
512
|
-
*
|
|
513
|
-
*
|
|
514
|
-
*
|
|
515
|
-
*
|
|
516
|
-
* far more here than it used to for the pre-existing graceful-shutdown-only
|
|
517
|
-
* caller, since THAT path is additionally bounded by an outer deadline
|
|
518
|
-
* (`SHUTDOWN_TASK_TEARDOWN_DEADLINE_MS`/`DaemonConfig.shutdownGraceMs`,
|
|
519
|
-
* `create-daemon.ts`), while resource-limit enforcement fires during
|
|
520
|
-
* ordinary operation with no such outer bound watching it). `close()` is
|
|
521
|
-
* every adapter's harder teardown primitive — an actual process-level kill
|
|
522
|
-
* (SIGTERM, or `taskkill /F` on Windows — see e.g.
|
|
523
|
-
* `ClaudeProcessClient.kill()`/`PiRpcClient.kill()`) as opposed to pi's own
|
|
524
|
-
* soft in-band `interrupt()` (an RPC `abort` message that leaves the
|
|
525
|
-
* process alive and resumable) — so escalating to it is the closest thing
|
|
526
|
-
* to a "hard kill" the `Session` interface exposes. `finish()` below calls
|
|
527
|
-
* `session.close()` again regardless (documented idempotent) — this isn't
|
|
528
|
-
* a substitute for that, only an earlier, bounded attempt at actually
|
|
529
|
-
* stopping a stuck runtime before this method gives up and reports failure
|
|
530
|
-
* anyway.
|
|
520
|
+
* After the bounded soft interrupt, `finish()` always awaits the authoritative
|
|
521
|
+
* `Session.close()` receipt. A failed receipt retains active/Git ownership;
|
|
522
|
+
* shutdown surfaces the rejection while resource enforcement leaves local
|
|
523
|
+
* evidence for a later retry.
|
|
531
524
|
*
|
|
532
525
|
* Re-checks task identity (`this.tasks.get(...) === active`) immediately
|
|
533
|
-
* before sending `task.fail`: the interrupt
|
|
526
|
+
* before sending `task.fail`: the interrupt race above has await
|
|
534
527
|
* points during which a DIFFERENT path (a racing `task.cancel`/
|
|
535
528
|
* `task.reject`, or the session completing normally on its own) may have
|
|
536
529
|
* already finished this exact task and sent its own terminal message.
|
|
@@ -623,7 +616,7 @@ export declare class TaskRunner {
|
|
|
623
616
|
*
|
|
624
617
|
* `inFlightOffers` is naturally tiny (bounded by this device's real
|
|
625
618
|
* concurrent-offer-processing count — normally single digits, driven by
|
|
626
|
-
* how many `task.offer`s are simultaneously mid
|
|
619
|
+
* how many `task.offer`s are simultaneously mid-prepared-operation start() — nowhere
|
|
627
620
|
* near `MAX_TRACKED_TASK_IDS`), so this scan is cheap in practice: it
|
|
628
621
|
* finds a safe entry at or near the front almost always. The only case
|
|
629
622
|
* where NO entry is safe to evict is every single tracked cancel
|
|
@@ -943,15 +936,16 @@ export declare class TaskRunner {
|
|
|
943
936
|
/**
|
|
944
937
|
* Whether the CURRENTLY connected server advertised `result-document` —
|
|
945
938
|
* read fresh on every call, never captured, because the answer changes
|
|
946
|
-
* across a reconnect (`ConnectionManager
|
|
947
|
-
*
|
|
948
|
-
*
|
|
939
|
+
* across a reconnect or transport switch (`ConnectionManager` clears the
|
|
940
|
+
* old advertisement at the boundary, then repopulates it from a fresh WS
|
|
941
|
+
* ack or successful poll response). An absent `getServerCapabilities` seam is
|
|
949
942
|
* "no capabilities", the fail-closed reading.
|
|
950
943
|
*/
|
|
951
944
|
private hasResultDocumentCapability;
|
|
952
945
|
private observeGit;
|
|
953
946
|
private updateGitPhaseBestEffort;
|
|
954
947
|
private finish;
|
|
948
|
+
private reserveSemanticTerminal;
|
|
955
949
|
/** M3-B: bounded insert for `finishedTaskIds` — see its class-level doc comment and `MAX_TRACKED_TASK_IDS`. Evicts the oldest (first-inserted) entry once over cap, same idiom as `ConnectionHub.checkAndRecordDuplicate` (packages/server/src/hub.ts). */
|
|
956
950
|
private addFinishedTaskId;
|
|
957
951
|
/** `reuseDir`, when set (a known sessionRef's recorded workspace), is used verbatim instead of a fresh `workspaceRoot/<taskId>` directory — `mkdir recursive` is idempotent either way, so ensuring-exists is safe to do unconditionally. */
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { type CapabilityFlag, type Envelope, type RuntimeInfo } from '@byok-sdk/protocol';
|
|
1
|
+
import { type CapabilityFlag, type Envelope, type RuntimeInfo, type ToolsetId } from '@byok-sdk/protocol';
|
|
2
2
|
export type ConnectionState = 'connecting' | 'open' | 'closed' | 'degraded' | 'revoked';
|
|
3
3
|
/** The WS upgrade itself was rejected with a non-101 HTTP status (e.g. 401 for an expired/invalid bearer token). Surfaced via `onConnectOutcome` so `ConnectionManager` can force a reactive token renewal before the next attempt (protocol §6.2, "reactively on 401"). */
|
|
4
4
|
export declare class WsUnexpectedStatusError extends Error {
|
|
@@ -25,6 +25,8 @@ export interface WsTransportOptions {
|
|
|
25
25
|
capabilities: CapabilityFlag[];
|
|
26
26
|
/** Detected runtimes, sent on every `conn.hello` (protocol §10 gap #4/#11). */
|
|
27
27
|
runtimes?: RuntimeInfo[];
|
|
28
|
+
/** Sorted logical IDs configured locally; no MCP executable definition crosses the wire. */
|
|
29
|
+
configuredToolsets?: readonly ToolsetId[];
|
|
28
30
|
/** The redelivery cursor to send as `conn.hello.cursor` (protocol §9) — read fresh on every connect so a value learned mid-connection is used on the next reconnect. */
|
|
29
31
|
getCursor?: () => number | undefined;
|
|
30
32
|
onEnvelope: (envelope: Envelope) => void;
|
package/dist/index.d.ts
CHANGED
|
@@ -1,6 +1,8 @@
|
|
|
1
|
-
export type { RuntimeAdapter, RuntimeCapabilities, RuntimeDetectResult, Session,
|
|
2
|
-
export { PolicyUnsupportedError, SteerUnsupportedError } from './types';
|
|
1
|
+
export type { RuntimeAdapter, RuntimeAdapterDescriptor, RuntimeAdapterPrepareInput, RuntimeAdapterPrepareResult, RuntimeAdapterRejectedOperation, RuntimeAdapterPreparedOperation, PreparedRuntimeOperation, RuntimeOperationManifest, RuntimeOperationStartInput, RuntimeCapabilities, RuntimeDetectResult, Session, GitWorkspaceConfig, McpStdioServerConfig, McpToolsetConfig, } from './types';
|
|
2
|
+
export { PolicyUnsupportedError, SteerUnsupportedError, freezeRuntimeAdapterDescriptor, sealRuntimeOperationManifest } from './types';
|
|
3
3
|
export type { RuntimeEnvironmentRequirements } from './daemon/environment';
|
|
4
|
+
export { RuntimeExecutionFailure, RuntimeDisposalFailure, RUNTIME_ADAPTER_CONTRACT_VIOLATION_REASON, isRuntimeDisposalFailure, isRuntimeExecutionFailure, projectRuntimeBoundaryFailure, projectRuntimeExecutionFailure, } from './runtime-failure';
|
|
5
|
+
export type { RuntimeExecutionFailureInput, RuntimeDisposalFailureInput, RuntimeDisposalStage, RuntimeFailureCategory, RuntimeFailurePhase, RuntimeFailureProjection, RuntimeRetryDisposition, } from './runtime-failure';
|
|
4
6
|
export { GitWorkspaceManager, GitWorkspaceError, isGitWorkspaceConfig, prependGitWorkspaceGuidance } from './daemon/git-workspace';
|
|
5
7
|
export type { GitWorkspaceObservation, GitWorkspaceLease, GitWorkspaceOptions, GitErrorCategory } from './daemon/git-workspace';
|
|
6
8
|
export { GitWorkspaceStore } from './daemon/git-workspace-store';
|