@dxos/functions 0.8.3 → 0.8.4-main.1f223c7

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 (161) hide show
  1. package/dist/lib/browser/bundler/index.mjs +73 -44
  2. package/dist/lib/browser/bundler/index.mjs.map +3 -3
  3. package/dist/lib/browser/chunk-D2XO7XXY.mjs +611 -0
  4. package/dist/lib/browser/chunk-D2XO7XXY.mjs.map +7 -0
  5. package/dist/lib/browser/chunk-J5LGTIGS.mjs +10 -0
  6. package/dist/lib/browser/chunk-J5LGTIGS.mjs.map +7 -0
  7. package/dist/lib/browser/edge/index.mjs +24 -10
  8. package/dist/lib/browser/edge/index.mjs.map +3 -3
  9. package/dist/lib/browser/index.mjs +919 -130
  10. package/dist/lib/browser/index.mjs.map +4 -4
  11. package/dist/lib/browser/meta.json +1 -1
  12. package/dist/lib/browser/testing/index.mjs +110 -9
  13. package/dist/lib/browser/testing/index.mjs.map +4 -4
  14. package/dist/lib/node-esm/bundler/index.mjs +72 -44
  15. package/dist/lib/node-esm/bundler/index.mjs.map +3 -3
  16. package/dist/lib/node-esm/chunk-HSLMI22Q.mjs +11 -0
  17. package/dist/lib/node-esm/chunk-HSLMI22Q.mjs.map +7 -0
  18. package/dist/lib/node-esm/chunk-Z4CJ62WS.mjs +613 -0
  19. package/dist/lib/node-esm/chunk-Z4CJ62WS.mjs.map +7 -0
  20. package/dist/lib/node-esm/edge/index.mjs +23 -10
  21. package/dist/lib/node-esm/edge/index.mjs.map +3 -3
  22. package/dist/lib/node-esm/index.mjs +919 -130
  23. package/dist/lib/node-esm/index.mjs.map +4 -4
  24. package/dist/lib/node-esm/meta.json +1 -1
  25. package/dist/lib/node-esm/testing/index.mjs +110 -9
  26. package/dist/lib/node-esm/testing/index.mjs.map +4 -4
  27. package/dist/types/src/bundler/bundler.d.ts +12 -14
  28. package/dist/types/src/bundler/bundler.d.ts.map +1 -1
  29. package/dist/types/src/edge/functions.d.ts +4 -3
  30. package/dist/types/src/edge/functions.d.ts.map +1 -1
  31. package/dist/types/src/errors.d.ts +137 -0
  32. package/dist/types/src/errors.d.ts.map +1 -0
  33. package/dist/types/src/examples/fib.d.ts +7 -0
  34. package/dist/types/src/examples/fib.d.ts.map +1 -0
  35. package/dist/types/src/examples/index.d.ts +4 -0
  36. package/dist/types/src/examples/index.d.ts.map +1 -0
  37. package/dist/types/src/examples/reply.d.ts +3 -0
  38. package/dist/types/src/examples/reply.d.ts.map +1 -0
  39. package/dist/types/src/examples/sleep.d.ts +5 -0
  40. package/dist/types/src/examples/sleep.d.ts.map +1 -0
  41. package/dist/types/src/executor/executor.d.ts +4 -1
  42. package/dist/types/src/executor/executor.d.ts.map +1 -1
  43. package/dist/types/src/handler.d.ts +46 -16
  44. package/dist/types/src/handler.d.ts.map +1 -1
  45. package/dist/types/src/index.d.ts +3 -0
  46. package/dist/types/src/index.d.ts.map +1 -1
  47. package/dist/types/src/schema.d.ts +8 -3
  48. package/dist/types/src/schema.d.ts.map +1 -1
  49. package/dist/types/src/services/credentials.d.ts +18 -4
  50. package/dist/types/src/services/credentials.d.ts.map +1 -1
  51. package/dist/types/src/services/database.d.ts +55 -3
  52. package/dist/types/src/services/database.d.ts.map +1 -1
  53. package/dist/types/src/services/event-logger.d.ts +65 -30
  54. package/dist/types/src/services/event-logger.d.ts.map +1 -1
  55. package/dist/types/src/services/index.d.ts +2 -2
  56. package/dist/types/src/services/index.d.ts.map +1 -1
  57. package/dist/types/src/services/local-function-execution.d.ts +25 -0
  58. package/dist/types/src/services/local-function-execution.d.ts.map +1 -0
  59. package/dist/types/src/services/queues.d.ts +33 -6
  60. package/dist/types/src/services/queues.d.ts.map +1 -1
  61. package/dist/types/src/services/remote-function-execution-service.d.ts +15 -0
  62. package/dist/types/src/services/remote-function-execution-service.d.ts.map +1 -0
  63. package/dist/types/src/services/service-container.d.ts +29 -17
  64. package/dist/types/src/services/service-container.d.ts.map +1 -1
  65. package/dist/types/src/services/service-registry.d.ts +29 -0
  66. package/dist/types/src/services/service-registry.d.ts.map +1 -0
  67. package/dist/types/src/services/service-registry.test.d.ts +2 -0
  68. package/dist/types/src/services/service-registry.test.d.ts.map +1 -0
  69. package/dist/types/src/services/tracing.d.ts +46 -4
  70. package/dist/types/src/services/tracing.d.ts.map +1 -1
  71. package/dist/types/src/testing/index.d.ts +1 -0
  72. package/dist/types/src/testing/index.d.ts.map +1 -1
  73. package/dist/types/src/testing/layer.d.ts +15 -0
  74. package/dist/types/src/testing/layer.d.ts.map +1 -0
  75. package/dist/types/src/testing/logger.d.ts +3 -3
  76. package/dist/types/src/testing/logger.d.ts.map +1 -1
  77. package/dist/types/src/testing/persist-database.test.d.ts +2 -0
  78. package/dist/types/src/testing/persist-database.test.d.ts.map +1 -0
  79. package/dist/types/src/testing/services.d.ts +55 -9
  80. package/dist/types/src/testing/services.d.ts.map +1 -1
  81. package/dist/types/src/trace.d.ts +20 -22
  82. package/dist/types/src/trace.d.ts.map +1 -1
  83. package/dist/types/src/translations.d.ts +9 -9
  84. package/dist/types/src/translations.d.ts.map +1 -1
  85. package/dist/types/src/triggers/index.d.ts +4 -0
  86. package/dist/types/src/triggers/index.d.ts.map +1 -0
  87. package/dist/types/src/triggers/input-builder.d.ts +3 -0
  88. package/dist/types/src/triggers/input-builder.d.ts.map +1 -0
  89. package/dist/types/src/triggers/invocation-tracer.d.ts +35 -0
  90. package/dist/types/src/triggers/invocation-tracer.d.ts.map +1 -0
  91. package/dist/types/src/triggers/trigger-dispatcher.d.ts +75 -0
  92. package/dist/types/src/triggers/trigger-dispatcher.d.ts.map +1 -0
  93. package/dist/types/src/triggers/trigger-dispatcher.test.d.ts +2 -0
  94. package/dist/types/src/triggers/trigger-dispatcher.test.d.ts.map +1 -0
  95. package/dist/types/src/triggers/trigger-state-store.d.ts +27 -0
  96. package/dist/types/src/triggers/trigger-state-store.d.ts.map +1 -0
  97. package/dist/types/src/types.d.ts +44 -244
  98. package/dist/types/src/types.d.ts.map +1 -1
  99. package/dist/types/src/url.d.ts +10 -6
  100. package/dist/types/src/url.d.ts.map +1 -1
  101. package/dist/types/tsconfig.tsbuildinfo +1 -1
  102. package/package.json +35 -25
  103. package/src/bundler/bundler.test.ts +9 -10
  104. package/src/bundler/bundler.ts +56 -35
  105. package/src/edge/functions.ts +9 -6
  106. package/src/errors.ts +21 -0
  107. package/src/examples/fib.ts +30 -0
  108. package/src/examples/index.ts +7 -0
  109. package/src/examples/reply.ts +18 -0
  110. package/src/examples/sleep.ts +22 -0
  111. package/src/executor/executor.ts +22 -15
  112. package/src/handler.ts +115 -27
  113. package/src/index.ts +3 -2
  114. package/src/schema.ts +11 -0
  115. package/src/services/credentials.ts +87 -5
  116. package/src/services/database.ts +146 -3
  117. package/src/services/event-logger.ts +68 -37
  118. package/src/services/index.ts +2 -2
  119. package/src/services/local-function-execution.ts +114 -0
  120. package/src/services/queues.ts +56 -11
  121. package/src/services/remote-function-execution-service.ts +46 -0
  122. package/src/services/service-container.ts +47 -42
  123. package/src/services/service-registry.test.ts +42 -0
  124. package/src/services/service-registry.ts +59 -0
  125. package/src/services/tracing.ts +118 -5
  126. package/src/testing/index.ts +1 -0
  127. package/src/testing/layer.ts +111 -0
  128. package/src/testing/logger.ts +4 -4
  129. package/src/testing/persist-database.test.ts +87 -0
  130. package/src/testing/services.ts +97 -14
  131. package/src/trace.ts +17 -19
  132. package/src/translations.ts +4 -4
  133. package/src/triggers/index.ts +7 -0
  134. package/src/triggers/input-builder.ts +35 -0
  135. package/src/triggers/invocation-tracer.ts +99 -0
  136. package/src/triggers/trigger-dispatcher.test.ts +652 -0
  137. package/src/triggers/trigger-dispatcher.ts +512 -0
  138. package/src/triggers/trigger-state-store.ts +60 -0
  139. package/src/types.ts +22 -33
  140. package/src/url.ts +13 -10
  141. package/dist/lib/browser/chunk-WEFZUEL2.mjs +0 -300
  142. package/dist/lib/browser/chunk-WEFZUEL2.mjs.map +0 -7
  143. package/dist/lib/node/bundler/index.cjs +0 -260
  144. package/dist/lib/node/bundler/index.cjs.map +0 -7
  145. package/dist/lib/node/chunk-IJAE7FZK.cjs +0 -320
  146. package/dist/lib/node/chunk-IJAE7FZK.cjs.map +0 -7
  147. package/dist/lib/node/edge/index.cjs +0 -94
  148. package/dist/lib/node/edge/index.cjs.map +0 -7
  149. package/dist/lib/node/index.cjs +0 -522
  150. package/dist/lib/node/index.cjs.map +0 -7
  151. package/dist/lib/node/meta.json +0 -1
  152. package/dist/lib/node/testing/index.cjs +0 -43
  153. package/dist/lib/node/testing/index.cjs.map +0 -7
  154. package/dist/lib/node-esm/chunk-LIYPMWNQ.mjs +0 -302
  155. package/dist/lib/node-esm/chunk-LIYPMWNQ.mjs.map +0 -7
  156. package/dist/types/src/services/ai.d.ts +0 -12
  157. package/dist/types/src/services/ai.d.ts.map +0 -1
  158. package/dist/types/src/services/function-call-service.d.ts +0 -16
  159. package/dist/types/src/services/function-call-service.d.ts.map +0 -1
  160. package/src/services/ai.ts +0 -32
  161. package/src/services/function-call-service.ts +0 -64
