@allbluecn/web-app 0.22.4 → 0.23.1
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 +4 -14
- package/src/__tests__/integration/login-email-acceptance.test.ts +16 -0
- package/src/__tests__/story-view.test.ts +33 -1
- package/src/components/agents/__tests__/agent-bindings-tab.test.tsx +221 -0
- package/src/components/agents/__tests__/agents-page.test.tsx +284 -0
- package/src/components/agents/agent-bindings-tab.tsx +59 -45
- package/src/components/agents/agent-form-dialog.tsx +3 -3
- package/src/components/agents/agent-selector.tsx +2 -3
- package/src/components/agents/agents-page.tsx +66 -31
- package/src/components/agents/slash-skill-menu.tsx +2 -3
- package/src/components/auth/__tests__/session-guard.test.tsx +74 -0
- package/src/components/auth/session-guard.tsx +8 -0
- package/src/components/billing/login-prompt-dialog.tsx +1 -1
- package/src/components/billing/subscription-provider.tsx +2 -16
- package/src/components/bug/__tests__/peek-modes.test.tsx +8 -0
- package/src/components/bug/__tests__/subgroup-header.test.tsx +202 -40
- package/src/components/bug/peek-panel.tsx +5 -3
- package/src/components/bug/views/bug-list/group.tsx +12 -2
- package/src/components/bug/views/bug-list/index.tsx +94 -67
- package/src/components/command/command-palette.tsx +10 -9
- package/src/components/design/canvas/document/frame-custom-presets.ts +9 -1
- package/src/components/design/canvas/panels/toolbar.tsx +21 -22
- package/src/components/design/canvas/react/__tests__/canvas-context-load-echo.test.tsx +199 -0
- package/src/components/design/canvas/react/__tests__/hooks.test.tsx +17 -3
- package/src/components/design/canvas/react/canvas-context.tsx +47 -26
- package/src/components/design/canvas/react/hooks.ts +39 -34
- package/src/components/design/editor/layout/__tests__/collab-param-wiring.test.tsx +17 -0
- package/src/components/design/editor/layout/__tests__/context-menu.test.tsx +17 -1
- package/src/components/design/editor/layout/__tests__/no-page-save-toast.test.tsx +17 -0
- package/src/components/design/editor/layout/__tests__/persistence-restore.test.tsx +17 -1
- package/src/components/design/editor/layout/__tests__/ssr-localstorage-smoke.test.tsx +17 -1
- package/src/components/design/editor/layout/design-editor-layout.tsx +13 -2
- package/src/components/design/editor/layout/hooks/use-design-auto-save.ts +3 -19
- package/src/components/devtools/devtools-panel.tsx +56 -0
- package/src/components/forms/__tests__/create-app-form.test.tsx +131 -0
- package/src/components/forms/app-field-error.tsx +21 -1
- package/src/components/forms/app-field.tsx +8 -8
- package/src/components/forms/app-submit.tsx +12 -9
- package/src/components/forms/create-app-form.tsx +124 -0
- package/src/components/forms/index.ts +2 -3
- package/src/components/harness/__tests__/gallery-behavior.test.tsx +37 -1
- package/src/components/harness/__tests__/harness-workbench-first-send.test.tsx +4 -1
- package/src/components/harness/__tests__/message-actions.test.tsx +7 -6
- package/src/components/harness/__tests__/use-video-generation.test.tsx +165 -0
- package/src/components/harness/ai-chat-history/index.tsx +5 -3
- package/src/components/harness/gallery/gallery-card.tsx +57 -35
- package/src/components/harness/gallery/gallery-grid.tsx +32 -15
- package/src/components/harness/gallery/gallery-types.ts +19 -0
- package/src/components/harness/gallery/gallery-video-card.tsx +54 -0
- package/src/components/harness/gallery/types.ts +2 -0
- package/src/components/harness/gallery/use-video-generation.ts +95 -0
- package/src/components/harness/harness-workbench-page.tsx +2 -3
- package/src/components/harness/message-actions.tsx +5 -3
- package/src/components/hotkeys/shortcuts-panel.tsx +28 -13
- package/src/components/iteration/__tests__/burndown-chart.test.tsx +118 -0
- package/src/components/iteration/burndown-chart.tsx +54 -23
- package/src/components/knowledge/editor/__tests__/knowledge-doc-editor-collab.test.tsx +96 -0
- package/src/components/knowledge/editor/knowledge-doc-editor.tsx +56 -1
- package/src/components/knowledge/editor/mindmap-doc-editor.tsx +12 -0
- package/src/components/knowledge/editor/use-auto-save-channels.ts +3 -1
- package/src/components/layout/sidebar-03/__tests__/nav-workspace.test.tsx +0 -4
- package/src/components/layout/sidebar-03/nav-knowledge.tsx +11 -11
- package/src/components/layout/sidebar-03/nav-main.tsx +12 -15
- package/src/components/layout/sidebar-03/nav-notifications.tsx +5 -8
- package/src/components/layout/sidebar-03/nav-workspace.tsx +11 -9
- package/src/components/notifications/__tests__/settings-notifications.test.tsx +158 -0
- package/src/components/notifications/settings-notifications.tsx +37 -13
- package/src/components/notifications/team-notifications.tsx +10 -14
- package/src/components/settings/personal-team/account/__tests__/account-client.test.tsx +170 -0
- package/src/components/settings/personal-team/account/account-client.tsx +44 -7
- package/src/components/settings/personal-team/team/team-client.tsx +17 -19
- package/src/components/shared-kit/list-kit/__tests__/frozen-header.test.ts +210 -41
- package/src/components/shared-kit/list-kit/frozen-header.ts +134 -21
- package/src/components/shared-kit/list-kit/kanban/frozen-header.ts +20 -27
- package/src/components/story/__tests__/peek-panel-patch-sync.test.tsx +8 -0
- package/src/components/story/__tests__/story-list-table.test.tsx +214 -0
- package/src/components/story/columns.tsx +11 -2
- package/src/components/story/peek-panel.tsx +4 -2
- package/src/components/story/story-list-table.tsx +16 -1
- package/src/components/story/views/story-list/__tests__/frozen-headers.test.tsx +186 -0
- package/src/components/story/views/story-list/group.tsx +12 -1
- package/src/components/story/views/story-list/index.tsx +101 -68
- package/src/components/testcase/__tests__/case-row.test.tsx +134 -2
- package/src/components/testcase/__tests__/peek-panel.test.tsx +8 -0
- package/src/components/testcase/__tests__/step-editor.test.tsx +106 -0
- package/src/components/testcase/list/grouped-list.tsx +50 -22
- package/src/components/testcase/peek-panel.tsx +7 -4
- package/src/components/testcase/step-editor.tsx +196 -150
- package/src/components/tiptap/notion-like/editor-extensions.ts +0 -3
- package/src/components/tiptap/notion-like/notion-like-editor-header.tsx +1 -31
- package/src/components/tiptap/notion-like/notion-like-editor.tsx +32 -1
- package/src/components/workspace/__tests__/dialogs/create-workspace-dialog.test.tsx +2 -28
- package/src/components/workspace/__tests__/dialogs/edit-workspace-dialog.test.tsx +2 -28
- package/src/components/workspace/dialogs/create-workspace-dialog.tsx +45 -43
- package/src/components/workspace/dialogs/edit-workspace-dialog.tsx +38 -36
- package/src/design-engine/engine/engine-decor.ts +2 -0
- package/src/design-engine/engine/engine-path.ts +2 -0
- package/src/hooks/__tests__/use-unsaved-guard.test.tsx +180 -0
- package/src/hooks/use-notifications.ts +9 -16
- package/src/hooks/use-unsaved-guard.tsx +87 -0
- package/src/lib/__tests__/pacer.test.ts +33 -96
- package/src/lib/__tests__/query-defaults.test.ts +169 -0
- package/src/lib/__tests__/query-global-error.test.ts +256 -0
- package/src/lib/anyhub/anyhub-store.ts +2 -2
- package/src/lib/changelog/sdk-versions.ts +2 -10
- package/src/lib/collab/presence-store.ts +5 -5
- package/src/lib/collab/use-presence-list-refresh.ts +2 -2
- package/src/lib/collab/use-share-presence.ts +2 -2
- package/src/lib/collections/query-keys.ts +7 -2
- package/src/lib/commands/__tests__/command-palette-state.test.ts +12 -14
- package/src/lib/commands/__tests__/registry.test.ts +6 -3
- package/src/lib/commands/command-palette-state.ts +8 -31
- package/src/lib/hotkeys/__tests__/registry.test.ts +71 -18
- package/src/lib/hotkeys/registry.ts +188 -85
- package/src/lib/hotkeys/types.ts +1 -13
- package/src/lib/pacer.ts +1 -79
- package/src/lib/queries/README.md +67 -0
- package/src/lib/queries/__tests__/agents-queries.test.ts +101 -0
- package/src/lib/queries/__tests__/compliance-queries.test.ts +136 -0
- package/src/lib/queries/__tests__/notifications-queries.test.ts +175 -0
- package/src/lib/queries/__tests__/team-queries.test.ts +87 -0
- package/src/lib/queries/agents.ts +40 -0
- package/src/lib/queries/compliance.ts +69 -0
- package/src/lib/queries/notifications.ts +63 -0
- package/src/lib/queries/team.ts +39 -0
- package/src/lib/query-defaults.ts +8 -0
- package/src/lib/query-global-error.ts +128 -0
- package/src/lib/remote-auth-client.ts +16 -0
- package/src/paraglide/README.md +1 -1
- package/src/paraglide/messages/_index.d.ts +11 -0
- package/src/paraglide/messages/_index.js +5659 -88285
- package/src/paraglide/messages/common_error_generic.d.ts +16 -0
- package/src/paraglide/messages/common_error_generic.js +29 -0
- package/src/paraglide/messages/common_unsaved_body.d.ts +16 -0
- package/src/paraglide/messages/common_unsaved_body.js +29 -0
- package/src/paraglide/messages/common_unsaved_leave.d.ts +16 -0
- package/src/paraglide/messages/common_unsaved_leave.js +29 -0
- package/src/paraglide/messages/common_unsaved_stay.d.ts +16 -0
- package/src/paraglide/messages/common_unsaved_stay.js +29 -0
- package/src/paraglide/messages/common_unsaved_title.d.ts +16 -0
- package/src/paraglide/messages/common_unsaved_title.js +29 -0
- package/src/paraglide/messages/gallery_videofailed1.d.ts +17 -0
- package/src/paraglide/messages/gallery_videofailed1.js +30 -0
- package/src/paraglide/messages/gallery_videogenerating1.d.ts +17 -0
- package/src/paraglide/messages/gallery_videogenerating1.js +30 -0
- package/src/paraglide/messages/gallery_videomissingprompt2.d.ts +17 -0
- package/src/paraglide/messages/gallery_videomissingprompt2.js +30 -0
- package/src/paraglide/messages/gallery_videoprogress1.d.ts +19 -0
- package/src/paraglide/messages/gallery_videoprogress1.js +30 -0
- package/src/paraglide/messages/gallery_videostop1.d.ts +17 -0
- package/src/paraglide/messages/gallery_videostop1.js +30 -0
- package/src/paraglide/messages/story_table_resizecolumn1.d.ts +17 -0
- package/src/paraglide/messages/story_table_resizecolumn1.js +30 -0
- package/src/providers/index.tsx +5 -50
- package/src/routeTree.gen.ts +21 -0
- package/src/router.tsx +21 -8
- package/src/routes/__root.tsx +2 -1
- package/src/routes/__tests__/-edition-routing.test.tsx +6 -1
- package/src/routes/_login/forgot-password/route.lazy.tsx +7 -6
- package/src/routes/_login/login/route.lazy.tsx +10 -9
- package/src/routes/_login/register/route.lazy.tsx +19 -18
- package/src/routes/_login/reset-password/route.lazy.tsx +10 -9
- package/src/routes/_nav/knowledge/compliance/$id.lazy.tsx +9 -12
- package/src/routes/_nav/knowledge/compliance/index.lazy.tsx +16 -13
- package/src/routes/_nav/knowledge/laws/$id.lazy.tsx +1 -1
- package/src/routes/_nav/notifications/route.tsx +6 -16
- package/src/routes/_nav/settings/-settings-tabs.tsx +9 -12
- package/src/routes/api/generate/__tests__/media.test.ts +378 -0
- package/src/routes/api/generate/media.ts +179 -0
- package/src/server/__tests__/agent-client-graph.test.ts +0 -1
- package/src/server/__tests__/agent-crud.test.ts +37 -4
- package/src/server/__tests__/bug-groups-two-level.test.ts +34 -1
- package/src/server/__tests__/chat-conversations.test.ts +37 -4
- package/src/server/__tests__/chat-list-messages.test.ts +40 -7
- package/src/server/__tests__/csv-export.test.ts +36 -3
- package/src/server/__tests__/desktop-bootstrap.test.ts +189 -0
- package/src/server/__tests__/remote-auth.test.ts +72 -0
- package/src/server/__tests__/skill-crud.test.ts +37 -4
- package/src/server/__tests__/sso-domain.test.ts +1 -1
- package/src/server/__tests__/sso-rate-limit-singleton.test.ts +123 -0
- package/src/server/__tests__/task-serverfn-crud.test.ts +35 -2
- package/src/server/__tests__/task-serverfn-queries.test.ts +35 -2
- package/src/server/__tests__/testcase-board.test.ts +38 -5
- package/src/server/__tests__/testcase-bulk.test.ts +38 -5
- package/src/server/__tests__/testcase-list-scope.test.ts +38 -5
- package/src/server/ai-gateway/__tests__/ai-output-guard.test.ts +126 -2
- package/src/server/ai-gateway/__tests__/chat-stream-builder-code-mode.test.ts +4 -0
- package/src/server/ai-gateway/__tests__/chat-stream-builder-memory.test.ts +4 -0
- package/src/server/ai-gateway/__tests__/chat-stream-builder-sandbox.test.ts +4 -0
- package/src/server/ai-gateway/__tests__/chat-stream-builder-skills.test.ts +4 -0
- package/src/server/ai-gateway/__tests__/pgvector-memory-adapter.test.ts +30 -0
- package/src/server/ai-gateway/__tests__/pgvector-memory-conformance.test.ts +92 -0
- package/src/server/ai-gateway/__tests__/source-mode.test.ts +49 -8
- package/src/server/ai-gateway/ai-output-guard.ts +50 -2
- package/src/server/ai-gateway/chat-stream-builder.ts +3 -0
- package/src/server/ai-gateway/media/index.ts +36 -29
- package/src/server/ai-gateway/media/trim-input.ts +52 -0
- package/src/server/ai-gateway/memory/pgvector-adapter.ts +27 -13
- package/src/server/ai-gateway/sandbox/__tests__/harness-sandbox.test.ts +252 -41
- package/src/server/ai-gateway/sandbox/harness-sandbox.ts +6 -67
- package/src/server/ai-gateway/source-mode.ts +24 -8
- package/src/server/desktop-bootstrap.ts +74 -0
- package/src/server/lib/__tests__/rate-limit.test.ts +0 -1
- package/src/server/lib/rate-limit.ts +0 -2
- package/src/server/middlewares/__tests__/auth-context.test.ts +156 -0
- package/src/server/middlewares/auth-context.ts +62 -0
- package/src/server/remote-auth.ts +58 -31
- package/src/server/serverFns/__tests__/ai-hosted-models.test.ts +47 -15
- package/src/server/serverFns/__tests__/ai-source-mode.test.ts +45 -15
- package/src/server/serverFns/__tests__/billing.test.ts +37 -2
- package/src/server/serverFns/__tests__/collab-snapshot.test.ts +41 -14
- package/src/server/serverFns/__tests__/collab.test.ts +41 -14
- package/src/server/serverFns/__tests__/compliance.test.ts +33 -1
- package/src/server/serverFns/__tests__/email-verification.test.ts +35 -1
- package/src/server/serverFns/__tests__/knowledge-breadcrumb.test.ts +46 -6
- package/src/server/serverFns/__tests__/knowledge-delete.test.ts +42 -14
- package/src/server/serverFns/__tests__/knowledge-kb-projects.test.ts +46 -6
- package/src/server/serverFns/__tests__/knowledge-public-compliance.test.ts +36 -2
- package/src/server/serverFns/__tests__/knowledge-readable-kb.test.ts +42 -10
- package/src/server/serverFns/__tests__/knowledge-search.test.ts +45 -9
- package/src/server/serverFns/__tests__/legal-code-canonical.test.ts +36 -2
- package/src/server/serverFns/__tests__/link-preview.test.ts +38 -4
- package/src/server/serverFns/__tests__/notifications-list.test.ts +36 -3
- package/src/server/serverFns/__tests__/ownership-merge.test.ts +38 -4
- package/src/server/serverFns/__tests__/project-delete-transaction.test.ts +39 -2
- package/src/server/serverFns/__tests__/project-kb.test.ts +34 -1
- package/src/server/serverFns/__tests__/project-member-idor.test.ts +34 -1
- package/src/server/serverFns/__tests__/project-team-assign.test.ts +34 -1
- package/src/server/serverFns/__tests__/read-write-merge.test.ts +38 -4
- package/src/server/serverFns/__tests__/story-comments.test.ts +38 -4
- package/src/server/serverFns/__tests__/story-crud-archive-detail.test.ts +38 -4
- package/src/server/serverFns/__tests__/story-crud-labels-users.test.ts +37 -3
- package/src/server/serverFns/__tests__/story-crud.test.ts +36 -3
- package/src/server/serverFns/__tests__/story-links.test.ts +38 -4
- package/src/server/serverFns/__tests__/story-reactions.test.ts +38 -4
- package/src/server/serverFns/__tests__/story-tree.test.ts +38 -4
- package/src/server/serverFns/__tests__/team-accept.test.ts +34 -1
- package/src/server/serverFns/__tests__/team-invitation.test.ts +34 -1
- package/src/server/serverFns/__tests__/team-join-request.test.ts +34 -1
- package/src/server/serverFns/__tests__/team-members.test.ts +34 -1
- package/src/server/serverFns/__tests__/team-ownership-merge.test.ts +34 -1
- package/src/server/serverFns/__tests__/update-bug-guard.test.ts +37 -3
- package/src/server/serverFns/__tests__/update-document-guard.test.ts +38 -4
- package/src/server/serverFns/__tests__/update-page-guard.test.ts +40 -4
- package/src/server/serverFns/__tests__/update-seats.test.ts +33 -1
- package/src/server/serverFns/__tests__/update-story-guard.test.ts +36 -3
- package/src/server/serverFns/__tests__/update-testcase-guard.test.ts +37 -3
- package/src/server/serverFns/__tests__/workspace-kb-idor.test.ts +36 -2
- package/src/server/serverFns/__tests__/workspace-kb.test.ts +36 -2
- package/src/server/serverFns/__tests__/workspace.test.ts +34 -1
- package/src/server/serverFns/activity.ts +10 -14
- package/src/server/serverFns/agents/agent-crud.ts +16 -15
- package/src/server/serverFns/agents/bindings.ts +12 -13
- package/src/server/serverFns/agents/skill-crud.ts +16 -15
- package/src/server/serverFns/ai/code-mode-readiness.ts +3 -4
- package/src/server/serverFns/ai/search-capability.ts +3 -4
- package/src/server/serverFns/anyhub/app.ts +10 -14
- package/src/server/serverFns/anyhub/index.ts +7 -10
- package/src/server/serverFns/anyhub/install.ts +4 -4
- package/src/server/serverFns/anyhub/permissions.ts +10 -14
- package/src/server/serverFns/anyhub/proxy.ts +4 -6
- package/src/server/serverFns/auth/email-verification.ts +4 -5
- package/src/server/serverFns/auth/session.ts +9 -0
- package/src/server/serverFns/billing.ts +18 -28
- package/src/server/serverFns/blob-upload.ts +6 -9
- package/src/server/serverFns/bug/__tests__/bug-access-tokens.test.ts +34 -1
- package/src/server/serverFns/bug/__tests__/bug-activities.test.ts +34 -1
- package/src/server/serverFns/bug/__tests__/bug-comments.test.ts +34 -1
- package/src/server/serverFns/bug/__tests__/bug-crud.test.ts +34 -1
- package/src/server/serverFns/bug/__tests__/bug-fix.test.ts +34 -1
- package/src/server/serverFns/bug/__tests__/bug-groups.test.ts +34 -1
- package/src/server/serverFns/bug/__tests__/bug-reactions.test.ts +34 -1
- package/src/server/serverFns/bug/__tests__/bug-reorder.test.ts +39 -5
- package/src/server/serverFns/bug/__tests__/bug-repro.test.ts +34 -1
- package/src/server/serverFns/bug/__tests__/bug-story.test.ts +34 -1
- package/src/server/serverFns/bug/__tests__/bug-webhooks.test.ts +34 -1
- package/src/server/serverFns/bug/bug-access-tokens.ts +16 -22
- package/src/server/serverFns/bug/bug-activities.ts +4 -6
- package/src/server/serverFns/bug/bug-collect-tokens.ts +13 -18
- package/src/server/serverFns/bug/bug-comments.ts +13 -18
- package/src/server/serverFns/bug/bug-crud/detail.ts +10 -14
- package/src/server/serverFns/bug/bug-crud.ts +28 -38
- package/src/server/serverFns/bug/bug-display-options.ts +8 -11
- package/src/server/serverFns/bug/bug-export.ts +5 -7
- package/src/server/serverFns/bug/bug-fix.ts +10 -14
- package/src/server/serverFns/bug/bug-groups.ts +10 -14
- package/src/server/serverFns/bug/bug-reactions.ts +10 -14
- package/src/server/serverFns/bug/bug-reorder.ts +4 -6
- package/src/server/serverFns/bug/bug-repro.ts +8 -11
- package/src/server/serverFns/bug/bug-story-bulk.ts +13 -18
- package/src/server/serverFns/bug/bug-story.ts +10 -14
- package/src/server/serverFns/bug/bug-views.ts +12 -18
- package/src/server/serverFns/bug/bug-webhooks.ts +13 -18
- package/src/server/serverFns/bug/test-bug-confirm.ts +7 -10
- package/src/server/serverFns/changelog/__tests__/fetch.test.ts +40 -1
- package/src/server/serverFns/changelog/fetch.ts +4 -6
- package/src/server/serverFns/chat/conversations.ts +17 -28
- package/src/server/serverFns/chat/list-messages.ts +4 -7
- package/src/server/serverFns/collab-presence.ts +11 -13
- package/src/server/serverFns/collab-snapshot.ts +6 -7
- package/src/server/serverFns/collab.ts +7 -7
- package/src/server/serverFns/compliance.ts +8 -8
- package/src/server/serverFns/design/__tests__/comments.test.ts +54 -10
- package/src/server/serverFns/design/__tests__/designs.test.ts +39 -16
- package/src/server/serverFns/design/__tests__/page-versions.test.ts +52 -14
- package/src/server/serverFns/design/__tests__/shares-password.test.ts +44 -14
- package/src/server/serverFns/design/__tests__/shares.test.ts +44 -14
- package/src/server/serverFns/design/__tests__/versions.test.ts +44 -14
- package/src/server/serverFns/design/ai/__tests__/agent-conversations.test.ts +50 -21
- package/src/server/serverFns/design/ai/__tests__/providers.test.ts +42 -8
- package/src/server/serverFns/design/ai/agent-conversations.ts +19 -26
- package/src/server/serverFns/design/ai/fill-annotation.ts +5 -7
- package/src/server/serverFns/design/ai/generate-prototype.ts +5 -7
- package/src/server/serverFns/design/ai/hosted-models.ts +4 -5
- package/src/server/serverFns/design/ai/providers.ts +30 -39
- package/src/server/serverFns/design/ai/source-mode.ts +10 -12
- package/src/server/serverFns/design/comments.ts +14 -13
- package/src/server/serverFns/design/designs.ts +13 -19
- package/src/server/serverFns/design/page-versions.ts +17 -18
- package/src/server/serverFns/design/pages.ts +17 -18
- package/src/server/serverFns/design/reviews.ts +8 -9
- package/src/server/serverFns/design/shares-password.ts +13 -19
- package/src/server/serverFns/design/shares.ts +22 -31
- package/src/server/serverFns/design/versions.ts +8 -9
- package/src/server/serverFns/harness/__tests__/attach-prototype.spec.ts +52 -2
- package/src/server/serverFns/harness/__tests__/attach-to-kb.spec.ts +52 -2
- package/src/server/serverFns/harness/__tests__/attach-to-story-ssrf.spec.ts +52 -2
- package/src/server/serverFns/harness/__tests__/attach-to-story.spec.ts +52 -2
- package/src/server/serverFns/harness/__tests__/cancel-run.test.ts +40 -15
- package/src/server/serverFns/harness/__tests__/extract-attachment.spec.ts +52 -2
- package/src/server/serverFns/harness/__tests__/gallery.spec.ts +76 -12
- package/src/server/serverFns/harness/__tests__/github-workspace.spec.ts +38 -6
- package/src/server/serverFns/harness/__tests__/media-prototype.spec.ts +50 -6
- package/src/server/serverFns/harness/__tests__/media.spec.ts +55 -11
- package/src/server/serverFns/harness/__tests__/sandbox-policy.test.ts +41 -16
- package/src/server/serverFns/harness/__tests__/workspace-files.test.ts +41 -16
- package/src/server/serverFns/harness/attach-prototype.ts +4 -4
- package/src/server/serverFns/harness/attach-to-kb.ts +4 -4
- package/src/server/serverFns/harness/attach-to-story.ts +4 -4
- package/src/server/serverFns/harness/cancel-run.ts +4 -6
- package/src/server/serverFns/harness/extract-attachment.ts +3 -4
- package/src/server/serverFns/harness/gallery.ts +19 -23
- package/src/server/serverFns/harness/github-workspace.ts +14 -21
- package/src/server/serverFns/harness/media.ts +18 -117
- package/src/server/serverFns/harness/sandbox-policy.ts +11 -10
- package/src/server/serverFns/harness/search-mention-candidates.ts +4 -6
- package/src/server/serverFns/harness/workspace-files.ts +19 -26
- package/src/server/serverFns/iteration/__tests__/iteration-auto-schedule.test.ts +35 -3
- package/src/server/serverFns/iteration/__tests__/iteration-crud.test.ts +35 -3
- package/src/server/serverFns/iteration/__tests__/iteration-stories.test.ts +35 -3
- package/src/server/serverFns/iteration/__tests__/iteration-transfer.test.ts +35 -3
- package/src/server/serverFns/iteration/iteration-auto-schedule.ts +7 -10
- package/src/server/serverFns/iteration/iteration-burndown.ts +4 -6
- package/src/server/serverFns/iteration/iteration-crud.ts +26 -35
- package/src/server/serverFns/iteration/iteration-stories.ts +10 -14
- package/src/server/serverFns/iteration/iteration-transfer.ts +4 -6
- package/src/server/serverFns/knowledge/public/bookmarks/categories.ts +11 -15
- package/src/server/serverFns/knowledge/public/bookmarks/create.ts +4 -6
- package/src/server/serverFns/knowledge/public/bookmarks/delete.ts +5 -7
- package/src/server/serverFns/knowledge/public/bookmarks/detail.ts +4 -6
- package/src/server/serverFns/knowledge/public/bookmarks/favorite.ts +4 -6
- package/src/server/serverFns/knowledge/public/bookmarks/list.ts +4 -6
- package/src/server/serverFns/knowledge/public/bookmarks/refresh-favicon.ts +4 -6
- package/src/server/serverFns/knowledge/public/bookmarks/share.ts +4 -6
- package/src/server/serverFns/knowledge/public/bookmarks/sync-github.ts +5 -7
- package/src/server/serverFns/knowledge/public/bookmarks/unshare.ts +4 -6
- package/src/server/serverFns/knowledge/public/bookmarks/update.ts +6 -8
- package/src/server/serverFns/knowledge/public/compliance/create.ts +4 -6
- package/src/server/serverFns/knowledge/public/compliance/delete.ts +5 -7
- package/src/server/serverFns/knowledge/public/compliance/detail.ts +4 -6
- package/src/server/serverFns/knowledge/public/compliance/list.ts +4 -6
- package/src/server/serverFns/knowledge/public/compliance/share.ts +4 -6
- package/src/server/serverFns/knowledge/public/compliance/unshare.ts +4 -6
- package/src/server/serverFns/knowledge/public/compliance/update.ts +5 -7
- package/src/server/serverFns/knowledge/public/dictionary/create.ts +4 -6
- package/src/server/serverFns/knowledge/public/dictionary/delete.ts +5 -7
- package/src/server/serverFns/knowledge/public/dictionary/detail.ts +4 -6
- package/src/server/serverFns/knowledge/public/dictionary/list.ts +4 -6
- package/src/server/serverFns/knowledge/public/dictionary/share.ts +4 -6
- package/src/server/serverFns/knowledge/public/dictionary/unshare.ts +4 -6
- package/src/server/serverFns/knowledge/public/dictionary/update.ts +5 -7
- package/src/server/serverFns/knowledge/public/entity-tags.ts +4 -6
- package/src/server/serverFns/knowledge/public/favorite.ts +7 -10
- package/src/server/serverFns/knowledge/public/legal/create.ts +4 -6
- package/src/server/serverFns/knowledge/public/legal/delete.ts +5 -7
- package/src/server/serverFns/knowledge/public/legal/detail.ts +4 -6
- package/src/server/serverFns/knowledge/public/legal/list.ts +4 -6
- package/src/server/serverFns/knowledge/public/legal/share.ts +4 -6
- package/src/server/serverFns/knowledge/public/legal/unshare.ts +4 -6
- package/src/server/serverFns/knowledge/public/legal/update.ts +5 -7
- package/src/server/serverFns/knowledge-index.ts +12 -16
- package/src/server/serverFns/knowledge.ts +50 -67
- package/src/server/serverFns/notifications.ts +25 -34
- package/src/server/serverFns/plugins/harness-plugins.ts +16 -23
- package/src/server/serverFns/project/module-overview.ts +7 -10
- package/src/server/serverFns/project.ts +48 -68
- package/src/server/serverFns/references/create.ts +4 -6
- package/src/server/serverFns/references/resolve.ts +4 -6
- package/src/server/serverFns/references/search.ts +4 -6
- package/src/server/serverFns/share/design/[designId]/events.ts +4 -6
- package/src/server/serverFns/sso.ts +1 -1
- package/src/server/serverFns/story/__tests__/bulk.test.ts +34 -1
- package/src/server/serverFns/story/__tests__/story-assoc.test.ts +34 -1
- package/src/server/serverFns/story/__tests__/story-attachments.test.ts +34 -1
- package/src/server/serverFns/story/__tests__/story-crud-date-key.test.ts +42 -17
- package/src/server/serverFns/story/__tests__/story-dependencies.test.ts +34 -1
- package/src/server/serverFns/story/__tests__/story-gantt-deps.test.ts +34 -1
- package/src/server/serverFns/story/__tests__/story-groups.test.ts +34 -1
- package/src/server/serverFns/story/__tests__/story-read-path-authz.test.ts +40 -4
- package/src/server/serverFns/story/__tests__/story-search.test.ts +34 -1
- package/src/server/serverFns/story/__tests__/story-transfer.test.ts +34 -1
- package/src/server/serverFns/story/link-preview.ts +5 -7
- package/src/server/serverFns/story/story-assoc.ts +28 -38
- package/src/server/serverFns/story/story-attachments.ts +7 -10
- package/src/server/serverFns/story/story-children.ts +4 -6
- package/src/server/serverFns/story/story-comments.ts +13 -18
- package/src/server/serverFns/story/story-crud/activities.ts +4 -6
- package/src/server/serverFns/story/story-crud/archive.ts +7 -10
- package/src/server/serverFns/story/story-crud/bulk.ts +10 -14
- package/src/server/serverFns/story/story-crud/detail.ts +7 -10
- package/src/server/serverFns/story/story-crud/label-suggest.ts +4 -6
- package/src/server/serverFns/story/story-crud/labels.ts +6 -9
- package/src/server/serverFns/story/story-crud/user-brief.ts +4 -6
- package/src/server/serverFns/story/story-crud.ts +13 -18
- package/src/server/serverFns/story/story-dependencies.ts +16 -22
- package/src/server/serverFns/story/story-groups.ts +10 -14
- package/src/server/serverFns/story/story-links.ts +13 -18
- package/src/server/serverFns/story/story-reactions.ts +13 -18
- package/src/server/serverFns/story/story-search.ts +7 -10
- package/src/server/serverFns/story/story-transfer.ts +10 -14
- package/src/server/serverFns/story/story-tree.ts +7 -10
- package/src/server/serverFns/story-display-options.ts +7 -8
- package/src/server/serverFns/story-view.ts +12 -18
- package/src/server/serverFns/tasks/task-crud.ts +13 -17
- package/src/server/serverFns/tasks/task-queries.ts +12 -18
- package/src/server/serverFns/team.ts +46 -66
- package/src/server/serverFns/testcase/__tests__/automation.test.ts +38 -5
- package/src/server/serverFns/testcase/__tests__/evidence-upload.test.ts +37 -3
- package/src/server/serverFns/testcase/__tests__/generation.test.ts +38 -5
- package/src/server/serverFns/testcase/__tests__/plans.test.ts +36 -3
- package/src/server/serverFns/testcase/__tests__/regression.test.ts +36 -3
- package/src/server/serverFns/testcase/__tests__/run-cases.test.ts +36 -3
- package/src/server/serverFns/testcase/__tests__/runs.test.ts +36 -3
- package/src/server/serverFns/testcase/__tests__/stats.test.ts +36 -3
- package/src/server/serverFns/testcase/__tests__/testcase-board.test.ts +39 -5
- package/src/server/serverFns/testcase/__tests__/testcase-crud.test.ts +36 -3
- package/src/server/serverFns/testcase/__tests__/testcase-folders.test.ts +36 -3
- package/src/server/serverFns/testcase/__tests__/testcase-groups.test.ts +38 -5
- package/src/server/serverFns/testcase/automation.ts +13 -17
- package/src/server/serverFns/testcase/bulk.ts +10 -14
- package/src/server/serverFns/testcase/evidence-upload.ts +5 -7
- package/src/server/serverFns/testcase/generation.ts +10 -13
- package/src/server/serverFns/testcase/plans.ts +23 -31
- package/src/server/serverFns/testcase/regression.ts +7 -10
- package/src/server/serverFns/testcase/run-cases.ts +13 -18
- package/src/server/serverFns/testcase/runs.ts +13 -18
- package/src/server/serverFns/testcase/stats.ts +13 -18
- package/src/server/serverFns/testcase/testcase-activities.ts +4 -6
- package/src/server/serverFns/testcase/testcase-board.ts +4 -6
- package/src/server/serverFns/testcase/testcase-crud.ts +20 -27
- package/src/server/serverFns/testcase/testcase-display-options.ts +8 -11
- package/src/server/serverFns/testcase/testcase-export.ts +5 -7
- package/src/server/serverFns/testcase/testcase-filter-views.ts +12 -18
- package/src/server/serverFns/testcase/testcase-folders.ts +16 -22
- package/src/server/serverFns/testcase/testcase-groups.ts +4 -6
- package/src/server/serverFns/testcase/testcase-reorder.ts +4 -6
- package/src/server/serverFns/translation.ts +4 -6
- package/src/server/serverFns/user/avatar.ts +4 -6
- package/src/server/serverFns/user/settings.ts +4 -6
- package/src/server/serverFns/user/update-locale.ts +4 -6
- package/src/server/serverFns/workspace-kb.ts +26 -35
- package/src/server/serverFns/workspace.ts +43 -59
- package/src/server/serverFns/ws.ts +4 -6
- package/src/server/serverfn-public-allowlist.ts +117 -0
- package/src/server/story/types.ts +0 -1
- package/src/server/sync/__tests__/scopes.test.ts +64 -0
- package/src/server/sync/scopes.ts +7 -0
- package/src/server/testcase/__tests__/auto-bug.test.ts +44 -12
- package/src/__tests__/bench/baselines/format-timestamp.json +0 -44
- package/src/__typeprobe__.d.ts +0 -4
- package/src/components/forms/app-form-dialog.tsx +0 -126
- package/src/components/forms/hooks/use-form-submit.ts +0 -57
- package/src/components/forms/types.ts +0 -34
- package/src/components/harness/code/workspace-picker.tsx +0 -239
- package/src/components/tiptap/extensions/local-file/insert-local-file.ts +0 -35
- package/src/components/tiptap/extensions/local-file/local-file-node.ts +0 -71
- package/src/devframe-docks/ai-chat-iframe.tsx +0 -29
- package/src/devframe-docks/session-iframe.tsx +0 -90
- package/src/lib/__tests__/desktop-detect.test.ts +0 -19
- package/src/lib/collections/index.ts +0 -22
- package/src/lib/collections/knowledge/index.ts +0 -18
- package/src/lib/collections/knowledge/knowledge-bases-collection.ts +0 -34
- package/src/lib/collections/reference/bookmark-categories-collection.ts +0 -31
- package/src/lib/collections/reference/labels-collection.ts +0 -31
- package/src/lib/collections/reference/projects-collection.ts +0 -31
- package/src/lib/collections/reference/users-brief-collection.ts +0 -35
- package/src/lib/collections/reference/workspaces-collection.ts +0 -34
- package/src/lib/desktop-detect.ts +0 -29
- package/src/paraglide/messages/en.js +0 -28260
- package/src/paraglide/messages/zh.js +0 -28258
|
@@ -64,6 +64,18 @@ vi.mock("@allbluecn/database", () => ({
|
|
|
64
64
|
|
|
65
65
|
import { InMemoryRunStore } from "@tanstack/ai"
|
|
66
66
|
import { InMemoryLockStore } from "@tanstack/ai/locks"
|
|
67
|
+
import {
|
|
68
|
+
InMemorySandboxCheckpointStore,
|
|
69
|
+
SandboxCheckpointConflictError,
|
|
70
|
+
SandboxCheckpointDuplicateIdError,
|
|
71
|
+
SandboxCheckpointInvalidEntryError,
|
|
72
|
+
SandboxCheckpointInvalidIdError,
|
|
73
|
+
SandboxCheckpointNotHeadError,
|
|
74
|
+
SandboxCheckpointParentMismatchError,
|
|
75
|
+
SandboxCheckpointWriterConflictError,
|
|
76
|
+
SandboxCheckpointWriterLostError,
|
|
77
|
+
type SandboxCheckpoint,
|
|
78
|
+
} from "@tanstack/ai-sandbox"
|
|
67
79
|
import { buildSandboxMiddleware } from "../harness-sandbox"
|
|
68
80
|
|
|
69
81
|
const RUNS = new InMemoryRunStore()
|
|
@@ -362,14 +374,7 @@ describe("snapshots messages.loadThread 与 checkpoint store(审计 A3x-2)",
|
|
|
362
374
|
function snapshotStoresWithCheckpoints() {
|
|
363
375
|
return (mocks.withSandbox.mock.calls[0][1] as {
|
|
364
376
|
snapshots?: {
|
|
365
|
-
checkpoints?:
|
|
366
|
-
get: (id: string) => Promise<unknown>
|
|
367
|
-
list: (threadId: string) => Promise<unknown[]>
|
|
368
|
-
getHead: (threadId: string) => Promise<string | null>
|
|
369
|
-
append: (input: { checkpoint: unknown; writer: { threadId: string } }) => Promise<{ headId: string }>
|
|
370
|
-
deleteHead: (input: { threadId: string; checkpointId: string }) => Promise<void>
|
|
371
|
-
acquireWriter: (threadId: string) => Promise<{ ownerToken: string; fence: number }>
|
|
372
|
-
}
|
|
377
|
+
checkpoints?: InMemorySandboxCheckpointStore
|
|
373
378
|
persistence?: { stores?: { messages?: { loadThread: (threadId: string) => Promise<unknown[]> } } }
|
|
374
379
|
}
|
|
375
380
|
}).snapshots!
|
|
@@ -409,56 +414,262 @@ describe("snapshots messages.loadThread 与 checkpoint store(审计 A3x-2)",
|
|
|
409
414
|
expect.objectContaining({ where: { threadId: "thread-1" } }),
|
|
410
415
|
)
|
|
411
416
|
})
|
|
417
|
+
})
|
|
418
|
+
|
|
419
|
+
/**
|
|
420
|
+
* 官方 InMemorySandboxCheckpointStore 语义(任务 14:替换自建 99 行占位)。
|
|
421
|
+
*
|
|
422
|
+
* 占位版吞掉的官方错误语义在此逐条锁定:expectedHead 乐观并发(STALE_HEAD)、
|
|
423
|
+
* 重复 id、parent 链路一致、写者租约(conflict / lost)、deleteHead 非 head、
|
|
424
|
+
* id/entry 校验、blob 引用计数。checkpoint store 实例随 buildSandboxMiddleware
|
|
425
|
+
* 每次新建,用例间天然隔离;占位版的 200 条 FIFO 淘汰随占位一起移除——官方实现
|
|
426
|
+
* 不设上限,增长由 thread 生命周期(keepAlive 30m reap)约束。
|
|
427
|
+
*/
|
|
428
|
+
describe("官方 InMemorySandboxCheckpointStore 语义(任务 14)", () => {
|
|
429
|
+
beforeEach(() => {
|
|
430
|
+
vi.clearAllMocks()
|
|
431
|
+
vi.unstubAllEnvs()
|
|
432
|
+
delete process.env.DEPLOY_TARGET
|
|
433
|
+
mocks.resolveSandboxProvider.mockResolvedValue({ provider: { name: "mock" } })
|
|
434
|
+
mocks.defineSandbox.mockImplementation((config: unknown) => config)
|
|
435
|
+
mocks.prismaInstanceStore.mockReturnValue({ store: "prisma" })
|
|
436
|
+
mocks.pgLockStore.mockReturnValue({ lock: "pg" })
|
|
437
|
+
mocks.sandboxPolicyFor.mockImplementation((level: string) => ({ policy: level }))
|
|
438
|
+
mocks.withSandbox.mockImplementation((_sandbox: unknown, options: unknown) => options)
|
|
439
|
+
})
|
|
440
|
+
|
|
441
|
+
function store(): InMemorySandboxCheckpointStore {
|
|
442
|
+
return (mocks.withSandbox.mock.calls[0][1] as {
|
|
443
|
+
snapshots?: { checkpoints?: InMemorySandboxCheckpointStore }
|
|
444
|
+
}).snapshots!.checkpoints!
|
|
445
|
+
}
|
|
446
|
+
|
|
447
|
+
const HEX64 = "a".repeat(64)
|
|
448
|
+
|
|
449
|
+
function checkpoint(overrides: {
|
|
450
|
+
id: string
|
|
451
|
+
threadId: string
|
|
452
|
+
parentCheckpointId?: string | null
|
|
453
|
+
createdAt?: number
|
|
454
|
+
files?: SandboxCheckpoint["files"]
|
|
455
|
+
}): SandboxCheckpoint {
|
|
456
|
+
return {
|
|
457
|
+
id: overrides.id,
|
|
458
|
+
threadId: overrides.threadId,
|
|
459
|
+
parentCheckpointId: overrides.parentCheckpointId ?? null,
|
|
460
|
+
createdAt: overrides.createdAt ?? 1_000,
|
|
461
|
+
reason: "automatic",
|
|
462
|
+
files: overrides.files ?? [],
|
|
463
|
+
conversation: [],
|
|
464
|
+
artifacts: [],
|
|
465
|
+
}
|
|
466
|
+
}
|
|
467
|
+
|
|
468
|
+
/** 以合法租约把 checkpoint 追加为当前 head(parent/expectedHead 取实时 head),成功后释放租约。 */
|
|
469
|
+
async function appendAsHead(
|
|
470
|
+
s: InMemorySandboxCheckpointStore,
|
|
471
|
+
id: string,
|
|
472
|
+
threadId: string,
|
|
473
|
+
createdAt?: number,
|
|
474
|
+
): Promise<string> {
|
|
475
|
+
const writer = await s.acquireWriter(threadId)
|
|
476
|
+
const parent = await s.getHead(threadId)
|
|
477
|
+
const { headId } = await s.append({
|
|
478
|
+
checkpoint: checkpoint({ id, threadId, createdAt, parentCheckpointId: parent }),
|
|
479
|
+
expectedHeadId: parent,
|
|
480
|
+
writer,
|
|
481
|
+
})
|
|
482
|
+
await writer.release()
|
|
483
|
+
return headId
|
|
484
|
+
}
|
|
485
|
+
|
|
486
|
+
it("装配的是官方 InMemorySandboxCheckpointStore 实例(占位实现已移除)", async () => {
|
|
487
|
+
await buildSandboxMiddleware(baseParams())
|
|
488
|
+
expect(store()).toBeInstanceOf(InMemorySandboxCheckpointStore)
|
|
489
|
+
})
|
|
490
|
+
|
|
491
|
+
it("append → getHead/get 回放;list 按 createdAt 排序;deleteHead 真删并回退 head 到 parent", async () => {
|
|
492
|
+
await buildSandboxMiddleware(baseParams())
|
|
493
|
+
const s = store()
|
|
494
|
+
|
|
495
|
+
await appendAsHead(s, "cp-1", "t-1")
|
|
496
|
+
await appendAsHead(s, "cp-2", "t-1", 2_000)
|
|
497
|
+
expect(await s.getHead("t-1")).toBe("cp-2")
|
|
498
|
+
|
|
499
|
+
const listed = await s.list("t-1")
|
|
500
|
+
expect(listed.map((c) => c.id)).toEqual(["cp-1", "cp-2"])
|
|
501
|
+
|
|
502
|
+
const writer = await s.acquireWriter("t-1")
|
|
503
|
+
await s.deleteHead({ threadId: "t-1", checkpointId: "cp-2", writer })
|
|
504
|
+
expect(await s.get("cp-2")).toBeNull()
|
|
505
|
+
// head 回退到被删 checkpoint 的 parent(cp-1),而非清空——与 append 链式 parent 对齐
|
|
506
|
+
expect(await s.getHead("t-1")).toBe("cp-1")
|
|
507
|
+
expect(await s.get("cp-1")).toEqual(checkpoint({ id: "cp-1", threadId: "t-1" }))
|
|
508
|
+
})
|
|
412
509
|
|
|
413
|
-
it("
|
|
510
|
+
it("append expectedHead 过期 → SandboxCheckpointConflictError(占位版吞掉的 STALE_HEAD 语义)", async () => {
|
|
414
511
|
await buildSandboxMiddleware(baseParams())
|
|
415
|
-
const
|
|
512
|
+
const s = store()
|
|
513
|
+
await appendAsHead(s, "cp-1", "t-1")
|
|
514
|
+
const writer = await s.acquireWriter("t-1")
|
|
515
|
+
|
|
516
|
+
await expect(
|
|
517
|
+
s.append({
|
|
518
|
+
checkpoint: checkpoint({ id: "cp-2", threadId: "t-1", parentCheckpointId: "stale" }),
|
|
519
|
+
expectedHeadId: "stale",
|
|
520
|
+
writer,
|
|
521
|
+
}),
|
|
522
|
+
).rejects.toBeInstanceOf(SandboxCheckpointConflictError)
|
|
523
|
+
})
|
|
416
524
|
|
|
417
|
-
|
|
418
|
-
|
|
419
|
-
|
|
525
|
+
it("append 重复 id → SandboxCheckpointDuplicateIdError(先于 head 校验拦截)", async () => {
|
|
526
|
+
await buildSandboxMiddleware(baseParams())
|
|
527
|
+
const s = store()
|
|
528
|
+
await appendAsHead(s, "cp-1", "t-1")
|
|
529
|
+
const writer = await s.acquireWriter("t-1")
|
|
530
|
+
|
|
531
|
+
await expect(
|
|
532
|
+
s.append({
|
|
533
|
+
checkpoint: checkpoint({ id: "cp-1", threadId: "t-1", parentCheckpointId: "cp-1" }),
|
|
534
|
+
expectedHeadId: "cp-1",
|
|
535
|
+
writer,
|
|
536
|
+
}),
|
|
537
|
+
).rejects.toBeInstanceOf(SandboxCheckpointDuplicateIdError)
|
|
538
|
+
})
|
|
420
539
|
|
|
421
|
-
|
|
422
|
-
|
|
423
|
-
|
|
540
|
+
it("append parent 与 expectedHead 不一致 → SandboxCheckpointParentMismatchError", async () => {
|
|
541
|
+
await buildSandboxMiddleware(baseParams())
|
|
542
|
+
const s = store()
|
|
543
|
+
await appendAsHead(s, "cp-1", "t-1")
|
|
544
|
+
const writer = await s.acquireWriter("t-1")
|
|
545
|
+
|
|
546
|
+
// expectedHead 与真实 head 一致,但 checkpoint.parent 指向别处 → 链路断裂即拒
|
|
547
|
+
await expect(
|
|
548
|
+
s.append({
|
|
549
|
+
checkpoint: checkpoint({ id: "cp-2", threadId: "t-1", parentCheckpointId: null }),
|
|
550
|
+
expectedHeadId: "cp-1",
|
|
551
|
+
writer,
|
|
552
|
+
}),
|
|
553
|
+
).rejects.toBeInstanceOf(SandboxCheckpointParentMismatchError)
|
|
424
554
|
})
|
|
425
555
|
|
|
426
|
-
it("
|
|
556
|
+
it("append 未持有效写者租约 → SandboxCheckpointWriterLostError(占位版完全忽略 writer)", async () => {
|
|
427
557
|
await buildSandboxMiddleware(baseParams())
|
|
428
|
-
const
|
|
558
|
+
const s = store()
|
|
559
|
+
await appendAsHead(s, "cp-1", "t-1")
|
|
560
|
+
|
|
561
|
+
await expect(
|
|
562
|
+
s.append({
|
|
563
|
+
checkpoint: checkpoint({ id: "cp-2", threadId: "t-1", parentCheckpointId: "cp-1" }),
|
|
564
|
+
expectedHeadId: "cp-1",
|
|
565
|
+
// 伪造 writer(从未 acquire):ownerToken/fence 均不匹配
|
|
566
|
+
writer: { threadId: "t-1", ownerToken: "bogus", fence: 999 },
|
|
567
|
+
}),
|
|
568
|
+
).rejects.toBeInstanceOf(SandboxCheckpointWriterLostError)
|
|
569
|
+
})
|
|
429
570
|
|
|
430
|
-
|
|
431
|
-
|
|
571
|
+
it("release 后 renew 抛 WriterLostError(租约真正失效,占位版 renew 恒成功)", async () => {
|
|
572
|
+
await buildSandboxMiddleware(baseParams())
|
|
573
|
+
const s = store()
|
|
574
|
+
const writer = await s.acquireWriter("t-1")
|
|
575
|
+
await writer.release()
|
|
432
576
|
|
|
433
|
-
|
|
434
|
-
await cp.deleteHead({ threadId: "t-2", checkpointId: first.headId })
|
|
435
|
-
expect(await cp.getHead("t-2")).toBe(second.headId)
|
|
577
|
+
await expect(writer.renew()).rejects.toBeInstanceOf(SandboxCheckpointWriterLostError)
|
|
436
578
|
})
|
|
437
579
|
|
|
438
|
-
it("
|
|
580
|
+
it("并发 acquireWriter → WriterConflictError;release 后可再取且 ownerToken 唯一 fence 单调", async () => {
|
|
439
581
|
await buildSandboxMiddleware(baseParams())
|
|
440
|
-
const
|
|
582
|
+
const s = store()
|
|
441
583
|
|
|
442
|
-
const w1 = await
|
|
443
|
-
|
|
444
|
-
|
|
584
|
+
const w1 = await s.acquireWriter("t-1")
|
|
585
|
+
await expect(s.acquireWriter("t-1")).rejects.toBeInstanceOf(
|
|
586
|
+
SandboxCheckpointWriterConflictError,
|
|
587
|
+
)
|
|
588
|
+
|
|
589
|
+
await w1.release()
|
|
590
|
+
const w2 = await s.acquireWriter("t-1")
|
|
591
|
+
expect(w2.ownerToken).not.toBe(w1.ownerToken)
|
|
445
592
|
expect(w2.fence).toBeGreaterThan(w1.fence)
|
|
446
593
|
})
|
|
447
594
|
|
|
448
|
-
it("
|
|
595
|
+
it("deleteHead 非 head → SandboxCheckpointNotHeadError(占位版静默 no-op 的语义收紧)", async () => {
|
|
596
|
+
await buildSandboxMiddleware(baseParams())
|
|
597
|
+
const s = store()
|
|
598
|
+
const first = await appendAsHead(s, "cp-1", "t-1")
|
|
599
|
+
await appendAsHead(s, "cp-2", "t-1", 2_000)
|
|
600
|
+
const writer = await s.acquireWriter("t-1")
|
|
601
|
+
|
|
602
|
+
// 用旧 head 调 deleteHead → 抛 NotHeadError,新 head 不受影响
|
|
603
|
+
await expect(
|
|
604
|
+
s.deleteHead({ threadId: "t-1", checkpointId: first, writer }),
|
|
605
|
+
).rejects.toBeInstanceOf(SandboxCheckpointNotHeadError)
|
|
606
|
+
expect(await s.getHead("t-1")).toBe("cp-2")
|
|
607
|
+
})
|
|
608
|
+
|
|
609
|
+
it("无效 checkpoint id → SandboxCheckpointInvalidIdError(get/append 同门槛)", async () => {
|
|
449
610
|
await buildSandboxMiddleware(baseParams())
|
|
450
|
-
const
|
|
611
|
+
const s = store()
|
|
612
|
+
|
|
613
|
+
await expect(s.get("")).rejects.toBeInstanceOf(SandboxCheckpointInvalidIdError)
|
|
614
|
+
const writer = await s.acquireWriter("t-1")
|
|
615
|
+
await expect(
|
|
616
|
+
s.append({
|
|
617
|
+
checkpoint: checkpoint({ id: "", threadId: "t-1" }),
|
|
618
|
+
expectedHeadId: null,
|
|
619
|
+
writer,
|
|
620
|
+
}),
|
|
621
|
+
).rejects.toBeInstanceOf(SandboxCheckpointInvalidIdError)
|
|
622
|
+
})
|
|
451
623
|
|
|
452
|
-
|
|
453
|
-
|
|
454
|
-
|
|
455
|
-
|
|
456
|
-
|
|
457
|
-
|
|
458
|
-
|
|
459
|
-
|
|
460
|
-
|
|
461
|
-
|
|
462
|
-
|
|
624
|
+
it("files blobKey 不符内容寻址格式 → SandboxCheckpointInvalidEntryError(占位版来者不拒)", async () => {
|
|
625
|
+
await buildSandboxMiddleware(baseParams())
|
|
626
|
+
const s = store()
|
|
627
|
+
const writer = await s.acquireWriter("t-1")
|
|
628
|
+
|
|
629
|
+
await expect(
|
|
630
|
+
s.append({
|
|
631
|
+
checkpoint: checkpoint({
|
|
632
|
+
id: "cp-bad",
|
|
633
|
+
threadId: "t-1",
|
|
634
|
+
files: [{ path: "src/a.txt", kind: "file", blobKey: "run-no-artifact", size: 3 }],
|
|
635
|
+
}),
|
|
636
|
+
expectedHeadId: null,
|
|
637
|
+
writer,
|
|
638
|
+
}),
|
|
639
|
+
).rejects.toBeInstanceOf(SandboxCheckpointInvalidEntryError)
|
|
640
|
+
})
|
|
641
|
+
|
|
642
|
+
it("listBlobReferences 按 blobKey 计数引用,deleteHead 递减(blob GC 依据)", async () => {
|
|
643
|
+
await buildSandboxMiddleware(baseParams())
|
|
644
|
+
const s = store()
|
|
645
|
+
const blobKey = `sandbox-files/sha256/${HEX64}`
|
|
646
|
+
const files: SandboxCheckpoint["files"] = [
|
|
647
|
+
{ path: "src/a.txt", kind: "file", blobKey, size: 3 },
|
|
648
|
+
]
|
|
649
|
+
|
|
650
|
+
const w1 = await s.acquireWriter("t-1")
|
|
651
|
+
await s.append({
|
|
652
|
+
checkpoint: checkpoint({ id: "cp-1", threadId: "t-1", files }),
|
|
653
|
+
expectedHeadId: null,
|
|
654
|
+
writer: w1,
|
|
655
|
+
})
|
|
656
|
+
await w1.release()
|
|
657
|
+
const w2 = await s.acquireWriter("t-1")
|
|
658
|
+
await s.append({
|
|
659
|
+
checkpoint: checkpoint({
|
|
660
|
+
id: "cp-2",
|
|
661
|
+
threadId: "t-1",
|
|
662
|
+
parentCheckpointId: "cp-1",
|
|
663
|
+
createdAt: 2_000,
|
|
664
|
+
files,
|
|
665
|
+
}),
|
|
666
|
+
expectedHeadId: "cp-1",
|
|
667
|
+
writer: w2,
|
|
668
|
+
})
|
|
669
|
+
|
|
670
|
+
expect(await s.listBlobReferences()).toEqual([{ key: blobKey, references: 2 }])
|
|
671
|
+
|
|
672
|
+
await s.deleteHead({ threadId: "t-1", checkpointId: "cp-2", writer: w2 })
|
|
673
|
+
expect(await s.listBlobReferences()).toEqual([{ key: blobKey, references: 1 }])
|
|
463
674
|
})
|
|
464
675
|
})
|
|
@@ -19,11 +19,11 @@ import type { RunStore, AnyTextAdapter } from "@tanstack/ai"
|
|
|
19
19
|
import {
|
|
20
20
|
defineSandbox,
|
|
21
21
|
withSandbox,
|
|
22
|
+
InMemorySandboxCheckpointStore,
|
|
22
23
|
type WorkspaceDefinition,
|
|
23
24
|
createSecrets,
|
|
24
25
|
localSource,
|
|
25
26
|
} from "@tanstack/ai-sandbox"
|
|
26
|
-
import { randomUUID } from "node:crypto"
|
|
27
27
|
import { InMemoryLockStore } from "@tanstack/ai/locks"
|
|
28
28
|
import type { PgStreamDurabilityFactory } from "../durability/pg-stream"
|
|
29
29
|
import { pgLockStore } from "../locks/pg-lock"
|
|
@@ -39,70 +39,6 @@ import {
|
|
|
39
39
|
import { codexText, CODEX_MODELS } from "@tanstack/ai-codex"
|
|
40
40
|
import { acpCompatibleText } from "@tanstack/ai-acp"
|
|
41
41
|
import { opencodeText } from "@tanstack/ai-opencode"
|
|
42
|
-
import type { SandboxCheckpointStore } from "@tanstack/ai-sandbox"
|
|
43
|
-
|
|
44
|
-
/**
|
|
45
|
-
* 内存 checkpoint store 骨架——任务 14 占位,后续接 DB 持久化。
|
|
46
|
-
*
|
|
47
|
-
* 占位不等于放任(审计 2026-10-25 🟡):append 只增不删会让长生命周期进程
|
|
48
|
-
* 内存持续增长,故设条目上限 FIFO 淘汰;deleteHead 真删 head 指向条目;
|
|
49
|
-
* ownerToken 用 randomUUID(Date.now() 同毫秒并发即重复);fence 单调递增
|
|
50
|
-
* (恒 0 使写者栅栏失效)。
|
|
51
|
-
*/
|
|
52
|
-
const MEMORY_CHECKPOINT_MAX_ENTRIES = 200
|
|
53
|
-
|
|
54
|
-
function memoryCheckpointStore(): SandboxCheckpointStore {
|
|
55
|
-
const checkpoints = new Map<string, unknown>()
|
|
56
|
-
const heads = new Map<string, string>()
|
|
57
|
-
let fenceCounter = 0
|
|
58
|
-
return {
|
|
59
|
-
get: async (_id: string) => (checkpoints.get(_id) ?? null) as never,
|
|
60
|
-
list: async (threadId: string) => {
|
|
61
|
-
const prefix = `thread:${threadId}:`
|
|
62
|
-
return Array.from(checkpoints.entries())
|
|
63
|
-
.filter(([id]) => id.startsWith(prefix))
|
|
64
|
-
.map(([, v]) => v as never)
|
|
65
|
-
},
|
|
66
|
-
getHead: async (threadId: string) => heads.get(`thread:${threadId}`) ?? null,
|
|
67
|
-
append: async (input: any) => {
|
|
68
|
-
const tid = input?.writer?.threadId ?? "unknown"
|
|
69
|
-
const id = `thread:${tid}:${Date.now()}-${randomUUID().slice(0, 8)}`
|
|
70
|
-
checkpoints.set(id, input.checkpoint)
|
|
71
|
-
heads.set(`thread:${tid}`, id)
|
|
72
|
-
// FIFO 淘汰:Map 迭代按插入序,删到上限以内(head 指向的条目若被淘汰,
|
|
73
|
-
// getHead 返回的 id 在 get 中自然落空——占位实现的已知边界)。
|
|
74
|
-
while (checkpoints.size > MEMORY_CHECKPOINT_MAX_ENTRIES) {
|
|
75
|
-
const oldest = checkpoints.keys().next().value
|
|
76
|
-
if (oldest === undefined) break
|
|
77
|
-
checkpoints.delete(oldest)
|
|
78
|
-
}
|
|
79
|
-
return { headId: id } as any
|
|
80
|
-
},
|
|
81
|
-
deleteHead: async (input: {
|
|
82
|
-
threadId: string
|
|
83
|
-
checkpointId: string
|
|
84
|
-
}) => {
|
|
85
|
-
// 仅当 input.checkpointId 仍是当前 head 时才删(防误删新 head)。
|
|
86
|
-
// heads 的 key 与 getHead 同前缀(`thread:<threadId>`),value 是完整
|
|
87
|
-
// checkpoint id(`thread:<threadId>:<ts>-<uuid>`)。
|
|
88
|
-
const headKey = `thread:${input.threadId}`
|
|
89
|
-
const headId = heads.get(headKey)
|
|
90
|
-
if (headId === undefined || headId !== input.checkpointId) return
|
|
91
|
-
heads.delete(headKey)
|
|
92
|
-
checkpoints.delete(headId)
|
|
93
|
-
},
|
|
94
|
-
acquireWriter: async (threadId: string) => ({
|
|
95
|
-
threadId,
|
|
96
|
-
expiresAt: Date.now() + 60_000,
|
|
97
|
-
renewAfterMs: 30_000,
|
|
98
|
-
renew: () => Promise.resolve({ expiresAt: Date.now() + 60_000 } as any),
|
|
99
|
-
ownerToken: `token-${threadId}-${randomUUID()}`,
|
|
100
|
-
fence: ++fenceCounter,
|
|
101
|
-
release: () => Promise.resolve(),
|
|
102
|
-
}) as any,
|
|
103
|
-
listBlobReferences: async () => [],
|
|
104
|
-
} as never
|
|
105
|
-
}
|
|
106
42
|
|
|
107
43
|
/** 快照恢复的消息上限——与 persistence/message-store.ts 的 LOAD_THREAD_MAX_MESSAGES 同口径。 */
|
|
108
44
|
const SANDBOX_LOAD_THREAD_MAX_MESSAGES = 100
|
|
@@ -239,9 +175,12 @@ export async function buildSandboxMiddleware(
|
|
|
239
175
|
},
|
|
240
176
|
}
|
|
241
177
|
: {}),
|
|
242
|
-
// snapshots.blobs(artifacts + blobs store)P3b 任务 14
|
|
178
|
+
// snapshots.blobs(artifacts + blobs store)P3b 任务 14 接线收口。
|
|
179
|
+
// checkpoint store 用官方 InMemorySandboxCheckpointStore(任务 14 替换自建
|
|
180
|
+
// 占位):完整写者租约 + expectedHead 乐观并发 + 9 个错误类语义;后续接
|
|
181
|
+
// DB 持久化时同接口平移。
|
|
243
182
|
snapshots: {
|
|
244
|
-
checkpoints:
|
|
183
|
+
checkpoints: new InMemorySandboxCheckpointStore(),
|
|
245
184
|
persistence: {
|
|
246
185
|
stores: {
|
|
247
186
|
messages: {
|
|
@@ -18,6 +18,7 @@
|
|
|
18
18
|
import { prisma } from '@allbluecn/database'
|
|
19
19
|
import type { AiSourceMode } from '@allbluecn/kernel'
|
|
20
20
|
import { AI_SOURCE_MODES } from '@allbluecn/kernel'
|
|
21
|
+
import { GUEST_USER_ID } from '../desktop-guest'
|
|
21
22
|
import { getPorts } from './runtime'
|
|
22
23
|
|
|
23
24
|
export interface SourceModeSubject {
|
|
@@ -25,16 +26,30 @@ export interface SourceModeSubject {
|
|
|
25
26
|
isGuest: boolean
|
|
26
27
|
}
|
|
27
28
|
|
|
29
|
+
/** guest 隔离键:aiSourceMode:local-guest(GUEST_USER_ID 统一从 desktop-guest 引用) */
|
|
30
|
+
const GUEST_SOURCE_MODE_KEY = `aiSourceMode:${GUEST_USER_ID}`
|
|
31
|
+
/** 旧全局键:仅迁移读,不回写、不删除 */
|
|
32
|
+
const LEGACY_SOURCE_MODE_KEY = 'aiSourceMode'
|
|
33
|
+
|
|
28
34
|
/** 读用户当前模型来源模式;null = 未选择(按 byok 现状链路由) */
|
|
29
35
|
export async function resolveSourceMode(subject: SourceModeSubject): Promise<AiSourceMode | null> {
|
|
30
36
|
try {
|
|
31
37
|
if (subject.isGuest) {
|
|
32
|
-
//
|
|
33
|
-
//
|
|
34
|
-
//
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
+
// guest 键隔离:读写均走 aiSourceMode:${GUEST_USER_ID},不再共享全局键,
|
|
39
|
+
// 多 guest/多实例写入互不覆盖。旧全局键仅做迁移读:新键缺失时回落旧值,
|
|
40
|
+
// 下次写入自然 upsert 落新键;旧键保留不删(桌面单机幂等,无害残留)。
|
|
41
|
+
const row = await prisma.desktopSetting.findUnique({ where: { key: GUEST_SOURCE_MODE_KEY } })
|
|
42
|
+
if (!row) {
|
|
43
|
+
const legacy = await prisma.desktopSetting.findUnique({
|
|
44
|
+
where: { key: LEGACY_SOURCE_MODE_KEY },
|
|
45
|
+
})
|
|
46
|
+
const legacyRaw = legacy?.value
|
|
47
|
+
if (typeof legacyRaw === 'string' && AI_SOURCE_MODES.includes(legacyRaw as AiSourceMode)) {
|
|
48
|
+
return legacyRaw as AiSourceMode
|
|
49
|
+
}
|
|
50
|
+
return null
|
|
51
|
+
}
|
|
52
|
+
const raw = row.value
|
|
38
53
|
if (typeof raw !== 'string' || !AI_SOURCE_MODES.includes(raw as AiSourceMode)) return null
|
|
39
54
|
return raw as AiSourceMode
|
|
40
55
|
}
|
|
@@ -55,9 +70,10 @@ export async function resolveSourceMode(subject: SourceModeSubject): Promise<AiS
|
|
|
55
70
|
|
|
56
71
|
export async function setSourceMode(subject: SourceModeSubject, mode: AiSourceMode): Promise<void> {
|
|
57
72
|
if (subject.isGuest) {
|
|
73
|
+
// 写隔离键;旧键不删除(迁移读后首次写入自然落新键)
|
|
58
74
|
await prisma.desktopSetting.upsert({
|
|
59
|
-
where: { key:
|
|
60
|
-
create: { key:
|
|
75
|
+
where: { key: GUEST_SOURCE_MODE_KEY },
|
|
76
|
+
create: { key: GUEST_SOURCE_MODE_KEY, value: mode },
|
|
61
77
|
update: { value: mode },
|
|
62
78
|
})
|
|
63
79
|
return
|
|
@@ -0,0 +1,74 @@
|
|
|
1
|
+
// SPDX-License-Identifier: AGPL-3.0-or-later
|
|
2
|
+
// AllBlue - 理想之海
|
|
3
|
+
// Copyright (C) 2026 AllBlue Contributors
|
|
4
|
+
//
|
|
5
|
+
// This program is free software: you can redistribute it and/or modify
|
|
6
|
+
// it under the terms of the GNU Affero General Public License as published by
|
|
7
|
+
// the Free Software Foundation, either version 3 of the License, or
|
|
8
|
+
// (at your option) any later version.
|
|
9
|
+
//
|
|
10
|
+
// This program is distributed in the hope that it will be useful,
|
|
11
|
+
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
12
|
+
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
13
|
+
// GNU Affero General Public License for more details.
|
|
14
|
+
//
|
|
15
|
+
// You should have received a copy of the GNU Affero General Public License
|
|
16
|
+
// along with this program. If not, see <https://www.gnu.org/licenses/>.
|
|
17
|
+
|
|
18
|
+
// 桌面首启本地影子用户(本地优先改造 P1,规格 §3.1 懒 seed)。
|
|
19
|
+
// 背景:桌面端(Electron + PGlite)免登录发放 guest 会话(desktop-guest.ts),但
|
|
20
|
+
// users 表无行 → assertOwned / assertProjectMembership / requireUserInDb 与各表
|
|
21
|
+
// FK 在 guest 写入时全部失败。解法:首启为 local-guest 建真实影子行(users 一行
|
|
22
|
+
// + 内置「独立需求」项目 + owner member),业务链零改动自然通过。
|
|
23
|
+
// 挂点:serverFns/auth/session.ts getSessionFn 桌面 guest 分支(失败仅 warn 不
|
|
24
|
+
// 阻断会话发放——首启体验优先)。
|
|
25
|
+
|
|
26
|
+
import { randomUUID } from 'node:crypto'
|
|
27
|
+
import { prisma } from '@allbluecn/database'
|
|
28
|
+
import { ensureBuiltinIndependentProject } from '@/server/builtin-project'
|
|
29
|
+
import {
|
|
30
|
+
GUEST_EMAIL,
|
|
31
|
+
GUEST_USER_ID,
|
|
32
|
+
GUEST_USERNAME,
|
|
33
|
+
isDesktopServer,
|
|
34
|
+
} from '@/server/desktop-guest'
|
|
35
|
+
import { defaultAvatarConfig, presetBgColors } from '@/lib/avatar/avatar-config'
|
|
36
|
+
|
|
37
|
+
// 与 desktop-guest.ts 的 guestBgColor 同式(未导出,为不扩散导出面在此重复;两处
|
|
38
|
+
// seed 同为 GUEST_USERNAME,影子行与内存 guest 会话的头像底色恒一致)
|
|
39
|
+
function shadowBgColor(seed: string): string {
|
|
40
|
+
const sum = [...seed].reduce((acc, ch) => acc + ch.charCodeAt(0), 0)
|
|
41
|
+
return presetBgColors[sum % presetBgColors.length] as string
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
/**
|
|
45
|
+
* 幂等落库本地影子用户(id=local-guest)并复用内置独立项目,返回 GUEST_USER_ID。
|
|
46
|
+
*
|
|
47
|
+
* - 非 desktop 部署:防御性早退不触库(正常调用方只在桌面分支触达)。
|
|
48
|
+
* - upsert 的 update 分支留空:不覆盖用户后续改名/改头像(幂等)。
|
|
49
|
+
* - password 为随机占位(非 bcrypt 哈希):guest 不走密码登录,凭据比对必失败,
|
|
50
|
+
* 杜绝影子行被密码登录复用。
|
|
51
|
+
* - 头像三件(avatarConfig/bgShape/bgColor)与 buildGuestSession 对齐,经 DB 读
|
|
52
|
+
* 取用户的路径(成员列表等)与内存 guest 会话渲染一致。
|
|
53
|
+
*/
|
|
54
|
+
export async function ensureLocalShadowUser(): Promise<string> {
|
|
55
|
+
if (!isDesktopServer()) return GUEST_USER_ID
|
|
56
|
+
|
|
57
|
+
await prisma.user.upsert({
|
|
58
|
+
where: { id: GUEST_USER_ID },
|
|
59
|
+
create: {
|
|
60
|
+
id: GUEST_USER_ID,
|
|
61
|
+
email: GUEST_EMAIL,
|
|
62
|
+
username: GUEST_USERNAME,
|
|
63
|
+
password: randomUUID(),
|
|
64
|
+
avatarConfig: defaultAvatarConfig as object,
|
|
65
|
+
bgShape: 'square',
|
|
66
|
+
bgColor: shadowBgColor(GUEST_USERNAME),
|
|
67
|
+
status: 'ACTIVE',
|
|
68
|
+
},
|
|
69
|
+
update: {},
|
|
70
|
+
})
|
|
71
|
+
|
|
72
|
+
await ensureBuiltinIndependentProject(GUEST_USER_ID)
|
|
73
|
+
return GUEST_USER_ID
|
|
74
|
+
}
|
|
@@ -31,7 +31,6 @@ describe('限流注册表', () => {
|
|
|
31
31
|
expect(AI_RATE_LIMIT.mediaVideo.max).toBeGreaterThan(0)
|
|
32
32
|
expect(AI_RATE_LIMIT.mediaSpeech.max).toBeGreaterThan(0)
|
|
33
33
|
expect(AI_RATE_LIMIT.mediaTranscription.max).toBeGreaterThan(0)
|
|
34
|
-
expect(AI_RATE_LIMIT.mediaPoll.max).toBeGreaterThanOrEqual(AI_RATE_LIMIT.mediaImage.max)
|
|
35
34
|
expect(AI_RATE_LIMIT.mediaPrototype.max).toBeGreaterThan(0)
|
|
36
35
|
})
|
|
37
36
|
|
|
@@ -47,8 +47,6 @@ export const AI_RATE_LIMIT = {
|
|
|
47
47
|
mediaVideo: { max: 5, windowMs: 60_000 },
|
|
48
48
|
mediaSpeech: { max: 10, windowMs: 60_000 },
|
|
49
49
|
mediaTranscription: { max: 10, windowMs: 60_000 },
|
|
50
|
-
// 轮询端点:任务进行期间会被周期调用,放宽阈值防误伤(仍封死无任务空转滥用)
|
|
51
|
-
mediaPoll: { max: 60, windowMs: 60_000 },
|
|
52
50
|
mediaPrototype: { max: 5, windowMs: 60_000 },
|
|
53
51
|
aiTask: { max: 5, windowMs: 60_000 },
|
|
54
52
|
// 审计 A2x-serverfns-4 补口:知识库向量索引(embedding 计费调用,单文档建索引;
|