@dxos/assistant 0.8.4-main.7ace549 → 0.8.4-main.937b3ca

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/browser/chunk-7CDDG6LL.mjs +578 -0
  2. package/dist/lib/browser/chunk-7CDDG6LL.mjs.map +7 -0
  3. package/dist/lib/browser/extraction/index.mjs +3 -3
  4. package/dist/lib/browser/extraction/index.mjs.map +3 -3
  5. package/dist/lib/browser/index.mjs +239 -678
  6. package/dist/lib/browser/index.mjs.map +4 -4
  7. package/dist/lib/browser/meta.json +1 -1
  8. package/dist/lib/browser/testing/index.mjs +32 -0
  9. package/dist/lib/browser/testing/index.mjs.map +7 -0
  10. package/dist/lib/node-esm/chunk-CC7ER6Q3.mjs +579 -0
  11. package/dist/lib/node-esm/chunk-CC7ER6Q3.mjs.map +7 -0
  12. package/dist/lib/node-esm/extraction/index.mjs +3 -3
  13. package/dist/lib/node-esm/extraction/index.mjs.map +3 -3
  14. package/dist/lib/node-esm/index.mjs +239 -678
  15. package/dist/lib/node-esm/index.mjs.map +4 -4
  16. package/dist/lib/node-esm/meta.json +1 -1
  17. package/dist/lib/node-esm/testing/index.mjs +33 -0
  18. package/dist/lib/node-esm/testing/index.mjs.map +7 -0
  19. package/dist/types/src/conversation/context.d.ts +74 -42
  20. package/dist/types/src/conversation/context.d.ts.map +1 -1
  21. package/dist/types/src/conversation/context.test.d.ts +2 -0
  22. package/dist/types/src/conversation/context.test.d.ts.map +1 -0
  23. package/dist/types/src/conversation/conversation.d.ts +14 -14
  24. package/dist/types/src/conversation/conversation.d.ts.map +1 -1
  25. package/dist/types/src/conversation/conversation.test.d.ts +2 -0
  26. package/dist/types/src/conversation/conversation.test.d.ts.map +1 -0
  27. package/dist/types/src/errors.d.ts +12 -16
  28. package/dist/types/src/errors.d.ts.map +1 -1
  29. package/dist/types/src/extraction/extraction-ner-function/extraction-ner-function.d.ts +179 -178
  30. package/dist/types/src/extraction/extraction-ner-function/extraction-ner-function.d.ts.map +1 -1
  31. package/dist/types/src/extraction/extraction.d.ts +285 -241
  32. package/dist/types/src/extraction/extraction.d.ts.map +1 -1
  33. package/dist/types/src/extraction/quotes.d.ts +2 -2
  34. package/dist/types/src/extraction/quotes.d.ts.map +1 -1
  35. package/dist/types/src/functions/services.d.ts +3 -3
  36. package/dist/types/src/functions/services.d.ts.map +1 -1
  37. package/dist/types/src/functions.test.d.ts +2 -0
  38. package/dist/types/src/functions.test.d.ts.map +1 -0
  39. package/dist/types/src/session/GenericToolkit.d.ts +1 -0
  40. package/dist/types/src/session/GenericToolkit.d.ts.map +1 -1
  41. package/dist/types/src/session/format.d.ts +3 -3
  42. package/dist/types/src/session/format.d.ts.map +1 -1
  43. package/dist/types/src/session/observer.d.ts +4 -3
  44. package/dist/types/src/session/observer.d.ts.map +1 -1
  45. package/dist/types/src/session/session.d.ts +14 -9
  46. package/dist/types/src/session/session.d.ts.map +1 -1
  47. package/dist/types/src/session/toolkit.d.ts +5 -6
  48. package/dist/types/src/session/toolkit.d.ts.map +1 -1
  49. package/dist/types/src/session/version-pin.d.ts +1 -1
  50. package/dist/types/src/session/version-pin.d.ts.map +1 -1
  51. package/dist/types/src/testing/index.d.ts +2 -0
  52. package/dist/types/src/testing/index.d.ts.map +1 -0
  53. package/dist/types/src/testing/layer.d.ts +21 -0
  54. package/dist/types/src/testing/layer.d.ts.map +1 -0
  55. package/dist/types/src/types/artifact.d.ts +12 -3
  56. package/dist/types/src/types/artifact.d.ts.map +1 -1
  57. package/dist/types/tsconfig.tsbuildinfo +1 -1
  58. package/package.json +38 -29
  59. package/src/conversation/context.test.ts +46 -0
  60. package/src/conversation/context.ts +183 -65
  61. package/src/conversation/conversation.test.ts +65 -0
  62. package/src/conversation/conversation.ts +46 -49
  63. package/src/diff.test.ts +1 -1
  64. package/src/errors.ts +2 -2
  65. package/src/execution-graph.ts +2 -2
  66. package/src/extraction/extraction-ner-function/extraction-ner-function.test.ts +3 -3
  67. package/src/extraction/extraction-ner-function/extraction-ner-function.ts +1 -1
  68. package/src/extraction/extraction.ts +3 -3
  69. package/src/extraction/quotes.ts +3 -4
  70. package/src/functions/services.ts +28 -10
  71. package/src/functions.conversations.json +1 -0
  72. package/src/functions.test.ts +74 -0
  73. package/src/session/GenericToolkit.ts +1 -0
  74. package/src/session/format.test.ts +101 -38
  75. package/src/session/format.ts +11 -12
  76. package/src/session/observer.ts +3 -1
  77. package/src/session/session.conversations.json +1 -1
  78. package/src/session/session.test.ts +7 -13
  79. package/src/session/session.ts +33 -12
  80. package/src/session/toolkit.ts +13 -22
  81. package/src/session/version-pin.ts +2 -2
  82. package/src/testing/index.ts +5 -0
  83. package/src/testing/layer.ts +78 -0
  84. package/src/types/artifact.ts +18 -6
