@query-farm/vgi-rpc 0.7.0 → 0.7.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 (65) hide show
  1. package/dist/access-log.d.ts +5 -0
  2. package/dist/access-log.d.ts.map +1 -1
  3. package/dist/auth.d.ts +5 -0
  4. package/dist/auth.d.ts.map +1 -1
  5. package/dist/client/connect.d.ts +10 -0
  6. package/dist/client/connect.d.ts.map +1 -1
  7. package/dist/client/introspect.d.ts +14 -0
  8. package/dist/client/introspect.d.ts.map +1 -1
  9. package/dist/client/oauth.d.ts +9 -0
  10. package/dist/client/oauth.d.ts.map +1 -1
  11. package/dist/client/pipe.d.ts +24 -0
  12. package/dist/client/pipe.d.ts.map +1 -1
  13. package/dist/client/stream.d.ts +8 -0
  14. package/dist/client/stream.d.ts.map +1 -1
  15. package/dist/client/types.d.ts +23 -0
  16. package/dist/client/types.d.ts.map +1 -1
  17. package/dist/constants.d.ts +15 -1
  18. package/dist/constants.d.ts.map +1 -1
  19. package/dist/errors.d.ts +20 -3
  20. package/dist/errors.d.ts.map +1 -1
  21. package/dist/external.d.ts +2 -0
  22. package/dist/external.d.ts.map +1 -1
  23. package/dist/http/auth.d.ts +13 -0
  24. package/dist/http/auth.d.ts.map +1 -1
  25. package/dist/http/common.d.ts +1 -0
  26. package/dist/http/common.d.ts.map +1 -1
  27. package/dist/http/jwt.d.ts +1 -0
  28. package/dist/http/jwt.d.ts.map +1 -1
  29. package/dist/http/mtls.d.ts +7 -0
  30. package/dist/http/mtls.d.ts.map +1 -1
  31. package/dist/http/token.d.ts +5 -0
  32. package/dist/http/token.d.ts.map +1 -1
  33. package/dist/http/types.d.ts +2 -0
  34. package/dist/http/types.d.ts.map +1 -1
  35. package/dist/index.js.map +10 -10
  36. package/dist/launcher/serve-unix.d.ts +1 -0
  37. package/dist/launcher/serve-unix.d.ts.map +1 -1
  38. package/dist/launcher/state.d.ts +12 -0
  39. package/dist/launcher/state.d.ts.map +1 -1
  40. package/dist/protocol.d.ts +3 -0
  41. package/dist/protocol.d.ts.map +1 -1
  42. package/dist/types.d.ts +54 -0
  43. package/dist/types.d.ts.map +1 -1
  44. package/package.json +12 -12
  45. package/src/access-log.ts +5 -0
  46. package/src/auth.ts +5 -0
  47. package/src/client/connect.ts +10 -0
  48. package/src/client/introspect.ts +14 -0
  49. package/src/client/oauth.ts +9 -0
  50. package/src/client/pipe.ts +24 -0
  51. package/src/client/stream.ts +8 -0
  52. package/src/client/types.ts +23 -0
  53. package/src/constants.ts +16 -1
  54. package/src/errors.ts +13 -2
  55. package/src/external.ts +6 -1
  56. package/src/http/auth.ts +13 -0
  57. package/src/http/common.ts +1 -0
  58. package/src/http/jwt.ts +1 -0
  59. package/src/http/mtls.ts +7 -0
  60. package/src/http/token.ts +5 -0
  61. package/src/http/types.ts +2 -0
  62. package/src/launcher/serve-unix.ts +1 -0
  63. package/src/launcher/state.ts +12 -0
  64. package/src/protocol.ts +3 -0
  65. package/src/types.ts +54 -0
package/src/constants.ts CHANGED
@@ -1,21 +1,33 @@
1
1
  // © Copyright 2025-2026, Query.Farm LLC - https://query.farm
2
2
  // SPDX-License-Identifier: Apache-2.0
3
3
 
