@dxos/compute 0.8.4-main.ae835ea → 0.8.4-main.bc674ce

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,9 +1,13 @@
1
1
  {
2
2
  "name": "@dxos/compute",
3
- "version": "0.8.4-main.ae835ea",
3
+ "version": "0.8.4-main.bc674ce",
4
4
  "description": "Low-level compute API",
5
5
  "homepage": "https://dxos.org",
6
6
  "bugs": "https://github.com/dxos/dxos/issues",
7
+ "repository": {
8
+ "type": "git",
9
+ "url": "https://github.com/dxos/dxos"
10
+ },
7
11
  "license": "MIT",
8
12
  "author": "DXOS.org",
9
13
  "sideEffects": true,
@@ -35,35 +39,34 @@
35
39
  "src"
36
40
  ],
37
41
  "dependencies": {
38
- "@preact/signals-core": "^1.12.1",
39
- "effect": "3.18.3",
42
+ "effect": "3.19.11",
40
43
  "lodash.defaultsdeep": "^4.6.1",
41
- "@dxos/ai": "0.8.4-main.ae835ea",
42
- "@dxos/async": "0.8.4-main.ae835ea",
43
- "@dxos/client": "0.8.4-main.ae835ea",
44
- "@dxos/debug": "0.8.4-main.ae835ea",
45
- "@dxos/echo": "0.8.4-main.ae835ea",
46
- "@dxos/functions": "0.8.4-main.ae835ea",
47
- "@dxos/context": "0.8.4-main.ae835ea",
48
- "@dxos/keys": "0.8.4-main.ae835ea",
49
- "@dxos/live-object": "0.8.4-main.ae835ea",
50
- "@dxos/invariant": "0.8.4-main.ae835ea",
51
- "@dxos/log": "0.8.4-main.ae835ea",
52
- "@dxos/protocols": "0.8.4-main.ae835ea",
53
- "@dxos/plugin-automation": "0.8.4-main.ae835ea",
54
- "@dxos/schema": "0.8.4-main.ae835ea",
55
- "@dxos/util": "0.8.4-main.ae835ea",
56
- "@dxos/vendor-hyperformula": "0.8.4-main.ae835ea"
44
+ "@dxos/ai": "0.8.4-main.bc674ce",
45
+ "@dxos/async": "0.8.4-main.bc674ce",
46
+ "@dxos/context": "0.8.4-main.bc674ce",
47
+ "@dxos/debug": "0.8.4-main.bc674ce",
48
+ "@dxos/client": "0.8.4-main.bc674ce",
49
+ "@dxos/echo": "0.8.4-main.bc674ce",
50
+ "@dxos/functions": "0.8.4-main.bc674ce",
51
+ "@dxos/functions-runtime": "0.8.4-main.bc674ce",
52
+ "@dxos/invariant": "0.8.4-main.bc674ce",
53
+ "@dxos/keys": "0.8.4-main.bc674ce",
54
+ "@dxos/log": "0.8.4-main.bc674ce",
55
+ "@dxos/plugin-automation": "0.8.4-main.bc674ce",
56
+ "@dxos/schema": "0.8.4-main.bc674ce",
57
+ "@dxos/util": "0.8.4-main.bc674ce",
58
+ "@dxos/protocols": "0.8.4-main.bc674ce",
59
+ "@dxos/vendor-hyperformula": "0.8.4-main.bc674ce"
57
60
  },
58
61
  "devDependencies": {
59
62
  "@tldraw/indices": "^2.0.0-alpha.14",
60
63
  "@types/lodash.defaultsdeep": "^4.6.6",
61
- "@dxos/echo": "0.8.4-main.ae835ea",
62
- "@dxos/random": "0.8.4-main.ae835ea",
63
- "@dxos/echo-db": "0.8.4-main.ae835ea"
64
+ "@dxos/echo": "0.8.4-main.bc674ce",
65
+ "@dxos/echo-db": "0.8.4-main.bc674ce",
66
+ "@dxos/random": "0.8.4-main.bc674ce"
64
67
  },
65
68
  "peerDependencies": {
66
- "effect": "^3.13.3"
69
+ "effect": "3.19.11"
67
70
  },
