@dxos/assistant 0.8.4-main.f9ba587 → 0.8.4-main.fcfe5033a5

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 (233) hide show
  1. package/README.md +1 -0
  2. package/dist/lib/neutral/chunk-2TBLG3XY.mjs +1793 -0
  3. package/dist/lib/neutral/chunk-2TBLG3XY.mjs.map +7 -0
  4. package/dist/lib/neutral/chunk-J5LGTIGS.mjs +10 -0
  5. package/dist/lib/neutral/chunk-J5LGTIGS.mjs.map +7 -0
  6. package/dist/lib/neutral/extraction/index.mjs +219 -0
  7. package/dist/lib/neutral/extraction/index.mjs.map +7 -0
  8. package/dist/lib/neutral/index.mjs +537 -0
  9. package/dist/lib/neutral/index.mjs.map +7 -0
  10. package/dist/lib/neutral/meta.json +1 -0
  11. package/dist/lib/neutral/testing/index.mjs +111 -0
  12. package/dist/lib/neutral/testing/index.mjs.map +7 -0
  13. package/dist/types/src/conversation/context.d.ts +155 -0
  14. package/dist/types/src/conversation/context.d.ts.map +1 -0
  15. package/dist/types/src/conversation/context.test.d.ts +2 -0
  16. package/dist/types/src/conversation/context.test.d.ts.map +1 -0
  17. package/dist/types/src/conversation/index.d.ts +2 -1
  18. package/dist/types/src/conversation/index.d.ts.map +1 -1
  19. package/dist/types/src/conversation/session.d.ts +78 -0
  20. package/dist/types/src/conversation/session.d.ts.map +1 -0
  21. package/dist/types/src/conversation/session.test.d.ts.map +1 -0
  22. package/dist/types/src/diff.d.ts +17 -0
  23. package/dist/types/src/diff.d.ts.map +1 -0
  24. package/dist/types/src/diff.test.d.ts +2 -0
  25. package/dist/types/src/diff.test.d.ts.map +1 -0
  26. package/dist/types/src/errors.d.ts +67 -0
  27. package/dist/types/src/errors.d.ts.map +1 -0
  28. package/dist/types/src/execution-graph.d.ts +85 -0
  29. package/dist/types/src/execution-graph.d.ts.map +1 -0
  30. package/dist/types/src/execution-graph.test.d.ts +2 -0
  31. package/dist/types/src/execution-graph.test.d.ts.map +1 -0
  32. package/dist/types/src/extraction/extraction-ner-function/index.d.ts +0 -1
  33. package/dist/types/src/extraction/extraction-ner-function/index.d.ts.map +1 -1
  34. package/dist/types/src/extraction/extraction-ner-function/named-entity-recognition.d.ts +1 -1
  35. package/dist/types/src/extraction/extraction-ner-function/named-entity-recognition.d.ts.map +1 -1
  36. package/dist/types/src/extraction/extraction.d.ts +1066 -215
  37. package/dist/types/src/extraction/extraction.d.ts.map +1 -1
  38. package/dist/types/src/extraction/index.d.ts +0 -1
  39. package/dist/types/src/extraction/index.d.ts.map +1 -1
  40. package/dist/types/src/extraction/quotes.d.ts +3 -3
  41. package/dist/types/src/extraction/quotes.d.ts.map +1 -1
  42. package/dist/types/src/functions/index.d.ts +2 -0
  43. package/dist/types/src/functions/index.d.ts.map +1 -0
  44. package/dist/types/src/functions/services.d.ts +17 -0
  45. package/dist/types/src/functions/services.d.ts.map +1 -0
  46. package/dist/types/src/functions.test.d.ts +2 -0
  47. package/dist/types/src/functions.test.d.ts.map +1 -0
  48. package/dist/types/src/index.d.ts +7 -5
  49. package/dist/types/src/index.d.ts.map +1 -1
  50. package/dist/types/src/service/AgentService.d.ts +75 -0
  51. package/dist/types/src/service/AgentService.d.ts.map +1 -0
  52. package/dist/types/src/service/AgentService.test.d.ts +2 -0
  53. package/dist/types/src/service/AgentService.test.d.ts.map +1 -0
  54. package/dist/types/src/service/agent-process.d.ts +21 -0
  55. package/dist/types/src/service/agent-process.d.ts.map +1 -0
  56. package/dist/types/src/service/index.d.ts +3 -0
  57. package/dist/types/src/service/index.d.ts.map +1 -0
  58. package/dist/types/src/session/artifact-diff.d.ts +27 -0
  59. package/dist/types/src/session/artifact-diff.d.ts.map +1 -0
  60. package/dist/types/src/session/error-handling.d.ts +4 -0
  61. package/dist/types/src/session/error-handling.d.ts.map +1 -0
  62. package/dist/types/src/session/format.d.ts +16 -0
  63. package/dist/types/src/session/format.d.ts.map +1 -0
  64. package/dist/types/src/session/format.test.d.ts +2 -0
  65. package/dist/types/src/session/format.test.d.ts.map +1 -0
  66. package/dist/types/src/session/index.d.ts +5 -1
  67. package/dist/types/src/session/index.d.ts.map +1 -1
  68. package/dist/types/src/session/observer.d.ts +23 -0
  69. package/dist/types/src/session/observer.d.ts.map +1 -0
  70. package/dist/types/src/session/request.d.ts +106 -0
  71. package/dist/types/src/session/request.d.ts.map +1 -0
  72. package/dist/types/src/session/request.test.d.ts +2 -0
  73. package/dist/types/src/session/request.test.d.ts.map +1 -0
  74. package/dist/types/src/session/session-ollama.test.d.ts +2 -0
  75. package/dist/types/src/session/session-ollama.test.d.ts.map +1 -0
  76. package/dist/types/src/session/toolkit.d.ts +16 -0
  77. package/dist/types/src/session/toolkit.d.ts.map +1 -0
  78. package/dist/types/src/session/version-pin.d.ts +5 -5
  79. package/dist/types/src/session/version-pin.d.ts.map +1 -1
  80. package/dist/types/src/templates/index.d.ts +2 -0
  81. package/dist/types/src/templates/index.d.ts.map +1 -0
  82. package/dist/types/src/templates/system.d.ts +17 -0
  83. package/dist/types/src/templates/system.d.ts.map +1 -0
  84. package/dist/types/src/testing/index.d.ts +1 -2
  85. package/dist/types/src/testing/index.d.ts.map +1 -1
  86. package/dist/types/src/testing/layer.d.ts +40 -0
  87. package/dist/types/src/testing/layer.d.ts.map +1 -0
  88. package/dist/types/src/tracing.d.ts +223 -0
  89. package/dist/types/src/tracing.d.ts.map +1 -0
  90. package/dist/types/src/types/artifact.d.ts +28 -0
  91. package/dist/types/src/types/artifact.d.ts.map +1 -0
  92. package/dist/types/src/types/index.d.ts +2 -0
  93. package/dist/types/src/types/index.d.ts.map +1 -0
  94. package/dist/types/tsconfig.tsbuildinfo +1 -1
  95. package/package.json +60 -29
  96. package/src/conversation/context.test.ts +52 -0
  97. package/src/conversation/context.ts +403 -0
  98. package/src/conversation/index.ts +2 -1
  99. package/src/conversation/session.test.ts +58 -0
  100. package/src/conversation/session.ts +300 -0
  101. package/src/diff.test.ts +74 -0
  102. package/src/diff.ts +93 -0
  103. package/src/errors.ts +15 -0
  104. package/src/execution-graph.test.ts +740 -0
  105. package/src/execution-graph.ts +509 -0
  106. package/src/extraction/extraction-ner-function/index.ts +0 -1
  107. package/src/extraction/extraction-ner-function/named-entity-recognition.test.ts +12 -6
  108. package/src/extraction/extraction-ner-function/named-entity-recognition.ts +3 -1
  109. package/src/extraction/extraction.ts +44 -15
  110. package/src/extraction/index.ts +0 -1
  111. package/src/extraction/quotes.test.ts +3 -3
  112. package/src/extraction/quotes.ts +6 -7
  113. package/src/functions/index.ts +5 -0
  114. package/src/functions/services.ts +214 -0
  115. package/src/functions.conversations.json +1 -0
  116. package/src/functions.test.ts +88 -0
  117. package/src/index.ts +7 -5
  118. package/src/service/AgentService.conversations.json +1 -0
  119. package/src/service/AgentService.test.ts +169 -0
  120. package/src/service/AgentService.ts +184 -0
  121. package/src/service/agent-process.ts +364 -0
  122. package/src/service/index.ts +6 -0
  123. package/src/session/artifact-diff.ts +41 -0
  124. package/src/session/error-handling.ts +41 -0
  125. package/src/session/format.test.ts +132 -0
  126. package/src/session/format.ts +149 -0
  127. package/src/session/index.ts +5 -1
  128. package/src/session/observer.ts +62 -0
  129. package/src/session/request.conversations.json +1 -0
  130. package/src/session/request.test.ts +195 -0
  131. package/src/session/request.ts +344 -0
  132. package/src/session/session-ollama.test.ts +81 -0
  133. package/src/session/toolkit.ts +47 -0
  134. package/src/session/version-pin.ts +12 -12
  135. package/src/templates/index.ts +5 -0
  136. package/src/templates/instructions/format.tpl +57 -0
  137. package/src/templates/instructions/system.tpl +85 -0
  138. package/src/templates/system.ts +42 -0
  139. package/src/testing/index.ts +2 -8
  140. package/src/testing/layer.ts +236 -0
  141. package/src/tracing.ts +43 -0
  142. package/src/types/artifact.ts +89 -0
  143. package/src/types/index.ts +5 -0
  144. package/src/typings.d.ts +5 -0
  145. package/dist/lib/browser/index.mjs +0 -2019
  146. package/dist/lib/browser/index.mjs.map +0 -7
  147. package/dist/lib/browser/meta.json +0 -1
  148. package/dist/lib/node-esm/index.mjs +0 -2021
  149. package/dist/lib/node-esm/index.mjs.map +0 -7
  150. package/dist/lib/node-esm/meta.json +0 -1
  151. package/dist/types/bin/chat.d.ts +0 -2
  152. package/dist/types/bin/chat.d.ts.map +0 -1
  153. package/dist/types/src/blueprint/blueprint.d.ts +0 -41
  154. package/dist/types/src/blueprint/blueprint.d.ts.map +0 -1
  155. package/dist/types/src/blueprint/index.d.ts +0 -3
  156. package/dist/types/src/blueprint/index.d.ts.map +0 -1
  157. package/dist/types/src/blueprint/registry.d.ts +0 -7
  158. package/dist/types/src/blueprint/registry.d.ts.map +0 -1
  159. package/dist/types/src/context/binder.d.ts +0 -34
  160. package/dist/types/src/context/binder.d.ts.map +0 -1
  161. package/dist/types/src/context/binding.d.ts +0 -38
  162. package/dist/types/src/context/binding.d.ts.map +0 -1
  163. package/dist/types/src/context/index.d.ts +0 -3
  164. package/dist/types/src/context/index.d.ts.map +0 -1
  165. package/dist/types/src/conversation/conversation.d.ts +0 -44
  166. package/dist/types/src/conversation/conversation.d.ts.map +0 -1
  167. package/dist/types/src/extraction/extraction-llm-function/extraction-llm-function.d.ts +0 -4
  168. package/dist/types/src/extraction/extraction-llm-function/extraction-llm-function.d.ts.map +0 -1
  169. package/dist/types/src/extraction/extraction-llm-function/extraction-llm-function.test.d.ts +0 -2
  170. package/dist/types/src/extraction/extraction-llm-function/extraction-llm-function.test.d.ts.map +0 -1
  171. package/dist/types/src/extraction/extraction-llm-function/index.d.ts +0 -2
  172. package/dist/types/src/extraction/extraction-llm-function/index.d.ts.map +0 -1
  173. package/dist/types/src/extraction/extraction-ner-function/extraction-ner-function.d.ts +0 -208
  174. package/dist/types/src/extraction/extraction-ner-function/extraction-ner-function.d.ts.map +0 -1
  175. package/dist/types/src/extraction/extraction-ner-function/extraction-ner-function.test.d.ts +0 -2
  176. package/dist/types/src/extraction/extraction-ner-function/extraction-ner-function.test.d.ts.map +0 -1
  177. package/dist/types/src/research/exa.d.ts +0 -7
  178. package/dist/types/src/research/exa.d.ts.map +0 -1
  179. package/dist/types/src/research/graph.d.ts +0 -41
  180. package/dist/types/src/research/graph.d.ts.map +0 -1
  181. package/dist/types/src/research/graph.test.d.ts +0 -2
  182. package/dist/types/src/research/graph.test.d.ts.map +0 -1
  183. package/dist/types/src/research/index.d.ts +0 -4
  184. package/dist/types/src/research/index.d.ts.map +0 -1
  185. package/dist/types/src/research/research.d.ts +0 -10
  186. package/dist/types/src/research/research.d.ts.map +0 -1
  187. package/dist/types/src/research/research.test.d.ts +0 -2
  188. package/dist/types/src/research/research.test.d.ts.map +0 -1
  189. package/dist/types/src/session/session.d.ts +0 -283
  190. package/dist/types/src/session/session.d.ts.map +0 -1
  191. package/dist/types/src/session/session.test.d.ts.map +0 -1
  192. package/dist/types/src/session/version-pin.test.d.ts +0 -2
  193. package/dist/types/src/session/version-pin.test.d.ts.map +0 -1
  194. package/dist/types/src/summarization/summarization.test.d.ts +0 -2
  195. package/dist/types/src/summarization/summarization.test.d.ts.map +0 -1
  196. package/dist/types/src/testing/exa-search-1748337321991.d.ts +0 -38
  197. package/dist/types/src/testing/exa-search-1748337321991.d.ts.map +0 -1
  198. package/dist/types/src/testing/exa-search-1748337331526.d.ts +0 -37
  199. package/dist/types/src/testing/exa-search-1748337331526.d.ts.map +0 -1
  200. package/dist/types/src/testing/exa-search-1748337344119.d.ts +0 -58
  201. package/dist/types/src/testing/exa-search-1748337344119.d.ts.map +0 -1
  202. package/dist/types/src/types.d.ts +0 -3
  203. package/dist/types/src/types.d.ts.map +0 -1
  204. package/src/blueprint/blueprint.ts +0 -75
  205. package/src/blueprint/index.ts +0 -6
  206. package/src/blueprint/registry.ts +0 -15
  207. package/src/context/binder.ts +0 -101
  208. package/src/context/binding.ts +0 -31
  209. package/src/context/index.ts +0 -6
  210. package/src/conversation/conversation.ts +0 -103
  211. package/src/extraction/extraction-llm-function/extraction-llm-function.test.ts +0 -95
  212. package/src/extraction/extraction-llm-function/extraction-llm-function.ts +0 -66
  213. package/src/extraction/extraction-llm-function/index.ts +0 -5
  214. package/src/extraction/extraction-ner-function/extraction-ner-function.test.ts +0 -115
  215. package/src/extraction/extraction-ner-function/extraction-ner-function.ts +0 -54
  216. package/src/research/exa.ts +0 -100
  217. package/src/research/graph.test.ts +0 -15
  218. package/src/research/graph.ts +0 -337
  219. package/src/research/index.ts +0 -7
  220. package/src/research/instructions-research.tpl +0 -97
  221. package/src/research/research.test.ts +0 -190
  222. package/src/research/research.ts +0 -90
  223. package/src/session/session.test.ts +0 -275
  224. package/src/session/session.ts +0 -582
  225. package/src/session/version-pin.test.ts +0 -26
  226. package/src/summarization/summarization.test.ts +0 -221
  227. package/src/testing/exa-search-1748337321991.ts +0 -131
  228. package/src/testing/exa-search-1748337331526.ts +0 -144
  229. package/src/testing/exa-search-1748337344119.ts +0 -133
  230. package/src/typedefs.d.ts +0 -8
  231. package/src/types.ts +0 -8
  232. /package/dist/types/src/{session → conversation}/session.test.d.ts +0 -0
  233. /package/src/extraction/extraction-llm-function/{instructions.tpl → transcription-instructions.tpl} +0 -0
