@dxos/assistant 0.8.1-main.ba2dec9 → 0.8.1-staging.31c3ee1

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 (75) hide show
  1. package/dist/lib/browser/chunk-PND5VR6D.mjs +2315 -0
  2. package/dist/lib/browser/chunk-PND5VR6D.mjs.map +7 -0
  3. package/dist/lib/browser/index.mjs +313 -1631
  4. package/dist/lib/browser/index.mjs.map +4 -4
  5. package/dist/lib/browser/meta.json +1 -1
  6. package/dist/lib/browser/testing/index.mjs +20 -6
  7. package/dist/lib/browser/testing/index.mjs.map +4 -4
  8. package/dist/lib/node/chunk-IBOBRBDF.cjs +2326 -0
  9. package/dist/lib/node/chunk-IBOBRBDF.cjs.map +7 -0
  10. package/dist/lib/node/index.cjs +321 -1629
  11. package/dist/lib/node/index.cjs.map +4 -4
  12. package/dist/lib/node/meta.json +1 -1
  13. package/dist/lib/node/testing/index.cjs +22 -11
  14. package/dist/lib/node/testing/index.cjs.map +4 -4
  15. package/dist/lib/node-esm/chunk-DCQJOLSR.mjs +2317 -0
  16. package/dist/lib/node-esm/chunk-DCQJOLSR.mjs.map +7 -0
  17. package/dist/lib/node-esm/index.mjs +313 -1631
  18. package/dist/lib/node-esm/index.mjs.map +4 -4
  19. package/dist/lib/node-esm/meta.json +1 -1
  20. package/dist/lib/node-esm/testing/index.mjs +20 -6
  21. package/dist/lib/node-esm/testing/index.mjs.map +4 -4
  22. package/dist/types/src/ai-service/defs.d.ts +8 -2
  23. package/dist/types/src/ai-service/defs.d.ts.map +1 -1
  24. package/dist/types/src/ai-service/edge-client.d.ts.map +1 -1
  25. package/dist/types/src/ai-service/message-collector.d.ts +16 -16
  26. package/dist/types/src/ai-service/message-collector.d.ts.map +1 -1
  27. package/dist/types/src/ai-service/ollama-client.d.ts +1 -5
  28. package/dist/types/src/ai-service/ollama-client.d.ts.map +1 -1
  29. package/dist/types/src/ai-service/parser.d.ts +8 -8
  30. package/dist/types/src/ai-service/parser.d.ts.map +1 -1
  31. package/dist/types/src/ai-service/types.d.ts +90 -156
  32. package/dist/types/src/ai-service/types.d.ts.map +1 -1
  33. package/dist/types/src/conversation/conversation.d.ts +8 -8
  34. package/dist/types/src/conversation/conversation.d.ts.map +1 -1
  35. package/dist/types/src/index.d.ts +1 -0
  36. package/dist/types/src/index.d.ts.map +1 -1
  37. package/dist/types/src/session/index.d.ts +2 -0
  38. package/dist/types/src/session/index.d.ts.map +1 -0
  39. package/dist/types/src/session/session.d.ts +216 -0
  40. package/dist/types/src/session/session.d.ts.map +1 -0
  41. package/dist/types/src/session/session.test.d.ts +2 -0
  42. package/dist/types/src/session/session.test.d.ts.map +1 -0
  43. package/dist/types/src/testing/index.d.ts +1 -0
  44. package/dist/types/src/testing/index.d.ts.map +1 -1
  45. package/dist/types/src/testing/ollama.d.ts +6 -0
  46. package/dist/types/src/testing/ollama.d.ts.map +1 -0
  47. package/package.json +13 -13
  48. package/src/ai-service/client.test.ts +14 -14
  49. package/src/ai-service/defs.ts +18 -3
  50. package/src/ai-service/edge-client.ts +3 -2
  51. package/src/ai-service/ollama-client.ts +50 -24
  52. package/src/ai-service/parser.ts +4 -2
  53. package/src/ai-service/stream.test.ts +28 -4
  54. package/src/ai-service/types.ts +2 -2
  55. package/src/bin/chat.ts +3 -3
  56. package/src/conversation/conversation.test.ts +3 -3
  57. package/src/conversation/conversation.ts +17 -1
  58. package/src/cypher/query-executor.test.ts +3 -3
  59. package/src/cypher/schema.test.ts +1 -1
  60. package/src/index.ts +1 -0
  61. package/src/session/index.ts +5 -0
  62. package/src/session/session.test.ts +257 -0
  63. package/src/session/session.ts +375 -0
  64. package/src/testing/artifacts.test.ts +6 -6
  65. package/src/testing/index.ts +1 -0
  66. package/src/testing/object-extraction.test.ts +2 -2
  67. package/src/testing/ollama.ts +15 -0
  68. package/src/testing/query.test.ts +5 -5
  69. package/src/testing/test-schema.ts +5 -5
  70. package/dist/lib/browser/chunk-AXUUNA7O.mjs +0 -565
  71. package/dist/lib/browser/chunk-AXUUNA7O.mjs.map +0 -7
  72. package/dist/lib/node/chunk-QPHGQINW.cjs +0 -577
  73. package/dist/lib/node/chunk-QPHGQINW.cjs.map +0 -7
  74. package/dist/lib/node-esm/chunk-GOVFOBIB.mjs +0 -567
  75. package/dist/lib/node-esm/chunk-GOVFOBIB.mjs.map +0 -7
