@dxos/assistant 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.
Files changed (116) hide show
  1. package/dist/lib/browser/{chunk-4VIJTKPM.mjs → chunk-7CDDG6LL.mjs} +252 -28
  2. package/dist/lib/browser/chunk-7CDDG6LL.mjs.map +7 -0
  3. package/dist/lib/browser/chunk-J5LGTIGS.mjs +10 -0
  4. package/dist/lib/browser/extraction/index.mjs +119 -166
  5. package/dist/lib/browser/extraction/index.mjs.map +4 -4
  6. package/dist/lib/browser/index.mjs +239 -289
  7. package/dist/lib/browser/index.mjs.map +4 -4
  8. package/dist/lib/browser/meta.json +1 -1
  9. package/dist/lib/browser/testing/index.mjs +32 -0
  10. package/dist/lib/browser/testing/index.mjs.map +7 -0
  11. package/dist/lib/node-esm/{chunk-AUUC7II4.mjs → chunk-CC7ER6Q3.mjs} +251 -28
  12. package/dist/lib/node-esm/chunk-CC7ER6Q3.mjs.map +7 -0
  13. package/dist/lib/node-esm/chunk-HSLMI22Q.mjs +11 -0
  14. package/dist/lib/node-esm/extraction/index.mjs +119 -166
  15. package/dist/lib/node-esm/extraction/index.mjs.map +4 -4
  16. package/dist/lib/node-esm/index.mjs +239 -289
  17. package/dist/lib/node-esm/index.mjs.map +4 -4
  18. package/dist/lib/node-esm/meta.json +1 -1
  19. package/dist/lib/node-esm/testing/index.mjs +33 -0
  20. package/dist/lib/node-esm/testing/index.mjs.map +7 -0
  21. package/dist/types/src/conversation/context.d.ts +88 -62
  22. package/dist/types/src/conversation/context.d.ts.map +1 -1
  23. package/dist/types/src/conversation/context.test.d.ts +2 -0
  24. package/dist/types/src/conversation/context.test.d.ts.map +1 -0
  25. package/dist/types/src/conversation/conversation.d.ts +16 -16
  26. package/dist/types/src/conversation/conversation.d.ts.map +1 -1
  27. package/dist/types/src/conversation/conversation.test.d.ts +2 -0
  28. package/dist/types/src/conversation/conversation.test.d.ts.map +1 -0
  29. package/dist/types/src/errors.d.ts +22 -30
  30. package/dist/types/src/errors.d.ts.map +1 -1
  31. package/dist/types/src/execution-graph.d.ts +5 -2
  32. package/dist/types/src/execution-graph.d.ts.map +1 -1
  33. package/dist/types/src/extraction/extraction-llm-function/extraction-llm-function.d.ts.map +1 -1
  34. package/dist/types/src/extraction/extraction-ner-function/extraction-ner-function.d.ts +254 -252
  35. package/dist/types/src/extraction/extraction-ner-function/extraction-ner-function.d.ts.map +1 -1
  36. package/dist/types/src/extraction/extraction.d.ts +344 -309
  37. package/dist/types/src/extraction/extraction.d.ts.map +1 -1
  38. package/dist/types/src/extraction/quotes.d.ts +2 -2
  39. package/dist/types/src/extraction/quotes.d.ts.map +1 -1
  40. package/dist/types/src/functions/services.d.ts +4 -3
  41. package/dist/types/src/functions/services.d.ts.map +1 -1
  42. package/dist/types/src/functions.test.d.ts +2 -0
  43. package/dist/types/src/functions.test.d.ts.map +1 -0
  44. package/dist/types/src/session/GenericToolkit.d.ts +85 -0
  45. package/dist/types/src/session/GenericToolkit.d.ts.map +1 -0
  46. package/dist/types/src/session/artifact-diff.d.ts +1 -1
  47. package/dist/types/src/session/artifact-diff.d.ts.map +1 -1
  48. package/dist/types/src/session/format.d.ts +4 -178
  49. package/dist/types/src/session/format.d.ts.map +1 -1
  50. package/dist/types/src/session/index.d.ts +1 -0
  51. package/dist/types/src/session/index.d.ts.map +1 -1
  52. package/dist/types/src/session/observer.d.ts +6 -5
  53. package/dist/types/src/session/observer.d.ts.map +1 -1
  54. package/dist/types/src/session/session.d.ts +16 -11
  55. package/dist/types/src/session/session.d.ts.map +1 -1
  56. package/dist/types/src/session/toolkit.d.ts +5 -6
  57. package/dist/types/src/session/toolkit.d.ts.map +1 -1
  58. package/dist/types/src/session/version-pin.d.ts +3 -3
  59. package/dist/types/src/session/version-pin.d.ts.map +1 -1
  60. package/dist/types/src/testing/index.d.ts +2 -0
  61. package/dist/types/src/testing/index.d.ts.map +1 -0
  62. package/dist/types/src/testing/layer.d.ts +21 -0
  63. package/dist/types/src/testing/layer.d.ts.map +1 -0
  64. package/dist/types/src/types/artifact.d.ts +14 -2
  65. package/dist/types/src/types/artifact.d.ts.map +1 -1
  66. package/dist/types/tsconfig.tsbuildinfo +1 -1
  67. package/package.json +38 -27
  68. package/src/conversation/context.test.ts +46 -0
  69. package/src/conversation/context.ts +183 -66
  70. package/src/conversation/conversation.test.ts +65 -0
  71. package/src/conversation/conversation.ts +51 -54
  72. package/src/diff.test.ts +3 -3
  73. package/src/errors.ts +2 -2
  74. package/src/execution-graph.test.ts +45 -43
  75. package/src/execution-graph.ts +23 -14
  76. package/src/extraction/extraction-llm-function/extraction-llm-function.test.ts +2 -2
  77. package/src/extraction/extraction-llm-function/extraction-llm-function.ts +44 -54
  78. package/src/extraction/extraction-ner-function/extraction-ner-function.test.ts +14 -13
  79. package/src/extraction/extraction-ner-function/extraction-ner-function.ts +36 -44
  80. package/src/extraction/extraction-ner-function/named-entity-recognition.test.ts +10 -5
  81. package/src/extraction/extraction.ts +9 -8
  82. package/src/extraction/quotes.ts +4 -5
  83. package/src/functions/services.ts +41 -19
  84. package/src/functions.conversations.json +1 -0
  85. package/src/functions.test.ts +74 -0
  86. package/src/session/GenericToolkit.ts +131 -0
  87. package/src/session/artifact-diff.ts +1 -1
  88. package/src/session/format.test.ts +103 -39
  89. package/src/session/format.ts +17 -16
  90. package/src/session/index.ts +2 -0
  91. package/src/session/observer.ts +5 -3
  92. package/src/session/session.conversations.json +1 -1
  93. package/src/session/session.test.ts +7 -13
  94. package/src/session/session.ts +40 -19
  95. package/src/session/toolkit.ts +13 -22
  96. package/src/session/version-pin.ts +6 -6
  97. package/src/templates/{format.tpl → instructions/format.tpl} +1 -0
  98. package/src/templates/system.ts +2 -2
  99. package/src/testing/index.ts +5 -0
  100. package/src/testing/layer.ts +78 -0
  101. package/src/types/artifact.ts +33 -3
  102. package/dist/lib/browser/chunk-4VIJTKPM.mjs.map +0 -7
  103. package/dist/lib/browser/chunk-UB26N5UF.mjs +0 -89
  104. package/dist/lib/browser/chunk-UB26N5UF.mjs.map +0 -7
  105. package/dist/lib/browser/named-entity-recognition-QPYHML66.mjs +0 -13
  106. package/dist/lib/node-esm/chunk-AUUC7II4.mjs.map +0 -7
  107. package/dist/lib/node-esm/chunk-BCFXTNSK.mjs +0 -91
  108. package/dist/lib/node-esm/chunk-BCFXTNSK.mjs.map +0 -7
  109. package/dist/lib/node-esm/named-entity-recognition-2HDF46YX.mjs +0 -14
  110. package/dist/types/src/summarization/summarization.test.d.ts +0 -2
  111. package/dist/types/src/summarization/summarization.test.d.ts.map +0 -1
  112. package/src/summarization/summarization.test.ts +0 -202
  113. /package/dist/lib/browser/{named-entity-recognition-QPYHML66.mjs.map → chunk-J5LGTIGS.mjs.map} +0 -0
  114. /package/dist/lib/node-esm/{named-entity-recognition-2HDF46YX.mjs.map → chunk-HSLMI22Q.mjs.map} +0 -0
  115. /package/src/extraction/extraction-llm-function/{instructions.tpl → transcription-instructions.tpl} +0 -0
  116. /package/src/templates/{system.tpl → instructions/system.tpl} +0 -0
