@dxos/functions 0.8.4-main.c4373fc → 0.8.4-main.c85a9c8dae

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 (205) hide show
  1. package/README.md +4 -6
  2. package/dist/lib/neutral/index.mjs +1240 -0
  3. package/dist/lib/neutral/index.mjs.map +7 -0
  4. package/dist/lib/neutral/meta.json +1 -0
  5. package/dist/types/src/errors.d.ts +44 -60
  6. package/dist/types/src/errors.d.ts.map +1 -1
  7. package/dist/types/src/{examples → example}/fib.d.ts +1 -1
  8. package/dist/types/src/example/fib.d.ts.map +1 -0
  9. package/dist/types/src/example/forex-effect.d.ts +3 -0
  10. package/dist/types/src/example/forex-effect.d.ts.map +1 -0
  11. package/dist/types/src/example/index.d.ts +12 -0
  12. package/dist/types/src/example/index.d.ts.map +1 -0
  13. package/dist/types/src/{examples → example}/reply.d.ts +1 -1
  14. package/dist/types/src/example/reply.d.ts.map +1 -0
  15. package/dist/types/src/{examples → example}/sleep.d.ts +1 -1
  16. package/dist/types/src/example/sleep.d.ts.map +1 -0
  17. package/dist/types/src/index.d.ts +4 -8
  18. package/dist/types/src/index.d.ts.map +1 -1
  19. package/dist/types/src/operation-compatibility.test.d.ts +2 -0
  20. package/dist/types/src/operation-compatibility.test.d.ts.map +1 -0
  21. package/dist/types/src/protocol/functions-ai-http-client.d.ts +12 -0
  22. package/dist/types/src/protocol/functions-ai-http-client.d.ts.map +1 -0
  23. package/dist/types/src/protocol/index.d.ts +2 -0
  24. package/dist/types/src/protocol/index.d.ts.map +1 -0
  25. package/dist/types/src/protocol/protocol.d.ts +7 -0
  26. package/dist/types/src/protocol/protocol.d.ts.map +1 -0
  27. package/dist/types/src/protocol/protocol.test.d.ts +2 -0
  28. package/dist/types/src/protocol/protocol.test.d.ts.map +1 -0
  29. package/dist/types/src/sdk.d.ts +117 -0
  30. package/dist/types/src/sdk.d.ts.map +1 -0
  31. package/dist/types/src/services/credentials.d.ts +6 -4
  32. package/dist/types/src/services/credentials.d.ts.map +1 -1
  33. package/dist/types/src/services/event-logger.d.ts +33 -27
  34. package/dist/types/src/services/event-logger.d.ts.map +1 -1
  35. package/dist/types/src/services/function-invocation-service.d.ts +7 -19
  36. package/dist/types/src/services/function-invocation-service.d.ts.map +1 -1
  37. package/dist/types/src/services/index.d.ts +2 -4
  38. package/dist/types/src/services/index.d.ts.map +1 -1
  39. package/dist/types/src/services/queues.d.ts +4 -4
  40. package/dist/types/src/services/queues.d.ts.map +1 -1
  41. package/dist/types/src/services/tracing.d.ts +41 -12
  42. package/dist/types/src/services/tracing.d.ts.map +1 -1
  43. package/dist/types/src/types/Function.d.ts +52 -0
  44. package/dist/types/src/types/Function.d.ts.map +1 -0
  45. package/dist/types/src/types/Script.d.ts +21 -0
  46. package/dist/types/src/types/Script.d.ts.map +1 -0
  47. package/dist/types/src/types/Trigger.d.ts +122 -0
  48. package/dist/types/src/types/Trigger.d.ts.map +1 -0
  49. package/dist/types/src/types/TriggerEvent.d.ts +75 -0
  50. package/dist/types/src/types/TriggerEvent.d.ts.map +1 -0
  51. package/dist/types/src/types/index.d.ts +6 -0
  52. package/dist/types/src/types/index.d.ts.map +1 -0
  53. package/dist/types/src/types/url.d.ts +13 -0
  54. package/dist/types/src/types/url.d.ts.map +1 -0
  55. package/dist/types/tsconfig.tsbuildinfo +1 -1
  56. package/package.json +24 -63
  57. package/src/errors.ts +4 -4
  58. package/src/{examples → example}/fib.ts +1 -1
  59. package/src/example/forex-effect.ts +40 -0
  60. package/src/example/index.ts +13 -0
  61. package/src/{examples → example}/reply.ts +1 -1
  62. package/src/{examples → example}/sleep.ts +1 -1
  63. package/src/index.ts +4 -8
  64. package/src/operation-compatibility.test.ts +185 -0
  65. package/src/protocol/functions-ai-http-client.ts +67 -0
  66. package/src/{executor → protocol}/index.ts +1 -1
  67. package/src/protocol/protocol.test.ts +59 -0
  68. package/src/protocol/protocol.ts +258 -0
  69. package/src/sdk.ts +297 -0
  70. package/src/services/credentials.ts +32 -17
  71. package/src/services/event-logger.ts +10 -4
  72. package/src/services/function-invocation-service.ts +23 -70
  73. package/src/services/index.ts +2 -4
  74. package/src/services/queues.ts +5 -7
  75. package/src/services/tracing.ts +68 -44
  76. package/src/types/Function.ts +83 -0
  77. package/src/types/Script.ts +34 -0
  78. package/src/types/Trigger.ts +153 -0
  79. package/src/types/TriggerEvent.ts +62 -0
  80. package/src/types/index.ts +9 -0
  81. package/src/types/url.ts +32 -0
  82. package/dist/lib/browser/bundler/index.mjs +0 -269
  83. package/dist/lib/browser/bundler/index.mjs.map +0 -7
  84. package/dist/lib/browser/chunk-J5LGTIGS.mjs +0 -10
  85. package/dist/lib/browser/chunk-J5LGTIGS.mjs.map +0 -7
  86. package/dist/lib/browser/chunk-LKYT2SAL.mjs +0 -665
  87. package/dist/lib/browser/chunk-LKYT2SAL.mjs.map +0 -7
  88. package/dist/lib/browser/edge/index.mjs +0 -83
  89. package/dist/lib/browser/edge/index.mjs.map +0 -7
  90. package/dist/lib/browser/index.mjs +0 -1395
  91. package/dist/lib/browser/index.mjs.map +0 -7
  92. package/dist/lib/browser/meta.json +0 -1
  93. package/dist/lib/browser/testing/index.mjs +0 -131
  94. package/dist/lib/browser/testing/index.mjs.map +0 -7
  95. package/dist/lib/node-esm/bundler/index.mjs +0 -270
  96. package/dist/lib/node-esm/bundler/index.mjs.map +0 -7
  97. package/dist/lib/node-esm/chunk-HSLMI22Q.mjs +0 -11
  98. package/dist/lib/node-esm/chunk-HSLMI22Q.mjs.map +0 -7
  99. package/dist/lib/node-esm/chunk-NAQIKLZB.mjs +0 -667
  100. package/dist/lib/node-esm/chunk-NAQIKLZB.mjs.map +0 -7
  101. package/dist/lib/node-esm/edge/index.mjs +0 -84
  102. package/dist/lib/node-esm/edge/index.mjs.map +0 -7
  103. package/dist/lib/node-esm/index.mjs +0 -1396
  104. package/dist/lib/node-esm/index.mjs.map +0 -7
  105. package/dist/lib/node-esm/meta.json +0 -1
  106. package/dist/lib/node-esm/testing/index.mjs +0 -132
  107. package/dist/lib/node-esm/testing/index.mjs.map +0 -7
  108. package/dist/types/src/bundler/bundler.d.ts +0 -49
  109. package/dist/types/src/bundler/bundler.d.ts.map +0 -1
  110. package/dist/types/src/bundler/bundler.test.d.ts +0 -2
  111. package/dist/types/src/bundler/bundler.test.d.ts.map +0 -1
  112. package/dist/types/src/bundler/index.d.ts +0 -2
  113. package/dist/types/src/bundler/index.d.ts.map +0 -1
  114. package/dist/types/src/edge/functions.d.ts +0 -17
  115. package/dist/types/src/edge/functions.d.ts.map +0 -1
  116. package/dist/types/src/edge/index.d.ts +0 -2
  117. package/dist/types/src/edge/index.d.ts.map +0 -1
  118. package/dist/types/src/examples/fib.d.ts.map +0 -1
  119. package/dist/types/src/examples/index.d.ts +0 -4
  120. package/dist/types/src/examples/index.d.ts.map +0 -1
  121. package/dist/types/src/examples/reply.d.ts.map +0 -1
  122. package/dist/types/src/examples/sleep.d.ts.map +0 -1
  123. package/dist/types/src/executor/executor.d.ts +0 -14
  124. package/dist/types/src/executor/executor.d.ts.map +0 -1
  125. package/dist/types/src/executor/index.d.ts +0 -2
  126. package/dist/types/src/executor/index.d.ts.map +0 -1
  127. package/dist/types/src/handler.d.ts +0 -109
  128. package/dist/types/src/handler.d.ts.map +0 -1
  129. package/dist/types/src/schema.d.ts +0 -43
  130. package/dist/types/src/schema.d.ts.map +0 -1
  131. package/dist/types/src/services/database.d.ts +0 -67
  132. package/dist/types/src/services/database.d.ts.map +0 -1
  133. package/dist/types/src/services/function-invocation-service.test.d.ts +0 -2
  134. package/dist/types/src/services/function-invocation-service.test.d.ts.map +0 -1
  135. package/dist/types/src/services/local-function-execution.d.ts +0 -34
  136. package/dist/types/src/services/local-function-execution.d.ts.map +0 -1
  137. package/dist/types/src/services/remote-function-execution-service.d.ts +0 -22
  138. package/dist/types/src/services/remote-function-execution-service.d.ts.map +0 -1
  139. package/dist/types/src/services/service-container.d.ts +0 -57
  140. package/dist/types/src/services/service-container.d.ts.map +0 -1
  141. package/dist/types/src/services/service-registry.d.ts +0 -31
  142. package/dist/types/src/services/service-registry.d.ts.map +0 -1
  143. package/dist/types/src/services/service-registry.test.d.ts +0 -2
  144. package/dist/types/src/services/service-registry.test.d.ts.map +0 -1
  145. package/dist/types/src/testing/index.d.ts +0 -3
  146. package/dist/types/src/testing/index.d.ts.map +0 -1
  147. package/dist/types/src/testing/layer.d.ts +0 -18
  148. package/dist/types/src/testing/layer.d.ts.map +0 -1
  149. package/dist/types/src/testing/logger.d.ts +0 -5
  150. package/dist/types/src/testing/logger.d.ts.map +0 -1
  151. package/dist/types/src/testing/persist-database.test.d.ts +0 -2
  152. package/dist/types/src/testing/persist-database.test.d.ts.map +0 -1
  153. package/dist/types/src/testing/services.d.ts +0 -59
  154. package/dist/types/src/testing/services.d.ts.map +0 -1
  155. package/dist/types/src/trace.d.ts +0 -122
  156. package/dist/types/src/trace.d.ts.map +0 -1
  157. package/dist/types/src/translations.d.ts +0 -12
  158. package/dist/types/src/translations.d.ts.map +0 -1
  159. package/dist/types/src/triggers/index.d.ts +0 -4
  160. package/dist/types/src/triggers/index.d.ts.map +0 -1
  161. package/dist/types/src/triggers/input-builder.d.ts +0 -3
  162. package/dist/types/src/triggers/input-builder.d.ts.map +0 -1
  163. package/dist/types/src/triggers/invocation-tracer.d.ts +0 -37
  164. package/dist/types/src/triggers/invocation-tracer.d.ts.map +0 -1
  165. package/dist/types/src/triggers/trigger-dispatcher.d.ts +0 -78
  166. package/dist/types/src/triggers/trigger-dispatcher.d.ts.map +0 -1
  167. package/dist/types/src/triggers/trigger-dispatcher.test.d.ts +0 -2
  168. package/dist/types/src/triggers/trigger-dispatcher.test.d.ts.map +0 -1
  169. package/dist/types/src/triggers/trigger-state-store.d.ts +0 -28
  170. package/dist/types/src/triggers/trigger-state-store.d.ts.map +0 -1
  171. package/dist/types/src/types.d.ts +0 -230
  172. package/dist/types/src/types.d.ts.map +0 -1
  173. package/dist/types/src/url.d.ts +0 -21
  174. package/dist/types/src/url.d.ts.map +0 -1
  175. package/src/bundler/bundler.test.ts +0 -58
  176. package/src/bundler/bundler.ts +0 -295
  177. package/src/bundler/index.ts +0 -5
  178. package/src/edge/functions.ts +0 -67
  179. package/src/edge/index.ts +0 -9
  180. package/src/examples/index.ts +0 -7
  181. package/src/executor/executor.ts +0 -58
  182. package/src/handler.ts +0 -225
  183. package/src/schema.ts +0 -71
  184. package/src/services/database.ts +0 -175
  185. package/src/services/function-invocation-service.test.ts +0 -81
  186. package/src/services/local-function-execution.ts +0 -153
  187. package/src/services/remote-function-execution-service.ts +0 -63
  188. package/src/services/service-container.ts +0 -115
  189. package/src/services/service-registry.test.ts +0 -45
  190. package/src/services/service-registry.ts +0 -63
  191. package/src/testing/index.ts +0 -6
  192. package/src/testing/layer.ts +0 -114
  193. package/src/testing/logger.ts +0 -17
  194. package/src/testing/persist-database.test.ts +0 -87
  195. package/src/testing/services.ts +0 -115
  196. package/src/trace.ts +0 -178
  197. package/src/translations.ts +0 -20
  198. package/src/triggers/index.ts +0 -7
  199. package/src/triggers/input-builder.ts +0 -35
  200. package/src/triggers/invocation-tracer.ts +0 -101
  201. package/src/triggers/trigger-dispatcher.test.ts +0 -665
  202. package/src/triggers/trigger-dispatcher.ts +0 -533
  203. package/src/triggers/trigger-state-store.ts +0 -61
  204. package/src/types.ts +0 -218
  205. package/src/url.ts +0 -55
