@dxos/assistant 0.8.4-main.3f58842 → 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.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@dxos/assistant",
3
- "version": "0.8.4-main.3f58842",
3
+ "version": "0.8.4-main.5acf9ea",
4
4
  "description": "Natural language interface to DXOS",
5
5
  "homepage": "https://dxos.org",
6
6
  "bugs": "https://github.com/dxos/dxos/issues",
@@ -12,7 +12,8 @@
12
12
  ".": {
13
13
  "types": "./dist/types/src/index.d.ts",
14
14
  "browser": "./dist/lib/browser/index.mjs",
15
- "node": "./dist/lib/node-esm/index.mjs"
15
+ "node": "./dist/lib/node-esm/index.mjs",
16
+ "source": "./src/index.ts"
16
17
  }
17
18
  },
18
19
  "types": "dist/types/src/index.d.ts",
@@ -31,26 +32,26 @@
31
32
  "exa-js": "^1.5.12",
32
33
  "handlebars": "4.7.8",
33
34
  "lodash.defaultsdeep": "^4.6.1",
34
- "@dxos/async": "0.8.4-main.3f58842",
35
- "@dxos/ai": "0.8.4-main.3f58842",
36
- "@dxos/blueprints": "0.8.4-main.3f58842",
37
- "@dxos/context": "0.8.4-main.3f58842",
38
- "@dxos/debug": "0.8.4-main.3f58842",
39
- "@dxos/echo": "0.8.4-main.3f58842",
40
- "@dxos/echo-schema": "0.8.4-main.3f58842",
41
- "@dxos/echo-protocol": "0.8.4-main.3f58842",
42
- "@dxos/echo-db": "0.8.4-main.3f58842",
43
- "@dxos/effect": "0.8.4-main.3f58842",
44
- "@dxos/errors": "0.8.4-main.3f58842",
45
- "@dxos/functions": "0.8.4-main.3f58842",
46
- "@dxos/invariant": "0.8.4-main.3f58842",
47
- "@dxos/keys": "0.8.4-main.3f58842",
48
- "@dxos/graph": "0.8.4-main.3f58842",
49
- "@dxos/live-object": "0.8.4-main.3f58842",
50
- "@dxos/log": "0.8.4-main.3f58842",
51
- "@dxos/node-std": "0.8.4-main.3f58842",
52
- "@dxos/schema": "0.8.4-main.3f58842",
53
- "@dxos/util": "0.8.4-main.3f58842"
35
+ "@dxos/ai": "0.8.4-main.5acf9ea",
36
+ "@dxos/async": "0.8.4-main.5acf9ea",
37
+ "@dxos/blueprints": "0.8.4-main.5acf9ea",
38
+ "@dxos/context": "0.8.4-main.5acf9ea",
39
+ "@dxos/debug": "0.8.4-main.5acf9ea",
40
+ "@dxos/echo-db": "0.8.4-main.5acf9ea",
41
+ "@dxos/echo-protocol": "0.8.4-main.5acf9ea",
42
+ "@dxos/echo-schema": "0.8.4-main.5acf9ea",
43
+ "@dxos/echo": "0.8.4-main.5acf9ea",
44
+ "@dxos/effect": "0.8.4-main.5acf9ea",
45
+ "@dxos/errors": "0.8.4-main.5acf9ea",
46
+ "@dxos/functions": "0.8.4-main.5acf9ea",
47
+ "@dxos/invariant": "0.8.4-main.5acf9ea",
48
+ "@dxos/keys": "0.8.4-main.5acf9ea",
49
+ "@dxos/graph": "0.8.4-main.5acf9ea",
50
+ "@dxos/live-object": "0.8.4-main.5acf9ea",
51
+ "@dxos/log": "0.8.4-main.5acf9ea",
52
+ "@dxos/node-std": "0.8.4-main.5acf9ea",
53
+ "@dxos/util": "0.8.4-main.5acf9ea",
54
+ "@dxos/schema": "0.8.4-main.5acf9ea"
54
55
  },
