@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
@@ -2,6 +2,7 @@
2
2
  // Copyright 2025 DXOS.org
3
3
  //
4
4
 
5
+ import type * as Tool from '@effect/ai/Tool';
5
6
  import * as Effect from 'effect/Effect';
6
7
  import * as Function from 'effect/Function';
7
8
 
@@ -11,7 +12,8 @@ import { type Message } from '@dxos/types';
11
12
  /**
12
13
  * Live observer of the generation process.
13
14
  */
14
- export interface GenerationObserver extends AiParser.ParseResponseCallbacks {
15
+ export interface GenerationObserver<Tools extends Record<string, Tool.Any> = any>
16
+ extends AiParser.ParseResponseCallbacks<Tools> {
15
17
  /**
16
18
  * Complete messages fired during the session, both from the model and from the user.
17
19
  * This message will contain all message blocks emitted through the `onBlock` callback.
@@ -1 +1 @@
1
- {"conversations":[{"parameters":{"model":"@anthropic/claude-3-5-sonnet-20241022","stream":true,"tools":[]},"prompt":{"content":[{"role":"user","content":"Hello world!","options":{}}]},"response":[{"type":"response-metadata","id":"msg_01Bm496JGgDMgC9YwdYTFFHo","modelId":"claude-3-5-sonnet-20241022","timestamp":"1970-01-01T00:00:00.000Z","metadata":{}},{"type":"text-start","id":"0","metadata":{}},{"type":"text-delta","id":"0","delta":"Hi","metadata":{}},{"type":"text-delta","id":"0","delta":"!","metadata":{}},{"type":"text-delta","id":"0","delta":" How can","metadata":{}},{"type":"text-delta","id":"0","delta":" I help you today?","metadata":{}},{"type":"text-end","id":"0","metadata":{}},{"type":"finish","reason":"stop","usage":{"inputTokens":10,"outputTokens":12,"totalTokens":22},"metadata":{"anthropic":{"usage":{"cache_creation":{"ephemeral_1h_input_tokens":0,"ephemeral_5m_input_tokens":0},"cache_creation_input_tokens":0,"cache_read_input_tokens":0,"input_tokens":10,"output_tokens":1,"server_tool_use":null,"service_tier":"standard"}}}}]},{"parameters":{"model":"@anthropic/claude-3-5-sonnet-20241022","stream":true,"tools":[{"name":"Calculator","description":"Basic calculator tool","inputSchema":{"type":"object","required":["input"],"properties":{"input":{"type":"string","description":"The calculation to perform."}},"additionalProperties":false}}]},"prompt":{"content":[{"role":"user","content":"What is 10 + 30?","options":{}}]},"response":[{"type":"response-metadata","id":"msg_01UNTbjtTHEpdFgGunu2k8Br","modelId":"claude-3-5-sonnet-20241022","timestamp":"1970-01-01T00:00:00.000Z","metadata":{}},{"type":"text-start","id":"0","metadata":{}},{"type":"text-delta","id":"0","delta":"I","metadata":{}},{"type":"text-delta","id":"0","delta":"'ll help","metadata":{}},{"type":"text-delta","id":"0","delta":" you calculate","metadata":{}},{"type":"text-delta","id":"0","delta":" ","metadata":{}},{"type":"text-delta","id":"0","delta":"10 + 30","metadata":{}},{"type":"text-delta","id":"0","delta":" using the","metadata":{}},{"type":"text-delta","id":"0","delta":" Calculator tool.","metadata":{}},{"type":"text-end","id":"0","metadata":{}},{"type":"tool-params-start","id":"toolu_01LTGUgfihCQtVchm1b37xHQ","name":"Calculator","providerExecuted":false,"metadata":{}},{"type":"tool-params-delta","id":"toolu_01LTGUgfihCQtVchm1b37xHQ","delta":"","metadata":{}},{"type":"tool-params-delta","id":"toolu_01LTGUgfihCQtVchm1b37xHQ","delta":"{\"input\": \"","metadata":{}},{"type":"tool-params-delta","id":"toolu_01LTGUgfihCQtVchm1b37xHQ","delta":"10 + 30","metadata":{}},{"type":"tool-params-delta","id":"toolu_01LTGUgfihCQtVchm1b37xHQ","delta":"\"}","metadata":{}},{"type":"tool-params-end","id":"toolu_01LTGUgfihCQtVchm1b37xHQ","metadata":{}},{"type":"tool-call","id":"toolu_01LTGUgfihCQtVchm1b37xHQ","name":"Calculator","params":{"input":"10 + 30"},"providerExecuted":false,"metadata":{}},{"type":"finish","reason":"tool-calls","usage":{"inputTokens":394,"outputTokens":73,"totalTokens":467},"metadata":{"anthropic":{"usage":{"cache_creation":{"ephemeral_1h_input_tokens":0,"ephemeral_5m_input_tokens":0},"cache_creation_input_tokens":0,"cache_read_input_tokens":0,"input_tokens":394,"output_tokens":1,"server_tool_use":null,"service_tier":"standard"}}}}]},{"parameters":{"model":"@anthropic/claude-3-5-sonnet-20241022","stream":true,"tools":[{"name":"Calculator","description":"Basic calculator tool","inputSchema":{"type":"object","required":["input"],"properties":{"input":{"type":"string","description":"The calculation to perform."}},"additionalProperties":false}}]},"prompt":{"content":[{"role":"user","content":"What is 10 + 30?","options":{}},{"role":"assistant","content":[{"type":"text","text":"I'll help you calculate 10 + 30 using the Calculator tool.","options":{}},{"type":"tool-call","id":"toolu_01LTGUgfihCQtVchm1b37xHQ","name":"Calculator","params":{"input":"10 + 30"},"providerExecuted":false,"options":{}}],"options":{}},{"role":"tool","content":[{"type":"tool-result","id":"toolu_01LTGUgfihCQtVchm1b37xHQ","name":"Calculator","result":{"result":40},"options":{}}],"options":{}}]},"response":[{"type":"response-metadata","id":"msg_01AKio3GheJGn38BhvAp33rs","modelId":"claude-3-5-sonnet-20241022","timestamp":"1970-01-01T00:00:00.000Z","metadata":{}},{"type":"text-start","id":"0","metadata":{}},{"type":"text-delta","id":"0","delta":"The result","metadata":{}},{"type":"text-delta","id":"0","delta":" of 10 +","metadata":{}},{"type":"text-delta","id":"0","delta":" 30 is ","metadata":{}},{"type":"text-delta","id":"0","delta":"40.","metadata":{}},{"type":"text-end","id":"0","metadata":{}},{"type":"finish","reason":"stop","usage":{"inputTokens":482,"outputTokens":18,"totalTokens":500},"metadata":{"anthropic":{"usage":{"cache_creation":{"ephemeral_1h_input_tokens":0,"ephemeral_5m_input_tokens":0},"cache_creation_input_tokens":0,"cache_read_input_tokens":0,"input_tokens":482,"output_tokens":3,"server_tool_use":null,"service_tier":"standard"}}}}]}]}
1
+ {"conversations":[{"parameters":{"model":"@anthropic/claude-3-5-sonnet-20241022","stream":true,"tools":[]},"prompt":{"content":[{"role":"user","content":"Hello world!","options":{}}]},"response":[{"type":"response-metadata","id":"msg_01Bm496JGgDMgC9YwdYTFFHo","modelId":"claude-3-5-sonnet-20241022","timestamp":"1970-01-01T00:00:00.000Z","metadata":{}},{"type":"text-start","id":"0","metadata":{}},{"type":"text-delta","id":"0","delta":"Hi","metadata":{}},{"type":"text-delta","id":"0","delta":"!","metadata":{}},{"type":"text-delta","id":"0","delta":" How can","metadata":{}},{"type":"text-delta","id":"0","delta":" I help you today?","metadata":{}},{"type":"text-end","id":"0","metadata":{}},{"type":"finish","reason":"stop","usage":{"inputTokens":10,"outputTokens":12,"totalTokens":22},"metadata":{"anthropic":{"usage":{"cache_creation":{"ephemeral_1h_input_tokens":0,"ephemeral_5m_input_tokens":0},"cache_creation_input_tokens":0,"cache_read_input_tokens":0,"input_tokens":10,"output_tokens":1,"server_tool_use":null,"service_tier":"standard"}}}}]},{"parameters":{"model":"@anthropic/claude-3-5-sonnet-20241022","stream":true,"tools":[{"name":"Calculator","description":"Basic calculator tool","inputSchema":{"type":"object","required":["input"],"properties":{"input":{"type":"string","description":"The calculation to perform."}},"additionalProperties":false}}]},"prompt":{"content":[{"role":"user","content":"What is 10 + 30?","options":{}}]},"response":[{"type":"response-metadata","id":"msg_01UNTbjtTHEpdFgGunu2k8Br","modelId":"claude-3-5-sonnet-20241022","timestamp":"1970-01-01T00:00:00.000Z","metadata":{}},{"type":"text-start","id":"0","metadata":{}},{"type":"text-delta","id":"0","delta":"I","metadata":{}},{"type":"text-delta","id":"0","delta":"'ll help","metadata":{}},{"type":"text-delta","id":"0","delta":" you calculate","metadata":{}},{"type":"text-delta","id":"0","delta":" ","metadata":{}},{"type":"text-delta","id":"0","delta":"10 + 30","metadata":{}},{"type":"text-delta","id":"0","delta":" using the","metadata":{}},{"type":"text-delta","id":"0","delta":" Calculator tool.","metadata":{}},{"type":"text-end","id":"0","metadata":{}},{"type":"tool-params-start","id":"toolu_01LTGUgfihCQtVchm1b37xHQ","name":"Calculator","providerExecuted":false,"metadata":{}},{"type":"tool-params-delta","id":"toolu_01LTGUgfihCQtVchm1b37xHQ","delta":"","metadata":{}},{"type":"tool-params-delta","id":"toolu_01LTGUgfihCQtVchm1b37xHQ","delta":"{\"input\": \"","metadata":{}},{"type":"tool-params-delta","id":"toolu_01LTGUgfihCQtVchm1b37xHQ","delta":"10 + 30","metadata":{}},{"type":"tool-params-delta","id":"toolu_01LTGUgfihCQtVchm1b37xHQ","delta":"\"}","metadata":{}},{"type":"tool-params-end","id":"toolu_01LTGUgfihCQtVchm1b37xHQ","metadata":{}},{"type":"tool-call","id":"toolu_01LTGUgfihCQtVchm1b37xHQ","name":"Calculator","params":{"input":"10 + 30"},"providerExecuted":false,"metadata":{}},{"type":"finish","reason":"tool-calls","usage":{"inputTokens":394,"outputTokens":73,"totalTokens":467},"metadata":{"anthropic":{"usage":{"cache_creation":{"ephemeral_1h_input_tokens":0,"ephemeral_5m_input_tokens":0},"cache_creation_input_tokens":0,"cache_read_input_tokens":0,"input_tokens":394,"output_tokens":1,"server_tool_use":null,"service_tier":"standard"}}}}]},{"parameters":{"model":"@anthropic/claude-3-5-sonnet-20241022","stream":true,"tools":[{"name":"Calculator","description":"Basic calculator tool","inputSchema":{"type":"object","required":["input"],"properties":{"input":{"type":"string","description":"The calculation to perform."}},"additionalProperties":false}}]},"prompt":{"content":[{"role":"user","content":"What is 10 + 30?","options":{}},{"role":"assistant","content":[{"type":"text","text":"I'll help you calculate 10 + 30 using the Calculator tool.","options":{}},{"type":"tool-call","id":"toolu_01LTGUgfihCQtVchm1b37xHQ","name":"Calculator","params":{"input":"10 + 30"},"providerExecuted":false,"options":{}}],"options":{}},{"role":"tool","content":[{"type":"tool-result","id":"toolu_01LTGUgfihCQtVchm1b37xHQ","name":"Calculator","isFailure":false,"result":{"result":40},"options":{}}],"options":{}}]},"response":[{"type":"response-metadata","id":"msg_01AKio3GheJGn38BhvAp33rs","modelId":"claude-3-5-sonnet-20241022","timestamp":"1970-01-01T00:00:00.000Z","metadata":{}},{"type":"text-start","id":"0","metadata":{}},{"type":"text-delta","id":"0","delta":"The result","metadata":{}},{"type":"text-delta","id":"0","delta":" of 10 +","metadata":{}},{"type":"text-delta","id":"0","delta":" 30 is ","metadata":{}},{"type":"text-delta","id":"0","delta":"40.","metadata":{}},{"type":"text-end","id":"0","metadata":{}},{"type":"finish","reason":"stop","usage":{"inputTokens":482,"outputTokens":18,"totalTokens":500},"metadata":{"anthropic":{"usage":{"cache_creation":{"ephemeral_1h_input_tokens":0,"ephemeral_5m_input_tokens":0},"cache_creation_input_tokens":0,"cache_read_input_tokens":0,"input_tokens":482,"output_tokens":3,"server_tool_use":null,"service_tier":"standard"}}}}]},{"parameters":{"model":"@anthropic/claude-opus-4-0","stream":true,"tools":[]},"prompt":{"content":[{"role":"user","content":"Hello world!","options":{}}]},"response":[{"type":"response-metadata","id":"msg_01QPPeofAkjiYa83LPCeSYfS","modelId":"claude-opus-4-20250514","timestamp":"1970-01-01T00:00:00.000Z","metadata":{}},{"type":"text-start","id":"0","metadata":{}},{"type":"text-delta","id":"0","delta":"Hello!","metadata":{}},{"type":"text-delta","id":"0","delta":" Welcome","metadata":{}},{"type":"text-delta","id":"0","delta":" to the worl","metadata":{}},{"type":"text-delta","id":"0","delta":"d!","metadata":{}},{"type":"text-delta","id":"0","delta":" 🌍 ","metadata":{}},{"type":"text-delta","id":"0","delta":"How","metadata":{}},{"type":"text-delta","id":"0","delta":" are you doing today? Is there anything","metadata":{}},{"type":"text-delta","id":"0","delta":" specific you'd like to chat about or","metadata":{}},{"type":"text-delta","id":"0","delta":" any questions","metadata":{}},{"type":"text-delta","id":"0","delta":" I can help you with?","metadata":{}},{"type":"text-end","id":"0","metadata":{}},{"type":"finish","reason":"stop","usage":{"inputTokens":10,"outputTokens":40,"totalTokens":50},"metadata":{"anthropic":{"usage":{"cache_creation":{"ephemeral_1h_input_tokens":0,"ephemeral_5m_input_tokens":0},"cache_creation_input_tokens":0,"cache_read_input_tokens":0,"input_tokens":10,"output_tokens":2,"server_tool_use":null,"service_tier":"standard"}}}}]},{"parameters":{"model":"@anthropic/claude-opus-4-0","stream":true,"tools":[{"name":"Calculator","description":"Basic calculator tool","inputSchema":{"type":"object","required":["input"],"properties":{"input":{"type":"string","description":"The calculation to perform."}},"additionalProperties":false}}]},"prompt":{"content":[{"role":"user","content":"What is 10 + 30?","options":{}}]},"response":[{"type":"response-metadata","id":"msg_01EaHNEDYN3Hvp5toY8hQGe6","modelId":"claude-opus-4-20250514","timestamp":"1970-01-01T00:00:00.000Z","metadata":{}},{"type":"text-start","id":"0","metadata":{}},{"type":"text-delta","id":"0","delta":"I'll help","metadata":{}},{"type":"text-delta","id":"0","delta":" you calculate ","metadata":{}},{"type":"text-delta","id":"0","delta":"10 + 30.","metadata":{}},{"type":"text-end","id":"0","metadata":{}},{"type":"tool-params-start","id":"toolu_01X4qkrMwCisiUN8Cm4E4Voe","name":"Calculator","providerExecuted":false,"metadata":{}},{"type":"tool-params-delta","id":"toolu_01X4qkrMwCisiUN8Cm4E4Voe","delta":"","metadata":{}},{"type":"tool-params-delta","id":"toolu_01X4qkrMwCisiUN8Cm4E4Voe","delta":"{\"input\": ","metadata":{}},{"type":"tool-params-delta","id":"toolu_01X4qkrMwCisiUN8Cm4E4Voe","delta":"\"10 + 3","metadata":{}},{"type":"tool-params-delta","id":"toolu_01X4qkrMwCisiUN8Cm4E4Voe","delta":"0\"}","metadata":{}},{"type":"tool-params-end","id":"toolu_01X4qkrMwCisiUN8Cm4E4Voe","metadata":{}},{"type":"tool-call","id":"toolu_01X4qkrMwCisiUN8Cm4E4Voe","name":"Calculator","params":{"input":"10 + 30"},"providerExecuted":false,"metadata":{}},{"type":"finish","reason":"tool-calls","usage":{"inputTokens":394,"outputTokens":68,"totalTokens":462},"metadata":{"anthropic":{"usage":{"cache_creation":{"ephemeral_1h_input_tokens":0,"ephemeral_5m_input_tokens":0},"cache_creation_input_tokens":0,"cache_read_input_tokens":0,"input_tokens":394,"output_tokens":3,"server_tool_use":null,"service_tier":"standard"}}}}]},{"parameters":{"model":"@anthropic/claude-opus-4-0","stream":true,"tools":[{"name":"Calculator","description":"Basic calculator tool","inputSchema":{"type":"object","required":["input"],"properties":{"input":{"type":"string","description":"The calculation to perform."}},"additionalProperties":false}}]},"prompt":{"content":[{"role":"user","content":"What is 10 + 30?","options":{}},{"role":"assistant","content":[{"type":"text","text":"I'll help you calculate 10 + 30.","options":{}},{"type":"tool-call","id":"toolu_01X4qkrMwCisiUN8Cm4E4Voe","name":"Calculator","params":{"input":"10 + 30"},"providerExecuted":false,"options":{}}],"options":{}},{"role":"tool","content":[{"type":"tool-result","id":"toolu_01X4qkrMwCisiUN8Cm4E4Voe","name":"Calculator","isFailure":false,"result":{"result":40},"options":{}}],"options":{}}]},"response":[{"type":"response-metadata","id":"msg_01RjnEkFT3iEUFCpfC4B28aS","modelId":"claude-opus-4-20250514","timestamp":"1970-01-01T00:00:00.000Z","metadata":{}},{"type":"text-start","id":"0","metadata":{}},{"type":"text-delta","id":"0","delta":"10 + 30 = ","metadata":{}},{"type":"text-delta","id":"0","delta":"40","metadata":{}},{"type":"text-end","id":"0","metadata":{}},{"type":"finish","reason":"stop","usage":{"inputTokens":478,"outputTokens":12,"totalTokens":490},"metadata":{"anthropic":{"usage":{"cache_creation":{"ephemeral_1h_input_tokens":0,"ephemeral_5m_input_tokens":0},"cache_creation_input_tokens":0,"cache_read_input_tokens":0,"input_tokens":478,"output_tokens":8,"server_tool_use":null,"service_tier":"standard"}}}}]}]}
@@ -9,13 +9,12 @@ import * as Effect from 'effect/Effect';
9
9
  import * as Layer from 'effect/Layer';
10
10
  import * as Schema from 'effect/Schema';
11
11
 
12
- import { AiService, MemoizedAiService, ToolExecutionService, ToolResolverService } from '@dxos/ai';
13
- import { AiServiceTestingPreset } from '@dxos/ai/testing';
14
12
  import { Obj, Type } from '@dxos/echo';
15
- import { TestHelpers } from '@dxos/effect';
16
- import { TracingService } from '@dxos/functions';
13
+ import { TestHelpers } from '@dxos/effect/testing';
17
14
  import { log } from '@dxos/log';
18
15
 
16
+ import { AssistantTestLayer } from '../testing';
17
+
19
18
  import { AiSession } from './session';
20
19
 
21
20
  // Define a calendar event artifact schema.
@@ -25,7 +24,7 @@ const CalendarEventSchema = Schema.Struct({
25
24
  endTime: Schema.String,
26
25
  description: Schema.String,
27
26
  }).pipe(
28
- Type.Obj({
27
+ Type.object({
29
28
  typename: 'example.com/type/CalendarEvent',
30
29
  version: '0.1.0',
31
30
  }),
@@ -66,15 +65,10 @@ const toolkitLayer = TestToolkit.toLayer({
66
65
  });
67
66
 
68
67
  const TestLayer = Layer.mergeAll(
68
+ AssistantTestLayer({
69
+ types: [CalendarEventSchema],
70
+ }),
69
71
  toolkitLayer,
70
- AiService.model('@anthropic/claude-3-5-sonnet-20241022'),
71
- TracingService.layerNoop,
72
- ToolResolverService.layerEmpty,
73
- ToolExecutionService.layerEmpty,
74
- ).pipe(
75
- //
76
- Layer.provideMerge(MemoizedAiService.layerTest()),
77
- Layer.provide(AiServiceTestingPreset('direct')),
78
72
  );
79
73
 
80
74
  describe('AiSession', () => {
@@ -24,7 +24,7 @@ import {
24
24
  import { type Blueprint } from '@dxos/blueprints';
25
25
  import { todo } from '@dxos/debug';
26
26
  import { Obj } from '@dxos/echo';
27
- import { TracingService } from '@dxos/functions';
27
+ import { type FunctionInvocationService, TracingService } from '@dxos/functions';
28
28
  import { log } from '@dxos/log';
29
29
  import { Message } from '@dxos/types';
30
30
 
@@ -39,21 +39,22 @@ export type AiSessionRunRequirements =
39
39
  | LanguageModel.LanguageModel
40
40
  | ToolExecutionService
41
41
  | ToolResolverService
42
- | TracingService;
42
+ | TracingService
43
+ | FunctionInvocationService;
43
44
 
44
- export type AiSessionRunParams<Tools extends Record<string, Tool.Any>> = {
45
+ export type AiSessionOptions = {};
46
+
47
+ export type AiSessionRunProps<Tools extends Record<string, Tool.Any>> = {
45
48
  prompt: string;
46
49
  // TODO(wittjosiah): Rename to systemPrompt.
47
50
  system?: string;
48
51
  history?: Message.Message[];
49
- objects?: Obj.Any[];
50
- blueprints?: Blueprint.Blueprint[];
52
+ objects?: Obj.Unknown[];
53
+ blueprints?: readonly Blueprint.Blueprint[];
51
54
  toolkit?: Toolkit.WithHandler<Tools>;
52
- observer?: GenerationObserver;
55
+ observer?: GenerationObserver<Tools>;
53
56
  };
54
57
 
55
- export type AiSessionOptions = {};
56
-
57
58
  /**
58
59
  * Contains message history, tools, current context.
59
60
  * Current context means the state of the app, time of day, and other contextual information.
@@ -75,8 +76,20 @@ export class AiSession {
75
76
  /** Pending messages for this session (incl. the current prompt). */
76
77
  private _pending: Message.Message[] = [];
77
78
 
79
+ private _started = 0;
80
+ private _ended = 0;
81
+ private _toolCalls = 0;
82
+
78
83
  constructor(private readonly _options: AiSessionOptions = {}) {}
79
84
 
85
+ get duration(): number {
86
+ return this._ended - this._started;
87
+ }
88
+
89
+ get toolCalls(): number {
90
+ return this._toolCalls;
91
+ }
92
+
80
93
  run = <Tools extends Record<string, Tool.Any>>({
81
94
  prompt,
82
95
  system: systemTemplate,
@@ -85,8 +98,9 @@ export class AiSession {
85
98
  blueprints = [],
86
99
  toolkit,
87
100
  observer = GenerationObserver.noop(),
88
- }: AiSessionRunParams<Tools>): Effect.Effect<Message.Message[], AiSessionRunError, AiSessionRunRequirements> =>
101
+ }: AiSessionRunProps<Tools>): Effect.Effect<Message.Message[], AiSessionRunError, AiSessionRunRequirements> =>
89
102
  Effect.gen(this, function* () {
103
+ this._started = Date.now();
90
104
  this._history = [...history];
91
105
  this._pending = [];
92
106
  const pending = this._pending;
@@ -103,7 +117,9 @@ export class AiSession {
103
117
  const promptMessage = yield* submitMessage(yield* formatUserPrompt({ prompt, history }));
104
118
 
105
119
  // Generate system and prompt messages.
106
- const system = yield* formatSystemPrompt({ system: systemTemplate, blueprints, objects });
120
+ const system = yield* formatSystemPrompt({ system: systemTemplate, blueprints, objects }).pipe(Effect.orDie);
121
+
122
+ // log('system', { prompt: system });
107
123
 
108
124
  // Tool call loop.
109
125
  do {
@@ -135,6 +151,8 @@ export class AiSession {
135
151
  Effect.map(Chunk.toArray),
136
152
  );
137
153
 
154
+ // log('blocks', { blocks });
155
+
138
156
  // Create the response message.
139
157
  const response = yield* submitMessage(
140
158
  Obj.make(Message.Message, {
@@ -176,9 +194,12 @@ export class AiSession {
176
194
  blocks: toolResults,
177
195
  }),
178
196
  );
197
+
198
+ this._toolCalls++;
179
199
  } while (true);
180
200
 
181
- log('done', { pending: this._pending.length });
201
+ this._ended = Date.now();
202
+ log('done', { pending: this._pending.length, duration: this.duration, tools: this._toolCalls });
182
203
  return this._pending;
183
204
  }).pipe(this._semaphore.withPermits(1), Effect.withSpan('AiSession.run'));
184
205
 
@@ -188,7 +209,7 @@ export class AiSession {
188
209
  // TODO(burdon): Implement or remove.
189
210
  async runStructured<S extends Schema.Schema.AnyNoContext>(
190
211
  _schema: S,
191
- _options: AiSessionRunParams<any>,
212
+ _options: AiSessionRunProps<any>,
192
213
  ): Promise<Schema.Schema.Type<S>> {
193
214
  return todo();
194
215
  // const parser = structuredOutputParser(schema);
@@ -4,45 +4,36 @@
4
4
 
5
5
  import type * as Tool from '@effect/ai/Tool';
6
6
  import * as Toolkit from '@effect/ai/Toolkit';
7
- import type * as Context from 'effect/Context';
8
7
  import * as Effect from 'effect/Effect';
9
8
 
10
- import { type AiToolNotFoundError, ToolExecutionService, type ToolId, ToolResolverService } from '@dxos/ai';
9
+ import { type AiToolNotFoundError, ToolExecutionService, ToolResolverService } from '@dxos/ai';
11
10
  import { type Blueprint } from '@dxos/blueprints';
12
11
  import { isTruthy } from '@dxos/util';
13
12
 
14
- export type ToolkitParams<Tools extends Record<string, Tool.Any>> = {
15
- toolkit?: Toolkit.Toolkit<Tools>;
16
- toolIds?: ToolId[];
17
- blueprints?: Blueprint.Blueprint[];
13
+ export type CreateToolkitProps = {
14
+ toolkit?: Toolkit.Any;
15
+ blueprints?: readonly Blueprint.Blueprint[];
18
16
  };
19
17
 
20
18
  /**
21
19
  * Build a combined toolkit from the blueprint tools and the provided toolkit.
22
20
  */
23
- export const createToolkit = <Tools extends Record<string, Tool.Any> = {}>({
24
- toolkit: toolkitParam,
25
- toolIds = [],
21
+ export const createToolkit = ({
22
+ toolkit: toolkitProp,
26
23
  blueprints = [],
27
- }: ToolkitParams<Tools>): Effect.Effect<
24
+ }: CreateToolkitProps): Effect.Effect<
28
25
  Toolkit.WithHandler<any>,
29
26
  AiToolNotFoundError,
30
- ToolResolverService | ToolExecutionService | Tool.HandlersFor<Tools>
27
+ ToolResolverService | ToolExecutionService | Tool.HandlersFor<any>
31
28
  > =>
32
29
  Effect.gen(function* () {
33
- const blueprintToolkit = yield* ToolResolverService.resolveToolkit([
34
- ...blueprints.flatMap(({ tools }) => tools),
35
- ...toolIds,
36
- ]);
30
+ const blueprintToolkit = yield* ToolResolverService.resolveToolkit(blueprints.flatMap(({ tools }) => tools));
31
+ const blueprintToolHandler = yield* blueprintToolkit.toContext(ToolExecutionService.handlersFor(blueprintToolkit));
37
32
 
38
- const blueprintToolkitHandler: Context.Context<Tool.HandlersFor<any>> = yield* blueprintToolkit.toContext(
39
- ToolExecutionService.handlersFor(blueprintToolkit),
40
- );
41
-
42
- const toolkit = Toolkit.merge(...[toolkitParam, blueprintToolkit].filter(isTruthy));
43
- return yield* toolkit.pipe(Effect.provide(blueprintToolkitHandler)) as any as Effect.Effect<
33
+ const toolkit = Toolkit.merge(...[toolkitProp, blueprintToolkit].filter(isTruthy));
34
+ return yield* toolkit.pipe(Effect.provide(blueprintToolHandler)) as any as Effect.Effect<
44
35
  Toolkit.WithHandler<any>,
45
36
  never,
46
- Tool.HandlersFor<Tools>
37
+ Tool.HandlersFor<any>
47
38
  >;
48
39
  });
@@ -27,11 +27,11 @@ export interface VersionPin extends Schema.Schema.Type<typeof VersionPinSchema>
27
27
 
28
28
  export const VersionPin: typeof VersionPinSchema & {
29
29
  DISPOSITION: 'version-pin';
30
- fromObject: (object: Obj.Any) => VersionPin;
30
+ fromObject: (object: Obj.Unknown) => VersionPin;
31
31
  createBlock: (pin: VersionPin) => ContentBlock.Any;
32
32
  } = class extends VersionPinSchema {
33
33
  static readonly DISPOSITION = 'version-pin';
34
- static fromObject(object: Obj.Any): VersionPin {
34
+ static fromObject(object: Obj.Unknown): VersionPin {
35
35
  return VersionPin.make({
36
36
  objectId: object.id,
37
37
  version: getVersion(object),
@@ -0,0 +1,5 @@
1
+ //
2
+ // Copyright 2026 DXOS.org
3
+ //
4
+
5
+ export * from './layer';
@@ -0,0 +1,78 @@
1
+ //
2
+ // Copyright 2026 DXOS.org
3
+ //
4
+
5
+ import * as Layer from 'effect/Layer';
6
+ import * as Match from 'effect/Match';
7
+
8
+ import { AiService, type ModelName } from '@dxos/ai';
9
+ import { TestAiService } from '@dxos/ai/testing';
10
+ import type { Type } from '@dxos/echo';
11
+ import { CredentialsService, type FunctionDefinition, type ServiceCredential, TracingService } from '@dxos/functions';
12
+ import { TracingServiceExt, TriggerDispatcher, TriggerStateStore } from '@dxos/functions-runtime';
13
+ import { FunctionInvocationServiceLayerTest, TestDatabaseLayer } from '@dxos/functions-runtime/testing';
14
+
15
+ import { makeToolExecutionServiceFromFunctions, makeToolResolverFromFunctions } from '../functions';
16
+ import { GenericToolkit } from '../session';
17
+
18
+ interface TestLayerOptions {
19
+ aiServicePreset?: 'direct' | 'edge-local' | 'edge-remote';
20
+ model?: ModelName;
21
+ functions?: FunctionDefinition.Any[];
22
+ toolkits?: GenericToolkit.GenericToolkit[];
23
+ types?: Type.Entity.Any[];
24
+ credentials?: ServiceCredential[];
25
+ /*
26
+ * Tracing configuration.
27
+ * @default 'noop'
28
+ */
29
+ tracing?: 'noop' | 'console' | 'pretty';
30
+ }
31
+
32
+ export const AssistantTestLayer = ({
33
+ aiServicePreset = 'direct',
34
+ model = '@anthropic/claude-opus-4-0',
35
+ functions = [],
36
+ toolkits = [],
37
+ types = [],
38
+ credentials = [],
39
+ tracing = 'noop',
40
+ }: TestLayerOptions) =>
41
+ Layer.mergeAll(
42
+ AiService.model(model),
43
+ makeToolResolverFromFunctions(functions, GenericToolkit.merge(...toolkits).toolkit as any),
44
+ makeToolExecutionServiceFromFunctions(
45
+ GenericToolkit.merge(...toolkits).toolkit as any,
46
+ GenericToolkit.merge(...toolkits).layer as any,
47
+ ),
48
+ ).pipe(
49
+ Layer.provideMerge(
50
+ FunctionInvocationServiceLayerTest({
51
+ functions,
52
+ }),
53
+ ),
54
+ Layer.provideMerge(
55
+ Layer.mergeAll(
56
+ TestAiService({ preset: aiServicePreset }),
57
+ TestDatabaseLayer({
58
+ spaceKey: 'fixed',
59
+ types,
60
+ }),
61
+ CredentialsService.configuredLayer(credentials),
62
+ Match.value(tracing).pipe(
63
+ Match.when('noop', () => TracingService.layerNoop),
64
+ Match.when('console', () => TracingServiceExt.layerLogInfo()),
65
+ Match.when('pretty', () => TracingServiceExt.layerConsolePrettyPrint()),
66
+ Match.exhaustive,
67
+ ),
68
+ ),
69
+ ),
70
+ );
71
+
72
+ interface TestLayerWithTriggersOptions extends TestLayerOptions {}
73
+
74
+ export const AssistantTestLayerWithTriggers = (options: TestLayerWithTriggersOptions) =>
75
+ Layer.mergeAll(
76
+ AssistantTestLayer(options),
77
+ TriggerDispatcher.layer({ timeControl: 'manual', startingTime: new Date('2025-09-05T15:01:00.000Z') }),
78
+ ).pipe(Layer.provideMerge(TriggerStateStore.layerMemory));
@@ -5,8 +5,9 @@
5
5
  import type * as Effect from 'effect/Effect';
6
6
  import * as Schema from 'effect/Schema';
7
7
 
8
- import { type ObjectNotFoundError, type Type } from '@dxos/echo';
9
- import { DatabaseService } from '@dxos/echo-db';
8
+ import { type Err, Type } from '@dxos/echo';
9
+ import { Database } from '@dxos/echo';
10
+ import { EncodedReference } from '@dxos/echo-protocol';
10
11
  import { DXN, LOCAL_SPACE_TAG, type ObjectId, type SpaceId } from '@dxos/keys';
11
12
  import { trim } from '@dxos/util';
12
13
 
@@ -18,14 +19,16 @@ export const createArtifactElement = (id: ObjectId) => `<artifact id=${id} />`;
18
19
  /**
19
20
  * A model-friendly way to reference an object.
20
21
  * Supports vairous formats that will be normalized to a DXN.
22
+ *
23
+ * @deprecated Use `RefFromLLM` instead.
21
24
  */
22
- // TODO(burdon): Rename RefFromLLM?
25
+ // TODO(burdon): Rename RefFromLLM? -- yes -dm
23
26
  export const ArtifactId: Schema.Schema<string> & {
24
27
  toDXN: (reference: ArtifactId, owningSpaceId?: SpaceId) => DXN;
25
28
  resolve: <S extends Type.Entity.Any>(
26
29
  schema: S,
27
30
  ref: ArtifactId,
28
- ) => Effect.Effect<Schema.Schema.Type<S>, ObjectNotFoundError, DatabaseService>;
31
+ ) => Effect.Effect<Schema.Schema.Type<S>, Err.ObjectNotFoundError, Database.Service>;
29
32
  } = class extends Schema.String.annotations({
30
33
  // TODO(dmaretskyi): This section gets overriden.
31
34
  description: trim`
@@ -61,10 +64,19 @@ export const ArtifactId: Schema.Schema<string> & {
61
64
  static resolve<S extends Type.Entity.Any>(
62
65
  schema: S,
63
66
  ref: ArtifactId,
64
- ): Effect.Effect<Schema.Schema.Type<S>, ObjectNotFoundError, DatabaseService> {
67
+ ): Effect.Effect<Schema.Schema.Type<S>, Err.ObjectNotFoundError, Database.Service> {
65
68
  const dxn = ArtifactId.toDXN(ref);
66
- return DatabaseService.resolve(dxn, schema);
69
+ return Database.Service.resolve(dxn, schema);
67
70
  }
68
71
  };
69
72
 
70
73
  export type ArtifactId = Schema.Schema.Type<typeof ArtifactId>;
74
+
75
+ /**
76
+ * Schema that decodes ECHO reference object from an LLM-friendly input.
77
+ */
78
+ export const RefFromLLM = Schema.transform(ArtifactId, Type.Ref(Type.Obj), {
79
+ decode: (fromA, fromI) => EncodedReference.fromDXN(ArtifactId.toDXN(fromA)),
80
+ encode: (toI, toA) => EncodedReference.toDXN(toI).toString(),
81
+ strict: false,
82
+ });