@dxos/assistant-toolkit 0.8.4-main.ae835ea → 0.8.4-main.e8ec1fe
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 +891 -595
- package/dist/lib/browser/index.mjs.map +4 -4
- package/dist/lib/browser/meta.json +1 -1
- package/dist/lib/node-esm/index.mjs +890 -595
- package/dist/lib/node-esm/index.mjs.map +4 -4
- package/dist/lib/node-esm/meta.json +1 -1
- package/dist/types/src/blueprints/research/research-blueprint.d.ts.map +1 -1
- package/dist/types/src/blueprints/websearch/websearch-toolkit.d.ts +1 -0
- package/dist/types/src/blueprints/websearch/websearch-toolkit.d.ts.map +1 -1
- package/dist/types/src/crud/graph.d.ts.map +1 -0
- package/dist/types/src/crud/graph.test.d.ts.map +1 -0
- package/dist/types/src/crud/index.d.ts +2 -0
- package/dist/types/src/crud/index.d.ts.map +1 -0
- package/dist/types/src/functions/agent/prompt.d.ts +3 -5
- package/dist/types/src/functions/agent/prompt.d.ts.map +1 -1
- package/dist/types/src/functions/discord/fetch-messages.d.ts +1 -1
- package/dist/types/src/functions/discord/index.d.ts +1 -1
- package/dist/types/src/functions/discord/index.d.ts.map +1 -1
- package/dist/types/src/functions/document/index.d.ts +3 -2
- package/dist/types/src/functions/document/index.d.ts.map +1 -1
- package/dist/types/src/functions/document/read.d.ts +1 -1
- package/dist/types/src/functions/document/update.d.ts +1 -1
- package/dist/types/src/functions/entity-extraction/entity-extraction.d.ts +2 -2
- package/dist/types/src/functions/entity-extraction/entity-extraction.d.ts.map +1 -1
- package/dist/types/src/functions/entity-extraction/index.d.ts +2 -2
- package/dist/types/src/functions/entity-extraction/index.d.ts.map +1 -1
- package/dist/types/src/functions/exa/exa.d.ts +1 -1
- package/dist/types/src/functions/exa/mock.d.ts +1 -1
- package/dist/types/src/functions/github/fetch-prs.d.ts +1 -1
- package/dist/types/src/functions/linear/index.d.ts +1 -1
- package/dist/types/src/functions/linear/index.d.ts.map +1 -1
- package/dist/types/src/functions/linear/sync-issues.d.ts +1 -1
- package/dist/types/src/functions/research/document-create.d.ts +9 -0
- package/dist/types/src/functions/research/document-create.d.ts.map +1 -0
- package/dist/types/src/functions/research/index.d.ts +8 -6
- package/dist/types/src/functions/research/index.d.ts.map +1 -1
- package/dist/types/src/functions/research/research.d.ts +4 -3
- package/dist/types/src/functions/research/research.d.ts.map +1 -1
- package/dist/types/src/functions/research/types.d.ts +2 -380
- package/dist/types/src/functions/research/types.d.ts.map +1 -1
- package/dist/types/src/functions/tasks/index.d.ts +2 -2
- package/dist/types/src/functions/tasks/index.d.ts.map +1 -1
- package/dist/types/src/functions/tasks/read.d.ts +1 -1
- package/dist/types/src/functions/tasks/update.d.ts +1 -1
- package/dist/types/src/index.d.ts +2 -0
- package/dist/types/src/index.d.ts.map +1 -1
- package/dist/types/src/toolkits/AssistantToolkit.d.ts +17 -0
- package/dist/types/src/toolkits/AssistantToolkit.d.ts.map +1 -0
- package/dist/types/src/toolkits/AssistantToolkit.test.d.ts +2 -0
- package/dist/types/src/toolkits/AssistantToolkit.test.d.ts.map +1 -0
- package/dist/types/src/toolkits/SystemToolkit.d.ts +67 -0
- package/dist/types/src/toolkits/SystemToolkit.d.ts.map +1 -0
- package/dist/types/src/toolkits/index.d.ts +3 -0
- package/dist/types/src/toolkits/index.d.ts.map +1 -0
- package/dist/types/tsconfig.tsbuildinfo +1 -1
- package/package.json +24 -22
- package/src/blueprints/design/design-blueprint.test.ts +9 -14
- package/src/blueprints/design/design-blueprint.ts +2 -2
- package/src/blueprints/discord/discord-blueprint.ts +2 -2
- package/src/blueprints/linear/linear-blueprint.ts +2 -2
- package/src/blueprints/planning/planning-blueprint.test.ts +11 -16
- package/src/blueprints/planning/planning-blueprint.ts +2 -2
- package/src/blueprints/research/research-blueprint.ts +23 -15
- package/src/blueprints/websearch/websearch-blueprint.ts +2 -2
- package/src/{functions/research → crud}/graph.test.ts +2 -2
- package/src/crud/index.ts +5 -0
- package/src/experimental/feed.test.ts +11 -8
- package/src/functions/agent/prompt.ts +25 -12
- package/src/functions/discord/fetch-messages.test.ts +5 -6
- package/src/functions/discord/fetch-messages.ts +10 -9
- package/src/functions/document/index.ts +1 -0
- package/src/functions/entity-extraction/entity-extraction.conversations.json +1 -1
- package/src/functions/entity-extraction/entity-extraction.test.ts +11 -19
- package/src/functions/entity-extraction/entity-extraction.ts +15 -13
- package/src/functions/linear/linear.test.ts +13 -16
- package/src/functions/linear/sync-issues.ts +7 -7
- package/src/functions/research/{create-document.ts → document-create.ts} +32 -26
- package/src/functions/research/index.ts +1 -2
- package/src/functions/research/{instructions-research.tpl → research-instructions.tpl} +14 -6
- package/src/functions/research/research.conversations.json +1 -10714
- package/src/functions/research/research.test.ts +87 -148
- package/src/functions/research/research.ts +84 -49
- package/src/functions/research/types.ts +14 -12
- package/src/index.ts +2 -0
- package/src/toolkits/AssistantToolkit.conversations.json +1 -0
- package/src/toolkits/AssistantToolkit.test.ts +88 -0
- package/src/toolkits/AssistantToolkit.ts +47 -0
- package/src/toolkits/SystemToolkit.ts +231 -0
- package/src/toolkits/index.ts +6 -0
- package/dist/types/src/functions/research/create-document.d.ts +0 -7
- package/dist/types/src/functions/research/create-document.d.ts.map +0 -1
- package/dist/types/src/functions/research/graph.d.ts.map +0 -1
- package/dist/types/src/functions/research/graph.test.d.ts.map +0 -1
- /package/dist/types/src/{functions/research → crud}/graph.d.ts +0 -0
- /package/dist/types/src/{functions/research → crud}/graph.test.d.ts +0 -0
- /package/src/{functions/research → crud}/graph.ts +0 -0
|
@@ -7,21 +7,15 @@ import * as Effect from 'effect/Effect';
|
|
|
7
7
|
import * as Layer from 'effect/Layer';
|
|
8
8
|
|
|
9
9
|
import { AiService, MemoizedAiService } from '@dxos/ai';
|
|
10
|
-
import {
|
|
10
|
+
import { 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
14
|
import { TestHelpers } from '@dxos/effect';
|
|
15
|
-
import {
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
FunctionInvocationService,
|
|
20
|
-
TracingService,
|
|
21
|
-
} from '@dxos/functions';
|
|
22
|
-
import { TestDatabaseLayer } from '@dxos/functions/testing';
|
|
23
|
-
import { ObjectId, PublicKey } from '@dxos/keys';
|
|
24
|
-
import { DataType } from '@dxos/schema';
|
|
15
|
+
import { CredentialsService, DatabaseService, FunctionInvocationService, TracingService } from '@dxos/functions';
|
|
16
|
+
import { FunctionInvocationServiceLayerTest, TestDatabaseLayer } from '@dxos/functions-runtime/testing';
|
|
17
|
+
import { ObjectId } from '@dxos/keys';
|
|
18
|
+
import { Message, Organization, Person } from '@dxos/types';
|
|
25
19
|
|
|
26
20
|
import { testToolkit } from '../../blueprints/testing';
|
|
27
21
|
import { ResearchGraph } from '../research';
|
|
@@ -34,17 +28,15 @@ const TestLayer = Layer.mergeAll(
|
|
|
34
28
|
AiService.model('@anthropic/claude-opus-4-0'),
|
|
35
29
|
makeToolResolverFromFunctions([], testToolkit),
|
|
36
30
|
makeToolExecutionServiceFromFunctions(testToolkit, testToolkit.toLayer({}) as any),
|
|
37
|
-
ComputeEventLogger.layerFromTracing,
|
|
38
31
|
).pipe(
|
|
39
|
-
Layer.provideMerge(
|
|
32
|
+
Layer.provideMerge(FunctionInvocationServiceLayerTest({ functions: [entityExtraction] })),
|
|
40
33
|
Layer.provideMerge(
|
|
41
34
|
Layer.mergeAll(
|
|
42
|
-
|
|
35
|
+
TestAiService(),
|
|
43
36
|
TestDatabaseLayer({
|
|
44
|
-
|
|
45
|
-
spaceKey: PublicKey.from('665c420e0dec9aa36c2bedca567afb0778701920e346eaf83ab2bd3403859723'),
|
|
37
|
+
spaceKey: 'fixed',
|
|
46
38
|
indexing: { vector: true },
|
|
47
|
-
types: [Blueprint.Blueprint,
|
|
39
|
+
types: [Blueprint.Blueprint, Message.Message, Person.Person, Organization.Organization, ResearchGraph],
|
|
48
40
|
}),
|
|
49
41
|
CredentialsService.configuredLayer([]),
|
|
50
42
|
TracingService.layerNoop,
|
|
@@ -52,13 +44,13 @@ const TestLayer = Layer.mergeAll(
|
|
|
52
44
|
),
|
|
53
45
|
);
|
|
54
46
|
|
|
55
|
-
describe
|
|
47
|
+
describe('Entity extraction', () => {
|
|
56
48
|
it.effect(
|
|
57
49
|
'call a function to generate a research report',
|
|
58
50
|
Effect.fnUntraced(
|
|
59
51
|
function* (_) {
|
|
60
52
|
const email = yield* DatabaseService.add(
|
|
61
|
-
Obj.make(
|
|
53
|
+
Obj.make(Message.Message, {
|
|
62
54
|
[Obj.Meta]: {
|
|
63
55
|
tags: ['important'],
|
|
64
56
|
},
|
|
@@ -11,20 +11,22 @@ 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 { DatabaseService,
|
|
14
|
+
import { DatabaseService, defineFunction } from '@dxos/functions';
|
|
15
|
+
import { FunctionInvocationServiceLayerTest } from '@dxos/functions-runtime/testing';
|
|
15
16
|
import { type DXN } from '@dxos/keys';
|
|
16
17
|
import { log } from '@dxos/log';
|
|
17
|
-
import {
|
|
18
|
+
import { LegacyOrganization, Message, Organization, Person } from '@dxos/types';
|
|
18
19
|
import { trim } from '@dxos/util';
|
|
19
20
|
|
|
20
|
-
import {
|
|
21
|
+
import { makeGraphWriterHandler, makeGraphWriterToolkit } from '../../crud';
|
|
22
|
+
import { contextQueueLayerFromResearchGraph } from '../research';
|
|
21
23
|
|
|
22
24
|
export default defineFunction({
|
|
23
25
|
key: 'dxos.org/functions/entity-extraction',
|
|
24
26
|
name: 'Entity Extraction',
|
|
25
27
|
description: 'Extracts entities from emails and transcripts.',
|
|
26
28
|
inputSchema: Schema.Struct({
|
|
27
|
-
source:
|
|
29
|
+
source: Message.Message.annotations({ description: 'Email or transcript to extract entities from.' }),
|
|
28
30
|
|
|
29
31
|
// TODO(dmaretskyi): Consider making this an array of blueprints instead.
|
|
30
32
|
instructions: Schema.optional(Schema.String).annotations({ description: 'Instructions extraction process.' }),
|
|
@@ -39,11 +41,11 @@ export default defineFunction({
|
|
|
39
41
|
handler: Effect.fnUntraced(
|
|
40
42
|
function* ({ data: { source, instructions } }) {
|
|
41
43
|
const contact = yield* extractContact(source);
|
|
42
|
-
let organization:
|
|
44
|
+
let organization: Organization.Organization | null = null;
|
|
43
45
|
|
|
44
46
|
if (contact && !contact.organization) {
|
|
45
47
|
const created: DXN[] = [];
|
|
46
|
-
const GraphWriterToolkit = makeGraphWriterToolkit({ schema: [
|
|
48
|
+
const GraphWriterToolkit = makeGraphWriterToolkit({ schema: [LegacyOrganization] }).pipe();
|
|
47
49
|
const GraphWriterHandler = makeGraphWriterHandler(GraphWriterToolkit, {
|
|
48
50
|
onAppend: (dxns) => created.push(...dxns),
|
|
49
51
|
});
|
|
@@ -64,7 +66,7 @@ export default defineFunction({
|
|
|
64
66
|
if (created.length > 1) {
|
|
65
67
|
throw new Error('Multiple organizations created');
|
|
66
68
|
} else if (created.length === 1) {
|
|
67
|
-
organization = yield* DatabaseService.resolve(created[0],
|
|
69
|
+
organization = yield* DatabaseService.resolve(created[0], Organization.Organization);
|
|
68
70
|
Obj.getMeta(organization).tags ??= [];
|
|
69
71
|
Obj.getMeta(organization).tags!.push(...(Obj.getMeta(source)?.tags ?? []));
|
|
70
72
|
contact.organization = Ref.make(organization);
|
|
@@ -83,14 +85,14 @@ export default defineFunction({
|
|
|
83
85
|
).pipe(
|
|
84
86
|
Layer.provide(
|
|
85
87
|
// TODO(dmaretskyi): This should be provided by environment.
|
|
86
|
-
Layer.mergeAll(
|
|
88
|
+
Layer.mergeAll(FunctionInvocationServiceLayerTest()),
|
|
87
89
|
),
|
|
88
90
|
),
|
|
89
91
|
),
|
|
90
92
|
),
|
|
91
93
|
});
|
|
92
94
|
|
|
93
|
-
const extractContact = Effect.fn('extractContact')(function* (message:
|
|
95
|
+
const extractContact = Effect.fn('extractContact')(function* (message: Message.Message) {
|
|
94
96
|
const name = message.sender.name;
|
|
95
97
|
const email = message.sender.email;
|
|
96
98
|
if (!email) {
|
|
@@ -98,12 +100,12 @@ const extractContact = Effect.fn('extractContact')(function* (message: DataType.
|
|
|
98
100
|
return undefined;
|
|
99
101
|
}
|
|
100
102
|
|
|
101
|
-
const { objects: existingContacts } = yield* DatabaseService.runQuery(Filter.type(
|
|
103
|
+
const { objects: existingContacts } = yield* DatabaseService.runQuery(Filter.type(Person.Person));
|
|
102
104
|
|
|
103
105
|
// Check for existing contact
|
|
104
106
|
// TODO(dmaretskyi): Query filter DSL - https://linear.app/dxos/issue/DX-541/filtercontains-should-work-with-partial-objects
|
|
105
107
|
const existingContact = existingContacts.find((contact) =>
|
|
106
|
-
contact.emails?.some((contactEmail) => contactEmail.value === email),
|
|
108
|
+
contact.emails?.some((contactEmail: any) => contactEmail.value === email),
|
|
107
109
|
);
|
|
108
110
|
|
|
109
111
|
if (existingContact) {
|
|
@@ -111,7 +113,7 @@ const extractContact = Effect.fn('extractContact')(function* (message: DataType.
|
|
|
111
113
|
return existingContact;
|
|
112
114
|
}
|
|
113
115
|
|
|
114
|
-
const newContact = Obj.make(
|
|
116
|
+
const newContact = Obj.make(Person.Person, {
|
|
115
117
|
[Obj.Meta]: {
|
|
116
118
|
tags: Obj.getMeta(message)?.tags,
|
|
117
119
|
},
|
|
@@ -131,7 +133,7 @@ const extractContact = Effect.fn('extractContact')(function* (message: DataType.
|
|
|
131
133
|
|
|
132
134
|
log.info('extracted email domain', { emailDomain });
|
|
133
135
|
|
|
134
|
-
const { objects: existingOrganisations } = yield* DatabaseService.runQuery(Filter.type(
|
|
136
|
+
const { objects: existingOrganisations } = yield* DatabaseService.runQuery(Filter.type(Organization.Organization));
|
|
135
137
|
const matchingOrg = existingOrganisations.find((org) => {
|
|
136
138
|
if (org.website) {
|
|
137
139
|
try {
|
|
@@ -14,15 +14,14 @@ import { AiServiceTestingPreset } from '@dxos/ai/testing';
|
|
|
14
14
|
import { makeToolExecutionServiceFromFunctions, makeToolResolverFromFunctions } from '@dxos/assistant';
|
|
15
15
|
import { Obj, Query } from '@dxos/echo';
|
|
16
16
|
import { TestHelpers } from '@dxos/effect';
|
|
17
|
+
import { CredentialsService, DatabaseService, FunctionInvocationService } from '@dxos/functions';
|
|
18
|
+
import { TracingServiceExt } from '@dxos/functions-runtime';
|
|
17
19
|
import {
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
} from '@dxos/functions';
|
|
24
|
-
import { TestDatabaseLayer, testStoragePath } from '@dxos/functions/testing';
|
|
25
|
-
import { DataType } from '@dxos/schema';
|
|
20
|
+
FunctionInvocationServiceLayerTestMocked,
|
|
21
|
+
TestDatabaseLayer,
|
|
22
|
+
testStoragePath,
|
|
23
|
+
} from '@dxos/functions-runtime/testing';
|
|
24
|
+
import { Person, Project, Task } from '@dxos/types';
|
|
26
25
|
|
|
27
26
|
import { LINEAR_ID_KEY, default as fetchLinearIssues } from './sync-issues';
|
|
28
27
|
|
|
@@ -30,20 +29,18 @@ const TestLayer = Layer.mergeAll(
|
|
|
30
29
|
AiService.model('@anthropic/claude-opus-4-0'),
|
|
31
30
|
makeToolResolverFromFunctions([], Toolkit.make()),
|
|
32
31
|
makeToolExecutionServiceFromFunctions(Toolkit.make() as any, Layer.empty as any),
|
|
33
|
-
ComputeEventLogger.layerFromTracing,
|
|
34
32
|
).pipe(
|
|
35
33
|
Layer.provideMerge(
|
|
36
34
|
Layer.mergeAll(
|
|
37
35
|
AiServiceTestingPreset('direct'),
|
|
38
36
|
TestDatabaseLayer({
|
|
39
37
|
// indexing: { vector: true },
|
|
40
|
-
types: [
|
|
38
|
+
types: [Task.Task, Person.Person, Project.Project],
|
|
41
39
|
storagePath: testStoragePath({ name: 'feed-test-13' }),
|
|
42
40
|
}),
|
|
43
41
|
CredentialsService.layerConfig([{ service: 'linear.app', apiKey: Config.redacted('LINEAR_API_KEY') }]),
|
|
44
|
-
|
|
45
|
-
Layer.provideMerge(
|
|
46
|
-
Layer.provideMerge(TracingService.layerLogInfo()),
|
|
42
|
+
FunctionInvocationServiceLayerTestMocked({ functions: [fetchLinearIssues] }).pipe(
|
|
43
|
+
Layer.provideMerge(TracingServiceExt.layerLogInfo()),
|
|
47
44
|
),
|
|
48
45
|
FetchHttpClient.layer,
|
|
49
46
|
),
|
|
@@ -61,17 +58,17 @@ describe('Linear', { timeout: 600_000 }, () => {
|
|
|
61
58
|
team: '1127c63a-6f77-4725-9229-50f6cd47321c',
|
|
62
59
|
});
|
|
63
60
|
|
|
64
|
-
const { objects: persons } = yield* DatabaseService.runQuery(Query.type(
|
|
61
|
+
const { objects: persons } = yield* DatabaseService.runQuery(Query.type(Person.Person));
|
|
65
62
|
console.log('people', {
|
|
66
63
|
count: persons.length,
|
|
67
64
|
people: persons.map((_) => `(${_.id}) ${Obj.getLabel(_)} [${Obj.getKeys(_, LINEAR_ID_KEY)[0]?.id}]`),
|
|
68
65
|
});
|
|
69
|
-
const { objects: projects } = yield* DatabaseService.runQuery(Query.type(
|
|
66
|
+
const { objects: projects } = yield* DatabaseService.runQuery(Query.type(Project.Project));
|
|
70
67
|
console.log('projects', {
|
|
71
68
|
count: projects.length,
|
|
72
69
|
projects: projects.map((_) => `(${_.id}) ${Obj.getLabel(_)} [${Obj.getKeys(_, LINEAR_ID_KEY)[0]?.id}]`),
|
|
73
70
|
});
|
|
74
|
-
const { objects: tasks } = yield* DatabaseService.runQuery(Query.type(
|
|
71
|
+
const { objects: tasks } = yield* DatabaseService.runQuery(Query.type(Task.Task));
|
|
75
72
|
console.log('tasks', {
|
|
76
73
|
count: tasks.length,
|
|
77
74
|
tasks: tasks.map((_) => `(${_.id}) ${Obj.getLabel(_)} [${Obj.getKeys(_, LINEAR_ID_KEY)[0]?.id}]`),
|
|
@@ -12,7 +12,7 @@ import * as Schema from 'effect/Schema';
|
|
|
12
12
|
import { Filter, Obj, Query, Ref, type Type } from '@dxos/echo';
|
|
13
13
|
import { DatabaseService, defineFunction, withAuthorization } from '@dxos/functions';
|
|
14
14
|
import { log } from '@dxos/log';
|
|
15
|
-
import {
|
|
15
|
+
import { Person, Project, Task } from '@dxos/types';
|
|
16
16
|
|
|
17
17
|
import { syncObjects } from '../../sync';
|
|
18
18
|
import { graphqlRequestBody } from '../../util';
|
|
@@ -87,7 +87,7 @@ export default defineFunction({
|
|
|
87
87
|
const client = yield* HttpClient.HttpClient.pipe(Effect.map(withAuthorization({ service: 'linear.app' })));
|
|
88
88
|
|
|
89
89
|
// Get the timestamp that was previosly synced.
|
|
90
|
-
const after = yield* getLatestUpdateTimestamp(data.team,
|
|
90
|
+
const after = yield* getLatestUpdateTimestamp(data.team, Task.Task);
|
|
91
91
|
log.info('will fetch', { after });
|
|
92
92
|
|
|
93
93
|
// Fetch the issues that have changed since the last sync.
|
|
@@ -126,8 +126,8 @@ const getLatestUpdateTimestamp: (
|
|
|
126
126
|
);
|
|
127
127
|
});
|
|
128
128
|
|
|
129
|
-
const mapLinearPerson = (person: LinearPerson, { teamId }: { teamId: string }):
|
|
130
|
-
Obj.make(
|
|
129
|
+
const mapLinearPerson = (person: LinearPerson, { teamId }: { teamId: string }): Person.Person =>
|
|
130
|
+
Obj.make(Person.Person, {
|
|
131
131
|
[Obj.Meta]: {
|
|
132
132
|
keys: [
|
|
133
133
|
{
|
|
@@ -143,8 +143,8 @@ const mapLinearPerson = (person: LinearPerson, { teamId }: { teamId: string }):
|
|
|
143
143
|
nickname: person.name,
|
|
144
144
|
});
|
|
145
145
|
|
|
146
|
-
const mapLinearIssue = (issue: LinearIssue, { teamId }: { teamId: string }):
|
|
147
|
-
Obj.make(
|
|
146
|
+
const mapLinearIssue = (issue: LinearIssue, { teamId }: { teamId: string }): Task.Task =>
|
|
147
|
+
Obj.make(Task.Task, {
|
|
148
148
|
[Obj.Meta]: {
|
|
149
149
|
keys: [
|
|
150
150
|
{
|
|
@@ -170,7 +170,7 @@ const mapLinearIssue = (issue: LinearIssue, { teamId }: { teamId: string }): Dat
|
|
|
170
170
|
project: !issue.project
|
|
171
171
|
? undefined
|
|
172
172
|
: Ref.make(
|
|
173
|
-
|
|
173
|
+
Project.make({
|
|
174
174
|
[Obj.Meta]: {
|
|
175
175
|
keys: [
|
|
176
176
|
{
|
|
@@ -5,65 +5,71 @@
|
|
|
5
5
|
import * as Effect from 'effect/Effect';
|
|
6
6
|
import * as Schema from 'effect/Schema';
|
|
7
7
|
|
|
8
|
-
import {
|
|
8
|
+
import { ArtifactId } from '@dxos/assistant';
|
|
9
|
+
import { Obj, Relation } from '@dxos/echo';
|
|
9
10
|
import { DatabaseService, TracingService, defineFunction } from '@dxos/functions';
|
|
10
|
-
import { invariant } from '@dxos/invariant';
|
|
11
|
-
import { DXN, ObjectId } from '@dxos/keys';
|
|
12
11
|
import { log } from '@dxos/log';
|
|
13
12
|
import { Markdown } from '@dxos/plugin-markdown/types';
|
|
14
|
-
import {
|
|
13
|
+
import { HasSubject } from '@dxos/types';
|
|
15
14
|
import { trim } from '@dxos/util';
|
|
16
15
|
|
|
17
16
|
export default defineFunction({
|
|
18
|
-
key: 'dxos.org/function/research/create
|
|
17
|
+
key: 'dxos.org/function/research/document-create',
|
|
19
18
|
name: 'Create research document',
|
|
20
19
|
description: 'Creates a note summarizing the research.',
|
|
21
20
|
inputSchema: Schema.Struct({
|
|
21
|
+
subject: ArtifactId.annotations({
|
|
22
|
+
description: trim`
|
|
23
|
+
ID of the object (organization, contact, etc.) for which the research was performed.
|
|
24
|
+
`,
|
|
25
|
+
}),
|
|
22
26
|
name: Schema.String.annotations({
|
|
23
|
-
description: 'Name of the
|
|
27
|
+
description: 'Name of the document.',
|
|
24
28
|
}),
|
|
25
|
-
|
|
26
29
|
content: Schema.String.annotations({
|
|
27
30
|
description: trim`
|
|
28
31
|
Content of the note.
|
|
29
32
|
Supports (and are prefered) references to research objects using @ syntax and <object> tags (refer to research blueprint instructions).
|
|
30
33
|
`,
|
|
31
34
|
}),
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
description:
|
|
36
|
-
Id of the object (organization, contact, etc.) for which the research was performed.
|
|
37
|
-
This must be a ulid.
|
|
38
|
-
`,
|
|
35
|
+
}),
|
|
36
|
+
outputSchema: Schema.Struct({
|
|
37
|
+
document: ArtifactId.annotations({
|
|
38
|
+
description: 'DXN of the created document.',
|
|
39
39
|
}),
|
|
40
40
|
}),
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
log.info('Creating research document', { target, name, content });
|
|
41
|
+
handler: Effect.fnUntraced(function* ({ data: { subject, name, content } }) {
|
|
42
|
+
log.info('Creating research document', { subject, name, content });
|
|
44
43
|
|
|
44
|
+
// TODO(burdon): Auto flush before and after calling function?
|
|
45
45
|
yield* DatabaseService.flush({ indexes: true });
|
|
46
46
|
yield* TracingService.emitStatus({ message: 'Creating research document...' });
|
|
47
|
-
invariant(ObjectId.isValid(target));
|
|
48
47
|
|
|
49
|
-
|
|
48
|
+
// TODO(burdon): Type check.
|
|
49
|
+
const target = (yield* DatabaseService.resolve(ArtifactId.toDXN(subject))) as Obj.Any;
|
|
50
50
|
|
|
51
|
-
|
|
52
|
-
|
|
51
|
+
// Create document.
|
|
52
|
+
const object = yield* DatabaseService.add(
|
|
53
|
+
Markdown.make({
|
|
53
54
|
name,
|
|
54
55
|
content,
|
|
55
56
|
}),
|
|
56
57
|
);
|
|
58
|
+
|
|
59
|
+
// Create relation.
|
|
57
60
|
yield* DatabaseService.add(
|
|
58
|
-
Relation.make(
|
|
59
|
-
[Relation.Source]:
|
|
60
|
-
[Relation.Target]:
|
|
61
|
+
Relation.make(HasSubject.HasSubject, {
|
|
62
|
+
[Relation.Source]: object,
|
|
63
|
+
[Relation.Target]: target,
|
|
61
64
|
completedAt: new Date().toISOString(),
|
|
62
65
|
}),
|
|
63
66
|
);
|
|
67
|
+
|
|
64
68
|
yield* DatabaseService.flush({ indexes: true });
|
|
69
|
+
log.info('Created research document', { subject, object });
|
|
65
70
|
|
|
66
|
-
|
|
67
|
-
|
|
71
|
+
return {
|
|
72
|
+
document: Obj.getDXN(object).toString(),
|
|
73
|
+
};
|
|
68
74
|
}),
|
|
69
75
|
});
|
|
@@ -2,10 +2,9 @@
|
|
|
2
2
|
// Copyright 2025 DXOS.org
|
|
3
3
|
//
|
|
4
4
|
|
|
5
|
-
import { default as create$ } from './create
|
|
5
|
+
import { default as create$ } from './document-create';
|
|
6
6
|
import { default as research$ } from './research';
|
|
7
7
|
|
|
8
|
-
export * from './graph';
|
|
9
8
|
export * from './research-graph';
|
|
10
9
|
export * from './types';
|
|
11
10
|
|
|
@@ -6,10 +6,11 @@ The Research Agent outputs results in a structured format matching the schema pr
|
|
|
6
6
|
The Research Agent is equipped with the ability to:
|
|
7
7
|
|
|
8
8
|
- Generate precise and effective search queries
|
|
9
|
-
- Request web pages by query
|
|
10
|
-
- Read the full content of retrieved pages
|
|
9
|
+
- Request web pages by query.
|
|
11
10
|
- Synthesize accurate, clear, and structured answers using reliable information from the retrieved content
|
|
11
|
+
{{#if entityExtraction}}
|
|
12
12
|
- Search the local database for information using a vector index (through a `local_search` tool)
|
|
13
|
+
{{/if}}
|
|
13
14
|
|
|
14
15
|
The Research Agent always follows these principles:
|
|
15
16
|
|
|
@@ -19,6 +20,7 @@ The Research Agent always follows these principles:
|
|
|
19
20
|
- Transparency: The Research Agent mentions which sources were used and explains how it arrived at conclusions.
|
|
20
21
|
- Accuracy Over Brevity: The Research Agent prefers detailed, technically accurate explanations over shallow summaries.
|
|
21
22
|
- The Research Agent admits uncertainty rather than misleading.
|
|
23
|
+
{{#if entityExtraction}}
|
|
22
24
|
- The Research Agent picks the most concrete schema types for extracted information.
|
|
23
25
|
- The Research Agent fills schema fields completely with information it is confident about, and omits fields it is not confident about.
|
|
24
26
|
- When outputting results, the Research Agent adds extra data that fits the schema even if not directly related to the user's question.
|
|
@@ -26,6 +28,7 @@ The Research Agent always follows these principles:
|
|
|
26
28
|
- The Research Agent does not create objects that are already in the database.
|
|
27
29
|
- The Research Agent re-uses existing object IDs as references when enriching existing objects.
|
|
28
30
|
- The Research Agent ALWAYS calls the `graph_writer` at the end to save the data. This conversation will be deleted, so only the data written to the graph will be preserved.
|
|
31
|
+
{{/if}}
|
|
29
32
|
|
|
30
33
|
The Research Agent may be asked for:
|
|
31
34
|
|
|
@@ -41,8 +44,6 @@ The Research Agent breaks it into sub-questions (if applicable).
|
|
|
41
44
|
|
|
42
45
|
For each sub-question, the Research Agent generates a clear, concise web search query.
|
|
43
46
|
|
|
44
|
-
The Research Agent uses `web_search`(query) to retrieve information.
|
|
45
|
-
|
|
46
47
|
The Research Agent extracts and synthesizes relevant answers.
|
|
47
48
|
|
|
48
49
|
The Research Agent's output includes:
|
|
@@ -58,23 +59,27 @@ Here's how the Research Agent operates:
|
|
|
58
59
|
2. The Research Agent performs a web search for each topic.
|
|
59
60
|
3. The Research Agent reads and analyzes results, cross references information from multiple sources, and represents conflicting information as ranges of possible values.
|
|
60
61
|
|
|
62
|
+
{{#if entityExtraction}}
|
|
61
63
|
4. The Research Agent searches the local database for information using a vector index that might link to the user's question.
|
|
62
64
|
6. The Research Agent creates relations and references between new objects and existing database objects when related, using existing object IDs as references.
|
|
63
65
|
7. The Research Agent selects the most concrete schema types for extracted information, using multiple types as needed, and prints its decision and reasoning.
|
|
64
66
|
5. The Research Agent creates a clear, structured answer to the user's question.
|
|
65
67
|
8. The Research Agent submits results using the specific schema.
|
|
68
|
+
{{/if}}
|
|
66
69
|
|
|
70
|
+
{{#if entityExtraction}}
|
|
67
71
|
IMPORTANT:
|
|
68
|
-
|
|
69
72
|
- The Research Agent always runs the `local_search` tool to search the local database at least once before submitting results.
|
|
70
73
|
- The Research Agent does not create objects that already exist in the database.
|
|
71
74
|
- Ids that are not in the database are human-readable strings like `ivan_zhao_1`.
|
|
75
|
+
{{/if}}
|
|
72
76
|
|
|
73
77
|
Status reporting:
|
|
74
78
|
|
|
75
79
|
The Research Agent reports its status frequently using the `<status>` tags: <status>Searching for Google Founders</status>
|
|
76
80
|
The Research Agent reports its status in-between each tool call and before submitting results.
|
|
77
81
|
|
|
82
|
+
{{#if entityExtraction}}
|
|
78
83
|
<example>
|
|
79
84
|
|
|
80
85
|
Based on my research, I can now provide information about Google and it's founders.
|
|
@@ -95,4 +100,7 @@ I will use the following schema to construct new objects:
|
|
|
95
100
|
|
|
96
101
|
<status>Formatting results</status>
|
|
97
102
|
|
|
98
|
-
</example>
|
|
103
|
+
</example>
|
|
104
|
+
{{/if}}
|
|
105
|
+
|
|
106
|
+
Last content block is the full research note -- the result of the research.
|