4
- /** Well-known metadata keys matching Python's metadata.py */
4
+ // Well-known metadata keys matching Python's metadata.py.
5
5
 
6
+ /** Batch-metadata key carrying the invoked RPC method name. */
6
7
  export const RPC_METHOD_KEY = "vgi_rpc.method";
8
+ /** Batch-metadata key carrying a log batch's severity level. */
7
9
  export const LOG_LEVEL_KEY = "vgi_rpc.log_level";
10
+ /** Batch-metadata key carrying a log batch's message text. */
8
11
  export const LOG_MESSAGE_KEY = "vgi_rpc.log_message";
12
+ /** Batch-metadata key carrying a log batch's structured extra fields. */
9
13
  export const LOG_EXTRA_KEY = "vgi_rpc.log_extra";
14
+ /** Batch-metadata key carrying the wire request-framing version. */
10
15
  export const REQUEST_VERSION_KEY = "vgi_rpc.request_version";
16
+ /** Current wire request-framing version. Distinct from the application-level
17
+ * {@link PROTOCOL_VERSION_KEY protocol version}. */
11
18
  export const REQUEST_VERSION = "1";
12
19
 
20
+ /** Batch-metadata key identifying the server instance that produced a batch. */
13
21
  export const SERVER_ID_KEY = "vgi_rpc.server_id";
22
+ /** Batch-metadata key carrying the client-supplied request id. */
14
23
  export const REQUEST_ID_KEY = "vgi_rpc.request_id";
15
24
 
25
+ /** Batch-metadata key carrying the service / protocol name. */
16
26
  export const PROTOCOL_NAME_KEY = "vgi_rpc.protocol_name";
27
+ /** Batch-metadata key carrying the `__describe__` response schema version. */
17
28
  export const DESCRIBE_VERSION_KEY = "vgi_rpc.describe_version";
18
29
  export const PROTOCOL_HASH_KEY = "vgi_rpc.protocol_hash";
30
+ /** Current `__describe__` response schema version (the slim 8-column schema). */
19
31
  export const DESCRIBE_VERSION = "4";
20
32
 
21
33
  /** Application protocol surface version. Carried on every request batch from
@@ -26,14 +38,17 @@ export const DESCRIBE_VERSION = "4";
26
38
  * (wire framing). Mirrors Python's `PROTOCOL_VERSION_KEY`. */
27
39
  export const PROTOCOL_VERSION_KEY = "vgi_rpc.protocol_version";
28
40
 
41
+ /** Reserved method name for the introspection (`__describe__`) call. */
29
42
  export const DESCRIBE_METHOD_NAME = "__describe__";
30
43
 
44
+ /** Batch-metadata key carrying the base64-encoded stream continuation/state token. */
31
45
  export const STATE_KEY = "vgi_rpc.stream_state#b64";
32
46
  export const CANCEL_KEY = "vgi_rpc.cancel";
33
47
 
34
48
  export const LOCATION_KEY = "vgi_rpc.location";
35
49
  export const LOCATION_SHA256_KEY = "vgi_rpc.location.sha256";
36
50
 
51
+ /** HTTP response header set when an RPC error is returned over the HTTP transport. */
37
52
  export const RPC_ERROR_HEADER = "X-VGI-RPC-Error";
38
53
 
39
54
  /** Top-level metadata key on an EXCEPTION batch identifying the error category.
package/src/errors.ts CHANGED
@@ -4,8 +4,11 @@
4
4
  /** Error thrown when the server encounters an RPC protocol error. */
