@dxos/functions 0.8.4-main.40e3dcdf1b → 0.8.4-main.43cb759274
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 +290 -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 +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 +8 -6
- package/dist/types/src/services/function-invocation-service.d.ts.map +1 -1
- package/dist/types/src/services/index.d.ts +1 -5
- package/dist/types/src/services/index.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 +20 -19
- 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 +10 -10
- package/src/protocol/protocol.ts +246 -59
- package/src/sdk.ts +11 -279
- package/src/services/credentials.ts +76 -120
- package/src/services/function-invocation-service.ts +9 -10
- package/src/services/index.ts +1 -5
- 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/services/queues.d.ts +0 -47
- package/dist/types/src/services/queues.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/services/queues.ts +0 -82
- package/src/types/Function.ts +0 -83
- package/src/types/Script.ts +0 -34
- package/src/types/Trigger.ts +0 -154
- 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: "org.dxos.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: "org.dxos.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: "org.dxos.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 = "org.dxos.service.function";
|
|
328
|
-
var FUNCTIONS_PRESET_META_KEY = "org.dxos.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,124 @@ 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: "org.dxos.type.compute-event",
|
|
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
|
-
// src/services/
|
|
838
|
-
|
|
839
|
-
|
|
840
|
-
|
|
841
|
-
var
|
|
842
|
-
|
|
843
|
-
|
|
844
|
-
|
|
845
|
-
throw new Error("Queues not available");
|
|
846
|
-
},
|
|
847
|
-
create() {
|
|
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));
|
|
89
|
+
// src/services/tracing.ts
|
|
90
|
+
var MESSAGE_PROPERTY_TOOL_CALL_ID = "toolCallId";
|
|
91
|
+
|
|
92
|
+
// src/types/url.ts
|
|
93
|
+
var FUNCTIONS_META_KEY = "org.dxos.service.function";
|
|
94
|
+
var FUNCTIONS_PRESET_META_KEY = "org.dxos.service.function-preset";
|
|
95
|
+
var getUserFunctionIdInMetadata = (meta) => {
|
|
96
|
+
return meta.keys.find((key) => key.source === FUNCTIONS_META_KEY)?.id;
|
|
869
97
|
};
|
|
870
|
-
var
|
|
871
|
-
|
|
872
|
-
|
|
873
|
-
|
|
98
|
+
var setUserFunctionIdInMetadata = (meta, functionId) => {
|
|
99
|
+
const key = meta.keys.find((key2) => key2.source === FUNCTIONS_META_KEY);
|
|
100
|
+
if (key) {
|
|
101
|
+
if (key.id !== functionId) {
|
|
102
|
+
throw new Error("Metadata mismatch");
|
|
103
|
+
}
|
|
104
|
+
} else {
|
|
105
|
+
meta.keys.push({
|
|
106
|
+
source: FUNCTIONS_META_KEY,
|
|
107
|
+
id: functionId
|
|
108
|
+
});
|
|
109
|
+
}
|
|
874
110
|
};
|
|
875
111
|
|
|
876
112
|
// src/protocol/protocol.ts
|
|
877
113
|
import * as AnthropicClient from "@effect/ai-anthropic/AnthropicClient";
|
|
878
|
-
import * as
|
|
879
|
-
import * as
|
|
880
|
-
import * as
|
|
881
|
-
import * as
|
|
882
|
-
import
|
|
114
|
+
import * as Effect4 from "effect/Effect";
|
|
115
|
+
import * as Layer4 from "effect/Layer";
|
|
116
|
+
import * as Option from "effect/Option";
|
|
117
|
+
import * as Schema from "effect/Schema";
|
|
118
|
+
import * as SchemaAST from "effect/SchemaAST";
|
|
119
|
+
import { AiModelResolver, AiService, OpaqueToolkit } from "@dxos/ai";
|
|
883
120
|
import { AnthropicResolver } from "@dxos/ai/resolvers";
|
|
121
|
+
import { FunctionError, InvalidOperationInputError, InvalidOperationOutputError, Operation, OperationRegistry, Trace } from "@dxos/compute";
|
|
884
122
|
import { LifecycleState, Resource } from "@dxos/context";
|
|
885
|
-
import { Database as Database2, Feed, JsonSchema
|
|
123
|
+
import { Database as Database2, Feed, JsonSchema, Ref, Registry } from "@dxos/echo";
|
|
124
|
+
import { createFeedServiceLayer, EchoClient, makeRegistry } from "@dxos/echo-db";
|
|
886
125
|
import { refFromEncodedReference } from "@dxos/echo/internal";
|
|
887
|
-
import { EchoClient, createFeedServiceLayer } from "@dxos/echo-db";
|
|
888
126
|
import { runAndForwardErrors } from "@dxos/effect";
|
|
889
|
-
import { assertState, failedInvariant
|
|
127
|
+
import { assertState, failedInvariant, invariant } from "@dxos/invariant";
|
|
890
128
|
import { PublicKey } from "@dxos/keys";
|
|
129
|
+
import { log as log2 } from "@dxos/log";
|
|
130
|
+
import { ErrorCodec as ErrorCodec2 } from "@dxos/protocols";
|
|
891
131
|
|
|
892
132
|
// src/protocol/functions-ai-http-client.ts
|
|
893
133
|
import * as Headers from "@effect/platform/Headers";
|
|
894
134
|
import * as HttpClient2 from "@effect/platform/HttpClient";
|
|
895
135
|
import * as HttpClientError from "@effect/platform/HttpClientError";
|
|
896
136
|
import * as HttpClientResponse from "@effect/platform/HttpClientResponse";
|
|
897
|
-
import * as
|
|
137
|
+
import * as Effect3 from "effect/Effect";
|
|
898
138
|
import * as FiberRef from "effect/FiberRef";
|
|
899
|
-
import * as
|
|
139
|
+
import * as Layer3 from "effect/Layer";
|
|
900
140
|
import * as Stream from "effect/Stream";
|
|
901
|
-
import {
|
|
141
|
+
import { FunctionsAiMemoizationMissError, FunctionsAiUpstreamError } from "@dxos/compute";
|
|
142
|
+
import { log } from "@dxos/log";
|
|
902
143
|
import { ErrorCodec } from "@dxos/protocols";
|
|
903
|
-
var
|
|
144
|
+
var __dxlog_file = "/__w/dxos/dxos/packages/core/compute/functions/src/protocol/functions-ai-http-client.ts";
|
|
904
145
|
var requestInitTagKey = "@effect/platform/FetchHttpClient/FetchOptions";
|
|
905
146
|
var FunctionsAiHttpClient = class _FunctionsAiHttpClient {
|
|
906
147
|
static make = (service) => HttpClient2.make((request, url, signal, fiber) => {
|
|
907
148
|
const context = fiber.getFiberRef(FiberRef.currentContext);
|
|
908
149
|
const options = context.unsafeMap.get(requestInitTagKey) ?? {};
|
|
909
150
|
const headers = options.headers ? Headers.merge(Headers.fromInput(options.headers), request.headers) : request.headers;
|
|
910
|
-
const send = (body) =>
|
|
151
|
+
const send = (body) => Effect3.tryPromise({
|
|
911
152
|
try: () => service.fetch(new Request(url, {
|
|
912
153
|
...options,
|
|
913
154
|
method: request.method,
|
|
@@ -915,21 +156,21 @@ var FunctionsAiHttpClient = class _FunctionsAiHttpClient {
|
|
|
915
156
|
body
|
|
916
157
|
})),
|
|
917
158
|
catch: (cause) => {
|
|
918
|
-
|
|
159
|
+
log.error("Failed to fetch", {
|
|
919
160
|
errorSerialized: ErrorCodec.encode(cause)
|
|
920
|
-
}, {
|
|
921
|
-
F: __dxlog_file2,
|
|
922
|
-
L: 43,
|
|
923
|
-
S: this,
|
|
924
|
-
C: (f, a) => f(...a)
|
|
925
|
-
});
|
|
161
|
+
}, { "~LogMeta": "~LogMeta", F: __dxlog_file, L: 31, S: this });
|
|
926
162
|
return new HttpClientError.RequestError({
|
|
927
163
|
request,
|
|
928
164
|
reason: "Transport",
|
|
929
165
|
cause
|
|
930
166
|
});
|
|
931
167
|
}
|
|
932
|
-
}).pipe(
|
|
168
|
+
}).pipe(Effect3.flatMap((response) => (
|
|
169
|
+
// Inspect the body before handing the response to `@effect/ai` so that structured
|
|
170
|
+
// upstream errors surface as typed defects (`FunctionsAiUpstreamError` and friends)
|
|
171
|
+
// rather than as the generic `HttpResponseError` from `@effect/ai/AiError`.
|
|
172
|
+
Effect3.flatMap(Effect3.promise(() => parseUpstreamError(response)), (typedError) => typedError ? Effect3.die(typedError) : Effect3.succeed(HttpClientResponse.fromWeb(request, response)))
|
|
173
|
+
)));
|
|
933
174
|
switch (request.body._tag) {
|
|
934
175
|
case "Raw":
|
|
935
176
|
case "Uint8Array":
|
|
@@ -937,14 +178,54 @@ var FunctionsAiHttpClient = class _FunctionsAiHttpClient {
|
|
|
937
178
|
case "FormData":
|
|
938
179
|
return send(request.body.formData);
|
|
939
180
|
case "Stream":
|
|
940
|
-
return Stream.toReadableStreamEffect(request.body.stream).pipe(
|
|
181
|
+
return Stream.toReadableStreamEffect(request.body.stream).pipe(Effect3.flatMap(send));
|
|
941
182
|
}
|
|
942
183
|
return send(void 0);
|
|
943
184
|
});
|
|
944
|
-
static layer = (service) =>
|
|
185
|
+
static layer = (service) => Layer3.succeed(HttpClient2.HttpClient, _FunctionsAiHttpClient.make(service));
|
|
186
|
+
};
|
|
187
|
+
var parseUpstreamError = async (response) => {
|
|
188
|
+
if (response.ok) {
|
|
189
|
+
return void 0;
|
|
190
|
+
}
|
|
191
|
+
const contentType = response.headers.get("content-type") ?? "";
|
|
192
|
+
if (!contentType.toLowerCase().includes("application/json")) {
|
|
193
|
+
return void 0;
|
|
194
|
+
}
|
|
195
|
+
let body;
|
|
196
|
+
try {
|
|
197
|
+
body = await response.clone().json();
|
|
198
|
+
} catch {
|
|
199
|
+
return void 0;
|
|
200
|
+
}
|
|
201
|
+
if (!body || body.type !== "error" || typeof body.error !== "object" || body.error === null) {
|
|
202
|
+
return void 0;
|
|
203
|
+
}
|
|
204
|
+
const inner = body.error;
|
|
205
|
+
const message = inner.message ?? `Upstream AI service responded with HTTP ${response.status}`;
|
|
206
|
+
if (inner.type === "memoization_miss" && typeof inner.cacheKey === "string") {
|
|
207
|
+
return new FunctionsAiMemoizationMissError({
|
|
208
|
+
message,
|
|
209
|
+
context: {
|
|
210
|
+
cacheKey: inner.cacheKey,
|
|
211
|
+
status: response.status
|
|
212
|
+
}
|
|
213
|
+
});
|
|
214
|
+
}
|
|
215
|
+
return new FunctionsAiUpstreamError({
|
|
216
|
+
message,
|
|
217
|
+
context: {
|
|
218
|
+
type: inner.type,
|
|
219
|
+
status: response.status,
|
|
220
|
+
...inner.cacheKey ? {
|
|
221
|
+
cacheKey: inner.cacheKey
|
|
222
|
+
} : {}
|
|
223
|
+
}
|
|
224
|
+
});
|
|
945
225
|
};
|
|
946
226
|
|
|
947
227
|
// src/protocol/protocol.ts
|
|
228
|
+
var __dxlog_file2 = "/__w/dxos/dxos/packages/core/compute/functions/src/protocol/protocol.ts";
|
|
948
229
|
function _ts_add_disposable_resource(env, value2, async) {
|
|
949
230
|
if (value2 !== null && value2 !== void 0) {
|
|
950
231
|
if (typeof value2 !== "object" && typeof value2 !== "function") throw new TypeError("Object expected.");
|
|
@@ -1010,22 +291,22 @@ function _ts_dispose_resources(env) {
|
|
|
1010
291
|
return next();
|
|
1011
292
|
})(env);
|
|
1012
293
|
}
|
|
1013
|
-
var
|
|
1014
|
-
|
|
1015
|
-
|
|
1016
|
-
throw new TypeError("Invalid function definition");
|
|
294
|
+
var wrapFunctionHandler = (func, opts = {}) => {
|
|
295
|
+
if (!Operation.isOperationWithHandler(func)) {
|
|
296
|
+
throw new TypeError("Expected operation with handler");
|
|
1017
297
|
}
|
|
298
|
+
const serviceTags = func.services.map((service) => service.key);
|
|
1018
299
|
return {
|
|
1019
300
|
meta: {
|
|
1020
|
-
key: func.key,
|
|
1021
|
-
name: func.name,
|
|
1022
|
-
description: func.description,
|
|
1023
|
-
inputSchema:
|
|
1024
|
-
outputSchema: func.
|
|
1025
|
-
services: func.services
|
|
301
|
+
key: func.meta.key,
|
|
302
|
+
name: func.meta.name,
|
|
303
|
+
description: func.meta.description,
|
|
304
|
+
inputSchema: JsonSchema.toJsonSchema(func.input),
|
|
305
|
+
outputSchema: func.output === void 0 ? void 0 : JsonSchema.toJsonSchema(func.output),
|
|
306
|
+
services: func.services.map((service) => service.key)
|
|
1026
307
|
},
|
|
1027
308
|
handler: async ({ data, context }) => {
|
|
1028
|
-
if ((
|
|
309
|
+
if ((serviceTags.includes(Database2.Service.key) || serviceTags.includes(Feed.FeedService.key)) && (!context.services.dataService || !context.services.queryService)) {
|
|
1029
310
|
throw new FunctionError({
|
|
1030
311
|
message: "Services not provided: dataService, queryService"
|
|
1031
312
|
});
|
|
@@ -1037,40 +318,49 @@ var wrapFunctionHandler = (func) => {
|
|
|
1037
318
|
hasError: false
|
|
1038
319
|
};
|
|
1039
320
|
try {
|
|
1040
|
-
if (!
|
|
321
|
+
if (!SchemaAST.isAnyKeyword(func.input.ast)) {
|
|
1041
322
|
try {
|
|
1042
|
-
|
|
323
|
+
Schema.validateSync(func.input, {
|
|
324
|
+
onExcessProperty: "error"
|
|
325
|
+
})(data);
|
|
1043
326
|
} catch (error) {
|
|
1044
|
-
throw new
|
|
1045
|
-
message:
|
|
327
|
+
throw new InvalidOperationInputError({
|
|
328
|
+
message: `Operation input did not match schema (${func.meta.key}): ${error.message}`,
|
|
1046
329
|
cause: error
|
|
1047
330
|
});
|
|
1048
331
|
}
|
|
1049
332
|
}
|
|
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);
|
|
333
|
+
const funcContext = _ts_add_disposable_resource(env, await new FunctionContext(context, opts).open(), true);
|
|
334
|
+
const types = [
|
|
335
|
+
...opts.types ?? [],
|
|
336
|
+
...func.types ?? []
|
|
337
|
+
];
|
|
338
|
+
if (types.length > 0) {
|
|
339
|
+
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'"] });
|
|
340
|
+
funcContext.db.graph.registry.add(types);
|
|
1062
341
|
}
|
|
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())));
|
|
342
|
+
const dataWithDecodedRefs = funcContext.db && !SchemaAST.isAnyKeyword(func.input.ast) ? decodeRefsFromSchema(func.input.ast, data, funcContext.db) : data;
|
|
343
|
+
let result = await func.handler(dataWithDecodedRefs);
|
|
344
|
+
if (Effect4.isEffect(result)) {
|
|
345
|
+
result = await runAndForwardErrors(result.pipe(Effect4.orDie, Effect4.provide(funcContext.createLayer())));
|
|
1071
346
|
}
|
|
1072
|
-
if (
|
|
1073
|
-
|
|
347
|
+
if (serviceTags.includes(Database2.Service.key) && funcContext.db) {
|
|
348
|
+
await funcContext.db.flush({
|
|
349
|
+
disk: true,
|
|
350
|
+
indexes: false
|
|
351
|
+
});
|
|
352
|
+
}
|
|
353
|
+
if (func.output && !SchemaAST.isAnyKeyword(func.output.ast)) {
|
|
354
|
+
try {
|
|
355
|
+
Schema.validateSync(func.output, {
|
|
356
|
+
onExcessProperty: "error"
|
|
357
|
+
})(result);
|
|
358
|
+
} catch (error) {
|
|
359
|
+
throw new InvalidOperationOutputError({
|
|
360
|
+
message: `Operation output did not match schema (${func.meta.key}): ${error.message}`,
|
|
361
|
+
cause: error
|
|
362
|
+
});
|
|
363
|
+
}
|
|
1074
364
|
}
|
|
1075
365
|
return result;
|
|
1076
366
|
} catch (e) {
|
|
@@ -1091,9 +381,11 @@ var FunctionContext = class extends Resource {
|
|
|
1091
381
|
client;
|
|
1092
382
|
db;
|
|
1093
383
|
queues;
|
|
1094
|
-
|
|
384
|
+
opts;
|
|
385
|
+
constructor(context, opts) {
|
|
1095
386
|
super();
|
|
1096
387
|
this.context = context;
|
|
388
|
+
this.opts = opts;
|
|
1097
389
|
if (context.services.dataService && context.services.queryService) {
|
|
1098
390
|
this.client = new EchoClient().connectToService({
|
|
1099
391
|
dataService: context.services.dataService,
|
|
@@ -1105,12 +397,12 @@ var FunctionContext = class extends Resource {
|
|
|
1105
397
|
async _open() {
|
|
1106
398
|
await this.client?.open();
|
|
1107
399
|
this.db = this.client && this.context.spaceId ? this.client.constructDatabase({
|
|
1108
|
-
spaceId: this.context.spaceId ??
|
|
1109
|
-
spaceKey: PublicKey.fromHex(this.context.spaceKey ??
|
|
400
|
+
spaceId: this.context.spaceId ?? failedInvariant(),
|
|
401
|
+
spaceKey: PublicKey.fromHex(this.context.spaceKey ?? failedInvariant("spaceKey missing in context")),
|
|
1110
402
|
reactiveSchemaQuery: false,
|
|
1111
403
|
preloadSchemaOnOpen: false
|
|
1112
404
|
}) : void 0;
|
|
1113
|
-
await this.db?.setSpaceRoot(this.context.spaceRootUrl ??
|
|
405
|
+
await this.db?.setSpaceRoot(this.context.spaceRootUrl ?? failedInvariant("spaceRootUrl missing in context"));
|
|
1114
406
|
await this.db?.open();
|
|
1115
407
|
this.queues = this.client && this.context.spaceId ? this.client.constructQueueFactory(this.context.spaceId) : void 0;
|
|
1116
408
|
}
|
|
@@ -1121,31 +413,115 @@ var FunctionContext = class extends Resource {
|
|
|
1121
413
|
createLayer() {
|
|
1122
414
|
assertState(this._lifecycleState === LifecycleState.OPEN, "FunctionContext is not open");
|
|
1123
415
|
const dbLayer = this.db ? Database2.layer(this.db) : Database2.notAvailable;
|
|
1124
|
-
const queuesLayer = this.queues ? QueueService.layer(this.queues) : QueueService.notAvailable;
|
|
1125
416
|
const feedLayer = this.queues ? createFeedServiceLayer(this.queues) : Feed.notAvailable;
|
|
1126
|
-
const credentials = dbLayer ?
|
|
417
|
+
const credentials = dbLayer ? credentialsLayerFromDatabase({
|
|
1127
418
|
caching: true
|
|
1128
|
-
}).pipe(
|
|
1129
|
-
const
|
|
1130
|
-
const
|
|
1131
|
-
const
|
|
1132
|
-
|
|
1133
|
-
|
|
1134
|
-
|
|
1135
|
-
|
|
419
|
+
}).pipe(Layer4.provide(dbLayer)) : configuredCredentialsLayer([]);
|
|
420
|
+
const aiLayer = this.context.services.functionsAiService ? InternalAiServiceLayer(this.context.services.functionsAiService) : AiService.notAvailable;
|
|
421
|
+
const operationServiceLayer = this.context.services.functionsService ? makeOperationServiceLayer(this.context.services.functionsService) : unavailableOperationServiceLayer;
|
|
422
|
+
const operationRegistryLayer = this.context.services.functionsService ? makeOperationRegistryLayer(this.context.services.functionsService, this.context.spaceId) : emptyOperationRegistryLayer;
|
|
423
|
+
const traceWriterLayer = this.context.services.traceService ? makeTraceWriterLayer(this.context.services.traceService) : Trace.writerLayerNoop;
|
|
424
|
+
log2("Creating function context layer", {
|
|
425
|
+
traceService: !!this.context.services.traceService,
|
|
426
|
+
functionsService: !!this.context.services.functionsService,
|
|
427
|
+
functionsAiService: !!this.context.services.functionsAiService,
|
|
428
|
+
spaceId: this.context.spaceId,
|
|
429
|
+
spaceRootUrl: this.context.spaceRootUrl,
|
|
430
|
+
toolkits: this.opts.toolkits?.length ?? 0,
|
|
431
|
+
types: this.opts.types?.length ?? 0
|
|
432
|
+
}, { "~LogMeta": "~LogMeta", F: __dxlog_file2, L: 233, S: this });
|
|
433
|
+
const registryLayer = this.db ? Layer4.succeed(Registry.Service, this.db.graph.registry) : Layer4.succeed(Registry.Service, makeRegistry());
|
|
434
|
+
return Layer4.mergeAll(
|
|
435
|
+
dbLayer,
|
|
436
|
+
feedLayer,
|
|
437
|
+
credentials,
|
|
438
|
+
operationServiceLayer,
|
|
439
|
+
operationRegistryLayer,
|
|
440
|
+
aiLayer,
|
|
441
|
+
OpaqueToolkit.providerLayer(OpaqueToolkit.merge(...this.opts.toolkits ?? [])),
|
|
442
|
+
traceWriterLayer,
|
|
443
|
+
registryLayer,
|
|
444
|
+
// `FunctionInvocationService` is deprecated; new code should yield `Operation.Service`.
|
|
445
|
+
// The cloudflare wrapper provides only the unavailable layer to satisfy the (still-present)
|
|
446
|
+
// type union — handlers that yield it will die at invocation time.
|
|
447
|
+
FunctionInvocationService.layerNotAvailable
|
|
448
|
+
);
|
|
449
|
+
}
|
|
450
|
+
};
|
|
451
|
+
var makeTraceWriterLayer = (traceService) => Layer4.succeed(Trace.TraceService, {
|
|
452
|
+
write: (eventType, payload) => {
|
|
453
|
+
log2("Writing trace event", {
|
|
454
|
+
eventType: eventType.key
|
|
455
|
+
}, { "~LogMeta": "~LogMeta", F: __dxlog_file2, L: 254, S: void 0 });
|
|
456
|
+
traceService.write([
|
|
457
|
+
{
|
|
458
|
+
key: eventType.key,
|
|
459
|
+
isEphemeral: eventType.isEphemeral,
|
|
460
|
+
data: payload
|
|
461
|
+
}
|
|
462
|
+
]);
|
|
1136
463
|
}
|
|
464
|
+
});
|
|
465
|
+
var InternalAiServiceLayer = (functionsAiService) => AiModelResolver.AiModelResolver.buildAiService.pipe(Layer4.provide(AnthropicResolver.make().pipe(Layer4.provide(AnthropicClient.layer({
|
|
466
|
+
// Note: It doesn't matter what is base url here, it will be proxied to ai gateway in edge.
|
|
467
|
+
apiUrl: "http://internal/provider/anthropic"
|
|
468
|
+
}).pipe(Layer4.provide(FunctionsAiHttpClient.layer(functionsAiService)))))));
|
|
469
|
+
var makeOperationServiceLayer = (functionsService) => {
|
|
470
|
+
const invokeRemote = async (op, input, options) => {
|
|
471
|
+
invariant(op.meta.deployedId, `Operation '${op.meta.key}' has no deployedId; cannot invoke remotely.`, { "~LogMeta": "~LogMeta", F: __dxlog_file2, L: 278, S: void 0, A: ["op.meta.deployedId", "`Operation '${op.meta.key}' has no deployedId; cannot invoke remotely.`"] });
|
|
472
|
+
const result = await functionsService.invoke(op.meta.deployedId, input, {
|
|
473
|
+
spaceId: options?.spaceId,
|
|
474
|
+
// Forward the conversation DXN so the remote runtime can rebuild conversation-scoped
|
|
475
|
+
// services (e.g. `AiContext.Service`) needed by operations like `GetContext`.
|
|
476
|
+
conversation: options?.conversation
|
|
477
|
+
});
|
|
478
|
+
if (result._kind === "success") {
|
|
479
|
+
return {
|
|
480
|
+
data: result.data
|
|
481
|
+
};
|
|
482
|
+
}
|
|
483
|
+
return {
|
|
484
|
+
error: ErrorCodec2.decode(result.error)
|
|
485
|
+
};
|
|
486
|
+
};
|
|
487
|
+
return Layer4.succeed(Operation.Service, {
|
|
488
|
+
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))),
|
|
489
|
+
schedule: (op, input, _options) => Effect4.sync(() => {
|
|
490
|
+
invariant(op.meta.deployedId, `Operation '${op.meta.key}' has no deployedId; cannot schedule remotely.`, { "~LogMeta": "~LogMeta", F: __dxlog_file2, L: 297, S: void 0, A: ["op.meta.deployedId", "`Operation '${op.meta.key}' has no deployedId; cannot schedule remotely.`"] });
|
|
491
|
+
void functionsService.invoke(op.meta.deployedId, input).catch(() => {
|
|
492
|
+
});
|
|
493
|
+
}),
|
|
494
|
+
invokePromise: (op, input, options) => invokeRemote(op, input, options).catch((error) => ({
|
|
495
|
+
error: error instanceof Error ? error : new Error(String(error))
|
|
496
|
+
}))
|
|
497
|
+
});
|
|
1137
498
|
};
|
|
1138
|
-
var
|
|
1139
|
-
|
|
1140
|
-
|
|
499
|
+
var unavailableOperationServiceLayer = Layer4.succeed(Operation.Service, {
|
|
500
|
+
invoke: () => Effect4.die("Operation.Service is not available: missing functionsService in EDGE context."),
|
|
501
|
+
schedule: () => Effect4.die("Operation.Service is not available: missing functionsService in EDGE context."),
|
|
502
|
+
invokePromise: async () => ({
|
|
503
|
+
error: new Error("Operation.Service is not available: missing functionsService in EDGE context.")
|
|
504
|
+
})
|
|
505
|
+
});
|
|
506
|
+
var makeOperationRegistryLayer = (functionsService, spaceId) => Layer4.succeed(OperationRegistry.Service, {
|
|
507
|
+
resolve: (key) => Effect4.gen(function* () {
|
|
508
|
+
const records = yield* Effect4.tryPromise(() => functionsService.query({
|
|
509
|
+
spaceId
|
|
510
|
+
})).pipe(Effect4.orDie);
|
|
511
|
+
const match = records.find((record) => Operation.getKey(record) === key);
|
|
512
|
+
return match ? Option.some(Operation.deserialize(match)) : Option.none();
|
|
513
|
+
})
|
|
514
|
+
});
|
|
515
|
+
var emptyOperationRegistryLayer = Layer4.succeed(OperationRegistry.Service, {
|
|
516
|
+
resolve: () => Effect4.succeed(Option.none())
|
|
1141
517
|
});
|
|
1142
518
|
var decodeRefsFromSchema = (ast, value2, db) => {
|
|
1143
519
|
if (value2 == null) {
|
|
1144
520
|
return value2;
|
|
1145
521
|
}
|
|
1146
|
-
const encoded =
|
|
1147
|
-
if (
|
|
1148
|
-
if (
|
|
522
|
+
const encoded = SchemaAST.encodedBoundAST(ast);
|
|
523
|
+
if (Ref.isRefType(encoded)) {
|
|
524
|
+
if (Ref.isRef(value2)) {
|
|
1149
525
|
return value2;
|
|
1150
526
|
}
|
|
1151
527
|
if (typeof value2 === "object" && value2 !== null && typeof value2["/"] === "string") {
|
|
@@ -1166,7 +542,7 @@ var decodeRefsFromSchema = (ast, value2, db) => {
|
|
|
1166
542
|
const result = {
|
|
1167
543
|
...value2
|
|
1168
544
|
};
|
|
1169
|
-
for (const prop of
|
|
545
|
+
for (const prop of SchemaAST.getPropertySignatures(encoded)) {
|
|
1170
546
|
const key = prop.name.toString();
|
|
1171
547
|
if (key in result) {
|
|
1172
548
|
result[key] = decodeRefsFromSchema(prop.type, result[key], db);
|
|
@@ -1185,7 +561,7 @@ var decodeRefsFromSchema = (ast, value2, db) => {
|
|
|
1185
561
|
return value2;
|
|
1186
562
|
}
|
|
1187
563
|
case "Union": {
|
|
1188
|
-
const nonUndefined = encoded.types.filter((t) => !
|
|
564
|
+
const nonUndefined = encoded.types.filter((t) => !SchemaAST.isUndefinedKeyword(t));
|
|
1189
565
|
if (nonUndefined.length === 1) {
|
|
1190
566
|
return decodeRefsFromSchema(nonUndefined[0], value2, db);
|
|
1191
567
|
}
|
|
@@ -1203,37 +579,16 @@ var decodeRefsFromSchema = (ast, value2, db) => {
|
|
|
1203
579
|
}
|
|
1204
580
|
};
|
|
1205
581
|
export {
|
|
1206
|
-
ComputeEvent,
|
|
1207
|
-
ComputeEventLogger,
|
|
1208
|
-
ComputeEventPayload,
|
|
1209
582
|
ConfiguredCredentialsService,
|
|
1210
|
-
ContextQueueService,
|
|
1211
|
-
CredentialsService,
|
|
1212
|
-
ExampleFunctions,
|
|
1213
583
|
FUNCTIONS_META_KEY,
|
|
1214
584
|
FUNCTIONS_PRESET_META_KEY,
|
|
1215
|
-
Function_exports as Function,
|
|
1216
|
-
FunctionDefinition,
|
|
1217
|
-
FunctionError,
|
|
1218
585
|
FunctionInvocationService,
|
|
1219
|
-
FunctionNotFoundError,
|
|
1220
586
|
MESSAGE_PROPERTY_TOOL_CALL_ID,
|
|
1221
|
-
|
|
1222
|
-
|
|
1223
|
-
|
|
1224
|
-
TracingService,
|
|
1225
|
-
Trigger_exports as Trigger,
|
|
1226
|
-
TriggerEvent_exports as TriggerEvent,
|
|
1227
|
-
TriggerStateNotFoundError,
|
|
1228
|
-
createDefectLogger,
|
|
1229
|
-
createEventLogger,
|
|
1230
|
-
defineFunction,
|
|
1231
|
-
deserializeFunction,
|
|
587
|
+
configuredCredentialsLayer,
|
|
588
|
+
credentialsLayerConfig,
|
|
589
|
+
credentialsLayerFromDatabase,
|
|
1232
590
|
getUserFunctionIdInMetadata,
|
|
1233
|
-
logCustomEvent,
|
|
1234
|
-
serializeFunction,
|
|
1235
591
|
setUserFunctionIdInMetadata,
|
|
1236
|
-
toOperation,
|
|
1237
592
|
withAuthorization,
|
|
1238
593
|
wrapFunctionHandler
|
|
1239
594
|
};
|