@byok-sdk/client 0.4.2 → 0.5.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.
- package/README.md +18 -0
- package/dist/bin/byok-agent.js +51 -1
- package/dist/bin/byok-agent.js.map +1 -1
- package/dist/daemon/create-daemon.d.ts +9 -2
- package/dist/daemon/progress-batcher.d.ts +13 -0
- package/dist/daemon/task-runner.d.ts +2 -0
- package/dist/index.d.ts +1 -0
- package/dist/index.js +51 -1
- package/dist/index.js.map +1 -1
- package/package.json +4 -4
|
@@ -11,7 +11,7 @@ import { type LocalTaskJournal } from './journal/journal';
|
|
|
11
11
|
import { type JournalOpenFaultSeam } from './journal/sqlite-support';
|
|
12
12
|
import { LocalStoragePressureEngine, type LocalStoragePolicyInput } from './journal/storage-policy';
|
|
13
13
|
import { type ResultDocumentExtractor } from './task-runner';
|
|
14
|
-
import type
|
|
14
|
+
import { type ProgressBatcherOptions } from './progress-batcher';
|
|
15
15
|
/**
|
|
16
16
|
* Optional white-label product display info — purely opaque passthrough
|
|
17
17
|
* (never interpreted, validated, or rendered by the daemon itself). Carried
|
|
@@ -223,6 +223,14 @@ export interface DaemonConfig {
|
|
|
223
223
|
* explicitly instead to opt out of enforcement altogether.
|
|
224
224
|
*/
|
|
225
225
|
maxTaskOutputBytes?: number;
|
|
226
|
+
/**
|
|
227
|
+
* Host-owned batching policy for normalized `task.progress` events.
|
|
228
|
+
* `maxBatchBytes`, when set, measures exactly the UTF-8 bytes of
|
|
229
|
+
* `JSON.stringify(events)` and must match the deployment's activity-ingress
|
|
230
|
+
* budget. It is deliberately unset by default because that ingress ceiling
|
|
231
|
+
* is deployment policy, not a frozen protocol constant.
|
|
232
|
+
*/
|
|
233
|
+
progressBatch?: ProgressBatcherOptions;
|
|
226
234
|
/**
|
|
227
235
|
* additive-minor (`task.complete.document`): the seam through which this
|
|
228
236
|
* product turns a finished task's final output text into the STRUCTURED
|
|
@@ -415,7 +423,6 @@ export interface Daemon {
|
|
|
415
423
|
/** Internal seam so tests can substitute stub adapters / faster backoff+batch+liveness+long-poll timing. `createDaemonWithAdapters` (which takes this) is also the real entry point for products supplying a hand-built adapter set `createDaemon` can't construct on its own — e.g. custom adapter options, or an adapter that REPLACES a bundled runtime's implementation under the same id. Honest limit: an adapter id outside `pi`/`claude`/`codex` cannot pass wire validation today — `RuntimeIdSchema` (`@byok-sdk/protocol`) is a closed `z.enum(['pi', 'claude', 'codex'])`, and `isRuntimeId` filtering below (see `detectRuntimes`) drops any detected adapter outside that set before it ever reaches a wire-visible field. A genuinely fourth/namespaced runtime id is a future protocol change, not something this seam enables today. */
|
|
416
424
|
export interface DaemonOverrides {
|
|
417
425
|
backoff?: BackoffOptions;
|
|
418
|
-
batch?: ProgressBatcherOptions;
|
|
419
426
|
liveness?: LivenessOptions;
|
|
420
427
|
/** M4 Phase 3: overrides `TaskRunner`'s default out-of-band approval wait (`DEFAULT_APPROVAL_TIMEOUT_MS`, 10 minutes) before an unanswered `requestApproval` force-resolves as a fail-closed rejection. */
|
|
421
428
|
approvalTimeoutMs?: number;
|
|
@@ -5,7 +5,19 @@ export interface ProgressBatcherOptions {
|
|
|
5
5
|
maxBatchSize?: number;
|
|
6
6
|
/** Otherwise flush at most this often (ms) while events are pending. Default 250 (~4/sec). */
|
|
7
7
|
flushIntervalMs?: number;
|
|
8
|
+
/**
|
|
9
|
+
* Optional deployment-owned ceiling for the UTF-8 bytes in the serialized
|
|
10
|
+
* `events[]` array. Unset means no byte ceiling; hosts should inject the
|
|
11
|
+
* same value their activity ingress enforces.
|
|
12
|
+
*/
|
|
13
|
+
maxBatchBytes?: number;
|
|
8
14
|
}
|
|
15
|
+
export declare class ProgressEventTooLargeError extends Error {
|
|
16
|
+
readonly actualBytes: number;
|
|
17
|
+
readonly maxBatchBytes: number;
|
|
18
|
+
constructor(actualBytes: number, maxBatchBytes: number);
|
|
19
|
+
}
|
|
20
|
+
export declare function validateProgressBatcherOptions(options?: ProgressBatcherOptions): void;
|
|
9
21
|
/**
|
|
10
22
|
* Coalesces a task's `AgentEvent`s into seq-ordered `task.progress` batches:
|
|
11
23
|
* flush immediately at `maxBatchSize` events, otherwise at most every
|
|
@@ -19,6 +31,7 @@ export declare class ProgressBatcher {
|
|
|
19
31
|
private timer;
|
|
20
32
|
private readonly maxBatchSize;
|
|
21
33
|
private readonly flushIntervalMs;
|
|
34
|
+
private readonly maxBatchBytes;
|
|
22
35
|
constructor(emit: ProgressEmitter, options?: ProgressBatcherOptions);
|
|
23
36
|
push(event: AgentEvent): void;
|
|
24
37
|
/** M4 Phase 4 (part B.3, observability): events buffered right now, not yet flushed as a `task.progress` batch — a cheap per-task queue-depth watermark for the daemon's control-socket `status` result (see `task-runner.ts`'s `getQueueWatermarks`). */
|
|
@@ -102,6 +102,8 @@ export declare const MAX_TRACKED_TASK_IDS = 2000;
|
|
|
102
102
|
export declare const MAX_DURATION_EXCEEDED_REASON_PREFIX = "resource limit exceeded: maxDurationMs";
|
|
103
103
|
/** M5 batch-3 (workstream 2): same contract as {@link MAX_DURATION_EXCEEDED_REASON_PREFIX}, for `DaemonConfig.maxTaskOutputBytes` — see `TaskRunner.pump`'s own per-event byte counting. */
|
|
104
104
|
export declare const MAX_OUTPUT_BYTES_EXCEEDED_REASON_PREFIX = "resource limit exceeded: maxTaskOutputBytes";
|
|
105
|
+
/** Stable fail-closed reason for one normalized event that cannot fit the configured activity batch budget. */
|
|
106
|
+
export declare const MAX_PROGRESS_BATCH_BYTES_EXCEEDED_REASON_PREFIX = "resource limit exceeded: progressBatch.maxBatchBytes";
|
|
105
107
|
/**
|
|
106
108
|
* additive-minor (`task.complete.document`): same stable-PREFIX contract as
|
|
107
109
|
* {@link MAX_DURATION_EXCEEDED_REASON_PREFIX} above, carried by every
|
package/dist/index.d.ts
CHANGED
|
@@ -9,6 +9,7 @@ export { GitWorkspaceStore } from './daemon/git-workspace-store';
|
|
|
9
9
|
export type { GitWorkspaceLedger, GitWorkspaceLedgerRecord, GitWorkspacePhase } from './daemon/git-workspace-store';
|
|
10
10
|
export { createDaemon, createDaemonWithAdapters } from './daemon/create-daemon';
|
|
11
11
|
export type { Daemon, DaemonConfig, DaemonStatus, DaemonOverrides, DaemonBranding, HostedJournalConfig, DeviceAssertionConfig } from './daemon/create-daemon';
|
|
12
|
+
export type { ProgressBatcherOptions } from './daemon/progress-batcher';
|
|
12
13
|
/**
|
|
13
14
|
* Plan `device-assertion-broker`: the ONLY control-socket capability this
|
|
14
15
|
* package exposes publicly. `connectControlClient`/`ControlClient` are
|
package/dist/index.js
CHANGED
|
@@ -8188,6 +8188,11 @@ function createStatfsFreeBytesProvider(dir) {
|
|
|
8188
8188
|
var BASE_PLATFORM_ALLOWLIST = [
|
|
8189
8189
|
"PATH",
|
|
8190
8190
|
"HOME",
|
|
8191
|
+
// macOS credential-store discovery used by subscription-authenticated
|
|
8192
|
+
// agent CLIs depends on the login account name as well as HOME. Omitting
|
|
8193
|
+
// USER makes `claude auth status` report logged out under the filtered
|
|
8194
|
+
// child environment even when the host CLI is logged in.
|
|
8195
|
+
"USER",
|
|
8191
8196
|
"USERPROFILE",
|
|
8192
8197
|
"TMPDIR",
|
|
8193
8198
|
"TEMP",
|
|
@@ -8295,11 +8300,37 @@ function computeEffectivePolicy(offered, ceiling) {
|
|
|
8295
8300
|
}
|
|
8296
8301
|
|
|
8297
8302
|
// src/daemon/progress-batcher.ts
|
|
8303
|
+
var ProgressEventTooLargeError = class extends Error {
|
|
8304
|
+
constructor(actualBytes, maxBatchBytes) {
|
|
8305
|
+
super(`Progress event requires ${actualBytes} UTF-8 bytes, exceeding maxBatchBytes ${maxBatchBytes}.`);
|
|
8306
|
+
this.actualBytes = actualBytes;
|
|
8307
|
+
this.maxBatchBytes = maxBatchBytes;
|
|
8308
|
+
this.name = "ProgressEventTooLargeError";
|
|
8309
|
+
}
|
|
8310
|
+
actualBytes;
|
|
8311
|
+
maxBatchBytes;
|
|
8312
|
+
};
|
|
8313
|
+
var encoder = new TextEncoder();
|
|
8314
|
+
function assertPositiveSafeInteger(value, name) {
|
|
8315
|
+
if (value !== void 0 && (!Number.isSafeInteger(value) || value <= 0)) {
|
|
8316
|
+
throw new TypeError(`${name} must be a positive safe integer when configured.`);
|
|
8317
|
+
}
|
|
8318
|
+
}
|
|
8319
|
+
function validateProgressBatcherOptions(options = {}) {
|
|
8320
|
+
assertPositiveSafeInteger(options.maxBatchSize, "maxBatchSize");
|
|
8321
|
+
assertPositiveSafeInteger(options.flushIntervalMs, "flushIntervalMs");
|
|
8322
|
+
assertPositiveSafeInteger(options.maxBatchBytes, "maxBatchBytes");
|
|
8323
|
+
}
|
|
8324
|
+
function encodedEventsBytes(events) {
|
|
8325
|
+
return encoder.encode(JSON.stringify(events)).length;
|
|
8326
|
+
}
|
|
8298
8327
|
var ProgressBatcher = class {
|
|
8299
8328
|
constructor(emit, options = {}) {
|
|
8300
8329
|
this.emit = emit;
|
|
8330
|
+
validateProgressBatcherOptions(options);
|
|
8301
8331
|
this.maxBatchSize = options.maxBatchSize ?? 10;
|
|
8302
8332
|
this.flushIntervalMs = options.flushIntervalMs ?? 250;
|
|
8333
|
+
this.maxBatchBytes = options.maxBatchBytes;
|
|
8303
8334
|
}
|
|
8304
8335
|
emit;
|
|
8305
8336
|
buffer = [];
|
|
@@ -8307,7 +8338,17 @@ var ProgressBatcher = class {
|
|
|
8307
8338
|
timer;
|
|
8308
8339
|
maxBatchSize;
|
|
8309
8340
|
flushIntervalMs;
|
|
8341
|
+
maxBatchBytes;
|
|
8310
8342
|
push(event) {
|
|
8343
|
+
if (this.maxBatchBytes !== void 0) {
|
|
8344
|
+
const eventBytes = encodedEventsBytes([event]);
|
|
8345
|
+
if (eventBytes > this.maxBatchBytes) {
|
|
8346
|
+
throw new ProgressEventTooLargeError(eventBytes, this.maxBatchBytes);
|
|
8347
|
+
}
|
|
8348
|
+
if (this.buffer.length > 0 && encodedEventsBytes([...this.buffer, event]) > this.maxBatchBytes) {
|
|
8349
|
+
this.flush();
|
|
8350
|
+
}
|
|
8351
|
+
}
|
|
8311
8352
|
this.buffer.push(event);
|
|
8312
8353
|
if (this.buffer.length >= this.maxBatchSize) {
|
|
8313
8354
|
this.flush();
|
|
@@ -8360,6 +8401,7 @@ var MAX_INLINE_ARTIFACT_BYTES = 64 * 1024;
|
|
|
8360
8401
|
var MAX_TRACKED_TASK_IDS = 2e3;
|
|
8361
8402
|
var MAX_DURATION_EXCEEDED_REASON_PREFIX = "resource limit exceeded: maxDurationMs";
|
|
8362
8403
|
var MAX_OUTPUT_BYTES_EXCEEDED_REASON_PREFIX = "resource limit exceeded: maxTaskOutputBytes";
|
|
8404
|
+
var MAX_PROGRESS_BATCH_BYTES_EXCEEDED_REASON_PREFIX = "resource limit exceeded: progressBatch.maxBatchBytes";
|
|
8363
8405
|
var RESULT_DOCUMENT_UNDELIVERABLE_REASON_PREFIX = "result document undeliverable";
|
|
8364
8406
|
function resultDocumentRejectionDetail(check) {
|
|
8365
8407
|
switch (check.reason) {
|
|
@@ -9216,6 +9258,13 @@ var TaskRunner = class {
|
|
|
9216
9258
|
} catch (err) {
|
|
9217
9259
|
if (this.tasks.get(active.taskId) !== active || active.beingTornDown) return;
|
|
9218
9260
|
active.batcher.flush();
|
|
9261
|
+
if (err instanceof ProgressEventTooLargeError) {
|
|
9262
|
+
await this.failActiveTaskForResourceLimit(
|
|
9263
|
+
active.taskId,
|
|
9264
|
+
`${MAX_PROGRESS_BATCH_BYTES_EXCEEDED_REASON_PREFIX}: event requires ${err.actualBytes} UTF-8 bytes, exceeding the configured limit of ${err.maxBatchBytes} bytes`
|
|
9265
|
+
);
|
|
9266
|
+
return;
|
|
9267
|
+
}
|
|
9219
9268
|
const failure = projectRuntimeBoundaryFailure(err, "run");
|
|
9220
9269
|
if (failure.contractViolation) {
|
|
9221
9270
|
console.error("[byok/client] runtime adapter events iterable returned an untyped failure", err);
|
|
@@ -10302,6 +10351,7 @@ function buildDaemonWithAdapters(config, adapters, overrides = {}, assertionProb
|
|
|
10302
10351
|
`DaemonConfig.maxTaskOutputBytes must be a positive number (or omitted to use the ${DEFAULT_MAX_TASK_OUTPUT_BYTES}-byte default) \u2014 got ${config.maxTaskOutputBytes}. Pass Number.POSITIVE_INFINITY to explicitly disable the cap; 0 or a negative number is rejected rather than silently treated as "disabled".`
|
|
10303
10352
|
);
|
|
10304
10353
|
}
|
|
10354
|
+
validateProgressBatcherOptions(config.progressBatch);
|
|
10305
10355
|
const presenceCadence = {
|
|
10306
10356
|
intervalMs: config.presence?.intervalMs ?? DEFAULT_PRESENCE_HEARTBEAT_INTERVAL_MS,
|
|
10307
10357
|
ttlMs: config.presence?.ttlMs ?? DEFAULT_PRESENCE_TTL_MS,
|
|
@@ -10587,7 +10637,7 @@ function buildDaemonWithAdapters(config, adapters, overrides = {}, assertionProb
|
|
|
10587
10637
|
// untouched. See `observer.ts`'s module doc comment.
|
|
10588
10638
|
send: sendEnvelope,
|
|
10589
10639
|
blobClient,
|
|
10590
|
-
batcherOptions:
|
|
10640
|
+
batcherOptions: config.progressBatch,
|
|
10591
10641
|
sessionWorkspaces,
|
|
10592
10642
|
gitWorkspaceManager,
|
|
10593
10643
|
gitWorkspaceStore,
|