@dxos/assistant-toolkit 0.8.4-main.2c6827d → 0.8.4-main.3eb6e50203

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 (219) hide show
  1. package/dist/lib/neutral/chunk-J5LGTIGS.mjs +10 -0
  2. package/dist/lib/neutral/chunk-J5LGTIGS.mjs.map +7 -0
  3. package/dist/lib/{browser → neutral}/index.mjs +1410 -480
  4. package/dist/lib/neutral/index.mjs.map +7 -0
  5. package/dist/lib/neutral/meta.json +1 -0
  6. package/dist/lib/neutral/testing/index.mjs +44 -0
  7. package/dist/lib/neutral/testing/index.mjs.map +7 -0
  8. package/dist/types/src/blueprints/design/design-blueprint.d.ts +17 -3
  9. package/dist/types/src/blueprints/design/design-blueprint.d.ts.map +1 -1
  10. package/dist/types/src/blueprints/design/index.d.ts +1 -1
  11. package/dist/types/src/blueprints/design/index.d.ts.map +1 -1
  12. package/dist/types/src/blueprints/discord/discord-blueprint.d.ts +13 -13
  13. package/dist/types/src/blueprints/discord/discord-blueprint.d.ts.map +1 -1
  14. package/dist/types/src/blueprints/discord/index.d.ts +1 -1
  15. package/dist/types/src/blueprints/discord/index.d.ts.map +1 -1
  16. package/dist/types/src/blueprints/index.d.ts +1 -0
  17. package/dist/types/src/blueprints/index.d.ts.map +1 -1
  18. package/dist/types/src/blueprints/linear/index.d.ts +1 -1
  19. package/dist/types/src/blueprints/linear/index.d.ts.map +1 -1
  20. package/dist/types/src/blueprints/linear/linear-blueprint.d.ts +13 -13
  21. package/dist/types/src/blueprints/linear/linear-blueprint.d.ts.map +1 -1
  22. package/dist/types/src/blueprints/markdown/index.d.ts +3 -0
  23. package/dist/types/src/blueprints/markdown/index.d.ts.map +1 -0
  24. package/dist/types/src/blueprints/markdown/markdown-blueprint.d.ts +18 -0
  25. package/dist/types/src/blueprints/markdown/markdown-blueprint.d.ts.map +1 -0
  26. package/dist/types/src/blueprints/planning/index.d.ts +1 -1
  27. package/dist/types/src/blueprints/planning/index.d.ts.map +1 -1
  28. package/dist/types/src/blueprints/planning/planning-blueprint.d.ts +17 -3
  29. package/dist/types/src/blueprints/planning/planning-blueprint.d.ts.map +1 -1
  30. package/dist/types/src/blueprints/research/index.d.ts +1 -1
  31. package/dist/types/src/blueprints/research/index.d.ts.map +1 -1
  32. package/dist/types/src/blueprints/research/research-blueprint.d.ts +17 -3
  33. package/dist/types/src/blueprints/research/research-blueprint.d.ts.map +1 -1
  34. package/dist/types/src/blueprints/testing.d.ts +2 -4
  35. package/dist/types/src/blueprints/testing.d.ts.map +1 -1
  36. package/dist/types/src/blueprints/websearch/index.d.ts +1 -1
  37. package/dist/types/src/blueprints/websearch/index.d.ts.map +1 -1
  38. package/dist/types/src/blueprints/websearch/websearch-blueprint.d.ts +17 -3
  39. package/dist/types/src/blueprints/websearch/websearch-blueprint.d.ts.map +1 -1
  40. package/dist/types/src/chat/Chat.d.ts +31 -0
  41. package/dist/types/src/chat/Chat.d.ts.map +1 -0
  42. package/dist/types/src/chat/index.d.ts +2 -0
  43. package/dist/types/src/chat/index.d.ts.map +1 -0
  44. package/dist/types/src/crud/graph.d.ts +14 -11
  45. package/dist/types/src/crud/graph.d.ts.map +1 -1
  46. package/dist/types/src/functions/agent/prompt.d.ts +71 -4
  47. package/dist/types/src/functions/agent/prompt.d.ts.map +1 -1
  48. package/dist/types/src/functions/document/create.d.ts +6 -0
  49. package/dist/types/src/functions/document/create.d.ts.map +1 -0
  50. package/dist/types/src/functions/document/index.d.ts +20 -3
  51. package/dist/types/src/functions/document/index.d.ts.map +1 -1
  52. package/dist/types/src/functions/document/read.d.ts +8 -1
  53. package/dist/types/src/functions/document/read.d.ts.map +1 -1
  54. package/dist/types/src/functions/document/update.d.ts +8 -1
  55. package/dist/types/src/functions/document/update.d.ts.map +1 -1
  56. package/dist/types/src/functions/entity-extraction/entity-extraction.d.ts +125 -124
  57. package/dist/types/src/functions/entity-extraction/entity-extraction.d.ts.map +1 -1
  58. package/dist/types/src/functions/entity-extraction/index.d.ts +125 -124
  59. package/dist/types/src/functions/entity-extraction/index.d.ts.map +1 -1
  60. package/dist/types/src/functions/exa/data/exa-search-1748337321991.d.ts.map +1 -0
  61. package/dist/types/src/functions/exa/data/exa-search-1748337331526.d.ts.map +1 -0
  62. package/dist/types/src/functions/exa/data/exa-search-1748337344119.d.ts.map +1 -0
  63. package/dist/types/src/functions/exa/data/index.d.ts.map +1 -0
  64. package/dist/types/src/functions/github/fetch-prs.d.ts.map +1 -1
  65. package/dist/types/src/functions/linear/index.d.ts +1 -1
  66. package/dist/types/src/functions/linear/sync-issues.d.ts +1 -1
  67. package/dist/types/src/functions/linear/sync-issues.d.ts.map +1 -1
  68. package/dist/types/src/functions/research/document-create.d.ts +1 -1
  69. package/dist/types/src/functions/research/document-create.d.ts.map +1 -1
  70. package/dist/types/src/functions/research/index.d.ts +2 -2
  71. package/dist/types/src/functions/research/research-graph.d.ts +9 -8
  72. package/dist/types/src/functions/research/research-graph.d.ts.map +1 -1
  73. package/dist/types/src/functions/research/research.d.ts +1 -1
  74. package/dist/types/src/functions/research/research.d.ts.map +1 -1
  75. package/dist/types/src/functions/research/types.d.ts +1 -1
  76. package/dist/types/src/functions/research/types.d.ts.map +1 -1
  77. package/dist/types/src/functions/tasks/index.d.ts +16 -2
  78. package/dist/types/src/functions/tasks/index.d.ts.map +1 -1
  79. package/dist/types/src/functions/tasks/read.d.ts +8 -1
  80. package/dist/types/src/functions/tasks/read.d.ts.map +1 -1
  81. package/dist/types/src/functions/tasks/update.d.ts +8 -1
  82. package/dist/types/src/functions/tasks/update.d.ts.map +1 -1
  83. package/dist/types/src/index.d.ts +4 -2
  84. package/dist/types/src/index.d.ts.map +1 -1
  85. package/dist/types/src/initiative/Initiative.d.ts +41 -0
  86. package/dist/types/src/initiative/Initiative.d.ts.map +1 -0
  87. package/dist/types/src/initiative/blueprint.d.ts +153 -0
  88. package/dist/types/src/initiative/blueprint.d.ts.map +1 -0
  89. package/dist/types/src/initiative/functions/addArtifact.d.ts +6 -0
  90. package/dist/types/src/initiative/functions/addArtifact.d.ts.map +1 -0
  91. package/dist/types/src/initiative/functions/agent.d.ts +62 -0
  92. package/dist/types/src/initiative/functions/agent.d.ts.map +1 -0
  93. package/dist/types/src/initiative/functions/getContext.d.ts +13 -0
  94. package/dist/types/src/initiative/functions/getContext.d.ts.map +1 -0
  95. package/dist/types/src/initiative/functions/index.d.ts +5 -0
  96. package/dist/types/src/initiative/functions/index.d.ts.map +1 -0
  97. package/dist/types/src/initiative/functions/qualifier.d.ts +60 -0
  98. package/dist/types/src/initiative/functions/qualifier.d.ts.map +1 -0
  99. package/dist/types/src/initiative/index.d.ts +6 -0
  100. package/dist/types/src/initiative/index.d.ts.map +1 -0
  101. package/dist/types/src/initiative/initiative.test.d.ts +2 -0
  102. package/dist/types/src/initiative/initiative.test.d.ts.map +1 -0
  103. package/dist/types/src/initiative/plan.d.ts +77 -0
  104. package/dist/types/src/initiative/plan.d.ts.map +1 -0
  105. package/dist/types/src/initiative/util.d.ts +29 -0
  106. package/dist/types/src/initiative/util.d.ts.map +1 -0
  107. package/dist/types/src/planning/blueprint.d.ts +18 -0
  108. package/dist/types/src/planning/blueprint.d.ts.map +1 -0
  109. package/dist/types/src/planning/functions/index.d.ts +2 -0
  110. package/dist/types/src/planning/functions/index.d.ts.map +1 -0
  111. package/dist/types/src/planning/functions/update-tasks.d.ts +9 -0
  112. package/dist/types/src/planning/functions/update-tasks.d.ts.map +1 -0
  113. package/dist/types/src/planning/index.d.ts +3 -0
  114. package/dist/types/src/planning/index.d.ts.map +1 -0
  115. package/dist/types/src/sync/sync.d.ts +3 -3
  116. package/dist/types/src/sync/sync.d.ts.map +1 -1
  117. package/dist/types/src/testing/index.d.ts +1 -1
  118. package/dist/types/src/testing/index.d.ts.map +1 -1
  119. package/dist/types/src/testing/plugins.d.ts +19 -0
  120. package/dist/types/src/testing/plugins.d.ts.map +1 -0
  121. package/dist/types/src/toolkits/AssistantToolkit.d.ts +31 -5
  122. package/dist/types/src/toolkits/AssistantToolkit.d.ts.map +1 -1
  123. package/dist/types/src/toolkits/SystemToolkit.d.ts +42 -10
  124. package/dist/types/src/toolkits/SystemToolkit.d.ts.map +1 -1
  125. package/dist/types/src/toolkits/WebToolkit.d.ts +38 -0
  126. package/dist/types/src/toolkits/WebToolkit.d.ts.map +1 -0
  127. package/dist/types/src/toolkits/index.d.ts +1 -0
  128. package/dist/types/src/toolkits/index.d.ts.map +1 -1
  129. package/dist/types/tsconfig.tsbuildinfo +1 -1
  130. package/package.json +45 -40
  131. package/src/blueprints/design/design-blueprint.test.ts +14 -17
  132. package/src/blueprints/design/design-blueprint.ts +2 -4
  133. package/src/blueprints/design/index.ts +1 -1
  134. package/src/blueprints/discord/discord-blueprint.ts +2 -4
  135. package/src/blueprints/discord/index.ts +1 -1
  136. package/src/blueprints/index.ts +1 -0
  137. package/src/blueprints/linear/index.ts +1 -1
  138. package/src/blueprints/linear/linear-blueprint.ts +2 -4
  139. package/src/blueprints/markdown/index.ts +7 -0
  140. package/src/blueprints/markdown/markdown-blueprint.ts +24 -0
  141. package/src/blueprints/planning/index.ts +1 -1
  142. package/src/blueprints/planning/planning-blueprint.test.ts +12 -16
  143. package/src/blueprints/planning/planning-blueprint.ts +2 -4
  144. package/src/blueprints/research/index.ts +1 -1
  145. package/src/blueprints/research/research-blueprint.ts +2 -4
  146. package/src/blueprints/testing.ts +2 -6
  147. package/src/blueprints/websearch/index.ts +2 -1
  148. package/src/blueprints/websearch/websearch-blueprint.ts +2 -4
  149. package/src/chat/Chat.ts +45 -0
  150. package/src/chat/index.ts +5 -0
  151. package/src/crud/graph.test.ts +6 -29
  152. package/src/crud/graph.ts +32 -40
  153. package/src/experimental/feed.test.ts +4 -9
  154. package/src/functions/agent/prompt.ts +15 -13
  155. package/src/functions/discord/fetch-messages.test.ts +4 -8
  156. package/src/functions/discord/fetch-messages.ts +1 -1
  157. package/src/functions/document/create.ts +29 -0
  158. package/src/functions/document/index.ts +2 -1
  159. package/src/functions/document/read.ts +11 -8
  160. package/src/functions/document/update.ts +9 -7
  161. package/src/functions/entity-extraction/entity-extraction.conversations.json +1 -1
  162. package/src/functions/entity-extraction/entity-extraction.test.ts +11 -29
  163. package/src/functions/entity-extraction/entity-extraction.ts +41 -24
  164. package/src/functions/exa/mock.ts +1 -1
  165. package/src/functions/github/fetch-prs.ts +3 -2
  166. package/src/functions/linear/linear.test.ts +18 -43
  167. package/src/functions/linear/sync-issues.ts +9 -7
  168. package/src/functions/research/document-create.ts +9 -11
  169. package/src/functions/research/research-graph.ts +13 -11
  170. package/src/functions/research/research.conversations.json +1 -1
  171. package/src/functions/research/research.test.ts +29 -64
  172. package/src/functions/research/research.ts +15 -23
  173. package/src/functions/research/types.ts +3 -3
  174. package/src/functions/tasks/read.ts +6 -6
  175. package/src/functions/tasks/update.ts +6 -6
  176. package/src/index.ts +4 -2
  177. package/src/initiative/Initiative.ts +61 -0
  178. package/src/initiative/blueprint.ts +60 -0
  179. package/src/initiative/functions/addArtifact.ts +41 -0
  180. package/src/initiative/functions/agent.ts +77 -0
  181. package/src/initiative/functions/getContext.ts +62 -0
  182. package/src/initiative/functions/index.ts +8 -0
  183. package/src/initiative/functions/qualifier.ts +98 -0
  184. package/src/initiative/index.ts +9 -0
  185. package/src/initiative/initiative.test.ts +584 -0
  186. package/src/initiative/plan.ts +107 -0
  187. package/src/initiative/util.ts +137 -0
  188. package/src/planning/blueprint.ts +14 -0
  189. package/src/planning/functions/index.ts +5 -0
  190. package/src/planning/functions/update-tasks.ts +168 -0
  191. package/src/planning/index.ts +6 -0
  192. package/src/sync/sync.ts +38 -30
  193. package/src/testing/index.ts +1 -1
  194. package/src/{plugins.tsx → testing/plugins.tsx} +14 -13
  195. package/src/toolkits/AssistantToolkit.conversations.json +1 -1
  196. package/src/toolkits/AssistantToolkit.test.ts +27 -43
  197. package/src/toolkits/AssistantToolkit.ts +31 -8
  198. package/src/toolkits/SystemToolkit.ts +100 -32
  199. package/src/toolkits/WebToolkit.ts +34 -0
  200. package/src/toolkits/index.ts +1 -0
  201. package/dist/lib/browser/index.mjs.map +0 -7
  202. package/dist/lib/browser/meta.json +0 -1
  203. package/dist/lib/node-esm/index.mjs +0 -2779
  204. package/dist/lib/node-esm/index.mjs.map +0 -7
  205. package/dist/lib/node-esm/meta.json +0 -1
  206. package/dist/types/src/plugins.d.ts +0 -19
  207. package/dist/types/src/plugins.d.ts.map +0 -1
  208. package/dist/types/src/testing/data/exa-search-1748337321991.d.ts.map +0 -1
  209. package/dist/types/src/testing/data/exa-search-1748337331526.d.ts.map +0 -1
  210. package/dist/types/src/testing/data/exa-search-1748337344119.d.ts.map +0 -1
  211. package/dist/types/src/testing/data/index.d.ts.map +0 -1
  212. /package/dist/types/src/{testing → functions/exa}/data/exa-search-1748337321991.d.ts +0 -0
  213. /package/dist/types/src/{testing → functions/exa}/data/exa-search-1748337331526.d.ts +0 -0
  214. /package/dist/types/src/{testing → functions/exa}/data/exa-search-1748337344119.d.ts +0 -0
  215. /package/dist/types/src/{testing → functions/exa}/data/index.d.ts +0 -0
  216. /package/src/{testing → functions/exa}/data/exa-search-1748337321991.ts +0 -0
  217. /package/src/{testing → functions/exa}/data/exa-search-1748337331526.ts +0 -0
  218. /package/src/{testing → functions/exa}/data/exa-search-1748337344119.ts +0 -0
  219. /package/src/{testing → functions/exa}/data/index.ts +0 -0
