@dxos/assistant 0.9.0 → 0.9.1-staging.ee54ba693a

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 (84) hide show
  1. package/dist/lib/neutral/extraction/index.mjs +108 -119
  2. package/dist/lib/neutral/extraction/index.mjs.map +4 -4
  3. package/dist/lib/neutral/index.mjs +395 -234
  4. package/dist/lib/neutral/index.mjs.map +4 -4
  5. package/dist/lib/neutral/meta.json +1 -1
  6. package/dist/types/src/extraction/extraction-llm-function/index.d.ts +2 -0
  7. package/dist/types/src/extraction/extraction-llm-function/index.d.ts.map +1 -0
  8. package/dist/types/src/extraction/extraction-llm-function/proper-noun-extraction.d.ts +26 -0
  9. package/dist/types/src/extraction/extraction-llm-function/proper-noun-extraction.d.ts.map +1 -0
  10. package/dist/types/src/extraction/index.d.ts +1 -1
  11. package/dist/types/src/extraction/index.d.ts.map +1 -1
  12. package/dist/types/src/extraction/quotes.d.ts +8 -1
  13. package/dist/types/src/extraction/quotes.d.ts.map +1 -1
  14. package/dist/types/src/index.d.ts +1 -1
  15. package/dist/types/src/index.d.ts.map +1 -1
  16. package/dist/types/src/request/AiRequest.d.ts +19 -208
  17. package/dist/types/src/request/AiRequest.d.ts.map +1 -1
  18. package/dist/types/src/request/format.d.ts +1 -1
  19. package/dist/types/src/request/format.d.ts.map +1 -1
  20. package/dist/types/src/session/AiContext.d.ts +27 -105
  21. package/dist/types/src/session/AiContext.d.ts.map +1 -1
  22. package/dist/types/src/session/AiSession.d.ts +11 -29
  23. package/dist/types/src/session/AiSession.d.ts.map +1 -1
  24. package/dist/types/src/session/Harness.d.ts +122 -0
  25. package/dist/types/src/session/Harness.d.ts.map +1 -0
  26. package/dist/types/src/session/SessionLink.d.ts +8 -11
  27. package/dist/types/src/session/SessionLink.d.ts.map +1 -1
  28. package/dist/types/src/session/SessionLoader.d.ts +2 -2
  29. package/dist/types/src/session/SessionLoader.d.ts.map +1 -1
  30. package/dist/types/src/session/SkillHooks.d.ts +28 -0
  31. package/dist/types/src/session/SkillHooks.d.ts.map +1 -0
  32. package/dist/types/src/session/harness-control.d.ts +177 -0
  33. package/dist/types/src/session/harness-control.d.ts.map +1 -0
  34. package/dist/types/src/session/index.d.ts +3 -0
  35. package/dist/types/src/session/index.d.ts.map +1 -1
  36. package/dist/types/src/session/toolkit.d.ts +4 -4
  37. package/dist/types/src/session/toolkit.d.ts.map +1 -1
  38. package/dist/types/src/templates/system.d.ts +4 -6
  39. package/dist/types/src/templates/system.d.ts.map +1 -1
  40. package/dist/types/src/tool-runtime/index.d.ts.map +1 -0
  41. package/dist/types/src/tool-runtime/services.d.ts.map +1 -0
  42. package/dist/types/src/util/artifact.d.ts.map +1 -1
  43. package/dist/types/src/util/diff.d.ts +9 -3
  44. package/dist/types/src/util/diff.d.ts.map +1 -1
  45. package/dist/types/src/util/tracing.d.ts +40 -0
  46. package/dist/types/src/util/tracing.d.ts.map +1 -1
  47. package/dist/types/tsconfig.tsbuildinfo +1 -1
  48. package/package.json +28 -25
  49. package/src/extraction/extraction-llm-function/index.ts +5 -0
  50. package/src/extraction/extraction-llm-function/proper-noun-extraction.ts +78 -0
  51. package/src/extraction/index.ts +1 -1
  52. package/src/extraction/quotes.test.ts +67 -2
  53. package/src/extraction/quotes.ts +47 -13
  54. package/src/index.ts +1 -1
  55. package/src/request/AiRequest.ts +45 -14
  56. package/src/request/format.ts +9 -11
  57. package/src/session/AiContext.test.ts +52 -32
  58. package/src/session/AiContext.ts +73 -95
  59. package/src/session/AiSession.test.ts +4 -4
  60. package/src/session/AiSession.ts +51 -83
  61. package/src/session/Harness.ts +241 -0
  62. package/src/session/SessionLink.ts +8 -8
  63. package/src/session/SessionLoader.ts +4 -4
  64. package/src/session/SkillHooks.ts +71 -0
  65. package/src/session/harness-control.ts +30 -0
  66. package/src/session/index.ts +3 -0
  67. package/src/session/toolkit.ts +8 -8
  68. package/src/templates/instructions/format.tpl +3 -3
  69. package/src/templates/instructions/system.tpl +10 -12
  70. package/src/templates/system.ts +6 -2
  71. package/src/util/artifact.ts +9 -2
  72. package/src/util/diff.test.ts +4 -4
  73. package/src/util/diff.ts +15 -8
  74. package/src/util/tracing.ts +1 -1
  75. package/dist/types/src/extraction/extraction.d.ts +0 -1677
  76. package/dist/types/src/extraction/extraction.d.ts.map +0 -1
  77. package/dist/types/src/functions/index.d.ts.map +0 -1
  78. package/dist/types/src/functions/services.d.ts.map +0 -1
  79. package/src/extraction/extraction-llm-function/transcription-instructions.tpl +0 -28
  80. package/src/extraction/extraction.ts +0 -105
  81. /package/dist/types/src/{functions → tool-runtime}/index.d.ts +0 -0
  82. /package/dist/types/src/{functions → tool-runtime}/services.d.ts +0 -0
  83. /package/src/{functions → tool-runtime}/index.ts +0 -0
  84. /package/src/{functions → tool-runtime}/services.ts +0 -0
