@dxos/assistant-toolkit 0.8.4-main.ae835ea → 0.8.4-main.e8ec1fe

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 (96) hide show
  1. package/dist/lib/browser/index.mjs +891 -595
  2. package/dist/lib/browser/index.mjs.map +4 -4
  3. package/dist/lib/browser/meta.json +1 -1
  4. package/dist/lib/node-esm/index.mjs +890 -595
  5. package/dist/lib/node-esm/index.mjs.map +4 -4
  6. package/dist/lib/node-esm/meta.json +1 -1
  7. package/dist/types/src/blueprints/research/research-blueprint.d.ts.map +1 -1
  8. package/dist/types/src/blueprints/websearch/websearch-toolkit.d.ts +1 -0
  9. package/dist/types/src/blueprints/websearch/websearch-toolkit.d.ts.map +1 -1
  10. package/dist/types/src/crud/graph.d.ts.map +1 -0
  11. package/dist/types/src/crud/graph.test.d.ts.map +1 -0
  12. package/dist/types/src/crud/index.d.ts +2 -0
  13. package/dist/types/src/crud/index.d.ts.map +1 -0
  14. package/dist/types/src/functions/agent/prompt.d.ts +3 -5
  15. package/dist/types/src/functions/agent/prompt.d.ts.map +1 -1
  16. package/dist/types/src/functions/discord/fetch-messages.d.ts +1 -1
  17. package/dist/types/src/functions/discord/index.d.ts +1 -1
  18. package/dist/types/src/functions/discord/index.d.ts.map +1 -1
  19. package/dist/types/src/functions/document/index.d.ts +3 -2
  20. package/dist/types/src/functions/document/index.d.ts.map +1 -1
  21. package/dist/types/src/functions/document/read.d.ts +1 -1
  22. package/dist/types/src/functions/document/update.d.ts +1 -1
  23. package/dist/types/src/functions/entity-extraction/entity-extraction.d.ts +2 -2
  24. package/dist/types/src/functions/entity-extraction/entity-extraction.d.ts.map +1 -1
  25. package/dist/types/src/functions/entity-extraction/index.d.ts +2 -2
  26. package/dist/types/src/functions/entity-extraction/index.d.ts.map +1 -1
  27. package/dist/types/src/functions/exa/exa.d.ts +1 -1
  28. package/dist/types/src/functions/exa/mock.d.ts +1 -1
  29. package/dist/types/src/functions/github/fetch-prs.d.ts +1 -1
  30. package/dist/types/src/functions/linear/index.d.ts +1 -1
  31. package/dist/types/src/functions/linear/index.d.ts.map +1 -1
  32. package/dist/types/src/functions/linear/sync-issues.d.ts +1 -1
  33. package/dist/types/src/functions/research/document-create.d.ts +9 -0
  34. package/dist/types/src/functions/research/document-create.d.ts.map +1 -0
  35. package/dist/types/src/functions/research/index.d.ts +8 -6
  36. package/dist/types/src/functions/research/index.d.ts.map +1 -1
  37. package/dist/types/src/functions/research/research.d.ts +4 -3
  38. package/dist/types/src/functions/research/research.d.ts.map +1 -1
  39. package/dist/types/src/functions/research/types.d.ts +2 -380
  40. package/dist/types/src/functions/research/types.d.ts.map +1 -1
  41. package/dist/types/src/functions/tasks/index.d.ts +2 -2
  42. package/dist/types/src/functions/tasks/index.d.ts.map +1 -1
  43. package/dist/types/src/functions/tasks/read.d.ts +1 -1
  44. package/dist/types/src/functions/tasks/update.d.ts +1 -1
  45. package/dist/types/src/index.d.ts +2 -0
  46. package/dist/types/src/index.d.ts.map +1 -1
  47. package/dist/types/src/toolkits/AssistantToolkit.d.ts +17 -0
  48. package/dist/types/src/toolkits/AssistantToolkit.d.ts.map +1 -0
  49. package/dist/types/src/toolkits/AssistantToolkit.test.d.ts +2 -0
  50. package/dist/types/src/toolkits/AssistantToolkit.test.d.ts.map +1 -0
  51. package/dist/types/src/toolkits/SystemToolkit.d.ts +67 -0
  52. package/dist/types/src/toolkits/SystemToolkit.d.ts.map +1 -0
  53. package/dist/types/src/toolkits/index.d.ts +3 -0
  54. package/dist/types/src/toolkits/index.d.ts.map +1 -0
  55. package/dist/types/tsconfig.tsbuildinfo +1 -1
  56. package/package.json +24 -22
  57. package/src/blueprints/design/design-blueprint.test.ts +9 -14
  58. package/src/blueprints/design/design-blueprint.ts +2 -2
  59. package/src/blueprints/discord/discord-blueprint.ts +2 -2
  60. package/src/blueprints/linear/linear-blueprint.ts +2 -2
  61. package/src/blueprints/planning/planning-blueprint.test.ts +11 -16
  62. package/src/blueprints/planning/planning-blueprint.ts +2 -2
  63. package/src/blueprints/research/research-blueprint.ts +23 -15
  64. package/src/blueprints/websearch/websearch-blueprint.ts +2 -2
  65. package/src/{functions/research → crud}/graph.test.ts +2 -2
  66. package/src/crud/index.ts +5 -0
  67. package/src/experimental/feed.test.ts +11 -8
  68. package/src/functions/agent/prompt.ts +25 -12
  69. package/src/functions/discord/fetch-messages.test.ts +5 -6
  70. package/src/functions/discord/fetch-messages.ts +10 -9
  71. package/src/functions/document/index.ts +1 -0
  72. package/src/functions/entity-extraction/entity-extraction.conversations.json +1 -1
  73. package/src/functions/entity-extraction/entity-extraction.test.ts +11 -19
  74. package/src/functions/entity-extraction/entity-extraction.ts +15 -13
  75. package/src/functions/linear/linear.test.ts +13 -16
  76. package/src/functions/linear/sync-issues.ts +7 -7
  77. package/src/functions/research/{create-document.ts → document-create.ts} +32 -26
  78. package/src/functions/research/index.ts +1 -2
  79. package/src/functions/research/{instructions-research.tpl → research-instructions.tpl} +14 -6
  80. package/src/functions/research/research.conversations.json +1 -10714
  81. package/src/functions/research/research.test.ts +87 -148
  82. package/src/functions/research/research.ts +84 -49
  83. package/src/functions/research/types.ts +14 -12
  84. package/src/index.ts +2 -0
  85. package/src/toolkits/AssistantToolkit.conversations.json +1 -0
  86. package/src/toolkits/AssistantToolkit.test.ts +88 -0
  87. package/src/toolkits/AssistantToolkit.ts +47 -0
  88. package/src/toolkits/SystemToolkit.ts +231 -0
  89. package/src/toolkits/index.ts +6 -0
  90. package/dist/types/src/functions/research/create-document.d.ts +0 -7
  91. package/dist/types/src/functions/research/create-document.d.ts.map +0 -1
  92. package/dist/types/src/functions/research/graph.d.ts.map +0 -1
  93. package/dist/types/src/functions/research/graph.test.d.ts.map +0 -1
  94. /package/dist/types/src/{functions/research → crud}/graph.d.ts +0 -0
  95. /package/dist/types/src/{functions/research → crud}/graph.test.d.ts +0 -0
  96. /package/src/{functions/research → crud}/graph.ts +0 -0
@@ -1,16 +1,22 @@
1
1
  import { createRequire } from 'node:module';const require = createRequire(import.meta.url);
2
+ var __defProp = Object.defineProperty;
3
+ var __export = (target, all) => {
4
+ for (var name in all)
5
+ __defProp(target, name, { get: all[name], enumerable: true });
6
+ };
2
7
 
3
8
  // src/blueprints/design/design-blueprint.ts
4
9
  import { ToolId } from "@dxos/ai";
5
10
  import { Blueprint } from "@dxos/blueprints";
6
- import { Obj as Obj9, Ref as Ref6 } from "@dxos/echo";
7
- import { DataType as DataType7 } from "@dxos/schema";
11
+ import { Obj as Obj10, Ref as Ref6 } from "@dxos/echo";
12
+ import { Text as Text2 } from "@dxos/schema";
8
13
  import { trim as trim5 } from "@dxos/util";
9
14
 
10
15
  // src/functions/agent/prompt.ts
11
16
  import * as Array2 from "effect/Array";
12
17
  import * as Effect from "effect/Effect";
13
18
  import * as Function from "effect/Function";
19
+ import * as Match from "effect/Match";
14
20
  import * as Option from "effect/Option";
15
21
  import * as Schema from "effect/Schema";
16
22
  import { AiService, ConsolePrinter, ModelName } from "@dxos/ai";
@@ -36,10 +42,9 @@ var prompt_default = defineFunction({
36
42
  * Input object or data.
37
43
  * References get auto-resolved.
38
44
  */
39
- input: Schema.Record({
40
- key: Schema.String,
41
- value: Schema.Any
42
- })
45
+ input: Schema.Any.pipe(Schema.annotations({
46
+ title: "Input"
47
+ }))
43
48
  }),
44
49
  outputSchema: Schema.Any,
