@dxos/assistant-toolkit 0.8.4-main.2c6827d → 0.8.4-main.3c1ae3b
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/dist/lib/browser/index.mjs +123 -112
- package/dist/lib/browser/index.mjs.map +3 -3
- package/dist/lib/browser/meta.json +1 -1
- package/dist/lib/node-esm/index.mjs +123 -112
- package/dist/lib/node-esm/index.mjs.map +3 -3
- package/dist/lib/node-esm/meta.json +1 -1
- package/dist/types/src/blueprints/discord/discord-blueprint.d.ts +4 -3
- package/dist/types/src/blueprints/discord/discord-blueprint.d.ts.map +1 -1
- package/dist/types/src/blueprints/linear/linear-blueprint.d.ts +4 -3
- package/dist/types/src/blueprints/linear/linear-blueprint.d.ts.map +1 -1
- package/dist/types/src/crud/graph.d.ts +5 -4
- package/dist/types/src/crud/graph.d.ts.map +1 -1
- package/dist/types/src/functions/agent/prompt.d.ts.map +1 -1
- package/dist/types/src/functions/document/read.d.ts.map +1 -1
- package/dist/types/src/functions/document/update.d.ts.map +1 -1
- package/dist/types/src/functions/entity-extraction/entity-extraction.d.ts +12 -13
- package/dist/types/src/functions/entity-extraction/entity-extraction.d.ts.map +1 -1
- package/dist/types/src/functions/entity-extraction/index.d.ts +12 -13
- package/dist/types/src/functions/entity-extraction/index.d.ts.map +1 -1
- package/dist/types/src/functions/linear/sync-issues.d.ts.map +1 -1
- package/dist/types/src/functions/research/document-create.d.ts.map +1 -1
- package/dist/types/src/functions/research/research-graph.d.ts +7 -6
- package/dist/types/src/functions/research/research-graph.d.ts.map +1 -1
- package/dist/types/src/functions/research/research.d.ts.map +1 -1
- package/dist/types/src/functions/research/types.d.ts +1 -1
- package/dist/types/src/functions/research/types.d.ts.map +1 -1
- package/dist/types/src/functions/tasks/read.d.ts.map +1 -1
- package/dist/types/src/functions/tasks/update.d.ts.map +1 -1
- package/dist/types/src/plugins.d.ts.map +1 -1
- package/dist/types/src/sync/sync.d.ts +2 -2
- package/dist/types/src/sync/sync.d.ts.map +1 -1
- package/dist/types/src/toolkits/AssistantToolkit.d.ts +2 -2
- package/dist/types/src/toolkits/AssistantToolkit.d.ts.map +1 -1
- package/dist/types/src/toolkits/SystemToolkit.d.ts +8 -8
- package/dist/types/src/toolkits/SystemToolkit.d.ts.map +1 -1
- package/dist/types/tsconfig.tsbuildinfo +1 -1
- package/package.json +23 -23
- package/src/blueprints/design/design-blueprint.test.ts +8 -6
- package/src/blueprints/planning/planning-blueprint.test.ts +6 -4
- package/src/crud/graph.test.ts +4 -3
- package/src/crud/graph.ts +19 -24
- package/src/experimental/feed.test.ts +1 -1
- package/src/functions/agent/prompt.ts +13 -10
- package/src/functions/discord/fetch-messages.test.ts +1 -1
- package/src/functions/document/read.ts +4 -3
- package/src/functions/document/update.ts +4 -3
- package/src/functions/entity-extraction/entity-extraction.test.ts +7 -6
- package/src/functions/entity-extraction/entity-extraction.ts +20 -10
- package/src/functions/linear/linear.test.ts +11 -10
- package/src/functions/linear/sync-issues.ts +5 -4
- package/src/functions/research/document-create.ts +7 -6
- package/src/functions/research/research-graph.ts +12 -10
- package/src/functions/research/research.test.ts +20 -24
- package/src/functions/research/research.ts +5 -4
- package/src/functions/research/types.ts +1 -1
- package/src/functions/tasks/read.ts +4 -3
- package/src/functions/tasks/update.ts +4 -3
- package/src/plugins.tsx +3 -3
- package/src/sync/sync.ts +4 -6
- package/src/toolkits/AssistantToolkit.test.ts +8 -6
- package/src/toolkits/AssistantToolkit.ts +3 -3
- package/src/toolkits/SystemToolkit.ts +18 -18
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@dxos/assistant-toolkit",
|
|
3
|
-
"version": "0.8.4-main.
|
|
3
|
+
"version": "0.8.4-main.3c1ae3b",
|
|
4
4
|
"description": "Assistant toolkit, definitions, and utilities.",
|
|
5
5
|
"homepage": "https://dxos.org",
|
|
6
6
|
"bugs": "https://github.com/dxos/dxos/issues",
|
|
@@ -30,28 +30,28 @@
|
|
|
30
30
|
"@effect/platform": "^0.92.1",
|
|
31
31
|
"dfx": "^0.126.0",
|
|
32
32
|
"exa-js": "^1.5.12",
|
|
33
|
-
"@dxos/app-framework": "0.8.4-main.
|
|
34
|
-
"@dxos/
|
|
35
|
-
"@dxos/
|
|
36
|
-
"@dxos/
|
|
37
|
-
"@dxos/
|
|
38
|
-
"@dxos/echo": "0.8.4-main.
|
|
39
|
-
"@dxos/
|
|
40
|
-
"@dxos/
|
|
41
|
-
"@dxos/edge-client": "0.8.4-main.
|
|
42
|
-
"@dxos/
|
|
43
|
-
"@dxos/
|
|
44
|
-
"@dxos/
|
|
45
|
-
"@dxos/
|
|
46
|
-
"@dxos/
|
|
47
|
-
"@dxos/functions
|
|
48
|
-
"@dxos/keys": "0.8.4-main.
|
|
49
|
-
"@dxos/
|
|
50
|
-
"@dxos/
|
|
51
|
-
"@dxos/
|
|
52
|
-
"@dxos/schema": "0.8.4-main.
|
|
53
|
-
"@dxos/types": "0.8.4-main.
|
|
54
|
-
"@dxos/util": "0.8.4-main.
|
|
33
|
+
"@dxos/app-framework": "0.8.4-main.3c1ae3b",
|
|
34
|
+
"@dxos/assistant": "0.8.4-main.3c1ae3b",
|
|
35
|
+
"@dxos/ai": "0.8.4-main.3c1ae3b",
|
|
36
|
+
"@dxos/conductor": "0.8.4-main.3c1ae3b",
|
|
37
|
+
"@dxos/blueprints": "0.8.4-main.3c1ae3b",
|
|
38
|
+
"@dxos/echo": "0.8.4-main.3c1ae3b",
|
|
39
|
+
"@dxos/echo-protocol": "0.8.4-main.3c1ae3b",
|
|
40
|
+
"@dxos/context": "0.8.4-main.3c1ae3b",
|
|
41
|
+
"@dxos/edge-client": "0.8.4-main.3c1ae3b",
|
|
42
|
+
"@dxos/effect": "0.8.4-main.3c1ae3b",
|
|
43
|
+
"@dxos/functions-runtime": "0.8.4-main.3c1ae3b",
|
|
44
|
+
"@dxos/errors": "0.8.4-main.3c1ae3b",
|
|
45
|
+
"@dxos/invariant": "0.8.4-main.3c1ae3b",
|
|
46
|
+
"@dxos/echo-db": "0.8.4-main.3c1ae3b",
|
|
47
|
+
"@dxos/functions": "0.8.4-main.3c1ae3b",
|
|
48
|
+
"@dxos/keys": "0.8.4-main.3c1ae3b",
|
|
49
|
+
"@dxos/log": "0.8.4-main.3c1ae3b",
|
|
50
|
+
"@dxos/plugin-markdown": "0.8.4-main.3c1ae3b",
|
|
51
|
+
"@dxos/react-ui-syntax-highlighter": "0.8.4-main.3c1ae3b",
|
|
52
|
+
"@dxos/schema": "0.8.4-main.3c1ae3b",
|
|
53
|
+
"@dxos/types": "0.8.4-main.3c1ae3b",
|
|
54
|
+
"@dxos/util": "0.8.4-main.3c1ae3b"
|
|
55
55
|
},
|
|
56
56
|
"devDependencies": {
|
|
57
57
|
"effect": "3.18.3",
|
|
@@ -17,8 +17,10 @@ import {
|
|
|
17
17
|
} from '@dxos/assistant';
|
|
18
18
|
import { Blueprint } from '@dxos/blueprints';
|
|
19
19
|
import { Obj, Ref } from '@dxos/echo';
|
|
20
|
-
import {
|
|
21
|
-
import {
|
|
20
|
+
import { Database } from '@dxos/echo';
|
|
21
|
+
import { acquireReleaseResource } from '@dxos/effect';
|
|
22
|
+
import { TestHelpers } from '@dxos/effect/testing';
|
|
23
|
+
import { QueueService, TracingService } from '@dxos/functions';
|
|
22
24
|
import { FunctionInvocationServiceLayerTestMocked, TestDatabaseLayer } from '@dxos/functions-runtime/testing';
|
|
23
25
|
import { log } from '@dxos/log';
|
|
24
26
|
import { Markdown } from '@dxos/plugin-markdown/types';
|
|
@@ -40,19 +42,19 @@ describe('Design Blueprint', { timeout: 120_000 }, () => {
|
|
|
40
42
|
const queue = yield* QueueService.createQueue<Message.Message | ContextBinding>();
|
|
41
43
|
const conversation = yield* acquireReleaseResource(() => new AiConversation(queue));
|
|
42
44
|
|
|
43
|
-
yield*
|
|
45
|
+
yield* Database.Service.add(blueprint);
|
|
44
46
|
yield* Effect.promise(() =>
|
|
45
47
|
conversation.context.bind({
|
|
46
48
|
blueprints: [Ref.make(blueprint)],
|
|
47
49
|
}),
|
|
48
50
|
);
|
|
49
51
|
|
|
50
|
-
const artifact = yield*
|
|
52
|
+
const artifact = yield* Database.Service.add(Markdown.make({ content: 'Hello, world!' }));
|
|
51
53
|
let prevContent = artifact.content;
|
|
52
54
|
|
|
53
55
|
{
|
|
54
56
|
const prompt = trim`
|
|
55
|
-
I want to design a new feature for our product.
|
|
57
|
+
I want to design a new feature for our product.
|
|
56
58
|
|
|
57
59
|
We need to add a user profile system with the following requirements:
|
|
58
60
|
1. Users should be able to create and edit their profiles
|
|
@@ -72,7 +74,7 @@ describe('Design Blueprint', { timeout: 120_000 }, () => {
|
|
|
72
74
|
|
|
73
75
|
{
|
|
74
76
|
const prompt = trim`
|
|
75
|
-
I want this to be built on top of Durable Objects and SQLite database.
|
|
77
|
+
I want this to be built on top of Durable Objects and SQLite database.
|
|
76
78
|
Adjust the spec to reflect this.
|
|
77
79
|
`;
|
|
78
80
|
|
|
@@ -16,8 +16,10 @@ import {
|
|
|
16
16
|
} from '@dxos/assistant';
|
|
17
17
|
import { Blueprint } from '@dxos/blueprints';
|
|
18
18
|
import { Obj, Ref } from '@dxos/echo';
|
|
19
|
-
import {
|
|
20
|
-
import {
|
|
19
|
+
import { Database } from '@dxos/echo';
|
|
20
|
+
import { acquireReleaseResource } from '@dxos/effect';
|
|
21
|
+
import { TestHelpers } from '@dxos/effect/testing';
|
|
22
|
+
import { QueueService, TracingService } from '@dxos/functions';
|
|
21
23
|
import { FunctionImplementationResolver } from '@dxos/functions-runtime';
|
|
22
24
|
import { FunctionInvocationServiceLayerTestMocked, TestDatabaseLayer } from '@dxos/functions-runtime/testing';
|
|
23
25
|
import { log } from '@dxos/log';
|
|
@@ -39,14 +41,14 @@ describe('Planning Blueprint', { timeout: 120_000 }, () => {
|
|
|
39
41
|
const queue = yield* QueueService.createQueue<Message.Message | ContextBinding>();
|
|
40
42
|
const conversation = yield* acquireReleaseResource(() => new AiConversation(queue));
|
|
41
43
|
|
|
42
|
-
yield*
|
|
44
|
+
yield* Database.Service.add(blueprint);
|
|
43
45
|
yield* Effect.promise(() =>
|
|
44
46
|
conversation.context.bind({
|
|
45
47
|
blueprints: [Ref.make(blueprint)],
|
|
46
48
|
}),
|
|
47
49
|
);
|
|
48
50
|
|
|
49
|
-
const artifact = yield*
|
|
51
|
+
const artifact = yield* Database.Service.add(Markdown.make());
|
|
50
52
|
let prevContent = artifact.content;
|
|
51
53
|
const matchList =
|
|
52
54
|
({ includes = [], excludes = [] }: { includes: RegExp[]; excludes?: RegExp[] }) =>
|
package/src/crud/graph.test.ts
CHANGED
|
@@ -14,8 +14,9 @@ import { AiService, ToolExecutionService, ToolResolverService } from '@dxos/ai';
|
|
|
14
14
|
import * as AiServiceRouter from '@dxos/ai/AiServiceRouter';
|
|
15
15
|
import { tapHttpErrors } from '@dxos/ai/testing';
|
|
16
16
|
import { AiSession } from '@dxos/assistant';
|
|
17
|
-
import {
|
|
18
|
-
import {
|
|
17
|
+
import { Database } from '@dxos/echo';
|
|
18
|
+
import { TestHelpers } from '@dxos/effect/testing';
|
|
19
|
+
import { TracingService } from '@dxos/functions';
|
|
19
20
|
import { log } from '@dxos/log';
|
|
20
21
|
import { Project } from '@dxos/types';
|
|
21
22
|
|
|
@@ -25,7 +26,7 @@ import { makeGraphWriterHandler, makeGraphWriterToolkit } from './graph';
|
|
|
25
26
|
|
|
26
27
|
const TestLayer = Function.pipe(
|
|
27
28
|
AiService.model('@anthropic/claude-3-5-sonnet-20241022'),
|
|
28
|
-
Layer.provideMerge(
|
|
29
|
+
Layer.provideMerge(Database.Service.notAvailable),
|
|
29
30
|
Layer.provideMerge(ToolResolverService.layerEmpty),
|
|
30
31
|
Layer.provideMerge(ToolExecutionService.layerEmpty),
|
|
31
32
|
Layer.provide(AiServiceRouter.AiServiceRouter),
|
package/src/crud/graph.ts
CHANGED
|
@@ -11,28 +11,23 @@ import * as Option from 'effect/Option';
|
|
|
11
11
|
import * as Schema from 'effect/Schema';
|
|
12
12
|
import * as SchemaAST from 'effect/SchemaAST';
|
|
13
13
|
|
|
14
|
-
import { Obj,
|
|
15
|
-
import {
|
|
14
|
+
import { Entity, Filter, Obj, Query, Type } from '@dxos/echo';
|
|
15
|
+
import { Database } from '@dxos/echo';
|
|
16
16
|
import {
|
|
17
|
-
EntityKind,
|
|
18
|
-
ObjectId,
|
|
19
17
|
ReferenceAnnotationId,
|
|
20
18
|
RelationSourceDXNId,
|
|
21
19
|
RelationSourceId,
|
|
22
20
|
RelationTargetDXNId,
|
|
23
21
|
RelationTargetId,
|
|
24
|
-
|
|
25
|
-
getEntityKind,
|
|
26
|
-
getSchemaDXN,
|
|
27
|
-
getSchemaTypename,
|
|
22
|
+
createObject,
|
|
28
23
|
getTypeAnnotation,
|
|
29
24
|
getTypeIdentifierAnnotation,
|
|
30
25
|
} from '@dxos/echo/internal';
|
|
31
26
|
import { type EchoDatabase, type Queue } from '@dxos/echo-db';
|
|
32
27
|
import { isEncodedReference } from '@dxos/echo-protocol';
|
|
33
28
|
import { mapAst } from '@dxos/effect';
|
|
34
|
-
import { ContextQueueService
|
|
35
|
-
import { DXN } from '@dxos/keys';
|
|
29
|
+
import { ContextQueueService } from '@dxos/functions';
|
|
30
|
+
import { DXN, ObjectId } from '@dxos/keys';
|
|
36
31
|
import { log } from '@dxos/log';
|
|
37
32
|
import { deepMapValues, isNonNullable, trim } from '@dxos/util';
|
|
38
33
|
|
|
@@ -66,7 +61,7 @@ export const findRelatedSchema = async (
|
|
|
66
61
|
// TODO(dmaretskyi): Also do references.
|
|
67
62
|
return allSchemas
|
|
68
63
|
.filter((schema) => {
|
|
69
|
-
if (getTypeAnnotation(schema)?.kind !==
|
|
64
|
+
if (getTypeAnnotation(schema)?.kind !== Entity.Kind.Relation) {
|
|
70
65
|
return false;
|
|
71
66
|
}
|
|
72
67
|
|
|
@@ -94,7 +89,7 @@ const isSchemaAddressableByDxn = (schema: Schema.Schema.AnyNoContext, dxn: DXN):
|
|
|
94
89
|
|
|
95
90
|
const t = dxn.asTypeDXN();
|
|
96
91
|
if (t) {
|
|
97
|
-
return t.type ===
|
|
92
|
+
return t.type === Type.getTypename(schema);
|
|
98
93
|
}
|
|
99
94
|
|
|
100
95
|
return false;
|
|
@@ -114,13 +109,13 @@ export const LocalSearchToolkit = Toolkit.make(
|
|
|
114
109
|
},
|
|
115
110
|
success: Schema.Unknown,
|
|
116
111
|
failure: Schema.Never,
|
|
117
|
-
dependencies: [
|
|
112
|
+
dependencies: [Database.Service],
|
|
118
113
|
}),
|
|
119
114
|
);
|
|
120
115
|
|
|
121
116
|
export const LocalSearchHandler = LocalSearchToolkit.toLayer({
|
|
122
117
|
search_local_search: Effect.fn(function* ({ query }) {
|
|
123
|
-
const
|
|
118
|
+
const objects = yield* Database.Service.runQuery(Query.select(Filter.text(query, { type: 'vector' })));
|
|
124
119
|
const results = [...objects];
|
|
125
120
|
|
|
126
121
|
const option = yield* Effect.serviceOption(ContextQueueService);
|
|
@@ -158,7 +153,7 @@ export const makeGraphWriterToolkit = ({ schema }: { schema: Schema.Schema.AnyNo
|
|
|
158
153
|
parameters: createExtractionSchema(schema).fields,
|
|
159
154
|
success: Schema.Unknown,
|
|
160
155
|
failure: Schema.Never,
|
|
161
|
-
dependencies: [
|
|
156
|
+
dependencies: [Database.Service, ContextQueueService],
|
|
162
157
|
}).annotateContext(Context.make(GraphWriterSchema, { schema })),
|
|
163
158
|
);
|
|
164
159
|
};
|
|
@@ -178,7 +173,7 @@ export const makeGraphWriterHandler = (
|
|
|
178
173
|
|
|
179
174
|
return toolkit.toLayer({
|
|
180
175
|
graph_writer: Effect.fn(function* (input) {
|
|
181
|
-
const { db } = yield*
|
|
176
|
+
const { db } = yield* Database.Service;
|
|
182
177
|
const { queue } = yield* ContextQueueService;
|
|
183
178
|
const data = yield* Effect.promise(() => sanitizeObjects(schema, input as any, db, queue));
|
|
184
179
|
yield* Effect.promise(() => queue.append(data as Obj.Any[]));
|
|
@@ -199,7 +194,7 @@ export const createExtractionSchema = (types: Schema.Schema.AnyNoContext[]) => {
|
|
|
199
194
|
types.map(preprocessSchema).map((schema, index) => [
|
|
200
195
|
`objects_${getSanitizedSchemaName(types[index])}`,
|
|
201
196
|
Schema.optional(Schema.Array(schema)).annotations({
|
|
202
|
-
description: `The objects of type: ${
|
|
197
|
+
description: `The objects of type: ${Type.getDXN(types[index])?.asTypeDXN()!.type}. ${SchemaAST.getDescriptionAnnotation(types[index].ast).pipe(Option.getOrElse(() => ''))}`,
|
|
203
198
|
}),
|
|
204
199
|
]),
|
|
205
200
|
),
|
|
@@ -207,7 +202,7 @@ export const createExtractionSchema = (types: Schema.Schema.AnyNoContext[]) => {
|
|
|
207
202
|
};
|
|
208
203
|
|
|
209
204
|
export const getSanitizedSchemaName = (schema: Schema.Schema.AnyNoContext) => {
|
|
210
|
-
return
|
|
205
|
+
return Type.getDXN(schema)!
|
|
211
206
|
.asTypeDXN()!
|
|
212
207
|
.type.replaceAll(/[^a-zA-Z0-9]+/g, '_');
|
|
213
208
|
};
|
|
@@ -215,7 +210,7 @@ export const getSanitizedSchemaName = (schema: Schema.Schema.AnyNoContext) => {
|
|
|
215
210
|
export const sanitizeObjects = async (
|
|
216
211
|
types: Schema.Schema.AnyNoContext[],
|
|
217
212
|
data: Record<string, readonly unknown[]>,
|
|
218
|
-
db:
|
|
213
|
+
db: Database.Database,
|
|
219
214
|
queue?: Queue,
|
|
220
215
|
): Promise<Obj.Any[]> => {
|
|
221
216
|
const entries = types
|
|
@@ -230,7 +225,7 @@ export const sanitizeObjects = async (
|
|
|
230
225
|
|
|
231
226
|
const idMap = new Map<string, string>();
|
|
232
227
|
const existingIds = new Set<ObjectId>();
|
|
233
|
-
const enitties = new Map<ObjectId,
|
|
228
|
+
const enitties = new Map<ObjectId, Entity.Unknown>();
|
|
234
229
|
|
|
235
230
|
const resolveId = (id: string): DXN | undefined => {
|
|
236
231
|
if (ObjectId.isValid(id)) {
|
|
@@ -275,7 +270,7 @@ export const sanitizeObjects = async (
|
|
|
275
270
|
return recurse(value);
|
|
276
271
|
});
|
|
277
272
|
|
|
278
|
-
if (
|
|
273
|
+
if (Entity.getKind(entry.schema) === 'relation') {
|
|
279
274
|
const sourceDxn = resolveId(data.source);
|
|
280
275
|
if (!sourceDxn) {
|
|
281
276
|
log.warn('source not found', { source: data.source });
|
|
@@ -298,7 +293,7 @@ export const sanitizeObjects = async (
|
|
|
298
293
|
.filter((object) => !existingIds.has(object.data.id)); // TODO(dmaretskyi): This dissallows updating existing objects.
|
|
299
294
|
|
|
300
295
|
// TODO(dmaretskyi): Use ref resolver.
|
|
301
|
-
const
|
|
296
|
+
const dbObjects = await db.query(Query.select(Filter.id(...existingIds))).run();
|
|
302
297
|
const queueObjects = (await queue?.getObjectsById([...existingIds])) ?? [];
|
|
303
298
|
const objects = [...dbObjects, ...queueObjects].filter(isNonNullable);
|
|
304
299
|
|
|
@@ -332,7 +327,7 @@ export const sanitizeObjects = async (
|
|
|
332
327
|
}
|
|
333
328
|
}
|
|
334
329
|
if (!skip) {
|
|
335
|
-
const obj =
|
|
330
|
+
const obj = createObject(schema, data);
|
|
336
331
|
enitties.set(obj.id, obj);
|
|
337
332
|
return [obj];
|
|
338
333
|
}
|
|
@@ -347,7 +342,7 @@ const SoftRef = Schema.Struct({
|
|
|
347
342
|
});
|
|
348
343
|
|
|
349
344
|
const preprocessSchema = (schema: Schema.Schema.AnyNoContext) => {
|
|
350
|
-
const isRelationSchema =
|
|
345
|
+
const isRelationSchema = Entity.getKind(schema) === 'relation';
|
|
351
346
|
|
|
352
347
|
const go = (ast: SchemaAST.AST, visited = new Set<SchemaAST.AST>()): SchemaAST.AST => {
|
|
353
348
|
if (visited.has(ast)) {
|
|
@@ -13,7 +13,7 @@ import * as Redacted from 'effect/Redacted';
|
|
|
13
13
|
import { AiService } from '@dxos/ai';
|
|
14
14
|
import { AiServiceTestingPreset, EXA_API_KEY } from '@dxos/ai/testing';
|
|
15
15
|
import { makeToolExecutionServiceFromFunctions, makeToolResolverFromFunctions } from '@dxos/assistant';
|
|
16
|
-
import { TestHelpers } from '@dxos/effect';
|
|
16
|
+
import { TestHelpers } from '@dxos/effect/testing';
|
|
17
17
|
import { CredentialsService, FunctionInvocationService } from '@dxos/functions';
|
|
18
18
|
import { TracingServiceExt } from '@dxos/functions-runtime';
|
|
19
19
|
import {
|
|
@@ -13,7 +13,8 @@ import { AiService, ConsolePrinter, ModelName } from '@dxos/ai';
|
|
|
13
13
|
import { AiSession, GenerationObserver, createToolkit } from '@dxos/assistant';
|
|
14
14
|
import { Prompt, Template } from '@dxos/blueprints';
|
|
15
15
|
import { Obj, Ref, Type } from '@dxos/echo';
|
|
16
|
-
import {
|
|
16
|
+
import { Database } from '@dxos/echo';
|
|
17
|
+
import { TracingService, defineFunction } from '@dxos/functions';
|
|
17
18
|
import { log } from '@dxos/log';
|
|
18
19
|
|
|
19
20
|
const DEFAULT_MODEL: ModelName = '@anthropic/claude-opus-4-0';
|
|
@@ -45,7 +46,7 @@ export default defineFunction({
|
|
|
45
46
|
// for (const key of Object.keys(data.input)) {
|
|
46
47
|
// const value = data.input[key];
|
|
47
48
|
// if (Ref.isRef(value)) {
|
|
48
|
-
// const object = yield*
|
|
49
|
+
// const object = yield* Database.Service.load(value);
|
|
49
50
|
// input[key] = Obj.toJSON(object);
|
|
50
51
|
// } else {
|
|
51
52
|
// input[key] = JSON.stringify(value);
|
|
@@ -55,16 +56,16 @@ export default defineFunction({
|
|
|
55
56
|
Match.when(
|
|
56
57
|
(value: any) => Ref.isRef(value),
|
|
57
58
|
Effect.fnUntraced(function* (ref) {
|
|
58
|
-
const object = yield*
|
|
59
|
+
const object = yield* Database.Service.load(ref);
|
|
59
60
|
return Obj.toJSON(object as Obj.Any);
|
|
60
61
|
}),
|
|
61
62
|
),
|
|
62
63
|
Match.orElse(() => Effect.succeed(data.input)),
|
|
63
64
|
);
|
|
64
65
|
|
|
65
|
-
yield*
|
|
66
|
-
const prompt = yield*
|
|
67
|
-
const systemPrompt = data.systemPrompt ? yield*
|
|
66
|
+
yield* Database.Service.flush({ indexes: true });
|
|
67
|
+
const prompt = yield* Database.Service.load(data.prompt);
|
|
68
|
+
const systemPrompt = data.systemPrompt ? yield* Database.Service.load(data.systemPrompt) : undefined;
|
|
68
69
|
yield* TracingService.emitStatus({ message: `Running ${prompt.id}` });
|
|
69
70
|
|
|
70
71
|
log.info('starting agent', { prompt: prompt.id, input });
|
|
@@ -72,23 +73,25 @@ export default defineFunction({
|
|
|
72
73
|
const blueprints = yield* Function.pipe(
|
|
73
74
|
prompt.blueprints,
|
|
74
75
|
Array.appendAll(systemPrompt?.blueprints ?? []),
|
|
75
|
-
Effect.forEach(
|
|
76
|
+
Effect.forEach(Database.Service.loadOption),
|
|
76
77
|
Effect.map(Array.filter(Option.isSome)),
|
|
77
78
|
Effect.map(Array.map((option) => option.value)),
|
|
78
79
|
);
|
|
79
80
|
const objects = yield* Function.pipe(
|
|
80
81
|
prompt.context,
|
|
81
82
|
Array.appendAll(systemPrompt?.context ?? []),
|
|
82
|
-
Effect.forEach(
|
|
83
|
+
Effect.forEach(Database.Service.loadOption),
|
|
83
84
|
Effect.map(Array.filter(Option.isSome)),
|
|
84
85
|
Effect.map(Array.map((option) => option.value)),
|
|
85
86
|
);
|
|
86
87
|
const toolkit = yield* createToolkit({ blueprints });
|
|
87
88
|
|
|
88
|
-
const promptInstructions = yield*
|
|
89
|
+
const promptInstructions = yield* Database.Service.load(prompt.instructions.source);
|
|
89
90
|
const promptText = Template.process(promptInstructions.content, input);
|
|
90
91
|
|
|
91
|
-
const systemInstructions = systemPrompt
|
|
92
|
+
const systemInstructions = systemPrompt
|
|
93
|
+
? yield* Database.Service.load(systemPrompt.instructions.source)
|
|
94
|
+
: undefined;
|
|
92
95
|
const systemText = systemInstructions ? Template.process(systemInstructions.content, {}) : undefined;
|
|
93
96
|
|
|
94
97
|
const session = new AiSession();
|
|
@@ -12,7 +12,7 @@ import * as Layer from 'effect/Layer';
|
|
|
12
12
|
import { AiService } from '@dxos/ai';
|
|
13
13
|
import { AiServiceTestingPreset } from '@dxos/ai/testing';
|
|
14
14
|
import { makeToolExecutionServiceFromFunctions, makeToolResolverFromFunctions } from '@dxos/assistant';
|
|
15
|
-
import { TestHelpers } from '@dxos/effect';
|
|
15
|
+
import { TestHelpers } from '@dxos/effect/testing';
|
|
16
16
|
import { CredentialsService, FunctionInvocationService, TracingService } from '@dxos/functions';
|
|
17
17
|
import { FunctionInvocationServiceLayerTestMocked, TestDatabaseLayer } from '@dxos/functions-runtime/testing';
|
|
18
18
|
|
|
@@ -6,7 +6,8 @@ import * as Effect from 'effect/Effect';
|
|
|
6
6
|
import * as Schema from 'effect/Schema';
|
|
7
7
|
|
|
8
8
|
import { ArtifactId } from '@dxos/assistant';
|
|
9
|
-
import {
|
|
9
|
+
import { Database } from '@dxos/echo';
|
|
10
|
+
import { defineFunction } from '@dxos/functions';
|
|
10
11
|
import { Markdown } from '@dxos/plugin-markdown/types';
|
|
11
12
|
|
|
12
13
|
export default defineFunction({
|
|
@@ -22,8 +23,8 @@ export default defineFunction({
|
|
|
22
23
|
content: Schema.String,
|
|
23
24
|
}),
|
|
24
25
|
handler: Effect.fn(function* ({ data: { id } }) {
|
|
25
|
-
const doc = yield*
|
|
26
|
-
const { content } = yield*
|
|
26
|
+
const doc = yield* Database.Service.resolve(ArtifactId.toDXN(id), Markdown.Document);
|
|
27
|
+
const { content } = yield* Database.Service.load(doc.content);
|
|
27
28
|
return { content };
|
|
28
29
|
}),
|
|
29
30
|
});
|
|
@@ -6,7 +6,8 @@ import * as Effect from 'effect/Effect';
|
|
|
6
6
|
import * as Schema from 'effect/Schema';
|
|
7
7
|
|
|
8
8
|
import { ArtifactId } from '@dxos/assistant';
|
|
9
|
-
import {
|
|
9
|
+
import { Database } from '@dxos/echo';
|
|
10
|
+
import { defineFunction } from '@dxos/functions';
|
|
10
11
|
import { Markdown } from '@dxos/plugin-markdown/types';
|
|
11
12
|
|
|
12
13
|
export default defineFunction({
|
|
@@ -23,8 +24,8 @@ export default defineFunction({
|
|
|
23
24
|
}),
|
|
24
25
|
outputSchema: Schema.Void,
|
|
25
26
|
handler: Effect.fn(function* ({ data: { id, content } }) {
|
|
26
|
-
const doc = yield*
|
|
27
|
-
const text = yield*
|
|
27
|
+
const doc = yield* Database.Service.resolve(ArtifactId.toDXN(id), Markdown.Document);
|
|
28
|
+
const text = yield* Database.Service.load(doc.content);
|
|
28
29
|
text.content = content;
|
|
29
30
|
}),
|
|
30
31
|
});
|
|
@@ -6,13 +6,14 @@ import { describe, expect, it } from '@effect/vitest';
|
|
|
6
6
|
import * as Effect from 'effect/Effect';
|
|
7
7
|
import * as Layer from 'effect/Layer';
|
|
8
8
|
|
|
9
|
-
import { AiService
|
|
10
|
-
import { TestAiService } from '@dxos/ai/testing';
|
|
9
|
+
import { AiService } from '@dxos/ai';
|
|
10
|
+
import { MemoizedAiService, TestAiService } from '@dxos/ai/testing';
|
|
11
11
|
import { makeToolExecutionServiceFromFunctions, makeToolResolverFromFunctions } from '@dxos/assistant';
|
|
12
12
|
import { Blueprint } from '@dxos/blueprints';
|
|
13
13
|
import { Obj } from '@dxos/echo';
|
|
14
|
-
import {
|
|
15
|
-
import {
|
|
14
|
+
import { Database } from '@dxos/echo';
|
|
15
|
+
import { TestHelpers } from '@dxos/effect/testing';
|
|
16
|
+
import { CredentialsService, FunctionInvocationService, TracingService } from '@dxos/functions';
|
|
16
17
|
import { FunctionInvocationServiceLayerTest, TestDatabaseLayer } from '@dxos/functions-runtime/testing';
|
|
17
18
|
import { ObjectId } from '@dxos/keys';
|
|
18
19
|
import { Message, Organization, Person } from '@dxos/types';
|
|
@@ -49,7 +50,7 @@ describe('Entity extraction', () => {
|
|
|
49
50
|
'call a function to generate a research report',
|
|
50
51
|
Effect.fnUntraced(
|
|
51
52
|
function* (_) {
|
|
52
|
-
const email = yield*
|
|
53
|
+
const email = yield* Database.Service.add(
|
|
53
54
|
Obj.make(Message.Message, {
|
|
54
55
|
[Obj.Meta]: {
|
|
55
56
|
tags: ['important'],
|
|
@@ -75,7 +76,7 @@ describe('Entity extraction', () => {
|
|
|
75
76
|
],
|
|
76
77
|
}),
|
|
77
78
|
);
|
|
78
|
-
yield*
|
|
79
|
+
yield* Database.Service.flush({ indexes: true });
|
|
79
80
|
const result = yield* FunctionInvocationService.invokeFunction(entityExtraction, {
|
|
80
81
|
source: email,
|
|
81
82
|
});
|
|
@@ -11,7 +11,8 @@ import * as Schema from 'effect/Schema';
|
|
|
11
11
|
import { AiService } from '@dxos/ai';
|
|
12
12
|
import { AiSession, makeToolExecutionServiceFromFunctions, makeToolResolverFromFunctions } from '@dxos/assistant';
|
|
13
13
|
import { Filter, Obj, Ref } from '@dxos/echo';
|
|
14
|
-
import {
|
|
14
|
+
import { Database } from '@dxos/echo';
|
|
15
|
+
import { defineFunction } from '@dxos/functions';
|
|
15
16
|
import { FunctionInvocationServiceLayerTest } from '@dxos/functions-runtime/testing';
|
|
16
17
|
import { type DXN } from '@dxos/keys';
|
|
17
18
|
import { log } from '@dxos/log';
|
|
@@ -26,10 +27,14 @@ export default defineFunction({
|
|
|
26
27
|
name: 'Entity Extraction',
|
|
27
28
|
description: 'Extracts entities from emails and transcripts.',
|
|
28
29
|
inputSchema: Schema.Struct({
|
|
29
|
-
source: Message.Message.annotations({
|
|
30
|
+
source: Message.Message.annotations({
|
|
31
|
+
description: 'Email or transcript to extract entities from.',
|
|
32
|
+
}),
|
|
30
33
|
|
|
31
34
|
// TODO(dmaretskyi): Consider making this an array of blueprints instead.
|
|
32
|
-
instructions: Schema.optional(Schema.String).annotations({
|
|
35
|
+
instructions: Schema.optional(Schema.String).annotations({
|
|
36
|
+
description: 'Instructions extraction process.',
|
|
37
|
+
}),
|
|
33
38
|
}),
|
|
34
39
|
outputSchema: Schema.Struct({
|
|
35
40
|
entities: Schema.optional(
|
|
@@ -46,7 +51,9 @@ export default defineFunction({
|
|
|
46
51
|
|
|
47
52
|
if (contact && !contact.organization) {
|
|
48
53
|
const created: DXN[] = [];
|
|
49
|
-
const GraphWriterToolkit = makeGraphWriterToolkit({
|
|
54
|
+
const GraphWriterToolkit = makeGraphWriterToolkit({
|
|
55
|
+
schema: [LegacyOrganization],
|
|
56
|
+
}).pipe();
|
|
50
57
|
const GraphWriterHandler = makeGraphWriterHandler(GraphWriterToolkit, {
|
|
51
58
|
onAppend: (dxns) => created.push(...dxns),
|
|
52
59
|
});
|
|
@@ -67,7 +74,7 @@ export default defineFunction({
|
|
|
67
74
|
if (created.length > 1) {
|
|
68
75
|
throw new Error('Multiple organizations created');
|
|
69
76
|
} else if (created.length === 1) {
|
|
70
|
-
organization = yield*
|
|
77
|
+
organization = yield* Database.Service.resolve(created[0], Organization.Organization);
|
|
71
78
|
Obj.getMeta(organization).tags ??= [];
|
|
72
79
|
Obj.getMeta(organization).tags!.push(...(tags ?? []));
|
|
73
80
|
contact.organization = Ref.make(organization);
|
|
@@ -101,12 +108,12 @@ const extractContact = Effect.fn('extractContact')(function* (actor: Actor.Actor
|
|
|
101
108
|
return undefined;
|
|
102
109
|
}
|
|
103
110
|
|
|
104
|
-
const
|
|
111
|
+
const existingContacts = yield* Database.Service.runQuery(Filter.type(Person.Person));
|
|
105
112
|
|
|
106
113
|
// Check for existing contact
|
|
107
114
|
// TODO(dmaretskyi): Query filter DSL - https://linear.app/dxos/issue/DX-541/filtercontains-should-work-with-partial-objects
|
|
108
115
|
const existingContact = existingContacts.find((contact) =>
|
|
109
|
-
contact.emails?.some((contactEmail
|
|
116
|
+
contact.emails?.some((contactEmail) => contactEmail.value === email),
|
|
110
117
|
);
|
|
111
118
|
|
|
112
119
|
if (existingContact) {
|
|
@@ -118,7 +125,7 @@ const extractContact = Effect.fn('extractContact')(function* (actor: Actor.Actor
|
|
|
118
125
|
[Obj.Meta]: { tags },
|
|
119
126
|
emails: [{ value: email }],
|
|
120
127
|
});
|
|
121
|
-
yield*
|
|
128
|
+
yield* Database.Service.add(newContact);
|
|
122
129
|
|
|
123
130
|
if (name) {
|
|
124
131
|
newContact.fullName = name;
|
|
@@ -132,7 +139,7 @@ const extractContact = Effect.fn('extractContact')(function* (actor: Actor.Actor
|
|
|
132
139
|
|
|
133
140
|
log.info('extracted email domain', { emailDomain });
|
|
134
141
|
|
|
135
|
-
const
|
|
142
|
+
const existingOrganisations = yield* Database.Service.runQuery(Filter.type(Organization.Organization));
|
|
136
143
|
const matchingOrg = existingOrganisations.find((org) => {
|
|
137
144
|
if (org.website) {
|
|
138
145
|
try {
|
|
@@ -148,7 +155,10 @@ const extractContact = Effect.fn('extractContact')(function* (actor: Actor.Actor
|
|
|
148
155
|
emailDomain.endsWith(`.${websiteDomain}`)
|
|
149
156
|
);
|
|
150
157
|
} catch (e) {
|
|
151
|
-
log.warn('Error parsing website URL', {
|
|
158
|
+
log.warn('Error parsing website URL', {
|
|
159
|
+
website: org.website,
|
|
160
|
+
error: e,
|
|
161
|
+
});
|
|
152
162
|
return false;
|
|
153
163
|
}
|
|
154
164
|
}
|
|
@@ -13,8 +13,9 @@ import { AiService } from '@dxos/ai';
|
|
|
13
13
|
import { AiServiceTestingPreset } from '@dxos/ai/testing';
|
|
14
14
|
import { makeToolExecutionServiceFromFunctions, makeToolResolverFromFunctions } from '@dxos/assistant';
|
|
15
15
|
import { Obj, Query } from '@dxos/echo';
|
|
16
|
-
import {
|
|
17
|
-
import {
|
|
16
|
+
import { Database } from '@dxos/echo';
|
|
17
|
+
import { TestHelpers } from '@dxos/effect/testing';
|
|
18
|
+
import { CredentialsService, FunctionInvocationService } from '@dxos/functions';
|
|
18
19
|
import { TracingServiceExt } from '@dxos/functions-runtime';
|
|
19
20
|
import {
|
|
20
21
|
FunctionInvocationServiceLayerTestMocked,
|
|
@@ -39,9 +40,9 @@ const TestLayer = Layer.mergeAll(
|
|
|
39
40
|
storagePath: testStoragePath({ name: 'feed-test-13' }),
|
|
40
41
|
}),
|
|
41
42
|
CredentialsService.layerConfig([{ service: 'linear.app', apiKey: Config.redacted('LINEAR_API_KEY') }]),
|
|
42
|
-
FunctionInvocationServiceLayerTestMocked({
|
|
43
|
-
|
|
44
|
-
),
|
|
43
|
+
FunctionInvocationServiceLayerTestMocked({
|
|
44
|
+
functions: [fetchLinearIssues],
|
|
45
|
+
}).pipe(Layer.provideMerge(TracingServiceExt.layerLogInfo())),
|
|
45
46
|
FetchHttpClient.layer,
|
|
46
47
|
),
|
|
47
48
|
),
|
|
@@ -52,29 +53,29 @@ describe('Linear', { timeout: 600_000 }, () => {
|
|
|
52
53
|
'sync',
|
|
53
54
|
Effect.fnUntraced(
|
|
54
55
|
function* (_) {
|
|
55
|
-
yield*
|
|
56
|
+
yield* Database.Service.flush({ indexes: true });
|
|
56
57
|
|
|
57
58
|
yield* FunctionInvocationService.invokeFunction(fetchLinearIssues, {
|
|
58
59
|
team: '1127c63a-6f77-4725-9229-50f6cd47321c',
|
|
59
60
|
});
|
|
60
61
|
|
|
61
|
-
const
|
|
62
|
+
const persons = yield* Database.Service.runQuery(Query.type(Person.Person));
|
|
62
63
|
console.log('people', {
|
|
63
64
|
count: persons.length,
|
|
64
65
|
people: persons.map((_) => `(${_.id}) ${Obj.getLabel(_)} [${Obj.getKeys(_, LINEAR_ID_KEY)[0]?.id}]`),
|
|
65
66
|
});
|
|
66
|
-
const
|
|
67
|
+
const projects = yield* Database.Service.runQuery(Query.type(Project.Project));
|
|
67
68
|
console.log('projects', {
|
|
68
69
|
count: projects.length,
|
|
69
70
|
projects: projects.map((_) => `(${_.id}) ${Obj.getLabel(_)} [${Obj.getKeys(_, LINEAR_ID_KEY)[0]?.id}]`),
|
|
70
71
|
});
|
|
71
|
-
const
|
|
72
|
+
const tasks = yield* Database.Service.runQuery(Query.type(Task.Task));
|
|
72
73
|
console.log('tasks', {
|
|
73
74
|
count: tasks.length,
|
|
74
75
|
tasks: tasks.map((_) => `(${_.id}) ${Obj.getLabel(_)} [${Obj.getKeys(_, LINEAR_ID_KEY)[0]?.id}]`),
|
|
75
76
|
});
|
|
76
77
|
|
|
77
|
-
yield*
|
|
78
|
+
yield* Database.Service.flush({ indexes: true });
|
|
78
79
|
},
|
|
79
80
|
Effect.provide(TestLayer),
|
|
80
81
|
TestHelpers.taggedTest('sync'),
|