@allbluecn/web-app 0.22.0 → 0.22.3
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/package.json +6 -8
- package/public/logo/allblue-logo-app-icon.svg +1 -1
- package/src/components/changelog/changelog-page.tsx +24 -5
- package/src/components/desktop/cloud-login.tsx +91 -0
- package/src/components/desktop/conflict-center.tsx +148 -0
- package/src/components/desktop/renamed-toast.tsx +23 -0
- package/src/components/desktop/shell-widgets.tsx +19 -0
- package/src/components/desktop/sync-indicator.tsx +60 -0
- package/src/components/desktop/sync-status-card.tsx +60 -0
- package/src/components/layout/sidebar-03/app-sidebar.tsx +38 -3
- package/src/components/shared-kit/avatars/__tests__/avatar-shape.test.ts +17 -1
- package/src/components/shared-kit/avatars/avatar-shape.ts +10 -0
- package/src/components/shared-kit/avatars/user-avatar.tsx +2 -2
- package/src/lib/auth/auth.config.ts +4 -1
- package/src/lib/changelog/sdk-versions.ts +33 -2
- package/src/lib/desktop-bridge-types.ts +30 -0
- package/src/lib/desktop-detect.ts +2 -0
- package/src/lib/vector-store/__tests__/factory.test.ts +0 -7
- package/src/lib/vector-store/index.ts +2 -4
- package/src/paraglide/messages/_index.d.ts +1 -1
- package/src/paraglide/messages/_index.js +32 -16
- package/src/paraglide/messages/common_sidebar_usermenu_loginsaas3.d.ts +1 -1
- package/src/paraglide/messages/common_sidebar_usermenu_loginsaas3.js +3 -3
- package/src/paraglide/messages/en.js +11 -6
- package/src/paraglide/messages/{tasks_ai_desktop_notice.d.ts → settings_tabs_sync.d.ts} +5 -5
- package/src/paraglide/messages/settings_tabs_sync.js +29 -0
- package/src/paraglide/messages/zh.js +11 -6
- package/src/providers/index.tsx +6 -0
- package/src/routeTree.gen.ts +107 -49
- package/src/routes/_nav/route.lazy.tsx +12 -0
- package/src/routes/_nav/settings/-settings-tabs.tsx +1 -1
- package/src/routes/_nav/settings/sync/route.lazy.tsx +40 -0
- package/src/routes/_nav/settings/sync/route.tsx +15 -0
- package/src/routes/_nav/tasks/index.lazy.tsx +1 -11
- package/src/routes/api/billing-webhook.ts +6 -2
- package/src/routes/api/sync/bootstrap.ts +38 -0
- package/src/routes/api/sync/pull.ts +96 -0
- package/src/routes/api/sync/push.ts +169 -0
- package/src/routes/api/sync/snapshot.ts +104 -0
- package/src/server/__tests__/fetch-guard.test.ts +2 -2
- package/src/server/__tests__/resource-registry.test.ts +4 -2
- package/src/server/__tests__/sandbox-entitlement.test.ts +5 -0
- package/src/server/__tests__/security-headers.test.ts +25 -0
- package/src/server/__tests__/task-assigned-query.test.ts +0 -11
- package/src/server/__tests__/task-serverfn-crud.test.ts +1 -22
- package/src/server/__tests__/task-serverfn-queries.test.ts +1 -9
- package/src/server/ai-gateway/__tests__/chat-stream-builder-memory.test.ts +0 -11
- package/src/server/ai-gateway/__tests__/embedding-request.test.ts +1 -1
- package/src/server/ai-gateway/__tests__/provider-adapter.test.ts +2 -2
- package/src/server/ai-gateway/__tests__/run-store-durable.test.ts +1 -1
- package/src/server/ai-gateway/durability/__tests__/pg-stream.test.ts +1 -1
- package/src/server/ai-gateway/durability/__tests__/reaper-real-db.test.ts +1 -1
- package/src/server/ai-gateway/memory/index.ts +2 -2
- package/src/server/ai-gateway/sandbox/__tests__/instance-store.test.ts +1 -1
- package/src/server/ai-task/assigned-query.ts +4 -15
- package/src/server/desktop-guest.ts +12 -0
- package/src/server/fetch-guard.ts +3 -3
- package/src/server/middlewares/desktop-token.ts +23 -0
- package/src/server/remote-auth.ts +6 -0
- package/src/server/serverFns/__tests__/billing.test.ts +58 -1
- package/src/server/serverFns/__tests__/update-seats.test.ts +8 -8
- package/src/server/serverFns/agents/agent-crud.ts +3 -1
- package/src/server/serverFns/auth/session.ts +9 -0
- package/src/server/serverFns/billing.ts +10 -4
- package/src/server/serverFns/bug/bug-crud.ts +7 -2
- package/src/server/serverFns/story/__tests__/labels.test.ts +37 -15
- package/src/server/serverFns/story/story-comments.ts +2 -1
- package/src/server/serverFns/story/story-crud/activities.ts +1 -1
- package/src/server/serverFns/story/story-crud/user-brief.ts +1 -1
- package/src/server/serverFns/story/story-crud.ts +2 -1
- package/src/server/serverFns/story/story-transfer.ts +2 -1
- package/src/server/serverFns/tasks/task-crud.ts +0 -13
- package/src/server/serverFns/tasks/task-queries.ts +1 -12
- package/src/server/serverFns/testcase/plans.ts +1 -1
- package/src/server/serverFns/testcase/run-cases.ts +1 -1
- package/src/server/serverFns/testcase/runs.ts +1 -1
- package/src/server/serverFns/testcase/testcase-activities.ts +1 -1
- package/src/server/serverFns/testcase/testcase-board.ts +1 -1
- package/src/server/serverFns/testcase/testcase-crud.ts +1 -1
- package/src/server/serverFns/workspace.ts +1 -1
- package/src/server/story/types.ts +7 -22
- package/src/server/story/user-brief.ts +48 -0
- package/src/server/sync/scopes.ts +29 -0
- package/src/start.ts +10 -2
- package/src/styles/globals.css +10 -0
- package/src/__tests__/desktop-connection-validate.test.ts +0 -66
- package/src/lib/vector-store/__tests__/sqlite-vec-store.test.ts +0 -143
- package/src/lib/vector-store/sqlite-vec-store.ts +0 -224
- package/src/paraglide/messages/tasks_ai_desktop_notice.js +0 -29
- package/src/routes/__desktop/onboarding/route.lazy.tsx +0 -175
- package/src/routes/__desktop/onboarding/route.tsx +0 -11
- package/src/routes/_nav/settings/connection/route.lazy.tsx +0 -64
- package/src/routes/_nav/settings/connection/route.tsx +0 -10
package/src/routeTree.gen.ts
CHANGED
|
@@ -17,7 +17,6 @@ import { Route as PublicRouteRouteImport } from './routes/_public/route'
|
|
|
17
17
|
import { Route as DocsRouteImport } from './routes/docs'
|
|
18
18
|
import { Route as ShareRouteRouteImport } from './routes/share/route'
|
|
19
19
|
import { Route as WorkspaceRouteImport } from './routes/workspace'
|
|
20
|
-
import { Route as _desktopOnboardingRouteRouteImport } from './routes/__desktop/onboarding/route'
|
|
21
20
|
import { Route as LoginEmailUnsubscribeRouteRouteImport } from './routes/_login/email-unsubscribe/route'
|
|
22
21
|
import { Route as LoginForgotPasswordRouteRouteImport } from './routes/_login/forgot-password/route'
|
|
23
22
|
import { Route as LoginLoginRouteRouteImport } from './routes/_login/login/route'
|
|
@@ -75,10 +74,10 @@ import { Route as NavSettingsAccountRouteRouteImport } from './routes/_nav/setti
|
|
|
75
74
|
import { Route as NavSettingsAgentsRouteRouteImport } from './routes/_nav/settings/agents/route'
|
|
76
75
|
import { Route as NavSettingsAiRouteRouteImport } from './routes/_nav/settings/ai/route'
|
|
77
76
|
import { Route as NavSettingsBillingRouteRouteImport } from './routes/_nav/settings/billing/route'
|
|
78
|
-
import { Route as NavSettingsConnectionRouteRouteImport } from './routes/_nav/settings/connection/route'
|
|
79
77
|
import { Route as NavSettingsGeneralRouteRouteImport } from './routes/_nav/settings/general/route'
|
|
80
78
|
import { Route as NavSettingsNotificationsRouteRouteImport } from './routes/_nav/settings/notifications/route'
|
|
81
79
|
import { Route as NavSettingsPrivacyRouteRouteImport } from './routes/_nav/settings/privacy/route'
|
|
80
|
+
import { Route as NavSettingsSyncRouteRouteImport } from './routes/_nav/settings/sync/route'
|
|
82
81
|
import { Route as NavSettingsTeamRouteRouteImport } from './routes/_nav/settings/team/route'
|
|
83
82
|
import { Route as NavStoriesIndexRouteImport } from './routes/_nav/stories/index'
|
|
84
83
|
import { Route as NavStoriesStoryIdRouteRouteImport } from './routes/_nav/stories/$storyId/route'
|
|
@@ -105,6 +104,10 @@ import { Route as ApiLicenseActivateRouteRouteImport } from './routes/api/licens
|
|
|
105
104
|
import { Route as ApiLicenseHeartbeatRouteRouteImport } from './routes/api/license/heartbeat/route'
|
|
106
105
|
import { Route as ApiMcpBugsRouteImport } from './routes/api/mcp/bugs'
|
|
107
106
|
import { Route as ApiNotificationsStreamRouteImport } from './routes/api/notifications/stream'
|
|
107
|
+
import { Route as ApiSyncBootstrapRouteImport } from './routes/api/sync/bootstrap'
|
|
108
|
+
import { Route as ApiSyncPullRouteImport } from './routes/api/sync/pull'
|
|
109
|
+
import { Route as ApiSyncPushRouteImport } from './routes/api/sync/push'
|
|
110
|
+
import { Route as ApiSyncSnapshotRouteImport } from './routes/api/sync/snapshot'
|
|
108
111
|
import { Route as ServerAnyhubProxySplatRouteImport } from './routes/server/anyhub-proxy/$'
|
|
109
112
|
import { Route as ShareComplianceIdRouteRouteImport } from './routes/share/compliance/$id/route'
|
|
110
113
|
import { Route as ShareDesignDesignIdRouteRouteImport } from './routes/share/design/$designId/route'
|
|
@@ -202,15 +205,6 @@ const WorkspaceRoute = WorkspaceRouteImport.update({
|
|
|
202
205
|
path: '/workspace',
|
|
203
206
|
getParentRoute: () => rootRouteImport,
|
|
204
207
|
} as any)
|
|
205
|
-
const _desktopOnboardingRouteRoute = _desktopOnboardingRouteRouteImport
|
|
206
|
-
.update({
|
|
207
|
-
id: '/__desktop/onboarding',
|
|
208
|
-
path: '/onboarding',
|
|
209
|
-
getParentRoute: () => rootRouteImport,
|
|
210
|
-
} as any)
|
|
211
|
-
.lazy(() =>
|
|
212
|
-
import('./routes/__desktop/onboarding/route.lazy').then((d) => d.Route),
|
|
213
|
-
)
|
|
214
208
|
const LoginEmailUnsubscribeRouteRoute =
|
|
215
209
|
LoginEmailUnsubscribeRouteRouteImport.update({
|
|
216
210
|
id: '/email-unsubscribe',
|
|
@@ -566,14 +560,6 @@ const NavSettingsBillingRouteRoute = NavSettingsBillingRouteRouteImport.update({
|
|
|
566
560
|
} as any).lazy(() =>
|
|
567
561
|
import('./routes/_nav/settings/billing/route.lazy').then((d) => d.Route),
|
|
568
562
|
)
|
|
569
|
-
const NavSettingsConnectionRouteRoute =
|
|
570
|
-
NavSettingsConnectionRouteRouteImport.update({
|
|
571
|
-
id: '/connection',
|
|
572
|
-
path: '/connection',
|
|
573
|
-
getParentRoute: () => NavSettingsRouteRoute,
|
|
574
|
-
} as any).lazy(() =>
|
|
575
|
-
import('./routes/_nav/settings/connection/route.lazy').then((d) => d.Route),
|
|
576
|
-
)
|
|
577
563
|
const NavSettingsGeneralRouteRoute = NavSettingsGeneralRouteRouteImport.update({
|
|
578
564
|
id: '/general',
|
|
579
565
|
path: '/general',
|
|
@@ -598,6 +584,13 @@ const NavSettingsPrivacyRouteRoute = NavSettingsPrivacyRouteRouteImport.update({
|
|
|
598
584
|
} as any).lazy(() =>
|
|
599
585
|
import('./routes/_nav/settings/privacy/route.lazy').then((d) => d.Route),
|
|
600
586
|
)
|
|
587
|
+
const NavSettingsSyncRouteRoute = NavSettingsSyncRouteRouteImport.update({
|
|
588
|
+
id: '/sync',
|
|
589
|
+
path: '/sync',
|
|
590
|
+
getParentRoute: () => NavSettingsRouteRoute,
|
|
591
|
+
} as any).lazy(() =>
|
|
592
|
+
import('./routes/_nav/settings/sync/route.lazy').then((d) => d.Route),
|
|
593
|
+
)
|
|
601
594
|
const NavSettingsTeamRouteRoute = NavSettingsTeamRouteRouteImport.update({
|
|
602
595
|
id: '/team',
|
|
603
596
|
path: '/team',
|
|
@@ -752,6 +745,26 @@ const ApiNotificationsStreamRoute = ApiNotificationsStreamRouteImport.update({
|
|
|
752
745
|
path: '/api/notifications/stream',
|
|
753
746
|
getParentRoute: () => rootRouteImport,
|
|
754
747
|
} as any)
|
|
748
|
+
const ApiSyncBootstrapRoute = ApiSyncBootstrapRouteImport.update({
|
|
749
|
+
id: '/api/sync/bootstrap',
|
|
750
|
+
path: '/api/sync/bootstrap',
|
|
751
|
+
getParentRoute: () => rootRouteImport,
|
|
752
|
+
} as any)
|
|
753
|
+
const ApiSyncPullRoute = ApiSyncPullRouteImport.update({
|
|
754
|
+
id: '/api/sync/pull',
|
|
755
|
+
path: '/api/sync/pull',
|
|
756
|
+
getParentRoute: () => rootRouteImport,
|
|
757
|
+
} as any)
|
|
758
|
+
const ApiSyncPushRoute = ApiSyncPushRouteImport.update({
|
|
759
|
+
id: '/api/sync/push',
|
|
760
|
+
path: '/api/sync/push',
|
|
761
|
+
getParentRoute: () => rootRouteImport,
|
|
762
|
+
} as any)
|
|
763
|
+
const ApiSyncSnapshotRoute = ApiSyncSnapshotRouteImport.update({
|
|
764
|
+
id: '/api/sync/snapshot',
|
|
765
|
+
path: '/api/sync/snapshot',
|
|
766
|
+
getParentRoute: () => rootRouteImport,
|
|
767
|
+
} as any)
|
|
755
768
|
const ServerAnyhubProxySplatRoute = ServerAnyhubProxySplatRouteImport.update({
|
|
756
769
|
id: '/server/anyhub-proxy/$',
|
|
757
770
|
path: '/server/anyhub-proxy/$',
|
|
@@ -1092,7 +1105,6 @@ export interface FileRoutesByFullPath {
|
|
|
1092
1105
|
'/share': typeof ShareRouteRouteWithChildren
|
|
1093
1106
|
'/docs': typeof DocsRoute
|
|
1094
1107
|
'/workspace': typeof WorkspaceRoute
|
|
1095
|
-
'/onboarding': typeof _desktopOnboardingRouteRoute
|
|
1096
1108
|
'/email-unsubscribe': typeof LoginEmailUnsubscribeRouteRoute
|
|
1097
1109
|
'/forgot-password': typeof LoginForgotPasswordRouteRoute
|
|
1098
1110
|
'/login': typeof LoginLoginRouteRoute
|
|
@@ -1144,10 +1156,10 @@ export interface FileRoutesByFullPath {
|
|
|
1144
1156
|
'/settings/agents': typeof NavSettingsAgentsRouteRoute
|
|
1145
1157
|
'/settings/ai': typeof NavSettingsAiRouteRouteWithChildren
|
|
1146
1158
|
'/settings/billing': typeof NavSettingsBillingRouteRoute
|
|
1147
|
-
'/settings/connection': typeof NavSettingsConnectionRouteRoute
|
|
1148
1159
|
'/settings/general': typeof NavSettingsGeneralRouteRoute
|
|
1149
1160
|
'/settings/notifications': typeof NavSettingsNotificationsRouteRoute
|
|
1150
1161
|
'/settings/privacy': typeof NavSettingsPrivacyRouteRoute
|
|
1162
|
+
'/settings/sync': typeof NavSettingsSyncRouteRoute
|
|
1151
1163
|
'/settings/team': typeof NavSettingsTeamRouteRoute
|
|
1152
1164
|
'/stories/$storyId': typeof NavStoriesStoryIdRouteRoute
|
|
1153
1165
|
'/tasks/$taskId': typeof NavTasksTaskIdRouteRoute
|
|
@@ -1175,6 +1187,10 @@ export interface FileRoutesByFullPath {
|
|
|
1175
1187
|
'/api/knowledge/sync-github': typeof ApiKnowledgeSyncGithubRoute
|
|
1176
1188
|
'/api/mcp/bugs': typeof ApiMcpBugsRoute
|
|
1177
1189
|
'/api/notifications/stream': typeof ApiNotificationsStreamRoute
|
|
1190
|
+
'/api/sync/bootstrap': typeof ApiSyncBootstrapRoute
|
|
1191
|
+
'/api/sync/pull': typeof ApiSyncPullRoute
|
|
1192
|
+
'/api/sync/push': typeof ApiSyncPushRoute
|
|
1193
|
+
'/api/sync/snapshot': typeof ApiSyncSnapshotRoute
|
|
1178
1194
|
'/server/anyhub-proxy/$': typeof ServerAnyhubProxySplatRoute
|
|
1179
1195
|
'/share/prd/$designId': typeof SharePrdDesignIdRoute
|
|
1180
1196
|
'/bugs/': typeof NavBugsIndexRoute
|
|
@@ -1226,7 +1242,6 @@ export interface FileRoutesByTo {
|
|
|
1226
1242
|
'/share': typeof ShareRouteRouteWithChildren
|
|
1227
1243
|
'/docs': typeof DocsRoute
|
|
1228
1244
|
'/workspace': typeof WorkspaceRoute
|
|
1229
|
-
'/onboarding': typeof _desktopOnboardingRouteRoute
|
|
1230
1245
|
'/email-unsubscribe': typeof LoginEmailUnsubscribeRouteRoute
|
|
1231
1246
|
'/forgot-password': typeof LoginForgotPasswordRouteRoute
|
|
1232
1247
|
'/login': typeof LoginLoginRouteRoute
|
|
@@ -1263,10 +1278,10 @@ export interface FileRoutesByTo {
|
|
|
1263
1278
|
'/settings/account': typeof NavSettingsAccountRouteRoute
|
|
1264
1279
|
'/settings/agents': typeof NavSettingsAgentsRouteRoute
|
|
1265
1280
|
'/settings/billing': typeof NavSettingsBillingRouteRoute
|
|
1266
|
-
'/settings/connection': typeof NavSettingsConnectionRouteRoute
|
|
1267
1281
|
'/settings/general': typeof NavSettingsGeneralRouteRoute
|
|
1268
1282
|
'/settings/notifications': typeof NavSettingsNotificationsRouteRoute
|
|
1269
1283
|
'/settings/privacy': typeof NavSettingsPrivacyRouteRoute
|
|
1284
|
+
'/settings/sync': typeof NavSettingsSyncRouteRoute
|
|
1270
1285
|
'/settings/team': typeof NavSettingsTeamRouteRoute
|
|
1271
1286
|
'/stories/$storyId': typeof NavStoriesStoryIdRouteRoute
|
|
1272
1287
|
'/tasks/$taskId': typeof NavTasksTaskIdRouteRoute
|
|
@@ -1294,6 +1309,10 @@ export interface FileRoutesByTo {
|
|
|
1294
1309
|
'/api/knowledge/sync-github': typeof ApiKnowledgeSyncGithubRoute
|
|
1295
1310
|
'/api/mcp/bugs': typeof ApiMcpBugsRoute
|
|
1296
1311
|
'/api/notifications/stream': typeof ApiNotificationsStreamRoute
|
|
1312
|
+
'/api/sync/bootstrap': typeof ApiSyncBootstrapRoute
|
|
1313
|
+
'/api/sync/pull': typeof ApiSyncPullRoute
|
|
1314
|
+
'/api/sync/push': typeof ApiSyncPushRoute
|
|
1315
|
+
'/api/sync/snapshot': typeof ApiSyncSnapshotRoute
|
|
1297
1316
|
'/server/anyhub-proxy/$': typeof ServerAnyhubProxySplatRoute
|
|
1298
1317
|
'/share/prd/$designId': typeof SharePrdDesignIdRoute
|
|
1299
1318
|
'/bugs': typeof NavBugsIndexRoute
|
|
@@ -1349,7 +1368,6 @@ export interface FileRoutesById {
|
|
|
1349
1368
|
'/docs': typeof DocsRoute
|
|
1350
1369
|
'/workspace': typeof WorkspaceRoute
|
|
1351
1370
|
'/_public/': typeof PublicIndexRouteRoute
|
|
1352
|
-
'/__desktop/onboarding': typeof _desktopOnboardingRouteRoute
|
|
1353
1371
|
'/_login/email-unsubscribe': typeof LoginEmailUnsubscribeRouteRoute
|
|
1354
1372
|
'/_login/forgot-password': typeof LoginForgotPasswordRouteRoute
|
|
1355
1373
|
'/_login/login': typeof LoginLoginRouteRoute
|
|
@@ -1401,10 +1419,10 @@ export interface FileRoutesById {
|
|
|
1401
1419
|
'/_nav/settings/agents': typeof NavSettingsAgentsRouteRoute
|
|
1402
1420
|
'/_nav/settings/ai': typeof NavSettingsAiRouteRouteWithChildren
|
|
1403
1421
|
'/_nav/settings/billing': typeof NavSettingsBillingRouteRoute
|
|
1404
|
-
'/_nav/settings/connection': typeof NavSettingsConnectionRouteRoute
|
|
1405
1422
|
'/_nav/settings/general': typeof NavSettingsGeneralRouteRoute
|
|
1406
1423
|
'/_nav/settings/notifications': typeof NavSettingsNotificationsRouteRoute
|
|
1407
1424
|
'/_nav/settings/privacy': typeof NavSettingsPrivacyRouteRoute
|
|
1425
|
+
'/_nav/settings/sync': typeof NavSettingsSyncRouteRoute
|
|
1408
1426
|
'/_nav/settings/team': typeof NavSettingsTeamRouteRoute
|
|
1409
1427
|
'/_nav/stories/$storyId': typeof NavStoriesStoryIdRouteRoute
|
|
1410
1428
|
'/_nav/tasks/$taskId': typeof NavTasksTaskIdRouteRoute
|
|
@@ -1432,6 +1450,10 @@ export interface FileRoutesById {
|
|
|
1432
1450
|
'/api/knowledge/sync-github': typeof ApiKnowledgeSyncGithubRoute
|
|
1433
1451
|
'/api/mcp/bugs': typeof ApiMcpBugsRoute
|
|
1434
1452
|
'/api/notifications/stream': typeof ApiNotificationsStreamRoute
|
|
1453
|
+
'/api/sync/bootstrap': typeof ApiSyncBootstrapRoute
|
|
1454
|
+
'/api/sync/pull': typeof ApiSyncPullRoute
|
|
1455
|
+
'/api/sync/push': typeof ApiSyncPushRoute
|
|
1456
|
+
'/api/sync/snapshot': typeof ApiSyncSnapshotRoute
|
|
1435
1457
|
'/server/anyhub-proxy/$': typeof ServerAnyhubProxySplatRoute
|
|
1436
1458
|
'/share/prd/$designId': typeof SharePrdDesignIdRoute
|
|
1437
1459
|
'/_nav/bugs/': typeof NavBugsIndexRoute
|
|
@@ -1485,7 +1507,6 @@ export interface FileRouteTypes {
|
|
|
1485
1507
|
| '/share'
|
|
1486
1508
|
| '/docs'
|
|
1487
1509
|
| '/workspace'
|
|
1488
|
-
| '/onboarding'
|
|
1489
1510
|
| '/email-unsubscribe'
|
|
1490
1511
|
| '/forgot-password'
|
|
1491
1512
|
| '/login'
|
|
@@ -1537,10 +1558,10 @@ export interface FileRouteTypes {
|
|
|
1537
1558
|
| '/settings/agents'
|
|
1538
1559
|
| '/settings/ai'
|
|
1539
1560
|
| '/settings/billing'
|
|
1540
|
-
| '/settings/connection'
|
|
1541
1561
|
| '/settings/general'
|
|
1542
1562
|
| '/settings/notifications'
|
|
1543
1563
|
| '/settings/privacy'
|
|
1564
|
+
| '/settings/sync'
|
|
1544
1565
|
| '/settings/team'
|
|
1545
1566
|
| '/stories/$storyId'
|
|
1546
1567
|
| '/tasks/$taskId'
|
|
@@ -1568,6 +1589,10 @@ export interface FileRouteTypes {
|
|
|
1568
1589
|
| '/api/knowledge/sync-github'
|
|
1569
1590
|
| '/api/mcp/bugs'
|
|
1570
1591
|
| '/api/notifications/stream'
|
|
1592
|
+
| '/api/sync/bootstrap'
|
|
1593
|
+
| '/api/sync/pull'
|
|
1594
|
+
| '/api/sync/push'
|
|
1595
|
+
| '/api/sync/snapshot'
|
|
1571
1596
|
| '/server/anyhub-proxy/$'
|
|
1572
1597
|
| '/share/prd/$designId'
|
|
1573
1598
|
| '/bugs/'
|
|
@@ -1619,7 +1644,6 @@ export interface FileRouteTypes {
|
|
|
1619
1644
|
| '/share'
|
|
1620
1645
|
| '/docs'
|
|
1621
1646
|
| '/workspace'
|
|
1622
|
-
| '/onboarding'
|
|
1623
1647
|
| '/email-unsubscribe'
|
|
1624
1648
|
| '/forgot-password'
|
|
1625
1649
|
| '/login'
|
|
@@ -1656,10 +1680,10 @@ export interface FileRouteTypes {
|
|
|
1656
1680
|
| '/settings/account'
|
|
1657
1681
|
| '/settings/agents'
|
|
1658
1682
|
| '/settings/billing'
|
|
1659
|
-
| '/settings/connection'
|
|
1660
1683
|
| '/settings/general'
|
|
1661
1684
|
| '/settings/notifications'
|
|
1662
1685
|
| '/settings/privacy'
|
|
1686
|
+
| '/settings/sync'
|
|
1663
1687
|
| '/settings/team'
|
|
1664
1688
|
| '/stories/$storyId'
|
|
1665
1689
|
| '/tasks/$taskId'
|
|
@@ -1687,6 +1711,10 @@ export interface FileRouteTypes {
|
|
|
1687
1711
|
| '/api/knowledge/sync-github'
|
|
1688
1712
|
| '/api/mcp/bugs'
|
|
1689
1713
|
| '/api/notifications/stream'
|
|
1714
|
+
| '/api/sync/bootstrap'
|
|
1715
|
+
| '/api/sync/pull'
|
|
1716
|
+
| '/api/sync/push'
|
|
1717
|
+
| '/api/sync/snapshot'
|
|
1690
1718
|
| '/server/anyhub-proxy/$'
|
|
1691
1719
|
| '/share/prd/$designId'
|
|
1692
1720
|
| '/bugs'
|
|
@@ -1741,7 +1769,6 @@ export interface FileRouteTypes {
|
|
|
1741
1769
|
| '/docs'
|
|
1742
1770
|
| '/workspace'
|
|
1743
1771
|
| '/_public/'
|
|
1744
|
-
| '/__desktop/onboarding'
|
|
1745
1772
|
| '/_login/email-unsubscribe'
|
|
1746
1773
|
| '/_login/forgot-password'
|
|
1747
1774
|
| '/_login/login'
|
|
@@ -1793,10 +1820,10 @@ export interface FileRouteTypes {
|
|
|
1793
1820
|
| '/_nav/settings/agents'
|
|
1794
1821
|
| '/_nav/settings/ai'
|
|
1795
1822
|
| '/_nav/settings/billing'
|
|
1796
|
-
| '/_nav/settings/connection'
|
|
1797
1823
|
| '/_nav/settings/general'
|
|
1798
1824
|
| '/_nav/settings/notifications'
|
|
1799
1825
|
| '/_nav/settings/privacy'
|
|
1826
|
+
| '/_nav/settings/sync'
|
|
1800
1827
|
| '/_nav/settings/team'
|
|
1801
1828
|
| '/_nav/stories/$storyId'
|
|
1802
1829
|
| '/_nav/tasks/$taskId'
|
|
@@ -1824,6 +1851,10 @@ export interface FileRouteTypes {
|
|
|
1824
1851
|
| '/api/knowledge/sync-github'
|
|
1825
1852
|
| '/api/mcp/bugs'
|
|
1826
1853
|
| '/api/notifications/stream'
|
|
1854
|
+
| '/api/sync/bootstrap'
|
|
1855
|
+
| '/api/sync/pull'
|
|
1856
|
+
| '/api/sync/push'
|
|
1857
|
+
| '/api/sync/snapshot'
|
|
1827
1858
|
| '/server/anyhub-proxy/$'
|
|
1828
1859
|
| '/share/prd/$designId'
|
|
1829
1860
|
| '/_nav/bugs/'
|
|
@@ -1878,7 +1909,6 @@ export interface RootRouteChildren {
|
|
|
1878
1909
|
ShareRouteRoute: typeof ShareRouteRouteWithChildren
|
|
1879
1910
|
DocsRoute: typeof DocsRoute
|
|
1880
1911
|
WorkspaceRoute: typeof WorkspaceRoute
|
|
1881
|
-
_desktopOnboardingRouteRoute: typeof _desktopOnboardingRouteRoute
|
|
1882
1912
|
CollectTokenRouteRoute: typeof CollectTokenRouteRoute
|
|
1883
1913
|
InviteTokenRouteRoute: typeof InviteTokenRouteRoute
|
|
1884
1914
|
ApiBillingWebhookRoute: typeof ApiBillingWebhookRoute
|
|
@@ -1906,6 +1936,10 @@ export interface RootRouteChildren {
|
|
|
1906
1936
|
ApiKnowledgeSyncGithubRoute: typeof ApiKnowledgeSyncGithubRoute
|
|
1907
1937
|
ApiMcpBugsRoute: typeof ApiMcpBugsRoute
|
|
1908
1938
|
ApiNotificationsStreamRoute: typeof ApiNotificationsStreamRoute
|
|
1939
|
+
ApiSyncBootstrapRoute: typeof ApiSyncBootstrapRoute
|
|
1940
|
+
ApiSyncPullRoute: typeof ApiSyncPullRoute
|
|
1941
|
+
ApiSyncPushRoute: typeof ApiSyncPushRoute
|
|
1942
|
+
ApiSyncSnapshotRoute: typeof ApiSyncSnapshotRoute
|
|
1909
1943
|
ServerAnyhubProxySplatRoute: typeof ServerAnyhubProxySplatRoute
|
|
1910
1944
|
ApiAttachmentsIdContentRoute: typeof ApiAttachmentsIdContentRoute
|
|
1911
1945
|
ApiTestRunsRunIdEventsRoute: typeof ApiTestRunsRunIdEventsRoute
|
|
@@ -1957,13 +1991,6 @@ declare module '@tanstack/react-router' {
|
|
|
1957
1991
|
preLoaderRoute: typeof WorkspaceRouteImport
|
|
1958
1992
|
parentRoute: typeof rootRouteImport
|
|
1959
1993
|
}
|
|
1960
|
-
'/__desktop/onboarding': {
|
|
1961
|
-
id: '/__desktop/onboarding'
|
|
1962
|
-
path: '/onboarding'
|
|
1963
|
-
fullPath: '/onboarding'
|
|
1964
|
-
preLoaderRoute: typeof _desktopOnboardingRouteRouteImport
|
|
1965
|
-
parentRoute: typeof rootRouteImport
|
|
1966
|
-
}
|
|
1967
1994
|
'/_login/email-unsubscribe': {
|
|
1968
1995
|
id: '/_login/email-unsubscribe'
|
|
1969
1996
|
path: '/email-unsubscribe'
|
|
@@ -2363,13 +2390,6 @@ declare module '@tanstack/react-router' {
|
|
|
2363
2390
|
preLoaderRoute: typeof NavSettingsBillingRouteRouteImport
|
|
2364
2391
|
parentRoute: typeof NavSettingsRouteRoute
|
|
2365
2392
|
}
|
|
2366
|
-
'/_nav/settings/connection': {
|
|
2367
|
-
id: '/_nav/settings/connection'
|
|
2368
|
-
path: '/connection'
|
|
2369
|
-
fullPath: '/settings/connection'
|
|
2370
|
-
preLoaderRoute: typeof NavSettingsConnectionRouteRouteImport
|
|
2371
|
-
parentRoute: typeof NavSettingsRouteRoute
|
|
2372
|
-
}
|
|
2373
2393
|
'/_nav/settings/general': {
|
|
2374
2394
|
id: '/_nav/settings/general'
|
|
2375
2395
|
path: '/general'
|
|
@@ -2391,6 +2411,13 @@ declare module '@tanstack/react-router' {
|
|
|
2391
2411
|
preLoaderRoute: typeof NavSettingsPrivacyRouteRouteImport
|
|
2392
2412
|
parentRoute: typeof NavSettingsRouteRoute
|
|
2393
2413
|
}
|
|
2414
|
+
'/_nav/settings/sync': {
|
|
2415
|
+
id: '/_nav/settings/sync'
|
|
2416
|
+
path: '/sync'
|
|
2417
|
+
fullPath: '/settings/sync'
|
|
2418
|
+
preLoaderRoute: typeof NavSettingsSyncRouteRouteImport
|
|
2419
|
+
parentRoute: typeof NavSettingsRouteRoute
|
|
2420
|
+
}
|
|
2394
2421
|
'/_nav/settings/team': {
|
|
2395
2422
|
id: '/_nav/settings/team'
|
|
2396
2423
|
path: '/team'
|
|
@@ -2573,6 +2600,34 @@ declare module '@tanstack/react-router' {
|
|
|
2573
2600
|
preLoaderRoute: typeof ApiNotificationsStreamRouteImport
|
|
2574
2601
|
parentRoute: typeof rootRouteImport
|
|
2575
2602
|
}
|
|
2603
|
+
'/api/sync/bootstrap': {
|
|
2604
|
+
id: '/api/sync/bootstrap'
|
|
2605
|
+
path: '/api/sync/bootstrap'
|
|
2606
|
+
fullPath: '/api/sync/bootstrap'
|
|
2607
|
+
preLoaderRoute: typeof ApiSyncBootstrapRouteImport
|
|
2608
|
+
parentRoute: typeof rootRouteImport
|
|
2609
|
+
}
|
|
2610
|
+
'/api/sync/pull': {
|
|
2611
|
+
id: '/api/sync/pull'
|
|
2612
|
+
path: '/api/sync/pull'
|
|
2613
|
+
fullPath: '/api/sync/pull'
|
|
2614
|
+
preLoaderRoute: typeof ApiSyncPullRouteImport
|
|
2615
|
+
parentRoute: typeof rootRouteImport
|
|
2616
|
+
}
|
|
2617
|
+
'/api/sync/push': {
|
|
2618
|
+
id: '/api/sync/push'
|
|
2619
|
+
path: '/api/sync/push'
|
|
2620
|
+
fullPath: '/api/sync/push'
|
|
2621
|
+
preLoaderRoute: typeof ApiSyncPushRouteImport
|
|
2622
|
+
parentRoute: typeof rootRouteImport
|
|
2623
|
+
}
|
|
2624
|
+
'/api/sync/snapshot': {
|
|
2625
|
+
id: '/api/sync/snapshot'
|
|
2626
|
+
path: '/api/sync/snapshot'
|
|
2627
|
+
fullPath: '/api/sync/snapshot'
|
|
2628
|
+
preLoaderRoute: typeof ApiSyncSnapshotRouteImport
|
|
2629
|
+
parentRoute: typeof rootRouteImport
|
|
2630
|
+
}
|
|
2576
2631
|
'/server/anyhub-proxy/$': {
|
|
2577
2632
|
id: '/server/anyhub-proxy/$'
|
|
2578
2633
|
path: '/server/anyhub-proxy/$'
|
|
@@ -3138,10 +3193,10 @@ interface NavSettingsRouteRouteChildren {
|
|
|
3138
3193
|
NavSettingsAgentsRouteRoute: typeof NavSettingsAgentsRouteRoute
|
|
3139
3194
|
NavSettingsAiRouteRoute: typeof NavSettingsAiRouteRouteWithChildren
|
|
3140
3195
|
NavSettingsBillingRouteRoute: typeof NavSettingsBillingRouteRoute
|
|
3141
|
-
NavSettingsConnectionRouteRoute: typeof NavSettingsConnectionRouteRoute
|
|
3142
3196
|
NavSettingsGeneralRouteRoute: typeof NavSettingsGeneralRouteRoute
|
|
3143
3197
|
NavSettingsNotificationsRouteRoute: typeof NavSettingsNotificationsRouteRoute
|
|
3144
3198
|
NavSettingsPrivacyRouteRoute: typeof NavSettingsPrivacyRouteRoute
|
|
3199
|
+
NavSettingsSyncRouteRoute: typeof NavSettingsSyncRouteRoute
|
|
3145
3200
|
NavSettingsTeamRouteRoute: typeof NavSettingsTeamRouteRoute
|
|
3146
3201
|
}
|
|
3147
3202
|
|
|
@@ -3150,10 +3205,10 @@ const NavSettingsRouteRouteChildren: NavSettingsRouteRouteChildren = {
|
|
|
3150
3205
|
NavSettingsAgentsRouteRoute: NavSettingsAgentsRouteRoute,
|
|
3151
3206
|
NavSettingsAiRouteRoute: NavSettingsAiRouteRouteWithChildren,
|
|
3152
3207
|
NavSettingsBillingRouteRoute: NavSettingsBillingRouteRoute,
|
|
3153
|
-
NavSettingsConnectionRouteRoute: NavSettingsConnectionRouteRoute,
|
|
3154
3208
|
NavSettingsGeneralRouteRoute: NavSettingsGeneralRouteRoute,
|
|
3155
3209
|
NavSettingsNotificationsRouteRoute: NavSettingsNotificationsRouteRoute,
|
|
3156
3210
|
NavSettingsPrivacyRouteRoute: NavSettingsPrivacyRouteRoute,
|
|
3211
|
+
NavSettingsSyncRouteRoute: NavSettingsSyncRouteRoute,
|
|
3157
3212
|
NavSettingsTeamRouteRoute: NavSettingsTeamRouteRoute,
|
|
3158
3213
|
}
|
|
3159
3214
|
|
|
@@ -3342,7 +3397,6 @@ const rootRouteChildren: RootRouteChildren = {
|
|
|
3342
3397
|
ShareRouteRoute: ShareRouteRouteWithChildren,
|
|
3343
3398
|
DocsRoute: DocsRoute,
|
|
3344
3399
|
WorkspaceRoute: WorkspaceRoute,
|
|
3345
|
-
_desktopOnboardingRouteRoute: _desktopOnboardingRouteRoute,
|
|
3346
3400
|
CollectTokenRouteRoute: CollectTokenRouteRoute,
|
|
3347
3401
|
InviteTokenRouteRoute: InviteTokenRouteRoute,
|
|
3348
3402
|
ApiBillingWebhookRoute: ApiBillingWebhookRoute,
|
|
@@ -3370,6 +3424,10 @@ const rootRouteChildren: RootRouteChildren = {
|
|
|
3370
3424
|
ApiKnowledgeSyncGithubRoute: ApiKnowledgeSyncGithubRoute,
|
|
3371
3425
|
ApiMcpBugsRoute: ApiMcpBugsRoute,
|
|
3372
3426
|
ApiNotificationsStreamRoute: ApiNotificationsStreamRoute,
|
|
3427
|
+
ApiSyncBootstrapRoute: ApiSyncBootstrapRoute,
|
|
3428
|
+
ApiSyncPullRoute: ApiSyncPullRoute,
|
|
3429
|
+
ApiSyncPushRoute: ApiSyncPushRoute,
|
|
3430
|
+
ApiSyncSnapshotRoute: ApiSyncSnapshotRoute,
|
|
3373
3431
|
ServerAnyhubProxySplatRoute: ServerAnyhubProxySplatRoute,
|
|
3374
3432
|
ApiAttachmentsIdContentRoute: ApiAttachmentsIdContentRoute,
|
|
3375
3433
|
ApiTestRunsRunIdEventsRoute: ApiTestRunsRunIdEventsRoute,
|
|
@@ -25,6 +25,17 @@ import { CommandPalette } from '@/components/command/command-palette'
|
|
|
25
25
|
import type { Session } from '@/lib/auth/auth-client'
|
|
26
26
|
import { usePresenceReport } from '@/lib/collab/use-presence-report'
|
|
27
27
|
import { NavigationIndicator } from './-components/navigation-indicator'
|
|
28
|
+
import { isDesktopEdition } from '@/lib/edition-desktop'
|
|
29
|
+
|
|
30
|
+
// 桌面壳顶缘拖动条:内容区顶部没有可吸附的顶栏组件,窗口上缘条补齐
|
|
31
|
+
// 「整个顶部区域可拖动」(侧栏 header 已整块 drag,见 app-sidebar.tsx)。
|
|
32
|
+
// h-11 覆盖侧栏第一行 + 内容区上缘(用户红框区域)。z-0 是层叠关键:
|
|
33
|
+
// Sidebar 容器 fixed z-10(stacking context),条必须低于它让按钮可点、
|
|
34
|
+
// 高于内容区(非定位)拿拖动命中。浏览器/云端部署 no-op。
|
|
35
|
+
function DesktopDragStrip() {
|
|
36
|
+
if (!isDesktopEdition()) return null
|
|
37
|
+
return <div aria-hidden className="app-region-drag fixed inset-x-0 top-0 z-0 h-11" />
|
|
38
|
+
}
|
|
28
39
|
|
|
29
40
|
export const Route = createLazyFileRoute('/_nav')({
|
|
30
41
|
component: AppLayout,
|
|
@@ -40,6 +51,7 @@ function AppLayout() {
|
|
|
40
51
|
return (
|
|
41
52
|
<>
|
|
42
53
|
<NavigationIndicator />
|
|
54
|
+
<DesktopDragStrip />
|
|
43
55
|
<TimezoneBootstrap timezone={session?.user?.timezone} />
|
|
44
56
|
<LayoutResponsiveProvider>
|
|
45
57
|
<SubscriptionProvider>
|
|
@@ -65,7 +65,7 @@ const groups: SettingsGroup[] = [
|
|
|
65
65
|
const desktopGroups: SettingsGroup[] = [
|
|
66
66
|
{
|
|
67
67
|
title: m.settings_tabs_desktop,
|
|
68
|
-
tabs: [{ label: m.
|
|
68
|
+
tabs: [{ label: m.settings_tabs_sync, path: '/settings/sync', icon: Plug }],
|
|
69
69
|
},
|
|
70
70
|
]
|
|
71
71
|
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
// SPDX-License-Identifier: AGPL-3.0-or-later
|
|
2
|
+
// AllBlue - 理想之海
|
|
3
|
+
// Copyright (C) 2026 AllBlue Contributors
|
|
4
|
+
|
|
5
|
+
import { createLazyFileRoute } from '@tanstack/react-router'
|
|
6
|
+
import { DesktopCloudLogin } from '@/components/desktop/cloud-login'
|
|
7
|
+
import { DesktopConflictCenter } from '@/components/desktop/conflict-center'
|
|
8
|
+
import { DesktopSyncStatusCard } from '@/components/desktop/sync-status-card'
|
|
9
|
+
|
|
10
|
+
export const Route = createLazyFileRoute('/_nav/settings/sync')({
|
|
11
|
+
component: SyncSettingsPage,
|
|
12
|
+
})
|
|
13
|
+
|
|
14
|
+
function SyncSettingsPage() {
|
|
15
|
+
return (
|
|
16
|
+
<div className="flex max-w-3xl flex-col gap-6 p-6">
|
|
17
|
+
<div>
|
|
18
|
+
<h2 className="text-lg font-semibold">同步</h2>
|
|
19
|
+
<p className="text-sm text-muted-foreground">
|
|
20
|
+
本地优先存储,登录云端账号后可多端同步。断网时照常编辑,恢复后自动推送。
|
|
21
|
+
</p>
|
|
22
|
+
</div>
|
|
23
|
+
|
|
24
|
+
<section className="space-y-3 rounded-lg border p-4">
|
|
25
|
+
<h3 className="text-sm font-medium">云端账号</h3>
|
|
26
|
+
<DesktopCloudLogin />
|
|
27
|
+
</section>
|
|
28
|
+
|
|
29
|
+
<section className="space-y-3 rounded-lg border p-4">
|
|
30
|
+
<h3 className="text-sm font-medium">同步状态</h3>
|
|
31
|
+
<DesktopSyncStatusCard />
|
|
32
|
+
</section>
|
|
33
|
+
|
|
34
|
+
<section className="space-y-3 rounded-lg border p-4">
|
|
35
|
+
<h3 className="text-sm font-medium">冲突处理</h3>
|
|
36
|
+
<DesktopConflictCenter />
|
|
37
|
+
</section>
|
|
38
|
+
</div>
|
|
39
|
+
)
|
|
40
|
+
}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
// SPDX-License-Identifier: AGPL-3.0-or-later
|
|
2
|
+
// AllBlue - 理想之海
|
|
3
|
+
// Copyright (C) 2026 AllBlue Contributors
|
|
4
|
+
|
|
5
|
+
// 桌面同步设置页(迁移设计 §3.5/§3.7):云端账号登录桥 + 冲突中心。
|
|
6
|
+
// 仅桌面端可访问(beforeLoad 守卫复用 VITE_DEPLOY_TARGET,与 connection 页同口径)。
|
|
7
|
+
import { createFileRoute, redirect } from '@tanstack/react-router'
|
|
8
|
+
|
|
9
|
+
export const Route = createFileRoute('/_nav/settings/sync')({
|
|
10
|
+
beforeLoad: () => {
|
|
11
|
+
if (import.meta.env.VITE_DEPLOY_TARGET !== 'desktop') {
|
|
12
|
+
throw redirect({ to: '/settings' })
|
|
13
|
+
}
|
|
14
|
+
},
|
|
15
|
+
})
|
|
@@ -20,10 +20,9 @@
|
|
|
20
20
|
// 标题/指令 includes 匹配)、右簇「新建任务」;@container 行由 flex-col 直排
|
|
21
21
|
// 拿满宽(页面容器 h-full p-4 应用式,无需 min-w-0 包装)。数据来自 index.tsx
|
|
22
22
|
// beforeLoad context(Route.useRouteContext);AI 任务创建触发 CreateAiTaskDialog;
|
|
23
|
-
//
|
|
23
|
+
// 历史 sqlite 降级(ai.degraded)已随 Tauri 清退移除(迁移 P1)。Skeleton pending 由 index.tsx 承担。
|
|
24
24
|
import { useState } from "react";
|
|
25
25
|
import { createLazyFileRoute } from "@tanstack/react-router";
|
|
26
|
-
import { Alert, AlertDescription } from "@/components/ui/alert";
|
|
27
26
|
import { Button } from "@/components/ui/button";
|
|
28
27
|
import { Input } from "@/components/ui/input";
|
|
29
28
|
import {
|
|
@@ -47,7 +46,6 @@ function TasksIndexPage() {
|
|
|
47
46
|
const { assigned, ai } = Route.useRouteContext();
|
|
48
47
|
const [createOpen, setCreateOpen] = useState(false);
|
|
49
48
|
const [search, setSearch] = useState("");
|
|
50
|
-
const desktopDegraded = ai.degraded === true;
|
|
51
49
|
const filtered = useTaskFilter(search, assigned, ai.items);
|
|
52
50
|
|
|
53
51
|
return (
|
|
@@ -75,7 +73,6 @@ function TasksIndexPage() {
|
|
|
75
73
|
<Button
|
|
76
74
|
size="sm"
|
|
77
75
|
onClick={() => setCreateOpen(true)}
|
|
78
|
-
disabled={desktopDegraded}
|
|
79
76
|
>
|
|
80
77
|
<CREATE_ICON data-icon="inline-start" />
|
|
81
78
|
{m.tasks_create_new()}
|
|
@@ -87,16 +84,9 @@ function TasksIndexPage() {
|
|
|
87
84
|
<AssignedList result={filtered.assigned} searching={filtered.searching} />
|
|
88
85
|
</TabsContent>
|
|
89
86
|
<TabsContent value="ai" className="flex flex-col gap-3">
|
|
90
|
-
{desktopDegraded ? (
|
|
91
|
-
<Alert>
|
|
92
|
-
<AlertDescription>{m.tasks_ai_desktop_notice()}</AlertDescription>
|
|
93
|
-
</Alert>
|
|
94
|
-
) : null}
|
|
95
87
|
<AiTaskList
|
|
96
88
|
items={filtered.ai}
|
|
97
89
|
onRequestCreate={() => setCreateOpen(true)}
|
|
98
|
-
createDisabled={desktopDegraded}
|
|
99
|
-
runDisabled={desktopDegraded}
|
|
100
90
|
searching={filtered.searching}
|
|
101
91
|
/>
|
|
102
92
|
</TabsContent>
|
|
@@ -38,8 +38,12 @@ export const Route = createFileRoute('/api/billing-webhook')({
|
|
|
38
38
|
return new Response('Billing module unavailable', { status: 501 })
|
|
39
39
|
}
|
|
40
40
|
try {
|
|
41
|
-
await billing.handleWebhookEvent(rawBody, signature)
|
|
42
|
-
|
|
41
|
+
const result = await billing.handleWebhookEvent(rawBody, signature)
|
|
42
|
+
// 审计 M13:幂等命中的重投事件跳过幂等门外的邮件链路,防重复收据;
|
|
43
|
+
// 旧版 Pro 包无 alreadyProcessed 字段,按未命中处理(行为不变)
|
|
44
|
+
if (!result.alreadyProcessed) {
|
|
45
|
+
await sendBillingEmailForEvent(rawBody, signature, billing)
|
|
46
|
+
}
|
|
43
47
|
return new Response(JSON.stringify({ received: true }), {
|
|
44
48
|
status: 200,
|
|
45
49
|
headers: { 'Content-Type': 'application/json' },
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
// SPDX-License-Identifier: AGPL-3.0-or-later
|
|
2
|
+
// AllBlue - 理想之海
|
|
3
|
+
// Copyright (C) 2026 AllBlue Contributors
|
|
4
|
+
|
|
5
|
+
// bootstrap 端点(迁移设计 §3.4):返回当前水位 + 各表行数。首登快照拉取
|
|
6
|
+
// 按 (table, pk) 分页全量行(后续端点),完成后续走 last_seq = watermark 增量
|
|
7
|
+
// ——不依赖 change_log 从头回放(30 天滚动清理)。
|
|
8
|
+
import { createFileRoute } from "@tanstack/react-router"
|
|
9
|
+
import { getRequest } from "@tanstack/react-start/server"
|
|
10
|
+
import { getPrisma } from "@allbluecn/database/get-prisma"
|
|
11
|
+
import { requireAuth } from "@/server/auth-helpers"
|
|
12
|
+
import { resolveSyncScopes } from "@/server/sync/scopes"
|
|
13
|
+
import { SYNC_TABLES } from "@allbluecn/sync-core/registrations"
|
|
14
|
+
|
|
15
|
+
export const Route = createFileRoute("/api/sync/bootstrap")({
|
|
16
|
+
server: {
|
|
17
|
+
handlers: {
|
|
18
|
+
GET: async () => {
|
|
19
|
+
const session = await requireAuth(getRequest())
|
|
20
|
+
const prisma = await getPrisma()
|
|
21
|
+
|
|
22
|
+
const [{ seq }] = await prisma.$queryRawUnsafe<Array<{ seq: bigint }>>(
|
|
23
|
+
`SELECT COALESCE(MAX(seq), 0) AS seq FROM sync_change_log`,
|
|
24
|
+
)
|
|
25
|
+
const counts = await Promise.all(
|
|
26
|
+
SYNC_TABLES.map(async (reg) => {
|
|
27
|
+
const [r] = await prisma.$queryRawUnsafe<Array<{ c: bigint }>>(
|
|
28
|
+
`SELECT COUNT(*)::bigint AS c FROM ${reg.table}`,
|
|
29
|
+
)
|
|
30
|
+
return { name: reg.table, count: Number(r.c) }
|
|
31
|
+
}),
|
|
32
|
+
)
|
|
33
|
+
void resolveSyncScopes // scopes 解析在快照分页端点逐页执行(此处仅鉴权)
|
|
34
|
+
return Response.json({ watermarkSeq: Number(seq), tables: counts })
|
|
35
|
+
},
|
|
36
|
+
},
|
|
37
|
+
},
|
|
38
|
+
})
|