assistant-stream 0.3.25 → 0.3.27
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 +4 -1
- package/dist/core/AssistantStream.d.ts +0 -1
- package/dist/core/AssistantStream.d.ts.map +1 -1
- package/dist/core/AssistantStreamChunk.d.ts +26 -14
- package/dist/core/AssistantStreamChunk.d.ts.map +1 -1
- package/dist/core/accumulators/AssistantMessageStream.d.ts +0 -1
- package/dist/core/accumulators/AssistantMessageStream.d.ts.map +1 -1
- package/dist/core/accumulators/TimingTracker.d.ts +0 -1
- package/dist/core/accumulators/TimingTracker.d.ts.map +1 -1
- package/dist/core/accumulators/assistant-message-accumulator.d.ts +3 -9
- package/dist/core/accumulators/assistant-message-accumulator.d.ts.map +1 -1
- package/dist/core/accumulators/assistant-message-accumulator.js +70 -28
- package/dist/core/accumulators/assistant-message-accumulator.js.map +1 -1
- package/dist/core/converters/toGenericMessages.d.ts.map +1 -1
- package/dist/core/converters/toGenericMessages.js +2 -1
- package/dist/core/converters/toGenericMessages.js.map +1 -1
- package/dist/core/gorp/GorpStreamAccumulator.d.ts +15 -0
- package/dist/core/gorp/GorpStreamAccumulator.d.ts.map +1 -0
- package/dist/core/{object/ObjectStreamAccumulator.js → gorp/GorpStreamAccumulator.js} +11 -9
- package/dist/core/gorp/GorpStreamAccumulator.js.map +1 -0
- package/dist/core/gorp/GorpStreamDeltaTracker.d.ts +17 -0
- package/dist/core/gorp/GorpStreamDeltaTracker.d.ts.map +1 -0
- package/dist/core/gorp/GorpStreamDeltaTracker.js +38 -0
- package/dist/core/gorp/GorpStreamDeltaTracker.js.map +1 -0
- package/dist/core/gorp/GorpStreamResponse.d.ts +16 -0
- package/dist/core/gorp/GorpStreamResponse.d.ts.map +1 -0
- package/dist/core/gorp/GorpStreamResponse.js +51 -0
- package/dist/core/gorp/GorpStreamResponse.js.map +1 -0
- package/dist/core/gorp/changeTree.d.ts +16 -0
- package/dist/core/gorp/changeTree.d.ts.map +1 -0
- package/dist/core/gorp/changeTree.js +77 -0
- package/dist/core/gorp/changeTree.js.map +1 -0
- package/dist/core/gorp/createGorpStream.d.ts +16 -0
- package/dist/core/gorp/createGorpStream.d.ts.map +1 -0
- package/dist/core/{object/createObjectStream.js → gorp/createGorpStream.js} +13 -8
- package/dist/core/gorp/createGorpStream.js.map +1 -0
- package/dist/core/gorp/types.d.ts +20 -0
- package/dist/core/gorp/types.d.ts.map +1 -0
- package/dist/core/modules/assistant-stream.d.ts +18 -11
- package/dist/core/modules/assistant-stream.d.ts.map +1 -1
- package/dist/core/modules/assistant-stream.js +10 -6
- package/dist/core/modules/assistant-stream.js.map +1 -1
- package/dist/core/modules/text.d.ts +0 -1
- package/dist/core/modules/text.d.ts.map +1 -1
- package/dist/core/modules/tool-call.d.ts +0 -1
- package/dist/core/modules/tool-call.d.ts.map +1 -1
- package/dist/core/modules/tool-call.js +2 -2
- package/dist/core/modules/tool-call.js.map +1 -1
- package/dist/core/serialization/PlainText.d.ts +0 -1
- package/dist/core/serialization/PlainText.d.ts.map +1 -1
- package/dist/core/serialization/assistant-transport/AssistantTransport.d.ts +0 -1
- package/dist/core/serialization/assistant-transport/AssistantTransport.d.ts.map +1 -1
- package/dist/core/serialization/assistant-transport/AssistantTransport.js +93 -53
- package/dist/core/serialization/assistant-transport/AssistantTransport.js.map +1 -1
- package/dist/core/serialization/data-stream/DataStream.d.ts +0 -1
- package/dist/core/serialization/data-stream/DataStream.d.ts.map +1 -1
- package/dist/core/serialization/data-stream/chunk-types.d.ts +3 -4
- package/dist/core/serialization/data-stream/chunk-types.d.ts.map +1 -1
- package/dist/core/serialization/data-stream/chunk-types.js.map +1 -1
- package/dist/core/serialization/data-stream/serialization.d.ts +0 -1
- package/dist/core/serialization/data-stream/serialization.d.ts.map +1 -1
- package/dist/core/serialization/ui-message-stream/UIMessageStream.d.ts +0 -1
- package/dist/core/serialization/ui-message-stream/UIMessageStream.d.ts.map +1 -1
- package/dist/core/serialization/ui-message-stream/UIMessageStream.js +76 -53
- package/dist/core/serialization/ui-message-stream/UIMessageStream.js.map +1 -1
- package/dist/core/serialization/ui-message-stream/chunk-types.d.ts +0 -1
- package/dist/core/serialization/ui-message-stream/chunk-types.d.ts.map +1 -1
- package/dist/core/tool/ToolCallReader.d.ts +1 -0
- package/dist/core/tool/ToolCallReader.d.ts.map +1 -1
- package/dist/core/tool/ToolCallReader.js.map +1 -1
- package/dist/core/tool/ToolExecutionStream.d.ts +0 -1
- package/dist/core/tool/ToolExecutionStream.d.ts.map +1 -1
- package/dist/core/tool/ToolExecutionStream.js +9 -1
- package/dist/core/tool/ToolExecutionStream.js.map +1 -1
- package/dist/core/tool/ToolResponse.d.ts +6 -4
- package/dist/core/tool/ToolResponse.d.ts.map +1 -1
- package/dist/core/tool/schema-utils.d.ts +0 -1
- package/dist/core/tool/schema-utils.d.ts.map +1 -1
- package/dist/core/tool/tool-types.d.ts +71 -33
- package/dist/core/tool/tool-types.d.ts.map +1 -1
- package/dist/core/tool/toolResultStream.d.ts +3 -2
- package/dist/core/tool/toolResultStream.d.ts.map +1 -1
- package/dist/core/tool/toolResultStream.js +7 -2
- package/dist/core/tool/toolResultStream.js.map +1 -1
- package/dist/core/tool/type-path-utils.d.ts +2 -2
- package/dist/core/tool/type-path-utils.d.ts.map +1 -1
- package/dist/core/utils/Counter.d.ts.map +1 -1
- package/dist/core/utils/generateId.d.ts.map +1 -1
- package/dist/core/utils/stream/AssistantMetaTransformStream.d.ts +0 -1
- package/dist/core/utils/stream/AssistantMetaTransformStream.d.ts.map +1 -1
- package/dist/core/utils/stream/AssistantTransformStream.d.ts +0 -1
- package/dist/core/utils/stream/AssistantTransformStream.d.ts.map +1 -1
- package/dist/core/utils/stream/LineDecoderStream.d.ts +1 -0
- package/dist/core/utils/stream/LineDecoderStream.d.ts.map +1 -1
- package/dist/core/utils/stream/LineDecoderStream.js +19 -6
- package/dist/core/utils/stream/LineDecoderStream.js.map +1 -1
- package/dist/core/utils/stream/PipeableTransformStream.d.ts.map +1 -1
- package/dist/core/utils/stream/SSE.d.ts +0 -1
- package/dist/core/utils/stream/SSE.d.ts.map +1 -1
- package/dist/core/utils/stream/SSE.js +2 -52
- package/dist/core/utils/stream/SSE.js.map +1 -1
- package/dist/core/utils/stream/SSEEventDecoder.d.ts +27 -0
- package/dist/core/utils/stream/SSEEventDecoder.d.ts.map +1 -0
- package/dist/core/utils/stream/SSEEventDecoder.js +84 -0
- package/dist/core/utils/stream/SSEEventDecoder.js.map +1 -0
- package/dist/core/utils/stream/SSEEventDecoderStream.d.ts +13 -0
- package/dist/core/utils/stream/SSEEventDecoderStream.d.ts.map +1 -0
- package/dist/core/utils/stream/SSEEventDecoderStream.js +24 -0
- package/dist/core/utils/stream/SSEEventDecoderStream.js.map +1 -0
- package/dist/core/utils/stream/UnderlyingReadable.d.ts.map +1 -1
- package/dist/core/utils/stream/merge.d.ts +2 -1
- package/dist/core/utils/stream/merge.d.ts.map +1 -1
- package/dist/core/utils/stream/merge.js +27 -8
- package/dist/core/utils/stream/merge.js.map +1 -1
- package/dist/core/utils/stream/path-utils.d.ts +0 -1
- package/dist/core/utils/stream/path-utils.d.ts.map +1 -1
- package/dist/core/utils/types.d.ts +16 -8
- package/dist/core/utils/types.d.ts.map +1 -1
- package/dist/core/utils/withPromiseOrValue.d.ts.map +1 -1
- package/dist/index.d.ts +25 -4
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +14 -3
- package/dist/index.js.map +1 -0
- package/dist/node_modules/.pnpm/@types_json-schema@7.0.15/node_modules/@types/json-schema/index.d.ts +3 -3
- package/dist/node_modules/.pnpm/@types_json-schema@7.0.15/node_modules/@types/json-schema/index.d.ts.map +1 -1
- package/dist/resumable/ResumableStreamContext.d.ts +0 -1
- package/dist/resumable/ResumableStreamContext.d.ts.map +1 -1
- package/dist/resumable/ResumableStreamContext.js +12 -5
- package/dist/resumable/ResumableStreamContext.js.map +1 -1
- package/dist/resumable/constants.d.ts.map +1 -1
- package/dist/resumable/createResumableAssistantStreamResponse.d.ts +6 -4
- package/dist/resumable/createResumableAssistantStreamResponse.d.ts.map +1 -1
- package/dist/resumable/errors.d.ts.map +1 -1
- package/dist/resumable/stores/InMemoryResumableStreamStore.d.ts +0 -1
- package/dist/resumable/stores/InMemoryResumableStreamStore.d.ts.map +1 -1
- package/dist/resumable/stores/InMemoryResumableStreamStore.js +2 -1
- package/dist/resumable/stores/InMemoryResumableStreamStore.js.map +1 -1
- package/dist/resumable/stores/ioredis.d.ts +0 -1
- package/dist/resumable/stores/ioredis.d.ts.map +1 -1
- package/dist/resumable/stores/redis-impl.d.ts +2 -2
- package/dist/resumable/stores/redis-impl.d.ts.map +1 -1
- package/dist/resumable/stores/redis.d.ts +0 -1
- package/dist/resumable/stores/redis.d.ts.map +1 -1
- package/dist/resumable/types.d.ts.map +1 -1
- package/dist/utils/AsyncIterableStream.d.ts.map +1 -1
- package/dist/utils/AsyncIterableStream.js +18 -3
- package/dist/utils/AsyncIterableStream.js.map +1 -1
- package/dist/utils/json/fix-json.d.ts.map +1 -1
- package/dist/utils/json/json-value.d.ts.map +1 -1
- package/dist/utils/json/parse-partial-json-object.d.ts +0 -1
- package/dist/utils/json/parse-partial-json-object.d.ts.map +1 -1
- package/dist/utils/promiseWithResolvers.d.ts.map +1 -1
- package/dist/utils.d.ts +2 -1
- package/dist/utils.js +2 -1
- package/package.json +5 -5
- package/src/core/AssistantStreamChunk.ts +5 -3
- package/src/core/accumulators/assistant-message-accumulator.test.ts +437 -1
- package/src/core/accumulators/assistant-message-accumulator.ts +89 -26
- package/src/core/{object/ObjectStream.test.ts → gorp/GorpStream.test.ts} +104 -23
- package/src/core/gorp/GorpStreamAccumulator.test.ts +28 -0
- package/src/core/{object/ObjectStreamAccumulator.ts → gorp/GorpStreamAccumulator.ts} +13 -15
- package/src/core/gorp/GorpStreamDeltaTracker.test.ts +182 -0
- package/src/core/gorp/GorpStreamDeltaTracker.ts +55 -0
- package/src/core/gorp/GorpStreamResponse.test.ts +32 -0
- package/src/core/gorp/GorpStreamResponse.ts +88 -0
- package/src/core/gorp/changeTree.test.ts +168 -0
- package/src/core/gorp/changeTree.ts +96 -0
- package/src/core/{object/createObjectStream.ts → gorp/createGorpStream.ts} +23 -17
- package/src/core/{object → gorp}/types.ts +5 -3
- package/src/core/modules/assistant-stream.test.ts +154 -2
- package/src/core/modules/assistant-stream.ts +16 -6
- package/src/core/modules/tool-call.test.ts +67 -0
- package/src/core/modules/tool-call.ts +3 -3
- package/src/core/serialization/assistant-transport/AssistantTransport.test.ts +215 -1
- package/src/core/serialization/assistant-transport/AssistantTransport.ts +83 -71
- package/src/core/serialization/data-stream/chunk-types.ts +2 -2
- package/src/core/serialization/ui-message-stream/UIMessageStream.test.ts +323 -4
- package/src/core/serialization/ui-message-stream/UIMessageStream.ts +81 -71
- package/src/core/tool/ToolExecutionStream.ts +10 -0
- package/src/core/tool/toolResultStream.test.ts +50 -0
- package/src/core/tool/toolResultStream.ts +7 -2
- package/src/core/utils/stream/LineDecoderStream.test.ts +26 -2
- package/src/core/utils/stream/LineDecoderStream.ts +21 -11
- package/src/core/utils/stream/SSE.ts +6 -70
- package/src/core/utils/stream/SSEEventDecoder.test.ts +146 -0
- package/src/core/utils/stream/SSEEventDecoder.ts +109 -0
- package/src/core/utils/stream/SSEEventDecoderStream.test.ts +42 -0
- package/src/core/utils/stream/SSEEventDecoderStream.ts +34 -0
- package/src/core/utils/stream/merge.ts +31 -9
- package/src/gorp.test.ts +42 -0
- package/src/index.ts +21 -6
- package/src/resumable/ResumableStreamContext.test.ts +116 -1
- package/src/resumable/ResumableStreamContext.ts +32 -5
- package/src/resumable/createResumableAssistantStreamResponse.test.ts +1 -25
- package/src/utils/AsyncIterableStream.test.ts +61 -0
- package/src/utils/AsyncIterableStream.ts +18 -3
- package/src/utils.ts +4 -0
- package/dist/core/object/ObjectStreamAccumulator.d.ts +0 -15
- package/dist/core/object/ObjectStreamAccumulator.d.ts.map +0 -1
- package/dist/core/object/ObjectStreamAccumulator.js.map +0 -1
- package/dist/core/object/ObjectStreamResponse.d.ts +0 -17
- package/dist/core/object/ObjectStreamResponse.d.ts.map +0 -1
- package/dist/core/object/ObjectStreamResponse.js +0 -57
- package/dist/core/object/ObjectStreamResponse.js.map +0 -1
- package/dist/core/object/createObjectStream.d.ts +0 -19
- package/dist/core/object/createObjectStream.d.ts.map +0 -1
- package/dist/core/object/createObjectStream.js.map +0 -1
- package/dist/core/object/types.d.ts +0 -18
- package/dist/core/object/types.d.ts.map +0 -1
- package/dist/utils/json/is-json.d.ts +0 -9
- package/dist/utils/json/is-json.d.ts.map +0 -1
- package/dist/utils/json/is-json.js +0 -17
- package/dist/utils/json/is-json.js.map +0 -1
- package/src/core/object/ObjectStreamResponse.ts +0 -109
- package/src/utils/json/is-json.ts +0 -43
- /package/dist/core/{object → gorp}/types.js +0 -0
|
@@ -1,22 +1,24 @@
|
|
|
1
1
|
import { AssistantStreamController } from "../core/modules/assistant-stream.js";
|
|
2
2
|
import { AssistantStreamEncoder } from "../core/AssistantStream.js";
|
|
3
3
|
import { ResumableStreamContext } from "./ResumableStreamContext.js";
|
|
4
|
-
|
|
5
4
|
//#region src/resumable/createResumableAssistantStreamResponse.d.ts
|
|
6
5
|
declare const RESUMABLE_STREAM_ID_HEADER = "x-resumable-stream-id";
|
|
7
6
|
type CreateResumableAssistantStreamResponseOptions = {
|
|
8
7
|
readonly context: ResumableStreamContext;
|
|
9
8
|
readonly streamId: string;
|
|
10
|
-
readonly callback: (controller: AssistantStreamController) => PromiseLike<void> | void;
|
|
9
|
+
readonly callback: (controller: AssistantStreamController) => PromiseLike<void> | void;
|
|
10
|
+
/** Defaults to `DataStreamEncoder`. Also consulted for response headers. */
|
|
11
11
|
readonly encoder?: () => AssistantStreamEncoder;
|
|
12
12
|
readonly headers?: HeadersInit;
|
|
13
13
|
};
|
|
14
14
|
declare function createResumableAssistantStreamResponse(options: CreateResumableAssistantStreamResponseOptions): Promise<Response>;
|
|
15
15
|
type CreateResumeAssistantStreamResponseOptions = {
|
|
16
16
|
readonly context: ResumableStreamContext;
|
|
17
|
-
readonly streamId: string;
|
|
17
|
+
readonly streamId: string;
|
|
18
|
+
/** Read for `headers` only; the encoder transform is not invoked on resume. */
|
|
18
19
|
readonly encoder?: () => AssistantStreamEncoder;
|
|
19
|
-
readonly headers?: HeadersInit;
|
|
20
|
+
readonly headers?: HeadersInit;
|
|
21
|
+
/** Defaults to a 404 JSON response. */
|
|
20
22
|
readonly missingResponse?: () => Response;
|
|
21
23
|
};
|
|
22
24
|
declare function createResumeAssistantStreamResponse(options: CreateResumeAssistantStreamResponseOptions): Promise<Response>;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"createResumableAssistantStreamResponse.d.ts","names":[],"sources":["../../src/resumable/createResumableAssistantStreamResponse.ts"],"mappings":"
|
|
1
|
+
{"version":3,"file":"createResumableAssistantStreamResponse.d.ts","names":[],"sources":["../../src/resumable/createResumableAssistantStreamResponse.ts"],"mappings":";;;;cAQa;KAED;WACD,SAAS;WACT;WACA,WACP,YAAY,8BACT;;WAEI,gBAAgB;WAChB,UAAU;;iBAGC,uCACpB,SAAS,gDACR,QAAQ;KAaC;WACD,SAAS;WACT;;WAEA,gBAAgB;WAChB,UAAU;;WAEV,wBAAwB;;iBAGb,oCACpB,SAAS,6CACR,QAAQ"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"errors.d.ts","names":[],"sources":["../../src/resumable/errors.ts"],"mappings":";KAAY
|
|
1
|
+
{"version":3,"file":"errors.d.ts","names":[],"sources":["../../src/resumable/errors.ts"],"mappings":";KAAY;cAMC,6BAA6B;WAC/B,MAAM;EAEH,YAAA,MAAM,0BAA0B;;iBAS9B,iBAAiB"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"InMemoryResumableStreamStore.d.ts","names":[],"sources":["../../../src/resumable/stores/InMemoryResumableStreamStore.ts"],"mappings":"
|
|
1
|
+
{"version":3,"file":"InMemoryResumableStreamStore.d.ts","names":[],"sources":["../../../src/resumable/stores/InMemoryResumableStreamStore.ts"],"mappings":";;KA0BY;WACD;WACA;WACA;WACA;WACA;WACA;;iBAGK,mCACd,UAAS,sCACR;EAAyB"}
|
|
@@ -134,7 +134,8 @@ function createInMemoryResumableStreamStore(options = {}) {
|
|
|
134
134
|
if (state.final.kind === "error") throw new Error(state.final.error);
|
|
135
135
|
return;
|
|
136
136
|
}
|
|
137
|
-
|
|
137
|
+
const wakeBy = state.expiresAt - now();
|
|
138
|
+
await waitForUpdate(state, signal, wakeBy);
|
|
138
139
|
evictExpired();
|
|
139
140
|
}
|
|
140
141
|
},
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"InMemoryResumableStreamStore.js","names":[],"sources":["../../../src/resumable/stores/InMemoryResumableStreamStore.ts"],"sourcesContent":["import { DEFAULT_TTL_MS } from \"../constants\";\nimport { ResumableStreamError, validateStreamId } from \"../errors\";\nimport type {\n ResumableStreamEntry,\n ResumableStreamStatus,\n ResumableStreamStore,\n} from \"../types\";\n\ntype FinalizeMarker = { kind: \"done\" } | { kind: \"error\"; error: string };\n\ntype StreamState = {\n entries: ResumableStreamEntry[];\n nextSeq: number;\n expiresAt: number;\n ttlMs: number;\n final: FinalizeMarker | undefined;\n waiters: Array<() => void>;\n};\n\nconst cursorOf = (seq: number): string => seq.toString(36);\nconst seqFromCursor = (cursor: string): number => {\n if (cursor === \"\") return 0;\n const parsed = Number.parseInt(cursor, 36);\n return Number.isNaN(parsed) ? 0 : parsed;\n};\n\nexport type InMemoryResumableStreamStoreOptions = {\n readonly defaultTtlMs?: number;\n readonly now?: () => number;\n readonly maxChunkBytes?: number;\n readonly maxEntriesPerStream?: number;\n readonly maxStreams?: number;\n readonly gcIntervalMs?: number;\n};\n\nexport function createInMemoryResumableStreamStore(\n options: InMemoryResumableStreamStoreOptions = {},\n): ResumableStreamStore & { dispose: () => void } {\n const streams = new Map<string, StreamState>();\n const defaultTtlMs = options.defaultTtlMs ?? DEFAULT_TTL_MS;\n const now = options.now ?? Date.now;\n const maxChunkBytes = options.maxChunkBytes;\n const maxEntriesPerStream = options.maxEntriesPerStream;\n const maxStreams = options.maxStreams;\n\n const evictExpired = (): void => {\n const t = now();\n for (const [id, state] of streams) {\n if (state.expiresAt > t) continue;\n streams.delete(id);\n state.final ??= { kind: \"error\", error: \"Stream expired\" };\n notify(state);\n }\n };\n\n const notify = (state: StreamState): void => {\n const waiters = state.waiters;\n state.waiters = [];\n for (const wake of waiters) wake();\n };\n\n const findStartIndex = (state: StreamState, cursor: string): number => {\n if (cursor === \"\") return 0;\n const after = seqFromCursor(cursor);\n let lo = 0;\n let hi = state.entries.length;\n while (lo < hi) {\n const mid = (lo + hi) >>> 1;\n const seq = seqFromCursor(state.entries[mid]!.cursor);\n if (seq <= after) lo = mid + 1;\n else hi = mid;\n }\n return lo;\n };\n\n const waitForUpdate = (\n state: StreamState,\n signal: AbortSignal,\n wakeBy?: number,\n ): Promise<void> =>\n new Promise<void>((resolve) => {\n let settled = false;\n let timer: ReturnType<typeof setTimeout> | undefined;\n const wake = () => {\n if (settled) return;\n settled = true;\n if (timer !== undefined) clearTimeout(timer);\n signal.removeEventListener(\"abort\", wake);\n const idx = state.waiters.indexOf(wake);\n if (idx !== -1) state.waiters.splice(idx, 1);\n resolve();\n };\n if (signal.aborted) {\n wake();\n return;\n }\n state.waiters.push(wake);\n signal.addEventListener(\"abort\", wake, { once: true });\n if (wakeBy !== undefined) {\n if (wakeBy > 0) {\n timer = setTimeout(wake, wakeBy);\n } else {\n // already past the deadline; resolve so the caller can re-check\n // expiration without waiting for an external notify.\n wake();\n }\n }\n });\n\n const requireActive = (streamId: string): StreamState => {\n evictExpired();\n const state = streams.get(streamId);\n if (!state) throw new Error(`Stream not found: ${streamId}`);\n if (state.final) {\n throw new ResumableStreamError(\n \"finalized\",\n `Stream already finalized: ${streamId}`,\n );\n }\n return state;\n };\n\n const gcTimer =\n options.gcIntervalMs !== undefined\n ? setInterval(evictExpired, options.gcIntervalMs)\n : undefined;\n gcTimer?.unref?.();\n\n return {\n async acquire(streamId, acquireOptions) {\n validateStreamId(streamId);\n evictExpired();\n const existing = streams.get(streamId);\n if (existing) return \"consumer\";\n\n if (maxStreams !== undefined && streams.size >= maxStreams) {\n throw new Error(\"maxStreams exceeded\");\n }\n\n const ttlMs = acquireOptions?.ttlMs ?? defaultTtlMs;\n streams.set(streamId, {\n entries: [],\n nextSeq: 1,\n expiresAt: now() + ttlMs,\n ttlMs,\n final: undefined,\n waiters: [],\n });\n return \"producer\";\n },\n\n async append(streamId, chunk) {\n validateStreamId(streamId);\n if (maxChunkBytes !== undefined && chunk.byteLength > maxChunkBytes) {\n throw new Error(`Chunk exceeds maxChunkBytes: ${chunk.byteLength}`);\n }\n const state = requireActive(streamId);\n if (\n maxEntriesPerStream !== undefined &&\n state.entries.length >= maxEntriesPerStream\n ) {\n throw new Error(`Stream exceeded maxEntriesPerStream: ${streamId}`);\n }\n const seq = state.nextSeq;\n state.nextSeq += 1;\n state.entries.push({ cursor: cursorOf(seq), chunk });\n state.expiresAt = now() + state.ttlMs;\n notify(state);\n },\n\n async finalize(streamId, status, error) {\n validateStreamId(streamId);\n evictExpired();\n const state = streams.get(streamId);\n if (!state) throw new Error(`Stream not found: ${streamId}`);\n if (state.final) return;\n state.final =\n status === \"done\"\n ? { kind: \"done\" }\n : { kind: \"error\", error: error ?? \"Stream errored\" };\n state.expiresAt = now() + state.ttlMs;\n notify(state);\n },\n\n async *read(streamId, cursor, signal) {\n validateStreamId(streamId);\n evictExpired();\n const state = streams.get(streamId);\n if (!state) throw new Error(`Stream not found: ${streamId}`);\n\n let idx = findStartIndex(state, cursor);\n\n while (true) {\n if (signal.aborted) return;\n\n while (idx < state.entries.length) {\n if (signal.aborted) return;\n yield state.entries[idx]!;\n idx += 1;\n }\n\n if (state.final) {\n if (state.final.kind === \"error\") {\n throw new Error(state.final.error);\n }\n return;\n }\n\n const wakeBy = state.expiresAt - now();\n await waitForUpdate(state, signal, wakeBy);\n evictExpired();\n }\n },\n\n async status(streamId): Promise<ResumableStreamStatus> {\n validateStreamId(streamId);\n evictExpired();\n const state = streams.get(streamId);\n if (!state) return \"missing\";\n if (!state.final) return \"streaming\";\n return state.final.kind === \"error\" ? \"error\" : \"done\";\n },\n\n async delete(streamId) {\n validateStreamId(streamId);\n const state = streams.get(streamId);\n if (!state) return;\n streams.delete(streamId);\n state.final ??= { kind: \"done\" };\n notify(state);\n },\n\n dispose() {\n if (gcTimer !== undefined) clearInterval(gcTimer);\n },\n };\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"InMemoryResumableStreamStore.js","names":[],"sources":["../../../src/resumable/stores/InMemoryResumableStreamStore.ts"],"sourcesContent":["import { DEFAULT_TTL_MS } from \"../constants\";\nimport { ResumableStreamError, validateStreamId } from \"../errors\";\nimport type {\n ResumableStreamEntry,\n ResumableStreamStatus,\n ResumableStreamStore,\n} from \"../types\";\n\ntype FinalizeMarker = { kind: \"done\" } | { kind: \"error\"; error: string };\n\ntype StreamState = {\n entries: ResumableStreamEntry[];\n nextSeq: number;\n expiresAt: number;\n ttlMs: number;\n final: FinalizeMarker | undefined;\n waiters: Array<() => void>;\n};\n\nconst cursorOf = (seq: number): string => seq.toString(36);\nconst seqFromCursor = (cursor: string): number => {\n if (cursor === \"\") return 0;\n const parsed = Number.parseInt(cursor, 36);\n return Number.isNaN(parsed) ? 0 : parsed;\n};\n\nexport type InMemoryResumableStreamStoreOptions = {\n readonly defaultTtlMs?: number;\n readonly now?: () => number;\n readonly maxChunkBytes?: number;\n readonly maxEntriesPerStream?: number;\n readonly maxStreams?: number;\n readonly gcIntervalMs?: number;\n};\n\nexport function createInMemoryResumableStreamStore(\n options: InMemoryResumableStreamStoreOptions = {},\n): ResumableStreamStore & { dispose: () => void } {\n const streams = new Map<string, StreamState>();\n const defaultTtlMs = options.defaultTtlMs ?? DEFAULT_TTL_MS;\n const now = options.now ?? Date.now;\n const maxChunkBytes = options.maxChunkBytes;\n const maxEntriesPerStream = options.maxEntriesPerStream;\n const maxStreams = options.maxStreams;\n\n const evictExpired = (): void => {\n const t = now();\n for (const [id, state] of streams) {\n if (state.expiresAt > t) continue;\n streams.delete(id);\n state.final ??= { kind: \"error\", error: \"Stream expired\" };\n notify(state);\n }\n };\n\n const notify = (state: StreamState): void => {\n const waiters = state.waiters;\n state.waiters = [];\n for (const wake of waiters) wake();\n };\n\n const findStartIndex = (state: StreamState, cursor: string): number => {\n if (cursor === \"\") return 0;\n const after = seqFromCursor(cursor);\n let lo = 0;\n let hi = state.entries.length;\n while (lo < hi) {\n const mid = (lo + hi) >>> 1;\n const seq = seqFromCursor(state.entries[mid]!.cursor);\n if (seq <= after) lo = mid + 1;\n else hi = mid;\n }\n return lo;\n };\n\n const waitForUpdate = (\n state: StreamState,\n signal: AbortSignal,\n wakeBy?: number,\n ): Promise<void> =>\n new Promise<void>((resolve) => {\n let settled = false;\n let timer: ReturnType<typeof setTimeout> | undefined;\n const wake = () => {\n if (settled) return;\n settled = true;\n if (timer !== undefined) clearTimeout(timer);\n signal.removeEventListener(\"abort\", wake);\n const idx = state.waiters.indexOf(wake);\n if (idx !== -1) state.waiters.splice(idx, 1);\n resolve();\n };\n if (signal.aborted) {\n wake();\n return;\n }\n state.waiters.push(wake);\n signal.addEventListener(\"abort\", wake, { once: true });\n if (wakeBy !== undefined) {\n if (wakeBy > 0) {\n timer = setTimeout(wake, wakeBy);\n } else {\n // already past the deadline; resolve so the caller can re-check\n // expiration without waiting for an external notify.\n wake();\n }\n }\n });\n\n const requireActive = (streamId: string): StreamState => {\n evictExpired();\n const state = streams.get(streamId);\n if (!state) throw new Error(`Stream not found: ${streamId}`);\n if (state.final) {\n throw new ResumableStreamError(\n \"finalized\",\n `Stream already finalized: ${streamId}`,\n );\n }\n return state;\n };\n\n const gcTimer =\n options.gcIntervalMs !== undefined\n ? setInterval(evictExpired, options.gcIntervalMs)\n : undefined;\n gcTimer?.unref?.();\n\n return {\n async acquire(streamId, acquireOptions) {\n validateStreamId(streamId);\n evictExpired();\n const existing = streams.get(streamId);\n if (existing) return \"consumer\";\n\n if (maxStreams !== undefined && streams.size >= maxStreams) {\n throw new Error(\"maxStreams exceeded\");\n }\n\n const ttlMs = acquireOptions?.ttlMs ?? defaultTtlMs;\n streams.set(streamId, {\n entries: [],\n nextSeq: 1,\n expiresAt: now() + ttlMs,\n ttlMs,\n final: undefined,\n waiters: [],\n });\n return \"producer\";\n },\n\n async append(streamId, chunk) {\n validateStreamId(streamId);\n if (maxChunkBytes !== undefined && chunk.byteLength > maxChunkBytes) {\n throw new Error(`Chunk exceeds maxChunkBytes: ${chunk.byteLength}`);\n }\n const state = requireActive(streamId);\n if (\n maxEntriesPerStream !== undefined &&\n state.entries.length >= maxEntriesPerStream\n ) {\n throw new Error(`Stream exceeded maxEntriesPerStream: ${streamId}`);\n }\n const seq = state.nextSeq;\n state.nextSeq += 1;\n state.entries.push({ cursor: cursorOf(seq), chunk });\n state.expiresAt = now() + state.ttlMs;\n notify(state);\n },\n\n async finalize(streamId, status, error) {\n validateStreamId(streamId);\n evictExpired();\n const state = streams.get(streamId);\n if (!state) throw new Error(`Stream not found: ${streamId}`);\n if (state.final) return;\n state.final =\n status === \"done\"\n ? { kind: \"done\" }\n : { kind: \"error\", error: error ?? \"Stream errored\" };\n state.expiresAt = now() + state.ttlMs;\n notify(state);\n },\n\n async *read(streamId, cursor, signal) {\n validateStreamId(streamId);\n evictExpired();\n const state = streams.get(streamId);\n if (!state) throw new Error(`Stream not found: ${streamId}`);\n\n let idx = findStartIndex(state, cursor);\n\n while (true) {\n if (signal.aborted) return;\n\n while (idx < state.entries.length) {\n if (signal.aborted) return;\n yield state.entries[idx]!;\n idx += 1;\n }\n\n if (state.final) {\n if (state.final.kind === \"error\") {\n throw new Error(state.final.error);\n }\n return;\n }\n\n const wakeBy = state.expiresAt - now();\n await waitForUpdate(state, signal, wakeBy);\n evictExpired();\n }\n },\n\n async status(streamId): Promise<ResumableStreamStatus> {\n validateStreamId(streamId);\n evictExpired();\n const state = streams.get(streamId);\n if (!state) return \"missing\";\n if (!state.final) return \"streaming\";\n return state.final.kind === \"error\" ? \"error\" : \"done\";\n },\n\n async delete(streamId) {\n validateStreamId(streamId);\n const state = streams.get(streamId);\n if (!state) return;\n streams.delete(streamId);\n state.final ??= { kind: \"done\" };\n notify(state);\n },\n\n dispose() {\n if (gcTimer !== undefined) clearInterval(gcTimer);\n },\n };\n}\n"],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ioredis.d.ts","names":[],"sources":["../../../src/resumable/stores/ioredis.ts"],"mappings":"
|
|
1
|
+
{"version":3,"file":"ioredis.d.ts","names":[],"sources":["../../../src/resumable/stores/ioredis.ts"],"mappings":";;;;KAaY,cAAc,QAAU;;;;;iBAMpB,kCACd,QAAQ,aACR,UAAU,mCACT"}
|
|
@@ -1,5 +1,4 @@
|
|
|
1
1
|
import { ResumableStreamAcquireOptions, ResumableStreamEntry, ResumableStreamRole, ResumableStreamStatus, ResumableStreamStore } from "../types.js";
|
|
2
|
-
|
|
3
2
|
//#region src/resumable/stores/redis-impl.d.ts
|
|
4
3
|
type PipelineCommand = {
|
|
5
4
|
readonly type: "xAdd";
|
|
@@ -37,7 +36,8 @@ interface RedisLikeClient {
|
|
|
37
36
|
}
|
|
38
37
|
type RedisResumableStreamStoreOptions = {
|
|
39
38
|
readonly keyPrefix?: string;
|
|
40
|
-
readonly defaultTtlMs?: number;
|
|
39
|
+
readonly defaultTtlMs?: number;
|
|
40
|
+
/** Defaults to 100ms. Lower values reduce read latency, raise traffic. */
|
|
41
41
|
readonly pollIntervalMs?: number;
|
|
42
42
|
readonly maxChunkBytes?: number;
|
|
43
43
|
};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"redis-impl.d.ts","names":[],"sources":["../../../src/resumable/stores/redis-impl.ts"],"mappings":"
|
|
1
|
+
{"version":3,"file":"redis-impl.d.ts","names":[],"sources":["../../../src/resumable/stores/redis-impl.ts"],"mappings":";;KAsBY;WAEG;WACA;WACA,QAAQ,wBAAwB;;WAEhC;WAAyB;WAAsB;;WAE/C;WACA;WACA;WACA;;;;;;;UAQE;EACf,MAAM,aAAa,eAAe,iBAAiB;EACnD,IAAI,aAAa,eAAe,iBAAiB;EACjD,IAAI,cAAc;EAClB,OAAO,aAAa,iBAAiB;EACrC,OAAO,cAAc;EACrB,IAAI,iBAAiB;EACrB,KACE,aACA,QAAQ,wBAAwB,cAC/B;EACH,OACE,aACA,eACA,cACC,QACD;IAAQ;IAAY,QAAQ,wBAAwB;;;EAGtD,SAAS,mBAAmB,oBAAoB;;KAGtC;WACD;WACA;;WAEA;WACA;;cAGE,qCAAqC;mBAC/B;mBACA;mBACA;mBACA;mBACA;EAGf,YAAA,QAAQ,iBACR,UAAS;EASL,QACJ,kBACA,UAAU,gCACT,QAAQ;EAiBL,OAAO,kBAAkB,OAAO,aAAa;EA8B7C,SACJ,kBACA,0BACA,iBACC;EA6BI,KACL,kBACA,gBACA,QAAQ,cACP,cAAc;EA2CX,OAAO,mBAAmB,QAAQ;EAWlC,OAAO,mBAAmB;UAKlB;UAQN;UAIA"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"redis.d.ts","names":[],"sources":["../../../src/resumable/stores/redis.ts"],"mappings":"
|
|
1
|
+
{"version":3,"file":"redis.d.ts","names":[],"sources":["../../../src/resumable/stores/redis.ts"],"mappings":";;;KAUK,kBAAkB,wBAAwB;UAErC;EACR,KAAK,aAAa,YAAY,QAAQ,kBAAkB;EACxD,OAAO,aAAa,kBAAkB;EACtC,IACE,aACA,eACA;IAAW;MACV;EACH,kBAAkB;EAClB,QAAQ;;;UAIO;EACf,IACE,aACA,eACA;IAAW;IAAU;MACpB;EACH,IACE,aACA,eACA;IAAW;MACV;EACH,IAAI,cAAc;EAClB,OAAO,aAAa,kBAAkB;EACtC,OAAO,cAAc;EACrB,IAAI,0BAA0B;EAC9B,KAAK,aAAa,YAAY,QAAQ,kBAAkB;EACxD,YAAY,aACV,MAAM,uBAAuB,SAC7B;IAAY,cAAc;MACzB,QAAQ;EACX,SAAS;;;;;;;iBAQK,gCACd,QAAQ,eACR,UAAU,mCACT"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"types.d.ts","names":[],"sources":["../../src/resumable/types.ts"],"mappings":";KAAY
|
|
1
|
+
{"version":3,"file":"types.d.ts","names":[],"sources":["../../src/resumable/types.ts"],"mappings":";KAAY;KAEA;KAEA;WACD;WACA,OAAO;;KAGN;WACD;;UAGM;;;;;;EAMf,QACE,kBACA,UAAU,gCACT,QAAQ;;EAGX,OAAO,kBAAkB,OAAO,aAAa;EAE7C,SACE,kBACA,0BACA,iBACC;;;;;;EAOH,KACE,kBACA,gBACA,QAAQ,cACP,cAAc;EAEjB,OAAO,mBAAmB,QAAQ;;EAGlC,OAAO,mBAAmB"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"AsyncIterableStream.d.ts","names":[],"sources":["../../src/utils/AsyncIterableStream.ts"],"mappings":";KAAY,
|
|
1
|
+
{"version":3,"file":"AsyncIterableStream.d.ts","names":[],"sources":["../../src/utils/AsyncIterableStream.ts"],"mappings":";KAAY,oBAAoB,KAAK,cAAc,KAAK,eAAe;iBAgCvD,sBAAsB,GACpC,QAAQ,eAAe,KACtB,oBAAoB"}
|
|
@@ -1,14 +1,29 @@
|
|
|
1
1
|
//#region src/utils/AsyncIterableStream.ts
|
|
2
2
|
async function* streamGeneratorPolyfill() {
|
|
3
3
|
const reader = this.getReader();
|
|
4
|
+
let shouldCancel = true;
|
|
4
5
|
try {
|
|
5
6
|
while (true) {
|
|
6
|
-
|
|
7
|
-
|
|
7
|
+
let result;
|
|
8
|
+
try {
|
|
9
|
+
result = await reader.read();
|
|
10
|
+
} catch (error) {
|
|
11
|
+
shouldCancel = false;
|
|
12
|
+
throw error;
|
|
13
|
+
}
|
|
14
|
+
if (result.done) {
|
|
15
|
+
shouldCancel = false;
|
|
16
|
+
break;
|
|
17
|
+
}
|
|
18
|
+
const { value } = result;
|
|
8
19
|
yield value;
|
|
9
20
|
}
|
|
10
21
|
} finally {
|
|
11
|
-
|
|
22
|
+
try {
|
|
23
|
+
if (shouldCancel) await reader.cancel();
|
|
24
|
+
} finally {
|
|
25
|
+
reader.releaseLock();
|
|
26
|
+
}
|
|
12
27
|
}
|
|
13
28
|
}
|
|
14
29
|
function asAsyncIterableStream(source) {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"AsyncIterableStream.js","names":[],"sources":["../../src/utils/AsyncIterableStream.ts"],"sourcesContent":["export type AsyncIterableStream<T> = AsyncIterable<T> & ReadableStream<T>;\n\nasync function* streamGeneratorPolyfill<T>(\n this: ReadableStream<T>,\n): AsyncGenerator<T, undefined, unknown> {\n const reader = this.getReader();\n try {\n while (true) {\n
|
|
1
|
+
{"version":3,"file":"AsyncIterableStream.js","names":[],"sources":["../../src/utils/AsyncIterableStream.ts"],"sourcesContent":["export type AsyncIterableStream<T> = AsyncIterable<T> & ReadableStream<T>;\n\nasync function* streamGeneratorPolyfill<T>(\n this: ReadableStream<T>,\n): AsyncGenerator<T, undefined, unknown> {\n const reader = this.getReader();\n let shouldCancel = true;\n try {\n while (true) {\n let result: ReadableStreamReadResult<T>;\n try {\n result = await reader.read();\n } catch (error) {\n shouldCancel = false;\n throw error;\n }\n if (result.done) {\n shouldCancel = false;\n break;\n }\n const { value } = result;\n yield value;\n }\n } finally {\n try {\n if (shouldCancel) await reader.cancel();\n } finally {\n reader.releaseLock();\n }\n }\n}\n\nexport function asAsyncIterableStream<T>(\n source: ReadableStream<T>,\n): AsyncIterableStream<T> {\n (source as AsyncIterableStream<T>)[Symbol.asyncIterator] ??=\n streamGeneratorPolyfill;\n return source as AsyncIterableStream<T>;\n}\n"],"mappings":";AAEA,gBAAgB,0BAEyB;CACvC,MAAM,SAAS,KAAK,UAAU;CAC9B,IAAI,eAAe;CACnB,IAAI;EACF,OAAO,MAAM;GACX,IAAI;GACJ,IAAI;IACF,SAAS,MAAM,OAAO,KAAK;GAC7B,SAAS,OAAO;IACd,eAAe;IACf,MAAM;GACR;GACA,IAAI,OAAO,MAAM;IACf,eAAe;IACf;GACF;GACA,MAAM,EAAE,UAAU;GAClB,MAAM;EACR;CACF,UAAU;EACR,IAAI;GACF,IAAI,cAAc,MAAM,OAAO,OAAO;EACxC,UAAU;GACR,OAAO,YAAY;EACrB;CACF;AACF;AAEA,SAAgB,sBACd,QACwB;CACxB,OAAmC,OAAO,mBACxC;CACF,OAAO;AACT"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"fix-json.d.ts","names":[],"sources":["../../../src/utils/json/fix-json.ts"],"mappings":";iBA+DgB,
|
|
1
|
+
{"version":3,"file":"fix-json.d.ts","names":[],"sources":["../../../src/utils/json/fix-json.ts"],"mappings":";iBA+DgB,QAAQ"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"json-value.d.ts","names":[],"sources":["../../../src/utils/json/json-value.ts"],"mappings":";KAAY,
|
|
1
|
+
{"version":3,"file":"json-value.d.ts","names":[],"sources":["../../../src/utils/json/json-value.ts"],"mappings":";KAAY,uDAKR,qBACA;KAEQ;YACA,cAAc;;KAGd,6BAA6B"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"parse-partial-json-object.d.ts","names":[],"sources":["../../../src/utils/json/parse-partial-json-object.ts"],"mappings":"
|
|
1
|
+
{"version":3,"file":"parse-partial-json-object.d.ts","names":[],"sources":["../../../src/utils/json/parse-partial-json-object.ts"],"mappings":";;cAIM;KAID;KAEA;EACH;EACA;;cAGW,2BACX,KAAK,4BACJ;cAIU,yBACX,kBAEG;GACE,kCAAkC;;cAqE5B,iCACX,KAAK,yBACL,mCACC"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"promiseWithResolvers.d.ts","names":[],"sources":["../../src/utils/promiseWithResolvers.ts"],"mappings":";cAAa,
|
|
1
|
+
{"version":3,"file":"promiseWithResolvers.d.ts","names":[],"sources":["../../src/utils/promiseWithResolvers.ts"],"mappings":";cAAa,uBAAwB;;EACb,UAAA,OAAA,IAAI,YAAY;EACf,SAAA"}
|
package/dist/utils.d.ts
CHANGED
|
@@ -3,4 +3,5 @@ import { getPartialJsonObjectFieldState, getPartialJsonObjectMeta, parsePartialJ
|
|
|
3
3
|
import { AsyncIterableStream, asAsyncIterableStream } from "./utils/AsyncIterableStream.js";
|
|
4
4
|
import { AssistantTransformStream } from "./core/utils/stream/AssistantTransformStream.js";
|
|
5
5
|
import { AssistantMetaTransformStream } from "./core/utils/stream/AssistantMetaTransformStream.js";
|
|
6
|
-
|
|
6
|
+
import { SSEEvent, SSEEventDecoder } from "./core/utils/stream/SSEEventDecoder.js";
|
|
7
|
+
export { AssistantMetaTransformStream, AssistantTransformStream, type AsyncIterableStream, type ReadonlyJSONArray, type ReadonlyJSONObject, type ReadonlyJSONValue, type SSEEvent, SSEEventDecoder, asAsyncIterableStream, getPartialJsonObjectFieldState, getPartialJsonObjectMeta, parsePartialJsonObject };
|
package/dist/utils.js
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { AssistantTransformStream } from "./core/utils/stream/AssistantTransformStream.js";
|
|
2
2
|
import { AssistantMetaTransformStream } from "./core/utils/stream/AssistantMetaTransformStream.js";
|
|
3
3
|
import { getPartialJsonObjectFieldState, getPartialJsonObjectMeta, parsePartialJsonObject } from "./utils/json/parse-partial-json-object.js";
|
|
4
|
+
import { SSEEventDecoder } from "./core/utils/stream/SSEEventDecoder.js";
|
|
4
5
|
import { asAsyncIterableStream } from "./utils/AsyncIterableStream.js";
|
|
5
|
-
export { AssistantMetaTransformStream, AssistantTransformStream, asAsyncIterableStream, getPartialJsonObjectFieldState, getPartialJsonObjectMeta, parsePartialJsonObject };
|
|
6
|
+
export { AssistantMetaTransformStream, AssistantTransformStream, SSEEventDecoder, asAsyncIterableStream, getPartialJsonObjectFieldState, getPartialJsonObjectMeta, parsePartialJsonObject };
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "assistant-stream",
|
|
3
|
-
"version": "0.3.
|
|
3
|
+
"version": "0.3.27",
|
|
4
4
|
"description": "Streaming utilities for AI assistants",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"ai",
|
|
@@ -47,7 +47,7 @@
|
|
|
47
47
|
"sideEffects": false,
|
|
48
48
|
"dependencies": {
|
|
49
49
|
"@standard-schema/spec": "^1.1.0",
|
|
50
|
-
"nanoid": "^
|
|
50
|
+
"nanoid": "^6.0.0",
|
|
51
51
|
"secure-json-parse": "^4.1.0"
|
|
52
52
|
},
|
|
53
53
|
"peerDependencies": {
|
|
@@ -65,9 +65,9 @@
|
|
|
65
65
|
"devDependencies": {
|
|
66
66
|
"@types/json-schema": "^7.0.15",
|
|
67
67
|
"ioredis": "^5.11.1",
|
|
68
|
-
"redis": "^6.
|
|
69
|
-
"vitest": "^4.1.
|
|
70
|
-
"@assistant-ui/x-buildutils": "0.0.
|
|
68
|
+
"redis": "^6.1.0",
|
|
69
|
+
"vitest": "^4.1.10",
|
|
70
|
+
"@assistant-ui/x-buildutils": "0.0.19"
|
|
71
71
|
},
|
|
72
72
|
"publishConfig": {
|
|
73
73
|
"access": "public",
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import type { ReadonlyJSONValue } from "../utils/json/json-value";
|
|
2
|
-
import type {
|
|
2
|
+
import type { AssistantTransportStateOperation } from "./gorp/types";
|
|
3
3
|
import type { ToolModelContentPart } from "./tool/tool-types";
|
|
4
4
|
|
|
5
5
|
/**
|
|
@@ -132,10 +132,12 @@ export type AssistantStreamChunk = { readonly path: readonly number[] } & (
|
|
|
132
132
|
/** Emits a stream-level error message. */
|
|
133
133
|
readonly type: "error";
|
|
134
134
|
readonly error: string;
|
|
135
|
+
readonly code?: string;
|
|
136
|
+
readonly severity?: "critical" | "warning" | "info";
|
|
135
137
|
}
|
|
136
138
|
| {
|
|
137
|
-
/** Applies
|
|
139
|
+
/** Applies gorp-stream operations to state carried by this stream. */
|
|
138
140
|
readonly type: "update-state";
|
|
139
|
-
readonly operations:
|
|
141
|
+
readonly operations: AssistantTransportStateOperation[];
|
|
140
142
|
}
|
|
141
143
|
);
|