@dxos/assistant 0.8.2-main.f081794 → 0.8.2-main.f11618f

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 (39) hide show
  1. package/dist/lib/browser/index.mjs +270 -150
  2. package/dist/lib/browser/index.mjs.map +4 -4
  3. package/dist/lib/browser/meta.json +1 -1
  4. package/dist/lib/browser/testing/index.mjs +7 -7
  5. package/dist/lib/browser/testing/index.mjs.map +3 -3
  6. package/dist/lib/node/index.cjs +266 -149
  7. package/dist/lib/node/index.cjs.map +4 -4
  8. package/dist/lib/node/meta.json +1 -1
  9. package/dist/lib/node/testing/index.cjs +8 -8
  10. package/dist/lib/node/testing/index.cjs.map +3 -3
  11. package/dist/lib/node-esm/index.mjs +270 -150
  12. package/dist/lib/node-esm/index.mjs.map +4 -4
  13. package/dist/lib/node-esm/meta.json +1 -1
  14. package/dist/lib/node-esm/testing/index.mjs +7 -7
  15. package/dist/lib/node-esm/testing/index.mjs.map +3 -3
  16. package/dist/types/src/session/index.d.ts +1 -0
  17. package/dist/types/src/session/index.d.ts.map +1 -1
  18. package/dist/types/src/session/session.d.ts +29 -4
  19. package/dist/types/src/session/session.d.ts.map +1 -1
  20. package/dist/types/src/session/version-pin.d.ts +17 -0
  21. package/dist/types/src/session/version-pin.d.ts.map +1 -0
  22. package/dist/types/src/session/version-pin.test.d.ts +2 -0
  23. package/dist/types/src/session/version-pin.test.d.ts.map +1 -0
  24. package/dist/types/src/testing/test-schema.d.ts +2 -2
  25. package/dist/types/src/testing/test-schema.d.ts.map +1 -1
  26. package/package.json +13 -13
  27. package/src/bin/chat.ts +2 -2
  28. package/src/cypher/combinators.test.ts +4 -4
  29. package/src/cypher/execution-plan.test.ts +1 -1
  30. package/src/cypher/query-executor.test.ts +1 -1
  31. package/src/cypher/schema.test.ts +3 -3
  32. package/src/session/index.ts +1 -0
  33. package/src/session/session.test.ts +2 -1
  34. package/src/session/session.ts +283 -147
  35. package/src/session/version-pin.test.ts +26 -0
  36. package/src/session/version-pin.ts +43 -0
  37. package/src/testing/query.test.ts +3 -3
  38. package/src/testing/test-data.ts +5 -5
  39. package/src/testing/test-schema.ts +3 -3
@@ -33,12 +33,45 @@ import {
33
33
  } from "./chunk-7JI4MDGL.mjs";
34
34
 
35
35
  // packages/experimental/assistant/src/session/session.ts
36
- import { Schema as S } from "effect";
36
+ import { Option, Schema as S } from "effect";
37
37
  import { defineTool, Message, ToolResult } from "@dxos/artifact";
38
38
  import { Event, synchronized } from "@dxos/async";
39
+ import { ObjectVersion } from "@dxos/echo-db";
39
40
  import { create } from "@dxos/echo-schema";
40
41
  import { invariant } from "@dxos/invariant";
41
42
  import { log } from "@dxos/log";
43
+
44
+ // packages/experimental/assistant/src/session/version-pin.ts
45
+ import { Schema } from "effect";
46
+ import { getVersion } from "@dxos/echo-db";
47
+ import { ObjectId } from "@dxos/echo-schema";
48
+ var ObjectVersionSchema = Schema.Unknown;
49
+ var VersionPinSchema = Schema.Struct({
50
+ // TODO(dmaretskyi): Use Ref when those support encoding.
51
+ objectId: ObjectId,
52
+ // TODO(dmaretskyi): Could be opaque
53
+ version: ObjectVersionSchema
54
+ });
55
+ var VersionPin = class extends VersionPinSchema {
56
+ static {
57
+ this.DISPOSITION = "version-pin";
58
+ }
59
+ static fromObject(object) {
60
+ return VersionPin.make({
61
+ objectId: object.id,
62
+ version: getVersion(object)
63
+ });
64
+ }
65
+ static createBlock(pin) {
66
+ return {
67
+ type: "json",
68
+ disposition: VersionPin.DISPOSITION,
69
+ json: JSON.stringify(pin)
70
+ };
71
+ }
72
+ };
73
+
74
+ // packages/experimental/assistant/src/session/session.ts
42
75
  function _ts_decorate(decorators, target, key, desc) {
43
76
  var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
44
77
  if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
@@ -62,152 +95,28 @@ var AISession = class _AISession {
62
95
  });
