@dxos/assistant-toolkit 0.8.4-main.ae835ea → 0.8.4-main.bc674ce
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/lib/browser/chunk-J5LGTIGS.mjs +10 -0
- package/dist/lib/browser/chunk-J5LGTIGS.mjs.map +7 -0
- package/dist/lib/browser/index.mjs +1091 -692
- package/dist/lib/browser/index.mjs.map +4 -4
- package/dist/lib/browser/meta.json +1 -1
- package/dist/lib/browser/testing/index.mjs +43 -0
- package/dist/lib/browser/testing/index.mjs.map +7 -0
- package/dist/lib/node-esm/chunk-HSLMI22Q.mjs +11 -0
- package/dist/lib/node-esm/chunk-HSLMI22Q.mjs.map +7 -0
- package/dist/lib/node-esm/index.mjs +1090 -692
- package/dist/lib/node-esm/index.mjs.map +4 -4
- package/dist/lib/node-esm/meta.json +1 -1
- package/dist/lib/node-esm/testing/index.mjs +44 -0
- package/dist/lib/node-esm/testing/index.mjs.map +7 -0
- package/dist/types/src/blueprints/design/design-blueprint.d.ts +17 -3
- package/dist/types/src/blueprints/design/design-blueprint.d.ts.map +1 -1
- package/dist/types/src/blueprints/design/index.d.ts +1 -1
- package/dist/types/src/blueprints/design/index.d.ts.map +1 -1
- package/dist/types/src/blueprints/discord/discord-blueprint.d.ts +13 -13
- package/dist/types/src/blueprints/discord/discord-blueprint.d.ts.map +1 -1
- package/dist/types/src/blueprints/discord/index.d.ts +1 -1
- package/dist/types/src/blueprints/discord/index.d.ts.map +1 -1
- package/dist/types/src/blueprints/linear/index.d.ts +1 -1
- package/dist/types/src/blueprints/linear/index.d.ts.map +1 -1
- package/dist/types/src/blueprints/linear/linear-blueprint.d.ts +13 -13
- package/dist/types/src/blueprints/linear/linear-blueprint.d.ts.map +1 -1
- package/dist/types/src/blueprints/planning/index.d.ts +1 -1
- package/dist/types/src/blueprints/planning/index.d.ts.map +1 -1
- package/dist/types/src/blueprints/planning/planning-blueprint.d.ts +17 -3
- package/dist/types/src/blueprints/planning/planning-blueprint.d.ts.map +1 -1
- package/dist/types/src/blueprints/research/index.d.ts +1 -1
- package/dist/types/src/blueprints/research/index.d.ts.map +1 -1
- package/dist/types/src/blueprints/research/research-blueprint.d.ts +17 -3
- package/dist/types/src/blueprints/research/research-blueprint.d.ts.map +1 -1
- package/dist/types/src/blueprints/testing.d.ts +2 -2
- package/dist/types/src/blueprints/testing.d.ts.map +1 -1
- package/dist/types/src/blueprints/websearch/index.d.ts +1 -1
- package/dist/types/src/blueprints/websearch/index.d.ts.map +1 -1
- package/dist/types/src/blueprints/websearch/websearch-blueprint.d.ts +17 -3
- package/dist/types/src/blueprints/websearch/websearch-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/{functions/research → crud}/graph.d.ts +14 -11
- 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 +73 -8
- 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/read.d.ts.map +1 -1
- package/dist/types/src/functions/document/update.d.ts +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 +126 -125
- package/dist/types/src/functions/entity-extraction/entity-extraction.d.ts.map +1 -1
- package/dist/types/src/functions/entity-extraction/index.d.ts +126 -125
- package/dist/types/src/functions/entity-extraction/index.d.ts.map +1 -1
- package/dist/types/src/functions/exa/data/exa-search-1748337321991.d.ts.map +1 -0
- package/dist/types/src/functions/exa/data/exa-search-1748337331526.d.ts.map +1 -0
- package/dist/types/src/functions/exa/data/exa-search-1748337344119.d.ts.map +1 -0
- package/dist/types/src/functions/exa/data/index.d.ts.map +1 -0
- 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/github/fetch-prs.d.ts.map +1 -1
- package/dist/types/src/functions/linear/index.d.ts +2 -2
- package/dist/types/src/functions/linear/index.d.ts.map +1 -1
- package/dist/types/src/functions/linear/sync-issues.d.ts +2 -2
- package/dist/types/src/functions/linear/sync-issues.d.ts.map +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-graph.d.ts +9 -8
- package/dist/types/src/functions/research/research-graph.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/read.d.ts.map +1 -1
- package/dist/types/src/functions/tasks/update.d.ts +1 -1
- package/dist/types/src/functions/tasks/update.d.ts.map +1 -1
- package/dist/types/src/index.d.ts +2 -1
- package/dist/types/src/index.d.ts.map +1 -1
- package/dist/types/src/initiative/Initiative.d.ts +84 -0
- package/dist/types/src/initiative/Initiative.d.ts.map +1 -0
- package/dist/types/src/initiative/InitiativeSchema.d.ts +19 -0
- package/dist/types/src/initiative/InitiativeSchema.d.ts.map +1 -0
- package/dist/types/src/initiative/functions/agent.d.ts +37 -0
- package/dist/types/src/initiative/functions/agent.d.ts.map +1 -0
- package/dist/types/src/initiative/functions/getContext.d.ts +17 -0
- package/dist/types/src/initiative/functions/getContext.d.ts.map +1 -0
- package/dist/types/src/initiative/functions/index.d.ts +4 -0
- package/dist/types/src/initiative/functions/index.d.ts.map +1 -0
- package/dist/types/src/{functions/research/create-document.d.ts → initiative/functions/update.d.ts} +3 -3
- package/dist/types/src/initiative/functions/update.d.ts.map +1 -0
- package/dist/types/src/initiative/index.d.ts +1 -0
- package/dist/types/src/initiative/index.d.ts.map +1 -0
- package/dist/types/src/initiative/initiative.test.d.ts +2 -0
- package/dist/types/src/initiative/initiative.test.d.ts.map +1 -0
- package/dist/types/src/sync/sync.d.ts +3 -3
- package/dist/types/src/sync/sync.d.ts.map +1 -1
- package/dist/types/src/testing/index.d.ts +1 -1
- package/dist/types/src/testing/index.d.ts.map +1 -1
- package/dist/types/src/testing/plugins.d.ts +19 -0
- package/dist/types/src/testing/plugins.d.ts.map +1 -0
- package/dist/types/src/toolkits/AssistantToolkit.d.ts +43 -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 +99 -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 +49 -33
- package/src/blueprints/design/design-blueprint.test.ts +17 -20
- package/src/blueprints/design/design-blueprint.ts +4 -6
- package/src/blueprints/design/index.ts +1 -1
- package/src/blueprints/discord/discord-blueprint.ts +4 -6
- package/src/blueprints/discord/index.ts +1 -1
- package/src/blueprints/linear/index.ts +1 -1
- package/src/blueprints/linear/linear-blueprint.ts +4 -6
- package/src/blueprints/planning/index.ts +1 -1
- package/src/blueprints/planning/planning-blueprint.test.ts +17 -20
- package/src/blueprints/planning/planning-blueprint.ts +4 -6
- package/src/blueprints/research/index.ts +1 -1
- package/src/blueprints/research/research-blueprint.ts +25 -19
- package/src/blueprints/testing.ts +2 -2
- package/src/blueprints/websearch/index.ts +2 -1
- package/src/blueprints/websearch/websearch-blueprint.ts +4 -6
- package/src/crud/graph.test.ts +46 -0
- package/src/{functions/research → crud}/graph.ts +32 -40
- package/src/crud/index.ts +5 -0
- package/src/experimental/feed.test.ts +12 -9
- package/src/functions/agent/prompt.ts +39 -22
- package/src/functions/discord/fetch-messages.test.ts +6 -7
- package/src/functions/discord/fetch-messages.ts +11 -10
- package/src/functions/document/index.ts +1 -0
- package/src/functions/document/read.ts +4 -3
- package/src/functions/document/update.ts +7 -4
- package/src/functions/entity-extraction/entity-extraction.conversations.json +6597 -1
- package/src/functions/entity-extraction/entity-extraction.test.ts +16 -23
- package/src/functions/entity-extraction/entity-extraction.ts +51 -31
- package/src/functions/exa/mock.ts +1 -1
- package/src/functions/github/fetch-prs.ts +3 -2
- package/src/functions/linear/linear.test.ts +18 -20
- package/src/functions/linear/sync-issues.ts +14 -12
- package/src/functions/research/document-create.ts +76 -0
- package/src/functions/research/index.ts +1 -2
- package/src/functions/research/research-graph.ts +13 -11
- 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 +92 -161
- package/src/functions/research/research.ts +88 -54
- package/src/functions/research/types.ts +14 -12
- package/src/functions/tasks/read.ts +4 -3
- package/src/functions/tasks/update.ts +4 -3
- package/src/index.ts +2 -1
- package/src/initiative/Initiative.ts +99 -0
- package/src/initiative/InitiativeSchema.ts +37 -0
- package/src/initiative/functions/agent.ts +57 -0
- package/src/initiative/functions/getContext.ts +74 -0
- package/src/initiative/functions/index.ts +7 -0
- package/src/initiative/functions/update.ts +63 -0
- package/src/initiative/index.ts +3 -0
- package/src/initiative/initiative.conversations.json +1 -0
- package/src/initiative/initiative.test.ts +485 -0
- package/src/sync/sync.ts +38 -30
- package/src/testing/index.ts +1 -1
- package/src/{plugins.tsx → testing/plugins.tsx} +15 -15
- package/src/toolkits/AssistantToolkit.conversations.json +1 -0
- package/src/toolkits/AssistantToolkit.test.ts +94 -0
- package/src/toolkits/AssistantToolkit.ts +70 -0
- package/src/toolkits/SystemToolkit.ts +299 -0
- package/src/toolkits/index.ts +6 -0
- 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/plugins.d.ts +0 -19
- package/dist/types/src/plugins.d.ts.map +0 -1
- package/dist/types/src/testing/data/exa-search-1748337321991.d.ts.map +0 -1
- package/dist/types/src/testing/data/exa-search-1748337331526.d.ts.map +0 -1
- package/dist/types/src/testing/data/exa-search-1748337344119.d.ts.map +0 -1
- package/dist/types/src/testing/data/index.d.ts.map +0 -1
- package/src/functions/research/create-document.ts +0 -69
- package/src/functions/research/graph.test.ts +0 -69
- /package/dist/types/src/{functions/research → crud}/graph.test.d.ts +0 -0
- /package/dist/types/src/{testing → functions/exa}/data/exa-search-1748337321991.d.ts +0 -0
- /package/dist/types/src/{testing → functions/exa}/data/exa-search-1748337331526.d.ts +0 -0
- /package/dist/types/src/{testing → functions/exa}/data/exa-search-1748337344119.d.ts +0 -0
- /package/dist/types/src/{testing → functions/exa}/data/index.d.ts +0 -0
- /package/src/{testing → functions/exa}/data/exa-search-1748337321991.ts +0 -0
- /package/src/{testing → functions/exa}/data/exa-search-1748337331526.ts +0 -0
- /package/src/{testing → functions/exa}/data/exa-search-1748337344119.ts +0 -0
- /package/src/{testing → functions/exa}/data/index.ts +0 -0
|
@@ -8,8 +8,8 @@ import { describe, it } from '@effect/vitest';
|
|
|
8
8
|
import * as Effect from 'effect/Effect';
|
|
9
9
|
import * as Layer from 'effect/Layer';
|
|
10
10
|
|
|
11
|
-
import { AiService, ConsolePrinter
|
|
12
|
-
import {
|
|
11
|
+
import { AiService, ConsolePrinter } from '@dxos/ai';
|
|
12
|
+
import { MemoizedAiService, TestAiService } from '@dxos/ai/testing';
|
|
13
13
|
import {
|
|
14
14
|
AiConversation,
|
|
15
15
|
type ContextBinding,
|
|
@@ -18,25 +18,21 @@ import {
|
|
|
18
18
|
makeToolResolverFromFunctions,
|
|
19
19
|
} from '@dxos/assistant';
|
|
20
20
|
import { Blueprint } from '@dxos/blueprints';
|
|
21
|
-
import { Obj,
|
|
22
|
-
import {
|
|
23
|
-
import {
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
FunctionInvocationService,
|
|
28
|
-
QueueService,
|
|
29
|
-
TracingService,
|
|
30
|
-
} from '@dxos/functions';
|
|
31
|
-
import { TestDatabaseLayer } from '@dxos/functions/testing';
|
|
21
|
+
import { Database, Filter, Obj, Query, Ref } from '@dxos/echo';
|
|
22
|
+
import { acquireReleaseResource } from '@dxos/effect';
|
|
23
|
+
import { TestHelpers } from '@dxos/effect/testing';
|
|
24
|
+
import { CredentialsService, FunctionInvocationService, QueueService, TracingService } from '@dxos/functions';
|
|
25
|
+
import { FunctionInvocationServiceLayerTest, TestDatabaseLayer } from '@dxos/functions-runtime/testing';
|
|
26
|
+
import { invariant } from '@dxos/invariant';
|
|
32
27
|
import { ObjectId } from '@dxos/keys';
|
|
33
|
-
import {
|
|
28
|
+
import { MarkdownBlueprint } from '@dxos/plugin-markdown/blueprints';
|
|
29
|
+
import { Markdown } from '@dxos/plugin-markdown/types';
|
|
30
|
+
import { HasSubject, type Message, Organization } from '@dxos/types';
|
|
34
31
|
|
|
35
32
|
import { ResearchBlueprint } from '../../blueprints';
|
|
36
33
|
import { testToolkit } from '../../blueprints/testing';
|
|
37
34
|
|
|
38
|
-
import createDocument from './create
|
|
39
|
-
import { createExtractionSchema, getSanitizedSchemaName } from './graph';
|
|
35
|
+
import { default as createDocument } from './document-create';
|
|
40
36
|
import { default as research } from './research';
|
|
41
37
|
import { ResearchGraph, queryResearchGraph } from './research-graph';
|
|
42
38
|
import { ResearchDataTypes } from './types';
|
|
@@ -45,196 +41,131 @@ ObjectId.dangerouslyDisableRandomness();
|
|
|
45
41
|
|
|
46
42
|
const TestLayer = Layer.mergeAll(
|
|
47
43
|
AiService.model('@anthropic/claude-opus-4-0'),
|
|
48
|
-
makeToolResolverFromFunctions([research, createDocument], testToolkit),
|
|
44
|
+
makeToolResolverFromFunctions([research, createDocument, ...MarkdownBlueprint.functions], testToolkit),
|
|
49
45
|
makeToolExecutionServiceFromFunctions(testToolkit, testToolkit.toLayer({}) as any),
|
|
50
|
-
ComputeEventLogger.layerFromTracing,
|
|
51
46
|
).pipe(
|
|
52
|
-
Layer.provideMerge(
|
|
47
|
+
Layer.provideMerge(
|
|
48
|
+
FunctionInvocationServiceLayerTest({
|
|
49
|
+
functions: [research, createDocument, ...MarkdownBlueprint.functions],
|
|
50
|
+
}),
|
|
51
|
+
),
|
|
53
52
|
Layer.provideMerge(
|
|
54
53
|
Layer.mergeAll(
|
|
55
|
-
|
|
54
|
+
TestAiService(),
|
|
56
55
|
TestDatabaseLayer({
|
|
56
|
+
spaceKey: 'fixed',
|
|
57
57
|
indexing: { vector: true },
|
|
58
|
-
types: [...ResearchDataTypes, ResearchGraph, Blueprint.Blueprint],
|
|
58
|
+
types: [...ResearchDataTypes, ResearchGraph, Blueprint.Blueprint, Markdown.Document, HasSubject.HasSubject],
|
|
59
59
|
}),
|
|
60
|
-
CredentialsService.configuredLayer([
|
|
60
|
+
CredentialsService.configuredLayer([]),
|
|
61
61
|
TracingService.layerNoop,
|
|
62
62
|
),
|
|
63
63
|
),
|
|
64
64
|
);
|
|
65
65
|
|
|
66
|
-
|
|
67
|
-
describe.skip('Research', () => {
|
|
66
|
+
describe('Research', () => {
|
|
68
67
|
it.effect(
|
|
69
68
|
'call a function to generate a research report',
|
|
70
69
|
Effect.fnUntraced(
|
|
71
70
|
function* (_) {
|
|
72
|
-
yield*
|
|
73
|
-
Obj.make(
|
|
74
|
-
name: '
|
|
75
|
-
website: 'https://
|
|
71
|
+
yield* Database.Service.add(
|
|
72
|
+
Obj.make(Organization.Organization, {
|
|
73
|
+
name: 'BlueYard',
|
|
74
|
+
website: 'https://blueyard.com',
|
|
76
75
|
}),
|
|
77
76
|
);
|
|
78
|
-
yield*
|
|
79
|
-
|
|
77
|
+
yield* Database.Service.flush({ indexes: true });
|
|
80
78
|
const result = yield* FunctionInvocationService.invokeFunction(research, {
|
|
81
|
-
query: 'Founders and
|
|
82
|
-
mockSearch: false,
|
|
79
|
+
query: 'Founders and portfolio of BlueYard.',
|
|
83
80
|
});
|
|
84
81
|
|
|
85
82
|
console.log(inspect(result, { depth: null, colors: true }));
|
|
86
83
|
console.log(JSON.stringify(result, null, 2));
|
|
87
84
|
|
|
88
|
-
yield*
|
|
85
|
+
yield* Database.Service.flush({ indexes: true });
|
|
89
86
|
const researchGraph = yield* queryResearchGraph();
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
87
|
+
if (researchGraph) {
|
|
88
|
+
const data = yield* Database.Service.load(researchGraph.queue).pipe(
|
|
89
|
+
Effect.flatMap((queue) => Effect.promise(() => queue.queryObjects())),
|
|
90
|
+
);
|
|
91
|
+
console.log(inspect(data, { depth: null, colors: true }));
|
|
92
|
+
}
|
|
94
93
|
},
|
|
95
94
|
Effect.provide(TestLayer),
|
|
96
95
|
TestHelpers.provideTestContext,
|
|
97
96
|
),
|
|
98
|
-
MemoizedAiService.isGenerationEnabled() ? 240_000 :
|
|
97
|
+
MemoizedAiService.isGenerationEnabled() ? 240_000 : 30_000,
|
|
99
98
|
);
|
|
100
99
|
|
|
101
100
|
it.scoped(
|
|
102
|
-
'research
|
|
101
|
+
'create and update research report',
|
|
103
102
|
Effect.fnUntraced(
|
|
104
103
|
function* (_) {
|
|
105
|
-
const
|
|
106
|
-
|
|
104
|
+
const organization = yield* Database.Service.add(
|
|
105
|
+
Obj.make(Organization.Organization, {
|
|
106
|
+
name: 'BlueYard',
|
|
107
|
+
website: 'https://blueyard.com',
|
|
108
|
+
}),
|
|
109
|
+
);
|
|
107
110
|
|
|
108
|
-
const
|
|
109
|
-
yield*
|
|
110
|
-
yield* DatabaseService.flush({ indexes: true });
|
|
111
|
+
const queue = yield* QueueService.createQueue<Message.Message | ContextBinding>();
|
|
112
|
+
const conversation = yield* acquireReleaseResource(() => new AiConversation({ queue }));
|
|
111
113
|
|
|
112
|
-
|
|
113
|
-
yield*
|
|
114
|
+
yield* Database.Service.flush({ indexes: true });
|
|
115
|
+
const researchBlueprint = yield* Database.Service.add(Obj.clone(ResearchBlueprint));
|
|
116
|
+
const markdownBlueprint = yield* Database.Service.add(Obj.clone(MarkdownBlueprint.make()));
|
|
117
|
+
yield* Effect.promise(() =>
|
|
118
|
+
conversation.context.bind({
|
|
119
|
+
blueprints: [Ref.make(researchBlueprint), Ref.make(markdownBlueprint)],
|
|
120
|
+
objects: [Ref.make(organization)],
|
|
121
|
+
}),
|
|
122
|
+
);
|
|
114
123
|
|
|
115
124
|
const observer = GenerationObserver.fromPrinter(new ConsolePrinter());
|
|
125
|
+
|
|
116
126
|
yield* conversation.createRequest({
|
|
117
127
|
observer,
|
|
118
|
-
prompt: `
|
|
128
|
+
prompt: `Create a research summary about ${organization.name}.`,
|
|
119
129
|
});
|
|
130
|
+
{
|
|
131
|
+
const docs = yield* Database.Service.runQuery(
|
|
132
|
+
Query.select(Filter.id(organization.id)).targetOf(HasSubject.HasSubject).source(),
|
|
133
|
+
);
|
|
134
|
+
if (docs.length !== 1) {
|
|
135
|
+
throw new Error(`Expected 1 research document; got ${docs.length}: ${docs.map((_) => _.name)}`);
|
|
136
|
+
}
|
|
137
|
+
|
|
138
|
+
const doc = docs[0];
|
|
139
|
+
invariant(Obj.instanceOf(Markdown.Document, doc));
|
|
140
|
+
console.log({
|
|
141
|
+
name: doc.name,
|
|
142
|
+
content: yield* Database.Service.load(doc.content).pipe(Effect.map((_) => _.content)),
|
|
143
|
+
});
|
|
144
|
+
}
|
|
120
145
|
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
);
|
|
125
|
-
|
|
146
|
+
yield* conversation.createRequest({
|
|
147
|
+
observer,
|
|
148
|
+
prompt: 'Add a section about their portfolio.',
|
|
149
|
+
});
|
|
150
|
+
{
|
|
151
|
+
const docs = yield* Database.Service.runQuery(
|
|
152
|
+
Query.select(Filter.id(organization.id)).targetOf(HasSubject.HasSubject).source(),
|
|
153
|
+
);
|
|
154
|
+
if (docs.length !== 1) {
|
|
155
|
+
throw new Error(`Expected 1 research document; got ${docs.length}: ${docs.map((_) => _.name)}`);
|
|
156
|
+
}
|
|
157
|
+
|
|
158
|
+
const doc = docs[0];
|
|
159
|
+
invariant(Obj.instanceOf(Markdown.Document, doc));
|
|
160
|
+
console.log({
|
|
161
|
+
name: doc.name,
|
|
162
|
+
content: yield* Database.Service.load(doc.content).pipe(Effect.map((_) => _.content)),
|
|
163
|
+
});
|
|
164
|
+
}
|
|
126
165
|
},
|
|
127
166
|
Effect.provide(TestLayer),
|
|
128
167
|
TestHelpers.provideTestContext,
|
|
129
168
|
),
|
|
130
|
-
MemoizedAiService.isGenerationEnabled() ? 240_000 :
|
|
169
|
+
MemoizedAiService.isGenerationEnabled() ? 240_000 : 30_000,
|
|
131
170
|
);
|
|
132
171
|
});
|
|
133
|
-
|
|
134
|
-
describe('misc', () => {
|
|
135
|
-
it('createExtractionSchema', () => {
|
|
136
|
-
const _schema = createExtractionSchema(ResearchDataTypes);
|
|
137
|
-
// log.info('schema', { schema });
|
|
138
|
-
});
|
|
139
|
-
|
|
140
|
-
it('getSanitizedSchemaName', () => {
|
|
141
|
-
const _names = ResearchDataTypes.map(getSanitizedSchemaName);
|
|
142
|
-
// log.info('names', { names }) ;
|
|
143
|
-
});
|
|
144
|
-
|
|
145
|
-
it('getTypeAnnotation', () => {
|
|
146
|
-
for (const schema of ResearchDataTypes) {
|
|
147
|
-
const _dxn = Type.getDXN(schema);
|
|
148
|
-
// log.info('dxn', { schema, dxn });
|
|
149
|
-
}
|
|
150
|
-
});
|
|
151
|
-
|
|
152
|
-
it.skip('sanitizeObjects', () => {
|
|
153
|
-
const _TEST_DATA = {
|
|
154
|
-
objects_dxos_org_type_Project: [
|
|
155
|
-
{
|
|
156
|
-
name: 'Reor',
|
|
157
|
-
description:
|
|
158
|
-
'A private & local AI personal knowledge management app focused on high entropy thinkers. Features include Q&A chat with full context of notes, automatic connection of ideas, semantic search, and local-first architecture with LLMs and vector databases.',
|
|
159
|
-
image: 'https://reorhomepage-2-cwy0zagzg-reor-team.vercel.app/opengraph-image.jpg',
|
|
160
|
-
id: 'reor-project-01',
|
|
161
|
-
},
|
|
162
|
-
{
|
|
163
|
-
name: 'Personal AI',
|
|
164
|
-
description:
|
|
165
|
-
'A platform for creating personal AI models with unlimited memory capabilities. Features include memory stacking, data uploads, and personalized language models that can be trained on individual knowledge bases.',
|
|
166
|
-
image: 'https://cdn.prod.website-files.com/5ff65c460ce39f5ec5681c6a/663d12aab1b425e1ad40d3a6_Memory-min.jpg',
|
|
167
|
-
id: 'personal-ai-project-01',
|
|
168
|
-
},
|
|
169
|
-
{
|
|
170
|
-
name: 'IKI AI',
|
|
171
|
-
description:
|
|
172
|
-
'An AI-native workspace for research, strategy, and creative work. Offers features like AI summarization, content analysis, and team knowledge sharing capabilities.',
|
|
173
|
-
image: 'https://framerusercontent.com/assets/cI6Uo7x4q0W3uxzOt2preXjv6aE.jpg',
|
|
174
|
-
id: 'iki-ai-project-01',
|
|
175
|
-
},
|
|
176
|
-
{
|
|
177
|
-
name: 'Forethink',
|
|
178
|
-
description:
|
|
179
|
-
'A privacy-first, on-device AI system that proactively links current activities to relevant knowledge. Features real-time learning across teams and local data processing.',
|
|
180
|
-
image: 'https://framerusercontent.com/assets/XDhN6tICnlElB134JWcWXOuXc.jpeg',
|
|
181
|
-
id: 'forethink-project-01',
|
|
182
|
-
},
|
|
183
|
-
{
|
|
184
|
-
name: 'Amurex',
|
|
185
|
-
description:
|
|
186
|
-
'An invisible AI companion that handles tasks, remembers important information, and supports workflow. Includes features for meeting automation, email categorization, and cross-platform search.',
|
|
187
|
-
image: 'https://amurex.ai/ogimages/og_amurex.jpg',
|
|
188
|
-
id: 'amurex-project-01',
|
|
189
|
-
},
|
|
190
|
-
],
|
|
191
|
-
objects_dxos_org_type_Organization: [
|
|
192
|
-
{
|
|
193
|
-
name: 'Reor',
|
|
194
|
-
description:
|
|
195
|
-
'A technology company focused on developing local-first AI solutions for personal knowledge management.',
|
|
196
|
-
status: 'active',
|
|
197
|
-
website: 'https://www.reorproject.org',
|
|
198
|
-
id: 'reor-org-01',
|
|
199
|
-
},
|
|
200
|
-
{
|
|
201
|
-
name: 'Personal.ai',
|
|
202
|
-
description: 'A company specializing in personal AI development and memory management solutions.',
|
|
203
|
-
status: 'active',
|
|
204
|
-
website: 'https://www.personal.ai',
|
|
205
|
-
id: 'personal-ai-org-01',
|
|
206
|
-
},
|
|
207
|
-
{
|
|
208
|
-
name: 'IKI AI',
|
|
209
|
-
description: 'A startup backed by 500 Global, developing AI-native workspaces for knowledge workers.',
|
|
210
|
-
status: 'active',
|
|
211
|
-
website: 'https://iki.ai',
|
|
212
|
-
id: 'iki-ai-org-01',
|
|
213
|
-
},
|
|
214
|
-
{
|
|
215
|
-
name: 'Forethink.ai',
|
|
216
|
-
description:
|
|
217
|
-
'A company focused on privacy-first AI solutions for knowledge management and team collaboration.',
|
|
218
|
-
status: 'active',
|
|
219
|
-
website: 'https://www.forethink.ai',
|
|
220
|
-
id: 'forethink-org-01',
|
|
221
|
-
},
|
|
222
|
-
],
|
|
223
|
-
objects_dxos_org_type_Text: [
|
|
224
|
-
{
|
|
225
|
-
content:
|
|
226
|
-
'Current trends in AI-powered Personal Knowledge Management (PKM) systems include: 1) Shift from document-based to graph-based systems for better knowledge connection, 2) Integration of large language models for enhanced content understanding and retrieval, 3) Focus on privacy-first and local-first architectures, 4) Emphasis on automatic knowledge connection and discovery, 5) Implementation of semantic search capabilities.',
|
|
227
|
-
id: 'pkm-trends-text-01',
|
|
228
|
-
},
|
|
229
|
-
{
|
|
230
|
-
content:
|
|
231
|
-
'Key features emerging across modern PKM tools include: automated content categorization, semantic analysis and linking, personalized AI models that learn from user interaction, integration with existing workflows, and robust privacy protection. These tools are increasingly focusing on proactive knowledge surfacing rather than passive storage.',
|
|
232
|
-
id: 'pkm-features-text-01',
|
|
233
|
-
},
|
|
234
|
-
],
|
|
235
|
-
};
|
|
236
|
-
|
|
237
|
-
// const data = await sanitizeObjects(TYPES, TEST_DATA, db);
|
|
238
|
-
// log.info('data', { data });
|
|
239
|
-
});
|
|
240
|
-
});
|
|
@@ -6,8 +6,11 @@ import * as Toolkit from '@effect/ai/Toolkit';
|
|
|
6
6
|
import * as AnthropicTool from '@effect/ai-anthropic/AnthropicTool';
|
|
7
7
|
import * as Array from 'effect/Array';
|
|
8
8
|
import * as Effect from 'effect/Effect';
|
|
9
|
+
import * as Function from 'effect/Function';
|
|
9
10
|
import * as Layer from 'effect/Layer';
|
|
11
|
+
import * as Option from 'effect/Option';
|
|
10
12
|
import * as Schema from 'effect/Schema';
|
|
13
|
+
import * as String from 'effect/String';
|
|
11
14
|
|
|
12
15
|
import { AiService, ConsolePrinter } from '@dxos/ai';
|
|
13
16
|
import {
|
|
@@ -17,17 +20,19 @@ import {
|
|
|
17
20
|
makeToolExecutionServiceFromFunctions,
|
|
18
21
|
makeToolResolverFromFunctions,
|
|
19
22
|
} from '@dxos/assistant';
|
|
20
|
-
import {
|
|
21
|
-
import {
|
|
22
|
-
import {
|
|
23
|
+
import { Template } from '@dxos/blueprints';
|
|
24
|
+
import { type DXN, Entity, Obj } from '@dxos/echo';
|
|
25
|
+
import { Database } from '@dxos/echo';
|
|
26
|
+
import { TracingService, defineFunction } from '@dxos/functions';
|
|
27
|
+
import { FunctionInvocationServiceLayerTestMocked } from '@dxos/functions-runtime/testing';
|
|
28
|
+
import { type Message, Person } from '@dxos/types';
|
|
23
29
|
import { trim } from '@dxos/util';
|
|
24
30
|
|
|
31
|
+
import { LocalSearchHandler, LocalSearchToolkit, makeGraphWriterHandler, makeGraphWriterToolkit } from '../../crud';
|
|
25
32
|
import { exaFunction, exaMockFunction } from '../exa';
|
|
26
33
|
|
|
27
|
-
import { LocalSearchHandler, LocalSearchToolkit, makeGraphWriterHandler, makeGraphWriterToolkit } from './graph';
|
|
28
|
-
// TODO(dmaretskyi): Vite build bug with instruction files with the same filename getting mixed-up.
|
|
29
|
-
import PROMPT from './instructions-research.tpl?raw';
|
|
30
34
|
import { contextQueueLayerFromResearchGraph } from './research-graph';
|
|
35
|
+
import PROMPT from './research-instructions.tpl?raw';
|
|
31
36
|
import { ResearchDataTypes } from './types';
|
|
32
37
|
|
|
33
38
|
/**
|
|
@@ -37,22 +42,21 @@ export default defineFunction({
|
|
|
37
42
|
key: 'dxos.org/function/research',
|
|
38
43
|
name: 'Research',
|
|
39
44
|
description: trim`
|
|
40
|
-
|
|
45
|
+
Search the web to research information about the given subject.
|
|
41
46
|
Inserts structured data into the research graph.
|
|
42
|
-
|
|
47
|
+
Creates a research summary and returns the objects created.
|
|
43
48
|
`,
|
|
44
49
|
inputSchema: Schema.Struct({
|
|
45
50
|
query: Schema.String.annotations({
|
|
46
51
|
description: trim`
|
|
47
|
-
The
|
|
48
|
-
If doing research on an object
|
|
52
|
+
The search query.
|
|
53
|
+
If doing research on an object then load it first and pass it as JSON.
|
|
49
54
|
`,
|
|
50
55
|
}),
|
|
51
56
|
|
|
52
|
-
|
|
57
|
+
instructions: Schema.optional(Schema.String).annotations({
|
|
53
58
|
description: trim`
|
|
54
59
|
The instructions for the research agent.
|
|
55
|
-
E.g., preference on fast responses or in-depth analysis, number of web searcher or the objects created.
|
|
56
60
|
`,
|
|
57
61
|
}),
|
|
58
62
|
|
|
@@ -61,20 +65,28 @@ export default defineFunction({
|
|
|
61
65
|
description: 'Whether to use the mock search tool.',
|
|
62
66
|
default: false,
|
|
63
67
|
}),
|
|
68
|
+
|
|
69
|
+
entityExtraction: Schema.optional(Schema.Boolean).annotations({
|
|
70
|
+
description: trim`
|
|
71
|
+
Whether to extract structured entities from the research.
|
|
72
|
+
Experimental feature only enable if user explicitly requests it.
|
|
73
|
+
`,
|
|
74
|
+
default: false,
|
|
75
|
+
}),
|
|
64
76
|
}),
|
|
65
77
|
outputSchema: Schema.Struct({
|
|
66
|
-
|
|
67
|
-
description: '
|
|
78
|
+
document: Schema.optional(Schema.String).annotations({
|
|
79
|
+
description: 'The generated research document.',
|
|
68
80
|
}),
|
|
69
81
|
objects: Schema.Array(Schema.Unknown).annotations({
|
|
70
|
-
description: '
|
|
82
|
+
description: 'Structured objects created during the research process.',
|
|
71
83
|
}),
|
|
72
84
|
}),
|
|
73
85
|
handler: Effect.fnUntraced(
|
|
74
|
-
function* ({ data: { query, mockSearch,
|
|
86
|
+
function* ({ data: { query, instructions, mockSearch = false, entityExtraction = false } }) {
|
|
75
87
|
if (mockSearch) {
|
|
76
|
-
const mockPerson = yield*
|
|
77
|
-
Obj.make(
|
|
88
|
+
const mockPerson = yield* Database.Service.add(
|
|
89
|
+
Obj.make(Person.Person, {
|
|
78
90
|
preferredName: 'John Doe',
|
|
79
91
|
emails: [{ value: 'john.doe@example.com' }],
|
|
80
92
|
phoneNumbers: [{ value: '123-456-7890' }],
|
|
@@ -82,59 +94,54 @@ export default defineFunction({
|
|
|
82
94
|
);
|
|
83
95
|
|
|
84
96
|
return {
|
|
85
|
-
|
|
86
|
-
The research
|
|
87
|
-
Proceed as usual.
|
|
97
|
+
document: trim`
|
|
98
|
+
The research ran in test-mode and was mocked. Proceed as usual.
|
|
88
99
|
We reference John Doe to test reference: ${Obj.getDXN(mockPerson)}
|
|
89
100
|
`,
|
|
90
101
|
objects: [Obj.toJSON(mockPerson)],
|
|
91
102
|
};
|
|
92
103
|
}
|
|
93
104
|
|
|
94
|
-
yield*
|
|
95
|
-
yield* TracingService.emitStatus({ message: '
|
|
105
|
+
yield* Database.Service.flush({ indexes: true });
|
|
106
|
+
yield* TracingService.emitStatus({ message: 'Starting research...' });
|
|
96
107
|
|
|
97
|
-
const objectDXNs: DXN[] = [];
|
|
98
|
-
const GraphWriterToolkit = makeGraphWriterToolkit({ schema: ResearchDataTypes });
|
|
99
|
-
const GraphWriterHandler = makeGraphWriterHandler(GraphWriterToolkit, {
|
|
100
|
-
onAppend: (dxns) => objectDXNs.push(...dxns),
|
|
101
|
-
});
|
|
102
108
|
const NativeWebSearch = Toolkit.make(AnthropicTool.WebSearch_20250305({}));
|
|
103
109
|
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
)
|
|
115
|
-
|
|
110
|
+
let toolkit: Toolkit.Any = NativeWebSearch;
|
|
111
|
+
let handlers: Layer.Layer<any, any> = Layer.empty as any;
|
|
112
|
+
|
|
113
|
+
const objectDXNs: DXN[] = [];
|
|
114
|
+
if (entityExtraction) {
|
|
115
|
+
const GraphWriterToolkit = makeGraphWriterToolkit({ schema: ResearchDataTypes });
|
|
116
|
+
const GraphWriterHandler = makeGraphWriterHandler(GraphWriterToolkit, {
|
|
117
|
+
onAppend: (dxns) => objectDXNs.push(...dxns),
|
|
118
|
+
});
|
|
119
|
+
|
|
120
|
+
toolkit = Toolkit.merge(toolkit, LocalSearchToolkit, GraphWriterToolkit);
|
|
121
|
+
handlers = Layer.mergeAll(handlers, LocalSearchHandler, GraphWriterHandler).pipe(
|
|
122
|
+
Layer.provide(contextQueueLayerFromResearchGraph),
|
|
123
|
+
) as any;
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
const finishedToolkit = yield* createToolkit({ toolkit }).pipe(Effect.provide(handlers));
|
|
116
127
|
|
|
117
128
|
const session = new AiSession();
|
|
118
129
|
const result = yield* session.run({
|
|
119
130
|
prompt: query,
|
|
120
|
-
system:
|
|
121
|
-
PROMPT
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
toolkit,
|
|
131
|
+
system: join(
|
|
132
|
+
Template.process(PROMPT, { entityExtraction }),
|
|
133
|
+
instructions && `<instructions>${instructions}</instructions>`,
|
|
134
|
+
),
|
|
135
|
+
toolkit: finishedToolkit,
|
|
126
136
|
observer: GenerationObserver.fromPrinter(new ConsolePrinter({ tag: 'research' })),
|
|
127
137
|
});
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
.at(-1)?.text;
|
|
132
|
-
const objects = yield* Effect.forEach(objectDXNs, (dxn) => DatabaseService.resolve(dxn)).pipe(
|
|
133
|
-
Effect.map(Array.map((obj) => Obj.toJSON(obj))),
|
|
138
|
+
|
|
139
|
+
const objects = yield* Effect.forEach(objectDXNs, (dxn) => Database.Service.resolve(dxn)).pipe(
|
|
140
|
+
Effect.map(Array.map((obj) => Entity.toJSON(obj))),
|
|
134
141
|
);
|
|
135
142
|
|
|
136
143
|
return {
|
|
137
|
-
|
|
144
|
+
document: extractLastTextBlock(result),
|
|
138
145
|
objects,
|
|
139
146
|
};
|
|
140
147
|
},
|
|
@@ -147,9 +154,36 @@ export default defineFunction({
|
|
|
147
154
|
).pipe(
|
|
148
155
|
Layer.provide(
|
|
149
156
|
// TODO(dmaretskyi): This should be provided by environment.
|
|
150
|
-
Layer.mergeAll(
|
|
157
|
+
Layer.mergeAll(FunctionInvocationServiceLayerTestMocked({ functions: [exaFunction, exaMockFunction] })),
|
|
151
158
|
),
|
|
152
159
|
),
|
|
153
160
|
),
|
|
154
161
|
),
|
|
155
162
|
});
|
|
163
|
+
|
|
164
|
+
// TODO(burdon): Factor out.
|
|
165
|
+
const join = (...strings: (string | undefined)[]) => strings.filter(Boolean).join('\n\n');
|
|
166
|
+
|
|
167
|
+
/**
|
|
168
|
+
* Extracts the last text block from the result.
|
|
169
|
+
* Skips citations.
|
|
170
|
+
*/
|
|
171
|
+
// TODO(burdon): Factor out.
|
|
172
|
+
const extractLastTextBlock = (result: Message.Message[]) => {
|
|
173
|
+
return Function.pipe(
|
|
174
|
+
result,
|
|
175
|
+
Array.last,
|
|
176
|
+
Option.map(
|
|
177
|
+
Function.flow(
|
|
178
|
+
(_: Message.Message) => _.blocks,
|
|
179
|
+
Array.reverse,
|
|
180
|
+
Array.dropWhile((_: any) => _._tag === 'summary'),
|
|
181
|
+
Array.takeWhile((_: any) => _._tag === 'text'),
|
|
182
|
+
Array.reverse,
|
|
183
|
+
Array.map((_: any) => _.text),
|
|
184
|
+
Array.reduce('', String.concat),
|
|
185
|
+
),
|
|
186
|
+
),
|
|
187
|
+
Option.getOrElse(() => ''),
|
|
188
|
+
);
|
|
189
|
+
};
|
|
@@ -2,23 +2,25 @@
|
|
|
2
2
|
// Copyright 2025 DXOS.org
|
|
3
3
|
//
|
|
4
4
|
|
|
5
|
-
import {
|
|
5
|
+
import { type Type } from '@dxos/echo';
|
|
6
|
+
import { Text } from '@dxos/schema';
|
|
7
|
+
import { Event, HasConnection, HasRelationship, LegacyOrganization, LegacyPerson, Project, Task } from '@dxos/types';
|
|
6
8
|
|
|
7
9
|
/**
|
|
8
10
|
* Data types for research.
|
|
9
11
|
*/
|
|
10
|
-
export const ResearchDataTypes = [
|
|
12
|
+
export const ResearchDataTypes: Type.Entity.Any[] = [
|
|
11
13
|
// Objects
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
DataType.Task,
|
|
17
|
-
DataType.Text,
|
|
14
|
+
Event.Event,
|
|
15
|
+
LegacyOrganization,
|
|
16
|
+
Task.Task,
|
|
17
|
+
Text.Text,
|
|
18
18
|
|
|
19
19
|
// Relations
|
|
20
|
-
// TODO(wittjosiah): Until views (e.g
|
|
21
|
-
//
|
|
22
|
-
|
|
23
|
-
|
|
20
|
+
// TODO(wittjosiah): Until views (e.g., Table) support relations this needs to be expressed via organization ref.
|
|
21
|
+
// Employer.Employer,
|
|
22
|
+
LegacyPerson,
|
|
23
|
+
Project.Project,
|
|
24
|
+
HasRelationship.HasRelationship,
|
|
25
|
+
HasConnection.HasConnection,
|
|
24
26
|
];
|
|
@@ -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,10 +23,10 @@ export default defineFunction({
|
|
|
22
23
|
content: Schema.String,
|
|
23
24
|
}),
|
|
24
25
|
handler: Effect.fn(function* ({ data: { id } }) {
|
|
25
|
-
const doc = yield*
|
|
26
|
+
const doc = yield* Database.Service.resolve(ArtifactId.toDXN(id), Markdown.Document);
|
|
26
27
|
|
|
27
28
|
// Return content with line numbers prefixed.
|
|
28
|
-
const { content } = yield*
|
|
29
|
+
const { content } = yield* Database.Service.load(doc.content);
|
|
29
30
|
const lines = content.split('\n');
|
|
30
31
|
const len = String(lines.length).length;
|
|
31
32
|
const numbered = lines.map((line, i) => `${String(i + 1).padStart(len, ' ')}. ${line}`).join('\n');
|
|
@@ -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
|
import { MarkdownTasks, type TaskOperation } from './task-list';
|
|
@@ -34,10 +35,10 @@ export default defineFunction({
|
|
|
34
35
|
}),
|
|
35
36
|
}),
|
|
36
37
|
handler: Effect.fn(function* ({ data: { id, operations = [] } }) {
|
|
37
|
-
const doc = yield*
|
|
38
|
+
const doc = yield* Database.Service.resolve(ArtifactId.toDXN(id), Markdown.Document);
|
|
38
39
|
|
|
39
40
|
// Create task manager and apply operations if provided.
|
|
40
|
-
const { content } = yield*
|
|
41
|
+
const { content } = yield* Database.Service.load(doc.content);
|
|
41
42
|
const taskManager = new MarkdownTasks(content);
|
|
42
43
|
if (operations.length > 0) {
|
|
43
44
|
taskManager.applyOperations(operations as TaskOperation[]);
|