68
71
  "publishConfig": {
69
72
  "access": "public"
@@ -6,7 +6,7 @@ import * as Schema from 'effect/Schema';
6
6
  import { describe, expect, onTestFinished, test } from 'vitest';
7
7
 
8
8
  import { Trigger } from '@dxos/async';
9
- import { fullyQualifiedId } from '@dxos/client/echo';
9
+ import { Obj } from '@dxos/echo';
10
10
  import { Function, FunctionDefinition } from '@dxos/functions';
11
11
 
12
12
  import { ComputeGraphRegistry, defaultPlugins } from './compute-graph-registry';
@@ -23,8 +23,13 @@ describe('ComputeGraphRegistry', () => {
23
23
  });
24
24
 
25
25
  test('invokes user function through compute graph', async () => {
26
- const computeRuntime = createMockedComputeRuntimeProvider({ functions: [add] });
27
- const testBuilder = new TestBuilder({ types: [Function.Function], computeRuntime });
26
+ const computeRuntime = createMockedComputeRuntimeProvider({
27
+ functions: [add],
28
+ });
29
+ const testBuilder = new TestBuilder({
30
+ types: [Function.Function],
31
+ computeRuntime,
32
+ });
28
33
  await testBuilder.open();
29
34
  onTestFinished(async () => {
30
35
  await testBuilder.close();
@@ -33,7 +38,10 @@ describe('ComputeGraphRegistry', () => {
33
38
  const space = await testBuilder.client.spaces.create();
34
39
 
35
40
  // Register Edge function plugin and runtime in the registry.
36
- const registry = new ComputeGraphRegistry({ plugins: defaultPlugins, computeRuntime });
41
+ const registry = new ComputeGraphRegistry({
42
+ plugins: defaultPlugins,
43
+ computeRuntime,
44
+ });
37
45
  await registry.open();
38
46
  onTestFinished(async () => {
39
47
  await registry.close();
@@ -47,7 +55,9 @@ describe('ComputeGraphRegistry', () => {
47
55
 
48
56
  // Create a function object in ECHO with binding that maps to DX calls.
49
57
  const functionObj = FunctionDefinition.serialize(add);
50
- functionObj.binding = 'ADD';
58
+ Obj.change(functionObj, (f) => {
59
+ f.binding = 'ADD';
60
+ });
51
61
  space.db.add(functionObj);
52
62
 
53
63
  const node = await graph.getOrCreateNode('sheet').open();
@@ -69,12 +79,17 @@ describe('ComputeGraphRegistry', () => {
69
79
 
70
80
  // Sanity check: mapping to fully qualified id works as well.
71
81
  const bindingId = graph.mapFunctionBindingToId('ADD(2, 3)');
72
- expect(bindingId.startsWith(`${fullyQualifiedId(functionObj)}`)).to.be.true;
82
+ expect(bindingId.startsWith(`${Obj.getDXN(functionObj).toString()}`)).to.be.true;
73
83
  });
74
84
 
75
85
  test('adding a function binding updates autocomplete and enables execution', async () => {
76
- const computeRuntime = createMockedComputeRuntimeProvider({ functions: [add] });
77
- const testBuilder = new TestBuilder({ types: [Function.Function], computeRuntime });
86
+ const computeRuntime = createMockedComputeRuntimeProvider({
87
+ functions: [add],
88
+ });
89
+ const testBuilder = new TestBuilder({
90
+ types: [Function.Function],
91
+ computeRuntime,
92
+ });
78
93
  await testBuilder.open();
79
94
  onTestFinished(async () => {
80
95
  await testBuilder.close();
@@ -82,7 +97,10 @@ describe('ComputeGraphRegistry', () => {
82
97
 
83
98
  const space = await testBuilder.client.spaces.create();
84
99
 
85
- const registry = new ComputeGraphRegistry({ plugins: defaultPlugins, computeRuntime });
100
+ const registry = new ComputeGraphRegistry({
101
+ plugins: defaultPlugins,
102
+ computeRuntime,
103
+ });
86
104
  await registry.open();
87
105
  onTestFinished(async () => {
88
106
  await registry.close();
@@ -108,13 +126,15 @@ describe('ComputeGraphRegistry', () => {
108
126
 
109
127
  // Add a bound function to the space; graph should pick it up.
110
128
  const functionObj = FunctionDefinition.serialize(add);
111
- functionObj.binding = 'ADD';
129
+ Obj.change(functionObj, (f) => {
130
+ f.binding = 'ADD';
131
+ });
112
132
  space.db.add(functionObj);
113
133
 
114
134
  await functionsUpdated.wait();
115
135
 
116
136
  // Autocomplete should now include the binding.
117
- const echoFunctions = graph.getFunctions({ standard: false, echo: true }).map((f) => f.name);
137
+ const echoFunctions = graph.getFunctions({ standard: false, echo: true }).map((fn) => fn.name);
118
138
  expect(echoFunctions).toContain('ADD');
119
139
 
120
140
  // And the binding should execute when used in a formula.
@@ -5,7 +5,7 @@
5
5
  import { afterEach, beforeEach, describe, expect, test } from 'vitest';
6
6
 
7
7
  import { Trigger } from '@dxos/async';
8
- import { fullyQualifiedId } from '@dxos/client/echo';
8
+ import { Obj } from '@dxos/echo';
9
9
  import { Function } from '@dxos/functions';
10
10
  import { type CellValue } from '@dxos/vendor-hyperformula';
11
11
  import { DetailedCellError } from '@dxos/vendor-hyperformula';
@@ -36,7 +36,7 @@ describe('ComputeGraph', () => {
36
36
  expect(functions).to.toHaveLength(1);
37
37
 
38
38
  const id = graph.mapFunctionBindingToId('TEST()');
39
- expect(id).to.eq(`${fullyQualifiedId(functionObject)}()`);
39
+ expect(id).to.eq(`${Obj.getDXN(functionObject).toString()}()`);
40
40
  });
41
41
 
42
42
  test('cross-node references', async () => {
@@ -51,22 +51,38 @@ describe('ComputeGraph', () => {
51
51
  {
52
52
  node1.graph.hf.setCellContents({ sheet: node1.sheetId, row: 0, col: 0 }, [[100, 200, 300, '=SUM(A1:C1)']]);
53
53
  node2.graph.hf.setCellContents({ sheet: node2.sheetId, row: 0, col: 0 }, "='node-1'!D1");
54
- const value1 = node1.graph.hf.getCellValue({ sheet: node1.sheetId, col: 3, row: 0 });
55
- const value2 = node2.graph.hf.getCellValue({ sheet: node2.sheetId, col: 0, row: 0 });
54
+ const value1 = node1.graph.hf.getCellValue({
55
+ sheet: node1.sheetId,
56
+ col: 3,
57
+ row: 0,
58
+ });
59
+ const value2 = node2.graph.hf.getCellValue({
60
+ sheet: node2.sheetId,
61
+ col: 0,
62
+ row: 0,
63
+ });
56
64
  expect(value1).to.eq(value2);
57
65
  }
58
66
 
59
67
  // Get updated event.
60
68
  const trigger = new Trigger<CellValue>();
61
69
  node2.update.on(({ change }) => {
62
- const value = node2.graph.hf.getCellValue({ sheet: node2.sheetId, col: 0, row: 0 });
70
+ const value = node2.graph.hf.getCellValue({
71
+ sheet: node2.sheetId,
72
+ col: 0,
73
+ row: 0,
74
+ });
63
75
  expect(value).to.eq(change?.newValue);
64
76
  trigger.wake(value);
65
77
  });
66
78
 
67
79
  {
68
80
  node1.graph.hf.setCellContents({ sheet: node1.sheetId, row: 0, col: 0 }, 400);
69
- const value1 = node1.graph.hf.getCellValue({ sheet: node1.sheetId, col: 3, row: 0 });
81
+ const value1 = node1.graph.hf.getCellValue({
82
+ sheet: node1.sheetId,
83
+ col: 3,
84
+ row: 0,
85
+ });
70
86
  const value2 = await trigger.wait();
71
87
  expect(value1).to.eq(value2);
72
88
  }
@@ -80,7 +96,11 @@ describe('ComputeGraph', () => {
80
96
 
81
97
  const node1 = await graph.getOrCreateNode('node-1').open();
82
98
  node1.graph.hf.setCellContents({ sheet: node1.sheetId, row: 0, col: 0 }, "='node-2'!A1");
83
- const value1 = node1.graph.hf.getCellValue({ sheet: node1.sheetId, col: 0, row: 0 });
99
+ const value1 = node1.graph.hf.getCellValue({
100
+ sheet: node1.sheetId,
101
+ col: 0,
102
+ row: 0,
103
+ });
84
104
  expect(value1).to.be.instanceof(DetailedCellError);
85
105
  expect((value1 as DetailedCellError).type).to.eq('REF');
86
106
  });
@@ -2,14 +2,13 @@
2
2
  // Copyright 2024 DXOS.org
3
3
  //
4
4
 
5
- import { effect } from '@preact/signals-core';
6
5
  import type * as ManagedRuntime from 'effect/ManagedRuntime';
7
6
 
8
7
  import { Event } from '@dxos/async';
9
- import { Filter, type Space, fullyQualifiedId } from '@dxos/client/echo';
8
+ import { Filter, type Space } from '@dxos/client/echo';
10
9
  import { FQ_ID_LENGTH } from '@dxos/client/echo';
11
10
  import { Resource } from '@dxos/context';
12
- import { getTypename } from '@dxos/echo/internal';
11
+ import { Obj } from '@dxos/echo';
13
12
  import { Function, type FunctionInvocationService } from '@dxos/functions';
14
13
  import { invariant } from '@dxos/invariant';
15
14
  import { PublicKey } from '@dxos/keys';
@@ -107,7 +106,10 @@ export class ComputeGraph extends Resource {
107
106
  }
108
107
 
109
108
  getFunctions(
110
- { standard, echo }: { standard?: boolean; echo?: boolean } = { standard: true, echo: true },
109
+ { standard, echo }: { standard?: boolean; echo?: boolean } = {
110
+ standard: true,
111
+ echo: true,
112
+ },
111
113
  ): FunctionDefinition[] {
112
114
  return [
113
115
  ...(standard
@@ -167,7 +169,7 @@ export class ComputeGraph extends Resource {
167
169
 
168
170
  for (const obj of objects) {
169
171
  if (obj.name === name) {
170
- const type = getTypename(obj)!;
172
+ const type = Obj.getTypename(obj)!;
171
173
  // NOTE: Names must be single quoted.
172
174
  return `'${createSheetName({ type, id: obj.id })}'!`;
173
175
  }
@@ -207,7 +209,7 @@ export class ComputeGraph extends Resource {
207
209
 
208
210
  const fn = this._remoteFunctions.find((fn) => fn.binding === binding);
209
211
  if (fn) {
210
- const id = fullyQualifiedId(fn);
212
+ const id = Obj.getDXN(fn).toString();
211
213
  return `${id}(${args})`;
212
214
  } else {
213
215
  return match;
@@ -226,7 +228,7 @@ export class ComputeGraph extends Resource {
226
228
  return match;
227
229
  }
228
230
 
229
- const fn = this._remoteFunctions.find((fn) => fullyQualifiedId(fn) === id);
231
+ const fn = this._remoteFunctions.find((fn) => Obj.getDXN(fn).toString() === id);
230
232
  if (fn?.binding) {
231
233
  return `${fn.binding}(${args})`;
232
234
  } else {
@@ -245,16 +247,12 @@ export class ComputeGraph extends Resource {
245
247
  if (this._space) {
246
248
  // Subscribe to remote function definitions.
247
249
  const query = this._space.db.query(Filter.type(Function.Function));
248
- const unsubscribe = query.subscribe();
249
- const dispose = effect(() => {
250
- this._remoteFunctions = query.objects.filter(({ binding }) => binding);
250
+ const unsubscribe = query.subscribe(() => {
251
+ this._remoteFunctions = query.results.filter((fn) => fn.binding);
251
252
  this.update.emit({ type: 'functionsUpdated' });
252
253
  });
253
254
 
254
- this._ctx.onDispose(() => {
255
- unsubscribe();
256
- dispose();
257
- });
255
+ this._ctx.onDispose(unsubscribe);
258
256
  }
259
257
  }
260
258
 
@@ -2,13 +2,12 @@
2
2
  // Copyright 2024 DXOS.org
3
3
  //
4
4
 
5
- import { effect } from '@preact/signals-core';
6
5
  import * as Effect from 'effect/Effect';
7
6
  import * as SchemaAST from 'effect/SchemaAST';
8
7
 
9
8
  import { Filter } from '@dxos/client/echo';
10
- import { toEffectSchema } from '@dxos/echo/internal';
11
- import { ComputeEventLogger, Function, FunctionInvocationService, TracingService } from '@dxos/functions';
9
+ import { JsonSchema, Obj } from '@dxos/echo';
10
+ import { Function, FunctionInvocationService, TracingService } from '@dxos/functions';
12
11
  import { FunctionDefinition } from '@dxos/functions';
13
12
  import { log } from '@dxos/log';
14
13
  import { isNonNullable } from '@dxos/util';
@@ -36,22 +35,20 @@ export class EdgeFunctionPlugin extends AsyncFunctionPlugin {
36
35
  return new CellError(ErrorType.REF, 'Missing space');
37
36
  }
38
37
 
39
- const {
40
- objects: [fn],
41
- } = await space.db.query(Filter.type(Function.Function, { binding })).run();
38
+ const [fn] = await space.db.query(Filter.type(Function.Function, { binding })).run();
42
39
  if (!fn) {
43
40
  log.info('Function not found', { binding });
44
41
  return new CellError(ErrorType.REF, 'Function not found');
45
42
  }
46
43
 
47
44
  if (subscribe) {
48
- const unsubscribe = effect(() => {
45
+ const unsubscribe = Obj.subscribe(fn, () => {
49
46
  log('function changed', { fn });
50
- const _ = fn?.version;
51
-
52
47
  // TODO(wittjosiah): `ttl` should be 0 to force a recalculation when a new version is deployed.
53
48
  // This needs a ttl to prevent a binding change from causing the function not to be found.
54
- this.runAsyncFunction(ast, state, handler(false), { ttl: FUNCTION_TTL });
49
+ this.runAsyncFunction(ast, state, handler(false), {
50
+ ttl: FUNCTION_TTL,
51
+ });
55
52
  });
56
53
 
57
54
  this.context.createSubscription(ast.procedureName, unsubscribe);
@@ -62,7 +59,7 @@ export class EdgeFunctionPlugin extends AsyncFunctionPlugin {
62
59
  // If input schema exists, construct an object from args using the schema props order, otherwise pass { args }.
63
60
  let input: any;
64
61
  if (fn.inputSchema) {
65
- const schema = toEffectSchema(fn.inputSchema);
62
+ const schema = JsonSchema.toEffectSchema(fn.inputSchema);
66
63
  const props = SchemaAST.getPropertySignatures(schema.ast);
67
64
  input = {} as any;
68
65
  props.forEach(({ name }, index) => {
@@ -74,12 +71,14 @@ export class EdgeFunctionPlugin extends AsyncFunctionPlugin {
74
71
  const result = runtime.runPromise(
75
72
  Effect.gen(function* () {
76
73
  return yield* FunctionInvocationService.invokeFunction(functionDef, input);
77
- }).pipe(Effect.provide(ComputeEventLogger.layerFromTracing), Effect.provide(TracingService.layerNoop)),
74
+ }).pipe(Effect.provide(TracingService.layerNoop)),
78
75
  );
79
76
  return result as any;
80
77
  };
81
78
 
82
- return this.runAsyncFunction(ast, state, handler(true), { ttl: FUNCTION_TTL });
79
+ return this.runAsyncFunction(ast, state, handler(true), {
80
+ ttl: FUNCTION_TTL,
81
+ });
83
82
  }
84
83
  }
85
84
 
@@ -7,13 +7,9 @@ import * as ManagedRuntime from 'effect/ManagedRuntime';
7
7
 
8
8
  import { AiService } from '@dxos/ai';
9
9
  import { type SpaceId } from '@dxos/client/echo';
10
- import {
11
- CredentialsService,
12
- DatabaseService,
13
- type FunctionDefinition,
14
- FunctionInvocationService,
15
- QueueService,
16
- } from '@dxos/functions';
10
+ import { Database } from '@dxos/echo';
11
+ import { CredentialsService, type FunctionDefinition, QueueService } from '@dxos/functions';
12
+ import { FunctionInvocationServiceLayerTest } from '@dxos/functions-runtime/testing';
17
13
 
18
14
  import { type FunctionsRuntimeProvider } from '../compute-graph-registry';
19
15
 
@@ -23,14 +19,14 @@ import { type FunctionsRuntimeProvider } from '../compute-graph-registry';
23
19
  */
24
20
  export const createMockedComputeRuntimeProvider = ({
25
21
  functions,
26
- }: { functions?: FunctionDefinition<any, any>[] } = {}): FunctionsRuntimeProvider => {
22
+ }: { functions?: FunctionDefinition.Any[] } = {}): FunctionsRuntimeProvider => {
27
23
  return {
28
24
  getRuntime: (_spaceId: SpaceId) =>
29
25
  ManagedRuntime.make(
30
- FunctionInvocationService.layerTest({ functions }).pipe(
26
+ FunctionInvocationServiceLayerTest({ functions }).pipe(
31
27
  Layer.provide(AiService.notAvailable),
32
28
  Layer.provide(CredentialsService.configuredLayer([])),
33
- Layer.provide(DatabaseService.notAvailable),
29
+ Layer.provide(Database.Service.notAvailable),
34
30
  Layer.provide(QueueService.notAvailable),
35
31
  ),
36
32
  ),