@dxos/functions 0.8.4-main.03d5cd7b56 → 0.8.4-main.05e74ebcff

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.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@dxos/functions",
3
- "version": "0.8.4-main.03d5cd7b56",
3
+ "version": "0.8.4-main.05e74ebcff",
4
4
  "description": "Functions API.",
5
5
  "homepage": "https://dxos.org",
6
6
  "bugs": "https://github.com/dxos/dxos/issues",
@@ -8,7 +8,7 @@
8
8
  "type": "git",
9
9
  "url": "https://github.com/dxos/dxos"
10
10
  },
11
- "license": "MIT",
11
+ "license": "FSL-1.1-Apache-2.0",
12
12
  "author": "info@dxos.org",
13
13
  "sideEffects": false,
14
14
  "type": "module",
@@ -30,20 +30,20 @@
30
30
  "@effect/ai-anthropic": "0.23.0",
31
31
  "@effect/platform": "0.94.4",
32
32
  "effect": "3.20.0",
33
- "@dxos/ai": "0.8.4-main.03d5cd7b56",
34
- "@dxos/context": "0.8.4-main.03d5cd7b56",
35
- "@dxos/compute": "0.8.4-main.03d5cd7b56",
36
- "@dxos/echo": "0.8.4-main.03d5cd7b56",
37
- "@dxos/errors": "0.8.4-main.03d5cd7b56",
38
- "@dxos/invariant": "0.8.4-main.03d5cd7b56",
39
- "@dxos/keys": "0.8.4-main.03d5cd7b56",
40
- "@dxos/echo-db": "0.8.4-main.03d5cd7b56",
41
- "@dxos/log": "0.8.4-main.03d5cd7b56",
42
- "@dxos/node-std": "0.8.4-main.03d5cd7b56",
43
- "@dxos/protocols": "0.8.4-main.03d5cd7b56",
44
- "@dxos/schema": "0.8.4-main.03d5cd7b56",
45
- "@dxos/types": "0.8.4-main.03d5cd7b56",
46
- "@dxos/effect": "0.8.4-main.03d5cd7b56"
33
+ "@dxos/ai": "0.8.4-main.05e74ebcff",
34
+ "@dxos/compute": "0.8.4-main.05e74ebcff",
35
+ "@dxos/echo": "0.8.4-main.05e74ebcff",
36
+ "@dxos/echo-db": "0.8.4-main.05e74ebcff",
37
+ "@dxos/context": "0.8.4-main.05e74ebcff",
38
+ "@dxos/errors": "0.8.4-main.05e74ebcff",
39
+ "@dxos/keys": "0.8.4-main.05e74ebcff",
40
+ "@dxos/invariant": "0.8.4-main.05e74ebcff",
41
+ "@dxos/node-std": "0.8.4-main.05e74ebcff",
42
+ "@dxos/log": "0.8.4-main.05e74ebcff",
43
+ "@dxos/protocols": "0.8.4-main.05e74ebcff",
44
+ "@dxos/effect": "0.8.4-main.05e74ebcff",
45
+ "@dxos/schema": "0.8.4-main.05e74ebcff",
46
+ "@dxos/types": "0.8.4-main.05e74ebcff"
47
47
  },
