@danypops/vehicle-core 0.15.0 → 0.16.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/dist/vehicle-contract.d.ts +19 -1
- package/dist/vehicle-jobs.d.ts +45 -0
- package/package.json +1 -1
- package/src/vehicle-contract.ts +25 -1
- package/src/vehicle-jobs.ts +50 -0
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import type { VehicleJobWakeBudget } from "./vehicle-jobs.js";
|
|
1
|
+
import type { VehicleJobSnapshot, VehicleJobSubmitOptions, VehicleJobSubmitResult, VehicleJobTailResult, VehicleJobWakeBudget } from "./vehicle-jobs.js";
|
|
2
2
|
export type JsonPrimitive = string | number | boolean | null;
|
|
3
3
|
export type JsonValue = JsonPrimitive | readonly JsonValue[] | {
|
|
4
4
|
readonly [key: string]: JsonValue;
|
|
@@ -324,6 +324,24 @@ export interface VehicleClient {
|
|
|
324
324
|
manifest(): Promise<VehicleManifest>;
|
|
325
325
|
invoke<Output = unknown>(name: string, version: number, input: unknown, options?: VehicleInvocationOptions): Promise<Output>;
|
|
326
326
|
close(): Promise<void>;
|
|
327
|
+
/**
|
|
328
|
+
* Vehicle Jobs -- submit a background-capable operation (one whose descriptor declares
|
|
329
|
+
* `background`, see {@link VehicleBackgroundCapability}) and get its jobId back immediately,
|
|
330
|
+
* without waiting for the operation itself to make any progress. Optional: a client that
|
|
331
|
+
* never talks to a job-capable Vehicle (or a hand-rolled test double) simply omits these five
|
|
332
|
+
* methods, exactly like this interface's own long-standing `subscribe()`-shaped extras --
|
|
333
|
+
* present on both LocalVehicleClient and RemoteVehicleClient, absent elsewhere. Feature-detect
|
|
334
|
+
* via the operation's own manifest `background` capability, not by probing for these methods.
|
|
335
|
+
*/
|
|
336
|
+
submitJob?(name: string, version: number, input: unknown, options?: VehicleJobSubmitOptions): Promise<VehicleJobSubmitResult>;
|
|
337
|
+
/** Never blocks -- current status, plus output/error once terminal. */
|
|
338
|
+
pollJob?(jobId: string): Promise<VehicleJobSnapshot>;
|
|
339
|
+
/** Progress entries strictly after `cursor` (0 for everything so far), plus the next cursor. Never blocks. */
|
|
340
|
+
tailJob?(jobId: string, cursor?: number): Promise<VehicleJobTailResult>;
|
|
341
|
+
/** Pushes new input to an already-running job's handler, if it opted in via context.steerInputs. */
|
|
342
|
+
steerJob?(jobId: string, input: unknown): Promise<void>;
|
|
343
|
+
/** Best-effort cancellation of a still-running job -- a no-op against an already-terminal one. */
|
|
344
|
+
cancelJob?(jobId: string): Promise<void>;
|
|
327
345
|
}
|
|
328
346
|
export declare function defineVehicleOperation<Input, Output>(options: DefineVehicleOperationOptions<Input, Output>): VehicleOperation<Input, Output>;
|
|
329
347
|
export declare function bindVehicleOperation<Input, Output>(operation: VehicleOperation<Input, Output>, bind: () => VehicleOperationHandler<Input, Output>): VehicleOperationBinding<Input, Output>;
|
package/dist/vehicle-jobs.d.ts
CHANGED
|
@@ -1,4 +1,6 @@
|
|
|
1
1
|
/** Pure pieces of Vehicle Jobs: a termination-reason resolver and a bounded wake-log accumulator. Orchestration lives in vehicle-server's VehicleJobStore. */
|
|
2
|
+
import type { VehiclePrincipal } from "./vehicle-contract.js";
|
|
3
|
+
import type { VehicleFailure } from "./vehicle-errors.js";
|
|
2
4
|
export type VehicleJobStatus = "running" | "succeeded" | "failed" | "canceled";
|
|
3
5
|
/** Highest precedence first -- an explicit cancel always wins even if the handler also settled around the same time. "orphaned" is a restart-reconciliation outcome: a job that was still "running" when its process died, so nothing ever really failed or succeeded -- the record's own status just goes stale. */
|
|
4
6
|
export declare const VEHICLE_JOB_TERMINATION_PRECEDENCE: readonly ["canceled", "timeout", "orphaned", "failed", "succeeded"];
|
|
@@ -101,6 +103,49 @@ export interface VehicleJobRetentionOptions {
|
|
|
101
103
|
readonly deliveredRetentionMs: number;
|
|
102
104
|
readonly now: number;
|
|
103
105
|
}
|
|
106
|
+
/**
|
|
107
|
+
* The client-facing wire shapes for Vehicle Jobs -- submit/poll/tail options and results, shared by
|
|
108
|
+
* vehicle-server's VehicleJobStore (the orchestration side) and vehicle-client's job-capable clients
|
|
109
|
+
* (the calling side), so both halves of the wire agree on one definition instead of two structurally
|
|
110
|
+
*-identical copies drifting apart. Every field type referenced here already lives in vehicle-core
|
|
111
|
+
* (VehiclePrincipal, VehicleFailure, VehicleJobStatus, ...), which is what makes it safe for these
|
|
112
|
+
* shapes to live here too, alongside the rest of Vehicle Jobs' pure pieces.
|
|
113
|
+
*/
|
|
114
|
+
export interface VehicleJobSubmitOptions {
|
|
115
|
+
readonly permissions?: readonly string[];
|
|
116
|
+
readonly principal?: VehiclePrincipal;
|
|
117
|
+
readonly idempotencyKey?: string;
|
|
118
|
+
readonly expectedRevision?: string | number;
|
|
119
|
+
readonly approvalCapability?: string;
|
|
120
|
+
readonly correlationId?: string;
|
|
121
|
+
readonly callerSessionId?: string;
|
|
122
|
+
readonly callerProjectRoot?: string;
|
|
123
|
+
/** Defaults to "transition". */
|
|
124
|
+
readonly notifyMode?: VehicleJobNotifyMode;
|
|
125
|
+
/** Defaults to background.defaultWakeBudget; clamped to background.maxWakeBudget either way. */
|
|
126
|
+
readonly wakeBudget?: VehicleJobWakeBudget;
|
|
127
|
+
/** No default -- unset means the job runs until it settles or is canceled. */
|
|
128
|
+
readonly maxLifetimeMs?: number;
|
|
129
|
+
}
|
|
130
|
+
export interface VehicleJobSubmitResult {
|
|
131
|
+
readonly jobId: string;
|
|
132
|
+
}
|
|
133
|
+
export interface VehicleJobSnapshot {
|
|
134
|
+
readonly jobId: string;
|
|
135
|
+
readonly operationName: string;
|
|
136
|
+
readonly operationVersion: number;
|
|
137
|
+
readonly status: VehicleJobStatus;
|
|
138
|
+
readonly createdAt: number;
|
|
139
|
+
readonly updatedAt: number;
|
|
140
|
+
readonly delivered: boolean;
|
|
141
|
+
readonly terminationReason?: VehicleJobTerminationReason;
|
|
142
|
+
readonly output?: unknown;
|
|
143
|
+
readonly error?: VehicleFailure;
|
|
144
|
+
}
|
|
145
|
+
export interface VehicleJobTailResult {
|
|
146
|
+
readonly entries: readonly VehicleJobWakeEntry[];
|
|
147
|
+
readonly cursor: number;
|
|
148
|
+
}
|
|
104
149
|
/**
|
|
105
150
|
* Pure eviction-selection policy, kept separate from VehicleJobStore's own
|
|
106
151
|
* bookkeeping so the bounded-retention rule is independently testable.
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@danypops/vehicle-core",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.16.0",
|
|
4
4
|
"description": "Vehicle's runtime-neutral wire contract: operation descriptors, schema codecs, failure shapes. Zero runtime dependencies, zero Bun-specific code -- the one thing every Vehicle client and server package depends on.",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"type": "module",
|
package/src/vehicle-contract.ts
CHANGED
|
@@ -1,4 +1,10 @@
|
|
|
1
|
-
import type {
|
|
1
|
+
import type {
|
|
2
|
+
VehicleJobSnapshot,
|
|
3
|
+
VehicleJobSubmitOptions,
|
|
4
|
+
VehicleJobSubmitResult,
|
|
5
|
+
VehicleJobTailResult,
|
|
6
|
+
VehicleJobWakeBudget,
|
|
7
|
+
} from "./vehicle-jobs.js";
|
|
2
8
|
|
|
3
9
|
export type JsonPrimitive = string | number | boolean | null;
|
|
4
10
|
export type JsonValue = JsonPrimitive | readonly JsonValue[] | { readonly [key: string]: JsonValue };
|
|
@@ -438,6 +444,24 @@ export interface VehicleClient {
|
|
|
438
444
|
manifest(): Promise<VehicleManifest>;
|
|
439
445
|
invoke<Output = unknown>(name: string, version: number, input: unknown, options?: VehicleInvocationOptions): Promise<Output>;
|
|
440
446
|
close(): Promise<void>;
|
|
447
|
+
/**
|
|
448
|
+
* Vehicle Jobs -- submit a background-capable operation (one whose descriptor declares
|
|
449
|
+
* `background`, see {@link VehicleBackgroundCapability}) and get its jobId back immediately,
|
|
450
|
+
* without waiting for the operation itself to make any progress. Optional: a client that
|
|
451
|
+
* never talks to a job-capable Vehicle (or a hand-rolled test double) simply omits these five
|
|
452
|
+
* methods, exactly like this interface's own long-standing `subscribe()`-shaped extras --
|
|
453
|
+
* present on both LocalVehicleClient and RemoteVehicleClient, absent elsewhere. Feature-detect
|
|
454
|
+
* via the operation's own manifest `background` capability, not by probing for these methods.
|
|
455
|
+
*/
|
|
456
|
+
submitJob?(name: string, version: number, input: unknown, options?: VehicleJobSubmitOptions): Promise<VehicleJobSubmitResult>;
|
|
457
|
+
/** Never blocks -- current status, plus output/error once terminal. */
|
|
458
|
+
pollJob?(jobId: string): Promise<VehicleJobSnapshot>;
|
|
459
|
+
/** Progress entries strictly after `cursor` (0 for everything so far), plus the next cursor. Never blocks. */
|
|
460
|
+
tailJob?(jobId: string, cursor?: number): Promise<VehicleJobTailResult>;
|
|
461
|
+
/** Pushes new input to an already-running job's handler, if it opted in via context.steerInputs. */
|
|
462
|
+
steerJob?(jobId: string, input: unknown): Promise<void>;
|
|
463
|
+
/** Best-effort cancellation of a still-running job -- a no-op against an already-terminal one. */
|
|
464
|
+
cancelJob?(jobId: string): Promise<void>;
|
|
441
465
|
}
|
|
442
466
|
|
|
443
467
|
export function defineVehicleOperation<Input, Output>(
|
package/src/vehicle-jobs.ts
CHANGED
|
@@ -1,5 +1,8 @@
|
|
|
1
1
|
/** Pure pieces of Vehicle Jobs: a termination-reason resolver and a bounded wake-log accumulator. Orchestration lives in vehicle-server's VehicleJobStore. */
|
|
2
2
|
|
|
3
|
+
import type { VehiclePrincipal } from "./vehicle-contract.js";
|
|
4
|
+
import type { VehicleFailure } from "./vehicle-errors.js";
|
|
5
|
+
|
|
3
6
|
export type VehicleJobStatus = "running" | "succeeded" | "failed" | "canceled";
|
|
4
7
|
|
|
5
8
|
/** Highest precedence first -- an explicit cancel always wins even if the handler also settled around the same time. "orphaned" is a restart-reconciliation outcome: a job that was still "running" when its process died, so nothing ever really failed or succeeded -- the record's own status just goes stale. */
|
|
@@ -212,6 +215,53 @@ export interface VehicleJobRetentionOptions {
|
|
|
212
215
|
readonly now: number;
|
|
213
216
|
}
|
|
214
217
|
|
|
218
|
+
/**
|
|
219
|
+
* The client-facing wire shapes for Vehicle Jobs -- submit/poll/tail options and results, shared by
|
|
220
|
+
* vehicle-server's VehicleJobStore (the orchestration side) and vehicle-client's job-capable clients
|
|
221
|
+
* (the calling side), so both halves of the wire agree on one definition instead of two structurally
|
|
222
|
+
*-identical copies drifting apart. Every field type referenced here already lives in vehicle-core
|
|
223
|
+
* (VehiclePrincipal, VehicleFailure, VehicleJobStatus, ...), which is what makes it safe for these
|
|
224
|
+
* shapes to live here too, alongside the rest of Vehicle Jobs' pure pieces.
|
|
225
|
+
*/
|
|
226
|
+
export interface VehicleJobSubmitOptions {
|
|
227
|
+
readonly permissions?: readonly string[];
|
|
228
|
+
readonly principal?: VehiclePrincipal;
|
|
229
|
+
readonly idempotencyKey?: string;
|
|
230
|
+
readonly expectedRevision?: string | number;
|
|
231
|
+
readonly approvalCapability?: string;
|
|
232
|
+
readonly correlationId?: string;
|
|
233
|
+
readonly callerSessionId?: string;
|
|
234
|
+
readonly callerProjectRoot?: string;
|
|
235
|
+
/** Defaults to "transition". */
|
|
236
|
+
readonly notifyMode?: VehicleJobNotifyMode;
|
|
237
|
+
/** Defaults to background.defaultWakeBudget; clamped to background.maxWakeBudget either way. */
|
|
238
|
+
readonly wakeBudget?: VehicleJobWakeBudget;
|
|
239
|
+
/** No default -- unset means the job runs until it settles or is canceled. */
|
|
240
|
+
readonly maxLifetimeMs?: number;
|
|
241
|
+
}
|
|
242
|
+
|
|
243
|
+
export interface VehicleJobSubmitResult {
|
|
244
|
+
readonly jobId: string;
|
|
245
|
+
}
|
|
246
|
+
|
|
247
|
+
export interface VehicleJobSnapshot {
|
|
248
|
+
readonly jobId: string;
|
|
249
|
+
readonly operationName: string;
|
|
250
|
+
readonly operationVersion: number;
|
|
251
|
+
readonly status: VehicleJobStatus;
|
|
252
|
+
readonly createdAt: number;
|
|
253
|
+
readonly updatedAt: number;
|
|
254
|
+
readonly delivered: boolean;
|
|
255
|
+
readonly terminationReason?: VehicleJobTerminationReason;
|
|
256
|
+
readonly output?: unknown;
|
|
257
|
+
readonly error?: VehicleFailure;
|
|
258
|
+
}
|
|
259
|
+
|
|
260
|
+
export interface VehicleJobTailResult {
|
|
261
|
+
readonly entries: readonly VehicleJobWakeEntry[];
|
|
262
|
+
readonly cursor: number;
|
|
263
|
+
}
|
|
264
|
+
|
|
215
265
|
/**
|
|
216
266
|
* Pure eviction-selection policy, kept separate from VehicleJobStore's own
|
|
217
267
|
* bookkeeping so the bounded-retention rule is independently testable.
|