@agent-native/core 0.101.6 → 0.101.7

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 (101) hide show
  1. package/corpus/README.md +1 -1
  2. package/corpus/core/CHANGELOG.md +6 -0
  3. package/corpus/core/package.json +1 -1
  4. package/corpus/core/src/a2a/artifact-response.ts +255 -12
  5. package/corpus/core/src/agent/thread-data-builder.ts +84 -11
  6. package/corpus/core/src/integrations/a2a-continuation-processor.ts +99 -7
  7. package/corpus/core/src/integrations/adapters/discord.ts +3 -1
  8. package/corpus/core/src/integrations/adapters/email.ts +4 -1
  9. package/corpus/core/src/integrations/adapters/google-docs.ts +4 -1
  10. package/corpus/core/src/integrations/adapters/microsoft-teams.ts +3 -1
  11. package/corpus/core/src/integrations/adapters/slack.ts +38 -9
  12. package/corpus/core/src/integrations/adapters/telegram.ts +32 -10
  13. package/corpus/core/src/integrations/adapters/whatsapp.ts +5 -1
  14. package/corpus/core/src/integrations/index.ts +1 -0
  15. package/corpus/core/src/integrations/types.ts +9 -2
  16. package/corpus/core/src/integrations/webhook-handler.ts +69 -45
  17. package/corpus/core/src/server/agent-chat/action-filters-a2a.ts +1 -0
  18. package/corpus/templates/content/.agents/skills/content/SKILL.md +31 -0
  19. package/corpus/templates/content/.agents/skills/document-editing/SKILL.md +35 -21
  20. package/corpus/templates/content/AGENTS.md +29 -7
  21. package/corpus/templates/content/actions/_database-source-utils.ts +30 -16
  22. package/corpus/templates/content/actions/_database-utils.ts +15 -1
  23. package/corpus/templates/content/actions/_local-file-documents.ts +53 -1
  24. package/corpus/templates/content/actions/_property-utils.ts +7 -1
  25. package/corpus/templates/content/actions/configure-document-property.ts +11 -0
  26. package/corpus/templates/content/actions/create-content-database.ts +11 -0
  27. package/corpus/templates/content/actions/create-document.ts +9 -0
  28. package/corpus/templates/content/actions/create-inline-content-database.ts +3 -0
  29. package/corpus/templates/content/actions/export-content-source.ts +1 -0
  30. package/corpus/templates/content/actions/get-content-database.ts +13 -1
  31. package/corpus/templates/content/actions/get-document.ts +12 -2
  32. package/corpus/templates/content/actions/import-content-source.ts +6 -0
  33. package/corpus/templates/content/actions/list-documents.ts +3 -0
  34. package/corpus/templates/content/actions/pull-document.ts +2 -0
  35. package/corpus/templates/content/actions/search-documents.ts +5 -1
  36. package/corpus/templates/content/actions/update-document.ts +16 -1
  37. package/corpus/templates/content/actions/view-screen.ts +15 -2
  38. package/corpus/templates/content/app/components/editor/DescriptionField.tsx +121 -0
  39. package/corpus/templates/content/app/components/editor/DocumentEditor.tsx +14 -0
  40. package/corpus/templates/content/app/components/editor/DocumentProperties.tsx +223 -34
  41. package/corpus/templates/content/app/components/editor/database/DatabaseView.tsx +56 -8
  42. package/corpus/templates/content/app/i18n/zh-TW.ts +5 -0
  43. package/corpus/templates/content/app/i18n-data.ts +52 -0
  44. package/corpus/templates/content/changelog/2026-07-14-pages-and-databases-can-describe-themselves-with-guidance-fo.md +6 -0
  45. package/corpus/templates/content/changelog/2026-07-14-slack-follow-ups-now-retain-created-content-identity-and-per.md +6 -0
  46. package/corpus/templates/content/server/db/schema.ts +4 -0
  47. package/corpus/templates/content/server/lib/document-context.ts +76 -0
  48. package/corpus/templates/content/server/lib/public-documents.ts +3 -0
  49. package/corpus/templates/content/server/plugins/db.ts +6 -0
  50. package/corpus/templates/content/server/routes/api/document-agent-context.json.get.ts +5 -0
  51. package/corpus/templates/content/shared/api.ts +17 -0
  52. package/corpus/templates/content/shared/content-source.ts +7 -0
  53. package/corpus/templates/content/shared/properties.ts +2 -0
  54. package/dist/a2a/artifact-response.d.ts +15 -0
  55. package/dist/a2a/artifact-response.d.ts.map +1 -1
  56. package/dist/a2a/artifact-response.js +204 -5
  57. package/dist/a2a/artifact-response.js.map +1 -1
  58. package/dist/agent/thread-data-builder.d.ts +6 -0
  59. package/dist/agent/thread-data-builder.d.ts.map +1 -1
  60. package/dist/agent/thread-data-builder.js +71 -8
  61. package/dist/agent/thread-data-builder.js.map +1 -1
  62. package/dist/integrations/a2a-continuation-processor.d.ts.map +1 -1
  63. package/dist/integrations/a2a-continuation-processor.js +72 -6
  64. package/dist/integrations/a2a-continuation-processor.js.map +1 -1
  65. package/dist/integrations/adapters/discord.d.ts.map +1 -1
  66. package/dist/integrations/adapters/discord.js +1 -0
  67. package/dist/integrations/adapters/discord.js.map +1 -1
  68. package/dist/integrations/adapters/email.d.ts.map +1 -1
  69. package/dist/integrations/adapters/email.js +2 -0
  70. package/dist/integrations/adapters/email.js.map +1 -1
  71. package/dist/integrations/adapters/google-docs.d.ts.map +1 -1
  72. package/dist/integrations/adapters/google-docs.js +2 -0
  73. package/dist/integrations/adapters/google-docs.js.map +1 -1
  74. package/dist/integrations/adapters/microsoft-teams.d.ts.map +1 -1
  75. package/dist/integrations/adapters/microsoft-teams.js +1 -0
  76. package/dist/integrations/adapters/microsoft-teams.js.map +1 -1
  77. package/dist/integrations/adapters/slack.d.ts.map +1 -1
  78. package/dist/integrations/adapters/slack.js +21 -6
  79. package/dist/integrations/adapters/slack.js.map +1 -1
  80. package/dist/integrations/adapters/telegram.d.ts.map +1 -1
  81. package/dist/integrations/adapters/telegram.js +11 -2
  82. package/dist/integrations/adapters/telegram.js.map +1 -1
  83. package/dist/integrations/adapters/whatsapp.d.ts.map +1 -1
  84. package/dist/integrations/adapters/whatsapp.js +3 -0
  85. package/dist/integrations/adapters/whatsapp.js.map +1 -1
  86. package/dist/integrations/index.d.ts +1 -1
  87. package/dist/integrations/index.d.ts.map +1 -1
  88. package/dist/integrations/index.js.map +1 -1
  89. package/dist/integrations/types.d.ts +8 -2
  90. package/dist/integrations/types.d.ts.map +1 -1
  91. package/dist/integrations/types.js.map +1 -1
  92. package/dist/integrations/webhook-handler.d.ts.map +1 -1
  93. package/dist/integrations/webhook-handler.js +40 -43
  94. package/dist/integrations/webhook-handler.js.map +1 -1
  95. package/dist/observability/routes.d.ts +1 -1
  96. package/dist/provider-api/corpus-jobs.d.ts +2 -2
  97. package/dist/resources/handlers.d.ts +1 -1
  98. package/dist/server/agent-chat/action-filters-a2a.d.ts.map +1 -1
  99. package/dist/server/agent-chat/action-filters-a2a.js +1 -0
  100. package/dist/server/agent-chat/action-filters-a2a.js.map +1 -1
  101. package/package.json +1 -1
