@dxos/functions 0.8.4-main.422d1c7879 → 0.8.4-main.4f23b4e393

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (98) hide show
  1. package/dist/lib/neutral/index.mjs +256 -883
  2. package/dist/lib/neutral/index.mjs.map +4 -4
  3. package/dist/lib/neutral/meta.json +1 -1
  4. package/dist/types/src/index.d.ts +0 -6
  5. package/dist/types/src/index.d.ts.map +1 -1
  6. package/dist/types/src/protocol/functions-ai-http-client.d.ts.map +1 -1
  7. package/dist/types/src/protocol/functions-ai-http-client.test.d.ts +2 -0
  8. package/dist/types/src/protocol/functions-ai-http-client.test.d.ts.map +1 -0
  9. package/dist/types/src/protocol/protocol.d.ts +14 -2
  10. package/dist/types/src/protocol/protocol.d.ts.map +1 -1
  11. package/dist/types/src/sdk.d.ts +3 -4
  12. package/dist/types/src/sdk.d.ts.map +1 -1
  13. package/dist/types/src/services/credentials.d.ts +15 -38
  14. package/dist/types/src/services/credentials.d.ts.map +1 -1
  15. package/dist/types/src/services/function-invocation-service.d.ts +1 -2
  16. package/dist/types/src/services/function-invocation-service.d.ts.map +1 -1
  17. package/dist/types/src/services/index.d.ts +0 -3
  18. package/dist/types/src/services/index.d.ts.map +1 -1
  19. package/dist/types/src/services/queues.d.ts +1 -49
  20. package/dist/types/src/services/queues.d.ts.map +1 -1
  21. package/dist/types/src/services/tracing.d.ts +1 -1
  22. package/dist/types/src/types/index.d.ts +0 -3
  23. package/dist/types/src/types/index.d.ts.map +1 -1
  24. package/dist/types/src/types/url.d.ts +1 -1
  25. package/dist/types/src/types/url.d.ts.map +1 -1
  26. package/dist/types/tsconfig.tsbuildinfo +1 -1
  27. package/package.json +15 -20
  28. package/src/index.ts +0 -6
  29. package/src/protocol/functions-ai-http-client.test.ts +105 -0
  30. package/src/protocol/functions-ai-http-client.ts +75 -1
  31. package/src/protocol/protocol.test.ts +10 -10
  32. package/src/protocol/protocol.ts +200 -45
  33. package/src/sdk.ts +5 -4
  34. package/src/services/credentials.ts +76 -120
  35. package/src/services/function-invocation-service.ts +1 -3
  36. package/src/services/index.ts +0 -3
  37. package/src/services/queues.ts +1 -87
  38. package/src/types/index.ts +0 -3
  39. package/src/types/url.ts +1 -1
  40. package/dist/lib/neutral/Trace.mjs +0 -42
  41. package/dist/lib/neutral/Trace.mjs.map +0 -7
  42. package/dist/lib/neutral/chunk-27Y24OTY.mjs +0 -167
  43. package/dist/lib/neutral/chunk-27Y24OTY.mjs.map +0 -7
  44. package/dist/lib/neutral/chunk-IVDUS56O.mjs +0 -49
  45. package/dist/lib/neutral/chunk-IVDUS56O.mjs.map +0 -7
  46. package/dist/lib/neutral/chunk-J5LGTIGS.mjs +0 -10
  47. package/dist/lib/neutral/chunk-J5LGTIGS.mjs.map +0 -7
  48. package/dist/lib/neutral/fib-N45KAC7C.mjs +0 -23
  49. package/dist/lib/neutral/fib-N45KAC7C.mjs.map +0 -7
  50. package/dist/lib/neutral/reply-EUEPKNJF.mjs +0 -19
  51. package/dist/lib/neutral/reply-EUEPKNJF.mjs.map +0 -7
  52. package/dist/lib/neutral/sleep-PUK3D4FF.mjs +0 -15
  53. package/dist/lib/neutral/sleep-PUK3D4FF.mjs.map +0 -7
  54. package/dist/types/src/Trace.d.ts +0 -174
  55. package/dist/types/src/Trace.d.ts.map +0 -1
  56. package/dist/types/src/errors.d.ts +0 -121
  57. package/dist/types/src/errors.d.ts.map +0 -1
  58. package/dist/types/src/example/definitions.d.ts +0 -11
  59. package/dist/types/src/example/definitions.d.ts.map +0 -1
  60. package/dist/types/src/example/fib.d.ts +0 -8
  61. package/dist/types/src/example/fib.d.ts.map +0 -1
  62. package/dist/types/src/example/forex-effect.d.ts +0 -3
  63. package/dist/types/src/example/forex-effect.d.ts.map +0 -1
  64. package/dist/types/src/example/index.d.ts +0 -4
  65. package/dist/types/src/example/index.d.ts.map +0 -1
  66. package/dist/types/src/example/reply.d.ts +0 -4
  67. package/dist/types/src/example/reply.d.ts.map +0 -1
  68. package/dist/types/src/example/sleep.d.ts +0 -6
  69. package/dist/types/src/example/sleep.d.ts.map +0 -1
  70. package/dist/types/src/process/Process.d.ts +0 -246
  71. package/dist/types/src/process/Process.d.ts.map +0 -1
  72. package/dist/types/src/process/ServiceResolver.d.ts +0 -74
  73. package/dist/types/src/process/ServiceResolver.d.ts.map +0 -1
  74. package/dist/types/src/process/StorageService.d.ts +0 -58
  75. package/dist/types/src/process/StorageService.d.ts.map +0 -1
  76. package/dist/types/src/services/event-logger.d.ts +0 -77
  77. package/dist/types/src/services/event-logger.d.ts.map +0 -1
  78. package/dist/types/src/types/Script.d.ts +0 -22
  79. package/dist/types/src/types/Script.d.ts.map +0 -1
  80. package/dist/types/src/types/Trigger.d.ts +0 -150
  81. package/dist/types/src/types/Trigger.d.ts.map +0 -1
  82. package/dist/types/src/types/TriggerEvent.d.ts +0 -75
  83. package/dist/types/src/types/TriggerEvent.d.ts.map +0 -1
  84. package/src/Trace.ts +0 -225
  85. package/src/errors.ts +0 -21
  86. package/src/example/definitions.ts +0 -49
  87. package/src/example/fib.ts +0 -23
  88. package/src/example/forex-effect.ts +0 -40
  89. package/src/example/index.ts +0 -12
  90. package/src/example/reply.ts +0 -19
  91. package/src/example/sleep.ts +0 -17
  92. package/src/process/Process.ts +0 -487
  93. package/src/process/ServiceResolver.ts +0 -174
  94. package/src/process/StorageService.ts +0 -99
  95. package/src/services/event-logger.ts +0 -111
  96. package/src/types/Script.ts +0 -38
  97. package/src/types/Trigger.ts +0 -207
  98. package/src/types/TriggerEvent.ts +0 -62
