@dxos/assistant 0.8.4-main.b97322e → 0.8.4-main.bc2380dfbc
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +102 -5
- package/README.md +2 -1
- package/dist/lib/neutral/chunk-J5LGTIGS.mjs +10 -0
- package/dist/lib/neutral/chunk-J5LGTIGS.mjs.map +7 -0
- package/dist/lib/neutral/extraction/index.mjs +204 -0
- package/dist/lib/neutral/extraction/index.mjs.map +7 -0
- package/dist/lib/neutral/index.mjs +1755 -0
- package/dist/lib/neutral/index.mjs.map +7 -0
- package/dist/lib/neutral/meta.json +1 -0
- package/dist/types/src/extraction/extraction-ner-function/index.d.ts +0 -1
- package/dist/types/src/extraction/extraction-ner-function/index.d.ts.map +1 -1
- package/dist/types/src/extraction/extraction-ner-function/named-entity-recognition.d.ts.map +1 -1
- package/dist/types/src/extraction/extraction.d.ts +1066 -273
- package/dist/types/src/extraction/extraction.d.ts.map +1 -1
- package/dist/types/src/extraction/index.d.ts +0 -1
- package/dist/types/src/extraction/index.d.ts.map +1 -1
- package/dist/types/src/extraction/quotes.d.ts +3 -3
- package/dist/types/src/extraction/quotes.d.ts.map +1 -1
- package/dist/types/src/functions/services.d.ts +15 -4
- package/dist/types/src/functions/services.d.ts.map +1 -1
- package/dist/types/src/index.d.ts +2 -5
- package/dist/types/src/index.d.ts.map +1 -1
- package/dist/types/src/request/AiRequest.d.ts +104 -0
- package/dist/types/src/request/AiRequest.d.ts.map +1 -0
- package/dist/types/src/request/artifact-diff.d.ts +27 -0
- package/dist/types/src/request/artifact-diff.d.ts.map +1 -0
- package/dist/types/src/request/format.d.ts +15 -0
- package/dist/types/src/request/format.d.ts.map +1 -0
- package/dist/types/src/request/index.d.ts +4 -0
- package/dist/types/src/request/index.d.ts.map +1 -0
- package/dist/types/src/request/observer.d.ts +23 -0
- package/dist/types/src/request/observer.d.ts.map +1 -0
- package/dist/types/src/{session → request}/version-pin.d.ts +4 -4
- package/dist/types/src/request/version-pin.d.ts.map +1 -0
- package/dist/types/src/session/AiContext.d.ts +154 -0
- package/dist/types/src/session/AiContext.d.ts.map +1 -0
- package/dist/types/src/session/AiContext.test.d.ts +2 -0
- package/dist/types/src/session/AiContext.test.d.ts.map +1 -0
- package/dist/types/src/session/AiSession.d.ts +73 -0
- package/dist/types/src/session/AiSession.d.ts.map +1 -0
- package/dist/types/src/session/index.d.ts +3 -2
- package/dist/types/src/session/index.d.ts.map +1 -1
- package/dist/types/src/session/toolkit.d.ts +16 -0
- package/dist/types/src/session/toolkit.d.ts.map +1 -0
- package/dist/types/src/templates/index.d.ts +1 -1
- package/dist/types/src/templates/system.d.ts +17 -0
- package/dist/types/src/templates/system.d.ts.map +1 -0
- package/dist/types/src/util/artifact.d.ts +27 -0
- package/dist/types/src/util/artifact.d.ts.map +1 -0
- package/dist/types/src/util/diff.d.ts +17 -0
- package/dist/types/src/util/diff.d.ts.map +1 -0
- package/dist/types/src/util/diff.test.d.ts +2 -0
- package/dist/types/src/util/diff.test.d.ts.map +1 -0
- package/dist/types/src/util/error-handling.d.ts +4 -0
- package/dist/types/src/util/error-handling.d.ts.map +1 -0
- package/dist/types/src/util/errors.d.ts +67 -0
- package/dist/types/src/util/errors.d.ts.map +1 -0
- package/dist/types/src/util/execution-graph.d.ts +85 -0
- package/dist/types/src/util/execution-graph.d.ts.map +1 -0
- package/dist/types/src/util/execution-graph.test.d.ts +2 -0
- package/dist/types/src/util/execution-graph.test.d.ts.map +1 -0
- package/dist/types/src/util/index.d.ts +7 -0
- package/dist/types/src/util/index.d.ts.map +1 -0
- package/dist/types/src/util/tracing.d.ts +233 -0
- package/dist/types/src/util/tracing.d.ts.map +1 -0
- package/dist/types/tsconfig.tsbuildinfo +1 -1
- package/package.json +42 -36
- package/src/extraction/extraction-ner-function/index.ts +0 -1
- package/src/extraction/extraction-ner-function/named-entity-recognition.test.ts +12 -6
- package/src/extraction/extraction-ner-function/named-entity-recognition.ts +2 -0
- package/src/extraction/extraction.ts +44 -15
- package/src/extraction/index.ts +0 -1
- package/src/extraction/quotes.test.ts +3 -3
- package/src/extraction/quotes.ts +6 -7
- package/src/functions/services.ts +173 -98
- package/src/index.ts +2 -5
- package/src/request/AiRequest.ts +348 -0
- package/src/request/artifact-diff.ts +41 -0
- package/src/request/format.ts +147 -0
- package/src/request/index.ts +8 -0
- package/src/request/observer.ts +62 -0
- package/src/{session → request}/version-pin.ts +8 -8
- package/src/session/AiContext.test.ts +53 -0
- package/src/session/AiContext.ts +403 -0
- package/src/session/AiSession.ts +324 -0
- package/src/session/index.ts +4 -2
- package/src/session/toolkit.ts +47 -0
- package/src/templates/index.ts +1 -1
- package/src/templates/instructions/format.tpl +57 -0
- package/src/templates/instructions/system.tpl +96 -0
- package/src/templates/system.ts +42 -0
- package/src/typings.d.ts +5 -0
- package/src/util/artifact.ts +88 -0
- package/src/util/diff.test.ts +74 -0
- package/src/util/diff.ts +93 -0
- package/src/util/error-handling.ts +42 -0
- package/src/util/errors.ts +15 -0
- package/src/util/execution-graph.test.ts +740 -0
- package/src/util/execution-graph.ts +519 -0
- package/src/util/index.ts +10 -0
- package/src/util/tracing.ts +57 -0
- package/dist/lib/browser/index.mjs +0 -1831
- package/dist/lib/browser/index.mjs.map +0 -7
- package/dist/lib/browser/meta.json +0 -1
- package/dist/lib/node-esm/index.mjs +0 -1833
- package/dist/lib/node-esm/index.mjs.map +0 -7
- package/dist/lib/node-esm/meta.json +0 -1
- package/dist/types/bin/chat.d.ts +0 -2
- package/dist/types/bin/chat.d.ts.map +0 -1
- package/dist/types/src/context/binder.d.ts +0 -34
- package/dist/types/src/context/binder.d.ts.map +0 -1
- package/dist/types/src/context/binding.d.ts +0 -56
- package/dist/types/src/context/binding.d.ts.map +0 -1
- package/dist/types/src/context/index.d.ts +0 -3
- package/dist/types/src/context/index.d.ts.map +0 -1
- package/dist/types/src/conversation/conversation.d.ts +0 -38
- package/dist/types/src/conversation/conversation.d.ts.map +0 -1
- package/dist/types/src/conversation/index.d.ts +0 -2
- package/dist/types/src/conversation/index.d.ts.map +0 -1
- package/dist/types/src/errors.d.ts +0 -38
- package/dist/types/src/errors.d.ts.map +0 -1
- package/dist/types/src/extraction/extraction-llm-function/extraction-llm-function.d.ts +0 -4
- package/dist/types/src/extraction/extraction-llm-function/extraction-llm-function.d.ts.map +0 -1
- package/dist/types/src/extraction/extraction-llm-function/extraction-llm-function.test.d.ts +0 -2
- package/dist/types/src/extraction/extraction-llm-function/extraction-llm-function.test.d.ts.map +0 -1
- package/dist/types/src/extraction/extraction-llm-function/index.d.ts +0 -2
- package/dist/types/src/extraction/extraction-llm-function/index.d.ts.map +0 -1
- package/dist/types/src/extraction/extraction-ner-function/extraction-ner-function.d.ts +0 -302
- package/dist/types/src/extraction/extraction-ner-function/extraction-ner-function.d.ts.map +0 -1
- package/dist/types/src/extraction/extraction-ner-function/extraction-ner-function.test.d.ts +0 -2
- package/dist/types/src/extraction/extraction-ner-function/extraction-ner-function.test.d.ts.map +0 -1
- package/dist/types/src/research/exa.d.ts +0 -12
- package/dist/types/src/research/exa.d.ts.map +0 -1
- package/dist/types/src/research/graph.d.ts +0 -51
- package/dist/types/src/research/graph.d.ts.map +0 -1
- package/dist/types/src/research/graph.test.d.ts +0 -2
- package/dist/types/src/research/graph.test.d.ts.map +0 -1
- package/dist/types/src/research/index.d.ts +0 -4
- package/dist/types/src/research/index.d.ts.map +0 -1
- package/dist/types/src/research/research.d.ts +0 -10
- package/dist/types/src/research/research.d.ts.map +0 -1
- package/dist/types/src/research/research.test.d.ts +0 -2
- package/dist/types/src/research/research.test.d.ts.map +0 -1
- package/dist/types/src/session/session.d.ts +0 -260
- package/dist/types/src/session/session.d.ts.map +0 -1
- package/dist/types/src/session/session.test.d.ts +0 -2
- package/dist/types/src/session/session.test.d.ts.map +0 -1
- package/dist/types/src/session/version-pin.d.ts.map +0 -1
- package/dist/types/src/session/version-pin.test.d.ts +0 -2
- package/dist/types/src/session/version-pin.test.d.ts.map +0 -1
- package/dist/types/src/summarization/summarization.test.d.ts +0 -2
- package/dist/types/src/summarization/summarization.test.d.ts.map +0 -1
- package/dist/types/src/templates/prompt.d.ts +0 -30
- package/dist/types/src/templates/prompt.d.ts.map +0 -1
- package/dist/types/src/testing/exa-search-1748337321991.d.ts +0 -38
- package/dist/types/src/testing/exa-search-1748337321991.d.ts.map +0 -1
- package/dist/types/src/testing/exa-search-1748337331526.d.ts +0 -37
- package/dist/types/src/testing/exa-search-1748337331526.d.ts.map +0 -1
- package/dist/types/src/testing/exa-search-1748337344119.d.ts +0 -58
- package/dist/types/src/testing/exa-search-1748337344119.d.ts.map +0 -1
- package/dist/types/src/testing/index.d.ts +0 -3
- package/dist/types/src/testing/index.d.ts.map +0 -1
- package/dist/types/src/types.d.ts +0 -13
- package/dist/types/src/types.d.ts.map +0 -1
- package/src/context/binder.ts +0 -103
- package/src/context/binding.ts +0 -32
- package/src/context/index.ts +0 -6
- package/src/conversation/conversation.ts +0 -96
- package/src/conversation/index.ts +0 -5
- package/src/errors.ts +0 -10
- package/src/extraction/extraction-llm-function/extraction-llm-function.test.ts +0 -83
- package/src/extraction/extraction-llm-function/extraction-llm-function.ts +0 -70
- package/src/extraction/extraction-llm-function/index.ts +0 -5
- package/src/extraction/extraction-ner-function/extraction-ner-function.test.ts +0 -115
- package/src/extraction/extraction-ner-function/extraction-ner-function.ts +0 -57
- package/src/research/exa.ts +0 -97
- package/src/research/graph.test.ts +0 -64
- package/src/research/graph.ts +0 -369
- package/src/research/index.ts +0 -7
- package/src/research/instructions-research.tpl +0 -98
- package/src/research/research.test.ts +0 -190
- package/src/research/research.ts +0 -87
- package/src/session/__snapshots__/session.test.ts.snap +0 -32
- package/src/session/session.test.ts +0 -310
- package/src/session/session.ts +0 -336
- package/src/session/version-pin.test.ts +0 -7
- package/src/summarization/summarization.test.ts +0 -208
- package/src/templates/assistant.tpl +0 -111
- package/src/templates/prompt.ts +0 -45
- package/src/testing/exa-search-1748337321991.ts +0 -131
- package/src/testing/exa-search-1748337331526.ts +0 -144
- package/src/testing/exa-search-1748337344119.ts +0 -133
- package/src/testing/index.ts +0 -11
- package/src/typedefs.d.ts +0 -8
- package/src/types.ts +0 -47
- /package/src/extraction/extraction-llm-function/{instructions.tpl → transcription-instructions.tpl} +0 -0
|
@@ -1,190 +0,0 @@
|
|
|
1
|
-
//
|
|
2
|
-
// Copyright 2025 DXOS.org
|
|
3
|
-
//
|
|
4
|
-
|
|
5
|
-
import { AnthropicClient } from '@effect/ai-anthropic';
|
|
6
|
-
import { FetchHttpClient } from '@effect/platform';
|
|
7
|
-
import { Config, Layer, ManagedRuntime } from 'effect';
|
|
8
|
-
import { inspect } from 'node:util';
|
|
9
|
-
import { afterAll, beforeAll, describe, test } from 'vitest';
|
|
10
|
-
|
|
11
|
-
import { AiService, AiServiceRouter, structuredOutputParser } from '@dxos/ai';
|
|
12
|
-
import { EXA_API_KEY, tapHttpErrors } from '@dxos/ai/testing';
|
|
13
|
-
import { Obj } from '@dxos/echo';
|
|
14
|
-
import { type EchoDatabase } from '@dxos/echo-db';
|
|
15
|
-
import { EchoTestBuilder } from '@dxos/echo-db/testing';
|
|
16
|
-
import { getSchemaDXN } from '@dxos/echo-schema';
|
|
17
|
-
import { ConfiguredCredentialsService, FunctionExecutor, ServiceContainer, TracingService } from '@dxos/functions';
|
|
18
|
-
import { DataType, DataTypes } from '@dxos/schema';
|
|
19
|
-
|
|
20
|
-
import { createExtractionSchema, getSanitizedSchemaName } from './graph';
|
|
21
|
-
import { researchFn } from './research';
|
|
22
|
-
|
|
23
|
-
const MOCK_SEARCH = false;
|
|
24
|
-
|
|
25
|
-
const AnthropicLayer = AnthropicClient.layerConfig({
|
|
26
|
-
apiKey: Config.redacted('ANTHROPIC_API_KEY'),
|
|
27
|
-
transformClient: tapHttpErrors,
|
|
28
|
-
});
|
|
29
|
-
|
|
30
|
-
const AiServiceLayer = AiServiceRouter.AiServiceRouter.pipe(
|
|
31
|
-
Layer.provide(AnthropicLayer),
|
|
32
|
-
Layer.provide(FetchHttpClient.layer),
|
|
33
|
-
);
|
|
34
|
-
|
|
35
|
-
describe.skip('Research', () => {
|
|
36
|
-
let runtime: ManagedRuntime.ManagedRuntime<AiService, any>;
|
|
37
|
-
let builder: EchoTestBuilder;
|
|
38
|
-
let db: EchoDatabase;
|
|
39
|
-
let executor: FunctionExecutor;
|
|
40
|
-
|
|
41
|
-
beforeAll(async () => {
|
|
42
|
-
runtime = ManagedRuntime.make(AiServiceLayer);
|
|
43
|
-
|
|
44
|
-
// TODO(dmaretskyi): Helper to scaffold this from a config.
|
|
45
|
-
builder = await new EchoTestBuilder().open();
|
|
46
|
-
|
|
47
|
-
db = (await builder.createDatabase({ indexing: { vector: true } })).db;
|
|
48
|
-
|
|
49
|
-
executor = new FunctionExecutor(
|
|
50
|
-
new ServiceContainer().setServices({
|
|
51
|
-
ai: await runtime.runPromise(AiService),
|
|
52
|
-
credentials: new ConfiguredCredentialsService([{ service: 'exa.ai', apiKey: EXA_API_KEY }]),
|
|
53
|
-
database: { db },
|
|
54
|
-
tracing: TracingService.console,
|
|
55
|
-
}),
|
|
56
|
-
);
|
|
57
|
-
});
|
|
58
|
-
|
|
59
|
-
afterAll(async () => {
|
|
60
|
-
await runtime.dispose();
|
|
61
|
-
});
|
|
62
|
-
|
|
63
|
-
// TODO(dmaretskyi): Refactor using effect.
|
|
64
|
-
test.only('should generate a research report', { timeout: 300_000 }, async () => {
|
|
65
|
-
db.add(Obj.make(DataType.Organization, { name: 'Notion', website: 'https://www.notion.com' }));
|
|
66
|
-
await db.flush({ indexes: true });
|
|
67
|
-
|
|
68
|
-
const result = await executor.invoke(researchFn, {
|
|
69
|
-
query: 'Who are the founders of Notion?',
|
|
70
|
-
mockSearch: MOCK_SEARCH,
|
|
71
|
-
});
|
|
72
|
-
|
|
73
|
-
console.log(inspect(result, { depth: null, colors: true }));
|
|
74
|
-
console.log(JSON.stringify(result, null, 2));
|
|
75
|
-
});
|
|
76
|
-
});
|
|
77
|
-
|
|
78
|
-
describe('misc', () => {
|
|
79
|
-
test('createExtractionSchema', () => {
|
|
80
|
-
const _schema = createExtractionSchema(DataTypes);
|
|
81
|
-
// log.info('schema', { schema });
|
|
82
|
-
});
|
|
83
|
-
|
|
84
|
-
test('extract schema json schema', () => {
|
|
85
|
-
const schema = createExtractionSchema(DataTypes);
|
|
86
|
-
const _parser = structuredOutputParser(schema);
|
|
87
|
-
// log.info('schema', { json: parser.tool.parameters });
|
|
88
|
-
});
|
|
89
|
-
|
|
90
|
-
test('getSanitizedSchemaName', () => {
|
|
91
|
-
const _names = DataTypes.map(getSanitizedSchemaName);
|
|
92
|
-
// log.info('names', { names });
|
|
93
|
-
});
|
|
94
|
-
|
|
95
|
-
test('getTypeAnnotation', () => {
|
|
96
|
-
for (const schema of DataTypes) {
|
|
97
|
-
const _dxn = getSchemaDXN(schema);
|
|
98
|
-
// log.info('dxn', { schema, dxn });
|
|
99
|
-
}
|
|
100
|
-
});
|
|
101
|
-
|
|
102
|
-
test.skip('sanitizeObjects', () => {
|
|
103
|
-
const _TEST_DATA = {
|
|
104
|
-
objects_dxos_org_type_Project: [
|
|
105
|
-
{
|
|
106
|
-
name: 'Reor',
|
|
107
|
-
description:
|
|
108
|
-
'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.',
|
|
109
|
-
image: 'https://reorhomepage-2-cwy0zagzg-reor-team.vercel.app/opengraph-image.jpg',
|
|
110
|
-
id: 'reor-project-01',
|
|
111
|
-
},
|
|
112
|
-
{
|
|
113
|
-
name: 'Personal AI',
|
|
114
|
-
description:
|
|
115
|
-
'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.',
|
|
116
|
-
image: 'https://cdn.prod.website-files.com/5ff65c460ce39f5ec5681c6a/663d12aab1b425e1ad40d3a6_Memory-min.jpg',
|
|
117
|
-
id: 'personal-ai-project-01',
|
|
118
|
-
},
|
|
119
|
-
{
|
|
120
|
-
name: 'IKI AI',
|
|
121
|
-
description:
|
|
122
|
-
'An AI-native workspace for research, strategy, and creative work. Offers features like AI summarization, content analysis, and team knowledge sharing capabilities.',
|
|
123
|
-
image: 'https://framerusercontent.com/assets/cI6Uo7x4q0W3uxzOt2preXjv6aE.jpg',
|
|
124
|
-
id: 'iki-ai-project-01',
|
|
125
|
-
},
|
|
126
|
-
{
|
|
127
|
-
name: 'Forethink',
|
|
128
|
-
description:
|
|
129
|
-
'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.',
|
|
130
|
-
image: 'https://framerusercontent.com/assets/XDhN6tICnlElB134JWcWXOuXc.jpeg',
|
|
131
|
-
id: 'forethink-project-01',
|
|
132
|
-
},
|
|
133
|
-
{
|
|
134
|
-
name: 'Amurex',
|
|
135
|
-
description:
|
|
136
|
-
'An invisible AI companion that handles tasks, remembers important information, and supports workflow. Includes features for meeting automation, email categorization, and cross-platform search.',
|
|
137
|
-
image: 'https://amurex.ai/ogimages/og_amurex.jpg',
|
|
138
|
-
id: 'amurex-project-01',
|
|
139
|
-
},
|
|
140
|
-
],
|
|
141
|
-
objects_dxos_org_type_Organization: [
|
|
142
|
-
{
|
|
143
|
-
name: 'Reor',
|
|
144
|
-
description:
|
|
145
|
-
'A technology company focused on developing local-first AI solutions for personal knowledge management.',
|
|
146
|
-
status: 'active',
|
|
147
|
-
website: 'https://www.reorproject.org',
|
|
148
|
-
id: 'reor-org-01',
|
|
149
|
-
},
|
|
150
|
-
{
|
|
151
|
-
name: 'Personal.ai',
|
|
152
|
-
description: 'A company specializing in personal AI development and memory management solutions.',
|
|
153
|
-
status: 'active',
|
|
154
|
-
website: 'https://www.personal.ai',
|
|
155
|
-
id: 'personal-ai-org-01',
|
|
156
|
-
},
|
|
157
|
-
{
|
|
158
|
-
name: 'IKI AI',
|
|
159
|
-
description: 'A startup backed by 500 Global, developing AI-native workspaces for knowledge workers.',
|
|
160
|
-
status: 'active',
|
|
161
|
-
website: 'https://iki.ai',
|
|
162
|
-
id: 'iki-ai-org-01',
|
|
163
|
-
},
|
|
164
|
-
{
|
|
165
|
-
name: 'Forethink.ai',
|
|
166
|
-
description:
|
|
167
|
-
'A company focused on privacy-first AI solutions for knowledge management and team collaboration.',
|
|
168
|
-
status: 'active',
|
|
169
|
-
website: 'https://www.forethink.ai',
|
|
170
|
-
id: 'forethink-org-01',
|
|
171
|
-
},
|
|
172
|
-
],
|
|
173
|
-
objects_dxos_org_type_Text: [
|
|
174
|
-
{
|
|
175
|
-
content:
|
|
176
|
-
'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.',
|
|
177
|
-
id: 'pkm-trends-text-01',
|
|
178
|
-
},
|
|
179
|
-
{
|
|
180
|
-
content:
|
|
181
|
-
'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.',
|
|
182
|
-
id: 'pkm-features-text-01',
|
|
183
|
-
},
|
|
184
|
-
],
|
|
185
|
-
};
|
|
186
|
-
|
|
187
|
-
// const data = await sanitizeObjects(TYPES, TEST_DATA, db);
|
|
188
|
-
// log.info('data', { data });
|
|
189
|
-
});
|
|
190
|
-
});
|
package/src/research/research.ts
DELETED
|
@@ -1,87 +0,0 @@
|
|
|
1
|
-
//
|
|
2
|
-
// Copyright 2025 DXOS.org
|
|
3
|
-
//
|
|
4
|
-
|
|
5
|
-
// TODO(burdon): Fix.
|
|
6
|
-
// @ts-nocheck
|
|
7
|
-
|
|
8
|
-
import { AiToolkit } from '@effect/ai';
|
|
9
|
-
import { Effect, Layer, Schema } from 'effect';
|
|
10
|
-
|
|
11
|
-
import { AiService, ConsolePrinter } from '@dxos/ai';
|
|
12
|
-
import { defineFunction, TracingService } from '@dxos/functions';
|
|
13
|
-
import { log } from '@dxos/log';
|
|
14
|
-
import { DataTypes } from '@dxos/schema';
|
|
15
|
-
|
|
16
|
-
import { ExaToolkit, LiveExaHandler, MockExaHandler } from './exa';
|
|
17
|
-
import { LocalSearchHandler, LocalSearchToolkit, makeGraphWriterHandler, makeGraphWriterToolkit } from './graph';
|
|
18
|
-
// TODO(dmaretskyi): Vite build bug with instruction files with the same filename getting mixed-up
|
|
19
|
-
import PROMPT from './instructions-research.tpl?raw';
|
|
20
|
-
import { AiSession } from '../session';
|
|
21
|
-
|
|
22
|
-
/**
|
|
23
|
-
* Exec external service and return the results as a Subgraph.
|
|
24
|
-
*/
|
|
25
|
-
// TODO(burdon): Rename.
|
|
26
|
-
export const researchFn = defineFunction({
|
|
27
|
-
description: 'Research the web for information',
|
|
28
|
-
inputSchema: Schema.Struct({
|
|
29
|
-
query: Schema.String.annotations({
|
|
30
|
-
description: 'The query to search for.',
|
|
31
|
-
}),
|
|
32
|
-
|
|
33
|
-
// TOOD(burdon): Move to context.
|
|
34
|
-
mockSearch: Schema.optional(Schema.Boolean).annotations({
|
|
35
|
-
description: 'Whether to use the mock search tool.',
|
|
36
|
-
default: false,
|
|
37
|
-
}),
|
|
38
|
-
}),
|
|
39
|
-
outputSchema: Schema.Struct({
|
|
40
|
-
result: Schema.Unknown,
|
|
41
|
-
}),
|
|
42
|
-
handler: Effect.fnUntraced(
|
|
43
|
-
function* ({ data: { query, mockSearch } }) {
|
|
44
|
-
yield* TracingService.emitStatus({ message: 'Researching...' });
|
|
45
|
-
|
|
46
|
-
const graphWriteToolkit = makeGraphWriterToolkit({ schema: DataTypes });
|
|
47
|
-
const toolkit = yield* AiToolkit.merge(ExaToolkit, LocalSearchToolkit, graphWriteToolkit).pipe(
|
|
48
|
-
Effect.provide(
|
|
49
|
-
Layer.mergeAll(
|
|
50
|
-
mockSearch ? MockExaHandler : LiveExaHandler,
|
|
51
|
-
LocalSearchHandler,
|
|
52
|
-
makeGraphWriterHandler(graphWriteToolkit),
|
|
53
|
-
),
|
|
54
|
-
),
|
|
55
|
-
);
|
|
56
|
-
|
|
57
|
-
const printer = new ConsolePrinter();
|
|
58
|
-
const session = new AiSession();
|
|
59
|
-
session.message.on((message) => printer.printMessage(message));
|
|
60
|
-
session.userMessage.on((message) => printer.printMessage(message));
|
|
61
|
-
session.block.on((block) => printer.printContentBlock(block));
|
|
62
|
-
session.streamEvent.on((event) => log('stream', { event }));
|
|
63
|
-
|
|
64
|
-
// TODO(dmaretskyi): Consider adding this pattern as the "Graph" output mode for the session.
|
|
65
|
-
const result = yield* session.run({
|
|
66
|
-
prompt: query,
|
|
67
|
-
history: [],
|
|
68
|
-
systemPrompt: PROMPT,
|
|
69
|
-
toolkit,
|
|
70
|
-
});
|
|
71
|
-
|
|
72
|
-
return {
|
|
73
|
-
result,
|
|
74
|
-
};
|
|
75
|
-
|
|
76
|
-
// queues.contextQueue!.append(data);
|
|
77
|
-
|
|
78
|
-
// return {
|
|
79
|
-
// result: `
|
|
80
|
-
// The research results are placed in the following objects:
|
|
81
|
-
// ${data.map((object, id) => `[obj_${id}][dxn:echo:@:${object.id}]`).join('\n')}
|
|
82
|
-
// `,
|
|
83
|
-
// };
|
|
84
|
-
},
|
|
85
|
-
Effect.provide(AiService.model('@anthropic/claude-3-5-sonnet-20241022')),
|
|
86
|
-
),
|
|
87
|
-
});
|
|
@@ -1,32 +0,0 @@
|
|
|
1
|
-
// Vitest Snapshot v1, https://vitest.dev/guide/snapshot.html
|
|
2
|
-
|
|
3
|
-
exports[`AiSession > no tools 1`] = `
|
|
4
|
-
[
|
|
5
|
-
{
|
|
6
|
-
"blocks": ReactiveArray [
|
|
7
|
-
{
|
|
8
|
-
"_tag": "text",
|
|
9
|
-
"text": "Hello world!",
|
|
10
|
-
},
|
|
11
|
-
],
|
|
12
|
-
"created": "Sun, 20 Jul 2025 10:54:08 GMT",
|
|
13
|
-
"id": "01K0KQGFTFV3GBKGEWZW67K8HK",
|
|
14
|
-
"sender": {
|
|
15
|
-
"role": "user",
|
|
16
|
-
},
|
|
17
|
-
},
|
|
18
|
-
{
|
|
19
|
-
"blocks": ReactiveArray [
|
|
20
|
-
{
|
|
21
|
-
"_tag": "text",
|
|
22
|
-
"text": "Hi there! How can I help you today?",
|
|
23
|
-
},
|
|
24
|
-
],
|
|
25
|
-
"created": "2025-07-20T10:54:10.801Z",
|
|
26
|
-
"id": "01K0KQGHVHJ37D4YG45WG090WV",
|
|
27
|
-
"sender": {
|
|
28
|
-
"role": "assistant",
|
|
29
|
-
},
|
|
30
|
-
},
|
|
31
|
-
]
|
|
32
|
-
`;
|
|
@@ -1,310 +0,0 @@
|
|
|
1
|
-
//
|
|
2
|
-
// Copyright 2025 DXOS.org
|
|
3
|
-
//
|
|
4
|
-
|
|
5
|
-
import { AiTool, AiToolkit } from '@effect/ai';
|
|
6
|
-
import { describe, it } from '@effect/vitest';
|
|
7
|
-
import { Effect, Layer, Schema } from 'effect';
|
|
8
|
-
|
|
9
|
-
import { AiService, ToolExecutionService, ToolResolverService } from '@dxos/ai';
|
|
10
|
-
import { AiServiceTestingPreset } from '@dxos/ai/testing';
|
|
11
|
-
import { Obj, Type } from '@dxos/echo';
|
|
12
|
-
import { log } from '@dxos/log';
|
|
13
|
-
|
|
14
|
-
import { AiSession } from './session';
|
|
15
|
-
|
|
16
|
-
// Define a calendar event artifact schema.
|
|
17
|
-
const CalendarEventSchema = Schema.Struct({
|
|
18
|
-
title: Schema.String,
|
|
19
|
-
startTime: Schema.String,
|
|
20
|
-
endTime: Schema.String,
|
|
21
|
-
description: Schema.String,
|
|
22
|
-
}).pipe(
|
|
23
|
-
Type.Obj({
|
|
24
|
-
typename: 'example.com/type/CalendarEvent',
|
|
25
|
-
version: '0.1.0',
|
|
26
|
-
}),
|
|
27
|
-
);
|
|
28
|
-
|
|
29
|
-
type CalendarEvent = Schema.Schema.Type<typeof CalendarEventSchema>;
|
|
30
|
-
|
|
31
|
-
class TestToolkit extends AiToolkit.make(
|
|
32
|
-
AiTool.make('Calculator', {
|
|
33
|
-
description: 'Basic calculator tool',
|
|
34
|
-
parameters: {
|
|
35
|
-
input: Schema.String.annotations({
|
|
36
|
-
description: 'The calculation to perform.',
|
|
37
|
-
}),
|
|
38
|
-
},
|
|
39
|
-
success: Schema.Struct({
|
|
40
|
-
result: Schema.Number,
|
|
41
|
-
}),
|
|
42
|
-
failure: Schema.Never,
|
|
43
|
-
}),
|
|
44
|
-
) {}
|
|
45
|
-
|
|
46
|
-
// Tool handlers.
|
|
47
|
-
const toolkitLayer = TestToolkit.toLayer({
|
|
48
|
-
Calculator: ({ input }) =>
|
|
49
|
-
Effect.gen(function* () {
|
|
50
|
-
const result = (() => {
|
|
51
|
-
// Restrict to basic arithmetic operations for safety.
|
|
52
|
-
const sanitizedInput = input.replace(/[^0-9+\-*/().\s]/g, '');
|
|
53
|
-
log.info('calculate', { sanitizedInput });
|
|
54
|
-
|
|
55
|
-
// eslint-disable-next-line no-new-func, @typescript-eslint/no-implied-eval
|
|
56
|
-
return Function(`"use strict"; return (${sanitizedInput})`)();
|
|
57
|
-
})();
|
|
58
|
-
|
|
59
|
-
return { result };
|
|
60
|
-
}),
|
|
61
|
-
});
|
|
62
|
-
|
|
63
|
-
describe.runIf(process.env.DX_RUN_SLOW_TESTS)('AiSession', () => {
|
|
64
|
-
it.effect(
|
|
65
|
-
'no tools',
|
|
66
|
-
Effect.fn(
|
|
67
|
-
function* ({ expect }) {
|
|
68
|
-
const session = new AiSession({ operationModel: 'configured' });
|
|
69
|
-
|
|
70
|
-
const response = yield* session.run({
|
|
71
|
-
prompt: 'Hello world!',
|
|
72
|
-
history: [],
|
|
73
|
-
});
|
|
74
|
-
log.info('response', { response });
|
|
75
|
-
},
|
|
76
|
-
Effect.provide(
|
|
77
|
-
AiService.model('@anthropic/claude-3-5-sonnet-20241022').pipe(
|
|
78
|
-
Layer.provideMerge(ToolResolverService.layerEmpty),
|
|
79
|
-
Layer.provideMerge(ToolExecutionService.layerEmpty),
|
|
80
|
-
Layer.provideMerge(AiServiceTestingPreset('direct')),
|
|
81
|
-
),
|
|
82
|
-
),
|
|
83
|
-
),
|
|
84
|
-
);
|
|
85
|
-
|
|
86
|
-
it.effect.only(
|
|
87
|
-
'calculator',
|
|
88
|
-
Effect.fn(
|
|
89
|
-
function* ({ expect }) {
|
|
90
|
-
const session = new AiSession({ operationModel: 'configured' });
|
|
91
|
-
|
|
92
|
-
const response = yield* session.run({
|
|
93
|
-
prompt: 'What is 10 + 20?',
|
|
94
|
-
history: [],
|
|
95
|
-
toolkit: TestToolkit,
|
|
96
|
-
});
|
|
97
|
-
log.info('response', { response });
|
|
98
|
-
},
|
|
99
|
-
Effect.provide(
|
|
100
|
-
Layer.mergeAll(
|
|
101
|
-
toolkitLayer,
|
|
102
|
-
ToolResolverService.layerEmpty,
|
|
103
|
-
ToolExecutionService.layerEmpty,
|
|
104
|
-
AiService.model('@anthropic/claude-3-5-sonnet-20241022').pipe(
|
|
105
|
-
Layer.provideMerge(AiServiceTestingPreset('direct')),
|
|
106
|
-
),
|
|
107
|
-
),
|
|
108
|
-
),
|
|
109
|
-
),
|
|
110
|
-
);
|
|
111
|
-
|
|
112
|
-
// TODO(dmaretskyi): Revive test.
|
|
113
|
-
/*
|
|
114
|
-
it.skip('create calendar itinerary', { timeout: 60_000 }, async () => {
|
|
115
|
-
|
|
116
|
-
// overrides: { model: 'llama3.1:8b' },
|
|
117
|
-
|
|
118
|
-
const session = new AiSession({ operationModel: 'configured' });
|
|
119
|
-
|
|
120
|
-
const objects = new Set<string>();
|
|
121
|
-
|
|
122
|
-
// Define calendar artifact.
|
|
123
|
-
const calendarArtifact = defineArtifact({
|
|
124
|
-
id: 'artifact:dxos.org/plugin/calendar',
|
|
125
|
-
name: 'Calendar',
|
|
126
|
-
instructions: 'Use this to create and query calendar events.',
|
|
127
|
-
schema: CalendarEventSchema,
|
|
128
|
-
tools: [
|
|
129
|
-
createTool('calendar', {
|
|
130
|
-
name: 'query',
|
|
131
|
-
description: 'Query the calendar for events',
|
|
132
|
-
schema: Schema.Struct({}),
|
|
133
|
-
execute: async () => {
|
|
134
|
-
return ToolResult.Success(CALENDAR_EVENTS);
|
|
135
|
-
},
|
|
136
|
-
}),
|
|
137
|
-
],
|
|
138
|
-
});
|
|
139
|
-
|
|
140
|
-
const tableArtifact = defineArtifact({
|
|
141
|
-
id: 'artifact:dxos.org/plugin/table',
|
|
142
|
-
name: 'Table',
|
|
143
|
-
instructions: 'Use this to create and manage tables. Each table has a unique id.',
|
|
144
|
-
schema: Schema.Struct({}),
|
|
145
|
-
tools: [
|
|
146
|
-
createTool('table', {
|
|
147
|
-
name: 'create',
|
|
148
|
-
description: 'Create a table',
|
|
149
|
-
schema: Schema.Struct({
|
|
150
|
-
data: Schema.Array(Schema.Any).annotations({ description: 'Array of data payloads to add as rows' }),
|
|
151
|
-
}),
|
|
152
|
-
execute: async ({ data }) => {
|
|
153
|
-
log('create table', { data });
|
|
154
|
-
const id = DXN.fromLocalObjectId(ObjectId.random()).toString();
|
|
155
|
-
objects.add(id);
|
|
156
|
-
// TODO(dmaretskyi): consider xml for refs instead of @dxn:echo:@:XXXXX
|
|
157
|
-
return ToolResult.Success(`table @${id}`);
|
|
158
|
-
},
|
|
159
|
-
}),
|
|
160
|
-
],
|
|
161
|
-
});
|
|
162
|
-
|
|
163
|
-
const mapArtifact = defineArtifact({
|
|
164
|
-
id: 'artifact:dxos.org/plugin/map',
|
|
165
|
-
name: 'Map',
|
|
166
|
-
instructions:
|
|
167
|
-
'Use this to create and manage maps. Maps source data from tables. Table id is required to create a map.',
|
|
168
|
-
schema: Schema.Struct({}),
|
|
169
|
-
tools: [
|
|
170
|
-
createTool('map', {
|
|
171
|
-
name: 'create',
|
|
172
|
-
description: 'Create a map',
|
|
173
|
-
schema: Schema.Struct({
|
|
174
|
-
source: ArtifactId.annotations({
|
|
175
|
-
description: 'The table that will be used as the source of the map',
|
|
176
|
-
}),
|
|
177
|
-
}),
|
|
178
|
-
execute: async ({ source }) => {
|
|
179
|
-
// TODO(dmaretskyi): Use effect-schema decode instead of manual parsing.
|
|
180
|
-
const sourceId = ArtifactId.toDXN(source);
|
|
181
|
-
if (!objects.has(sourceId.toString())) {
|
|
182
|
-
return ToolResult.Error(`table id=${source} not found`);
|
|
183
|
-
}
|
|
184
|
-
log('create map', { sourceId });
|
|
185
|
-
const id = DXN.fromLocalObjectId(ObjectId.random()).toString();
|
|
186
|
-
objects.add(id);
|
|
187
|
-
// TODO(dmaretskyi): consider xml for refs instead of @dxn:echo:@:XXXXX
|
|
188
|
-
return ToolResult.Success(`map @${id}`);
|
|
189
|
-
},
|
|
190
|
-
}),
|
|
191
|
-
],
|
|
192
|
-
});
|
|
193
|
-
|
|
194
|
-
const scriptArtifact = defineArtifact({
|
|
195
|
-
id: 'artifact:dxos.org/plugin/script',
|
|
196
|
-
name: 'Script',
|
|
197
|
-
instructions: 'Use this to create and manage scripts',
|
|
198
|
-
schema: Schema.Struct({}),
|
|
199
|
-
tools: [],
|
|
200
|
-
});
|
|
201
|
-
|
|
202
|
-
// session.streamEvent.on((event) => {
|
|
203
|
-
// printStreamEvent(event);
|
|
204
|
-
// });
|
|
205
|
-
|
|
206
|
-
const printer = new ConsolePrinter();
|
|
207
|
-
session.message.on((message) => printer.printMessage(message));
|
|
208
|
-
session.userMessage.on((message) => printer.printMessage(message));
|
|
209
|
-
session.block.on((block) => printer.printContentBlock(block));
|
|
210
|
-
|
|
211
|
-
// session.update.on((update) => {
|
|
212
|
-
// log('update', { update });
|
|
213
|
-
// });
|
|
214
|
-
|
|
215
|
-
// Test creating an itinerary
|
|
216
|
-
const response = await session.run({
|
|
217
|
-
client: aiClient,
|
|
218
|
-
tools: [],
|
|
219
|
-
artifacts: [calendarArtifact, tableArtifact, mapArtifact, scriptArtifact],
|
|
220
|
-
requiredArtifactIds: [calendarArtifact.id, tableArtifact.id, mapArtifact.id, scriptArtifact.id],
|
|
221
|
-
history: [],
|
|
222
|
-
generationOptions: {
|
|
223
|
-
model: '@anthropic/claude-3-5-haiku-20241022',
|
|
224
|
-
},
|
|
225
|
-
prompt: 'create a table and map for a travel itinerary based on events in my calendar',
|
|
226
|
-
toolResolver: new ToolRegistry([]),
|
|
227
|
-
});
|
|
228
|
-
|
|
229
|
-
log('result', {
|
|
230
|
-
objects,
|
|
231
|
-
finalMessage: response.at(-1),
|
|
232
|
-
});
|
|
233
|
-
});
|
|
234
|
-
*/
|
|
235
|
-
});
|
|
236
|
-
|
|
237
|
-
// Travel to rome, florence, livorno, siena, madrid for conferences
|
|
238
|
-
// eslint-disable-next-line no-unused-vars
|
|
239
|
-
const _CALENDAR_EVENTS: CalendarEvent[] = [
|
|
240
|
-
Obj.make(CalendarEventSchema, {
|
|
241
|
-
title: 'Exploring Ancient Ruins in Rome',
|
|
242
|
-
startTime: '2024-01-01T10:00:00Z',
|
|
243
|
-
endTime: '2024-01-01T11:00:00Z',
|
|
244
|
-
description: 'Tech conference at the historic Colosseum with networking opportunities',
|
|
245
|
-
}),
|
|
246
|
-
Obj.make(CalendarEventSchema, {
|
|
247
|
-
title: 'Renaissance Tech Summit in Florence',
|
|
248
|
-
startTime: '2024-01-01T11:00:00Z',
|
|
249
|
-
endTime: '2024-01-01T12:00:00Z',
|
|
250
|
-
description: 'Discussing AI innovations surrounded by Renaissance art',
|
|
251
|
-
}),
|
|
252
|
-
Obj.make(CalendarEventSchema, {
|
|
253
|
-
title: 'Travel to Livorno',
|
|
254
|
-
startTime: '2024-01-01T12:00:00Z',
|
|
255
|
-
endTime: '2024-01-01T13:00:00Z',
|
|
256
|
-
description: 'Travel to Livorno',
|
|
257
|
-
}),
|
|
258
|
-
Obj.make(CalendarEventSchema, {
|
|
259
|
-
title: 'Travel to Siena',
|
|
260
|
-
startTime: '2024-01-01T13:00:00Z',
|
|
261
|
-
endTime: '2024-01-01T14:00:00Z',
|
|
262
|
-
description: 'Travel to Siena',
|
|
263
|
-
}),
|
|
264
|
-
Obj.make(CalendarEventSchema, {
|
|
265
|
-
title: 'Travel to Madrid',
|
|
266
|
-
startTime: '2024-01-01T14:00:00Z',
|
|
267
|
-
endTime: '2024-01-01T15:00:00Z',
|
|
268
|
-
description: 'Travel to Madrid',
|
|
269
|
-
}),
|
|
270
|
-
];
|
|
271
|
-
|
|
272
|
-
// const printStreamEvent = (event: GenerationStreamEvent) => {
|
|
273
|
-
// switch (event.type) {
|
|
274
|
-
// case 'message_start': {
|
|
275
|
-
// process.stdout.write(`${event.message.role.toUpperCase()}\n\n`);
|
|
276
|
-
// for (const content of event.message.content) {
|
|
277
|
-
// printContentBlock(content);
|
|
278
|
-
// }
|
|
279
|
-
// break;
|
|
280
|
-
// }
|
|
281
|
-
// case 'content_block_start': {
|
|
282
|
-
// printContentBlock(event.content);
|
|
283
|
-
// break;
|
|
284
|
-
// }
|
|
285
|
-
// case 'content_block_delta': {
|
|
286
|
-
// switch (event.delta.type) {
|
|
287
|
-
// case 'text_delta': {
|
|
288
|
-
// process.stdout.write(event.delta.text);
|
|
289
|
-
// break;
|
|
290
|
-
// }
|
|
291
|
-
// case 'input_json_delta': {
|
|
292
|
-
// process.stdout.write(event.delta.partial_json);
|
|
293
|
-
// break;
|
|
294
|
-
// }
|
|
295
|
-
// }
|
|
296
|
-
// break;
|
|
297
|
-
// }
|
|
298
|
-
// case 'content_block_stop': {
|
|
299
|
-
// process.stdout.write('\n');
|
|
300
|
-
// break;
|
|
301
|
-
// }
|
|
302
|
-
// case 'message_delta': {
|
|
303
|
-
// break;
|
|
304
|
-
// }
|
|
305
|
-
// case 'message_stop': {
|
|
306
|
-
// process.stdout.write('\n\n');
|
|
307
|
-
// break;
|
|
308
|
-
// }
|
|
309
|
-
// }
|
|
310
|
-
// };
|