55
56
  "devDependencies": {
56
57
  "@types/lodash.defaultsdeep": "^4.6.6",
@@ -2,35 +2,23 @@
2
2
  // Copyright 2025 DXOS.org
3
3
  //
4
4
 
5
- import { describe, test, beforeAll } from 'vitest';
5
+ import { beforeAll, describe, test } from 'vitest';
6
6
 
7
- import { EdgeAiServiceClient } from '@dxos/ai';
8
- import { AI_SERVICE_ENDPOINT } from '@dxos/ai/testing';
9
- import { FunctionExecutor, ServiceContainer } from '@dxos/functions';
7
+ import { todo } from '@dxos/debug';
8
+ import { FunctionExecutor } from '@dxos/functions';
10
9
  import { log } from '@dxos/log';
11
10
  import { createTestData } from '@dxos/schema/testing';
12
11
  import { range } from '@dxos/util';
13
12
 
14
- import { extractionAnthropicFn } from './extraction-llm-function';
15
13
  import { processTranscriptMessage } from '../extraction';
14
+ import { extractionAnthropicFn } from './extraction-llm-function';
16
15
 
16
+ // TODO(burdon): Rewrite test.
17
17
  describe.skip('LLM EntityExtraction', () => {
18
18
  let executor: FunctionExecutor;
19
19
 
20
20
  beforeAll(async () => {
21
- executor = new FunctionExecutor(
22
- new ServiceContainer().setServices({
23
- ai: {
24
- client: new EdgeAiServiceClient({
25
- endpoint: AI_SERVICE_ENDPOINT.REMOTE,
26
- defaultGenerationOptions: {
27
- // model: '@anthropic/claude-sonnet-4-20250514',
28
- model: '@anthropic/claude-3-5-haiku-20241022',
29
- },
30
- }),
31
- } as any, // TODO(burdon): Rewrite test.
32
- }),
33
- );
21
+ executor = new FunctionExecutor(todo());
34
22
  });
35
23
 
36
24
  test('should process a transcript block', async () => {
@@ -6,8 +6,7 @@ import { AiTool } from '@effect/ai';
6
6
  import { Context, Effect, Layer, Match, Predicate, Record, Schema } from 'effect';
7
7
 
8
8
  import { AiToolNotFoundError, ToolExecutionService, ToolResolverService } from '@dxos/ai';
9
- import { todo } from '@dxos/debug';
10
- import { FunctionError, type FunctionContext, type FunctionDefinition, type Services } from '@dxos/functions';
9
+ import { LocalFunctionExecutionService, type FunctionDefinition } from '@dxos/functions';
11
10
  import { invariant } from '@dxos/invariant';
12
11
 
13
12
  export const makeToolResolverFromFunctions = (
@@ -27,24 +26,32 @@ export const makeToolResolverFromFunctions = (
27
26
 
28
27
  export const makeToolExecutionServiceFromFunctions = (
29
28
  functions: FunctionDefinition<any, any>[],
30
- ): Layer.Layer<ToolExecutionService> => {
31
- return Layer.succeed(ToolExecutionService, {
32
- handlersFor: (toolkit) => {
33
- const makeHandler = (tool: AiTool.Any): ((params: unknown) => Effect.Effect<unknown, any, any>) => {
34
- return Effect.fn('toolFunctionHandler')(function* (input: any) {
35
- const { functionName } = Context.get(FunctionToolAnnotation)(tool.annotations as any);
36
- const fnDef = functions.find((f) => f.name === functionName);
37
- if (!fnDef) {
38
- return yield* Effect.fail(new AiToolNotFoundError(tool.name));
39
- }
40
-
41
- return yield* invokeFunction(fnDef, input).pipe(Effect.catchAllDefect((defect) => Effect.fail(defect)));
42
- });
29
+ ): Layer.Layer<ToolExecutionService, never, LocalFunctionExecutionService> => {
30
+ return Layer.effect(
31
+ ToolExecutionService,
32
+ Effect.gen(function* () {
33
+ const localFunctionExecutionService = yield* LocalFunctionExecutionService;
34
+ return {
35
+ handlersFor: (toolkit) => {
36
+ const makeHandler = (tool: AiTool.Any): ((params: unknown) => Effect.Effect<unknown, any, any>) => {
37
+ return Effect.fn('toolFunctionHandler')(function* (input: any) {
38
+ const { functionName } = Context.get(FunctionToolAnnotation)(tool.annotations as any);
39
+ const fnDef = functions.find((f) => f.name === functionName);
40
+ if (!fnDef) {
41
+ return yield* Effect.fail(new AiToolNotFoundError(tool.name));
42
+ }
43
+
44
+ return yield* localFunctionExecutionService
45
+ .invokeFunction(fnDef, input)
46
+ .pipe(Effect.catchAllDefect((defect) => Effect.fail(defect)));
47
+ });
48
+ };
49
+
50
+ return toolkit.of(Record.map(toolkit.tools, (tool, name) => makeHandler(tool)) as any) as any;
51
+ },
43
52
  };
44
-
45
- return toolkit.of(Record.map(toolkit.tools, (tool, name) => makeHandler(tool)) as any) as any;
46
- },
47
- });
53
+ }),
54
+ );
48
55
  };
49
56
 
50
57
  /**
@@ -90,50 +97,3 @@ const createStructFieldsFromSchema = (schema: Schema.Schema<any, any>): Record<s
90
97
  Match.orElseAbsurd,
91
98
  );
92
99
  };
93
-
94
- // TODO(dmaretskyi): Factor out.
95
- const invokeFunction = (fnDef: FunctionDefinition<any, any>, input: any): Effect.Effect<unknown, never, Services> =>
96
- Effect.gen(function* () {
97
- // Assert input matches schema
98
- const assertInput = fnDef.inputSchema.pipe(Schema.asserts);
99
- (assertInput as any)(input);
100
-
101
- const context: FunctionContext = {
102
- getService: () => todo(),
103
- getSpace: async (_spaceId: any) => {
104
- throw new Error('Not available. Use the database service instead.');
105
- },
106
- space: undefined,
107
- get ai(): never {
108
- throw new Error('Not available. Use the ai service instead.');
109
- },
110
- };
111
-
112
- // TODO(dmaretskyi): This should be delegated to a function invoker service.
113
- const data = yield* Effect.gen(function* () {
114
- const result = fnDef.handler({ context, data: input });
115
- if (Effect.isEffect(result)) {
116
- return yield* (result as Effect.Effect<unknown, unknown, Services>).pipe(Effect.orDie);
117
- } else if (
118
- typeof result === 'object' &&
119
- result !== null &&
120
- 'then' in result &&
121
- typeof result.then === 'function'
122
- ) {
123
- return yield* Effect.promise(() => result);
124
- } else {
125
- return result;
126
- }
127
- }).pipe(
128
- Effect.orDie,
129
- Effect.catchAllDefect((defect) =>
130
- Effect.die(new FunctionError('Error running function', { context: { name: fnDef.name }, cause: defect })),
131
- ),
132
- );
133
-
134
- // Assert output matches schema
135
- const assertOutput = fnDef.outputSchema?.pipe(Schema.asserts);
136
- (assertOutput as any)(data);
137
-
138
- return data;
139
- }).pipe(Effect.withSpan('invokeFunction', { attributes: { name: fnDef.name } }));
@@ -134,7 +134,7 @@ export const LocalSearchHandler = LocalSearchToolkit.toLayer({
134
134
  /**
135
135
  * Attached as an annotation to the writer tool.
136
136
  */
137
- class GraphWriterSchema extends Context.Tag('GraphWriterSchema')<
137
+ class GraphWriterSchema extends Context.Tag('@dxos/assistant/GraphWriterSchema')<
138
138
  GraphWriterSchema,
139
139
  { schema: Schema.Schema.AnyNoContext[] }
140
140
  >() {}
@@ -109,12 +109,12 @@ describe.runIf(process.env.DX_RUN_SLOW_TESTS)('AiSession', () => {
109
109
  ),
110
110
  );
111
111
 
112
+ // TODO(dmaretskyi): Revive test.
112
113
  /*
113
114
  it.skip('create calendar itinerary', { timeout: 60_000 }, async () => {
114
- const aiClient = new EdgeAiServiceClient({ endpoint: AI_SERVICE_ENDPOINT.REMOTE });
115
- // const aiClient = new OllamaAiServiceClient({
115
+
116
116
  // overrides: { model: 'llama3.1:8b' },
117
- // });
117
+
118
118
  const session = new AiSession({ operationModel: 'configured' });
119
119
 
120
120
  const objects = new Set<string>();
@@ -137,7 +137,7 @@ export class AiSession {
137
137
  // TODO(dmaretskyi): Loading BP from the Database should be done at the higher level. We need a type for the resolved blueprint.
138
138
  const systemPrompt = yield* pipe(
139
139
  blueprints,
140
- Effect.forEach((blueprint) => DatabaseService.loadRef(blueprint.instructions)),
140
+ Effect.forEach((blueprint) => Effect.succeed(blueprint.instructions)),
141
141
  Effect.flatMap(Effect.forEach((template) => DatabaseService.loadRef(template.source))),
142
142
  Effect.map(Array.map((template) => `\n\n<blueprint>${template.content}</blueprint>`)),
143
143
  Effect.map(Array.reduce(options.systemPrompt ?? '', String.concat)),
@@ -305,7 +305,7 @@ const createArtifactUpdateBlock = (
305
305
  * Can be optionally provided to the session run call.
306
306
  */
307
307
  // TODO(dmaretskyi): Convert to Context.Reference
308
- export class ArtifactDiffResolver extends Context.Tag('ArtifactDiffResolver')<
308
+ export class ArtifactDiffResolver extends Context.Tag('@dxos/assistant/ArtifactDiffResolver')<
309
309
  ArtifactDiffResolver,
310
310
  ArtifactDiffResolver.Service
311
311
  >() {}
@@ -8,8 +8,7 @@
8
8
  import { pipe, Schema } from 'effect';
9
9
  import { beforeAll, describe, test } from 'vitest';
10
10
 
11
- import { EdgeAiServiceClient, MixedStreamParser, OllamaAiServiceClient, AiService } from '@dxos/ai';
12
- import { AI_SERVICE_ENDPOINT } from '@dxos/ai/testing';
11
+ import { AiService, MixedStreamParser } from '@dxos/ai';
13
12
  import { Obj } from '@dxos/echo';
14
13
  import { type EchoDatabase } from '@dxos/echo-db';
15
14
  import { EchoTestBuilder } from '@dxos/echo-db/testing';
@@ -79,9 +78,8 @@ const summarizationFn = defineFunction({
79
78
  ],
80
79
  }),
81
80
  );
82
- return Obj.make(DataType.Text, {
83
- content: pipe(result[0]?.blocks[0], (c) => (c?._tag === 'text' ? c.text : '')),
84
- });
81
+
82
+ return DataType.makeText(pipe(result[0]?.blocks[0], (c) => (c?._tag === 'text' ? c.text : '')));
85
83
  },
86
84
  });
87
85
 
@@ -136,9 +134,7 @@ const refinementFn = defineFunction({
136
134
  }),
137
135
  );
138
136
  return {
139
- summary: Obj.make(DataType.Text, {
140
- content: pipe(result[0]?.blocks[0], (c) => (c?._tag === 'text' ? c.text : '')),
141
- }),
137
+ summary: DataType.makeText(pipe(result[0]?.blocks[0], (c) => (c?._tag === 'text' ? c.text : ''))),
142
138
  };
143
139
  },
144
140
  });
