effect 4.0.0-beta.32 → 4.0.0-beta.33

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.
@@ -0,0 +1,97 @@
1
+ /**
2
+ * @since 4.0.0
3
+ */
4
+ import * as Effect from "../../Effect.ts"
5
+ import * as Option from "../../Option.ts"
6
+ import * as ServiceMap from "../../ServiceMap.ts"
7
+ import * as Prompt from "./Prompt.ts"
8
+
9
+ /**
10
+ * @since 4.0.0
11
+ * @category models
12
+ */
13
+ export interface PrepareResult {
14
+ readonly previousResponseId: string
15
+ readonly prompt: Prompt.Prompt
16
+ }
17
+
18
+ /**
19
+ * @since 4.0.0
20
+ * @category models
21
+ */
22
+ export interface Service {
23
+ clearUnsafe(): void
24
+ markParts(parts: ReadonlyArray<object>, responseId: string): void
25
+ prepareUnsafe(prompt: Prompt.Prompt): Option.Option<PrepareResult>
26
+ }
27
+
28
+ /**
29
+ * @since 4.0.0
30
+ * @category Services
31
+ */
32
+ export class ResponseIdTracker
33
+ extends ServiceMap.Service<ResponseIdTracker, Service>()("effect/ai/ResponseIdTracker")
34
+ {}
35
+
36
+ /**
37
+ * @since 4.0.0
38
+ * @category constructors
39
+ */
40
+ export const make: Effect.Effect<Service> = Effect.sync(() => {
41
+ let sentParts = new WeakMap<object, string>()
42
+
43
+ const none = () => {
44
+ sentParts = new WeakMap<object, string>()
45
+ return Option.none<PrepareResult>()
46
+ }
47
+
48
+ return {
49
+ clearUnsafe() {
50
+ sentParts = new WeakMap<object, string>()
51
+ },
52
+ markParts(parts, responseId) {
53
+ for (let i = 0; i < parts.length; i++) {
54
+ sentParts.set(parts[i], responseId)
55
+ }
56
+ },
57
+ prepareUnsafe(prompt) {
58
+ const messages = prompt.content
59
+
60
+ let anyTracked = false
61
+ for (let i = 0; i < messages.length; i++) {
62
+ if (sentParts.has(messages[i])) {
63
+ anyTracked = true
64
+ break
65
+ }
66
+ }
67
+ if (!anyTracked) return none()
68
+
69
+ let lastAssistantIndex = -1
70
+ for (let i = messages.length - 1; i >= 0; i--) {
71
+ if (messages[i].role === "assistant") {
72
+ lastAssistantIndex = i
73
+ break
74
+ }
75
+ }
76
+ if (lastAssistantIndex === -1) return none()
77
+
78
+ let responseId: string | undefined
79
+ for (let i = 0; i < lastAssistantIndex; i++) {
80
+ const id = sentParts.get(messages[i])
81
+ if (id === undefined) return none()
82
+ responseId = id
83
+ }
84
+ if (responseId === undefined) return none()
85
+
86
+ const partsAfterLastAssistant = messages.slice(lastAssistantIndex + 1)
87
+ if (partsAfterLastAssistant.length === 0) {
88
+ return none()
89
+ }
90
+
91
+ return Option.some({
92
+ previousResponseId: responseId,
93
+ prompt: Prompt.fromMessages(partsAfterLastAssistant)
94
+ })
95
+ }
96
+ }
97
+ })
@@ -388,6 +388,11 @@ export * as Prompt from "./Prompt.ts"
388
388
  */
389
389
  export * as Response from "./Response.ts"
390
390
 
391
+ /**
392
+ * @since 4.0.0
393
+ */
394
+ export * as ResponseIdTracker from "./ResponseIdTracker.ts"
395
+
391
396
  /**
392
397
  * The `Telemetry` module provides OpenTelemetry integration for operations
393
398
  * performed against a large language model provider by defining telemetry
@@ -214,7 +214,7 @@ export type SocketErrorReason =
214
214
  * @since 4.0.0
215
215
  * @category errors
216
216
  */
217
- export class SocketError extends Schema.ErrorClass<SocketError>(SocketErrorTypeId)({
217
+ export class SocketError extends Schema.TaggedErrorClass<SocketError>(SocketErrorTypeId)("SocketError", {
218
218
  _tag: Schema.tag("SocketError"),
219
219
  reason: SocketErrorReason
220
220
  }) {
@@ -243,6 +243,8 @@ export class SocketError extends Schema.ErrorClass<SocketError>(SocketErrorTypeI
243
243
  static is(u: unknown): u is SocketError {
244
244
  return isSocketError(u)
245
245
  }
246
+
247
+ override readonly message = this.reason.message
246
248
  }
247
249
 
248
250
  /**
@@ -426,14 +428,16 @@ export const makeWebSocket = (url: string | Effect.Effect<string>, options?: {
426
428
  readonly openTimeout?: Duration.Input | undefined
427
429
  readonly protocols?: string | Array<string> | undefined
428
430
  }): Effect.Effect<Socket, never, WebSocketConstructor> =>
429
- fromWebSocket(
430
- Effect.acquireRelease(
431
- (typeof url === "string" ? Effect.succeed(url) : url).pipe(
432
- Effect.flatMap((url) => Effect.map(WebSocketConstructor.asEffect(), (f) => f(url, options?.protocols)))
431
+ WebSocketConstructor.use((makeWs) =>
432
+ fromWebSocket(
433
+ Effect.acquireRelease(
434
+ (typeof url === "string" ? Effect.succeed(url) : url).pipe(
435
+ Effect.map((url) => makeWs(url, options?.protocols))
436
+ ),
437
+ (ws) => Effect.sync(() => ws.close(1000))
433
438
  ),
434
- (ws) => Effect.sync(() => ws.close(1000))
435
- ),
436
- options
439
+ options
440
+ )
437
441
  )
438
442
 
439
443
  /**