@dxos/functions 0.8.4-main.8360d9e660 → 0.8.4-main.8baae0fced
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/LICENSE +102 -5
- package/README.md +1 -1
- package/dist/lib/neutral/index.mjs +294 -935
- package/dist/lib/neutral/index.mjs.map +4 -4
- package/dist/lib/neutral/meta.json +1 -1
- package/dist/types/src/index.d.ts +0 -2
- package/dist/types/src/index.d.ts.map +1 -1
- package/dist/types/src/protocol/functions-ai-http-client.d.ts.map +1 -1
- package/dist/types/src/protocol/functions-ai-http-client.test.d.ts +2 -0
- package/dist/types/src/protocol/functions-ai-http-client.test.d.ts.map +1 -0
- package/dist/types/src/protocol/protocol.d.ts +19 -2
- package/dist/types/src/protocol/protocol.d.ts.map +1 -1
- package/dist/types/src/sdk.d.ts +5 -112
- package/dist/types/src/sdk.d.ts.map +1 -1
- package/dist/types/src/services/credentials.d.ts +15 -38
- package/dist/types/src/services/credentials.d.ts.map +1 -1
- package/dist/types/src/services/function-invocation-service.d.ts +8 -6
- package/dist/types/src/services/function-invocation-service.d.ts.map +1 -1
- package/dist/types/src/services/index.d.ts +1 -4
- package/dist/types/src/services/index.d.ts.map +1 -1
- package/dist/types/src/services/queues.d.ts +1 -46
- package/dist/types/src/services/queues.d.ts.map +1 -1
- package/dist/types/src/services/tracing.d.ts +1 -84
- package/dist/types/src/services/tracing.d.ts.map +1 -1
- package/dist/types/src/types/index.d.ts +0 -4
- package/dist/types/src/types/index.d.ts.map +1 -1
- package/dist/types/src/types/url.d.ts +1 -1
- package/dist/types/src/types/url.d.ts.map +1 -1
- package/dist/types/tsconfig.tsbuildinfo +1 -1
- package/package.json +18 -17
- package/src/index.ts +0 -2
- package/src/protocol/functions-ai-http-client.test.ts +105 -0
- package/src/protocol/functions-ai-http-client.ts +75 -1
- package/src/protocol/protocol.test.ts +9 -10
- package/src/protocol/protocol.ts +255 -58
- package/src/sdk.ts +12 -278
- package/src/services/credentials.ts +76 -120
- package/src/services/function-invocation-service.ts +9 -10
- package/src/services/index.ts +1 -4
- package/src/services/queues.ts +1 -78
- package/src/services/tracing.ts +0 -159
- package/src/types/index.ts +0 -4
- package/src/types/url.ts +1 -1
- package/dist/types/src/errors.d.ts +0 -121
- package/dist/types/src/errors.d.ts.map +0 -1
- package/dist/types/src/example/fib.d.ts +0 -7
- package/dist/types/src/example/fib.d.ts.map +0 -1
- package/dist/types/src/example/forex-effect.d.ts +0 -3
- package/dist/types/src/example/forex-effect.d.ts.map +0 -1
- package/dist/types/src/example/index.d.ts +0 -12
- package/dist/types/src/example/index.d.ts.map +0 -1
- package/dist/types/src/example/reply.d.ts +0 -3
- package/dist/types/src/example/reply.d.ts.map +0 -1
- package/dist/types/src/example/sleep.d.ts +0 -5
- package/dist/types/src/example/sleep.d.ts.map +0 -1
- package/dist/types/src/operation-compatibility.test.d.ts +0 -2
- package/dist/types/src/operation-compatibility.test.d.ts.map +0 -1
- package/dist/types/src/services/event-logger.d.ts +0 -81
- package/dist/types/src/services/event-logger.d.ts.map +0 -1
- package/dist/types/src/types/Function.d.ts +0 -52
- package/dist/types/src/types/Function.d.ts.map +0 -1
- package/dist/types/src/types/Script.d.ts +0 -21
- package/dist/types/src/types/Script.d.ts.map +0 -1
- package/dist/types/src/types/Trigger.d.ts +0 -122
- package/dist/types/src/types/Trigger.d.ts.map +0 -1
- package/dist/types/src/types/TriggerEvent.d.ts +0 -75
- package/dist/types/src/types/TriggerEvent.d.ts.map +0 -1
- package/src/errors.ts +0 -21
- package/src/example/fib.ts +0 -32
- package/src/example/forex-effect.ts +0 -40
- package/src/example/index.ts +0 -13
- package/src/example/reply.ts +0 -21
- package/src/example/sleep.ts +0 -24
- package/src/operation-compatibility.test.ts +0 -185
- package/src/services/event-logger.ts +0 -127
- package/src/types/Function.ts +0 -83
- package/src/types/Script.ts +0 -38
- package/src/types/Trigger.ts +0 -154
- package/src/types/TriggerEvent.ts +0 -62
|
@@ -1,621 +1,12 @@
|
|
|
1
|
-
var __defProp = Object.defineProperty;
|
|
2
|
-
var __export = (target, all) => {
|
|
3
|
-
for (var name in all)
|
|
4
|
-
__defProp(target, name, { get: all[name], enumerable: true });
|
|
5
|
-
};
|
|
6
|
-
|
|
7
|
-
// src/errors.ts
|
|
8
|
-
import { BaseError } from "@dxos/errors";
|
|
9
|
-
var ServiceNotAvailableError = class extends BaseError.extend("ServiceNotAvailable", "Service not available") {
|
|
10
|
-
constructor(service, options) {
|
|
11
|
-
super({
|
|
12
|
-
context: {
|
|
13
|
-
service
|
|
14
|
-
},
|
|
15
|
-
...options
|
|
16
|
-
});
|
|
17
|
-
}
|
|
18
|
-
};
|
|
19
|
-
var FunctionNotFoundError = class extends BaseError.extend("FunctionNotFound", "Function not found") {
|
|
20
|
-
constructor(functionKey, options) {
|
|
21
|
-
super({
|
|
22
|
-
context: {
|
|
23
|
-
function: functionKey
|
|
24
|
-
},
|
|
25
|
-
...options
|
|
26
|
-
});
|
|
27
|
-
}
|
|
28
|
-
};
|
|
29
|
-
var FunctionError = class extends BaseError.extend("FunctionError", "Function invocation error") {
|
|
30
|
-
};
|
|
31
|
-
var TriggerStateNotFoundError = class extends BaseError.extend("TriggerStateNotFound", "Trigger state not found") {
|
|
32
|
-
};
|
|
33
|
-
|
|
34
|
-
// src/example/fib.ts
|
|
35
|
-
import * as Effect2 from "effect/Effect";
|
|
36
|
-
import * as Schema6 from "effect/Schema";
|
|
37
|
-
|
|
38
|
-
// src/sdk.ts
|
|
39
|
-
import * as Effect from "effect/Effect";
|
|
40
|
-
import * as Schema5 from "effect/Schema";
|
|
41
|
-
import { JsonSchema as JsonSchema2, Obj as Obj5 } from "@dxos/echo";
|
|
42
|
-
import { assertArgument, failedInvariant } from "@dxos/invariant";
|
|
43
|
-
import { Operation } from "@dxos/operation";
|
|
44
|
-
|
|
45
|
-
// src/types/Function.ts
|
|
46
|
-
var Function_exports = {};
|
|
47
|
-
__export(Function_exports, {
|
|
48
|
-
Function: () => Function,
|
|
49
|
-
make: () => make2,
|
|
50
|
-
setFrom: () => setFrom
|
|
51
|
-
});
|
|
52
|
-
import * as Schema2 from "effect/Schema";
|
|
53
|
-
import { Annotation as Annotation2, JsonSchema, Obj as Obj2, Ref as Ref2, Type as Type2 } from "@dxos/echo";
|
|
54
|
-
import { SystemTypeAnnotation } from "@dxos/echo/internal";
|
|
55
|
-
|
|
56
|
-
// src/types/Script.ts
|
|
57
|
-
var Script_exports = {};
|
|
58
|
-
__export(Script_exports, {
|
|
59
|
-
Script: () => Script,
|
|
60
|
-
make: () => make
|
|
61
|
-
});
|
|
62
|
-
import * as Schema from "effect/Schema";
|
|
63
|
-
import { Annotation, Obj, Ref, Type } from "@dxos/echo";
|
|
64
|
-
import { FormInputAnnotation } from "@dxos/echo/internal";
|
|
65
|
-
import { Text } from "@dxos/schema";
|
|
66
|
-
var Script = Schema.Struct({
|
|
67
|
-
name: Schema.String.pipe(Schema.optional),
|
|
68
|
-
description: Schema.String.pipe(Schema.optional),
|
|
69
|
-
// TODO(burdon): Change to hash of deployed content.
|
|
70
|
-
// Whether source has changed since last deploy.
|
|
71
|
-
changed: Schema.Boolean.pipe(FormInputAnnotation.set(false), Schema.optional),
|
|
72
|
-
source: Ref.Ref(Text.Text).pipe(FormInputAnnotation.set(false))
|
|
73
|
-
}).pipe(Type.object({
|
|
74
|
-
typename: "org.dxos.type.script",
|
|
75
|
-
version: "0.1.0"
|
|
76
|
-
}), Annotation.LabelAnnotation.set([
|
|
77
|
-
"name"
|
|
78
|
-
]), Annotation.IconAnnotation.set({
|
|
79
|
-
icon: "ph--code--regular",
|
|
80
|
-
hue: "sky"
|
|
81
|
-
}));
|
|
82
|
-
var make = ({ source = "", ...props } = {}) => Obj.make(Script, {
|
|
83
|
-
...props,
|
|
84
|
-
source: Ref.make(Text.make(source))
|
|
85
|
-
});
|
|
86
|
-
|
|
87
|
-
// src/types/Function.ts
|
|
88
|
-
var Function = Schema2.Struct({
|
|
89
|
-
/**
|
|
90
|
-
* Global registry ID.
|
|
91
|
-
* NOTE: The `key` property refers to the original registry entry.
|
|
92
|
-
*/
|
|
93
|
-
// TODO(burdon): Create Format type for DXN-like ids, such as this and schema type.
|
|
94
|
-
// TODO(dmaretskyi): Consider making it part of ECHO meta.
|
|
95
|
-
// TODO(dmaretskyi): Make required.
|
|
96
|
-
key: Schema2.optional(Schema2.String).annotations({
|
|
97
|
-
description: "Unique registration key for the blueprint"
|
|
98
|
-
}),
|
|
99
|
-
name: Schema2.NonEmptyString,
|
|
100
|
-
version: Schema2.String,
|
|
101
|
-
description: Schema2.optional(Schema2.String),
|
|
102
|
-
/**
|
|
103
|
-
* ISO date string of the last deployment.
|
|
104
|
-
*/
|
|
105
|
-
updated: Schema2.optional(Schema2.String),
|
|
106
|
-
// Reference to a source script if it exists within ECHO.
|
|
107
|
-
// TODO(burdon): Don't ref ScriptType directly (core).
|
|
108
|
-
source: Schema2.optional(Ref2.Ref(Script)),
|
|
109
|
-
inputSchema: Schema2.optional(JsonSchema.JsonSchema),
|
|
110
|
-
outputSchema: Schema2.optional(JsonSchema.JsonSchema),
|
|
111
|
-
/**
|
|
112
|
-
* List of required services.
|
|
113
|
-
* Match the Context.Tag keys of the FunctionServices variants.
|
|
114
|
-
*/
|
|
115
|
-
services: Schema2.optional(Schema2.Array(Schema2.String)),
|
|
116
|
-
// Local binding to a function name.
|
|
117
|
-
binding: Schema2.optional(Schema2.String)
|
|
118
|
-
}).pipe(Type2.object({
|
|
119
|
-
typename: "org.dxos.type.function",
|
|
120
|
-
version: "0.1.0"
|
|
121
|
-
}), Annotation2.LabelAnnotation.set([
|
|
122
|
-
"name"
|
|
123
|
-
]), Annotation2.IconAnnotation.set({
|
|
124
|
-
icon: "ph--function--regular",
|
|
125
|
-
hue: "blue"
|
|
126
|
-
}), SystemTypeAnnotation.set(true));
|
|
127
|
-
var make2 = (props) => Obj2.make(Function, props);
|
|
128
|
-
var setFrom = (target, source) => {
|
|
129
|
-
Obj2.change(target, (t) => {
|
|
130
|
-
t.key = source.key ?? target.key;
|
|
131
|
-
t.name = source.name ?? target.name;
|
|
132
|
-
t.version = source.version;
|
|
133
|
-
t.description = source.description;
|
|
134
|
-
t.updated = source.updated;
|
|
135
|
-
t.inputSchema = source.inputSchema ? JSON.parse(JSON.stringify(source.inputSchema)) : void 0;
|
|
136
|
-
t.outputSchema = source.outputSchema ? JSON.parse(JSON.stringify(source.outputSchema)) : void 0;
|
|
137
|
-
Obj2.getMeta(t).keys = JSON.parse(JSON.stringify(Obj2.getMeta(source).keys));
|
|
138
|
-
});
|
|
139
|
-
};
|
|
140
|
-
|
|
141
|
-
// src/types/Trigger.ts
|
|
142
|
-
var Trigger_exports = {};
|
|
143
|
-
__export(Trigger_exports, {
|
|
144
|
-
EmailSpec: () => EmailSpec,
|
|
145
|
-
Kinds: () => Kinds,
|
|
146
|
-
QueueSpec: () => QueueSpec,
|
|
147
|
-
Spec: () => Spec,
|
|
148
|
-
SubscriptionSpec: () => SubscriptionSpec,
|
|
149
|
-
TimerSpec: () => TimerSpec,
|
|
150
|
-
Trigger: () => Trigger,
|
|
151
|
-
WebhookSpec: () => WebhookSpec,
|
|
152
|
-
make: () => make3
|
|
153
|
-
});
|
|
154
|
-
import * as Schema3 from "effect/Schema";
|
|
155
|
-
import * as SchemaAST from "effect/SchemaAST";
|
|
156
|
-
import { Annotation as Annotation3, Obj as Obj3, QueryAST, Ref as Ref3, Type as Type3 } from "@dxos/echo";
|
|
157
|
-
import { OptionsAnnotationId, SystemTypeAnnotation as SystemTypeAnnotation2 } from "@dxos/echo/internal";
|
|
158
|
-
import { DXN } from "@dxos/keys";
|
|
159
|
-
import { Expando } from "@dxos/schema";
|
|
160
|
-
var Kinds = [
|
|
161
|
-
"email",
|
|
162
|
-
"queue",
|
|
163
|
-
"subscription",
|
|
164
|
-
"timer",
|
|
165
|
-
"webhook"
|
|
166
|
-
];
|
|
167
|
-
var kindLiteralAnnotations = {
|
|
168
|
-
title: "Kind"
|
|
169
|
-
};
|
|
170
|
-
var EmailSpec = Schema3.Struct({
|
|
171
|
-
kind: Schema3.Literal("email").annotations(kindLiteralAnnotations)
|
|
172
|
-
});
|
|
173
|
-
var QueueSpec = Schema3.Struct({
|
|
174
|
-
kind: Schema3.Literal("queue").annotations(kindLiteralAnnotations),
|
|
175
|
-
// TODO(dmaretskyi): Change to a reference.
|
|
176
|
-
queue: DXN.Schema
|
|
177
|
-
});
|
|
178
|
-
var SubscriptionSpec = Schema3.Struct({
|
|
179
|
-
kind: Schema3.Literal("subscription").annotations(kindLiteralAnnotations),
|
|
180
|
-
query: Schema3.Struct({
|
|
181
|
-
raw: Schema3.optional(Schema3.String.annotations({
|
|
182
|
-
title: "Query"
|
|
183
|
-
})),
|
|
184
|
-
ast: QueryAST.Query
|
|
185
|
-
}),
|
|
186
|
-
options: Schema3.optional(Schema3.Struct({
|
|
187
|
-
// Watch changes to object (not just creation).
|
|
188
|
-
deep: Schema3.optional(Schema3.Boolean.annotations({
|
|
189
|
-
title: "Nested"
|
|
190
|
-
})),
|
|
191
|
-
// Debounce changes (delay in ms).
|
|
192
|
-
delay: Schema3.optional(Schema3.Number.annotations({
|
|
193
|
-
title: "Delay"
|
|
194
|
-
}))
|
|
195
|
-
}).annotations({
|
|
196
|
-
title: "Options"
|
|
197
|
-
}))
|
|
198
|
-
});
|
|
199
|
-
var TimerSpec = Schema3.Struct({
|
|
200
|
-
kind: Schema3.Literal("timer").annotations(kindLiteralAnnotations),
|
|
201
|
-
cron: Schema3.String.annotations({
|
|
202
|
-
title: "Cron",
|
|
203
|
-
[SchemaAST.ExamplesAnnotationId]: [
|
|
204
|
-
"0 0 * * *"
|
|
205
|
-
]
|
|
206
|
-
})
|
|
207
|
-
});
|
|
208
|
-
var WebhookSpec = Schema3.Struct({
|
|
209
|
-
kind: Schema3.Literal("webhook").annotations(kindLiteralAnnotations),
|
|
210
|
-
method: Schema3.optional(Schema3.String.annotations({
|
|
211
|
-
title: "Method",
|
|
212
|
-
[OptionsAnnotationId]: [
|
|
213
|
-
"GET",
|
|
214
|
-
"POST"
|
|
215
|
-
]
|
|
216
|
-
})),
|
|
217
|
-
port: Schema3.optional(Schema3.Number.annotations({
|
|
218
|
-
title: "Port"
|
|
219
|
-
}))
|
|
220
|
-
});
|
|
221
|
-
var Spec = Schema3.Union(EmailSpec, QueueSpec, SubscriptionSpec, TimerSpec, WebhookSpec).annotations({
|
|
222
|
-
title: "Trigger"
|
|
223
|
-
});
|
|
224
|
-
var TriggerSchema = Schema3.Struct({
|
|
225
|
-
/**
|
|
226
|
-
* Function or workflow to invoke.
|
|
227
|
-
*/
|
|
228
|
-
// TODO(dmaretskyi): Can be a Ref(FunctionType) or Ref(ComputeGraphType).
|
|
229
|
-
function: Schema3.optional(Ref3.Ref(Expando.Expando).annotations({
|
|
230
|
-
title: "Function"
|
|
231
|
-
})),
|
|
232
|
-
/**
|
|
233
|
-
* Only used for workflowSchema.
|
|
234
|
-
* Specifies the input node in the circuit.
|
|
235
|
-
* @deprecated Remove and enforce a single input node in all compute graphSchema.
|
|
236
|
-
*/
|
|
237
|
-
inputNodeId: Schema3.optional(Schema3.String.annotations({
|
|
238
|
-
title: "Input Node ID"
|
|
239
|
-
})),
|
|
240
|
-
// TODO(burdon): NO BOOLEAN PROPERTIES (enabld/disabled/paused, etc.)
|
|
241
|
-
// Need lint rule; or agent rule to require PR review for "boolean" key word.
|
|
242
|
-
enabled: Schema3.optional(Schema3.Boolean.annotations({
|
|
243
|
-
title: "Enabled"
|
|
244
|
-
})),
|
|
245
|
-
spec: Schema3.optional(Spec),
|
|
246
|
-
concurrency: Schema3.optional(Schema3.Number.annotations({
|
|
247
|
-
title: "Concurrency",
|
|
248
|
-
default: 1,
|
|
249
|
-
description: "Maximum number of concurrent invocations of the trigger. For queue triggers, this will process queue items in parallel."
|
|
250
|
-
})),
|
|
251
|
-
/**
|
|
252
|
-
* Passed as the input data to the function.
|
|
253
|
-
* Must match the function's input schema.
|
|
254
|
-
*
|
|
255
|
-
* @example
|
|
256
|
-
* {
|
|
257
|
-
* item: '{{event.item}}',
|
|
258
|
-
* instructions: 'Summarize and perform entity-extraction'
|
|
259
|
-
* mailbox: { '/': 'dxn:echo:AAA:ZZZ' }
|
|
260
|
-
* }
|
|
261
|
-
*/
|
|
262
|
-
input: Schema3.optional(Schema3.Record({
|
|
263
|
-
key: Schema3.String,
|
|
264
|
-
value: Schema3.Any
|
|
265
|
-
}))
|
|
266
|
-
}).pipe(Type3.object({
|
|
267
|
-
typename: "org.dxos.type.trigger",
|
|
268
|
-
version: "0.1.0"
|
|
269
|
-
}), Annotation3.IconAnnotation.set({
|
|
270
|
-
icon: "ph--lightning--regular",
|
|
271
|
-
hue: "yellow"
|
|
272
|
-
}), SystemTypeAnnotation2.set(true));
|
|
273
|
-
var Trigger = TriggerSchema;
|
|
274
|
-
var make3 = (props) => Obj3.make(Trigger, props);
|
|
275
|
-
|
|
276
|
-
// src/types/TriggerEvent.ts
|
|
277
|
-
var TriggerEvent_exports = {};
|
|
278
|
-
__export(TriggerEvent_exports, {
|
|
279
|
-
EmailEvent: () => EmailEvent,
|
|
280
|
-
QueueEvent: () => QueueEvent,
|
|
281
|
-
SubscriptionEvent: () => SubscriptionEvent,
|
|
282
|
-
TimerEvent: () => TimerEvent,
|
|
283
|
-
TriggerEvent: () => TriggerEvent,
|
|
284
|
-
WebhookEvent: () => WebhookEvent
|
|
285
|
-
});
|
|
286
|
-
import * as Schema4 from "effect/Schema";
|
|
287
|
-
import { DXN as DXN2, Obj as Obj4, Ref as Ref4 } from "@dxos/echo";
|
|
288
|
-
var EmailEvent = Schema4.Struct({
|
|
289
|
-
from: Schema4.String,
|
|
290
|
-
to: Schema4.String,
|
|
291
|
-
subject: Schema4.String,
|
|
292
|
-
created: Schema4.String,
|
|
293
|
-
body: Schema4.String
|
|
294
|
-
});
|
|
295
|
-
var QueueEvent = Schema4.Struct({
|
|
296
|
-
queue: DXN2.Schema,
|
|
297
|
-
item: Schema4.Any,
|
|
298
|
-
cursor: Schema4.String
|
|
299
|
-
});
|
|
300
|
-
var SubscriptionEvent = Schema4.Struct({
|
|
301
|
-
/**
|
|
302
|
-
* Type of the mutation.
|
|
303
|
-
*/
|
|
304
|
-
// TODO(dmaretskyi): Specify enum.
|
|
305
|
-
type: Schema4.String,
|
|
306
|
-
/**
|
|
307
|
-
* Reference to the object that was changed or created.
|
|
308
|
-
*/
|
|
309
|
-
subject: Ref4.Ref(Obj4.Unknown),
|
|
310
|
-
/**
|
|
311
|
-
* @deprecated
|
|
312
|
-
*/
|
|
313
|
-
changedObjectId: Schema4.optional(Schema4.String)
|
|
314
|
-
});
|
|
315
|
-
var TimerEvent = Schema4.Struct({
|
|
316
|
-
tick: Schema4.Number
|
|
317
|
-
});
|
|
318
|
-
var WebhookEvent = Schema4.Struct({
|
|
319
|
-
url: Schema4.String,
|
|
320
|
-
method: Schema4.Literal("GET", "POST"),
|
|
321
|
-
headers: Schema4.Record({
|
|
322
|
-
key: Schema4.String,
|
|
323
|
-
value: Schema4.String
|
|
324
|
-
}),
|
|
325
|
-
bodyText: Schema4.String
|
|
326
|
-
});
|
|
327
|
-
var TriggerEvent = Schema4.Union(EmailEvent, QueueEvent, SubscriptionEvent, TimerEvent, WebhookEvent);
|
|
328
|
-
|
|
329
|
-
// src/types/url.ts
|
|
330
|
-
var FUNCTIONS_META_KEY = "org.dxos.service.function";
|
|
331
|
-
var FUNCTIONS_PRESET_META_KEY = "org.dxos.service.function-preset";
|
|
332
|
-
var getUserFunctionIdInMetadata = (meta) => {
|
|
333
|
-
return meta.keys.find((key) => key.source === FUNCTIONS_META_KEY)?.id;
|
|
334
|
-
};
|
|
335
|
-
var setUserFunctionIdInMetadata = (meta, functionId) => {
|
|
336
|
-
const key = meta.keys.find((key2) => key2.source === FUNCTIONS_META_KEY);
|
|
337
|
-
if (key) {
|
|
338
|
-
if (key.id !== functionId) {
|
|
339
|
-
throw new Error("Metadata mismatch");
|
|
340
|
-
}
|
|
341
|
-
} else {
|
|
342
|
-
meta.keys.push({
|
|
343
|
-
source: FUNCTIONS_META_KEY,
|
|
344
|
-
id: functionId
|
|
345
|
-
});
|
|
346
|
-
}
|
|
347
|
-
};
|
|
348
|
-
|
|
349
|
-
// src/sdk.ts
|
|
350
|
-
var typeId = /* @__PURE__ */ Symbol.for("@dxos/functions/FunctionDefinition");
|
|
351
|
-
var defineFunction = ({ key, name, description, inputSchema, outputSchema = Schema5.Any, handler, types, services }) => {
|
|
352
|
-
if (!Schema5.isSchema(inputSchema)) {
|
|
353
|
-
throw new Error("Input schema must be a valid schema");
|
|
354
|
-
}
|
|
355
|
-
if (typeof handler !== "function") {
|
|
356
|
-
throw new Error("Handler must be a function");
|
|
357
|
-
}
|
|
358
|
-
const limit = Error.stackTraceLimit;
|
|
359
|
-
Error.stackTraceLimit = 2;
|
|
360
|
-
const traceError = new Error();
|
|
361
|
-
Error.stackTraceLimit = limit;
|
|
362
|
-
let cache = false;
|
|
363
|
-
const captureStackTrace = () => {
|
|
364
|
-
if (cache !== false) {
|
|
365
|
-
return cache;
|
|
366
|
-
}
|
|
367
|
-
if (traceError.stack !== void 0) {
|
|
368
|
-
const stack = traceError.stack.split("\n");
|
|
369
|
-
if (stack[2] !== void 0) {
|
|
370
|
-
cache = stack[2].trim();
|
|
371
|
-
return cache;
|
|
372
|
-
}
|
|
373
|
-
}
|
|
374
|
-
};
|
|
375
|
-
const handlerWithSpan = (...args) => {
|
|
376
|
-
const result = handler(...args);
|
|
377
|
-
if (Effect.isEffect(result)) {
|
|
378
|
-
return Effect.withSpan(result, `${key ?? name}`, {
|
|
379
|
-
captureStackTrace
|
|
380
|
-
});
|
|
381
|
-
}
|
|
382
|
-
return result;
|
|
383
|
-
};
|
|
384
|
-
return {
|
|
385
|
-
[typeId]: true,
|
|
386
|
-
key,
|
|
387
|
-
name,
|
|
388
|
-
description,
|
|
389
|
-
inputSchema,
|
|
390
|
-
outputSchema,
|
|
391
|
-
handler: handlerWithSpan,
|
|
392
|
-
types: types ?? [],
|
|
393
|
-
services: !services ? [] : getServiceKeys(services)
|
|
394
|
-
};
|
|
395
|
-
};
|
|
396
|
-
var getServiceKeys = (services) => {
|
|
397
|
-
return services.map((tag) => {
|
|
398
|
-
if (typeof tag.key === "string") {
|
|
399
|
-
return tag.key;
|
|
400
|
-
}
|
|
401
|
-
failedInvariant();
|
|
402
|
-
});
|
|
403
|
-
};
|
|
404
|
-
var toOperation = (functionDef) => {
|
|
405
|
-
const op = Operation.make({
|
|
406
|
-
schema: {
|
|
407
|
-
input: functionDef.inputSchema,
|
|
408
|
-
output: functionDef.outputSchema ?? Schema5.Any
|
|
409
|
-
},
|
|
410
|
-
meta: {
|
|
411
|
-
key: functionDef.key,
|
|
412
|
-
name: functionDef.name,
|
|
413
|
-
description: functionDef.description
|
|
414
|
-
}
|
|
415
|
-
});
|
|
416
|
-
const operationHandler = (input) => {
|
|
417
|
-
const result = functionDef.handler({
|
|
418
|
-
context: {},
|
|
419
|
-
data: input
|
|
420
|
-
});
|
|
421
|
-
if (Effect.isEffect(result)) {
|
|
422
|
-
return result;
|
|
423
|
-
}
|
|
424
|
-
if (result instanceof Promise) {
|
|
425
|
-
return Effect.tryPromise(() => result);
|
|
426
|
-
}
|
|
427
|
-
return Effect.succeed(result);
|
|
428
|
-
};
|
|
429
|
-
return {
|
|
430
|
-
...op,
|
|
431
|
-
handler: operationHandler
|
|
432
|
-
};
|
|
433
|
-
};
|
|
434
|
-
var FunctionDefinition = {
|
|
435
|
-
make: defineFunction,
|
|
436
|
-
isFunction: (value2) => {
|
|
437
|
-
return typeof value2 === "object" && value2 !== null && /* @__PURE__ */ Symbol.for("@dxos/functions/FunctionDefinition") in value2;
|
|
438
|
-
},
|
|
439
|
-
serialize: (functionDef) => {
|
|
440
|
-
assertArgument(FunctionDefinition.isFunction(functionDef), "functionDef");
|
|
441
|
-
return serializeFunction(functionDef);
|
|
442
|
-
},
|
|
443
|
-
deserialize: (functionObj) => {
|
|
444
|
-
assertArgument(Obj5.instanceOf(Function_exports.Function, functionObj), "functionObj");
|
|
445
|
-
return deserializeFunction(functionObj);
|
|
446
|
-
},
|
|
447
|
-
toOperation
|
|
448
|
-
};
|
|
449
|
-
var serializeFunction = (functionDef) => {
|
|
450
|
-
const fn4 = Function_exports.make({
|
|
451
|
-
key: functionDef.key,
|
|
452
|
-
name: functionDef.name,
|
|
453
|
-
version: "0.1.0",
|
|
454
|
-
description: functionDef.description,
|
|
455
|
-
inputSchema: JsonSchema2.toJsonSchema(functionDef.inputSchema),
|
|
456
|
-
outputSchema: !functionDef.outputSchema ? void 0 : JsonSchema2.toJsonSchema(functionDef.outputSchema),
|
|
457
|
-
services: functionDef.services
|
|
458
|
-
});
|
|
459
|
-
if (functionDef.meta?.deployedFunctionId) {
|
|
460
|
-
Obj5.change(fn4, (fn5) => setUserFunctionIdInMetadata(Obj5.getMeta(fn5), functionDef.meta.deployedFunctionId));
|
|
461
|
-
}
|
|
462
|
-
return fn4;
|
|
463
|
-
};
|
|
464
|
-
var deserializeFunction = (functionObj) => {
|
|
465
|
-
return {
|
|
466
|
-
[typeId]: true,
|
|
467
|
-
// TODO(dmaretskyi): Fix key.
|
|
468
|
-
key: functionObj.key ?? functionObj.name,
|
|
469
|
-
name: functionObj.name,
|
|
470
|
-
description: functionObj.description,
|
|
471
|
-
inputSchema: !functionObj.inputSchema ? Schema5.Unknown : JsonSchema2.toEffectSchema(functionObj.inputSchema),
|
|
472
|
-
outputSchema: !functionObj.outputSchema ? void 0 : JsonSchema2.toEffectSchema(functionObj.outputSchema),
|
|
473
|
-
// TODO(dmaretskyi): This should throw error.
|
|
474
|
-
handler: () => {
|
|
475
|
-
},
|
|
476
|
-
services: functionObj.services ?? [],
|
|
477
|
-
types: [],
|
|
478
|
-
meta: {
|
|
479
|
-
deployedFunctionId: getUserFunctionIdInMetadata(Obj5.getMeta(functionObj))
|
|
480
|
-
}
|
|
481
|
-
};
|
|
482
|
-
};
|
|
483
|
-
|
|
484
|
-
// src/example/fib.ts
|
|
485
|
-
var fib_default = defineFunction({
|
|
486
|
-
key: "example.org/function/fib",
|
|
487
|
-
name: "Fibonacci",
|
|
488
|
-
description: "Function that calculates a Fibonacci number",
|
|
489
|
-
inputSchema: Schema6.Struct({
|
|
490
|
-
iterations: Schema6.optional(Schema6.Number).annotations({
|
|
491
|
-
description: "Number of iterations",
|
|
492
|
-
default: 1e5
|
|
493
|
-
})
|
|
494
|
-
}),
|
|
495
|
-
outputSchema: Schema6.Struct({
|
|
496
|
-
result: Schema6.String
|
|
497
|
-
}),
|
|
498
|
-
handler: Effect2.fn(function* ({ data: { iterations = 1e5 } }) {
|
|
499
|
-
let a = 0n;
|
|
500
|
-
let b = 1n;
|
|
501
|
-
for (let i = 0; i < iterations; i++) {
|
|
502
|
-
a += b;
|
|
503
|
-
b = a - b;
|
|
504
|
-
}
|
|
505
|
-
return {
|
|
506
|
-
result: a.toString()
|
|
507
|
-
};
|
|
508
|
-
})
|
|
509
|
-
});
|
|
510
|
-
|
|
511
|
-
// src/example/reply.ts
|
|
512
|
-
import * as Console from "effect/Console";
|
|
513
|
-
import * as Effect3 from "effect/Effect";
|
|
514
|
-
import * as Schema7 from "effect/Schema";
|
|
515
|
-
var reply_default = defineFunction({
|
|
516
|
-
key: "example.org/function/reply",
|
|
517
|
-
name: "Reply",
|
|
518
|
-
description: "Function that echoes the input",
|
|
519
|
-
inputSchema: Schema7.Any,
|
|
520
|
-
outputSchema: Schema7.Any,
|
|
521
|
-
handler: Effect3.fn(function* ({ data }) {
|
|
522
|
-
yield* Console.log("reply", {
|
|
523
|
-
data
|
|
524
|
-
});
|
|
525
|
-
return data;
|
|
526
|
-
})
|
|
527
|
-
});
|
|
528
|
-
|
|
529
|
-
// src/example/sleep.ts
|
|
530
|
-
import * as Effect4 from "effect/Effect";
|
|
531
|
-
import * as Schema8 from "effect/Schema";
|
|
532
|
-
var sleep_default = defineFunction({
|
|
533
|
-
key: "example.org/function/sleep",
|
|
534
|
-
name: "Sleep",
|
|
535
|
-
description: "Function that sleeps for a given amount of time",
|
|
536
|
-
inputSchema: Schema8.Struct({
|
|
537
|
-
duration: Schema8.optional(Schema8.Number).annotations({
|
|
538
|
-
description: "Milliseconds to sleep",
|
|
539
|
-
default: 1e5
|
|
540
|
-
})
|
|
541
|
-
}),
|
|
542
|
-
outputSchema: Schema8.Void,
|
|
543
|
-
handler: Effect4.fn(function* ({ data: { duration = 1e5 } }) {
|
|
544
|
-
yield* Effect4.sleep(duration);
|
|
545
|
-
})
|
|
546
|
-
});
|
|
547
|
-
|
|
548
|
-
// src/example/index.ts
|
|
549
|
-
var ExampleFunctions = {
|
|
550
|
-
Fibonacci: fib_default,
|
|
551
|
-
Reply: reply_default,
|
|
552
|
-
Sleep: sleep_default
|
|
553
|
-
};
|
|
554
|
-
|
|
555
1
|
// src/services/credentials.ts
|
|
556
2
|
import * as HttpClient from "@effect/platform/HttpClient";
|
|
557
3
|
import * as HttpClientRequest from "@effect/platform/HttpClientRequest";
|
|
558
|
-
import * as
|
|
559
|
-
import * as Effect5 from "effect/Effect";
|
|
4
|
+
import * as Effect from "effect/Effect";
|
|
560
5
|
import * as Layer from "effect/Layer";
|
|
561
6
|
import * as Redacted from "effect/Redacted";
|
|
562
|
-
import {
|
|
563
|
-
import { Database } from "@dxos/echo";
|
|
7
|
+
import { Credential } from "@dxos/compute";
|
|
8
|
+
import { Database, Query } from "@dxos/echo";
|
|
564
9
|
import { AccessToken } from "@dxos/types";
|
|
565
|
-
var CredentialsService = class _CredentialsService extends Context.Tag("@dxos/functions/CredentialsService")() {
|
|
566
|
-
static getCredential = (query) => Effect5.gen(function* () {
|
|
567
|
-
const credentials = yield* _CredentialsService;
|
|
568
|
-
return yield* Effect5.promise(() => credentials.getCredential(query));
|
|
569
|
-
});
|
|
570
|
-
static getApiKey = (query) => Effect5.gen(function* () {
|
|
571
|
-
const credential = yield* _CredentialsService.getCredential(query);
|
|
572
|
-
if (!credential.apiKey) {
|
|
573
|
-
throw new Error(`API key not found for service: ${query.service}`);
|
|
574
|
-
}
|
|
575
|
-
return Redacted.make(credential.apiKey);
|
|
576
|
-
});
|
|
577
|
-
static configuredLayer = (credentials) => Layer.succeed(_CredentialsService, new ConfiguredCredentialsService(credentials));
|
|
578
|
-
static layerConfig = (credentials) => Layer.effect(_CredentialsService, Effect5.gen(function* () {
|
|
579
|
-
const serviceCredentials = yield* Effect5.forEach(credentials, ({ service, apiKey }) => Effect5.gen(function* () {
|
|
580
|
-
return {
|
|
581
|
-
service,
|
|
582
|
-
apiKey: Redacted.value(yield* apiKey)
|
|
583
|
-
};
|
|
584
|
-
}));
|
|
585
|
-
return new ConfiguredCredentialsService(serviceCredentials);
|
|
586
|
-
}));
|
|
587
|
-
static layerFromDatabase = ({ caching = false } = {}) => Layer.effect(_CredentialsService, Effect5.gen(function* () {
|
|
588
|
-
const dbService = yield* Database.Service;
|
|
589
|
-
const cache = /* @__PURE__ */ new Map();
|
|
590
|
-
const queryCredentials = async (query) => {
|
|
591
|
-
const cacheKey = JSON.stringify(query);
|
|
592
|
-
if (caching && cache.has(cacheKey)) {
|
|
593
|
-
return cache.get(cacheKey);
|
|
594
|
-
}
|
|
595
|
-
const accessTokens = await dbService.db.query(Query.type(AccessToken.AccessToken)).run();
|
|
596
|
-
const credentials = accessTokens.filter((accessToken) => accessToken.source === query.service).map((accessToken) => ({
|
|
597
|
-
service: accessToken.source,
|
|
598
|
-
apiKey: accessToken.token
|
|
599
|
-
}));
|
|
600
|
-
if (caching) {
|
|
601
|
-
cache.set(cacheKey, credentials);
|
|
602
|
-
}
|
|
603
|
-
return credentials;
|
|
604
|
-
};
|
|
605
|
-
return {
|
|
606
|
-
getCredential: async (query) => {
|
|
607
|
-
const credentials = await queryCredentials(query);
|
|
608
|
-
if (credentials.length === 0) {
|
|
609
|
-
throw new Error(`Credential not found for service: ${query.service}`);
|
|
610
|
-
}
|
|
611
|
-
return credentials[0];
|
|
612
|
-
},
|
|
613
|
-
queryCredentials: async (query) => {
|
|
614
|
-
return queryCredentials(query);
|
|
615
|
-
}
|
|
616
|
-
};
|
|
617
|
-
}));
|
|
618
|
-
};
|
|
619
10
|
var ConfiguredCredentialsService = class {
|
|
620
11
|
credentials;
|
|
621
12
|
constructor(credentials = []) {
|
|
@@ -640,277 +31,127 @@ var withAuthorization = (token, kind) => HttpClient.mapRequest((request) => {
|
|
|
640
31
|
const authorization = kind ? `${kind} ${token}` : token;
|
|
641
32
|
return HttpClientRequest.setHeader(request, "Authorization", authorization);
|
|
642
33
|
});
|
|
643
|
-
|
|
644
|
-
|
|
645
|
-
|
|
646
|
-
import * as Effect7 from "effect/Effect";
|
|
647
|
-
import * as Layer3 from "effect/Layer";
|
|
648
|
-
import * as Schema9 from "effect/Schema";
|
|
649
|
-
import { Obj as Obj7, Type as Type4 } from "@dxos/echo";
|
|
650
|
-
import { invariant } from "@dxos/invariant";
|
|
651
|
-
import { LogLevel, log as log2 } from "@dxos/log";
|
|
652
|
-
|
|
653
|
-
// src/services/tracing.ts
|
|
654
|
-
import * as Context2 from "effect/Context";
|
|
655
|
-
import * as Effect6 from "effect/Effect";
|
|
656
|
-
import * as Layer2 from "effect/Layer";
|
|
657
|
-
import { AgentStatus } from "@dxos/ai";
|
|
658
|
-
import { Obj as Obj6 } from "@dxos/echo";
|
|
659
|
-
import { ObjectId } from "@dxos/keys";
|
|
660
|
-
import { Message } from "@dxos/types";
|
|
661
|
-
var TracingService = class _TracingService extends Context2.Tag("@dxos/functions/TracingService")() {
|
|
662
|
-
static noop = {
|
|
663
|
-
getTraceContext: () => ({}),
|
|
664
|
-
write: () => {
|
|
665
|
-
},
|
|
666
|
-
traceInvocationStart: () => Effect6.sync(() => ({
|
|
667
|
-
invocationId: ObjectId.random(),
|
|
668
|
-
invocationTraceQueue: void 0
|
|
669
|
-
})),
|
|
670
|
-
traceInvocationEnd: () => Effect6.sync(() => {
|
|
671
|
-
})
|
|
672
|
-
};
|
|
673
|
-
static layerNoop = Layer2.succeed(_TracingService, _TracingService.noop);
|
|
674
|
-
/**
|
|
675
|
-
* Creates a TracingService layer that emits events to the parent tracing service.
|
|
676
|
-
*/
|
|
677
|
-
static layerSubframe = (mapContext) => Layer2.effect(_TracingService, Effect6.gen(function* () {
|
|
678
|
-
const tracing = yield* _TracingService;
|
|
679
|
-
const context = mapContext(tracing.getTraceContext());
|
|
34
|
+
var configuredCredentialsLayer = (credentials) => Layer.succeed(Credential.CredentialsService, new ConfiguredCredentialsService(credentials));
|
|
35
|
+
var credentialsLayerConfig = (credentials) => Layer.effect(Credential.CredentialsService, Effect.gen(function* () {
|
|
36
|
+
const serviceCredentials = yield* Effect.forEach(credentials, ({ service, apiKey }) => Effect.gen(function* () {
|
|
680
37
|
return {
|
|
681
|
-
|
|
682
|
-
|
|
683
|
-
traceInvocationStart: () => Effect6.die("Tracing invocation inside another invocation is not supported."),
|
|
684
|
-
traceInvocationEnd: () => Effect6.die("Tracing invocation inside another invocation is not supported.")
|
|
38
|
+
service,
|
|
39
|
+
apiKey: Redacted.value(yield* apiKey)
|
|
685
40
|
};
|
|
686
41
|
}));
|
|
687
|
-
|
|
688
|
-
* Create sublayer to trace an invocation.
|
|
689
|
-
* @param data
|
|
690
|
-
* @returns
|
|
691
|
-
*/
|
|
692
|
-
static layerInvocation = (data) => _TracingService.layerSubframe((context) => ({
|
|
693
|
-
...context,
|
|
694
|
-
currentInvocation: data
|
|
695
|
-
}));
|
|
696
|
-
/**
|
|
697
|
-
* Emit the current human-readable execution status.
|
|
698
|
-
*/
|
|
699
|
-
static emitStatus = Effect6.fnUntraced(function* (data) {
|
|
700
|
-
const tracing = yield* _TracingService;
|
|
701
|
-
tracing.write(Obj6.make(AgentStatus, {
|
|
702
|
-
parentMessage: tracing.getTraceContext().parentMessage,
|
|
703
|
-
toolCallId: tracing.getTraceContext().toolCallId,
|
|
704
|
-
created: (/* @__PURE__ */ new Date()).toISOString(),
|
|
705
|
-
...data
|
|
706
|
-
}), tracing.getTraceContext());
|
|
707
|
-
});
|
|
708
|
-
static emitConverationMessage = Effect6.fnUntraced(function* (data) {
|
|
709
|
-
const tracing = yield* _TracingService;
|
|
710
|
-
tracing.write(Obj6.make(Message.Message, {
|
|
711
|
-
parentMessage: tracing.getTraceContext().parentMessage,
|
|
712
|
-
...data,
|
|
713
|
-
properties: {
|
|
714
|
-
[MESSAGE_PROPERTY_TOOL_CALL_ID]: tracing.getTraceContext().toolCallId,
|
|
715
|
-
...data.properties
|
|
716
|
-
}
|
|
717
|
-
}), tracing.getTraceContext());
|
|
718
|
-
});
|
|
719
|
-
};
|
|
720
|
-
var MESSAGE_PROPERTY_TOOL_CALL_ID = "toolCallId";
|
|
721
|
-
|
|
722
|
-
// src/services/event-logger.ts
|
|
723
|
-
var __dxlog_file = "/__w/dxos/dxos/packages/core/functions/src/services/event-logger.ts";
|
|
724
|
-
var ComputeEventPayload = Schema9.Union(Schema9.Struct({
|
|
725
|
-
type: Schema9.Literal("begin-compute"),
|
|
726
|
-
nodeId: Schema9.String,
|
|
727
|
-
/**
|
|
728
|
-
* Names of the inputs begin computed.
|
|
729
|
-
*/
|
|
730
|
-
inputs: Schema9.Array(Schema9.String)
|
|
731
|
-
}), Schema9.Struct({
|
|
732
|
-
type: Schema9.Literal("end-compute"),
|
|
733
|
-
nodeId: Schema9.String,
|
|
734
|
-
/**
|
|
735
|
-
* Names of the outputs computed.
|
|
736
|
-
*/
|
|
737
|
-
outputs: Schema9.Array(Schema9.String)
|
|
738
|
-
}), Schema9.Struct({
|
|
739
|
-
type: Schema9.Literal("compute-input"),
|
|
740
|
-
nodeId: Schema9.String,
|
|
741
|
-
property: Schema9.String,
|
|
742
|
-
value: Schema9.Any
|
|
743
|
-
}), Schema9.Struct({
|
|
744
|
-
type: Schema9.Literal("compute-output"),
|
|
745
|
-
nodeId: Schema9.String,
|
|
746
|
-
property: Schema9.String,
|
|
747
|
-
value: Schema9.Any
|
|
748
|
-
}), Schema9.Struct({
|
|
749
|
-
type: Schema9.Literal("custom"),
|
|
750
|
-
nodeId: Schema9.String,
|
|
751
|
-
event: Schema9.Any
|
|
752
|
-
}));
|
|
753
|
-
var ComputeEvent = Schema9.Struct({
|
|
754
|
-
payload: ComputeEventPayload
|
|
755
|
-
}).pipe(Type4.object({
|
|
756
|
-
typename: "org.dxos.type.compute-event",
|
|
757
|
-
version: "0.1.0"
|
|
42
|
+
return new ConfiguredCredentialsService(serviceCredentials);
|
|
758
43
|
}));
|
|
759
|
-
var
|
|
760
|
-
|
|
761
|
-
|
|
762
|
-
|
|
763
|
-
|
|
44
|
+
var credentialsLayerFromDatabase = ({ caching = false } = {}) => Layer.effect(Credential.CredentialsService, Effect.gen(function* () {
|
|
45
|
+
const dbService = yield* Database.Service;
|
|
46
|
+
const cache = /* @__PURE__ */ new Map();
|
|
47
|
+
const queryCredentials = async (query) => {
|
|
48
|
+
const cacheKey = JSON.stringify(query);
|
|
49
|
+
if (caching && cache.has(cacheKey)) {
|
|
50
|
+
return cache.get(cacheKey);
|
|
51
|
+
}
|
|
52
|
+
const accessTokens = await dbService.db.query(Query.type(AccessToken.AccessToken)).run();
|
|
53
|
+
const credentials = accessTokens.filter((accessToken) => accessToken.source === query.service).map((accessToken) => ({
|
|
54
|
+
service: accessToken.source,
|
|
55
|
+
apiKey: accessToken.token
|
|
56
|
+
}));
|
|
57
|
+
if (caching) {
|
|
58
|
+
cache.set(cacheKey, credentials);
|
|
59
|
+
}
|
|
60
|
+
return credentials;
|
|
764
61
|
};
|
|
765
|
-
/**
|
|
766
|
-
* Implements ComputeEventLogger using TracingService.
|
|
767
|
-
*/
|
|
768
|
-
static layerFromTracing = Layer3.effect(_ComputeEventLogger, Effect7.gen(function* () {
|
|
769
|
-
const tracing = yield* TracingService;
|
|
770
|
-
return {
|
|
771
|
-
log: (event) => {
|
|
772
|
-
tracing.write(Obj7.make(ComputeEvent, {
|
|
773
|
-
payload: event
|
|
774
|
-
}), tracing.getTraceContext());
|
|
775
|
-
},
|
|
776
|
-
nodeId: void 0
|
|
777
|
-
};
|
|
778
|
-
}));
|
|
779
|
-
};
|
|
780
|
-
var logCustomEvent = (data) => Effect7.gen(function* () {
|
|
781
|
-
const logger = yield* ComputeEventLogger;
|
|
782
|
-
if (!logger.nodeId) {
|
|
783
|
-
throw new Error("logCustomEvent must be called within a node compute function");
|
|
784
|
-
}
|
|
785
|
-
logger.log({
|
|
786
|
-
type: "custom",
|
|
787
|
-
nodeId: logger.nodeId,
|
|
788
|
-
event: data
|
|
789
|
-
});
|
|
790
|
-
});
|
|
791
|
-
var createDefectLogger = () => Effect7.catchAll((error) => Effect7.gen(function* () {
|
|
792
|
-
log2.error("unhandled effect error", {
|
|
793
|
-
error
|
|
794
|
-
}, {
|
|
795
|
-
F: __dxlog_file,
|
|
796
|
-
L: 102,
|
|
797
|
-
S: this,
|
|
798
|
-
C: (f, a) => f(...a)
|
|
799
|
-
});
|
|
800
|
-
throw error;
|
|
801
|
-
}));
|
|
802
|
-
var createEventLogger = (level, message = "event") => {
|
|
803
|
-
const logFunction = {
|
|
804
|
-
[LogLevel.WARN]: log2.warn,
|
|
805
|
-
[LogLevel.VERBOSE]: log2.verbose,
|
|
806
|
-
[LogLevel.DEBUG]: log2.debug,
|
|
807
|
-
[LogLevel.INFO]: log2.info,
|
|
808
|
-
[LogLevel.ERROR]: log2.error
|
|
809
|
-
}[level];
|
|
810
|
-
invariant(logFunction, void 0, {
|
|
811
|
-
F: __dxlog_file,
|
|
812
|
-
L: 120,
|
|
813
|
-
S: void 0,
|
|
814
|
-
A: [
|
|
815
|
-
"logFunction",
|
|
816
|
-
""
|
|
817
|
-
]
|
|
818
|
-
});
|
|
819
62
|
return {
|
|
820
|
-
|
|
821
|
-
|
|
63
|
+
getCredential: async (query) => {
|
|
64
|
+
const credentials = await queryCredentials(query);
|
|
65
|
+
if (credentials.length === 0) {
|
|
66
|
+
throw new Error(`Credential not found for service: ${query.service}`);
|
|
67
|
+
}
|
|
68
|
+
return credentials[0];
|
|
822
69
|
},
|
|
823
|
-
|
|
70
|
+
queryCredentials: async (query) => {
|
|
71
|
+
return queryCredentials(query);
|
|
72
|
+
}
|
|
824
73
|
};
|
|
825
|
-
};
|
|
74
|
+
}));
|
|
826
75
|
|
|
827
76
|
// src/services/function-invocation-service.ts
|
|
828
|
-
import * as
|
|
829
|
-
import * as
|
|
830
|
-
import * as
|
|
831
|
-
var FunctionInvocationService = class _FunctionInvocationService extends
|
|
832
|
-
static layerNotAvailable =
|
|
833
|
-
invokeFunction: () =>
|
|
834
|
-
resolveFunction: () =>
|
|
77
|
+
import * as Context from "effect/Context";
|
|
78
|
+
import * as Effect2 from "effect/Effect";
|
|
79
|
+
import * as Layer2 from "effect/Layer";
|
|
80
|
+
var FunctionInvocationService = class _FunctionInvocationService extends Context.Tag("@dxos/functions/FunctionInvocationService")() {
|
|
81
|
+
static layerNotAvailable = Layer2.succeed(_FunctionInvocationService, {
|
|
82
|
+
invokeFunction: () => Effect2.die("FunctionInvocationService is not avaialble."),
|
|
83
|
+
resolveFunction: () => Effect2.die("FunctionInvocationService is not available.")
|
|
835
84
|
});
|
|
836
|
-
static invokeFunction = (functionDef, input) =>
|
|
837
|
-
static resolveFunction = (key) =>
|
|
85
|
+
static invokeFunction = (functionDef, input) => Effect2.serviceFunctionEffect(_FunctionInvocationService, (service) => service.invokeFunction)(functionDef, input);
|
|
86
|
+
static resolveFunction = (key) => Effect2.serviceFunctionEffect(_FunctionInvocationService, (service) => service.resolveFunction)(key);
|
|
838
87
|
};
|
|
839
88
|
|
|
840
89
|
// src/services/queues.ts
|
|
841
|
-
import
|
|
842
|
-
|
|
843
|
-
|
|
844
|
-
var
|
|
845
|
-
|
|
846
|
-
|
|
847
|
-
|
|
848
|
-
|
|
849
|
-
|
|
850
|
-
|
|
851
|
-
throw new Error("Queues not available");
|
|
852
|
-
}
|
|
853
|
-
},
|
|
854
|
-
queue: void 0
|
|
855
|
-
});
|
|
856
|
-
static make = (queues, queue) => {
|
|
857
|
-
return {
|
|
858
|
-
queues,
|
|
859
|
-
queue
|
|
860
|
-
};
|
|
861
|
-
};
|
|
862
|
-
static layer = (queues, queue) => Layer5.succeed(_QueueService, _QueueService.make(queues, queue));
|
|
863
|
-
/**
|
|
864
|
-
* Gets a queue by its DXN.
|
|
865
|
-
*/
|
|
866
|
-
static getQueue = (dxn) => _QueueService.pipe(Effect9.map(({ queues }) => queues.get(dxn)));
|
|
867
|
-
/**
|
|
868
|
-
* Creates a new queue.
|
|
869
|
-
*/
|
|
870
|
-
static createQueue = (options) => _QueueService.pipe(Effect9.map(({ queues }) => queues.create(options)));
|
|
871
|
-
static append = (queue, objects) => Effect9.promise(() => queue.append(objects));
|
|
90
|
+
import { QueueService, feedServiceFromQueueServiceLayer } from "@dxos/echo-db";
|
|
91
|
+
|
|
92
|
+
// src/services/tracing.ts
|
|
93
|
+
var MESSAGE_PROPERTY_TOOL_CALL_ID = "toolCallId";
|
|
94
|
+
|
|
95
|
+
// src/types/url.ts
|
|
96
|
+
var FUNCTIONS_META_KEY = "org.dxos.service.function";
|
|
97
|
+
var FUNCTIONS_PRESET_META_KEY = "org.dxos.service.function-preset";
|
|
98
|
+
var getUserFunctionIdInMetadata = (meta) => {
|
|
99
|
+
return meta.keys.find((key) => key.source === FUNCTIONS_META_KEY)?.id;
|
|
872
100
|
};
|
|
873
|
-
var
|
|
874
|
-
|
|
875
|
-
|
|
876
|
-
|
|
101
|
+
var setUserFunctionIdInMetadata = (meta, functionId) => {
|
|
102
|
+
const key = meta.keys.find((key2) => key2.source === FUNCTIONS_META_KEY);
|
|
103
|
+
if (key) {
|
|
104
|
+
if (key.id !== functionId) {
|
|
105
|
+
throw new Error("Metadata mismatch");
|
|
106
|
+
}
|
|
107
|
+
} else {
|
|
108
|
+
meta.keys.push({
|
|
109
|
+
source: FUNCTIONS_META_KEY,
|
|
110
|
+
id: functionId
|
|
111
|
+
});
|
|
112
|
+
}
|
|
877
113
|
};
|
|
878
114
|
|
|
879
115
|
// src/protocol/protocol.ts
|
|
880
116
|
import * as AnthropicClient from "@effect/ai-anthropic/AnthropicClient";
|
|
881
|
-
import * as
|
|
882
|
-
import * as
|
|
883
|
-
import * as
|
|
884
|
-
import * as
|
|
885
|
-
import
|
|
117
|
+
import * as Effect4 from "effect/Effect";
|
|
118
|
+
import * as Layer4 from "effect/Layer";
|
|
119
|
+
import * as Option from "effect/Option";
|
|
120
|
+
import * as Schema from "effect/Schema";
|
|
121
|
+
import * as SchemaAST from "effect/SchemaAST";
|
|
122
|
+
import { AiModelResolver, AiService, OpaqueToolkit } from "@dxos/ai";
|
|
886
123
|
import { AnthropicResolver } from "@dxos/ai/resolvers";
|
|
124
|
+
import { Blueprint, FunctionError, InvalidOperationInputError, InvalidOperationOutputError, Operation, OperationRegistry, Trace } from "@dxos/compute";
|
|
887
125
|
import { LifecycleState, Resource } from "@dxos/context";
|
|
888
|
-
import { Database as Database2, Feed, JsonSchema
|
|
126
|
+
import { Database as Database2, Feed, JsonSchema, Ref } from "@dxos/echo";
|
|
127
|
+
import { createFeedServiceLayer, EchoClient } from "@dxos/echo-db";
|
|
889
128
|
import { refFromEncodedReference } from "@dxos/echo/internal";
|
|
890
|
-
import { EchoClient, createFeedServiceLayer } from "@dxos/echo-db";
|
|
891
129
|
import { runAndForwardErrors } from "@dxos/effect";
|
|
892
|
-
import { assertState, failedInvariant
|
|
130
|
+
import { assertState, failedInvariant, invariant } from "@dxos/invariant";
|
|
893
131
|
import { PublicKey } from "@dxos/keys";
|
|
132
|
+
import { log as log2 } from "@dxos/log";
|
|
133
|
+
import { ErrorCodec as ErrorCodec2 } from "@dxos/protocols";
|
|
894
134
|
|
|
895
135
|
// src/protocol/functions-ai-http-client.ts
|
|
896
136
|
import * as Headers from "@effect/platform/Headers";
|
|
897
137
|
import * as HttpClient2 from "@effect/platform/HttpClient";
|
|
898
138
|
import * as HttpClientError from "@effect/platform/HttpClientError";
|
|
899
139
|
import * as HttpClientResponse from "@effect/platform/HttpClientResponse";
|
|
900
|
-
import * as
|
|
140
|
+
import * as Effect3 from "effect/Effect";
|
|
901
141
|
import * as FiberRef from "effect/FiberRef";
|
|
902
|
-
import * as
|
|
142
|
+
import * as Layer3 from "effect/Layer";
|
|
903
143
|
import * as Stream from "effect/Stream";
|
|
904
|
-
import {
|
|
144
|
+
import { FunctionsAiMemoizationMissError, FunctionsAiUpstreamError } from "@dxos/compute";
|
|
145
|
+
import { log } from "@dxos/log";
|
|
905
146
|
import { ErrorCodec } from "@dxos/protocols";
|
|
906
|
-
var
|
|
147
|
+
var __dxlog_file = "/__w/dxos/dxos/packages/core/compute/functions/src/protocol/functions-ai-http-client.ts";
|
|
907
148
|
var requestInitTagKey = "@effect/platform/FetchHttpClient/FetchOptions";
|
|
908
149
|
var FunctionsAiHttpClient = class _FunctionsAiHttpClient {
|
|
909
150
|
static make = (service) => HttpClient2.make((request, url, signal, fiber) => {
|
|
910
151
|
const context = fiber.getFiberRef(FiberRef.currentContext);
|
|
911
152
|
const options = context.unsafeMap.get(requestInitTagKey) ?? {};
|
|
912
153
|
const headers = options.headers ? Headers.merge(Headers.fromInput(options.headers), request.headers) : request.headers;
|
|
913
|
-
const send = (body) =>
|
|
154
|
+
const send = (body) => Effect3.tryPromise({
|
|
914
155
|
try: () => service.fetch(new Request(url, {
|
|
915
156
|
...options,
|
|
916
157
|
method: request.method,
|
|
@@ -918,21 +159,21 @@ var FunctionsAiHttpClient = class _FunctionsAiHttpClient {
|
|
|
918
159
|
body
|
|
919
160
|
})),
|
|
920
161
|
catch: (cause) => {
|
|
921
|
-
|
|
162
|
+
log.error("Failed to fetch", {
|
|
922
163
|
errorSerialized: ErrorCodec.encode(cause)
|
|
923
|
-
}, {
|
|
924
|
-
F: __dxlog_file2,
|
|
925
|
-
L: 43,
|
|
926
|
-
S: this,
|
|
927
|
-
C: (f, a) => f(...a)
|
|
928
|
-
});
|
|
164
|
+
}, { "~LogMeta": "~LogMeta", F: __dxlog_file, L: 31, S: this });
|
|
929
165
|
return new HttpClientError.RequestError({
|
|
930
166
|
request,
|
|
931
167
|
reason: "Transport",
|
|
932
168
|
cause
|
|
933
169
|
});
|
|
934
170
|
}
|
|
935
|
-
}).pipe(
|
|
171
|
+
}).pipe(Effect3.flatMap((response) => (
|
|
172
|
+
// Inspect the body before handing the response to `@effect/ai` so that structured
|
|
173
|
+
// upstream errors surface as typed defects (`FunctionsAiUpstreamError` and friends)
|
|
174
|
+
// rather than as the generic `HttpResponseError` from `@effect/ai/AiError`.
|
|
175
|
+
Effect3.flatMap(Effect3.promise(() => parseUpstreamError(response)), (typedError) => typedError ? Effect3.die(typedError) : Effect3.succeed(HttpClientResponse.fromWeb(request, response)))
|
|
176
|
+
)));
|
|
936
177
|
switch (request.body._tag) {
|
|
937
178
|
case "Raw":
|
|
938
179
|
case "Uint8Array":
|
|
@@ -940,14 +181,54 @@ var FunctionsAiHttpClient = class _FunctionsAiHttpClient {
|
|
|
940
181
|
case "FormData":
|
|
941
182
|
return send(request.body.formData);
|
|
942
183
|
case "Stream":
|
|
943
|
-
return Stream.toReadableStreamEffect(request.body.stream).pipe(
|
|
184
|
+
return Stream.toReadableStreamEffect(request.body.stream).pipe(Effect3.flatMap(send));
|
|
944
185
|
}
|
|
945
186
|
return send(void 0);
|
|
946
187
|
});
|
|
947
|
-
static layer = (service) =>
|
|
188
|
+
static layer = (service) => Layer3.succeed(HttpClient2.HttpClient, _FunctionsAiHttpClient.make(service));
|
|
189
|
+
};
|
|
190
|
+
var parseUpstreamError = async (response) => {
|
|
191
|
+
if (response.ok) {
|
|
192
|
+
return void 0;
|
|
193
|
+
}
|
|
194
|
+
const contentType = response.headers.get("content-type") ?? "";
|
|
195
|
+
if (!contentType.toLowerCase().includes("application/json")) {
|
|
196
|
+
return void 0;
|
|
197
|
+
}
|
|
198
|
+
let body;
|
|
199
|
+
try {
|
|
200
|
+
body = await response.clone().json();
|
|
201
|
+
} catch {
|
|
202
|
+
return void 0;
|
|
203
|
+
}
|
|
204
|
+
if (!body || body.type !== "error" || typeof body.error !== "object" || body.error === null) {
|
|
205
|
+
return void 0;
|
|
206
|
+
}
|
|
207
|
+
const inner = body.error;
|
|
208
|
+
const message = inner.message ?? `Upstream AI service responded with HTTP ${response.status}`;
|
|
209
|
+
if (inner.type === "memoization_miss" && typeof inner.cacheKey === "string") {
|
|
210
|
+
return new FunctionsAiMemoizationMissError({
|
|
211
|
+
message,
|
|
212
|
+
context: {
|
|
213
|
+
cacheKey: inner.cacheKey,
|
|
214
|
+
status: response.status
|
|
215
|
+
}
|
|
216
|
+
});
|
|
217
|
+
}
|
|
218
|
+
return new FunctionsAiUpstreamError({
|
|
219
|
+
message,
|
|
220
|
+
context: {
|
|
221
|
+
type: inner.type,
|
|
222
|
+
status: response.status,
|
|
223
|
+
...inner.cacheKey ? {
|
|
224
|
+
cacheKey: inner.cacheKey
|
|
225
|
+
} : {}
|
|
226
|
+
}
|
|
227
|
+
});
|
|
948
228
|
};
|
|
949
229
|
|
|
950
230
|
// src/protocol/protocol.ts
|
|
231
|
+
var __dxlog_file2 = "/__w/dxos/dxos/packages/core/compute/functions/src/protocol/protocol.ts";
|
|
951
232
|
function _ts_add_disposable_resource(env, value2, async) {
|
|
952
233
|
if (value2 !== null && value2 !== void 0) {
|
|
953
234
|
if (typeof value2 !== "object" && typeof value2 !== "function") throw new TypeError("Object expected.");
|
|
@@ -1013,22 +294,22 @@ function _ts_dispose_resources(env) {
|
|
|
1013
294
|
return next();
|
|
1014
295
|
})(env);
|
|
1015
296
|
}
|
|
1016
|
-
var
|
|
1017
|
-
|
|
1018
|
-
|
|
1019
|
-
throw new TypeError("Invalid function definition");
|
|
297
|
+
var wrapFunctionHandler = (func, opts = {}) => {
|
|
298
|
+
if (!Operation.isOperationWithHandler(func)) {
|
|
299
|
+
throw new TypeError("Expected operation with handler");
|
|
1020
300
|
}
|
|
301
|
+
const serviceTags = func.services.map((service) => service.key);
|
|
1021
302
|
return {
|
|
1022
303
|
meta: {
|
|
1023
|
-
key: func.key,
|
|
1024
|
-
name: func.name,
|
|
1025
|
-
description: func.description,
|
|
1026
|
-
inputSchema:
|
|
1027
|
-
outputSchema: func.
|
|
1028
|
-
services: func.services
|
|
304
|
+
key: func.meta.key,
|
|
305
|
+
name: func.meta.name,
|
|
306
|
+
description: func.meta.description,
|
|
307
|
+
inputSchema: JsonSchema.toJsonSchema(func.input),
|
|
308
|
+
outputSchema: func.output === void 0 ? void 0 : JsonSchema.toJsonSchema(func.output),
|
|
309
|
+
services: func.services.map((service) => service.key)
|
|
1029
310
|
},
|
|
1030
311
|
handler: async ({ data, context }) => {
|
|
1031
|
-
if ((
|
|
312
|
+
if ((serviceTags.includes(Database2.Service.key) || serviceTags.includes(QueueService.key) || serviceTags.includes(Feed.FeedService.key)) && (!context.services.dataService || !context.services.queryService)) {
|
|
1032
313
|
throw new FunctionError({
|
|
1033
314
|
message: "Services not provided: dataService, queryService"
|
|
1034
315
|
});
|
|
@@ -1040,40 +321,49 @@ var wrapFunctionHandler = (func) => {
|
|
|
1040
321
|
hasError: false
|
|
1041
322
|
};
|
|
1042
323
|
try {
|
|
1043
|
-
if (!
|
|
324
|
+
if (!SchemaAST.isAnyKeyword(func.input.ast)) {
|
|
1044
325
|
try {
|
|
1045
|
-
|
|
326
|
+
Schema.validateSync(func.input, {
|
|
327
|
+
onExcessProperty: "error"
|
|
328
|
+
})(data);
|
|
1046
329
|
} catch (error) {
|
|
1047
|
-
throw new
|
|
1048
|
-
message:
|
|
330
|
+
throw new InvalidOperationInputError({
|
|
331
|
+
message: `Operation input did not match schema (${func.meta.key}): ${error.message}`,
|
|
1049
332
|
cause: error
|
|
1050
333
|
});
|
|
1051
334
|
}
|
|
1052
335
|
}
|
|
1053
|
-
const funcContext = _ts_add_disposable_resource(env, await new FunctionContext(context).open(), true);
|
|
1054
|
-
|
|
1055
|
-
|
|
1056
|
-
|
|
1057
|
-
|
|
1058
|
-
|
|
1059
|
-
|
|
1060
|
-
|
|
1061
|
-
"'Database is required for functions with types'"
|
|
1062
|
-
]
|
|
1063
|
-
});
|
|
1064
|
-
await funcContext.db.graph.schemaRegistry.register(func.types);
|
|
336
|
+
const funcContext = _ts_add_disposable_resource(env, await new FunctionContext(context, opts).open(), true);
|
|
337
|
+
const types = [
|
|
338
|
+
...opts.types ?? [],
|
|
339
|
+
...func.types ?? []
|
|
340
|
+
];
|
|
341
|
+
if (types.length > 0) {
|
|
342
|
+
invariant(funcContext.db, "Database is required for functions with types", { "~LogMeta": "~LogMeta", F: __dxlog_file2, L: 137, S: void 0, A: ["funcContext.db", "'Database is required for functions with types'"] });
|
|
343
|
+
await funcContext.db.graph.schemaRegistry.register(types);
|
|
1065
344
|
}
|
|
1066
|
-
const dataWithDecodedRefs = funcContext.db && !
|
|
1067
|
-
let result = await func.handler(
|
|
1068
|
-
|
|
1069
|
-
|
|
1070
|
-
|
|
1071
|
-
|
|
1072
|
-
|
|
1073
|
-
|
|
345
|
+
const dataWithDecodedRefs = funcContext.db && !SchemaAST.isAnyKeyword(func.input.ast) ? decodeRefsFromSchema(func.input.ast, data, funcContext.db) : data;
|
|
346
|
+
let result = await func.handler(dataWithDecodedRefs);
|
|
347
|
+
if (Effect4.isEffect(result)) {
|
|
348
|
+
result = await runAndForwardErrors(result.pipe(Effect4.orDie, Effect4.provide(funcContext.createLayer())));
|
|
349
|
+
}
|
|
350
|
+
if (serviceTags.includes(Database2.Service.key) && funcContext.db) {
|
|
351
|
+
await funcContext.db.flush({
|
|
352
|
+
disk: true,
|
|
353
|
+
indexes: false
|
|
354
|
+
});
|
|
1074
355
|
}
|
|
1075
|
-
if (func.
|
|
1076
|
-
|
|
356
|
+
if (func.output && !SchemaAST.isAnyKeyword(func.output.ast)) {
|
|
357
|
+
try {
|
|
358
|
+
Schema.validateSync(func.output, {
|
|
359
|
+
onExcessProperty: "error"
|
|
360
|
+
})(result);
|
|
361
|
+
} catch (error) {
|
|
362
|
+
throw new InvalidOperationOutputError({
|
|
363
|
+
message: `Operation output did not match schema (${func.meta.key}): ${error.message}`,
|
|
364
|
+
cause: error
|
|
365
|
+
});
|
|
366
|
+
}
|
|
1077
367
|
}
|
|
1078
368
|
return result;
|
|
1079
369
|
} catch (e) {
|
|
@@ -1094,9 +384,11 @@ var FunctionContext = class extends Resource {
|
|
|
1094
384
|
client;
|
|
1095
385
|
db;
|
|
1096
386
|
queues;
|
|
1097
|
-
|
|
387
|
+
opts;
|
|
388
|
+
constructor(context, opts) {
|
|
1098
389
|
super();
|
|
1099
390
|
this.context = context;
|
|
391
|
+
this.opts = opts;
|
|
1100
392
|
if (context.services.dataService && context.services.queryService) {
|
|
1101
393
|
this.client = new EchoClient().connectToService({
|
|
1102
394
|
dataService: context.services.dataService,
|
|
@@ -1108,12 +400,12 @@ var FunctionContext = class extends Resource {
|
|
|
1108
400
|
async _open() {
|
|
1109
401
|
await this.client?.open();
|
|
1110
402
|
this.db = this.client && this.context.spaceId ? this.client.constructDatabase({
|
|
1111
|
-
spaceId: this.context.spaceId ??
|
|
1112
|
-
spaceKey: PublicKey.fromHex(this.context.spaceKey ??
|
|
403
|
+
spaceId: this.context.spaceId ?? failedInvariant(),
|
|
404
|
+
spaceKey: PublicKey.fromHex(this.context.spaceKey ?? failedInvariant("spaceKey missing in context")),
|
|
1113
405
|
reactiveSchemaQuery: false,
|
|
1114
406
|
preloadSchemaOnOpen: false
|
|
1115
407
|
}) : void 0;
|
|
1116
|
-
await this.db?.setSpaceRoot(this.context.spaceRootUrl ??
|
|
408
|
+
await this.db?.setSpaceRoot(this.context.spaceRootUrl ?? failedInvariant("spaceRootUrl missing in context"));
|
|
1117
409
|
await this.db?.open();
|
|
1118
410
|
this.queues = this.client && this.context.spaceId ? this.client.constructQueueFactory(this.context.spaceId) : void 0;
|
|
1119
411
|
}
|
|
@@ -1126,29 +418,115 @@ var FunctionContext = class extends Resource {
|
|
|
1126
418
|
const dbLayer = this.db ? Database2.layer(this.db) : Database2.notAvailable;
|
|
1127
419
|
const queuesLayer = this.queues ? QueueService.layer(this.queues) : QueueService.notAvailable;
|
|
1128
420
|
const feedLayer = this.queues ? createFeedServiceLayer(this.queues) : Feed.notAvailable;
|
|
1129
|
-
const credentials = dbLayer ?
|
|
421
|
+
const credentials = dbLayer ? credentialsLayerFromDatabase({
|
|
1130
422
|
caching: true
|
|
1131
|
-
}).pipe(
|
|
1132
|
-
const
|
|
1133
|
-
const
|
|
1134
|
-
const
|
|
1135
|
-
|
|
1136
|
-
|
|
1137
|
-
|
|
1138
|
-
|
|
423
|
+
}).pipe(Layer4.provide(dbLayer)) : configuredCredentialsLayer([]);
|
|
424
|
+
const aiLayer = this.context.services.functionsAiService ? InternalAiServiceLayer(this.context.services.functionsAiService) : AiService.notAvailable;
|
|
425
|
+
const operationServiceLayer = this.context.services.functionsService ? makeOperationServiceLayer(this.context.services.functionsService) : unavailableOperationServiceLayer;
|
|
426
|
+
const operationRegistryLayer = this.context.services.functionsService ? makeOperationRegistryLayer(this.context.services.functionsService, this.context.spaceId) : emptyOperationRegistryLayer;
|
|
427
|
+
const traceWriterLayer = this.context.services.traceService ? makeTraceWriterLayer(this.context.services.traceService) : Trace.writerLayerNoop;
|
|
428
|
+
log2("Creating function context layer", {
|
|
429
|
+
traceService: !!this.context.services.traceService,
|
|
430
|
+
functionsService: !!this.context.services.functionsService,
|
|
431
|
+
functionsAiService: !!this.context.services.functionsAiService,
|
|
432
|
+
spaceId: this.context.spaceId,
|
|
433
|
+
spaceRootUrl: this.context.spaceRootUrl,
|
|
434
|
+
toolkits: this.opts.toolkits?.length ?? 0,
|
|
435
|
+
types: this.opts.types?.length ?? 0
|
|
436
|
+
}, { "~LogMeta": "~LogMeta", F: __dxlog_file2, L: 234, S: this });
|
|
437
|
+
const blueprintRegistryLayer = this.opts.blueprintRegistry ? Layer4.succeed(Blueprint.RegistryService, this.opts.blueprintRegistry) : Blueprint.RegistryService.notAvailable;
|
|
438
|
+
return Layer4.mergeAll(
|
|
439
|
+
dbLayer,
|
|
440
|
+
queuesLayer,
|
|
441
|
+
feedLayer,
|
|
442
|
+
credentials,
|
|
443
|
+
operationServiceLayer,
|
|
444
|
+
operationRegistryLayer,
|
|
445
|
+
aiLayer,
|
|
446
|
+
OpaqueToolkit.providerLayer(OpaqueToolkit.merge(...this.opts.toolkits ?? [])),
|
|
447
|
+
traceWriterLayer,
|
|
448
|
+
blueprintRegistryLayer,
|
|
449
|
+
// `FunctionInvocationService` is deprecated; new code should yield `Operation.Service`.
|
|
450
|
+
// The cloudflare wrapper provides only the unavailable layer to satisfy the (still-present)
|
|
451
|
+
// type union — handlers that yield it will die at invocation time.
|
|
452
|
+
FunctionInvocationService.layerNotAvailable
|
|
453
|
+
);
|
|
1139
454
|
}
|
|
1140
455
|
};
|
|
1141
|
-
var
|
|
1142
|
-
|
|
1143
|
-
|
|
456
|
+
var makeTraceWriterLayer = (traceService) => Layer4.succeed(Trace.TraceService, {
|
|
457
|
+
write: (eventType, payload) => {
|
|
458
|
+
log2("Writing trace event", {
|
|
459
|
+
eventType: eventType.key
|
|
460
|
+
}, { "~LogMeta": "~LogMeta", F: __dxlog_file2, L: 255, S: void 0 });
|
|
461
|
+
traceService.write([
|
|
462
|
+
{
|
|
463
|
+
key: eventType.key,
|
|
464
|
+
isEphemeral: eventType.isEphemeral,
|
|
465
|
+
data: payload
|
|
466
|
+
}
|
|
467
|
+
]);
|
|
468
|
+
}
|
|
469
|
+
});
|
|
470
|
+
var InternalAiServiceLayer = (functionsAiService) => AiModelResolver.AiModelResolver.buildAiService.pipe(Layer4.provide(AnthropicResolver.make().pipe(Layer4.provide(AnthropicClient.layer({
|
|
471
|
+
// Note: It doesn't matter what is base url here, it will be proxied to ai gateway in edge.
|
|
472
|
+
apiUrl: "http://internal/provider/anthropic"
|
|
473
|
+
}).pipe(Layer4.provide(FunctionsAiHttpClient.layer(functionsAiService)))))));
|
|
474
|
+
var makeOperationServiceLayer = (functionsService) => {
|
|
475
|
+
const invokeRemote = async (op, input, options) => {
|
|
476
|
+
invariant(op.meta.deployedId, `Operation '${op.meta.key}' has no deployedId; cannot invoke remotely.`, { "~LogMeta": "~LogMeta", F: __dxlog_file2, L: 279, S: void 0, A: ["op.meta.deployedId", "`Operation '${op.meta.key}' has no deployedId; cannot invoke remotely.`"] });
|
|
477
|
+
const result = await functionsService.invoke(op.meta.deployedId, input, {
|
|
478
|
+
spaceId: options?.spaceId,
|
|
479
|
+
// Forward the conversation DXN so the remote runtime can rebuild conversation-scoped
|
|
480
|
+
// services (e.g. `AiContext.Service`) needed by operations like `GetContext`.
|
|
481
|
+
conversation: options?.conversation
|
|
482
|
+
});
|
|
483
|
+
if (result._kind === "success") {
|
|
484
|
+
return {
|
|
485
|
+
data: result.data
|
|
486
|
+
};
|
|
487
|
+
}
|
|
488
|
+
return {
|
|
489
|
+
error: ErrorCodec2.decode(result.error)
|
|
490
|
+
};
|
|
491
|
+
};
|
|
492
|
+
return Layer4.succeed(Operation.Service, {
|
|
493
|
+
invoke: (op, input, options) => Effect4.tryPromise(() => invokeRemote(op, input, options)).pipe(Effect4.orDie, Effect4.flatMap((outcome) => outcome.error ? Effect4.die(outcome.error) : Effect4.succeed(outcome.data))),
|
|
494
|
+
schedule: (op, input) => Effect4.sync(() => {
|
|
495
|
+
invariant(op.meta.deployedId, `Operation '${op.meta.key}' has no deployedId; cannot schedule remotely.`, { "~LogMeta": "~LogMeta", F: __dxlog_file2, L: 298, S: void 0, A: ["op.meta.deployedId", "`Operation '${op.meta.key}' has no deployedId; cannot schedule remotely.`"] });
|
|
496
|
+
void functionsService.invoke(op.meta.deployedId, input).catch(() => {
|
|
497
|
+
});
|
|
498
|
+
}),
|
|
499
|
+
invokePromise: (op, input, options) => invokeRemote(op, input, options).catch((error) => ({
|
|
500
|
+
error: error instanceof Error ? error : new Error(String(error))
|
|
501
|
+
}))
|
|
502
|
+
});
|
|
503
|
+
};
|
|
504
|
+
var unavailableOperationServiceLayer = Layer4.succeed(Operation.Service, {
|
|
505
|
+
invoke: () => Effect4.die("Operation.Service is not available: missing functionsService in EDGE context."),
|
|
506
|
+
schedule: () => Effect4.die("Operation.Service is not available: missing functionsService in EDGE context."),
|
|
507
|
+
invokePromise: async () => ({
|
|
508
|
+
error: new Error("Operation.Service is not available: missing functionsService in EDGE context.")
|
|
509
|
+
})
|
|
510
|
+
});
|
|
511
|
+
var makeOperationRegistryLayer = (functionsService, spaceId) => Layer4.succeed(OperationRegistry.Service, {
|
|
512
|
+
resolve: (key) => Effect4.gen(function* () {
|
|
513
|
+
const records = yield* Effect4.tryPromise(() => functionsService.query({
|
|
514
|
+
spaceId
|
|
515
|
+
})).pipe(Effect4.orDie);
|
|
516
|
+
const match = records.find((record) => Operation.getKey(record) === key);
|
|
517
|
+
return match ? Option.some(Operation.deserialize(match)) : Option.none();
|
|
518
|
+
})
|
|
519
|
+
});
|
|
520
|
+
var emptyOperationRegistryLayer = Layer4.succeed(OperationRegistry.Service, {
|
|
521
|
+
resolve: () => Effect4.succeed(Option.none())
|
|
1144
522
|
});
|
|
1145
523
|
var decodeRefsFromSchema = (ast, value2, db) => {
|
|
1146
524
|
if (value2 == null) {
|
|
1147
525
|
return value2;
|
|
1148
526
|
}
|
|
1149
|
-
const encoded =
|
|
1150
|
-
if (
|
|
1151
|
-
if (
|
|
527
|
+
const encoded = SchemaAST.encodedBoundAST(ast);
|
|
528
|
+
if (Ref.isRefType(encoded)) {
|
|
529
|
+
if (Ref.isRef(value2)) {
|
|
1152
530
|
return value2;
|
|
1153
531
|
}
|
|
1154
532
|
if (typeof value2 === "object" && value2 !== null && typeof value2["/"] === "string") {
|
|
@@ -1169,7 +547,7 @@ var decodeRefsFromSchema = (ast, value2, db) => {
|
|
|
1169
547
|
const result = {
|
|
1170
548
|
...value2
|
|
1171
549
|
};
|
|
1172
|
-
for (const prop of
|
|
550
|
+
for (const prop of SchemaAST.getPropertySignatures(encoded)) {
|
|
1173
551
|
const key = prop.name.toString();
|
|
1174
552
|
if (key in result) {
|
|
1175
553
|
result[key] = decodeRefsFromSchema(prop.type, result[key], db);
|
|
@@ -1188,7 +566,7 @@ var decodeRefsFromSchema = (ast, value2, db) => {
|
|
|
1188
566
|
return value2;
|
|
1189
567
|
}
|
|
1190
568
|
case "Union": {
|
|
1191
|
-
const nonUndefined = encoded.types.filter((t) => !
|
|
569
|
+
const nonUndefined = encoded.types.filter((t) => !SchemaAST.isUndefinedKeyword(t));
|
|
1192
570
|
if (nonUndefined.length === 1) {
|
|
1193
571
|
return decodeRefsFromSchema(nonUndefined[0], value2, db);
|
|
1194
572
|
}
|
|
@@ -1206,37 +584,18 @@ var decodeRefsFromSchema = (ast, value2, db) => {
|
|
|
1206
584
|
}
|
|
1207
585
|
};
|
|
1208
586
|
export {
|
|
1209
|
-
ComputeEvent,
|
|
1210
|
-
ComputeEventLogger,
|
|
1211
|
-
ComputeEventPayload,
|
|
1212
587
|
ConfiguredCredentialsService,
|
|
1213
|
-
ContextQueueService,
|
|
1214
|
-
CredentialsService,
|
|
1215
|
-
ExampleFunctions,
|
|
1216
588
|
FUNCTIONS_META_KEY,
|
|
1217
589
|
FUNCTIONS_PRESET_META_KEY,
|
|
1218
|
-
Function_exports as Function,
|
|
1219
|
-
FunctionDefinition,
|
|
1220
|
-
FunctionError,
|
|
1221
590
|
FunctionInvocationService,
|
|
1222
|
-
FunctionNotFoundError,
|
|
1223
591
|
MESSAGE_PROPERTY_TOOL_CALL_ID,
|
|
1224
592
|
QueueService,
|
|
1225
|
-
|
|
1226
|
-
|
|
1227
|
-
|
|
1228
|
-
|
|
1229
|
-
TriggerEvent_exports as TriggerEvent,
|
|
1230
|
-
TriggerStateNotFoundError,
|
|
1231
|
-
createDefectLogger,
|
|
1232
|
-
createEventLogger,
|
|
1233
|
-
defineFunction,
|
|
1234
|
-
deserializeFunction,
|
|
593
|
+
configuredCredentialsLayer,
|
|
594
|
+
credentialsLayerConfig,
|
|
595
|
+
credentialsLayerFromDatabase,
|
|
596
|
+
feedServiceFromQueueServiceLayer,
|
|
1235
597
|
getUserFunctionIdInMetadata,
|
|
1236
|
-
logCustomEvent,
|
|
1237
|
-
serializeFunction,
|
|
1238
598
|
setUserFunctionIdInMetadata,
|
|
1239
|
-
toOperation,
|
|
1240
599
|
withAuthorization,
|
|
1241
600
|
wrapFunctionHandler
|
|
1242
601
|
};
|