@@ -0,0 +1,579 @@
1
+ import { createRequire } from 'node:module';const require = createRequire(import.meta.url);
2
+ import {
3
+ __export
4
+ } from "./chunk-HSLMI22Q.mjs";
5
+
6
+ // src/session/artifact-diff.ts
7
+ import * as Context from "effect/Context";
8
+ var ArtifactDiffResolver = class extends Context.Tag("@dxos/assistant/ArtifactDiffResolver")() {
9
+ };
10
+
11
+ // src/session/observer.ts
12
+ import * as Effect from "effect/Effect";
13
+ import * as Function from "effect/Function";
14
+ var GenerationObserver = Object.freeze({
15
+ make: ({ onBegin = Function.constant(Effect.void), onPart = Function.constant(Effect.void), onBlock = Function.constant(Effect.void), onEnd = Function.constant(Effect.void), onMessage = Function.constant(Effect.void) } = {}) => ({
16
+ onBegin,
17
+ onPart,
18
+ onBlock,
19
+ onEnd,
20
+ onMessage
21
+ }),
22
+ noop: () => GenerationObserver.make(),
23
+ /**
24
+ * Debug printer to be used in unit-tests and browser devtools.
25
+ */
26
+ fromPrinter: (printer) => GenerationObserver.make({
27
+ onBlock: (block) => Effect.sync(() => {
28
+ if (block.pending) {
29
+ return;
30
+ }
31
+ printer.printContentBlock(block);
32
+ }),
33
+ onMessage: (message) => Effect.sync(() => {
34
+ if (message.sender.role === "assistant") {
35
+ return;
36
+ }
37
+ printer.printMessage(message);
38
+ })
39
+ })
40
+ });
41
+
42
+ // src/errors.ts
43
+ import { BaseError } from "@dxos/errors";
44
+ var AiModelError = class extends BaseError.extend("AiModelError", "AI model error") {
45
+ };
46
+ var AiAssistantError = class extends BaseError.extend("AiAssistantError", "AI assistant error") {
47
+ };
48
+
49
+ // src/session/session.ts
50
+ import * as LanguageModel from "@effect/ai/LanguageModel";
51
+ import * as Chunk from "effect/Chunk";
52
+ import * as Effect3 from "effect/Effect";
53
+ import * as Stream from "effect/Stream";
54
+ import { AiParser, AiPreprocessor, callTool, getToolCalls } from "@dxos/ai";
55
+ import { todo } from "@dxos/debug";
56
+ import { Obj as Obj2 } from "@dxos/echo";
57
+ import { TracingService } from "@dxos/functions";
58
+ import { log as log2 } from "@dxos/log";
59
+ import { Message as Message2 } from "@dxos/types";
60
+
61
+ // src/session/format.ts
62
+ import * as Effect2 from "effect/Effect";
63
+ import * as Function2 from "effect/Function";
64
+ import * as Option from "effect/Option";
65
+ import { Template } from "@dxos/blueprints";
66
+ import { Obj } from "@dxos/echo";
67
+ import { ObjectVersion } from "@dxos/echo-db";
68
+ import { log } from "@dxos/log";
69
+ import { Message } from "@dxos/types";
70
+ import { trim } from "@dxos/util";
71
+ var __dxlog_file = "/__w/dxos/dxos/packages/core/assistant/src/session/format.ts";
72
+ var formatSystemPrompt = ({ system, blueprints = [], objects = [] }) => Effect2.gen(function* () {
73
+ const blueprintDefs = yield* Function2.pipe(blueprints, Effect2.forEach((blueprint) => Effect2.succeed(blueprint.instructions)), Effect2.flatMap(Effect2.forEach((template) => Effect2.gen(function* () {
74
+ return trim`
75
+ <blueprint>
76
+ ${yield* Template.processTemplate(template)}
77
+ </blueprint>
78
+ `;
79
+ }))), Effect2.map((blueprints2) => blueprints2.length > 0 ? [
80
+ "## Blueprints Definitions",
81
+ ...blueprints2
82
+ ].join("\n\n") : void 0));
83
+ const objectDefs = yield* Function2.pipe(objects, Effect2.forEach((object) => Effect2.succeed(trim`
84
+ <object>
85
+ <dxn>${Obj.getDXN(object)}</dxn>
86
+ <typename>${Obj.getTypename(object)}</typename>
87
+ </object>
88
+ `)), Effect2.map((objects2) => objects2.length > 0 ? [
89
+ "## Context Objects",
90
+ ...objects2
91
+ ].join("\n\n") : void 0));
92
+ return yield* Function2.pipe(Effect2.succeed([
93
+ system,
94
+ blueprintDefs,
95
+ objectDefs
96
+ ].filter((def) => def !== void 0)), Effect2.map((parts) => parts.join("\n\n")));
97
+ });
98
+ var formatUserPrompt = ({ prompt, history = [] }) => Effect2.gen(function* () {
99
+ const blocks = [];
100
+ const artifactDiffResolver = yield* Effect2.serviceOption(ArtifactDiffResolver);
101
+ if (Option.isSome(artifactDiffResolver)) {
102
+ const versions = gatherObjectVersions(history);
103
+ const artifactDiff = yield* Effect2.tryPromise({
104
+ try: () => artifactDiffResolver.value.resolve([
105
+ ...versions.entries()
106
+ ].map(([id, version]) => ({
107
+ id,
108
+ lastVersion: version
109
+ }))),
110
+ catch: AiAssistantError.wrap({
111
+ message: "Artifact diff resolution error"
112
+ })
113
+ });
114
+ log("version", {
115
+ artifactDiff,
116
+ versions
117
+ }, {
118
+ F: __dxlog_file,
119
+ L: 94,
120
+ S: this,
121
+ C: (f, a) => f(...a)
122
+ });
123
+ for (const [id, { version }] of [
124
+ ...artifactDiff.entries()
125
+ ]) {
126
+ if (ObjectVersion.equals(version, versions.get(id))) {
127
+ artifactDiff.delete(id);
128
+ continue;
129
+ }
130
+ blocks.push({
131
+ _tag: "anchor",
132
+ objectId: id,
133
+ version
134
+ });
135
+ }
136
+ if (artifactDiff.size > 0) {
137
+ blocks.push(createArtifactUpdateBlock(artifactDiff));
138
+ }
139
+ }
140
+ return Obj.make(Message.Message, {
141
+ created: (/* @__PURE__ */ new Date()).toISOString(),
142
+ sender: {
143
+ role: "user"
144
+ },
145
+ blocks: [
146
+ ...blocks,
147
+ {
148
+ _tag: "text",
149
+ text: prompt
150
+ }
151
+ ]
152
+ });
153
+ });
154
+ var gatherObjectVersions = (messages) => {
155
+ const artifactIds = /* @__PURE__ */ new Map();
156
+ for (const message of messages) {
157
+ for (const block of message.blocks) {
158
+ if (block._tag === "anchor") {
159
+ artifactIds.set(block.objectId, block.version);
160
+ }
161
+ }
162
+ }
163
+ return artifactIds;
164
+ };
165
+ var createArtifactUpdateBlock = (artifactDiff) => {
166
+ return {
167
+ _tag: "text",
168
+ // TODO(dmaretskyi): Does this need to be a special content-block?
169
+ disposition: "artifact-update",
170
+ text: trim`
171
+ The following artifacts have been updated since the last message:
172
+ ${[
173
+ ...artifactDiff.entries()
174
+ ].map(([id, { diff }]) => `<changed-artifact id="${id}">${diff ? `
175
+ ${diff}` : ""}</changed-artifact>`).join("\n")}
176
+ `
177
+ };
178
+ };
179
+
180
+ // src/session/session.ts
181
+ var __dxlog_file2 = "/__w/dxos/dxos/packages/core/assistant/src/session/session.ts";
182
+ var AiSession = class {
183
+ _options;
184
+ /** Prevents concurrent execution of session. */
185
+ _semaphore = Effect3.runSync(Effect3.makeSemaphore(1));
186
+ /** Message history from queue. */
187
+ // TODO(burdon): Evolve into supporting a git-like graph of messages.
188
+ _history = [];
189
+ /** Pending messages for this session (incl. the current prompt). */
190
+ _pending = [];
191
+ _started = 0;
192
+ _ended = 0;
193
+ _toolCalls = 0;
194
+ constructor(_options = {}) {
195
+ this._options = _options;
196
+ }
197
+ get duration() {
198
+ return this._ended - this._started;
199
+ }
200
+ get toolCalls() {
201
+ return this._toolCalls;
202
+ }
203
+ run = ({ prompt, system: systemTemplate, history = [], objects = [], blueprints = [], toolkit, observer = GenerationObserver.noop() }) => Effect3.gen(this, function* () {
204
+ this._started = Date.now();
205
+ this._history = [
206
+ ...history
207
+ ];
208
+ this._pending = [];
209
+ const pending = this._pending;
210
+ const submitMessage = Effect3.fnUntraced(function* (message) {
211
+ pending.push(message);
212
+ yield* observer.onMessage(message);
213
+ yield* TracingService.emitConverationMessage(message);
214
+ return message;
215
+ });
216
+ const promptMessage = yield* submitMessage(yield* formatUserPrompt({
217
+ prompt,
218
+ history
219
+ }));
220
+ const system = yield* formatSystemPrompt({
221
+ system: systemTemplate,
222
+ blueprints,
223
+ objects
224
+ }).pipe(Effect3.orDie);
225
+ do {
226
+ log2("request", {
227
+ prompt: promptMessage,
228
+ system: {
229
+ snippet: createSnippet(system),
230
+ length: system.length
231
+ },
232
+ pending: this._pending.length,
233
+ history: this._history.length,
234
+ objects: objects?.length ?? 0
235
+ }, {
236
+ F: __dxlog_file2,
237
+ L: 126,
238
+ S: this,
239
+ C: (f, a) => f(...a)
240
+ });
241
+ const prompt2 = yield* AiPreprocessor.preprocessPrompt([
242
+ ...this._history,
243
+ ...this._pending
244
+ ], {
245
+ system
246
+ });
247
+ const blocks = yield* LanguageModel.streamText({
248
+ prompt: prompt2,
249
+ toolkit,
250
+ disableToolCallResolution: true
251
+ }).pipe(
252
+ // TOOD(dmaretskyi): Error mapping.
253
+ AiParser.parseResponse({
254
+ onBegin: () => observer.onBegin(),
255
+ onBlock: (block) => observer.onBlock(block),
256
+ onPart: (part) => observer.onPart(part),
257
+ onEnd: (summary) => observer.onEnd(summary)
258
+ }),
259
+ Stream.runCollect,
260
+ Effect3.map(Chunk.toArray)
261
+ );
262
+ const response = yield* submitMessage(Obj2.make(Message2.Message, {
263
+ created: (/* @__PURE__ */ new Date()).toISOString(),
264
+ sender: {
265
+ role: "assistant"
266
+ },
267
+ blocks
268
+ }));
269
+ const toolCalls = getToolCalls(response);
270
+ if (toolCalls.length === 0) {
271
+ break;
272
+ } else if (!toolkit) {
273
+ throw new Error("No toolkit provided");
274
+ }
275
+ const toolResults = yield* Effect3.forEach(toolCalls, (toolCall) => {
276
+ return callTool(toolkit, toolCall).pipe(Effect3.provide(TracingService.layerSubframe((context) => ({
277
+ ...context,
278
+ parentMessage: response.id,
279
+ toolCallId: toolCall.toolCallId
280
+ }))));
281
+ });
282
+ yield* submitMessage(Obj2.make(Message2.Message, {
283
+ created: (/* @__PURE__ */ new Date()).toISOString(),
284
+ sender: {
285
+ role: "tool"
286
+ },
287
+ blocks: toolResults
288
+ }));
289
+ this._toolCalls++;
290
+ } while (true);
291
+ this._ended = Date.now();
292
+ log2("done", {
293
+ pending: this._pending.length,
294
+ duration: this.duration,
295
+ tools: this._toolCalls
296
+ }, {
297
+ F: __dxlog_file2,
298
+ L: 202,
299
+ S: this,
300
+ C: (f, a) => f(...a)
301
+ });
302
+ return this._pending;
303
+ }).pipe(this._semaphore.withPermits(1), Effect3.withSpan("AiSession.run"));
304
+ /**
305
+ * @deprecated
306
+ */
307
+ // TODO(burdon): Implement or remove.
308
+ async runStructured(_schema, _options) {
309
+ return todo();
310
+ }
311
+ };
312
+ var createSnippet = (text, len = 32) => text.length <= len * 2 ? text : [
313
+ text.slice(0, len),
314
+ "...",
315
+ text.slice(-len)
316
+ ].join("");
317
+
318
+ // src/session/toolkit.ts
319
+ import * as Toolkit from "@effect/ai/Toolkit";
320
+ import * as Effect4 from "effect/Effect";
321
+ import { ToolExecutionService, ToolResolverService } from "@dxos/ai";
322
+ import { isTruthy } from "@dxos/util";
323
+ var createToolkit = ({ toolkit: toolkitProp, blueprints = [] }) => Effect4.gen(function* () {
324
+ const blueprintToolkit = yield* ToolResolverService.resolveToolkit(blueprints.flatMap(({ tools }) => tools));
325
+ const blueprintToolHandler = yield* blueprintToolkit.toContext(ToolExecutionService.handlersFor(blueprintToolkit));
326
+ const toolkit = Toolkit.merge(...[
327
+ toolkitProp,
328
+ blueprintToolkit
329
+ ].filter(isTruthy));
330
+ return yield* toolkit.pipe(Effect4.provide(blueprintToolHandler));
331
+ });
332
+
333
+ // src/session/version-pin.ts
334
+ import * as Schema from "effect/Schema";
335
+ import { getVersion } from "@dxos/echo-db";
336
+ import { ObjectId } from "@dxos/keys";
337
+ var ObjectVersionSchema = Schema.Unknown;
338
+ var VersionPinSchema = Schema.Struct({
339
+ // TODO(dmaretskyi): Use Ref when those support encoding.
340
+ objectId: ObjectId,
341
+ // TODO(dmaretskyi): Could be opaque.
342
+ version: ObjectVersionSchema
343
+ });
344
+ var VersionPin = class extends VersionPinSchema {
345
+ static DISPOSITION = "version-pin";
346
+ static fromObject(object) {
347
+ return VersionPin.make({
348
+ objectId: object.id,
349
+ version: getVersion(object)
350
+ });
351
+ }
352
+ static createBlock(pin) {
353
+ return {
354
+ _tag: "json",
355
+ disposition: VersionPin.DISPOSITION,
356
+ data: JSON.stringify(pin)
357
+ };
358
+ }
359
+ };
360
+
361
+ // src/session/GenericToolkit.ts
362
+ var GenericToolkit_exports = {};
363
+ __export(GenericToolkit_exports, {
364
+ TypeId: () => TypeId,
365
+ make: () => make,
366
+ merge: () => merge3
367
+ });
368
+ import * as Toolkit2 from "@effect/ai/Toolkit";
369
+ import * as Effect5 from "effect/Effect";
370
+ import * as Layer from "effect/Layer";
371
+ import * as Pipeable from "effect/Pipeable";
372
+ var TypeId = "~@dxos/assistant/GenericToolkit";
373
+ var make = (toolkit, layer) => {
374
+ return {
375
+ [TypeId]: TypeId,
376
+ toolkit,
377
+ layer,
378
+ handlers: toolkit.pipe(Effect5.provide(layer)),
379
+ pipe() {
380
+ return Pipeable.pipeArguments(this, arguments);
381
+ }
382
+ };
383
+ };
384
+ var merge3 = (...toolkits) => {
385
+ return make(Toolkit2.merge(...toolkits.map((t) => t.toolkit)), Layer.mergeAll(...toolkits.map((t) => t.layer)));
386
+ };
387
+
388
+ // src/types/artifact.ts
389
+ import * as Schema2 from "effect/Schema";
390
+ import { Type } from "@dxos/echo";
391
+ import { Database } from "@dxos/echo";
392
+ import { EncodedReference } from "@dxos/echo-protocol";
393
+ import { DXN, LOCAL_SPACE_TAG } from "@dxos/keys";
394
+ import { trim as trim2 } from "@dxos/util";
395
+ var createArtifactElement = (id) => `<artifact id=${id} />`;
396
+ var ArtifactId = class extends Schema2.String.annotations({
397
+ // TODO(dmaretskyi): This section gets overriden.
398
+ description: trim2`
399
+ The ID of the referenced object. Formats accepted:
400
+ - DXN (dxn:echo:@:XXXXX). DXNs can be prepended with an @ symbol for compatibility with in-text references.
401
+ - space ID, object ID tuple (spaceID:objectID)
402
+ - Only object ID that is assumed to be in the current space (XXXXX)
403
+ `,
404
+ examples: [
405
+ "dxn:echo:@:XXXXX",
406
+ "@dxn:echo:@:XXXXX",
407
+ "spaceID:objectID",
408
+ "XXXXX"
409
+ ]
410
+ }) {
411
+ static toDXN(reference, owningSpaceId) {
412
+ if (reference.startsWith("@dxn:")) {
413
+ return DXN.parse(reference.slice(1));
414
+ } else if (reference.startsWith("dxn:")) {
415
+ return DXN.parse(reference);
416
+ } else if (/^[A-Z0-9]+:[A-Z0-9]+$/.test(reference)) {
417
+ const [spaceId, objectId] = reference.split(":");
418
+ return new DXN(DXN.kind.ECHO, [
419
+ spaceId === owningSpaceId ? LOCAL_SPACE_TAG : spaceId,
420
+ objectId
421
+ ]);
422
+ } else if (/^[A-Z0-9]+$/.test(reference)) {
423
+ return DXN.fromLocalObjectId(reference);
424
+ } else {
425
+ throw new Error(`Unable to parse object reference: ${reference}`);
426
+ }
427
+ }
428
+ /**
429
+ * Resolves an artifact ID to an object.
430
+ */
431
+ static resolve(schema, ref) {
432
+ const dxn = ArtifactId.toDXN(ref);
433
+ return Database.Service.resolve(dxn, schema);
434
+ }
435
+ };
436
+ var RefFromLLM = Schema2.transform(ArtifactId, Type.Ref(Type.Obj), {
437
+ decode: (fromA, fromI) => EncodedReference.fromDXN(ArtifactId.toDXN(fromA)),
438
+ encode: (toI, toA) => EncodedReference.toDXN(toI).toString(),
439
+ strict: false
440
+ });
441
+
442
+ // src/functions/services.ts
443
+ import * as Tool from "@effect/ai/Tool";
444
+ import * as Context2 from "effect/Context";
445
+ import * as Effect6 from "effect/Effect";
446
+ import * as Layer2 from "effect/Layer";
447
+ import * as Record from "effect/Record";
448
+ import * as Schema3 from "effect/Schema";
449
+ import { AiToolNotFoundError, ToolExecutionService as ToolExecutionService2, ToolResolverService as ToolResolverService2 } from "@dxos/ai";
450
+ import { todo as todo2 } from "@dxos/debug";
451
+ import { Query, Type as Type2 } from "@dxos/echo";
452
+ import { Database as Database2 } from "@dxos/echo";
453
+ import { Function as Function3, FunctionDefinition, FunctionInvocationService } from "@dxos/functions";
454
+ import { invariant } from "@dxos/invariant";
455
+ var __dxlog_file3 = "/__w/dxos/dxos/packages/core/assistant/src/functions/services.ts";
456
+ var makeToolResolverFromFunctions = (functions, toolkit) => {
457
+ return Layer2.effect(ToolResolverService2, Effect6.gen(function* () {
458
+ const dbService = yield* Database2.Service;
459
+ return {
460
+ resolve: (id) => Effect6.gen(function* () {
461
+ const tool = toolkit.tools[id];
462
+ if (tool) {
463
+ return tool;
464
+ }
465
+ const [dbFunction] = yield* Database2.Service.runQuery(Query.type(Function3.Function, {
466
+ key: id
467
+ }));
468
+ const functionDef = dbFunction ? FunctionDefinition.deserialize(dbFunction) : functions.find((fn2) => fn2.key === id);
469
+ if (!functionDef) {
470
+ return yield* Effect6.fail(new AiToolNotFoundError(id));
471
+ }
472
+ return projectFunctionToTool(functionDef);
473
+ }).pipe(Effect6.provideService(Database2.Service, dbService))
474
+ };
475
+ }));
476
+ };
477
+ var makeToolExecutionServiceFromFunctions = (toolkit, handlersLayer) => {
478
+ return Layer2.effect(ToolExecutionService2, Effect6.gen(function* () {
479
+ const toolkitHandler = yield* toolkit.pipe(Effect6.provide(handlersLayer));
480
+ invariant(isHandlerLike(toolkitHandler), void 0, {
481
+ F: __dxlog_file3,
482
+ L: 77,
483
+ S: this,
484
+ A: [
485
+ "isHandlerLike(toolkitHandler)",
486
+ ""
487
+ ]
488
+ });
489
+ const functionInvocationService = yield* FunctionInvocationService;
490
+ return {
491
+ handlersFor: (toolkit2) => {
492
+ const makeHandler = (tool) => {
493
+ return Effect6.fn(`toolFunctionHandler ${tool.name}`)(function* (input) {
494
+ if (toolkitHandler.tools[tool.name]) {
495
+ if (Tool.isProviderDefined(tool)) {
496
+ throw new Error("Attempted to call a provider-defined tool");
497
+ }
498
+ const { result } = yield* toolkitHandler.handle(tool.name, input);
499
+ return result;
500
+ }
501
+ const { definition: functionDef } = Context2.get(FunctionToolAnnotation)(tool.annotations);
502
+ return yield* functionInvocationService.invokeFunction(functionDef, input).pipe(Effect6.catchAllDefect((defect) => Effect6.fail(defect)));
503
+ });
504
+ };
505
+ return toolkit2.of(Record.map(toolkit2.tools, (tool, _name) => Tool.isUserDefined(tool) ? makeHandler(tool) : null));
506
+ }
507
+ };
508
+ }));
509
+ };
510
+ var FunctionToolAnnotation = class extends Context2.Tag("@dxos/assistant/FunctionToolAnnotation")() {
511
+ };
512
+ var toolCache = /* @__PURE__ */ new WeakMap();
513
+ var projectFunctionToTool = (fn2) => {
514
+ if (toolCache.has(fn2)) {
515
+ return toolCache.get(fn2);
516
+ }
517
+ const tool = Tool.make(makeToolName(fn2.name), {
518
+ description: fn2.description,
519
+ parameters: createStructFieldsFromSchema(fn2.inputSchema),
520
+ // TODO(dmaretskyi): Include output schema.
521
+ failure: Schema3.Any
522
+ }).annotate(FunctionToolAnnotation, {
523
+ definition: fn2
524
+ });
525
+ toolCache.set(fn2, tool);
526
+ return tool;
527
+ };
528
+ var makeToolName = (name) => {
529
+ const toolName = name.toLowerCase().replace(/[^a-zA-Z0-9]/g, "-");
530
+ invariant(toolName.match(/^[a-z_][a-z0-9-_]*$/), void 0, {
531
+ F: __dxlog_file3,
532
+ L: 148,
533
+ S: void 0,
534
+ A: [
535
+ "toolName.match(/^[a-z_][a-z0-9-_]*$/)",
536
+ ""
537
+ ]
538
+ });
539
+ return toolName;
540
+ };
541
+ var createStructFieldsFromSchema = (schema) => {
542
+ switch (schema.ast._tag) {
543
+ case "TypeLiteral":
544
+ return Object.fromEntries(schema.ast.propertySignatures.map((prop) => [
545
+ prop.name,
546
+ Schema3.make(mapSchemaTypeForLLM(prop.type))
547
+ ]));
548
+ case "VoidKeyword":
549
+ return {};
550
+ default:
551
+ return todo2(`Unsupported schema AST: ${schema.ast._tag}`);
552
+ }
553
+ };
554
+ var mapSchemaTypeForLLM = (ast) => {
555
+ if (Type2.Ref.isRefSchemaAST(ast)) {
556
+ return RefFromLLM.ast;
557
+ }
558
+ return ast;
559
+ };
560
+ var isHandlerLike = (value) => {
561
+ return typeof value.tools === "object" && typeof value.handle === "function";
562
+ };
563
+
564
+ export {
565
+ ArtifactDiffResolver,
566
+ GenerationObserver,
567
+ AiModelError,
568
+ AiAssistantError,
569
+ AiSession,
570
+ createToolkit,
571
+ VersionPin,
572
+ GenericToolkit_exports,
573
+ createArtifactElement,
574
+ ArtifactId,
575
+ RefFromLLM,
576
+ makeToolResolverFromFunctions,
577
+ makeToolExecutionServiceFromFunctions
578
+ };
579
+ //# sourceMappingURL=chunk-CC7ER6Q3.mjs.map