@agent-native/core 0.181.0 → 0.181.1-nightly-20260916144018
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/templates/clips/app/components/player/create-account-dialog.tsx +2 -1
- package/corpus/templates/clips/changelog/2026-09-15-google-sign-up-now-opens-reliably-in-embedded-browsers.md +6 -0
- package/corpus/templates/content/actions/resolve-preview-document-draft.ts +320 -60
- package/corpus/templates/content/app/components/editor/DocumentBlockFields.tsx +3 -1
- package/corpus/templates/content/app/components/editor/DocumentEditor.tsx +349 -104
- package/corpus/templates/content/app/components/editor/DocumentReconcileRecovery.tsx +109 -0
- package/corpus/templates/content/app/components/editor/PageDraftRecovery.tsx +31 -153
- package/corpus/templates/content/app/components/editor/RecoveryComparison.tsx +230 -0
- package/corpus/templates/content/app/components/editor/VisualEditor.tsx +46 -19
- package/corpus/templates/content/app/components/editor/editor-draft-save.ts +13 -0
- package/corpus/templates/content/app/components/editor/useDocumentReconcileRecovery.ts +248 -0
- package/corpus/templates/content/app/components/sidebar/NotionButton.tsx +2 -1
- package/corpus/templates/content/app/i18n-data.ts +13 -0
- package/corpus/templates/content/changelog/2026-09-15-oauth-connections-now-open-reliably-in-embedded-browsers.md +6 -0
- package/corpus/templates/content/docs/solutions/2026-09-02-content-suggested-edits-parity-shape.md +84 -2
- package/corpus/templates/design/.generated/bridge/editor-chrome.generated.ts +27 -7
- package/corpus/templates/design/app/components/design/DesignCanvas.tsx +45 -15
- package/corpus/templates/design/app/components/design/bridge/editor-chrome.bridge.ts +35 -8
- package/corpus/templates/design/app/components/design/design-canvas/element-payload.ts +14 -0
- package/corpus/templates/design/app/pages/DesignEditor.tsx +18 -5
- package/corpus/templates/design/app/pages/design-editor/commands/record-pending-live-structure-edit.ts +9 -4
- package/corpus/templates/design/app/pages/design-editor/commands/screen-visual-structure-change.ts +3 -0
- package/corpus/templates/design/app/pages/design-editor/commands/start-sidebar-resize.ts +7 -2
- package/corpus/templates/design/app/pages/design-editor/commands/visual-structure-change.ts +2 -0
- package/corpus/templates/design/app/pages/design-editor/pending-edits.ts +4 -0
- package/corpus/templates/design/app/pages/design-editor/pending-structure-verification.ts +197 -147
- package/corpus/templates/design/changelog/2026-09-16-design-editor-agent-chat-uses-shared-conversation-tabs-and-s.md +6 -0
- package/corpus/templates/design/changelog/2026-09-16-visual-edits-stay-applied-after-replacements.md +5 -0
- package/corpus/templates/mail/app/components/GoogleConnectBanner.tsx +2 -1
- package/corpus/templates/mail/changelog/2026-09-15-google-connections-now-open-reliably-in-embedded-browsers.md +6 -0
- package/dist/client/AgentPanel.d.ts +1 -1
- package/dist/client/AgentPanel.js +4 -4
- package/dist/client/auth/AuthPage.js +6 -1
- package/dist/client/oauth-popup.d.ts +7 -0
- package/dist/client/oauth-popup.js +14 -0
- package/dist/client/ocean/OceanBackground.d.ts +3 -1
- package/dist/client/ocean/OceanBackground.js +4 -3
- package/dist/client/resources/mcp-integration-catalog.js +7 -3
- package/dist/client/settings/useBuilderStatus.js +4 -3
- package/dist/collab/routes.d.ts +1 -1
- package/dist/collab/struct-routes.d.ts +1 -1
- package/dist/file-upload/actions/upload-image.d.ts +2 -2
- package/dist/mcp/screen-memory-stdio.d.ts +7 -7
- package/dist/notifications/routes.d.ts +3 -3
- package/dist/observability/routes.d.ts +3 -3
- package/dist/org/app-roles.d.ts +8 -0
- package/dist/org/app-roles.js +7 -0
- package/dist/org/index.d.ts +1 -1
- package/dist/org/index.js +1 -1
- package/dist/provider-api/actions/custom-provider-registration.d.ts +4 -4
- package/dist/secrets/routes.d.ts +6 -6
- package/dist/server/agent-engine-api-key-route.d.ts +1 -1
- package/dist/server/auth.js +3 -0
- package/dist/server/core-routes-plugin.d.ts +3 -0
- package/dist/server/core-routes-plugin.js +17 -0
- package/dist/server/realtime-token.d.ts +1 -1
- package/package.json +5 -4
package/corpus/README.md
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { trackEvent } from "@agent-native/core/client/analytics";
|
|
2
2
|
import { appPath } from "@agent-native/core/client/api-path";
|
|
3
3
|
import { useT } from "@agent-native/core/client/i18n";
|
|
4
|
+
import { openOAuthPopup } from "@agent-native/core/client/oauth-popup";
|
|
4
5
|
import { buildSignInReturnHref } from "@agent-native/core/client/ui";
|
|
5
6
|
import { isQaTestEmail } from "@agent-native/core/shared";
|
|
6
7
|
import { resolveNativeAuthCopy } from "@agent-native/core/shared/auth-copy";
|
|
@@ -177,7 +178,7 @@ export function AccountGateDialog({
|
|
|
177
178
|
|
|
178
179
|
const startGoogleSignup = async () => {
|
|
179
180
|
if (googleBusy || submitting) return;
|
|
180
|
-
const popup =
|
|
181
|
+
const popup = openOAuthPopup({ features: "width=640,height=760" });
|
|
181
182
|
if (!popup) {
|
|
182
183
|
setErrorMessage(copy.failedToConnect);
|
|
183
184
|
return;
|
|
@@ -23,7 +23,10 @@ const exactDraft = {
|
|
|
23
23
|
|
|
24
24
|
const durableClaimPayload = z.object({
|
|
25
25
|
choice: z.enum(["keep_mine", "use_saved", "save_separately"]),
|
|
26
|
-
status: z.enum(["claimed", "resolved"]),
|
|
26
|
+
status: z.enum(["claimed", "processing", "resolved"]),
|
|
27
|
+
expectedDocumentUpdatedAt: z.string().optional(),
|
|
28
|
+
processingToken: z.string().optional(),
|
|
29
|
+
processingStartedAt: z.string().optional(),
|
|
27
30
|
draftId: z.string().min(1),
|
|
28
31
|
baseDocumentUpdatedAt: z.string().nullable(),
|
|
29
32
|
loadedContentWasEmpty: z.number().int(),
|
|
@@ -78,8 +81,16 @@ export default defineAction({
|
|
|
78
81
|
...exactDraft,
|
|
79
82
|
expectedDocumentUpdatedAt: z.string().min(1),
|
|
80
83
|
}),
|
|
81
|
-
z.object({
|
|
82
|
-
|
|
84
|
+
z.object({
|
|
85
|
+
choice: z.literal("use_saved"),
|
|
86
|
+
...exactDraft,
|
|
87
|
+
expectedDocumentUpdatedAt: z.string().min(1),
|
|
88
|
+
}),
|
|
89
|
+
z.object({
|
|
90
|
+
choice: z.literal("save_separately"),
|
|
91
|
+
...exactDraft,
|
|
92
|
+
expectedDocumentUpdatedAt: z.string().min(1),
|
|
93
|
+
}),
|
|
83
94
|
]),
|
|
84
95
|
run: async (args, ctx) => {
|
|
85
96
|
const userEmail = getRequestUserEmail();
|
|
@@ -101,6 +112,7 @@ export default defineAction({
|
|
|
101
112
|
const claimId = `draft-claim-${recoveryId.slice("recovery-".length)}`;
|
|
102
113
|
const claimDocumentId =
|
|
103
114
|
ownerEmail === userEmail ? args.documentId : claimId;
|
|
115
|
+
const processingToken = crypto.randomUUID();
|
|
104
116
|
const draftFilter = and(
|
|
105
117
|
eq(schema.documentPreviewDrafts.ownerEmail, userEmail),
|
|
106
118
|
eq(schema.documentPreviewDrafts.orgId, orgId),
|
|
@@ -143,23 +155,68 @@ export default defineAction({
|
|
|
143
155
|
if (payload.choice !== args.choice) {
|
|
144
156
|
conflict("This draft was already resolved with another choice.");
|
|
145
157
|
}
|
|
158
|
+
if (payload.status === "resolved") {
|
|
159
|
+
return { status: "resolved" as const };
|
|
160
|
+
}
|
|
161
|
+
const [currentDocument] = await tx
|
|
162
|
+
.select()
|
|
163
|
+
.from(schema.documents)
|
|
164
|
+
.where(eq(schema.documents.id, args.documentId))
|
|
165
|
+
.for("update")
|
|
166
|
+
.limit(1);
|
|
167
|
+
const expectedUpdatedAt =
|
|
168
|
+
payload.expectedDocumentUpdatedAt ?? args.expectedDocumentUpdatedAt;
|
|
169
|
+
if (
|
|
170
|
+
args.expectedDocumentUpdatedAt !== expectedUpdatedAt ||
|
|
171
|
+
!currentDocument ||
|
|
172
|
+
(currentDocument.updatedAt !== expectedUpdatedAt &&
|
|
173
|
+
!(
|
|
174
|
+
args.choice === "keep_mine" &&
|
|
175
|
+
currentDocument.title === claim.title &&
|
|
176
|
+
currentDocument.content === claim.content
|
|
177
|
+
))
|
|
178
|
+
) {
|
|
179
|
+
return {
|
|
180
|
+
status: "document_conflict" as const,
|
|
181
|
+
document: currentDocument ?? null,
|
|
182
|
+
};
|
|
183
|
+
}
|
|
146
184
|
return {
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
185
|
+
status: "claimed" as const,
|
|
186
|
+
draft: {
|
|
187
|
+
id: payload.draftId,
|
|
188
|
+
ownerEmail: userEmail,
|
|
189
|
+
orgId,
|
|
190
|
+
documentId: args.documentId,
|
|
191
|
+
title: claim.title,
|
|
192
|
+
content: claim.content,
|
|
193
|
+
baseDocumentUpdatedAt: payload.baseDocumentUpdatedAt,
|
|
194
|
+
loadedContentWasEmpty: payload.loadedContentWasEmpty,
|
|
195
|
+
deferredReason: payload.deferredReason,
|
|
196
|
+
version: args.expectedDraftVersion,
|
|
197
|
+
createdAt: payload.createdAt,
|
|
198
|
+
updatedAt: payload.updatedAt,
|
|
199
|
+
},
|
|
200
|
+
acquired: false,
|
|
201
|
+
};
|
|
202
|
+
}
|
|
203
|
+
const [currentDocument] = await tx
|
|
204
|
+
.select()
|
|
205
|
+
.from(schema.documents)
|
|
206
|
+
.where(eq(schema.documents.id, args.documentId))
|
|
207
|
+
.for("update")
|
|
208
|
+
.limit(1);
|
|
209
|
+
if (
|
|
210
|
+
!currentDocument ||
|
|
211
|
+
currentDocument.updatedAt !== args.expectedDocumentUpdatedAt
|
|
212
|
+
) {
|
|
213
|
+
return {
|
|
214
|
+
status: "document_conflict" as const,
|
|
215
|
+
document: currentDocument ?? null,
|
|
159
216
|
};
|
|
160
217
|
}
|
|
161
218
|
const now = new Date().toISOString();
|
|
162
|
-
await tx
|
|
219
|
+
const inserted = await tx
|
|
163
220
|
.insert(schema.documentVersions)
|
|
164
221
|
.values({
|
|
165
222
|
id: claimId,
|
|
@@ -169,7 +226,10 @@ export default defineAction({
|
|
|
169
226
|
content: draft.content,
|
|
170
227
|
chatContext: JSON.stringify({
|
|
171
228
|
choice: args.choice,
|
|
172
|
-
status: "
|
|
229
|
+
status: "processing",
|
|
230
|
+
expectedDocumentUpdatedAt: args.expectedDocumentUpdatedAt,
|
|
231
|
+
processingToken,
|
|
232
|
+
processingStartedAt: now,
|
|
173
233
|
draftId: draft.id,
|
|
174
234
|
baseDocumentUpdatedAt: draft.baseDocumentUpdatedAt,
|
|
175
235
|
loadedContentWasEmpty: draft.loadedContentWasEmpty,
|
|
@@ -190,64 +250,235 @@ export default defineAction({
|
|
|
190
250
|
createdAt: now,
|
|
191
251
|
updatedAt: now,
|
|
192
252
|
})
|
|
193
|
-
.onConflictDoNothing()
|
|
253
|
+
.onConflictDoNothing()
|
|
254
|
+
.returning({ id: schema.documentVersions.id });
|
|
255
|
+
if (inserted.length === 0) {
|
|
256
|
+
const [claim] = await tx
|
|
257
|
+
.select()
|
|
258
|
+
.from(schema.documentVersions)
|
|
259
|
+
.where(
|
|
260
|
+
and(
|
|
261
|
+
eq(schema.documentVersions.id, claimId),
|
|
262
|
+
eq(schema.documentVersions.ownerEmail, userEmail),
|
|
263
|
+
eq(schema.documentVersions.documentId, claimDocumentId),
|
|
264
|
+
),
|
|
265
|
+
)
|
|
266
|
+
.for("update")
|
|
267
|
+
.limit(1);
|
|
268
|
+
if (!claim?.chatContext) conflict("The recovery claim was lost.");
|
|
269
|
+
const payload = durableClaimPayload.parse(
|
|
270
|
+
JSON.parse(claim.chatContext),
|
|
271
|
+
);
|
|
272
|
+
if (payload.choice !== args.choice)
|
|
273
|
+
conflict("This draft was already resolved with another choice.");
|
|
274
|
+
if (payload.status === "resolved") {
|
|
275
|
+
const deleted = await tx
|
|
276
|
+
.delete(schema.documentPreviewDrafts)
|
|
277
|
+
.where(draftFilter)
|
|
278
|
+
.returning({ id: schema.documentPreviewDrafts.id });
|
|
279
|
+
if (deleted.length !== 1)
|
|
280
|
+
conflict("The saved draft changed during recovery.");
|
|
281
|
+
return { status: "resolved" as const };
|
|
282
|
+
}
|
|
283
|
+
if (
|
|
284
|
+
payload.status === "processing" &&
|
|
285
|
+
payload.processingStartedAt &&
|
|
286
|
+
Date.now() - Date.parse(payload.processingStartedAt) < 30_000
|
|
287
|
+
)
|
|
288
|
+
conflict("This recovery choice is already being applied.");
|
|
289
|
+
await tx
|
|
290
|
+
.update(schema.documentVersions)
|
|
291
|
+
.set({
|
|
292
|
+
chatContext: JSON.stringify({
|
|
293
|
+
...payload,
|
|
294
|
+
status: "processing",
|
|
295
|
+
processingToken,
|
|
296
|
+
processingStartedAt: now,
|
|
297
|
+
}),
|
|
298
|
+
updatedAt: now,
|
|
299
|
+
})
|
|
300
|
+
.where(eq(schema.documentVersions.id, claimId));
|
|
301
|
+
}
|
|
194
302
|
const deleted = await tx
|
|
195
303
|
.delete(schema.documentPreviewDrafts)
|
|
196
304
|
.where(draftFilter)
|
|
197
305
|
.returning({ id: schema.documentPreviewDrafts.id });
|
|
198
306
|
if (deleted.length !== 1)
|
|
199
307
|
conflict("The saved draft changed during recovery.");
|
|
200
|
-
return draft;
|
|
308
|
+
return { status: "claimed" as const, draft, acquired: true };
|
|
201
309
|
});
|
|
202
310
|
};
|
|
311
|
+
const acquireClaim = async () =>
|
|
312
|
+
db.transaction(async (tx) => {
|
|
313
|
+
const [claim] = await tx
|
|
314
|
+
.select()
|
|
315
|
+
.from(schema.documentVersions)
|
|
316
|
+
.where(
|
|
317
|
+
and(
|
|
318
|
+
eq(schema.documentVersions.id, claimId),
|
|
319
|
+
eq(schema.documentVersions.ownerEmail, userEmail),
|
|
320
|
+
eq(schema.documentVersions.documentId, claimDocumentId),
|
|
321
|
+
),
|
|
322
|
+
)
|
|
323
|
+
.for("update")
|
|
324
|
+
.limit(1);
|
|
325
|
+
if (!claim?.chatContext) conflict("The recovery claim was lost.");
|
|
326
|
+
const payload = durableClaimPayload.parse(
|
|
327
|
+
JSON.parse(claim.chatContext),
|
|
328
|
+
);
|
|
329
|
+
if (payload.choice !== args.choice)
|
|
330
|
+
conflict("This draft was already resolved with another choice.");
|
|
331
|
+
if (payload.status === "resolved") return false;
|
|
332
|
+
const [currentDocument] = await tx
|
|
333
|
+
.select({
|
|
334
|
+
updatedAt: schema.documents.updatedAt,
|
|
335
|
+
title: schema.documents.title,
|
|
336
|
+
content: schema.documents.content,
|
|
337
|
+
})
|
|
338
|
+
.from(schema.documents)
|
|
339
|
+
.where(eq(schema.documents.id, args.documentId))
|
|
340
|
+
.for("update")
|
|
341
|
+
.limit(1);
|
|
342
|
+
if (
|
|
343
|
+
!currentDocument ||
|
|
344
|
+
(currentDocument.updatedAt !== args.expectedDocumentUpdatedAt &&
|
|
345
|
+
!(
|
|
346
|
+
args.choice === "keep_mine" &&
|
|
347
|
+
currentDocument.title === claim.title &&
|
|
348
|
+
currentDocument.content === claim.content
|
|
349
|
+
))
|
|
350
|
+
) {
|
|
351
|
+
conflict("The page changed after this recovery choice was reviewed.");
|
|
352
|
+
}
|
|
353
|
+
if (
|
|
354
|
+
payload.status === "processing" &&
|
|
355
|
+
payload.processingStartedAt &&
|
|
356
|
+
Date.now() - Date.parse(payload.processingStartedAt) < 30_000
|
|
357
|
+
) {
|
|
358
|
+
conflict("This recovery choice is already being applied.");
|
|
359
|
+
}
|
|
360
|
+
const now = new Date().toISOString();
|
|
361
|
+
await tx
|
|
362
|
+
.update(schema.documentVersions)
|
|
363
|
+
.set({
|
|
364
|
+
chatContext: JSON.stringify({
|
|
365
|
+
...payload,
|
|
366
|
+
status: "processing",
|
|
367
|
+
processingToken,
|
|
368
|
+
processingStartedAt: now,
|
|
369
|
+
}),
|
|
370
|
+
updatedAt: now,
|
|
371
|
+
})
|
|
372
|
+
.where(eq(schema.documentVersions.id, claimId));
|
|
373
|
+
return true;
|
|
374
|
+
});
|
|
203
375
|
const markClaimResolved = async () => {
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
}
|
|
220
|
-
await db
|
|
221
|
-
.update(schema.documentVersions)
|
|
222
|
-
.set({
|
|
223
|
-
chatContext: JSON.stringify({ ...payload, status: "resolved" }),
|
|
224
|
-
updatedAt: new Date().toISOString(),
|
|
225
|
-
})
|
|
226
|
-
.where(
|
|
227
|
-
and(
|
|
228
|
-
eq(schema.documentVersions.id, claimId),
|
|
229
|
-
eq(schema.documentVersions.ownerEmail, userEmail),
|
|
230
|
-
eq(schema.documentVersions.documentId, claimDocumentId),
|
|
231
|
-
),
|
|
376
|
+
await db.transaction(async (tx) => {
|
|
377
|
+
const [claim] = await tx
|
|
378
|
+
.select({ chatContext: schema.documentVersions.chatContext })
|
|
379
|
+
.from(schema.documentVersions)
|
|
380
|
+
.where(
|
|
381
|
+
and(
|
|
382
|
+
eq(schema.documentVersions.id, claimId),
|
|
383
|
+
eq(schema.documentVersions.ownerEmail, userEmail),
|
|
384
|
+
eq(schema.documentVersions.documentId, claimDocumentId),
|
|
385
|
+
),
|
|
386
|
+
)
|
|
387
|
+
.limit(1);
|
|
388
|
+
if (!claim?.chatContext) conflict("The recovery claim was lost.");
|
|
389
|
+
const payload = durableClaimPayload.parse(
|
|
390
|
+
JSON.parse(claim.chatContext),
|
|
232
391
|
);
|
|
392
|
+
if (payload.choice !== args.choice) {
|
|
393
|
+
conflict("This draft was already resolved with another choice.");
|
|
394
|
+
}
|
|
395
|
+
if (payload.status === "resolved") return;
|
|
396
|
+
if (payload.processingToken !== processingToken)
|
|
397
|
+
conflict("This recovery choice is already being applied.");
|
|
398
|
+
await tx
|
|
399
|
+
.update(schema.documentVersions)
|
|
400
|
+
.set({
|
|
401
|
+
chatContext: JSON.stringify({ ...payload, status: "resolved" }),
|
|
402
|
+
updatedAt: new Date().toISOString(),
|
|
403
|
+
})
|
|
404
|
+
.where(
|
|
405
|
+
and(
|
|
406
|
+
eq(schema.documentVersions.id, claimId),
|
|
407
|
+
eq(schema.documentVersions.ownerEmail, userEmail),
|
|
408
|
+
eq(schema.documentVersions.documentId, claimDocumentId),
|
|
409
|
+
),
|
|
410
|
+
);
|
|
411
|
+
});
|
|
233
412
|
};
|
|
234
413
|
const restoreClaimedDraft = async (
|
|
235
414
|
draft: typeof schema.documentPreviewDrafts.$inferSelect,
|
|
236
415
|
) => {
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
416
|
+
await db.transaction(async (tx) => {
|
|
417
|
+
const [claim] = await tx
|
|
418
|
+
.select({ chatContext: schema.documentVersions.chatContext })
|
|
419
|
+
.from(schema.documentVersions)
|
|
420
|
+
.where(eq(schema.documentVersions.id, claimId))
|
|
421
|
+
.for("update")
|
|
422
|
+
.limit(1);
|
|
423
|
+
if (!claim?.chatContext) conflict("The recovery claim was lost.");
|
|
424
|
+
const payload = durableClaimPayload.parse(
|
|
425
|
+
JSON.parse(claim.chatContext),
|
|
426
|
+
);
|
|
427
|
+
if (
|
|
428
|
+
payload.status === "resolved" ||
|
|
429
|
+
payload.processingToken !== processingToken
|
|
430
|
+
)
|
|
431
|
+
return;
|
|
432
|
+
const restored = await tx
|
|
433
|
+
.insert(schema.documentPreviewDrafts)
|
|
434
|
+
.values(draft)
|
|
435
|
+
.onConflictDoNothing()
|
|
436
|
+
.returning({ id: schema.documentPreviewDrafts.id });
|
|
437
|
+
if (restored.length === 1) {
|
|
438
|
+
await tx
|
|
439
|
+
.update(schema.documentVersions)
|
|
440
|
+
.set({
|
|
441
|
+
chatContext: JSON.stringify({ ...payload, status: "claimed" }),
|
|
442
|
+
updatedAt: new Date().toISOString(),
|
|
443
|
+
})
|
|
444
|
+
.where(eq(schema.documentVersions.id, claimId));
|
|
445
|
+
return;
|
|
446
|
+
}
|
|
243
447
|
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
448
|
+
conflict(
|
|
449
|
+
"A newer draft replaced this recovery draft. The claimed version was preserved in Version History.",
|
|
450
|
+
{ recoveryVersionId: claimId },
|
|
451
|
+
);
|
|
452
|
+
});
|
|
248
453
|
};
|
|
249
454
|
if (args.choice === "keep_mine") {
|
|
250
|
-
const
|
|
455
|
+
const claimed = await claimExactDraft();
|
|
456
|
+
if (claimed.status === "document_conflict") return claimed;
|
|
457
|
+
if (claimed.status === "resolved") {
|
|
458
|
+
const [current] = await db
|
|
459
|
+
.select()
|
|
460
|
+
.from(schema.documents)
|
|
461
|
+
.where(eq(schema.documents.id, args.documentId))
|
|
462
|
+
.limit(1);
|
|
463
|
+
return {
|
|
464
|
+
status: "resolved" as const,
|
|
465
|
+
choice: args.choice,
|
|
466
|
+
document: current,
|
|
467
|
+
};
|
|
468
|
+
}
|
|
469
|
+
if (!claimed.acquired && !(await acquireClaim())) {
|
|
470
|
+
const [current] = await db
|
|
471
|
+
.select()
|
|
472
|
+
.from(schema.documents)
|
|
473
|
+
.where(eq(schema.documents.id, args.documentId))
|
|
474
|
+
.limit(1);
|
|
475
|
+
return {
|
|
476
|
+
status: "resolved" as const,
|
|
477
|
+
choice: args.choice,
|
|
478
|
+
document: current,
|
|
479
|
+
};
|
|
480
|
+
}
|
|
481
|
+
const { draft } = claimed;
|
|
251
482
|
try {
|
|
252
483
|
const [current] = await db
|
|
253
484
|
.select()
|
|
@@ -299,7 +530,12 @@ export default defineAction({
|
|
|
299
530
|
}
|
|
300
531
|
|
|
301
532
|
if (args.choice === "use_saved") {
|
|
302
|
-
await claimExactDraft();
|
|
533
|
+
const claimed = await claimExactDraft();
|
|
534
|
+
if (claimed.status === "document_conflict") return claimed;
|
|
535
|
+
if (claimed.status === "resolved")
|
|
536
|
+
return { status: "resolved" as const, choice: args.choice };
|
|
537
|
+
if (!claimed.acquired && !(await acquireClaim()))
|
|
538
|
+
return { status: "resolved" as const, choice: args.choice };
|
|
303
539
|
await markClaimResolved();
|
|
304
540
|
return { status: "resolved" as const, choice: args.choice };
|
|
305
541
|
}
|
|
@@ -318,7 +554,31 @@ export default defineAction({
|
|
|
318
554
|
? existing
|
|
319
555
|
: null;
|
|
320
556
|
};
|
|
321
|
-
const
|
|
557
|
+
const claimed = await claimExactDraft();
|
|
558
|
+
if (claimed.status === "document_conflict") return claimed;
|
|
559
|
+
if (claimed.status === "resolved") {
|
|
560
|
+
const existing = await findExistingRecovery();
|
|
561
|
+
if (!existing) conflict("The recovered copy could not be found.");
|
|
562
|
+
return {
|
|
563
|
+
status: "resolved" as const,
|
|
564
|
+
choice: args.choice,
|
|
565
|
+
document: existing,
|
|
566
|
+
createdDocumentId: existing.id,
|
|
567
|
+
urlPath: `/page/${existing.id}`,
|
|
568
|
+
};
|
|
569
|
+
}
|
|
570
|
+
if (!claimed.acquired && !(await acquireClaim())) {
|
|
571
|
+
const existing = await findExistingRecovery();
|
|
572
|
+
if (!existing) conflict("The recovered copy could not be found.");
|
|
573
|
+
return {
|
|
574
|
+
status: "resolved" as const,
|
|
575
|
+
choice: args.choice,
|
|
576
|
+
document: existing,
|
|
577
|
+
createdDocumentId: existing.id,
|
|
578
|
+
urlPath: `/page/${existing.id}`,
|
|
579
|
+
};
|
|
580
|
+
}
|
|
581
|
+
const { draft } = claimed;
|
|
322
582
|
const existingRecovery = await findExistingRecovery();
|
|
323
583
|
if (existingRecovery) {
|
|
324
584
|
await markClaimResolved();
|
|
@@ -985,7 +985,9 @@ function AdditionalBlockEditor({
|
|
|
985
985
|
documentId={documentId}
|
|
986
986
|
content={content}
|
|
987
987
|
onChange={onChange}
|
|
988
|
-
onSaveContent={
|
|
988
|
+
onSaveContent={async (markdown) =>
|
|
989
|
+
(await onSaveContent(markdown)) ? "persisted" : "failed"
|
|
990
|
+
}
|
|
989
991
|
editable={canEdit}
|
|
990
992
|
localFileMode
|
|
991
993
|
/>
|