@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,5 +1,4 @@
|
|
|
1
1
|
import {
|
|
2
|
-
BUILDER_CMS_SAFE_WRITE_MODEL,
|
|
3
2
|
type ContentDatabaseSourceCapabilities,
|
|
4
3
|
type ContentDatabaseSourcePushMode,
|
|
5
4
|
type ContentDatabaseSourceWriteMode,
|
|
@@ -126,6 +125,32 @@ function pushModeForTier(
|
|
|
126
125
|
return "none";
|
|
127
126
|
}
|
|
128
127
|
|
|
128
|
+
function writeModeCopy(writeMode: ContentDatabaseSourceWriteMode) {
|
|
129
|
+
if (writeMode === "publish_updates") {
|
|
130
|
+
return {
|
|
131
|
+
pushModeLabel: "Publish updates",
|
|
132
|
+
pushModeDescription:
|
|
133
|
+
"Review, update, and publish existing Builder entries. New entries are never created by this mode.",
|
|
134
|
+
notes:
|
|
135
|
+
"Builder CMS source with reviewed update-in-place publication enabled for existing entries.",
|
|
136
|
+
};
|
|
137
|
+
}
|
|
138
|
+
if (writeMode === "stage_only") {
|
|
139
|
+
return {
|
|
140
|
+
pushModeLabel: "Stage only",
|
|
141
|
+
pushModeDescription:
|
|
142
|
+
"Prepare and review local revisions without writing to Builder.",
|
|
143
|
+
notes:
|
|
144
|
+
"Builder CMS source with local review staging enabled and remote writes disabled.",
|
|
145
|
+
};
|
|
146
|
+
}
|
|
147
|
+
return {
|
|
148
|
+
pushModeLabel: "Read only",
|
|
149
|
+
pushModeDescription: "Refresh and review Builder content without writing.",
|
|
150
|
+
notes: "Builder CMS source with remote writes disabled.",
|
|
151
|
+
};
|
|
152
|
+
}
|
|
153
|
+
|
|
129
154
|
export function builderCmsWriteSettingsFromJson(args: {
|
|
130
155
|
capabilitiesJson: string | null | undefined;
|
|
131
156
|
metadataJson: string | null | undefined;
|
|
@@ -178,11 +203,6 @@ export function buildBuilderCmsWriteModeJson(
|
|
|
178
203
|
"Live writes can only be enabled for Builder CMS sources.",
|
|
179
204
|
);
|
|
180
205
|
}
|
|
181
|
-
if (args.sourceTable !== BUILDER_CMS_SAFE_WRITE_MODEL) {
|
|
182
|
-
throw new Error(
|
|
183
|
-
`Live Builder writes are only allowed for ${BUILDER_CMS_SAFE_WRITE_MODEL}.`,
|
|
184
|
-
);
|
|
185
|
-
}
|
|
186
206
|
}
|
|
187
207
|
|
|
188
208
|
if (
|
|
@@ -199,6 +219,7 @@ export function buildBuilderCmsWriteModeJson(
|
|
|
199
219
|
};
|
|
200
220
|
const nextMetadata: Record<string, unknown> = {
|
|
201
221
|
...metadata,
|
|
222
|
+
...writeModeCopy(writeMode),
|
|
202
223
|
writeMode,
|
|
203
224
|
allowPublicationTransitions,
|
|
204
225
|
allowedWriteModes,
|
|
@@ -226,7 +247,6 @@ export function mergeBuilderCmsWriteSettingsIntoJson(args: {
|
|
|
226
247
|
});
|
|
227
248
|
if (
|
|
228
249
|
currentSettings.liveWritesEnabled !== true ||
|
|
229
|
-
args.sourceTable !== BUILDER_CMS_SAFE_WRITE_MODEL ||
|
|
230
250
|
currentSettings.writeMode === "read_only"
|
|
231
251
|
) {
|
|
232
252
|
return {
|
|
@@ -0,0 +1,124 @@
|
|
|
1
|
+
import { createHash } from "node:crypto";
|
|
2
|
+
|
|
3
|
+
import { and, eq } from "drizzle-orm";
|
|
4
|
+
|
|
5
|
+
import { getDb, schema } from "../server/db/index.js";
|
|
6
|
+
import { builderExecutionHasResponseEvidence } from "./_builder-source-execution-preservation.js";
|
|
7
|
+
|
|
8
|
+
function claimId(sourceId: string, idempotencyKey: string) {
|
|
9
|
+
return createHash("sha256")
|
|
10
|
+
.update(`${sourceId}\u0000${idempotencyKey}`)
|
|
11
|
+
.digest("hex");
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
function evidenceRank(row: {
|
|
15
|
+
state: string;
|
|
16
|
+
payloadJson: string;
|
|
17
|
+
updatedAt: string;
|
|
18
|
+
id: string;
|
|
19
|
+
}) {
|
|
20
|
+
const stateRank =
|
|
21
|
+
row.state === "succeeded"
|
|
22
|
+
? 0
|
|
23
|
+
: row.state === "response_received"
|
|
24
|
+
? 1
|
|
25
|
+
: row.state === "reconciliation_required"
|
|
26
|
+
? 2
|
|
27
|
+
: builderExecutionHasResponseEvidence(row.payloadJson)
|
|
28
|
+
? 3
|
|
29
|
+
: row.state === "running"
|
|
30
|
+
? 4
|
|
31
|
+
: 5;
|
|
32
|
+
return { stateRank, updatedAt: row.updatedAt, id: row.id };
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
function canonicalExecution<
|
|
36
|
+
T extends {
|
|
37
|
+
state: string;
|
|
38
|
+
payloadJson: string;
|
|
39
|
+
updatedAt: string;
|
|
40
|
+
id: string;
|
|
41
|
+
},
|
|
42
|
+
>(rows: T[]) {
|
|
43
|
+
return [...rows].sort((left, right) => {
|
|
44
|
+
const a = evidenceRank(left);
|
|
45
|
+
const b = evidenceRank(right);
|
|
46
|
+
return (
|
|
47
|
+
a.stateRank - b.stateRank ||
|
|
48
|
+
b.updatedAt.localeCompare(a.updatedAt) ||
|
|
49
|
+
a.id.localeCompare(b.id)
|
|
50
|
+
);
|
|
51
|
+
})[0];
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
export async function claimBuilderSourceExecutionGate(args: {
|
|
55
|
+
ownerEmail: string;
|
|
56
|
+
sourceId: string;
|
|
57
|
+
idempotencyKey: string;
|
|
58
|
+
now: string;
|
|
59
|
+
}) {
|
|
60
|
+
const db = getDb();
|
|
61
|
+
const whereKey = and(
|
|
62
|
+
eq(schema.contentDatabaseSourceExecutionClaims.ownerEmail, args.ownerEmail),
|
|
63
|
+
eq(schema.contentDatabaseSourceExecutionClaims.sourceId, args.sourceId),
|
|
64
|
+
eq(
|
|
65
|
+
schema.contentDatabaseSourceExecutionClaims.idempotencyKey,
|
|
66
|
+
args.idempotencyKey,
|
|
67
|
+
),
|
|
68
|
+
);
|
|
69
|
+
const [existingClaim] = await db
|
|
70
|
+
.select()
|
|
71
|
+
.from(schema.contentDatabaseSourceExecutionClaims)
|
|
72
|
+
.where(whereKey)
|
|
73
|
+
.limit(1);
|
|
74
|
+
if (existingClaim) return existingClaim.executionId;
|
|
75
|
+
|
|
76
|
+
const candidates = await db
|
|
77
|
+
.select()
|
|
78
|
+
.from(schema.contentDatabaseSourceExecutions)
|
|
79
|
+
.where(
|
|
80
|
+
and(
|
|
81
|
+
eq(schema.contentDatabaseSourceExecutions.ownerEmail, args.ownerEmail),
|
|
82
|
+
eq(schema.contentDatabaseSourceExecutions.sourceId, args.sourceId),
|
|
83
|
+
eq(
|
|
84
|
+
schema.contentDatabaseSourceExecutions.idempotencyKey,
|
|
85
|
+
args.idempotencyKey,
|
|
86
|
+
),
|
|
87
|
+
),
|
|
88
|
+
);
|
|
89
|
+
const canonical = canonicalExecution(candidates);
|
|
90
|
+
const executionId = canonical?.id ?? crypto.randomUUID();
|
|
91
|
+
|
|
92
|
+
try {
|
|
93
|
+
await db.insert(schema.contentDatabaseSourceExecutionClaims).values({
|
|
94
|
+
id: claimId(args.sourceId, args.idempotencyKey),
|
|
95
|
+
ownerEmail: args.ownerEmail,
|
|
96
|
+
sourceId: args.sourceId,
|
|
97
|
+
idempotencyKey: args.idempotencyKey,
|
|
98
|
+
executionId,
|
|
99
|
+
createdAt: args.now,
|
|
100
|
+
});
|
|
101
|
+
} catch (error) {
|
|
102
|
+
const [winner] = await db
|
|
103
|
+
.select()
|
|
104
|
+
.from(schema.contentDatabaseSourceExecutionClaims)
|
|
105
|
+
.where(whereKey)
|
|
106
|
+
.limit(1);
|
|
107
|
+
if (!winner) throw error;
|
|
108
|
+
return winner.executionId;
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
if (candidates.length > 1 && canonical) {
|
|
112
|
+
await db
|
|
113
|
+
.update(schema.contentDatabaseSourceExecutions)
|
|
114
|
+
.set({
|
|
115
|
+
state: "reconciliation_required",
|
|
116
|
+
summary: "Duplicate execution gates require reconciliation.",
|
|
117
|
+
lastError:
|
|
118
|
+
"Multiple execution rows exist for this idempotency key. Evidence was preserved; do not retry.",
|
|
119
|
+
updatedAt: args.now,
|
|
120
|
+
})
|
|
121
|
+
.where(eq(schema.contentDatabaseSourceExecutions.id, canonical.id));
|
|
122
|
+
}
|
|
123
|
+
return executionId;
|
|
124
|
+
}
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
export function builderExecutionHasResponseEvidence(payloadJson: string) {
|
|
2
|
+
try {
|
|
3
|
+
const payload = JSON.parse(payloadJson) as Record<string, unknown>;
|
|
4
|
+
return Boolean(payload.response && typeof payload.response === "object");
|
|
5
|
+
} catch {
|
|
6
|
+
return false;
|
|
7
|
+
}
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
export function shouldPreserveBuilderExecution(args: {
|
|
11
|
+
state: string;
|
|
12
|
+
payloadJson: string;
|
|
13
|
+
}) {
|
|
14
|
+
return (
|
|
15
|
+
args.state === "running" ||
|
|
16
|
+
args.state === "response_received" ||
|
|
17
|
+
args.state === "reconciliation_required" ||
|
|
18
|
+
args.state === "succeeded" ||
|
|
19
|
+
builderExecutionHasResponseEvidence(args.payloadJson)
|
|
20
|
+
);
|
|
21
|
+
}
|
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
import type { BuilderActionTiming } from "../shared/api.js";
|
|
2
|
+
|
|
3
|
+
type Clock = () => number;
|
|
4
|
+
|
|
5
|
+
function defaultClock() {
|
|
6
|
+
return performance.now();
|
|
7
|
+
}
|
|
8
|
+
|
|
9
|
+
export function createBuilderSourceTiming(
|
|
10
|
+
action: string,
|
|
11
|
+
clock: Clock = defaultClock,
|
|
12
|
+
) {
|
|
13
|
+
const actionStartedAt = clock();
|
|
14
|
+
const timings: BuilderActionTiming[] = [];
|
|
15
|
+
|
|
16
|
+
function record(name: string, startedAt: number) {
|
|
17
|
+
const durationMs = Math.max(0, clock() - startedAt);
|
|
18
|
+
timings.push({ name, durationMs });
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
async function measure<T>(name: string, operation: () => Promise<T>) {
|
|
22
|
+
const startedAt = clock();
|
|
23
|
+
try {
|
|
24
|
+
return await operation();
|
|
25
|
+
} finally {
|
|
26
|
+
record(name, startedAt);
|
|
27
|
+
}
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
function ensure(name: string) {
|
|
31
|
+
if (!timings.some((timing) => timing.name === name)) {
|
|
32
|
+
timings.push({ name, durationMs: 0 });
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
function add(name: string, durationMs: number) {
|
|
37
|
+
const safeDurationMs = Math.max(0, durationMs);
|
|
38
|
+
timings.push({ name, durationMs: safeDurationMs });
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
function finish() {
|
|
42
|
+
if (!timings.some((timing) => timing.name === "total")) {
|
|
43
|
+
record("total", actionStartedAt);
|
|
44
|
+
}
|
|
45
|
+
return timings.map((timing) => ({ ...timing }));
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
function log(outcome: "succeeded" | "failed") {
|
|
49
|
+
console.info("builder_source_action_timing", {
|
|
50
|
+
action,
|
|
51
|
+
outcome,
|
|
52
|
+
timings: finish(),
|
|
53
|
+
});
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
return { start: clock, record, measure, add, ensure, finish, log };
|
|
57
|
+
}
|