@dxos/assistant 0.8.4-main.ae835ea → 0.8.4-main.bc2380dfbc
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/LICENSE +102 -5
- package/README.md +2 -1
- package/dist/lib/neutral/chunk-J5LGTIGS.mjs +10 -0
- package/dist/lib/neutral/extraction/index.mjs +204 -0
- package/dist/lib/neutral/extraction/index.mjs.map +7 -0
- package/dist/lib/neutral/index.mjs +1755 -0
- package/dist/lib/neutral/index.mjs.map +7 -0
- package/dist/lib/neutral/meta.json +1 -0
- package/dist/types/src/extraction/extraction-ner-function/index.d.ts +0 -1
- package/dist/types/src/extraction/extraction-ner-function/index.d.ts.map +1 -1
- package/dist/types/src/extraction/extraction-ner-function/named-entity-recognition.d.ts.map +1 -1
- package/dist/types/src/extraction/extraction.d.ts +1065 -312
- package/dist/types/src/extraction/extraction.d.ts.map +1 -1
- package/dist/types/src/extraction/index.d.ts +0 -1
- package/dist/types/src/extraction/index.d.ts.map +1 -1
- package/dist/types/src/extraction/quotes.d.ts +2 -2
- package/dist/types/src/extraction/quotes.d.ts.map +1 -1
- package/dist/types/src/functions/services.d.ts +13 -15
- package/dist/types/src/functions/services.d.ts.map +1 -1
- package/dist/types/src/index.d.ts +2 -5
- package/dist/types/src/index.d.ts.map +1 -1
- package/dist/types/src/request/AiRequest.d.ts +104 -0
- package/dist/types/src/request/AiRequest.d.ts.map +1 -0
- package/dist/types/src/{session → request}/artifact-diff.d.ts +1 -1
- package/dist/types/src/request/artifact-diff.d.ts.map +1 -0
- package/dist/types/src/request/format.d.ts +15 -0
- package/dist/types/src/request/format.d.ts.map +1 -0
- package/dist/types/src/request/index.d.ts +4 -0
- package/dist/types/src/request/index.d.ts.map +1 -0
- package/dist/types/src/{session → request}/observer.d.ts +6 -5
- package/dist/types/src/request/observer.d.ts.map +1 -0
- package/dist/types/src/{session → request}/version-pin.d.ts +3 -3
- package/dist/types/src/request/version-pin.d.ts.map +1 -0
- package/dist/types/src/session/AiContext.d.ts +154 -0
- package/dist/types/src/session/AiContext.d.ts.map +1 -0
- package/dist/types/src/session/AiContext.test.d.ts +2 -0
- package/dist/types/src/session/AiContext.test.d.ts.map +1 -0
- package/dist/types/src/session/AiSession.d.ts +73 -0
- package/dist/types/src/session/AiSession.d.ts.map +1 -0
- package/dist/types/src/session/index.d.ts +2 -4
- package/dist/types/src/session/index.d.ts.map +1 -1
- package/dist/types/src/session/toolkit.d.ts +10 -9
- package/dist/types/src/session/toolkit.d.ts.map +1 -1
- package/dist/types/src/templates/system.d.ts +1 -2
- package/dist/types/src/templates/system.d.ts.map +1 -1
- package/dist/types/src/util/artifact.d.ts +27 -0
- package/dist/types/src/util/artifact.d.ts.map +1 -0
- package/dist/types/src/{diff.d.ts → util/diff.d.ts} +3 -1
- package/dist/types/src/util/diff.d.ts.map +1 -0
- package/dist/types/src/{diff.test.d.ts.map → util/diff.test.d.ts.map} +1 -1
- package/dist/types/src/util/error-handling.d.ts.map +1 -0
- package/dist/types/src/{errors.d.ts → util/errors.d.ts} +32 -40
- package/dist/types/src/util/errors.d.ts.map +1 -0
- package/dist/types/src/{execution-graph.d.ts → util/execution-graph.d.ts} +5 -2
- package/dist/types/src/util/execution-graph.d.ts.map +1 -0
- package/dist/types/src/util/execution-graph.test.d.ts.map +1 -0
- package/dist/types/src/util/index.d.ts +7 -0
- package/dist/types/src/util/index.d.ts.map +1 -0
- package/dist/types/src/util/tracing.d.ts +233 -0
- package/dist/types/src/util/tracing.d.ts.map +1 -0
- package/dist/types/tsconfig.tsbuildinfo +1 -1
- package/package.json +36 -42
- package/src/extraction/extraction-ner-function/index.ts +0 -1
- package/src/extraction/extraction-ner-function/named-entity-recognition.test.ts +10 -5
- package/src/extraction/extraction.ts +43 -14
- package/src/extraction/index.ts +0 -1
- package/src/extraction/quotes.ts +4 -5
- package/src/functions/services.ts +119 -63
- package/src/index.ts +2 -5
- package/src/request/AiRequest.ts +348 -0
- package/src/{session → request}/artifact-diff.ts +1 -1
- package/src/{session → request}/format.ts +29 -24
- package/src/request/index.ts +8 -0
- package/src/{session → request}/observer.ts +6 -3
- package/src/{session → request}/version-pin.ts +6 -6
- package/src/session/AiContext.test.ts +53 -0
- package/src/session/AiContext.ts +403 -0
- package/src/session/AiSession.ts +324 -0
- package/src/session/index.ts +3 -4
- package/src/session/toolkit.ts +27 -28
- package/src/templates/{format.tpl → instructions/format.tpl} +1 -4
- package/src/templates/{system.tpl → instructions/system.tpl} +50 -2
- package/src/templates/system.ts +9 -8
- package/src/{types → util}/artifact.ts +42 -6
- package/src/util/diff.test.ts +74 -0
- package/src/{diff.ts → util/diff.ts} +13 -4
- package/src/{session → util}/error-handling.ts +3 -2
- package/src/util/errors.ts +15 -0
- package/src/{execution-graph.test.ts → util/execution-graph.test.ts} +47 -45
- package/src/{execution-graph.ts → util/execution-graph.ts} +41 -22
- package/src/util/index.ts +10 -0
- package/src/util/tracing.ts +57 -0
- package/dist/lib/browser/chunk-4VIJTKPM.mjs +0 -354
- package/dist/lib/browser/chunk-4VIJTKPM.mjs.map +0 -7
- package/dist/lib/browser/chunk-UB26N5UF.mjs +0 -89
- package/dist/lib/browser/chunk-UB26N5UF.mjs.map +0 -7
- package/dist/lib/browser/extraction/index.mjs +0 -272
- package/dist/lib/browser/extraction/index.mjs.map +0 -7
- package/dist/lib/browser/index.mjs +0 -900
- package/dist/lib/browser/index.mjs.map +0 -7
- package/dist/lib/browser/meta.json +0 -1
- package/dist/lib/browser/named-entity-recognition-QPYHML66.mjs +0 -13
- package/dist/lib/node-esm/chunk-AUUC7II4.mjs +0 -356
- package/dist/lib/node-esm/chunk-AUUC7II4.mjs.map +0 -7
- package/dist/lib/node-esm/chunk-BCFXTNSK.mjs +0 -91
- package/dist/lib/node-esm/chunk-BCFXTNSK.mjs.map +0 -7
- package/dist/lib/node-esm/extraction/index.mjs +0 -273
- package/dist/lib/node-esm/extraction/index.mjs.map +0 -7
- package/dist/lib/node-esm/index.mjs +0 -901
- package/dist/lib/node-esm/index.mjs.map +0 -7
- package/dist/lib/node-esm/meta.json +0 -1
- package/dist/lib/node-esm/named-entity-recognition-2HDF46YX.mjs +0 -14
- package/dist/lib/node-esm/named-entity-recognition-2HDF46YX.mjs.map +0 -7
- package/dist/types/src/conversation/context.d.ts +0 -103
- package/dist/types/src/conversation/context.d.ts.map +0 -1
- package/dist/types/src/conversation/conversation.d.ts +0 -41
- package/dist/types/src/conversation/conversation.d.ts.map +0 -1
- package/dist/types/src/conversation/index.d.ts +0 -3
- package/dist/types/src/conversation/index.d.ts.map +0 -1
- package/dist/types/src/diff.d.ts.map +0 -1
- package/dist/types/src/errors.d.ts.map +0 -1
- package/dist/types/src/execution-graph.d.ts.map +0 -1
- package/dist/types/src/execution-graph.test.d.ts.map +0 -1
- package/dist/types/src/extraction/extraction-llm-function/extraction-llm-function.d.ts +0 -4
- package/dist/types/src/extraction/extraction-llm-function/extraction-llm-function.d.ts.map +0 -1
- package/dist/types/src/extraction/extraction-llm-function/extraction-llm-function.test.d.ts +0 -2
- package/dist/types/src/extraction/extraction-llm-function/extraction-llm-function.test.d.ts.map +0 -1
- package/dist/types/src/extraction/extraction-llm-function/index.d.ts +0 -2
- package/dist/types/src/extraction/extraction-llm-function/index.d.ts.map +0 -1
- package/dist/types/src/extraction/extraction-ner-function/extraction-ner-function.d.ts +0 -345
- package/dist/types/src/extraction/extraction-ner-function/extraction-ner-function.d.ts.map +0 -1
- package/dist/types/src/extraction/extraction-ner-function/extraction-ner-function.test.d.ts +0 -2
- package/dist/types/src/extraction/extraction-ner-function/extraction-ner-function.test.d.ts.map +0 -1
- package/dist/types/src/session/artifact-diff.d.ts.map +0 -1
- package/dist/types/src/session/error-handling.d.ts.map +0 -1
- package/dist/types/src/session/format.d.ts +0 -186
- package/dist/types/src/session/format.d.ts.map +0 -1
- package/dist/types/src/session/format.test.d.ts +0 -2
- package/dist/types/src/session/format.test.d.ts.map +0 -1
- package/dist/types/src/session/observer.d.ts.map +0 -1
- package/dist/types/src/session/session.d.ts +0 -51
- package/dist/types/src/session/session.d.ts.map +0 -1
- package/dist/types/src/session/session.test.d.ts +0 -2
- package/dist/types/src/session/session.test.d.ts.map +0 -1
- package/dist/types/src/session/version-pin.d.ts.map +0 -1
- package/dist/types/src/summarization/summarization.test.d.ts +0 -2
- package/dist/types/src/summarization/summarization.test.d.ts.map +0 -1
- package/dist/types/src/types/artifact.d.ts +0 -16
- package/dist/types/src/types/artifact.d.ts.map +0 -1
- package/dist/types/src/types/index.d.ts +0 -2
- package/dist/types/src/types/index.d.ts.map +0 -1
- package/src/conversation/context.ts +0 -186
- package/src/conversation/conversation.ts +0 -128
- package/src/conversation/index.ts +0 -6
- package/src/diff.test.ts +0 -43
- package/src/errors.ts +0 -15
- package/src/extraction/extraction-llm-function/extraction-llm-function.test.ts +0 -84
- package/src/extraction/extraction-llm-function/extraction-llm-function.ts +0 -72
- package/src/extraction/extraction-llm-function/index.ts +0 -5
- package/src/extraction/extraction-ner-function/extraction-ner-function.test.ts +0 -115
- package/src/extraction/extraction-ner-function/extraction-ner-function.ts +0 -64
- package/src/session/format.test.ts +0 -60
- package/src/session/session.conversations.json +0 -1
- package/src/session/session.test.ts +0 -149
- package/src/session/session.ts +0 -213
- package/src/summarization/summarization.test.ts +0 -202
- package/src/types/index.ts +0 -5
- /package/dist/lib/{browser/named-entity-recognition-QPYHML66.mjs.map → neutral/chunk-J5LGTIGS.mjs.map} +0 -0
- /package/dist/types/src/{diff.test.d.ts → util/diff.test.d.ts} +0 -0
- /package/dist/types/src/{session → util}/error-handling.d.ts +0 -0
- /package/dist/types/src/{execution-graph.test.d.ts → util/execution-graph.test.d.ts} +0 -0
- /package/src/extraction/extraction-llm-function/{instructions.tpl → transcription-instructions.tpl} +0 -0
|
@@ -47,9 +47,10 @@ export const reduceDiffs = (diffs: readonly string[]): Diff[] => {
|
|
|
47
47
|
}
|
|
48
48
|
return acc;
|
|
49
49
|
}
|
|
50
|
+
default: {
|
|
51
|
+
throw new Error(`Invalid diff format: each line must start with "- " or "+ ", got: ${JSON.stringify(diff)}`);
|
|
52
|
+
}
|
|
50
53
|
}
|
|
51
|
-
|
|
52
|
-
return acc;
|
|
53
54
|
}, []);
|
|
54
55
|
};
|
|
55
56
|
|
|
@@ -65,7 +66,11 @@ export const computeDiffsWithCursors = <T>(accessor: DocAccessor<T>, diffs: read
|
|
|
65
66
|
.filter(isNonNullable);
|
|
66
67
|
};
|
|
67
68
|
|
|
68
|
-
export const applyDiffs = <T>(
|
|
69
|
+
export const applyDiffs = <T>(
|
|
70
|
+
accessor: DocAccessor<T>,
|
|
71
|
+
diffs: readonly string[],
|
|
72
|
+
{ errorOnNotFound = false }: { errorOnNotFound?: boolean } = {},
|
|
73
|
+
): string => {
|
|
69
74
|
for (const diff of reduceDiffs(diffs)) {
|
|
70
75
|
accessor.handle.change((doc: Doc<T>) => {
|
|
71
76
|
const text = DocAccessor.getValue<string>(accessor);
|
|
@@ -75,7 +80,11 @@ export const applyDiffs = <T>(accessor: DocAccessor<T>, diffs: readonly string[]
|
|
|
75
80
|
// NOTE: This only replaces the first match.
|
|
76
81
|
A.splice(doc, accessor.path as A.Prop[], idx, diff.match.length, diff.replace);
|
|
77
82
|
} else {
|
|
78
|
-
|
|
83
|
+
if (errorOnNotFound) {
|
|
84
|
+
throw new Error(`Diff not found: ${diff.match}`);
|
|
85
|
+
} else {
|
|
86
|
+
log.warn('diff not found', diff);
|
|
87
|
+
}
|
|
79
88
|
}
|
|
80
89
|
});
|
|
81
90
|
}
|
|
@@ -7,7 +7,7 @@ import * as HttpClientError from '@effect/platform/HttpClientError';
|
|
|
7
7
|
import * as Effect from 'effect/Effect';
|
|
8
8
|
import * as Schema from 'effect/Schema';
|
|
9
9
|
|
|
10
|
-
import { AiModelError } from '
|
|
10
|
+
import { AiModelError } from './errors';
|
|
11
11
|
|
|
12
12
|
const AnthropicErrorResponse = Schema.Struct({
|
|
13
13
|
type: Schema.Literal('error'),
|
|
@@ -17,7 +17,7 @@ const AnthropicErrorResponse = Schema.Struct({
|
|
|
17
17
|
}),
|
|
18
18
|
});
|
|
19
19
|
|
|
20
|
-
// TODO(dmaretskyi): Needs rework
|
|
20
|
+
// TODO(dmaretskyi): Needs rework.
|
|
21
21
|
export const mapAiError = (err: AiError.AiError): Effect.Effect<AiError.AiError> =>
|
|
22
22
|
Effect.gen(function* () {
|
|
23
23
|
const cause = err.cause;
|
|
@@ -30,6 +30,7 @@ export const mapAiError = (err: AiError.AiError): Effect.Effect<AiError.AiError>
|
|
|
30
30
|
message: body.error.message,
|
|
31
31
|
context: { model: 'anthropic', type: body.error.type },
|
|
32
32
|
});
|
|
33
|
+
|
|
33
34
|
return AiError.UnknownError.make({
|
|
34
35
|
description: body.error.message,
|
|
35
36
|
module: err.module,
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
//
|
|
2
|
+
// Copyright 2025 DXOS.org
|
|
3
|
+
//
|
|
4
|
+
|
|
5
|
+
import { BaseError } from '@dxos/errors';
|
|
6
|
+
|
|
7
|
+
/**
|
|
8
|
+
* Generic error from AI model.
|
|
9
|
+
*/
|
|
10
|
+
export class AiModelError extends BaseError.extend('AiModelError', 'AI model error') {}
|
|
11
|
+
|
|
12
|
+
/**
|
|
13
|
+
* Generic error for AI agent execution.
|
|
14
|
+
*/
|
|
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/
|
|
9
|
+
import { ObjectId } from '@dxos/keys';
|
|
10
10
|
import { log } from '@dxos/log';
|
|
11
|
-
import {
|
|
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(
|
|
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(
|
|
66
|
+
const message = Obj.make(Message.Message, {
|
|
65
67
|
created: '2025-09-29T14:29:37.860Z',
|
|
66
68
|
sender: {
|
|
67
69
|
role: 'user',
|
|
@@ -69,7 +71,7 @@ describe('ExecutionGraph', () => {
|
|
|
69
71
|
blocks: [
|
|
70
72
|
{
|
|
71
73
|
_tag: 'text',
|
|
72
|
-
text: '{"id":"01K6AXZKK79H4E54RKP1YZDARK","@type":"dxn:type:dxos.
|
|
74
|
+
text: '{"id":"01K6AXZKK79H4E54RKP1YZDARK","@type":"dxn:type:org.dxos.type.organization:0.1.0","@meta":{"keys":[]},"name":"Blue Yard","website":"https://blueyard.com"}',
|
|
73
75
|
},
|
|
74
76
|
],
|
|
75
77
|
properties: {},
|
|
@@ -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(
|
|
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(
|
|
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(
|
|
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(
|
|
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(
|
|
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(
|
|
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(
|
|
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(
|
|
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(
|
|
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(
|
|
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(
|
|
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(
|
|
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(
|
|
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(
|
|
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(
|
|
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(
|
|
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(
|
|
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(
|
|
613
|
+
const message = Obj.make(Message.Message, {
|
|
612
614
|
id: messageId,
|
|
613
615
|
created: '2025-01-01T00:00:00Z',
|
|
614
616
|
sender: { role: 'assistant' },
|
|
@@ -617,7 +619,7 @@ describe('ExecutionGraph', () => {
|
|
|
617
619
|
{ _tag: 'reasoning', reasoningText: 'I need to think about this' },
|
|
618
620
|
{ _tag: 'toolCall', toolCallId: 'tool1', name: 'analyze', input: '{}', providerExecuted: false },
|
|
619
621
|
{
|
|
620
|
-
_tag: '
|
|
622
|
+
_tag: 'stats',
|
|
621
623
|
message: 'OK',
|
|
622
624
|
duration: 1000,
|
|
623
625
|
toolCalls: 1,
|
|
@@ -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(
|
|
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(
|
|
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(
|
|
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(
|
|
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(
|
|
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(
|
|
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,
|
|
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
|
*/
|
|
@@ -38,7 +40,7 @@ enum IconType {
|
|
|
38
40
|
// Interactions.
|
|
39
41
|
USER = 'ph--user--regular',
|
|
40
42
|
USER_INTERACTION = 'ph--user-sound--regular',
|
|
41
|
-
AGENT = 'ph--
|
|
43
|
+
AGENT = 'ph--drone--regular',
|
|
42
44
|
THINKING = 'ph--brain--regular',
|
|
43
45
|
LINK = 'ph--link--regular',
|
|
44
46
|
TOOL = 'ph--wrench--regular',
|
|
@@ -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:
|
|
68
|
+
addEvents(events: Entity.Unknown[]) {
|
|
65
69
|
const sortedEvents = this.sortObjectsByCreated(events);
|
|
66
70
|
for (const event of sortedEvents) {
|
|
67
|
-
if (Obj.instanceOf(
|
|
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:
|
|
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
|
|
|
@@ -194,13 +199,19 @@ export class ExecutionGraph {
|
|
|
194
199
|
*/
|
|
195
200
|
private _updatePendingToolResults(toolCallId: string, agentStatusId: string) {
|
|
196
201
|
const toolResultId = this._pendingToolResults.get(toolCallId);
|
|
197
|
-
if (!toolResultId)
|
|
202
|
+
if (!toolResultId) {
|
|
203
|
+
return;
|
|
204
|
+
}
|
|
198
205
|
|
|
199
206
|
const toolResultCommit = this._commits.find((c) => c.id === toolResultId);
|
|
200
|
-
if (!toolResultCommit)
|
|
207
|
+
if (!toolResultCommit) {
|
|
208
|
+
return;
|
|
209
|
+
}
|
|
201
210
|
|
|
202
211
|
const toolCallCommitId = this._toolCallCommitIds.get(toolCallId);
|
|
203
|
-
if (!toolCallCommitId)
|
|
212
|
+
if (!toolCallCommitId) {
|
|
213
|
+
return;
|
|
214
|
+
}
|
|
204
215
|
|
|
205
216
|
// Replace tool call commit with AgentStatus commit.
|
|
206
217
|
const toolCallIndex = toolResultCommit.parents.indexOf(toolCallCommitId);
|
|
@@ -216,7 +227,9 @@ export class ExecutionGraph {
|
|
|
216
227
|
*/
|
|
217
228
|
private _handleLateToolResultUpdate(toolCallId: string, toolResultId: string) {
|
|
218
229
|
const toolCallCommitId = this._toolCallCommitIds.get(toolCallId);
|
|
219
|
-
if (!toolCallCommitId)
|
|
230
|
+
if (!toolCallCommitId) {
|
|
231
|
+
return;
|
|
232
|
+
}
|
|
220
233
|
|
|
221
234
|
const messageId = toolCallCommitId.split('_toolCall_')[0];
|
|
222
235
|
const toolCallBranch = `${messageId}_${toolCallId}`;
|
|
@@ -278,15 +291,16 @@ export class ExecutionGraph {
|
|
|
278
291
|
}
|
|
279
292
|
}
|
|
280
293
|
|
|
281
|
-
// TODO(burdon): Pass in AiToolProvider.
|
|
282
294
|
/**
|
|
283
295
|
* Creates commits for all blocks in a message.
|
|
284
296
|
*/
|
|
297
|
+
// TODO(burdon): Pass in AiToolProvider.
|
|
285
298
|
const messageToCommits = (
|
|
286
|
-
message:
|
|
299
|
+
message: Message.Message,
|
|
287
300
|
lastBlockId?: string,
|
|
288
301
|
toolCallIds?: Map<string, string>,
|
|
289
302
|
lastCommitByBranch?: Map<string, string>,
|
|
303
|
+
skipBlocks?: ContentBlock.Any['_tag'][],
|
|
290
304
|
): Commit[] => {
|
|
291
305
|
let previousBlockId: string | undefined = lastBlockId;
|
|
292
306
|
|
|
@@ -294,6 +308,9 @@ const messageToCommits = (
|
|
|
294
308
|
.map((block, idx) => {
|
|
295
309
|
const branch = getMessageBranch(message);
|
|
296
310
|
const parents = getBlockParents(block, previousBlockId, message, toolCallIds, lastCommitByBranch);
|
|
311
|
+
if (skipBlocks?.includes(block._tag)) {
|
|
312
|
+
return null;
|
|
313
|
+
}
|
|
297
314
|
|
|
298
315
|
const commit = createBlockCommit(block, message, branch, parents, idx);
|
|
299
316
|
if (commit) {
|
|
@@ -311,14 +328,14 @@ const messageToCommits = (
|
|
|
311
328
|
const getBlockParents = (
|
|
312
329
|
block: ContentBlock.Any,
|
|
313
330
|
previousBlockId: string | undefined,
|
|
314
|
-
message:
|
|
331
|
+
message: Message.Message,
|
|
315
332
|
toolCallIds?: Map<string, string>,
|
|
316
333
|
lastCommitByBranch?: Map<string, string>,
|
|
317
334
|
): string[] => {
|
|
318
335
|
const parents: string[] = [];
|
|
319
336
|
|
|
320
337
|
if (block._tag === 'toolResult') {
|
|
321
|
-
// Tool results have two parents: previous block and last block from tool call branch
|
|
338
|
+
// Tool results have two parents: previous block and last block from tool call branch.
|
|
322
339
|
if (previousBlockId) {
|
|
323
340
|
parents.push(previousBlockId);
|
|
324
341
|
}
|
|
@@ -355,7 +372,7 @@ const getBlockParents = (
|
|
|
355
372
|
*/
|
|
356
373
|
const createBlockCommit = (
|
|
357
374
|
block: ContentBlock.Any,
|
|
358
|
-
message:
|
|
375
|
+
message: Message.Message,
|
|
359
376
|
branch: string,
|
|
360
377
|
parents: string[],
|
|
361
378
|
idx: number,
|
|
@@ -363,7 +380,9 @@ const createBlockCommit = (
|
|
|
363
380
|
const timestamp = new Date(message.created);
|
|
364
381
|
switch (block._tag) {
|
|
365
382
|
case 'text':
|
|
366
|
-
if (!block.text.trim().length)
|
|
383
|
+
if (!block.text.trim().length) {
|
|
384
|
+
return null;
|
|
385
|
+
}
|
|
367
386
|
return {
|
|
368
387
|
id: getGenericBlockId(message.id, idx),
|
|
369
388
|
branch,
|
|
@@ -403,7 +422,7 @@ const createBlockCommit = (
|
|
|
403
422
|
message: block.error ? 'Tool error: ' + block.error : 'Tool call succeeded',
|
|
404
423
|
} satisfies Commit;
|
|
405
424
|
|
|
406
|
-
case '
|
|
425
|
+
case 'stats':
|
|
407
426
|
return {
|
|
408
427
|
id: getGenericBlockId(message.id, idx),
|
|
409
428
|
branch,
|
|
@@ -411,7 +430,7 @@ const createBlockCommit = (
|
|
|
411
430
|
timestamp,
|
|
412
431
|
icon: IconType.ROCKET,
|
|
413
432
|
level: LogLevel.INFO,
|
|
414
|
-
message: ContentBlock.
|
|
433
|
+
message: ContentBlock.createStatsMessage(block),
|
|
415
434
|
} satisfies Commit;
|
|
416
435
|
|
|
417
436
|
case 'status':
|
|
@@ -472,14 +491,14 @@ const getBranchName = (options: { parentMessage?: ObjectId; toolCallId?: string
|
|
|
472
491
|
}
|
|
473
492
|
};
|
|
474
493
|
|
|
475
|
-
const getMessageBranch = (message:
|
|
494
|
+
const getMessageBranch = (message: Message.Message) => {
|
|
476
495
|
return getBranchName({
|
|
477
496
|
parentMessage: message.parentMessage,
|
|
478
497
|
toolCallId: message.properties?.[MESSAGE_PROPERTY_TOOL_CALL_ID],
|
|
479
498
|
});
|
|
480
499
|
};
|
|
481
500
|
|
|
482
|
-
const getParentId = (message:
|
|
501
|
+
const getParentId = (message: Message.Message) => {
|
|
483
502
|
if (message.parentMessage && message.properties?.[MESSAGE_PROPERTY_TOOL_CALL_ID]) {
|
|
484
503
|
return getToolCallId(message.parentMessage, message.properties[MESSAGE_PROPERTY_TOOL_CALL_ID]);
|
|
485
504
|
} else {
|
|
@@ -487,7 +506,7 @@ const getParentId = (message: DataType.Message) => {
|
|
|
487
506
|
}
|
|
488
507
|
};
|
|
489
508
|
|
|
490
|
-
const stringifyRef = (ref: Ref.
|
|
509
|
+
const stringifyRef = (ref: Ref.Unknown) => {
|
|
491
510
|
if (ref.target) {
|
|
492
511
|
return stringifyObject(ref.target);
|
|
493
512
|
}
|
|
@@ -495,6 +514,6 @@ const stringifyRef = (ref: Ref.Any) => {
|
|
|
495
514
|
return ref.dxn.asEchoDXN()?.echoId ?? ref.dxn.asQueueDXN()?.objectId ?? '';
|
|
496
515
|
};
|
|
497
516
|
|
|
498
|
-
const stringifyObject = (obj: Obj.
|
|
517
|
+
const stringifyObject = (obj: Obj.Unknown) => {
|
|
499
518
|
return Obj.getLabel(obj) ?? Obj.getTypename(obj) ?? obj.id;
|
|
500
519
|
};
|