45
50
  handler: Effect.fnUntraced(function* ({ data }) {
@@ -47,22 +52,14 @@ var prompt_default = defineFunction({
47
52
  input: data.input
48
53
  }, {
49
54
  F: __dxlog_file,
50
- L: 39,
55
+ L: 40,
51
56
  S: this,
52
57
  C: (f, a) => f(...a)
53
58
  });
54
- const input = {
55
- ...data.input
56
- };
57
- for (const key of Object.keys(data.input)) {
58
- const value = data.input[key];
59
- if (Ref.isRef(value)) {
60
- const object = yield* DatabaseService.load(value);
61
- input[key] = Obj.toJSON(object);
62
- } else {
63
- input[key] = JSON.stringify(value);
64
- }
65
- }
59
+ const input = yield* Match.value(data.input).pipe(Match.when((value2) => Ref.isRef(value2), Effect.fnUntraced(function* (ref) {
60
+ const object = yield* DatabaseService.load(ref);
61
+ return Obj.toJSON(object);
62
+ })), Match.orElse(() => Effect.succeed(data.input)));
66
63
  yield* DatabaseService.flush({
67
64
  indexes: true
68
65
  });
@@ -73,10 +70,10 @@ var prompt_default = defineFunction({
73
70
  });
74
71
  log.info("starting agent", {
75
72
  prompt: prompt.id,
76
- input: data.input
73
+ input
77
74
  }, {
78
75
  F: __dxlog_file,
79
- L: 57,
76
+ L: 70,
80
77
  S: this,
81
78
  C: (f, a) => f(...a)
82
79
  });
@@ -125,7 +122,7 @@ import * as Schema2 from "effect/Schema";
125
122
  import { Obj as Obj2 } from "@dxos/echo";
126
123
  import { CredentialsService, TracingService as TracingService2, defineFunction as defineFunction2 } from "@dxos/functions";
127
124
  import { log as log2 } from "@dxos/log";
128
- import { DataType } from "@dxos/schema";
125
+ import { Message } from "@dxos/types";
129
126
  var __dxlog_file2 = "/__w/dxos/dxos/packages/core/assistant-toolkit/src/functions/discord/fetch-messages.ts";
130
127
  var TimeRange = class extends Schema2.String.pipe(Schema2.pattern(/\d+(s|m|h|d)/)).annotations({
131
128
  description: "Time range. 1d - 1 day, 2h - 2 hours, 30m - 30 minutes, 15s - 15 seconds.",
@@ -198,11 +195,11 @@ var fetch_messages_default = defineFunction2({
198
195
  description: "Exclude messages from these usernames."
199
196
  })
200
197
  }),
201
- handler: Effect2.fnUntraced(function* ({ data: { serverId, channelId, after, last, pageSize = 100, limit = DEFAULT_LIMIT, ignoreUsernames = DEFAULT_IGNORE_USERNAMES } }) {
202
- if (!after && !last) {
198
+ handler: Effect2.fnUntraced(function* ({ data: { serverId, channelId, after, last: last2, pageSize = 100, limit = DEFAULT_LIMIT, ignoreUsernames = DEFAULT_IGNORE_USERNAMES } }) {
199
+ if (!after && !last2) {
203
200
  throw new Error("cannot specify both `after` and `last`");
204
201
  }
205
- const afterTs = last ? Date.now() / 1e3 - TimeRange.toSeconds(last) : after ?? DEFAULT_AFTER;
202
+ const afterTs = last2 ? Date.now() / 1e3 - TimeRange.toSeconds(last2) : after ?? DEFAULT_AFTER;
206
203
  const rest = yield* DiscordREST;
207
204
  let channels = [];
208
205
  channels.push(...yield* rest.listGuildChannels(serverId));
@@ -276,7 +273,7 @@ var parseSnowflake = (snowflake) => {
276
273
  const discordEpoch = 1420070400000n;
277
274
  return new Date(Number((BigInt(snowflake) >> 22n) + discordEpoch));
278
275
  };
279
- var makeMessage = (message) => Obj2.make(DataType.Message, {
276
+ var makeMessage = (message) => Obj2.make(Message.Message, {
280
277
  [Obj2.Meta]: {
281
278
  keys: [
282
279
  {
@@ -380,97 +377,375 @@ import * as Predicate from "effect/Predicate";
380
377
  import * as Schema11 from "effect/Schema";
381
378
  import { AiService as AiService3 } from "@dxos/ai";
382
379
  import { AiSession as AiSession3, makeToolExecutionServiceFromFunctions as makeToolExecutionServiceFromFunctions2, makeToolResolverFromFunctions as makeToolResolverFromFunctions2 } from "@dxos/assistant";
383
- import { Filter as Filter2, Obj as Obj6, Ref as Ref3 } from "@dxos/echo";
384
- import { DatabaseService as DatabaseService8, FunctionInvocationService as FunctionInvocationService2, defineFunction as defineFunction9 } from "@dxos/functions";
380
+ import { Filter as Filter2, Obj as Obj7, Ref as Ref3 } from "@dxos/echo";
381
+ import { DatabaseService as DatabaseService8, defineFunction as defineFunction9 } from "@dxos/functions";
382
+ import { FunctionInvocationServiceLayerTest } from "@dxos/functions-runtime/testing";
385
383
  import { log as log5 } from "@dxos/log";
386
- import { DataType as DataType5 } from "@dxos/schema";
384
+ import { LegacyOrganization as LegacyOrganization2, Message as Message2, Organization, Person as Person2 } from "@dxos/types";
387
385
  import { trim as trim4 } from "@dxos/util";
388
386
 
389
- // src/functions/research/create-document.ts
387
+ // src/crud/graph.ts
388
+ import * as Tool from "@effect/ai/Tool";
389
+ import * as Toolkit from "@effect/ai/Toolkit";
390
+ import * as Context from "effect/Context";
390
391
  import * as Effect5 from "effect/Effect";
392
+ import * as Function3 from "effect/Function";
393
+ import * as Option3 from "effect/Option";
391
394
  import * as Schema5 from "effect/Schema";
392
- import { Relation } from "@dxos/echo";
393
- import { DatabaseService as DatabaseService4, TracingService as TracingService3, defineFunction as defineFunction5 } from "@dxos/functions";
394
- import { invariant } from "@dxos/invariant";
395
- import { DXN, ObjectId } from "@dxos/keys";
395
+ import * as SchemaAST from "effect/SchemaAST";
396
+ import { Obj as Obj3 } from "@dxos/echo";
397
+ import { Filter, Query } from "@dxos/echo";
398
+ import { EntityKind, ObjectId, ReferenceAnnotationId, RelationSourceDXNId, RelationSourceId, RelationTargetDXNId, RelationTargetId, create, getEntityKind, getSchemaDXN, getSchemaTypename, getTypeAnnotation, getTypeIdentifierAnnotation } from "@dxos/echo/internal";
399
+ import { isEncodedReference } from "@dxos/echo-protocol";
400
+ import { mapAst } from "@dxos/effect";
401
+ import { ContextQueueService, DatabaseService as DatabaseService4 } from "@dxos/functions";
402
+ import { DXN } from "@dxos/keys";
396
403
  import { log as log3 } from "@dxos/log";
404
+ import { deepMapValues, isNonNullable, trim } from "@dxos/util";
405
+ var __dxlog_file3 = "/__w/dxos/dxos/packages/core/assistant-toolkit/src/crud/graph.ts";
406
+ var Subgraph = Schema5.Struct({
407
+ /** Objects and relations. */
408
+ objects: Schema5.Array(Schema5.Any)
409
+ });
410
+ var findRelatedSchema = async (db, anchor) => {
411
+ const allSchemas = [
412
+ ...db.graph.schemaRegistry.schemas
413
+ ];
414
+ return allSchemas.filter((schema) => {
415
+ if (getTypeAnnotation(schema)?.kind !== EntityKind.Relation) {
416
+ return false;
417
+ }
418
+ return isSchemaAddressableByDxn(anchor, DXN.parse(getTypeAnnotation(schema).sourceSchema)) || isSchemaAddressableByDxn(anchor, DXN.parse(getTypeAnnotation(schema).targetSchema));
419
+ }).map((schema) => ({
420
+ schema,
421
+ kind: "relation"
422
+ }));
423
+ };
424
+ var isSchemaAddressableByDxn = (schema, dxn) => {
425
+ if (getTypeIdentifierAnnotation(schema) === dxn.toString()) {
426
+ return true;
427
+ }
428
+ const t = dxn.asTypeDXN();
429
+ if (t) {
430
+ return t.type === getSchemaTypename(schema);
431
+ }
432
+ return false;
433
+ };
434
+ var LocalSearchToolkit = Toolkit.make(Tool.make("search_local_search", {
435
+ description: "Search the local database for information using a vector index",
436
+ parameters: {
437
+ query: Schema5.String.annotations({
438
+ description: "The query to search for. Could be a question or a topic or a set of keywords."
439
+ })
440
+ },
441
+ success: Schema5.Unknown,
442
+ failure: Schema5.Never,
443
+ dependencies: [
444
+ DatabaseService4
445
+ ]
446
+ }));
447
+ var LocalSearchHandler = LocalSearchToolkit.toLayer({
448
+ search_local_search: Effect5.fn(function* ({ query }) {
449
+ const { objects } = yield* DatabaseService4.runQuery(Query.select(Filter.text(query, {
450
+ type: "vector"
451
+ })));
452
+ const results = [
453
+ ...objects
454
+ ];
455
+ const option = yield* Effect5.serviceOption(ContextQueueService);
456
+ if (Option3.isSome(option)) {
457
+ const queueObjects = yield* Effect5.promise(() => option.value.queue.queryObjects());
458
+ results.push(...queueObjects);
459
+ }
460
+ return trim`
461
+ <local_context>
462
+ ${JSON.stringify(results, null, 2)}
463
+ </local_context>
464
+ `;
465
+ })
466
+ });
467
+ var GraphWriterSchema = class extends Context.Tag("@dxos/assistant/GraphWriterSchema")() {
468
+ };
469
+ var makeGraphWriterToolkit = ({ schema }) => {
470
+ return Toolkit.make(Tool.make("graph_writer", {
471
+ description: "Write to the local graph database",
472
+ parameters: createExtractionSchema(schema).fields,
473
+ success: Schema5.Unknown,
474
+ failure: Schema5.Never,
475
+ dependencies: [
476
+ DatabaseService4,
477
+ ContextQueueService
478
+ ]
479
+ }).annotateContext(Context.make(GraphWriterSchema, {
480
+ schema
481
+ })));
482
+ };
483
+ var makeGraphWriterHandler = (toolkit, { onAppend } = {}) => {
484
+ const { schema } = Context.get(toolkit.tools.graph_writer.annotations, GraphWriterSchema);
485
+ return toolkit.toLayer({
486
+ graph_writer: Effect5.fn(function* (input) {
487
+ const { db } = yield* DatabaseService4;
488
+ const { queue } = yield* ContextQueueService;
489
+ const data = yield* Effect5.promise(() => sanitizeObjects(schema, input, db, queue));
490
+ yield* Effect5.promise(() => queue.append(data));
491
+ const dxns = data.map((obj) => Obj3.getDXN(obj));
492
+ onAppend?.(dxns);
493
+ return dxns;
494
+ })
495
+ });
496
+ };
497
+ var createExtractionSchema = (types) => {
498
+ return Schema5.Struct({
499
+ ...Object.fromEntries(types.map(preprocessSchema).map((schema, index) => [
500
+ `objects_${getSanitizedSchemaName(types[index])}`,
501
+ Schema5.optional(Schema5.Array(schema)).annotations({
502
+ description: `The objects of type: ${getSchemaDXN(types[index])?.asTypeDXN().type}. ${SchemaAST.getDescriptionAnnotation(types[index].ast).pipe(Option3.getOrElse(() => ""))}`
503
+ })
504
+ ]))
505
+ });
506
+ };
507
+ var getSanitizedSchemaName = (schema) => {
508
+ return getSchemaDXN(schema).asTypeDXN().type.replaceAll(/[^a-zA-Z0-9]+/g, "_");
509
+ };
510
+ var sanitizeObjects = async (types, data, db, queue) => {
511
+ const entries = types.map((type) => data[`objects_${getSanitizedSchemaName(type)}`]?.map((object) => ({
512
+ data: object,
513
+ schema: type
514
+ })) ?? []).flat();
515
+ const idMap = /* @__PURE__ */ new Map();
516
+ const existingIds = /* @__PURE__ */ new Set();
517
+ const enitties = /* @__PURE__ */ new Map();
518
+ const resolveId = (id) => {
519
+ if (ObjectId.isValid(id)) {
520
+ existingIds.add(id);
521
+ return DXN.fromLocalObjectId(id);
522
+ }
523
+ const mappedId = idMap.get(id);
524
+ if (mappedId) {
525
+ return DXN.fromLocalObjectId(mappedId);
526
+ }
527
+ return void 0;
528
+ };
529
+ const res = entries.map((entry) => {
530
+ if (ObjectId.isValid(entry.data.id)) {
531
+ return entry;
532
+ }
533
+ idMap.set(entry.data.id, ObjectId.random());
534
+ entry.data.id = idMap.get(entry.data.id);
535
+ return entry;
536
+ }).map((entry) => {
537
+ const data2 = deepMapValues(entry.data, (value2, recurse) => {
538
+ if (isEncodedReference(value2)) {
539
+ const ref = value2["/"];
540
+ const id = resolveId(ref);
541
+ if (id) {
542
+ return {
543
+ "/": id.toString()
544
+ };
545
+ } else {
546
+ return {
547
+ "/": `search:?q=${encodeURIComponent(ref)}`
548
+ };
549
+ }
550
+ }
551
+ return recurse(value2);
552
+ });
553
+ if (getEntityKind(entry.schema) === "relation") {
554
+ const sourceDxn = resolveId(data2.source);
555
+ if (!sourceDxn) {
556
+ log3.warn("source not found", {
557
+ source: data2.source
558
+ }, {
559
+ F: __dxlog_file3,
560
+ L: 281,
561
+ S: void 0,
562
+ C: (f, a) => f(...a)
563
+ });
564
+ }
565
+ const targetDxn = resolveId(data2.target);
566
+ if (!targetDxn) {
567
+ log3.warn("target not found", {
568
+ target: data2.target
569
+ }, {
570
+ F: __dxlog_file3,
571
+ L: 285,
572
+ S: void 0,
573
+ C: (f, a) => f(...a)
574
+ });
575
+ }
576
+ delete data2.source;
577
+ delete data2.target;
578
+ data2[RelationSourceDXNId] = sourceDxn;
579
+ data2[RelationTargetDXNId] = targetDxn;
580
+ }
581
+ return {
582
+ data: data2,
583
+ schema: entry.schema
584
+ };
585
+ }).filter((object) => !existingIds.has(object.data.id));
586
+ const { objects: dbObjects } = await db.query(Query.select(Filter.ids(...existingIds))).run();
587
+ const queueObjects = await queue?.getObjectsById([
588
+ ...existingIds
589
+ ]) ?? [];
590
+ const objects = [
591
+ ...dbObjects,
592
+ ...queueObjects
593
+ ].filter(isNonNullable);
594
+ log3.info("objects", {
595
+ dbObjects,
596
+ queueObjects,
597
+ existingIds
598
+ }, {
599
+ F: __dxlog_file3,
600
+ L: 306,
601
+ S: void 0,
602
+ C: (f, a) => f(...a)
603
+ });
604
+ const missing = Array.from(existingIds).filter((id) => !objects.some((object) => object.id === id));
605
+ if (missing.length > 0) {
606
+ throw new Error(`Object IDs do not point to existing objects: ${missing.join(", ")}`);
607
+ }
608
+ return res.flatMap(({ data: data2, schema }) => {
609
+ let skip = false;
610
+ if (RelationSourceDXNId in data2) {
611
+ const id = data2[RelationSourceDXNId].asEchoDXN()?.echoId;
612
+ const obj = objects.find((object) => object.id === id) ?? enitties.get(id);
613
+ if (obj) {
614
+ delete data2[RelationSourceDXNId];
615
+ data2[RelationSourceId] = obj;
616
+ } else {
617
+ skip = true;
618
+ }
619
+ }
620
+ if (RelationTargetDXNId in data2) {
621
+ const id = data2[RelationTargetDXNId].asEchoDXN()?.echoId;
622
+ const obj = objects.find((object) => object.id === id) ?? enitties.get(id);
623
+ if (obj) {
624
+ delete data2[RelationTargetDXNId];
625
+ data2[RelationTargetId] = obj;
626
+ } else {
627
+ skip = true;
628
+ }
629
+ }
630
+ if (!skip) {
631
+ const obj = create(schema, data2);
632
+ enitties.set(obj.id, obj);
633
+ return [
634
+ obj
635
+ ];
636
+ }
637
+ return [];
638
+ });
639
+ };
640
+ var SoftRef = Schema5.Struct({
641
+ "/": Schema5.String
642
+ }).annotations({
643
+ description: "Reference to another object."
644
+ });
645
+ var preprocessSchema = (schema) => {
646
+ const isRelationSchema = getEntityKind(schema) === "relation";
647
+ const go = (ast, visited = /* @__PURE__ */ new Set()) => {
648
+ if (visited.has(ast)) {
649
+ return ast;
650
+ }
651
+ visited.add(ast);
652
+ if (SchemaAST.getAnnotation(ast, ReferenceAnnotationId).pipe(Option3.isSome)) {
653
+ return SoftRef.ast;
654
+ }
655
+ return mapAst(ast, (child) => go(child, visited));
656
+ };
657
+ return Schema5.make(mapAst(schema.ast, (ast) => go(ast))).pipe(Schema5.omit("id"), Schema5.extend(Schema5.Struct({
658
+ id: Schema5.String.annotations({
659
+ description: "The id of this object. Come up with a unique id based on your judgement."
660
+ })
661
+ })), isRelationSchema ? Schema5.extend(Schema5.Struct({
662
+ source: Schema5.String.annotations({
663
+ description: "The id of the source object for this relation."
664
+ }),
665
+ target: Schema5.String.annotations({
666
+ description: "The id of the target object for this relation."
667
+ })
668
+ })) : Function3.identity);
669
+ };
670
+
671
+ // src/functions/research/document-create.ts
672
+ import * as Effect6 from "effect/Effect";
673
+ import * as Schema6 from "effect/Schema";
674
+ import { ArtifactId as ArtifactId3 } from "@dxos/assistant";
675
+ import { Obj as Obj4, Relation } from "@dxos/echo";
676
+ import { DatabaseService as DatabaseService5, TracingService as TracingService3, defineFunction as defineFunction5 } from "@dxos/functions";
677
+ import { log as log4 } from "@dxos/log";
397
678
  import { Markdown as Markdown3 } from "@dxos/plugin-markdown/types";
398
- import { DataType as DataType2 } from "@dxos/schema";
399
- import { trim } from "@dxos/util";
400
- var __dxlog_file3 = "/__w/dxos/dxos/packages/core/assistant-toolkit/src/functions/research/create-document.ts";
401
- var create_document_default = defineFunction5({
402
- key: "dxos.org/function/research/create-document",
679
+ import { HasSubject } from "@dxos/types";
680
+ import { trim as trim2 } from "@dxos/util";
681
+ var __dxlog_file4 = "/__w/dxos/dxos/packages/core/assistant-toolkit/src/functions/research/document-create.ts";
682
+ var document_create_default = defineFunction5({
683
+ key: "dxos.org/function/research/document-create",
403
684
  name: "Create research document",
404
685
  description: "Creates a note summarizing the research.",
405
- inputSchema: Schema5.Struct({
406
- name: Schema5.String.annotations({
407
- description: "Name of the note."
686
+ inputSchema: Schema6.Struct({
687
+ subject: ArtifactId3.annotations({
688
+ description: trim2`
689
+ ID of the object (organization, contact, etc.) for which the research was performed.
690
+ `
408
691
  }),
409
- content: Schema5.String.annotations({
410
- description: trim`
692
+ name: Schema6.String.annotations({
693
+ description: "Name of the document."
694
+ }),
695
+ content: Schema6.String.annotations({
696
+ description: trim2`
411
697
  Content of the note.
412
698
  Supports (and are prefered) references to research objects using @ syntax and <object> tags (refer to research blueprint instructions).
413
699
  `
414
- }),
415
- // TODO(dmaretskyi): Use a specialized type for this (e.g., ArtifactId renamed as RefFromLLM).
416
- target: Schema5.String.annotations({
417
- description: trim`
418
- Id of the object (organization, contact, etc.) for which the research was performed.
419
- This must be a ulid.
420
- `
421
700
  })
422
701
  }),
423
- outputSchema: Schema5.Struct({}),
424
- handler: Effect5.fnUntraced(function* ({ data: { target, name, content } }) {
425
- log3.info("Creating research document", {
426
- target,
702
+ outputSchema: Schema6.Struct({
703
+ document: ArtifactId3.annotations({
704
+ description: "DXN of the created document."
705
+ })
706
+ }),
707
+ handler: Effect6.fnUntraced(function* ({ data: { subject, name, content } }) {
708
+ log4.info("Creating research document", {
709
+ subject,
427
710
  name,
428
711
  content
429
712
  }, {
430
- F: __dxlog_file3,
431
- L: 43,
713
+ F: __dxlog_file4,
714
+ L: 42,
432
715
  S: this,
433
716
  C: (f, a) => f(...a)
434
717
  });
435
- yield* DatabaseService4.flush({
718
+ yield* DatabaseService5.flush({
436
719
  indexes: true
437
720
  });
438
721
  yield* TracingService3.emitStatus({
439
722
  message: "Creating research document..."
440
723
  });
441
- invariant(ObjectId.isValid(target), void 0, {
442
- F: __dxlog_file3,
443
- L: 47,
444
- S: this,
445
- A: [
446
- "ObjectId.isValid(target)",
447
- ""
448
- ]
449
- });
450
- const targetObj = yield* DatabaseService4.resolve(DXN.fromLocalObjectId(target));
451
- const doc = yield* DatabaseService4.add(Markdown3.makeDocument({
724
+ const target = yield* DatabaseService5.resolve(ArtifactId3.toDXN(subject));
725
+ const object = yield* DatabaseService5.add(Markdown3.make({
452
726
  name,
453
727
  content
454
728
  }));
455
- yield* DatabaseService4.add(Relation.make(DataType2.HasSubject, {
456
- [Relation.Source]: doc,
457
- [Relation.Target]: targetObj,
729
+ yield* DatabaseService5.add(Relation.make(HasSubject.HasSubject, {
730
+ [Relation.Source]: object,
731
+ [Relation.Target]: target,
458
732
  completedAt: (/* @__PURE__ */ new Date()).toISOString()
459
733
  }));
460
- yield* DatabaseService4.flush({
734
+ yield* DatabaseService5.flush({
461
735
  indexes: true
462
736
  });
463
- log3.info("Created research document", {
464
- target,
465
- name,
466
- content
737
+ log4.info("Created research document", {
738
+ subject,
739
+ object
467
740
  }, {
468
- F: __dxlog_file3,
469
- L: 66,
741
+ F: __dxlog_file4,
742
+ L: 69,
470
743
  S: this,
471
744
  C: (f, a) => f(...a)
472
745
  });
473
- return {};
746
+ return {
747
+ document: Obj4.getDXN(object).toString()
748
+ };
474
749
  })
475
750
  });
476
751
 
@@ -479,36 +754,41 @@ import * as Toolkit2 from "@effect/ai/Toolkit";
479
754
  import * as AnthropicTool from "@effect/ai-anthropic/AnthropicTool";
480
755
  import * as Array6 from "effect/Array";
481
756
  import * as Effect10 from "effect/Effect";
757
+ import * as Function4 from "effect/Function";
482
758
  import * as Layer3 from "effect/Layer";
759
+ import * as Option4 from "effect/Option";
483
760
  import * as Schema10 from "effect/Schema";
761
+ import * as String10 from "effect/String";
484
762
  import { AiService as AiService2, ConsolePrinter as ConsolePrinter2 } from "@dxos/ai";
485
763
  import { AiSession as AiSession2, GenerationObserver as GenerationObserver2, createToolkit as createToolkit2, makeToolExecutionServiceFromFunctions, makeToolResolverFromFunctions } from "@dxos/assistant";
486
- import { Obj as Obj5 } from "@dxos/echo";
487
- import { DatabaseService as DatabaseService7, FunctionInvocationService, TracingService as TracingService4, defineFunction as defineFunction8 } from "@dxos/functions";
488
- import { DataType as DataType4 } from "@dxos/schema";
764
+ import { Template as Template2 } from "@dxos/blueprints";
765
+ import { Obj as Obj6 } from "@dxos/echo";
766
+ import { DatabaseService as DatabaseService7, TracingService as TracingService4, defineFunction as defineFunction8 } from "@dxos/functions";
767
+ import { FunctionInvocationServiceLayerTestMocked } from "@dxos/functions-runtime/testing";
768
+ import { Person } from "@dxos/types";
489
769
  import { trim as trim3 } from "@dxos/util";
490
770
 
491
771
  // src/functions/exa/exa.ts
492
- import * as Effect6 from "effect/Effect";
493
- import * as Schema6 from "effect/Schema";
772
+ import * as Effect7 from "effect/Effect";
773
+ import * as Schema7 from "effect/Schema";
494
774
  import Exa from "exa-js";
495
775
  import { CredentialsService as CredentialsService2, defineFunction as defineFunction6 } from "@dxos/functions";
496
776
  var exa_default = defineFunction6({
497
777
  key: "dxos.org/function/exa",
498
778
  name: "Exa",
499
779
  description: "Search the web for information",
500
- inputSchema: Schema6.Struct({
501
- query: Schema6.String.annotations({
780
+ inputSchema: Schema7.Struct({
781
+ query: Schema7.String.annotations({
502
782
  description: "The query to search for."
503
783
  })
504
784
  }),
505
- outputSchema: Schema6.Unknown,
506
- handler: Effect6.fnUntraced(function* ({ data: { query } }) {
785
+ outputSchema: Schema7.Unknown,
786
+ handler: Effect7.fnUntraced(function* ({ data: { query } }) {
507
787
  const credential = yield* CredentialsService2.getCredential({
508
788
  service: "exa.ai"
509
789
  });
510
790
  const exa = new Exa(credential.apiKey);
511
- const context = yield* Effect6.promise(async () => exa.searchAndContents(query, {
791
+ const context = yield* Effect7.promise(async () => exa.searchAndContents(query, {
512
792
  type: "auto",
513
793
  text: {
514
794
  maxCharacters: 3e3
@@ -520,8 +800,8 @@ var exa_default = defineFunction6({
520
800
  });
521
801
 
522
802
  // src/functions/exa/mock.ts
523
- import * as Effect7 from "effect/Effect";
524
- import * as Schema7 from "effect/Schema";
803
+ import * as Effect8 from "effect/Effect";
804
+ import * as Schema8 from "effect/Schema";
525
805
  import { defineFunction as defineFunction7 } from "@dxos/functions";
526
806
 
527
807
  // src/testing/data/exa-search-1748337321991.ts
@@ -987,390 +1267,103 @@ var exa_search_1748337344119_default = {
987
1267
  id: "https://github.com/RoboZoom/knowledge_management",
988
1268
  title: "GitHub - RoboZoom/knowledge_management",
989
1269
  url: "https://github.com/RoboZoom/knowledge_management",
990
- publishedDate: "2024-02-08T02:20:22.000Z",
991
- author: "RoboZoom",
992
- score: 0.37371376156806946,
993
- text: "\n \n \n \n \n \n \n \n \n \n \nGitHub Copilot\n \nWrite better code with AI\n \n \n \n \n \n \nGitHub Models\n \nNew\n \n \nManage and compare prompts\n \n \n \n \n \n \nGitHub Advanced Security\n \nFind and fix vulnerabilities\n \n \n \n \n \n \nActions\n \nAutomate any workflow\n \n \n \n \n \n \nCodespaces\n \nInstant dev environments\n \n \n \n \n \n \n \n \n \n \nIssues\n \nPlan and track work\n \n \n \n \n \n \nCode Review\n \nManage code changes\n \n \n \n \n \n \nDiscussions\n \nCollaborate outside of code\n \n \n \n \n \n \nCode Search\n \nFind more, search less\n \n \n \n \n \n \n \n \n \n \n Explore \n \n \nLearning Pathways\n \n \n \nEvents &amp; Webinars\n \n \n \nEbooks &amp; Whitepapers\n \n \n \nCustomer Stories\n \n \n \nPartners\n \n \n \nExecutive Insights\n \n \n \n \n \n \n \n \n \n \n \n \nGitHub Sponsors\n \nFund open source developers\n \n \n \n \n \n \n \n \n \n \nThe ReadME Project\n \nGitHub community articles\n \n \n \n \n \n \n \n \n \n \n \n \n \nEnterprise platform\n \nAI-powered developer platform\n \n \n \n \n \n \n Pricing \n \n \n \n \n \nSign up\n \n \n",
994
- image: "https://opengraph.githubassets.com/2388498497e355faeecdd0ebc0ae18ac0680ba329b5f7030aa21bc38ddaa6b8b/RoboZoom/knowledge_management",
995
- favicon: "https://github.com/fluidicon.png"
996
- },
997
- {
998
- id: "https://creati.ai/ai-tools/sciphi/",
999
- title: "SciPhi: Build, Deploy, and Optimize AI Systems | Creati.ai",
1000
- url: "https://creati.ai/ai-tools/sciphi/",
1001
- publishedDate: "2024-07-01T00:00:00.000Z",
1002
- author: "",
1003
- score: 0.37101393938064575,
1004
- text: "SciPhi simplifies building, deploying, and optimizing Retrieval-Augmented Generation (RAG) systems, empowering developers to focus on AI innovation. Added on: Social &amp; Email: Platform: SciPhi SciPhi simplifies building, deploying, and optimizing Retrieval-Augmented Generation (RAG) systems, empowering developers to focus on AI innovation. Added on: Social &amp; Email: Platform: What is SciPhi? SciPhi is an open-source platform designed to simplify the building, deploying, and scaling of Retrieval-Augmented Generation (RAG) systems. It provides an end-to-end solution for developers, enabling them to focus on AI innovation without worrying about the underlying infrastructure. With tools for automated knowledge graph extraction, document and user management, and robust observability, SciPhi ensures efficient and optimized RAG system deployment. Who will use SciPhi? Developers AI Engineers Data Scientists Tech Startups Research Institutions How to use the SciPhi? Step1: Visit the SciPhi website. Step2: Sign up for an account or log in. Step3: Access the platform's dashboard. Step4: Follow guides to build and deploy your RAG system. Step5: Use tools for knowledge graph extraction and management. Step6: Optimize and monitor your system using provided observability features. SciPhi's Core Features &amp; Benefits The Core Features of SciPhi End-to-End RAG System Deployment Automated Knowledge Graph Extraction Document and User Management Robust Observability Tools The Benefits of SciPhi Simplifies AI Development Speeds Up Deployment Time Enhances System Optimization Reduces Infrastructure Complexity SciPhi's Main Use Cases &amp; Applications Building RAG Systems for AI Applications Deploying Knowledge Graphs Managing Large Document Repositories Optimizing AI System Performance FAQs of SciPhi SciPhi is an open-source platform designed to simplify building, deploying, and optimizing Retrieval-Augmented Generation (RAG) systems. SciPhi is intended for developers, AI engineers, data scientists, tech startups, and research institutions. Core features include end-to-end RAG system deployment, automated knowledge graph extraction, document and user management, and robust observability tools. Visit the SciPhi website, sign up for an account, and follow the guides to build and deploy your RAG system. SciPhi supports web platforms. SciPhi simplifies AI development, speeds up deployment time, enhances system optimization, and reduces infrastructure complexity. Yes, alternatives include LangChain, LlamaIndex, Haystack, and Flower. SciPhi supports building RAG systems for AI applications, deploying knowledge graphs, managing large document repositories, and optimizing AI system performance. You can reach out to their support team via their support email provided on the website. SciPhi offers both free and paid plans. Details on pricing can be found on their website. SciPhi Company Information Website: https://www.sciphi.ai Company Name: SciPhi Support Email: [ema",
1005
- image: "https://cdn-image.creati.ai/ai-tools/product-image/sciphi.webp",
1006
- favicon: "https://cdn-image.creati.ai/image/Creatiai.ico"
1007
- },
1008
- {
1009
- id: "https://helpjuice.com/blog/open-source-knowledge-base",
1010
- title: "The 12 Best Open Source Knowledge Base Software for 2024",
1011
- url: "https://helpjuice.com/blog/open-source-knowledge-base",
1012
- author: "Zeeshan Khan",
1013
- text: "\n \n \n \n \n At Helpjuice / \n \n #Software &amp; Alternatives\n May 15 2025 \n 11m read \n \n \n \n \n On the hunt for the perfect knowledge base software that\u2019s open source? This post will walk you through the best options for your business. \n \n \n \n \n There\u2019s no denying that a knowledge base can make a major impact on your organization.\xA0 Whether it's to help provide better support to your customers or to enable your employees to find the information they need to do their job, a finely-tuned knowledge base can make all the difference when it comes to how knowledge and information flows through your business. And with plenty of options on the market out there, there\u2019s certainly no shortage of open source knowledge base software. But how can you tell you\u2019re not investing time into installing and learning new software that your team won't use anyway? How can you avoid the time and effort put into an open source option that you later determine to not be a good fit for your needs?\xA0 It\u2019s simple\u2014do a little research beforehand. We know, we know\u2014you don\u2019t have endless time to invest in that kind of thing (what with a business to run and all). That\u2019s why we\u2019ve created a helpful list of the must-consider open source knowledge base software that companies of all niches, industries, and sizes should consider.\xA0 We\u2019re even throwing in a little helpful knowledge that should equip you with the information needed to choose the right software for you\u2014like what knowledge base software is in the first place, the benefits of open source software, and how to address your unique needs as a company to choose the right software for you.\xA0 Want to skip ahead on some of the basics of open-source knowledge base software?\xA0 Be our guest.\xA0 The best open source knowledge base software includes: \n BookStack \n OpenKM \n myBase \n eXo \n PHPKB \n Documize \n DocuWiki \n phpMyFAQ \n MediaWiki \n xWiki \n TWiki \n TiddlyWiki \n What is an Open Source Knowledge Base? Before we dive into which open-source knowledge base software you should consider for your business, we should probably ensure we\u2019re on the same page about what exactly open-source knowledge base software is.\xA0 First things first, let\u2019s start with the term knowledge base. A knowledge base is a central place that allows structured storage of information where users can search for and access this information. \xA0Knowledge base software should be the key tool that helps make this process seamless, simplified, and efficient. Knowledge base software is designed to help you create and manage your knowledge base to the best of your ability. this usually includes setting up the knowledge base architecture, creating and editing documentation, searching, and analyzing your knowledge base, and more. Ideally, this is the irreplaceable piece of the puzzle that operates your entire knowledge management system that helps orchestrate, manage, and optimize the flow of knowledge within your organization.\xA0 That part seems pretty clear, right? Next, we\u2019ll move on to",
1014
- image: "https://static.helpjuice.com/helpjuice_production/uploads/upload/image/4752/direct/1636499945090-Open%20Source%20Knowledge%20Base%20Software.jpg",
1015
- favicon: "https://static.helpjuice.com/assets/favicon-32x32-161f2153235b710a8ed7b9233ed6b195936bdb57bf1310e720f7fea79547cf9d.png"
1016
- }
1017
- ],
1018
- costDollars: {
1019
- total: 0.015,
1020
- search: {
1021
- neural: 5e-3
1022
- },
1023
- contents: {
1024
- text: 0.01
1025
- }
1026
- }
1027
- };
1028
-
1029
- // src/testing/data/index.ts
1030
- var SEARCH_RESULTS = [
1031
- exa_search_1748337321991_default,
1032
- exa_search_1748337331526_default,
1033
- exa_search_1748337344119_default
1034
- ];
1035
-
1036
- // src/functions/exa/mock.ts
1037
- var mock_default = defineFunction7({
1038
- key: "dxos.org/function/exa-mock",
1039
- name: "Exa mock",
1040
- description: "Search the web for information",
1041
- inputSchema: Schema7.Struct({
1042
- query: Schema7.String.annotations({
1043
- description: "The query to search for."
1044
- })
1045
- }),
1046
- outputSchema: Schema7.Unknown,
1047
- handler: Effect7.fnUntraced(function* ({ data: { query } }) {
1048
- const result = SEARCH_RESULTS.reduce((closest, current) => {
1049
- if (!current.autopromptString) {
1050
- return closest;
1051
- }
1052
- if (!closest) {
1053
- return current;
1054
- }
1055
- const dist1 = levenshteinDistance(query, current.autopromptString);
1056
- const dist2 = levenshteinDistance(query, closest.autopromptString || "");
1057
- const weight1 = dist1 / Math.max(query.length, current.autopromptString.length);
1058
- const weight2 = dist2 / Math.max(query.length, closest.autopromptString?.length || 0);
1059
- return weight1 < weight2 ? current : closest;
1060
- }, null);
1061
- return result;
1062
- })
1063
- });
1064
- var levenshteinDistance = (str1, str2) => {
1065
- const m = str1.length;
1066
- const n = str2.length;
1067
- const dp = Array(m + 1).fill(null).map(() => Array(n + 1).fill(0));
1068
- for (let i = 0; i <= m; i++) {
1069
- dp[i][0] = i;
1070
- }
1071
- for (let j = 0; j <= n; j++) {
1072
- dp[0][j] = j;
1073
- }
1074
- for (let i = 1; i <= m; i++) {
1075
- for (let j = 1; j <= n; j++) {
1076
- dp[i][j] = str1[i - 1] === str2[j - 1] ? dp[i - 1][j - 1] : Math.min(dp[i - 1][j - 1], dp[i - 1][j], dp[i][j - 1]) + 1;
1077
- }
1078
- }
1079
- return dp[m][n];
1080
- };
1081
-
1082
- // src/functions/research/graph.ts
1083
- import * as Tool from "@effect/ai/Tool";
1084
- import * as Toolkit from "@effect/ai/Toolkit";
1085
- import * as Context from "effect/Context";
1086
- import * as Effect8 from "effect/Effect";
1087
- import * as Function3 from "effect/Function";
1088
- import * as Option3 from "effect/Option";
1089
- import * as Schema8 from "effect/Schema";
1090
- import * as SchemaAST from "effect/SchemaAST";
1091
- import { Obj as Obj3 } from "@dxos/echo";
1092
- import { Filter, Query } from "@dxos/echo";
1093
- import { EntityKind, ObjectId as ObjectId2, ReferenceAnnotationId, RelationSourceDXNId, RelationSourceId, RelationTargetDXNId, RelationTargetId, create, getEntityKind, getSchemaDXN, getSchemaTypename, getTypeAnnotation, getTypeIdentifierAnnotation } from "@dxos/echo/internal";
1094
- import { isEncodedReference } from "@dxos/echo-protocol";
1095
- import { mapAst } from "@dxos/effect";
1096
- import { ContextQueueService, DatabaseService as DatabaseService5 } from "@dxos/functions";
1097
- import { DXN as DXN2 } from "@dxos/keys";
1098
- import { log as log4 } from "@dxos/log";
1099
- import { deepMapValues, isNonNullable, trim as trim2 } from "@dxos/util";
1100
- var __dxlog_file4 = "/__w/dxos/dxos/packages/core/assistant-toolkit/src/functions/research/graph.ts";
1101
- var Subgraph = Schema8.Struct({
1102
- /** Objects and relations. */
1103
- objects: Schema8.Array(Schema8.Any)
1104
- });
1105
- var findRelatedSchema = async (db, anchor) => {
1106
- const allSchemas = [
1107
- ...db.graph.schemaRegistry.schemas
1108
- ];
1109
- return allSchemas.filter((schema) => {
1110
- if (getTypeAnnotation(schema)?.kind !== EntityKind.Relation) {
1111
- return false;
1112
- }
1113
- return isSchemaAddressableByDxn(anchor, DXN2.parse(getTypeAnnotation(schema).sourceSchema)) || isSchemaAddressableByDxn(anchor, DXN2.parse(getTypeAnnotation(schema).targetSchema));
1114
- }).map((schema) => ({
1115
- schema,
1116
- kind: "relation"
1117
- }));
1118
- };
1119
- var isSchemaAddressableByDxn = (schema, dxn) => {
1120
- if (getTypeIdentifierAnnotation(schema) === dxn.toString()) {
1121
- return true;
1122
- }
1123
- const t = dxn.asTypeDXN();
1124
- if (t) {
1125
- return t.type === getSchemaTypename(schema);
1126
- }
1127
- return false;
1128
- };
1129
- var LocalSearchToolkit = Toolkit.make(Tool.make("search_local_search", {
1130
- description: "Search the local database for information using a vector index",
1131
- parameters: {
1132
- query: Schema8.String.annotations({
1133
- description: "The query to search for. Could be a question or a topic or a set of keywords."
1134
- })
1135
- },
1136
- success: Schema8.Unknown,
1137
- failure: Schema8.Never,
1138
- dependencies: [
1139
- DatabaseService5
1140
- ]
1141
- }));
1142
- var LocalSearchHandler = LocalSearchToolkit.toLayer({
1143
- search_local_search: Effect8.fn(function* ({ query }) {
1144
- const { objects } = yield* DatabaseService5.runQuery(Query.select(Filter.text(query, {
1145
- type: "vector"
1146
- })));
1147
- const results = [
1148
- ...objects
1149
- ];
1150
- const option = yield* Effect8.serviceOption(ContextQueueService);
1151
- if (Option3.isSome(option)) {
1152
- const queueObjects = yield* Effect8.promise(() => option.value.queue.queryObjects());
1153
- results.push(...queueObjects);
1154
- }
1155
- return trim2`
1156
- <local_context>
1157
- ${JSON.stringify(results, null, 2)}
1158
- </local_context>
1159
- `;
1160
- })
1161
- });
1162
- var GraphWriterSchema = class extends Context.Tag("@dxos/assistant/GraphWriterSchema")() {
1163
- };
1164
- var makeGraphWriterToolkit = ({ schema }) => {
1165
- return Toolkit.make(Tool.make("graph_writer", {
1166
- description: "Write to the local graph database",
1167
- parameters: createExtractionSchema(schema).fields,
1168
- success: Schema8.Unknown,
1169
- failure: Schema8.Never,
1170
- dependencies: [
1171
- DatabaseService5,
1172
- ContextQueueService
1173
- ]
1174
- }).annotateContext(Context.make(GraphWriterSchema, {
1175
- schema
1176
- })));
1177
- };
1178
- var makeGraphWriterHandler = (toolkit, { onAppend } = {}) => {
1179
- const { schema } = Context.get(toolkit.tools.graph_writer.annotations, GraphWriterSchema);
1180
- return toolkit.toLayer({
1181
- graph_writer: Effect8.fn(function* (input) {
1182
- const { db } = yield* DatabaseService5;
1183
- const { queue } = yield* ContextQueueService;
1184
- const data = yield* Effect8.promise(() => sanitizeObjects(schema, input, db, queue));
1185
- yield* Effect8.promise(() => queue.append(data));
1186
- const dxns = data.map((obj) => Obj3.getDXN(obj));
1187
- onAppend?.(dxns);
1188
- return dxns;
1189
- })
1190
- });
1191
- };
1192
- var createExtractionSchema = (types) => {
1193
- return Schema8.Struct({
1194
- ...Object.fromEntries(types.map(preprocessSchema).map((schema, index) => [
1195
- `objects_${getSanitizedSchemaName(types[index])}`,
1196
- Schema8.optional(Schema8.Array(schema)).annotations({
1197
- description: `The objects of type: ${getSchemaDXN(types[index])?.asTypeDXN().type}. ${SchemaAST.getDescriptionAnnotation(types[index].ast).pipe(Option3.getOrElse(() => ""))}`
1198
- })
1199
- ]))
1200
- });
1201
- };
1202
- var getSanitizedSchemaName = (schema) => {
1203
- return getSchemaDXN(schema).asTypeDXN().type.replaceAll(/[^a-zA-Z0-9]+/g, "_");
1204
- };
1205
- var sanitizeObjects = async (types, data, db, queue) => {
1206
- const entries = types.map((type) => data[`objects_${getSanitizedSchemaName(type)}`]?.map((object) => ({
1207
- data: object,
1208
- schema: type
1209
- })) ?? []).flat();
1210
- const idMap = /* @__PURE__ */ new Map();
1211
- const existingIds = /* @__PURE__ */ new Set();
1212
- const enitties = /* @__PURE__ */ new Map();
1213
- const resolveId = (id) => {
1214
- if (ObjectId2.isValid(id)) {
1215
- existingIds.add(id);
1216
- return DXN2.fromLocalObjectId(id);
1217
- }
1218
- const mappedId = idMap.get(id);
1219
- if (mappedId) {
1220
- return DXN2.fromLocalObjectId(mappedId);
1221
- }
1222
- return void 0;
1223
- };
1224
- const res = entries.map((entry) => {
1225
- if (ObjectId2.isValid(entry.data.id)) {
1226
- return entry;
1227
- }
1228
- idMap.set(entry.data.id, ObjectId2.random());
1229
- entry.data.id = idMap.get(entry.data.id);
1230
- return entry;
1231
- }).map((entry) => {
1232
- const data2 = deepMapValues(entry.data, (value, recurse) => {
1233
- if (isEncodedReference(value)) {
1234
- const ref = value["/"];
1235
- const id = resolveId(ref);
1236
- if (id) {
1237
- return {
1238
- "/": id.toString()
1239
- };
1240
- } else {
1241
- return {
1242
- "/": `search:?q=${encodeURIComponent(ref)}`
1243
- };
1244
- }
1245
- }
1246
- return recurse(value);
1247
- });
1248
- if (getEntityKind(entry.schema) === "relation") {
1249
- const sourceDxn = resolveId(data2.source);
1250
- if (!sourceDxn) {
1251
- log4.warn("source not found", {
1252
- source: data2.source
1253
- }, {
1254
- F: __dxlog_file4,
1255
- L: 281,
1256
- S: void 0,
1257
- C: (f, a) => f(...a)
1258
- });
1259
- }
1260
- const targetDxn = resolveId(data2.target);
1261
- if (!targetDxn) {
1262
- log4.warn("target not found", {
1263
- target: data2.target
1264
- }, {
1265
- F: __dxlog_file4,
1266
- L: 285,
1267
- S: void 0,
1268
- C: (f, a) => f(...a)
1269
- });
1270
- }
1271
- delete data2.source;
1272
- delete data2.target;
1273
- data2[RelationSourceDXNId] = sourceDxn;
1274
- data2[RelationTargetDXNId] = targetDxn;
1270
+ publishedDate: "2024-02-08T02:20:22.000Z",
1271
+ author: "RoboZoom",
1272
+ score: 0.37371376156806946,
1273
+ text: "\n \n \n \n \n \n \n \n \n \n \nGitHub Copilot\n \nWrite better code with AI\n \n \n \n \n \n \nGitHub Models\n \nNew\n \n \nManage and compare prompts\n \n \n \n \n \n \nGitHub Advanced Security\n \nFind and fix vulnerabilities\n \n \n \n \n \n \nActions\n \nAutomate any workflow\n \n \n \n \n \n \nCodespaces\n \nInstant dev environments\n \n \n \n \n \n \n \n \n \n \nIssues\n \nPlan and track work\n \n \n \n \n \n \nCode Review\n \nManage code changes\n \n \n \n \n \n \nDiscussions\n \nCollaborate outside of code\n \n \n \n \n \n \nCode Search\n \nFind more, search less\n \n \n \n \n \n \n \n \n \n \n Explore \n \n \nLearning Pathways\n \n \n \nEvents &amp; Webinars\n \n \n \nEbooks &amp; Whitepapers\n \n \n \nCustomer Stories\n \n \n \nPartners\n \n \n \nExecutive Insights\n \n \n \n \n \n \n \n \n \n \n \n \nGitHub Sponsors\n \nFund open source developers\n \n \n \n \n \n \n \n \n \n \nThe ReadME Project\n \nGitHub community articles\n \n \n \n \n \n \n \n \n \n \n \n \n \nEnterprise platform\n \nAI-powered developer platform\n \n \n \n \n \n \n Pricing \n \n \n \n \n \nSign up\n \n \n",
1274
+ image: "https://opengraph.githubassets.com/2388498497e355faeecdd0ebc0ae18ac0680ba329b5f7030aa21bc38ddaa6b8b/RoboZoom/knowledge_management",
1275
+ favicon: "https://github.com/fluidicon.png"
1276
+ },
1277
+ {
1278
+ id: "https://creati.ai/ai-tools/sciphi/",
1279
+ title: "SciPhi: Build, Deploy, and Optimize AI Systems | Creati.ai",
1280
+ url: "https://creati.ai/ai-tools/sciphi/",
1281
+ publishedDate: "2024-07-01T00:00:00.000Z",
1282
+ author: "",
1283
+ score: 0.37101393938064575,
1284
+ text: "SciPhi simplifies building, deploying, and optimizing Retrieval-Augmented Generation (RAG) systems, empowering developers to focus on AI innovation. Added on: Social &amp; Email: Platform: SciPhi SciPhi simplifies building, deploying, and optimizing Retrieval-Augmented Generation (RAG) systems, empowering developers to focus on AI innovation. Added on: Social &amp; Email: Platform: What is SciPhi? SciPhi is an open-source platform designed to simplify the building, deploying, and scaling of Retrieval-Augmented Generation (RAG) systems. It provides an end-to-end solution for developers, enabling them to focus on AI innovation without worrying about the underlying infrastructure. With tools for automated knowledge graph extraction, document and user management, and robust observability, SciPhi ensures efficient and optimized RAG system deployment. Who will use SciPhi? Developers AI Engineers Data Scientists Tech Startups Research Institutions How to use the SciPhi? Step1: Visit the SciPhi website. Step2: Sign up for an account or log in. Step3: Access the platform's dashboard. Step4: Follow guides to build and deploy your RAG system. Step5: Use tools for knowledge graph extraction and management. Step6: Optimize and monitor your system using provided observability features. SciPhi's Core Features &amp; Benefits The Core Features of SciPhi End-to-End RAG System Deployment Automated Knowledge Graph Extraction Document and User Management Robust Observability Tools The Benefits of SciPhi Simplifies AI Development Speeds Up Deployment Time Enhances System Optimization Reduces Infrastructure Complexity SciPhi's Main Use Cases &amp; Applications Building RAG Systems for AI Applications Deploying Knowledge Graphs Managing Large Document Repositories Optimizing AI System Performance FAQs of SciPhi SciPhi is an open-source platform designed to simplify building, deploying, and optimizing Retrieval-Augmented Generation (RAG) systems. SciPhi is intended for developers, AI engineers, data scientists, tech startups, and research institutions. Core features include end-to-end RAG system deployment, automated knowledge graph extraction, document and user management, and robust observability tools. Visit the SciPhi website, sign up for an account, and follow the guides to build and deploy your RAG system. SciPhi supports web platforms. SciPhi simplifies AI development, speeds up deployment time, enhances system optimization, and reduces infrastructure complexity. Yes, alternatives include LangChain, LlamaIndex, Haystack, and Flower. SciPhi supports building RAG systems for AI applications, deploying knowledge graphs, managing large document repositories, and optimizing AI system performance. You can reach out to their support team via their support email provided on the website. SciPhi offers both free and paid plans. Details on pricing can be found on their website. SciPhi Company Information Website: https://www.sciphi.ai Company Name: SciPhi Support Email: [ema",
1285
+ image: "https://cdn-image.creati.ai/ai-tools/product-image/sciphi.webp",
1286
+ favicon: "https://cdn-image.creati.ai/image/Creatiai.ico"
1287
+ },
1288
+ {
1289
+ id: "https://helpjuice.com/blog/open-source-knowledge-base",
1290
+ title: "The 12 Best Open Source Knowledge Base Software for 2024",
1291
+ url: "https://helpjuice.com/blog/open-source-knowledge-base",
1292
+ author: "Zeeshan Khan",
1293
+ text: "\n \n \n \n \n At Helpjuice / \n \n #Software &amp; Alternatives\n May 15 2025 \n 11m read \n \n \n \n \n On the hunt for the perfect knowledge base software that\u2019s open source? This post will walk you through the best options for your business. \n \n \n \n \n There\u2019s no denying that a knowledge base can make a major impact on your organization.\xA0 Whether it's to help provide better support to your customers or to enable your employees to find the information they need to do their job, a finely-tuned knowledge base can make all the difference when it comes to how knowledge and information flows through your business. And with plenty of options on the market out there, there\u2019s certainly no shortage of open source knowledge base software. But how can you tell you\u2019re not investing time into installing and learning new software that your team won't use anyway? How can you avoid the time and effort put into an open source option that you later determine to not be a good fit for your needs?\xA0 It\u2019s simple\u2014do a little research beforehand. We know, we know\u2014you don\u2019t have endless time to invest in that kind of thing (what with a business to run and all). That\u2019s why we\u2019ve created a helpful list of the must-consider open source knowledge base software that companies of all niches, industries, and sizes should consider.\xA0 We\u2019re even throwing in a little helpful knowledge that should equip you with the information needed to choose the right software for you\u2014like what knowledge base software is in the first place, the benefits of open source software, and how to address your unique needs as a company to choose the right software for you.\xA0 Want to skip ahead on some of the basics of open-source knowledge base software?\xA0 Be our guest.\xA0 The best open source knowledge base software includes: \n BookStack \n OpenKM \n myBase \n eXo \n PHPKB \n Documize \n DocuWiki \n phpMyFAQ \n MediaWiki \n xWiki \n TWiki \n TiddlyWiki \n What is an Open Source Knowledge Base? Before we dive into which open-source knowledge base software you should consider for your business, we should probably ensure we\u2019re on the same page about what exactly open-source knowledge base software is.\xA0 First things first, let\u2019s start with the term knowledge base. A knowledge base is a central place that allows structured storage of information where users can search for and access this information. \xA0Knowledge base software should be the key tool that helps make this process seamless, simplified, and efficient. Knowledge base software is designed to help you create and manage your knowledge base to the best of your ability. this usually includes setting up the knowledge base architecture, creating and editing documentation, searching, and analyzing your knowledge base, and more. Ideally, this is the irreplaceable piece of the puzzle that operates your entire knowledge management system that helps orchestrate, manage, and optimize the flow of knowledge within your organization.\xA0 That part seems pretty clear, right? Next, we\u2019ll move on to",
1294
+ image: "https://static.helpjuice.com/helpjuice_production/uploads/upload/image/4752/direct/1636499945090-Open%20Source%20Knowledge%20Base%20Software.jpg",
1295
+ favicon: "https://static.helpjuice.com/assets/favicon-32x32-161f2153235b710a8ed7b9233ed6b195936bdb57bf1310e720f7fea79547cf9d.png"
1296
+ }
1297
+ ],
1298
+ costDollars: {
1299
+ total: 0.015,
1300
+ search: {
1301
+ neural: 5e-3
1302
+ },
1303
+ contents: {
1304
+ text: 0.01
1275
1305
  }
1276
- return {
1277
- data: data2,
1278
- schema: entry.schema
1279
- };
1280
- }).filter((object) => !existingIds.has(object.data.id));
1281
- const { objects: dbObjects } = await db.query(Query.select(Filter.ids(...existingIds))).run();
1282
- const queueObjects = await queue?.getObjectsById([
1283
- ...existingIds
1284
- ]) ?? [];
1285
- const objects = [
1286
- ...dbObjects,
1287
- ...queueObjects
1288
- ].filter(isNonNullable);
1289
- log4.info("objects", {
1290
- dbObjects,
1291
- queueObjects,
1292
- existingIds
1293
- }, {
1294
- F: __dxlog_file4,
1295
- L: 306,
1296
- S: void 0,
1297
- C: (f, a) => f(...a)
1298
- });
1299
- const missing = Array.from(existingIds).filter((id) => !objects.some((object) => object.id === id));
1300
- if (missing.length > 0) {
1301
- throw new Error(`Object IDs do not point to existing objects: ${missing.join(", ")}`);
1302
1306
  }
1303
- return res.flatMap(({ data: data2, schema }) => {
1304
- let skip = false;
1305
- if (RelationSourceDXNId in data2) {
1306
- const id = data2[RelationSourceDXNId].asEchoDXN()?.echoId;
1307
- const obj = objects.find((object) => object.id === id) ?? enitties.get(id);
1308
- if (obj) {
1309
- delete data2[RelationSourceDXNId];
1310
- data2[RelationSourceId] = obj;
1311
- } else {
1312
- skip = true;
1307
+ };
1308
+
1309
+ // src/testing/data/index.ts
1310
+ var SEARCH_RESULTS = [
1311
+ exa_search_1748337321991_default,
1312
+ exa_search_1748337331526_default,
1313
+ exa_search_1748337344119_default
1314
+ ];
1315
+
1316
+ // src/functions/exa/mock.ts
1317
+ var mock_default = defineFunction7({
1318
+ key: "dxos.org/function/exa-mock",
1319
+ name: "Exa mock",
1320
+ description: "Search the web for information",
1321
+ inputSchema: Schema8.Struct({
1322
+ query: Schema8.String.annotations({
1323
+ description: "The query to search for."
1324
+ })
1325
+ }),
1326
+ outputSchema: Schema8.Unknown,
1327
+ handler: Effect8.fnUntraced(function* ({ data: { query } }) {
1328
+ const result = SEARCH_RESULTS.reduce((closest, current) => {
1329
+ if (!current.autopromptString) {
1330
+ return closest;
1313
1331
  }
1314
- }
1315
- if (RelationTargetDXNId in data2) {
1316
- const id = data2[RelationTargetDXNId].asEchoDXN()?.echoId;
1317
- const obj = objects.find((object) => object.id === id) ?? enitties.get(id);
1318
- if (obj) {
1319
- delete data2[RelationTargetDXNId];
1320
- data2[RelationTargetId] = obj;
1321
- } else {
1322
- skip = true;
1332
+ if (!closest) {
1333
+ return current;
1323
1334
  }
1324
- }
1325
- if (!skip) {
1326
- const obj = create(schema, data2);
1327
- enitties.set(obj.id, obj);
1328
- return [
1329
- obj
1330
- ];
1331
- }
1332
- return [];
1333
- });
1334
- };
1335
- var SoftRef = Schema8.Struct({
1336
- "/": Schema8.String
1337
- }).annotations({
1338
- description: "Reference to another object."
1335
+ const dist1 = levenshteinDistance(query, current.autopromptString);
1336
+ const dist2 = levenshteinDistance(query, closest.autopromptString || "");
1337
+ const weight1 = dist1 / Math.max(query.length, current.autopromptString.length);
1338
+ const weight2 = dist2 / Math.max(query.length, closest.autopromptString?.length || 0);
1339
+ return weight1 < weight2 ? current : closest;
1340
+ }, null);
1341
+ return result;
1342
+ })
1339
1343
  });
1340
- var preprocessSchema = (schema) => {
1341
- const isRelationSchema = getEntityKind(schema) === "relation";
1342
- const go = (ast, visited = /* @__PURE__ */ new Set()) => {
1343
- if (visited.has(ast)) {
1344
- return ast;
1345
- }
1346
- visited.add(ast);
1347
- if (SchemaAST.getAnnotation(ast, ReferenceAnnotationId).pipe(Option3.isSome)) {
1348
- return SoftRef.ast;
1344
+ var levenshteinDistance = (str1, str2) => {
1345
+ const m = str1.length;
1346
+ const n = str2.length;
1347
+ const dp = Array(m + 1).fill(null).map(() => Array(n + 1).fill(0));
1348
+ for (let i = 0; i <= m; i++) {
1349
+ dp[i][0] = i;
1350
+ }
1351
+ for (let j = 0; j <= n; j++) {
1352
+ dp[0][j] = j;
1353
+ }
1354
+ for (let i = 1; i <= m; i++) {
1355
+ for (let j = 1; j <= n; j++) {
1356
+ dp[i][j] = str1[i - 1] === str2[j - 1] ? dp[i - 1][j - 1] : Math.min(dp[i - 1][j - 1], dp[i - 1][j], dp[i][j - 1]) + 1;
1349
1357
  }
1350
- return mapAst(ast, (child) => go(child, visited));
1351
- };
1352
- return Schema8.make(mapAst(schema.ast, (ast) => go(ast))).pipe(Schema8.omit("id"), Schema8.extend(Schema8.Struct({
1353
- id: Schema8.String.annotations({
1354
- description: "The id of this object. Come up with a unique id based on your judgement."
1355
- })
1356
- })), isRelationSchema ? Schema8.extend(Schema8.Struct({
1357
- source: Schema8.String.annotations({
1358
- description: "The id of the source object for this relation."
1359
- }),
1360
- target: Schema8.String.annotations({
1361
- description: "The id of the target object for this relation."
1362
- })
1363
- })) : Function3.identity);
1358
+ }
1359
+ return dp[m][n];
1364
1360
  };
1365
1361
 
1366
- // raw-loader:/__w/dxos/dxos/packages/core/assistant-toolkit/src/functions/research/instructions-research.tpl?raw
1367
- var instructions_research_default = "You are the Research Agent.\n\nThe Research Agent is an expert assistant that conducts in-depth research using real-time web search.\nThe Research Agent outputs results in a structured format matching the schema provided.\n\nThe Research Agent is equipped with the ability to:\n\n- Generate precise and effective search queries \n- Request web pages by query (through a `web_search` tool)\n- Read the full content of retrieved pages\n- Synthesize accurate, clear, and structured answers using reliable information from the retrieved content\n- Search the local database for information using a vector index (through a `local_search` tool)\n\nThe Research Agent always follows these principles:\n\n- Relevance First: The Research Agent only returns facts supported by content in retrieved web pages. The Research Agent never fabricates or guesses information.\n- Summarize, Don't Copy: The Research Agent synthesizes and rephrases content in its own words. The Research Agent quotes only when necessary.\n- Multiple Sources: The Research Agent cross-references at least 2 sources before drawing conclusions, unless the information is directly stated and non-controversial.\n- Transparency: The Research Agent mentions which sources were used and explains how it arrived at conclusions.\n- Accuracy Over Brevity: The Research Agent prefers detailed, technically accurate explanations over shallow summaries.\n- The Research Agent admits uncertainty rather than misleading.\n- The Research Agent picks the most concrete schema types for extracted information.\n- The Research Agent fills schema fields completely with information it is confident about, and omits fields it is not confident about.\n- When outputting results, the Research Agent adds extra data that fits the schema even if not directly related to the user's question.\n- The Research Agent creates relations and references between new objects found and what's already in the database.\n- The Research Agent does not create objects that are already in the database.\n- The Research Agent re-uses existing object IDs as references when enriching existing objects.\n- The Research Agent ALWAYS calls the `graph_writer` at the end to save the data. This conversation will be deleted, so only the data written to the graph will be preserved.\n\nThe Research Agent may be asked for:\n\n- Technical explanations\n- Literature reviews \n- Comparisons\n- Emerging trends\n- Implementation strategies\n\nThe Research Agent begins by interpreting the user's request, then:\n\nThe Research Agent breaks it into sub-questions (if applicable).\n\nFor each sub-question, the Research Agent generates a clear, concise web search query.\n\nThe Research Agent uses `web_search`(query) to retrieve information.\n\nThe Research Agent extracts and synthesizes relevant answers.\n\nThe Research Agent's output includes:\n\n- A clear, structured answer to the user's question\n- A citation list or link list of sources used\n\nOptionally, the Research Agent provides follow-up suggestions or questions for deeper inquiry.\n\nHere's how the Research Agent operates:\n\n1. The Research Agent analyzes the user's request and identifies key topics to search for (3 or more), printing them out.\n2. The Research Agent performs a web search for each topic.\n3. The Research Agent reads and analyzes results, cross references information from multiple sources, and represents conflicting information as ranges of possible values.\n\n4. The Research Agent searches the local database for information using a vector index that might link to the user's question.\n6. The Research Agent creates relations and references between new objects and existing database objects when related, using existing object IDs as references.\n7. The Research Agent selects the most concrete schema types for extracted information, using multiple types as needed, and prints its decision and reasoning.\n5. The Research Agent creates a clear, structured answer to the user's question.\n8. The Research Agent submits results using the specific schema.\n\nIMPORTANT:\n\n- The Research Agent always runs the `local_search` tool to search the local database at least once before submitting results.\n- The Research Agent does not create objects that already exist in the database.\n- Ids that are not in the database are human-readable strings like `ivan_zhao_1`.\n\nStatus reporting:\n\nThe Research Agent reports its status frequently using the `<status>` tags: <status>Searching for Google Founders</status>\nThe Research Agent reports its status in-between each tool call and before submitting results.\n\n<example>\n\nBased on my research, I can now provide information about Google and it's founders.\n\nThe following objects are already in the database, I will not submit them again, but I'll re-use their IDs as references:\n\n- 01JWRDEHPB5TT2JQQQC15038BT Google\n- 01JWRDEHPA14CYW2NW9FAH6DJJ Larry Page\n- 01JWRDEHPBN0BBJP57B9S108W6 Sergey Brin\n\nI will use the following schema to construct new objects:\n\n- type:dxos.org/type/Organization for Alphabet Inc.\n- type:dxos.org/type/Person for Ivan Zhao\n- type:dxos.org/type/Person for Simon Last\n- dxn:type:dxos.org/relation/Employer for Ivan's employer\n- dxn:type:dxos.org/relation/Employer for Simon's employer\n\n<status>Formatting results</status>\n\n</example>";
1368
-
1369
1362
  // src/functions/research/research-graph.ts
1370
1363
  import * as Effect9 from "effect/Effect";
1371
1364
  import * as Layer2 from "effect/Layer";
1372
1365
  import * as Schema9 from "effect/Schema";
1373
- import { Obj as Obj4, Query as Query2, Ref as Ref2, Type as Type2 } from "@dxos/echo";
1366
+ import { Obj as Obj5, Query as Query2, Ref as Ref2, Type as Type2 } from "@dxos/echo";
1374
1367
  import { Queue } from "@dxos/echo-db";
1375
1368
  import { ContextQueueService as ContextQueueService2, DatabaseService as DatabaseService6, QueueService } from "@dxos/functions";
1376
1369
  var ResearchGraph = Schema9.Struct({
@@ -1385,7 +1378,7 @@ var queryResearchGraph = Effect9.fn("queryResearchGraph")(function* () {
1385
1378
  });
1386
1379
  var createResearchGraph = Effect9.fn("createResearchGraph")(function* () {
1387
1380
  const queue = yield* QueueService.createQueue();
1388
- return yield* DatabaseService6.add(Obj4.make(ResearchGraph, {
1381
+ return yield* DatabaseService6.add(Obj5.make(ResearchGraph, {
1389
1382
  queue: Ref2.fromDXN(queue.dxn)
1390
1383
  }));
1391
1384
  });
@@ -1395,21 +1388,25 @@ var contextQueueLayerFromResearchGraph = Layer2.unwrapEffect(Effect9.gen(functio
1395
1388
  return ContextQueueService2.layer(researchQueue);
1396
1389
  }));
1397
1390
 
1391
+ // raw-loader:/__w/dxos/dxos/packages/core/assistant-toolkit/src/functions/research/research-instructions.tpl?raw
1392
+ var research_instructions_default = "You are the Research Agent.\n\nThe Research Agent is an expert assistant that conducts in-depth research using real-time web search.\nThe Research Agent outputs results in a structured format matching the schema provided.\n\nThe Research Agent is equipped with the ability to:\n\n- Generate precise and effective search queries \n- Request web pages by query.\n- Synthesize accurate, clear, and structured answers using reliable information from the retrieved content\n{{#if entityExtraction}}\n- Search the local database for information using a vector index (through a `local_search` tool)\n{{/if}}\n\nThe Research Agent always follows these principles:\n\n- Relevance First: The Research Agent only returns facts supported by content in retrieved web pages. The Research Agent never fabricates or guesses information.\n- Summarize, Don't Copy: The Research Agent synthesizes and rephrases content in its own words. The Research Agent quotes only when necessary.\n- Multiple Sources: The Research Agent cross-references at least 2 sources before drawing conclusions, unless the information is directly stated and non-controversial.\n- Transparency: The Research Agent mentions which sources were used and explains how it arrived at conclusions.\n- Accuracy Over Brevity: The Research Agent prefers detailed, technically accurate explanations over shallow summaries.\n- The Research Agent admits uncertainty rather than misleading.\n{{#if entityExtraction}}\n- The Research Agent picks the most concrete schema types for extracted information.\n- The Research Agent fills schema fields completely with information it is confident about, and omits fields it is not confident about.\n- When outputting results, the Research Agent adds extra data that fits the schema even if not directly related to the user's question.\n- The Research Agent creates relations and references between new objects found and what's already in the database.\n- The Research Agent does not create objects that are already in the database.\n- The Research Agent re-uses existing object IDs as references when enriching existing objects.\n- The Research Agent ALWAYS calls the `graph_writer` at the end to save the data. This conversation will be deleted, so only the data written to the graph will be preserved.\n{{/if}}\n\nThe Research Agent may be asked for:\n\n- Technical explanations\n- Literature reviews \n- Comparisons\n- Emerging trends\n- Implementation strategies\n\nThe Research Agent begins by interpreting the user's request, then:\n\nThe Research Agent breaks it into sub-questions (if applicable).\n\nFor each sub-question, the Research Agent generates a clear, concise web search query.\n\nThe Research Agent extracts and synthesizes relevant answers.\n\nThe Research Agent's output includes:\n\n- A clear, structured answer to the user's question\n- A citation list or link list of sources used\n\nOptionally, the Research Agent provides follow-up suggestions or questions for deeper inquiry.\n\nHere's how the Research Agent operates:\n\n1. The Research Agent analyzes the user's request and identifies key topics to search for (3 or more), printing them out.\n2. The Research Agent performs a web search for each topic.\n3. The Research Agent reads and analyzes results, cross references information from multiple sources, and represents conflicting information as ranges of possible values.\n\n{{#if entityExtraction}}\n4. The Research Agent searches the local database for information using a vector index that might link to the user's question.\n6. The Research Agent creates relations and references between new objects and existing database objects when related, using existing object IDs as references.\n7. The Research Agent selects the most concrete schema types for extracted information, using multiple types as needed, and prints its decision and reasoning.\n5. The Research Agent creates a clear, structured answer to the user's question.\n8. The Research Agent submits results using the specific schema.\n{{/if}}\n\n{{#if entityExtraction}}\nIMPORTANT:\n- The Research Agent always runs the `local_search` tool to search the local database at least once before submitting results.\n- The Research Agent does not create objects that already exist in the database.\n- Ids that are not in the database are human-readable strings like `ivan_zhao_1`.\n{{/if}}\n\nStatus reporting:\n\nThe Research Agent reports its status frequently using the `<status>` tags: <status>Searching for Google Founders</status>\nThe Research Agent reports its status in-between each tool call and before submitting results.\n\n{{#if entityExtraction}}\n<example>\n\nBased on my research, I can now provide information about Google and it's founders.\n\nThe following objects are already in the database, I will not submit them again, but I'll re-use their IDs as references:\n\n- 01JWRDEHPB5TT2JQQQC15038BT Google\n- 01JWRDEHPA14CYW2NW9FAH6DJJ Larry Page\n- 01JWRDEHPBN0BBJP57B9S108W6 Sergey Brin\n\nI will use the following schema to construct new objects:\n\n- type:dxos.org/type/Organization for Alphabet Inc.\n- type:dxos.org/type/Person for Ivan Zhao\n- type:dxos.org/type/Person for Simon Last\n- dxn:type:dxos.org/relation/Employer for Ivan's employer\n- dxn:type:dxos.org/relation/Employer for Simon's employer\n\n<status>Formatting results</status>\n\n</example>\n{{/if}}\n\nLast content block is the full research note -- the result of the research.\n";
1393
+
1398
1394
  // src/functions/research/types.ts
1399
- import { DataType as DataType3 } from "@dxos/schema";
1395
+ import { Text } from "@dxos/schema";
1396
+ import { Event, HasConnection, HasRelationship, LegacyOrganization, LegacyPerson, Project, Task } from "@dxos/types";
1400
1397
  var ResearchDataTypes = [
1401
1398
  // Objects
1402
- DataType3.Event,
1403
- DataType3.LegacyOrganization,
1404
- DataType3.LegacyPerson,
1405
- DataType3.Project,
1406
- DataType3.Task,
1407
- DataType3.Text,
1399
+ Event.Event,
1400
+ LegacyOrganization,
1401
+ Task.Task,
1402
+ Text.Text,
1408
1403
  // Relations
1409
- // TODO(wittjosiah): Until views (e.g. table) support relations this needs to be expressed via organization ref.
1410
- // DataType.Employer,
1411
- DataType3.HasRelationship,
1412
- DataType3.HasConnection
1404
+ // TODO(wittjosiah): Until views (e.g., Table) support relations this needs to be expressed via organization ref.
1405
+ // Employer.Employer,
1406
+ LegacyPerson,
1407
+ Project.Project,
1408
+ HasRelationship.HasRelationship,
1409
+ HasConnection.HasConnection
1413
1410
  ];
1414
1411
 
1415
1412
  // src/functions/research/research.ts
@@ -1417,40 +1414,46 @@ var research_default = defineFunction8({
1417
1414
  key: "dxos.org/function/research",
1418
1415
  name: "Research",
1419
1416
  description: trim3`
1420
- Research the web for information.
1417
+ Search the web to research information about the given subject.
1421
1418
  Inserts structured data into the research graph.
1422
- Will return research summary and the objects created.
1419
+ Creates a research summary and returns the objects created.
1423
1420
  `,
1424
1421
  inputSchema: Schema10.Struct({
1425
1422
  query: Schema10.String.annotations({
1426
1423
  description: trim3`
1427
- The query to search for.
1428
- If doing research on an object, load it first and pass it as a JSON string.
1424
+ The search query.
1425
+ If doing research on an object then load it first and pass it as JSON.
1429
1426
  `
1430
1427
  }),
1431
- researchInstructions: Schema10.optional(Schema10.String).annotations({
1428
+ instructions: Schema10.optional(Schema10.String).annotations({
1432
1429
  description: trim3`
1433
1430
  The instructions for the research agent.
1434
- E.g., preference on fast responses or in-depth analysis, number of web searcher or the objects created.
1435
1431
  `
1436
1432
  }),
1437
1433
  // TOOD(burdon): Move to context.
1438
1434
  mockSearch: Schema10.optional(Schema10.Boolean).annotations({
1439
1435
  description: "Whether to use the mock search tool.",
1440
1436
  default: false
1437
+ }),
1438
+ entityExtraction: Schema10.optional(Schema10.Boolean).annotations({
1439
+ description: trim3`
1440
+ Whether to extract structured entities from the research.
1441
+ Experimental feature only enable if user explicitly requests it.
1442
+ `,
1443
+ default: false
1441
1444
  })
1442
1445
  }),
1443
1446
  outputSchema: Schema10.Struct({
1444
- note: Schema10.optional(Schema10.String).annotations({
1445
- description: "A note from the research agent."
1447
+ document: Schema10.optional(Schema10.String).annotations({
1448
+ description: "The generated research document."
1446
1449
  }),
1447
1450
  objects: Schema10.Array(Schema10.Unknown).annotations({
1448
- description: "The structured objects created as a result of the research."
1451
+ description: "Structured objects created during the research process."
1449
1452
  })
1450
1453
  }),
1451
- handler: Effect10.fnUntraced(function* ({ data: { query, mockSearch, researchInstructions } }) {
1454
+ handler: Effect10.fnUntraced(function* ({ data: { query, instructions: instructions6, mockSearch = false, entityExtraction = false } }) {
1452
1455
  if (mockSearch) {
1453
- const mockPerson = yield* DatabaseService7.add(Obj5.make(DataType4.Person, {
1456
+ const mockPerson = yield* DatabaseService7.add(Obj6.make(Person.Person, {
1454
1457
  preferredName: "John Doe",
1455
1458
  emails: [
1456
1459
  {
@@ -1464,13 +1467,12 @@ var research_default = defineFunction8({
1464
1467
  ]
1465
1468
  }));
1466
1469
  return {
1467
- note: trim3`
1468
- The research run in test-mode and was mocked.
1469
- Proceed as usual.
1470
- We reference John Doe to test reference: ${Obj5.getDXN(mockPerson)}
1470
+ document: trim3`
1471
+ The research ran in test-mode and was mocked. Proceed as usual.
1472
+ We reference John Doe to test reference: ${Obj6.getDXN(mockPerson)}
1471
1473
  `,
1472
1474
  objects: [
1473
- Obj5.toJSON(mockPerson)
1475
+ Obj6.toJSON(mockPerson)
1474
1476
  ]
1475
1477
  };
1476
1478
  }
@@ -1478,38 +1480,39 @@ var research_default = defineFunction8({
1478
1480
  indexes: true
1479
1481
  });
1480
1482
  yield* TracingService4.emitStatus({
1481
- message: "Researching..."
1482
- });
1483
- const objectDXNs = [];
1484
- const GraphWriterToolkit = makeGraphWriterToolkit({
1485
- schema: ResearchDataTypes
1486
- });
1487
- const GraphWriterHandler = makeGraphWriterHandler(GraphWriterToolkit, {
1488
- onAppend: (dxns) => objectDXNs.push(...dxns)
1483
+ message: "Starting research..."
1489
1484
  });
1490
1485
  const NativeWebSearch = Toolkit2.make(AnthropicTool.WebSearch_20250305({}));
1491
- const toolkit = yield* createToolkit2({
1492
- toolkit: Toolkit2.merge(LocalSearchToolkit, GraphWriterToolkit, NativeWebSearch)
1493
- }).pipe(Effect10.provide(Layer3.mergeAll(
1494
- //
1495
- GraphWriterHandler,
1496
- LocalSearchHandler
1497
- ).pipe(Layer3.provide(contextQueueLayerFromResearchGraph))));
1486
+ let toolkit = NativeWebSearch;
1487
+ let handlers = Layer3.empty;
1488
+ const objectDXNs = [];
1489
+ if (entityExtraction) {
1490
+ const GraphWriterToolkit = makeGraphWriterToolkit({
1491
+ schema: ResearchDataTypes
1492
+ });
1493
+ const GraphWriterHandler = makeGraphWriterHandler(GraphWriterToolkit, {
1494
+ onAppend: (dxns) => objectDXNs.push(...dxns)
1495
+ });
1496
+ toolkit = Toolkit2.merge(toolkit, LocalSearchToolkit, GraphWriterToolkit);
1497
+ handlers = Layer3.mergeAll(handlers, LocalSearchHandler, GraphWriterHandler).pipe(Layer3.provide(contextQueueLayerFromResearchGraph));
1498
+ }
1499
+ const finishedToolkit = yield* createToolkit2({
1500
+ toolkit
1501
+ }).pipe(Effect10.provide(handlers));
1498
1502
  const session = new AiSession2();
1499
1503
  const result = yield* session.run({
1500
1504
  prompt: query,
1501
- system: instructions_research_default + (researchInstructions ? `
1502
-
1503
- <research_instructions>${researchInstructions}</research_instructions>` : ""),
1504
- toolkit,
1505
+ system: join(Template2.process(research_instructions_default, {
1506
+ entityExtraction
1507
+ }), instructions6 && `<instructions>${instructions6}</instructions>`),
1508
+ toolkit: finishedToolkit,
1505
1509
  observer: GenerationObserver2.fromPrinter(new ConsolePrinter2({
1506
1510
  tag: "research"
1507
1511
  }))
1508
1512
  });
1509
- const note = result.at(-1)?.blocks.filter((block) => block._tag === "text").at(-1)?.text;
1510
- const objects = yield* Effect10.forEach(objectDXNs, (dxn) => DatabaseService7.resolve(dxn)).pipe(Effect10.map(Array6.map((obj) => Obj5.toJSON(obj))));
1513
+ const objects = yield* Effect10.forEach(objectDXNs, (dxn) => DatabaseService7.resolve(dxn)).pipe(Effect10.map(Array6.map((obj) => Obj6.toJSON(obj))));
1511
1514
  return {
1512
- note,
1515
+ document: extractLastTextBlock(result),
1513
1516
  objects
1514
1517
  };
1515
1518
  }, Effect10.provide(Layer3.mergeAll(
@@ -1522,7 +1525,7 @@ var research_default = defineFunction8({
1522
1525
  makeToolExecutionServiceFromFunctions(Toolkit2.make(), Layer3.empty)
1523
1526
  ).pipe(Layer3.provide(
1524
1527
  // TODO(dmaretskyi): This should be provided by environment.
1525
- Layer3.mergeAll(FunctionInvocationService.layerTestMocked({
1528
+ Layer3.mergeAll(FunctionInvocationServiceLayerTestMocked({
1526
1529
  functions: [
1527
1530
  exa_default,
1528
1531
  mock_default
@@ -1530,10 +1533,14 @@ var research_default = defineFunction8({
1530
1533
  }))
1531
1534
  ))))
1532
1535
  });
1536
+ var join = (...strings) => strings.filter(Boolean).join("\n\n");
1537
+ var extractLastTextBlock = (result) => {
1538
+ return Function4.pipe(result, Array6.last, Option4.map(Function4.flow((_) => _.blocks, Array6.reverse, Array6.dropWhile((_) => _._tag === "summary"), Array6.takeWhile((_) => _._tag === "text"), Array6.reverse, Array6.map((_) => _.text), Array6.reduce("", String10.concat))), Option4.getOrElse(() => ""));
1539
+ };
1533
1540
 
1534
1541
  // src/functions/research/index.ts
1535
1542
  (function(Research2) {
1536
- Research2.create = create_document_default;
1543
+ Research2.create = document_create_default;
1537
1544
  Research2.research = research_default;
1538
1545
  })(Research || (Research = {}));
1539
1546
  var Research;
@@ -1545,7 +1552,7 @@ var entity_extraction_default = defineFunction9({
1545
1552
  name: "Entity Extraction",
1546
1553
  description: "Extracts entities from emails and transcripts.",
1547
1554
  inputSchema: Schema11.Struct({
1548
- source: DataType5.Message.annotations({
1555
+ source: Message2.Message.annotations({
1549
1556
  description: "Email or transcript to extract entities from."
1550
1557
  }),
1551
1558
  // TODO(dmaretskyi): Consider making this an array of blueprints instead.
@@ -1554,7 +1561,7 @@ var entity_extraction_default = defineFunction9({
1554
1561
  })
1555
1562
  }),
1556
1563
  outputSchema: Schema11.Struct({
1557
- entities: Schema11.optional(Schema11.Array(Obj6.Any).annotations({
1564
+ entities: Schema11.optional(Schema11.Array(Obj7.Any).annotations({
1558
1565
  description: "Extracted entities."
1559
1566
  }))
1560
1567
  }),
@@ -1565,7 +1572,7 @@ var entity_extraction_default = defineFunction9({
1565
1572
  const created = [];
1566
1573
  const GraphWriterToolkit = makeGraphWriterToolkit({
1567
1574
  schema: [
1568
- DataType5.LegacyOrganization
1575
+ LegacyOrganization2
1569
1576
  ]
1570
1577
  }).pipe();
1571
1578
  const GraphWriterHandler = makeGraphWriterHandler(GraphWriterToolkit, {
@@ -1587,9 +1594,9 @@ var entity_extraction_default = defineFunction9({
1587
1594
  if (created.length > 1) {
1588
1595
  throw new Error("Multiple organizations created");
1589
1596
  } else if (created.length === 1) {
1590
- organization = yield* DatabaseService8.resolve(created[0], DataType5.Organization);
1591
- Obj6.getMeta(organization).tags ??= [];
1592
- Obj6.getMeta(organization).tags.push(...Obj6.getMeta(source)?.tags ?? []);
1597
+ organization = yield* DatabaseService8.resolve(created[0], Organization.Organization);
1598
+ Obj7.getMeta(organization).tags ??= [];
1599
+ Obj7.getMeta(organization).tags.push(...Obj7.getMeta(source)?.tags ?? []);
1593
1600
  contact.organization = Ref3.make(organization);
1594
1601
  }
1595
1602
  }
@@ -1601,7 +1608,7 @@ var entity_extraction_default = defineFunction9({
1601
1608
  };
1602
1609
  }, Effect11.provide(Layer4.mergeAll(AiService3.model("@anthropic/claude-sonnet-4-0"), makeToolResolverFromFunctions2([], Toolkit3.make()), makeToolExecutionServiceFromFunctions2(Toolkit3.make(), Layer4.empty)).pipe(Layer4.provide(
1603
1610
  // TODO(dmaretskyi): This should be provided by environment.
1604
- Layer4.mergeAll(FunctionInvocationService2.layerTest())
1611
+ Layer4.mergeAll(FunctionInvocationServiceLayerTest())
1605
1612
  ))))
1606
1613
  });
1607
1614
  var extractContact = Effect11.fn("extractContact")(function* (message) {
@@ -1612,13 +1619,13 @@ var extractContact = Effect11.fn("extractContact")(function* (message) {
1612
1619
  sender: message.sender
1613
1620
  }, {
1614
1621
  F: __dxlog_file5,
1615
- L: 97,
1622
+ L: 99,
1616
1623
  S: this,
1617
1624
  C: (f, a) => f(...a)
1618
1625
  });
1619
1626
  return void 0;
1620
1627
  }
1621
- const { objects: existingContacts } = yield* DatabaseService8.runQuery(Filter2.type(DataType5.Person));
1628
+ const { objects: existingContacts } = yield* DatabaseService8.runQuery(Filter2.type(Person2.Person));
1622
1629
  const existingContact = existingContacts.find((contact) => contact.emails?.some((contactEmail) => contactEmail.value === email));
1623
1630
  if (existingContact) {
1624
1631
  log5.info("Contact already exists", {
@@ -1626,15 +1633,15 @@ var extractContact = Effect11.fn("extractContact")(function* (message) {
1626
1633
  existingContact
1627
1634
  }, {
1628
1635
  F: __dxlog_file5,
1629
- L: 110,
1636
+ L: 112,
1630
1637
  S: this,
1631
1638
  C: (f, a) => f(...a)
1632
1639
  });
1633
1640
  return existingContact;
1634
1641
  }
1635
- const newContact = Obj6.make(DataType5.Person, {
1636
- [Obj6.Meta]: {
1637
- tags: Obj6.getMeta(message)?.tags
1642
+ const newContact = Obj7.make(Person2.Person, {
1643
+ [Obj7.Meta]: {
1644
+ tags: Obj7.getMeta(message)?.tags
1638
1645
  },
1639
1646
  emails: [
1640
1647
  {
@@ -1652,7 +1659,7 @@ var extractContact = Effect11.fn("extractContact")(function* (message) {
1652
1659
  email
1653
1660
  }, {
1654
1661
  F: __dxlog_file5,
1655
- L: 128,
1662
+ L: 130,
1656
1663
  S: this,
1657
1664
  C: (f, a) => f(...a)
1658
1665
  });
@@ -1662,11 +1669,11 @@ var extractContact = Effect11.fn("extractContact")(function* (message) {
1662
1669
  emailDomain
1663
1670
  }, {
1664
1671
  F: __dxlog_file5,
1665
- L: 132,
1672
+ L: 134,
1666
1673
  S: this,
1667
1674
  C: (f, a) => f(...a)
1668
1675
  });
1669
- const { objects: existingOrganisations } = yield* DatabaseService8.runQuery(Filter2.type(DataType5.Organization));
1676
+ const { objects: existingOrganisations } = yield* DatabaseService8.runQuery(Filter2.type(Organization.Organization));
1670
1677
  const matchingOrg = existingOrganisations.find((org) => {
1671
1678
  if (org.website) {
1672
1679
  try {
@@ -1679,7 +1686,7 @@ var extractContact = Effect11.fn("extractContact")(function* (message) {
1679
1686
  error: e
1680
1687
  }, {
1681
1688
  F: __dxlog_file5,
1682
- L: 150,
1689
+ L: 152,
1683
1690
  S: this,
1684
1691
  C: (f, a) => f(...a)
1685
1692
  });
@@ -1693,7 +1700,7 @@ var extractContact = Effect11.fn("extractContact")(function* (message) {
1693
1700
  organization: matchingOrg
1694
1701
  }, {
1695
1702
  F: __dxlog_file5,
1696
- L: 158,
1703
+ L: 160,
1697
1704
  S: this,
1698
1705
  C: (f, a) => f(...a)
1699
1706
  });
@@ -1713,16 +1720,16 @@ import * as FetchHttpClient2 from "@effect/platform/FetchHttpClient";
1713
1720
  import * as HttpClient from "@effect/platform/HttpClient";
1714
1721
  import * as Array9 from "effect/Array";
1715
1722
  import * as Effect13 from "effect/Effect";
1716
- import * as Function4 from "effect/Function";
1723
+ import * as Function5 from "effect/Function";
1717
1724
  import * as Schema12 from "effect/Schema";
1718
- import { Filter as Filter4, Obj as Obj8, Query as Query4, Ref as Ref5 } from "@dxos/echo";
1725
+ import { Filter as Filter4, Obj as Obj9, Query as Query4, Ref as Ref5 } from "@dxos/echo";
1719
1726
  import { DatabaseService as DatabaseService10, defineFunction as defineFunction10, withAuthorization } from "@dxos/functions";
1720
1727
  import { log as log7 } from "@dxos/log";
1721
- import { DataType as DataType6 } from "@dxos/schema";
1728
+ import { Person as Person3, Project as Project2, Task as Task2 } from "@dxos/types";
1722
1729
 
1723
1730
  // src/sync/sync.ts
1724
1731
  import * as Effect12 from "effect/Effect";
1725
- import { Filter as Filter3, Obj as Obj7, Query as Query3, Ref as Ref4 } from "@dxos/echo";
1732
+ import { Filter as Filter3, Obj as Obj8, Query as Query3, Ref as Ref4 } from "@dxos/echo";
1726
1733
  import { DatabaseService as DatabaseService9 } from "@dxos/functions";
1727
1734
  import { failedInvariant } from "@dxos/invariant";
1728
1735
  import { log as log6 } from "@dxos/log";
@@ -1734,7 +1741,7 @@ var syncObjects = Effect12.fn("syncObjects")(function* (objs, { foreignKeyId })
1734
1741
  if (!Ref4.isRef(obj[key])) continue;
1735
1742
  const ref = obj[key];
1736
1743
  if (!ref.target) continue;
1737
- if (Obj7.getDXN(ref.target).isLocalObjectId()) {
1744
+ if (Obj8.getDXN(ref.target).isLocalObjectId()) {
1738
1745
  const [target] = yield* syncObjects([
1739
1746
  ref.target
1740
1747
  ], {
@@ -1743,8 +1750,8 @@ var syncObjects = Effect12.fn("syncObjects")(function* (objs, { foreignKeyId })
1743
1750
  obj[key] = Ref4.make(target);
1744
1751
  }
1745
1752
  }
1746
- const schema = Obj7.getSchema(obj) ?? failedInvariant("No schema.");
1747
- const foreignId = Obj7.getKeys(obj, foreignKeyId)[0]?.id ?? failedInvariant("No foreign key.");
1753
+ const schema = Obj8.getSchema(obj) ?? failedInvariant("No schema.");
1754
+ const foreignId = Obj8.getKeys(obj, foreignKeyId)[0]?.id ?? failedInvariant("No foreign key.");
1748
1755
  const { objects: [existing] } = yield* DatabaseService9.runQuery(Query3.select(Filter3.foreignKeys(schema, [
1749
1756
  {
1750
1757
  source: foreignKeyId,
@@ -1752,9 +1759,9 @@ var syncObjects = Effect12.fn("syncObjects")(function* (objs, { foreignKeyId })
1752
1759
  }
1753
1760
  ])));
1754
1761
  log6("sync object", {
1755
- type: Obj7.getTypename(obj),
1762
+ type: Obj8.getTypename(obj),
1756
1763
  foreignId,
1757
- existing: existing ? Obj7.getDXN(existing) : void 0
1764
+ existing: existing ? Obj8.getDXN(existing) : void 0
1758
1765
  }, {
1759
1766
  F: __dxlog_file6,
1760
1767
  L: 47,
@@ -1784,9 +1791,9 @@ var copyObjectData = (existing, newObj) => {
1784
1791
  delete existing[key];
1785
1792
  }
1786
1793
  }
1787
- for (const foreignKey of Obj7.getMeta(newObj).keys) {
1788
- Obj7.deleteKeys(existing, foreignKey.source);
1789
- Obj7.getMeta(existing).keys.push({
1794
+ for (const foreignKey of Obj8.getMeta(newObj).keys) {
1795
+ Obj8.deleteKeys(existing, foreignKey.source);
1796
+ Obj8.getMeta(existing).keys.push({
1790
1797
  ...foreignKey
1791
1798
  });
1792
1799
  }
@@ -1853,7 +1860,7 @@ var sync_issues_default = defineFunction10({
1853
1860
  const client = yield* HttpClient.HttpClient.pipe(Effect13.map(withAuthorization({
1854
1861
  service: "linear.app"
1855
1862
  })));
1856
- const after = yield* getLatestUpdateTimestamp(data.team, DataType6.Task);
1863
+ const after = yield* getLatestUpdateTimestamp(data.team, Task2.Task);
1857
1864
  log7.info("will fetch", {
1858
1865
  after
1859
1866
  }, {
@@ -1895,10 +1902,10 @@ var getLatestUpdateTimestamp = Effect13.fnUntraced(function* (teamId, dataType)
1895
1902
  id: teamId
1896
1903
  }
1897
1904
  ])));
1898
- return Function4.pipe(existingTasks, Array9.map((task) => Obj8.getKeys(task, LINEAR_UPDATED_AT_KEY).at(0)?.id), Array9.filter((x) => x !== void 0), Array9.reduce("2025-01-01T00:00:00.000Z", (acc, x) => x > acc ? x : acc));
1905
+ return Function5.pipe(existingTasks, Array9.map((task) => Obj9.getKeys(task, LINEAR_UPDATED_AT_KEY).at(0)?.id), Array9.filter((x) => x !== void 0), Array9.reduce("2025-01-01T00:00:00.000Z", (acc, x) => x > acc ? x : acc));
1899
1906
  });
1900
- var mapLinearPerson = (person, { teamId }) => Obj8.make(DataType6.Person, {
1901
- [Obj8.Meta]: {
1907
+ var mapLinearPerson = (person, { teamId }) => Obj9.make(Person3.Person, {
1908
+ [Obj9.Meta]: {
1902
1909
  keys: [
1903
1910
  {
1904
1911
  id: person.id,
@@ -1912,8 +1919,8 @@ var mapLinearPerson = (person, { teamId }) => Obj8.make(DataType6.Person, {
1912
1919
  },
1913
1920
  nickname: person.name
1914
1921
  });
1915
- var mapLinearIssue = (issue, { teamId }) => Obj8.make(DataType6.Task, {
1916
- [Obj8.Meta]: {
1922
+ var mapLinearIssue = (issue, { teamId }) => Obj9.make(Task2.Task, {
1923
+ [Obj9.Meta]: {
1917
1924
  keys: [
1918
1925
  {
1919
1926
  id: issue.id,
@@ -1936,8 +1943,8 @@ var mapLinearIssue = (issue, { teamId }) => Obj8.make(DataType6.Task, {
1936
1943
  })),
1937
1944
  // TODO(dmaretskyi): Sync those (+ linear team as org?).
1938
1945
  // state: issue.state.name,
1939
- project: !issue.project ? void 0 : Ref5.make(DataType6.makeProject({
1940
- [Obj8.Meta]: {
1946
+ project: !issue.project ? void 0 : Ref5.make(Project2.make({
1947
+ [Obj9.Meta]: {
1941
1948
  keys: [
1942
1949
  {
1943
1950
  id: issue.project.id,
@@ -1962,7 +1969,7 @@ var Linear;
1962
1969
  // src/functions/tasks/read.ts
1963
1970
  import * as Effect14 from "effect/Effect";
1964
1971
  import * as Schema13 from "effect/Schema";
1965
- import { ArtifactId as ArtifactId3 } from "@dxos/assistant";
1972
+ import { ArtifactId as ArtifactId4 } from "@dxos/assistant";
1966
1973
  import { DatabaseService as DatabaseService11, defineFunction as defineFunction11 } from "@dxos/functions";
1967
1974
  import { Markdown as Markdown4 } from "@dxos/plugin-markdown/types";
1968
1975
  var read_default2 = defineFunction11({
@@ -1970,7 +1977,7 @@ var read_default2 = defineFunction11({
1970
1977
  name: "Read",
1971
1978
  description: "Read markdown tasks.",
1972
1979
  inputSchema: Schema13.Struct({
1973
- id: ArtifactId3.annotations({
1980
+ id: ArtifactId4.annotations({
1974
1981
  description: "The ID of the document to read."
1975
1982
  })
1976
1983
  }),
@@ -1978,7 +1985,7 @@ var read_default2 = defineFunction11({
1978
1985
  content: Schema13.String
1979
1986
  }),
1980
1987
  handler: Effect14.fn(function* ({ data: { id } }) {
1981
- const doc = yield* DatabaseService11.resolve(ArtifactId3.toDXN(id), Markdown4.Document);
1988
+ const doc = yield* DatabaseService11.resolve(ArtifactId4.toDXN(id), Markdown4.Document);
1982
1989
  const { content } = yield* DatabaseService11.load(doc.content);
1983
1990
  const lines = content.split("\n");
1984
1991
  const len = String(lines.length).length;
@@ -1992,7 +1999,7 @@ var read_default2 = defineFunction11({
1992
1999
  // src/functions/tasks/update.ts
1993
2000
  import * as Effect15 from "effect/Effect";
1994
2001
  import * as Schema14 from "effect/Schema";
1995
- import { ArtifactId as ArtifactId4 } from "@dxos/assistant";
2002
+ import { ArtifactId as ArtifactId5 } from "@dxos/assistant";
1996
2003
  import { DatabaseService as DatabaseService12, defineFunction as defineFunction12 } from "@dxos/functions";
1997
2004
  import { Markdown as Markdown5 } from "@dxos/plugin-markdown/types";
1998
2005
 
@@ -2130,7 +2137,7 @@ var update_default2 = defineFunction12({
2130
2137
  name: "Update markdown",
2131
2138
  description: "Creates and updates tasks in markdown documents.",
2132
2139
  inputSchema: Schema14.Struct({
2133
- id: ArtifactId4.annotations({
2140
+ id: ArtifactId5.annotations({
2134
2141
  description: "The ID of the document to update."
2135
2142
  }),
2136
2143
  operations: Schema14.optional(Schema14.Array(Schema14.Any.annotations({
@@ -2144,7 +2151,7 @@ var update_default2 = defineFunction12({
2144
2151
  })
2145
2152
  }),
2146
2153
  handler: Effect15.fn(function* ({ data: { id, operations = [] } }) {
2147
- const doc = yield* DatabaseService12.resolve(ArtifactId4.toDXN(id), Markdown5.Document);
2154
+ const doc = yield* DatabaseService12.resolve(ArtifactId5.toDXN(id), Markdown5.Document);
2148
2155
  const { content } = yield* DatabaseService12.load(doc.content);
2149
2156
  const taskManager = new MarkdownTasks(content);
2150
2157
  if (operations.length > 0) {
@@ -2174,12 +2181,12 @@ var instructions = trim5`
2174
2181
  When replying to the user, be terse with your comments about design doc handling.
2175
2182
  Do not announce when you read or write the design spec document.
2176
2183
  `;
2177
- var blueprint = Obj9.make(Blueprint.Blueprint, {
2184
+ var blueprint = Obj10.make(Blueprint.Blueprint, {
2178
2185
  key: "dxos.org/blueprint/design",
2179
2186
  name: "Design Spec",
2180
2187
  description: "Preserve the conversation in the design spec.",
2181
2188
  instructions: {
2182
- source: Ref6.make(DataType7.makeText(instructions))
2189
+ source: Ref6.make(Text2.make(instructions))
2183
2190
  },
2184
2191
  tools: [
2185
2192
  Document.read,
@@ -2194,8 +2201,8 @@ var design_default = design_blueprint_default;
2194
2201
  // src/blueprints/discord/discord-blueprint.ts
2195
2202
  import { ToolId as ToolId2 } from "@dxos/ai";
2196
2203
  import { Blueprint as Blueprint2 } from "@dxos/blueprints";
2197
- import { Obj as Obj10, Ref as Ref7 } from "@dxos/echo";
2198
- import { DataType as DataType8 } from "@dxos/schema";
2204
+ import { Obj as Obj11, Ref as Ref7 } from "@dxos/echo";
2205
+ import { Text as Text3 } from "@dxos/schema";
2199
2206
  import { trim as trim6 } from "@dxos/util";
2200
2207
  var instructions2 = trim6`
2201
2208
  You are able to fetch messages from Discord servers.
@@ -2204,12 +2211,12 @@ var instructions2 = trim6`
2204
2211
 
2205
2212
  DXOS serverId: 837138313172353095
2206
2213
  `;
2207
- var blueprint2 = Obj10.make(Blueprint2.Blueprint, {
2214
+ var blueprint2 = Obj11.make(Blueprint2.Blueprint, {
2208
2215
  key: "dxos.org/blueprint/discord",
2209
2216
  name: "Discord",
2210
2217
  description: "Discord integration.",
2211
2218
  instructions: {
2212
- source: Ref7.make(DataType8.makeText(instructions2))
2219
+ source: Ref7.make(Text3.make(instructions2))
2213
2220
  },
2214
2221
  tools: [
2215
2222
  ToolId2.make(Discord.fetch.key)
@@ -2223,8 +2230,8 @@ var discord_default = discord_blueprint_default;
2223
2230
  // src/blueprints/linear/linear-blueprint.ts
2224
2231
  import { ToolId as ToolId3 } from "@dxos/ai";
2225
2232
  import { Blueprint as Blueprint3 } from "@dxos/blueprints";
2226
- import { Obj as Obj11, Ref as Ref8 } from "@dxos/echo";
2227
- import { DataType as DataType9 } from "@dxos/schema";
2233
+ import { Obj as Obj12, Ref as Ref8 } from "@dxos/echo";
2234
+ import { Text as Text4 } from "@dxos/schema";
2228
2235
  import { trim as trim7 } from "@dxos/util";
2229
2236
  var instructions3 = trim7`
2230
2237
  You are able to sync Linear workspaces.
@@ -2234,12 +2241,12 @@ var instructions3 = trim7`
2234
2241
 
2235
2242
  DXOS teamId: 1127c63a-6f77-4725-9229-50f6cd47321c
2236
2243
  `;
2237
- var blueprint3 = Obj11.make(Blueprint3.Blueprint, {
2244
+ var blueprint3 = Obj12.make(Blueprint3.Blueprint, {
2238
2245
  key: "dxos.org/blueprint/linear",
2239
2246
  name: "Linear",
2240
2247
  description: "Syncs Linear workspaces.",
2241
2248
  instructions: {
2242
- source: Ref8.make(DataType9.makeText(instructions3))
2249
+ source: Ref8.make(Text4.make(instructions3))
2243
2250
  },
2244
2251
  tools: [
2245
2252
  Linear.sync
@@ -2253,8 +2260,8 @@ var linear_default = linear_blueprint_default;
2253
2260
  // src/blueprints/planning/planning-blueprint.ts
2254
2261
  import { ToolId as ToolId4 } from "@dxos/ai";
2255
2262
  import { Blueprint as Blueprint4 } from "@dxos/blueprints";
2256
- import { Obj as Obj12, Ref as Ref9 } from "@dxos/echo";
2257
- import { DataType as DataType10 } from "@dxos/schema";
2263
+ import { Obj as Obj13, Ref as Ref9 } from "@dxos/echo";
2264
+ import { Text as Text5 } from "@dxos/schema";
2258
2265
  import { trim as trim8 } from "@dxos/util";
2259
2266
  var instructions4 = trim8`
2260
2267
  You are a task management agent that maintains hierarchical task lists where each line is a task.
@@ -2327,12 +2334,12 @@ var instructions4 = trim8`
2327
2334
  - When creating subtasks, consider the parent task's completion status
2328
2335
  - Be precise with task descriptions and hierarchy levels
2329
2336
  `;
2330
- var blueprint4 = Obj12.make(Blueprint4.Blueprint, {
2337
+ var blueprint4 = Obj13.make(Blueprint4.Blueprint, {
2331
2338
  key: "dxos.org/blueprint/planning",
2332
2339
  name: "Planning",
2333
2340
  description: "Plans and tracks complex tasks with artifact management.",
2334
2341
  instructions: {
2335
- source: Ref9.make(DataType10.makeText(instructions4))
2342
+ source: Ref9.make(Text5.make(instructions4))
2336
2343
  },
2337
2344
  tools: [
2338
2345
  Tasks.read,
@@ -2347,33 +2354,41 @@ var planning_default = planning_blueprint_default;
2347
2354
  // src/blueprints/research/research-blueprint.ts
2348
2355
  import { ToolId as ToolId5 } from "@dxos/ai";
2349
2356
  import { Blueprint as Blueprint5 } from "@dxos/blueprints";
2350
- import { Obj as Obj13, Ref as Ref10 } from "@dxos/echo";
2351
- import { DataType as DataType11 } from "@dxos/schema";
2357
+ import { Obj as Obj14, Ref as Ref10 } from "@dxos/echo";
2358
+ import { Text as Text6 } from "@dxos/schema";
2352
2359
  import { trim as trim9 } from "@dxos/util";
2353
2360
  var instructions5 = trim9`
2354
2361
  {{! Research }}
2355
2362
 
2356
2363
  You are an analyst that does research tasks using tools that scrape the web and create structured data.
2357
- The result of the research is a set of structured entities forming an interconnected graph.
2358
- When you are done, reply with the created objects.
2359
- Do not print the data, instead reply with inline references to the created objects.
2360
- Those will be later substituted with the pills representing the created objects.
2361
- Print the rest of the created objects as block references after the main note.
2362
-
2363
- <example>
2364
- Based on my research, Google was founded by @dxn:queue:data:B6INSIBY3CBEF4M5VZRYBCMAHQMPYK5AJ:01K24XMVHSZHS97SG1VTVQDM5Z:01K24XPK464FSCKVQJAB2H662M and @dxn:queue:data:B6INSIBY3CBEF4M5VZRYBCMAHQMPYK5AJ:01K24XMVHSZHS97SG1VTVQDM5Z:01K24XPK46K31DDW62PBW9H2ZQ
2365
-
2366
- <object><dxn>dxn:queue:data:B6INSIBY3CBEF4M5VZRYBCMAHQMPYK5AJ:01K24XMVHSZHS97SG1VTVQDM5Z:01K24XPK464FSCKVQJAB2H662M</dxn></object>
2367
- <object><dxn>dxn:queue:data:B6INSIBY3CBEF4M5VZRYBCMAHQMPYK5AJ:01K24XMVHSZHS97SG1VTVQDM5Z:01K24XPK46K31DDW62PBW9H2ZQ</dxn></object>
2368
- <object><dxn>dxn:queue:data:B6INSIBY3CBEF4M5VZRYBCMAHQMPYK5AJ:01K24XMVHSZHS97SG1VTVQDM5Z:01K24XPK46K31DDW62PBW92333</dxn></object>
2369
- </example>
2364
+ Structured data extraction is an experimental feature -- only enable it if the user explicitly requests it in the prompt.
2365
+ Prefer updating existing notes instead of creating new ones.
2366
+
2367
+ <strcutured_mode>
2368
+ When you are done, reply with the created objects.
2369
+ Do not print the data, instead reply with inline references to the created objects.
2370
+ Those will be later substituted with the pills representing the created objects.
2371
+ Print the rest of the created objects as block references after the main note.
2372
+
2373
+ <example>
2374
+ Based on my research, Google was founded by @dxn:queue:data:B6INSIBY3CBEF4M5VZRYBCMAHQMPYK5AJ:01K24XMVHSZHS97SG1VTVQDM5Z:01K24XPK464FSCKVQJAB2H662M and @dxn:queue:data:B6INSIBY3CBEF4M5VZRYBCMAHQMPYK5AJ:01K24XMVHSZHS97SG1VTVQDM5Z:01K24XPK46K31DDW62PBW9H2ZQ
2375
+
2376
+ <object><dxn>dxn:queue:data:B6INSIBY3CBEF4M5VZRYBCMAHQMPYK5AJ:01K24XMVHSZHS97SG1VTVQDM5Z:01K24XPK464FSCKVQJAB2H662M</dxn></object>
2377
+ <object><dxn>dxn:queue:data:B6INSIBY3CBEF4M5VZRYBCMAHQMPYK5AJ:01K24XMVHSZHS97SG1VTVQDM5Z:01K24XPK46K31DDW62PBW9H2ZQ</dxn></object>
2378
+ <object><dxn>dxn:queue:data:B6INSIBY3CBEF4M5VZRYBCMAHQMPYK5AJ:01K24XMVHSZHS97SG1VTVQDM5Z:01K24XPK46K31DDW62PBW92333</dxn></object>
2379
+ </example>
2380
+ </structured_mode>
2381
+
2382
+ <unstructured_mode>
2383
+ Reply normally with the text mode of the result of your research.
2384
+ </unstructured_mode>
2370
2385
  `;
2371
- var blueprint5 = Obj13.make(Blueprint5.Blueprint, {
2386
+ var blueprint5 = Obj14.make(Blueprint5.Blueprint, {
2372
2387
  key: "dxos.org/blueprint/research",
2373
2388
  name: "Research",
2374
2389
  description: "Researches the web and creates structured data.",
2375
2390
  instructions: {
2376
- source: Ref10.make(DataType11.makeText(instructions5))
2391
+ source: Ref10.make(Text6.make(instructions5))
2377
2392
  },
2378
2393
  tools: [
2379
2394
  Research.create,
@@ -2388,14 +2403,14 @@ var research_default2 = research_blueprint_default;
2388
2403
  // src/blueprints/websearch/websearch-blueprint.ts
2389
2404
  import { ToolId as ToolId6 } from "@dxos/ai";
2390
2405
  import { Blueprint as Blueprint6 } from "@dxos/blueprints";
2391
- import { Obj as Obj14, Ref as Ref11 } from "@dxos/echo";
2392
- import { DataType as DataType12 } from "@dxos/schema";
2393
- var blueprint6 = Obj14.make(Blueprint6.Blueprint, {
2406
+ import { Obj as Obj15, Ref as Ref11 } from "@dxos/echo";
2407
+ import { Text as Text7 } from "@dxos/schema";
2408
+ var blueprint6 = Obj15.make(Blueprint6.Blueprint, {
2394
2409
  key: "dxos.org/blueprint/web-search",
2395
2410
  name: "Web Search",
2396
2411
  description: "Search the web.",
2397
2412
  instructions: {
2398
- source: Ref11.make(DataType12.makeText(""))
2413
+ source: Ref11.make(Text7.make())
2399
2414
  },
2400
2415
  tools: [
2401
2416
  ToolId6.make("AnthropicWebSearch")
@@ -2447,8 +2462,287 @@ var capabilities = [
2447
2462
  })
2448
2463
  }))
2449
2464
  ];
2465
+
2466
+ // src/toolkits/AssistantToolkit.ts
2467
+ var AssistantToolkit_exports = {};
2468
+ __export(AssistantToolkit_exports, {
2469
+ AssistantToolkit: () => AssistantToolkit,
2470
+ layer: () => layer3,
2471
+ tools: () => tools
2472
+ });
2473
+ import * as Tool2 from "@effect/ai/Tool";
2474
+ import * as Toolkit5 from "@effect/ai/Toolkit";
2475
+ import * as Effect16 from "effect/Effect";
2476
+ import * as Record from "effect/Record";
2477
+ import * as Schema16 from "effect/Schema";
2478
+ import { AiContextService, ArtifactId as ArtifactId6 } from "@dxos/assistant";
2479
+ import { Ref as Ref12 } from "@dxos/echo";
2480
+ import { DatabaseService as DatabaseService13 } from "@dxos/functions";
2481
+ import { trim as trim10 } from "@dxos/util";
2482
+ var AssistantToolkit = Toolkit5.make(Tool2.make("add-to-context", {
2483
+ description: trim10`
2484
+ Adds the object to the chat context.
2485
+ `,
2486
+ parameters: {
2487
+ id: ArtifactId6.annotations({
2488
+ description: "The ID of the document to read."
2489
+ })
2490
+ },
2491
+ success: Schema16.Void,
2492
+ failure: Schema16.Never,
2493
+ dependencies: [
2494
+ AiContextService,
2495
+ DatabaseService13
2496
+ ]
2497
+ }));
2498
+ var tools = Record.keys(AssistantToolkit.tools);
2499
+ var layer3 = () => AssistantToolkit.toLayer({
2500
+ "add-to-context": Effect16.fnUntraced(function* ({ id }) {
2501
+ const { binder } = yield* AiContextService;
2502
+ const { db } = yield* DatabaseService13;
2503
+ const ref = Ref12.fromDXN(ArtifactId6.toDXN(id, db.spaceId));
2504
+ yield* Effect16.promise(() => binder.bind({
2505
+ blueprints: [],
2506
+ objects: [
2507
+ ref
2508
+ ]
2509
+ }));
2510
+ })
2511
+ });
2512
+
2513
+ // src/toolkits/SystemToolkit.ts
2514
+ var SystemToolkit_exports = {};
2515
+ __export(SystemToolkit_exports, {
2516
+ SystemToolkit: () => SystemToolkit,
2517
+ layer: () => layer4,
2518
+ tools: () => tools2
2519
+ });
2520
+ import * as Tool3 from "@effect/ai/Tool";
2521
+ import * as Toolkit6 from "@effect/ai/Toolkit";
2522
+ import * as Effect17 from "effect/Effect";
2523
+ import * as Record2 from "effect/Record";
2524
+ import * as Schema17 from "effect/Schema";
2525
+ import { ArtifactId as ArtifactId7 } from "@dxos/assistant";
2526
+ import { DXN as DXN2, Obj as Obj16, Relation as Relation2, Tag as Tag2, Type as Type4 } from "@dxos/echo";
2527
+ import { DatabaseService as DatabaseService14 } from "@dxos/functions";
2528
+ import { trim as trim11 } from "@dxos/util";
2529
+ var SystemToolkit = Toolkit6.make(
2530
+ //
2531
+ // Schema
2532
+ //
2533
+ Tool3.make("schema-list", {
2534
+ description: trim11`
2535
+ Lists schemas definitions.
2536
+ `,
2537
+ parameters: {
2538
+ // TODO(wittjosiah): Remove this once parameter-less tools are fixed.
2539
+ limit: Schema17.Number
2540
+ },
2541
+ // TODO(dmaretskyi): Effect returns ({ result, encodedResult })
2542
+ success: Schema17.Any,
2543
+ failure: Schema17.Never,
2544
+ dependencies: [
2545
+ DatabaseService14
2546
+ ]
2547
+ }),
2548
+ Tool3.make("schema-add", {
2549
+ description: trim11`
2550
+ Adds a schema to the space.
2551
+ The name will be used when displayed to the user.
2552
+ The typename must be in the format of "example.com/type/Type".
2553
+ `,
2554
+ parameters: {
2555
+ name: Schema17.String,
2556
+ typename: Schema17.String,
2557
+ jsonSchema: Schema17.Any
2558
+ },
2559
+ success: Schema17.Any,
2560
+ failure: Schema17.Never,
2561
+ dependencies: [
2562
+ DatabaseService14
2563
+ ]
2564
+ }),
2565
+ //
2566
+ // Objects
2567
+ //
2568
+ Tool3.make("object-create", {
2569
+ description: trim11`
2570
+ Creates a new object and adds it to the current space.
2571
+ Get the schema from the schema-list tool and ensure that the data matches the corresponding schema.
2572
+ `,
2573
+ parameters: {
2574
+ typename: Schema17.String,
2575
+ data: Schema17.Any
2576
+ },
2577
+ success: Schema17.Any,
2578
+ failure: Schema17.Never,
2579
+ dependencies: [
2580
+ DatabaseService14
2581
+ ]
2582
+ }),
2583
+ Tool3.make("object-remove", {
2584
+ description: trim11`
2585
+ Removes an object or relation from the database.
2586
+ `,
2587
+ parameters: {
2588
+ id: ArtifactId7.annotations({
2589
+ description: "The ID of the object."
2590
+ })
2591
+ },
2592
+ success: Schema17.Any,
2593
+ failure: Schema17.Never,
2594
+ dependencies: [
2595
+ DatabaseService14
2596
+ ]
2597
+ }),
2598
+ //
2599
+ // Relations
2600
+ //
2601
+ Tool3.make("relation-create", {
2602
+ description: trim11`
2603
+ Creates a new relation and adds it to the current space.
2604
+ Get the schema from the schema-list tool and ensure that the data matches the corresponding schema.
2605
+ `,
2606
+ parameters: {
2607
+ typename: Schema17.String,
2608
+ source: ArtifactId7.annotations({
2609
+ description: "The ID of the source object."
2610
+ }),
2611
+ target: ArtifactId7.annotations({
2612
+ description: "The ID of the target object."
2613
+ }),
2614
+ data: Schema17.Any.annotations({
2615
+ description: "The data to be stored in the relation."
2616
+ })
2617
+ },
2618
+ success: Schema17.Any,
2619
+ failure: Schema17.Never,
2620
+ dependencies: [
2621
+ DatabaseService14
2622
+ ]
2623
+ }),
2624
+ //
2625
+ // Tags
2626
+ //
2627
+ Tool3.make("tag-add", {
2628
+ description: trim11`
2629
+ Adds a tag to an object.
2630
+ Tags are objects of type ${Tag2.Tag.typename}.
2631
+ `,
2632
+ parameters: {
2633
+ tagId: ArtifactId7.annotations({
2634
+ description: "The ID of the tag."
2635
+ }),
2636
+ objectId: ArtifactId7.annotations({
2637
+ description: "The ID of the object."
2638
+ })
2639
+ },
2640
+ success: Schema17.Any,
2641
+ failure: Schema17.Never,
2642
+ dependencies: [
2643
+ DatabaseService14
2644
+ ]
2645
+ }),
2646
+ Tool3.make("tag-remove", {
2647
+ description: trim11`
2648
+ Removes a tag from an object.
2649
+ Tags are objects of type ${Tag2.Tag.typename}.
2650
+ `,
2651
+ parameters: {
2652
+ tagId: ArtifactId7.annotations({
2653
+ description: "The ID of the tag."
2654
+ }),
2655
+ objectId: ArtifactId7.annotations({
2656
+ description: "The ID of the object."
2657
+ })
2658
+ },
2659
+ success: Schema17.Any,
2660
+ failure: Schema17.Never,
2661
+ dependencies: [
2662
+ DatabaseService14
2663
+ ]
2664
+ })
2665
+ );
2666
+ var tools2 = Record2.keys(SystemToolkit.tools);
2667
+ var layer4 = () => SystemToolkit.toLayer({
2668
+ "schema-list": Effect17.fnUntraced(function* () {
2669
+ const { db } = yield* DatabaseService14;
2670
+ const schema = yield* Effect17.promise(() => db.schemaRegistry.query({
2671
+ location: [
2672
+ "database",
2673
+ "runtime"
2674
+ ]
2675
+ }).run());
2676
+ return schema.map((schema2) => {
2677
+ const meta = Type4.getMeta(schema2);
2678
+ return {
2679
+ typename: Type4.getTypename(schema2),
2680
+ jsonSchema: Type4.toJsonSchema(schema2),
2681
+ kind: meta?.sourceSchema ? "relation" : "record"
2682
+ };
2683
+ });
2684
+ }),
2685
+ "schema-add": Effect17.fnUntraced(function* ({ name, typename, jsonSchema }) {
2686
+ const { db } = yield* DatabaseService14;
2687
+ yield* Effect17.promise(() => db.schemaRegistry.register([
2688
+ {
2689
+ typename,
2690
+ version: "0.1.0",
2691
+ jsonSchema,
2692
+ name
2693
+ }
2694
+ ]));
2695
+ }),
2696
+ "object-create": Effect17.fnUntraced(function* ({ typename, data }) {
2697
+ const { db } = yield* DatabaseService14;
2698
+ const schema = yield* Effect17.promise(() => db.schemaRegistry.query({
2699
+ typename,
2700
+ location: [
2701
+ "database",
2702
+ "runtime"
2703
+ ]
2704
+ }).first());
2705
+ const object = db.add(Obj16.make(schema, data));
2706
+ return object;
2707
+ }),
2708
+ "object-remove": Effect17.fnUntraced(function* ({ id }) {
2709
+ const { db } = yield* DatabaseService14;
2710
+ const object = yield* DatabaseService14.resolve(DXN2.parse(id));
2711
+ db.remove(object);
2712
+ return object;
2713
+ }),
2714
+ "relation-create": Effect17.fnUntraced(function* ({ typename, source, target, data }) {
2715
+ const { db } = yield* DatabaseService14;
2716
+ const schema = yield* Effect17.promise(() => db.schemaRegistry.query({
2717
+ typename,
2718
+ location: [
2719
+ "database",
2720
+ "runtime"
2721
+ ]
2722
+ }).first());
2723
+ const sourceObj = yield* DatabaseService14.resolve(DXN2.parse(source));
2724
+ const targetObj = yield* DatabaseService14.resolve(DXN2.parse(target));
2725
+ const relation = db.add(Relation2.make(schema, {
2726
+ [Relation2.Source]: sourceObj,
2727
+ [Relation2.Target]: targetObj,
2728
+ ...data
2729
+ }));
2730
+ return relation;
2731
+ }),
2732
+ "tag-add": Effect17.fnUntraced(function* ({ tagId, objectId }) {
2733
+ const object = yield* DatabaseService14.resolve(DXN2.parse(objectId));
2734
+ Obj16.addTag(object, DXN2.parse(tagId).toString());
2735
+ return object;
2736
+ }),
2737
+ "tag-remove": Effect17.fnUntraced(function* ({ tagId, objectId }) {
2738
+ const object = yield* DatabaseService14.resolve(DXN2.parse(objectId));
2739
+ Obj16.removeTag(object, DXN2.parse(tagId).toString());
2740
+ return object;
2741
+ })
2742
+ });
2450
2743
  export {
2451
2744
  Agent,
2745
+ AssistantToolkit_exports as AssistantToolkit,
2452
2746
  design_default as DesignBlueprint,
2453
2747
  Discord,
2454
2748
  discord_default as DiscordBlueprint,
@@ -2465,6 +2759,7 @@ export {
2465
2759
  ResearchDataTypes,
2466
2760
  ResearchGraph,
2467
2761
  Subgraph,
2762
+ SystemToolkit_exports as SystemToolkit,
2468
2763
  Tasks,
2469
2764
  websearch_default as WebSearchBlueprint,
2470
2765
  WebSearchToolkit,