@@ -59,6 +59,7 @@ export default defineAction({
59
59
  (doc) =>
60
60
  !normalizedQuery ||
61
61
  doc.title.toLowerCase().includes(normalizedQuery) ||
62
+ (doc.description ?? "").toLowerCase().includes(normalizedQuery) ||
62
63
  doc.content.toLowerCase().includes(normalizedQuery),
63
64
  )
64
65
  .sort((a, b) => b.updatedAt.localeCompare(a.updatedAt))
@@ -69,6 +70,7 @@ export default defineAction({
69
70
  id: doc.id,
70
71
  parentId: doc.parentId,
71
72
  title: doc.title,
73
+ description: doc.description,
72
74
  icon: doc.icon,
73
75
  snippet: makeSnippet(doc.content, query),
74
76
  contentLength: doc.content.length,
@@ -95,6 +97,7 @@ export default defineAction({
95
97
  id: schema.documents.id,
96
98
  parentId: schema.documents.parentId,
97
99
  title: schema.documents.title,
100
+ description: schema.documents.description,
98
101
  icon: schema.documents.icon,
99
102
  contentPreview: sql<string>`substr(${schema.documents.content}, 1, 5000)`,
100
103
  contentLength: sql<number>`length(${schema.documents.content})`,
@@ -106,7 +109,7 @@ export default defineAction({
106
109
  and(
107
110
  accessFilter(schema.documents, schema.documentShares),
108
111
  documentDiscoveryFilter(),
109
- sql`(${schema.documents.title} LIKE ${pattern} ESCAPE '\\' OR ${schema.documents.content} LIKE ${pattern} ESCAPE '\\')`,
112
+ sql`(${schema.documents.title} LIKE ${pattern} ESCAPE '\\' OR ${schema.documents.description} LIKE ${pattern} ESCAPE '\\' OR ${schema.documents.content} LIKE ${pattern} ESCAPE '\\')`,
110
113
  ),
111
114
  )
112
115
  .orderBy(sql`${schema.documents.updatedAt} DESC`)
@@ -117,6 +120,7 @@ export default defineAction({
117
120
  id: doc.id,
118
121
  parentId: doc.parentId,
119
122
  title: doc.title,
123
+ description: doc.description,
120
124
  icon: doc.icon,
121
125
  snippet: makeSnippet(doc.contentPreview, query),
122
126
  contentLength: Number(doc.contentLength) || 0,
@@ -152,6 +152,10 @@ export default defineAction({
152
152
  id: z.string().optional().describe("Document ID (required)"),
153
153
  title: z.string().optional().describe("New title"),
154
154
  content: z.string().optional().describe("New markdown content"),
155
+ description: z
156
+ .string()
157
+ .optional()
158
+ .describe("Stable page guidance; this does not alter page content"),
155
159
  icon: z.string().nullable().optional().describe("New emoji icon"),
156
160
  isFavorite: z.coerce
157
161
  .boolean()
@@ -285,8 +289,15 @@ export default defineAction({
285
289
  const favoriteChanged =
286
290
  args.isFavorite !== undefined &&
287
291
  (args.isFavorite ? 1 : 0) !== (existing.isFavorite ?? 0);
292
+ const descriptionChanged =
293
+ args.description !== undefined &&
294
+ args.description.trim() !== existing.description;
288
295
  const anyChange =
289
- titleChanged || contentChanged || iconChanged || favoriteChanged;
296
+ titleChanged ||
297
+ contentChanged ||
298
+ iconChanged ||
299
+ favoriteChanged ||
300
+ descriptionChanged;
290
301
 
291
302
  // Snapshot the current state before applying content/title changes.
292
303
  // Versions are scoped to the document owner, not the caller — an editor
@@ -338,6 +349,8 @@ export default defineAction({
338
349
  };
339
350
 
340
351
  if (titleChanged) updates.title = args.title;
352
+ if (args.description !== undefined)
353
+ updates.description = args.description.trim();
341
354
  if (contentChanged) updates.content = content;
342
355
  if (iconChanged) updates.icon = args.icon;
343
356
  if (favoriteChanged) updates.isFavorite = args.isFavorite ? 1 : 0;
@@ -373,6 +386,7 @@ export default defineAction({
373
386
  parentId: current.parentId,
374
387
  title: current.title,
375
388
  content: current.content,
389
+ description: current.description,
376
390
  icon: current.icon,
377
391
  position: current.position,
378
392
  isFavorite: parseDocumentFavorite(current.isFavorite),
@@ -449,6 +463,7 @@ export default defineAction({
449
463
  parentId: doc.parentId,
450
464
  title: doc.title,
451
465
  content: doc.content,
466
+ description: doc.description,
452
467
  icon: doc.icon,
453
468
  position: doc.position,
454
469
  isFavorite: parseDocumentFavorite(doc.isFavorite),
@@ -34,11 +34,13 @@ import {
34
34
  getContentDatabaseResponse,
35
35
  getDatabaseByDocumentId,
36
36
  getDatabaseItemByDocumentId,
37
+ getDocumentContextPath,
37
38
  serializeDatabaseMembership,
38
39
  } from "./_database-utils.js";
39
40
  import { serializeDocumentSource } from "./_document-source.js";
40
41
  import {
41
42
  getLocalFileDocument,
43
+ getLocalDocumentContextPath,
42
44
  isContentLocalFileMode,
43
45
  isLocalDocumentId,
44
46
  localContentViewScreenSummary,
@@ -675,7 +677,10 @@ export default defineAction({
675
677
  ],
676
678
  };
677
679
  if (nav?.documentId && isLocalDocumentId(nav.documentId)) {
678
- screen.document = await getLocalFileDocument(nav.documentId);
680
+ screen.document = {
681
+ ...(await getLocalFileDocument(nav.documentId)),
682
+ contextPath: await getLocalDocumentContextPath(nav.documentId),
683
+ };
679
684
  } else if (nav?.documentId) {
680
685
  const access = await resolveAccess("document", nav.documentId);
681
686
  if (access) {
@@ -685,6 +690,7 @@ export default defineAction({
685
690
  parentId: doc.parentId,
686
691
  title: doc.title,
687
692
  content: doc.content,
693
+ description: doc.description,
688
694
  icon: doc.icon,
689
695
  position: doc.position,
690
696
  isFavorite: parseDocumentFavorite(doc.isFavorite),
@@ -693,6 +699,7 @@ export default defineAction({
693
699
  source: serializeDocumentSource(doc),
694
700
  createdAt: doc.createdAt,
695
701
  updatedAt: doc.updatedAt,
702
+ contextPath: await getDocumentContextPath(doc),
696
703
  };
697
704
  }
698
705
  }
@@ -725,18 +732,22 @@ export default defineAction({
725
732
  parentId: doc.parentId,
726
733
  title: doc.title,
727
734
  content: doc.content,
735
+ description: doc.description,
728
736
  icon: doc.icon,
729
737
  position: doc.position,
730
738
  isFavorite: parseDocumentFavorite(doc.isFavorite),
731
739
  hideFromSearch: parseDocumentHideFromSearch(doc.hideFromSearch),
732
740
  visibility: doc.visibility,
733
- database: database ? serializeDatabase(database) : undefined,
741
+ database: database
742
+ ? serializeDatabase(database, doc.description)
743
+ : undefined,
734
744
  databaseMembership: databaseMembership
735
745
  ? serializeDatabaseMembership(databaseMembership)
736
746
  : undefined,
737
747
  properties: await listPropertiesForDocument(doc),
738
748
  createdAt: doc.createdAt,
739
749
  updatedAt: doc.updatedAt,
750
+ contextPath: await getDocumentContextPath(doc),
740
751
  };
741
752
  if (database) {
742
753
  const databaseResponse = await getContentDatabaseResponse(
@@ -774,6 +785,7 @@ export default defineAction({
774
785
  parentId: previewDoc.parentId,
775
786
  title: previewDoc.title,
776
787
  content: previewDoc.content,
788
+ description: previewDoc.description,
777
789
  icon: previewDoc.icon,
778
790
  position: previewDoc.position,
779
791
  isFavorite: parseDocumentFavorite(previewDoc.isFavorite),
@@ -786,6 +798,7 @@ export default defineAction({
786
798
  properties: await listPropertiesForDocument(previewDoc),
787
799
  createdAt: previewDoc.createdAt,
788
800
  updatedAt: previewDoc.updatedAt,
801
+ contextPath: await getDocumentContextPath(previewDoc),
789
802
  },
790
803
  };
791
804
  }
@@ -0,0 +1,121 @@
1
+ import { useEffect, useRef, useState } from "react";
2
+
3
+ import { Textarea } from "@/components/ui/textarea";
4
+ import { cn } from "@/lib/utils";
5
+
6
+ export function descriptionFieldSavedValue(
7
+ draft: string,
8
+ savedDescription: string | null | undefined,
9
+ ) {
10
+ const next = draft.trim();
11
+ return next === (savedDescription ?? "") ? null : next;
12
+ }
13
+
14
+ export function descriptionFieldEscapeDraft(
15
+ savedDescription: string | null | undefined,
16
+ ) {
17
+ return savedDescription ?? "";
18
+ }
19
+
20
+ /**
21
+ * Quiet, stable guidance attached to a page or database. This intentionally
22
+ * renders the owned description only; ancestor context is assembled for agent
23
+ * reads rather than copied into the surface.
24
+ */
25
+ export function DescriptionField({
26
+ description,
27
+ canEdit,
28
+ label = "Description",
29
+ placeholder = "Add a description…",
30
+ className,
31
+ onSave,
32
+ }: {
33
+ description: string | null | undefined;
34
+ canEdit: boolean;
35
+ label?: string;
36
+ placeholder?: string;
37
+ className?: string;
38
+ onSave: (description: string) => Promise<unknown> | unknown;
39
+ }) {
40
+ const [draft, setDraft] = useState(description ?? "");
41
+ const [editing, setEditing] = useState(false);
42
+ const skipNextBlurSaveRef = useRef(false);
43
+ const saveQueueRef = useRef<Promise<void>>(Promise.resolve());
44
+ const saveRevisionRef = useRef(0);
45
+ const confirmedDescriptionRef = useRef(description ?? "");
46
+
47
+ useEffect(() => {
48
+ confirmedDescriptionRef.current = description ?? "";
49
+ }, [description]);
50
+
51
+ useEffect(() => {
52
+ if (!editing) setDraft(description ?? "");
53
+ }, [description, editing]);
54
+
55
+ const save = async () => {
56
+ const next = descriptionFieldSavedValue(draft, description);
57
+ if (next === null) return;
58
+
59
+ const revision = ++saveRevisionRef.current;
60
+ const request = saveQueueRef.current.then(() => onSave(next));
61
+ saveQueueRef.current = request.then(
62
+ () => undefined,
63
+ () => undefined,
64
+ );
65
+
66
+ try {
67
+ await request;
68
+ confirmedDescriptionRef.current = next;
69
+ } catch {
70
+ if (saveRevisionRef.current === revision) {
71
+ setDraft(confirmedDescriptionRef.current);
72
+ }
73
+ }
74
+ };
75
+
76
+ if (!canEdit && !description) return null;
77
+
78
+ if (!canEdit) {
79
+ return (
80
+ <p
81
+ className={cn(
82
+ "mt-2 text-sm leading-6 text-muted-foreground",
83
+ className,
84
+ )}
85
+ >
86
+ {description}
87
+ </p>
88
+ );
89
+ }
90
+
91
+ return (
92
+ <Textarea
93
+ aria-label={label}
94
+ rows={editing || draft ? 2 : 1}
95
+ value={draft}
96
+ placeholder={placeholder}
97
+ onFocus={() => setEditing(true)}
98
+ onChange={(event) => setDraft(event.target.value)}
99
+ onBlur={() => {
100
+ setEditing(false);
101
+ if (skipNextBlurSaveRef.current) {
102
+ skipNextBlurSaveRef.current = false;
103
+ return;
104
+ }
105
+ void save();
106
+ }}
107
+ onKeyDown={(event) => {
108
+ if (event.key === "Escape") {
109
+ event.preventDefault();
110
+ skipNextBlurSaveRef.current = true;
111
+ setDraft(descriptionFieldEscapeDraft(description));
112
+ event.currentTarget.blur();
113
+ }
114
+ }}
115
+ className={cn(
116
+ "mt-2 block w-full resize-none overflow-hidden rounded border-0 bg-transparent px-0 py-0 text-sm leading-6 text-muted-foreground outline-none placeholder:text-muted-foreground/45 hover:bg-muted/30 focus:bg-muted/30 focus:px-1 focus:outline-none focus:ring-1 focus:ring-ring",
117
+ className,
118
+ )}
119
+ />
120
+ );
121
+ }
@@ -61,6 +61,7 @@ import {
61
61
  import { BuilderBodySyncingNotice } from "./BuilderBodySyncingNotice";
62
62
  import type { CommentTextAnchor } from "./comment-anchors";
63
63
  import { CommentsSidebar } from "./CommentsSidebar";
64
+ import { DescriptionField } from "./DescriptionField";
64
65
  import { DocumentBlockFields } from "./DocumentBlockFields";
65
66
  import { DocumentDatabase } from "./DocumentDatabase";
66
67
  import { DocumentEditorSkeleton } from "./DocumentEditorSkeleton";
@@ -629,6 +630,7 @@ function DocumentEditorBody({ documentId, document }: DocumentEditorBodyProps) {
629
630
  updates: {
630
631
  title?: string;
631
632
  content?: string;
633
+ description?: string;
632
634
  icon?: string | null;
633
635
  },
634
636
  options: DocumentSaveOptions = {},
@@ -645,6 +647,7 @@ function DocumentEditorBody({ documentId, document }: DocumentEditorBodyProps) {
645
647
  ...document,
646
648
  title: updates.title ?? localTitleRef.current,
647
649
  content: updates.content ?? localContentRef.current,
650
+ description: updates.description ?? document.description,
648
651
  icon: updates.icon !== undefined ? updates.icon : document.icon,
649
652
  updatedAt: nextSavedAt,
650
653
  source: localSource,
@@ -1431,6 +1434,17 @@ function DocumentEditorBody({ documentId, document }: DocumentEditorBodyProps) {
1431
1434
  isDatabasePage ? "text-3xl" : "text-3xl md:text-4xl",
1432
1435
  )}
1433
1436
  />
1437
+ {!document.database ? (
1438
+ <DescriptionField
1439
+ description={document.description}
1440
+ canEdit={editorCanEdit}
1441
+ label={t("editor.properties.description")}
1442
+ placeholder={t("editor.properties.addPageDescription")}
1443
+ onSave={(description) =>
1444
+ persistDocumentUpdates({ description })
1445
+ }
1446
+ />
1447
+ ) : null}
1434
1448
  {document.databaseMembership && !isLocalFileDocument ? (
1435
1449
  <DocumentProperties
1436
1450
  documentId={documentId}