@uncensoredcode/openbridge 0.1.0

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 (145) hide show
  1. package/README.md +117 -0
  2. package/bin/openbridge.js +10 -0
  3. package/package.json +85 -0
  4. package/packages/cli/dist/args.d.ts +30 -0
  5. package/packages/cli/dist/args.js +160 -0
  6. package/packages/cli/dist/cli.d.ts +2 -0
  7. package/packages/cli/dist/cli.js +9 -0
  8. package/packages/cli/dist/index.d.ts +26 -0
  9. package/packages/cli/dist/index.js +76 -0
  10. package/packages/runtime/dist/assistant-protocol.d.ts +34 -0
  11. package/packages/runtime/dist/assistant-protocol.js +121 -0
  12. package/packages/runtime/dist/execution/in-process.d.ts +14 -0
  13. package/packages/runtime/dist/execution/in-process.js +45 -0
  14. package/packages/runtime/dist/execution/types.d.ts +49 -0
  15. package/packages/runtime/dist/execution/types.js +20 -0
  16. package/packages/runtime/dist/index.d.ts +86 -0
  17. package/packages/runtime/dist/index.js +60 -0
  18. package/packages/runtime/dist/normalizers/index.d.ts +6 -0
  19. package/packages/runtime/dist/normalizers/index.js +12 -0
  20. package/packages/runtime/dist/normalizers/legacy-packet.d.ts +6 -0
  21. package/packages/runtime/dist/normalizers/legacy-packet.js +131 -0
  22. package/packages/runtime/dist/output-sanitizer.d.ts +23 -0
  23. package/packages/runtime/dist/output-sanitizer.js +78 -0
  24. package/packages/runtime/dist/packet-extractor.d.ts +17 -0
  25. package/packages/runtime/dist/packet-extractor.js +43 -0
  26. package/packages/runtime/dist/packet-normalizer.d.ts +21 -0
  27. package/packages/runtime/dist/packet-normalizer.js +47 -0
  28. package/packages/runtime/dist/prompt-compiler.d.ts +28 -0
  29. package/packages/runtime/dist/prompt-compiler.js +301 -0
  30. package/packages/runtime/dist/protocol.d.ts +44 -0
  31. package/packages/runtime/dist/protocol.js +165 -0
  32. package/packages/runtime/dist/provider-failure.d.ts +52 -0
  33. package/packages/runtime/dist/provider-failure.js +236 -0
  34. package/packages/runtime/dist/provider.d.ts +40 -0
  35. package/packages/runtime/dist/provider.js +1 -0
  36. package/packages/runtime/dist/runtime.d.ts +86 -0
  37. package/packages/runtime/dist/runtime.js +462 -0
  38. package/packages/runtime/dist/session-bound-provider.d.ts +52 -0
  39. package/packages/runtime/dist/session-bound-provider.js +366 -0
  40. package/packages/runtime/dist/tool-name-aliases.d.ts +5 -0
  41. package/packages/runtime/dist/tool-name-aliases.js +13 -0
  42. package/packages/runtime/dist/tools/bash.d.ts +9 -0
  43. package/packages/runtime/dist/tools/bash.js +157 -0
  44. package/packages/runtime/dist/tools/edit.d.ts +9 -0
  45. package/packages/runtime/dist/tools/edit.js +94 -0
  46. package/packages/runtime/dist/tools/index.d.ts +39 -0
  47. package/packages/runtime/dist/tools/index.js +27 -0
  48. package/packages/runtime/dist/tools/list-dir.d.ts +9 -0
  49. package/packages/runtime/dist/tools/list-dir.js +127 -0
  50. package/packages/runtime/dist/tools/read.d.ts +9 -0
  51. package/packages/runtime/dist/tools/read.js +56 -0
  52. package/packages/runtime/dist/tools/registry.d.ts +15 -0
  53. package/packages/runtime/dist/tools/registry.js +38 -0
  54. package/packages/runtime/dist/tools/runtime-path.d.ts +7 -0
  55. package/packages/runtime/dist/tools/runtime-path.js +22 -0
  56. package/packages/runtime/dist/tools/search-files.d.ts +9 -0
  57. package/packages/runtime/dist/tools/search-files.js +149 -0
  58. package/packages/runtime/dist/tools/text-file.d.ts +32 -0
  59. package/packages/runtime/dist/tools/text-file.js +101 -0
  60. package/packages/runtime/dist/tools/workspace-path.d.ts +17 -0
  61. package/packages/runtime/dist/tools/workspace-path.js +70 -0
  62. package/packages/runtime/dist/tools/write.d.ts +9 -0
  63. package/packages/runtime/dist/tools/write.js +59 -0
  64. package/packages/server/dist/bridge/bridge-model-catalog.d.ts +56 -0
  65. package/packages/server/dist/bridge/bridge-model-catalog.js +100 -0
  66. package/packages/server/dist/bridge/bridge-runtime-service.d.ts +61 -0
  67. package/packages/server/dist/bridge/bridge-runtime-service.js +1386 -0
  68. package/packages/server/dist/bridge/chat-completions/chat-completion-service.d.ts +127 -0
  69. package/packages/server/dist/bridge/chat-completions/chat-completion-service.js +1026 -0
  70. package/packages/server/dist/bridge/index.d.ts +335 -0
  71. package/packages/server/dist/bridge/index.js +45 -0
  72. package/packages/server/dist/bridge/live-provider-extraction-canary.d.ts +69 -0
  73. package/packages/server/dist/bridge/live-provider-extraction-canary.js +186 -0
  74. package/packages/server/dist/bridge/providers/generic-provider-transport.d.ts +53 -0
  75. package/packages/server/dist/bridge/providers/generic-provider-transport.js +973 -0
  76. package/packages/server/dist/bridge/providers/provider-session-resolver.d.ts +17 -0
  77. package/packages/server/dist/bridge/providers/provider-session-resolver.js +95 -0
  78. package/packages/server/dist/bridge/providers/provider-streams.d.ts +80 -0
  79. package/packages/server/dist/bridge/providers/provider-streams.js +844 -0
  80. package/packages/server/dist/bridge/providers/provider-transport-profile.d.ts +194 -0
  81. package/packages/server/dist/bridge/providers/provider-transport-profile.js +198 -0
  82. package/packages/server/dist/bridge/providers/web-provider-transport.d.ts +30 -0
  83. package/packages/server/dist/bridge/providers/web-provider-transport.js +151 -0
  84. package/packages/server/dist/bridge/state/file-bridge-state-store.d.ts +36 -0
  85. package/packages/server/dist/bridge/state/file-bridge-state-store.js +164 -0
  86. package/packages/server/dist/bridge/stores/local-session-package-store.d.ts +23 -0
  87. package/packages/server/dist/bridge/stores/local-session-package-store.js +548 -0
  88. package/packages/server/dist/bridge/stores/provider-store.d.ts +94 -0
  89. package/packages/server/dist/bridge/stores/provider-store.js +143 -0
  90. package/packages/server/dist/bridge/stores/session-backed-provider-store.d.ts +7 -0
  91. package/packages/server/dist/bridge/stores/session-backed-provider-store.js +26 -0
  92. package/packages/server/dist/bridge/stores/session-package-store.d.ts +286 -0
  93. package/packages/server/dist/bridge/stores/session-package-store.js +1527 -0
  94. package/packages/server/dist/bridge/stores/session-store.d.ts +120 -0
  95. package/packages/server/dist/bridge/stores/session-store.js +139 -0
  96. package/packages/server/dist/cli/index.d.ts +9 -0
  97. package/packages/server/dist/cli/index.js +6 -0
  98. package/packages/server/dist/cli/main.d.ts +2 -0
  99. package/packages/server/dist/cli/main.js +9 -0
  100. package/packages/server/dist/cli/run-bridge-server-cli.d.ts +54 -0
  101. package/packages/server/dist/cli/run-bridge-server-cli.js +371 -0
  102. package/packages/server/dist/client/bridge-api-client.d.ts +61 -0
  103. package/packages/server/dist/client/bridge-api-client.js +267 -0
  104. package/packages/server/dist/client/index.d.ts +11 -0
  105. package/packages/server/dist/client/index.js +11 -0
  106. package/packages/server/dist/config/bridge-server-config.d.ts +52 -0
  107. package/packages/server/dist/config/bridge-server-config.js +118 -0
  108. package/packages/server/dist/config/index.d.ts +20 -0
  109. package/packages/server/dist/config/index.js +8 -0
  110. package/packages/server/dist/http/bridge-api-route-context.d.ts +14 -0
  111. package/packages/server/dist/http/bridge-api-route-context.js +1 -0
  112. package/packages/server/dist/http/create-bridge-api-server.d.ts +72 -0
  113. package/packages/server/dist/http/create-bridge-api-server.js +225 -0
  114. package/packages/server/dist/http/index.d.ts +5 -0
  115. package/packages/server/dist/http/index.js +5 -0
  116. package/packages/server/dist/http/parse-request.d.ts +6 -0
  117. package/packages/server/dist/http/parse-request.js +27 -0
  118. package/packages/server/dist/http/register-bridge-api-routes.d.ts +7 -0
  119. package/packages/server/dist/http/register-bridge-api-routes.js +17 -0
  120. package/packages/server/dist/http/routes/admin-routes.d.ts +7 -0
  121. package/packages/server/dist/http/routes/admin-routes.js +135 -0
  122. package/packages/server/dist/http/routes/chat-completions-route.d.ts +7 -0
  123. package/packages/server/dist/http/routes/chat-completions-route.js +49 -0
  124. package/packages/server/dist/http/routes/health-routes.d.ts +6 -0
  125. package/packages/server/dist/http/routes/health-routes.js +7 -0
  126. package/packages/server/dist/http/routes/message-routes.d.ts +7 -0
  127. package/packages/server/dist/http/routes/message-routes.js +7 -0
  128. package/packages/server/dist/index.d.ts +85 -0
  129. package/packages/server/dist/index.js +28 -0
  130. package/packages/server/dist/security/bridge-auth.d.ts +9 -0
  131. package/packages/server/dist/security/bridge-auth.js +41 -0
  132. package/packages/server/dist/security/cors-policy.d.ts +5 -0
  133. package/packages/server/dist/security/cors-policy.js +34 -0
  134. package/packages/server/dist/security/index.d.ts +16 -0
  135. package/packages/server/dist/security/index.js +12 -0
  136. package/packages/server/dist/security/redact-sensitive-values.d.ts +19 -0
  137. package/packages/server/dist/security/redact-sensitive-values.js +67 -0
  138. package/packages/server/dist/shared/api-schema.d.ts +133 -0
  139. package/packages/server/dist/shared/api-schema.js +1 -0
  140. package/packages/server/dist/shared/bridge-api-error.d.ts +17 -0
  141. package/packages/server/dist/shared/bridge-api-error.js +19 -0
  142. package/packages/server/dist/shared/index.d.ts +7 -0
  143. package/packages/server/dist/shared/index.js +7 -0
  144. package/packages/server/dist/shared/output.d.ts +5 -0
  145. package/packages/server/dist/shared/output.js +14 -0
