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