5
5
  export class RpcError extends Error {
6
6
  constructor(
7
+ /** Remote error class name (e.g. `"ValueError"`). */
7
8
  public readonly errorType: string,
9
+ /** Human-readable message from the remote error. */
8
10
  public readonly errorMessage: string,
11
+ /** Remote stack-trace text, or an empty string when unavailable. */
9
12
  public readonly remoteTraceback: string,
10
13
  ) {
11
14
  super(`${errorType}: ${errorMessage}`);
@@ -21,10 +24,12 @@ export class VersionError extends Error {
21
24
  }
22
25
  }
23
26
 
24
- /** Well-known values for the `vgi_rpc.error_kind` batch metadata key. Mirrors
25
- * Python's `vgi_rpc.metadata.ERROR_KIND_*` constants. */
27
+ /** `vgi_rpc.error_kind` batch-metadata value for {@link MethodNotImplementedError}.
28
+ * Mirrors Python's `vgi_rpc.metadata.ERROR_KIND_*` constants. */
26
29
  export const ERROR_KIND_METHOD_NOT_IMPLEMENTED = "method_not_implemented";
30
+ /** `vgi_rpc.error_kind` batch-metadata value for {@link SessionLostError}. */
27
31
  export const ERROR_KIND_SESSION_LOST = "session_lost";
32
+ /** `vgi_rpc.error_kind` batch-metadata value for {@link ServerDrainingError}. */
28
33
  export const ERROR_KIND_SERVER_DRAINING = "server_draining";
29
34
  export const ERROR_KIND_PROTOCOL_VERSION_MISMATCH = "protocol_version_mismatch";
30
35
 
@@ -68,7 +73,9 @@ export function parseProtocolVersion(value: string): [number, number, number] {
68
73
  * string-matching the message.
69
74
  */
70
75
  export class MethodNotImplementedError extends Error {
76
+ /** Typed `vgi_rpc.error_kind` marker for this error class. */
71
77
  static readonly errorKind = ERROR_KIND_METHOD_NOT_IMPLEMENTED;
78
+ /** Typed `vgi_rpc.error_kind` marker hoisted onto the error batch metadata. */
72
79
  readonly errorKind = ERROR_KIND_METHOD_NOT_IMPLEMENTED;
73
80
  constructor(message: string) {
74
81
  super(message);
@@ -79,7 +86,9 @@ export class MethodNotImplementedError extends Error {
79
86
  /** Raised when a sticky session token is malformed, expired, evicted, or
80
87
  * bound to a different worker / principal. HTTP-only. */
81
88
  export class SessionLostError extends Error {
89
+ /** Typed `vgi_rpc.error_kind` marker for this error class. */
82
90
  static readonly errorKind = ERROR_KIND_SESSION_LOST;
91
+ /** Typed `vgi_rpc.error_kind` marker hoisted onto the error batch metadata. */
83
92
  readonly errorKind = ERROR_KIND_SESSION_LOST;
84
93
  constructor(message: string) {
85
94
  super(message);
@@ -89,7 +98,9 @@ export class SessionLostError extends Error {
89
98
 
90
99
  /** Raised when `ctx.openSession` is called while the server is draining. */
91
100
  export class ServerDrainingError extends Error {
101
+ /** Typed `vgi_rpc.error_kind` marker for this error class. */
92
102
  static readonly errorKind = ERROR_KIND_SERVER_DRAINING;
103
+ /** Typed `vgi_rpc.error_kind` marker hoisted onto the error batch metadata. */
93
104
  readonly errorKind = ERROR_KIND_SERVER_DRAINING;
94
105
  constructor(message: string) {
95
106
  super(message);
package/src/external.ts CHANGED
@@ -54,7 +54,12 @@ export interface ExternalLocationConfig {
54
54
  /** Minimum batch byte size to trigger externalization. Default: 1MB. */
55
55
  externalizeThresholdBytes?: number;
56
56
  /** Optional zstd compression for uploaded data. */
57
- compression?: { algorithm: "zstd"; level?: number };
57
+ compression?: {
58
+ /** Compression algorithm; only `"zstd"` is currently supported. */
59
+ algorithm: "zstd";
60
+ /** zstd compression level. Default: 3. */
61
+ level?: number;
62
+ };
58
63
  /** URL validator called before fetching. Throw to reject. Default: HTTPS-only. */
59
64
  urlValidator?: ((url: string) => void) | null;
60
65
  }
package/src/http/auth.ts CHANGED
@@ -8,14 +8,27 @@ export type AuthenticateFn = (request: Request) => AuthContext | Promise<AuthCon
8
8
 
9
9
  /** RFC 9728 OAuth Protected Resource Metadata. */
10
10
  export interface OAuthResourceMetadata {
11
+ /** The protected resource's canonical URL. Doubles as the base for the
12
+ * `/_oauth/callback` redirect URI. */
11
13
  resource: string;
14
+ /** Authorization-server issuer URLs. The PKCE flow uses
15
+ * `authorizationServers[0]` for OIDC discovery. */
12
16
  authorizationServers: string[];
17
+ /** Scopes the resource advertises. When non-empty these become the PKCE
18
+ * authorization request's space-joined `scope`, taking precedence over
19
+ * {@link HttpHandlerOptions.oauthPkceScope}. */
13
20
  scopesSupported?: string[];
21
+ /** Advertised bearer methods (e.g. `["header"]`). */
14
22
  bearerMethodsSupported?: string[];
23
+ /** JWS algorithms the resource accepts. */
15
24
  resourceSigningAlgValuesSupported?: string[];
25
+ /** Human-readable resource name. */
16
26
  resourceName?: string;
27
+ /** Documentation URL for the resource. */
17
28
  resourceDocumentation?: string;
29
+ /** Policy URL for the resource. */
18
30
  resourcePolicyUri?: string;
31
+ /** Terms-of-service URL for the resource. */
19
32
  resourceTosUri?: string;
20
33
  /** OAuth client_id that clients should use with the authorization server. */
21
34
  clientId?: string;
@@ -11,6 +11,7 @@ import {
11
11
  import { RPC_ERROR_HEADER } from "../constants.js";
12
12
  import type { CookieSpec } from "../types.js";
13
13
 
14
+ /** MIME type for Arrow IPC stream request and response bodies. */
14
15
  export const ARROW_CONTENT_TYPE = "application/vnd.apache.arrow.stream";
15
16
 
16
17
  // Sticky session header conventions (HTTP-only). Mirrors Python's
package/src/http/jwt.ts CHANGED
@@ -5,6 +5,7 @@ import * as oauth from "oauth4webapi";
5
5
  import { AuthContext } from "../auth.js";
6
6
  import type { AuthenticateFn } from "./auth.js";
7
7
 
8
+ /** Options for {@link jwtAuthenticate}, configuring JWT Bearer-token validation. */
8
9
  export interface JwtAuthenticateOptions {
9
10
  /** The expected `iss` claim (also used to discover AS metadata). */
10
11
  issuer: string;
package/src/http/mtls.ts CHANGED
@@ -24,11 +24,18 @@ function _loadNodeCrypto(): { X509Certificate: any; createHash: any } {
24
24
 
25
25
  /** A single element from an `x-forwarded-client-cert` header. */
26
26
  export interface XfccElement {
27
+ /** Hex SHA-256 digest of the client certificate (`Hash` key). */
27
28
  hash: string | null;
29
+ /** URL-decoded PEM of the client certificate (`Cert` key), if the proxy
30
+ * forwarded it. */
28
31
  cert: string | null;
32
+ /** Certificate Subject DN (`Subject` key). */
29
33
  subject: string | null;
34
+ /** URL-decoded URI-type Subject Alternative Name (`URI` key). */
30
35
  uri: string | null;
36
+ /** DNS-type Subject Alternative Names (`DNS` keys); may repeat in the header. */
31
37
  dns: readonly string[];
38
+ /** URL-decoded URI of the proxy that presented the cert (`By` key). */
32
39
  by: string | null;
33
40
  }
34
41
 
package/src/http/token.ts CHANGED
@@ -139,10 +139,15 @@ export function packStateToken(
139
139
  return bytesToBase64(wire);
140
140
  }
141
141
 
142
+ /** Decrypted payload of a state token, as returned by {@link unpackStateToken}. */
142
143
  export interface UnpackedToken {
144
+ /** Serialized stream-state bytes carried by the token. */
143
145
  stateBytes: Uint8Array;
146
+ /** Serialized output-schema IPC bytes. */
144
147
  schemaBytes: Uint8Array;
148
+ /** Serialized input-schema IPC bytes (exchange streams). */
145
149
  inputSchemaBytes: Uint8Array;
150
+ /** Unix epoch seconds at which the token was minted (used for TTL checks). */
146
151
  createdAt: number;
147
152
  }
148
153
 
package/src/http/types.ts CHANGED
@@ -112,7 +112,9 @@ export interface HttpHandlerOptions {
112
112
 
113
113
  /** Serializer for stream state objects stored in state tokens. */
114
114
  export interface StateSerializer {
115
+ /** Encode a stream-state object into the bytes sealed inside a state token. */
115
116
  serialize(state: any): Uint8Array;
117
+ /** Decode the bytes recovered from a state token back into a state object. */
116
118
  deserialize(bytes: Uint8Array): any;
117
119
  }
118
120
 
@@ -79,6 +79,7 @@ export interface ServeUnixOptions {
79
79
 
80
80
  /** Handle returned by {@link serveUnix} for callers that want to stop the server. */
81
81
  export interface ServeUnixHandle {
82
+ /** Absolute path of the bound AF_UNIX socket the server is listening on. */
82
83
  readonly socketPath: string;
83
84
  /** Shut down the listener and unlink the socket file. */
84
85
  stop(): Promise<void>;
@@ -15,11 +15,15 @@ import { computeHash } from "./hash.js";
15
15
 
16
16
  /** Filesystem layout for one worker tuple: `<state_dir>/<hash>.{lock,sock,meta}`. */
17
17
  export interface SocketPaths {
18
+ /** Advisory lockfile path (`<hash>.lock`) guarding launch + liveness. */
18
19
  lockPath: string;
20
+ /** AF_UNIX socket path (`<hash>.sock`) the worker binds. */
19
21
  sockPath: string;
22
+ /** Launch-metadata JSON path (`<hash>.meta`) read by `--status`. */
20
23
  metaPath: string;
21
24
  }
22
25
 
26
+ /** Derive the lock/sock/meta path triple for a worker `hashId` under `stateDir`. */
23
27
  export function socketPaths(stateDir: string, hashId: string): SocketPaths {
24
28
  return {
25
29
  lockPath: path.join(stateDir, `${hashId}.lock`),
@@ -97,15 +101,23 @@ export function writeMeta(metaPath: string, workerArgv: readonly string[], cwd:
97
101
  // Status / GC
98
102
  // ---------------------------------------------------------------------------
99
103
 
104
+ /** One row of `--status` output describing a launched worker tuple. */
100
105
  export interface StatusRow {
106
+ /** Canonical hash identifying the worker tuple (the `<hash>` filename stem). */
101
107
  hashId: string;
108
+ /** Worker argv recorded at launch, or `[]` when the meta file is missing. */
102
109
  cmd: string[];
110
+ /** Working directory recorded at launch, or `""` when unknown. */
103
111
  cwd: string;
112
+ /** AF_UNIX socket path the worker binds. */
104
113
  socket: string;
114
+ /** Unix epoch seconds the worker was launched, or `null` when unknown. */
105
115
  startedAt: number | null;
116
+ /** Whether a probe connection to {@link StatusRow.socket} currently succeeds. */
106
117
  alive: boolean;
107
118
  }
108
119
 
120
+ /** Outcome of a {@link gcStateDir} sweep. */
109
121
  export interface GcResult {
110
122
  /** Hash IDs of stale entries that were removed. */
111
123
  cleaned: string[];
package/src/protocol.ts CHANGED
@@ -23,6 +23,7 @@ const EMPTY_SCHEMA = makeSchema([]);
23
23
  * Register unary, producer, and exchange methods, then pass to `VgiRpcServer`.
24
24
  */
25
25
  export class Protocol {
26
+ /** Service / protocol name, exposed to clients via introspection. */
26
27
  readonly name: string;
27
28
  /**
28
29
  * Application protocol surface version. When non-empty, the server enforces
@@ -162,6 +163,8 @@ export class Protocol {
162
163
  return this;
163
164
  }
164
165
 
166
+ /** Snapshot of the registered methods, keyed by method name. Returns a copy,
167
+ * so mutating it does not affect the protocol. */
165
168
  getMethods(): Map<string, MethodDefinition> {
166
169
  return new Map(this._methods);
167
170
  }
package/src/types.ts CHANGED
@@ -5,8 +5,14 @@ import { batchFromColumns, isBatch, type VgiBatch, type VgiSchema } from "./arro
5
5
  import { AuthContext } from "./auth.js";
6
6
  import { buildLogBatch, coerceInt64 } from "./wire/response.js";
7
7
 
8
+ /**
9
+ * Whether an RPC method is request/response or streaming. Mirrors Python's
10
+ * `MethodType` and is carried in the `__describe__` payload.
11
+ */
8
12
  export enum MethodType {
13
+ /** Single request batch in, single result batch out. */
9
14
  UNARY = "unary",
15
+ /** Streamed batches — either a producer or an exchange stream. */
10
16
  STREAM = "stream",
11
17
  }
12
18
 
@@ -25,8 +31,11 @@ export enum MethodType {
25
31
  * - `UNIX` — AF_UNIX socket handler (the launcher path).
26
32
  */
27
33
  export enum TransportKind {
34
+ /** Stdio worker — the standalone {@link VgiRpcServer} loop. */
28
35
  PIPE = "pipe",
36
+ /** Fetch-style HTTP handler (`createHttpHandler`). */
29
37
  HTTP = "http",
38
+ /** AF_UNIX socket handler (the launcher path). */
30
39
  UNIX = "unix",
31
40
  }
32
41
 
@@ -46,6 +55,9 @@ export type ServeStartHook = (kind: TransportKind) => void | Promise<void>;
46
55
 
47
56
  /** Logging interface available to handlers. */
48
57
  export interface LogContext {
58
+ /** Emit a client-directed log message (sent as a zero-row log batch on the
59
+ * wire). `level` is a severity label such as `"info"`, `"warning"`, or
60
+ * `"error"`; `extra` carries optional structured string key/value pairs. */
49
61
  clientLog(level: string, message: string, extra?: Record<string, string>): void;
50
62
  }
51
63
 
@@ -90,6 +102,8 @@ export interface StickyContext {
90
102
 
91
103
  /** Extended context with authentication info, available to handlers. */
92
104
  export interface CallContext extends LogContext {
105
+ /** Authenticated principal for this call; {@link AuthContext.anonymous} when
106
+ * the request was not authenticated. */
93
107
  readonly auth: AuthContext;
94
108
  /** Coarse identifier of the bound transport, or `undefined` until the
95
109
  * server begins serving (the value is committed by the lifecycle hook
@@ -200,23 +214,47 @@ export type HeaderInit = (params: Record<string, any>, state: any, ctx: LogConte
200
214
  */
201
215
  export type OnCancelFn<S = any> = (state: S) => Promise<void> | void;
202
216
 
217
+ /**
218
+ * In-memory definition of one registered RPC method, produced by the
219
+ * {@link Protocol} builder and consumed by the dispatch layer. Which optional
220
+ * fields are populated depends on the method {@link type}: `handler` for unary
221
+ * methods, `producerInit`/`producerFn` for producer streams, and
222
+ * `exchangeInit`/`exchangeFn` for exchange streams.
223
+ */
203
224
  export interface MethodDefinition {
225
+ /** Method name as registered on the protocol. */
204
226
  name: string;
227
+ /** Whether the method is unary or streaming. */
205
228
  type: MethodType;
229
+ /** Schema of the request parameters batch. */
206
230
  paramsSchema: VgiSchema;
231
+ /** Schema of the unary result batch (unused for streams). */
207
232
  resultSchema: VgiSchema;
233
+ /** Schema of streamed output batches (producer and exchange streams). */
208
234
  outputSchema?: VgiSchema;
235
+ /** Schema of streamed input batches (exchange streams only). */
209
236
  inputSchema?: VgiSchema;
237
+ /** Implementation for unary methods. */
210
238
  handler?: UnaryHandler;
239
+ /** Builds the initial state object for a producer stream. */
211
240
  producerInit?: ProducerInit;
241
+ /** Produces output batches for a producer stream. */
212
242
  producerFn?: ProducerFn;
243
+ /** Builds the initial state object for an exchange stream. */
213
244
  exchangeInit?: ExchangeInit;
245
+ /** Handles each input batch of an exchange stream. */
214
246
  exchangeFn?: ExchangeFn;
247
+ /** Schema of the optional per-stream header batch. */
215
248
  headerSchema?: VgiSchema;
249
+ /** Builds the optional header batch emitted before the first output batch. */
216
250
  headerInit?: HeaderInit;
251
+ /** Optional hook run when the client cancels a stream. */
217
252
  onCancel?: OnCancelFn;
253
+ /** Human-readable method documentation, surfaced via introspection. */
218
254
  doc?: string;
255
+ /** Default values applied to omitted request parameters. */
219
256
  defaults?: Record<string, any>;
257
+ /** Human-readable parameter type names, surfaced via introspection. */
220
258
  paramTypes?: Record<string, string>;
221
259
  }
222
260
 
@@ -264,11 +302,17 @@ export interface DispatchInfo {
264
302
 
265
303
  /** Per-call I/O counters, matching Python's CallStatistics. */
266
304
  export interface CallStatistics {
305
+ /** Number of input batches read from the client. */
267
306
  inputBatches: number;
307
+ /** Number of output batches written to the client. */
268
308
  outputBatches: number;
309
+ /** Total rows across all input batches. */
269
310
  inputRows: number;
311
+ /** Total rows across all output batches. */
270
312
  outputRows: number;
313
+ /** Total serialized bytes of all input batches. */
271
314
  inputBytes: number;
315
+ /** Total serialized bytes of all output batches. */
272
316
  outputBytes: number;
273
317
  }
274
318
 
@@ -280,7 +324,11 @@ export type HookToken = unknown;
280
324
  * Implementations must be safe for concurrent use (HTTP transport is concurrent).
281
325
  */
282
326
  export interface DispatchHook {
327
+ /** Invoked before the method runs. The returned {@link HookToken} is opaque
328
+ * to the framework and passed back to {@link onDispatchEnd}. */
283
329
  onDispatchStart(info: DispatchInfo): HookToken;
330
+ /** Invoked after the method completes or throws. `stats` carries the per-call
331
+ * I/O counters; `error` is set only when the dispatch failed. */
284
332
  onDispatchEnd(token: HookToken, info: DispatchInfo, stats: CallStatistics, error?: Error): void;
285
333
  }
286
334
 
@@ -304,6 +352,8 @@ export class OutputCollector implements CallContext {
304
352
  private _cookieSinkEnabled = false;
305
353
  private _responseCookies: CookieSpec[] = [];
306
354
  private _stickyContext: StickyContext | null = null;
355
+ /** Authenticated principal for this call; {@link AuthContext.anonymous} when
356
+ * the request was not authenticated. */
307
357
  readonly auth: AuthContext;
308
358
  readonly cookies: ReadonlyMap<string, string>;
309
359
  readonly kind?: TransportKind;
@@ -423,14 +473,18 @@ export class OutputCollector implements CallContext {
423
473
  sink.action = "close";
424
474
  }
425
475
 
476
+ /** Schema of the data batches this collector emits. */
426
477
  get outputSchema(): VgiSchema {
427
478
  return this._outputSchema;
428
479
  }
429
480
 
481
+ /** True once {@link finish} has been called (producer streams only). */
430
482
  get finished(): boolean {
431
483
  return this._finished;
432
484
  }
433
485
 
486
+ /** Batches emitted so far this call — the single data batch plus any log
487
+ * batches, in emission order. Consumed by the dispatch layer. */
434
488
  get batches(): EmittedBatch[] {
435
489
  return this._batches;
436
490
  }