@agent-native/core 0.101.5 → 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.
- package/README.md +1 -1
- package/corpus/README.md +1 -1
- package/corpus/core/CHANGELOG.md +12 -0
- package/corpus/core/docs/content/locales/ar-SA/pure-agent-apps.mdx +2 -2
- package/corpus/core/docs/content/locales/de-DE/pure-agent-apps.mdx +2 -2
- package/corpus/core/docs/content/locales/es-ES/pure-agent-apps.mdx +2 -2
- package/corpus/core/docs/content/locales/fr-FR/pure-agent-apps.mdx +2 -2
- package/corpus/core/docs/content/locales/hi-IN/pure-agent-apps.mdx +2 -2
- package/corpus/core/docs/content/locales/ja-JP/pure-agent-apps.mdx +2 -2
- package/corpus/core/docs/content/locales/ko-KR/pure-agent-apps.mdx +2 -2
- package/corpus/core/docs/content/locales/pt-BR/pure-agent-apps.mdx +2 -2
- package/corpus/core/docs/content/locales/zh-CN/pure-agent-apps.mdx +2 -2
- package/corpus/core/docs/content/locales/zh-TW/pure-agent-apps.mdx +2 -2
- package/corpus/core/docs/content/pure-agent-apps.mdx +58 -14
- package/corpus/core/package.json +1 -1
- package/corpus/core/src/a2a/artifact-response.ts +255 -12
- package/corpus/core/src/agent/thread-data-builder.ts +84 -11
- package/corpus/core/src/integrations/a2a-continuation-processor.ts +99 -7
- package/corpus/core/src/integrations/adapters/discord.ts +3 -1
- package/corpus/core/src/integrations/adapters/email.ts +4 -1
- package/corpus/core/src/integrations/adapters/google-docs.ts +4 -1
- package/corpus/core/src/integrations/adapters/microsoft-teams.ts +3 -1
- package/corpus/core/src/integrations/adapters/slack.ts +38 -9
- package/corpus/core/src/integrations/adapters/telegram.ts +32 -10
- package/corpus/core/src/integrations/adapters/whatsapp.ts +5 -1
- package/corpus/core/src/integrations/index.ts +1 -0
- package/corpus/core/src/integrations/types.ts +9 -2
- package/corpus/core/src/integrations/webhook-handler.ts +69 -45
- package/corpus/core/src/server/agent-chat/action-filters-a2a.ts +1 -0
- package/corpus/templates/analytics/AGENTS.md +6 -0
- package/corpus/templates/analytics/README.md +1 -1
- package/corpus/templates/analytics/actions/data-source-status.ts +19 -1
- package/corpus/templates/analytics/app/pages/adhoc/sql-dashboard/index.tsx +5 -1
- package/corpus/templates/analytics/app/routes/_index.tsx +2 -2
- package/corpus/templates/analytics/changelog/2026-07-14-analytics-chat-guides-you-to-connect-a-data-source-with-a-di.md +6 -0
- package/corpus/templates/analytics/changelog/2026-07-14-analytics-landing-pages-now-clearly-position-the-app-as-an-o.md +6 -0
- package/corpus/templates/analytics/changelog/2026-07-15-daily-dashboard-emails-now-include-the-complete-dashboard-sc.md +6 -0
- package/corpus/templates/analytics/server/jobs/dashboard-report.ts +8 -1
- package/corpus/templates/analytics/server/lib/dashboard-report.ts +64 -12
- package/corpus/templates/analytics/server/lib/real-data-actions.ts +15 -3
- package/corpus/templates/analytics/server/plugins/agent-chat.ts +364 -4
- package/corpus/templates/clips/app/components/dictate/vocabulary-section.tsx +1 -0
- package/corpus/templates/clips/app/components/library/folder-tree.tsx +12 -9
- package/corpus/templates/clips/app/components/library/library-layout.tsx +19 -16
- package/corpus/templates/clips/app/routes/_app.spaces._index.tsx +13 -9
- package/corpus/templates/clips/changelog/2026-07-15-folders-and-sidebar-links-are-clickable-again-immediately-af.md +6 -0
- package/corpus/templates/clips/changelog/2026-07-15-hovering-a-truncated-folder-name-now-shows-the-full-name.md +6 -0
- package/corpus/templates/clips/changelog/2026-07-15-space-creation-controls-are-now-shown-only-to-organization-a.md +6 -0
- package/corpus/templates/clips/changelog/2026-07-15-vocabulary-terms-can-now-be-deleted-from-the-dictation-dicti.md +6 -0
- package/corpus/templates/clips/desktop/src/styles.css +23 -1
- package/corpus/templates/clips/desktop/src-tauri/src/whisper_speech.rs +49 -7
- package/corpus/templates/clips/server/lib/recordings.ts +5 -2
- package/corpus/templates/content/.agents/skills/content/SKILL.md +31 -0
- package/corpus/templates/content/.agents/skills/document-editing/SKILL.md +35 -21
- package/corpus/templates/content/AGENTS.md +29 -7
- package/corpus/templates/content/actions/_database-source-utils.ts +30 -16
- package/corpus/templates/content/actions/_database-utils.ts +15 -1
- package/corpus/templates/content/actions/_local-file-documents.ts +53 -1
- package/corpus/templates/content/actions/_property-utils.ts +7 -1
- package/corpus/templates/content/actions/configure-document-property.ts +11 -0
- package/corpus/templates/content/actions/create-content-database.ts +11 -0
- package/corpus/templates/content/actions/create-document.ts +9 -0
- package/corpus/templates/content/actions/create-inline-content-database.ts +3 -0
- package/corpus/templates/content/actions/export-content-source.ts +1 -0
- package/corpus/templates/content/actions/get-content-database.ts +13 -1
- package/corpus/templates/content/actions/get-document.ts +12 -2
- package/corpus/templates/content/actions/import-content-source.ts +6 -0
- package/corpus/templates/content/actions/list-documents.ts +3 -0
- package/corpus/templates/content/actions/pull-document.ts +2 -0
- package/corpus/templates/content/actions/search-documents.ts +5 -1
- package/corpus/templates/content/actions/update-document.ts +16 -1
- package/corpus/templates/content/actions/view-screen.ts +15 -2
- package/corpus/templates/content/app/components/editor/DescriptionField.tsx +121 -0
- package/corpus/templates/content/app/components/editor/DocumentEditor.tsx +14 -0
- package/corpus/templates/content/app/components/editor/DocumentProperties.tsx +223 -34
- package/corpus/templates/content/app/components/editor/database/DatabaseView.tsx +56 -8
- package/corpus/templates/content/app/i18n/zh-TW.ts +5 -0
- package/corpus/templates/content/app/i18n-data.ts +52 -0
- package/corpus/templates/content/changelog/2026-07-14-pages-and-databases-can-describe-themselves-with-guidance-fo.md +6 -0
- package/corpus/templates/content/changelog/2026-07-14-slack-follow-ups-now-retain-created-content-identity-and-per.md +6 -0
- package/corpus/templates/content/server/db/schema.ts +4 -0
- package/corpus/templates/content/server/lib/document-context.ts +76 -0
- package/corpus/templates/content/server/lib/public-documents.ts +3 -0
- package/corpus/templates/content/server/plugins/db.ts +6 -0
- package/corpus/templates/content/server/routes/api/document-agent-context.json.get.ts +5 -0
- package/corpus/templates/content/shared/api.ts +17 -0
- package/corpus/templates/content/shared/content-source.ts +7 -0
- package/corpus/templates/content/shared/properties.ts +2 -0
- package/dist/a2a/artifact-response.d.ts +15 -0
- package/dist/a2a/artifact-response.d.ts.map +1 -1
- package/dist/a2a/artifact-response.js +204 -5
- package/dist/a2a/artifact-response.js.map +1 -1
- package/dist/agent/thread-data-builder.d.ts +6 -0
- package/dist/agent/thread-data-builder.d.ts.map +1 -1
- package/dist/agent/thread-data-builder.js +71 -8
- package/dist/agent/thread-data-builder.js.map +1 -1
- package/dist/collab/struct-routes.d.ts +1 -1
- package/dist/integrations/a2a-continuation-processor.d.ts.map +1 -1
- package/dist/integrations/a2a-continuation-processor.js +72 -6
- package/dist/integrations/a2a-continuation-processor.js.map +1 -1
- package/dist/integrations/adapters/discord.d.ts.map +1 -1
- package/dist/integrations/adapters/discord.js +1 -0
- package/dist/integrations/adapters/discord.js.map +1 -1
- package/dist/integrations/adapters/email.d.ts.map +1 -1
- package/dist/integrations/adapters/email.js +2 -0
- package/dist/integrations/adapters/email.js.map +1 -1
- package/dist/integrations/adapters/google-docs.d.ts.map +1 -1
- package/dist/integrations/adapters/google-docs.js +2 -0
- package/dist/integrations/adapters/google-docs.js.map +1 -1
- package/dist/integrations/adapters/microsoft-teams.d.ts.map +1 -1
- package/dist/integrations/adapters/microsoft-teams.js +1 -0
- package/dist/integrations/adapters/microsoft-teams.js.map +1 -1
- package/dist/integrations/adapters/slack.d.ts.map +1 -1
- package/dist/integrations/adapters/slack.js +21 -6
- package/dist/integrations/adapters/slack.js.map +1 -1
- package/dist/integrations/adapters/telegram.d.ts.map +1 -1
- package/dist/integrations/adapters/telegram.js +11 -2
- package/dist/integrations/adapters/telegram.js.map +1 -1
- package/dist/integrations/adapters/whatsapp.d.ts.map +1 -1
- package/dist/integrations/adapters/whatsapp.js +3 -0
- package/dist/integrations/adapters/whatsapp.js.map +1 -1
- package/dist/integrations/index.d.ts +1 -1
- package/dist/integrations/index.d.ts.map +1 -1
- package/dist/integrations/index.js.map +1 -1
- package/dist/integrations/types.d.ts +8 -2
- package/dist/integrations/types.d.ts.map +1 -1
- package/dist/integrations/types.js.map +1 -1
- package/dist/integrations/webhook-handler.d.ts.map +1 -1
- package/dist/integrations/webhook-handler.js +40 -43
- package/dist/integrations/webhook-handler.js.map +1 -1
- package/dist/progress/routes.d.ts +1 -1
- package/dist/provider-api/corpus-jobs.d.ts +2 -2
- package/dist/resources/handlers.d.ts +2 -2
- package/dist/server/agent-chat/action-filters-a2a.d.ts.map +1 -1
- package/dist/server/agent-chat/action-filters-a2a.js +1 -0
- package/dist/server/agent-chat/action-filters-a2a.js.map +1 -1
- package/dist/server/agent-engine-api-key-route.d.ts +1 -1
- package/docs/content/locales/ar-SA/pure-agent-apps.mdx +2 -2
- package/docs/content/locales/de-DE/pure-agent-apps.mdx +2 -2
- package/docs/content/locales/es-ES/pure-agent-apps.mdx +2 -2
- package/docs/content/locales/fr-FR/pure-agent-apps.mdx +2 -2
- package/docs/content/locales/hi-IN/pure-agent-apps.mdx +2 -2
- package/docs/content/locales/ja-JP/pure-agent-apps.mdx +2 -2
- package/docs/content/locales/ko-KR/pure-agent-apps.mdx +2 -2
- package/docs/content/locales/pt-BR/pure-agent-apps.mdx +2 -2
- package/docs/content/locales/zh-CN/pure-agent-apps.mdx +2 -2
- package/docs/content/locales/zh-TW/pure-agent-apps.mdx +2 -2
- package/docs/content/pure-agent-apps.mdx +58 -14
- package/package.json +3 -3
|
@@ -28,6 +28,10 @@ const createContentDatabaseSchema = z.object({
|
|
|
28
28
|
.nullish()
|
|
29
29
|
.describe("Parent document for a new database page"),
|
|
30
30
|
title: z.string().optional().describe("Database title"),
|
|
31
|
+
description: z
|
|
32
|
+
.string()
|
|
33
|
+
.optional()
|
|
34
|
+
.describe("Stable guidance describing what belongs in this database"),
|
|
31
35
|
});
|
|
32
36
|
|
|
33
37
|
export default defineAction({
|
|
@@ -110,6 +114,12 @@ export async function createContentDatabaseRecord(
|
|
|
110
114
|
.set({ title, updatedAt: now })
|
|
111
115
|
.where(eq(schema.documents.id, documentId));
|
|
112
116
|
}
|
|
117
|
+
if (args.description !== undefined) {
|
|
118
|
+
await db
|
|
119
|
+
.update(schema.documents)
|
|
120
|
+
.set({ description: args.description.trim(), updatedAt: now })
|
|
121
|
+
.where(eq(schema.documents.id, documentId));
|
|
122
|
+
}
|
|
113
123
|
} else {
|
|
114
124
|
title = databaseTitleForPage(title);
|
|
115
125
|
const parentId = args.parentId || null;
|
|
@@ -163,6 +173,7 @@ export async function createContentDatabaseRecord(
|
|
|
163
173
|
parentId,
|
|
164
174
|
title,
|
|
165
175
|
content: "",
|
|
176
|
+
description: args.description?.trim() ?? "",
|
|
166
177
|
icon: null,
|
|
167
178
|
position: (maxPos?.max ?? -1) + 1,
|
|
168
179
|
isFavorite: 0,
|
|
@@ -45,6 +45,12 @@ export default defineAction({
|
|
|
45
45
|
.describe("Pre-generated document ID (for optimistic UI)"),
|
|
46
46
|
title: z.string().describe("Document title"),
|
|
47
47
|
content: z.string().optional().describe("Markdown content"),
|
|
48
|
+
description: z
|
|
49
|
+
.string()
|
|
50
|
+
.optional()
|
|
51
|
+
.describe(
|
|
52
|
+
"Stable guidance describing why this page exists and what belongs in it",
|
|
53
|
+
),
|
|
48
54
|
parentId: z.string().nullish().describe("Parent document ID for nesting"),
|
|
49
55
|
icon: z.string().optional().describe("Emoji icon"),
|
|
50
56
|
}),
|
|
@@ -78,6 +84,7 @@ export default defineAction({
|
|
|
78
84
|
const title = args.title;
|
|
79
85
|
|
|
80
86
|
let content = args.content || "";
|
|
87
|
+
const description = args.description?.trim() ?? "";
|
|
81
88
|
// Strip leading H1 that duplicates the title
|
|
82
89
|
if (title && content) {
|
|
83
90
|
const h1Match = content.match(/^#\s+(.+?)(\r?\n|$)/);
|
|
@@ -154,6 +161,7 @@ export default defineAction({
|
|
|
154
161
|
parentId,
|
|
155
162
|
title,
|
|
156
163
|
content,
|
|
164
|
+
description,
|
|
157
165
|
icon,
|
|
158
166
|
position,
|
|
159
167
|
isFavorite: 0,
|
|
@@ -202,6 +210,7 @@ export default defineAction({
|
|
|
202
210
|
parentId: doc.parentId,
|
|
203
211
|
title: doc.title,
|
|
204
212
|
content: doc.content,
|
|
213
|
+
description: doc.description,
|
|
205
214
|
icon: doc.icon,
|
|
206
215
|
position: doc.position,
|
|
207
216
|
isFavorite: parseDocumentFavorite(doc.isFavorite),
|
|
@@ -22,10 +22,12 @@ export default defineAction({
|
|
|
22
22
|
schema: z.object({
|
|
23
23
|
hostDocumentId: z.string().describe("Host page document ID"),
|
|
24
24
|
title: z.string().optional().describe("Database title"),
|
|
25
|
+
description: z.string().optional().describe("Stable database guidance"),
|
|
25
26
|
}),
|
|
26
27
|
run: async ({
|
|
27
28
|
hostDocumentId,
|
|
28
29
|
title,
|
|
30
|
+
description,
|
|
29
31
|
}): Promise<CreateInlineDatabaseResponse> => {
|
|
30
32
|
const db = getDb();
|
|
31
33
|
const ownerBlockId = createInlineDatabaseBlockId();
|
|
@@ -37,6 +39,7 @@ export default defineAction({
|
|
|
37
39
|
{
|
|
38
40
|
parentId: hostDocumentId,
|
|
39
41
|
title: databaseTitleForPage(title),
|
|
42
|
+
description,
|
|
40
43
|
},
|
|
41
44
|
{ db: tx },
|
|
42
45
|
);
|
|
@@ -11,6 +11,7 @@ import type {
|
|
|
11
11
|
import {
|
|
12
12
|
CONTENT_DATABASE_MAX_READ_LIMIT,
|
|
13
13
|
getContentDatabaseResponse,
|
|
14
|
+
getDocumentContextPath,
|
|
14
15
|
} from "./_database-utils.js";
|
|
15
16
|
|
|
16
17
|
export default defineAction({
|
|
@@ -78,6 +79,17 @@ export default defineAction({
|
|
|
78
79
|
};
|
|
79
80
|
}
|
|
80
81
|
|
|
81
|
-
|
|
82
|
+
const response = await getContentDatabaseResponse(resolvedDatabaseId, {
|
|
83
|
+
limit,
|
|
84
|
+
offset,
|
|
85
|
+
});
|
|
86
|
+
const [document] = await db
|
|
87
|
+
.select()
|
|
88
|
+
.from(schema.documents)
|
|
89
|
+
.where(eq(schema.documents.id, database.documentId));
|
|
90
|
+
return {
|
|
91
|
+
...response,
|
|
92
|
+
contextPath: document ? await getDocumentContextPath(document) : [],
|
|
93
|
+
};
|
|
82
94
|
},
|
|
83
95
|
});
|
|
@@ -9,6 +9,7 @@ import {
|
|
|
9
9
|
} from "../server/lib/documents.js";
|
|
10
10
|
import {
|
|
11
11
|
getDatabaseByDocumentId,
|
|
12
|
+
getDocumentContextPath,
|
|
12
13
|
getDatabaseItemByDocumentId,
|
|
13
14
|
isSoftDeletedDatabaseDocument,
|
|
14
15
|
serializeDatabaseMembership,
|
|
@@ -16,6 +17,7 @@ import {
|
|
|
16
17
|
import { serializeDocumentSource } from "./_document-source.js";
|
|
17
18
|
import {
|
|
18
19
|
getLocalFileDocument,
|
|
20
|
+
getLocalDocumentContextPath,
|
|
19
21
|
isLocalDocumentId,
|
|
20
22
|
isContentLocalFileMode,
|
|
21
23
|
} from "./_local-file-documents.js";
|
|
@@ -45,7 +47,11 @@ export default defineAction({
|
|
|
45
47
|
if (!args.id) throw new Error("--id is required");
|
|
46
48
|
|
|
47
49
|
if ((await isContentLocalFileMode()) && isLocalDocumentId(args.id)) {
|
|
48
|
-
|
|
50
|
+
const document = await getLocalFileDocument(args.id);
|
|
51
|
+
return {
|
|
52
|
+
...document,
|
|
53
|
+
contextPath: await getLocalDocumentContextPath(args.id),
|
|
54
|
+
};
|
|
49
55
|
}
|
|
50
56
|
|
|
51
57
|
const access = await resolveAccess("document", args.id);
|
|
@@ -76,6 +82,7 @@ export default defineAction({
|
|
|
76
82
|
parentId: doc.parentId,
|
|
77
83
|
title: doc.title,
|
|
78
84
|
content: doc.content,
|
|
85
|
+
description: doc.description,
|
|
79
86
|
icon: doc.icon,
|
|
80
87
|
position: doc.position,
|
|
81
88
|
isFavorite: parseDocumentFavorite(doc.isFavorite),
|
|
@@ -85,13 +92,16 @@ export default defineAction({
|
|
|
85
92
|
accessRole: access.role,
|
|
86
93
|
canEdit: canEditRole(access.role),
|
|
87
94
|
canManage: canManageRole(access.role),
|
|
88
|
-
database: database
|
|
95
|
+
database: database
|
|
96
|
+
? serializeDatabase(database, doc.description)
|
|
97
|
+
: undefined,
|
|
89
98
|
databaseMembership: databaseMembership
|
|
90
99
|
? serializeDatabaseMembership(databaseMembership)
|
|
91
100
|
: undefined,
|
|
92
101
|
createdAt: doc.createdAt,
|
|
93
102
|
updatedAt: doc.updatedAt,
|
|
94
103
|
properties: await listPropertiesForDocument(doc),
|
|
104
|
+
contextPath: await getDocumentContextPath(doc),
|
|
95
105
|
};
|
|
96
106
|
},
|
|
97
107
|
link: ({ result }) => {
|
|
@@ -282,6 +282,9 @@ export default defineAction({
|
|
|
282
282
|
}
|
|
283
283
|
const titleChanged = file.title !== existing.title;
|
|
284
284
|
const contentChanged = file.content !== existing.content;
|
|
285
|
+
const descriptionChanged =
|
|
286
|
+
file.description !== undefined &&
|
|
287
|
+
file.description !== existing.description;
|
|
285
288
|
const iconChanged =
|
|
286
289
|
file.icon !== undefined && file.icon !== existing.icon;
|
|
287
290
|
const favoriteChanged =
|
|
@@ -299,6 +302,7 @@ export default defineAction({
|
|
|
299
302
|
const anyChange =
|
|
300
303
|
titleChanged ||
|
|
301
304
|
contentChanged ||
|
|
305
|
+
descriptionChanged ||
|
|
302
306
|
iconChanged ||
|
|
303
307
|
favoriteChanged ||
|
|
304
308
|
discoverabilityChanged ||
|
|
@@ -322,6 +326,7 @@ export default defineAction({
|
|
|
322
326
|
const updates: Record<string, unknown> = { updatedAt: now };
|
|
323
327
|
if (titleChanged) updates.title = file.title;
|
|
324
328
|
if (contentChanged) updates.content = file.content;
|
|
329
|
+
if (descriptionChanged) updates.description = file.description;
|
|
325
330
|
if (iconChanged) updates.icon = file.icon ?? null;
|
|
326
331
|
if (favoriteChanged) updates.isFavorite = boolToInt(file.isFavorite);
|
|
327
332
|
if (discoverabilityChanged) {
|
|
@@ -347,6 +352,7 @@ export default defineAction({
|
|
|
347
352
|
orgId: currentOrgId,
|
|
348
353
|
parentId: null,
|
|
349
354
|
title: file.title,
|
|
355
|
+
description: file.description ?? "",
|
|
350
356
|
content: file.content,
|
|
351
357
|
icon: file.icon ?? null,
|
|
352
358
|
position: file.position ?? index,
|
|
@@ -70,6 +70,7 @@ export default defineAction({
|
|
|
70
70
|
id: schema.documents.id,
|
|
71
71
|
parentId: schema.documents.parentId,
|
|
72
72
|
title: schema.documents.title,
|
|
73
|
+
description: schema.documents.description,
|
|
73
74
|
contentSnippet: sql<string>`substr(${schema.documents.content}, 1, 400)`,
|
|
74
75
|
contentLength: sql<number>`length(${schema.documents.content})`,
|
|
75
76
|
icon: schema.documents.icon,
|
|
@@ -282,6 +283,7 @@ export default defineAction({
|
|
|
282
283
|
id: d.id,
|
|
283
284
|
parentId: d.parentId,
|
|
284
285
|
title: d.title,
|
|
286
|
+
description: d.description,
|
|
285
287
|
contentPreview: contentPreview(d.contentSnippet),
|
|
286
288
|
contentLength: Number(d.contentLength) || 0,
|
|
287
289
|
icon: d.icon,
|
|
@@ -299,6 +301,7 @@ export default defineAction({
|
|
|
299
301
|
id: database.id,
|
|
300
302
|
documentId: database.documentId,
|
|
301
303
|
title: database.title,
|
|
304
|
+
description: d.description,
|
|
302
305
|
viewConfig: parseDatabaseViewConfig(database.viewConfigJson),
|
|
303
306
|
createdAt: database.createdAt,
|
|
304
307
|
updatedAt: database.updatedAt,
|
|
@@ -73,6 +73,7 @@ export default defineAction({
|
|
|
73
73
|
return {
|
|
74
74
|
id: doc.id,
|
|
75
75
|
title: doc.title,
|
|
76
|
+
description: doc.description ?? "",
|
|
76
77
|
content: formatDocumentContent(doc.content ?? "", format),
|
|
77
78
|
format,
|
|
78
79
|
deepLink: buildDeepLink({
|
|
@@ -104,6 +105,7 @@ export default defineAction({
|
|
|
104
105
|
return {
|
|
105
106
|
id: doc.id,
|
|
106
107
|
title: doc.title,
|
|
108
|
+
description: (doc.description as string | null | undefined) ?? "",
|
|
107
109
|
content,
|
|
108
110
|
format,
|
|
109
111
|
deepLink: buildDeepLink({
|
|
@@ -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 ||
|
|
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 =
|
|
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
|
|
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}
|