@@ -0,0 +1,15 @@
1
+ //
2
+ // Copyright 2025 DXOS.org
3
+ //
4
+
5
+ import { DEFAULT_OLLAMA_MODEL, OllamaClient, type OllamaClientParams } from '../ai-service';
6
+
7
+ /**
8
+ * Create a test client with small local model and no temperature for predictable results.
9
+ */
10
+ export const createTestOllamaClient = (options?: Pick<OllamaClientParams, 'tools'>) => {
11
+ return new OllamaClient({
12
+ tools: options?.tools,
13
+ overrides: { model: DEFAULT_OLLAMA_MODEL, temperature: 0 },
14
+ });
15
+ };
@@ -15,7 +15,7 @@ import { createLogger } from './logger';
15
15
  import { createCypherTool, createSystemPrompt } from './query-promts';
16
16
  import { createTestData, seedTestData } from './test-data';
17
17
  import { Contact, Org, Project, Task } from './test-schema';
18
- import { AIServiceEdgeClient, DEFAULT_LLM_MODEL } from '../ai-service';
18
+ import { AIServiceEdgeClient, DEFAULT_EDGE_MODEL } from '../ai-service';
19
19
  import { runLLM } from '../conversation';
20
20
  import { EchoDataSource } from '../cypher';
21
21
 
@@ -41,7 +41,7 @@ test.skip('cypher query', async () => {
41
41
  ]);
42
42
 
43
43
  const result = await runLLM({
44
- model: DEFAULT_LLM_MODEL,
44
+ model: DEFAULT_EDGE_MODEL,
45
45
  tools: [cypherTool],
46
46
  spaceId,
47
47
  threadId,
@@ -50,7 +50,7 @@ test.skip('cypher query', async () => {
50
50
  logger: createLogger({ stream: false }),
51
51
  });
52
52
 
53
- log.info('DONE', { result: result.result });
53
+ log('DONE', { result: result.result });
54
54
  });
55
55
 