package/package.json CHANGED
@@ -1,9 +1,13 @@
1
1
  {
2
2
  "name": "@dxos/functions",
3
- "version": "0.8.4-main.c4373fc",
4
- "description": "Functions API and runtime.",
3
+ "version": "0.8.4-main.c85a9c8dae",
4
+ "description": "Functions API.",
5
5
  "homepage": "https://dxos.org",
6
6
  "bugs": "https://github.com/dxos/dxos/issues",
7
+ "repository": {
8
+ "type": "git",
9
+ "url": "https://github.com/dxos/dxos"
10
+ },
7
11
  "license": "MIT",
8
12
  "author": "info@dxos.org",
9
13
  "sideEffects": false,
@@ -12,76 +16,33 @@
12
16
  ".": {
13
17
  "source": "./src/index.ts",
14
18
  "types": "./dist/types/src/index.d.ts",
15
- "browser": "./dist/lib/browser/index.mjs",
16
- "node": "./dist/lib/node-esm/index.mjs"
17
- },
18
- "./bundler": {
19
- "source": "./src/bundler/index.ts",
20
- "types": "./dist/types/src/bundler/index.d.ts",
21
- "browser": "./dist/lib/browser/bundler/index.mjs",
22
- "node": "./dist/lib/node-esm/bundler/index.mjs"
23
- },
24
- "./edge": {
25
- "source": "./src/edge/index.ts",
26
- "types": "./dist/types/src/edge/index.d.ts",
27
- "browser": "./dist/lib/browser/edge/index.mjs",
28
- "node": "./dist/lib/node-esm/edge/index.mjs"
29
- },
30
- "./testing": {
31
- "source": "./src/testing/index.ts",
32
- "types": "./dist/types/src/testing/index.d.ts",
33
- "browser": "./dist/lib/browser/testing/index.mjs",
34
- "node": "./dist/lib/node-esm/testing/index.mjs"
19
+ "default": "./dist/lib/neutral/index.mjs"
35
20
  }
36
21
  },