@@ -0,0 +1,169 @@
1
+ //
2
+ // Copyright 2026 DXOS.org
3
+ //
4
+
5
+ import { Registry } from '@effect-atom/atom';
6
+ import { describe, it } from '@effect/vitest';
7
+ import * as Effect from 'effect/Effect';
8
+ import * as Schema from 'effect/Schema';
9
+ import * as Stream from 'effect/Stream';
10
+ import { expect } from 'vitest';
11
+
12
+ import { Blueprint } from '@dxos/blueprints';
13
+ import { Feed } from '@dxos/echo';
14
+ import { TestHelpers } from '@dxos/effect/testing';
15
+ import { Trace } from '@dxos/functions';
16
+ import { Process } from '@dxos/functions-runtime';
17
+ import { ObjectId } from '@dxos/keys';
18
+ import { log } from '@dxos/log';
19
+ import { Operation, OperationHandlerSet } from '@dxos/operation';
20
+ import { Organization } from '@dxos/types';
21
+ import { trim } from '@dxos/util';
22
+
23
+ import { AssistantTestLayer } from '../testing';
24
+ import { PartialBlock } from '../tracing';
25
+ import * as AgentService from './AgentService';
26
+
27
+ ObjectId.dangerouslyDisableRandomness();
28
+
29
+ //
30
+ // Test data.
31
+ //
32
+
33
+ const TEST_DATA = {
34
+ organizations: [
35
+ Organization.make({
36
+ name: 'Cyberdyne Systems',
37
+ website: 'https://cyberdyne.com',
38
+ }),
39
+ Organization.make({
40
+ name: 'Acme Robotics',
41
+ website: 'https://acmerobotics.example',
42
+ }),
43
+ Organization.make({
44
+ name: 'Globex Research',
45
+ website: 'https://globex.example',
46
+ }),
47
+ ],
48
+ research: {
49
+ 'https://cyberdyne.com': `
50
+ Cyberdyne Systems is a company that builds AI agents.
51
+ They are based in San Francisco, California.
52
+ They were founded in 1984.
53
+ They are a public company.
54
+ They are listed on the NASDAQ under the symbol CYBR.
55
+ They are a member of the S&P 500 index.
56
+ `,
57
+ 'https://acmerobotics.example': `
58
+ Acme Robotics designs industrial automation and collaborative robots.
59
+ They are headquartered in Austin, Texas.
60
+ They were founded in 2010.
61
+ They serve manufacturing and logistics customers worldwide.
62
+ `,
63
+ 'https://globex.example': `
64
+ Globex Research runs applied R&D labs focused on materials science and energy storage.
65
+ They are based in Cambridge, Massachusetts.
66
+ They partner with universities and government grants programs.
67
+ Their flagship product line is solid-state battery prototypes for EVs.
68
+ `,
69
+ } as Record<string, string>,
70
+ };
71
+
72
+ const Research = Operation.make({
73
+ meta: {
74
+ key: 'org.dxos.function.research',
75
+ name: 'Research',
76
+ description: 'Research an organization',
77
+ },
78
+ input: Schema.Struct({
79
+ website: Schema.String.annotations({ description: 'The website of the organization to research' }),
80
+ }),
81
+ output: Schema.String,
82
+ });
83
+
84
+ const handlers = OperationHandlerSet.make(
85
+ Research.pipe(
86
+ Operation.withHandler(
87
+ Effect.fnUntraced(function* ({ website }) {
88
+ log.info('begin research', { website });
89
+ yield* Effect.sleep(
90
+ 15_000 * (TEST_DATA.organizations.findIndex((organization) => organization.website === website) + 1),
91
+ );
92
+ log.info('end research', { website });
93
+ return TEST_DATA.research[website];
94
+ }),
95
+ ),
96
+ ),
97
+ );
98
+
99
+ const ResearchBlueprint = Blueprint.make({
100
+ key: 'org.dxos.blueprint.research',
101
+ name: 'Research',
102
+ tools: Blueprint.toolDefinitions({ operations: [Research] }),
103
+ });
104
+
105
+ //
106
+ // Test layer: AI services + toolkit.
107
+ //
108
+
109
+ const SYSTEM_PROMPT = trim`
110
+ You are reacting to a continuous stream of organizations.
111
+ Research each organization.
112
+ Research takes a while to complete.
113
+ Do not block on the research since there might be more organizations to research, and we want research to happen in parallel.
114
+ Do not wait longer then 3 seconds to keep the conversation open for new events or user queries.
115
+ Do internal reasoning, but only show the answers to the user.
116
+ `;
117
+
118
+ const TestLayer = AssistantTestLayer({
119
+ types: [Organization.Organization, Feed.Feed, Blueprint.Blueprint],
120
+ tracing: 'console',
121
+ aiServicePreset: 'edge-remote',
122
+ operationHandlers: [handlers],
123
+ blueprints: [ResearchBlueprint],
124
+ systemPrompt: SYSTEM_PROMPT,
125
+ });
126
+
127
+ describe('Agent Executable', () => {
128
+ // TODO(dmaretskyi): Figure out how to make it not sleep for 45 seconds.
129
+ it.scoped.skip(
130
+ 'runs AI agent with background tools via process manager',
131
+ Effect.fnUntraced(
132
+ function* (_) {
133
+ const registry = yield* Registry.AtomRegistry;
134
+ const monitor = yield* Process.ProcessMonitorService;
135
+ registry.subscribe(monitor.processTreeAtom, (tree) => {
136
+ console.log(`\n----- Process tree -----\n${Process.prettyProcessTree(tree)}\n-----------------\n`);
137
+ });
138
+
139
+ const agent = yield* AgentService.createSession({
140
+ blueprints: [ResearchBlueprint],
141
+ });
142
+
143
+ let ephemeralEventCount = 0;
144
+ yield* agent.subscribeEphemeral().pipe(
145
+ Stream.runForEach((msg) =>
146
+ Effect.gen(function* () {
147
+ for (const event of msg.events) {
148
+ if (Trace.isOfType(PartialBlock, event)) {
149
+ ephemeralEventCount++;
150
+ }
151
+ }
152
+ }),
153
+ ),
154
+ Effect.fork,
155
+ );
156
+
157
+ for (const org of TEST_DATA.organizations) {
158
+ yield* agent.submitPrompt(JSON.stringify(org));
159
+ }
160
+ yield* agent.submitPrompt('When all research is complete, print 1-sentence summary for each organization.');
161
+ yield* agent.waitForCompletion();
162
+ expect(ephemeralEventCount).toBeGreaterThan(0);
163
+ },
164
+ Effect.provide(TestLayer),
165
+ TestHelpers.provideTestContext,
166
+ ),
167
+ { timeout: 120_000 },
168
+ );
169
+ });
@@ -0,0 +1,184 @@
1
+ //
2
+ // Copyright 2026 DXOS.org
3
+ //
4
+
5
+ // @import-as-namespace
6
+
7
+ import * as Context from 'effect/Context';
8
+ import * as Effect from 'effect/Effect';
9
+ import * as Layer from 'effect/Layer';
10
+ import * as Stream from 'effect/Stream';
11
+
12
+ import { ModelName } from '@dxos/ai';
13
+ import { Blueprint } from '@dxos/blueprints';
14
+ import { Database, Feed, Obj, Ref } from '@dxos/echo';
15
+ import { acquireReleaseResource } from '@dxos/effect';
16
+ import { type Trace } from '@dxos/functions';
17
+ import { ProcessManager } from '@dxos/functions-runtime';
18
+
19
+ import { type McpServerConfig, AiContextBinder } from '../conversation';
20
+ import { AgentProcess } from './agent-process';
21
+
22
+ export interface Service {
23
+ /**
24
+ * Gets or creates a session for a feed.
25
+ */
26
+ getSession: (feed: Feed.Feed, options?: GetSessionOptions) => Effect.Effect<Session>;
27
+ }
28
+
29
+ export class AgentService extends Context.Tag('@dxos/assistant/AgentService')<AgentService, Service>() {}
30
+
31
+ /**
32
+ * Handle to an agent session.
33
+ */
34
+ export interface Session {
35
+ /**
36
+ * The feed that the session is associated with.
37
+ */
38
+ readonly feed: Feed.Feed;
39
+
40
+ /**
41
+ * Submits a prompt to the agent.
42
+ */
43
+ submitPrompt: (prompt: string) => Effect.Effect<void>;
44
+
45
+ /**
46
+ * Wait until agent has completed its work.
47
+ */
48
+ waitForCompletion: () => Effect.Effect<void>;
49
+
50
+ /**
51
+ * Subscribe to ephemeral trace events (e.g., streaming partial messages).
52
+ * Replays buffered events, then streams new ones until the process ends.
53
+ */
54
+ subscribeEphemeral: () => Stream.Stream<Trace.Message>;
55
+
56
+ /**
57
+ * Adds context objects to the agent.
58
+ */
59
+ addContext: (context: Ref.Ref<Obj.Unknown>[]) => Effect.Effect<void, never, Feed.FeedService>;
60
+
61
+ /**
62
+ * Gets the context objects from the agent.
63
+ */
64
+ getContext: () => Effect.Effect<Ref.Ref<Obj.Unknown>[], never, Feed.FeedService>;
65
+ }
66
+
67
+ /**
68
+ * Gets or creates a session for a feed.
69
+ */
70
+ export const getSession = Effect.serviceFunctionEffect(AgentService, (service) => service.getSession);
71
+
72
+ export interface GetSessionOptions {
73
+ readonly model?: ModelName;
74
+ }
75
+
76
+ export interface CreateSessionOptions {
77
+ readonly blueprints?: Blueprint.Blueprint[];
78
+ readonly context?: Ref.Ref<Obj.Unknown>[];
79
+ readonly model?: ModelName;
80
+ }
81
+
82
+ export const createSession: (
83
+ opts?: CreateSessionOptions,
84
+ ) => Effect.Effect<
85
+ Session,
86
+ Blueprint.NotFoundError,
87
+ Database.Service | Feed.FeedService | Blueprint.RegistryService | AgentService
88
+ > = Effect.fn('createSession')(function* (opts) {
89
+ const blueprints = yield* Effect.forEach(opts?.blueprints ?? [], (blueprint) =>
90
+ Blueprint.upsert(blueprint.key).pipe(Effect.map(Ref.make)),
91
+ );
92
+
93
+ const feed = yield* Database.add(Feed.make());
94
+ const runtime = yield* Effect.runtime<Feed.FeedService>();
95
+ const binder = yield* acquireReleaseResource(() => new AiContextBinder({ feed, runtime }));
96
+
97
+ yield* Effect.promise(() =>
98
+ binder.bind({
99
+ blueprints,
100
+ objects: opts?.context ?? [],
101
+ }),
102
+ );
103
+
104
+ return yield* getSession(feed, { model: opts?.model });
105
+ }, Effect.scoped);
106
+
107
+ export const layer = (opts?: {
108
+ systemPrompt?: string;
109
+ /**
110
+ * Default model used by sessions that don't specify one explicitly.
111
+ */
112
+ model?: ModelName;
113
+
114
+ /**
115
+ * Provider for space-level MCP server configs.
116
+ */
117
+ getMcpServers?: () => McpServerConfig[];
118
+ }): Layer.Layer<AgentService, never, ProcessManager.ProcessManagerService> =>
119
+ Layer.effect(
120
+ AgentService,
121
+ Effect.gen(function* () {
122
+ const processManager = yield* ProcessManager.ProcessManagerService;
123
+ const sessionCache = new Map<string, Session>();
124
+
125
+ return {
126
+ getSession: (feed: Feed.Feed, options?: GetSessionOptions) =>
127
+ Effect.gen(function* () {
128
+ const cached = sessionCache.get(feed.id);
129
+ if (cached) {
130
+ return cached;
131
+ }
132
+
133
+ const target = Obj.getDXN(feed).toString();
134
+ const executable = AgentProcess({
135
+ systemPrompt: opts?.systemPrompt,
136
+ model: options?.model ?? opts?.model,
137
+ getMcpServers: opts?.getMcpServers,
138
+ });
139
+ const processes = yield* processManager.list({ target, key: executable.key });
140
+
141
+ let handle: ProcessManager.Handle<string, void>;
142
+ if (processes.length > 0) {
143
+ handle = processes[0];
144
+ } else {
145
+ handle = yield* processManager.spawn(executable, {
146
+ name: 'agent',
147
+ target,
148
+ traceMeta: {
149
+ conversationId: feed.id,
150
+ },
151
+ });
152
+ }
153
+
154
+ const session = makeSession(handle, feed);
155
+ sessionCache.set(feed.id, session);
156
+ return session;
157
+ }),
158
+ };
159
+ }),
160
+ );
161
+
162
+ const makeSession = (process: ProcessManager.Handle<string, void>, feed: Feed.Feed): Session => ({
163
+ feed,
164
+ submitPrompt: (prompt: string) => process.submitInput(prompt),
165
+ waitForCompletion: () => process.runToCompletion(),
166
+ subscribeEphemeral: () => process.subscribeEphemeral(),
167
+ addContext: (context: Ref.Ref<Obj.Unknown>[]) =>
168
+ Effect.gen(function* () {
169
+ const runtime = yield* Effect.runtime<Feed.FeedService>();
170
+ const binder = yield* acquireReleaseResource(() => new AiContextBinder({ feed, runtime }));
171
+ yield* Effect.promise(() =>
172
+ binder.bind({
173
+ blueprints: [],
174
+ objects: context,
175
+ }),
176
+ );
177
+ }).pipe(Effect.scoped),
178
+ getContext: () =>
179
+ Effect.gen(function* () {
180
+ const runtime = yield* Effect.runtime<Feed.FeedService>();
181
+ const binder = yield* acquireReleaseResource(() => new AiContextBinder({ feed, runtime }));
182
+ return binder.getObjects().map((object) => Ref.make(object));
183
+ }).pipe(Effect.scoped),
184
+ });