@@ -3,16 +3,15 @@
3
3
  //
4
4
 
5
5
  import type * as Toolkit from '@effect/ai/Toolkit';
6
- import * as Array from 'effect/Array';
6
+ import type { Registry } from '@effect-atom/atom-react';
7
7
  import * as Effect from 'effect/Effect';
8
- import * as Option from 'effect/Option';
9
8
 
10
9
  import { Resource } from '@dxos/context';
11
10
  import { Obj } from '@dxos/echo';
12
11
  import { type Queue } from '@dxos/echo-db';
13
- import { DatabaseService } from '@dxos/functions';
12
+ import { invariant } from '@dxos/invariant';
14
13
  import { log } from '@dxos/log';
15
- import { DataType } from '@dxos/schema';
14
+ import { Message } from '@dxos/types';
16
15
 
17
16
  import {
18
17
  AiSession,
@@ -24,105 +23,103 @@ import {
24
23
 
25
24
  import { AiContextBinder, AiContextService, type ContextBinding } from './context';
26
25
 
27
- export interface AiConversationRunParams {
26
+ export interface AiConversationRunProps {
28
27
  prompt: string;
29
28
  system?: string;
30
29
  observer?: GenerationObserver;
31
30
  }
32
31
 
32
+ export type AiConversationOptions = {
33
+ queue: Queue<Message.Message | ContextBinding>;
34
+ toolkit?: Toolkit.Any;
35
+ registry?: Registry.Registry;
36
+ };
37
+
33
38
  /**
34
39
  * Durable conversation state (initiated by users and agents) backed by a Queue.
35
40
  * Executes tools based on AI responses and supports cancellation of in-progress requests.
36
41
  */
37
42
  export class AiConversation extends Resource {
38
43
  /**
39
- * Message and binding queue.
40
- */
41
- private readonly _queue: Queue<DataType.Message | ContextBinding>;
42
-
43
- /**
44
- * Blueprints bound to the conversation.
44
+ * Blueprints and objects bound to the conversation.
45
45
  */
46
- private readonly _context: AiContextBinder;
46
+ private readonly _binder: AiContextBinder;
47
+ private readonly _queue: Queue<Message.Message | ContextBinding>;
48
+ private readonly _toolkit?: Toolkit.Any;
47
49
 
48
- /**
49
- * Toolkit from the current session request.
50
- */
51
- private _toolkit: Toolkit.WithHandler<any> | undefined;
52
-
53
- public constructor(queue: Queue<DataType.Message | ContextBinding>) {
50
+ public constructor(options: AiConversationOptions) {
54
51
  super();
55
- this._queue = queue;
56
- this._context = new AiContextBinder(this._queue);
52
+ this._queue = options.queue;
53
+ this._toolkit = options.toolkit;
54
+ invariant(this._queue);
55
+ this._binder = new AiContextBinder({ queue: this._queue, registry: options.registry });
57
56
  }
58
57
 
59
58
  protected override async _open(): Promise<void> {
60
- // TODO(wittjosiah): Pass in parent context?
61
- await this._context.open();
59
+ await this._binder.open(this._ctx);
62
60
  }
63
61
 
64
- protected override async _close(): Promise<void> {
65
- await this._context.close();
62
+ public get queue() {
63
+ return this._queue;
66
64
  }
67
65
 
68
66
  public get context() {
69
- return this._context;
67
+ return this._binder;
70
68
  }
71
69
 
72
70
  public get toolkit() {
73
71
  return this._toolkit;
74
72
  }
75
73
 
76
- public async getHistory(): Promise<DataType.Message[]> {
77
- const queueItems = await this._queue.queryObjects();
78
- return queueItems.filter(Obj.instanceOf(DataType.Message));
74
+ public async getHistory(): Promise<Message.Message[]> {
75
+ const queueItems = await this._queue.queryObjects(); // TODO(burdon): Update.
76
+ return queueItems.filter(Obj.instanceOf(Message.Message));
79
77
  }
80
78
 
81
79
  /**
82
80
  * Creates a new cancelable request effect.
83
81
  */
84
- createRequest(
85
- params: AiConversationRunParams,
86
- ): Effect.Effect<DataType.Message[], AiSessionRunError, AiSessionRunRequirements> {
87
- return Effect.gen(this, function* () {
88
- const session = new AiSession();
89
- const history = yield* Effect.promise(() => this.getHistory());
90
-
91
- // Get context objects.
92
- const context = yield* Effect.promise(() => this.context.query());
93
- const blueprints = yield* Effect.forEach(context.blueprints.values(), DatabaseService.loadOption).pipe(
94
- Effect.map(Array.filter(Option.isSome)),
95
- Effect.map(Array.map((option) => option.value)),
96
- );
97
- const objects = yield* Effect.forEach(context.objects.values(), DatabaseService.loadOption).pipe(
98
- Effect.map(Array.filter(Option.isSome)),
99
- Effect.map(Array.map((option) => option.value)),
100
- );
82
+ public createRequest(
83
+ params: AiConversationRunProps,
84
+ ): Effect.Effect<Message.Message[], AiSessionRunError, AiSessionRunRequirements> {
85
+ const self = this;
86
+ return Effect.gen(function* () {
87
+ const history = yield* Effect.promise(() => self.getHistory());
101
88
 
102
89
  // Create toolkit.
103
- const toolkit = yield* createToolkit({ blueprints });
104
- this._toolkit = toolkit;
90
+ const blueprints = self.context.getBlueprints();
91
+ const toolkit = yield* createToolkit({
92
+ toolkit: self._toolkit,
93
+ blueprints,
94
+ });
95
+
96
+ // Context objects.
97
+ const objects = self.context.getObjects();
105
98
 
106
- const start = Date.now();
107
99
  log('run', {
108
100
  history: history.length,
109
101
  blueprints: blueprints.length,
102
+ tools: Object.keys(toolkit.tools).length,
110
103
  objects: objects.length,
111
- tools: this._toolkit?.tools.length ?? 0,
112
104
  });
113
105
 
114
106
  // Process request.
115
- const messages = yield* session.run({ history, blueprints, objects, toolkit, ...params }).pipe(
107
+ const session = new AiSession();
108
+ const messages = yield* session.run({ history, blueprints, toolkit, objects, ...params }).pipe(
116
109
  Effect.provideService(AiContextService, {
117
- binder: this.context,
110
+ binder: self.context,
118
111
  }),
119
112
  );
120
113
 
121
- log('result', { messages: messages.length, duration: Date.now() - start });
114
+ log('result', {
115
+ messages: messages.length,
116
+ duration: session.duration,
117
+ toolCalls: session.toolCalls,
118
+ });
122
119
 
123
120
  // Append to queue.
124
- yield* Effect.promise(() => this._queue.append(messages));
121
+ yield* Effect.promise(() => self._queue.append(messages));
125
122
  return messages;
126
- }).pipe(Effect.withSpan('AiConversation.request'));
123
+ });
127
124
  }
128
125
  }
package/src/diff.test.ts CHANGED
@@ -6,7 +6,7 @@ import { describe, expect, it } from 'vitest';
6
6
 
7
7
  import { createDocAccessor } from '@dxos/echo-db';
8
8
  import { EchoTestBuilder } from '@dxos/echo-db/testing';
9
- import { DataType } from '@dxos/schema';
9
+ import { Text } from '@dxos/schema';
10
10
  import { trim } from '@dxos/util';
11
11
 
12
12
  import { applyDiffs } from './diff';
@@ -15,7 +15,7 @@ describe('diff', () => {
15
15
  it('should apply diffs', async () => {
16
16
  const builder = new EchoTestBuilder();
17
17
  const { db, graph } = await builder.createDatabase();
18
- graph.schemaRegistry.addSchema([DataType.Text]);
18
+ await graph.schemaRegistry.register([Text.Text]);
19
19
 
20
20
  const document = trim`
21
21
  # Hello World
@@ -24,7 +24,7 @@ describe('diff', () => {
24
24
  But not this one.
25
25
  `;
26
26
 
27
- const text = db.add(DataType.makeText(document));
27
+ const text = db.add(Text.make(document));
28
28
  const accessor = createDocAccessor(text, ['content']);
29
29
  const result = applyDiffs(accessor, [
30
30
  `- There'z a typo in this sentence.`,
package/src/errors.ts CHANGED
@@ -7,9 +7,9 @@ import { BaseError } from '@dxos/errors';
7
7
  /**
8
8
  * Generic error from AI model.
9
9
  */
10
- export class AiModelError extends BaseError.extend('AI_MODEL_ERROR', 'AI model error') {}
10
+ export class AiModelError extends BaseError.extend('AiModelError', 'AI model error') {}
11
11
 
12
12
  /**
13
13
  * Generic error for AI agent execution.
14
14
  */
15
- export class AiAssistantError extends BaseError.extend('AI_ASSISTANT_ERROR', 'AI assistant error') {}
15
+ export class AiAssistantError extends BaseError.extend('AiAssistantError', 'AI assistant error') {}
@@ -6,15 +6,17 @@ import { describe, expect, it } from '@effect/vitest';
6
6
 
7
7
  import { AgentStatus } from '@dxos/ai';
8
8
  import { Obj } from '@dxos/echo';
9
- import { ObjectId } from '@dxos/echo/internal';
9
+ import { ObjectId } from '@dxos/keys';
10
10
  import { log } from '@dxos/log';
11
- import { DataType } from '@dxos/schema';
11
+ import { type ContentBlock, Message } from '@dxos/types';
12
12
 
13
13
  import { ExecutionGraph } from './execution-graph';
14
14
 
15
- // Helper function to create valid object IDs for testing
15
+ // Helper function to create valid object IDs for testing.
16
16
  const createTestId = () => ObjectId.random();
17
17
 
18
+ const SKIP_BLOCKS: ContentBlock.Any['_tag'][] = [];
19
+
18
20
  describe('ExecutionGraph', () => {
19
21
  describe('basic functionality', () => {
20
22
  it('should create an empty graph initially', () => {
@@ -26,9 +28,9 @@ describe('ExecutionGraph', () => {
26
28
  });
27
29
 
28
30
  it('should add a simple user message', () => {
29
- const graph = new ExecutionGraph();
31
+ const graph = new ExecutionGraph(SKIP_BLOCKS);
30
32
  const messageId = createTestId();
31
- const message = Obj.make(DataType.Message, {
33
+ const message = Obj.make(Message.Message, {
32
34
  id: messageId,
33
35
  created: '2025-01-01T00:00:00Z',
34
36
  sender: { role: 'user' },
@@ -56,12 +58,12 @@ describe('ExecutionGraph', () => {
56
58
  });
57
59
 
58
60
  it('should handle basic status & message processing', () => {
59
- const graph = new ExecutionGraph();
61
+ const graph = new ExecutionGraph(SKIP_BLOCKS);
60
62
  const status = Obj.make(AgentStatus, {
61
63
  created: '2025-01-01T00:00:00Z',
62
64
  message: 'Running Research',
63
65
  });
64
- const message = Obj.make(DataType.Message, {
66
+ const message = Obj.make(Message.Message, {
65
67
  created: '2025-09-29T14:29:37.860Z',
66
68
  sender: {
67
69
  role: 'user',
@@ -90,9 +92,9 @@ describe('ExecutionGraph', () => {
90
92
  });
91
93
 
92
94
  it('should add an assistant message with text', () => {
93
- const graph = new ExecutionGraph();
95
+ const graph = new ExecutionGraph(SKIP_BLOCKS);
94
96
  const messageId = createTestId();
95
- const message = Obj.make(DataType.Message, {
97
+ const message = Obj.make(Message.Message, {
96
98
  id: messageId,
97
99
  created: '2025-01-01T00:00:00Z',
98
100
  sender: { role: 'assistant' },
@@ -120,9 +122,9 @@ describe('ExecutionGraph', () => {
120
122
 
121
123
  describe('sequential chaining within messages', () => {
122
124
  it('should chain blocks within a message', () => {
123
- const graph = new ExecutionGraph();
125
+ const graph = new ExecutionGraph(SKIP_BLOCKS);
124
126
  const messageId = createTestId();
125
- const message = Obj.make(DataType.Message, {
127
+ const message = Obj.make(Message.Message, {
126
128
  id: messageId,
127
129
  created: '2025-01-01T00:00:00Z',
128
130
  sender: { role: 'assistant' },
@@ -168,11 +170,11 @@ describe('ExecutionGraph', () => {
168
170
  });
169
171
 
170
172
  it('should chain across multiple messages', () => {
171
- const graph = new ExecutionGraph();
173
+ const graph = new ExecutionGraph(SKIP_BLOCKS);
172
174
 
173
175
  // First message
174
176
  const message1Id = createTestId();
175
- const message1 = Obj.make(DataType.Message, {
177
+ const message1 = Obj.make(Message.Message, {
176
178
  id: message1Id,
177
179
  created: '2025-01-01T00:00:00Z',
178
180
  sender: { role: 'user' },
@@ -182,7 +184,7 @@ describe('ExecutionGraph', () => {
182
184
 
183
185
  // Second message
184
186
  const message2Id = createTestId();
185
- const message2 = Obj.make(DataType.Message, {
187
+ const message2 = Obj.make(Message.Message, {
186
188
  id: message2Id,
187
189
  created: '2025-01-01T00:01:00Z',
188
190
  sender: { role: 'assistant' },
@@ -211,7 +213,7 @@ describe('ExecutionGraph', () => {
211
213
 
212
214
  describe('tool calls and results', () => {
213
215
  it('should handle tool calls and results with proper parent relationships', () => {
214
- const graph = new ExecutionGraph();
216
+ const graph = new ExecutionGraph(SKIP_BLOCKS);
215
217
 
216
218
  const message1Id = createTestId();
217
219
  const message2Id = createTestId();
@@ -219,7 +221,7 @@ describe('ExecutionGraph', () => {
219
221
  const toolCallId = 'tool1';
220
222
 
221
223
  // Assistant message with tool call
222
- const toolCallMessage = Obj.make(DataType.Message, {
224
+ const toolCallMessage = Obj.make(Message.Message, {
223
225
  id: message1Id,
224
226
  created: '2025-01-01T00:00:00Z',
225
227
  sender: { role: 'assistant' },
@@ -240,7 +242,7 @@ describe('ExecutionGraph', () => {
240
242
  });
241
243
 
242
244
  // User message with tool result
243
- const toolResultMessage = Obj.make(DataType.Message, {
245
+ const toolResultMessage = Obj.make(Message.Message, {
244
246
  id: message2Id,
245
247
  created: '2025-01-01T00:01:00Z',
246
248
  sender: { role: 'user' },
@@ -296,7 +298,7 @@ describe('ExecutionGraph', () => {
296
298
  });
297
299
 
298
300
  it('should handle tool errors with proper parent relationships', () => {
299
- const graph = new ExecutionGraph();
301
+ const graph = new ExecutionGraph(SKIP_BLOCKS);
300
302
 
301
303
  const message1Id = createTestId();
302
304
  const message2Id = createTestId();
@@ -304,7 +306,7 @@ describe('ExecutionGraph', () => {
304
306
  const toolCallId = 'tool1';
305
307
 
306
308
  // Assistant message with tool call
307
- const toolCallMessage = Obj.make(DataType.Message, {
309
+ const toolCallMessage = Obj.make(Message.Message, {
308
310
  id: message1Id,
309
311
  created: '2025-01-01T00:00:00Z',
310
312
  sender: { role: 'assistant' },
@@ -321,7 +323,7 @@ describe('ExecutionGraph', () => {
321
323
  });
322
324
 
323
325
  // User message with tool error
324
- const toolErrorMessage = Obj.make(DataType.Message, {
326
+ const toolErrorMessage = Obj.make(Message.Message, {
325
327
  id: message2Id,
326
328
  created: '2025-01-01T00:01:00Z',
327
329
  sender: { role: 'user' },
@@ -373,7 +375,7 @@ describe('ExecutionGraph', () => {
373
375
 
374
376
  describe('different processing orders', () => {
375
377
  it('should handle AgentStatus processed after tool result', () => {
376
- const graph = new ExecutionGraph();
378
+ const graph = new ExecutionGraph(SKIP_BLOCKS);
377
379
 
378
380
  const message1Id = createTestId();
379
381
  const message2Id = createTestId();
@@ -381,7 +383,7 @@ describe('ExecutionGraph', () => {
381
383
  const toolCallId = 'tool1';
382
384
 
383
385
  // Tool call message
384
- const toolCallMessage = Obj.make(DataType.Message, {
386
+ const toolCallMessage = Obj.make(Message.Message, {
385
387
  id: message1Id,
386
388
  created: '2025-01-01T00:00:00Z',
387
389
  sender: { role: 'assistant' },
@@ -398,7 +400,7 @@ describe('ExecutionGraph', () => {
398
400
  });
399
401
 
400
402
  // Tool result message
401
- const toolResultMessage = Obj.make(DataType.Message, {
403
+ const toolResultMessage = Obj.make(Message.Message, {
402
404
  id: message2Id,
403
405
  created: '2025-01-01T00:01:00Z',
404
406
  sender: { role: 'user' },
@@ -432,7 +434,7 @@ describe('ExecutionGraph', () => {
432
434
  });
433
435
 
434
436
  it('should handle AgentStatus processed before tool result', () => {
435
- const graph = new ExecutionGraph();
437
+ const graph = new ExecutionGraph(SKIP_BLOCKS);
436
438
 
437
439
  const message1Id = createTestId();
438
440
  const message2Id = createTestId();
@@ -440,7 +442,7 @@ describe('ExecutionGraph', () => {
440
442
  const toolCallId = 'tool1';
441
443
 
442
444
  // Tool call message
443
- const toolCallMessage = Obj.make(DataType.Message, {
445
+ const toolCallMessage = Obj.make(Message.Message, {
444
446
  id: message1Id,
445
447
  created: '2025-01-01T00:00:00Z',
446
448
  sender: { role: 'assistant' },
@@ -466,7 +468,7 @@ describe('ExecutionGraph', () => {
466
468
  });
467
469
 
468
470
  // Tool result message
469
- const toolResultMessage = Obj.make(DataType.Message, {
471
+ const toolResultMessage = Obj.make(Message.Message, {
470
472
  id: message2Id,
471
473
  created: '2025-01-01T00:01:00Z',
472
474
  sender: { role: 'user' },
@@ -493,7 +495,7 @@ describe('ExecutionGraph', () => {
493
495
 
494
496
  describe('complex scenarios', () => {
495
497
  it('should handle multiple tool calls in sequence', () => {
496
- const graph = new ExecutionGraph();
498
+ const graph = new ExecutionGraph(SKIP_BLOCKS);
497
499
 
498
500
  const msg1Id = createTestId();
499
501
  const msg2Id = createTestId();
@@ -505,7 +507,7 @@ describe('ExecutionGraph', () => {
505
507
 
506
508
  const events = [
507
509
  // User message
508
- Obj.make(DataType.Message, {
510
+ Obj.make(Message.Message, {
509
511
  id: msg1Id,
510
512
  created: '2025-01-01T00:00:00Z',
511
513
  sender: { role: 'user' },
@@ -514,7 +516,7 @@ describe('ExecutionGraph', () => {
514
516
  }),
515
517
 
516
518
  // Assistant with first tool call
517
- Obj.make(DataType.Message, {
519
+ Obj.make(Message.Message, {
518
520
  id: msg2Id,
519
521
  created: '2025-01-01T00:01:00Z',
520
522
  sender: { role: 'assistant' },
@@ -526,7 +528,7 @@ describe('ExecutionGraph', () => {
526
528
  }),
527
529
 
528
530
  // First tool result
529
- Obj.make(DataType.Message, {
531
+ Obj.make(Message.Message, {
530
532
  id: msg3Id,
531
533
  created: '2025-01-01T00:02:00Z',
532
534
  sender: { role: 'user' },
@@ -543,7 +545,7 @@ describe('ExecutionGraph', () => {
543
545
  }),
544
546
 
545
547
  // Assistant with second tool call
546
- Obj.make(DataType.Message, {
548
+ Obj.make(Message.Message, {
547
549
  id: msg4Id,
548
550
  created: '2025-01-01T00:03:00Z',
549
551
  sender: { role: 'assistant' },
@@ -555,7 +557,7 @@ describe('ExecutionGraph', () => {
555
557
  }),
556
558
 
557
559
  // Second tool result
558
- Obj.make(DataType.Message, {
560
+ Obj.make(Message.Message, {
559
561
  id: msg5Id,
560
562
  created: '2025-01-01T00:04:00Z',
561
563
  sender: { role: 'user' },
@@ -605,10 +607,10 @@ describe('ExecutionGraph', () => {
605
607
  });
606
608
 
607
609
  it('should handle mixed block types in a message', () => {
608
- const graph = new ExecutionGraph();
610
+ const graph = new ExecutionGraph(SKIP_BLOCKS);
609
611
 
610
612
  const messageId = createTestId();
611
- const message = Obj.make(DataType.Message, {
613
+ const message = Obj.make(Message.Message, {
612
614
  id: messageId,
613
615
  created: '2025-01-01T00:00:00Z',
614
616
  sender: { role: 'assistant' },
@@ -642,10 +644,10 @@ describe('ExecutionGraph', () => {
642
644
 
643
645
  describe('edge cases', () => {
644
646
  it('should handle empty text blocks', () => {
645
- const graph = new ExecutionGraph();
647
+ const graph = new ExecutionGraph(SKIP_BLOCKS);
646
648
 
647
649
  const messageId = createTestId();
648
- const message = Obj.make(DataType.Message, {
650
+ const message = Obj.make(Message.Message, {
649
651
  id: messageId,
650
652
  created: '2025-01-01T00:00:00Z',
651
653
  sender: { role: 'assistant' },
@@ -666,10 +668,10 @@ describe('ExecutionGraph', () => {
666
668
  });
667
669
 
668
670
  it('should handle messages with no blocks', () => {
669
- const graph = new ExecutionGraph();
671
+ const graph = new ExecutionGraph(SKIP_BLOCKS);
670
672
 
671
673
  const messageId = createTestId();
672
- const message = Obj.make(DataType.Message, {
674
+ const message = Obj.make(Message.Message, {
673
675
  id: messageId,
674
676
  created: '2025-01-01T00:00:00Z',
675
677
  sender: { role: 'assistant' },
@@ -684,7 +686,7 @@ describe('ExecutionGraph', () => {
684
686
  });
685
687
 
686
688
  it('should handle getGraph with lastRequest filter', () => {
687
- const graph = new ExecutionGraph();
689
+ const graph = new ExecutionGraph(SKIP_BLOCKS);
688
690
 
689
691
  const msg1Id = createTestId();
690
692
  const msg2Id = createTestId();
@@ -692,28 +694,28 @@ describe('ExecutionGraph', () => {
692
694
  const msg4Id = createTestId();
693
695
 
694
696
  const events = [
695
- Obj.make(DataType.Message, {
697
+ Obj.make(Message.Message, {
696
698
  id: msg1Id,
697
699
  created: '2025-01-01T00:00:00Z',
698
700
  sender: { role: 'user' },
699
701
  blocks: [{ _tag: 'text', text: 'First request' }],
700
702
  properties: {},
701
703
  }),
702
- Obj.make(DataType.Message, {
704
+ Obj.make(Message.Message, {
703
705
  id: msg2Id,
704
706
  created: '2025-01-01T00:01:00Z',
705
707
  sender: { role: 'assistant' },
706
708
  blocks: [{ _tag: 'text', text: 'Response 1' }],
707
709
  properties: {},
708
710
  }),
709
- Obj.make(DataType.Message, {
711
+ Obj.make(Message.Message, {
710
712
  id: msg3Id,
711
713
  created: '2025-01-01T00:02:00Z',
712
714
  sender: { role: 'user' },
713
715
  blocks: [{ _tag: 'text', text: 'Second request' }],
714
716
  properties: {},
715
717
  }),
716
- Obj.make(DataType.Message, {
718
+ Obj.make(Message.Message, {
717
719
  id: msg4Id,
718
720
  created: '2025-01-01T00:03:00Z',
719
721
  sender: { role: 'assistant' },
@@ -3,13 +3,15 @@
3
3
  //
4
4
 
5
5
  import { AgentStatus } from '@dxos/ai';
6
- import { Obj, type Ref } from '@dxos/echo';
6
+ import { type Entity, Obj, type Ref } from '@dxos/echo';
7
7
  import { MESSAGE_PROPERTY_TOOL_CALL_ID } from '@dxos/functions';
8
8
  import { type ObjectId } from '@dxos/keys';
9
9
  import { LogLevel } from '@dxos/log';
10
- import { ContentBlock, DataType } from '@dxos/schema';
10
+ import { ContentBlock, Message } from '@dxos/types';
11
11
  import { isNonNullable } from '@dxos/util';
12
12
 
13
+ const SKIP_BLOCKS: ContentBlock.Any['_tag'][] = ['text'];
14
+
13
15
  /**
14
16
  * Mercurial-style Commit.
15
17
  */
@@ -58,13 +60,15 @@ export class ExecutionGraph {
58
60
  private _lastCommitByBranch = new Map<string, string>(); // branch -> last commitId
59
61
  private _pendingToolResults = new Map<string, string>(); // toolCallId -> toolResultCommitId
60
62
 
63
+ constructor(private readonly _skipBlocks: ContentBlock.Any['_tag'][] = SKIP_BLOCKS) {}
64
+
61
65
  /**
62
66
  * Adds events to the graph.
63
67
  */
64
- addEvents(events: Obj.Any[]) {
68
+ addEvents(events: Entity.Unknown[]) {
65
69
  const sortedEvents = this.sortObjectsByCreated(events);
66
70
  for (const event of sortedEvents) {
67
- if (Obj.instanceOf(DataType.Message, event)) {
71
+ if (Obj.instanceOf(Message.Message, event)) {
68
72
  this._processMessage(event);
69
73
  } else if (Obj.instanceOf(AgentStatus, event)) {
70
74
  this._processAgentStatus(event);
@@ -75,12 +79,13 @@ export class ExecutionGraph {
75
79
  /**
76
80
  * Processes a message event and creates commits for its blocks.
77
81
  */
78
- private _processMessage(message: DataType.Message) {
82
+ private _processMessage(message: Message.Message) {
79
83
  const messageCommits = messageToCommits(
80
84
  message,
81
85
  this._lastBlockId,
82
86
  this._toolCallCommitIds,
83
87
  this._lastCommitByBranch,
88
+ this._skipBlocks,
84
89
  );
85
90
  this._commits.push(...messageCommits);
86
91
 
@@ -278,15 +283,16 @@ export class ExecutionGraph {
278
283
  }
279
284
  }
280
285
 
281
- // TODO(burdon): Pass in AiToolProvider.
282
286
  /**
283
287
  * Creates commits for all blocks in a message.
284
288
  */
289
+ // TODO(burdon): Pass in AiToolProvider.
285
290
  const messageToCommits = (
286
- message: DataType.Message,
291
+ message: Message.Message,
287
292
  lastBlockId?: string,
288
293
  toolCallIds?: Map<string, string>,
289
294
  lastCommitByBranch?: Map<string, string>,
295
+ skipBlocks?: ContentBlock.Any['_tag'][],
290
296
  ): Commit[] => {
291
297
  let previousBlockId: string | undefined = lastBlockId;
292
298
 
@@ -294,6 +300,9 @@ const messageToCommits = (
294
300
  .map((block, idx) => {
295
301
  const branch = getMessageBranch(message);
296
302
  const parents = getBlockParents(block, previousBlockId, message, toolCallIds, lastCommitByBranch);
303
+ if (skipBlocks?.includes(block._tag)) {
304
+ return null;
305
+ }
297
306
 
298
307
  const commit = createBlockCommit(block, message, branch, parents, idx);
299
308
  if (commit) {
@@ -311,14 +320,14 @@ const messageToCommits = (
311
320
  const getBlockParents = (
312
321
  block: ContentBlock.Any,
313
322
  previousBlockId: string | undefined,
314
- message: DataType.Message,
323
+ message: Message.Message,
315
324
  toolCallIds?: Map<string, string>,
316
325
  lastCommitByBranch?: Map<string, string>,
317
326
  ): string[] => {
318
327
  const parents: string[] = [];
319
328
 
320
329
  if (block._tag === 'toolResult') {
321
- // Tool results have two parents: previous block and last block from tool call branch
330
+ // Tool results have two parents: previous block and last block from tool call branch.
322
331
  if (previousBlockId) {
323
332
  parents.push(previousBlockId);
324
333
  }
@@ -355,7 +364,7 @@ const getBlockParents = (
355
364
  */
356
365
  const createBlockCommit = (
357
366
  block: ContentBlock.Any,
358
- message: DataType.Message,
367
+ message: Message.Message,
359
368
  branch: string,
360
369
  parents: string[],
361
370
  idx: number,
@@ -472,14 +481,14 @@ const getBranchName = (options: { parentMessage?: ObjectId; toolCallId?: string
472
481
  }
473
482
  };
474
483
 
475
- const getMessageBranch = (message: DataType.Message) => {
484
+ const getMessageBranch = (message: Message.Message) => {
476
485
  return getBranchName({
477
486
  parentMessage: message.parentMessage,
478
487
  toolCallId: message.properties?.[MESSAGE_PROPERTY_TOOL_CALL_ID],
479
488
  });
480
489
  };
481
490
 
482
- const getParentId = (message: DataType.Message) => {
491
+ const getParentId = (message: Message.Message) => {
483
492
  if (message.parentMessage && message.properties?.[MESSAGE_PROPERTY_TOOL_CALL_ID]) {
484
493
  return getToolCallId(message.parentMessage, message.properties[MESSAGE_PROPERTY_TOOL_CALL_ID]);
485
494
  } else {
@@ -487,7 +496,7 @@ const getParentId = (message: DataType.Message) => {
487
496
  }
488
497
  };
489
498
 
490
- const stringifyRef = (ref: Ref.Any) => {
499
+ const stringifyRef = (ref: Ref.Unknown) => {
491
500
  if (ref.target) {
492
501
  return stringifyObject(ref.target);
493
502
  }
@@ -495,6 +504,6 @@ const stringifyRef = (ref: Ref.Any) => {
495
504
  return ref.dxn.asEchoDXN()?.echoId ?? ref.dxn.asQueueDXN()?.objectId ?? '';
496
505
  };
497
506
 
498
- const stringifyObject = (obj: Obj.Any) => {
507
+ const stringifyObject = (obj: Obj.Unknown) => {
499
508
  return Obj.getLabel(obj) ?? Obj.getTypename(obj) ?? obj.id;
500
509
  };