@crewhaus/gateway-protocol 0.3.2 → 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/dist/index.d.ts +113 -1
- package/dist/index.js +98 -0
- package/package.json +2 -2
package/dist/index.d.ts
CHANGED
|
@@ -231,13 +231,125 @@ export declare const AuditTailParams: z.ZodObject<{
|
|
|
231
231
|
sinceTs?: number | undefined;
|
|
232
232
|
}>;
|
|
233
233
|
export type AuditTailParamsT = z.infer<typeof AuditTailParams>;
|
|
234
|
-
|
|
234
|
+
/** Mirror of `@crewhaus/feedback-distill`'s `MAX_FEEDBACK_TEXT`. Kept in sync
|
|
235
|
+
* by hand for the same reason as SESSION_ID_REGEX above; the distill side
|
|
236
|
+
* still clips, so a drift can only ever be stricter here. */
|
|
237
|
+
export declare const MAX_FEEDBACK_TEXT = 8192;
|
|
238
|
+
export declare const FeedbackSubmitParams: z.ZodEffects<z.ZodObject<{
|
|
239
|
+
sessionId: z.ZodString;
|
|
240
|
+
/** 1-based ordinal of the rated user-text turn. */
|
|
241
|
+
turnNumber: z.ZodNumber;
|
|
242
|
+
thumbs: z.ZodOptional<z.ZodEnum<["up", "down"]>>;
|
|
243
|
+
stars: z.ZodOptional<z.ZodNumber>;
|
|
244
|
+
scale: z.ZodOptional<z.ZodObject<{
|
|
245
|
+
value: z.ZodNumber;
|
|
246
|
+
min: z.ZodNumber;
|
|
247
|
+
max: z.ZodNumber;
|
|
248
|
+
}, "strict", z.ZodTypeAny, {
|
|
249
|
+
value: number;
|
|
250
|
+
min: number;
|
|
251
|
+
max: number;
|
|
252
|
+
}, {
|
|
253
|
+
value: number;
|
|
254
|
+
min: number;
|
|
255
|
+
max: number;
|
|
256
|
+
}>>;
|
|
257
|
+
comment: z.ZodOptional<z.ZodString>;
|
|
258
|
+
/** A better answer — becomes `expected_output` at distill time. */
|
|
259
|
+
correction: z.ZodOptional<z.ZodString>;
|
|
260
|
+
/** Opaque rater handle. Redacted at ingestion like every other free text. */
|
|
261
|
+
rater: z.ZodOptional<z.ZodString>;
|
|
262
|
+
/** B19 — this record settles a multi-rater disagreement. */
|
|
263
|
+
adjudication: z.ZodOptional<z.ZodBoolean>;
|
|
264
|
+
}, "strict", z.ZodTypeAny, {
|
|
265
|
+
sessionId: string;
|
|
266
|
+
turnNumber: number;
|
|
267
|
+
thumbs?: "up" | "down" | undefined;
|
|
268
|
+
stars?: number | undefined;
|
|
269
|
+
scale?: {
|
|
270
|
+
value: number;
|
|
271
|
+
min: number;
|
|
272
|
+
max: number;
|
|
273
|
+
} | undefined;
|
|
274
|
+
comment?: string | undefined;
|
|
275
|
+
correction?: string | undefined;
|
|
276
|
+
rater?: string | undefined;
|
|
277
|
+
adjudication?: boolean | undefined;
|
|
278
|
+
}, {
|
|
279
|
+
sessionId: string;
|
|
280
|
+
turnNumber: number;
|
|
281
|
+
thumbs?: "up" | "down" | undefined;
|
|
282
|
+
stars?: number | undefined;
|
|
283
|
+
scale?: {
|
|
284
|
+
value: number;
|
|
285
|
+
min: number;
|
|
286
|
+
max: number;
|
|
287
|
+
} | undefined;
|
|
288
|
+
comment?: string | undefined;
|
|
289
|
+
correction?: string | undefined;
|
|
290
|
+
rater?: string | undefined;
|
|
291
|
+
adjudication?: boolean | undefined;
|
|
292
|
+
}>, {
|
|
293
|
+
sessionId: string;
|
|
294
|
+
turnNumber: number;
|
|
295
|
+
thumbs?: "up" | "down" | undefined;
|
|
296
|
+
stars?: number | undefined;
|
|
297
|
+
scale?: {
|
|
298
|
+
value: number;
|
|
299
|
+
min: number;
|
|
300
|
+
max: number;
|
|
301
|
+
} | undefined;
|
|
302
|
+
comment?: string | undefined;
|
|
303
|
+
correction?: string | undefined;
|
|
304
|
+
rater?: string | undefined;
|
|
305
|
+
adjudication?: boolean | undefined;
|
|
306
|
+
}, {
|
|
307
|
+
sessionId: string;
|
|
308
|
+
turnNumber: number;
|
|
309
|
+
thumbs?: "up" | "down" | undefined;
|
|
310
|
+
stars?: number | undefined;
|
|
311
|
+
scale?: {
|
|
312
|
+
value: number;
|
|
313
|
+
min: number;
|
|
314
|
+
max: number;
|
|
315
|
+
} | undefined;
|
|
316
|
+
comment?: string | undefined;
|
|
317
|
+
correction?: string | undefined;
|
|
318
|
+
rater?: string | undefined;
|
|
319
|
+
adjudication?: boolean | undefined;
|
|
320
|
+
}>;
|
|
321
|
+
export declare const FeedbackSubmitResult: z.ZodObject<{
|
|
322
|
+
recorded: z.ZodBoolean;
|
|
323
|
+
id: z.ZodString;
|
|
324
|
+
}, "strict", z.ZodTypeAny, {
|
|
325
|
+
id: string;
|
|
326
|
+
recorded: boolean;
|
|
327
|
+
}, {
|
|
328
|
+
id: string;
|
|
329
|
+
recorded: boolean;
|
|
330
|
+
}>;
|
|
331
|
+
export type FeedbackSubmitParamsT = z.infer<typeof FeedbackSubmitParams>;
|
|
332
|
+
export type FeedbackSubmitResultT = z.infer<typeof FeedbackSubmitResult>;
|
|
333
|
+
export declare const Method: z.ZodEnum<["runs.create", "runs.continue", "runs.cancel", "runs.subscribe", "sessions.list", "sessions.fork", "audit.tail", "feedback.submit"]>;
|
|
235
334
|
export type MethodT = z.infer<typeof Method>;
|
|
236
335
|
export declare function decodeRequest(raw: unknown): RequestEnvelopeT & {
|
|
237
336
|
method: MethodT;
|
|
238
337
|
};
|
|
239
338
|
export declare function encodeSuccess(id: string, result: unknown): ResponseEnvelopeT;
|
|
240
339
|
export declare function encodeError(id: string, code: string, message: string, data?: unknown): ResponseEnvelopeT;
|
|
340
|
+
/** MIME type of a `runs.subscribe` response body. */
|
|
341
|
+
export declare const SSE_CONTENT_TYPE: "text/event-stream";
|
|
342
|
+
/**
|
|
343
|
+
* Encode one trace event as an SSE `data:` frame. `event` is serialized with
|
|
344
|
+
* `JSON.stringify` (a TraceEvent is always JSON-serializable), so the frame is
|
|
345
|
+
* a single `data:` line terminated by the mandatory blank line.
|
|
346
|
+
*/
|
|
347
|
+
export declare function encodeSseEvent(event: unknown): string;
|
|
348
|
+
/**
|
|
349
|
+
* Encode an SSE comment frame (heartbeat / open marker). Any newline in `text`
|
|
350
|
+
* is collapsed to a space so the comment stays a single well-formed frame.
|
|
351
|
+
*/
|
|
352
|
+
export declare function encodeSseComment(text: string): string;
|
|
241
353
|
export declare const ErrorCode: {
|
|
242
354
|
readonly Unauthorized: "unauthorized";
|
|
243
355
|
readonly Forbidden: "forbidden";
|
package/dist/index.js
CHANGED
|
@@ -116,6 +116,63 @@ export const SessionsForkResult = z.object({ newSessionId: z.string().min(1) }).
|
|
|
116
116
|
export const AuditTailParams = z
|
|
117
117
|
.object({ tenantId: z.string().min(1), sinceTs: z.number().int().nonnegative().optional() })
|
|
118
118
|
.strict();
|
|
119
|
+
/**
|
|
120
|
+
* NEW-inloop-coverage — the gateway's RATING-CAPTURE method. A gateway-served
|
|
121
|
+
* agent is the highest-traffic surface CrewHaus has, and until this method it
|
|
122
|
+
* had no spec'd way to record a human verdict at all: `distill`, `optimize
|
|
123
|
+
* --ratings`, `judge calibrate` and the auto-distill flywheel were all
|
|
124
|
+
* structurally unreachable for the managed shape.
|
|
125
|
+
*
|
|
126
|
+
* The params are the USER-SUPPLIED subset of a `FeedbackRecord` (the daemon
|
|
127
|
+
* stamps `schemaVersion`, `id`, `source: "ui"` and `ts` itself, so a client
|
|
128
|
+
* cannot forge provenance or backdate a rating past the auto-distill
|
|
129
|
+
* watermark). `sessionId` + `turnNumber` are the same join key `crewhaus
|
|
130
|
+
* rate` uses, so a gateway rating and a CLI rating distill identically.
|
|
131
|
+
*
|
|
132
|
+
* The grammars are pinned HERE, at the boundary, so a bad submission is a
|
|
133
|
+
* protocol error instead of a durable line nothing downstream can use:
|
|
134
|
+
* - `sessionId` must match `@crewhaus/session-store`'s id grammar, which is
|
|
135
|
+
* also what `isFeedbackRecord` requires — an id in any other shape would
|
|
136
|
+
* be accepted, written, counted against disk, and then silently dropped
|
|
137
|
+
* by every reader (and it is interpolated into a path by the managed
|
|
138
|
+
* daemon's tenant-ownership check);
|
|
139
|
+
* - the free-text fields are length-capped at the same bound
|
|
140
|
+
* `clipFeedbackText` enforces, so oversize input is REFUSED rather than
|
|
141
|
+
* silently truncated on a surface whose `correction` becomes a dataset's
|
|
142
|
+
* `expected_output`.
|
|
143
|
+
*/
|
|
144
|
+
/** `@crewhaus/session-store`'s `generateId` grammar (mirrored — this package
|
|
145
|
+
* is dependency-light by design and must not pull the store in). */
|
|
146
|
+
const SESSION_ID_REGEX = /^sess_[0-9a-f]{16}$/;
|
|
147
|
+
/** Mirror of `@crewhaus/feedback-distill`'s `MAX_FEEDBACK_TEXT`. Kept in sync
|
|
148
|
+
* by hand for the same reason as SESSION_ID_REGEX above; the distill side
|
|
149
|
+
* still clips, so a drift can only ever be stricter here. */
|
|
150
|
+
export const MAX_FEEDBACK_TEXT = 8192;
|
|
151
|
+
export const FeedbackSubmitParams = z
|
|
152
|
+
.object({
|
|
153
|
+
sessionId: z.string().regex(SESSION_ID_REGEX, "sessionId must look like sess_<16 hex digits>"),
|
|
154
|
+
/** 1-based ordinal of the rated user-text turn. */
|
|
155
|
+
turnNumber: z.number().int().positive(),
|
|
156
|
+
thumbs: z.enum(["up", "down"]).optional(),
|
|
157
|
+
stars: z.number().int().min(1).max(5).optional(),
|
|
158
|
+
scale: z.object({ value: z.number(), min: z.number(), max: z.number() }).strict().optional(),
|
|
159
|
+
comment: z.string().max(MAX_FEEDBACK_TEXT).optional(),
|
|
160
|
+
/** A better answer — becomes `expected_output` at distill time. */
|
|
161
|
+
correction: z.string().max(MAX_FEEDBACK_TEXT).optional(),
|
|
162
|
+
/** Opaque rater handle. Redacted at ingestion like every other free text. */
|
|
163
|
+
rater: z.string().max(MAX_FEEDBACK_TEXT).optional(),
|
|
164
|
+
/** B19 — this record settles a multi-rater disagreement. */
|
|
165
|
+
adjudication: z.boolean().optional(),
|
|
166
|
+
})
|
|
167
|
+
.strict()
|
|
168
|
+
.refine((p) => p.thumbs !== undefined ||
|
|
169
|
+
p.stars !== undefined ||
|
|
170
|
+
p.scale !== undefined ||
|
|
171
|
+
(p.comment ?? "") !== "" ||
|
|
172
|
+
(p.correction ?? "") !== "", { message: "feedback.submit needs at least one of thumbs/stars/scale/comment/correction" });
|
|
173
|
+
export const FeedbackSubmitResult = z
|
|
174
|
+
.object({ recorded: z.boolean(), id: z.string().min(1) })
|
|
175
|
+
.strict();
|
|
119
176
|
export const Method = z.enum([
|
|
120
177
|
"runs.create",
|
|
121
178
|
"runs.continue",
|
|
@@ -124,6 +181,7 @@ export const Method = z.enum([
|
|
|
124
181
|
"sessions.list",
|
|
125
182
|
"sessions.fork",
|
|
126
183
|
"audit.tail",
|
|
184
|
+
"feedback.submit",
|
|
127
185
|
]);
|
|
128
186
|
const PARAM_SCHEMAS = {
|
|
129
187
|
"runs.create": RunsCreateParams,
|
|
@@ -133,6 +191,7 @@ const PARAM_SCHEMAS = {
|
|
|
133
191
|
"sessions.list": SessionsListParams,
|
|
134
192
|
"sessions.fork": SessionsForkParams,
|
|
135
193
|
"audit.tail": AuditTailParams,
|
|
194
|
+
"feedback.submit": FeedbackSubmitParams,
|
|
136
195
|
};
|
|
137
196
|
export function decodeRequest(raw) {
|
|
138
197
|
const parsed = RequestEnvelope.safeParse(raw);
|
|
@@ -165,6 +224,45 @@ export function encodeError(id, code, message, data) {
|
|
|
165
224
|
};
|
|
166
225
|
}
|
|
167
226
|
// ---------------------------------------------------------------------------
|
|
227
|
+
// `runs.subscribe` — Server-Sent Events framing.
|
|
228
|
+
//
|
|
229
|
+
// `runs.subscribe` is the ONE method that does not answer with a JSON
|
|
230
|
+
// `ResponseEnvelope`: it upgrades to a long-lived `text/event-stream` that
|
|
231
|
+
// replays the run's buffered trace events and then live-streams new ones.
|
|
232
|
+
// The frame format lives HERE (the wire-contract package) so the daemon and
|
|
233
|
+
// every reference client encode/parse it identically:
|
|
234
|
+
//
|
|
235
|
+
// - each trace event is one SSE `data:` frame carrying the event's JSON.
|
|
236
|
+
// `JSON.stringify` never emits a literal newline (newlines inside string
|
|
237
|
+
// fields are escaped to `\n`), so one event is always exactly one `data:`
|
|
238
|
+
// line — no multi-line-`data:` reassembly is required on the read side.
|
|
239
|
+
// - heartbeats and the connection-open marker are SSE COMMENT frames
|
|
240
|
+
// (`:`-prefixed); a spec-compliant client ignores them, so they keep
|
|
241
|
+
// intermediaries from idling the connection out without polluting the
|
|
242
|
+
// event stream. A comment body must not contain a newline.
|
|
243
|
+
//
|
|
244
|
+
// A stream carries no envelope `id`/`protocol` — those are per-request-reply
|
|
245
|
+
// fields; the subscription is a fire-hose keyed by the `runId` in the
|
|
246
|
+
// originating `runs.subscribe` request.
|
|
247
|
+
// ---------------------------------------------------------------------------
|
|
248
|
+
/** MIME type of a `runs.subscribe` response body. */
|
|
249
|
+
export const SSE_CONTENT_TYPE = "text/event-stream";
|
|
250
|
+
/**
|
|
251
|
+
* Encode one trace event as an SSE `data:` frame. `event` is serialized with
|
|
252
|
+
* `JSON.stringify` (a TraceEvent is always JSON-serializable), so the frame is
|
|
253
|
+
* a single `data:` line terminated by the mandatory blank line.
|
|
254
|
+
*/
|
|
255
|
+
export function encodeSseEvent(event) {
|
|
256
|
+
return `data: ${JSON.stringify(event)}\n\n`;
|
|
257
|
+
}
|
|
258
|
+
/**
|
|
259
|
+
* Encode an SSE comment frame (heartbeat / open marker). Any newline in `text`
|
|
260
|
+
* is collapsed to a space so the comment stays a single well-formed frame.
|
|
261
|
+
*/
|
|
262
|
+
export function encodeSseComment(text) {
|
|
263
|
+
return `: ${text.replace(/[\r\n]+/g, " ")}\n\n`;
|
|
264
|
+
}
|
|
265
|
+
// ---------------------------------------------------------------------------
|
|
168
266
|
// Standard error codes — wire-stable so reference clients can switch on them.
|
|
169
267
|
// ---------------------------------------------------------------------------
|
|
170
268
|
export const ErrorCode = {
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@crewhaus/gateway-protocol",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.4.2",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"description": "JSON-RPC wire protocol for the managed-daemon gateway — versioned envelope + Zod schemas",
|
|
6
6
|
"main": "dist/index.js",
|
|
@@ -15,7 +15,7 @@
|
|
|
15
15
|
"test": "bun test src"
|
|
16
16
|
},
|
|
17
17
|
"dependencies": {
|
|
18
|
-
"@crewhaus/errors": "0.
|
|
18
|
+
"@crewhaus/errors": "0.4.2",
|
|
19
19
|
"zod": "^3.23.8"
|
|
20
20
|
},
|
|
21
21
|
"license": "Apache-2.0",
|