@dxos/functions 0.8.4-main.3a94e84 → 0.8.4-main.5acf9ea

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 (56) hide show
  1. package/dist/lib/browser/{chunk-3NGCSUEW.mjs → chunk-6PTFLPCO.mjs} +194 -60
  2. package/dist/lib/browser/chunk-6PTFLPCO.mjs.map +7 -0
  3. package/dist/lib/browser/index.mjs +13 -15
  4. package/dist/lib/browser/index.mjs.map +4 -4
  5. package/dist/lib/browser/meta.json +1 -1
  6. package/dist/lib/browser/testing/index.mjs +2 -34
  7. package/dist/lib/browser/testing/index.mjs.map +3 -3
  8. package/dist/lib/node-esm/{chunk-FJ2MU7TL.mjs → chunk-NYJ2TSXO.mjs} +194 -60
  9. package/dist/lib/node-esm/chunk-NYJ2TSXO.mjs.map +7 -0
  10. package/dist/lib/node-esm/index.mjs +13 -15
  11. package/dist/lib/node-esm/index.mjs.map +4 -4
  12. package/dist/lib/node-esm/meta.json +1 -1
  13. package/dist/lib/node-esm/testing/index.mjs +2 -34
  14. package/dist/lib/node-esm/testing/index.mjs.map +3 -3
  15. package/dist/types/src/services/credentials.d.ts +3 -2
  16. package/dist/types/src/services/credentials.d.ts.map +1 -1
  17. package/dist/types/src/services/database.d.ts +2 -1
  18. package/dist/types/src/services/database.d.ts.map +1 -1
  19. package/dist/types/src/services/event-logger.d.ts +65 -30
  20. package/dist/types/src/services/event-logger.d.ts.map +1 -1
  21. package/dist/types/src/services/index.d.ts +2 -1
  22. package/dist/types/src/services/index.d.ts.map +1 -1
  23. package/dist/types/src/services/local-function-execution.d.ts +11 -0
  24. package/dist/types/src/services/local-function-execution.d.ts.map +1 -0
  25. package/dist/types/src/services/queues.d.ts +3 -2
  26. package/dist/types/src/services/queues.d.ts.map +1 -1
  27. package/dist/types/src/services/remote-function-execution-service.d.ts +15 -0
  28. package/dist/types/src/services/remote-function-execution-service.d.ts.map +1 -0
  29. package/dist/types/src/services/service-container.d.ts +4 -4
  30. package/dist/types/src/services/service-container.d.ts.map +1 -1
  31. package/dist/types/src/services/service-registry.d.ts +1 -1
  32. package/dist/types/src/services/service-registry.d.ts.map +1 -1
  33. package/dist/types/src/services/tracing.d.ts +3 -2
  34. package/dist/types/src/services/tracing.d.ts.map +1 -1
  35. package/dist/types/src/testing/logger.d.ts +3 -3
  36. package/dist/types/src/testing/logger.d.ts.map +1 -1
  37. package/dist/types/src/testing/services.d.ts +6 -17
  38. package/dist/types/src/testing/services.d.ts.map +1 -1
  39. package/dist/types/tsconfig.tsbuildinfo +1 -1
  40. package/package.json +32 -27
  41. package/src/services/credentials.ts +5 -2
  42. package/src/services/database.ts +5 -1
  43. package/src/services/event-logger.ts +67 -36
  44. package/src/services/index.ts +2 -1
  45. package/src/services/local-function-execution.ts +70 -0
  46. package/src/services/queues.ts +5 -2
  47. package/src/services/{function-call-service.ts → remote-function-execution-service.ts} +7 -5
  48. package/src/services/service-container.ts +7 -7
  49. package/src/services/service-registry.ts +4 -1
  50. package/src/services/tracing.ts +4 -2
  51. package/src/testing/logger.ts +3 -3
  52. package/src/testing/services.ts +8 -62
  53. package/dist/lib/browser/chunk-3NGCSUEW.mjs.map +0 -7
  54. package/dist/lib/node-esm/chunk-FJ2MU7TL.mjs.map +0 -7
  55. package/dist/types/src/services/function-call-service.d.ts +0 -16
  56. package/dist/types/src/services/function-call-service.d.ts.map +0 -1
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@dxos/functions",
3
- "version": "0.8.4-main.3a94e84",
3
+ "version": "0.8.4-main.5acf9ea",
4
4
  "description": "Functions API and runtime.",
