@dxos/functions 0.8.1 → 0.8.2-main.10c050d

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 (204) hide show
  1. package/dist/lib/browser/bundler/index.mjs +0 -3
  2. package/dist/lib/browser/bundler/index.mjs.map +3 -3
  3. package/dist/lib/browser/edge/index.mjs +63 -7
  4. package/dist/lib/browser/edge/index.mjs.map +4 -4
  5. package/dist/lib/browser/index.mjs +513 -100
  6. package/dist/lib/browser/index.mjs.map +4 -4
  7. package/dist/lib/browser/meta.json +1 -1
  8. package/dist/lib/node/bundler/index.cjs +0 -1
  9. package/dist/lib/node/bundler/index.cjs.map +3 -3
  10. package/dist/lib/node/edge/index.cjs +65 -5
  11. package/dist/lib/node/edge/index.cjs.map +4 -4
  12. package/dist/lib/node/index.cjs +519 -92
  13. package/dist/lib/node/index.cjs.map +4 -4
  14. package/dist/lib/node/meta.json +1 -1
  15. package/dist/lib/node-esm/bundler/index.mjs +0 -1
  16. package/dist/lib/node-esm/bundler/index.mjs.map +3 -3
  17. package/dist/lib/node-esm/edge/index.mjs +64 -6
  18. package/dist/lib/node-esm/edge/index.mjs.map +4 -4
  19. package/dist/lib/node-esm/index.mjs +513 -98
  20. package/dist/lib/node-esm/index.mjs.map +4 -4
  21. package/dist/lib/node-esm/meta.json +1 -1
  22. package/dist/types/src/bundler/bundler.d.ts.map +1 -1
  23. package/dist/types/src/edge/functions.d.ts +3 -3
  24. package/dist/types/src/edge/functions.d.ts.map +1 -1
  25. package/dist/types/src/edge/index.d.ts.map +1 -1
  26. package/dist/types/src/executor/executor.d.ts +8 -0
  27. package/dist/types/src/executor/executor.d.ts.map +1 -0
  28. package/dist/types/src/executor/index.d.ts +2 -0
  29. package/dist/types/src/executor/index.d.ts.map +1 -0
  30. package/dist/types/src/handler.d.ts +23 -67
  31. package/dist/types/src/handler.d.ts.map +1 -1
  32. package/dist/types/src/index.d.ts +5 -3
  33. package/dist/types/src/index.d.ts.map +1 -1
  34. package/dist/types/src/schema.d.ts +57 -0
  35. package/dist/types/src/schema.d.ts.map +1 -0
  36. package/dist/types/src/services/ai.d.ts +9 -0
  37. package/dist/types/src/services/ai.d.ts.map +1 -0
  38. package/dist/types/src/services/credentials.d.ts +30 -0
  39. package/dist/types/src/services/credentials.d.ts.map +1 -0
  40. package/dist/types/src/services/database.d.ts +9 -0
  41. package/dist/types/src/services/database.d.ts.map +1 -0
  42. package/dist/types/src/services/index.d.ts +7 -0
  43. package/dist/types/src/services/index.d.ts.map +1 -0
  44. package/dist/types/src/services/queues.d.ts +10 -0
  45. package/dist/types/src/services/queues.d.ts.map +1 -0
  46. package/dist/types/src/services/service-container.d.ts +25 -0
  47. package/dist/types/src/services/service-container.d.ts.map +1 -0
  48. package/dist/types/src/services/tracing.d.ts +15 -0
  49. package/dist/types/src/services/tracing.d.ts.map +1 -0
  50. package/dist/types/src/trace.d.ts +149 -0
  51. package/dist/types/src/trace.d.ts.map +1 -0
  52. package/dist/types/src/translations.d.ts +2 -1
  53. package/dist/types/src/translations.d.ts.map +1 -1
  54. package/dist/types/src/types.d.ts +407 -0
  55. package/dist/types/src/types.d.ts.map +1 -0
  56. package/dist/types/src/{types/url.d.ts → url.d.ts} +6 -0
  57. package/dist/types/src/url.d.ts.map +1 -0
  58. package/dist/types/tsconfig.tsbuildinfo +1 -1
  59. package/package.json +21 -36
  60. package/src/bundler/bundler.ts +7 -1
  61. package/src/edge/functions.ts +7 -4
  62. package/src/edge/index.ts +4 -0
  63. package/src/executor/executor.ts +47 -0
  64. package/src/executor/index.ts +5 -0
  65. package/src/handler.ts +29 -125
  66. package/src/index.ts +8 -5
  67. package/src/schema.ts +52 -0
  68. package/src/services/ai.ts +15 -0
  69. package/src/services/credentials.ts +55 -0
  70. package/src/services/database.ts +14 -0
  71. package/src/services/index.ts +10 -0
  72. package/src/services/queues.ts +16 -0
  73. package/src/services/service-container.ts +58 -0
  74. package/src/services/tracing.ts +27 -0
  75. package/src/{types/trace.ts → trace.ts} +37 -35
  76. package/src/translations.ts +1 -1
  77. package/src/types.ts +211 -0
  78. package/src/{types/url.ts → url.ts} +5 -0
  79. package/dist/lib/browser/chunk-HI7YZO2K.mjs +0 -482
  80. package/dist/lib/browser/chunk-HI7YZO2K.mjs.map +0 -7
  81. package/dist/lib/browser/chunk-LT4LR4VU.mjs +0 -72
  82. package/dist/lib/browser/chunk-LT4LR4VU.mjs.map +0 -7
  83. package/dist/lib/browser/chunk-RVSG6WTL.mjs +0 -358
  84. package/dist/lib/browser/chunk-RVSG6WTL.mjs.map +0 -7
  85. package/dist/lib/browser/chunk-XRCXIG74.mjs +0 -12
  86. package/dist/lib/browser/chunk-XRCXIG74.mjs.map +0 -7
  87. package/dist/lib/browser/testing/index.mjs +0 -670
  88. package/dist/lib/browser/testing/index.mjs.map +0 -7
  89. package/dist/lib/browser/types/index.mjs +0 -49
  90. package/dist/lib/browser/types/index.mjs.map +0 -7
  91. package/dist/lib/node/chunk-DSUGRAAL.cjs +0 -392
  92. package/dist/lib/node/chunk-DSUGRAAL.cjs.map +0 -7
  93. package/dist/lib/node/chunk-JEQ2X3Z6.cjs +0 -34
  94. package/dist/lib/node/chunk-JEQ2X3Z6.cjs.map +0 -7
  95. package/dist/lib/node/chunk-NXZNXVT3.cjs +0 -94
  96. package/dist/lib/node/chunk-NXZNXVT3.cjs.map +0 -7
  97. package/dist/lib/node/chunk-RXMCVAMJ.cjs +0 -496
  98. package/dist/lib/node/chunk-RXMCVAMJ.cjs.map +0 -7
  99. package/dist/lib/node/testing/index.cjs +0 -687
  100. package/dist/lib/node/testing/index.cjs.map +0 -7
  101. package/dist/lib/node/types/index.cjs +0 -70
  102. package/dist/lib/node/types/index.cjs.map +0 -7
  103. package/dist/lib/node-esm/chunk-DHGBFXSZ.mjs +0 -12
  104. package/dist/lib/node-esm/chunk-DHGBFXSZ.mjs.map +0 -7
  105. package/dist/lib/node-esm/chunk-HBD2FZXO.mjs +0 -358
  106. package/dist/lib/node-esm/chunk-HBD2FZXO.mjs.map +0 -7
  107. package/dist/lib/node-esm/chunk-O2SXVYU5.mjs +0 -72
  108. package/dist/lib/node-esm/chunk-O2SXVYU5.mjs.map +0 -7
  109. package/dist/lib/node-esm/chunk-SQSJO5HI.mjs +0 -482
  110. package/dist/lib/node-esm/chunk-SQSJO5HI.mjs.map +0 -7
  111. package/dist/lib/node-esm/testing/index.mjs +0 -670
  112. package/dist/lib/node-esm/testing/index.mjs.map +0 -7
  113. package/dist/lib/node-esm/types/index.mjs +0 -49
  114. package/dist/lib/node-esm/types/index.mjs.map +0 -7
  115. package/dist/types/src/browser/index.d.ts +0 -2
  116. package/dist/types/src/browser/index.d.ts.map +0 -1
  117. package/dist/types/src/function/function-registry.d.ts +0 -25
  118. package/dist/types/src/function/function-registry.d.ts.map +0 -1
  119. package/dist/types/src/function/function-registry.test.d.ts +0 -2
  120. package/dist/types/src/function/function-registry.test.d.ts.map +0 -1
  121. package/dist/types/src/function/index.d.ts +0 -2
  122. package/dist/types/src/function/index.d.ts.map +0 -1
  123. package/dist/types/src/runtime/dev-server.d.ts +0 -52
  124. package/dist/types/src/runtime/dev-server.d.ts.map +0 -1
  125. package/dist/types/src/runtime/dev-server.test.d.ts +0 -2
  126. package/dist/types/src/runtime/dev-server.test.d.ts.map +0 -1
  127. package/dist/types/src/runtime/index.d.ts +0 -3
  128. package/dist/types/src/runtime/index.d.ts.map +0 -1
  129. package/dist/types/src/runtime/scheduler.d.ts +0 -34
  130. package/dist/types/src/runtime/scheduler.d.ts.map +0 -1
  131. package/dist/types/src/runtime/scheduler.test.d.ts +0 -2
  132. package/dist/types/src/runtime/scheduler.test.d.ts.map +0 -1
  133. package/dist/types/src/testing/functions-integration.test.d.ts +0 -2
  134. package/dist/types/src/testing/functions-integration.test.d.ts.map +0 -1
  135. package/dist/types/src/testing/index.d.ts +0 -5
  136. package/dist/types/src/testing/index.d.ts.map +0 -1
  137. package/dist/types/src/testing/manifest.d.ts +0 -3
  138. package/dist/types/src/testing/manifest.d.ts.map +0 -1
  139. package/dist/types/src/testing/plugin-init.d.ts +0 -6
  140. package/dist/types/src/testing/plugin-init.d.ts.map +0 -1
  141. package/dist/types/src/testing/setup.d.ts +0 -15
  142. package/dist/types/src/testing/setup.d.ts.map +0 -1
  143. package/dist/types/src/testing/test/handler.d.ts +0 -4
  144. package/dist/types/src/testing/test/handler.d.ts.map +0 -1
  145. package/dist/types/src/testing/test/index.d.ts +0 -3
  146. package/dist/types/src/testing/test/index.d.ts.map +0 -1
  147. package/dist/types/src/testing/types.d.ts +0 -10
  148. package/dist/types/src/testing/types.d.ts.map +0 -1
  149. package/dist/types/src/testing/util.d.ts +0 -5
  150. package/dist/types/src/testing/util.d.ts.map +0 -1
  151. package/dist/types/src/trigger/index.d.ts +0 -3
  152. package/dist/types/src/trigger/index.d.ts.map +0 -1
  153. package/dist/types/src/trigger/trigger-registry.d.ts +0 -38
  154. package/dist/types/src/trigger/trigger-registry.d.ts.map +0 -1
  155. package/dist/types/src/trigger/trigger-registry.test.d.ts +0 -2
  156. package/dist/types/src/trigger/trigger-registry.test.d.ts.map +0 -1
  157. package/dist/types/src/trigger/type/index.d.ts +0 -3
  158. package/dist/types/src/trigger/type/index.d.ts.map +0 -1
  159. package/dist/types/src/trigger/type/subscription-trigger.d.ts +0 -4
  160. package/dist/types/src/trigger/type/subscription-trigger.d.ts.map +0 -1
  161. package/dist/types/src/trigger/type/timer-trigger.d.ts +0 -4
  162. package/dist/types/src/trigger/type/timer-trigger.d.ts.map +0 -1
  163. package/dist/types/src/trigger/type/webhook-trigger.d.ts +0 -4
  164. package/dist/types/src/trigger/type/webhook-trigger.d.ts.map +0 -1
  165. package/dist/types/src/types/index.d.ts +0 -5
  166. package/dist/types/src/types/index.d.ts.map +0 -1
  167. package/dist/types/src/types/schema.d.ts +0 -53
  168. package/dist/types/src/types/schema.d.ts.map +0 -1
  169. package/dist/types/src/types/trace.d.ts +0 -146
  170. package/dist/types/src/types/trace.d.ts.map +0 -1
  171. package/dist/types/src/types/types.d.ts +0 -265
  172. package/dist/types/src/types/types.d.ts.map +0 -1
  173. package/dist/types/src/types/url.d.ts.map +0 -1
  174. package/dist/types/tools/schema.d.ts +0 -2
  175. package/dist/types/tools/schema.d.ts.map +0 -1
  176. package/schema/functions.json +0 -211
  177. package/src/browser/index.ts +0 -5
  178. package/src/function/function-registry.test.ts +0 -118
  179. package/src/function/function-registry.ts +0 -104
  180. package/src/function/index.ts +0 -5
  181. package/src/runtime/dev-server.test.ts +0 -79
  182. package/src/runtime/dev-server.ts +0 -240
  183. package/src/runtime/index.ts +0 -6
  184. package/src/runtime/scheduler.test.ts +0 -152
  185. package/src/runtime/scheduler.ts +0 -170
  186. package/src/testing/functions-integration.test.ts +0 -65
  187. package/src/testing/index.ts +0 -8
  188. package/src/testing/manifest.ts +0 -15
  189. package/src/testing/plugin-init.ts +0 -20
  190. package/src/testing/setup.ts +0 -109
  191. package/src/testing/test/handler.ts +0 -15
  192. package/src/testing/test/index.ts +0 -7
  193. package/src/testing/types.ts +0 -9
  194. package/src/testing/util.ts +0 -26
  195. package/src/trigger/index.ts +0 -6
  196. package/src/trigger/trigger-registry.test.ts +0 -278
  197. package/src/trigger/trigger-registry.ts +0 -218
  198. package/src/trigger/type/index.ts +0 -7
  199. package/src/trigger/type/subscription-trigger.ts +0 -84
  200. package/src/trigger/type/timer-trigger.ts +0 -48
  201. package/src/trigger/type/webhook-trigger.ts +0 -48
  202. package/src/types/index.ts +0 -8
  203. package/src/types/schema.ts +0 -46
  204. package/src/types/types.ts +0 -163