@@ -2,48 +2,68 @@
2
2
  // Copyright 2025 DXOS.org
3
3
  //
4
4
 
5
- import * as Context from 'effect/Context';
6
5
  import * as Effect from 'effect/Effect';
7
- import * as Layer from 'effect/Layer';
8
- import * as Runtime from 'effect/Runtime';
9
6
  import * as Schema from 'effect/Schema';
10
- import { describe, it } from 'vitest';
7
+ import { describe, test } from 'vitest';
11
8
 
12
- import { DXN, Feed, Obj, Ref, Type } from '@dxos/echo';
9
+ import { Database, DXN, Feed, Obj, Ref, Type } from '@dxos/echo';
10
+ import { TestDatabaseLayer } from '@dxos/echo-client/testing';
13
11
 
14
12
  import * as AiContext from './AiContext';
15
13
 
16
- const createMockFeedRuntime = (): Runtime.Runtime<Feed.FeedService> => {
17
- const mockFeedService: Context.Tag.Service<Feed.FeedService> = {
18
- append: async () => {},
19
- remove: async () => {},
20
- query: () =>
21
- ({
22
- subscribe: () => () => {},
23
- results: [],
24
- run: async () => [],
25
- }) as any,
26
- sync: async () => {},
27
- getSyncState: async () => ({ blocksToPull: 0, blocksToPush: 0, totalBlocks: 0 }),
28
- };
29
- const layer = Layer.succeed(Feed.FeedService, mockFeedService);
30
- return Effect.runSync(Effect.runtime<Feed.FeedService>().pipe(Effect.provide(layer)));
31
- };
14
+ const TypeA = Type.makeObject(DXN.make('org.dxos.type.a', '0.1.0'))(Schema.Struct({}));
15
+ const TypeB = Type.makeObject(DXN.make('org.dxos.type.b', '0.1.0'))(Schema.Struct({}));
32
16
 
