@dxos/functions 0.8.4-main.dedc0f3 → 0.8.4-main.dfabb4ec29

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 (181) hide show
  1. package/README.md +4 -6
  2. package/dist/lib/neutral/index.mjs +593 -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/index.d.ts +3 -9
  6. package/dist/types/src/index.d.ts.map +1 -1
  7. package/dist/types/src/protocol/functions-ai-http-client.d.ts +12 -0
  8. package/dist/types/src/protocol/functions-ai-http-client.d.ts.map +1 -0
  9. package/dist/types/src/protocol/functions-ai-http-client.test.d.ts +2 -0
  10. package/dist/types/src/protocol/functions-ai-http-client.test.d.ts.map +1 -0
  11. package/dist/types/src/protocol/index.d.ts +2 -0
  12. package/dist/types/src/protocol/index.d.ts.map +1 -0
  13. package/dist/types/src/protocol/protocol.d.ts +19 -0
  14. package/dist/types/src/protocol/protocol.d.ts.map +1 -0
  15. package/dist/types/src/protocol/protocol.test.d.ts +2 -0
  16. package/dist/types/src/protocol/protocol.test.d.ts.map +1 -0
  17. package/dist/types/src/sdk.d.ts +10 -0
  18. package/dist/types/src/sdk.d.ts.map +1 -0
  19. package/dist/types/src/services/credentials.d.ts +22 -39
  20. package/dist/types/src/services/credentials.d.ts.map +1 -1
  21. package/dist/types/src/services/function-invocation-service.d.ts +15 -0
  22. package/dist/types/src/services/function-invocation-service.d.ts.map +1 -0
  23. package/dist/types/src/services/index.d.ts +3 -7
  24. package/dist/types/src/services/index.d.ts.map +1 -1
  25. package/dist/types/src/services/queues.d.ts +1 -44
  26. package/dist/types/src/services/queues.d.ts.map +1 -1
  27. package/dist/types/src/services/tracing.d.ts +2 -54
  28. package/dist/types/src/services/tracing.d.ts.map +1 -1
  29. package/dist/types/src/types/index.d.ts +2 -0
  30. package/dist/types/src/types/index.d.ts.map +1 -0
  31. package/dist/types/src/types/url.d.ts +13 -0
  32. package/dist/types/src/types/url.d.ts.map +1 -0
  33. package/dist/types/tsconfig.tsbuildinfo +1 -1
  34. package/package.json +25 -72
  35. package/src/index.ts +3 -9
  36. package/src/protocol/functions-ai-http-client.test.ts +105 -0
  37. package/src/protocol/functions-ai-http-client.ts +141 -0
  38. package/src/{executor → protocol}/index.ts +1 -1
  39. package/src/protocol/protocol.test.ts +58 -0
  40. package/src/protocol/protocol.ts +428 -0
  41. package/src/sdk.ts +31 -0
  42. package/src/services/credentials.ts +90 -111
  43. package/src/services/function-invocation-service.ts +33 -0
  44. package/src/services/index.ts +3 -7
  45. package/src/services/queues.ts +1 -78
  46. package/src/services/tracing.ts +1 -133
  47. package/src/types/index.ts +5 -0
  48. package/src/types/url.ts +32 -0
  49. package/dist/lib/browser/bundler/index.mjs +0 -265
  50. package/dist/lib/browser/bundler/index.mjs.map +0 -7
  51. package/dist/lib/browser/chunk-ANP3DFCO.mjs +0 -623
  52. package/dist/lib/browser/chunk-ANP3DFCO.mjs.map +0 -7
  53. package/dist/lib/browser/chunk-J5LGTIGS.mjs +0 -10
  54. package/dist/lib/browser/chunk-J5LGTIGS.mjs.map +0 -7
  55. package/dist/lib/browser/edge/index.mjs +0 -83
  56. package/dist/lib/browser/edge/index.mjs.map +0 -7
  57. package/dist/lib/browser/index.mjs +0 -1265
  58. package/dist/lib/browser/index.mjs.map +0 -7
  59. package/dist/lib/browser/meta.json +0 -1
  60. package/dist/lib/browser/testing/index.mjs +0 -129
  61. package/dist/lib/browser/testing/index.mjs.map +0 -7
  62. package/dist/lib/node-esm/bundler/index.mjs +0 -266
  63. package/dist/lib/node-esm/bundler/index.mjs.map +0 -7
  64. package/dist/lib/node-esm/chunk-HSLMI22Q.mjs +0 -11
  65. package/dist/lib/node-esm/chunk-HSLMI22Q.mjs.map +0 -7
  66. package/dist/lib/node-esm/chunk-MPKVY7ZR.mjs +0 -625
  67. package/dist/lib/node-esm/chunk-MPKVY7ZR.mjs.map +0 -7
  68. package/dist/lib/node-esm/edge/index.mjs +0 -84
  69. package/dist/lib/node-esm/edge/index.mjs.map +0 -7
  70. package/dist/lib/node-esm/index.mjs +0 -1266
  71. package/dist/lib/node-esm/index.mjs.map +0 -7
  72. package/dist/lib/node-esm/meta.json +0 -1
  73. package/dist/lib/node-esm/testing/index.mjs +0 -130
  74. package/dist/lib/node-esm/testing/index.mjs.map +0 -7
  75. package/dist/types/src/bundler/bundler.d.ts +0 -49
  76. package/dist/types/src/bundler/bundler.d.ts.map +0 -1
  77. package/dist/types/src/bundler/bundler.test.d.ts +0 -2
  78. package/dist/types/src/bundler/bundler.test.d.ts.map +0 -1
  79. package/dist/types/src/bundler/index.d.ts +0 -2
  80. package/dist/types/src/bundler/index.d.ts.map +0 -1
  81. package/dist/types/src/edge/functions.d.ts +0 -17
  82. package/dist/types/src/edge/functions.d.ts.map +0 -1
  83. package/dist/types/src/edge/index.d.ts +0 -2
  84. package/dist/types/src/edge/index.d.ts.map +0 -1
  85. package/dist/types/src/errors.d.ts +0 -137
  86. package/dist/types/src/errors.d.ts.map +0 -1
  87. package/dist/types/src/examples/fib.d.ts +0 -7
  88. package/dist/types/src/examples/fib.d.ts.map +0 -1
  89. package/dist/types/src/examples/index.d.ts +0 -4
  90. package/dist/types/src/examples/index.d.ts.map +0 -1
  91. package/dist/types/src/examples/reply.d.ts +0 -3
  92. package/dist/types/src/examples/reply.d.ts.map +0 -1
  93. package/dist/types/src/examples/sleep.d.ts +0 -5
  94. package/dist/types/src/examples/sleep.d.ts.map +0 -1
  95. package/dist/types/src/executor/executor.d.ts +0 -11
  96. package/dist/types/src/executor/executor.d.ts.map +0 -1
  97. package/dist/types/src/executor/index.d.ts +0 -2
  98. package/dist/types/src/executor/index.d.ts.map +0 -1
  99. package/dist/types/src/handler.d.ts +0 -94
  100. package/dist/types/src/handler.d.ts.map +0 -1
  101. package/dist/types/src/schema.d.ts +0 -43
  102. package/dist/types/src/schema.d.ts.map +0 -1
  103. package/dist/types/src/services/database.d.ts +0 -98
  104. package/dist/types/src/services/database.d.ts.map +0 -1
  105. package/dist/types/src/services/event-logger.d.ts +0 -72
  106. package/dist/types/src/services/event-logger.d.ts.map +0 -1
  107. package/dist/types/src/services/local-function-execution.d.ts +0 -25
  108. package/dist/types/src/services/local-function-execution.d.ts.map +0 -1
  109. package/dist/types/src/services/remote-function-execution-service.d.ts +0 -15
  110. package/dist/types/src/services/remote-function-execution-service.d.ts.map +0 -1
  111. package/dist/types/src/services/service-container.d.ts +0 -56
  112. package/dist/types/src/services/service-container.d.ts.map +0 -1
  113. package/dist/types/src/services/service-registry.d.ts +0 -29
  114. package/dist/types/src/services/service-registry.d.ts.map +0 -1
  115. package/dist/types/src/services/service-registry.test.d.ts +0 -2
  116. package/dist/types/src/services/service-registry.test.d.ts.map +0 -1
  117. package/dist/types/src/testing/index.d.ts +0 -3
  118. package/dist/types/src/testing/index.d.ts.map +0 -1
  119. package/dist/types/src/testing/layer.d.ts +0 -15
  120. package/dist/types/src/testing/layer.d.ts.map +0 -1
  121. package/dist/types/src/testing/logger.d.ts +0 -5
  122. package/dist/types/src/testing/logger.d.ts.map +0 -1
  123. package/dist/types/src/testing/persist-database.test.d.ts +0 -2
  124. package/dist/types/src/testing/persist-database.test.d.ts.map +0 -1
  125. package/dist/types/src/testing/services.d.ts +0 -59
  126. package/dist/types/src/testing/services.d.ts.map +0 -1
  127. package/dist/types/src/trace.d.ts +0 -122
  128. package/dist/types/src/trace.d.ts.map +0 -1
  129. package/dist/types/src/translations.d.ts +0 -12
  130. package/dist/types/src/translations.d.ts.map +0 -1
  131. package/dist/types/src/triggers/index.d.ts +0 -4
  132. package/dist/types/src/triggers/index.d.ts.map +0 -1
  133. package/dist/types/src/triggers/input-builder.d.ts +0 -3
  134. package/dist/types/src/triggers/input-builder.d.ts.map +0 -1
  135. package/dist/types/src/triggers/invocation-tracer.d.ts +0 -35
  136. package/dist/types/src/triggers/invocation-tracer.d.ts.map +0 -1
  137. package/dist/types/src/triggers/trigger-dispatcher.d.ts +0 -75
  138. package/dist/types/src/triggers/trigger-dispatcher.d.ts.map +0 -1
  139. package/dist/types/src/triggers/trigger-dispatcher.test.d.ts +0 -2
  140. package/dist/types/src/triggers/trigger-dispatcher.test.d.ts.map +0 -1
  141. package/dist/types/src/triggers/trigger-state-store.d.ts +0 -27
  142. package/dist/types/src/triggers/trigger-state-store.d.ts.map +0 -1
  143. package/dist/types/src/types.d.ts +0 -211
  144. package/dist/types/src/types.d.ts.map +0 -1
  145. package/dist/types/src/url.d.ts +0 -21
  146. package/dist/types/src/url.d.ts.map +0 -1
  147. package/src/bundler/bundler.test.ts +0 -58
  148. package/src/bundler/bundler.ts +0 -291
  149. package/src/bundler/index.ts +0 -5
  150. package/src/edge/functions.ts +0 -67
  151. package/src/edge/index.ts +0 -9
  152. package/src/errors.ts +0 -21
  153. package/src/examples/fib.ts +0 -30
  154. package/src/examples/index.ts +0 -7
  155. package/src/examples/reply.ts +0 -18
  156. package/src/examples/sleep.ts +0 -22
  157. package/src/executor/executor.ts +0 -54
  158. package/src/handler.ts +0 -201
  159. package/src/schema.ts +0 -68
  160. package/src/services/database.ts +0 -170
  161. package/src/services/event-logger.ts +0 -118
  162. package/src/services/local-function-execution.ts +0 -114
  163. package/src/services/remote-function-execution-service.ts +0 -46
  164. package/src/services/service-container.ts +0 -114
  165. package/src/services/service-registry.test.ts +0 -42
  166. package/src/services/service-registry.ts +0 -59
  167. package/src/testing/index.ts +0 -6
  168. package/src/testing/layer.ts +0 -111
  169. package/src/testing/logger.ts +0 -16
  170. package/src/testing/persist-database.test.ts +0 -87
  171. package/src/testing/services.ts +0 -115
  172. package/src/trace.ts +0 -178
  173. package/src/translations.ts +0 -20
  174. package/src/triggers/index.ts +0 -7
  175. package/src/triggers/input-builder.ts +0 -35
  176. package/src/triggers/invocation-tracer.ts +0 -99
  177. package/src/triggers/trigger-dispatcher.test.ts +0 -652
  178. package/src/triggers/trigger-dispatcher.ts +0 -512
  179. package/src/triggers/trigger-state-store.ts +0 -60
  180. package/src/types.ts +0 -200
  181. package/src/url.ts +0 -55
