effect 4.0.0-beta.105 → 4.0.0-beta.106
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/dist/Config.js +3 -3
- package/dist/Config.js.map +1 -1
- package/dist/ConfigProvider.d.ts +35 -3
- package/dist/ConfigProvider.d.ts.map +1 -1
- package/dist/ConfigProvider.js +41 -8
- package/dist/ConfigProvider.js.map +1 -1
- package/dist/Fiber.d.ts +1 -1
- package/dist/Fiber.d.ts.map +1 -1
- package/dist/Function.d.ts +26 -0
- package/dist/Function.d.ts.map +1 -1
- package/dist/Function.js +36 -0
- package/dist/Function.js.map +1 -1
- package/dist/JsonSchema.d.ts.map +1 -1
- package/dist/JsonSchema.js +34 -17
- package/dist/JsonSchema.js.map +1 -1
- package/dist/Schema.d.ts +32 -84
- package/dist/Schema.d.ts.map +1 -1
- package/dist/Schema.js +58 -54
- package/dist/Schema.js.map +1 -1
- package/dist/SchemaAST.d.ts +2 -17
- package/dist/SchemaAST.d.ts.map +1 -1
- package/dist/SchemaAST.js +39 -28
- package/dist/SchemaAST.js.map +1 -1
- package/dist/SchemaRepresentation.d.ts +15 -3
- package/dist/SchemaRepresentation.d.ts.map +1 -1
- package/dist/SchemaRepresentation.js +8 -2
- package/dist/SchemaRepresentation.js.map +1 -1
- package/dist/ScopedRef.d.ts.map +1 -1
- package/dist/ScopedRef.js +1 -1
- package/dist/ScopedRef.js.map +1 -1
- package/dist/TxQueue.js +1 -1
- package/dist/TxQueue.js.map +1 -1
- package/dist/internal/effect.js +2 -4
- package/dist/internal/effect.js.map +1 -1
- package/dist/internal/executionPlan.js +3 -2
- package/dist/internal/executionPlan.js.map +1 -1
- package/dist/internal/rcRef.js +18 -13
- package/dist/internal/rcRef.js.map +1 -1
- package/dist/internal/schema/fromJsonSchemaDocument.js +10 -6
- package/dist/internal/schema/fromJsonSchemaDocument.js.map +1 -1
- package/dist/internal/schema/toArbitrary.d.ts +1 -4
- package/dist/internal/schema/toArbitrary.d.ts.map +1 -1
- package/dist/internal/schema/toArbitrary.js +0 -74
- package/dist/internal/schema/toArbitrary.js.map +1 -1
- package/dist/internal/schema/toJsonSchemaDocument.js +18 -4
- package/dist/internal/schema/toJsonSchemaDocument.js.map +1 -1
- package/dist/internal/schema/toRepresentation.js +45 -43
- package/dist/internal/schema/toRepresentation.js.map +1 -1
- package/dist/testing/TestSchema.js +2 -2
- package/dist/testing/TestSchema.js.map +1 -1
- package/dist/unstable/ai/McpSchema.d.ts +110 -110
- package/dist/unstable/ai/McpSchema.d.ts.map +1 -1
- package/dist/unstable/ai/McpServer.d.ts.map +1 -1
- package/dist/unstable/ai/McpServer.js +23 -11
- package/dist/unstable/ai/McpServer.js.map +1 -1
- package/dist/unstable/ai/Prompt.d.ts +4 -3
- package/dist/unstable/ai/Prompt.d.ts.map +1 -1
- package/dist/unstable/ai/Prompt.js +38 -13
- package/dist/unstable/ai/Prompt.js.map +1 -1
- package/dist/unstable/cluster/Entity.d.ts +2 -2
- package/dist/unstable/cluster/Entity.d.ts.map +1 -1
- package/dist/unstable/cluster/Entity.js.map +1 -1
- package/dist/unstable/cluster/EntityProxy.d.ts +3 -3
- package/dist/unstable/cluster/EntityProxy.d.ts.map +1 -1
- package/dist/unstable/cluster/EntityProxy.js +4 -3
- package/dist/unstable/cluster/EntityProxy.js.map +1 -1
- package/dist/unstable/cluster/Sharding.d.ts +2 -2
- package/dist/unstable/cluster/Sharding.d.ts.map +1 -1
- package/dist/unstable/cluster/Sharding.js +14 -5
- package/dist/unstable/cluster/Sharding.js.map +1 -1
- package/dist/unstable/eventlog/EventLogEncryption.d.ts +6 -5
- package/dist/unstable/eventlog/EventLogEncryption.d.ts.map +1 -1
- package/dist/unstable/eventlog/EventLogEncryption.js +14 -12
- package/dist/unstable/eventlog/EventLogEncryption.js.map +1 -1
- package/dist/unstable/eventlog/EventLogMessage.d.ts +3 -3
- package/dist/unstable/eventlog/EventLogMessage.d.ts.map +1 -1
- package/dist/unstable/eventlog/EventLogMessage.js +2 -3
- package/dist/unstable/eventlog/EventLogMessage.js.map +1 -1
- package/dist/unstable/eventlog/EventLogRemote.js +4 -4
- package/dist/unstable/eventlog/EventLogRemote.js.map +1 -1
- package/dist/unstable/eventlog/EventLogServerEncrypted.js +3 -2
- package/dist/unstable/eventlog/EventLogServerEncrypted.js.map +1 -1
- package/dist/unstable/http/HttpServerRequest.d.ts.map +1 -1
- package/dist/unstable/http/HttpServerRequest.js +7 -1
- package/dist/unstable/http/HttpServerRequest.js.map +1 -1
- package/dist/unstable/http/MultipartParser/internal/multipart.d.ts.map +1 -1
- package/dist/unstable/http/MultipartParser/internal/multipart.js +18 -6
- package/dist/unstable/http/MultipartParser/internal/multipart.js.map +1 -1
- package/dist/unstable/httpapi/OpenApi.d.ts.map +1 -1
- package/dist/unstable/httpapi/OpenApi.js +1 -1
- package/dist/unstable/httpapi/OpenApi.js.map +1 -1
- package/dist/unstable/rpc/RpcClient.d.ts.map +1 -1
- package/dist/unstable/rpc/RpcClient.js +5 -0
- package/dist/unstable/rpc/RpcClient.js.map +1 -1
- package/dist/unstable/sql/SqlResolver.d.ts.map +1 -1
- package/dist/unstable/sql/SqlResolver.js +20 -16
- package/dist/unstable/sql/SqlResolver.js.map +1 -1
- package/dist/unstable/workers/Worker.d.ts.map +1 -1
- package/dist/unstable/workers/Worker.js +11 -12
- package/dist/unstable/workers/Worker.js.map +1 -1
- package/package.json +1 -1
- package/src/Config.ts +3 -3
- package/src/ConfigProvider.ts +43 -8
- package/src/Fiber.ts +1 -1
- package/src/Function.ts +37 -0
- package/src/JsonSchema.ts +43 -42
- package/src/Schema.ts +68 -146
- package/src/SchemaAST.ts +50 -30
- package/src/SchemaRepresentation.ts +15 -3
- package/src/ScopedRef.ts +3 -1
- package/src/TxQueue.ts +1 -1
- package/src/internal/effect.ts +3 -6
- package/src/internal/executionPlan.ts +3 -2
- package/src/internal/rcRef.ts +24 -16
- package/src/internal/schema/fromJsonSchemaDocument.ts +19 -14
- package/src/internal/schema/toArbitrary.ts +0 -72
- package/src/internal/schema/toJsonSchemaDocument.ts +24 -4
- package/src/internal/schema/toRepresentation.ts +66 -48
- package/src/testing/TestSchema.ts +2 -2
- package/src/unstable/ai/McpServer.ts +23 -11
- package/src/unstable/ai/Prompt.ts +37 -15
- package/src/unstable/cluster/Entity.ts +7 -2
- package/src/unstable/cluster/EntityProxy.ts +12 -5
- package/src/unstable/cluster/Sharding.ts +29 -17
- package/src/unstable/eventlog/EventLogEncryption.ts +15 -16
- package/src/unstable/eventlog/EventLogMessage.ts +2 -3
- package/src/unstable/eventlog/EventLogRemote.ts +4 -4
- package/src/unstable/eventlog/EventLogServerEncrypted.ts +2 -2
- package/src/unstable/http/HttpServerRequest.ts +8 -3
- package/src/unstable/http/MultipartParser/internal/multipart.ts +19 -6
- package/src/unstable/httpapi/OpenApi.ts +4 -1
- package/src/unstable/rpc/RpcClient.ts +5 -0
- package/src/unstable/sql/SqlResolver.ts +28 -20
- package/src/unstable/workers/Worker.ts +13 -14
|
@@ -7,17 +7,24 @@ import * as InternalAnnotations from "./annotations.ts"
|
|
|
7
7
|
|
|
8
8
|
/** @internal */
|
|
9
9
|
export function toRepresentation(
|
|
10
|
-
ast: SchemaAST.AST
|
|
10
|
+
ast: SchemaAST.AST,
|
|
11
|
+
options?: Options
|
|
11
12
|
): SchemaRepresentation.Document {
|
|
12
|
-
const { references, representations } = toRepresentations([ast])
|
|
13
|
+
const { references, representations } = toRepresentations([ast], options)
|
|
13
14
|
return { representation: representations[0], references }
|
|
14
15
|
}
|
|
15
16
|
|
|
16
17
|
/** @internal */
|
|
17
18
|
export function toRepresentations(
|
|
18
|
-
asts: readonly [SchemaAST.AST, ...Array<SchemaAST.AST>]
|
|
19
|
+
asts: readonly [SchemaAST.AST, ...Array<SchemaAST.AST>],
|
|
20
|
+
options?: Options
|
|
19
21
|
): SchemaRepresentation.MultiDocument {
|
|
20
|
-
return fromASTs(asts)
|
|
22
|
+
return fromASTs(asts, options)
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
/** @internal */
|
|
26
|
+
export interface Options {
|
|
27
|
+
readonly isAnonymousReferenceAllowed?: ((ast: SchemaAST.AST) => boolean) | undefined
|
|
21
28
|
}
|
|
22
29
|
|
|
23
30
|
type CheckRepresentationAnnotation = SchemaRepresentation.CheckRepresentationAnnotation<
|
|
@@ -28,11 +35,49 @@ function annotationsField<A>(annotations: A | undefined): { readonly annotations
|
|
|
28
35
|
return annotations === undefined ? undefined : { annotations }
|
|
29
36
|
}
|
|
30
37
|
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
38
|
+
function hasShareableStructure(
|
|
39
|
+
ast: SchemaAST.AST,
|
|
40
|
+
isAnonymousReferenceAllowed: Options["isAnonymousReferenceAllowed"]
|
|
41
|
+
): boolean {
|
|
42
|
+
if (isAnonymousReferenceAllowed?.(ast) === false) return false
|
|
43
|
+
switch (ast._tag) {
|
|
44
|
+
case "Arrays":
|
|
45
|
+
case "Objects":
|
|
46
|
+
case "Suspend":
|
|
47
|
+
return true
|
|
48
|
+
case "Declaration":
|
|
49
|
+
return true
|
|
50
|
+
case "Union":
|
|
51
|
+
return ast.types.some((ast) => hasShareableStructure(ast, isAnonymousReferenceAllowed))
|
|
52
|
+
default:
|
|
53
|
+
return false
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
function isWorthReferencing(bodyCost: number, occurrences: number): boolean {
|
|
58
|
+
return occurrences * bodyCost > bodyCost + occurrences + 1
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
function isAnonymousReferenceEligible(
|
|
62
|
+
ast: SchemaAST.AST,
|
|
63
|
+
occurrences: number,
|
|
64
|
+
isAnonymousReferenceAllowed: Options["isAnonymousReferenceAllowed"]
|
|
65
|
+
): boolean {
|
|
66
|
+
if (isAnonymousReferenceAllowed?.(ast) === false) return false
|
|
67
|
+
if (hasShareableStructure(ast, isAnonymousReferenceAllowed)) return true
|
|
68
|
+
switch (ast._tag) {
|
|
69
|
+
case "Union":
|
|
70
|
+
return isWorthReferencing(ast.types.length + 1, occurrences)
|
|
71
|
+
case "Enum":
|
|
72
|
+
return isWorthReferencing(ast.enums.length + 1, occurrences)
|
|
73
|
+
case "TemplateLiteral":
|
|
74
|
+
return isWorthReferencing(ast.parts.length + 1, occurrences)
|
|
75
|
+
case "Literal":
|
|
76
|
+
return typeof ast.literal === "string" &&
|
|
77
|
+
isWorthReferencing(ast.literal.length / 32 + 1, occurrences)
|
|
78
|
+
default:
|
|
79
|
+
return false
|
|
80
|
+
}
|
|
36
81
|
}
|
|
37
82
|
|
|
38
83
|
interface ReferenceIdentifier {
|
|
@@ -54,17 +99,15 @@ function resolveReferenceIdentifier(
|
|
|
54
99
|
}
|
|
55
100
|
|
|
56
101
|
function fromASTs(
|
|
57
|
-
asts: readonly [SchemaAST.AST, ...Array<SchemaAST.AST>]
|
|
102
|
+
asts: readonly [SchemaAST.AST, ...Array<SchemaAST.AST>],
|
|
103
|
+
options: Options | undefined
|
|
58
104
|
): SchemaRepresentation.MultiDocument {
|
|
59
105
|
const references: Record<string, SchemaRepresentation.Representation> = {}
|
|
60
106
|
const anonymousReferences = new Map<SchemaAST.AST, string>()
|
|
61
107
|
const referenceOwners = new Map<string, SchemaAST.AST>()
|
|
62
|
-
const valueIds = new Map<unknown, number>()
|
|
63
|
-
const canonicalByKey = new Map<string, SchemaAST.AST>()
|
|
64
|
-
let nextValueId = 0
|
|
65
108
|
const buildingReferences = new Set<string>()
|
|
66
109
|
const visiting = new Set<SchemaAST.AST>()
|
|
67
|
-
const
|
|
110
|
+
const occurrences = new Map<SchemaAST.AST, number>()
|
|
68
111
|
const shared = new Set<SchemaAST.AST>()
|
|
69
112
|
|
|
70
113
|
for (const ast of asts) visit(ast)
|
|
@@ -84,35 +127,6 @@ function fromASTs(
|
|
|
84
127
|
return candidate
|
|
85
128
|
}
|
|
86
129
|
|
|
87
|
-
function getValueId(value: unknown): number {
|
|
88
|
-
if (typeof value === "number" && globalThis.Number.isNaN(value)) {
|
|
89
|
-
return nextValueId++
|
|
90
|
-
}
|
|
91
|
-
const found = valueIds.get(value)
|
|
92
|
-
if (found !== undefined) return found
|
|
93
|
-
const id = nextValueId++
|
|
94
|
-
valueIds.set(value, id)
|
|
95
|
-
return id
|
|
96
|
-
}
|
|
97
|
-
|
|
98
|
-
function getIdentityKey(ast: SchemaAST.AST): string {
|
|
99
|
-
let identity = ast._tag
|
|
100
|
-
for (const [key, value] of Object.entries(ast)) {
|
|
101
|
-
if (key !== "_tag" && key !== "context") identity += `:${getValueId(value)}`
|
|
102
|
-
}
|
|
103
|
-
return identity
|
|
104
|
-
}
|
|
105
|
-
|
|
106
|
-
function getCanonicalAST(ast: SchemaAST.AST): SchemaAST.AST {
|
|
107
|
-
const key = getIdentityKey(ast)
|
|
108
|
-
const canonical = canonicalByKey.get(key)
|
|
109
|
-
if (canonical === undefined) {
|
|
110
|
-
canonicalByKey.set(key, ast)
|
|
111
|
-
return ast
|
|
112
|
-
}
|
|
113
|
-
return canonical
|
|
114
|
-
}
|
|
115
|
-
|
|
116
130
|
function annotateReference(
|
|
117
131
|
ast: SchemaAST.AST,
|
|
118
132
|
referenceIdentifier: ReferenceIdentifier,
|
|
@@ -143,12 +157,16 @@ function fromASTs(
|
|
|
143
157
|
|
|
144
158
|
function visit(input: SchemaAST.AST): void {
|
|
145
159
|
const ast = SchemaAST.getLastEncoding(input)
|
|
146
|
-
const owner =
|
|
147
|
-
|
|
148
|
-
|
|
160
|
+
const owner = SchemaAST.getContextOwner(ast)
|
|
161
|
+
const count = (occurrences.get(owner) ?? 0) + 1
|
|
162
|
+
occurrences.set(owner, count)
|
|
163
|
+
if (count > 1) {
|
|
164
|
+
if (
|
|
165
|
+
!shared.has(owner) &&
|
|
166
|
+
isAnonymousReferenceEligible(owner, count, options?.isAnonymousReferenceAllowed)
|
|
167
|
+
) shared.add(owner)
|
|
149
168
|
return
|
|
150
169
|
}
|
|
151
|
-
visited.add(owner)
|
|
152
170
|
visitChecks(ast.checks)
|
|
153
171
|
switch (ast._tag) {
|
|
154
172
|
case "Declaration":
|
|
@@ -178,7 +196,7 @@ function fromASTs(
|
|
|
178
196
|
|
|
179
197
|
function recur(input: SchemaAST.AST): SchemaRepresentation.Representation {
|
|
180
198
|
const ast = SchemaAST.getLastEncoding(input)
|
|
181
|
-
const owner =
|
|
199
|
+
const owner = SchemaAST.getContextOwner(ast)
|
|
182
200
|
const referenceIdentifier = resolveReferenceIdentifier(input, ast)
|
|
183
201
|
if (referenceIdentifier !== undefined) {
|
|
184
202
|
const reference = getReference(referenceIdentifier.identifier, owner)
|
|
@@ -172,7 +172,7 @@ export class Asserts<S extends Schema.Constraint> {
|
|
|
172
172
|
}) {
|
|
173
173
|
const decodeUnknownEffect = SchemaParser.decodeUnknownEffect(this.schema)
|
|
174
174
|
const encodeEffect = SchemaParser.encodeEffect(this.schema)
|
|
175
|
-
const arbitrary = Schema.toArbitrary(this.schema)
|
|
175
|
+
const arbitrary = Schema.toArbitrary(this.schema)(FastCheck)
|
|
176
176
|
return FastCheck.assert(
|
|
177
177
|
FastCheck.asyncProperty(arbitrary, async (t) => {
|
|
178
178
|
const r = await Effect.runPromise(
|
|
@@ -280,7 +280,7 @@ export class Asserts<S extends Schema.Constraint> {
|
|
|
280
280
|
}) {
|
|
281
281
|
const params = options?.params
|
|
282
282
|
const is = Schema.is(schema)
|
|
283
|
-
const arb = Schema.toArbitrary(schema)
|
|
283
|
+
const arb = Schema.toArbitrary(schema)(FastCheck)
|
|
284
284
|
FastCheck.assert(FastCheck.property(arb, (a) => is(a)), { numRuns: 20, ...params })
|
|
285
285
|
}
|
|
286
286
|
}
|
|
@@ -489,7 +489,7 @@ const runWithProtocolState = Effect.fnUntraced(function*(options: {
|
|
|
489
489
|
const isHttp = Option.isSome(yield* Effect.serviceOption(HttpRouter.HttpRouter))
|
|
490
490
|
const sessions = protocolState.sessions
|
|
491
491
|
const clientProtocols = new Map<number, McpProtocol.ProtocolAdapter>()
|
|
492
|
-
const
|
|
492
|
+
const activeRequests = new Map<number, Map<string, boolean>>()
|
|
493
493
|
const handlers = yield* Layer.build(layerHandlers(options, {
|
|
494
494
|
sessions,
|
|
495
495
|
protocolRegistry
|
|
@@ -577,11 +577,13 @@ const runWithProtocolState = Effect.fnUntraced(function*(options: {
|
|
|
577
577
|
...protocol,
|
|
578
578
|
send: (clientId, response) => {
|
|
579
579
|
if (response._tag === "Exit") {
|
|
580
|
-
const requests =
|
|
581
|
-
|
|
582
|
-
|
|
583
|
-
|
|
584
|
-
|
|
580
|
+
const requests = activeRequests.get(clientId)
|
|
581
|
+
const key = requestKey(response.requestId)
|
|
582
|
+
const cancelled = requests?.get(key)
|
|
583
|
+
if (requests !== undefined && requests.delete(key) && requests.size === 0) {
|
|
584
|
+
activeRequests.delete(clientId)
|
|
585
|
+
}
|
|
586
|
+
if (cancelled === true) {
|
|
585
587
|
return Effect.void
|
|
586
588
|
}
|
|
587
589
|
}
|
|
@@ -670,9 +672,12 @@ const runWithProtocolState = Effect.fnUntraced(function*(options: {
|
|
|
670
672
|
if (request.tag === "notifications/cancelled") {
|
|
671
673
|
return decodeCancelledNotification(request.payload).pipe(
|
|
672
674
|
Effect.flatMap(({ requestId }) => {
|
|
673
|
-
const
|
|
674
|
-
requests.
|
|
675
|
-
|
|
675
|
+
const key = requestKey(requestId)
|
|
676
|
+
const requests = activeRequests.get(clientId)
|
|
677
|
+
if (requests?.has(key) !== true) {
|
|
678
|
+
return Effect.void
|
|
679
|
+
}
|
|
680
|
+
requests.set(key, true)
|
|
676
681
|
return f(clientId, {
|
|
677
682
|
_tag: "Interrupt",
|
|
678
683
|
requestId: RpcMessage.RequestId(requestId)
|
|
@@ -732,7 +737,14 @@ const runWithProtocolState = Effect.fnUntraced(function*(options: {
|
|
|
732
737
|
}
|
|
733
738
|
return selectedProtocol.payloadCodecs(rpc).decode(request.payload).pipe(
|
|
734
739
|
Effect.matchEffect({
|
|
735
|
-
onSuccess: () =>
|
|
740
|
+
onSuccess: () => {
|
|
741
|
+
if (request.isNotification !== true) {
|
|
742
|
+
const requests = activeRequests.get(clientId) ?? new Map<string, boolean>()
|
|
743
|
+
requests.set(requestKey(request.id), false)
|
|
744
|
+
activeRequests.set(clientId, requests)
|
|
745
|
+
}
|
|
746
|
+
return f(clientId, routedRequest)
|
|
747
|
+
},
|
|
736
748
|
onFailure: () =>
|
|
737
749
|
request.isNotification
|
|
738
750
|
? Effect.void
|
|
@@ -752,7 +764,7 @@ const runWithProtocolState = Effect.fnUntraced(function*(options: {
|
|
|
752
764
|
case "Interrupt":
|
|
753
765
|
return f(clientId, request)
|
|
754
766
|
case "Eof":
|
|
755
|
-
|
|
767
|
+
activeRequests.delete(clientId)
|
|
756
768
|
return f(clientId, request)
|
|
757
769
|
case "Pong":
|
|
758
770
|
case "Exit":
|
|
@@ -2004,11 +2004,23 @@ export const make = (input: RawInput): Prompt => {
|
|
|
2004
2004
|
*/
|
|
2005
2005
|
export const fromMessages = (messages: ReadonlyArray<Message>): Prompt => makePrompt(messages)
|
|
2006
2006
|
|
|
2007
|
+
const mergeOptions = (left: ProviderOptions, right: ProviderOptions): ProviderOptions => {
|
|
2008
|
+
const result: Record<string, ProviderOptions[string]> = { ...left }
|
|
2009
|
+
for (const [provider, metadata] of Object.entries(right)) {
|
|
2010
|
+
const previous = result[provider]
|
|
2011
|
+
result[provider] = Predicate.isObject(previous) && Predicate.isObject(metadata)
|
|
2012
|
+
? Object.assign({}, previous, metadata)
|
|
2013
|
+
: metadata
|
|
2014
|
+
}
|
|
2015
|
+
return result
|
|
2016
|
+
}
|
|
2017
|
+
|
|
2007
2018
|
/**
|
|
2008
2019
|
* Creates a `Prompt` from response parts by folding completed text and
|
|
2009
|
-
* reasoning streams into assistant parts,
|
|
2010
|
-
*
|
|
2011
|
-
* in a tool message using
|
|
2020
|
+
* reasoning streams into assistant parts, preserving provider metadata as
|
|
2021
|
+
* prompt options, placing tool calls and approval requests in an assistant
|
|
2022
|
+
* message, and placing non-preliminary tool results in a tool message using
|
|
2023
|
+
* their encoded results.
|
|
2012
2024
|
*
|
|
2013
2025
|
* **Example** (Creating prompts from response parts)
|
|
2014
2026
|
*
|
|
@@ -2052,55 +2064,63 @@ export const fromResponseParts = (parts: ReadonlyArray<Response.AnyPart>): Promp
|
|
|
2052
2064
|
const assistantParts: Array<AssistantMessagePart> = []
|
|
2053
2065
|
const toolParts: Array<ToolMessagePart> = []
|
|
2054
2066
|
|
|
2055
|
-
const activeTextDeltas = new Map<string, { text: string }>()
|
|
2056
|
-
const activeReasoningDeltas = new Map<string, { text: string }>()
|
|
2067
|
+
const activeTextDeltas = new Map<string, { text: string; options: ProviderOptions }>()
|
|
2068
|
+
const activeReasoningDeltas = new Map<string, { text: string; options: ProviderOptions }>()
|
|
2057
2069
|
|
|
2058
2070
|
for (const part of parts) {
|
|
2059
2071
|
switch (part.type) {
|
|
2060
2072
|
// Text Parts
|
|
2061
2073
|
case "text": {
|
|
2062
|
-
assistantParts.push(makePart("text", { text: part.text }))
|
|
2074
|
+
assistantParts.push(makePart("text", { text: part.text, options: part.metadata }))
|
|
2063
2075
|
break
|
|
2064
2076
|
}
|
|
2065
2077
|
|
|
2066
2078
|
// Text Parts (streaming)
|
|
2067
2079
|
case "text-start": {
|
|
2068
|
-
activeTextDeltas.set(part.id, { text: "" })
|
|
2080
|
+
activeTextDeltas.set(part.id, { text: "", options: part.metadata })
|
|
2069
2081
|
break
|
|
2070
2082
|
}
|
|
2071
2083
|
case "text-delta": {
|
|
2072
2084
|
if (activeTextDeltas.has(part.id)) {
|
|
2073
|
-
activeTextDeltas.get(part.id)
|
|
2085
|
+
const active = activeTextDeltas.get(part.id)!
|
|
2086
|
+
active.text += part.delta
|
|
2087
|
+
active.options = mergeOptions(active.options, part.metadata)
|
|
2074
2088
|
}
|
|
2075
2089
|
break
|
|
2076
2090
|
}
|
|
2077
2091
|
case "text-end": {
|
|
2078
2092
|
if (activeTextDeltas.has(part.id)) {
|
|
2079
|
-
|
|
2093
|
+
const active = activeTextDeltas.get(part.id)!
|
|
2094
|
+
active.options = mergeOptions(active.options, part.metadata)
|
|
2095
|
+
assistantParts.push(makePart("text", active))
|
|
2080
2096
|
}
|
|
2081
2097
|
break
|
|
2082
2098
|
}
|
|
2083
2099
|
|
|
2084
2100
|
// Reasoning Parts
|
|
2085
2101
|
case "reasoning": {
|
|
2086
|
-
assistantParts.push(makePart("reasoning", { text: part.text }))
|
|
2102
|
+
assistantParts.push(makePart("reasoning", { text: part.text, options: part.metadata }))
|
|
2087
2103
|
break
|
|
2088
2104
|
}
|
|
2089
2105
|
|
|
2090
2106
|
// Reasoning Parts (streaming)
|
|
2091
2107
|
case "reasoning-start": {
|
|
2092
|
-
activeReasoningDeltas.set(part.id, { text: "" })
|
|
2108
|
+
activeReasoningDeltas.set(part.id, { text: "", options: part.metadata })
|
|
2093
2109
|
break
|
|
2094
2110
|
}
|
|
2095
2111
|
case "reasoning-delta": {
|
|
2096
2112
|
if (activeReasoningDeltas.has(part.id)) {
|
|
2097
|
-
activeReasoningDeltas.get(part.id)
|
|
2113
|
+
const active = activeReasoningDeltas.get(part.id)!
|
|
2114
|
+
active.text += part.delta
|
|
2115
|
+
active.options = mergeOptions(active.options, part.metadata)
|
|
2098
2116
|
}
|
|
2099
2117
|
break
|
|
2100
2118
|
}
|
|
2101
2119
|
case "reasoning-end": {
|
|
2102
2120
|
if (activeReasoningDeltas.has(part.id)) {
|
|
2103
|
-
|
|
2121
|
+
const active = activeReasoningDeltas.get(part.id)!
|
|
2122
|
+
active.options = mergeOptions(active.options, part.metadata)
|
|
2123
|
+
assistantParts.push(makePart("reasoning", active))
|
|
2104
2124
|
}
|
|
2105
2125
|
break
|
|
2106
2126
|
}
|
|
@@ -2111,7 +2131,8 @@ export const fromResponseParts = (parts: ReadonlyArray<Response.AnyPart>): Promp
|
|
|
2111
2131
|
id: part.id,
|
|
2112
2132
|
name: part.name,
|
|
2113
2133
|
params: part.params,
|
|
2114
|
-
providerExecuted: part.providerExecuted ?? false
|
|
2134
|
+
providerExecuted: part.providerExecuted ?? false,
|
|
2135
|
+
options: part.metadata
|
|
2115
2136
|
}))
|
|
2116
2137
|
break
|
|
2117
2138
|
}
|
|
@@ -2125,7 +2146,8 @@ export const fromResponseParts = (parts: ReadonlyArray<Response.AnyPart>): Promp
|
|
|
2125
2146
|
name: part.name,
|
|
2126
2147
|
isFailure: part.isFailure,
|
|
2127
2148
|
result: part.encodedResult,
|
|
2128
|
-
providerExecuted: part.providerExecuted ?? false
|
|
2149
|
+
providerExecuted: part.providerExecuted ?? false,
|
|
2150
|
+
options: part.metadata
|
|
2129
2151
|
}))
|
|
2130
2152
|
}
|
|
2131
2153
|
break
|
|
@@ -34,7 +34,12 @@ import * as RpcClient from "../rpc/RpcClient.ts"
|
|
|
34
34
|
import * as RpcGroup from "../rpc/RpcGroup.ts"
|
|
35
35
|
import * as RpcSchema from "../rpc/RpcSchema.ts"
|
|
36
36
|
import * as RpcServer from "../rpc/RpcServer.ts"
|
|
37
|
-
import type {
|
|
37
|
+
import type {
|
|
38
|
+
AlreadyProcessingMessage,
|
|
39
|
+
EntityNotAssignedToRunner,
|
|
40
|
+
MailboxFull,
|
|
41
|
+
PersistenceError
|
|
42
|
+
} from "./ClusterError.ts"
|
|
38
43
|
import { Persisted, ShardGroup, Uninterruptible } from "./ClusterSchema.ts"
|
|
39
44
|
import { EntityAddress } from "./EntityAddress.ts"
|
|
40
45
|
import type { EntityId } from "./EntityId.ts"
|
|
@@ -117,7 +122,7 @@ export interface Entity<
|
|
|
117
122
|
entityId: string
|
|
118
123
|
) => RpcClient.RpcClient.From<
|
|
119
124
|
Rpcs,
|
|
120
|
-
MailboxFull | AlreadyProcessingMessage | PersistenceError
|
|
125
|
+
MailboxFull | AlreadyProcessingMessage | PersistenceError | EntityNotAssignedToRunner
|
|
121
126
|
>,
|
|
122
127
|
never,
|
|
123
128
|
Sharding
|
|
@@ -14,7 +14,7 @@ import * as HttpApiEndpoint from "../httpapi/HttpApiEndpoint.ts"
|
|
|
14
14
|
import * as HttpApiGroup from "../httpapi/HttpApiGroup.ts"
|
|
15
15
|
import * as Rpc from "../rpc/Rpc.ts"
|
|
16
16
|
import * as RpcGroup from "../rpc/RpcGroup.ts"
|
|
17
|
-
import { AlreadyProcessingMessage, MailboxFull, PersistenceError } from "./ClusterError.ts"
|
|
17
|
+
import { AlreadyProcessingMessage, EntityNotAssignedToRunner, MailboxFull, PersistenceError } from "./ClusterError.ts"
|
|
18
18
|
import type * as Entity from "./Entity.ts"
|
|
19
19
|
import type { EntityId } from "./EntityId.ts"
|
|
20
20
|
|
|
@@ -24,6 +24,11 @@ const clientErrors = [
|
|
|
24
24
|
PersistenceError
|
|
25
25
|
] as const
|
|
26
26
|
|
|
27
|
+
const requestErrors = [
|
|
28
|
+
...clientErrors,
|
|
29
|
+
EntityNotAssignedToRunner
|
|
30
|
+
] as const
|
|
31
|
+
|
|
27
32
|
/**
|
|
28
33
|
* Derives an `RpcGroup` from an `Entity`.
|
|
29
34
|
*
|
|
@@ -75,7 +80,7 @@ export const toRpcGroup = <Type extends string, Rpcs extends Rpc.Any>(
|
|
|
75
80
|
}
|
|
76
81
|
const rpc = Rpc.make(`${entity.type}.${parentRpc._tag}`, {
|
|
77
82
|
payload: payloadSchema,
|
|
78
|
-
error: Schema.Union([parentRpc.errorSchema, ...
|
|
83
|
+
error: Schema.Union([parentRpc.errorSchema, ...requestErrors]),
|
|
79
84
|
success: parentRpc.successSchema
|
|
80
85
|
}).annotateMerge(parentRpc.annotations)
|
|
81
86
|
const rpcDiscard = Rpc.make(`${entity.type}.${parentRpc._tag}Discard`, {
|
|
@@ -115,11 +120,12 @@ export type ConvertRpcs<Rpcs extends Rpc.Any, Prefix extends string> = Rpcs exte
|
|
|
115
120
|
}>,
|
|
116
121
|
_Success,
|
|
117
122
|
Schema.Codec<
|
|
118
|
-
_Error["Type"] | MailboxFull | AlreadyProcessingMessage | PersistenceError,
|
|
123
|
+
_Error["Type"] | MailboxFull | AlreadyProcessingMessage | PersistenceError | EntityNotAssignedToRunner,
|
|
119
124
|
| _Error["Encoded"]
|
|
120
125
|
| typeof MailboxFull["Encoded"]
|
|
121
126
|
| typeof AlreadyProcessingMessage["Encoded"]
|
|
122
|
-
| typeof PersistenceError["Encoded"]
|
|
127
|
+
| typeof PersistenceError["Encoded"]
|
|
128
|
+
| typeof EntityNotAssignedToRunner["Encoded"],
|
|
123
129
|
_Error["DecodingServices"],
|
|
124
130
|
_Error["EncodingServices"]
|
|
125
131
|
>
|
|
@@ -193,7 +199,7 @@ export const toHttpApiGroup = <const Name extends string, Type extends string, R
|
|
|
193
199
|
params: entityIdPath,
|
|
194
200
|
payload: parentRpc.payloadSchema,
|
|
195
201
|
success: parentRpc.successSchema,
|
|
196
|
-
error: [parentRpc.errorSchema, ...
|
|
202
|
+
error: [parentRpc.errorSchema, ...requestErrors]
|
|
197
203
|
}).annotateMerge(parentRpc.annotations)
|
|
198
204
|
const endpointDiscard = HttpApiEndpoint.post(
|
|
199
205
|
`${parentRpc._tag}Discard`,
|
|
@@ -250,6 +256,7 @@ export type ConvertHttpApi<Rpcs extends Rpc.Any> = Rpcs extends Rpc.Rpc<
|
|
|
250
256
|
| typeof MailboxFull
|
|
251
257
|
| typeof AlreadyProcessingMessage
|
|
252
258
|
| typeof PersistenceError
|
|
259
|
+
| typeof EntityNotAssignedToRunner
|
|
253
260
|
>
|
|
254
261
|
| HttpApiEndpoint.HttpApiEndpoint<
|
|
255
262
|
`${_Tag}Discard`,
|
|
@@ -124,7 +124,7 @@ export class Sharding extends Context.Service<Sharding, {
|
|
|
124
124
|
entityId: string
|
|
125
125
|
) => RpcClient.RpcClient.From<
|
|
126
126
|
Rpcs,
|
|
127
|
-
MailboxFull | AlreadyProcessingMessage | PersistenceError
|
|
127
|
+
MailboxFull | AlreadyProcessingMessage | PersistenceError | EntityNotAssignedToRunner
|
|
128
128
|
>
|
|
129
129
|
>
|
|
130
130
|
|
|
@@ -178,7 +178,7 @@ export class Sharding extends Context.Service<Sharding, {
|
|
|
178
178
|
discard: boolean
|
|
179
179
|
) => Effect.Effect<
|
|
180
180
|
void,
|
|
181
|
-
MailboxFull | AlreadyProcessingMessage | PersistenceError
|
|
181
|
+
MailboxFull | AlreadyProcessingMessage | PersistenceError | EntityNotAssignedToRunner
|
|
182
182
|
>
|
|
183
183
|
|
|
184
184
|
/**
|
|
@@ -967,18 +967,40 @@ const make = Effect.gen(function*() {
|
|
|
967
967
|
retries?: number
|
|
968
968
|
): Effect.Effect<
|
|
969
969
|
void,
|
|
970
|
-
MailboxFull | AlreadyProcessingMessage | PersistenceError
|
|
970
|
+
MailboxFull | AlreadyProcessingMessage | PersistenceError | EntityNotAssignedToRunner
|
|
971
971
|
> {
|
|
972
972
|
const isPersisted = Context.get(
|
|
973
973
|
message._tag === "OutgoingRequest" ? message.annotations : message.rpc.annotations,
|
|
974
974
|
Persisted
|
|
975
975
|
)
|
|
976
|
+
const shouldFail = !discard &&
|
|
977
|
+
(message._tag === "OutgoingRequest" || message.envelope._tag === "AckChunk")
|
|
978
|
+
const abandon = (error: EntityNotAssignedToRunner) => {
|
|
979
|
+
if (!isPersisted) {
|
|
980
|
+
return shouldFail
|
|
981
|
+
? Effect.fail(error)
|
|
982
|
+
: Effect.logDebug("Abandoning outgoing message during shutdown", message.envelope.address)
|
|
983
|
+
}
|
|
984
|
+
const persist = message._tag === "OutgoingRequest"
|
|
985
|
+
? storage.saveRequest(message)
|
|
986
|
+
: storage.saveEnvelope(message)
|
|
987
|
+
return Effect.catchTag(persist, "MalformedMessage", Effect.die).pipe(
|
|
988
|
+
Effect.andThen(
|
|
989
|
+
shouldFail
|
|
990
|
+
? Effect.fail(error)
|
|
991
|
+
: Effect.logWarning("Persisting outgoing message abandoned during shutdown", message.envelope.address)
|
|
992
|
+
)
|
|
993
|
+
)
|
|
994
|
+
}
|
|
976
995
|
return Effect.catchFilter(
|
|
977
996
|
Effect.suspend(() => {
|
|
978
997
|
const address = message.envelope.address
|
|
979
998
|
if (isPersisted && !storageEnabled) {
|
|
980
999
|
return Effect.die("Sharding.sendOutgoing: Persisted messages require MessageStorage")
|
|
981
1000
|
}
|
|
1001
|
+
if (shouldFail && MutableRef.get(isShutdown)) {
|
|
1002
|
+
return Effect.fail(new EntityNotAssignedToRunner({ address }))
|
|
1003
|
+
}
|
|
982
1004
|
const maybeRunner = MutableHashMap.get(shardAssignments, address.shardId)
|
|
983
1005
|
const runnerIsLocal = Option.isSome(maybeRunner) && isLocalRunner(maybeRunner.value)
|
|
984
1006
|
if (isPersisted) {
|
|
@@ -1003,17 +1025,7 @@ const make = Effect.gen(function*() {
|
|
|
1003
1025
|
const cannotRecover = MutableRef.get(isShutdown) ||
|
|
1004
1026
|
(targetManager !== undefined && targetManager.status !== "alive")
|
|
1005
1027
|
if (cannotRecover) {
|
|
1006
|
-
|
|
1007
|
-
return Effect.logDebug("Abandoning outgoing message during shutdown", message.envelope.address)
|
|
1008
|
-
}
|
|
1009
|
-
const persist = message._tag === "OutgoingRequest"
|
|
1010
|
-
? storage.saveRequest(message)
|
|
1011
|
-
: storage.saveEnvelope(message)
|
|
1012
|
-
return Effect.catchTag(persist, "MalformedMessage", Effect.die).pipe(
|
|
1013
|
-
Effect.andThen(
|
|
1014
|
-
Effect.logWarning("Persisting outgoing message abandoned during shutdown", message.envelope.address)
|
|
1015
|
-
)
|
|
1016
|
-
)
|
|
1028
|
+
return abandon(error)
|
|
1017
1029
|
}
|
|
1018
1030
|
}
|
|
1019
1031
|
if (retries === 0) {
|
|
@@ -1183,7 +1195,7 @@ const make = Effect.gen(function*() {
|
|
|
1183
1195
|
Entity<any, any>,
|
|
1184
1196
|
(entityId: string) => RpcClient.RpcClient<
|
|
1185
1197
|
any,
|
|
1186
|
-
MailboxFull | AlreadyProcessingMessage
|
|
1198
|
+
MailboxFull | AlreadyProcessingMessage | EntityNotAssignedToRunner
|
|
1187
1199
|
>,
|
|
1188
1200
|
never
|
|
1189
1201
|
> = yield* ResourceMap.make(
|
|
@@ -1196,7 +1208,7 @@ const make = Effect.gen(function*() {
|
|
|
1196
1208
|
flatten: true,
|
|
1197
1209
|
onFromClient(options): Effect.Effect<
|
|
1198
1210
|
void,
|
|
1199
|
-
MailboxFull | AlreadyProcessingMessage | PersistenceError
|
|
1211
|
+
MailboxFull | AlreadyProcessingMessage | PersistenceError | EntityNotAssignedToRunner
|
|
1200
1212
|
> {
|
|
1201
1213
|
const address = Context.getUnsafe(options.context, ClientAddressTag)
|
|
1202
1214
|
switch (options.message._tag) {
|
|
@@ -1337,7 +1349,7 @@ const make = Effect.gen(function*() {
|
|
|
1337
1349
|
const makeClient = <Type extends string, Rpcs extends Rpc.Any>(entity: Entity<Type, Rpcs>): Effect.Effect<
|
|
1338
1350
|
(
|
|
1339
1351
|
entityId: string
|
|
1340
|
-
) => RpcClient.RpcClient.From<Rpcs, MailboxFull | AlreadyProcessingMessage>
|
|
1352
|
+
) => RpcClient.RpcClient.From<Rpcs, MailboxFull | AlreadyProcessingMessage | EntityNotAssignedToRunner>
|
|
1341
1353
|
> => clients.get(entity) as any
|
|
1342
1354
|
|
|
1343
1355
|
const clientRespondDiscard = (_reply: Reply.Reply<any>) => Effect.void
|
|
@@ -19,14 +19,15 @@ import type { Identity } from "./EventLog.ts"
|
|
|
19
19
|
import { makeGetIdentityRootSecretMaterial } from "./internal/identityRootSecretDerivation.ts"
|
|
20
20
|
|
|
21
21
|
/**
|
|
22
|
-
* Schema for an encrypted journal entry paired with
|
|
23
|
-
* entry.
|
|
22
|
+
* Schema for an encrypted journal entry paired with its initialization vector
|
|
23
|
+
* and the id of the original entry.
|
|
24
24
|
*
|
|
25
25
|
* @category models
|
|
26
26
|
* @since 4.0.0
|
|
27
27
|
*/
|
|
28
28
|
export const EncryptedEntry = Schema.Struct({
|
|
29
29
|
entryId: EntryId,
|
|
30
|
+
iv: Transferable.Uint8Array,
|
|
30
31
|
encryptedEntry: Transferable.Uint8Array
|
|
31
32
|
})
|
|
32
33
|
|
|
@@ -76,10 +77,12 @@ export class EventLogEncryption extends Context.Service<EventLogEncryption, {
|
|
|
76
77
|
readonly encrypt: (
|
|
77
78
|
identity: Identity["Service"],
|
|
78
79
|
entries: ReadonlyArray<Entry>
|
|
79
|
-
) => Effect.Effect<
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
80
|
+
) => Effect.Effect<
|
|
81
|
+
ReadonlyArray<{
|
|
82
|
+
readonly iv: Uint8Array<ArrayBuffer>
|
|
83
|
+
readonly encryptedEntry: Uint8Array<ArrayBuffer>
|
|
84
|
+
}>
|
|
85
|
+
>
|
|
83
86
|
readonly decrypt: (
|
|
84
87
|
identity: Identity["Service"],
|
|
85
88
|
entries: ReadonlyArray<EncryptedRemoteEntry>
|
|
@@ -104,22 +107,18 @@ export const makeEncryptionSubtle = (crypto: Crypto): Effect.Effect<EventLogEncr
|
|
|
104
107
|
encrypt: Effect.fnUntraced(function*(identity, entries) {
|
|
105
108
|
const data = yield* Effect.orDie(Entry.encodeArray(entries))
|
|
106
109
|
const key = (yield* getIdentityRootSecretMaterial(identity)).encryptionKey
|
|
107
|
-
|
|
108
|
-
const encryptedEntries = yield* Effect.promise(() =>
|
|
110
|
+
return yield* Effect.promise(() =>
|
|
109
111
|
Promise.all(
|
|
110
|
-
data.map((entry) =>
|
|
111
|
-
crypto.
|
|
112
|
+
data.map((entry) => {
|
|
113
|
+
const iv = crypto.getRandomValues(new Uint8Array(12))
|
|
114
|
+
return crypto.subtle.encrypt(
|
|
112
115
|
{ name: "AES-GCM", iv: toBufferSource(iv), tagLength: 128 },
|
|
113
116
|
key,
|
|
114
117
|
toBufferSource(entry)
|
|
115
|
-
)
|
|
116
|
-
)
|
|
118
|
+
).then((encryptedEntry) => ({ iv, encryptedEntry: new Uint8Array(encryptedEntry) }))
|
|
119
|
+
})
|
|
117
120
|
)
|
|
118
121
|
)
|
|
119
|
-
return {
|
|
120
|
-
iv,
|
|
121
|
-
encryptedEntries: encryptedEntries.map((entry) => new Uint8Array(entry))
|
|
122
|
-
}
|
|
123
122
|
}),
|
|
124
123
|
decrypt: Effect.fnUntraced(function*(identity, entries) {
|
|
125
124
|
const key = (yield* getIdentityRootSecretMaterial(identity)).encryptionKey
|
|
@@ -261,8 +261,8 @@ export class WriteChunkedRpc extends Rpc.make("EventLog.WriteChunked", {
|
|
|
261
261
|
*
|
|
262
262
|
* **Details**
|
|
263
263
|
*
|
|
264
|
-
* It includes the client public key, target store id,
|
|
265
|
-
*
|
|
264
|
+
* It includes the client public key, target store id, and encrypted entries
|
|
265
|
+
* with their AES-GCM initialization vectors.
|
|
266
266
|
*
|
|
267
267
|
* @category protocols
|
|
268
268
|
* @since 4.0.0
|
|
@@ -270,7 +270,6 @@ export class WriteChunkedRpc extends Rpc.make("EventLog.WriteChunked", {
|
|
|
270
270
|
export class WriteEntries extends Schema.Class<WriteEntries>("effect/eventlog/EventLogRemote/WriteEntries")({
|
|
271
271
|
publicKey: Schema.String,
|
|
272
272
|
storeId: StoreId,
|
|
273
|
-
iv: Transferable.Uint8Array,
|
|
274
273
|
encryptedEntries: Schema.Array(EncryptedEntry)
|
|
275
274
|
}) {
|
|
276
275
|
static FromMsgpack = Msgpack.schema(WriteEntries)
|
|
@@ -307,14 +307,14 @@ export const makeEncrypted = Effect.gen(function*(): Effect.fn.Return<
|
|
|
307
307
|
return yield* makeWith({
|
|
308
308
|
encodeWrite: (options) =>
|
|
309
309
|
encryption.encrypt(options.identity, options.entries).pipe(
|
|
310
|
-
Effect.flatMap((
|
|
310
|
+
Effect.flatMap((encryptedEntries) =>
|
|
311
311
|
new WriteEntries({
|
|
312
312
|
publicKey: options.identity.publicKey,
|
|
313
313
|
storeId: options.storeId,
|
|
314
|
-
|
|
315
|
-
encryptedEntries: msg.encryptedEntries.map((entry, i) => ({
|
|
314
|
+
encryptedEntries: encryptedEntries.map((entry, i) => ({
|
|
316
315
|
entryId: options.entries[i].id,
|
|
317
|
-
|
|
316
|
+
iv: entry.iv,
|
|
317
|
+
encryptedEntry: entry.encryptedEntry
|
|
318
318
|
}))
|
|
319
319
|
}).encoded
|
|
320
320
|
)
|