assistant-stream 0.1.8 → 0.2.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.
- package/ai-sdk/package.json +2 -2
- package/dist/ai-sdk/index.js +7 -34
- package/dist/ai-sdk/index.js.map +1 -1
- package/dist/ai-sdk/language-model.js +5 -31
- package/dist/ai-sdk/language-model.js.map +1 -1
- package/dist/ai-sdk.js +4 -32
- package/dist/ai-sdk.js.map +1 -1
- package/dist/core/AssistantStream.js +3 -29
- package/dist/core/AssistantStream.js.map +1 -1
- package/dist/core/AssistantStreamChunk.js +0 -18
- package/dist/core/AssistantStreamChunk.js.map +1 -1
- package/dist/core/accumulators/AssistantMessageStream.js +9 -35
- package/dist/core/accumulators/AssistantMessageStream.js.map +1 -1
- package/dist/core/accumulators/assistant-message-accumulator.js +22 -48
- package/dist/core/accumulators/assistant-message-accumulator.js.map +1 -1
- package/dist/core/index.js +16 -46
- package/dist/core/index.js.map +1 -1
- package/dist/core/modules/assistant-stream.js +29 -52
- package/dist/core/modules/assistant-stream.js.map +1 -1
- package/dist/core/modules/text.js +6 -33
- package/dist/core/modules/text.js.map +1 -1
- package/dist/core/modules/tool-call.js +8 -35
- package/dist/core/modules/tool-call.js.map +1 -1
- package/dist/core/serialization/PlainText.js +9 -36
- package/dist/core/serialization/PlainText.js.map +1 -1
- package/dist/core/serialization/data-stream/DataStream.js +57 -79
- package/dist/core/serialization/data-stream/DataStream.js.map +1 -1
- package/dist/core/serialization/data-stream/chunk-types.js +2 -28
- package/dist/core/serialization/data-stream/chunk-types.js.map +1 -1
- package/dist/core/serialization/data-stream/serialization.js +6 -33
- package/dist/core/serialization/data-stream/serialization.js.map +1 -1
- package/dist/core/tool/ToolCallReader.js +30 -55
- package/dist/core/tool/ToolCallReader.js.map +1 -1
- package/dist/core/tool/ToolExecutionStream.js +18 -52
- package/dist/core/tool/ToolExecutionStream.js.map +1 -1
- package/dist/core/tool/ToolResponse.js +5 -31
- package/dist/core/tool/ToolResponse.js.map +1 -1
- package/dist/core/tool/index.js +9 -35
- package/dist/core/tool/index.js.map +1 -1
- package/dist/core/tool/tool-types.js +0 -18
- package/dist/core/tool/tool-types.js.map +1 -1
- package/dist/core/tool/toolResultStream.js +8 -35
- package/dist/core/tool/toolResultStream.js.map +1 -1
- package/dist/core/tool/type-path-utils.js +0 -18
- package/dist/core/tool/type-path-utils.js.map +1 -1
- package/dist/core/utils/Counter.js +4 -30
- package/dist/core/utils/Counter.js.map +1 -1
- package/dist/core/utils/generateId.js +4 -30
- package/dist/core/utils/generateId.js.map +1 -1
- package/dist/core/utils/stream/AssistantMetaTransformStream.js +4 -30
- package/dist/core/utils/stream/AssistantMetaTransformStream.js.map +1 -1
- package/dist/core/utils/stream/AssistantTransformStream.js +8 -32
- package/dist/core/utils/stream/AssistantTransformStream.js.map +1 -1
- package/dist/core/utils/stream/LineDecoderStream.js +4 -30
- package/dist/core/utils/stream/LineDecoderStream.js.map +1 -1
- package/dist/core/utils/stream/PipeableTransformStream.js +4 -30
- package/dist/core/utils/stream/PipeableTransformStream.js.map +1 -1
- package/dist/core/utils/stream/UnderlyingReadable.js +0 -18
- package/dist/core/utils/stream/UnderlyingReadable.js.map +1 -1
- package/dist/core/utils/stream/merge.js +5 -31
- package/dist/core/utils/stream/merge.js.map +1 -1
- package/dist/core/utils/stream/path-utils.js +10 -38
- package/dist/core/utils/stream/path-utils.js.map +1 -1
- package/dist/core/utils/types.js +0 -18
- package/dist/core/utils/types.js.map +1 -1
- package/dist/core/utils/withPromiseOrValue.js +2 -28
- package/dist/core/utils/withPromiseOrValue.js.map +1 -1
- package/dist/index.js +1 -24
- package/dist/index.js.map +1 -1
- package/dist/utils/AsyncIterableStream.js +2 -28
- package/dist/utils/AsyncIterableStream.js.map +1 -1
- package/dist/utils/json/fix-json.js +2 -28
- package/dist/utils/json/fix-json.js.map +1 -1
- package/dist/utils/json/is-json.js +2 -30
- package/dist/utils/json/is-json.js.map +1 -1
- package/dist/utils/json/json-value.js +0 -18
- package/dist/utils/json/json-value.js.map +1 -1
- package/dist/utils/json/parse-partial-json-object.js +12 -50
- package/dist/utils/json/parse-partial-json-object.js.map +1 -1
- package/dist/utils/promiseWithResolvers.js +3 -29
- package/dist/utils/promiseWithResolvers.js.map +1 -1
- package/dist/utils.js +9 -32
- package/dist/utils.js.map +1 -1
- package/package.json +7 -9
- package/{dist/ai-sdk/index.mjs → src/ai-sdk/index.ts} +64 -33
- package/{dist/ai-sdk/language-model.mjs → src/ai-sdk/language-model.ts} +35 -19
- package/src/ai-sdk.ts +2 -0
- package/src/core/AssistantStream.ts +39 -0
- package/src/core/AssistantStreamChunk.ts +93 -0
- package/src/core/accumulators/AssistantMessageStream.ts +56 -0
- package/{dist/core/accumulators/assistant-message-accumulator.mjs → src/core/accumulators/assistant-message-accumulator.ts} +152 -67
- package/src/core/index.ts +17 -0
- package/{dist/core/modules/assistant-stream.mjs → src/core/modules/assistant-stream.ts} +122 -60
- package/src/core/modules/text.ts +64 -0
- package/{dist/core/modules/tool-call.mjs → src/core/modules/tool-call.ts} +48 -27
- package/src/core/serialization/PlainText.ts +68 -0
- package/{dist/core/serialization/data-stream/DataStream.mjs → src/core/serialization/data-stream/DataStream.ts} +111 -67
- package/src/core/serialization/data-stream/chunk-types.ts +93 -0
- package/src/core/serialization/data-stream/serialization.ts +32 -0
- package/src/core/tool/ToolCallReader.ts +432 -0
- package/{dist/core/tool/ToolExecutionStream.mjs → src/core/tool/ToolExecutionStream.ts} +83 -35
- package/src/core/tool/ToolResponse.ts +31 -0
- package/src/core/tool/index.ts +8 -0
- package/src/core/tool/tool-types.ts +107 -0
- package/src/core/tool/toolResultStream.ts +119 -0
- package/src/core/tool/type-path-utils.ts +36 -0
- package/src/core/utils/Counter.ts +7 -0
- package/src/core/utils/generateId.tsx +6 -0
- package/src/core/utils/stream/AssistantMetaTransformStream.ts +74 -0
- package/src/core/utils/stream/AssistantTransformStream.ts +74 -0
- package/{dist/core/utils/stream/LineDecoderStream.mjs → src/core/utils/stream/LineDecoderStream.ts} +12 -10
- package/src/core/utils/stream/PipeableTransformStream.ts +10 -0
- package/src/core/utils/stream/UnderlyingReadable.ts +5 -0
- package/src/core/utils/stream/merge.ts +212 -0
- package/src/core/utils/stream/path-utils.ts +71 -0
- package/src/core/utils/types.ts +150 -0
- package/src/core/utils/withPromiseOrValue.ts +20 -0
- package/src/index.ts +1 -0
- package/src/utils/AsyncIterableStream.ts +24 -0
- package/{dist/utils/json/fix-json.mjs → src/utils/json/fix-json.ts} +146 -20
- package/src/utils/json/is-json.ts +43 -0
- package/src/utils/json/json-value.ts +13 -0
- package/src/utils/json/parse-partial-json-object.test.ts +225 -0
- package/src/utils/json/parse-partial-json-object.ts +103 -0
- package/src/utils/promiseWithResolvers.ts +10 -0
- package/src/utils.ts +13 -0
- package/dist/ai-sdk/index.mjs.map +0 -1
- package/dist/ai-sdk/language-model.mjs.map +0 -1
- package/dist/ai-sdk.mjs +0 -7
- package/dist/ai-sdk.mjs.map +0 -1
- package/dist/core/AssistantStream.mjs +0 -21
- package/dist/core/AssistantStream.mjs.map +0 -1
- package/dist/core/AssistantStreamChunk.mjs +0 -1
- package/dist/core/AssistantStreamChunk.mjs.map +0 -1
- package/dist/core/accumulators/AssistantMessageStream.mjs +0 -54
- package/dist/core/accumulators/AssistantMessageStream.mjs.map +0 -1
- package/dist/core/accumulators/assistant-message-accumulator.mjs.map +0 -1
- package/dist/core/index.mjs +0 -26
- package/dist/core/index.mjs.map +0 -1
- package/dist/core/modules/assistant-stream.mjs.map +0 -1
- package/dist/core/modules/text.mjs +0 -52
- package/dist/core/modules/text.mjs.map +0 -1
- package/dist/core/modules/tool-call.mjs.map +0 -1
- package/dist/core/serialization/PlainText.mjs +0 -44
- package/dist/core/serialization/PlainText.mjs.map +0 -1
- package/dist/core/serialization/data-stream/DataStream.mjs.map +0 -1
- package/dist/core/serialization/data-stream/chunk-types.mjs +0 -24
- package/dist/core/serialization/data-stream/chunk-types.mjs.map +0 -1
- package/dist/core/serialization/data-stream/serialization.mjs +0 -30
- package/dist/core/serialization/data-stream/serialization.mjs.map +0 -1
- package/dist/core/tool/ToolCallReader.mjs +0 -315
- package/dist/core/tool/ToolCallReader.mjs.map +0 -1
- package/dist/core/tool/ToolExecutionStream.mjs.map +0 -1
- package/dist/core/tool/ToolResponse.mjs +0 -22
- package/dist/core/tool/ToolResponse.mjs.map +0 -1
- package/dist/core/tool/index.mjs +0 -14
- package/dist/core/tool/index.mjs.map +0 -1
- package/dist/core/tool/tool-types.mjs +0 -1
- package/dist/core/tool/tool-types.mjs.map +0 -1
- package/dist/core/tool/toolResultStream.mjs +0 -78
- package/dist/core/tool/toolResultStream.mjs.map +0 -1
- package/dist/core/tool/type-path-utils.mjs +0 -1
- package/dist/core/tool/type-path-utils.mjs.map +0 -1
- package/dist/core/utils/Counter.mjs +0 -11
- package/dist/core/utils/Counter.mjs.map +0 -1
- package/dist/core/utils/generateId.mjs +0 -10
- package/dist/core/utils/generateId.mjs.map +0 -1
- package/dist/core/utils/stream/AssistantMetaTransformStream.mjs +0 -44
- package/dist/core/utils/stream/AssistantMetaTransformStream.mjs.map +0 -1
- package/dist/core/utils/stream/AssistantTransformStream.mjs +0 -46
- package/dist/core/utils/stream/AssistantTransformStream.mjs.map +0 -1
- package/dist/core/utils/stream/LineDecoderStream.mjs.map +0 -1
- package/dist/core/utils/stream/PipeableTransformStream.mjs +0 -15
- package/dist/core/utils/stream/PipeableTransformStream.mjs.map +0 -1
- package/dist/core/utils/stream/UnderlyingReadable.mjs +0 -1
- package/dist/core/utils/stream/UnderlyingReadable.mjs.map +0 -1
- package/dist/core/utils/stream/merge.mjs +0 -85
- package/dist/core/utils/stream/merge.mjs.map +0 -1
- package/dist/core/utils/stream/path-utils.mjs +0 -61
- package/dist/core/utils/stream/path-utils.mjs.map +0 -1
- package/dist/core/utils/types.mjs +0 -1
- package/dist/core/utils/types.mjs.map +0 -1
- package/dist/core/utils/withPromiseOrValue.mjs +0 -17
- package/dist/core/utils/withPromiseOrValue.mjs.map +0 -1
- package/dist/index.mjs +0 -3
- package/dist/index.mjs.map +0 -1
- package/dist/utils/AsyncIterableStream.mjs +0 -21
- package/dist/utils/AsyncIterableStream.mjs.map +0 -1
- package/dist/utils/json/fix-json.mjs.map +0 -1
- package/dist/utils/json/is-json.mjs +0 -29
- package/dist/utils/json/is-json.mjs.map +0 -1
- package/dist/utils/json/json-value.mjs +0 -1
- package/dist/utils/json/json-value.mjs.map +0 -1
- package/dist/utils/json/parse-partial-json-object.mjs +0 -65
- package/dist/utils/json/parse-partial-json-object.mjs.map +0 -1
- package/dist/utils/promiseWithResolvers.mjs +0 -15
- package/dist/utils/promiseWithResolvers.mjs.map +0 -1
- package/dist/utils.mjs +0 -14
- package/dist/utils.mjs.map +0 -1
- package/utils/README.md +0 -1
- package/utils/package.json +0 -5
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
import { AssistantStreamChunk } from "../../AssistantStreamChunk";
|
|
2
|
+
import { Counter } from "../Counter";
|
|
3
|
+
|
|
4
|
+
export class PathAppendEncoder extends TransformStream<
|
|
5
|
+
AssistantStreamChunk,
|
|
6
|
+
AssistantStreamChunk
|
|
7
|
+
> {
|
|
8
|
+
constructor(idx: number) {
|
|
9
|
+
super({
|
|
10
|
+
transform(chunk, controller) {
|
|
11
|
+
controller.enqueue({
|
|
12
|
+
...chunk,
|
|
13
|
+
path: [idx, ...chunk.path],
|
|
14
|
+
});
|
|
15
|
+
},
|
|
16
|
+
});
|
|
17
|
+
}
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
export class PathAppendDecoder extends TransformStream<
|
|
21
|
+
AssistantStreamChunk,
|
|
22
|
+
AssistantStreamChunk
|
|
23
|
+
> {
|
|
24
|
+
constructor(idx: number) {
|
|
25
|
+
super({
|
|
26
|
+
transform(chunk, controller) {
|
|
27
|
+
const {
|
|
28
|
+
path: [idx2, ...path],
|
|
29
|
+
} = chunk;
|
|
30
|
+
|
|
31
|
+
if (idx !== idx2)
|
|
32
|
+
throw new Error(`Path mismatch: expected ${idx}, got ${idx2}`);
|
|
33
|
+
|
|
34
|
+
controller.enqueue({
|
|
35
|
+
...chunk,
|
|
36
|
+
path,
|
|
37
|
+
});
|
|
38
|
+
},
|
|
39
|
+
});
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
export class PathMergeEncoder extends TransformStream<
|
|
44
|
+
AssistantStreamChunk,
|
|
45
|
+
AssistantStreamChunk
|
|
46
|
+
> {
|
|
47
|
+
constructor(counter: Counter) {
|
|
48
|
+
const innerCounter = new Counter();
|
|
49
|
+
const mapping = new Map<number, number>();
|
|
50
|
+
super({
|
|
51
|
+
transform(chunk, controller) {
|
|
52
|
+
if (chunk.type === "part-start" && chunk.path.length === 0) {
|
|
53
|
+
mapping.set(innerCounter.up(), counter.up());
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
const [idx, ...path] = chunk.path;
|
|
57
|
+
if (idx === undefined) {
|
|
58
|
+
controller.enqueue(chunk);
|
|
59
|
+
return;
|
|
60
|
+
}
|
|
61
|
+
const mappedIdx = mapping.get(idx);
|
|
62
|
+
if (mappedIdx === undefined) throw new Error("Path not found");
|
|
63
|
+
|
|
64
|
+
controller.enqueue({
|
|
65
|
+
...chunk,
|
|
66
|
+
path: [mappedIdx, ...path],
|
|
67
|
+
});
|
|
68
|
+
},
|
|
69
|
+
});
|
|
70
|
+
}
|
|
71
|
+
}
|
|
@@ -0,0 +1,150 @@
|
|
|
1
|
+
import {
|
|
2
|
+
ReadonlyJSONObject,
|
|
3
|
+
ReadonlyJSONValue,
|
|
4
|
+
} from "../../utils/json/json-value";
|
|
5
|
+
|
|
6
|
+
type TextStatus =
|
|
7
|
+
| {
|
|
8
|
+
type: "running";
|
|
9
|
+
}
|
|
10
|
+
| {
|
|
11
|
+
type: "complete";
|
|
12
|
+
reason: "stop" | "unknown";
|
|
13
|
+
}
|
|
14
|
+
| {
|
|
15
|
+
type: "incomplete";
|
|
16
|
+
reason: "cancelled" | "length" | "content-filter" | "other";
|
|
17
|
+
};
|
|
18
|
+
|
|
19
|
+
// export type StepStartPart = {
|
|
20
|
+
// type: "step-start";
|
|
21
|
+
// };
|
|
22
|
+
|
|
23
|
+
export type TextPart = {
|
|
24
|
+
type: "text";
|
|
25
|
+
text: string;
|
|
26
|
+
status: TextStatus;
|
|
27
|
+
};
|
|
28
|
+
|
|
29
|
+
export type ReasoningPart = {
|
|
30
|
+
type: "reasoning";
|
|
31
|
+
text: string;
|
|
32
|
+
status: TextStatus;
|
|
33
|
+
};
|
|
34
|
+
|
|
35
|
+
type ToolCallStatus =
|
|
36
|
+
| {
|
|
37
|
+
type: "running";
|
|
38
|
+
isArgsComplete: boolean;
|
|
39
|
+
}
|
|
40
|
+
| {
|
|
41
|
+
type: "requires-action";
|
|
42
|
+
reason: "tool-call-result";
|
|
43
|
+
}
|
|
44
|
+
| {
|
|
45
|
+
type: "complete";
|
|
46
|
+
reason: "stop" | "unknown";
|
|
47
|
+
}
|
|
48
|
+
| {
|
|
49
|
+
type: "incomplete";
|
|
50
|
+
reason: "cancelled" | "length" | "content-filter" | "other";
|
|
51
|
+
};
|
|
52
|
+
|
|
53
|
+
export type ToolCallPart = {
|
|
54
|
+
type: "tool-call";
|
|
55
|
+
state: "partial-call" | "call" | "result";
|
|
56
|
+
status: ToolCallStatus;
|
|
57
|
+
toolCallId: string;
|
|
58
|
+
toolName: string;
|
|
59
|
+
argsText: string;
|
|
60
|
+
args: ReadonlyJSONObject;
|
|
61
|
+
artifact?: unknown;
|
|
62
|
+
result?: ReadonlyJSONValue;
|
|
63
|
+
isError?: boolean;
|
|
64
|
+
};
|
|
65
|
+
|
|
66
|
+
export type SourcePart = {
|
|
67
|
+
type: "source";
|
|
68
|
+
sourceType: "url";
|
|
69
|
+
id: string;
|
|
70
|
+
url: string;
|
|
71
|
+
title?: string;
|
|
72
|
+
};
|
|
73
|
+
|
|
74
|
+
export type FilePart = {
|
|
75
|
+
type: "file";
|
|
76
|
+
data: string;
|
|
77
|
+
mimeType: string;
|
|
78
|
+
};
|
|
79
|
+
|
|
80
|
+
export type AssistantMessagePart =
|
|
81
|
+
| TextPart
|
|
82
|
+
| ReasoningPart
|
|
83
|
+
| ToolCallPart
|
|
84
|
+
| SourcePart
|
|
85
|
+
| FilePart;
|
|
86
|
+
|
|
87
|
+
type AssistantMessageStepUsage = {
|
|
88
|
+
promptTokens: number;
|
|
89
|
+
completionTokens: number;
|
|
90
|
+
};
|
|
91
|
+
|
|
92
|
+
type AssistantMessageStepMetadata =
|
|
93
|
+
| {
|
|
94
|
+
state: "started";
|
|
95
|
+
messageId: string;
|
|
96
|
+
}
|
|
97
|
+
| {
|
|
98
|
+
state: "finished";
|
|
99
|
+
messageId: string;
|
|
100
|
+
finishReason:
|
|
101
|
+
| "stop"
|
|
102
|
+
| "length"
|
|
103
|
+
| "content-filter"
|
|
104
|
+
| "tool-calls"
|
|
105
|
+
| "error"
|
|
106
|
+
| "other"
|
|
107
|
+
| "unknown";
|
|
108
|
+
usage?: AssistantMessageStepUsage;
|
|
109
|
+
isContinued: boolean;
|
|
110
|
+
};
|
|
111
|
+
|
|
112
|
+
export type AssistantMessageStatus =
|
|
113
|
+
| {
|
|
114
|
+
type: "running";
|
|
115
|
+
}
|
|
116
|
+
| {
|
|
117
|
+
type: "requires-action";
|
|
118
|
+
reason: "tool-calls";
|
|
119
|
+
}
|
|
120
|
+
| {
|
|
121
|
+
type: "complete";
|
|
122
|
+
reason: "stop" | "unknown";
|
|
123
|
+
}
|
|
124
|
+
| {
|
|
125
|
+
type: "incomplete";
|
|
126
|
+
reason:
|
|
127
|
+
| "cancelled"
|
|
128
|
+
| "tool-calls"
|
|
129
|
+
| "length"
|
|
130
|
+
| "content-filter"
|
|
131
|
+
| "other"
|
|
132
|
+
| "error";
|
|
133
|
+
error?: ReadonlyJSONValue;
|
|
134
|
+
};
|
|
135
|
+
|
|
136
|
+
export type AssistantMessage = {
|
|
137
|
+
role: "assistant";
|
|
138
|
+
status: AssistantMessageStatus;
|
|
139
|
+
parts: AssistantMessagePart[];
|
|
140
|
+
/**
|
|
141
|
+
* @deprecated Use `parts` instead.
|
|
142
|
+
*/
|
|
143
|
+
content: AssistantMessagePart[];
|
|
144
|
+
metadata: {
|
|
145
|
+
unstable_data: ReadonlyJSONValue[];
|
|
146
|
+
unstable_annotations: ReadonlyJSONValue[];
|
|
147
|
+
steps: AssistantMessageStepMetadata[];
|
|
148
|
+
custom: Record<string, unknown>;
|
|
149
|
+
};
|
|
150
|
+
};
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
export function withPromiseOrValue<T>(
|
|
2
|
+
callback: () => T | PromiseLike<T>,
|
|
3
|
+
thenHandler: (value: T) => PromiseLike<void> | void,
|
|
4
|
+
catchHandler: (error: unknown) => PromiseLike<void> | void,
|
|
5
|
+
): PromiseLike<void> | void {
|
|
6
|
+
try {
|
|
7
|
+
const promiseOrValue = callback();
|
|
8
|
+
if (
|
|
9
|
+
typeof promiseOrValue === "object" &&
|
|
10
|
+
promiseOrValue !== null &&
|
|
11
|
+
"then" in promiseOrValue
|
|
12
|
+
) {
|
|
13
|
+
return promiseOrValue.then(thenHandler, catchHandler);
|
|
14
|
+
} else {
|
|
15
|
+
thenHandler(promiseOrValue);
|
|
16
|
+
}
|
|
17
|
+
} catch (e) {
|
|
18
|
+
catchHandler(e);
|
|
19
|
+
}
|
|
20
|
+
}
|
package/src/index.ts
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export * from "./core";
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
export type AsyncIterableStream<T> = AsyncIterable<T> & ReadableStream<T>;
|
|
2
|
+
|
|
3
|
+
async function* streamGeneratorPolyfill<T>(
|
|
4
|
+
this: ReadableStream<T>,
|
|
5
|
+
): AsyncIterator<T, undefined, unknown> {
|
|
6
|
+
const reader = this.getReader();
|
|
7
|
+
try {
|
|
8
|
+
while (true) {
|
|
9
|
+
const { done, value } = await reader.read();
|
|
10
|
+
if (done) break;
|
|
11
|
+
yield value;
|
|
12
|
+
}
|
|
13
|
+
} finally {
|
|
14
|
+
reader.releaseLock();
|
|
15
|
+
}
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
export function asAsyncIterableStream<T>(
|
|
19
|
+
source: ReadableStream<T>,
|
|
20
|
+
): AsyncIterableStream<T> {
|
|
21
|
+
(source as AsyncIterableStream<T>)[Symbol.asyncIterator] ??=
|
|
22
|
+
streamGeneratorPolyfill;
|
|
23
|
+
return source as AsyncIterableStream<T>;
|
|
24
|
+
}
|
|
@@ -1,17 +1,81 @@
|
|
|
1
|
-
//
|
|
2
|
-
|
|
3
|
-
|
|
1
|
+
// LICENSE for this file only
|
|
2
|
+
|
|
3
|
+
// MIT License
|
|
4
|
+
|
|
5
|
+
// Copyright (c) 2025 AgentbaseAI Inc.
|
|
6
|
+
// Copyright (c) 2023 Lars Grammel
|
|
7
|
+
|
|
8
|
+
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
9
|
+
// of this software and associated documentation files (the "Software"), to deal
|
|
10
|
+
// in the Software without restriction, including without limitation the rights
|
|
11
|
+
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
12
|
+
// copies of the Software, and to permit persons to whom the Software is
|
|
13
|
+
// furnished to do so, subject to the following conditions:
|
|
14
|
+
|
|
15
|
+
// The above copyright notice and this permission notice shall be included in all
|
|
16
|
+
// copies or substantial portions of the Software.
|
|
17
|
+
|
|
18
|
+
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
19
|
+
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
20
|
+
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
21
|
+
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
22
|
+
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
23
|
+
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
24
|
+
// SOFTWARE.
|
|
25
|
+
|
|
26
|
+
type State =
|
|
27
|
+
| "ROOT"
|
|
28
|
+
| "FINISH"
|
|
29
|
+
| "INSIDE_STRING"
|
|
30
|
+
| "INSIDE_STRING_ESCAPE"
|
|
31
|
+
| "INSIDE_LITERAL"
|
|
32
|
+
| "INSIDE_NUMBER"
|
|
33
|
+
| "INSIDE_OBJECT_START"
|
|
34
|
+
| "INSIDE_OBJECT_KEY"
|
|
35
|
+
| "INSIDE_OBJECT_AFTER_KEY"
|
|
36
|
+
| "INSIDE_OBJECT_BEFORE_VALUE"
|
|
37
|
+
| "INSIDE_OBJECT_AFTER_VALUE"
|
|
38
|
+
| "INSIDE_OBJECT_AFTER_COMMA"
|
|
39
|
+
| "INSIDE_ARRAY_START"
|
|
40
|
+
| "INSIDE_ARRAY_AFTER_VALUE"
|
|
41
|
+
| "INSIDE_ARRAY_AFTER_COMMA";
|
|
42
|
+
|
|
43
|
+
// Implemented as a scanner with additional fixing
|
|
44
|
+
// that performs a single linear time scan pass over the partial JSON.
|
|
45
|
+
//
|
|
46
|
+
// The states should ideally match relevant states from the JSON spec:
|
|
47
|
+
// https://www.json.org/json-en.html
|
|
48
|
+
//
|
|
49
|
+
// Please note that invalid JSON is not considered/covered, because it
|
|
50
|
+
// is assumed that the resulting JSON will be processed by a standard
|
|
51
|
+
// JSON parser that will detect any invalid JSON.
|
|
52
|
+
|
|
53
|
+
// Returns a tuple of [fixedJson, partialPath]
|
|
54
|
+
// partialPath is an array of object/array keys that represent
|
|
55
|
+
// the currently partial values. An object is considered partial
|
|
56
|
+
// if through appending extra characters to the JSON string, its
|
|
57
|
+
// value could change.
|
|
58
|
+
|
|
59
|
+
// Example input: '{"foo":[{"a":f'
|
|
60
|
+
// Example output: ['{"foo":[{"a":false}]}', ['foo', '0']]
|
|
61
|
+
// Example input: '{"foo":'
|
|
62
|
+
// Example output: ['{}', []]
|
|
63
|
+
|
|
64
|
+
export function fixJson(input: string): [string, string[]] {
|
|
65
|
+
const stack: State[] = ["ROOT"];
|
|
4
66
|
let lastValidIndex = -1;
|
|
5
|
-
let literalStart = null;
|
|
6
|
-
const path = [];
|
|
7
|
-
let currentKey;
|
|
8
|
-
|
|
9
|
-
|
|
67
|
+
let literalStart: number | null = null;
|
|
68
|
+
const path: string[] = [];
|
|
69
|
+
let currentKey: string | undefined;
|
|
70
|
+
|
|
71
|
+
function pushCurrentKeyToPath(): void {
|
|
72
|
+
if (currentKey !== undefined) {
|
|
10
73
|
path.push(JSON.parse('"' + currentKey + '"'));
|
|
11
|
-
currentKey =
|
|
74
|
+
currentKey = undefined;
|
|
12
75
|
}
|
|
13
76
|
}
|
|
14
|
-
|
|
77
|
+
|
|
78
|
+
function processValueStart(char: string, i: number, swapState: State) {
|
|
15
79
|
{
|
|
16
80
|
switch (char) {
|
|
17
81
|
case '"': {
|
|
@@ -19,9 +83,11 @@ function fixJson(input) {
|
|
|
19
83
|
stack.pop();
|
|
20
84
|
stack.push(swapState);
|
|
21
85
|
stack.push("INSIDE_STRING");
|
|
86
|
+
|
|
22
87
|
pushCurrentKeyToPath();
|
|
23
88
|
break;
|
|
24
89
|
}
|
|
90
|
+
|
|
25
91
|
case "f":
|
|
26
92
|
case "t":
|
|
27
93
|
case "n": {
|
|
@@ -32,10 +98,12 @@ function fixJson(input) {
|
|
|
32
98
|
stack.push("INSIDE_LITERAL");
|
|
33
99
|
break;
|
|
34
100
|
}
|
|
101
|
+
|
|
35
102
|
case "-": {
|
|
36
103
|
stack.pop();
|
|
37
104
|
stack.push(swapState);
|
|
38
105
|
stack.push("INSIDE_NUMBER");
|
|
106
|
+
|
|
39
107
|
pushCurrentKeyToPath();
|
|
40
108
|
break;
|
|
41
109
|
}
|
|
@@ -53,29 +121,35 @@ function fixJson(input) {
|
|
|
53
121
|
stack.pop();
|
|
54
122
|
stack.push(swapState);
|
|
55
123
|
stack.push("INSIDE_NUMBER");
|
|
124
|
+
|
|
56
125
|
pushCurrentKeyToPath();
|
|
57
126
|
break;
|
|
58
127
|
}
|
|
128
|
+
|
|
59
129
|
case "{": {
|
|
60
130
|
lastValidIndex = i;
|
|
61
131
|
stack.pop();
|
|
62
132
|
stack.push(swapState);
|
|
63
133
|
stack.push("INSIDE_OBJECT_START");
|
|
134
|
+
|
|
64
135
|
pushCurrentKeyToPath();
|
|
65
136
|
break;
|
|
66
137
|
}
|
|
138
|
+
|
|
67
139
|
case "[": {
|
|
68
140
|
lastValidIndex = i;
|
|
69
141
|
stack.pop();
|
|
70
142
|
stack.push(swapState);
|
|
71
143
|
stack.push("INSIDE_ARRAY_START");
|
|
144
|
+
|
|
72
145
|
pushCurrentKeyToPath();
|
|
73
146
|
break;
|
|
74
147
|
}
|
|
75
148
|
}
|
|
76
149
|
}
|
|
77
150
|
}
|
|
78
|
-
|
|
151
|
+
|
|
152
|
+
function processAfterObjectValue(char: string, i: number) {
|
|
79
153
|
switch (char) {
|
|
80
154
|
case ",": {
|
|
81
155
|
stack.pop();
|
|
@@ -90,7 +164,8 @@ function fixJson(input) {
|
|
|
90
164
|
}
|
|
91
165
|
}
|
|
92
166
|
}
|
|
93
|
-
|
|
167
|
+
|
|
168
|
+
function processAfterArrayValue(char: string, i: number) {
|
|
94
169
|
switch (char) {
|
|
95
170
|
case ",": {
|
|
96
171
|
stack.pop();
|
|
@@ -106,13 +181,16 @@ function fixJson(input) {
|
|
|
106
181
|
}
|
|
107
182
|
}
|
|
108
183
|
}
|
|
184
|
+
|
|
109
185
|
for (let i = 0; i < input.length; i++) {
|
|
110
|
-
const char = input[i]
|
|
186
|
+
const char = input[i]!;
|
|
111
187
|
const currentState = stack[stack.length - 1];
|
|
188
|
+
|
|
112
189
|
switch (currentState) {
|
|
113
190
|
case "ROOT":
|
|
114
191
|
processValueStart(char, i, "FINISH");
|
|
115
192
|
break;
|
|
193
|
+
|
|
116
194
|
case "INSIDE_OBJECT_START": {
|
|
117
195
|
switch (char) {
|
|
118
196
|
case '"': {
|
|
@@ -130,6 +208,7 @@ function fixJson(input) {
|
|
|
130
208
|
}
|
|
131
209
|
break;
|
|
132
210
|
}
|
|
211
|
+
|
|
133
212
|
case "INSIDE_OBJECT_AFTER_COMMA": {
|
|
134
213
|
switch (char) {
|
|
135
214
|
case '"': {
|
|
@@ -141,6 +220,7 @@ function fixJson(input) {
|
|
|
141
220
|
}
|
|
142
221
|
break;
|
|
143
222
|
}
|
|
223
|
+
|
|
144
224
|
case "INSIDE_OBJECT_KEY": {
|
|
145
225
|
switch (char) {
|
|
146
226
|
case '"': {
|
|
@@ -160,42 +240,52 @@ function fixJson(input) {
|
|
|
160
240
|
}
|
|
161
241
|
break;
|
|
162
242
|
}
|
|
243
|
+
|
|
163
244
|
case "INSIDE_OBJECT_AFTER_KEY": {
|
|
164
245
|
switch (char) {
|
|
165
246
|
case ":": {
|
|
166
247
|
stack.pop();
|
|
167
248
|
stack.push("INSIDE_OBJECT_BEFORE_VALUE");
|
|
249
|
+
|
|
168
250
|
break;
|
|
169
251
|
}
|
|
170
252
|
}
|
|
171
253
|
break;
|
|
172
254
|
}
|
|
255
|
+
|
|
173
256
|
case "INSIDE_OBJECT_BEFORE_VALUE": {
|
|
174
257
|
processValueStart(char, i, "INSIDE_OBJECT_AFTER_VALUE");
|
|
175
258
|
break;
|
|
176
259
|
}
|
|
260
|
+
|
|
177
261
|
case "INSIDE_OBJECT_AFTER_VALUE": {
|
|
178
262
|
processAfterObjectValue(char, i);
|
|
179
263
|
break;
|
|
180
264
|
}
|
|
265
|
+
|
|
181
266
|
case "INSIDE_STRING": {
|
|
182
267
|
switch (char) {
|
|
183
268
|
case '"': {
|
|
184
269
|
stack.pop();
|
|
185
270
|
lastValidIndex = i;
|
|
271
|
+
|
|
186
272
|
currentKey = path.pop();
|
|
187
273
|
break;
|
|
188
274
|
}
|
|
275
|
+
|
|
189
276
|
case "\\": {
|
|
190
277
|
stack.push("INSIDE_STRING_ESCAPE");
|
|
191
278
|
break;
|
|
192
279
|
}
|
|
280
|
+
|
|
193
281
|
default: {
|
|
194
282
|
lastValidIndex = i;
|
|
195
283
|
}
|
|
196
284
|
}
|
|
285
|
+
|
|
197
286
|
break;
|
|
198
287
|
}
|
|
288
|
+
|
|
199
289
|
case "INSIDE_ARRAY_START": {
|
|
200
290
|
switch (char) {
|
|
201
291
|
case "]": {
|
|
@@ -204,6 +294,7 @@ function fixJson(input) {
|
|
|
204
294
|
currentKey = path.pop();
|
|
205
295
|
break;
|
|
206
296
|
}
|
|
297
|
+
|
|
207
298
|
default: {
|
|
208
299
|
lastValidIndex = i;
|
|
209
300
|
currentKey = "0";
|
|
@@ -213,40 +304,50 @@ function fixJson(input) {
|
|
|
213
304
|
}
|
|
214
305
|
break;
|
|
215
306
|
}
|
|
307
|
+
|
|
216
308
|
case "INSIDE_ARRAY_AFTER_VALUE": {
|
|
217
309
|
switch (char) {
|
|
218
310
|
case ",": {
|
|
219
311
|
stack.pop();
|
|
220
312
|
stack.push("INSIDE_ARRAY_AFTER_COMMA");
|
|
313
|
+
|
|
221
314
|
currentKey = (Number(currentKey) + 1).toString();
|
|
222
315
|
break;
|
|
223
316
|
}
|
|
317
|
+
|
|
224
318
|
case "]": {
|
|
225
319
|
lastValidIndex = i;
|
|
226
320
|
stack.pop();
|
|
227
321
|
currentKey = path.pop();
|
|
228
322
|
break;
|
|
229
323
|
}
|
|
324
|
+
|
|
230
325
|
default: {
|
|
231
326
|
lastValidIndex = i;
|
|
232
327
|
break;
|
|
233
328
|
}
|
|
234
329
|
}
|
|
330
|
+
|
|
235
331
|
break;
|
|
236
332
|
}
|
|
333
|
+
|
|
237
334
|
case "INSIDE_ARRAY_AFTER_COMMA": {
|
|
238
335
|
processValueStart(char, i, "INSIDE_ARRAY_AFTER_VALUE");
|
|
239
336
|
break;
|
|
240
337
|
}
|
|
338
|
+
|
|
241
339
|
case "INSIDE_STRING_ESCAPE": {
|
|
242
340
|
stack.pop();
|
|
341
|
+
|
|
243
342
|
if (stack[stack.length - 1] === "INSIDE_STRING") {
|
|
244
343
|
lastValidIndex = i;
|
|
245
344
|
} else if (stack[stack.length - 1] === "INSIDE_OBJECT_KEY") {
|
|
246
345
|
currentKey += char;
|
|
247
346
|
}
|
|
347
|
+
|
|
248
348
|
break;
|
|
249
349
|
}
|
|
350
|
+
|
|
250
351
|
case "INSIDE_NUMBER": {
|
|
251
352
|
switch (char) {
|
|
252
353
|
case "0":
|
|
@@ -262,51 +363,71 @@ function fixJson(input) {
|
|
|
262
363
|
lastValidIndex = i;
|
|
263
364
|
break;
|
|
264
365
|
}
|
|
366
|
+
|
|
265
367
|
case "e":
|
|
266
368
|
case "E":
|
|
267
369
|
case "-":
|
|
268
370
|
case ".": {
|
|
269
371
|
break;
|
|
270
372
|
}
|
|
373
|
+
|
|
271
374
|
case ",": {
|
|
272
375
|
stack.pop();
|
|
273
376
|
currentKey = path.pop();
|
|
377
|
+
|
|
274
378
|
if (stack[stack.length - 1] === "INSIDE_ARRAY_AFTER_VALUE") {
|
|
275
379
|
processAfterArrayValue(char, i);
|
|
276
380
|
}
|
|
381
|
+
|
|
277
382
|
if (stack[stack.length - 1] === "INSIDE_OBJECT_AFTER_VALUE") {
|
|
278
383
|
processAfterObjectValue(char, i);
|
|
279
384
|
}
|
|
385
|
+
|
|
280
386
|
break;
|
|
281
387
|
}
|
|
388
|
+
|
|
282
389
|
case "}": {
|
|
283
390
|
stack.pop();
|
|
284
391
|
currentKey = path.pop();
|
|
392
|
+
|
|
285
393
|
if (stack[stack.length - 1] === "INSIDE_OBJECT_AFTER_VALUE") {
|
|
286
394
|
processAfterObjectValue(char, i);
|
|
287
395
|
}
|
|
396
|
+
|
|
288
397
|
break;
|
|
289
398
|
}
|
|
399
|
+
|
|
290
400
|
case "]": {
|
|
291
401
|
stack.pop();
|
|
292
402
|
currentKey = path.pop();
|
|
403
|
+
|
|
293
404
|
if (stack[stack.length - 1] === "INSIDE_ARRAY_AFTER_VALUE") {
|
|
294
405
|
processAfterArrayValue(char, i);
|
|
295
406
|
}
|
|
407
|
+
|
|
296
408
|
break;
|
|
297
409
|
}
|
|
410
|
+
|
|
298
411
|
default: {
|
|
299
412
|
stack.pop();
|
|
300
413
|
currentKey = path.pop();
|
|
301
414
|
break;
|
|
302
415
|
}
|
|
303
416
|
}
|
|
417
|
+
|
|
304
418
|
break;
|
|
305
419
|
}
|
|
420
|
+
|
|
306
421
|
case "INSIDE_LITERAL": {
|
|
307
|
-
const partialLiteral = input.substring(literalStart
|
|
308
|
-
|
|
422
|
+
const partialLiteral = input.substring(literalStart!, i + 1);
|
|
423
|
+
|
|
424
|
+
if (
|
|
425
|
+
!"false".startsWith(partialLiteral) &&
|
|
426
|
+
!"true".startsWith(partialLiteral) &&
|
|
427
|
+
!"null".startsWith(partialLiteral)
|
|
428
|
+
) {
|
|
309
429
|
stack.pop();
|
|
430
|
+
|
|
310
431
|
if (stack[stack.length - 1] === "INSIDE_OBJECT_AFTER_VALUE") {
|
|
311
432
|
processAfterObjectValue(char, i);
|
|
312
433
|
} else if (stack[stack.length - 1] === "INSIDE_ARRAY_AFTER_VALUE") {
|
|
@@ -315,18 +436,23 @@ function fixJson(input) {
|
|
|
315
436
|
} else {
|
|
316
437
|
lastValidIndex = i;
|
|
317
438
|
}
|
|
439
|
+
|
|
318
440
|
break;
|
|
319
441
|
}
|
|
320
442
|
}
|
|
321
443
|
}
|
|
444
|
+
|
|
322
445
|
let result = input.slice(0, lastValidIndex + 1);
|
|
446
|
+
|
|
323
447
|
for (let i = stack.length - 1; i >= 0; i--) {
|
|
324
448
|
const state = stack[i];
|
|
449
|
+
|
|
325
450
|
switch (state) {
|
|
326
451
|
case "INSIDE_STRING": {
|
|
327
452
|
result += '"';
|
|
328
453
|
break;
|
|
329
454
|
}
|
|
455
|
+
|
|
330
456
|
case "INSIDE_OBJECT_KEY":
|
|
331
457
|
case "INSIDE_OBJECT_AFTER_KEY":
|
|
332
458
|
case "INSIDE_OBJECT_AFTER_COMMA":
|
|
@@ -336,14 +462,17 @@ function fixJson(input) {
|
|
|
336
462
|
result += "}";
|
|
337
463
|
break;
|
|
338
464
|
}
|
|
465
|
+
|
|
339
466
|
case "INSIDE_ARRAY_START":
|
|
340
467
|
case "INSIDE_ARRAY_AFTER_COMMA":
|
|
341
468
|
case "INSIDE_ARRAY_AFTER_VALUE": {
|
|
342
469
|
result += "]";
|
|
343
470
|
break;
|
|
344
471
|
}
|
|
472
|
+
|
|
345
473
|
case "INSIDE_LITERAL": {
|
|
346
|
-
const partialLiteral = input.substring(literalStart
|
|
474
|
+
const partialLiteral = input.substring(literalStart!, input.length);
|
|
475
|
+
|
|
347
476
|
if ("true".startsWith(partialLiteral)) {
|
|
348
477
|
result += "true".slice(partialLiteral.length);
|
|
349
478
|
} else if ("false".startsWith(partialLiteral)) {
|
|
@@ -354,9 +483,6 @@ function fixJson(input) {
|
|
|
354
483
|
}
|
|
355
484
|
}
|
|
356
485
|
}
|
|
486
|
+
|
|
357
487
|
return [result, path];
|
|
358
488
|
}
|
|
359
|
-
export {
|
|
360
|
-
fixJson
|
|
361
|
-
};
|
|
362
|
-
//# sourceMappingURL=fix-json.mjs.map
|