package/README.md CHANGED
@@ -27,11 +27,9 @@ import { FunctionContext } from '@dxos/functions';
27
27
 
28
28
  export default (event: any, context: FunctionContext) => {
29
29
  const identity = context.client.halo.identity.get();
30
- return context
31
- .status(200)
32
- .succeed({
33
- message: `Hello ${identity?.profile?.displayName}`
34
- });
30
+ return context.status(200).succeed({
31
+ message: `Hello ${identity?.profile?.displayName}`,
32
+ });
35
33
  };
36
34
  ```
37
35
 
@@ -69,7 +67,7 @@ nodemon -w ./src -e ts --exec $(git rev-parse --show-toplevel)/packages/devtools
69
67
  > NOTE: The port (7001) must match the one in config.
70
68
 
71
69
  ```bash
72
- curl http://localhost:7001/dev/hello -X POST -H 'Content-Type: application/json' -w '\n' --data '{ "message": "Hello World!" }'
70
+ curl http://localhost:7001/dev/hello -X POST -H 'Content-Type: application/json' -w '\n' --data '{ "message": "Hello World!" }'
73
71
  ```
74
72
 
75
73
  ## DXOS Resources
@@ -0,0 +1,593 @@
1
+ // src/services/credentials.ts
2
+ import * as HttpClient from "@effect/platform/HttpClient";
3
+ import * as HttpClientRequest from "@effect/platform/HttpClientRequest";
4
+ import * as Effect from "effect/Effect";
5
+ import * as Layer from "effect/Layer";
6
+ import * as Redacted from "effect/Redacted";
7
+ import { Credential } from "@dxos/compute";
8
+ import { Query } from "@dxos/echo";
9
+ import { Database } from "@dxos/echo";
10
+ import { AccessToken } from "@dxos/types";
11
+ var ConfiguredCredentialsService = class {
12
+ credentials;
13
+ constructor(credentials = []) {
14
+ this.credentials = credentials;
15
+ }
16
+ addCredentials(credentials) {
17
+ this.credentials.push(...credentials);
18
+ return this;
19
+ }
20
+ async queryCredentials(query) {
21
+ return this.credentials.filter((credential) => credential.service === query.service);
22
+ }
23
+ async getCredential(query) {
24
+ const credential = this.credentials.find((credential2) => credential2.service === query.service);
25
+ if (!credential) {
26
+ throw new Error(`Credential not found for service: ${query.service}`);
27
+ }
28
+ return credential;
29
+ }
30
+ };
31
+ var withAuthorization = (token, kind) => HttpClient.mapRequest((request) => {
32
+ const authorization = kind ? `${kind} ${token}` : token;
33
+ return HttpClientRequest.setHeader(request, "Authorization", authorization);
34
+ });
35
+ var configuredCredentialsLayer = (credentials) => Layer.succeed(Credential.CredentialsService, new ConfiguredCredentialsService(credentials));
36
+ var credentialsLayerConfig = (credentials) => Layer.effect(Credential.CredentialsService, Effect.gen(function* () {
37
+ const serviceCredentials = yield* Effect.forEach(credentials, ({ service, apiKey }) => Effect.gen(function* () {
38
+ return {
39
+ service,
40
+ apiKey: Redacted.value(yield* apiKey)
41
+ };
42
+ }));
43
+ return new ConfiguredCredentialsService(serviceCredentials);
44
+ }));
45
+ var credentialsLayerFromDatabase = ({ caching = false } = {}) => Layer.effect(Credential.CredentialsService, Effect.gen(function* () {
46
+ const dbService = yield* Database.Service;
47
+ const cache = /* @__PURE__ */ new Map();
48
+ const queryCredentials = async (query) => {
49
+ const cacheKey = JSON.stringify(query);
50
+ if (caching && cache.has(cacheKey)) {
51
+ return cache.get(cacheKey);
52
+ }
53
+ const accessTokens = await dbService.db.query(Query.type(AccessToken.AccessToken)).run();
54
+ const credentials = accessTokens.filter((accessToken) => accessToken.source === query.service).map((accessToken) => ({
55
+ service: accessToken.source,
56
+ apiKey: accessToken.token
57
+ }));
58
+ if (caching) {
59
+ cache.set(cacheKey, credentials);
60
+ }
61
+ return credentials;
62
+ };
63
+ return {
64
+ getCredential: async (query) => {
65
+ const credentials = await queryCredentials(query);
66
+ if (credentials.length === 0) {
67
+ throw new Error(`Credential not found for service: ${query.service}`);
68
+ }
69
+ return credentials[0];
70
+ },
71
+ queryCredentials: async (query) => {
72
+ return queryCredentials(query);
73
+ }
74
+ };
75
+ }));
76
+
77
+ // src/services/function-invocation-service.ts
78
+ import * as Context from "effect/Context";
79
+ import * as Effect2 from "effect/Effect";
80
+ import * as Layer2 from "effect/Layer";
81
+ var FunctionInvocationService = class _FunctionInvocationService extends Context.Tag("@dxos/functions/FunctionInvocationService")() {
82
+ static layerNotAvailable = Layer2.succeed(_FunctionInvocationService, {
83
+ invokeFunction: () => Effect2.die("FunctionInvocationService is not avaialble."),
84
+ resolveFunction: () => Effect2.die("FunctionInvocationService is not available.")
85
+ });
86
+ static invokeFunction = (functionDef, input) => Effect2.serviceFunctionEffect(_FunctionInvocationService, (service) => service.invokeFunction)(functionDef, input);
87
+ static resolveFunction = (key) => Effect2.serviceFunctionEffect(_FunctionInvocationService, (service) => service.resolveFunction)(key);
88
+ };
89
+
90
+ // src/services/queues.ts
91
+ import { ContextQueueService, QueueService, feedServiceFromQueueServiceLayer } from "@dxos/echo-db";
92
+
93
+ // src/services/tracing.ts
94
+ var MESSAGE_PROPERTY_TOOL_CALL_ID = "toolCallId";
95
+
96
+ // src/types/url.ts
97
+ var FUNCTIONS_META_KEY = "org.dxos.service.function";
98
+ var FUNCTIONS_PRESET_META_KEY = "org.dxos.service.function-preset";
99
+ var getUserFunctionIdInMetadata = (meta) => {
100
+ return meta.keys.find((key) => key.source === FUNCTIONS_META_KEY)?.id;
101
+ };
102
+ var setUserFunctionIdInMetadata = (meta, functionId) => {
103
+ const key = meta.keys.find((key2) => key2.source === FUNCTIONS_META_KEY);
104
+ if (key) {
105
+ if (key.id !== functionId) {
106
+ throw new Error("Metadata mismatch");
107
+ }
108
+ } else {
109
+ meta.keys.push({
110
+ source: FUNCTIONS_META_KEY,
111
+ id: functionId
112
+ });
113
+ }
114
+ };
115
+
116
+ // src/protocol/protocol.ts
117
+ import * as AnthropicClient from "@effect/ai-anthropic/AnthropicClient";
118
+ import * as Effect4 from "effect/Effect";
119
+ import * as Layer4 from "effect/Layer";
120
+ import * as Option from "effect/Option";
121
+ import * as Schema from "effect/Schema";
122
+ import * as SchemaAST from "effect/SchemaAST";
123
+ import { AiModelResolver, AiService, OpaqueToolkit } from "@dxos/ai";
124
+ import { AnthropicResolver } from "@dxos/ai/resolvers";
125
+ import { FunctionError, InvalidOperationInputError, InvalidOperationOutputError, Operation, OperationRegistry, Trace } from "@dxos/compute";
126
+ import { LifecycleState, Resource } from "@dxos/context";
127
+ import { Database as Database2, Feed, JsonSchema, Ref } from "@dxos/echo";
128
+ import { createFeedServiceLayer, EchoClient } from "@dxos/echo-db";
129
+ import { refFromEncodedReference } from "@dxos/echo/internal";
130
+ import { runAndForwardErrors } from "@dxos/effect";
131
+ import { assertState, failedInvariant, invariant } from "@dxos/invariant";
132
+ import { PublicKey } from "@dxos/keys";
133
+ import { log as log2 } from "@dxos/log";
134
+ import { ErrorCodec as ErrorCodec2 } from "@dxos/protocols";
135
+
136
+ // src/protocol/functions-ai-http-client.ts
137
+ import * as Headers from "@effect/platform/Headers";
138
+ import * as HttpClient2 from "@effect/platform/HttpClient";
139
+ import * as HttpClientError from "@effect/platform/HttpClientError";
140
+ import * as HttpClientResponse from "@effect/platform/HttpClientResponse";
141
+ import * as Effect3 from "effect/Effect";
142
+ import * as FiberRef from "effect/FiberRef";
143
+ import * as Layer3 from "effect/Layer";
144
+ import * as Stream from "effect/Stream";
145
+ import { FunctionsAiMemoizationMissError, FunctionsAiUpstreamError } from "@dxos/compute";
146
+ import { log } from "@dxos/log";
147
+ import { ErrorCodec } from "@dxos/protocols";
148
+ var __dxlog_file = "/__w/dxos/dxos/packages/core/compute/functions/src/protocol/functions-ai-http-client.ts";
149
+ var requestInitTagKey = "@effect/platform/FetchHttpClient/FetchOptions";
150
+ var FunctionsAiHttpClient = class _FunctionsAiHttpClient {
151
+ static make = (service) => HttpClient2.make((request, url, signal, fiber) => {
152
+ const context = fiber.getFiberRef(FiberRef.currentContext);
153
+ const options = context.unsafeMap.get(requestInitTagKey) ?? {};
154
+ const headers = options.headers ? Headers.merge(Headers.fromInput(options.headers), request.headers) : request.headers;
155
+ const send = (body) => Effect3.tryPromise({
156
+ try: () => service.fetch(new Request(url, {
157
+ ...options,
158
+ method: request.method,
159
+ headers,
160
+ body
161
+ })),
162
+ catch: (cause) => {
163
+ log.error("Failed to fetch", {
164
+ errorSerialized: ErrorCodec.encode(cause)
165
+ }, { "~LogMeta": "~LogMeta", F: __dxlog_file, L: 31, S: this });
166
+ return new HttpClientError.RequestError({
167
+ request,
168
+ reason: "Transport",
169
+ cause
170
+ });
171
+ }
172
+ }).pipe(Effect3.flatMap((response) => (
173
+ // Inspect the body before handing the response to `@effect/ai` so that structured
174
+ // upstream errors surface as typed defects (`FunctionsAiUpstreamError` and friends)
175
+ // rather than as the generic `HttpResponseError` from `@effect/ai/AiError`.
176
+ Effect3.flatMap(Effect3.promise(() => parseUpstreamError(response)), (typedError) => typedError ? Effect3.die(typedError) : Effect3.succeed(HttpClientResponse.fromWeb(request, response)))
177
+ )));
178
+ switch (request.body._tag) {
179
+ case "Raw":
180
+ case "Uint8Array":
181
+ return send(request.body.body);
182
+ case "FormData":
183
+ return send(request.body.formData);
184
+ case "Stream":
185
+ return Stream.toReadableStreamEffect(request.body.stream).pipe(Effect3.flatMap(send));
186
+ }
187
+ return send(void 0);
188
+ });
189
+ static layer = (service) => Layer3.succeed(HttpClient2.HttpClient, _FunctionsAiHttpClient.make(service));
190
+ };
191
+ var parseUpstreamError = async (response) => {
192
+ if (response.ok) {
193
+ return void 0;
194
+ }
195
+ const contentType = response.headers.get("content-type") ?? "";
196
+ if (!contentType.toLowerCase().includes("application/json")) {
197
+ return void 0;
198
+ }
199
+ let body;
200
+ try {
201
+ body = await response.clone().json();
202
+ } catch {
203
+ return void 0;
204
+ }
205
+ if (!body || body.type !== "error" || typeof body.error !== "object" || body.error === null) {
206
+ return void 0;
207
+ }
208
+ const inner = body.error;
209
+ const message = inner.message ?? `Upstream AI service responded with HTTP ${response.status}`;
210
+ if (inner.type === "memoization_miss" && typeof inner.cacheKey === "string") {
211
+ return new FunctionsAiMemoizationMissError({
212
+ message,
213
+ context: {
214
+ cacheKey: inner.cacheKey,
215
+ status: response.status
216
+ }
217
+ });
218
+ }
219
+ return new FunctionsAiUpstreamError({
220
+ message,
221
+ context: {
222
+ type: inner.type,
223
+ status: response.status,
224
+ ...inner.cacheKey ? {
225
+ cacheKey: inner.cacheKey
226
+ } : {}
227
+ }
228
+ });
229
+ };
230
+
231
+ // src/protocol/protocol.ts
232
+ var __dxlog_file2 = "/__w/dxos/dxos/packages/core/compute/functions/src/protocol/protocol.ts";
233
+ function _ts_add_disposable_resource(env, value2, async) {
234
+ if (value2 !== null && value2 !== void 0) {
235
+ if (typeof value2 !== "object" && typeof value2 !== "function") throw new TypeError("Object expected.");
236
+ var dispose, inner;
237
+ if (async) {
238
+ if (!Symbol.asyncDispose) throw new TypeError("Symbol.asyncDispose is not defined.");
239
+ dispose = value2[Symbol.asyncDispose];
240
+ }
241
+ if (dispose === void 0) {
242
+ if (!Symbol.dispose) throw new TypeError("Symbol.dispose is not defined.");
243
+ dispose = value2[Symbol.dispose];
244
+ if (async) inner = dispose;
245
+ }
246
+ if (typeof dispose !== "function") throw new TypeError("Object not disposable.");
247
+ if (inner) dispose = function() {
248
+ try {
249
+ inner.call(this);
250
+ } catch (e) {
251
+ return Promise.reject(e);
252
+ }
253
+ };
254
+ env.stack.push({
255
+ value: value2,
256
+ dispose,
257
+ async
258
+ });
259
+ } else if (async) {
260
+ env.stack.push({
261
+ async: true
262
+ });
263
+ }
264
+ return value2;
265
+ }
266
+ function _ts_dispose_resources(env) {
267
+ var _SuppressedError = typeof SuppressedError === "function" ? SuppressedError : function(error, suppressed, message) {
268
+ var e = new Error(message);
269
+ return e.name = "SuppressedError", e.error = error, e.suppressed = suppressed, e;
270
+ };
271
+ return (_ts_dispose_resources = function _ts_dispose_resources2(env2) {
272
+ function fail(e) {
273
+ env2.error = env2.hasError ? new _SuppressedError(e, env2.error, "An error was suppressed during disposal.") : e;
274
+ env2.hasError = true;
275
+ }
276
+ var r, s = 0;
277
+ function next() {
278
+ while (r = env2.stack.pop()) {
279
+ try {
280
+ if (!r.async && s === 1) return s = 0, env2.stack.push(r), Promise.resolve().then(next);
281
+ if (r.dispose) {
282
+ var result = r.dispose.call(r.value);
283
+ if (r.async) return s |= 2, Promise.resolve(result).then(next, function(e) {
284
+ fail(e);
285
+ return next();
286
+ });
287
+ } else s |= 1;
288
+ } catch (e) {
289
+ fail(e);
290
+ }
291
+ }
292
+ if (s === 1) return env2.hasError ? Promise.reject(env2.error) : Promise.resolve();
293
+ if (env2.hasError) throw env2.error;
294
+ }
295
+ return next();
296
+ })(env);
297
+ }
298
+ var wrapFunctionHandler = (func, opts = {}) => {
299
+ if (!Operation.isOperationWithHandler(func)) {
300
+ throw new TypeError("Expected operation with handler");
301
+ }
302
+ const serviceTags = func.services.map((service) => service.key);
303
+ return {
304
+ meta: {
305
+ key: func.meta.key,
306
+ name: func.meta.name,
307
+ description: func.meta.description,
308
+ inputSchema: JsonSchema.toJsonSchema(func.input),
309
+ outputSchema: func.output === void 0 ? void 0 : JsonSchema.toJsonSchema(func.output),
310
+ services: func.services.map((service) => service.key)
311
+ },
312
+ handler: async ({ data, context }) => {
313
+ if ((serviceTags.includes(Database2.Service.key) || serviceTags.includes(QueueService.key) || serviceTags.includes(Feed.FeedService.key)) && (!context.services.dataService || !context.services.queryService)) {
314
+ throw new FunctionError({
315
+ message: "Services not provided: dataService, queryService"
316
+ });
317
+ }
318
+ try {
319
+ const env = {
320
+ stack: [],
321
+ error: void 0,
322
+ hasError: false
323
+ };
324
+ try {
325
+ if (!SchemaAST.isAnyKeyword(func.input.ast)) {
326
+ try {
327
+ Schema.validateSync(func.input, {
328
+ onExcessProperty: "error"
329
+ })(data);
330
+ } catch (error) {
331
+ throw new InvalidOperationInputError({
332
+ message: `Operation input did not match schema (${func.meta.key}): ${error.message}`,
333
+ cause: error
334
+ });
335
+ }
336
+ }
337
+ const funcContext = _ts_add_disposable_resource(env, await new FunctionContext(context, opts).open(), true);
338
+ const types = [
339
+ ...opts.types ?? [],
340
+ ...func.types ?? []
341
+ ];
342
+ if (types.length > 0) {
343
+ invariant(funcContext.db, "Database is required for functions with types", { "~LogMeta": "~LogMeta", F: __dxlog_file2, L: 137, S: void 0, A: ["funcContext.db", "'Database is required for functions with types'"] });
344
+ await funcContext.db.graph.schemaRegistry.register(types);
345
+ }
346
+ const dataWithDecodedRefs = funcContext.db && !SchemaAST.isAnyKeyword(func.input.ast) ? decodeRefsFromSchema(func.input.ast, data, funcContext.db) : data;
347
+ let result = await func.handler(dataWithDecodedRefs);
348
+ if (Effect4.isEffect(result)) {
349
+ result = await runAndForwardErrors(result.pipe(Effect4.orDie, Effect4.provide(funcContext.createLayer())));
350
+ }
351
+ if (func.output && !SchemaAST.isAnyKeyword(func.output.ast)) {
352
+ try {
353
+ Schema.validateSync(func.output, {
354
+ onExcessProperty: "error"
355
+ })(result);
356
+ } catch (error) {
357
+ throw new InvalidOperationOutputError({
358
+ message: `Operation output did not match schema (${func.meta.key}): ${error.message}`,
359
+ cause: error
360
+ });
361
+ }
362
+ }
363
+ return result;
364
+ } catch (e) {
365
+ env.error = e;
366
+ env.hasError = true;
367
+ } finally {
368
+ const result = _ts_dispose_resources(env);
369
+ if (result) await result;
370
+ }
371
+ } catch (error) {
372
+ throw error;
373
+ }
374
+ }
375
+ };
376
+ };
377
+ var FunctionContext = class extends Resource {
378
+ context;
379
+ client;
380
+ db;
381
+ queues;
382
+ opts;
383
+ constructor(context, opts) {
384
+ super();
385
+ this.context = context;
386
+ this.opts = opts;
387
+ if (context.services.dataService && context.services.queryService) {
388
+ this.client = new EchoClient().connectToService({
389
+ dataService: context.services.dataService,
390
+ queryService: context.services.queryService,
391
+ queueService: context.services.queueService
392
+ });
393
+ }
394
+ }
395
+ async _open() {
396
+ await this.client?.open();
397
+ this.db = this.client && this.context.spaceId ? this.client.constructDatabase({
398
+ spaceId: this.context.spaceId ?? failedInvariant(),
399
+ spaceKey: PublicKey.fromHex(this.context.spaceKey ?? failedInvariant("spaceKey missing in context")),
400
+ reactiveSchemaQuery: false,
401
+ preloadSchemaOnOpen: false
402
+ }) : void 0;
403
+ await this.db?.setSpaceRoot(this.context.spaceRootUrl ?? failedInvariant("spaceRootUrl missing in context"));
404
+ await this.db?.open();
405
+ this.queues = this.client && this.context.spaceId ? this.client.constructQueueFactory(this.context.spaceId) : void 0;
406
+ }
407
+ async _close() {
408
+ await this.db?.close();
409
+ await this.client?.close();
410
+ }
411
+ createLayer() {
412
+ assertState(this._lifecycleState === LifecycleState.OPEN, "FunctionContext is not open");
413
+ const dbLayer = this.db ? Database2.layer(this.db) : Database2.notAvailable;
414
+ const queuesLayer = this.queues ? QueueService.layer(this.queues) : QueueService.notAvailable;
415
+ const feedLayer = this.queues ? createFeedServiceLayer(this.queues) : Feed.notAvailable;
416
+ const credentials = dbLayer ? credentialsLayerFromDatabase({
417
+ caching: true
418
+ }).pipe(Layer4.provide(dbLayer)) : configuredCredentialsLayer([]);
419
+ const aiLayer = this.context.services.functionsAiService ? InternalAiServiceLayer(this.context.services.functionsAiService) : AiService.notAvailable;
420
+ const operationServiceLayer = this.context.services.functionsService ? makeOperationServiceLayer(this.context.services.functionsService) : unavailableOperationServiceLayer;
421
+ const operationRegistryLayer = this.context.services.functionsService ? makeOperationRegistryLayer(this.context.services.functionsService, this.context.spaceId) : emptyOperationRegistryLayer;
422
+ const traceWriterLayer = this.context.services.traceService ? makeTraceWriterLayer(this.context.services.traceService) : Trace.writerLayerNoop;
423
+ log2("Creating function context layer", {
424
+ traceService: !!this.context.services.traceService,
425
+ functionsService: !!this.context.services.functionsService,
426
+ functionsAiService: !!this.context.services.functionsAiService,
427
+ spaceId: this.context.spaceId,
428
+ spaceRootUrl: this.context.spaceRootUrl,
429
+ toolkits: this.opts.toolkits?.length ?? 0,
430
+ types: this.opts.types?.length ?? 0
431
+ }, { "~LogMeta": "~LogMeta", F: __dxlog_file2, L: 220, S: this });
432
+ return Layer4.mergeAll(
433
+ dbLayer,
434
+ queuesLayer,
435
+ feedLayer,
436
+ credentials,
437
+ operationServiceLayer,
438
+ operationRegistryLayer,
439
+ aiLayer,
440
+ OpaqueToolkit.providerLayer(OpaqueToolkit.merge(...this.opts.toolkits ?? [])),
441
+ traceWriterLayer,
442
+ // `FunctionInvocationService` is deprecated; new code should yield `Operation.Service`.
443
+ // The cloudflare wrapper provides only the unavailable layer to satisfy the (still-present)
444
+ // type union — handlers that yield it will die at invocation time.
445
+ FunctionInvocationService.layerNotAvailable
446
+ );
447
+ }
448
+ };
449
+ var makeTraceWriterLayer = (traceService) => Layer4.succeed(Trace.TraceService, {
450
+ write: (eventType, payload) => {
451
+ log2("Writing trace event", {
452
+ eventType: eventType.key
453
+ }, { "~LogMeta": "~LogMeta", F: __dxlog_file2, L: 240, S: void 0 });
454
+ traceService.write([
455
+ {
456
+ key: eventType.key,
457
+ isEphemeral: eventType.isEphemeral,
458
+ data: payload
459
+ }
460
+ ]);
461
+ }
462
+ });
463
+ var InternalAiServiceLayer = (functionsAiService) => AiModelResolver.AiModelResolver.buildAiService.pipe(Layer4.provide(AnthropicResolver.make().pipe(Layer4.provide(AnthropicClient.layer({
464
+ // Note: It doesn't matter what is base url here, it will be proxied to ai gateway in edge.
465
+ apiUrl: "http://internal/provider/anthropic"
466
+ }).pipe(Layer4.provide(FunctionsAiHttpClient.layer(functionsAiService)))))));
467
+ var makeOperationServiceLayer = (functionsService) => {
468
+ const invokeRemote = async (op, input, options) => {
469
+ invariant(op.meta.deployedId, `Operation '${op.meta.key}' has no deployedId; cannot invoke remotely.`, { "~LogMeta": "~LogMeta", F: __dxlog_file2, L: 264, S: void 0, A: ["op.meta.deployedId", "`Operation '${op.meta.key}' has no deployedId; cannot invoke remotely.`"] });
470
+ const result = await functionsService.invoke(op.meta.deployedId, input, {
471
+ spaceId: options?.spaceId
472
+ });
473
+ if (result._kind === "success") {
474
+ return {
475
+ data: result.data
476
+ };
477
+ }
478
+ return {
479
+ error: ErrorCodec2.decode(result.error)
480
+ };
481
+ };
482
+ return Layer4.succeed(Operation.Service, {
483
+ invoke: (op, input, options) => Effect4.tryPromise(() => invokeRemote(op, input, options)).pipe(Effect4.orDie, Effect4.flatMap((outcome) => outcome.error ? Effect4.die(outcome.error) : Effect4.succeed(outcome.data))),
484
+ schedule: (op, input) => Effect4.sync(() => {
485
+ invariant(op.meta.deployedId, `Operation '${op.meta.key}' has no deployedId; cannot schedule remotely.`, { "~LogMeta": "~LogMeta", F: __dxlog_file2, L: 280, S: void 0, A: ["op.meta.deployedId", "`Operation '${op.meta.key}' has no deployedId; cannot schedule remotely.`"] });
486
+ void functionsService.invoke(op.meta.deployedId, input).catch(() => {
487
+ });
488
+ }),
489
+ invokePromise: (op, input, options) => invokeRemote(op, input, options).catch((error) => ({
490
+ error: error instanceof Error ? error : new Error(String(error))
491
+ }))
492
+ });
493
+ };
494
+ var unavailableOperationServiceLayer = Layer4.succeed(Operation.Service, {
495
+ invoke: () => Effect4.die("Operation.Service is not available: missing functionsService in EDGE context."),
496
+ schedule: () => Effect4.die("Operation.Service is not available: missing functionsService in EDGE context."),
497
+ invokePromise: async () => ({
498
+ error: new Error("Operation.Service is not available: missing functionsService in EDGE context.")
499
+ })
500
+ });
501
+ var makeOperationRegistryLayer = (functionsService, spaceId) => Layer4.succeed(OperationRegistry.Service, {
502
+ resolve: (key) => Effect4.gen(function* () {
503
+ const records = yield* Effect4.tryPromise(() => functionsService.query({
504
+ spaceId
505
+ })).pipe(Effect4.orDie);
506
+ const match = records.find((record) => record.key === key);
507
+ return match ? Option.some(Operation.deserialize(match)) : Option.none();
508
+ })
509
+ });
510
+ var emptyOperationRegistryLayer = Layer4.succeed(OperationRegistry.Service, {
511
+ resolve: () => Effect4.succeed(Option.none())
512
+ });
513
+ var decodeRefsFromSchema = (ast, value2, db) => {
514
+ if (value2 == null) {
515
+ return value2;
516
+ }
517
+ const encoded = SchemaAST.encodedBoundAST(ast);
518
+ if (Ref.isRefType(encoded)) {
519
+ if (Ref.isRef(value2)) {
520
+ return value2;
521
+ }
522
+ if (typeof value2 === "object" && value2 !== null && typeof value2["/"] === "string") {
523
+ const resolver = db.graph.createRefResolver({
524
+ context: {
525
+ space: db.spaceId
526
+ }
527
+ });
528
+ return refFromEncodedReference(value2, resolver);
529
+ }
530
+ return value2;
531
+ }
532
+ switch (encoded._tag) {
533
+ case "TypeLiteral": {
534
+ if (typeof value2 !== "object" || value2 === null || Array.isArray(value2)) {
535
+ return value2;
536
+ }
537
+ const result = {
538
+ ...value2
539
+ };
540
+ for (const prop of SchemaAST.getPropertySignatures(encoded)) {
541
+ const key = prop.name.toString();
542
+ if (key in result) {
543
+ result[key] = decodeRefsFromSchema(prop.type, result[key], db);
544
+ }
545
+ }
546
+ return result;
547
+ }
548
+ case "TupleType": {
549
+ if (!Array.isArray(value2)) {
550
+ return value2;
551
+ }
552
+ if (encoded.elements.length === 0 && encoded.rest.length === 1) {
553
+ const elementType = encoded.rest[0].type;
554
+ return value2.map((item) => decodeRefsFromSchema(elementType, item, db));
555
+ }
556
+ return value2;
557
+ }
558
+ case "Union": {
559
+ const nonUndefined = encoded.types.filter((t) => !SchemaAST.isUndefinedKeyword(t));
560
+ if (nonUndefined.length === 1) {
561
+ return decodeRefsFromSchema(nonUndefined[0], value2, db);
562
+ }
563
+ return value2;
564
+ }
565
+ case "Suspend": {
566
+ return decodeRefsFromSchema(encoded.f(), value2, db);
567
+ }
568
+ case "Refinement": {
569
+ return decodeRefsFromSchema(encoded.from, value2, db);
570
+ }
571
+ default: {
572
+ return value2;
573
+ }
574
+ }
575
+ };
576
+ export {
577
+ ConfiguredCredentialsService,
578
+ ContextQueueService,
579
+ FUNCTIONS_META_KEY,
580
+ FUNCTIONS_PRESET_META_KEY,
581
+ FunctionInvocationService,
582
+ MESSAGE_PROPERTY_TOOL_CALL_ID,
583
+ QueueService,
584
+ configuredCredentialsLayer,
585
+ credentialsLayerConfig,
586
+ credentialsLayerFromDatabase,
587
+ feedServiceFromQueueServiceLayer,
588
+ getUserFunctionIdInMetadata,
589
+ setUserFunctionIdInMetadata,
590
+ withAuthorization,
591
+ wrapFunctionHandler
592
+ };
593
+ //# sourceMappingURL=index.mjs.map