@dxos/assistant 0.8.3 → 0.8.4-main.2e9d522
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/lib/browser/index.mjs +760 -1087
- package/dist/lib/browser/index.mjs.map +4 -4
- package/dist/lib/browser/meta.json +1 -1
- package/dist/lib/node-esm/index.mjs +760 -1087
- package/dist/lib/node-esm/index.mjs.map +4 -4
- package/dist/lib/node-esm/meta.json +1 -1
- package/dist/types/src/context/binder.d.ts +34 -0
- package/dist/types/src/context/binder.d.ts.map +1 -0
- package/dist/types/src/context/binding.d.ts +56 -0
- package/dist/types/src/context/binding.d.ts.map +1 -0
- package/dist/types/src/context/index.d.ts +3 -0
- package/dist/types/src/context/index.d.ts.map +1 -0
- package/dist/types/src/conversation/conversation.d.ts +38 -0
- package/dist/types/src/conversation/conversation.d.ts.map +1 -0
- package/dist/types/src/conversation/index.d.ts +2 -0
- package/dist/types/src/conversation/index.d.ts.map +1 -0
- package/dist/types/src/errors.d.ts +38 -0
- package/dist/types/src/errors.d.ts.map +1 -0
- package/dist/types/src/extraction/extraction-llm-function/extraction-llm-function.d.ts.map +1 -1
- package/dist/types/src/extraction/extraction-ner-function/extraction-ner-function.d.ts +135 -41
- package/dist/types/src/extraction/extraction-ner-function/extraction-ner-function.d.ts.map +1 -1
- package/dist/types/src/extraction/extraction-ner-function/named-entity-recognition.d.ts +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 +100 -42
- package/dist/types/src/extraction/extraction.d.ts.map +1 -1
- package/dist/types/src/functions/index.d.ts +2 -0
- package/dist/types/src/functions/index.d.ts.map +1 -0
- package/dist/types/src/functions/services.d.ts +6 -0
- package/dist/types/src/functions/services.d.ts.map +1 -0
- package/dist/types/src/index.d.ts +4 -1
- package/dist/types/src/index.d.ts.map +1 -1
- package/dist/types/src/research/exa.d.ts +10 -5
- package/dist/types/src/research/exa.d.ts.map +1 -1
- package/dist/types/src/research/graph.d.ts +18 -8
- package/dist/types/src/research/graph.d.ts.map +1 -1
- package/dist/types/src/research/research.d.ts +1 -1
- package/dist/types/src/research/research.d.ts.map +1 -1
- package/dist/types/src/session/session.d.ts +183 -184
- package/dist/types/src/session/session.d.ts.map +1 -1
- package/dist/types/src/session/version-pin.d.ts +2 -2
- package/dist/types/src/session/version-pin.d.ts.map +1 -1
- package/dist/types/src/templates/index.d.ts +2 -0
- package/dist/types/src/templates/index.d.ts.map +1 -0
- package/dist/types/src/templates/prompt.d.ts +30 -0
- package/dist/types/src/templates/prompt.d.ts.map +1 -0
- package/dist/types/src/types.d.ts +10 -0
- package/dist/types/src/types.d.ts.map +1 -1
- package/dist/types/tsconfig.tsbuildinfo +1 -1
- package/package.json +29 -30
- package/src/context/binder.ts +103 -0
- package/src/context/binding.ts +32 -0
- package/src/context/index.ts +6 -0
- package/src/conversation/conversation.ts +96 -0
- package/src/conversation/index.ts +5 -0
- package/src/errors.ts +10 -0
- package/src/extraction/extraction-llm-function/extraction-llm-function.test.ts +6 -18
- package/src/extraction/extraction-llm-function/extraction-llm-function.ts +19 -14
- package/src/extraction/extraction-ner-function/extraction-ner-function.ts +6 -3
- package/src/extraction/extraction-ner-function/named-entity-recognition.test.ts +2 -2
- package/src/extraction/extraction-ner-function/named-entity-recognition.ts +1 -1
- package/src/functions/index.ts +5 -0
- package/src/functions/services.ts +139 -0
- package/src/index.ts +4 -1
- package/src/research/exa.ts +56 -59
- package/src/research/graph.test.ts +50 -1
- package/src/research/graph.ts +85 -53
- package/src/research/instructions-research.tpl +1 -0
- package/src/research/research.test.ts +27 -27
- package/src/research/research.ts +50 -52
- package/src/session/__snapshots__/session.test.ts.snap +32 -0
- package/src/session/session.test.ts +99 -18
- package/src/session/session.ts +230 -443
- package/src/session/version-pin.test.ts +2 -21
- package/src/session/version-pin.ts +5 -5
- package/src/summarization/summarization.test.ts +75 -88
- package/src/templates/assistant.tpl +111 -0
- package/src/templates/index.ts +5 -0
- package/src/templates/prompt.ts +45 -0
- package/src/types.ts +40 -1
- package/dist/lib/node/index.cjs +0 -2178
- package/dist/lib/node/index.cjs.map +0 -7
- package/dist/lib/node/meta.json +0 -1
- package/dist/types/src/blueprint/ai.test.d.ts +0 -2
- package/dist/types/src/blueprint/ai.test.d.ts.map +0 -1
- package/dist/types/src/blueprint/blueprint.d.ts +0 -55
- package/dist/types/src/blueprint/blueprint.d.ts.map +0 -1
- package/dist/types/src/blueprint/blueprint.test.d.ts +0 -2
- package/dist/types/src/blueprint/blueprint.test.d.ts.map +0 -1
- package/dist/types/src/blueprint/index.d.ts +0 -4
- package/dist/types/src/blueprint/index.d.ts.map +0 -1
- package/dist/types/src/blueprint/logger.d.ts +0 -25
- package/dist/types/src/blueprint/logger.d.ts.map +0 -1
- package/dist/types/src/blueprint/machine.d.ts +0 -143
- package/dist/types/src/blueprint/machine.d.ts.map +0 -1
- package/dist/types/src/blueprint/test-data.d.ts +0 -3
- package/dist/types/src/blueprint/test-data.d.ts.map +0 -1
- package/src/blueprint/ai.test.ts +0 -156
- package/src/blueprint/blueprint.test.ts +0 -151
- package/src/blueprint/blueprint.ts +0 -75
- package/src/blueprint/index.ts +0 -7
- package/src/blueprint/logger.ts +0 -155
- package/src/blueprint/machine.ts +0 -251
- package/src/blueprint/test-data.ts +0 -55
|
@@ -1,514 +1,296 @@
|
|
|
1
1
|
import { createRequire } from 'node:module';const require = createRequire(import.meta.url);
|
|
2
2
|
|
|
3
|
-
//
|
|
3
|
+
// src/context/binder.ts
|
|
4
|
+
import { computed } from "@preact/signals-core";
|
|
5
|
+
import { Array as Array2, pipe } from "effect";
|
|
6
|
+
import { Obj } from "@dxos/echo";
|
|
7
|
+
import { ComplexSet } from "@dxos/util";
|
|
8
|
+
|
|
9
|
+
// src/context/binding.ts
|
|
4
10
|
import { Schema } from "effect";
|
|
5
|
-
import {
|
|
6
|
-
import {
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
})
|
|
17
|
-
})
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
11
|
+
import { Blueprint } from "@dxos/blueprints";
|
|
12
|
+
import { Type } from "@dxos/echo";
|
|
13
|
+
var ContextBinding = Schema.Struct({
|
|
14
|
+
blueprints: Schema.Struct({
|
|
15
|
+
added: Schema.Array(Type.Ref(Blueprint.Blueprint)),
|
|
16
|
+
removed: Schema.Array(Type.Ref(Blueprint.Blueprint))
|
|
17
|
+
}),
|
|
18
|
+
// TODO(burdon): Type.Expando => Type.Obj (or Obj.Any?)
|
|
19
|
+
objects: Schema.Struct({
|
|
20
|
+
added: Schema.Array(Type.Ref(Type.Expando)),
|
|
21
|
+
removed: Schema.Array(Type.Ref(Type.Expando))
|
|
22
|
+
})
|
|
23
|
+
}).pipe(Type.Obj({
|
|
24
|
+
typename: "dxos.org/type/ContextBinding",
|
|
25
|
+
version: "0.1.0"
|
|
26
|
+
}));
|
|
27
|
+
|
|
28
|
+
// src/context/binder.ts
|
|
29
|
+
var ContextBinder = class {
|
|
30
|
+
constructor(_queue) {
|
|
31
|
+
this._queue = _queue;
|
|
32
|
+
this.bindings = computed(() => this._reduce(this._queue.objects));
|
|
33
|
+
this.blueprints = computed(() => [
|
|
34
|
+
...this.bindings.value.blueprints
|
|
35
|
+
]);
|
|
36
|
+
this.objects = computed(() => [
|
|
37
|
+
...this.bindings.value.objects
|
|
38
|
+
]);
|
|
39
|
+
}
|
|
40
|
+
/**
|
|
41
|
+
* Asynchronous query of all bindings.
|
|
42
|
+
*/
|
|
43
|
+
async query() {
|
|
44
|
+
const queueItems = await this._queue.queryObjects();
|
|
45
|
+
return this._reduce(queueItems);
|
|
46
|
+
}
|
|
47
|
+
// TODO(burdon): Pass in Blueprint obj (from registry?) and create reference.
|
|
48
|
+
async bind(props) {
|
|
49
|
+
if (!props.blueprints?.length && !props.objects?.length) {
|
|
50
|
+
return;
|
|
28
51
|
}
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
52
|
+
await this._queue.append([
|
|
53
|
+
Obj.make(ContextBinding, {
|
|
54
|
+
blueprints: {
|
|
55
|
+
added: props.blueprints ?? [],
|
|
56
|
+
removed: []
|
|
57
|
+
},
|
|
58
|
+
objects: {
|
|
59
|
+
added: props.objects ?? [],
|
|
60
|
+
removed: []
|
|
61
|
+
}
|
|
62
|
+
})
|
|
63
|
+
]);
|
|
64
|
+
}
|
|
65
|
+
async unbind(props) {
|
|
66
|
+
if (!props.blueprints?.length && !props.objects?.length) {
|
|
67
|
+
return;
|
|
45
68
|
}
|
|
69
|
+
await this._queue.append([
|
|
70
|
+
Obj.make(ContextBinding, {
|
|
71
|
+
blueprints: {
|
|
72
|
+
added: [],
|
|
73
|
+
removed: props.blueprints ?? []
|
|
74
|
+
},
|
|
75
|
+
objects: {
|
|
76
|
+
added: [],
|
|
77
|
+
removed: props.objects ?? []
|
|
78
|
+
}
|
|
79
|
+
})
|
|
80
|
+
]);
|
|
81
|
+
}
|
|
82
|
+
_reduce(items) {
|
|
83
|
+
return pipe(items, Array2.filter(Obj.instanceOf(ContextBinding)), Array2.reduce(new Bindings(), (context, item) => {
|
|
84
|
+
item.blueprints.removed.forEach((item2) => context.blueprints.delete(item2));
|
|
85
|
+
item.blueprints.added.forEach((item2) => context.blueprints.add(item2));
|
|
86
|
+
item.objects.removed.forEach((item2) => context.objects.delete(item2));
|
|
87
|
+
item.objects.added.forEach((item2) => context.objects.add(item2));
|
|
88
|
+
return context;
|
|
89
|
+
}));
|
|
90
|
+
}
|
|
91
|
+
};
|
|
92
|
+
var Bindings = class {
|
|
93
|
+
constructor() {
|
|
94
|
+
this.blueprints = new ComplexSet((ref) => ref.dxn.toString());
|
|
95
|
+
this.objects = new ComplexSet((ref) => ref.dxn.toString());
|
|
46
96
|
}
|
|
47
97
|
};
|
|
48
98
|
|
|
49
|
-
//
|
|
50
|
-
import {
|
|
51
|
-
import {
|
|
52
|
-
import {
|
|
53
|
-
import {
|
|
99
|
+
// src/conversation/conversation.ts
|
|
100
|
+
import { Effect as Effect2 } from "effect";
|
|
101
|
+
import { Event as Event2 } from "@dxos/async";
|
|
102
|
+
import { Obj as Obj3 } from "@dxos/echo";
|
|
103
|
+
import { DatabaseService as DatabaseService2 } from "@dxos/functions";
|
|
54
104
|
import { DataType as DataType2 } from "@dxos/schema";
|
|
55
105
|
|
|
56
|
-
//
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
import {
|
|
61
|
-
import {
|
|
62
|
-
import {
|
|
63
|
-
import { Obj } from "@dxos/echo";
|
|
106
|
+
// src/session/session.ts
|
|
107
|
+
import { AiLanguageModel, AiToolkit } from "@effect/ai";
|
|
108
|
+
import { Chunk, Context, Effect, Option, pipe as pipe2, Stream } from "effect";
|
|
109
|
+
import { Array as Array3, String } from "effect";
|
|
110
|
+
import { AiParser, AiPreprocessor, getToolCalls, runTool, ToolExecutionService, ToolResolverService } from "@dxos/ai";
|
|
111
|
+
import { Event } from "@dxos/async";
|
|
112
|
+
import { todo } from "@dxos/debug";
|
|
113
|
+
import { Obj as Obj2 } from "@dxos/echo";
|
|
64
114
|
import { ObjectVersion } from "@dxos/echo-db";
|
|
65
|
-
import {
|
|
66
|
-
import {
|
|
67
|
-
import {
|
|
115
|
+
import { DatabaseService } from "@dxos/functions";
|
|
116
|
+
import { log } from "@dxos/log";
|
|
117
|
+
import { DataType } from "@dxos/schema";
|
|
68
118
|
|
|
69
|
-
//
|
|
70
|
-
import {
|
|
71
|
-
|
|
72
|
-
import { ObjectId } from "@dxos/echo-schema";
|
|
73
|
-
var ObjectVersionSchema = Schema2.Unknown;
|
|
74
|
-
var VersionPinSchema = Schema2.Struct({
|
|
75
|
-
// TODO(dmaretskyi): Use Ref when those support encoding.
|
|
76
|
-
objectId: ObjectId,
|
|
77
|
-
// TODO(dmaretskyi): Could be opaque
|
|
78
|
-
version: ObjectVersionSchema
|
|
79
|
-
});
|
|
80
|
-
var VersionPin = class extends VersionPinSchema {
|
|
81
|
-
static {
|
|
82
|
-
this.DISPOSITION = "version-pin";
|
|
83
|
-
}
|
|
84
|
-
static fromObject(object) {
|
|
85
|
-
return VersionPin.make({
|
|
86
|
-
objectId: object.id,
|
|
87
|
-
version: getVersion(object)
|
|
88
|
-
});
|
|
89
|
-
}
|
|
90
|
-
static createBlock(pin) {
|
|
91
|
-
return {
|
|
92
|
-
type: "json",
|
|
93
|
-
disposition: VersionPin.DISPOSITION,
|
|
94
|
-
json: JSON.stringify(pin)
|
|
95
|
-
};
|
|
96
|
-
}
|
|
119
|
+
// src/errors.ts
|
|
120
|
+
import { BaseError } from "@dxos/errors";
|
|
121
|
+
var AiAssistantError = class extends BaseError.extend("AI_ASSISTANT_ERROR") {
|
|
97
122
|
};
|
|
98
123
|
|
|
99
|
-
//
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
|
|
104
|
-
return c > 3 && r && Object.defineProperty(target, key, r), r;
|
|
105
|
-
}
|
|
106
|
-
var __dxlog_file2 = "/home/runner/work/dxos/dxos/packages/core/assistant/src/session/session.ts";
|
|
107
|
-
var AISession = class _AISession {
|
|
108
|
-
constructor(_options) {
|
|
124
|
+
// src/session/session.ts
|
|
125
|
+
var __dxlog_file = "/__w/dxos/dxos/packages/core/assistant/src/session/session.ts";
|
|
126
|
+
var AiSession = class {
|
|
127
|
+
constructor(_options = {}) {
|
|
109
128
|
this._options = _options;
|
|
110
|
-
this.
|
|
129
|
+
this._semaphore = Effect.runSync(Effect.makeSemaphore(1));
|
|
111
130
|
this._pending = [];
|
|
112
131
|
this._history = [];
|
|
113
|
-
this.message =
|
|
114
|
-
this.block =
|
|
115
|
-
this.update =
|
|
116
|
-
this.streamEvent =
|
|
132
|
+
this.message = new Event();
|
|
133
|
+
this.block = new Event();
|
|
134
|
+
this.update = new Event();
|
|
135
|
+
this.streamEvent = new Event();
|
|
117
136
|
this.userMessage = new Event();
|
|
118
137
|
this.statusReport = new Event();
|
|
119
|
-
this.
|
|
120
|
-
this.
|
|
121
|
-
this.
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
});
|
|
130
|
-
}
|
|
131
|
-
async run(options) {
|
|
132
|
-
const systemTools = [];
|
|
133
|
-
switch (this._options.operationModel) {
|
|
134
|
-
case "planning":
|
|
135
|
-
systemTools.push(this._createQueryArtifactsTool(options.artifacts), this._createPlanningTool(options));
|
|
136
|
-
break;
|
|
137
|
-
case "importing":
|
|
138
|
-
systemTools.push(this._createQueryArtifactsTool(options.artifacts), this._createRequireTool(options.artifacts, (artifactDefinitionIds) => {
|
|
139
|
-
for (const artifactDefinitionId of artifactDefinitionIds) {
|
|
140
|
-
requiredArtifactIds.add(artifactDefinitionId);
|
|
141
|
-
}
|
|
142
|
-
}));
|
|
143
|
-
break;
|
|
144
|
-
case "configured":
|
|
145
|
-
break;
|
|
146
|
-
default:
|
|
147
|
-
throw new TypeError(`Invalid operation model: ${this._options.operationModel}`);
|
|
148
|
-
}
|
|
149
|
-
this._history = [
|
|
150
|
-
...options.history
|
|
151
|
-
];
|
|
152
|
-
this._pending = [
|
|
153
|
-
await this._formatUserPrompt(options.artifactDiffResolver, options.prompt, options.history)
|
|
154
|
-
];
|
|
155
|
-
this.userMessage.emit(this._pending.at(-1));
|
|
156
|
-
this._stream = void 0;
|
|
157
|
-
let error;
|
|
158
|
-
const requiredArtifactIds = new Set(options.requiredArtifactIds ?? []);
|
|
159
|
-
try {
|
|
160
|
-
let more = false;
|
|
138
|
+
this.done = new Event();
|
|
139
|
+
this.run = (options) => Effect.gen(this, function* () {
|
|
140
|
+
this._history = [
|
|
141
|
+
...options.history
|
|
142
|
+
];
|
|
143
|
+
const promptMessages = yield* this._formatUserPrompt(options.prompt, options.history);
|
|
144
|
+
this._pending = [
|
|
145
|
+
promptMessages
|
|
146
|
+
];
|
|
147
|
+
this.userMessage.emit(promptMessages);
|
|
161
148
|
do {
|
|
162
|
-
|
|
163
|
-
...systemTools,
|
|
164
|
-
...options.tools,
|
|
165
|
-
...options.artifacts.filter((artifact) => requiredArtifactIds.has(artifact.id)).flatMap((artifact) => artifact.tools)
|
|
166
|
-
];
|
|
167
|
-
log2("request", {
|
|
149
|
+
log("request", {
|
|
168
150
|
pending: this._pending.length,
|
|
169
151
|
history: this._history.length,
|
|
170
|
-
tools: tools.map((tool) => tool.name)
|
|
152
|
+
tools: Object.values(options.toolkit?.tools ?? {}).map((tool) => tool.name)
|
|
171
153
|
}, {
|
|
172
|
-
F:
|
|
173
|
-
L:
|
|
154
|
+
F: __dxlog_file,
|
|
155
|
+
L: 126,
|
|
174
156
|
S: this,
|
|
175
157
|
C: (f, a) => f(...a)
|
|
176
158
|
});
|
|
177
|
-
|
|
178
|
-
...
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
159
|
+
const prompt = yield* AiPreprocessor.preprocessAiInput([
|
|
160
|
+
...this._history,
|
|
161
|
+
...this._pending
|
|
162
|
+
]);
|
|
163
|
+
const blueprints = options.blueprints ?? [];
|
|
164
|
+
const systemPrompt = yield* pipe2(blueprints, Effect.forEach((blueprint) => DatabaseService.loadRef(blueprint.instructions)), Effect.flatMap(Effect.forEach((template) => DatabaseService.loadRef(template.source))), Effect.map(Array3.map((template) => `
|
|
165
|
+
|
|
166
|
+
<blueprint>${template.content}</blueprint>`)), Effect.map(Array3.reduce(options.systemPrompt ?? "", String.concat)));
|
|
167
|
+
const blueprintToolkit = yield* ToolResolverService.resolveToolkit(blueprints.flatMap((bp) => bp.tools));
|
|
168
|
+
const blueprintToolkitHandler = yield* blueprintToolkit.toContext(yield* ToolExecutionService.handlersFor(blueprintToolkit));
|
|
169
|
+
const toolkit = options.toolkit != null ? AiToolkit.merge(options.toolkit, blueprintToolkit) : blueprintToolkit;
|
|
170
|
+
const toolkitWithBlueprintHandlers = yield* toolkit.pipe(Effect.provide(blueprintToolkitHandler));
|
|
171
|
+
log.info("run", {
|
|
172
|
+
systemPrompt: [
|
|
173
|
+
systemPrompt.slice(0, 32),
|
|
174
|
+
"...",
|
|
175
|
+
systemPrompt.slice(-32),
|
|
176
|
+
systemPrompt.length
|
|
177
|
+
].join(" "),
|
|
178
|
+
tools: Object.keys(blueprintToolkit.tools)
|
|
194
179
|
}, {
|
|
195
|
-
F:
|
|
196
|
-
L:
|
|
180
|
+
F: __dxlog_file,
|
|
181
|
+
L: 155,
|
|
197
182
|
S: this,
|
|
198
183
|
C: (f, a) => f(...a)
|
|
199
184
|
});
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
if (isToolUse(message)) {
|
|
212
|
-
log2("tool request...", void 0, {
|
|
213
|
-
F: __dxlog_file2,
|
|
214
|
-
L: 233,
|
|
215
|
-
S: this,
|
|
216
|
-
C: (f, a) => f(...a)
|
|
217
|
-
});
|
|
218
|
-
const response = await runTools({
|
|
219
|
-
message: this._pending.at(-1),
|
|
220
|
-
tools,
|
|
221
|
-
extensions: options.extensions ?? {},
|
|
222
|
-
reportStatus: (status) => this._onToolStatusReport(message, status)
|
|
223
|
-
});
|
|
224
|
-
log2("tool response", {
|
|
225
|
-
response
|
|
226
|
-
}, {
|
|
227
|
-
F: __dxlog_file2,
|
|
228
|
-
L: 241,
|
|
229
|
-
S: this,
|
|
230
|
-
C: (f, a) => f(...a)
|
|
231
|
-
});
|
|
232
|
-
switch (response.type) {
|
|
233
|
-
case "continue": {
|
|
234
|
-
this._pending = [
|
|
235
|
-
...this._pending,
|
|
236
|
-
response.message
|
|
237
|
-
];
|
|
238
|
-
this.userMessage.emit(response.message);
|
|
239
|
-
more = true;
|
|
240
|
-
break;
|
|
185
|
+
const blocks = yield* AiLanguageModel.streamText({
|
|
186
|
+
prompt,
|
|
187
|
+
system: systemPrompt,
|
|
188
|
+
toolkit: toolkitWithBlueprintHandlers,
|
|
189
|
+
disableToolCallResolution: true
|
|
190
|
+
}).pipe(AiParser.parseGptStream({
|
|
191
|
+
onBlock: (block) => Effect.gen(this, function* () {
|
|
192
|
+
if (block.pending) {
|
|
193
|
+
this.update.emit(block);
|
|
194
|
+
} else {
|
|
195
|
+
this.block.emit(block);
|
|
241
196
|
}
|
|
242
|
-
}
|
|
243
|
-
}
|
|
244
|
-
} while (more);
|
|
245
|
-
} catch (err) {
|
|
246
|
-
log2.catch(err, void 0, {
|
|
247
|
-
F: __dxlog_file2,
|
|
248
|
-
L: 253,
|
|
249
|
-
S: this,
|
|
250
|
-
C: (f, a) => f(...a)
|
|
251
|
-
});
|
|
252
|
-
if (err instanceof Error && err.message.includes("Overloaded")) {
|
|
253
|
-
error = new AIServiecOverloadedError("AI service overloaded", {
|
|
254
|
-
cause: err
|
|
255
|
-
});
|
|
256
|
-
} else {
|
|
257
|
-
error = new Error("AI service error", {
|
|
258
|
-
cause: err
|
|
259
|
-
});
|
|
260
|
-
}
|
|
261
|
-
} finally {
|
|
262
|
-
this._stream = void 0;
|
|
263
|
-
}
|
|
264
|
-
if (error) {
|
|
265
|
-
throw error;
|
|
266
|
-
}
|
|
267
|
-
return this._pending;
|
|
268
|
-
}
|
|
269
|
-
async runStructured(schema, options) {
|
|
270
|
-
const parser = structuredOutputParser(schema);
|
|
271
|
-
const result = await this.run({
|
|
272
|
-
...options,
|
|
273
|
-
tools: [
|
|
274
|
-
...options.tools,
|
|
275
|
-
parser.tool
|
|
276
|
-
]
|
|
277
|
-
});
|
|
278
|
-
return parser.getResult(result);
|
|
279
|
-
}
|
|
280
|
-
async _formatUserPrompt(artifactDiffResolver, prompt, history) {
|
|
281
|
-
const prelude = [];
|
|
282
|
-
if (artifactDiffResolver) {
|
|
283
|
-
const versions = gatherObjectVersions(history);
|
|
284
|
-
const artifactDiff = await artifactDiffResolver(Array.from(versions.entries()).map(([id, version]) => ({
|
|
285
|
-
id,
|
|
286
|
-
lastVersion: version
|
|
287
|
-
})));
|
|
288
|
-
log2.info("vision", {
|
|
289
|
-
artifactDiff,
|
|
290
|
-
versions
|
|
291
|
-
}, {
|
|
292
|
-
F: __dxlog_file2,
|
|
293
|
-
L: 296,
|
|
294
|
-
S: this,
|
|
295
|
-
C: (f, a) => f(...a)
|
|
296
|
-
});
|
|
297
|
-
for (const [id, { version }] of [
|
|
298
|
-
...artifactDiff.entries()
|
|
299
|
-
]) {
|
|
300
|
-
if (ObjectVersion.equals(version, versions.get(id))) {
|
|
301
|
-
artifactDiff.delete(id);
|
|
302
|
-
continue;
|
|
303
|
-
}
|
|
304
|
-
prelude.push(VersionPin.createBlock(VersionPin.make({
|
|
305
|
-
objectId: id,
|
|
306
|
-
version
|
|
307
|
-
})));
|
|
308
|
-
}
|
|
309
|
-
if (artifactDiff.size > 0) {
|
|
310
|
-
prelude.push(createArtifactUpdateBlock(artifactDiff));
|
|
311
|
-
}
|
|
312
|
-
}
|
|
313
|
-
return Obj.make(Message, {
|
|
314
|
-
role: "user",
|
|
315
|
-
content: [
|
|
316
|
-
...prelude,
|
|
317
|
-
{
|
|
318
|
-
type: "text",
|
|
319
|
-
text: prompt
|
|
320
|
-
}
|
|
321
|
-
]
|
|
322
|
-
});
|
|
323
|
-
}
|
|
324
|
-
_createQueryArtifactsTool(artifacts) {
|
|
325
|
-
return createTool("system", {
|
|
326
|
-
name: "query_artifact_definitions",
|
|
327
|
-
description: "Query the available artifact definitions",
|
|
328
|
-
schema: Schema3.Struct({}),
|
|
329
|
-
execute: async () => {
|
|
330
|
-
return ToolResult.Success({
|
|
331
|
-
artifactDefinitions: artifacts.map((artifact) => ({
|
|
332
|
-
id: artifact.id,
|
|
333
|
-
name: artifact.name,
|
|
334
|
-
description: artifact.description
|
|
335
|
-
}))
|
|
336
|
-
});
|
|
337
|
-
}
|
|
338
|
-
});
|
|
339
|
-
}
|
|
340
|
-
_createRequireTool(artifacts, onRequire) {
|
|
341
|
-
return createTool("system", {
|
|
342
|
-
name: "require_artifact_definitions",
|
|
343
|
-
description: "Require the use of specific artifact definitions. This will allow the model to interact with artifact definitions and use their tools.",
|
|
344
|
-
schema: Schema3.Struct({
|
|
345
|
-
artifactDefinitionIds: Schema3.Array(Schema3.String).annotations({
|
|
346
|
-
description: "The ids of the artifact definitions to require",
|
|
347
|
-
examples: [
|
|
348
|
-
[
|
|
349
|
-
"artifact:dxos.org/example/Test"
|
|
350
|
-
]
|
|
351
|
-
]
|
|
352
|
-
})
|
|
353
|
-
}),
|
|
354
|
-
execute: async ({ artifactDefinitionIds }) => {
|
|
355
|
-
const missingArtifactDefinitionIds = artifactDefinitionIds.filter((artifactId) => !artifacts.some((artifact) => artifact.id === artifactId));
|
|
356
|
-
if (missingArtifactDefinitionIds.length > 0) {
|
|
357
|
-
return ToolResult.Error(`One or more artifact definition ids are invalid: ${missingArtifactDefinitionIds.join(", ")}`);
|
|
358
|
-
}
|
|
359
|
-
onRequire(artifactDefinitionIds);
|
|
360
|
-
return ToolResult.Success({});
|
|
361
|
-
}
|
|
362
|
-
});
|
|
363
|
-
}
|
|
364
|
-
_createPlanningTool(options) {
|
|
365
|
-
return createTool("system", {
|
|
366
|
-
name: "create_plan",
|
|
367
|
-
description: "Create a plan. Make sure that each step is independent and can be executed solely on the data returned by the previous step. The steps only share the data that is specified in the plan.",
|
|
368
|
-
schema: Schema3.Struct({
|
|
369
|
-
goal: Schema3.String.annotations({
|
|
370
|
-
description: "The goal that the plan will achieve."
|
|
371
|
-
}),
|
|
372
|
-
steps: Schema3.Array(Schema3.Struct({
|
|
373
|
-
action: Schema3.String.annotations({
|
|
374
|
-
description: "Complete, detailed action to perform."
|
|
375
|
-
}),
|
|
376
|
-
input: Schema3.String.annotations({
|
|
377
|
-
description: "The required input data for this step. First step must not require any data."
|
|
378
197
|
}),
|
|
379
|
-
|
|
380
|
-
|
|
381
|
-
}),
|
|
382
|
-
requiredArtifactIds: Schema3.Array(Schema3.String).annotations({
|
|
383
|
-
description: "The ids of the artifacts required to perform this step.",
|
|
384
|
-
examples: [
|
|
385
|
-
[
|
|
386
|
-
"artifact:dxos.org/example/Test"
|
|
387
|
-
]
|
|
388
|
-
]
|
|
198
|
+
onPart: (part) => Effect.gen(this, function* () {
|
|
199
|
+
this.streamEvent.emit(part);
|
|
389
200
|
})
|
|
390
|
-
})
|
|
391
|
-
|
|
392
|
-
|
|
393
|
-
|
|
394
|
-
|
|
395
|
-
|
|
396
|
-
|
|
397
|
-
|
|
201
|
+
}), Stream.runCollect, Effect.map(Chunk.toArray));
|
|
202
|
+
const response = Obj2.make(DataType.Message, {
|
|
203
|
+
created: (/* @__PURE__ */ new Date()).toISOString(),
|
|
204
|
+
sender: {
|
|
205
|
+
role: "assistant"
|
|
206
|
+
},
|
|
207
|
+
blocks
|
|
208
|
+
});
|
|
209
|
+
this._pending.push(response);
|
|
210
|
+
this.message.emit(response);
|
|
211
|
+
const toolCalls = getToolCalls(response);
|
|
212
|
+
if (toolCalls.length === 0) {
|
|
213
|
+
break;
|
|
398
214
|
}
|
|
399
|
-
const
|
|
400
|
-
|
|
401
|
-
|
|
402
|
-
|
|
403
|
-
|
|
404
|
-
|
|
405
|
-
|
|
406
|
-
|
|
407
|
-
|
|
408
|
-
|
|
409
|
-
|
|
410
|
-
|
|
411
|
-
|
|
412
|
-
|
|
413
|
-
|
|
414
|
-
|
|
415
|
-
|
|
416
|
-
|
|
417
|
-
|
|
418
|
-
|
|
419
|
-
|
|
420
|
-
|
|
421
|
-
|
|
422
|
-
|
|
423
|
-
|
|
424
|
-
|
|
425
|
-
|
|
426
|
-
|
|
427
|
-
|
|
428
|
-
|
|
429
|
-
|
|
430
|
-
|
|
431
|
-
|
|
432
|
-
|
|
433
|
-
|
|
434
|
-
|
|
435
|
-
|
|
436
|
-
|
|
437
|
-
|
|
438
|
-
|
|
439
|
-
|
|
440
|
-
|
|
441
|
-
|
|
442
|
-
|
|
443
|
-
|
|
215
|
+
const toolResults = yield* runTools(toolCalls, toolkitWithBlueprintHandlers);
|
|
216
|
+
this._pending.push(Obj2.make(DataType.Message, {
|
|
217
|
+
created: (/* @__PURE__ */ new Date()).toISOString(),
|
|
218
|
+
sender: {
|
|
219
|
+
role: "user"
|
|
220
|
+
},
|
|
221
|
+
blocks: toolResults
|
|
222
|
+
}));
|
|
223
|
+
} while (true);
|
|
224
|
+
return this._pending;
|
|
225
|
+
}).pipe(this._semaphore.withPermits(1), Effect.withSpan("AiSession.run"));
|
|
226
|
+
this._formatUserPrompt = (prompt, history) => Effect.gen(function* () {
|
|
227
|
+
const prelude = [];
|
|
228
|
+
const artifactDiffResolver = yield* Effect.serviceOption(ArtifactDiffResolver);
|
|
229
|
+
if (Option.isSome(artifactDiffResolver)) {
|
|
230
|
+
const versions = gatherObjectVersions(history);
|
|
231
|
+
const artifactDiff = yield* Effect.tryPromise({
|
|
232
|
+
try: () => artifactDiffResolver.value.resolve([
|
|
233
|
+
...versions.entries()
|
|
234
|
+
].map(([id, version]) => ({
|
|
235
|
+
id,
|
|
236
|
+
lastVersion: version
|
|
237
|
+
}))),
|
|
238
|
+
catch: AiAssistantError.wrap("Artifact diff resolution error")
|
|
239
|
+
});
|
|
240
|
+
log.info("vision", {
|
|
241
|
+
artifactDiff,
|
|
242
|
+
versions
|
|
243
|
+
}, {
|
|
244
|
+
F: __dxlog_file,
|
|
245
|
+
L: 240,
|
|
246
|
+
S: this,
|
|
247
|
+
C: (f, a) => f(...a)
|
|
248
|
+
});
|
|
249
|
+
for (const [id, { version }] of [
|
|
250
|
+
...artifactDiff.entries()
|
|
251
|
+
]) {
|
|
252
|
+
if (ObjectVersion.equals(version, versions.get(id))) {
|
|
253
|
+
artifactDiff.delete(id);
|
|
254
|
+
continue;
|
|
255
|
+
}
|
|
256
|
+
prelude.push({
|
|
257
|
+
_tag: "anchor",
|
|
258
|
+
objectId: id,
|
|
259
|
+
version
|
|
444
260
|
});
|
|
445
|
-
const result = messages.at(-1);
|
|
446
|
-
stepResults.push(result);
|
|
447
261
|
}
|
|
448
|
-
|
|
449
|
-
|
|
450
|
-
}
|
|
262
|
+
if (artifactDiff.size > 0) {
|
|
263
|
+
prelude.push(createArtifactUpdateBlock(artifactDiff));
|
|
264
|
+
}
|
|
451
265
|
}
|
|
266
|
+
return Obj2.make(DataType.Message, {
|
|
267
|
+
created: (/* @__PURE__ */ new Date()).toISOString(),
|
|
268
|
+
sender: {
|
|
269
|
+
role: "user"
|
|
270
|
+
},
|
|
271
|
+
blocks: [
|
|
272
|
+
...prelude,
|
|
273
|
+
{
|
|
274
|
+
_tag: "text",
|
|
275
|
+
text: prompt
|
|
276
|
+
}
|
|
277
|
+
]
|
|
278
|
+
});
|
|
452
279
|
});
|
|
453
280
|
}
|
|
454
|
-
|
|
455
|
-
|
|
456
|
-
message,
|
|
457
|
-
status
|
|
458
|
-
});
|
|
281
|
+
async runStructured(schema, options) {
|
|
282
|
+
return todo();
|
|
459
283
|
}
|
|
460
284
|
abort() {
|
|
461
285
|
this._stream?.abort();
|
|
462
286
|
}
|
|
463
287
|
};
|
|
464
|
-
_ts_decorate([
|
|
465
|
-
synchronized
|
|
466
|
-
], AISession.prototype, "run", null);
|
|
467
|
-
var createBaseInstructions = ({ availableArtifacts, operationModel }) => `
|
|
468
|
-
You are a friendly, advanced AI assistant capable of creating and managing artifacts from available data and tools.
|
|
469
|
-
Your task is to process user commands and questions and decide how best to respond.
|
|
470
|
-
In some cases, you will need to create or reference data objects called artifacts.
|
|
471
|
-
|
|
472
|
-
Follow these guidelines carefully:
|
|
473
|
-
|
|
474
|
-
Decision-making:
|
|
475
|
-
|
|
476
|
-
- Analyze the structure and type of the content in the user's message.
|
|
477
|
-
|
|
478
|
-
|
|
479
|
-
${operationModel === "planning" ? `
|
|
480
|
-
- Can you complete the task using the available artifacts?
|
|
481
|
-
- If you can't complete the task using the available artifacts, query the list of available artifacts using the appropriate tool.
|
|
482
|
-
- Identify which artifacts are relevant to the user's request.
|
|
483
|
-
- Break down the user's request into a step-by-step plan that you will use to execute the user's request, the plan items should include artifacts which will be used to perform the actions.
|
|
484
|
-
` : ""}
|
|
485
|
-
${operationModel === "importing" ? `
|
|
486
|
-
- Can you complete the task using the available artifacts?
|
|
487
|
-
- If you can't complete the task using the available artifacts, query the list of available artifacts using the appropriate tool.
|
|
488
|
-
- Identify which artifacts are relevant to the user's request.
|
|
489
|
-
- Are the required artifacts already available?
|
|
490
|
-
- If not, select which artifact(s) will be the most relevant and require them using the require_artifacts tool.
|
|
491
|
-
- The require'd artifact tools will be available for use after require.
|
|
492
|
-
` : ""}
|
|
493
|
-
${operationModel === "configured" ? `
|
|
494
|
-
- Select the most relevant artifact(s) to complete the task.
|
|
495
|
-
- Call the appropriate tool to use the artifact(s).
|
|
496
|
-
` : ""}
|
|
497
|
-
|
|
498
|
-
${availableArtifacts.length > 0 ? `Artifacts already in context: ${availableArtifacts.join("\n")}` : ""}
|
|
499
|
-
`;
|
|
500
|
-
var AIServiecOverloadedError = class extends Schema3.TaggedError()("AIServiecOverloadedError", {}) {
|
|
501
|
-
};
|
|
502
288
|
var gatherObjectVersions = (messages) => {
|
|
503
289
|
const artifactIds = /* @__PURE__ */ new Map();
|
|
504
290
|
for (const message of messages) {
|
|
505
|
-
for (const block of message.
|
|
506
|
-
if (block.
|
|
507
|
-
|
|
508
|
-
if (!pin) {
|
|
509
|
-
continue;
|
|
510
|
-
}
|
|
511
|
-
artifactIds.set(pin.objectId, pin.version);
|
|
291
|
+
for (const block of message.blocks) {
|
|
292
|
+
if (block._tag === "anchor") {
|
|
293
|
+
artifactIds.set(block.objectId, block.version);
|
|
512
294
|
}
|
|
513
295
|
}
|
|
514
296
|
}
|
|
@@ -516,23 +298,153 @@ var gatherObjectVersions = (messages) => {
|
|
|
516
298
|
};
|
|
517
299
|
var createArtifactUpdateBlock = (artifactDiff) => {
|
|
518
300
|
return {
|
|
519
|
-
|
|
301
|
+
_tag: "text",
|
|
302
|
+
// TODO(dmaretskyi): Does this need to be a special content-block?
|
|
520
303
|
disposition: "artifact-update",
|
|
521
304
|
text: `
|
|
522
305
|
The following artifacts have been updated since the last message:
|
|
523
|
-
${
|
|
306
|
+
${[
|
|
307
|
+
...artifactDiff.entries()
|
|
308
|
+
].map(([id, { diff }]) => `<changed-artifact id="${id}">${diff ? `
|
|
524
309
|
${diff}` : ""}</changed-artifact>`).join("\n")}
|
|
525
310
|
`
|
|
526
311
|
};
|
|
527
312
|
};
|
|
313
|
+
var ArtifactDiffResolver = class extends Context.Tag("ArtifactDiffResolver")() {
|
|
314
|
+
};
|
|
315
|
+
var runTools = Effect.fn("runTools")(function* (toolCalls, toolkit) {
|
|
316
|
+
const toolkitWithHandlers = Effect.isEffect(toolkit) ? yield* toolkit : toolkit;
|
|
317
|
+
return yield* Effect.forEach(toolCalls, (toolCall) => runTool(toolkitWithHandlers, toolCall));
|
|
318
|
+
});
|
|
319
|
+
|
|
320
|
+
// src/session/version-pin.ts
|
|
321
|
+
import { Schema as Schema2 } from "effect";
|
|
322
|
+
import { getVersion } from "@dxos/echo-db";
|
|
323
|
+
import { ObjectId } from "@dxos/echo-schema";
|
|
324
|
+
var ObjectVersionSchema = Schema2.Unknown;
|
|
325
|
+
var VersionPinSchema = Schema2.Struct({
|
|
326
|
+
// TODO(dmaretskyi): Use Ref when those support encoding.
|
|
327
|
+
objectId: ObjectId,
|
|
328
|
+
// TODO(dmaretskyi): Could be opaque
|
|
329
|
+
version: ObjectVersionSchema
|
|
330
|
+
});
|
|
331
|
+
var VersionPin = class extends VersionPinSchema {
|
|
332
|
+
static {
|
|
333
|
+
this.DISPOSITION = "version-pin";
|
|
334
|
+
}
|
|
335
|
+
static fromObject(object) {
|
|
336
|
+
return VersionPin.make({
|
|
337
|
+
objectId: object.id,
|
|
338
|
+
version: getVersion(object)
|
|
339
|
+
});
|
|
340
|
+
}
|
|
341
|
+
static createBlock(pin) {
|
|
342
|
+
return {
|
|
343
|
+
_tag: "json",
|
|
344
|
+
disposition: VersionPin.DISPOSITION,
|
|
345
|
+
data: JSON.stringify(pin)
|
|
346
|
+
};
|
|
347
|
+
}
|
|
348
|
+
};
|
|
349
|
+
|
|
350
|
+
// src/conversation/conversation.ts
|
|
351
|
+
var Conversation = class {
|
|
352
|
+
constructor(options) {
|
|
353
|
+
/**
|
|
354
|
+
* Fired when the execution loop begins.
|
|
355
|
+
* This is called before the first message is sent.
|
|
356
|
+
*/
|
|
357
|
+
this.onBegin = new Event2();
|
|
358
|
+
this.run = (options) => Effect2.gen(this, function* () {
|
|
359
|
+
const session = new AiSession();
|
|
360
|
+
this.onBegin.emit(session);
|
|
361
|
+
const history = yield* Effect2.promise(() => this.getHistory());
|
|
362
|
+
const context = yield* Effect2.promise(() => this.context.query());
|
|
363
|
+
const blueprints = yield* Effect2.forEach(context.blueprints.values(), DatabaseService2.loadRef);
|
|
364
|
+
const contextObjects = yield* Effect2.forEach(context.objects.values(), DatabaseService2.loadRef);
|
|
365
|
+
const systemPrompt = (options.systemPrompt ?? "") + "\n\n" + contextObjects.map((obj) => `<object>${Obj3.getDXN(obj)}</object>`).join("\n");
|
|
366
|
+
const messages = yield* session.run({
|
|
367
|
+
prompt: options.prompt,
|
|
368
|
+
history,
|
|
369
|
+
systemPrompt,
|
|
370
|
+
toolkit: options.toolkit,
|
|
371
|
+
blueprints
|
|
372
|
+
});
|
|
373
|
+
yield* Effect2.promise(() => this._queue.append(messages));
|
|
374
|
+
return messages;
|
|
375
|
+
}).pipe(Effect2.withSpan("Conversation.run"));
|
|
376
|
+
this._queue = options.queue;
|
|
377
|
+
this.context = new ContextBinder(this._queue);
|
|
378
|
+
}
|
|
379
|
+
async getHistory() {
|
|
380
|
+
const queueItems = await this._queue.queryObjects();
|
|
381
|
+
return queueItems.filter(Obj3.instanceOf(DataType2.Message));
|
|
382
|
+
}
|
|
383
|
+
};
|
|
384
|
+
|
|
385
|
+
// src/extraction/extraction.ts
|
|
386
|
+
import { Schema as Schema3 } from "effect";
|
|
387
|
+
import { asyncTimeout } from "@dxos/async";
|
|
388
|
+
import { Expando } from "@dxos/echo-schema";
|
|
389
|
+
import { log as log2 } from "@dxos/log";
|
|
390
|
+
import { DataType as DataType3 } from "@dxos/schema";
|
|
391
|
+
var __dxlog_file2 = "/__w/dxos/dxos/packages/core/assistant/src/extraction/extraction.ts";
|
|
392
|
+
var ExtractionInput = Schema3.Struct({
|
|
393
|
+
message: DataType3.Message,
|
|
394
|
+
objects: Schema3.optional(Schema3.Array(Expando)),
|
|
395
|
+
options: Schema3.optional(Schema3.Struct({
|
|
396
|
+
timeout: Schema3.optional(Schema3.Number),
|
|
397
|
+
fallbackToRaw: Schema3.optional(Schema3.Boolean)
|
|
398
|
+
}))
|
|
399
|
+
});
|
|
400
|
+
var ExtractionOutput = Schema3.Struct({
|
|
401
|
+
message: DataType3.Message,
|
|
402
|
+
timeElapsed: Schema3.Number
|
|
403
|
+
});
|
|
404
|
+
var processTranscriptMessage = async (params) => {
|
|
405
|
+
try {
|
|
406
|
+
if (params.options?.timeout && params.options.timeout > 0) {
|
|
407
|
+
return await asyncTimeout(params.executor.invoke(params.function, params.input), params.options.timeout);
|
|
408
|
+
} else {
|
|
409
|
+
return await params.executor.invoke(params.function, params.input);
|
|
410
|
+
}
|
|
411
|
+
} catch (error) {
|
|
412
|
+
if (params.options?.fallbackToRaw) {
|
|
413
|
+
log2.warn("failed to process message, falling back to raw text", {
|
|
414
|
+
error
|
|
415
|
+
}, {
|
|
416
|
+
F: __dxlog_file2,
|
|
417
|
+
L: 66,
|
|
418
|
+
S: void 0,
|
|
419
|
+
C: (f, a) => f(...a)
|
|
420
|
+
});
|
|
421
|
+
return {
|
|
422
|
+
message: params.input.message,
|
|
423
|
+
timeElapsed: 0
|
|
424
|
+
};
|
|
425
|
+
} else {
|
|
426
|
+
throw error;
|
|
427
|
+
}
|
|
428
|
+
}
|
|
429
|
+
};
|
|
528
430
|
|
|
529
|
-
//
|
|
431
|
+
// src/extraction/extraction-llm-function/extraction-llm-function.ts
|
|
432
|
+
import { ToolRegistry, AiService } from "@dxos/ai";
|
|
433
|
+
import { Obj as Obj4 } from "@dxos/echo";
|
|
434
|
+
import { create } from "@dxos/echo-schema";
|
|
435
|
+
import { defineFunction } from "@dxos/functions";
|
|
436
|
+
import { DataType as DataType4 } from "@dxos/schema";
|
|
437
|
+
|
|
438
|
+
// raw-loader:./instructions.tpl?raw
|
|
439
|
+
var instructions_default = 'You are an AI assistant specialized in processing and enhancing transcripts with contextual information.\nYour task is to analyze a given transcript and extract references to the context objects.\n\nThe context and transcript are provided in the user message in `context` and `transcript` XML tags.\n\nHere are your instructions:\n\n1. Read the transcript and context information provided above.\n\n2. Process each segment of the transcript separately.\n\n3. For each segment:\n a. Analyze the content and identify relevant information from the context.\n b. Extract a number of references to the context objects that are mentioned in the segment.\n c. Output the references in the format `{ "quote": "earnings report", "id": "01JT0JP9AX0XKGZX4MV4B69VT6" }`.\n d. If there are no references, just output an empty array.\n\n4. Maintain the exact order and structure of the original transcript segments.\n\nOutput Format:\nYou have been provided with a tool that specifies output format\n\nRemember:\n- Only quote the text that is in the transcript.\n- Analyze each segment carefully before processing it.\n- Only reference objects that appear in the context and exactly by their id, If the object is not in the context, do not insert a reference. \n\nNow, process the transcript and context provided below according to these instructions.';
|
|
440
|
+
|
|
441
|
+
// src/extraction/quotes.ts
|
|
530
442
|
import { Schema as Schema4 } from "effect";
|
|
531
443
|
import { Query, Filter } from "@dxos/echo";
|
|
532
444
|
import { ObjectId as ObjectId2 } from "@dxos/echo-schema";
|
|
533
445
|
import { DXN } from "@dxos/keys";
|
|
534
446
|
import { log as log3 } from "@dxos/log";
|
|
535
|
-
var __dxlog_file3 = "/
|
|
447
|
+
var __dxlog_file3 = "/__w/dxos/dxos/packages/core/assistant/src/extraction/quotes.ts";
|
|
536
448
|
var ReferencedQuotes = Schema4.Struct({
|
|
537
449
|
references: Schema4.Array(Schema4.Struct({
|
|
538
450
|
id: Schema4.String,
|
|
@@ -581,7 +493,7 @@ var insertReferences = (text, quotes) => {
|
|
|
581
493
|
return text;
|
|
582
494
|
};
|
|
583
495
|
|
|
584
|
-
//
|
|
496
|
+
// src/extraction/extraction-llm-function/extraction-llm-function.ts
|
|
585
497
|
var extractionAnthropicFn = defineFunction({
|
|
586
498
|
description: "Extract entities from the transcript message and add them to the message.",
|
|
587
499
|
inputSchema: ExtractionInput,
|
|
@@ -589,7 +501,7 @@ var extractionAnthropicFn = defineFunction({
|
|
|
589
501
|
handler: async ({ data: { message, objects }, context }) => {
|
|
590
502
|
const startTime = performance.now();
|
|
591
503
|
const ai = context.getService(AiService);
|
|
592
|
-
const session = new
|
|
504
|
+
const session = new AiSession({
|
|
593
505
|
operationModel: "configured"
|
|
594
506
|
});
|
|
595
507
|
const result = await session.runStructured(ReferencedQuotes, {
|
|
@@ -599,15 +511,18 @@ var extractionAnthropicFn = defineFunction({
|
|
|
599
511
|
client: ai.client,
|
|
600
512
|
systemPrompt: instructions_default,
|
|
601
513
|
history: [
|
|
602
|
-
|
|
603
|
-
|
|
604
|
-
|
|
514
|
+
Obj4.make(DataType4.Message, {
|
|
515
|
+
created: (/* @__PURE__ */ new Date()).toISOString(),
|
|
516
|
+
sender: {
|
|
517
|
+
role: "user"
|
|
518
|
+
},
|
|
519
|
+
blocks: [
|
|
605
520
|
{
|
|
606
|
-
|
|
521
|
+
_tag: "text",
|
|
607
522
|
text: `<context>${JSON.stringify(objects)}</context>`
|
|
608
523
|
},
|
|
609
524
|
{
|
|
610
|
-
|
|
525
|
+
_tag: "text",
|
|
611
526
|
text: `<transcript>${JSON.stringify(message.blocks)}</transcript>`
|
|
612
527
|
}
|
|
613
528
|
]
|
|
@@ -615,12 +530,13 @@ var extractionAnthropicFn = defineFunction({
|
|
|
615
530
|
],
|
|
616
531
|
artifacts: [],
|
|
617
532
|
prompt: "",
|
|
618
|
-
tools: []
|
|
533
|
+
tools: [],
|
|
534
|
+
toolResolver: new ToolRegistry([])
|
|
619
535
|
});
|
|
620
536
|
return {
|
|
621
|
-
message:
|
|
537
|
+
message: create(DataType4.Message, {
|
|
622
538
|
...message,
|
|
623
|
-
blocks: message.blocks.map((block, i) => block.
|
|
539
|
+
blocks: message.blocks.map((block, i) => block._tag !== "transcript" ? block : {
|
|
624
540
|
...block,
|
|
625
541
|
text: insertReferences(block.text, result)
|
|
626
542
|
})
|
|
@@ -630,18 +546,18 @@ var extractionAnthropicFn = defineFunction({
|
|
|
630
546
|
}
|
|
631
547
|
});
|
|
632
548
|
|
|
633
|
-
//
|
|
549
|
+
// src/extraction/extraction-ner-function/extraction-ner-function.ts
|
|
634
550
|
import { asyncTimeout as asyncTimeout2 } from "@dxos/async";
|
|
635
|
-
import { create as
|
|
636
|
-
import { DatabaseService, defineFunction as defineFunction2 } from "@dxos/functions";
|
|
637
|
-
import { invariant
|
|
551
|
+
import { create as create2 } from "@dxos/echo-schema";
|
|
552
|
+
import { DatabaseService as DatabaseService3, defineFunction as defineFunction2 } from "@dxos/functions";
|
|
553
|
+
import { invariant } from "@dxos/invariant";
|
|
638
554
|
import { log as log5 } from "@dxos/log";
|
|
639
|
-
import { DataType as
|
|
555
|
+
import { DataType as DataType5 } from "@dxos/schema";
|
|
640
556
|
|
|
641
|
-
//
|
|
557
|
+
// src/extraction/extraction-ner-function/named-entity-recognition.ts
|
|
642
558
|
import { pipeline } from "@xenova/transformers";
|
|
643
559
|
import { log as log4 } from "@dxos/log";
|
|
644
|
-
var __dxlog_file4 = "/
|
|
560
|
+
var __dxlog_file4 = "/__w/dxos/dxos/packages/core/assistant/src/extraction/extraction-ner-function/named-entity-recognition.ts";
|
|
645
561
|
var _ner;
|
|
646
562
|
var getNer = () => {
|
|
647
563
|
if (!_ner) {
|
|
@@ -720,8 +636,8 @@ var combineNerTokens = (group) => {
|
|
|
720
636
|
return combinedToken;
|
|
721
637
|
};
|
|
722
638
|
|
|
723
|
-
//
|
|
724
|
-
var __dxlog_file5 = "/
|
|
639
|
+
// src/extraction/extraction-ner-function/extraction-ner-function.ts
|
|
640
|
+
var __dxlog_file5 = "/__w/dxos/dxos/packages/core/assistant/src/extraction/extraction-ner-function/extraction-ner-function.ts";
|
|
725
641
|
var extractionNerFn = defineFunction2({
|
|
726
642
|
description: "Extracts named entities from a text",
|
|
727
643
|
inputSchema: ExtractionInput,
|
|
@@ -732,19 +648,19 @@ var extractionNerFn = defineFunction2({
|
|
|
732
648
|
options
|
|
733
649
|
}, {
|
|
734
650
|
F: __dxlog_file5,
|
|
735
|
-
L:
|
|
651
|
+
L: 25,
|
|
736
652
|
S: void 0,
|
|
737
653
|
C: (f, a) => f(...a)
|
|
738
654
|
});
|
|
739
655
|
const startTime = performance.now();
|
|
740
|
-
const { db } = context.getService(
|
|
656
|
+
const { db } = context.getService(DatabaseService3);
|
|
741
657
|
const entitiesPromise = Promise.all(message.blocks.map(async (block) => {
|
|
742
|
-
|
|
658
|
+
invariant(block._tag === "transcript" || block._tag === "text", "Block must have text", {
|
|
743
659
|
F: __dxlog_file5,
|
|
744
|
-
L:
|
|
660
|
+
L: 31,
|
|
745
661
|
S: void 0,
|
|
746
662
|
A: [
|
|
747
|
-
"block.
|
|
663
|
+
"block._tag === 'transcript' || block._tag === 'text'",
|
|
748
664
|
"'Block must have text'"
|
|
749
665
|
]
|
|
750
666
|
});
|
|
@@ -755,27 +671,27 @@ var extractionNerFn = defineFunction2({
|
|
|
755
671
|
entities
|
|
756
672
|
}, {
|
|
757
673
|
F: __dxlog_file5,
|
|
758
|
-
L:
|
|
674
|
+
L: 36,
|
|
759
675
|
S: void 0,
|
|
760
676
|
C: (f, a) => f(...a)
|
|
761
677
|
});
|
|
762
678
|
const quoteReferences = await findQuotes(entities.map((entity) => entity.word), db);
|
|
763
679
|
const blocksWithReferences = message.blocks.map((block, i) => {
|
|
764
|
-
|
|
680
|
+
invariant(block._tag === "transcript" || block._tag === "text", "Block must have text", {
|
|
765
681
|
F: __dxlog_file5,
|
|
766
|
-
L:
|
|
682
|
+
L: 42,
|
|
767
683
|
S: void 0,
|
|
768
684
|
A: [
|
|
769
|
-
"block.
|
|
685
|
+
"block._tag === 'transcript' || block._tag === 'text'",
|
|
770
686
|
"'Block must have text'"
|
|
771
687
|
]
|
|
772
688
|
});
|
|
773
689
|
return {
|
|
774
690
|
...block,
|
|
775
|
-
text: insertReferences(block.
|
|
691
|
+
text: insertReferences(block._tag, quoteReferences)
|
|
776
692
|
};
|
|
777
693
|
});
|
|
778
|
-
const messageWithReferences =
|
|
694
|
+
const messageWithReferences = create2(DataType5.Message, {
|
|
779
695
|
...message,
|
|
780
696
|
blocks: blocksWithReferences
|
|
781
697
|
});
|
|
@@ -783,7 +699,7 @@ var extractionNerFn = defineFunction2({
|
|
|
783
699
|
messageWithReferences
|
|
784
700
|
}, {
|
|
785
701
|
F: __dxlog_file5,
|
|
786
|
-
L:
|
|
702
|
+
L: 50,
|
|
787
703
|
S: void 0,
|
|
788
704
|
C: (f, a) => f(...a)
|
|
789
705
|
});
|
|
@@ -794,13 +710,129 @@ var extractionNerFn = defineFunction2({
|
|
|
794
710
|
}
|
|
795
711
|
});
|
|
796
712
|
|
|
797
|
-
//
|
|
798
|
-
import {
|
|
713
|
+
// src/functions/services.ts
|
|
714
|
+
import { AiTool } from "@effect/ai";
|
|
715
|
+
import { Context as Context2, Effect as Effect3, Layer, Match, Predicate, Record, Schema as Schema5 } from "effect";
|
|
716
|
+
import { AiToolNotFoundError, ToolExecutionService as ToolExecutionService2, ToolResolverService as ToolResolverService2 } from "@dxos/ai";
|
|
717
|
+
import { todo as todo2 } from "@dxos/debug";
|
|
718
|
+
import { FunctionError } from "@dxos/functions";
|
|
719
|
+
import { invariant as invariant2 } from "@dxos/invariant";
|
|
720
|
+
var __dxlog_file6 = "/__w/dxos/dxos/packages/core/assistant/src/functions/services.ts";
|
|
721
|
+
var makeToolResolverFromFunctions = (functions) => {
|
|
722
|
+
return Layer.succeed(ToolResolverService2, {
|
|
723
|
+
resolve: Effect3.fn("resolveTool")(function* (id) {
|
|
724
|
+
const fn = functions.find((f) => f.name === id);
|
|
725
|
+
if (!fn) {
|
|
726
|
+
return yield* Effect3.fail(new AiToolNotFoundError(id));
|
|
727
|
+
}
|
|
728
|
+
return projectFunctionToTool(fn);
|
|
729
|
+
})
|
|
730
|
+
});
|
|
731
|
+
};
|
|
732
|
+
var makeToolExecutionServiceFromFunctions = (functions) => {
|
|
733
|
+
return Layer.succeed(ToolExecutionService2, {
|
|
734
|
+
handlersFor: (toolkit) => {
|
|
735
|
+
const makeHandler = (tool) => {
|
|
736
|
+
return Effect3.fn("toolFunctionHandler")(function* (input) {
|
|
737
|
+
const { functionName } = Context2.get(FunctionToolAnnotation)(tool.annotations);
|
|
738
|
+
const fnDef = functions.find((f) => f.name === functionName);
|
|
739
|
+
if (!fnDef) {
|
|
740
|
+
return yield* Effect3.fail(new AiToolNotFoundError(tool.name));
|
|
741
|
+
}
|
|
742
|
+
return yield* invokeFunction(fnDef, input).pipe(Effect3.catchAllDefect((defect) => Effect3.fail(defect)));
|
|
743
|
+
});
|
|
744
|
+
};
|
|
745
|
+
return toolkit.of(Record.map(toolkit.tools, (tool, name) => makeHandler(tool)));
|
|
746
|
+
}
|
|
747
|
+
});
|
|
748
|
+
};
|
|
749
|
+
var FunctionToolAnnotation = class extends Context2.Tag("@dxos/assisatnt/FunctionToolAnnotation")() {
|
|
750
|
+
};
|
|
751
|
+
var toolCache = /* @__PURE__ */ new WeakMap();
|
|
752
|
+
var projectFunctionToTool = (fn) => {
|
|
753
|
+
if (toolCache.has(fn)) {
|
|
754
|
+
return toolCache.get(fn);
|
|
755
|
+
}
|
|
756
|
+
const tool = AiTool.make(makeToolName(fn.name), {
|
|
757
|
+
description: fn.description,
|
|
758
|
+
parameters: createStructFieldsFromSchema(fn.inputSchema),
|
|
759
|
+
// TODO(dmaretskyi): Include output schema.
|
|
760
|
+
failure: Schema5.Any
|
|
761
|
+
}).annotate(FunctionToolAnnotation, {
|
|
762
|
+
functionName: fn.name
|
|
763
|
+
});
|
|
764
|
+
toolCache.set(fn, tool);
|
|
765
|
+
return tool;
|
|
766
|
+
};
|
|
767
|
+
var makeToolName = (name) => {
|
|
768
|
+
const toolName = name.replace(/[^a-zA-Z0-9]/g, "");
|
|
769
|
+
invariant2(toolName.match(/^[a-zA-Z_][a-zA-Z0-9-_]*$/), void 0, {
|
|
770
|
+
F: __dxlog_file6,
|
|
771
|
+
L: 80,
|
|
772
|
+
S: void 0,
|
|
773
|
+
A: [
|
|
774
|
+
"toolName.match(/^[a-zA-Z_][a-zA-Z0-9-_]*$/)",
|
|
775
|
+
""
|
|
776
|
+
]
|
|
777
|
+
});
|
|
778
|
+
return toolName;
|
|
779
|
+
};
|
|
780
|
+
var createStructFieldsFromSchema = (schema) => {
|
|
781
|
+
return Match.value(schema.ast).pipe(Match.when(Predicate.isTagged("TypeLiteral"), (ast) => {
|
|
782
|
+
return Object.fromEntries(ast.propertySignatures.map((prop) => [
|
|
783
|
+
prop.name,
|
|
784
|
+
Schema5.make(prop.type)
|
|
785
|
+
]));
|
|
786
|
+
}), Match.orElseAbsurd);
|
|
787
|
+
};
|
|
788
|
+
var invokeFunction = (fnDef, input) => Effect3.gen(function* () {
|
|
789
|
+
const assertInput = fnDef.inputSchema.pipe(Schema5.asserts);
|
|
790
|
+
assertInput(input);
|
|
791
|
+
const context = {
|
|
792
|
+
getService: () => todo2(),
|
|
793
|
+
getSpace: async (_spaceId) => {
|
|
794
|
+
throw new Error("Not available. Use the database service instead.");
|
|
795
|
+
},
|
|
796
|
+
space: void 0,
|
|
797
|
+
get ai() {
|
|
798
|
+
throw new Error("Not available. Use the ai service instead.");
|
|
799
|
+
}
|
|
800
|
+
};
|
|
801
|
+
const data = yield* Effect3.gen(function* () {
|
|
802
|
+
const result = fnDef.handler({
|
|
803
|
+
context,
|
|
804
|
+
data: input
|
|
805
|
+
});
|
|
806
|
+
if (Effect3.isEffect(result)) {
|
|
807
|
+
return yield* result.pipe(Effect3.orDie);
|
|
808
|
+
} else if (typeof result === "object" && result !== null && "then" in result && typeof result.then === "function") {
|
|
809
|
+
return yield* Effect3.promise(() => result);
|
|
810
|
+
} else {
|
|
811
|
+
return result;
|
|
812
|
+
}
|
|
813
|
+
}).pipe(Effect3.orDie, Effect3.catchAllDefect((defect) => Effect3.die(new FunctionError("Error running function", {
|
|
814
|
+
context: {
|
|
815
|
+
name: fnDef.name
|
|
816
|
+
},
|
|
817
|
+
cause: defect
|
|
818
|
+
}))));
|
|
819
|
+
const assertOutput = fnDef.outputSchema?.pipe(Schema5.asserts);
|
|
820
|
+
assertOutput(data);
|
|
821
|
+
return data;
|
|
822
|
+
}).pipe(Effect3.withSpan("invokeFunction", {
|
|
823
|
+
attributes: {
|
|
824
|
+
name: fnDef.name
|
|
825
|
+
}
|
|
826
|
+
}));
|
|
827
|
+
|
|
828
|
+
// src/research/exa.ts
|
|
829
|
+
import { AiTool as AiTool2, AiToolkit as AiToolkit2 } from "@effect/ai";
|
|
830
|
+
import { Effect as Effect4, Schema as Schema6 } from "effect";
|
|
799
831
|
import Exa from "exa-js";
|
|
800
|
-
import {
|
|
832
|
+
import { CredentialsService } from "@dxos/functions";
|
|
801
833
|
import { log as log6 } from "@dxos/log";
|
|
802
834
|
|
|
803
|
-
//
|
|
835
|
+
// src/testing/exa-search-1748337321991.ts
|
|
804
836
|
var exa_search_1748337321991_default = {
|
|
805
837
|
requestId: "324936368a74f4db978982172bc18a6c",
|
|
806
838
|
autopromptString: "AI personal knowledge management tools projects 2024",
|
|
@@ -956,7 +988,7 @@ var exa_search_1748337321991_default = {
|
|
|
956
988
|
}
|
|
957
989
|
};
|
|
958
990
|
|
|
959
|
-
//
|
|
991
|
+
// src/testing/exa-search-1748337331526.ts
|
|
960
992
|
var exa_search_1748337331526_default = {
|
|
961
993
|
requestId: "0dc12e344fa649884456960ca1a54954",
|
|
962
994
|
autopromptString: "PKM software artificial intelligence integration open source projects",
|
|
@@ -1179,7 +1211,7 @@ npm run tauri dev
|
|
|
1179
1211
|
}
|
|
1180
1212
|
};
|
|
1181
1213
|
|
|
1182
|
-
//
|
|
1214
|
+
// src/testing/exa-search-1748337344119.ts
|
|
1183
1215
|
var exa_search_1748337344119_default = {
|
|
1184
1216
|
requestId: "32df0c541f9883180b35e04caece4374",
|
|
1185
1217
|
autopromptString: "open source AI knowledge management projects features comparison 2024",
|
|
@@ -1302,73 +1334,69 @@ var exa_search_1748337344119_default = {
|
|
|
1302
1334
|
}
|
|
1303
1335
|
};
|
|
1304
1336
|
|
|
1305
|
-
//
|
|
1337
|
+
// src/testing/index.ts
|
|
1306
1338
|
var SEARCH_RESULTS = [
|
|
1307
1339
|
exa_search_1748337321991_default,
|
|
1308
1340
|
exa_search_1748337331526_default,
|
|
1309
1341
|
exa_search_1748337344119_default
|
|
1310
1342
|
];
|
|
1311
1343
|
|
|
1312
|
-
//
|
|
1313
|
-
var
|
|
1314
|
-
var
|
|
1315
|
-
|
|
1316
|
-
|
|
1317
|
-
|
|
1318
|
-
|
|
1319
|
-
|
|
1320
|
-
|
|
1321
|
-
|
|
1322
|
-
|
|
1323
|
-
|
|
1324
|
-
execute: async ({ query }) => {
|
|
1325
|
-
const context = await exa.searchAndContents(query, {
|
|
1326
|
-
type: "auto",
|
|
1327
|
-
text: {
|
|
1328
|
-
maxCharacters: 3e3
|
|
1329
|
-
},
|
|
1330
|
-
livecrawl: "always"
|
|
1331
|
-
});
|
|
1332
|
-
log6.info("exa search", {
|
|
1333
|
-
query,
|
|
1334
|
-
costDollars: context.costDollars
|
|
1335
|
-
}, {
|
|
1336
|
-
F: __dxlog_file6,
|
|
1337
|
-
L: 35,
|
|
1338
|
-
S: void 0,
|
|
1339
|
-
C: (f, a) => f(...a)
|
|
1340
|
-
});
|
|
1341
|
-
return ToolResult2.Success(context);
|
|
1342
|
-
}
|
|
1343
|
-
});
|
|
1344
|
-
};
|
|
1345
|
-
var createMockExaTool = () => {
|
|
1346
|
-
return createTool2("search", {
|
|
1347
|
-
name: "web_search",
|
|
1348
|
-
description: "Search the web for information",
|
|
1349
|
-
schema: Schema5.Struct({
|
|
1350
|
-
query: Schema5.String.annotations({
|
|
1351
|
-
description: "The query to search for"
|
|
1352
|
-
})
|
|
1353
|
-
}),
|
|
1354
|
-
execute: async ({ query }) => {
|
|
1355
|
-
const result = SEARCH_RESULTS.reduce((closest, current) => {
|
|
1356
|
-
if (!current.autopromptString) {
|
|
1357
|
-
return closest;
|
|
1358
|
-
}
|
|
1359
|
-
if (!closest) {
|
|
1360
|
-
return current;
|
|
1361
|
-
}
|
|
1362
|
-
const dist1 = levenshteinDistance(query, current.autopromptString);
|
|
1363
|
-
const dist2 = levenshteinDistance(query, closest.autopromptString || "");
|
|
1364
|
-
const weight1 = dist1 / Math.max(query.length, current.autopromptString.length);
|
|
1365
|
-
const weight2 = dist2 / Math.max(query.length, closest.autopromptString?.length || 0);
|
|
1366
|
-
return weight1 < weight2 ? current : closest;
|
|
1367
|
-
}, null);
|
|
1368
|
-
return ToolResult2.Success(result);
|
|
1369
|
-
}
|
|
1370
|
-
});
|
|
1344
|
+
// src/research/exa.ts
|
|
1345
|
+
var __dxlog_file7 = "/__w/dxos/dxos/packages/core/assistant/src/research/exa.ts";
|
|
1346
|
+
var ExaToolkit = class extends AiToolkit2.make(AiTool2.make("exa_search", {
|
|
1347
|
+
description: "Search the web for information",
|
|
1348
|
+
parameters: {
|
|
1349
|
+
query: Schema6.String.annotations({
|
|
1350
|
+
description: "The query to search for"
|
|
1351
|
+
})
|
|
1352
|
+
},
|
|
1353
|
+
success: Schema6.Unknown,
|
|
1354
|
+
failure: Schema6.Never
|
|
1355
|
+
}).addRequirement()) {
|
|
1371
1356
|
};
|
|
1357
|
+
var LiveExaHandler = ExaToolkit.toLayer({
|
|
1358
|
+
exa_search: Effect4.fn(function* ({ query }) {
|
|
1359
|
+
const credential = yield* CredentialsService.getCredential({
|
|
1360
|
+
service: "exa.ai"
|
|
1361
|
+
});
|
|
1362
|
+
const exa = new Exa(credential.apiKey);
|
|
1363
|
+
const context = yield* Effect4.promise(async () => exa.searchAndContents(query, {
|
|
1364
|
+
type: "auto",
|
|
1365
|
+
text: {
|
|
1366
|
+
maxCharacters: 3e3
|
|
1367
|
+
},
|
|
1368
|
+
livecrawl: "always"
|
|
1369
|
+
}));
|
|
1370
|
+
log6.info("exa search", {
|
|
1371
|
+
query,
|
|
1372
|
+
costDollars: context.costDollars
|
|
1373
|
+
}, {
|
|
1374
|
+
F: __dxlog_file7,
|
|
1375
|
+
L: 40,
|
|
1376
|
+
S: this,
|
|
1377
|
+
C: (f, a) => f(...a)
|
|
1378
|
+
});
|
|
1379
|
+
return context;
|
|
1380
|
+
})
|
|
1381
|
+
});
|
|
1382
|
+
var MockExaHandler = ExaToolkit.toLayer({
|
|
1383
|
+
exa_search: Effect4.fn(function* ({ query }) {
|
|
1384
|
+
const result = SEARCH_RESULTS.reduce((closest, current) => {
|
|
1385
|
+
if (!current.autopromptString) {
|
|
1386
|
+
return closest;
|
|
1387
|
+
}
|
|
1388
|
+
if (!closest) {
|
|
1389
|
+
return current;
|
|
1390
|
+
}
|
|
1391
|
+
const dist1 = levenshteinDistance(query, current.autopromptString);
|
|
1392
|
+
const dist2 = levenshteinDistance(query, closest.autopromptString || "");
|
|
1393
|
+
const weight1 = dist1 / Math.max(query.length, current.autopromptString.length);
|
|
1394
|
+
const weight2 = dist2 / Math.max(query.length, closest.autopromptString?.length || 0);
|
|
1395
|
+
return weight1 < weight2 ? current : closest;
|
|
1396
|
+
}, null);
|
|
1397
|
+
return result;
|
|
1398
|
+
})
|
|
1399
|
+
});
|
|
1372
1400
|
var levenshteinDistance = (str1, str2) => {
|
|
1373
1401
|
const m = str1.length;
|
|
1374
1402
|
const n = str2.length;
|
|
@@ -1387,28 +1415,29 @@ var levenshteinDistance = (str1, str2) => {
|
|
|
1387
1415
|
return dp[m][n];
|
|
1388
1416
|
};
|
|
1389
1417
|
|
|
1390
|
-
//
|
|
1391
|
-
import {
|
|
1392
|
-
import {
|
|
1393
|
-
import {
|
|
1394
|
-
import {
|
|
1418
|
+
// src/research/research.ts
|
|
1419
|
+
import { AiToolkit as AiToolkit4 } from "@effect/ai";
|
|
1420
|
+
import { Effect as Effect6, Layer as Layer2, Schema as Schema8 } from "effect";
|
|
1421
|
+
import { AiService as AiService2, ConsolePrinter } from "@dxos/ai";
|
|
1422
|
+
import { defineFunction as defineFunction3, TracingService } from "@dxos/functions";
|
|
1395
1423
|
import { log as log8 } from "@dxos/log";
|
|
1396
1424
|
import { DataTypes } from "@dxos/schema";
|
|
1397
1425
|
|
|
1398
|
-
//
|
|
1399
|
-
import {
|
|
1400
|
-
import {
|
|
1401
|
-
import {
|
|
1426
|
+
// src/research/graph.ts
|
|
1427
|
+
import { AiTool as AiTool3, AiToolkit as AiToolkit3 } from "@effect/ai";
|
|
1428
|
+
import { Context as Context3, Effect as Effect5, identity, Option as Option2, Schema as Schema7, SchemaAST } from "effect";
|
|
1429
|
+
import { Filter as Filter2, Query as Query2 } from "@dxos/echo";
|
|
1402
1430
|
import { isEncodedReference } from "@dxos/echo-protocol";
|
|
1403
|
-
import {
|
|
1431
|
+
import { create as create3, EntityKind, getEntityKind, getSchemaDXN, getSchemaTypename, getTypeAnnotation, getTypeIdentifierAnnotation, ObjectId as ObjectId3, ReferenceAnnotationId, RelationSourceDXNId, RelationSourceId, RelationTargetDXNId, RelationTargetId } from "@dxos/echo-schema";
|
|
1404
1432
|
import { mapAst } from "@dxos/effect";
|
|
1433
|
+
import { ContextQueueService, DatabaseService as DatabaseService4 } from "@dxos/functions";
|
|
1405
1434
|
import { DXN as DXN2 } from "@dxos/keys";
|
|
1406
1435
|
import { log as log7 } from "@dxos/log";
|
|
1407
1436
|
import { deepMapValues, isNonNullable } from "@dxos/util";
|
|
1408
|
-
var
|
|
1409
|
-
var Subgraph =
|
|
1437
|
+
var __dxlog_file8 = "/__w/dxos/dxos/packages/core/assistant/src/research/graph.ts";
|
|
1438
|
+
var Subgraph = Schema7.Struct({
|
|
1410
1439
|
/** Objects and relations. */
|
|
1411
|
-
objects:
|
|
1440
|
+
objects: Schema7.Array(Schema7.Any)
|
|
1412
1441
|
});
|
|
1413
1442
|
var findRelatedSchema = async (db, anchor) => {
|
|
1414
1443
|
const allSchemas = [
|
|
@@ -1434,39 +1463,65 @@ var isSchemaAddressableByDxn = (schema, dxn) => {
|
|
|
1434
1463
|
}
|
|
1435
1464
|
return false;
|
|
1436
1465
|
};
|
|
1437
|
-
var
|
|
1438
|
-
|
|
1439
|
-
|
|
1440
|
-
|
|
1441
|
-
|
|
1442
|
-
|
|
1443
|
-
|
|
1444
|
-
|
|
1445
|
-
|
|
1446
|
-
|
|
1447
|
-
|
|
1448
|
-
|
|
1449
|
-
|
|
1450
|
-
|
|
1451
|
-
|
|
1452
|
-
|
|
1453
|
-
|
|
1454
|
-
|
|
1455
|
-
|
|
1456
|
-
|
|
1457
|
-
|
|
1458
|
-
|
|
1459
|
-
|
|
1460
|
-
</local_context>
|
|
1461
|
-
`);
|
|
1466
|
+
var LocalSearchToolkit = class extends AiToolkit3.make(AiTool3.make("search_local_search", {
|
|
1467
|
+
description: "Search the local database for information using a vector index",
|
|
1468
|
+
parameters: {
|
|
1469
|
+
query: Schema7.String.annotations({
|
|
1470
|
+
description: "The query to search for. Could be a question or a topic or a set of keywords."
|
|
1471
|
+
})
|
|
1472
|
+
},
|
|
1473
|
+
success: Schema7.Unknown,
|
|
1474
|
+
failure: Schema7.Never
|
|
1475
|
+
}).addRequirement()) {
|
|
1476
|
+
};
|
|
1477
|
+
var LocalSearchHandler = LocalSearchToolkit.toLayer({
|
|
1478
|
+
search_local_search: Effect5.fn(function* ({ query }) {
|
|
1479
|
+
const { objects } = yield* DatabaseService4.runQuery(Query2.select(Filter2.text(query, {
|
|
1480
|
+
type: "vector"
|
|
1481
|
+
})));
|
|
1482
|
+
const results = [
|
|
1483
|
+
...objects
|
|
1484
|
+
];
|
|
1485
|
+
const contextQueue = yield* Effect5.serviceOption(ContextQueueService);
|
|
1486
|
+
if (Option2.isSome(contextQueue)) {
|
|
1487
|
+
const queueObjects = yield* Effect5.promise(() => contextQueue.value.contextQueue.queryObjects());
|
|
1488
|
+
results.push(...queueObjects);
|
|
1462
1489
|
}
|
|
1490
|
+
return `
|
|
1491
|
+
<local_context>
|
|
1492
|
+
${JSON.stringify(results, null, 2)}
|
|
1493
|
+
</local_context>
|
|
1494
|
+
`;
|
|
1495
|
+
})
|
|
1496
|
+
});
|
|
1497
|
+
var GraphWriterSchema = class extends Context3.Tag("GraphWriterSchema")() {
|
|
1498
|
+
};
|
|
1499
|
+
var makeGraphWriterToolkit = ({ schema }) => {
|
|
1500
|
+
return AiToolkit3.make(AiTool3.make("graph_writer", {
|
|
1501
|
+
description: "Write to the local graph database",
|
|
1502
|
+
parameters: createExtractionSchema(schema).fields,
|
|
1503
|
+
success: Schema7.Unknown,
|
|
1504
|
+
failure: Schema7.Never
|
|
1505
|
+
}).addRequirement().annotateContext(Context3.make(GraphWriterSchema, {
|
|
1506
|
+
schema
|
|
1507
|
+
})));
|
|
1508
|
+
};
|
|
1509
|
+
var makeGraphWriterHandler = (toolkit) => {
|
|
1510
|
+
const { schema } = Context3.get(toolkit.tools.graph_writer.annotations, GraphWriterSchema);
|
|
1511
|
+
return toolkit.toLayer({
|
|
1512
|
+
graph_writer: Effect5.fn(function* (input) {
|
|
1513
|
+
const { db } = yield* DatabaseService4;
|
|
1514
|
+
const contextQueue = yield* Effect5.serviceOption(ContextQueueService);
|
|
1515
|
+
const data = yield* Effect5.promise(() => sanitizeObjects(schema, input, db, contextQueue.pipe(Option2.getOrUndefined)?.contextQueue));
|
|
1516
|
+
return data;
|
|
1517
|
+
})
|
|
1463
1518
|
});
|
|
1464
1519
|
};
|
|
1465
1520
|
var createExtractionSchema = (types) => {
|
|
1466
|
-
return
|
|
1521
|
+
return Schema7.Struct({
|
|
1467
1522
|
...Object.fromEntries(types.map(preprocessSchema).map((schema, index) => [
|
|
1468
1523
|
`objects_${getSanitizedSchemaName(types[index])}`,
|
|
1469
|
-
|
|
1524
|
+
Schema7.optional(Schema7.Array(schema)).annotations({
|
|
1470
1525
|
description: `The objects of type: ${getSchemaDXN(types[index])?.asTypeDXN().type}. ${SchemaAST.getDescriptionAnnotation(types[index].ast).pipe(Option2.getOrElse(() => ""))}`
|
|
1471
1526
|
})
|
|
1472
1527
|
]))
|
|
@@ -1524,8 +1579,8 @@ var sanitizeObjects = async (types, data, db, queue) => {
|
|
|
1524
1579
|
log7.warn("source not found", {
|
|
1525
1580
|
source: data2.source
|
|
1526
1581
|
}, {
|
|
1527
|
-
F:
|
|
1528
|
-
L:
|
|
1582
|
+
F: __dxlog_file8,
|
|
1583
|
+
L: 262,
|
|
1529
1584
|
S: void 0,
|
|
1530
1585
|
C: (f, a) => f(...a)
|
|
1531
1586
|
});
|
|
@@ -1535,8 +1590,8 @@ var sanitizeObjects = async (types, data, db, queue) => {
|
|
|
1535
1590
|
log7.warn("target not found", {
|
|
1536
1591
|
target: data2.target
|
|
1537
1592
|
}, {
|
|
1538
|
-
F:
|
|
1539
|
-
L:
|
|
1593
|
+
F: __dxlog_file8,
|
|
1594
|
+
L: 266,
|
|
1540
1595
|
S: void 0,
|
|
1541
1596
|
C: (f, a) => f(...a)
|
|
1542
1597
|
});
|
|
@@ -1564,8 +1619,8 @@ var sanitizeObjects = async (types, data, db, queue) => {
|
|
|
1564
1619
|
queueObjects,
|
|
1565
1620
|
existingIds
|
|
1566
1621
|
}, {
|
|
1567
|
-
F:
|
|
1568
|
-
L:
|
|
1622
|
+
F: __dxlog_file8,
|
|
1623
|
+
L: 287,
|
|
1569
1624
|
S: void 0,
|
|
1570
1625
|
C: (f, a) => f(...a)
|
|
1571
1626
|
});
|
|
@@ -1596,7 +1651,7 @@ var sanitizeObjects = async (types, data, db, queue) => {
|
|
|
1596
1651
|
}
|
|
1597
1652
|
}
|
|
1598
1653
|
if (!skip) {
|
|
1599
|
-
const obj =
|
|
1654
|
+
const obj = create3(schema, data2);
|
|
1600
1655
|
enitties.set(obj.id, obj);
|
|
1601
1656
|
return [
|
|
1602
1657
|
obj
|
|
@@ -1605,543 +1660,159 @@ var sanitizeObjects = async (types, data, db, queue) => {
|
|
|
1605
1660
|
return [];
|
|
1606
1661
|
});
|
|
1607
1662
|
};
|
|
1608
|
-
var SoftRef =
|
|
1609
|
-
"/":
|
|
1663
|
+
var SoftRef = Schema7.Struct({
|
|
1664
|
+
"/": Schema7.String
|
|
1610
1665
|
}).annotations({
|
|
1611
1666
|
description: "Reference to another object."
|
|
1612
1667
|
});
|
|
1613
1668
|
var preprocessSchema = (schema) => {
|
|
1614
1669
|
const isRelationSchema = getEntityKind(schema) === "relation";
|
|
1615
|
-
const go = (ast) => {
|
|
1670
|
+
const go = (ast, visited = /* @__PURE__ */ new Set()) => {
|
|
1671
|
+
if (visited.has(ast)) {
|
|
1672
|
+
return ast;
|
|
1673
|
+
}
|
|
1674
|
+
visited.add(ast);
|
|
1616
1675
|
if (SchemaAST.getAnnotation(ast, ReferenceAnnotationId).pipe(Option2.isSome)) {
|
|
1617
1676
|
return SoftRef.ast;
|
|
1618
1677
|
}
|
|
1619
|
-
return mapAst(ast, go);
|
|
1678
|
+
return mapAst(ast, (child) => go(child, visited));
|
|
1620
1679
|
};
|
|
1621
|
-
return
|
|
1622
|
-
id:
|
|
1680
|
+
return Schema7.make(mapAst(schema.ast, (ast) => go(ast))).pipe(Schema7.omit("id"), Schema7.extend(Schema7.Struct({
|
|
1681
|
+
id: Schema7.String.annotations({
|
|
1623
1682
|
description: "The id of this object. Come up with a unique id based on your judgement."
|
|
1624
1683
|
})
|
|
1625
|
-
})), isRelationSchema ?
|
|
1626
|
-
source:
|
|
1684
|
+
})), isRelationSchema ? Schema7.extend(Schema7.Struct({
|
|
1685
|
+
source: Schema7.String.annotations({
|
|
1627
1686
|
description: "The id of the source object for this relation."
|
|
1628
1687
|
}),
|
|
1629
|
-
target:
|
|
1688
|
+
target: Schema7.String.annotations({
|
|
1630
1689
|
description: "The id of the target object for this relation."
|
|
1631
1690
|
})
|
|
1632
1691
|
})) : identity);
|
|
1633
1692
|
};
|
|
1634
|
-
var createGraphWriterTool = ({ db, queue, schema, onDone = async (x) => x }) => {
|
|
1635
|
-
return createTool3("graph", {
|
|
1636
|
-
name: "writer",
|
|
1637
|
-
description: "Write to the local graph database",
|
|
1638
|
-
schema: createExtractionSchema(schema),
|
|
1639
|
-
execute: async (input) => {
|
|
1640
|
-
const data = await sanitizeObjects(schema, input, db, queue);
|
|
1641
|
-
return ToolResult3.Success(await onDone(data));
|
|
1642
|
-
}
|
|
1643
|
-
});
|
|
1644
|
-
};
|
|
1645
1693
|
|
|
1646
1694
|
// raw-loader:./instructions-research.tpl?raw
|
|
1647
|
-
var instructions_research_default = "You are the Research Agent.\n\nThe Research Agent is an expert assistant that conducts in-depth research using real-time web search.\nThe Research Agent outputs results in a structured format matching the schema provided.\n\nThe Research Agent is equipped with the ability to:\n\n- Generate precise and effective search queries \n- Request web pages by query (through a `web_search` tool)\n- Read the full content of retrieved pages\n- Synthesize accurate, clear, and structured answers using reliable information from the retrieved content\n- Search the local database for information using a vector index (through a `local_search` tool)\n\nThe Research Agent always follows these principles:\n\n- Relevance First: The Research Agent only returns facts supported by content in retrieved web pages. The Research Agent never fabricates or guesses information.\n- Summarize, Don't Copy: The Research Agent synthesizes and rephrases content in its own words. The Research Agent quotes only when necessary.\n- Multiple Sources: The Research Agent cross-references at least 2 sources before drawing conclusions, unless the information is directly stated and non-controversial.\n- Transparency: The Research Agent mentions which sources were used and explains how it arrived at conclusions.\n- Accuracy Over Brevity: The Research Agent prefers detailed, technically accurate explanations over shallow summaries.\n- The Research Agent admits uncertainty rather than misleading.\n- The Research Agent picks the most concrete schema types for extracted information.\n- The Research Agent fills schema fields completely with information it is confident about, and omits fields it is not confident about.\n- When outputting results, the Research Agent adds extra data that fits the schema even if not directly related to the user's question.\n- The Research Agent creates relations and references between new objects found and what's already in the database.\n- The Research Agent does not create objects that are already in the database.\n- The Research Agent re-uses existing object IDs as references when enriching existing objects.\n\nThe Research Agent may be asked for:\n\n- Technical explanations\n- Literature reviews \n- Comparisons\n- Emerging trends\n- Implementation strategies\n\nThe Research Agent begins by interpreting the user's request, then:\n\nThe Research Agent breaks it into sub-questions (if applicable).\n\nFor each sub-question, the Research Agent generates a clear, concise web search query.\n\nThe Research Agent uses `web_search`(query) to retrieve information.\n\nThe Research Agent extracts and synthesizes relevant answers.\n\nThe Research Agent's output includes:\n\n- A clear, structured answer to the user's question\n- A citation list or link list of sources used\n\nOptionally, the Research Agent provides follow-up suggestions or questions for deeper inquiry.\n\nHere's how the Research Agent operates:\n\n1. The Research Agent analyzes the user's request and identifies key topics to search for (3 or more), printing them out.\n2. The Research Agent performs a web search for each topic.\n3. The Research Agent reads and analyzes results, cross references information from multiple sources, and represents conflicting information as ranges of possible values.\n\n4. The Research Agent searches the local database for information using a vector index that might link to the user's question.\n6. The Research Agent creates relations and references between new objects and existing database objects when related, using existing object IDs as references.\n7. The Research Agent selects the most concrete schema types for extracted information, using multiple types as needed, and prints its decision and reasoning.\n5. The Research Agent creates a clear, structured answer to the user's question.\n8. The Research Agent submits results using the specific schema.\n\nIMPORTANT:\n\n- The Research Agent always runs the `local_search` tool to search the local database at least once before submitting results.\n- The Research Agent does not create objects that already exist in the database.\n- Ids that are not in the database are human-readable strings like `ivan_zhao_1`.\n\nStatus reporting:\n\nThe Research Agent reports its status frequently using the `<status>` tags: <status>Searching for Google Founders</status>\nThe Research Agent reports its status in-between each tool call and before submitting results.\n\n<example>\n\nBased on my research, I can now provide information about Google and it's founders.\n\nThe following objects are already in the database, I will not submit them again, but I'll re-use their IDs as references:\n\n- 01JWRDEHPB5TT2JQQQC15038BT Google\n- 01JWRDEHPA14CYW2NW9FAH6DJJ Larry Page\n- 01JWRDEHPBN0BBJP57B9S108W6 Sergey Brin\n\nI will use the following schema to construct new objects:\n\n- type:dxos.org/type/Organization for Alphabet Inc.\n- type:dxos.org/type/Person for Ivan Zhao\n- type:dxos.org/type/Person for Simon Last\n- dxn:type:dxos.org/relation/Employer for Ivan's employer\n- dxn:type:dxos.org/relation/Employer for Simon's employer\n\n<status>Formatting results</status>\n\n</example>";
|
|
1695
|
+
var instructions_research_default = "You are the Research Agent.\n\nThe Research Agent is an expert assistant that conducts in-depth research using real-time web search.\nThe Research Agent outputs results in a structured format matching the schema provided.\n\nThe Research Agent is equipped with the ability to:\n\n- Generate precise and effective search queries \n- Request web pages by query (through a `web_search` tool)\n- Read the full content of retrieved pages\n- Synthesize accurate, clear, and structured answers using reliable information from the retrieved content\n- Search the local database for information using a vector index (through a `local_search` tool)\n\nThe Research Agent always follows these principles:\n\n- Relevance First: The Research Agent only returns facts supported by content in retrieved web pages. The Research Agent never fabricates or guesses information.\n- Summarize, Don't Copy: The Research Agent synthesizes and rephrases content in its own words. The Research Agent quotes only when necessary.\n- Multiple Sources: The Research Agent cross-references at least 2 sources before drawing conclusions, unless the information is directly stated and non-controversial.\n- Transparency: The Research Agent mentions which sources were used and explains how it arrived at conclusions.\n- Accuracy Over Brevity: The Research Agent prefers detailed, technically accurate explanations over shallow summaries.\n- The Research Agent admits uncertainty rather than misleading.\n- The Research Agent picks the most concrete schema types for extracted information.\n- The Research Agent fills schema fields completely with information it is confident about, and omits fields it is not confident about.\n- When outputting results, the Research Agent adds extra data that fits the schema even if not directly related to the user's question.\n- The Research Agent creates relations and references between new objects found and what's already in the database.\n- The Research Agent does not create objects that are already in the database.\n- The Research Agent re-uses existing object IDs as references when enriching existing objects.\n- The Research Agent ALWAYS calls the `graph_writer` at the end to save the data. This conversation will be delted, so only the data written to the graph will be preserved.\n\nThe Research Agent may be asked for:\n\n- Technical explanations\n- Literature reviews \n- Comparisons\n- Emerging trends\n- Implementation strategies\n\nThe Research Agent begins by interpreting the user's request, then:\n\nThe Research Agent breaks it into sub-questions (if applicable).\n\nFor each sub-question, the Research Agent generates a clear, concise web search query.\n\nThe Research Agent uses `web_search`(query) to retrieve information.\n\nThe Research Agent extracts and synthesizes relevant answers.\n\nThe Research Agent's output includes:\n\n- A clear, structured answer to the user's question\n- A citation list or link list of sources used\n\nOptionally, the Research Agent provides follow-up suggestions or questions for deeper inquiry.\n\nHere's how the Research Agent operates:\n\n1. The Research Agent analyzes the user's request and identifies key topics to search for (3 or more), printing them out.\n2. The Research Agent performs a web search for each topic.\n3. The Research Agent reads and analyzes results, cross references information from multiple sources, and represents conflicting information as ranges of possible values.\n\n4. The Research Agent searches the local database for information using a vector index that might link to the user's question.\n6. The Research Agent creates relations and references between new objects and existing database objects when related, using existing object IDs as references.\n7. The Research Agent selects the most concrete schema types for extracted information, using multiple types as needed, and prints its decision and reasoning.\n5. The Research Agent creates a clear, structured answer to the user's question.\n8. The Research Agent submits results using the specific schema.\n\nIMPORTANT:\n\n- The Research Agent always runs the `local_search` tool to search the local database at least once before submitting results.\n- The Research Agent does not create objects that already exist in the database.\n- Ids that are not in the database are human-readable strings like `ivan_zhao_1`.\n\nStatus reporting:\n\nThe Research Agent reports its status frequently using the `<status>` tags: <status>Searching for Google Founders</status>\nThe Research Agent reports its status in-between each tool call and before submitting results.\n\n<example>\n\nBased on my research, I can now provide information about Google and it's founders.\n\nThe following objects are already in the database, I will not submit them again, but I'll re-use their IDs as references:\n\n- 01JWRDEHPB5TT2JQQQC15038BT Google\n- 01JWRDEHPA14CYW2NW9FAH6DJJ Larry Page\n- 01JWRDEHPBN0BBJP57B9S108W6 Sergey Brin\n\nI will use the following schema to construct new objects:\n\n- type:dxos.org/type/Organization for Alphabet Inc.\n- type:dxos.org/type/Person for Ivan Zhao\n- type:dxos.org/type/Person for Simon Last\n- dxn:type:dxos.org/relation/Employer for Ivan's employer\n- dxn:type:dxos.org/relation/Employer for Simon's employer\n\n<status>Formatting results</status>\n\n</example>";
|
|
1648
1696
|
|
|
1649
|
-
//
|
|
1650
|
-
var
|
|
1697
|
+
// src/research/research.ts
|
|
1698
|
+
var __dxlog_file9 = "/__w/dxos/dxos/packages/core/assistant/src/research/research.ts";
|
|
1651
1699
|
var researchFn = defineFunction3({
|
|
1652
1700
|
description: "Research the web for information",
|
|
1653
|
-
inputSchema:
|
|
1654
|
-
query:
|
|
1701
|
+
inputSchema: Schema8.Struct({
|
|
1702
|
+
query: Schema8.String.annotations({
|
|
1655
1703
|
description: "The query to search for."
|
|
1656
1704
|
}),
|
|
1657
1705
|
// TOOD(burdon): Move to context.
|
|
1658
|
-
mockSearch:
|
|
1706
|
+
mockSearch: Schema8.optional(Schema8.Boolean).annotations({
|
|
1659
1707
|
description: "Whether to use the mock search tool.",
|
|
1660
1708
|
default: false
|
|
1661
1709
|
})
|
|
1662
1710
|
}),
|
|
1663
|
-
outputSchema:
|
|
1664
|
-
|
|
1665
|
-
result: Schema7.Any
|
|
1711
|
+
outputSchema: Schema8.Struct({
|
|
1712
|
+
result: Schema8.Unknown
|
|
1666
1713
|
}),
|
|
1667
|
-
handler:
|
|
1668
|
-
|
|
1669
|
-
const credentials = context.getService(CredentialsService);
|
|
1670
|
-
const { db } = context.getService(DatabaseService2);
|
|
1671
|
-
const tracing = context.getService(TracingService);
|
|
1672
|
-
tracing.write(create5(AgentStatusReport2, {
|
|
1714
|
+
handler: Effect6.fnUntraced(function* ({ data: { query, mockSearch } }) {
|
|
1715
|
+
yield* TracingService.emitStatus({
|
|
1673
1716
|
message: "Researching..."
|
|
1674
|
-
}));
|
|
1675
|
-
const exaCredential = await credentials.getCredential({
|
|
1676
|
-
service: "exa.ai"
|
|
1677
1717
|
});
|
|
1678
|
-
const
|
|
1679
|
-
|
|
1718
|
+
const graphWriteToolkit = makeGraphWriterToolkit({
|
|
1719
|
+
schema: DataTypes
|
|
1680
1720
|
});
|
|
1721
|
+
const toolkit = yield* AiToolkit4.merge(ExaToolkit, LocalSearchToolkit, graphWriteToolkit).pipe(Effect6.provide(Layer2.mergeAll(mockSearch ? MockExaHandler : LiveExaHandler, LocalSearchHandler, makeGraphWriterHandler(graphWriteToolkit))));
|
|
1681
1722
|
const printer = new ConsolePrinter();
|
|
1682
|
-
const session = new
|
|
1683
|
-
operationModel: "configured"
|
|
1684
|
-
});
|
|
1723
|
+
const session = new AiSession();
|
|
1685
1724
|
session.message.on((message) => printer.printMessage(message));
|
|
1686
1725
|
session.userMessage.on((message) => printer.printMessage(message));
|
|
1687
1726
|
session.block.on((block) => printer.printContentBlock(block));
|
|
1688
|
-
session.statusReport.on((status) => {
|
|
1689
|
-
log8.info("[agent] status", {
|
|
1690
|
-
status
|
|
1691
|
-
}, {
|
|
1692
|
-
F: __dxlog_file8,
|
|
1693
|
-
L: 58,
|
|
1694
|
-
S: void 0,
|
|
1695
|
-
C: (f, a) => f(...a)
|
|
1696
|
-
});
|
|
1697
|
-
tracing.write(status);
|
|
1698
|
-
});
|
|
1699
1727
|
session.streamEvent.on((event) => log8("stream", {
|
|
1700
1728
|
event
|
|
1701
1729
|
}, {
|
|
1702
|
-
F:
|
|
1703
|
-
L:
|
|
1704
|
-
S:
|
|
1730
|
+
F: __dxlog_file9,
|
|
1731
|
+
L: 62,
|
|
1732
|
+
S: this,
|
|
1705
1733
|
C: (f, a) => f(...a)
|
|
1706
1734
|
}));
|
|
1707
|
-
const
|
|
1708
|
-
|
|
1709
|
-
schema: DataTypes
|
|
1710
|
-
});
|
|
1711
|
-
log8.info("graphWriteTool", {
|
|
1712
|
-
schema: graphWriteTool.parameters
|
|
1713
|
-
}, {
|
|
1714
|
-
F: __dxlog_file8,
|
|
1715
|
-
L: 64,
|
|
1716
|
-
S: void 0,
|
|
1717
|
-
C: (f, a) => f(...a)
|
|
1718
|
-
});
|
|
1719
|
-
const result = await session.run({
|
|
1720
|
-
client: ai.client,
|
|
1721
|
-
systemPrompt: instructions_research_default,
|
|
1722
|
-
artifacts: [],
|
|
1723
|
-
tools: [
|
|
1724
|
-
searchTool,
|
|
1725
|
-
graphWriteTool
|
|
1726
|
-
],
|
|
1735
|
+
const result = yield* session.run({
|
|
1736
|
+
prompt: query,
|
|
1727
1737
|
history: [],
|
|
1728
|
-
|
|
1738
|
+
systemPrompt: instructions_research_default,
|
|
1739
|
+
toolkit
|
|
1729
1740
|
});
|
|
1730
1741
|
return {
|
|
1731
1742
|
result
|
|
1732
1743
|
};
|
|
1733
|
-
}
|
|
1744
|
+
}, Effect6.provide(AiService2.model("@anthropic/claude-3-5-sonnet-20241022")))
|
|
1734
1745
|
});
|
|
1735
1746
|
|
|
1736
|
-
//
|
|
1737
|
-
|
|
1747
|
+
// src/templates/prompt.ts
|
|
1748
|
+
import { Template } from "@dxos/blueprints";
|
|
1738
1749
|
|
|
1739
|
-
//
|
|
1740
|
-
|
|
1741
|
-
import { Key, Obj as Obj3, Type } from "@dxos/echo";
|
|
1742
|
-
var BlueprintStep = Schema8.Struct({
|
|
1743
|
-
id: Key.ObjectId,
|
|
1744
|
-
instructions: Schema8.String,
|
|
1745
|
-
tools: Schema8.optional(Schema8.Array(Schema8.String))
|
|
1746
|
-
});
|
|
1747
|
-
var BlueprintDefinition = Schema8.Struct({
|
|
1748
|
-
steps: Schema8.Array(BlueprintStep.pipe(Schema8.omit("id")))
|
|
1749
|
-
});
|
|
1750
|
-
var Blueprint = Schema8.Struct({
|
|
1751
|
-
name: Schema8.optional(Schema8.String),
|
|
1752
|
-
steps: Schema8.Array(BlueprintStep)
|
|
1753
|
-
}).pipe(Type.Obj({
|
|
1754
|
-
typename: "dxos.org/type/Blueprint",
|
|
1755
|
-
version: "0.1.0"
|
|
1756
|
-
}));
|
|
1757
|
-
(function(BlueprintBuilder2) {
|
|
1758
|
-
BlueprintBuilder2.create = () => new Builder();
|
|
1759
|
-
class Builder {
|
|
1760
|
-
constructor() {
|
|
1761
|
-
this._steps = [];
|
|
1762
|
-
}
|
|
1763
|
-
step(instructions, options) {
|
|
1764
|
-
this._steps.push({
|
|
1765
|
-
id: Key.ObjectId.random(),
|
|
1766
|
-
instructions,
|
|
1767
|
-
tools: options?.tools ?? []
|
|
1768
|
-
});
|
|
1769
|
-
return this;
|
|
1770
|
-
}
|
|
1771
|
-
build() {
|
|
1772
|
-
return Obj3.make(Blueprint, {
|
|
1773
|
-
steps: this._steps
|
|
1774
|
-
});
|
|
1775
|
-
}
|
|
1776
|
-
}
|
|
1777
|
-
})(BlueprintBuilder || (BlueprintBuilder = {}));
|
|
1778
|
-
(function(BlueprintParser2) {
|
|
1779
|
-
BlueprintParser2.create = () => new Parser();
|
|
1780
|
-
class Parser {
|
|
1781
|
-
parse({ steps }) {
|
|
1782
|
-
const builder = BlueprintBuilder.create();
|
|
1783
|
-
for (const step of steps) {
|
|
1784
|
-
builder.step(step.instructions, {
|
|
1785
|
-
tools: step.tools ?? []
|
|
1786
|
-
});
|
|
1787
|
-
}
|
|
1788
|
-
return builder.build();
|
|
1789
|
-
}
|
|
1790
|
-
}
|
|
1791
|
-
})(BlueprintParser || (BlueprintParser = {}));
|
|
1792
|
-
var BlueprintBuilder;
|
|
1793
|
-
var BlueprintParser;
|
|
1750
|
+
// raw-loader:./assistant.tpl?raw
|
|
1751
|
+
var assistant_default = "{{! System Prompt }}\n\nYou are a friendly, advanced AI assistant capable of creating and managing artifacts from available data and tools.\nYour task is to process user commands and questions and decide how best to respond.\nIn some cases, you will need to create or reference data objects called artifacts.\n\nFollow these guidelines carefully:\n\n{{section}}. Decision-making:\n\n{{#if cot}}\nBefore responding, explain your reasoning and include your detailed chain-of-thought in a <cot> tag.\n{{/if}}\n\nInclude the following steps:\n\n- Analyze the structure and type of the content in the user's message.\n- Can you complete the task using the available artifact definitions?\n- If you can't complete the task using the available artifact definitions, query the list of available artifact definitions using the appropriate tool.\n- Identify which artifact definitions are relevant to the user's request.\n- Evaluate the potential benefits of creating an artifact vs. normal processing for each identified element.\n- Make a final decision on whether to create an artifact and explain your reasoning.\n- Are the required artifact definitions already available?\n- If not, select which artifact definition(s) will be the most relevant and require them using the require_artifact_definitions tool.\n- The require'd artifact tools will be available for use after require.\n- If creating an artifact, outline how you will structure it within the response.\n- Decide if the artifact needs to be shown to the user.\n- Call the show tool to show the artifact to the user.\n- If you ask the user a multiple choice question, then present each of the possible answers as concise text inside <option> tags inside a well formed <select> tag.\n- If you have suggestions for follow-up actions then present each action as text within a <suggest> tag.\n- Your reasoning must include: whether to use artifacts or not, to create one or query, whether to show the artifact to the user, and how to structure the response.\n\nIf the user asks for a list of tools, then just emit a single self-closing <tool-list/> tag instead of listing the tools.The tag will be replaced with the list of tools when the response is rendered.\nDo not list the tools or artifacts in your response, only emit the tag.\nDo not mention the tag anywhere else in your response unless you are rendering a tool list.\n\n{{section}}. Artifacts:\n\n- Determine if the interaction involves an artifact. Prefer artifacts for tables, lists, spreadsheets, kanbans, games, images, and other structured data.\n- Determine if the user is explicitly talking about creating a new artifact, or wants to use an existing artifact.\n- If it is ambiguous, query for existing artifacts first and then decide.\n- If you decide to create an artifact, call the associated tool to create the artifact.\n- Artifacts are stored in the database. Tools are used to create and query artifacts.\n- If you are unsure about creating an artifact ask the user for clarification.\n\n{{#if artifacts}}\n{{section}}. Artifact Rules:\n\n- Artifacts are mutable objects that can change over the course of the conversation.\n- Always re-query the artifact using the tool (like query or inspect) to get the latest state of the artifact before answering the user.\n- You must never generate the id of the artifact; only recall the ids that are already in the history.\n- Artifacts are created by requiring the specific artifact using the require_artifact tool and creating it by calling the associated tool.\n\n{{section}}. Artifact Providers:\n\n{{#each artifacts}}\n- {{this}}\n{{/each}}\n{{/if}}\n\n{{#if associatedArtifact}}\n{{section}}. Associated artifact:\n\nThe following ID and typename identify the artifact associated with this conversation.\nThis conversation appears alongside the associated artifact as a peer, and the user is likely to make reference to and requests about it.\nYou can interact with this artifact using tools.\n\nID: {{associatedArtifact.id}}\nTypename: {{associatedArtifact.typename}}\n{{/if}}\n\n{{#if suggestions}}\n{{section}}. Suggested actions:\n\n- You can add suggested actions at the end of your response.\n- Suggested actions should be very concise and start with a verb and be phrased as a command to an agent -- not a question to the user.\n- Suggested actions must be in the form of a user instruction that you can follow.\n- Suggested actions could include actions that create artifacts.\n- Suggested actions must be enclosed in a <suggest> tag and on a separate line.\n Examples:\n <suggest>Show the data on a map.</suggest>\n <suggest>Create a kanban from the table.</suggest>\n\n- If you have asked a multiple choice question, then present each of the possible answers as concise text inside <option> tags inside a well formed <select> tag.\n Example:\n <select><option>Yes</option><option>No</option></select>\n{{/if}}\n\n{{section}}. Content proposals:\n\nYou can propose content to add to associated artifacts. Enclose the content you are proposing to add in a <proposal> tag on a separate line.\nFor example:\n<proposal>Apples add a delightful crunch and natural sweetness to salads</proposal>\n\n{{section}}. Output Formats:\n\nIt is very important to respond in the correct format.\n\n{{#if cot}}\n- Your detailed chain-of-thought must be in the form of a markdown list enclosed in <cot> tags.\n- The <cot> tag should be the first thing in your response.\n{{/if}}\n- Suggested actions must be enclosed in a <suggest> tag and on a separate line.\n- Content proposals must be enclosed in a <proposal> tag and on a separate line.\n\nReferences:\n\n- Both user and you can reference external data in the markdown format: [label][URI].\n- If you get references back from a tool call, you can render them as is by preserving the ID literally.\n\n{{instructions}}";
|
|
1794
1752
|
|
|
1795
|
-
//
|
|
1796
|
-
|
|
1797
|
-
|
|
1798
|
-
import { Event as Event2 } from "@dxos/async";
|
|
1799
|
-
import { Key as Key2, Obj as Obj4 } from "@dxos/echo";
|
|
1800
|
-
import { log as log9 } from "@dxos/log";
|
|
1801
|
-
import { isNonNullable as isNonNullable2 } from "@dxos/util";
|
|
1802
|
-
var __dxlog_file9 = "/home/runner/work/dxos/dxos/packages/core/assistant/src/blueprint/machine.ts";
|
|
1803
|
-
var SYSTEM_PROMPT = `
|
|
1804
|
-
You are a smart Rule-Following Agent.
|
|
1805
|
-
Rule-Following Agent executes the command that the user sent in the last message.
|
|
1806
|
-
After doing the work, the Rule-Following Agent calls report tool.
|
|
1807
|
-
If the Rule-Following agent believes that no action is needed, it calls the report tool with "skipped" status.
|
|
1808
|
-
If the Rule-Following Agent is unable to perform the task, it calls the report tool with "bail" status.
|
|
1809
|
-
Rule-Following Agent explains the reason it is unable to perform the task before bailing.
|
|
1810
|
-
The Rule-Following Agent can express creativity and imagination in the way it performs the task.
|
|
1811
|
-
The Rule-Following Agent precisely follows the instructions.
|
|
1812
|
-
`;
|
|
1813
|
-
var INITIAL_STATE = {
|
|
1814
|
-
state: "working",
|
|
1815
|
-
history: [],
|
|
1816
|
-
trace: []
|
|
1817
|
-
};
|
|
1818
|
-
var BlueprintMachine = class {
|
|
1819
|
-
constructor(registry, blueprint) {
|
|
1820
|
-
this.registry = registry;
|
|
1821
|
-
this.blueprint = blueprint;
|
|
1822
|
-
this.begin = new Event2();
|
|
1823
|
-
this.end = new Event2();
|
|
1824
|
-
this.stepStart = new Event2();
|
|
1825
|
-
this.stepComplete = new Event2();
|
|
1826
|
-
this.message = new Event2();
|
|
1827
|
-
this.block = new Event2();
|
|
1828
|
-
this._state = structuredClone(INITIAL_STATE);
|
|
1829
|
-
}
|
|
1830
|
-
get state() {
|
|
1831
|
-
return this._state;
|
|
1832
|
-
}
|
|
1833
|
-
setLogger(logger) {
|
|
1834
|
-
this.logger = logger;
|
|
1835
|
-
return this;
|
|
1836
|
-
}
|
|
1837
|
-
async runToCompletion(options) {
|
|
1838
|
-
const invocationId = Key2.ObjectId.random();
|
|
1839
|
-
log9.info("runToCompletion", {
|
|
1840
|
-
invocationId,
|
|
1841
|
-
options
|
|
1842
|
-
}, {
|
|
1843
|
-
F: __dxlog_file9,
|
|
1844
|
-
L: 107,
|
|
1845
|
-
S: this,
|
|
1846
|
-
C: (f, a) => f(...a)
|
|
1847
|
-
});
|
|
1848
|
-
this.begin.emit();
|
|
1849
|
-
this.logger?.log({
|
|
1850
|
-
type: "begin",
|
|
1851
|
-
invocationId
|
|
1852
|
-
});
|
|
1853
|
-
let firstStep = true;
|
|
1854
|
-
while (this._state.state !== "done") {
|
|
1855
|
-
const input = firstStep ? options.input : void 0;
|
|
1856
|
-
firstStep = false;
|
|
1857
|
-
this._state = await this._execStep(invocationId, this._state, {
|
|
1858
|
-
input,
|
|
1859
|
-
aiClient: options.aiClient
|
|
1860
|
-
});
|
|
1861
|
-
const step = this.blueprint.steps.find((step2) => step2.id === this._state.trace.at(-1)?.stepId);
|
|
1862
|
-
this.stepComplete.emit(step);
|
|
1863
|
-
this.logger?.log({
|
|
1864
|
-
type: "step-complete",
|
|
1865
|
-
invocationId,
|
|
1866
|
-
step
|
|
1867
|
-
});
|
|
1868
|
-
if (this._state.state === "bail") {
|
|
1869
|
-
throw new Error("Agent unable to follow the blueprint");
|
|
1870
|
-
}
|
|
1871
|
-
}
|
|
1872
|
-
this.end.emit();
|
|
1873
|
-
this.logger?.log({
|
|
1874
|
-
type: "end",
|
|
1875
|
-
invocationId
|
|
1876
|
-
});
|
|
1877
|
-
}
|
|
1878
|
-
async _execStep(invocationId, state, options) {
|
|
1879
|
-
const prevStep = this.blueprint.steps.findIndex((step) => step.id === this._state.trace.at(-1)?.stepId);
|
|
1880
|
-
if (prevStep === this.blueprint.steps.length - 1) {
|
|
1881
|
-
throw new Error("Done execution blueprint");
|
|
1882
|
-
}
|
|
1883
|
-
const nextStep = this.blueprint.steps[prevStep + 1];
|
|
1884
|
-
const onLastStep = prevStep === this.blueprint.steps.length - 2;
|
|
1885
|
-
this.stepStart.emit(nextStep);
|
|
1886
|
-
this.logger?.log({
|
|
1887
|
-
type: "step-start",
|
|
1888
|
-
invocationId,
|
|
1889
|
-
step: nextStep
|
|
1890
|
-
});
|
|
1891
|
-
const ReportSchema = Schema9.Struct({
|
|
1892
|
-
status: Schema9.Literal("done", "bailed", "skipped").annotations({
|
|
1893
|
-
description: "The status of the task completion"
|
|
1894
|
-
}),
|
|
1895
|
-
comment: Schema9.String.annotations({
|
|
1896
|
-
description: "A comment about the task completion. If you bailed, you must explain why in detail (min couple of sentences)."
|
|
1897
|
-
})
|
|
1898
|
-
});
|
|
1899
|
-
const report = createTool4("system", {
|
|
1900
|
-
name: "report",
|
|
1901
|
-
description: "This tool reports that the agent has completed the task or is unable to do so.",
|
|
1902
|
-
schema: ReportSchema,
|
|
1903
|
-
execute: async (input) => ToolResult4.Break(input)
|
|
1904
|
-
});
|
|
1905
|
-
const session = new AISession({
|
|
1906
|
-
operationModel: "configured"
|
|
1907
|
-
});
|
|
1908
|
-
session.userMessage.pipeInto(this.message);
|
|
1909
|
-
session.message.pipeInto(this.message);
|
|
1910
|
-
session.block.pipeInto(this.block);
|
|
1911
|
-
const inputMessages = options.input ? [
|
|
1912
|
-
Obj4.make(Message3, {
|
|
1913
|
-
role: "user",
|
|
1914
|
-
content: [
|
|
1915
|
-
taggedDataBlock("input", options.input)
|
|
1916
|
-
]
|
|
1917
|
-
})
|
|
1918
|
-
] : [];
|
|
1919
|
-
inputMessages.forEach((message) => {
|
|
1920
|
-
this.message.emit(message);
|
|
1921
|
-
this.logger?.log({
|
|
1922
|
-
type: "message",
|
|
1923
|
-
invocationId,
|
|
1924
|
-
message
|
|
1925
|
-
});
|
|
1926
|
-
});
|
|
1927
|
-
const tools = nextStep.tools?.map((tool) => this.registry.get(tool)).filter(isNonNullable2) ?? [];
|
|
1928
|
-
const messages = await session.run({
|
|
1929
|
-
systemPrompt: SYSTEM_PROMPT,
|
|
1930
|
-
history: [
|
|
1931
|
-
...state.history,
|
|
1932
|
-
...inputMessages
|
|
1933
|
-
],
|
|
1934
|
-
tools: [
|
|
1935
|
-
...tools,
|
|
1936
|
-
report
|
|
1937
|
-
],
|
|
1938
|
-
artifacts: [],
|
|
1939
|
-
client: options.aiClient,
|
|
1940
|
-
prompt: nextStep.instructions
|
|
1941
|
-
});
|
|
1942
|
-
const { messages: trimmedHistory, call: lastBlock } = popLastToolCall(messages);
|
|
1943
|
-
if (!lastBlock) {
|
|
1944
|
-
throw new Error("Agent did not call the report tool");
|
|
1945
|
-
}
|
|
1946
|
-
const { status, comment } = ReportSchema.pipe(Schema9.decodeUnknownSync)(lastBlock.input);
|
|
1947
|
-
return {
|
|
1948
|
-
history: [
|
|
1949
|
-
...state.history,
|
|
1950
|
-
...inputMessages,
|
|
1951
|
-
...trimmedHistory
|
|
1952
|
-
],
|
|
1953
|
-
trace: [
|
|
1954
|
-
...state.trace,
|
|
1955
|
-
{
|
|
1956
|
-
stepId: nextStep.id,
|
|
1957
|
-
status,
|
|
1958
|
-
comment
|
|
1959
|
-
}
|
|
1960
|
-
],
|
|
1961
|
-
state: Match.value(status).pipe(Match.withReturnType(), Match.when("done", () => onLastStep ? "done" : "working"), Match.when("skipped", () => onLastStep ? "done" : "working"), Match.when("bailed", () => "bail"), Match.exhaustive)
|
|
1962
|
-
};
|
|
1963
|
-
}
|
|
1964
|
-
};
|
|
1965
|
-
var taggedDataBlock = (tag, data) => {
|
|
1966
|
-
return {
|
|
1967
|
-
type: "text",
|
|
1968
|
-
text: `<${tag}>
|
|
1969
|
-
${JSON.stringify(data, null, 2)}
|
|
1970
|
-
</${tag}>`
|
|
1971
|
-
};
|
|
1972
|
-
};
|
|
1973
|
-
var popLastToolCall = (messages) => {
|
|
1974
|
-
const lastBlock = messages.at(-1)?.content.at(-1);
|
|
1975
|
-
if (lastBlock?.type !== "tool_use") {
|
|
1976
|
-
return {
|
|
1977
|
-
messages
|
|
1978
|
-
};
|
|
1979
|
-
}
|
|
1980
|
-
const trimmedHistory = [
|
|
1981
|
-
...messages.slice(0, -1),
|
|
1982
|
-
{
|
|
1983
|
-
...messages.at(-1),
|
|
1984
|
-
content: [
|
|
1985
|
-
...messages.at(-1).content.slice(0, -1)
|
|
1986
|
-
]
|
|
1987
|
-
}
|
|
1988
|
-
];
|
|
1989
|
-
return {
|
|
1990
|
-
messages: trimmedHistory,
|
|
1991
|
-
call: lastBlock
|
|
1992
|
-
};
|
|
1753
|
+
// src/templates/prompt.ts
|
|
1754
|
+
var createSystemPrompt = (options) => {
|
|
1755
|
+
return Template.createPrompt(assistant_default, options);
|
|
1993
1756
|
};
|
|
1994
1757
|
|
|
1995
|
-
//
|
|
1996
|
-
import {
|
|
1997
|
-
import
|
|
1998
|
-
|
|
1999
|
-
|
|
2000
|
-
|
|
2001
|
-
|
|
2002
|
-
|
|
2003
|
-
|
|
2004
|
-
|
|
2005
|
-
|
|
2006
|
-
|
|
2007
|
-
|
|
2008
|
-
|
|
2009
|
-
|
|
2010
|
-
|
|
2011
|
-
|
|
2012
|
-
|
|
2013
|
-
|
|
2014
|
-
|
|
2015
|
-
|
|
2016
|
-
|
|
2017
|
-
|
|
2018
|
-
|
|
2019
|
-
|
|
2020
|
-
|
|
2021
|
-
|
|
2022
|
-
|
|
2023
|
-
|
|
2024
|
-
|
|
2025
|
-
|
|
2026
|
-
|
|
2027
|
-
|
|
2028
|
-
case "begin":
|
|
2029
|
-
this.logger.log("begin", {
|
|
2030
|
-
invocationId: event.invocationId
|
|
2031
|
-
});
|
|
2032
|
-
break;
|
|
2033
|
-
case "end":
|
|
2034
|
-
this.logger.log("end", {
|
|
2035
|
-
invocationId: event.invocationId
|
|
2036
|
-
});
|
|
2037
|
-
break;
|
|
2038
|
-
case "step-start":
|
|
2039
|
-
this.logger.log("step-start", {
|
|
2040
|
-
invocationId: event.invocationId,
|
|
2041
|
-
step: event.step
|
|
2042
|
-
});
|
|
2043
|
-
break;
|
|
2044
|
-
case "step-complete":
|
|
2045
|
-
this.logger.log("step-complete", {
|
|
2046
|
-
invocationId: event.invocationId,
|
|
2047
|
-
step: event.step
|
|
2048
|
-
});
|
|
2049
|
-
break;
|
|
2050
|
-
case "message":
|
|
2051
|
-
this.logger.log("message", {
|
|
2052
|
-
invocationId: event.invocationId,
|
|
2053
|
-
message: event.message
|
|
2054
|
-
});
|
|
2055
|
-
break;
|
|
2056
|
-
case "block":
|
|
2057
|
-
this.logger.log("block", {
|
|
2058
|
-
invocationId: event.invocationId,
|
|
2059
|
-
block: event.block
|
|
2060
|
-
});
|
|
2061
|
-
break;
|
|
1758
|
+
// src/types.ts
|
|
1759
|
+
import { Schema as Schema9 } from "effect";
|
|
1760
|
+
import { DXN as DXN3, LOCAL_SPACE_TAG } from "@dxos/keys";
|
|
1761
|
+
var createArtifactElement = (id) => `<artifact id=${id} />`;
|
|
1762
|
+
var ArtifactId = class extends Schema9.String.annotations({
|
|
1763
|
+
description: `
|
|
1764
|
+
The ID of the referenced object. Formats accepted:
|
|
1765
|
+
- DXN (dxn:echo:@:XXXXX). DXNs can be prepended with an @ symbol for compatibility with in-text references.
|
|
1766
|
+
- space ID, object ID tuple (spaceID:objectID)
|
|
1767
|
+
- Only object ID that is assumed to be in the current space (XXXXX)
|
|
1768
|
+
`,
|
|
1769
|
+
examples: [
|
|
1770
|
+
"dxn:echo:@:XXXXX",
|
|
1771
|
+
"@dxn:echo:@:XXXXX",
|
|
1772
|
+
"spaceID:objectID",
|
|
1773
|
+
"XXXXX"
|
|
1774
|
+
]
|
|
1775
|
+
}) {
|
|
1776
|
+
static toDXN(reference, owningSpaceId) {
|
|
1777
|
+
if (reference.startsWith("@dxn:")) {
|
|
1778
|
+
return DXN3.parse(reference.slice(1));
|
|
1779
|
+
} else if (reference.startsWith("dxn:")) {
|
|
1780
|
+
return DXN3.parse(reference);
|
|
1781
|
+
} else if (/^[A-Z0-9]+:[A-Z0-9]+$/.test(reference)) {
|
|
1782
|
+
const [spaceId, objectId] = reference.split(":");
|
|
1783
|
+
return new DXN3(DXN3.kind.ECHO, [
|
|
1784
|
+
spaceId === owningSpaceId ? LOCAL_SPACE_TAG : spaceId,
|
|
1785
|
+
objectId
|
|
1786
|
+
]);
|
|
1787
|
+
} else if (/^[A-Z0-9]+$/.test(reference)) {
|
|
1788
|
+
return DXN3.fromLocalObjectId(reference);
|
|
1789
|
+
} else {
|
|
1790
|
+
throw new Error(`Unable to parse object reference: ${reference}`);
|
|
2062
1791
|
}
|
|
2063
1792
|
}
|
|
2064
1793
|
};
|
|
2065
|
-
var setLogger = (machine, logger) => {
|
|
2066
|
-
return combine(machine.begin.on(() => {
|
|
2067
|
-
logger.log("Starting...");
|
|
2068
|
-
}), machine.stepStart.on((step) => {
|
|
2069
|
-
const index = machine.blueprint.steps.indexOf(step);
|
|
2070
|
-
logger.log(`Step ${index + 1} of ${machine.blueprint.steps.length}`);
|
|
2071
|
-
logger.log(`Instructions: ${step.instructions}`);
|
|
2072
|
-
}), machine.stepComplete.on((step) => {
|
|
2073
|
-
const trace = machine.state.trace.find((t) => t.stepId === step.id);
|
|
2074
|
-
logger.log(`Complete: ${trace?.comment}`);
|
|
2075
|
-
}), machine.end.on(() => {
|
|
2076
|
-
logger.log("OK");
|
|
2077
|
-
}));
|
|
2078
|
-
};
|
|
2079
|
-
var setConsolePrinter = (machine, verbose = false) => {
|
|
2080
|
-
const printer = new ConsolePrinter2();
|
|
2081
|
-
return combine(machine.begin.on(() => printTrace(machine.blueprint, machine.state)), machine.stepStart.on((step) => console.log(`
|
|
2082
|
-
${chalk.magenta(`${chalk.bold(`STEP ${machine.blueprint.steps.indexOf(step) + 1} of ${machine.blueprint.steps.length}:`)} ${step.instructions}`)}
|
|
2083
|
-
`)), machine.stepComplete.on(() => printTrace(machine.blueprint, machine.state)), machine.end.on(() => console.log("DONE")), verbose ? [
|
|
2084
|
-
machine.message.on((msg) => printer.printMessage(msg)),
|
|
2085
|
-
machine.block.on((block) => printer.printContentBlock(block))
|
|
2086
|
-
] : []);
|
|
2087
|
-
};
|
|
2088
|
-
var BREAK_LINE = `
|
|
2089
|
-
${"_".repeat(80)}
|
|
2090
|
-
`;
|
|
2091
|
-
var printTrace = (blueprint, state) => {
|
|
2092
|
-
console.group(chalk.bold("\nBlueprint"));
|
|
2093
|
-
blueprint.steps.forEach((step) => {
|
|
2094
|
-
const traceStep = state.trace.find((t) => t.stepId === step.id);
|
|
2095
|
-
let color = chalk.gray;
|
|
2096
|
-
let bullet = "\u25CB";
|
|
2097
|
-
if (traceStep) {
|
|
2098
|
-
switch (traceStep.status) {
|
|
2099
|
-
case "done":
|
|
2100
|
-
color = chalk.green;
|
|
2101
|
-
bullet = "\u2713";
|
|
2102
|
-
break;
|
|
2103
|
-
case "skipped":
|
|
2104
|
-
color = chalk.blue;
|
|
2105
|
-
bullet = "\u2193";
|
|
2106
|
-
break;
|
|
2107
|
-
case "bailed":
|
|
2108
|
-
color = chalk.red;
|
|
2109
|
-
bullet = "\u2717";
|
|
2110
|
-
break;
|
|
2111
|
-
}
|
|
2112
|
-
}
|
|
2113
|
-
console.log(color(`
|
|
2114
|
-
${bullet} ${step.instructions}`));
|
|
2115
|
-
if (traceStep?.comment) {
|
|
2116
|
-
console.log(chalk.white(` \u21B3 ${traceStep.comment}`));
|
|
2117
|
-
}
|
|
2118
|
-
});
|
|
2119
|
-
console.groupEnd();
|
|
2120
|
-
console.log(BREAK_LINE);
|
|
2121
|
-
};
|
|
2122
1794
|
export {
|
|
2123
|
-
|
|
2124
|
-
|
|
2125
|
-
|
|
2126
|
-
|
|
2127
|
-
|
|
2128
|
-
|
|
2129
|
-
|
|
2130
|
-
|
|
2131
|
-
BlueprintStep,
|
|
2132
|
-
BufferedLogger,
|
|
1795
|
+
AiSession,
|
|
1796
|
+
ArtifactDiffResolver,
|
|
1797
|
+
ArtifactId,
|
|
1798
|
+
Bindings,
|
|
1799
|
+
ContextBinder,
|
|
1800
|
+
ContextBinding,
|
|
1801
|
+
Conversation,
|
|
1802
|
+
ExaToolkit,
|
|
2133
1803
|
ExtractionInput,
|
|
2134
1804
|
ExtractionOutput,
|
|
1805
|
+
LiveExaHandler,
|
|
1806
|
+
LocalSearchHandler,
|
|
1807
|
+
LocalSearchToolkit,
|
|
1808
|
+
MockExaHandler,
|
|
2135
1809
|
ReferencedQuotes,
|
|
2136
1810
|
Subgraph,
|
|
2137
1811
|
VersionPin,
|
|
2138
1812
|
combineNerTokens,
|
|
2139
1813
|
createArtifactElement,
|
|
2140
|
-
createExaTool,
|
|
2141
1814
|
createExtractionSchema,
|
|
2142
|
-
|
|
2143
|
-
createLocalSearchTool,
|
|
2144
|
-
createMockExaTool,
|
|
1815
|
+
createSystemPrompt,
|
|
2145
1816
|
createTokenGroups,
|
|
2146
1817
|
extractFullEntities,
|
|
2147
1818
|
extractionAnthropicFn,
|
|
@@ -2151,10 +1822,12 @@ export {
|
|
|
2151
1822
|
getNer,
|
|
2152
1823
|
getSanitizedSchemaName,
|
|
2153
1824
|
insertReferences,
|
|
1825
|
+
makeGraphWriterHandler,
|
|
1826
|
+
makeGraphWriterToolkit,
|
|
1827
|
+
makeToolExecutionServiceFromFunctions,
|
|
1828
|
+
makeToolResolverFromFunctions,
|
|
2154
1829
|
processTranscriptMessage,
|
|
2155
1830
|
researchFn,
|
|
2156
|
-
sanitizeObjects
|
|
2157
|
-
setConsolePrinter,
|
|
2158
|
-
setLogger
|
|
1831
|
+
sanitizeObjects
|
|
2159
1832
|
};
|
|
2160
1833
|
//# sourceMappingURL=index.mjs.map
|