@shpitdev/convex-cliproxy-observability 0.3.6 → 0.3.7
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/CHANGELOG.md +10 -0
- package/README.md +2 -2
- package/dist/capture/content-health.d.ts +4 -1
- package/dist/capture/content-health.d.ts.map +1 -1
- package/dist/capture/content-health.js +6 -5
- package/dist/capture/content-health.js.map +1 -1
- package/dist/capture/index.d.ts +21 -0
- package/dist/capture/index.d.ts.map +1 -1
- package/dist/capture/index.js +53 -0
- package/dist/capture/index.js.map +1 -1
- package/dist/component/_generated/api.d.ts.map +1 -1
- package/dist/component/_generated/api.js.map +1 -1
- package/dist/component/_generated/component.d.ts.map +1 -1
- package/dist/component/ingest.d.ts +1 -0
- package/dist/component/ingest.d.ts.map +1 -1
- package/dist/projection.d.ts +6 -3
- package/dist/projection.d.ts.map +1 -1
- package/dist/projection.js +55 -7
- package/dist/projection.js.map +1 -1
- package/dist/protocols/body-parts.d.ts +19 -0
- package/dist/protocols/body-parts.d.ts.map +1 -0
- package/dist/protocols/body-parts.js +56 -0
- package/dist/protocols/body-parts.js.map +1 -0
- package/dist/protocols/checkpoint.d.ts +16 -1
- package/dist/protocols/checkpoint.d.ts.map +1 -1
- package/dist/protocols/checkpoint.js +48 -14
- package/dist/protocols/checkpoint.js.map +1 -1
- package/dist/protocols/index.d.ts +1 -0
- package/dist/protocols/index.d.ts.map +1 -1
- package/dist/protocols/index.js +1 -0
- package/dist/protocols/index.js.map +1 -1
- package/package.json +1 -1
- package/src/capture/content-health.ts +8 -5
- package/src/capture/index.ts +74 -0
- package/src/component/_generated/api.ts +5 -6
- package/src/component/_generated/component.ts +6 -6
- package/src/projection.ts +71 -16
- package/src/protocols/body-parts.ts +58 -0
- package/src/protocols/checkpoint.ts +51 -13
- package/src/protocols/index.ts +1 -0
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { stockHookPieces } from "./body-parts.js";
|
|
2
2
|
import {
|
|
3
3
|
providerIdentity,
|
|
4
4
|
TOKEN_FIELDS,
|
|
@@ -7,7 +7,7 @@ import {
|
|
|
7
7
|
type PrivateContentReference,
|
|
8
8
|
} from "../model-call/index.js";
|
|
9
9
|
import type { CaptureObservationV1 } from "../capture/index.js";
|
|
10
|
-
import { decodeBody } from "../capture/index.js";
|
|
10
|
+
import { continuesBodyPart, decodeBody } from "../capture/index.js";
|
|
11
11
|
import { assembleResponsesStream } from "./responses.js";
|
|
12
12
|
import { SSEReader, type SSECheckpoint } from "./framing.js";
|
|
13
13
|
import { count, list, nanoTime, object, parseObject } from "./values.js";
|
|
@@ -28,6 +28,10 @@ export type ProjectionCheckpoint = {
|
|
|
28
28
|
streamed?: boolean;
|
|
29
29
|
inputSeen?: boolean;
|
|
30
30
|
chatFinished?: boolean;
|
|
31
|
+
/** First segment of an unfinished split body; projection reassembles from there. */
|
|
32
|
+
bodyPartSegment?: number;
|
|
33
|
+
/** Last part of an unfinished split body; the next observation must continue it. */
|
|
34
|
+
openBodyPart?: Pick<CaptureObservationV1, "kind" | "sequence" | "bodyPart">;
|
|
31
35
|
};
|
|
32
36
|
const usageFields = [
|
|
33
37
|
"input_tokens",
|
|
@@ -186,10 +190,22 @@ function observeProtocol(
|
|
|
186
190
|
}
|
|
187
191
|
}
|
|
188
192
|
}
|
|
193
|
+
/**
|
|
194
|
+
* Split bodies up to this size are reassembled for scalar projection. Larger ones
|
|
195
|
+
* stay complete in raw segments; projection does not allocate them in a 64 MiB
|
|
196
|
+
* Convex action.
|
|
197
|
+
*/
|
|
198
|
+
export const MAX_PROJECTED_SPLIT_BYTES = 8 * 1024 * 1024;
|
|
199
|
+
/**
|
|
200
|
+
* Earlier parts of a split body only advance the sequence. The final part needs
|
|
201
|
+
* the exact reassembled body (`BodyPartAssembler`) as `assembled`, or `null` when
|
|
202
|
+
* the body exceeds `MAX_PROJECTED_SPLIT_BYTES` and its semantics are not projected.
|
|
203
|
+
*/
|
|
189
204
|
export function applyObservation(
|
|
190
205
|
call: ModelCallV1,
|
|
191
206
|
state: ProjectionCheckpoint,
|
|
192
207
|
o: CaptureObservationV1,
|
|
208
|
+
assembled?: Uint8Array | null,
|
|
193
209
|
): void {
|
|
194
210
|
if (o.sequence !== call.capture.projectedThroughSequence + 1)
|
|
195
211
|
throw new Error("projection sequence gap");
|
|
@@ -204,7 +220,25 @@ export function applyObservation(
|
|
|
204
220
|
if (!call.capture.gaps.includes(o.gap) && call.capture.gaps.length < 8)
|
|
205
221
|
call.capture.gaps.push(o.gap.slice(0, 128));
|
|
206
222
|
}
|
|
207
|
-
const
|
|
223
|
+
const part = o.bodyPart;
|
|
224
|
+
// Segments validate only their own neighbors; continuity across them is checked here.
|
|
225
|
+
if (
|
|
226
|
+
(state.openBodyPart || (part && part.index > 0)) &&
|
|
227
|
+
!(state.openBodyPart && continuesBodyPart(state.openBodyPart, o))
|
|
228
|
+
)
|
|
229
|
+
throw new Error("body part interrupted");
|
|
230
|
+
const deferred = part !== undefined && part.index < part.count - 1;
|
|
231
|
+
state.openBodyPart = deferred
|
|
232
|
+
? { kind: o.kind, sequence: o.sequence, bodyPart: part }
|
|
233
|
+
: undefined;
|
|
234
|
+
if (part && !deferred && assembled === undefined)
|
|
235
|
+
throw new Error("split body requires reassembly");
|
|
236
|
+
const unprojected = part !== undefined && !deferred && assembled === null;
|
|
237
|
+
if (unprojected && part.totalBytes <= MAX_PROJECTED_SPLIT_BYTES)
|
|
238
|
+
throw new Error("split body within projection bound");
|
|
239
|
+
// Like an over-limit SSE frame: content is retained, its semantics are not decoded.
|
|
240
|
+
if (unprojected && o.kind !== "request") state.invalid = state.frameLimit = true;
|
|
241
|
+
const body = deferred || unprojected ? new Uint8Array() : (assembled ?? decodeBody(o));
|
|
208
242
|
const decoder = new TextDecoder("utf-8", { fatal: true });
|
|
209
243
|
// A new after-auth event replaces the selection, including unknown fields.
|
|
210
244
|
// Stream initialization may omit auth; an explicit selection replaces the pair.
|
|
@@ -227,14 +261,21 @@ export function applyObservation(
|
|
|
227
261
|
call.correlationConflicts = o.correlationConflicts ?? [];
|
|
228
262
|
call.traceId = o.correlation?.traceId;
|
|
229
263
|
call.sourceTraceId = o.sourceTraceId;
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
264
|
+
if (!deferred && !unprojected) {
|
|
265
|
+
try {
|
|
266
|
+
const input = parseObject(decoder.decode(body));
|
|
267
|
+
state.streamed = input.stream === true;
|
|
268
|
+
call.streamed = state.streamed;
|
|
269
|
+
} catch {
|
|
270
|
+
state.invalid = true;
|
|
271
|
+
}
|
|
236
272
|
}
|
|
237
273
|
}
|
|
274
|
+
// An unparsed request (e.g. a split body over the projection bound) takes
|
|
275
|
+
// streaming from the protocol evidence that follows it.
|
|
276
|
+
if (call.streamed === undefined && (o.kind === "stream_init" || o.kind === "stream_chunk"))
|
|
277
|
+
call.streamed = true;
|
|
278
|
+
else if (call.streamed === undefined && o.kind === "response") call.streamed = false;
|
|
238
279
|
// Derived read fields: reads fill them only for summaries projected before 0.3.0.
|
|
239
280
|
Object.assign(call, providerIdentity(call), { costProvenance: call.cost.kind });
|
|
240
281
|
if (o.kind === "response" || o.kind === "stream_chunk" || o.kind === "completion") {
|
|
@@ -251,10 +292,7 @@ export function applyObservation(
|
|
|
251
292
|
}
|
|
252
293
|
if ((o.kind === "stream_chunk" || o.kind === "completion") && body.length) {
|
|
253
294
|
const reader = new SSEReader(state.sse);
|
|
254
|
-
const pieces =
|
|
255
|
-
o.bodyFraming === "stock_hook_block"
|
|
256
|
-
? expandStockHookBlock(body, o.stockHookChunkLengths ?? [])
|
|
257
|
-
: [body];
|
|
295
|
+
const pieces = o.bodyFraming === "stock_hook_block" ? stockHookPieces(o, body) : [body];
|
|
258
296
|
const frames = pieces.flatMap((piece) =>
|
|
259
297
|
o.bodyFraming === "stock_hook_chunk" || o.bodyFraming === "stock_hook_block"
|
|
260
298
|
? reader.feedStock(piece, call.clientProtocol, o.observedAt)
|
package/src/protocols/index.ts
CHANGED