33
17
  describe('AiContext.Binder', () => {
34
- it('should handle bind with Ref', async () => {
35
- const feed = Feed.make();
36
- const runtime = createMockFeedRuntime();
37
- const binder = new AiContext.Binder({ feed, runtime });
18
+ const TestLayer = TestDatabaseLayer({ types: [Feed.Feed, TypeA, TypeB] });
38
19
 
39
- const TestSchema = Schema.Struct({}).pipe(Type.makeObject(DXN.make('org.dxos.type.example', '0.1.0')));
20
+ test('reopened binder resolves all distinct bound objects', async ({ expect }) => {
21
+ await Effect.gen(function* () {
22
+ const feed = yield* Database.add(Feed.make());
23
+ const runtime = yield* Effect.runtime<Database.Service>();
40
24
 
41
- const obj = Obj.make(TestSchema, {});
42
- const ref = Ref.make(obj);
25
+ const a = yield* Database.add(Obj.make(TypeA, {}));
26
+ const b = yield* Database.add(Obj.make(TypeB, {}));
43
27
 
44
- await binder.bind({
45
- blueprints: [],
46
- objects: [ref],
47
- });
28
+ // Bind two distinct objects across two separate bindings (as the chat + companion do).
29
+ const writer = new AiContext.Binder({ feed, runtime });
30
+ yield* Effect.promise(() => writer.open());
31
+ yield* Effect.promise(() => writer.bind({ objects: [Ref.make(a)] }));
32
+ yield* Effect.promise(() => writer.bind({ objects: [Ref.make(b)] }));
33
+ yield* Effect.promise(() => writer.close());
34
+
35
+ // Reopen over the same feed (the path ContextModule takes): bindings are re-read via _reduce.
36
+ const reader = new AiContext.Binder({ feed, runtime });
37
+ yield* Effect.promise(() => reader.open());
38
+ const objects = reader.getObjects();
39
+ yield* Effect.promise(() => reader.close());
40
+
41
+ expect(objects.map((obj) => Obj.getURI(obj)).sort()).toEqual([Obj.getURI(a), Obj.getURI(b)].sort());
42
+ })
43
+ .pipe(Effect.provide(TestLayer))
44
+ .pipe(Effect.runPromise);
45
+ });
46
+
47
+ test('should handle bind with Ref', async () => {
48
+ await Effect.gen(function* () {
49
+ const feed = yield* Database.add(Feed.make());
50
+ const runtime = yield* Effect.runtime<Database.Service>();
51
+
52
+ const TestSchema = Type.makeObject(DXN.make('org.dxos.type.example', '0.1.0'))(Schema.Struct({}));
53
+
54
+ const obj = Obj.make(TestSchema, {});
55
+ const ref = Ref.make(obj);
56
+
57
+ const binder = new AiContext.Binder({ feed, runtime });
58
+
59
+ yield* Effect.promise(() =>
60
+ binder.bind({
61
+ skills: [],
62
+ objects: [ref],
63
+ }),
64
+ );
65
+ })
66
+ .pipe(Effect.provide(TestLayer))
67
+ .pipe(Effect.runPromise);
48
68
  });
49
69
  });
@@ -6,15 +6,13 @@
6
6
 
7
7
  import { Atom, Registry as AtomRegistry } from '@effect-atom/atom-react';
8
8
  import * as EArray from 'effect/Array';
9
- import * as Context from 'effect/Context';
10
- import * as Effect from 'effect/Effect';
11
9
  import * as Function from 'effect/Function';
12
10
  import * as Runtime from 'effect/Runtime';
13
11
  import * as Schema from 'effect/Schema';
14
12
 
15
- import { Blueprint } from '@dxos/compute';
13
+ import { Skill } from '@dxos/compute';
16
14
  import { Resource } from '@dxos/context';
17
- import { Annotation, DXN, Feed, Obj, type QueryResult, Query, Ref, Type } from '@dxos/echo';
15
+ import { Annotation, Database, DXN, Feed, Obj, Query, type QueryResult, Ref, Type } from '@dxos/echo';
18
16
  import { assertArgument } from '@dxos/invariant';
19
17
  import { EID, type URI } from '@dxos/keys';
20
18
  import { log } from '@dxos/log';
@@ -23,26 +21,26 @@ import { ComplexSet, isNonNullable } from '@dxos/util';
23
21
  /**
24
22
  * Thread message that binds or unbinds contextual objects to a conversation.
25
23
  */
26
- export const Binding = Schema.Struct({
27
- blueprints: Schema.Struct({
28
- added: Schema.Array(Ref.Ref(Blueprint.Blueprint)),
29
- removed: Schema.Array(Ref.Ref(Blueprint.Blueprint)),
30
- }),
31
-
32
- objects: Schema.Struct({
33
- added: Schema.Array(Ref.Ref(Obj.Unknown)),
34
- removed: Schema.Array(Ref.Ref(Obj.Unknown)),
35
- }),
36
- }).pipe(Annotation.HiddenAnnotation.set(true), Type.makeObject(DXN.make('org.dxos.type.contextBinding', '0.1.0')));
37
-
38
- export type Binding = Type.InstanceType<typeof Binding>;
24
+ export class Binding extends Type.makeObject<Binding>(DXN.make('org.dxos.type.contextBinding', '0.1.0'))(
25
+ Schema.Struct({
26
+ skills: Schema.Struct({
27
+ added: Schema.Array(Ref.Ref(Skill.Skill)),
28
+ removed: Schema.Array(Ref.Ref(Skill.Skill)),
29
+ }),
30
+
31
+ objects: Schema.Struct({
32
+ added: Schema.Array(Ref.Ref(Obj.Unknown)),
33
+ removed: Schema.Array(Ref.Ref(Obj.Unknown)),
34
+ }),
35
+ }).pipe(Annotation.HiddenAnnotation.set(true)),
36
+ ) {}
39
37
  export type BindingProps = Partial<{
40
- blueprints: Ref.Ref<Blueprint.Blueprint>[];
38
+ skills: Ref.Ref<Skill.Skill>[];
41
39
  objects: Ref.Ref<Obj.Unknown>[];
42
40
  }>;
43
41
 
44
42
  export class Bindings {
45
- readonly blueprints = new ComplexSet<Ref.Ref<Blueprint.Blueprint>>((ref) => ref.uri);
43
+ readonly skills = new ComplexSet<Ref.Ref<Skill.Skill>>((ref) => ref.uri);
46
44
 
47
45
  // TODO(burdon): Some DXNs have the Space prefix so only compare the object ID.
48
46
  readonly objects = new ComplexSet<Ref.Ref<Obj.Unknown>>((ref) => {
@@ -50,9 +48,9 @@ export class Bindings {
50
48
  return echoUri ? EID.getEntityId(echoUri) : undefined;
51
49
  });
52
50
 
53
- toJSON(): { blueprints: URI.URI[]; objects: URI.URI[] } {
51
+ toJSON(): { skills: URI.URI[]; objects: URI.URI[] } {
54
52
  return {
55
- blueprints: EArray.fromIterable(this.blueprints).map((ref) => ref.uri),
53
+ skills: EArray.fromIterable(this.skills).map((ref) => ref.uri),
56
54
  objects: EArray.fromIterable(this.objects).map((ref) => ref.uri),
57
55
  };
58
56
  }
@@ -60,21 +58,21 @@ export class Bindings {
60
58
 
61
59
  export type BinderOptions = {
62
60
  feed: Feed.Feed;
63
- runtime: Runtime.Runtime<Feed.FeedService>;
61
+ runtime: Runtime.Runtime<Database.Service>;
64
62
  /** @effect-atom/atom-react Registry for reactive state management. */
65
63
  registry?: AtomRegistry.Registry;
66
64
  };
67
65
 
68
66
  /**
69
- * Manages bindings of blueprints and objects to a conversation.
67
+ * Manages bindings of skills and objects to a conversation.
70
68
  */
71
69
  // TODO(burdon): Context should manage ephemeral state of bindings until prompt is issued?
72
70
  export class Binder extends Resource {
73
- private readonly _blueprints = Atom.make<Blueprint.Blueprint[]>([]).pipe(Atom.keepAlive);
71
+ private readonly _skills = Atom.make<Skill.Skill[]>([]).pipe(Atom.keepAlive);
74
72
  private readonly _objects = Atom.make<Obj.Unknown[]>([]).pipe(Atom.keepAlive);
75
73
  private readonly _registry: AtomRegistry.Registry;
76
74
  private readonly _feed: Feed.Feed;
77
- private readonly _runtime: Runtime.Runtime<Feed.FeedService>;
75
+ private readonly _runtime: Runtime.Runtime<Database.Service>;
78
76
 
79
77
  #bindingsQuery: QueryResult.QueryResult<Binding> | undefined;
80
78
 
@@ -88,10 +86,10 @@ export class Binder extends Resource {
88
86
  }
89
87
 
90
88
  /**
91
- * Returns the blueprints atom for subscription.
89
+ * Returns the skills atom for subscription.
92
90
  */
93
- get blueprints(): Atom.Atom<Blueprint.Blueprint[]> {
94
- return this._blueprints;
91
+ get skills(): Atom.Atom<Skill.Skill[]> {
92
+ return this._skills;
95
93
  }
96
94
 
97
95
  /**
@@ -102,10 +100,10 @@ export class Binder extends Resource {
102
100
  }
103
101
 
104
102
  /**
105
- * Gets the current blueprints value.
103
+ * Gets the current skills value.
106
104
  */
107
- getBlueprints(): Blueprint.Blueprint[] {
108
- return this._registry.get(this._blueprints);
105
+ getSkills(): Skill.Skill[] {
106
+ return this._registry.get(this._skills);
109
107
  }
110
108
 
111
109
  /**
@@ -116,10 +114,10 @@ export class Binder extends Resource {
116
114
  }
117
115
 
118
116
  /**
119
- * Subscribe to changes in blueprints.
117
+ * Subscribe to changes in skills.
120
118
  */
121
- subscribeBlueprints(cb: (blueprints: Blueprint.Blueprint[]) => void): () => void {
122
- return this._registry.subscribe(this._blueprints, () => cb(this._registry.get(this._blueprints)));
119
+ subscribeSkills(cb: (skills: Skill.Skill[]) => void): () => void {
120
+ return this._registry.subscribe(this._skills, () => cb(this._registry.get(this._skills)));
123
121
  }
124
122
 
125
123
  /**
@@ -153,8 +151,8 @@ export class Binder extends Resource {
153
151
  log('sync', { bindingItems: results.length });
154
152
  await this._updateBindings(results);
155
153
  log('sync complete', {
156
- blueprints: this._registry.get(this._blueprints).length,
157
- blueprintKeys: this._registry.get(this._blueprints).map((bp) => Blueprint.getKey(bp)),
154
+ skills: this._registry.get(this._skills).length,
155
+ skillKeys: this._registry.get(this._skills).map((bp) => Skill.getKey(bp)),
158
156
  });
159
157
  }
160
158
  }
@@ -169,25 +167,25 @@ export class Binder extends Resource {
169
167
 
170
168
  log('_updateBindings', {
171
169
  items: items.length,
172
- blueprintRefs: [...bindings.blueprints].map((ref) => ({ uri: ref.uri, available: ref.isAvailable })),
170
+ skillRefs: [...bindings.skills].map((ref) => ({ uri: ref.uri, available: ref.isAvailable })),
173
171
  });
174
172
 
175
173
  // Resolve references (loading them first if needed).
176
- const currentBlueprints = this._registry.get(this._blueprints);
174
+ const currentSkills = this._registry.get(this._skills);
177
175
  const currentObjects = this._registry.get(this._objects);
178
- const resolvedBlueprints = await this._resolve(bindings.blueprints, currentBlueprints);
176
+ const resolvedSkills = await this._resolve(bindings.skills, currentSkills);
179
177
  const resolvedObjects = await this._resolve(bindings.objects, currentObjects);
180
178
 
181
179
  log('_updateBindings resolved', {
182
- resolvedBlueprints: resolvedBlueprints.length,
183
- resolvedBlueprintKeys: resolvedBlueprints.map((bp) => Obj.getMeta(bp).key ?? '<missing>'),
180
+ resolvedSkills: resolvedSkills.length,
181
+ resolvedSkillKeys: resolvedSkills.map((bp) => Obj.getMeta(bp).key ?? '<missing>'),
184
182
  });
185
183
 
186
- // Drop blueprints that have no registry key — they cannot be used downstream
187
- // (e.g. tool/operation registration calls Blueprint.getKey which throws).
188
- const keyedBlueprints = resolvedBlueprints.filter((bp) => {
184
+ // Drop skills that have no registry key — they cannot be used downstream
185
+ // (e.g. tool/operation registration calls Skill.getKey which throws).
186
+ const keyedSkills = resolvedSkills.filter((bp) => {
189
187
  if (Obj.getMeta(bp).key === undefined) {
190
- log.warn('dropping blueprint with no meta key', { uri: Obj.getURI(bp) });
188
+ log.warn('dropping skill with no meta key', { uri: Obj.getURI(bp) });
191
189
  return false;
192
190
  }
193
191
  return true;
@@ -195,54 +193,54 @@ export class Binder extends Resource {
195
193
 
196
194
  // Filter current state to only items still in the reduced binding set,
197
195
  // then merge in newly resolved items. This ensures unbind events are respected.
198
- const reducedBlueprintDxns = new Set<URI.URI>([...bindings.blueprints].map((ref) => ref.uri));
196
+ const reducedSkillDxns = new Set<URI.URI>([...bindings.skills].map((ref) => ref.uri));
199
197
  const reducedObjectDxns = new Set<URI.URI>([...bindings.objects].map((ref) => ref.uri));
200
- const filteredBlueprints = currentBlueprints.filter((obj) => {
198
+ const filteredSkills = currentSkills.filter((obj) => {
201
199
  const uri = Obj.getURI(obj);
202
- return uri != null && reducedBlueprintDxns.has(uri) && Obj.getMeta(obj).key !== undefined;
200
+ return uri != null && reducedSkillDxns.has(uri) && Obj.getMeta(obj).key !== undefined;
203
201
  });
204
202
  const filteredObjects = currentObjects.filter((obj) => {
205
203
  const uri = Obj.getURI(obj);
206
204
  return uri != null && reducedObjectDxns.has(uri);
207
205
  });
208
- const mergedBlueprints = this._mergeInto(filteredBlueprints, keyedBlueprints);
206
+ const mergedSkills = this._mergeInto(filteredSkills, keyedSkills);
209
207
  const mergedObjects = this._mergeInto(filteredObjects, resolvedObjects);
210
208
 
211
- this._registry.set(this._blueprints, mergedBlueprints);
209
+ this._registry.set(this._skills, mergedSkills);
212
210
  this._registry.set(this._objects, mergedObjects);
213
211
 
214
212
  log('updated bindings', {
215
- blueprints: mergedBlueprints.length,
213
+ skills: mergedSkills.length,
216
214
  objects: mergedObjects.length,
217
215
  });
218
216
  }
219
217
 
220
218
  protected override async _close(): Promise<void> {
221
219
  // Reset atoms to empty state.
222
- this._registry.set(this._blueprints, []);
220
+ this._registry.set(this._skills, []);
223
221
  this._registry.set(this._objects, []);
224
222
  }
225
223
 
226
- async bind({ blueprints, objects }: BindingProps): Promise<void> {
227
- const currentBlueprints = this._registry.get(this._blueprints);
224
+ async bind({ skills, objects }: BindingProps): Promise<void> {
225
+ const currentSkills = this._registry.get(this._skills);
228
226
  const currentObjects = this._registry.get(this._objects);
229
227
 
230
- const { added: addedBlueprints, next: nextBlueprints } = this._processBindings(blueprints, currentBlueprints);
228
+ const { added: addedSkills, next: nextSkills } = this._processBindings(skills, currentSkills);
231
229
  const { added: addedObjects, next: nextObjects } = this._processBindings(objects, currentObjects);
232
- if (!addedBlueprints.length && !addedObjects.length) {
230
+ if (!addedSkills.length && !addedObjects.length) {
233
231
  return;
234
232
  }
235
233
 
236
234
  // Atomic updates - subscribers notified automatically.
237
- this._registry.set(this._blueprints, nextBlueprints);
235
+ this._registry.set(this._skills, nextSkills);
238
236
  this._registry.set(this._objects, nextObjects);
239
237
 
240
- log('bind', { blueprints: addedBlueprints.length, objects: addedObjects.length });
238
+ log('bind', { skills: addedSkills.length, objects: addedObjects.length });
241
239
  await Runtime.runPromise(this._runtime)(
242
240
  Feed.append(this._feed, [
243
241
  Obj.make(Binding, {
244
- blueprints: {
245
- added: addedBlueprints,
242
+ skills: {
243
+ added: addedSkills,
246
244
  removed: [],
247
245
  },
248
246
  objects: {
@@ -254,19 +252,19 @@ export class Binder extends Resource {
254
252
  );
255
253
  }
256
254
 
257
- async unbind({ blueprints, objects }: BindingProps): Promise<void> {
258
- if (!blueprints?.length && !objects?.length) {
255
+ async unbind({ skills, objects }: BindingProps): Promise<void> {
256
+ if (!skills?.length && !objects?.length) {
259
257
  return;
260
258
  }
261
259
 
262
260
  // Immediately update atom state so removals are reflected before the queue round-trips.
263
- const removedBlueprintDxns = (blueprints ?? []).map((ref) => ref.uri);
261
+ const removedSkillDxns = (skills ?? []).map((ref) => ref.uri);
264
262
  const removedObjectDxns = (objects ?? []).map((ref) => ref.uri);
265
- if (removedBlueprintDxns.length > 0) {
266
- const current = this._registry.get(this._blueprints);
263
+ if (removedSkillDxns.length > 0) {
264
+ const current = this._registry.get(this._skills);
267
265
  this._registry.set(
268
- this._blueprints,
269
- current.filter((obj) => !removedBlueprintDxns.some((uri) => Obj.getURI(obj) === uri)),
266
+ this._skills,
267
+ current.filter((obj) => !removedSkillDxns.some((uri) => Obj.getURI(obj) === uri)),
270
268
  );
271
269
  }
272
270
  if (removedObjectDxns.length > 0) {
@@ -277,13 +275,13 @@ export class Binder extends Resource {
277
275
  );
278
276
  }
279
277
 
280
- log('unbind', { blueprints: blueprints?.length, objects: objects?.length });
278
+ log('unbind', { skills: skills?.length, objects: objects?.length });
281
279
  await Runtime.runPromise(this._runtime)(
282
280
  Feed.append(this._feed, [
283
281
  Obj.make(Binding, {
284
- blueprints: {
282
+ skills: {
285
283
  added: [],
286
- removed: blueprints ?? [],
284
+ removed: skills ?? [],
287
285
  },
288
286
  objects: {
289
287
  added: [],
@@ -329,14 +327,14 @@ export class Binder extends Resource {
329
327
  }
330
328
 
331
329
  /**
332
- * Reduce results into sets of blueprints and objects.
330
+ * Reduce results into sets of skills and objects.
333
331
  */
334
332
  private _reduce(items: Binding[]): Bindings {
335
333
  return Function.pipe(
336
334
  items,
337
- EArray.reduce(new Bindings(), (context, { blueprints, objects }) => {
338
- blueprints.added.forEach((ref) => context.blueprints.add(ref));
339
- blueprints.removed.forEach((ref) => context.blueprints.delete(ref));
335
+ EArray.reduce(new Bindings(), (context, { skills, objects }) => {
336
+ skills.added.forEach((ref) => context.skills.add(ref));
337
+ skills.removed.forEach((ref) => context.skills.delete(ref));
340
338
 
341
339
  objects.added.forEach((ref) => context.objects.add(ref));
342
340
  objects.removed.forEach((ref) => {
@@ -375,7 +373,7 @@ export class Binder extends Resource {
375
373
 
376
374
  /**
377
375
  * Resolve references to objects, loading them first if needed and falling back to existing objects.
378
- * DXN refs (e.g. `dxn:org.dxos.blueprint.database`) resolve via the wired-up ECHO ref resolver
376
+ * DXN refs (e.g. `dxn:org.dxos.skill.database`) resolve via the wired-up ECHO ref resolver
379
377
  * which already spans both the space DB and the hypergraph registry.
380
378
  */
381
379
  private async _resolve<T extends Obj.Unknown>(refs: Iterable<Ref.Ref<T>>, current: T[]): Promise<T[]> {
@@ -398,23 +396,3 @@ export class Binder extends Resource {
398
396
  .filter(isNonNullable);
399
397
  }
400
398
  }
401
-
402
- export class Service extends Context.Tag('@dxos/assistant/AiContextService')<
403
- Service,
404
- {
405
- binder: Binder;
406
- }
407
- >() {
408
- static bindContext = ({ blueprints, objects }: BindingProps): Effect.Effect<void, never, Service> =>
409
- Effect.gen(function* () {
410
- const { binder } = yield* Service;
411
- yield* Effect.promise(() => binder.bind({ blueprints, objects }));
412
- });
413
-
414
- static findObjects = <T extends Type.AnyObj>(type: T): Effect.Effect<Type.InstanceType<T>[], never, Service> => {
415
- return Effect.gen(function* () {
416
- const { binder } = yield* Service;
417
- return binder.getObjects().filter(Obj.instanceOf(type));
418
- });
419
- };
420
- }
@@ -27,7 +27,7 @@ describe('AiSession.Session.getHistory', () => {
27
27
  const message = makeMessage('hello');
28
28
  yield* Feed.append(feed, [message]);
29
29
 
30
- const runtime = yield* Effect.runtime<Feed.FeedService>();
30
+ const runtime = yield* Effect.runtime<Database.Service>();
31
31
  const session = new AiSession.Session({ feed, runtime });
32
32
 
33
33
  const result = yield* Effect.promise(() => session.getHistory());
@@ -51,7 +51,7 @@ describe('AiSession.Session.getHistory', () => {
51
51
  forkMsg,
52
52
  ]);
53
53
 
54
- const runtime = yield* Effect.runtime<Feed.FeedService>();
54
+ const runtime = yield* Effect.runtime<Database.Service>();
55
55
  const session = new AiSession.Session({ feed: forkFeed, runtime });
56
56
 
57
57
  const result = yield* Effect.promise(() => session.getHistory());
@@ -76,7 +76,7 @@ describe('AiSession.Session.getHistory', () => {
76
76
  Obj.make(SessionLink.SessionLink, { feedRef: Ref.make(sourceFeed), messageId: msg2.id }),
77
77
  ]);
78
78
 
79
- const runtime = yield* Effect.runtime<Feed.FeedService>();
79
+ const runtime = yield* Effect.runtime<Database.Service>();
80
80
  const session = new AiSession.Session({ feed: forkFeed, runtime });
81
81
 
82
82
  const result = yield* Effect.promise(() => session.getHistory());
@@ -100,7 +100,7 @@ describe('AiSession.Session.getHistory', () => {
100
100
  forkMsg,
101
101
  ]);
102
102
 
103
- const runtime = yield* Effect.runtime<Feed.FeedService>();
103
+ const runtime = yield* Effect.runtime<Database.Service>();
104
104
  const session = new AiSession.Session({ feed: forkFeed, runtime });
105
105
 
106
106
  const result = yield* Effect.promise(() => session.getHistory());