@librechat/agents 3.3.4 → 3.3.5

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (159) hide show
  1. package/dist/cjs/common/constants.cjs +21 -0
  2. package/dist/cjs/common/constants.cjs.map +1 -1
  3. package/dist/cjs/events.cjs +10 -1
  4. package/dist/cjs/events.cjs.map +1 -1
  5. package/dist/cjs/graphs/Graph.cjs +456 -7
  6. package/dist/cjs/graphs/Graph.cjs.map +1 -1
  7. package/dist/cjs/hooks/HookRegistry.cjs +25 -0
  8. package/dist/cjs/hooks/HookRegistry.cjs.map +1 -1
  9. package/dist/cjs/hooks/index.cjs +12 -0
  10. package/dist/cjs/hooks/index.cjs.map +1 -1
  11. package/dist/cjs/hooks/types.cjs +1 -0
  12. package/dist/cjs/hooks/types.cjs.map +1 -1
  13. package/dist/cjs/langfuse.cjs +8 -0
  14. package/dist/cjs/langfuse.cjs.map +1 -1
  15. package/dist/cjs/llm/bedrock/utils/message_inputs.cjs +1 -3
  16. package/dist/cjs/llm/bedrock/utils/message_inputs.cjs.map +1 -1
  17. package/dist/cjs/llm/invoke.cjs +268 -3
  18. package/dist/cjs/llm/invoke.cjs.map +1 -1
  19. package/dist/cjs/llm/preempt.cjs +132 -0
  20. package/dist/cjs/llm/preempt.cjs.map +1 -0
  21. package/dist/cjs/main.cjs +17 -3
  22. package/dist/cjs/messages/alternation.cjs +92 -0
  23. package/dist/cjs/messages/alternation.cjs.map +1 -0
  24. package/dist/cjs/messages/format.cjs +72 -0
  25. package/dist/cjs/messages/format.cjs.map +1 -1
  26. package/dist/cjs/messages/handoffCue.cjs +63 -0
  27. package/dist/cjs/messages/handoffCue.cjs.map +1 -0
  28. package/dist/cjs/messages/index.cjs +3 -0
  29. package/dist/cjs/messages/injected.cjs +60 -0
  30. package/dist/cjs/messages/injected.cjs.map +1 -0
  31. package/dist/cjs/run.cjs +80 -7
  32. package/dist/cjs/run.cjs.map +1 -1
  33. package/dist/cjs/session/handlers.cjs +18 -9
  34. package/dist/cjs/session/handlers.cjs.map +1 -1
  35. package/dist/cjs/stream.cjs +28 -7
  36. package/dist/cjs/stream.cjs.map +1 -1
  37. package/dist/cjs/tools/ToolNode.cjs +3 -23
  38. package/dist/cjs/tools/ToolNode.cjs.map +1 -1
  39. package/dist/cjs/tools/search/keenable-scraper.cjs +90 -0
  40. package/dist/cjs/tools/search/keenable-scraper.cjs.map +1 -0
  41. package/dist/cjs/tools/search/tool.cjs +9 -1
  42. package/dist/cjs/tools/search/tool.cjs.map +1 -1
  43. package/dist/esm/common/constants.mjs +19 -1
  44. package/dist/esm/common/constants.mjs.map +1 -1
  45. package/dist/esm/events.mjs +10 -1
  46. package/dist/esm/events.mjs.map +1 -1
  47. package/dist/esm/graphs/Graph.mjs +455 -6
  48. package/dist/esm/graphs/Graph.mjs.map +1 -1
  49. package/dist/esm/hooks/HookRegistry.mjs +25 -0
  50. package/dist/esm/hooks/HookRegistry.mjs.map +1 -1
  51. package/dist/esm/hooks/index.mjs +12 -1
  52. package/dist/esm/hooks/index.mjs.map +1 -1
  53. package/dist/esm/hooks/types.mjs +1 -0
  54. package/dist/esm/hooks/types.mjs.map +1 -1
  55. package/dist/esm/langfuse.mjs +9 -1
  56. package/dist/esm/langfuse.mjs.map +1 -1
  57. package/dist/esm/llm/bedrock/utils/message_inputs.mjs +1 -3
  58. package/dist/esm/llm/bedrock/utils/message_inputs.mjs.map +1 -1
  59. package/dist/esm/llm/invoke.mjs +270 -6
  60. package/dist/esm/llm/invoke.mjs.map +1 -1
  61. package/dist/esm/llm/preempt.mjs +131 -0
  62. package/dist/esm/llm/preempt.mjs.map +1 -0
  63. package/dist/esm/main.mjs +8 -5
  64. package/dist/esm/messages/alternation.mjs +91 -0
  65. package/dist/esm/messages/alternation.mjs.map +1 -0
  66. package/dist/esm/messages/format.mjs +72 -0
  67. package/dist/esm/messages/format.mjs.map +1 -1
  68. package/dist/esm/messages/handoffCue.mjs +61 -0
  69. package/dist/esm/messages/handoffCue.mjs.map +1 -0
  70. package/dist/esm/messages/index.mjs +3 -0
  71. package/dist/esm/messages/injected.mjs +60 -0
  72. package/dist/esm/messages/injected.mjs.map +1 -0
  73. package/dist/esm/run.mjs +80 -7
  74. package/dist/esm/run.mjs.map +1 -1
  75. package/dist/esm/session/handlers.mjs +19 -10
  76. package/dist/esm/session/handlers.mjs.map +1 -1
  77. package/dist/esm/stream.mjs +27 -8
  78. package/dist/esm/stream.mjs.map +1 -1
  79. package/dist/esm/tools/ToolNode.mjs +3 -23
  80. package/dist/esm/tools/ToolNode.mjs.map +1 -1
  81. package/dist/esm/tools/search/keenable-scraper.mjs +88 -0
  82. package/dist/esm/tools/search/keenable-scraper.mjs.map +1 -0
  83. package/dist/esm/tools/search/tool.mjs +9 -1
  84. package/dist/esm/tools/search/tool.mjs.map +1 -1
  85. package/dist/types/common/constants.d.ts +18 -0
  86. package/dist/types/graphs/Graph.d.ts +138 -1
  87. package/dist/types/hooks/HookRegistry.d.ts +15 -0
  88. package/dist/types/hooks/index.d.ts +12 -1
  89. package/dist/types/hooks/types.d.ts +45 -6
  90. package/dist/types/index.d.ts +1 -1
  91. package/dist/types/llm/invoke.d.ts +7 -0
  92. package/dist/types/llm/preempt.d.ts +40 -0
  93. package/dist/types/messages/alternation.d.ts +23 -0
  94. package/dist/types/messages/handoffCue.d.ts +40 -0
  95. package/dist/types/messages/index.d.ts +3 -0
  96. package/dist/types/messages/injected.d.ts +3 -0
  97. package/dist/types/run.d.ts +7 -0
  98. package/dist/types/stream.d.ts +14 -0
  99. package/dist/types/tools/ToolNode.d.ts +0 -7
  100. package/dist/types/tools/search/keenable-scraper.d.ts +15 -0
  101. package/dist/types/tools/search/types.d.ts +31 -2
  102. package/dist/types/types/graph.d.ts +8 -1
  103. package/dist/types/types/run.d.ts +65 -0
  104. package/dist/types/types/stream.d.ts +0 -25
  105. package/package.json +1 -1
  106. package/src/{splitStream.test.ts → aggregator.test.ts} +59 -666
  107. package/src/common/constants.ts +21 -0
  108. package/src/events.ts +15 -1
  109. package/src/graphs/Graph.ts +568 -3
  110. package/src/graphs/__tests__/Graph.contextOverflow.test.ts +18 -7
  111. package/src/graphs/__tests__/Graph.preemptSignal.test.ts +126 -0
  112. package/src/hooks/HookRegistry.ts +40 -0
  113. package/src/hooks/__tests__/preemptBoundary.test.ts +152 -0
  114. package/src/hooks/index.ts +16 -2
  115. package/src/hooks/types.ts +47 -3
  116. package/src/index.ts +1 -1
  117. package/src/langfuse.ts +26 -1
  118. package/src/llm/bedrock/utils/message_inputs.test.ts +82 -0
  119. package/src/llm/bedrock/utils/message_inputs.ts +14 -11
  120. package/src/llm/bedrock/utils/toolResultCachePoint.test.ts +15 -0
  121. package/src/llm/invoke.alternation.test.ts +87 -0
  122. package/src/llm/invoke.handoffCue.test.ts +112 -0
  123. package/src/llm/invoke.ts +417 -8
  124. package/src/llm/preempt.test.ts +323 -0
  125. package/src/llm/preempt.ts +178 -0
  126. package/src/messages/alternation.test.ts +212 -0
  127. package/src/messages/alternation.ts +112 -0
  128. package/src/messages/format.ts +91 -0
  129. package/src/messages/formatAgentMessages.steer.test.ts +267 -0
  130. package/src/messages/handoffCue.test.ts +96 -0
  131. package/src/messages/handoffCue.ts +78 -0
  132. package/src/messages/index.ts +3 -0
  133. package/src/messages/injected.test.ts +90 -0
  134. package/src/messages/injected.ts +74 -0
  135. package/src/run.ts +91 -6
  136. package/src/scripts/preempt-probe.ts +330 -0
  137. package/src/scripts/preempt-scenarios.ts +388 -0
  138. package/src/session/handlers.ts +32 -12
  139. package/src/specs/handoffCue.test.ts +165 -0
  140. package/src/specs/langfuse-callbacks.test.ts +352 -2
  141. package/src/specs/preemptSeal.test.ts +309 -0
  142. package/src/stream.dispatch.test.ts +63 -0
  143. package/src/stream.ts +36 -8
  144. package/src/tools/ToolNode.ts +3 -31
  145. package/src/tools/search/keenable-scraper.test.ts +153 -0
  146. package/src/tools/search/keenable-scraper.ts +137 -0
  147. package/src/tools/search/tool.ts +13 -2
  148. package/src/tools/search/types.ts +50 -3
  149. package/src/types/graph.ts +12 -1
  150. package/src/types/run.ts +67 -0
  151. package/src/types/stream.ts +0 -41
  152. package/dist/cjs/splitStream.cjs +0 -151
  153. package/dist/cjs/splitStream.cjs.map +0 -1
  154. package/dist/esm/splitStream.mjs +0 -150
  155. package/dist/esm/splitStream.mjs.map +0 -1
  156. package/dist/types/mockStream.d.ts +0 -32
  157. package/dist/types/splitStream.d.ts +0 -37
  158. package/src/mockStream.ts +0 -99
  159. package/src/splitStream.ts +0 -234