37
22
  "types": "dist/types/src/index.d.ts",
38
- "typesVersions": {
39
- "*": {
40
- "bundler": [
41
- "dist/types/src/bundler/index.d.ts"
42
- ],
43
- "edge": [
44
- "dist/types/src/edge/index.d.ts"
45
- ]
46
- }
47
- },
48
23
  "files": [
49
24
  "dist",
50
25
  "schema",
51
26
  "src"
52
27
  ],
53
28
  "dependencies": {
54
- "@effect/platform": "0.92.1",
55
- "effect": "3.18.3",
56
- "esbuild-wasm": "^0.16.14",
57
- "i18next": "^24.2.1",
58
- "iso-did": "^1.6.0",
59
- "@dxos/ai": "0.8.4-main.c4373fc",
60
- "@dxos/async": "0.8.4-main.c4373fc",
61
- "@dxos/client": "0.8.4-main.c4373fc",
62
- "@dxos/client-protocol": "0.8.4-main.c4373fc",
63
- "@dxos/context": "0.8.4-main.c4373fc",
64
- "@dxos/crypto": "0.8.4-main.c4373fc",
65
- "@dxos/debug": "0.8.4-main.c4373fc",
66
- "@dxos/echo": "0.8.4-main.c4373fc",
67
- "@dxos/echo-db": "0.8.4-main.c4373fc",
68
- "@dxos/echo-pipeline": "0.8.4-main.c4373fc",
69
- "@dxos/echo-protocol": "0.8.4-main.c4373fc",
70
- "@dxos/edge-client": "0.8.4-main.c4373fc",
71
- "@dxos/effect": "0.8.4-main.c4373fc",
72
- "@dxos/errors": "0.8.4-main.c4373fc",
73
- "@dxos/invariant": "0.8.4-main.c4373fc",
74
- "@dxos/kv-store": "0.8.4-main.c4373fc",
75
- "@dxos/live-object": "0.8.4-main.c4373fc",
76
- "@dxos/keys": "0.8.4-main.c4373fc",
77
- "@dxos/log": "0.8.4-main.c4373fc",
78
- "@dxos/node-std": "0.8.4-main.c4373fc",
79
- "@dxos/protocols": "0.8.4-main.c4373fc",
80
- "@dxos/schema": "0.8.4-main.c4373fc",
81
- "@dxos/util": "0.8.4-main.c4373fc"
82
- },
83
- "devDependencies": {
84
- "@dxos/agent": "0.8.4-main.c4373fc"
29
+ "@effect/ai-anthropic": "0.23.0",
30
+ "@effect/platform": "0.94.4",
31
+ "effect": "3.19.16",
32
+ "@dxos/echo-db": "0.8.4-main.c85a9c8dae",
33
+ "@dxos/echo": "0.8.4-main.c85a9c8dae",
34
+ "@dxos/ai": "0.8.4-main.c85a9c8dae",
35
+ "@dxos/effect": "0.8.4-main.c85a9c8dae",
36
+ "@dxos/errors": "0.8.4-main.c85a9c8dae",
37
+ "@dxos/keys": "0.8.4-main.c85a9c8dae",
38
+ "@dxos/log": "0.8.4-main.c85a9c8dae",
39
+ "@dxos/node-std": "0.8.4-main.c85a9c8dae",
40
+ "@dxos/invariant": "0.8.4-main.c85a9c8dae",
41
+ "@dxos/operation": "0.8.4-main.c85a9c8dae",
42
+ "@dxos/types": "0.8.4-main.c85a9c8dae",
43
+ "@dxos/schema": "0.8.4-main.c85a9c8dae",
44
+ "@dxos/context": "0.8.4-main.c85a9c8dae",
45
+ "@dxos/protocols": "0.8.4-main.c85a9c8dae"
85
46
  },