@@ -1,376 +1,12 @@
1
- import {
2
- EventType,
3
- OperationEnd,
4
- OperationStart,
5
- Trace_exports,
6
- write,
7
- writerLayerNoop
8
- } from "./chunk-27Y24OTY.mjs";
9
- import {
10
- Fibonacci,
11
- Reply,
12
- Sleep
13
- } from "./chunk-IVDUS56O.mjs";
14
- import {
15
- __export
16
- } from "./chunk-J5LGTIGS.mjs";
17
-
18
- // src/errors.ts
19
- import { BaseError } from "@dxos/errors";
20
- var ServiceNotAvailableError = class extends BaseError.extend("ServiceNotAvailable", "Service not available") {
21
- constructor(service, options) {
22
- super({
23
- context: {
24
- service
25
- },
26
- ...options,
27
- message: `Service not available: ${service}`
28
- });
29
- }
30
- };
31
- var FunctionNotFoundError = class extends BaseError.extend("FunctionNotFound", "Function not found") {
32
- constructor(functionKey, options) {
33
- super({
34
- context: {
35
- function: functionKey
36
- },
37
- ...options
38
- });
39
- }
40
- };
41
- var FunctionError = class extends BaseError.extend("FunctionError", "Function invocation error") {
42
- };
43
- var TriggerStateNotFoundError = class extends BaseError.extend("TriggerStateNotFound", "Trigger state not found") {
44
- };
45
-
46
- // src/example/index.ts
47
- import { OperationHandlerSet } from "@dxos/operation";
48
- var ExampleHandlers = OperationHandlerSet.lazy(() => import("./fib-N45KAC7C.mjs"), () => import("./reply-EUEPKNJF.mjs"), () => import("./sleep-PUK3D4FF.mjs"));
49
-
50
- // src/process/Process.ts
51
- var Process_exports = {};
52
- __export(Process_exports, {
53
- ExitedEvent: () => ExitedEvent,
54
- ID: () => ID,
55
- ProcessMonitorService: () => ProcessMonitorService,
56
- ProcessTypeId: () => ProcessTypeId,
57
- SpawnedEvent: () => SpawnedEvent,
58
- State: () => State,
59
- fromOperation: () => fromOperation,
60
- isProcess: () => isProcess,
61
- make: () => make,
62
- prettyProcessTree: () => prettyProcessTree
63
- });
64
- import * as Context from "effect/Context";
65
- import * as Effect from "effect/Effect";
66
- import * as Schema from "effect/Schema";
67
- import { assertArgument } from "@dxos/invariant";
68
- import { OperationHandlerSet as OperationHandlerSet2 } from "@dxos/operation";
69
- var ID = Schema.String.pipe(Schema.brand("ProcessId"));
70
- var ProcessTypeId = "~@dxos/functions/Process";
71
- var isProcess = (executable) => typeof executable === "object" && executable !== null && ProcessTypeId in executable;
72
- var make = (opts, create) => {
73
- assertArgument(/^[a-z0-9]([a-z0-9.\-/]*[a-z0-9])?$/i.test(opts.key), "key", "Invalid key");
74
- return {
75
- [ProcessTypeId]: {},
76
- ...opts,
77
- create: (ctx) => create(ctx).pipe(Effect.map((partial) => ({
78
- onSpawn: () => Effect.void,
79
- onInput: () => Effect.void,
80
- onAlarm: () => Effect.void,
81
- onChildEvent: () => Effect.void,
82
- ...partial
83
- })))
84
- };
85
- };
86
- var fromOperation = (op, handler) => make({
87
- key: op.meta.key,
88
- input: op.input,
89
- output: op.output,
90
- services: op.services
91
- }, (ctx) => Effect.gen(function* () {
92
- const semaphore = yield* Effect.makeSemaphore(1);
93
- return {
94
- onInput: (input) => Effect.gen(function* () {
95
- yield* write(OperationStart, {
96
- key: op.meta.key,
97
- name: op.meta.name
98
- });
99
- const opHandler = yield* OperationHandlerSet2.getHandler(handler, op).pipe(Effect.orDie);
100
- const output = yield* opHandler.handler(input).pipe(Effect.orDie, Effect.withSpan(op.meta.key));
101
- ctx.submitOutput(output);
102
- ctx.succeed();
103
- yield* write(OperationEnd, {
104
- key: op.meta.key,
105
- name: op.meta.name,
106
- outcome: "success"
107
- });
108
- }).pipe(Effect.catchAllDefect((defect) => Effect.gen(function* () {
109
- const errorMessage = defect instanceof Error ? defect.message : String(defect);
110
- yield* write(OperationEnd, {
111
- key: op.meta.key,
112
- name: op.meta.name,
113
- outcome: "failure",
114
- error: errorMessage
115
- });
116
- return yield* Effect.die(defect);
117
- })), semaphore.withPermits(1))
118
- };
119
- }));
120
- var State = /* @__PURE__ */ (function(State2) {
121
- State2["RUNNING"] = "RUNNING";
122
- State2["HYBERNATING"] = "HYBERNATING";
123
- State2["IDLE"] = "IDLE";
124
- State2["TERMINATING"] = "TERMINATING";
125
- State2["TERMINATED"] = "TERMINATED";
126
- State2["SUCCEEDED"] = "SUCCEEDED";
127
- State2["FAILED"] = "FAILED";
128
- return State2;
129
- })({});
130
- var ProcessMonitorService = class extends Context.Tag("@dxos/functions/ProcessMonitorService")() {
131
- };
132
- var SpawnedEvent = EventType("process.spawned", {
133
- schema: Schema.Void,
134
- isEphemeral: false
135
- });
136
- var ExitedEvent = EventType("process.exited", {
137
- schema: Schema.Struct({
138
- outcome: Schema.Literal("succeeded", "failed", "terminated")
139
- }),
140
- isEphemeral: false
141
- });
142
- var prettyProcessTree = (tree) => {
143
- if (tree.length === 0) {
144
- return "";
145
- }
146
- const pidSet = new Set(tree.map((node) => node.pid));
147
- const childrenByParent = /* @__PURE__ */ new Map();
148
- const roots = [];
149
- for (const node of tree) {
150
- const parent = node.parentPid;
151
- if (parent === null || !pidSet.has(parent)) {
152
- roots.push(node);
153
- continue;
154
- }
155
- const key2 = String(parent);
156
- const siblings = childrenByParent.get(key2) ?? [];
157
- siblings.push(node);
158
- childrenByParent.set(key2, siblings);
159
- }
160
- const byPid = (a, b) => String(a.pid).localeCompare(String(b.pid));
161
- roots.sort(byPid);
162
- for (const siblings of childrenByParent.values()) {
163
- siblings.sort(byPid);
164
- }
165
- const formatLabel = (node) => {
166
- const idShort = String(node.pid).slice(0, 6);
167
- const parts = [
168
- idShort,
169
- node.state
170
- ];
171
- if (node.params.name != null && node.params.name !== "") {
172
- parts.push(node.params.name);
173
- }
174
- if (node.error != null) {
175
- parts.push(`(${node.error})`);
176
- }
177
- const { inputCount, outputCount, wallTime } = node.metrics;
178
- parts.push(`[in:${inputCount} out:${outputCount} wall:${Math.round(wallTime)}ms]`);
179
- return parts.join(" ");
180
- };
181
- const lines = [];
182
- const walk = (node, prefix, isLast, isRoot) => {
183
- if (isRoot) {
184
- lines.push(`- ${formatLabel(node)}`);
185
- } else {
186
- const branch = isLast ? "\u2514\u2500\u2500 " : "\u251C\u2500\u2500 ";
187
- lines.push(`${prefix}${branch}${formatLabel(node)}`);
188
- }
189
- const children = childrenByParent.get(String(node.pid)) ?? [];
190
- const nextPrefix = isRoot ? " " : `${prefix}${isLast ? " " : "\u2502 "}`;
191
- children.forEach((child, index) => {
192
- walk(child, nextPrefix, index === children.length - 1, false);
193
- });
194
- };
195
- for (const root of roots) {
196
- walk(root, "", true, true);
197
- }
198
- return lines.join("\n");
199
- };
200
-
201
- // src/process/ServiceResolver.ts
202
- var ServiceResolver_exports = {};
203
- __export(ServiceResolver_exports, {
204
- ServiceResolver: () => ServiceResolver,
205
- compose: () => compose,
206
- empty: () => empty2,
207
- fromContext: () => fromContext,
208
- fromRequirements: () => fromRequirements,
209
- layerRequirements: () => layerRequirements,
210
- make: () => make3,
211
- resolve: () => resolve,
212
- resolveAll: () => resolveAll,
213
- succeed: () => succeed
214
- });
215
- import * as Context2 from "effect/Context";
216
- import * as Effect2 from "effect/Effect";
217
- import * as Either from "effect/Either";
218
- import * as Layer from "effect/Layer";
219
- import * as Option from "effect/Option";
220
- var ServiceResolverTypeId = "~@dxos/functions/ServiceResolver";
221
- var ServiceResolver = Context2.GenericTag("@dxos/functions/ServiceResolver");
222
- var resolve = Effect2.serviceFunctionEffect(ServiceResolver, (_) => _.resolve);
223
- var resolveAll = (tags, context) => Effect2.gen(function* () {
224
- const services = yield* Effect2.forEach(tags, (tag) => resolve(tag, context).pipe(Effect2.map((service) => Context2.make(tag, service))));
225
- return Context2.mergeAll(...services);
226
- });
227
- var succeed = (tag, getService) => {
228
- return make3((tag1, context) => {
229
- if (tag1.key !== tag.key) {
230
- return Effect2.fail(new ServiceNotAvailableError(`Service not available: ${String(tag.key ?? tag)}`));
231
- }
232
- const service = getService(context);
233
- return service;
234
- });
235
- };
236
- var make3 = (resolveFn) => ({
237
- [ServiceResolverTypeId]: ServiceResolverTypeId,
238
- resolve: resolveFn
239
- });
240
- var fromContext = (ctx) => make3((tag, context) => Effect2.gen(function* () {
241
- const service = Context2.getOption(ctx, tag);
242
- if (Option.isNone(service)) {
243
- return yield* Effect2.fail(new ServiceNotAvailableError(String(tag.key ?? tag)));
244
- }
245
- return service.value;
246
- }));
247
- var fromRequirements = (...tags) => Effect2.contextWith((parentCtx) => {
248
- const available = new Set(tags.map((tag) => tag.key));
249
- return make3((tag, context) => Effect2.gen(function* () {
250
- let result = Context2.empty();
251
- if (!available.has(tag.key)) {
252
- return yield* Effect2.fail(new ServiceNotAvailableError(String(tag.key ?? tag)));
253
- }
254
- const service = Context2.getOption(parentCtx, tag);
255
- if (Option.isNone(service)) {
256
- return yield* Effect2.fail(new ServiceNotAvailableError(String(tag.key ?? tag)));
257
- }
258
- return service.value;
259
- }));
260
- });
261
- var layerRequirements = (...tags) => Layer.effect(ServiceResolver, fromRequirements(...tags));
262
- var compose = (...resolvers) => make3((tag, context) => Effect2.gen(function* () {
263
- for (const resolver of resolvers) {
264
- const single = yield* resolver.resolve(tag, context).pipe(Effect2.either);
265
- if (Either.isRight(single)) {
266
- return single.right;
267
- }
268
- }
269
- return yield* Effect2.fail(new ServiceNotAvailableError(String(tag.key ?? tag)));
270
- }));
271
- var empty2 = make3((tag, context) => {
272
- return Effect2.fail(new ServiceNotAvailableError(String(tag.key ?? tag)));
273
- });
274
-
275
- // src/process/StorageService.ts
276
- import * as Context3 from "effect/Context";
277
- import * as Effect3 from "effect/Effect";
278
- import * as Option2 from "effect/Option";
279
- import * as Pipeable from "effect/Pipeable";
280
- var StorageService = class extends Context3.Tag("@dxos/functions/StorageService")() {
281
- };
282
- var get = Effect3.serviceFunctionEffect(StorageService, (_) => _.get);
283
- var set = Effect3.serviceFunctionEffect(StorageService, (_) => _.set);
284
- var deleteKey = Effect3.serviceFunctionEffect(StorageService, (_) => _.delete);
285
- var list = Effect3.serviceFunctionEffect(StorageService, (_) => _.list);
286
- var clear = Effect3.serviceFunctionEffect(StorageService, (_) => _.clear);
287
- var key = (schema, key2) => {
288
- return {
289
- key: key2,
290
- get: get(schema, key2),
291
- set: (value2) => set(schema, key2, value2),
292
- delete: () => deleteKey(key2),
293
- pipe(...args) {
294
- return Pipeable.pipeArguments(this, arguments);
295
- }
296
- };
297
- };
298
- var withDefault = (getDefault) => (key2) => {
299
- return {
300
- key: key2.key,
301
- get: key2.get.pipe(Effect3.map(Option2.getOrElse(() => getDefault()))),
302
- set: (value2) => key2.set(value2),
303
- delete: () => key2.delete(),
304
- pipe(...args) {
305
- return Pipeable.pipeArguments(this, arguments);
306
- }
307
- };
308
- };
309
-
310
1
  // src/services/credentials.ts
