@dxos/assistant 0.8.4-main.fffef41 → 0.9.0

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 (174) hide show
  1. package/LICENSE +102 -5
  2. package/README.md +2 -1
  3. package/dist/lib/{browser → neutral}/extraction/index.mjs +42 -59
  4. package/dist/lib/neutral/extraction/index.mjs.map +7 -0
  5. package/dist/lib/neutral/index.mjs +1886 -0
  6. package/dist/lib/neutral/index.mjs.map +7 -0
  7. package/dist/lib/neutral/meta.json +1 -0
  8. package/dist/types/src/extraction/extraction-ner-function/index.d.ts +0 -1
  9. package/dist/types/src/extraction/extraction-ner-function/index.d.ts.map +1 -1
  10. package/dist/types/src/extraction/extraction-ner-function/named-entity-recognition.d.ts.map +1 -1
  11. package/dist/types/src/extraction/extraction.d.ts +1649 -317
  12. package/dist/types/src/extraction/extraction.d.ts.map +1 -1
  13. package/dist/types/src/extraction/index.d.ts +0 -1
  14. package/dist/types/src/extraction/index.d.ts.map +1 -1
  15. package/dist/types/src/extraction/quotes.d.ts +2 -2
  16. package/dist/types/src/extraction/quotes.d.ts.map +1 -1
  17. package/dist/types/src/functions/services.d.ts +14 -16
  18. package/dist/types/src/functions/services.d.ts.map +1 -1
  19. package/dist/types/src/index.d.ts +2 -5
  20. package/dist/types/src/index.d.ts.map +1 -1
  21. package/dist/types/src/request/AiRequest.d.ts +308 -0
  22. package/dist/types/src/request/AiRequest.d.ts.map +1 -0
  23. package/dist/types/src/{session → request}/artifact-diff.d.ts +4 -4
  24. package/dist/types/src/request/artifact-diff.d.ts.map +1 -0
  25. package/dist/types/src/request/format.d.ts +15 -0
  26. package/dist/types/src/request/format.d.ts.map +1 -0
  27. package/dist/types/src/request/index.d.ts +4 -0
  28. package/dist/types/src/request/index.d.ts.map +1 -0
  29. package/dist/types/src/{session → request}/observer.d.ts +4 -3
  30. package/dist/types/src/request/observer.d.ts.map +1 -0
  31. package/dist/types/src/{session → request}/version-pin.d.ts +4 -4
  32. package/dist/types/src/request/version-pin.d.ts.map +1 -0
  33. package/dist/types/src/session/AiContext.d.ts +178 -0
  34. package/dist/types/src/session/AiContext.d.ts.map +1 -0
  35. package/dist/types/src/session/AiContext.test.d.ts +2 -0
  36. package/dist/types/src/session/AiContext.test.d.ts.map +1 -0
  37. package/dist/types/src/session/AiSession.d.ts +79 -0
  38. package/dist/types/src/session/AiSession.d.ts.map +1 -0
  39. package/dist/types/src/session/AiSession.test.d.ts +2 -0
  40. package/dist/types/src/session/AiSession.test.d.ts.map +1 -0
  41. package/dist/types/src/session/SessionLink.d.ts +17 -0
  42. package/dist/types/src/session/SessionLink.d.ts.map +1 -0
  43. package/dist/types/src/session/SessionLoader.d.ts +15 -0
  44. package/dist/types/src/session/SessionLoader.d.ts.map +1 -0
  45. package/dist/types/src/session/SessionLoader.test.d.ts +2 -0
  46. package/dist/types/src/session/SessionLoader.test.d.ts.map +1 -0
  47. package/dist/types/src/session/index.d.ts +4 -5
  48. package/dist/types/src/session/index.d.ts.map +1 -1
  49. package/dist/types/src/session/toolkit.d.ts +10 -9
  50. package/dist/types/src/session/toolkit.d.ts.map +1 -1
  51. package/dist/types/src/templates/system.d.ts +12 -3
  52. package/dist/types/src/templates/system.d.ts.map +1 -1
  53. package/dist/types/src/util/artifact.d.ts +18 -0
  54. package/dist/types/src/util/artifact.d.ts.map +1 -0
  55. package/dist/types/src/{diff.d.ts → util/diff.d.ts} +4 -2
  56. package/dist/types/src/util/diff.d.ts.map +1 -0
  57. package/dist/types/src/{diff.test.d.ts.map → util/diff.test.d.ts.map} +1 -1
  58. package/dist/types/src/util/error-handling.d.ts.map +1 -0
  59. package/dist/types/src/{errors.d.ts → util/errors.d.ts} +24 -28
  60. package/dist/types/src/util/errors.d.ts.map +1 -0
  61. package/dist/types/src/{execution-graph.d.ts → util/execution-graph.d.ts} +2 -2
  62. package/dist/types/src/util/execution-graph.d.ts.map +1 -0
  63. package/dist/types/src/util/execution-graph.test.d.ts.map +1 -0
  64. package/dist/types/src/util/index.d.ts +7 -0
  65. package/dist/types/src/util/index.d.ts.map +1 -0
  66. package/dist/types/src/util/tracing.d.ts +296 -0
  67. package/dist/types/src/util/tracing.d.ts.map +1 -0
  68. package/dist/types/tsconfig.tsbuildinfo +1 -1
  69. package/package.json +36 -44
  70. package/src/extraction/extraction-ner-function/index.ts +0 -1
  71. package/src/extraction/extraction.ts +47 -18
  72. package/src/extraction/index.ts +0 -1
  73. package/src/extraction/quotes.test.ts +2 -2
  74. package/src/extraction/quotes.ts +6 -8
  75. package/src/functions/services.ts +129 -63
  76. package/src/index.ts +2 -5
  77. package/src/request/AiRequest.ts +387 -0
  78. package/src/{session → request}/artifact-diff.ts +4 -4
  79. package/src/{session → request}/format.ts +28 -25
  80. package/src/request/index.ts +8 -0
  81. package/src/{session → request}/observer.ts +4 -1
  82. package/src/{session → request}/version-pin.ts +6 -5
  83. package/src/session/AiContext.test.ts +49 -0
  84. package/src/session/AiContext.ts +420 -0
  85. package/src/session/AiSession.test.ts +111 -0
  86. package/src/session/AiSession.ts +328 -0
  87. package/src/session/SessionLink.ts +23 -0
  88. package/src/session/SessionLoader.test.ts +115 -0
  89. package/src/session/SessionLoader.ts +55 -0
  90. package/src/session/index.ts +4 -5
  91. package/src/session/toolkit.ts +27 -28
  92. package/src/templates/instructions/format.tpl +0 -4
  93. package/src/templates/instructions/system.tpl +50 -2
  94. package/src/templates/system.ts +7 -6
  95. package/src/util/artifact.ts +96 -0
  96. package/src/util/diff.test.ts +74 -0
  97. package/src/{diff.ts → util/diff.ts} +14 -5
  98. package/src/{session → util}/error-handling.ts +3 -2
  99. package/src/util/errors.ts +15 -0
  100. package/src/{execution-graph.test.ts → util/execution-graph.test.ts} +4 -4
  101. package/src/{execution-graph.ts → util/execution-graph.ts} +30 -19
  102. package/src/util/index.ts +10 -0
  103. package/src/util/tracing.ts +60 -0
  104. package/dist/lib/browser/extraction/index.mjs.map +0 -7
  105. package/dist/lib/browser/index.mjs +0 -1290
  106. package/dist/lib/browser/index.mjs.map +0 -7
  107. package/dist/lib/browser/meta.json +0 -1
  108. package/dist/lib/node-esm/chunk-HSLMI22Q.mjs +0 -11
  109. package/dist/lib/node-esm/chunk-HSLMI22Q.mjs.map +0 -7
  110. package/dist/lib/node-esm/extraction/index.mjs +0 -226
  111. package/dist/lib/node-esm/extraction/index.mjs.map +0 -7
  112. package/dist/lib/node-esm/index.mjs +0 -1291
  113. package/dist/lib/node-esm/index.mjs.map +0 -7
  114. package/dist/lib/node-esm/meta.json +0 -1
  115. package/dist/types/src/conversation/context.d.ts +0 -103
  116. package/dist/types/src/conversation/context.d.ts.map +0 -1
  117. package/dist/types/src/conversation/conversation.d.ts +0 -41
  118. package/dist/types/src/conversation/conversation.d.ts.map +0 -1
  119. package/dist/types/src/conversation/index.d.ts +0 -3
  120. package/dist/types/src/conversation/index.d.ts.map +0 -1
  121. package/dist/types/src/diff.d.ts.map +0 -1
  122. package/dist/types/src/errors.d.ts.map +0 -1
  123. package/dist/types/src/execution-graph.d.ts.map +0 -1
  124. package/dist/types/src/execution-graph.test.d.ts.map +0 -1
  125. package/dist/types/src/extraction/extraction-llm-function/extraction-llm-function.d.ts +0 -4
  126. package/dist/types/src/extraction/extraction-llm-function/extraction-llm-function.d.ts.map +0 -1
  127. package/dist/types/src/extraction/extraction-llm-function/extraction-llm-function.test.d.ts +0 -2
  128. package/dist/types/src/extraction/extraction-llm-function/extraction-llm-function.test.d.ts.map +0 -1
  129. package/dist/types/src/extraction/extraction-llm-function/index.d.ts +0 -2
  130. package/dist/types/src/extraction/extraction-llm-function/index.d.ts.map +0 -1
  131. package/dist/types/src/extraction/extraction-ner-function/extraction-ner-function.d.ts +0 -345
  132. package/dist/types/src/extraction/extraction-ner-function/extraction-ner-function.d.ts.map +0 -1
  133. package/dist/types/src/extraction/extraction-ner-function/extraction-ner-function.test.d.ts +0 -2
  134. package/dist/types/src/extraction/extraction-ner-function/extraction-ner-function.test.d.ts.map +0 -1
  135. package/dist/types/src/session/GenericToolkit.d.ts +0 -84
  136. package/dist/types/src/session/GenericToolkit.d.ts.map +0 -1
  137. package/dist/types/src/session/artifact-diff.d.ts.map +0 -1
  138. package/dist/types/src/session/error-handling.d.ts.map +0 -1
  139. package/dist/types/src/session/format.d.ts +0 -12
  140. package/dist/types/src/session/format.d.ts.map +0 -1
  141. package/dist/types/src/session/format.test.d.ts +0 -2
  142. package/dist/types/src/session/format.test.d.ts.map +0 -1
  143. package/dist/types/src/session/observer.d.ts.map +0 -1
  144. package/dist/types/src/session/session.d.ts +0 -51
  145. package/dist/types/src/session/session.d.ts.map +0 -1
  146. package/dist/types/src/session/session.test.d.ts +0 -2
  147. package/dist/types/src/session/session.test.d.ts.map +0 -1
  148. package/dist/types/src/session/version-pin.d.ts.map +0 -1
  149. package/dist/types/src/types/artifact.d.ts +0 -20
  150. package/dist/types/src/types/artifact.d.ts.map +0 -1
  151. package/dist/types/src/types/index.d.ts +0 -2
  152. package/dist/types/src/types/index.d.ts.map +0 -1
  153. package/src/conversation/context.ts +0 -186
  154. package/src/conversation/conversation.ts +0 -128
  155. package/src/conversation/index.ts +0 -6
  156. package/src/diff.test.ts +0 -43
  157. package/src/errors.ts +0 -15
  158. package/src/extraction/extraction-llm-function/extraction-llm-function.test.ts +0 -84
  159. package/src/extraction/extraction-llm-function/extraction-llm-function.ts +0 -62
  160. package/src/extraction/extraction-llm-function/index.ts +0 -5
  161. package/src/extraction/extraction-ner-function/extraction-ner-function.test.ts +0 -116
  162. package/src/extraction/extraction-ner-function/extraction-ner-function.ts +0 -56
  163. package/src/session/GenericToolkit.ts +0 -130
  164. package/src/session/format.test.ts +0 -61
  165. package/src/session/session.conversations.json +0 -1
  166. package/src/session/session.test.ts +0 -149
  167. package/src/session/session.ts +0 -213
  168. package/src/types/artifact.ts +0 -71
  169. package/src/types/index.ts +0 -5
  170. /package/dist/lib/{browser → neutral}/chunk-J5LGTIGS.mjs +0 -0
  171. /package/dist/lib/{browser → neutral}/chunk-J5LGTIGS.mjs.map +0 -0
  172. /package/dist/types/src/{diff.test.d.ts → util/diff.test.d.ts} +0 -0
  173. /package/dist/types/src/{session → util}/error-handling.d.ts +0 -0
  174. /package/dist/types/src/{execution-graph.test.d.ts → util/execution-graph.test.d.ts} +0 -0
