@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.
Files changed (77) hide show
  1. package/dist/lib/neutral/index.mjs +283 -932
  2. package/dist/lib/neutral/index.mjs.map +4 -4
  3. package/dist/lib/neutral/meta.json +1 -1
  4. package/dist/types/src/index.d.ts +0 -2
  5. package/dist/types/src/index.d.ts.map +1 -1
  6. package/dist/types/src/protocol/functions-ai-http-client.d.ts.map +1 -1
  7. package/dist/types/src/protocol/functions-ai-http-client.test.d.ts +2 -0
  8. package/dist/types/src/protocol/functions-ai-http-client.test.d.ts.map +1 -0
  9. package/dist/types/src/protocol/protocol.d.ts +14 -2
  10. package/dist/types/src/protocol/protocol.d.ts.map +1 -1
  11. package/dist/types/src/sdk.d.ts +5 -112
  12. package/dist/types/src/sdk.d.ts.map +1 -1
  13. package/dist/types/src/services/credentials.d.ts +15 -38
  14. package/dist/types/src/services/credentials.d.ts.map +1 -1
  15. package/dist/types/src/services/function-invocation-service.d.ts +5 -6
  16. package/dist/types/src/services/function-invocation-service.d.ts.map +1 -1
  17. package/dist/types/src/services/index.d.ts +1 -4
  18. package/dist/types/src/services/index.d.ts.map +1 -1
  19. package/dist/types/src/services/queues.d.ts +1 -46
  20. package/dist/types/src/services/queues.d.ts.map +1 -1
  21. package/dist/types/src/services/tracing.d.ts +1 -84
  22. package/dist/types/src/services/tracing.d.ts.map +1 -1
  23. package/dist/types/src/types/index.d.ts +0 -4
  24. package/dist/types/src/types/index.d.ts.map +1 -1
  25. package/dist/types/src/types/url.d.ts +3 -3
  26. package/dist/types/src/types/url.d.ts.map +1 -1
  27. package/dist/types/tsconfig.tsbuildinfo +1 -1
  28. package/package.json +17 -16
  29. package/src/index.ts +0 -2
  30. package/src/protocol/functions-ai-http-client.test.ts +105 -0
  31. package/src/protocol/functions-ai-http-client.ts +75 -1
  32. package/src/protocol/protocol.test.ts +9 -10
  33. package/src/protocol/protocol.ts +227 -57
  34. package/src/sdk.ts +12 -278
  35. package/src/services/credentials.ts +76 -120
  36. package/src/services/function-invocation-service.ts +6 -10
  37. package/src/services/index.ts +1 -4
  38. package/src/services/queues.ts +1 -78
  39. package/src/services/tracing.ts +0 -159
  40. package/src/types/index.ts +0 -4
  41. package/src/types/url.ts +3 -3
  42. package/dist/types/src/errors.d.ts +0 -121
  43. package/dist/types/src/errors.d.ts.map +0 -1
  44. package/dist/types/src/example/fib.d.ts +0 -7
  45. package/dist/types/src/example/fib.d.ts.map +0 -1
  46. package/dist/types/src/example/forex-effect.d.ts +0 -3
  47. package/dist/types/src/example/forex-effect.d.ts.map +0 -1
  48. package/dist/types/src/example/index.d.ts +0 -12
  49. package/dist/types/src/example/index.d.ts.map +0 -1
  50. package/dist/types/src/example/reply.d.ts +0 -3
  51. package/dist/types/src/example/reply.d.ts.map +0 -1
  52. package/dist/types/src/example/sleep.d.ts +0 -5
  53. package/dist/types/src/example/sleep.d.ts.map +0 -1
  54. package/dist/types/src/operation-compatibility.test.d.ts +0 -2
  55. package/dist/types/src/operation-compatibility.test.d.ts.map +0 -1
  56. package/dist/types/src/services/event-logger.d.ts +0 -81
  57. package/dist/types/src/services/event-logger.d.ts.map +0 -1
  58. package/dist/types/src/types/Function.d.ts +0 -52
  59. package/dist/types/src/types/Function.d.ts.map +0 -1
  60. package/dist/types/src/types/Script.d.ts +0 -21
  61. package/dist/types/src/types/Script.d.ts.map +0 -1
  62. package/dist/types/src/types/Trigger.d.ts +0 -122
  63. package/dist/types/src/types/Trigger.d.ts.map +0 -1
  64. package/dist/types/src/types/TriggerEvent.d.ts +0 -75
  65. package/dist/types/src/types/TriggerEvent.d.ts.map +0 -1
  66. package/src/errors.ts +0 -21
  67. package/src/example/fib.ts +0 -32
  68. package/src/example/forex-effect.ts +0 -40
  69. package/src/example/index.ts +0 -13
  70. package/src/example/reply.ts +0 -21
  71. package/src/example/sleep.ts +0 -24
  72. package/src/operation-compatibility.test.ts +0 -185
  73. package/src/services/event-logger.ts +0 -127
  74. package/src/types/Function.ts +0 -83
  75. package/src/types/Script.ts +0 -34
  76. package/src/types/Trigger.ts +0 -153
  77. 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 Context from "effect/Context";
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 { Query } from "@dxos/echo";
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
- // src/services/event-logger.ts
642
- import * as Context3 from "effect/Context";
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
- write: (event, context2) => tracing.write(event, context2),
679
- getTraceContext: () => context,
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 ComputeEventLogger = class _ComputeEventLogger extends Context3.Tag("@dxos/functions/ComputeEventLogger")() {
757
- static noop = {
758
- log: () => {
759
- },
760
- nodeId: void 0
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
- log: (event) => {
818
- logFunction(message, event);
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
- nodeId: void 0
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 Context4 from "effect/Context";
826
- import * as Effect8 from "effect/Effect";
827
- import * as Layer4 from "effect/Layer";
828
- var FunctionInvocationService = class _FunctionInvocationService extends Context4.Tag("@dxos/functions/FunctionInvocationService")() {
829
- static layerNotAvailable = Layer4.succeed(_FunctionInvocationService, {
830
- invokeFunction: () => Effect8.die("FunctionInvocationService is not avaialble."),
831
- resolveFunction: () => Effect8.die("FunctionInvocationService is not available.")
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) => Effect8.serviceFunctionEffect(_FunctionInvocationService, (service) => service.invokeFunction)(functionDef, input);
834
- static resolveFunction = (key) => Effect8.serviceFunctionEffect(_FunctionInvocationService, (service) => service.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 * as Context5 from "effect/Context";
839
- import * as Effect9 from "effect/Effect";
840
- import * as Layer5 from "effect/Layer";
841
- var QueueService = class _QueueService extends Context5.Tag("@dxos/functions/QueueService")() {
842
- static notAvailable = Layer5.succeed(_QueueService, {
843
- queues: {
844
- get(_dxn) {
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));
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 ContextQueueService = class _ContextQueueService extends Context5.Tag("@dxos/functions/ContextQueueService")() {
871
- static layer = (queue) => Layer5.succeed(_ContextQueueService, {
872
- queue
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 Effect11 from "effect/Effect";
879
- import * as Layer7 from "effect/Layer";
880
- import * as Schema10 from "effect/Schema";
881
- import * as SchemaAST2 from "effect/SchemaAST";
882
- import { AiModelResolver, AiService } from "@dxos/ai";
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 as JsonSchema3, Ref as Ref5 } from "@dxos/echo";
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 as failedInvariant2, invariant as invariant2 } from "@dxos/invariant";
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 Effect10 from "effect/Effect";
140
+ import * as Effect3 from "effect/Effect";
898
141
  import * as FiberRef from "effect/FiberRef";
899
- import * as Layer6 from "effect/Layer";
142
+ import * as Layer3 from "effect/Layer";
900
143
  import * as Stream from "effect/Stream";
901
- import { log as log3 } from "@dxos/log";
144
+ import { FunctionsAiMemoizationMissError, FunctionsAiUpstreamError } from "@dxos/compute";
145
+ import { log } from "@dxos/log";
902
146
  import { ErrorCodec } from "@dxos/protocols";
903
- var __dxlog_file2 = "/__w/dxos/dxos/packages/core/functions/src/protocol/functions-ai-http-client.ts";
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) => Effect10.tryPromise({
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
- log3.error("Failed to fetch", {
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(Effect10.map((response) => HttpClientResponse.fromWeb(request, response)));
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(Effect10.flatMap(send));
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) => Layer6.succeed(HttpClient2.HttpClient, _FunctionsAiHttpClient.make(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 __dxlog_file3 = "/__w/dxos/dxos/packages/core/functions/src/protocol/protocol.ts";
1014
- var wrapFunctionHandler = (func) => {
1015
- if (!FunctionDefinition.isFunction(func)) {
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: JsonSchema3.toJsonSchema(func.inputSchema),
1024
- outputSchema: func.outputSchema === void 0 ? void 0 : JsonSchema3.toJsonSchema(func.outputSchema),
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 ((func.services.includes(Database2.Service.key) || func.services.includes(QueueService.key) || func.services.includes(Feed.Service.key)) && (!context.services.dataService || !context.services.queryService)) {
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 (!SchemaAST2.isAnyKeyword(func.inputSchema.ast)) {
324
+ if (!SchemaAST.isAnyKeyword(func.input.ast)) {
1041
325
  try {
1042
- Schema10.validateSync(func.inputSchema)(data);
326
+ Schema.validateSync(func.input, {
327
+ onExcessProperty: "error"
328
+ })(data);
1043
329
  } catch (error) {
1044
- throw new FunctionError({
1045
- message: "Invalid input schema",
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
- if (func.types.length > 0) {
1052
- invariant2(funcContext.db, "Database is required for functions with types", {
1053
- F: __dxlog_file3,
1054
- L: 70,
1055
- S: void 0,
1056
- A: [
1057
- "funcContext.db",
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 && !SchemaAST2.isAnyKeyword(func.inputSchema.ast) ? decodeRefsFromSchema(func.inputSchema.ast, data, funcContext.db) : data;
1064
- let result = await func.handler({
1065
- // TODO(dmaretskyi): Fix the types.
1066
- context,
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.outputSchema && !SchemaAST2.isAnyKeyword(func.outputSchema.ast)) {
1073
- Schema10.validateSync(func.outputSchema)(result);
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
- constructor(context) {
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 ?? failedInvariant2(),
1109
- spaceKey: PublicKey.fromHex(this.context.spaceKey ?? failedInvariant2("spaceKey missing in context")),
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 ?? failedInvariant2("spaceRootUrl missing in context"));
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 ? CredentialsService.layerFromDatabase({
415
+ const credentials = dbLayer ? credentialsLayerFromDatabase({
1127
416
  caching: true
1128
- }).pipe(Layer7.provide(dbLayer)) : CredentialsService.configuredLayer([]);
1129
- const functionInvocationService = MockedFunctionInvocationService;
1130
- const tracing = TracingService.layerNoop;
1131
- const aiLayer = this.context.services.functionsAiService ? AiModelResolver.AiModelResolver.buildAiService.pipe(Layer7.provide(AnthropicResolver.make().pipe(Layer7.provide(AnthropicClient.layer({
1132
- // Note: It doesn't matter what is base url here, it will be proxied to ai gateway in edge.
1133
- apiUrl: "http://internal/provider/anthropic"
1134
- }).pipe(Layer7.provide(FunctionsAiHttpClient.layer(this.context.services.functionsAiService))))))) : AiService.notAvailable;
1135
- return Layer7.mergeAll(dbLayer, queuesLayer, feedLayer, credentials, functionInvocationService, aiLayer, tracing);
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 MockedFunctionInvocationService = Layer7.succeed(FunctionInvocationService, {
1139
- invokeFunction: () => Effect11.die("Calling functions from functions is not implemented yet."),
1140
- resolveFunction: () => Effect11.die("Not implemented.")
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 = SchemaAST2.encodedBoundAST(ast);
1147
- if (Ref5.isRefType(encoded)) {
1148
- if (Ref5.isRef(value2)) {
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 SchemaAST2.getPropertySignatures(encoded)) {
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) => !SchemaAST2.isUndefinedKeyword(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
- Script_exports as Script,
1223
- ServiceNotAvailableError,
1224
- TracingService,
1225
- Trigger_exports as Trigger,
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
  };