@@ -1,47 +1,74 @@
1
1
  import {
2
- AiService,
2
+ ComputeEvent,
3
+ ComputeEventLogger,
4
+ ComputeEventPayload,
3
5
  ConfiguredCredentialsService,
6
+ ContextQueueService,
4
7
  CredentialsService,
5
8
  DatabaseService,
6
- EventLogger,
7
- FunctionCallService,
9
+ FUNCTIONS_META_KEY,
10
+ FUNCTIONS_PRESET_META_KEY,
11
+ MESSAGE_PROPERTY_TOOL_CALL_ID,
8
12
  QueueService,
13
+ RemoteFunctionExecutionService,
9
14
  SERVICE_TAGS,
10
15
  ServiceContainer,
11
16
  TracingService,
12
17
  createDefectLogger,
13
18
  createEventLogger,
14
- logCustomEvent
15
- } from "./chunk-WEFZUEL2.mjs";
19
+ getInvocationUrl,
20
+ getUserFunctionIdInMetadata,
21
+ logCustomEvent,
22
+ setUserFunctionIdInMetadata,
23
+ withAuthorization
24
+ } from "./chunk-D2XO7XXY.mjs";
25
+ import {
26
+ __export
27
+ } from "./chunk-J5LGTIGS.mjs";
16
28
 