@@ -148,6 +144,7 @@ describe.skip('Summarization', () => {
148
144
  let db: EchoDatabase;
149
145
  let executor: FunctionExecutor;
150
146
 
147
+ // TODO(burdon): Rewrite test.
151
148
  beforeAll(async () => {
152
149
  // TODO(dmaretskyi): Helper to scaffold this from a config.
153
150
  builder = await new EchoTestBuilder().open();
@@ -155,21 +152,7 @@ describe.skip('Summarization', () => {
155
152
  db = db1;
156
153
  executor = new FunctionExecutor(
157
154
  new ServiceContainer().setServices({
158
- ai: {
159
- client: REMOTE_AI
160
- ? new EdgeAiServiceClient({
161
- endpoint: AI_SERVICE_ENDPOINT.REMOTE,
162
- defaultGenerationOptions: {
163
- // model: '@anthropic/claude-sonnet-4-20250514',
164
- model: '@anthropic/claude-3-5-sonnet-20241022',
165
- },
166
- })
167
- : new OllamaAiServiceClient({
168
- overrides: {
169
- model: 'llama3.1:8b',
170
- },
171
- }),
172
- } as any, // TODO(burdon): Rewrite test.
155
+ ai: todo(),
173
156
  database: {
174
157
  db,
175
158
  },
@@ -180,9 +163,7 @@ describe.skip('Summarization', () => {
180
163
  test('keeps transcript outline', { timeout: 1000_000 }, async () => {
181
164
  const { transcriptMessages } = createTestData();
182
165
 
183
- const summary = Obj.make(DataType.Text, {
184
- content: '',
185
- });
166
+ const summary = DataType.makeText();
186
167
 
187
168
  const summaries = [];
188
169
 
@@ -193,12 +174,10 @@ describe.skip('Summarization', () => {
193
174
  transcript: blocks,
194
175
  });
195
176
  summary.content = result.content;
196
- summaries.push(Obj.make(DataType.Text, { content: result.content }));
177
+ summaries.push(DataType.makeText(result.content));
197
178
 
198
179
  console.log(blocks.at(-1));
199
180
  console.log();
200
- console.log('--------------------------------');
201
- console.log();
202
181
  console.log(summary.content);
203
182
  console.log();
204
183
 
@@ -208,12 +187,10 @@ describe.skip('Summarization', () => {
208
187
  summaries: history,
209
188
  });
210
189
  summary.content = result.summary.content;
211
- summaries.push(Obj.make(DataType.Text, { content: result.summary.content }));
190
+ summaries.push(DataType.makeText(result.summary.content));
212
191
 
213
192
  console.log('REFINED');
214
193
  console.log();
215
- console.log('--------------------------------');
216
- console.log();
217
194
  console.log(summary.content);
218
195
  console.log();
219
196
  }