@dxos/assistant 0.8.3 → 0.8.4-main.2e9d522

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