package/src/handler.ts CHANGED
@@ -2,17 +2,14 @@
2
2
  // Copyright 2023 DXOS.org
3
3
  //
4
4
 
5
- import { Schema as S } from 'effect';
6
- import { type Effect } from 'effect';
5
+ import { Schema, type Context, type Effect } from 'effect';
7
6
 
8
- import { type Client, PublicKey } from '@dxos/client';
9
- import { type Space, type SpaceId } from '@dxos/client/echo';
10
- import type { CoreDatabase, EchoDatabase, ReactiveEchoObject } from '@dxos/echo-db';
7
+ import { type AIServiceClient } from '@dxos/ai';
8
+ // import { type Space } from '@dxos/client/echo';
9
+ import type { CoreDatabase, EchoDatabase } from '@dxos/echo-db';
11
10
  import { type HasId } from '@dxos/echo-schema';
12
- import { type DXN } from '@dxos/keys';
13
- import { log } from '@dxos/log';
11
+ import { type SpaceId, type DXN } from '@dxos/keys';
14
12
  import { type QueryResult } from '@dxos/protocols';
15
- import { isNonNullable } from '@dxos/util';
16
13
 
17
14
  // TODO(burdon): Model after http request. Ref Lambda/OpenFaaS.
18
15
  // https://docs.aws.amazon.com/lambda/latest/dg/typescript-handler.html