63
96
  }
64
97
  async run(options) {
65
- const systemTools = [
66
- defineTool("system", {
67
- name: "query_artifact_definitions",
68
- description: "Query the available artifact definitions",
69
- schema: S.Struct({}),
70
- execute: async () => {
71
- return ToolResult.Success({
72
- artifactDefinitions: options.artifacts.map((artifact) => ({
73
- id: artifact.id,
74
- name: artifact.name,
75
- description: artifact.description
76
- }))
77
- });
78
- }
79
- })
80
- ];
98
+ const systemTools = [];
81
99
  switch (this._options.operationModel) {
82
100
  case "planning":
83
- systemTools.push(defineTool("system", {
84
- name: "create_plan",
85
- 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.",
86
- schema: S.Struct({
87
- goal: S.String.annotations({
88
- description: "The goal that the plan will achieve."
89
- }),
90
- steps: S.Array(S.Struct({
91
- action: S.String.annotations({
92
- description: "Complete, detailed action to perform."
93
- }),
94
- input: S.String.annotations({
95
- description: "The required input data for this step. First step must not require any data."
96
- }),
97
- output: S.String.annotations({
98
- description: "The output data from this step. This is passed to the next step as input."
99
- }),
100
- requiredArtifactIds: S.Array(S.String).annotations({
101
- description: "The ids of the artifacts required to perform this step.",
102
- examples: [
103
- [
104
- "artifact:dxos.org/example/Test"
105
- ]
106
- ]
107
- })
108
- })).annotations({
109
- description: "Steps"
110
- })
111
- }),
112
- execute: async ({ goal, steps }) => {
113
- const missingArtifactIds = steps.flatMap((step) => step.requiredArtifactIds).filter((artifactId) => !options.artifacts.some((artifact) => artifact.id === artifactId));
114
- if (missingArtifactIds.length > 0) {
115
- return ToolResult.Error(`One or more artifact ids are invalid: ${missingArtifactIds.join(", ")}`);
116
- }
117
- const stepResults = [];
118
- for (const step of steps) {
119
- log("executing step", {
120
- action: step.action
121
- }, {
122
- F: __dxlog_file,
123
- L: 160,
124
- S: this,
125
- C: (f, a) => f(...a)
126
- });
127
- const session = new _AISession({
128
- operationModel: "immediate"
129
- });
130
- session.message.on((ev) => this.message.emit(ev));
131
- session.block.on((ev) => this.block.emit(ev));
132
- session.update.on((ev) => this.update.emit(ev));
133
- session.streamEvent.on((ev) => this.streamEvent.emit(ev));
134
- session.userMessage.on((ev) => this.userMessage.emit(ev));
135
- const messages = await session.run({
136
- client: options.client,
137
- artifacts: options.artifacts,
138
- tools: options.tools,
139
- history: options.history,
140
- extensions: options.extensions,
141
- generationOptions: options.generationOptions,
142
- requiredArtifactIds: step.requiredArtifactIds.slice(),
143
- prompt: `
144
- You are an agent that executes the subtask in a plan.
145
-
146
- While you know the plan's goal only focus on your subtask
147
- Use the data from the previous step to complete your task.
148
- Return all of the data from "output" in your last message.
149
-
150
- Current step (that you need to complete):
151
- ${JSON.stringify({
152
- goal,
153
- input: step.input,
154
- output: step.output,
155
- yourTask: step.action
156
- }, null, 2)}
157
-
158
- Previous step results:
159
- ${JSON.stringify(stepResults.at(-1))}.
160
- `
161
- });
162
- const result = messages.at(-1);
163
- stepResults.push(result);
164
- }
165
- return ToolResult.Success({
166
- stepResults
167
- });
168
- }
169
- }));
101
+ systemTools.push(this._createQueryArtifactsTool(options.artifacts), this._createPlanningTool(options));
170
102
  break;
171
- case "immediate":
172
- systemTools.push(defineTool("system", {
173
- name: "require_artifact_definitions",
174
- description: "Require the use of specific artifact definitions. This will allow the model to interact with artifact definitions and use their tools.",
175
- schema: S.Struct({
176
- artifactDefinitionIds: S.Array(S.String).annotations({
177
- description: "The ids of the artifact definitions to require",
178
- examples: [
179
- [
180
- "artifact:dxos.org/example/Test"
181
- ]
182
- ]
183
- })
184
- }),
185
- execute: async ({ artifactDefinitionIds }) => {
186
- const missingArtifactDefinitionIds = artifactDefinitionIds.filter((artifactId) => !options.artifacts.some((artifact) => artifact.id === artifactId));
187
- if (missingArtifactDefinitionIds.length > 0) {
188
- return ToolResult.Error(`One or more artifact definition ids are invalid: ${missingArtifactDefinitionIds.join(", ")}`);
189
- }
190
- for (const artifactDefinitionId of artifactDefinitionIds) {
191
- requiredArtifactIds.add(artifactDefinitionId);
192
- }
193
- return ToolResult.Success({});
103
+ case "importing":
104
+ systemTools.push(this._createQueryArtifactsTool(options.artifacts), this._createRequireTool(options.artifacts, (artifactDefinitionIds) => {
105
+ for (const artifactDefinitionId of artifactDefinitionIds) {
106
+ requiredArtifactIds.add(artifactDefinitionId);
194
107
  }
195
108
  }));
196
109
  break;
110
+ case "configured":
111
+ break;
112
+ default:
113
+ throw new TypeError(`Invalid operation model: ${this._options.operationModel}`);
197
114
  }
198
115
  this._history = [
199
116
  ...options.history
200
117
  ];
201
118
  this._pending = [
202
- create(Message, {
203
- role: "user",
204
- content: [
205
- {
206
- type: "text",
207
- text: options.prompt
208
- }
209
- ]
210
- })
119
+ await this._formatUserPrompt(options.artifactDiffResolver, options.prompt, options.history)
211
120
  ];
212
121
  this.userMessage.emit(this._pending.at(-1));
213
122
  this._stream = void 0;
@@ -227,7 +136,7 @@ var AISession = class _AISession {
227
136
  tools: tools.map((tool) => tool.name)
228
137
  }, {
229
138
  F: __dxlog_file,
230
- L: 264,
139
+ L: 180,
231
140
  S: this,
232
141
  C: (f, a) => f(...a)
233
142
  });
@@ -250,7 +159,7 @@ var AISession = class _AISession {
250
159
  pending: this._pending
251
160
  }, {
252
161
  F: __dxlog_file,
253
- L: 289,
162
+ L: 205,
254
163
  S: this,
255
164
  C: (f, a) => f(...a)
256
165
  });
@@ -258,7 +167,7 @@ var AISession = class _AISession {
258
167
  const message = this._pending.at(-1);
259
168
  invariant(message, void 0, {
260
169
  F: __dxlog_file,
261
- L: 294,
170
+ L: 210,
262
171
  S: this,
263
172
  A: [
264
173
  "message",
@@ -268,7 +177,7 @@ var AISession = class _AISession {
268
177
  if (isToolUse(message)) {
269
178
  log("tool request...", void 0, {
270
179
  F: __dxlog_file,
271
- L: 296,
180
+ L: 212,
272
181
  S: this,
273
182
  C: (f, a) => f(...a)
274
183
  });
@@ -281,7 +190,7 @@ var AISession = class _AISession {
281
190
  response
282
191
  }, {
283
192
  F: __dxlog_file,
284
- L: 303,
193
+ L: 219,
285
194
  S: this,
286
195
  C: (f, a) => f(...a)
287
196
  });
@@ -301,7 +210,7 @@ var AISession = class _AISession {
301
210
  } catch (err) {
302
211
  log.catch(err, void 0, {
303
212
  F: __dxlog_file,
304
- L: 315,
213
+ L: 231,
305
214
  S: this,
306
215
  C: (f, a) => f(...a)
307
216
  });
@@ -322,6 +231,180 @@ var AISession = class _AISession {
322
231
  }
323
232
  return this._pending;
324
233
  }
234
+ async _formatUserPrompt(artifactDiffResolver, prompt, history) {
235
+ const prelude = [];
236
+ if (artifactDiffResolver) {
237
+ const versions = gatherObjectVersions(history);
238
+ const artifactDiff = await artifactDiffResolver(Array.from(versions.entries()).map(([id, version]) => ({
239
+ id,
240
+ lastVersion: version
241
+ })));
242
+ log.info("vision", {
243
+ artifactDiff,
244
+ versions
245
+ }, {
246
+ F: __dxlog_file,
247
+ L: 262,
248
+ S: this,
249
+ C: (f, a) => f(...a)
250
+ });
251
+ for (const [id, { version }] of [
252
+ ...artifactDiff.entries()
253
+ ]) {
254
+ if (ObjectVersion.equals(version, versions.get(id))) {
255
+ artifactDiff.delete(id);
256
+ continue;
257
+ }
258
+ prelude.push(VersionPin.createBlock(VersionPin.make({
259
+ objectId: id,
260
+ version
261
+ })));
262
+ }
263
+ if (artifactDiff.size > 0) {
264
+ prelude.push(createArtifactUpdateBlock(artifactDiff));
265
+ }
266
+ }
267
+ return create(Message, {
268
+ role: "user",
269
+ content: [
270
+ ...prelude,
271
+ {
272
+ type: "text",
273
+ text: prompt
274
+ }
275
+ ]
276
+ });
277
+ }
278
+ _createQueryArtifactsTool(artifacts) {
279
+ return defineTool("system", {
280
+ name: "query_artifact_definitions",
281
+ description: "Query the available artifact definitions",
282
+ schema: S.Struct({}),
283
+ execute: async () => {
284
+ return ToolResult.Success({
285
+ artifactDefinitions: artifacts.map((artifact) => ({
286
+ id: artifact.id,
287
+ name: artifact.name,
288
+ description: artifact.description
289
+ }))
290
+ });
291
+ }
292
+ });
293
+ }
294
+ _createRequireTool(artifacts, onRequire) {
295
+ return defineTool("system", {
296
+ name: "require_artifact_definitions",
297
+ description: "Require the use of specific artifact definitions. This will allow the model to interact with artifact definitions and use their tools.",
298
+ schema: S.Struct({
299
+ artifactDefinitionIds: S.Array(S.String).annotations({
300
+ description: "The ids of the artifact definitions to require",
301
+ examples: [
302
+ [
303
+ "artifact:dxos.org/example/Test"
304
+ ]
305
+ ]
306
+ })
307
+ }),
308
+ execute: async ({ artifactDefinitionIds }) => {
309
+ const missingArtifactDefinitionIds = artifactDefinitionIds.filter((artifactId) => !artifacts.some((artifact) => artifact.id === artifactId));
310
+ if (missingArtifactDefinitionIds.length > 0) {
311
+ return ToolResult.Error(`One or more artifact definition ids are invalid: ${missingArtifactDefinitionIds.join(", ")}`);
312
+ }
313
+ onRequire(artifactDefinitionIds);
314
+ return ToolResult.Success({});
315
+ }
316
+ });
317
+ }
318
+ _createPlanningTool(options) {
319
+ return defineTool("system", {
320
+ name: "create_plan",
321
+ 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.",
322
+ schema: S.Struct({
323
+ goal: S.String.annotations({
324
+ description: "The goal that the plan will achieve."
325
+ }),
326
+ steps: S.Array(S.Struct({
327
+ action: S.String.annotations({
328
+ description: "Complete, detailed action to perform."
329
+ }),
330
+ input: S.String.annotations({
331
+ description: "The required input data for this step. First step must not require any data."
332
+ }),
333
+ output: S.String.annotations({
334
+ description: "The output data from this step. This is passed to the next step as input."
335
+ }),
336
+ requiredArtifactIds: S.Array(S.String).annotations({
337
+ description: "The ids of the artifacts required to perform this step.",
338
+ examples: [
339
+ [
340
+ "artifact:dxos.org/example/Test"
341
+ ]
342
+ ]
343
+ })
344
+ })).annotations({
345
+ description: "Steps"
346
+ })
347
+ }),
348
+ execute: async ({ goal, steps }) => {
349
+ const missingArtifactIds = steps.flatMap((step) => step.requiredArtifactIds).filter((artifactId) => !options.artifacts.some((artifact) => artifact.id === artifactId));
350
+ if (missingArtifactIds.length > 0) {
351
+ return ToolResult.Error(`One or more artifact ids are invalid: ${missingArtifactIds.join(", ")}`);
352
+ }
353
+ const stepResults = [];
354
+ for (const step of steps) {
355
+ log("executing step", {
356
+ action: step.action
357
+ }, {
358
+ F: __dxlog_file,
359
+ L: 369,
360
+ S: this,
361
+ C: (f, a) => f(...a)
362
+ });
363
+ const session = new _AISession({
364
+ operationModel: "importing"
365
+ });
366
+ session.message.on((ev) => this.message.emit(ev));
367
+ session.block.on((ev) => this.block.emit(ev));
368
+ session.update.on((ev) => this.update.emit(ev));
369
+ session.streamEvent.on((ev) => this.streamEvent.emit(ev));
370
+ session.userMessage.on((ev) => this.userMessage.emit(ev));
371
+ const messages = await session.run({
372
+ client: options.client,
373
+ artifacts: options.artifacts,
374
+ tools: options.tools,
375
+ history: options.history,
376
+ extensions: options.extensions,
377
+ generationOptions: options.generationOptions,
378
+ requiredArtifactIds: step.requiredArtifactIds.slice(),
379
+ artifactDiffResolver: options.artifactDiffResolver,
380
+ prompt: `
381
+ You are an agent that executes the subtask in a plan.
382
+
383
+ While you know the plan's goal only focus on your subtask
384
+ Use the data from the previous step to complete your task.
385
+ Return all of the data from "output" in your last message.
386
+
387
+ Current step (that you need to complete):
388
+ ${JSON.stringify({
389
+ goal,
390
+ input: step.input,
391
+ output: step.output,
392
+ yourTask: step.action
393
+ }, null, 2)}
394
+
395
+ Previous step results:
396
+ ${JSON.stringify(stepResults.at(-1))}.
397
+ `
398
+ });
399
+ const result = messages.at(-1);
400
+ stepResults.push(result);
401
+ }
402
+ return ToolResult.Success({
403
+ stepResults
404
+ });
405
+ }
406
+ });
407
+ }
325
408
  abort() {
326
409
  this._stream?.abort();
327
410
  }
@@ -339,21 +422,57 @@ var createBaseInstructions = ({ availableArtifacts, operationModel }) => `
339
422
  Decision-making:
340
423
 
341
424
  - Analyze the structure and type of the content in the user's message.
342
- - Can you complete the task using the available artifacts?
343
- - If you can't complete the task using the available artifacts, query the list of available artifacts using the appropriate tool.
344
- - Identify which artifacts are relevant to the user's request.
425
+
426
+
345
427
  ${operationModel === "planning" ? `
428
+ - Can you complete the task using the available artifacts?
429
+ - If you can't complete the task using the available artifacts, query the list of available artifacts using the appropriate tool.
430
+ - Identify which artifacts are relevant to the user's request.
346
431
  - 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.
347
- ` : `
348
- - Are the required artifacts already available?
349
- - If not, select which artifact(s) will be the most relevant and require them using the require_artifacts tool.
350
- - The require'd artifact tools will be available for use after require.
351
- `}
432
+ ` : ""}
433
+ ${operationModel === "importing" ? `
434
+ - Can you complete the task using the available artifacts?
435
+ - If you can't complete the task using the available artifacts, query the list of available artifacts using the appropriate tool.
436
+ - Identify which artifacts are relevant to the user's request.
437
+ - Are the required artifacts already available?
438
+ - If not, select which artifact(s) will be the most relevant and require them using the require_artifacts tool.
439
+ - The require'd artifact tools will be available for use after require.
440
+ ` : ""}
441
+ ${operationModel === "configured" ? `
442
+ - Select the most relevant artifact(s) to complete the task.
443
+ - Call the appropriate tool to use the artifact(s).
444
+ ` : ""}
352
445
 
353
446
  ${availableArtifacts.length > 0 ? `Artifacts already in context: ${availableArtifacts.join("\n")}` : ""}
354
447
  `;
355
448
  var AIServiecOverloadedError = class extends S.TaggedError()("AIServiecOverloadedError", {}) {
356
449
  };
450
+ var gatherObjectVersions = (messages) => {
451
+ const artifactIds = /* @__PURE__ */ new Map();
452
+ for (const message of messages) {
453
+ for (const block of message.content) {
454
+ if (block.type === "json" && block.disposition === VersionPin.DISPOSITION) {
455
+ const pin = VersionPin.pipe(S.decodeOption)(JSON.parse(block.json)).pipe(Option.getOrUndefined);
456
+ if (!pin) {
457
+ continue;
458
+ }
459
+ artifactIds.set(pin.objectId, pin.version);
460
+ }
461
+ }
462
+ }
463
+ return artifactIds;
464
+ };
465
+ var createArtifactUpdateBlock = (artifactDiff) => {
466
+ return {
467
+ type: "text",
468
+ disposition: "artifact-update",
469
+ text: `
470
+ The following artifacts have been updated since the last message:
471
+ ${Array.from(artifactDiff.entries()).map(([id, { diff }]) => `<changed-artifact id="${id}">${diff ? `
472
+ ${diff}` : ""}</changed-artifact>`).join("\n")}
473
+ `
474
+ };
475
+ };
357
476
  export {
358
477
  AIServiceEdgeClient,
359
478
  AIServiecOverloadedError,
@@ -373,6 +492,7 @@ export {
373
492
  OllamaClient,
374
493
  StreamTransform,
375
494
  ToolTypes,
495
+ VersionPin,
376
496
  createArtifactElement,
377
497
  createGenerationStream,
378
498
  emitMessageAsEvents,