@@ -0,0 +1,844 @@
1
+ import { bridgeRuntime } from "@uncensoredcode/openbridge/runtime";
2
+ import { outputModule } from "../../shared/output.js";
3
+ const { extractPacketMessage, ProviderFailure } = bridgeRuntime;
4
+ const { sanitizeBridgeApiOutput } = outputModule;
5
+ async function collectSseCompletion(stream, pushEvent, finalizeContent) {
6
+ const completion = await collectProviderCompletion(stream, pushEvent);
7
+ return {
8
+ ...completion,
9
+ content: finalizeContent ? finalizeContent(completion.content) : completion.content
10
+ };
11
+ }
12
+ async function* streamSseFragments(stream, pushEvent, onComplete) {
13
+ yield* streamProviderFragments(stream, pushEvent, onComplete);
14
+ }
15
+ async function* streamVisibleProviderCompletion(stream, pushEvent, onComplete) {
16
+ const rawFragments = [];
17
+ let emittedContent = "";
18
+ for await (const fragment of streamProviderFragments(stream, pushEvent, onComplete)) {
19
+ rawFragments.push(fragment.content);
20
+ const visibleContent = extractIncrementalPacketMessage(rawFragments.join(""));
21
+ if (visibleContent.startsWith(emittedContent) &&
22
+ visibleContent.length > emittedContent.length) {
23
+ const delta = visibleContent.slice(emittedContent.length);
24
+ emittedContent = visibleContent;
25
+ yield delta;
26
+ }
27
+ }
28
+ const finalContent = sanitizeBridgeApiOutput(rawFragments.join("")).content;
29
+ if (finalContent.startsWith(emittedContent) && finalContent.length > emittedContent.length) {
30
+ yield finalContent.slice(emittedContent.length);
31
+ }
32
+ else if (!emittedContent && finalContent) {
33
+ yield finalContent;
34
+ }
35
+ }
36
+ function createSseJsonEventParser(input) {
37
+ const contentPaths = input.contentPaths.map((path) => splitPath(path));
38
+ const responseIdPaths = (input.responseIdPaths ?? []).map((path) => splitPath(path));
39
+ const conversationIdPaths = (input.conversationIdPaths ?? []).map((path) => splitPath(path));
40
+ const eventFilters = (input.eventFilters ?? []).map((filter) => ({
41
+ path: splitPath(filter.path),
42
+ equals: filter.equals
43
+ }));
44
+ const patchState = createPatchContentState();
45
+ return (parts, rawLine, currentResponseId, currentConversationId) => {
46
+ const line = rawLine.trim();
47
+ if (!line || line.startsWith("event:")) {
48
+ return {
49
+ responseId: currentResponseId,
50
+ conversationId: currentConversationId,
51
+ eventCountDelta: 0,
52
+ fragmentCountDelta: 0
53
+ };
54
+ }
55
+ const normalized = line.startsWith("data:") ? line.slice("data:".length).trim() : line;
56
+ if (!normalized || normalized === "[DONE]") {
57
+ return {
58
+ responseId: currentResponseId,
59
+ conversationId: currentConversationId,
60
+ eventCountDelta: 0,
61
+ fragmentCountDelta: 0
62
+ };
63
+ }
64
+ try {
65
+ const payload = JSON.parse(normalized);
66
+ const responseId = extractConfiguredString(payload, responseIdPaths) || currentResponseId;
67
+ const conversationId = extractConfiguredString(payload, conversationIdPaths) || currentConversationId;
68
+ if (!matchesEventFilters(payload, eventFilters)) {
69
+ return {
70
+ responseId,
71
+ conversationId,
72
+ eventCountDelta: 0,
73
+ fragmentCountDelta: 0
74
+ };
75
+ }
76
+ const fragments = extractConfiguredFragments(payload, contentPaths);
77
+ const patchedFragments = fragments.length === 0 ? extractPatchedContentFragments(payload, patchState) : [];
78
+ if (patchedFragments.length > 0) {
79
+ fragments.push(...patchedFragments);
80
+ }
81
+ parts.push(...fragments);
82
+ return {
83
+ responseId,
84
+ conversationId,
85
+ eventCountDelta: 1,
86
+ fragmentCountDelta: fragments.length
87
+ };
88
+ }
89
+ catch {
90
+ return {
91
+ responseId: currentResponseId,
92
+ conversationId: currentConversationId,
93
+ eventCountDelta: 0,
94
+ fragmentCountDelta: 0
95
+ };
96
+ }
97
+ };
98
+ }
99
+ async function collectConnectJsonCompletion(stream, input, finalizeContent) {
100
+ const completion = await collectConnectProviderCompletion(stream, input);
101
+ return {
102
+ ...completion,
103
+ content: finalizeContent ? finalizeContent(completion.content) : completion.content
104
+ };
105
+ }
106
+ async function* streamConnectJsonFragments(stream, input, onComplete) {
107
+ yield* streamConnectProviderFragments(stream, input, onComplete);
108
+ }
109
+ function extractIncrementalPacketMessage(content) {
110
+ const finalStart = content.search(/<final>/i);
111
+ if (finalStart >= 0) {
112
+ const finalContent = content.slice(finalStart + "<final>".length);
113
+ const finalEnd = finalContent.search(/<\/final>/i);
114
+ return finalEnd >= 0 ? finalContent.slice(0, finalEnd) : finalContent;
115
+ }
116
+ const packetStart = content.search(/<(?:zc_packet|packet)\b/i);
117
+ if (packetStart < 0) {
118
+ return "";
119
+ }
120
+ const packetContent = content.slice(packetStart);
121
+ const messageStartMatch = packetContent.match(/<message>/i);
122
+ if (!messageStartMatch) {
123
+ return "";
124
+ }
125
+ const messageStartIndex = (messageStartMatch.index ?? 0) + messageStartMatch[0].length;
126
+ const messageBody = packetContent.slice(messageStartIndex);
127
+ if (/^<!\[CDATA\[/i.test(messageBody)) {
128
+ const cdataBody = messageBody.slice("<![CDATA[".length);
129
+ const cdataEnd = cdataBody.indexOf("]]>");
130
+ return cdataEnd >= 0 ? (extractPacketMessage(packetContent) ?? "") : cdataBody;
131
+ }
132
+ const messageEnd = messageBody.search(/<\/message>/i);
133
+ if (messageEnd >= 0) {
134
+ const messageContent = messageBody.slice(0, messageEnd);
135
+ return /</.test(messageContent) ? "" : messageContent;
136
+ }
137
+ return /</.test(messageBody) ? "" : messageBody;
138
+ }
139
+ function normalizeLeadingAssistantBlock(content) {
140
+ const trimmed = content.trim();
141
+ return (extractLeadingSimpleAssistantBlock(trimmed, "final") ??
142
+ extractLeadingSimpleAssistantBlock(trimmed, "tool") ??
143
+ extractLatestSimpleAssistantBlock(trimmed) ??
144
+ trimmed);
145
+ }
146
+ async function collectProviderCompletion(stream, pushEvent) {
147
+ if (!stream) {
148
+ return {
149
+ content: "",
150
+ responseId: "",
151
+ conversationId: "",
152
+ eventCount: 0,
153
+ fragmentCount: 0
154
+ };
155
+ }
156
+ const reader = stream.getReader();
157
+ const decoder = new TextDecoder();
158
+ let buffer = "";
159
+ const parts = [];
160
+ let responseId = "";
161
+ let conversationId = "";
162
+ let eventCount = 0;
163
+ let fragmentCount = 0;
164
+ while (true) {
165
+ const { done, value } = await reader.read();
166
+ if (done) {
167
+ break;
168
+ }
169
+ buffer += decoder.decode(value, { stream: true });
170
+ const lines = buffer.split("\n");
171
+ buffer = lines.pop() ?? "";
172
+ for (const rawLine of lines) {
173
+ const result = pushEvent(parts, rawLine, responseId, conversationId);
174
+ responseId = result.responseId;
175
+ conversationId = result.conversationId;
176
+ eventCount += result.eventCountDelta;
177
+ fragmentCount += result.fragmentCountDelta;
178
+ }
179
+ }
180
+ const finalResult = pushEvent(parts, buffer, responseId, conversationId);
181
+ return {
182
+ content: parts.join("").trim(),
183
+ responseId: finalResult.responseId,
184
+ conversationId: finalResult.conversationId,
185
+ eventCount: eventCount + finalResult.eventCountDelta,
186
+ fragmentCount: fragmentCount + finalResult.fragmentCountDelta
187
+ };
188
+ }
189
+ async function* streamProviderFragments(stream, pushEvent, onComplete) {
190
+ const rawFragments = [];
191
+ let responseId = "";
192
+ let conversationId = "";
193
+ let eventCount = 0;
194
+ let fragmentCount = 0;
195
+ for await (const fragment of iterateProviderFragments(stream, pushEvent)) {
196
+ rawFragments.push(fragment.content);
197
+ responseId = fragment.responseId;
198
+ conversationId = fragment.conversationId;
199
+ eventCount += fragment.eventCountDelta;
200
+ fragmentCount += fragment.fragmentCountDelta;
201
+ yield fragment;
202
+ }
203
+ onComplete?.({
204
+ content: rawFragments.join("").trim(),
205
+ responseId,
206
+ conversationId,
207
+ eventCount,
208
+ fragmentCount
209
+ });
210
+ }
211
+ async function* iterateProviderFragments(stream, pushEvent) {
212
+ if (!stream) {
213
+ return;
214
+ }
215
+ const reader = stream.getReader();
216
+ const decoder = new TextDecoder();
217
+ let buffer = "";
218
+ let responseId = "";
219
+ let conversationId = "";
220
+ while (true) {
221
+ const { done, value } = await reader.read();
222
+ if (done) {
223
+ break;
224
+ }
225
+ buffer += decoder.decode(value, { stream: true });
226
+ const lines = buffer.split("\n");
227
+ buffer = lines.pop() ?? "";
228
+ for (const rawLine of lines) {
229
+ const parts = [];
230
+ const result = pushEvent(parts, rawLine, responseId, conversationId);
231
+ responseId = result.responseId;
232
+ conversationId = result.conversationId;
233
+ for (const fragment of parts) {
234
+ if (fragment) {
235
+ yield {
236
+ content: fragment,
237
+ responseId,
238
+ conversationId,
239
+ eventCountDelta: result.eventCountDelta,
240
+ fragmentCountDelta: result.fragmentCountDelta
241
+ };
242
+ }
243
+ }
244
+ }
245
+ }
246
+ const parts = [];
247
+ const result = pushEvent(parts, buffer, responseId, conversationId);
248
+ responseId = result.responseId;
249
+ conversationId = result.conversationId;
250
+ for (const fragment of parts) {
251
+ if (fragment) {
252
+ yield {
253
+ content: fragment,
254
+ responseId,
255
+ conversationId,
256
+ eventCountDelta: result.eventCountDelta,
257
+ fragmentCountDelta: result.fragmentCountDelta
258
+ };
259
+ }
260
+ }
261
+ }
262
+ async function collectConnectProviderCompletion(stream, input) {
263
+ const fragments = [];
264
+ let responseId = "";
265
+ let conversationId = "";
266
+ let eventCount = 0;
267
+ let fragmentCount = 0;
268
+ for await (const fragment of iterateConnectProviderFragments(stream, input)) {
269
+ fragments.push(fragment.content);
270
+ responseId = fragment.responseId;
271
+ conversationId = fragment.conversationId;
272
+ eventCount += fragment.eventCountDelta;
273
+ fragmentCount += fragment.fragmentCountDelta;
274
+ }
275
+ return {
276
+ content: fragments.join("").trim(),
277
+ responseId,
278
+ conversationId,
279
+ eventCount,
280
+ fragmentCount
281
+ };
282
+ }
283
+ async function* streamConnectProviderFragments(stream, input, onComplete) {
284
+ const rawFragments = [];
285
+ let responseId = "";
286
+ let conversationId = "";
287
+ let eventCount = 0;
288
+ let fragmentCount = 0;
289
+ for await (const fragment of iterateConnectProviderFragments(stream, input)) {
290
+ rawFragments.push(fragment.content);
291
+ responseId = fragment.responseId;
292
+ conversationId = fragment.conversationId;
293
+ eventCount += fragment.eventCountDelta;
294
+ fragmentCount += fragment.fragmentCountDelta;
295
+ yield fragment;
296
+ }
297
+ onComplete?.({
298
+ content: rawFragments.join("").trim(),
299
+ responseId,
300
+ conversationId,
301
+ eventCount,
302
+ fragmentCount
303
+ });
304
+ }
305
+ async function* iterateConnectProviderFragments(stream, input) {
306
+ if (!stream) {
307
+ return;
308
+ }
309
+ const reader = stream.getReader();
310
+ let buffer = new Uint8Array(0);
311
+ const contentPaths = input.contentPaths.map((path) => splitPath(path));
312
+ const responseIdPaths = (input.responseIdPaths ?? []).map((path) => splitPath(path));
313
+ const conversationIdPaths = (input.conversationIdPaths ?? []).map((path) => splitPath(path));
314
+ const eventFilters = (input.eventFilters ?? []).map((filter) => ({
315
+ path: splitPath(filter.path),
316
+ equals: filter.equals
317
+ }));
318
+ let responseId = "";
319
+ let conversationId = "";
320
+ while (true) {
321
+ const { done, value } = await reader.read();
322
+ if (done) {
323
+ break;
324
+ }
325
+ buffer = concatUint8Arrays(buffer, value);
326
+ while (buffer.length >= 5) {
327
+ const messageLength = readConnectEnvelopeLength(buffer);
328
+ const totalLength = 5 + messageLength;
329
+ if (buffer.length < totalLength) {
330
+ break;
331
+ }
332
+ const envelope = buffer.slice(0, totalLength);
333
+ buffer = buffer.slice(totalLength);
334
+ const fragment = parseConnectEnvelope(envelope, contentPaths, responseIdPaths, conversationIdPaths, eventFilters, responseId, conversationId);
335
+ if (!fragment) {
336
+ continue;
337
+ }
338
+ responseId = fragment.responseId;
339
+ conversationId = fragment.conversationId;
340
+ yield fragment;
341
+ }
342
+ }
343
+ if (buffer.length > 0) {
344
+ throw new ProviderFailure({
345
+ kind: "permanent",
346
+ code: "request_invalid",
347
+ message: "Provider returned a truncated Connect stream.",
348
+ displayMessage: "Provider response format is invalid.",
349
+ retryable: false,
350
+ sessionResetEligible: false
351
+ });
352
+ }
353
+ }
354
+ function extractLeadingSimpleAssistantBlock(content, tag) {
355
+ const openTag = `<${tag}>`;
356
+ const closeTag = `</${tag}>`;
357
+ if (!content.startsWith(openTag)) {
358
+ return null;
359
+ }
360
+ const closeIndex = content.indexOf(closeTag);
361
+ if (closeIndex < 0) {
362
+ return null;
363
+ }
364
+ const inner = content.slice(openTag.length, closeIndex);
365
+ if (containsNestedAssistantBlockMarker(inner)) {
366
+ return null;
367
+ }
368
+ const block = content.slice(0, closeIndex + closeTag.length);
369
+ const trailing = content.slice(closeIndex + closeTag.length).trim();
370
+ if (!trailing) {
371
+ return block;
372
+ }
373
+ return trailing.includes("<") ? null : block;
374
+ }
375
+ function containsNestedAssistantBlockMarker(content) {
376
+ return /<(?:final|tool)>/i.test(content) || /(?:^|[^<])(?:final|tool)>/i.test(content);
377
+ }
378
+ function extractLatestSimpleAssistantBlock(content) {
379
+ const finalBlock = extractLastSimpleAssistantBlock(content, "final");
380
+ const toolBlock = extractLastSimpleAssistantBlock(content, "tool");
381
+ if (!finalBlock) {
382
+ return toolBlock?.block ?? null;
383
+ }
384
+ if (!toolBlock) {
385
+ return finalBlock.block;
386
+ }
387
+ return finalBlock.index >= toolBlock.index ? finalBlock.block : toolBlock.block;
388
+ }
389
+ function extractLastSimpleAssistantBlock(content, tag) {
390
+ const closeTag = `</${tag}>`;
391
+ const closeIndex = content.lastIndexOf(closeTag);
392
+ if (closeIndex < 0) {
393
+ return null;
394
+ }
395
+ const marker = new RegExp(`(?:<)?${tag}>`, "gi");
396
+ let latestMatch = null;
397
+ for (const match of content.matchAll(marker)) {
398
+ const index = match.index ?? -1;
399
+ if (index < 0 || index >= closeIndex) {
400
+ continue;
401
+ }
402
+ latestMatch = {
403
+ index,
404
+ markerLength: match[0].length
405
+ };
406
+ }
407
+ if (!latestMatch) {
408
+ return null;
409
+ }
410
+ return {
411
+ index: latestMatch.index,
412
+ block: `<${tag}>${content.slice(latestMatch.index + latestMatch.markerLength, closeIndex)}${closeTag}`
413
+ };
414
+ }
415
+ function splitPath(path) {
416
+ return path
417
+ .split(".")
418
+ .map((segment) => segment.trim())
419
+ .filter(Boolean);
420
+ }
421
+ function extractConfiguredString(payload, paths) {
422
+ for (const path of paths) {
423
+ for (const value of extractPathValues(payload, path)) {
424
+ const normalized = normalizeProviderResponseId(value);
425
+ if (normalized) {
426
+ return normalized;
427
+ }
428
+ }
429
+ }
430
+ return "";
431
+ }
432
+ function extractConfiguredFragments(payload, paths) {
433
+ const fragments = [];
434
+ const filteredPaths = filterNonAssistantMessageContentPaths(payload, paths);
435
+ for (const path of filteredPaths) {
436
+ for (const value of extractPathValues(payload, path)) {
437
+ if (typeof value === "string" && value) {
438
+ const normalized = normalizeProviderContentFragment(value);
439
+ if (normalized) {
440
+ fragments.push(normalized);
441
+ }
442
+ }
443
+ }
444
+ }
445
+ return fragments;
446
+ }
447
+ function createPatchContentState() {
448
+ return {
449
+ fragmentTypes: new Map(),
450
+ pendingContent: new Map(),
451
+ currentPath: "",
452
+ currentOp: "SET",
453
+ collectionLastIndex: new Map()
454
+ };
455
+ }
456
+ function extractPatchedContentFragments(payload, state) {
457
+ const fragments = [];
458
+ for (const operation of flattenPatchOperations(payload, state)) {
459
+ collectPatchContentFromStructuredValue(operation.value, state, fragments);
460
+ const fragmentPath = parseResponseFragmentPath(operation.path, state);
461
+ if (!fragmentPath) {
462
+ continue;
463
+ }
464
+ if (fragmentPath.kind === "collection") {
465
+ collectFragmentArray(fragmentPath.basePath, operation.value, state, fragments, operation.op);
466
+ continue;
467
+ }
468
+ if (fragmentPath.kind === "fragment") {
469
+ collectFragmentRecord(fragmentPath.basePath, operation.value, state, fragments);
470
+ continue;
471
+ }
472
+ if (fragmentPath.kind === "field" &&
473
+ fragmentPath.field === "type" &&
474
+ typeof operation.value === "string") {
475
+ setFragmentType(fragmentPath.basePath, operation.value, state, fragments);
476
+ continue;
477
+ }
478
+ if (fragmentPath.kind === "field" &&
479
+ fragmentPath.field === "content" &&
480
+ typeof operation.value === "string") {
481
+ pushFragmentContent(fragmentPath.basePath, operation.value, state, fragments);
482
+ }
483
+ }
484
+ return fragments;
485
+ }
486
+ function flattenPatchOperations(payload, state) {
487
+ const parserState = {
488
+ path: state.currentPath,
489
+ op: state.currentOp
490
+ };
491
+ const operations = flattenPatchOperation({
492
+ p: typeof payload.p === "string" ? payload.p : "",
493
+ o: typeof payload.o === "string" ? payload.o : "",
494
+ v: "v" in payload ? payload.v : payload
495
+ }, parserState);
496
+ state.currentPath = parserState.path;
497
+ state.currentOp = parserState.op;
498
+ return operations;
499
+ }
500
+ function flattenPatchOperation(input, parserState) {
501
+ const operation = input.o.trim().toUpperCase() || parserState.op || "SET";
502
+ const path = input.p.trim() || parserState.path || "";
503
+ parserState.op = operation;
504
+ parserState.path = path;
505
+ if (operation !== "BATCH") {
506
+ return [
507
+ {
508
+ path,
509
+ op: operation,
510
+ value: input.v
511
+ }
512
+ ];
513
+ }
514
+ if (!Array.isArray(input.v)) {
515
+ return [];
516
+ }
517
+ const batchState = {
518
+ path: "",
519
+ op: "SET"
520
+ };
521
+ return input.v.flatMap((entry) => {
522
+ if (!entry || typeof entry !== "object") {
523
+ return [];
524
+ }
525
+ const record = entry;
526
+ return flattenPatchOperation({
527
+ p: typeof record.p === "string" ? record.p : "",
528
+ o: typeof record.o === "string" ? record.o : "",
529
+ v: "v" in record ? record.v : record
530
+ }, batchState).map((nestedOperation) => ({
531
+ ...nestedOperation,
532
+ path: joinPatchPaths(path, nestedOperation.path)
533
+ }));
534
+ });
535
+ }
536
+ function joinPatchPaths(basePath, nextPath) {
537
+ if (!basePath) {
538
+ return nextPath;
539
+ }
540
+ if (!nextPath) {
541
+ return basePath;
542
+ }
543
+ const normalizedBase = basePath.endsWith("/") ? basePath.slice(0, -1) : basePath;
544
+ const normalizedNext = nextPath.startsWith("/") ? nextPath.slice(1) : nextPath;
545
+ return `${normalizedBase}/${normalizedNext}`;
546
+ }
547
+ function collectPatchContentFromStructuredValue(value, state, fragments) {
548
+ for (const [path, basePath] of [
549
+ ["response.fragments", "/response/fragments"],
550
+ ["v.response.fragments", "/response/fragments"],
551
+ ["fragments", "/response/fragments"]
552
+ ]) {
553
+ const fragmentArrays = extractPathValues(value, splitPath(path));
554
+ for (const fragmentArray of fragmentArrays) {
555
+ collectFragmentArray(basePath, fragmentArray, state, fragments, "SET");
556
+ }
557
+ }
558
+ }
559
+ function collectFragmentArray(basePath, value, state, fragments, operation) {
560
+ if (!Array.isArray(value)) {
561
+ return;
562
+ }
563
+ const startIndex = operation === "APPEND" ? (state.collectionLastIndex.get(basePath) ?? -1) + 1 : 0;
564
+ value.forEach((entry, index) => {
565
+ collectFragmentRecord(`${basePath}/${startIndex + index}`, entry, state, fragments);
566
+ });
567
+ state.collectionLastIndex.set(basePath, startIndex + value.length - 1);
568
+ }
569
+ function collectFragmentRecord(basePath, value, state, fragments) {
570
+ if (!value || typeof value !== "object") {
571
+ return;
572
+ }
573
+ const record = value;
574
+ const type = typeof record.type === "string" ? record.type : "";
575
+ if (type) {
576
+ setFragmentType(basePath, type, state, fragments);
577
+ }
578
+ if (typeof record.content === "string") {
579
+ pushFragmentContent(basePath, record.content, state, fragments);
580
+ }
581
+ }
582
+ function setFragmentType(basePath, type, state, fragments) {
583
+ const normalizedType = type.trim().toUpperCase();
584
+ if (!normalizedType) {
585
+ return;
586
+ }
587
+ state.fragmentTypes.set(basePath, normalizedType);
588
+ const pending = state.pendingContent.get(basePath) ?? [];
589
+ state.pendingContent.delete(basePath);
590
+ if (!isVisibleResponseFragmentType(normalizedType)) {
591
+ return;
592
+ }
593
+ for (const content of pending) {
594
+ if (content) {
595
+ fragments.push(content);
596
+ }
597
+ }
598
+ }
599
+ function pushFragmentContent(basePath, content, state, fragments) {
600
+ if (!content) {
601
+ return;
602
+ }
603
+ const type = state.fragmentTypes.get(basePath);
604
+ if (!type) {
605
+ fragments.push(content);
606
+ return;
607
+ }
608
+ if (isVisibleResponseFragmentType(type)) {
609
+ fragments.push(content);
610
+ }
611
+ }
612
+ function isVisibleResponseFragmentType(type) {
613
+ return type === "RESPONSE" || type === "TEMPLATE_RESPONSE";
614
+ }
615
+ function parseResponseFragmentPath(path, state) {
616
+ const segments = path
617
+ .split("/")
618
+ .map((segment) => segment.trim())
619
+ .filter(Boolean);
620
+ if (segments.length === 0) {
621
+ return null;
622
+ }
623
+ const normalized = segments.map((segment) => segment.toLowerCase());
624
+ const rootOffset = normalized[0] === "response" ? 1 : 0;
625
+ if (normalized[rootOffset] !== "fragments") {
626
+ return null;
627
+ }
628
+ const basePathRoot = "/response/fragments";
629
+ if (normalized.length === rootOffset + 1) {
630
+ return {
631
+ kind: "collection",
632
+ basePath: basePathRoot
633
+ };
634
+ }
635
+ const fragmentIndexToken = normalized[rootOffset + 1] ?? "";
636
+ const fragmentIndex = fragmentIndexToken === "-1"
637
+ ? (state.collectionLastIndex.get(basePathRoot) ?? -1)
638
+ : Number.parseInt(fragmentIndexToken, 10);
639
+ if (!Number.isInteger(fragmentIndex)) {
640
+ return null;
641
+ }
642
+ const basePath = `${basePathRoot}/${fragmentIndex}`;
643
+ if (normalized.length === rootOffset + 2) {
644
+ return {
645
+ kind: "fragment",
646
+ basePath
647
+ };
648
+ }
649
+ return {
650
+ kind: "field",
651
+ basePath,
652
+ field: normalized[rootOffset + 2] ?? ""
653
+ };
654
+ }
655
+ function filterNonAssistantMessageContentPaths(payload, paths) {
656
+ const message = readProviderMessageRecord(payload);
657
+ if (!message || typeof message !== "object") {
658
+ return paths;
659
+ }
660
+ const role = readProviderMessageRole(message);
661
+ if (!role || role === "assistant") {
662
+ return paths;
663
+ }
664
+ return paths.filter((path) => path[0] !== "message");
665
+ }
666
+ function readProviderMessageRecord(payload) {
667
+ const direct = payload.message;
668
+ if (direct && typeof direct === "object") {
669
+ return direct;
670
+ }
671
+ const nestedValue = payload.v;
672
+ if (!nestedValue || typeof nestedValue !== "object") {
673
+ return null;
674
+ }
675
+ const nestedMessage = nestedValue.message;
676
+ return nestedMessage && typeof nestedMessage === "object"
677
+ ? nestedMessage
678
+ : null;
679
+ }
680
+ function readProviderMessageRole(message) {
681
+ const directRole = typeof message.role === "string" ? message.role.trim().toLowerCase() : "";
682
+ if (directRole) {
683
+ return directRole;
684
+ }
685
+ const author = message.author;
686
+ if (!author || typeof author !== "object") {
687
+ return "";
688
+ }
689
+ return typeof author.role === "string"
690
+ ? String(author.role)
691
+ .trim()
692
+ .toLowerCase()
693
+ : "";
694
+ }
695
+ function normalizeProviderContentFragment(value) {
696
+ if (isHiddenInlineReferenceToken(value)) {
697
+ return "";
698
+ }
699
+ return value;
700
+ }
701
+ function isHiddenInlineReferenceToken(value) {
702
+ return /^\uE200[A-Za-z0-9_-]+\uE202[\s\S]*\uE201$/u.test(value.trim());
703
+ }
704
+ function extractPathValues(value, segments) {
705
+ if (segments.length === 0) {
706
+ return [value];
707
+ }
708
+ if (value === null || value === undefined) {
709
+ return [];
710
+ }
711
+ const [segment, ...rest] = segments;
712
+ if (segment === "*") {
713
+ if (Array.isArray(value)) {
714
+ return value.flatMap((entry) => extractPathValues(entry, rest));
715
+ }
716
+ if (typeof value === "object") {
717
+ return Object.values(value).flatMap((entry) => extractPathValues(entry, rest));
718
+ }
719
+ return [];
720
+ }
721
+ if (Array.isArray(value)) {
722
+ const index = Number.parseInt(segment, 10);
723
+ if (!Number.isInteger(index)) {
724
+ return [];
725
+ }
726
+ return extractPathValues(value[index], rest);
727
+ }
728
+ if (typeof value === "object") {
729
+ return extractPathValues(value[segment], rest);
730
+ }
731
+ return [];
732
+ }
733
+ function normalizeProviderResponseId(value) {
734
+ if (typeof value === "string") {
735
+ return value;
736
+ }
737
+ if (typeof value === "number" && Number.isFinite(value)) {
738
+ return String(value);
739
+ }
740
+ return "";
741
+ }
742
+ function parseConnectEnvelope(envelope, contentPaths, responseIdPaths, conversationIdPaths, eventFilters, currentResponseId, currentConversationId) {
743
+ const flags = envelope[0] ?? 0;
744
+ if ((flags & 0x01) !== 0) {
745
+ throw new ProviderFailure({
746
+ kind: "permanent",
747
+ code: "request_invalid",
748
+ message: "Provider returned a compressed Connect message, which is not supported yet.",
749
+ displayMessage: "Provider response format is unsupported.",
750
+ retryable: false,
751
+ sessionResetEligible: false
752
+ });
753
+ }
754
+ const payloadBytes = envelope.slice(5);
755
+ const payloadText = new TextDecoder().decode(payloadBytes).trim();
756
+ if (!payloadText) {
757
+ return null;
758
+ }
759
+ let payload;
760
+ try {
761
+ payload = JSON.parse(payloadText);
762
+ }
763
+ catch {
764
+ return null;
765
+ }
766
+ if ((flags & 0x02) !== 0) {
767
+ const error = readConnectEndStreamError(payload);
768
+ if (error) {
769
+ throw new ProviderFailure({
770
+ kind: error.retryable ? "transient" : "permanent",
771
+ code: error.retryable ? "transport_error" : "request_invalid",
772
+ message: `Provider Connect stream ended with error code "${error.code}"${error.message ? `: ${error.message}` : "."}`,
773
+ displayMessage: error.message || "Provider request failed.",
774
+ retryable: error.retryable,
775
+ sessionResetEligible: false,
776
+ details: {
777
+ upstreamCode: error.code
778
+ }
779
+ });
780
+ }
781
+ return null;
782
+ }
783
+ const nextResponseId = extractConfiguredString(payload, responseIdPaths) || currentResponseId;
784
+ const nextConversationId = extractConfiguredString(payload, conversationIdPaths) || currentConversationId;
785
+ if (!matchesEventFilters(payload, eventFilters)) {
786
+ return {
787
+ content: "",
788
+ responseId: nextResponseId,
789
+ conversationId: nextConversationId,
790
+ eventCountDelta: 0,
791
+ fragmentCountDelta: 0
792
+ };
793
+ }
794
+ const fragments = extractConfiguredFragments(payload, contentPaths);
795
+ return {
796
+ content: fragments.join(""),
797
+ responseId: nextResponseId,
798
+ conversationId: nextConversationId,
799
+ eventCountDelta: fragments.length > 0 ? 1 : 0,
800
+ fragmentCountDelta: fragments.length
801
+ };
802
+ }
803
+ function matchesEventFilters(payload, filters) {
804
+ if (filters.length === 0) {
805
+ return true;
806
+ }
807
+ return filters.every((filter) => extractPathValues(payload, filter.path).some((value) => value === filter.equals));
808
+ }
809
+ function readConnectEnvelopeLength(buffer) {
810
+ return (((buffer[1] ?? 0) << 24) | ((buffer[2] ?? 0) << 16) | ((buffer[3] ?? 0) << 8) | (buffer[4] ?? 0));
811
+ }
812
+ function concatUint8Arrays(left, right) {
813
+ const combined = new Uint8Array(left.length + right.length);
814
+ combined.set(left, 0);
815
+ combined.set(right, left.length);
816
+ return combined;
817
+ }
818
+ function readConnectEndStreamError(payload) {
819
+ const error = payload.error;
820
+ if (typeof error !== "object" || error === null) {
821
+ return null;
822
+ }
823
+ const record = error;
824
+ const code = typeof record.code === "string" ? record.code.trim() : "";
825
+ if (!code) {
826
+ return null;
827
+ }
828
+ const message = typeof record.message === "string" ? record.message.trim() : "";
829
+ return {
830
+ code,
831
+ message,
832
+ retryable: /^(aborted|deadline_exceeded|resource_exhausted|unavailable)$/i.test(code)
833
+ };
834
+ }
835
+ export const providerStreamsModule = {
836
+ collectSseCompletion,
837
+ streamSseFragments,
838
+ streamVisibleProviderCompletion,
839
+ createSseJsonEventParser,
840
+ collectConnectJsonCompletion,
841
+ streamConnectJsonFragments,
842
+ extractIncrementalPacketMessage,
843
+ normalizeLeadingAssistantBlock
844
+ };