@@ -22,19 +19,30 @@ import { isNonNullable } from '@dxos/util';
22
19
  /**
23
20
  * Function handler.
24
21
  */
25
- export type FunctionHandler<TData = {}, TMeta = {}, TOutput = any> = (params: {
22
+ export type FunctionHandler<TData = {}, TOutput = any> = (params: {
23
+ /**
24
+ * Services and context available to the function.
25
+ */
26
26
  context: FunctionContext;
27
- event: FunctionEvent<TData, TMeta>;
27
+
28
28
  /**
29
- * @deprecated
29
+ * Data passed as the input to the function.
30
+ * Must match the function's input schema.
31
+ * This will be the payload from the trigger or other data passed into the function in a workflow.
30
32
  */
31
- response: FunctionResponse;
33
+ data: TData;
32
34
  }) => TOutput | Promise<TOutput> | Effect.Effect<TOutput, any>;
33
35
 
34
36
  /**
35
37
  * Function context.
36
38
  */
37
39
  export interface FunctionContext {
40
+ /**
41
+ * Resolves a service available to the function.
42
+ * @throws if the service is not available.
43
+ */
44
+ getService: <T extends Context.Tag<any, any>>(tag: T) => Context.Tag.Service<T>;
45
+
38
46
  getSpace: (spaceId: SpaceId) => Promise<SpaceAPI>;
39
47
 
40
48
  /**
@@ -42,18 +50,7 @@ export interface FunctionContext {
42
50
  */
43
51
  space: SpaceAPI | undefined;
44
52
 
45
- ai: FunctionContextAi;
46
-
47
- /**
48
- * @deprecated
49
- */
50
- // TODO(burdon): Limit access to individual space.
51
- client: Client;
52
- /**
53
- * @deprecated
54
- */
55
- // TODO(burdon): Replace with storage service abstraction.
56
- dataDir?: string;
53
+ ai: AIServiceClient;
57
54
  }
58
55
 
59
56
  export interface FunctionContextAi {
@@ -61,28 +58,6 @@ export interface FunctionContextAi {
61
58
  run(model: string, inputs: any, options?: any): Promise<any>;
62
59
  }
63
60
 
64
- /**
65
- * Event payload.
66
- */
67
- // TODO(dmaretskyi): Update type definitions to match the actual payload.
68
- export type FunctionEvent<TData = {}, TMeta = {}> = {
69
- data: FunctionEventMeta<TMeta> & TData;
70
- };
71
-
72
- /**
73
- * Metadata from trigger.
74
- */
75
- export type FunctionEventMeta<TMeta = {}> = {
76
- meta: TMeta;
77
- };
78
-
79
- /**
80
- * Function response.
81
- */
82
- export type FunctionResponse = {
83
- status(code: number): FunctionResponse;
84
- };
85
-
86
61
  //
87
62
  // API.
88
63
  //
@@ -108,28 +83,21 @@ export interface SpaceAPI {
108
83
  get queues(): QueuesAPI;
109
84
  }
110
85
 
111
- // TODO(wittjosiah): Fix this.
86
+ // TODO(wittjosiah): Queues are incompatible.
112
87
  const __assertFunctionSpaceIsCompatibleWithTheClientSpace = () => {
113
88
  // const _: SpaceAPI = {} as Space;
114
89
  };
115
90
 
116
- export type FunctionDefinition = {
91
+ export type FunctionDefinition<T = {}, O = any> = {
117
92
  description?: string;
118
- inputSchema: S.Schema.AnyNoContext;
119
- outputSchema?: S.Schema.AnyNoContext;
120
- handler: FunctionHandler<any>;
121
- };
122
-
123
- export type DefineFunctionParams<T, O = any> = {
124
- description?: string;
125
- inputSchema: S.Schema<T, any>;
126
- outputSchema?: S.Schema<O, any>;
127
- handler: FunctionHandler<T, any, O>;
93
+ inputSchema: Schema.Schema<T, any>;
94
+ outputSchema?: Schema.Schema<O, any>;
95
+ handler: FunctionHandler<T, O>;
128
96
  };
129
97
 
130
98
  // TODO(dmaretskyi): Bind input type to function handler.
131
- export const defineFunction = <T, O>(params: DefineFunctionParams<T, O>): FunctionDefinition => {
132
- if (!S.isSchema(params.inputSchema)) {
99
+ export const defineFunction = <T, O>(params: FunctionDefinition<T, O>): FunctionDefinition<T, O> => {
100
+ if (!Schema.isSchema(params.inputSchema)) {
133
101
  throw new Error('Input schema must be a valid schema');
134
102
  }
135
103
  if (typeof params.handler !== 'function') {
@@ -139,71 +107,7 @@ export const defineFunction = <T, O>(params: DefineFunctionParams<T, O>): Functi
139
107
  return {
140
108
  description: params.description,
141
109
  inputSchema: params.inputSchema,
142
- outputSchema: params.outputSchema ?? S.Any,
110
+ outputSchema: params.outputSchema ?? Schema.Any,
143
111
  handler: params.handler,
144
112
  };
145
113
  };
146
-
147
- //
148
- // Subscription utils.
149
- //
150
-
151
- export type RawSubscriptionData = {
152
- spaceKey?: string;
153
- objects?: string[];
154
- };
155
-
156
- export type SubscriptionData = {
157
- space?: Space;
158
- objects?: ReactiveEchoObject<any>[];
159
- };
160
-
161
- /**
162
- * Handler wrapper for subscription events; extracts space and objects.
163
- *
164
- * To test:
165
- * ```
166
- * curl -s -X POST -H "Content-Type: application/json" --data '{"space": "0446...1cbb"}' http://localhost:7100/dev/email-extractor
167
- * ```
168
- *
169
- * NOTE: Get space key from devtools or `dx space list --json`
170
- */
171
- // TODO(burdon): Evolve into plugin definition like Composer.
172
- export const subscriptionHandler = <TMeta>(
173
- handler: FunctionHandler<SubscriptionData, TMeta>,
174
- types?: S.Schema.AnyNoContext[],
175
- ): FunctionHandler<RawSubscriptionData, TMeta> => {
176
- return async ({ event: { data }, context, response, ...rest }) => {
177
- const { client } = context;
178
- const space = data.spaceKey ? client.spaces.get(PublicKey.from(data.spaceKey)) : undefined;
179
- if (!space) {
180
- log.error('Invalid space');
181
- return response.status(500);
182
- }
183
-
184
- registerTypes(space, types);
185
- const objects = space
186
- ? data.objects
187
- ?.map<ReactiveEchoObject<any> | undefined>((id) => space!.db.getObjectById(id))
188
- .filter(isNonNullable)
189
- : [];
190
-
191
- if (!!data.spaceKey && !space) {
192
- log.warn('invalid space', { data });
193
- } else {
194
- log.info('handler', { space: space?.key.truncate(), objects: objects?.length });
195
- }
196
-
197
- return handler({ event: { data: { ...data, space, objects } }, context, response, ...rest });
198
- };
199
- };
200
-
201
- // TODO(burdon): Evolve types as part of function metadata.
202
- const registerTypes = (space: Space, types: S.Schema.AnyNoContext[] = []) => {
203
- const registry = space.db.graph.schemaRegistry;
204
- for (const type of types) {
205
- if (!registry.hasSchema(type)) {
206
- registry.addSchema([type]);
207
- }
208
- }
209
- };
package/src/index.ts CHANGED
@@ -1,10 +1,13 @@
1
1
  //
2
- // Copyright 2023 DXOS.org
2
+ // Copyright 2024 DXOS.org
3
3
  //
4
4
 
5
- export * from './edge';
6
- export * from './function';
7
5
  export * from './handler';
8
- // export * from './runtime';
9
- export * from './trigger';
6
+ export * from './schema';
7
+ export * from './trace';
10
8
  export * from './types';
9
+ export * from './url';
10
+ export * from './services';
11
+ export * from './executor';
12
+
13
+ // Blow up cache
package/src/schema.ts ADDED
@@ -0,0 +1,52 @@
1
+ //
2
+ // Copyright 2024 DXOS.org
3
+ //
4
+
5
+ import { Schema } from 'effect';
6
+
7
+ import { EchoObject, JsonSchemaType, LabelAnnotation, Ref, TypedObject } from '@dxos/echo-schema';
8
+ import { DataType } from '@dxos/schema';
9
+
10
+ /**
11
+ * Source script.
12
+ */
13
+ export const ScriptType = Schema.Struct({
14
+ name: Schema.optional(Schema.String),
15
+ description: Schema.optional(Schema.String),
16
+ // TODO(burdon): Change to hash of deployed content.
17
+ // Whether source has changed since last deploy.
18
+ changed: Schema.optional(Schema.Boolean),
19
+ source: Ref(DataType.Text),
20
+ }).pipe(
21
+ EchoObject({
22
+ typename: 'dxos.org/type/Script',
23
+ version: '0.1.0',
24
+ }),
25
+ LabelAnnotation.set(['name']),
26
+ );
27
+
28
+ export type ScriptType = Schema.Schema.Type<typeof ScriptType>;
29
+
30
+ /**
31
+ * Function deployment.
32
+ */
33
+ export class FunctionType extends TypedObject({
34
+ typename: 'dxos.org/type/Function',
35
+ version: '0.1.0',
36
+ })({
37
+ // TODO(burdon): Rename to id/uri?
38
+ name: Schema.NonEmptyString,
39
+ version: Schema.String,
40
+
41
+ description: Schema.optional(Schema.String),
42
+
43
+ // Reference to a source script if it exists within ECHO.
44
+ // TODO(burdon): Don't ref ScriptType directly (core).
45
+ source: Schema.optional(Ref(ScriptType)),
46
+
47
+ inputSchema: Schema.optional(JsonSchemaType),
48
+ outputSchema: Schema.optional(JsonSchemaType),
49
+
50
+ // Local binding to a function name.
51
+ binding: Schema.optional(Schema.String),
52
+ }) {}
@@ -0,0 +1,15 @@
1
+ //
2
+ // Copyright 2025 DXOS.org
3
+ //
4
+
5
+ import { Context } from 'effect';
6
+
7
+ import type { AIServiceClient } from '@dxos/ai';
8
+
9
+ // TODO(burdon): Move to @dxos/ai.
10
+ export class AiService extends Context.Tag('AiService')<
11
+ AiService,
12
+ {
13
+ readonly client: AIServiceClient;
14
+ }
15
+ >() {}
@@ -0,0 +1,55 @@
1
+ //
2
+ // Copyright 2025 DXOS.org
3
+ //
4
+
5
+ import { Context } from 'effect';
6
+
7
+ type CredentialQuery = {
8
+ service?: string;
9
+ };
10
+
11
+ // TODO(dmaretskyi): Unify with other apis.
12
+ // packages/sdk/schema/src/common/access-token.ts
13
+ type ServiceCredential = {
14
+ service: string;
15
+
16
+ // TODO(dmaretskyi): Build out.
17
+ apiKey?: string;
18
+ };
19
+
20
+ export class CredentialsService extends Context.Tag('CredentialsService')<
21
+ CredentialsService,
22
+ {
23
+ /**
24
+ * Query all.
25
+ */
26
+ queryCredentials: (query: CredentialQuery) => Promise<ServiceCredential[]>;
27
+
28
+ /**
29
+ * Get a single credential.
30
+ * @throws {Error} If no credential is found.
31
+ */
32
+ getCredential: (query: CredentialQuery) => Promise<ServiceCredential>;
33
+ }
34
+ >() {}
35
+
36
+ export class ConfiguredCredentialsService implements Context.Tag.Service<CredentialsService> {
37
+ constructor(private readonly credentials: ServiceCredential[] = []) {}
38
+
39
+ addCredentials(credentials: ServiceCredential[]): ConfiguredCredentialsService {
40
+ this.credentials.push(...credentials);
41
+ return this;
42
+ }
43
+
44
+ async queryCredentials(query: CredentialQuery): Promise<ServiceCredential[]> {
45
+ return this.credentials.filter((credential) => credential.service === query.service);
46
+ }
47
+
48
+ async getCredential(query: CredentialQuery): Promise<ServiceCredential> {
49
+ const credential = this.credentials.find((credential) => credential.service === query.service);
50
+ if (!credential) {
51
+ throw new Error(`Credential not found for service: ${query.service}`);
52
+ }
53
+ return credential;
54
+ }
55
+ }
@@ -0,0 +1,14 @@
1
+ //
2
+ // Copyright 2025 DXOS.org
3
+ //
4
+
5
+ import { Context } from 'effect';
6
+
7
+ import type { EchoDatabase } from '@dxos/echo-db';
8
+
9
+ export class DatabaseService extends Context.Tag('DatabaseService')<
10
+ DatabaseService,
11
+ {
12
+ readonly db: EchoDatabase;
13
+ }
14
+ >() {}
@@ -0,0 +1,10 @@
1
+ //
2
+ // Copyright 2025 DXOS.org
3
+ //
4
+
5
+ export * from './ai';
6
+ export * from './database';
7
+ export * from './queues';
8
+ export * from './service-container';
9
+ export * from './credentials';
10
+ export * from './tracing';
@@ -0,0 +1,16 @@
1
+ //
2
+ // Copyright 2025 DXOS.org
3
+ //
4
+
5
+ import { Context } from 'effect';
6
+
7
+ import type { Queue, QueueFactory } from '@dxos/echo-db';
8
+
9
+ export class QueuesService extends Context.Tag('QueuesService')<
10
+ QueuesService,
11
+ {
12
+ readonly contextQueue: Queue | undefined;
13
+
14
+ readonly queues: QueueFactory;
15
+ }
16
+ >() {}
@@ -0,0 +1,58 @@
1
+ //
2
+ // Copyright 2025 DXOS.org
3
+ //
4
+
5
+ import { type Context } from 'effect';
6
+
7
+ import { AiService } from './ai';
8
+ import { CredentialsService } from './credentials';
9
+ import { DatabaseService } from './database';
10
+ import { QueuesService } from './queues';
11
+ import { TracingService } from './tracing';
12
+
13
+ export interface Services {
14
+ database: Context.Tag.Service<DatabaseService>;
15
+ ai: Context.Tag.Service<AiService>;
16
+ queues: Context.Tag.Service<QueuesService>;
17
+ credentials: Context.Tag.Service<CredentialsService>;
18
+ tracing: Context.Tag.Service<TracingService>;
19
+ }
20
+
21
+ const SERVICE_MAPPING: Record<string, keyof Services> = {
22
+ [DatabaseService.key]: 'database',
23
+ [AiService.key]: 'ai',
24
+ [QueuesService.key]: 'queues',
25
+ [CredentialsService.key]: 'credentials',
26
+ [TracingService.key]: 'tracing',
27
+ };
28
+
29
+ const DEFAULT_SERVICES: Partial<Services> = {
30
+ tracing: TracingService.noop,
31
+ };
32
+
33
+ export class ServiceContainer {
34
+ private _services: Partial<Services> = { ...DEFAULT_SERVICES };
35
+
36
+ /**
37
+ * Set services.
38
+ * @param services - Services to set.
39
+ * @returns The container instance.
40
+ */
41
+ setServices(services: Partial<Services>): this {
42
+ this._services = { ...this._services, ...services };
43
+ return this;
44
+ }
45
+
46
+ getService<T extends Context.Tag<any, any>>(tag: T): Context.Tag.Service<T> {
47
+ const serviceKey = SERVICE_MAPPING[tag.key];
48
+ const service = serviceKey != null ? this._services[serviceKey] : undefined;
49
+ if (!service) {
50
+ throw new Error(`Service not available: ${tag.key}`);
51
+ }
52
+ return service as Context.Tag.Service<T>;
53
+ }
54
+
55
+ clone(): ServiceContainer {
56
+ return new ServiceContainer().setServices({ ...this._services });
57
+ }
58
+ }
@@ -0,0 +1,27 @@
1
+ //
2
+ // Copyright 2025 DXOS.org
3
+ //
4
+
5
+ import { Context } from 'effect';
6
+
7
+ import type { AnyEchoObject } from '@dxos/echo-schema';
8
+
9
+ export class TracingService extends Context.Tag('TracingService')<
10
+ TracingService,
11
+ {
12
+ /**
13
+ * Write an event to the tracing queue.
14
+ * @param event - The event to write. Must be an a typed object.
15
+ */
16
+ write(event: AnyEchoObject): void;
17
+ }
18
+ >() {
19
+ static noop: Context.Tag.Service<TracingService> = { write: () => {} };
20
+
21
+ static console: Context.Tag.Service<TracingService> = {
22
+ write: (event) => {
23
+ // eslint-disable-next-line no-console
24
+ console.log(event);
25
+ },
26
+ };
27
+ }
@@ -2,7 +2,10 @@
2
2
  // Copyright 2025 DXOS.org
3
3
  //
4
4
 
5
- import { EchoObject, Expando, ObjectId, Ref, S } from '@dxos/echo-schema';
5
+ import { Schema } from 'effect';
6
+
7
+ import { Queue } from '@dxos/echo-db';
8
+ import { EchoObject, Expando, ObjectId, Ref } from '@dxos/echo-schema';
6
9
  import { log } from '@dxos/log';
7
10
 
8
11
  import { FunctionTrigger, type FunctionTriggerType } from './types';
@@ -19,20 +22,20 @@ export enum InvocationTraceEventType {
19
22
  END = 'end',
20
23
  }
21
24
 
22
- export const TraceEventException = S.Struct({
23
- timestampMs: S.Number,
24
- message: S.String,
25
- name: S.String,
26
- stack: S.optional(S.String),
25
+ export const TraceEventException = Schema.Struct({
26
+ timestampMs: Schema.Number,
27
+ message: Schema.String,
28
+ name: Schema.String,
29
+ stack: Schema.optional(Schema.String),
27
30
  });
28
- export type TraceEventException = S.Schema.Type<typeof TraceEventException>;
31
+ export type TraceEventException = Schema.Schema.Type<typeof TraceEventException>;
29
32
 
30
- export const InvocationTraceStartEvent = S.Struct({
33
+ export const InvocationTraceStartEvent = Schema.Struct({
31
34
  /**
32
35
  * Queue message id.
33
36
  */
34
37
  id: ObjectId,
35
- type: S.Literal(InvocationTraceEventType.START),
38
+ type: Schema.Literal(InvocationTraceEventType.START),
36
39
  /**
37
40
  * Invocation id, the same for invocation start and end events.
38
41
  */
@@ -40,17 +43,16 @@ export const InvocationTraceStartEvent = S.Struct({
40
43
  /**
41
44
  * Event generation time.
42
45
  */
43
- timestampMs: S.Number,
46
+ timestampMs: Schema.Number,
44
47
  /**
45
48
  * Data passed to function / workflow as an argument.
46
49
  */
47
50
  // TODO(burdon): Input schema?
48
- input: S.Object,
51
+ input: Schema.Object,
49
52
  /**
50
- * Queue DXN for function/workflow invocation events.
53
+ * Queue for function/workflow invocation events.
51
54
  */
52
- // TODO(burdon): Need reference type for queue. vs. string?
53
- invocationTraceQueue: Ref(Expando),
55
+ invocationTraceQueue: Ref(Queue),
54
56
  /**
55
57
  * DXN of the invoked function/workflow.
56
58
  */
@@ -58,17 +60,17 @@ export const InvocationTraceStartEvent = S.Struct({
58
60
  /**
59
61
  * Present for automatic invocations.
60
62
  */
61
- trigger: S.optional(Ref(FunctionTrigger)),
63
+ trigger: Schema.optional(Ref(FunctionTrigger)),
62
64
  }).pipe(EchoObject({ typename: 'dxos.org/type/InvocationTraceStart', version: '0.1.0' }));
63
65
 
64
- export type InvocationTraceStartEvent = S.Schema.Type<typeof InvocationTraceStartEvent>;
66
+ export type InvocationTraceStartEvent = Schema.Schema.Type<typeof InvocationTraceStartEvent>;
65
67
 
66
- export const InvocationTraceEndEvent = S.Struct({
68
+ export const InvocationTraceEndEvent = Schema.Struct({
67
69
  /**
68
70
  * Trace event id.
69
71
  */
70
72
  id: ObjectId,
71
- type: S.Literal(InvocationTraceEventType.END),
73
+ type: Schema.Literal(InvocationTraceEventType.END),
72
74
  /**
73
75
  * Invocation id, will be the same for invocation start and end.
74
76
  */
@@ -77,36 +79,36 @@ export const InvocationTraceEndEvent = S.Struct({
77
79
  * Event generation time.
78
80
  */
79
81
  // TODO(burdon): Remove ms suffix.
80
- timestampMs: S.Number,
81
- outcome: S.Enums(InvocationOutcome),
82
- exception: S.optional(TraceEventException),
82
+ timestampMs: Schema.Number,
83
+ outcome: Schema.Enums(InvocationOutcome),
84
+ exception: Schema.optional(TraceEventException),
83
85
  }).pipe(EchoObject({ typename: 'dxos.org/type/InvocationTraceEnd', version: '0.1.0' }));
84
86
 
85
- export type InvocationTraceEndEvent = S.Schema.Type<typeof InvocationTraceEndEvent>;
87
+ export type InvocationTraceEndEvent = Schema.Schema.Type<typeof InvocationTraceEndEvent>;
86
88
 
87
89
  export type InvocationTraceEvent = InvocationTraceStartEvent | InvocationTraceEndEvent;
88
90
 
89
- export const TraceEventLog = S.Struct({
90
- timestampMs: S.Number,
91
- level: S.String,
92
- message: S.String,
93
- context: S.optional(S.Object),
91
+ export const TraceEventLog = Schema.Struct({
92
+ timestampMs: Schema.Number,
93
+ level: Schema.String,
94
+ message: Schema.String,
95
+ context: Schema.optional(Schema.Object),
94
96
  });
95
97
 
96
- export const TraceEvent = S.Struct({
98
+ export const TraceEvent = Schema.Struct({
97
99
  id: ObjectId,
98
100
  // TODO(burdon): Need enum/numeric result (not string).
99
- outcome: S.String,
100
- truncated: S.Boolean,
101
+ outcome: Schema.String,
102
+ truncated: Schema.Boolean,
101
103
  /**
102
104
  * Time when the event was persisted.
103
105
  */
104
- ingestionTimestampMs: S.Number,
105
- logs: S.Array(TraceEventLog),
106
- exceptions: S.Array(TraceEventException),
106
+ ingestionTimestampMs: Schema.Number,
107
+ logs: Schema.Array(TraceEventLog),
108
+ exceptions: Schema.Array(TraceEventException),
107
109
  }).pipe(EchoObject({ typename: 'dxos.org/type/TraceEvent', version: '0.1.0' }));
108
110
 
109
- export type TraceEvent = S.Schema.Type<typeof TraceEvent>;
111
+ export type TraceEvent = Schema.Schema.Type<typeof TraceEvent>;
110
112
 
111
113
  /**
112
114
  * Deprecated InvocationTrace event format.
@@ -119,7 +121,7 @@ export type InvocationSpan = {
119
121
  outcome: InvocationOutcome;
120
122
  input: object;
121
123
  durationMs: number;
122
- invocationTraceQueue: Ref<Expando>;
124
+ invocationTraceQueue: Ref<Queue>;
123
125
  invocationTarget: Ref<Expando>;
124
126
  trigger?: Ref<FunctionTriggerType>;
125
127
  exception?: TraceEventException;
@@ -2,7 +2,7 @@
2
2
  // Copyright 2023 DXOS.org
3
3
  //
4
4
 
5
- import { ScriptType } from './types';
5
+ import { ScriptType } from './schema';
6
6
 
7
7
  export default [
8
8
  {