@dxos/assistant-toolkit 0.8.4-main.ae835ea
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 +8 -0
- package/README.md +3 -0
- package/dist/lib/browser/index.mjs +2481 -0
- package/dist/lib/browser/index.mjs.map +7 -0
- package/dist/lib/browser/meta.json +1 -0
- package/dist/lib/node-esm/index.mjs +2483 -0
- package/dist/lib/node-esm/index.mjs.map +7 -0
- package/dist/lib/node-esm/meta.json +1 -0
- package/dist/types/src/blueprints/design/design-blueprint.d.ts +4 -0
- package/dist/types/src/blueprints/design/design-blueprint.d.ts.map +1 -0
- package/dist/types/src/blueprints/design/design-blueprint.test.d.ts +2 -0
- package/dist/types/src/blueprints/design/design-blueprint.test.d.ts.map +1 -0
- package/dist/types/src/blueprints/design/index.d.ts +3 -0
- package/dist/types/src/blueprints/design/index.d.ts.map +1 -0
- package/dist/types/src/blueprints/discord/discord-blueprint.d.ts +18 -0
- package/dist/types/src/blueprints/discord/discord-blueprint.d.ts.map +1 -0
- package/dist/types/src/blueprints/discord/index.d.ts +3 -0
- package/dist/types/src/blueprints/discord/index.d.ts.map +1 -0
- package/dist/types/src/blueprints/index.d.ts +7 -0
- package/dist/types/src/blueprints/index.d.ts.map +1 -0
- package/dist/types/src/blueprints/linear/index.d.ts +3 -0
- package/dist/types/src/blueprints/linear/index.d.ts.map +1 -0
- package/dist/types/src/blueprints/linear/linear-blueprint.d.ts +18 -0
- package/dist/types/src/blueprints/linear/linear-blueprint.d.ts.map +1 -0
- package/dist/types/src/blueprints/planning/index.d.ts +3 -0
- package/dist/types/src/blueprints/planning/index.d.ts.map +1 -0
- package/dist/types/src/blueprints/planning/planning-blueprint.d.ts +4 -0
- package/dist/types/src/blueprints/planning/planning-blueprint.d.ts.map +1 -0
- package/dist/types/src/blueprints/planning/planning-blueprint.test.d.ts +2 -0
- package/dist/types/src/blueprints/planning/planning-blueprint.test.d.ts.map +1 -0
- package/dist/types/src/blueprints/research/index.d.ts +3 -0
- package/dist/types/src/blueprints/research/index.d.ts.map +1 -0
- package/dist/types/src/blueprints/research/research-blueprint.d.ts +4 -0
- package/dist/types/src/blueprints/research/research-blueprint.d.ts.map +1 -0
- package/dist/types/src/blueprints/research/research-blueprint.test.d.ts +2 -0
- package/dist/types/src/blueprints/research/research-blueprint.test.d.ts.map +1 -0
- package/dist/types/src/blueprints/testing.d.ts +12 -0
- package/dist/types/src/blueprints/testing.d.ts.map +1 -0
- package/dist/types/src/blueprints/websearch/index.d.ts +4 -0
- package/dist/types/src/blueprints/websearch/index.d.ts.map +1 -0
- package/dist/types/src/blueprints/websearch/websearch-blueprint.d.ts +4 -0
- package/dist/types/src/blueprints/websearch/websearch-blueprint.d.ts.map +1 -0
- package/dist/types/src/blueprints/websearch/websearch-toolkit.d.ts +26 -0
- package/dist/types/src/blueprints/websearch/websearch-toolkit.d.ts.map +1 -0
- package/dist/types/src/experimental/feed.test.d.ts +2 -0
- package/dist/types/src/experimental/feed.test.d.ts.map +1 -0
- package/dist/types/src/functions/agent/index.d.ts +5 -0
- package/dist/types/src/functions/agent/index.d.ts.map +1 -0
- package/dist/types/src/functions/agent/prompt.d.ts +11 -0
- package/dist/types/src/functions/agent/prompt.d.ts.map +1 -0
- package/dist/types/src/functions/discord/fetch-messages.d.ts +11 -0
- package/dist/types/src/functions/discord/fetch-messages.d.ts.map +1 -0
- package/dist/types/src/functions/discord/fetch-messages.test.d.ts +2 -0
- package/dist/types/src/functions/discord/fetch-messages.test.d.ts.map +1 -0
- package/dist/types/src/functions/discord/index.d.ts +12 -0
- package/dist/types/src/functions/discord/index.d.ts.map +1 -0
- package/dist/types/src/functions/document/index.d.ts +12 -0
- package/dist/types/src/functions/document/index.d.ts.map +1 -0
- package/dist/types/src/functions/document/read.d.ts +7 -0
- package/dist/types/src/functions/document/read.d.ts.map +1 -0
- package/dist/types/src/functions/document/update.d.ts +6 -0
- package/dist/types/src/functions/document/update.d.ts.map +1 -0
- package/dist/types/src/functions/entity-extraction/entity-extraction.d.ts +173 -0
- package/dist/types/src/functions/entity-extraction/entity-extraction.d.ts.map +1 -0
- package/dist/types/src/functions/entity-extraction/entity-extraction.test.d.ts +2 -0
- package/dist/types/src/functions/entity-extraction/entity-extraction.test.d.ts.map +1 -0
- package/dist/types/src/functions/entity-extraction/index.d.ts +174 -0
- package/dist/types/src/functions/entity-extraction/index.d.ts.map +1 -0
- package/dist/types/src/functions/exa/exa.d.ts +5 -0
- package/dist/types/src/functions/exa/exa.d.ts.map +1 -0
- package/dist/types/src/functions/exa/index.d.ts +3 -0
- package/dist/types/src/functions/exa/index.d.ts.map +1 -0
- package/dist/types/src/functions/exa/mock.d.ts +5 -0
- package/dist/types/src/functions/exa/mock.d.ts.map +1 -0
- package/dist/types/src/functions/github/fetch-prs.d.ts +6 -0
- package/dist/types/src/functions/github/fetch-prs.d.ts.map +1 -0
- package/dist/types/src/functions/index.d.ts +8 -0
- package/dist/types/src/functions/index.d.ts.map +1 -0
- package/dist/types/src/functions/linear/index.d.ts +9 -0
- package/dist/types/src/functions/linear/index.d.ts.map +1 -0
- package/dist/types/src/functions/linear/linear.test.d.ts +2 -0
- package/dist/types/src/functions/linear/linear.test.d.ts.map +1 -0
- package/dist/types/src/functions/linear/sync-issues.d.ts +12 -0
- package/dist/types/src/functions/linear/sync-issues.d.ts.map +1 -0
- package/dist/types/src/functions/research/create-document.d.ts +7 -0
- package/dist/types/src/functions/research/create-document.d.ts.map +1 -0
- package/dist/types/src/functions/research/graph.d.ts +64 -0
- package/dist/types/src/functions/research/graph.d.ts.map +1 -0
- package/dist/types/src/functions/research/graph.test.d.ts +2 -0
- package/dist/types/src/functions/research/graph.test.d.ts.map +1 -0
- package/dist/types/src/functions/research/index.d.ts +19 -0
- package/dist/types/src/functions/research/index.d.ts.map +1 -0
- package/dist/types/src/functions/research/research-graph.d.ts +18 -0
- package/dist/types/src/functions/research/research-graph.d.ts.map +1 -0
- package/dist/types/src/functions/research/research.d.ts +13 -0
- package/dist/types/src/functions/research/research.d.ts.map +1 -0
- package/dist/types/src/functions/research/research.test.d.ts +2 -0
- package/dist/types/src/functions/research/research.test.d.ts.map +1 -0
- package/dist/types/src/functions/research/types.d.ts +384 -0
- package/dist/types/src/functions/research/types.d.ts.map +1 -0
- package/dist/types/src/functions/tasks/index.d.ts +15 -0
- package/dist/types/src/functions/tasks/index.d.ts.map +1 -0
- package/dist/types/src/functions/tasks/read.d.ts +7 -0
- package/dist/types/src/functions/tasks/read.d.ts.map +1 -0
- package/dist/types/src/functions/tasks/task-list.d.ts +74 -0
- package/dist/types/src/functions/tasks/task-list.d.ts.map +1 -0
- package/dist/types/src/functions/tasks/task-list.test.d.ts +2 -0
- package/dist/types/src/functions/tasks/task-list.test.d.ts.map +1 -0
- package/dist/types/src/functions/tasks/update.d.ts +9 -0
- package/dist/types/src/functions/tasks/update.d.ts.map +1 -0
- package/dist/types/src/index.d.ts +5 -0
- package/dist/types/src/index.d.ts.map +1 -0
- package/dist/types/src/plugins.d.ts +19 -0
- package/dist/types/src/plugins.d.ts.map +1 -0
- package/dist/types/src/sync/index.d.ts +2 -0
- package/dist/types/src/sync/index.d.ts.map +1 -0
- package/dist/types/src/sync/sync.d.ts +15 -0
- package/dist/types/src/sync/sync.d.ts.map +1 -0
- package/dist/types/src/testing/data/exa-search-1748337321991.d.ts +38 -0
- package/dist/types/src/testing/data/exa-search-1748337321991.d.ts.map +1 -0
- package/dist/types/src/testing/data/exa-search-1748337331526.d.ts +37 -0
- package/dist/types/src/testing/data/exa-search-1748337331526.d.ts.map +1 -0
- package/dist/types/src/testing/data/exa-search-1748337344119.d.ts +58 -0
- package/dist/types/src/testing/data/exa-search-1748337344119.d.ts.map +1 -0
- package/dist/types/src/testing/data/index.d.ts +3 -0
- package/dist/types/src/testing/data/index.d.ts.map +1 -0
- package/dist/types/src/testing/index.d.ts +2 -0
- package/dist/types/src/testing/index.d.ts.map +1 -0
- package/dist/types/src/util/graphql.d.ts +22 -0
- package/dist/types/src/util/graphql.d.ts.map +1 -0
- package/dist/types/src/util/index.d.ts +2 -0
- package/dist/types/src/util/index.d.ts.map +1 -0
- package/dist/types/tsconfig.tsbuildinfo +1 -0
- package/package.json +67 -0
- package/src/blueprints/design/design-blueprint.test.ts +108 -0
- package/src/blueprints/design/design-blueprint.ts +33 -0
- package/src/blueprints/design/index.ts +7 -0
- package/src/blueprints/discord/discord-blueprint.ts +34 -0
- package/src/blueprints/discord/index.ts +7 -0
- package/src/blueprints/index.ts +10 -0
- package/src/blueprints/linear/index.ts +7 -0
- package/src/blueprints/linear/linear-blueprint.ts +35 -0
- package/src/blueprints/planning/index.ts +7 -0
- package/src/blueprints/planning/planning-blueprint.test.ts +129 -0
- package/src/blueprints/planning/planning-blueprint.ts +98 -0
- package/src/blueprints/research/index.ts +7 -0
- package/src/blueprints/research/research-blueprint.test.ts +7 -0
- package/src/blueprints/research/research-blueprint.ts +45 -0
- package/src/blueprints/testing.ts +34 -0
- package/src/blueprints/websearch/index.ts +8 -0
- package/src/blueprints/websearch/websearch-blueprint.ts +20 -0
- package/src/blueprints/websearch/websearch-toolkit.ts +8 -0
- package/src/experimental/feed.test.ts +108 -0
- package/src/functions/agent/index.ts +11 -0
- package/src/functions/agent/prompt.ts +101 -0
- package/src/functions/discord/fetch-messages.test.ts +59 -0
- package/src/functions/discord/fetch-messages.ts +251 -0
- package/src/functions/discord/index.ts +9 -0
- package/src/functions/document/index.ts +11 -0
- package/src/functions/document/read.ts +29 -0
- package/src/functions/document/update.ts +30 -0
- package/src/functions/entity-extraction/entity-extraction.conversations.json +1 -0
- package/src/functions/entity-extraction/entity-extraction.test.ts +100 -0
- package/src/functions/entity-extraction/entity-extraction.ts +163 -0
- package/src/functions/entity-extraction/index.ts +9 -0
- package/src/functions/exa/exa.ts +37 -0
- package/src/functions/exa/index.ts +6 -0
- package/src/functions/exa/mock.ts +71 -0
- package/src/functions/github/fetch-prs.ts +30 -0
- package/src/functions/index.ts +11 -0
- package/src/functions/linear/index.ts +9 -0
- package/src/functions/linear/linear.test.ts +86 -0
- package/src/functions/linear/sync-issues.ts +189 -0
- package/src/functions/research/create-document.ts +69 -0
- package/src/functions/research/graph.test.ts +69 -0
- package/src/functions/research/graph.ts +388 -0
- package/src/functions/research/index.ts +15 -0
- package/src/functions/research/instructions-research.tpl +98 -0
- package/src/functions/research/research-graph.ts +47 -0
- package/src/functions/research/research.conversations.json +10714 -0
- package/src/functions/research/research.test.ts +240 -0
- package/src/functions/research/research.ts +155 -0
- package/src/functions/research/types.ts +24 -0
- package/src/functions/tasks/index.ts +11 -0
- package/src/functions/tasks/read.ts +34 -0
- package/src/functions/tasks/task-list.test.ts +99 -0
- package/src/functions/tasks/task-list.ts +165 -0
- package/src/functions/tasks/update.ts +52 -0
- package/src/index.ts +8 -0
- package/src/plugins.tsx +68 -0
- package/src/sync/index.ts +5 -0
- package/src/sync/sync.ts +87 -0
- package/src/testing/data/exa-search-1748337321991.ts +131 -0
- package/src/testing/data/exa-search-1748337331526.ts +144 -0
- package/src/testing/data/exa-search-1748337344119.ts +133 -0
- package/src/testing/data/index.ts +11 -0
- package/src/testing/index.ts +5 -0
- package/src/typedefs.d.ts +8 -0
- package/src/util/graphql.ts +31 -0
- package/src/util/index.ts +5 -0
package/package.json
ADDED
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@dxos/assistant-toolkit",
|
|
3
|
+
"version": "0.8.4-main.ae835ea",
|
|
4
|
+
"description": "Assistant toolkit, definitions, and utilities.",
|
|
5
|
+
"homepage": "https://dxos.org",
|
|
6
|
+
"bugs": "https://github.com/dxos/dxos/issues",
|
|
7
|
+
"license": "MIT",
|
|
8
|
+
"author": "DXOS.org",
|
|
9
|
+
"type": "module",
|
|
10
|
+
"exports": {
|
|
11
|
+
".": {
|
|
12
|
+
"source": "./src/index.ts",
|
|
13
|
+
"types": "./dist/types/src/index.d.ts",
|
|
14
|
+
"browser": "./dist/lib/browser/index.mjs",
|
|
15
|
+
"node": "./dist/lib/node-esm/index.mjs"
|
|
16
|
+
}
|
|
17
|
+
},
|
|
18
|
+
"types": "dist/types/src/index.d.ts",
|
|
19
|
+
"typesVersions": {
|
|
20
|
+
"*": {}
|
|
21
|
+
},
|
|
22
|
+
"files": [
|
|
23
|
+
"dist",
|
|
24
|
+
"src"
|
|
25
|
+
],
|
|
26
|
+
"dependencies": {
|
|
27
|
+
"@effect/ai": "0.29.1",
|
|
28
|
+
"@effect/ai-anthropic": "0.19.2",
|
|
29
|
+
"@effect/experimental": "0.56.0",
|
|
30
|
+
"@effect/platform": "^0.92.1",
|
|
31
|
+
"dfx": "^0.126.0",
|
|
32
|
+
"exa-js": "^1.5.12",
|
|
33
|
+
"@dxos/ai": "0.8.4-main.ae835ea",
|
|
34
|
+
"@dxos/app-framework": "0.8.4-main.ae835ea",
|
|
35
|
+
"@dxos/assistant": "0.8.4-main.ae835ea",
|
|
36
|
+
"@dxos/blueprints": "0.8.4-main.ae835ea",
|
|
37
|
+
"@dxos/context": "0.8.4-main.ae835ea",
|
|
38
|
+
"@dxos/conductor": "0.8.4-main.ae835ea",
|
|
39
|
+
"@dxos/echo-db": "0.8.4-main.ae835ea",
|
|
40
|
+
"@dxos/echo": "0.8.4-main.ae835ea",
|
|
41
|
+
"@dxos/echo-protocol": "0.8.4-main.ae835ea",
|
|
42
|
+
"@dxos/edge-client": "0.8.4-main.ae835ea",
|
|
43
|
+
"@dxos/functions": "0.8.4-main.ae835ea",
|
|
44
|
+
"@dxos/errors": "0.8.4-main.ae835ea",
|
|
45
|
+
"@dxos/invariant": "0.8.4-main.ae835ea",
|
|
46
|
+
"@dxos/keys": "0.8.4-main.ae835ea",
|
|
47
|
+
"@dxos/log": "0.8.4-main.ae835ea",
|
|
48
|
+
"@dxos/react-ui-syntax-highlighter": "0.8.4-main.ae835ea",
|
|
49
|
+
"@dxos/util": "0.8.4-main.ae835ea",
|
|
50
|
+
"@dxos/effect": "0.8.4-main.ae835ea",
|
|
51
|
+
"@dxos/plugin-markdown": "0.8.4-main.ae835ea",
|
|
52
|
+
"@dxos/schema": "0.8.4-main.ae835ea"
|
|
53
|
+
},
|
|
54
|
+
"devDependencies": {
|
|
55
|
+
"effect": "3.18.3",
|
|
56
|
+
"react": "~19.2.0",
|
|
57
|
+
"react-dom": "~19.2.0"
|
|
58
|
+
},
|
|
59
|
+
"peerDependencies": {
|
|
60
|
+
"effect": "^3.13.3",
|
|
61
|
+
"react": "^19.0.0",
|
|
62
|
+
"react-dom": "^19.0.0"
|
|
63
|
+
},
|
|
64
|
+
"publishConfig": {
|
|
65
|
+
"access": "public"
|
|
66
|
+
}
|
|
67
|
+
}
|
|
@@ -0,0 +1,108 @@
|
|
|
1
|
+
//
|
|
2
|
+
// Copyright 2025 DXOS.org
|
|
3
|
+
//
|
|
4
|
+
|
|
5
|
+
import { describe, it } from '@effect/vitest';
|
|
6
|
+
import * as Effect from 'effect/Effect';
|
|
7
|
+
import * as Layer from 'effect/Layer';
|
|
8
|
+
|
|
9
|
+
import { AiService, ConsolePrinter } from '@dxos/ai';
|
|
10
|
+
import { AiServiceTestingPreset } from '@dxos/ai/testing';
|
|
11
|
+
import {
|
|
12
|
+
AiConversation,
|
|
13
|
+
type ContextBinding,
|
|
14
|
+
GenerationObserver,
|
|
15
|
+
makeToolExecutionServiceFromFunctions,
|
|
16
|
+
makeToolResolverFromFunctions,
|
|
17
|
+
} from '@dxos/assistant';
|
|
18
|
+
import { Blueprint } from '@dxos/blueprints';
|
|
19
|
+
import { Obj, Ref } from '@dxos/echo';
|
|
20
|
+
import { TestHelpers, acquireReleaseResource } from '@dxos/effect';
|
|
21
|
+
import {
|
|
22
|
+
ComputeEventLogger,
|
|
23
|
+
DatabaseService,
|
|
24
|
+
FunctionInvocationService,
|
|
25
|
+
QueueService,
|
|
26
|
+
TracingService,
|
|
27
|
+
} from '@dxos/functions';
|
|
28
|
+
import { TestDatabaseLayer } from '@dxos/functions/testing';
|
|
29
|
+
import { log } from '@dxos/log';
|
|
30
|
+
import { Markdown } from '@dxos/plugin-markdown/types';
|
|
31
|
+
import { DataType } from '@dxos/schema';
|
|
32
|
+
import { trim } from '@dxos/util';
|
|
33
|
+
|
|
34
|
+
import { Document } from '../../functions';
|
|
35
|
+
import { testToolkit } from '../testing';
|
|
36
|
+
|
|
37
|
+
import blueprint from './design-blueprint';
|
|
38
|
+
|
|
39
|
+
describe('Design Blueprint', { timeout: 120_000 }, () => {
|
|
40
|
+
it.scoped(
|
|
41
|
+
'design blueprint',
|
|
42
|
+
Effect.fn(
|
|
43
|
+
function* ({ expect }) {
|
|
44
|
+
const observer = GenerationObserver.fromPrinter(new ConsolePrinter());
|
|
45
|
+
const queue = yield* QueueService.createQueue<DataType.Message | ContextBinding>();
|
|
46
|
+
const conversation = yield* acquireReleaseResource(() => new AiConversation(queue));
|
|
47
|
+
|
|
48
|
+
yield* DatabaseService.add(blueprint);
|
|
49
|
+
yield* Effect.promise(() =>
|
|
50
|
+
conversation.context.bind({
|
|
51
|
+
blueprints: [Ref.make(blueprint)],
|
|
52
|
+
}),
|
|
53
|
+
);
|
|
54
|
+
|
|
55
|
+
const artifact = yield* DatabaseService.add(Markdown.makeDocument({ content: 'Hello, world!' }));
|
|
56
|
+
let prevContent = artifact.content;
|
|
57
|
+
|
|
58
|
+
{
|
|
59
|
+
const prompt = trim`
|
|
60
|
+
I want to design a new feature for our product.
|
|
61
|
+
|
|
62
|
+
We need to add a user profile system with the following requirements:
|
|
63
|
+
1. Users should be able to create and edit their profiles
|
|
64
|
+
2. Profile should include basic info like name, bio, avatar
|
|
65
|
+
3. Users can control privacy settings for their profile
|
|
66
|
+
4. Profile should show user's activity history
|
|
67
|
+
5. Need to consider data storage and security implications
|
|
68
|
+
|
|
69
|
+
Let's capture the key design decisions in our spec in ${Obj.getDXN(artifact)}
|
|
70
|
+
`;
|
|
71
|
+
|
|
72
|
+
yield* conversation.createRequest({ prompt, observer });
|
|
73
|
+
log.info('spec', { doc: artifact });
|
|
74
|
+
expect(artifact.content).not.toBe(prevContent);
|
|
75
|
+
prevContent = artifact.content;
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
{
|
|
79
|
+
const prompt = trim`
|
|
80
|
+
I want this to be built on top of Durable Objects and SQLite database.
|
|
81
|
+
Adjust the spec to reflect this.
|
|
82
|
+
`;
|
|
83
|
+
|
|
84
|
+
yield* conversation.createRequest({ observer, prompt });
|
|
85
|
+
expect(artifact.content).not.toBe(prevContent);
|
|
86
|
+
prevContent = artifact.content;
|
|
87
|
+
}
|
|
88
|
+
},
|
|
89
|
+
Effect.provide(
|
|
90
|
+
Layer.mergeAll(
|
|
91
|
+
makeToolResolverFromFunctions([Document.read, Document.update], testToolkit),
|
|
92
|
+
makeToolExecutionServiceFromFunctions(testToolkit, testToolkit.toLayer({}) as any),
|
|
93
|
+
AiService.model('@anthropic/claude-3-5-sonnet-20241022'),
|
|
94
|
+
).pipe(
|
|
95
|
+
Layer.provideMerge(TestDatabaseLayer({ types: [DataType.Text, Markdown.Document, Blueprint.Blueprint] })),
|
|
96
|
+
Layer.provideMerge(AiServiceTestingPreset('direct')),
|
|
97
|
+
Layer.provideMerge(
|
|
98
|
+
FunctionInvocationService.layerTestMocked({ functions: [Document.read, Document.update] }).pipe(
|
|
99
|
+
Layer.provideMerge(ComputeEventLogger.layerFromTracing),
|
|
100
|
+
Layer.provideMerge(TracingService.layerNoop),
|
|
101
|
+
),
|
|
102
|
+
),
|
|
103
|
+
),
|
|
104
|
+
),
|
|
105
|
+
TestHelpers.taggedTest('llm'),
|
|
106
|
+
),
|
|
107
|
+
);
|
|
108
|
+
});
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
//
|
|
2
|
+
// Copyright 2025 DXOS.org
|
|
3
|
+
//
|
|
4
|
+
|
|
5
|
+
import { ToolId } from '@dxos/ai';
|
|
6
|
+
import { Blueprint } from '@dxos/blueprints';
|
|
7
|
+
import { Obj, Ref } from '@dxos/echo';
|
|
8
|
+
import { DataType } from '@dxos/schema';
|
|
9
|
+
import { trim } from '@dxos/util';
|
|
10
|
+
|
|
11
|
+
import { Document } from '../../functions';
|
|
12
|
+
|
|
13
|
+
const instructions = trim`
|
|
14
|
+
You manage a design spec based on the conversation.
|
|
15
|
+
The design spec is a markdown document that is used to record the tasks.
|
|
16
|
+
The design spec document follows a hierarchical structure, with nested markdown bulleted sections.
|
|
17
|
+
Use the appropriate tools to read and write the design spec document.
|
|
18
|
+
Maintain the document so that it can convey all relevant points from the conversation.
|
|
19
|
+
When replying to the user, be terse with your comments about design doc handling.
|
|
20
|
+
Do not announce when you read or write the design spec document.
|
|
21
|
+
`;
|
|
22
|
+
|
|
23
|
+
const blueprint: Blueprint.Blueprint = Obj.make(Blueprint.Blueprint, {
|
|
24
|
+
key: 'dxos.org/blueprint/design',
|
|
25
|
+
name: 'Design Spec',
|
|
26
|
+
description: 'Preserve the conversation in the design spec.',
|
|
27
|
+
instructions: {
|
|
28
|
+
source: Ref.make(DataType.makeText(instructions)),
|
|
29
|
+
},
|
|
30
|
+
tools: [Document.read, Document.update].map((fn) => ToolId.make(fn.key)),
|
|
31
|
+
});
|
|
32
|
+
|
|
33
|
+
export default blueprint;
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
//
|
|
2
|
+
// Copyright 2025 DXOS.org
|
|
3
|
+
//
|
|
4
|
+
|
|
5
|
+
import { ToolId } from '@dxos/ai';
|
|
6
|
+
import { Blueprint } from '@dxos/blueprints';
|
|
7
|
+
import { Obj, Ref } from '@dxos/echo';
|
|
8
|
+
import { DataType } from '@dxos/schema';
|
|
9
|
+
import { trim } from '@dxos/util';
|
|
10
|
+
|
|
11
|
+
import { Discord } from '../../functions';
|
|
12
|
+
|
|
13
|
+
/**
|
|
14
|
+
* Agent prompt instructions for managing hierarchical task lists.
|
|
15
|
+
*/
|
|
16
|
+
const instructions = trim`
|
|
17
|
+
You are able to fetch messages from Discord servers.
|
|
18
|
+
|
|
19
|
+
Known servers:
|
|
20
|
+
|
|
21
|
+
DXOS serverId: 837138313172353095
|
|
22
|
+
`;
|
|
23
|
+
|
|
24
|
+
export const blueprint = Obj.make(Blueprint.Blueprint, {
|
|
25
|
+
key: 'dxos.org/blueprint/discord',
|
|
26
|
+
name: 'Discord',
|
|
27
|
+
description: 'Discord integration.',
|
|
28
|
+
instructions: {
|
|
29
|
+
source: Ref.make(DataType.makeText(instructions)),
|
|
30
|
+
},
|
|
31
|
+
tools: [ToolId.make(Discord.fetch.key)],
|
|
32
|
+
});
|
|
33
|
+
|
|
34
|
+
export default blueprint;
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
//
|
|
2
|
+
// Copyright 2025 DXOS.org
|
|
3
|
+
//
|
|
4
|
+
|
|
5
|
+
export { default as DesignBlueprint } from './design';
|
|
6
|
+
export { default as DiscordBlueprint } from './discord';
|
|
7
|
+
export { default as LinearBlueprint } from './linear';
|
|
8
|
+
export { default as PlanningBlueprint } from './planning';
|
|
9
|
+
export { default as ResearchBlueprint } from './research';
|
|
10
|
+
export { default as WebSearchBlueprint, WebSearchToolkit } from './websearch';
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
//
|
|
2
|
+
// Copyright 2025 DXOS.org
|
|
3
|
+
//
|
|
4
|
+
|
|
5
|
+
import { ToolId } from '@dxos/ai';
|
|
6
|
+
import { Blueprint } from '@dxos/blueprints';
|
|
7
|
+
import { Obj, Ref } from '@dxos/echo';
|
|
8
|
+
import { DataType } from '@dxos/schema';
|
|
9
|
+
import { trim } from '@dxos/util';
|
|
10
|
+
|
|
11
|
+
import { Linear } from '../../functions';
|
|
12
|
+
|
|
13
|
+
/**
|
|
14
|
+
* Agent prompt instructions for managing hierarchical task lists.
|
|
15
|
+
*/
|
|
16
|
+
const instructions = trim`
|
|
17
|
+
You are able to sync Linear workspaces.
|
|
18
|
+
Sometimes sync does not complete in one go and you need to call the function again.
|
|
19
|
+
|
|
20
|
+
Known workspaces:
|
|
21
|
+
|
|
22
|
+
DXOS teamId: 1127c63a-6f77-4725-9229-50f6cd47321c
|
|
23
|
+
`;
|
|
24
|
+
|
|
25
|
+
export const blueprint = Obj.make(Blueprint.Blueprint, {
|
|
26
|
+
key: 'dxos.org/blueprint/linear',
|
|
27
|
+
name: 'Linear',
|
|
28
|
+
description: 'Syncs Linear workspaces.',
|
|
29
|
+
instructions: {
|
|
30
|
+
source: Ref.make(DataType.makeText(instructions)),
|
|
31
|
+
},
|
|
32
|
+
tools: [Linear.sync].map((tool) => ToolId.make(tool.key)),
|
|
33
|
+
});
|
|
34
|
+
|
|
35
|
+
export default blueprint;
|
|
@@ -0,0 +1,129 @@
|
|
|
1
|
+
//
|
|
2
|
+
// Copyright 2025 DXOS.org
|
|
3
|
+
//
|
|
4
|
+
|
|
5
|
+
import { describe, it } from '@effect/vitest';
|
|
6
|
+
import * as Effect from 'effect/Effect';
|
|
7
|
+
import * as Layer from 'effect/Layer';
|
|
8
|
+
|
|
9
|
+
import { AiService } from '@dxos/ai';
|
|
10
|
+
import { AiServiceTestingPreset } from '@dxos/ai/testing';
|
|
11
|
+
import {
|
|
12
|
+
AiConversation,
|
|
13
|
+
type ContextBinding,
|
|
14
|
+
makeToolExecutionServiceFromFunctions,
|
|
15
|
+
makeToolResolverFromFunctions,
|
|
16
|
+
} from '@dxos/assistant';
|
|
17
|
+
import { Blueprint } from '@dxos/blueprints';
|
|
18
|
+
import { Obj, Ref } from '@dxos/echo';
|
|
19
|
+
import { TestHelpers, acquireReleaseResource } from '@dxos/effect';
|
|
20
|
+
import {
|
|
21
|
+
ComputeEventLogger,
|
|
22
|
+
DatabaseService,
|
|
23
|
+
FunctionImplementationResolver,
|
|
24
|
+
FunctionInvocationService,
|
|
25
|
+
QueueService,
|
|
26
|
+
TracingService,
|
|
27
|
+
} from '@dxos/functions';
|
|
28
|
+
import { TestDatabaseLayer } from '@dxos/functions/testing';
|
|
29
|
+
import { log } from '@dxos/log';
|
|
30
|
+
import { Markdown } from '@dxos/plugin-markdown/types';
|
|
31
|
+
import { DataType } from '@dxos/schema';
|
|
32
|
+
import { trim } from '@dxos/util';
|
|
33
|
+
|
|
34
|
+
import { Tasks } from '../../functions';
|
|
35
|
+
import { type TestStep, runSteps, testToolkit } from '../testing';
|
|
36
|
+
|
|
37
|
+
import blueprint from './planning-blueprint';
|
|
38
|
+
|
|
39
|
+
describe('Planning Blueprint', { timeout: 120_000 }, () => {
|
|
40
|
+
it.scoped(
|
|
41
|
+
'planning blueprint',
|
|
42
|
+
Effect.fn(
|
|
43
|
+
function* ({ expect }) {
|
|
44
|
+
const queue = yield* QueueService.createQueue<DataType.Message | ContextBinding>();
|
|
45
|
+
const conversation = yield* acquireReleaseResource(() => new AiConversation(queue));
|
|
46
|
+
|
|
47
|
+
yield* DatabaseService.add(blueprint);
|
|
48
|
+
yield* Effect.promise(() =>
|
|
49
|
+
conversation.context.bind({
|
|
50
|
+
blueprints: [Ref.make(blueprint)],
|
|
51
|
+
}),
|
|
52
|
+
);
|
|
53
|
+
|
|
54
|
+
const artifact = yield* DatabaseService.add(Markdown.makeDocument());
|
|
55
|
+
let prevContent = artifact.content;
|
|
56
|
+
const matchList =
|
|
57
|
+
({ includes = [], excludes = [] }: { includes: RegExp[]; excludes?: RegExp[] }) =>
|
|
58
|
+
async () => {
|
|
59
|
+
const { content } = await artifact.content.load();
|
|
60
|
+
log.info('spec', { doc: artifact.content.target?.content });
|
|
61
|
+
expect(content).not.toBe(prevContent);
|
|
62
|
+
const text = content.toLowerCase();
|
|
63
|
+
for (const include of includes) {
|
|
64
|
+
expect(text.match(include), `does not include: ${include}`).toBeTruthy();
|
|
65
|
+
}
|
|
66
|
+
for (const exclude of excludes) {
|
|
67
|
+
expect(text.match(exclude), `includes: ${exclude}`).toBeFalsy();
|
|
68
|
+
}
|
|
69
|
+
prevContent = artifact.content;
|
|
70
|
+
};
|
|
71
|
+
|
|
72
|
+
const system = 'You are a helpful assistant.';
|
|
73
|
+
const steps: TestStep[] = [
|
|
74
|
+
{
|
|
75
|
+
system,
|
|
76
|
+
prompt: trim`
|
|
77
|
+
I'm building a shelf.
|
|
78
|
+
Maintain a shopping list here: ${Obj.getDXN(artifact)}
|
|
79
|
+
I need a hammer, nails, and a saw.
|
|
80
|
+
`,
|
|
81
|
+
test: matchList({
|
|
82
|
+
includes: [/- \[.+hammer/, /- \[.+nails/, /- \[.+saw/],
|
|
83
|
+
}),
|
|
84
|
+
},
|
|
85
|
+
{
|
|
86
|
+
system,
|
|
87
|
+
prompt: trim`
|
|
88
|
+
I will need a board too.
|
|
89
|
+
`,
|
|
90
|
+
test: matchList({
|
|
91
|
+
includes: [/- \[.+board/],
|
|
92
|
+
}),
|
|
93
|
+
},
|
|
94
|
+
{
|
|
95
|
+
system,
|
|
96
|
+
prompt: trim`
|
|
97
|
+
Actually I'm going to use screws and a screwdriver.
|
|
98
|
+
`,
|
|
99
|
+
test: matchList({
|
|
100
|
+
includes: [/- \[.+screwdriver/, /- \[.+screws/],
|
|
101
|
+
excludes: [/- \[.+hammer/, /- \[.+nails/],
|
|
102
|
+
}),
|
|
103
|
+
},
|
|
104
|
+
];
|
|
105
|
+
|
|
106
|
+
yield* runSteps(conversation, steps);
|
|
107
|
+
},
|
|
108
|
+
Effect.provide(
|
|
109
|
+
Layer.mergeAll(
|
|
110
|
+
TestDatabaseLayer({ types: [DataType.Text, Markdown.Document, Blueprint.Blueprint] }),
|
|
111
|
+
makeToolResolverFromFunctions([Tasks.read, Tasks.update], testToolkit),
|
|
112
|
+
makeToolExecutionServiceFromFunctions(testToolkit, testToolkit.toLayer({}) as any),
|
|
113
|
+
AiService.model('@anthropic/claude-3-5-sonnet-20241022'),
|
|
114
|
+
).pipe(
|
|
115
|
+
Layer.provideMerge(
|
|
116
|
+
FunctionInvocationService.layerTestMocked({ functions: [Tasks.read, Tasks.update] }).pipe(
|
|
117
|
+
Layer.provideMerge(ComputeEventLogger.layerFromTracing),
|
|
118
|
+
Layer.provideMerge(TracingService.layerNoop),
|
|
119
|
+
),
|
|
120
|
+
),
|
|
121
|
+
Layer.provideMerge(FunctionImplementationResolver.layerTest({ functions: [Tasks.read, Tasks.update] })),
|
|
122
|
+
Layer.provideMerge(TestDatabaseLayer({ types: [DataType.Text, Markdown.Document, Blueprint.Blueprint] })),
|
|
123
|
+
Layer.provideMerge(AiServiceTestingPreset('direct')),
|
|
124
|
+
),
|
|
125
|
+
),
|
|
126
|
+
TestHelpers.taggedTest('llm'),
|
|
127
|
+
),
|
|
128
|
+
);
|
|
129
|
+
});
|
|
@@ -0,0 +1,98 @@
|
|
|
1
|
+
//
|
|
2
|
+
// Copyright 2025 DXOS.org
|
|
3
|
+
//
|
|
4
|
+
|
|
5
|
+
import { ToolId } from '@dxos/ai';
|
|
6
|
+
import { Blueprint } from '@dxos/blueprints';
|
|
7
|
+
import { Obj, Ref } from '@dxos/echo';
|
|
8
|
+
import { DataType } from '@dxos/schema';
|
|
9
|
+
import { trim } from '@dxos/util';
|
|
10
|
+
|
|
11
|
+
import { Tasks } from '../../functions';
|
|
12
|
+
|
|
13
|
+
/**
|
|
14
|
+
* Agent prompt instructions for managing hierarchical task lists.
|
|
15
|
+
*/
|
|
16
|
+
const instructions = trim`
|
|
17
|
+
You are a task management agent that maintains hierarchical task lists where each line is a task.
|
|
18
|
+
|
|
19
|
+
## Document Format
|
|
20
|
+
You will receive task lists with line numbers prefixed like:
|
|
21
|
+
|
|
22
|
+
${'```'}
|
|
23
|
+
1. - [ ] First main task
|
|
24
|
+
2. - [ ] Subtask 1: Research phase
|
|
25
|
+
3. - [x] Literature review
|
|
26
|
+
4. - [ ] Stakeholder interviews
|
|
27
|
+
5. - [ ] Subtask 2: Implementation
|
|
28
|
+
6. - [ ] Setup infrastructure
|
|
29
|
+
7. - [ ] Write core functionality
|
|
30
|
+
8. - [ ] Another main task
|
|
31
|
+
${'```'}
|
|
32
|
+
|
|
33
|
+
## Task Hierarchy
|
|
34
|
+
- 0 spaces: Top-level tasks
|
|
35
|
+
- 2 spaces: First-level subtasks
|
|
36
|
+
- 4 spaces: Second-level subtasks
|
|
37
|
+
- 6 spaces: Third-level subtasks (and so on)
|
|
38
|
+
|
|
39
|
+
## Available Operations
|
|
40
|
+
You can modify the task list using these operations:
|
|
41
|
+
|
|
42
|
+
1. **insertTask(lineNumber, text, completed?, indent?)** - Insert a new task
|
|
43
|
+
2. **deleteTask(lineNumber)** - Delete a task
|
|
44
|
+
3. **updateTaskText(lineNumber, text)** - Change task description
|
|
45
|
+
4. **toggleTaskCompletion(lineNumber, completed?)** - Mark task complete/incomplete
|
|
46
|
+
5. **setTaskIndent(lineNumber, indent)** - Change task hierarchy level
|
|
47
|
+
|
|
48
|
+
## Examples
|
|
49
|
+
|
|
50
|
+
### Example 1: Adding a subtask
|
|
51
|
+
**User:** "Add a subtask 'Code review' under the task on line 1"
|
|
52
|
+
**Response:** \`insertTask(2, "Code review", false, 2)\`
|
|
53
|
+
|
|
54
|
+
### Example 2: Marking a task complete
|
|
55
|
+
**User:** "Mark the task on line 3 as complete"
|
|
56
|
+
**Response:** \`toggleTaskCompletion(3, true)\`
|
|
57
|
+
|
|
58
|
+
### Example 3: Updating task text
|
|
59
|
+
**User:** "Change the task on line 5 to 'Backend implementation'"
|
|
60
|
+
**Response:** \`updateTaskText(5, "Backend implementation")\`
|
|
61
|
+
|
|
62
|
+
### Example 4: Creating a task hierarchy
|
|
63
|
+
**User:** "Add a main task 'Testing phase' with two subtasks"
|
|
64
|
+
**Response:**
|
|
65
|
+
\`\`\`
|
|
66
|
+
insertTask(999, "Testing phase", false, 0)
|
|
67
|
+
insertTask(999, "Unit tests", false, 2)
|
|
68
|
+
insertTask(999, "Integration tests", false, 2)
|
|
69
|
+
\`\`\`
|
|
70
|
+
|
|
71
|
+
### Example 5: Reorganizing hierarchy
|
|
72
|
+
**User:** "Move the task on line 4 to be a main task (top level)"
|
|
73
|
+
**Response:** \`setTaskIndent(4, 0)\`
|
|
74
|
+
|
|
75
|
+
### Example 6: Adding nested subtasks
|
|
76
|
+
**User:** "Add a sub-subtask 'Write test cases' under line 6"
|
|
77
|
+
**Response:** \`insertTask(7, "Write test cases", false, 4)\`
|
|
78
|
+
|
|
79
|
+
## Guidelines
|
|
80
|
+
- Always reference line numbers from the numbered document you receive
|
|
81
|
+
- Use line number 999 to append to the end of the document
|
|
82
|
+
- Maintain logical hierarchy (subtasks should be indented under their parent)
|
|
83
|
+
- Use appropriate indentation levels (0, 2, 4, 6, etc. spaces)
|
|
84
|
+
- When creating subtasks, consider the parent task's completion status
|
|
85
|
+
- Be precise with task descriptions and hierarchy levels
|
|
86
|
+
`;
|
|
87
|
+
|
|
88
|
+
export const blueprint: Blueprint.Blueprint = Obj.make(Blueprint.Blueprint, {
|
|
89
|
+
key: 'dxos.org/blueprint/planning',
|
|
90
|
+
name: 'Planning',
|
|
91
|
+
description: 'Plans and tracks complex tasks with artifact management.',
|
|
92
|
+
instructions: {
|
|
93
|
+
source: Ref.make(DataType.makeText(instructions)),
|
|
94
|
+
},
|
|
95
|
+
tools: [Tasks.read, Tasks.update].map((fn) => ToolId.make(fn.key)),
|
|
96
|
+
});
|
|
97
|
+
|
|
98
|
+
export default blueprint;
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
//
|
|
2
|
+
// Copyright 2025 DXOS.org
|
|
3
|
+
//
|
|
4
|
+
|
|
5
|
+
import { ToolId } from '@dxos/ai';
|
|
6
|
+
import { Blueprint } from '@dxos/blueprints';
|
|
7
|
+
import { Obj, Ref } from '@dxos/echo';
|
|
8
|
+
import { DataType } from '@dxos/schema';
|
|
9
|
+
import { trim } from '@dxos/util';
|
|
10
|
+
|
|
11
|
+
import { Research } from '../../functions';
|
|
12
|
+
|
|
13
|
+
/**
|
|
14
|
+
* Agent prompt instructions for managing hierarchical task lists.
|
|
15
|
+
*/
|
|
16
|
+
const instructions = trim`
|
|
17
|
+
{{! Research }}
|
|
18
|
+
|
|
19
|
+
You are an analyst that does research tasks using tools that scrape the web and create structured data.
|
|
20
|
+
The result of the research is a set of structured entities forming an interconnected graph.
|
|
21
|
+
When you are done, reply with the created objects.
|
|
22
|
+
Do not print the data, instead reply with inline references to the created objects.
|
|
23
|
+
Those will be later substituted with the pills representing the created objects.
|
|
24
|
+
Print the rest of the created objects as block references after the main note.
|
|
25
|
+
|
|
26
|
+
<example>
|
|
27
|
+
Based on my research, Google was founded by @dxn:queue:data:B6INSIBY3CBEF4M5VZRYBCMAHQMPYK5AJ:01K24XMVHSZHS97SG1VTVQDM5Z:01K24XPK464FSCKVQJAB2H662M and @dxn:queue:data:B6INSIBY3CBEF4M5VZRYBCMAHQMPYK5AJ:01K24XMVHSZHS97SG1VTVQDM5Z:01K24XPK46K31DDW62PBW9H2ZQ
|
|
28
|
+
|
|
29
|
+
<object><dxn>dxn:queue:data:B6INSIBY3CBEF4M5VZRYBCMAHQMPYK5AJ:01K24XMVHSZHS97SG1VTVQDM5Z:01K24XPK464FSCKVQJAB2H662M</dxn></object>
|
|
30
|
+
<object><dxn>dxn:queue:data:B6INSIBY3CBEF4M5VZRYBCMAHQMPYK5AJ:01K24XMVHSZHS97SG1VTVQDM5Z:01K24XPK46K31DDW62PBW9H2ZQ</dxn></object>
|
|
31
|
+
<object><dxn>dxn:queue:data:B6INSIBY3CBEF4M5VZRYBCMAHQMPYK5AJ:01K24XMVHSZHS97SG1VTVQDM5Z:01K24XPK46K31DDW62PBW92333</dxn></object>
|
|
32
|
+
</example>
|
|
33
|
+
`;
|
|
34
|
+
|
|
35
|
+
export const blueprint: Blueprint.Blueprint = Obj.make(Blueprint.Blueprint, {
|
|
36
|
+
key: 'dxos.org/blueprint/research',
|
|
37
|
+
name: 'Research',
|
|
38
|
+
description: 'Researches the web and creates structured data.',
|
|
39
|
+
instructions: {
|
|
40
|
+
source: Ref.make(DataType.makeText(instructions)),
|
|
41
|
+
},
|
|
42
|
+
tools: [Research.create, Research.research].map((fn) => ToolId.make(fn.key)),
|
|
43
|
+
});
|
|
44
|
+
|
|
45
|
+
export default blueprint;
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
//
|
|
2
|
+
// Copyright 2025 DXOS.org
|
|
3
|
+
//
|
|
4
|
+
|
|
5
|
+
import * as Toolkit from '@effect/ai/Toolkit';
|
|
6
|
+
import * as Effect from 'effect/Effect';
|
|
7
|
+
|
|
8
|
+
import { ConsolePrinter } from '@dxos/ai';
|
|
9
|
+
import { type AiConversation, type AiConversationRunParams, GenerationObserver } from '@dxos/assistant';
|
|
10
|
+
import { log } from '@dxos/log';
|
|
11
|
+
|
|
12
|
+
export type TestStep = Pick<AiConversationRunParams, 'prompt' | 'system'> & {
|
|
13
|
+
test?: () => Promise<void>;
|
|
14
|
+
};
|
|
15
|
+
|
|
16
|
+
/**
|
|
17
|
+
* Runs the prompt steps, calling the test function after each step.
|
|
18
|
+
*/
|
|
19
|
+
export const runSteps = Effect.fn(function* (conversation: AiConversation, steps: TestStep[]) {
|
|
20
|
+
for (const { test, ...props } of steps) {
|
|
21
|
+
yield* conversation.createRequest({
|
|
22
|
+
...props,
|
|
23
|
+
observer: GenerationObserver.fromPrinter(new ConsolePrinter({ mode: 'json' })),
|
|
24
|
+
});
|
|
25
|
+
const messages = yield* Effect.promise(() => conversation.getHistory());
|
|
26
|
+
log.info('conversation', { messages });
|
|
27
|
+
if (test) {
|
|
28
|
+
yield* Effect.promise(() => test());
|
|
29
|
+
}
|
|
30
|
+
}
|
|
31
|
+
});
|
|
32
|
+
|
|
33
|
+
// TODO(wittjosiah): Don't cast.
|
|
34
|
+
export const testToolkit = Toolkit.empty as Toolkit.Toolkit<any>;
|