17
- // packages/core/functions/src/handler.ts
18
- import { Schema } from "effect";
19
- var defineFunction = (params) => {
20
- if (!Schema.isSchema(params.inputSchema)) {
21
- throw new Error("Input schema must be a valid schema");
29
+ // src/errors.ts
30
+ import { BaseError } from "@dxos/errors";
31
+ var ServiceNotAvailableError = class extends BaseError.extend("SERVICE_NOT_AVAILABLE", "Service not available") {
32
+ constructor(service, options) {
33
+ super({
34
+ context: {
35
+ service
36
+ },
37
+ ...options
38
+ });
22
39
  }
23
- if (typeof params.handler !== "function") {
24
- throw new Error("Handler must be a function");
40
+ };
41
+ var FunctionNotFoundError = class extends BaseError.extend("FUNCTION_NOT_FOUND", "Function not found") {
42
+ constructor(functionKey, options) {
43
+ super({
44
+ context: {
45
+ function: functionKey
46
+ },
47
+ ...options
48
+ });
25
49
  }
26
- return {
27
- description: params.description,
28
- inputSchema: params.inputSchema,
29
- outputSchema: params.outputSchema ?? Schema.Any,
30
- handler: params.handler
31
- };
50
+ };
51
+ var FunctionError = class extends BaseError.extend("FUNCTION_ERROR", "Function invocation error") {
52
+ };
53
+ var TriggerStateNotFoundError = class extends BaseError.extend("TRIGGER_STATE_NOT_FOUND", "Trigger state not found") {
32
54
  };
33
55
 
34
- // packages/core/functions/src/schema.ts
35
- import { Schema as Schema2 } from "effect";
56
+ // src/handler.ts
57
+ import { Effect, Schema as Schema2 } from "effect";
58
+ import { Obj, Type as Type2 } from "@dxos/echo";
59
+ import { assertArgument } from "@dxos/invariant";
60
+
61
+ // src/schema.ts
62
+ import { Schema } from "effect";
36
63
  import { Type } from "@dxos/echo";
37
64
  import { JsonSchemaType, LabelAnnotation, Ref } from "@dxos/echo-schema";
38
65
  import { DataType } from "@dxos/schema";
39
- var ScriptType = Schema2.Struct({
40
- name: Schema2.optional(Schema2.String),
41
- description: Schema2.optional(Schema2.String),
66
+ var ScriptType = Schema.Struct({
67
+ name: Schema.optional(Schema.String),
68
+ description: Schema.optional(Schema.String),
42
69
  // TODO(burdon): Change to hash of deployed content.
43
70
  // Whether source has changed since last deploy.
44
- changed: Schema2.optional(Schema2.Boolean),
71
+ changed: Schema.optional(Schema.Boolean),
45
72
  source: Ref(DataType.Text)
46
73
  }).pipe(Type.Obj({
47
74
  typename: "dxos.org/type/Script",
@@ -49,18 +76,28 @@ var ScriptType = Schema2.Struct({
49
76
  }), LabelAnnotation.set([
50
77
  "name"
51
78
  ]));
52
- var FunctionType = Schema2.Struct({
79
+ var FunctionType = Schema.Struct({
80
+ /**
81
+ * Global registry ID.
82
+ * NOTE: The `key` property refers to the original registry entry.
83
+ */
84
+ // TODO(burdon): Create Format type for DXN-like ids, such as this and schema type.
85
+ // TODO(dmaretskyi): Consider making it part of ECHO meta.
86
+ // TODO(dmaretskyi): Make required.
87
+ key: Schema.optional(Schema.String).annotations({
88
+ description: "Unique registration key for the blueprint"
89
+ }),
53
90
  // TODO(burdon): Rename to id/uri?
54
- name: Schema2.NonEmptyString,
55
- version: Schema2.String,
56
- description: Schema2.optional(Schema2.String),
91
+ name: Schema.NonEmptyString,
92
+ version: Schema.String,
93
+ description: Schema.optional(Schema.String),
57
94
  // Reference to a source script if it exists within ECHO.
58
95
  // TODO(burdon): Don't ref ScriptType directly (core).
59
- source: Schema2.optional(Ref(ScriptType)),
60
- inputSchema: Schema2.optional(JsonSchemaType),
61
- outputSchema: Schema2.optional(JsonSchemaType),
96
+ source: Schema.optional(Ref(ScriptType)),
97
+ inputSchema: Schema.optional(JsonSchemaType),
98
+ outputSchema: Schema.optional(JsonSchemaType),
62
99
  // Local binding to a function name.
63
- binding: Schema2.optional(Schema2.String)
100
+ binding: Schema.optional(Schema.String)
64
101
  }).pipe(Type.Obj({
65
102
  typename: "dxos.org/type/Function",
66
103
  version: "0.1.0"
@@ -68,25 +105,106 @@ var FunctionType = Schema2.Struct({
68
105
  "name"
69
106
  ]));
70
107
 
71
- // packages/core/functions/src/trace.ts
108
+ // src/handler.ts
109
+ var typeId = Symbol.for("@dxos/functions/FunctionDefinition");
110
+ var defineFunction = ({ key, name, description, inputSchema, outputSchema = Schema2.Any, handler }) => {
111
+ if (!Schema2.isSchema(inputSchema)) {
112
+ throw new Error("Input schema must be a valid schema");
113
+ }
114
+ if (typeof handler !== "function") {
115
+ throw new Error("Handler must be a function");
116
+ }
117
+ const limit = Error.stackTraceLimit;
118
+ Error.stackTraceLimit = 2;
119
+ const traceError = new Error();
120
+ Error.stackTraceLimit = limit;
121
+ let cache = false;
122
+ const captureStackTrace = () => {
123
+ if (cache !== false) {
124
+ return cache;
125
+ }
126
+ if (traceError.stack !== void 0) {
127
+ const stack = traceError.stack.split("\n");
128
+ if (stack[2] !== void 0) {
129
+ cache = stack[2].trim();
130
+ return cache;
131
+ }
132
+ }
133
+ };
134
+ const handlerWithSpan = (...args) => {
135
+ const result = handler(...args);
136
+ if (Effect.isEffect(result)) {
137
+ return Effect.withSpan(result, `${key ?? name}`, {
138
+ captureStackTrace
139
+ });
140
+ }
141
+ return result;
142
+ };
143
+ return {
144
+ [typeId]: true,
145
+ key: key ?? name,
146
+ name,
147
+ description,
148
+ inputSchema,
149
+ outputSchema,
150
+ handler: handlerWithSpan
151
+ };
152
+ };
153
+ var FunctionDefinition = {
154
+ make: defineFunction,
155
+ isFunction: (value) => {
156
+ return typeof value === "object" && value !== null && Symbol.for("@dxos/functions/FunctionDefinition") in value;
157
+ },
158
+ serialize: (functionDef) => {
159
+ assertArgument(FunctionDefinition.isFunction(functionDef), "functionDef");
160
+ return serializeFunction(functionDef);
161
+ },
162
+ deserialize: (functionObj) => {
163
+ assertArgument(Obj.instanceOf(FunctionType, functionObj), "functionObj");
164
+ return deserializeFunction(functionObj);
165
+ }
166
+ };
167
+ var serializeFunction = (functionDef) => Obj.make(FunctionType, {
168
+ key: functionDef.name,
169
+ name: functionDef.name,
170
+ version: "0.1.0",
171
+ description: functionDef.description,
172
+ inputSchema: Type2.toJsonSchema(functionDef.inputSchema),
173
+ outputSchema: !functionDef.outputSchema ? void 0 : Type2.toJsonSchema(functionDef.outputSchema)
174
+ });
175
+ var deserializeFunction = (functionObj) => {
176
+ return {
177
+ [typeId]: true,
178
+ // TODO(dmaretskyi): Fix key.
179
+ key: functionObj.key ?? functionObj.name,
180
+ name: functionObj.name,
181
+ description: functionObj.description,
182
+ inputSchema: !functionObj.inputSchema ? Schema2.Unknown : Type2.toEffectSchema(functionObj.inputSchema),
183
+ outputSchema: !functionObj.outputSchema ? void 0 : Type2.toEffectSchema(functionObj.outputSchema),
184
+ handler: () => {
185
+ }
186
+ };
187
+ };
188
+
189
+ // src/trace.ts
72
190
  import { Schema as Schema4 } from "effect";
73
- import { Type as Type2 } from "@dxos/echo";
191
+ import { Type as Type4 } from "@dxos/echo";
74
192
  import { Queue } from "@dxos/echo-db";
75
193
  import { ObjectId } from "@dxos/echo-schema";
76
194
  import { log } from "@dxos/log";
77
195
 
78
- // packages/core/functions/src/types.ts
196
+ // src/types.ts
79
197
  import { Schema as Schema3, SchemaAST } from "effect";
80
- import { Expando, OptionsAnnotationId, TypedObject, Ref as Ref2, RawObject } from "@dxos/echo-schema";
198
+ import { QueryAST, Type as Type3 } from "@dxos/echo";
199
+ import { Expando, OptionsAnnotationId, RawObject, Ref as Ref2 } from "@dxos/echo-schema";
81
200
  import { DXN } from "@dxos/keys";
82
- var TriggerKind = /* @__PURE__ */ function(TriggerKind2) {
83
- TriggerKind2["Timer"] = "timer";
84
- TriggerKind2["Webhook"] = "webhook";
85
- TriggerKind2["Subscription"] = "subscription";
86
- TriggerKind2["Email"] = "email";
87
- TriggerKind2["Queue"] = "queue";
88
- return TriggerKind2;
89
- }({});
201
+ var TriggerKinds = [
202
+ "timer",
203
+ "webhook",
204
+ "subscription",
205
+ "email",
206
+ "queue"
207
+ ];
90
208
  var kindLiteralAnnotations = {
91
209
  title: "Kind"
92
210
  };
@@ -104,6 +222,7 @@ var EmailTriggerSchema = Schema3.Struct({
104
222
  }).pipe(Schema3.mutable);
105
223
  var QueueTriggerSchema = Schema3.Struct({
106
224
  kind: Schema3.Literal("queue").annotations(kindLiteralAnnotations),
225
+ // TODO(dmaretskyi): Change to a reference.
107
226
  queue: DXN.Schema
108
227
  }).pipe(Schema3.mutable);
109
228
  var WebhookTriggerSchema = Schema3.Struct({
@@ -119,21 +238,11 @@ var WebhookTriggerSchema = Schema3.Struct({
119
238
  title: "Port"
120
239
  }))
121
240
  }).pipe(Schema3.mutable);
122
- var QuerySchema = Schema3.Struct({
123
- type: Schema3.optional(Schema3.String.annotations({
124
- title: "Type"
125
- })),
126
- props: Schema3.optional(Schema3.Record({
127
- key: Schema3.String,
128
- value: Schema3.Any
129
- }))
130
- }).annotations({
131
- title: "Query"
132
- });
133
241
  var SubscriptionTriggerSchema = Schema3.Struct({
134
242
  kind: Schema3.Literal("subscription").annotations(kindLiteralAnnotations),
135
- // TODO(burdon): Define query DSL (from ECHO). Reconcile with Table.Query.
136
- filter: QuerySchema,
243
+ query: QueryAST.Query.annotations({
244
+ title: "Query"
245
+ }),
137
246
  options: Schema3.optional(Schema3.Struct({
138
247
  // Watch changes to object (not just creation).
139
248
  deep: Schema3.optional(Schema3.Boolean.annotations({
@@ -178,7 +287,7 @@ var SubscriptionTriggerOutput = Schema3.mutable(Schema3.Struct({
178
287
  var TimerTriggerOutput = Schema3.mutable(Schema3.Struct({
179
288
  tick: Schema3.Number
180
289
  }));
181
- var FunctionTriggerSchema = Schema3.Struct({
290
+ var FunctionTrigger_ = Schema3.Struct({
182
291
  /**
183
292
  * Function or workflow to invoke.
184
293
  */
@@ -213,12 +322,11 @@ var FunctionTriggerSchema = Schema3.Struct({
213
322
  key: Schema3.String,
214
323
  value: Schema3.Any
215
324
  })))
216
- });
217
- var FunctionTrigger = class extends TypedObject({
325
+ }).pipe(Type3.Obj({
218
326
  typename: "dxos.org/type/FunctionTrigger",
219
327
  version: "0.2.0"
220
- })(FunctionTriggerSchema.fields) {
221
- };
328
+ }));
329
+ var FunctionTrigger = FunctionTrigger_;
222
330
  var FunctionManifestSchema = Schema3.Struct({
223
331
  functions: Schema3.optional(Schema3.mutable(Schema3.Array(RawObject(FunctionType)))),
224
332
  triggers: Schema3.optional(Schema3.mutable(Schema3.Array(RawObject(FunctionTrigger))))
@@ -228,8 +336,8 @@ var FUNCTION_TYPES = [
228
336
  FunctionTrigger
229
337
  ];
230
338
 
231
- // packages/core/functions/src/trace.ts
232
- var __dxlog_file = "/home/runner/work/dxos/dxos/packages/core/functions/src/trace.ts";
339
+ // src/trace.ts
340
+ var __dxlog_file = "/__w/dxos/dxos/packages/core/functions/src/trace.ts";
233
341
  var InvocationOutcome = /* @__PURE__ */ function(InvocationOutcome2) {
234
342
  InvocationOutcome2["SUCCESS"] = "success";
235
343
  InvocationOutcome2["FAILURE"] = "failure";
@@ -242,7 +350,7 @@ var InvocationTraceEventType = /* @__PURE__ */ function(InvocationTraceEventType
242
350
  return InvocationTraceEventType2;
243
351
  }({});
244
352
  var TraceEventException = Schema4.Struct({
245
- timestampMs: Schema4.Number,
353
+ timestamp: Schema4.Number,
246
354
  message: Schema4.String,
247
355
  name: Schema4.String,
248
356
  stack: Schema4.optional(Schema4.String)
@@ -260,7 +368,7 @@ var InvocationTraceStartEvent = Schema4.Struct({
260
368
  /**
261
369
  * Event generation time.
262
370
  */
263
- timestampMs: Schema4.Number,
371
+ timestamp: Schema4.Number,
264
372
  /**
265
373
  * Data passed to function / workflow as an argument.
266
374
  */
@@ -269,16 +377,16 @@ var InvocationTraceStartEvent = Schema4.Struct({
269
377
  /**
270
378
  * Queue for function/workflow invocation events.
271
379
  */
272
- invocationTraceQueue: Type2.Ref(Queue),
380
+ invocationTraceQueue: Schema4.optional(Type4.Ref(Queue)),
273
381
  /**
274
382
  * DXN of the invoked function/workflow.
275
383
  */
276
- invocationTarget: Type2.Ref(Type2.Expando),
384
+ invocationTarget: Schema4.optional(Type4.Ref(Type4.Expando)),
277
385
  /**
278
386
  * Present for automatic invocations.
279
387
  */
280
- trigger: Schema4.optional(Type2.Ref(FunctionTrigger))
281
- }).pipe(Type2.Obj({
388
+ trigger: Schema4.optional(Type4.Ref(FunctionTrigger))
389
+ }).pipe(Type4.Obj({
282
390
  typename: "dxos.org/type/InvocationTraceStart",
283
391
  version: "0.1.0"
284
392
  }));
@@ -296,15 +404,15 @@ var InvocationTraceEndEvent = Schema4.Struct({
296
404
  * Event generation time.
297
405
  */
298
406
  // TODO(burdon): Remove ms suffix.
299
- timestampMs: Schema4.Number,
407
+ timestamp: Schema4.Number,
300
408
  outcome: Schema4.Enums(InvocationOutcome),
301
409
  exception: Schema4.optional(TraceEventException)
302
- }).pipe(Type2.Obj({
410
+ }).pipe(Type4.Obj({
303
411
  typename: "dxos.org/type/InvocationTraceEnd",
304
412
  version: "0.1.0"
305
413
  }));
306
414
  var TraceEventLog = Schema4.Struct({
307
- timestampMs: Schema4.Number,
415
+ timestamp: Schema4.Number,
308
416
  level: Schema4.String,
309
417
  message: Schema4.String,
310
418
  context: Schema4.optional(Schema4.Object)
@@ -314,13 +422,11 @@ var TraceEvent = Schema4.Struct({
314
422
  // TODO(burdon): Need enum/numeric result (not string).
315
423
  outcome: Schema4.String,
316
424
  truncated: Schema4.Boolean,
317
- /**
318
- * Time when the event was persisted.
319
- */
320
- ingestionTimestampMs: Schema4.Number,
425
+ /** Time when the event was persisted. */
426
+ ingestionTimestamp: Schema4.Number,
321
427
  logs: Schema4.Array(TraceEventLog),
322
428
  exceptions: Schema4.Array(TraceEventException)
323
- }).pipe(Type2.Obj({
429
+ }).pipe(Type4.Obj({
324
430
  typename: "dxos.org/type/TraceEvent",
325
431
  version: "0.1.0"
326
432
  }));
@@ -353,7 +459,7 @@ var createInvocationSpans = (items) => {
353
459
  invocationId
354
460
  }, {
355
461
  F: __dxlog_file,
356
- L: 160,
462
+ L: 158,
357
463
  S: void 0,
358
464
  C: (f, a) => f(...a)
359
465
  });
@@ -362,8 +468,8 @@ var createInvocationSpans = (items) => {
362
468
  const isInProgress = end === void 0;
363
469
  result.push({
364
470
  id: invocationId,
365
- timestampMs: start.timestampMs,
366
- durationMs: isInProgress ? now - start.timestampMs : end.timestampMs - start.timestampMs,
471
+ timestamp: start.timestamp,
472
+ duration: isInProgress ? now - start.timestamp : end.timestamp - start.timestamp,
367
473
  outcome: end?.outcome ?? "pending",
368
474
  exception: end?.exception,
369
475
  input: start.input,
@@ -375,112 +481,795 @@ var createInvocationSpans = (items) => {
375
481
  return result;
376
482
  };
377
483
 
378
- // packages/core/functions/src/url.ts
379
- var FUNCTIONS_META_KEY = "dxos.org/service/function";
380
- var FUNCTIONS_PRESET_META_KEY = "dxos.org/service/function-preset";
381
- var isSecure = (protocol) => {
382
- return protocol === "https:" || protocol === "wss:";
484
+ // src/triggers/invocation-tracer.ts
485
+ import { Context as Context2, Effect as Effect3, Layer as Layer2 } from "effect";
486
+ import { Obj as Obj2, Ref as Ref3 } from "@dxos/echo";
487
+ import { DXN as DXN2, ObjectId as ObjectId2 } from "@dxos/keys";
488
+
489
+ // src/services/local-function-execution.ts
490
+ import { Context, Effect as Effect2, Layer, Schema as Schema5 } from "effect";
491
+ import { todo } from "@dxos/debug";
492
+ function _define_property(obj, key, value) {
493
+ if (key in obj) {
494
+ Object.defineProperty(obj, key, {
495
+ value,
496
+ enumerable: true,
497
+ configurable: true,
498
+ writable: true
499
+ });
500
+ } else {
501
+ obj[key] = value;
502
+ }
503
+ return obj;
504
+ }
505
+ var _Context_Tag;
506
+ var LocalFunctionExecutionService = class extends (_Context_Tag = Context.Tag("@dxos/functions/LocalFunctionExecutionService")()) {
383
507
  };
384
- var getUserFunctionUrlInMetadata = (meta) => {
385
- return meta.keys.find((key) => key.source === FUNCTIONS_META_KEY)?.id;
508
+ _define_property(LocalFunctionExecutionService, "layer", Layer.succeed(LocalFunctionExecutionService, {
509
+ invokeFunction: (functionDef, input) => invokeFunction(functionDef, input)
510
+ }));
511
+ _define_property(LocalFunctionExecutionService, "layerLive", Layer.effect(LocalFunctionExecutionService, Effect2.gen(function* () {
512
+ const resolver = yield* FunctionImplementationResolver;
513
+ return {
514
+ invokeFunction: Effect2.fn("invokeFunction")(function* (functionDef, input) {
515
+ const resolved = yield* resolver.resolveFunctionImplementation(functionDef).pipe(Effect2.orDie);
516
+ return yield* invokeFunction(resolved, input);
517
+ })
518
+ };
519
+ })));
520
+ _define_property(LocalFunctionExecutionService, "invokeFunction", Effect2.serviceFunctionEffect(LocalFunctionExecutionService, (_) => _.invokeFunction));
521
+ var invokeFunction = (functionDef, input) => Effect2.gen(function* () {
522
+ const assertInput = functionDef.inputSchema.pipe(Schema5.asserts);
523
+ assertInput(input);
524
+ const context = {
525
+ space: void 0,
526
+ getService: () => todo(),
527
+ getSpace: async (_spaceId) => {
528
+ throw new Error("Not available. Use the database service instead.");
529
+ }
530
+ };
531
+ const data = yield* Effect2.gen(function* () {
532
+ const result = functionDef.handler({
533
+ context,
534
+ data: input
535
+ });
536
+ if (Effect2.isEffect(result)) {
537
+ return yield* result.pipe(Effect2.orDie);
538
+ } else if (typeof result === "object" && result !== null && "then" in result && typeof result.then === "function") {
539
+ return yield* Effect2.promise(() => result);
540
+ } else {
541
+ return result;
542
+ }
543
+ }).pipe(Effect2.orDie, Effect2.catchAllDefect((defect) => Effect2.die(new FunctionError({
544
+ context: {
545
+ name: functionDef.name
546
+ },
547
+ cause: defect
548
+ }))));
549
+ const assertOutput = functionDef.outputSchema?.pipe(Schema5.asserts);
550
+ assertOutput(data);
551
+ return data;
552
+ }).pipe(Effect2.withSpan("invokeFunction", {
553
+ attributes: {
554
+ name: functionDef.name
555
+ }
556
+ }));
557
+ var _Context_Tag1;
558
+ var FunctionImplementationResolver = class extends (_Context_Tag1 = Context.Tag("@dxos/functions/FunctionImplementationResolver")()) {
386
559
  };
387
- var setUserFunctionUrlInMetadata = (meta, functionUrl) => {
388
- const key = meta.keys.find((key2) => key2.source === FUNCTIONS_META_KEY);
389
- if (key) {
390
- if (key.id !== functionUrl) {
391
- throw new Error("Metadata mismatch");
560
+ _define_property(FunctionImplementationResolver, "layerTest", ({ functions }) => Layer.succeed(FunctionImplementationResolver, {
561
+ resolveFunctionImplementation: (functionDef) => {
562
+ const resolved = functions.find((f) => f.name === functionDef.name);
563
+ if (!resolved) {
564
+ return Effect2.fail(new FunctionNotFoundError(functionDef.name));
392
565
  }
566
+ return Effect2.succeed(resolved);
567
+ }
568
+ }));
569
+
570
+ // src/triggers/invocation-tracer.ts
571
+ function _define_property2(obj, key, value) {
572
+ if (key in obj) {
573
+ Object.defineProperty(obj, key, {
574
+ value,
575
+ enumerable: true,
576
+ configurable: true,
577
+ writable: true
578
+ });
393
579
  } else {
394
- meta.keys.push({
395
- source: FUNCTIONS_META_KEY,
396
- id: functionUrl
580
+ obj[key] = value;
581
+ }
582
+ return obj;
583
+ }
584
+ var _Context_Tag2;
585
+ var InvocationTracer = class extends (_Context_Tag2 = Context2.Tag("@dxos/functions/InvocationTracer")()) {
586
+ };
587
+ _define_property2(InvocationTracer, "layerLive", (opts) => Layer2.effect(InvocationTracer, Effect3.gen(function* () {
588
+ return {
589
+ traceInvocationStart: Effect3.fn("traceInvocationStart")(function* ({ payload, target }) {
590
+ const invocationId = ObjectId2.random();
591
+ const invocationTraceQueue = yield* QueueService.createQueue({
592
+ subspaceTag: "trace"
593
+ });
594
+ const now = Date.now();
595
+ const traceEvent = Obj2.make(InvocationTraceStartEvent, {
596
+ type: InvocationTraceEventType.START,
597
+ invocationId,
598
+ timestamp: now,
599
+ // TODO(dmaretskyi): Not json-stringifying this makes ECHO fail when one ECHO object becomes embedded in another ECHO object.
600
+ input: JSON.parse(JSON.stringify(payload.data ?? {})),
601
+ invocationTraceQueue: Ref3.fromDXN(invocationTraceQueue.dxn),
602
+ invocationTarget: target ? Ref3.fromDXN(target) : void 0,
603
+ trigger: payload.trigger ? Ref3.fromDXN(DXN2.fromLocalObjectId(payload.trigger.id)) : void 0
604
+ });
605
+ yield* QueueService.append(opts.invocationTraceQueue, [
606
+ traceEvent
607
+ ]);
608
+ return {
609
+ invocationId,
610
+ invocationTraceQueue
611
+ };
612
+ }),
613
+ traceInvocationEnd: Effect3.fn("traceInvocationEnd")(function* ({ trace, exception }) {
614
+ const now = Date.now();
615
+ const traceEvent = Obj2.make(InvocationTraceEndEvent, {
616
+ type: InvocationTraceEventType.END,
617
+ invocationId: trace.invocationId,
618
+ timestamp: now,
619
+ outcome: exception ? InvocationOutcome.FAILURE : InvocationOutcome.SUCCESS,
620
+ exception: exception ? {
621
+ name: exception.constructor.name,
622
+ timestamp: now,
623
+ message: exception?.message ?? "Unknown error",
624
+ stack: exception?.stack
625
+ } : void 0
626
+ });
627
+ yield* QueueService.append(opts.invocationTraceQueue, [
628
+ traceEvent
629
+ ]);
630
+ })
631
+ };
632
+ })));
633
+ _define_property2(InvocationTracer, "layerTest", Layer2.unwrapEffect(Effect3.gen(function* () {
634
+ const queue = yield* QueueService.createQueue({
635
+ subspaceTag: "trace"
636
+ });
637
+ return InvocationTracer.layerLive({
638
+ invocationTraceQueue: queue
639
+ });
640
+ })));
641
+
642
+ // src/triggers/trigger-dispatcher.ts
643
+ import { Cause, Context as Context4, Cron, Duration, Effect as Effect5, Either, Exit, Fiber, Layer as Layer4, Option as Option2, Record, Schedule } from "effect";
644
+ import { DXN as DXN3, Filter, Obj as Obj3, Query } from "@dxos/echo";
645
+ import { causeToError } from "@dxos/effect";
646
+ import { invariant } from "@dxos/invariant";
647
+ import { log as log2 } from "@dxos/log";
648
+ import { KEY_QUEUE_POSITION } from "@dxos/protocols";
649
+
650
+ // src/triggers/input-builder.ts
651
+ var createInvocationPayload = (trigger, event) => {
652
+ if (!trigger.input) {
653
+ return event;
654
+ }
655
+ const payload = {};
656
+ for (const [key, value] of Object.entries(trigger.input)) {
657
+ if (typeof value !== "string" || !(value.startsWith("{{") && value.endsWith("}}"))) {
658
+ payload[key] = value;
659
+ continue;
660
+ }
661
+ const propertyPath = value.slice(2, -2);
662
+ let valueSubstitution = propertyPath.startsWith("trigger.") ? trigger : propertyPath.startsWith("event.") ? event : void 0;
663
+ for (const pathSegment of propertyPath.split(".").slice(1)) {
664
+ if (valueSubstitution && typeof valueSubstitution === "object") {
665
+ valueSubstitution = valueSubstitution[pathSegment];
666
+ }
667
+ }
668
+ payload[key] = valueSubstitution;
669
+ }
670
+ return payload;
671
+ };
672
+
673
+ // src/triggers/trigger-state-store.ts
674
+ import { KeyValueStore } from "@effect/platform";
675
+ import { Context as Context3 } from "effect";
676
+ import { Schema as Schema6 } from "effect";
677
+ import { Effect as Effect4, Layer as Layer3 } from "effect";
678
+ import { Option } from "effect";
679
+ import { ObjectId as ObjectId3 } from "@dxos/keys";
680
+ function _define_property3(obj, key, value) {
681
+ if (key in obj) {
682
+ Object.defineProperty(obj, key, {
683
+ value,
684
+ enumerable: true,
685
+ configurable: true,
686
+ writable: true
397
687
  });
688
+ } else {
689
+ obj[key] = value;
398
690
  }
691
+ return obj;
692
+ }
693
+ var TriggerState = Schema6.Struct({
694
+ version: Schema6.Literal("1"),
695
+ triggerId: Schema6.String,
696
+ state: Schema6.optional(Schema6.Union(Schema6.TaggedStruct("subscription", {
697
+ processedVersions: Schema6.Record({
698
+ key: ObjectId3,
699
+ value: Schema6.String
700
+ })
701
+ })))
702
+ });
703
+ var _Context_Tag3;
704
+ var TriggerStateStore = class extends (_Context_Tag3 = Context3.Tag("@dxos/functions/TriggerStateStore")()) {
399
705
  };
400
- var makeFunctionUrl = (fn) => `/${fn.functionId}`;
401
- var getInvocationUrl = (functionUrl, edgeUrl, options = {}) => {
402
- const baseUrl = new URL("functions/", edgeUrl);
403
- const relativeUrl = functionUrl.replace(/^\//, "");
404
- const url = new URL(`./${relativeUrl}`, baseUrl.toString());
405
- options.spaceId && url.searchParams.set("spaceId", options.spaceId);
406
- options.subjectId && url.searchParams.set("subjectId", options.subjectId);
407
- url.protocol = isSecure(url.protocol) ? "https" : "http";
408
- return url.toString();
706
+ _define_property3(TriggerStateStore, "getState", Effect4.serviceFunctionEffect(TriggerStateStore, (_) => _.getState));
707
+ _define_property3(TriggerStateStore, "saveState", Effect4.serviceFunctionEffect(TriggerStateStore, (_) => _.saveState));
708
+ _define_property3(TriggerStateStore, "layerKv", Layer3.effect(TriggerStateStore, Effect4.gen(function* () {
709
+ const kv = yield* KeyValueStore.KeyValueStore;
710
+ const schemaStore = kv.forSchema(Schema6.parseJson(TriggerState));
711
+ const store = {
712
+ getState: Effect4.fn("TriggerStateStore.getState")(function* (triggerId) {
713
+ const valueOption = yield* schemaStore.get(triggerId).pipe(Effect4.orDie);
714
+ if (Option.isNone(valueOption)) {
715
+ return yield* Effect4.fail(new TriggerStateNotFoundError());
716
+ }
717
+ return valueOption.value;
718
+ }),
719
+ saveState: Effect4.fn("TriggerStateStore.saveState")(function* (state) {
720
+ yield* schemaStore.set(state.triggerId, state).pipe(Effect4.orDie);
721
+ })
722
+ };
723
+ return store;
724
+ })));
725
+ _define_property3(TriggerStateStore, "layerMemory", TriggerStateStore.layerKv.pipe(Layer3.provide(KeyValueStore.layerMemory)));
726
+
727
+ // src/triggers/trigger-dispatcher.ts
728
+ function _define_property4(obj, key, value) {
729
+ if (key in obj) {
730
+ Object.defineProperty(obj, key, {
731
+ value,
732
+ enumerable: true,
733
+ configurable: true,
734
+ writable: true
735
+ });
736
+ } else {
737
+ obj[key] = value;
738
+ }
739
+ return obj;
740
+ }
741
+ var __dxlog_file2 = "/__w/dxos/dxos/packages/core/functions/src/triggers/trigger-dispatcher.ts";
742
+ var _Context_Tag4;
743
+ var TriggerDispatcher = class extends (_Context_Tag4 = Context4.Tag("@dxos/functions/TriggerDispatcher")()) {
409
744
  };
745
+ _define_property4(TriggerDispatcher, "layer", (options) => Layer4.effect(TriggerDispatcher, Effect5.gen(function* () {
746
+ return new TriggerDispatcherImpl(options);
747
+ })));
748
+ var TriggerDispatcherImpl = class {
749
+ get running() {
750
+ return this._running;
751
+ }
752
+ constructor(options) {
753
+ _define_property4(this, "livePollInterval", void 0);
754
+ _define_property4(this, "timeControl", void 0);
755
+ _define_property4(this, "_running", false);
756
+ _define_property4(this, "_internalTime", void 0);
757
+ _define_property4(this, "_timerFiber", void 0);
758
+ _define_property4(this, "_scheduledTriggers", /* @__PURE__ */ new Map());
759
+ _define_property4(this, "start", () => Effect5.gen(this, function* () {
760
+ if (this._running) {
761
+ return;
762
+ }
763
+ this._running = true;
764
+ if (this.timeControl === "natural") {
765
+ this._timerFiber = yield* this._startNaturalTimeProcessing().pipe(Effect5.tapErrorCause((cause) => {
766
+ const error = causeToError(cause);
767
+ log2.error("trigger dispatcher error", {
768
+ error
769
+ }, {
770
+ F: __dxlog_file2,
771
+ L: 170,
772
+ S: this,
773
+ C: (f, a) => f(...a)
774
+ });
775
+ this._running = false;
776
+ return Effect5.void;
777
+ }), Effect5.forkDaemon);
778
+ } else {
779
+ return yield* Effect5.dieMessage("TriggerDispatcher started in manual time control mode");
780
+ }
781
+ log2.info("TriggerDispatcher started", {
782
+ timeControl: this.timeControl
783
+ }, {
784
+ F: __dxlog_file2,
785
+ L: 180,
786
+ S: this,
787
+ C: (f, a) => f(...a)
788
+ });
789
+ }));
790
+ _define_property4(this, "stop", () => Effect5.gen(this, function* () {
791
+ if (!this._running) {
792
+ return;
793
+ }
794
+ this._running = false;
795
+ if (this._timerFiber) {
796
+ yield* Fiber.interrupt(this._timerFiber);
797
+ this._timerFiber = void 0;
798
+ }
799
+ this._scheduledTriggers.clear();
800
+ log2.info("TriggerDispatcher stopped", void 0, {
801
+ F: __dxlog_file2,
802
+ L: 200,
803
+ S: this,
804
+ C: (f, a) => f(...a)
805
+ });
806
+ }));
807
+ _define_property4(this, "invokeTrigger", (options2) => Effect5.gen(this, function* () {
808
+ const { trigger, event } = options2;
809
+ log2.info("running trigger", {
810
+ triggerId: trigger.id,
811
+ spec: trigger.spec,
812
+ event
813
+ }, {
814
+ F: __dxlog_file2,
815
+ L: 208,
816
+ S: this,
817
+ C: (f, a) => f(...a)
818
+ });
819
+ const tracer = yield* InvocationTracer;
820
+ const trace = yield* tracer.traceInvocationStart({
821
+ target: trigger.function?.dxn,
822
+ payload: {
823
+ trigger: {
824
+ id: trigger.id,
825
+ // TODO(dmaretskyi): Is `spec` always there>
826
+ kind: trigger.spec.kind
827
+ },
828
+ data: event
829
+ }
830
+ });
831
+ const result = yield* Effect5.gen(this, function* () {
832
+ if (!trigger.enabled) {
833
+ return yield* Effect5.dieMessage("Attempting to invoke disabled trigger");
834
+ }
835
+ if (!trigger.function) {
836
+ return yield* Effect5.dieMessage("Trigger has no function reference");
837
+ }
838
+ const serialiedFunction = yield* DatabaseService.load(trigger.function).pipe(Effect5.orDie);
839
+ invariant(Obj3.instanceOf(FunctionType, serialiedFunction), void 0, {
840
+ F: __dxlog_file2,
841
+ L: 235,
842
+ S: this,
843
+ A: [
844
+ "Obj.instanceOf(FunctionType, serialiedFunction)",
845
+ ""
846
+ ]
847
+ });
848
+ const functionDef = deserializeFunction(serialiedFunction);
849
+ const inputData = this._prepareInputData(trigger, event);
850
+ return yield* LocalFunctionExecutionService.invokeFunction(functionDef, inputData).pipe(Effect5.provide(ComputeEventLogger.layerFromTracing.pipe(Layer4.provideMerge(TracingService.layerQueue(trace.invocationTraceQueue)))));
851
+ }).pipe(Effect5.exit);
852
+ const triggerExecutionResult = {
853
+ triggerId: trigger.id,
854
+ result
855
+ };
856
+ if (Exit.isSuccess(result)) {
857
+ log2.info("trigger execution success", {
858
+ triggerId: trigger.id
859
+ }, {
860
+ F: __dxlog_file2,
861
+ L: 256,
862
+ S: this,
863
+ C: (f, a) => f(...a)
864
+ });
865
+ } else {
866
+ log2.error("trigger execution failure", {
867
+ error: causeToError(result.cause)
868
+ }, {
869
+ F: __dxlog_file2,
870
+ L: 260,
871
+ S: this,
872
+ C: (f, a) => f(...a)
873
+ });
874
+ }
875
+ yield* tracer.traceInvocationEnd({
876
+ trace,
877
+ // TODO(dmaretskyi): Might miss errors.
878
+ exception: Exit.isFailure(result) ? Cause.prettyErrors(result.cause)[0] : void 0
879
+ });
880
+ return triggerExecutionResult;
881
+ }));
882
+ _define_property4(this, "invokeScheduledTriggers", ({ kinds = [
883
+ "timer",
884
+ "queue",
885
+ "subscription"
886
+ ] } = {}) => Effect5.gen(this, function* () {
887
+ const invocations = [];
888
+ for (const kind of kinds) {
889
+ switch (kind) {
890
+ case "timer":
891
+ {
892
+ yield* this.refreshTriggers();
893
+ const now = this.getCurrentTime();
894
+ const triggersToInvoke = [];
895
+ for (const [triggerId, scheduledTrigger] of this._scheduledTriggers.entries()) {
896
+ if (scheduledTrigger.nextExecution <= now) {
897
+ triggersToInvoke.push(scheduledTrigger.trigger);
898
+ scheduledTrigger.nextExecution = Cron.next(scheduledTrigger.cron, now);
899
+ }
900
+ }
901
+ invocations.push(...yield* Effect5.forEach(triggersToInvoke, (trigger) => this.invokeTrigger({
902
+ trigger,
903
+ event: {
904
+ tick: now.getTime()
905
+ }
906
+ }), {
907
+ concurrency: 1
908
+ }));
909
+ }
910
+ break;
911
+ case "queue": {
912
+ const triggers = yield* this._fetchTriggers();
913
+ for (const trigger of triggers) {
914
+ const spec = trigger.spec;
915
+ if (spec?.kind !== "queue") {
916
+ continue;
917
+ }
918
+ const cursor = Obj3.getKeys(trigger, KEY_QUEUE_CURSOR).at(0)?.id;
919
+ const queue = yield* QueueService.getQueue(DXN3.parse(spec.queue));
920
+ const objects = yield* Effect5.promise(() => queue.queryObjects());
921
+ for (const object of objects) {
922
+ const objectPos = Obj3.getKeys(object, KEY_QUEUE_POSITION).at(0)?.id;
923
+ if (!objectPos || cursor && parseInt(cursor) >= parseInt(objectPos)) {
924
+ continue;
925
+ }
926
+ invocations.push(yield* this.invokeTrigger({
927
+ trigger,
928
+ event: {
929
+ queue: spec.queue,
930
+ item: object,
931
+ cursor: objectPos
932
+ }
933
+ }));
934
+ Obj3.deleteKeys(trigger, KEY_QUEUE_CURSOR);
935
+ Obj3.getMeta(trigger).keys.push({
936
+ source: KEY_QUEUE_CURSOR,
937
+ id: objectPos
938
+ });
939
+ yield* DatabaseService.flush();
940
+ break;
941
+ }
942
+ }
943
+ break;
944
+ }
945
+ case "subscription": {
946
+ const triggers = yield* this._fetchTriggers();
947
+ for (const trigger of triggers) {
948
+ const spec = Obj3.getSnapshot(trigger).spec;
949
+ if (spec?.kind !== "subscription") {
950
+ continue;
951
+ }
952
+ const { objects } = yield* DatabaseService.runQuery(Query.fromAst(spec.query));
953
+ const state = yield* TriggerStateStore.getState(trigger.id).pipe(Effect5.catchTag("TRIGGER_STATE_NOT_FOUND", () => Effect5.succeed({
954
+ version: "1",
955
+ triggerId: trigger.id,
956
+ state: {
957
+ _tag: "subscription",
958
+ processedVersions: {}
959
+ }
960
+ })));
961
+ invariant(state.state?._tag === "subscription", void 0, {
962
+ F: __dxlog_file2,
963
+ L: 373,
964
+ S: this,
965
+ A: [
966
+ "state.state?._tag === 'subscription'",
967
+ ""
968
+ ]
969
+ });
970
+ let updated = false;
971
+ for (const object of objects) {
972
+ const existingVersion = Record.get(state.state.processedVersions, object.id).pipe(Option2.map(Obj3.decodeVersion));
973
+ const currentVersion = Obj3.version(object);
974
+ const run = Option2.isNone(existingVersion) || Obj3.compareVersions(currentVersion, existingVersion.value) === "different";
975
+ if (!run) {
976
+ continue;
977
+ }
978
+ invocations.push(yield* this.invokeTrigger({
979
+ trigger,
980
+ event: {
981
+ // TODO(dmaretskyi): Change type not supported.
982
+ type: "unknown",
983
+ changedObjectId: object.id
984
+ }
985
+ }));
986
+ state.state.processedVersions[object.id] = Obj3.encodeVersion(currentVersion);
987
+ updated = true;
988
+ }
989
+ if (updated) {
990
+ yield* TriggerStateStore.saveState(state);
991
+ }
992
+ }
993
+ break;
994
+ }
995
+ default: {
996
+ return yield* Effect5.dieMessage(`Unknown trigger kind: ${kind}`);
997
+ }
998
+ }
999
+ }
1000
+ return invocations;
1001
+ }));
1002
+ _define_property4(this, "advanceTime", (duration) => Effect5.gen(this, function* () {
1003
+ if (this.timeControl !== "manual") {
1004
+ return yield* Effect5.dieMessage("advanceTime can only be used in manual time control mode");
1005
+ }
1006
+ const millis = Duration.toMillis(duration);
1007
+ this._internalTime = new Date(this._internalTime.getTime() + millis);
1008
+ log2("Advanced internal time", {
1009
+ newTime: this._internalTime,
1010
+ advancedBy: Duration.format(duration)
1011
+ }, {
1012
+ F: __dxlog_file2,
1013
+ L: 426,
1014
+ S: this,
1015
+ C: (f, a) => f(...a)
1016
+ });
1017
+ }).pipe(Effect5.orDie));
1018
+ _define_property4(this, "getCurrentTime", () => {
1019
+ if (this.timeControl === "natural") {
1020
+ return /* @__PURE__ */ new Date();
1021
+ } else {
1022
+ return new Date(this._internalTime);
1023
+ }
1024
+ });
1025
+ _define_property4(this, "refreshTriggers", () => Effect5.gen(this, function* () {
1026
+ const triggers = yield* this._fetchTriggers();
1027
+ const currentTriggerIds = new Set(triggers.map((t) => t.id));
1028
+ for (const triggerId of this._scheduledTriggers.keys()) {
1029
+ if (!currentTriggerIds.has(triggerId)) {
1030
+ this._scheduledTriggers.delete(triggerId);
1031
+ }
1032
+ }
1033
+ for (const trigger of triggers) {
1034
+ if (trigger.spec?.kind === "timer" && trigger.enabled) {
1035
+ const timerSpec = trigger.spec;
1036
+ const cronEither = Cron.parse(timerSpec.cron);
1037
+ if (Either.isRight(cronEither)) {
1038
+ const cron = cronEither.right;
1039
+ const existing = this._scheduledTriggers.get(trigger.id);
1040
+ const now = this.getCurrentTime();
1041
+ const nextExecution = existing?.nextExecution ?? Cron.next(cron, now);
1042
+ log2("Updated scheduled trigger", {
1043
+ triggerId: trigger.id,
1044
+ cron: timerSpec.cron,
1045
+ nextExecution,
1046
+ now
1047
+ }, {
1048
+ F: __dxlog_file2,
1049
+ L: 466,
1050
+ S: this,
1051
+ C: (f, a) => f(...a)
1052
+ });
1053
+ this._scheduledTriggers.set(trigger.id, {
1054
+ trigger,
1055
+ cron,
1056
+ nextExecution
1057
+ });
1058
+ } else {
1059
+ log2.error("Invalid cron expression", {
1060
+ triggerId: trigger.id,
1061
+ cron: timerSpec.cron,
1062
+ error: cronEither.left.message
1063
+ }, {
1064
+ F: __dxlog_file2,
1065
+ L: 478,
1066
+ S: this,
1067
+ C: (f, a) => f(...a)
1068
+ });
1069
+ }
1070
+ }
1071
+ }
1072
+ log2("Updated scheduled triggers", {
1073
+ count: this._scheduledTriggers.size
1074
+ }, {
1075
+ F: __dxlog_file2,
1076
+ L: 487,
1077
+ S: this,
1078
+ C: (f, a) => f(...a)
1079
+ });
1080
+ }).pipe(Effect5.withSpan("TriggerDispatcher.refreshTriggers")));
1081
+ _define_property4(this, "_fetchTriggers", () => Effect5.gen(this, function* () {
1082
+ const { objects } = yield* DatabaseService.runQuery(Filter.type(FunctionTrigger));
1083
+ return objects;
1084
+ }).pipe(Effect5.withSpan("TriggerDispatcher.fetchTriggers")));
1085
+ _define_property4(this, "_startNaturalTimeProcessing", () => Effect5.gen(this, function* () {
1086
+ yield* this.invokeScheduledTriggers();
1087
+ }).pipe(Effect5.repeat(Schedule.fixed(this.livePollInterval)), Effect5.asVoid));
1088
+ _define_property4(this, "_prepareInputData", (trigger, event) => {
1089
+ return createInvocationPayload(trigger, event);
1090
+ });
1091
+ this.timeControl = options.timeControl;
1092
+ this.livePollInterval = options.livePollInterval ?? Duration.seconds(1);
1093
+ this._internalTime = options.startingTime ?? /* @__PURE__ */ new Date();
1094
+ }
1095
+ };
1096
+ var KEY_QUEUE_CURSOR = "dxos.org/key/local-trigger-dispatcher/queue-cursor";
410
1097
 
411
- // packages/core/functions/src/executor/executor.ts
412
- import { Effect, Schema as Schema5 } from "effect";
413
- var FunctionExecutor = class {
414
- constructor(_services) {
415
- this._services = _services;
1098
+ // src/executor/executor.ts
1099
+ import { Effect as Effect6, Schema as Schema7 } from "effect";
1100
+ import { runAndForwardErrors } from "@dxos/effect";
1101
+ function _define_property5(obj, key, value) {
1102
+ if (key in obj) {
1103
+ Object.defineProperty(obj, key, {
1104
+ value,
1105
+ enumerable: true,
1106
+ configurable: true,
1107
+ writable: true
1108
+ });
1109
+ } else {
1110
+ obj[key] = value;
416
1111
  }
1112
+ return obj;
1113
+ }
1114
+ var FunctionExecutor = class {
1115
+ /**
1116
+ * Invoke function.
1117
+ */
417
1118
  // TODO(dmaretskyi): Invocation context: queue, space, etc...
418
- async invoke(fnDef, input) {
419
- const assertInput = fnDef.inputSchema.pipe(Schema5.asserts);
1119
+ async invoke(functionDef, input) {
1120
+ const assertInput = functionDef.inputSchema.pipe(Schema7.asserts);
420
1121
  assertInput(input);
421
1122
  const context = {
1123
+ space: void 0,
422
1124
  getService: this._services.getService.bind(this._services),
423
1125
  getSpace: async (_spaceId) => {
424
1126
  throw new Error("Not available. Use the database service instead.");
425
- },
426
- space: void 0,
427
- get ai() {
428
- throw new Error("Not available. Use the ai service instead.");
429
1127
  }
430
1128
  };
431
- const result = await fnDef.handler({
1129
+ const result = functionDef.handler({
432
1130
  context,
433
1131
  data: input
434
1132
  });
435
- const assertOutput = fnDef.outputSchema?.pipe(Schema5.asserts);
436
- assertOutput(result);
437
- if (Effect.isEffect(result)) {
438
- return Effect.runPromise(result);
1133
+ let data;
1134
+ if (Effect6.isEffect(result)) {
1135
+ data = await result.pipe(Effect6.provide(this._services.createLayer()), runAndForwardErrors);
1136
+ } else {
1137
+ data = await result;
439
1138
  }
440
- return result;
1139
+ const assertOutput = functionDef.outputSchema?.pipe(Schema7.asserts);
1140
+ assertOutput(data);
1141
+ return data;
1142
+ }
1143
+ constructor(_services) {
1144
+ _define_property5(this, "_services", void 0);
1145
+ this._services = _services;
441
1146
  }
442
1147
  };
1148
+
1149
+ // src/examples/index.ts
1150
+ var examples_exports = {};
1151
+ __export(examples_exports, {
1152
+ fib: () => fib_default,
1153
+ reply: () => reply_default,
1154
+ sleep: () => sleep_default
1155
+ });
1156
+
1157
+ // src/examples/fib.ts
1158
+ import { Effect as Effect7, Schema as Schema8 } from "effect";
1159
+ var fib_default = defineFunction({
1160
+ name: "example.org/function/fib",
1161
+ description: "Function that calculates a Fibonacci number",
1162
+ inputSchema: Schema8.Struct({
1163
+ iterations: Schema8.optional(Schema8.Number).annotations({
1164
+ description: "Number of iterations",
1165
+ default: 1e5
1166
+ })
1167
+ }),
1168
+ outputSchema: Schema8.Struct({
1169
+ result: Schema8.String
1170
+ }),
1171
+ handler: Effect7.fn(function* ({ data: { iterations = 1e5 } }) {
1172
+ let a = 0n;
1173
+ let b = 1n;
1174
+ for (let i = 0; i < iterations; i++) {
1175
+ a += b;
1176
+ b = a - b;
1177
+ }
1178
+ return {
1179
+ result: a.toString()
1180
+ };
1181
+ })
1182
+ });
1183
+
1184
+ // src/examples/reply.ts
1185
+ import { Console, Effect as Effect8, Schema as Schema9 } from "effect";
1186
+ var reply_default = defineFunction({
1187
+ name: "example.org/function/reply",
1188
+ description: "Function that echoes the input",
1189
+ inputSchema: Schema9.Any,
1190
+ outputSchema: Schema9.Any,
1191
+ handler: Effect8.fn(function* ({ data }) {
1192
+ yield* Console.log("reply", {
1193
+ data
1194
+ });
1195
+ return data;
1196
+ })
1197
+ });
1198
+
1199
+ // src/examples/sleep.ts
1200
+ import { Effect as Effect9, Schema as Schema10 } from "effect";
1201
+ var sleep_default = defineFunction({
1202
+ name: "example.org/function/sleep",
1203
+ description: "Function that sleeps for a given amount of time",
1204
+ inputSchema: Schema10.Struct({
1205
+ duration: Schema10.optional(Schema10.Number).annotations({
1206
+ description: "Milliseconds to sleep",
1207
+ default: 1e5
1208
+ })
1209
+ }),
1210
+ outputSchema: Schema10.Void,
1211
+ handler: Effect9.fn(function* ({ data: { duration = 1e5 } }) {
1212
+ yield* Effect9.sleep(duration);
1213
+ })
1214
+ });
443
1215
  export {
444
- AiService,
1216
+ ComputeEvent,
1217
+ ComputeEventLogger,
1218
+ ComputeEventPayload,
445
1219
  ConfiguredCredentialsService,
1220
+ ContextQueueService,
446
1221
  CredentialsService,
447
1222
  DatabaseService,
448
1223
  EmailTriggerOutput,
449
- EventLogger,
1224
+ FUNCTIONS_META_KEY,
450
1225
  FUNCTIONS_PRESET_META_KEY,
451
1226
  FUNCTION_TYPES,
452
- FunctionCallService,
1227
+ FunctionDefinition,
1228
+ FunctionError,
453
1229
  FunctionExecutor,
1230
+ FunctionImplementationResolver,
454
1231
  FunctionManifestSchema,
1232
+ FunctionNotFoundError,
455
1233
  FunctionTrigger,
456
- FunctionTriggerSchema,
457
1234
  FunctionType,
458
1235
  InvocationOutcome,
459
1236
  InvocationTraceEndEvent,
460
1237
  InvocationTraceEventType,
461
1238
  InvocationTraceStartEvent,
1239
+ InvocationTracer,
1240
+ LocalFunctionExecutionService,
1241
+ MESSAGE_PROPERTY_TOOL_CALL_ID,
462
1242
  QueueService,
463
1243
  QueueTriggerOutput,
1244
+ RemoteFunctionExecutionService,
464
1245
  SERVICE_TAGS,
465
1246
  ScriptType,
466
1247
  ServiceContainer,
1248
+ ServiceNotAvailableError,
467
1249
  SubscriptionTriggerOutput,
468
1250
  TimerTriggerOutput,
469
1251
  TraceEvent,
470
1252
  TraceEventException,
471
1253
  TraceEventLog,
472
1254
  TracingService,
473
- TriggerKind,
1255
+ TriggerDispatcher,
1256
+ TriggerKinds,
474
1257
  TriggerSchema,
1258
+ TriggerState,
1259
+ TriggerStateNotFoundError,
1260
+ TriggerStateStore,
475
1261
  WebhookTriggerOutput,
476
1262
  createDefectLogger,
477
1263
  createEventLogger,
478
1264
  createInvocationSpans,
479
1265
  defineFunction,
1266
+ deserializeFunction,
1267
+ examples_exports as exampleFunctions,
480
1268
  getInvocationUrl,
481
- getUserFunctionUrlInMetadata,
1269
+ getUserFunctionIdInMetadata,
482
1270
  logCustomEvent,
483
- makeFunctionUrl,
484
- setUserFunctionUrlInMetadata
1271
+ serializeFunction,
1272
+ setUserFunctionIdInMetadata,
1273
+ withAuthorization
485
1274
  };
486
1275
  //# sourceMappingURL=index.mjs.map