@@ -1,56 +0,0 @@
1
- //
2
- // Copyright 2025 DXOS.org
3
- //
4
-
5
- import { defineFunction } from '@dxos/functions';
6
-
7
- import { ExtractionInput, ExtractionOutput } from '../extraction';
8
-
9
- /**
10
- * Named Entity Recognition model
11
- */
12
- // TODO(mykola): Make it use vector index to query objects and not pass objects as input.
13
- export const extractionNerFunction = defineFunction({
14
- key: 'dxos.org/function/extraction/extract-entities',
15
- name: 'Extract Entities',
16
- description: 'Extracts named entities from a text',
17
- inputSchema: ExtractionInput,
18
- outputSchema: ExtractionOutput,
19
- handler: async ({ data: { message, options }, context }) => {
20
- throw new Error('not implemented');
21
- // log.info('input', { message, options });
22
- // const startTime = performance.now();
23
- // const { db } = context.getService(DatabaseService);
24
- // const { extractFullEntities } = await import('./named-entity-recognition');
25
-
26
- // const entitiesPromise = Promise.all(
27
- // message.blocks.map(async (block) => {
28
- // invariant(block._tag === 'transcript' || block._tag === 'text');
29
- // return extractFullEntities(block.text);
30
- // }),
31
- // ).then((entities) => entities.flat());
32
- // const entities = options?.timeout ? await asyncTimeout(entitiesPromise, options.timeout) : await entitiesPromise;
33
-
34
- // log.info('entities', { entities });
35
- // const quoteReferences = await findQuotes(
36
- // entities.map((entity) => entity.word),
37
- // db,
38
- // );
39
-
40
- // const blocksWithReferences = message.blocks.map((block) => {
41
- // invariant(block._tag === 'transcript' || block._tag === 'text');
42
- // return { ...block, text: insertReferences(block._tag, quoteReferences) };
43
- // });
44
-
45
- // const messageWithReferences = create(Message.Message, {
46
- // ...message,
47
- // blocks: blocksWithReferences,
48
- // });
49
-
50
- // log.info('output', { messageWithReferences });
51
- // return {
52
- // message: messageWithReferences,
53
- // timeElapsed: performance.now() - startTime,
54
- // };
55
- },
56
- });
@@ -1,130 +0,0 @@
1
- //
2
- // Copyright 2025 DXOS.org
3
- //
4
-
5
- import type * as Tool from '@effect/ai/Tool';
6
- import * as Toolkit from '@effect/ai/Toolkit';
7
- import * as Effect from 'effect/Effect';
8
- import * as Layer from 'effect/Layer';
9
- import * as Pipeable from 'effect/Pipeable';
10
- import type * as Schema from 'effect/Schema';
11
- import type * as SchemaAST from 'effect/SchemaAST';
12
-
13
- /**
14
- * Unique identifier for generic toolkit instances.
15
- */
16
- export const TypeId = '~@dxos/assistant/GenericToolkit';
17
-
18
- /**
19
- * Type-level representation of the generic toolkit identifier.
20
- */
21
- export type TypeId = typeof TypeId;
22
-
23
- /**
24
- * Type-safe way to define toolkits where we don't know specific types of tools,
25
- * and we want to bundle definition and handlers together.
26
- *
27
- * Usefull for plugin-based systems, where tools are dynamically added.
28
- *
29
- * @param TR requirements type to the tool invocation.
30
- * @param E failure type to the handlers layer.
31
- * @param R requirements type to the handlers layer.
32
- */
33
- export interface GenericToolkit<TR = never, E = never, R = never> extends Pipeable.Pipeable {
34
- readonly [TypeId]: TypeId;
35
-
36
- /**
37
- * Toolkit definition.
38
- */
39
- readonly toolkit: Toolkit.Toolkit<GenericTools<TR>>;
40
-
41
- /**
42
- * Handlers layer.
43
- */
44
- readonly layer: Layer.Layer<unknown, E, R>;
45
-
46
- /**
47
- * Handlers effect.
48
- */
49
- readonly handlers: Effect.Effect<Toolkit.WithHandler<GenericTools<TR>>, E, R>;
50
- }
51
-
52
- /**
53
- * Generic constraint.
54
- *
55
- * NOTE: Only use in place of `T extends PortableToolkit.Any`. Not suitable for standalone use.
56
- */
57
- export interface Any {
58
- readonly [TypeId]: TypeId;
59
- readonly toolkit: Toolkit.Toolkit<any>;
60
- readonly layer: Layer.Layer<unknown, any, any>;
61
- }
62
-
63
- export type InvocationRequirements<T extends Any> = T extends GenericToolkit<infer TR, infer _E, infer _R> ? TR : never;
64
- export type Failure<T extends Any> = T extends GenericToolkit<infer _TR, infer E, infer _R> ? E : never;
65
- export type Requirements<T extends Any> = T extends GenericToolkit<infer _TR, infer _E, infer R> ? R : never;
66
-
67
- /**
68
- * Creates a portable toolkit from toolkit definition and handlers layer.
69
- */
70
- export const make = <Tools extends Record<string, Tool.Any>, E, R>(
71
- toolkit: Toolkit.Toolkit<Tools>,
72
- layer: Layer.Layer<Tool.HandlersFor<Tools>, E, R>,
73
- ): GenericToolkit<E, R> => {
74
- return {
75
- [TypeId]: TypeId,
76
- toolkit: toolkit as any,
77
- layer: layer as any,
78
- handlers: toolkit.pipe(Effect.provide(layer)) as any,
79
- pipe() {
80
- // eslint-disable-next-line prefer-rest-params
81
- return Pipeable.pipeArguments(this, arguments);
82
- },
83
- };
84
- };
85
-
86
- /**
87
- * Merges multiple portable toolkits into a single portable toolkit.
88
- */
89
- export const merge = <const Toolkits extends ReadonlyArray<Any>>(
90
- /**
91
- * The toolkits to merge together.
92
- */
93
- ...toolkits: Toolkits
94
- ): GenericToolkit<
95
- InvocationRequirements<Toolkits[number]>,
96
- Failure<Toolkits[number]>,
97
- Requirements<Toolkits[number]>
98
- > => {
99
- return make(
100
- Toolkit.merge(...toolkits.map((t) => t.toolkit)),
101
- Layer.mergeAll(...(toolkits.map((t) => t.layer) as any)),
102
- ) as any;
103
- };
104
-
105
- /**
106
- * Generic tools type where we cannot statically enumerate individual tools.
107
- */
108
- export type GenericTools<R = never> = Record<
109
- string,
110
- Tool.Tool<
111
- string,
112
- {
113
- readonly parameters: AnyStructSchemaNoContext;
114
- readonly success: Schema.Schema.AnyNoContext;
115
- readonly failure: typeof Schema.Never;
116
- },
117
- R
118
- >
119
- >;
120
-
121
- export interface AnyStructSchemaNoContext extends Pipeable.Pipeable {
122
- readonly [Schema.TypeId]: any;
123
- readonly make: any;
124
- readonly Type: any;
125
- readonly Encoded: any;
126
- readonly Context: never;
127
- readonly ast: SchemaAST.AST;
128
- readonly fields: Schema.Struct.Fields;
129
- readonly annotations: any;
130
- }
@@ -1,61 +0,0 @@
1
- //
2
- // Copyright 2025 DXOS.org
3
- //
4
-
5
- import { beforeAll, describe, it } from '@effect/vitest';
6
- import * as Effect from 'effect/Effect';
7
-
8
- import { Blueprint, Template } from '@dxos/blueprints';
9
- import { Obj } from '@dxos/echo';
10
- import { type EchoDatabase } from '@dxos/echo-db';
11
- import { EchoTestBuilder } from '@dxos/echo-db/testing';
12
- import { Text } from '@dxos/schema';
13
- import { Organization } from '@dxos/types';
14
- import { trim } from '@dxos/util';
15
-
16
- import { createSystemPrompt } from '../templates/system';
17
-
18
- import { formatSystemPrompt } from './format';
19
-
20
- describe('format', () => {
21
- let db: EchoDatabase;
22
- beforeAll(async () => {
23
- const builder = await new EchoTestBuilder().open();
24
- ({ db } = await builder.createDatabase({
25
- types: [Text.Text, Organization.Organization, Blueprint.Blueprint],
26
- }));
27
- });
28
-
29
- it.effect(
30
- 'should format',
31
- Effect.fn(function* () {
32
- const object = db.add(
33
- Obj.make(Organization.Organization, {
34
- name: 'Test',
35
- website: 'https://www.test.com',
36
- }),
37
- );
38
-
39
- const blueprint = db.add(
40
- Blueprint.make({
41
- key: 'example.com/blueprint/test',
42
- name: 'Test',
43
- instructions: Template.make({
44
- source: trim`
45
- Test
46
- This is the test blueprint.
47
- `,
48
- }),
49
- }),
50
- );
51
-
52
- const output = yield* formatSystemPrompt({
53
- system: createSystemPrompt({}),
54
- blueprints: [blueprint, blueprint],
55
- objects: [object, object],
56
- });
57
-
58
- console.log(output);
59
- }),
60
- );
61
- });
@@ -1 +0,0 @@
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,149 +0,0 @@
1
- //
2
- // Copyright 2025 DXOS.org
3
- //
4
-
5
- import * as Tool from '@effect/ai/Tool';
6
- import * as Toolkit from '@effect/ai/Toolkit';
7
- import { describe, it } from '@effect/vitest';
8
- import * as Effect from 'effect/Effect';
9
- import * as Layer from 'effect/Layer';
10
- import * as Schema from 'effect/Schema';
11
-
12
- import { AiService, MemoizedAiService, ToolExecutionService, ToolResolverService } from '@dxos/ai';
13
- import { AiServiceTestingPreset } from '@dxos/ai/testing';
14
- import { Obj, Type } from '@dxos/echo';
15
- import { TestHelpers } from '@dxos/effect';
16
- import { TracingService } from '@dxos/functions';
17
- import { log } from '@dxos/log';
18
-
19
- import { AiSession } from './session';
20
-
21
- // Define a calendar event artifact schema.
22
- const CalendarEventSchema = Schema.Struct({
23
- title: Schema.String,
24
- startTime: Schema.String,
25
- endTime: Schema.String,
26
- description: Schema.String,
27
- }).pipe(
28
- Type.Obj({
29
- typename: 'example.com/type/CalendarEvent',
30
- version: '0.1.0',
31
- }),
32
- );
33
-
34
- type CalendarEvent = Schema.Schema.Type<typeof CalendarEventSchema>;
35
-
36
- const TestToolkit = Toolkit.make(
37
- Tool.make('Calculator', {
38
- description: 'Basic calculator tool',
39
- parameters: {
40
- input: Schema.String.annotations({
41
- description: 'The calculation to perform.',
42
- }),
43
- },
44
- success: Schema.Struct({
45
- result: Schema.Number,
46
- }),
47
- failure: Schema.Never,
48
- }),
49
- );
50
-
51
- // Tool handlers.
52
- const toolkitLayer = TestToolkit.toLayer({
53
- Calculator: ({ input }) =>
54
- Effect.gen(function* () {
55
- const result = (() => {
56
- // Restrict to basic arithmetic operations for safety.
57
- const sanitizedInput = input.replace(/[^0-9+\-*/().\s]/g, '');
58
- log.info('calculate', { sanitizedInput });
59
-
60
- // eslint-disable-next-line @typescript-eslint/no-implied-eval
61
- return Function(`"use strict"; return (${sanitizedInput})`)();
62
- })();
63
-
64
- return { result };
65
- }),
66
- });
67
-
68
- const TestLayer = Layer.mergeAll(
69
- 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
- );
79
-
80
- describe('AiSession', () => {
81
- it.effect(
82
- 'no tools',
83
- Effect.fnUntraced(
84
- function* (_) {
85
- const session = new AiSession({ operationModel: 'configured' });
86
- const response = yield* session.run({
87
- prompt: 'Hello world!',
88
- history: [],
89
- });
90
- log.info('response', { response });
91
- },
92
- Effect.provide(TestLayer),
93
- TestHelpers.provideTestContext,
94
- ),
95
- );
96
-
97
- it.effect(
98
- 'calculator',
99
- Effect.fnUntraced(
100
- function* (_) {
101
- const session = new AiSession({ operationModel: 'configured' });
102
- const toolkit = yield* TestToolkit;
103
- const response = yield* session.run({
104
- toolkit,
105
- prompt: 'What is 10 + 30?',
106
- history: [],
107
- });
108
- log.info('response', { response });
109
- },
110
- Effect.provide(TestLayer),
111
- TestHelpers.provideTestContext,
112
- ),
113
- );
114
- });
115
-
116
- // Travel to rome, florence, livorno, siena, madrid for conferences
117
-
118
- const _CALENDAR_EVENTS: CalendarEvent[] = [
119
- Obj.make(CalendarEventSchema, {
120
- title: 'Exploring Ancient Ruins in Rome',
121
- startTime: '2024-01-01T10:00:00Z',
122
- endTime: '2024-01-01T11:00:00Z',
123
- description: 'Tech conference at the historic Colosseum with networking opportunities',
124
- }),
125
- Obj.make(CalendarEventSchema, {
126
- title: 'Renaissance Tech Summit in Florence',
127
- startTime: '2024-01-01T11:00:00Z',
128
- endTime: '2024-01-01T12:00:00Z',
129
- description: 'Discussing AI innovations surrounded by Renaissance art',
130
- }),
131
- Obj.make(CalendarEventSchema, {
132
- title: 'Travel to Livorno',
133
- startTime: '2024-01-01T12:00:00Z',
134
- endTime: '2024-01-01T13:00:00Z',
135
- description: 'Travel to Livorno',
136
- }),
137
- Obj.make(CalendarEventSchema, {
138
- title: 'Travel to Siena',
139
- startTime: '2024-01-01T13:00:00Z',
140
- endTime: '2024-01-01T14:00:00Z',
141
- description: 'Travel to Siena',
142
- }),
143
- Obj.make(CalendarEventSchema, {
144
- title: 'Travel to Madrid',
145
- startTime: '2024-01-01T14:00:00Z',
146
- endTime: '2024-01-01T15:00:00Z',
147
- description: 'Travel to Madrid',
148
- }),
149
- ];
@@ -1,213 +0,0 @@
1
- //
2
- // Copyright 2025 DXOS.org
3
- //
4
-
5
- import type * as AiError from '@effect/ai/AiError';
6
- import * as LanguageModel from '@effect/ai/LanguageModel';
7
- import type * as Tool from '@effect/ai/Tool';
8
- import type * as Toolkit from '@effect/ai/Toolkit';
9
- import * as Chunk from 'effect/Chunk';
10
- import * as Effect from 'effect/Effect';
11
- import type * as Schema from 'effect/Schema';
12
- import * as Stream from 'effect/Stream';
13
-
14
- import {
15
- AiParser,
16
- AiPreprocessor,
17
- type AiToolNotFoundError,
18
- type PromptPreprocessingError,
19
- type ToolExecutionService,
20
- type ToolResolverService,
21
- callTool,
22
- getToolCalls,
23
- } from '@dxos/ai';
24
- import { type Blueprint } from '@dxos/blueprints';
25
- import { todo } from '@dxos/debug';
26
- import { Obj } from '@dxos/echo';
27
- import { TracingService } from '@dxos/functions';
28
- import { log } from '@dxos/log';
29
- import { Message } from '@dxos/types';
30
-
31
- import { type AiAssistantError } from '../errors';
32
-
33
- import { formatSystemPrompt, formatUserPrompt } from './format';
34
- import { GenerationObserver } from './observer';
35
-
36
- export type AiSessionRunError = AiError.AiError | PromptPreprocessingError | AiToolNotFoundError | AiAssistantError;
37
-
38
- export type AiSessionRunRequirements =
39
- | LanguageModel.LanguageModel
40
- | ToolExecutionService
41
- | ToolResolverService
42
- | TracingService;
43
-
44
- export type AiSessionRunParams<Tools extends Record<string, Tool.Any>> = {
45
- prompt: string;
46
- // TODO(wittjosiah): Rename to systemPrompt.
47
- system?: string;
48
- history?: Message.Message[];
49
- objects?: Obj.Any[];
50
- blueprints?: Blueprint.Blueprint[];
51
- toolkit?: Toolkit.WithHandler<Tools>;
52
- observer?: GenerationObserver;
53
- };
54
-
55
- export type AiSessionOptions = {};
56
-
57
- /**
58
- * Contains message history, tools, current context.
59
- * Current context means the state of the app, time of day, and other contextual information.
60
- * It makes requests to the model, its a state machine.
61
- * It keeps track of the current goal.
62
- * It manages the context window.
63
- * Tracks the success criteria of reaching the goal, exposing metrics (stretch).
64
- * Could be run locally in the app or remotely.
65
- * Could be personal or shared.
66
- */
67
- export class AiSession {
68
- /** Prevents concurrent execution of session. */
69
- private readonly _semaphore = Effect.runSync(Effect.makeSemaphore(1));
70
-
71
- /** Message history from queue. */
72
- // TODO(burdon): Evolve into supporting a git-like graph of messages.
73
- private _history: Message.Message[] = [];
74
-
75
- /** Pending messages for this session (incl. the current prompt). */
76
- private _pending: Message.Message[] = [];
77
-
78
- constructor(private readonly _options: AiSessionOptions = {}) {}
79
-
80
- run = <Tools extends Record<string, Tool.Any>>({
81
- prompt,
82
- system: systemTemplate,
83
- history = [],
84
- objects = [],
85
- blueprints = [],
86
- toolkit,
87
- observer = GenerationObserver.noop(),
88
- }: AiSessionRunParams<Tools>): Effect.Effect<Message.Message[], AiSessionRunError, AiSessionRunRequirements> =>
89
- Effect.gen(this, function* () {
90
- this._history = [...history];
91
- this._pending = [];
92
- const pending = this._pending;
93
-
94
- const submitMessage = Effect.fnUntraced(function* (message: Message.Message) {
95
- pending.push(message);
96
- yield* observer.onMessage(message);
97
- yield* TracingService.emitConverationMessage(message);
98
- return message;
99
- });
100
-
101
- // Submit the prompt.
102
- // TODO(burdon): Remove if cancelled?
103
- const promptMessage = yield* submitMessage(yield* formatUserPrompt({ prompt, history }));
104
-
105
- // Generate system and prompt messages.
106
- const system = yield* formatSystemPrompt({ system: systemTemplate, blueprints, objects });
107
-
108
- // Tool call loop.
109
- do {
110
- log('request', {
111
- prompt: promptMessage,
112
- system: { snippet: createSnippet(system), length: system.length },
113
- pending: this._pending.length,
114
- history: this._history.length,
115
- objects: objects?.length ?? 0,
116
- });
117
-
118
- const prompt = yield* AiPreprocessor.preprocessPrompt([...this._history, ...this._pending], { system });
119
-
120
- // Execute the stream request.
121
- // logDump('prompt', Prompt.Prompt.pipe(Schema.encodeSync)(prompt));
122
- const blocks = yield* LanguageModel.streamText({
123
- prompt,
124
- toolkit,
125
- disableToolCallResolution: true,
126
- }).pipe(
127
- // TOOD(dmaretskyi): Error mapping.
128
- AiParser.parseResponse({
129
- onBegin: () => observer.onBegin(),
130
- onBlock: (block) => observer.onBlock(block),
131
- onPart: (part) => observer.onPart(part),
132
- onEnd: (summary) => observer.onEnd(summary),
133
- }),
134
- Stream.runCollect,
135
- Effect.map(Chunk.toArray),
136
- );
137
-
138
- // Create the response message.
139
- const response = yield* submitMessage(
140
- Obj.make(Message.Message, {
141
- created: new Date().toISOString(),
142
- sender: { role: 'assistant' },
143
- blocks,
144
- }),
145
- );
146
-
147
- // Parse the response for tool calls.
148
- const toolCalls = getToolCalls(response);
149
- if (toolCalls.length === 0) {
150
- break;
151
- } else if (!toolkit) {
152
- throw new Error('No toolkit provided'); // TODO(burdon): Throw user error?
153
- }
154
-
155
- // Execute the tool calls.
156
- // TODO(burdon): Retry errors? Write result when each completes individually?
157
- const toolResults = yield* Effect.forEach(toolCalls, (toolCall) => {
158
- return callTool(toolkit, toolCall).pipe(
159
- Effect.provide(
160
- TracingService.layerSubframe((context) => ({
161
- ...context,
162
- parentMessage: response.id,
163
- toolCallId: toolCall.toolCallId,
164
- })),
165
- ),
166
- );
167
- });
168
-
169
- // Add to queue and continue loop.
170
- // TODO(wittjosiah): Sometimes tool error results are added to the queue before the tool agent statuses.
171
- // This results in a broken execution graph.
172
- yield* submitMessage(
173
- Obj.make(Message.Message, {
174
- created: new Date().toISOString(),
175
- sender: { role: 'tool' },
176
- blocks: toolResults,
177
- }),
178
- );
179
- } while (true);
180
-
181
- log('done', { pending: this._pending.length });
182
- return this._pending;
183
- }).pipe(this._semaphore.withPermits(1), Effect.withSpan('AiSession.run'));
184
-
185
- /**
186
- * @deprecated
187
- */
188
- // TODO(burdon): Implement or remove.
189
- async runStructured<S extends Schema.Schema.AnyNoContext>(
190
- _schema: S,
191
- _options: AiSessionRunParams<any>,
192
- ): Promise<Schema.Schema.Type<S>> {
193
- return todo();
194
- // const parser = structuredOutputParser(schema);
195
- // const result = await this.run({
196
- // ...options,
197
- // executableTools: [...(options.executableTools ?? []), parser.tool],
198
- // });
199
- // return parser.getResult(result);
200
- }
201
- }
202
-
203
- const createSnippet = (text: string, len = 32) =>
204
- text.length <= len * 2 ? text : [text.slice(0, len), '...', text.slice(-len)].join('');
205
-
206
- // TODO(dmaretskyi): Extract as a general util.
207
- const logDump = (message: string, data: unknown) => {
208
- // eslint-disable-next-line @typescript-eslint/no-require-imports
209
- const { writeFileSync } = require('node:fs');
210
- const path = `/tmp/log-data-${Date.now()}.json`;
211
- writeFileSync(path, JSON.stringify(data, null, 2));
212
- log.info(message, { path });
213
- };