86
47
  "publishConfig": {
87
48
  "access": "public"
package/src/errors.ts CHANGED
@@ -4,18 +4,18 @@
4
4
 
5
5
  import { BaseError, type BaseErrorOptions } from '@dxos/errors';
6
6
 
7
- export class ServiceNotAvailableError extends BaseError.extend('SERVICE_NOT_AVAILABLE', 'Service not available') {
7
+ export class ServiceNotAvailableError extends BaseError.extend('ServiceNotAvailable', 'Service not available') {
8
8
  constructor(service: string, options?: Omit<BaseErrorOptions, 'context'>) {
9
9
  super({ context: { service }, ...options });
10
10
  }
11
11
  }
12
12
 
13
- export class FunctionNotFoundError extends BaseError.extend('FUNCTION_NOT_FOUND', 'Function not found') {
13
+ export class FunctionNotFoundError extends BaseError.extend('FunctionNotFound', 'Function not found') {
14
14
  constructor(functionKey: string, options?: Omit<BaseErrorOptions, 'context'>) {
15
15
  super({ context: { function: functionKey }, ...options });
16
16
  }
17
17
  }
18
18
 
19
- export class FunctionError extends BaseError.extend('FUNCTION_ERROR', 'Function invocation error') {}
19
+ export class FunctionError extends BaseError.extend('FunctionError', 'Function invocation error') {}
20
20
 
21
- export class TriggerStateNotFoundError extends BaseError.extend('TRIGGER_STATE_NOT_FOUND', 'Trigger state not found') {}
21
+ export class TriggerStateNotFoundError extends BaseError.extend('TriggerStateNotFound', 'Trigger state not found') {}
@@ -5,7 +5,7 @@
5
5
  import * as Effect from 'effect/Effect';
6
6
  import * as Schema from 'effect/Schema';
7
7
 
8
- import { defineFunction } from '../handler';
8
+ import { defineFunction } from '../sdk';
9
9
 
10
10
  export default defineFunction({
11
11
  key: 'example.org/function/fib',
@@ -0,0 +1,40 @@
1
+ //
2
+ // Copyright 2025 DXOS.org
3
+ //
4
+
5
+ // @ts-ignore
6
+ import { S, defineFunction } from 'dxos:functions';
7
+ import {
8
+ FetchHttpClient,
9
+ HttpClient,
10
+ HttpClientRequest,
11
+ // @ts-ignore
12
+ } from 'https://esm.sh/@effect/platform@0.89.0?deps=effect@3.17.0&bundle=false';
13
+ // @ts-ignore
14
+ import { Effect, Schedule } from 'https://esm.sh/effect@3.17.0?bundle=false';
15
+
16
+ export default defineFunction({
17
+ key: 'dxos.org/script/forex-effect',
18
+ name: 'Forex Effect',
19
+ description: 'Returns the exchange rate between two currencies.',
20
+
21
+ inputSchema: S.Struct({
22
+ from: S.String.annotations({ description: 'The source currency' }),
23
+ to: S.String.annotations({ description: 'The target currency' }),
24
+ }),
25
+
26
+ outputSchema: S.String.annotations({ description: 'The exchange rate between the two currencies' }),
27
+
28
+ handler: async ({ data: { from, to } }: any) =>
29
+ Effect.gen(function* () {
30
+ const res = yield* HttpClientRequest.get(`https://free.ratesdb.com/v1/rates?from=${from}&to=${to}`).pipe(
31
+ HttpClient.execute,
32
+ Effect.flatMap((res: any) => res.json),
33
+ Effect.timeout('1 second'),
34
+ Effect.retry(Schedule.exponential(1_000).pipe(Schedule.compose(Schedule.recurs(3)))),
35
+ Effect.scoped,
36
+ );
37
+
38
+ return res.data.rates[to].toString();
39
+ }).pipe(Effect.provide(FetchHttpClient.layer)),
40
+ });
@@ -0,0 +1,13 @@
1
+ //
2
+ // Copyright 2025 DXOS.org
3
+ //
4
+
5
+ import Fibonacci from './fib';
6
+ import Reply from './reply';
7
+ import Sleep from './sleep';
8
+
9
+ export const ExampleFunctions = {
10
+ Fibonacci,
11
+ Reply,
12
+ Sleep,
13
+ };
@@ -6,7 +6,7 @@ import * as Console from 'effect/Console';
6
6
  import * as Effect from 'effect/Effect';
7
7
  import * as Schema from 'effect/Schema';
8
8
 
9
- import { defineFunction } from '../handler';
9
+ import { defineFunction } from '../sdk';
10
10
 
11
11
  export default defineFunction({
12
12
  key: 'example.org/function/reply',
@@ -5,7 +5,7 @@
5
5
  import * as Effect from 'effect/Effect';
6
6
  import * as Schema from 'effect/Schema';
7
7
 
8
- import { defineFunction } from '../handler';
8
+ import { defineFunction } from '../sdk';
9
9
 
10
10
  export default defineFunction({
11
11
  key: 'example.org/function/sleep',
package/src/index.ts CHANGED
@@ -3,12 +3,8 @@
3
3
  //
4
4
 
5
5
  export * from './errors';
6
- export * from './handler';
7
- export * from './schema';
8
- export * from './trace';
9
- export * from './types';
10
- export * from './url';
11
- export * from './triggers';
6
+ export * from './example';
7
+ export * from './sdk';
12
8
  export * from './services';
13
- export * from './executor';
14
- export * as exampleFunctions from './examples';
9
+ export * from './types';
10
+ export * from './protocol';
@@ -0,0 +1,185 @@
1
+ //
2
+ // Copyright 2025 DXOS.org
3
+ //
4
+
5
+ import * as Effect from 'effect/Effect';
6
+ import * as Schema from 'effect/Schema';
7
+ import { describe, expect, test } from 'vitest';
8
+
9
+ import { FunctionDefinition, defineFunction } from './sdk';
10
+
11
+ describe('Function/Operation Compatibility', () => {
12
+ test('can convert FunctionDefinition to OperationDefinition', () => {
13
+ const func = defineFunction({
14
+ key: 'test.function',
15
+ name: 'Test Function',
16
+ description: 'A test function',
17
+ inputSchema: Schema.Struct({ value: Schema.Number }),
18
+ outputSchema: Schema.Struct({ result: Schema.String }),
19
+ handler: async ({ data }) => {
20
+ return { result: data.value.toString() };
21
+ },
22
+ });
23
+
24
+ const op = FunctionDefinition.toOperation(func);
25
+
26
+ expect(op.meta.key).toBe('test.function');
27
+ expect(op.meta.name).toBe('Test Function');
28
+ expect(op.meta.description).toBe('A test function');
29
+ expect(Schema.isSchema(op.schema.input)).toBe(true);
30
+ expect(Schema.isSchema(op.schema.output)).toBe(true);
31
+ });
32
+
33
+ test('converted operation has matching schemas', () => {
34
+ const inputSchema = Schema.Struct({
35
+ name: Schema.String,
36
+ age: Schema.Number,
37
+ });
38
+ const outputSchema = Schema.Struct({
39
+ greeting: Schema.String,
40
+ });
41
+
42
+ const func = defineFunction({
43
+ key: 'test.greet',
44
+ name: 'Greet',
45
+ inputSchema,
46
+ outputSchema,
47
+ handler: async ({ data }) => {
48
+ return { greeting: `Hello, ${data.name}!` };
49
+ },
50
+ });
51
+
52
+ const op = FunctionDefinition.toOperation(func);
53
+
54
+ // Verify schemas match
55
+ const testInput = { name: 'Alice', age: 30 };
56
+ const validatedInput = Schema.decodeSync(op.schema.input)(testInput);
57
+ expect(validatedInput).toEqual(testInput);
58
+
59
+ const testOutput = { greeting: 'Hello, Alice!' };
60
+ const validatedOutput = Schema.decodeSync(op.schema.output)(testOutput);
61
+ expect(validatedOutput).toEqual(testOutput);
62
+ });
63
+
64
+ test('converted operation preserves metadata', () => {
65
+ const func = defineFunction({
66
+ key: 'test.meta',
67
+ name: 'Meta Test',
68
+ description: 'Tests metadata preservation',
69
+ inputSchema: Schema.Void,
70
+ outputSchema: Schema.Void,
71
+ handler: async () => {},
72
+ });
73
+
74
+ const op = FunctionDefinition.toOperation(func);
75
+
76
+ expect(op.meta.key).toBe('test.meta');
77
+ expect(op.meta.name).toBe('Meta Test');
78
+ expect(op.meta.description).toBe('Tests metadata preservation');
79
+ });
80
+
81
+ test('converted operation is pipeable', () => {
82
+ const func = defineFunction({
83
+ key: 'test.pipe',
84
+ name: 'Pipe Test',
85
+ inputSchema: Schema.Void,
86
+ outputSchema: Schema.Void,
87
+ handler: async () => {},
88
+ });
89
+
90
+ const op = FunctionDefinition.toOperation(func);
91
+
92
+ expect(typeof op.pipe).toBe('function');
93
+ });
94
+
95
+ test('handles functions without output schema', () => {
96
+ const func = defineFunction({
97
+ key: 'test.no-output',
98
+ name: 'No Output',
99
+ inputSchema: Schema.Struct({ value: Schema.Number }),
100
+ handler: async ({ data }) => {
101
+ return data.value * 2;
102
+ },
103
+ });
104
+
105
+ const op = FunctionDefinition.toOperation(func);
106
+
107
+ expect(op.meta.key).toBe('test.no-output');
108
+ expect(Schema.isSchema(op.schema.output)).toBe(true);
109
+ });
110
+
111
+ test('converted operation includes handler', () => {
112
+ const func = defineFunction({
113
+ key: 'test.handler',
114
+ name: 'Handler Test',
115
+ inputSchema: Schema.Struct({ value: Schema.Number }),
116
+ outputSchema: Schema.Struct({ doubled: Schema.Number }),
117
+ handler: async ({ data }) => {
118
+ return { doubled: data.value * 2 };
119
+ },
120
+ });
121
+
122
+ const op = FunctionDefinition.toOperation(func);
123
+
124
+ expect(op.handler).toBeDefined();
125
+ expect(typeof op.handler).toBe('function');
126
+ });
127
+
128
+ test('converted operation has handler function', () => {
129
+ const func = defineFunction({
130
+ key: 'test.execute',
131
+ name: 'Execute Test',
132
+ inputSchema: Schema.Struct({ value: Schema.Number }),
133
+ outputSchema: Schema.Struct({ result: Schema.Number }),
134
+ handler: async ({ data }) => {
135
+ return { result: data.value * 3 };
136
+ },
137
+ });
138
+
139
+ const op = FunctionDefinition.toOperation(func);
140
+
141
+ // Handler is present and is a function that returns an Effect
142
+ expect(op.handler).toBeDefined();
143
+ const effect = op.handler({ value: 5 });
144
+ // Verify it returns an Effect-like object
145
+ expect(effect).toHaveProperty('pipe');
146
+ });
147
+
148
+ test('converted operation works with Effect-based handlers', () => {
149
+ const func = defineFunction({
150
+ key: 'test.effect',
151
+ name: 'Effect Test',
152
+ inputSchema: Schema.Struct({ value: Schema.Number }),
153
+ outputSchema: Schema.Struct({ result: Schema.Number }),
154
+ handler: Effect.fn(function* ({ data }) {
155
+ return { result: data.value * 4 };
156
+ }),
157
+ });
158
+
159
+ const op = FunctionDefinition.toOperation(func);
160
+
161
+ // Handler is present and produces an Effect
162
+ expect(op.handler).toBeDefined();
163
+ const effect = op.handler({ value: 3 });
164
+ expect(effect).toHaveProperty('pipe');
165
+ });
166
+
167
+ test('converted operation works with synchronous handlers', () => {
168
+ const func = defineFunction({
169
+ key: 'test.sync',
170
+ name: 'Sync Test',
171
+ inputSchema: Schema.Struct({ value: Schema.Number }),
172
+ outputSchema: Schema.Struct({ result: Schema.Number }),
173
+ handler: ({ data }) => {
174
+ return { result: data.value * 5 };
175
+ },
176
+ });
177
+
178
+ const op = FunctionDefinition.toOperation(func);
179
+
180
+ // Handler is present and produces an Effect
181
+ expect(op.handler).toBeDefined();
182
+ const effect = op.handler({ value: 2 });
183
+ expect(effect).toHaveProperty('pipe');
184
+ });
185
+ });
@@ -0,0 +1,67 @@
1
+ //
2
+ // Copyright 2025 DXOS.org
3
+ //
4
+
5
+ import * as Headers from '@effect/platform/Headers';
6
+ import * as HttpClient from '@effect/platform/HttpClient';
7
+ import * as HttpClientError from '@effect/platform/HttpClientError';
8
+ import * as HttpClientResponse from '@effect/platform/HttpClientResponse';
9
+ import * as Effect from 'effect/Effect';
10
+ import * as FiberRef from 'effect/FiberRef';
11
+ import * as Layer from 'effect/Layer';
12
+ import * as Stream from 'effect/Stream';
13
+
14
+ import { log } from '@dxos/log';
15
+ import { type EdgeFunctionEnv, ErrorCodec } from '@dxos/protocols';
16
+ /**
17
+ * Copy pasted from https://github.com/Effect-TS/effect/blob/main/packages/platform/src/internal/fetchHttpClient.ts
18
+ */
19
+ export const requestInitTagKey = '@effect/platform/FetchHttpClient/FetchOptions';
20
+
21
+ export class FunctionsAiHttpClient {
22
+ static make = (service: EdgeFunctionEnv.FunctionsAiService) =>
23
+ HttpClient.make((request, url, signal, fiber) => {
24
+ const context = fiber.getFiberRef(FiberRef.currentContext);
25
+ const options: RequestInit = context.unsafeMap.get(requestInitTagKey) ?? {};
26
+ const headers = options.headers
27
+ ? Headers.merge(Headers.fromInput(options.headers), request.headers)
28
+ : request.headers;
29
+
30
+ const send = (body: BodyInit | undefined) =>
31
+ Effect.tryPromise({
32
+ try: () =>
33
+ service.fetch(
34
+ new Request(url, {
35
+ ...options,
36
+ method: request.method,
37
+ headers,
38
+ body,
39
+ // Note: Don't pass signal - it can't be serialized through RPC
40
+ }),
41
+ ),
42
+ catch: (cause) => {
43
+ log.error('Failed to fetch', { errorSerialized: ErrorCodec.encode(cause as Error) });
44
+ return new HttpClientError.RequestError({
45
+ request,
46
+ reason: 'Transport',
47
+ cause,
48
+ });
49
+ },
50
+ }).pipe(Effect.map((response) => HttpClientResponse.fromWeb(request, response)));
51
+
52
+ switch (request.body._tag) {
53
+ case 'Raw':
54
+ case 'Uint8Array':
55
+ return send(request.body.body as any);
56
+ case 'FormData':
57
+ return send(request.body.formData);
58
+ case 'Stream':
59
+ return Stream.toReadableStreamEffect(request.body.stream).pipe(Effect.flatMap(send));
60
+ }
61
+
62
+ return send(undefined);
63
+ });
64
+
65
+ static layer = (service: EdgeFunctionEnv.FunctionsAiService) =>
66
+ Layer.succeed(HttpClient.HttpClient, FunctionsAiHttpClient.make(service));
67
+ }
@@ -2,4 +2,4 @@
2
2
  // Copyright 2025 DXOS.org
3
3
  //
4
4
 
5
- export * from './executor';
5
+ export * from './protocol';
@@ -0,0 +1,59 @@
1
+ //
2
+ // Copyright 2025 DXOS.org
3
+ //
4
+
5
+ import { describe, test } from 'vitest';
6
+
7
+ import { FunctionError } from '../errors';
8
+ import fibFunc from '../example/fib';
9
+ import replyFunc from '../example/reply';
10
+
11
+ import { wrapFunctionHandler } from './protocol';
12
+
13
+ describe('wrapFunctionHandler', () => {
14
+ test('wraps reply function and executes handler', async ({ expect }) => {
15
+ const wrapped = wrapFunctionHandler(replyFunc);
16
+
17
+ expect(wrapped.meta.key).toBe('example.org/function/reply');
18
+ expect(wrapped.meta.name).toBe('Reply');
19
+
20
+ const testData = { message: 'hello' };
21
+ const result = await wrapped.handler({
22
+ data: testData,
23
+ context: {
24
+ services: {},
25
+ },
26
+ });
27
+
28
+ expect(result).toEqual(testData);
29
+ });
30
+
31
+ test('wraps fibonacci function with valid input', async ({ expect }) => {
32
+ const wrapped = wrapFunctionHandler(fibFunc);
33
+
34
+ expect(wrapped.meta.key).toBe('example.org/function/fib');
35
+ expect(wrapped.meta.name).toBe('Fibonacci');
36
+
37
+ const result = await wrapped.handler({
38
+ data: { iterations: 10 },
39
+ context: {
40
+ services: {},
41
+ },
42
+ });
43
+
44
+ expect(result).toEqual({ result: '55' });
45
+ });
46
+
47
+ test('throws FunctionError on invalid input schema for fibonacci', async ({ expect }) => {
48
+ const wrapped = wrapFunctionHandler(fibFunc);
49
+
50
+ await expect(
51
+ wrapped.handler({
52
+ data: { iterations: 'invalid' },
53
+ context: {
54
+ services: {},
55
+ },
56
+ }),
57
+ ).rejects.toThrow(FunctionError);
58
+ });
59
+ });