@@ -2,16 +2,16 @@
2
2
  // Copyright 2025 DXOS.org
3
3
  //
4
4
 
5
- import * as Toolkit from '@effect/ai/Toolkit';
6
5
  import * as Effect from 'effect/Effect';
7
6
  import * as Layer from 'effect/Layer';
8
7
  import * as Predicate from 'effect/Predicate';
9
8
  import * as Schema from 'effect/Schema';
10
9
 
11
10
  import { AiService } from '@dxos/ai';
12
- import { AiSession, makeToolExecutionServiceFromFunctions, makeToolResolverFromFunctions } from '@dxos/assistant';
13
- import { Filter, Obj, Ref } from '@dxos/echo';
14
- import { DatabaseService, defineFunction } from '@dxos/functions';
11
+ import { AiSession, GenericToolkit, ToolExecutionServices } from '@dxos/assistant';
12
+ import { Filter, Obj, Ref, Type } from '@dxos/echo';
13
+ import { Database } from '@dxos/echo';
14
+ import { defineFunction } from '@dxos/functions';
15
15
  import { FunctionInvocationServiceLayerTest } from '@dxos/functions-runtime/testing';
16
16
  import { type DXN } from '@dxos/keys';
17
17
  import { log } from '@dxos/log';
@@ -26,14 +26,18 @@ export default defineFunction({
26
26
  name: 'Entity Extraction',
27
27
  description: 'Extracts entities from emails and transcripts.',
28
28
  inputSchema: Schema.Struct({
29
- source: Message.Message.annotations({ description: 'Email or transcript to extract entities from.' }),
29
+ source: Message.Message.annotations({
30
+ description: 'Email or transcript to extract entities from.',
31
+ }),
30
32
 
31
33
  // TODO(dmaretskyi): Consider making this an array of blueprints instead.
32
- instructions: Schema.optional(Schema.String).annotations({ description: 'Instructions extraction process.' }),
34
+ instructions: Schema.optional(Schema.String).annotations({
35
+ description: 'Instructions extraction process.',
36
+ }),
33
37
  }),
34
38
  outputSchema: Schema.Struct({
35
39
  entities: Schema.optional(
36
- Schema.Array(Obj.Any).annotations({
40
+ Schema.Array(Type.Obj).annotations({
37
41
  description: 'Extracted entities.',
38
42
  }),
39
43
  ),
@@ -46,7 +50,9 @@ export default defineFunction({
46
50
 
47
51
  if (contact && !contact.organization) {
48
52
  const created: DXN[] = [];
49
- const GraphWriterToolkit = makeGraphWriterToolkit({ schema: [LegacyOrganization] }).pipe();
53
+ const GraphWriterToolkit = makeGraphWriterToolkit({
54
+ schema: [LegacyOrganization],
55
+ }).pipe();
50
56
  const GraphWriterHandler = makeGraphWriterHandler(GraphWriterToolkit, {
51
57
  onAppend: (dxns) => created.push(...dxns),
52
58
  });
@@ -67,10 +73,15 @@ export default defineFunction({
67
73
  if (created.length > 1) {
68
74
  throw new Error('Multiple organizations created');
69
75
  } else if (created.length === 1) {
70
- organization = yield* DatabaseService.resolve(created[0], Organization.Organization);
71
- Obj.getMeta(organization).tags ??= [];
72
- Obj.getMeta(organization).tags!.push(...(tags ?? []));
73
- contact.organization = Ref.make(organization);
76
+ organization = yield* Database.resolve(created[0], Organization.Organization);
77
+ Obj.change(organization, (org) => {
78
+ const meta = Obj.getMeta(org);
79
+ meta.tags ??= [];
80
+ meta.tags.push(...(tags ?? []));
81
+ });
82
+ Obj.change(contact, (c) => {
83
+ c.organization = Ref.make(organization!);
84
+ });
74
85
  }
75
86
  }
76
87
 
@@ -81,19 +92,18 @@ export default defineFunction({
81
92
  Effect.provide(
82
93
  Layer.mergeAll(
83
94
  AiService.model('@anthropic/claude-sonnet-4-0'), // TODO(dmaretskyi): Extract.
84
- makeToolResolverFromFunctions([], Toolkit.make()),
85
- makeToolExecutionServiceFromFunctions(Toolkit.make() as any, Layer.empty as any),
95
+ ToolExecutionServices,
86
96
  ).pipe(
87
97
  Layer.provide(
88
98
  // TODO(dmaretskyi): This should be provided by environment.
89
- Layer.mergeAll(FunctionInvocationServiceLayerTest()),
99
+ Layer.mergeAll(GenericToolkit.providerEmpty, FunctionInvocationServiceLayerTest()),
90
100
  ),
91
101
  ),
92
102
  ),
93
103
  ),
94
104
  });
95
105
 
96
- const extractContact = Effect.fn('extractContact')(function* (actor: Actor.Actor, tags?: string[]) {
106
+ const extractContact = Effect.fn('extractContact')(function* (actor: Actor.Actor, tags?: readonly string[]) {
97
107
  const name = actor.name;
98
108
  const email = actor.email;
99
109
  if (!email) {
@@ -101,12 +111,12 @@ const extractContact = Effect.fn('extractContact')(function* (actor: Actor.Actor
101
111
  return undefined;
102
112
  }
103
113
 
104
- const { objects: existingContacts } = yield* DatabaseService.runQuery(Filter.type(Person.Person));
114
+ const existingContacts = yield* Database.runQuery(Filter.type(Person.Person));
105
115
 
106
116
  // Check for existing contact
107
117
  // TODO(dmaretskyi): Query filter DSL - https://linear.app/dxos/issue/DX-541/filtercontains-should-work-with-partial-objects
108
118
  const existingContact = existingContacts.find((contact) =>
109
- contact.emails?.some((contactEmail: any) => contactEmail.value === email),
119
+ contact.emails?.some((contactEmail) => contactEmail.value === email),
110
120
  );
111
121
 
112
122
  if (existingContact) {
@@ -115,13 +125,15 @@ const extractContact = Effect.fn('extractContact')(function* (actor: Actor.Actor
115
125
  }
116
126
 
117
127
  const newContact = Obj.make(Person.Person, {
118
- [Obj.Meta]: { tags },
128
+ ...(tags ? { [Obj.Meta]: { tags: [...tags] } } : {}),
119
129
  emails: [{ value: email }],
120
130
  });
121
- yield* DatabaseService.add(newContact);
131
+ yield* Database.add(newContact);
122
132
 
123
133
  if (name) {
124
- newContact.fullName = name;
134
+ Obj.change(newContact, (c) => {
135
+ c.fullName = name;
136
+ });
125
137
  }
126
138
 
127
139
  const emailDomain = email.split('@')[1]?.toLowerCase();
@@ -132,7 +144,7 @@ const extractContact = Effect.fn('extractContact')(function* (actor: Actor.Actor
132
144
 
133
145
  log.info('extracted email domain', { emailDomain });
134
146
 
135
- const { objects: existingOrganisations } = yield* DatabaseService.runQuery(Filter.type(Organization.Organization));
147
+ const existingOrganisations = yield* Database.runQuery(Filter.type(Organization.Organization));
136
148
  const matchingOrg = existingOrganisations.find((org) => {
137
149
  if (org.website) {
138
150
  try {
@@ -148,7 +160,10 @@ const extractContact = Effect.fn('extractContact')(function* (actor: Actor.Actor
148
160
  emailDomain.endsWith(`.${websiteDomain}`)
149
161
  );
150
162
  } catch (e) {
151
- log.warn('Error parsing website URL', { website: org.website, error: e });
163
+ log.warn('Error parsing website URL', {
164
+ website: org.website,
165
+ error: e,
166
+ });
152
167
  return false;
153
168
  }
154
169
  }
@@ -157,7 +172,9 @@ const extractContact = Effect.fn('extractContact')(function* (actor: Actor.Actor
157
172
 
158
173
  if (matchingOrg) {
159
174
  log.info('found matching organization', { organization: matchingOrg });
160
- newContact.organization = Ref.make(matchingOrg);
175
+ Obj.change(newContact, (c) => {
176
+ c.organization = Ref.make(matchingOrg);
177
+ });
161
178
  }
162
179
 
163
180
  return newContact;
@@ -7,7 +7,7 @@ import * as Schema from 'effect/Schema';
7
7
 
8
8
  import { defineFunction } from '@dxos/functions';
9
9
 
10
- import { SEARCH_RESULTS } from '../../testing';
10
+ import { SEARCH_RESULTS } from './data';
11
11
 
12
12
  export default defineFunction({
13
13
  key: 'dxos.org/function/exa-mock',
@@ -6,7 +6,7 @@ import * as HttpClient from '@effect/platform/HttpClient';
6
6
  import * as Effect from 'effect/Effect';
7
7
  import * as Schema from 'effect/Schema';
8
8
 
9
- import { defineFunction, withAuthorization } from '@dxos/functions';
9
+ import { CredentialsService, defineFunction, withAuthorization } from '@dxos/functions';
10
10
 
11
11
  export default defineFunction({
12
12
  key: 'dxos.org/function/github/fetch-prs',
@@ -21,7 +21,8 @@ export default defineFunction({
21
21
  }),
22
22
  }),
23
23
  handler: Effect.fnUntraced(function* ({ data }) {
24
- const client = yield* HttpClient.HttpClient.pipe(Effect.map(withAuthorization({ service: 'github.com' })));
24
+ const credential = yield* CredentialsService.getCredential({ service: 'github.com' });
25
+ const client = yield* HttpClient.HttpClient.pipe(Effect.map(withAuthorization(credential.apiKey!)));
25
26
 
26
27
  const response = yield* client.get(`https://api.github.com/repos/${data.owner}/${data.repo}/pulls`);
27
28
  const json: any = yield* response.json;
@@ -2,82 +2,57 @@
2
2
  // Copyright 2025 DXOS.org
3
3
  //
4
4
 
5
- import * as Toolkit from '@effect/ai/Toolkit';
6
- import * as FetchHttpClient from '@effect/platform/FetchHttpClient';
7
5
  import { describe, it } from '@effect/vitest';
8
- import * as Config from 'effect/Config';
9
6
  import * as Effect from 'effect/Effect';
10
- import * as Layer from 'effect/Layer';
11
7
 
12
- import { AiService } from '@dxos/ai';
13
- import { AiServiceTestingPreset } from '@dxos/ai/testing';
14
- import { makeToolExecutionServiceFromFunctions, makeToolResolverFromFunctions } from '@dxos/assistant';
8
+ import { AssistantTestLayer } from '@dxos/assistant/testing';
15
9
  import { Obj, Query } from '@dxos/echo';
16
- import { TestHelpers } from '@dxos/effect';
17
- import { CredentialsService, DatabaseService, FunctionInvocationService } from '@dxos/functions';
18
- import { TracingServiceExt } from '@dxos/functions-runtime';
19
- import {
20
- FunctionInvocationServiceLayerTestMocked,
21
- TestDatabaseLayer,
22
- testStoragePath,
23
- } from '@dxos/functions-runtime/testing';
24
- import { Person, Project, Task } from '@dxos/types';
10
+ import { Database } from '@dxos/echo';
11
+ import { TestHelpers } from '@dxos/effect/testing';
12
+ import { FunctionInvocationService } from '@dxos/functions';
13
+ import { Person, Pipeline, Task } from '@dxos/types';
25
14
 
26
15
  import { LINEAR_ID_KEY, default as fetchLinearIssues } from './sync-issues';
27
16
 
28
- const TestLayer = Layer.mergeAll(
29
- AiService.model('@anthropic/claude-opus-4-0'),
30
- makeToolResolverFromFunctions([], Toolkit.make()),
31
- makeToolExecutionServiceFromFunctions(Toolkit.make() as any, Layer.empty as any),
32
- ).pipe(
33
- Layer.provideMerge(
34
- Layer.mergeAll(
35
- AiServiceTestingPreset('direct'),
36
- TestDatabaseLayer({
37
- // indexing: { vector: true },
38
- types: [Task.Task, Person.Person, Project.Project],
39
- storagePath: testStoragePath({ name: 'feed-test-13' }),
40
- }),
41
- CredentialsService.layerConfig([{ service: 'linear.app', apiKey: Config.redacted('LINEAR_API_KEY') }]),
42
- FunctionInvocationServiceLayerTestMocked({ functions: [fetchLinearIssues] }).pipe(
43
- Layer.provideMerge(TracingServiceExt.layerLogInfo()),
44
- ),
45
- FetchHttpClient.layer,
46
- ),
47
- ),
48
- );
17
+ const TestLayer = AssistantTestLayer({
18
+ functions: [fetchLinearIssues],
19
+ types: [Task.Task, Person.Person, Pipeline.Pipeline],
20
+ credentials: [{ service: 'linear.app', apiKey: process.env.LINEAR_API_KEY }],
21
+ tracing: 'pretty',
22
+ });
49
23
 
50
- describe('Linear', { timeout: 600_000 }, () => {
24
+ describe.skip('Linear', { timeout: 600_000 }, () => {
51
25
  it.effect(
52
26
  'sync',
53
27
  Effect.fnUntraced(
54
28
  function* (_) {
55
- yield* DatabaseService.flush({ indexes: true });
29
+ yield* Database.flush({ indexes: true });
56
30
 
57
31
  yield* FunctionInvocationService.invokeFunction(fetchLinearIssues, {
58
32
  team: '1127c63a-6f77-4725-9229-50f6cd47321c',
59
33
  });
60
34
 
61
- const { objects: persons } = yield* DatabaseService.runQuery(Query.type(Person.Person));
35
+ const persons = yield* Database.runQuery(Query.type(Person.Person));
62
36
  console.log('people', {
63
37
  count: persons.length,
64
38
  people: persons.map((_) => `(${_.id}) ${Obj.getLabel(_)} [${Obj.getKeys(_, LINEAR_ID_KEY)[0]?.id}]`),
65
39
  });
66
- const { objects: projects } = yield* DatabaseService.runQuery(Query.type(Project.Project));
40
+ const projects = yield* Database.runQuery(Query.type(Pipeline.Pipeline));
67
41
  console.log('projects', {
68
42
  count: projects.length,
69
43
  projects: projects.map((_) => `(${_.id}) ${Obj.getLabel(_)} [${Obj.getKeys(_, LINEAR_ID_KEY)[0]?.id}]`),
70
44
  });
71
- const { objects: tasks } = yield* DatabaseService.runQuery(Query.type(Task.Task));
45
+ const tasks = yield* Database.runQuery(Query.type(Task.Task));
72
46
  console.log('tasks', {
73
47
  count: tasks.length,
74
48
  tasks: tasks.map((_) => `(${_.id}) ${Obj.getLabel(_)} [${Obj.getKeys(_, LINEAR_ID_KEY)[0]?.id}]`),
75
49
  });
76
50
 
77
- yield* DatabaseService.flush({ indexes: true });
51
+ yield* Database.flush({ indexes: true });
78
52
  },
79
53
  Effect.provide(TestLayer),
80
54
  TestHelpers.taggedTest('sync'),
55
+ TestHelpers.provideTestContext,
81
56
  ),
82
57
  );
83
58
  });
@@ -10,9 +10,10 @@ import * as Function from 'effect/Function';
10
10
  import * as Schema from 'effect/Schema';
11
11
 
12
12
  import { Filter, Obj, Query, Ref, type Type } from '@dxos/echo';
13
- import { DatabaseService, defineFunction, withAuthorization } from '@dxos/functions';
13
+ import { Database } from '@dxos/echo';
14
+ import { CredentialsService, defineFunction, withAuthorization } from '@dxos/functions';
14
15
  import { log } from '@dxos/log';
15
- import { Person, Project, Task } from '@dxos/types';
16
+ import { Person, Pipeline, Task } from '@dxos/types';
16
17
 
17
18
  import { syncObjects } from '../../sync';
18
19
  import { graphqlRequestBody } from '../../util';
@@ -35,7 +36,7 @@ query Issues($teamId: String!, $after: DateTimeOrDuration!) {
35
36
  updatedAt
36
37
  description
37
38
  assignee { id, name }
38
- state {
39
+ state {
39
40
  name
40
41
  }
41
42
  project {
@@ -84,7 +85,8 @@ export default defineFunction({
84
85
  }),
85
86
  }),
86
87
  handler: Effect.fnUntraced(function* ({ data }) {
87
- const client = yield* HttpClient.HttpClient.pipe(Effect.map(withAuthorization({ service: 'linear.app' })));
88
+ const credential = yield* CredentialsService.getCredential({ service: 'linear.app' });
89
+ const client = yield* HttpClient.HttpClient.pipe(Effect.map(withAuthorization(credential.apiKey!)));
88
90
 
89
91
  // Get the timestamp that was previosly synced.
90
92
  const after = yield* getLatestUpdateTimestamp(data.team, Task.Task);
@@ -114,8 +116,8 @@ export default defineFunction({
114
116
  const getLatestUpdateTimestamp: (
115
117
  teamId: string,
116
118
  dataType: Type.Obj.Any,
117
- ) => Effect.Effect<string, never, DatabaseService> = Effect.fnUntraced(function* (teamId, dataType) {
118
- const { objects: existingTasks } = yield* DatabaseService.runQuery(
119
+ ) => Effect.Effect<string, never, Database.Service> = Effect.fnUntraced(function* (teamId, dataType) {
120
+ const existingTasks = yield* Database.runQuery(
119
121
  Query.type(dataType).select(Filter.foreignKeys(dataType, [{ source: LINEAR_TEAM_ID_KEY, id: teamId }])),
120
122
  );
121
123
  return Function.pipe(
@@ -170,7 +172,7 @@ const mapLinearIssue = (issue: LinearIssue, { teamId }: { teamId: string }): Tas
170
172
  project: !issue.project
171
173
  ? undefined
172
174
  : Ref.make(
173
- Project.make({
175
+ Pipeline.make({
174
176
  [Obj.Meta]: {
175
177
  keys: [
176
178
  {
@@ -5,9 +5,8 @@
5
5
  import * as Effect from 'effect/Effect';
6
6
  import * as Schema from 'effect/Schema';
7
7
 
8
- import { ArtifactId } from '@dxos/assistant';
9
- import { Obj, Relation } from '@dxos/echo';
10
- import { DatabaseService, TracingService, defineFunction } from '@dxos/functions';
8
+ import { Database, Obj, Relation, Type } from '@dxos/echo';
9
+ import { TracingService, defineFunction } from '@dxos/functions';
11
10
  import { log } from '@dxos/log';
12
11
  import { Markdown } from '@dxos/plugin-markdown/types';
13
12
  import { HasSubject } from '@dxos/types';
@@ -18,7 +17,7 @@ export default defineFunction({
18
17
  name: 'Create research document',
19
18
  description: 'Creates a note summarizing the research.',
20
19
  inputSchema: Schema.Struct({
21
- subject: ArtifactId.annotations({
20
+ subject: Type.Ref(Type.Obj).annotations({
22
21
  description: trim`
23
22
  ID of the object (organization, contact, etc.) for which the research was performed.
24
23
  `,
@@ -34,7 +33,7 @@ export default defineFunction({
34
33
  }),
35
34
  }),
36
35
  outputSchema: Schema.Struct({
37
- document: ArtifactId.annotations({
36
+ document: Schema.String.annotations({
38
37
  description: 'DXN of the created document.',
39
38
  }),
40
39
  }),
@@ -42,14 +41,13 @@ export default defineFunction({
42
41
  log.info('Creating research document', { subject, name, content });
43
42
 
44
43
  // TODO(burdon): Auto flush before and after calling function?
45
- yield* DatabaseService.flush({ indexes: true });
44
+ yield* Database.flush({ indexes: true });
46
45
  yield* TracingService.emitStatus({ message: 'Creating research document...' });
47
46
 
48
- // TODO(burdon): Type check.
49
- const target = (yield* DatabaseService.resolve(ArtifactId.toDXN(subject))) as Obj.Any;
47
+ const target = yield* Database.load(subject);
50
48
 
51
49
  // Create document.
52
- const object = yield* DatabaseService.add(
50
+ const object = yield* Database.add(
53
51
  Markdown.make({
54
52
  name,
55
53
  content,
@@ -57,7 +55,7 @@ export default defineFunction({
57
55
  );
58
56
 
59
57
  // Create relation.
60
- yield* DatabaseService.add(
58
+ yield* Database.add(
61
59
  Relation.make(HasSubject.HasSubject, {
62
60
  [Relation.Source]: object,
63
61
  [Relation.Target]: target,
@@ -65,7 +63,7 @@ export default defineFunction({
65
63
  }),
66
64
  );
67
65
 
68
- yield* DatabaseService.flush({ indexes: true });
66
+ yield* Database.flush({ indexes: true });
69
67
  log.info('Created research document', { subject, object });
70
68
 
71
69
  return {
@@ -7,8 +7,10 @@ import * as Layer from 'effect/Layer';
7
7
  import * as Schema from 'effect/Schema';
8
8
 
9
9
  import { Obj, Query, Ref, Type } from '@dxos/echo';
10
+ import { Database } from '@dxos/echo';
11
+ import { SystemTypeAnnotation } from '@dxos/echo/internal';
10
12
  import { Queue } from '@dxos/echo-db';
11
- import { ContextQueueService, DatabaseService, QueueService } from '@dxos/functions';
13
+ import { ContextQueueService, QueueService } from '@dxos/functions';
12
14
 
13
15
  /**
14
16
  * Container for a set of ephemeral research results.
@@ -16,32 +18,32 @@ import { ContextQueueService, DatabaseService, QueueService } from '@dxos/functi
16
18
  export const ResearchGraph = Schema.Struct({
17
19
  queue: Type.Ref(Queue),
18
20
  }).pipe(
19
- Type.Obj({
21
+ Type.object({
20
22
  typename: 'dxos.org/type/ResearchGraph',
21
23
  version: '0.1.0',
22
24
  }),
25
+ SystemTypeAnnotation.set(true),
23
26
  );
24
27
 
25
28
  export interface ResearchGraph extends Schema.Schema.Type<typeof ResearchGraph> {}
26
29
 
27
- export const queryResearchGraph: () => Effect.Effect<ResearchGraph | undefined, never, DatabaseService> = Effect.fn(
30
+ export const queryResearchGraph: () => Effect.Effect<ResearchGraph | undefined, never, Database.Service> = Effect.fn(
28
31
  'queryResearchGraph',
29
32
  )(function* () {
30
- const { objects } = yield* DatabaseService.runQuery(Query.type(ResearchGraph));
33
+ const objects = yield* Database.runQuery(Query.type(ResearchGraph));
31
34
  return objects.at(0);
32
35
  });
33
36
 
34
- export const createResearchGraph: () => Effect.Effect<ResearchGraph, never, DatabaseService | QueueService> = Effect.fn(
35
- 'createResearchGraph',
36
- )(function* () {
37
- const queue = yield* QueueService.createQueue();
38
- return yield* DatabaseService.add(Obj.make(ResearchGraph, { queue: Ref.fromDXN(queue.dxn) }));
39
- });
37
+ export const createResearchGraph: () => Effect.Effect<ResearchGraph, never, Database.Service | QueueService> =
38
+ Effect.fn('createResearchGraph')(function* () {
39
+ const queue = yield* QueueService.createQueue();
40
+ return yield* Database.add(Obj.make(ResearchGraph, { queue: Ref.fromDXN(queue.dxn) }));
41
+ });
40
42
 
41
43
  export const contextQueueLayerFromResearchGraph = Layer.unwrapEffect(
42
44
  Effect.gen(function* () {
43
45
  const researchGraph = (yield* queryResearchGraph()) ?? (yield* createResearchGraph());
44
- const researchQueue = yield* DatabaseService.load(researchGraph.queue);
46
+ const researchQueue = yield* Database.load(researchGraph.queue);
45
47
  return ContextQueueService.layer(researchQueue);
46
48
  }),
47
49
  );