56
56
  test.skip('query ECHO', async () => {
@@ -78,7 +78,7 @@ test.skip('query ECHO', async () => {
78
78
  ]);
79
79
 
80
80
  const result = await runLLM({
81
- model: DEFAULT_LLM_MODEL,
81
+ model: DEFAULT_EDGE_MODEL,
82
82
  tools: [cypherTool],
83
83
  spaceId,
84
84
  threadId,
@@ -87,5 +87,5 @@ test.skip('query ECHO', async () => {
87
87
  logger: createLogger({ stream: false }),
88
88
  });
89
89
 
90
- log.info('DONE', { result: result.result });
90
+ log('DONE', { result: result.result });
91
91
  });
@@ -4,7 +4,7 @@
4
4
 
5
5
  import { Schema as S } from 'effect';
6
6
 
7
- import { EntityKind, ObjectAnnotationId, Ref } from '@dxos/echo-schema';
7
+ import { EntityKind, TypeAnnotationId, Ref } from '@dxos/echo-schema';
8
8
 
9
9
  // TODO(burdon): Reconcile with sdk/schema/testing.
10
10
  // TODO(burdon): Convert interface to type.
@@ -19,7 +19,7 @@ export const Contact = S.Struct({
19
19
  })
20
20
  .pipe(S.mutable)
21
21
  .annotations({
22
- [ObjectAnnotationId]: {
22
+ [TypeAnnotationId]: {
23
23
  kind: EntityKind.Object,
24
24
  typename: 'example.com/type/Contact',
25
25
  version: '0.1.0',
@@ -35,7 +35,7 @@ export const Project = S.Struct({
35
35
  })
36
36
  .pipe(S.mutable)
37
37
  .annotations({
38
- [ObjectAnnotationId]: {
38
+ [TypeAnnotationId]: {
39
39
  kind: EntityKind.Object,
40
40
  typename: 'example.com/type/Project',
41
41
  version: '0.1.0',
@@ -53,7 +53,7 @@ export const Task = S.Struct({
53
53
  })
54
54
  .pipe(S.mutable)
55
55
  .annotations({
56
- [ObjectAnnotationId]: {
56
+ [TypeAnnotationId]: {
57
57
  kind: EntityKind.Object,
58
58
  typename: 'example.com/type/Task',
59
59
  version: '0.1.0',
@@ -70,7 +70,7 @@ export const Org = S.Struct({
70
70
  })
71
71
  .pipe(S.mutable)
72
72
  .annotations({
73
- [ObjectAnnotationId]: {
73
+ [TypeAnnotationId]: {
74
74
  kind: EntityKind.Object,
75
75
  typename: 'example.com/type/Org',
76
76
  version: '0.1.0',
@@ -1,565 +0,0 @@
1
- // packages/experimental/assistant/src/cypher/parjs.ts
2
- import { parjsCombinators, parjs } from "#parjs";
3
-
4
- // packages/experimental/assistant/src/cypher/combinators.ts
5
- var ws = parjs.whitespace();
6
- var nothing = parjs.string("").pipe(parjsCombinators.map(() => null));
7
- var optional = (parser) => parser.pipe(parjsCombinators.recover(() => ({
8
- kind: "Soft"
9
- })), parjsCombinators.or(nothing));
10
- var keyword = (word) => parjs.string(word).pipe(parjsCombinators.map(() => word));
11
- var identifier = parjs.regexp(/[a-zA-Z_][a-zA-Z0-9_]*/).pipe(parjsCombinators.map((match) => ({
12
- astKind: "Identifier",
13
- name: match[0]
14
- })));
15
- var numberLiteral = parjs.regexp(/-?\d+(\.\d+)?/).pipe(parjsCombinators.map(Number));
16
- var stringLiteral = parjs.regexp(/"([^"]*)"|'([^']*)'/).pipe(parjsCombinators.map((match) => ({
17
- astKind: "StringLiteral",
18
- value: match[1] || match[2]
19
- })));
20
- var variableTag = identifier.pipe(parjsCombinators.map((variable) => variable)).expects("variable tag");
21
- var label = identifier.pipe(parjsCombinators.map((name) => name));
22
- var property = identifier.pipe(parjsCombinators.then(parjs.string(":"), ws, stringLiteral), parjsCombinators.map(([key, , , value]) => ({
23
- key,
24
- value
25
- })));
26
- var properties = property.pipe(parjsCombinators.manySepBy(","), parjsCombinators.between("{", "}"), parjsCombinators.map((properties2) => ({
27
- astKind: "Properties",
28
- properties: properties2
29
- })));
30
- var nodePattern = optional(variableTag).pipe(parjsCombinators.then(":"), parjsCombinators.then(ws, label, ws), parjsCombinators.then(optional(properties)), parjsCombinators.between("(", ")"), parjsCombinators.map(([[[variable], _, label2], properties2]) => ({
31
- astKind: "NodePattern",
32
- variable,
33
- label: label2,
34
- properties: properties2
35
- })));
36
- var relationshipPattern = optional(variableTag).pipe(parjsCombinators.then(":"), parjsCombinators.then(ws, label, ws), parjsCombinators.then(optional(properties)), parjsCombinators.between("[", "]"), parjsCombinators.map(([[[variable], _, label2], properties2]) => ({
37
- astKind: "RelationshipPattern",
38
- variable,
39
- label: label2,
40
- properties: properties2
41
- })));
42
- var graphPatternConnector = parjs.string("->").pipe(parjsCombinators.or("<-", "-"), parjsCombinators.map((x) => ({
43
- astKind: "GraphPatternConnector",
44
- direction: x
45
- })));
46
- var graphPattern = nodePattern.pipe(parjsCombinators.or(relationshipPattern), parjsCombinators.manySepBy(graphPatternConnector), parjsCombinators.map((segments) => ({
47
- astKind: "GraphPattern",
48
- segments
49
- })));
50
- var matchClause = keyword("MATCH").pipe(parjsCombinators.then(ws), parjsCombinators.then(graphPattern), parjsCombinators.map(([, pattern]) => ({
51
- astKind: "MatchClause",
52
- pattern
53
- })));
54
- var memberExpression = identifier.pipe(parjsCombinators.manySepBy("."), parjsCombinators.map((path) => ({
55
- astKind: "MemberExpression",
56
- path
57
- })));
58
- var equalsPredicate = memberExpression.pipe(parjsCombinators.then(ws, parjs.string("="), ws, stringLiteral), parjsCombinators.map(([left, , , , right]) => ({
59
- astKind: "EqualsPredicate",
60
- left,
61
- right
62
- })));
63
- var whereClause = keyword("WHERE").pipe(parjsCombinators.then(ws, equalsPredicate.pipe(parjsCombinators.between(ws, ws), parjsCombinators.manySepBy(parjs.string("AND"))), ws), parjsCombinators.map(([, , predicates]) => ({
64
- astKind: "WhereClause",
65
- predicates
66
- })));
67
- var returnClause = keyword("RETURN").pipe(parjsCombinators.then(ws, memberExpression.pipe(parjsCombinators.then(optional(parjs.string("AS").pipe(parjsCombinators.between(ws), parjsCombinators.then(identifier))), ws), parjsCombinators.manySepBy(parjs.string(",").pipe(parjsCombinators.then(ws)))), ws), parjsCombinators.map(([, , fields]) => ({
68
- astKind: "ReturnClause",
69
- fields: fields.map(([f]) => f)
70
- })));
71
- var cypherQuery = ws.pipe(parjsCombinators.then(matchClause, ws, optional(whereClause), ws, returnClause, ws), parjsCombinators.map(([, matchClause2, , whereClause2, , returnClause2]) => ({
72
- astKind: "CypherQuery",
73
- matchClause: matchClause2,
74
- whereClause: whereClause2,
75
- returnClause: returnClause2
76
- })));
77
-
78
- // packages/experimental/assistant/src/cypher/parser.ts
79
- var parseCypherQuery = (query) => {
80
- const parseResult = cypherQuery.parse(query);
81
- if (parseResult.isOk) {
82
- return {
83
- ast: parseResult.value
84
- };
85
- } else {
86
- throw new Error(`Failed to parse query: ${parseResult}`);
87
- }
88
- };
89
-
90
- // packages/experimental/assistant/src/cypher/query-executor.ts
91
- import { log as log2 } from "@dxos/log";
92
- import { mapValues } from "@dxos/util";
93
-
94
- // packages/experimental/assistant/src/cypher/execution-plan.ts
95
- import { invariant } from "@dxos/invariant";
96
- import { log } from "@dxos/log";
97
- var __dxlog_file = "/home/runner/work/dxos/dxos/packages/experimental/assistant/src/cypher/execution-plan.ts";
98
- var createExecutionPlan = (query) => {
99
- return new ExecutionPlanBuilder().build(query);
100
- };
101
- var ExecutionPlanBuilder = class {
102
- constructor() {
103
- this.counter = 0;
104
- }
105
- newVariable() {
106
- return `anon_${this.counter++}`;
107
- }
108
- build(query) {
109
- log("Creating execution plan for query", {
110
- query
111
- }, {
112
- F: __dxlog_file,
113
- L: 76,
114
- S: this,
115
- C: (f, a) => f(...a)
116
- });
117
- return {
118
- steps: [
119
- ...this.createStepsForMatchClause(query.ast.matchClause),
120
- ...query.ast.whereClause ? this.createStepsForWhereClause(query.ast.whereClause) : [],
121
- ...this.createStepsForReturnClause(query.ast.returnClause)
122
- ],
123
- output: {
124
- fields: this.getOutputFields(query.ast.returnClause)
125
- }
126
- };
127
- }
128
- createStepsForMatchClause(match) {
129
- invariant(match.pattern.segments.length > 0, void 0, {
130
- F: __dxlog_file,
131
- L: 90,
132
- S: this,
133
- A: [
134
- "match.pattern.segments.length > 0",
135
- ""
136
- ]
137
- });
138
- const firstSegment = match.pattern.segments[0];
139
- invariant(firstSegment.astKind === "NodePattern", void 0, {
140
- F: __dxlog_file,
141
- L: 92,
142
- S: this,
143
- A: [
144
- "firstSegment.astKind === 'NodePattern'",
145
- ""
146
- ]
147
- });
148
- let lastNodeVariable = firstSegment.variable?.name ?? this.newVariable();
149
- const steps = [];
150
- steps.push({
151
- type: "NodeScan",
152
- label: firstSegment.label.name,
153
- into: lastNodeVariable
154
- });
155
- if (firstSegment.properties) {
156
- for (const property2 of firstSegment.properties.properties) {
157
- steps.push({
158
- type: "FilterByProperty",
159
- variable: lastNodeVariable,
160
- property: property2.key.name,
161
- value: property2.value.value
162
- });
163
- }
164
- }
165
- for (let i = 1; i < match.pattern.segments.length; i++) {
166
- const relationshipSegment = match.pattern.segments[i++];
167
- invariant(relationshipSegment.astKind === "RelationshipPattern", void 0, {
168
- F: __dxlog_file,
169
- L: 115,
170
- S: this,
171
- A: [
172
- "relationshipSegment.astKind === 'RelationshipPattern'",
173
- ""
174
- ]
175
- });
176
- const nodeSegment = match.pattern.segments[i];
177
- invariant(nodeSegment.astKind === "NodePattern", void 0, {
178
- F: __dxlog_file,
179
- L: 117,
180
- S: this,
181
- A: [
182
- "nodeSegment.astKind === 'NodePattern'",
183
- ""
184
- ]
185
- });
186
- const leftSeparator = match.pattern.segments.separators[i - 2];
187
- const rightSeparator = match.pattern.segments.separators[i - 1];
188
- const direction = getDirection(leftSeparator.direction, rightSeparator.direction);
189
- const relationshipVariable = relationshipSegment.variable?.name ?? this.newVariable();
190
- const nodeVariable = nodeSegment.variable?.name ?? this.newVariable();
191
- steps.push({
192
- type: "RelationshipScan",
193
- label: relationshipSegment.label.name,
194
- direction,
195
- anchor: lastNodeVariable,
196
- relationshipInto: relationshipVariable,
197
- nodeInto: nodeVariable
198
- });
199
- if (relationshipSegment.properties) {
200
- for (const property2 of relationshipSegment.properties.properties) {
201
- steps.push({
202
- type: "FilterByProperty",
203
- variable: relationshipVariable,
204
- property: property2.key.name,
205
- value: property2.value.value
206
- });
207
- }
208
- }
209
- if (nodeSegment.label) {
210
- steps.push({
211
- type: "FilterByLabel",
212
- variable: nodeVariable,
213
- label: nodeSegment.label.name
214
- });
215
- }
216
- if (nodeSegment.properties) {
217
- for (const property2 of nodeSegment.properties.properties) {
218
- steps.push({
219
- type: "FilterByProperty",
220
- variable: nodeVariable,
221
- property: property2.key.name,
222
- value: property2.value.value
223
- });
224
- }
225
- }
226
- lastNodeVariable = nodeVariable;
227
- }
228
- return steps;
229
- }
230
- createStepsForWhereClause(where) {
231
- return [];
232
- }
233
- createStepsForReturnClause(returnClause2) {
234
- return [
235
- {
236
- type: "ProduceResults",
237
- fields: returnClause2.fields.map((field) => ({
238
- name: field.path.map((p) => p.name).join("_"),
239
- variable: field.path[0].name,
240
- path: field.path.length > 1 ? field.path.slice(1).map((p) => p.name).join(".") : "$"
241
- }))
242
- }
243
- ];
244
- }
245
- getOutputFields(returnClause2) {
246
- return returnClause2.fields.map((field) => field.path.map((p) => p.name).join("_"));
247
- }
248
- };
249
- var getDirection = (left, right) => {
250
- if (left === "-" && right === "->") {
251
- return "out";
252
- } else if (left === "<-" && right === "-") {
253
- return "in";
254
- } else if (left === "-" && right === "-") {
255
- return "both";
256
- }
257
- throw new Error(`Invalid direction: ()${left}[]${right}()`);
258
- };
259
-
260
- // packages/experimental/assistant/src/cypher/query-executor.ts
261
- var __dxlog_file2 = "/home/runner/work/dxos/dxos/packages/experimental/assistant/src/cypher/query-executor.ts";
262
- var executeQueryPlan = async (dataSource, plan) => {
263
- let buffer = [];
264
- const results = [];
265
- for (const step of plan.steps) {
266
- log2("begin step", {
267
- step
268
- }, {
269
- F: __dxlog_file2,
270
- L: 41,
271
- S: void 0,
272
- C: (f, a) => f(...a)
273
- });
274
- switch (step.type) {
275
- case "NodeScan": {
276
- const nodes = await dataSource.getNodes({
277
- label: step.label
278
- });
279
- buffer.push(...nodes.map((node) => ({
280
- [step.into]: node
281
- })));
282
- break;
283
- }
284
- case "FilterByLabel": {
285
- buffer = buffer.filter((item) => {
286
- const node = item[step.variable];
287
- return node && node.kind === "node" && node.label === step.label;
288
- });
289
- break;
290
- }
291
- case "FilterByProperty": {
292
- buffer = buffer.filter((item) => {
293
- const node = item[step.variable];
294
- return node && node.kind === "node" && node.properties[step.property] === step.value;
295
- });
296
- break;
297
- }
298
- case "RelationshipScan": {
299
- const relationships = await dataSource.getRelationships({
300
- label: step.label
301
- });
302
- for (const tuple of [
303
- ...buffer
304
- ]) {
305
- if (tuple[step.anchor].kind !== "node") {
306
- continue;
307
- }
308
- const filteredRelationships = relationships.filter((relationship) => {
309
- switch (step.direction) {
310
- case "in":
311
- return relationship.target.id === tuple[step.anchor].id;
312
- case "out":
313
- return relationship.source.id === tuple[step.anchor].id;
314
- case "both":
315
- return relationship.source.id === tuple[step.anchor].id || relationship.target.id === tuple[step.anchor].id;
316
- default:
317
- throw new Error(`Unknown direction: ${step.direction}`);
318
- }
319
- });
320
- for (let i = 0; i < filteredRelationships.length; i++) {
321
- const relationship = filteredRelationships[i];
322
- const newTuple = i === 0 ? tuple : {
323
- ...tuple
324
- };
325
- if (newTuple !== tuple) {
326
- buffer.push(newTuple);
327
- }
328
- newTuple[step.relationshipInto] = relationship;
329
- switch (step.direction) {
330
- case "in":
331
- newTuple[step.nodeInto] = relationship.source;
332
- break;
333
- case "out":
334
- newTuple[step.nodeInto] = relationship.target;
335
- break;
336
- case "both":
337
- newTuple[step.nodeInto] = relationship.source.id === newTuple[step.anchor].id ? relationship.target : relationship.source;
338
- break;
339
- }
340
- }
341
- }
342
- break;
343
- }
344
- case "ProduceResults": {
345
- for (const tuple of buffer) {
346
- const result = {};
347
- for (const field of step.fields) {
348
- result[field.name] = jsonPathGet(tuple[field.variable].properties, field.path);
349
- }
350
- results.push(result);
351
- }
352
- break;
353
- }
354
- }
355
- log2("finish step", {
356
- buffer: buffer.map((tuple) => mapValues(tuple, (x) => x.id)),
357
- results
358
- }, {
359
- F: __dxlog_file2,
360
- L: 118,
361
- S: void 0,
362
- C: (f, a) => f(...a)
363
- });
364
- }
365
- return results;
366
- };
367
- var executeQuery = (dataSource, query) => {
368
- const plan = createExecutionPlan(parseCypherQuery(query));
369
- return executeQueryPlan(dataSource, plan);
370
- };
371
- var jsonPathGet = (obj, path) => {
372
- if (path === "" || path === "$") {
373
- return obj;
374
- }
375
- const parts = path.split(".");
376
- if (parts[0] === "$") {
377
- parts.shift();
378
- }
379
- let result = obj;
380
- for (const part of parts) {
381
- result = result?.[part];
382
- }
383
- return result;
384
- };
385
-
386
- // packages/experimental/assistant/src/cypher/schema.ts
387
- import { raise } from "@dxos/debug";
388
- import { JSON_SCHEMA_ECHO_REF_ID } from "@dxos/echo-schema";
389
-
390
- // packages/experimental/assistant/src/util/trim.ts
391
- var trim = (strings, ...values) => {
392
- const combined = strings.reduce((acc, str, i) => {
393
- return acc + str + (values[i] || "");
394
- }, "");
395
- return combined.replace("/^\n/", "").replace(/\n$/, "");
396
- };
397
-
398
- // packages/experimental/assistant/src/cypher/schema.ts
399
- var formatJsonSchemaForLLM = (schemaTypes) => {
400
- return schemaTypes.flatMap((schema) => [
401
- formatNodeSchema(schema),
402
- ...formatInferredRelationships(schema, schemaTypes)
403
- ]);
404
- };
405
- var formatNodeSchema = (schema) => {
406
- const label2 = formatNodeLabel(schema.typename ?? raise(new Error("Schema must have $id")));
407
- const properties2 = Object.entries(schema.properties).filter(([key, prop]) => key !== "id" && !isReference(prop));
408
- return trim`
409
- <node>
410
- (:${label2})
411
-
412
- <description>${schema.description}</description>
413
-
414
- <properties>
415
- ${properties2.map(([key, value]) => {
416
- return trim`
417
- <${key}>
418
- <type>${value.type}</type>
419
- <description>${value.description}</description>
420
- </${key}>
421
- `;
422
- })}
423
- </properties>
424
- </node>
425
- `;
426
- };
427
- var formatInferredRelationships = (schema, allSchema) => {
428
- const nodeLabel = formatNodeLabel(schema.typename ?? raise(new Error("Schema must have $id")));
429
- const relationships = Object.entries(schema.properties).filter(([key, prop]) => isReference(prop));
430
- return relationships.map(([key, value]) => {
431
- const relationshipLabel = formatInferredRelationshipLabel(schema.typename ?? raise(new Error("Schema must have $id")), key);
432
- const targetSchema = allSchema.find((schema2) => `dxn:type/${schema2.typename}` === value.reference?.schema.$ref);
433
- const targetLabel = targetSchema ? formatNodeLabel(targetSchema?.typename ?? "") : "";
434
- return trim`
435
- <relationship>
436
- (:${nodeLabel})-[:${relationshipLabel}]->(:${targetLabel})
437
-
438
- <description>${value.description}</description>
439
- </relationship>
440
- `;
441
- });
442
- };
443
- var formatNodeLabel = (typename) => {
444
- return typename.replace(/^example\.com\/type\//g, "");
445
- };
446
- var formatInferredRelationshipLabel = (typename, property2) => {
447
- const nodeLabel = formatNodeLabel(typename);
448
- return `${nodeLabel}_${property2}`.toUpperCase();
449
- };
450
- var isReference = (schema) => schema.$id === JSON_SCHEMA_ECHO_REF_ID || schema.type === "array" && !Array.isArray(schema.items) && typeof schema.items === "object" && "$id" in schema.items && schema.items.$id === JSON_SCHEMA_ECHO_REF_ID;
451
-
452
- // packages/experimental/assistant/src/cypher/echo-data-source.ts
453
- import { raise as raise2 } from "@dxos/debug";
454
- import { Filter } from "@dxos/echo-db";
455
- import { getSchemaTypename, StoredSchema, toJsonSchema } from "@dxos/echo-schema";
456
- import { getSchema } from "@dxos/live-object";
457
- import { log as log3 } from "@dxos/log";
458
- function _ts_decorate(decorators, target, key, desc) {
459
- var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
460
- if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
461
- else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
462
- return c > 3 && r && Object.defineProperty(target, key, r), r;
463
- }
464
- var __dxlog_file3 = "/home/runner/work/dxos/dxos/packages/experimental/assistant/src/cypher/echo-data-source.ts";
465
- var EchoDataSource = class {
466
- constructor(_db) {
467
- this._db = _db;
468
- }
469
- async getNodes({ label: label2 }) {
470
- if (!label2) {
471
- const { objects: objects2 } = await this._db.query().run();
472
- return objects2.map(this._objectToNode);
473
- }
474
- const schema = (await this._getAllSchema()).find((s) => getSchemaTypename(s)?.endsWith(label2));
475
- if (!schema) {
476
- return [];
477
- }
478
- const { objects } = await this._db.query(Filter.schema(schema)).run();
479
- return objects.map(this._objectToNode);
480
- }
481
- async getRelationships({ label: label2 }) {
482
- const syntheticRefRelationships = (await this._getAllSchema()).filter((schema) => getSchemaTypename(schema) !== StoredSchema.typename).flatMap((schema) => {
483
- const jsonSchema = toJsonSchema(schema);
484
- const relationships = Object.entries(jsonSchema.properties).filter(([key, prop]) => isReference(prop));
485
- return relationships.map(([key, value]) => {
486
- const relationshipLabel = formatInferredRelationshipLabel(jsonSchema.typename ?? raise2(new Error("Schema must have typename")), key);
487
- return {
488
- label: relationshipLabel,
489
- schema,
490
- property: key
491
- };
492
- });
493
- });
494
- const relationship = syntheticRefRelationships.find((r) => r.label === label2);
495
- if (!relationship) {
496
- return [];
497
- }
498
- const { objects } = await this._db.query(Filter.schema(relationship.schema)).run();
499
- return (await Promise.all(objects.map((object) => this._projectRefRelationship(object, relationship.property)))).flat();
500
- }
501
- async _getAllSchema() {
502
- return [
503
- ...await this._db.schemaRegistry.query().run(),
504
- // TODO(dmaretskyi): Remove once we can serialize recursive schema.
505
- ...this._db.graph.schemaRegistry.schemas.filter((s) => getSchemaTypename(s)?.startsWith("example.org"))
506
- ].filter((schema) => getSchemaTypename(schema) !== StoredSchema.typename);
507
- }
508
- _objectToNode(object) {
509
- const { id, ...properties2 } = object;
510
- return {
511
- id,
512
- kind: "node",
513
- label: formatNodeLabel(getSchemaTypename(getSchema(object))),
514
- properties: properties2
515
- };
516
- }
517
- async _projectRefRelationship(object, prop) {
518
- if (!object[prop]) {
519
- return [];
520
- }
521
- const value = Array.isArray(object[prop]) ? object[prop] : [
522
- object[prop]
523
- ];
524
- return Promise.all(value.map(async (ref) => {
525
- const target = await ref.load();
526
- return {
527
- id: `${object.id}-${prop}-${target.id}`,
528
- kind: "relationship",
529
- label: formatInferredRelationshipLabel(getSchemaTypename(getSchema(object)), prop),
530
- properties: {},
531
- source: this._objectToNode(object),
532
- target: this._objectToNode(target)
533
- };
534
- }));
535
- }
536
- };
537
- _ts_decorate([
538
- log3.method(void 0, void 0, {
539
- F: __dxlog_file3,
540
- L: 17,
541
- S: void 0,
542
- C: (f, a) => f(...a)
543
- })
544
- ], EchoDataSource.prototype, "getNodes", null);
545
- _ts_decorate([
546
- log3.method(void 0, void 0, {
547
- F: __dxlog_file3,
548
- L: 34,
549
- S: void 0,
550
- C: (f, a) => f(...a)
551
- })
552
- ], EchoDataSource.prototype, "getRelationships", null);
553
-
554
- export {
555
- parseCypherQuery,
556
- executeQueryPlan,
557
- executeQuery,
558
- trim,
559
- formatJsonSchemaForLLM,
560
- formatNodeLabel,
561
- formatInferredRelationshipLabel,
562
- isReference,
563
- EchoDataSource
564
- };
565
- //# sourceMappingURL=chunk-AXUUNA7O.mjs.map