@agent-native/core 0.101.7 → 0.101.11
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/client.ts +23 -1
- package/corpus/core/src/a2a/handlers.ts +65 -1
- package/corpus/core/src/a2a/server.ts +124 -0
- package/corpus/core/src/a2a/task-store.ts +253 -0
- package/corpus/core/src/a2a/types.ts +26 -0
- package/corpus/core/src/agent/production-agent.ts +5 -2
- 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/mcp/builtin-tools.ts +25 -1
- package/corpus/core/src/scripts/call-agent.ts +22 -3
- package/corpus/core/src/server/agent-chat-plugin.ts +86 -1
- 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/core/src/templates/workspace-core/.agents/skills/a2a-protocol/SKILL.md +25 -0
- 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/document-editing/SKILL.md +23 -0
- package/corpus/templates/content/AGENTS.md +3 -2
- 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 +1041 -154
- package/corpus/templates/content/actions/_database-utils.ts +89 -12
- package/corpus/templates/content/actions/_preview-document-draft.ts +31 -0
- package/corpus/templates/content/actions/cancel-prepared-builder-source-update.ts +309 -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/get-preview-document-draft.ts +26 -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/set-content-database-source-write-mode.ts +2 -2
- package/corpus/templates/content/actions/update-preview-document-draft.ts +153 -0
- package/corpus/templates/content/app/components/editor/DocumentProperties.tsx +27 -15
- package/corpus/templates/content/app/components/editor/MathRenderer.tsx +43 -0
- package/corpus/templates/content/app/components/editor/SlashCommandMenu.tsx +260 -4
- 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 +2353 -576
- 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/extensions/NotionExtensions.tsx +78 -0
- 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 +71 -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 +38 -0
- package/corpus/templates/content/app/i18n-data.ts +450 -0
- package/corpus/templates/content/app/root.tsx +2 -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-latex-equations-render-in-documents-public-pages-and-exports.md +6 -0
- package/corpus/templates/content/package.json +1 -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 +47 -0
- package/corpus/templates/content/server/plugins/auth.ts +1 -0
- package/corpus/templates/content/server/plugins/db.ts +53 -0
- package/corpus/templates/content/shared/api.ts +70 -1
- package/corpus/templates/content/shared/builder-mdx.ts +705 -15
- package/corpus/templates/content/shared/document-export.ts +296 -25
- package/corpus/templates/content/shared/inline-math.ts +128 -0
- package/corpus/templates/content/shared/math-rendering.ts +50 -0
- package/corpus/templates/content/shared/nfm.ts +20 -17
- package/corpus/templates/content/vite.config.ts +0 -1
- 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/mail/.agents/skills/email-drafts/SKILL.md +17 -0
- package/corpus/templates/mail/AGENTS.md +21 -19
- package/corpus/templates/mail/actions/create-attachment-upload.ts +49 -0
- package/corpus/templates/mail/changelog/2026-07-14-connected-agents-can-now-securely-upload-local-files-for-mai.md +6 -0
- package/corpus/templates/mail/server/handlers/media.ts +84 -61
- package/corpus/templates/mail/server/lib/attachment-upload-ticket.ts +234 -0
- package/corpus/templates/mail/server/lib/mail-connector-catalog.ts +8 -4
- package/corpus/templates/mail/server/lib/media-upload.ts +114 -0
- package/corpus/templates/mail/server/plugins/auth.ts +9 -1
- package/corpus/templates/mail/server/routes/api/media/attachment-upload/[uploadId].put.ts +1 -0
- package/corpus/templates/plan/server/plan-mdx.ts +53 -7
- package/dist/a2a/client.d.ts +5 -1
- package/dist/a2a/client.d.ts.map +1 -1
- package/dist/a2a/client.js +18 -1
- package/dist/a2a/client.js.map +1 -1
- package/dist/a2a/handlers.d.ts.map +1 -1
- package/dist/a2a/handlers.js +57 -8
- package/dist/a2a/handlers.js.map +1 -1
- package/dist/a2a/server.d.ts.map +1 -1
- package/dist/a2a/server.js +87 -1
- package/dist/a2a/server.js.map +1 -1
- package/dist/a2a/task-store.d.ts +27 -0
- package/dist/a2a/task-store.d.ts.map +1 -1
- package/dist/a2a/task-store.js +216 -0
- package/dist/a2a/task-store.js.map +1 -1
- package/dist/a2a/types.d.ts +24 -0
- package/dist/a2a/types.d.ts.map +1 -1
- package/dist/a2a/types.js.map +1 -1
- package/dist/agent/production-agent.d.ts +1 -0
- package/dist/agent/production-agent.d.ts.map +1 -1
- package/dist/agent/production-agent.js +5 -2
- package/dist/agent/production-agent.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/collab/struct-routes.d.ts +1 -1
- package/dist/file-upload/actions/upload-image.d.ts +1 -1
- package/dist/mcp/builtin-tools.d.ts.map +1 -1
- package/dist/mcp/builtin-tools.js +22 -3
- package/dist/mcp/builtin-tools.js.map +1 -1
- package/dist/notifications/routes.d.ts +3 -3
- package/dist/resources/handlers.d.ts +2 -2
- package/dist/scripts/call-agent.d.ts +1 -1
- package/dist/scripts/call-agent.d.ts.map +1 -1
- package/dist/scripts/call-agent.js +19 -1
- package/dist/scripts/call-agent.js.map +1 -1
- package/dist/server/agent-chat-plugin.d.ts.map +1 -1
- package/dist/server/agent-chat-plugin.js +71 -2
- package/dist/server/agent-chat-plugin.js.map +1 -1
- package/dist/server/agent-engine-api-key-route.d.ts +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/dist/templates/workspace-core/.agents/skills/a2a-protocol/SKILL.md +25 -0
- 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
- package/src/templates/workspace-core/.agents/skills/a2a-protocol/SKILL.md +25 -0
|
@@ -1,21 +1,66 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { useT } from "@agent-native/core/client";
|
|
2
|
+
import { IconInfoCircle, IconMessage } from "@tabler/icons-react";
|
|
3
|
+
|
|
4
|
+
import { Button } from "@/components/ui/button";
|
|
5
|
+
import {
|
|
6
|
+
Tooltip,
|
|
7
|
+
TooltipContent,
|
|
8
|
+
TooltipTrigger,
|
|
9
|
+
} from "@/components/ui/tooltip";
|
|
10
|
+
import { cn } from "@/lib/utils";
|
|
2
11
|
|
|
3
12
|
/**
|
|
4
13
|
* Slim, non-blocking banner shown below the canvas when the current user only
|
|
5
14
|
* has viewer access to the design (Figma-style "you can't edit this" notice).
|
|
6
|
-
*
|
|
7
|
-
*
|
|
15
|
+
* Editing affordances are disabled elsewhere via `canEditDesign`; signed-in
|
|
16
|
+
* viewers get their one canvas action integrated into the same quiet notice.
|
|
8
17
|
*/
|
|
9
|
-
export function ReadOnlyDesignBanner(
|
|
18
|
+
export function ReadOnlyDesignBanner({
|
|
19
|
+
pinMode = false,
|
|
20
|
+
onCommentPin,
|
|
21
|
+
}: {
|
|
22
|
+
pinMode?: boolean;
|
|
23
|
+
onCommentPin?: () => void;
|
|
24
|
+
}) {
|
|
25
|
+
const t = useT();
|
|
26
|
+
const commentLabel = pinMode
|
|
27
|
+
? t("designEditor.stopPinningComments")
|
|
28
|
+
: t("designEditor.pinComment");
|
|
29
|
+
|
|
10
30
|
return (
|
|
11
|
-
<div
|
|
12
|
-
|
|
31
|
+
<div
|
|
32
|
+
data-read-only-design-banner
|
|
33
|
+
className="pointer-events-none absolute inset-x-0 bottom-0 z-[50] flex items-center justify-center px-3 pb-2"
|
|
34
|
+
>
|
|
35
|
+
<div className="flex max-w-full items-center gap-2 rounded-full border border-blue-500/30 bg-blue-500/10 py-1 pe-1 ps-3 text-xs text-blue-600 shadow-sm backdrop-blur-sm dark:text-blue-400">
|
|
13
36
|
<IconInfoCircle className="size-3.5 shrink-0" />
|
|
14
|
-
<span className="truncate">
|
|
37
|
+
<span className="min-w-0 truncate">
|
|
15
38
|
{
|
|
16
39
|
"You don't have access to edit this design" /* i18n-ignore Figma-style read-only notice */
|
|
17
40
|
}
|
|
18
41
|
</span>
|
|
42
|
+
{onCommentPin ? (
|
|
43
|
+
<Tooltip>
|
|
44
|
+
<TooltipTrigger asChild>
|
|
45
|
+
<Button
|
|
46
|
+
type="button"
|
|
47
|
+
variant="ghost"
|
|
48
|
+
size="icon"
|
|
49
|
+
className={cn(
|
|
50
|
+
"pointer-events-auto size-7 shrink-0 rounded-full text-blue-600 hover:bg-blue-500/15 hover:text-blue-700 dark:text-blue-400 dark:hover:text-blue-300",
|
|
51
|
+
pinMode &&
|
|
52
|
+
"bg-blue-500/20 text-blue-700 dark:bg-blue-400/20 dark:text-blue-300",
|
|
53
|
+
)}
|
|
54
|
+
aria-label={commentLabel}
|
|
55
|
+
aria-pressed={pinMode}
|
|
56
|
+
onClick={onCommentPin}
|
|
57
|
+
>
|
|
58
|
+
<IconMessage className="size-4" />
|
|
59
|
+
</Button>
|
|
60
|
+
</TooltipTrigger>
|
|
61
|
+
<TooltipContent side="top">{commentLabel}</TooltipContent>
|
|
62
|
+
</Tooltip>
|
|
63
|
+
) : null}
|
|
19
64
|
</div>
|
|
20
65
|
</div>
|
|
21
66
|
);
|
|
@@ -15,6 +15,9 @@ import { cn } from "@/lib/utils";
|
|
|
15
15
|
export interface ReviewCommentsPanelProps {
|
|
16
16
|
designId: string;
|
|
17
17
|
activeFileId?: string | null;
|
|
18
|
+
commentAnchor?: unknown | null;
|
|
19
|
+
commentMetadata?: Record<string, unknown>;
|
|
20
|
+
commentContextLabel?: string;
|
|
18
21
|
canComment: boolean;
|
|
19
22
|
/** Caller-derived editor capability for resolving threads. */
|
|
20
23
|
canResolve?: boolean;
|
|
@@ -30,9 +33,27 @@ export interface ReviewCommentsPanelProps {
|
|
|
30
33
|
className?: string;
|
|
31
34
|
}
|
|
32
35
|
|
|
36
|
+
type ReviewCommentsScope = "screen" | "all";
|
|
37
|
+
|
|
38
|
+
export function resolveReviewComposerTargetId({
|
|
39
|
+
scope,
|
|
40
|
+
activeFileId,
|
|
41
|
+
commentAnchor,
|
|
42
|
+
}: {
|
|
43
|
+
scope: ReviewCommentsScope;
|
|
44
|
+
activeFileId?: string | null;
|
|
45
|
+
commentAnchor?: unknown | null;
|
|
46
|
+
}): string | null | undefined {
|
|
47
|
+
if (commentAnchor != null) return activeFileId;
|
|
48
|
+
return scope === "screen" ? activeFileId : undefined;
|
|
49
|
+
}
|
|
50
|
+
|
|
33
51
|
export function ReviewCommentsPanel({
|
|
34
52
|
designId,
|
|
35
53
|
activeFileId,
|
|
54
|
+
commentAnchor,
|
|
55
|
+
commentMetadata,
|
|
56
|
+
commentContextLabel,
|
|
36
57
|
canComment,
|
|
37
58
|
canResolve,
|
|
38
59
|
canDeleteComment,
|
|
@@ -46,8 +67,13 @@ export function ReviewCommentsPanel({
|
|
|
46
67
|
className,
|
|
47
68
|
}: ReviewCommentsPanelProps) {
|
|
48
69
|
const t = useT();
|
|
49
|
-
const [scope, setScope] = useState<
|
|
70
|
+
const [scope, setScope] = useState<ReviewCommentsScope>("screen");
|
|
50
71
|
const targetId = scope === "screen" ? activeFileId : undefined;
|
|
72
|
+
const composerTargetId = resolveReviewComposerTargetId({
|
|
73
|
+
scope,
|
|
74
|
+
activeFileId,
|
|
75
|
+
commentAnchor,
|
|
76
|
+
});
|
|
51
77
|
|
|
52
78
|
return (
|
|
53
79
|
<div
|
|
@@ -87,6 +113,10 @@ export function ReviewCommentsPanel({
|
|
|
87
113
|
resourceType="design"
|
|
88
114
|
resourceId={designId}
|
|
89
115
|
targetId={targetId}
|
|
116
|
+
composerTargetId={composerTargetId}
|
|
117
|
+
composerAnchor={commentAnchor}
|
|
118
|
+
composerMetadata={commentMetadata}
|
|
119
|
+
composerContextLabel={commentContextLabel}
|
|
90
120
|
title={t("review.panelTitle")}
|
|
91
121
|
placeholder={t("review.placeholder")}
|
|
92
122
|
emptyState={t("review.emptyState")}
|
|
@@ -104,13 +134,15 @@ export function ReviewCommentsPanel({
|
|
|
104
134
|
variant="plain"
|
|
105
135
|
showComposer={canComment && showComposer}
|
|
106
136
|
canReply={canComment}
|
|
107
|
-
canResolve={canResolve ??
|
|
137
|
+
canResolve={canResolve ?? false}
|
|
108
138
|
canDeleteComment={canDeleteComment}
|
|
109
|
-
showComposerTargetPicker={
|
|
139
|
+
showComposerTargetPicker={
|
|
140
|
+
canComment && showComposer && canDispatchToAgent
|
|
141
|
+
}
|
|
110
142
|
composerCommentLabel={t("review.commentMode")}
|
|
111
143
|
composerAgentLabel={t("review.sendToAgent")}
|
|
112
144
|
onCommentCreated={(comment) => {
|
|
113
|
-
if (comment.resolutionTarget === "agent") {
|
|
145
|
+
if (canDispatchToAgent && comment.resolutionTarget === "agent") {
|
|
114
146
|
onDispatchCommentToAgent?.(comment);
|
|
115
147
|
}
|
|
116
148
|
}}
|
|
@@ -777,6 +777,7 @@ export function ReviewCanvasPins({
|
|
|
777
777
|
postDraft({ ...draftPin, resolutionTarget });
|
|
778
778
|
}}
|
|
779
779
|
resolutionTarget={draftPin.resolutionTarget}
|
|
780
|
+
showAgentAction={Boolean(onDispatchCommentToAgent)}
|
|
780
781
|
placement={getReviewPopoverPlacement(draftPinPosition.point)}
|
|
781
782
|
submitting={createComment.isPending}
|
|
782
783
|
/>
|
|
@@ -843,6 +844,7 @@ function DraftComposer({
|
|
|
843
844
|
onCancel,
|
|
844
845
|
onSubmit,
|
|
845
846
|
resolutionTarget,
|
|
847
|
+
showAgentAction,
|
|
846
848
|
placement,
|
|
847
849
|
submitting,
|
|
848
850
|
}: {
|
|
@@ -851,6 +853,7 @@ function DraftComposer({
|
|
|
851
853
|
onCancel: () => void;
|
|
852
854
|
onSubmit: (target: "agent" | "human") => void;
|
|
853
855
|
resolutionTarget: "agent" | "human";
|
|
856
|
+
showAgentAction: boolean;
|
|
854
857
|
placement: ReviewPopoverPlacement;
|
|
855
858
|
submitting: boolean;
|
|
856
859
|
}) {
|
|
@@ -886,7 +889,7 @@ function DraftComposer({
|
|
|
886
889
|
onChange={onChange}
|
|
887
890
|
onSubmit={onSubmit}
|
|
888
891
|
submittingTarget={submitting ? resolutionTarget : null}
|
|
889
|
-
showAgentAction
|
|
892
|
+
showAgentAction={showAgentAction}
|
|
890
893
|
placeholder={t("review.placeholder")}
|
|
891
894
|
commentLabel={t("review.commentMode")}
|
|
892
895
|
agentLabel={t("review.sendToAgent")}
|
|
@@ -12,6 +12,7 @@ const messages = {
|
|
|
12
12
|
signInToComment: "سجّل الدخول للتعليق",
|
|
13
13
|
panelTitle: "الملاحظات",
|
|
14
14
|
placeholder: "اترك ملاحظاتك…",
|
|
15
|
+
commentingOn: "التعليق على {{name}}",
|
|
15
16
|
emptyState: "لا توجد تعليقات مراجعة بعد.",
|
|
16
17
|
clickToPin: "انقر في أي مكان لتثبيت ملاحظة",
|
|
17
18
|
escToExit: "اضغط Esc للخروج",
|
|
@@ -12,6 +12,7 @@ const messages = {
|
|
|
12
12
|
signInToComment: "Zum Kommentieren anmelden",
|
|
13
13
|
panelTitle: "Feedback",
|
|
14
14
|
placeholder: "Feedback hinterlassen…",
|
|
15
|
+
commentingOn: "Kommentar zu {{name}}",
|
|
15
16
|
emptyState: "Noch keine Prüfkommentare.",
|
|
16
17
|
clickToPin: "Klicke an eine beliebige Stelle, um Feedback anzuheften",
|
|
17
18
|
escToExit: "Esc zum Beenden",
|
|
@@ -12,6 +12,7 @@ const messages = {
|
|
|
12
12
|
signInToComment: "Sign in to comment",
|
|
13
13
|
panelTitle: "Feedback",
|
|
14
14
|
placeholder: "Leave feedback…",
|
|
15
|
+
commentingOn: "Commenting on {{name}}",
|
|
15
16
|
emptyState: "No review comments yet.",
|
|
16
17
|
clickToPin: "Click anywhere to pin feedback",
|
|
17
18
|
escToExit: "Esc to exit",
|
|
@@ -12,6 +12,7 @@ const messages = {
|
|
|
12
12
|
signInToComment: "Inicia sesión para comentar",
|
|
13
13
|
panelTitle: "Opiniones",
|
|
14
14
|
placeholder: "Deja tus comentarios…",
|
|
15
|
+
commentingOn: "Comentando en {{name}}",
|
|
15
16
|
emptyState: "Aún no hay comentarios de revisión.",
|
|
16
17
|
clickToPin: "Haz clic en cualquier lugar para fijar un comentario",
|
|
17
18
|
escToExit: "Pulsa Esc para salir",
|
|
@@ -12,6 +12,7 @@ const messages = {
|
|
|
12
12
|
signInToComment: "Connectez-vous pour commenter",
|
|
13
13
|
panelTitle: "Retours",
|
|
14
14
|
placeholder: "Laissez un commentaire…",
|
|
15
|
+
commentingOn: "Commentaire sur {{name}}",
|
|
15
16
|
emptyState: "Aucun commentaire de révision pour le moment.",
|
|
16
17
|
clickToPin: "Cliquez n’importe où pour épingler un commentaire",
|
|
17
18
|
escToExit: "Appuyez sur Esc pour quitter",
|
|
@@ -12,6 +12,7 @@ const messages = {
|
|
|
12
12
|
signInToComment: "टिप्पणी करने के लिए साइन इन करें",
|
|
13
13
|
panelTitle: "प्रतिक्रिया",
|
|
14
14
|
placeholder: "अपनी प्रतिक्रिया दें…",
|
|
15
|
+
commentingOn: "{{name}} पर टिप्पणी",
|
|
15
16
|
emptyState: "अभी तक कोई समीक्षा टिप्पणी नहीं है।",
|
|
16
17
|
clickToPin: "प्रतिक्रिया पिन करने के लिए कहीं भी क्लिक करें",
|
|
17
18
|
escToExit: "बाहर निकलने के लिए Esc दबाएँ",
|
|
@@ -12,6 +12,7 @@ const messages = {
|
|
|
12
12
|
signInToComment: "Entre para comentar",
|
|
13
13
|
panelTitle: "Feedback",
|
|
14
14
|
placeholder: "Deixe seu feedback…",
|
|
15
|
+
commentingOn: "Comentando em {{name}}",
|
|
15
16
|
emptyState: "Ainda não há comentários de revisão.",
|
|
16
17
|
clickToPin: "Clique em qualquer lugar para fixar o feedback",
|
|
17
18
|
escToExit: "Pressione Esc para sair",
|
|
@@ -483,6 +483,14 @@ export function shouldClearBridgeSelectionOnEmptyMarquee(args: {
|
|
|
483
483
|
return args.resolvedCount === 0 && !args.additive;
|
|
484
484
|
}
|
|
485
485
|
|
|
486
|
+
/** Clear element context only when a selected review thread changes screens. */
|
|
487
|
+
export function shouldClearSelectionForReviewThreadTarget(args: {
|
|
488
|
+
activeFileId?: string | null;
|
|
489
|
+
targetId?: string | null;
|
|
490
|
+
}): boolean {
|
|
491
|
+
return Boolean(args.targetId && args.targetId !== args.activeFileId);
|
|
492
|
+
}
|
|
493
|
+
|
|
486
494
|
/**
|
|
487
495
|
* PICK-RACE: MultiScreenCanvas's `onPick` prop is `(id: string) => void` — no
|
|
488
496
|
* modifier/event info — even though a shift-click there already toggled a
|
|
@@ -102,6 +102,17 @@ export function shouldAutoEnableDrawOverlay(args: {
|
|
|
102
102
|
);
|
|
103
103
|
}
|
|
104
104
|
|
|
105
|
+
export type DesignBottomToolbarMode = "editor" | "commenter" | "hidden";
|
|
106
|
+
|
|
107
|
+
export function getDesignBottomToolbarMode(args: {
|
|
108
|
+
isSignedIn: boolean;
|
|
109
|
+
canEditDesign: boolean;
|
|
110
|
+
hasActiveFile: boolean;
|
|
111
|
+
}): DesignBottomToolbarMode {
|
|
112
|
+
if (!args.isSignedIn || !args.hasActiveFile) return "hidden";
|
|
113
|
+
return args.canEditDesign ? "editor" : "commenter";
|
|
114
|
+
}
|
|
115
|
+
|
|
105
116
|
export function getSingleScreenCreationTool(args: {
|
|
106
117
|
activeTool: DesignTool;
|
|
107
118
|
viewMode: "single" | "overview";
|
|
@@ -14,6 +14,54 @@ export interface ResolvedReviewAnchor {
|
|
|
14
14
|
source: "node" | "point";
|
|
15
15
|
}
|
|
16
16
|
|
|
17
|
+
export function createElementReviewAnchor(input: {
|
|
18
|
+
nodeId?: string | null;
|
|
19
|
+
rect?: { x: number; y: number; width: number; height: number } | null;
|
|
20
|
+
viewportWidth?: number | null;
|
|
21
|
+
viewportHeight?: number | null;
|
|
22
|
+
}): DesignReviewAnchor | null {
|
|
23
|
+
const nodeId = input.nodeId?.trim() ?? "";
|
|
24
|
+
const rect = input.rect;
|
|
25
|
+
const hasRect = Boolean(
|
|
26
|
+
rect &&
|
|
27
|
+
Number.isFinite(rect.x) &&
|
|
28
|
+
Number.isFinite(rect.y) &&
|
|
29
|
+
Number.isFinite(rect.width) &&
|
|
30
|
+
rect.width > 0 &&
|
|
31
|
+
Number.isFinite(rect.height) &&
|
|
32
|
+
rect.height > 0 &&
|
|
33
|
+
typeof input.viewportWidth === "number" &&
|
|
34
|
+
Number.isFinite(input.viewportWidth) &&
|
|
35
|
+
input.viewportWidth > 0 &&
|
|
36
|
+
typeof input.viewportHeight === "number" &&
|
|
37
|
+
Number.isFinite(input.viewportHeight) &&
|
|
38
|
+
input.viewportHeight > 0,
|
|
39
|
+
);
|
|
40
|
+
if (!nodeId && !hasRect) return null;
|
|
41
|
+
|
|
42
|
+
const point = hasRect
|
|
43
|
+
? {
|
|
44
|
+
xPct:
|
|
45
|
+
finitePercentage(
|
|
46
|
+
(((rect?.x ?? 0) + (rect?.width ?? 0) / 2) /
|
|
47
|
+
(input.viewportWidth as number)) *
|
|
48
|
+
100,
|
|
49
|
+
) ?? 50,
|
|
50
|
+
yPct:
|
|
51
|
+
finitePercentage(
|
|
52
|
+
(((rect?.y ?? 0) + (rect?.height ?? 0) / 2) /
|
|
53
|
+
(input.viewportHeight as number)) *
|
|
54
|
+
100,
|
|
55
|
+
) ?? 50,
|
|
56
|
+
}
|
|
57
|
+
: { xPct: 50, yPct: 50 };
|
|
58
|
+
|
|
59
|
+
return {
|
|
60
|
+
...(nodeId ? { nodeId } : {}),
|
|
61
|
+
point,
|
|
62
|
+
};
|
|
63
|
+
}
|
|
64
|
+
|
|
17
65
|
function finitePercentage(value: unknown): number | null {
|
|
18
66
|
if (typeof value !== "number" || !Number.isFinite(value)) return null;
|
|
19
67
|
return Math.min(100, Math.max(0, value));
|
|
@@ -121,6 +121,23 @@ const drafts = await listAppState("compose-");
|
|
|
121
121
|
|
|
122
122
|
The `send-email` action accepts an optional `attachments` array. Each entry must reference a file that was previously uploaded via the media-upload endpoint (`/api/media/upload`). Pass the server-side `filename` (the key returned by the upload endpoint, e.g. `abc123.pdf`), and optionally `originalName` (display name for the recipient) and `mimeType`. The attachment plumbing resolves the file from `data/uploads/` or from the configured file-storage URL recorded by the upload endpoint, then includes it as a MIME multipart attachment in the outgoing Gmail message. Do not store or paste attachment bytes, base64, or `data:` URLs in draft state/settings; files are never sent speculatively — only attach what the user has explicitly provided and confirmed.
|
|
123
123
|
|
|
124
|
+
### Local files from an MCP host
|
|
125
|
+
|
|
126
|
+
A hosted Mail app cannot read a path on the MCP host's local filesystem. Use
|
|
127
|
+
`create-attachment-upload` with the file's display name. It returns a
|
|
128
|
+
five-minute, owner-bound `uploadUrl`, a `PUT` method, and the attachment handle
|
|
129
|
+
Mail expects. From the local host, upload the raw bytes directly:
|
|
130
|
+
|
|
131
|
+
```bash
|
|
132
|
+
curl --fail-with-body --request PUT --header '<Authorization header>' --data-binary @/absolute/path/to/report.pdf '<uploadUrl>'
|
|
133
|
+
```
|
|
134
|
+
|
|
135
|
+
Use the response's `attachment` object in the draft/send request. The upload
|
|
136
|
+
Authorization header is a short-lived bearer credential: do not log, persist,
|
|
137
|
+
reuse, or share it. Creating or consuming it does not send mail. Keep `send-email` behind its
|
|
138
|
+
normal explicit-intent and human-approval gate; for drafting, pass the handle
|
|
139
|
+
through `ask_app` or open the returned compose deep link.
|
|
140
|
+
|
|
124
141
|
Example:
|
|
125
142
|
```json
|
|
126
143
|
{
|
|
@@ -60,8 +60,9 @@ needed.
|
|
|
60
60
|
- Never send mail unless the user explicitly asks to send. Draft or queue
|
|
61
61
|
review by default. `send-email` has `needsApproval: true` — it is the
|
|
62
62
|
canonical, intentionally rare use of the human-in-the-loop gate in this
|
|
63
|
-
framework
|
|
64
|
-
|
|
63
|
+
framework. An authenticated A2A caller may carry the user's exact chat
|
|
64
|
+
authorization for one matching send; otherwise the loop pauses for approval.
|
|
65
|
+
Drafting and queueing are unaffected.
|
|
65
66
|
- When drafting, first read `get-mail-settings` for signature and writing
|
|
66
67
|
style. Use `signature` exactly when present — draft-writing paths that build
|
|
67
68
|
a `compose-*` entry (`manage-draft`, `open-queued-draft`) call
|
|
@@ -93,23 +94,24 @@ needed.
|
|
|
93
94
|
|
|
94
95
|
## Action Map
|
|
95
96
|
|
|
96
|
-
| Action | Purpose
|
|
97
|
-
| -------------------------------------------------------------------------------------------------------------------------------------- |
|
|
98
|
-
| `search-emails` / `list-emails` | Query across Gmail or local-fallback data by view/query.
|
|
99
|
-
| `get-email` / `get-thread` | Full body/metadata for one message or thread.
|
|
100
|
-
| `find-contact` | Resolve a name/partial address to a real email.
|
|
101
|
-
| `get-hubspot-contact` | CRM contact + deals + tickets by email (HubSpot only).
|
|
102
|
-
| `
|
|
103
|
-
| `
|
|
104
|
-
| `
|
|
105
|
-
| `
|
|
106
|
-
| `
|
|
107
|
-
| `manage-
|
|
108
|
-
| `
|
|
109
|
-
| `
|
|
110
|
-
| `
|
|
111
|
-
| `
|
|
112
|
-
| `
|
|
97
|
+
| Action | Purpose |
|
|
98
|
+
| -------------------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------- |
|
|
99
|
+
| `search-emails` / `list-emails` | Query across Gmail or local-fallback data by view/query. |
|
|
100
|
+
| `get-email` / `get-thread` | Full body/metadata for one message or thread. |
|
|
101
|
+
| `find-contact` | Resolve a name/partial address to a real email. |
|
|
102
|
+
| `get-hubspot-contact` | CRM contact + deals + tickets by email (HubSpot only). |
|
|
103
|
+
| `create-attachment-upload` | Mint a five-minute, owner-bound raw-byte upload URL for one local attachment. |
|
|
104
|
+
| `manage-draft` | Create/update/delete a `compose-{id}` draft (signature-aware). |
|
|
105
|
+
| `send-email` | Real send. `needsApproval: true`; exact authenticated chat grants run once, otherwise it pauses for approval. |
|
|
106
|
+
| `queue-email-draft` / `list-queued-drafts` / `update-queued-draft` / `open-queued-draft` / `send-queued-drafts` | Teammate/Slack draft-review workflow — see `draft-queue`. |
|
|
107
|
+
| `mark-read` / `mark-thread-read` / `star-email` / `archive-email` / `unarchive-email` / `trash-email` / `untrash-email` / `move-email` | Per-message or per-thread state changes; most call `refresh-list` internally. |
|
|
108
|
+
| `manage-gmail-filters` | Provider-native Gmail filters (create/replace/delete). |
|
|
109
|
+
| `manage-automations` / `trigger-automations` | Natural-language inbox automation rules. |
|
|
110
|
+
| `respond-calendar-invite` | Accept/decline/tentative an invite found in Mail. |
|
|
111
|
+
| `get-mail-settings` / `update-mail-settings` / `import-gmail-signature` | Signature and writing-style settings. |
|
|
112
|
+
| `manage-snippets` | List/create/update/delete saved reply snippets insertable from the compose slash menu. |
|
|
113
|
+
| `get-tracking` | Open/click stats for a previously sent, tracked message. |
|
|
114
|
+
| `provider-api-catalog` / `provider-api-docs` / `provider-api-request` | Raw Gmail, Calendar, or HubSpot API calls beyond the canned actions. |
|
|
113
115
|
|
|
114
116
|
## Application State
|
|
115
117
|
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
import { defineAction } from "@agent-native/core/action";
|
|
2
|
+
import {
|
|
3
|
+
getAppProductionUrl,
|
|
4
|
+
getRequestUserEmail,
|
|
5
|
+
withConfiguredAppBasePath,
|
|
6
|
+
} from "@agent-native/core/server";
|
|
7
|
+
import { z } from "zod";
|
|
8
|
+
|
|
9
|
+
import { createAttachmentUploadTicket } from "../server/lib/attachment-upload-ticket.js";
|
|
10
|
+
|
|
11
|
+
const originalNameSchema = z
|
|
12
|
+
.string()
|
|
13
|
+
.trim()
|
|
14
|
+
.min(1)
|
|
15
|
+
.max(255)
|
|
16
|
+
.refine(
|
|
17
|
+
(value) => !/[\\/\0\r\n]/.test(value),
|
|
18
|
+
"Filename must not contain path separators or control characters",
|
|
19
|
+
);
|
|
20
|
+
|
|
21
|
+
export default defineAction({
|
|
22
|
+
description:
|
|
23
|
+
"Create a short-lived authenticated Mail upload URL for one local attachment. Upload the file bytes with HTTP PUT, then pass the returned attachment handle to ask_app so Mail can include it in a draft or approved send. Creating the URL does not send email.",
|
|
24
|
+
schema: z.object({
|
|
25
|
+
originalName: originalNameSchema.describe(
|
|
26
|
+
"Display filename, including its extension (for example, report.png)",
|
|
27
|
+
),
|
|
28
|
+
}),
|
|
29
|
+
run: async ({ originalName }) => {
|
|
30
|
+
const ownerEmail = getRequestUserEmail();
|
|
31
|
+
if (!ownerEmail) throw new Error("Authentication required");
|
|
32
|
+
const ticket = await createAttachmentUploadTicket(ownerEmail, originalName);
|
|
33
|
+
const appUrl = withConfiguredAppBasePath(getAppProductionUrl());
|
|
34
|
+
const uploadUrl = `${appUrl}/api/media/attachment-upload/${encodeURIComponent(ticket.uploadId)}`;
|
|
35
|
+
return {
|
|
36
|
+
method: "PUT" as const,
|
|
37
|
+
uploadUrl,
|
|
38
|
+
headers: { Authorization: `Bearer ${ticket.token}` },
|
|
39
|
+
expiresAt: new Date(ticket.expiresAt).toISOString(),
|
|
40
|
+
maxBytes: 10 * 1024 * 1024,
|
|
41
|
+
attachment: {
|
|
42
|
+
filename: ticket.filename,
|
|
43
|
+
originalName: ticket.originalName,
|
|
44
|
+
mimeType: ticket.mimeType,
|
|
45
|
+
},
|
|
46
|
+
next: "PUT the raw local file bytes to uploadUrl with the returned Authorization header before passing attachment to ask_app. Do not paste base64 into chat or action arguments.",
|
|
47
|
+
};
|
|
48
|
+
},
|
|
49
|
+
});
|