311
2
  import * as HttpClient from "@effect/platform/HttpClient";
312
3
  import * as HttpClientRequest from "@effect/platform/HttpClientRequest";
313
- import * as Context4 from "effect/Context";
314
- import * as Effect4 from "effect/Effect";
315
- import * as Layer2 from "effect/Layer";
4
+ import * as Effect from "effect/Effect";
5
+ import * as Layer from "effect/Layer";
316
6
  import * as Redacted from "effect/Redacted";
317
- import { Query } from "@dxos/echo";
318
- import { Database } from "@dxos/echo";
7
+ import { Credential } from "@dxos/compute";
8
+ import { Database, Query } from "@dxos/echo";
319
9
  import { AccessToken } from "@dxos/types";
320
- var CredentialsService = class _CredentialsService extends Context4.Tag("@dxos/functions/CredentialsService")() {
321
- static getCredential = (query) => Effect4.gen(function* () {
322
- const credentials = yield* _CredentialsService;
323
- return yield* Effect4.promise(() => credentials.getCredential(query));
324
- });
325
- static getApiKey = (query) => Effect4.gen(function* () {
326
- const credential = yield* _CredentialsService.getCredential(query);
327
- if (!credential.apiKey) {
328
- throw new Error(`API key not found for service: ${query.service}`);
329
- }
330
- return Redacted.make(credential.apiKey);
331
- });
332
- static configuredLayer = (credentials) => Layer2.succeed(_CredentialsService, new ConfiguredCredentialsService(credentials));
333
- static layerConfig = (credentials) => Layer2.effect(_CredentialsService, Effect4.gen(function* () {
334
- const serviceCredentials = yield* Effect4.forEach(credentials, ({ service, apiKey }) => Effect4.gen(function* () {
335
- return {
336
- service,
337
- apiKey: Redacted.value(yield* apiKey)
338
- };
339
- }));
340
- return new ConfiguredCredentialsService(serviceCredentials);
341
- }));
342
- static layerFromDatabase = ({ caching = false } = {}) => Layer2.effect(_CredentialsService, Effect4.gen(function* () {
343
- const dbService = yield* Database.Service;
344
- const cache = /* @__PURE__ */ new Map();
345
- const queryCredentials = async (query) => {
346
- const cacheKey = JSON.stringify(query);
347
- if (caching && cache.has(cacheKey)) {
348
- return cache.get(cacheKey);
349
- }
350
- const accessTokens = await dbService.db.query(Query.type(AccessToken.AccessToken)).run();
351
- const credentials = accessTokens.filter((accessToken) => accessToken.source === query.service).map((accessToken) => ({
352
- service: accessToken.source,
353
- apiKey: accessToken.token
354
- }));
355
- if (caching) {
356
- cache.set(cacheKey, credentials);
357
- }
358
- return credentials;
359
- };
360
- return {
361
- getCredential: async (query) => {
362
- const credentials = await queryCredentials(query);
363
- if (credentials.length === 0) {
364
- throw new Error(`Credential not found for service: ${query.service}`);
365
- }
366
- return credentials[0];
367
- },
368
- queryCredentials: async (query) => {
369
- return queryCredentials(query);
370
- }
371
- };
372
- }));
373
- };
374
10
  var ConfiguredCredentialsService = class {
375
11
  credentials;
376
12
  constructor(credentials = []) {
@@ -395,430 +31,77 @@ var withAuthorization = (token, kind) => HttpClient.mapRequest((request) => {
395
31
  const authorization = kind ? `${kind} ${token}` : token;
396
32
  return HttpClientRequest.setHeader(request, "Authorization", authorization);
397
33
  });
398
-
399
- // src/services/event-logger.ts
400
- import * as Context5 from "effect/Context";
401
- import * as Effect5 from "effect/Effect";
402
- import * as Layer3 from "effect/Layer";
403
- import * as Schema2 from "effect/Schema";
404
- import { Type } from "@dxos/echo";
405
- import { invariant } from "@dxos/invariant";
406
- import { LogLevel, log } from "@dxos/log";
407
- var __dxlog_file = "/__w/dxos/dxos/packages/core/functions/src/services/event-logger.ts";
408
- var ComputeEventPayload = Schema2.Union(Schema2.Struct({
409
- type: Schema2.Literal("begin-compute"),
410
- nodeId: Schema2.String,
411
- /**
412
- * Names of the inputs begin computed.
413
- */
414
- inputs: Schema2.Array(Schema2.String)
415
- }), Schema2.Struct({
416
- type: Schema2.Literal("end-compute"),
417
- nodeId: Schema2.String,
418
- /**
419
- * Names of the outputs computed.
420
- */
421
- outputs: Schema2.Array(Schema2.String)
422
- }), Schema2.Struct({
423
- type: Schema2.Literal("compute-input"),
424
- nodeId: Schema2.String,
425
- property: Schema2.String,
426
- value: Schema2.Any
427
- }), Schema2.Struct({
428
- type: Schema2.Literal("compute-output"),
429
- nodeId: Schema2.String,
430
- property: Schema2.String,
431
- value: Schema2.Any
432
- }), Schema2.Struct({
433
- type: Schema2.Literal("custom"),
434
- nodeId: Schema2.String,
435
- event: Schema2.Any
436
- }));
437
- var ComputeEvent = Schema2.Struct({
438
- payload: ComputeEventPayload
439
- }).pipe(Type.object({
440
- typename: "org.dxos.type.computeEvent",
441
- version: "0.1.0"
34
+ var configuredCredentialsLayer = (credentials) => Layer.succeed(Credential.CredentialsService, new ConfiguredCredentialsService(credentials));
35
+ var credentialsLayerConfig = (credentials) => Layer.effect(Credential.CredentialsService, Effect.gen(function* () {
36
+ const serviceCredentials = yield* Effect.forEach(credentials, ({ service, apiKey }) => Effect.gen(function* () {
37
+ return {
38
+ service,
39
+ apiKey: Redacted.value(yield* apiKey)
40
+ };
41
+ }));
42
+ return new ConfiguredCredentialsService(serviceCredentials);
442
43
  }));
443
- var ComputeEventLogger = class _ComputeEventLogger extends Context5.Tag("@dxos/functions/ComputeEventLogger")() {
444
- static noop = {
445
- log: () => {
446
- },
447
- nodeId: void 0
44
+ var credentialsLayerFromDatabase = ({ caching = false } = {}) => Layer.effect(Credential.CredentialsService, Effect.gen(function* () {
45
+ const dbService = yield* Database.Service;
46
+ const cache = /* @__PURE__ */ new Map();
47
+ const queryCredentials = async (query) => {
48
+ const cacheKey = JSON.stringify(query);
49
+ if (caching && cache.has(cacheKey)) {
50
+ return cache.get(cacheKey);
51
+ }
52
+ const accessTokens = await dbService.db.query(Query.type(AccessToken.AccessToken)).run();
53
+ const credentials = accessTokens.filter((accessToken) => accessToken.source === query.service).map((accessToken) => ({
54
+ service: accessToken.source,
55
+ apiKey: accessToken.token
56
+ }));
57
+ if (caching) {
58
+ cache.set(cacheKey, credentials);
59
+ }
60
+ return credentials;
448
61
  };
449
- static layerNoop = Layer3.succeed(_ComputeEventLogger, _ComputeEventLogger.noop);
450
- };
451
- var logCustomEvent = (data) => Effect5.gen(function* () {
452
- const logger = yield* ComputeEventLogger;
453
- if (!logger.nodeId) {
454
- throw new Error("logCustomEvent must be called within a node compute function");
455
- }
456
- logger.log({
457
- type: "custom",
458
- nodeId: logger.nodeId,
459
- event: data
460
- });
461
- });
462
- var createDefectLogger = () => Effect5.catchAll((error) => Effect5.gen(function* () {
463
- log.error("unhandled effect error", {
464
- error
465
- }, {
466
- F: __dxlog_file,
467
- L: 86,
468
- S: this,
469
- C: (f, a) => f(...a)
470
- });
471
- throw error;
472
- }));
473
- var createEventLogger = (level, message = "event") => {
474
- const logFunction = {
475
- [LogLevel.WARN]: log.warn,
476
- [LogLevel.VERBOSE]: log.verbose,
477
- [LogLevel.DEBUG]: log.debug,
478
- [LogLevel.INFO]: log.info,
479
- [LogLevel.ERROR]: log.error
480
- }[level];
481
- invariant(logFunction, void 0, {
482
- F: __dxlog_file,
483
- L: 104,
484
- S: void 0,
485
- A: [
486
- "logFunction",
487
- ""
488
- ]
489
- });
490
62
  return {
491
- log: (event) => {
492
- logFunction(message, event);
63
+ getCredential: async (query) => {
64
+ const credentials = await queryCredentials(query);
65
+ if (credentials.length === 0) {
66
+ throw new Error(`Credential not found for service: ${query.service}`);
67
+ }
68
+ return credentials[0];
493
69
  },
494
- nodeId: void 0
70
+ queryCredentials: async (query) => {
71
+ return queryCredentials(query);
72
+ }
495
73
  };
496
- };
74
+ }));
497
75
 
498
76
  // src/services/function-invocation-service.ts
499
- import * as Context6 from "effect/Context";
500
- import * as Effect6 from "effect/Effect";
501
- import * as Layer4 from "effect/Layer";
502
- var FunctionInvocationService = class _FunctionInvocationService extends Context6.Tag("@dxos/functions/FunctionInvocationService")() {
503
- static layerNotAvailable = Layer4.succeed(_FunctionInvocationService, {
504
- invokeFunction: () => Effect6.die("FunctionInvocationService is not avaialble."),
505
- resolveFunction: () => Effect6.die("FunctionInvocationService is not available.")
77
+ import * as Context from "effect/Context";
78
+ import * as Effect2 from "effect/Effect";
79
+ import * as Layer2 from "effect/Layer";
80
+ var FunctionInvocationService = class _FunctionInvocationService extends Context.Tag("@dxos/functions/FunctionInvocationService")() {
81
+ static layerNotAvailable = Layer2.succeed(_FunctionInvocationService, {
82
+ invokeFunction: () => Effect2.die("FunctionInvocationService is not avaialble."),
83
+ resolveFunction: () => Effect2.die("FunctionInvocationService is not available.")
506
84
  });
507
- static invokeFunction = (functionDef, input) => Effect6.serviceFunctionEffect(_FunctionInvocationService, (service) => service.invokeFunction)(functionDef, input);
508
- static resolveFunction = (key2) => Effect6.serviceFunctionEffect(_FunctionInvocationService, (service) => service.resolveFunction)(key2);
85
+ static invokeFunction = (functionDef, input) => Effect2.serviceFunctionEffect(_FunctionInvocationService, (service) => service.invokeFunction)(functionDef, input);
86
+ static resolveFunction = (key) => Effect2.serviceFunctionEffect(_FunctionInvocationService, (service) => service.resolveFunction)(key);
509
87
  };
510
88
 
511
89
  // src/services/queues.ts
512
- import * as Context7 from "effect/Context";
513
- import * as Effect7 from "effect/Effect";
514
- import * as Layer5 from "effect/Layer";
515
- import { createFeedServiceLayer } from "@dxos/echo-db";
516
- var QueueService = class _QueueService extends Context7.Tag("@dxos/functions/QueueService")() {
517
- static notAvailable = Layer5.succeed(_QueueService, {
518
- queues: {
519
- get(_dxn) {
520
- throw new Error("Queues not available");
521
- },
522
- create() {
523
- throw new Error("Queues not available");
524
- }
525
- },
526
- queue: void 0
527
- });
528
- static make = (queues, queue) => {
529
- return {
530
- queues,
531
- queue
532
- };
533
- };
534
- static layer = (queues, queue) => Layer5.succeed(_QueueService, _QueueService.make(queues, queue));
535
- /**
536
- * Gets a queue by its DXN.
537
- */
538
- static getQueue = (dxn) => _QueueService.pipe(Effect7.map(({ queues }) => queues.get(dxn)));
539
- /**
540
- * Creates a new queue.
541
- */
542
- static createQueue = (options) => _QueueService.pipe(Effect7.map(({ queues }) => queues.create(options)));
543
- static append = (queue, objects) => Effect7.promise(() => queue.append(objects));
544
- };
545
- var ContextQueueService = class _ContextQueueService extends Context7.Tag("@dxos/functions/ContextQueueService")() {
546
- static layer = (queue) => Layer5.succeed(_ContextQueueService, {
547
- queue
548
- });
549
- };
550
- var feedServiceFromQueueServiceLayer = Layer5.unwrapEffect(Effect7.gen(function* () {
551
- const { queues } = yield* QueueService;
552
- return createFeedServiceLayer(queues);
553
- }));
90
+ import { QueueService, feedServiceFromQueueServiceLayer } from "@dxos/echo-db";
554
91
 
555
92
  // src/services/tracing.ts
556
93
  var MESSAGE_PROPERTY_TOOL_CALL_ID = "toolCallId";
557
94
 
558
- // src/types/Script.ts
559
- var Script_exports = {};
560
- __export(Script_exports, {
561
- Script: () => Script,
562
- make: () => make5
563
- });
564
- import * as Schema3 from "effect/Schema";
565
- import { Annotation, Obj, Ref, Type as Type2 } from "@dxos/echo";
566
- import { FormInputAnnotation } from "@dxos/echo/internal";
567
- import { Text } from "@dxos/schema";
568
- var Script = Schema3.Struct({
569
- name: Schema3.String.pipe(Schema3.optional),
570
- description: Schema3.String.pipe(Schema3.optional),
571
- // TODO(burdon): Change to hash of deployed content.
572
- // Whether source has changed since last deploy.
573
- changed: Schema3.Boolean.pipe(FormInputAnnotation.set(false), Schema3.optional),
574
- source: Ref.Ref(Text.Text).pipe(FormInputAnnotation.set(false))
575
- }).pipe(Type2.object({
576
- typename: "org.dxos.type.script",
577
- version: "0.1.0"
578
- }), Annotation.LabelAnnotation.set([
579
- "name"
580
- ]), Annotation.IconAnnotation.set({
581
- icon: "ph--code--regular",
582
- hue: "sky"
583
- }));
584
- var make5 = ({ source = "", ...props } = {}) => Obj.make(Script, {
585
- ...props,
586
- source: Ref.make(Text.make({
587
- content: source
588
- }))
589
- });
590
-
591
- // src/types/Trigger.ts
592
- var Trigger_exports = {};
593
- __export(Trigger_exports, {
594
- EmailSpec: () => EmailSpec,
595
- Kinds: () => Kinds,
596
- QueueSpec: () => QueueSpec,
597
- Spec: () => Spec,
598
- SubscriptionSpec: () => SubscriptionSpec,
599
- TimerSpec: () => TimerSpec,
600
- Trigger: () => Trigger,
601
- WebhookSpec: () => WebhookSpec,
602
- make: () => make6,
603
- specEmail: () => specEmail,
604
- specFeed: () => specFeed,
605
- specQueue: () => specQueue,
606
- specSubscription: () => specSubscription,
607
- specTimer: () => specTimer,
608
- specWebhook: () => specWebhook
609
- });
610
- import * as Schema4 from "effect/Schema";
611
- import * as SchemaAST from "effect/SchemaAST";
612
- import { Annotation as Annotation2, Feed, Obj as Obj2, QueryAST, Ref as Ref2, Type as Type3 } from "@dxos/echo";
613
- import { OptionsAnnotationId, SystemTypeAnnotation } from "@dxos/echo/internal";
614
- import { failedInvariant } from "@dxos/invariant";
615
- import { DXN } from "@dxos/keys";
616
- var Kinds = [
617
- "email",
618
- "queue",
619
- "subscription",
620
- "timer",
621
- "webhook"
622
- ];
623
- var kindLiteralAnnotations = {
624
- title: "Kind"
625
- };
626
- var EmailSpec = Schema4.Struct({
627
- kind: Schema4.Literal("email").annotations(kindLiteralAnnotations)
628
- });
629
- var specEmail = () => ({
630
- kind: "email"
631
- });
632
- var QueueSpec = Schema4.Struct({
633
- kind: Schema4.Literal("queue").annotations(kindLiteralAnnotations),
634
- // TODO(dmaretskyi): Rename to `feed` and change to a reference.
635
- queue: DXN.Schema
636
- });
637
- var specQueue = (queueDxn) => ({
638
- kind: "queue",
639
- queue: queueDxn
640
- });
641
- var specFeed = (feed) => specQueue(Feed.getQueueDxn(feed)?.toString() ?? failedInvariant(new Error("Could not extract DXN from feed")));
642
- var SubscriptionSpec = Schema4.Struct({
643
- kind: Schema4.Literal("subscription").annotations(kindLiteralAnnotations),
644
- query: Schema4.Struct({
645
- raw: Schema4.optional(Schema4.String.annotations({
646
- title: "Query"
647
- })),
648
- ast: QueryAST.Query
649
- }),
650
- options: Schema4.optional(Schema4.Struct({
651
- // Watch changes to object (not just creation).
652
- deep: Schema4.optional(Schema4.Boolean.annotations({
653
- title: "Nested"
654
- })),
655
- // Debounce changes (delay in ms).
656
- delay: Schema4.optional(Schema4.Number.annotations({
657
- title: "Delay"
658
- }))
659
- }).annotations({
660
- title: "Options"
661
- }))
662
- });
663
- var specSubscription = (query, options) => ({
664
- kind: "subscription",
665
- query: {
666
- ast: query.ast
667
- },
668
- options: options ? {
669
- deep: options.deep,
670
- delay: options.delay
671
- } : void 0
672
- });
673
- var TimerSpec = Schema4.Struct({
674
- kind: Schema4.Literal("timer").annotations(kindLiteralAnnotations),
675
- cron: Schema4.String.annotations({
676
- title: "Cron",
677
- [SchemaAST.ExamplesAnnotationId]: [
678
- "0 0 * * *"
679
- ]
680
- })
681
- });
682
- var specTimer = (cron) => ({
683
- kind: "timer",
684
- cron
685
- });
686
- var WebhookSpec = Schema4.Struct({
687
- kind: Schema4.Literal("webhook").annotations(kindLiteralAnnotations),
688
- method: Schema4.optional(Schema4.String.annotations({
689
- title: "Method",
690
- [OptionsAnnotationId]: [
691
- "GET",
692
- "POST"
693
- ]
694
- })),
695
- port: Schema4.optional(Schema4.Number.annotations({
696
- title: "Port"
697
- }))
698
- });
699
- var specWebhook = (opts) => ({
700
- kind: "webhook",
701
- method: opts?.method,
702
- port: opts?.port
703
- });
704
- var Spec = Schema4.Union(EmailSpec, QueueSpec, SubscriptionSpec, TimerSpec, WebhookSpec).annotations({
705
- title: "Trigger"
706
- });
707
- var TriggerSchema = Schema4.Struct({
708
- /**
709
- * Function or workflow to invoke.
710
- */
711
- // TODO(dmaretskyi): Can be a Ref(FunctionType) or Ref(ComputeGraphType).
712
- function: Schema4.optional(Ref2.Ref(Obj2.Unknown).annotations({
713
- title: "Function"
714
- })),
715
- /**
716
- * Only used for workflowSchema.
717
- * Specifies the input node in the circuit.
718
- * @deprecated Remove and enforce a single input node in all compute graphSchema.
719
- */
720
- inputNodeId: Schema4.optional(Schema4.String.annotations({
721
- title: "Input Node ID"
722
- })),
723
- // TODO(burdon): NO BOOLEAN PROPERTIES (enabld/disabled/paused, etc.)
724
- // Need lint rule; or agent rule to require PR review for "boolean" key word.
725
- enabled: Schema4.optional(Schema4.Boolean.annotations({
726
- title: "Enabled"
727
- })),
728
- spec: Schema4.optional(Spec),
729
- concurrency: Schema4.optional(Schema4.Number.annotations({
730
- title: "Concurrency",
731
- default: 1,
732
- description: "Maximum number of concurrent invocations of the trigger. For Feed triggers, this will process Feed items in parallel."
733
- })),
734
- /**
735
- * Passed as the input data to the function.
736
- * Must match the function's input schema.
737
- *
738
- * @example
739
- * {
740
- * item: '{{event.item}}',
741
- * instructions: 'Summarize and perform entity-extraction'
742
- * mailbox: { '/': 'dxn:echo:AAA:ZZZ' }
743
- * }
744
- */
745
- input: Schema4.optional(Schema4.Record({
746
- key: Schema4.String,
747
- value: Schema4.Any
748
- }))
749
- }).pipe(Type3.object({
750
- typename: "org.dxos.type.trigger",
751
- version: "0.1.0"
752
- }), Annotation2.IconAnnotation.set({
753
- icon: "ph--lightning--regular",
754
- hue: "yellow"
755
- }), SystemTypeAnnotation.set(true));
756
- var Trigger = TriggerSchema;
757
- var make6 = (props) => Obj2.make(Trigger, props);
758
-
759
- // src/types/TriggerEvent.ts
760
- var TriggerEvent_exports = {};
761
- __export(TriggerEvent_exports, {
762
- EmailEvent: () => EmailEvent,
763
- QueueEvent: () => QueueEvent,
764
- SubscriptionEvent: () => SubscriptionEvent,
765
- TimerEvent: () => TimerEvent,
766
- TriggerEvent: () => TriggerEvent,
767
- WebhookEvent: () => WebhookEvent
768
- });
769
- import * as Schema5 from "effect/Schema";
770
- import { DXN as DXN2, Obj as Obj3, Ref as Ref3 } from "@dxos/echo";
771
- var EmailEvent = Schema5.Struct({
772
- from: Schema5.String,
773
- to: Schema5.String,
774
- subject: Schema5.String,
775
- created: Schema5.String,
776
- body: Schema5.String
777
- });
778
- var QueueEvent = Schema5.Struct({
779
- queue: DXN2.Schema,
780
- item: Schema5.Any,
781
- cursor: Schema5.String
782
- });
783
- var SubscriptionEvent = Schema5.Struct({
784
- /**
785
- * Type of the mutation.
786
- */
787
- // TODO(dmaretskyi): Specify enum.
788
- type: Schema5.String,
789
- /**
790
- * Reference to the object that was changed or created.
791
- */
792
- subject: Ref3.Ref(Obj3.Unknown),
793
- /**
794
- * @deprecated
795
- */
796
- changedObjectId: Schema5.optional(Schema5.String)
797
- });
798
- var TimerEvent = Schema5.Struct({
799
- tick: Schema5.Number
800
- });
801
- var WebhookEvent = Schema5.Struct({
802
- url: Schema5.String,
803
- method: Schema5.Literal("GET", "POST"),
804
- headers: Schema5.Record({
805
- key: Schema5.String,
806
- value: Schema5.String
807
- }),
808
- bodyText: Schema5.String
809
- });
810
- var TriggerEvent = Schema5.Union(EmailEvent, QueueEvent, SubscriptionEvent, TimerEvent, WebhookEvent);
811
-
812
95
  // src/types/url.ts
813
96
  var FUNCTIONS_META_KEY = "org.dxos.service.function";
814
97
  var FUNCTIONS_PRESET_META_KEY = "org.dxos.service.function-preset";
815
98
  var getUserFunctionIdInMetadata = (meta) => {
816
- return meta.keys.find((key2) => key2.source === FUNCTIONS_META_KEY)?.id;
99
+ return meta.keys.find((key) => key.source === FUNCTIONS_META_KEY)?.id;
817
100
  };
818
101
  var setUserFunctionIdInMetadata = (meta, functionId) => {
819
- const key2 = meta.keys.find((key3) => key3.source === FUNCTIONS_META_KEY);
820
- if (key2) {
821
- if (key2.id !== functionId) {
102
+ const key = meta.keys.find((key2) => key2.source === FUNCTIONS_META_KEY);
103
+ if (key) {
104
+ if (key.id !== functionId) {
822
105
  throw new Error("Metadata mismatch");
823
106
  }
824
107
  } else {
@@ -831,40 +114,44 @@ var setUserFunctionIdInMetadata = (meta, functionId) => {
831
114
 
832
115
  // src/protocol/protocol.ts
833
116
  import * as AnthropicClient from "@effect/ai-anthropic/AnthropicClient";
834
- import * as Effect9 from "effect/Effect";
835
- import * as Layer7 from "effect/Layer";
836
- import * as Schema6 from "effect/Schema";
837
- import * as SchemaAST2 from "effect/SchemaAST";
838
- import { AiModelResolver, AiService } from "@dxos/ai";
117
+ import * as Effect4 from "effect/Effect";
118
+ import * as Layer4 from "effect/Layer";
119
+ import * as Option from "effect/Option";
120
+ import * as Schema from "effect/Schema";
121
+ import * as SchemaAST from "effect/SchemaAST";
122
+ import { AiModelResolver, AiService, OpaqueToolkit } from "@dxos/ai";
839
123
  import { AnthropicResolver } from "@dxos/ai/resolvers";
124
+ import { FunctionError, InvalidOperationInputError, InvalidOperationOutputError, Operation, OperationRegistry, Trace } from "@dxos/compute";
840
125
  import { LifecycleState, Resource } from "@dxos/context";
841
- import { Database as Database2, Feed as Feed2, JsonSchema, Ref as Ref4 } from "@dxos/echo";
842
- import { EchoClient, createFeedServiceLayer as createFeedServiceLayer2 } from "@dxos/echo-db";
126
+ import { Database as Database2, Feed, JsonSchema, Ref } from "@dxos/echo";
127
+ import { createFeedServiceLayer, EchoClient } from "@dxos/echo-db";
843
128
  import { refFromEncodedReference } from "@dxos/echo/internal";
844
129
  import { runAndForwardErrors } from "@dxos/effect";
845
- import { assertState, failedInvariant as failedInvariant2, invariant as invariant2 } from "@dxos/invariant";
130
+ import { assertState, failedInvariant, invariant } from "@dxos/invariant";
846
131
  import { PublicKey } from "@dxos/keys";
847
- import { Operation } from "@dxos/operation";
132
+ import { log as log2 } from "@dxos/log";
133
+ import { ErrorCodec as ErrorCodec2 } from "@dxos/protocols";
848
134
 
849
135
  // src/protocol/functions-ai-http-client.ts
850
136
  import * as Headers from "@effect/platform/Headers";
851
137
  import * as HttpClient2 from "@effect/platform/HttpClient";
852
138
  import * as HttpClientError from "@effect/platform/HttpClientError";
853
139
  import * as HttpClientResponse from "@effect/platform/HttpClientResponse";
854
- import * as Effect8 from "effect/Effect";
140
+ import * as Effect3 from "effect/Effect";
855
141
  import * as FiberRef from "effect/FiberRef";
856
- import * as Layer6 from "effect/Layer";
142
+ import * as Layer3 from "effect/Layer";
857
143
  import * as Stream from "effect/Stream";
858
- import { log as log2 } from "@dxos/log";
144
+ import { FunctionsAiMemoizationMissError, FunctionsAiUpstreamError } from "@dxos/compute";
145
+ import { log } from "@dxos/log";
859
146
  import { ErrorCodec } from "@dxos/protocols";
860
- var __dxlog_file2 = "/__w/dxos/dxos/packages/core/functions/src/protocol/functions-ai-http-client.ts";
147
+ var __dxlog_file = "/__w/dxos/dxos/packages/core/compute/functions/src/protocol/functions-ai-http-client.ts";
861
148
  var requestInitTagKey = "@effect/platform/FetchHttpClient/FetchOptions";
862
149
  var FunctionsAiHttpClient = class _FunctionsAiHttpClient {
863
150
  static make = (service) => HttpClient2.make((request, url, signal, fiber) => {
864
151
  const context = fiber.getFiberRef(FiberRef.currentContext);
865
152
  const options = context.unsafeMap.get(requestInitTagKey) ?? {};
866
153
  const headers = options.headers ? Headers.merge(Headers.fromInput(options.headers), request.headers) : request.headers;
867
- const send = (body) => Effect8.tryPromise({
154
+ const send = (body) => Effect3.tryPromise({
868
155
  try: () => service.fetch(new Request(url, {
869
156
  ...options,
870
157
  method: request.method,
@@ -872,21 +159,21 @@ var FunctionsAiHttpClient = class _FunctionsAiHttpClient {
872
159
  body
873
160
  })),
874
161
  catch: (cause) => {
875
- log2.error("Failed to fetch", {
162
+ log.error("Failed to fetch", {
876
163
  errorSerialized: ErrorCodec.encode(cause)
877
- }, {
878
- F: __dxlog_file2,
879
- L: 43,
880
- S: this,
881
- C: (f, a) => f(...a)
882
- });
164
+ }, { "~LogMeta": "~LogMeta", F: __dxlog_file, L: 31, S: this });
883
165
  return new HttpClientError.RequestError({
884
166
  request,
885
167
  reason: "Transport",
886
168
  cause
887
169
  });
888
170
  }
889
- }).pipe(Effect8.map((response) => HttpClientResponse.fromWeb(request, response)));
171
+ }).pipe(Effect3.flatMap((response) => (
172
+ // Inspect the body before handing the response to `@effect/ai` so that structured
173
+ // upstream errors surface as typed defects (`FunctionsAiUpstreamError` and friends)
174
+ // rather than as the generic `HttpResponseError` from `@effect/ai/AiError`.
175
+ Effect3.flatMap(Effect3.promise(() => parseUpstreamError(response)), (typedError) => typedError ? Effect3.die(typedError) : Effect3.succeed(HttpClientResponse.fromWeb(request, response)))
176
+ )));
890
177
  switch (request.body._tag) {
891
178
  case "Raw":
892
179
  case "Uint8Array":
@@ -894,14 +181,54 @@ var FunctionsAiHttpClient = class _FunctionsAiHttpClient {
894
181
  case "FormData":
895
182
  return send(request.body.formData);
896
183
  case "Stream":
897
- return Stream.toReadableStreamEffect(request.body.stream).pipe(Effect8.flatMap(send));
184
+ return Stream.toReadableStreamEffect(request.body.stream).pipe(Effect3.flatMap(send));
898
185
  }
899
186
  return send(void 0);
900
187
  });
901
- static layer = (service) => Layer6.succeed(HttpClient2.HttpClient, _FunctionsAiHttpClient.make(service));
188
+ static layer = (service) => Layer3.succeed(HttpClient2.HttpClient, _FunctionsAiHttpClient.make(service));
189
+ };
190
+ var parseUpstreamError = async (response) => {
191
+ if (response.ok) {
192
+ return void 0;
193
+ }
194
+ const contentType = response.headers.get("content-type") ?? "";
195
+ if (!contentType.toLowerCase().includes("application/json")) {
196
+ return void 0;
197
+ }
198
+ let body;
199
+ try {
200
+ body = await response.clone().json();
201
+ } catch {
202
+ return void 0;
203
+ }
204
+ if (!body || body.type !== "error" || typeof body.error !== "object" || body.error === null) {
205
+ return void 0;
206
+ }
207
+ const inner = body.error;
208
+ const message = inner.message ?? `Upstream AI service responded with HTTP ${response.status}`;
209
+ if (inner.type === "memoization_miss" && typeof inner.cacheKey === "string") {
210
+ return new FunctionsAiMemoizationMissError({
211
+ message,
212
+ context: {
213
+ cacheKey: inner.cacheKey,
214
+ status: response.status
215
+ }
216
+ });
217
+ }
218
+ return new FunctionsAiUpstreamError({
219
+ message,
220
+ context: {
221
+ type: inner.type,
222
+ status: response.status,
223
+ ...inner.cacheKey ? {
224
+ cacheKey: inner.cacheKey
225
+ } : {}
226
+ }
227
+ });
902
228
  };
903
229
 
904
230
  // src/protocol/protocol.ts
231
+ var __dxlog_file2 = "/__w/dxos/dxos/packages/core/compute/functions/src/protocol/protocol.ts";
905
232
  function _ts_add_disposable_resource(env, value2, async) {
906
233
  if (value2 !== null && value2 !== void 0) {
907
234
  if (typeof value2 !== "object" && typeof value2 !== "function") throw new TypeError("Object expected.");
@@ -941,7 +268,7 @@ function _ts_dispose_resources(env) {
941
268
  return e.name = "SuppressedError", e.error = error, e.suppressed = suppressed, e;
942
269
  };
943
270
  return (_ts_dispose_resources = function _ts_dispose_resources2(env2) {
944
- function fail2(e) {
271
+ function fail(e) {
945
272
  env2.error = env2.hasError ? new _SuppressedError(e, env2.error, "An error was suppressed during disposal.") : e;
946
273
  env2.hasError = true;
947
274
  }
@@ -953,12 +280,12 @@ function _ts_dispose_resources(env) {
953
280
  if (r.dispose) {
954
281
  var result = r.dispose.call(r.value);
955
282
  if (r.async) return s |= 2, Promise.resolve(result).then(next, function(e) {
956
- fail2(e);
283
+ fail(e);
957
284
  return next();
958
285
  });
959
286
  } else s |= 1;
960
287
  } catch (e) {
961
- fail2(e);
288
+ fail(e);
962
289
  }
963
290
  }
964
291
  if (s === 1) return env2.hasError ? Promise.reject(env2.error) : Promise.resolve();
@@ -967,8 +294,7 @@ function _ts_dispose_resources(env) {
967
294
  return next();
968
295
  })(env);
969
296
  }
970
- var __dxlog_file3 = "/__w/dxos/dxos/packages/core/functions/src/protocol/protocol.ts";
971
- var wrapFunctionHandler = (func) => {
297
+ var wrapFunctionHandler = (func, opts = {}) => {
972
298
  if (!Operation.isOperationWithHandler(func)) {
973
299
  throw new TypeError("Expected operation with handler");
974
300
  }
@@ -983,7 +309,7 @@ var wrapFunctionHandler = (func) => {
983
309
  services: func.services.map((service) => service.key)
984
310
  },
985
311
  handler: async ({ data, context }) => {
986
- if ((serviceTags.includes(Database2.Service.key) || serviceTags.includes(QueueService.key) || serviceTags.includes(Feed2.FeedService.key)) && (!context.services.dataService || !context.services.queryService)) {
312
+ if ((serviceTags.includes(Database2.Service.key) || serviceTags.includes(QueueService.key) || serviceTags.includes(Feed.FeedService.key)) && (!context.services.dataService || !context.services.queryService)) {
987
313
  throw new FunctionError({
988
314
  message: "Services not provided: dataService, queryService"
989
315
  });
@@ -995,36 +321,43 @@ var wrapFunctionHandler = (func) => {
995
321
  hasError: false
996
322
  };
997
323
  try {
998
- if (!SchemaAST2.isAnyKeyword(func.input.ast)) {
324
+ if (!SchemaAST.isAnyKeyword(func.input.ast)) {
999
325
  try {
1000
- Schema6.validateSync(func.input)(data);
326
+ Schema.validateSync(func.input, {
327
+ onExcessProperty: "error"
328
+ })(data);
1001
329
  } catch (error) {
1002
- throw new FunctionError({
1003
- message: "Invalid input schema",
330
+ throw new InvalidOperationInputError({
331
+ message: `Operation input did not match schema (${func.meta.key}): ${error.message}`,
1004
332
  cause: error
1005
333
  });
1006
334
  }
1007
335
  }
1008
- const funcContext = _ts_add_disposable_resource(env, await new FunctionContext(context).open(), true);
1009
- if (func.types.length > 0) {
1010
- invariant2(funcContext.db, "Database is required for functions with types", {
1011
- F: __dxlog_file3,
1012
- L: 73,
1013
- S: void 0,
1014
- A: [
1015
- "funcContext.db",
1016
- "'Database is required for functions with types'"
1017
- ]
1018
- });
1019
- await funcContext.db.graph.schemaRegistry.register(func.types);
336
+ const funcContext = _ts_add_disposable_resource(env, await new FunctionContext(context, opts).open(), true);
337
+ const types = [
338
+ ...opts.types ?? [],
339
+ ...func.types ?? []
340
+ ];
341
+ if (types.length > 0) {
342
+ invariant(funcContext.db, "Database is required for functions with types", { "~LogMeta": "~LogMeta", F: __dxlog_file2, L: 137, S: void 0, A: ["funcContext.db", "'Database is required for functions with types'"] });
343
+ await funcContext.db.graph.schemaRegistry.register(types);
1020
344
  }
1021
- const dataWithDecodedRefs = funcContext.db && !SchemaAST2.isAnyKeyword(func.input.ast) ? decodeRefsFromSchema(func.input.ast, data, funcContext.db) : data;
345
+ const dataWithDecodedRefs = funcContext.db && !SchemaAST.isAnyKeyword(func.input.ast) ? decodeRefsFromSchema(func.input.ast, data, funcContext.db) : data;
1022
346
  let result = await func.handler(dataWithDecodedRefs);
1023
- if (Effect9.isEffect(result)) {
1024
- result = await runAndForwardErrors(result.pipe(Effect9.orDie, Effect9.provide(funcContext.createLayer())));
347
+ if (Effect4.isEffect(result)) {
348
+ result = await runAndForwardErrors(result.pipe(Effect4.orDie, Effect4.provide(funcContext.createLayer())));
1025
349
  }
1026
- if (func.output && !SchemaAST2.isAnyKeyword(func.output.ast)) {
1027
- Schema6.validateSync(func.output)(result);
350
+ if (func.output && !SchemaAST.isAnyKeyword(func.output.ast)) {
351
+ try {
352
+ Schema.validateSync(func.output, {
353
+ onExcessProperty: "error"
354
+ })(result);
355
+ } catch (error) {
356
+ throw new InvalidOperationOutputError({
357
+ message: `Operation output did not match schema (${func.meta.key}): ${error.message}`,
358
+ cause: error
359
+ });
360
+ }
1028
361
  }
1029
362
  return result;
1030
363
  } catch (e) {
@@ -1045,9 +378,11 @@ var FunctionContext = class extends Resource {
1045
378
  client;
1046
379
  db;
1047
380
  queues;
1048
- constructor(context) {
381
+ opts;
382
+ constructor(context, opts) {
1049
383
  super();
1050
384
  this.context = context;
385
+ this.opts = opts;
1051
386
  if (context.services.dataService && context.services.queryService) {
1052
387
  this.client = new EchoClient().connectToService({
1053
388
  dataService: context.services.dataService,
@@ -1059,12 +394,12 @@ var FunctionContext = class extends Resource {
1059
394
  async _open() {
1060
395
  await this.client?.open();
1061
396
  this.db = this.client && this.context.spaceId ? this.client.constructDatabase({
1062
- spaceId: this.context.spaceId ?? failedInvariant2(),
1063
- spaceKey: PublicKey.fromHex(this.context.spaceKey ?? failedInvariant2("spaceKey missing in context")),
397
+ spaceId: this.context.spaceId ?? failedInvariant(),
398
+ spaceKey: PublicKey.fromHex(this.context.spaceKey ?? failedInvariant("spaceKey missing in context")),
1064
399
  reactiveSchemaQuery: false,
1065
400
  preloadSchemaOnOpen: false
1066
401
  }) : void 0;
1067
- await this.db?.setSpaceRoot(this.context.spaceRootUrl ?? failedInvariant2("spaceRootUrl missing in context"));
402
+ await this.db?.setSpaceRoot(this.context.spaceRootUrl ?? failedInvariant("spaceRootUrl missing in context"));
1068
403
  await this.db?.open();
1069
404
  this.queues = this.client && this.context.spaceId ? this.client.constructQueueFactory(this.context.spaceId) : void 0;
1070
405
  }
@@ -1076,46 +411,111 @@ var FunctionContext = class extends Resource {
1076
411
  assertState(this._lifecycleState === LifecycleState.OPEN, "FunctionContext is not open");
1077
412
  const dbLayer = this.db ? Database2.layer(this.db) : Database2.notAvailable;
1078
413
  const queuesLayer = this.queues ? QueueService.layer(this.queues) : QueueService.notAvailable;
1079
- const feedLayer = this.queues ? createFeedServiceLayer2(this.queues) : Feed2.notAvailable;
1080
- const credentials = dbLayer ? CredentialsService.layerFromDatabase({
414
+ const feedLayer = this.queues ? createFeedServiceLayer(this.queues) : Feed.notAvailable;
415
+ const credentials = dbLayer ? credentialsLayerFromDatabase({
1081
416
  caching: true
1082
- }).pipe(Layer7.provide(dbLayer)) : CredentialsService.configuredLayer([]);
1083
- const functionInvocationService = MockedFunctionInvocationService;
1084
- const operationServiceLayer = MockedOperationServiceLayer;
1085
- const aiLayer = this.context.services.functionsAiService ? AiModelResolver.AiModelResolver.buildAiService.pipe(Layer7.provide(AnthropicResolver.make().pipe(Layer7.provide(AnthropicClient.layer({
1086
- // Note: It doesn't matter what is base url here, it will be proxied to ai gateway in edge.
1087
- apiUrl: "http://internal/provider/anthropic"
1088
- }).pipe(Layer7.provide(FunctionsAiHttpClient.layer(this.context.services.functionsAiService))))))) : AiService.notAvailable;
1089
- return Layer7.mergeAll(
417
+ }).pipe(Layer4.provide(dbLayer)) : configuredCredentialsLayer([]);
418
+ const aiLayer = this.context.services.functionsAiService ? InternalAiServiceLayer(this.context.services.functionsAiService) : AiService.notAvailable;
419
+ const operationServiceLayer = this.context.services.functionsService ? makeOperationServiceLayer(this.context.services.functionsService) : unavailableOperationServiceLayer;
420
+ const operationRegistryLayer = this.context.services.functionsService ? makeOperationRegistryLayer(this.context.services.functionsService, this.context.spaceId) : emptyOperationRegistryLayer;
421
+ const traceWriterLayer = this.context.services.traceService ? makeTraceWriterLayer(this.context.services.traceService) : Trace.writerLayerNoop;
422
+ log2("Creating function context layer", {
423
+ traceService: !!this.context.services.traceService,
424
+ functionsService: !!this.context.services.functionsService,
425
+ functionsAiService: !!this.context.services.functionsAiService,
426
+ spaceId: this.context.spaceId,
427
+ spaceRootUrl: this.context.spaceRootUrl,
428
+ toolkits: this.opts.toolkits?.length ?? 0,
429
+ types: this.opts.types?.length ?? 0
430
+ }, { "~LogMeta": "~LogMeta", F: __dxlog_file2, L: 220, S: this });
431
+ return Layer4.mergeAll(
1090
432
  dbLayer,
1091
433
  queuesLayer,
1092
434
  feedLayer,
1093
435
  credentials,
1094
- functionInvocationService,
1095
436
  operationServiceLayer,
437
+ operationRegistryLayer,
1096
438
  aiLayer,
1097
- writerLayerNoop
439
+ OpaqueToolkit.providerLayer(OpaqueToolkit.merge(...this.opts.toolkits ?? [])),
440
+ traceWriterLayer,
441
+ // `FunctionInvocationService` is deprecated; new code should yield `Operation.Service`.
442
+ // The cloudflare wrapper provides only the unavailable layer to satisfy the (still-present)
443
+ // type union — handlers that yield it will die at invocation time.
444
+ FunctionInvocationService.layerNotAvailable
1098
445
  );
1099
446
  }
1100
447
  };
1101
- var MockedFunctionInvocationService = Layer7.succeed(FunctionInvocationService, {
1102
- invokeFunction: () => Effect9.die("Calling functions from functions is not implemented yet."),
1103
- resolveFunction: () => Effect9.die("Not implemented.")
448
+ var makeTraceWriterLayer = (traceService) => Layer4.succeed(Trace.TraceService, {
449
+ write: (eventType, payload) => {
450
+ log2("Writing trace event", {
451
+ eventType: eventType.key
452
+ }, { "~LogMeta": "~LogMeta", F: __dxlog_file2, L: 240, S: void 0 });
453
+ traceService.write([
454
+ {
455
+ key: eventType.key,
456
+ isEphemeral: eventType.isEphemeral,
457
+ data: payload
458
+ }
459
+ ]);
460
+ }
1104
461
  });
1105
- var MockedOperationServiceLayer = Layer7.succeed(Operation.Service, {
1106
- invoke: () => Effect9.die("Calling operations from functions is not implemented yet."),
1107
- schedule: () => Effect9.die("Not implemented."),
462
+ var InternalAiServiceLayer = (functionsAiService) => AiModelResolver.AiModelResolver.buildAiService.pipe(Layer4.provide(AnthropicResolver.make().pipe(Layer4.provide(AnthropicClient.layer({
463
+ // Note: It doesn't matter what is base url here, it will be proxied to ai gateway in edge.
464
+ apiUrl: "http://internal/provider/anthropic"
465
+ }).pipe(Layer4.provide(FunctionsAiHttpClient.layer(functionsAiService)))))));
466
+ var makeOperationServiceLayer = (functionsService) => {
467
+ const invokeRemote = async (op, input, options) => {
468
+ invariant(op.meta.deployedId, `Operation '${op.meta.key}' has no deployedId; cannot invoke remotely.`, { "~LogMeta": "~LogMeta", F: __dxlog_file2, L: 264, S: void 0, A: ["op.meta.deployedId", "`Operation '${op.meta.key}' has no deployedId; cannot invoke remotely.`"] });
469
+ const result = await functionsService.invoke(op.meta.deployedId, input, {
470
+ spaceId: options?.spaceId
471
+ });
472
+ if (result._kind === "success") {
473
+ return {
474
+ data: result.data
475
+ };
476
+ }
477
+ return {
478
+ error: ErrorCodec2.decode(result.error)
479
+ };
480
+ };
481
+ return Layer4.succeed(Operation.Service, {
482
+ invoke: (op, input, options) => Effect4.tryPromise(() => invokeRemote(op, input, options)).pipe(Effect4.orDie, Effect4.flatMap((outcome) => outcome.error ? Effect4.die(outcome.error) : Effect4.succeed(outcome.data))),
483
+ schedule: (op, input) => Effect4.sync(() => {
484
+ invariant(op.meta.deployedId, `Operation '${op.meta.key}' has no deployedId; cannot schedule remotely.`, { "~LogMeta": "~LogMeta", F: __dxlog_file2, L: 280, S: void 0, A: ["op.meta.deployedId", "`Operation '${op.meta.key}' has no deployedId; cannot schedule remotely.`"] });
485
+ void functionsService.invoke(op.meta.deployedId, input).catch(() => {
486
+ });
487
+ }),
488
+ invokePromise: (op, input, options) => invokeRemote(op, input, options).catch((error) => ({
489
+ error: error instanceof Error ? error : new Error(String(error))
490
+ }))
491
+ });
492
+ };
493
+ var unavailableOperationServiceLayer = Layer4.succeed(Operation.Service, {
494
+ invoke: () => Effect4.die("Operation.Service is not available: missing functionsService in EDGE context."),
495
+ schedule: () => Effect4.die("Operation.Service is not available: missing functionsService in EDGE context."),
1108
496
  invokePromise: async () => ({
1109
- error: new Error("Not implemented")
497
+ error: new Error("Operation.Service is not available: missing functionsService in EDGE context.")
1110
498
  })
1111
499
  });
500
+ var makeOperationRegistryLayer = (functionsService, spaceId) => Layer4.succeed(OperationRegistry.Service, {
501
+ resolve: (key) => Effect4.gen(function* () {
502
+ const records = yield* Effect4.tryPromise(() => functionsService.query({
503
+ spaceId
504
+ })).pipe(Effect4.orDie);
505
+ const match = records.find((record) => record.key === key);
506
+ return match ? Option.some(Operation.deserialize(match)) : Option.none();
507
+ })
508
+ });
509
+ var emptyOperationRegistryLayer = Layer4.succeed(OperationRegistry.Service, {
510
+ resolve: () => Effect4.succeed(Option.none())
511
+ });
1112
512
  var decodeRefsFromSchema = (ast, value2, db) => {
1113
513
  if (value2 == null) {
1114
514
  return value2;
1115
515
  }
1116
- const encoded = SchemaAST2.encodedBoundAST(ast);
1117
- if (Ref4.isRefType(encoded)) {
1118
- if (Ref4.isRef(value2)) {
516
+ const encoded = SchemaAST.encodedBoundAST(ast);
517
+ if (Ref.isRefType(encoded)) {
518
+ if (Ref.isRef(value2)) {
1119
519
  return value2;
1120
520
  }
1121
521
  if (typeof value2 === "object" && value2 !== null && typeof value2["/"] === "string") {
@@ -1136,10 +536,10 @@ var decodeRefsFromSchema = (ast, value2, db) => {
1136
536
  const result = {
1137
537
  ...value2
1138
538
  };
1139
- for (const prop of SchemaAST2.getPropertySignatures(encoded)) {
1140
- const key2 = prop.name.toString();
1141
- if (key2 in result) {
1142
- result[key2] = decodeRefsFromSchema(prop.type, result[key2], db);
539
+ for (const prop of SchemaAST.getPropertySignatures(encoded)) {
540
+ const key = prop.name.toString();
541
+ if (key in result) {
542
+ result[key] = decodeRefsFromSchema(prop.type, result[key], db);
1143
543
  }
1144
544
  }
1145
545
  return result;
@@ -1155,7 +555,7 @@ var decodeRefsFromSchema = (ast, value2, db) => {
1155
555
  return value2;
1156
556
  }
1157
557
  case "Union": {
1158
- const nonUndefined = encoded.types.filter((t) => !SchemaAST2.isUndefinedKeyword(t));
558
+ const nonUndefined = encoded.types.filter((t) => !SchemaAST.isUndefinedKeyword(t));
1159
559
  if (nonUndefined.length === 1) {
1160
560
  return decodeRefsFromSchema(nonUndefined[0], value2, db);
1161
561
  }
@@ -1173,46 +573,19 @@ var decodeRefsFromSchema = (ast, value2, db) => {
1173
573
  }
1174
574
  };
1175
575
  export {
1176
- ComputeEvent,
1177
- ComputeEventLogger,
1178
- ComputeEventPayload,
1179
576
  ConfiguredCredentialsService,
1180
- ContextQueueService,
1181
- CredentialsService,
1182
- ExampleHandlers,
1183
577
  FUNCTIONS_META_KEY,
1184
578
  FUNCTIONS_PRESET_META_KEY,
1185
- Fibonacci,
1186
- FunctionError,
1187
579
  FunctionInvocationService,
1188
- FunctionNotFoundError,
1189
580
  MESSAGE_PROPERTY_TOOL_CALL_ID,
1190
- Process_exports as Process,
1191
581
  QueueService,
1192
- Reply,
1193
- Script_exports as Script,
1194
- ServiceNotAvailableError,
1195
- ServiceResolver_exports as ServiceResolver,
1196
- Sleep,
1197
- StorageService,
1198
- Trace_exports as Trace,
1199
- Trigger_exports as Trigger,
1200
- TriggerEvent_exports as TriggerEvent,
1201
- TriggerStateNotFoundError,
1202
- clear,
1203
- createDefectLogger,
1204
- createEventLogger,
1205
- deleteKey,
582
+ configuredCredentialsLayer,
583
+ credentialsLayerConfig,
584
+ credentialsLayerFromDatabase,
1206
585
  feedServiceFromQueueServiceLayer,
1207
- get,
1208
586
  getUserFunctionIdInMetadata,
1209
- key,
1210
- list,
1211
- logCustomEvent,
1212
- set,
1213
587
  setUserFunctionIdInMetadata,
1214
588
  withAuthorization,
1215
- withDefault,
1216
589
  wrapFunctionHandler
1217
590
  };
1218
591
  //# sourceMappingURL=index.mjs.map