5
5
  "homepage": "https://dxos.org",
6
6
  "bugs": "https://github.com/dxos/dxos/issues",
@@ -12,22 +12,26 @@
12
12
  "./bundler": {
13
13
  "types": "./dist/types/src/bundler/index.d.ts",
14
14
  "browser": "./dist/lib/browser/bundler/index.mjs",
15
- "node": "./dist/lib/node-esm/bundler/index.mjs"
15
+ "node": "./dist/lib/node-esm/bundler/index.mjs",
16
+ "source": "./src/bundler/index.ts"
16
17
  },
17
18
  "./edge": {
18
19
  "types": "./dist/types/src/edge/index.d.ts",
19
20
  "browser": "./dist/lib/browser/edge/index.mjs",
20
- "node": "./dist/lib/node-esm/edge/index.mjs"
21
+ "node": "./dist/lib/node-esm/edge/index.mjs",
22
+ "source": "./src/edge/index.ts"
21
23
  },
22
24
  ".": {
23
25
  "types": "./dist/types/src/index.d.ts",
24
26
  "browser": "./dist/lib/browser/index.mjs",
25
- "node": "./dist/lib/node-esm/index.mjs"
27
+ "node": "./dist/lib/node-esm/index.mjs",
28
+ "source": "./src/index.ts"
26
29
  },
27
30
  "./testing": {
28
31
  "types": "./dist/types/src/testing/index.d.ts",
29
32
  "browser": "./dist/lib/browser/testing/index.mjs",
30
- "node": "./dist/lib/node-esm/testing/index.mjs"
33
+ "node": "./dist/lib/node-esm/testing/index.mjs",
34
+ "source": "./src/testing/index.ts"
31
35
  }
32
36
  },
33
37
  "types": "dist/types/src/index.d.ts",
@@ -58,32 +62,33 @@
58
62
  "i18next": "^24.2.1",
59
63
  "iso-did": "^1.6.0",
60
64
  "ws": "^8.14.2",
61
- "@dxos/ai": "0.8.4-main.3a94e84",
62
- "@dxos/async": "0.8.4-main.3a94e84",
63
- "@dxos/context": "0.8.4-main.3a94e84",
64
- "@dxos/crypto": "0.8.4-main.3a94e84",
65
- "@dxos/echo": "0.8.4-main.3a94e84",
66
- "@dxos/client": "0.8.4-main.3a94e84",
67
- "@dxos/echo-db": "0.8.4-main.3a94e84",
68
- "@dxos/echo-pipeline": "0.8.4-main.3a94e84",
69
- "@dxos/echo-protocol": "0.8.4-main.3a94e84",
70
- "@dxos/echo-schema": "0.8.4-main.3a94e84",
71
- "@dxos/edge-client": "0.8.4-main.3a94e84",
72
- "@dxos/effect": "0.8.4-main.3a94e84",
73
- "@dxos/errors": "0.8.4-main.3a94e84",
74
- "@dxos/invariant": "0.8.4-main.3a94e84",
75
- "@dxos/keys": "0.8.4-main.3a94e84",
76
- "@dxos/live-object": "0.8.4-main.3a94e84",
77
- "@dxos/log": "0.8.4-main.3a94e84",
78
- "@dxos/node-std": "0.8.4-main.3a94e84",
79
- "@dxos/schema": "0.8.4-main.3a94e84",
80
- "@dxos/util": "0.8.4-main.3a94e84",
81
- "@dxos/protocols": "0.8.4-main.3a94e84"
65
+ "@dxos/ai": "0.8.4-main.5acf9ea",
66
+ "@dxos/async": "0.8.4-main.5acf9ea",
67
+ "@dxos/crypto": "0.8.4-main.5acf9ea",
68
+ "@dxos/client": "0.8.4-main.5acf9ea",
69
+ "@dxos/echo": "0.8.4-main.5acf9ea",
70
+ "@dxos/context": "0.8.4-main.5acf9ea",
71
+ "@dxos/debug": "0.8.4-main.5acf9ea",
72
+ "@dxos/echo-db": "0.8.4-main.5acf9ea",
73
+ "@dxos/echo-protocol": "0.8.4-main.5acf9ea",
74
+ "@dxos/echo-pipeline": "0.8.4-main.5acf9ea",
75
+ "@dxos/echo-schema": "0.8.4-main.5acf9ea",
76
+ "@dxos/edge-client": "0.8.4-main.5acf9ea",
77
+ "@dxos/effect": "0.8.4-main.5acf9ea",
78
+ "@dxos/errors": "0.8.4-main.5acf9ea",
79
+ "@dxos/keys": "0.8.4-main.5acf9ea",
80
+ "@dxos/invariant": "0.8.4-main.5acf9ea",
81
+ "@dxos/live-object": "0.8.4-main.5acf9ea",
82
+ "@dxos/log": "0.8.4-main.5acf9ea",
83
+ "@dxos/node-std": "0.8.4-main.5acf9ea",
84
+ "@dxos/protocols": "0.8.4-main.5acf9ea",
85
+ "@dxos/schema": "0.8.4-main.5acf9ea",
86
+ "@dxos/util": "0.8.4-main.5acf9ea"
82
87
  },
