@dxos/assistant 0.8.4-main.84f28bd → 0.8.4-main.b97322e

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.
Files changed (82) hide show
  1. package/dist/lib/browser/index.mjs +623 -811
  2. package/dist/lib/browser/index.mjs.map +4 -4
  3. package/dist/lib/browser/meta.json +1 -1
  4. package/dist/lib/node-esm/index.mjs +623 -811
  5. package/dist/lib/node-esm/index.mjs.map +4 -4
  6. package/dist/lib/node-esm/meta.json +1 -1
  7. package/dist/types/src/context/binder.d.ts +4 -4
  8. package/dist/types/src/context/binder.d.ts.map +1 -1
  9. package/dist/types/src/context/binding.d.ts +24 -6
  10. package/dist/types/src/context/binding.d.ts.map +1 -1
  11. package/dist/types/src/conversation/conversation.d.ts +12 -18
  12. package/dist/types/src/conversation/conversation.d.ts.map +1 -1
  13. package/dist/types/src/errors.d.ts +38 -0
  14. package/dist/types/src/errors.d.ts.map +1 -0
  15. package/dist/types/src/extraction/extraction-llm-function/extraction-llm-function.d.ts.map +1 -1
  16. package/dist/types/src/extraction/extraction-ner-function/extraction-ner-function.d.ts +127 -33
  17. package/dist/types/src/extraction/extraction-ner-function/extraction-ner-function.d.ts.map +1 -1
  18. package/dist/types/src/extraction/extraction-ner-function/named-entity-recognition.d.ts +1 -1
  19. package/dist/types/src/extraction/extraction-ner-function/named-entity-recognition.d.ts.map +1 -1
  20. package/dist/types/src/extraction/extraction.d.ts +100 -42
  21. package/dist/types/src/extraction/extraction.d.ts.map +1 -1
  22. package/dist/types/src/functions/index.d.ts +2 -0
  23. package/dist/types/src/functions/index.d.ts.map +1 -0
  24. package/dist/types/src/functions/services.d.ts +6 -0
  25. package/dist/types/src/functions/services.d.ts.map +1 -0
  26. package/dist/types/src/index.d.ts +2 -2
  27. package/dist/types/src/index.d.ts.map +1 -1
  28. package/dist/types/src/research/exa.d.ts +10 -5
  29. package/dist/types/src/research/exa.d.ts.map +1 -1
  30. package/dist/types/src/research/graph.d.ts +18 -8
  31. package/dist/types/src/research/graph.d.ts.map +1 -1
  32. package/dist/types/src/research/research.d.ts +1 -1
  33. package/dist/types/src/research/research.d.ts.map +1 -1
  34. package/dist/types/src/session/session.d.ts +170 -193
  35. package/dist/types/src/session/session.d.ts.map +1 -1
  36. package/dist/types/src/session/version-pin.d.ts +2 -2
  37. package/dist/types/src/session/version-pin.d.ts.map +1 -1
  38. package/dist/types/src/templates/index.d.ts +2 -0
  39. package/dist/types/src/templates/index.d.ts.map +1 -0
  40. package/dist/types/src/templates/prompt.d.ts +30 -0
  41. package/dist/types/src/templates/prompt.d.ts.map +1 -0
  42. package/dist/types/src/types.d.ts +10 -0
  43. package/dist/types/src/types.d.ts.map +1 -1
  44. package/dist/types/tsconfig.tsbuildinfo +1 -1
  45. package/package.json +29 -21
  46. package/src/context/binder.ts +6 -4
  47. package/src/context/binding.ts +4 -3
  48. package/src/conversation/conversation.ts +54 -61
  49. package/src/errors.ts +10 -0
  50. package/src/extraction/extraction-llm-function/extraction-llm-function.test.ts +6 -18
  51. package/src/extraction/extraction-llm-function/extraction-llm-function.ts +18 -14
  52. package/src/extraction/extraction-ner-function/extraction-ner-function.ts +6 -3
  53. package/src/extraction/extraction-ner-function/named-entity-recognition.test.ts +2 -2
  54. package/src/extraction/extraction-ner-function/named-entity-recognition.ts +1 -1
  55. package/src/functions/index.ts +5 -0
  56. package/src/functions/services.ts +139 -0
  57. package/src/index.ts +2 -2
  58. package/src/research/exa.ts +56 -59
  59. package/src/research/graph.test.ts +50 -1
  60. package/src/research/graph.ts +85 -53
  61. package/src/research/instructions-research.tpl +1 -0
  62. package/src/research/research.test.ts +27 -27
  63. package/src/research/research.ts +50 -53
  64. package/src/session/__snapshots__/session.test.ts.snap +32 -0
  65. package/src/session/session.test.ts +90 -55
  66. package/src/session/session.ts +215 -461
  67. package/src/session/version-pin.test.ts +2 -21
  68. package/src/session/version-pin.ts +5 -5
  69. package/src/summarization/summarization.test.ts +75 -88
  70. package/src/templates/assistant.tpl +111 -0
  71. package/src/templates/index.ts +5 -0
  72. package/src/templates/prompt.ts +45 -0
  73. package/src/types.ts +40 -1
  74. package/dist/types/src/blueprint/blueprint.d.ts +0 -41
  75. package/dist/types/src/blueprint/blueprint.d.ts.map +0 -1
  76. package/dist/types/src/blueprint/index.d.ts +0 -3
  77. package/dist/types/src/blueprint/index.d.ts.map +0 -1
  78. package/dist/types/src/blueprint/registry.d.ts +0 -7
  79. package/dist/types/src/blueprint/registry.d.ts.map +0 -1
  80. package/src/blueprint/blueprint.ts +0 -75
  81. package/src/blueprint/index.ts +0 -6
  82. package/src/blueprint/registry.ts +0 -15
@@ -1,74 +1,5 @@
1
1
  import { createRequire } from 'node:module';const require = createRequire(import.meta.url);
2
2
 
3
- // src/blueprint/blueprint.ts
4
- import { Schema } from "effect";
5
- import { ToolId } from "@dxos/ai";
6
- import { Type } from "@dxos/echo";
7
- import { LabelAnnotation } from "@dxos/echo-schema";
8
- var Blueprint = Schema.Struct({
9
- /**
10
- * Global registry ID.
11
- * NOTE: Once a blueprint has been cloned from the registry, its stored definition may converge,
12
- * but the `key` property refers to the original registry entry.
13
- */
14
- // TODO(burdon): Create Format type.
15
- key: Schema.String.annotations({
16
- description: "Unique registration key for the blueprint"
17
- }),
18
- /**
19
- * Human-readable name of the blueprint.
20
- */
21
- name: Schema.String.annotations({
22
- description: "Human-readable name of the blueprint"
23
- }),
24
- /**
25
- * Description of the blueprint's purpose and functionality.
26
- */
27
- description: Schema.optional(Schema.String).annotations({
28
- description: "Description of the blueprint's purpose and functionality"
29
- }),
30
- /**
31
- * Instructions that guide the AI assistant's behavior and responses.
32
- * These are system prompts or guidelines that the AI should follow.
33
- */
34
- instructions: Schema.String.annotations({
35
- description: "Instructions that guide the AI assistant's behavior and responses"
36
- }),
37
- /**
38
- * Array of tools that the AI assistant can use when this blueprint is active.
39
- */
40
- tools: Schema.Array(ToolId).annotations({
41
- description: "Array of tools that the AI assistant can use when this blueprint is active"
42
- }),
43
- /**
44
- * Array of artifacts that the AI assistant can create or modify.
45
- */
46
- artifacts: Schema.Array(Schema.String).annotations({
47
- description: "Ids of artifact definitions that should be pulled into the blueprint"
48
- })
49
- }).pipe(
50
- Type.Obj({
51
- // TODO(burdon): Is this a DXN? Need to create a Format type for these IDs.
52
- typename: "dxos.org/type/Blueprint",
53
- version: "0.1.0"
54
- }),
55
- // TODO(burdon): Move to main API.
56
- LabelAnnotation.set([
57
- "name"
58
- ])
59
- );
60
-
61
- // src/blueprint/registry.ts
62
- var BlueprintRegistry = class {
63
- constructor(_blueprints) {
64
- this._blueprints = _blueprints;
65
- this._blueprints.sort(({ name: a }, { name: b }) => a.localeCompare(b));
66
- }
67
- query() {
68
- return this._blueprints;
69
- }
70
- };
71
-
72
3
  // src/context/binder.ts