@@ -1,150 +0,0 @@
1
- import "./common/enum.mjs";
2
- import "./common/index.mjs";
3
- import { nanoid } from "nanoid";
4
- //#region src/splitStream.ts
5
- const SEPARATORS = [
6
- ". ",
7
- "?",
8
- "!",
9
- "۔",
10
- "- ",
11
- "。",
12
- "‥",
13
- ";",
14
- "¡",
15
- "¿",
16
- "\n",
17
- "```"
18
- ];
19
- var SplitStreamHandler = class {
20
- inCodeBlock = false;
21
- inThinkBlock = false;
22
- accumulate;
23
- tokens = [];
24
- lastToken = "";
25
- reasoningTokens = [];
26
- currentStepId;
27
- currentMessageId;
28
- currentType;
29
- currentLength = 0;
30
- reasoningKey = "reasoning_content";
31
- currentIndex = -1;
32
- blockThreshold = 4500;
33
- /** The run ID AKA the Message ID associated with the complete generation */
34
- runId;
35
- handlers;
36
- constructor({ runId, handlers, accumulate, reasoningKey, blockThreshold }) {
37
- this.runId = runId;
38
- this.handlers = handlers;
39
- if (reasoningKey) this.reasoningKey = reasoningKey;
40
- if (blockThreshold != null) this.blockThreshold = blockThreshold;
41
- this.accumulate = accumulate ?? false;
42
- }
43
- getMessageId = () => {
44
- const messageId = this.currentMessageId;
45
- if (messageId != null && messageId) return messageId;
46
- };
47
- createMessageStep = (type) => {
48
- if (type != null && this.currentType !== type) this.currentType = type;
49
- this.currentLength = 0;
50
- this.currentIndex += 1;
51
- this.currentStepId = `step_${nanoid()}`;
52
- this.currentMessageId = `msg_${nanoid()}`;
53
- return [this.currentStepId, this.currentMessageId];
54
- };
55
- dispatchRunStep = (stepId, stepDetails) => {
56
- const runStep = {
57
- id: stepId,
58
- runId: this.runId,
59
- type: stepDetails.type,
60
- index: this.currentIndex,
61
- stepDetails
62
- };
63
- this.handlers?.["on_run_step"]?.({
64
- event: "on_run_step",
65
- data: runStep
66
- });
67
- };
68
- dispatchMessageDelta = (stepId, delta) => {
69
- const messageDelta = {
70
- id: stepId,
71
- delta
72
- };
73
- this.handlers?.["on_message_delta"]?.({
74
- event: "on_message_delta",
75
- data: messageDelta
76
- });
77
- };
78
- dispatchReasoningDelta = (stepId, delta) => {
79
- const reasoningDelta = {
80
- id: stepId,
81
- delta
82
- };
83
- this.handlers?.["on_reasoning_delta"]?.({
84
- event: "on_reasoning_delta",
85
- data: reasoningDelta
86
- });
87
- };
88
- handleContent = (content, _type) => {
89
- let type = _type;
90
- if (this.inThinkBlock && type === "text") type = "think";
91
- if (this.accumulate) if (type === "think") this.reasoningTokens.push(content);
92
- else this.tokens.push(content);
93
- if (this.currentType !== type) {
94
- const [newStepId, newMessageId] = this.createMessageStep(type);
95
- this.dispatchRunStep(newStepId, {
96
- type: "message_creation",
97
- message_creation: { message_id: newMessageId }
98
- });
99
- }
100
- const stepId = this.currentStepId ?? "";
101
- if (type === "think") this.dispatchReasoningDelta(stepId, { content: [{
102
- type: "think",
103
- think: content
104
- }] });
105
- else this.dispatchMessageDelta(stepId, { content: [{
106
- type: "text",
107
- text: content
108
- }] });
109
- this.currentLength += content.length;
110
- if (this.inCodeBlock) return;
111
- if (this.currentLength > this.blockThreshold && SEPARATORS.some((sep) => content.includes(sep))) {
112
- const [newStepId, newMessageId] = this.createMessageStep(type);
113
- this.dispatchRunStep(newStepId, {
114
- type: "message_creation",
115
- message_creation: { message_id: newMessageId }
116
- });
117
- }
118
- };
119
- getDeltaContent(chunk) {
120
- return (chunk?.choices?.[0]?.delta)?.content ?? "";
121
- }
122
- getReasoningDelta(chunk) {
123
- return (chunk?.choices?.[0]?.delta)?.[this.reasoningKey] ?? "";
124
- }
125
- handle(chunk) {
126
- if (!chunk) return;
127
- const content = this.getDeltaContent(chunk);
128
- const reasoning_content = this.getReasoningDelta(chunk);
129
- if (!content.length && !reasoning_content.length) return;
130
- if (content.includes("```")) this.inCodeBlock = !this.inCodeBlock;
131
- if (content.includes("<think>") && !this.inCodeBlock) this.inThinkBlock = true;
132
- else if (this.lastToken.includes("</think>") && !this.inCodeBlock) this.inThinkBlock = false;
133
- this.lastToken = content;
134
- if (!(this.getMessageId() ?? "")) {
135
- const initialContentType = this.inThinkBlock ? "think" : "text";
136
- const initialType = reasoning_content ? "think" : initialContentType;
137
- const [stepId, message_id] = this.createMessageStep(initialType);
138
- this.dispatchRunStep(stepId, {
139
- type: "message_creation",
140
- message_creation: { message_id }
141
- });
142
- }
143
- if (reasoning_content) this.handleContent(reasoning_content, "think");
144
- else this.handleContent(content, "text");
145
- }
146
- };
147
- //#endregion
148
- export { SEPARATORS, SplitStreamHandler };
149
-
150
- //# sourceMappingURL=splitStream.mjs.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"splitStream.mjs","names":[],"sources":["../../src/splitStream.ts"],"sourcesContent":["import { nanoid } from 'nanoid';\nimport type * as t from '@/types';\nimport { ContentTypes, GraphEvents, StepTypes } from '@/common';\n\nexport const SEPARATORS = [\n '. ',\n '?',\n '!',\n '۔',\n '- ',\n '。',\n '‥',\n ';',\n '¡',\n '¿',\n '\\n',\n '```',\n];\n\nexport class SplitStreamHandler {\n private inCodeBlock = false;\n private inThinkBlock = false;\n private accumulate: boolean;\n tokens: string[] = [];\n lastToken = '';\n reasoningTokens: string[] = [];\n currentStepId?: string;\n currentMessageId?: string;\n currentType?: ContentTypes.TEXT | ContentTypes.THINK;\n currentLength = 0;\n reasoningKey: 'reasoning_content' | 'reasoning' = 'reasoning_content';\n currentIndex = -1;\n blockThreshold = 4500;\n /** The run ID AKA the Message ID associated with the complete generation */\n runId: string;\n handlers?: t.SplitStreamHandlers;\n constructor({\n runId,\n handlers,\n accumulate,\n reasoningKey,\n blockThreshold,\n }: {\n runId: string;\n accumulate?: boolean;\n handlers: t.SplitStreamHandlers;\n blockThreshold?: number;\n reasoningKey?: 'reasoning_content' | 'reasoning';\n }) {\n this.runId = runId;\n this.handlers = handlers;\n if (reasoningKey) {\n this.reasoningKey = reasoningKey;\n }\n if (blockThreshold != null) {\n this.blockThreshold = blockThreshold;\n }\n this.accumulate = accumulate ?? false;\n }\n getMessageId = (): string | undefined => {\n const messageId = this.currentMessageId;\n if (messageId != null && messageId) {\n return messageId;\n }\n return undefined;\n };\n createMessageStep = (\n type?: ContentTypes.TEXT | ContentTypes.THINK\n ): [string, string] => {\n if (type != null && this.currentType !== type) {\n this.currentType = type;\n }\n this.currentLength = 0;\n this.currentIndex += 1;\n this.currentStepId = `step_${nanoid()}`;\n this.currentMessageId = `msg_${nanoid()}`;\n return [this.currentStepId, this.currentMessageId];\n };\n dispatchRunStep = (stepId: string, stepDetails: t.StepDetails): void => {\n const runStep: t.RunStep = {\n id: stepId,\n runId: this.runId,\n type: stepDetails.type,\n index: this.currentIndex,\n stepDetails,\n // usage: null,\n };\n this.handlers?.[GraphEvents.ON_RUN_STEP]?.({\n event: GraphEvents.ON_RUN_STEP,\n data: runStep,\n });\n };\n dispatchMessageDelta = (stepId: string, delta: t.MessageDelta): void => {\n const messageDelta: t.MessageDeltaEvent = {\n id: stepId,\n delta,\n };\n this.handlers?.[GraphEvents.ON_MESSAGE_DELTA]?.({\n event: GraphEvents.ON_MESSAGE_DELTA,\n data: messageDelta,\n });\n };\n dispatchReasoningDelta = (stepId: string, delta: t.ReasoningDelta): void => {\n const reasoningDelta: t.ReasoningDeltaEvent = {\n id: stepId,\n delta,\n };\n this.handlers?.[GraphEvents.ON_REASONING_DELTA]?.({\n event: GraphEvents.ON_REASONING_DELTA,\n data: reasoningDelta,\n });\n };\n handleContent = (\n content: string,\n _type: ContentTypes.TEXT | ContentTypes.THINK\n ): void => {\n let type = _type;\n if (this.inThinkBlock && type === ContentTypes.TEXT) {\n type = ContentTypes.THINK;\n }\n if (this.accumulate) {\n if (type === ContentTypes.THINK) {\n this.reasoningTokens.push(content);\n } else {\n this.tokens.push(content);\n }\n }\n\n if (this.currentType !== type) {\n const [newStepId, newMessageId] = this.createMessageStep(type);\n this.dispatchRunStep(newStepId, {\n type: StepTypes.MESSAGE_CREATION,\n message_creation: {\n message_id: newMessageId,\n },\n });\n }\n\n const stepId = this.currentStepId ?? '';\n if (type === ContentTypes.THINK) {\n this.dispatchReasoningDelta(stepId, {\n content: [\n {\n type: ContentTypes.THINK,\n think: content,\n },\n ],\n });\n } else {\n this.dispatchMessageDelta(stepId, {\n content: [\n {\n type: ContentTypes.TEXT,\n text: content,\n },\n ],\n });\n }\n\n this.currentLength += content.length;\n if (this.inCodeBlock) {\n return;\n }\n\n if (\n this.currentLength > this.blockThreshold &&\n SEPARATORS.some((sep) => content.includes(sep))\n ) {\n const [newStepId, newMessageId] = this.createMessageStep(type);\n this.dispatchRunStep(newStepId, {\n type: StepTypes.MESSAGE_CREATION,\n message_creation: {\n message_id: newMessageId,\n },\n });\n }\n };\n getDeltaContent(chunk?: t.CustomChunk): string {\n return (chunk?.choices?.[0]?.delta as t.CustomChunkDelta)?.content ?? '';\n }\n getReasoningDelta(chunk?: t.CustomChunk): string {\n return (\n (chunk?.choices?.[0]?.delta as t.CustomChunkDelta)?.[this.reasoningKey] ??\n ''\n );\n }\n handle(chunk?: t.CustomChunk): void {\n if (!chunk) {\n return;\n }\n\n const content = this.getDeltaContent(chunk);\n const reasoning_content = this.getReasoningDelta(chunk);\n if (!content.length && !reasoning_content.length) {\n return;\n }\n\n if (content.includes('```')) {\n this.inCodeBlock = !this.inCodeBlock;\n }\n\n if (content.includes('<think>') && !this.inCodeBlock) {\n this.inThinkBlock = true;\n } else if (this.lastToken.includes('</think>') && !this.inCodeBlock) {\n this.inThinkBlock = false;\n }\n\n this.lastToken = content;\n\n const message_id = this.getMessageId() ?? '';\n\n if (!message_id) {\n const initialContentType = this.inThinkBlock\n ? ContentTypes.THINK\n : ContentTypes.TEXT;\n const initialType = reasoning_content\n ? ContentTypes.THINK\n : initialContentType;\n const [stepId, message_id] = this.createMessageStep(initialType);\n this.dispatchRunStep(stepId, {\n type: StepTypes.MESSAGE_CREATION,\n message_creation: {\n message_id,\n },\n });\n }\n\n if (reasoning_content) {\n this.handleContent(reasoning_content, ContentTypes.THINK);\n } else {\n this.handleContent(content, ContentTypes.TEXT);\n }\n }\n}\n"],"mappings":"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"}
@@ -1,32 +0,0 @@
1
- import type * as t from '@/types';
2
- export declare const createMockStream: (options?: {
3
- text?: string;
4
- reasoningText?: string;
5
- streamRate?: number;
6
- reasoningKey?: "reasoning" | "reasoning_content";
7
- }) => () => AsyncGenerator<t.CustomChunk>;
8
- /**
9
- (async function testStream(): Promise<void> {
10
- const runId = nanoid();
11
-
12
- const streamHandler = new SplitStreamHandler({
13
- runId,
14
- handlers: {
15
- [GraphEvents.ON_RUN_STEP]: (data): void => {
16
- console.dir(data, { depth: null });
17
- },
18
- [GraphEvents.ON_MESSAGE_DELTA]: (): void => {
19
- // console.dir(data, { depth: null });
20
- },
21
- },
22
- });
23
- const stream = createMockStream({
24
- reasoningText: 'This is a test reasoning text.',
25
- streamRate: 5,
26
- })();
27
-
28
- for await (const chunk of stream) {
29
- streamHandler.handle(chunk);
30
- }
31
- })();
32
- */
@@ -1,37 +0,0 @@
1
- import type * as t from '@/types';
2
- import { ContentTypes } from '@/common';
3
- export declare const SEPARATORS: string[];
4
- export declare class SplitStreamHandler {
5
- private inCodeBlock;
6
- private inThinkBlock;
7
- private accumulate;
8
- tokens: string[];
9
- lastToken: string;
10
- reasoningTokens: string[];
11
- currentStepId?: string;
12
- currentMessageId?: string;
13
- currentType?: ContentTypes.TEXT | ContentTypes.THINK;
14
- currentLength: number;
15
- reasoningKey: 'reasoning_content' | 'reasoning';
16
- currentIndex: number;
17
- blockThreshold: number;
18
- /** The run ID AKA the Message ID associated with the complete generation */
19
- runId: string;
20
- handlers?: t.SplitStreamHandlers;
21
- constructor({ runId, handlers, accumulate, reasoningKey, blockThreshold, }: {
22
- runId: string;
23
- accumulate?: boolean;
24
- handlers: t.SplitStreamHandlers;
25
- blockThreshold?: number;
26
- reasoningKey?: 'reasoning_content' | 'reasoning';
27
- });
28
- getMessageId: () => string | undefined;
29
- createMessageStep: (type?: ContentTypes.TEXT | ContentTypes.THINK) => [string, string];
30
- dispatchRunStep: (stepId: string, stepDetails: t.StepDetails) => void;
31
- dispatchMessageDelta: (stepId: string, delta: t.MessageDelta) => void;
32
- dispatchReasoningDelta: (stepId: string, delta: t.ReasoningDelta) => void;
33
- handleContent: (content: string, _type: ContentTypes.TEXT | ContentTypes.THINK) => void;
34
- getDeltaContent(chunk?: t.CustomChunk): string;
35
- getReasoningDelta(chunk?: t.CustomChunk): string;
36
- handle(chunk?: t.CustomChunk): void;
37
- }
package/src/mockStream.ts DELETED
@@ -1,99 +0,0 @@
1
-
2
- // import { nanoid } from 'nanoid';
3
- import type OpenAITypes from 'openai';
4
- import type * as t from '@/types';
5
- // import { SplitStreamHandler } from '@/splitStream';
6
- // import { GraphEvents } from '@/common';
7
- import { sleep } from '@/utils';
8
-
9
- const choiceProps: OpenAITypes.Chat.Completions.ChatCompletionChunk.Choice = { finish_reason: null, index: 0, delta: {} };
10
- const reasoningSplitRegex = /(?<=\s+)|(?=\s+)/;
11
- const contentSplitRegex = /(?<=<\/?think>)|(?=<\/?think>)|(?<=\s+)|(?=\s+)/;
12
- export const createMockStream = (options: {
13
- text?: string;
14
- reasoningText?: string;
15
- streamRate?: number;
16
- reasoningKey?: 'reasoning' | 'reasoning_content';
17
- } = {}) => {
18
- const {
19
- text,
20
- reasoningText,
21
- streamRate = 25,
22
- reasoningKey = 'reasoning_content'
23
- } = options;
24
-
25
- return async function* mockOpenAIStream(): AsyncGenerator<t.CustomChunk> {
26
- const content = text ?? `Here's a sample message that includes code:
27
- \`\`\`python
28
- def hello_world():
29
- print("Hello, World!")
30
- # This is a long code block
31
- # That shouldn't be split
32
- return True
33
- \`\`\`
34
- Now we're back to regular text. This is a very long sentence that should probably be split at some point because it exceeds our threshold and contains multiple natural breaking points. Let's see how it handles this case properly.
35
-
36
- Here's another code block:
37
- \`\`\`javascript
38
- console.log("Another test");
39
- // More code here
40
- \`\`\`
41
- And finally some more regular text to test our splitting logic.`;
42
-
43
- if (reasoningText != null && reasoningText) {
44
- // Split reasoning text into "token-like" chunks
45
- const reasoningTokens = reasoningText.split(reasoningSplitRegex);
46
- for (const token of reasoningTokens) {
47
- yield {
48
- choices: [{
49
- ...choiceProps,
50
- delta: {
51
- [reasoningKey]: token,
52
- },
53
- }]
54
- };
55
- await sleep(streamRate);
56
- }
57
- }
58
-
59
- // Split main content into "token-like" chunks
60
- const tokens = content.split(contentSplitRegex);
61
- for (const token of tokens) {
62
- yield {
63
- choices: [{
64
- ...choiceProps,
65
- delta: {
66
- content: token
67
- }
68
- }]
69
- };
70
- await sleep(streamRate);
71
- }
72
- };
73
- };
74
-
75
- /**
76
- (async function testStream(): Promise<void> {
77
- const runId = nanoid();
78
-
79
- const streamHandler = new SplitStreamHandler({
80
- runId,
81
- handlers: {
82
- [GraphEvents.ON_RUN_STEP]: (data): void => {
83
- console.dir(data, { depth: null });
84
- },
85
- [GraphEvents.ON_MESSAGE_DELTA]: (): void => {
86
- // console.dir(data, { depth: null });
87
- },
88
- },
89
- });
90
- const stream = createMockStream({
91
- reasoningText: 'This is a test reasoning text.',
92
- streamRate: 5,
93
- })();
94
-
95
- for await (const chunk of stream) {
96
- streamHandler.handle(chunk);
97
- }
98
- })();
99
- */
@@ -1,234 +0,0 @@
1
- import { nanoid } from 'nanoid';
2
- import type * as t from '@/types';
3
- import { ContentTypes, GraphEvents, StepTypes } from '@/common';
4
-
5
- export const SEPARATORS = [
6
- '. ',
7
- '?',
8
- '!',
9
- '۔',
10
- '- ',
11
- '。',
12
- '‥',
13
- ';',
14
- '¡',
15
- '¿',
16
- '\n',
17
- '```',
18
- ];
19
-
20
- export class SplitStreamHandler {
21
- private inCodeBlock = false;
22
- private inThinkBlock = false;
23
- private accumulate: boolean;
24
- tokens: string[] = [];
25
- lastToken = '';
26
- reasoningTokens: string[] = [];
27
- currentStepId?: string;
28
- currentMessageId?: string;
29
- currentType?: ContentTypes.TEXT | ContentTypes.THINK;
30
- currentLength = 0;
31
- reasoningKey: 'reasoning_content' | 'reasoning' = 'reasoning_content';
32
- currentIndex = -1;
33
- blockThreshold = 4500;
34
- /** The run ID AKA the Message ID associated with the complete generation */
35
- runId: string;
36
- handlers?: t.SplitStreamHandlers;
37
- constructor({
38
- runId,
39
- handlers,
40
- accumulate,
41
- reasoningKey,
42
- blockThreshold,
43
- }: {
44
- runId: string;
45
- accumulate?: boolean;
46
- handlers: t.SplitStreamHandlers;
47
- blockThreshold?: number;
48
- reasoningKey?: 'reasoning_content' | 'reasoning';
49
- }) {
50
- this.runId = runId;
51
- this.handlers = handlers;
52
- if (reasoningKey) {
53
- this.reasoningKey = reasoningKey;
54
- }
55
- if (blockThreshold != null) {
56
- this.blockThreshold = blockThreshold;
57
- }
58
- this.accumulate = accumulate ?? false;
59
- }
60
- getMessageId = (): string | undefined => {
61
- const messageId = this.currentMessageId;
62
- if (messageId != null && messageId) {
63
- return messageId;
64
- }
65
- return undefined;
66
- };
67
- createMessageStep = (
68
- type?: ContentTypes.TEXT | ContentTypes.THINK
69
- ): [string, string] => {
70
- if (type != null && this.currentType !== type) {
71
- this.currentType = type;
72
- }
73
- this.currentLength = 0;
74
- this.currentIndex += 1;
75
- this.currentStepId = `step_${nanoid()}`;
76
- this.currentMessageId = `msg_${nanoid()}`;
77
- return [this.currentStepId, this.currentMessageId];
78
- };
79
- dispatchRunStep = (stepId: string, stepDetails: t.StepDetails): void => {
80
- const runStep: t.RunStep = {
81
- id: stepId,
82
- runId: this.runId,
83
- type: stepDetails.type,
84
- index: this.currentIndex,
85
- stepDetails,
86
- // usage: null,
87
- };
88
- this.handlers?.[GraphEvents.ON_RUN_STEP]?.({
89
- event: GraphEvents.ON_RUN_STEP,
90
- data: runStep,
91
- });
92
- };
93
- dispatchMessageDelta = (stepId: string, delta: t.MessageDelta): void => {
94
- const messageDelta: t.MessageDeltaEvent = {
95
- id: stepId,
96
- delta,
97
- };
98
- this.handlers?.[GraphEvents.ON_MESSAGE_DELTA]?.({
99
- event: GraphEvents.ON_MESSAGE_DELTA,
100
- data: messageDelta,
101
- });
102
- };
103
- dispatchReasoningDelta = (stepId: string, delta: t.ReasoningDelta): void => {
104
- const reasoningDelta: t.ReasoningDeltaEvent = {
105
- id: stepId,
106
- delta,
107
- };
108
- this.handlers?.[GraphEvents.ON_REASONING_DELTA]?.({
109
- event: GraphEvents.ON_REASONING_DELTA,
110
- data: reasoningDelta,
111
- });
112
- };
113
- handleContent = (
114
- content: string,
115
- _type: ContentTypes.TEXT | ContentTypes.THINK
116
- ): void => {
117
- let type = _type;
118
- if (this.inThinkBlock && type === ContentTypes.TEXT) {
119
- type = ContentTypes.THINK;
120
- }
121
- if (this.accumulate) {
122
- if (type === ContentTypes.THINK) {
123
- this.reasoningTokens.push(content);
124
- } else {
125
- this.tokens.push(content);
126
- }
127
- }
128
-
129
- if (this.currentType !== type) {
130
- const [newStepId, newMessageId] = this.createMessageStep(type);
131
- this.dispatchRunStep(newStepId, {
132
- type: StepTypes.MESSAGE_CREATION,
133
- message_creation: {
134
- message_id: newMessageId,
135
- },
136
- });
137
- }
138
-
139
- const stepId = this.currentStepId ?? '';
140
- if (type === ContentTypes.THINK) {
141
- this.dispatchReasoningDelta(stepId, {
142
- content: [
143
- {
144
- type: ContentTypes.THINK,
145
- think: content,
146
- },
147
- ],
148
- });
149
- } else {
150
- this.dispatchMessageDelta(stepId, {
151
- content: [
152
- {
153
- type: ContentTypes.TEXT,
154
- text: content,
155
- },
156
- ],
157
- });
158
- }
159
-
160
- this.currentLength += content.length;
161
- if (this.inCodeBlock) {
162
- return;
163
- }
164
-
165
- if (
166
- this.currentLength > this.blockThreshold &&
167
- SEPARATORS.some((sep) => content.includes(sep))
168
- ) {
169
- const [newStepId, newMessageId] = this.createMessageStep(type);
170
- this.dispatchRunStep(newStepId, {
171
- type: StepTypes.MESSAGE_CREATION,
172
- message_creation: {
173
- message_id: newMessageId,
174
- },
175
- });
176
- }
177
- };
178
- getDeltaContent(chunk?: t.CustomChunk): string {
179
- return (chunk?.choices?.[0]?.delta as t.CustomChunkDelta)?.content ?? '';
180
- }
181
- getReasoningDelta(chunk?: t.CustomChunk): string {
182
- return (
183
- (chunk?.choices?.[0]?.delta as t.CustomChunkDelta)?.[this.reasoningKey] ??
184
- ''
185
- );
186
- }
187
- handle(chunk?: t.CustomChunk): void {
188
- if (!chunk) {
189
- return;
190
- }
191
-
192
- const content = this.getDeltaContent(chunk);
193
- const reasoning_content = this.getReasoningDelta(chunk);
194
- if (!content.length && !reasoning_content.length) {
195
- return;
196
- }
197
-
198
- if (content.includes('```')) {
199
- this.inCodeBlock = !this.inCodeBlock;
200
- }
201
-
202
- if (content.includes('<think>') && !this.inCodeBlock) {
203
- this.inThinkBlock = true;
204
- } else if (this.lastToken.includes('</think>') && !this.inCodeBlock) {
205
- this.inThinkBlock = false;
206
- }
207
-
208
- this.lastToken = content;
209
-
210
- const message_id = this.getMessageId() ?? '';
211
-
212
- if (!message_id) {
213
- const initialContentType = this.inThinkBlock
214
- ? ContentTypes.THINK
215
- : ContentTypes.TEXT;
216
- const initialType = reasoning_content
217
- ? ContentTypes.THINK
218
- : initialContentType;
219
- const [stepId, message_id] = this.createMessageStep(initialType);
220
- this.dispatchRunStep(stepId, {
221
- type: StepTypes.MESSAGE_CREATION,
222
- message_creation: {
223
- message_id,
224
- },
225
- });
226
- }
227
-
228
- if (reasoning_content) {
229
- this.handleContent(reasoning_content, ContentTypes.THINK);
230
- } else {
231
- this.handleContent(content, ContentTypes.TEXT);
232
- }
233
- }
234
- }