@alneas/appkit-react 0.1.0 → 0.2.0
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/CHANGELOG.md +53 -0
- package/README.md +85 -15
- package/consumer-ai/SKILL.md +12 -0
- package/consumer-ai/api-index.json +103754 -0
- package/consumer-ai/package-context.json +409 -0
- package/dist/ai/action/ExecutionHistory.cjs.map +1 -1
- package/dist/ai/action/ExecutionHistory.d.cts +32 -2
- package/dist/ai/action/ExecutionHistory.d.ts +32 -2
- package/dist/ai/action/ExecutionHistory.js.map +1 -1
- package/dist/ai/action/ScreenActionContext.cjs.map +1 -1
- package/dist/ai/action/ScreenActionContext.d.cts +15 -2
- package/dist/ai/action/ScreenActionContext.d.ts +15 -2
- package/dist/ai/action/ScreenActionContext.js.map +1 -1
- package/dist/ai/action/context.cjs.map +1 -1
- package/dist/ai/action/context.d.cts +19 -3
- package/dist/ai/action/context.d.ts +19 -3
- package/dist/ai/action/context.js.map +1 -1
- package/dist/ai/action/types.d.cts +35 -3
- package/dist/ai/action/types.d.ts +35 -3
- package/dist/ai/action/use-execution-session.cjs.map +1 -1
- package/dist/ai/action/use-execution-session.d.cts +17 -1
- package/dist/ai/action/use-execution-session.d.ts +17 -1
- package/dist/ai/action/use-execution-session.js.map +1 -1
- package/dist/ai/action/use-screen-action-registry.cjs.map +1 -1
- package/dist/ai/action/use-screen-action-registry.d.cts +77 -8
- package/dist/ai/action/use-screen-action-registry.d.ts +77 -8
- package/dist/ai/action/use-screen-action-registry.js.map +1 -1
- package/dist/ai/action/use-screen-action.cjs.map +1 -1
- package/dist/ai/action/use-screen-action.d.cts +23 -6
- package/dist/ai/action/use-screen-action.d.ts +23 -6
- package/dist/ai/action/use-screen-action.js.map +1 -1
- package/dist/ai/action/use-screen-context.cjs.map +1 -1
- package/dist/ai/action/use-screen-context.d.cts +42 -5
- package/dist/ai/action/use-screen-context.d.ts +42 -5
- package/dist/ai/action/use-screen-context.js.map +1 -1
- package/dist/ai/ai-chat/transport.cjs.map +1 -1
- package/dist/ai/ai-chat/transport.d.cts +35 -8
- package/dist/ai/ai-chat/transport.d.ts +35 -8
- package/dist/ai/ai-chat/transport.js.map +1 -1
- package/dist/ai/generative-ui/GenerativeUIRenderer.cjs.map +1 -1
- package/dist/ai/generative-ui/GenerativeUIRenderer.d.cts +21 -3
- package/dist/ai/generative-ui/GenerativeUIRenderer.d.ts +21 -3
- package/dist/ai/generative-ui/GenerativeUIRenderer.js.map +1 -1
- package/dist/ai/generative-ui/error-boundary.cjs.map +1 -1
- package/dist/ai/generative-ui/error-boundary.d.cts +98 -2
- package/dist/ai/generative-ui/error-boundary.d.ts +98 -2
- package/dist/ai/generative-ui/error-boundary.js.map +1 -1
- package/dist/ai/generative-ui/registry.cjs.map +1 -1
- package/dist/ai/generative-ui/registry.d.cts +96 -7
- package/dist/ai/generative-ui/registry.d.ts +96 -7
- package/dist/ai/generative-ui/registry.js.map +1 -1
- package/dist/ai/proposal/ProposalFieldReview.cjs.map +1 -1
- package/dist/ai/proposal/ProposalFieldReview.d.cts +170 -8
- package/dist/ai/proposal/ProposalFieldReview.d.ts +170 -8
- package/dist/ai/proposal/ProposalFieldReview.js.map +1 -1
- package/dist/ai/proposal/types.d.cts +97 -26
- package/dist/ai/proposal/types.d.ts +97 -26
- package/dist/ai/proposal/use-proposal-batch-review.cjs.map +1 -1
- package/dist/ai/proposal/use-proposal-batch-review.d.cts +133 -7
- package/dist/ai/proposal/use-proposal-batch-review.d.ts +133 -7
- package/dist/ai/proposal/use-proposal-batch-review.js.map +1 -1
- package/dist/ai/proposal/use-proposal-review.cjs.map +1 -1
- package/dist/ai/proposal/use-proposal-review.d.cts +47 -5
- package/dist/ai/proposal/use-proposal-review.d.ts +47 -5
- package/dist/ai/proposal/use-proposal-review.js.map +1 -1
- package/dist/avatar.svg +1 -0
- package/dist/consumer-ai/SKILL.md +6 -0
- package/dist/consumer-ai/api-index.json +103754 -0
- package/dist/consumer-ai/package-context.json +5 -3
- package/dist/mockServiceWorker.js +361 -0
- package/dist/styles.css +1 -1
- package/dist/tools/components/auth/AuthForms.cjs.map +1 -1
- package/dist/tools/components/auth/AuthForms.d.cts +131 -81
- package/dist/tools/components/auth/AuthForms.d.ts +131 -81
- package/dist/tools/components/auth/AuthForms.js.map +1 -1
- package/dist/tools/components/auth/AuthGuard.cjs.map +1 -1
- package/dist/tools/components/auth/AuthGuard.d.cts +31 -4
- package/dist/tools/components/auth/AuthGuard.d.ts +31 -4
- package/dist/tools/components/auth/AuthGuard.js.map +1 -1
- package/dist/tools/components/auth/AuthProvider.cjs.map +1 -1
- package/dist/tools/components/auth/AuthProvider.d.cts +39 -42
- package/dist/tools/components/auth/AuthProvider.d.ts +39 -42
- package/dist/tools/components/auth/AuthProvider.js.map +1 -1
- package/dist/tools/components/auth/ProtectedRoute.cjs.map +1 -1
- package/dist/tools/components/auth/ProtectedRoute.d.cts +75 -60
- package/dist/tools/components/auth/ProtectedRoute.d.ts +75 -60
- package/dist/tools/components/auth/ProtectedRoute.js.map +1 -1
- package/dist/tools/components/auth/SignInButton.cjs.map +1 -1
- package/dist/tools/components/auth/SignInButton.d.cts +26 -18
- package/dist/tools/components/auth/SignInButton.d.ts +26 -18
- package/dist/tools/components/auth/SignInButton.js.map +1 -1
- package/dist/tools/components/auth/UserProfileProvider.cjs.map +1 -1
- package/dist/tools/components/auth/UserProfileProvider.d.cts +48 -20
- package/dist/tools/components/auth/UserProfileProvider.d.ts +48 -20
- package/dist/tools/components/auth/UserProfileProvider.js.map +1 -1
- package/dist/tools/components/auth/adapters/better-auth-adapter.cjs.map +1 -1
- package/dist/tools/components/auth/adapters/better-auth-adapter.d.cts +371 -51
- package/dist/tools/components/auth/adapters/better-auth-adapter.d.ts +371 -51
- package/dist/tools/components/auth/adapters/better-auth-adapter.js.map +1 -1
- package/dist/tools/components/auth/adapters/mock-adapter.cjs.map +1 -1
- package/dist/tools/components/auth/adapters/mock-adapter.d.cts +149 -28
- package/dist/tools/components/auth/adapters/mock-adapter.d.ts +149 -28
- package/dist/tools/components/auth/adapters/mock-adapter.js.map +1 -1
- package/dist/tools/components/auth/auth-session.cjs.map +1 -1
- package/dist/tools/components/auth/auth-session.d.cts +147 -1
- package/dist/tools/components/auth/auth-session.d.ts +147 -1
- package/dist/tools/components/auth/auth-session.js.map +1 -1
- package/dist/tools/components/auth/session-cache.cjs.map +1 -1
- package/dist/tools/components/auth/session-cache.d.cts +88 -24
- package/dist/tools/components/auth/session-cache.d.ts +88 -24
- package/dist/tools/components/auth/session-cache.js.map +1 -1
- package/dist/tools/components/auth/types.cjs.map +1 -1
- package/dist/tools/components/auth/types.d.cts +329 -106
- package/dist/tools/components/auth/types.d.ts +329 -106
- package/dist/tools/components/auth/types.js.map +1 -1
- package/dist/tools/components/auth/useAuth.cjs.map +1 -1
- package/dist/tools/components/auth/useAuth.d.cts +110 -17
- package/dist/tools/components/auth/useAuth.d.ts +110 -17
- package/dist/tools/components/auth/useAuth.js.map +1 -1
- package/dist/tools/components/auth/useAuthGuard.cjs.map +1 -1
- package/dist/tools/components/auth/useAuthGuard.d.cts +49 -38
- package/dist/tools/components/auth/useAuthGuard.d.ts +49 -38
- package/dist/tools/components/auth/useAuthGuard.js.map +1 -1
- package/dist/tools/components/auth/useRoleCheck.cjs.map +1 -1
- package/dist/tools/components/auth/useRoleCheck.d.cts +48 -1
- package/dist/tools/components/auth/useRoleCheck.d.ts +48 -1
- package/dist/tools/components/auth/useRoleCheck.js.map +1 -1
- package/dist/tools/components/auth/useUserProfile.cjs.map +1 -1
- package/dist/tools/components/auth/useUserProfile.d.cts +66 -1
- package/dist/tools/components/auth/useUserProfile.d.ts +66 -1
- package/dist/tools/components/auth/useUserProfile.js.map +1 -1
- package/dist/tools/components/barcode/BarcodeGenerator.cjs.map +1 -1
- package/dist/tools/components/barcode/BarcodeGenerator.d.cts +32 -18
- package/dist/tools/components/barcode/BarcodeGenerator.d.ts +32 -18
- package/dist/tools/components/barcode/BarcodeGenerator.js.map +1 -1
- package/dist/tools/components/barcode/QRCodeGenerator.cjs +1 -1
- package/dist/tools/components/barcode/QRCodeGenerator.cjs.map +1 -1
- package/dist/tools/components/barcode/QRCodeGenerator.d.cts +20 -13
- package/dist/tools/components/barcode/QRCodeGenerator.d.ts +20 -13
- package/dist/tools/components/barcode/QRCodeGenerator.js +1 -1
- package/dist/tools/components/barcode/QRCodeGenerator.js.map +1 -1
- package/dist/tools/components/barcode/QRCodeScanner.cjs.map +1 -1
- package/dist/tools/components/barcode/QRCodeScanner.d.cts +32 -1
- package/dist/tools/components/barcode/QRCodeScanner.d.ts +32 -1
- package/dist/tools/components/barcode/QRCodeScanner.js.map +1 -1
- package/dist/tools/components/calendar/ResourceCalendar.cjs.map +1 -1
- package/dist/tools/components/calendar/ResourceCalendar.d.cts +17 -42
- package/dist/tools/components/calendar/ResourceCalendar.d.ts +17 -42
- package/dist/tools/components/calendar/ResourceCalendar.js.map +1 -1
- package/dist/tools/components/calendar/views/ResourceView.cjs +1 -1
- package/dist/tools/components/calendar/views/ResourceView.cjs.map +1 -1
- package/dist/tools/components/calendar/views/ResourceView.js +2 -2
- package/dist/tools/components/calendar/views/ResourceView.js.map +1 -1
- package/dist/tools/components/chart/ComposedChart.cjs.map +1 -1
- package/dist/tools/components/chart/ComposedChart.d.cts +54 -1
- package/dist/tools/components/chart/ComposedChart.d.ts +54 -1
- package/dist/tools/components/chart/ComposedChart.js.map +1 -1
- package/dist/tools/components/chart/SimpleAreaChart.cjs.map +1 -1
- package/dist/tools/components/chart/SimpleAreaChart.d.cts +41 -1
- package/dist/tools/components/chart/SimpleAreaChart.d.ts +41 -1
- package/dist/tools/components/chart/SimpleAreaChart.js.map +1 -1
- package/dist/tools/components/chart/SimpleBarChart.cjs.map +1 -1
- package/dist/tools/components/chart/SimpleBarChart.d.cts +34 -24
- package/dist/tools/components/chart/SimpleBarChart.d.ts +34 -24
- package/dist/tools/components/chart/SimpleBarChart.js.map +1 -1
- package/dist/tools/components/chart/SimpleLineChart.cjs.map +1 -1
- package/dist/tools/components/chart/SimpleLineChart.d.cts +31 -28
- package/dist/tools/components/chart/SimpleLineChart.d.ts +31 -28
- package/dist/tools/components/chart/SimpleLineChart.js.map +1 -1
- package/dist/tools/components/chart/SimplePieChart.cjs.map +1 -1
- package/dist/tools/components/chart/SimplePieChart.d.cts +28 -22
- package/dist/tools/components/chart/SimplePieChart.d.ts +28 -22
- package/dist/tools/components/chart/SimplePieChart.js.map +1 -1
- package/dist/tools/components/chart/SimpleRadarChart.cjs.map +1 -1
- package/dist/tools/components/chart/SimpleRadarChart.d.cts +38 -1
- package/dist/tools/components/chart/SimpleRadarChart.d.ts +38 -1
- package/dist/tools/components/chart/SimpleRadarChart.js.map +1 -1
- package/dist/tools/components/chart/SimpleScatterChart.cjs.map +1 -1
- package/dist/tools/components/chart/SimpleScatterChart.d.cts +44 -1
- package/dist/tools/components/chart/SimpleScatterChart.d.ts +44 -1
- package/dist/tools/components/chart/SimpleScatterChart.js.map +1 -1
- package/dist/tools/components/chart/StackedBarChart.cjs.map +1 -1
- package/dist/tools/components/chart/StackedBarChart.d.cts +38 -1
- package/dist/tools/components/chart/StackedBarChart.d.ts +38 -1
- package/dist/tools/components/chart/StackedBarChart.js.map +1 -1
- package/dist/tools/components/data-table/data-table.cjs +1 -1
- package/dist/tools/components/data-table/data-table.cjs.map +1 -1
- package/dist/tools/components/data-table/data-table.js +286 -263
- package/dist/tools/components/data-table/data-table.js.map +1 -1
- package/dist/tools/components/data-table/table-utils.cjs.map +1 -1
- package/dist/tools/components/data-table/table-utils.d.cts +45 -35
- package/dist/tools/components/data-table/table-utils.d.ts +45 -35
- package/dist/tools/components/data-table/table-utils.js.map +1 -1
- package/dist/tools/components/editable-table/editable-table.cjs +1 -1
- package/dist/tools/components/editable-table/editable-table.cjs.map +1 -1
- package/dist/tools/components/editable-table/editable-table.js +15 -2
- package/dist/tools/components/editable-table/editable-table.js.map +1 -1
- package/dist/tools/components/error/ErrorDialog.cjs +1 -1
- package/dist/tools/components/error/ErrorDialog.cjs.map +1 -1
- package/dist/tools/components/error/ErrorDialog.js +1 -1
- package/dist/tools/components/error/ErrorDialog.js.map +1 -1
- package/dist/tools/components/error/ErrorInline.cjs +1 -1
- package/dist/tools/components/error/ErrorInline.cjs.map +1 -1
- package/dist/tools/components/error/ErrorInline.js +1 -1
- package/dist/tools/components/error/ErrorInline.js.map +1 -1
- package/dist/tools/components/error/ErrorNotification.cjs +1 -1
- package/dist/tools/components/error/ErrorNotification.cjs.map +1 -1
- package/dist/tools/components/error/ErrorNotification.js +10 -10
- package/dist/tools/components/error/ErrorNotification.js.map +1 -1
- package/dist/tools/components/file-browser/FilePreview.cjs +1 -1
- package/dist/tools/components/file-browser/FilePreview.cjs.map +1 -1
- package/dist/tools/components/file-browser/FilePreview.js +28 -26
- package/dist/tools/components/file-browser/FilePreview.js.map +1 -1
- package/dist/tools/components/filter/filter.cjs.map +1 -1
- package/dist/tools/components/filter/filter.d.cts +23 -34
- package/dist/tools/components/filter/filter.d.ts +23 -34
- package/dist/tools/components/filter/filter.js.map +1 -1
- package/dist/tools/components/form/EnhancedDetailPage.cjs.map +1 -1
- package/dist/tools/components/form/EnhancedDetailPage.d.cts +47 -42
- package/dist/tools/components/form/EnhancedDetailPage.d.ts +47 -42
- package/dist/tools/components/form/EnhancedDetailPage.js.map +1 -1
- package/dist/tools/components/form/form-grid.cjs.map +1 -1
- package/dist/tools/components/form/form-grid.d.cts +44 -22
- package/dist/tools/components/form/form-grid.d.ts +44 -22
- package/dist/tools/components/form/form-grid.js.map +1 -1
- package/dist/tools/components/gantt/GanttChart.cjs +1 -1
- package/dist/tools/components/gantt/GanttChart.cjs.map +1 -1
- package/dist/tools/components/gantt/GanttChart.d.cts +20 -1
- package/dist/tools/components/gantt/GanttChart.d.ts +20 -1
- package/dist/tools/components/gantt/GanttChart.js +3 -0
- package/dist/tools/components/gantt/GanttChart.js.map +1 -1
- package/dist/tools/components/gantt/components/GanttTaskBar.cjs +1 -1
- package/dist/tools/components/gantt/components/GanttTaskBar.cjs.map +1 -1
- package/dist/tools/components/gantt/components/GanttTaskBar.js +2 -1
- package/dist/tools/components/gantt/components/GanttTaskBar.js.map +1 -1
- package/dist/tools/components/header/header.cjs +1 -1
- package/dist/tools/components/header/header.cjs.map +1 -1
- package/dist/tools/components/header/header.d.cts +103 -40
- package/dist/tools/components/header/header.d.ts +103 -40
- package/dist/tools/components/header/header.js +1 -1
- package/dist/tools/components/header/header.js.map +1 -1
- package/dist/tools/components/i18n/LanguageSwitcher.cjs.map +1 -1
- package/dist/tools/components/i18n/LanguageSwitcher.d.cts +18 -14
- package/dist/tools/components/i18n/LanguageSwitcher.d.ts +18 -14
- package/dist/tools/components/i18n/LanguageSwitcher.js.map +1 -1
- package/dist/tools/components/kanban/KanbanBoard.cjs +1 -1
- package/dist/tools/components/kanban/KanbanBoard.cjs.map +1 -1
- package/dist/tools/components/kanban/KanbanBoard.d.cts +16 -34
- package/dist/tools/components/kanban/KanbanBoard.d.ts +16 -34
- package/dist/tools/components/kanban/KanbanBoard.js +3 -0
- package/dist/tools/components/kanban/KanbanBoard.js.map +1 -1
- package/dist/tools/components/kanban/KanbanColumn.cjs +1 -1
- package/dist/tools/components/kanban/KanbanColumn.cjs.map +1 -1
- package/dist/tools/components/kanban/KanbanColumn.js +1 -1
- package/dist/tools/components/kanban/KanbanColumn.js.map +1 -1
- package/dist/tools/components/kanban/kanban-compound.cjs +1 -1
- package/dist/tools/components/kanban/kanban-compound.cjs.map +1 -1
- package/dist/tools/components/kanban/kanban-compound.js +4 -1
- package/dist/tools/components/kanban/kanban-compound.js.map +1 -1
- package/dist/tools/components/kanban/kanban-primitives.cjs +1 -1
- package/dist/tools/components/kanban/kanban-primitives.cjs.map +1 -1
- package/dist/tools/components/kanban/kanban-primitives.js +0 -1
- package/dist/tools/components/kanban/kanban-primitives.js.map +1 -1
- package/dist/tools/components/priority-queue/PriorityCard.cjs +1 -1
- package/dist/tools/components/priority-queue/PriorityCard.cjs.map +1 -1
- package/dist/tools/components/priority-queue/PriorityCard.js +3 -1
- package/dist/tools/components/priority-queue/PriorityCard.js.map +1 -1
- package/dist/tools/components/sidebar/SmartSidebar.cjs.map +1 -1
- package/dist/tools/components/sidebar/SmartSidebar.d.cts +41 -43
- package/dist/tools/components/sidebar/SmartSidebar.d.ts +41 -43
- package/dist/tools/components/sidebar/SmartSidebar.js.map +1 -1
- package/dist/tools/components/splash/SplashScreen.cjs.map +1 -1
- package/dist/tools/components/splash/SplashScreen.d.cts +43 -68
- package/dist/tools/components/splash/SplashScreen.d.ts +43 -68
- package/dist/tools/components/splash/SplashScreen.js.map +1 -1
- package/dist/tools/components/workflow/WorkflowStatusPanel.cjs +1 -1
- package/dist/tools/components/workflow/WorkflowStatusPanel.cjs.map +1 -1
- package/dist/tools/components/workflow/WorkflowStatusPanel.js +2 -2
- package/dist/tools/components/workflow/WorkflowStatusPanel.js.map +1 -1
- package/dist/tools/lib/data-access/data-access-context.cjs.map +1 -1
- package/dist/tools/lib/data-access/data-access-context.d.cts +15 -6
- package/dist/tools/lib/data-access/data-access-context.d.ts +15 -6
- package/dist/tools/lib/data-access/data-access-context.js.map +1 -1
- package/dist/tools/lib/data-access/react-query-provider.cjs.map +1 -1
- package/dist/tools/lib/data-access/react-query-provider.d.cts +19 -2
- package/dist/tools/lib/data-access/react-query-provider.d.ts +19 -2
- package/dist/tools/lib/data-access/react-query-provider.js.map +1 -1
- package/dist/tools/lib/data-access/react-query.cjs.map +1 -1
- package/dist/tools/lib/data-access/react-query.d.cts +365 -90
- package/dist/tools/lib/data-access/react-query.d.ts +365 -90
- package/dist/tools/lib/data-access/react-query.js.map +1 -1
- package/dist/tools/lib/error/AppError.cjs.map +1 -1
- package/dist/tools/lib/error/AppError.d.cts +157 -63
- package/dist/tools/lib/error/AppError.d.ts +157 -63
- package/dist/tools/lib/error/AppError.js.map +1 -1
- package/dist/tools/lib/hooks/useAsyncWithTimeout.cjs.map +1 -1
- package/dist/tools/lib/hooks/useAsyncWithTimeout.d.cts +79 -26
- package/dist/tools/lib/hooks/useAsyncWithTimeout.d.ts +79 -26
- package/dist/tools/lib/hooks/useAsyncWithTimeout.js.map +1 -1
- package/dist/tools/lib/hooks/useError.cjs.map +1 -1
- package/dist/tools/lib/hooks/useError.d.cts +51 -16
- package/dist/tools/lib/hooks/useError.d.ts +51 -16
- package/dist/tools/lib/hooks/useError.js.map +1 -1
- package/dist/tools/lib/schema/ajv.cjs +1 -1
- package/dist/tools/lib/schema/ajv.cjs.map +1 -1
- package/dist/tools/lib/schema/ajv.d.cts +19 -8
- package/dist/tools/lib/schema/ajv.d.ts +19 -8
- package/dist/tools/lib/schema/ajv.js +2 -1
- package/dist/tools/lib/schema/ajv.js.map +1 -1
- package/dist/tools/lib/state/error-store.cjs.map +1 -1
- package/dist/tools/lib/state/error-store.d.cts +61 -10
- package/dist/tools/lib/state/error-store.d.ts +61 -10
- package/dist/tools/lib/state/error-store.js.map +1 -1
- package/dist/tools/lib/state/store-factory.cjs.map +1 -1
- package/dist/tools/lib/state/store-factory.d.cts +25 -4
- package/dist/tools/lib/state/store-factory.d.ts +25 -4
- package/dist/tools/lib/state/store-factory.js.map +1 -1
- package/dist/tools/lib/state/ui-store.cjs.map +1 -1
- package/dist/tools/lib/state/ui-store.d.cts +39 -0
- package/dist/tools/lib/state/ui-store.d.ts +39 -0
- package/dist/tools/lib/state/ui-store.js.map +1 -1
- package/dist/ui/components/theme/theme-context.cjs.map +1 -1
- package/dist/ui/components/theme/theme-context.d.cts +171 -1
- package/dist/ui/components/theme/theme-context.d.ts +171 -1
- package/dist/ui/components/theme/theme-context.js.map +1 -1
- package/dist/ui/components/theme/theme-provider.cjs.map +1 -1
- package/dist/ui/components/theme/theme-provider.d.cts +31 -19
- package/dist/ui/components/theme/theme-provider.d.ts +31 -19
- package/dist/ui/components/theme/theme-provider.js.map +1 -1
- package/dist/ui/components/theme/theme-script.cjs.map +1 -1
- package/dist/ui/components/theme/theme-script.d.cts +16 -1
- package/dist/ui/components/theme/theme-script.d.ts +16 -1
- package/dist/ui/components/theme/theme-script.js.map +1 -1
- package/dist/ui/components/theme/theme-switcher.cjs +1 -1
- package/dist/ui/components/theme/theme-switcher.cjs.map +1 -1
- package/dist/ui/components/theme/theme-switcher.d.cts +82 -13
- package/dist/ui/components/theme/theme-switcher.d.ts +82 -13
- package/dist/ui/components/theme/theme-switcher.js +8 -0
- package/dist/ui/components/theme/theme-switcher.js.map +1 -1
- package/dist/ui/components/ui/accordion.cjs.map +1 -1
- package/dist/ui/components/ui/accordion.d.cts +60 -0
- package/dist/ui/components/ui/accordion.d.ts +60 -0
- package/dist/ui/components/ui/accordion.js.map +1 -1
- package/dist/ui/components/ui/adjustable-pane.cjs.map +1 -1
- package/dist/ui/components/ui/adjustable-pane.d.cts +44 -26
- package/dist/ui/components/ui/adjustable-pane.d.ts +44 -26
- package/dist/ui/components/ui/adjustable-pane.js.map +1 -1
- package/dist/ui/components/ui/alert-dialog.cjs.map +1 -1
- package/dist/ui/components/ui/alert-dialog.d.cts +179 -2
- package/dist/ui/components/ui/alert-dialog.d.ts +179 -2
- package/dist/ui/components/ui/alert-dialog.js.map +1 -1
- package/dist/ui/components/ui/alert.cjs.map +1 -1
- package/dist/ui/components/ui/alert.d.cts +52 -4
- package/dist/ui/components/ui/alert.d.ts +52 -4
- package/dist/ui/components/ui/alert.js.map +1 -1
- package/dist/ui/components/ui/aspect-ratio.cjs.map +1 -1
- package/dist/ui/components/ui/aspect-ratio.d.cts +16 -1
- package/dist/ui/components/ui/aspect-ratio.d.ts +16 -1
- package/dist/ui/components/ui/aspect-ratio.js.map +1 -1
- package/dist/ui/components/ui/avatar.cjs.map +1 -1
- package/dist/ui/components/ui/avatar.d.cts +87 -3
- package/dist/ui/components/ui/avatar.d.ts +87 -3
- package/dist/ui/components/ui/avatar.js.map +1 -1
- package/dist/ui/components/ui/badge-components.cjs.map +1 -1
- package/dist/ui/components/ui/badge-components.d.cts +13 -1
- package/dist/ui/components/ui/badge-components.d.ts +13 -1
- package/dist/ui/components/ui/badge-components.js.map +1 -1
- package/dist/ui/components/ui/badge-variants.cjs.map +1 -1
- package/dist/ui/components/ui/badge-variants.d.cts +15 -0
- package/dist/ui/components/ui/badge-variants.d.ts +15 -0
- package/dist/ui/components/ui/badge-variants.js.map +1 -1
- package/dist/ui/components/ui/breadcrumb.cjs.map +1 -1
- package/dist/ui/components/ui/breadcrumb.d.cts +91 -7
- package/dist/ui/components/ui/breadcrumb.d.ts +91 -7
- package/dist/ui/components/ui/breadcrumb.js.map +1 -1
- package/dist/ui/components/ui/button-components.cjs.map +1 -1
- package/dist/ui/components/ui/button-components.d.cts +18 -6
- package/dist/ui/components/ui/button-components.d.ts +18 -6
- package/dist/ui/components/ui/button-components.js.map +1 -1
- package/dist/ui/components/ui/button-group-components.cjs.map +1 -1
- package/dist/ui/components/ui/button-group-components.d.cts +39 -3
- package/dist/ui/components/ui/button-group-components.d.ts +39 -3
- package/dist/ui/components/ui/button-group-components.js.map +1 -1
- package/dist/ui/components/ui/button-group-variants.cjs.map +1 -1
- package/dist/ui/components/ui/button-group-variants.d.cts +15 -0
- package/dist/ui/components/ui/button-group-variants.d.ts +15 -0
- package/dist/ui/components/ui/button-group-variants.js.map +1 -1
- package/dist/ui/components/ui/button-variants.cjs.map +1 -1
- package/dist/ui/components/ui/button-variants.d.cts +13 -2
- package/dist/ui/components/ui/button-variants.d.ts +13 -2
- package/dist/ui/components/ui/button-variants.js.map +1 -1
- package/dist/ui/components/ui/card.cjs.map +1 -1
- package/dist/ui/components/ui/card.d.cts +106 -2
- package/dist/ui/components/ui/card.d.ts +106 -2
- package/dist/ui/components/ui/card.js.map +1 -1
- package/dist/ui/components/ui/checkbox-group.cjs.map +1 -1
- package/dist/ui/components/ui/checkbox-group.d.cts +13 -1
- package/dist/ui/components/ui/checkbox-group.d.ts +13 -1
- package/dist/ui/components/ui/checkbox-group.js.map +1 -1
- package/dist/ui/components/ui/checkbox.cjs.map +1 -1
- package/dist/ui/components/ui/checkbox.d.cts +17 -6
- package/dist/ui/components/ui/checkbox.d.ts +17 -6
- package/dist/ui/components/ui/checkbox.js.map +1 -1
- package/dist/ui/components/ui/collapsible.cjs.map +1 -1
- package/dist/ui/components/ui/collapsible.d.cts +39 -3
- package/dist/ui/components/ui/collapsible.d.ts +39 -3
- package/dist/ui/components/ui/collapsible.js.map +1 -1
- package/dist/ui/components/ui/combobox-components.cjs.map +1 -1
- package/dist/ui/components/ui/combobox-components.d.cts +209 -14
- package/dist/ui/components/ui/combobox-components.d.ts +209 -14
- package/dist/ui/components/ui/combobox-components.js.map +1 -1
- package/dist/ui/components/ui/combobox-hooks.cjs.map +1 -1
- package/dist/ui/components/ui/combobox-hooks.d.cts +13 -1
- package/dist/ui/components/ui/combobox-hooks.d.ts +13 -1
- package/dist/ui/components/ui/combobox-hooks.js.map +1 -1
- package/dist/ui/components/ui/command.cjs.map +1 -1
- package/dist/ui/components/ui/command.d.cts +132 -9
- package/dist/ui/components/ui/command.d.ts +132 -9
- package/dist/ui/components/ui/command.js.map +1 -1
- package/dist/ui/components/ui/context-menu.cjs.map +1 -1
- package/dist/ui/components/ui/context-menu.d.cts +233 -2
- package/dist/ui/components/ui/context-menu.d.ts +233 -2
- package/dist/ui/components/ui/context-menu.js.map +1 -1
- package/dist/ui/components/ui/dialog.cjs.map +1 -1
- package/dist/ui/components/ui/dialog.d.cts +157 -5
- package/dist/ui/components/ui/dialog.d.ts +157 -5
- package/dist/ui/components/ui/dialog.js.map +1 -1
- package/dist/ui/components/ui/drawer.cjs.map +1 -1
- package/dist/ui/components/ui/drawer.d.cts +130 -10
- package/dist/ui/components/ui/drawer.d.ts +130 -10
- package/dist/ui/components/ui/drawer.js.map +1 -1
- package/dist/ui/components/ui/dropdown-menu.cjs.map +1 -1
- package/dist/ui/components/ui/dropdown-menu.d.cts +225 -6
- package/dist/ui/components/ui/dropdown-menu.d.ts +225 -6
- package/dist/ui/components/ui/dropdown-menu.js.map +1 -1
- package/dist/ui/components/ui/empty.cjs.map +1 -1
- package/dist/ui/components/ui/empty.d.cts +78 -6
- package/dist/ui/components/ui/empty.d.ts +78 -6
- package/dist/ui/components/ui/empty.js.map +1 -1
- package/dist/ui/components/ui/field.cjs.map +1 -1
- package/dist/ui/components/ui/field.d.cts +180 -6
- package/dist/ui/components/ui/field.d.ts +180 -6
- package/dist/ui/components/ui/field.js.map +1 -1
- package/dist/ui/components/ui/file-icon.cjs.map +1 -1
- package/dist/ui/components/ui/file-icon.d.cts +32 -4
- package/dist/ui/components/ui/file-icon.d.ts +32 -4
- package/dist/ui/components/ui/file-icon.js.map +1 -1
- package/dist/ui/components/ui/hover-card.cjs.map +1 -1
- package/dist/ui/components/ui/hover-card.d.cts +39 -3
- package/dist/ui/components/ui/hover-card.d.ts +39 -3
- package/dist/ui/components/ui/hover-card.js.map +1 -1
- package/dist/ui/components/ui/input-group.cjs.map +1 -1
- package/dist/ui/components/ui/input-group.d.cts +84 -6
- package/dist/ui/components/ui/input-group.d.ts +84 -6
- package/dist/ui/components/ui/input-group.js.map +1 -1
- package/dist/ui/components/ui/input-otp.cjs.map +1 -1
- package/dist/ui/components/ui/input-otp.d.cts +58 -4
- package/dist/ui/components/ui/input-otp.d.ts +58 -4
- package/dist/ui/components/ui/input-otp.js.map +1 -1
- package/dist/ui/components/ui/input.cjs.map +1 -1
- package/dist/ui/components/ui/input.d.cts +18 -10
- package/dist/ui/components/ui/input.d.ts +18 -10
- package/dist/ui/components/ui/input.js.map +1 -1
- package/dist/ui/components/ui/item.cjs.map +1 -1
- package/dist/ui/components/ui/item.d.cts +130 -10
- package/dist/ui/components/ui/item.d.ts +130 -10
- package/dist/ui/components/ui/item.js.map +1 -1
- package/dist/ui/components/ui/kbd.cjs.map +1 -1
- package/dist/ui/components/ui/kbd.d.cts +26 -2
- package/dist/ui/components/ui/kbd.d.ts +26 -2
- package/dist/ui/components/ui/kbd.js.map +1 -1
- package/dist/ui/components/ui/label.cjs.map +1 -1
- package/dist/ui/components/ui/label.d.cts +15 -0
- package/dist/ui/components/ui/label.d.ts +15 -0
- package/dist/ui/components/ui/label.js.map +1 -1
- package/dist/ui/components/ui/layout.cjs +1 -1
- package/dist/ui/components/ui/layout.cjs.map +1 -1
- package/dist/ui/components/ui/layout.d.cts +45 -11
- package/dist/ui/components/ui/layout.d.ts +45 -11
- package/dist/ui/components/ui/layout.js +22 -20
- package/dist/ui/components/ui/layout.js.map +1 -1
- package/dist/ui/components/ui/menubar.cjs.map +1 -1
- package/dist/ui/components/ui/menubar.d.cts +220 -16
- package/dist/ui/components/ui/menubar.d.ts +220 -16
- package/dist/ui/components/ui/menubar.js.map +1 -1
- package/dist/ui/components/ui/meter.cjs.map +1 -1
- package/dist/ui/components/ui/meter.d.cts +52 -4
- package/dist/ui/components/ui/meter.d.ts +52 -4
- package/dist/ui/components/ui/meter.js.map +1 -1
- package/dist/ui/components/ui/mobile-form-variants.cjs.map +1 -1
- package/dist/ui/components/ui/mobile-form-variants.d.cts +30 -0
- package/dist/ui/components/ui/mobile-form-variants.d.ts +30 -0
- package/dist/ui/components/ui/mobile-form-variants.js.map +1 -1
- package/dist/ui/components/ui/mobile-form.cjs.map +1 -1
- package/dist/ui/components/ui/mobile-form.d.cts +186 -9
- package/dist/ui/components/ui/mobile-form.d.ts +186 -9
- package/dist/ui/components/ui/mobile-form.js.map +1 -1
- package/dist/ui/components/ui/navigation-menu-components.cjs.map +1 -1
- package/dist/ui/components/ui/navigation-menu-components.d.cts +104 -8
- package/dist/ui/components/ui/navigation-menu-components.d.ts +104 -8
- package/dist/ui/components/ui/navigation-menu-components.js.map +1 -1
- package/dist/ui/components/ui/navigation-menu-variants.cjs.map +1 -1
- package/dist/ui/components/ui/navigation-menu-variants.d.cts +15 -0
- package/dist/ui/components/ui/navigation-menu-variants.d.ts +15 -0
- package/dist/ui/components/ui/navigation-menu-variants.js.map +1 -1
- package/dist/ui/components/ui/number-field.cjs.map +1 -1
- package/dist/ui/components/ui/number-field.d.cts +78 -6
- package/dist/ui/components/ui/number-field.d.ts +78 -6
- package/dist/ui/components/ui/number-field.js.map +1 -1
- package/dist/ui/components/ui/pagination.cjs.map +1 -1
- package/dist/ui/components/ui/pagination.d.cts +99 -7
- package/dist/ui/components/ui/pagination.d.ts +99 -7
- package/dist/ui/components/ui/pagination.js.map +1 -1
- package/dist/ui/components/ui/password-input.cjs.map +1 -1
- package/dist/ui/components/ui/password-input.d.cts +10 -7
- package/dist/ui/components/ui/password-input.d.ts +10 -7
- package/dist/ui/components/ui/password-input.js.map +1 -1
- package/dist/ui/components/ui/popover.cjs.map +1 -1
- package/dist/ui/components/ui/popover.d.cts +86 -2
- package/dist/ui/components/ui/popover.d.ts +86 -2
- package/dist/ui/components/ui/popover.js.map +1 -1
- package/dist/ui/components/ui/progress.cjs.map +1 -1
- package/dist/ui/components/ui/progress.d.cts +72 -2
- package/dist/ui/components/ui/progress.d.ts +72 -2
- package/dist/ui/components/ui/progress.js.map +1 -1
- package/dist/ui/components/ui/radio-card.cjs.map +1 -1
- package/dist/ui/components/ui/radio-card.d.cts +32 -4
- package/dist/ui/components/ui/radio-card.d.ts +32 -4
- package/dist/ui/components/ui/radio-card.js.map +1 -1
- package/dist/ui/components/ui/radio-group.cjs.map +1 -1
- package/dist/ui/components/ui/radio-group.d.cts +28 -2
- package/dist/ui/components/ui/radio-group.d.ts +28 -2
- package/dist/ui/components/ui/radio-group.js.map +1 -1
- package/dist/ui/components/ui/resizable.cjs.map +1 -1
- package/dist/ui/components/ui/resizable.d.cts +42 -3
- package/dist/ui/components/ui/resizable.d.ts +42 -3
- package/dist/ui/components/ui/resizable.js.map +1 -1
- package/dist/ui/components/ui/responsive-list.cjs.map +1 -1
- package/dist/ui/components/ui/responsive-list.d.cts +176 -13
- package/dist/ui/components/ui/responsive-list.d.ts +176 -13
- package/dist/ui/components/ui/responsive-list.js.map +1 -1
- package/dist/ui/components/ui/scroll-area.cjs.map +1 -1
- package/dist/ui/components/ui/scroll-area.d.cts +28 -1
- package/dist/ui/components/ui/scroll-area.d.ts +28 -1
- package/dist/ui/components/ui/scroll-area.js.map +1 -1
- package/dist/ui/components/ui/searchable-select-input.cjs.map +1 -1
- package/dist/ui/components/ui/searchable-select-input.d.cts +199 -49
- package/dist/ui/components/ui/searchable-select-input.d.ts +199 -49
- package/dist/ui/components/ui/searchable-select-input.js.map +1 -1
- package/dist/ui/components/ui/select.cjs.map +1 -1
- package/dist/ui/components/ui/select.d.cts +205 -40
- package/dist/ui/components/ui/select.d.ts +205 -40
- package/dist/ui/components/ui/select.js.map +1 -1
- package/dist/ui/components/ui/separator.cjs.map +1 -1
- package/dist/ui/components/ui/separator.d.cts +13 -2
- package/dist/ui/components/ui/separator.d.ts +13 -2
- package/dist/ui/components/ui/separator.js.map +1 -1
- package/dist/ui/components/ui/sheet.cjs.map +1 -1
- package/dist/ui/components/ui/sheet.d.cts +128 -3
- package/dist/ui/components/ui/sheet.d.ts +128 -3
- package/dist/ui/components/ui/sheet.js.map +1 -1
- package/dist/ui/components/ui/skeleton.cjs.map +1 -1
- package/dist/ui/components/ui/skeleton.d.cts +13 -1
- package/dist/ui/components/ui/skeleton.d.ts +13 -1
- package/dist/ui/components/ui/skeleton.js.map +1 -1
- package/dist/ui/components/ui/slider.cjs.map +1 -1
- package/dist/ui/components/ui/slider.d.cts +13 -7
- package/dist/ui/components/ui/slider.d.ts +13 -7
- package/dist/ui/components/ui/slider.js.map +1 -1
- package/dist/ui/components/ui/spinner.cjs.map +1 -1
- package/dist/ui/components/ui/spinner.d.cts +13 -1
- package/dist/ui/components/ui/spinner.d.ts +13 -1
- package/dist/ui/components/ui/spinner.js.map +1 -1
- package/dist/ui/components/ui/switch.cjs.map +1 -1
- package/dist/ui/components/ui/switch.d.cts +26 -0
- package/dist/ui/components/ui/switch.d.ts +26 -0
- package/dist/ui/components/ui/switch.js.map +1 -1
- package/dist/ui/components/ui/table.cjs.map +1 -1
- package/dist/ui/components/ui/table.d.cts +118 -2
- package/dist/ui/components/ui/table.d.ts +118 -2
- package/dist/ui/components/ui/table.js.map +1 -1
- package/dist/ui/components/ui/tabs-components.cjs.map +1 -1
- package/dist/ui/components/ui/tabs-components.d.cts +52 -5
- package/dist/ui/components/ui/tabs-components.d.ts +52 -5
- package/dist/ui/components/ui/tabs-components.js.map +1 -1
- package/dist/ui/components/ui/tabs-variants.cjs.map +1 -1
- package/dist/ui/components/ui/tabs-variants.d.cts +15 -0
- package/dist/ui/components/ui/tabs-variants.d.ts +15 -0
- package/dist/ui/components/ui/tabs-variants.js.map +1 -1
- package/dist/ui/components/ui/textarea.cjs.map +1 -1
- package/dist/ui/components/ui/textarea.d.cts +23 -0
- package/dist/ui/components/ui/textarea.d.ts +23 -0
- package/dist/ui/components/ui/textarea.js.map +1 -1
- package/dist/ui/components/ui/toast.cjs.map +1 -1
- package/dist/ui/components/ui/toast.d.cts +136 -0
- package/dist/ui/components/ui/toast.d.ts +136 -0
- package/dist/ui/components/ui/toast.js.map +1 -1
- package/dist/ui/components/ui/toaster.cjs.map +1 -1
- package/dist/ui/components/ui/toaster.d.cts +12 -3
- package/dist/ui/components/ui/toaster.d.ts +12 -3
- package/dist/ui/components/ui/toaster.js.map +1 -1
- package/dist/ui/components/ui/toggle-components.cjs.map +1 -1
- package/dist/ui/components/ui/toggle-components.d.cts +15 -0
- package/dist/ui/components/ui/toggle-components.d.ts +15 -0
- package/dist/ui/components/ui/toggle-components.js.map +1 -1
- package/dist/ui/components/ui/toggle-group.cjs.map +1 -1
- package/dist/ui/components/ui/toggle-group.d.cts +33 -0
- package/dist/ui/components/ui/toggle-group.d.ts +33 -0
- package/dist/ui/components/ui/toggle-group.js.map +1 -1
- package/dist/ui/components/ui/toggle-variants.cjs.map +1 -1
- package/dist/ui/components/ui/toggle-variants.d.cts +15 -0
- package/dist/ui/components/ui/toggle-variants.d.ts +15 -0
- package/dist/ui/components/ui/toggle-variants.js.map +1 -1
- package/dist/ui/components/ui/toolbar.cjs.map +1 -1
- package/dist/ui/components/ui/toolbar.d.cts +94 -7
- package/dist/ui/components/ui/toolbar.d.ts +94 -7
- package/dist/ui/components/ui/toolbar.js.map +1 -1
- package/dist/ui/components/ui/tooltip.cjs.map +1 -1
- package/dist/ui/components/ui/tooltip.d.cts +54 -3
- package/dist/ui/components/ui/tooltip.d.ts +54 -3
- package/dist/ui/components/ui/tooltip.js.map +1 -1
- package/dist/ui/lib/hooks/use-gps.cjs.map +1 -1
- package/dist/ui/lib/hooks/use-gps.d.cts +29 -4
- package/dist/ui/lib/hooks/use-gps.d.ts +29 -4
- package/dist/ui/lib/hooks/use-gps.js.map +1 -1
- package/dist/ui/lib/hooks/use-is-client.cjs.map +1 -1
- package/dist/ui/lib/hooks/use-is-client.d.cts +11 -2
- package/dist/ui/lib/hooks/use-is-client.d.ts +11 -2
- package/dist/ui/lib/hooks/use-is-client.js.map +1 -1
- package/dist/ui/lib/hooks/use-keyboard-shortcut.cjs.map +1 -1
- package/dist/ui/lib/hooks/use-keyboard-shortcut.d.cts +48 -18
- package/dist/ui/lib/hooks/use-keyboard-shortcut.d.ts +48 -18
- package/dist/ui/lib/hooks/use-keyboard-shortcut.js.map +1 -1
- package/dist/ui/lib/hooks/use-mobile.cjs.map +1 -1
- package/dist/ui/lib/hooks/use-mobile.d.cts +11 -3
- package/dist/ui/lib/hooks/use-mobile.d.ts +11 -3
- package/dist/ui/lib/hooks/use-mobile.js.map +1 -1
- package/dist/ui/lib/hooks/use-toast.cjs.map +1 -1
- package/dist/ui/lib/hooks/use-toast.d.cts +184 -15
- package/dist/ui/lib/hooks/use-toast.d.ts +184 -15
- package/dist/ui/lib/hooks/use-toast.js.map +1 -1
- package/dist/ui/lib/ime-utils.cjs.map +1 -1
- package/dist/ui/lib/ime-utils.d.cts +40 -13
- package/dist/ui/lib/ime-utils.d.ts +40 -13
- package/dist/ui/lib/ime-utils.js.map +1 -1
- package/dist/ui/lib/utils.cjs.map +1 -1
- package/dist/ui/lib/utils.d.cts +9 -6
- package/dist/ui/lib/utils.d.ts +9 -6
- package/dist/ui/lib/utils.js.map +1 -1
- package/docs/ai.md +34 -1
- package/docs/exports.md +5 -1
- package/docs/index.md +89 -16
- package/docs/migration.md +268 -0
- package/docs/request-form.md +4 -1
- package/docs/tools.md +4 -1
- package/docs/ui.md +4 -1
- package/llms-full.txt +499 -36
- package/llms.txt +4 -0
- package/package.json +35 -5
|
@@ -1,36 +1,162 @@
|
|
|
1
1
|
import { ExecutionContext, ExecutionRecord, ApplyProposalPayload, FieldDecision, FieldKey, PreparedProposalBatch, ProposalBatchItem, ProposalBatchValidator, ReviewDecisions } from '@alneas/appkit-core/ai';
|
|
2
|
-
/**
|
|
2
|
+
/**
|
|
3
|
+
* Host inputs for reviewing unique immutable proposals across multiple records.
|
|
4
|
+
*
|
|
5
|
+
* @typeParam TRecord - Record shape; defaults to a string-keyed record.
|
|
6
|
+
*
|
|
7
|
+
* @see useProposalBatchReview for usage.
|
|
8
|
+
*/
|
|
3
9
|
export interface UseProposalBatchReviewOptions<TRecord extends Record<string, any> = Record<string, any>> {
|
|
4
10
|
/** Change for a new review session, including an intentional replay of the same proposals. */
|
|
5
11
|
batchId: string;
|
|
12
|
+
/**
|
|
13
|
+
* Validated proposals and latest records/versions; proposal IDs must be unique.
|
|
14
|
+
*/
|
|
6
15
|
items: readonly ProposalBatchItem<TRecord>[];
|
|
16
|
+
/**
|
|
17
|
+
* Optional synchronous validator passed to Core batch preparation; thrown errors become invalid_candidate issues.
|
|
18
|
+
*/
|
|
7
19
|
validateCandidate?: ProposalBatchValidator<TRecord>;
|
|
8
|
-
/**
|
|
20
|
+
/**
|
|
21
|
+
* Sequential host callback receiving one prepared payload and cooperative abort/progress context.
|
|
22
|
+
*
|
|
23
|
+
* @param payload - Validated candidate and decisions for one proposal.
|
|
24
|
+
*
|
|
25
|
+
* @param context - Abort signal and fractional-progress reporting for this row.
|
|
26
|
+
*
|
|
27
|
+
* @returns No value after the host confirms application; reject to stop later rows.
|
|
28
|
+
*/
|
|
9
29
|
onApply?: (payload: ApplyProposalPayload<TRecord>, context: ExecutionContext) => void | Promise<void>;
|
|
10
30
|
}
|
|
11
|
-
/**
|
|
31
|
+
/**
|
|
32
|
+
* Batch selection/decision state and explicit execution controls.
|
|
33
|
+
*
|
|
34
|
+
* @typeParam TRecord - Shared record shape; defaults to a string-keyed record.
|
|
35
|
+
*
|
|
36
|
+
* @see useProposalBatchReview for usage.
|
|
37
|
+
*/
|
|
12
38
|
export interface UseProposalBatchReviewReturn<TRecord extends Record<string, any> = Record<string, any>> {
|
|
39
|
+
/**
|
|
40
|
+
* Current selected proposal IDs; applied IDs are excluded from preparation.
|
|
41
|
+
*/
|
|
13
42
|
selectedIds: ReadonlySet<string>;
|
|
43
|
+
/**
|
|
44
|
+
* Host-confirmed successes in this review session.
|
|
45
|
+
*/
|
|
14
46
|
appliedIds: ReadonlySet<string>;
|
|
47
|
+
/**
|
|
48
|
+
* Per-proposal field decisions; absent choices remain pending.
|
|
49
|
+
*/
|
|
15
50
|
decisions: ReadonlyMap<string, ReviewDecisions<TRecord>>;
|
|
51
|
+
/**
|
|
52
|
+
* Core batch preflight result for current selection and latest input props.
|
|
53
|
+
*/
|
|
16
54
|
preparation: PreparedProposalBatch<TRecord>;
|
|
55
|
+
/**
|
|
56
|
+
* Whether a handler exists, preparation passes and state is not submitting.
|
|
57
|
+
*/
|
|
17
58
|
canApply: boolean;
|
|
59
|
+
/**
|
|
60
|
+
* Whether the displayed batch is currently running.
|
|
61
|
+
*/
|
|
18
62
|
isSubmitting: boolean;
|
|
63
|
+
/**
|
|
64
|
+
* Current row being applied, or null outside active row work.
|
|
65
|
+
*/
|
|
19
66
|
activeProposalId: string | null;
|
|
67
|
+
/**
|
|
68
|
+
* Generic current-session batch failure message, or null; raw host exceptions are not exposed.
|
|
69
|
+
*/
|
|
20
70
|
error: string | null;
|
|
71
|
+
/**
|
|
72
|
+
* Read-only execution history for this batch session.
|
|
73
|
+
*/
|
|
21
74
|
history: readonly ExecutionRecord[];
|
|
75
|
+
/**
|
|
76
|
+
* Select or deselect an editable known proposal.
|
|
77
|
+
*
|
|
78
|
+
* @param id - Proposal identifier.
|
|
79
|
+
*
|
|
80
|
+
* @param selected - Desired selection state.
|
|
81
|
+
*
|
|
82
|
+
* @returns No value; unknown/applied/busy proposals are ignored.
|
|
83
|
+
*/
|
|
22
84
|
setSelected(id: string, selected: boolean): void;
|
|
85
|
+
/**
|
|
86
|
+
* Change selection for the current items when idle.
|
|
87
|
+
*
|
|
88
|
+
* @param selected - True selects all current IDs; false retains only applied IDs in the selection set.
|
|
89
|
+
*
|
|
90
|
+
* @returns No value; calls while execution is busy are ignored.
|
|
91
|
+
*/
|
|
23
92
|
selectAll(selected: boolean): void;
|
|
93
|
+
/**
|
|
94
|
+
* Change one existing proposed field while editable.
|
|
95
|
+
*
|
|
96
|
+
* @param id - Proposal identifier.
|
|
97
|
+
*
|
|
98
|
+
* @param field - Field present in that proposal.
|
|
99
|
+
*
|
|
100
|
+
* @param decision - Pending, accepted or rejected choice.
|
|
101
|
+
*
|
|
102
|
+
* @returns No value; invalid IDs/fields and busy/applied proposals are ignored.
|
|
103
|
+
*/
|
|
24
104
|
setDecision(id: string, field: FieldKey<TRecord>, decision: FieldDecision): void;
|
|
105
|
+
/**
|
|
106
|
+
* Change every proposed field choice for one editable proposal.
|
|
107
|
+
*
|
|
108
|
+
* @param id - Proposal identifier.
|
|
109
|
+
*
|
|
110
|
+
* @param decision - Choice applied to all its changes.
|
|
111
|
+
*
|
|
112
|
+
* @returns No value; unknown/applied/busy proposals are ignored.
|
|
113
|
+
*/
|
|
25
114
|
decideAll(id: string, decision: FieldDecision): void;
|
|
115
|
+
/**
|
|
116
|
+
* Preflight the selection, then apply rows sequentially with latest-record rechecks.
|
|
117
|
+
*
|
|
118
|
+
* @returns True only for current-session complete success; false when blocked, failed, cancelled or superseded.
|
|
119
|
+
*
|
|
120
|
+
* @remarks Confirmed successes are retained and skipped on retry; unconfirmed backend effects may still exist.
|
|
121
|
+
*/
|
|
26
122
|
apply(): Promise<boolean>;
|
|
123
|
+
/**
|
|
124
|
+
* Request cooperative cancellation of current execution.
|
|
125
|
+
*
|
|
126
|
+
* @returns No value; does not roll back previously applied rows or force host work to stop.
|
|
127
|
+
*/
|
|
27
128
|
cancel(): void;
|
|
129
|
+
/**
|
|
130
|
+
* Clear settled execution history using the session policy.
|
|
131
|
+
*
|
|
132
|
+
* @returns No value; does not clear review choices or confirmed applied IDs.
|
|
133
|
+
*/
|
|
28
134
|
clearHistory(): void;
|
|
29
135
|
}
|
|
30
136
|
/**
|
|
31
|
-
* Reviews
|
|
32
|
-
*
|
|
33
|
-
*
|
|
34
|
-
*
|
|
137
|
+
* Reviews a batch with explicit field decisions and sequential host application.
|
|
138
|
+
*
|
|
139
|
+
* @typeParam TRecord - Record shape; defaults to a string-keyed record.
|
|
140
|
+
*
|
|
141
|
+
* @param options - Batch identity, unique immutable proposals/latest records, validation and optional host apply callback.
|
|
142
|
+
*
|
|
143
|
+
* @returns Selection/decision controls, preflight state, bounded execution history and cooperative cancellation.
|
|
144
|
+
*
|
|
145
|
+
* @remarks Requires React; no context/styles. Changing batchId or serialized proposal
|
|
146
|
+
* content starts a new session; unmount/session changes request cancellation. Each row
|
|
147
|
+
* is rechecked against latest committed host inputs before apply. Stops at the first
|
|
148
|
+
* failure/cancellation; successes remain excluded from retries. Cancellation cannot
|
|
149
|
+
* undo host effects, so persist idempotently and enforce concurrency/authorization in
|
|
150
|
+
* the backend. A row that changed the backend before rejecting has an uncertain outcome.
|
|
151
|
+
*
|
|
152
|
+
* @example
|
|
153
|
+
* ```tsx
|
|
154
|
+
* import { useProposalBatchReview, type UseProposalBatchReviewOptions } from '@alneas/appkit-react/ai/proposal';
|
|
155
|
+
* type RecordData = { title: string };
|
|
156
|
+
* export function Batch({ options }: { options: UseProposalBatchReviewOptions<RecordData> }) {
|
|
157
|
+
* const review = useProposalBatchReview(options);
|
|
158
|
+
* return <button disabled={!review.canApply} onClick={() => { void review.apply(); }}>Apply selected records</button>;
|
|
159
|
+
* }
|
|
160
|
+
* ```
|
|
35
161
|
*/
|
|
36
162
|
export declare function useProposalBatchReview<TRecord extends Record<string, any> = Record<string, any>>(options: UseProposalBatchReviewOptions<TRecord>): UseProposalBatchReviewReturn<TRecord>;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"use-proposal-batch-review.js","names":["initial","createExecutionSession","useProposalBatchReview","key","options","item","stored","setStored","useState","state","session","live","useRef","latest","useLayoutEffect","current","history","useSyncExternalStore","busy","record","update","change","entries","items","applied","preparation","prepareProposalBatch","editable","id","next","value","selected","field","decision","planned","outcome","completed","payload","context","checked","fraction","progress"],"sources":["../../../src/ai/proposal/use-proposal-batch-review.ts"],"sourcesContent":["import { useLayoutEffect, useRef, useState, useSyncExternalStore } from 'react';\nimport { createExecutionSession, type ExecutionContext, type ExecutionRecord, type ExecutionSession } from \"@alneas/appkit-core/ai\";\nimport {\n prepareProposalBatch,\n type ApplyProposalPayload,\n type FieldDecision,\n type FieldKey,\n type PreparedProposalBatch,\n type ProposalBatchEntry,\n type ProposalBatchItem,\n type ProposalBatchValidator,\n type ReviewDecisions,\n} from \"@alneas/appkit-core/ai\";\n\n/** Multi-record review. Each item must have a unique validated immutable proposal. */\nexport interface UseProposalBatchReviewOptions<TRecord extends Record<string, any> = Record<string, any>> {\n /** Change for a new review session, including an intentional replay of the same proposals. */\n batchId: string;\n items: readonly ProposalBatchItem<TRecord>[];\n validateCandidate?: ProposalBatchValidator<TRecord>;\n /** Called sequentially. Resolve only when this row is applied; reject to stop the batch. */\n onApply?: (payload: ApplyProposalPayload<TRecord>, context: ExecutionContext) => void | Promise<void>;\n}\n\n/** Headless controller shared by batch lists and custom application layouts. */\nexport interface UseProposalBatchReviewReturn<TRecord extends Record<string, any> = Record<string, any>> {\n selectedIds: ReadonlySet<string>;\n appliedIds: ReadonlySet<string>;\n decisions: ReadonlyMap<string, ReviewDecisions<TRecord>>;\n preparation: PreparedProposalBatch<TRecord>;\n canApply: boolean;\n isSubmitting: boolean;\n activeProposalId: string | null;\n error: string | null;\n history: readonly ExecutionRecord[];\n setSelected(id: string, selected: boolean): void;\n selectAll(selected: boolean): void;\n setDecision(id: string, field: FieldKey<TRecord>, decision: FieldDecision): void;\n decideAll(id: string, decision: FieldDecision): void;\n apply(): Promise<boolean>;\n cancel(): void;\n clearHistory(): void;\n}\n\ninterface ReviewState<TRecord extends Record<string, any>> {\n key: string;\n session: ExecutionSession;\n selected: ReadonlySet<string>;\n applied: ReadonlySet<string>;\n decisions: ReadonlyMap<string, ReviewDecisions<TRecord>>;\n running: boolean;\n active: string | null;\n error: string | null;\n}\n\nfunction initial<TRecord extends Record<string, any>>(key: string): ReviewState<TRecord> {\n return {\n key,\n session: createExecutionSession(),\n selected: new Set(),\n applied: new Set(),\n decisions: new Map(),\n running: false,\n active: null,\n error: null,\n };\n}\n\n/**\n * Reviews multiple records without implicit field acceptance. Preflights the entire\n * selection, then rechecks each latest committed record immediately before applying it.\n * Stops on first failure or cancellation; confirmed successes are never retried within\n * this session.\n */\nexport function useProposalBatchReview<TRecord extends Record<string, any> = Record<string, any>>(\n options: UseProposalBatchReviewOptions<TRecord>\n): UseProposalBatchReviewReturn<TRecord> {\n const key = JSON.stringify([options.batchId, options.items.map(item => JSON.stringify(item.proposal)).sort()]);\n const [stored, setStored] = useState(() => initial<TRecord>(key));\n let state = stored;\n if (state.key !== key) {\n state = initial<TRecord>(key);\n setStored(state);\n }\n const session = state.session;\n const live = useRef<{ session: ExecutionSession; applied: Set<string> } | null>(null);\n const latest = useRef(options);\n useLayoutEffect(() => {\n latest.current = options;\n });\n useLayoutEffect(() => {\n const current = { session, applied: new Set<string>() };\n live.current = current;\n return () => {\n session.cancel();\n if (live.current === current) live.current = null;\n };\n }, [session]);\n\n const history = useSyncExternalStore(session.subscribe, session.getSnapshot, session.getSnapshot);\n const busy = () => session.getSnapshot().some(record => record.status === 'running' || record.status === 'cancelling');\n const update = (change: (current: ReviewState<TRecord>) => ReviewState<TRecord>) => {\n setStored(current => (current.session === session ? change(current) : current));\n };\n\n const entries = (\n items: readonly ProposalBatchItem<TRecord>[],\n applied: ReadonlySet<string>\n ): ProposalBatchEntry<TRecord>[] =>\n items.map(item => ({\n ...item,\n decisions: state.decisions.get(item.proposal.id) ?? ({} as ReviewDecisions<TRecord>),\n selected: state.selected.has(item.proposal.id) && !applied.has(item.proposal.id),\n }));\n\n const preparation = prepareProposalBatch(entries(options.items, state.applied), options.validateCandidate);\n const editable = (id: string) =>\n live.current?.session === session && !busy() && !live.current.applied.has(id) && options.items.some(item => item.proposal.id === id);\n\n const apply = async (): Promise<boolean> => {\n const current = live.current;\n if (!current || current.session !== session || busy() || !latest.current.onApply) return false;\n const planned = prepareProposalBatch(entries(latest.current.items, current.applied), latest.current.validateCandidate);\n if (!planned.canApply) return false;\n update(value => ({ ...value, running: true, error: null }));\n const outcome = await session.run(`一括適用 ${planned.payloads.length} 件`, async context => {\n context.reportProgress({ completed: 0, total: planned.payloads.length });\n let completed = 0;\n for (const payload of planned.payloads) {\n context.signal.throwIfAborted();\n if (live.current !== current) throw new DOMException('Review session changed', 'AbortError');\n const item = latest.current.items.find(value => value.proposal.id === payload.proposalId);\n if (!item) throw new Error('対象の提案が見つかりません。再確認してください。');\n const checked = prepareProposalBatch(\n [{ ...item, selected: true, decisions: state.decisions.get(payload.proposalId) ?? ({} as ReviewDecisions<TRecord>) }],\n latest.current.validateCandidate\n );\n if (!checked.canApply || !latest.current.onApply) {\n throw new Error('適用前にデータが変更されたため停止しました。再確認してください。');\n }\n update(value => ({ ...value, active: payload.proposalId }));\n await latest.current.onApply(checked.payloads[0], {\n signal: context.signal,\n reportProgress(progress) {\n const fraction =\n progress.total && Number.isFinite(progress.total) && Number.isFinite(progress.completed)\n ? Math.max(0, Math.min(1, progress.completed / progress.total))\n : 0;\n context.reportProgress({\n completed: completed + fraction,\n total: planned.payloads.length,\n message: progress.message,\n });\n },\n });\n if (live.current !== current) throw new DOMException('Review session changed', 'AbortError');\n current.applied.add(payload.proposalId);\n update(value => ({ ...value, applied: new Set(current.applied) }));\n context.reportProgress({ completed: ++completed, total: planned.payloads.length });\n }\n });\n if (live.current !== current) return false;\n update(value => ({\n ...value,\n running: false,\n active: null,\n error: outcome.status === 'failed' ? '適用に失敗しました。成功済みの提案を除いて再試行できます。' : null,\n }));\n return outcome.status === 'succeeded';\n };\n\n return {\n selectedIds: state.selected,\n appliedIds: state.applied,\n decisions: state.decisions,\n preparation,\n canApply: !!options.onApply && preparation.canApply && !state.running,\n isSubmitting: state.running,\n activeProposalId: state.active,\n error: state.error,\n history,\n setSelected(id, selected) {\n if (!editable(id)) return;\n update(value => {\n const next = new Set(value.selected);\n if (selected) next.add(id);\n else next.delete(id);\n return { ...value, selected: next, error: null };\n });\n },\n selectAll(selected) {\n if (busy()) return;\n update(value => ({\n ...value,\n selected: new Set(selected ? options.items.map(item => item.proposal.id) : value.applied),\n error: null,\n }));\n },\n setDecision(id, field, decision) {\n if (!editable(id) || !options.items.find(item => item.proposal.id === id)?.proposal.changes.some(change => change.field === field)) return;\n update(value => ({\n ...value,\n decisions: new Map(value.decisions).set(id, {\n ...value.decisions.get(id),\n [field]: decision,\n } as ReviewDecisions<TRecord>),\n error: null,\n }));\n },\n decideAll(id, decision) {\n if (!editable(id)) return;\n const item = options.items.find(value => value.proposal.id === id)!;\n update(value => ({\n ...value,\n decisions: new Map(value.decisions).set(\n id,\n Object.fromEntries(item.proposal.changes.map(change => [change.field, decision])) as ReviewDecisions<TRecord>\n ),\n error: null,\n }));\n },\n apply,\n cancel: session.cancel,\n clearHistory: session.clearHistory,\n };\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"use-proposal-batch-review.js","names":["initial","createExecutionSession","useProposalBatchReview","key","options","item","stored","setStored","useState","state","session","live","useRef","latest","useLayoutEffect","current","history","useSyncExternalStore","busy","record","update","change","entries","items","applied","preparation","prepareProposalBatch","editable","id","next","value","selected","field","decision","planned","outcome","completed","payload","context","checked","fraction","progress"],"sources":["../../../src/ai/proposal/use-proposal-batch-review.ts"],"sourcesContent":["import { useLayoutEffect, useRef, useState, useSyncExternalStore } from 'react';\nimport { createExecutionSession, type ExecutionContext, type ExecutionRecord, type ExecutionSession } from \"@alneas/appkit-core/ai\";\nimport {\n prepareProposalBatch,\n type ApplyProposalPayload,\n type FieldDecision,\n type FieldKey,\n type PreparedProposalBatch,\n type ProposalBatchEntry,\n type ProposalBatchItem,\n type ProposalBatchValidator,\n type ReviewDecisions,\n} from \"@alneas/appkit-core/ai\";\n\n/**\n * Host inputs for reviewing unique immutable proposals across multiple records.\n *\n * @typeParam TRecord - Record shape; defaults to a string-keyed record.\n *\n * @see useProposalBatchReview for usage.\n */\nexport interface UseProposalBatchReviewOptions<TRecord extends Record<string, any> = Record<string, any>> {\n /** Change for a new review session, including an intentional replay of the same proposals. */\n batchId: string;\n /**\n * Validated proposals and latest records/versions; proposal IDs must be unique.\n */\n items: readonly ProposalBatchItem<TRecord>[];\n /**\n * Optional synchronous validator passed to Core batch preparation; thrown errors become invalid_candidate issues.\n */\n validateCandidate?: ProposalBatchValidator<TRecord>;\n /**\n * Sequential host callback receiving one prepared payload and cooperative abort/progress context.\n *\n * @param payload - Validated candidate and decisions for one proposal.\n *\n * @param context - Abort signal and fractional-progress reporting for this row.\n *\n * @returns No value after the host confirms application; reject to stop later rows.\n */\n onApply?: (payload: ApplyProposalPayload<TRecord>, context: ExecutionContext) => void | Promise<void>;\n}\n\n/**\n * Batch selection/decision state and explicit execution controls.\n *\n * @typeParam TRecord - Shared record shape; defaults to a string-keyed record.\n *\n * @see useProposalBatchReview for usage.\n */\nexport interface UseProposalBatchReviewReturn<TRecord extends Record<string, any> = Record<string, any>> {\n /**\n * Current selected proposal IDs; applied IDs are excluded from preparation.\n */\n selectedIds: ReadonlySet<string>;\n /**\n * Host-confirmed successes in this review session.\n */\n appliedIds: ReadonlySet<string>;\n /**\n * Per-proposal field decisions; absent choices remain pending.\n */\n decisions: ReadonlyMap<string, ReviewDecisions<TRecord>>;\n /**\n * Core batch preflight result for current selection and latest input props.\n */\n preparation: PreparedProposalBatch<TRecord>;\n /**\n * Whether a handler exists, preparation passes and state is not submitting.\n */\n canApply: boolean;\n /**\n * Whether the displayed batch is currently running.\n */\n isSubmitting: boolean;\n /**\n * Current row being applied, or null outside active row work.\n */\n activeProposalId: string | null;\n /**\n * Generic current-session batch failure message, or null; raw host exceptions are not exposed.\n */\n error: string | null;\n /**\n * Read-only execution history for this batch session.\n */\n history: readonly ExecutionRecord[];\n /**\n * Select or deselect an editable known proposal.\n *\n * @param id - Proposal identifier.\n *\n * @param selected - Desired selection state.\n *\n * @returns No value; unknown/applied/busy proposals are ignored.\n */\n setSelected(id: string, selected: boolean): void;\n /**\n * Change selection for the current items when idle.\n *\n * @param selected - True selects all current IDs; false retains only applied IDs in the selection set.\n *\n * @returns No value; calls while execution is busy are ignored.\n */\n selectAll(selected: boolean): void;\n /**\n * Change one existing proposed field while editable.\n *\n * @param id - Proposal identifier.\n *\n * @param field - Field present in that proposal.\n *\n * @param decision - Pending, accepted or rejected choice.\n *\n * @returns No value; invalid IDs/fields and busy/applied proposals are ignored.\n */\n setDecision(id: string, field: FieldKey<TRecord>, decision: FieldDecision): void;\n /**\n * Change every proposed field choice for one editable proposal.\n *\n * @param id - Proposal identifier.\n *\n * @param decision - Choice applied to all its changes.\n *\n * @returns No value; unknown/applied/busy proposals are ignored.\n */\n decideAll(id: string, decision: FieldDecision): void;\n /**\n * Preflight the selection, then apply rows sequentially with latest-record rechecks.\n *\n * @returns True only for current-session complete success; false when blocked, failed, cancelled or superseded.\n *\n * @remarks Confirmed successes are retained and skipped on retry; unconfirmed backend effects may still exist.\n */\n apply(): Promise<boolean>;\n /**\n * Request cooperative cancellation of current execution.\n *\n * @returns No value; does not roll back previously applied rows or force host work to stop.\n */\n cancel(): void;\n /**\n * Clear settled execution history using the session policy.\n *\n * @returns No value; does not clear review choices or confirmed applied IDs.\n */\n clearHistory(): void;\n}\n\ninterface ReviewState<TRecord extends Record<string, any>> {\n key: string;\n session: ExecutionSession;\n selected: ReadonlySet<string>;\n applied: ReadonlySet<string>;\n decisions: ReadonlyMap<string, ReviewDecisions<TRecord>>;\n running: boolean;\n active: string | null;\n error: string | null;\n}\n\nfunction initial<TRecord extends Record<string, any>>(key: string): ReviewState<TRecord> {\n return {\n key,\n session: createExecutionSession(),\n selected: new Set(),\n applied: new Set(),\n decisions: new Map(),\n running: false,\n active: null,\n error: null,\n };\n}\n\n/**\n * Reviews a batch with explicit field decisions and sequential host application.\n *\n * @typeParam TRecord - Record shape; defaults to a string-keyed record.\n *\n * @param options - Batch identity, unique immutable proposals/latest records, validation and optional host apply callback.\n *\n * @returns Selection/decision controls, preflight state, bounded execution history and cooperative cancellation.\n *\n * @remarks Requires React; no context/styles. Changing batchId or serialized proposal\n * content starts a new session; unmount/session changes request cancellation. Each row\n * is rechecked against latest committed host inputs before apply. Stops at the first\n * failure/cancellation; successes remain excluded from retries. Cancellation cannot\n * undo host effects, so persist idempotently and enforce concurrency/authorization in\n * the backend. A row that changed the backend before rejecting has an uncertain outcome.\n *\n * @example\n * ```tsx\n * import { useProposalBatchReview, type UseProposalBatchReviewOptions } from '@alneas/appkit-react/ai/proposal';\n * type RecordData = { title: string };\n * export function Batch({ options }: { options: UseProposalBatchReviewOptions<RecordData> }) {\n * const review = useProposalBatchReview(options);\n * return <button disabled={!review.canApply} onClick={() => { void review.apply(); }}>Apply selected records</button>;\n * }\n * ```\n */\nexport function useProposalBatchReview<TRecord extends Record<string, any> = Record<string, any>>(\n options: UseProposalBatchReviewOptions<TRecord>\n): UseProposalBatchReviewReturn<TRecord> {\n const key = JSON.stringify([options.batchId, options.items.map(item => JSON.stringify(item.proposal)).sort()]);\n const [stored, setStored] = useState(() => initial<TRecord>(key));\n let state = stored;\n if (state.key !== key) {\n state = initial<TRecord>(key);\n setStored(state);\n }\n const session = state.session;\n const live = useRef<{ session: ExecutionSession; applied: Set<string> } | null>(null);\n const latest = useRef(options);\n useLayoutEffect(() => {\n latest.current = options;\n });\n useLayoutEffect(() => {\n const current = { session, applied: new Set<string>() };\n live.current = current;\n return () => {\n session.cancel();\n if (live.current === current) live.current = null;\n };\n }, [session]);\n\n const history = useSyncExternalStore(session.subscribe, session.getSnapshot, session.getSnapshot);\n const busy = () => session.getSnapshot().some(record => record.status === 'running' || record.status === 'cancelling');\n const update = (change: (current: ReviewState<TRecord>) => ReviewState<TRecord>) => {\n setStored(current => (current.session === session ? change(current) : current));\n };\n\n const entries = (\n items: readonly ProposalBatchItem<TRecord>[],\n applied: ReadonlySet<string>\n ): ProposalBatchEntry<TRecord>[] =>\n items.map(item => ({\n ...item,\n decisions: state.decisions.get(item.proposal.id) ?? ({} as ReviewDecisions<TRecord>),\n selected: state.selected.has(item.proposal.id) && !applied.has(item.proposal.id),\n }));\n\n const preparation = prepareProposalBatch(entries(options.items, state.applied), options.validateCandidate);\n const editable = (id: string) =>\n live.current?.session === session && !busy() && !live.current.applied.has(id) && options.items.some(item => item.proposal.id === id);\n\n const apply = async (): Promise<boolean> => {\n const current = live.current;\n if (!current || current.session !== session || busy() || !latest.current.onApply) return false;\n const planned = prepareProposalBatch(entries(latest.current.items, current.applied), latest.current.validateCandidate);\n if (!planned.canApply) return false;\n update(value => ({ ...value, running: true, error: null }));\n const outcome = await session.run(`一括適用 ${planned.payloads.length} 件`, async context => {\n context.reportProgress({ completed: 0, total: planned.payloads.length });\n let completed = 0;\n for (const payload of planned.payloads) {\n context.signal.throwIfAborted();\n if (live.current !== current) throw new DOMException('Review session changed', 'AbortError');\n const item = latest.current.items.find(value => value.proposal.id === payload.proposalId);\n if (!item) throw new Error('対象の提案が見つかりません。再確認してください。');\n const checked = prepareProposalBatch(\n [{ ...item, selected: true, decisions: state.decisions.get(payload.proposalId) ?? ({} as ReviewDecisions<TRecord>) }],\n latest.current.validateCandidate\n );\n if (!checked.canApply || !latest.current.onApply) {\n throw new Error('適用前にデータが変更されたため停止しました。再確認してください。');\n }\n update(value => ({ ...value, active: payload.proposalId }));\n await latest.current.onApply(checked.payloads[0], {\n signal: context.signal,\n reportProgress(progress) {\n const fraction =\n progress.total && Number.isFinite(progress.total) && Number.isFinite(progress.completed)\n ? Math.max(0, Math.min(1, progress.completed / progress.total))\n : 0;\n context.reportProgress({\n completed: completed + fraction,\n total: planned.payloads.length,\n message: progress.message,\n });\n },\n });\n if (live.current !== current) throw new DOMException('Review session changed', 'AbortError');\n current.applied.add(payload.proposalId);\n update(value => ({ ...value, applied: new Set(current.applied) }));\n context.reportProgress({ completed: ++completed, total: planned.payloads.length });\n }\n });\n if (live.current !== current) return false;\n update(value => ({\n ...value,\n running: false,\n active: null,\n error: outcome.status === 'failed' ? '適用に失敗しました。成功済みの提案を除いて再試行できます。' : null,\n }));\n return outcome.status === 'succeeded';\n };\n\n return {\n selectedIds: state.selected,\n appliedIds: state.applied,\n decisions: state.decisions,\n preparation,\n canApply: !!options.onApply && preparation.canApply && !state.running,\n isSubmitting: state.running,\n activeProposalId: state.active,\n error: state.error,\n history,\n setSelected(id, selected) {\n if (!editable(id)) return;\n update(value => {\n const next = new Set(value.selected);\n if (selected) next.add(id);\n else next.delete(id);\n return { ...value, selected: next, error: null };\n });\n },\n selectAll(selected) {\n if (busy()) return;\n update(value => ({\n ...value,\n selected: new Set(selected ? options.items.map(item => item.proposal.id) : value.applied),\n error: null,\n }));\n },\n setDecision(id, field, decision) {\n if (!editable(id) || !options.items.find(item => item.proposal.id === id)?.proposal.changes.some(change => change.field === field)) return;\n update(value => ({\n ...value,\n decisions: new Map(value.decisions).set(id, {\n ...value.decisions.get(id),\n [field]: decision,\n } as ReviewDecisions<TRecord>),\n error: null,\n }));\n },\n decideAll(id, decision) {\n if (!editable(id)) return;\n const item = options.items.find(value => value.proposal.id === id)!;\n update(value => ({\n ...value,\n decisions: new Map(value.decisions).set(\n id,\n Object.fromEntries(item.proposal.changes.map(change => [change.field, decision])) as ReviewDecisions<TRecord>\n ),\n error: null,\n }));\n },\n apply,\n cancel: session.cancel,\n clearHistory: session.clearHistory,\n };\n}\n"],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"use-proposal-review.cjs","names":["useState","useRef","useCallback","useMemo","buildCandidateRecord","verifyCurrentState","computeReviewStatus","canApplyProposal","buildApplyPayload","react","_alneas_appkit_core_ai","useProposalReview","options","activeProposalId","setActiveProposalId","proposal","rawDecisions","setRawDecisions","isSubmitting","setIsSubmitting","saveError","setSaveError","displayGeneration","setDisplayGeneration","displayGenerationRef","executionTokenRef","isExecutingLockRef","decisions","prev","setDecision","field","decision","acceptAll","next","change","rejectAll","resetDecisions","candidateRecord","currentRecord","consistency","currentVersion","candidateValidation","validateCandidate","reviewStatus","canApply","onApply","handleApply","executionGen","currentToken","payload","err","message"],"sources":["../../../src/ai/proposal/use-proposal-review.ts"],"sourcesContent":["'use client';\n\nimport { useState, useMemo, useCallback, useRef, useEffect } from 'react';\nimport {\n buildApplyPayload,\n buildCandidateRecord,\n canApplyProposal,\n computeReviewStatus,\n verifyCurrentState,\n} from \"@alneas/appkit-core/ai\";\nimport type {\n CandidateValidationResult,\n FieldDecision,\n FieldKey,\n RecordProposal,\n ReviewDecisions,\n} from \"@alneas/appkit-core/ai\";\nimport type { ProposalReviewCardProps, UseProposalReviewReturn } from './types';\n\n/** Options for useProposalReview hook. */\nexport interface UseProposalReviewOptions<\n TRecord extends Record<string, any> = Record<string, any>,\n> {\n proposal: RecordProposal<TRecord>;\n currentRecord: TRecord;\n currentVersion: string | number;\n validateCandidate?: (candidate: TRecord) => CandidateValidationResult;\n onApply?: ProposalReviewCardProps<TRecord>['onApply'];\n}\n\n/**\n * 変更提案のレビュー状態を管理するカスタムフック\n *\n * @template TRecord レコード型\n * @param options フックオプション\n * @returns レビュー状態と操作ハンドラ\n */\nexport function useProposalReview<\n TRecord extends Record<string, any> = Record<string, any>,\n>(options: UseProposalReviewOptions<TRecord>): UseProposalReviewReturn<TRecord> {\n const { proposal, currentRecord, currentVersion, validateCandidate, onApply } = options;\n\n // 提案切替(proposal.id 変更)の検知用\n const [activeProposalId, setActiveProposalId] = useState<string>(proposal.id);\n const [rawDecisions, setRawDecisions] = useState<ReviewDecisions<TRecord>>(\n {} as ReviewDecisions<TRecord>\n );\n const [isSubmitting, setIsSubmitting] = useState(false);\n const [saveError, setSaveError] = useState<string | null>(null);\n\n // 表示世代カウンター: 提案切替(A→B, B→A など)のたびにインクリメント\n const [displayGeneration, setDisplayGeneration] = useState<number>(1);\n const displayGenerationRef = useRef<number>(1);\n\n // 実行トークン: 適用実行ごとに一意なトークンをインクリメント\n const executionTokenRef = useRef<number>(0);\n // 同期実行ロック: 再レンダー完了前の高速な連続クリック(二重実行)を同期的にブロック\n const isExecutingLockRef = useRef<boolean>(false);\n\n // プロジェクト標準ルール: 「No synchronous setState in useEffect」\n // 提案 ID が切り替わった場合、レンダー中に状態を初期化して同期ズレを防ぐ\n let decisions = rawDecisions;\n if (proposal.id !== activeProposalId) {\n setActiveProposalId(proposal.id);\n setRawDecisions({} as ReviewDecisions<TRecord>);\n setSaveError(null);\n setIsSubmitting(false);\n setDisplayGeneration((prev) => prev + 1);\n decisions = {} as ReviewDecisions<TRecord>;\n }\n\n // 提案が切り替わった場合、実行ロックを非同期完了を待たずに解除し、表示世代Refを同期\n useEffect(() => {\n displayGenerationRef.current = displayGeneration;\n isExecutingLockRef.current = false;\n }, [displayGeneration]);\n\n // 個別フィールド決定の更新\n const setDecision = useCallback((field: FieldKey<TRecord>, decision: FieldDecision) => {\n setRawDecisions((prev) => ({\n ...prev,\n [field]: decision,\n }));\n setSaveError(null);\n }, []);\n\n // 全採用\n const acceptAll = useCallback(() => {\n const next: Partial<Record<FieldKey<TRecord>, FieldDecision>> = {};\n for (const change of proposal.changes) {\n next[change.field] = 'accepted';\n }\n setRawDecisions(next);\n setSaveError(null);\n }, [proposal.changes]);\n\n // 全却下\n const rejectAll = useCallback(() => {\n const next: Partial<Record<FieldKey<TRecord>, FieldDecision>> = {};\n for (const change of proposal.changes) {\n next[change.field] = 'rejected';\n }\n setRawDecisions(next);\n setSaveError(null);\n }, [proposal.changes]);\n\n // リセット(全 pending)\n const resetDecisions = useCallback(() => {\n setRawDecisions({} as ReviewDecisions<TRecord>);\n setSaveError(null);\n }, []);\n\n // 候補レコードの合成(不変・純粋関数)\n const candidateRecord = useMemo(() => {\n return buildCandidateRecord(currentRecord, proposal, decisions);\n }, [currentRecord, proposal, decisions]);\n\n // 現在値およびバージョンとの整合性検査\n const consistency = useMemo(() => {\n return verifyCurrentState(currentRecord, currentVersion, proposal, decisions);\n }, [currentRecord, currentVersion, proposal, decisions]);\n\n // 候補レコード全体のカスタム検証(相関チェック等)\n const candidateValidation = useMemo(() => {\n if (!validateCandidate) return undefined;\n return validateCandidate(candidateRecord);\n }, [validateCandidate, candidateRecord]);\n\n // 全体のレビュー状態(派生値)\n const reviewStatus = useMemo(() => {\n return computeReviewStatus(proposal, decisions);\n }, [proposal, decisions]);\n\n // 適用可能かどうかの判定(onApply が指定されていることも条件)\n const canApply = useMemo(() => {\n if (!onApply) return false;\n return canApplyProposal({\n proposal,\n decisions,\n consistency,\n candidateValidation,\n });\n }, [onApply, proposal, decisions, consistency, candidateValidation]);\n\n // 適用実行ハンドラ(提案世代・トークン・同期ロックによる完全隔離)\n const handleApply = useCallback(async (): Promise<boolean> => {\n // 1. 同期ロックおよび適用可否チェック(再レンダー前の重複実行も防止)\n if (!canApply || isExecutingLockRef.current || !onApply) {\n return false;\n }\n\n isExecutingLockRef.current = true;\n const executionGen = displayGenerationRef.current;\n const currentToken = ++executionTokenRef.current;\n\n setIsSubmitting(true);\n setSaveError(null);\n\n try {\n const payload = buildApplyPayload({\n proposal,\n candidateRecord,\n decisions,\n });\n\n await onApply(payload);\n\n // 非同期完了時: 表示世代および実行トークンが現在と一致している場合のみ状態を更新\n if (\n displayGenerationRef.current === executionGen &&\n executionTokenRef.current === currentToken\n ) {\n setIsSubmitting(false);\n setSaveError(null);\n isExecutingLockRef.current = false;\n return true;\n }\n return false;\n } catch (err) {\n // 非同期失敗時: 表示世代および実行トークンが現在と一致している場合のみエラーを設定\n if (\n displayGenerationRef.current === executionGen &&\n executionTokenRef.current === currentToken\n ) {\n setIsSubmitting(false);\n const message = err instanceof Error ? err.message : '適用の保存中にエラーが発生しました';\n setSaveError(message);\n isExecutingLockRef.current = false;\n }\n return false;\n } finally {\n // 過去世代の結果が遅れて完了した場合の finally では、現在のロックを解除しない\n if (\n displayGenerationRef.current === executionGen &&\n executionTokenRef.current === currentToken\n ) {\n isExecutingLockRef.current = false;\n }\n }\n }, [canApply, onApply, proposal, candidateRecord, decisions]);\n\n return {\n decisions,\n setDecision,\n acceptAll,\n rejectAll,\n resetDecisions,\n candidateRecord,\n reviewStatus,\n consistency,\n candidateValidation,\n canApply,\n isSubmitting,\n saveError,\n handleApply,\n };\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"use-proposal-review.cjs","names":["useState","useRef","useCallback","useMemo","buildCandidateRecord","verifyCurrentState","computeReviewStatus","canApplyProposal","buildApplyPayload","react","_alneas_appkit_core_ai","useProposalReview","options","activeProposalId","setActiveProposalId","proposal","rawDecisions","setRawDecisions","isSubmitting","setIsSubmitting","saveError","setSaveError","displayGeneration","setDisplayGeneration","displayGenerationRef","executionTokenRef","isExecutingLockRef","decisions","prev","setDecision","field","decision","acceptAll","next","change","rejectAll","resetDecisions","candidateRecord","currentRecord","consistency","currentVersion","candidateValidation","validateCandidate","reviewStatus","canApply","onApply","handleApply","executionGen","currentToken","payload","err","message"],"sources":["../../../src/ai/proposal/use-proposal-review.ts"],"sourcesContent":["'use client';\n\nimport { useState, useMemo, useCallback, useRef, useEffect } from 'react';\nimport {\n buildApplyPayload,\n buildCandidateRecord,\n canApplyProposal,\n computeReviewStatus,\n verifyCurrentState,\n} from \"@alneas/appkit-core/ai\";\nimport type {\n CandidateValidationResult,\n FieldDecision,\n FieldKey,\n RecordProposal,\n ReviewDecisions,\n} from \"@alneas/appkit-core/ai\";\nimport type { ProposalReviewCardProps, UseProposalReviewReturn } from './types';\n\n/**\n * Host inputs for one immutable change proposal.\n *\n * @typeParam TRecord - Record shape; defaults to a string-keyed record.\n *\n * @see useProposalReview for complete usage.\n */\nexport interface UseProposalReviewOptions<\n TRecord extends Record<string, any> = Record<string, any>,\n> {\n /**\n * Validated immutable proposal; a new id starts a new review generation.\n */\n proposal: RecordProposal<TRecord>;\n /**\n * Latest record to compare and compose with accepted changes.\n */\n currentRecord: TRecord;\n /**\n * Current host version used for consistency checks.\n */\n currentVersion: string | number;\n /**\n * Optional pure synchronous full-record validator; render-time exceptions propagate.\n */\n validateCandidate?: (candidate: TRecord) => CandidateValidationResult;\n /**\n * Optional async host persistence/form-application handler; absence prevents apply.\n */\n onApply?: ProposalReviewCardProps<TRecord>['onApply'];\n}\n\n/**\n * Manages explicit field decisions and candidate consistency for a single proposal.\n *\n * @typeParam TRecord - Current record shape; defaults to a string-keyed record.\n *\n * @param options - Immutable proposal, latest record/version, optional candidate validator and host apply handler.\n *\n * @returns Review decisions, composed candidate, validation state and explicit apply controls.\n *\n * @throws Host validateCandidate errors propagate from render.\n *\n * @remarks Requires React; no context or CSS. Changing proposal.id resets choices, error\n * and displayed submission state. A synchronous lock blocks duplicate apply calls.\n * Late results from an older displayed generation do not update the current review;\n * this does not cancel or roll back host effects. onApply errors become saveError and\n * handleApply returns false. No backend authorization or persistence is provided.\n *\n * @example\n * ```tsx\n * import { useProposalReview, type UseProposalReviewOptions } from '@alneas/appkit-react/ai/proposal';\n * type RecordData = { title: string };\n * // The host supplies a validated proposal, current record/version and real onApply.\n * export function Review({ options }: { options: UseProposalReviewOptions<RecordData> }) {\n * const review = useProposalReview(options);\n * return <button disabled={!review.canApply || review.isSubmitting} onClick={() => { void review.handleApply(); }}>Apply reviewed changes</button>;\n * }\n * ```\n */\nexport function useProposalReview<\n TRecord extends Record<string, any> = Record<string, any>,\n>(options: UseProposalReviewOptions<TRecord>): UseProposalReviewReturn<TRecord> {\n const { proposal, currentRecord, currentVersion, validateCandidate, onApply } = options;\n\n // 提案切替(proposal.id 変更)の検知用\n const [activeProposalId, setActiveProposalId] = useState<string>(proposal.id);\n const [rawDecisions, setRawDecisions] = useState<ReviewDecisions<TRecord>>(\n {} as ReviewDecisions<TRecord>\n );\n const [isSubmitting, setIsSubmitting] = useState(false);\n const [saveError, setSaveError] = useState<string | null>(null);\n\n // 表示世代カウンター: 提案切替(A→B, B→A など)のたびにインクリメント\n const [displayGeneration, setDisplayGeneration] = useState<number>(1);\n const displayGenerationRef = useRef<number>(1);\n\n // 実行トークン: 適用実行ごとに一意なトークンをインクリメント\n const executionTokenRef = useRef<number>(0);\n // 同期実行ロック: 再レンダー完了前の高速な連続クリック(二重実行)を同期的にブロック\n const isExecutingLockRef = useRef<boolean>(false);\n\n // プロジェクト標準ルール: 「No synchronous setState in useEffect」\n // 提案 ID が切り替わった場合、レンダー中に状態を初期化して同期ズレを防ぐ\n let decisions = rawDecisions;\n if (proposal.id !== activeProposalId) {\n setActiveProposalId(proposal.id);\n setRawDecisions({} as ReviewDecisions<TRecord>);\n setSaveError(null);\n setIsSubmitting(false);\n setDisplayGeneration((prev) => prev + 1);\n decisions = {} as ReviewDecisions<TRecord>;\n }\n\n // 提案が切り替わった場合、実行ロックを非同期完了を待たずに解除し、表示世代Refを同期\n useEffect(() => {\n displayGenerationRef.current = displayGeneration;\n isExecutingLockRef.current = false;\n }, [displayGeneration]);\n\n // 個別フィールド決定の更新\n const setDecision = useCallback((field: FieldKey<TRecord>, decision: FieldDecision) => {\n setRawDecisions((prev) => ({\n ...prev,\n [field]: decision,\n }));\n setSaveError(null);\n }, []);\n\n // 全採用\n const acceptAll = useCallback(() => {\n const next: Partial<Record<FieldKey<TRecord>, FieldDecision>> = {};\n for (const change of proposal.changes) {\n next[change.field] = 'accepted';\n }\n setRawDecisions(next);\n setSaveError(null);\n }, [proposal.changes]);\n\n // 全却下\n const rejectAll = useCallback(() => {\n const next: Partial<Record<FieldKey<TRecord>, FieldDecision>> = {};\n for (const change of proposal.changes) {\n next[change.field] = 'rejected';\n }\n setRawDecisions(next);\n setSaveError(null);\n }, [proposal.changes]);\n\n // リセット(全 pending)\n const resetDecisions = useCallback(() => {\n setRawDecisions({} as ReviewDecisions<TRecord>);\n setSaveError(null);\n }, []);\n\n // 候補レコードの合成(不変・純粋関数)\n const candidateRecord = useMemo(() => {\n return buildCandidateRecord(currentRecord, proposal, decisions);\n }, [currentRecord, proposal, decisions]);\n\n // 現在値およびバージョンとの整合性検査\n const consistency = useMemo(() => {\n return verifyCurrentState(currentRecord, currentVersion, proposal, decisions);\n }, [currentRecord, currentVersion, proposal, decisions]);\n\n // 候補レコード全体のカスタム検証(相関チェック等)\n const candidateValidation = useMemo(() => {\n if (!validateCandidate) return undefined;\n return validateCandidate(candidateRecord);\n }, [validateCandidate, candidateRecord]);\n\n // 全体のレビュー状態(派生値)\n const reviewStatus = useMemo(() => {\n return computeReviewStatus(proposal, decisions);\n }, [proposal, decisions]);\n\n // 適用可能かどうかの判定(onApply が指定されていることも条件)\n const canApply = useMemo(() => {\n if (!onApply) return false;\n return canApplyProposal({\n proposal,\n decisions,\n consistency,\n candidateValidation,\n });\n }, [onApply, proposal, decisions, consistency, candidateValidation]);\n\n // 適用実行ハンドラ(提案世代・トークン・同期ロックによる完全隔離)\n const handleApply = useCallback(async (): Promise<boolean> => {\n // 1. 同期ロックおよび適用可否チェック(再レンダー前の重複実行も防止)\n if (!canApply || isExecutingLockRef.current || !onApply) {\n return false;\n }\n\n isExecutingLockRef.current = true;\n const executionGen = displayGenerationRef.current;\n const currentToken = ++executionTokenRef.current;\n\n setIsSubmitting(true);\n setSaveError(null);\n\n try {\n const payload = buildApplyPayload({\n proposal,\n candidateRecord,\n decisions,\n });\n\n await onApply(payload);\n\n // 非同期完了時: 表示世代および実行トークンが現在と一致している場合のみ状態を更新\n if (\n displayGenerationRef.current === executionGen &&\n executionTokenRef.current === currentToken\n ) {\n setIsSubmitting(false);\n setSaveError(null);\n isExecutingLockRef.current = false;\n return true;\n }\n return false;\n } catch (err) {\n // 非同期失敗時: 表示世代および実行トークンが現在と一致している場合のみエラーを設定\n if (\n displayGenerationRef.current === executionGen &&\n executionTokenRef.current === currentToken\n ) {\n setIsSubmitting(false);\n const message = err instanceof Error ? err.message : '適用の保存中にエラーが発生しました';\n setSaveError(message);\n isExecutingLockRef.current = false;\n }\n return false;\n } finally {\n // 過去世代の結果が遅れて完了した場合の finally では、現在のロックを解除しない\n if (\n displayGenerationRef.current === executionGen &&\n executionTokenRef.current === currentToken\n ) {\n isExecutingLockRef.current = false;\n }\n }\n }, [canApply, onApply, proposal, candidateRecord, decisions]);\n\n return {\n decisions,\n setDecision,\n acceptAll,\n rejectAll,\n resetDecisions,\n candidateRecord,\n reviewStatus,\n consistency,\n candidateValidation,\n canApply,\n isSubmitting,\n saveError,\n handleApply,\n };\n}\n"],"mappings":"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"}
|
|
@@ -1,18 +1,60 @@
|
|
|
1
1
|
import { CandidateValidationResult, RecordProposal } from '@alneas/appkit-core/ai';
|
|
2
2
|
import { ProposalReviewCardProps, UseProposalReviewReturn } from './types.cjs';
|
|
3
|
-
/**
|
|
3
|
+
/**
|
|
4
|
+
* Host inputs for one immutable change proposal.
|
|
5
|
+
*
|
|
6
|
+
* @typeParam TRecord - Record shape; defaults to a string-keyed record.
|
|
7
|
+
*
|
|
8
|
+
* @see useProposalReview for complete usage.
|
|
9
|
+
*/
|
|
4
10
|
export interface UseProposalReviewOptions<TRecord extends Record<string, any> = Record<string, any>> {
|
|
11
|
+
/**
|
|
12
|
+
* Validated immutable proposal; a new id starts a new review generation.
|
|
13
|
+
*/
|
|
5
14
|
proposal: RecordProposal<TRecord>;
|
|
15
|
+
/**
|
|
16
|
+
* Latest record to compare and compose with accepted changes.
|
|
17
|
+
*/
|
|
6
18
|
currentRecord: TRecord;
|
|
19
|
+
/**
|
|
20
|
+
* Current host version used for consistency checks.
|
|
21
|
+
*/
|
|
7
22
|
currentVersion: string | number;
|
|
23
|
+
/**
|
|
24
|
+
* Optional pure synchronous full-record validator; render-time exceptions propagate.
|
|
25
|
+
*/
|
|
8
26
|
validateCandidate?: (candidate: TRecord) => CandidateValidationResult;
|
|
27
|
+
/**
|
|
28
|
+
* Optional async host persistence/form-application handler; absence prevents apply.
|
|
29
|
+
*/
|
|
9
30
|
onApply?: ProposalReviewCardProps<TRecord>['onApply'];
|
|
10
31
|
}
|
|
11
32
|
/**
|
|
12
|
-
*
|
|
33
|
+
* Manages explicit field decisions and candidate consistency for a single proposal.
|
|
34
|
+
*
|
|
35
|
+
* @typeParam TRecord - Current record shape; defaults to a string-keyed record.
|
|
36
|
+
*
|
|
37
|
+
* @param options - Immutable proposal, latest record/version, optional candidate validator and host apply handler.
|
|
38
|
+
*
|
|
39
|
+
* @returns Review decisions, composed candidate, validation state and explicit apply controls.
|
|
40
|
+
*
|
|
41
|
+
* @throws Host validateCandidate errors propagate from render.
|
|
42
|
+
*
|
|
43
|
+
* @remarks Requires React; no context or CSS. Changing proposal.id resets choices, error
|
|
44
|
+
* and displayed submission state. A synchronous lock blocks duplicate apply calls.
|
|
45
|
+
* Late results from an older displayed generation do not update the current review;
|
|
46
|
+
* this does not cancel or roll back host effects. onApply errors become saveError and
|
|
47
|
+
* handleApply returns false. No backend authorization or persistence is provided.
|
|
13
48
|
*
|
|
14
|
-
* @
|
|
15
|
-
*
|
|
16
|
-
* @
|
|
49
|
+
* @example
|
|
50
|
+
* ```tsx
|
|
51
|
+
* import { useProposalReview, type UseProposalReviewOptions } from '@alneas/appkit-react/ai/proposal';
|
|
52
|
+
* type RecordData = { title: string };
|
|
53
|
+
* // The host supplies a validated proposal, current record/version and real onApply.
|
|
54
|
+
* export function Review({ options }: { options: UseProposalReviewOptions<RecordData> }) {
|
|
55
|
+
* const review = useProposalReview(options);
|
|
56
|
+
* return <button disabled={!review.canApply || review.isSubmitting} onClick={() => { void review.handleApply(); }}>Apply reviewed changes</button>;
|
|
57
|
+
* }
|
|
58
|
+
* ```
|
|
17
59
|
*/
|
|
18
60
|
export declare function useProposalReview<TRecord extends Record<string, any> = Record<string, any>>(options: UseProposalReviewOptions<TRecord>): UseProposalReviewReturn<TRecord>;
|
|
@@ -1,18 +1,60 @@
|
|
|
1
1
|
import { CandidateValidationResult, RecordProposal } from '@alneas/appkit-core/ai';
|
|
2
2
|
import { ProposalReviewCardProps, UseProposalReviewReturn } from './types.js';
|
|
3
|
-
/**
|
|
3
|
+
/**
|
|
4
|
+
* Host inputs for one immutable change proposal.
|
|
5
|
+
*
|
|
6
|
+
* @typeParam TRecord - Record shape; defaults to a string-keyed record.
|
|
7
|
+
*
|
|
8
|
+
* @see useProposalReview for complete usage.
|
|
9
|
+
*/
|
|
4
10
|
export interface UseProposalReviewOptions<TRecord extends Record<string, any> = Record<string, any>> {
|
|
11
|
+
/**
|
|
12
|
+
* Validated immutable proposal; a new id starts a new review generation.
|
|
13
|
+
*/
|
|
5
14
|
proposal: RecordProposal<TRecord>;
|
|
15
|
+
/**
|
|
16
|
+
* Latest record to compare and compose with accepted changes.
|
|
17
|
+
*/
|
|
6
18
|
currentRecord: TRecord;
|
|
19
|
+
/**
|
|
20
|
+
* Current host version used for consistency checks.
|
|
21
|
+
*/
|
|
7
22
|
currentVersion: string | number;
|
|
23
|
+
/**
|
|
24
|
+
* Optional pure synchronous full-record validator; render-time exceptions propagate.
|
|
25
|
+
*/
|
|
8
26
|
validateCandidate?: (candidate: TRecord) => CandidateValidationResult;
|
|
27
|
+
/**
|
|
28
|
+
* Optional async host persistence/form-application handler; absence prevents apply.
|
|
29
|
+
*/
|
|
9
30
|
onApply?: ProposalReviewCardProps<TRecord>['onApply'];
|
|
10
31
|
}
|
|
11
32
|
/**
|
|
12
|
-
*
|
|
33
|
+
* Manages explicit field decisions and candidate consistency for a single proposal.
|
|
34
|
+
*
|
|
35
|
+
* @typeParam TRecord - Current record shape; defaults to a string-keyed record.
|
|
36
|
+
*
|
|
37
|
+
* @param options - Immutable proposal, latest record/version, optional candidate validator and host apply handler.
|
|
38
|
+
*
|
|
39
|
+
* @returns Review decisions, composed candidate, validation state and explicit apply controls.
|
|
40
|
+
*
|
|
41
|
+
* @throws Host validateCandidate errors propagate from render.
|
|
42
|
+
*
|
|
43
|
+
* @remarks Requires React; no context or CSS. Changing proposal.id resets choices, error
|
|
44
|
+
* and displayed submission state. A synchronous lock blocks duplicate apply calls.
|
|
45
|
+
* Late results from an older displayed generation do not update the current review;
|
|
46
|
+
* this does not cancel or roll back host effects. onApply errors become saveError and
|
|
47
|
+
* handleApply returns false. No backend authorization or persistence is provided.
|
|
13
48
|
*
|
|
14
|
-
* @
|
|
15
|
-
*
|
|
16
|
-
* @
|
|
49
|
+
* @example
|
|
50
|
+
* ```tsx
|
|
51
|
+
* import { useProposalReview, type UseProposalReviewOptions } from '@alneas/appkit-react/ai/proposal';
|
|
52
|
+
* type RecordData = { title: string };
|
|
53
|
+
* // The host supplies a validated proposal, current record/version and real onApply.
|
|
54
|
+
* export function Review({ options }: { options: UseProposalReviewOptions<RecordData> }) {
|
|
55
|
+
* const review = useProposalReview(options);
|
|
56
|
+
* return <button disabled={!review.canApply || review.isSubmitting} onClick={() => { void review.handleApply(); }}>Apply reviewed changes</button>;
|
|
57
|
+
* }
|
|
58
|
+
* ```
|
|
17
59
|
*/
|
|
18
60
|
export declare function useProposalReview<TRecord extends Record<string, any> = Record<string, any>>(options: UseProposalReviewOptions<TRecord>): UseProposalReviewReturn<TRecord>;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"use-proposal-review.js","names":["useProposalReview","options","activeProposalId","setActiveProposalId","useState","proposal","rawDecisions","setRawDecisions","isSubmitting","setIsSubmitting","saveError","setSaveError","displayGeneration","setDisplayGeneration","displayGenerationRef","useRef","executionTokenRef","isExecutingLockRef","decisions","prev","useEffect","setDecision","useCallback","field","decision","acceptAll","next","change","rejectAll","resetDecisions","candidateRecord","useMemo","buildCandidateRecord","currentRecord","consistency","verifyCurrentState","currentVersion","candidateValidation","validateCandidate","reviewStatus","computeReviewStatus","canApply","onApply","canApplyProposal","handleApply","executionGen","currentToken","payload","buildApplyPayload","err","message"],"sources":["../../../src/ai/proposal/use-proposal-review.ts"],"sourcesContent":["'use client';\n\nimport { useState, useMemo, useCallback, useRef, useEffect } from 'react';\nimport {\n buildApplyPayload,\n buildCandidateRecord,\n canApplyProposal,\n computeReviewStatus,\n verifyCurrentState,\n} from \"@alneas/appkit-core/ai\";\nimport type {\n CandidateValidationResult,\n FieldDecision,\n FieldKey,\n RecordProposal,\n ReviewDecisions,\n} from \"@alneas/appkit-core/ai\";\nimport type { ProposalReviewCardProps, UseProposalReviewReturn } from './types';\n\n/** Options for useProposalReview hook. */\nexport interface UseProposalReviewOptions<\n TRecord extends Record<string, any> = Record<string, any>,\n> {\n proposal: RecordProposal<TRecord>;\n currentRecord: TRecord;\n currentVersion: string | number;\n validateCandidate?: (candidate: TRecord) => CandidateValidationResult;\n onApply?: ProposalReviewCardProps<TRecord>['onApply'];\n}\n\n/**\n * 変更提案のレビュー状態を管理するカスタムフック\n *\n * @template TRecord レコード型\n * @param options フックオプション\n * @returns レビュー状態と操作ハンドラ\n */\nexport function useProposalReview<\n TRecord extends Record<string, any> = Record<string, any>,\n>(options: UseProposalReviewOptions<TRecord>): UseProposalReviewReturn<TRecord> {\n const { proposal, currentRecord, currentVersion, validateCandidate, onApply } = options;\n\n // 提案切替(proposal.id 変更)の検知用\n const [activeProposalId, setActiveProposalId] = useState<string>(proposal.id);\n const [rawDecisions, setRawDecisions] = useState<ReviewDecisions<TRecord>>(\n {} as ReviewDecisions<TRecord>\n );\n const [isSubmitting, setIsSubmitting] = useState(false);\n const [saveError, setSaveError] = useState<string | null>(null);\n\n // 表示世代カウンター: 提案切替(A→B, B→A など)のたびにインクリメント\n const [displayGeneration, setDisplayGeneration] = useState<number>(1);\n const displayGenerationRef = useRef<number>(1);\n\n // 実行トークン: 適用実行ごとに一意なトークンをインクリメント\n const executionTokenRef = useRef<number>(0);\n // 同期実行ロック: 再レンダー完了前の高速な連続クリック(二重実行)を同期的にブロック\n const isExecutingLockRef = useRef<boolean>(false);\n\n // プロジェクト標準ルール: 「No synchronous setState in useEffect」\n // 提案 ID が切り替わった場合、レンダー中に状態を初期化して同期ズレを防ぐ\n let decisions = rawDecisions;\n if (proposal.id !== activeProposalId) {\n setActiveProposalId(proposal.id);\n setRawDecisions({} as ReviewDecisions<TRecord>);\n setSaveError(null);\n setIsSubmitting(false);\n setDisplayGeneration((prev) => prev + 1);\n decisions = {} as ReviewDecisions<TRecord>;\n }\n\n // 提案が切り替わった場合、実行ロックを非同期完了を待たずに解除し、表示世代Refを同期\n useEffect(() => {\n displayGenerationRef.current = displayGeneration;\n isExecutingLockRef.current = false;\n }, [displayGeneration]);\n\n // 個別フィールド決定の更新\n const setDecision = useCallback((field: FieldKey<TRecord>, decision: FieldDecision) => {\n setRawDecisions((prev) => ({\n ...prev,\n [field]: decision,\n }));\n setSaveError(null);\n }, []);\n\n // 全採用\n const acceptAll = useCallback(() => {\n const next: Partial<Record<FieldKey<TRecord>, FieldDecision>> = {};\n for (const change of proposal.changes) {\n next[change.field] = 'accepted';\n }\n setRawDecisions(next);\n setSaveError(null);\n }, [proposal.changes]);\n\n // 全却下\n const rejectAll = useCallback(() => {\n const next: Partial<Record<FieldKey<TRecord>, FieldDecision>> = {};\n for (const change of proposal.changes) {\n next[change.field] = 'rejected';\n }\n setRawDecisions(next);\n setSaveError(null);\n }, [proposal.changes]);\n\n // リセット(全 pending)\n const resetDecisions = useCallback(() => {\n setRawDecisions({} as ReviewDecisions<TRecord>);\n setSaveError(null);\n }, []);\n\n // 候補レコードの合成(不変・純粋関数)\n const candidateRecord = useMemo(() => {\n return buildCandidateRecord(currentRecord, proposal, decisions);\n }, [currentRecord, proposal, decisions]);\n\n // 現在値およびバージョンとの整合性検査\n const consistency = useMemo(() => {\n return verifyCurrentState(currentRecord, currentVersion, proposal, decisions);\n }, [currentRecord, currentVersion, proposal, decisions]);\n\n // 候補レコード全体のカスタム検証(相関チェック等)\n const candidateValidation = useMemo(() => {\n if (!validateCandidate) return undefined;\n return validateCandidate(candidateRecord);\n }, [validateCandidate, candidateRecord]);\n\n // 全体のレビュー状態(派生値)\n const reviewStatus = useMemo(() => {\n return computeReviewStatus(proposal, decisions);\n }, [proposal, decisions]);\n\n // 適用可能かどうかの判定(onApply が指定されていることも条件)\n const canApply = useMemo(() => {\n if (!onApply) return false;\n return canApplyProposal({\n proposal,\n decisions,\n consistency,\n candidateValidation,\n });\n }, [onApply, proposal, decisions, consistency, candidateValidation]);\n\n // 適用実行ハンドラ(提案世代・トークン・同期ロックによる完全隔離)\n const handleApply = useCallback(async (): Promise<boolean> => {\n // 1. 同期ロックおよび適用可否チェック(再レンダー前の重複実行も防止)\n if (!canApply || isExecutingLockRef.current || !onApply) {\n return false;\n }\n\n isExecutingLockRef.current = true;\n const executionGen = displayGenerationRef.current;\n const currentToken = ++executionTokenRef.current;\n\n setIsSubmitting(true);\n setSaveError(null);\n\n try {\n const payload = buildApplyPayload({\n proposal,\n candidateRecord,\n decisions,\n });\n\n await onApply(payload);\n\n // 非同期完了時: 表示世代および実行トークンが現在と一致している場合のみ状態を更新\n if (\n displayGenerationRef.current === executionGen &&\n executionTokenRef.current === currentToken\n ) {\n setIsSubmitting(false);\n setSaveError(null);\n isExecutingLockRef.current = false;\n return true;\n }\n return false;\n } catch (err) {\n // 非同期失敗時: 表示世代および実行トークンが現在と一致している場合のみエラーを設定\n if (\n displayGenerationRef.current === executionGen &&\n executionTokenRef.current === currentToken\n ) {\n setIsSubmitting(false);\n const message = err instanceof Error ? err.message : '適用の保存中にエラーが発生しました';\n setSaveError(message);\n isExecutingLockRef.current = false;\n }\n return false;\n } finally {\n // 過去世代の結果が遅れて完了した場合の finally では、現在のロックを解除しない\n if (\n displayGenerationRef.current === executionGen &&\n executionTokenRef.current === currentToken\n ) {\n isExecutingLockRef.current = false;\n }\n }\n }, [canApply, onApply, proposal, candidateRecord, decisions]);\n\n return {\n decisions,\n setDecision,\n acceptAll,\n rejectAll,\n resetDecisions,\n candidateRecord,\n reviewStatus,\n consistency,\n candidateValidation,\n canApply,\n isSubmitting,\n saveError,\n handleApply,\n };\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"use-proposal-review.js","names":["useProposalReview","options","activeProposalId","setActiveProposalId","useState","proposal","rawDecisions","setRawDecisions","isSubmitting","setIsSubmitting","saveError","setSaveError","displayGeneration","setDisplayGeneration","displayGenerationRef","useRef","executionTokenRef","isExecutingLockRef","decisions","prev","useEffect","setDecision","useCallback","field","decision","acceptAll","next","change","rejectAll","resetDecisions","candidateRecord","useMemo","buildCandidateRecord","currentRecord","consistency","verifyCurrentState","currentVersion","candidateValidation","validateCandidate","reviewStatus","computeReviewStatus","canApply","onApply","canApplyProposal","handleApply","executionGen","currentToken","payload","buildApplyPayload","err","message"],"sources":["../../../src/ai/proposal/use-proposal-review.ts"],"sourcesContent":["'use client';\n\nimport { useState, useMemo, useCallback, useRef, useEffect } from 'react';\nimport {\n buildApplyPayload,\n buildCandidateRecord,\n canApplyProposal,\n computeReviewStatus,\n verifyCurrentState,\n} from \"@alneas/appkit-core/ai\";\nimport type {\n CandidateValidationResult,\n FieldDecision,\n FieldKey,\n RecordProposal,\n ReviewDecisions,\n} from \"@alneas/appkit-core/ai\";\nimport type { ProposalReviewCardProps, UseProposalReviewReturn } from './types';\n\n/**\n * Host inputs for one immutable change proposal.\n *\n * @typeParam TRecord - Record shape; defaults to a string-keyed record.\n *\n * @see useProposalReview for complete usage.\n */\nexport interface UseProposalReviewOptions<\n TRecord extends Record<string, any> = Record<string, any>,\n> {\n /**\n * Validated immutable proposal; a new id starts a new review generation.\n */\n proposal: RecordProposal<TRecord>;\n /**\n * Latest record to compare and compose with accepted changes.\n */\n currentRecord: TRecord;\n /**\n * Current host version used for consistency checks.\n */\n currentVersion: string | number;\n /**\n * Optional pure synchronous full-record validator; render-time exceptions propagate.\n */\n validateCandidate?: (candidate: TRecord) => CandidateValidationResult;\n /**\n * Optional async host persistence/form-application handler; absence prevents apply.\n */\n onApply?: ProposalReviewCardProps<TRecord>['onApply'];\n}\n\n/**\n * Manages explicit field decisions and candidate consistency for a single proposal.\n *\n * @typeParam TRecord - Current record shape; defaults to a string-keyed record.\n *\n * @param options - Immutable proposal, latest record/version, optional candidate validator and host apply handler.\n *\n * @returns Review decisions, composed candidate, validation state and explicit apply controls.\n *\n * @throws Host validateCandidate errors propagate from render.\n *\n * @remarks Requires React; no context or CSS. Changing proposal.id resets choices, error\n * and displayed submission state. A synchronous lock blocks duplicate apply calls.\n * Late results from an older displayed generation do not update the current review;\n * this does not cancel or roll back host effects. onApply errors become saveError and\n * handleApply returns false. No backend authorization or persistence is provided.\n *\n * @example\n * ```tsx\n * import { useProposalReview, type UseProposalReviewOptions } from '@alneas/appkit-react/ai/proposal';\n * type RecordData = { title: string };\n * // The host supplies a validated proposal, current record/version and real onApply.\n * export function Review({ options }: { options: UseProposalReviewOptions<RecordData> }) {\n * const review = useProposalReview(options);\n * return <button disabled={!review.canApply || review.isSubmitting} onClick={() => { void review.handleApply(); }}>Apply reviewed changes</button>;\n * }\n * ```\n */\nexport function useProposalReview<\n TRecord extends Record<string, any> = Record<string, any>,\n>(options: UseProposalReviewOptions<TRecord>): UseProposalReviewReturn<TRecord> {\n const { proposal, currentRecord, currentVersion, validateCandidate, onApply } = options;\n\n // 提案切替(proposal.id 変更)の検知用\n const [activeProposalId, setActiveProposalId] = useState<string>(proposal.id);\n const [rawDecisions, setRawDecisions] = useState<ReviewDecisions<TRecord>>(\n {} as ReviewDecisions<TRecord>\n );\n const [isSubmitting, setIsSubmitting] = useState(false);\n const [saveError, setSaveError] = useState<string | null>(null);\n\n // 表示世代カウンター: 提案切替(A→B, B→A など)のたびにインクリメント\n const [displayGeneration, setDisplayGeneration] = useState<number>(1);\n const displayGenerationRef = useRef<number>(1);\n\n // 実行トークン: 適用実行ごとに一意なトークンをインクリメント\n const executionTokenRef = useRef<number>(0);\n // 同期実行ロック: 再レンダー完了前の高速な連続クリック(二重実行)を同期的にブロック\n const isExecutingLockRef = useRef<boolean>(false);\n\n // プロジェクト標準ルール: 「No synchronous setState in useEffect」\n // 提案 ID が切り替わった場合、レンダー中に状態を初期化して同期ズレを防ぐ\n let decisions = rawDecisions;\n if (proposal.id !== activeProposalId) {\n setActiveProposalId(proposal.id);\n setRawDecisions({} as ReviewDecisions<TRecord>);\n setSaveError(null);\n setIsSubmitting(false);\n setDisplayGeneration((prev) => prev + 1);\n decisions = {} as ReviewDecisions<TRecord>;\n }\n\n // 提案が切り替わった場合、実行ロックを非同期完了を待たずに解除し、表示世代Refを同期\n useEffect(() => {\n displayGenerationRef.current = displayGeneration;\n isExecutingLockRef.current = false;\n }, [displayGeneration]);\n\n // 個別フィールド決定の更新\n const setDecision = useCallback((field: FieldKey<TRecord>, decision: FieldDecision) => {\n setRawDecisions((prev) => ({\n ...prev,\n [field]: decision,\n }));\n setSaveError(null);\n }, []);\n\n // 全採用\n const acceptAll = useCallback(() => {\n const next: Partial<Record<FieldKey<TRecord>, FieldDecision>> = {};\n for (const change of proposal.changes) {\n next[change.field] = 'accepted';\n }\n setRawDecisions(next);\n setSaveError(null);\n }, [proposal.changes]);\n\n // 全却下\n const rejectAll = useCallback(() => {\n const next: Partial<Record<FieldKey<TRecord>, FieldDecision>> = {};\n for (const change of proposal.changes) {\n next[change.field] = 'rejected';\n }\n setRawDecisions(next);\n setSaveError(null);\n }, [proposal.changes]);\n\n // リセット(全 pending)\n const resetDecisions = useCallback(() => {\n setRawDecisions({} as ReviewDecisions<TRecord>);\n setSaveError(null);\n }, []);\n\n // 候補レコードの合成(不変・純粋関数)\n const candidateRecord = useMemo(() => {\n return buildCandidateRecord(currentRecord, proposal, decisions);\n }, [currentRecord, proposal, decisions]);\n\n // 現在値およびバージョンとの整合性検査\n const consistency = useMemo(() => {\n return verifyCurrentState(currentRecord, currentVersion, proposal, decisions);\n }, [currentRecord, currentVersion, proposal, decisions]);\n\n // 候補レコード全体のカスタム検証(相関チェック等)\n const candidateValidation = useMemo(() => {\n if (!validateCandidate) return undefined;\n return validateCandidate(candidateRecord);\n }, [validateCandidate, candidateRecord]);\n\n // 全体のレビュー状態(派生値)\n const reviewStatus = useMemo(() => {\n return computeReviewStatus(proposal, decisions);\n }, [proposal, decisions]);\n\n // 適用可能かどうかの判定(onApply が指定されていることも条件)\n const canApply = useMemo(() => {\n if (!onApply) return false;\n return canApplyProposal({\n proposal,\n decisions,\n consistency,\n candidateValidation,\n });\n }, [onApply, proposal, decisions, consistency, candidateValidation]);\n\n // 適用実行ハンドラ(提案世代・トークン・同期ロックによる完全隔離)\n const handleApply = useCallback(async (): Promise<boolean> => {\n // 1. 同期ロックおよび適用可否チェック(再レンダー前の重複実行も防止)\n if (!canApply || isExecutingLockRef.current || !onApply) {\n return false;\n }\n\n isExecutingLockRef.current = true;\n const executionGen = displayGenerationRef.current;\n const currentToken = ++executionTokenRef.current;\n\n setIsSubmitting(true);\n setSaveError(null);\n\n try {\n const payload = buildApplyPayload({\n proposal,\n candidateRecord,\n decisions,\n });\n\n await onApply(payload);\n\n // 非同期完了時: 表示世代および実行トークンが現在と一致している場合のみ状態を更新\n if (\n displayGenerationRef.current === executionGen &&\n executionTokenRef.current === currentToken\n ) {\n setIsSubmitting(false);\n setSaveError(null);\n isExecutingLockRef.current = false;\n return true;\n }\n return false;\n } catch (err) {\n // 非同期失敗時: 表示世代および実行トークンが現在と一致している場合のみエラーを設定\n if (\n displayGenerationRef.current === executionGen &&\n executionTokenRef.current === currentToken\n ) {\n setIsSubmitting(false);\n const message = err instanceof Error ? err.message : '適用の保存中にエラーが発生しました';\n setSaveError(message);\n isExecutingLockRef.current = false;\n }\n return false;\n } finally {\n // 過去世代の結果が遅れて完了した場合の finally では、現在のロックを解除しない\n if (\n displayGenerationRef.current === executionGen &&\n executionTokenRef.current === currentToken\n ) {\n isExecutingLockRef.current = false;\n }\n }\n }, [canApply, onApply, proposal, candidateRecord, decisions]);\n\n return {\n decisions,\n setDecision,\n acceptAll,\n rejectAll,\n resetDecisions,\n candidateRecord,\n reviewStatus,\n consistency,\n candidateValidation,\n canApply,\n isSubmitting,\n saveError,\n handleApply,\n };\n}\n"],"mappings":"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"}
|
package/dist/avatar.svg
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 64 64"><rect width="64" height="64" rx="32" fill="#334155"/><circle cx="32" cy="23" r="11" fill="#f8fafc"/><path d="M12 58a20 20 0 0 1 40 0" fill="#f8fafc"/></svg>
|
|
@@ -4,3 +4,9 @@ description: Integrate @alneas/appkit-react using published feature subpaths.
|
|
|
4
4
|
---
|
|
5
5
|
|
|
6
6
|
Read package-context.json for exact exports and peers. Install package names; import feature subpaths. Each feature guide must state its public import path. Preserve host providers and explicit CSS imports. Applications own authorization, migrations, final writes, atomic checks and durable idempotency. AI metadata consistency does not establish end-to-end coding-agent capability.
|
|
7
|
+
|
|
8
|
+
Use api-index.json for actual exported names, signatures and public import paths. Read llms.txt and the linked feature guide before choosing optional peers, host providers or CSS. Package.json appkit.agent is Appkit-specific discovery metadata, not an automatically executed agent hook. The same skill, context and catalog are present at consumer-ai/ and dist/consumer-ai/ for compatibility.
|
|
9
|
+
|
|
10
|
+
The Core package's appkit-api CLI searches locally available catalogs without running tools or contacting a provider. Check each result's package version and digest; registry 0.1.0 does not include this new CLI. Never replace a missing legacy catalog with a newer API surface. Always verify generated code with the consumer's type checker and relevant behavior tests.
|
|
11
|
+
|
|
12
|
+
AI tool calls and outputs are untrusted. Schema validity is not approval. Bind host approval to immutable arguments/targets/session/registration, enforce server permissions and durable idempotency at execution, and project minimal outputs. Adapters do not run tools or authorize writes. Read the AI guide and Core error guide; never infer permission from a tool-output event or bypass duplicate-call protection.
|