83
88
  "devDependencies": {
84
89
  "@types/express": "^4.17.17",
85
90
  "@types/ws": "^7.4.0",
86
- "@dxos/agent": "0.8.4-main.3a94e84"
91
+ "@dxos/agent": "0.8.4-main.5acf9ea"
87
92
  },
88
93
  "publishConfig": {
89
94
  "access": "public"
@@ -2,7 +2,7 @@
2
2
  // Copyright 2025 DXOS.org
3
3
  //
4
4
 
5
- import { Context, Effect } from 'effect';
5
+ import { Context, Effect, Layer } from 'effect';
6
6
 
7
7
  type CredentialQuery = {
8
8
  service?: string;
@@ -17,7 +17,7 @@ export type ServiceCredential = {
17
17
  apiKey?: string;
18
18
  };
19
19
 
20
- export class CredentialsService extends Context.Tag('CredentialsService')<
20
+ export class CredentialsService extends Context.Tag('@dxos/functions/CredentialsService')<
21
21
  CredentialsService,
22
22
  {
23
23
  /**
@@ -32,6 +32,9 @@ export class CredentialsService extends Context.Tag('CredentialsService')<
32
32
  getCredential: (query: CredentialQuery) => Promise<ServiceCredential>;
33
33
  }
34
34
  >() {
35
+ static configuredLayer = (credentials: ServiceCredential[]) =>
36
+ Layer.succeed(CredentialsService, new ConfiguredCredentialsService(credentials));
37
+
35
38
  static getCredential = (query: CredentialQuery): Effect.Effect<ServiceCredential, never, CredentialsService> =>
36
39
  Effect.gen(function* () {
37
40
  const credentials = yield* CredentialsService;
@@ -8,7 +8,7 @@ import type { Filter, Live, Obj, Query, Ref, Relation } from '@dxos/echo';
8
8
  import type { EchoDatabase, OneShotQueryResult, QueryResult } from '@dxos/echo-db';
9
9
  import type { DXN } from '@dxos/keys';
10
10
 
11
- export class DatabaseService extends Context.Tag('DatabaseService')<
11
+ export class DatabaseService extends Context.Tag('@dxos/functions/DatabaseService')<
12
12
  DatabaseService,
13
13
  {
14
14
  readonly db: EchoDatabase;
@@ -28,6 +28,10 @@ export class DatabaseService extends Context.Tag('DatabaseService')<
28
28
  };
29
29
  };
30
30
 
31
+ static makeLayer = (db: EchoDatabase): Layer.Layer<DatabaseService> => {
32
+ return Layer.succeed(DatabaseService, DatabaseService.make(db));
33
+ };
34
+
31
35
  static resolve: (dxn: DXN) => Effect.Effect<Obj.Any | Relation.Any, Error, DatabaseService> = Effect.fn(
32
36
  function* (dxn) {
33
37
  const { db } = yield* DatabaseService;
@@ -2,53 +2,81 @@
2
2
  // Copyright 2025 DXOS.org
3
3
  //
4
4
 
5
- import { Effect, Context } from 'effect';
5
+ import { Effect, Context, Schema, Layer } from 'effect';
6
6
 
7
+ import { Obj, Type } from '@dxos/echo';
7
8
  import { invariant } from '@dxos/invariant';
8
9
  import { log, LogLevel } from '@dxos/log';
9
10
 
10
- export type ComputeEvent =
11
- | {
12
- type: 'begin-compute';
13
- nodeId: string;
14
- inputs: Record<string, any>;
15
- }
16
- | {
17
- type: 'end-compute';
18
- nodeId: string;
19
- outputs: Record<string, any>;
20
- }
21
- | {
22
- type: 'compute-input';
23
- nodeId: string;
24
- property: string;
25
- value: any;
26
- }
27
- | {
28
- type: 'compute-output';
29
- nodeId: string;
30
- property: string;
31
- value: any;
32
- }
33
- | {
34
- type: 'custom';
35
- nodeId: string;
36
- event: any;
37
- };
11
+ import { TracingService } from './tracing';
12
+
13
+ export const ComputeEventPayload = Schema.Union(
14
+ Schema.Struct({
15
+ type: Schema.Literal('begin-compute'),
16
+ nodeId: Schema.String,
17
+ inputs: Schema.Record({ key: Schema.String, value: Schema.Any }),
18
+ }),
19
+ Schema.Struct({
20
+ type: Schema.Literal('end-compute'),
21
+ nodeId: Schema.String,
22
+ outputs: Schema.Record({ key: Schema.String, value: Schema.Any }),
23
+ }),
24
+ Schema.Struct({
25
+ type: Schema.Literal('compute-input'),
26
+ nodeId: Schema.String,
27
+ property: Schema.String,
28
+ value: Schema.Any,
29
+ }),
30
+ Schema.Struct({
31
+ type: Schema.Literal('compute-output'),
32
+ nodeId: Schema.String,
33
+ property: Schema.String,
34
+ value: Schema.Any,
35
+ }),
36
+ Schema.Struct({
37
+ type: Schema.Literal('custom'),
38
+ nodeId: Schema.String,
39
+ event: Schema.Any,
40
+ }),
41
+ );
42
+ export type ComputeEventPayload = Schema.Schema.Type<typeof ComputeEventPayload>;
38
43
 
39
- export class EventLogger extends Context.Tag('EventLogger')<
40
- EventLogger,
41
- { readonly log: (event: ComputeEvent) => void; readonly nodeId: string | undefined }
44
+ export const ComputeEvent = Schema.Struct({
45
+ payload: ComputeEventPayload,
46
+ }).pipe(Type.Obj({ typename: 'dxos.org/type/ComputeEvent', version: '0.1.0' }));
47
+
48
+ /**
49
+ * Logs event for the compute workflows.
50
+ */
51
+ export class ComputeEventLogger extends Context.Tag('@dxos/functions/ComputeEventLogger')<
52
+ ComputeEventLogger,
53
+ { readonly log: (event: ComputeEventPayload) => void; readonly nodeId: string | undefined }
42
54
  >() {
43
- static noop: Context.Tag.Service<EventLogger> = {
55
+ static noop: Context.Tag.Service<ComputeEventLogger> = {
44
56
  log: () => {},
45
57
  nodeId: undefined,
46
58
  };
59
+
60
+ /**
61
+ * Implements ComputeEventLogger using TracingService.
62
+ */
63
+ static layerFromTracing = Layer.effect(
64
+ ComputeEventLogger,
65
+ Effect.gen(function* () {
66
+ const tracing = yield* TracingService;
67
+ return {
68
+ log: (event: ComputeEventPayload) => {
69
+ tracing.write(Obj.make(ComputeEvent, { payload: event }));
70
+ },
71
+ nodeId: undefined,
72
+ };
73
+ }),
74
+ );
47
75
  }
48
76
 
49
77
  export const logCustomEvent = (data: any) =>
50
78
  Effect.gen(function* () {
51
- const logger = yield* EventLogger;
79
+ const logger = yield* ComputeEventLogger;
52
80
  if (!logger.nodeId) {
53
81
  throw new Error('logCustomEvent must be called within a node compute function');
54
82
  }
@@ -67,7 +95,10 @@ export const createDefectLogger = <A, E, R>(): ((self: Effect.Effect<A, E, R>) =
67
95
  }),
68
96
  );
69
97
 
70
- export const createEventLogger = (level: LogLevel, message: string = 'event'): Context.Tag.Service<EventLogger> => {
98
+ export const createEventLogger = (
99
+ level: LogLevel,
100
+ message: string = 'event',
101
+ ): Context.Tag.Service<ComputeEventLogger> => {
71
102
  const logFunction = (
72
103
  {
73
104
  [LogLevel.WARN]: log.warn,
@@ -79,7 +110,7 @@ export const createEventLogger = (level: LogLevel, message: string = 'event'): C
79
110
  )[level];
80
111
  invariant(logFunction);
81
112
  return {
82
- log: (event: ComputeEvent) => {
113
+ log: (event: ComputeEventPayload) => {
83
114
  logFunction(message, event);
84
115
  },
85
116
  nodeId: undefined,
@@ -8,4 +8,5 @@ export * from './service-container';
8
8
  export * from './credentials';
9
9
  export * from './tracing';
10
10
  export * from './event-logger';
11
- export * from './function-call-service';
11
+ export * from './remote-function-execution-service';
12
+ export * from './local-function-execution';
@@ -0,0 +1,70 @@
1
+ //
2
+ // Copyright 2025 DXOS.org
3
+ //
4
+
5
+ import { Context, Effect, Layer, Schema } from 'effect';
6
+
7
+ import { todo } from '@dxos/debug';
8
+
9
+ import type { FunctionContext, FunctionDefinition } from '../handler';
10
+ import type { Services } from './service-container';
11
+ import { FunctionError } from '../errors';
12
+
13
+ export class LocalFunctionExecutionService extends Context.Tag('@dxos/functions/LocalFunctionExecutionService')<
14
+ LocalFunctionExecutionService,
15
+ {
16
+ // TODO(dmaretskyi): This should take function id instead of the definition object.
17
+ // TODO(dmaretskyi): Services should be satisfied from environment rather then bubbled up.
18
+ invokeFunction(fnDef: FunctionDefinition<any, any>, input: unknown): Effect.Effect<unknown, never, Services>;
19
+ }
20
+ >() {
21
+ static layer = Layer.succeed(LocalFunctionExecutionService, {
22
+ invokeFunction: (fnDef, input) => invokeFunction(fnDef, input),
23
+ });
24
+ }
25
+
26
+ const invokeFunction = (fnDef: FunctionDefinition<any, any>, input: any): Effect.Effect<unknown, never, Services> =>
27
+ Effect.gen(function* () {
28
+ // Assert input matches schema
29
+ const assertInput = fnDef.inputSchema.pipe(Schema.asserts);
30
+ (assertInput as any)(input);
31
+
32
+ const context: FunctionContext = {
33
+ getService: () => todo(),
34
+ getSpace: async (_spaceId: any) => {
35
+ throw new Error('Not available. Use the database service instead.');
36
+ },
37
+ space: undefined,
38
+ get ai(): never {
39
+ throw new Error('Not available. Use the ai service instead.');
40
+ },
41
+ };
42
+
43
+ // TODO(dmaretskyi): This should be delegated to a function invoker service.
44
+ const data = yield* Effect.gen(function* () {
45
+ const result = fnDef.handler({ context, data: input });
46
+ if (Effect.isEffect(result)) {
47
+ return yield* (result as Effect.Effect<unknown, unknown, Services>).pipe(Effect.orDie);
48
+ } else if (
49
+ typeof result === 'object' &&
50
+ result !== null &&
51
+ 'then' in result &&
52
+ typeof result.then === 'function'
53
+ ) {
54
+ return yield* Effect.promise(() => result);
55
+ } else {
56
+ return result;
57
+ }
58
+ }).pipe(
59
+ Effect.orDie,
60
+ Effect.catchAllDefect((defect) =>
61
+ Effect.die(new FunctionError('Error running function', { context: { name: fnDef.name }, cause: defect })),
62
+ ),
63
+ );
64
+
65
+ // Assert output matches schema
66
+ const assertOutput = fnDef.outputSchema?.pipe(Schema.asserts);
67
+ (assertOutput as any)(data);
68
+
69
+ return data;
70
+ }).pipe(Effect.withSpan('invokeFunction', { attributes: { name: fnDef.name } }));
@@ -9,7 +9,7 @@ import type { Queue, QueueAPI, QueueFactory } from '@dxos/echo-db';
9
9
  /**
10
10
  * Gives access to all queues.
11
11
  */
12
- export class QueueService extends Context.Tag('QueueService')<
12
+ export class QueueService extends Context.Tag('@dxos/functions/QueueService')<
13
13
  QueueService,
14
14
  {
15
15
  /**
@@ -42,12 +42,15 @@ export class QueueService extends Context.Tag('QueueService')<
42
42
  contextQueue,
43
43
  };
44
44
  };
45
+
46
+ static makeLayer = (queues: QueueFactory, contextQueue?: Queue): Layer.Layer<QueueService> =>
47
+ Layer.succeed(QueueService, QueueService.make(queues, contextQueue));
45
48
  }
46
49
 
47
50
  /**
48
51
  * Gives access to a specific queue passed as a context.
49
52
  */
50
- export class ContextQueueService extends Context.Tag('ContextQueueService')<
53
+ export class ContextQueueService extends Context.Tag('@dxos/functions/ContextQueueService')<
51
54
  ContextQueueService,
52
55
  {
53
56
  readonly contextQueue: Queue;
@@ -2,20 +2,20 @@
2
2
  // Copyright 2025 DXOS.org
3
3
  //
4
4
 
5
- import { Context } from 'effect';
5
+ import { Context, Layer } from 'effect';
6
6
 
7
7
  import type { SpaceId } from '@dxos/keys';
8
8
 
9
9
  /**
10
10
  * Allows calling into other functions.
11
11
  */
12
- export class FunctionCallService extends Context.Tag('FunctionCallService')<
13
- FunctionCallService,
12
+ export class RemoteFunctionExecutionService extends Context.Tag('@dxos/functions/RemoteFunctionExecutionService')<
13
+ RemoteFunctionExecutionService,
14
14
  {
15
15
  callFunction(deployedFunctionId: string, input: any, spaceId?: SpaceId): Promise<any>;
16
16
  }
17
17
  >() {
18
- static fromClient(baseUrl: string, spaceId: SpaceId): Context.Tag.Service<FunctionCallService> {
18
+ static fromClient(baseUrl: string, spaceId: SpaceId): Context.Tag.Service<RemoteFunctionExecutionService> {
19
19
  return {
20
20
  callFunction: async (deployedFunctionId: string, input: any) => {
21
21
  const url = getInvocationUrl(deployedFunctionId, baseUrl, { spaceId });
@@ -32,13 +32,15 @@ export class FunctionCallService extends Context.Tag('FunctionCallService')<
32
32
  };
33
33
  }
34
34
 
35
- static mock = () => {
35
+ static mock = (): Context.Tag.Service<RemoteFunctionExecutionService> => {
36
36
  return {
37
37
  callFunction: async (deployedFunctionId: string, input: any) => {
38
38
  return input;
39
39
  },
40
40
  };
41
41
  };
42
+
43
+ static mockLayer = Layer.succeed(RemoteFunctionExecutionService, RemoteFunctionExecutionService.mock());
42
44
  }
43
45
 
44
46
  // TODO(dmaretskyi): Reconcile with `getInvocationUrl` in `@dxos/functions/edge`.
@@ -9,9 +9,9 @@ import { entries } from '@dxos/util';
9
9
 
10
10
  import { ConfiguredCredentialsService, CredentialsService } from './credentials';
11
11
  import { DatabaseService } from './database';
12
- import { EventLogger } from './event-logger';
13
- import { FunctionCallService } from './function-call-service';
12
+ import { ComputeEventLogger } from './event-logger';
14
13
  import { QueueService } from './queues';
14
+ import { RemoteFunctionExecutionService } from './remote-function-execution-service';
15
15
  import { TracingService } from './tracing';
16
16
 
17
17
  // TODO(dmaretskyi): Refactor this module to only rely on tags and not the human-assigned names.
@@ -23,8 +23,8 @@ const SERVICES = {
23
23
  ai: AiService,
24
24
  credentials: CredentialsService,
25
25
  database: DatabaseService,
26
- eventLogger: EventLogger,
27
- functionCallService: FunctionCallService,
26
+ eventLogger: ComputeEventLogger,
27
+ functionCallService: RemoteFunctionExecutionService,
28
28
  queues: QueueService,
29
29
  tracing: TracingService,
30
30
  } as const satisfies Record<string, Context.TagClass<any, string, any>>;
@@ -102,10 +102,10 @@ export class ServiceContainer {
102
102
  const queues =
103
103
  this._services.queues != null ? Layer.succeed(QueueService, this._services.queues) : QueueService.notAvailable;
104
104
  const tracing = Layer.succeed(TracingService, this._services.tracing ?? TracingService.noop);
105
- const eventLogger = Layer.succeed(EventLogger, this._services.eventLogger ?? EventLogger.noop);
105
+ const eventLogger = Layer.succeed(ComputeEventLogger, this._services.eventLogger ?? ComputeEventLogger.noop);
106
106
  const functionCallService = Layer.succeed(
107
- FunctionCallService,
108
- this._services.functionCallService ?? FunctionCallService.mock(),
107
+ RemoteFunctionExecutionService,
108
+ this._services.functionCallService ?? RemoteFunctionExecutionService.mock(),
109
109
  );
110
110
 
111
111
  return Layer.mergeAll(ai, credentials, database, queues, tracing, eventLogger, functionCallService);
@@ -12,7 +12,10 @@ export namespace ServiceRegistry {
12
12
  }
13
13
  }
14
14
 
15
- export class ServiceRegistry extends Context.Tag('ServiceRegistry')<ServiceRegistry, ServiceRegistry.Service>() {
15
+ export class ServiceRegistry extends Context.Tag('@dxos/functions/ServiceRegistry')<
16
+ ServiceRegistry,
17
+ ServiceRegistry.Service
18
+ >() {
16
19
  /**
17
20
  * Resolves the service from the registry.
18
21
  * @param tag Service tag to resolve.
@@ -2,7 +2,7 @@
2
2
  // Copyright 2025 DXOS.org
3
3
  //
4
4
 
5
- import { Context, Effect } from 'effect';
5
+ import { Context, Effect, Layer } from 'effect';
6
6
 
7
7
  import { AgentStatus } from '@dxos/ai';
8
8
  import { Obj } from '@dxos/echo';
@@ -12,7 +12,7 @@ import type { AnyEchoObject } from '@dxos/echo-schema';
12
12
  * Provides a way for compute primitives (functions, workflows, tools)
13
13
  * to emit an execution trace as a series of structured ECHO objects.
14
14
  */
15
- export class TracingService extends Context.Tag('TracingService')<
15
+ export class TracingService extends Context.Tag('@dxos/functions/TracingService')<
16
16
  TracingService,
17
17
  {
18
18
  /**
@@ -24,6 +24,8 @@ export class TracingService extends Context.Tag('TracingService')<
24
24
  >() {
25
25
  static noop: Context.Tag.Service<TracingService> = { write: () => {} };
26
26
 
27
+ static layerNoop = Layer.succeed(TracingService, TracingService.noop);
28
+
27
29
  static console: Context.Tag.Service<TracingService> = {
28
30
  write: (event) => {
29
31
  // eslint-disable-next-line no-console
@@ -6,11 +6,11 @@ import { Effect, type Context } from 'effect';
6
6
 
7
7
  import { LogLevel } from '@dxos/log';
8
8
 
9
- import { type EventLogger, createEventLogger } from '../services';
9
+ import { type ComputeEventLogger, createEventLogger } from '../services';
10
10
 
11
- export const noopLogger: Context.Tag.Service<EventLogger> = {
11
+ export const noopLogger: Context.Tag.Service<ComputeEventLogger> = {
12
12
  log: () => Effect.succeed(undefined),
13
13
  nodeId: undefined,
14
14
  };
15
15
 
16
- export const consoleLogger: Context.Tag.Service<EventLogger> = createEventLogger(LogLevel.INFO);
16
+ export const consoleLogger: Context.Tag.Service<ComputeEventLogger> = createEventLogger(LogLevel.INFO);
@@ -4,23 +4,21 @@
4
4
 
5
5
  import { type Context } from 'effect';
6
6
 
7
- import { AiService, type AiServiceClient, type AiServiceEdgeClientOptions, EdgeAiServiceClient } from '@dxos/ai';
8
- import { AI_SERVICE_ENDPOINT, createTestAiServiceClient } from '@dxos/ai/testing';
9
7
  import type { Space } from '@dxos/client/echo';
10
8
  import type { EchoDatabase, QueueFactory } from '@dxos/echo-db';
11
9
  import { assertArgument } from '@dxos/invariant';
12
10
 
13
- import { consoleLogger, noopLogger } from './logger';
14
11
  import {
15
12
  ConfiguredCredentialsService,
16
13
  type CredentialsService,
17
14
  DatabaseService,
18
- type EventLogger,
15
+ type ComputeEventLogger,
19
16
  QueueService,
20
17
  ServiceContainer,
21
18
  type ServiceCredential,
22
19
  type TracingService,
23
20
  } from '../services';
21
+ import { consoleLogger, noopLogger } from './logger';
24
22
 
25
23
  // TODO(burdon): Factor out.
26
24
  export type OneOf<T> = {
@@ -33,23 +31,7 @@ export type TestServiceOptions = {
33
31
  /**
34
32
  * AI service configuration.
35
33
  */
36
- ai?: OneOf<{
37
- /**
38
- * Custom AI service client.
39
- */
40
- client?: AiServiceClient;
41
-
42
- /**
43
- * Edge AI service at specified endpoint.
44
- */
45
- endpoint?: AiServiceEdgeClientOptions['endpoint'];
46
-
47
- /**
48
- * Predefined AI service configuration.
49
- */
50
- // TODO(burdon): 'dev' and 'edge' are redundant with providing an endpoint.
51
- provider?: AiServiceProvider;
52
- }>;
34
+ ai?: any;
53
35
 
54
36
  /**
55
37
  * Credentials service configuration.
@@ -82,7 +64,7 @@ export type TestServiceOptions = {
82
64
  */
83
65
  logging?: {
84
66
  enabled?: boolean;
85
- logger?: Context.Tag.Service<EventLogger>;
67
+ logger?: Context.Tag.Service<ComputeEventLogger>;
86
68
  };
87
69
 
88
70
  /**
@@ -95,6 +77,9 @@ export type TestServiceOptions = {
95
77
  };
96
78
  };
97
79
 
80
+ /**
81
+ * @deprecated
82
+ */
98
83
  export const createTestServices = ({
99
84
  ai,
100
85
  credentials,
@@ -107,7 +92,7 @@ export const createTestServices = ({
107
92
  assertArgument(!(!!space && (!!db || !!queues)), 'space can be provided only if db and queues are not');
108
93
 
109
94
  return new ServiceContainer().setServices({
110
- ai: createAiService(ai),
95
+ // ai: createAiService(ai),
111
96
  credentials: createCredentialsService(credentials),
112
97
  database: space || db ? DatabaseService.make(space?.db || db!) : undefined,
113
98
  eventLogger: (logging?.logger ?? logging?.enabled) ? consoleLogger : noopLogger,
@@ -116,45 +101,6 @@ export const createTestServices = ({
116
101
  });
117
102
  };
118
103
 
119
- // TODO(burdon): Enable model configuration.
120
- const createAiService = (ai: TestServiceOptions['ai']): Context.Tag.Service<AiService> | undefined => {
121
- if (ai?.client != null) {
122
- return AiService.make(ai.client);
123
- }
124
-
125
- if (ai?.endpoint != null) {
126
- return AiService.make(new EdgeAiServiceClient({ endpoint: ai.endpoint }));
127
- }
128
-
129
- switch (ai?.provider) {
130
- case 'dev':
131
- return AiService.make(
132
- new EdgeAiServiceClient({
133
- endpoint: AI_SERVICE_ENDPOINT.LOCAL,
134
- defaultGenerationOptions: {
135
- model: '@anthropic/claude-3-5-sonnet-20241022',
136
- },
137
- }),
138
- );
139
-
140
- case 'edge':
141
- return AiService.make(
142
- new EdgeAiServiceClient({
143
- endpoint: AI_SERVICE_ENDPOINT.REMOTE,
144
- defaultGenerationOptions: {
145
- model: '@anthropic/claude-3-5-sonnet-20241022',
146
- },
147
- }),
148
- );
149
-
150
- case 'ollama':
151
- return AiService.make(createTestAiServiceClient());
152
-
153
- case 'lmstudio':
154
- throw new Error('LMStudio is not supported');
155
- }
156
- };
157
-
158
104
  const createCredentialsService = (
159
105
  credentials: TestServiceOptions['credentials'] | undefined,
160
106
  ): Context.Tag.Service<CredentialsService> | undefined => {