73
4
  import { computed } from "@preact/signals-core";
74
5
  import { Array as Array2, pipe } from "effect";
@@ -76,19 +7,20 @@ import { Obj } from "@dxos/echo";
76
7
  import { ComplexSet } from "@dxos/util";
77
8
 
78
9
  // src/context/binding.ts
79
- import { Schema as Schema2 } from "effect";
80
- import { Type as Type2 } from "@dxos/echo";
81
- var ContextBinding = Schema2.Struct({
82
- blueprints: Schema2.Struct({
83
- added: Schema2.Array(Type2.Ref(Blueprint)),
84
- removed: Schema2.Array(Type2.Ref(Blueprint))
10
+ import { Schema } from "effect";
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))
85
17
  }),
86
18
  // TODO(burdon): Type.Expando => Type.Obj (or Obj.Any?)
87
- objects: Schema2.Struct({
88
- added: Schema2.Array(Type2.Ref(Type2.Expando)),
89
- removed: Schema2.Array(Type2.Ref(Type2.Expando))
19
+ objects: Schema.Struct({
20
+ added: Schema.Array(Type.Ref(Type.Expando)),
21
+ removed: Schema.Array(Type.Ref(Type.Expando))
90
22
  })
91
- }).pipe(Type2.Obj({
23
+ }).pipe(Type.Obj({
92
24
  typename: "dxos.org/type/ContextBinding",
93
25
  version: "0.1.0"
94
26
  }));
@@ -165,479 +97,200 @@ var Bindings = class {
165
97
  };
166
98
 
167
99
  // src/conversation/conversation.ts
168
- import { Message as Message2 } from "@dxos/ai";
100
+ import { Effect as Effect2 } from "effect";
169
101
  import { Event as Event2 } from "@dxos/async";
170
- import { Obj as Obj3, Ref } from "@dxos/echo";
171
- import { AiService, ToolResolverService } from "@dxos/functions";
172
- import { log as log2 } from "@dxos/log";
173
- import { isNonNullable } from "@dxos/util";
102
+ import { Obj as Obj3 } from "@dxos/echo";
103
+ import { DatabaseService as DatabaseService2 } from "@dxos/functions";
104
+ import { DataType as DataType2 } from "@dxos/schema";
174
105
 
175
106
  // src/session/session.ts
176
- import { Array as Array3, Option, pipe as pipe2, Schema as Schema4 } from "effect";
177
- import { AgentStatusReport, isToolUse, runTools, structuredOutputParser, Message, MixedStreamParser, ToolResult, createTool } from "@dxos/ai";
178
- import { Event, synchronized } from "@dxos/async";
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";
179
113
  import { Obj as Obj2 } from "@dxos/echo";
180
114
  import { ObjectVersion } from "@dxos/echo-db";
181
- import { create } from "@dxos/echo-schema";
182
- import { invariant } from "@dxos/invariant";
115
+ import { DatabaseService } from "@dxos/functions";
183
116
  import { log } from "@dxos/log";
117
+ import { DataType } from "@dxos/schema";
184
118
 
185
- // src/session/version-pin.ts
186
- import { Schema as Schema3 } from "effect";
187
- import { getVersion } from "@dxos/echo-db";
188
- import { ObjectId } from "@dxos/echo-schema";
189
- var ObjectVersionSchema = Schema3.Unknown;
190
- var VersionPinSchema = Schema3.Struct({
191
- // TODO(dmaretskyi): Use Ref when those support encoding.
192
- objectId: ObjectId,
193
- // TODO(dmaretskyi): Could be opaque
194
- version: ObjectVersionSchema
195
- });
196
- var VersionPin = class extends VersionPinSchema {
197
- static {
198
- this.DISPOSITION = "version-pin";
199
- }
200
- static fromObject(object) {
201
- return VersionPin.make({
202
- objectId: object.id,
203
- version: getVersion(object)
204
- });
205
- }
206
- static createBlock(pin) {
207
- return {
208
- type: "json",
209
- disposition: VersionPin.DISPOSITION,
210
- json: JSON.stringify(pin)
211
- };
212
- }
119
+ // src/errors.ts
120
+ import { BaseError } from "@dxos/errors";
121
+ var AiAssistantError = class extends BaseError.extend("AI_ASSISTANT_ERROR") {
213
122
  };
214
123
 
215
124
  // src/session/session.ts
216
- function _ts_decorate(decorators, target, key, desc) {
217
- var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
218
- if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
219
- 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;
220
- return c > 3 && r && Object.defineProperty(target, key, r), r;
221
- }
222
125
  var __dxlog_file = "/__w/dxos/dxos/packages/core/assistant/src/session/session.ts";
223
- var AISession = class _AISession {
224
- constructor(_options) {
126
+ var AiSession = class {
127
+ constructor(_options = {}) {
225
128
  this._options = _options;
226
- this._parser = new MixedStreamParser();
129
+ this._semaphore = Effect.runSync(Effect.makeSemaphore(1));
227
130
  this._pending = [];
228
131
  this._history = [];
229
- this.message = this._parser.message;
230
- this.block = this._parser.block;
231
- this.update = this._parser.update;
232
- this.streamEvent = this._parser.streamEvent;
132
+ this.message = new Event();
133
+ this.block = new Event();
134
+ this.update = new Event();
135
+ this.streamEvent = new Event();
233
136
  this.userMessage = new Event();
234
137
  this.statusReport = new Event();
235
138
  this.done = new Event();
236
- this.toolStatusReport = new Event();
237
- this._parser.message.on((message) => {
238
- this._pending.push(message);
239
- });
240
- this._parser.block.on((block) => {
241
- if (block.type === "text" && block.disposition === "status") {
242
- this.statusReport.emit(create(AgentStatusReport, {
243
- message: block.text
244
- }));
245
- }
246
- });
247
- }
248
- /**
249
- * Runs the AI model loop interacting with tools and artifacts.
250
- * @param options - The session options.
251
- * @returns The messages generated by the session, including the user's prompt.
252
- */
253
- async run(options) {
254
- const systemTools = [];
255
- switch (this._options.operationModel) {
256
- case "planning":
257
- systemTools.push(this._createQueryArtifactsTool(options.artifacts), this._createPlanningTool(options));
258
- break;
259
- case "importing":
260
- systemTools.push(this._createQueryArtifactsTool(options.artifacts), this._createRequireTool(options.artifacts, (artifactDefinitionIds) => {
261
- for (const artifactDefinitionId of artifactDefinitionIds) {
262
- requiredArtifactIds.add(artifactDefinitionId);
263
- }
264
- }));
265
- break;
266
- case "configured":
267
- break;
268
- default:
269
- throw new TypeError(`Invalid operation model: ${this._options.operationModel}`);
270
- }
271
- this._history = [
272
- ...options.history
273
- ];
274
- this._pending = [
275
- await this._formatUserPrompt(options.artifactDiffResolver, options.prompt, options.history)
276
- ];
277
- this.userMessage.emit(this._pending.at(-1));
278
- this._stream = void 0;
279
- let error;
280
- const requiredArtifactIds = new Set(options.requiredArtifactIds ?? []);
281
- try {
282
- let more = false;
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);
283
148
  do {
284
- const tools = pipe2([
285
- ...systemTools,
286
- ...await Promise.all(options.tools.map((toolId) => options.toolResolver.resolve(toolId))),
287
- ...options.executableTools ?? [],
288
- ...options.artifacts.filter((artifact) => requiredArtifactIds.has(artifact.id)).flatMap((artifact) => artifact.tools)
289
- ], Array3.dedupeWith((a, b) => a.id === b.id));
290
149
  log("request", {
291
150
  pending: this._pending.length,
292
151
  history: this._history.length,
293
- tools: tools.map((tool) => tool.name)
152
+ tools: Object.values(options.toolkit?.tools ?? {}).map((tool) => tool.name)
294
153
  }, {
295
154
  F: __dxlog_file,
296
- L: 231,
155
+ L: 126,
297
156
  S: this,
298
157
  C: (f, a) => f(...a)
299
158
  });
300
- this._stream = await options.client.execStream({
301
- ...options.generationOptions ?? {},
302
- // TODO(burdon): Rename messages or separate history/message.
303
- history: [
304
- ...this._history,
305
- ...this._pending
306
- ],
307
- tools,
308
- systemPrompt: options.systemPrompt ?? createBaseInstructions({
309
- availableArtifacts: [
310
- ...requiredArtifactIds
311
- ],
312
- operationModel: this._options.operationModel
313
- })
314
- });
315
- await this._parser.parse(this._stream);
316
- await this._stream.complete();
317
- log("response", {
318
- pending: this._pending
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)
319
179
  }, {
320
180
  F: __dxlog_file,
321
- L: 256,
181
+ L: 155,
322
182
  S: this,
323
183
  C: (f, a) => f(...a)
324
184
  });
325
- more = false;
326
- const message = this._pending.at(-1);
327
- invariant(message, void 0, {
328
- F: __dxlog_file,
329
- L: 261,
330
- S: this,
331
- A: [
332
- "message",
333
- ""
334
- ]
335
- });
336
- if (isToolUse(message)) {
337
- log("tool request...", void 0, {
338
- F: __dxlog_file,
339
- L: 263,
340
- S: this,
341
- C: (f, a) => f(...a)
342
- });
343
- const response = await runTools({
344
- message: this._pending.at(-1),
345
- tools,
346
- extensions: options.extensions ?? {},
347
- reportStatus: (status) => this._onToolStatusReport(message, status)
348
- });
349
- log("tool response", {
350
- response
351
- }, {
352
- F: __dxlog_file,
353
- L: 271,
354
- S: this,
355
- C: (f, a) => f(...a)
356
- });
357
- switch (response.type) {
358
- case "continue": {
359
- this._pending = [
360
- ...this._pending,
361
- response.message
362
- ];
363
- this.userMessage.emit(response.message);
364
- more = true;
365
- 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);
366
196
  }
367
- }
368
- }
369
- } while (more);
370
- } catch (err) {
371
- log.catch(err, void 0, {
372
- F: __dxlog_file,
373
- L: 283,
374
- S: this,
375
- C: (f, a) => f(...a)
376
- });
377
- if (err instanceof Error && err.message.includes("Overloaded")) {
378
- error = new AIServiecOverloadedError("AI service overloaded", {
379
- cause: err
380
- });
381
- } else {
382
- error = new Error("AI service error", {
383
- cause: err
384
- });
385
- }
386
- } finally {
387
- this._stream = void 0;
388
- this.done.emit();
389
- }
390
- if (error) {
391
- throw error;
392
- }
393
- return this._pending;
394
- }
395
- async runStructured(schema, options) {
396
- const parser = structuredOutputParser(schema);
397
- const result = await this.run({
398
- ...options,
399
- executableTools: [
400
- ...options.executableTools ?? [],
401
- parser.tool
402
- ]
403
- });
404
- return parser.getResult(result);
405
- }
406
- async _formatUserPrompt(artifactDiffResolver, prompt, history) {
407
- const prelude = [];
408
- if (artifactDiffResolver) {
409
- const versions = gatherObjectVersions(history);
410
- const artifactDiff = await artifactDiffResolver([
411
- ...versions.entries()
412
- ].map(([id, version]) => ({
413
- id,
414
- lastVersion: version
415
- })));
416
- log.info("vision", {
417
- artifactDiff,
418
- versions
419
- }, {
420
- F: __dxlog_file,
421
- L: 327,
422
- S: this,
423
- C: (f, a) => f(...a)
424
- });
425
- for (const [id, { version }] of [
426
- ...artifactDiff.entries()
427
- ]) {
428
- if (ObjectVersion.equals(version, versions.get(id))) {
429
- artifactDiff.delete(id);
430
- continue;
431
- }
432
- prelude.push(VersionPin.createBlock(VersionPin.make({
433
- objectId: id,
434
- version
435
- })));
436
- }
437
- if (artifactDiff.size > 0) {
438
- prelude.push(createArtifactUpdateBlock(artifactDiff));
439
- }
440
- }
441
- return Obj2.make(Message, {
442
- role: "user",
443
- content: [
444
- ...prelude,
445
- {
446
- type: "text",
447
- text: prompt
448
- }
449
- ]
450
- });
451
- }
452
- _createQueryArtifactsTool(artifacts) {
453
- return createTool("system", {
454
- name: "query_artifact_definitions",
455
- description: "Query the available artifact definitions",
456
- schema: Schema4.Struct({}),
457
- execute: async () => {
458
- return ToolResult.Success({
459
- artifactDefinitions: artifacts.map((artifact) => ({
460
- id: artifact.id,
461
- name: artifact.name,
462
- description: artifact.description
463
- }))
464
- });
465
- }
466
- });
467
- }
468
- _createRequireTool(artifacts, onRequire) {
469
- return createTool("system", {
470
- name: "require_artifact_definitions",
471
- description: "Require the use of specific artifact definitions. This will allow the model to interact with artifact definitions and use their tools.",
472
- schema: Schema4.Struct({
473
- artifactDefinitionIds: Schema4.Array(Schema4.String).annotations({
474
- description: "The ids of the artifact definitions to require",
475
- examples: [
476
- [
477
- "artifact:dxos.org/example/Test"
478
- ]
479
- ]
480
- })
481
- }),
482
- execute: async ({ artifactDefinitionIds }) => {
483
- const missingArtifactDefinitionIds = artifactDefinitionIds.filter((artifactId) => !artifacts.some((artifact) => artifact.id === artifactId));
484
- if (missingArtifactDefinitionIds.length > 0) {
485
- return ToolResult.Error(`One or more artifact definition ids are invalid: ${missingArtifactDefinitionIds.join(", ")}`);
486
- }
487
- onRequire(artifactDefinitionIds);
488
- return ToolResult.Success({});
489
- }
490
- });
491
- }
492
- _createPlanningTool(options) {
493
- return createTool("system", {
494
- name: "create_plan",
495
- 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.",
496
- schema: Schema4.Struct({
497
- goal: Schema4.String.annotations({
498
- description: "The goal that the plan will achieve."
499
- }),
500
- steps: Schema4.Array(Schema4.Struct({
501
- action: Schema4.String.annotations({
502
- description: "Complete, detailed action to perform."
503
- }),
504
- input: Schema4.String.annotations({
505
- description: "The required input data for this step. First step must not require any data."
506
197
  }),
507
- output: Schema4.String.annotations({
508
- description: "The output data from this step. This is passed to the next step as input."
509
- }),
510
- requiredArtifactIds: Schema4.Array(Schema4.String).annotations({
511
- description: "The ids of the artifacts required to perform this step.",
512
- examples: [
513
- [
514
- "artifact:dxos.org/example/Test"
515
- ]
516
- ]
198
+ onPart: (part) => Effect.gen(this, function* () {
199
+ this.streamEvent.emit(part);
517
200
  })
518
- })).annotations({
519
- description: "Steps"
520
- })
521
- }),
522
- execute: async ({ goal, steps }) => {
523
- const missingArtifactIds = steps.flatMap((step) => step.requiredArtifactIds).filter((artifactId) => !options.artifacts.some((artifact) => artifact.id === artifactId));
524
- if (missingArtifactIds.length > 0) {
525
- return ToolResult.Error(`One or more artifact ids are invalid: ${missingArtifactIds.join(", ")}`);
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;
526
214
  }
527
- const stepResults = [];
528
- for (const step of steps) {
529
- log("executing step", {
530
- action: step.action
531
- }, {
532
- F: __dxlog_file,
533
- L: 434,
534
- S: this,
535
- C: (f, a) => f(...a)
536
- });
537
- const session = new _AISession({
538
- operationModel: "importing"
539
- });
540
- session.message.on((ev) => this.message.emit(ev));
541
- session.block.on((ev) => this.block.emit(ev));
542
- session.update.on((ev) => this.update.emit(ev));
543
- session.streamEvent.on((ev) => this.streamEvent.emit(ev));
544
- session.userMessage.on((ev) => this.userMessage.emit(ev));
545
- const messages = await session.run({
546
- artifacts: options.artifacts,
547
- tools: options.tools,
548
- history: options.history,
549
- extensions: options.extensions,
550
- requiredArtifactIds: step.requiredArtifactIds.slice(),
551
- prompt: `
552
- You are an agent that executes the subtask in a plan.
553
-
554
- While you know the plan's goal only focus on your subtask
555
- Use the data from the previous step to complete your task.
556
- Return all of the data from "output" in your last message.
557
-
558
- Current step (that you need to complete):
559
- ${JSON.stringify({
560
- goal,
561
- input: step.input,
562
- output: step.output,
563
- yourTask: step.action
564
- }, null, 2)}
565
-
566
- Previous step results:
567
- ${JSON.stringify(stepResults.at(-1))}.
568
- `,
569
- generationOptions: options.generationOptions,
570
- client: options.client,
571
- toolResolver: options.toolResolver,
572
- artifactDiffResolver: options.artifactDiffResolver
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
573
260
  });
574
- const result = messages.at(-1);
575
- stepResults.push(result);
576
261
  }
577
- return ToolResult.Success({
578
- stepResults
579
- });
262
+ if (artifactDiff.size > 0) {
263
+ prelude.push(createArtifactUpdateBlock(artifactDiff));
264
+ }
580
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
+ });
581
279
  });
582
280
  }
583
- _onToolStatusReport(message, status) {
584
- this.toolStatusReport.emit({
585
- message,
586
- status
587
- });
281
+ async runStructured(schema, options) {
282
+ return todo();
588
283
  }
589
284
  abort() {
590
285
  this._stream?.abort();
591
286
  }
592
287
  };
593
- _ts_decorate([
594
- synchronized
595
- ], AISession.prototype, "run", null);
596
- var createBaseInstructions = ({ availableArtifacts, operationModel }) => `
597
- You are a friendly, advanced AI assistant capable of creating and managing artifacts from available data and tools.
598
- Your task is to process user commands and questions and decide how best to respond.
599
- In some cases, you will need to create or reference data objects called artifacts.
600
-
601
- Follow these guidelines carefully:
602
-
603
- Decision-making:
604
-
605
- - Analyze the structure and type of the content in the user's message.
606
-
607
-
608
- ${operationModel === "planning" ? `
609
- - Can you complete the task using the available artifacts?
610
- - If you can't complete the task using the available artifacts, query the list of available artifacts using the appropriate tool.
611
- - Identify which artifacts are relevant to the user's request.
612
- - 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.
613
- ` : ""}
614
- ${operationModel === "importing" ? `
615
- - Can you complete the task using the available artifacts?
616
- - If you can't complete the task using the available artifacts, query the list of available artifacts using the appropriate tool.
617
- - Identify which artifacts are relevant to the user's request.
618
- - Are the required artifacts already available?
619
- - If not, select which artifact(s) will be the most relevant and require them using the require_artifacts tool.
620
- - The require'd artifact tools will be available for use after require.
621
- ` : ""}
622
- ${operationModel === "configured" ? `
623
- - Select the most relevant artifact(s) to complete the task.
624
- - Call the appropriate tool to use the artifact(s).
625
- ` : ""}
626
-
627
- ${availableArtifacts.length > 0 ? `Artifacts already in context: ${availableArtifacts.join("\n")}` : ""}
628
- `;
629
- var AIServiecOverloadedError = class extends Schema4.TaggedError()("AIServiecOverloadedError", {}) {
630
- };
631
288
  var gatherObjectVersions = (messages) => {
632
289
  const artifactIds = /* @__PURE__ */ new Map();
633
290
  for (const message of messages) {
634
- for (const block of message.content) {
635
- if (block.type === "json" && block.disposition === VersionPin.DISPOSITION) {
636
- const pin = VersionPin.pipe(Schema4.decodeOption)(JSON.parse(block.json)).pipe(Option.getOrUndefined);
637
- if (!pin) {
638
- continue;
639
- }
640
- 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);
641
294
  }
642
295
  }
643
296
  }
@@ -645,7 +298,8 @@ var gatherObjectVersions = (messages) => {
645
298
  };
646
299
  var createArtifactUpdateBlock = (artifactDiff) => {
647
300
  return {
648
- type: "text",
301
+ _tag: "text",
302
+ // TODO(dmaretskyi): Does this need to be a special content-block?
649
303
  disposition: "artifact-update",
650
304
  text: `
651
305
  The following artifacts have been updated since the last message:
@@ -656,9 +310,44 @@ ${diff}` : ""}</changed-artifact>`).join("\n")}
656
310
  `
657
311
  };
658
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
+ };
659
349
 
660
350
  // src/conversation/conversation.ts
661
- var __dxlog_file2 = "/__w/dxos/dxos/packages/core/assistant/src/conversation/conversation.ts";
662
351
  var Conversation = class {
663
352
  constructor(options) {
664
353
  /**
@@ -666,72 +355,51 @@ var Conversation = class {
666
355
  * This is called before the first message is sent.
667
356
  */
668
357
  this.onBegin = new Event2();
669
- this._serviceContainer = options.serviceContainer;
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"));
670
376
  this._queue = options.queue;
671
377
  this.context = new ContextBinder(this._queue);
672
378
  }
673
- async run(options) {
674
- const session = new AISession({
675
- operationModel: "configured"
676
- });
677
- this.onBegin.emit(session);
678
- const history = await this.getHistory();
679
- const context = await this.context.query();
680
- const blueprints = (await Ref.Array.loadAll([
681
- ...context.blueprints
682
- ])).filter(isNonNullable);
683
- if (blueprints.length > 1) {
684
- log2.warn("multiple blueprints are not yet supported", void 0, {
685
- F: __dxlog_file2,
686
- L: 72,
687
- S: this,
688
- C: (f, a) => f(...a)
689
- });
690
- }
691
- const messages = await session.run({
692
- history,
693
- prompt: options.prompt,
694
- systemPrompt: (options.systemPrompt ?? "") + (blueprints.at(0)?.instructions ?? ""),
695
- // TODO(dmaretskyi): Artifacts come from the blueprint?
696
- artifacts: options.artifacts ?? [],
697
- tools: blueprints.at(0)?.tools ?? [],
698
- executableTools: options.tools,
699
- requiredArtifactIds: options.requiredArtifactIds,
700
- client: this._serviceContainer.getService(AiService).client,
701
- toolResolver: this._serviceContainer.getService(ToolResolverService).toolResolver,
702
- extensions: {
703
- serviceContainer: this._serviceContainer,
704
- ...options.extensions
705
- },
706
- generationOptions: options.generationOptions
707
- });
708
- await this._queue.append(messages);
709
- return messages;
710
- }
711
379
  async getHistory() {
712
380
  const queueItems = await this._queue.queryObjects();
713
- return queueItems.filter(Obj3.instanceOf(Message2));
381
+ return queueItems.filter(Obj3.instanceOf(DataType2.Message));
714
382
  }
715
383
  };
716
384
 
717
385
  // src/extraction/extraction.ts
718
- import { Schema as Schema5 } from "effect";
386
+ import { Schema as Schema3 } from "effect";
719
387
  import { asyncTimeout } from "@dxos/async";
720
388
  import { Expando } from "@dxos/echo-schema";
721
- import { log as log3 } from "@dxos/log";
722
- import { DataType } from "@dxos/schema";
723
- var __dxlog_file3 = "/__w/dxos/dxos/packages/core/assistant/src/extraction/extraction.ts";
724
- var ExtractionInput = Schema5.Struct({
725
- message: DataType.Message,
726
- objects: Schema5.optional(Schema5.Array(Expando)),
727
- options: Schema5.optional(Schema5.Struct({
728
- timeout: Schema5.optional(Schema5.Number),
729
- fallbackToRaw: Schema5.optional(Schema5.Boolean)
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)
730
398
  }))
731
399
  });
732
- var ExtractionOutput = Schema5.Struct({
733
- message: DataType.Message,
734
- timeElapsed: Schema5.Number
400
+ var ExtractionOutput = Schema3.Struct({
401
+ message: DataType3.Message,
402
+ timeElapsed: Schema3.Number
735
403
  });
736
404
  var processTranscriptMessage = async (params) => {
737
405
  try {
@@ -742,10 +410,10 @@ var processTranscriptMessage = async (params) => {
742
410
  }
743
411
  } catch (error) {
744
412
  if (params.options?.fallbackToRaw) {
745
- log3.warn("failed to process message, falling back to raw text", {
413
+ log2.warn("failed to process message, falling back to raw text", {
746
414
  error
747
415
  }, {
748
- F: __dxlog_file3,
416
+ F: __dxlog_file2,
749
417
  L: 66,
750
418
  S: void 0,
751
419
  C: (f, a) => f(...a)
@@ -761,27 +429,27 @@ var processTranscriptMessage = async (params) => {
761
429
  };
762
430
 
763
431
  // src/extraction/extraction-llm-function/extraction-llm-function.ts
764
- import { Message as Message3, ToolRegistry } from "@dxos/ai";
432
+ import { ToolRegistry, AiService } from "@dxos/ai";
765
433
  import { Obj as Obj4 } from "@dxos/echo";
766
- import { create as create2 } from "@dxos/echo-schema";
767
- import { AiService as AiService2, defineFunction } from "@dxos/functions";
768
- import { DataType as DataType2 } from "@dxos/schema";
434
+ import { create } from "@dxos/echo-schema";
435
+ import { defineFunction } from "@dxos/functions";
436
+ import { DataType as DataType4 } from "@dxos/schema";
769
437
 
770
438
  // raw-loader:./instructions.tpl?raw
771
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.';
772
440
 
773
441
  // src/extraction/quotes.ts
774
- import { Schema as Schema6 } from "effect";
442
+ import { Schema as Schema4 } from "effect";
775
443
  import { Query, Filter } from "@dxos/echo";
776
444
  import { ObjectId as ObjectId2 } from "@dxos/echo-schema";
777
445
  import { DXN } from "@dxos/keys";
778
- import { log as log4 } from "@dxos/log";
779
- var __dxlog_file4 = "/__w/dxos/dxos/packages/core/assistant/src/extraction/quotes.ts";
780
- var ReferencedQuotes = Schema6.Struct({
781
- references: Schema6.Array(Schema6.Struct({
782
- id: Schema6.String,
783
- quote: Schema6.String
784
- })).pipe(Schema6.mutable).annotations({
446
+ import { log as log3 } from "@dxos/log";
447
+ var __dxlog_file3 = "/__w/dxos/dxos/packages/core/assistant/src/extraction/quotes.ts";
448
+ var ReferencedQuotes = Schema4.Struct({
449
+ references: Schema4.Array(Schema4.Struct({
450
+ id: Schema4.String,
451
+ quote: Schema4.String
452
+ })).pipe(Schema4.mutable).annotations({
785
453
  // TODO(burdon): Does this description make sense?
786
454
  description: `
787
455
  The references to the context objects that are mentioned in the transcript.
@@ -794,11 +462,11 @@ var findQuotes = async (quotes, db) => {
794
462
  const { objects } = await db.query(Query.select(Filter.text(quote, {
795
463
  type: "vector"
796
464
  }))).run();
797
- log4.info("found quotes in vector index", {
465
+ log3.info("found quotes in vector index", {
798
466
  objects,
799
467
  quote
800
468
  }, {
801
- F: __dxlog_file4,
469
+ F: __dxlog_file3,
802
470
  L: 35,
803
471
  S: void 0,
804
472
  C: (f, a) => f(...a)
@@ -832,8 +500,8 @@ var extractionAnthropicFn = defineFunction({
832
500
  outputSchema: ExtractionOutput,
833
501
  handler: async ({ data: { message, objects }, context }) => {
834
502
  const startTime = performance.now();
835
- const ai = context.getService(AiService2);
836
- const session = new AISession({
503
+ const ai = context.getService(AiService);
504
+ const session = new AiSession({
837
505
  operationModel: "configured"
838
506
  });
839
507
  const result = await session.runStructured(ReferencedQuotes, {
@@ -843,15 +511,18 @@ var extractionAnthropicFn = defineFunction({
843
511
  client: ai.client,
844
512
  systemPrompt: instructions_default,
845
513
  history: [
846
- Obj4.make(Message3, {
847
- role: "user",
848
- content: [
514
+ Obj4.make(DataType4.Message, {
515
+ created: (/* @__PURE__ */ new Date()).toISOString(),
516
+ sender: {
517
+ role: "user"
518
+ },
519
+ blocks: [
849
520
  {
850
- type: "text",
521
+ _tag: "text",
851
522
  text: `<context>${JSON.stringify(objects)}</context>`
852
523
  },
853
524
  {
854
- type: "text",
525
+ _tag: "text",
855
526
  text: `<transcript>${JSON.stringify(message.blocks)}</transcript>`
856
527
  }
857
528
  ]
@@ -863,9 +534,9 @@ var extractionAnthropicFn = defineFunction({
863
534
  toolResolver: new ToolRegistry([])
864
535
  });
865
536
  return {
866
- message: create2(DataType2.Message, {
537
+ message: create(DataType4.Message, {
867
538
  ...message,
868
- blocks: message.blocks.map((block, i) => block.type !== "transcription" ? block : {
539
+ blocks: message.blocks.map((block, i) => block._tag !== "transcript" ? block : {
869
540
  ...block,
870
541
  text: insertReferences(block.text, result)
871
542
  })
@@ -877,22 +548,22 @@ var extractionAnthropicFn = defineFunction({
877
548
 
878
549
  // src/extraction/extraction-ner-function/extraction-ner-function.ts
879
550
  import { asyncTimeout as asyncTimeout2 } from "@dxos/async";
880
- import { create as create3 } from "@dxos/echo-schema";
881
- import { DatabaseService, defineFunction as defineFunction2 } from "@dxos/functions";
882
- import { invariant as invariant2 } from "@dxos/invariant";
883
- import { log as log6 } from "@dxos/log";
884
- import { DataType as DataType3 } from "@dxos/schema";
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";
554
+ import { log as log5 } from "@dxos/log";
555
+ import { DataType as DataType5 } from "@dxos/schema";
885
556
 
886
557
  // src/extraction/extraction-ner-function/named-entity-recognition.ts
887
558
  import { pipeline } from "@xenova/transformers";
888
- import { log as log5 } from "@dxos/log";
889
- var __dxlog_file5 = "/__w/dxos/dxos/packages/core/assistant/src/extraction/extraction-ner-function/named-entity-recognition.ts";
559
+ import { log as log4 } from "@dxos/log";
560
+ var __dxlog_file4 = "/__w/dxos/dxos/packages/core/assistant/src/extraction/extraction-ner-function/named-entity-recognition.ts";
890
561
  var _ner;
891
562
  var getNer = () => {
892
563
  if (!_ner) {
893
564
  _ner = pipeline("ner", "Xenova/bert-base-NER").then((ner) => {
894
- log5.info("NER model is ready", void 0, {
895
- F: __dxlog_file5,
565
+ log4.info("NER model is ready", void 0, {
566
+ F: __dxlog_file4,
896
567
  L: 23,
897
568
  S: void 0,
898
569
  C: (f, a) => f(...a)
@@ -966,69 +637,69 @@ var combineNerTokens = (group) => {
966
637
  };
967
638
 
968
639
  // src/extraction/extraction-ner-function/extraction-ner-function.ts
969
- var __dxlog_file6 = "/__w/dxos/dxos/packages/core/assistant/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";
970
641
  var extractionNerFn = defineFunction2({
971
642
  description: "Extracts named entities from a text",
972
643
  inputSchema: ExtractionInput,
973
644
  outputSchema: ExtractionOutput,
974
645
  handler: async ({ data: { message, options }, context }) => {
975
- log6.info("input", {
646
+ log5.info("input", {
976
647
  message,
977
648
  options
978
649
  }, {
979
- F: __dxlog_file6,
980
- L: 22,
650
+ F: __dxlog_file5,
651
+ L: 25,
981
652
  S: void 0,
982
653
  C: (f, a) => f(...a)
983
654
  });
984
655
  const startTime = performance.now();
985
- const { db } = context.getService(DatabaseService);
656
+ const { db } = context.getService(DatabaseService3);
986
657
  const entitiesPromise = Promise.all(message.blocks.map(async (block) => {
987
- invariant2(block.type === "transcription" || block.type === "text", "Block must have text", {
988
- F: __dxlog_file6,
989
- L: 28,
658
+ invariant(block._tag === "transcript" || block._tag === "text", "Block must have text", {
659
+ F: __dxlog_file5,
660
+ L: 31,
990
661
  S: void 0,
991
662
  A: [
992
- "block.type === 'transcription' || block.type === 'text'",
663
+ "block._tag === 'transcript' || block._tag === 'text'",
993
664
  "'Block must have text'"
994
665
  ]
995
666
  });
996
667
  return extractFullEntities(block.text);
997
668
  })).then((entities2) => entities2.flat());
998
669
  const entities = options?.timeout ? await asyncTimeout2(entitiesPromise, options.timeout) : await entitiesPromise;
999
- log6.info("entities", {
670
+ log5.info("entities", {
1000
671
  entities
1001
672
  }, {
1002
- F: __dxlog_file6,
1003
- L: 33,
673
+ F: __dxlog_file5,
674
+ L: 36,
1004
675
  S: void 0,
1005
676
  C: (f, a) => f(...a)
1006
677
  });
1007
678
  const quoteReferences = await findQuotes(entities.map((entity) => entity.word), db);
1008
679
  const blocksWithReferences = message.blocks.map((block, i) => {
1009
- invariant2(block.type === "transcription" || block.type === "text", "Block must have text", {
1010
- F: __dxlog_file6,
1011
- L: 39,
680
+ invariant(block._tag === "transcript" || block._tag === "text", "Block must have text", {
681
+ F: __dxlog_file5,
682
+ L: 42,
1012
683
  S: void 0,
1013
684
  A: [
1014
- "block.type === 'transcription' || block.type === 'text'",
685
+ "block._tag === 'transcript' || block._tag === 'text'",
1015
686
  "'Block must have text'"
1016
687
  ]
1017
688
  });
1018
689
  return {
1019
690
  ...block,
1020
- text: insertReferences(block.text, quoteReferences)
691
+ text: insertReferences(block._tag, quoteReferences)
1021
692
  };
1022
693
  });
1023
- const messageWithReferences = create3(DataType3.Message, {
694
+ const messageWithReferences = create2(DataType5.Message, {
1024
695
  ...message,
1025
696
  blocks: blocksWithReferences
1026
697
  });
1027
- log6.info("output", {
698
+ log5.info("output", {
1028
699
  messageWithReferences
1029
700
  }, {
1030
- F: __dxlog_file6,
1031
- L: 47,
701
+ F: __dxlog_file5,
702
+ L: 50,
1032
703
  S: void 0,
1033
704
  C: (f, a) => f(...a)
1034
705
  });
@@ -1039,11 +710,127 @@ var extractionNerFn = defineFunction2({
1039
710
  }
1040
711
  });
1041
712
 
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
+
1042
828
  // src/research/exa.ts
1043
- import { Schema as Schema7 } from "effect";
829
+ import { AiTool as AiTool2, AiToolkit as AiToolkit2 } from "@effect/ai";
830
+ import { Effect as Effect4, Schema as Schema6 } from "effect";
1044
831
  import Exa from "exa-js";
1045
- import { createTool as createTool2, ToolResult as ToolResult2 } from "@dxos/ai";
1046
- import { log as log7 } from "@dxos/log";
832
+ import { CredentialsService } from "@dxos/functions";
833
+ import { log as log6 } from "@dxos/log";
1047
834
 
1048
835
  // src/testing/exa-search-1748337321991.ts
1049
836
  var exa_search_1748337321991_default = {
@@ -1556,64 +1343,60 @@ var SEARCH_RESULTS = [
1556
1343
 
1557
1344
  // src/research/exa.ts
1558
1345
  var __dxlog_file7 = "/__w/dxos/dxos/packages/core/assistant/src/research/exa.ts";
1559
- var createExaTool = ({ apiKey }) => {
1560
- const exa = new Exa(apiKey);
1561
- return createTool2("search", {
1562
- name: "web_search",
1563
- description: "Search the web for information",
1564
- schema: Schema7.Struct({
1565
- query: Schema7.String.annotations({
1566
- description: "The query to search for"
1567
- })
1568
- }),
1569
- execute: async ({ query }) => {
1570
- const context = await exa.searchAndContents(query, {
1571
- type: "auto",
1572
- text: {
1573
- maxCharacters: 3e3
1574
- },
1575
- livecrawl: "always"
1576
- });
1577
- log7.info("exa search", {
1578
- query,
1579
- costDollars: context.costDollars
1580
- }, {
1581
- F: __dxlog_file7,
1582
- L: 35,
1583
- S: void 0,
1584
- C: (f, a) => f(...a)
1585
- });
1586
- return ToolResult2.Success(context);
1587
- }
1588
- });
1589
- };
1590
- var createMockExaTool = () => {
1591
- return createTool2("search", {
1592
- name: "web_search",
1593
- description: "Search the web for information",
1594
- schema: Schema7.Struct({
1595
- query: Schema7.String.annotations({
1596
- description: "The query to search for"
1597
- })
1598
- }),
1599
- execute: async ({ query }) => {
1600
- const result = SEARCH_RESULTS.reduce((closest, current) => {
1601
- if (!current.autopromptString) {
1602
- return closest;
1603
- }
1604
- if (!closest) {
1605
- return current;
1606
- }
1607
- const dist1 = levenshteinDistance(query, current.autopromptString);
1608
- const dist2 = levenshteinDistance(query, closest.autopromptString || "");
1609
- const weight1 = dist1 / Math.max(query.length, current.autopromptString.length);
1610
- const weight2 = dist2 / Math.max(query.length, closest.autopromptString?.length || 0);
1611
- return weight1 < weight2 ? current : closest;
1612
- }, null);
1613
- return ToolResult2.Success(result);
1614
- }
1615
- });
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()) {
1616
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
+ });
1617
1400
  var levenshteinDistance = (str1, str2) => {
1618
1401
  const m = str1.length;
1619
1402
  const n = str2.length;
@@ -1633,27 +1416,28 @@ var levenshteinDistance = (str1, str2) => {
1633
1416
  };
1634
1417
 
1635
1418
  // src/research/research.ts
1636
- import { Schema as Schema9 } from "effect";
1637
- import { AgentStatusReport as AgentStatusReport2, ConsolePrinter, ToolRegistry as ToolRegistry2 } from "@dxos/ai";
1638
- import { create as create5 } from "@dxos/echo-schema";
1639
- import { AiService as AiService3, CredentialsService, DatabaseService as DatabaseService2, defineFunction as defineFunction3, TracingService } from "@dxos/functions";
1640
- import { log as log9 } from "@dxos/log";
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";
1423
+ import { log as log8 } from "@dxos/log";
1641
1424
  import { DataTypes } from "@dxos/schema";
1642
1425
 
1643
1426
  // src/research/graph.ts
1644
- import { Schema as Schema8, identity, Option as Option2, SchemaAST } from "effect";
1645
- import { createTool as createTool3, ToolResult as ToolResult3 } from "@dxos/ai";
1646
- import { Query as Query2, Filter as Filter2 } from "@dxos/echo";
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";
1647
1430
  import { isEncodedReference } from "@dxos/echo-protocol";
1648
- import { EntityKind, getSchemaTypename, getTypeAnnotation, getTypeIdentifierAnnotation, create as create4, getEntityKind, getSchemaDXN, ObjectId as ObjectId3, ReferenceAnnotationId, RelationSourceDXNId, RelationTargetDXNId, RelationSourceId, RelationTargetId } from "@dxos/echo-schema";
1431
+ import { create as create3, EntityKind, getEntityKind, getSchemaDXN, getSchemaTypename, getTypeAnnotation, getTypeIdentifierAnnotation, ObjectId as ObjectId3, ReferenceAnnotationId, RelationSourceDXNId, RelationSourceId, RelationTargetDXNId, RelationTargetId } from "@dxos/echo-schema";
1649
1432
  import { mapAst } from "@dxos/effect";
1433
+ import { ContextQueueService, DatabaseService as DatabaseService4 } from "@dxos/functions";
1650
1434
  import { DXN as DXN2 } from "@dxos/keys";
1651
- import { log as log8 } from "@dxos/log";
1652
- import { deepMapValues, isNonNullable as isNonNullable2 } from "@dxos/util";
1435
+ import { log as log7 } from "@dxos/log";
1436
+ import { deepMapValues, isNonNullable } from "@dxos/util";
1653
1437
  var __dxlog_file8 = "/__w/dxos/dxos/packages/core/assistant/src/research/graph.ts";
1654
- var Subgraph = Schema8.Struct({
1438
+ var Subgraph = Schema7.Struct({
1655
1439
  /** Objects and relations. */
1656
- objects: Schema8.Array(Schema8.Any)
1440
+ objects: Schema7.Array(Schema7.Any)
1657
1441
  });
1658
1442
  var findRelatedSchema = async (db, anchor) => {
1659
1443
  const allSchemas = [
@@ -1679,39 +1463,65 @@ var isSchemaAddressableByDxn = (schema, dxn) => {
1679
1463
  }
1680
1464
  return false;
1681
1465
  };
1682
- var createLocalSearchTool = (db, queue) => {
1683
- return createTool3("search", {
1684
- name: "local_search",
1685
- description: "Search the local database for information using a vector index",
1686
- schema: Schema8.Struct({
1687
- query: Schema8.String.annotations({
1688
- description: "The query to search for. Could be a question or a topic or a set of keywords."
1689
- })
1690
- }),
1691
- execute: async ({ query }) => {
1692
- const { objects } = await db.query(Query2.select(Filter2.text(query, {
1693
- type: "vector"
1694
- }))).run();
1695
- const results = [
1696
- ...objects
1697
- ];
1698
- if (queue) {
1699
- const queueObjects = await queue.queryObjects();
1700
- results.push(...queueObjects);
1701
- }
1702
- return ToolResult3.Success(`
1703
- <local_context>
1704
- ${JSON.stringify(results, null, 2)}
1705
- </local_context>
1706
- `);
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);
1707
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
+ })
1708
1518
  });
1709
1519
  };
1710
1520
  var createExtractionSchema = (types) => {
1711
- return Schema8.Struct({
1521
+ return Schema7.Struct({
1712
1522
  ...Object.fromEntries(types.map(preprocessSchema).map((schema, index) => [
1713
1523
  `objects_${getSanitizedSchemaName(types[index])}`,
1714
- Schema8.optional(Schema8.Array(schema)).annotations({
1524
+ Schema7.optional(Schema7.Array(schema)).annotations({
1715
1525
  description: `The objects of type: ${getSchemaDXN(types[index])?.asTypeDXN().type}. ${SchemaAST.getDescriptionAnnotation(types[index].ast).pipe(Option2.getOrElse(() => ""))}`
1716
1526
  })
1717
1527
  ]))
@@ -1766,22 +1576,22 @@ var sanitizeObjects = async (types, data, db, queue) => {
1766
1576
  if (getEntityKind(entry.schema) === "relation") {
1767
1577
  const sourceDxn = resolveId(data2.source);
1768
1578
  if (!sourceDxn) {
1769
- log8.warn("source not found", {
1579
+ log7.warn("source not found", {
1770
1580
  source: data2.source
1771
1581
  }, {
1772
1582
  F: __dxlog_file8,
1773
- L: 214,
1583
+ L: 262,
1774
1584
  S: void 0,
1775
1585
  C: (f, a) => f(...a)
1776
1586
  });
1777
1587
  }
1778
1588
  const targetDxn = resolveId(data2.target);
1779
1589
  if (!targetDxn) {
1780
- log8.warn("target not found", {
1590
+ log7.warn("target not found", {
1781
1591
  target: data2.target
1782
1592
  }, {
1783
1593
  F: __dxlog_file8,
1784
- L: 218,
1594
+ L: 266,
1785
1595
  S: void 0,
1786
1596
  C: (f, a) => f(...a)
1787
1597
  });
@@ -1803,14 +1613,14 @@ var sanitizeObjects = async (types, data, db, queue) => {
1803
1613
  const objects = [
1804
1614
  ...dbObjects,
1805
1615
  ...queueObjects
1806
- ].filter(isNonNullable2);
1807
- log8.info("objects", {
1616
+ ].filter(isNonNullable);
1617
+ log7.info("objects", {
1808
1618
  dbObjects,
1809
1619
  queueObjects,
1810
1620
  existingIds
1811
1621
  }, {
1812
1622
  F: __dxlog_file8,
1813
- L: 239,
1623
+ L: 287,
1814
1624
  S: void 0,
1815
1625
  C: (f, a) => f(...a)
1816
1626
  });
@@ -1841,7 +1651,7 @@ var sanitizeObjects = async (types, data, db, queue) => {
1841
1651
  }
1842
1652
  }
1843
1653
  if (!skip) {
1844
- const obj = create4(schema, data2);
1654
+ const obj = create3(schema, data2);
1845
1655
  enitties.set(obj.id, obj);
1846
1656
  return [
1847
1657
  obj
@@ -1850,161 +1660,159 @@ var sanitizeObjects = async (types, data, db, queue) => {
1850
1660
  return [];
1851
1661
  });
1852
1662
  };
1853
- var SoftRef = Schema8.Struct({
1854
- "/": Schema8.String
1663
+ var SoftRef = Schema7.Struct({
1664
+ "/": Schema7.String
1855
1665
  }).annotations({
1856
1666
  description: "Reference to another object."
1857
1667
  });
1858
1668
  var preprocessSchema = (schema) => {
1859
1669
  const isRelationSchema = getEntityKind(schema) === "relation";
1860
- const go = (ast) => {
1670
+ const go = (ast, visited = /* @__PURE__ */ new Set()) => {
1671
+ if (visited.has(ast)) {
1672
+ return ast;
1673
+ }
1674
+ visited.add(ast);
1861
1675
  if (SchemaAST.getAnnotation(ast, ReferenceAnnotationId).pipe(Option2.isSome)) {
1862
1676
  return SoftRef.ast;
1863
1677
  }
1864
- return mapAst(ast, go);
1678
+ return mapAst(ast, (child) => go(child, visited));
1865
1679
  };
1866
- return Schema8.make(mapAst(schema.ast, go)).pipe(Schema8.omit("id"), Schema8.extend(Schema8.Struct({
1867
- id: Schema8.String.annotations({
1680
+ return Schema7.make(mapAst(schema.ast, (ast) => go(ast))).pipe(Schema7.omit("id"), Schema7.extend(Schema7.Struct({
1681
+ id: Schema7.String.annotations({
1868
1682
  description: "The id of this object. Come up with a unique id based on your judgement."
1869
1683
  })
1870
- })), isRelationSchema ? Schema8.extend(Schema8.Struct({
1871
- source: Schema8.String.annotations({
1684
+ })), isRelationSchema ? Schema7.extend(Schema7.Struct({
1685
+ source: Schema7.String.annotations({
1872
1686
  description: "The id of the source object for this relation."
1873
1687
  }),
1874
- target: Schema8.String.annotations({
1688
+ target: Schema7.String.annotations({
1875
1689
  description: "The id of the target object for this relation."
1876
1690
  })
1877
1691
  })) : identity);
1878
1692
  };
1879
- var createGraphWriterTool = ({ db, queue, schema, onDone = async (x) => x }) => {
1880
- return createTool3("graph", {
1881
- name: "writer",
1882
- description: "Write to the local graph database",
1883
- schema: createExtractionSchema(schema),
1884
- execute: async (input) => {
1885
- const data = await sanitizeObjects(schema, input, db, queue);
1886
- return ToolResult3.Success(await onDone(data));
1887
- }
1888
- });
1889
- };
1890
1693
 
1891
1694
  // raw-loader:./instructions-research.tpl?raw
1892
- 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>";
1893
1696
 
1894
1697
  // src/research/research.ts
1895
1698
  var __dxlog_file9 = "/__w/dxos/dxos/packages/core/assistant/src/research/research.ts";
1896
1699
  var researchFn = defineFunction3({
1897
1700
  description: "Research the web for information",
1898
- inputSchema: Schema9.Struct({
1899
- query: Schema9.String.annotations({
1701
+ inputSchema: Schema8.Struct({
1702
+ query: Schema8.String.annotations({
1900
1703
  description: "The query to search for."
1901
1704
  }),
1902
1705
  // TOOD(burdon): Move to context.
1903
- mockSearch: Schema9.optional(Schema9.Boolean).annotations({
1706
+ mockSearch: Schema8.optional(Schema8.Boolean).annotations({
1904
1707
  description: "Whether to use the mock search tool.",
1905
1708
  default: false
1906
1709
  })
1907
1710
  }),
1908
- outputSchema: Schema9.Struct({
1909
- // result: Schema.String,
1910
- result: Schema9.Any
1711
+ outputSchema: Schema8.Struct({
1712
+ result: Schema8.Unknown
1911
1713
  }),
1912
- handler: async ({ data: { query, mockSearch }, context }) => {
1913
- const ai = context.getService(AiService3);
1914
- const credentials = context.getService(CredentialsService);
1915
- const { db } = context.getService(DatabaseService2);
1916
- const tracing = context.getService(TracingService);
1917
- tracing.write(create5(AgentStatusReport2, {
1714
+ handler: Effect6.fnUntraced(function* ({ data: { query, mockSearch } }) {
1715
+ yield* TracingService.emitStatus({
1918
1716
  message: "Researching..."
1919
- }));
1920
- const exaCredential = await credentials.getCredential({
1921
- service: "exa.ai"
1922
1717
  });
1923
- const searchTool = mockSearch ? createMockExaTool() : createExaTool({
1924
- apiKey: exaCredential.apiKey
1718
+ const graphWriteToolkit = makeGraphWriterToolkit({
1719
+ schema: DataTypes
1925
1720
  });
1721
+ const toolkit = yield* AiToolkit4.merge(ExaToolkit, LocalSearchToolkit, graphWriteToolkit).pipe(Effect6.provide(Layer2.mergeAll(mockSearch ? MockExaHandler : LiveExaHandler, LocalSearchHandler, makeGraphWriterHandler(graphWriteToolkit))));
1926
1722
  const printer = new ConsolePrinter();
1927
- const session = new AISession({
1928
- operationModel: "configured"
1929
- });
1723
+ const session = new AiSession();
1930
1724
  session.message.on((message) => printer.printMessage(message));
1931
1725
  session.userMessage.on((message) => printer.printMessage(message));
1932
1726
  session.block.on((block) => printer.printContentBlock(block));
1933
- session.statusReport.on((status) => {
1934
- log9.info("[agent] status", {
1935
- status
1936
- }, {
1937
- F: __dxlog_file9,
1938
- L: 58,
1939
- S: void 0,
1940
- C: (f, a) => f(...a)
1941
- });
1942
- tracing.write(status);
1943
- });
1944
- session.streamEvent.on((event) => log9("stream", {
1727
+ session.streamEvent.on((event) => log8("stream", {
1945
1728
  event
1946
1729
  }, {
1947
1730
  F: __dxlog_file9,
1948
- L: 61,
1949
- S: void 0,
1731
+ L: 62,
1732
+ S: this,
1950
1733
  C: (f, a) => f(...a)
1951
1734
  }));
1952
- const graphWriteTool = createGraphWriterTool({
1953
- db,
1954
- schema: DataTypes
1955
- });
1956
- log9.info("graphWriteTool", {
1957
- schema: graphWriteTool.parameters
1958
- }, {
1959
- F: __dxlog_file9,
1960
- L: 64,
1961
- S: void 0,
1962
- C: (f, a) => f(...a)
1963
- });
1964
- const result = await session.run({
1965
- client: ai.client,
1966
- systemPrompt: instructions_research_default,
1967
- artifacts: [],
1968
- tools: [
1969
- searchTool.id,
1970
- graphWriteTool.id
1971
- ],
1972
- history: [],
1735
+ const result = yield* session.run({
1973
1736
  prompt: query,
1974
- toolResolver: new ToolRegistry2([
1975
- searchTool,
1976
- graphWriteTool
1977
- ])
1737
+ history: [],
1738
+ systemPrompt: instructions_research_default,
1739
+ toolkit
1978
1740
  });
1979
1741
  return {
1980
1742
  result
1981
1743
  };
1982
- }
1744
+ }, Effect6.provide(AiService2.model("@anthropic/claude-3-5-sonnet-20241022")))
1983
1745
  });
1984
1746
 
1747
+ // src/templates/prompt.ts
1748
+ import { Template } from "@dxos/blueprints";
1749
+
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}}";
1752
+
1753
+ // src/templates/prompt.ts
1754
+ var createSystemPrompt = (options) => {
1755
+ return Template.createPrompt(assistant_default, options);
1756
+ };
1757
+
1985
1758
  // src/types.ts
1759
+ import { Schema as Schema9 } from "effect";
1760
+ import { DXN as DXN3, LOCAL_SPACE_TAG } from "@dxos/keys";
1986
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}`);
1791
+ }
1792
+ }
1793
+ };
1987
1794
  export {
1988
- AIServiecOverloadedError,
1989
- AISession,
1795
+ AiSession,
1796
+ ArtifactDiffResolver,
1797
+ ArtifactId,
1990
1798
  Bindings,
1991
- Blueprint,
1992
- BlueprintRegistry,
1993
1799
  ContextBinder,
1994
1800
  ContextBinding,
1995
1801
  Conversation,
1802
+ ExaToolkit,
1996
1803
  ExtractionInput,
1997
1804
  ExtractionOutput,
1805
+ LiveExaHandler,
1806
+ LocalSearchHandler,
1807
+ LocalSearchToolkit,
1808
+ MockExaHandler,
1998
1809
  ReferencedQuotes,
1999
1810
  Subgraph,
2000
1811
  VersionPin,
2001
1812
  combineNerTokens,
2002
1813
  createArtifactElement,
2003
- createExaTool,
2004
1814
  createExtractionSchema,
2005
- createGraphWriterTool,
2006
- createLocalSearchTool,
2007
- createMockExaTool,
1815
+ createSystemPrompt,
2008
1816
  createTokenGroups,
2009
1817
  extractFullEntities,
2010
1818
  extractionAnthropicFn,
@@ -2014,6 +1822,10 @@ export {
2014
1822
  getNer,
2015
1823
  getSanitizedSchemaName,
2016
1824
  insertReferences,
1825
+ makeGraphWriterHandler,
1826
+ makeGraphWriterToolkit,
1827
+ makeToolExecutionServiceFromFunctions,
1828
+ makeToolResolverFromFunctions,
2017
1829
  processTranscriptMessage,
2018
1830
  researchFn,
2019
1831
  sanitizeObjects