@agent-native/core 0.101.6 → 0.101.10
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/corpus/README.md +1 -1
- package/corpus/core/CHANGELOG.md +28 -0
- package/corpus/core/docs/content/deployment.mdx +9 -7
- package/corpus/core/docs/content/locales/ar-SA/deployment.mdx +9 -7
- package/corpus/core/docs/content/locales/de-DE/deployment.mdx +9 -7
- package/corpus/core/docs/content/locales/es-ES/deployment.mdx +9 -7
- package/corpus/core/docs/content/locales/fr-FR/deployment.mdx +9 -7
- package/corpus/core/docs/content/locales/hi-IN/deployment.mdx +9 -7
- package/corpus/core/docs/content/locales/ja-JP/deployment.mdx +9 -7
- package/corpus/core/docs/content/locales/ko-KR/deployment.mdx +9 -7
- package/corpus/core/docs/content/locales/pt-BR/deployment.mdx +9 -7
- package/corpus/core/docs/content/locales/zh-CN/deployment.mdx +9 -7
- package/corpus/core/docs/content/locales/zh-TW/deployment.mdx +9 -7
- 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/client/review/ReviewCommentComposer.tsx +9 -1
- package/corpus/core/src/client/review/ReviewThreadPanel.tsx +17 -2
- package/corpus/core/src/client/settings/SettingsPanel.tsx +41 -21
- package/corpus/core/src/client/settings/useBuilderStatus.ts +28 -9
- package/corpus/core/src/client/setup-connections/BuilderConnectCard.tsx +2 -7
- 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/core/src/server/auth.ts +25 -1
- package/corpus/core/src/server/builder-browser.ts +353 -1
- package/corpus/core/src/server/core-routes-plugin.ts +601 -223
- package/corpus/templates/calendar/app/components/calendar/DayView.tsx +80 -1
- package/corpus/templates/calendar/app/components/calendar/EventCard.tsx +28 -3
- package/corpus/templates/calendar/app/components/calendar/EventDetailPanel.tsx +5 -1
- package/corpus/templates/calendar/app/components/calendar/EventDetailPopover.tsx +30 -3
- package/corpus/templates/calendar/app/components/calendar/OutOfOfficeEvent.tsx +196 -0
- package/corpus/templates/calendar/app/components/calendar/WeekView.tsx +115 -1
- package/corpus/templates/calendar/app/lib/out-of-office.ts +45 -0
- package/corpus/templates/calendar/changelog/2026-07-14-out-of-office-blocks-now-sit-behind-meetings-and-event-stack.md +6 -0
- 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 +32 -9
- package/corpus/templates/content/actions/_builder-cms-intent-lookup.ts +87 -0
- package/corpus/templates/content/actions/_builder-cms-read-client.ts +173 -25
- package/corpus/templates/content/actions/_builder-cms-source-adapter.ts +1 -0
- package/corpus/templates/content/actions/_builder-cms-write-adapter.ts +427 -18
- package/corpus/templates/content/actions/_builder-cms-write-client.ts +17 -73
- package/corpus/templates/content/actions/_builder-cms-write-settings.ts +27 -7
- package/corpus/templates/content/actions/_builder-source-execution-claim.ts +124 -0
- package/corpus/templates/content/actions/_builder-source-execution-preservation.ts +21 -0
- package/corpus/templates/content/actions/_builder-source-timings.ts +57 -0
- package/corpus/templates/content/actions/_database-source-utils.ts +1071 -170
- package/corpus/templates/content/actions/_database-utils.ts +104 -13
- package/corpus/templates/content/actions/_local-file-documents.ts +53 -1
- package/corpus/templates/content/actions/_preview-document-draft.ts +31 -0
- package/corpus/templates/content/actions/_property-utils.ts +7 -1
- package/corpus/templates/content/actions/cancel-prepared-builder-source-update.ts +309 -0
- 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/execute-builder-source-batch.ts +120 -49
- package/corpus/templates/content/actions/execute-builder-source-execution.ts +608 -264
- 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/get-preview-document-draft.ts +26 -0
- 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/materialize-builder-required-fields.ts +550 -0
- package/corpus/templates/content/actions/prepare-builder-source-execution.ts +112 -65
- package/corpus/templates/content/actions/prepare-builder-source-review.ts +463 -170
- package/corpus/templates/content/actions/preview-builder-source-review.ts +99 -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/set-content-database-source-write-mode.ts +2 -2
- package/corpus/templates/content/actions/update-document.ts +16 -1
- package/corpus/templates/content/actions/update-preview-document-draft.ts +153 -0
- 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 +250 -49
- package/corpus/templates/content/app/components/editor/VisualEditor.tsx +57 -5
- package/corpus/templates/content/app/components/editor/body-hydration.ts +27 -0
- package/corpus/templates/content/app/components/editor/database/DatabaseView.tsx +2414 -589
- package/corpus/templates/content/app/components/editor/database/settings.tsx +13 -10
- package/corpus/templates/content/app/components/editor/database-sources/BuilderSourceReviewDialog.tsx +358 -75
- package/corpus/templates/content/app/components/editor/previewDocumentSaveController.ts +124 -29
- package/corpus/templates/content/app/components/editor/previewDocumentSaveRegistry.ts +2 -0
- package/corpus/templates/content/app/global.css +18 -1
- package/corpus/templates/content/app/hooks/use-content-database.ts +68 -0
- package/corpus/templates/content/app/hooks/use-documents.ts +53 -4
- package/corpus/templates/content/app/i18n/zh-TW.ts +30 -0
- package/corpus/templates/content/app/i18n-data.ts +339 -0
- package/corpus/templates/content/changelog/2026-07-10-builder-backed-preview-edits-are-preserved-when-article-bodi.md +6 -0
- package/corpus/templates/content/changelog/2026-07-10-builder-cms-sources-can-now-be-enabled-for-guarded-staged-or.md +6 -0
- package/corpus/templates/content/changelog/2026-07-13-builder-connection-setup-is-now-available-directly-from-conn.md +6 -0
- package/corpus/templates/content/changelog/2026-07-13-builder-reviews-now-hide-already-applied-writes-detect-nativ.md +6 -0
- package/corpus/templates/content/changelog/2026-07-13-required-builder-publishing-fields-can-now-be-added-directly.md +6 -0
- package/corpus/templates/content/changelog/2026-07-13-you-can-now-cancel-a-prepared-builder-update-safely-before-i.md +6 -0
- package/corpus/templates/content/changelog/2026-07-14-builder-account-connection-now-remains-available-when-branch.md +6 -0
- package/corpus/templates/content/changelog/2026-07-14-builder-backed-articles-now-preserve-fifth-and-sixth-level-h.md +6 -0
- package/corpus/templates/content/changelog/2026-07-14-builder-sources-now-review-and-publish-rich-article-updates-.md +6 -0
- package/corpus/templates/content/changelog/2026-07-14-builder-writes-now-stop-retries-when-reconciliation-is-needed.md +6 -0
- package/corpus/templates/content/changelog/2026-07-14-file-and-media-links-now-validate-before-saving.md +6 -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/parity/matrix.md +27 -25
- package/corpus/templates/content/parity/matrix.ts +50 -2
- package/corpus/templates/content/server/db/schema.ts +51 -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/auth.ts +1 -0
- package/corpus/templates/content/server/plugins/db.ts +59 -0
- package/corpus/templates/content/server/routes/api/document-agent-context.json.get.ts +5 -0
- package/corpus/templates/content/shared/api.ts +87 -1
- package/corpus/templates/content/shared/builder-mdx.ts +705 -15
- package/corpus/templates/content/shared/content-source.ts +7 -0
- package/corpus/templates/content/shared/nfm.ts +3 -3
- package/corpus/templates/content/shared/properties.ts +2 -0
- package/corpus/templates/design/app/components/design/ReadOnlyDesignBanner.tsx +52 -7
- package/corpus/templates/design/app/components/design/ReviewCommentsPanel.tsx +36 -4
- package/corpus/templates/design/app/components/visual-editor/ReviewCanvasPins.tsx +4 -1
- package/corpus/templates/design/app/i18n/ar-SA.ts +1 -0
- package/corpus/templates/design/app/i18n/de-DE.ts +1 -0
- package/corpus/templates/design/app/i18n/en-US.ts +1 -0
- package/corpus/templates/design/app/i18n/es-ES.ts +1 -0
- package/corpus/templates/design/app/i18n/fr-FR.ts +1 -0
- package/corpus/templates/design/app/i18n/hi-IN.ts +1 -0
- package/corpus/templates/design/app/i18n/ja-JP.ts +1 -0
- package/corpus/templates/design/app/i18n/ko-KR.ts +1 -0
- package/corpus/templates/design/app/i18n/pt-BR.ts +1 -0
- package/corpus/templates/design/app/i18n/zh-CN.ts +1 -0
- package/corpus/templates/design/app/i18n/zh-TW.ts +1 -0
- package/corpus/templates/design/app/pages/design-editor/selection-state.ts +8 -0
- package/corpus/templates/design/app/pages/design-editor/tool-state.ts +11 -0
- package/corpus/templates/design/changelog/2026-07-14-reviewers-can-now-pin-comments-from-the-canvas-toolbar-targe.md +6 -0
- package/corpus/templates/design/changelog/2026-07-15-viewer-comment-controls-now-sit-inside-the-read-only-notice-.md +6 -0
- package/corpus/templates/design/shared/review-anchor.ts +48 -0
- package/corpus/templates/plan/server/plan-mdx.ts +53 -7
- 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/client/review/ReviewCommentComposer.d.ts +2 -1
- package/dist/client/review/ReviewCommentComposer.d.ts.map +1 -1
- package/dist/client/review/ReviewCommentComposer.js +3 -3
- package/dist/client/review/ReviewCommentComposer.js.map +1 -1
- package/dist/client/review/ReviewThreadPanel.d.ts +9 -1
- package/dist/client/review/ReviewThreadPanel.d.ts.map +1 -1
- package/dist/client/review/ReviewThreadPanel.js +6 -4
- package/dist/client/review/ReviewThreadPanel.js.map +1 -1
- package/dist/client/settings/SettingsPanel.d.ts +3 -0
- package/dist/client/settings/SettingsPanel.d.ts.map +1 -1
- package/dist/client/settings/SettingsPanel.js +11 -4
- package/dist/client/settings/SettingsPanel.js.map +1 -1
- package/dist/client/settings/useBuilderStatus.d.ts +8 -4
- package/dist/client/settings/useBuilderStatus.d.ts.map +1 -1
- package/dist/client/settings/useBuilderStatus.js +19 -6
- package/dist/client/settings/useBuilderStatus.js.map +1 -1
- package/dist/client/setup-connections/BuilderConnectCard.d.ts.map +1 -1
- package/dist/client/setup-connections/BuilderConnectCard.js +2 -5
- package/dist/client/setup-connections/BuilderConnectCard.js.map +1 -1
- package/dist/collab/awareness.d.ts +2 -2
- package/dist/collab/awareness.d.ts.map +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/observability/routes.d.ts +5 -5
- package/dist/provider-api/corpus-jobs.d.ts +2 -2
- package/dist/secrets/routes.d.ts +9 -9
- 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/auth.d.ts +1 -0
- package/dist/server/auth.d.ts.map +1 -1
- package/dist/server/auth.js +19 -2
- package/dist/server/auth.js.map +1 -1
- package/dist/server/builder-browser.d.ts +78 -0
- package/dist/server/builder-browser.d.ts.map +1 -1
- package/dist/server/builder-browser.js +246 -1
- package/dist/server/builder-browser.js.map +1 -1
- package/dist/server/core-routes-plugin.d.ts +41 -0
- package/dist/server/core-routes-plugin.d.ts.map +1 -1
- package/dist/server/core-routes-plugin.js +260 -14
- package/dist/server/core-routes-plugin.js.map +1 -1
- package/docs/content/deployment.mdx +9 -7
- package/docs/content/locales/ar-SA/deployment.mdx +9 -7
- package/docs/content/locales/de-DE/deployment.mdx +9 -7
- package/docs/content/locales/es-ES/deployment.mdx +9 -7
- package/docs/content/locales/fr-FR/deployment.mdx +9 -7
- package/docs/content/locales/hi-IN/deployment.mdx +9 -7
- package/docs/content/locales/ja-JP/deployment.mdx +9 -7
- package/docs/content/locales/ko-KR/deployment.mdx +9 -7
- package/docs/content/locales/pt-BR/deployment.mdx +9 -7
- package/docs/content/locales/zh-CN/deployment.mdx +9 -7
- package/docs/content/locales/zh-TW/deployment.mdx +9 -7
- package/package.json +2 -2
|
@@ -43,6 +43,11 @@ import {
|
|
|
43
43
|
partitionAllDayEvents,
|
|
44
44
|
} from "@/lib/all-day-layout";
|
|
45
45
|
import { getEventDisplayColor, allOtherDeclined } from "@/lib/event-colors";
|
|
46
|
+
import {
|
|
47
|
+
getFirstVisibleOutOfOfficeDayIndex,
|
|
48
|
+
getOutOfOfficeSegment,
|
|
49
|
+
isOutOfOfficeEvent,
|
|
50
|
+
} from "@/lib/out-of-office";
|
|
46
51
|
import {
|
|
47
52
|
shouldSuppressAfterPopoverClose,
|
|
48
53
|
shouldSuppressCreatePointerDown,
|
|
@@ -56,6 +61,7 @@ import {
|
|
|
56
61
|
} from "@/lib/working-location";
|
|
57
62
|
|
|
58
63
|
import { EventDetailPopover } from "./EventDetailPopover";
|
|
64
|
+
import { OutOfOfficeEvent } from "./OutOfOfficeEvent";
|
|
59
65
|
import { shouldRenderWeekDragSegment } from "./week-drag-segment";
|
|
60
66
|
|
|
61
67
|
interface WeekViewProps {
|
|
@@ -285,6 +291,7 @@ interface WeekEventCardProps {
|
|
|
285
291
|
onDraftUpdate?: WeekViewProps["onDraftUpdate"];
|
|
286
292
|
onDraftCreate?: WeekViewProps["onDraftCreate"];
|
|
287
293
|
onDraftDiscard?: WeekViewProps["onDraftDiscard"];
|
|
294
|
+
onPopoverOpenChange: (event: CalendarEvent, open: boolean) => void;
|
|
288
295
|
}
|
|
289
296
|
|
|
290
297
|
/**
|
|
@@ -320,6 +327,7 @@ const WeekEventCard = memo(function WeekEventCard({
|
|
|
320
327
|
onDraftUpdate,
|
|
321
328
|
onDraftCreate,
|
|
322
329
|
onDraftDiscard,
|
|
330
|
+
onPopoverOpenChange,
|
|
323
331
|
}: WeekEventCardProps) {
|
|
324
332
|
const t = useT();
|
|
325
333
|
const li = layout.get(event.id) ?? {
|
|
@@ -558,6 +566,7 @@ const WeekEventCard = memo(function WeekEventCard({
|
|
|
558
566
|
onDraftUpdate={onDraftUpdate}
|
|
559
567
|
onDraftCreate={onDraftCreate}
|
|
560
568
|
onDraftDiscard={onDraftDiscard}
|
|
569
|
+
onOpenChange={(open) => onPopoverOpenChange(event, open)}
|
|
561
570
|
>
|
|
562
571
|
{eventButton}
|
|
563
572
|
</EventDetailPopover>
|
|
@@ -618,6 +627,7 @@ export const WeekView = memo(function WeekView({
|
|
|
618
627
|
const GUTTER_WIDTH = isMobile ? MOBILE_GUTTER_WIDTH : DESKTOP_GUTTER_WIDTH;
|
|
619
628
|
const [now, setNow] = useState(new Date());
|
|
620
629
|
const [focusedEventId, setFocusedEventId] = useState<string | null>(null);
|
|
630
|
+
const focusedEventIdRef = useRef<string | null>(null);
|
|
621
631
|
const currentTimeRef = useRef<HTMLDivElement>(null);
|
|
622
632
|
const scrollContainerRef = useRef<HTMLDivElement>(null);
|
|
623
633
|
const allDayContainerRef = useRef<HTMLDivElement>(null);
|
|
@@ -628,6 +638,7 @@ export const WeekView = memo(function WeekView({
|
|
|
628
638
|
useEffect(() => {
|
|
629
639
|
function handleKey(e: KeyboardEvent) {
|
|
630
640
|
if (e.key === "Escape") {
|
|
641
|
+
focusedEventIdRef.current = null;
|
|
631
642
|
setFocusedEventId(null);
|
|
632
643
|
setFocusedEvent(null);
|
|
633
644
|
}
|
|
@@ -675,7 +686,15 @@ export const WeekView = memo(function WeekView({
|
|
|
675
686
|
// Separate all-day and timed events
|
|
676
687
|
const allDayEvents = useMemo(() => events.filter((e) => e.allDay), [events]);
|
|
677
688
|
|
|
678
|
-
const
|
|
689
|
+
const outOfOfficeEvents = useMemo(
|
|
690
|
+
() => events.filter((event) => !event.allDay && isOutOfOfficeEvent(event)),
|
|
691
|
+
[events],
|
|
692
|
+
);
|
|
693
|
+
|
|
694
|
+
const timedEvents = useMemo(
|
|
695
|
+
() => events.filter((event) => !event.allDay && !isOutOfOfficeEvent(event)),
|
|
696
|
+
[events],
|
|
697
|
+
);
|
|
679
698
|
|
|
680
699
|
const { workingLocations, regularEvents } = useMemo(
|
|
681
700
|
() => partitionAllDayEvents(allDayEvents),
|
|
@@ -849,6 +868,22 @@ export const WeekView = memo(function WeekView({
|
|
|
849
868
|
|
|
850
869
|
const canDrag = !!onEventTimeChange;
|
|
851
870
|
|
|
871
|
+
const handleEventPopoverOpenChange = useCallback(
|
|
872
|
+
(event: CalendarEvent, open: boolean) => {
|
|
873
|
+
if (open) {
|
|
874
|
+
focusedEventIdRef.current = event.id;
|
|
875
|
+
setFocusedEventId(event.id);
|
|
876
|
+
setFocusedEvent(event);
|
|
877
|
+
return;
|
|
878
|
+
}
|
|
879
|
+
if (focusedEventIdRef.current !== event.id) return;
|
|
880
|
+
focusedEventIdRef.current = null;
|
|
881
|
+
setFocusedEventId(null);
|
|
882
|
+
setFocusedEvent(null);
|
|
883
|
+
},
|
|
884
|
+
[setFocusedEvent],
|
|
885
|
+
);
|
|
886
|
+
|
|
852
887
|
const handleEventPointerDown = useCallback(
|
|
853
888
|
(
|
|
854
889
|
e: React.PointerEvent,
|
|
@@ -856,6 +891,7 @@ export const WeekView = memo(function WeekView({
|
|
|
856
891
|
isStart: boolean,
|
|
857
892
|
dayIndex: number,
|
|
858
893
|
) => {
|
|
894
|
+
focusedEventIdRef.current = event.id;
|
|
859
895
|
setFocusedEventId(event.id);
|
|
860
896
|
setFocusedEvent(event);
|
|
861
897
|
if (
|
|
@@ -1262,6 +1298,16 @@ export const WeekView = memo(function WeekView({
|
|
|
1262
1298
|
}
|
|
1263
1299
|
}
|
|
1264
1300
|
|
|
1301
|
+
const visibleOutOfOfficeEvents = outOfOfficeEvents.filter(
|
|
1302
|
+
(event) => {
|
|
1303
|
+
const overrides = getDragOverrides(event.id);
|
|
1304
|
+
return (
|
|
1305
|
+
getOutOfOfficeSegment(event, day) !== null ||
|
|
1306
|
+
(dragEventId === event.id && overrides?.dayIndex === dayIndex)
|
|
1307
|
+
);
|
|
1308
|
+
},
|
|
1309
|
+
);
|
|
1310
|
+
|
|
1265
1311
|
return (
|
|
1266
1312
|
<div
|
|
1267
1313
|
key={day.toISOString()}
|
|
@@ -1338,6 +1384,73 @@ export const WeekView = memo(function WeekView({
|
|
|
1338
1384
|
</div>
|
|
1339
1385
|
)}
|
|
1340
1386
|
|
|
1387
|
+
{/* Native Google out-of-office context sits behind meetings. */}
|
|
1388
|
+
{!isLoading &&
|
|
1389
|
+
visibleOutOfOfficeEvents.map((event, markerIndex) => {
|
|
1390
|
+
const isBeingDragged = dragEventId === event.id;
|
|
1391
|
+
const overrides = getDragOverrides(event.id);
|
|
1392
|
+
const canonicalDayIndex =
|
|
1393
|
+
getFirstVisibleOutOfOfficeDayIndex(event, days);
|
|
1394
|
+
return (
|
|
1395
|
+
<OutOfOfficeEvent
|
|
1396
|
+
key={`${event._tempId ?? event.id}:${day.toISOString()}`}
|
|
1397
|
+
event={event}
|
|
1398
|
+
day={day}
|
|
1399
|
+
hourHeight={HOUR_HEIGHT}
|
|
1400
|
+
color={
|
|
1401
|
+
getEventDisplayColor(event, prefs) ??
|
|
1402
|
+
"hsl(var(--primary))"
|
|
1403
|
+
}
|
|
1404
|
+
label={t("eventForm.outOfOffice")}
|
|
1405
|
+
markerIndex={markerIndex}
|
|
1406
|
+
compactMarker
|
|
1407
|
+
canDrag={canDrag}
|
|
1408
|
+
isBeingDragged={isBeingDragged}
|
|
1409
|
+
isDragging={isDragging}
|
|
1410
|
+
isDragTargetDay={overrides?.dayIndex === dayIndex}
|
|
1411
|
+
overrideTop={overrides?.top ?? null}
|
|
1412
|
+
overrideHeight={overrides?.height ?? null}
|
|
1413
|
+
onMovePointerDown={(pointerEvent, startsOnDay) =>
|
|
1414
|
+
handleEventPointerDown(
|
|
1415
|
+
pointerEvent,
|
|
1416
|
+
event,
|
|
1417
|
+
startsOnDay,
|
|
1418
|
+
dayIndex,
|
|
1419
|
+
)
|
|
1420
|
+
}
|
|
1421
|
+
onResizeTopPointerDown={(pointerEvent) =>
|
|
1422
|
+
handleResizeTopPointerDown(
|
|
1423
|
+
pointerEvent,
|
|
1424
|
+
event.id,
|
|
1425
|
+
dayIndex,
|
|
1426
|
+
)
|
|
1427
|
+
}
|
|
1428
|
+
onResizeBottomPointerDown={(pointerEvent) =>
|
|
1429
|
+
handleResizeBottomPointerDown(
|
|
1430
|
+
pointerEvent,
|
|
1431
|
+
event.id,
|
|
1432
|
+
dayIndex,
|
|
1433
|
+
)
|
|
1434
|
+
}
|
|
1435
|
+
shouldSuppressClick={shouldSuppressClick}
|
|
1436
|
+
onDelete={onDeleteEvent}
|
|
1437
|
+
isDraft={draftEventIds.includes(event.id)}
|
|
1438
|
+
defaultOpen={
|
|
1439
|
+
quickEditEventId === event.id &&
|
|
1440
|
+
dayIndex === canonicalDayIndex
|
|
1441
|
+
}
|
|
1442
|
+
onTitleSave={onQuickEditSave}
|
|
1443
|
+
onDismissNew={onQuickEditCancel}
|
|
1444
|
+
onDraftUpdate={onDraftUpdate}
|
|
1445
|
+
onDraftCreate={onDraftCreate}
|
|
1446
|
+
onDraftDiscard={onDraftDiscard}
|
|
1447
|
+
onOpenChange={(open) =>
|
|
1448
|
+
handleEventPopoverOpenChange(event, open)
|
|
1449
|
+
}
|
|
1450
|
+
/>
|
|
1451
|
+
);
|
|
1452
|
+
})}
|
|
1453
|
+
|
|
1341
1454
|
{/* Skeleton events when loading */}
|
|
1342
1455
|
{isLoading &&
|
|
1343
1456
|
WEEK_SKELETONS[dayIndex]?.map(
|
|
@@ -1402,6 +1515,7 @@ export const WeekView = memo(function WeekView({
|
|
|
1402
1515
|
onDraftUpdate={onDraftUpdate}
|
|
1403
1516
|
onDraftCreate={onDraftCreate}
|
|
1404
1517
|
onDraftDiscard={onDraftDiscard}
|
|
1518
|
+
onPopoverOpenChange={handleEventPopoverOpenChange}
|
|
1405
1519
|
/>
|
|
1406
1520
|
);
|
|
1407
1521
|
})}
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
import type { CalendarEvent } from "@shared/api";
|
|
2
|
+
import { addDays, differenceInMinutes, parseISO, startOfDay } from "date-fns";
|
|
3
|
+
|
|
4
|
+
export interface OutOfOfficeSegment {
|
|
5
|
+
topMinutes: number;
|
|
6
|
+
durationMinutes: number;
|
|
7
|
+
startsOnDay: boolean;
|
|
8
|
+
endsOnDay: boolean;
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
export function isOutOfOfficeEvent(
|
|
12
|
+
event: Pick<CalendarEvent, "eventType">,
|
|
13
|
+
): boolean {
|
|
14
|
+
return event.eventType === "outOfOffice";
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
/** Return the portion of a timed out-of-office event visible on one day. */
|
|
18
|
+
export function getOutOfOfficeSegment(
|
|
19
|
+
event: Pick<CalendarEvent, "start" | "end">,
|
|
20
|
+
day: Date,
|
|
21
|
+
): OutOfOfficeSegment | null {
|
|
22
|
+
const eventStart = parseISO(event.start);
|
|
23
|
+
const eventEnd = parseISO(event.end);
|
|
24
|
+
const dayStart = startOfDay(day);
|
|
25
|
+
const dayEnd = addDays(dayStart, 1);
|
|
26
|
+
|
|
27
|
+
if (eventStart >= dayEnd || eventEnd <= dayStart) return null;
|
|
28
|
+
|
|
29
|
+
const segmentStart = eventStart > dayStart ? eventStart : dayStart;
|
|
30
|
+
const segmentEnd = eventEnd < dayEnd ? eventEnd : dayEnd;
|
|
31
|
+
|
|
32
|
+
return {
|
|
33
|
+
topMinutes: Math.max(0, differenceInMinutes(segmentStart, dayStart)),
|
|
34
|
+
durationMinutes: Math.max(1, differenceInMinutes(segmentEnd, segmentStart)),
|
|
35
|
+
startsOnDay: eventStart >= dayStart && eventStart < dayEnd,
|
|
36
|
+
endsOnDay: eventEnd > dayStart && eventEnd <= dayEnd,
|
|
37
|
+
};
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
export function getFirstVisibleOutOfOfficeDayIndex(
|
|
41
|
+
event: Pick<CalendarEvent, "start" | "end">,
|
|
42
|
+
days: Date[],
|
|
43
|
+
): number {
|
|
44
|
+
return days.findIndex((day) => getOutOfOfficeSegment(event, day) !== null);
|
|
45
|
+
}
|
|
@@ -101,6 +101,37 @@ inferences for confirmation, then submit once. When required information is
|
|
|
101
101
|
missing, keep the clarification in the originating thread and retain earlier
|
|
102
102
|
answers as context.
|
|
103
103
|
|
|
104
|
+
### Slack Follow-ups And Corrections
|
|
105
|
+
|
|
106
|
+
A follow-up in an existing Slack thread is not automatically a new intake. Read
|
|
107
|
+
the thread context and inspect the prior Content artifact identity first,
|
|
108
|
+
including any returned document ID or `/page/<id>` path and the canonical
|
|
109
|
+
database row when available. Then choose the operation that matches the user's
|
|
110
|
+
intent:
|
|
111
|
+
|
|
112
|
+
- **Update** the same document for corrections, refinements, status changes, or
|
|
113
|
+
renames that still describe the same request. A rename changes the title, not
|
|
114
|
+
the artifact identity: preserve the stable Content document ID and page path.
|
|
115
|
+
- **Add** new details to the same document when the follow-up extends the
|
|
116
|
+
original request without replacing it.
|
|
117
|
+
- **Supersede** only when the user intends a replacement artifact or distinct
|
|
118
|
+
successor and the workspace's schema or instructions define how that
|
|
119
|
+
relationship is recorded. Preserve a concrete link to the prior artifact.
|
|
120
|
+
- **Create** only when the follow-up is genuinely a separate request or the user
|
|
121
|
+
explicitly asks for a new artifact. Do not blindly submit another row merely
|
|
122
|
+
because a new Slack message arrived.
|
|
123
|
+
|
|
124
|
+
Apply people fields from verified identity and intent, not from convenient
|
|
125
|
+
guesswork:
|
|
126
|
+
|
|
127
|
+
- When the database has a `Requester` field, default it to the verified Slack
|
|
128
|
+
sender unless the user explicitly identifies a different requester.
|
|
129
|
+
- A named doer such as "for Apoorva" maps to `Assignee` when that field exists.
|
|
130
|
+
Naming an assignee never changes or replaces `Requester`.
|
|
131
|
+
- Resolve named people to the database's accepted person identity before
|
|
132
|
+
writing. If a named person cannot be resolved unambiguously, clarify in the
|
|
133
|
+
originating Slack thread; never omit, downgrade, or silently drop the person.
|
|
134
|
+
|
|
104
135
|
## Local File Mode
|
|
105
136
|
|
|
106
137
|
Install into an existing repo with:
|
|
@@ -7,7 +7,10 @@ description: >-
|
|
|
7
7
|
|
|
8
8
|
# Document Editing
|
|
9
9
|
|
|
10
|
-
Documents are stored in the SQL database via Drizzle ORM. Each document has a
|
|
10
|
+
Documents are stored in the SQL database via Drizzle ORM. Each document has a
|
|
11
|
+
title, stable description, markdown content, optional parent (for nesting), and
|
|
12
|
+
a position for ordering. The description explains why the page exists and what
|
|
13
|
+
belongs there; it is not a changing synopsis of the current body.
|
|
11
14
|
|
|
12
15
|
## Scripts
|
|
13
16
|
|
|
@@ -48,6 +51,7 @@ Create a new document.
|
|
|
48
51
|
pnpm action create-document --title "Meeting Notes" --content "# Meeting Notes\n\nAttendees: ..."
|
|
49
52
|
pnpm action create-document --title "Sub Page" --parentId parent123
|
|
50
53
|
pnpm action create-document --title "My Page" --icon "📝"
|
|
54
|
+
pnpm action create-document --title "Research" --description "Evidence and source notes that support the current project"
|
|
51
55
|
```
|
|
52
56
|
|
|
53
57
|
### edit-document
|
|
@@ -73,6 +77,7 @@ Update an existing document. Use for **full rewrites or new content**, not for s
|
|
|
73
77
|
pnpm action update-document --id abc123 --title "New Title"
|
|
74
78
|
pnpm action update-document --id abc123 --content "# Updated Content\n\nNew text here"
|
|
75
79
|
pnpm action update-document --id abc123 --title "New Title" --content "New content"
|
|
80
|
+
pnpm action update-document --id abc123 --description "Stable guidance for what belongs on this page"
|
|
76
81
|
```
|
|
77
82
|
|
|
78
83
|
### delete-document
|
|
@@ -123,17 +128,18 @@ Always run this after any document modification to update the sidebar.
|
|
|
123
128
|
|
|
124
129
|
## Document Schema
|
|
125
130
|
|
|
126
|
-
| Column
|
|
127
|
-
|
|
|
128
|
-
| `id`
|
|
129
|
-
| `parent_id`
|
|
130
|
-
| `title`
|
|
131
|
-
| `
|
|
132
|
-
| `
|
|
133
|
-
| `
|
|
134
|
-
| `
|
|
135
|
-
| `
|
|
136
|
-
| `
|
|
131
|
+
| Column | Type | Description |
|
|
132
|
+
| ------------- | ------- | -------------------------------------- |
|
|
133
|
+
| `id` | text | Primary key (12-char hex string) |
|
|
134
|
+
| `parent_id` | text | Parent document ID (null for root) |
|
|
135
|
+
| `title` | text | Document title (default: "Untitled") |
|
|
136
|
+
| `description` | text | Stable semantic guidance for the page |
|
|
137
|
+
| `content` | text | Markdown content |
|
|
138
|
+
| `icon` | text | Emoji icon (optional) |
|
|
139
|
+
| `position` | integer | Sort order within parent (0-based) |
|
|
140
|
+
| `is_favorite` | integer | Whether document is favorited (0 or 1) |
|
|
141
|
+
| `created_at` | text | ISO timestamp |
|
|
142
|
+
| `updated_at` | text | ISO timestamp |
|
|
137
143
|
|
|
138
144
|
## Content Format
|
|
139
145
|
|
|
@@ -142,21 +148,29 @@ Documents use **markdown** for content. The editor renders markdown in real time
|
|
|
142
148
|
## Parent-Child Hierarchy
|
|
143
149
|
|
|
144
150
|
Documents form a tree via `parent_id`:
|
|
151
|
+
|
|
145
152
|
- Root documents have `parent_id = null`
|
|
146
153
|
- Child documents reference their parent's `id`
|
|
147
154
|
- Deleting a parent recursively deletes all children
|
|
148
155
|
- Position determines ordering within the same parent
|
|
149
156
|
|
|
157
|
+
Descriptions are owned; context is inherited. `get-document` and `view-screen`
|
|
158
|
+
return the focused page's own description plus a computed root-to-parent
|
|
159
|
+
`contextPath`. Use that path to understand where the page lives, but never copy
|
|
160
|
+
ancestor descriptions into the child. Database, property, and option
|
|
161
|
+
descriptions narrow the guidance further when working with structured values.
|
|
162
|
+
|
|
150
163
|
## Common Tasks
|
|
151
164
|
|
|
152
|
-
| User says
|
|
153
|
-
|
|
|
154
|
-
| "Create a page about X"
|
|
155
|
-
| "
|
|
156
|
-
| "
|
|
157
|
-
| "
|
|
158
|
-
| "
|
|
159
|
-
| "
|
|
160
|
-
| "
|
|
165
|
+
| User says | What to do |
|
|
166
|
+
| ---------------------------- | ----------------------------------------------------------------------------------- |
|
|
167
|
+
| "Create a page about X" | `create-document --title "X" --content "# X\n\n..."` |
|
|
168
|
+
| "Describe what belongs here" | `update-document --id ... --description "..."` |
|
|
169
|
+
| "Find my meeting notes" | `search-documents --query "meeting notes"` |
|
|
170
|
+
| "Fix a typo / edit a line" | `view-screen` to get ID, then `edit-document --id ... --find "old" --replace "new"` |
|
|
171
|
+
| "Rewrite this document" | `view-screen` to get ID, then `update-document --id ... --content ...` |
|
|
172
|
+
| "Delete this page" | `view-screen` to get ID, then `delete-document --id ...` |
|
|
173
|
+
| "Add a sub-page" | `create-document --title "Sub" --parentId <parentId>` |
|
|
174
|
+
| "Show me the document tree" | `list-documents` |
|
|
161
175
|
|
|
162
176
|
Always run `refresh-list` after any create, update, or delete operation.
|
|
@@ -102,19 +102,19 @@ cd templates/content && pnpm action <name> [args]
|
|
|
102
102
|
| `push-builder-doc` | `--files <json> [--path <file.builder.mdx>] [--dryRun true\|false]` | Guarded Builder autosave PATCH for the safe Builder test model; never publishes |
|
|
103
103
|
| `navigate` | `--path <path>` or `--documentId <id>` or `--databaseId <id>` | Open a route, document page, or database page in the UI |
|
|
104
104
|
| `search-documents` | `--query <text> [--format json]` | Search by title/content and return snippets |
|
|
105
|
-
| `get-document` | `--id <id> [--format json]` | Get a
|
|
105
|
+
| `get-document` | `--id <id> [--format json]` | Get a document with content, stable description, properties, and computed ancestry context |
|
|
106
106
|
| `pull-document` | `--id <id> [--format markdown\|text]` | Collab-aware "ingest the final" read |
|
|
107
|
-
| `create-document` | `--title <text> [--content] [--parentId] [--icon]`
|
|
107
|
+
| `create-document` | `--title <text> [--content] [--description] [--parentId] [--icon]` | Create a document with optional stable guidance about why it exists and what belongs there |
|
|
108
108
|
| `edit-document` | `--id <id> --find <text> --replace <text>` | Surgical text edit (preferred for modifications) |
|
|
109
109
|
| `edit-document` | `--id <id> --edits <json>` | Batch surgical text edits |
|
|
110
|
-
| `update-document` | `--id <id> [--title] [--content] [--icon]`
|
|
110
|
+
| `update-document` | `--id <id> [--title] [--content] [--description] [--icon]` | Update document fields; descriptions are stable guidance, not summaries of current content |
|
|
111
111
|
| `share-local-file-document` | `--id <local-file-document-id>` | Create or refresh a DB-backed shareable copy of a local file document |
|
|
112
112
|
| `remove-local-file-source` | `[--sourceRootPath <path>]` | Unlink local-file sources from Content without deleting local Markdown/MDX files |
|
|
113
113
|
| `list-local-component-files` | | List registered local MDX component source files |
|
|
114
114
|
| `write-local-component-file` | `--workspaceId <id> --path <relative-component-path> --content <source>` | Create or update a file in a registered local `components/` folder |
|
|
115
|
-
| `create-content-database` | `[--documentId <id>] [--parentId <id>] [--title <text>]`
|
|
116
|
-
| `create-inline-content-database` | `--hostDocumentId <id> [--title <text>]`
|
|
117
|
-
| `get-content-database` | `--databaseId <id>` or `--documentId <id>` | Get a database
|
|
115
|
+
| `create-content-database` | `[--documentId <id>] [--parentId <id>] [--title <text>] [--description <text>]` | Create a described database page or convert an existing page into a database |
|
|
116
|
+
| `create-inline-content-database` | `--hostDocumentId <id> [--title <text>] [--description <text>]` | Create a described database owned by an inline database block in the host document |
|
|
117
|
+
| `get-content-database` | `--databaseId <id>` or `--documentId <id>` | Get a database with its description, property/option schema guidance, item pages, and computed ancestry context |
|
|
118
118
|
| `list-trashed-content-databases` | | List soft-deleted databases visible in the sidebar Trash surface |
|
|
119
119
|
| `restore-content-database` | `--databaseId <id>` | Restore a soft-deleted database from the sidebar Trash surface |
|
|
120
120
|
| `get-content-database-source` | `--databaseId <id>` or `--documentId <id>` | Inspect local/no-source or source-backed status, mappings, row identity, freshness, and change sets |
|
|
@@ -123,13 +123,14 @@ cd templates/content && pnpm action <name> [args]
|
|
|
123
123
|
| `change-content-database-source-role` | `--databaseId <id>` or `--documentId <id> --sourceId <id> --relationshipMode items\|details [--join <json>]` | Change an attached source between adding rows and adding matched detail columns without removing the source |
|
|
124
124
|
| `refresh-content-database-source` | `--databaseId <id>` or `--documentId <id>` | Refresh the read-only source status envelope; large Builder CMS sources may return a partial fetch, and another refresh continues loading remaining rows |
|
|
125
125
|
| `process-builder-body-hydration` | `--sourceId <id> [--documentId <id>] [--limit <n>]` | Hydrate queued Builder article bodies into readable Content markdown with preserved source-component markers |
|
|
126
|
-
| `set-content-database-source-write-mode` | `--databaseId <id>` or `--documentId <id> --
|
|
126
|
+
| `set-content-database-source-write-mode` | `--databaseId <id>` or `--documentId <id> [--sourceId <id>] --writeMode read_only\|stage_only\|publish_updates [--allowPublicationTransitions true\|false]` | Set the per-source Builder write tier; requires page admin access and remains read-only by default |
|
|
127
127
|
| `stage-builder-revision` | `--databaseId <id>` or `--documentId <id>` | Stage pending local Builder CMS changes as a local-only save-revision record; never calls Builder |
|
|
128
128
|
| `review-content-database-source-change-set` | `--databaseId <id>` or `--documentId <id> --changeSetId <id> --decision approve\|reject [--note]` | Approve or reject a local source change-set review record without provider writes |
|
|
129
129
|
| `stage-builder-source-bulk-update` | `--databaseId <id>` or `--documentId <id> --itemIds <json-array>` or `--documentIds <json-array> --field <json> [--sourceId <id>] [--dryRun true\|false]` | Preview or stage one bounded field update across selected source-backed Builder rows; apply still goes through Builder review/execution |
|
|
130
130
|
| `prepare-builder-source-execution` | `--databaseId <id>` or `--documentId <id> --changeSetId <id> [--pushModeConfirmation autosave\|draft\|publish]` | Prepare a dry-run Builder execution gate for approved field/body changes with request semantics/idempotency key; never calls Builder |
|
|
131
131
|
| `validate-builder-source-execution` | `--databaseId <id>` or `--documentId <id> --changeSetId <id> [--idempotencyKey <key>]` | Validate/replay a prepared Builder execution gate locally as a dry run; never calls Builder |
|
|
132
|
-
| `execute-builder-source-execution` | `--databaseId <id>` or `--documentId <id> --changeSetId <id> [--idempotencyKey <key>] [--pushModeConfirmation autosave\|draft\|publish]` | Execute a guarded live Builder write only when approved, validated, enabled
|
|
132
|
+
| `execute-builder-source-execution` | `--databaseId <id>` or `--documentId <id> --changeSetId <id> [--idempotencyKey <key>] [--pushModeConfirmation autosave\|draft\|publish]` | Execute a guarded live Builder write only when approved, validated, enabled for that source, and idempotent |
|
|
133
|
+
| `cancel-prepared-builder-source-update` | `--databaseId <id>` or `--documentId <id> --sourceId <id> --changeSetId <id> [--note <text>]` | Cancel an exact prepared Builder update only when every associated execution is provably pre-dispatch; preserves review and execution history and never calls Builder |
|
|
133
134
|
| `add-database-item` | `--databaseId <id> [--title <text>] [--propertyValues <json>]` | Add a page row to a database, optionally seeding property values |
|
|
134
135
|
| `submit-content-database-form` | `--databaseId <id> [--viewId <form-view-id>] [--title <text>] [--propertyValues <json>]` | Submit one form response atomically; validates required questions, resolves option labels/IDs, writes Blocks correctly, verifies persistence, and returns the exact row page link |
|
|
135
136
|
| `duplicate-database-item` | `--itemId <id>` or `--documentId <id> [--title <text>]` | Duplicate exactly one database row page and its stored property values; for two or more rows, use `duplicate-database-items` once |
|
|
@@ -138,7 +139,7 @@ cd templates/content && pnpm action <name> [args]
|
|
|
138
139
|
| `move-database-item` | `--itemId <id>` or `--documentId <id> --position <number>` | Move a database row page to a new zero-based table position |
|
|
139
140
|
| `update-content-database-view` | `--databaseId <id> --viewConfig <json>` | Persist database views, sorts, filters, hidden properties, and view settings |
|
|
140
141
|
| `list-document-properties` | `--documentId <id> [--format json]` | List Notion-style property definitions and values for a document |
|
|
141
|
-
| `configure-document-property` | `--documentId <id> [--id <propertyId>] --name <name> --type <type> [--visibility always_show\|hide_when_empty\|always_hide]`
|
|
142
|
+
| `configure-document-property` | `--documentId <id> [--id <propertyId>] --name <name> --type <type> [--description <text>] [--visibility always_show\|hide_when_empty\|always_hide] [--options <json>]` | Create or update a property definition and its option-level guidance |
|
|
142
143
|
| `duplicate-document-property` | `--documentId <id> --propertyId <propertyId>` | Duplicate a property definition and its stored values |
|
|
143
144
|
| `delete-document-property` | `--documentId <id> --propertyId <propertyId>` | Delete a property definition and its stored values |
|
|
144
145
|
| `set-document-property` | `--documentId <id> --propertyId <propertyId> --value <json>` | Set a document property value (for a `blocks` field, the value is its markdown content) |
|
|
@@ -151,6 +152,27 @@ Database views follow Notion-style tab labels. When creating or duplicating
|
|
|
151
152
|
views in `viewConfig`, use unique default names (`Table 2`, `SEO copy 2`, etc.)
|
|
152
153
|
instead of appending several tabs with the same label.
|
|
153
154
|
|
|
155
|
+
### Self-Documenting Descriptions
|
|
156
|
+
|
|
157
|
+
Descriptions are stable semantic guidance, not generated summaries of current
|
|
158
|
+
content. Preserve this distinction when reading or writing them:
|
|
159
|
+
|
|
160
|
+
- A page description explains why the page exists and what belongs there.
|
|
161
|
+
- A database description explains the collection's purpose and inclusion
|
|
162
|
+
boundary. Inline and full-page views of one database share the same
|
|
163
|
+
description.
|
|
164
|
+
- A property description explains what the field means and what value belongs
|
|
165
|
+
there.
|
|
166
|
+
- A select, status, or multi-select option description explains when to choose
|
|
167
|
+
that option.
|
|
168
|
+
|
|
169
|
+
Descriptions are owned; context is inherited. Never copy an ancestor's prose
|
|
170
|
+
into a child description. Focused reads expose a root-to-parent `contextPath`
|
|
171
|
+
so the agent can use ancestor guidance without creating stale duplicates. Read
|
|
172
|
+
the returned descriptions before placing content or setting property values.
|
|
173
|
+
Update a description only when the object's meaning changes, not whenever its
|
|
174
|
+
current content changes.
|
|
175
|
+
|
|
154
176
|
**`pull-document` is the collab-aware "ingest the final" read** — prefer it over
|
|
155
177
|
`get-document` for external ingest (another app, an external coding agent over
|
|
156
178
|
MCP/A2A, an A2A peer). `get-document` returns whatever is in the
|
|
@@ -388,6 +410,7 @@ Public documents are reachable at `/p/<id>` once visibility is `public`. Anyone
|
|
|
388
410
|
| ------------------------------ | ------------------------------------------------------------------------------ |
|
|
389
411
|
| "What am I looking at?" | `view-screen` |
|
|
390
412
|
| "Create a page about X" | `create-document --title "X" --content "# X\n\n..."` |
|
|
413
|
+
| "Explain what belongs here" | `view-screen` to get ID, `update-document --id ... --description "..."` |
|
|
391
414
|
| "Find my meeting notes" | `search-documents --query "meeting notes"` |
|
|
392
415
|
| "Update the title of this doc" | `view-screen` to get ID, `update-document --id ... --title "New"` |
|
|
393
416
|
| "Fix a typo / small edit" | `view-screen` to get ID, `edit-document --id ... --find "old" --replace "new"` |
|
|
@@ -0,0 +1,87 @@
|
|
|
1
|
+
import { isDeepStrictEqual } from "node:util";
|
|
2
|
+
|
|
3
|
+
import { BUILDER_CMS_SAFE_WRITE_MODEL } from "../shared/api.js";
|
|
4
|
+
import { readBuilderCmsContentEntries } from "./_builder-cms-read-client.js";
|
|
5
|
+
import type { BuilderCmsSourceEntry } from "./_builder-cms-source-adapter.js";
|
|
6
|
+
import { BUILDER_CMS_EXECUTION_MARKER_FIELD } from "./_builder-cms-write-adapter.js";
|
|
7
|
+
|
|
8
|
+
export interface BuilderCmsIntentMatch {
|
|
9
|
+
id: string;
|
|
10
|
+
title: string;
|
|
11
|
+
lastUpdated: string | null;
|
|
12
|
+
published: string | null;
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
export function matchBuilderCmsSafeModelIntentEntries(
|
|
16
|
+
entries: BuilderCmsSourceEntry[],
|
|
17
|
+
args: {
|
|
18
|
+
marker?: string;
|
|
19
|
+
exactTitle?: string;
|
|
20
|
+
intendedFields?: Record<string, unknown>;
|
|
21
|
+
},
|
|
22
|
+
) {
|
|
23
|
+
const identityMatches = entries.filter((entry) => {
|
|
24
|
+
const data = rawRecord(entry.rawEntry?.data);
|
|
25
|
+
if (args.marker) {
|
|
26
|
+
return data?.[BUILDER_CMS_EXECUTION_MARKER_FIELD] === args.marker;
|
|
27
|
+
}
|
|
28
|
+
const title = data?.title;
|
|
29
|
+
return (
|
|
30
|
+
typeof title === "string" && title.trim() === args.exactTitle?.trim()
|
|
31
|
+
);
|
|
32
|
+
});
|
|
33
|
+
const matchingIntent = identityMatches.filter((entry) => {
|
|
34
|
+
const data = rawRecord(entry.rawEntry?.data);
|
|
35
|
+
return Object.entries(args.intendedFields ?? {}).every(([key, value]) =>
|
|
36
|
+
isDeepStrictEqual(data?.[key], value),
|
|
37
|
+
);
|
|
38
|
+
});
|
|
39
|
+
return {
|
|
40
|
+
count: identityMatches.length,
|
|
41
|
+
matchingIntentCount: matchingIntent.length,
|
|
42
|
+
matches: identityMatches.map(compactMatch),
|
|
43
|
+
};
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
function rawRecord(value: unknown): Record<string, unknown> | null {
|
|
47
|
+
return value && typeof value === "object" && !Array.isArray(value)
|
|
48
|
+
? (value as Record<string, unknown>)
|
|
49
|
+
: null;
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
function compactMatch(entry: BuilderCmsSourceEntry): BuilderCmsIntentMatch {
|
|
53
|
+
const raw = rawRecord(entry.rawEntry);
|
|
54
|
+
return {
|
|
55
|
+
id: entry.id,
|
|
56
|
+
title: entry.title,
|
|
57
|
+
lastUpdated:
|
|
58
|
+
typeof raw?.lastUpdated === "string" ||
|
|
59
|
+
typeof raw?.lastUpdated === "number"
|
|
60
|
+
? String(raw.lastUpdated)
|
|
61
|
+
: entry.updatedAt || null,
|
|
62
|
+
published: typeof raw?.published === "string" ? raw.published : null,
|
|
63
|
+
};
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
export async function lookupBuilderCmsSafeModelIntent(args: {
|
|
67
|
+
marker?: string;
|
|
68
|
+
exactTitle?: string;
|
|
69
|
+
intendedFields?: Record<string, unknown>;
|
|
70
|
+
}) {
|
|
71
|
+
if (!args.marker && !args.exactTitle) {
|
|
72
|
+
throw new Error("Provide an exact execution marker or exact title.");
|
|
73
|
+
}
|
|
74
|
+
const result = await readBuilderCmsContentEntries({
|
|
75
|
+
model: BUILDER_CMS_SAFE_WRITE_MODEL,
|
|
76
|
+
rawData: true,
|
|
77
|
+
requirePrivateKey: true,
|
|
78
|
+
limit: 10_000,
|
|
79
|
+
});
|
|
80
|
+
if (result.state !== "live" || result.progress.partial) {
|
|
81
|
+
throw new Error(
|
|
82
|
+
result.message ??
|
|
83
|
+
"Builder safe-model lookup was incomplete; reconciliation cannot proceed.",
|
|
84
|
+
);
|
|
85
|
+
}
|
|
86
|
+
return matchBuilderCmsSafeModelIntentEntries(result.entries, args);
|
|
87
|
+
}
|