48
48
  "publishConfig": {
49
49
  "access": "public"
@@ -12,6 +12,7 @@ import * as SchemaAST from 'effect/SchemaAST';
12
12
  import { AiModelResolver, AiService, OpaqueToolkit } from '@dxos/ai';
13
13
  import { AnthropicResolver } from '@dxos/ai/resolvers';
14
14
  import {
15
+ Blueprint,
15
16
  FunctionError,
16
17
  InvalidOperationInputError,
17
18
  InvalidOperationOutputError,
@@ -48,6 +49,12 @@ export interface FunctionWrappingOptions {
48
49
  * Toolkits to make available via the `OpaqueToolkitProvider`.
49
50
  */
50
51
  toolkits?: OpaqueToolkit.OpaqueToolkit[];
52
+
53
+ /**
54
+ * Blueprint registry to expose as `Blueprint.RegistryService` inside handler Effects.
55
+ * Required for operations that declare `Blueprint.RegistryService` in their `services` list.
56
+ */
57
+ blueprintRegistry?: Blueprint.Registry;
51
58
  }
52
59
 
53
60
  /**
@@ -121,6 +128,18 @@ export const wrapFunctionHandler = (
121
128
  );
122
129
  }
123
130
 
131
+ // Flush in-memory ECHO writes before the function scope closes.
132
+ // Writes performed by `db.add` / `db.remove` are buffered in the in-memory
133
+ // `EchoDatabaseImpl` and only pushed across the `DataService` binding when
134
+ // `db.flush({ disk })` is called. `FunctionContext._close` (invoked by the
135
+ // `await using` above) calls `db.close()` but does NOT flush, so mutations
136
+ // performed by handlers that declare `Database.Service` (e.g. `object-create`,
137
+ // `object-update`, `relation-create`) would be silently dropped before reaching
138
+ // the edge `AutomergeReplicator`. Flushing here closes that hole.
139
+ if (serviceTags.includes(Database.Service.key) && funcContext.db) {
140
+ await funcContext.db.flush({ disk: true, indexes: false });
141
+ }
142
+
124
143
  if (func.output && !SchemaAST.isAnyKeyword(func.output.ast)) {
125
144
  try {
126
145
  Schema.validateSync(func.output, { onExcessProperty: 'error' })(result);
@@ -223,6 +242,10 @@ class FunctionContext extends Resource {
223
242
  types: this.opts.types?.length ?? 0,
224
243
  });
225
244
 
245
+ const blueprintRegistryLayer = this.opts.blueprintRegistry
246
+ ? Layer.succeed(Blueprint.RegistryService, this.opts.blueprintRegistry)
247
+ : Blueprint.RegistryService.notAvailable;
248
+
226
249
  return Layer.mergeAll(
227
250
  dbLayer,
228
251
  queuesLayer,
@@ -233,6 +256,7 @@ class FunctionContext extends Resource {
233
256
  aiLayer,
234
257
  OpaqueToolkit.providerLayer(OpaqueToolkit.merge(...(this.opts.toolkits ?? []))),
235
258
  traceWriterLayer,
259
+ blueprintRegistryLayer,
236
260
 
237
261
  // `FunctionInvocationService` is deprecated; new code should yield `Operation.Service`.
238
262
  // The cloudflare wrapper provides only the unavailable layer to satisfy the (still-present)
@@ -295,6 +319,9 @@ const makeOperationServiceLayer = (
295
319
  invariant(op.meta.deployedId, `Operation '${op.meta.key}' has no deployedId; cannot invoke remotely.`);
296
320
  const result = await functionsService.invoke(op.meta.deployedId, input, {
297
321
  spaceId: options?.spaceId,
322
+ // Forward the conversation DXN so the remote runtime can rebuild conversation-scoped
323
+ // services (e.g. `AiContext.Service`) needed by operations like `GetContext`.
324
+ conversation: options?.conversation,
298
325
  });
299
326
  if (result._kind === 'success') {
300
327
  return { data: result.data };
@@ -345,7 +372,7 @@ const makeOperationRegistryLayer = (
345
372
  resolve: (key: string) =>
346
373
  Effect.gen(function* () {
347
374
  const records = yield* Effect.tryPromise(() => functionsService.query({ spaceId })).pipe(Effect.orDie);
348
- const match = (records as Operation.PersistentOperation[]).find((record) => record.key === key);
375
+ const match = (records as Operation.PersistentOperation[]).find((record) => Operation.getKey(record) === key);
349
376
  return match ? Option.some(Operation.deserialize(match)) : Option.none();
350
377
  }),
351
378
  });
@@ -11,8 +11,7 @@ import * as Layer from 'effect/Layer';
11
11
  import * as Redacted from 'effect/Redacted';
12
12
 
13
13
  import { Credential } from '@dxos/compute';
14
- import { Query } from '@dxos/echo';
15
- import { Database } from '@dxos/echo';
14
+ import { Database, Query } from '@dxos/echo';
16
15
  import { AccessToken } from '@dxos/types';
17
16
 
18
17
  export class ConfiguredCredentialsService implements Context.Tag.Service<Credential.CredentialsService> {
@@ -7,6 +7,9 @@ import * as Layer from 'effect/Layer';
7
7
 
8
8
  import { type FunctionNotFoundError, Operation } from '@dxos/compute';
9
9
 
10
+ /**
11
+ * @deprecated
12
+ */
10
13
  export class FunctionInvocationService extends Context.Tag('@dxos/functions/FunctionInvocationService')<
11
14
  FunctionInvocationService,
12
15
  {
@@ -2,4 +2,4 @@
2
2
  // Copyright 2025 DXOS.org
3
3
  //
4
4
 
5
- export { ContextQueueService, QueueService, feedServiceFromQueueServiceLayer } from '@dxos/echo-db';
5
+ export { QueueService, feedServiceFromQueueServiceLayer } from '@dxos/echo-db';